commit 2d0a76b94a69e68f191a93cd6bc47b4e51a04ff7 Author: Douglas Teles Date: Wed Apr 29 14:36:32 2026 -0300 ArchR v2.0-rc3 — first official release-candidate Kernel 6.12 LTS · Mesa 26.0.5 Panfrost · CMA 96 MB · zlib-ng 2.2.4 CPU turbo 1.5 GHz (vdd_arm 1.45 V) · GPU 650 MHz @ 1.150 V · mali_kbase PM patch 43 motherboard revisions covered · two image variants with hardware auto-detect PortMaster pre-installed · MESA_GLTHREAD whitelist · RetroAchievements Tailscale / WireGuard / ZeroTier · Syncthing + rclone · Samba Co-Authored-By: Claude Opus 4.7 (1M context) diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md new file mode 100644 index 0000000000..cdfff5e690 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -0,0 +1,30 @@ +--- +name: Bug Report +about: Describe this issue +title: "[BUG]" +labels: ISSUE NEEDS REVIEW +assignees: '' + +--- +### Have you first checked existing issues and documentation for a solution? +[ArchR GitHub Issues](https://github.com/archr-linux/Arch-R/issues) + + +### Describe the bug + + +### How to reproduce +Steps to reproduce the behavior: +1. Go to '...' +2. Play '....' +3. See error + +### Information + - ArchR Version: [e.g. 20260316] + - Hardware Platform: [e.g. Powkiddy RGB20SX] + +### Log file + + +### Context + diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000..50b1e180a3 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: Help and Support + url: https://discord.gg/Q5RY3gEuwv + about: Please ask for help and post questions in our Discord + - name: Feature Requests + url: https://discord.gg/Q5RY3gEuwv + about: Please ask for feature requests in our Discord diff --git a/.github/release-body.md b/.github/release-body.md new file mode 100644 index 0000000000..4b3b2dc4df --- /dev/null +++ b/.github/release-body.md @@ -0,0 +1,119 @@ +   +# +ArchR is a community developed Linux distribution for handheld gaming devices, forked from [ROCKNIX](https://github.com/ROCKNIX/distribution). Our goal is to produce an operating system that has the features and capabilities that we need, and to have fun as we develop it. + +## Licenses +ArchR is a Linux distribution forked from ROCKNIX, made up of many open-source components. Components are provided under their respective licenses. This distribution includes components licensed for non-commercial use only. + +### ArchR Branding +ArchR 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. + +### ArchR Software +Copyright (C) 2024-2026 ArchR (https://github.com/archr-linux). Derived from ROCKNIX, Copyright (C) 2024 ROCKNIX (https://github.com/ROCKNIX). + +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 ArchR. +* 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. + +### Installation Package Downloads +| **Device/Platform** | **Download Package** | **Documentation** | +|------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------| +| **Anbernic RG351P/M/V, Game Console R33S/R35S/R36S, ODROID Go Advance, ODROID Go Super, Magicx XU10, Powkiddy V10/RGB10** | [ArchR-RK3326.aarch64-$DATE-a.img.gz](https://github.com/archr-linux/Arch-R/releases/download/$DATE/ArchR-RK3326.aarch64-$DATE-a.img.gz) | [documentation](/documentation/PER_DEVICE_DOCUMENTATION/RK3326/) | +| **Magicx XU Mini M, Powkiddy RGB10X** | [ArchR-RK3326.aarch64-$DATE-b.img.gz](https://github.com/archr-linux/Arch-R/releases/download/$DATE/ArchR-RK3326.aarch64-$DATE-b.img.gz) | [documentation](/documentation/PER_DEVICE_DOCUMENTATION/RK3326/) | +| **Anbernic RG353P/M/V/VS/PS, RG503, RGARC-D/S, Powkiddy RK2023, RGB10 Max 3, RGB30, RGB20SX, RGB20 Pro** | [ArchR-RK3566.aarch64-$DATE-Generic.img.gz](https://github.com/archr-linux/Arch-R/releases/download/$DATE/ArchR-RK3566.aarch64-$DATE-Generic.img.gz) | [documentation](/documentation/PER_DEVICE_DOCUMENTATION/RK3566/) | +| **Anbernic RG552** | [ArchR-RK3399.aarch64-$DATE.img.gz](https://github.com/archr-linux/Arch-R/releases/download/$DATE/ArchR-RK3399.aarch64-$DATE.img.gz) | [documentation](/documentation/PER_DEVICE_DOCUMENTATION/RK3399/) | +| **Anbernic RG35XX PLUS/H/SP/2024, RG40XX V/H, RGCUBEXX, RG34XX SP, RG28XX [Must Follow Install Instructions](https://github.com/archr-linux/Arch-R/wiki/h700-installation)** | [ArchR-H700.aarch64-$DATE.img.gz](https://github.com/archr-linux/Arch-R/releases/download/$DATE/ArchR-H700.aarch64-$DATE.img.gz) | [documentation](/documentation/PER_DEVICE_DOCUMENTATION/H700/) | +| **Hardkernel ODROID Go Ultra, Powkiddy RGB10 Max 3 Pro** | [ArchR-S922X.aarch64-$DATE.img.gz](https://github.com/archr-linux/Arch-R/releases/download/$DATE/ArchR-S922X.aarch64-$DATE.img.gz) | [documentation](/documentation/PER_DEVICE_DOCUMENTATION/S922X/) | +| **Gameforce Ace (default). Orange Pi 5 / 5 Plus, Radxa Rock 5a / 5b / 5b+ / CM5, and Indiedroid Nova** | [ArchR-RK3588.aarch64-$DATE.img.gz](https://github.com/archr-linux/Arch-R/releases/download/$DATE/ArchR-RK3588.aarch64-$DATE.img.gz) | [documentation](/documentation/PER_DEVICE_DOCUMENTATION/RK3588/) | +| **Powkiddy x55** | [ArchR-RK3566.aarch64-$DATE-Powkiddy_x55.img.gz](https://github.com/archr-linux/Arch-R/releases/download/$DATE/ArchR-RK3566.aarch64-$DATE-Powkiddy_x55.img.gz) | [documentation](/documentation/PER_DEVICE_DOCUMENTATION/RK3566-X55/) | +| **Retroid Pocket 5, Pocket Mini, Pocket Mini V2, Pocket Flip2** | [ArchR-SM8250.aarch64-$DATE.img.gz](https://github.com/archr-linux/Arch-R/releases/download/$DATE/ArchR-SM8250.aarch64-$DATE.img.gz) | [documentation](/documentation/PER_DEVICE_DOCUMENTATION/SM8250/) | +| **Ayn Odin 2, Odin 2 Mini, Odin 2 Portal, Thor, Ayaneo Pocket ACE/EVO/DMG/DS** | [ArchR-SM8550.aarch64-$DATE.img.gz](https://github.com/archr-linux/Arch-R/releases/download/$DATE/ArchR-SM8550.aarch64-$DATE.img.gz) | [documentation](/documentation/PER_DEVICE_DOCUMENTATION/SM8550/) | +| **Ayaneo Pocket S2** | [ArchR-SM8650.aarch64-$DATE.img.gz](https://github.com/archr-linux/Arch-R/releases/download/$DATE/ArchR-SM8650.aarch64-$DATE.img.gz) | [documentation](/documentation/PER_DEVICE_DOCUMENTATION/SM8650/) | + +## Upgrading +* Download and install the update online via the System Settings menu. +* If you are unable to update online +* Download the latest version of ArchR from Github +* Copy the update to your device over the network to your device's update share. +* Reboot the device, and the update will begin automatically. + +### Update Package Downloads +| **Device/Platform** | **Download Package** | +|---------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------| +| **Anbernic RG351P/M/V, Game Console R33S/R35S/R36S, ODROID Go Advance, ODROID Go Super, Magicx XU10, XU Mini M, Powkiddy V10/RGB10/RGB10X** | [ArchR-RK3326.aarch64-$DATE.tar](https://github.com/archr-linux/Arch-R/releases/download/$DATE/ArchR-RK3326.aarch64-$DATE.tar) | +| **Anbernic RG353P/M/V/VS/PS, RG503, RGARC-D/S, Powkiddy RK2023, RGB10 Max 3, RGB30, RGB20SX, RGB20 Pro, X55** | [ArchR-RK3566.aarch64-$DATE.tar](https://github.com/archr-linux/Arch-R/releases/download/$DATE/ArchR-RK3566.aarch64-$DATE.tar) | +| **Anbernic RG552** | [ArchR-RK3399.aarch64-$DATE.tar](https://github.com/archr-linux/Arch-R/releases/download/$DATE/ArchR-RK3399.aarch64-$DATE.tar) | +| **Anbernic RG35XX PLUS/H/SP/2024, RG40XX V/H, RGCUBEXX, RG34XX SP, RG28XX** | [ArchR-H700.aarch64-$DATE.tar](https://github.com/archr-linux/Arch-R/releases/download/$DATE/ArchR-H700.aarch64-$DATE.tar) | +| **Hardkernel ODROID Go Ultra, Powkiddy RGB10 Max 3 Pro** | [ArchR-S922X.aarch64-$DATE.tar](https://github.com/archr-linux/Arch-R/releases/download/$DATE/ArchR-S922X.aarch64-$DATE.tar) | +| **Gameforce Ace, Orange Pi 5 / 5 Plus, Radxa Rock 5a / 5b / 5b+ / CM5 and Indiedroid Nova** | [ArchR-RK3588.aarch64-$DATE.tar](https://github.com/archr-linux/Arch-R/releases/download/$DATE/ArchR-RK3588.aarch64-$DATE.tar) | +| **Retroid Pocket 5, Pocket Mini, Pocket Mini V2, Pocket Flip2** | [ArchR-SM8250.aarch64-$DATE.tar](https://github.com/archr-linux/Arch-R/releases/download/$DATE/ArchR-SM8250.aarch64-$DATE.tar) | +| **Ayn Odin 2, Odin 2 Mini, Odin 2 Portal, Thor, Ayaneo Pocket ACE/EVO/DMG/DS** | [ArchR-SM8550.aarch64-$DATE.tar](https://github.com/archr-linux/Arch-R/releases/download/$DATE/ArchR-SM8550.aarch64-$DATE.tar) | +| **Ayaneo Pocket S2** | [ArchR-SM8650.aarch64-$DATE.tar](https://github.com/archr-linux/Arch-R/releases/download/$DATE/ArchR-SM8650.aarch64-$DATE.tar) | + +## Documentation + +### Contribute + +* [Building ArchR](https://github.com/archr-linux/distribution/wiki/contribute/build/) +* [Code of Conduct](https://github.com/archr-linux/distribution/wiki/contribute/code-of-conduct/) +* [Contributing to ArchR](https://github.com/archr-linux/distribution/wiki/contribute/) +* [Modifying ArchR](https://github.com/archr-linux/distribution/wiki/contribute/modify/) +* [Adding Hardware Quirks](https://github.com/archr-linux/distribution/wiki/contribute/quirks/) +* [Creating Packages](https://github.com/archr-linux/distribution/wiki/contribute/packages/) +* [Pull Request Template](/PULL_REQUEST_TEMPLATE.md) + +### Play + +* [Installing ArchR](https://github.com/archr-linux/distribution/wiki/play/install/) +* [Updating ArchR](https://github.com/archr-linux/distribution/wiki/play/update/) +* [Controls](https://github.com/archr-linux/distribution/wiki/play/controls/) +* [Netplay](https://github.com/archr-linux/distribution/wiki/play/netplay/) +* [Configuring Moonlight](https://github.com/archr-linux/distribution/wiki/systems/moonlight/) +* [Device Specific Documentation](/documentation/PER_DEVICE_DOCUMENTATION) + +### Configure + +* [Optimizations](https://github.com/archr-linux/distribution/wiki/configure/optimizations/) +* [Shaders](https://github.com/archr-linux/distribution/wiki/configure/shaders/) +* [Cloud Sync](https://github.com/archr-linux/distribution/wiki/configure/cloud-sync/) +* [VPN](https://github.com/archr-linux/distribution/wiki/configure/vpn/) + +### Other + +* [Frequently Asked Questions](https://github.com/archr-linux/distribution/wiki/faqs/) +* [Donating to ArchR](https://github.com/archr-linux/Arch-R) + +## Change Log + +### New Features +* Added...? + +### Updates +* Updated...? + +### Bug Fixes +* Fixed...? + +**Full Changelog**: https://github.com/archr-linux/Arch-R/compare/$LAST_TAG...$DATE diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..52e2c4052c --- /dev/null +++ b/.gitignore @@ -0,0 +1,175 @@ +# build directories +/build.*/ +/builds +/.fakeroot.* +.claude + +# automatically downloaded source files +/sources/ + +# 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 + +# crap +.DS_Store +.directory +Thumbs.db +*.log +*.pdf + +# temp scripts (debug/install helpers) +fix-debug.sh +install-debug.sh + +# ignore git repos from update scripts +tools/mkpkg/*.git + +# ignore old linux configs +projects/**/*.old + +# Generated MIPI overlay output (regenerated by generator.sh) +config/mipi-generator/output/ + +# Generated DTBO overlays in u-boot config (copied from mipi-generator output) +projects/ArchR/devices/RK3326/packages/u-boot/config/overlays_original/*.dtbo +projects/ArchR/devices/RK3326/packages/u-boot/config/overlays_clone/*.dtbo + +# ArchR +/.archr +/.cache +/.doc_cache +/.env +/.es_cache +/.config + +# Upstream/legacy distributions (not used by ArchR) +distributions/ROCKNIX/ +distributions/LibreELEC/ +distributions/LEIoT/ + +# Upstream/other platform projects (not used by PROJECT=ArchR) +projects/ROCKNIX/ +projects/Allwinner/ +projects/Amlogic/ +projects/ARM/ +projects/Generic/ +projects/NXP/ +projects/Qualcomm/ +projects/Rockchip/ +projects/RPi/ +projects/Samsung/ + +# Non-R36S device directories +projects/ArchR/devices/H700/ +projects/ArchR/devices/RK3399/ +projects/ArchR/devices/RK3566/ +projects/ArchR/devices/RK3588/ +projects/ArchR/devices/S922X/ +projects/ArchR/devices/SDM845/ +projects/ArchR/devices/SM8250/ +projects/ArchR/devices/SM8550/ +projects/ArchR/devices/SM8650/ + +# Non-R36S device documentation +documentation/PER_DEVICE_DOCUMENTATION/H700/ +documentation/PER_DEVICE_DOCUMENTATION/RK3399/ +documentation/PER_DEVICE_DOCUMENTATION/RK3566/ +documentation/PER_DEVICE_DOCUMENTATION/RK3588/ +documentation/PER_DEVICE_DOCUMENTATION/S922X/ +documentation/PER_DEVICE_DOCUMENTATION/SDM845/ +documentation/PER_DEVICE_DOCUMENTATION/SM8250/ +documentation/PER_DEVICE_DOCUMENTATION/SM8550/ +documentation/PER_DEVICE_DOCUMENTATION/SM8650/ + +# Kodi/mediacenter (MEDIACENTER not set in ArchR) +packages/mediacenter/ + +# Driver addons (DRIVER_ADDONS_SUPPORT=no in ArchR) +packages/linux-driver-addons/ + +# Kodi addons (no MEDIACENTER in ArchR) +# Kodi addons (no MEDIACENTER in ArchR) - keep addon-depends for shared libraries +packages/addons/* +!packages/addons/addon-depends/ + +# Platform-specific bootloaders/tools (not RK3326) +packages/tools/bcm2835-bootloader/ +packages/tools/bcm2835-utils/ +packages/tools/bcmstat/ +packages/tools/rpi-eeprom/ +packages/tools/amlogic-boot-fip/ +packages/tools/exynos-boot-fip/ + +# Firmware not used by R36S (FIRMWARE=esp8089-firmware only) +packages/linux-firmware/brcmfmac_sdio-firmware/ +packages/linux-firmware/brcmfmac_sdio-firmware-imx/ +packages/linux-firmware/brcmfmac_sdio-firmware-rpi/ +packages/linux-firmware/dvb-firmware/ +packages/linux-firmware/firmware-dragonboard/ +packages/linux-firmware/firmware-imx/ +packages/linux-firmware/iwlwifi-firmware/ + +# Non-R36S CI workflows +.github/workflows/build-aarch64-emu-libretro.yml +.github/workflows/build-aarch64-emu-standalone.yml +.github/workflows/build-aarch64-qt6.yml +.github/workflows/build-aarch64-mame-lr.yml + +# Emulators not used by RK3326 (too heavy or Vulkan-only) +projects/ArchR/packages/emulators/standalone/aethersx2-sa/ +projects/ArchR/packages/emulators/standalone/azahar-sa/ +projects/ArchR/packages/emulators/standalone/bigpemu-sa/ +projects/ArchR/packages/emulators/standalone/cemu-sa/ +projects/ArchR/packages/emulators/standalone/rpcs3-sa/ +projects/ArchR/packages/emulators/standalone/supermodel-sa/ +projects/ArchR/packages/emulators/standalone/xemu-sa/ +projects/ArchR/packages/emulators/standalone/skyemu-sa/ +projects/ArchR/packages/emulators/libretro/kronos-lr/ + +# Graphics packages not used by RK3326 (no Vulkan on Mali G31) +projects/ArchR/packages/graphics/libmali-vulkan/ +projects/ArchR/packages/graphics/vulkan-wsi-layer/ + +# Qualcomm/non-RK3326 tools +projects/ArchR/packages/tools/archr-abl/ +projects/ArchR/packages/tools/qcom-abl/ + +# Platform-specific base packages (not used by RK3326) +packages/audio/rpi-cirrus-config/ +packages/tools/crust/ +packages/tools/mkbootimg/ +packages/tools/grub/ +packages/linux-firmware/firmware-dragonboard/ +packages/linux-firmware/firmware-imx/ +packages/graphics/nvidia/ +packages/multimedia/intel-vaapi-driver/ +packages/multimedia/media-driver/ +packages/multimedia/gmmlib/ +packages/sysutils/open-vm-tools/ + + +#other +docs/* +bench-results/ \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100755 index 0000000000..f14901b0e6 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,58 @@ +FROM archlinux:latest + +SHELL ["/usr/bin/bash", "-c"] + +# Update system and install base packages +# Fix: archlinux:latest has corrupt pacman local db (missing desc files in overlay) +# Step 1: upgrade base system (creates new layer, fixes stale db entries) +RUN pacman-db-upgrade 2>/dev/null; \ + for pkg in /var/lib/pacman/local/*/; do \ + [ ! -f "${pkg}desc" ] && rm -rf "$pkg" 2>/dev/null; \ + done; true +RUN pacman -Syu --noconfirm +# Step 2: clean stale entries from previous layer, then install build deps +RUN for pkg in /var/lib/pacman/local/*/; do \ + [ ! -f "${pkg}desc" ] && rm -rf "$pkg" 2>/dev/null; \ + done; true +RUN pacman -S --noconfirm --needed \ + base-devel bc jdk-openjdk file gawk gettext git go gperf \ + perl-json perl-xml-parser ncurses lzop make patchutils \ + python python-setuptools parted unzip wget curl \ + xorg-mkfontscale libxslt zip vim zstd rdfind automake \ + xmlstarlet rsync which sudo rpcsvc-proto perl-parse-yapp xorg-bdftopcf \ + dtc python-pip +# Python fdt package for MIPI panel overlay generation +RUN pip3 install --break-system-packages fdt + +# Note: GCC downgrade removed - build system compiles its own cross-toolchain (GCC 15.1). +# Host GCC is only used for host tools. Fixes from projects/ArchR/packages/ handle +# any GCC 15 incompatibilities in individual packages (spirv-tools, llvm, etc.) + +# Create build user +RUN useradd -m -s /bin/bash docker && \ + echo 'docker ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers + +# Set locale +RUN echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen && \ + locale-gen +ENV LANG=en_US.UTF-8 \ + LANGUAGE=en_US:en \ + LC_ALL=en_US.UTF-8 + +# Ensure Perl tools (pod2man, yapp, etc.) are in standard PATH +RUN for f in /usr/bin/core_perl/*; do [ -f "$f" ] && ln -sf "$f" /usr/bin/ 2>/dev/null; done; \ + for f in /usr/bin/vendor_perl/*; do [ -f "$f" ] && ln -sf "$f" /usr/bin/ 2>/dev/null; done; \ + true + +### Cross compiling on ARM +RUN if [ "$(uname -m)" = "aarch64" ]; then pacman -S --noconfirm qemu-user-static; fi +RUN if [ ! -d /lib64 ]; then ln -sf /usr/x86_64-archr-linux-gnu/lib64 /lib64 2>/dev/null || true; fi +RUN if [ ! -d /lib/x86_64-archr-linux-gnu ]; then ln -sf /usr/x86_64-archr-linux-gnu/lib /lib/x86_64-archr-linux-gnu 2>/dev/null || true; fi + +RUN mkdir -p /work && chown docker /work + +# Git safe.directory for any user (env-file may override HOME) +RUN git config --system --add safe.directory '*' + +WORKDIR /work +USER docker diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000000..1935d7295f --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,33 @@ + + +--- + +## Licenses + +ArchR is a Linux distribution forked from [ROCKNIX](https://github.com/ROCKNIX/distribution), made up of many open-source components. Components are provided under their respective licenses. This distribution includes components licensed for non-commercial use only. + +### ArchR Branding + +ArchR 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/). Original ROCKNIX branding remains the property of the ROCKNIX project. + +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. + +### ArchR Software + +Copyright 2024-2026 ArchR (https://github.com/archr-linux) + +Original software and scripts developed by the ArchR team are licensed under the terms of the [GNU GPL Version 2](https://choosealicense.com/licenses/gpl-2.0/). The full license can be found in this project's licenses folder. + +Portions of this software are derived from ROCKNIX, Copyright 2024 ROCKNIX (https://github.com/ROCKNIX). + +### Bundled Works +All other software is provided under each component's respective license. These licenses can be found in the software sources or in this project's licenses folder. Modifications to bundled software and scripts by the ArchR team are licensed under the terms of the software being modified. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000000..f819f8f907 --- /dev/null +++ b/Makefile @@ -0,0 +1,111 @@ +-include $(HOME)/.archr/options + +export OFFICIAL + +all: world + +system: + ./scripts/image + +release: + ./scripts/image release + +image: + ./scripts/image mkimage + +noobs: + ./scripts/image noobs + +clean: + ./scripts/makefile_helper --clean + +distclean: + ./scripts/makefile_helper --distclean + +src-pkg: + tar cvJf sources.tar.xz sources + +docs: + ./tools/foreach './scripts/clean emulators && ./scripts/build emulators' + +world: RK3326 + +kconfig-olddefconfig-%: + DEVICE=$* ./tools/adjust_kernel_config olddefconfig + +kconfig-menuconfig-%: + DEVICE=$* ./tools/adjust_kernel_config menuconfig + +RK3326: + unset DEVICE_ROOT + OFFICIAL=$(if $(filter y yes Y YES 1,$(OFFICIAL)),yes,) PROJECT=ArchR DEVICE=RK3326 ARCH=arm ./scripts/build_distro + OFFICIAL=$(if $(filter y yes Y YES 1,$(OFFICIAL)),yes,) PROJECT=ArchR DEVICE=RK3326 ARCH=aarch64 ./scripts/build_distro + +update: + PROJECT=ArchR DEVICE=RK3326 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-RK3326 will use docker to call: make RK3326 +# All variables are scoped to docker-* commands to prevent weird collisions/behavior with non-docker commands + +docker-%: DOCKER_IMAGE := "archr-build:latest" + +# DOCKER_WORK_DIR is the directory in the Docker image - it is set to /work by default +# Anytime this directory changes, you must run `make clean` similarly to moving the distribution directory +docker-%: DOCKER_WORK_DIR := $(shell if [ -n "${DOCKER_WORK_DIR}" ]; then echo ${DOCKER_WORK_DIR}; else echo "$$(pwd)" ; fi) + +# ${HOME}/.archr/options is a global options file containing developer and build settings. +docker-%: GLOBAL_SETTINGS := $(shell if [ -f "${HOME}/.archr/options" ]; then echo "-v \"${HOME}/.archr/options:${HOME}/.archr/options\""; else echo ""; fi) + +# LOCAL_SSH_KEYS_FILE is a variable that contains the location of the authorized keys file for development build use. It will be mounted into the container if it exists. +docker-%: LOCAL_SSH_KEYS_FILE := $(shell if [ -n "${LOCAL_SSH_KEYS_FILE}" ]; then echo "-v \"${LOCAL_SSH_KEYS_FILE}:${LOCAL_SSH_KEYS_FILE}\""; else echo ""; fi) + +# EMULATIONSTATION_SRC is a variable that contains the location of local emulationstation source code. It will be mounted into the container if it exists. +docker-%: EMULATIONSTATION_SRC := $(shell if [ -n "${EMULATIONSTATION_SRC}" ]; then echo "-v \"${EMULATIONSTATION_SRC}:${EMULATIONSTATION_SRC}\""; 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 +# Make sure that docker isn't just an alias for podman +docker-%: PODMAN_ARGS:= $(shell if echo "$$(docker --version 2>/dev/null || podman --version 2>/dev/null )" | grep podman 1>/dev/null ; then echo "--userns=keep-id --security-opt=label=disable -v /proc/mounts:/etc/mtab"; 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 $* + +# If the user issues a `make docker-shell` just start up bash as the shell to run commands +docker-shell: COMMAND=bash + +# Command: builds and saves a docker builder image locally. +# The build user must also be a member of the "docker" group. +docker-image-build: + $(DOCKER_CMD) buildx create --use + $(DOCKER_CMD) buildx build --tag $(DOCKER_IMAGE) --platform $(shell if [ "$$(uname -m)" = "aarch64" ]; then echo "linux/arm64"; else echo "linux/amd64"; fi) --load . + +# Command: pulls latest docker image from dockerhub. This will *replace* locally built version. +docker-image-pull: + $(DOCKER_CMD) pull $(DOCKER_IMAGE) + +# Wire up docker to call equivalent make files using % to match and $* to pass the value matched by % +docker-%: + ./scripts/get_env > .env + BUILD_DIR="$(DOCKER_WORK_DIR)" $(DOCKER_CMD) run $(PODMAN_ARGS) $(INTERACTIVE) --init --env-file .env --rm --user $(UID):$(GID) $(GLOBAL_SETTINGS) $(LOCAL_SSH_KEYS_FILE) $(EMULATIONSTATION_SRC) -v "$(PWD)":"$(DOCKER_WORK_DIR)" -v /tmp:/tmp -w "$(DOCKER_WORK_DIR)" $(DOCKER_EXTRA_OPTS) $(DOCKER_IMAGE) $(COMMAND) diff --git a/README.md b/README.md new file mode 100644 index 0000000000..40854a796a --- /dev/null +++ b/README.md @@ -0,0 +1,179 @@ +

+ Arch R +

+ +

+ Arch Linux-based gaming distribution for handheld devices. +

+ +

+ Latest Version + Activity + Pull Requests +

+ +--- + +Arch R is a custom Linux distribution for the **R36S** handheld gaming console and all its variants, built on top of [ROCKNIX](https://github.com/ROCKNIX/distribution) with an **Arch Linux-based** build environment. It supports **16 board profiles** and **20 display panels** across original and clone hardware. + +## Features + +- Arch Linux-based build system with Docker support. +- Kernel 6.12 LTS with board auto-detection via SARADC. +- Mesa Panfrost open-source GPU driver (GLES 3.1, no proprietary blobs). +- EmulationStation frontend with RetroArch and 18+ cores pre-installed. +- Full audio support with speaker/headphone auto-switch. +- Battery monitoring with capacity reporting and LED warning. +- 43 pre-generated MIPI panel overlays (15 original + 18 clone + 10 soysauce variants), one per motherboard revision. +- Separate images for original and clone boards, both with hardware auto-detection. +- Integrated cross-device local and remote network play. +- Fine-grained control for battery life and performance. +- Bluetooth audio and controller support. +- HDMI audio/video output, USB audio. +- Device sync with Syncthing and rclone. +- VPN support with WireGuard, Tailscale, and ZeroTier. +- Built-in scraping and RetroAchievements. + +## Supported Hardware + +### Boards + +| Board | Image | +|-------|-------| +| R36S (original), R33S | Original | +| Odroid Go Advance / v1.1 / Super | Original | +| Anbernic RG351V / RG351M | Original | +| GameForce Chi, MagicX XU10 | Original | +| K36 / R36S clones / EE Clone | Clone | +| Powkiddy RGB10 / RGB10X / RGB20S | Clone | +| MagicX XU-Mini-M, BatLexp G350 | Clone | + +### Display Panels + +Arch R ships 43 pre-generated MIPI panel overlays covering all known R36S display variants, named after the exact motherboard revision (e.g. `R36S-V21_2024-12-18_2551.dtbo`, `G80CA-MB_V1.3-20251212_Panel_8.dtbo`). Panel selection is done by copying the correct `.dtbo` file to `overlays/mipi-panel.dtbo` on the boot partition. Sources live under `config/archr-dts/{original,clone,soysauce}//`; the build extracts the panel description from each revision's `rk3326-r36s-linux.dtb` via `config/mipi-generator/generator.sh`. + +## Quick Start + +Download the latest images from [Releases](https://github.com/archr-linux/Arch-R/releases): + +- **Original image** -- for genuine R36S and compatible boards. +- **Clone image** -- for K36 clones and compatible boards. + +Flash to a MicroSD card: + +```bash +xz -d ArchR-R36S-*.img.xz +sudo dd if=ArchR-R36S-*.img of=/dev/sdX bs=4M status=progress +sync +``` + +Insert the SD card and power on. The correct board DTB is selected automatically. + +## Building from Source + +### Requirements + +- Docker (recommended) or native Linux build environment +- ~40 GB free disk space +- ~8 GB RAM recommended + +### Build + +```bash +git clone https://github.com/archr-linux/Arch-R.git +cd Arch-R + +# Build Docker image (first time only) +make docker-image-build + +# Build for R36S (all variants) +make docker-RK3326 +``` + +Output images are generated in `target/`. + +### Build Commands + +| Command | Description | +|---------|-------------| +| `make docker-RK3326` | Full build inside Docker | +| `make RK3326` | Native build (requires all dependencies) | +| `make docker-image-build` | Build the Docker build environment | +| `make clean` | Remove build artifacts | + +## Architecture + +Arch R separates **board configuration** from **panel configuration**: + +- **Board DTB** = hardware profile (GPIOs, PMIC, joypad, audio codec). Selected automatically by U-Boot via SARADC. +- **Panel overlay** = display init sequence and timings. Applied on top of the board DTB at boot time. + +This means the same image works on all boards of a variant. Only the panel overlay needs to match the specific display. + +### Boot Flow + +``` +Power On + U-Boot (BSP or mainline) + boot.scr: read SARADC hwrev, select board DTB + sysboot: load kernel + DTB + overlay from extlinux.conf + Kernel 6.12 + initramfs + mount root (ext4) + storage + switch_root to systemd + systemd + archr-autostart (quirks, governors, audio) + EmulationStation +``` + +### Partition Layout + +| Partition | Filesystem | Label | Purpose | +|-----------|-----------|-------|---------| +| 1 | FAT32 | ARCHR | Boot (kernel, DTBs, overlays, boot.scr) | +| 2 | ext4 | ARCHR_ROOT | Root filesystem | +| 3 | ext4 | STORAGE | User data, ROMs, configs | + +## Community + +Contributions are welcome. Please open issues or pull requests on [GitHub](https://github.com/archr-linux/Arch-R). + +## Licenses + +**Arch R** is a fork of [ROCKNIX](https://github.com/ROCKNIX/distribution), which is a fork of [JELOS](https://github.com/JustEnoughLinuxOS/distribution/). All upstream licenses apply. + +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. + +### Arch R Software + +Copyright (C) 2026-present [Arch R](https://github.com/archr-linux/Arch-R) + +Original software and scripts developed by Arch R are licensed under the terms of the [GNU GPL Version 2](https://choosealicense.com/licenses/gpl-2.0/). The full license can be found in this project's licenses folder. + +### Bundled Works + +All other software is provided under each component's respective license. These licenses can be found in the software sources or in this project's licenses folder. Modifications to bundled software and scripts by upstream projects are licensed under the terms of the software being modified. + +## Credits + +Like any Linux distribution, this project is not the work of one person. It is the work of many people around the world who have developed the open-source components without which this project could not exist. + +Special thanks to: + +- **[ROCKNIX](https://github.com/ROCKNIX/distribution)** -- the upstream distribution that Arch R is forked from. ROCKNIX provided the complete build system, device support, EmulationStation integration, and the foundation for handheld gaming on Linux. +- **[JELOS](https://github.com/JustEnoughLinuxOS/distribution/)** -- the project that ROCKNIX was originally forked from. +- **[CoreELEC](https://coreelec.org/)** and **[LibreELEC](https://libreelec.tv/)** -- the embedded Linux distributions whose build system forms the backbone of this project. +- **[Hardkernel](https://www.hardkernel.com/)** -- for the Odroid Go Advance BSP U-Boot and kernel device trees. +- **[Rockchip](https://www.rock-chips.com/)** -- for the RK3326 SoC and rkbin firmware. +- **[Mesa](https://mesa3d.org/)** -- for the Panfrost open-source GPU driver. +- **[RetroArch](https://www.retroarch.com/)** and **[Libretro](https://www.libretro.com/)** -- for the emulation framework and cores. +- **[EmulationStation](https://emulationstation.org/)** -- for the frontend. +- All developers and contributors across the open-source community who made this possible. diff --git a/config/addon/dummy.xml b/config/addon/dummy.xml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/config/addon/xbmc.broken.xml b/config/addon/xbmc.broken.xml new file mode 100644 index 0000000000..e6c42dce4b --- /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 0000000000..ac82d23763 --- /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 0000000000..1a376d0594 --- /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 0000000000..b4c515fbab --- /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 0000000000..52c5ebe635 --- /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 0000000000..4283ce5d77 --- /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 0000000000..576ec77260 --- /dev/null +++ b/config/arch.aarch64 @@ -0,0 +1,38 @@ +# 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|cortex-a73.cortex-a53) + TARGET_SUBARCH=armv8-a + TARGET_FEATURES+=" neon" + # This only makes sense for 8.0-a, later revisions have LSE + TARGET_CFLAGS=" -mno-outline-atomics" + ;; + cortex-a55|cortex-a76.cortex-a55|cortex-a77|cortex-a75.cortex-a55|cortex-a710) + TARGET_SUBARCH=armv8.2-a + TARGET_FEATURES+=" neon" + ;; + cortex-x3|cortex-x4) + TARGET_SUBARCH=armv9-a + TARGET_FEATURES+=" neon" + ;; + esac + + TARGET_SUBARCH="$TARGET_SUBARCH$TARGET_ARCH_FLAGS" + TARGET_TUNE="$TARGET_CPU" + + TARGET_GCC_ARCH=aarch64 + TARGET_KERNEL_ARCH=arm64 + +# setup ARCH specific *FLAGS + TARGET_CFLAGS="$TARGET_CFLAGS -march=$TARGET_SUBARCH -mtune=$TARGET_TUNE -mabi=lp64 -Wno-psabi" + TARGET_LDFLAGS="$TARGET_LDFLAGS -march=$TARGET_SUBARCH -mtune=$TARGET_TUNE" + TARGET_ARCH_GCC_OPTS="--with-abi=lp64 --with-arch=$TARGET_SUBARCH --with-tune=$TARGET_TUNE" diff --git a/config/arch.arm b/config/arch.arm new file mode 100644 index 0000000000..08c7d6f4ac --- /dev/null +++ b/config/arch.arm @@ -0,0 +1,71 @@ +# 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 + ;; + cortex-a7|cortex-a15|cortex-a17|cortex-a15.cortex-a7|cortex-a17.cortex-a7) + TARGET_SUBARCH=armv7ve + TARGET_ABI=eabi + TARGET_FEATURES+=" neon" + ;; + cortex-a5|cortex-a8|cortex-a9) + TARGET_SUBARCH=armv7-a + TARGET_ABI=eabi + TARGET_FEATURES+=" neon" + ;; + cortex-a35|cortex-a53|cortex-a72.cortex-a53|cortex-a55|cortex-a76.cortex-a55|cortex-a73.cortex-a53|cortex-a75.cortex-a55) + TARGET_SUBARCH=armv8-a + TARGET_ABI=eabi + TARGET_FEATURES+=" neon" + ;; + cortex-a77) + TARGET_SUBARCH=armv8.2-a + TARGET_ABI=eabi + TARGET_FEATURES+=" neon" + ;; + cortex-a710) + TARGET_SUBARCH=armv9-a + TARGET_ABI=eabi + TARGET_FEATURES+=" neon" + ;; + esac + +# if [ "${TARGET_FLOAT}" = "hard" ]; then +# TARGET_ABI+="hf" +# fi + + TARGET_GCC_ARCH=${TARGET_SUBARCH/-} + TARGET_KERNEL_ARCH=${TARGET_KERNEL_ARCH:-arm} + + TARGET_SUBARCH="$TARGET_SUBARCH$TARGET_ARCH_FLAGS" + TARGET_TUNE="$TARGET_CPU$TARGET_TUNE_FLAGS" + +# setup ARCH specific *FLAGS + TARGET_CFLAGS="$TARGET_CFLAGS -march=$TARGET_SUBARCH -mtune=$TARGET_TUNE -mfloat-abi=$TARGET_FLOAT -mfpu=$TARGET_FPU -mabi=aapcs-linux -Wno-psabi -Wa,-mno-warn-deprecated" + TARGET_LDFLAGS="$TARGET_LDFLAGS -march=$TARGET_SUBARCH -mtune=$TARGET_TUNE -mfloat-abi=$TARGET_FLOAT -mfpu=$TARGET_FPU" + TARGET_ARCH_GCC_OPTS="--with-abi=aapcs-linux --with-arch=$TARGET_SUBARCH --with-tune=$TARGET_TUNE --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 0000000000..b8eead4556 --- /dev/null +++ b/config/arch.x86_64 @@ -0,0 +1,30 @@ +# determines TARGET_CPU, if not forced by user + if [ -z "${TARGET_CPU}" ]; then + TARGET_CPU="x86-64" + 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}" + TARGET_LDFLAGS="" + +# build with microarchitecture feature support defined by the TARGET_CPU value +# see https://gitlab.com/x86-psABIs/x86-64-ABI/-/wikis/home for further details + if [ -z "${TARGET_FEATURES}" ]; then + TARGET_FEATURES="64bit cmov cx8 fpu fxsr mmx osfxsr sce sse sse2" + TARGET_FEATURES_X86_64_V2="cmpxchg16b lahf-sahf popcnt sse3 sse4_1 sse4_2 ssse3" + TARGET_FEATURES_X86_64_V3="avx avx2 bmi1 bmi2 f16c fma lzcnt movbe osxsave" + if [ "${TARGET_CPU}" = "x86-64" ]; then + TARGET_FEATURES+=" no_sahf" + elif [ "${TARGET_CPU}" = "x86-64-v2" ]; then + TARGET_FEATURES+=" ${TARGET_FEATURES_X86_64_V2}" + elif [ "${TARGET_CPU}" = "x86-64-v3" ]; then + TARGET_FEATURES+=" ${TARGET_FEATURES_X86_64_V2} ${TARGET_FEATURES_X86_64_V3}" + fi + fi + TARGET_FEATURES="$(echo ${TARGET_FEATURES} | xargs -n1 | sort -u | xargs)" diff --git a/config/archr-dts/clone/G80C-MB V1.1-20250319 Panel 8/rg351v-uboot.dtb b/config/archr-dts/clone/G80C-MB V1.1-20250319 Panel 8/rg351v-uboot.dtb new file mode 100644 index 0000000000..4b0e936f61 Binary files /dev/null and b/config/archr-dts/clone/G80C-MB V1.1-20250319 Panel 8/rg351v-uboot.dtb differ diff --git a/config/archr-dts/clone/G80C-MB V1.1-20250319 Panel 8/rk3326-r36s-linux.dtb b/config/archr-dts/clone/G80C-MB V1.1-20250319 Panel 8/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..268a86080f Binary files /dev/null and b/config/archr-dts/clone/G80C-MB V1.1-20250319 Panel 8/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/clone/G80C-MB V1.1-20250319 Panel 9/rg351v-uboot.dtb b/config/archr-dts/clone/G80C-MB V1.1-20250319 Panel 9/rg351v-uboot.dtb new file mode 100644 index 0000000000..2a1bda66ed Binary files /dev/null and b/config/archr-dts/clone/G80C-MB V1.1-20250319 Panel 9/rg351v-uboot.dtb differ diff --git a/config/archr-dts/clone/G80C-MB V1.1-20250319 Panel 9/rk3326-r36s-linux.dtb b/config/archr-dts/clone/G80C-MB V1.1-20250319 Panel 9/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..9c89d09099 Binary files /dev/null and b/config/archr-dts/clone/G80C-MB V1.1-20250319 Panel 9/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/clone/G80CA-MB V1.2-20250422 Panel 8/rg351v-uboot.dtb b/config/archr-dts/clone/G80CA-MB V1.2-20250422 Panel 8/rg351v-uboot.dtb new file mode 100644 index 0000000000..55c000bd80 Binary files /dev/null and b/config/archr-dts/clone/G80CA-MB V1.2-20250422 Panel 8/rg351v-uboot.dtb differ diff --git a/config/archr-dts/clone/G80CA-MB V1.2-20250422 Panel 8/rk3326-r36s-linux.dtb b/config/archr-dts/clone/G80CA-MB V1.2-20250422 Panel 8/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..6897c5ff81 Binary files /dev/null and b/config/archr-dts/clone/G80CA-MB V1.2-20250422 Panel 8/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/clone/G80CA-MB V1.2-20250422 Panel 9/rg351v-uboot.dtb b/config/archr-dts/clone/G80CA-MB V1.2-20250422 Panel 9/rg351v-uboot.dtb new file mode 100644 index 0000000000..2a1bda66ed Binary files /dev/null and b/config/archr-dts/clone/G80CA-MB V1.2-20250422 Panel 9/rg351v-uboot.dtb differ diff --git a/config/archr-dts/clone/G80CA-MB V1.2-20250422 Panel 9/rk3326-r36s-linux.dtb b/config/archr-dts/clone/G80CA-MB V1.2-20250422 Panel 9/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..d350b8582e Binary files /dev/null and b/config/archr-dts/clone/G80CA-MB V1.2-20250422 Panel 9/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/clone/G80CA-MB V1.2-20250423 Panel 8/rg351v-uboot.dtb b/config/archr-dts/clone/G80CA-MB V1.2-20250423 Panel 8/rg351v-uboot.dtb new file mode 100644 index 0000000000..55c000bd80 Binary files /dev/null and b/config/archr-dts/clone/G80CA-MB V1.2-20250423 Panel 8/rg351v-uboot.dtb differ diff --git a/config/archr-dts/clone/G80CA-MB V1.2-20250423 Panel 8/rk3326-r36s-linux.dtb b/config/archr-dts/clone/G80CA-MB V1.2-20250423 Panel 8/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..c9c0ce3fd7 Binary files /dev/null and b/config/archr-dts/clone/G80CA-MB V1.2-20250423 Panel 8/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/clone/G80CA-MB V1.2-20250423 Panel 9/rg351v-uboot.dtb b/config/archr-dts/clone/G80CA-MB V1.2-20250423 Panel 9/rg351v-uboot.dtb new file mode 100644 index 0000000000..2a1bda66ed Binary files /dev/null and b/config/archr-dts/clone/G80CA-MB V1.2-20250423 Panel 9/rg351v-uboot.dtb differ diff --git a/config/archr-dts/clone/G80CA-MB V1.2-20250423 Panel 9/rk3326-r36s-linux.dtb b/config/archr-dts/clone/G80CA-MB V1.2-20250423 Panel 9/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..2f5efc492b Binary files /dev/null and b/config/archr-dts/clone/G80CA-MB V1.2-20250423 Panel 9/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/clone/G80CA-MB V1.3-20251212 Panel 8/rg351v-uboot.dtb b/config/archr-dts/clone/G80CA-MB V1.3-20251212 Panel 8/rg351v-uboot.dtb new file mode 100644 index 0000000000..55c000bd80 Binary files /dev/null and b/config/archr-dts/clone/G80CA-MB V1.3-20251212 Panel 8/rg351v-uboot.dtb differ diff --git a/config/archr-dts/clone/G80CA-MB V1.3-20251212 Panel 8/rk3326-r36s-linux.dtb b/config/archr-dts/clone/G80CA-MB V1.3-20251212 Panel 8/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..30b693b212 Binary files /dev/null and b/config/archr-dts/clone/G80CA-MB V1.3-20251212 Panel 8/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/clone/G80D-MB V1.0-20250609 Panel 8/rg351v-uboot.dtb b/config/archr-dts/clone/G80D-MB V1.0-20250609 Panel 8/rg351v-uboot.dtb new file mode 100644 index 0000000000..4b0e936f61 Binary files /dev/null and b/config/archr-dts/clone/G80D-MB V1.0-20250609 Panel 8/rg351v-uboot.dtb differ diff --git a/config/archr-dts/clone/G80D-MB V1.0-20250609 Panel 8/rk3326-r36s-linux.dtb b/config/archr-dts/clone/G80D-MB V1.0-20250609 Panel 8/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..9edd54164d Binary files /dev/null and b/config/archr-dts/clone/G80D-MB V1.0-20250609 Panel 8/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/clone/GR36-MB V1.1-20250422/rg351v-uboot.dtb b/config/archr-dts/clone/GR36-MB V1.1-20250422/rg351v-uboot.dtb new file mode 100644 index 0000000000..4aee1bf2c0 Binary files /dev/null and b/config/archr-dts/clone/GR36-MB V1.1-20250422/rg351v-uboot.dtb differ diff --git a/config/archr-dts/clone/GR36-MB V1.1-20250422/rk3326-r36s-linux.dtb b/config/archr-dts/clone/GR36-MB V1.1-20250422/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..e1d8c59951 Binary files /dev/null and b/config/archr-dts/clone/GR36-MB V1.1-20250422/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/clone/R36S-V12 2023-08-18 Variant 1 Panel 3 A/rg351v-uboot.dtb b/config/archr-dts/clone/R36S-V12 2023-08-18 Variant 1 Panel 3 A/rg351v-uboot.dtb new file mode 100644 index 0000000000..2a1bda66ed Binary files /dev/null and b/config/archr-dts/clone/R36S-V12 2023-08-18 Variant 1 Panel 3 A/rg351v-uboot.dtb differ diff --git a/config/archr-dts/clone/R36S-V12 2023-08-18 Variant 1 Panel 3 A/rk3326-r36s-linux.dtb b/config/archr-dts/clone/R36S-V12 2023-08-18 Variant 1 Panel 3 A/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..dc261d91a0 Binary files /dev/null and b/config/archr-dts/clone/R36S-V12 2023-08-18 Variant 1 Panel 3 A/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/clone/R36S-V12 2023-08-18 Variant 1 Panel 8 A/rg351v-uboot.dtb b/config/archr-dts/clone/R36S-V12 2023-08-18 Variant 1 Panel 8 A/rg351v-uboot.dtb new file mode 100644 index 0000000000..c42bbadb94 Binary files /dev/null and b/config/archr-dts/clone/R36S-V12 2023-08-18 Variant 1 Panel 8 A/rg351v-uboot.dtb differ diff --git a/config/archr-dts/clone/R36S-V12 2023-08-18 Variant 1 Panel 8 A/rk3326-r36s-linux.dtb b/config/archr-dts/clone/R36S-V12 2023-08-18 Variant 1 Panel 8 A/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..871f0602ba Binary files /dev/null and b/config/archr-dts/clone/R36S-V12 2023-08-18 Variant 1 Panel 8 A/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/clone/R36S-V12 2023-08-18 Variant 2 Panel 1 A/rg351v-uboot.dtb b/config/archr-dts/clone/R36S-V12 2023-08-18 Variant 2 Panel 1 A/rg351v-uboot.dtb new file mode 100644 index 0000000000..436de3ef88 Binary files /dev/null and b/config/archr-dts/clone/R36S-V12 2023-08-18 Variant 2 Panel 1 A/rg351v-uboot.dtb differ diff --git a/config/archr-dts/clone/R36S-V12 2023-08-18 Variant 2 Panel 1 A/rk3326-r36s-linux.dtb b/config/archr-dts/clone/R36S-V12 2023-08-18 Variant 2 Panel 1 A/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..ec0576ccb3 Binary files /dev/null and b/config/archr-dts/clone/R36S-V12 2023-08-18 Variant 2 Panel 1 A/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/clone/R36S-V12 2023-08-18 Variant 2 Panel 1/rg351v-uboot.dtb b/config/archr-dts/clone/R36S-V12 2023-08-18 Variant 2 Panel 1/rg351v-uboot.dtb new file mode 100644 index 0000000000..81aaa7c57e Binary files /dev/null and b/config/archr-dts/clone/R36S-V12 2023-08-18 Variant 2 Panel 1/rg351v-uboot.dtb differ diff --git a/config/archr-dts/clone/R36S-V12 2023-08-18 Variant 2 Panel 1/rk3326-r36s-linux.dtb b/config/archr-dts/clone/R36S-V12 2023-08-18 Variant 2 Panel 1/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..bb477a65a4 Binary files /dev/null and b/config/archr-dts/clone/R36S-V12 2023-08-18 Variant 2 Panel 1/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/clone/R36S-V12 2023-08-18 Variant 3 Panel 3/rg351v-uboot.dtb b/config/archr-dts/clone/R36S-V12 2023-08-18 Variant 3 Panel 3/rg351v-uboot.dtb new file mode 100644 index 0000000000..bb4e70d973 Binary files /dev/null and b/config/archr-dts/clone/R36S-V12 2023-08-18 Variant 3 Panel 3/rg351v-uboot.dtb differ diff --git a/config/archr-dts/clone/R36S-V12 2023-08-18 Variant 3 Panel 3/rk3326-r36s-linux.dtb b/config/archr-dts/clone/R36S-V12 2023-08-18 Variant 3 Panel 3/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..ee2b7c2064 Binary files /dev/null and b/config/archr-dts/clone/R36S-V12 2023-08-18 Variant 3 Panel 3/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/clone/R36S-V12 2023-08-18 Variant 3 Panel A/rg351v-uboot.dtb b/config/archr-dts/clone/R36S-V12 2023-08-18 Variant 3 Panel A/rg351v-uboot.dtb new file mode 100644 index 0000000000..5f723fec57 Binary files /dev/null and b/config/archr-dts/clone/R36S-V12 2023-08-18 Variant 3 Panel A/rg351v-uboot.dtb differ diff --git a/config/archr-dts/clone/R36S-V12 2023-08-18 Variant 3 Panel A/rk3326-r36s-linux.dtb b/config/archr-dts/clone/R36S-V12 2023-08-18 Variant 3 Panel A/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..922cacf078 Binary files /dev/null and b/config/archr-dts/clone/R36S-V12 2023-08-18 Variant 3 Panel A/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/clone/R36S-V20 2025-05-18 2541/rg351v-uboot.dtb b/config/archr-dts/clone/R36S-V20 2025-05-18 2541/rg351v-uboot.dtb new file mode 100644 index 0000000000..4460c8301d Binary files /dev/null and b/config/archr-dts/clone/R36S-V20 2025-05-18 2541/rg351v-uboot.dtb differ diff --git a/config/archr-dts/clone/R36S-V20 2025-05-18 2541/rk3326-r36s-linux.dtb b/config/archr-dts/clone/R36S-V20 2025-05-18 2541/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..11d0d3e63d Binary files /dev/null and b/config/archr-dts/clone/R36S-V20 2025-05-18 2541/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/clone/R36S-V20 2025-05-18 2548/rg351v-uboot.dtb b/config/archr-dts/clone/R36S-V20 2025-05-18 2548/rg351v-uboot.dtb new file mode 100644 index 0000000000..c240a4adae Binary files /dev/null and b/config/archr-dts/clone/R36S-V20 2025-05-18 2548/rg351v-uboot.dtb differ diff --git a/config/archr-dts/clone/R36S-V20 2025-05-18 2548/rk3326-r36s-linux.dtb b/config/archr-dts/clone/R36S-V20 2025-05-18 2548/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..e033873546 Binary files /dev/null and b/config/archr-dts/clone/R36S-V20 2025-05-18 2548/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/clone/R36S-V20 2025-05-18 2549/rg351v-uboot.dtb b/config/archr-dts/clone/R36S-V20 2025-05-18 2549/rg351v-uboot.dtb new file mode 100644 index 0000000000..c240a4adae Binary files /dev/null and b/config/archr-dts/clone/R36S-V20 2025-05-18 2549/rg351v-uboot.dtb differ diff --git a/config/archr-dts/clone/R36S-V20 2025-05-18 2549/rk3326-r36s-linux.dtb b/config/archr-dts/clone/R36S-V20 2025-05-18 2549/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..0b7aa23d2f Binary files /dev/null and b/config/archr-dts/clone/R36S-V20 2025-05-18 2549/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/original/HL-R36H-V20 2024-05-18/rg351mp-uboot.dtb b/config/archr-dts/original/HL-R36H-V20 2024-05-18/rg351mp-uboot.dtb new file mode 100644 index 0000000000..674624086b Binary files /dev/null and b/config/archr-dts/original/HL-R36H-V20 2024-05-18/rg351mp-uboot.dtb differ diff --git a/config/archr-dts/original/HL-R36H-V20 2024-05-18/rk3326-r36s-linux.dtb b/config/archr-dts/original/HL-R36H-V20 2024-05-18/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..e249a48413 Binary files /dev/null and b/config/archr-dts/original/HL-R36H-V20 2024-05-18/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/original/HL-R36H-V21 2024-11-18/rg351mp-uboot.dtb b/config/archr-dts/original/HL-R36H-V21 2024-11-18/rg351mp-uboot.dtb new file mode 100644 index 0000000000..beae6be706 Binary files /dev/null and b/config/archr-dts/original/HL-R36H-V21 2024-11-18/rg351mp-uboot.dtb differ diff --git a/config/archr-dts/original/HL-R36H-V21 2024-11-18/rk3326-r36s-linux.dtb b/config/archr-dts/original/HL-R36H-V21 2024-11-18/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..cd5eae473a Binary files /dev/null and b/config/archr-dts/original/HL-R36H-V21 2024-11-18/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/original/R35S-V11 2022-08-18/rg351mp-uboot.dtb b/config/archr-dts/original/R35S-V11 2022-08-18/rg351mp-uboot.dtb new file mode 100644 index 0000000000..13082d4950 Binary files /dev/null and b/config/archr-dts/original/R35S-V11 2022-08-18/rg351mp-uboot.dtb differ diff --git a/config/archr-dts/original/R35S-V11 2022-08-18/rk3326-r36s-linux.dtb b/config/archr-dts/original/R35S-V11 2022-08-18/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..9f849a61d0 Binary files /dev/null and b/config/archr-dts/original/R35S-V11 2022-08-18/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/original/R36S Plus-V20 2025-03-18/rg351mp-uboot.dtb b/config/archr-dts/original/R36S Plus-V20 2025-03-18/rg351mp-uboot.dtb new file mode 100644 index 0000000000..d4efbe1979 Binary files /dev/null and b/config/archr-dts/original/R36S Plus-V20 2025-03-18/rg351mp-uboot.dtb differ diff --git a/config/archr-dts/original/R36S Plus-V20 2025-03-18/rk3326-r36s-linux.dtb b/config/archr-dts/original/R36S Plus-V20 2025-03-18/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..b1fcad8e57 Binary files /dev/null and b/config/archr-dts/original/R36S Plus-V20 2025-03-18/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/original/R36S-V12 2023-08-18 Panel 0/rg351mp-uboot.dtb b/config/archr-dts/original/R36S-V12 2023-08-18 Panel 0/rg351mp-uboot.dtb new file mode 100644 index 0000000000..13082d4950 Binary files /dev/null and b/config/archr-dts/original/R36S-V12 2023-08-18 Panel 0/rg351mp-uboot.dtb differ diff --git a/config/archr-dts/original/R36S-V12 2023-08-18 Panel 0/rk3326-r36s-linux.dtb b/config/archr-dts/original/R36S-V12 2023-08-18 Panel 0/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..4c236e2e2c Binary files /dev/null and b/config/archr-dts/original/R36S-V12 2023-08-18 Panel 0/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/original/R36S-V12 2023-08-18 Panel 4/rg351mp-uboot.dtb b/config/archr-dts/original/R36S-V12 2023-08-18 Panel 4/rg351mp-uboot.dtb new file mode 100644 index 0000000000..cd2e421411 Binary files /dev/null and b/config/archr-dts/original/R36S-V12 2023-08-18 Panel 4/rg351mp-uboot.dtb differ diff --git a/config/archr-dts/original/R36S-V12 2023-08-18 Panel 4/rk3326-r36s-linux.dtb b/config/archr-dts/original/R36S-V12 2023-08-18 Panel 4/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..1b62e80c93 Binary files /dev/null and b/config/archr-dts/original/R36S-V12 2023-08-18 Panel 4/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/original/R36S-V21 2024-12-18 2550/rg351mp-uboot.dtb b/config/archr-dts/original/R36S-V21 2024-12-18 2550/rg351mp-uboot.dtb new file mode 100644 index 0000000000..16fc5db27e Binary files /dev/null and b/config/archr-dts/original/R36S-V21 2024-12-18 2550/rg351mp-uboot.dtb differ diff --git a/config/archr-dts/original/R36S-V21 2024-12-18 2550/rk3326-r36s-linux.dtb b/config/archr-dts/original/R36S-V21 2024-12-18 2550/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..4aea8292d3 Binary files /dev/null and b/config/archr-dts/original/R36S-V21 2024-12-18 2550/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/original/R36S-V21 2024-12-18 2551/rg351mp-uboot.dtb b/config/archr-dts/original/R36S-V21 2024-12-18 2551/rg351mp-uboot.dtb new file mode 100644 index 0000000000..16fc5db27e Binary files /dev/null and b/config/archr-dts/original/R36S-V21 2024-12-18 2551/rg351mp-uboot.dtb differ diff --git a/config/archr-dts/original/R36S-V21 2024-12-18 2551/rk3326-r36s-linux.dtb b/config/archr-dts/original/R36S-V21 2024-12-18 2551/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..40cd573d67 Binary files /dev/null and b/config/archr-dts/original/R36S-V21 2024-12-18 2551/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/original/R36S-V21 2024-12-18 2552/rg351mp-uboot.dtb b/config/archr-dts/original/R36S-V21 2024-12-18 2552/rg351mp-uboot.dtb new file mode 100644 index 0000000000..16fc5db27e Binary files /dev/null and b/config/archr-dts/original/R36S-V21 2024-12-18 2552/rg351mp-uboot.dtb differ diff --git a/config/archr-dts/original/R36S-V21 2024-12-18 2552/rk3326-r36s-linux.dtb b/config/archr-dts/original/R36S-V21 2024-12-18 2552/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..65e725f6a9 Binary files /dev/null and b/config/archr-dts/original/R36S-V21 2024-12-18 2552/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/original/R36S-V22 2024-12-18/rg351mp-uboot.dtb b/config/archr-dts/original/R36S-V22 2024-12-18/rg351mp-uboot.dtb new file mode 100644 index 0000000000..ea75c89cf6 Binary files /dev/null and b/config/archr-dts/original/R36S-V22 2024-12-18/rg351mp-uboot.dtb differ diff --git a/config/archr-dts/original/R36S-V22 2024-12-18/rk3326-r36s-linux.dtb b/config/archr-dts/original/R36S-V22 2024-12-18/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..064b737ba6 Binary files /dev/null and b/config/archr-dts/original/R36S-V22 2024-12-18/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/original/R36S-V30 2025-11-18/rg351mp-uboot.dtb b/config/archr-dts/original/R36S-V30 2025-11-18/rg351mp-uboot.dtb new file mode 100644 index 0000000000..9d08e62621 Binary files /dev/null and b/config/archr-dts/original/R36S-V30 2025-11-18/rg351mp-uboot.dtb differ diff --git a/config/archr-dts/original/R36S-V30 2025-11-18/rk3326-r36s-linux.dtb b/config/archr-dts/original/R36S-V30 2025-11-18/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..a338769cf7 Binary files /dev/null and b/config/archr-dts/original/R36S-V30 2025-11-18/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/original/R36S-Y02 2024-11-27/rg351mp-uboot.dtb b/config/archr-dts/original/R36S-Y02 2024-11-27/rg351mp-uboot.dtb new file mode 100644 index 0000000000..c66f37270d Binary files /dev/null and b/config/archr-dts/original/R36S-Y02 2024-11-27/rg351mp-uboot.dtb differ diff --git a/config/archr-dts/original/R36S-Y02 2024-11-27/rk3326-r36s-linux.dtb b/config/archr-dts/original/R36S-Y02 2024-11-27/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..2bc7cfa6b2 Binary files /dev/null and b/config/archr-dts/original/R36S-Y02 2024-11-27/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/original/R36S-Y02 2024-12-18/rg351mp-uboot.dtb b/config/archr-dts/original/R36S-Y02 2024-12-18/rg351mp-uboot.dtb new file mode 100644 index 0000000000..c66f37270d Binary files /dev/null and b/config/archr-dts/original/R36S-Y02 2024-12-18/rg351mp-uboot.dtb differ diff --git a/config/archr-dts/original/R36S-Y02 2024-12-18/rk3326-r36s-linux.dtb b/config/archr-dts/original/R36S-Y02 2024-12-18/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..f631964460 Binary files /dev/null and b/config/archr-dts/original/R36S-Y02 2024-12-18/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/original/R36XX-V21 2024-12-18/rg351mp-uboot.dtb b/config/archr-dts/original/R36XX-V21 2024-12-18/rg351mp-uboot.dtb new file mode 100644 index 0000000000..c72ddcd7e7 Binary files /dev/null and b/config/archr-dts/original/R36XX-V21 2024-12-18/rg351mp-uboot.dtb differ diff --git a/config/archr-dts/original/R36XX-V21 2024-12-18/rk3326-r36s-linux.dtb b/config/archr-dts/original/R36XX-V21 2024-12-18/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..409dfd63ee Binary files /dev/null and b/config/archr-dts/original/R36XX-V21 2024-12-18/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/original/RG36S-Y07 2025-09-11/rg351mp-uboot.dtb b/config/archr-dts/original/RG36S-Y07 2025-09-11/rg351mp-uboot.dtb new file mode 100644 index 0000000000..c66f37270d Binary files /dev/null and b/config/archr-dts/original/RG36S-Y07 2025-09-11/rg351mp-uboot.dtb differ diff --git a/config/archr-dts/original/RG36S-Y07 2025-09-11/rk3326-r36s-linux.dtb b/config/archr-dts/original/RG36S-Y07 2025-09-11/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..39e8f5f1c3 Binary files /dev/null and b/config/archr-dts/original/RG36S-Y07 2025-09-11/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/retrogame_joypad_s2_f1.dtsi b/config/archr-dts/retrogame_joypad_s2_f1.dtsi new file mode 100644 index 0000000000..7a0f231091 --- /dev/null +++ b/config/archr-dts/retrogame_joypad_s2_f1.dtsi @@ -0,0 +1,122 @@ +/* + This is a skeleton of joypad with 2 sticks and FN (MODE) button. + Fits devices with 1 stick and 2 extra face buttons too. + By including this ans setting I/O properties only, + devices should get consistent controller id and mapping + thus reusing non-game configs: + * SDL gamecontrollerdb.txt + * ES es_input.cfg + * Retroarch gamepad +*/ + +/ { + joypad: retrogame_joypad_s2_f1 { + /* These drivers emit the same button set which makes this skeleton ADC-agnostic */ + /* compatible = "archr-joypad"; */ + /* compatible = "archr-singleadc-joypad"; */ + + /* These are constants making Joystick Guid the same */ + joypad-name = "retrogame_joypad_s2_f1"; + joypad-vendor = <0x484B>; + joypad-product = <0x1121>; /* 11 inherited, 2 for number of sticks, 1 for number of FN */ + joypad-revision = <0x0100>; + + /* require explicit status = "okay"; */ + status = "disabled"; + + /* adc calculate scale */ + button-adc-scale = <2>; + + /* adc deadzone range */ + button-adc-deadzone = <64>; + + /* + specifies fuzz value that is used to filter noise from + the event stream. + */ + button-adc-fuzz = <32>; + button-adc-flat = <32>; + + /* poll device interval (ms), adc read interval */ + poll-interval = <10>; + + /* gpio button auto repeat set value : default disable */ + /* + autorepeat; + */ + + /* meaningful node names for easier use */ + up { + label = "GPIO DPAD-UP"; + linux,code = ; + }; + down { + label = "GPIO DPAD-DOWN"; + linux,code = ; + }; + left { + label = "GPIO DPAD-LEFT"; + linux,code = ; + }; + right { + label = "GPIO DPAD-RIGHT"; + linux,code = ; + }; + + a { + label = "GPIO BTN-A"; + linux,code = ; + }; + b { + label = "GPIO BTN-B"; + linux,code = ; + }; + x { + label = "GPIO BTN-X"; + linux,code = ; + }; + y { + label = "GPIO BTN-Y"; + linux,code = ; + }; + + select { + label = "GPIO BTN_SELECT"; + linux,code = ; + }; + start { + label = "GPIO BTN_START"; + linux,code = ; + }; + mode { + label = "GPIO BTN_F"; + linux,code = ; + }; + + tl { + label = "GPIO BTN_TL"; + linux,code = ; + }; + tr { + label = "GPIO BTN_TR"; + linux,code = ; + }; + tl2 { + label = "GPIO BTN_TL2"; + linux,code = ; + }; + tr2 { + label = "GPIO BTN_TR2"; + linux,code = ; + }; + + thumbl { + label = "GPIO BTN_THUMBL"; + linux,code = ; + }; + thumbr { + label = "GPIO BTN_THUMBR"; + linux,code = ; + }; + }; +}; diff --git a/config/archr-dts/rk3326-anbernic-rg351m.dts b/config/archr-dts/rk3326-anbernic-rg351m.dts new file mode 100644 index 0000000000..c12bb79944 --- /dev/null +++ b/config/archr-dts/rk3326-anbernic-rg351m.dts @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2019 Hardkernel Co., Ltd + * Copyright (c) 2020 Theobroma Systems Design und Consulting GmbH + * Copyright (c) 2022 Maya Matuszczyk + */ + +/dts-v1/; +#include "rk3326-odroid-go.dtsi" + +/ { + model = "Anbernic RG351M"; + compatible = "anbernic,rg351m", "rockchip,rk3326"; + + battery: battery { + compatible = "simple-battery"; + charge-full-design-microamp-hours = <3500000>; + charge-term-current-microamp = <350000>; + constant-charge-current-max-microamp = <2000000>; + constant-charge-voltage-max-microvolt = <4200000>; + factory-internal-resistance-micro-ohms = <180000>; + voltage-max-design-microvolt = <4100000>; + voltage-min-design-microvolt = <3500000>; + + ocv-capacity-celsius = <20>; + ocv-capacity-table-0 = <4046950 100>, <4001920 95>, <3967900 90>, <3919950 85>, + <3888450 80>, <3861850 75>, <3831540 70>, <3799130 65>, + <3768190 60>, <3745650 55>, <3726610 50>, <3711630 45>, + <3696720 40>, <3685660 35>, <3674950 30>, <3663050 25>, + <3649470 20>, <3635260 15>, <3616920 10>, <3592440 5>, + <3574170 0>; + }; + + vibrator { + compatible = "pwm-vibrator"; + pwms = <&pwm0 0 1000000 0>; + pwm-names = "enable"; + }; +}; + +/delete-node/ &vcc_host; /* conflicts with pwm vibration motor */ + +&internal_display { + compatible = "elida,kd35t133"; + iovcc-supply = <&vcc_lcd>; + vdd-supply = <&vcc_lcd>; + rotation = <270>; +}; + +&pwm0 { + status = "okay"; +}; + +&rk817_charger { + /* This device does not have a current sense resistor */ + //rockchip,resistor-sense-micro-ohms = <0>; + monitored-battery = <&battery>; +}; diff --git a/config/archr-dts/rk3326-anbernic-rg351m.dtsi b/config/archr-dts/rk3326-anbernic-rg351m.dtsi new file mode 100644 index 0000000000..f580df54e6 --- /dev/null +++ b/config/archr-dts/rk3326-anbernic-rg351m.dtsi @@ -0,0 +1,480 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2019 Hardkernel Co., Ltd + * Copyright (c) 2020 Theobroma Systems Design und Consulting GmbH + * Copyright (c) 2022 Maya Matuszczyk + */ + +/dts-v1/; +#include +#include +#include +#include +#include "rk3326.dtsi" + +/ { + aliases { + mmc0 = &sdmmc; + }; + + chosen { + stdout-path = "serial2:115200n8"; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + power-supply = <&vcc_bl>; + pwms = <&pwm1 0 25000 0>; + }; + + /* + * LED is a tri-state. Driven high it is red, driven low it is + * green, and not driven at all (pin set to input) it is amber. + * Additionally, there is a 2nd LED that is not controllable + * that is on (red) when plugged in to power. + */ + gpio_led: gpio-leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pin>; + + red_green_led: led-0 { + color = ; + gpios = <&gpio2 RK_PB5 GPIO_ACTIVE_HIGH>; + function = LED_FUNCTION_CHARGING; + }; + }; + + rk817-sound { + compatible = "simple-audio-card"; + simple-audio-card,name = "rk817_int"; + simple-audio-card,format = "i2s"; + simple-audio-card,hp-det-gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>; + simple-audio-card,mclk-fs = <256>; + simple-audio-card,widgets = + "Microphone", "Mic Jack", + "Headphone", "Headphones", + "Speaker", "Speaker"; + simple-audio-card,routing = + "MICL", "Mic Jack", + "Headphones", "HPOL", + "Headphones", "HPOR", + "Speaker", "SPKO"; + + simple-audio-card,codec { + sound-dai = <&rk817>; + }; + + simple-audio-card,cpu { + sound-dai = <&i2s1_2ch>; + }; + }; + + vccsys: regulator-vccsys { + compatible = "regulator-fixed"; + regulator-name = "vcc3v8_sys"; + regulator-always-on; + regulator-min-microvolt = <3800000>; + regulator-max-microvolt = <3800000>; + }; + + vibrator { + compatible = "pwm-vibrator"; + pwms = <&pwm0 0 1000000 0>; + pwm-names = "enable"; + }; +}; + +&cpu0 { + cpu-supply = <&vdd_arm>; +}; + +&cpu1 { + cpu-supply = <&vdd_arm>; +}; + +&cpu2 { + cpu-supply = <&vdd_arm>; +}; + +&cpu3 { + cpu-supply = <&vdd_arm>; +}; + +&cru { + assigned-clocks = <&cru PLL_NPLL>, + <&cru ACLK_BUS_PRE>, <&cru ACLK_PERI_PRE>, + <&cru HCLK_BUS_PRE>, <&cru HCLK_PERI_PRE>, + <&cru PCLK_BUS_PRE>, <&cru SCLK_GPU>; + + assigned-clock-rates = <1188000000>, + <200000000>, <200000000>, + <150000000>, <150000000>, + <100000000>, <200000000>; +}; + +&display_subsystem { + status = "okay"; +}; + +&dsi { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + ports { + mipi_out: port@1 { + reg = <1>; + + mipi_out_panel: endpoint { + remote-endpoint = <&mipi_in_panel>; + }; + }; + }; + + internal_display: panel@0 { + reg = <0>; + backlight = <&backlight>; + reset-gpios = <&gpio3 RK_PC0 GPIO_ACTIVE_LOW>; + + port { + mipi_in_panel: endpoint { + remote-endpoint = <&mipi_out_panel>; + }; + }; + }; +}; + +&dsi_dphy { + status = "okay"; +}; + +&gpu { + mali-supply = <&vdd_logic>; + status = "okay"; +}; + +&i2c0 { + clock-frequency = <400000>; + i2c-scl-falling-time-ns = <16>; + i2c-scl-rising-time-ns = <280>; + status = "okay"; + + rk817: pmic@20 { + compatible = "rockchip,rk817"; + reg = <0x20>; + #clock-cells = <1>; + clock-names = "mclk"; + clock-output-names = "rk808-clkout1", "xin32k"; + clocks = <&cru SCLK_I2S1_OUT>; + interrupt-parent = <&gpio0>; + interrupts = ; + pinctrl-0 = <&pmic_int>, <&i2s1_2ch_mclk>; + pinctrl-names = "default"; + #sound-dai-cells = <0>; + wakeup-source; + + vcc1-supply = <&vccsys>; + vcc2-supply = <&vccsys>; + vcc3-supply = <&vccsys>; + vcc4-supply = <&vccsys>; + vcc5-supply = <&vccsys>; + vcc6-supply = <&vccsys>; + vcc7-supply = <&vccsys>; + vcc8-supply = <&vccsys>; + + regulators { + vdd_logic: DCDC_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1150000>; + regulator-min-microvolt = <950000>; + regulator-name = "vdd_logic"; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vdd_arm: DCDC_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1350000>; + regulator-min-microvolt = <950000>; + regulator-name = "vdd_arm"; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc_ddr"; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_3v3: DCDC_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "vcc_3v3"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_1v8: LDO_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1800000>; + regulator-min-microvolt = <1800000>; + regulator-name = "vcc_1v8"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd_1v0: LDO_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1000000>; + regulator-min-microvolt = <1000000>; + regulator-name = "vdd_1v0"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vcc3v3_pmu: LDO_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "vcc3v3_pmu"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vccio_sd: LDO_REG5 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <1800000>; + regulator-name = "vccio_sd"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_sd: LDO_REG6 { + regulator-boot-on; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "vcc_sd"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_bl: LDO_REG7 { + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "vcc_bl"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_lcd: LDO_REG8 { + regulator-max-microvolt = <2800000>; + regulator-min-microvolt = <2800000>; + regulator-name = "vcc_lcd"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <2800000>; + }; + }; + + vcc_wifi: LDO_REG9 { + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "vcc_wifi"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + usb_midu: BOOST { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <5400000>; + regulator-min-microvolt = <5000000>; + regulator-name = "usb_midu"; + }; + }; + + rk817_codec: codec { + rockchip,mic-in-differential; + }; + }; +}; + +&i2s1_2ch { + status = "okay"; +}; + +&io_domains { + vccio1-supply = <&vcc_3v3>; + vccio2-supply = <&vccio_sd>; + vccio3-supply = <&vcc_3v3>; + vccio4-supply = <&vcc_3v3>; + vccio5-supply = <&vcc_3v3>; + vccio6-supply = <&vcc_3v3>; + status = "okay"; +}; + +&pmu_io_domains { + pmuio1-supply = <&vcc3v3_pmu>; + pmuio2-supply = <&vcc3v3_pmu>; + status = "okay"; +}; + +&pwm0 { + status = "okay"; +}; + +&pwm1 { + status = "okay"; +}; + +&saradc { + vref-supply = <&vcc_1v8>; + status = "okay"; +}; + +&sdmmc { + cap-sd-highspeed; + card-detect-delay = <200>; + cd-gpios = <&gpio0 RK_PA3 GPIO_ACTIVE_LOW>; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + vmmc-supply = <&vcc_sd>; + vqmmc-supply = <&vccio_sd>; + status = "okay"; +}; + +&sfc { + #address-cells = <1>; + pinctrl-0 = <&sfc_clk &sfc_cs0 &sfc_bus2>; + pinctrl-names = "default"; + #size-cells = <0>; + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <108000000>; + spi-rx-bus-width = <2>; + spi-tx-bus-width = <1>; + }; +}; + +&tsadc { + status = "okay"; +}; + +&u2phy { + status = "okay"; + + u2phy_host: host-port { + status = "okay"; + }; + + u2phy_otg: otg-port { + status = "okay"; + }; +}; + +&usb20_otg { + status = "okay"; +}; + +&uart2 { + pinctrl-0 = <&uart2m1_xfer>; + pinctrl-names = "default"; + status = "okay"; +}; + +&vopb { + status = "okay"; +}; + +&vopb_mmu { + status = "okay"; +}; + +&pinctrl { + headphone { + hp_det: hp-det { + rockchip,pins = <2 RK_PC6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + + leds { + led_pin: led-pin { + rockchip,pins = <2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pmic { + dc_det: dc-det { + rockchip,pins = <0 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + pmic_int: pmic-int { + rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + soc_slppin_gpio: soc_slppin_gpio { + rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_output_low>; + }; + + soc_slppin_rst: soc_slppin_rst { + rockchip,pins = <0 RK_PA4 2 &pcfg_pull_none>; + }; + + soc_slppin_slp: soc_slppin_slp { + rockchip,pins = <0 RK_PA4 1 &pcfg_pull_none>; + }; + }; +}; diff --git a/config/archr-dts/rk3326-anbernic-rg351v.dts b/config/archr-dts/rk3326-anbernic-rg351v.dts new file mode 100644 index 0000000000..26658a37f4 --- /dev/null +++ b/config/archr-dts/rk3326-anbernic-rg351v.dts @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2019 Hardkernel Co., Ltd + * Copyright (c) 2020 Theobroma Systems Design und Consulting GmbH + * Copyright (c) 2022 Maya Matuszczyk + */ + +/dts-v1/; +#include "rk3326-odroid-go.dtsi" + +/ { + model = "Anbernic RG351V"; + compatible = "anbernic,rg351v", "rockchip,rk3326"; + + aliases { + mmc0 = &sdio; + mmc1 = &sdmmc; + }; + + gpio-keys-vol { + compatible = "gpio-keys"; + autorepeat; + pinctrl-0 = <&btn_pins_vol>; + pinctrl-names = "default"; + + button-vol-down { + gpios = <&gpio2 RK_PA1 GPIO_ACTIVE_LOW>; + label = "VOLUMEDOWN"; + linux,code = ; + }; + + button-volume-up { + gpios = <&gpio2 RK_PA0 GPIO_ACTIVE_LOW>; + label = "VOLUMEUP"; + linux,code = ; + }; + }; + + battery: battery { + compatible = "simple-battery"; + charge-full-design-microamp-hours = <3500000>; + charge-term-current-microamp = <350000>; + constant-charge-current-max-microamp = <2000000>; + constant-charge-voltage-max-microvolt = <4200000>; + factory-internal-resistance-micro-ohms = <180000>; + voltage-max-design-microvolt = <4100000>; + voltage-min-design-microvolt = <3500000>; + + ocv-capacity-celsius = <20>; + ocv-capacity-table-0 = <4046950 100>, <4001920 95>, <3967900 90>, <3919950 85>, + <3888450 80>, <3861850 75>, <3831540 70>, <3799130 65>, + <3768190 60>, <3745650 55>, <3726610 50>, <3711630 45>, + <3696720 40>, <3685660 35>, <3674950 30>, <3663050 25>, + <3649470 20>, <3635260 15>, <3616920 10>, <3592440 5>, + <3574170 0>; + }; + + vibrator { + compatible = "pwm-vibrator"; + pwms = <&pwm0 0 1000000 0>; + pwm-names = "enable"; + }; +}; + +/* conflicts with pwm vibration motor */ +/delete-node/ &vcc_host; + +/* Device only has 1 LED compared to Odroid Go Advance */ +/delete-node/ &gpio_led; + +&internal_display { + compatible = "anbernic,rg351v-panel", "newvision,nv3051d"; + iovcc-supply = <&vcc_lcd>; + vdd-supply = <&vcc_lcd>; +}; + +&io_domains { + vccio1-supply = <&vccio_sd>; +}; + +/delete-node/ &pwm_led; + +&pwm0 { + status = "okay"; +}; + +/delete-node/ &pwm3; + +&rk817_charger { + /* This device does not have a current sense resistor */ + rockchip,resistor-sense-micro-ohms = <0>; + monitored-battery = <&battery>; +}; + +&sdio { + cap-sd-highspeed; + card-detect-delay = <200>; + cd-gpios = <&gpio3 RK_PB4 GPIO_ACTIVE_LOW>; /*[> CD GPIO <]*/ + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + vmmc-supply = <&vcc_sd>; + vqmmc-supply = <&vccio_sd>; + status = "okay"; +}; + +&vcc_sd { + regulator-max-microvolt = <3000000>; + regulator-min-microvolt = <1800000>; +}; + +&vccio_sd { + regulator-max-microvolt = <1800000>; +}; + +&pinctrl { + btns { + btn_pins_vol: btn-pins-vol { + rockchip,pins = <2 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +}; diff --git a/config/archr-dts/rk3326-batlexp-g350.dts b/config/archr-dts/rk3326-batlexp-g350.dts new file mode 100644 index 0000000000..9cad95fc57 --- /dev/null +++ b/config/archr-dts/rk3326-batlexp-g350.dts @@ -0,0 +1,163 @@ +/// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* +* Copyright (c) 2025 lcdyk <2670878301@qq.com> +*/ + +/dts-v1/; +#include "rk3326-gameconsole-r3xs.dtsi" +#include "retrogame_joypad_s2_f1.dtsi" + +/ { + model = "BatleXP G350"; + compatible = "batlexp,g350", "rockchip,rk3326"; +}; + +&joypad { + compatible = "archr-singleadc-joypad"; + pwms = <&pwm0 0 200000000 0>; + pwm-names = "enable"; + rumble-boost-weak = <0x0000>; + rumble-boost-strong = <0x0000>; + joypad-name = "retrogame_joypad"; + joypad-vendor = <0x484B>; + joypad-product = <0x1101>; + joypad-revision = <0x0100>; + + status = "okay"; + + /* gpio pincontrol setup */ + pinctrl-names = "default"; + pinctrl-0 = <&btn_pins>; + pinctrl-1 = <&pwm0_pin>; + + /* Analog mux define */ + io-channel-names = "amux_adc"; + io-channels = <&saradc 1>; + + /* adc mux channel count */ + amux-count = <4>; + /* non-default wiring */ + amux-channel-mapping = <2 0 1 3>; + /* adc mux enable gpio */ + amux-a-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>; + amux-b-gpios = <&gpio3 RK_PB3 GPIO_ACTIVE_LOW>; + /* adc mux enable gpio */ + amux-en-gpios = <&gpio3 RK_PB5 GPIO_ACTIVE_LOW>; + + /* + Analog Stick data tuning value(precent) + p = positive direction, n = negative direction + report value = (real_adc_data * tuning_value) / 100 + */ + abs_x-p-tuning = <200>; + abs_x-n-tuning = <200>; + + abs_y-p-tuning = <200>; + abs_y-n-tuning = <200>; + + abs_rx-p-tuning = <200>; + abs_rx-n-tuning = <200>; + + abs_ry-p-tuning = <200>; + abs_ry-n-tuning = <200>; + + /* gpio button auto repeat set value : default disable */ + /* + autorepeat; + */ + invert-absx; + invert-absy; + invert-absrx; + + up { gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_LOW>; }; + down { gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_LOW>; }; + left { gpios = <&gpio1 RK_PB6 GPIO_ACTIVE_LOW>; }; + right { gpios = <&gpio1 RK_PB7 GPIO_ACTIVE_LOW>; }; + a { gpios = <&gpio1 RK_PA2 GPIO_ACTIVE_LOW>; }; + b { gpios = <&gpio1 RK_PA5 GPIO_ACTIVE_LOW>; }; + x { gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_LOW>; }; + y { gpios = <&gpio1 RK_PA6 GPIO_ACTIVE_LOW>; }; + select { gpios = <&gpio3 RK_PB1 GPIO_ACTIVE_LOW>; }; + start { gpios = <&gpio3 RK_PB4 GPIO_ACTIVE_LOW>; }; + mode { gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_LOW>; }; + tl { gpios = <&gpio2 RK_PA6 GPIO_ACTIVE_LOW>; }; + tr { gpios = <&gpio2 RK_PA7 GPIO_ACTIVE_LOW>; }; + tl2 { gpios = <&gpio3 RK_PB2 GPIO_ACTIVE_LOW>; }; + tr2 { gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; }; + thumbl { gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; }; + thumbr { gpios = <&gpio2 RK_PA3 GPIO_ACTIVE_LOW>; }; +}; + +&dsi { + internal_display: panel@0 { + compatible = "archr,generic-dsi"; + iovcc-supply = <&vcc_lcd>; + vcc-supply = <&vcc_lcd>; + reset-gpios = <&gpio3 RK_PC0 GPIO_ACTIVE_LOW>; + panel_description = + "G size=52,70 delays=20,150,20,120,20 format=rgb888 lanes=4 flags=0xe03", + + "M clock=50000 horizontal=640,450,70,450 vertical=480,17,5,13 default=1", + "M clock=50000 horizontal=640,450,85,450 vertical=480,17,106,13", + "M clock=50010 horizontal=640,450,127,450 vertical=480,17,90,13", + "M clock=50010 horizontal=640,450,73,450 vertical=480,17,110,13", + "M clock=50830 horizontal=640,450,85,450 vertical=480,17,34,13", + "M clock=53200 horizontal=640,450,128,450 vertical=480,17,24,13", + "M clock=50400 horizontal=640,450,77,450 vertical=480,17,10,13", + "M clock=50310 horizontal=640,450,85,450 vertical=480,17,6,13", + "M clock=54600 horizontal=640,450,94,450 vertical=480,17,46,13", + "M clock=65370 horizontal=640,450,113,450 vertical=480,17,14,13", + "M clock=76050 horizontal=640,450,85,450 vertical=480,17,10,13", + "M clock=100620 horizontal=640,450,85,450 vertical=480,17,6,13", + + "I seq=b9f11283", + "I seq=b1000000da80", + "I seq=b2001370", + "I seq=b31010282803ff00000000", + "I seq=b480", + "I seq=b50a0a", + "I seq=b67f7f", + "I seq=b82662f063", + "I seq=ba338105f90e0e2000000000000000442500900a0000014f01000037", + "I seq=bc47", + "I seq=bf021100", + "I seq=c0737350500000125000", + "I seq=c15300323277d1cccc77773333", + "I seq=c68200bfff00ff", + "I seq=c7b8000a000000", + "I seq=c810401e02", + "I seq=cc0b", + "I seq=e000070d37353f4144060c0d0f111012141a00070d37353f4144060c0d0f111012141a", + "I seq=e307070b0b0b0b00000000ff00c010", + "I seq=e9c810020000b0b11131232880b0b127080004020000000004020000008888ba60240888888888888888ba713518888888888800000001000000000000000000", + "I seq=ea970a820203070000000000008188ba17538888888888888088ba0642888888888888230000028000000000000000000000000000000000000000000000", + "I seq=efffff01", + "I seq=11 wait=200", + "I seq=29 wait=50"; + }; +}; + +&pinctrl { + btns { + btn_pins: btn-pins { + rockchip,pins = + <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +}; diff --git a/config/archr-dts/rk3326-device-group-r36.dtsi b/config/archr-dts/rk3326-device-group-r36.dtsi new file mode 100644 index 0000000000..f38e1abe8e --- /dev/null +++ b/config/archr-dts/rk3326-device-group-r36.dtsi @@ -0,0 +1,8 @@ +/ { + archr,device_switch { + r33s = "rk3326-gameconsole-r33s"; + r36s = "rk3326-gameconsole-r36s"; + soysauce = "rk3326-gameconsole-soysauce"; + rgb10x = "rk3326-powkiddy-rgb10x"; + }; +}; diff --git a/config/archr-dts/rk3326-gameconsole-eeclone.dts b/config/archr-dts/rk3326-gameconsole-eeclone.dts new file mode 100644 index 0000000000..f833102605 --- /dev/null +++ b/config/archr-dts/rk3326-gameconsole-eeclone.dts @@ -0,0 +1,960 @@ +/// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2024-present ROCKNIX (https://github.com/ROCKNIX) + * Copyright (c) 2025 Danil Zagoskin + */ + +/dts-v1/; +#include +#include +#include +#include +#include "rk3326.dtsi" + +/ { + model = "R36S Clone"; + compatible = "gameconsole,eeclone", "rockchip,rk3326"; + + aliases { + mmc0 = &emmc; + mmc1 = &sdmmc; + mmc2 = &sdio; + serial1 = &uart2; + serial2 = &uart5; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + pwms = <&pwm1 0 25000 0>; + brightness-levels = < + 0 1 2 3 4 5 6 7 + 8 9 10 11 12 13 14 15 + 16 17 18 19 20 21 22 23 + 24 25 26 27 28 29 30 31 + 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 + 48 49 50 51 52 53 54 55 + 56 57 58 59 60 61 62 63 + 64 65 66 67 68 69 70 71 + 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 + 88 89 90 91 92 93 94 95 + 96 97 98 99 100 101 102 103 + 104 105 106 107 108 109 110 111 + 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 + 128 129 130 131 132 133 134 135 + 136 137 138 139 140 141 142 143 + 144 145 146 147 148 149 150 151 + 152 153 154 155 156 157 158 159 + 160 161 162 163 164 165 166 167 + 168 169 170 171 172 173 174 175 + 176 177 178 179 180 181 182 183 + 184 185 186 187 188 189 190 191 + 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 + 208 209 210 211 212 213 214 215 + 216 217 218 219 220 221 222 223 + 224 225 226 227 228 229 230 231 + 232 233 234 235 236 237 238 239 + 240 241 242 243 244 245 246 247 + 248 249 250 251 252 253 254 255>; + default-brightness-level = <128>; + }; + + battery: battery { + compatible = "simple-battery"; + charge-full-design-microamp-hours = <4000000>; + charge-term-current-microamp = <200000>; + constant-charge-current-max-microamp = <1500000>; + constant-charge-voltage-max-microvolt = <4200000>; + factory-internal-resistance-micro-ohms = <100000>; + voltage-max-design-microvolt = <4100000>; + voltage-min-design-microvolt = <3300000>; + + ocv-capacity-celsius = <20>; + ocv-capacity-table-0 = + <4046950 100>, <4001920 95>, <3967900 90>, <3940000 85>, + <3910000 80>, <3870000 75>, <3830000 70>, <3790000 65>, + <3750000 60>, <3720000 55>, <3690000 50>, <3650000 45>, + <3610000 40>, <3570000 35>, <3540000 30>, <3500000 25>, + <3460000 20>, <3420000 15>, <3380000 10>, <3340000 5>, + <3300000 0>; + }; + + adc_keys: adc-keys { + compatible = "adc-keys"; + io-channels = <&saradc 2>; + io-channel-names = "buttons"; + keyup-threshold-microvolt = <1800000>; + poll-interval = <100>; + + /* disabled by default, dtbo may enable it when needed */ + status = "disabled"; + + button-vol-up { + press-threshold-microvolt = <15000>; + label = "VOLUMEUP"; + linux,code = ; + }; + + button-vol-down { + press-threshold-microvolt = <300000>; + label = "VOLUMEDOWN"; + linux,code = ; + }; + }; + + joypad: joypad { + compatible = "archr-singleadc-joypad"; + + joypad-name = "r36s_Gamepad"; + joypad-product = <0x1188>; + joypad-revision = <0x0188>; + + status = "okay"; + + /* gpio pincontrol setup */ + pinctrl-names = "default"; + pinctrl-0 = <&btn_pins>; + + /* Analog mux define */ + io-channel-names = "amux_adc"; + io-channels = <&saradc 1>; + + /* adc mux channel count */ + amux-count = <4>; + /* non-default wiring */ + amux-channel-mapping = <2 3 1 0>; + /* adc mux enable gpio */ + amux-en-gpios = <&gpio2 RK_PB4 GPIO_ACTIVE_LOW>; /* rocker0-gpios */ + /* adc mux select(a,b) gpio */ + amux-a-gpios = <&gpio2 RK_PC0 GPIO_ACTIVE_LOW>; /* rocker1-gpios */ + amux-b-gpios = <&gpio2 RK_PB7 GPIO_ACTIVE_LOW>; /* rocker-gpios */ + + /* adc calculate scale */ + button-adc-scale = <2>; + + /* adc deadzone range */ + button-adc-deadzone = <64>; + + /* + specifies fuzz value that is used to filter noise from + the event stream. + */ + button-adc-fuzz = <32>; + button-adc-flat = <32>; + + /* + Analog Stick data tuning value(precent) + p = positive direction, n = negative direction + report value = (real_adc_data * tuning_value) / 100 + */ + abs_x-p-tuning = <200>; + abs_x-n-tuning = <200>; + + abs_y-p-tuning = <200>; + abs_y-n-tuning = <200>; + + abs_rx-p-tuning = <200>; + abs_rx-n-tuning = <200>; + + abs_ry-p-tuning = <200>; + abs_ry-n-tuning = <200>; + + /* poll device interval (ms), adc read interval */ + poll-interval = <10>; + + /* gpio button auto repeat set value : default disable */ + /* + autorepeat; + */ + + /* + joypad driver is poll-device driver. + poll-device is does not support wakeup-source. + */ + sw1 { + gpios = <&gpio3 RK_PC6 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-UP"; + linux,code = ; // 0x220 + }; + sw2 { + gpios = <&gpio3 RK_PC7 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-DOWN"; + linux,code = ; // 0x221 + }; + sw3 { + gpios = <&gpio3 RK_PC4 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-LEFT"; + linux,code = ; // 0x222 + }; + sw4 { + gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-RIGHT"; + linux,code = ; // 0x223 + }; + + sw5 { + gpios = <&gpio3 RK_PC0 GPIO_ACTIVE_LOW>; + label = "GPIO KEY BTN-A"; + linux,code = ; // 0x131 + }; + sw6 { + gpios = <&gpio3 RK_PC1 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-B"; + linux,code = ; // 0x130 + }; + sw7 { + gpios = <&gpio3 RK_PC3 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-Y"; + linux,code = ; // 0x134 + }; + sw8 { + gpios = <&gpio3 RK_PC2 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-X"; + linux,code = ; // 0x133 + }; + + sw11 { + gpios = <&gpio2 RK_PB5 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_THUMBL"; + linux,code = ; // 0x2c2 + }; + sw12 { + gpios = <&gpio2 RK_PB6 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_THUMBR"; + linux,code = ; // 0x2c3 + }; + + sw13 { + gpios = <&gpio3 RK_PB2 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_FN"; + linux,code = ; // 0x2c4 + }; + + sw15 { + gpios = <&gpio3 RK_PB5 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-LEFT"; + linux,code = ; // 0x02 + }; + sw16 { + gpios = <&gpio3 RK_PB3 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-RIGHT"; + linux,code = ; // 0x05 + }; + sw19 { + gpios = <&gpio3 RK_PD0 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_SELECT"; + linux,code = ; + }; + sw20 { + gpios = <&gpio3 RK_PB4 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-RIGHT2"; + linux,code = ; + }; + sw21 { + gpios = <&gpio3 RK_PB6 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-LEFT2"; + linux,code = ; + }; + sw22 { + gpios = <&gpio3 RK_PD1 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_START"; + linux,code = ; + }; + }; + + leds: gpio-leds { + compatible = "gpio-leds"; + pinctrl-0 = <&led_pins>; + pinctrl-names = "default"; + + /* charge_red_gpio = <&gpio0 17 0>; */ + led-0 { + color = ; + default-state = "off"; + function = LED_FUNCTION_CHARGING; + linux,default-trigger = "none"; + gpios = <&gpio0 RK_PC1 GPIO_ACTIVE_HIGH>; + }; + + /* charge_blue_gpio = <&gpio0 0 0>; */ + led-1 { + color = ; + default-state = "on"; + function = LED_FUNCTION_POWER; + linux,default-trigger = "default-on"; + gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; + }; + }; + + spk_amp: audio-amplifier { + compatible = "simple-audio-amplifier"; + enable-gpios = <&gpio3 RK_PA7 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&spk_amp_enable_h>; + pinctrl-names = "default"; + sound-name-prefix = "Speaker Amp"; + }; + + rk817-sound-amplified { + compatible = "simple-audio-card"; + pinctrl-names = "default"; + pinctrl-0 = <&hp_det>; + simple-audio-card,name = "rk817_ext"; + simple-audio-card,aux-devs = <&spk_amp>; + simple-audio-card,format = "i2s"; + simple-audio-card,hp-det-gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>; + simple-audio-card,mclk-fs = <256>; + simple-audio-card,widgets = + "Headphone", "Headphones", + "Speaker", "Internal Speakers"; + /* despite it's just a mono speaker, we need to route both Speaker Amp channels + Otherwise, the second channel stays on and keeps amp enabled */ + simple-audio-card,routing = + "Headphones", "HPOL", + "Headphones", "HPOR", + "Internal Speakers", "Speaker Amp OUTL", + "Internal Speakers", "Speaker Amp OUTR", + "Speaker Amp INL", "HPOL", + "Speaker Amp INR", "HPOR"; + + simple-audio-card,pin-switches = "Internal Speakers"; + + status = "disabled"; + + simple-audio-card,codec { + sound-dai = <&rk817>; + }; + + simple-audio-card,cpu { + sound-dai = <&i2s1_2ch>; + }; + }; + + rk817-sound-simple { + compatible = "simple-audio-card"; + pinctrl-names = "default"; + pinctrl-0 = <&hp_det>; + simple-audio-card,name = "rk817_ext"; + simple-audio-card,format = "i2s"; + simple-audio-card,hp-det-gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>; + simple-audio-card,mclk-fs = <256>; + simple-audio-card,widgets = + "Headphone", "Headphones", + "Speaker", "Internal Speakers"; + simple-audio-card,routing = + "Headphones", "HPOL", + "Headphones", "HPOR", + "Internal Speakers", "SPKO"; + + status = "disabled"; + + simple-audio-card,codec { + sound-dai = <&rk817>; + }; + + simple-audio-card,cpu { + sound-dai = <&i2s1_2ch>; + }; + }; + + vccsys: vccsys { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + + vcc-phy-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_phy"; + regulator-always-on; + regulator-boot-on; + }; + + vcc18_lcd0: vcc18-lcd0 { + compatible = "regulator-fixed"; + regulator-name = "vcc18_lcd0_n"; + gpio = <&gpio0 RK_PB5 GPIO_ACTIVE_HIGH>; + enable-active-high; + pinctrl-0 = <&vcc18_lcd_n>; + pinctrl-names = "default"; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_host: vcc_host { + compatible = "regulator-fixed"; + regulator-name = "vcc_host"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio3 RK_PA4 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&vcc5_usb>; + pinctrl-names = "default"; + enable-active-high; + regulator-always-on; + regulator-boot-on; + vin-supply = <&usb_midu>; + }; +}; + +&dmc { + center-supply = <&vdd_logic>; +}; + +&cpu0 { + cpu-supply = <&vdd_arm>; +}; + +&cpu1 { + cpu-supply = <&vdd_arm>; +}; + +&cpu2 { + cpu-supply = <&vdd_arm>; +}; + +&cpu3 { + cpu-supply = <&vdd_arm>; +}; + +&cru { + assigned-clocks = <&cru PLL_NPLL>, + <&cru ACLK_BUS_PRE>, <&cru ACLK_PERI_PRE>, + <&cru HCLK_BUS_PRE>, <&cru HCLK_PERI_PRE>, + <&cru PCLK_BUS_PRE>, <&cru SCLK_GPU>; + + assigned-clock-rates = <1188000000>, + <200000000>, <200000000>, + <150000000>, <150000000>, + <100000000>, <200000000>; +}; + +&display_subsystem { + status = "okay"; +}; + +&dsi { + status = "okay"; + + ports { + mipi_out: port@1 { + reg = <1>; + + mipi_out_panel: endpoint { + remote-endpoint = <&mipi_in_panel>; + }; + }; + }; + + internal_display: panel@0 { + compatible = "magicx,xu10-panel", "sitronix,st7703"; + iovcc-supply = <&vcc18_lcd0>; + vcc-supply = <&vcc18_lcd0>; + reg = <0>; + backlight = <&backlight>; + reset-gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&lcd_rst>; + + port { + mipi_in_panel: endpoint { + remote-endpoint = <&mipi_out_panel>; + }; + }; + }; +}; + +&dsi_dphy { + status = "okay"; +}; + +&gpu { + mali-supply = <&vdd_logic>; + status = "okay"; +}; + +&i2c0 { + clock-frequency = <400000>; + i2c-scl-falling-time-ns = <16>; + i2c-scl-rising-time-ns = <280>; + status = "okay"; + + rk817: pmic@20 { + compatible = "rockchip,rk817"; + reg = <0x20>; + interrupt-parent = <&gpio0>; + interrupts = ; + clock-output-names = "rk808-clkout1", "xin32k"; + clock-names = "mclk"; + clocks = <&cru SCLK_I2S1_OUT>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int>, <&i2s1_2ch_mclk>; + rockchip,system-power-controller; + wakeup-source; + #clock-cells = <1>; + #sound-dai-cells = <0>; + + vcc1-supply = <&vccsys>; + vcc2-supply = <&vccsys>; + vcc3-supply = <&vccsys>; + vcc4-supply = <&vccsys>; + vcc5-supply = <&vccsys>; + vcc6-supply = <&vccsys>; + vcc7-supply = <&vcc_3v0>; + vcc8-supply = <&vccsys>; + + regulators { + vdd_logic: DCDC_REG1 { + regulator-name = "vdd_logic"; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1350000>; + regulator-initial-mode = <0x02>; + regulator-ramp-delay = <6001>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vdd_arm: DCDC_REG2 { + regulator-name = "vdd_arm"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-initial-mode = <0x02>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-name = "vcc_ddr"; + regulator-always-on; + regulator-boot-on; + regulator-initial-mode = <0x02>; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_3v0: DCDC_REG4 { + regulator-name = "vcc_3v0"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-initial-mode = <0x02>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcc_1v0: LDO_REG1 { + regulator-name = "vcc_1v0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vcc1v8_soc: LDO_REG2 { + regulator-name = "vcc1v8_soc"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc1v0_soc: LDO_REG3 { + regulator-name = "vcc1v0_soc"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vcc3v0_pmu: LDO_REG4 { + regulator-name = "vcc3v0_pmu"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vccio_sd: LDO_REG5 { + regulator-name = "vccio_sd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_sd: LDO_REG6 { + regulator-name = "vcc_sd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc2v8_dvp: LDO_REG7 { + regulator-name = "vcc2v8_dvp"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc3v0_dvp: LDO_REG8 { + regulator-name = "vcc3v0_dvp"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vdd1v5_dvp: LDO_REG9 { + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + regulator-name = "vdd1v5_dvp"; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <1500000>; + }; + }; + + usb_midu: BOOST { + regulator-name = "usb_midu"; + regulator-min-microvolt = <4900000>; + regulator-max-microvolt = <5400000>; + regulator-always-on; + regulator-boot-on; + }; + + /* + otg_switch: OTG_SWITCH { + regulator-name = "otg_switch"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + */ + }; + + rk817_charger: charger { + monitored-battery = <&battery>; + rockchip,resistor-sense-micro-ohms = <10000>; + rockchip,sleep-enter-current-microamp = <300000>; + rockchip,sleep-filter-current-microamp = <100000>; + }; + + rk817_codec: codec { + rockchip,mic-in-differential; + }; + }; +}; + +/* I2S 1 Channel Used Header(P2):1(GPIO2.C3),2(.C2), 3(.C1), 4(.C5), 5(.C4) */ +&i2s1_2ch { + status = "okay"; + #sound-dai-cells = <0>; +}; + +&io_domains { + vccio1-supply = <&vcc2v8_dvp>; + vccio2-supply = <&vccio_sd>; + vccio3-supply = <&vcc1v8_soc>; + vccio4-supply = <&vcc_3v0>; + vccio5-supply = <&vcc_3v0>; + vccio6-supply = <&vcc1v8_soc>; + status = "okay"; +}; + +&isp { + status = "okay"; +}; + +&isp_mmu { + status = "okay"; +}; + +&pmu_io_domains { + pmuio1-supply = <&vcc3v0_pmu>; + pmuio2-supply = <&vcc3v0_pmu>; + status = "okay"; +}; + +&csi_dphy { + status = "okay"; +}; + +&pwm1 { + status = "okay"; +}; + +&saradc { + vref-supply = <&vcc1v8_soc>; + status = "okay"; +}; + +&sdmmc { + cap-sd-highspeed; + card-detect-delay = <800>; + cd-gpios = <&gpio0 RK_PA3 GPIO_ACTIVE_LOW>; /*[> ff370000 PD_SDCARD CD GPIO <]*/ + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + vqmmc-supply = <&vccio_sd>; + vmmc-supply = <&vcc_sd>; + status = "okay"; +}; + +&sdio { + cap-sd-highspeed; + max-frequency = <100000000>; + cd-gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_LOW>; + card-detect-delay = <800>; + supports-sd; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + vqmmc-supply = <&vcc2v8_dvp>; + vmmc-supply = <&vcc3v0_dvp>; + status = "okay"; +}; + +&emmc { + status = "okay"; + no-sdio; + no-sd; + disable-wp; + non-removable; + num-slots = <1>; +}; + +&tsadc { + status = "okay"; +}; + +&u2phy { + status = "okay"; + + u2phy_host: host-port { + status = "okay"; + }; + + u2phy_otg: otg-port { + status = "okay"; + }; +}; + +&usb20_otg { + status = "okay"; +}; + +&vopb { + status = "okay"; +}; + +&vopb_mmu { + status = "okay"; +}; +&pinctrl { + btns { + btn_pins: btn-pins { + rockchip,pins = + <2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB3 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PC0 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PC1 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PC2 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PC3 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PC4 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PC6 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PC7 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PD0 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PD1 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + headphone { + hp_det: hp-det { + rockchip,pins = <2 RK_PC6 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + gpio-lcd { + lcd_rst: lcd-rst { + rockchip,pins = <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + vcc18-lcd { + vcc18_lcd_n: vcc18-lcd-n { + rockchip,pins = <0 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + vcc5-usb { + vcc5_usb: vcc5-usb { + rockchip,pins = <3 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + gpio-led { + led_pins: led-pins { + rockchip,pins = + <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>, /* charge_blue_gpio = <&gpio0 0 0>; */ + <0 RK_PC1 RK_FUNC_GPIO &pcfg_pull_none>; /* charge_red_gpio = <&gpio0 17 0>; */ + }; + }; + + pmic { + dc_det: dc-det { + rockchip,pins = <0 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + pmic_int: pmic-int { + rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + soc_slppin_gpio: soc_slppin_gpio { + rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_output_low>; + }; + + soc_slppin_rst: soc_slppin_rst { + rockchip,pins = <0 RK_PA4 2 &pcfg_pull_none>; + }; + + soc_slppin_slp: soc_slppin_slp { + rockchip,pins = <0 RK_PA4 1 &pcfg_pull_none>; + }; + }; + + speaker { + spk_amp_enable_h: spk-amp-enable-h { + rockchip,pins = <3 RK_PA7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&uart5 { + status = "okay"; +}; +&uart2 { + status = "disabled"; +}; + + +&internal_display { + compatible = "archr,generic-dsi"; + panel_description = + "G size=153,85 delays=20,20,20,120,20 format=rgb888 lanes=4 flags=0xe03", + + "M clock=50000 horizontal=720,140,80,140 vertical=720,20,4,20 default=1", + "M clock=50000 horizontal=720,140,100,140 vertical=720,20,150,20", + "M clock=50040 horizontal=720,140,112,140 vertical=720,20,140,20", + "M clock=51400 horizontal=720,140,132,140 vertical=720,20,148,20", + "M clock=50140 horizontal=720,140,90,140 vertical=720,20,40,20", + "M clock=56900 horizontal=720,140,90,140 vertical=720,20,114,20", + "M clock=50400 horizontal=720,140,92,140 vertical=720,20,10,20", + "M clock=50220 horizontal=720,140,80,140 vertical=720,20,15,20", + "M clock=54600 horizontal=720,140,112,140 vertical=720,20,57,20", + "M clock=75450 horizontal=720,140,95,140 vertical=720,20,153,20", + "M clock=75330 horizontal=720,140,80,140 vertical=720,20,15,20", + "M clock=100440 horizontal=720,140,80,140 vertical=720,20,15,20", + + "I seq=b9f11283", + "I seq=b1000000da80", + "I seq=b23c1230", + "I seq=b31010282803ff00000000", + "I seq=b480", + "I seq=b50a0a", + "I seq=b69797", + "I seq=b82622f013", + "I seq=ba338105f90e0e2000000000000000442500900a0000014f01000037", + "I seq=bc47", + "I seq=bf021100", + "I seq=c0737350500000127000", + "I seq=c12500323277e4ffffcccc7777", + "I seq=c68200bfff00ff", + "I seq=c7b8000a000000", + "I seq=c810401e02", + "I seq=cc0b", + "I seq=e0000b102c3d3f423a070d0f131513140f16000b102c3d3f423a070d0f131513140f16", + "I seq=e307070b0b0b0b00000000ff00c010", + "I seq=e9c8100a000080811231234f86a000470800000c00000000000c00000098028baf4602888888888898138baf5713888888888800000000000000000000000000", + "I seq=ea970c090909780000000000009f318ba8317588888888889f208ba820648888888888230000027100000000000000000000000000000040808100000000", + "I seq=efffff01", + "I seq=11 wait=250", + "I seq=29 wait=50"; +}; + + diff --git a/config/archr-dts/rk3326-gameconsole-r33s.dts b/config/archr-dts/rk3326-gameconsole-r33s.dts new file mode 100644 index 0000000000..21dbab6d19 --- /dev/null +++ b/config/archr-dts/rk3326-gameconsole-r33s.dts @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * # Copyright (C) 2022-24 JELOS (https://github.com/JustEnoughLinuxOS) + */ + +/dts-v1/; +#include "rk3326-gameconsole-r3xs.dtsi" +#include "rk3326-device-group-r36.dtsi" + +/ { + model = "Game Console R33S"; + compatible = "gameconsole,r33s", "rockchip,rk3326"; + + archr,device_switch { + this = "r33s"; + }; + + builtin_gamepad: r33s_joypad { + compatible = "archr-singleadc-joypad"; + pinctrl-names = "default"; + pinctrl-0 = <&btn_pins>; + joypad-name = "r33s_joypad"; + joypad-product = <0x0AA2>; + joypad-revision = <0x0100>; + joypad-vendor = <0x0001>; + + status = "okay"; + amux-count = <0>; + /* poll device interval (ms), adc read interval */ + poll-interval = <10>; + pwms = <&pwm0 0 1000000000 0>; + pwm-names = "enable"; + rumble-boost-weak = <0x0000>; + rumble-boost-strong = <0x0000>; + + button-sw1 { + gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_LOW>; + label = "DPAD-UP"; + linux,code = ; + }; + button-sw2 { + gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_LOW>; + label = "DPAD-DOWN"; + linux,code = ; + }; + button-sw3 { + gpios = <&gpio1 RK_PB6 GPIO_ACTIVE_LOW>; + label = "DPAD-LEFT"; + linux,code = ; + }; + button-sw4 { + gpios = <&gpio1 RK_PB7 GPIO_ACTIVE_LOW>; + label = "DPAD-RIGHT"; + linux,code = ; + }; + button-sw5 { + gpios = <&gpio1 RK_PA2 GPIO_ACTIVE_LOW>; + label = "BTN-A"; + linux,code = ; + }; + button-sw6 { + gpios = <&gpio1 RK_PA5 GPIO_ACTIVE_LOW>; + label = "BTN-B"; + linux,code = ; + }; + button-sw7 { + gpios = <&gpio1 RK_PA6 GPIO_ACTIVE_LOW>; + label = "BTN-Y"; + linux,code = ; + }; + button-sw8 { + gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_LOW>; + label = "BTN-X"; + linux,code = ; + }; + button-sw9 { + gpios = <&gpio2 RK_PA6 GPIO_ACTIVE_LOW>; + label = "TOP-LEFT"; + linux,code = ; + }; + button-sw10 { + gpios = <&gpio2 RK_PA7 GPIO_ACTIVE_LOW>; + label = "TOP-RIGHT"; + linux,code = ; + }; + button-sw11 { + gpios = <&gpio3 RK_PB1 GPIO_ACTIVE_LOW>; + label = "SELECT"; + linux,code = ; + }; + button-sw12 { + gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; + label = "TOP-RIGHT 2"; + linux,code = ; + }; + button-sw13 { + gpios = <&gpio3 RK_PB2 GPIO_ACTIVE_LOW>; + label = "TOP-LEFT 2"; + linux,code = ; + }; + button-sw14 { + gpios = <&gpio3 RK_PB4 GPIO_ACTIVE_LOW>; + label = "START"; + linux,code = ; + }; + }; +}; + +&pinctrl { + btns { + btn_pins: btn-pins { + rockchip,pins = <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + }; +}; diff --git a/config/archr-dts/rk3326-gameconsole-r36max.dts b/config/archr-dts/rk3326-gameconsole-r36max.dts new file mode 100644 index 0000000000..dfc2c6e099 --- /dev/null +++ b/config/archr-dts/rk3326-gameconsole-r36max.dts @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * R36Max / K36 clone — alias for Generic EE clone board. + * + * ROCKNIX uses "r36max" for the K36 clone family. This DTS + * includes the eeclone base with a different model/compatible + * so U-Boot's fdtfile can reference either name. + * + * Copyright (c) 2024-present ROCKNIX (https://github.com/ROCKNIX) + * Copyright (c) 2025 Arch R + */ + +#include "rk3326-gameconsole-eeclone.dts" + +/ { + model = "Game Console R36Max"; + compatible = "gameconsole,r36max", "gameconsole,eeclone", "rockchip,rk3326"; +}; diff --git a/config/archr-dts/rk3326-gameconsole-r36s.dts b/config/archr-dts/rk3326-gameconsole-r36s.dts new file mode 100644 index 0000000000..5dbee3a001 --- /dev/null +++ b/config/archr-dts/rk3326-gameconsole-r36s.dts @@ -0,0 +1,234 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * # Copyright (C) 2022-24 JELOS (https://github.com/JustEnoughLinuxOS) + */ + +/dts-v1/; +#include "rk3326-gameconsole-r3xs.dtsi" +#include "rk3326-device-group-r36.dtsi" + +/ { + model = "Game Console R36S"; + compatible = "gameconsole,r35s", "gameconsole,r36s", "rockchip,rk3326"; + + archr,device_switch { + this = "r36s"; + }; + + /* R36S has an external speaker amplifier on GPIO3_PC4 */ + spk_amp: audio-amplifier { + compatible = "simple-audio-amplifier"; + enable-gpios = <&gpio3 RK_PC4 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&spk_amp_enable_h>; + pinctrl-names = "default"; + sound-name-prefix = "Speaker Amp"; + }; + + joypad: odroidgo3-joypad { + compatible = "odroidgo3-joypad"; + pwms = <&pwm0 0 200000000 0>; + pwm-names = "enable"; + rumble-boost-weak = <0x0000>; + rumble-boost-strong = <0x0000>; + + joypad-name = "r36s_Gamepad"; + joypad-product = <0x1188>; + joypad-revision = <0x0188>; + + status = "okay"; + + /* gpio pincontrol setup */ + pinctrl-names = "default"; + pinctrl-0 = <&btn_pins>; + pinctrl-1 = <&pwm0_pin>; + + /* Analog mux define */ + io-channel-names = "amux_adc"; + io-channels = <&saradc 1>; + + /* adc mux channel count */ + amux-count = <4>; + /* adc mux select(a,b) gpio */ + amux-a-gpios = <&gpio3 RK_PB3 GPIO_ACTIVE_LOW>; + amux-b-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>; + /* adc mux enable gpio */ + amux-en-gpios = <&gpio3 RK_PB5 GPIO_ACTIVE_LOW>; + + /* adc calculate scale */ + button-adc-scale = <2>; + + /* adc deadzone range */ + button-adc-deadzone = <64>; + + /* + specifies fuzz value that is used to filter noise from + the event stream. + */ + button-adc-fuzz = <32>; + button-adc-flat = <32>; + + /* + Analog Stick data tuning value(precent) + p = positive direction, n = negative direction + report value = (real_adc_data * tuning_value) / 100 + */ + abs_x-p-tuning = <200>; + abs_x-n-tuning = <200>; + + abs_y-p-tuning = <200>; + abs_y-n-tuning = <200>; + + abs_rx-p-tuning = <200>; + abs_rx-n-tuning = <200>; + + abs_ry-p-tuning = <200>; + abs_ry-n-tuning = <200>; + + /* poll device interval (ms), adc read interval */ + poll-interval = <10>; + + /* required for RG36S */ + invert-absx; + invert-absy; + + /* gpio button auto repeat set value : default disable */ + /* + autorepeat; + */ + + /* + joypad driver is poll-device driver. + poll-device is does not support wakeup-source. + */ + sw1 { + gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-UP"; + linux,code = ; // 0x220 + }; + sw2 { + gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-DOWN"; + linux,code = ; // 0x221 + }; + sw3 { + gpios = <&gpio1 RK_PB6 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-LEFT"; + linux,code = ; // 0x222 + }; + sw4 { + gpios = <&gpio1 RK_PB7 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-RIGHT"; + linux,code = ; // 0x223 + }; + sw5 { + gpios = <&gpio1 RK_PA2 GPIO_ACTIVE_LOW>; + label = "GPIO KEY BTN-A"; + linux,code = ; // 0x131 + }; + sw6 { + gpios = <&gpio1 RK_PA5 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-B"; + linux,code = ; // 0x130 + }; + sw7 { + gpios = <&gpio1 RK_PA6 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-Y"; + linux,code = ; // 0x134 + }; + sw8 { + gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-X"; + linux,code = ; // 0x133 + }; + sw11 { + gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_THUMBL"; + linux,code = ; // 0x2c2 + }; + sw12 { + gpios = <&gpio2 RK_PA3 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_THUMBR"; + linux,code = ; // 0x2c3 + }; + sw13 { + gpios = <&gpio2 RK_PA4 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_FN"; + linux,code = ; // 0x2c4 + }; + sw15 { + gpios = <&gpio2 RK_PA6 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-LEFT"; + linux,code = ; // 0x02 + }; + sw16 { + gpios = <&gpio2 RK_PA7 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-RIGHT"; + linux,code = ; // 0x05 + }; + sw19 { + gpios = <&gpio3 RK_PB1 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_SELECT"; + linux,code = ; + }; + sw20 { + gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-RIGHT2"; + linux,code = ; + }; + sw21 { + gpios = <&gpio3 RK_PB2 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-LEFT2"; + linux,code = ; + }; + sw22 { + gpios = <&gpio3 RK_PB4 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_START"; + linux,code = ; + }; + }; +}; + +/* Override sound card from r3xs.dtsi: add speaker amplifier */ +/ { + rk817-sound { + simple-audio-card,aux-devs = <&spk_amp>; + simple-audio-card,routing = + "MICL", "Mic Jack", + "Headphones", "HPOL", + "Headphones", "HPOR", + "Speaker Amp INL", "SPKO"; + }; +}; + +&pinctrl { + btns { + btn_pins: btn-pins { + rockchip,pins = <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>; + + }; + + }; + + speaker { + spk_amp_enable_h: spk-amp-enable-h { + rockchip,pins = <3 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; diff --git a/config/archr-dts/rk3326-gameconsole-r3xs.dtsi b/config/archr-dts/rk3326-gameconsole-r3xs.dtsi new file mode 100644 index 0000000000..b9f4f17ed5 --- /dev/null +++ b/config/archr-dts/rk3326-gameconsole-r3xs.dtsi @@ -0,0 +1,545 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * # Copyright (C) 2022-24 JELOS (https://github.com/JustEnoughLinuxOS) + */ + +/dts-v1/; +#include +#include +#include +#include +#include "rk3326.dtsi" + +/ { + model = "Game Console R33S"; + compatible = "gameconsolec,r33s", "rockchip,rk3326"; + + aliases { + mmc0 = &sdio; + mmc1 = &sdmmc; + }; + + chosen { + stdout-path = "serial2:115200n8"; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + power-supply = <&vcc_bl>; + pwms = <&pwm1 0 25000 0>; + brightness-levels = < + 0 1 2 3 4 5 6 7 + 8 9 10 11 12 13 14 15 + 16 17 18 19 20 21 22 23 + 24 25 26 27 28 29 30 31 + 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 + 48 49 50 51 52 53 54 55 + 56 57 58 59 60 61 62 63 + 64 65 66 67 68 69 70 71 + 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 + 88 89 90 91 92 93 94 95 + 96 97 98 99 100 101 102 103 + 104 105 106 107 108 109 110 111 + 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 + 128 129 130 131 132 133 134 135 + 136 137 138 139 140 141 142 143 + 144 145 146 147 148 149 150 151 + 152 153 154 155 156 157 158 159 + 160 161 162 163 164 165 166 167 + 168 169 170 171 172 173 174 175 + 176 177 178 179 180 181 182 183 + 184 185 186 187 188 189 190 191 + 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 + 208 209 210 211 212 213 214 215 + 216 217 218 219 220 221 222 223 + 224 225 226 227 228 229 230 231 + 232 233 234 235 236 237 238 239 + 240 241 242 243 244 245 246 247 + 248 249 250 251 252 253 254 255>; + default-brightness-level = <128>; + }; + + gpio-keys-vol { + compatible = "gpio-keys"; + autorepeat; + pinctrl-0 = <&btn_pins_vol>; + pinctrl-names = "default"; + + button-vol-down { + gpios = <&gpio2 RK_PA1 GPIO_ACTIVE_LOW>; + label = "VOLUMEDOWN"; + linux,code = ; + }; + + button-volume-up { + gpios = <&gpio2 RK_PA0 GPIO_ACTIVE_LOW>; + label = "VOLUMEUP"; + linux,code = ; + }; + }; + + battery: battery { + compatible = "simple-battery"; + charge-full-design-microamp-hours = <3200000>; + charge-term-current-microamp = <320000>; + constant-charge-current-max-microamp = <2000000>; + constant-charge-voltage-max-microvolt = <4200000>; + factory-internal-resistance-micro-ohms = <180000>; + voltage-max-design-microvolt = <4100000>; + voltage-min-design-microvolt = <3500000>; + + ocv-capacity-celsius = <20>; + ocv-capacity-table-0 = <4046950 100>, <4001920 95>, <3967900 90>, <3919950 85>, + <3888450 80>, <3861850 75>, <3831540 70>, <3799130 65>, + <3768190 60>, <3745650 55>, <3726610 50>, <3711630 45>, + <3696720 40>, <3685660 35>, <3674950 30>, <3663050 25>, + <3649470 20>, <3635260 15>, <3616920 10>, <3592440 5>, + <3574170 0>; + + }; + + rk817-sound { + compatible = "simple-audio-card"; + simple-audio-card,name = "rk817_int"; + simple-audio-card,format = "i2s"; + simple-audio-card,hp-det-gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>; + simple-audio-card,mclk-fs = <256>; + simple-audio-card,widgets = + "Microphone", "Mic Jack", + "Headphone", "Headphones", + "Speaker", "Speaker"; + simple-audio-card,routing = + "MICL", "Mic Jack", + "Headphones", "HPOL", + "Headphones", "HPOR", + "Speaker", "SPKO"; + + simple-audio-card,codec { + sound-dai = <&rk817>; + }; + + simple-audio-card,cpu { + sound-dai = <&i2s1_2ch>; + }; + }; + + vccsys: vccsys { + compatible = "regulator-fixed"; + regulator-name = "vcc3v8_sys"; + regulator-always-on; + regulator-min-microvolt = <3800000>; + regulator-max-microvolt = <3800000>; + }; +}; + +&dmc { + center-supply = <&vdd_logic>; +}; + +&cpu0 { + cpu-supply = <&vdd_arm>; +}; + +&cpu1 { + cpu-supply = <&vdd_arm>; +}; + +&cpu2 { + cpu-supply = <&vdd_arm>; +}; + +&cpu3 { + cpu-supply = <&vdd_arm>; +}; + +&cru { + assigned-clocks = <&cru PLL_NPLL>, + <&cru ACLK_BUS_PRE>, <&cru ACLK_PERI_PRE>, + <&cru HCLK_BUS_PRE>, <&cru HCLK_PERI_PRE>, + <&cru PCLK_BUS_PRE>, <&cru SCLK_GPU>; + + assigned-clock-rates = <1188000000>, + <200000000>, <200000000>, + <150000000>, <150000000>, + <100000000>, <200000000>; +}; + +&display_subsystem { + status = "okay"; +}; + +&dsi { + status = "okay"; + + ports { + mipi_out: port@1 { + reg = <1>; + + mipi_out_panel: endpoint { + remote-endpoint = <&mipi_in_panel>; + }; + }; + }; + + internal_display: panel@0 { + reg = <0>; + backlight = <&backlight>; + reset-gpios = <&gpio3 RK_PC0 GPIO_ACTIVE_LOW>; + + port { + mipi_in_panel: endpoint { + remote-endpoint = <&mipi_out_panel>; + }; + }; + }; +}; + +&dsi_dphy { + status = "okay"; +}; + +&gpu { + mali-supply = <&vdd_logic>; + status = "okay"; +}; + +&internal_display { + compatible = "gameconsole,r36s-panel", "sitronix,st7703"; + iovcc-supply = <&vcc_lcd>; + vdd-supply = <&vcc_lcd>; +}; + +&i2c0 { + clock-frequency = <400000>; + i2c-scl-falling-time-ns = <16>; + i2c-scl-rising-time-ns = <280>; + status = "okay"; + + rk817: pmic@20 { + compatible = "rockchip,rk817"; + reg = <0x20>; + interrupt-parent = <&gpio0>; + interrupts = ; + clock-output-names = "rk808-clkout1", "xin32k"; + clock-names = "mclk"; + clocks = <&cru SCLK_I2S1_OUT>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int>, <&i2s1_2ch_mclk>; + rockchip,system-power-controller; + wakeup-source; + #clock-cells = <1>; + #sound-dai-cells = <0>; + + vcc1-supply = <&vccsys>; + vcc2-supply = <&vccsys>; + vcc3-supply = <&vccsys>; + vcc4-supply = <&vccsys>; + vcc5-supply = <&vccsys>; + vcc6-supply = <&vccsys>; + vcc7-supply = <&vccsys>; + vcc8-supply = <&vccsys>; + + regulators { + vdd_logic: DCDC_REG1 { + regulator-name = "vdd_logic"; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1150000>; + regulator-ramp-delay = <6001>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vdd_arm: DCDC_REG2 { + regulator-name = "vdd_arm"; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-name = "vcc_ddr"; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_3v3: DCDC_REG4 { + regulator-name = "vcc_3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_1v8: LDO_REG2 { + regulator-name = "vcc_1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd_1v0: LDO_REG3 { + regulator-name = "vdd_1v0"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vcc3v3_pmu: LDO_REG4 { + regulator-name = "vcc3v3_pmu"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vccio_sd: LDO_REG5 { + regulator-name = "vccio_sd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc_sd: LDO_REG6 { + regulator-name = "vcc_sd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3000000>; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcc_bl: LDO_REG7 { + regulator-name = "vcc_bl"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_lcd: LDO_REG8 { + regulator-name = "vcc_lcd"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <2800000>; + }; + }; + + LDO_REG9 { + /* unused */ + }; + + usb_midu: BOOST { + regulator-name = "usb_midu"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5400000>; + regulator-always-on; + regulator-boot-on; + }; + }; + + rk817_charger: charger { + rockchip,resistor-sense-micro-ohms = <10000>; + rockchip,sleep-enter-current-microamp = <300000>; + rockchip,sleep-filter-current-microamp = <100000>; + }; + + rk817_codec: codec { + rockchip,mic-in-differential; + }; + }; +}; + +&i2s1_2ch { + status = "okay"; +}; + +&io_domains { + vccio1-supply = <&vccio_sd>; + vccio2-supply = <&vccio_sd>; + vccio3-supply = <&vcc_3v3>; + vccio4-supply = <&vcc_3v3>; + vccio5-supply = <&vcc_3v3>; + vccio6-supply = <&vcc_3v3>; + status = "okay"; +}; + +&pmu_io_domains { + pmuio1-supply = <&vcc3v3_pmu>; + pmuio2-supply = <&vcc3v3_pmu>; + status = "okay"; +}; + +&pwm0 { + status = "okay"; +}; + +&pwm1 { + status = "okay"; +}; + +&saradc { + vref-supply = <&vcc_1v8>; + status = "okay"; +}; + +&sdmmc { + bus-width = <4>; + cap-sd-highspeed; + card-detect-delay = <800>; + cd-gpios = <&gpio0 RK_PA3 GPIO_ACTIVE_LOW>; /*[> CD GPIO <]*/ + disable-wp; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + vmmc-supply = <&vcc_sd>; + vqmmc-supply = <&vccio_sd>; + status = "okay"; +}; + +&sdio { + bus-width = <4>; + cap-sd-highspeed; + card-detect-delay = <800>; + cd-gpios = <&gpio3 RK_PB6 GPIO_ACTIVE_LOW>; /*[> CD GPIO <]*/ + disable-wp; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + vmmc-supply = <&vcc_sd>; + vqmmc-supply = <&vccio_sd>; + status = "okay"; +}; + +&tsadc { + status = "okay"; +}; + +&u2phy { + status = "okay"; + + u2phy_host: host-port { + status = "okay"; + }; + + u2phy_otg: otg-port { + status = "okay"; + }; +}; + +&usb20_otg { + status = "okay"; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&uart2m1_xfer>; + status = "okay"; +}; + +&vopb { + status = "okay"; +}; + +&vopb_mmu { + status = "okay"; +}; + +&rk817_charger { + monitored-battery = <&battery>; +}; + +&pinctrl { + btns { + btn_pins_vol: btn-pins-vol { + rockchip,pins = <2 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + headphone { + hp_det: hp-det { + rockchip,pins = <2 RK_PC6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + + pmic { + dc_det: dc-det { + rockchip,pins = <0 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + pmic_int: pmic-int { + rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + soc_slppin_gpio: soc_slppin_gpio { + rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_output_low>; + }; + + soc_slppin_rst: soc_slppin_rst { + rockchip,pins = <0 RK_PA4 2 &pcfg_pull_none>; + }; + + soc_slppin_slp: soc_slppin_slp { + rockchip,pins = <0 RK_PA4 1 &pcfg_pull_none>; + }; + }; +}; diff --git a/config/archr-dts/rk3326-gameconsole-soysauce.dts b/config/archr-dts/rk3326-gameconsole-soysauce.dts new file mode 100644 index 0000000000..74b236bd6f --- /dev/null +++ b/config/archr-dts/rk3326-gameconsole-soysauce.dts @@ -0,0 +1,243 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (C) 2026 ArchR (https://github.com/archr-linux/Arch-R) + * + * Device tree for R36S "soysauce" variant (Y3506 boards). + * Hardware differences from standard R36S: + * - All buttons on GPIO3 (standard uses GPIO1/GPIO2) + * - Analog mux on GPIO0 (standard uses GPIO3) + * - Panel reset GPIO: GPIO3_PB0 + * - Panel enable GPIO: GPIO1_PC2 + * - amux-channel-mapping reordered + * - Different joypad product ID (0x1100 "GO-Super Gamepad") + */ + +/dts-v1/; +#include "rk3326-gameconsole-r3xs.dtsi" +#include "rk3326-device-group-r36.dtsi" + +/ { + model = "Game Console R36S Soysauce"; + compatible = "gameconsole,soysauce", "gameconsole,r36s", "rockchip,rk3326"; + + archr,device_switch { + this = "soysauce"; + }; + + /* LED indicators (soysauce-specific) */ + leds { + compatible = "gpio-leds"; + + led-red { + gpios = <&gpio0 RK_PA5 GPIO_ACTIVE_LOW>; + label = "red"; + default-state = "off"; + }; + + led-blue { + gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_LOW>; + label = "blue"; + default-state = "off"; + }; + }; + + /* Volume buttons: GPIO3_PC6/PC5 on soysauce (base has GPIO2_PA0/PA1) */ + gpio-keys-vol { + button-vol-down { + gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_LOW>; + }; + + button-volume-up { + gpios = <&gpio3 RK_PC6 GPIO_ACTIVE_LOW>; + }; + }; + + joypad: odroidgo3-joypad { + compatible = "archr-joypad", "odroidgo3-joypad"; + pwms = <&pwm0 0 200000000 0>; + pwm-names = "enable"; + rumble-boost-weak = <0x0000>; + rumble-boost-strong = <0x0000>; + + joypad-name = "GO-Super Gamepad"; + joypad-product = <0x1100>; + joypad-revision = <0x0100>; + + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&btn_pins>; + pinctrl-1 = <&pwm0_pin>; + + /* Analog mux on GPIO0 (different from standard R36S) */ + io-channel-names = "amux_adc"; + io-channels = <&saradc 1>; + + amux-count = <4>; + amux-channel-mapping = <3 2 0 1>; + amux-a-gpios = <&gpio0 RK_PB5 GPIO_ACTIVE_LOW>; + amux-b-gpios = <&gpio0 RK_PB4 GPIO_ACTIVE_LOW>; + amux-en-gpios = <&gpio0 RK_PC1 GPIO_ACTIVE_LOW>; + + button-adc-scale = <2>; + button-adc-deadzone = <64>; + button-adc-fuzz = <32>; + button-adc-flat = <32>; + + abs_x-p-tuning = <200>; + abs_x-n-tuning = <200>; + abs_y-p-tuning = <200>; + abs_y-n-tuning = <200>; + abs_rx-p-tuning = <200>; + abs_rx-n-tuning = <200>; + abs_ry-p-tuning = <200>; + abs_ry-n-tuning = <200>; + + poll-interval = <10>; + + invert-absx; + invert-absy; + + /* All buttons on GPIO3 (soysauce layout) */ + sw1 { + gpios = <&gpio3 RK_PA7 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-UP"; + linux,code = ; + }; + sw2 { + gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-DOWN"; + linux,code = ; + }; + sw3 { + gpios = <&gpio3 RK_PB2 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-LEFT"; + linux,code = ; + }; + sw4 { + gpios = <&gpio3 RK_PB1 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-RIGHT"; + linux,code = ; + }; + sw5 { + gpios = <&gpio3 RK_PB6 GPIO_ACTIVE_LOW>; + label = "GPIO KEY BTN-A"; + linux,code = ; + }; + sw6 { + gpios = <&gpio3 RK_PB4 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-B"; + linux,code = ; + }; + sw7 { + gpios = <&gpio3 RK_PB3 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-Y"; + linux,code = ; + }; + sw8 { + gpios = <&gpio3 RK_PB5 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-X"; + linux,code = ; + }; + sw11 { + gpios = <&gpio0 RK_PB3 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_THUMBL"; + linux,code = ; + }; + sw12 { + gpios = <&gpio3 RK_PD3 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_THUMBR"; + linux,code = ; + }; + sw13 { + gpios = <&gpio3 RK_PA4 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_MODE"; + linux,code = ; + }; + sw15 { + gpios = <&gpio3 RK_PA3 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-LEFT"; + linux,code = ; + }; + sw16 { + gpios = <&gpio3 RK_PA0 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-RIGHT"; + linux,code = ; + }; + sw19 { + gpios = <&gpio3 RK_PA5 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_SELECT"; + linux,code = ; + }; + sw20 { + gpios = <&gpio3 RK_PA2 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-LEFT2"; + linux,code = ; + }; + sw21 { + gpios = <&gpio3 RK_PA1 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-RIGHT2"; + linux,code = ; + }; + sw22 { + gpios = <&gpio3 RK_PA6 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_START"; + linux,code = ; + }; + }; +}; + +/* Soysauce panel: same reset GPIO as base (GPIO3_PC0), add enable GPIO */ +&internal_display { + compatible = "archr,generic-dsi", "rocknix,generic-dsi"; + enable-gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_HIGH>; +}; + +/* Soysauce uses GPIO3_PB6 for BTN-A, not sdio card detect */ +&sdio { + /delete-property/ cd-gpios; + non-removable; +}; + +&rk817_codec { + spk-ctl-gpios = <&gpio3 RK_PC4 GPIO_ACTIVE_HIGH>; +}; + +&pinctrl { + btns { + btn_pins_vol: btn-pins-vol { + rockchip,pins = <3 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PC6 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + btn_pins: btn-pins { + rockchip,pins = + <3 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB3 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>, + <0 RK_PB3 RK_FUNC_GPIO &pcfg_pull_up>, + <0 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <0 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>, + <0 RK_PC1 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + panel { + panel_enable: panel-enable { + rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; diff --git a/config/archr-dts/rk3326-gameforce-chi.dts b/config/archr-dts/rk3326-gameforce-chi.dts new file mode 100644 index 0000000000..7b47cf7017 --- /dev/null +++ b/config/archr-dts/rk3326-gameforce-chi.dts @@ -0,0 +1,811 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2024 Chris Morgan + */ + +/dts-v1/; +#include +#include +#include +#include +#include "rk3326.dtsi" + +/ { + model = "GameForce Chi"; + compatible = "gameforce,chi", "rockchip,rk3326"; + chassis-type = "handset"; + + aliases { + mmc0 = &sdmmc; + mmc1 = &sdio; + }; + + chosen { + stdout-path = "serial2:115200n8"; + }; + + adc_joystick: adc-joystick { + compatible = "adc-joystick"; + io-channels = <&saradc 0>, + <&saradc 1>; + poll-interval = <100>; + #address-cells = <1>; + #size-cells = <0>; + + axis@0 { + reg = <0>; + abs-flat = <10>; + abs-fuzz = <10>; + abs-range = <850 175>; + linux,code = ; + }; + + axis@1 { + reg = <1>; + abs-flat = <10>; + abs-fuzz = <10>; + abs-range = <800 190>; + linux,code = ; + }; + }; + + adc_keys: adc-keys { + compatible = "adc-keys"; + io-channels = <&saradc 2>; + io-channel-names = "buttons"; + keyup-threshold-microvolt = <1800000>; + poll-interval = <60>; + + button-1 { + label = "HAPPY1"; + linux,code = ; + press-threshold-microvolt = <15000>; + }; + + button-2 { + label = "HAPPY2"; + linux,code = ; + press-threshold-microvolt = <300000>; + }; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + power-supply = <&vcc_bl>; + pwms = <&pwm1 0 25000 0>; + }; + + battery: battery { + compatible = "simple-battery"; + charge-full-design-microamp-hours = <3000000>; + charge-term-current-microamp = <300000>; + constant-charge-current-max-microamp = <1500000>; + constant-charge-voltage-max-microvolt = <4200000>; + factory-internal-resistance-micro-ohms = <180000>; + ocv-capacity-celsius = <20>; + ocv-capacity-table-0 = <4106000 100>, <4071000 95>, <4018000 90>, <3975000 85>, + <3946000 80>, <3908000 75>, <3877000 70>, <3853000 65>, + <3834000 60>, <3816000 55>, <3802000 50>, <3788000 45>, + <3774000 40>, <3760000 35>, <3748000 30>, <3735000 25>, + <3718000 20>, <3697000 15>, <3685000 10>, <3625000 5>, + <3400000 0>; + voltage-max-design-microvolt = <4250000>; + voltage-min-design-microvolt = <3400000>; + }; + + gpio_leds: gpio-leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins>; + + red_led: led-0 { + color = ; + gpios = <&gpio3 RK_PC4 GPIO_ACTIVE_HIGH>; + }; + + green_led: led-1 { + color = ; + gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>; + }; + + blue_led: led-2 { + color = ; + gpios = <&gpio3 RK_PC6 GPIO_ACTIVE_HIGH>; + }; + + white_led: led-3 { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&gpio3 RK_PB3 GPIO_ACTIVE_HIGH>; + }; + + chg_led: led-4 { + color = ; + function = LED_FUNCTION_CHARGING; + gpios = <&gpio3 RK_PB2 GPIO_ACTIVE_HIGH>; + }; + + }; + + gpio_keys: gpio-keys { + compatible = "gpio-keys"; + pinctrl-0 = <&btn_pins_ctrl>; + pinctrl-names = "default"; + + button-a { + gpios = <&gpio2 RK_PB0 GPIO_ACTIVE_LOW>; + label = "EAST"; + linux,code = ; + }; + + button-b { + gpios = <&gpio2 RK_PB1 GPIO_ACTIVE_LOW>; + label = "SOUTH"; + linux,code = ; + }; + + button-down { + gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_LOW>; + label = "DPAD-DOWN"; + linux,code = ; + }; + + button-home { + gpios = <&gpio2 RK_PA0 GPIO_ACTIVE_LOW>; + label = "HOME"; + linux,code = ; + }; + + button-l1 { + gpios = <&gpio2 RK_PA6 GPIO_ACTIVE_LOW>; + label = "TL"; + linux,code = ; + }; + + button-l2 { + gpios = <&gpio2 RK_PA4 GPIO_ACTIVE_LOW>; + label = "TL2"; + linux,code = ; + }; + + button-left { + gpios = <&gpio1 RK_PB6 GPIO_ACTIVE_LOW>; + label = "DPAD-LEFT"; + linux,code = ; + }; + + button-r1 { + gpios = <&gpio2 RK_PA7 GPIO_ACTIVE_LOW>; + label = "TR"; + linux,code = ; + }; + + button-r2 { + gpios = <&gpio2 RK_PA5 GPIO_ACTIVE_LOW>; + label = "TR2"; + linux,code = ; + }; + + button-right { + gpios = <&gpio1 RK_PB7 GPIO_ACTIVE_LOW>; + label = "DPAD-RIGHT"; + linux,code = ; + }; + + button-select { + gpios = <&gpio2 RK_PA3 GPIO_ACTIVE_LOW>; + label = "SELECT"; + linux,code = ; + }; + + button-start { + gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; + label = "START"; + linux,code = ; + }; + + button-up { + gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_LOW>; + label = "DPAD-UP"; + linux,code = ; + }; + + button-x { + gpios = <&gpio2 RK_PB3 GPIO_ACTIVE_LOW>; + label = "NORTH"; + linux,code = ; + }; + + button-y { + gpios = <&gpio2 RK_PB2 GPIO_ACTIVE_LOW>; + label = "WEST"; + linux,code = ; + }; + }; + + multi-led { + compatible = "leds-group-multicolor"; + color = ; + function = LED_FUNCTION_KBD_BACKLIGHT; + leds = <&red_led>, <&green_led>, <&blue_led>; + }; + + spk_amp: audio-amplifier { + compatible = "simple-audio-amplifier"; + enable-gpios = <&gpio2 RK_PB5 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&spk_amp_enable_h>; + pinctrl-names = "default"; + sound-name-prefix = "Speaker Amp"; + }; + + sound { + compatible = "simple-audio-card"; + pinctrl-0 = <&hp_det>; + pinctrl-names = "default"; + simple-audio-card,name = "rk817_ext"; + simple-audio-card,aux-devs = <&spk_amp>; + simple-audio-card,format = "i2s"; + simple-audio-card,hp-det-gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>; + simple-audio-card,mclk-fs = <256>; + simple-audio-card,widgets = + "Microphone", "Mic Jack", + "Headphone", "Headphones", + "Speaker", "Internal Speakers"; + simple-audio-card,routing = + "MICL", "Mic Jack", + "Headphones", "HPOL", + "Headphones", "HPOR", + "Internal Speakers", "Speaker Amp OUTL", + "Internal Speakers", "Speaker Amp OUTR", + "Speaker Amp INL", "HPOL", + "Speaker Amp INR", "HPOR"; + simple-audio-card,pin-switches = "Internal Speakers"; + + simple-audio-card,codec { + sound-dai = <&rk817>; + }; + + simple-audio-card,cpu { + sound-dai = <&i2s1_2ch>; + }; + }; + + vibrator_left: pwm-vibrator-l { + compatible = "pwm-vibrator"; + pwm-names = "enable"; + pwms = <&pwm4 0 25000 0>; + }; + + vibrator_right: pwm-vibrator-r { + compatible = "pwm-vibrator"; + pwm-names = "enable"; + pwms = <&pwm5 0 25000 0>; + }; + + sdio_pwrseq: sdio-pwrseq { + compatible = "mmc-pwrseq-simple"; + clocks = <&rk817 1>; + clock-names = "ext_clock"; + pinctrl-0 = <&wifi_enable_h>; + pinctrl-names = "default"; + post-power-on-delay-ms = <200>; + reset-gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_LOW>; + }; + + vccsys: regulator-vccsys { + compatible = "regulator-fixed"; + regulator-name = "vcc3v8_sys"; + regulator-always-on; + regulator-min-microvolt = <3800000>; + regulator-max-microvolt = <3800000>; + }; +}; + +&cpu0 { + cpu-supply = <&vdd_arm>; +}; + +&cpu1 { + cpu-supply = <&vdd_arm>; +}; + +&cpu2 { + cpu-supply = <&vdd_arm>; +}; + +&cpu3 { + cpu-supply = <&vdd_arm>; +}; + +&display_subsystem { + status = "okay"; +}; + +&dsi { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + internal_display: panel@0 { + reg = <0>; + compatible = "gameforce,chi-panel"; + backlight = <&backlight>; + iovcc-supply = <&vcc_lcd>; + vcc-supply = <&vcc_lcd>; + reset-gpios = <&gpio3 RK_PA0 GPIO_ACTIVE_LOW>; + + port { + mipi_in_panel: endpoint { + remote-endpoint = <&mipi_out_panel>; + }; + }; + }; + + ports { + mipi_out: port@1 { + reg = <1>; + + mipi_out_panel: endpoint { + remote-endpoint = <&mipi_in_panel>; + }; + }; + }; +}; + +&dsi_dphy { + status = "okay"; +}; + +&gpu { + mali-supply = <&vdd_logic>; + status = "okay"; +}; + +&i2c0 { + clock-frequency = <400000>; + i2c-scl-falling-time-ns = <16>; + i2c-scl-rising-time-ns = <280>; + status = "okay"; + + rk817: pmic@20 { + compatible = "rockchip,rk817"; + reg = <0x20>; + #clock-cells = <1>; + clock-names = "mclk"; + clock-output-names = "rk808-clkout1", "xin32k"; + clocks = <&cru SCLK_I2S1_OUT>; + interrupt-parent = <&gpio0>; + interrupts = ; + pinctrl-0 = <&pmic_int>, <&i2s1_2ch_mclk>; + pinctrl-names = "default"; + #sound-dai-cells = <0>; + system-power-controller; + wakeup-source; + + vcc1-supply = <&vccsys>; + vcc2-supply = <&vccsys>; + vcc3-supply = <&vccsys>; + vcc4-supply = <&vccsys>; + vcc5-supply = <&vccsys>; + vcc6-supply = <&vccsys>; + vcc7-supply = <&vcc_3v0>; + vcc8-supply = <&vccsys>; + vcc9-supply = <&dcdc_boost>; + + regulators { + vdd_logic: DCDC_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1150000>; + regulator-min-microvolt = <950000>; + regulator-name = "vdd_logic"; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vdd_arm: DCDC_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1350000>; + regulator-min-microvolt = <950000>; + regulator-name = "vdd_arm"; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc_ddr"; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_3v0: DCDC_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <3000000>; + regulator-min-microvolt = <3000000>; + regulator-name = "vcc_3v0"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcc_1v8: LDO_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1800000>; + regulator-min-microvolt = <1800000>; + regulator-name = "vcc_1v8"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd_1v0: LDO_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1000000>; + regulator-min-microvolt = <1000000>; + regulator-name = "vdd_1v0"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vcc_3v0_pmu: LDO_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <3000000>; + regulator-min-microvolt = <3000000>; + regulator-name = "vcc_3v0_pmu"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vccio_sd: LDO_REG5 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <1800000>; + regulator-name = "vccio_sd"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_sd: LDO_REG6 { + regulator-boot-on; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "vcc_sd"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_bl: LDO_REG7 { + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "vcc_bl"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_lcd: LDO_REG8 { + regulator-max-microvolt = <2800000>; + regulator-min-microvolt = <2800000>; + regulator-name = "vcc_lcd"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <2800000>; + }; + }; + + vcc_wifi: LDO_REG9 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "vcc_wifi"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + dcdc_boost: BOOST { + regulator-max-microvolt = <5000000>; + regulator-min-microvolt = <5000000>; + regulator-name = "dcdc_boost"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + otg_switch: OTG_SWITCH { + regulator-name = "otg_switch"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + + rk817_charger: charger { + monitored-battery = <&battery>; + rockchip,resistor-sense-micro-ohms = <10000>; + rockchip,sleep-enter-current-microamp = <300000>; + rockchip,sleep-filter-current-microamp = <100000>; + }; + }; +}; + +&i2s1_2ch { + status = "okay"; +}; + +&io_domains { + vccio1-supply = <&vcc_3v0_pmu>; + vccio2-supply = <&vccio_sd>; + vccio3-supply = <&vcc_3v0>; + vccio4-supply = <&vcc_3v0>; + vccio5-supply = <&vcc_3v0>; + vccio6-supply = <&vcc_3v0>; + status = "okay"; +}; + +&pinctrl { + bluetooth-pins { + bt_reset: bt-reset { + rockchip,pins = + <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + bt_wake_dev: bt-wake-dev { + rockchip,pins = + <0 RK_PA1 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + bt_wake_host: bt-wake-host { + rockchip,pins = + <0 RK_PA7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + headphone { + hp_det: hp-det { + rockchip,pins = + <2 RK_PC6 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + gpio-btns { + btn_pins_ctrl: btn-pins-ctrl { + rockchip,pins = + <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PB3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + gpio-leds { + led_pins: led-pins { + rockchip,pins = + <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>, + <3 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>, + <3 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>, + <3 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>, + <3 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pmic { + pmic_int: pmic-int { + rockchip,pins = + <0 RK_PC1 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + soc_slppin_gpio: soc_slppin_gpio { + rockchip,pins = + <0 RK_PA4 RK_FUNC_GPIO &pcfg_output_low>; + }; + + soc_slppin_rst: soc_slppin_rst { + rockchip,pins = + <0 RK_PA4 2 &pcfg_pull_none>; + }; + + soc_slppin_slp: soc_slppin_slp { + rockchip,pins = + <0 RK_PA4 1 &pcfg_pull_none>; + }; + }; + + sdio-pwrseq { + wifi_enable_h: wifi-enable-h { + rockchip,pins = + <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + speaker { + spk_amp_enable_h: spk-amp-enable-h { + rockchip,pins = + <2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&pmu_io_domains { + pmuio1-supply = <&vcc_1v8>; + pmuio2-supply = <&vcc_3v0_pmu>; + status = "okay"; +}; + +&pwm1 { + status = "okay"; +}; + +&pwm4 { + status = "okay"; +}; + +&pwm5 { + status = "okay"; +}; + +&saradc { + vref-supply = <&vcc_1v8>; + status = "okay"; +}; + +&sdio { + bus-width = <4>; + cap-sd-highspeed; + cap-sdio-irq; + disable-wp; + keep-power-in-suspend; + mmc-pwrseq = <&sdio_pwrseq>; + no-mmc; + no-sd; + non-removable; + sd-uhs-sdr104; + status = "okay"; +}; + +&sdmmc { + cap-mmc-highspeed; + cap-sd-highspeed; + no-sdio; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + vmmc-supply = <&vcc_sd>; + vqmmc-supply = <&vccio_sd>; + status = "okay"; +}; + +&sfc { + #address-cells = <1>; + pinctrl-0 = <&sfc_clk &sfc_cs0 &sfc_bus2>; + pinctrl-names = "default"; + #size-cells = <0>; + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <108000000>; + spi-rx-bus-width = <2>; + spi-tx-bus-width = <1>; + }; +}; + +&tsadc { + status = "okay"; +}; + +&u2phy { + status = "okay"; + + u2phy_otg: otg-port { + status = "okay"; + }; +}; + +&usb20_otg { + status = "okay"; +}; + +/* + * The right ADC joystick exists connected to an unknown ADC + * controller which can be communicated with via uart0. This ADC device + * is an 8-pin SOIC with no markings located right next to the left ADC + * joystick ribbon cable. The pinout for this ADC controller appears to + * be pin 1 - VCC (2.8v), pin 2 - 1.8v (clk maybe?), pin 3 - GPIO 10, + * pin 4 - unknown, pin 5 - unknown, pin 6 - analog in, pin 7 - analog in, + * pin 8 - ground. There is currently a userspace UART driver for this + * device but it only works with the BSP joystick driver. + */ +&uart0 { + status = "okay"; +}; + +/* + * Bluetooth was not working on BSP and is not currently working on + * mainline due to missing firmware. Bluetooth requires removal of DMA + * or else it will not probe. + */ +&uart1 { + /delete-property/ dma-names; + /delete-property/ dmas; + uart-has-rtscts; + status = "okay"; + + bluetooth: bluetooth { + compatible = "realtek,rtl8723ds-bt"; + device-wake-gpios = <&gpio0 RK_PA1 GPIO_ACTIVE_HIGH>; + enable-gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; + host-wake-gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&bt_reset>, <&bt_wake_dev>, <&bt_wake_host>; + pinctrl-names = "default"; + }; +}; + +&uart2 { + pinctrl-0 = <&uart2m1_xfer>; + pinctrl-names = "default"; + status = "okay"; +}; + +&vopb { + status = "okay"; +}; + +&vopb_mmu { + status = "okay"; +}; diff --git a/config/archr-dts/rk3326-magicx-xu-mini-m.dts b/config/archr-dts/rk3326-magicx-xu-mini-m.dts new file mode 100644 index 0000000000..ad4841e365 --- /dev/null +++ b/config/archr-dts/rk3326-magicx-xu-mini-m.dts @@ -0,0 +1,109 @@ +/// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2024-present ROCKNIX (https://github.com/ROCKNIX) + * Copyright (c) 2024 Olivier Schonken + */ + +#include "rk3326-magicx-xu10.dts" + +/ { + model = "MagicX XU Mini M"; + compatible = "magicx,xu-mini-m", "rockchip,rk3326"; +}; + +&battery { + charge-full-design-microamp-hours = <2600000>; +}; + +&dsi { + internal_display: panel@0 { + compatible = "archr,generic-dsi"; + panel_description = + "G size=69,139 delays=5,20,20,120,20 format=rgb888 lanes=2 flags=0xe03", + + "M clock=25000 horizontal=480,60,10,54 vertical=640,20,10,20 default=1", + "M clock=25200 horizontal=480,60,22,54 vertical=640,20,139,20", + "M clock=25000 horizontal=480,60,31,54 vertical=640,20,120,20", + "M clock=25660 horizontal=480,60,22,54 vertical=640,20,153,20", + "M clock=25300 horizontal=480,60,31,54 vertical=640,20,24,20", + "M clock=28590 horizontal=480,60,15,54 vertical=640,20,106,20", + "M clock=25380 horizontal=480,60,17,54 vertical=640,20,13,20", + "M clock=25410 horizontal=480,60,11,54 vertical=640,20,20,20", + "M clock=29490 horizontal=480,60,24,54 vertical=640,20,114,20", + "M clock=33520 horizontal=480,60,36,54 vertical=640,20,25,20", + "M clock=38430 horizontal=480,60,16,54 vertical=640,20,20,20", + "M clock=50820 horizontal=480,60,11,54 vertical=640,20,20,20", + + "I seq=ff7701000013", + "I seq=ef08", + "I seq=ff7701000010", + "I seq=c04f00", "I seq=c11002", "I seq=c22002", "I seq=cc10", + "I seq=b006161e0e12060a0809230412102b311f", + "I seq=b1060f160d100704090720051210262f1f", + "I seq=ff7701000011", + "I seq=b065", "I seq=b185", "I seq=b282", "I seq=b380", "I seq=b542", "I seq=b785", + "I seq=b820", + "I seq=c178", "I seq=c278", + "I seq=d088", + "I seq=e0000002", + "I seq=e104a006a005a007a0004444", + "I seq=e2000000000000000000000000", + "I seq=e300002222", + "I seq=e44444", + "I seq=e50c90a0a00e92a0a0088ca0a00a8ea0a0", + "I seq=e600002222", + "I seq=e74444", + "I seq=e80d91a0a00f93a0a0098da0a00b8fa0a0", + "I seq=eb0000e4e4440040", + "I seq=edfff5476f0ba1abffffba1ab0f6745fff", + "I seq=ef080808403f64", + "I seq=ff7701000013", + "I seq=e6167c", "I seq=e8000e", + "I seq=e8000c wait=50", + "I seq=e80000", + "I seq=ff7701000000", + "I seq=11 wait=150", + "I seq=29 wait=120"; + rotation = <90>; + }; +}; + +&joypad { + joypad-name = "XU Mini M Gamepad"; + + invert-absrx; + /delete-property/ invert-absx; + + sw5 { + gpios = <&gpio2 RK_PA3 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-B"; + }; + sw6 { + gpios = <&gpio2 RK_PA1 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-A"; + }; + sw7 { + gpios = <&gpio2 RK_PA0 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-X"; + }; + sw8 { + gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-Y"; + }; + sw16 { + gpios = <&gpio3 RK_PB4 GPIO_ACTIVE_LOW>; + }; + sw17 { + gpios = <&gpio3 RK_PB2 GPIO_ACTIVE_LOW>; + }; +}; + +&pinctrl { + headphone { + hp_det: hp-det { + rockchip,pins = <2 RK_PC6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; +}; + + diff --git a/config/archr-dts/rk3326-magicx-xu10.dts b/config/archr-dts/rk3326-magicx-xu10.dts new file mode 100644 index 0000000000..91e06ffd17 --- /dev/null +++ b/config/archr-dts/rk3326-magicx-xu10.dts @@ -0,0 +1,872 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2019 Hardkernel Co., Ltd + * Copyright (c) 2020 Theobroma Systems Design und Consulting GmbH + * Copyright (c) 2022 Maya Matuszczyk + */ + +/dts-v1/; +#include +#include +#include +#include +#include "rk3326.dtsi" + +/ { + model = "MagicX XU10"; + compatible = "magicx,xu10", "rockchip,rk3326"; + + aliases { + mmc0 = &sdio; + mmc1 = &sdmmc; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + pwms = <&pwm1 0 25000 0>; + brightness-levels = < + 0 1 2 3 4 5 6 7 + 8 9 10 11 12 13 14 15 + 16 17 18 19 20 21 22 23 + 24 25 26 27 28 29 30 31 + 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 + 48 49 50 51 52 53 54 55 + 56 57 58 59 60 61 62 63 + 64 65 66 67 68 69 70 71 + 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 + 88 89 90 91 92 93 94 95 + 96 97 98 99 100 101 102 103 + 104 105 106 107 108 109 110 111 + 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 + 128 129 130 131 132 133 134 135 + 136 137 138 139 140 141 142 143 + 144 145 146 147 148 149 150 151 + 152 153 154 155 156 157 158 159 + 160 161 162 163 164 165 166 167 + 168 169 170 171 172 173 174 175 + 176 177 178 179 180 181 182 183 + 184 185 186 187 188 189 190 191 + 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 + 208 209 210 211 212 213 214 215 + 216 217 218 219 220 221 222 223 + 224 225 226 227 228 229 230 231 + 232 233 234 235 236 237 238 239 + 240 241 242 243 244 245 246 247 + 248 249 250 251 252 253 254 255>; + default-brightness-level = <128>; + }; + + joypad: xu10-joypad { + compatible = "xu10-joypad"; + + joypad-name = "XU10 Gamepad"; + joypad-product = <0x0200>; + joypad-revision = <0x0010>; + + status = "okay"; + /* + - xu10-joypad sysfs list - + * for poll device interval(ms) + /sys/devices/platform/odroidgo3_joypad/poll_interval [rw] + ex) echo 20 > poll_interval + * for button-adc-fuzz + /sys/devices/platform/odroidgo3_joypad/adc_fuzz [r] + * for button-adc-flat + /sys/devices/platform/odroidgo3_joypad/adc_flat [r] + + * for report control(1:enable, 0:disable) + /sys/devices/platform/odroidgo3_joypad/enable [rw] + * for adc calibration value setup(current adcs value -> cal value) + /sys/devices/platform/odroidgo3_joypad/adc_cal [rw] + ex) echo 0 > adc_cal + * for amux data debug + * Joypad driver is disabled when using this sysfs. + /sys/devices/platform/odroidgo3_joypad/amux_debug [rw] + ex) echo 0 > amux_debug --> select amux channel + ex) cat amux_debug --> get adc data of seleted channel + */ + + /* gpio pincontrol setup */ + pinctrl-names = "default"; + pinctrl-0 = <&btn_pins>; + + /* Analog mux define */ + io-channel-names = "joy_left", "joy_right"; + io-channels = <&saradc 1>, <&saradc 2>; + + /* adc mux channel count */ + amux-count = <4>; + + /* adc mux select(a,b) gpio */ + amux-a-gpios = <&gpio2 RK_PB3 GPIO_ACTIVE_LOW>; + amux-b-gpios = <&gpio2 RK_PB5 GPIO_ACTIVE_LOW>; + + /* adc mux enable gpio */ + amux-en-gpios = <&gpio1 RK_PB0 GPIO_ACTIVE_LOW>; + + /* adc calculate scale */ + button-adc-scale = <2>; + + /* adc deadzone range */ + button-adc-deadzone = <180>; + + /* + specifies fuzz value that is used to filter noise from + the event stream. + */ + button-adc-fuzz = <32>; + button-adc-flat = <32>; + + /* + Analog Stick data tuning value(precent) + p = positive direction, n = negative direction + report value = (real_adc_data * tuning_value) / 100 + */ + abs_x-p-tuning = <200>; + abs_x-n-tuning = <200>; + + abs_y-p-tuning = <200>; + abs_y-n-tuning = <200>; + + abs_rx-p-tuning = <200>; + abs_rx-n-tuning = <200>; + + abs_ry-p-tuning = <200>; + abs_ry-n-tuning = <200>; + + /* poll device interval (ms), adc read interval */ + poll-interval = <10>; + + /* required for XU10 */ + invert-absx; + invert-absy; + + /* gpio button auto repeat set value : default disable */ + /* + autorepeat; + */ + + /* + *** MagicX XU10 - layoout *** + |-------------------------------| + | sw14 sw17 sw16 sw15 | + |-----|-------------------|-----| + | | | | + |vol+ | | sw13| + |vol- | | | + | | LCD Display | | + | | | | + | | | | + | |-------------------| | + | sw9 sw10 | + | | + | sw1 sw7 | + | sw3 sw4 sw8 sw6 | + | sw2 sw5 | + | | + | sw11 sw12 | + | | + |-------|---------------|-------| + */ + + /* + joypad driver is poll-device driver. + poll-device is does not support wakeup-source. + */ + + sw1 { + gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-UP"; + linux,code = ; // 0x220 + }; + sw2 { + gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-DOWN"; + linux,code = ; // 0x221 + }; + sw3 { + gpios = <&gpio1 RK_PB6 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-LEFT"; + linux,code = ; // 0x222 + }; + sw4 { + gpios = <&gpio1 RK_PB7 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-RIGHT"; + linux,code = ; // 0x223 + }; + sw5 { + gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-A"; + linux,code = ; // 0x130 + }; + sw6 { + gpios = <&gpio2 RK_PA3 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-B"; + linux,code = ; // 0x131 + }; + sw7 { + gpios = <&gpio2 RK_PA1 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-Y"; + linux,code = ; // 0x133 + }; + sw8 { + gpios = <&gpio2 RK_PA0 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-X"; + linux,code = ; // 0x134 + }; + sw9 { + gpios = <&gpio2 RK_PB0 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-SELECT"; + linux,code = ; // 0x13a + }; + sw10 { + gpios = <&gpio2 RK_PA5 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-START"; + linux,code = ; // 0x13b + }; + sw11 { + gpios = <&gpio2 RK_PB1 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-THUMBL"; + linux,code = ; // 0x13d + }; + sw12 { + gpios = <&gpio2 RK_PB2 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-THUMBR"; + linux,code = ; // 0x13e + }; + sw13 { + gpios = <&gpio2 RK_PA4 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-G"; + linux,code = ; // 0x2c0 + }; + sw14 { + gpios = <&gpio2 RK_PA6 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-LEFT"; + linux,code = ; // 0x136 + }; + sw15 { + gpios = <&gpio2 RK_PA7 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-RIGHT"; + linux,code = ; // 0x137 + }; + sw16 { + gpios = <&gpio3 RK_PB2 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-RIGHT2"; + linux,code = ; // 0x139 + }; + sw17 { + gpios = <&gpio3 RK_PB4 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-LEFT2"; + linux,code = ; // 0x138 + }; + }; + + battery: battery { + compatible = "simple-battery"; + charge-full-design-microamp-hours = <3000000>; + charge-term-current-microamp = <200000>; + constant-charge-current-max-microamp = <1500000>; + constant-charge-voltage-max-microvolt = <4200000>; + factory-internal-resistance-micro-ohms = <100000>; + voltage-max-design-microvolt = <4100000>; + voltage-min-design-microvolt = <3300000>; + + ocv-capacity-celsius = <20>; + ocv-capacity-table-0 = + <4046950 100>, <4001920 95>, <3967900 90>, <3940000 85>, + <3910000 80>, <3870000 75>, <3830000 70>, <3790000 65>, + <3750000 60>, <3720000 55>, <3690000 50>, <3650000 45>, + <3610000 40>, <3570000 35>, <3540000 30>, <3500000 25>, + <3460000 20>, <3420000 15>, <3380000 10>, <3340000 5>, + <3300000 0>; + }; + + gpio-keys-vol { + compatible = "gpio-keys"; + autorepeat; + pinctrl-0 = <&btn_pins_vol>; + pinctrl-names = "default"; + + button-vol-down { + gpios = <&gpio0 RK_PC1 GPIO_ACTIVE_LOW>; + label = "VOLUMEDOWN"; + linux,code = ; + }; + + button-vol-up { + gpios = <&gpio0 RK_PB7 GPIO_ACTIVE_LOW>; + label = "VOLUMEUP"; + linux,code = ; + }; + }; + + leds: gpio-leds { + compatible = "gpio-leds"; + pinctrl-0 = <&led_pins>; + pinctrl-names = "default"; + + led-0 { + color = ; + default-state = "off"; + function = LED_FUNCTION_CHARGING; + gpios = <&gpio0 RK_PB3 GPIO_ACTIVE_HIGH>; + }; + + led-1 { + color = ; + default-state = "off"; + function = LED_FUNCTION_STATUS; + gpios = <&gpio0 RK_PB4 GPIO_ACTIVE_HIGH>; + }; + }; + + rk817-sound { + compatible = "simple-audio-card"; + pinctrl-names = "default"; + pinctrl-0 = <&hp_det>; + simple-audio-card,name = "rk817_int"; + simple-audio-card,format = "i2s"; + simple-audio-card,hp-det-gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_LOW>; + simple-audio-card,mclk-fs = <256>; + simple-audio-card,widgets = + "Microphone", "Mic Jack", + "Headphone", "Headphones", + "Speaker", "Speaker"; + simple-audio-card,routing = + "MICL", "Mic Jack", + "Headphones", "HPOL", + "Headphones", "HPOR", + "Speaker", "SPKO"; + + simple-audio-card,codec { + sound-dai = <&rk817>; + }; + + simple-audio-card,cpu { + sound-dai = <&i2s1_2ch>; + }; + }; + + vccsys: vccsys { + compatible = "regulator-fixed"; + regulator-name = "vcc3v8_sys"; + regulator-always-on; + regulator-min-microvolt = <3800000>; + regulator-max-microvolt = <3800000>; + }; + + vcc-phy-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_phy"; + regulator-always-on; + regulator-boot-on; + }; + + vcc18_lcd0: vcc18-lcd0 { + compatible = "regulator-fixed"; + regulator-name = "vcc18_lcd0_n"; + gpio = <&gpio0 RK_PB5 GPIO_ACTIVE_HIGH>; + enable-active-high; + pinctrl-0 = <&vcc18_lcd_n>; + pinctrl-names = "default"; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_host: vcc_host { + compatible = "regulator-fixed"; + regulator-name = "vcc_host"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-always-on; + regulator-boot-on; + vin-supply = <&usb_midu>; + }; +}; + +&dmc { + center-supply = <&vdd_logic>; +}; + +&cpu0 { + cpu-supply = <&vdd_arm>; +}; + +&cpu1 { + cpu-supply = <&vdd_arm>; +}; + +&cpu2 { + cpu-supply = <&vdd_arm>; +}; + +&cpu3 { + cpu-supply = <&vdd_arm>; +}; + +&cru { + assigned-clocks = <&cru PLL_NPLL>, + <&cru ACLK_BUS_PRE>, <&cru ACLK_PERI_PRE>, + <&cru HCLK_BUS_PRE>, <&cru HCLK_PERI_PRE>, + <&cru PCLK_BUS_PRE>, <&cru SCLK_GPU>; + + assigned-clock-rates = <1188000000>, + <200000000>, <200000000>, + <150000000>, <150000000>, + <100000000>, <200000000>; +}; + +&display_subsystem { + status = "okay"; +}; + +&dsi { + status = "okay"; + + ports { + mipi_out: port@1 { + reg = <1>; + + mipi_out_panel: endpoint { + remote-endpoint = <&mipi_in_panel>; + }; + }; + }; + + internal_display: panel@0 { + compatible = "magicx,xu10-panel", "sitronix,st7703"; + iovcc-supply = <&vcc18_lcd0>; + vcc-supply = <&vcc18_lcd0>; + reg = <0>; + backlight = <&backlight>; + reset-gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&lcd_rst>; + + port { + mipi_in_panel: endpoint { + remote-endpoint = <&mipi_out_panel>; + }; + }; + }; +}; + +&dsi_dphy { + status = "okay"; +}; + +&gpu { + mali-supply = <&vdd_logic>; + status = "okay"; +}; + +&i2c0 { + clock-frequency = <400000>; + i2c-scl-falling-time-ns = <16>; + i2c-scl-rising-time-ns = <280>; + status = "okay"; + + rk817: pmic@20 { + compatible = "rockchip,rk817"; + reg = <0x20>; + interrupt-parent = <&gpio0>; + interrupts = ; + clock-output-names = "rk808-clkout1", "xin32k"; + clock-names = "mclk"; + clocks = <&cru SCLK_I2S1_OUT>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int>, <&i2s1_2ch_mclk>; + rockchip,system-power-controller; + wakeup-source; + #clock-cells = <1>; + #sound-dai-cells = <0>; + + vcc1-supply = <&vccsys>; + vcc2-supply = <&vccsys>; + vcc3-supply = <&vccsys>; + vcc4-supply = <&vccsys>; + vcc5-supply = <&vccsys>; + vcc6-supply = <&vccsys>; + vcc7-supply = <&vcc_3v0>; + vcc8-supply = <&vccsys>; + vcc9-supply = <&usb_midu>; + + regulators { + vdd_logic: DCDC_REG1 { + regulator-name = "vdd_logic"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <1150000>; + regulator-ramp-delay = <6001>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vdd_arm: DCDC_REG2 { + regulator-name = "vdd_arm"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-name = "vcc_ddr"; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_3v0: DCDC_REG4 { + regulator-name = "vcc_3v0"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcc_1v0: LDO_REG1 { + regulator-name = "vcc_1v0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vcc1v8_soc: LDO_REG2 { + regulator-name = "vcc1v8_soc"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc1v0_soc: LDO_REG3 { + regulator-name = "vcc1v0_soc"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vcc3v0_pmu: LDO_REG4 { + regulator-name = "vcc3v0_pmu"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vccio_sd: LDO_REG5 { + regulator-name = "vccio_sd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_sd: LDO_REG6 { + regulator-name = "vcc_sd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3000000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcc2v8_dvp: LDO_REG7 { + regulator-name = "vcc2v8_dvp"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <2800000>; + }; + }; + + vcc3v0_dvp: LDO_REG8 { + regulator-name = "vcc3v0_dvp"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vdd1v5_dvp: LDO_REG9 { + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + regulator-name = "vdd1v5_dvp"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <1500000>; + }; + }; + + usb_midu: BOOST { + regulator-name = "usb_midu"; + regulator-min-microvolt = <4700000>; + regulator-max-microvolt = <5400000>; + regulator-always-on; + regulator-boot-on; + }; + + }; + + rk817_charger: charger { + monitored-battery = <&battery>; + rockchip,resistor-sense-micro-ohms = <10000>; + rockchip,sleep-enter-current-microamp = <300000>; + rockchip,sleep-filter-current-microamp = <100000>; + }; + + rk817_codec: codec { + rockchip,mic-in-differential; + }; + }; +}; + +/* I2S 1 Channel Used Header(P2):1(GPIO2.C3),2(.C2), 3(.C1), 4(.C5), 5(.C4) */ +&i2s1_2ch { + status = "okay"; + #sound-dai-cells = <0>; +}; + +&io_domains { + vccio1-supply = <&vcc1v8_soc>; + vccio2-supply = <&vccio_sd>; + vccio3-supply = <&vcc3v0_dvp>; + vccio4-supply = <&vcc_3v0>; + vccio5-supply = <&vcc_3v0>; + vccio6-supply = <&vcc_3v0>; + status = "okay"; +}; + +&isp { + status = "okay"; +}; + +&isp_mmu { + status = "okay"; +}; + +&pmu_io_domains { + pmuio1-supply = <&vcc3v0_pmu>; + pmuio2-supply = <&vcc3v0_pmu>; + status = "okay"; +}; + +&csi_dphy { + status = "okay"; +}; + +&pwm1 { + status = "okay"; +}; + +&saradc { + vref-supply = <&vcc1v8_soc>; + status = "okay"; +}; + +&sdmmc { + cap-sd-highspeed; + card-detect-delay = <200>; + cd-gpios = <&gpio0 RK_PA3 GPIO_ACTIVE_LOW>; /*[> ff370000 PD_SDCARD CD GPIO <]*/ + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + vmmc-supply = <&vcc_sd>; + vqmmc-supply = <&vccio_sd>; + status = "okay"; +}; + +&sdio { + cap-sd-highspeed; + card-detect-delay = <200>; + cd-gpios = <&gpio3 RK_PB6 GPIO_ACTIVE_LOW>; /*[> CD GPIO <]*/ + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + vmmc-supply = <&vcc_sd>; + vqmmc-supply = <&vccio_sd>; + status = "okay"; +}; + +&tsadc { + status = "okay"; +}; + +&u2phy { + status = "okay"; + + u2phy_host: host-port { + status = "okay"; + }; + + u2phy_otg: otg-port { + status = "okay"; + }; +}; + +/* FIQ Header(P2): 2(RXD:GPIO2.B4),3(TXD:.B6) */ +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&uart2m1_xfer>; + status = "okay"; +}; + +&usb20_otg { + status = "okay"; + dr_mode = "otg"; +}; + +&vopb { + status = "okay"; +}; + +&vopb_mmu { + status = "okay"; +}; + +&pinctrl { + btns { + btn_pins: btn-pins { + rockchip,pins = <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + btn_pins_vol: btn-pins-vol { + rockchip,pins = + <0 RK_PC1 RK_FUNC_GPIO &pcfg_pull_up>, + <0 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + headphone { + hp_det: hp-det { + rockchip,pins = <2 RK_PC6 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + gpio-lcd { + lcd_rst: lcd-rst { + rockchip,pins = <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + vcc18-lcd { + vcc18_lcd_n: vcc18-lcd-n { + rockchip,pins = <0 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + gpio-led { + led_pins: led-pins { + rockchip,pins = + <0 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>, + <0 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pmic { + dc_det: dc-det { + rockchip,pins = <0 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + pmic_int: pmic-int { + rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + soc_slppin_gpio: soc_slppin_gpio { + rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_output_low>; + }; + + soc_slppin_rst: soc_slppin_rst { + rockchip,pins = <0 RK_PA4 2 &pcfg_pull_none>; + }; + + soc_slppin_slp: soc_slppin_slp { + rockchip,pins = <0 RK_PA4 1 &pcfg_pull_none>; + }; + }; +}; diff --git a/config/archr-dts/rk3326-odroid-go.dtsi b/config/archr-dts/rk3326-odroid-go.dtsi new file mode 100644 index 0000000000..6195402b5b --- /dev/null +++ b/config/archr-dts/rk3326-odroid-go.dtsi @@ -0,0 +1,568 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2019 Hardkernel Co., Ltd + * Copyright (c) 2020 Theobroma Systems Design und Consulting GmbH + * Copyright (c) 2022 Maya Matuszczyk + */ + +/dts-v1/; +#include +#include +#include +#include +#include "rk3326.dtsi" + +/ { + aliases { + mmc0 = &sdmmc; + }; + + chosen { + stdout-path = "serial2:115200n8"; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + power-supply = <&vcc_bl>; + pwms = <&pwm1 0 25000 0>; + brightness-levels = < + 0 1 2 3 4 5 6 7 + 8 9 10 11 12 13 14 15 + 16 17 18 19 20 21 22 23 + 24 25 26 27 28 29 30 31 + 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 + 48 49 50 51 52 53 54 55 + 56 57 58 59 60 61 62 63 + 64 65 66 67 68 69 70 71 + 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 + 88 89 90 91 92 93 94 95 + 96 97 98 99 100 101 102 103 + 104 105 106 107 108 109 110 111 + 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 + 128 129 130 131 132 133 134 135 + 136 137 138 139 140 141 142 143 + 144 145 146 147 148 149 150 151 + 152 153 154 155 156 157 158 159 + 160 161 162 163 164 165 166 167 + 168 169 170 171 172 173 174 175 + 176 177 178 179 180 181 182 183 + 184 185 186 187 188 189 190 191 + 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 + 208 209 210 211 212 213 214 215 + 216 217 218 219 220 221 222 223 + 224 225 226 227 228 229 230 231 + 232 233 234 235 236 237 238 239 + 240 241 242 243 244 245 246 247 + 248 249 250 251 252 253 254 255>; + default-brightness-level = <128>; + }; + + /* led-1 is wired directly to output of always-on regulator */ + + gpio_led: gpio-leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&red_led_pin>; + + red_led: led-3 { + color = ; + gpios = <&gpio0 RK_PB5 GPIO_ACTIVE_HIGH>; + function = LED_FUNCTION_CHARGING; + }; + }; + + pwm_led: led-controller { + compatible = "pwm-leds"; + + blue_led: led-2 { + color = ; + function = LED_FUNCTION_STATUS; + linux,default-trigger = "heartbeat"; + max-brightness = <255>; + pwms = <&pwm3 0 25000 0>; + }; + }; + + rk817-sound { + compatible = "simple-audio-card"; + simple-audio-card,name = "rk817_int"; + simple-audio-card,format = "i2s"; + simple-audio-card,hp-det-gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>; + simple-audio-card,mclk-fs = <256>; + simple-audio-card,widgets = + "Microphone", "Mic Jack", + "Headphone", "Headphones", + "Speaker", "Speaker"; + simple-audio-card,routing = + "MICL", "Mic Jack", + "Headphones", "HPOL", + "Headphones", "HPOR", + "Speaker", "SPKO"; + + simple-audio-card,codec { + sound-dai = <&rk817>; + }; + + simple-audio-card,cpu { + sound-dai = <&i2s1_2ch>; + }; + }; + + vccsys: regulator-vccsys { + compatible = "regulator-fixed"; + regulator-name = "vcc3v8_sys"; + regulator-always-on; + regulator-min-microvolt = <3800000>; + regulator-max-microvolt = <3800000>; + }; + + vcc_host: regulator-vcc-host { + compatible = "regulator-fixed"; + regulator-name = "vcc_host"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + + gpio = <&gpio0 RK_PB7 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-always-on; + regulator-boot-on; + vin-supply = <&usb_midu>; + }; +}; + +&dmc { + center-supply = <&vdd_logic>; +}; + +&cpu0 { + cpu-supply = <&vdd_arm>; +}; + +&cpu1 { + cpu-supply = <&vdd_arm>; +}; + +&cpu2 { + cpu-supply = <&vdd_arm>; +}; + +&cpu3 { + cpu-supply = <&vdd_arm>; +}; + +&cru { + assigned-clocks = <&cru PLL_NPLL>, + <&cru ACLK_BUS_PRE>, <&cru ACLK_PERI_PRE>, + <&cru HCLK_BUS_PRE>, <&cru HCLK_PERI_PRE>, + <&cru PCLK_BUS_PRE>, <&cru SCLK_GPU>; + + assigned-clock-rates = <1188000000>, + <200000000>, <200000000>, + <150000000>, <150000000>, + <100000000>, <200000000>; +}; + +&display_subsystem { + status = "okay"; +}; + +&dsi { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + ports { + mipi_out: port@1 { + reg = <1>; + + mipi_out_panel: endpoint { + remote-endpoint = <&mipi_in_panel>; + }; + }; + }; + + internal_display: panel@0 { + reg = <0>; + backlight = <&backlight>; + reset-gpios = <&gpio3 RK_PC0 GPIO_ACTIVE_LOW>; + + port { + mipi_in_panel: endpoint { + remote-endpoint = <&mipi_out_panel>; + }; + }; + }; +}; + +&dsi_dphy { + status = "okay"; +}; + +&gpu { + mali-supply = <&vdd_logic>; + status = "okay"; +}; + +&i2c0 { + clock-frequency = <400000>; + i2c-scl-falling-time-ns = <16>; + i2c-scl-rising-time-ns = <280>; + status = "okay"; + + rk817: pmic@20 { + compatible = "rockchip,rk817"; + reg = <0x20>; + interrupt-parent = <&gpio0>; + interrupts = ; + clock-output-names = "rk808-clkout1", "xin32k"; + clock-names = "mclk"; + clocks = <&cru SCLK_I2S1_OUT>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int>, <&i2s1_2ch_mclk>; + rockchip,system-power-controller; + wakeup-source; + #clock-cells = <1>; + #sound-dai-cells = <0>; + + vcc1-supply = <&vccsys>; + vcc2-supply = <&vccsys>; + vcc3-supply = <&vccsys>; + vcc4-supply = <&vccsys>; + vcc5-supply = <&vccsys>; + vcc6-supply = <&vccsys>; + vcc7-supply = <&vccsys>; + vcc8-supply = <&vccsys>; + + regulators { + vdd_logic: DCDC_REG1 { + regulator-name = "vdd_logic"; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1150000>; + regulator-ramp-delay = <6001>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vdd_arm: DCDC_REG2 { + regulator-name = "vdd_arm"; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-name = "vcc_ddr"; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_3v3: DCDC_REG4 { + regulator-name = "vcc_3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_1v8: LDO_REG2 { + regulator-name = "vcc_1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd_1v0: LDO_REG3 { + regulator-name = "vdd_1v0"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vcc3v3_pmu: LDO_REG4 { + regulator-name = "vcc3v3_pmu"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vccio_sd: LDO_REG5 { + regulator-name = "vccio_sd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_sd: LDO_REG6 { + regulator-name = "vcc_sd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_bl: LDO_REG7 { + regulator-name = "vcc_bl"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_lcd: LDO_REG8 { + regulator-name = "vcc_lcd"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <2800000>; + }; + }; + + LDO_REG9 { + /* unused */ + }; + + usb_midu: BOOST { + regulator-name = "usb_midu"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5400000>; + regulator-always-on; + regulator-boot-on; + }; + }; + + rk817_charger: charger { + rockchip,resistor-sense-micro-ohms = <10000>; + rockchip,sleep-enter-current-microamp = <300000>; + rockchip,sleep-filter-current-microamp = <100000>; + }; + + rk817_codec: codec { + rockchip,mic-in-differential; + }; + }; +}; + +/* EXT Header(P2): 7(SCL:GPIO0.C2), 8(SDA:GPIO0.C3) */ +&i2c1 { + clock-frequency = <400000>; + status = "okay"; +}; + +/* I2S 1 Channel Used */ +&i2s1_2ch { + status = "okay"; +}; + +&io_domains { + vccio1-supply = <&vcc_3v3>; + vccio2-supply = <&vccio_sd>; + vccio3-supply = <&vcc_3v3>; + vccio4-supply = <&vcc_3v3>; + vccio5-supply = <&vcc_3v3>; + vccio6-supply = <&vcc_3v3>; + status = "okay"; +}; + +&pmu_io_domains { + pmuio1-supply = <&vcc3v3_pmu>; + pmuio2-supply = <&vcc3v3_pmu>; + status = "okay"; +}; + +&pwm1 { + status = "okay"; +}; + +&pwm3 { + status = "okay"; +}; + +&saradc { + vref-supply = <&vcc_1v8>; + status = "okay"; +}; + +&sdmmc { + cap-sd-highspeed; + card-detect-delay = <200>; + cd-gpios = <&gpio0 RK_PA3 GPIO_ACTIVE_LOW>; /*[> CD GPIO <]*/ + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + vmmc-supply = <&vcc_sd>; + vqmmc-supply = <&vccio_sd>; + status = "okay"; +}; + +&sfc { + pinctrl-0 = <&sfc_clk &sfc_cs0 &sfc_bus2>; + pinctrl-names = "default"; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <108000000>; + spi-rx-bus-width = <2>; + spi-tx-bus-width = <1>; + }; +}; + +&tsadc { + status = "okay"; +}; + +&u2phy { + status = "okay"; + + u2phy_host: host-port { + status = "okay"; + }; + + u2phy_otg: otg-port { + status = "okay"; + }; +}; + +&usb20_otg { + status = "okay"; +}; + +/* EXT Header(P2): 2(RXD:GPIO1.C0),3(TXD:.C1),4(CTS:.C2),5(RTS:.C3) */ +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_xfer &uart1_cts>; + status = "okay"; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&uart2m1_xfer>; + status = "okay"; +}; + +&vopb { + status = "okay"; +}; + +&vopb_mmu { + status = "okay"; +}; + +&pinctrl { + btns { + btn_pins: btn-pins { + rockchip,pins = <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + headphone { + hp_det: hp-det { + rockchip,pins = <2 RK_PC6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + + leds { + red_led_pin: red-led-pin { + rockchip,pins = <0 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pmic { + dc_det: dc-det { + rockchip,pins = <0 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + pmic_int: pmic-int { + rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + soc_slppin_gpio: soc_slppin_gpio { + rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_output_low>; + }; + + soc_slppin_rst: soc_slppin_rst { + rockchip,pins = <0 RK_PA4 2 &pcfg_pull_none>; + }; + + soc_slppin_slp: soc_slppin_slp { + rockchip,pins = <0 RK_PA4 1 &pcfg_pull_none>; + }; + }; +}; diff --git a/config/archr-dts/rk3326-odroid-go2-v11.dts b/config/archr-dts/rk3326-odroid-go2-v11.dts new file mode 100644 index 0000000000..489e0e2d0f --- /dev/null +++ b/config/archr-dts/rk3326-odroid-go2-v11.dts @@ -0,0 +1,310 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2019 Hardkernel Co., Ltd + * Copyright (c) 2020 Theobroma Systems Design und Consulting GmbH + * Copyright (c) 2022 Maya Matuszczyk + */ + +/dts-v1/; +#include "rk3326-odroid-go.dtsi" + +/ { + model = "ODROID-GO Advance Black Edition"; + compatible = "hardkernel,rk3326-odroid-go2-v11", "rockchip,rk3326"; + + aliases { + mmc1 = &sdio; + }; + + gpio_keys: volume-keys { + compatible = "gpio-keys"; + autorepeat; + pinctrl-0 = <&btn_pins_vol>; + pinctrl-names = "default"; + + volume-up-button { + label = "VOLUMEUP"; + linux,code = ; + gpios = <&gpio2 RK_PA3 GPIO_ACTIVE_LOW>; + + }; + volume-down-button { + label = "VOLUMEDOWN"; + linux,code = ; + gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; + + }; + }; + + joypad: odroidgo2-joypad { + compatible = "odroidgo2-v11-joypad"; + + /* + - odroidgo2-joypad sysfs list - + * for poll device interval(ms) + /sys/devices/platform/odroidgo2_joypad/poll_interval [rw] + * for button-adc-fuzz + /sys/devices/platform/odroidgo2_joypad/adc_fuzz [r] + * for button-adc-flat + /sys/devices/platform/odroidgo2_joypad/adc_flat [r] + + * for report control(1:enable, 0:disable) + /sys/devices/platform/odroidgo2_joypad/enable [rw] + * for adc calibration value setup(1:current adcs value -> cal value) + /sys/devices/platform/odroidgo2_joypad/adc_cal [rw] + */ + + /* gpio pincontrol setup */ + pinctrl-names = "default"; + pinctrl-0 = <&btn_pins>; + + /* JOY_X, JOY_Y Channel define */ + io-channel-names = "joy_x", "joy_y"; + io-channels = <&saradc 1>, <&saradc 2>; + + /* adc channel count */ + button-adc-count = <2>; + + /* adc calculate scale */ + button-adc-scale = <2>; + + /* adc deadzone range */ + button-adc-deadzone = <20>; + + /* + joy-stick voltage range + /sys/devices/platform/ff288000.saradc/iio:device0 + adc-x : in_voltage1_raw + adc-y : in_voltage2_raw + + range calculate. + (adc raw max value - adc raw min value) * scale * 1.7515 + */ + button-adc-x-range = <1800>; + button-adc-y-range = <1800>; + + /* + specifies fuzz value that is used to filter noise from + the event stream. + */ + button-adc-fuzz = <32>; + button-adc-flat = <32>; + + /* poll device interval (ms), adc read interval */ + poll-interval = <10>; + + /* gpio button auto repeat set value : default disable */ + /* + autorepeat; + */ + + /* + *** ODROIDGO2-Advance Switch layoout *** + |------------------------------------------------| + | sw15 sw16 | + | sw20 sw21 | + |------------------------------------------------| + | sw1 |-------------------| sw8 | + | sw3 sw4 | | sw7 sw5 | + | sw2 | LCD Display | sw6 | + | | | | + | |-------------------| | + | sw9 sw10 vol- vol+ sw13 sw14 | + |------------------------------------------------| + */ + /* + joypad driver is poll-device driver. + poll-device is does not support wakeup-source. + */ + sw1 { + gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-UP"; + linux,code = ; // 0x220 + }; + sw2 { + gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-DOWN"; + linux,code = ; // 0x221 + }; + sw3 { + gpios = <&gpio1 RK_PB6 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-LEFT"; + linux,code = ; // 0x222 + }; + sw4 { + gpios = <&gpio1 RK_PB7 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-RIGHT"; + linux,code = ; // 0x223 + }; + sw5 { + gpios = <&gpio1 RK_PA2 GPIO_ACTIVE_LOW>; + label = "GPIO KEY BTN-A"; + linux,code = ; // 0x131 + }; + sw6 { + gpios = <&gpio1 RK_PA5 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-B"; + linux,code = ; // 0x130 + }; + sw7 { + gpios = <&gpio1 RK_PA6 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-Y"; + linux,code = ; // 0x134 + }; + sw8 { + gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-X"; + linux,code = ; // 0x133 + }; + sw9 { + gpios = <&gpio2 RK_PA0 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-SELECT"; + linux,code = ; // 0x2c0 + }; + sw10 { + gpios = <&gpio2 RK_PA1 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-THUMBL"; + linux,code = ; // 0x2c1 + }; + sw13 { + gpios = <&gpio2 RK_PA4 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-THUMBR"; + linux,code = ; // 0x2c4 + }; + sw14 { + gpios = <&gpio2 RK_PA5 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-START"; + linux,code = ; // 0x13c + }; + sw15 { + gpios = <&gpio2 RK_PA6 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-LEFT"; + linux,code = ; // 0x02 + }; + sw16 { + gpios = <&gpio2 RK_PA7 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-RIGHT"; + linux,code = ; // 0x05 + }; + sw20 { + gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-LEFT2"; + linux,code = ; + }; + sw21 { + gpios = <&gpio3 RK_PB2 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-RIGHT2"; + linux,code = ; + }; + }; + + battery: battery { + compatible = "simple-battery"; + charge-full-design-microamp-hours = <3000000>; + charge-term-current-microamp = <300000>; + constant-charge-current-max-microamp = <2000000>; + constant-charge-voltage-max-microvolt = <4200000>; + factory-internal-resistance-micro-ohms = <180000>; + voltage-max-design-microvolt = <4100000>; + voltage-min-design-microvolt = <3500000>; + + ocv-capacity-celsius = <20>; + ocv-capacity-table-0 = <4046950 100>, <4001920 95>, <3967900 90>, <3919950 85>, + <3888450 80>, <3861850 75>, <3831540 70>, <3799130 65>, + <3768190 60>, <3745650 55>, <3726610 50>, <3711630 45>, + <3696720 40>, <3685660 35>, <3674950 30>, <3663050 25>, + <3649470 20>, <3635260 15>, <3616920 10>, <3592440 5>, + <3574170 0>; + }; + + wifi_pwrseq: wifi-pwrseq { + compatible = "mmc-pwrseq-simple"; + pinctrl-names = "default"; + pinctrl-0 = <&wifi_pwrseq_pins>; + reset-gpios = <&gpio3 RK_PB1 GPIO_ACTIVE_LOW>; + post-power-on-delay-ms = <300>; + power-off-delay-us = <200000>; + }; +}; + +&internal_display { + compatible = "elida,kd35t133"; + iovcc-supply = <&vcc_lcd>; + vdd-supply = <&vcc_lcd>; + rotation = <270>; +}; + +&rk817 { + regulators { + vcc_wifi: LDO_REG9 { + regulator-name = "vcc_wifi"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + }; +}; + +&rk817_charger { + monitored-battery = <&battery>; +}; + +&sdio { + #address-cells = <1>; + #size-cells = <0>; + bus-width = <4>; + cap-sd-highspeed; + cap-sdio-irq; + disable-wp; + keep-power-in-suspend; + non-removable; + vmmc-supply = <&vcc_wifi>; + mmc-pwrseq = <&wifi_pwrseq>; + status = "okay"; + + esp8089: wifi@1 { + compatible = "esp,esp8089"; + reg = <1>; + esp,crystal-26M-en = <1>; + }; +}; + +&pinctrl { + btns { + btn_pins: btn-pins { + rockchip,pins = <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + btn_pins_vol: btn-pins-vol { + rockchip,pins = <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + wifi { + wifi_pwrseq_pins: wifi-pwrseq-pins { + rockchip,pins = <3 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB6 RK_FUNC_GPIO &pcfg_output_high>; + }; + }; +}; diff --git a/config/archr-dts/rk3326-odroid-go2.dts b/config/archr-dts/rk3326-odroid-go2.dts new file mode 100644 index 0000000000..f142737a01 --- /dev/null +++ b/config/archr-dts/rk3326-odroid-go2.dts @@ -0,0 +1,235 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2019 Hardkernel Co., Ltd + * Copyright (c) 2020 Theobroma Systems Design und Consulting GmbH + * Copyright (c) 2022 Maya Matuszczyk + */ + +/dts-v1/; +#include "rk3326-odroid-go.dtsi" + +/ { + model = "ODROID-GO Advance"; + compatible = "hardkernel,rk3326-odroid-go2", "rockchip,rk3326"; + + gpio_keys: volume-keys { + compatible = "gpio-keys-polled"; + poll-interval = <5>; + autorepeat; + + volume-up-button { + label = "VOLUME-UP"; + linux,code = ; + gpios = <&gpio2 RK_PA3 GPIO_ACTIVE_LOW>; + + }; + volume-down-button { + label = "VOLUME-DOWN"; + linux,code = ; + gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; + + }; + }; + + joypad: odroidgo2-joypad { + compatible = "odroidgo2-joypad"; + + /* + - odroidgo2-joypad sysfs list - + * for poll device interval(ms) + /sys/devices/platform/odroidgo2_joypad/poll_interval [rw] + * for button-adc-fuzz + /sys/devices/platform/odroidgo2_joypad/adc_fuzz [r] + * for button-adc-flat + /sys/devices/platform/odroidgo2_joypad/adc_flat [r] + + * for report control(1:enable, 0:disable) + /sys/devices/platform/odroidgo2_joypad/enable [rw] + * for adc calibration value setup(1:current adcs value -> cal value) + /sys/devices/platform/odroidgo2_joypad/adc_cal [rw] + */ + + /* gpio pincontrol setup */ + pinctrl-names = "default"; + pinctrl-0 = <&btn_pins>; + + /* JOY_X, JOY_Y Channel define */ + io-channel-names = "joy_x", "joy_y"; + io-channels = <&saradc 1>, <&saradc 2>; + + /* adc channel count */ + button-adc-count = <2>; + + /* adc calculate scale */ + button-adc-scale = <2>; + + /* adc deadzone range */ + button-adc-deadzone = <20>; + + /* + joy-stick voltage range + /sys/devices/platform/ff288000.saradc/iio:device0 + adc-x : in_voltage1_raw + adc-y : in_voltage2_raw + + range calculate. + (adc raw max value - adc raw min value) * scale * 1.7515 + */ + button-adc-x-range = <1800>; + button-adc-y-range = <1800>; + + /* + specifies fuzz value that is used to filter noise from + the event stream. + */ + button-adc-fuzz = <32>; + button-adc-flat = <32>; + + /* poll device interval (ms), adc read interval */ + poll-interval = <10>; + + /* gpio button auto repeat set value : default disable */ + /* + autorepeat; + */ + + /* + *** ODROIDGO2-Advance Switch layoout *** + |------------------------------------------------| + | sw15 sw16 | + |------------------------------------------------| + | sw1 |-------------------| sw8 | + | sw3 sw4 | | sw7 sw5 | + | sw2 | LCD Display | sw6 | + | | | | + | |-------------------| | + | sw9 sw10 vol- vol+ sw13 sw14 | + |------------------------------------------------| + */ + /* + joypad driver is poll-device driver. + poll-device is does not support wakeup-source. + */ + sw1 { + gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-UP"; + linux,code = ; // 0x220 + }; + sw2 { + gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-DOWN"; + linux,code = ; // 0x221 + }; + sw3 { + gpios = <&gpio1 RK_PB6 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-LEFT"; + linux,code = ; // 0x222 + }; + sw4 { + gpios = <&gpio1 RK_PB7 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-RIGHT"; + linux,code = ; // 0x223 + }; + sw5 { + gpios = <&gpio1 RK_PA2 GPIO_ACTIVE_LOW>; + label = "GPIO KEY BTN-A"; + linux,code = ; // 0x131 + }; + sw6 { + gpios = <&gpio1 RK_PA5 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-B"; + linux,code = ; // 0x130 + }; + sw7 { + gpios = <&gpio1 RK_PA6 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-Y"; + linux,code = ; // 0x134 + }; + sw8 { + gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-X"; + linux,code = ; // 0x133 + }; + sw9 { + gpios = <&gpio2 RK_PA0 GPIO_ACTIVE_LOW>; + label = "GPIO F1"; + linux,code = ; // 0x2c0 + }; + sw10 { + gpios = <&gpio2 RK_PA1 GPIO_ACTIVE_LOW>; + label = "GPIO F2"; + linux,code = ; // 0x2c1 + }; + sw13 { + gpios = <&gpio2 RK_PA4 GPIO_ACTIVE_LOW>; + label = "GPIO F5"; + linux,code = ; // 0x2c4 + }; + sw14 { + gpios = <&gpio2 RK_PA5 GPIO_ACTIVE_LOW>; + label = "GPIO F6"; + linux,code = ; // 0x13c + }; + sw15 { + gpios = <&gpio2 RK_PA6 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-LEFT"; + linux,code = ; // 0x02 + }; + sw16 { + gpios = <&gpio2 RK_PA7 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-RIGHT"; + linux,code = ; // 0x05 + }; + }; + + battery: battery { + compatible = "simple-battery"; + charge-full-design-microamp-hours = <3000000>; + charge-term-current-microamp = <300000>; + constant-charge-current-max-microamp = <2000000>; + constant-charge-voltage-max-microvolt = <4200000>; + factory-internal-resistance-micro-ohms = <180000>; + voltage-max-design-microvolt = <4100000>; + voltage-min-design-microvolt = <3500000>; + + ocv-capacity-celsius = <20>; + ocv-capacity-table-0 = <4046950 100>, <4001920 95>, <3967900 90>, <3919950 85>, + <3888450 80>, <3861850 75>, <3831540 70>, <3799130 65>, + <3768190 60>, <3745650 55>, <3726610 50>, <3711630 45>, + <3696720 40>, <3685660 35>, <3674950 30>, <3663050 25>, + <3649470 20>, <3635260 15>, <3616920 10>, <3592440 5>, + <3574170 0>; + }; +}; + +&internal_display { + compatible = "elida,kd35t133"; + iovcc-supply = <&vcc_lcd>; + vdd-supply = <&vcc_lcd>; + rotation = <270>; +}; + +&rk817_charger { + monitored-battery = <&battery>; +}; + +&pinctrl { + btns { + btn_pins: btn-pins { + rockchip,pins = <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +}; diff --git a/config/archr-dts/rk3326-odroid-go3.dts b/config/archr-dts/rk3326-odroid-go3.dts new file mode 100644 index 0000000000..c3099f9cfe --- /dev/null +++ b/config/archr-dts/rk3326-odroid-go3.dts @@ -0,0 +1,289 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2019 Hardkernel Co., Ltd + * Copyright (c) 2020 Theobroma Systems Design und Consulting GmbH + * Copyright (c) 2022 Maya Matuszczyk + */ + +/dts-v1/; +#include "rk3326-odroid-go.dtsi" + +/ { + model = "ODROID-GO Super"; + compatible = "hardkernel,rk3326-odroid-go3", "rockchip,rk3326"; + + joypad: odroidgo3-joypad { + compatible = "odroidgo3-joypad"; + + joypad-name = "odroidgo3_joypad"; + joypad-product = <0x0001>; + joypad-revision = <0x0101>; + + status = "okay"; + /* + - odroidgo3-joypad sysfs list - + * for poll device interval(ms) + /sys/devices/platform/odroidgo3_joypad/poll_interval [rw] + ex) echo 20 > poll_interval + * for button-adc-fuzz + /sys/devices/platform/odroidgo3_joypad/adc_fuzz [r] + * for button-adc-flat + /sys/devices/platform/odroidgo3_joypad/adc_flat [r] + + * for report control(1:enable, 0:disable) + /sys/devices/platform/odroidgo3_joypad/enable [rw] + * for adc calibration value setup(current adcs value -> cal value) + /sys/devices/platform/odroidgo3_joypad/adc_cal [rw] + ex) echo 0 > adc_cal + * for amux data debug + * Joypad driver is disabled when using this sysfs. + /sys/devices/platform/odroidgo3_joypad/amux_debug [rw] + ex) echo 0 > amux_debug --> select amux channel + ex) cat amux_debug --> get adc data of seleted channel + */ + + /* gpio pincontrol setup */ + pinctrl-names = "default"; + pinctrl-0 = <&btn_pins>; + + /* Analog mux define */ + io-channel-names = "amux_adc"; + io-channels = <&saradc 1>; + + /* adc mux channel count */ + amux-count = <4>; + /* adc mux select(a,b) gpio */ + amux-a-gpios = <&gpio3 RK_PB3 GPIO_ACTIVE_LOW>; + amux-b-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>; + /* adc mux enable gpio */ + amux-en-gpios = <&gpio3 RK_PB5 GPIO_ACTIVE_LOW>; + + /* adc calculate scale */ + button-adc-scale = <2>; + + /* adc deadzone range */ + button-adc-deadzone = <64>; + + /* + specifies fuzz value that is used to filter noise from + the event stream. + */ + button-adc-fuzz = <32>; + button-adc-flat = <32>; + + /* + Analog Stick data tuning value(precent) + p = positive direction, n = negative direction + report value = (real_adc_data * tuning_value) / 100 + */ + abs_x-p-tuning = <180>; + abs_x-n-tuning = <180>; + + abs_y-p-tuning = <180>; + abs_y-n-tuning = <170>; + + abs_rx-p-tuning = <180>; + abs_rx-n-tuning = <180>; + + abs_ry-p-tuning = <180>; + abs_ry-n-tuning = <170>; + + /* poll device interval (ms), adc read interval */ + poll-interval = <10>; + + /* gpio button auto repeat set value : default disable */ + /* + autorepeat; + */ + + /* + *** ODROIDGO3-Advance Switch layoout *** + |------------------------------------------------| + | sw15 sw21 sw10 sw9 sw20 sw16 | + |------------------------------------------------| + | sw19 sw22 | + | |-------------------| | + | sw1 | | sw8 | + | sw3 sw4 | | sw7 sw5 | + | sw2 | LCD Display | sw6 | + | | | | + | | | | + | |-------------------| | + | sw11 sw12 | sd-slot | sw13 sw14 | + |-------------------| |------------------| + */ + /* + joypad driver is poll-device driver. + poll-device is does not support wakeup-source. + */ + sw1 { + gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-UP"; + linux,code = ; // 0x220 + }; + sw2 { + gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-DOWN"; + linux,code = ; // 0x221 + }; + sw3 { + gpios = <&gpio1 RK_PB6 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-LEFT"; + linux,code = ; // 0x222 + }; + sw4 { + gpios = <&gpio1 RK_PB7 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-RIGHT"; + linux,code = ; // 0x223 + }; + sw5 { + gpios = <&gpio1 RK_PA2 GPIO_ACTIVE_LOW>; + label = "GPIO KEY BTN-A"; + linux,code = ; // 0x131 + }; + sw6 { + gpios = <&gpio1 RK_PA5 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-B"; + linux,code = ; // 0x130 + }; + sw7 { + gpios = <&gpio1 RK_PA6 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-Y"; + linux,code = ; // 0x134 + }; + sw8 { + gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-X"; + linux,code = ; // 0x133 + }; + sw11 { + gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; + label = "GPIO F3"; + linux,code = ; // 0x2c2 + }; + sw12 { + gpios = <&gpio2 RK_PA3 GPIO_ACTIVE_LOW>; + label = "GPIO F4"; + linux,code = ; // 0x2c3 + }; + sw13 { + gpios = <&gpio2 RK_PA4 GPIO_ACTIVE_LOW>; + label = "GPIO F5"; + linux,code = ; // 0x2c4 + }; + sw14 { + gpios = <&gpio2 RK_PA5 GPIO_ACTIVE_LOW>; + label = "GPIO F6"; + linux,code = ; // 0x13c + }; + sw15 { + gpios = <&gpio2 RK_PA6 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-LEFT"; + linux,code = ; // 0x02 + }; + sw16 { + gpios = <&gpio2 RK_PA7 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-RIGHT"; + linux,code = ; // 0x05 + }; + sw19 { + gpios = <&gpio3 RK_PB1 GPIO_ACTIVE_LOW>; + label = "GPIO F1"; + linux,code = ; + }; + sw20 { + gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-RIGHT2"; + linux,code = ; + }; + sw21 { + gpios = <&gpio3 RK_PB2 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-LEFT2"; + linux,code = ; + }; + sw22 { + gpios = <&gpio3 RK_PB4 GPIO_ACTIVE_LOW>; + label = "GPIO F2"; + linux,code = ; + }; + }; + + battery: battery { + compatible = "simple-battery"; + charge-full-design-microamp-hours = <4000000>; + charge-term-current-microamp = <300000>; + constant-charge-current-max-microamp = <2000000>; + constant-charge-voltage-max-microvolt = <4200000>; + factory-internal-resistance-micro-ohms = <180000>; + voltage-max-design-microvolt = <4100000>; + voltage-min-design-microvolt = <3500000>; + + ocv-capacity-celsius = <20>; + ocv-capacity-table-0 = <4046950 100>, <4001920 95>, <3967900 90>, <3919950 85>, + <3888450 80>, <3861850 75>, <3831540 70>, <3799130 65>, + <3768190 60>, <3745650 55>, <3726610 50>, <3711630 45>, + <3696720 40>, <3685660 35>, <3674950 30>, <3663050 25>, + <3649470 20>, <3635260 15>, <3616920 10>, <3592440 5>, + <3574170 0>; + }; + + gpio-keys-vol { + compatible = "gpio-keys"; + autorepeat; + pinctrl-0 = <&btn_pins_vol>; + pinctrl-names = "default"; + + button-vol-down { + gpios = <&gpio2 RK_PA1 GPIO_ACTIVE_LOW>; + label = "VOLUMEDOWN"; + linux,code = ; + }; + + button-volume-up { + gpios = <&gpio2 RK_PA0 GPIO_ACTIVE_LOW>; + label = "VOLUMEUP"; + linux,code = ; + }; + }; +}; + +&internal_display { + compatible = "elida,kd50t048a", "sitronix,st7701"; + reset-gpios = <&gpio3 RK_PC0 GPIO_ACTIVE_HIGH>; + IOVCC-supply = <&vcc_lcd>; + VCC-supply = <&vcc_lcd>; + rotation = <270>; +}; + +&rk817_charger { + monitored-battery = <&battery>; +}; + +&pinctrl { + btns { + btn_pins: btn-pins { + rockchip,pins = <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + btn_pins_vol: btn-pins-vol { + rockchip,pins = <2 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +}; diff --git a/config/archr-dts/rk3326-powkiddy-rgb10.dts b/config/archr-dts/rk3326-powkiddy-rgb10.dts new file mode 100644 index 0000000000..de0f069fdd --- /dev/null +++ b/config/archr-dts/rk3326-powkiddy-rgb10.dts @@ -0,0 +1,282 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2019 Hardkernel Co., Ltd + * Copyright (c) 2020 Theobroma Systems Design und Consulting GmbH + * Copyright (c) 2022 Maya Matuszczyk + */ + +/dts-v1/; +#include "rk3326-odroid-go.dtsi" + +/ { + model = "Powkiddy RGB10"; + compatible = "powkiddy,rk3326-rgb10", "rockchip,rk3326"; + + aliases { + mmc1 = &sdio; + }; + + joypad: odroidgo2-joypad { + compatible = "odroidgo2-v11-joypad"; + + /* + - odroidgo2-joypad sysfs list - + * for poll device interval(ms) + /sys/devices/platform/odroidgo2_joypad/poll_interval [rw] + * for button-adc-fuzz + /sys/devices/platform/odroidgo2_joypad/adc_fuzz [r] + * for button-adc-flat + /sys/devices/platform/odroidgo2_joypad/adc_flat [r] + + * for report control(1:enable, 0:disable) + /sys/devices/platform/odroidgo2_joypad/enable [rw] + * for adc calibration value setup(1:current adcs value -> cal value) + /sys/devices/platform/odroidgo2_joypad/adc_cal [rw] + */ + + /* gpio pincontrol setup */ + pinctrl-names = "default"; + pinctrl-0 = <&btn_pins>; + + /* JOY_X, JOY_Y Channel define */ + io-channel-names = "joy_x", "joy_y"; + io-channels = <&saradc 1>, <&saradc 2>; + + /* adc channel count */ + button-adc-count = <2>; + + /* adc calculate scale */ + button-adc-scale = <2>; + + /* adc deadzone range */ + button-adc-deadzone = <20>; + + /* + joy-stick voltage range + /sys/devices/platform/ff288000.saradc/iio:device0 + adc-x : in_voltage1_raw + adc-y : in_voltage2_raw + + range calculate. + (adc raw max value - adc raw min value) * scale * 1.7515 + */ + button-adc-x-range = <1800>; + button-adc-y-range = <1800>; + + /* + specifies fuzz value that is used to filter noise from + the event stream. + */ + button-adc-fuzz = <32>; + button-adc-flat = <32>; + + /* poll device interval (ms), adc read interval */ + poll-interval = <10>; + + /* gpio button auto repeat set value : default disable */ + /* + autorepeat; + */ + + /* + *** RGB10 Switch layoout *** + |------------------------------------------------| + | sw15 sw16 | + | sw20 sw21 | + |------------------------------------------------| + | sw1 sw10 |-------------------| sw13 sw8 | + | sw3 sw4 | | sw7 sw5 | + | sw2 | LCD Display | sw6 | + | | | | + | |-------------------| | + |------------------------------------------------| + */ + /* + joypad driver is poll-device driver. + poll-device is does not support wakeup-source. + */ + sw1 { + gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-UP"; + linux,code = ; // 0x220 + }; + sw2 { + gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-DOWN"; + linux,code = ; // 0x221 + }; + sw3 { + gpios = <&gpio1 RK_PB6 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-LEFT"; + linux,code = ; // 0x222 + }; + sw4 { + gpios = <&gpio1 RK_PB7 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-RIGHT"; + linux,code = ; // 0x223 + }; + sw5 { + gpios = <&gpio1 RK_PA2 GPIO_ACTIVE_LOW>; + label = "GPIO KEY BTN-A"; + linux,code = ; // 0x131 + }; + sw6 { + gpios = <&gpio1 RK_PA5 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-B"; + linux,code = ; // 0x130 + }; + sw7 { + gpios = <&gpio1 RK_PA6 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-Y"; + linux,code = ; // 0x134 + }; + sw8 { + gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-X"; + linux,code = ; // 0x133 + }; + sw9 { + gpios = <&gpio2 RK_PA0 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-SELECT"; + linux,code = ; // 0x2c0 + }; + sw10 { + gpios = <&gpio2 RK_PA1 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-THUMBL"; + linux,code = ; // 0x2c1 + }; + sw13 { + gpios = <&gpio2 RK_PA4 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-THUMBR"; + linux,code = ; // 0x2c4 + }; + sw14 { + gpios = <&gpio2 RK_PA5 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-START"; + linux,code = ; // 0x13c + }; + sw15 { + gpios = <&gpio2 RK_PA6 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-LEFT"; + linux,code = ; // 0x02 + }; + sw16 { + gpios = <&gpio2 RK_PA7 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-RIGHT"; + linux,code = ; // 0x05 + }; + sw20 { + gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-LEFT2"; + linux,code = ; + }; + sw21 { + gpios = <&gpio2 RK_PA3 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-RIGHT2"; + linux,code = ; + }; + }; + + battery: battery { + compatible = "simple-battery"; + charge-full-design-microamp-hours = <2800000>; + charge-term-current-microamp = <280000>; + constant-charge-current-max-microamp = <2000000>; + constant-charge-voltage-max-microvolt = <4200000>; + factory-internal-resistance-micro-ohms = <180000>; + voltage-max-design-microvolt = <4100000>; + voltage-min-design-microvolt = <3500000>; + + ocv-capacity-celsius = <20>; + ocv-capacity-table-0 = <4046950 100>, <4001920 95>, <3967900 90>, <3919950 85>, + <3888450 80>, <3861850 75>, <3831540 70>, <3799130 65>, + <3768190 60>, <3745650 55>, <3726610 50>, <3711630 45>, + <3696720 40>, <3685660 35>, <3674950 30>, <3663050 25>, + <3649470 20>, <3635260 15>, <3616920 10>, <3592440 5>, + <3574170 0>; + }; + + wifi_pwrseq: wifi-pwrseq { + compatible = "mmc-pwrseq-simple"; + pinctrl-names = "default"; + pinctrl-0 = <&wifi_pwrseq_pins>; + /*reset-gpios = <&gpio3 RK_PB1 GPIO_ACTIVE_LOW>;*/ + }; +}; + +&internal_display { + compatible = "elida,kd35t133"; + iovcc-supply = <&vcc_lcd>; + vdd-supply = <&vcc_lcd>; + rotation = <270>; +}; + +&rk817 { + regulators { + vcc_wifi: LDO_REG9 { + regulator-name = "vcc_wifi"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + }; +}; + +&rk817_charger { + monitored-battery = <&battery>; +}; + +&sdio { + #address-cells = <1>; + #size-cells = <0>; + bus-width = <4>; + cap-sd-highspeed; + cap-sdio-irq; + disable-wp; + keep-power-in-suspend; + non-removable; + vmmc-supply = <&vcc_wifi>; + status = "okay"; + + esp8089: wifi@1 { + compatible = "esp,esp8089"; + reg = <1>; + esp,crystal-26M-en = <2>; + }; +}; + +&pinctrl { + btns { + btn_pins: btn-pins { + rockchip,pins = <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + wifi { + wifi_pwrseq_pins: wifi-pwrseq-pins { + rockchip,pins = /*<3 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>,*/ + <3 RK_PB6 RK_FUNC_GPIO &pcfg_output_high>; + }; + }; +}; diff --git a/config/archr-dts/rk3326-powkiddy-rgb10x.dts b/config/archr-dts/rk3326-powkiddy-rgb10x.dts new file mode 100644 index 0000000000..debc628194 --- /dev/null +++ b/config/archr-dts/rk3326-powkiddy-rgb10x.dts @@ -0,0 +1,214 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2024 ROCKNIX + */ + +/dts-v1/; +#include "rk3326-odroid-go.dtsi" +#include "retrogame_joypad_s2_f1.dtsi" +#include "rk3326-device-group-r36.dtsi" + +/ { + model = "Powkiddy RGB10X"; + compatible = "powkiddy,rk3326-rgb10x", "rockchip,rk3326"; + + archr,device_switch { + this = "rgb10x"; + }; + + aliases { + mmc1 = &sdio; + }; + + battery: battery { + compatible = "simple-battery"; + charge-full-design-microamp-hours = <2800000>; + charge-term-current-microamp = <280000>; + constant-charge-current-max-microamp = <2000000>; + constant-charge-voltage-max-microvolt = <4200000>; + factory-internal-resistance-micro-ohms = <180000>; + voltage-max-design-microvolt = <4100000>; + voltage-min-design-microvolt = <3500000>; + + ocv-capacity-celsius = <20>; + ocv-capacity-table-0 = <4046950 100>, <4001920 95>, <3967900 90>, <3919950 85>, + <3888450 80>, <3861850 75>, <3831540 70>, <3799130 65>, + <3768190 60>, <3745650 55>, <3726610 50>, <3711630 45>, + <3696720 40>, <3685660 35>, <3674950 30>, <3663050 25>, + <3649470 20>, <3635260 15>, <3616920 10>, <3592440 5>, + <3574170 0>; + }; + + gpio-keys-vol { + compatible = "gpio-keys"; + autorepeat; + pinctrl-0 = <&btn_pins_vol>; + pinctrl-names = "default"; + + button-vol-down { + gpios = <&gpio2 RK_PA1 GPIO_ACTIVE_LOW>; + label = "VOLUMEDOWN"; + linux,code = ; + }; + + button-volume-up { + gpios = <&gpio2 RK_PA0 GPIO_ACTIVE_LOW>; + label = "VOLUMEUP"; + linux,code = ; + }; + }; +}; + +&joypad { + compatible = "archr-singleadc-joypad"; + joypad-name = "retrogame_joypad_s1_f2"; /* distinct name to indicate there is 1 stick and 2 fn buttons */ + joypad-product = <0x1112>; /* 11 inherited, 1 for number of sticks, 2 for number of FN */ + status = "okay"; + + /* gpio pincontrol setup */ + pinctrl-names = "default"; + pinctrl-0 = <&btn_pins>; + + /* Analog mux define */ + io-channel-names = "amux_adc"; + io-channels = <&saradc 1>; + + /* adc mux channel count */ + /* despite there is only left stick, amux-count needs to be 4, */ + /* because amux 0 and 1 are hardcoded as RX and RY in the driver */ + amux-count = <4>; + /* adc mux select(a,b) gpio */ + amux-a-gpios = <&gpio3 RK_PB3 GPIO_ACTIVE_LOW>; + amux-b-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>; + /* adc mux enable gpio */ + amux-en-gpios = <&gpio3 RK_PB5 GPIO_ACTIVE_LOW>; + + /* + Analog Stick data tuning value(precent) + p = positive direction, n = negative direction + report value = (real_adc_data * tuning_value) / 100 + */ + abs_x-p-tuning = <200>; + abs_x-n-tuning = <200>; + + abs_y-p-tuning = <200>; + abs_y-n-tuning = <200>; + + abs_rx-p-tuning = <200>; + abs_rx-n-tuning = <200>; + + abs_ry-p-tuning = <200>; + abs_ry-n-tuning = <200>; + + /* required for RGB10X */ + invert-absx; + invert-absy; + + /* + joypad driver is poll-device driver. + poll-device is does not support wakeup-source. + */ + up { gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_LOW>; }; + down { gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_LOW>; }; + left { gpios = <&gpio1 RK_PB6 GPIO_ACTIVE_LOW>; }; + right { gpios = <&gpio1 RK_PB7 GPIO_ACTIVE_LOW>; }; + + a { gpios = <&gpio1 RK_PA2 GPIO_ACTIVE_LOW>; }; + b { gpios = <&gpio1 RK_PA5 GPIO_ACTIVE_LOW>; }; + x { gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_LOW>; }; + y { gpios = <&gpio1 RK_PA6 GPIO_ACTIVE_LOW>; }; + + tl { gpios = <&gpio2 RK_PA6 GPIO_ACTIVE_LOW>; }; + tr { gpios = <&gpio2 RK_PA7 GPIO_ACTIVE_LOW>; }; + tr2 { gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; }; + tl2 { gpios = <&gpio3 RK_PB2 GPIO_ACTIVE_LOW>; }; + + select{ gpios = <&gpio3 RK_PB1 GPIO_ACTIVE_LOW>; }; + start { gpios = <&gpio3 RK_PB4 GPIO_ACTIVE_LOW>; }; + + thumbl{ gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; }; + + /* Plus and Minus face buttons are mapped to mode and thumbr */ + mode { + gpios = <&gpio2 RK_PA4 GPIO_ACTIVE_LOW>; + label = "GPIO MINUS"; + }; + thumbr { + gpios = <&gpio2 RK_PA3 GPIO_ACTIVE_LOW>; + label = "GPIO PLUS"; + }; +}; + +&internal_display { + compatible = "powkiddy,rk2023-panel", "newvision,nv3051d"; + vdd-supply = <&vcc_lcd>; +}; + +&io_domains { + vccio1-supply = <&vccio_sd>; +}; + +/delete-node/ &pwm3; +/delete-node/ &pwm_led; + +&red_led { + gpios = <&gpio2 RK_PB5 GPIO_ACTIVE_HIGH>; +}; + +&red_led_pin { + rockchip,pins = <2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; +}; + +&rk817_charger { + monitored-battery = <&battery>; +}; + +&sdio { + cap-sd-highspeed; + card-detect-delay = <200>; + cd-gpios = <&gpio3 RK_PB6 GPIO_ACTIVE_LOW>; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + vmmc-supply = <&vcc_sd>; + vqmmc-supply = <&vccio_sd>; + status = "okay"; +}; + +&vcc_sd { + regulator-max-microvolt = <3000000>; + regulator-min-microvolt = <1800000>; +}; + +&vccio_sd { + regulator-max-microvolt = <1800000>; +}; + +&pinctrl { + btns { + btn_pins: btn-pins { + rockchip,pins = <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + btn_pins_vol: btn-pins-vol { + rockchip,pins = <2 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +}; diff --git a/config/archr-dts/rk3326-powkiddy-rgb20s.dts b/config/archr-dts/rk3326-powkiddy-rgb20s.dts new file mode 100644 index 0000000000..93f149e62a --- /dev/null +++ b/config/archr-dts/rk3326-powkiddy-rgb20s.dts @@ -0,0 +1,375 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2019 Hardkernel Co., Ltd + * Copyright (c) 2020 Theobroma Systems Design und Consulting GmbH + * Copyright (c) 2022 Maya Matuszczyk + */ + +/dts-v1/; +#include "rk3326-odroid-go.dtsi" + +/ { + model = "Powkiddy RGB20S"; + compatible = "powkiddy,rgb20s", "rockchip,rk3326"; + + aliases { + mmc0 = &sdio; + mmc1 = &sdmmc; + }; + + gpio-keys-vol { + compatible = "gpio-keys"; + autorepeat; + pinctrl-0 = <&btn_pins_vol>; + pinctrl-names = "default"; + + button-vol-down { + gpios = <&gpio2 RK_PA1 GPIO_ACTIVE_LOW>; + label = "VOLUMEDOWN"; + linux,code = ; + }; + + button-volume-up { + gpios = <&gpio2 RK_PA0 GPIO_ACTIVE_LOW>; + label = "VOLUMEUP"; + linux,code = ; + }; + }; + + joypad: joypad { + compatible = "archr-singleadc-joypad"; + + pwms = <&pwm0 0 200000000 0>; + pwm-names = "enable"; + rumble-boost-weak = <0x0000>; + rumble-boost-strong = <0x0000>; + + joypad-name = "r36s_Gamepad"; + joypad-product = <0x1188>; + joypad-revision = <0x0188>; + joypad-vendor = <0x0001>; + + status = "okay"; + + /* gpio pincontrol setup */ + pinctrl-names = "default"; + pinctrl-0 = <&btn_pins>; + pinctrl-1 = <&pwm0_pin>; + + /* Analog mux define */ + io-channel-names = "amux_adc"; + io-channels = <&saradc 1>; + + /* adc mux channel count */ + amux-count = <4>; + /* non-default wiring */ + amux-channel-mapping = <0 1 2 3>; + /* adc mux select(a,b) gpio */ + amux-a-gpios = <&gpio3 RK_PB3 GPIO_ACTIVE_LOW>; + amux-b-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>; + /* adc mux enable gpio */ + amux-en-gpios = <&gpio3 RK_PB5 GPIO_ACTIVE_LOW>; + + /* adc calculate scale */ + button-adc-scale = <2>; + + /* adc deadzone range */ + button-adc-deadzone = <64>; + + /* + specifies fuzz value that is used to filter noise from + the event stream. + */ + button-adc-fuzz = <32>; + button-adc-flat = <32>; + + /* + Analog Stick data tuning value(precent) + p = positive direction, n = negative direction + report value = (real_adc_data * tuning_value) / 100 + */ + abs_x-p-tuning = <400>; + abs_x-n-tuning = <400>; + + abs_y-p-tuning = <400>; + abs_y-n-tuning = <400>; + + abs_rx-p-tuning = <400>; + abs_rx-n-tuning = <400>; + + abs_ry-p-tuning = <400>; + abs_ry-n-tuning = <400>; + + /* poll device interval (ms), adc read interval */ + poll-interval = <10>; + + /* required for RG351MP */ + invert-absx; + invert-absy; + + /* gpio button auto repeat set value : default disable */ + /* + autorepeat; + */ + + /* + joypad driver is poll-device driver. + poll-device is does not support wakeup-source. + */ + sw1 { + gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-UP"; + linux,code = ; // 0x220 + }; + sw2 { + gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-DOWN"; + linux,code = ; // 0x221 + }; + sw3 { + gpios = <&gpio1 RK_PB6 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-LEFT"; + linux,code = ; // 0x222 + }; + sw4 { + gpios = <&gpio1 RK_PB7 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-RIGHT"; + linux,code = ; // 0x223 + }; + sw5 { + gpios = <&gpio1 RK_PA2 GPIO_ACTIVE_LOW>; + label = "GPIO KEY BTN-A"; + linux,code = ; // 0x131 + }; + sw6 { + gpios = <&gpio1 RK_PA5 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-B"; + linux,code = ; // 0x130 + }; + sw7 { + gpios = <&gpio1 RK_PA6 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-Y"; + linux,code = ; // 0x134 + }; + sw8 { + gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-X"; + linux,code = ; // 0x133 + }; + sw11 { + gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_THUMBL"; + linux,code = ; // 0x2c2 + }; + sw12 { + gpios = <&gpio2 RK_PA3 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_THUMBR"; + linux,code = ; // 0x2c3 + }; + + sw13 { + gpios = <&gpio2 RK_PA4 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_FN"; + linux,code = ; // 0x2c4 + }; + + sw15 { + gpios = <&gpio2 RK_PA6 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-LEFT"; + linux,code = ; // 0x02 + }; + sw16 { + gpios = <&gpio2 RK_PA7 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-RIGHT"; + linux,code = ; // 0x05 + }; + sw19 { + gpios = <&gpio3 RK_PB1 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_SELECT"; + linux,code = ; + }; + sw20 { + gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-RIGHT2"; + linux,code = ; + }; + sw21 { + gpios = <&gpio3 RK_PB2 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-LEFT2"; + linux,code = ; + }; + sw22 { + gpios = <&gpio3 RK_PB4 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_START"; + linux,code = ; + }; + }; + + battery: battery { + compatible = "simple-battery"; + charge-full-design-microamp-hours = <3500000>; + charge-term-current-microamp = <350000>; + constant-charge-current-max-microamp = <2000000>; + constant-charge-voltage-max-microvolt = <4200000>; + factory-internal-resistance-micro-ohms = <180000>; + voltage-max-design-microvolt = <4100000>; + voltage-min-design-microvolt = <3500000>; + + ocv-capacity-celsius = <20>; + ocv-capacity-table-0 = <4046950 100>, <4001920 95>, <3967900 90>, <3919950 85>, + <3888450 80>, <3861850 75>, <3831540 70>, <3799130 65>, + <3768190 60>, <3745650 55>, <3726610 50>, <3711630 45>, + <3696720 40>, <3685660 35>, <3674950 30>, <3663050 25>, + <3649470 20>, <3635260 15>, <3616920 10>, <3592440 5>, + <3574170 0>; + }; +}; + +/* conflicts with pwm vibration motor */ +/delete-node/ &vcc_host; + +/* Device only has 1 LED compared to Odroid Go Advance */ +/delete-node/ &gpio_led; + +&internal_display { +// compatible = "anbernic,rg351v-panel", "newvision,nv3051d"; + // compatible = "powkiddy,rk2023-panel", "newvision,nv3051d"; + compatible = "archr,generic-dsi"; + iovcc-supply = <&vcc_lcd>; + vdd-supply = <&vcc_lcd>; + panel_description = + "G size=52,70 delays=2,1,20,120,20 format=rgb888 lanes=4 flags=0xe03", + + "M clock=26400 horizontal=640,119,2,119 vertical=480,13,2,5 default=1", + "M clock=27300 horizontal=640,207,24,207 vertical=480,13,9,5", + "M clock=26400 horizontal=640,207,2,207 vertical=480,13,2,5", + "M clock=27140 horizontal=640,119,45,119 vertical=480,13,90,5", + "M clock=26450 horizontal=640,119,42,119 vertical=480,13,2,5", + "M clock=28520 horizontal=640,119,3,119 vertical=480,13,44,5", + "M clock=31440 horizontal=640,119,39,119 vertical=480,13,74,5", + "M clock=26440 horizontal=640,31,30,31 vertical=480,13,103,5", + "M clock=31970 horizontal=640,31,36,31 vertical=480,13,76,5", + // "M clock=31680 horizontal=640,31,2,31 vertical=480,13,2,5", + "M clock=42240 horizontal=640,31,2,31 vertical=480,13,2,5", + + "I seq=ff30", "I seq=ff52", "I seq=ff01", + "I seq=e300", + "I seq=400a", + "I seq=0340", "I seq=0400", "I seq=0503", + "I seq=2412", "I seq=251e", "I seq=2628", "I seq=2752", + "I seq=2857", "I seq=2901", "I seq=2adf", + "I seq=389c", "I seq=39a7", "I seq=3a53", + "I seq=4400", + "I seq=493c", + "I seq=59fe", "I seq=5c00", + "I seq=9177", "I seq=9277", + "I seq=a055", "I seq=a150", "I seq=a49c", "I seq=a702", + "I seq=a801", "I seq=a901", "I seq=aafc", "I seq=ab28", "I seq=ac06", "I seq=ad06", "I seq=ae06", "I seq=af03", + "I seq=b008", "I seq=b126", "I seq=b228", "I seq=b328", "I seq=b433", "I seq=b508", "I seq=b626", "I seq=b708", + "I seq=b826", + "I seq=ff30", "I seq=ff52", "I seq=ff02", + "I seq=b00b", "I seq=b116", "I seq=b217", "I seq=b32c", "I seq=b432", "I seq=b53b", "I seq=b629", "I seq=b740", + "I seq=b80d", "I seq=b905", "I seq=ba12", "I seq=bb10", "I seq=bc12", "I seq=bd15", "I seq=be19", "I seq=bf0e", + "I seq=c016", "I seq=c10a", + "I seq=d00c", "I seq=d117", "I seq=d214", "I seq=d32e", "I seq=d432", "I seq=d53c", "I seq=d622", "I seq=d73d", + "I seq=d80d", "I seq=d907", "I seq=da13", "I seq=db13", "I seq=dc11", "I seq=dd15", "I seq=de19", "I seq=df10", + "I seq=e017", "I seq=e10a", + "I seq=ff30", "I seq=ff52", "I seq=ff03", + "I seq=002a", "I seq=012a", "I seq=022a", "I seq=032a", "I seq=0461", "I seq=0580", "I seq=06c7", "I seq=0701", + "I seq=0882", "I seq=0983", + "I seq=302a", "I seq=312a", "I seq=322a", "I seq=332a", "I seq=3461", "I seq=35c5", "I seq=3680", "I seq=3723", + "I seq=4082", "I seq=4183", "I seq=4280", "I seq=4381", "I seq=4411", "I seq=45e6", "I seq=46e5", "I seq=4711", + "I seq=48e8", "I seq=49e7", + "I seq=5002", "I seq=5101", "I seq=5204", "I seq=5303", "I seq=5411", "I seq=55ea", "I seq=56e9", "I seq=5711", + "I seq=58ec", "I seq=59eb", + "I seq=7e02", "I seq=7f80", + "I seq=e05a", + "I seq=b100", "I seq=b40e", "I seq=b50f", "I seq=b604", "I seq=b707", + "I seq=b806", "I seq=b905", "I seq=ba0f", + "I seq=c700", + "I seq=ca0e", "I seq=cb0f", "I seq=cc04", "I seq=cd07", "I seq=ce06", "I seq=cf05", + "I seq=d00f", + "I seq=810f", "I seq=840e", "I seq=850f", "I seq=8607", "I seq=8704", + "I seq=8805", "I seq=8906", "I seq=8a00", + "I seq=970f", + "I seq=9a0e", "I seq=9b0f", "I seq=9c07", "I seq=9d04", "I seq=9e05", "I seq=9f06", + "I seq=a000", + "I seq=ff30", "I seq=ff52", "I seq=ff02", + "I seq=0101", "I seq=02da", "I seq=03ba", "I seq=04a8", "I seq=059a", "I seq=0670", "I seq=07ff", + "I seq=0891", "I seq=0990", "I seq=0aff", "I seq=0b8f", "I seq=0c60", "I seq=0d58", "I seq=0e48", "I seq=0f38", + "I seq=102b", + "I seq=ff30", "I seq=ff52", "I seq=ff00", + "I seq=3602", + "I seq=3a70", + "I seq=11 wait=200", + "I seq=29 wait=10"; +}; + +&io_domains { + vccio1-supply = <&vccio_sd>; +}; + +/delete-node/ &pwm_led; + +&pwm0 { + status = "okay"; +}; + +/delete-node/ &pwm3; + +&rk817_charger { + /* This device does not have a current sense resistor */ + rockchip,resistor-sense-micro-ohms = <0>; + monitored-battery = <&battery>; +}; + +&sdio { + cap-sd-highspeed; + card-detect-delay = <200>; + cd-gpios = <&gpio3 RK_PB6 GPIO_ACTIVE_LOW>; /*[> CD GPIO <]*/ + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + vmmc-supply = <&vcc_sd>; + vqmmc-supply = <&vccio_sd>; + status = "okay"; +}; + +&vcc_sd { + regulator-max-microvolt = <3000000>; + regulator-min-microvolt = <1800000>; +}; + +&vccio_sd { + regulator-max-microvolt = <1800000>; +}; + +&pinctrl { + btns { + btn_pins_vol: btn-pins-vol { + rockchip,pins = <2 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + btn_pins: btn-pins { + rockchip,pins = <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +}; diff --git a/config/archr-dts/soysauce/Y3506_V03_20241104/rg351p-uboot.dtb b/config/archr-dts/soysauce/Y3506_V03_20241104/rg351p-uboot.dtb new file mode 100644 index 0000000000..5603c698d0 Binary files /dev/null and b/config/archr-dts/soysauce/Y3506_V03_20241104/rg351p-uboot.dtb differ diff --git a/config/archr-dts/soysauce/Y3506_V03_20241104/rg351v-uboot.dtb b/config/archr-dts/soysauce/Y3506_V03_20241104/rg351v-uboot.dtb new file mode 100644 index 0000000000..5603c698d0 Binary files /dev/null and b/config/archr-dts/soysauce/Y3506_V03_20241104/rg351v-uboot.dtb differ diff --git a/config/archr-dts/soysauce/Y3506_V03_20241104/rk3326-r36s-linux.dtb b/config/archr-dts/soysauce/Y3506_V03_20241104/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..021b7393e3 Binary files /dev/null and b/config/archr-dts/soysauce/Y3506_V03_20241104/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/soysauce/Y3506_V03_20250317/rg351p-uboot.dtb b/config/archr-dts/soysauce/Y3506_V03_20250317/rg351p-uboot.dtb new file mode 100644 index 0000000000..d1daaa87f5 Binary files /dev/null and b/config/archr-dts/soysauce/Y3506_V03_20250317/rg351p-uboot.dtb differ diff --git a/config/archr-dts/soysauce/Y3506_V03_20250317/rg351v-uboot.dtb b/config/archr-dts/soysauce/Y3506_V03_20250317/rg351v-uboot.dtb new file mode 100644 index 0000000000..d1daaa87f5 Binary files /dev/null and b/config/archr-dts/soysauce/Y3506_V03_20250317/rg351v-uboot.dtb differ diff --git a/config/archr-dts/soysauce/Y3506_V03_20250317/rk3326-r36s-linux.dtb b/config/archr-dts/soysauce/Y3506_V03_20250317/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..e10696a1a3 Binary files /dev/null and b/config/archr-dts/soysauce/Y3506_V03_20250317/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/soysauce/Y3506_V04_20250529 253x Panel 6/rg351p-uboot.dtb b/config/archr-dts/soysauce/Y3506_V04_20250529 253x Panel 6/rg351p-uboot.dtb new file mode 100644 index 0000000000..7754976b6f Binary files /dev/null and b/config/archr-dts/soysauce/Y3506_V04_20250529 253x Panel 6/rg351p-uboot.dtb differ diff --git a/config/archr-dts/soysauce/Y3506_V04_20250529 253x Panel 6/rg351v-uboot.dtb b/config/archr-dts/soysauce/Y3506_V04_20250529 253x Panel 6/rg351v-uboot.dtb new file mode 100644 index 0000000000..7754976b6f Binary files /dev/null and b/config/archr-dts/soysauce/Y3506_V04_20250529 253x Panel 6/rg351v-uboot.dtb differ diff --git a/config/archr-dts/soysauce/Y3506_V04_20250529 253x Panel 6/rk3326-r36s-linux.dtb b/config/archr-dts/soysauce/Y3506_V04_20250529 253x Panel 6/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..85b2037304 Binary files /dev/null and b/config/archr-dts/soysauce/Y3506_V04_20250529 253x Panel 6/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/soysauce/Y3506_V04_20250529 253x Panel 7/rg351p-kernel.dtb b/config/archr-dts/soysauce/Y3506_V04_20250529 253x Panel 7/rg351p-kernel.dtb new file mode 100644 index 0000000000..98b1dbfe3c Binary files /dev/null and b/config/archr-dts/soysauce/Y3506_V04_20250529 253x Panel 7/rg351p-kernel.dtb differ diff --git a/config/archr-dts/soysauce/Y3506_V04_20250529 253x Panel 7/rg351v-kernel.dtb b/config/archr-dts/soysauce/Y3506_V04_20250529 253x Panel 7/rg351v-kernel.dtb new file mode 100644 index 0000000000..98b1dbfe3c Binary files /dev/null and b/config/archr-dts/soysauce/Y3506_V04_20250529 253x Panel 7/rg351v-kernel.dtb differ diff --git a/config/archr-dts/soysauce/Y3506_V04_20250529 253x Panel 7/rk3326-r36s-linux.dtb b/config/archr-dts/soysauce/Y3506_V04_20250529 253x Panel 7/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..37c26cccc3 Binary files /dev/null and b/config/archr-dts/soysauce/Y3506_V04_20250529 253x Panel 7/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/soysauce/Y3506_V04_20250529 2548 Panel 2/rg351p-uboot.dtb b/config/archr-dts/soysauce/Y3506_V04_20250529 2548 Panel 2/rg351p-uboot.dtb new file mode 100644 index 0000000000..7754976b6f Binary files /dev/null and b/config/archr-dts/soysauce/Y3506_V04_20250529 2548 Panel 2/rg351p-uboot.dtb differ diff --git a/config/archr-dts/soysauce/Y3506_V04_20250529 2548 Panel 2/rg351v-uboot.dtb b/config/archr-dts/soysauce/Y3506_V04_20250529 2548 Panel 2/rg351v-uboot.dtb new file mode 100644 index 0000000000..7754976b6f Binary files /dev/null and b/config/archr-dts/soysauce/Y3506_V04_20250529 2548 Panel 2/rg351v-uboot.dtb differ diff --git a/config/archr-dts/soysauce/Y3506_V04_20250529 2548 Panel 2/rk3326-r36s-linux.dtb b/config/archr-dts/soysauce/Y3506_V04_20250529 2548 Panel 2/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..3934e618be Binary files /dev/null and b/config/archr-dts/soysauce/Y3506_V04_20250529 2548 Panel 2/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/soysauce/Y3506_V04_20250529 2548/rg351p-uboot.dtb b/config/archr-dts/soysauce/Y3506_V04_20250529 2548/rg351p-uboot.dtb new file mode 100644 index 0000000000..d1daaa87f5 Binary files /dev/null and b/config/archr-dts/soysauce/Y3506_V04_20250529 2548/rg351p-uboot.dtb differ diff --git a/config/archr-dts/soysauce/Y3506_V04_20250529 2548/rg351v-uboot.dtb b/config/archr-dts/soysauce/Y3506_V04_20250529 2548/rg351v-uboot.dtb new file mode 100644 index 0000000000..d1daaa87f5 Binary files /dev/null and b/config/archr-dts/soysauce/Y3506_V04_20250529 2548/rg351v-uboot.dtb differ diff --git a/config/archr-dts/soysauce/Y3506_V04_20250529 2548/rk3326-r36s-linux.dtb b/config/archr-dts/soysauce/Y3506_V04_20250529 2548/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..6dfc274859 Binary files /dev/null and b/config/archr-dts/soysauce/Y3506_V04_20250529 2548/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/soysauce/Y3506_V05_20251215 2551/rg351p-uboot.dtb b/config/archr-dts/soysauce/Y3506_V05_20251215 2551/rg351p-uboot.dtb new file mode 100644 index 0000000000..2f233904bb Binary files /dev/null and b/config/archr-dts/soysauce/Y3506_V05_20251215 2551/rg351p-uboot.dtb differ diff --git a/config/archr-dts/soysauce/Y3506_V05_20251215 2551/rg351v-uboot.dtb b/config/archr-dts/soysauce/Y3506_V05_20251215 2551/rg351v-uboot.dtb new file mode 100644 index 0000000000..2f233904bb Binary files /dev/null and b/config/archr-dts/soysauce/Y3506_V05_20251215 2551/rg351v-uboot.dtb differ diff --git a/config/archr-dts/soysauce/Y3506_V05_20251215 2551/rk3326-r36s-linux.dtb b/config/archr-dts/soysauce/Y3506_V05_20251215 2551/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..67ad12ee26 Binary files /dev/null and b/config/archr-dts/soysauce/Y3506_V05_20251215 2551/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/soysauce/Y3506_V05_20251215 2601/rg351p-uboot.dtb b/config/archr-dts/soysauce/Y3506_V05_20251215 2601/rg351p-uboot.dtb new file mode 100644 index 0000000000..b4ee6f163a Binary files /dev/null and b/config/archr-dts/soysauce/Y3506_V05_20251215 2601/rg351p-uboot.dtb differ diff --git a/config/archr-dts/soysauce/Y3506_V05_20251215 2601/rg351v-uboot.dtb b/config/archr-dts/soysauce/Y3506_V05_20251215 2601/rg351v-uboot.dtb new file mode 100644 index 0000000000..b4ee6f163a Binary files /dev/null and b/config/archr-dts/soysauce/Y3506_V05_20251215 2601/rg351v-uboot.dtb differ diff --git a/config/archr-dts/soysauce/Y3506_V05_20251215 2601/rk3326-r36s-linux.dtb b/config/archr-dts/soysauce/Y3506_V05_20251215 2601/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..b115fd2875 Binary files /dev/null and b/config/archr-dts/soysauce/Y3506_V05_20251215 2601/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/soysauce/Y3506_v03_20241210 2507/rg351p-uboot.dtb b/config/archr-dts/soysauce/Y3506_v03_20241210 2507/rg351p-uboot.dtb new file mode 100644 index 0000000000..5603c698d0 Binary files /dev/null and b/config/archr-dts/soysauce/Y3506_v03_20241210 2507/rg351p-uboot.dtb differ diff --git a/config/archr-dts/soysauce/Y3506_v03_20241210 2507/rg351v-uboot.dtb b/config/archr-dts/soysauce/Y3506_v03_20241210 2507/rg351v-uboot.dtb new file mode 100644 index 0000000000..5603c698d0 Binary files /dev/null and b/config/archr-dts/soysauce/Y3506_v03_20241210 2507/rg351v-uboot.dtb differ diff --git a/config/archr-dts/soysauce/Y3506_v03_20241210 2507/rk3326-r36s-linux.dtb b/config/archr-dts/soysauce/Y3506_v03_20241210 2507/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..87df449997 Binary files /dev/null and b/config/archr-dts/soysauce/Y3506_v03_20241210 2507/rk3326-r36s-linux.dtb differ diff --git a/config/archr-dts/soysauce/Y3506_v03_20241210 2533/rg351p-uboot.dtb b/config/archr-dts/soysauce/Y3506_v03_20241210 2533/rg351p-uboot.dtb new file mode 100644 index 0000000000..2f233904bb Binary files /dev/null and b/config/archr-dts/soysauce/Y3506_v03_20241210 2533/rg351p-uboot.dtb differ diff --git a/config/archr-dts/soysauce/Y3506_v03_20241210 2533/rg351v-uboot.dtb b/config/archr-dts/soysauce/Y3506_v03_20241210 2533/rg351v-uboot.dtb new file mode 100644 index 0000000000..2f233904bb Binary files /dev/null and b/config/archr-dts/soysauce/Y3506_v03_20241210 2533/rg351v-uboot.dtb differ diff --git a/config/archr-dts/soysauce/Y3506_v03_20241210 2533/rk3326-r36s-linux.dtb b/config/archr-dts/soysauce/Y3506_v03_20241210 2533/rk3326-r36s-linux.dtb new file mode 100644 index 0000000000..0bd85da8ac Binary files /dev/null and b/config/archr-dts/soysauce/Y3506_v03_20241210 2533/rk3326-r36s-linux.dtb differ diff --git a/config/blocklist b/config/blocklist new file mode 100644 index 0000000000..921d58c31a --- /dev/null +++ b/config/blocklist @@ -0,0 +1,29 @@ +aethersx2-sa # package is EOL +amiberry # Updating breaks build packages +control-gen # package does not update +dolphin-sa # Wayland patch is now broken upstream +drastic-sa # Package is closed source bin +duckstation-lr # Libretro support removed from upstream. +duckstation-sa # Patches need to be reworked. +flycast-sa # Patched need to rebased +gptokeyb # Newer versions break hotkeys +gzdoom-sa # Stick to release versions. +idtech-lr # Just a dummy package +kronos-sa # Using the release version of kronos had better results. +melonds-sa # Broken OpenGL renderer upstream +minivmac-lr # Upstream Makefile change breaks build +mupen64plus-sa-ui-console # Causes segfaults +nanoboyadvance-sa # SDL version removed after this commit +np2kai # Last major commit before hiatus is broken. +openbor # Newer versions break controls, needs research. +pico-8 # Metapackage, doesn't need to update +portmaster # Manually update version +ppsspp-sa # Manually update to release versions. +retroarch # Manually update to release versions. +rpcs3-sa # Need to update to llvm 16 +scummvmsa # Updating breaks build packages +tic80-lr # patches need to be rebased +vice-lr # Updating breaks build patches +vice-sa # Doesn't support updating with the script. +vita3k-sa # Should be manually updated. +mupen64plus-nx-lr #Upstream brakes video out. diff --git a/config/docker/changelog.txt b/config/docker/changelog.txt new file mode 100644 index 0000000000..ffbebe8438 --- /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 0000000000..b34a83a8f0 --- /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 0000000000..54e66e198a --- /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 0000000000..3b7ab1a1e6 --- /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 0000000000..23c8b7c56e --- /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 0000000000..bafc603a73 --- /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 0000000000..1250444d2b --- /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/emulators/3do.conf b/config/emulators/3do.conf new file mode 100644 index 0000000000..e5655c59cc --- /dev/null +++ b/config/emulators/3do.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="3do" +SYSTEM_FULLNAME="3DO" +SYSTEM_MANUFACTURER="Panasonic" +SYSTEM_RELEASE="1993" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/3do" +SYSTEM_EXTENSION=".iso .bin .chd .cue" +SYSTEM_PLATFORM="3do" +SYSTEM_THEME="3do" +SYSTEM_WIKI_PATH="3do" \ No newline at end of file diff --git a/config/emulators/3ds.conf b/config/emulators/3ds.conf new file mode 100644 index 0000000000..ec9a25a2d3 --- /dev/null +++ b/config/emulators/3ds.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="3ds" +SYSTEM_FULLNAME="Nintendo 3DS" +SYSTEM_MANUFACTURER="Nintendo" +SYSTEM_RELEASE="2010" +SYSTEM_HARDWARE="portable" +SYSTEM_PATH="/storage/roms/3ds" +SYSTEM_EXTENSION=".3ds .3dsx .app .axf .cci .cxi .cia .elf .z3dsx .zcia .zcci .zcxi" +SYSTEM_PLATFORM="3ds" +SYSTEM_THEME="3ds" +SYSTEM_WIKI_PATH="3ds" diff --git a/config/emulators/amiga.conf b/config/emulators/amiga.conf new file mode 100644 index 0000000000..9eb22d57d7 --- /dev/null +++ b/config/emulators/amiga.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="amiga" +SYSTEM_FULLNAME="Amiga" +SYSTEM_MANUFACTURER="Commodore" +SYSTEM_RELEASE="1985" +SYSTEM_HARDWARE="computer" +SYSTEM_PATH="/storage/roms/amiga" +SYSTEM_EXTENSION=".zip .adf .uae .ipf .dms .adz .lha .m3u .hdf .hdz" +SYSTEM_PLATFORM="amiga" +SYSTEM_THEME="amiga" +SYSTEM_WIKI_PATH="amiga" diff --git a/config/emulators/amigacd32.conf b/config/emulators/amigacd32.conf new file mode 100644 index 0000000000..b107e5b21d --- /dev/null +++ b/config/emulators/amigacd32.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="amigacd32" +SYSTEM_FULLNAME="Amiga CD32" +SYSTEM_MANUFACTURER="Commodore" +SYSTEM_RELEASE="1994" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/amigacd32" +SYSTEM_EXTENSION=".iso .cue .lha .chd" +SYSTEM_PLATFORM="amigacd32" +SYSTEM_THEME="amigacd32" +SYSTEM_WIKI_PATH="amigacd32" diff --git a/config/emulators/amstradcpc.conf b/config/emulators/amstradcpc.conf new file mode 100644 index 0000000000..c64a64c297 --- /dev/null +++ b/config/emulators/amstradcpc.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="amstradcpc" +SYSTEM_FULLNAME="Amstrad CPC" +SYSTEM_MANUFACTURER="Amstrad" +SYSTEM_RELEASE="1984" +SYSTEM_HARDWARE="computer" +SYSTEM_PATH="/storage/roms/amstradcpc" +SYSTEM_EXTENSION=".dsk .cpr .sna .tap .cdt .kcr .voc .m3u .zip .7z" +SYSTEM_PLATFORM="amstradcpc" +SYSTEM_THEME="amstradcpc" +SYSTEM_WIKI_PATH="amstradcpc" diff --git a/config/emulators/arcade.conf b/config/emulators/arcade.conf new file mode 100644 index 0000000000..c7cb010e28 --- /dev/null +++ b/config/emulators/arcade.conf @@ -0,0 +1,9 @@ +SYSTEM_NAME="arcade" +SYSTEM_FULLNAME="Arcade" +SYSTEM_MANUFACTURER="Arcade" +SYSTEM_RELEASE="0000" +SYSTEM_HARDWARE="arcade" +SYSTEM_PATH="/storage/roms/arcade" +SYSTEM_EXTENSION=".zip .7z" +SYSTEM_PLATFORM="arcade" +SYSTEM_THEME="arcade" diff --git a/config/emulators/arduboy.conf b/config/emulators/arduboy.conf new file mode 100644 index 0000000000..4b75262131 --- /dev/null +++ b/config/emulators/arduboy.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="arduboy" +SYSTEM_FULLNAME="Arduboy" +SYSTEM_MANUFACTURER="Arduboy" +SYSTEM_RELEASE="2014" +SYSTEM_HARDWARE="portable" +SYSTEM_PATH="/storage/roms/arduboy" +SYSTEM_EXTENSION=".hex" +SYSTEM_PLATFORM="arduboy" +SYSTEM_THEME="arduboy" +SYSTEM_WIKI_PATH="arduboy" diff --git a/config/emulators/atari2600.conf b/config/emulators/atari2600.conf new file mode 100644 index 0000000000..48df284a38 --- /dev/null +++ b/config/emulators/atari2600.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="atari2600" +SYSTEM_FULLNAME="Atari 2600" +SYSTEM_MANUFACTURER="Atari" +SYSTEM_RELEASE="1977" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/atari2600" +SYSTEM_EXTENSION=".a26 .bin .zip .7z" +SYSTEM_PLATFORM="atari2600" +SYSTEM_THEME="atari2600" +SYSTEM_WIKI_PATH="atari2600" diff --git a/config/emulators/atari5200.conf b/config/emulators/atari5200.conf new file mode 100644 index 0000000000..94f2b2dade --- /dev/null +++ b/config/emulators/atari5200.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="atari5200" +SYSTEM_FULLNAME="Atari 5200" +SYSTEM_MANUFACTURER="Atari" +SYSTEM_RELEASE="1982" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/atari5200" +SYSTEM_EXTENSION=".rom .xfd .atr .atx .cdm .cas .car .bin .a52 .xex .zip .7z" +SYSTEM_PLATFORM="atari5200" +SYSTEM_THEME="atari5200" +SYSTEM_WIKI_PATH="atari5200" diff --git a/config/emulators/atari7800.conf b/config/emulators/atari7800.conf new file mode 100644 index 0000000000..ffbac48af2 --- /dev/null +++ b/config/emulators/atari7800.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="atari7800" +SYSTEM_FULLNAME="Atari 7800" +SYSTEM_MANUFACTURER="Atari" +SYSTEM_RELEASE="1986" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/atari7800" +SYSTEM_EXTENSION=".a78 .bin .zip .7z" +SYSTEM_PLATFORM="atari7800" +SYSTEM_THEME="atari7800" +SYSTEM_WIKI_PATH="atari7800" diff --git a/config/emulators/atari800.conf b/config/emulators/atari800.conf new file mode 100644 index 0000000000..af91084c09 --- /dev/null +++ b/config/emulators/atari800.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="atari800" +SYSTEM_FULLNAME="Atari 800" +SYSTEM_MANUFACTURER="Atari" +SYSTEM_RELEASE="1979" +SYSTEM_HARDWARE="computer" +SYSTEM_PATH="/storage/roms/atari800" +SYSTEM_EXTENSION=".rom .xfd .atr .atx .cdm .cas .car .bin .a52 .xex .zip .7z" +SYSTEM_PLATFORM="atari800" +SYSTEM_THEME="atari800" +SYSTEM_WIKI_PATH="atari800" diff --git a/config/emulators/atarijaguar.conf b/config/emulators/atarijaguar.conf new file mode 100644 index 0000000000..53ec06924e --- /dev/null +++ b/config/emulators/atarijaguar.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="atarijaguar" +SYSTEM_FULLNAME="Atari Jaguar" +SYSTEM_MANUFACTURER="Atari" +SYSTEM_RELEASE="1993" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/atarijaguar" +SYSTEM_EXTENSION=".j64 .jag .rom .abs .cof .bin .prg" +SYSTEM_PLATFORM="atarijaguar" +SYSTEM_THEME="atarijaguar" +SYSTEM_WIKI_PATH="atarijaguar" diff --git a/config/emulators/atarilynx.conf b/config/emulators/atarilynx.conf new file mode 100644 index 0000000000..bbb33a0b85 --- /dev/null +++ b/config/emulators/atarilynx.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="atarilynx" +SYSTEM_FULLNAME="Atari Lynx" +SYSTEM_MANUFACTURER="Atari" +SYSTEM_RELEASE="1989" +SYSTEM_HARDWARE="portable" +SYSTEM_PATH="/storage/roms/atarilynx" +SYSTEM_EXTENSION=".lnx .lyx .o .zip .7z" +SYSTEM_PLATFORM="atarilynx" +SYSTEM_THEME="atarilynx" +SYSTEM_WIKI_PATH="atarilynx" diff --git a/config/emulators/atarist.conf b/config/emulators/atarist.conf new file mode 100644 index 0000000000..6ed1c56354 --- /dev/null +++ b/config/emulators/atarist.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="atarist" +SYSTEM_FULLNAME="Atari ST" +SYSTEM_MANUFACTURER="Atari" +SYSTEM_RELEASE="1985" +SYSTEM_HARDWARE="computer" +SYSTEM_PATH="/storage/roms/atarist" +SYSTEM_EXTENSION=".st .msa .stx .dim .ipf .m3u .zip .7z" +SYSTEM_PLATFORM="atarist" +SYSTEM_THEME="atarist" +SYSTEM_WIKI_PATH="atarist" diff --git a/config/emulators/atomiswave.conf b/config/emulators/atomiswave.conf new file mode 100644 index 0000000000..b4bd9ef9c3 --- /dev/null +++ b/config/emulators/atomiswave.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="atomiswave" +SYSTEM_FULLNAME="Atomiswave" +SYSTEM_MANUFACTURER="Sammy" +SYSTEM_RELEASE="2003" +SYSTEM_HARDWARE="arcade" +SYSTEM_PATH="/storage/roms/atomiswave" +SYSTEM_EXTENSION=".lst .bin .dat .zip .7z" +SYSTEM_PLATFORM="atomiswave arcade" +SYSTEM_THEME="atomiswave" +SYSTEM_WIKI_PATH="atomiswave" diff --git a/config/emulators/bbcmicro.conf b/config/emulators/bbcmicro.conf new file mode 100644 index 0000000000..ab7951c9b7 --- /dev/null +++ b/config/emulators/bbcmicro.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="bbcmicro" +SYSTEM_FULLNAME="BBC Micro" +SYSTEM_MANUFACTURER="Acorn" +SYSTEM_RELEASE="1981" +SYSTEM_HARDWARE="computer" +SYSTEM_PATH="/storage/roms/bbcmicro" +SYSTEM_EXTENSION=".ssd .dsd" +SYSTEM_PLATFORM="bbcmicro" +SYSTEM_THEME="bbcmicro" +SYSTEM_WIKI_PATH="bbcmicro" diff --git a/config/emulators/bk.conf b/config/emulators/bk.conf new file mode 100644 index 0000000000..5b4c7e65ec --- /dev/null +++ b/config/emulators/bk.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="bk" +SYSTEM_FULLNAME="Elektronika BK" +SYSTEM_MANUFACTURER="Elektronika" +SYSTEM_RELEASE="1984" +SYSTEM_HARDWARE="computer" +SYSTEM_PATH="/storage/roms/bk" +SYSTEM_EXTENSION=".bin .img .dsk" +SYSTEM_PLATFORM="bk" +SYSTEM_THEME="bk" +SYSTEM_WIKI_PATH="bk" diff --git a/config/emulators/c128.conf b/config/emulators/c128.conf new file mode 100644 index 0000000000..b21db28ced --- /dev/null +++ b/config/emulators/c128.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="c128" +SYSTEM_FULLNAME="Commodore 128" +SYSTEM_MANUFACTURER="Commodore" +SYSTEM_RELEASE="1985" +SYSTEM_HARDWARE="computer" +SYSTEM_PATH="/storage/roms/c128" +SYSTEM_EXTENSION=".d64 .d71 .d80 .d81 .d82 .g64 .g41 .x64 .t64 .tap .prg .p00 .crt .bin .d6z .d7z .d8z .g6z .g4z .x6z .cmd .m3u .vsf .nib .nbz .zip" +SYSTEM_PLATFORM="c128" +SYSTEM_THEME="c128" +SYSTEM_WIKI_PATH="c128" diff --git a/config/emulators/c16.conf b/config/emulators/c16.conf new file mode 100644 index 0000000000..9aba9ec35f --- /dev/null +++ b/config/emulators/c16.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="c16" +SYSTEM_FULLNAME="Commodore 16" +SYSTEM_MANUFACTURER="Commodore" +SYSTEM_RELEASE="1984" +SYSTEM_HARDWARE="computer" +SYSTEM_PATH="/storage/roms/c16" +SYSTEM_EXTENSION=".d64 .d71 .d80 .d81 .d82 .g64 .g41 .x64 .t64 .tap .prg .p00 .crt .bin .d6z .d7z .d8z .g6z .g4z .x6z .cmd .m3u .vsf .nib .nbz .zip" +SYSTEM_PLATFORM="c16" +SYSTEM_THEME="c16" +SYSTEM_WIKI_PATH="c16" diff --git a/config/emulators/c64.conf b/config/emulators/c64.conf new file mode 100644 index 0000000000..044a6d0e70 --- /dev/null +++ b/config/emulators/c64.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="c64" +SYSTEM_FULLNAME="Commodore 64" +SYSTEM_MANUFACTURER="Commodore" +SYSTEM_RELEASE="1982" +SYSTEM_HARDWARE="computer" +SYSTEM_PATH="/storage/roms/c64" +SYSTEM_EXTENSION=".d64 .d71 .d80 .d81 .d82 .g64 .g41 .x64 .t64 .tap .prg .p00 .crt .bin .d6z .d7z .d8z .g6z .g4z .x6z .cmd .m3u .vsf .nib .nbz .zip" +SYSTEM_PLATFORM="c64" +SYSTEM_THEME="c64" +SYSTEM_WIKI_PATH="c64" diff --git a/config/emulators/cdi.conf b/config/emulators/cdi.conf new file mode 100644 index 0000000000..5a2462f98b --- /dev/null +++ b/config/emulators/cdi.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="cdi" +SYSTEM_FULLNAME="CD-i" +SYSTEM_MANUFACTURER="Philips" +SYSTEM_RELEASE="1991" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/cdi" +SYSTEM_EXTENSION=".chd .cue .iso" +SYSTEM_PLATFORM="cdi" +SYSTEM_THEME="cdi" +SYSTEM_WIKI_PATH="cdi" diff --git a/config/emulators/channelf.conf b/config/emulators/channelf.conf new file mode 100644 index 0000000000..6bd25798d9 --- /dev/null +++ b/config/emulators/channelf.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="channelf" +SYSTEM_FULLNAME="Fairchild Channel F" +SYSTEM_MANUFACTURER="Fairchild" +SYSTEM_RELEASE="1976" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/channelf" +SYSTEM_EXTENSION=".bin .chf .zip .7z" +SYSTEM_PLATFORM="channelf" +SYSTEM_THEME="channelf" +SYSTEM_WIKI_PATH="channelf" diff --git a/config/emulators/chip-8.conf b/config/emulators/chip-8.conf new file mode 100644 index 0000000000..1a8922fc53 --- /dev/null +++ b/config/emulators/chip-8.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="chip-8" +SYSTEM_FULLNAME="CHIP-8 / S-CHIP / XO-CHIP" +SYSTEM_MANUFACTURER="Various" +SYSTEM_RELEASE="1978" +SYSTEM_HARDWARE="game engine" +SYSTEM_PATH="/storage/roms/chip-8" +SYSTEM_EXTENSION=".ch8 .sc8 .xo8" +SYSTEM_PLATFORM="chip-8" +SYSTEM_THEME="chip-8" +SYSTEM_WIKI_PATH="chip-8" diff --git a/config/emulators/colecovision.conf b/config/emulators/colecovision.conf new file mode 100644 index 0000000000..b9065bcef2 --- /dev/null +++ b/config/emulators/colecovision.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="colecovision" +SYSTEM_FULLNAME="ColecoVision" +SYSTEM_MANUFACTURER="Coleco" +SYSTEM_RELEASE="1982" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/coleco" +SYSTEM_EXTENSION=".bin .col .rom .zip .7z" +SYSTEM_PLATFORM="colecovision" +SYSTEM_THEME="colecovision" +SYSTEM_WIKI_PATH="colecovision" diff --git a/config/emulators/cps1.conf b/config/emulators/cps1.conf new file mode 100644 index 0000000000..1dedd2bc35 --- /dev/null +++ b/config/emulators/cps1.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="cps1" +SYSTEM_FULLNAME="CPS-I" +SYSTEM_MANUFACTURER="Capcom" +SYSTEM_RELEASE="1988" +SYSTEM_HARDWARE="arcade" +SYSTEM_PATH="/storage/roms/cps1" +SYSTEM_EXTENSION=".zip .7z" +SYSTEM_PLATFORM="arcade" +SYSTEM_THEME="cps1" +SYSTEM_WIKI_PATH="cps1" diff --git a/config/emulators/cps2.conf b/config/emulators/cps2.conf new file mode 100644 index 0000000000..7c5ad82ef4 --- /dev/null +++ b/config/emulators/cps2.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="cps2" +SYSTEM_FULLNAME="CPS-II" +SYSTEM_MANUFACTURER="Capcom" +SYSTEM_RELEASE="1993" +SYSTEM_HARDWARE="arcade" +SYSTEM_PATH="/storage/roms/cps2" +SYSTEM_EXTENSION=".zip .7z" +SYSTEM_PLATFORM="arcade" +SYSTEM_THEME="cps2" +SYSTEM_WIKI_PATH="cps2" diff --git a/config/emulators/cps3.conf b/config/emulators/cps3.conf new file mode 100644 index 0000000000..7b80aec505 --- /dev/null +++ b/config/emulators/cps3.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="cps3" +SYSTEM_FULLNAME="CPS-III" +SYSTEM_MANUFACTURER="Capcom" +SYSTEM_RELEASE="1996" +SYSTEM_HARDWARE="arcade" +SYSTEM_PATH="/storage/roms/cps3" +SYSTEM_EXTENSION=".zip .7z" +SYSTEM_PLATFORM="arcade" +SYSTEM_THEME="cps3" +SYSTEM_WIKI_PATH="cps3" diff --git a/config/emulators/daphne.conf b/config/emulators/daphne.conf new file mode 100644 index 0000000000..790c98e772 --- /dev/null +++ b/config/emulators/daphne.conf @@ -0,0 +1,9 @@ +SYSTEM_NAME="daphne" +SYSTEM_FULLNAME="Daphne" +SYSTEM_MANUFACTURER="Arcade" +SYSTEM_HARDWARE="arcade" +SYSTEM_PATH="/storage/roms/daphne" +SYSTEM_EXTENSION=".daphne .singe" +SYSTEM_PLATFORM="daphne arcade" +SYSTEM_THEME="daphne" +SYSTEM_WIKI_PATH="daphne" diff --git a/config/emulators/doom.conf b/config/emulators/doom.conf new file mode 100644 index 0000000000..13d942f94c --- /dev/null +++ b/config/emulators/doom.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="doom" +SYSTEM_FULLNAME="Doom" +SYSTEM_MANUFACTURER="id Software" +SYSTEM_RELEASE="1993" +SYSTEM_HARDWARE="game engine" +SYSTEM_PATH="/storage/roms/doom" +SYSTEM_EXTENSION=".doom" +SYSTEM_PLATFORM="doom" +SYSTEM_THEME="doom" +SYSTEM_WIKI_PATH="doom" diff --git a/config/emulators/dreamcast.conf b/config/emulators/dreamcast.conf new file mode 100644 index 0000000000..b1e746024e --- /dev/null +++ b/config/emulators/dreamcast.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="dreamcast" +SYSTEM_FULLNAME="Dreamcast" +SYSTEM_MANUFACTURER="Sega" +SYSTEM_RELEASE="1998" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/dreamcast" +SYSTEM_EXTENSION=".cdi .gdi .chd .m3u .cue" +SYSTEM_PLATFORM="dreamcast" +SYSTEM_THEME="dreamcast" +SYSTEM_WIKI_PATH="dreamcast" diff --git a/config/emulators/easyrpg.conf b/config/emulators/easyrpg.conf new file mode 100644 index 0000000000..a4bf4151df --- /dev/null +++ b/config/emulators/easyrpg.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="easyrpg" +SYSTEM_FULLNAME="EasyRPG" +SYSTEM_MANUFACTURER="Various" +SYSTEM_RELEASE="2003" +SYSTEM_HARDWARE="game engine" +SYSTEM_PATH="/storage/roms/easyrpg" +SYSTEM_EXTENSION=".zip .easyrpg .ldb" +SYSTEM_PLATFORM="easyrpg" +SYSTEM_THEME="easyrpg" +SYSTEM_WIKI_PATH="easyrpg" diff --git a/config/emulators/famicom.conf b/config/emulators/famicom.conf new file mode 100644 index 0000000000..b6be64a5b5 --- /dev/null +++ b/config/emulators/famicom.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="famicom" +SYSTEM_FULLNAME="Famicom" +SYSTEM_MANUFACTURER="Nintendo" +SYSTEM_RELEASE="1983" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/famicom" +SYSTEM_EXTENSION=".nes .unif .unf .zip .7z" +SYSTEM_PLATFORM="nes" +SYSTEM_THEME="famicom" +SYSTEM_WIKI_PATH="nes" diff --git a/config/emulators/fbn.conf b/config/emulators/fbn.conf new file mode 100644 index 0000000000..eaa47508bd --- /dev/null +++ b/config/emulators/fbn.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="fbn" +SYSTEM_FULLNAME="Final Burn Neo" +SYSTEM_MANUFACTURER="Arcade" +SYSTEM_RELEASE="2002" +SYSTEM_HARDWARE="arcade" +SYSTEM_PATH="/storage/roms/fbneo" +SYSTEM_EXTENSION=".7z .zip" +SYSTEM_PLATFORM="arcade" +SYSTEM_THEME="fbneo" +SYSTEM_WIKI_PATH="fbn" diff --git a/config/emulators/fds.conf b/config/emulators/fds.conf new file mode 100644 index 0000000000..9f89dd4410 --- /dev/null +++ b/config/emulators/fds.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="fds" +SYSTEM_FULLNAME="Famicom Disk System" +SYSTEM_MANUFACTURER="Nintendo" +SYSTEM_RELEASE="1986" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/fds" +SYSTEM_EXTENSION=".fds .zip .7z" +SYSTEM_PLATFORM="fds" +SYSTEM_THEME="fds" +SYSTEM_WIKI_PATH="fds" diff --git a/config/emulators/gameandwatch.conf b/config/emulators/gameandwatch.conf new file mode 100644 index 0000000000..aa4ee9cf89 --- /dev/null +++ b/config/emulators/gameandwatch.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="gameandwatch" +SYSTEM_FULLNAME="Game & Watch" +SYSTEM_MANUFACTURER="Nintendo" +SYSTEM_RELEASE="1980" +SYSTEM_HARDWARE="portable" +SYSTEM_PATH="/storage/roms/gameandwatch" +SYSTEM_EXTENSION=".mgw .zip .7z" +SYSTEM_PLATFORM="gameandwatch" +SYSTEM_THEME="gameandwatch" +SYSTEM_WIKI_PATH="gameandwatch" diff --git a/config/emulators/gamecube.conf b/config/emulators/gamecube.conf new file mode 100644 index 0000000000..a55527afa9 --- /dev/null +++ b/config/emulators/gamecube.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="gamecube" +SYSTEM_FULLNAME="GameCube" +SYSTEM_MANUFACTURER="Nintendo" +SYSTEM_RELEASE="2001" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/gamecube" +SYSTEM_EXTENSION=".gcm .iso .gcz .ciso .wbfs .rvz .dol .m3u" +SYSTEM_PLATFORM="gc" +SYSTEM_THEME="gc" +SYSTEM_WIKI_PATH="gamecube" diff --git a/config/emulators/gamegear.conf b/config/emulators/gamegear.conf new file mode 100644 index 0000000000..1c2c0a6cd8 --- /dev/null +++ b/config/emulators/gamegear.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="gamegear" +SYSTEM_FULLNAME="Game Gear" +SYSTEM_MANUFACTURER="Sega" +SYSTEM_RELEASE="1990" +SYSTEM_HARDWARE="portable" +SYSTEM_PATH="/storage/roms/gamegear" +SYSTEM_EXTENSION=".bin .gg .zip .7z" +SYSTEM_PLATFORM="gamegear" +SYSTEM_THEME="gamegear" +SYSTEM_WIKI_PATH="gamegear" diff --git a/config/emulators/gb.conf b/config/emulators/gb.conf new file mode 100644 index 0000000000..2c77b0d85d --- /dev/null +++ b/config/emulators/gb.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="gb" +SYSTEM_FULLNAME="Game Boy" +SYSTEM_MANUFACTURER="Nintendo" +SYSTEM_RELEASE="1989" +SYSTEM_HARDWARE="portable" +SYSTEM_PATH="/storage/roms/gb" +SYSTEM_EXTENSION=".gb .gbc .zip .7z" +SYSTEM_PLATFORM="gb" +SYSTEM_THEME="gb" +SYSTEM_WIKI_PATH="gb" diff --git a/config/emulators/gba.conf b/config/emulators/gba.conf new file mode 100644 index 0000000000..c17cc1f6ec --- /dev/null +++ b/config/emulators/gba.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="gba" +SYSTEM_FULLNAME="Game Boy Advance" +SYSTEM_MANUFACTURER="Nintendo" +SYSTEM_RELEASE="2001" +SYSTEM_HARDWARE="portable" +SYSTEM_PATH="/storage/roms/gba" +SYSTEM_EXTENSION=".gba .zip .7z" +SYSTEM_PLATFORM="gba" +SYSTEM_THEME="gba" +SYSTEM_WIKI_PATH="gba" diff --git a/config/emulators/gbah.conf b/config/emulators/gbah.conf new file mode 100644 index 0000000000..a5de880adb --- /dev/null +++ b/config/emulators/gbah.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="gbah" +SYSTEM_FULLNAME="Game Boy Advance (Hacks)" +SYSTEM_MANUFACTURER="Nintendo" +SYSTEM_RELEASE="2001" +SYSTEM_HARDWARE="portable" +SYSTEM_PATH="/storage/roms/gbah" +SYSTEM_EXTENSION=".gba .zip .7z" +SYSTEM_PLATFORM="gba" +SYSTEM_THEME="gbah" +SYSTEM_WIKI_PATH="gba" diff --git a/config/emulators/gbav.conf b/config/emulators/gbav.conf new file mode 100644 index 0000000000..da832df949 --- /dev/null +++ b/config/emulators/gbav.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="gbav" +SYSTEM_FULLNAME="Game Boy Advance video" +SYSTEM_MANUFACTURER="Nintendo" +SYSTEM_RELEASE="2001" +SYSTEM_HARDWARE="portable" +SYSTEM_PATH="/storage/roms/gbav" +SYSTEM_EXTENSION=".gba .zip .7z" +SYSTEM_PLATFORM="gba" +SYSTEM_THEME="gbav" +SYSTEM_WIKI_PATH="gba" diff --git a/config/emulators/gbc.conf b/config/emulators/gbc.conf new file mode 100644 index 0000000000..eb54073728 --- /dev/null +++ b/config/emulators/gbc.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="gbc" +SYSTEM_FULLNAME="Game Boy Color" +SYSTEM_MANUFACTURER="Nintendo" +SYSTEM_RELEASE="1998" +SYSTEM_HARDWARE="portable" +SYSTEM_PATH="/storage/roms/gbc" +SYSTEM_EXTENSION=".gb .gbc .zip .7z" +SYSTEM_PLATFORM="gbc" +SYSTEM_THEME="gbc" +SYSTEM_WIKI_PATH="gbc" diff --git a/config/emulators/gbch.conf b/config/emulators/gbch.conf new file mode 100644 index 0000000000..1f435c3156 --- /dev/null +++ b/config/emulators/gbch.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="gbch" +SYSTEM_FULLNAME="Game Boy Color (Hacks)" +SYSTEM_MANUFACTURER="Nintendo" +SYSTEM_RELEASE="1998" +SYSTEM_HARDWARE="portable" +SYSTEM_PATH="/storage/roms/gbch" +SYSTEM_EXTENSION=".gb .gbc .zip .7z" +SYSTEM_PLATFORM="gbc" +SYSTEM_THEME="gbch" +SYSTEM_WIKI_PATH="gbc" diff --git a/config/emulators/gbh.conf b/config/emulators/gbh.conf new file mode 100644 index 0000000000..5cf3e9d087 --- /dev/null +++ b/config/emulators/gbh.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="gbh" +SYSTEM_FULLNAME="Game Boy (Hacks)" +SYSTEM_MANUFACTURER="Nintendo" +SYSTEM_RELEASE="1989" +SYSTEM_HARDWARE="portable" +SYSTEM_PATH="/storage/roms/gbh" +SYSTEM_EXTENSION=".gb .zip .7z" +SYSTEM_PLATFORM="gb" +SYSTEM_THEME="gbh" +SYSTEM_WIKI_PATH="gb" diff --git a/config/emulators/genesis.conf b/config/emulators/genesis.conf new file mode 100644 index 0000000000..afa81002bc --- /dev/null +++ b/config/emulators/genesis.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="genesis" +SYSTEM_FULLNAME="Genesis" +SYSTEM_MANUFACTURER="Sega" +SYSTEM_RELEASE="1989" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/genesis" +SYSTEM_EXTENSION=".bin .gen .md .sg .smd .zip .7z" +SYSTEM_PLATFORM="genesis" +SYSTEM_THEME="genesis" +SYSTEM_WIKI_PATH="genesis" diff --git a/config/emulators/genh.conf b/config/emulators/genh.conf new file mode 100644 index 0000000000..f39fe0e21b --- /dev/null +++ b/config/emulators/genh.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="genh" +SYSTEM_FULLNAME="Genesis (Hacks)" +SYSTEM_MANUFACTURER="Sega" +SYSTEM_RELEASE="1989" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/genh" +SYSTEM_EXTENSION=".bin .gen .md .sg .smd .zip .7z" +SYSTEM_PLATFORM="genesis" +SYSTEM_THEME="genh" +SYSTEM_WIKI_PATH="genesis" diff --git a/config/emulators/ggh.conf b/config/emulators/ggh.conf new file mode 100644 index 0000000000..5c7182b7e0 --- /dev/null +++ b/config/emulators/ggh.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="ggh" +SYSTEM_FULLNAME="Game Gear (Hacks)" +SYSTEM_MANUFACTURER="Sega" +SYSTEM_RELEASE="1990" +SYSTEM_HARDWARE="portable" +SYSTEM_PATH="/storage/roms/gamegearh" +SYSTEM_EXTENSION=".bin .gg .zip .7z" +SYSTEM_PLATFORM="gamegear" +SYSTEM_THEME="ggh" +SYSTEM_WIKI_PATH="gamegear" diff --git a/config/emulators/idtech.conf b/config/emulators/idtech.conf new file mode 100644 index 0000000000..0196894022 --- /dev/null +++ b/config/emulators/idtech.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="idtech" +SYSTEM_FULLNAME="iDtech" +SYSTEM_MANUFACTURER="id Software" +SYSTEM_RELEASE="1991" +SYSTEM_HARDWARE="game engine" +SYSTEM_PATH="/storage/.config/idtech" +SYSTEM_EXTENSION=".sh" +SYSTEM_PLATFORM="idtech" +SYSTEM_THEME="idtech" +SYSTEM_WIKI_PATH="idtech" diff --git a/config/emulators/imageviewer.conf b/config/emulators/imageviewer.conf new file mode 100644 index 0000000000..e1647b2496 --- /dev/null +++ b/config/emulators/imageviewer.conf @@ -0,0 +1,11 @@ +SYSTEM_NAME="imageviewer" +SYSTEM_FULLNAME="Screenshots" +SYSTEM_MANUFACTURER=" System" +SYSTEM_RELEASE="System" +SYSTEM_HARDWARE="System" +SYSTEM_PATH="/storage/roms/screenshots" +SYSTEM_EXTENSION=".jpg .jpeg .png .bmp .psd .tga .gif .hdr .pic .ppm .pgm .mkv .pdf .mp4 .avi" +SYSTEM_COMMAND="/usr/bin/true" +SYSTEM_PLATFORM="imageviewer" +SYSTEM_THEME="imageviewer" +SYSTEM_WIKI_PATH="screenshots" diff --git a/config/emulators/intellivision.conf b/config/emulators/intellivision.conf new file mode 100644 index 0000000000..99686864c8 --- /dev/null +++ b/config/emulators/intellivision.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="intellivision" +SYSTEM_FULLNAME="Intellivision" +SYSTEM_MANUFACTURER="Mattel" +SYSTEM_RELEASE="1979" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/intellivision" +SYSTEM_EXTENSION=".int .bin .rom .zip .7z" +SYSTEM_PLATFORM="intellivision" +SYSTEM_THEME="intellivision" +SYSTEM_WIKI_PATH="intellivision" diff --git a/config/emulators/ios.conf b/config/emulators/ios.conf new file mode 100644 index 0000000000..6bb6153a65 --- /dev/null +++ b/config/emulators/ios.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="ios" +SYSTEM_FULLNAME="iOS" +SYSTEM_MANUFACTURER="Apple" +SYSTEM_RELEASE="2008" +SYSTEM_HARDWARE="portable" +SYSTEM_PATH="/storage/roms/ios" +SYSTEM_EXTENSION=".ipa .app" +SYSTEM_PLATFORM="ios" +SYSTEM_THEME="ios" +SYSTEM_WIKI_PATH="ios" diff --git a/config/emulators/j2me.conf b/config/emulators/j2me.conf new file mode 100644 index 0000000000..a530023995 --- /dev/null +++ b/config/emulators/j2me.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="j2me" +SYSTEM_FULLNAME="J2ME" +SYSTEM_MANUFACTURER="Sun Microsystems" +SYSTEM_RELEASE="2002" +SYSTEM_HARDWARE="portable" +SYSTEM_PATH="/storage/roms/j2me" +SYSTEM_EXTENSION=".jar" +SYSTEM_PLATFORM="j2me" +SYSTEM_THEME="j2me" +SYSTEM_WIKI_PATH="j2me" diff --git a/config/emulators/macintosh.conf b/config/emulators/macintosh.conf new file mode 100644 index 0000000000..39e7cfd100 --- /dev/null +++ b/config/emulators/macintosh.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="macintosh" +SYSTEM_FULLNAME="Macintosh" +SYSTEM_MANUFACTURER="Apple" +SYSTEM_RELEASE="1984" +SYSTEM_HARDWARE="computer" +SYSTEM_PATH="/storage/roms/mac" +SYSTEM_EXTENSION=".dsk .img .hfv .cmd .zip" +SYSTEM_PLATFORM="macintosh" +SYSTEM_THEME="macintosh" +SYSTEM_WIKI_PATH="macintosh" diff --git a/config/emulators/mame.conf b/config/emulators/mame.conf new file mode 100644 index 0000000000..25fe59ce14 --- /dev/null +++ b/config/emulators/mame.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="mame" +SYSTEM_FULLNAME="MAME" +SYSTEM_MANUFACTURER="Arcade" +SYSTEM_RELEASE="1997" +SYSTEM_HARDWARE="arcade" +SYSTEM_PATH="/storage/roms/mame" +SYSTEM_EXTENSION=".7z .zip" +SYSTEM_PLATFORM="arcade" +SYSTEM_THEME="mame" +SYSTEM_WIKI_PATH="mame" diff --git a/config/emulators/mastersystem.conf b/config/emulators/mastersystem.conf new file mode 100644 index 0000000000..f0349a87d1 --- /dev/null +++ b/config/emulators/mastersystem.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="mastersystem" +SYSTEM_FULLNAME="Master System" +SYSTEM_MANUFACTURER="Sega" +SYSTEM_RELEASE="1985" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/mastersystem" +SYSTEM_EXTENSION=".bin .sms .zip .7z" +SYSTEM_PLATFORM="mastersystem" +SYSTEM_THEME="mastersystem" +SYSTEM_WIKI_PATH="mastersystem" diff --git a/config/emulators/megacd.conf b/config/emulators/megacd.conf new file mode 100644 index 0000000000..9c676b7247 --- /dev/null +++ b/config/emulators/megacd.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="megacd" +SYSTEM_FULLNAME="Mega CD" +SYSTEM_MANUFACTURER="Sega" +SYSTEM_RELEASE="1991" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/megacd" +SYSTEM_EXTENSION=".chd .cue .iso .m3u" +SYSTEM_PLATFORM="segacd" +SYSTEM_THEME="megacd" +SYSTEM_WIKI_PATH="segacd" diff --git a/config/emulators/megadrive-japan.conf b/config/emulators/megadrive-japan.conf new file mode 100644 index 0000000000..f9de561e1f --- /dev/null +++ b/config/emulators/megadrive-japan.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="megadrive-japan" +SYSTEM_FULLNAME="Mega Drive" +SYSTEM_MANUFACTURER="Sega" +SYSTEM_RELEASE="1988" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/megadrive-japan" +SYSTEM_EXTENSION=".bin .gen .md .sg .smd .zip .7z" +SYSTEM_PLATFORM="megadrive" +SYSTEM_THEME="megadrivejp" +SYSTEM_WIKI_PATH="genesis" diff --git a/config/emulators/megadrive.conf b/config/emulators/megadrive.conf new file mode 100644 index 0000000000..14846e884a --- /dev/null +++ b/config/emulators/megadrive.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="megadrive" +SYSTEM_FULLNAME="Mega Drive" +SYSTEM_MANUFACTURER="Sega" +SYSTEM_RELEASE="1990" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/megadrive" +SYSTEM_EXTENSION=".bin .gen .md .sg .smd .zip .7z" +SYSTEM_PLATFORM="megadrive" +SYSTEM_THEME="megadrive" +SYSTEM_WIKI_PATH="genesis" diff --git a/config/emulators/megadriveh.conf b/config/emulators/megadriveh.conf new file mode 100644 index 0000000000..425b709c3b --- /dev/null +++ b/config/emulators/megadriveh.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="megadriveh" +SYSTEM_FULLNAME="Mega Drive (Hacks)" +SYSTEM_MANUFACTURER="Sega" +SYSTEM_RELEASE="1990" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/megadriveh" +SYSTEM_EXTENSION=".bin .gen .md .sg .smd .zip .7z" +SYSTEM_PLATFORM="megadrive" +SYSTEM_THEME="megadriveh" +SYSTEM_WIKI_PATH="genesis" diff --git a/config/emulators/megaduck.conf b/config/emulators/megaduck.conf new file mode 100644 index 0000000000..1d6016e9f1 --- /dev/null +++ b/config/emulators/megaduck.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="megaduck" +SYSTEM_FULLNAME="Mega Duck" +SYSTEM_MANUFACTURER="Welback Holdings" +SYSTEM_RELEASE="1993" +SYSTEM_HARDWARE="portable" +SYSTEM_PATH="/storage/roms/megaduck" +SYSTEM_EXTENSION=".bin .zip .7z" +SYSTEM_PLATFORM="megaduck" +SYSTEM_THEME="megaduck" +SYSTEM_WIKI_PATH="megaduck" diff --git a/config/emulators/moonlight.conf b/config/emulators/moonlight.conf new file mode 100644 index 0000000000..d1e8d3b2bc --- /dev/null +++ b/config/emulators/moonlight.conf @@ -0,0 +1,11 @@ +SYSTEM_NAME="moonlight" +SYSTEM_FULLNAME="Moonlight Game Streaming" +SYSTEM_MANUFACTURER=" System" +SYSTEM_RELEASE="System" +SYSTEM_HARDWARE="System" +SYSTEM_PATH="/storage/roms/moonlight/" +SYSTEM_EXTENSION=".sh" +SYSTEM_COMMAND="/bin/sh %ROM%" +SYSTEM_PLATFORM="moonlight" +SYSTEM_THEME="moonlight" +SYSTEM_WIKI_PATH="moonlight" diff --git a/config/emulators/moto.conf b/config/emulators/moto.conf new file mode 100644 index 0000000000..5082f67f24 --- /dev/null +++ b/config/emulators/moto.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="moto" +SYSTEM_FULLNAME="MO/TO family (TO7, TO7/70, TO8, TO8D, TO9, TO9+, MO5 and MO6)" +SYSTEM_MANUFACTURER="Thomson" +SYSTEM_RELEASE="1982" +SYSTEM_HARDWARE="computer" +SYSTEM_PATH="/storage/roms/moto" +SYSTEM_EXTENSION=".fd .sap .k7 .m7 .m5 .rom" +SYSTEM_PLATFORM="moto" +SYSTEM_THEME="moto" +SYSTEM_WIKI_PATH="moto" diff --git a/config/emulators/mplayer.conf b/config/emulators/mplayer.conf new file mode 100644 index 0000000000..fcd8c48238 --- /dev/null +++ b/config/emulators/mplayer.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="mplayer" +SYSTEM_FULLNAME="Media Player" +SYSTEM_MANUFACTURER=" System" +SYSTEM_RELEASE="System" +SYSTEM_HARDWARE="System" +SYSTEM_PATH="/storage/roms/mplayer" +SYSTEM_EXTENSION=".3g2 .3gp .aac .ac3 .asf .avi .divx .dts .eac33 .f4f .f4v .flac .flv .m2p .m2ts .m3u .m4a .mka .mkv .mov .mp3 .mp4 .mpeg .mpg .mxf .ogg .ogm .opus .ps .sh .thd .ts .twi .vob .wav .webm .wma .wmv .wv .ytb" +SYSTEM_PLATFORM="mplayer" +SYSTEM_THEME="mplayer" +SYSTEM_WIKI_PATH="mplayer" diff --git a/config/emulators/msx.conf b/config/emulators/msx.conf new file mode 100644 index 0000000000..414ca45467 --- /dev/null +++ b/config/emulators/msx.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="msx" +SYSTEM_FULLNAME="MSX" +SYSTEM_MANUFACTURER="Microsoft" +SYSTEM_RELEASE="1983" +SYSTEM_HARDWARE="computer" +SYSTEM_PATH="/storage/roms/msx" +SYSTEM_EXTENSION=".dsk .mx1 .mx2 .rom .zip .7z .m3u" +SYSTEM_PLATFORM="msx" +SYSTEM_THEME="msx" +SYSTEM_WIKI_PATH="msx" diff --git a/config/emulators/msx2.conf b/config/emulators/msx2.conf new file mode 100644 index 0000000000..8ad2ea7559 --- /dev/null +++ b/config/emulators/msx2.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="msx2" +SYSTEM_FULLNAME="MSX 2" +SYSTEM_MANUFACTURER="Microsoft" +SYSTEM_RELEASE="1988" +SYSTEM_HARDWARE="computer" +SYSTEM_PATH="/storage/roms/msx2" +SYSTEM_EXTENSION=".dsk .mx1 .mx2 .rom .zip .7z .m3u" +SYSTEM_PLATFORM="msx" +SYSTEM_THEME="msx2" +SYSTEM_WIKI_PATH="msx" diff --git a/config/emulators/music.conf b/config/emulators/music.conf new file mode 100644 index 0000000000..6657dd7bf4 --- /dev/null +++ b/config/emulators/music.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="music" +SYSTEM_FULLNAME="Music Player" +SYSTEM_MANUFACTURER=" System" +SYSTEM_RELEASE="System" +SYSTEM_HARDWARE="System" +SYSTEM_PATH="/storage/.config/gmu/playlists" +SYSTEM_EXTENSION=".m3u .sh" +SYSTEM_PLATFORM="music" +SYSTEM_THEME="music" +SYSTEM_WIKI_PATH="music" diff --git a/config/emulators/n64.conf b/config/emulators/n64.conf new file mode 100644 index 0000000000..d7135a0b5d --- /dev/null +++ b/config/emulators/n64.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="n64" +SYSTEM_FULLNAME="Nintendo 64" +SYSTEM_MANUFACTURER="Nintendo" +SYSTEM_RELEASE="1996" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/n64" +SYSTEM_EXTENSION=".z64 .n64 .v64 .zip .7z" +SYSTEM_PLATFORM="n64" +SYSTEM_THEME="n64" +SYSTEM_WIKI_PATH="n64" diff --git a/config/emulators/naomi.conf b/config/emulators/naomi.conf new file mode 100644 index 0000000000..0df11462b3 --- /dev/null +++ b/config/emulators/naomi.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="naomi" +SYSTEM_FULLNAME="Naomi" +SYSTEM_MANUFACTURER="Sega" +SYSTEM_RELEASE="1998" +SYSTEM_HARDWARE="arcade" +SYSTEM_PATH="/storage/roms/naomi" +SYSTEM_EXTENSION=".lst .bin .dat .zip .7z" +SYSTEM_PLATFORM="naomi arcade" +SYSTEM_THEME="naomi" +SYSTEM_WIKI_PATH="naomi" diff --git a/config/emulators/nds.conf b/config/emulators/nds.conf new file mode 100644 index 0000000000..f6b1ffd184 --- /dev/null +++ b/config/emulators/nds.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="nds" +SYSTEM_FULLNAME="Nintendo DS" +SYSTEM_PATH="/storage/roms/nds" +SYSTEM_MANUFACTURER="Nintendo" +SYSTEM_RELEASE="2005" +SYSTEM_HARDWARE="portable" +SYSTEM_EXTENSION=".nds .zip .7z" +SYSTEM_PLATFORM="nds" +SYSTEM_THEME="nds" +SYSTEM_WIKI_PATH="nds" diff --git a/config/emulators/ndsiware.conf b/config/emulators/ndsiware.conf new file mode 100644 index 0000000000..cf23a16aee --- /dev/null +++ b/config/emulators/ndsiware.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="ndsiware" +SYSTEM_FULLNAME="Nintendo DSiWare" +SYSTEM_PATH="/storage/roms/ndsiware" +SYSTEM_MANUFACTURER="Nintendo" +SYSTEM_RELEASE="2008" +SYSTEM_HARDWARE="portable" +SYSTEM_EXTENSION=".nds .zip .7z" +SYSTEM_PLATFORM="nds" +SYSTEM_THEME="ndsiware" +SYSTEM_WIKI_PATH="nds" diff --git a/config/emulators/neocd.conf b/config/emulators/neocd.conf new file mode 100644 index 0000000000..5b806e5abf --- /dev/null +++ b/config/emulators/neocd.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="neocd" +SYSTEM_FULLNAME="Neo Geo CD" +SYSTEM_MANUFACTURER="SNK" +SYSTEM_RELEASE="1994" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/neocd" +SYSTEM_EXTENSION=".cue .iso .chd" +SYSTEM_PLATFORM="neogeocd" +SYSTEM_THEME="neogeocd" +SYSTEM_WIKI_PATH="neogeocd" diff --git a/config/emulators/neogeo.conf b/config/emulators/neogeo.conf new file mode 100644 index 0000000000..8d47c83a79 --- /dev/null +++ b/config/emulators/neogeo.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="neogeo" +SYSTEM_FULLNAME="Neo Geo" +SYSTEM_MANUFACTURER="SNK" +SYSTEM_RELEASE="1990" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/neogeo" +SYSTEM_EXTENSION=".7z .zip .neo" +SYSTEM_PLATFORM="neogeo" +SYSTEM_THEME="neogeo" +SYSTEM_WIKI_PATH="neogeo" diff --git a/config/emulators/nes.conf b/config/emulators/nes.conf new file mode 100644 index 0000000000..ddd66df9da --- /dev/null +++ b/config/emulators/nes.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="nes" +SYSTEM_FULLNAME="Nintendo Entertainment System" +SYSTEM_MANUFACTURER="Nintendo" +SYSTEM_RELEASE="1985" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/nes" +SYSTEM_EXTENSION=".nes .unif .unf .zip .7z" +SYSTEM_PLATFORM="nes" +SYSTEM_THEME="nes" +SYSTEM_WIKI_PATH="nes" diff --git a/config/emulators/nesh.conf b/config/emulators/nesh.conf new file mode 100644 index 0000000000..c6e9d36f6d --- /dev/null +++ b/config/emulators/nesh.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="nesh" +SYSTEM_FULLNAME="NES (Hacks)" +SYSTEM_MANUFACTURER="Nintendo" +SYSTEM_RELEASE="1985" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/nesh" +SYSTEM_EXTENSION=".nes .unif .unf .zip .7z" +SYSTEM_PLATFORM="nes" +SYSTEM_THEME="nesh" +SYSTEM_WIKI_PATH="nes" diff --git a/config/emulators/ngp.conf b/config/emulators/ngp.conf new file mode 100644 index 0000000000..956c23141f --- /dev/null +++ b/config/emulators/ngp.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="ngp" +SYSTEM_FULLNAME="Neo Geo Pocket" +SYSTEM_MANUFACTURER="SNK" +SYSTEM_RELEASE="1998" +SYSTEM_HARDWARE="portable" +SYSTEM_PATH="/storage/roms/ngp" +SYSTEM_EXTENSION=".ngp .ngc .zip .7z" +SYSTEM_PLATFORM="ngp" +SYSTEM_THEME="ngp" +SYSTEM_WIKI_PATH="ngp" diff --git a/config/emulators/ngpc.conf b/config/emulators/ngpc.conf new file mode 100644 index 0000000000..c43df8aa15 --- /dev/null +++ b/config/emulators/ngpc.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="ngpc" +SYSTEM_FULLNAME="Neo Geo Pocket Color" +SYSTEM_MANUFACTURER="SNK" +SYSTEM_RELEASE="1999" +SYSTEM_HARDWARE="portable" +SYSTEM_PATH="/storage/roms/ngpc" +SYSTEM_EXTENSION=".ngp .ngc .zip .7z" +SYSTEM_PLATFORM="ngpc" +SYSTEM_THEME="ngpc" +SYSTEM_WIKI_PATH="ngp" diff --git a/config/emulators/odyssey2.conf b/config/emulators/odyssey2.conf new file mode 100644 index 0000000000..4f4dd65344 --- /dev/null +++ b/config/emulators/odyssey2.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="odyssey2" +SYSTEM_FULLNAME="Odyssey 2" +SYSTEM_MANUFACTURER="Magnavox" +SYSTEM_RELEASE="1979" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/odyssey" +SYSTEM_EXTENSION=".bin .zip .7z" +SYSTEM_PLATFORM="odyssey2" +SYSTEM_THEME="odyssey2" +SYSTEM_WIKI_PATH="odyssey2" diff --git a/config/emulators/openbor.conf b/config/emulators/openbor.conf new file mode 100644 index 0000000000..6a0d9475d9 --- /dev/null +++ b/config/emulators/openbor.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="openbor" +SYSTEM_FULLNAME="OpenBOR" +SYSTEM_MANUFACTURER="Various" +SYSTEM_RELEASE="2003" +SYSTEM_HARDWARE="game engine" +SYSTEM_PATH="/storage/roms/openbor" +SYSTEM_EXTENSION=".pak" +SYSTEM_PLATFORM="openbor" +SYSTEM_THEME="openbor" +SYSTEM_WIKI_PATH="openbor" diff --git a/config/emulators/palm.conf b/config/emulators/palm.conf new file mode 100644 index 0000000000..94cc171d3f --- /dev/null +++ b/config/emulators/palm.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="palm" +SYSTEM_FULLNAME="Palm OS" +SYSTEM_MANUFACTURER="Palm, Inc." +SYSTEM_RELEASE="1996" +SYSTEM_HARDWARE="computer" +SYSTEM_PATH="/storage/roms/palm" +SYSTEM_EXTENSION=".prc .pqa .img .pdb .zip" +SYSTEM_PLATFORM="palm" +SYSTEM_THEME="palm" +SYSTEM_WIKI_PATH="palm" diff --git a/config/emulators/pc-8800.conf b/config/emulators/pc-8800.conf new file mode 100644 index 0000000000..5d85b3b35f --- /dev/null +++ b/config/emulators/pc-8800.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="pc-8800" +SYSTEM_FULLNAME="PC-8800" +SYSTEM_MANUFACTURER="NEC" +SYSTEM_RELEASE="1981" +SYSTEM_HARDWARE="computer" +SYSTEM_PATH="/storage/roms/pc88" +SYSTEM_EXTENSION=".d88 .u88 .m3u" +SYSTEM_PLATFORM="pc88" +SYSTEM_THEME="pc88" +SYSTEM_WIKI_PATH="pc88" diff --git a/config/emulators/pc-9800.conf b/config/emulators/pc-9800.conf new file mode 100644 index 0000000000..b40cd73ee9 --- /dev/null +++ b/config/emulators/pc-9800.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="pc-9800" +SYSTEM_FULLNAME="PC-9800" +SYSTEM_MANUFACTURER="NEC" +SYSTEM_RELEASE="1983" +SYSTEM_HARDWARE="computer" +SYSTEM_PATH="/storage/roms/pc98" +SYSTEM_EXTENSION=".d98 .zip .fdi .fdd .2hd .tfd .d88 .hdm .xdf .dup .hdi .thd .nhd .hdd .hdn .cmd" +SYSTEM_PLATFORM="pc98" +SYSTEM_THEME="pc98" +SYSTEM_WIKI_PATH="pc98" diff --git a/config/emulators/pc.conf b/config/emulators/pc.conf new file mode 100644 index 0000000000..2debacafb6 --- /dev/null +++ b/config/emulators/pc.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="pc" +SYSTEM_FULLNAME="DOS" +SYSTEM_MANUFACTURER="Microsoft" +SYSTEM_RELEASE="1981" +SYSTEM_HARDWARE="computer" +SYSTEM_PATH="/storage/roms/pc" +SYSTEM_EXTENSION=".com .bat .exe .dosz" +SYSTEM_PLATFORM="pc" +SYSTEM_THEME="pc" +SYSTEM_WIKI_PATH="dos" diff --git a/config/emulators/pcengine.conf b/config/emulators/pcengine.conf new file mode 100644 index 0000000000..6acd0de236 --- /dev/null +++ b/config/emulators/pcengine.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="pcengine" +SYSTEM_FULLNAME="PC Engine" +SYSTEM_MANUFACTURER="NEC" +SYSTEM_RELEASE="1987" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/pcengine" +SYSTEM_EXTENSION=".pce .bin .zip .7z" +SYSTEM_PLATFORM="pcengine" +SYSTEM_THEME="pcengine" +SYSTEM_WIKI_PATH="pcengine" diff --git a/config/emulators/pcenginecd.conf b/config/emulators/pcenginecd.conf new file mode 100644 index 0000000000..f6fea470cf --- /dev/null +++ b/config/emulators/pcenginecd.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="pcenginecd" +SYSTEM_FULLNAME="PC Engine CD" +SYSTEM_MANUFACTURER="NEC" +SYSTEM_RELEASE="1988" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/pcenginecd" +SYSTEM_EXTENSION=".cue .ccd .chd .toc .m3u" +SYSTEM_PLATFORM="pcenginecd" +SYSTEM_THEME="pce-cd" +SYSTEM_WIKI_PATH="pcengine" diff --git a/config/emulators/pcfx.conf b/config/emulators/pcfx.conf new file mode 100644 index 0000000000..2c2b0d5d65 --- /dev/null +++ b/config/emulators/pcfx.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="pcfx" +SYSTEM_FULLNAME="PC-FX" +SYSTEM_MANUFACTURER="NEC" +SYSTEM_RELEASE="1994" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/pcfx" +SYSTEM_EXTENSION=".chd .cue .ccd .toc" +SYSTEM_PLATFORM="pcfx" +SYSTEM_THEME="pcfx" +SYSTEM_WIKI_PATH="pcfx" diff --git a/config/emulators/pet.conf b/config/emulators/pet.conf new file mode 100644 index 0000000000..ffb7a3203b --- /dev/null +++ b/config/emulators/pet.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="pet" +SYSTEM_FULLNAME="Commodore PET" +SYSTEM_MANUFACTURER="Commodore" +SYSTEM_RELEASE="1977" +SYSTEM_HARDWARE="computer" +SYSTEM_PATH="/storage/roms/pet" +SYSTEM_EXTENSION=".20 .a0 .b0 .d64 .d71 .d80 .d81 .d82 .g64 .g41 .x64 .t64 .tap .prg .p00 .crt .bin .gz .d6z .d7z .d8z .g6z .g4z .x6z .cmd .m3u .vsf .nib .nbz .zip" +SYSTEM_PLATFORM="pet" +SYSTEM_THEME="pet" +SYSTEM_WIKI_PATH="pet" diff --git a/config/emulators/pico-8.conf b/config/emulators/pico-8.conf new file mode 100644 index 0000000000..0b542e2688 --- /dev/null +++ b/config/emulators/pico-8.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="pico-8" +SYSTEM_FULLNAME="PICO-8" +SYSTEM_MANUFACTURER="Lexaloffle" +SYSTEM_RELEASE="2015" +SYSTEM_HARDWARE="game engine" +SYSTEM_PATH="/storage/roms/pico-8" +SYSTEM_EXTENSION=".p8 .png" +SYSTEM_PLATFORM="pico-8" +SYSTEM_THEME="pico8" +SYSTEM_WIKI_PATH="pico-8" diff --git a/config/emulators/pokemini.conf b/config/emulators/pokemini.conf new file mode 100644 index 0000000000..eb07f8d08f --- /dev/null +++ b/config/emulators/pokemini.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="pokemini" +SYSTEM_FULLNAME="Pokémon Mini" +SYSTEM_MANUFACTURER="Nintendo" +SYSTEM_RELEASE="2001" +SYSTEM_HARDWARE="portable" +SYSTEM_PATH="/storage/roms/pokemini" +SYSTEM_EXTENSION=".min .zip .7z" +SYSTEM_PLATFORM="pokemini" +SYSTEM_THEME="pokemini" +SYSTEM_WIKI_PATH="pokemini" diff --git a/config/emulators/ports.conf b/config/emulators/ports.conf new file mode 100644 index 0000000000..af80534613 --- /dev/null +++ b/config/emulators/ports.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="ports" +SYSTEM_FULLNAME="Ports" +SYSTEM_MANUFACTURER=" System" +SYSTEM_RELEASE="System" +SYSTEM_HARDWARE="computer" +SYSTEM_PATH="/storage/roms/ports" +SYSTEM_EXTENSION=".sh" +SYSTEM_PLATFORM="pc" +SYSTEM_THEME="ports" +SYSTEM_WIKI_PATH="ports" diff --git a/config/emulators/ps2.conf b/config/emulators/ps2.conf new file mode 100644 index 0000000000..d1262d7fe8 --- /dev/null +++ b/config/emulators/ps2.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="ps2" +SYSTEM_FULLNAME="PlayStation 2" +SYSTEM_MANUFACTURER="Sony" +SYSTEM_RELEASE="2000" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/ps2" +SYSTEM_EXTENSION=".iso .mdf .nrg .bin .img .dump .gz .cso .chd" +SYSTEM_PLATFORM="ps2" +SYSTEM_THEME="ps2" +SYSTEM_WIKI_PATH="ps2" diff --git a/config/emulators/ps3.conf b/config/emulators/ps3.conf new file mode 100644 index 0000000000..e22a7cac07 --- /dev/null +++ b/config/emulators/ps3.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="ps3" +SYSTEM_FULLNAME="PlayStation 3" +SYSTEM_MANUFACTURER="Sony" +SYSTEM_RELEASE="2006" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/ps3" +SYSTEM_EXTENSION=".ps3 .psn .m3u" +SYSTEM_PLATFORM="ps3" +SYSTEM_THEME="ps3" +SYSTEM_WIKI_PATH="ps3" diff --git a/config/emulators/psp.conf b/config/emulators/psp.conf new file mode 100644 index 0000000000..d206ac6629 --- /dev/null +++ b/config/emulators/psp.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="psp" +SYSTEM_FULLNAME="PlayStation Portable" +SYSTEM_MANUFACTURER="Sony" +SYSTEM_RELEASE="2004" +SYSTEM_HARDWARE="portable" +SYSTEM_PATH="/storage/roms/psp" +SYSTEM_EXTENSION=".iso .cso .pbp .chd" +SYSTEM_PLATFORM="psp" +SYSTEM_THEME="psp" +SYSTEM_WIKI_PATH="psp" diff --git a/config/emulators/pspminis.conf b/config/emulators/pspminis.conf new file mode 100644 index 0000000000..de08649197 --- /dev/null +++ b/config/emulators/pspminis.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="pspminis" +SYSTEM_FULLNAME="PSP Minis" +SYSTEM_MANUFACTURER="Sony" +SYSTEM_RELEASE="2004" +SYSTEM_HARDWARE="portable" +SYSTEM_PATH="/storage/roms/pspminis" +SYSTEM_EXTENSION=".iso .cso .pbp .chd" +SYSTEM_PLATFORM="psp" +SYSTEM_THEME="pspminis" +SYSTEM_WIKI_PATH="psp" diff --git a/config/emulators/psvita.conf b/config/emulators/psvita.conf new file mode 100644 index 0000000000..b1a9ebd228 --- /dev/null +++ b/config/emulators/psvita.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="psvita" +SYSTEM_FULLNAME="PlayStation Vita" +SYSTEM_MANUFACTURER="Sony" +SYSTEM_RELEASE="2011" +SYSTEM_HARDWARE="portable" +SYSTEM_PATH="/storage/.config/vita3k/launcher/" +SYSTEM_EXTENSION=".sh .psvita" +SYSTEM_PLATFORM="psvita" +SYSTEM_THEME="psvita" +SYSTEM_WIKI_PATH="psvita" diff --git a/config/emulators/psx.conf b/config/emulators/psx.conf new file mode 100644 index 0000000000..0b08686f15 --- /dev/null +++ b/config/emulators/psx.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="psx" +SYSTEM_FULLNAME="PlayStation" +SYSTEM_MANUFACTURER="Sony" +SYSTEM_RELEASE="1994" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/psx" +SYSTEM_EXTENSION=".bin .cue .img .mdf .pbp .toc .cbn .m3u .ccd .chd .iso" +SYSTEM_PLATFORM="psx" +SYSTEM_THEME="psx" +SYSTEM_WIKI_PATH="psx" diff --git a/config/emulators/satellaview.conf b/config/emulators/satellaview.conf new file mode 100644 index 0000000000..46150e6a1e --- /dev/null +++ b/config/emulators/satellaview.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="satellaview" +SYSTEM_FULLNAME="Satellaview" +SYSTEM_MANUFACTURER="Nintendo" +SYSTEM_RELEASE="1995" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/satellaview" +SYSTEM_EXTENSION=".smc .fig .bs .sfc .bsx .swc .zip .7z" +SYSTEM_PLATFORM="satellaview" +SYSTEM_THEME="satellaview" +SYSTEM_WIKI_PATH="snes" diff --git a/config/emulators/saturn.conf b/config/emulators/saturn.conf new file mode 100644 index 0000000000..1db2be75ff --- /dev/null +++ b/config/emulators/saturn.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="saturn" +SYSTEM_FULLNAME="Saturn" +SYSTEM_MANUFACTURER="Sega" +SYSTEM_RELEASE="1994" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/saturn" +SYSTEM_EXTENSION=".cue .chd .iso .zip" +SYSTEM_PLATFORM="saturn" +SYSTEM_THEME="saturn" +SYSTEM_WIKI_PATH="saturn" diff --git a/config/emulators/scummvm.conf b/config/emulators/scummvm.conf new file mode 100644 index 0000000000..3d5506f740 --- /dev/null +++ b/config/emulators/scummvm.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="scummvm" +SYSTEM_FULLNAME="ScummVM" +SYSTEM_MANUFACTURER="Various" +SYSTEM_RELEASE="2001" +SYSTEM_HARDWARE="game engine" +SYSTEM_PATH="/storage/.config/scummvm/games" +SYSTEM_EXTENSION=".sh .svm .scummvm" +SYSTEM_PLATFORM="pc" +SYSTEM_THEME="scummvm" +SYSTEM_WIKI_PATH="scummvm" diff --git a/config/emulators/scv.conf b/config/emulators/scv.conf new file mode 100644 index 0000000000..4660eff079 --- /dev/null +++ b/config/emulators/scv.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="scv" +SYSTEM_FULLNAME="Super Cassette Vision" +SYSTEM_MANUFACTURER="EPOCH/YENO" +SYSTEM_RELEASE="1984" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/scv" +SYSTEM_EXTENSION=".cart .bin .rom .0 .zip" +SYSTEM_PLATFORM="scv" +SYSTEM_THEME="scv" +SYSTEM_WIKI_PATH="scv" diff --git a/config/emulators/sega32x.conf b/config/emulators/sega32x.conf new file mode 100644 index 0000000000..1e98df7830 --- /dev/null +++ b/config/emulators/sega32x.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="sega32x" +SYSTEM_FULLNAME="Sega 32X" +SYSTEM_MANUFACTURER="Sega" +SYSTEM_RELEASE="1994" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/sega32x" +SYSTEM_EXTENSION=".32x .smd .bin .md .zip .7z" +SYSTEM_PLATFORM="sega32x" +SYSTEM_THEME="sega32x" +SYSTEM_WIKI_PATH="sega32x" diff --git a/config/emulators/segacd.conf b/config/emulators/segacd.conf new file mode 100644 index 0000000000..aecaf9b614 --- /dev/null +++ b/config/emulators/segacd.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="segacd" +SYSTEM_FULLNAME="Sega CD" +SYSTEM_MANUFACTURER="Sega" +SYSTEM_RELEASE="1991" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/segacd" +SYSTEM_EXTENSION=".chd .cue .iso .m3u" +SYSTEM_PLATFORM="segacd" +SYSTEM_THEME="segacd" +SYSTEM_WIKI_PATH="segacd" diff --git a/config/emulators/segamodel3.conf b/config/emulators/segamodel3.conf new file mode 100644 index 0000000000..ffe14d749d --- /dev/null +++ b/config/emulators/segamodel3.conf @@ -0,0 +1,9 @@ +SYSTEM_NAME="segamodel3" +SYSTEM_FULLNAME="Sega Model 3" +SYSTEM_MANUFACTURER="Sega" +SYSTEM_RELEASE="1996" +SYSTEM_HARDWARE="arcade" +SYSTEM_PATH="/storage/roms/segamodel3" +SYSTEM_EXTENSION=".zip" +SYSTEM_PLATFORM="arcade" +SYSTEM_THEME="model3" diff --git a/config/emulators/sfc.conf b/config/emulators/sfc.conf new file mode 100644 index 0000000000..e66e76bb03 --- /dev/null +++ b/config/emulators/sfc.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="sfc" +SYSTEM_FULLNAME="Super Famicom" +SYSTEM_MANUFACTURER="Nintendo" +SYSTEM_RELEASE="1990" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/sfc" +SYSTEM_EXTENSION=".smc .fig .sfc .swc .zip .7z" +SYSTEM_PLATFORM="snes" +SYSTEM_THEME="sfc" +SYSTEM_WIKI_PATH="snes" diff --git a/config/emulators/sg-1000.conf b/config/emulators/sg-1000.conf new file mode 100644 index 0000000000..4924577201 --- /dev/null +++ b/config/emulators/sg-1000.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="sg-1000" +SYSTEM_FULLNAME="SG-1000" +SYSTEM_MANUFACTURER="Sega" +SYSTEM_RELEASE="1983" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/sg-1000" +SYSTEM_EXTENSION=".bin .sg .zip .7z" +SYSTEM_PLATFORM="sg-1000" +SYSTEM_THEME="sg-1000" +SYSTEM_WIKI_PATH="sg-1000" diff --git a/config/emulators/snes.conf b/config/emulators/snes.conf new file mode 100644 index 0000000000..e65a3b01cc --- /dev/null +++ b/config/emulators/snes.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="snes" +SYSTEM_FULLNAME="Super Nintendo" +SYSTEM_MANUFACTURER="Nintendo" +SYSTEM_RELEASE="1991" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/snes" +SYSTEM_EXTENSION=".smc .fig .sfc .swc .zip .7z" +SYSTEM_PLATFORM="snes" +SYSTEM_THEME="snes" +SYSTEM_WIKI_PATH="snes" diff --git a/config/emulators/snesh.conf b/config/emulators/snesh.conf new file mode 100644 index 0000000000..108c233c82 --- /dev/null +++ b/config/emulators/snesh.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="snesh" +SYSTEM_FULLNAME="Super Nintendo (Hacks)" +SYSTEM_MANUFACTURER="Nintendo" +SYSTEM_RELEASE="1991" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/snesh" +SYSTEM_EXTENSION=".smc .fig .sfc .swc .zip .7z" +SYSTEM_PLATFORM="snes" +SYSTEM_THEME="snesh" +SYSTEM_WIKI_PATH="snes" diff --git a/config/emulators/snesmsu1.conf b/config/emulators/snesmsu1.conf new file mode 100644 index 0000000000..e983775cf2 --- /dev/null +++ b/config/emulators/snesmsu1.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="snesmsu1" +SYSTEM_FULLNAME="Super NES MSU-1" +SYSTEM_MANUFACTURER="Nintendo" +SYSTEM_RELEASE="2012" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/snesmsu1" +SYSTEM_EXTENSION=".smc .fig .sfc .swc .zip .7z" +SYSTEM_PLATFORM="snesmsu1 snes" +SYSTEM_THEME="snes-msu1" +SYSTEM_WIKI_PATH="snes" diff --git a/config/emulators/st-v.conf b/config/emulators/st-v.conf new file mode 100644 index 0000000000..3c78e2a790 --- /dev/null +++ b/config/emulators/st-v.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="st-v" +SYSTEM_FULLNAME="ST-V" +SYSTEM_MANUFACTURER="Sega" +SYSTEM_RELEASE="1995" +SYSTEM_HARDWARE="arcade" +SYSTEM_PATH="/storage/roms/st-v" +SYSTEM_EXTENSION=".zip .ZIP" +SYSTEM_PLATFORM="st-v" +SYSTEM_THEME="stv" +SYSTEM_WIKI_PATH="st-v" diff --git a/config/emulators/sufami.conf b/config/emulators/sufami.conf new file mode 100644 index 0000000000..0737266213 --- /dev/null +++ b/config/emulators/sufami.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="sufami" +SYSTEM_FULLNAME="SuFami Turbo" +SYSTEM_MANUFACTURER="Bandai" +SYSTEM_RELEASE="1996" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/sufami" +SYSTEM_EXTENSION=".st .zip .7z" +SYSTEM_PLATFORM="sufami" +SYSTEM_THEME="sufami" +SYSTEM_WIKI_PATH="snes" diff --git a/config/emulators/supergrafx.conf b/config/emulators/supergrafx.conf new file mode 100644 index 0000000000..c52ae4ecbc --- /dev/null +++ b/config/emulators/supergrafx.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="supergrafx" +SYSTEM_FULLNAME="SuperGrafx" +SYSTEM_MANUFACTURER="NEC" +SYSTEM_RELEASE="1989" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/sgfx" +SYSTEM_EXTENSION=".pce .sgx .cue .ccd .chd .zip .7z" +SYSTEM_PLATFORM="supergrafx" +SYSTEM_THEME="supergrafx" +SYSTEM_WIKI_PATH="supergrafx" diff --git a/config/emulators/supervision.conf b/config/emulators/supervision.conf new file mode 100644 index 0000000000..39cd9d577f --- /dev/null +++ b/config/emulators/supervision.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="supervision" +SYSTEM_FULLNAME="Supervision" +SYSTEM_MANUFACTURER="Watara" +SYSTEM_RELEASE="1992" +SYSTEM_HARDWARE="portable" +SYSTEM_PATH="/storage/roms/supervision" +SYSTEM_EXTENSION=".sv .zip .7z" +SYSTEM_PLATFORM="supervision" +SYSTEM_THEME="supervision" +SYSTEM_WIKI_PATH="supervision" diff --git a/config/emulators/tg16.conf b/config/emulators/tg16.conf new file mode 100644 index 0000000000..6b2be777cc --- /dev/null +++ b/config/emulators/tg16.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="tg16" +SYSTEM_FULLNAME="TurboGrafx-16" +SYSTEM_MANUFACTURER="NEC" +SYSTEM_RELEASE="1989" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/tg16" +SYSTEM_EXTENSION=".pce .bin .zip .7z" +SYSTEM_PLATFORM="pcengine" +SYSTEM_THEME="tg16" +SYSTEM_WIKI_PATH="pcengine" diff --git a/config/emulators/tg16cd.conf b/config/emulators/tg16cd.conf new file mode 100644 index 0000000000..17fad539e0 --- /dev/null +++ b/config/emulators/tg16cd.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="tg16cd" +SYSTEM_FULLNAME="TurboGrafx-CD" +SYSTEM_MANUFACTURER="NEC" +SYSTEM_RELEASE="1989" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/tg16cd" +SYSTEM_EXTENSION=".cue .ccd .chd .toc .m3u" +SYSTEM_PLATFORM="pcenginecd" +SYSTEM_THEME="tg-cd" +SYSTEM_WIKI_PATH="pcengine" diff --git a/config/emulators/tic-80.conf b/config/emulators/tic-80.conf new file mode 100644 index 0000000000..c99c7d407b --- /dev/null +++ b/config/emulators/tic-80.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="tic-80" +SYSTEM_FULLNAME="TIC-80" +SYSTEM_MANUFACTURER="Nesbox" +SYSTEM_RELEASE="2017" +SYSTEM_HARDWARE="game engine" +SYSTEM_PATH="/storage/roms/tic-80" +SYSTEM_EXTENSION=".tic" +SYSTEM_PLATFORM="tic80" +SYSTEM_THEME="tic80" +SYSTEM_WIKI_PATH="tic-80" diff --git a/config/emulators/tools.conf b/config/emulators/tools.conf new file mode 100644 index 0000000000..7e4eae9971 --- /dev/null +++ b/config/emulators/tools.conf @@ -0,0 +1,11 @@ +SYSTEM_NAME="tools" +SYSTEM_FULLNAME="Tools" +SYSTEM_MANUFACTURER=" System" +SYSTEM_RELEASE="System" +SYSTEM_HARDWARE="System" +SYSTEM_PATH="/storage/.config/modules" +SYSTEM_EXTENSION=".sh" +SYSTEM_COMMAND="%RUNCOMMAND%" +SYSTEM_PLATFORM="tools" +SYSTEM_THEME="tools" +SYSTEM_WIKI_PATH="tools" diff --git a/config/emulators/triforce.conf b/config/emulators/triforce.conf new file mode 100644 index 0000000000..a16c9709b0 --- /dev/null +++ b/config/emulators/triforce.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="triforce" +SYSTEM_FULLNAME="Triforce" +SYSTEM_MANUFACTURER="Nintendo" +SYSTEM_RELEASE="2002" +SYSTEM_HARDWARE="arcade" +SYSTEM_PATH="/storage/roms/triforce" +SYSTEM_EXTENSION=".gcm .iso .gcz .ciso .wbfs .rvz .dol .m3u" +SYSTEM_PLATFORM="triforce" +SYSTEM_THEME="triforce" +SYSTEM_WIKI_PATH="triforce" diff --git a/config/emulators/uzebox.conf b/config/emulators/uzebox.conf new file mode 100644 index 0000000000..f40fc0f5e0 --- /dev/null +++ b/config/emulators/uzebox.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="uzebox" +SYSTEM_FULLNAME="Uzebox" +SYSTEM_MANUFACTURER="belogic" +SYSTEM_RELEASE="2008" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/uzebox" +SYSTEM_EXTENSION=".uze" +SYSTEM_PLATFORM="uzebox" +SYSTEM_THEME="uzebox" +SYSTEM_WIKI_PATH="uzebox" diff --git a/config/emulators/vectrex.conf b/config/emulators/vectrex.conf new file mode 100644 index 0000000000..37d05af563 --- /dev/null +++ b/config/emulators/vectrex.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="vectrex" +SYSTEM_FULLNAME="Vectrex" +SYSTEM_MANUFACTURER="Smith Engineering" +SYSTEM_RELEASE="1982" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/vectrex" +SYSTEM_EXTENSION=".bin .gam .vec .zip .7z" +SYSTEM_PLATFORM="vectrex" +SYSTEM_THEME="vectrex" +SYSTEM_WIKI_PATH="vectrex" diff --git a/config/emulators/vic20.conf b/config/emulators/vic20.conf new file mode 100644 index 0000000000..06cd3277ee --- /dev/null +++ b/config/emulators/vic20.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="vic20" +SYSTEM_FULLNAME="VIC-20" +SYSTEM_MANUFACTURER="Commodore" +SYSTEM_RELEASE="1980" +SYSTEM_HARDWARE="computer" +SYSTEM_PATH="/storage/roms/vic20" +SYSTEM_EXTENSION=".20 .a0 .b0 .d64 .d71 .d80 .d81 .d82 .g64 .g41 .x64 .t64 .tap .prg .p00 .crt .bin .gz .d6z .d7z .d8z .g6z .g4z .x6z .cmd .m3u .vsf .nib .nbz .zip" +SYSTEM_PLATFORM="vic20" +SYSTEM_THEME="vic20" +SYSTEM_WIKI_PATH="vic20" diff --git a/config/emulators/videopac.conf b/config/emulators/videopac.conf new file mode 100644 index 0000000000..30b6eec865 --- /dev/null +++ b/config/emulators/videopac.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="videopac" +SYSTEM_FULLNAME="VideoPac" +SYSTEM_MANUFACTURER="Philips" +SYSTEM_RELEASE="1978" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/videopac" +SYSTEM_EXTENSION=".bin .zip .7z" +SYSTEM_PLATFORM="videopac" +SYSTEM_THEME="videopac" +SYSTEM_WIKI_PATH="videopac" diff --git a/config/emulators/vircon32.conf b/config/emulators/vircon32.conf new file mode 100644 index 0000000000..42f82298bb --- /dev/null +++ b/config/emulators/vircon32.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="vircon32" +SYSTEM_FULLNAME="Vircon32" +SYSTEM_MANUFACTURER="Various" +SYSTEM_RELEASE="2021" +SYSTEM_HARDWARE="game engine" +SYSTEM_PATH="/storage/roms/vircon32" +SYSTEM_EXTENSION=".v32" +SYSTEM_PLATFORM="vircon32" +SYSTEM_THEME="vircon32" +SYSTEM_WIKI_PATH="vircon32" diff --git a/config/emulators/virtualboy.conf b/config/emulators/virtualboy.conf new file mode 100644 index 0000000000..4c59fae435 --- /dev/null +++ b/config/emulators/virtualboy.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="virtualboy" +SYSTEM_FULLNAME="Virtual Boy" +SYSTEM_MANUFACTURER="Nintendo" +SYSTEM_RELEASE="1995" +SYSTEM_HARDWARE="portable" +SYSTEM_PATH="/storage/roms/virtualboy" +SYSTEM_EXTENSION=".vb .zip .7z" +SYSTEM_PLATFORM="virtualboy" +SYSTEM_THEME="virtualboy" +SYSTEM_WIKI_PATH="virtualboy" diff --git a/config/emulators/wasm4.conf b/config/emulators/wasm4.conf new file mode 100644 index 0000000000..832009628b --- /dev/null +++ b/config/emulators/wasm4.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="wasm4" +SYSTEM_FULLNAME="WASM-4" +SYSTEM_MANUFACTURER="Various" +SYSTEM_RELEASE="2017" +SYSTEM_HARDWARE="game engine" +SYSTEM_PATH="/storage/roms/wasm4" +SYSTEM_EXTENSION=".wasm .wat" +SYSTEM_PLATFORM="wasm4" +SYSTEM_THEME="wasm4" +SYSTEM_WIKI_PATH="wasm-4" diff --git a/config/emulators/wii.conf b/config/emulators/wii.conf new file mode 100644 index 0000000000..e1a4bf0e19 --- /dev/null +++ b/config/emulators/wii.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="wii" +SYSTEM_FULLNAME="Wii" +SYSTEM_MANUFACTURER="Nintendo" +SYSTEM_RELEASE="2006" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/wii" +SYSTEM_EXTENSION=".gcm .iso .gcz .ciso .wbfs .rvz .dol .wad .m3u" +SYSTEM_PLATFORM="wii" +SYSTEM_THEME="wii" +SYSTEM_WIKI_PATH="wii" diff --git a/config/emulators/wiiu.conf b/config/emulators/wiiu.conf new file mode 100644 index 0000000000..9f37333e4a --- /dev/null +++ b/config/emulators/wiiu.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="wiiu" +SYSTEM_FULLNAME="Wii U" +SYSTEM_MANUFACTURER="Nintendo" +SYSTEM_RELEASE="2012" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/wiiu" +SYSTEM_EXTENSION=".wud .wux .wua .rpx" +SYSTEM_PLATFORM="wiiu" +SYSTEM_THEME="wiiu" +SYSTEM_WIKI_PATH="wiiu" diff --git a/config/emulators/wiiware.conf b/config/emulators/wiiware.conf new file mode 100644 index 0000000000..50e29bc4b7 --- /dev/null +++ b/config/emulators/wiiware.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="wiiware" +SYSTEM_FULLNAME="WiiWare" +SYSTEM_MANUFACTURER="Nintendo" +SYSTEM_RELEASE="2008" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/wiiware" +SYSTEM_EXTENSION=".gcm .iso .gcz .ciso .wbfs .rvz .dol .wad .m3u" +SYSTEM_PLATFORM="wii" +SYSTEM_THEME="wiiware" +SYSTEM_WIKI_PATH="wii" diff --git a/config/emulators/windows.conf b/config/emulators/windows.conf new file mode 100644 index 0000000000..3e9cfe420e --- /dev/null +++ b/config/emulators/windows.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="windows" +SYSTEM_FULLNAME="Windows" +SYSTEM_MANUFACTURER="Microsoft" +SYSTEM_RELEASE="System" +SYSTEM_HARDWARE="computer" +SYSTEM_PATH="/storage/roms/windows" +SYSTEM_EXTENSION=".sh" +SYSTEM_PLATFORM="pc" +SYSTEM_THEME="windows" +SYSTEM_WIKI_PATH="windows" diff --git a/config/emulators/wonderswan.conf b/config/emulators/wonderswan.conf new file mode 100644 index 0000000000..b61921d6da --- /dev/null +++ b/config/emulators/wonderswan.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="wonderswan" +SYSTEM_FULLNAME="Wonderswan" +SYSTEM_MANUFACTURER="Bandai" +SYSTEM_RELEASE="1999" +SYSTEM_HARDWARE="portable" +SYSTEM_PATH="/storage/roms/wonderswan" +SYSTEM_EXTENSION=".ws .wsc .zip .7z" +SYSTEM_PLATFORM="wonderswan" +SYSTEM_THEME="wonderswan" +SYSTEM_WIKI_PATH="wonderswan" diff --git a/config/emulators/wonderswancolor.conf b/config/emulators/wonderswancolor.conf new file mode 100644 index 0000000000..41631f79a4 --- /dev/null +++ b/config/emulators/wonderswancolor.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="wonderswancolor" +SYSTEM_FULLNAME="Wonderswan Color" +SYSTEM_MANUFACTURER="Bandai" +SYSTEM_RELEASE="2000" +SYSTEM_HARDWARE="portable" +SYSTEM_PATH="/storage/roms/wonderswancolor" +SYSTEM_EXTENSION=".ws .wsc .zip .7z" +SYSTEM_PLATFORM="wonderswancolor" +SYSTEM_THEME="wonderswancolor" +SYSTEM_WIKI_PATH="wonderswancolor" diff --git a/config/emulators/x1.conf b/config/emulators/x1.conf new file mode 100644 index 0000000000..01c16bf1d7 --- /dev/null +++ b/config/emulators/x1.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="x1" +SYSTEM_FULLNAME="X1" +SYSTEM_MANUFACTURER="Sharp" +SYSTEM_RELEASE="1982" +SYSTEM_HARDWARE="computer" +SYSTEM_PATH="/storage/roms/x1" +SYSTEM_EXTENSION=".dx1 .2d .2hd .tfd .d88 .88d .hdm .xdf .dup .tap .cmd .zip .7z" +SYSTEM_PLATFORM="x1" +SYSTEM_THEME="x1" +SYSTEM_WIKI_PATH="x1" diff --git a/config/emulators/x68000.conf b/config/emulators/x68000.conf new file mode 100644 index 0000000000..db3db6f3fd --- /dev/null +++ b/config/emulators/x68000.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="x68000" +SYSTEM_FULLNAME="x68000" +SYSTEM_MANUFACTURER="Sharp" +SYSTEM_RELEASE="1987" +SYSTEM_HARDWARE="computer" +SYSTEM_PATH="/storage/roms/x68000" +SYSTEM_EXTENSION=".dim .img .d88 .hdm .dup .2hd .xdf .hdf .cmd .m3u .zip .7z" +SYSTEM_PLATFORM="x68000" +SYSTEM_THEME="x68000" +SYSTEM_WIKI_PATH="x68000" diff --git a/config/emulators/xbox.conf b/config/emulators/xbox.conf new file mode 100644 index 0000000000..36ee74ec61 --- /dev/null +++ b/config/emulators/xbox.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="xbox" +SYSTEM_FULLNAME="Xbox" +SYSTEM_MANUFACTURER="Microsoft" +SYSTEM_RELEASE="2001" +SYSTEM_HARDWARE="console" +SYSTEM_PATH="/storage/roms/xbox" +SYSTEM_EXTENSION=".iso" +SYSTEM_PLATFORM="xbox" +SYSTEM_THEME="xbox" +SYSTEM_WIKI_PATH="xbox" diff --git a/config/emulators/zmachine.conf b/config/emulators/zmachine.conf new file mode 100644 index 0000000000..58f9e4eed0 --- /dev/null +++ b/config/emulators/zmachine.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="zmachine" +SYSTEM_FULLNAME="Z-machine" +SYSTEM_MANUFACTURER="Infocom" +SYSTEM_RELEASE="1979" +SYSTEM_HARDWARE="game engine" +SYSTEM_PATH="/storage/roms/zmachine" +SYSTEM_EXTENSION=".dat .z1 .z2 .z3 .z4 .z5 .z6 .zip" +SYSTEM_PLATFORM="z-machine" +SYSTEM_THEME="zmachine" +SYSTEM_WIKI_PATH="zmachine" diff --git a/config/emulators/zx81.conf b/config/emulators/zx81.conf new file mode 100644 index 0000000000..a9c7f3a77d --- /dev/null +++ b/config/emulators/zx81.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="zx81" +SYSTEM_FULLNAME="ZX81" +SYSTEM_MANUFACTURER="Sinclair" +SYSTEM_RELEASE="1981" +SYSTEM_HARDWARE="computer" +SYSTEM_PATH="/storage/roms/zx81" +SYSTEM_EXTENSION=".tzx .p .t81 .zip .7z" +SYSTEM_PLATFORM="zx81" +SYSTEM_THEME="zx81" +SYSTEM_WIKI_PATH="zx81" diff --git a/config/emulators/zxspectrum.conf b/config/emulators/zxspectrum.conf new file mode 100644 index 0000000000..a3754f9c0f --- /dev/null +++ b/config/emulators/zxspectrum.conf @@ -0,0 +1,10 @@ +SYSTEM_NAME="zxspectrum" +SYSTEM_FULLNAME="ZX Spectrum" +SYSTEM_MANUFACTURER="Sinclair" +SYSTEM_RELEASE="1982" +SYSTEM_HARDWARE="computer" +SYSTEM_PATH="/storage/roms/zxspectrum" +SYSTEM_EXTENSION=".tzx .tap .z80 .rzx .scl .trd .dsk .zip .7z" +SYSTEM_PLATFORM="zxspectrum" +SYSTEM_THEME="zxspectrum" +SYSTEM_WIKI_PATH="zxspectrum" diff --git a/config/functions b/config/functions new file mode 100644 index 0000000000..ed9ffd4b7f --- /dev/null +++ b/config/functions @@ -0,0 +1,1896 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +### FUNCTION HELPERS ### +# die (message, code) abort with optional message and code +die() { + if [ -n "$1" ]; then + echo -e "$1" >&2 + fi + exit "${2:-1}" +} + +onexitcleanup() { + [ $? -eq 0 ] && return + + local _BASH_COMMAND="${BASH_COMMAND}" + + if [ -n "${PKG_CURRENT_CALL}" ]; then + print_color CLR_ERROR "FAILURE: $* during ${PKG_CURRENT_CALL} (${PKG_CURRENT_CALL_TYPE})" + echo + fi + + if [ -n "${_BASH_COMMAND}" ]; then + if [[ ! ${_BASH_COMMAND} =~ ^exit\ ]] && [[ ! ${_BASH_COMMAND} =~ ^return\ ]]; then + echo "*********** FAILED COMMAND ***********" + echo "${_BASH_COMMAND}" + echo "**************************************" + fi + fi +} +[ "${NOONEXIT}" != "yes" ] && trap "onexitcleanup $0 $@" EXIT + +# 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_AUTOREMOVE) clr_actual="${boldblue}";; + + 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 +} + +print_qa_checks() { + if [ -n "${PKG_NAME}" ]; then + if [ -d "${PKG_QA_CHECKS}" ]; then + for qa_check in ${PKG_QA_CHECKS}/*; do + print_color CLR_WARNING "[QA CHECK] [${PKG_NAME}] [$(basename ${qa_check})]:\n$(cat ${qa_check})\n\n" + done + fi + fi +} + +log_qa_check() { + local qa_check_title="${1}" + local qa_check_message="${2}" + + if [ -n "${qa_check_title}" -a -n "${qa_check_message}" ]; then + if [ -n "${PKG_NAME}" ]; then + print_color CLR_WARNING "[QA CHECK] [${PKG_NAME}] [${qa_check_title}]:\n${qa_check_message}\n" + mkdir -p "${PKG_QA_CHECKS}" + echo -e "${qa_check_message}" >> ${PKG_QA_CHECKS}/${qa_check_title} + else + print_color CLR_WARNING "[QA CHECK] [general] [${qa_check_title}]:\n${qa_check_message}\n" + mkdir -p "${BUILD}/qa_checks/general" + echo -e "${qa_check_message}" >> ${BUILD}/qa_checks/general/${qa_check_title} + fi + 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 + + for path in "$@" ; do + if [ -e "${path}" -o -L "${path}" ]; then + rm -r "${path}" + else + log_qa_check "safe_remove" "path does not exist: ${path}" + fi + done +} + +### BUILDSYSTEM HELPERS ### +# check if a flag is enabled +# $1: flag-name, $2: default (yes/no), $3: ingenious check (none,only-disable,only-enable) +# return 0 if flag is enabled, otherwise 1 +flag_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 + return 0 + elif [ "$2" = "yes" ] && ! listcontains "${PKG_BUILD_FLAGS}" "-$1"; then + return 0 + else + if [ "${3:none}" = "only-enable" ]; then + die "ERROR: $1 cannot disable via PKG_BUILD_FLAGS (found in $PKG_NAME)" + fi + 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_BASE="$BUILD" + 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_BASE="" + export PKG_CONFIG_SYSROOT_DIR="" + unset PKG_CONFIG_ALLOW_SYSTEM_CFLAGS + unset PKG_CONFIG_ALLOW_SYSTEM_LIBS +} + +check_toolchain_config() { + local target=${1^^} + local toolchain=${2^^} + local var + if [ "${toolchain}" == "AUTOTOOLS" ]; then + toolchain="CONFIGURE" + fi + if [ "${toolchain}" == "CMAKE-MAKE" ]; then + toolchain="CMAKE" + fi + for var in "${!PKG_@}"; do + if [[ "${var}" =~ INSTALL_OPTS_ || "${var}" =~ _MAKE_OPTS || "${var}" =~ _TAR_COPY_OPTS ]]; then + continue + fi + if [[ "${var}" =~ _OPTS_${target}$ \ + && ! "${var}" =~ _${toolchain}_OPTS_${target}$ + || "${var}" =~ _OPTS$ && ! "${var}" =~ _${toolchain}_OPTS$ ]]; then + die "ERROR: using $2 toolchain but ${var} is configured." + fi + done +} + +# args: linker, default availability yes/no +linker_allowed() { + if flag_enabled "$1" "$2"; then + # bfd is always available, others need to be enabled with _SUPPORT="yes" + local linker_support="${1^^}_SUPPORT" + if [ "$1" = "bfd" ] || [ "${!linker_support}" = "yes" ]; then + return 0 + fi + fi + return 1 +} + +# return target linker to use for a package +get_target_linker() { + # all known linkers, in descending order of priority + # those are candidates for explicit opt-in via PKG_BUILD_FLAGS + local all_linkers="mold gold bfd" + + # linkers to choose from unless disabled via PKG_BUILD_FLAGS + local linker_candidates="${DEFAULT_LINKER:-bfd} ${all_linkers}" + + local linker + + # check if package prefers a specific linker + for linker in ${all_linkers}; do + if linker_allowed "${linker}" "no"; then + echo "${linker}" + return + fi + done + + # select linker which isn't disabled by PKG_BUILD_FLAGS + for linker in ${linker_candidates}; do + if linker_allowed "${linker}" "yes"; then + echo "${linker}" + return + fi + done + + # none of our linkers matched, use the compiler's default linker + echo "compiler_default" +} + +setup_toolchain() { + if [ "$LTO_SUPPORT" = "yes" ]; then + if flag_enabled "lto-fat" "no"; then + TARGET_CFLAGS+=" $FLAGS_OPTIM_LTO $FLAGS_OPTIM_LTO_FAT" + TARGET_CXXFLAGS+=" $FLAGS_OPTIM_LTO $FLAGS_OPTIM_LTO_FAT" + elif flag_enabled "lto" "no"; then + TARGET_CFLAGS+=" $FLAGS_OPTIM_LTO $FLAGS_OPTIM_LTO_NO_FAT" + TARGET_CXXFLAGS+=" $FLAGS_OPTIM_LTO $FLAGS_OPTIM_LTO_NO_FAT" + fi + fi + + if flag_enabled "lto-off" "no"; then + TARGET_CFLAGS+=" $FLAGS_OPTIM_LTO_OFF" + TARGET_CXXFLAGS+=" $FLAGS_OPTIM_LTO_OFF" + fi + + local linker="$(get_target_linker)" + local linker_opts="LDFLAGS_OPTIM_LINKER_${linker^^}" + + TARGET_LDFLAGS+=" ${!linker_opts}" + + # compiler optimization, descending priority: speed, size, default + if [ "${BUILD_WITH_DEBUG}" = "yes" ]; then + if [ "${SPLIT_DEBUG_INFO}" = "yes" -a "${linker}" = "gold" ]; then + TARGET_CFLAGS+=" $CFLAGS_OPTIM_DEBUG_SPLIT" + TARGET_CXXFLAGS+=" $CXXFLAGS_OPTIM_DEBUG_SPLIT" + TARGET_LDFLAGS+=" $LDFLAGS_OPTIM_DEBUG_SPLIT" + else + TARGET_CFLAGS+=" $CFLAGS_OPTIM_DEBUG" + TARGET_CXXFLAGS+=" $CXXFLAGS_OPTIM_DEBUG" + TARGET_LDFLAGS+=" $LDFLAGS_OPTIM_DEBUG" + fi + elif flag_enabled "speed" "no"; then + TARGET_CFLAGS+=" $CFLAGS_OPTIM_SPEED" + TARGET_CXXFLAGS+=" $CXXFLAGS_OPTIM_SPEED" + elif flag_enabled "size" "no"; then + TARGET_CFLAGS+=" $CFLAGS_OPTIM_SIZE" + TARGET_CXXFLAGS+=" $CXXFLAGS_OPTIM_SIZE" + else + TARGET_CFLAGS+=" $CFLAGS_OPTIM_DEFAULT" + TARGET_CXXFLAGS+=" $CXXFLAGS_OPTIM_DEFAULT" + 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="-j$CONCURRENCY_MAKE_LEVEL" + MAKEFLAGS="-j$CONCURRENCY_MAKE_LEVEL" + else + NINJA_OPTS="-j1" + MAKEFLAGS="-j1" + fi + + # verbose flag + if flag_enabled "verbose" "no"; then + NINJA_OPTS+=" -v" + MAKEFLAGS+=" V=1 VERBOSE=1" + fi + + # average load limit + if [ "${CONCURRENCY_LOAD}" != "0" ]; then + NINJA_OPTS+=" -l${CONCURRENCY_LOAD}" + MAKEFLAGS+=" -l${CONCURRENCY_LOAD}" + fi + export MAKEFLAGS + + case "$1:$2" in + target:meson|init:meson) + export DESTIMAGE="target" + 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_target + export TARGET_CC="${TARGET_PREFIX}gcc" + export TARGET_CXX="${TARGET_PREFIX}g++" + export TARGET_AR="${TARGET_PREFIX}ar" + export TARGET_STRIP="${TARGET_PREFIX}strip" + export TARGET_CFLAGS="$TARGET_CFLAGS" + export TARGET_CXXFLAGS="$TARGET_CXXFLAGS" + export TARGET_LDFLAGS="$TARGET_LDFLAGS" + 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="$SYSROOT_PREFIX" + export _python_prefix=/usr + export _python_exec_prefix=/usr + ;; + + 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_ASM_FLAGS_MINSIZEREL -DDUMMYOPT)" >> $CMAKE_CONF + echo "SET(CMAKE_CXX_FLAGS_MINSIZEREL -DDUMMYOPT)" >> $CMAKE_CONF + echo "SET(CMAKE_C_FLAGS_MINSIZEREL -DDUMMYOPT)" >> $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 + if [ "${DISPLAYSERVER}" = "x11" ]; then + if [ "${OPENGL}" = "mesa" ] || listcontains "${GRAPHIC_DRIVERS}" "nvidia"; then + echo "SET(OpenGL_GL_PREFERENCE GLVND)" >> $CMAKE_CONF + fi + fi + 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 + + # rust + export CARGO_TARGET_DIR="${PKG_BUILD}/.${TARGET_NAME}/target" + export CARGO_HOME="$(get_build_dir rust)/cargo_home" + export RUST_TARGET_PATH="${TOOLCHAIN}/lib/rustlib/" + + ;; + host:*|bootstrap:*) + export DESTIMAGE="host" + export AWK="gawk" + if [ "$1" = "host" ] && flag_enabled "local-cc" "no"; then + export CC="${LOCAL_CC}" + export CXX="${LOCAL_CXX}" + if [ -n "${LOCAL_CCACHE}" ]; then + export CCACHE_DIR="${LOCAL_CCACHE_DIR}" + export CC="${LOCAL_CCACHE} ${CC}"; + export CXX="${LOCAL_CCACHE} ${CXX}"; + fi + else + export CC="$TOOLCHAIN/bin/host-gcc" + export CXX="$TOOLCHAIN/bin/host-g++" + fi + 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_ASM_FLAGS_RELEASE -DDUMMYOPT)" >> $CMAKE_CONF + echo "SET(CMAKE_CXX_FLAGS_RELEASE -DDUMMYOPT)" >> $CMAKE_CONF + echo "SET(CMAKE_C_FLAGS_RELEASE -DDUMMYOPT)" >> $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=/ + + # rust + case "${MACHINE_HARDWARE_NAME}" in + "arm") + RUST_HOST="arm-unknown-linux-gnueabihf" + ;; + "aarch64") + RUST_HOST="aarch64-unknown-linux-gnu" + ;; + "x86_64") + RUST_HOST="x86_64-unknown-linux-gnu" + ;; + esac + + export CARGO_TARGET_DIR="${PKG_BUILD}/.${RUST_HOST}/target" + export CARGO_HOME="$(get_build_dir rust)/cargo_home" + export RUST_TARGET_PATH="${TOOLCHAIN}/lib/rustlib/" + ;; + esac +} + +create_meson_conf_host() { + local properties + properties="PKG_MESON_PROPERTIES_${1^^}" + + cat > $2 < $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 "${_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+="\n ERROR: Detected building inside /usr" + path_err_msg+="\n ${dashes}${dashes}${dashes}" + path_err_msg+="\n This is not supported by the buildsystem." + path_err_msg+="\n Please use another directory (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+="\n ERROR: Distro not found, use a valid distro or create a new config" + distro_err_msg+="\n ${dashes}${dashes}${dashes}" + distro_err_msg+="\n\n Valid distros:" + + for distros in ${DISTRO_DIR}/*; do + 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+="\n ERROR: Project not found. Use a valid project or create a new config" + project_err_msg+="\n ${dashes}${dashes}${dashes}" + project_err_msg+="\n\n Valid projects:" + + for projects in ${PROJECT_DIR}/*; do + project_err_msg+="\n - ${projects##*/}" + done + die "${project_err_msg}" + fi +} + +check_device() { + local dashes="===========================" device_err_msg + if [ -n "${DEVICE}" -a ! -d "${PROJECT_DIR}/${PROJECT}/devices" ]; then + device_err_msg="\n $dashes$dashes$dashes" + device_err_msg+="\n ERROR: You must not specify DEVICE for the $PROJECT project" + device_err_msg+="\n $dashes$dashes$dashes" + device_err_msg+="\n\n There are no devices for project: ${PROJECT}" + + die "${device_err_msg}" + elif [ \( -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+="\n ERROR: Specify a valid device for the ${PROJECT} project" + device_err_msg+="\n ${dashes}${dashes}${dashes}" + device_err_msg+="\n\n Valid devices for project: ${PROJECT}" + + for device in ${PROJECT_DIR}/${PROJECT}/devices/*; do + 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_KERNEL_PATCH_ARCH:-$TARGET_ARCH}.conf" ] && + ! ls "${linux_config_dir}/"*/linux.${TARGET_KERNEL_PATCH_ARCH:-$TARGET_ARCH}.conf &>/dev/null; then + arch_err_msg="\n ${dashes}${dashes}${dashes}" + arch_err_msg+="\n ERROR: Architecture not found. Use a valid Architecture" + arch_err_msg+="\n for your project or create a new config" + arch_err_msg+="\n ${dashes}${dashes}${dashes}" + arch_err_msg+="\n\n Valid Architectures for 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+="\n - $(echo ${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 + + # >autoconf-2.69 will call gtkdocize when used in macros + # when called with --install parameter. + # use "true" unless gtkdocsize is in the toolchain. + if [ -e "$TOOLCHAIN/bin/gtkdocize" ]; then + export GTKDOCIZE=$TOOLCHAIN/bin/gtkdocize + else + export GTKDOCIZE=true + 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 +} + +# True if this is a sequential build, false if multithreaded +is_sequential_build() { + [ "${MTWITHLOCKS}" != "yes" ] && return 0 || return 1 +} + +# arg1: filename (libtool) to remove hardcode rpath when --disable-rpath is not supported by configure +libtool_remove_rpath() { + sed -i 's|^hardcode_libdir_flag_spec=.*|hardcode_libdir_flag_spec=""|g' ${1} + sed -i 's|^runpath_var=LD_RUN_PATH|runpath_var=DIE_RPATH_DIE|g' ${1} + # Disable libtool relink — always broken in cross-compilation + # (relink tries to use host /usr/lib which is wrong arch) + sed -i 's|need_relink=yes|need_relink=no|g' ${1} +} + +### 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/build/${_PKG_NAME}-${_PKG_VERSION} + fi +} + +get_install_dir() { + get_pkg_variable "$1" PKG_INSTALL +} + +get_pkg_version() { + get_pkg_variable "$1" PKG_VERSION +} + +get_pkg_sha256() { + get_pkg_variable "$1" PKG_SHA256 +} + +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" +} + +# Return a list of sorted package names for this project/device/arch +get_all_package_names() { + sed -e 's#@?+?@##g; s#.*/##g' ${_CACHE_PACKAGE_GLOBAL} ${_CACHE_PACKAGE_LOCAL} | sort --ignore-case --unique +} + +calculate_stamp() { + local stamp data + + stamp="$PKG_DIR $PROJECT_DIR/$PROJECT/patches/$PKG_NAME $PROJECT_DIR/$PROJECT/packages/$PKG_NAME" + [ -n "$DEVICE" ] && stamp+=" $PROJECT_DIR/$PROJECT/devices/$DEVICE/patches/$PKG_NAME" + [ -n "$PKG_NEED_UNPACK" ] && stamp+=" $PKG_NEED_UNPACK" + + data="$(find -L ${stamp} -type f -not -name '.*' -print0 2>/dev/null | sed -z "s|^${ROOT}/||" | LC_ALL=C sort -zu | xargs -0 sha256sum)" + [ -n "${PKG_STAMP}" ] && data+=$'\n'"$(echo "${PKG_STAMP}" | sha256sum)" + + echo "${data}" | sha256sum | cut -d" " -f1 +} + +target_has_feature() { + listcontains "$TARGET_FEATURES" "$1" +} + +# configure variables for go +go_configure() { + unset GOARCH GOARM + 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 GOROOT=${TOOLCHAIN}/lib/golang + export PATH=${PATH}:${GOROOT}/bin + + go_configure_path + + export CGO_ENABLED=1 + export CGO_NO_EMULATION=1 + export CGO_CFLAGS=$CFLAGS +} + +go_configure_path() { + export GOLANG=${TOOLCHAIN}/lib/golang/bin/go + export GOPATH=${PKG_BUILD}/.gopath + export GOFLAGS="-modcacherw" +} + +# 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() { + PKG_CURRENT_CALL="${1}" + if [ "$(type -t ${1})" = "function" ]; then + PKG_CURRENT_CALL_TYPE="package.mk" + return 0 + else + PKG_CURRENT_CALL_TYPE="default" + return 1 + fi +} + +# Optional variant of pkg_call_exists() +# Clear PKG_CURRENT_CALL when function is not implemented. +pkg_call_exists_opt() { + if pkg_call_exists $1; then + return 0 + else + pkg_call_finish + return 1 + fi +} + +# Function to be called is set by pkg_call_exists/pkg_call_exists_opt +# Args: whatever the called function expects +# testing the exit code value of this function is likely to break set -e fail-on-error behaviour +pkg_call() { + [ -n "${PKG_CURRENT_CALL}" ] || die "$(print_color CLR_ERROR "PKG_CURRENT_CALL is not set!")" + [ -n "${PKG_NAME}" ] || die "$(print_color CLR_ERROR "FAILURE: Cannot call ${PKG_CURRENT_CALL} package function when package is not known!")" + + ${PKG_CURRENT_CALL} "${@}" + pkg_call_finish +} + +pkg_call_finish() { + PKG_CURRENT_CALL="" +} + +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 post_install_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="${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_IS_KERNEL_PKG}" -a "${PKG_NAME}" != "linux" ]; then + PKG_DEPENDS_TARGET="toolchain linux ${PKG_DEPENDS_TARGET}" + PKG_DEPENDS_UNPACK="linux ${PKG_DEPENDS_UNPACK}" + PKG_NEED_UNPACK="${LINUX_DEPENDS} ${PKG_NEED_UNPACK}" + 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 | *.tzst | *.7z | *.zip) + PKG_SOURCE_NAME=${PKG_NAME}-${PKG_VERSION}.${PKG_SOURCE_NAME##*\.} + ;; + *.tar.bz2 | *.tar.gz | *.tar.xz | *.tar.zst ) + 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/build/${PKG_NAME}-${PKG_VERSION}" + + if [[ "${1}" =~ :target$ || "${1//:/}" = "${1}" ]]; then + PKG_INSTALL="$BUILD/install_pkg/${PKG_NAME}-${PKG_VERSION}" + elif [[ "${1}" =~ :init$ ]]; then + PKG_INSTALL="$BUILD/install_init/${PKG_NAME}-${PKG_VERSION}" + fi + + PKG_QA_CHECKS="${BUILD}/qa_checks/${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_opt configure_package; then + pkg_call + 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 +} + +# arg1: python command for target +python_target_env() { + _PYTHON_HOST_PLATFORM="linux-${TARGET_ARCH}" \ + _PYTHON_PROJECT_BASE="$(get_install_dir Python3)" \ + _PYTHON_SYSCONFIGDATA_NAME="_sysconfigdata__linux_${TARGET_ARCH}-linux-gnu${TARGET_ABI}" \ + PYTHONPATH="$(get_install_dir Python3)/usr/lib/${PKG_PYTHON_VERSION}" \ + PYTHONNOUSERSITE=1 $@ +} + +### 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_KERNEL_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_initramfs_confs() { + local config_name cfg confs + + config_name="initramfs.${TARGET_KERNEL_PATCH_ARCH:-$TARGET_ARCH}.conf" + confs="$(get_pkg_directory initramfs)/config/initramfs.conf" + + for cfg in $PROJECT_DIR/$PROJECT/packages/initramfs/config/$config_name \ + $PROJECT_DIR/$PROJECT/devices/$DEVICE/packages/initramfs/config/$config_name \ + ; do + [[ $cfg =~ /devices//packages/ ]] && continue + [ -f "$cfg" ] && confs+=" $cfg" + done + + echo "$confs" +} + +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_install_dir linux)/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" +} + + +### ADDON HELPERS ### +install_binary_addon() { + local addon_id="$1" addon_so + + mkdir -p $ADDON_BUILD/$addon_id/ + cp -R $PKG_INSTALL/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_INSTALL/usr/lib/$MEDIACENTER/addons/$addon_id/$addon_so $ADDON_BUILD/$addon_id/ + chmod +x $ADDON_BUILD/$addon_id/$addon_so + fi + + if [ -d $PKG_INSTALL/usr/lib/kernel-overlays/$addon_id ] ; then + mkdir -p $ADDON_BUILD/$addon_id/kernel-overlay + cp -PR $PKG_INSTALL/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 ${DISTRONAME}"} + addon_name=${PKG_ADDON_NAME:-"$PKG_NAME"} + + for f in $PKG_DIR/source/resources/screenshot-*.{jpg,png}; do + if [ -f "$f" ]; then + screenshots+="resources/${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" + python_fix_abi "$1" + + if pkg_call_exists_opt post_install_addon; then + INSTALL="$1" pkg_call + fi +} + +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="*" + else + PASSWORD=$(openssl passwd -6 "${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 + + if [ ! -f "$target_dir/$unit_dir/$unit" ]; then + echo "WARNING: skipping non-existent service $target_dir/$unit_dir/$unit" + return 0 + fi + + 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 ### +# flocks: 94 (pkg_lock_status) +# 95 (scripts/pkgbuild) +# 96 (acquire_exclusive_lock) +# 97 (acquire_update_lock) +# 98 (pkg_lock) +# 99 (scripts/get) + +# Test build type so that these functions are a no-op during non-multithreaded builds. + +# Prevent concurrent modifications to a package during certain activities. +# With dynamic scheduling we now only need to acquire the lock +# during unpack and reconf, all other activities do not need to acquire a +# lock as there should be no concurrent access however the existing code path +# potentially generates useful logging for minimal cost so keep it. +# +# If a package is already locked and the owner is ourselves +# then assume we already have the required lock. +pkg_lock() { + is_sequential_build && 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 + + if [ "${task}" = "unpack" -o "${task}" = "reconf" ]; then + 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 + fi + + pkg_lock_status "LOCKED" "${pkg}" "${task}" +} + +# Log additional information for a locked package. +pkg_lock_status() { + is_sequential_build && return 0 + + local status="$1" pkg="$2" task="$3" msg="$4" + local this_job="${MTJOBID}" line idwidth + + [ "${THREADCOUNT}" = "0" ] && idwidth=${#MTMAXJOBS} || idwidth=2 + + ( + flock --exclusive 94 + + # Write the configured number of slots to history to improve accuracy of later analysis + if [ ! -f "${THREAD_CONTROL}/history" ]; then + printf "%s: <%06d> [%0*d/%0*d] %-7s %-7s %s %s\n" \ + "$(date +%Y-%m-%d\ %H:%M:%S.%N)" $$ ${idwidth} 0 ${#MTMAXJOBS} 0 "IDLE" "config" "info" "slots=${MTMAXSLOT};jobs=${MTMAXJOBS}" >>"${THREAD_CONTROL}/history" + fi + + printf -v line "%s: <%06d> [%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 "${this_job} ${PARALLEL_SEQ} ${task} ${pkg}" >"${THREAD_CONTROL}/locks/${pkg}.${task}.owner" + elif [ "${status}" = "UNLOCK" ]; then + rm -f "${THREAD_CONTROL}/locks/${pkg}.${task}.owner" + fi + + return 0 +} + +update_dashboard() { + is_sequential_build && return 0 + + local status="$1" pkg="$2" task="$3" msg="$4" + local line preamble num elapsed projdevarch + local boldred boldgreen boldyellow endcolor idwidth + + [ "${THREADCOUNT}" = "0" ] && idwidth=${#MTMAXSLOT} || idwidth=2 + + if [ ! -s ${THREAD_CONTROL}/status ]; then + echo "" >"${THREAD_CONTROL}/status" + echo "" >>"${THREAD_CONTROL}/status" + for i in $(seq 1 $((MTMAXSLOT))); do + printf "[%0*d/%0*d] %-7s\n" ${idwidth} ${i} ${#MTMAXJOBS} 0 "IDLE" >>"${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}@;$((MTJOBID + 2))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() { + is_sequential_build && 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() { + is_sequential_build && return 0 + + local pkg="$1" task="$2" lockfile="${3:-global}" + + pkg_lock_status "ACTIVE" "${pkg}" "${task}" + + rm "${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} +} + +# A lightweight target specific lock (eg. image, sysroot) +acquire_update_lock() { + is_sequential_build && return 0 + + exec 97>"${THREAD_CONTROL}/locks/.update.${1}" + flock --exclusive 97 +} + +release_update_lock() { + is_sequential_build && return 0 + + flock --unlock 97 2>/dev/null +} + +# store current timestamp in TIMESTAMP_xxx variable (xxx set by arg) +# timestamps are seconds.milliseconds since epoch +record_timestamp() { + if [ -n "${TRACE_BUILD_TIMING}" ]; then + typeset -g "TIMESTAMP_$1=$(date +%s.%3N)" + fi +} + +# args: text, start timestamp, end timestamp +show_timestamp_diff() { + if [ -n "${TRACE_BUILD_TIMING}" ]; then + local start="TIMESTAMP_$2" + local end="TIMESTAMP_$3" + local timediff=$(echo "${!end}-${!start}" | bc) + printf '%20s: %10.3f\n' "$1" "${timediff}" + fi +} + +# 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 0000000000..a8c86d825f --- /dev/null +++ b/config/graphic @@ -0,0 +1,167 @@ +[ -z "${OPENGL}" ] && OPENGL="no" +[ -z "${OPENGLES}" ] && OPENGLES="no" +[ -z "${VULKAN}" ] && VULKAN="no" + +if [ "${OPENGL}" = "no" ]; then + OPENGL_SUPPORT="no" +else + OPENGL_SUPPORT="yes" +fi + +if [ "${OPENGLES}" = "no" ]; then + OPENGLES_SUPPORT="no" +else + OPENGLES_SUPPORT="yes" +fi + +if [ "${VULKAN}" = "no" ]; then + VULKAN_SUPPORT="no" +else + VULKAN_SUPPORT="yes" +fi + +get_graphicdrivers() { + + # set defaults + GALLIUM_DRIVERS="softpipe" + XORG_DRIVERS="" + VULKAN_DRIVERS_CONFIG="" + VULKAN_DRIVERS_MESA="" + LLVM_SUPPORT="no" + COMPOSITE_SUPPORT="no" + VDPAU_SUPPORT="no" + VAAPI_SUPPORT="no" + V4L2_SUPPORT="no" + + if [ "${GRAPHIC_DRIVERS}" = "all" ]; then + GRAPHIC_DRIVERS="crocus i915 iris r300 r600 radeonsi nvidia nvidia-ng vmware virtio vc4" + fi + + if listcontains "${GRAPHIC_DRIVERS}" "crocus"; then + GALLIUM_DRIVERS+=" crocus" + XORG_DRIVERS+=" intel" + VULKAN_DRIVERS_MESA+=" intel_hasvk" + COMPOSITE_SUPPORT="yes" + VAAPI_SUPPORT="yes" + fi + + if listcontains "${GRAPHIC_DRIVERS}" "etnaviv"; then + GALLIUM_DRIVERS+=" etnaviv" + V4L2_SUPPORT="yes" + VAAPI_SUPPORT="no" + VDPAU_SUPPORT="no" + fi + + if listcontains "${GRAPHIC_DRIVERS}" "freedreno"; then + GALLIUM_DRIVERS+=" freedreno zink" + VULKAN_DRIVERS_MESA+=" freedreno" + V4L2_SUPPORT="yes" + VAAPI_SUPPORT="no" + VDPAU_SUPPORT="no" + fi + + if listcontains "${GRAPHIC_DRIVERS}" "i915"; then + GALLIUM_DRIVERS+=" i915" + XORG_DRIVERS+=" intel" + COMPOSITE_SUPPORT="yes" + VAAPI_SUPPORT="yes" + fi + + if listcontains "${GRAPHIC_DRIVERS}" "iris"; then + GALLIUM_DRIVERS+=" iris" + XORG_DRIVERS+=" intel" + VULKAN_DRIVERS_MESA+=" intel" + COMPOSITE_SUPPORT="yes" + VAAPI_SUPPORT="yes" + fi + + if listcontains "${GRAPHIC_DRIVERS}" "lima"; then + GALLIUM_DRIVERS+=" lima" + V4L2_SUPPORT="yes" + fi + + if listcontains "${GRAPHIC_DRIVERS}" "mali"; then + V4L2_SUPPORT="yes" + fi + + if listcontains "${GRAPHIC_DRIVERS}" "nvidia"; then + XORG_DRIVERS+=" nvidia" + VULKAN_DRIVERS_CONFIG+=" nvidia" + VDPAU_SUPPORT="yes" + fi + + if listcontains "${GRAPHIC_DRIVERS}" "nvidia-ng"; then + VULKAN_DRIVERS_CONFIG+=" nvidia-ng" + VAAPI_SUPPORT="yes" + fi + + if listcontains "${GRAPHIC_DRIVERS}" "panfrost"; then + GALLIUM_DRIVERS+=" panfrost" + VULKAN_DRIVERS_MESA+=" panfrost" + V4L2_SUPPORT="yes" + fi + + if listcontains "${GRAPHIC_DRIVERS}" "r300"; then + GALLIUM_DRIVERS+=" r300" + LLVM_SUPPORT="yes" + COMPOSITE_SUPPORT="yes" + VDPAU_SUPPORT="no" + fi + + if listcontains "${GRAPHIC_DRIVERS}" "r600"; then + GALLIUM_DRIVERS+=" r600" + LLVM_SUPPORT="yes" + COMPOSITE_SUPPORT="yes" + VDPAU_SUPPORT="no" + VAAPI_SUPPORT="yes" + fi + + if listcontains "${GRAPHIC_DRIVERS}" "radeonsi"; then + GALLIUM_DRIVERS+=" radeonsi" + XORG_DRIVERS+=" amdgpu" + VULKAN_DRIVERS_MESA+=" amd" + LLVM_SUPPORT="yes" + COMPOSITE_SUPPORT="yes" + VDPAU_SUPPORT="yes" + VAAPI_SUPPORT="yes" + fi + + if listcontains "${GRAPHIC_DRIVERS}" "vc4"; then + GALLIUM_DRIVERS+=" vc4 v3d" + VULKAN_DRIVERS_MESA+=" broadcom" + 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 + + # VDPAU Support depends on X11 + if [ ! "${DISPLAYSERVER}" = "x11" ]; then + VDPAU_SUPPORT="no" + fi + + # add lavapipe to GALLIUM_DRIVERS in llvm support enabled + if [ ${LLVM_SUPPORT} = "yes" ]; then + GALLIUM_DRIVERS+=" llvmpipe" + fi + + # add swrast to GALLIUM_DRIVERS regardless of GRAPHIC_DRIVERS value + GALLIUM_DRIVERS+=" softpipe" + + # remove duplicate entries + GALLIUM_DRIVERS="$(echo ${GALLIUM_DRIVERS} | xargs -n1 | sort -u | xargs)" + GRAPHIC_DRIVERS="$(echo ${GRAPHIC_DRIVERS} | xargs -n1 | sort -u | xargs)" + XORG_DRIVERS="$(echo ${XORG_DRIVERS} | xargs -n1 | sort -u | xargs)" + VULKAN_DRIVERS_MESA="$(echo ${VULKAN_DRIVERS_MESA} | xargs -n1 | sort -u | xargs)" + VULKAN_DRIVERS_CONFIG+=" ${VULKAN_DRIVERS_MESA}" + VULKAN_DRIVERS_CONFIG="$(echo ${VULKAN_DRIVERS_CONFIG} | xargs -n1 | sort -u | xargs)" +} diff --git a/config/mipi-generator/archr-dtbo.py b/config/mipi-generator/archr-dtbo.py new file mode 100644 index 0000000000..f958739f03 --- /dev/null +++ b/config/mipi-generator/archr-dtbo.py @@ -0,0 +1,542 @@ +#!/usr/bin/env python + +# https://pypi.org/project/fdt/ +# pip install fdt + +import os, sys +import fdt +import math + + + +def prop_default(panel, prop, default): + try: + return panel.get_property(prop).value + except: + return default + +def absfrac(x): + return abs(x - round(x)) + +def panel_to_desc(panel, args): + if 'name' in args: + g_name = args['name'] + ' ' + else: + g_name = '' + comment = args.get('comment') + acc = [] + + delays = [ + prop_default(panel, "prepare-delay-ms", 50), + prop_default(panel, "reset-delay-ms", 50), + prop_default(panel, "init-delay-ms", 50), + prop_default(panel, "enable-delay-ms", 50), + 20 # ready -- no such timeout in legacy dtbs + ] + delays_str = ','.join(map(str, delays)) + + fmtprop = panel.get_property("dsi,format") + if fmtprop: + fmt = ['rgb888', 'rgb666', 'rgb666_packed', 'rgb565'] [fmtprop.value] + else: + fmt = 'rgb888' + lanes = panel.get_property("dsi,lanes").value + flags = panel.get_property("dsi,flags").value + flags |= 0x0400 + + + timings = panel.get_subnode("display-timings") + if 'Dno' in args['flags']: + # Skip original mode (it may be broken) + native = None + else: + native = timings.get_property("native-mode").value + + # Collect vendor modes + modes = {} + orig_def_fps = None + for m in timings.nodes: + clock = round(m.get_property("clock-frequency").value/1000) + hor = [ + m.get_property("hactive").value, + m.get_property("hfront-porch").value, + m.get_property("hsync-len").value, + m.get_property("hback-porch").value, + ] + ver = [ + m.get_property("vactive").value, + m.get_property("vfront-porch").value, + m.get_property("vsync-len").value, + m.get_property("vback-porch").value, + ] + + mode = {'clock': clock, 'hor': hor, 'ver': ver} + # Some vendor DTBs (e.g. R36S-V20 2025-05-18) omit `phandle` on + # individual modes. A mode without a phandle can't be the native + # default, so skip the comparison instead of crashing. + phandle_prop = m.get_property("phandle") + is_native = phandle_prop is not None and phandle_prop.value == native + if is_native: + mode['default'] = True + + htotal = sum(hor) + vtotal = sum(ver) + fps = clock*1000/(htotal*vtotal) + + if fps not in modes: + modes[fps] = mode + if is_native: + modes[fps]['default'] = True + orig_def_fps = fps + + + try: + w = panel.get_property("width-mm").value + h = panel.get_property("height-mm").value + except: + if args.diagonal: + diag_mm = args.diagonal * 25.4 + else: + diag_mm = 3.5 * 2.54 + + randmode = list(modes.values())[0] + hactive = randmode['hor'][0] + vactive = randmode['ver'][0] + pxdiag = math.sqrt(hactive*hactive + vactive*vactive) + w = round(diag_mm * hactive/pxdiag) + h = round(diag_mm * vactive/pxdiag) + + # G size=52,70 delays=2,1,20,120,50,20 format=rgb888 lanes=4 flags=0xe03 + acc += [f"G {g_name}size={w},{h} delays={delays_str} format={fmt} lanes={lanes} flags=0x{flags:x}", ""] + + # Based on vendor modes construct a better set of modes + # https://tasvideos.org/PlatformFramerates + # 50, 60 -- generic + # */1.001 -- NTSC hack with 1001 divisor + # 50.0070 -- PAL NES https://www.nesdev.org/wiki/Cycle_reference_chart + # 60.0988 -- NTSC NES + # 54.8766 -- src/mame/toaplan/twincobr.cpp + # 57.5 -- src/mame/kaneko/snowbros.cpp + # 59.7275 -- https://en.wikipedia.org/wiki/Game_Boy + # 75.47 -- https://ws.nesdev.org/wiki/Display + def_fps = 60 + if orig_def_fps: + def_fps = orig_def_fps + common_fpss = [50/1.001, 50, 50.0070, 57.5, 59.7275, 60/1.001, 60, 60.0988, 75.47, 90, 120]; + common_fpss = [ fps for fps in common_fpss if fps != orig_def_fps] + for targetfps in [orig_def_fps] + common_fpss: + if not targetfps: + continue + warn = "" + # nearest fps to base on + greaterfps = [fps for fps in modes.keys() if fps >= targetfps] + if greaterfps == []: + basefps = max(modes.keys()) + basemode = modes[basefps] + clock = None + else: + # Trust original clock. If real clock differs, maybe make a whitelist or blacklist here + basefps = min(greaterfps) + basemode = modes[basefps] + clock = basemode['clock'] + hor = basemode['hor'].copy() + ver = basemode['ver'].copy() + # Assume original totals are minimal for the panel at this clock + htotal = sum(hor) + vtotal = sum(ver) + perfectclock = targetfps*htotal*vtotal/1000 + if not clock: + warn = "(CAN FAIL) " + # This may fail, but worth trying. Round up to 10kHz + clock = math.ceil(perfectclock/10)*10 + elif clock > 1.25*perfectclock: + # Too much deviation may cause no image + clock = math.ceil(perfectclock/10)*10 + + maxvtotal = round(vtotal*1.25) + # A little bruteforce to find a best totals for target fps + # TODO: maybe iterate over some clock values too + options = [(absfrac(c*1000/targetfps/vt), c, vt) + for vt in range(vtotal, maxvtotal+1) + for c in range(clock, round(1.25*perfectclock), 10) + if ((c*1000/targetfps/vt) >= htotal) and ((c*1000/targetfps/vt) < htotal*1.05) ] + if options == []: + acc += [f"# failed to find mode for fps={targetfps:.6f} c={clock} h={htotal} v={vtotal}"] + continue + (mindev, newclock, newvtotal) = min(options) + # construct a new mode with chosen vtotal + newhtotal = round(newclock*1000/targetfps/newvtotal) + addhtotal = newhtotal - htotal + addvtotal = newvtotal - vtotal + expectedfps = newclock*1000/newvtotal/newhtotal + hor[2] += addhtotal + ver[2] += addvtotal + hor_str = ','.join(map(str, hor)) + ver_str = ','.join(map(str, ver)) + maybe_default = " default=1" if targetfps == def_fps else "" + maybe_comment = f" # {warn}fps={expectedfps:.6f} (target={targetfps:.6f})" if comment else "" + acc += [f"M clock={newclock} horizontal={hor_str} vertical={ver_str}{maybe_default}{maybe_comment}"] + + acc += [""] + + iseq0 = panel.get_property("panel-init-sequence") + if (hasattr(iseq0, 'value')) and (isinstance(iseq0.value, (int))): + iseq = b''.join(map(lambda w : w.to_bytes(4, "big"), list(iseq0))) + else: + iseq = bytearray(iseq0) + + while iseq: + cmd = iseq[0] + wait = iseq[1] + datalen = iseq[2] + iseq = iseq[3:] + + data = iseq[0:datalen] + iseq = iseq[datalen:] + + maybe_wait = f" wait={wait}" if (wait) else "" + maybe_comment = f" # orig_cmd=0x{cmd:x}" if comment else "" + acc += [f"I seq={data.hex()}{maybe_wait}{maybe_comment}"] + + return acc + +def node_by_phandle(dt, phandle): + nodes = [p.parent + for p in dt.search('phandle', fdt.ItemType.PROP_WORDS) + if p.value == phandle] + return nodes[0] + +def resolve_phandle(dt, phandle): + p = node_by_phandle(dt, phandle) + return os.path.join(p.path, p.name) + +def add_overlay(overlay, path): + for f in range(100): + nodename = 'fragment@' + str(f) + if overlay.exist_node(nodename): + pass + else: + fragnode = fdt.Node(nodename) + if path[0] == '&': + fragnode.set_property('target', 0xffffffff) + overlay.set_property(path[1:], '/'+nodename+':target:0', path='/__fixups__') + else: + fragnode.set_property('target-path', path) + overlay.add_item(fragnode) + ovlnode = fdt.Node('__overlay__') + fragnode.append(ovlnode) + return ovlnode + +def add_fixup(overlay, label, fixup_path): + if overlay.exist_node('__fixups__'): + fixups = overlay.get_node('__fixups__') + else: + fixups = fdt.Node('__fixups__') + overlay.add_item(fixups) + prev_paths = fixups.get_property(label) + if prev_paths: + fixups.set_property(label, prev_paths.data + [fixup_path]) + else: + fixups.set_property(label, [fixup_path]) + +def add_local_fixup(overlay, parent_path, name): + overlay.set_property(name, 0, path='__local_fixups__'+parent_path) + +def add_gpio_vol_keys(dt, overlay, gpio_keys_ovl): + symbols = dt.get_node('__symbols__') + + keydata = dt.get_node('/play_joystick').get_property('key-gpios').data + pindata = dt.get_node('/pinctrl/buttons/gpio-key-pin').get_property('rockchip,pins').data + # extract volume keys from array + vol_up = keydata[14*3:15*3] + vol_up_pin = pindata[14*4:15*4] + vol_dn = keydata[15*3:16*3] + vol_dn_pin = pindata[15*4:16*4] + + gpio_path = resolve_phandle(dt, vol_up[0]) + gpio_sym = [p.name for p in symbols.props if p.value == gpio_path][0] + gpio_phandle = 0xffffffff + + pins_path = gpio_keys_ovl.path+'/__overlay__/pinctrl/btns/btn-pins-vol-overlay' + keys_path = gpio_keys_ovl.path+'/__overlay__/gpio-keys-overlay' + + pullup = 0xffffffff + overlay.set_property('rockchip,pins', vol_up_pin[0:3] + [pullup] + vol_dn_pin[0:3] + [pullup], path=pins_path) + pins_phandle = overlay.add_label('overlay_btns') + overlay.set_property('phandle', pins_phandle, path=pins_path) + add_fixup(overlay, 'pcfg_pull_up', pins_path+':rockchip,pins:12') + add_fixup(overlay, 'pcfg_pull_up', pins_path+':rockchip,pins:28') + + overlay.set_property('compatible', 'gpio-keys', path=keys_path) + overlay.set_property('autorepeat', None, path=keys_path) + overlay.set_property('pinctrl-0', pins_phandle, path=keys_path) + add_local_fixup(overlay, keys_path, 'pinctrl-0') + overlay.set_property('pinctrl-names', 'default', path=keys_path) + + overlay.set_property('gpios', [gpio_phandle, vol_up[1], vol_up[2]], path=keys_path+'/button-vol-up') + overlay.set_property('label', "VOLUMEUP", path=keys_path+'/button-vol-up') + overlay.set_property('linux,code', 0x73, path=keys_path+'/button-vol-up') + add_fixup(overlay, gpio_sym, keys_path+'/button-vol-up:gpios:0') + + overlay.set_property('gpios', [gpio_phandle, vol_dn[1], vol_dn[2]], path=keys_path+'/button-vol-down') + overlay.set_property('label', "VOLUMEDOWN", path=keys_path+'/button-vol-down') + overlay.set_property('linux,code', 0x72, path=keys_path+'/button-vol-down') + add_fixup(overlay, gpio_sym, keys_path+'/button-vol-down:gpios:0') + + +def switch_joypad_to_mymini(overlay, jp_ovl): + # My mini has separate ADC channels for axis, so we need another driver + jp_ovl.set_property('compatible', "archr-joypad") + jp_ovl.set_property('io-channel-names', ["key-RY", "key-RX", "key-LY", "key-LX"]) + jp_ovl.set_property('io-channels', [0xffffffff, 3, 0xffffffff, 3, 0xffffffff, 2, 0xffffffff, 1]) + add_fixup(overlay, 'saradc', jp_ovl.path+'/__overlay__:io-channels:0') + add_fixup(overlay, 'saradc', jp_ovl.path+'/__overlay__:io-channels:8') + add_fixup(overlay, 'saradc', jp_ovl.path+'/__overlay__:io-channels:16') + add_fixup(overlay, 'saradc', jp_ovl.path+'/__overlay__:io-channels:24') + jp_ovl.set_property('button-adc-scale', 2) + jp_ovl.set_property('button-adc-deadzone', 216) + jp_ovl.set_property('button-adc-fuzz', 54) + jp_ovl.set_property('button-adc-flat', 54) + jp_ovl.set_property('abs_x-p-tuning', 180) + jp_ovl.set_property('abs_x-n-tuning', 180) + jp_ovl.set_property('abs_y-p-tuning', 180) + jp_ovl.set_property('abs_y-n-tuning', 180) + jp_ovl.set_property('abs_rx-p-tuning', 0) + jp_ovl.set_property('abs_rx-n-tuning', 0) + jp_ovl.set_property('abs_ry-p-tuning', 0) + jp_ovl.set_property('abs_ry-n-tuning', 0) + jp_ovl.set_property('poll-interval', 10) + + +def make_dtbo(dtb_data, args): + dt = fdt.parse_dtb(dtb_data) + symbols = dt.get_node('__symbols__') + + dsipath = symbols.get_property('dsi').value + # panelpath is /dsi@ff450000/panel@0 on rk3326 and /dsi@fe060000/panel@0 on rk3566 + panelpath = dsipath + '/panel@0' + panel = dt.get_node(panelpath) + pdesc = panel_to_desc(panel, args) + + # remove empty lines as pyfdt does not like them + pdesc = [ l for l in pdesc if l != ''] + + panel_rst_gpio = panel.get_property('reset-gpios').data + gpio_sym = [p.name for p in symbols.props if p.value == resolve_phandle(dt, panel_rst_gpio[0])][0] + gpio_num = int(gpio_sym[4:]) + + # create an overlay tree + overlay = fdt.FDT() + overlay.header.version = 17 + + panel_ovl = add_overlay(overlay, '/') + panel_ovl_path = panel_ovl.path+'/__overlay__'+panelpath + overlay.set_property('compatible', 'archr,generic-dsi', path=panel_ovl_path) + overlay.set_property('panel_description', pdesc, path=panel_ovl_path) + if 'DR90' in args['flags']: + overlay.set_property('rotation', 90, path=panel_ovl_path) + elif 'DR180' in args['flags']: + overlay.set_property('rotation', 180, path=panel_ovl_path) + elif 'DR270' in args['flags']: + overlay.set_property('rotation', 270, path=panel_ovl_path) + + compat = dt.get_node('/').get_property('compatible').data[0] + args['logger'].info(f"compatible {compat}") + if 'odroidgo3' in compat: + # R36S base DTS already has reset-gpios, power-supply, backlight + # Only the panel description/timings/init-sequence are needed in overlay + return overlay.to_dtb() + + # copy reset config + pins_path = panel_ovl.path+'/__overlay__/pinctrl/gpio-lcd/lcd-rst' + overlay.set_property('reset-gpios', [0xffffffff, panel_rst_gpio[1], panel_rst_gpio[2]], path=panel_ovl_path) + add_fixup(overlay, gpio_sym, panel_ovl_path+':reset-gpios:0') + overlay.set_property('rockchip,pins', [gpio_num, panel_rst_gpio[1], 0, 0xffffffff], path=pins_path) + add_fixup(overlay, 'pcfg_pull_none', pins_path+':rockchip,pins:12') + # power supply gpio fetch (some trees do not have power-supply prop) + try: + panel_ps = dt.get_node(resolve_phandle(dt, panel.get_property('power-supply').value)) + panel_ps_gpio = panel_ps.get_property('gpio').data + gpio_sym = [p.name for p in symbols.props if p.value == resolve_phandle(dt, panel_ps_gpio[0])][0] + gpio_num = int(gpio_sym[4:]) + # power supply reg + panel_reg_path = panel_ovl.path+'/__overlay__/vcc18-lcd0' + overlay.set_property('gpio', [0xffffffff, panel_ps_gpio[1], panel_ps_gpio[2]], path=panel_reg_path) + add_fixup(overlay, gpio_sym, panel_reg_path+':gpio:0') + # power supply pinctrl + panel_ps_pin_path = panel_ovl.path+'/__overlay__/pinctrl/vcc18-lcd/vcc18-lcd-n' + overlay.set_property('rockchip,pins', [gpio_num, panel_ps_gpio[1], 0, 0xffffffff], path=panel_ps_pin_path) + add_fixup(overlay, 'pcfg_pull_none', panel_ps_pin_path+':rockchip,pins:12') + except: + pass + # some devices (e.g. R36s clone) have enable-gpios defined + try: + panel_en_gpio = panel.get_property('enable-gpios').data + gpio_sym = [p.name for p in symbols.props if p.value == resolve_phandle(dt, panel_en_gpio[0])][0] + overlay.set_property('enable-gpios', [0xffffffff, panel_en_gpio[1], panel_en_gpio[2]], path=panel_ovl_path) + add_fixup(overlay, gpio_sym, panel_ovl_path+':enable-gpios:0') + except: + pass + + + # If the vendor DTB explicitly disables /adc-keys, mirror that decision + # in the overlay. We deliberately do NOT treat "/adc-keys absent" as + # MyMini hardware: most ArchR vendor DTBs are partial extractions that + # don't ship that node even when the underlying board has K36-style + # single-ADC sticks. Auto-detecting MyMini from absence broke input on + # every K36 R36S in our 43-board set. Default is K36 unless JPmm is + # explicitly requested or /adc-keys is present-but-disabled. + need_adckeys_disable = False + if dt.exist_node('/adc-keys'): + adckeys_orig = dt.get_node('/adc-keys') + adckeys_status = adckeys_orig.get_property('status') + if (adckeys_status) and (adckeys_status.value == 'disabled'): + need_adckeys_disable = True + if need_adckeys_disable: + noadck_ovl = add_overlay(overlay, '/') + overlay.set_property('dtbo_comment', 'deliberately-disabled-adc-keys', path=noadck_ovl.path+'/__overlay__/adc-keys') + overlay.set_property('status', 'disabled', path=noadck_ovl.path+'/__overlay__/adc-keys') + args['logger'].info(f"disabled adc-keys") + # TODO: extract GPIO keys from play_joystick.key-gpios[14..15] + if dt.exist_node('/play_joystick'): + add_gpio_vol_keys(dt, overlay, noadck_ovl) + else: + adck_ovl = add_overlay(overlay, '/') + overlay.set_property('status', 'okay', path=adck_ovl.path+'/__overlay__/adc-keys') + + + # joypad overlay always present to simplify different options + jp_ovl = add_overlay(overlay, '&joypad') + + # If not explicitly specified, disabled adc-keys imply multi-adc MyMini-style joypad + if 'JPk36' in args['flags']: + pass + elif ('JPmm' in args['flags']) or (need_adckeys_disable): + args['logger'].info(f"My Mini joypad tweaks on {jp_ovl.path}") + switch_joypad_to_mymini(overlay, jp_ovl) + + # Left stick was inverted by default, so invert inversion here + if ('LSi' not in args['flags']) ^ (need_adckeys_disable): + jp_ovl.set_property('invert-absx', 1) + jp_ovl.set_property('invert-absy', 1) + args['logger'].info(f"left stick un-inverted on {jp_ovl.path}") + else: + args['logger'].info(f"left stick left inverted") + + # If needed, invert right stick + if 'RSi' in args['flags']: + jp_ovl.set_property('invert-absrx', 1) + jp_ovl.set_property('invert-absry', 1) + args['logger'].info(f"invert right stick on {jp_ovl.path}") + + + try: + snd = dt.get_node('/rk817-sound') + + # fetch raw hp-det-gpio = <0x6f 0x16 0x00>; + hpdet = snd.get_property('hp-det-gpio').data + hp_det = dt.get_node('/pinctrl/headphone/hp-det') + hp_det_pins = hp_det.get_property('rockchip,pins') + hp_det_pull_node = node_by_phandle(dt, hp_det_pins[3]) + # resolve <0x6f> into '/pinctrl/gpio2@ff260000' + hpdet_gpio_path = resolve_phandle(dt, hpdet[0]) + # find symbol 'gpio2' for path '/pinctrl/gpio2@ff260000' + gpiosyms = [p.name for p in symbols.props if p.value == hpdet_gpio_path] + gpio_sym = gpiosyms[0] + + # on success, add overlay + hpdet_ovl = add_overlay(overlay, '/') + + force_simple_audio_routing = ('SRs' in args['flags']) + + # Detect amplifier GPIO. Direct `spk-con-gpio` on the sound node is + # the legacy path. Newer R36S clones (post-2025-03-18 batches) wire + # the amplifier through `rockchip,codec/spk-ctl-gpios` instead, so + # we follow the codec phandle as a fallback. + amp_gpio = None + if not force_simple_audio_routing: + if snd.exist_property('spk-con-gpio'): + amp_gpio = snd.get_property('spk-con-gpio').data + elif snd.exist_property('rockchip,codec'): + snd_codec_ph = snd.get_property('rockchip,codec').value + snd_codec_path = resolve_phandle(dt, snd_codec_ph) + snd_codec = dt.get_node(snd_codec_path) + if snd_codec.exist_property('spk-ctl-gpios'): + amp_gpio = snd_codec.get_property('spk-ctl-gpios').data + + # Determine preset, configure amplifier if needed + if amp_gpio: + rk817_path = hpdet_ovl.path+'/__overlay__/rk817-sound-amplified' + amp_gpio_sym = [p.name for p in symbols.props if p.value == resolve_phandle(dt, amp_gpio[0])][0] + gpio_num = int(amp_gpio_sym[4:]) + args['logger'].info(f"spk-con-gpio {amp_gpio_sym} {amp_gpio[1]} on {hpdet_ovl.path}") + + amp_path = hpdet_ovl.path+'/__overlay__/audio-amplifier' + overlay.set_property('enable-gpios', [0xffffffff, amp_gpio[1], amp_gpio[2]], path=amp_path) + add_fixup(overlay, amp_gpio_sym, amp_path+':enable-gpios:0') + + amp_pc_path = hpdet_ovl.path+'/__overlay__/pinctrl/speaker/spk-amp-enable-h' + overlay.set_property('rockchip,pins', [gpio_num, amp_gpio[1], 0, 0xffffffff], path=amp_pc_path) + add_fixup(overlay, 'pcfg_pull_none', amp_pc_path+':rockchip,pins:12') + else: + rk817_path = hpdet_ovl.path+'/__overlay__/rk817-sound-simple' + + overlay.set_property('status', 'okay', path=rk817_path) + # for some reason hp detection polarity needs to be inverted on some devices + if 'HPi' in args['flags']: + if hpdet[2] == 0: + hpdet[2] = 1 + else: + hpdet[2] = 0 + overlay.set_property('simple-audio-card,hp-det-gpio', [0xffffffff, hpdet[1], hpdet[2]], path=rk817_path) + add_fixup(overlay, gpio_sym, rk817_path+':simple-audio-card,hp-det-gpio:0') + pins_path = hpdet_ovl.path+'/__overlay__/pinctrl/headphone/hp-det' + overlay.set_property('rockchip,pins', hp_det_pins[0:3] + [0xffffffff], path=pins_path) + # Restore bias reference + if hp_det_pull_node.exist_property('bias-pull-down'): + add_fixup(overlay, 'pcfg_pull_down', pins_path+':rockchip,pins:12') + else: + add_fixup(overlay, 'pcfg_pull_up', pins_path+':rockchip,pins:12') + args['logger'].info(f"hp-det-gpio {gpiosyms[0]} on {hpdet_ovl.path}") + + except Exception as e: + args['logger'].info(e) + + # Move fixups to the very end (if any) + if overlay.exist_node('__fixups__'): + fixups = overlay.get_node('__fixups__') + overlay.remove_node('__fixups__') + overlay.add_item(fixups) + + if overlay.exist_node('__local_fixups__'): + fixups = overlay.get_node('__local_fixups__') + overlay.remove_node('__local_fixups__') + overlay.add_item(fixups) + + # send the overlay to output + return overlay.to_dtb() + + +if __name__ == "__main__": + import argparse, logging + logging.basicConfig(level=logging.INFO) + logger = logging.getLogger("dtbo") + + parser = argparse.ArgumentParser(description="Generate a dtbo from a stock dtb") + parser.add_argument(dest="src", help="input stock dtb path", metavar="/path/to/stock.dtb") + parser.add_argument(dest="opts", help="dtbo options", nargs='?', metavar="LSi-HPi", default="") + parser.add_argument("-o", "--output", help="output (dtbo) path") + args = parser.parse_args() + + with open(args.src, 'rb') as f: + content = f.read() + + flags = args.opts.split('-') + flags = [ f for f in flags if f != ''] + dtbo = make_dtbo(content, {'flags': flags, 'logger': logger}) + + if args.output: + with open(args.output, 'wb') as f: + f.write(dtbo) + else: + sys.stdout.buffer.write(dtbo) diff --git a/config/mipi-generator/generator.sh b/config/mipi-generator/generator.sh new file mode 100755 index 0000000000..d7f020733e --- /dev/null +++ b/config/mipi-generator/generator.sh @@ -0,0 +1,184 @@ +#!/bin/bash + +#============================================================================== +# Arch R - Generate Panel DTBO Overlays +#============================================================================== +# Each MB (motherboard) variant lives under config/archr-dts/// +# and ships its kernel DTB as rk3326-r36s-linux.dtb. We extract one DTBO per +# MB folder, named after the folder (spaces → underscores) so users can pick +# the exact MB instead of a generic "Panel N" that historically collided +# across distinct boards. +# +# Sources: +# config/archr-dts/clone//rk3326-r36s-linux.dtb +# config/archr-dts/original//rk3326-r36s-linux.dtb +# config/archr-dts/soysauce//rk3326-r36s-linux.dtb +# +# Outputs: +# config/mipi-generator/output/clone/.dtbo +# config/mipi-generator/output/original/.dtbo +# config/mipi-generator/output/soysauce/.dtbo +#============================================================================== + +set +e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ROOT_DIR="$(dirname "$(dirname "$SCRIPT_DIR")")" +DTS_ROOT="${ROOT_DIR}/config/archr-dts" +OUTPUT_BASE="${MIPI_OUT:-${ROOT_DIR}/config/mipi-generator/output}" +DTBO_TOOL="$SCRIPT_DIR/archr-dtbo.py" +INPUT_DTB_NAME="rk3326-r36s-linux.dtb" + +# Subdevices to process. Order matters only for log readability. +SUBDEVICES=(original clone soysauce) + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' +log() { echo -e "${GREEN}[PANEL]${NC} $1"; } +warn() { echo -e "${YELLOW}[PANEL] WARNING:${NC} $1"; } +error() { echo -e "${RED}[PANEL] ERROR:${NC} $1"; exit 1; } + +command -v dtc &>/dev/null || error "dtc not found" +command -v python3 &>/dev/null || error "python3 not found" +python3 -c "import fdt" 2>/dev/null || error "Python fdt package not found. Install with: pip3 install fdt" +[ -f "$DTBO_TOOL" ] || error "archr-dtbo.py not found at: $DTBO_TOOL" + +GENERATED=0 +FAILED=0 +SKIPPED=0 + +# Map "G80C-MB V1.1-20250319 Panel 8" → "G80C-MB_V1.1-20250319_Panel_8". +# Spaces are the only character that needs taming; dashes, dots and digits +# are already filename-safe. +sanitize_mb_name() { + echo "${1// /_}" +} + +generate_overlay() { + local dtb="$1" + local out="$2" + local label="$3" + local flags="$4" # optional, e.g. "JPmm-SRs" + + local cmd=(python3 "$DTBO_TOOL" "$dtb") + [ -n "$flags" ] && cmd+=("$flags") + cmd+=(-o "$out") + + if "${cmd[@]}" 2>/dev/null; then + local sz=$(stat -c%s "$out") + log " OK: $(basename "$out") (${sz} bytes) [$label]" + GENERATED=$((GENERATED + 1)) + else + warn " archr-dtbo.py failed: $(basename "$out")" + FAILED=$((FAILED + 1)) + return 1 + fi +} + +# 6 variants per panel cover every joypad×audio override the user can pick +# from the flasher UI. Dno (skip vendor mode) is applied as a runtime string +# transform on panel_description so we don't need to multiply this set by 2. +# +# Default-joypad mapping: every R36S board we ship is K36-style except for +# the Y3506 family ("soysauce") which uses MyMini-style multi-ADC sticks. +# Our vendor DTBs are partial extracts that don't expose /adc-keys, so the +# generator can't auto-detect — we baked the choice in here per subdevice. +# +# Suffix pairs: | +# "" | "" -> default for the subdevice +# "JPk36" | "_JPk36" -> force K36 joypad +# "JPmm" | "_JPmm" -> force MyMini joypad +# "SRs" | "_SRs" -> force simple audio routing +# "JPk36-SRs" | "_JPk36_SRs" -> K36 joypad + simple audio +# "JPmm-SRs" | "_JPmm_SRs" -> MyMini joypad + simple audio +VARIANT_FLAGS_K36=("" "JPk36" "JPmm" "SRs" "JPk36-SRs" "JPmm-SRs") +VARIANT_SUFFIX_K36=("" "_JPk36" "_JPmm" "_SRs" "_JPk36_SRs" "_JPmm_SRs") +VARIANT_FLAGS_MM=("JPmm" "JPk36" "JPmm" "JPmm-SRs" "JPk36-SRs" "JPmm-SRs") +VARIANT_SUFFIX_MM=("" "_JPk36" "_JPmm" "_SRs" "_JPk36_SRs" "_JPmm_SRs") + +# Pick the variant flag/suffix arrays that match each subdevice's expected +# default. Names are matched literally against $sd. +default_variant_arrays() { + case "$1" in + soysauce) + echo "MM" + ;; + *) + echo "K36" + ;; + esac +} + +process_subdevice() { + local sd="$1" + local src_dir="${DTS_ROOT}/${sd}" + local out_dir="${OUTPUT_BASE}/${sd}" + + if [ ! -d "$src_dir" ]; then + warn "Subdevice source dir missing: $src_dir" + return + fi + + mkdir -p "$out_dir" + + log "" + log "=== ${sd} panel overlays ===" + log "Source: $src_dir" + log "Output: $out_dir" + + local kind="$(default_variant_arrays "$sd")" + local -n flags_arr="VARIANT_FLAGS_${kind}" + local -n suffix_arr="VARIANT_SUFFIX_${kind}" + log "Default joypad: ${kind} (${flags_arr[0]:-K36})" + + local count=0 + # Sort makes output deterministic across filesystems. + while IFS= read -r mb_dir; do + local mb_name="$(basename "$mb_dir")" + local input_dtb="${mb_dir}/${INPUT_DTB_NAME}" + + if [ ! -f "$input_dtb" ]; then + warn " ${mb_name}: missing ${INPUT_DTB_NAME}" + SKIPPED=$((SKIPPED + 1)) + continue + fi + + local sanitized="$(sanitize_mb_name "$mb_name")" + log " ${mb_name}" + + local i + for i in "${!flags_arr[@]}"; do + local flags="${flags_arr[$i]}" + local suffix="${suffix_arr[$i]}" + local out_file="${out_dir}/${sanitized}${suffix}.dtbo" + generate_overlay "$input_dtb" "$out_file" "${sd}/${mb_name}${suffix}" "$flags" + done + count=$((count + 1)) + done < <(find "$src_dir" -mindepth 1 -maxdepth 1 -type d | sort) + + if [ "$count" -eq 0 ]; then + warn "${sd}: no MB folders found" + fi +} + +mkdir -p "$OUTPUT_BASE" + +for sd in "${SUBDEVICES[@]}"; do + process_subdevice "$sd" +done + +log "" +log "=== Panel Generation Complete ===" +log "Generated: ${GENERATED} Failed: ${FAILED} Skipped: ${SKIPPED}" + +for sd in "${SUBDEVICES[@]}"; do + out_dir="${OUTPUT_BASE}/${sd}" + [ -d "$out_dir" ] || continue + log "" + log "${sd} overlays: ${out_dir}/" + ls -1 "$out_dir"/*.dtbo 2>/dev/null | while read -r f; do + log " $(basename "$f") ($(stat -c%s "$f") bytes)" + done +done diff --git a/config/multithread b/config/multithread new file mode 100644 index 0000000000..dcc8911be4 --- /dev/null +++ b/config/multithread @@ -0,0 +1,72 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +THREADCOUNT=${THREADCOUNT:-$(nproc)} + +start_multithread_build() { + local buildopts result=0 + + # init thread control folder + rm -rf "${THREAD_CONTROL}" + mkdir -p "${THREAD_CONTROL}/locks" + echo -1 >"${THREAD_CONTROL}/progress.prev" + echo 0 >"${THREAD_CONTROL}/progress" + touch "${THREAD_CONTROL}/status" + + # Increase file descriptors if building one thread/package + [ "${THREADCOUNT}" = "0" ] && ulimit -n ${ULIMITN:-10240} + + # create a single log file by default for a single threaded build (or the builder is a masochist) + if [ ${THREADCOUNT} -eq 1 -a "${ONELOG,,}" != "no" ] || [ "${ONELOG,,}" = "yes" ]; then + buildopts+=" --no-log-burst" + else + mkdir -p "${THREAD_CONTROL}/logs" + buildopts+=" --log-burst" + fi + buildopts+=" --log-combine ${LOGCOMBINE:-always}" + + [ "${AUTOREMOVE}" = "yes" ] && buildopts+=" --auto-remove" + + # When building addons, don't halt on error - keep building all packages/addons + [ "${MTADDONBUILD}" = "yes" ] && buildopts+=" --continue-on-error" || buildopts+=" --halt-on-error" + + [ "${MTPROGRESS}" = "yes" ] && buildopts+=" --progress" + [ "${MTVERBOSE}" = "yes" ] && buildopts+=" --verbose" + [ "${MTDEBUG}" = "yes" ] && buildopts+=" --debug" + if [ "${DISABLE_COLORS}" = "yes" ]; then + buildopts+=" --colors=never" + else + buildopts+=" --colors=${MTCOLORS:-auto}" + fi + [ "${MTBOOKENDS}" = "no" ] && buildopts+=" --without-bookends" || buildopts+=" --with-bookends" + [ "${MTIMMEDIATE}" = "no" ] && buildopts+=" --fail-after-active" || buildopts+=" --fail-immediately" + + buildopts+=" --stats-interval ${MTINTERVAL:-60}" + + # pipefail: return value of a pipeline is the value of the last (rightmost) command to exit with a non-zero status + set -o pipefail + + ${SCRIPTS}/pkgjson | ${SCRIPTS}/genbuildplan.py --show-wants --with-json "${THREAD_CONTROL}"/plan.json \ + --build ${@} > "${THREAD_CONTROL}"/plan || result=1 + + if [ ${result} -eq 0 ]; then + save_build_config + + # export the following vars so that they will be available to subprocesses of pkgbuilder.py + export ROOT SCRIPTS THREAD_CONTROL + + MTBUILDSTART=$(date +%s) MTWITHLOCKS=yes ${SCRIPTS}/pkgbuilder.py \ + --plan "${THREAD_CONTROL}"/plan.json \ + --joblog "${THREAD_CONTROL}"/joblog \ + --loadstats "${THREAD_CONTROL}"/loadstats \ + --max-procs ${THREADCOUNT} ${buildopts} || result=1 + + [ ${result} -eq 0 -a -f "${THREAD_CONTROL}"/history ] && echo && cat "${THREAD_CONTROL}"/history | ${ROOT}/tools/mtstats.py + + 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 0000000000..0925fbdff8 Binary files /dev/null and b/config/noobs/marketing/slides/A.png differ diff --git a/config/noobs/marketing/slides/B.png b/config/noobs/marketing/slides/B.png new file mode 100644 index 0000000000..b9266a9f2b Binary files /dev/null and b/config/noobs/marketing/slides/B.png differ diff --git a/config/noobs/marketing/slides/C.png b/config/noobs/marketing/slides/C.png new file mode 100644 index 0000000000..2882069a80 Binary files /dev/null and b/config/noobs/marketing/slides/C.png differ diff --git a/config/noobs/marketing/slides/D.png b/config/noobs/marketing/slides/D.png new file mode 100644 index 0000000000..f06b06993a Binary files /dev/null and b/config/noobs/marketing/slides/D.png differ diff --git a/config/noobs/marketing/slides/E.png b/config/noobs/marketing/slides/E.png new file mode 100644 index 0000000000..a993980af4 Binary files /dev/null and b/config/noobs/marketing/slides/E.png differ diff --git a/config/noobs/marketing/slides/noobs.psd b/config/noobs/marketing/slides/noobs.psd new file mode 100644 index 0000000000..2e1e7eb69e Binary files /dev/null and b/config/noobs/marketing/slides/noobs.psd differ diff --git a/config/noobs/marketing/slides_vga/A.png b/config/noobs/marketing/slides_vga/A.png new file mode 100644 index 0000000000..40b96b3a69 Binary files /dev/null and b/config/noobs/marketing/slides_vga/A.png differ diff --git a/config/noobs/marketing/slides_vga/B.png b/config/noobs/marketing/slides_vga/B.png new file mode 100644 index 0000000000..d6657d3f5b Binary files /dev/null and b/config/noobs/marketing/slides_vga/B.png differ diff --git a/config/noobs/marketing/slides_vga/C.png b/config/noobs/marketing/slides_vga/C.png new file mode 100644 index 0000000000..ae61c976a5 Binary files /dev/null and b/config/noobs/marketing/slides_vga/C.png differ diff --git a/config/noobs/marketing/slides_vga/D.png b/config/noobs/marketing/slides_vga/D.png new file mode 100644 index 0000000000..50110992c1 Binary files /dev/null and b/config/noobs/marketing/slides_vga/D.png differ diff --git a/config/noobs/marketing/slides_vga/E.png b/config/noobs/marketing/slides_vga/E.png new file mode 100644 index 0000000000..c06548a09c Binary files /dev/null and b/config/noobs/marketing/slides_vga/E.png differ 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 0000000000..22820db05a Binary files /dev/null and b/config/noobs/marketing/slides_vga/noobs_vga.psd differ diff --git a/config/noobs/os.json b/config/noobs/os.json new file mode 100644 index 0000000000..5b5cbbb413 --- /dev/null +++ b/config/noobs/os.json @@ -0,0 +1,11 @@ +{ + "name": "@DISTRONAME@_@PROJECT@", + "version": "@DISTRO_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 0000000000..052e6138d9 --- /dev/null +++ b/config/noobs/partition_setup.sh @@ -0,0 +1,54 @@ +#!/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 @EXTRA_CMDLINE@" >$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 0000000000..591b255ded --- /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": 120, + "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 0000000000..0709178d9f --- /dev/null +++ b/config/optimize @@ -0,0 +1,102 @@ +# Linker hash-style is set to gnu via gcc default +LD_OPTIM="-Wl,--as-needed" + +TARGET_CPPFLAGS="" +TARGET_CFLAGS="$TARGET_CFLAGS -Wall -pipe $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=x86-64 -mtune=generic -O2 -Wall -pipe -std=gnu17 -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="-flto" +FLAGS_OPTIM_LTO_NO_FAT="-fno-fat-lto-objects" +FLAGS_OPTIM_LTO_FAT="-ffat-lto-objects" +FLAGS_OPTIM_LTO_OFF="-fno-lto" + +# linker specific flags +LDFLAGS_OPTIM_LINKER_COMPILER_DEFAULT="" +LDFLAGS_OPTIM_LINKER_BFD="-fuse-ld=bfd" +LDFLAGS_OPTIM_LINKER_GOLD="-fuse-ld=gold" +LDFLAGS_OPTIM_LINKER_MOLD="-fuse-ld=mold" + +# default compiler optimization +CFLAGS_OPTIM_DEFAULT="-O2 -fomit-frame-pointer -DNDEBUG" +CXXFLAGS_OPTIM_DEFAULT="$CFLAGS_OPTIM_DEFAULT" +# speed flag +CFLAGS_OPTIM_SPEED="-O3 -fomit-frame-pointer -DNDEBUG" +CXXFLAGS_OPTIM_SPEED="$CFLAGS_OPTIM_SPEED" +# size flag +CFLAGS_OPTIM_SIZE="-Os -fomit-frame-pointer -DNDEBUG" +CXXFLAGS_OPTIM_SIZE="$CFLAGS_OPTIM_SIZE" +# debug settings +CFLAGS_OPTIM_DEBUG="-ggdb -Og" +CXXFLAGS_OPTIM_DEBUG="$CFLAGS_OPTIM_DEBUG" +LDFLAGS_OPTIM_DEBUG="-ggdb" +# split debug settings (requires gold) +CFLAGS_OPTIM_DEBUG_SPLIT="-gdwarf-4 -gsplit-dwarf -Og" +CXXFLAGS_OPTIM_DEBUG_SPLIT="$CFLAGS_OPTIM_DEBUG_SPLIT" +LDFLAGS_OPTIM_DEBUG_SPLIT="-gdwarf-4 -Wl,--gdb-index" + +# 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)" + FAMILY_TRIPLET=$($LOCAL_CC -print-multiarch) + if [ -n "$FAMILY_TRIPLET" ]; then + 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 + 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 0000000000..a5b5cd5088 --- /dev/null +++ b/config/options @@ -0,0 +1,176 @@ +# 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:-ArchR}" + +# determines PROJECT, if not forced by user +export PROJECT="${PROJECT:-ArchR}" + +# default to Generic device if building Generic project without device set +if [ "${PROJECT}" = "ArchR" -a -z "${DEVICE}" ]; then + export DEVICE="SM8250" +fi + +# determines TARGET_ARCH, if not forced by user +export ARCH="${ARCH:-aarch64}" +TARGET_ARCH="${ARCH}" + +# include helper functions +. config/functions + +# read DISTRO version information +. "${DISTRO_DIR}/${DISTRO}/version" || die "\nERROR: No distro version present\n" + +# read DISTRO options +if [ -f "${DISTRO_DIR}/${DISTRO}/options" ]; then + . "${DISTRO_DIR}/${DISTRO}/options" +fi + +# read PROJECT options +if [ -f "${PROJECT_DIR}/${PROJECT}/options" ]; then + . "${PROJECT_DIR}/${PROJECT}/options" +fi + +# read DEVICE options +if [ -f "${PROJECT_DIR}/${PROJECT}/devices/${DEVICE}/options" ]; then + . "${PROJECT_DIR}/${PROJECT}/devices/${DEVICE}/options" +fi + +# read architecture defaults +if [ -f "config/arch.${TARGET_ARCH}" ]; then + . "config/arch.${TARGET_ARCH}" +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" + +# 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 - run scripts/checkdeps *****" "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) +[ -z "${CONCURRENCY_LOAD}" ] && export CONCURRENCY_LOAD=$(python3 -c "import os; print(f'{os.cpu_count() * 1.5:.2f}')") + +# 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="15G" + +# compression level for ccache +# This option determines the level at which ccache will compress object files +# using the real-time compression algorithm Zstandard. It only has effect if +# compression is enabled (which it is by default). Zstandard is extremely fast +# for decompression and very fast for compression for lower compression +# levels. The default is 0. The value 0 means that ccache will choose a +# suitable zstd level, currently 1. +CCACHE_COMPRESSLEVEL="0" + +# Sloppiness options for ccache +# This tells ccache to be "sloppy" about certain things that normally would +# invalidate the cache: +# - pch_defines: ignore differences in macros inside precompiled headers. +# - time_macros: ignore __TIME__ and __DATE__ macros which change every build. +# Using these allows ccache to reuse cached objects even when these macros change, +# which is important when using precompiled headers +CCACHE_SLOPPINESS="pch_defines,time_macros" + +# set addon paths +if [ -z "$ADDON_PATH" ]; then + if [ -n "$ADDON_PROJECT" ]; then + ADDON_PATH="$ADDON_VERSION/$ADDON_PROJECT/$TARGET_ARCH" + else + ADDON_PATH="$ADDON_VERSION/$TARGET_ARCH" + fi +fi +if [ -z "$ADDON_URL" ]; then + ADDON_URL="$ADDON_SERVER_URL/$ADDON_PATH" +fi + +# read local persistent options from $ROOT if available +if [ -f "${ROOT}/.archr/options" ]; then + . "${ROOT}/.archr/options" +fi + +# read global persistent options from $HOME if available +if [ -f "${HOME}/.archr/options" ]; then + . "${HOME}/.archr/options" +fi + +if [ "${LOCAL_CCACHE_SUPPORT}" = "yes" ] && [ -z "${CCACHE_DISABLE}" ]; then + # like LOCAL_CC check for local ccache only on the very first + # call to config/options, before toolchain has been added to the path, + # otherwise we might pick up ccache from toolchain/bin here + if [ -z "${LOCAL_CCACHE}" ] && [ "${LOCAL_CCACHE_CHECKED}" != "yes" ]; then + export LOCAL_CCACHE="$(command -v ccache)" + export LOCAL_CCACHE_CHECKED="yes" + fi +else + export LOCAL_CCACHE="" +fi + +# overwrite OEM_SUPPORT via commandline +if [ "${OEM}" = "yes" -o "${OEM}" = "no" ]; then + OEM_SUPPORT="${OEM}" +fi + +# use /bin/dash as config shell if installed on the build host +if [ -z "${CONFIG_SHELL}" ] && [ -x "/bin/dash" ]; then + export CONFIG_SHELL="/bin/dash" +fi + +check_config + +. config/graphic +. config/path $1 + +## package processing + +# If the package caches are unset, then populate them +init_package_cache + +if [ -z "${DEFAULT_PYTHON_VERSION+set}" ]; then + export DEFAULT_PYTHON_VERSION="$(get_pkg_variable Python3 PKG_PYTHON_VERSION)" +fi + +# set package metadata +source_package "${1}" diff --git a/config/path b/config/path new file mode 100644 index 0000000000..691c8f6f94 --- /dev/null +++ b/config/path @@ -0,0 +1,105 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +set -e + +# setup initial directories (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 + +[ -z "${HOST_NAME}" ] && export HOST_NAME="$($LOCAL_CC -dumpmachine)" +TARGET_NAME=$TARGET_GCC_ARCH-${OSNAME}-linux-gnu${TARGET_ABI} + +BUILD=${BUILD_ROOT}/${BUILD_BASE}.${DISTRONAME}-${DEVICE:-$PROJECT}.${TARGET_ARCH} + +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 different toolchain for 64/32 split builds +if [ -z "$KERNEL_TOOLCHAIN" -a "$TARGET_KERNEL_ARCH" = "arm64" -a "$TARGET_ARCH" = "arm" ]; then + KERNEL_TOOLCHAIN="aarch64" +fi +if [ -n "$KERNEL_TOOLCHAIN" ]; then + TARGET_KERNEL_PREFIX=$KERNEL_TOOLCHAIN-none-elf- +else + TARGET_KERNEL_PREFIX=$TARGET_PREFIX +fi + +if [ -z "$CCACHE_DIR" ]; then + export CCACHE_DIR=$BUILD/.ccache +fi + +# keep a copy of ccache dir used for toolchain ccache +export BUILD_CCACHE_DIR="${CCACHE_DIR}" + +# local ccache dir in case we build early packages with local ccache +if [ -z "${LOCAL_CCACHE_DIR}" ]; then + export LOCAL_CCACHE_DIR="${BUILD}/.ccache-local" +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 + +# Fix #4737 +unset PYTHONDONTWRITEBYTECODE diff --git a/config/show_config b/config/show_config new file mode 100644 index 0000000000..2f87747d15 --- /dev/null +++ b/config/show_config @@ -0,0 +1,161 @@ +#!/bin/bash + +show_config() { + # load graphic configuration + get_graphicdrivers + + dashes="===========================" + config_message="\n ${dashes}${dashes}${dashes}" + config_message+="\n Configuration for ${DISTRONAME} " + if [ "${OFFICIAL}" = "yes" ]; then + config_message+="(official)" + else + config_message+="(community)" + fi + config_message+="\n ${dashes}${dashes}${dashes}" + + # Build options + + config_message+="\n\n Buildsystem configuration:" + config_message+="\n ${dashes}${dashes}" + + config_message+="\n - CPU:\t\t\t\t\t ${TARGET_CPU}" + config_message+="\n - Kernel Architecture:\t\t\t ${TARGET_KERNEL_ARCH}" + config_message+="\n - Userland Architecture:\t\t ${TARGET_ARCH}" + if [ -n "${TARGET_FLOAT}" ]; then + config_message+="\n - FLOAT:\t\t\t\t ${TARGET_FLOAT}" + fi + if [ -n "${TARGET_FPU}" ]; then + config_message+="\n - FPU:\t\t\t\t\t ${TARGET_FPU}" + fi + config_message+="\n - CPU features:\t\t\t ${TARGET_FEATURES}" + config_message+="\n - LTO (Link Time Optimization) support: ${LTO_SUPPORT}" + config_message+="\n - GOLD (Google Linker) Support:\t ${GOLD_SUPPORT}" + config_message+="\n - MOLD (Modern Linker) Support:\t ${MOLD_SUPPORT}" + config_message+="\n - Default Linker:\t\t\t ${DEFAULT_LINKER}" + config_message+="\n - Accelerated arm libc functions:\t ${ARM_MEM_SUPPORT}" + config_message+="\n - LLVM support:\t\t\t ${LLVM_SUPPORT}" + config_message+="\n - DEBUG:\t\t\t\t ${DEBUG:-no}" + config_message+="\n - CFLAGS:\t\t\t\t ${TARGET_CFLAGS}" + config_message+="\n - LDFLAGS:\t\t\t\t $(sed 's/^ *//' <<<${TARGET_LDFLAGS})" + config_message+="\n - Local Ccache:\t\t\t ${LOCAL_CCACHE:-no}" + config_message+="\n - CONFIG_SHELL:\t\t\t ${CONFIG_SHELL:-auto}" + + # Misc. hardware configuration + + config_message+="\n\n Misc. hardware configuration:" + config_message+="\n ${dashes}${dashes}" + + config_message+="\n - ALSA support:\t\t\t ${ALSA_SUPPORT}" + config_message+="\n - Pulseaudio support:\t\t\t ${PULSEAUDIO_SUPPORT}" + config_message+="\n - Bluetooth support:\t\t\t ${BLUETOOTH_SUPPORT}" + + for config_driver in ${ADDITIONAL_DRIVERS}; do + 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+="\n - Include driver add-ons:\t\t ${config_driver_addons}" + done + fi + + for config_firmware in ${FIRMWARE}; do + config_message+="\n - Include firmware:\t\t\t ${config_firmware}" + done + + # Image Filesystem + + config_message+="\n\n Image Filesystems:" + config_message+="\n ${dashes}${dashes}" + config_message+="\n - Root Size (MiB): \t\t\t ${ROOT_SIZE}" + config_message+="\n - Storage Size (MiB): \t\t\t ${STORAGE_SIZE}" + config_message+="\n - Root Filesystem: \t\t\t ext4" + + # Misc. Filesystems + + config_message+="\n\n Misc. Filesystems:" + config_message+="\n ${dashes}${dashes}" + + config_message+="\n - Swap Support:\t\t\t ${SWAP_SUPPORT}" + if [ "${SWAP_SUPPORT}" = "yes" ]; then + config_message+="\n - Swapfile default size:\t\t ${SWAPFILESIZE}" + fi + + # Network service configuration + + config_message+="\n\n Network service configuration:" + config_message+="\n ${dashes}${dashes}" + + config_message+="\n - Avahi (Zeroconf) support:\t\t ${AVAHI_DAEMON}" + config_message+="\n - NFS mounting support:\t\t ${NFS_SUPPORT}" + config_message+="\n - SAMBA mounting support:\t\t ${SAMBA_SUPPORT}" + config_message+="\n - SAMBA server support:\t\t ${SAMBA_SERVER}" + config_message+="\n - SFTP server support:\t\t\t ${SFTP_SERVER}" + config_message+="\n - OpenVPN support:\t\t\t ${OPENVPN_SUPPORT}" + config_message+="\n - WireGuard support:\t\t\t ${WIREGUARD_SUPPORT}" + + # Graphic configuration + + config_message+="\n\n Graphic configuration:" + config_message+="\n ${dashes}${dashes}" + config_message+="\n - Graphic Drivers:\t\t\t ${GRAPHIC_DRIVERS}" + config_message+="\n - Display Server:\t\t\t ${DISPLAYSERVER}" + if [ "${DISPLAYSERVER}" = "x11" ]; then + for drv in ${XORG_DRIVERS}; do + XORG_DRIVERS_CONFIG+="xf86-video-${drv} " + done + config_message+="\n - X.Org Graphic Drivers:\t\t ${XORG_DRIVERS_CONFIG}" + config_message+="\n - X.Org Composite support:\t\t ${COMPOSITE_SUPPORT}" + fi + config_message+="\n - Window Manager / Compositor:\t\t ${WINDOWMANAGER}" + config_message+="\n - OpenGL (GLX) support (provider):\t ${OPENGL_SUPPORT}" + [ "${OPENGL}" != "no" ] && config_message+=" (${OPENGL})" + config_message+="\n - OpenGL ES support (provider):\t ${OPENGLES_SUPPORT}" + [ "${OPENGLES}" != "no" ] && config_message+=" (${OPENGLES})" + config_message+="\n - Vulkan API support (provider):\t ${VULKAN_SUPPORT}" + [ "${VULKAN}" != "no" ] && config_message+=" (${VULKAN})" + if [ "${VULKAN_SUPPORT}" = "yes" ]; then + config_message+="\n - Vulkan Graphic Drivers:\t\t ${VULKAN_DRIVERS_CONFIG}" + fi + + # Video Acceleration configuration + + config_message+="\n\n Video Acceleration configuration:" + config_message+="\n ${dashes}${dashes}" + config_message+="\n - VA-API Support:\t\t\t ${VAAPI_SUPPORT}" + config_message+="\n - VDPAU Support:\t\t\t ${VDPAU_SUPPORT}" + + # OS configuration + + config_message+="\n\n OS configuration:" + config_message+="\n ${dashes}${dashes}" + + config_message+="\n - OEM Support:\t\t\t\t ${OEM_SUPPORT}" + config_message+="\n - Default ROOT Password:\t\t ${ROOT_PASSWORD}" + config_message+="\n - Bootloader:\t\t\t\t ${BOOTLOADER}" + config_message+="\n - UDevil support:\t\t\t ${UDEVIL}" + config_message+="\n - Installer support:\t\t\t ${INSTALLER_SUPPORT}" + for config_package in ${ADDITIONAL_PACKAGES}; do + config_message+="\n - Include package:\t\t\t ${config_package}" + done + + # Distribution specific configuration + # show_distro_config() should be included in one of: + # $DISTRO/config/functions + # $DISTRO/show_config + + if [ -f distributions/${DISTRO}/show_config ]; then + . distributions/${DISTRO}/show_config + fi + if [ "$(type -t show_distro_config)" = "function" ]; then + show_distro_config + fi + + config_message+="\n\n ${dashes}${dashes}${dashes}" + config_message+="\n End Configuration for ${DISTRONAME}" + config_message+="\n ${dashes}${dashes}${dashes}" + config_message+="\n\n\n" + + echo -e "${config_message}" +} diff --git a/config/sources b/config/sources new file mode 100644 index 0000000000..fe19a603fe --- /dev/null +++ b/config/sources @@ -0,0 +1,2 @@ +# Sourceforge download site + SOURCEFORGE_SRC="https://prdownloads.sourceforge.net" diff --git a/distributions/ArchR/config/functions b/distributions/ArchR/config/functions new file mode 100644 index 0000000000..31c5f94bbe --- /dev/null +++ b/distributions/ArchR/config/functions @@ -0,0 +1,339 @@ +### Generate System Documentation + +clean_doc_cache() { + DOCTMP="${ROOT}/.doc_cache/${DEVICE}" + if [ -d "${DOCTMP}" ] + then + rm -rf "${DOCTMP}" + fi +} + +start_system_doc() { + if [ -z "${SYSDOC}" ] + then + echo "Unable to generate documentation, define SYSDOC in options." + exit 1 + fi + if [ ! -d "${SYSDOCROOT}" ] + then + mkdir ${SYSDOCROOT} + fi + if [ -e "${SYSDOC}.md" ] + then + rm -f ${SYSDOC}.md + fi + if [ -e "${ROOT}/templates/HEADER.md" ] + then + cat ${ROOT}/templates/HEADER.md >${SYSDOC}.md + fi + DOCTEMPLATE="$(basename ${SYSDOC})" + if [ -e "${ROOT}/templates/${DOCTEMPLATE}.md" ] + then + cat ${ROOT}/templates/${DOCTEMPLATE}.md >>${SYSDOC}.md + fi + cat <>${SYSDOC}.md +|Manufacturer|System|Release Date|Games Path|Supported Extensions|Emulator / Core| +|----|----|----|----|----|----| +EOF +} + +add_system_doc() { + echo -n "|${SYSTEM_MANUFACTURER}|${SYSTEM_FULLNAME} (${SYSTEM_NAME})|${SYSTEM_RELEASE}|\`$(basename ${SYSTEM_PATH})\`|${SYSTEM_EXTENSION}|" >>${DOCTMP}/${1}:system.tmp +} + +add_emu_doc() { + if [ ! -d "${DOCTMP}" ] + then + mkdir -p "${DOCTMP}" + fi + if [ "${4}" = "true" ] + then + DEFAULT=" (default)" + else + unset DEFAULT + fi + echo -n "**${2}:** ${3}${DEFAULT}
" >>${DOCTMP}/${1}:emulators.tmp +} + +mk_system_doc() { + for system in $(ls ${DOCTMP}/ | awk 'BEGIN {FS=":"} {print $1}' | sort | uniq) + do + cat ${DOCTMP}/${system}:system.tmp >>${SYSDOC}.tmp + if [ -e "${DOCTMP}/${system}:emulators.tmp" ] + then + cat ${DOCTMP}/${system}:emulators.tmp >>${SYSDOC}.tmp + fi + echo "|" >>${SYSDOC}.tmp + done + cat ${SYSDOC}.tmp | sort -f >>${SYSDOC}.md + rm -f ${SYSDOC}.tmp +} + +### Generate ES Systems + +clean_es_cache() { + ESTMP="${ROOT}/.es_cache/${DEVICE}" + if [ -d "${ESTMP}" ] + then + rm -rf "${ESTMP}" + fi +} + +add_emu_core() { + if [ ! -d "${ESTMP}" ] + then + mkdir -p "${ESTMP}" + fi + + # Schema: emulator|core|true/false + echo "${2}|${3}|${4}" >>${ESTMP}/${1}-emulators.tmp + add_emu_doc $* +} + +mk_es_systems() { + + cat <${ESTMP}/.es_systems.cfg + + +EOF + rm -f ${ESTMP}/*-emulators.tmp + for essystem in $(ls ${ESTMP}/*.tmp | sort) + do + cat ${essystem} >>${ESTMP}/.es_systems.cfg + done + cat <>${ESTMP}/.es_systems.cfg + +EOF +xmlstarlet fo -t ${ESTMP}/.es_systems.cfg >${ESTMP}/es_systems.cfg 2>/dev/null + +} + +add_system_dir() { + if [ ! -d "${ESTMP}" ] + then + mkdir -p "${ESTMP}" + fi + cat <>${ESTMP}/system-dirs.conf +d ${1} 0777 root root - - +EOF +} + +add_es_system() { + RUNCMD='/usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%"' + if [ -e "${ROOT}/config/emulators/${1}.conf" ] + then + . ${ROOT}/config/emulators/${1}.conf + fi + + if [ ! -d "${ESTMP}" ] + then + mkdir -p "${ESTMP}" + fi + if [[ -z "${SYSTEM_COMMAND}" ]]; + then + SYSTEM_COMMAND=$RUNCMD + fi + if [ ! -e "${ESTMP}/${SYSTEM_NAME}.tmp" ] + then + cat <${ESTMP}/${SYSTEM_NAME}.tmp + + ${SYSTEM_NAME} + ${SYSTEM_FULLNAME} + ${SYSTEM_MANUFACTURER} + ${SYSTEM_RELEASE} + ${SYSTEM_HARDWARE} + ${SYSTEM_PATH} + ${SYSTEM_EXTENSION} + ${SYSTEM_COMMAND} + ${SYSTEM_PLATFORM} + ${SYSTEM_THEME} + +EOF + fi + + add_system_dir "${SYSTEM_PATH}" + + if [ -e "${ESTMP}/${SYSTEM_NAME}-emulators.tmp" ] + then + while read -r line + do + SYSTEM_EMULATOR=$(echo ${line} | awk 'BEGIN {FS="|"} {print $1}') + SYSTEM_CORE=$(echo ${line} | awk 'BEGIN {FS="|"} {print $2}') + SYSTEM_DEFAULT=$(echo ${line} | awk 'BEGIN {FS="|"} {print $3}') + + ### Check to see if we've already added an emulator key. + EMTEST=$(xmlstarlet sel -t -c "//system/emulators" ${ESTMP}/${SYSTEM_NAME}.tmp 2>/dev/null ||:) + if [ -z "${EMTEST}" ] + then + ### Add the emulator element + xmlstarlet ed --omit-decl --inplace \ + -s "//system" -t elem -n "emulators" -v "" \ + ${ESTMP}/${SYSTEM_NAME}.tmp 2>&1 >/dev/null + fi + + ### Check to see if we've already added an emulator key. + EETEST=$(xmlstarlet sel -t -c "//system/emulators/emulator[@name=\"${SYSTEM_EMULATOR}\"]" ${ESTMP}/${SYSTEM_NAME}.tmp 2>/dev/null ||:) + if [ -z "${EETEST}" ] + then + ### Add the emulator element + xmlstarlet ed --omit-decl --inplace \ + -s "//system/emulators" -t elem -n "emulator" -v "" \ + ${ESTMP}/${SYSTEM_NAME}.tmp 2>&1 >/dev/null + fi + + ### Add an attribute defining the emulator's name. + xmlstarlet ed --omit-decl --inplace \ + -s "//system/emulators/emulator[not(@name)]" -t attr -n "name" -v "${SYSTEM_EMULATOR}" \ + ${ESTMP}/${SYSTEM_NAME}.tmp 2>&1 >/dev/null + + ### Check to see if we've already added a core element. + COTEST=$(xmlstarlet sel -t -c "//system/emulators/emulator[@name=\"${SYSTEM_EMULATOR}\"]/cores/core" ${ESTMP}/${SYSTEM_NAME}.tmp 2>/dev/null ||:) + if [ -z "${COTEST}" ] + then + xmlstarlet ed --omit-decl --inplace \ + -s "//system/emulators/emulator[@name=\"${SYSTEM_EMULATOR}\"]" -t elem -n "cores" -v "" \ + ${ESTMP}/${SYSTEM_NAME}.tmp 2>&1 >/dev/null + fi + + ### Add each core. + xmlstarlet ed --omit-decl --inplace \ + -s "//system/emulators/emulator[@name=\"${SYSTEM_EMULATOR}\"]/cores" -t elem -n "core" -v "${SYSTEM_CORE}" \ + ${ESTMP}/${SYSTEM_NAME}.tmp 2>&1 >/dev/null + + if [ "${SYSTEM_DEFAULT}" = "true" ] + then + ### Add an attribute defining the default core + xmlstarlet ed --omit-decl --inplace \ + -i "//system/emulators/emulator[@name=\"${SYSTEM_EMULATOR}\"]/cores/core" -t attr -n "default" -v "true" \ + ${ESTMP}/${SYSTEM_NAME}.tmp 2>&1 >/dev/null + fi + done <${ESTMP}/${SYSTEM_NAME}-emulators.tmp + fi + add_system_doc ${SYSTEM_NAME} +} + +# config.xml parsing +CONFIGXML="${PROJECT_DIR}/${PROJECT}/config.xml" + +SUBDEVICES=$(xmlstarlet sel -t -m "//archr/${DEVICE}/*[@mkimage_options]" -v "name()" -n "${CONFIGXML}" 2>/dev/null | tr '\n' ' ') + +get_kernel_make_extracmd() { + local DTB_PREFIX + DTB_PREFIX=$(xmlstarlet sel -t -v "//archr/${DEVICE}/@dtb_prefix" "${CONFIGXML}" 2>/dev/null) + DTB_PREFIX="${DTB_PREFIX}/" + xmlstarlet sel -t -m "//archr/${DEVICE}//file" -o "${DTB_PREFIX}" -v "." -o ".dtb " "${CONFIGXML}" 2>/dev/null +} + +get_fdt() { + local FDT_FILENAME="" + + if [[ -n "${SUBDEVICE}" ]]; then + FDT_FILENAME=$(xmlstarlet sel -t -v "//archr/${DEVICE}/${SUBDEVICE}/@fdt" "${CONFIGXML}" 2>/dev/null || true) + fi + + if [[ -z "${FDT_FILENAME}" ]]; then + FDT_FILENAME=$(xmlstarlet sel -t -v "//archr/${DEVICE}/@fdt" "${CONFIGXML}" 2>/dev/null || true) + fi + + [ -n "${FDT_FILENAME}" ] && echo "${FDT_FILENAME}" || true +} + +get_fdt_type() { + local FDT_TYPE="" + + if [[ -n "${SUBDEVICE}" ]]; then + FDT_TYPE=$(xmlstarlet sel -t -v "//archr/${DEVICE}/${SUBDEVICE}/@fdt_type" "${CONFIGXML}" 2>/dev/null) + fi + + if [[ -z "${FDT_TYPE}" ]]; then + FDT_TYPE=$(xmlstarlet sel -t -v "//archr/${DEVICE}/@fdt_type" "${CONFIGXML}" 2>/dev/null) + fi + + if [[ "${FDT_TYPE}" == "fdtdir" ]]; then + echo "FDTDIR" + else + echo "FDT" + fi +} + +generate_grub_cfg_body() { + cat << EOF +insmod part_gpt +insmod part_msdos +load_env + +if [ "\${saved_entry}" ]; then + set timeout=2 + set default="\${saved_entry}" +else + set timeout=-1 +fi + +if [ x"\${feature_menuentry_id}" = xy ]; then + menuentry_id_option="--id" +else + menuentry_id_option="" +fi +export menuentry_id_option + +function savedefault { + saved_entry="\${chosen}" + save_env saved_entry +} + +set timeout_style=menu +set lang=en_US +loadfont /boot/grub/dejavu-mono.pf2 +set rotation=270 +set gfxmode=auto +insmod efi_gop +insmod gfxterm +terminal_output gfxterm +set menu_color_normal=cyan/blue +set menu_color_highlight=white/blue + +EOF + + xmlstarlet sel -t -m "//archr/${DEVICE}/file" \ + -v "concat(@short, '|', @full, '|', .)" -n "${CONFIGXML}" 2>/dev/null | while IFS='|' read -r SHORT FULL DTB; do + + cat << EOF +menuentry '${FULL}' \$menuentry_id_option '${SHORT}' { + savedefault + search --set -f /KERNEL + linux /KERNEL boot=LABEL=${DISTRO_BOOTLABEL} disk=LABEL=${DISTRO_DISKLABEL} grub_portable ${EXTRA_CMDLINE} + devicetree /boot/grub/${DTB}.dtb +} +EOF + done + + xmlstarlet sel -t -m "//archr/${DEVICE}/file" \ + -v "concat(@short, '|', @full, '|', .)" -n "${CONFIGXML}" 2>/dev/null | while IFS='|' read -r SHORT FULL DTB; do + + cat << EOF +menuentry '${FULL} RECOVERY' \$menuentry_id_option '${SHORT}-recovery' { + search --set -f /KERNEL + linux /KERNEL boot=LABEL=${DISTRO_BOOTLABEL} disk=LABEL=${DISTRO_DISKLABEL} grub_portable ${EXTRA_CMDLINE} recovery + devicetree /boot/grub/${DTB}.dtb +} +EOF + done +} + +mkimage_all() { + local OPTIONS_LIST="" + + if [[ -n "${SUBDEVICE}" ]]; then + OPTIONS_LIST=$(xmlstarlet sel -t -v "//archr/${DEVICE}/${SUBDEVICE}/@mkimage_options" "${CONFIGXML}" 2>/dev/null) + fi + + if [[ -z "${OPTIONS_LIST}" ]]; then + OPTIONS_LIST=$(xmlstarlet sel -t -v "//archr/${DEVICE}/@mkimage_options" "${CONFIGXML}" 2>/dev/null) + fi + + for step in $(echo "${OPTIONS_LIST}" | tr ',' ' '); do + local func_name="mkimage_${step}" + + "${func_name}" + done +} diff --git a/distributions/ArchR/kernel_options b/distributions/ArchR/kernel_options new file mode 100644 index 0000000000..e69de29bb2 diff --git a/distributions/ArchR/logos/archr-logo.png b/distributions/ArchR/logos/archr-logo.png new file mode 100644 index 0000000000..f85d59d604 Binary files /dev/null and b/distributions/ArchR/logos/archr-logo.png differ diff --git a/distributions/ArchR/logos/archr-logo.svg b/distributions/ArchR/logos/archr-logo.svg new file mode 100644 index 0000000000..5cd7063a7c --- /dev/null +++ b/distributions/ArchR/logos/archr-logo.svg @@ -0,0 +1,5 @@ + + + ARCHR + + diff --git a/distributions/ArchR/options b/distributions/ArchR/options new file mode 100644 index 0000000000..c2a17a518c --- /dev/null +++ b/distributions/ArchR/options @@ -0,0 +1,224 @@ +# 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" + +# The name of the parent organization for updates + GIT_ORGANIZATION="archr-linux" + +# The name of the github project for updates + GIT_REPO="Arch-R" + +# Name of the Distro to build (full name, without special characters) + DISTRONAME="ArchR" + +# Name of the OS to build (full name, lower case, without special characters) + OSNAME="archr" + +# short project description + DESCRIPTION="Arch R - Gaming OS for R36S" + +# Distribution Home URL + HOME_URL="https://arc-r.io" + +# Documentation URL + WIKI_URL="https://arch-r.io/docs/guide/" + +# Where to report bugs + BUG_REPORT_URL="https://github.com/archr-linux/Arch-R/issues" + +# Root password to integrate in the target system + ROOT_PASSWORD="archr" + +# Install glibc locales to the build (yes / no) + GLIBC_LOCALES="yes" + +# build and install pipewire support (yes / no) + PIPEWIRE_SUPPORT="yes" + +# Define package sets to clean based on the type of build being executed. +# This should be updated to be more dynamic in the future. + CLEAN_OS_BASE="emulators system-utils modules quirks autostart archr kernel-firmware" + CLEAN_NETWORK="" + CLEAN_EMU_32BIT="lib32 box86 pcsx_rearmed-lr arm" + # Sway depends on it, weston will use it if it's built but we don't want that. + CLEAN_WESTON="libdisplay-info sway" + +# build and install archr joypad driver (yes / no) + ARCHR_JOYPAD="yes" + +# 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="" + +# 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="" + +# Disable 32BIT support + ENABLE_32BIT="${ENABLE_32BIT-true}" + +# build and install bluetooth support (yes / no) + BLUETOOTH_SUPPORT="yes" + +# build and install Avahi (Zeroconf) daemon (yes / no) + AVAHI_DAEMON="yes" + +# build with NFS support (mounting nfs shares via the OS) (yes / no) + NFS_SUPPORT="yes" + +# 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 Simple HTTP Server (yes / no) + SIMPLE_HTTP_SERVER="yes" + +# build and install OpenVPN support (yes / no) + OPENVPN_SUPPORT="no" + +# build and install ZeroTier support (yes / no) + ZEROTIER_SUPPORT="yes" + +# build and install WireGuard support (yes / no) + WIREGUARD_SUPPORT="yes" + +# 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="no" + +# Target an emulation device + EMULATION_DEVICE="${EMULATION_DEVICE:-yes}" + +# Add support for containers + CONTAINER_SUPPORT="${CONTAINER_SUPPORT:-no}" + +# Build modules packages + MODULES_PKG="${MODULES_PKG:-yes}" + +# Support for debug tools such as strace + DEBUG_PACKAGES="${DEBUG_PACKAGES:-yes}" + +# Windowmanager to use (weston / swaywm-env / no) + 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" + +# 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" + +# Vestigial LibreELEC vars: SWAPSIZE and SWAP_TYPE are NOT read by +# ArchR's util-linux package.mk (it uses ZRAM_SWAP_SIZE / SWAP_FILE_SIZE +# / ZRAM_COMPRESSION_ALGO from device options). Swap policy on each +# device is zram-only when SWAP_FILE_SIZE=0; see RK3326/options. + +# Default weston terminal font size + WESTONFONTSIZE="14" + +# 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="no" + +# htop tool (yes / no) + HTOP_TOOL="yes" + +# btop tool (yes / no) + BTOP_TOOL="yes" + +# Distribution Specific source location + DISTRO_MIRROR="https://github.com/ROCKNIX/distribution-sources/releases/download/sources" + +# Root filesystem type (squashfs / ext4) + ROOTFS_TYPE="ext4" + +# Boot partition size (FAT32, kernel + DTBs + bootloader), in MB. + BOOT_SIZE=256 + +# Root partition size (ext4 rootfs), in MB + ROOT_SIZE=4608 + +# Default system partition offset, in sectors, eg. 2048 + SYSTEM_PART_START=32768 + +# Legacy SYSTEM_SIZE (used when ROOTFS_TYPE=squashfs, or as fallback) + SYSTEM_SIZE=${BOOT_SIZE} + +# Size of storage partition, in MB. Must be >=32 + STORAGE_SIZE=32 + +# Default supported get handlers (archive, git, file etc.) + GET_HANDLER_SUPPORT="archive git file" + +# Partition labels for USB/SD installation media + DISTRO_BOOTLABEL="ARCHR" + DISTRO_ROOTLABEL="ARCHR_ROOT" + DISTRO_DISKLABEL="STORAGE" + +# Settings package name - blank if not required + DISTRO_PKG_SETTINGS="" + +# Enable Updates + ENABLE_UPDATES="yes" + +# defines the born on date of a build + BUILD_DATE=$(date) + +# Define supported systems documentation path + SYSDOCROOT="${ROOT}/documentation/PER_DEVICE_DOCUMENTATION/${DEVICE}" + SYSDOC="${SYSDOCROOT}/SUPPORTED_EMULATORS_AND_CORES" diff --git a/distributions/ArchR/splash/boot-logo.bmp.gz b/distributions/ArchR/splash/boot-logo.bmp.gz new file mode 100644 index 0000000000..aac85ba472 Binary files /dev/null and b/distributions/ArchR/splash/boot-logo.bmp.gz differ diff --git a/distributions/ArchR/splash/splash-1080.png b/distributions/ArchR/splash/splash-1080.png new file mode 100644 index 0000000000..ae9b654877 Binary files /dev/null and b/distributions/ArchR/splash/splash-1080.png differ diff --git a/distributions/ArchR/splash/splash-1200.png b/distributions/ArchR/splash/splash-1200.png new file mode 100644 index 0000000000..5865ff0dc2 Binary files /dev/null and b/distributions/ArchR/splash/splash-1200.png differ diff --git a/distributions/ArchR/splash/splash-2160.png b/distributions/ArchR/splash/splash-2160.png new file mode 100644 index 0000000000..b576453a9c Binary files /dev/null and b/distributions/ArchR/splash/splash-2160.png differ diff --git a/distributions/ArchR/splash/splash-720.png b/distributions/ArchR/splash/splash-720.png new file mode 100644 index 0000000000..de3e1ecc9b Binary files /dev/null and b/distributions/ArchR/splash/splash-720.png differ diff --git a/distributions/ArchR/splash/splash-768.png b/distributions/ArchR/splash/splash-768.png new file mode 100644 index 0000000000..323f5e101d Binary files /dev/null and b/distributions/ArchR/splash/splash-768.png differ diff --git a/distributions/ArchR/splash/splash-base.svg b/distributions/ArchR/splash/splash-base.svg new file mode 100644 index 0000000000..f61d32630d --- /dev/null +++ b/distributions/ArchR/splash/splash-base.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + Arch R + + + + GAMING OS FOR R36S + + + + Loading... + + diff --git a/distributions/ArchR/version b/distributions/ArchR/version new file mode 100644 index 0000000000..9cfcbda200 --- /dev/null +++ b/distributions/ArchR/version @@ -0,0 +1,5 @@ +# VERSION: set full version, use "devel" for development version + DISTRO_VERSION="devel" + +# OS_VERSION: OS Version + OS_VERSION="$(date +%Y%m%d)" diff --git a/documentation/PER_DEVICE_DOCUMENTATION/RK3326/SUPPORTED_EMULATORS_AND_CORES.md b/documentation/PER_DEVICE_DOCUMENTATION/RK3326/SUPPORTED_EMULATORS_AND_CORES.md new file mode 100644 index 0000000000..4b16bca08d --- /dev/null +++ b/documentation/PER_DEVICE_DOCUMENTATION/RK3326/SUPPORTED_EMULATORS_AND_CORES.md @@ -0,0 +1,126 @@ +|Manufacturer|System|Release Date|Games Path|Supported Extensions|Emulator / Core| +|----|----|----|----|----|----| +| System|Media Player (mplayer)|System|`mplayer`|.3g2 .3gp .aac .ac3 .asf .avi .divx .dts .eac33 .f4f .f4v .flac .flv .m2p .m2ts .m3u .m4a .mka .mkv .mov .mp3 .mp4 .mpeg .mpg .mxf .ogg .ogm .opus .ps .sh .thd .ts .twi .vob .wav .webm .wma .wmv .wv .ytb|**mplayer:** mplayer (default)
**retroarch:** ffmpeg
| +| System|Moonlight Game Streaming (moonlight)|System|`moonlight`|.sh|**moonlight:** moonlight (default)
| +| System|Music Player (music)|System|`playlists`|.m3u .sh|**gmu:** gmu (default)
| +| System|Ports (ports)|System|`ports`|.sh|**portmaster:** portmaster (default)
| +| System|Screenshots (imageviewer)|System|`screenshots`|.jpg .jpeg .png .bmp .psd .tga .gif .hdr .pic .ppm .pgm .mkv .pdf .mp4 .avi|| +| System|Tools (tools)|System|`modules`|.sh|| +|Acorn|BBC Micro (bbcmicro)|1981|`bbcmicro`|.ssd .dsd|**retroarch:** b2 (default)
| +|Amstrad|Amstrad CPC (amstradcpc)|1984|`amstradcpc`|.dsk .cpr .sna .tap .cdt .kcr .voc .m3u .zip .7z|**retroarch:** crocods (default)
**retroarch:** cap32
| +|Apple|iOS (ios)|2008|`ios`|.ipa .app|**touchhle:** touchhle-sa (default)
| +|Apple|Macintosh (macintosh)|1984|`mac`|.dsk .img .hfv .cmd .zip|**retroarch:** minivmac (default)
| +|Arcade|Arcade (arcade)|0000|`arcade`|.zip .7z|**retroarch:** mame2003_plus (default)
**retroarch:** mame2010
**retroarch:** mame2015
**retroarch:** fbneo
**retroarch:** fbalpha2012
**retroarch:** fbalpha2019
**retroarch:** mame
| +|Arcade|Daphne (daphne)|1996|`daphne`|.daphne .singe|**hypseus-singe:** hypseus-singe (default)
**retroarch:** daphne
| +|Arcade|Final Burn Neo (fbn)|2002|`fbneo`|.7z .zip|**retroarch:** fbneo (default)
**retroarch:** mame2003_plus
**retroarch:** mame2010
**retroarch:** mame2015
**retroarch:** mame
**retroarch:** fbalpha2012
**retroarch:** fbalpha2019
| +|Arcade|MAME (mame)|1997|`mame`|.7z .zip|**retroarch:** mame2003_plus (default)
**retroarch:** mame2010
**retroarch:** mame2015
**retroarch:** mame
**retroarch:** fbneo
**retroarch:** fbalpha2012
**retroarch:** fbalpha2019
| +|Arduboy|Arduboy (arduboy)|2014|`arduboy`|.hex|**retroarch:** arduous (default)
| +|Atari|Atari 2600 (atari2600)|1977|`atari2600`|.a26 .bin .zip .7z|**retroarch:** stella (default)
| +|Atari|Atari 5200 (atari5200)|1982|`atari5200`|.rom .xfd .atr .atx .cdm .cas .car .bin .a52 .xex .zip .7z|**retroarch:** a5200 (default)
**retroarch:** atari800
| +|Atari|Atari 7800 (atari7800)|1986|`atari7800`|.a78 .bin .zip .7z|**retroarch:** prosystem (default)
| +|Atari|Atari 800 (atari800)|1979|`atari800`|.rom .xfd .atr .atx .cdm .cas .car .bin .a52 .xex .zip .7z|**retroarch:** atari800 (default)
| +|Atari|Atari Jaguar (atarijaguar)|1993|`atarijaguar`|.j64 .jag .rom .abs .cof .bin .prg|**retroarch:** virtualjaguar (default)
| +|Atari|Atari Lynx (atarilynx)|1989|`atarilynx`|.lnx .lyx .o .zip .7z|**retroarch:** handy (default)
**retroarch:** beetle_lynx
**mednafen:** lynx
| +|Atari|Atari ST (atarist)|1985|`atarist`|.st .msa .stx .dim .ipf .m3u .zip .7z|**retroarch:** hatari (default)
**hatarisa:** hatarisa
| +|Bandai|SuFami Turbo (sufami)|1996|`sufami`|.st .zip .7z|**retroarch:** snes9x (default)
| +|Bandai|Wonderswan (wonderswan)|1999|`wonderswan`|.ws .wsc .zip .7z|**retroarch:** beetle_wswan (default)
**mednafen:** wswan
| +|Bandai|Wonderswan Color (wonderswancolor)|2000|`wonderswancolor`|.ws .wsc .zip .7z|**retroarch:** beetle_wswan (default)
**mednafen:** wswan
| +|belogic|Uzebox (uzebox)|2008|`uzebox`|.uze|**retroarch:** uzem (default)
| +|Capcom|CPS-I (cps1)|1988|`cps1`|.zip .7z|**retroarch:** fbneo (default)
**retroarch:** mame2003_plus
**retroarch:** mame2010
**retroarch:** fbalpha2012
**AdvanceMame:** AdvanceMame
| +|Capcom|CPS-II (cps2)|1993|`cps2`|.zip .7z|**retroarch:** fbneo (default)
**retroarch:** mame2003_plus
**retroarch:** mame2010
**retroarch:** fbalpha2012
**AdvanceMame:** AdvanceMame
| +|Capcom|CPS-III (cps3)|1996|`cps3`|.zip .7z|**retroarch:** fbneo (default)
**retroarch:** mame2003_plus
**retroarch:** mame2010
**retroarch:** fbalpha2012
**AdvanceMame:** AdvanceMame
| +|Coleco|ColecoVision (colecovision)|1982|`coleco`|.bin .col .rom .zip .7z|**retroarch:** gearcoleco (default)
**retroarch:** bluemsx
**retroarch:** smsplus
| +|Commodore|Amiga (amiga)|1985|`amiga`|.zip .adf .uae .ipf .dms .adz .lha .m3u .hdf .hdz|**retroarch:** puae2021 (default)
**retroarch:** puae
**amiberry:** amiberry
**retroarch:** uae4arm
| +|Commodore|Amiga CD32 (amigacd32)|1994|`amigacd32`|.iso .cue .lha .chd|**retroarch:** puae2021 (default)
**retroarch:** puae
**retroarch:** uae4arm
| +|Commodore|Commodore 128 (c128)|1985|`c128`|.d64 .d71 .d80 .d81 .d82 .g64 .g41 .x64 .t64 .tap .prg .p00 .crt .bin .d6z .d7z .d8z .g6z .g4z .x6z .cmd .m3u .vsf .nib .nbz .zip|**retroarch:** vice_x128 (default)
**vicesa:** x128
| +|Commodore|Commodore 16 (c16)|1984|`c16`|.d64 .d71 .d80 .d81 .d82 .g64 .g41 .x64 .t64 .tap .prg .p00 .crt .bin .d6z .d7z .d8z .g6z .g4z .x6z .cmd .m3u .vsf .nib .nbz .zip|**retroarch:** vice_xplus4 (default)
**vicesa:** xplus4
| +|Commodore|Commodore 64 (c64)|1982|`c64`|.d64 .d71 .d80 .d81 .d82 .g64 .g41 .x64 .t64 .tap .prg .p00 .crt .bin .d6z .d7z .d8z .g6z .g4z .x6z .cmd .m3u .vsf .nib .nbz .zip|**retroarch:** vice_x64 (default)
**vicesa:** x64sc
| +|Commodore|Commodore PET (pet)|1977|`pet`|.20 .a0 .b0 .d64 .d71 .d80 .d81 .d82 .g64 .g41 .x64 .t64 .tap .prg .p00 .crt .bin .gz .d6z .d7z .d8z .g6z .g4z .x6z .cmd .m3u .vsf .nib .nbz .zip|**retroarch:** vice_xpet (default)
| +|Commodore|VIC-20 (vic20)|1980|`vic20`|.20 .a0 .b0 .d64 .d71 .d80 .d81 .d82 .g64 .g41 .x64 .t64 .tap .prg .p00 .crt .bin .gz .d6z .d7z .d8z .g6z .g4z .x6z .cmd .m3u .vsf .nib .nbz .zip|**retroarch:** vice_xvic (default)
**vicesa:** xvic
| +|Elektronika|Elektronika BK (bk)|1984|`bk`|.bin .img .dsk|**retroarch:** bk (default)
| +|EPOCH/YENO|Super Cassette Vision (scv)|1984|`scv`|.cart .bin .rom .0 .zip|**retroarch:** emuscv (default)
| +|Fairchild|Fairchild Channel F (channelf)|1976|`channelf`|.bin .chf .zip .7z|**retroarch:** freechaf (default)
| +|id Software|Doom (doom)|1993|`doom`|.doom|**gzdoom:** gzdoom-sa (default)
| +|id Software|iDtech (idtech)|1991|`idtech`|.sh|**retroarch:** idtech
| +|Infocom|Z-machine (zmachine)|1979|`zmachine`|.dat .z1 .z2 .z3 .z4 .z5 .z6 .zip|**retroarch:** mojozork (default)
| +|Lexaloffle|PICO-8 (pico-8)|2015|`pico-8`|.p8 .png|**pico-8:** pico8 (default)
**retroarch:** fake08
| +|Magnavox|Odyssey 2 (odyssey2)|1979|`odyssey`|.bin .zip .7z|**retroarch:** o2em (default)
| +|Mattel|Intellivision (intellivision)|1979|`intellivision`|.int .bin .rom .zip .7z|**retroarch:** freeintv (default)
| +|Microsoft|DOS (pc)|1981|`pc`|.com .bat .exe .dosz|**retroarch:** dosbox_pure
**retroarch:** dosbox_core
| +|Microsoft|MSX (msx)|1983|`msx`|.dsk .mx1 .mx2 .rom .zip .7z .m3u|**retroarch:** bluemsx (default)
**retroarch:** fmsx
| +|Microsoft|MSX 2 (msx2)|1988|`msx2`|.dsk .mx1 .mx2 .rom .zip .7z .m3u|**retroarch:** bluemsx (default)
**retroarch:** fmsx
| +|Microsoft|Windows (windows)|System|`windows`|.sh|**wine:** wine (default)
| +|NEC|PC Engine (pcengine)|1987|`pcengine`|.pce .bin .zip .7z|**retroarch:** beetle_pce_fast (default)
**retroarch:** beetle_pce
**retroarch:** beetle_supergrafx
**mednafen:** pce
**mednafen:** pce_fast
| +|NEC|PC Engine CD (pcenginecd)|1988|`pcenginecd`|.cue .ccd .chd .toc .m3u|**retroarch:** beetle_pce_fast (default)
**retroarch:** beetle_pce
**retroarch:** beetle_supergrafx
**mednafen:** pce
**mednafen:** pce_fast
| +|NEC|PC-8800 (pc-8800)|1981|`pc88`|.d88 .u88 .m3u|**retroarch:** quasi88 (default)
| +|NEC|PC-9800 (pc-9800)|1983|`pc98`|.d98 .zip .fdi .fdd .2hd .tfd .d88 .hdm .xdf .dup .hdi .thd .nhd .hdd .hdn .cmd|**retroarch:** np2kai (default)
| +|NEC|PC-FX (pcfx)|1994|`pcfx`|.chd .cue .ccd .toc|**retroarch:** beetle_pcfx (default)
**mednafen:** pcfx
| +|NEC|SuperGrafx (supergrafx)|1989|`sgfx`|.pce .sgx .cue .ccd .chd .zip .7z|**retroarch:** beetle_supergrafx
**retroarch:** beetle_pce
**mednafen:** pce
**mednafen:** pce_fast
| +|NEC|TurboGrafx-16 (tg16)|1989|`tg16`|.pce .bin .zip .7z|**retroarch:** beetle_pce_fast (default)
**retroarch:** beetle_pce
**retroarch:** beetle_supergrafx
**mednafen:** pce
**mednafen:** pce_fast
| +|NEC|TurboGrafx-CD (tg16cd)|1989|`tg16cd`|.cue .ccd .chd .toc .m3u|**retroarch:** beetle_pce_fast (default)
**retroarch:** beetle_pce
**retroarch:** beetle_supergrafx
**mednafen:** pce
**mednafen:** pce_fast
| +|Nesbox|TIC-80 (tic-80)|2017|`tic-80`|.tic|**retroarch:** tic80 (default)
| +|Nintendo|Famicom (famicom)|1983|`famicom`|.nes .unif .unf .zip .7z|**retroarch:** nestopia (default)
**retroarch:** fceumm
**retroarch:** quicknes
**retroarch:** mesen
**mednafen:** nes
| +|Nintendo|Famicom Disk System (fds)|1986|`fds`|.fds .zip .7z|**retroarch:** nestopia (default)
**retroarch:** fceumm
**retroarch:** quicknes
**retroarch:** mesen
**mednafen:** nes
| +|Nintendo|Game & Watch (gameandwatch)|1980|`gameandwatch`|.mgw .zip .7z|**retroarch:** gw
**retroarch:** mame
| +|Nintendo|Game Boy (gb)|1989|`gb`|.gb .gbc .zip .7z|**retroarch:** gambatte (default)
**retroarch:** sameboy
**retroarch:** gearboy
**retroarch:** tgbdual
**retroarch:** mgba
**retroarch:** vbam
**retroarch:** DoubleCherryGB
**retroarch:** skyemu
**mednafen:** gb
| +|Nintendo|Game Boy (Hacks) (gbh)|1989|`gbh`|.gb .zip .7z|**retroarch:** gambatte (default)
**retroarch:** sameboy
**retroarch:** gearboy
**retroarch:** tgbdual
**retroarch:** mgba
**retroarch:** vbam
**retroarch:** DoubleCherryGB
**retroarch:** skyemu
**mednafen:** gb
| +|Nintendo|Game Boy Advance (gba)|2001|`gba`|.gba .zip .7z|**retroarch:** gpsp (default)
**retroarch:** mgba
**retroarch:** vbam
**retroarch:** vba_next
**retroarch:** beetle_gba
**retroarch:** skyemu
**mednafen:** gba
| +|Nintendo|Game Boy Advance (Hacks) (gbah)|2001|`gbah`|.gba .zip .7z|**retroarch:** mgba (default)
**retroarch:** vbam
**retroarch:** vba_next
**retroarch:** beetle_gba
**retroarch:** skyemu
**retroarch:** gpsp
**mednafen:** gba
| +|Nintendo|Game Boy Advance video (gbav)|2001|`gbav`|.gba .zip .7z|**retroarch:** mgba (default)
**retroarch:** vbam
**retroarch:** vba_next
**retroarch:** beetle_gba
**retroarch:** skyemu
**retroarch:** gpsp
**mednafen:** gba
| +|Nintendo|Game Boy Color (gbc)|1998|`gbc`|.gb .gbc .zip .7z|**retroarch:** gambatte (default)
**retroarch:** sameboy
**retroarch:** gearboy
**retroarch:** tgbdual
**retroarch:** mgba
**retroarch:** vbam
**retroarch:** DoubleCherryGB
**retroarch:** skyemu
**mednafen:** gb
| +|Nintendo|Game Boy Color (Hacks) (gbch)|1998|`gbch`|.gb .gbc .zip .7z|**retroarch:** gambatte (default)
**retroarch:** sameboy
**retroarch:** gearboy
**retroarch:** tgbdual
**retroarch:** mgba
**retroarch:** vbam
**retroarch:** DoubleCherryGB
**retroarch:** skyemu
**mednafen:** gb
| +|Nintendo|NES (Hacks) (nesh)|1985|`nesh`|.nes .unif .unf .zip .7z|**retroarch:** nestopia (default)
**retroarch:** fceumm
**retroarch:** quicknes
**retroarch:** mesen
**mednafen:** nesh
| +|Nintendo|Nintendo 64 (n64)|1996|`n64`|.z64 .n64 .v64 .zip .7z|**retroarch:** mupen64plus_next (default)
**retroarch:** mupen64plus
**retroarch:** parallel_n64
**mupen64plus:** mupen64plus-sa
| +|Nintendo|Nintendo DS (nds)|2005|`nds`|.nds .zip .7z|**drastic:** drastic-sa (default)
**melonds:** melonds-sa
**retroarch:** melonds
**retroarch:** melondsds
**retroarch:** desmume
**retroarch:** skyemu
| +|Nintendo|Nintendo DSiWare (ndsiware)|2008|`ndsiware`|.nds .zip .7z|**retroarch:** melondsds (default)
**melonds:** melonds-sa
| +|Nintendo|Nintendo Entertainment System (nes)|1985|`nes`|.nes .unif .unf .zip .7z|**retroarch:** nestopia (default)
**retroarch:** fceumm
**retroarch:** quicknes
**retroarch:** mesen
**mednafen:** nes
| +|Nintendo|Pokémon Mini (pokemini)|2001|`pokemini`|.min .zip .7z|**retroarch:** pokemini (default)
| +|Nintendo|Satellaview (satellaview)|1995|`satellaview`|.smc .fig .bs .sfc .bsx .swc .zip .7z|**retroarch:** snes9x (default)
**retroarch:** snes9x2010
**retroarch:** snes9x2002
**retroarch:** snes9x2005_plus
| +|Nintendo|Super Famicom (sfc)|1990|`sfc`|.smc .fig .sfc .swc .zip .7z|**retroarch:** snes9x (default)
**retroarch:** snes9x2010
**retroarch:** snes9x2002
**retroarch:** snes9x2005_plus
**retroarch:** beetle_supafaust
**retroarch:** bsnes_mercury_performance
| +|Nintendo|Super NES MSU-1 (snesmsu1)|2012|`snesmsu1`|.smc .fig .sfc .swc .zip .7z|**retroarch:** snes9x (default)
**retroarch:** beetle_supafaust
**mednafen:** snes_faust
| +|Nintendo|Super Nintendo (Hacks) (snesh)|1991|`snesh`|.smc .fig .sfc .swc .zip .7z|**retroarch:** snes9x (default)
**retroarch:** snes9x2010
**retroarch:** snes9x2002
**retroarch:** snes9x2005_plus
**retroarch:** beetle_supafaust
**retroarch:** bsnes_mercury_performance
**mednafen:** snes_faust
| +|Nintendo|Super Nintendo (snes)|1991|`snes`|.smc .fig .sfc .swc .zip .7z|**retroarch:** snes9x (default)
**retroarch:** snes9x2010
**retroarch:** snes9x2002
**retroarch:** snes9x2005_plus
**retroarch:** beetle_supafaust
**retroarch:** bsnes_mercury_accuracy
**retroarch:** bsnes_mercury_balanced
**retroarch:** bsnes_mercury_performance
**mednafen:** snes_faust
**retroarch:** bsnes_mercury_accuracy
**retroarch:** bsnes_mercury_balanced
**retroarch:** bsnes_mercury_accuracy
**retroarch:** bsnes_mercury_balanced
**mednafen:** snes_faust
| +|Nintendo|Virtual Boy (virtualboy)|1995|`virtualboy`|.vb .zip .7z|**retroarch:** beetle_vb (default)
**mednafen:** vb
| +|Palm, Inc.|Palm OS (palm)|1996|`palm`|.prc .pqa .img .pdb .zip|**retroarch:** mu (default)
| +|Panasonic|3DO (3do)|1993|`3do`|.iso .bin .chd .cue|**retroarch:** opera (default)
| +|Philips|CD-i (cdi)|1991|`cdi`|.chd .cue .iso|**retroarch:** same_cdi (default)
| +|Philips|VideoPac (videopac)|1978|`videopac`|.bin .zip .7z|**retroarch:** o2em (default)
| +|Sammy|Atomiswave (atomiswave)|2003|`atomiswave`|.lst .bin .dat .zip .7z|**retroarch:** flycast2021 (default)
**retroarch:** flycast
**flycast:** flycast-sa
| +|Sega|Dreamcast (dreamcast)|1998|`dreamcast`|.cdi .gdi .chd .m3u .cue|**retroarch:** flycast2021 (default)
**retroarch:** flycast
**flycast:** flycast-sa
| +|Sega|Game Gear (gamegear)|1990|`gamegear`|.bin .gg .zip .7z|**retroarch:** gearsystem (default)
**retroarch:** genesis_plus_gx
**retroarch:** picodrive
**retroarch:** smsplus
**mednafen:** gg
| +|Sega|Game Gear (Hacks) (ggh)|1990|`gamegearh`|.bin .gg .zip .7z|**retroarch:** gearsystem (default)
**retroarch:** genesis_plus_gx
**retroarch:** picodrive
**retroarch:** smsplus
**mednafen:** gg
| +|Sega|Genesis (genesis)|1989|`genesis`|.bin .gen .md .sg .smd .zip .7z|**retroarch:** genesis_plus_gx (default)
**retroarch:** genesis_plus_gx_wide
**retroarch:** picodrive
**mednafen:** md
| +|Sega|Genesis (Hacks) (genh)|1989|`genh`|.bin .gen .md .sg .smd .zip .7z|**retroarch:** genesis_plus_gx (default)
**retroarch:** genesis_plus_gx_wide
**retroarch:** picodrive
**mednafen:** md
| +|Sega|Master System (mastersystem)|1985|`mastersystem`|.bin .sms .zip .7z|**retroarch:** gearsystem (default)
**retroarch:** genesis_plus_gx
**retroarch:** picodrive
**retroarch:** smsplus
**mednafen:** sms
| +|Sega|Mega CD (megacd)|1991|`megacd`|.chd .cue .iso .m3u|**retroarch:** genesis_plus_gx (default)
**retroarch:** picodrive
| +|Sega|Mega Drive (Hacks) (megadriveh)|1990|`megadriveh`|.bin .gen .md .sg .smd .zip .7z|**retroarch:** genesis_plus_gx (default)
**retroarch:** genesis_plus_gx_wide
**retroarch:** picodrive
**mednafen:** md
| +|Sega|Mega Drive (megadrive)|1990|`megadrive`|.bin .gen .md .sg .smd .zip .7z|**retroarch:** genesis_plus_gx (default)
**retroarch:** genesis_plus_gx_wide
**retroarch:** picodrive
**mednafen:** md
| +|Sega|Mega Drive (megadrive-japan)|1988|`megadrive-japan`|.bin .gen .md .sg .smd .zip .7z|**retroarch:** genesis_plus_gx (default)
**retroarch:** genesis_plus_gx_wide
**retroarch:** picodrive
**mednafen:** md
| +|Sega|Naomi (naomi)|1998|`naomi`|.lst .bin .dat .zip .7z|**retroarch:** flycast2021 (default)
**retroarch:** flycast
**flycast:** flycast-sa
| +|Sega|Saturn (saturn)|1994|`saturn`|.cue .chd .iso .zip|**yabasanshiro:** yabasanshiro-sa (default)
**retroarch:** yabasanshiro
| +|Sega|Sega 32X (sega32x)|1994|`sega32x`|.32x .smd .bin .md .zip .7z|**retroarch:** picodrive (default)
| +|Sega|Sega CD (segacd)|1991|`segacd`|.chd .cue .iso .m3u|**retroarch:** genesis_plus_gx (default)
**retroarch:** picodrive
| +|Sega|SG-1000 (sg-1000)|1983|`sg-1000`|.bin .sg .zip .7z|**retroarch:** gearsystem (default)
**retroarch:** genesis_plus_gx
**retroarch:** picodrive
| +|Sega|ST-V (st-v)|1995|`st-v`|.zip .ZIP|| +|Sharp|X1 (x1)|1982|`x1`|.dx1 .2d .2hd .tfd .d88 .88d .hdm .xdf .dup .tap .cmd .zip .7z|**retroarch:** x1 (default)
| +|Sharp|x68000 (x68000)|1987|`x68000`|.dim .img .d88 .hdm .dup .2hd .xdf .hdf .cmd .m3u .zip .7z|**retroarch:** px68k (default)
| +|Sinclair|ZX Spectrum (zxspectrum)|1982|`zxspectrum`|.tzx .tap .z80 .rzx .scl .trd .dsk .zip .7z|**retroarch:** fuse
| +|Sinclair|ZX81 (zx81)|1981|`zx81`|.tzx .p .t81 .zip .7z|**retroarch:** 81 (default)
| +|Smith Engineering|Vectrex (vectrex)|1982|`vectrex`|.bin .gam .vec .zip .7z|**retroarch:** vecx (default)
| +|SNK|Neo Geo (neogeo)|1990|`neogeo`|.7z .zip .neo|**retroarch:** fbneo (default)
**retroarch:** mame2003_plus
**retroarch:** fbalpha2012
**retroarch:** fbalpha2019
**retroarch:** mame2010
**retroarch:** mame2015
**retroarch:** mame
**retroarch:** geolith
| +|SNK|Neo Geo CD (neocd)|1994|`neocd`|.cue .iso .chd|**retroarch:** neocd (default)
**retroarch:** fbneo
| +|SNK|Neo Geo Pocket (ngp)|1998|`ngp`|.ngp .ngc .zip .7z|**retroarch:** beetle_ngp (default)
**retroarch:** race
**mednafen:** ngp
| +|SNK|Neo Geo Pocket Color (ngpc)|1999|`ngpc`|.ngp .ngc .zip .7z|**retroarch:** beetle_ngp (default)
**retroarch:** race
**mednafen:** ngp
| +|Sony|PlayStation (psx)|1994|`psx`|.bin .cue .img .mdf .pbp .toc .cbn .m3u .ccd .chd .iso|**retroarch:** pcsx_rearmed32 (default)
**retroarch:** pcsx_rearmed
**duckstation:** duckstation-sa
**retroarch:** swanstation
| +|Sony|PlayStation Portable (psp)|2004|`psp`|.iso .cso .pbp .chd|**ppsspp:** ppsspp-sa (default)
**retroarch:** ppsspp
| +|Sony|PSP Minis (pspminis)|2004|`pspminis`|.iso .cso .pbp .chd|**ppsspp:** ppsspp-sa (default)
**retroarch:** ppsspp
| +|Sun Microsystems|J2ME (j2me)|2002|`j2me`|.jar|**retroarch:** freej2me (default)
| +|Thomson|MO/TO family (TO7, TO7/70, TO8, TO8D, TO9, TO9+, MO5 and MO6) (moto)|1982|`moto`|.fd .sap .k7 .m7 .m5 .rom|**retroarch:** theodore (default)
| +|Various|CHIP-8 / S-CHIP / XO-CHIP (chip-8)|1978|`chip-8`|.ch8 .sc8 .xo8|**retroarch:** jaxe (default)
| +|Various|EasyRPG (easyrpg)|2003|`easyrpg`|.zip .easyrpg .ldb|**retroarch:** easyrpg (default)
| +|Various|OpenBOR (openbor)|2003|`openbor`|.pak|**OpenBOR:** OpenBOR (default)
| +|Various|ScummVM (scummvm)|2001|`games`|.sh .svm .scummvm|**scummvmsa:** scummvm (default)
**retroarch:** scummvm
| +|Various|Vircon32 (vircon32)|2021|`vircon32`|.v32|**retroarch:** vircon32 (default)
| +|Various|WASM-4 (wasm4)|2017|`wasm4`|.wasm .wat|**retroarch:** wasm4 (default)
| +|Watara|Supervision (supervision)|1992|`supervision`|.sv .zip .7z|**retroarch:** potator (default)
| +|Welback Holdings|Mega Duck (megaduck)|1993|`megaduck`|.bin .zip .7z|**retroarch:** sameduck (default)
| diff --git a/licenses/0BSD.txt b/licenses/0BSD.txt new file mode 100644 index 0000000000..4322122aec --- /dev/null +++ b/licenses/0BSD.txt @@ -0,0 +1,11 @@ +Permission to use, copy, modify, and/or distribute this +software for any purpose with or without fee is hereby granted. + +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/7-Zip.txt b/licenses/7-Zip.txt new file mode 100644 index 0000000000..c9e858fe10 --- /dev/null +++ b/licenses/7-Zip.txt @@ -0,0 +1,90 @@ + 7-Zip source code + ~~~~~~~~~~~~~~~~~ + License for use and distribution + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + 7-Zip Copyright (C) 1999-2020 Igor Pavlov. + + The licenses for files are: + + 1) CPP/7zip/Compress/Rar* files: the "GNU LGPL" with "unRAR license restriction" + 2) CPP/7zip/Compress/LzfseDecoder.cpp: the "BSD 3-clause License" + 3) Some files are "public domain" files, if "public domain" status is stated in source file. + 4) the "GNU LGPL" for all other files. If there is no license information in + some source file, that file is under the "GNU LGPL". + + The "GNU LGPL" with "unRAR license restriction" means that you must follow both + "GNU LGPL" rules and "unRAR license restriction" rules. + + + + + GNU LGPL information + -------------------- + + 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.1 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 + + + + + BSD 3-clause License + -------------------- + + The "BSD 3-clause License" is used for the code in LzfseDecoder.cpp that implements LZFSE data decompression. + That code was derived from the code in the "LZFSE compression library" developed by Apple Inc, + that also uses the "BSD 3-clause License": + + ---- + Copyright (c) 2015-2016, Apple Inc. All rights reserved. + + 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. Neither the name of the copyright holder(s) nor the names of any 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 OWNER 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. + ---- + + + + + unRAR license restriction + ------------------------- + + The decompression engine for RAR archives was developed using source + code of unRAR program. + All copyrights to original unRAR code are owned by Alexander Roshal. + + The license for original unRAR code has the following restriction: + + The unRAR sources cannot be used to re-create the RAR compression algorithm, + which is proprietary. Distribution of modified unRAR sources in separate form + or as a part of other software is permitted, provided that it is clearly + stated in the documentation and source comments that the code may + not be used to develop a RAR (WinRAR) compatible archiver. + + + -- + Igor Pavlov diff --git a/licenses/APL-1.0.txt b/licenses/APL-1.0.txt new file mode 100644 index 0000000000..4fe4111fec --- /dev/null +++ b/licenses/APL-1.0.txt @@ -0,0 +1,799 @@ +ADAPTIVE PUBLIC LICENSE +Version 1.0 + +THE LICENSED WORK IS PROVIDED UNDER THE TERMS OF THIS ADAPTIVE PUBLIC LICENSE +("LICENSE"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE LICENSED WORK CONSTITUTES +RECIPIENT'S ACCEPTANCE OF THIS LICENSE AND ITS TERMS, WHETHER OR NOT SUCH +RECIPIENT READS THE TERMS OF THIS LICENSE. "LICENSED WORK" AND "RECIPIENT" +ARE DEFINED BELOW. + +IMPORTANT NOTE: This License is "adaptive", and the generic version or another +version of an Adaptive Public License should not be relied upon to determine +your rights and obligations under this License. You must read the specific +Adaptive Public License that you receive with the Licensed Work, as certain +terms are defined at the outset by the Initial Contributor. + +See Section 2.2 below, Exhibit A attached, and any Suppfile.txt accompanying +this License to determine the specific adaptive features applicable to this +License. For example, without limiting the foregoing, (a) for selected choice +of law and jurisdiction see Part 3 of Exhibit A; (b) for the selected definition +of Third Party see Part 4 of Exhibit A; and (c) for selected patent licensing +terms (if any) see Section 2.2 below and Part 6 of Exhibit A. + +1. DEFINITIONS. + +1.1. "CONTRIBUTION" means: + +(a) In the case of the Initial Contributor, the Initial Work distributed under +this License by the Initial Contributor; and +(b) In the case of each Subsequent Contributor, the Subsequent Work originating +from and distributed by such Subsequent Contributor. + +1.2. "DESIGNATED WEB SITE" means the web site having the URL identified in +Part 1 of Exhibit A, which URL may be changed by the Initial Contributor by +posting on the current Designated Web Site the new URL for at least sixty +(60) days. + +1.3. "DISTRIBUTOR" means any Person that distributes the Licensed Work or +any portion thereof to at least one Third Party. + +1.4. "ELECTRONIC DISTRIBUTION MECHANISM" means any mechanism generally accepted +in the software development community for the electronic transfer of data. + +1.5. "EXECUTABLE" means the Licensed Work in any form other than Source Code. + +1.6. "GOVERNING JURISDICTION" means the state, province or other legal jurisdiction +identified in Part 3 of Exhibit A. + +1.7. "INDEPENDENT MODULE" means a separate module of software and/or data +that is not a derivative work of or copied from the Licensed Work or any portion +thereof. In addition, a module does not qualify as an Independent Module but +instead forms part of the Licensed Work if the module: (a) is embedded in +the Licensed Work; (b) is included by reference in the Licensed Work other +than by a function call or a class reference; or (c) must be included or contained, +in whole or in part, within a file directory or subdirectory actually containing +files making up the Licensed Work. + +1.8. "INITIAL CONTRIBUTOR" means the Person or entity identified as the Initial +Contributor in the notice required by Part 1 of Exhibit A. + +1.9. "INITIAL WORK" means the initial Source Code, object code (if any) and +documentation for the computer program identified in Part 2 of Exhibit A, +as such Source Code, object code and documentation is distributed under this +License by the Initial Contributor. + +1.10. "LARGER WORK" means a work that combines the Licensed Work or portions +thereof with code not governed by this License. + +1.11. "LICENSED WORK" means the Initial Work and/or any Subsequent Work, in +each case including portions thereof. + +1.12. "LICENSE NOTICE" has the meaning assigned in Part 5 of Exhibit A. + +1.13. "MODIFICATION" or "MODIFICATIONS" means any change to and/or addition +to the Licensed Work. + +1.14. "PERSON" means an individual or other legal entity, including a corporation, +partnership or other body. + +1.15. "RECIPIENT" means any Person who receives or obtains the Licensed Work +under this License (by way of example, without limiting the foregoing, any +Subsequent Contributor or Distributor). + +1.16. "SOURCE CODE" means the source code for a computer program, including +the source code for all modules and components of the computer program, plus +any associated interface definition files, and scripts used to control compilation +and installation of an executable. + +1.17. "SUBSEQUENT CONTRIBUTOR" means any Person that makes or contributes +to the making of any Subsequent Work and that distributes that Subsequent +Work to at least one Third Party. + +1.18. "SUBSEQUENT WORK" means a work that has resulted or arises from changes +to and/or additions to: + + (a) the Initial Work; + (b) any other Subsequent Work; or +(c) to any combination of the Initial Work and any such other Subsequent Work; +where such changes and/or additions originate from a Subsequent Contributor. +A Subsequent Work will "originate" from a Subsequent Contributor if the Subsequent +Work was a result of efforts by such Subsequent Contributor (or anyone acting +on such Subsequent Contributor's behalf, such as, a contractor or other entity +that is engaged by or under the direction of the Subsequent Contributor). +For greater certainty, a Subsequent Work expressly excludes and shall not +capture within its meaning any Independent Module. + +1.19. "SUPPLEMENT FILE" means a file distributed with the Licensed Work having +a file name "suppfile.txt". + +1.20. "THIRD PARTY" has the meaning assigned in Part 4 of Exhibit A. + +2. LICENSE. + +2.1. COPYRIGHT LICENSE FROM INITIAL AND SUBSEQUENT CONTRIBUTORS. + +(a) Subject to the terms of this License, the Initial Contributor hereby grants +each Recipient a world-wide, royalty-free, non-exclusive copyright license +to: + +(i) reproduce, prepare derivative works of, publicly display, publicly perform, +distribute and sublicense the Initial Work; and +(ii) reproduce, publicly display, publicly perform, distribute, and sublicense +any derivative works (if any) prepared by Recipient; +in Source Code and Executable form, either with other Modifications, on an +unmodified basis, or as part of a Larger Work. + +(b) Subject to the terms of this License, each Subsequent Contributor hereby +grants each Recipient a world-wide, royalty-free, non-exclusive copyright +license to: + +(i) reproduce, prepare derivative works of, publicly display, publicly perform, +distribute and sublicense the Subsequent Work of such Subsequent Contributor; +and +(ii) reproduce, publicly display, publicly perform, distribute, and sublicense +any derivative works (if any) prepared by Recipient; +in Source Code and Executable form, either with other Modifications, on an +unmodified basis, or as part of a Larger Work. + +2.2. PATENT LICENSE FROM INITIAL AND SUBSEQUENT CONTRIBUTORS. + +(a) This License does not include or grant any patent license whatsoever from +the Initial Contributor, Subsequent Contributor, or any Distributor unless, +at the time the Initial Work is first distributed or made available under +this License (as the case may be), the Initial Contributor has selected pursuant +to Part 6 of Exhibit A the patent terms in paragraphs A, B, C, D and E from +Part 6 of Exhibit A. If this is not done then the Initial Work and any other +Subsequent Work is made available under the License without any patent license +(the "PATENTS-EXCLUDED LICENSE"). +(b) However, the Initial Contributor may subsequently distribute or make available +(as the case may be) future copies of: (1) the Initial Work; or (2) any Licensed +Work distributed by the Initial Contributor which includes the Initial Work +(or any portion thereof) and/or any Modification made by the Initial Contributor; +available under a License which includes a patent license (the "PATENTS-INCLUDED +LICENSE") by selecting pursuant to Part 6 of Exhibit A the patent terms in +paragraphs A, B, C, D and E from Part 6 of Exhibit A, when the Initial Contributor +distributes or makes available (as the case may be) such future copies under +this License. +(c) If any Recipient receives or obtains one or more copies of the Initial +Work or any other portion of the Licensed Work under the Patents-Included +License, then all licensing of such copies under this License shall include +the terms in paragraphs A, B, C, D and E from Part 6 of Exhibit A and that +Recipient shall not be able to rely upon the Patents-Excluded License for +any such copies. However, all Recipients that receive one or more copies of +the Initial Work or any other portion of the Licensed Work under a copy of +the License which includes the Patents-Excluded License shall have no patent +license with respect to such copies received under the Patents-Excluded License +and availability and distribution of such copies, including Modifications +made by such Recipient to such copies, shall be under a copy of the License +without any patent license. +(d) Where a Recipient uses in combination or combines any copy of the Licensed +Work (or portion thereof) licensed under a copy of the License having a Patents-Excluded +License with any copy of the Licensed Work (or portion thereof) licensed under +a copy of the License having a Patents-Included License, the combination (and +any portion thereof) shall, from the first time such Recipient uses, makes +available or distributes the combination (as the case may be), be subject +to only the terms of the License having the Patents-Included License which +shall include the terms in paragraphs A, B, C, D and E from Part 6 of Exhibit +A. + +2.3. ACKNOWLEDGEMENT AND DISCLAIMER. +Recipient understands and agrees that although Initial Contributor and each +Subsequent Contributor grants the licenses to its Contributions set forth +herein, no representation, warranty, guarantee or assurance is provided by +any Initial Contributor, Subsequent Contributor, or Distributor that the Licensed +Work does not infringe the patent or other intellectual property rights of +any other entity. Initial Contributor, Subsequent Contributor, and each Distributor +disclaims any liability to Recipient for claims brought by any other entity +based on infringement of intellectual property rights or otherwise, in relation +to the Licensed Works. As a condition to exercising the rights and licenses +granted hereunder, each Recipient hereby assumes sole responsibility to secure +any other intellectual property rights needed, if any. For example, without +limiting the foregoing disclaimers, if a third party patent license is required +to allow Recipient to distribute the Licensed Work, it is Recipient's responsibility +to acquire that license before distributing the Licensed Work. + +2.4. RESERVATION. +Nothing in this License shall be deemed to grant any rights to trademarks, +copyrights, patents, trade secrets or any other intellectual property of Initial +Contributor, Subsequent Contributor, or Distributor except as expressly stated +herein. + +3. DISTRIBUTION OBLIGATIONS. + +3.1. DISTRIBUTION GENERALLY. + +(a) A Subsequent Contributor shall make that Subsequent Contributor's Subsequent +Work(s) available to the public via an Electronic Distribution Mechanism for +a period of at least twelve (12) months. The aforesaid twelve (12) month period +shall begin within a reasonable time after the creation of the Subsequent +Work and no later than sixty (60) days after first distribution of that Subsequent +Contributor's Subsequent Work. +(b) All Distributors must distribute the Licensed Work in accordance with +the terms of the License, and must include a copy of this License (including +without limitation Exhibit A and the accompanying Supplement File) with each +copy of the Licensed Work distributed. In particular, this License must be +prominently distributed with the Licensed Work in a file called "license.txt." +In addition, the License Notice in Part 5 of Exhibit A must be included at +the beginning of all Source Code files, and viewable to a user in any executable +such that the License Notice is reasonably brought to the attention of any +party using the Licensed Work. + +3.2. EXECUTABLE DISTRIBUTIONS OF THE LICENSED WORK. +A Distributor may choose to distribute the Licensed Work, or any portion thereof, +in Executable form (an "EXECUTABLE DISTRIBUTION") to any third party, under +the terms of Section 2 of this License, provided the Executable Distribution +is made available under and accompanied by a copy of this License, AND provided +at least ONE of the following conditions is fulfilled: + +(a) The Executable Distribution must be accompanied by the Source Code for +the Licensed Work making up the Executable Distribution, and the Source Code +must be distributed on the same media as the Executable Distribution or using +an Electronic Distribution Mechanism; or +(b) The Executable Distribution must be accompanied with a written offer, +valid for at least thirty six (36) months, to give any third party under the +terms of this License, for a charge no more than the cost of physically performing +source distribution, a complete machine-readable copy of the Source Code for +the Licensed Work making up the Executable Distribution, to be available and +distributed using an Electronic Distribution Mechanism, and such Executable +Distribution must remain available in Source Code form to any third party +via the Electronic Distribution Mechanism (or any replacement Electronic Distribution +Mechanism the particular Distributor may reasonably need to turn to as a substitute) +for said at least thirty six (36) months. + +For greater certainty, the above-noted requirements apply to any Licensed +Work or portion thereof distributed to any third party in Executable form, +whether such distribution is made alone, in combination with a Larger Work +or Independent Modules, or in some other combination. + +3.3. SOURCE CODE DISTRIBUTIONS. +When a Distributor makes the Licensed Work, or any portion thereof, available +to any Person in Source Code form, it must be made available under this License +and a copy of this License must be included with each copy of the Source Code, +situated so that the copy of the License is conspicuously brought to the attention +of that Person. For greater clarification, this Section 3.3 applies to all +distribution of the Licensed Work in any Source Code form. A Distributor may +charge a fee for the physical act of transferring a copy, which charge shall +be no more than the cost of physically performing source distribution. + +3.4. REQUIRED NOTICES IN SOURCE CODE. +Each Subsequent Contributor must ensure that the notice set out in Part 5 +of Exhibit A is included in each file of the Source Code for each Subsequent +Work originating from that particular Subsequent Contributor, if such notice +is not already included in each such file. If it is not possible to put such +notice in a particular Source Code file due to its structure, then the Subsequent +Contributor must include such notice in a location (such as a relevant directory +in which the file is stored) where a user would be likely to look for such +a notice. + +3.5. NO DISTRIBUTION REQUIREMENTS FOR INTERNALLY USED MODIFICATIONS. +Notwithstanding Sections 3.2, 3.3 and 3.4, Recipient may, internally within +its own corporation or organization use the Licensed Work, including the Initial +Work and Subsequent Works, and make Modifications for internal use within +Recipient's own corporation or organization (collectively, "INTERNAL USE MODIFICATIONS"). +The Recipient shall have no obligation to distribute, in either Source Code +or Executable form, any such Internal Use Modifications made by Recipient +in the course of such internal use, except where required below in this Section +3.5. All Internal Use Modifications distributed to any Person, whether or +not a Third Party, shall be distributed pursuant to and be accompanied by +the terms of this License. If the Recipient chooses to distribute any such +Internal Use Modifications to any Third Party, then the Recipient shall be +deemed a Subsequent Contributor, and any such Internal Use Modifications distributed +to any Third Party shall be deemed a Subsequent Work originating from that +Subsequent Contributor, and shall from the first such instance become part +of the Licensed Work that must thereafter be distributed and made available +to third parties in accordance with the terms of Sections 3.1 to 3.4 inclusive. + +3.6. INDEPENDENT MODULES. +This License shall not apply to Independent Modules of any Initial Contributor, +Subsequent Contributor, Distributor or any Recipient, and such Independent +Modules may be licensed or made available under one or more separate license +agreements. + +3.7. LARGER WORKS. +Any Distributor or Recipient may create or contribute to a Larger Work by +combining any of the Licensed Work with other code not governed by the terms +of this License, and may distribute the Larger Work as one or more products. +However, in any such case, Distributor or Recipient (as the case may be) must +make sure that the requirements of this License are fulfilled for the Licensed +Work portion of the Larger Work. + +3.8. DESCRIPTION OF DISTRIBUTED MODIFICATIONS. + +(a) Each Subsequent Contributor (including the Initial Contributor where the +Initial Contributor also qualifies as a Subsequent Contributor) must cause +each Subsequent Work created or contributed to by that Subsequent Contributor +to contain a file documenting the changes, in accordance with the requirements +of Part 1 of the Supplement File, that such Subsequent Contributor made in +the creation or contribution to that Subsequent Work. If no Supplement File +exists or no requirements are set out in Part 1 of the Supplement File, then +there are no requirements for Subsequent Contributors to document changes +that they make resulting in Subsequent Works. +(b) The Initial Contributor may at any time introduce requirements or add +to or change earlier requirements (in each case, the "EARLIER DESCRIPTION +REQUIREMENTS") for documenting changes resulting in Subsequent Works by revising +Part 1 of each copy of the Supplement File distributed by the Initial Contributor +with future copies of the Licensed Work so that Part 1 then contains new requirements +(the "NEW DESCRIPTION REQUIREMENTS") for documenting such changes. +(c) Any Recipient receiving at any time any copy of an Initial Work or any +Subsequent Work under a copy of this License (in each case, an "Earlier LICENSED +COPY") having the Earlier Description Requirements may choose, with respect +to each such Earlier Licensed Copy, to comply with the Earlier Description +Requirements or the New Description Requirements. Where a Recipient chooses +to comply with the New Description Requirements, that Recipient will, when +thereafter distributing any copies of any such Earlier Licensed Copy, include +a Supplement File having a section entitled Part 1 that contains a copy of +the New Description Requirements. +(d) For greater certainty, the intent of Part 1 of the Supplement File is +to provide a mechanism (if any) by which Subsequent Contributors must document +changes that they make to the Licensed Work resulting in Subsequent Works. +Part 1 of any Supplement File shall not be used to increase or reduce the +scope of the license granted in Article 2 of this License or in any other +way increase or decrease the rights and obligations of any Recipient, and +shall at no time serve as the basis for terminating the License. Further, +a Recipient can be required to correct and change its documentation procedures +to comply with Part 1 of the Supplement File, but cannot be penalised with +damages. Part 1 of any Supplement File is only binding on each Recipient of +any Licensed Work to the extent Part 1 sets out the requirements for documenting +changes to the Initial Work or any Subsequent Work. +(e) An example of a set of requirements for documenting changes and contributions +made by Subsequent Contributor is set out in Part 7 of Exhibit A of this License. +Part 7 is a sample only and is not binding on Recipients, unless (subject +to the earlier paragraphs of this Section 3.8) those are the requirements +that the Initial Contributor includes in Part 1 of the Supplement File with +the copies of the Initial Work distributed under this License. + +3.9. USE OF DISTRIBUTOR NAME. +The name of a Distributor may not be used by any other Distributor to endorse +or promote the Licensed Work or products derived from the Licensed Work, without +prior written permission. + +3.10. LIMITED RECOGNITION OF INITIAL CONTRIBUTOR. + +(a) As a modest attribution to the Initial Contributor, in the hope that its +promotional value may help justify the time, money and effort invested in +writing the Initial Work, the Initial Contributor may include in Part 2 of +the Supplement File a requirement that each time an executable program resulting +from the Initial Work or any Subsequent Work, or a program dependent thereon, +is launched or run, a prominent display of the Initial Contributor's attribution +information must occur (the "ATTRIBUTION INFORMATION"). The Attribution Information +must be included at the beginning of each Source Code file. For greater certainty, +the Initial Contributor may specify in the Supplement File that the above +attribution requirement only applies to an executable program resulting from +the Initial Work or any Subsequent Work, but not a program dependent thereon. +The intent is to provide for reasonably modest attribution, therefore the +Initial Contributor may not require Recipients to display, at any time, more +than the following Attribution Information: (a) a copyright notice including +the name of the Initial Contributor; (b) a word or one phrase (not exceeding +10 words); (c) one digital image or graphic provided with the Initial Work; +and (d) a URL (collectively, the "ATTRIBUTION LIMITS"). +(b) If no Supplement File exists, or no Attribution Information is set out +in Part 2 of the Supplement File, then there are no requirements for Recipients +to display any Attribution Information of the Initial Contributor. +(c) Each Recipient acknowledges that all trademarks, service marks and/or +trade names contained within Part 2 of the Supplement File distributed with +the Licensed Work are the exclusive property of the Initial Contributor and +may only be used with the permission of the Initial Contributor, or under +circumstances otherwise permitted by law, or as expressly set out in this +License. +3.11. For greater certainty, any description or attribution provisions contained +within a Supplement File may only be used to specify the nature of the description +or attribution requirements, as the case may be. Any provision in a Supplement +File that otherwise purports to modify, vary, nullify or amend any right, +obligation or representation contained herein shall be deemed void to that +extent, and shall be of no force or effect. + +4. COMMERCIAL USE AND INDEMNITY. + +4.1. COMMERCIAL SERVICES. +A Recipient ("COMMERCIAL RECIPIENT") may choose to offer, and to charge a +fee for, warranty, support, indemnity or liability obligations (collectively, +"SERVICES") to one or more other Recipients or Distributors. However, such +Commercial Recipient may do so only on that Commercial Recipient's own behalf, +and not on behalf of any other Distributor or Recipient, and Commercial Recipient +must make it clear than any such warranty, support, indemnity or liability +obligation(s) is/are offered by Commercial Recipient alone. At no time may +Commercial Recipient use any Services to deny any party the Licensed Work +in Source Code or Executable form when so required under any of the other +terms of this License. For greater certainty, this Section 4.1 does not diminish +any of the other terms of this License, including without limitation the obligation +of the Commercial Recipient as a Distributor, when distributing any of the +Licensed Work in Source Code or Executable form, to make such distribution +royalty-free (subject to the right to charge a fee of no more than the cost +of physically performing Source Code or Executable distribution (as the case +may be)). + +4.2. INDEMNITY. +Commercial distributors of software may accept certain responsibilities with +respect to end users, business partners and the like. While this License is +intended to facilitate the commercial use of the Licensed Work, the Distributor +who includes any of the Licensed Work in a commercial product offering should +do so in a manner which does not create potential liability for other Distributors. +Therefore, if a Distributor includes the Licensed Work in a commercial product +offering or offers any Services, such Distributor ("COMMERCIAL DISTRIBUTOR") +hereby agrees to defend and indemnify every other Distributor or Subsequent +Contributor (in each case an "INDEMNIFIED PARTY") against any losses, damages +and costs (collectively "LOSSES") arising from claims, lawsuits and other +legal actions brought by a third party against the Indemnified Party to the +extent caused by the acts or omissions of such Commercial Distributor in connection +with its distribution of any of the Licensed Work in a commercial product +offering or in connection with any Services. The obligations in this section +do not apply to any claims or Losses relating to any actual or alleged intellectual +property infringement. In order to qualify, an Indemnified Party must: (a) +promptly notify the Commercial Distributor in writing of such claim; and (b) +allow the Commercial Distributor to control, and co-operate with the Commercial +Distributor in, the defense and any related settlement negotiations. The Indemnified +Party may participate in any such claim at its own expense. + +5. VERSIONS OF THE LICENSE. + +5.1. NEW VERSIONS. +The Initial Contributor may publish revised and/or new versions of the License +from time to time. Each version will be given a distinguishing version number. + +5.2. EFFECT OF NEW VERSIONS. +Once the Licensed Work or any portion thereof has been published by Initial +Contributor under a particular version of the License, Recipient may choose +to continue to use it under the terms of that version. However, if a Recipient +chooses to use the Licensed Work under the terms of any subsequent version +of the License published by the Initial Contributor, then from the date of +making this choice, the Recipient must comply with the terms of that subsequent +version with respect to all further reproduction, preparation of derivative +works, public display of, public performance of, distribution and sublicensing +by the Recipient in connection with the Licensed Work. No one other than the +Initial Contributor has the right to modify the terms applicable to the Licensed +Work + +6. DISCLAIMER OF WARRANTY. + +6.1. GENERAL DISCLAIMER. +EXCEPT AS EXPRESSLY SET FORTH IN THIS LICENSE, THE LICENSED WORK IS PROVIDED +UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT ANY REPRESENTATION, WARRANTY, +GUARANTEE, ASSURANCE OR CONDITION OF ANY KIND, EITHER EXPRESSED OR IMPLIED, +INCLUDING, WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, +MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO +THE QUALITY AND PERFORMANCE OF THE LICENSED WORK IS WITH RECIPIENT. SHOULD +ANY LICENSED WORK PROVE DEFECTIVE IN ANY RESPECT, RECIPIENT (NOT THE INITIAL +CONTRIBUTOR OR ANY SUBSEQUENT CONTRIBUTOR) ASSUMES THE COST OF ANY NECESSARY +SERVICING, REPAIR OR CORRECTION. THIS CLAUSE CONSTITUTES AN ESSENTIAL PART +OF THIS LICENSE. NO USE OF ANY LICENSED WORK IS AUTHORIZED HEREUNDER EXCEPT +UNDER THIS LICENSE INCLUDING WITHOUT LIMITATION THIS DISCLAIMER. + +6.2. RESPONSIBILITY OF RECIPIENTS. +Each Recipient is solely responsible for determining the appropriateness of +using and distributing the Licensed Work and assumes all risks associated +with its exercise of rights under this License, including but not limited +to the risks and costs of program errors, compliance with applicable laws, +damage to or loss of data, programs or equipment, and unavailability or interruption +of operations. + +7. TERMINATION. + +7.1. This License shall continue until terminated in accordance with the express +terms herein. + +7.2. Recipient may choose to terminate this License automatically at any time. + +7.3. This License, including without limitation the rights granted hereunder +to a particular Recipient, will terminate automatically if such Recipient +is in material breach of any of the terms of this License and fails to cure +such breach within sixty (60) days of becoming aware of the breach. Without +limiting the foregoing, any material breach by such Recipient of any term +of any other License under which such Recipient is granted any rights to the +Licensed Work shall constitute a material breach of this License. + +7.4. Upon termination of this License by or with respect to a particular Recipient +for any reason, all rights granted hereunder and under any other License to +that Recipient shall terminate. However, all sublicenses to the Licensed Work +which were previously properly granted by such Recipient under a copy of this +License (in each case, an "Other License" and in plural, "Other Licenses") +shall survive any such termination of this License, including without limitation +the rights and obligations under such Other Licenses as set out in their respective +Sections 2, 3, 4, 5, 6, 7 and 8, mutatis mutandis, for so long as the respective +sublicensees (i.e. other Recipients) remain in compliance with the terms of +the copy of this License under which such sublicensees received rights to +the Licensed Work. Any termination of such Other Licenses shall be pursuant +to their respective Section 7, mutatis mutandis. Provisions which, by their +nature, must remain in effect beyond the termination of this License shall +survive. + +7.5. Upon any termination of this License by or with respect to a particular +Recipient, Sections 4.1, 4.2, 6.1, 6.2, 7.4, 7.5, 8.1, and 8.2, together with +all provisions of this License necessary for the interpretation and enforcement +of same, shall expressly survive such termination. + +8. LIMITATION OF LIABILITY. + +8.1. IN NO EVENT SHALL ANY OF INITIAL CONTRIBUTOR, ITS SUBSIDIARIES, OR AFFILIATES, +OR ANY OF ITS OR THEIR RESPECTIVE OFFICERS, DIRECTORS, EMPLOYEES, AND/OR AGENTS +(AS THE CASE MAY BE), HAVE ANY LIABILITY FOR ANY DIRECT DAMAGES, INDIRECT +DAMAGES, PUNITIVE DAMAGES, INCIDENTAL DAMAGES, SPECIAL DAMAGES, EXEMPLARY +DAMAGES, CONSEQUENTIAL DAMAGES OR ANY OTHER DAMAGES WHATSOEVER (INCLUDING +WITHOUT LIMITATION LOSS OF USE, DATA OR PROFITS, OR ANY OTHER LOSS ARISING +OUT OF OR IN ANY WAY RELATED TO THE USE, INABILITY TO USE, UNAUTHORIZED USE, +PERFORMANCE, OR NON-PERFORMANCE OF THE LICENSED WORK OR ANY PART THEREOF OR +THE PROVISION OF OR FAILURE TO PROVIDE SUPPORT SERVICES, OR THAT RESULT FROM +ERRORS, DEFECTS, OMISSIONS, DELAYS IN OPERATION OR TRANSMISSION, OR ANY OTHER +FAILURE OF PERFORMANCE), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +IN RELATION TO OR ARISING IN ANY WAY OUT OF THIS LICENSE OR THE USE OR DISTRIBUTION +OF THE LICENSED WORK OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN +IF ADVISED 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. +THIS CLAUSE CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY LICENSED +WORK IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS LICENSE INCLUDING WITHOUT LIMITATION +THE LIMITATIONS SET FORTH IN THIS SECTION 8.1. + +8.2. EXCEPT AS EXPRESSLY SET FORTH IN THIS LICENSE, EACH RECIPIENT SHALL NOT +HAVE ANY LIABILITY FOR ANY EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING +WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE LICENSED WORK OR +THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED 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. + +9. GOVERNING LAW AND LEGAL ACTION. + +9.1. This License shall be governed by and construed in accordance with the +laws of the Governing Jurisdiction assigned in Part 3 of Exhibit A, without +regard to its conflict of law provisions. No party may bring a legal action +under this License more than one year after the cause of the action arose. +Each party waives its rights (if any) to a jury trial in any litigation arising +under this License. Note that if the Governing Jurisdiction is not assigned +in Part 3 of Exhibit A, then the Governing Jurisdiction shall be the State +of New York. + +9.2. The courts of the Governing Jurisdiction shall have jurisdiction, but +not exclusive jurisdiction, to entertain and determine all disputes and claims, +whether for specific performance, injunction, damages or otherwise, both at +law and in equity, arising out of or in any way relating to this License, +including without limitation, the legality, validity, existence and enforceability +of this License. Each party to this License hereby irrevocably attorns to +and accepts the jurisdiction of the courts of the Governing Jurisdiction for +such purposes. + +9.3. Except as expressly set forth elsewhere herein, in the event of any action +or proceeding brought by any party against another under this License the +prevailing party shall be entitled to recover all costs and expenses including +the fees of its attorneys in such action or proceeding in such amount as the +court may adjudge reasonable. + +10. MISCELLANEOUS. + +10.1. The obligations imposed by this License are for the benefit of the Initial +Contributor and any Recipient, and each Recipient acknowledges and agrees +that the Initial Contributor and/or any other Recipient may enforce the terms +and conditions of this License against any Recipient. + +10.2. This License represents the complete agreement concerning subject matter +hereof, and supersedes and cancels all previous oral and written communications, +representations, agreements and understandings between the parties with respect +to the subject matter hereof. + +10.3. The application of the United Nations Convention on Contracts for the +International Sale of Goods is expressly excluded. + +10.4. The language in all parts of this License shall be in all cases construed +simply according to its fair meaning, and not strictly for or against any +of the parties hereto. Any law or regulation which provides that the language +of a contract shall be construed against the drafter shall not apply to this +License. + +10.5. If any provision of this License is invalid or unenforceable under the +laws of the Governing Jurisdiction, it shall not affect the validity or enforceability +of the remainder of the terms of this License, and without further action +by the parties hereto, such provision shall be reformed to the minimum extent +necessary to make such provision valid and enforceable. + +10.6. The paragraph headings of this License are for reference and convenience +only and are not a part of this License, and they shall have no effect upon +the construction or interpretation of any part hereof. + +10.7. Each of the terms "including", "include" and "includes", when used in +this License, is not limiting whether or not non-limiting language (such as +"without limitation" or "but not limited to" or words of similar import) is +used with reference thereto. + +10.8. The parties hereto acknowledge they have expressly required that this +License and notices relating thereto be drafted in the English language. + +//***THE LICENSE TERMS END HERE (OTHER THAN AS SET OUT IN EXHIBIT A).***// + +EXHIBIT A (to the Adaptive Public License) + +PART 1: INITIAL CONTRIBUTOR AND DESIGNATED WEB SITE + +The Initial Contributor is: +____________________________________________________ +  +[Enter full name of Initial Contributor] + +Address of Initial Contributor: +________________________________________________ +  +________________________________________________ +  +________________________________________________ +  +[Enter address above] + +The Designated Web Site is: +__________________________________________________ +  +[Enter URL for Designated Web Site of Initial Contributor] + +NOTE: The Initial Contributor is to complete this Part 1, along with Parts +2, 3, and 5, and, if applicable, Parts 4 and 6. + +PART 2: INITIAL WORK + +The Initial Work comprises the computer program(s) distributed by the Initial +Contributor having the following title(s): _______________________________________________. + +The date on which the Initial Work was first available under this License: +_________________ + +PART 3: GOVERNING JURISDICTION + +For the purposes of this License, the Governing Jurisdiction is _________________________________________________. +
[Initial Contributor to Enter Governing Jurisdiction here] + +PART 4: THIRD PARTIES + +For the purposes of this License, "Third Party" has the definition set forth +below in the ONE paragraph selected by the Initial Contributor from paragraphs +A, B, C, D and E when the Initial Work is distributed or otherwise made available +by the Initial Contributor. To select one of the following paragraphs, the +Initial Contributor must place an "X" or "x" in the selection box alongside +the one respective paragraph selected. +SELECTION +  +BOX PARAGRAPH +[  ] A. "THIRD PARTY" means any third party. +  +  +[  ] B. "THIRD PARTY" means any third party except for any of the following: +(a) a wholly owned subsidiary of the Subsequent Contributor in question; (b) +a legal entity (the "PARENT") that wholly owns the Subsequent Contributor +in question; or (c) a wholly owned subsidiary of the wholly owned subsidiary +in (a) or of the Parent in (b). +  +  +[  ] C. "THIRD PARTY" means any third party except for any of the following: +(a) any Person directly or indirectly owning a majority of the voting interest +in the Subsequent Contributor or (b) any Person in which the Subsequent Contributor +directly or indirectly owns a majority voting interest. +  +  +[  ] D. "THIRD PARTY" means any third party except for any Person directly +or indirectly controlled by the Subsequent Contributor. For purposes of this +definition, "control" shall mean the power to direct or cause the direction +of, the management and policies of such Person whether through the ownership +of voting interests, by contract, or otherwise. +  +  +[  ] E. "THIRD PARTY" means any third party except for any Person directly +or indirectly controlling, controlled by, or under common control with the +Subsequent Contributor. For purposes of this definition, "control" shall mean +the power to direct or cause the direction of, the management and policies +of such Person whether through the ownership of voting interests, by contract, +or otherwise. +The default definition of "THIRD PARTY" is the definition set forth in paragraph +A, if NONE OR MORE THAN ONE of paragraphs A, B, C, D or E in this Part 4 are +selected by the Initial Contributor. + +PART 5: NOTICE + +THE LICENSED WORK IS PROVIDED UNDER THE TERMS OF THE ADAPTIVE PUBLIC LICENSE +("LICENSE") AS FIRST COMPLETED BY: ______________________ [Insert the name +of the Initial Contributor here]. ANY USE, PUBLIC DISPLAY, PUBLIC PERFORMANCE, +REPRODUCTION OR DISTRIBUTION OF, OR PREPARATION OF DERIVATIVE WORKS BASED +ON, THE LICENSED WORK CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS LICENSE AND +ITS TERMS, WHETHER OR NOT SUCH RECIPIENT READS THE TERMS OF THE LICENSE. "LICENSED +WORK" AND "RECIPIENT" ARE DEFINED IN THE LICENSE. A COPY OF THE LICENSE IS +LOCATED IN THE TEXT FILE ENTITLED "LICENSE.TXT" ACCOMPANYING THE CONTENTS +OF THIS FILE. IF A COPY OF THE LICENSE DOES NOT ACCOMPANY THIS FILE, A COPY +OF THE LICENSE MAY ALSO BE OBTAINED AT THE FOLLOWING WEB SITE: ___________________________________________________[Insert +Initial Contributor's Designated Web Site here] + +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. + +PART 6: PATENT LICENSING TERMS + +For the purposes of this License, paragraphs A, B, C, D and E of this Part +6 of Exhibit A are only incorporated and form part of the terms of the License +if the Initial Contributor places an "X" or "x" in the selection box alongside +the YES answer to the question immediately below. + +Is this a Patents-Included License pursuant to Section 2.2 of the License? +YES [      ] +NO [      ] + +By default, if YES is not selected by the Initial Contributor, the answer +is NO. + +A. For the purposes of the paragraphs in this Part 6 of Exhibit A, "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 granted herein. + +B. The Initial Contributor hereby grants all Recipients a world-wide, royalty-free, +non-exclusive license, subject to third party intellectual property claims, +under patent claim(s) Licensable by the Initial Contributor that are or would +be infringed by the making, using, selling, offering for sale, having made, +importing, exporting, transfer or disposal of such Initial Work or any portion +thereof. Notwithstanding the foregoing, no patent license is granted under +this Paragraph B by the Initial Contributor: (1) for any code that the Initial +Contributor deletes from the Initial Work (or any portion thereof) distributed +by the Initial Contributor prior to such distribution; (2) for any Modifications +made to the Initial Work (or any portion thereof) by any other Person; or +(3) separate from the Initial Work (or portions thereof) distributed or made +available by the Initial Contributor. + +C. Effective upon distribution by a Subsequent Contributor to a Third Party +of any Modifications made by that Subsequent Contributor, such Subsequent +Contributor hereby grants all Recipients a world-wide, royalty-free, non-exclusive +license, subject to third party intellectual property claims, under patent +claim(s) Licensable by such Subsequent Contributor that are or would be infringed +by the making, using, selling, offering for sale, having made, importing, +exporting, transfer or disposal of any such Modifications made by that Subsequent +Contributor alone and/or in combination with its Subsequent Work (or portions +of such combination) to make, use, sell, offer for sale, have made, import, +export, transfer and otherwise dispose of: +(1) Modifications made by that Subsequent Contributor (or portions thereof); +and +(2) the combination of Modifications made by that Subsequent Contributor with +its Subsequent Work (or portions of such combination); +(collectively and in each case, the "SUBSEQUENT CONTRIBUTOR VERSION"). +Notwithstanding the foregoing, no patent license is granted under this Paragraph +C by such Subsequent Contributor: (1) for any code that such Subsequent Contributor +deletes from the Subsequent Contributor Version (or any portion thereof) distributed +by the Subsequent Contributor prior to such distribution; (2) for any Modifications +made to the Subsequent Contributor Version (or any portion thereof) by any +other Person; or (3) separate from the Subsequent Contributor Version (or +portions thereof) distributed or made available by the Subsequent Contributor. + +D. Effective upon distribution of any Licensed Work by a Distributor to a +Third Party, such Distributor hereby grants all Recipients a world-wide, royalty-free, +non-exclusive license, subject to third party intellectual property claims, +under patent claim(s) Licensable by such Distributor that are or would be +infringed by the making, using, selling, offering for sale, having made, importing, +exporting, transfer or disposal of any such Licensed Work distributed by such +Distributor, to make, use, sell, offer for sale, have made, import, export, +transfer and otherwise dispose of such Licensed Work or portions thereof (collectively +and in each case, the "DISTRIBUTOR VERSION"). Notwithstanding the foregoing, +no patent license is granted under this Paragraph D by such Distributor: (1) +for any code that such Distributor deletes from the Distributor Version (or +any portion thereof) distributed by the Distributor prior to such distribution; +(2) for any Modifications made to the Distributor Version (or any portion +thereof) by any other Person; or (3) separate from the Distributor Version +(or portions thereof) distributed or made available by the Distributor. + +E. If Recipient institutes patent litigation against another Recipient (a +"USER") with respect to a patent applicable to a computer program or software +(including a cross-claim or counterclaim in a lawsuit, and whether or not +any of the patent claims are directed to a system, method, process, apparatus, +device, product, article of manufacture or any other form of patent claim), +then any patent or copyright license granted by that User to such Recipient +under this License or any other copy of this License shall terminate. The +termination shall be effective ninety (90) days after notice of termination +from User to Recipient, unless the Recipient withdraws the patent litigation +claim before the end of the ninety (90) day period. To be effective, any such +notice of license termination must include a specific list of applicable patents +and/or a copy of the copyrighted work of User that User alleges will be infringed +by Recipient upon License termination. License termination is only effective +with respect to patents and/or copyrights for which proper notice has been +given. + +PART 7: SAMPLE REQUIREMENTS FOR THE DESCRIPTION OF DISTRIBUTED MODIFICATIONS + +Each Subsequent Contributor (including the Initial Contributor where the Initial +Contributor qualifies as a Subsequent Contributor) is invited (but not required) +to cause each Subsequent Work created or contributed to by that Subsequent +Contributor to contain a file documenting the changes such Subsequent Contributor +made to create that Subsequent Work and the date of any change. //***EXHIBIT +A ENDS HERE.***// diff --git a/licenses/APSL-2.0.txt b/licenses/APSL-2.0.txt new file mode 100644 index 0000000000..6489d0ab4d --- /dev/null +++ b/licenses/APSL-2.0.txt @@ -0,0 +1,330 @@ +APPLE PUBLIC SOURCE LICENSE +Version 2.0 - August 6, 2003 + +Please read this License carefully before downloading this software. By downloading +or using this software, you are agreeing to be bound by the terms of this +License. If you do not or cannot agree to the terms of this License, please +do not download or use the software. + +Apple Note: In January 2007, Apple changed its corporate name from "Apple +Computer, Inc." to "Apple Inc." This change has been reflected below and +copyright years updated, but no other changes have been made to the APSL 2.0. + +1. General; Definitions. This License applies to any program or other work +which Apple Inc. ("Apple") makes publicly available and which contains a notice +placed by Apple identifying such program or work as "Original Code" and stating +that it is subject to the terms of this Apple Public Source License version +2.0 ("License"). As used in this License: + +1.1 "Applicable Patent Rights" mean: (a) in the case where Apple is the +grantor of rights, (i) claims of patents that are now or hereafter acquired, +owned by or assigned to Apple and (ii) that cover subject matter contained +in the Original Code, but only to the extent necessary to use, reproduce and/or +distribute the Original Code without infringement; and (b) in the case where +You are the grantor of rights, (i) claims of patents that are now or hereafter +acquired, owned by or assigned to You and (ii) that cover subject matter in +Your Modifications, taken alone or in combination with Original Code. + +1.2 "Contributor" means any person or entity that creates or contributes to +the creation of Modifications. + +1.3 "Covered Code" means the Original Code, Modifications, the combination +of Original Code and any Modifications, and/or any respective portions thereof. + +1.4 "Externally Deploy" means: (a) to sublicense, distribute or otherwise +make Covered Code available, directly or indirectly, to anyone other than +You; and/or (b) to use Covered Code, alone or as part of a Larger Work, in +any way to provide a service, including but not limited to delivery of content, +through electronic communication with a client other than You. + +1.5 "Larger Work" means a work which combines Covered Code or portions thereof +with code not governed by the terms of this License. + +1.6 "Modifications" mean any addition to, deletion from, and/or change to, +the substance and/or structure of the Original Code, any previous Modifications, +the combination of Original Code and any previous Modifications, and/or any +respective portions thereof. When code is released as a series of files, +a Modification is: (a) any addition to or deletion from the contents of a +file containing Covered Code; and/or (b) any new file or other representation +of computer program statements that contains any part of Covered Code. + +1.7 "Original Code" means (a) the Source Code of a program or other work as +originally made available by Apple under this License, including the Source +Code of any updates or upgrades to such programs or works made available by +Apple under this License, and that has been expressly identified by Apple +as such in the header file(s) of such work; and (b) the object code compiled +from such Source Code and originally made available by Apple under this License + +1.8 "Source Code" means the human readable form of a program or other work +that is suitable 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 (object code). + +1.9 "You" or "Your" means an individual or a legal entity exercising rights +under this License. For legal entities, "You" or "Your" includes any entity +which controls, is controlled by, or is under common control with, You, where +"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 fifty percent (50%) or more of the outstanding shares or beneficial ownership +of such entity. + +2. Permitted Uses; Conditions & Restrictions. Subject to the terms and conditions +of this License, Apple hereby grants You, effective on the date You accept +this License and download the Original Code, a world-wide, royalty-free, non-exclusive +license, to the extent of Apple's Applicable Patent Rights and copyrights +covering the Original Code, to do the following: + +2.1 Unmodified Code. You may use, reproduce, display, perform, internally +distribute within Your organization, and Externally Deploy verbatim, unmodified +copies of the Original Code, for commercial or non-commercial purposes, provided +that in each instance: + +(a) You must retain and reproduce in all copies of Original Code the copyright +and other proprietary notices and disclaimers of Apple as they appear in the +Original Code, and keep intact all notices in the Original Code that refer +to this License; and + +(b) You must include a copy of this License with every copy of Source Code +of Covered Code and documentation You distribute or Externally Deploy, and +You may not offer or impose any terms on such Source Code that alter or restrict +this License or the recipients' rights hereunder, except as permitted under +Section 6. + +2.2 Modified Code. You may modify Covered Code and use, reproduce, display, +perform, internally distribute within Your organization, and Externally Deploy +Your Modifications and Covered Code, for commercial or non-commercial purposes, +provided that in each instance You also meet all of these conditions: + +(a) You must satisfy all the conditions of Section 2.1 with respect to the +Source Code of the Covered Code; + +(b) You must duplicate, to the extent it does not already exist, the notice +in Exhibit A in each file of the Source Code of all Your Modifications, and +cause the modified files to carry prominent notices stating that You changed +the files and the date of any change; and + +(c) If You Externally Deploy Your Modifications, You must make Source Code +of all Your Externally Deployed Modifications either available to those to +whom You have Externally Deployed Your Modifications, or publicly available. +Source Code of Your Externally Deployed Modifications must be released under +the terms set forth in this License, including the license grants set forth +in Section 3 below, for as long as you Externally Deploy the Covered Code +or twelve (12) months from the date of initial External Deployment, whichever +is longer. You should preferably distribute the Source Code of Your Externally +Deployed Modifications electronically (e.g. download from a web site). + +2.3 Distribution of Executable Versions. In addition, if You Externally Deploy +Covered Code (Original Code and/or Modifications) in object code, executable +form only, You must include a prominent notice, in the code itself as well +as in related documentation, stating that Source Code of the Covered Code +is available under the terms of this License with information on how and where +to obtain such Source Code. + +2.4 Third Party Rights. You expressly acknowledge and agree that although +Apple and each Contributor grants the licenses to their respective portions +of the Covered Code set forth herein, no assurances are provided by Apple +or any Contributor that the Covered Code does not infringe the patent or other +intellectual property rights of any other entity. Apple and each Contributor +disclaim any liability to You for claims brought by any other entity based +on infringement of intellectual property rights or otherwise. As a condition +to exercising the rights and licenses granted hereunder, You hereby assume +sole responsibility to secure any other intellectual property rights needed, +if any. For example, if a third party patent license is required to allow +You to distribute the Covered Code, it is Your responsibility to acquire that +license before distributing the Covered Code. + +3. Your Grants. In consideration of, and as a condition to, the licenses +granted to You under this License, You hereby grant to any person or entity +receiving or distributing Covered Code under this License a non-exclusive, +royalty-free, perpetual, irrevocable license, under Your Applicable Patent +Rights and other intellectual property rights (other than patent) owned or +controlled by You, to use, reproduce, display, perform, modify, sublicense, +distribute and Externally Deploy Your Modifications of the same scope and +extent as Apple's licenses under Sections 2.1 and 2.2 above. + +4. 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 each such instance, You must make sure the requirements +of this License are fulfilled for the Covered Code or any portion thereof. + +5. Limitations on Patent License. Except as expressly stated in Section +2, no other patent rights, express or implied, are granted by Apple herein. +Modifications and/or Larger Works may require additional patent licenses from +Apple which Apple may grant in its sole discretion. + +6. Additional Terms. You may choose to offer, and to charge a fee for, warranty, +support, indemnity or liability obligations and/or other rights consistent +with the scope of the license granted herein ("Additional Terms") to one or +more recipients of Covered Code. However, You may do so only on Your own behalf +and as Your sole responsibility, and not on behalf of Apple or any Contributor. +You must obtain the recipient's agreement that any such Additional Terms are +offered by You alone, and You hereby agree to indemnify, defend and hold Apple +and every Contributor harmless for any liability incurred by or claims asserted +against Apple or such Contributor by reason of any such Additional Terms. + +7. Versions of the License. Apple may publish revised and/or new versions +of this License from time to time. Each version will be given a distinguishing +version number. Once Original Code has been published under a particular +version of this License, You may continue to use it under the terms of that +version. You may also choose to use such Original Code under the terms of +any subsequent version of this License published by Apple. No one other than +Apple has the right to modify the terms applicable to Covered Code created +under this License. + +8. NO WARRANTY OR SUPPORT. The Covered Code may contain in whole or in part +pre-release, untested, or not fully tested works. The Covered Code may contain +errors that could cause failures or loss of data, and may be incomplete or +contain inaccuracies. You expressly acknowledge and agree that use of the +Covered Code, or any portion thereof, is at Your sole and entire risk. THE +COVERED CODE IS PROVIDED "AS IS" AND WITHOUT WARRANTY, UPGRADES OR SUPPORT +OF ANY KIND AND APPLE AND APPLE'S LICENSOR(S) (COLLECTIVELY REFERRED TO AS +"APPLE" FOR THE PURPOSES OF SECTIONS 8 AND 9) AND ALL CONTRIBUTORS EXPRESSLY +DISCLAIM ALL WARRANTIES AND/OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, +BUT NOT LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF MERCHANTABILITY, +OF SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY, +OF QUIET ENJOYMENT, AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. APPLE AND +EACH CONTRIBUTOR DOES NOT WARRANT AGAINST INTERFERENCE WITH YOUR ENJOYMENT +OF THE COVERED CODE, THAT THE FUNCTIONS CONTAINED IN THE COVERED CODE WILL +MEET YOUR REQUIREMENTS, THAT THE OPERATION OF THE COVERED CODE WILL BE UNINTERRUPTED +OR ERROR-FREE, OR THAT DEFECTS IN THE COVERED CODE WILL BE CORRECTED. NO +ORAL OR WRITTEN INFORMATION OR ADVICE GIVEN BY APPLE, AN APPLE AUTHORIZED +REPRESENTATIVE OR ANY CONTRIBUTOR SHALL CREATE A WARRANTY. You acknowledge +that the Covered Code is not intended for use in the operation of nuclear +facilities, aircraft navigation, communication systems, or air traffic control +machines in which case the failure of the Covered Code could lead to death, +personal injury, or severe physical or environmental damage. + +9. LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO EVENT +SHALL APPLE OR ANY CONTRIBUTOR BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT +OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING TO THIS LICENSE OR YOUR +USE OR INABILITY TO USE THE COVERED CODE, OR ANY PORTION THEREOF, WHETHER +UNDER A THEORY OF CONTRACT, WARRANTY, TORT (INCLUDING NEGLIGENCE), PRODUCTS +LIABILITY OR OTHERWISE, EVEN IF APPLE OR SUCH CONTRIBUTOR HAS BEEN ADVISED +OF THE POSSIBILITY OF SUCH DAMAGES AND NOTWITHSTANDING THE FAILURE OF ESSENTIAL +PURPOSE OF ANY REMEDY. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OF LIABILITY +OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT APPLY TO +YOU. In no event shall Apple's total liability to You for all damages (other +than as may be required by applicable law) under this License exceed the amount +of fifty dollars ($50.00). + +10. Trademarks. This License does not grant any rights to use the trademarks +or trade names "Apple", "Mac", "Mac OS", "QuickTime", "QuickTime Streaming +Server" or any other trademarks, service marks, logos or trade names belonging +to Apple (collectively "Apple Marks") or to any trademark, service mark, logo +or trade name belonging to any Contributor. You agree not to use any Apple +Marks in or as part of the name of products derived from the Original Code +or to endorse or promote products derived from the Original Code other than +as expressly permitted by and in strict compliance at all times with Apple's +third party trademark usage guidelines which are posted at http://www.apple.com/legal/guidelinesfor3rdparties.html. + +11. Ownership. Subject to the licenses granted under this License, each Contributor +retains all rights, title and interest in and to any Modifications made by +such Contributor. Apple retains all rights, title and interest in and to +the Original Code and any Modifications made by or on behalf of Apple ("Apple +Modifications"), and such Apple Modifications will not be automatically subject +to this License. Apple may, at its sole discretion, choose to license such +Apple Modifications under this License, or on different terms from those contained +in this License or may choose not to license them at all. + +12. Termination. + +12.1 Termination. This License and the rights granted hereunder will terminate: + +(a) automatically without notice from Apple if You fail to comply with any +term(s) of this License and fail to cure such breach within 30 days of becoming +aware of such breach; + +(b) immediately in the event of the circumstances described in Section 13.5(b); +or + +(c) automatically without notice from Apple if You, at any time during the +term of this License, commence an action for patent infringement against Apple; +provided that Apple did not first commence an action for patent infringement +against You in that instance. + +12.2 Effect of Termination. Upon termination, You agree to immediately stop +any further use, reproduction, modification, sublicensing and distribution +of the Covered Code. All sublicenses to the Covered Code which have been +properly granted prior to termination shall survive any termination of this +License. Provisions which, by their nature, should remain in effect beyond +the termination of this License shall survive, including but not limited to +Sections 3, 5, 8, 9, 10, 11, 12.2 and 13. No party will be liable to any +other for compensation, indemnity or damages of any sort solely as a result +of terminating this License in accordance with its terms, and termination +of this License will be without prejudice to any other right or remedy of +any party. + +13. Miscellaneous. + +13.1 Government End Users. The Covered Code is a "commercial item" as defined +in FAR 2.101. Government software and technical data rights in the Covered +Code include only those rights customarily provided to the public as defined +in this License. This customary commercial license in technical data and software +is provided in accordance with FAR 12.211 (Technical Data) and 12.212 (Computer +Software) and, for Department of Defense purchases, DFAR 252.227-7015 (Technical +Data -- Commercial Items) and 227.7202-3 (Rights in Commercial Computer Software +or Computer Software Documentation). Accordingly, all U.S. Government End +Users acquire Covered Code with only those rights set forth herein. + +13.2 Relationship of Parties. This License will not be construed as creating +an agency, partnership, joint venture or any other form of legal association +between or among You, Apple or any Contributor, and You will not represent +to the contrary, whether expressly, by implication, appearance or otherwise. + +13.3 Independent Development. Nothing in this License will impair Apple's +right to acquire, license, develop, have others develop for it, market and/or +distribute technology or products that perform the same or similar functions +as, or otherwise compete with, Modifications, Larger Works, technology or +products that You may develop, produce, market or distribute. + +13.4 Waiver; Construction. Failure by Apple or any Contributor to enforce +any provision of this License will not be deemed a waiver of future enforcement +of that or any other provision. Any law or regulation which provides that +the language of a contract shall be construed against the drafter will not +apply to this License. + +13.5 Severability. (a) If for any reason a court of competent jurisdiction +finds any provision of this License, or portion thereof, to be unenforceable, +that provision of the License will be enforced to the maximum extent permissible +so as to effect the economic benefits and intent of the parties, and the remainder +of this License will continue in full force and effect. (b) Notwithstanding +the foregoing, if applicable law prohibits or restricts You from fully and/or +specifically complying with Sections 2 and/or 3 or prevents the enforceability +of either of those Sections, this License will immediately terminate and You +must immediately discontinue any use of the Covered Code and destroy all copies +of it that are in your possession or control. + +13.6 Dispute Resolution. Any litigation or other dispute resolution between +You and Apple relating to this License shall take place in the Northern District +of California, and You and Apple hereby consent to the personal jurisdiction +of, and venue in, the state and federal courts within that District with respect +to this License. The application of the United Nations Convention on Contracts +for the International Sale of Goods is expressly excluded. + +13.7 Entire Agreement; Governing Law. This License constitutes the entire +agreement between the parties with respect to the subject matter hereof. +This License shall be governed by the laws of the United States and the State +of California, except that body of California law concerning conflicts of +law. + +Where You are located in the province of Quebec, Canada, the following clause +applies: The parties hereby confirm that they have requested that this License +and all related documents be drafted in English. Les parties ont exigé que +le présent contrat et tous les documents connexes soient rédigés en anglais. + +EXHIBIT A. + +"Portions Copyright (c) 1999-2007 Apple Inc. All Rights Reserved. + +This file contains Original Code and/or Modifications of Original Code as +defined in and that are subject to the Apple Public Source License Version +2.0 (the 'License'). You may not use this file except in compliance with +the License. Please obtain a copy of the License at http://www.opensource.apple.com/apsl/ +and read it before using this file. + +The 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, QUIET +ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the specific language +governing rights and limitations under the License." diff --git a/licenses/APSL.txt b/licenses/APSL.txt new file mode 100644 index 0000000000..a356de5114 --- /dev/null +++ b/licenses/APSL.txt @@ -0,0 +1,339 @@ +APPLE PUBLIC SOURCE LICENSE +Version 2.0 - August 6, 2003 + +Please read this License carefully before downloading this software. By +downloading or using this software, you are agreeing to be bound by the terms +of this License. If you do not or cannot agree to the terms of this License, +please do not download or use the software. + +Apple Note: In January 2007, Apple changed its corporate name from "Apple +Computer, Inc." to "Apple Inc." This change has been reflected below and +copyright years updated, but no other changes have been made to the APSL 2.0. + +1. General; Definitions. This License applies to any program or other +work which Apple Inc. ("Apple") makes publicly available and which contains a +notice placed by Apple identifying such program or work as "Original Code" and +stating that it is subject to the terms of this Apple Public Source License +version 2.0 ("License"). As used in this License: + +1.1 "Applicable Patent Rights" mean: (a) in the case where Apple is the +grantor of rights, (i) claims of patents that are now or hereafter acquired, +owned by or assigned to Apple and (ii) that cover subject matter contained in +the Original Code, but only to the extent necessary to use, reproduce and/or +distribute the Original Code without infringement; and (b) in the case where +You are the grantor of rights, (i) claims of patents that are now or hereafter +acquired, owned by or assigned to You and (ii) that cover subject matter in +Your Modifications, taken alone or in combination with Original Code. + +1.2 "Contributor" means any person or entity that creates or contributes +to the creation of Modifications. + +1.3 "Covered Code" means the Original Code, Modifications, the +combination of Original Code and any Modifications, and/or any respective +portions thereof. + +1.4 "Externally Deploy" means: (a) to sublicense, distribute or otherwise +make Covered Code available, directly or indirectly, to anyone other than You; +and/or (b) to use Covered Code, alone or as part of a Larger Work, in any way +to provide a service, including but not limited to delivery of content, +through electronic communication with a client other than You. + +1.5 "Larger Work" means a work which combines Covered Code or portions +thereof with code not governed by the terms of this License. + +1.6 "Modifications" mean any addition to, deletion from, and/or change to, +the substance and/or structure of the Original Code, any previous +Modifications, the combination of Original Code and any previous +Modifications, and/or any respective portions thereof. When code is released +as a series of files, a Modification is: (a) any addition to or deletion from +the contents of a file containing Covered Code; and/or (b) any new file or +other representation of computer program statements that contains any part of +Covered Code. + +1.7 "Original Code" means (a) the Source Code of a program or other work +as originally made available by Apple under this License, including the Source +Code of any updates or upgrades to such programs or works made available by +Apple under this License, and that has been expressly identified by Apple as +such in the header file(s) of such work; and (b) the object code compiled from +such Source Code and originally made available by Apple under this License + +1.8 "Source Code" means the human readable form of a program or other work +that is suitable 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 (object code). + +1.9 "You" or "Your" means an individual or a legal entity exercising +rights under this License. For legal entities, "You" or "Your" includes any +entity which controls, is controlled by, or is under common control with, You, +where "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 fifty percent (50%) or more of the outstanding shares or +beneficial ownership of such entity. + +2. Permitted Uses; Conditions & Restrictions. Subject to the terms and +conditions of this License, Apple hereby grants You, effective on the date You +accept this License and download the Original Code, a world-wide, +royalty-free, non-exclusive license, to the extent of Apple's Applicable +Patent Rights and copyrights covering the Original Code, to do the following: + +2.1 Unmodified Code. You may use, reproduce, display, perform, internally +distribute within Your organization, and Externally Deploy verbatim, +unmodified copies of the Original Code, for commercial or non-commercial +purposes, provided that in each instance: + +(a) You must retain and reproduce in all copies of Original Code the +copyright and other proprietary notices and disclaimers of Apple as they +appear in the Original Code, and keep intact all notices in the Original Code +that refer to this License; and + +(b) You must include a copy of this License with every copy of Source Code +of Covered Code and documentation You distribute or Externally Deploy, and You +may not offer or impose any terms on such Source Code that alter or restrict +this License or the recipients' rights hereunder, except as permitted under +Section 6. + +2.2 Modified Code. You may modify Covered Code and use, reproduce, +display, perform, internally distribute within Your organization, and +Externally Deploy Your Modifications and Covered Code, for commercial or +non-commercial purposes, provided that in each instance You also meet all of +these conditions: + +(a) You must satisfy all the conditions of Section 2.1 with respect to the +Source Code of the Covered Code; + +(b) You must duplicate, to the extent it does not already exist, the +notice in Exhibit A in each file of the Source Code of all Your Modifications, +and cause the modified files to carry prominent notices stating that You +changed the files and the date of any change; and + +(c) If You Externally Deploy Your Modifications, You must make Source Code +of all Your Externally Deployed Modifications either available to those to +whom You have Externally Deployed Your Modifications, or publicly available. +Source Code of Your Externally Deployed Modifications must be released under +the terms set forth in this License, including the license grants set forth in +Section 3 below, for as long as you Externally Deploy the Covered Code or +twelve (12) months from the date of initial External Deployment, whichever is +longer. You should preferably distribute the Source Code of Your Externally +Deployed Modifications electronically (e.g. download from a web site). + +2.3 Distribution of Executable Versions. In addition, if You Externally +Deploy Covered Code (Original Code and/or Modifications) in object code, +executable form only, You must include a prominent notice, in the code itself +as well as in related documentation, stating that Source Code of the Covered +Code is available under the terms of this License with information on how and +where to obtain such Source Code. + +2.4 Third Party Rights. You expressly acknowledge and agree that although +Apple and each Contributor grants the licenses to their respective portions of +the Covered Code set forth herein, no assurances are provided by Apple or any +Contributor that the Covered Code does not infringe the patent or other +intellectual property rights of any other entity. Apple and each Contributor +disclaim any liability to You for claims brought by any other entity based on +infringement of intellectual property rights or otherwise. As a condition to +exercising the rights and licenses granted hereunder, You hereby assume sole +responsibility to secure any other intellectual property rights needed, if +any. For example, if a third party patent license is required to allow You to +distribute the Covered Code, it is Your responsibility to acquire that license +before distributing the Covered Code. + +3. Your Grants. In consideration of, and as a condition to, the licenses +granted to You under this License, You hereby grant to any person or entity +receiving or distributing Covered Code under this License a non-exclusive, +royalty-free, perpetual, irrevocable license, under Your Applicable Patent +Rights and other intellectual property rights (other than patent) owned or +controlled by You, to use, reproduce, display, perform, modify, sublicense, +distribute and Externally Deploy Your Modifications of the same scope and +extent as Apple's licenses under Sections 2.1 and 2.2 above. + +4. 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 each such instance, You must make sure +the requirements of this License are fulfilled for the Covered Code or any +portion thereof. + +5. Limitations on Patent License. Except as expressly stated in Section +2, no other patent rights, express or implied, are granted by Apple herein. +Modifications and/or Larger Works may require additional patent licenses from +Apple which Apple may grant in its sole discretion. + +6. Additional Terms. You may choose to offer, and to charge a fee for, +warranty, support, indemnity or liability obligations and/or other rights +consistent with the scope of the license granted herein ("Additional Terms") +to one or more recipients of Covered Code. However, You may do so only on Your +own behalf and as Your sole responsibility, and not on behalf of Apple or any +Contributor. You must obtain the recipient's agreement that any such +Additional Terms are offered by You alone, and You hereby agree to indemnify, +defend and hold Apple and every Contributor harmless for any liability +incurred by or claims asserted against Apple or such Contributor by reason of +any such Additional Terms. + +7. Versions of the License. Apple may publish revised and/or new +versions of this License from time to time. Each version will be given a +distinguishing version number. Once Original Code has been published under a +particular version of this License, You may continue to use it under the terms +of that version. You may also choose to use such Original Code under the terms +of any subsequent version of this License published by Apple. No one other +than Apple has the right to modify the terms applicable to Covered Code +created under this License. + +8. NO WARRANTY OR SUPPORT. The Covered Code may contain in whole or in +part pre-release, untested, or not fully tested works. The Covered Code may +contain errors that could cause failures or loss of data, and may be +incomplete or contain inaccuracies. You expressly acknowledge and agree that +use of the Covered Code, or any portion thereof, is at Your sole and entire +risk. THE COVERED CODE IS PROVIDED "AS IS" AND WITHOUT WARRANTY, UPGRADES OR +SUPPORT OF ANY KIND AND APPLE AND APPLE'S LICENSOR(S) (COLLECTIVELY REFERRED +TO AS "APPLE" FOR THE PURPOSES OF SECTIONS 8 AND 9) AND ALL CONTRIBUTORS +EXPRESSLY DISCLAIM ALL WARRANTIES AND/OR CONDITIONS, EXPRESS OR IMPLIED, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF +MERCHANTABILITY, OF SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR PURPOSE, +OF ACCURACY, OF QUIET ENJOYMENT, AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. +APPLE AND EACH CONTRIBUTOR DOES NOT WARRANT AGAINST INTERFERENCE WITH YOUR +ENJOYMENT OF THE COVERED CODE, THAT THE FUNCTIONS CONTAINED IN THE COVERED +CODE WILL MEET YOUR REQUIREMENTS, THAT THE OPERATION OF THE COVERED CODE WILL +BE UNINTERRUPTED OR ERROR-FREE, OR THAT DEFECTS IN THE COVERED CODE WILL BE +CORRECTED. NO ORAL OR WRITTEN INFORMATION OR ADVICE GIVEN BY APPLE, AN APPLE +AUTHORIZED REPRESENTATIVE OR ANY CONTRIBUTOR SHALL CREATE A WARRANTY. You +acknowledge that the Covered Code is not intended for use in the operation of +nuclear facilities, aircraft navigation, communication systems, or air traffic +control machines in which case the failure of the Covered Code could lead to +death, personal injury, or severe physical or environmental damage. + +9. LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO +EVENT SHALL APPLE OR ANY CONTRIBUTOR BE LIABLE FOR ANY INCIDENTAL, SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING TO THIS LICENSE +OR YOUR USE OR INABILITY TO USE THE COVERED CODE, OR ANY PORTION THEREOF, +WHETHER UNDER A THEORY OF CONTRACT, WARRANTY, TORT (INCLUDING NEGLIGENCE), +PRODUCTS LIABILITY OR OTHERWISE, EVEN IF APPLE OR SUCH CONTRIBUTOR HAS BEEN +ADVISED OF THE POSSIBILITY OF SUCH DAMAGES AND NOTWITHSTANDING THE FAILURE OF +ESSENTIAL PURPOSE OF ANY REMEDY. SOME JURISDICTIONS DO NOT ALLOW THE +LIMITATION OF LIABILITY OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS +LIMITATION MAY NOT APPLY TO YOU. In no event shall Apple's total liability to +You for all damages (other than as may be required by applicable law) under +this License exceed the amount of fifty dollars ($50.00). + +10. Trademarks. This License does not grant any rights to use the +trademarks or trade names "Apple", "Mac", "Mac OS", "QuickTime", "QuickTime +Streaming Server" or any other trademarks, service marks, logos or trade names +belonging to Apple (collectively "Apple Marks") or to any trademark, service +mark, logo or trade name belonging to any Contributor. You agree not to use +any Apple Marks in or as part of the name of products derived from the +Original Code or to endorse or promote products derived from the Original Code +other than as expressly permitted by and in strict compliance at all times +with Apple's third party trademark usage guidelines which are posted at +http://www.apple.com/legal/guidelinesfor3rdparties.html. + +11. Ownership. Subject to the licenses granted under this License, each +Contributor retains all rights, title and interest in and to any Modifications +made by such Contributor. Apple retains all rights, title and interest in and +to the Original Code and any Modifications made by or on behalf of Apple +("Apple Modifications"), and such Apple Modifications will not be +automatically subject to this License. Apple may, at its sole discretion, +choose to license such Apple Modifications under this License, or on different +terms from those contained in this License or may choose not to license them +at all. + +12. Termination. + +12.1 Termination. This License and the rights granted hereunder will +terminate: + +(a) automatically without notice from Apple if You fail to comply with any +term(s) of this License and fail to cure such breach within 30 days of +becoming aware of such breach; +(b) immediately in the event of the circumstances described in Section +13.5(b); or +(c) automatically without notice from Apple if You, at any time during the +term of this License, commence an action for patent infringement against +Apple; provided that Apple did not first commence an action for patent +infringement against You in that instance. + +12.2 Effect of Termination. Upon termination, You agree to immediately +stop any further use, reproduction, modification, sublicensing and +distribution of the Covered Code. All sublicenses to the Covered Code which +have been properly granted prior to termination shall survive any termination +of this License. Provisions which, by their nature, should remain in effect +beyond the termination of this License shall survive, including but not +limited to Sections 3, 5, 8, 9, 10, 11, 12.2 and 13. No party will be liable +to any other for compensation, indemnity or damages of any sort solely as a +result of terminating this License in accordance with its terms, and +termination of this License will be without prejudice to any other right or +remedy of any party. + +13. Miscellaneous. + +13.1 Government End Users. The Covered Code is a "commercial item" as +defined in FAR 2.101. Government software and technical data rights in the +Covered Code include only those rights customarily provided to the public as +defined in this License. This customary commercial license in technical data +and software is provided in accordance with FAR 12.211 (Technical Data) and +12.212 (Computer Software) and, for Department of Defense purchases, DFAR +252.227-7015 (Technical Data -- Commercial Items) and 227.7202-3 (Rights in +Commercial Computer Software or Computer Software Documentation). +Accordingly, all U.S. Government End Users acquire Covered Code with only +those rights set forth herein. + +13.2 Relationship of Parties. This License will not be construed as +creating an agency, partnership, joint venture or any other form of legal +association between or among You, Apple or any Contributor, and You will not +represent to the contrary, whether expressly, by implication, appearance or +otherwise. + +13.3 Independent Development. Nothing in this License will impair Apple's +right to acquire, license, develop, have others develop for it, market and/or +distribute technology or products that perform the same or similar functions +as, or otherwise compete with, Modifications, Larger Works, technology or +products that You may develop, produce, market or distribute. + +13.4 Waiver; Construction. Failure by Apple or any Contributor to enforce +any provision of this License will not be deemed a waiver of future +enforcement of that or any other provision. Any law or regulation which +provides that the language of a contract shall be construed against the +drafter will not apply to this License. + +13.5 Severability. (a) If for any reason a court of competent jurisdiction +finds any provision of this License, or portion thereof, to be unenforceable, +that provision of the License will be enforced to the maximum extent +permissible so as to effect the economic benefits and intent of the parties, +and the remainder of this License will continue in full force and effect. (b) +Notwithstanding the foregoing, if applicable law prohibits or restricts You +from fully and/or specifically complying with Sections 2 and/or 3 or prevents +the enforceability of either of those Sections, this License will immediately +terminate and You must immediately discontinue any use of the Covered Code and +destroy all copies of it that are in your possession or control. + +13.6 Dispute Resolution. Any litigation or other dispute resolution +between You and Apple relating to this License shall take place in the +Northern District of California, and You and Apple hereby consent to the +personal jurisdiction of, and venue in, the state and federal courts within +that District with respect to this License. The application of the United +Nations Convention on Contracts for the International Sale of Goods is +expressly excluded. + +13.7 Entire Agreement; Governing Law. This License constitutes the entire +agreement between the parties with respect to the subject matter hereof. This +License shall be governed by the laws of the United States and the State of +California, except that body of California law concerning conflicts of law. + +Where You are located in the province of Quebec, Canada, the following clause +applies: The parties hereby confirm that they have requested that this +License and all related documents be drafted in English. Les parties ont +exigé que le présent contrat et tous les documents connexes soient rédigés +en anglais. + +EXHIBIT A. + +"Portions Copyright (c) 1999-2007 Apple Inc. All Rights Reserved. + +This file contains Original Code and/or Modifications of Original Code as +defined in and that are subject to the Apple Public Source License Version 2.0 +(the 'License'). You may not use this file except in compliance with the +License. Please obtain a copy of the License at +http://www.opensource.apple.com/apsl/ and read it before using this file. + +The 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, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the +specific language governing rights and limitations under the License." diff --git a/licenses/ATI.txt b/licenses/ATI.txt new file mode 100644 index 0000000000..c1ab25ebf0 --- /dev/null +++ b/licenses/ATI.txt @@ -0,0 +1,188 @@ + +AMD Software End User License Agreement + +PLEASE READ THIS LICENSE CAREFULLY BEFORE USING THE SOFTWARE. BY +DOWNLOADING, INSTALLING, COPYING OR USING THE SOFTWARE, YOU ARE AGREEING TO +BE BOUND BY THE TERMS OF THIS LICENSE. IF YOU ARE ACCESSING THE SOFTWARE +ELECTRONICALLY, SIGNIFY YOUR AGREEMENT BY CLICKING THE "AGREE/ACCEPT" +BUTTON. IF YOU DO NOT AGREE TO THE TERMS OF THIS LICENSE, PROMPTLY RETURN +THE SOFTWARE TO THE PLACE WHERE YOU OBTAINED IT AND (IF APPLICABLE) YOUR +MONEY WILL BE REFUNDED OR IF THE SOFTWARE WAS ACCESSED ELECTRONICALLY CLICK +"DISAGREE/DECLINE". + +1. License. Advanced Micro Devices, Inc., on behalf of itself, its +subsidiaries and licensors (referred collectively as "AMD") grants to you +the following non-exclusive, right to use the software accompanying +this License (hereinafter "Software") subject to the following terms and +limitations: + + +(a) Regardless of the media upon which it is distributed, the Software is +licensed to you for use solely in conjunction with AMD hardware products to +which the Software relates ("AMD Hardware"). + +(b) You own the medium on which the Software is recorded, but AMD and, if +applicable, its licensors retain title to the Software and related +documentation. + +(c) You may: + + i) use the Software solely in connection with the AMD Hardware on a + single computer; + + ii) make one copy of the Software in machine-readable form for backup + purposes only. You must reproduce on such copy AMD's copyright notice and + any other proprietary legends that were on the original copy of the + Software; + + iii) transfer all your license rights in the Software provided you must + also transfer a copy of this License, the backup copy of the Software, + the AMD Hardware and the related documentation and provided the other + party reads and agrees to accept the terms and conditions of this + License. Upon such transfer your license rights are then terminated. + +(d) In addition to the license terms above, with respect to portions of +the Software in source code or binary form designed exclusively for use +with the Linux operating system ("AMD Linux Code"), you may use, display, +modify, copy, distribute, allow others to re-distribute, package and re- +package such AMD Linux Code for commercial and non-commercial purposes, +provided that: + + i) all binary components of the AMD Linux Code are not modified in any + way; + + ii) the AMD Linux Code is only used as part of the Software and in + connection with AMD Hardware; + + iii) all copyright notices of AMD are reproduced and you refer to these + license terms; + + iv) you may not offer or impose any terms on the use of AMD Linux + Code that alter or restrict this License; and + + v) if you have modified the AMD Linux Code, such modifications will be + made publicly available and are licensed under the same terms provided + herein to AMD or any other third party without further restriction, + royalty or any other license requirement; + + vi) to the extent there is any AMD sample or control panel source + code included in the AMD Linux Code, no rights are granted to modify such + code except for portions thereof that may be subject to third party + license terms that grant such rights; + + vii) no rights are granted to distribute the binary form of the AMD Linux + Kernel Module made by linking the AMD Proprietary Kernel Library and the + AMD Kernel Compatibility Layer binary compiled using Linux kernel + headers; + + viii) AMD is not obligated to provide any maintenance or technical + support for any code resulting from AMD Linux Code. + +2. Restrictions. The Software contains copyrighted and patented material, +trade secrets and other proprietary material. In order to protect them, +and except as permitted by this license or applicable legislation, you may +not: + + a) decompile, reverse engineer, disassemble or otherwise reduce the + Software to a human-perceivable form; + + b) modify, network, rent, lend, loan, distribute or create derivative + works based upon the Software in whole or in part; or + + c) electronically transmit the Software from one computer to another or + over a network or otherwise transfer the Software except as permitted by + this License. + +3. Termination. This License is effective until terminated. You may +terminate this License at any time by destroying the Software, related +documentation and all copies thereof. This License will terminate +immediately without notice from AMD if you fail to comply with any +provision of this License. Upon termination you must destroy the Software, +related documentation and all copies thereof. + +4. Government End Users. If you are acquiring the Software on behalf of +any unit or agency of the United States Government, the following +provisions apply. The Government agrees the Software and documentation +were developed at private expense and are provided with "RESTRICTED +RIGHTS". Use, duplication, or disclosure by the Government is subject to +restrictions as set forth in DFARS 227.7202-1(a) and 227.7202-3(a) (1995), +DFARS 252.227-7013(c)(1)(ii) (Oct 1988), FAR 12.212(a)(1995), FAR 52.227- +19, (June 1987) or FAR 52.227-14(ALT III) (June 1987),as amended from time +to time. In the event that this License, or any part thereof, is deemed +inconsistent with the minimum rights identified in the Restricted Rights +provisions, the minimum rights shall prevail. + +5. No Other License. No rights or licenses are granted by AMD under this +License, expressly or by implication, with respect to any proprietary +information or patent, copyright, trade secret or other intellectual +property right owned or controlled by AMD, except as expressly provided in +this License. + +6. Additional Licenses. DISTRIBUTION OR USE OF THE SOFTWARE WITH AN +OPERATING SYSTEM MAY REQUIRE ADDITIONAL LICENSES FROM THE OPERATING SYSTEM +VENDOR. + +7. Disclaimer of Warranty on Software. You expressly acknowledge and +agree that use of the Software is at your sole risk. The Software and +related documentation are provided "AS IS" and without warranty of any kind +and AMD EXPRESSLY DISCLAIMS ALL WARRANTIES, EXPRESS AND IMPLIED, INCLUDING, +BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FORA PARTICULAR PURPOSE, OF QUALITY, OF QUIET ENJOYMENT AND OF NON- +INFRINGEMENT OF THIRD PARTY RIGHTS. AMD DOES NOT WARRANT THAT THE +FUNCTIONS CONTAINED IN THE SOFTWARE WILL MEET YOUR REQUIREMENTS, OR THAT +THE OPERATION OF THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE, OR THAT +DEFECTS IN THE SOFTWARE WILL BE CORRECTED. THE ENTIRE RISK AS TO THE +RESULTS AND PERFORMANCE OF THE SOFTWARE IS ASSUMED BY YOU. FURTHERMORE, +AMD DOES NOT WARRANT OR MAKE ANY REPRESENTATIONS REGARDING THE USE ORTHE +RESULTS OF THE USE OF THE SOFTWARE OR RELATED DOCUMENTATION IN TERMS OF +THEIR CORRECTNESS, ACCURACY, RELIABILITY, CURRENTNESS, OR OTHERWISE. NO +ORAL OR WRITTEN INFORMATION OR ADVICE GIVEN BY AMD OR AMD'S AUTHORIZED +REPRESENTATIVE SHALL CREATE A WARRANTY OR IN ANY WAY INCREASE THE SCOPE OF +THIS WARRANTY. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU (AND NOT AMD OR +AMD'S AUTHORIZED REPRESENTATIVE) ASSUME THE ENTIRE COST OF ALL NECESSARY +SERVICING, REPAIR OR CORRECTION. THE SOFTWARE IS NOT INTENDED FOR USE IN +MEDICAL, LIFE SAVING OR LIFE SUSTAINING APPLICATIONS. SOME JURISDICTIONS +DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO THE ABOVE EXCLUSION +MAY NOT APPLY TO YOU. + +8. Limitation of Liability. TO THE MAXIMUM EXTENT PERMITTED BY LAW, UNDER +NO CIRCUMSTANCES INCLUDING NEGLIGENCE, SHALL AMD, OR ITS DIRECTORS, +OFFICERS, EMPLOYEES OR AGENTS, BE LIABLE TO YOU 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 +OR RELATED DOCUMENTATION, BREACH OR DEFAULT, INCLUDING THOSE ARISING FROM +INFRINGEMENT OR ALLEGED INFRINGEMENT OF ANY PATENT, TRADEMARK, COPYRIGHT OR +OTHER INTELLECTUAL PROPERTY RIGHT, BY AMD, EVEN IF AMD OR AMD'S AUTHORIZED +REPRESENTATIVE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME +JURISDICTIONS DO NOT ALLOW THE LIMITATION OR EXCLUSION OF LIABILITY FOR +INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THE ABOVE LIMITATION OR EXCLUSION +MAY NOT APPLY TO YOU. AMD will not be liable for 1) loss of, or damage to, +your records or data or 2) any damages claimed by you based on any third +party claim. In no event shall AMD's total liability to you for all +damages, losses, and causes of action (whether in contract, tort (including +negligence) or otherwise) exceed the amount paid by you for the Software. +The foregoing limitations will apply even if the above stated limitation +fails of its essential purpose. + +9. Controlling Law and Severability. This License shall be governed by +and construed under the laws of the Province of Ontario, Canada without +reference to its conflict of law principles. Any dispute related hereto +will be brought only in the courts in Toronto, Ontario, Canada and such +courts are agreed to be the convenient forum. In the event of any +conflicts between foreign law, rules, and regulations, and Canadian law, +rules, and regulations, Canadian law, rules and regulations shall prevail +and govern. The United Nations Convention on Contracts for the +International Sale of Goods shall not apply to this License. If for any +reason a court of competent jurisdiction finds any provision of this +License or portion thereof, to be unenforceable, that provision of the +License shall be enforced to the maximum extent permissible so as to effect +the intent of the parties, and the remainder of this License shall continue +in full force and effect. + +10. Complete Agreement. This License constitutes the entire agreement +between the parties with respect to the use of the Software and the related +documentation, and supersedes all prior or contemporaneous understandings +or agreements, written or oral, regarding such subject matter. No +amendment to or modification of this License will be binding unless in +writing and signed by a duly authorized representative of AMD. diff --git a/licenses/Apache-2.0.txt b/licenses/Apache-2.0.txt new file mode 100644 index 0000000000..9a4104bbfb --- /dev/null +++ b/licenses/Apache-2.0.txt @@ -0,0 +1,183 @@ +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution +as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright +owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities +that control, are controlled by, or are under common control with that entity. +For the purposes of this definition, "control" means (i) the power, direct +or indirect, to cause the direction or management of such entity, whether +by contract or otherwise, or (ii) ownership of fifty percent (50%) or more +of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions +granted by this License. + +"Source" form shall mean the preferred form for making modifications, including +but not limited to software source code, documentation source, and configuration +files. + +"Object" form shall mean any form resulting from mechanical transformation +or translation of a Source form, including but not limited to compiled object +code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, +made available under the License, as indicated by a copyright notice that +is included in or attached to the work (an example is provided in the Appendix +below). + +"Derivative Works" shall mean any work, whether in Source or Object form, +that is based on (or derived from) the Work and for which the editorial revisions, +annotations, elaborations, or other modifications represent, as a whole, an +original work of authorship. For the purposes of this License, Derivative +Works shall not include works that remain separable from, or merely link (or +bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version +of the Work and any modifications or additions to that Work or Derivative +Works thereof, that is intentionally submitted to Licensor for inclusion in +the Work by the copyright owner or by an individual or Legal Entity authorized +to submit on behalf of the copyright owner. For the purposes of this definition, +"submitted" means any form of electronic, verbal, or written communication +sent to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, and +issue tracking systems that are managed by, or on behalf of, the Licensor +for the purpose of discussing and improving the Work, but excluding communication +that is conspicuously marked or otherwise designated in writing by the copyright +owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf +of whom a Contribution has been received by Licensor and subsequently incorporated +within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this +License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, +no-charge, royalty-free, irrevocable copyright license to reproduce, prepare +Derivative Works of, publicly display, publicly perform, sublicense, and distribute +the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, +each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, +no-charge, royalty-free, irrevocable (except as stated in this section) patent +license to make, have made, use, offer to sell, sell, import, and otherwise +transfer the Work, where such license applies only to those patent claims +licensable by such Contributor that are necessarily infringed by their Contribution(s) +alone or by combination of their Contribution(s) with the Work to which such +Contribution(s) was submitted. If You institute patent litigation against +any entity (including a cross-claim or counterclaim in a lawsuit) alleging +that the Work or a Contribution incorporated within the Work constitutes direct +or contributory patent infringement, then any patent licenses granted to You +under this License for that Work shall terminate as of the date such litigation +is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or +Derivative Works thereof in any medium, with or without modifications, and +in Source or Object form, provided that You meet the following conditions: + +(a) You must give any other recipients of the Work or Derivative Works a copy +of this License; and + +(b) You must cause any modified files to carry prominent notices stating that +You changed the files; and + +(c) You must retain, in the Source form of any Derivative Works that You distribute, +all copyright, patent, trademark, and attribution notices from the Source +form of the Work, excluding those notices that do not pertain to any part +of the Derivative Works; and + +(d) If the Work includes a "NOTICE" text file as part of its distribution, +then any Derivative Works that You distribute must include a readable copy +of the attribution notices contained within such NOTICE file, excluding those +notices that do not pertain to any part of the Derivative Works, in at least +one of the following places: within a NOTICE text file distributed as part +of the Derivative Works; within the Source form or documentation, if provided +along with the Derivative Works; or, within a display generated by the Derivative +Works, if and wherever such third-party notices normally appear. The contents +of the NOTICE file are for informational purposes only and do not modify the +License. You may add Your own attribution notices within Derivative Works +that You distribute, alongside or as an addendum to the NOTICE text from the +Work, provided that such additional attribution notices cannot be construed +as modifying the License. + +You may add Your own copyright statement to Your modifications and may provide +additional or different license terms and conditions for use, reproduction, +or distribution of Your modifications, or for any such Derivative Works as +a whole, provided Your use, reproduction, and distribution of the Work otherwise +complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any +Contribution intentionally submitted for inclusion in the Work by You to the +Licensor shall be under the terms and conditions of this License, without +any additional terms or conditions. Notwithstanding the above, nothing herein +shall supersede or modify the terms of any separate license agreement you +may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, +trademarks, service marks, or product names of the Licensor, except as required +for reasonable and customary use in describing the origin of the Work and +reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to +in writing, Licensor provides the Work (and each Contributor provides its +Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied, including, without limitation, any warranties +or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR +A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness +of using or redistributing the Work and assume any risks associated with Your +exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether +in tort (including negligence), contract, or otherwise, unless required by +applicable law (such as deliberate and grossly negligent acts) or agreed to +in writing, shall any Contributor be liable to You for damages, including +any direct, indirect, special, incidental, or consequential damages of any +character arising as a result of this License or out of the use or inability +to use the Work (including but not limited to damages for loss of goodwill, +work stoppage, computer failure or malfunction, or any and all other commercial +damages or losses), even if such Contributor has been advised of the possibility +of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work +or Derivative Works thereof, You may choose to offer, and charge a fee for, +acceptance of support, warranty, indemnity, or other liability obligations +and/or rights consistent with this License. However, in accepting such obligations, +You may act only on Your own behalf and on Your sole responsibility, not on +behalf of any other Contributor, and only if You agree to indemnify, defend, +and hold each Contributor harmless for any liability incurred by, or claims +asserted against, such Contributor by reason of your accepting any such warranty +or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate +notice, with the fields enclosed by brackets "[]" replaced with your own identifying +information. (Don't include the brackets!) The text should be enclosed in +the appropriate comment syntax for the file format. We also recommend that +a file or class name and description of purpose be included on the same "printed +page" as the copyright notice for easier identification within third-party +archives. + +Copyright [yyyy] [name of copyright owner] + +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. diff --git a/licenses/Artistic.txt b/licenses/Artistic.txt new file mode 100644 index 0000000000..5f221241e8 --- /dev/null +++ b/licenses/Artistic.txt @@ -0,0 +1,131 @@ + + + + + The "Artistic License" + + Preamble + +The intent of this document is to state the conditions under which a +Package may be copied, such that the Copyright Holder maintains some +semblance of artistic control over the development of the package, +while giving the users of the package the right to use and distribute +the Package in a more-or-less customary fashion, plus the right to make +reasonable modifications. + +Definitions: + + "Package" refers to the collection of files distributed by the + Copyright Holder, and derivatives of that collection of files + created through textual modification. + + "Standard Version" refers to such a Package if it has not been + modified, or has been modified in accordance with the wishes + of the Copyright Holder as specified below. + + "Copyright Holder" is whoever is named in the copyright or + copyrights for the package. + + "You" is you, if you're thinking about copying or distributing + this Package. + + "Reasonable copying fee" is whatever you can justify on the + basis of media cost, duplication charges, time of people involved, + and so on. (You will not be required to justify it to the + Copyright Holder, but only to the computing community at large + as a market that must bear the fee.) + + "Freely Available" means that no fee is charged for the item + itself, though there may be fees involved in handling the item. + It also means that recipients of the item may redistribute it + under the same conditions they received it. + +1. You may make and give away verbatim copies of the source form of the +Standard Version of this Package without restriction, provided that you +duplicate all of the original copyright notices and associated disclaimers. + +2. You may apply bug fixes, portability fixes and other modifications +derived from the Public Domain or from the Copyright Holder. A Package +modified in such a way shall still be considered the Standard Version. + +3. You may otherwise modify your copy of this Package in any way, provided +that you insert a prominent notice in each changed file stating how and +when you changed that file, and provided that you do at least ONE of the +following: + + a) place your modifications in the Public Domain or otherwise make them + Freely Available, such as by posting said modifications to Usenet or + an equivalent medium, or placing the modifications on a major archive + site such as uunet.uu.net, or by allowing the Copyright Holder to include + your modifications in the Standard Version of the Package. + + b) use the modified Package only within your corporation or organization. + + c) rename any non-standard executables so the names do not conflict + with standard executables, which must also be provided, and provide + a separate manual page for each non-standard executable that clearly + documents how it differs from the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + +4. You may distribute the programs of this Package in object code or +executable form, provided that you do at least ONE of the following: + + a) distribute a Standard Version of the executables and library files, + together with instructions (in the manual page or equivalent) on where + to get the Standard Version. + + b) accompany the distribution with the machine-readable source of + the Package with your modifications. + + c) give non-standard executables non-standard names, and clearly + document the differences in manual pages (or equivalent), together + with instructions on where to get the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + +5. You may charge a reasonable copying fee for any distribution of this +Package. You may charge any fee you choose for support of this +Package. You may not charge a fee for this Package itself. However, +you may distribute this Package in aggregate with other (possibly +commercial) programs as part of a larger (possibly commercial) software +distribution provided that you do not advertise this Package as a +product of your own. You may embed this Package's interpreter within +an executable of yours (by linking); this shall be construed as a mere +form of aggregation, provided that the complete Standard Version of the +interpreter is so embedded. + +6. The scripts and library files supplied as input to or produced as +output from the programs of this Package do not automatically fall +under the copyright of this Package, but belong to whoever generated +them, and may be sold commercially, and may be aggregated with this +Package. If such scripts or library files are aggregated with this +Package via the so-called "undump" or "unexec" methods of producing a +binary executable image, then distribution of such an image shall +neither be construed as a distribution of this Package nor shall it +fall under the restrictions of Paragraphs 3 and 4, provided that you do +not represent such an executable image as a Standard Version of this +Package. + +7. C subroutines (or comparably compiled subroutines in other +languages) supplied by you and linked into this Package in order to +emulate subroutines and variables of the language defined by this +Package shall not be considered part of this Package, but are the +equivalent of input as in Paragraph 6, provided these subroutines do +not change the language in any way that would cause it to fail the +regression tests for the language. + +8. Aggregation of this Package with a commercial distribution is always +permitted provided that the use of this Package is embedded; that is, +when no overt attempt is made to make this Package's interfaces visible +to the end user of the commercial distribution. Such use shall not be +construed as a distribution of this Package. + +9. The name of the Copyright Holder may not be used to endorse or promote +products derived from this software without specific prior written permission. + +10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + The End diff --git a/licenses/BSD-1-Clause.txt b/licenses/BSD-1-Clause.txt new file mode 100644 index 0000000000..3b3c4e814b --- /dev/null +++ b/licenses/BSD-1-Clause.txt @@ -0,0 +1,19 @@ +Copyright (c) 1995, 1999 Berkeley Software Design, Inc. All rights reserved. + +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. + +THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``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 Berkeley Software Design, Inc. 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. diff --git a/licenses/BSD-2-Clause.txt b/licenses/BSD-2-Clause.txt new file mode 100644 index 0000000000..baa80b56a2 --- /dev/null +++ b/licenses/BSD-2-Clause.txt @@ -0,0 +1,22 @@ +Copyright (c) All rights reserved. + +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. + +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. diff --git a/licenses/BSD-3-Clause.txt b/licenses/BSD-3-Clause.txt new file mode 100644 index 0000000000..0741db789e --- /dev/null +++ b/licenses/BSD-3-Clause.txt @@ -0,0 +1,26 @@ +Copyright (c) . All rights reserved. + +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. 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. diff --git a/licenses/BSD-4-Clause.txt b/licenses/BSD-4-Clause.txt new file mode 100644 index 0000000000..c0fcf169ff --- /dev/null +++ b/licenses/BSD-4-Clause.txt @@ -0,0 +1,30 @@ +Copyright (c) . All rights reserved. + +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 the organization. + +4. 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 COPYRIGHT HOLDER "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 COPYRIGHT +HOLDER 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. diff --git a/licenses/BSL.txt b/licenses/BSL.txt new file mode 100644 index 0000000000..36b7cd93cd --- /dev/null +++ b/licenses/BSL.txt @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +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, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS 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. diff --git a/licenses/BigPEmu_ReadMe.txt b/licenses/BigPEmu_ReadMe.txt new file mode 100644 index 0000000000..871560b988 --- /dev/null +++ b/licenses/BigPEmu_ReadMe.txt @@ -0,0 +1,356 @@ +Title: BigPEmu +Version: 1.19 +Author: Rich Whitehouse +Website: https://www.richwhitehouse.com/jaguar/ +Description: An Atari Jaguar emulator, featuring compatibility with every title in the Jaguar's retail library. See below for copyright and licensing information. + + +Patreon: /richwhitehouse +https://patreon.com/richwhitehouse + +Bluesky: @richwhitehouse.bsky.social +https://bsky.app/profile/richwhitehouse.bsky.social + +Twitter: @DickWhitehouse +https://twitter.com/DickWhitehouse + +Please consider showing your support! + + +Release Notes +------------- +Version 1.19 + - Added some more unaligned read/write edge case handling. This addresses a problem in Theme Park, possibly among other things. + - Changed some undocumented RISC instruction behavior to match some of my local hardware tests. One of these changes is known to correct an issue with object directions in Defender 2000. + - Added more Jaguar GD functionality. Filesystem functions are stubbed out, but I wasn't sure if anyone really needs/wants this fully implemented, so let me know if it's important to you. + - Fixed a few "undefined" Blitter cases. (not known to affect any existing titles) + - Linux ARM64 builds are now part of the automated build set. Special thanks to cubanismo for guiding me through the minefield of cross-compiling for ancient Linux targets. + - Significant improvements to the network rollback functionality, propagated back from BigInstinct. + - All kinds of new platform/framework functionality, also propagated back from BigInstinct. I didn't feel like going through hundreds of changes to make a coherent summary, but one of the more notable additions is a byuu-style run-ahead option. + - Exposed a bunch of sound spatialization functionality to the scripting API. + - Exposed MOD and MP3 playback to the scripting API. + - Added a timing fix for Val d'Isere Skiing and Snowboarding. + - Various developer build changes to more accurately reflect hardware and/or detect errors which would break on non-developer builds. (this includes enabling M68K address exceptions) + - Lots of "anti-emulator" code will be failing in developer builds at this point, and some related functionality may be propagating to non-developer builds soon; relying on inaccuracies to prevent your software from running in BigPEmu is unwise. If you really want to prevent your software from running in BigPEmu, contact me about better/future-proof methods. + +Version 1.18 + - New Steam integration! This includes support for game servers, friends/invites, rich presence, and more. At the time of this writing, Valve is still holding the actual Steam release up over some petty nonsense. (like supported categories and Patreon references) + - Added a script for Breakout 2000 touch control. The paddle is horizontally positioned to match the first active touch. + - Added an audio interpolation setting, along with a higher-quality bandlimited audio interpolator. + - Added an option to change the size of the state operation undo buffer. + - Exposed a few more network settings. + - Added options for PvP damage scaling and infinite shotgun ammo to the AvP MP script. + - Added another terrible secret. + - Fixed a bunch of problems in the socket implementation for non-Windows platforms. Special thanks to Luigi for spending the entire morning of December 4, 2024 helping me debug these problems and for offering some excellent tips on developing class consciousness. (he's a big fan of OOP) + - Various changes/optimizations in the network protocol. + - Fixed swipe velocity not being explicitly reset when entering the menu. + - Fixed a GUID conflict bug in the SDL2 input plugin. Thanks to Tartifless for the bug report. + - Fixed script input callbacks having the potential to break movie recording/playback. + +Version 1.17 + - Added a script for Raiden touch control. Ship automatically travels to the touch point and auto-fires when held, with a 2-finger tap to trigger bombs. + - Added a script for Vid Grid touch control. Drag and drop! + - Added a script for Towers II touch control. (with an option to uncap the framerate) In-game menu cursor is touch-driven, 2-finger tap exits the menu. + - Added a script for Myst touch control. Hold to drag the cursor, tap to activate. + - Added some scripting functionality to allow setting custom read/write handlers for non-RAM/ROM memory regions. + - The iOS port now prompts the user to determine their battery/heat versus performance preference on first run. (since we can't just be energy-efficient without the iOS scheduler punishing us, and I'm not having any luck getting anyone to read the FAQ/user manual) + - The iOS port now has a separate "Connected Idle Time" setting, which defaults to 3.0 and is used instead of "Overlay Idle Time" when at least one external device is connected. (workaround for the same FAQ/user manual problem above) + - Added lots of random new scripting functionality. + - Fixed game thumbnails rendering at the incorrect scale in portrait mode. + +Version 1.16 + - The iOS port is done, get it on the App Store here: https://apps.apple.com/us/app/bigpemu/id6737359949 Special thanks to neurocrash for putting so much time into testing the iOS build for me. + - Lots of new interface functionality (including a touch-based interface option), courtesy of the mobile port work. All of this functionality can be accessed through the menu on non-mobile platforms. + - Multi-touch device support has been added for the Windows (x64 and ARM64) platforms, in order to take advantage of the touch interface work done for the mobile ports. + - Added a "Pad Wheel" feature, which can be activated through the input binding system. + - Support for a new BigPImage disc format. BigPImage files can be created from existing images or physical discs through the developer menu. Before anyone asks, CHD support looked problematic for quite a few reasons (mostly pertaining to the likelihood of image-based performance problems and implementation bloat inherent to the format), making this new format a much more optimal choice for the particular needs of this emulator. + - Added stereoscopic rendering support to the AvP script. + - Added a new DOOM script with throttling and music options. + - Added a new turbo/rapid fire script. + - Added a "Factory Reset" option, as a convenient means of resetting the configuration across all categories. + - Added an option to auto-assign new input devices. Devices will not be auto-assigned if they have any existing associations with any Jaguar inputs. + - Fixed an incredible number of bugs, pertaining to both interface and emulation. Because so many fixes have been made to the emulator core in this release, I'm especially interested in finding regression bugs. Please let me know if you experience any issues which don't occur in 1.15. + +Version 1.15 + - Added a pure software video plugin for Windows builds. This plugin is primarily intended for development and diagnostic purposes, and is only visible in developer mode. + - New Noesis debugger scripting functionality for developer builds, this enables several new features. Make sure you're using the newest version of Noesis to take advantage of the functionality. + - Added -uiscale, -menunodex, and -menunodey command line options. + - Added a recalibration option under the Input menu. + - Added several more native window management functions to the script API. + - Added an optional flags parameter to the "opdump" debugger command, check the "help" output for details. + - Added the most terrible secret of all. + - Fixed a problem with directory checks on UNC paths under Windows, thanks to King Puff for the bug report. + - Lots of smaller fixes/changes in preparation for more port/interface functionality. + +Version 1.14 + - Added bigpemu_register_event_audio_frame, scripts are now able to read/modify audio frames. + - Added various audio/sampling utility functions to the scripting system. (see the spectrum analyzer sample usage in hello_pussycat and the full list of functions in bigpcrt.h) + - Added bigpemu_set_named_var_data and bigpemu_get_named_var_data, along with a "ScriptOption" Screen Effect data provider type. This allows script code to drive Screen Effect data, see hello_pussycat and liz for example usage. + - Added bigpemu_native_window_handle, as a convenience for scripts which may want to pass the window handle to a native DLL. + - Added support for the "physical disc" path under Linux. This will only function correctly with drives (virtual or otherwise) which support raw subchannel reads. + - Fixed a potential developer build crash from forcing script reloads while employing conditional breakpoints. + - Fixed an issue which could result in the application window being positioned incorrectly after switching to fullscreen. + - Fixed some SDL2-specific fullscreen/multi-monitor issues. Thanks to cubanismo for nudging me into investigating this. + +Version 1.13 + - Fixed a problem which resulted in some of the built-in D3D12 shaders requiring Shader Model 6.0. + - Added more logging for various D3D12 initialization failure cases. + +Version 1.12 + - New D3D12 video plugin. The shader tool has also been updated and supports generating DXIL. + - New Windows ARM64 builds. Less frequently used platform-dependent functionality may remain unimplemented on this platform. + - Added a Blitter capture feature for developer builds. See the "blitcap" debugger command. + - Various minor cross-platform fixes which came along with the new port/backend work. + +Version 1.11 + - Unmapped input labels now display an angle suffix for hat switches. + - Unmapped input labels now display a +/- prefix for analog bindings, when applicable. + - Added a -forcegpusync command line option. + +Version 1.1 + - Added a native Linux (x64) port. Generally not well tested, but seems to be working well enough in local testing under a couple of different distributions. Less frequently used platform-dependent functionality may remain unimplemented on this platform. + - Added a new SDL2 plugin for audio, video, and input. Not particularly recommended under Windows, but a Windows build is provided nonetheless. + - Added custom sky/background functionality to the Checkered Flag script. + - Added an "Alternate Scheduling" option. + - Added a "Rewind Skip" option. + - Added a "Frame Time Display" developer option. + - Fixed a minor interrupt timing issue. + - Fixed a bug in the object browser which could, rarely, result in a memory leak. + - Fixed a bug preventing BIGPEMU_TEXFLAG_REPEAT from affecting texture wrap mode in the OpenGL video plugin. + - Fixed another timing issue, which was manifesting as a rare crash in Cybermorph. Thanks to Will for managing to capture a saved state illustrating this problem. + - Developer builds will avoid crashing and warn the developer (via connected debugger) when a read/write straddles the end of ROM. Normal builds will still crash, in order to avoid overhead. Thanks to DrTypo for the bug report. + +Version 1.094 + - The Checkered Flag "Uncap Framerate" option can now be switched between 30Hz and 60Hz. + - Added some sync code to the Checkered Flag script to fix possible flickering issues. (only became noticeable at 60Hz) + - Checkered Flag is generally playable at 60Hz, but you're likely to encounter more timing bugs. Native system requirements are also significantly higher, as the Jaguar is automatically overclocked in this mode. + +Version 1.093 + - Added a Checkered Flag script, which features native resolution rendering, analog controller support, framerate unlocking, and lots of tweaks/options. + - Added a new Tempest 2000 script to patch some of the rotary controller bugs that existed on hardware. + - Added support for "AUDIOWITHSUB" track types in the CUE loader. + - Added an "optree" debug command. (only relevant for developer builds) + - Added a "gfxflags" debug command. (only relevant for developer builds) + - Added bigpemu_jag_op_render_bitmap_object_to_buffer to the scripting API. + - Native CRY rendering and ADDDSEL blending is now supported through the native polygon script interface. + - New scripting functionality to hook into save/load state events, allowing scripts to pack custom data into saved states. + - Fixed a potential resource leak when associating textured native polygons with a buffer. + - Fixed changes to the MSAA setting sometimes not being reflected until restarting the application. + - Fixed potential flickering and other visual problems after re-allocating native polygon hardware buffers. + - Fixed the script function bigpemu_drawui_get_virtual_to_native_scales returning incorrect values. + - Fixed an issue with one of the terrible secrets which was making the secret slightly less terrible than designed. + +Version 1.092 + - Added an optional rewind feature, see the new "Rewind Count" setting as well as the new "Rewind" key bind. + - Added an optional network rewind feature, see the "Network Rewind" setting under the Network menu. Rewinds the state and immediately runs the emulator back to the current frame when an input discrepancy occurs. Requires a powerful machine to avoid hitches. (emulating Jaguar frames isn't cheap) + - Added analog/mouselook support to the AvP script. + - Added a new Wolfenstein 3D script with analog/mouselook support. (includes always-strafe and always-run options) + - Added a new Iron Soldier script with analog/mouselook support. + - Minor performance improvements. + +Version 1.091 + - AvP multiplayer fixes. + - Fixed some player projectile weapons not colliding with other players. + - Fixed a bunch of AI projectiles not being correctly synchronized. + - Fixed an issue which would sometimes cause AI to stop attacking. + - If a human player teleports into a new level without a weapon, the shotgun is now automatically granted. + - Fixed a bug which could sometimes cause bigpemu_net_behind to misreport. + - New script functions: bigpemu_net_hostmsg, bigpemu_net_disconnect, and bigpemu_net_lastclient. + +Version 1.09 + - New "State Sync" network device type, synchronizes system state across the network. This allows local 2-player games to be played over Internet/LAN connections. + - Very simple implementation that just stalls out if input doesn't arrive in time. State Sync Delay option adjusts the anticipated latency window. If you run into timing issues, the host can manually kick everyone back together by loading a state. + - State Sync Remap can be used to remap the first local input device to any other input device. Also allows overlapping controls. (e.g. two peers both affecting the first input device) + - Works with any number of clients, with clients above the supported input device count being treated as spectators. + - New "Script" network device type, allows scripts to implement custom network/socket handlers. Includes automatic delta compression and some other niceties. + - A new script adds multiplayer to AvP! + - Implements networking from scratch using the aforementioned socket interface, and works with the unmodified retail ROM image. + - Proper client-server architecture, up to 32 players can drop in at any time during gameplay. (in theory) + - Generally handles the fundamentals, but expect plenty of limitations, bugs, and odd behavior. This game wasn't designed to support multiplayer, and I've left a few threads hanging under the guise of "shippable." + - Enemies can correctly change off between player targets. + - I hope this serves as another demonstration of the sort of madness which can be accomplished with the scripting system, and I'd love to see others give this sort of treatment to more titles. + - Lots of new scripting/VM functionality. + - UI event callbacks for custom rendering over/under the rest of the UI. + - New UI rendering functions for various primitives and text. + - Input functions to allow querying input states across all native devices. + - Scripts can now load and render/play texture and sound resources. + - New native-backed 4x4 matrix/transform operations. + - Script can now get a list of ROM from from the current ROM directory, and load images in that directory. + - Scripted polygon texture references now have the option of pointing to native texture resources. Could be useful for something like a high-res texture replacement script. + - Fixed a floating point comparison bug in the VM interpreter. + - VM modules are now loaded automatically if a .bigpcvm file is present with the same name as the ROM image being loaded, similar to other image-specific resources. This allows Jaguar software to be distributed alongside emulator-specific script enhancements. + +Version 1.08 + - JagLink support is here! + - Max player count is supported in AirCars and BattleSphere, with the potential for any number of emulated Jaguars to be networked together. + - Special splitscreen functionality has been added. + - Works over Internet/LAN or locally via loopback. + - Don't expect anything to be playable or stable over the Internet unless you've got LAN-like latency and no packet loss. + - When the central host loads a saved state, it's automatically propagated to all clients. + - Here's a video which goes over all of the network features and demonstrates a splitscreen setup: https://youtu.be/b2e7Vl4aLps + - Added -cfgpath and -cfgpathabs command line options. This overrides the default config path, useful for splitscreen instances. + - Added -windowx and -windowy command line options. Useful for tiling out instances for splitscreen play. + - Added a -noborder command line option. Removes the border from the window in windowed mode, best used with -windowx, -windowy, -forcewidth, and -forceheight. + - Added an -alwaystop command line option. Keeps the window always-on-top, also useful for splitscreen mode. + - Added -netlisten, -netconnect, -netport, -netmax, -netloaddelay, -netpcldelay, and -nettcp command line options. + - Bumped the debugger protocol version, make sure you update to the latest Noesis if you're using the developer build. + +Version 1.071 + - Fixed a bug which was causing the VR Swap Eyes setting to be incorrectly tied to other settings. This probably explains reports from some users of being "cross-eyed" by default. + - Added stereoscopic rendering support for the GPU list variant used by the MC3D stage 1-3 boss. + +Version 1.07 + - Jaguar VR support is here, with head tracking and stereoscopic rendering. + - A new Head Tracker input device type has been added, along with some options for converting analog inputs to tracker angles. + - Stereoscopic rendering is fully implemented, and integrated into the scripting system. + - Check out all the new settings in the Video/VR menu. + - The scripting system has the potential to add Head Tracker support and stereoscopic rendering to any Jaguar title, so more Jaguar VR games may be coming! + - This video demonstrates and explains some of the new VR functionality: https://youtu.be/BAJjzlrsbis + - Added an OpenVR plugin to support the new Jaguar VR implementation. + - A new script is included to implement stereoscopic rendering and enable Head Tracker support in the final/retail version of Missile Command 3D. + - To map the head tracking through any analog input with the script enabled: set the second input device type to "Head Tracker", and bind the second device's analog inputs to whatever pleases you. + - To enable stereoscopic rendering with the script enabled: go to Script Settings in the menu and enable the stereoscopic rendering option. Stereo-capable scenes will be rendered using the emulator's selected VR/anaglyph 3D settings. + - When VR is enabled (via the Video/VR settings) and successfully initialized, if a compatible headset is present, its orientation will automatically feed the Head Tracker input. + - Stereoscopic rendering was never actually implemented in MC3D, this is a brand new software feature designed to fully realize the potential of Jaguar VR. + - Fixed a Blitter issue with DCOMPEN in phrase mode. (introduced in the Patreon-exclusive 1.061 build) + - Lots of changes/additions for developer mode, and separate debugger-enabled builds are now available from the official web site. Check the ReadMeDev.txt file in the debugger-enabled build distribution for more information. (introduced in the Patreon-exclusive 1.061 build) + +Version 1.06 + - New scripting system. In developer mode, scripts are auto-recompiled on startup. Developer options are also available to automatically detect script changes while the application is running. Compiled scripts must be enabled through a new Script Modules feature. + - A new script is included which allows Cybermorph to render polygons/textures at the native resolution. + - An option for adjusting MSAA has been added to the video settings. This is only relevant to things which use the native depth buffer, like the new Cybermorph script. + - A new script is included which allows uncapping the framerate in Alien vs. Predator. + - A new script is included which fixes flickering in the Brett Hull Hockey prototype. + - A simplified CRT library along with a whole bunch of BigPEmu-specific API functionality is included in the scripting system via the Scripts/bigpcrt library. + - Basic native DLL (CDECL) call functionality has been implemented in the scripting API, so that others can take the initiative to start implementing things like RetroAchievements as desired. + - Added native mouse input support. (must be enabled in the input settings) Mouse movement and buttons can be bound to analog, rotary, and digital inputs interchangeably. + - Some more work on debugger-enabled builds has been done behind the scenes, but this shouldn't affect anything user-facing just yet. + - Even more terrible secrets have been added. + - Made sure native rendering works even with a Screen Effect active. However, this isn't generally a recommended combination, as the effect will be sourcing from a native-resolution buffer instead of a Jaguar-resolution buffer. (post-Patreon build addition) + - Added a -conout command line option. Under Windows, this spawns a console and directs log output here instead of to a file. (post-Patreon build addition) + - The breadth of functionality encompassed by the scripting system is too vast to cover here, so I've made a video to highlight some of the features and explain how the existing scripts work: https://youtu.be/y4gXxSmLOg4 + - Please help me out with support on social media and Patreon! Things have continued to be rough on the health front lately, and I've found it's getting harder to use Twitter to reach my actual target audience, so I'm depending more on organic word of mouth to spread project news and hopefully bring in support. + +Version 1.054 + - Made some adjustments to the refresh rate warning logic introduced in the last version. The warning is inhibited when VSync is disabled (no, don't do it!), and an option to disable the warning has been added. + +Version 1.053 + - VLM's CD+G support is now working. + - Refresh frequency can now be specified when selecting a display mode. (previously, the highest available was auto-selected) + - The program will now warn you if you're using a native display refresh rate which is lower than the Jaguar's current display frequency. (50Hz for PAL, 60Hz for NTSC) + - There's now a warning under the Mount Images menu telling users to avoid setting a cartridge image with a disc image if the two were not designed to run together. Depending on the CD BIOS (and if one is set at all), this can cause a wide variety of problems, so don't do it. + - Fixed a Blitter issue which was introduced several versions ago. The issue could result in crashes, especially when running Fight for Life. + - Fixed a problem with SUBQMOD, although there are no known instances where this fix changes any behavior in the retail library. + - Fixed more unmapped read behavior which was preventing some homebrew from running correctly. + - Fixed a Blitter negative base address issue. + - Various other minor bug fixes. Thanks to all of the people who submitted bug reports through the web site! + +Version 1.052 + - Added a "Sample Scale" option for the System Audio Disc. + - I heard you like minor timing fixes, so I made some minor timing fixes to the minor timing fixes. + +Version 1.051 + - Minor timing fixes. + +Version 1.05 + - Jaguar CD support! This encompasses a whole bunch of new functionality. Thank you to Mycah Mattox for donating the Jaguar CD hardware, this hardware was essential for my research. + - Added -nodevicechange and -fulldevrefresh as command line options. + - Added -forceloadaddr and -forcerunaddr as command line options. + - Added -setcfgprop and -setcfgpropcat as command line options. + - Added -audiocapindex as a command line option, can be used when launching *VirtualDisc_SystemAudio as the ROM image via command line. + - Added -physdevindex as a command line option, can be used when launching *VirtualDisc_SystemPath as the ROM image via command line. + - Added another DirectInput workaround which may help prevent stuck analog controls on some machines. Thanks to neurocrash for spending a lot of time running tests for me on a machine where this was an issue! + - Fixed a problem with depth writes in 32-bit mode, thanks to 42Bastian for providing a test case. + - Fixed an issue with word strobes not being correctly scheduled until a write to SMODE/SCLK. (only relevant when running with no boot ROM set) + - Fixed a timing problem with EEPROM reads. + - Fixed scaling on monitors with a non-standard DPI. + - When adding a new individual input trigger in the binds menu, the prompt mode now defaults to "specify hold and button" instead of just "specify button". (in line with binding all inputs via "Set All") + - Lots of additional core emulation fixes which came along with CD support. + - Implemented some intentional redundancy in the OpenGL video plugin's state management, to guard against things like Discord's video capture poking around in the context without cleaning up after itself. + - With CD support wrapped up, I'm taking a short hiatus! I need to recouperate, generate some income, and prepare for the next phase of my cancer treatment. Please don't inundate me with fix/feature requests via e-mail/Discord/etc. during this time. Instead, I ask that you use the less invasive Bug Report form on the web site. Thank you for your consideration! + +Version 1.04 + - Added -devmode as a command line option. Don't get too excited, this isn't opening up full developer build functionality just yet. (and the option will be auto-enabled in proper developer builds) It does enable a developer menu, though, and some additional developer-oriented key binds. + - Added a "Local EEPROM" option to the new developer menu at CJ Reboot's request. + - Added a "Save Window Position" option to the new developer menu at CJ Reboot's request. + - Added an "Always on Top" option to the new developer menu at CJ Reboot's request. + - Added a new set of developer input binds, which are only accessible when using -devmode. Most of these new binds were added at 42Bastian's request. + - Now picking through individual device/state changes instead of just refreshing all input devices when a DEVNODES_CHANGED-type message is received. Fixes input disruptions on machines where something is causing DEVNODES_CHANGED spam. + - Fixed a problem when recording a movie with the "Increment on Save" setting enabled. Thanks to Doug Engel for finding this bug! + - Fixed a crash when entering the Zero 5 sound options screen. + - Every issue which was submitted through the Bug Report form on the website has now been resolved. Thanks to everyone who contributed! If you submitted something which still isn't resolved in this build, let me know. + +Version 1.03 + - Fix for some emulator state overrides not sticking when launching software via command line. + +Version 1.02 + - Added interlaced display support. This is definitely not working the way it works on hardware, but it addresses the test case that Doug Engel was kind enough to send over. + - Added a "force horizontal overscan" option. + - Added an option to force Jaguar GD emulation, which enables bank switching even in ROM images smaller than 6MB. + - Added -localdata as a command line option. + - Changed the first visible column default. (applies to both NTSC and PAL) + - Fix for a 16-bit DAC write bug. (fixes one-sided audio in Super Burnout) + - Fix for a problem on the Blitter's SRCSHADE data path. Thanks to Doug Engel for reporting the BattleSphere bug which led to this fix. + - Fix for OP sometimes running over HDE, thanks to CJ Reboot for reporting the associated bug. + - Fix for input bindings sometimes not being picked up from per-game config files. This bug could also potentially cause game-specific bindings to "stick" and infect the global config bindings. + +Version 1.01 + - Added variable-sized EEPROM support, thanks to CJ Reboot for providing some test cases. 512 byte and 2KB EEPROM settings are picked up from the MRQ file if it exists, otherwise any number of EEPROM address bits can be specified via the -eeprombits command line option. + - Added Jaguar GD bank switching support. + - Fix for exception-handled M68K reads in unmapped address space. + - Fix for Blitter not correctly wrapping cyan/red on add when ADDDSEL is set, thanks to Doug Engel for reporting the BattleSphere bug which led to this fix. + - Fix for Blitter not starting on the correct bit when block width is less than pixel size and phrase mode is not enabled, thanks to Doug Engel for reporting the BattleSphere bug which led to this fix. + - Going in for a major surgery tomorrow (2022/12/06), so expect that I'll be mostly unavailable and that there won't be any emulator updates for at least a couple of weeks. + +Version 1.00 + - First public release! + + +Troubleshooting +--------------- +If you're encountering problems with BigPEmu after a successful first use, the first thing you should try is clearing out your configuration. You can do this by deleting the BigPEmuConfig.bigpcfg in your %APPDATA%\BigPEmu folder. (this is usually somewhere like C:\Users\YourUsername\AppData\Roaming\BigPEmu) + +If you have a different problem or your problem persists after deleting your configuration file, check the website for additional help and information. + + +Copyright, Permissions, and Special Thanks +------------------------------------------ +BigPEmu Copyright (C) 2022 Rich Whitehouse + +Special thanks to everyone at Digital Eclipse, especially Mike Mika and Stephen Frost! These guys helped fund the development of this emulator, and helped make sure I'd be able to release it publicly. In the video game industry, that's a real gesture of love. + +Extra special thanks to Mark Sowden (hogsy) for being a friend and long-time supporter of my work. + +Even more special thanks to Mycah Mattox for donating a Jaguar CD unit! + +Those Who Bare Fangs at God: + - Mark Sowden (hogsy) + - John Perez (neurocrash) + - Benjamin Bettridge + - Jan D. (thank you for going so far above and beyond) + - ZoeB + - Scott LeGrand + - William Thorup + - Dan McCombs + - noigeaR + - Luigi Mangione (thank you for your sacrifice) + - B.J. West + - Shannon Gates + - Havard Vatne + - Tony Walsh + - guru emulation +May your oppressors suffer all the torments this world has to offer, my friends. + +Thank you to my daughter, Alaura, for brightening my life from the moment of her birth. + +Thank you to my wife and my good friends (Ruth, Joseph, Boris, Jake) for helping me through (the remains of) my life as I suffer with cancer. + +As with all of the free software that I write, I accept no liability and offer no warranty. By using this software, you agree that you are solely responsible for any form of harm which may result from the use of this software. + +I forbid the use of this software for any form of private financial gain. You may not distribute this software without the inclusion of this document in unmodified form, and you may not distribute modified versions of the main BigPEmu executable file. Any exemption from these terms requires my written permission. + +For a list of third party software included in BigPEmu and the corresponding license/copyright information, please see the Data/ThirdParty/Licenses directory. (location may vary per platform/distribution, check the application documents folder on iOS/macOS) I've also auto-converted and included a few shaders written by Hyllian under the MIT license, see the relevant shader files in Data/ScreenEffects for the original license/copyright information. + +BigPEmu: The World's Prefurred Large Pussycat Emulator + +I'd say I'm going to hell, but I'm already there! diff --git a/licenses/Clarified_Artistic.txt b/licenses/Clarified_Artistic.txt new file mode 100644 index 0000000000..af1204c418 --- /dev/null +++ b/licenses/Clarified_Artistic.txt @@ -0,0 +1,136 @@ + The Clarified Artistic License + + Preamble + +The intent of this document is to state the conditions under which a +Package may be copied, such that the Copyright Holder maintains some +semblance of artistic control over the development of the package, +while giving the users of the package the right to use and distribute +the Package in a more-or-less customary fashion, plus the right to make +reasonable modifications. + +Definitions: + + "Package" refers to the collection of files distributed by the + Copyright Holder, and derivatives of that collection of files + created through textual modification. + + "Standard Version" refers to such a Package if it has not been + modified, or has been modified in accordance with the wishes + of the Copyright Holder as specified below. + + "Copyright Holder" is whoever is named in the copyright or + copyrights for the package. + + "You" is you, if you're thinking about copying or distributing + this Package. + + "Distribution fee" is a fee you charge for providing a copy + of this Package to another party. + + "Freely Available" means that no fee is charged for the right to + use the item, though there may be fees involved in handling the + item. It also means that recipients of the item may redistribute + it under the same conditions they received it. + +1. You may make and give away verbatim copies of the source form of the +Standard Version of this Package without restriction, provided that you +duplicate all of the original copyright notices and associated disclaimers. + +2. You may apply bug fixes, portability fixes and other modifications +derived from the Public Domain, or those made Freely Available, or from +the Copyright Holder. A Package modified in such a way shall still be +considered the Standard Version. + +3. You may otherwise modify your copy of this Package in any way, provided +that you insert a prominent notice in each changed file stating how and +when you changed that file, and provided that you do at least ONE of the +following: + + a) place your modifications in the Public Domain or otherwise make them + Freely Available, such as by posting said modifications to Usenet or an + equivalent medium, or placing the modifications on a major network + archive site allowing unrestricted access to them, or by allowing the + Copyright Holder to include your modifications in the Standard Version + of the Package. + + b) use the modified Package only within your corporation or organization. + + c) rename any non-standard executables so the names do not conflict + with standard executables, which must also be provided, and provide + a separate manual page for each non-standard executable that clearly + documents how it differs from the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + + e) permit and encourge anyone who receives a copy of the modified Package + permission to make your modifications Freely Available + in some specific way. + + +4. You may distribute the programs of this Package in object code or +executable form, provided that you do at least ONE of the following: + + a) distribute a Standard Version of the executables and library files, + together with instructions (in the manual page or equivalent) on where + to get the Standard Version. + + b) accompany the distribution with the machine-readable source of + the Package with your modifications. + + c) give non-standard executables non-standard names, and clearly + document the differences in manual pages (or equivalent), together + with instructions on where to get the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + + e) offer the machine-readable source of the Package, with your + modifications, by mail order. + +5. You may charge a distribution fee for any distribution of this Package. +If you offer support for this Package, you may charge any fee you choose +for that support. You may not charge a license fee for the right to use +this Package itself. You may distribute this Package in aggregate with +other (possibly commercial and possibly nonfree) programs as part of a +larger (possibly commercial and possibly nonfree) software distribution, +and charge license fees for other parts of that software distribution, +provided that you do not advertise this Package as a product of your own. +If the Package includes an interpreter, You may embed this Package's +interpreter within an executable of yours (by linking); this shall be +construed as a mere form of aggregation, provided that the complete +Standard Version of the interpreter is so embedded. + +6. The scripts and library files supplied as input to or produced as +output from the programs of this Package do not automatically fall +under the copyright of this Package, but belong to whoever generated +them, and may be sold commercially, and may be aggregated with this +Package. If such scripts or library files are aggregated with this +Package via the so-called "undump" or "unexec" methods of producing a +binary executable image, then distribution of such an image shall +neither be construed as a distribution of this Package nor shall it +fall under the restrictions of Paragraphs 3 and 4, provided that you do +not represent such an executable image as a Standard Version of this +Package. + +7. C subroutines (or comparably compiled subroutines in other +languages) supplied by you and linked into this Package in order to +emulate subroutines and variables of the language defined by this +Package shall not be considered part of this Package, but are the +equivalent of input as in Paragraph 6, provided these subroutines do +not change the language in any way that would cause it to fail the +regression tests for the language. + +8. Aggregation of the Standard Version of the Package with a commercial +distribution is always permitted provided that the use of this Package +is embedded; that is, when no overt attempt is made to make this Package's +interfaces visible to the end user of the commercial distribution. +Such use shall not be construed as a distribution of this Package. + +9. The name of the Copyright Holder may not be used to endorse or promote +products derived from this software without specific prior written permission. + +10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + The End diff --git a/licenses/EPL-1.0.txt b/licenses/EPL-1.0.txt new file mode 100644 index 0000000000..b3f7087dde --- /dev/null +++ b/licenses/EPL-1.0.txt @@ -0,0 +1,88 @@ +Eclipse Public License - v 1.0 + +THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + +a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and + +b) in the case of each subsequent Contributor: + +i) changes to the Program, and + +ii) additions to the Program; + +where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. + +"Contributor" means any person or entity that distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. + +"Program" means the Contributions distributed in accordance with this Agreement. + +"Recipient" means anyone who receives the Program under this Agreement, including all Contributors. + +2. GRANT OF RIGHTS + +a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. + +b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. + +c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. + +d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. + +3. REQUIREMENTS + +A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: + +a) it complies with the terms and conditions of this Agreement; and + +b) its license agreement: + +i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; + +ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; + +iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and + +iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. + +When the Program is made available in source code form: + +a) it must be made available under this Agreement; and + +b) a copy of this Agreement must be included with each copy of the Program. + +Contributors may not remove or alter any copyright notices contained within the Program. + +Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement , including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. The Eclipse Foundation is the initial Agreement Steward. The Eclipse Foundation may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. + +This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. + diff --git a/licenses/FDL.txt b/licenses/FDL.txt new file mode 100644 index 0000000000..4a0fe1c8de --- /dev/null +++ b/licenses/FDL.txt @@ -0,0 +1,397 @@ + GNU Free Documentation License + Version 1.2, November 2002 + + + Copyright (C) 2000,2001,2002 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + 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. + +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 for under this License. Any other attempt to +copy, modify, sublicense or distribute the Document 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. + + +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. + + +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.2 + 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/FDL1_2.txt b/licenses/FDL1_2.txt new file mode 100644 index 0000000000..4a0fe1c8de --- /dev/null +++ b/licenses/FDL1_2.txt @@ -0,0 +1,397 @@ + GNU Free Documentation License + Version 1.2, November 2002 + + + Copyright (C) 2000,2001,2002 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + 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. + +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 for under this License. Any other attempt to +copy, modify, sublicense or distribute the Document 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. + + +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. + + +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.2 + 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/FDL1_3.txt b/licenses/FDL1_3.txt new file mode 100644 index 0000000000..2f7e03ca51 --- /dev/null +++ b/licenses/FDL1_3.txt @@ -0,0 +1,451 @@ + + GNU Free Documentation License + Version 1.3, 3 November 2008 + + + Copyright (C) 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc. + + 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/FLIRC.txt b/licenses/FLIRC.txt new file mode 100644 index 0000000000..d135582636 --- /dev/null +++ b/licenses/FLIRC.txt @@ -0,0 +1,32 @@ +/* + * Copyright 2023 Flirc Inc. All rights reserved. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY FLIRC INC. \`\`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 ${AUTHOR_UPPER} 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. + * + * The views and conclusions contained in the software and documentation + * are those of the authors and should not be interpreted as representing + * official policies, either expressed or implied, of Flirc Inc. + */ diff --git a/licenses/GPL-1.0-only.txt b/licenses/GPL-1.0-only.txt new file mode 100644 index 0000000000..8d8c5dfe38 --- /dev/null +++ b/licenses/GPL-1.0-only.txt @@ -0,0 +1,229 @@ +GNU GENERAL PUBLIC LICENSE +Version 1, February 1989 + +Copyright (C) 1989 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, +Boston, MA 02110-1301 USA + +Everyone is permitted to copy and distribute verbatim copies of this license +document, but changing it is not allowed. + +Preamble + +The license agreements of most software companies try to keep users at the +mercy of those companies. By contrast, our 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. The General Public License applies +to the Free Software Foundation's software and to any other program whose +authors commit to using it. You can use it for your programs, too. + +When we speak of free software, we are referring to freedom, not price. Specifically, +the General Public License is designed to make sure that you have the freedom +to give away or sell copies of free software, 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 a 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 tell them 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. + +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 Agreement 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 work containing the Program or a portion of it, either verbatim +or with modifications. Each licensee is addressed as "you". + +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 General Public License and +to the absence of any warranty; and give any other recipients of the Program +a copy of this General Public License along with the Program. You may charge +a fee for the physical act of transferring a copy. + +2. You may modify your copy or copies of the Program or any portion of it, +and copy and distribute such modifications under the terms of Paragraph 1 +above, provided that you also do the following: + +a) cause the modified files to carry prominent notices stating that you changed +the files and the date of any change; and + +b) cause the whole of any work that you distribute or publish, that in whole +or in part contains the Program or any part thereof, either with or without +modifications, to be licensed at no charge to all third parties under the +terms of this General Public License (except that you may choose to grant +warranty protection to some or all third parties, at your option). + +c) If the modified program normally reads commands interactively when run, +you must cause it, when started running for such interactive use in the simplest +and most usual 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 General +Public License. + +d) 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. + +Mere aggregation of another independent work with the Program (or its derivative) +on a volume of a storage or distribution medium does not bring the other work +under the scope of these terms. + +3. You may copy and distribute the Program (or a portion or derivative of +it, under Paragraph 2) in object code or executable form under the terms of +Paragraphs 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 Paragraphs 1 and 2 above; or, + +b) accompany it with a written offer, valid for at least three years, to give +any third party free (except for a nominal charge for the cost of distribution) +a complete machine-readable copy of the corresponding source code, to be distributed +under the terms of Paragraphs 1 and 2 above; or, + +c) accompany it with the information you received as to where the corresponding +source code may be obtained. (This alternative is allowed only for noncommercial +distribution and only if you received the program in object code or executable +form alone.) + +Source code for a work means the preferred form of the work for making modifications +to it. For an executable file, complete source code means all the source code +for all modules it contains; but, as a special exception, it need not include +source code for modules which are standard libraries that accompany the operating +system on which the executable file runs, or for standard header files or +definitions files that accompany that operating system. + +4. You may not copy, modify, sublicense, distribute or transfer the Program +except as expressly provided under this General Public License. Any attempt +otherwise to copy, modify, sublicense, distribute or transfer the Program +is void, and will automatically terminate your rights to use the Program under +this License. However, parties who have received copies, or rights to use +copies, from you under this General Public License will not have their licenses +terminated so long as such parties remain in full compliance. + +5. By copying, distributing or modifying 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. + +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. + +7. 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 the 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 the license, you may choose any +version ever published by the Free Software Foundation. + +8. 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 + +9. 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. + +10. 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 + +Appendix: 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 humanity, 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) 19yy + +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 1, 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., 675 Mass +Ave, Cambridge, MA 02139, 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) 19xx 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 +a sample; alter the names: + +Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' +(a program to direct compilers to make passes at assemblers) written by James +Hacker. + + , 1 April 1989 Ty Coon, President of Vice + +That's all there is to it! diff --git a/licenses/GPL-2.0-only.txt b/licenses/GPL-2.0-only.txt new file mode 100644 index 0000000000..3b6070fcd0 --- /dev/null +++ b/licenses/GPL-2.0-only.txt @@ -0,0 +1,311 @@ +GNU GENERAL PUBLIC LICENSE +Version 2, June 1991 + +Copyright (C) 1989, 1991 Free Software Foundation, Inc. +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 Lesser 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. + +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. + +one line to give the program's name and an idea of what it does. Copyright +(C) yyyy name of author + +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. 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. + +signature of Ty Coon, 1 April 1989 Ty Coon, President of Vice diff --git a/licenses/GPL-2.0-or-later.txt b/licenses/GPL-2.0-or-later.txt new file mode 100644 index 0000000000..3b6070fcd0 --- /dev/null +++ b/licenses/GPL-2.0-or-later.txt @@ -0,0 +1,311 @@ +GNU GENERAL PUBLIC LICENSE +Version 2, June 1991 + +Copyright (C) 1989, 1991 Free Software Foundation, Inc. +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 Lesser 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. + +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. + +one line to give the program's name and an idea of what it does. Copyright +(C) yyyy name of author + +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. 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. + +signature of Ty Coon, 1 April 1989 Ty Coon, President of Vice diff --git a/licenses/GPL-3.0-only.txt b/licenses/GPL-3.0-only.txt new file mode 100644 index 0000000000..599077110a --- /dev/null +++ b/licenses/GPL-3.0-only.txt @@ -0,0 +1,604 @@ +GNU GENERAL PUBLIC LICENSE +Version 3, 29 June 2007 + +Copyright © 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/GPL-3.0-or-later.txt b/licenses/GPL-3.0-or-later.txt new file mode 100644 index 0000000000..599077110a --- /dev/null +++ b/licenses/GPL-3.0-or-later.txt @@ -0,0 +1,604 @@ +GNU GENERAL PUBLIC LICENSE +Version 3, 29 June 2007 + +Copyright © 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/HIDAPI-orig.txt b/licenses/HIDAPI-orig.txt new file mode 100644 index 0000000000..e3f3380829 --- /dev/null +++ b/licenses/HIDAPI-orig.txt @@ -0,0 +1,9 @@ + HIDAPI - Multi-Platform library for + communication with HID devices. + + Copyright 2009, Alan Ott, Signal 11 Software. + All Rights Reserved. + + This software may be used by anyone for any reason so + long as the copyright notice in the source files + remains intact. diff --git a/licenses/ISC.txt b/licenses/ISC.txt new file mode 100644 index 0000000000..a6d1964fef --- /dev/null +++ b/licenses/ISC.txt @@ -0,0 +1,15 @@ +ISC License: + +Copyright (c) 2004-2010 by Internet Systems Consortium, Inc. ("ISC") +Copyright (c) 1995-2003 by Internet Software Consortium + +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 ISC DISCLAIMS ALL WARRANTIES WITH REGARD +TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL ISC 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 0000000000..bcfe47e978 --- /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/LGPL-2.0-only.txt b/licenses/LGPL-2.0-only.txt new file mode 100644 index 0000000000..ec9eedc542 --- /dev/null +++ b/licenses/LGPL-2.0-only.txt @@ -0,0 +1,444 @@ +GNU LIBRARY GENERAL PUBLIC LICENSE + +Version 2, June 1991 + +Copyright (C) 1991 Free Software Foundation, Inc. +51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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. + +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 + +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. + + one line to give the library's name and an idea of what it does. + Copyright (C) year name of author + +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., +51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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. + +signature of Ty Coon, 1 April 1990 +Ty Coon, President of Vice + +That's all there is to it! diff --git a/licenses/LGPL-2.0-or-later.txt b/licenses/LGPL-2.0-or-later.txt new file mode 100644 index 0000000000..ec9eedc542 --- /dev/null +++ b/licenses/LGPL-2.0-or-later.txt @@ -0,0 +1,444 @@ +GNU LIBRARY GENERAL PUBLIC LICENSE + +Version 2, June 1991 + +Copyright (C) 1991 Free Software Foundation, Inc. +51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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. + +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 + +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. + + one line to give the library's name and an idea of what it does. + Copyright (C) year name of author + +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., +51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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. + +signature of Ty Coon, 1 April 1990 +Ty Coon, President of Vice + +That's all there is to it! diff --git a/licenses/LGPL-2.1-only.txt b/licenses/LGPL-2.1-only.txt new file mode 100644 index 0000000000..aaaba1688e --- /dev/null +++ b/licenses/LGPL-2.1-only.txt @@ -0,0 +1,462 @@ +GNU LESSER GENERAL PUBLIC LICENSE + +Version 2.1, February 1999 + +Copyright (C) 1991, 1999 Free Software Foundation, Inc. +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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. + +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. + +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. + +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 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. + +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. + +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. + +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 + +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. + + one line to give the library's name and an idea of what it does. + Copyright (C) year name of author + +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.1 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., 51 +Franklin Street, Fifth Floor, Boston, MA 02110-1301 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. + +signature of Ty Coon, 1 April 1990 +Ty Coon, President of Vice +That's all there is to it! diff --git a/licenses/LGPL-2.1-or-later.txt b/licenses/LGPL-2.1-or-later.txt new file mode 100644 index 0000000000..aaaba1688e --- /dev/null +++ b/licenses/LGPL-2.1-or-later.txt @@ -0,0 +1,462 @@ +GNU LESSER GENERAL PUBLIC LICENSE + +Version 2.1, February 1999 + +Copyright (C) 1991, 1999 Free Software Foundation, Inc. +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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. + +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. + +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. + +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 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. + +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. + +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. + +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 + +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. + + one line to give the library's name and an idea of what it does. + Copyright (C) year name of author + +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.1 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., 51 +Franklin Street, Fifth Floor, Boston, MA 02110-1301 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. + +signature of Ty Coon, 1 April 1990 +Ty Coon, President of Vice +That's all there is to it! diff --git a/licenses/LGPL-3.0-only.txt b/licenses/LGPL-3.0-only.txt new file mode 100644 index 0000000000..9e2e9f7831 --- /dev/null +++ b/licenses/LGPL-3.0-only.txt @@ -0,0 +1,144 @@ +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/LGPL-3.0-or-later.txt b/licenses/LGPL-3.0-or-later.txt new file mode 100644 index 0000000000..9e2e9f7831 --- /dev/null +++ b/licenses/LGPL-3.0-or-later.txt @@ -0,0 +1,144 @@ +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/LLVM.txt b/licenses/LLVM.txt new file mode 100644 index 0000000000..922092b052 --- /dev/null +++ b/licenses/LLVM.txt @@ -0,0 +1,70 @@ +============================================================================== +LLVM Release License +============================================================================== +University of Illinois/NCSA +Open Source License + +Copyright (c) 2003-2014 University of Illinois at Urbana-Champaign. +All rights reserved. + +Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +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: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + +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 +CONTRIBUTORS 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 WITH THE +SOFTWARE. + +============================================================================== +Copyrights and Licenses for Third Party Software Distributed with LLVM: +============================================================================== +The LLVM software contains code written by third parties. Such software will +have its own individual LICENSE.TXT file in the directory in which it appears. +This file will describe the copyrights, license, and restrictions which apply +to that code. + +The disclaimer of warranty in the University of Illinois Open Source License +applies to all code in the LLVM Distribution, and nothing in any of the +other licenses gives permission to use the names of the LLVM Team or the +University of Illinois to endorse or promote products derived from this +Software. + +The following pieces of software have additional or alternate copyrights, +licenses, and/or restrictions: + +Program Directory +------- --------- +Autoconf llvm/autoconf + llvm/projects/ModuleMaker/autoconf +Google Test llvm/utils/unittest/googletest +OpenBSD regex llvm/lib/Support/{reg*, COPYRIGHT.regex} +pyyaml tests llvm/test/YAMLParser/{*.data, LICENSE.TXT} +ARM contributions llvm/lib/Target/ARM/LICENSE.TXT +md5 contributions llvm/lib/Support/MD5.cpp llvm/include/llvm/Support/MD5.h diff --git a/licenses/LibPNG2.txt b/licenses/LibPNG2.txt new file mode 100644 index 0000000000..e0c5b531cf --- /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 0000000000..f0fd20ab68 --- /dev/null +++ b/licenses/MIT.txt @@ -0,0 +1,20 @@ +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 0000000000..b937e78621 --- /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/MPL-1.1.txt b/licenses/MPL-1.1.txt new file mode 100644 index 0000000000..25d5a85c90 --- /dev/null +++ b/licenses/MPL-1.1.txt @@ -0,0 +1,401 @@ +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: +Any addition to or deletion from the contents of a file containing Original +Code or previous Modifications. +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 Sections 3.1, 3.2, 3.3, 3.4 +and 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 MPL 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/MPL-2.0.txt b/licenses/MPL-2.0.txt new file mode 100644 index 0000000000..d231cffdcd --- /dev/null +++ b/licenses/MPL-2.0.txt @@ -0,0 +1,292 @@ +Mozilla Public License Version 2.0 + +1. Definitions + +1.1. "Contributor" means each individual or legal entity that creates, contributes +to the creation of, or owns Covered Software. + +1.2. "Contributor Version" means the combination of the Contributions of others +(if any) used by a Contributor and that particular Contributor's Contribution. + + 1.3. "Contribution" means Covered Software of a particular Contributor. + +1.4. "Covered Software" means Source Code Form to which the initial Contributor +has attached the notice in Exhibit A, the Executable Form of such Source Code +Form, and Modifications of such Source Code Form, in each case including portions +thereof. + + 1.5. "Incompatible With Secondary Licenses" means + +(a) that the initial Contributor has attached the notice described in Exhibit +B to the Covered Software; or + +(b) that the Covered Software was made available under the terms of version +1.1 or earlier of the License, but not also under the terms of a Secondary +License. + +1.6. "Executable Form" means any form of the work other than Source Code Form. + +1.7. "Larger Work" means a work that combines Covered Software with other +material, in a separate file or files, that is not Covered Software. + + 1.8. "License" means this document. + +1.9. "Licensable" means having the right to grant, to the maximum extent possible, +whether at the time of the initial grant or subsequently, any and all of the +rights conveyed by this License. + + 1.10. "Modifications" means any of the following: + +(a) any file in Source Code Form that results from an addition to, deletion +from, or modification of the contents of Covered Software; or + +(b) any new file in Source Code Form that contains any Covered Software. + +1.11. "Patent Claims" of a Contributor means any patent claim(s), including +without limitation, method, process, and apparatus claims, in any patent Licensable +by such Contributor that would be infringed, but for the grant of the License, +by the making, using, selling, offering for sale, having made, import, or +transfer of either its Contributions or its Contributor Version. + +1.12. "Secondary License" means either the GNU General Public License, Version +2.0, the GNU Lesser General Public License, Version 2.1, the GNU Affero General +Public License, Version 3.0, or any later versions of those licenses. + +1.13. "Source Code Form" means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") means an individual or a legal entity exercising rights +under this License. For legal entities, "You" includes any entity that 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. License Grants and Conditions + + 2.1. Grants +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 such Contributor to use, reproduce, make available, modify, display, perform, +distribute, and otherwise exploit its Contributions, either on an unmodified +basis, with Modifications, or as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer for +sale, have made, import, and otherwise transfer either its Contributions or +its Contributor Version. + + 2.2. Effective Date +The licenses granted in Section 2.1 with respect to any Contribution become +effective for each Contribution on the date the Contributor first distributes +such Contribution. + + 2.3. Limitations on Grant Scope +The licenses granted in this Section 2 are the only rights granted under this +License. No additional rights or licenses will be implied from the distribution +or licensing of Covered Software under this License. Notwithstanding Section +2.1(b) above, no patent license is granted by a Contributor: + +(a) for any code that a Contributor has removed from Covered Software; or + +(b) for infringements caused by: (i) Your and any other third party's modifications +of Covered Software, or (ii) the combination of its Contributions with other +software (except as part of its Contributor Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of its +Contributions. + +This License does not grant any rights in the trademarks, service marks, or +logos of any Contributor (except as may be necessary to comply with the notice +requirements in Section 3.4). + + 2.4. Subsequent Licenses +No Contributor makes additional grants as a result of Your choice to distribute +the Covered Software under a subsequent version of this License (see Section +10.2) or under the terms of a Secondary License (if permitted under the terms +of Section 3.3). + + 2.5. Representation +Each Contributor represents that the Contributor believes its Contributions +are its original creation(s) or it has sufficient rights to grant the rights +to its Contributions conveyed by this License. + + 2.6. Fair Use +This License is not intended to limit any rights You have under applicable +copyright doctrines of fair use, fair dealing, or other equivalents. + + 2.7. Conditions +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in +Section 2.1. + +3. Responsibilities + + 3.1. Distribution of Source Form +All distribution of Covered Software in Source Code Form, including any Modifications +that You create or to which You contribute, must be under the terms of this +License. You must inform recipients that the Source Code Form of the Covered +Software is governed by the terms of this License, and how they can obtain +a copy of this License. You may not attempt to alter or restrict the recipients' +rights in the Source Code Form. + + 3.2. Distribution of Executable Form + If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code Form, +as described in Section 3.1, and You must inform recipients of the Executable +Form how they can obtain a copy of such Source Code Form by reasonable means +in a timely manner, at a charge no more than the cost of distribution to the +recipient; and + +(b) You may distribute such Executable Form under the terms of this License, +or sublicense it under different terms, provided that the license for the +Executable Form does not attempt to limit or alter the recipients' rights +in the Source Code Form under this License. + + 3.3. Distribution of a Larger Work +You may create and distribute a Larger Work under terms of Your choice, provided +that You also comply with the requirements of this License for the Covered +Software. If the Larger Work is a combination of Covered Software with a work +governed by one or more Secondary Licenses, and the Covered Software is not +Incompatible With Secondary Licenses, this License permits You to additionally +distribute such Covered Software under the terms of such Secondary License(s), +so that the recipient of the Larger Work may, at their option, further distribute +the Covered Software under the terms of either this License or such Secondary +License(s). + + 3.4. Notices +You may not remove or alter the substance of any license notices (including +copyright notices, patent notices, disclaimers of warranty, or limitations +of liability) contained within the Source Code Form of the Covered Software, +except that You may alter any license notices to the extent required to remedy +known factual inaccuracies. + + 3.5. Application of Additional Terms +You may choose to offer, and to charge a fee for, warranty, support, indemnity +or liability obligations to one or more recipients of Covered Software. However, +You may do so only on Your own behalf, and not on behalf of any Contributor. +You must make it absolutely clear that any such warranty, support, indemnity, +or liability obligation is offered by You alone, and You hereby agree to indemnify +every Contributor for any liability incurred by such Contributor as a result +of warranty, support, indemnity or liability terms You offer. You may include +additional disclaimers of warranty and limitations of liability specific to +any jurisdiction. + +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 Software 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 placed in a text file included with +all distributions of the Covered Software under this License. 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. Termination + +5.1. The rights granted under this License will terminate automatically if +You fail to comply with any of its terms. However, if You become compliant, +then the rights granted under this License from a particular Contributor are +reinstated (a) provisionally, unless and until such Contributor explicitly +and finally terminates Your grants, and (b) on an ongoing basis, if such Contributor +fails to notify You of the non-compliance by some reasonable means prior to +60 days after You have come back into compliance. Moreover, Your grants from +a particular Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the first +time You have received notice of non-compliance with this License from such +Contributor, and You become compliant prior to 30 days after Your receipt +of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent infringement +claim (excluding declaratory judgment actions, counter-claims, and cross-claims) +alleging that a Contributor Version directly or indirectly infringes any patent, +then the rights granted to You by any and all Contributors for the Covered +Software under Section 2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all end +user license agreements (excluding distributors and resellers) which have +been validly granted by You or Your distributors under this License prior +to termination shall survive termination. + +6. Disclaimer of Warranty +Covered Software is provided under this License on an "as is" basis, without +warranty of any kind, either expressed, implied, or statutory, including, +without limitation, warranties that the Covered Software 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 Software is with You. Should +any Covered Software prove defective in any respect, You (not any 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 +Software is authorized under this License except under this disclaimer. + +7. Limitation of Liability +Under no circumstances and under no legal theory, whether tort (including +negligence), contract, or otherwise, shall any Contributor, or anyone who +distributes Covered Software as permitted above, be liable to You for any +direct, indirect, special, incidental, or consequential damages of any character +including, without limitation, damages for lost profits, 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. + +8. Litigation +Any litigation relating to this License may be brought only in the courts +of a jurisdiction where the defendant maintains its principal place of business +and such litigation shall be governed by laws of that jurisdiction, without +reference to its conflict-of-law provisions. Nothing in this Section shall +prevent a party's ability to bring cross-claims or counter-claims. + +9. Miscellaneous +This License represents the complete agreement concerning the 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. +Any law or regulation which provides that the language of a contract shall +be construed against the drafter shall not be used to construe this License +against a Contributor. + +10. Versions of the License + + 10.1. New Versions +Mozilla Foundation is the license steward. Except as provided in Section 10.3, +no one other than the license steward has the right to modify or publish new +versions of this License. Each version will be given a distinguishing version +number. + + 10.2. Effect of New Versions +You may distribute the Covered Software under the terms of the version of +the License under which You originally received the Covered Software, or under +the terms of any subsequent version published by the license steward. + + 10.3. Modified Versions +If you create software not governed by this License, and you want to create +a new license for such software, you may create and use a modified version +of this License if you rename the license and remove any references to the +name of the license steward (except to note that such modified license differs +from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses +If You choose to distribute Source Code Form that is Incompatible With Secondary +Licenses under the terms of this version of the License, the notice described +in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice + +This Source Code Form is subject to the terms of the Mozilla Public License, +v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain +one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular file, +then You may include the notice in a location (such as a LICENSE file in a +relevant directory) where a recipient would be likely to look for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice + +This Source Code Form is "Incompatible With Secondary Licenses", as defined +by the Mozilla Public License, v. 2.0. diff --git a/licenses/NVIDIA.txt b/licenses/NVIDIA.txt new file mode 100644 index 0000000000..11bcb7668b --- /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/NextPVR.txt b/licenses/NextPVR.txt new file mode 100644 index 0000000000..8e3c67bd49 --- /dev/null +++ b/licenses/NextPVR.txt @@ -0,0 +1,17 @@ +Software License Agreement for NextPVR + +IMPORTANT- PLEASE READ CAREFULLY BEFORE USING THIS SOFTWARE: THIS LICENSE AGREEMENT FOR NextPVR ("LICENSE AGREEMENT") IS A LEGAL AGREEMENT BETWEEN YOU (EITHER ON BEHALF OF YOURSELF AS AN INDIVIDUAL OR ON BEHALF OF AN ENTITY AS ITS AUTHORIZED REPRESENTATIVE) AND PINSTRIPE LIMITED. FOR THE NextPVR SOFTWARE ("SOFTWARE"). THIS LICENSE AGREEMENT FOR NextPVR SUPERSEDES PREVIOUS VERSIONS. BY INSTALLING THE SOFTWARE (AS DEFINED BELOW), COPYING OR OTHERWISE USING THE SOFTWARE YOU AGREE TO BE BOUND BY ALL OF THE TERMS OF THIS END USER LICENSE AGREEMENT REGARDING YOUR USE OF THE SOFTWARE. IF YOU DO NOT AGREE TO THE TERMS OF THIS LICENSE AGREEMENT, UNINSTALL THE SOFTWARE, AND DO NOT COPY OR OTHERWISE USE THE SOFTWARE. + +GRANT OF LICENSE: Subject to the following terms, PINSTRIPE LIMITED hereby grants you a non-exclusive, perpetual, non-transferable license to install and to use the NextPVR software ("Software") for personal, non-commercial use. You may copy the Software for back-up or archival purposes. + +LICENSE RESTRICTIONS: You may not: (i) reverse engineer, decompile, or disassemble the Software; (ii) modify, or create derivative works based upon, the Software in whole or in part; (iii) distribute copies of the Software; (iv) remove any proprietary notices or labels on the Software; or (v) resell, lease, rent, transfer, sublicense, or otherwise transfer rights to the Software. You agree that the NextPVR software will not be used for commercial purposes without full written permission. Any such forbidden use shall immediately terminate your license to the software. + +TITLE: You agree that no title to the intellectual property in the Software is transferred to you. Title, ownership, rights, and intellectual property rights in and to the Software shall remain in PINSTRIPE LIMITED. + +UPDATES: From time to time, PINSTRIPE LIMITED may make updates to the Software generally available. You may download and install these software updates released by PINSTRIPE LIMITED. All updates to the Software shall be governed by this Agreement, unless other license terms are provided with the update. Under the Software's default configuration, if you are connected to the Internet, the Software is enabled by default to query latest version of Software and display if updates are available. You may choose to switch this version check off and not use it. + +TECHNICAL SUPPORT: Technical support for the software, as made available by PINSTRIPE LIMITED, is available on the web site at: http://www.nextpvr.com + +DISCLAIMER OF WARRANTY: The Software is provided to you at minimal charge. ACCORDINGLY, YOU AGREE THAT PINSTRIPE LIMITED HAS MADE NO EXPRESS WARRANTIES, ORAL OR WRITTEN, TO YOU REGARDING THE SOFTWARE AND THAT THE SOFTWARE IS BEING PROVIDED TO YOU "AS IS" WITHOUT WARRANTY OF ANY KIND. PINSTRIPE LIMITED DISCLAIMS ANY AND ALL OTHER WARRANTIES, WHETHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF NONINFRINGEMENT OF THIRD PARTY RIGHTS, MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. PINSTRIPE LIMITED SHALL NOT BE LIABLE FOR INDIRECT, INCIDENTAL, SPECIAL, COVER, RELIANCE, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF ANTICIPATED PROFIT) ARISING FROM ANY CAUSE UNDER OR RELATED TO THIS AGREEMENT. + +LIMITATION OF LIABILITY: You must assume the entire risk of using the program. IN NO EVENT SHALL PINSTRIPE LIMITED BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING ANY LOST PROFITS, LOST SAVINGS, OR OTHER INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND ARISING OUT OF THE USE OF THE PINSTRIPE LIMITED SOFTWARE, EVEN IF PINSTRIPE LIMITED HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. IN NO EVENT WILL PINSTRIPE LIMITED'S LIABILITY FOR ANY CLAIM, WHETHER IN CONTRACT, TORT, OR ANY OTHER THEORY OF LIABILITY, EXCEED THE LICENSE FEE PAID BY YOU, PROVIDED, HOWEVER, IF THE RELEVANT SOFTWARE WAS PROVIDED TO YOU AT NO CHARGE YOU AGREE PINSTRIPE LIMITED SHALL NOT BE LIABLE TO YOU FOR ANY DAMAGES. THIS LIMITATION SHALL APPLY TO CLAIMS OF PERSONAL INJURY TO THE EXTENT PERMITTED BY LAW. diff --git a/licenses/OFL-1.1.txt b/licenses/OFL-1.1.txt new file mode 100644 index 0000000000..0da42f86bb --- /dev/null +++ b/licenses/OFL-1.1.txt @@ -0,0 +1,84 @@ +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/QCA.txt b/licenses/QCA.txt new file mode 100644 index 0000000000..68890f0f0c --- /dev/null +++ b/licenses/QCA.txt @@ -0,0 +1,45 @@ +Copyright (c) 2013-2017 Qualcomm Atheros, Inc. + +All rights reserved. + +Redistribution and use in binary forms, without +modification, are permitted (subject to the limitations in the +disclaimer below) provided that the following conditions are met: + +* Redistributions 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 Qualcomm Atheros, Inc. nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +* No Reverse engineering, decompiling, decrypting, or disassembling of + this software is permitted. + +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. NO LICENSES OR OTHER RIGHTS, +WHETHER EXPRESS, IMPLIED, BASED ON ESTOPPEL OR OTHERWISE, ARE GRANTED +TO ANY PARTY'S PATENTS, PATENT APPLICATIONS, OR PATENTABLE INVENTIONS +BY VIRTUE OF THIS LICENSE OR THE DELIVERY OR PROVISION BY QUALCOMM +ATHEROS, INC. OF THE SOFTWARE. + +IN NO EVENT SHALL THE COPYRIGHT OWNER OR ANY CONTRIBUTOR BE LIABLE FOR +ANY 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 REGARDLESS OF ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF OR RESULTING FROM THE USE OF THE +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. IN ANY +EVENT, THE TOTAL AGGREGATE LIABILITY THAT MAY BE IMPOSED ON QUALCOMM +ATHEROS, INC. FOR ANY DIRECT DAMAGES ARISING UNDER OR RESULTING FROM +THIS AGREEMENT OR IN CONNECTION WITH ANY USE OF THE SOFTWARE SHALL NOT +EXCEED A TOTAL AMOUNT OF US$5.00. + +IF ANY OF THE ABOVE PROVISIONS ARE HELD TO BE VOID, INVALID, +UNENFORCEABLE, OR ILLEGAL, THE OTHER PROVISIONS SHALL CONTINUE IN FULL +FORCE AND EFFECT. + diff --git a/licenses/Radeon_rlc.txt b/licenses/Radeon_rlc.txt new file mode 100644 index 0000000000..4ece3404c9 --- /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/licenses/Unlicense.txt b/licenses/Unlicense.txt new file mode 100644 index 0000000000..471f09f4cf --- /dev/null +++ b/licenses/Unlicense.txt @@ -0,0 +1,25 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +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 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. + +For more information, please refer to + diff --git a/licenses/Vim.txt b/licenses/Vim.txt new file mode 100644 index 0000000000..05738e69de --- /dev/null +++ b/licenses/Vim.txt @@ -0,0 +1,76 @@ +VIM LICENSE + +I) There are no restrictions on distributing unmodified copies of Vim except +that they must include this license text. You can also distribute unmodified +parts of Vim, likewise unrestricted except that they must include this license +text. You are also allowed to include executables that you made from the unmodified +Vim sources, plus your own usage examples and Vim scripts. + +II) It is allowed to distribute a modified (or extended) version of Vim, including +executables and/or source code, when the following four conditions are met: + + 1) This license text must be included unmodified. + + 2) The modified Vim must be distributed in one of the following five ways: + +a) If you make changes to Vim yourself, you must clearly describe in the distribution +how to contact you. When the maintainer asks you (in any way) for a copy of +the modified Vim you distributed, you must make your changes, including source +code, available to the maintainer without fee. The maintainer reserves the +right to include your changes in the official version of Vim. What the maintainer +will do with your changes and under what license they will be distributed +is negotiable. If there has been no negotiation then this license, or a later +version, also applies to your changes. The current maintainer is Bram Moolenaar +. If this changes it will be announced in appropriate places +(most likely vim.sf.net, www.vim.org and/or comp.editors). When it is completely +impossible to contact the maintainer, the obligation to send him your changes +ceases. Once the maintainer has confirmed that he has received your changes +they will not have to be sent again. + +b) If you have received a modified Vim that was distributed as mentioned under +a) you are allowed to further distribute it unmodified, as mentioned at I). +If you make additional changes the text under a) applies to those changes. + +c) Provide all the changes, including source code, with every copy of the +modified Vim you distribute. This may be done in the form of a context diff. +You can choose what license to use for new code you add. The changes and their +license must not restrict others from making their own changes to the official +version of Vim. + +d) When you have a modified Vim which includes changes as mentioned under +c), you can distribute it without the source code for the changes if the following +three conditions are met: +- The license that applies to the changes permits you to distribute the changes +to the Vim maintainer without fee or restriction, and permits the Vim maintainer +to include the changes in the official version of Vim without fee or restriction. +- You keep the changes for at least three years after last distributing the +corresponding modified Vim. When the maintainer or someone who you distributed +the modified Vim to asks you (in any way) for the changes within this period, +you must make them available to him. +- You clearly describe in the distribution how to contact you. This contact +information must remain valid for at least three years after last distributing +the corresponding modified Vim, or as long as possible. + +e) When the GNU General Public License (GPL) applies to the changes, you can +distribute the modified Vim under the GNU GPL version 2 or any later version. + +3) A message must be added, at least in the output of the ":version" command +and in the intro screen, such that the user of the modified Vim is able to +see that it was modified. When distributing as mentioned under 2)e) adding +the message is only required for as far as this does not conflict with the +license used for the changes. + +4) The contact information as required under 2)a) and 2)d) must not be removed +or changed, except that the person himself can make corrections. + +III) If you distribute a modified version of Vim, you are encouraged to use +the Vim license for your changes and make them available to the maintainer, +including the source code. The preferred way to do this is by e-mail or by +uploading the files to a server and e-mailing the URL. If the number of changes +is small (e.g., a modified Makefile) e-mailing a context diff will do. The +e-mail address to be used is + +IV) It is not allowed to remove this license from the distribution of the +Vim sources, parts of it or from a modified version. You may use this license +for previous Vim releases instead of the license that they came with, at your +option. diff --git a/licenses/Zlib.txt b/licenses/Zlib.txt new file mode 100644 index 0000000000..ccd742b5fc --- /dev/null +++ b/licenses/Zlib.txt @@ -0,0 +1,19 @@ +zlib License + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the +use of 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 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 notice may not be removed or altered from any source distribution. diff --git a/licenses/fdk-aac.txt b/licenses/fdk-aac.txt new file mode 100644 index 0000000000..05b32bdeaf --- /dev/null +++ b/licenses/fdk-aac.txt @@ -0,0 +1,92 @@ +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. 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), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de + diff --git a/licenses/gpgme.txt b/licenses/gpgme.txt new file mode 100644 index 0000000000..acfd614714 --- /dev/null +++ b/licenses/gpgme.txt @@ -0,0 +1,38 @@ +Additional license notices for GPGME. -*- org -*- + +This file contains the copying permission notices for various files in +the GPGME distribution which are not covered by the GNU Lesser +General Public License (LGPL) or the GNU General Public License (GPL). + +These notices all require that a copy of the notice be included +in the accompanying documentation and be distributed with binary +distributions of the code, so be sure to include this file along +with any binary distributions derived from the GNU C Library. + +* MIT License + + For files: + - cJSON.c, cJSON.h + +#+begin_quote + Copyright (c) 2009 Dave Gamble + + Permission is hereby granted, free of charge, to any person obtaining + a opy of this software and associated documentation files (the + "Software"), to eal in the Software without restriction, including + without limitation the ights 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 ROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +#+end_quote diff --git a/packages/addons/addon-depends/argtable2/package.mk b/packages/addons/addon-depends/argtable2/package.mk new file mode 100644 index 0000000000..5f9ea0e00e --- /dev/null +++ b/packages/addons/addon-depends/argtable2/package.mk @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="argtable2" +PKG_VERSION="2.13" +PKG_SHA256="8f77e8a7ced5301af6e22f47302fdbc3b1ff41f2b83c43c77ae5ca041771ddbf" +PKG_LICENSE="BSD" +PKG_SITE="http://argtable.sourceforge.net/" +PKG_URL="https://downloads.sourceforge.net/project/argtable/argtable/argtable-${PKG_VERSION}/argtable2-${PKG_VERSION:2:4}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Argtable is an open source ANSI C library that parses GNU-style command-line options." +PKG_TOOLCHAIN="autotools" +PKG_BUILD_FLAGS="-sysroot" + +PKG_CONFIGURE_OPTS_TARGET="--enable-static --disable-shared" diff --git a/packages/addons/addon-depends/ccid/package.mk b/packages/addons/addon-depends/ccid/package.mk new file mode 100644 index 0000000000..60ea0654cb --- /dev/null +++ b/packages/addons/addon-depends/ccid/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="ccid" +PKG_VERSION="1.6.2" +PKG_SHA256="41958410950157e622f9d91c9e78c7b708db74e22f71190c581d24d20564d449" +PKG_LICENSE="LGPL" +PKG_SITE="https://ccid.apdu.fr" +PKG_URL="https://ccid.apdu.fr/files/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain pcsc-lite" +PKG_LONGDESC="A generic USB Chip/Smart Card Interface Devices driver." +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="--enable-static --enable-twinserial" + +post_configure_target() { + libtool_remove_rpath libtool +} + +make_target() { + make + make -C src/ Info.plist +} diff --git a/packages/addons/addon-depends/chrome-depends/at-spi2-core/package.mk b/packages/addons/addon-depends/chrome-depends/at-spi2-core/package.mk new file mode 100644 index 0000000000..75947a25c4 --- /dev/null +++ b/packages/addons/addon-depends/chrome-depends/at-spi2-core/package.mk @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2017 Escalade +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="at-spi2-core" +PKG_VERSION="2.57.0" +PKG_SHA256="942070eff19155b7d6ce5557f1a020015287b840048536e9ef9a28c4e9ce428c" +PKG_LICENSE="OSS" +PKG_SITE="https://www.gnome.org/" +PKG_URL="https://download.gnome.org/sources/at-spi2-core/${PKG_VERSION:0:4}/at-spi2-core-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain atk dbus glib libxml2" +PKG_LONGDESC="Protocol definitions and daemon for D-Bus at-spi." + +configure_package() { + # Build with x11 support + if [ ${DISPLAYSERVER} = "x11" ]; then + PKG_DEPENDS_TARGET+=" libXtst" + fi +} + +pre_configure_target() { + PKG_MESON_OPTS_TARGET="-Ddocs=false \ + -Dintrospection=disabled \ + -Ddbus_daemon=/usr/bin/dbus-daemon" + + if [ ${DISPLAYSERVER} = "x11" ]; then + PKG_MESON_OPTS_TARGET+="-Dx11=true" + TARGET_LDFLAGS="${LDFLAGS} -lXext" + else + PKG_MESON_OPTS_TARGET+="-Dx11=false" + fi +} diff --git a/packages/addons/addon-depends/chrome-depends/atk/package.mk b/packages/addons/addon-depends/chrome-depends/atk/package.mk new file mode 100644 index 0000000000..8d0d3b217e --- /dev/null +++ b/packages/addons/addon-depends/chrome-depends/atk/package.mk @@ -0,0 +1,16 @@ +# 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="atk" +PKG_VERSION="2.38.0" +PKG_SHA256="ac4de2a4ef4bd5665052952fe169657e65e895c5057dffb3c2a810f6191a0c36" +PKG_LICENSE="GPL" +PKG_SITE="http://library.gnome.org/devel/atk/" +PKG_URL="https://ftp.gnome.org/pub/gnome/sources/atk/${PKG_VERSION:0:4}/atk-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain glib" +PKG_LONGDESC="Provides the set of accessibility interfaces that are implemented by other applications." +PKG_BUILD_FLAGS="+pic" + +PKG_MESON_OPTS_TARGET="-Ddocs=false \ + -Dintrospection=false" diff --git a/packages/addons/addon-depends/chrome-depends/chrome-libXcomposite/package.mk b/packages/addons/addon-depends/chrome-depends/chrome-libXcomposite/package.mk new file mode 100644 index 0000000000..e0933f95ad --- /dev/null +++ b/packages/addons/addon-depends/chrome-depends/chrome-libXcomposite/package.mk @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +. $(get_pkg_directory libXcomposite)/package.mk + +PKG_NAME="chrome-libXcomposite" +PKG_LONGDESC="libXcomposite for chrome" +PKG_URL="" +PKG_DEPENDS_UNPACK+=" libXcomposite" +PKG_BUILD_FLAGS="-sysroot" + +PKG_CONFIGURE_OPTS_TARGET="${PKG_CONFIGURE_OPTS_TARGET} \ + --disable-static \ + --enable-shared" + +unpack() { + mkdir -p ${PKG_BUILD} + tar --strip-components=1 -xf ${SOURCES}/${PKG_NAME:7}/${PKG_NAME:7}-${PKG_VERSION}.tar.xz -C ${PKG_BUILD} +} diff --git a/packages/addons/addon-depends/chrome-depends/chrome-libXdamage/package.mk b/packages/addons/addon-depends/chrome-depends/chrome-libXdamage/package.mk new file mode 100644 index 0000000000..6e5195a978 --- /dev/null +++ b/packages/addons/addon-depends/chrome-depends/chrome-libXdamage/package.mk @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +. $(get_pkg_directory libXdamage)/package.mk + +PKG_NAME="chrome-libXdamage" +PKG_LONGDESC="libXdamage for chrome" +PKG_URL="" +PKG_DEPENDS_UNPACK+=" libXdamage" +PKG_BUILD_FLAGS="-sysroot" + +PKG_CONFIGURE_OPTS_TARGET="${PKG_CONFIGURE_OPTS_TARGET} \ + --disable-static \ + --enable-shared" + +unpack() { + mkdir -p ${PKG_BUILD} + tar --strip-components=1 -xf ${SOURCES}/${PKG_NAME:7}/${PKG_NAME:7}-${PKG_VERSION}.tar.xz -C ${PKG_BUILD} +} diff --git a/packages/addons/addon-depends/chrome-depends/chrome-libXfixes/package.mk b/packages/addons/addon-depends/chrome-depends/chrome-libXfixes/package.mk new file mode 100644 index 0000000000..c2dbce04f1 --- /dev/null +++ b/packages/addons/addon-depends/chrome-depends/chrome-libXfixes/package.mk @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +. $(get_pkg_directory libXfixes)/package.mk + +PKG_NAME="chrome-libXfixes" +PKG_LONGDESC="libXfixes for chrome" +PKG_URL="" +PKG_DEPENDS_UNPACK+=" libXfixes" +PKG_BUILD_FLAGS="-sysroot" + +PKG_CONFIGURE_OPTS_TARGET="${PKG_CONFIGURE_OPTS_TARGET} \ + --disable-static \ + --enable-shared" + +unpack() { + mkdir -p ${PKG_BUILD} + tar --strip-components=1 -xf ${SOURCES}/${PKG_NAME:7}/${PKG_NAME:7}-${PKG_VERSION}.tar.xz -C ${PKG_BUILD} +} diff --git a/packages/addons/addon-depends/chrome-depends/chrome-libXi/package.mk b/packages/addons/addon-depends/chrome-depends/chrome-libXi/package.mk new file mode 100644 index 0000000000..3778b5e3da --- /dev/null +++ b/packages/addons/addon-depends/chrome-depends/chrome-libXi/package.mk @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +. $(get_pkg_directory libXi)/package.mk + +PKG_NAME="chrome-libXi" +PKG_LONGDESC="libXi for chrome" +PKG_URL="" +PKG_DEPENDS_UNPACK+=" libXi" +PKG_BUILD_FLAGS="-sysroot" + +PKG_CONFIGURE_OPTS_TARGET="${PKG_CONFIGURE_OPTS_TARGET} \ + --disable-static \ + --enable-shared" + +unpack() { + mkdir -p ${PKG_BUILD} + tar --strip-components=1 -xf ${SOURCES}/${PKG_NAME:7}/${PKG_NAME:7}-${PKG_VERSION}.tar.xz -C ${PKG_BUILD} +} diff --git a/packages/addons/addon-depends/chrome-depends/chrome-libXrender/package.mk b/packages/addons/addon-depends/chrome-depends/chrome-libXrender/package.mk new file mode 100644 index 0000000000..222b58985b --- /dev/null +++ b/packages/addons/addon-depends/chrome-depends/chrome-libXrender/package.mk @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +. $(get_pkg_directory libXrender)/package.mk + +PKG_NAME="chrome-libXrender" +PKG_LONGDESC="libXrender for chrome" +PKG_URL="" +PKG_DEPENDS_UNPACK+=" libXrender" +PKG_BUILD_FLAGS="-sysroot" + +PKG_CONFIGURE_OPTS_TARGET="${PKG_CONFIGURE_OPTS_TARGET} \ + --disable-static \ + --enable-shared" + +unpack() { + mkdir -p ${PKG_BUILD} + tar --strip-components=1 -xf ${SOURCES}/${PKG_NAME:7}/${PKG_NAME:7}-${PKG_VERSION}.tar.xz -C ${PKG_BUILD} +} diff --git a/packages/addons/addon-depends/chrome-depends/chrome-libXtst/package.mk b/packages/addons/addon-depends/chrome-depends/chrome-libXtst/package.mk new file mode 100644 index 0000000000..9b5a356701 --- /dev/null +++ b/packages/addons/addon-depends/chrome-depends/chrome-libXtst/package.mk @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +. $(get_pkg_directory libXtst)/package.mk + +PKG_NAME="chrome-libXtst" +PKG_LONGDESC="libXtst for chrome" +PKG_URL="" +PKG_DEPENDS_UNPACK+=" libXtst" +PKG_BUILD_FLAGS="-sysroot" + +PKG_CONFIGURE_OPTS_TARGET="${PKG_CONFIGURE_OPTS_TARGET} \ + --disable-static \ + --enable-shared" + +unpack() { + mkdir -p ${PKG_BUILD} + tar --strip-components=1 -xf ${SOURCES}/${PKG_NAME:7}/${PKG_NAME:7}-${PKG_VERSION}.tar.xz -C ${PKG_BUILD} +} diff --git a/packages/addons/addon-depends/chrome-depends/chrome-libxcb/package.mk b/packages/addons/addon-depends/chrome-depends/chrome-libxcb/package.mk new file mode 100644 index 0000000000..56b4afdeeb --- /dev/null +++ b/packages/addons/addon-depends/chrome-depends/chrome-libxcb/package.mk @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +. $(get_pkg_directory libxcb)/package.mk + +PKG_NAME="chrome-libxcb" +PKG_LONGDESC="libxcb for chrome" +PKG_URL="" +PKG_DEPENDS_UNPACK+=" libxcb" +PKG_BUILD_FLAGS="-sysroot" + +PKG_CONFIGURE_OPTS_TARGET="${PKG_CONFIGURE_OPTS_TARGET} \ + --disable-static \ + --enable-shared" + +unpack() { + mkdir -p ${PKG_BUILD} + tar --strip-components=1 -xf ${SOURCES}/${PKG_NAME:7}/${PKG_NAME:7}-${PKG_VERSION}.tar.xz -C ${PKG_BUILD} +} diff --git a/packages/addons/addon-depends/chrome-depends/chrome-libxkbcommon/package.mk b/packages/addons/addon-depends/chrome-depends/chrome-libxkbcommon/package.mk new file mode 100644 index 0000000000..47188670a6 --- /dev/null +++ b/packages/addons/addon-depends/chrome-depends/chrome-libxkbcommon/package.mk @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2020-present Team LibreELEC (https://libreelec.tv) + +. $(get_pkg_directory libxkbcommon)/package.mk + +PKG_NAME="chrome-libxkbcommon" +PKG_LONGDESC="libxkbcommon for chrome" +PKG_URL="" +PKG_DEPENDS_UNPACK+=" libxkbcommon" +PKG_BUILD_FLAGS="-sysroot" + +unpack() { + mkdir -p ${PKG_BUILD} + tar --strip-components=1 -xf ${SOURCES}/${PKG_NAME:7}/${PKG_NAME:7}-${PKG_VERSION}.tar.gz -C ${PKG_BUILD} +} diff --git a/packages/addons/addon-depends/chrome-depends/chrome-libxshmfence/package.mk b/packages/addons/addon-depends/chrome-depends/chrome-libxshmfence/package.mk new file mode 100644 index 0000000000..a7e4e36327 --- /dev/null +++ b/packages/addons/addon-depends/chrome-depends/chrome-libxshmfence/package.mk @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +. $(get_pkg_directory libxshmfence)/package.mk + +PKG_NAME="chrome-libxshmfence" +PKG_LONGDESC="libxshmfence for chrome" +PKG_URL="" +PKG_DEPENDS_UNPACK+=" libxshmfence" +PKG_BUILD_FLAGS="-sysroot" + +PKG_CONFIGURE_OPTS_TARGET="${PKG_CONFIGURE_OPTS_TARGET} \ + --disable-static \ + --enable-shared" + +unpack() { + mkdir -p ${PKG_BUILD} + tar --strip-components=1 -xf ${SOURCES}/${PKG_NAME:7}/${PKG_NAME:7}-${PKG_VERSION}.tar.xz -C ${PKG_BUILD} +} diff --git a/packages/addons/addon-depends/chrome-depends/cups/package.mk b/packages/addons/addon-depends/chrome-depends/cups/package.mk new file mode 100644 index 0000000000..e94eda9f79 --- /dev/null +++ b/packages/addons/addon-depends/chrome-depends/cups/package.mk @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2017 Escalade +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="cups" +PKG_VERSION="2.4.12" +PKG_SHA256="7a4d32822b320aa2999b18fdfc4ce5ca9ad204fe6302ff69e6c24b21f8d0eaa0" +PKG_LICENSE="GPL" +PKG_SITE="http://www.cups.org" +PKG_URL="https://github.com/openprinting/cups/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain gnutls zlib" +PKG_LONGDESC="CUPS printing system." +PKG_BUILD_FLAGS="+pic -sysroot" + +PKG_CONFIGURE_OPTS_TARGET="--libdir=/usr/lib \ + --disable-gssapi \ + --with-dnssd=no \ + --with-tls=gnutls + --disable-unit-tests" + +pre_configure_target() { + cd .. + rm -rf .${TARGET_NAME} +} + +makeinstall_target() { + make BUILDROOT="${INSTALL}" install +} diff --git a/packages/addons/addon-depends/chrome-depends/gtk3/package.mk b/packages/addons/addon-depends/chrome-depends/gtk3/package.mk new file mode 100644 index 0000000000..963ff0d2ff --- /dev/null +++ b/packages/addons/addon-depends/chrome-depends/gtk3/package.mk @@ -0,0 +1,37 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2017 Escalade +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="gtk3" +PKG_VERSION="3.24.49" +PKG_SHA256="5ea52c6a28f0e5ecf2e9a3c2facbb30d040b73871fcd5f33cd1317e9018a146e" +PKG_LICENSE="LGPL" +PKG_SITE="https://www.gtk.org/" +PKG_URL="https://download.gnome.org/sources/gtk/${PKG_VERSION:0:4}/gtk-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain at-spi2-core atk cairo gdk-pixbuf glib libX11 libXi libXrandr libepoxy pango libxkbcommon" +PKG_DEPENDS_CONFIG="libXft pango gdk-pixbuf shared-mime-info" +PKG_LONGDESC="A library for creating graphical user interfaces for the X Window System." +PKG_BUILD_FLAGS="-sysroot" + +PKG_MESON_OPTS_TARGET="-Dbroadway_backend=false \ + -Dcloudproviders=false \ + -Dcolord=no \ + -Ddemos=false \ + -Dexamples=false \ + -Dgtk_doc=false \ + -Dintrospection=false \ + -Dman=false \ + -Dprint_backends=file,lpr \ + -Dquartz_backend=false \ + -Dtests=false \ + -Dwayland_backend=false \ + -Dwin32_backend=false \ + -Dxinerama=no \ + -Dbuiltin_immodules=yes \ + -Dx11_backend=true" + +pre_configure_target() { + # ${TOOLCHAIN}/bin/glib-compile-resources requires ${TOOLCHAIN}/lib/libffi.so.6 + export LD_LIBRARY_PATH="${TOOLCHAIN}/lib:${LD_LIBRARY_PATH}" + export GLIB_COMPILE_RESOURCES=glib-compile-resources GLIB_MKENUMS=glib-mkenums GLIB_GENMARSHAL=glib-genmarshal +} diff --git a/packages/addons/addon-depends/chrome-depends/harfbuzz-icu/package.mk b/packages/addons/addon-depends/chrome-depends/harfbuzz-icu/package.mk new file mode 100644 index 0000000000..716edb7226 --- /dev/null +++ b/packages/addons/addon-depends/chrome-depends/harfbuzz-icu/package.mk @@ -0,0 +1,28 @@ +# 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) + +. $(get_pkg_directory harfbuzz)/package.mk + +PKG_NAME="harfbuzz-icu" +PKG_URL="" +PKG_DEPENDS_TARGET+=" icu" +PKG_LONGDESC="HarfBuzz with icu" +PKG_DEPENDS_CONFIG="icu" +PKG_DEPENDS_UNPACK+=" harfbuzz" +PKG_BUILD_FLAGS="-sysroot" + +PKG_MESON_OPTS_TARGET="-Dbenchmark=disabled \ + -Dcairo=enabled \ + -Ddocs=disabled \ + -Dfreetype=enabled \ + -Dglib=enabled \ + -Dgobject=disabled \ + -Dgraphite=disabled \ + -Dicu=enabled \ + -Dtests=disabled" + +unpack() { + mkdir -p ${PKG_BUILD} + tar --strip-components=1 -xf ${SOURCES}/${PKG_NAME:0:8}/${PKG_NAME:0:8}-${PKG_VERSION}.tar.xz -C ${PKG_BUILD} +} diff --git a/packages/addons/addon-depends/chrome-depends/libXScrnSaver/package.mk b/packages/addons/addon-depends/chrome-depends/libXScrnSaver/package.mk new file mode 100644 index 0000000000..6a7240e9ed --- /dev/null +++ b/packages/addons/addon-depends/chrome-depends/libXScrnSaver/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) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libXScrnSaver" +PKG_VERSION="1.2.4" +PKG_SHA256="75cd2859f38e207a090cac980d76bc71e9da99d48d09703584e00585abc920fe" +PKG_LICENSE="GPL" +PKG_SITE="https://xorg.freedesktop.org/" +PKG_URL="https://xorg.freedesktop.org/releases/individual/lib/libXScrnSaver-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain libXext scrnsaverproto" +PKG_LONGDESC="X11 Screen Saver extension client library." +PKG_BUILD_FLAGS="-sysroot" + +PKG_CONFIGURE_OPTS_TARGET="--disable-static \ + --enable-shared \ + --enable-malloc0returnsnull" diff --git a/packages/addons/addon-depends/chrome-depends/libXcursor/package.mk b/packages/addons/addon-depends/chrome-depends/libXcursor/package.mk new file mode 100644 index 0000000000..84c5ee3965 --- /dev/null +++ b/packages/addons/addon-depends/chrome-depends/libXcursor/package.mk @@ -0,0 +1,17 @@ +# 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="libXcursor" +PKG_VERSION="1.2.3" +PKG_SHA256="fde9402dd4cfe79da71e2d96bb980afc5e6ff4f8a7d74c159e1966afb2b2c2c0" +PKG_LICENSE="OSS" +PKG_SITE="http://www.X.org" +PKG_URL="https://xorg.freedesktop.org/archive/individual/lib/libXcursor-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain libX11 libXfixes libXrender" +PKG_LONGDESC="X11 Cursor management library.s" +PKG_BUILD_FLAGS="+pic -sysroot" + +post_configure_target() { + libtool_remove_rpath libtool +} diff --git a/packages/addons/addon-depends/chrome-depends/libxss/package.mk b/packages/addons/addon-depends/chrome-depends/libxss/package.mk new file mode 100644 index 0000000000..ab06ecca19 --- /dev/null +++ b/packages/addons/addon-depends/chrome-depends/libxss/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libxss" +PKG_VERSION="1.2.4" +PKG_SHA256="75cd2859f38e207a090cac980d76bc71e9da99d48d09703584e00585abc920fe" +PKG_LICENSE="OSS" +PKG_SITE="https://www.X.org" +PKG_URL="https://xorg.freedesktop.org/archive/individual/lib/libXScrnSaver-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain util-macros libXext scrnsaverproto" +PKG_LONGDESC="X11 Screen Saver extension library." +PKG_BUILD_FLAGS="+pic -sysroot" + +PKG_CONFIGURE_OPTS_TARGET="--enable-malloc0returnsnull" + +post_configure_target() { + libtool_remove_rpath libtool +} diff --git a/packages/addons/addon-depends/chrome-depends/scrnsaverproto/package.mk b/packages/addons/addon-depends/chrome-depends/scrnsaverproto/package.mk new file mode 100644 index 0000000000..aeafb7ef97 --- /dev/null +++ b/packages/addons/addon-depends/chrome-depends/scrnsaverproto/package.mk @@ -0,0 +1,13 @@ +# 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="scrnsaverproto" +PKG_VERSION="1.2.2" +PKG_SHA256="8bb70a8da164930cceaeb4c74180291660533ad3cc45377b30a795d1b85bcd65" +PKG_LICENSE="GPL" +PKG_SITE="http://xorg.freedesktop.org/" +PKG_URL="https://xorg.freedesktop.org/releases/individual/proto/scrnsaverproto-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="X11 Screen Saver extension wire protocol." +PKG_BUILD_FLAGS="-sysroot" diff --git a/packages/addons/addon-depends/chrome-depends/unclutter/package.mk b/packages/addons/addon-depends/chrome-depends/unclutter/package.mk new file mode 100644 index 0000000000..d5df736175 --- /dev/null +++ b/packages/addons/addon-depends/chrome-depends/unclutter/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="unclutter" +PKG_VERSION="1.09" +PKG_SHA256="3a53575fe2a75a34bc9a2b0ad92ee0f8a7dbedc05d8783f191c500060a40a9bd" +PKG_LICENSE="Public Domain" +PKG_SITE="https://sourceforge.net/projects/unclutter/" +PKG_URL="https://sourceforge.net/projects/unclutter/unclutter/source_${PKG_VERSION}/unclutter-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain libX11" +PKG_LONGDESC="Unclutter runs in the background of an X11 session and hides the X11 Cursor." + +make_target() { + rm -f Makefile + LDFLAGS="${LDFLAGS} -lX11" ${MAKE} unclutter +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + install -m 755 unclutter ${INSTALL}/usr/bin/ +} diff --git a/packages/addons/addon-depends/chrome-depends/unix_ar/package.mk b/packages/addons/addon-depends/chrome-depends/unix_ar/package.mk new file mode 100644 index 0000000000..2341540cdf --- /dev/null +++ b/packages/addons/addon-depends/chrome-depends/unix_ar/package.mk @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2022-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="unix_ar" +PKG_VERSION="0.2.1" +PKG_SHA256="4e1c6e8fe5255b7babe93b9af51532ba09c6946eee413c5db00cab3878d7ed2f" +PKG_LICENSE="BSD 3-Clause" +PKG_SITE="https://github.com/getninjas/unix_ar" +PKG_URL="https://github.com/getninjas/unix_ar/archive/refs/tags/${PKG_VERSION}.tar.gz" +PKG_TOOLCHAIN="manual" +PKG_LONGDESC="Python: This packages allows the reading and writing of AR archive files." diff --git a/packages/addons/addon-depends/comskip/package.mk b/packages/addons/addon-depends/comskip/package.mk new file mode 100644 index 0000000000..32ebf3c342 --- /dev/null +++ b/packages/addons/addon-depends/comskip/package.mk @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="comskip" +PKG_VERSION="0.83" +PKG_SHA256="bd90d7922916e0b04ea9f3426ea7747d347f218f3f915fb4d251961d0730876e" +PKG_LICENSE="GPL" +PKG_SITE="http://www.kaashoek.com/comskip/" +PKG_URL="https://github.com/erikkaashoek/Comskip/archive/V${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain argtable2 ffmpegx" +PKG_DEPENDS_CONFIG="argtable2 ffmpegx" +PKG_LONGDESC="Comskip detects commercial breaks from a video stream. It can be used for post-processing recordings." +PKG_TOOLCHAIN="autotools" +PKG_BUILD_FLAGS="-sysroot -cfg-libs" + +pre_configure_target() { + # pass ffmpegx to build + CFLAGS+=" -I$(get_install_dir ffmpegx)/usr/local/include" + LDFLAGS+=" -L$(get_install_dir ffmpegx)/usr/local/lib -ldl" +} diff --git a/packages/addons/addon-depends/cxxtools/package.mk b/packages/addons/addon-depends/cxxtools/package.mk new file mode 100644 index 0000000000..ac6be38966 --- /dev/null +++ b/packages/addons/addon-depends/cxxtools/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="cxxtools" +PKG_VERSION="3.0" +PKG_SHA256="07b18037fb0983f6292f5c8d53e2369e9e7a9711df2c9ad50838aacbc8c62f7c" +PKG_LICENSE="GPL-2" +PKG_SITE="http://www.tntnet.org/cxxtools.html" +PKG_URL="http://www.tntnet.org/download/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="toolchain:host openssl:host" +PKG_DEPENDS_TARGET="toolchain cxxtools:host openssl" +PKG_LONGDESC="Cxxtools is a collection of general-purpose C++ classes." +PKG_BUILD_FLAGS="+pic" + +PKG_CONFIGURE_OPTS_HOST="--disable-demos --disable-unittest" +PKG_CONFIGURE_OPTS_TARGET="--enable-static --disable-shared --disable-demos --disable-unittest" + +post_makeinstall_host() { + rm -rf ${TOOLCHAIN}/bin/cxxtools-config +} + +post_makeinstall_target() { + 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 + + rm -rf ${INSTALL}/usr/bin +} diff --git a/packages/addons/addon-depends/docker/cli/package.mk b/packages/addons/addon-depends/docker/cli/package.mk new file mode 100644 index 0000000000..c63c513462 --- /dev/null +++ b/packages/addons/addon-depends/docker/cli/package.mk @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="cli" +PKG_VERSION="$(get_pkg_version moby)" +PKG_SHA256="ef6808574ea7a4d02ec9715feb8fea419f253fb5b9f68a98020a9e39680baf35" +PKG_LICENSE="ASL" +PKG_SITE="https://github.com/docker/cli" +PKG_URL="https://github.com/docker/cli/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain go:host" +PKG_LONGDESC="The Docker CLI" +PKG_TOOLCHAIN="manual" + +# Git commit of the matching tag https://github.com/docker/cli/tags +export PKG_GIT_COMMIT="38b7060a218775811da953650d8df7d492653f8f" + +configure_target() { + go_configure + + export LDFLAGS="-w -linkmode external -extldflags -Wl,--unresolved-symbols=ignore-in-shared-libs -extld ${CC}" + + # used for docker version + export GITCOMMIT=${PKG_GIT_COMMIT} + export VERSION=${PKG_VERSION} + export BUILDTIME="$(date --utc)" + + cat >"${PKG_BUILD}/go.mod" <"${PKG_BUILD}/go.mod" <${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/addons/addon-depends/libmpdclient/package.mk b/packages/addons/addon-depends/libmpdclient/package.mk new file mode 100644 index 0000000000..f92a1337c0 --- /dev/null +++ b/packages/addons/addon-depends/libmpdclient/package.mk @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libmpdclient" +PKG_VERSION="2.23" +PKG_SHA256="4a1b6c7f783d8cac3d3b8e4cbe9ad021c45491e383de3b893ea4eedefbc71607" +PKG_LICENSE="BSD-3c" +PKG_SITE="https://www.musicpd.org" +PKG_URL="https://www.musicpd.org/download/libmpdclient/2/libmpdclient-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A C library which implements the Music Player Daemon protocol." diff --git a/packages/addons/addon-depends/librepfunc/package.mk b/packages/addons/addon-depends/librepfunc/package.mk new file mode 100644 index 0000000000..81e18fdb83 --- /dev/null +++ b/packages/addons/addon-depends/librepfunc/package.mk @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2023-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="librepfunc" +PKG_VERSION="1.10.0" +PKG_SHA256="cf44d9c2e70b06318eda5a6f9e0449f70d1ac71de577c3cc92f513893952a896" +PKG_LICENSE="GPL-2.0" +PKG_SITE="https://github.com/wirbel-at-vdr-portal/librepfunc" +PKG_URL="https://github.com/wirbel-at-vdr-portal/librepfunc/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="librepfunc - a collection of functions, classes used by wirbel-at-vdr-portal" +PKG_BUILD_FLAGS="-sysroot" + +pre_configure_target() { + sed -i -e 's/^install:/install-shared:/' -e 's/^install-static:/install:/' Makefile +} diff --git a/packages/addons/addon-depends/libusbmuxd/package.mk b/packages/addons/addon-depends/libusbmuxd/package.mk new file mode 100644 index 0000000000..f380ff1dca --- /dev/null +++ b/packages/addons/addon-depends/libusbmuxd/package.mk @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libusbmuxd" +PKG_VERSION="2.1.1" +PKG_SHA256="bcc185615a0f4ba80b617696235a084c64b68a1bf546a1dedd85da6b62b8cfbe" +PKG_LICENSE="GPL" +PKG_SITE="http://www.libimobiledevice.org" +PKG_URL="https://github.com/libimobiledevice/libusbmuxd/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain libimobiledevice-glue libplist" +PKG_LONGDESC="A USB multiplex daemon." +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="ac_cv_func_malloc_0_nonnull=yes \ + ac_cv_func_realloc_0_nonnull=yes \ + --enable-static \ + --disable-shared" + +configure_package() { + # if using a git hash as a package version - set RELEASE_VERSION + if [ -f ${PKG_BUILD}/NEWS ]; then + export RELEASE_VERSION="$(sed -n '1,/RE/s/Version \(.*\)/\1/p' ${PKG_BUILD}/NEWS)-git-${PKG_VERSION:0:7}" + fi +} + +post_configure_target() { + libtool_remove_rpath libtool +} diff --git a/packages/addons/addon-depends/libvncserver/package.mk b/packages/addons/addon-depends/libvncserver/package.mk new file mode 100644 index 0000000000..9ed2a8dc6a --- /dev/null +++ b/packages/addons/addon-depends/libvncserver/package.mk @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libvncserver" +PKG_VERSION="0.9.15" +PKG_SHA256="62352c7795e231dfce044beb96156065a05a05c974e5de9e023d688d8ff675d7" +PKG_LICENSE="GPL" +PKG_SITE="https://libvnc.github.io/" +PKG_URL="https://github.com/LibVNC/libvncserver/archive/LibVNCServer-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain libjpeg-turbo libpng openssl systemd" +PKG_LONGDESC="A C library that allow you to easily implement VNC server or client functionality." + +PKG_CMAKE_OPTS_TARGET="-DWITH_GCRYPT=0 \ + -DWITH_GNUTLS=0 \ + -DWITH_GTK=0 \ + -DWITH_SDL=0 \ + -DWITH_TIGHTVNC_FILETRANSFER=0 \ + -DWITH_EXAMPLES=OFF \ + -DWITH_TESTS=OFF \ + -DWITH_QT=OFF" diff --git a/packages/addons/addon-depends/libvpx/package.mk b/packages/addons/addon-depends/libvpx/package.mk new file mode 100644 index 0000000000..56820535d9 --- /dev/null +++ b/packages/addons/addon-depends/libvpx/package.mk @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libvpx" +PKG_VERSION="1.15.2" +PKG_SHA256="26fcd3db88045dee380e581862a6ef106f49b74b6396ee95c2993a260b4636aa" +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" + +if [ "${TARGET_ARCH}" = "x86_64" ]; then + PKG_DEPENDS_TARGET+=" nasm:host" +fi + +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/addons/addon-depends/libzip/package.mk b/packages/addons/addon-depends/libzip/package.mk new file mode 100644 index 0000000000..c6782c7288 --- /dev/null +++ b/packages/addons/addon-depends/libzip/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="libzip" +PKG_VERSION="1.11.4" +PKG_SHA256="8a247f57d1e3e6f6d11413b12a6f28a9d388de110adc0ec608d893180ed7097b" +PKG_LICENSE="GPL" +PKG_SITE="https://libzip.org/" +PKG_URL="https://libzip.org/download/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain zlib bzip2" +PKG_LONGDESC="A C library for reading, creating, and modifying zip archives." + +PKG_CMAKE_OPTS_TARGET="-DENABLE_COMMONCRYPTO=OFF \ + -DENABLE_GNUTLS=OFF \ + -DENABLE_MBEDTLS=OFF \ + -DENABLE_OPENSSL=OFF \ + -DENABLE_WINDOWS_CRYPTO=OFF \ + -DENABLE_ZSTD=OFF \ + -DBUILD_TOOLS=OFF \ + -DBUILD_REGRESS=OFF \ + -DBUILD_EXAMPLES=OFF \ + -DBUILD_DOC=OFF \ + -DBUILD_SHARED_LIBS=OFF" + +post_makeinstall_target() { + rm -rf ${INSTALL}/usr/lib +} diff --git a/packages/addons/addon-depends/mpd-mpc/package.mk b/packages/addons/addon-depends/mpd-mpc/package.mk new file mode 100644 index 0000000000..3c4cde2b0c --- /dev/null +++ b/packages/addons/addon-depends/mpd-mpc/package.mk @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="mpd-mpc" +PKG_VERSION="0.35" +PKG_SHA256="382959c3bfa2765b5346232438650491b822a16607ff5699178aa1386e3878d4" +PKG_LICENSE="GPL" +PKG_SITE="https://www.musicpd.org" +PKG_URL="https://www.musicpd.org/download/mpc/0/mpc-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain libiconv libmpdclient" +PKG_LONGDESC="Command-line client for MPD." +PKG_BUILD_FLAGS="-sysroot" diff --git a/packages/addons/addon-depends/multimedia-tools-depends/depends/libmediainfo/package.mk b/packages/addons/addon-depends/multimedia-tools-depends/depends/libmediainfo/package.mk new file mode 100644 index 0000000000..08683c7d46 --- /dev/null +++ b/packages/addons/addon-depends/multimedia-tools-depends/depends/libmediainfo/package.mk @@ -0,0 +1,43 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libmediainfo" +PKG_VERSION="25.04" +PKG_SHA256="ad45ed7c9db7807aa803845ca88bad9526aa8da883a58127e5390aaa2d81bbb1" +PKG_LICENSE="GPL" +PKG_SITE="https://mediaarea.net/en/MediaInfo/Download/Source" +PKG_URL="https://mediaarea.net/download/source/libmediainfo/${PKG_VERSION}/libmediainfo_${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain libzen zlib" +PKG_DEPENDS_CONFIG="libzen" +PKG_LONGDESC="MediaInfo is a convenient unified display of the most relevant technical and tag data for video and audio files" +PKG_TOOLCHAIN="manual" +PKG_BUILD_FLAGS="-sysroot" + +configure_target() { + cd Project/GNU/Library + do_autoreconf + ./configure \ + --host=${TARGET_NAME} \ + --build=${HOST_NAME} \ + --enable-static \ + --enable-shared \ + --prefix=/usr \ + --enable-visibility +} + +make_target() { + make +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/include/MediaInfo ${INSTALL}/usr/lib/pkgconfig + cp -aP ../../../Source/MediaInfo/*.h ${INSTALL}/usr/include/MediaInfo + for i in Archive Audio Duplicate Export Image Multiple Reader Tag Text Video; do + mkdir -p ${INSTALL}/usr/include/MediaInfo/${i}/ + cp -aP ../../../Source/MediaInfo/${i}/*.h ${INSTALL}/usr/include/MediaInfo/${i}/ + done + + # only install static library, so mediainfo does not build with shared library + cp -P .libs/libmediainfo.a ${INSTALL}/usr/lib + cp -P libmediainfo.pc ${INSTALL}/usr/lib/pkgconfig +} diff --git a/packages/addons/addon-depends/multimedia-tools-depends/depends/libzen/package.mk b/packages/addons/addon-depends/multimedia-tools-depends/depends/libzen/package.mk new file mode 100644 index 0000000000..bb354ad42e --- /dev/null +++ b/packages/addons/addon-depends/multimedia-tools-depends/depends/libzen/package.mk @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libzen" +PKG_VERSION="0.4.41" +PKG_SHA256="933bad3b7ecd29dc6bdc88a83645c83dfd098c15b0b90d6177a37fa1536704e8" +PKG_LICENSE="GPL" +PKG_SITE="https://mediaarea.net/en/MediaInfo/" +PKG_URL="https://mediaarea.net/download/source/libzen/${PKG_VERSION}/libzen_${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="MediaInfo is a convenient unified display of the most relevant technical and tag data for video and audio files" +PKG_TOOLCHAIN="manual" +PKG_BUILD_FLAGS="-sysroot" + +configure_target() { + cd Project/GNU/Library + do_autoreconf + ./configure \ + --host=${TARGET_NAME} \ + --build=${HOST_NAME} \ + --enable-static \ + --disable-shared \ + --prefix=/usr +} + +make_target() { + make +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/include/ZenLib ${INSTALL}/usr/lib/pkgconfig + cp -aP ../../../Source/ZenLib/*.h ${INSTALL}/usr/include/ZenLib + for i in HTTP_Client Format/Html Format/Http; do + mkdir -p ${INSTALL}/usr/include/ZenLib/${i}/ + cp -aP ../../../Source/ZenLib/${i}/*.h ${INSTALL}/usr/include/ZenLib/${i}/ + done + cp -P .libs/* ${INSTALL}/usr/lib + cp -P libzen.pc ${INSTALL}/usr/lib/pkgconfig +} diff --git a/packages/addons/addon-depends/multimedia-tools-depends/libplacebo/package.mk b/packages/addons/addon-depends/multimedia-tools-depends/libplacebo/package.mk new file mode 100644 index 0000000000..1dc9d4cc9c --- /dev/null +++ b/packages/addons/addon-depends/multimedia-tools-depends/libplacebo/package.mk @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2023-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libplacebo" +PKG_VERSION="7.351.0" +PKG_SHA256="716954501d9b76e6906fddda66febc5886493d0673dd265ec1e6e52f4e5cd7c6" +PKG_LICENSE="LGPLv2.1" +PKG_SITE="https://code.videolan.org/videolan/libplacebo" +PKG_URL="https://github.com/haasn/libplacebo/archive/refs/tags/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain glad:host" +PKG_DEPENDS_UNPACK="vulkan-headers" +PKG_LONGDESC="Reusable library for GPU-accelerated image/video processing primitives and shaders" +PKG_BUILD_FLAGS="-sysroot" + +PKG_MESON_OPTS_TARGET="-Ddefault_library=static \ + -Dprefer_static=true \ + -Dvulkan=disabled \ + -Dvk-proc-addr=disabled \ + -Dd3d11=disabled \ + -Dglslang=disabled \ + -Dshaderc=disabled \ + -Dlcms=disabled \ + -Ddovi=disabled \ + -Dlibdovi=disabled \ + -Ddemos=false" + +if [ "${OPENGL_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL}" + PKG_MESON_OPTS_TARGET+=" -Dopengl=enabled -Dgl-proc-addr=enabled" +else + PKG_MESON_OPTS_TARGET+=" -Dopengl=disabled -Dgl-proc-addr=disabled" +fi + +pre_configure_target() { + export TARGET_CFLAGS+=" -I$(get_build_dir vulkan-headers)/include" +} + +post_makeinstall_target() { + sed 's/^Libs:.*-lplacebo/& -lstdc++/' -i ${INSTALL}/usr/lib/pkgconfig/libplacebo.pc +} diff --git a/packages/addons/addon-depends/multimedia-tools-depends/mediainfo/package.mk b/packages/addons/addon-depends/multimedia-tools-depends/mediainfo/package.mk new file mode 100644 index 0000000000..f1b7f5dc18 --- /dev/null +++ b/packages/addons/addon-depends/multimedia-tools-depends/mediainfo/package.mk @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="mediainfo" +PKG_VERSION="25.04" +PKG_SHA256="4b2553fe9104332d3baca5fe61b6b87af4d493108c5b863801cdb0a4826a33ae" +PKG_LICENSE="GPL" +PKG_SITE="https://mediaarea.net/en/MediaInfo/Download/Source" +PKG_URL="https://mediaarea.net/download/source/mediainfo/${PKG_VERSION}/mediainfo_${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain libmediainfo" +PKG_DEPENDS_CONFIG="libzen libmediainfo" +PKG_LONGDESC="A convenient unified display of the most relevant technical and tag data for video and audio files." +PKG_TOOLCHAIN="manual" +PKG_BUILD_FLAGS="-sysroot" + +configure_target() { + cd Project/GNU/CLI + do_autoreconf + ./configure \ + --host=${TARGET_NAME} \ + --build=${HOST_NAME} \ + --prefix=/usr +} + +make_target() { + make +} + +makeinstall_target() { + make install DESTDIR=${INSTALL} +} diff --git a/packages/addons/addon-depends/multimedia-tools-depends/mesa-demos/package.mk b/packages/addons/addon-depends/multimedia-tools-depends/mesa-demos/package.mk new file mode 100644 index 0000000000..660469c900 --- /dev/null +++ b/packages/addons/addon-depends/multimedia-tools-depends/mesa-demos/package.mk @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="mesa-demos" +PKG_VERSION="9.0.0" +PKG_SHA256="3046a3d26a7b051af7ebdd257a5f23bfeb160cad6ed952329cdff1e9f1ed496b" +PKG_ARCH="x86_64" +PKG_LICENSE="OSS" +PKG_SITE="https://www.mesa3d.org/" +PKG_URL="https://archive.mesa3d.org/demos/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain libX11 mesa glu glew" +PKG_LONGDESC="Mesa 3D demos - installed are the well known glxinfo and glxgears." +PKG_BUILD_FLAGS="-sysroot" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp -P src/xdemos/glxdemo ${INSTALL}/usr/bin + cp -P src/xdemos/glxgears ${INSTALL}/usr/bin + cp -P src/xdemos/glxinfo ${INSTALL}/usr/bin +} diff --git a/packages/addons/addon-depends/multimedia-tools-depends/mpg123/package.mk b/packages/addons/addon-depends/multimedia-tools-depends/mpg123/package.mk new file mode 100644 index 0000000000..cc8346ffaf --- /dev/null +++ b/packages/addons/addon-depends/multimedia-tools-depends/mpg123/package.mk @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="mpg123" +PKG_VERSION="1.33.0" +PKG_SHA256="2290e3aede6f4d163e1a17452165af33caad4b5f0948f99429cfa2d8385faa9d" +PKG_LICENSE="LGPLv2" +PKG_SITE="https://www.mpg123.org/" +PKG_URL="https://downloads.sourceforge.net/sourceforge/mpg123/mpg123-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain alsa-lib" +PKG_LONGDESC="A console based real time MPEG Audio Player for Layer 1, 2 and 3." +PKG_BUILD_FLAGS="-sysroot +pic" + +PKG_CONFIGURE_OPTS_TARGET="--disable-shared \ + --enable-static" diff --git a/packages/addons/addon-depends/multimedia-tools-depends/mpv-drmprime/package.mk b/packages/addons/addon-depends/multimedia-tools-depends/mpv-drmprime/package.mk new file mode 100644 index 0000000000..6460610668 --- /dev/null +++ b/packages/addons/addon-depends/multimedia-tools-depends/mpv-drmprime/package.mk @@ -0,0 +1,63 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="mpv-drmprime" +PKG_VERSION="0.40.0" +PKG_SHA256="10a0f4654f62140a6dd4d380dcf0bbdbdcf6e697556863dc499c296182f081a3" +PKG_LICENSE="GPL" +PKG_SITE="https://mpv.io/" +PKG_URL="https://github.com/mpv-player/mpv/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain alsa ffmpeg libass libdrm libplacebo lua52" +PKG_LONGDESC="A media player based on MPlayer and mplayer2. It supports a wide variety of video file formats, audio and video codecs, and subtitle types." +PKG_BUILD_FLAGS="-sysroot" + +PKG_MESON_OPTS_TARGET="--prefix=/usr \ + -Dlibarchive=disabled \ + -Dlua=enabled \ + -Djavascript=disabled \ + -Duchardet=disabled \ + -Drubberband=disabled \ + -Dlcms2=disabled \ + -Dvapoursynth=disabled \ + -Djack=disabled \ + -Dwayland=disabled \ + -Dx11=disabled \ + -Dvulkan=disabled \ + -Dcaca=disabled \ + -Ddrm=enabled \ + -Dgbm=enabled \ + -Degl-drm=enabled \ + -Dmanpage-build=disabled" + +if [ "${OPENGLES_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" +fi + +if [ "${OPENGL_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL}" +fi + +if [ "${VAAPI_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" libva" + PKG_MESON_OPTS_TARGET+=" -Dvaapi=enabled -Dvaapi-drm=enabled" +else + PKG_MESON_OPTS_TARGET+=" -Dvaapi=disabled" +fi + +if [ "${PULSEAUDIO_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" pulseaudio" + PKG_MESON_OPTS_TARGET+=" -Dpulse=enabled" +else + PKG_MESON_OPTS_TARGET+=" -Dpulse=disabled" +fi + +if [ "${KODI_BLURAY_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" libbluray" + PKG_MESON_OPTS_TARGET+=" -Dlibbluray=enabled" +else + PKG_MESON_OPTS_TARGET+=" -Dlibbluray=disabled" +fi + +pre_configure_target() { + export PKG_CONFIG_PATH="$(get_install_dir libplacebo)/usr/lib/pkgconfig:${PKG_CONFIG_PATH}" +} diff --git a/packages/addons/addon-depends/multimedia-tools-depends/opencaster/package.mk b/packages/addons/addon-depends/multimedia-tools-depends/opencaster/package.mk new file mode 100644 index 0000000000..d50e3ede8c --- /dev/null +++ b/packages/addons/addon-depends/multimedia-tools-depends/opencaster/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="opencaster" +PKG_VERSION="3.2.2" +PKG_SHA256="c9d77f98b31d53f521e3179003a9cb66b0586704717e9d401f3bc0dafa243865" +PKG_LICENSE="GPL" +PKG_SITE="http://www.avalpa.com/the-key-values/15-free-software/33-opencaster" +PKG_URL="http://ftp.de.debian.org/debian/pool/main/o/opencaster/opencaster_${PKG_VERSION}+dfsg.orig.tar.gz" +PKG_DEPENDS_TARGET="toolchain zlib" +PKG_LONGDESC="A free and open source MPEG2 transport stream data generator and packet manipulator." +PKG_BUILD_FLAGS="-sysroot" + +pre_configure_target() { + PKG_MAKE_OPTS_TARGET="CC=${CC}" +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + make install DESTDIR=${INSTALL}/usr/bin +} diff --git a/packages/addons/addon-depends/multimedia-tools-depends/squeezelite/package.mk b/packages/addons/addon-depends/multimedia-tools-depends/squeezelite/package.mk new file mode 100644 index 0000000000..a152b8c66b --- /dev/null +++ b/packages/addons/addon-depends/multimedia-tools-depends/squeezelite/package.mk @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="squeezelite" +PKG_VERSION="0e5514efcb6366b74d7144626f1e9b4da7e81bf8" +PKG_SHA256="9d17b46aa3eee53141549758e874d259d8b20a0120d57a395b6a3ad8da5a1dae" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/ralph-irving/squeezelite" +PKG_URL="https://github.com/ralph-irving/squeezelite/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain faad2 ffmpeg flac libmad libvorbis mpg123 soxr libogg" +PKG_DEPENDS_CONFIG="mpg123" +PKG_LONGDESC="A client for the Lyrion Music Server." +PKG_BUILD_FLAGS="-sysroot" + +make_target() { + make \ + OPTS="-DDSD -DFFMPEG -DRESAMPLE -DVISEXPORT -DLINKALL" \ + CFLAGS="${CFLAGS} $(pkg-config --cflags libmpg123 vorbisfile vorbis ogg)" \ + LDFLAGS+=" $(pkg-config --libs libmpg123 vorbisfile vorbis ogg)" +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp -p squeezelite ${INSTALL}/usr/bin +} diff --git a/packages/addons/addon-depends/multimedia-tools-depends/tsdecrypt/package.mk b/packages/addons/addon-depends/multimedia-tools-depends/tsdecrypt/package.mk new file mode 100644 index 0000000000..db5e0a0689 --- /dev/null +++ b/packages/addons/addon-depends/multimedia-tools-depends/tsdecrypt/package.mk @@ -0,0 +1,23 @@ +# 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="tsdecrypt" +PKG_VERSION="10.0" +PKG_SHA256="a337a7d60cc8f78b9dffbd7d675390497763bcb8f878ec9f1bec3eb80f32b1f1" +PKG_LICENSE="GPL" +PKG_SITE="http://georgi.unixsol.org/programs/tsdecrypt" +PKG_URL="http://georgi.unixsol.org/programs/tsdecrypt/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain libdvbcsa openssl" +PKG_LONGDESC="A tool that reads incoming mpeg transport stream over UDP/RTP and then decrypts it using libdvbcsa/ffdecsa." +PKG_BUILD_FLAGS="-sysroot" + +PKG_MAKEINSTALL_OPTS_TARGET="PREFIX=/usr" + +make_target() { + make CC=${CC} LINK="${LD} -o" +} + +post_make_target() { + make strip STRIP=${STRIP} +} diff --git a/packages/addons/addon-depends/multimedia-tools-depends/tstools/package.mk b/packages/addons/addon-depends/multimedia-tools-depends/tstools/package.mk new file mode 100644 index 0000000000..aeca8cbc92 --- /dev/null +++ b/packages/addons/addon-depends/multimedia-tools-depends/tstools/package.mk @@ -0,0 +1,20 @@ +# 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="tstools" +PKG_VERSION="db1f79f409818fa0476ecf8593079a7ca3dbafd2" +PKG_SHA256="f204229016c9deafcc75fe602c390339878312126134edbfcebf239e093dc4ff" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/kynesim/tstools" +PKG_URL="https://github.com/kynesim/tstools/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="This is a set of cross-platform command line tools for working with MPEG data." +PKG_BUILD_FLAGS="-sysroot" + +PKG_MAKE_OPTS_TARGET="CROSS_COMPILE=${TARGET_PREFIX} prefix=/usr" +PKG_MAKEINSTALL_OPTS_TARGET="${PKG_MAKE_OPTS_TARGET}" + +pre_make_target() { + make builddirs +} diff --git a/packages/addons/addon-depends/network-tools-depends/bwm-ng/package.mk b/packages/addons/addon-depends/network-tools-depends/bwm-ng/package.mk new file mode 100644 index 0000000000..61a39ad62e --- /dev/null +++ b/packages/addons/addon-depends/network-tools-depends/bwm-ng/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="bwm-ng" +PKG_VERSION="0.6.3" +PKG_SHA256="c1a552b6ff48ea3e4e10110a7c188861abc4750befc67c6caaba8eb3ecf67f46" +PKG_LICENSE="GPL" +PKG_SITE="http://www.gropp.org/?id=projects&sub=bwm-ng" +PKG_URL="https://github.com/vgropp/bwm-ng/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain ncurses libstatgrab" +PKG_LONGDESC="A small and simple console-based live network and disk io bandwidth monitor." +PKG_TOOLCHAIN="autotools" +PKG_BUILD_FLAGS="-sysroot -cfg-libs" + +PKG_CONFIGURE_OPTS_TARGET="--with-libstatgrab \ + --with-time \ + --with-getifaddrs \ + --with-sysctl \ + --with-sysctldisk \ + --with-procnetdev \ + --with-partitions" diff --git a/packages/addons/addon-depends/network-tools-depends/depends/libpcap/package.mk b/packages/addons/addon-depends/network-tools-depends/depends/libpcap/package.mk new file mode 100644 index 0000000000..673ad4e4fc --- /dev/null +++ b/packages/addons/addon-depends/network-tools-depends/depends/libpcap/package.mk @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libpcap" +PKG_VERSION="1.10.5" +PKG_SHA256="37ced90a19a302a7f32e458224a00c365c117905c2cd35ac544b6880a81488f0" +PKG_LICENSE="GPL" +PKG_SITE="https://www.tcpdump.org/" +PKG_URL="https://www.tcpdump.org/release/libpcap-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A portable framework for low-level network monitoring." +# use configure, not cmake. review cmake in future release. +PKG_TOOLCHAIN="configure" +PKG_BUILD_FLAGS="-cfg-libs" + +PKG_CONFIGURE_OPTS_TARGET="LIBS=-lpthread \ + ac_cv_header_libusb_1_0_libusb_h=no \ + --disable-shared \ + --with-pcap=linux \ + --disable-bluetooth \ + --without-libnl \ + --disable-dbus" + +pre_configure_target() { + # When cross-compiling, configure can't set linux version + # forcing it + sed -i -e 's/ac_cv_linux_vers=unknown/ac_cv_linux_vers=2/' ../configure +} + +post_makeinstall_target() { + rm -rf ${INSTALL}/usr/bin +} diff --git a/packages/addons/addon-depends/network-tools-depends/depends/libstatgrab/package.mk b/packages/addons/addon-depends/network-tools-depends/depends/libstatgrab/package.mk new file mode 100644 index 0000000000..83ebca1bc3 --- /dev/null +++ b/packages/addons/addon-depends/network-tools-depends/depends/libstatgrab/package.mk @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libstatgrab" +PKG_VERSION="0.92.1" +PKG_SHA256="5688aa4a685547d7174a8a373ea9d8ee927e766e3cc302bdee34523c2c5d6c11" +PKG_SITE="https://libstatgrab.org" +PKG_URL="https://github.com/libstatgrab/libstatgrab/releases/download/LIBSTATGRAB_${PKG_VERSION//./_}/libstatgrab-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_SECTION=libs +PKG_LONGDESC="A library that provides cross platform access to statistics about the system on which it's run." +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="ac_cv_func_malloc_0_nonnull=yes \ + --enable-static \ + --disable-shared \ + --disable-saidar \ + --disable-examples \ + --disable-setuid-binaries \ + --disable-setgid-binaries" diff --git a/packages/addons/addon-depends/network-tools-depends/iftop/package.mk b/packages/addons/addon-depends/network-tools-depends/iftop/package.mk new file mode 100644 index 0000000000..485d4c5598 --- /dev/null +++ b/packages/addons/addon-depends/network-tools-depends/iftop/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="iftop" +PKG_VERSION="75d1818129cbb8ff1bb7ca4915b95046f3ed0666" +PKG_SHA256="a4b507ba5ad1ec3e41263bee38f202267644adc05d150322f0d8f85c3e2d3f43" +PKG_LICENSE="GPL" +PKG_SITE="http://www.ex-parrot.com/pdw/iftop/" +PKG_URL="https://code.blinkace.com/pdw/iftop/-/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain ncurses libpcap libnl" +PKG_LONGDESC="A tool to display bandwidth usage on an interface." +PKG_TOOLCHAIN="autotools" +PKG_BUILD_FLAGS="-sysroot -cfg-libs" + +pre_build_target() { + mkdir -p ${PKG_BUILD}/.${TARGET_NAME} + cp -RP ${PKG_BUILD}/* ${PKG_BUILD}/.${TARGET_NAME} +} + +pre_configure_target() { + export LIBS="-lpcap -lnl-3 -lnl-genl-3 -lncurses" +} diff --git a/packages/addons/addon-depends/network-tools-depends/iperf/package.mk b/packages/addons/addon-depends/network-tools-depends/iperf/package.mk new file mode 100644 index 0000000000..14abf62cd5 --- /dev/null +++ b/packages/addons/addon-depends/network-tools-depends/iperf/package.mk @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="iperf" +PKG_VERSION="3.19" +PKG_SHA256="da5cff29e4945b2ee05dcf9a0c67768cc000dc1b122935bce3492c4e36f6b5e9" +PKG_LICENSE="BSD" +PKG_SITE="http://software.es.net/iperf/" +PKG_URL="https://github.com/esnet/iperf/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain openssl" +PKG_LONGDESC="A tool to measuring maximum TCP and UDP bandwidth performance." +PKG_TOOLCHAIN="autotools" +PKG_BUILD_FLAGS="-sysroot" + +PKG_CONFIGURE_OPTS_TARGET="--enable-static \ + --disable-shared" diff --git a/packages/addons/addon-depends/network-tools-depends/irssi/package.mk b/packages/addons/addon-depends/network-tools-depends/irssi/package.mk new file mode 100644 index 0000000000..feada76590 --- /dev/null +++ b/packages/addons/addon-depends/network-tools-depends/irssi/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="irssi" +PKG_VERSION="1.4.5" +PKG_SHA256="72a951cb0ad622785a8962801f005a3a412736c7e7e3ce152f176287c52fe062" +PKG_LICENSE="GPL" +PKG_SITE="http://www.irssi.org/" +PKG_URL="https://github.com/irssi/irssi/releases/download/${PKG_VERSION}/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain glib ncurses openssl" +PKG_LONGDESC="Irssi is a terminal based IRC client for UNIX systems." +PKG_BUILD_FLAGS="-sysroot" + +PKG_MESON_OPTS_TARGET="-Dwithout-textui=no \ + -Dwith-bot=no \ + -Dwith-proxy=no \ + -Dwith-perl=no" diff --git a/packages/addons/addon-depends/network-tools-depends/lftp/package.mk b/packages/addons/addon-depends/network-tools-depends/lftp/package.mk new file mode 100644 index 0000000000..1ca0168c4c --- /dev/null +++ b/packages/addons/addon-depends/network-tools-depends/lftp/package.mk @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="lftp" +PKG_VERSION="4.9.2" +PKG_SHA256="c517c4f4f9c39bd415d7313088a2b1e313b2d386867fe40b7692b83a20f0670d" +PKG_LICENSE="GPLv3" +PKG_SITE="http://lftp.yar.ru/" +PKG_URL="http://lftp.yar.ru/ftp/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain readline openssl zlib libidn2" +PKG_LONGDESC="A sophisticated ftp/http client, and a file transfer program supporting a number of network protocols." +PKG_BUILD_FLAGS="-sysroot" + +PKG_CONFIGURE_OPTS_TARGET="--disable-nls \ + --disable-rpath \ + --without-gnutls \ + --with-openssl \ + --with-readline=${SYSROOT_PREFIX}/usr \ + --with-zlib=${SYSROOT_PREFIX}/usr" + +post_configure_target() { + libtool_remove_rpath libtool +} diff --git a/packages/addons/addon-depends/network-tools-depends/ncftp/package.mk b/packages/addons/addon-depends/network-tools-depends/ncftp/package.mk new file mode 100644 index 0000000000..a35874f5d4 --- /dev/null +++ b/packages/addons/addon-depends/network-tools-depends/ncftp/package.mk @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="ncftp" +PKG_VERSION="3.3.0" +PKG_SHA256="7920f884c2adafc82c8e41c46d6f3d22698785c7b3f56f5677a8d5c866396386" +PKG_LICENSE="GPLv3" +PKG_SITE="http://www.ncftp.com/ncftp/" +PKG_URL="https://www.ncftp.com/public_ftp/ncftp/ncftp-${PKG_VERSION}-src.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="NcFTP is a set of application programs implementing the File Transfer Protocol." +PKG_BUILD_FLAGS="-sysroot" + +PKG_CONFIGURE_OPTS_TARGET="ac_cv_header_librtmp_rtmp_h=yes \ + --enable-readline \ + --disable-universal \ + --disable-ccdv \ + --without-curses" + +pre_configure_target() { + export CFLAGS="${CFLAGS} -I../" +} + +pre_build_target() { + mkdir -p ${PKG_BUILD}/.${TARGET_NAME} + cp -RP ${PKG_BUILD}/* ${PKG_BUILD}/.${TARGET_NAME} +} diff --git a/packages/addons/addon-depends/network-tools-depends/ngrep/package.mk b/packages/addons/addon-depends/network-tools-depends/ngrep/package.mk new file mode 100644 index 0000000000..44a38ae85e --- /dev/null +++ b/packages/addons/addon-depends/network-tools-depends/ngrep/package.mk @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="ngrep" +PKG_VERSION="b2e3ba3c5a593abf203e65a407c3a9de0f998d4a" +PKG_SHA256="daeb3e0473120541ebfa0d16b9cf4829d797d04cf30348d6c02b9b9a37fc9f05" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/jpr5/ngrep" +PKG_URL="https://github.com/jpr5/ngrep/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain libpcap pcre2" +PKG_LONGDESC="A tool like GNU grep applied to the network layer." +PKG_TOOLCHAIN="autotools" +PKG_BUILD_FLAGS="-sysroot -parallel -cfg-libs" + +PKG_CONFIGURE_OPTS_TARGET="--with-pcap-includes=${SYSROOT_PREFIX}/usr/include \ + --enable-ipv6 \ + --enable-pcre2 \ + --disable-dropprivs" + +pre_build_target() { + mkdir -p ${PKG_BUILD}/.${TARGET_NAME} + cp -RP ${PKG_BUILD}/* ${PKG_BUILD}/.${TARGET_NAME} +} diff --git a/packages/addons/addon-depends/network-tools-depends/nmap/package.mk b/packages/addons/addon-depends/network-tools-depends/nmap/package.mk new file mode 100644 index 0000000000..1e796bcf43 --- /dev/null +++ b/packages/addons/addon-depends/network-tools-depends/nmap/package.mk @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="nmap" +PKG_VERSION="7.97" +PKG_SHA256="af98f27925c670c257dd96a9ddf2724e06cb79b2fd1e0d08c9206316be1645c0" +PKG_LICENSE="GPL" +PKG_SITE="https://nmap.org/" +PKG_URL="https://nmap.org/dist/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain openssl dbus libnl" +PKG_LONGDESC="Free Security Scanned for Network." +PKG_BUILD_FLAGS="-sysroot" + +PKG_CONFIGURE_OPTS_TARGET="--enable-static \ + --with-pcap=linux \ + --with-libpcap=included \ + --with-libpcre=included \ + --with-libdnet=included \ + --with-liblua=included \ + --with-liblinear=included \ + --with-openssl=${SYSROOT_PREFIX} \ + --with-ndiff=no \ + --with-zenmap=no" + +pre_configure_target() { + # nmap fails to build in subdirs + cd ${PKG_BUILD} + rm -rf .${TARGET_NAME} + + export CPPFLAGS="${CPPFLAGS} -Iliblua" + export LIBS="${LIBS} -ldbus-1 -lnl-3 -lnl-genl-3" +} diff --git a/packages/addons/addon-depends/network-tools-depends/rar2fs/package.mk b/packages/addons/addon-depends/network-tools-depends/rar2fs/package.mk new file mode 100644 index 0000000000..8ef78af5af --- /dev/null +++ b/packages/addons/addon-depends/network-tools-depends/rar2fs/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="rar2fs" +PKG_VERSION="1.29.7" +PKG_SHA256="a875d138b7ed7e3353b5de2f0c5ec02ef6a32c310fe3b07886bc95314d7875ba" +PKG_LICENSE="GPL3" +PKG_SITE="https://github.com/hasse69/rar2fs" +PKG_URL="https://github.com/hasse69/rar2fs/archive/refs/tags/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain fuse unrar" +PKG_LONGDESC="FUSE file system for reading RAR archives" +PKG_BUILD_FLAGS="-sysroot -cfg-libs" +PKG_TOOLCHAIN="autotools" + +pre_configure_target() { + PKG_CONFIGURE_OPTS_TARGET="--with-unrar=${PKG_BUILD}/unrar \ + --with-unrar-lib=${PKG_BUILD}/unrar \ + --disable-static-unrar" + cp -a $(get_install_dir unrar)/usr/include/unrar ${PKG_BUILD}/ + cp -p $(get_install_dir unrar)/usr/lib/libunrar.a ${PKG_BUILD}/unrar/ +} diff --git a/packages/addons/addon-depends/network-tools-depends/sshfs/package.mk b/packages/addons/addon-depends/network-tools-depends/sshfs/package.mk new file mode 100644 index 0000000000..9113c61691 --- /dev/null +++ b/packages/addons/addon-depends/network-tools-depends/sshfs/package.mk @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="sshfs" +PKG_VERSION="3.7.3" +PKG_SHA256="5218ce7bdd2ce0a34137a0d7798e0f6d09f0e6d21b1e98ee730a18b0699c2e99" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/libfuse/sshfs" +PKG_URL="https://github.com/libfuse/sshfs/releases/download/sshfs-${PKG_VERSION}/sshfs-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain fuse3 glib" +PKG_LONGDESC="A filesystem client based on the SSH File Transfer Protocol." +PKG_BUILD_FLAGS="-sysroot" diff --git a/packages/addons/addon-depends/network-tools-depends/tcpdump/package.mk b/packages/addons/addon-depends/network-tools-depends/tcpdump/package.mk new file mode 100644 index 0000000000..4b18224b07 --- /dev/null +++ b/packages/addons/addon-depends/network-tools-depends/tcpdump/package.mk @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="tcpdump" +PKG_VERSION="4.99.5" +PKG_SHA256="8c75856e00addeeadf70dad67c9ff3dd368536b2b8563abf6854d7c764cd3adb" +PKG_SITE="https://www.tcpdump.org/" +PKG_URL="https://www.tcpdump.org/release/tcpdump-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain libpcap libtirpc" +PKG_LONGDESC="A program that allows you to dump the traffic on a network." +PKG_BUILD_FLAGS="-sysroot -cfg-libs" +# use configure, not cmake. review cmake in future release. +PKG_TOOLCHAIN="configure" + +PKG_CONFIGURE_OPTS_TARGET="--with-crypto=no" + +pre_configure_target() { + # When cross-compiling, configure can't set linux version + # forcing it + sed -i -e 's/ac_cv_linux_vers=unknown/ac_cv_linux_vers=2/' ../configure + CFLAGS+=" -I${SYSROOT_PREFIX}/usr/include/tirpc" + LDFLAGS+=" -ltirpc" +} + +post_configure_target() { + # discard native system includes + sed -i "s%-I/usr/include%%g" Makefile +} diff --git a/packages/addons/addon-depends/network-tools-depends/udpxy/package.mk b/packages/addons/addon-depends/network-tools-depends/udpxy/package.mk new file mode 100644 index 0000000000..fc1555b8dd --- /dev/null +++ b/packages/addons/addon-depends/network-tools-depends/udpxy/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="udpxy" +PKG_VERSION="1.0-25.1" +PKG_SHA256="a1a16e60895c6b2fd151321db47f5d5373843116f1b98ed9749e6c25a6c44497" +PKG_LICENSE="GPLv3" +PKG_SITE="http://www.udpxy.com" +PKG_URL="https://github.com/pcherenkov/udpxy/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A UDP-to-HTTP multicast traffic relay daemon." +PKG_BUILD_FLAGS="-sysroot" + +PKG_MAKEINSTALL_OPTS_TARGET="PREFIX=/usr" + +post_unpack() { + mv ${PKG_BUILD}/README ${PKG_BUILD}/README- + mv ${PKG_BUILD}/chipmunk/* ${PKG_BUILD} + rmdir ${PKG_BUILD}/chipmunk +} + +configure_target() { + export CFLAGS+=" -Wno-stringop-truncation" +} diff --git a/packages/addons/addon-depends/network-tools-depends/wireless_tools/package.mk b/packages/addons/addon-depends/network-tools-depends/wireless_tools/package.mk new file mode 100644 index 0000000000..dce7f2138c --- /dev/null +++ b/packages/addons/addon-depends/network-tools-depends/wireless_tools/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="wireless_tools" +PKG_VERSION="30.pre9" +PKG_SHA256="abd9c5c98abf1fdd11892ac2f8a56737544fe101e1be27c6241a564948f34c63" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/HewlettPackard/wireless-tools" +PKG_URL="https://hewlettpackard.github.io/wireless-tools/${PKG_NAME}.${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="The Wireless Tools (WT) is a set of tools allowing to manipulate the Wireless Extensions." +PKG_BUILD_FLAGS="-sysroot" + +make_target() { + make PREFIX=/usr CC="${CC}" AR="${AR}" \ + CFLAGS="${CFLAGS}" CPPFLAGS="${CPPFLAGS}" iwmulticall +} + +makeinstall_target() { + make PREFIX=${INSTALL}/usr install-iwmulticall +} diff --git a/packages/addons/addon-depends/ntfs-3g_ntfsprogs/package.mk b/packages/addons/addon-depends/ntfs-3g_ntfsprogs/package.mk new file mode 100644 index 0000000000..6b99150b28 --- /dev/null +++ b/packages/addons/addon-depends/ntfs-3g_ntfsprogs/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="ntfs-3g_ntfsprogs" +PKG_VERSION="2022.10.3" +PKG_SHA256="f20e36ee68074b845e3629e6bced4706ad053804cbaf062fbae60738f854170c" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/tuxera/ntfs-3g" +PKG_URL="https://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 +speed -sysroot" + +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 \ + --disable-mount-helper" + diff --git a/packages/addons/addon-depends/pcsc-lite/package.mk b/packages/addons/addon-depends/pcsc-lite/package.mk new file mode 100644 index 0000000000..a5b22a4fe8 --- /dev/null +++ b/packages/addons/addon-depends/pcsc-lite/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="pcsc-lite" +PKG_VERSION="2.3.3" +PKG_SHA256="cdff7d7153a0b37aa74e26dfec89ec7dc5c5286aa21b91b903e38739d227e8e7" +PKG_LICENSE="GPL" +PKG_SITE="https://pcsclite.apdu.fr" +PKG_URL="https://pcsclite.apdu.fr/files/pcsc-lite-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain libusb polkit" +PKG_LONGDESC="Middleware to access a smart card using SCard API (PC/SC)." + +PKG_MESON_OPTS_TARGET="-Ddefault_library=static \ + -Dlibudev=false \ + -Dlibusb=true \ + -Dpolkit=true \ + -Dusbdropdir=/storage/.kodi/addons/service.pcscd/drivers" + +pre_configure_target() { + export PKG_CONFIG_PATH="$(get_install_dir polkit)/usr/lib/pkgconfig:${PKG_CONFIG_PATH}" +} diff --git a/packages/addons/addon-depends/pngquant/package.mk b/packages/addons/addon-depends/pngquant/package.mk new file mode 100644 index 0000000000..e92d89f636 --- /dev/null +++ b/packages/addons/addon-depends/pngquant/package.mk @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="pngquant" +PKG_VERSION="2.18.0" +PKG_SHA256="e72194b52b36f040deaec49a1ddd5dcd8d4feecc3a5fe6c5e9589a9707b233d4" +PKG_LICENSE="GPLv3" +PKG_SITE="https://pngquant.org" +PKG_URL="https://pngquant.org/pngquant-${PKG_VERSION}-src.tar.gz" +PKG_DEPENDS_HOST="toolchain:host libpng:host zlib:host" +PKG_LONGDESC="A lossy PNG compressor." + +configure_host() { + : +} + +make_host() { + cd ${PKG_BUILD} + BIN=${PKG_BUILD}/pngquant make + + ${STRIP} ${PKG_BUILD}/pngquant +} + +makeinstall_host() { + mkdir -p ${TOOLCHAIN}/bin + cp ${PKG_BUILD}/pngquant ${TOOLCHAIN}/bin +} diff --git a/packages/addons/addon-depends/podman/conmon/package.mk b/packages/addons/addon-depends/podman/conmon/package.mk new file mode 100644 index 0000000000..ca73fabf60 --- /dev/null +++ b/packages/addons/addon-depends/podman/conmon/package.mk @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2023-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="conmon" +PKG_VERSION="2.1.13" +PKG_SHA256="350992cb2fe4a69c0caddcade67be20462b21b4078dae00750e8da1774926d60" +PKG_LICENSE="Apache-2.0" +PKG_SITE="https://github.com/containers/conmon" +PKG_URL="https://github.com/containers/conmon/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain glib libseccomp systemd" +PKG_LONGDESC="An OCI container runtime monitor" + +# Git commit of the matching release https://github.com/containers/conmon +export PKG_GIT_COMMIT="82de887596ed8ee6d9b2ee85e4f167f307bb569b" + +pre_configure_target() { + export PKG_CONFIG_PATH="$(get_install_dir libseccomp)/usr/lib/pkgconfig:${PKG_CONFIG_PATH}" + export GIT_COMMIT=${PKG_GIT_COMMIT} +} diff --git a/packages/addons/addon-depends/podman/gpgme/package.mk b/packages/addons/addon-depends/podman/gpgme/package.mk new file mode 100644 index 0000000000..abe2b9b1e7 --- /dev/null +++ b/packages/addons/addon-depends/podman/gpgme/package.mk @@ -0,0 +1,30 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2023-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="gpgme" +PKG_VERSION="2.0.0" +PKG_SHA256="ddf161d3c41ff6a3fcbaf4be6c6e305ca4ef1cc3f1ecdfce0c8c2a167c0cc36d" +PKG_LICENSE="gpgme" +PKG_SITE="https://gnupg.org/software/gpgme/index.html" +PKG_URL="https://gnupg.org/ftp/gcrypt/gpgme/gpgme-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain libassuan libgpg-error" +PKG_LONGDESC="GnuPG Made Easy (GPGME) is a library designed to make access to GnuPG easier for applications" +PKG_TOOLCHAIN="autotools" +PKG_BUILD_FLAGS="-sysroot" + +PKG_CONFIGURE_OPTS_TARGET="--enable-languages=cl \ + --disable-static \ + --enable-shared \ + --disable-glibtest \ + --disable-gpgconf-test \ + --disable-gpg-test \ + --disable-gpgsm-test \ + --disable-g13-test \ + --with-pic \ + --with-libgpg-error-prefix=${SYSROOT_PREFIX}/usr \ + --with-libassuan-prefix=$(get_install_dir libassuan)/usr" + +pre_configure_target() { + CFLAGS+=" -I$(get_install_dir libassuan)/usr/include" + LDFLAGS+=" -L$(get_install_dir libassuan)/usr/lib" +} diff --git a/packages/addons/addon-depends/podman/libassuan/package.mk b/packages/addons/addon-depends/podman/libassuan/package.mk new file mode 100644 index 0000000000..1a41ac1e8a --- /dev/null +++ b/packages/addons/addon-depends/podman/libassuan/package.mk @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2023-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libassuan" +PKG_VERSION="3.0.2" +PKG_SHA256="d2931cdad266e633510f9970e1a2f346055e351bb19f9b78912475b8074c36f6" +PKG_LICENSE="LGPLv2.1+" +PKG_SITE="https://gnupg.org/software/libassuan/index.html" +PKG_URL="https://www.gnupg.org/ftp/gcrypt/libassuan/libassuan-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain libgpg-error" +PKG_LONGDESC="Libassuan is a small library implementing the so-called Assuan protocol" +PKG_TOOLCHAIN="autotools" +PKG_BUILD_FLAGS="-sysroot" + +PKG_CONFIGURE_OPTS_TARGET="--enable-static \ + --disable-shared \ + --with-gnu-ld \ + --with-pic \ + --with-libgpg-error-prefix=${SYSROOT_PREFIX}/usr" diff --git a/packages/addons/addon-depends/podman/netavark/package.mk b/packages/addons/addon-depends/podman/netavark/package.mk new file mode 100644 index 0000000000..ca07745f8b --- /dev/null +++ b/packages/addons/addon-depends/podman/netavark/package.mk @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2023-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="netavark" +PKG_VERSION="1.15.2" +PKG_SHA256="84325e03aa0a2818aef9fb57b62cda8e9472584744d91ce5e5b191098f9e6d6a" +PKG_LICENSE="Apache-2.0" +PKG_SITE="https://github.com/containers/netavark" +PKG_URL="https://github.com/containers/netavark/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain cargo:host protobuf:host" +PKG_LONGDESC="Container network stack" +PKG_TOOLCHAIN="manual" + +make_target() { + cargo build \ + --target ${TARGET_NAME} \ + --release \ + --locked \ + --all-features +} + +makeinstall_target() { + mkdir -p ${INSTALL} + cp ${PKG_BUILD}/.${TARGET_NAME}/target/${TARGET_NAME}/release/netavark ${INSTALL} +} diff --git a/packages/addons/addon-depends/podman/podman-bin/package.mk b/packages/addons/addon-depends/podman/podman-bin/package.mk new file mode 100644 index 0000000000..4cf90a459d --- /dev/null +++ b/packages/addons/addon-depends/podman/podman-bin/package.mk @@ -0,0 +1,43 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2023-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="podman-bin" +PKG_VERSION="5.5.2" +PKG_SHA256="a2dbd8280cd92d4741f32f5a99d385d7fc6f0dd36bc9cc90a7273767e26d43d9" +PKG_LICENSE="Apache-2.0" +PKG_SITE="https://podman.io/" +PKG_URL="https://github.com/containers/podman/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain go:host gpgme libassuan libseccomp systemd" +PKG_LONGDESC="Podman: A tool for managing OCI containers and pods." +PKG_TOOLCHAIN="manual" + +# Git commit of the matching release https://github.com/containers/podman +export PKG_GIT_COMMIT="e7d8226745ba07a64b7176a7f128e4ef53225a0e" + +PKG_PODMAN_BUILDTAGS="exclude_graphdriver_devicemapper \ + exclude_graphdriver_btrfs \ + seccomp \ + systemd" + +configure_target() { + export PKG_CONFIG_PATH="$(get_install_dir libassuan)/usr/lib/pkgconfig:$(get_install_dir gpgme)/usr/lib/pkgconfig:$(get_install_dir libseccomp)/usr/lib/pkgconfig:${PKG_CONFIG_PATH}" + + go_configure + + # used for podman commit + export GIT_COMMIT=${PKG_GIT_COMMIT} +} + +make_target() { + make BUILDTAGS="${PKG_PODMAN_BUILDTAGS}" \ + CGO_CPPFLAGS="-I$(get_install_dir gpgme)/usr/include" \ + GO="${GOLANG}" \ + PREFIX=/storage/.kodi/addons/service.system.podman \ + HELPER_BINARIES_DIR=/storage/.kodi/addons/service.system.podman/bin \ + EXTRA_LDFLAGS="-X github.com/containers/image/v5/sysregistries.systemRegistriesConfPath=/storage/.kodi/userdata/addon_data/service.system.podman/podman/etc/containers/registries.conf -X github.com/containers/image/v5/sysregistries.systemRegistriesConfDirectoryPath=/storage/.kodi/userdata/addon_data/service.system.podman/podman/etc/containers/registries.conf.d -X github.com/containers/image/v5/signature.systemDefaultPolicyPath=/storage/.kodi/addons/service.system.podman/etc/containers/policy.json -extldflags=-L$(get_install_dir gpgme)/usr/lib" \ + binaries +} + +makeinstall_target() { + : +} diff --git a/packages/addons/addon-depends/polkit/package.mk b/packages/addons/addon-depends/polkit/package.mk new file mode 100644 index 0000000000..3ac6e078a5 --- /dev/null +++ b/packages/addons/addon-depends/polkit/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2023-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="polkit" +PKG_VERSION="126" +PKG_SHA256="2814a7281989f6baa9e57bd33bbc5e148827e2721ccef22aaf28ab2b376068e8" +PKG_LICENSE="GPL" +PKG_SITE="https://polkit.pages.freedesktop.org/polkit" +PKG_URL="https://github.com/polkit-org/polkit/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain expat glib systemd" +PKG_LONGDESC="polkit provides an authorization API intended to be used by privileged programs offering service to unprivileged programs" +PKG_BUILD_FLAGS="-sysroot" + +PKG_MESON_OPTS_TARGET="-Dauthfw=shadow \ + -Dsession_tracking=logind \ + -Dlibs-only=true \ + -Dintrospection=false" diff --git a/packages/addons/addon-depends/protobuf/package.mk b/packages/addons/addon-depends/protobuf/package.mk new file mode 100644 index 0000000000..caba990d4b --- /dev/null +++ b/packages/addons/addon-depends/protobuf/package.mk @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="protobuf" +PKG_VERSION="21.12" +PKG_SHA256="4eab9b524aa5913c6fffb20b2a8abf5ef7f95a80bc0701f3a6dbb4c607f73460" +PKG_LICENSE="OSS" +PKG_SITE="https://developers.google.com/protocol-buffers/" +PKG_URL="https://github.com/google/${PKG_NAME}/releases/download/v${PKG_VERSION}/${PKG_NAME}-cpp-3.${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="toolchain:host zlib:host" +PKG_DEPENDS_TARGET="toolchain zlib protobuf:host" +PKG_LONGDESC="Protocol Buffers for Google's data interchange format." + +PKG_CMAKE_OPTS_HOST="-DCMAKE_NO_SYSTEM_FROM_IMPORTED=1 \ + -DBUILD_SHARED_LIBS=0 \ + -Dprotobuf_BUILD_TESTS=0 \ + -Dprotobuf_BUILD_EXAMPLES=0 \ + -Dprotobuf_WITH_ZLIB=1" + +PKG_CMAKE_OPTS_TARGET="${PKG_CMAKE_OPTS_HOST}" + +configure_package() { + PKG_CMAKE_SCRIPT="${PKG_BUILD}/cmake/CMakeLists.txt" +} + +post_makeinstall_target() { + rm -rf ${INSTALL}/usr/bin + + # HACK: we have protoc in ${TOOLCHAIN}/bin but it seems + # the one from sysroot prefix is picked when building hyperion. remove it! + rm -f ${SYSROOT_PREFIX}/usr/bin/protoc +} diff --git a/packages/addons/addon-depends/qt5/package.mk b/packages/addons/addon-depends/qt5/package.mk new file mode 100644 index 0000000000..d3c970ed4d --- /dev/null +++ b/packages/addons/addon-depends/qt5/package.mk @@ -0,0 +1,142 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="qt5" +PKG_VERSION="5.15.16" +PKG_SHA256="efa99827027782974356aceff8a52bd3d2a8a93a54dd0db4cca41b5e35f1041c" +PKG_LICENSE="GPL" +PKG_SITE="https://qt-project.org" +PKG_URL="https://download.qt.io/archive/qt/${PKG_VERSION%.*}/${PKG_VERSION}/single/qt-everywhere-opensource-src-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="freetype libjpeg-turbo libpng openssl sqlite zlib" +PKG_LONGDESC="A cross-platform application and UI framework." +PKG_BUILD_FLAGS="-sysroot" + +PKG_CONFIGURE_OPTS_TARGET="-prefix /usr + -sysroot "${SYSROOT_PREFIX}" + -hostprefix "${TOOLCHAIN}" + -device linux-libreelec-g++ + -opensource -confirm-license + -release + -optimize-size + -strip + -static + -silent + -force-pkg-config + -make libs + -no-dbus + -no-accessibility + -no-glib + -no-iconv + -no-icu + -qt-pcre + -system-zlib + -no-zstd + -openssl-linked + -no-libproxy + -no-cups + -no-fontconfig + -system-freetype + -no-harfbuzz + -no-opengl + -no-egl + -no-eglfs + -no-gbm + -no-kms + -no-linuxfb + -no-xcb + -no-feature-vnc + -no-feature-sessionmanager + -no-feature-easingcurve + -no-feature-effects + -no-feature-gestures + -no-feature-itemmodel + -no-libudev + -no-evdev + -no-libinput + -no-mtdev + -no-tslib + -no-xkbcommon + -no-gif + -no-ico + -system-libpng + -system-libjpeg + -no-sql-mysql + -system-sqlite + -no-gtk + -no-xcb-xlib + -skip qt3d + -skip qtactiveqt + -skip qtandroidextras + -skip qtcharts + -skip qtconnectivity + -skip qtdatavis3d + -skip qtdeclarative + -skip qtdoc + -skip qtgamepad + -skip qtgraphicaleffects + -skip qtimageformats + -skip qtlocation + -skip qtlottie + -skip qtmacextras + -skip qtmultimedia + -skip qtnetworkauth + -skip qtpurchasing + -skip qtquick3d + -skip qtquickcontrols + -skip qtquickcontrols2 + -skip qtquicktimeline + -skip qtremoteobjects + -skip qtscript + -skip qtscxml + -skip qtsensors + -skip qtserialbus + -skip qtspeech + -skip qtsvg + -skip qttools + -skip qttranslations + -skip qtvirtualkeyboard + -skip qtwayland + -skip qtwebchannel + -skip qtwebengine + -skip qtwebglplugin + -skip qtwebsockets + -skip qtwebview + -skip qtwinextras + -skip qtx11extras + -skip qtxmlpatterns" + +configure_target() { + QMAKE_CONF_DIR="qtbase/mkspecs/devices/linux-libreelec-g++" + + cd .. + mkdir -p ${QMAKE_CONF_DIR} + + cat >"${QMAKE_CONF_DIR}/qmake.conf" <"${QMAKE_CONF_DIR}/qplatformdefs.h" <${INSTALL}/usr/bin/dstat + chmod 755 ${INSTALL}/usr/bin/dstat +} diff --git a/packages/addons/addon-depends/system-tools-depends/dtach/package.mk b/packages/addons/addon-depends/system-tools-depends/dtach/package.mk new file mode 100644 index 0000000000..26d2eb39b7 --- /dev/null +++ b/packages/addons/addon-depends/system-tools-depends/dtach/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="dtach" +PKG_VERSION="b027c27b2439081064d07a86883c8e0b20a183c9" +PKG_SHA256="2ec8db52ed99700cf80258b52e77461068abf24a2798cb91f9c0b2bc6e6ee8f4" +PKG_LICENSE="GPL" +PKG_SITE="http://dtach.sourceforge.net" +PKG_URL="https://github.com/crigler/dtach/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A program that emulates the detach feature of screen." +PKG_BUILD_FLAGS="-sysroot -cfg-libs" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp -p dtach ${INSTALL}/usr/bin +} diff --git a/packages/addons/addon-depends/system-tools-depends/efibootmgr/package.mk b/packages/addons/addon-depends/system-tools-depends/efibootmgr/package.mk new file mode 100644 index 0000000000..7997087cda --- /dev/null +++ b/packages/addons/addon-depends/system-tools-depends/efibootmgr/package.mk @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="efibootmgr" +PKG_VERSION="0a85e9baaac8a34e4a0bb9c23dfcc9c4f759e061" +PKG_SHA256="05c621b1c08f3fdade8ddd4403240eb528705cee9e65d1bce937b0dc43c4fee9" +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." +PKG_BUILD_FLAGS="-sysroot" + +make_target() { + export CFLAGS="${CFLAGS} -I${SYSROOT_PREFIX}/usr/include -I${SYSROOT_PREFIX}/usr/include/efivar -fgnu89-inline -Wno-pointer-sign" + 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() { + mkdir -p ${INSTALL}/usr/bin + cp -p src/efibootmgr ${INSTALL}/usr/bin +} diff --git a/packages/addons/addon-depends/system-tools-depends/encfs/package.mk b/packages/addons/addon-depends/system-tools-depends/encfs/package.mk new file mode 100644 index 0000000000..c923a213c5 --- /dev/null +++ b/packages/addons/addon-depends/system-tools-depends/encfs/package.mk @@ -0,0 +1,18 @@ +# 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 tinyxml2" +PKG_LONGDESC="A Encrypted Filesystem for FUSE." +PKG_BUILD_FLAGS="-sysroot" + +PKG_CMAKE_OPTS_TARGET="-DCMAKE_INSTALL_PREFIX=/usr \ + -DCMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES=${SYSROOT_PREFIX}/usr/include \ + -DBUILD_UNIT_TESTS=OFF \ + -DCMAKE_SKIP_RPATH=ON \ + -DUSE_INTERNAL_TINYXML=OFF" diff --git a/packages/addons/addon-depends/system-tools-depends/evtest/package.mk b/packages/addons/addon-depends/system-tools-depends/evtest/package.mk new file mode 100644 index 0000000000..a70ea7db05 --- /dev/null +++ b/packages/addons/addon-depends/system-tools-depends/evtest/package.mk @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="evtest" +PKG_VERSION="1.35" +PKG_SHA256="a224abeb783561193660999b0c986216d691cb271b5ec3af88c6bb37b55ff51c" +PKG_LICENSE="GPL" +PKG_SITE="http://cgit.freedesktop.org/evtest/" +PKG_URL="https://repo.or.cz/evtest.git/snapshot/evtest-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain libxml2" +PKG_LONGDESC="A simple tool for input event debugging." +PKG_TOOLCHAIN="autotools" +PKG_BUILD_FLAGS="-sysroot -cfg-libs" diff --git a/packages/addons/addon-depends/system-tools-depends/fdupes/package.mk b/packages/addons/addon-depends/system-tools-depends/fdupes/package.mk new file mode 100644 index 0000000000..e35b392fca --- /dev/null +++ b/packages/addons/addon-depends/system-tools-depends/fdupes/package.mk @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="fdupes" +PKG_VERSION="2.4.0" +PKG_SHA256="527b27a39d031dcbe1d29a220b3423228c28366c2412887eb72c25473d7b1736" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/adrianlopezroche/fdupes" +PKG_URL="https://github.com/adrianlopezroche/fdupes/releases/download/v${PKG_VERSION}/fdupes-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain ncurses sqlite" +PKG_LONGDESC="A program for identifying or deleting duplicate files residing within specified directories." +PKG_BUILD_FLAGS="-sysroot -cfg-libs" + +PKG_CONFIGURE_OPTS_TARGET="--without-ncurses" +PKG_MAKE_OPTS_TARGET="PREFIX=/usr" +PKG_MAKEINSTALL_OPTS_TARGET="${PKG_MAKE_OPTS_TARGET}" diff --git a/packages/addons/addon-depends/system-tools-depends/file/package.mk b/packages/addons/addon-depends/system-tools-depends/file/package.mk new file mode 100644 index 0000000000..b9c0834625 --- /dev/null +++ b/packages/addons/addon-depends/system-tools-depends/file/package.mk @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="file" +PKG_VERSION="5.46" +PKG_SHA256="908d74bd8751e35e65611788f58f8b6f5c6d487d437fbd2f845daf0e051818a1" +PKG_LICENSE="BSD" +PKG_SITE="http://www.darwinsys.com/file/" +PKG_URL="https://github.com/file/file/archive/FILE${PKG_VERSION/./_}.tar.gz" +PKG_DEPENDS_HOST="toolchain:host" +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_BUILD_FLAGS="-sysroot" + +PKG_CONFIGURE_OPTS_HOST="--enable-fsect-man5 \ + --enable-static \ + --disable-shared" + +PKG_CONFIGURE_OPTS_TARGET="${PKG_CONFIGURE_OPTS_HOST}" diff --git a/packages/addons/addon-depends/system-tools-depends/getscancodes/package.mk b/packages/addons/addon-depends/system-tools-depends/getscancodes/package.mk new file mode 100644 index 0000000000..e7b9a4e32f --- /dev/null +++ b/packages/addons/addon-depends/system-tools-depends/getscancodes/package.mk @@ -0,0 +1,21 @@ +# 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." +PKG_BUILD_FLAGS="-sysroot" + +pre_configure_target() { + PKG_MAKE_OPTS_TARGET="CC=${CC}" +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp -p getscancodes ${INSTALL}/usr/bin +} diff --git a/packages/addons/addon-depends/system-tools-depends/hd-idle/package.mk b/packages/addons/addon-depends/system-tools-depends/hd-idle/package.mk new file mode 100644 index 0000000000..291d79b8ce --- /dev/null +++ b/packages/addons/addon-depends/system-tools-depends/hd-idle/package.mk @@ -0,0 +1,12 @@ +# 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." +PKG_BUILD_FLAGS="-sysroot" diff --git a/packages/addons/addon-depends/system-tools-depends/hddtemp/package.mk b/packages/addons/addon-depends/system-tools-depends/hddtemp/package.mk new file mode 100644 index 0000000000..41ab3dbec9 --- /dev/null +++ b/packages/addons/addon-depends/system-tools-depends/hddtemp/package.mk @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="hddtemp" +PKG_VERSION="0.4.3" +PKG_SHA256="592322c64f0d5f035132249e3d051b752f5d24867514522a17285d5e72d21075" +PKG_LICENSE="GPL" +PKG_SITE="https://savannah.nongnu.org/projects/hddtemp" +PKG_URL="https://github.com/vitlav/hddtemp/archive/v${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_BUILD_FLAGS="-sysroot -cfg-libs" +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="--with-db-path=/storage/.kodi/addons/virtual.system-tools/data/hddtemp.db" + +post_makeinstall_target() { + mkdir -p ${INSTALL}/usr/share/misc + cp ${PKG_DIR}/db/* ${INSTALL}/usr/share/misc +} diff --git a/packages/addons/addon-depends/system-tools-depends/hid_mapper/package.mk b/packages/addons/addon-depends/system-tools-depends/hid_mapper/package.mk new file mode 100644 index 0000000000..f115bd993d --- /dev/null +++ b/packages/addons/addon-depends/system-tools-depends/hid_mapper/package.mk @@ -0,0 +1,17 @@ +# 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." +PKG_BUILD_FLAGS="-sysroot" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp -p hid_mapper ${INSTALL}/usr/bin +} diff --git a/packages/addons/addon-depends/system-tools-depends/htop/package.mk b/packages/addons/addon-depends/system-tools-depends/htop/package.mk new file mode 100644 index 0000000000..77ec8dff58 --- /dev/null +++ b/packages/addons/addon-depends/system-tools-depends/htop/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="htop" +PKG_VERSION="3.4.1" +PKG_SHA256="af9ec878f831b7c27d33e775c668ec79d569aa781861c995a0fbadc1bdb666cf" +PKG_LICENSE="GPL" +PKG_SITE="https://hisham.hm/htop" +PKG_URL="https://github.com/htop-dev/htop/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain ncurses" +PKG_LONGDESC="An interactive process viewer for Unix." +PKG_TOOLCHAIN="autotools" +PKG_BUILD_FLAGS="-sysroot -cfg-libs" + +PKG_CONFIGURE_OPTS_TARGET="--disable-unicode \ + --disable-static \ + HTOP_NCURSES_CONFIG_SCRIPT=ncurses-config" + +pre_configure_target() { + export LDFLAGS="${LDFLAGS} -pthread" +} diff --git a/packages/addons/addon-depends/system-tools-depends/i2c-tools/package.mk b/packages/addons/addon-depends/system-tools-depends/i2c-tools/package.mk new file mode 100644 index 0000000000..d9e7ee8923 --- /dev/null +++ b/packages/addons/addon-depends/system-tools-depends/i2c-tools/package.mk @@ -0,0 +1,36 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="i2c-tools" +PKG_VERSION="4.4" +PKG_SHA256="8b15f0a880ab87280c40cfd7235cfff28134bf14d5646c07518b1ff6642a2473" +PKG_LICENSE="GPL" +PKG_SITE="https://i2c.wiki.kernel.org/index.php/I2C_Tools" +PKG_URL="https://www.kernel.org/pub/software/utils/i2c-tools/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain Python3 setuptools:host" +PKG_LONGDESC="A heterogeneous set of I2C tools for Linux." +PKG_BUILD_FLAGS="-sysroot" + +make_target() { + make CC="${CC}" \ + AR="${AR}" \ + CFLAGS="${TARGET_CFLAGS}" \ + CPPFLAGS="${TARGET_CPPFLAGS}" \ + all + + ( + cd py-smbus + python_target_env python3 -m build -n -w -x + ) +} + +makeinstall_target() { + make DESTDIR=${INSTALL} \ + PREFIX="/usr" \ + prefix="/usr" \ + install + ( + cd py-smbus + python3 -m installer --overwrite-existing dist/*.whl -d ${INSTALL} -p /usr + ) +} diff --git a/packages/addons/addon-depends/system-tools-depends/inotify-tools/package.mk b/packages/addons/addon-depends/system-tools-depends/inotify-tools/package.mk new file mode 100644 index 0000000000..79df143238 --- /dev/null +++ b/packages/addons/addon-depends/system-tools-depends/inotify-tools/package.mk @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="inotify-tools" +PKG_VERSION="4.23.9.0" +PKG_SHA256="1dfa33f80b6797ce2f6c01f454fd486d30be4dca1b0c5c2ea9ba3c30a5c39855" +PKG_LICENSE="GPLv2" +PKG_SITE="http://wiki.github.com/inotify-tools/inotify-tools/" +PKG_URL="https://github.com/inotify-tools/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_BUILD_FLAGS="-sysroot" + +PKG_CONFIGURE_OPTS_TARGET="--enable-static --disable-shared --disable-doxygen" + +pre_configure_target() { + CXXFLAGS+=" -Wno-error=unused-parameter" +} + +post_configure_target() { + libtool_remove_rpath libtool +} diff --git a/packages/addons/addon-depends/system-tools-depends/jq/package.mk b/packages/addons/addon-depends/system-tools-depends/jq/package.mk new file mode 100644 index 0000000000..18718ff860 --- /dev/null +++ b/packages/addons/addon-depends/system-tools-depends/jq/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="jq" +PKG_VERSION="1.8.1" +PKG_SHA256="2be64e7129cecb11d5906290eba10af694fb9e3e7f9fc208a311dc33ca837eb0" +PKG_LICENSE="MIT" +PKG_SITE="https://jqlang.github.io/jq/" +PKG_URL="https://github.com/jqlang/jq/releases/download/${PKG_NAME}-${PKG_VERSION}/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain oniguruma" +PKG_LONGDESC="Command-line JSON processor" +PKG_BUILD_FLAGS="-sysroot" + +PKG_CONFIGURE_OPTS_TARGET="--disable-shared \ + --enable-static \ + --disable-docs \ + --disable-maintainer-mode \ + --disable-valgrind" diff --git a/packages/addons/addon-depends/system-tools-depends/lm_sensors/package.mk b/packages/addons/addon-depends/system-tools-depends/lm_sensors/package.mk new file mode 100644 index 0000000000..c266f100f0 --- /dev/null +++ b/packages/addons/addon-depends/system-tools-depends/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="3.6.0" +PKG_SHA256="0591f9fa0339f0d15e75326d0365871c2d4e2ed8aa1ff759b3a55d3734b7d197" +PKG_LICENSE="GPL" +PKG_SITE="https://hwmon.wiki.kernel.org" +PKG_URL="https://github.com/groeck/lm-sensors/archive/V${PKG_VERSION//./-}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Provides user-space support for the hardware monitoring drivers." +PKG_BUILD_FLAGS="-sysroot" + +pre_make_target() { + PKG_MAKE_OPTS_TARGET="PREFIX=/usr CC=${CC} AR=${AR}" + + export CFLAGS="${TARGET_CFLAGS}" + export CPPFLAGS="${TARGET_CPPFLAGS}" + + sed -i 's|^EXLDFLAGS :=.*|EXLDFLAGS :=|' Makefile +} + +pre_makeinstall_target() { + PKG_MAKEINSTALL_OPTS_TARGET="PREFIX=/usr CC=${CC} AR=${AR}" +} diff --git a/packages/addons/addon-depends/system-tools-depends/lshw/package.mk b/packages/addons/addon-depends/system-tools-depends/lshw/package.mk new file mode 100644 index 0000000000..77044021a3 --- /dev/null +++ b/packages/addons/addon-depends/system-tools-depends/lshw/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="lshw" +PKG_VERSION="02.20" +PKG_SHA256="06d9cf122422220e5dc94e8ea5b01816a69bb6b59368f63d7f21fff31fc6922a" +PKG_LICENSE="GPL" +PKG_SITE="http://ezix.org/project/wiki/HardwareLiSter" +PKG_URL="http://ezix.org/software/files/lshw-B.${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A small tool to provide detailed information on the hardware configuration of the machine." +PKG_BUILD_FLAGS="-sysroot" + +make_target() { + export VERSION="B.${PKG_VERSION}" + make CXX=${CXX} -C src/ +} diff --git a/packages/addons/addon-depends/system-tools-depends/mc/package.mk b/packages/addons/addon-depends/system-tools-depends/mc/package.mk new file mode 100644 index 0000000000..c868fa8c0a --- /dev/null +++ b/packages/addons/addon-depends/system-tools-depends/mc/package.mk @@ -0,0 +1,50 @@ +# 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.33" +PKG_SHA256="cae149d42f844e5185d8c81d7db3913a8fa214c65f852200a9d896b468af164c" +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 pcre2" +PKG_LONGDESC="Midnight Commander is a text based filemanager that emulates Norton Commander." +PKG_BUILD_FLAGS="-sysroot" + +PKG_CONFIGURE_OPTS_TARGET=" \ + --datadir=/storage/.kodi/addons/virtual.system-tools/data \ + --libexecdir=/storage/.kodi/addons/virtual.system-tools/mclib \ + --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 \ + --with-search-engine=pcre2 \ + --with-pcre2=${SYSROOT_PREFIX}/usr \ + --without-x" + +pre_configure_target() { + 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 -p ${PKG_DIR}/wrapper/* ${INSTALL}/usr/bin +} diff --git a/packages/addons/addon-depends/system-tools-depends/mmc-utils/package.mk b/packages/addons/addon-depends/system-tools-depends/mmc-utils/package.mk new file mode 100644 index 0000000000..9ca003d2ad --- /dev/null +++ b/packages/addons/addon-depends/system-tools-depends/mmc-utils/package.mk @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="mmc-utils" +PKG_VERSION="1.0" +PKG_SHA256="39e6a89e06b53f99816f110af6743d1adc82220b26c51b0c3fd0a11ccf4206c2" +PKG_LICENSE="GPL" +PKG_SITE="https://www.kernel.org/doc/html/latest/driver-api/mmc/mmc-tools.html" +PKG_URL="https://git.kernel.org/pub/scm/utils/mmc/mmc-utils.git/snapshot/mmc-utils-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Configure MMC storage devices from userspace." +PKG_BUILD_FLAGS="-sysroot" + +PKG_MAKE_OPTS_TARGET+=" C=" diff --git a/packages/addons/addon-depends/system-tools-depends/mtpfs/package.mk b/packages/addons/addon-depends/system-tools-depends/mtpfs/package.mk new file mode 100644 index 0000000000..c31437b6ca --- /dev/null +++ b/packages/addons/addon-depends/system-tools-depends/mtpfs/package.mk @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="mtpfs" +PKG_VERSION="1177d6cfd8916915f5db7d9b5c6fc9e6eafae6e6" +PKG_SHA256="ed8101e05d668ba7fa13517ab5d6e4cee1097cf68206ff1c84d13433ca4192a5" +PKG_LICENSE="GPL" +PKG_SITE="https://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_BUILD_FLAGS="-sysroot -cfg-libs" + +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" +} diff --git a/packages/addons/addon-depends/system-tools-depends/nmon/package.mk b/packages/addons/addon-depends/system-tools-depends/nmon/package.mk new file mode 100644 index 0000000000..8d97a60d6c --- /dev/null +++ b/packages/addons/addon-depends/system-tools-depends/nmon/package.mk @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="nmon" +PKG_VERSION="16q" +PKG_SHA256="1b78a81672c19291b3d11a6e319dd9b23a022a262dba1efcea008d6df51aca51" +PKG_LICENSE="GPL" +PKG_SITE="https://nmon.sourceforge.net/pmwiki.php?n=Site.CompilingNmon" +PKG_URL="https://sourceforge.net/projects/nmon/files/lmon${PKG_VERSION}.c" +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" +PKG_BUILD_FLAGS="-sysroot" + +unpack() { + mkdir -p ${PKG_BUILD} + cp -p ${SOURCES}/nmon/${PKG_SOURCE_NAME} ${PKG_BUILD} +} + +make_target() { + case ${ARCH} in + x86_64) + arch="X86" + ;; + *) + arch="arm" + ;; + esac + # original makefile is located at + # - https://downloads.sourceforge.net/project/nmon/makefile + CFLAGS+=" -g -O3 -Wall -D JFS -D GETUSER -D LARGEMEM" + LDFLAGS+=" -lncurses -lm -g" + ${CC} -o nmon nmon-${PKG_VERSION}.c ${CFLAGS} ${LDFLAGS} -D ${arch} -DUBUNTU +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp -p nmon ${INSTALL}/usr/bin +} diff --git a/packages/addons/addon-depends/system-tools-depends/patch/package.mk b/packages/addons/addon-depends/system-tools-depends/patch/package.mk new file mode 100644 index 0000000000..93ac7625e6 --- /dev/null +++ b/packages/addons/addon-depends/system-tools-depends/patch/package.mk @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="patch" +PKG_VERSION="2.8" +PKG_SHA256="f87cee69eec2b4fcbf60a396b030ad6aa3415f192aa5f7ee84cad5e11f7f5ae3" +PKG_LICENSE="GPL" +PKG_SITE="https://savannah.gnu.org/projects/patch" +PKG_URL="https://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_BUILD_FLAGS="-sysroot -cfg-libs" + +PKG_CONFIGURE_OPTS_TARGET="--disable-xattr" diff --git a/packages/addons/addon-depends/system-tools-depends/pv/package.mk b/packages/addons/addon-depends/system-tools-depends/pv/package.mk new file mode 100644 index 0000000000..ffb0ea9146 --- /dev/null +++ b/packages/addons/addon-depends/system-tools-depends/pv/package.mk @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="pv" +PKG_VERSION="1.9.31" +PKG_SHA256="a35e92ec4ac0e8f380e8e840088167ae01014bfa008a3a9d6506b848079daedf" +PKG_LICENSE="GNU" +PKG_SITE="http://www.ivarch.com/programs/pv.shtml" +PKG_URL="http://www.ivarch.com/programs/sources/pv-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Pipe Viewer can be inserted into any normal pipeline between two processes." +PKG_BUILD_FLAGS="-sysroot -cfg-libs" diff --git a/packages/addons/addon-depends/system-tools-depends/screen/package.mk b/packages/addons/addon-depends/system-tools-depends/screen/package.mk new file mode 100644 index 0000000000..2a14cd7a60 --- /dev/null +++ b/packages/addons/addon-depends/system-tools-depends/screen/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="screen" +PKG_VERSION="5.0.1" +PKG_SHA256="2dae36f4db379ffcd14b691596ba6ec18ac3a9e22bc47ac239789ab58409869d" +PKG_LICENSE="GPL" +PKG_SITE="https://www.gnu.org/software/screen/" +PKG_URL="https://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_BUILD_FLAGS="-sysroot -parallel -cfg-libs" +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="ac_cv_header_utempter_h=no \ + --disable-pam \ + --disable-telnet \ + --disable-socket-dir" diff --git a/packages/addons/addon-depends/system-tools-depends/sdparm/package.mk b/packages/addons/addon-depends/system-tools-depends/sdparm/package.mk new file mode 100644 index 0000000000..6576a15040 --- /dev/null +++ b/packages/addons/addon-depends/system-tools-depends/sdparm/package.mk @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="sdparm" +PKG_VERSION="1.12" +PKG_SHA256="c4c9efafdbeb662e2f9712707ec490932bd4d010bb1129ae7a99526546eeadbe" +PKG_LICENSE="BSD" +PKG_SITE="https://sg.danny.cz/sg/sdparm.html" +PKG_URL="https://sg.danny.cz/sg/p/sdparm-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="The sdparm utility accesses SCSI device parameters." +PKG_BUILD_FLAGS="-sysroot -cfg-libs" diff --git a/packages/addons/addon-depends/system-tools-depends/smartmontools/package.mk b/packages/addons/addon-depends/system-tools-depends/smartmontools/package.mk new file mode 100644 index 0000000000..6194351dad --- /dev/null +++ b/packages/addons/addon-depends/system-tools-depends/smartmontools/package.mk @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="smartmontools" +PKG_VERSION="7.5" +PKG_SHA256="690b83ca331378da9ea0d9d61008c4b22dde391387b9bbad7f29387f2595f76e" +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_BUILD_FLAGS="-sysroot -cfg-libs" + +PKG_CONFIGURE_OPTS_TARGET="--prefix=/usr \ + --without-initscriptdir \ + --without-nvme-devicescan \ + --without-systemdenvfile \ + --without-systemdsystemunitdir \ + --without-systemdenvfile \ + --without-systemdsystemunitdir" diff --git a/packages/addons/addon-depends/system-tools-depends/st/package.mk b/packages/addons/addon-depends/system-tools-depends/st/package.mk new file mode 100644 index 0000000000..c9f0f0264a --- /dev/null +++ b/packages/addons/addon-depends/system-tools-depends/st/package.mk @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2020-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="st" +PKG_VERSION="0.9.2" +PKG_SHA256="6b215d4f472b21d6232f30f221117a777e24bcfee68955ddefb7426467f9494b" +PKG_ARCH="x86_64" +PKG_LICENSE="GPL" +PKG_SITE="https://st.suckless.org/" +PKG_URL="https://dl.suckless.org/st/st-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain libX11 libXft libXrender fontconfig freetype ncurses" +PKG_LONGDESC="A simple terminal implementation for X" +PKG_BUILD_FLAGS="-sysroot" + +PKG_MAKE_OPTS_TARGET="X11INC=$(get_install_dir libXft)/usr/include \ + X11LIB=$(get_install_dir libXft)/usr/lib" + +pre_configure_target() { + LDFLAGS="-lXrender ${LDFLAGS}" +} diff --git a/packages/addons/addon-depends/system-tools-depends/stress-ng/package.mk b/packages/addons/addon-depends/system-tools-depends/stress-ng/package.mk new file mode 100644 index 0000000000..01fd13bb61 --- /dev/null +++ b/packages/addons/addon-depends/system-tools-depends/stress-ng/package.mk @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="stress-ng" +PKG_VERSION="0.19.02" +PKG_SHA256="15a07030a14bbfd5991e9ba3fbfbc24ed3ae72a2c946b033c06b820bc16f41c4" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/ColinIanKing/stress-ng" +PKG_URL="https://github.com/ColinIanKing/stress-ng/archive/refs/tags/V${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain attr keyutils libaio libcap zlib" +PKG_LONGDESC="stress-ng will stress test a computer system in various selectable ways" +PKG_BUILD_FLAGS="-sysroot" diff --git a/packages/addons/addon-depends/system-tools-depends/tmux/package.mk b/packages/addons/addon-depends/system-tools-depends/tmux/package.mk new file mode 100644 index 0000000000..f25283f345 --- /dev/null +++ b/packages/addons/addon-depends/system-tools-depends/tmux/package.mk @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2025-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="tmux" +PKG_VERSION="3.5a" +PKG_SHA256="16216bd0877170dfcc64157085ba9013610b12b082548c7c9542cc0103198951" +PKG_LICENSE="ISC" +PKG_SITE="https://github.com/tmux/tmux/wiki" +PKG_URL="https://github.com/tmux/tmux/releases/download/${PKG_VERSION}/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain libevent ncurses" +PKG_LONGDESC="tmux is a terminal multiplexer" +PKG_BUILD_FLAGS="-sysroot" diff --git a/packages/addons/addon-depends/system-tools-depends/tree/package.mk b/packages/addons/addon-depends/system-tools-depends/tree/package.mk new file mode 100644 index 0000000000..62fed640ab --- /dev/null +++ b/packages/addons/addon-depends/system-tools-depends/tree/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="tree" +PKG_VERSION="2.1.1" +PKG_SHA256="1b70253994dca48a59d6ed99390132f4d55c486bf0658468f8520e7e63666a06" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/Old-Man-Programmer/tree" +PKG_URL="https://github.com/Old-Man-Programmer/tree/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Tree is utility for displaying a dictionary tree's contents including files, directories, and links." +PKG_TOOLCHAIN="manual" + +make_target() { + make tree CXX=${CXX} CC=${CC} +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp -p tree ${INSTALL}/usr/bin/ +} diff --git a/packages/addons/addon-depends/system-tools-depends/unrar/package.mk b/packages/addons/addon-depends/system-tools-depends/unrar/package.mk new file mode 100644 index 0000000000..2c1be03ab8 --- /dev/null +++ b/packages/addons/addon-depends/system-tools-depends/unrar/package.mk @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="unrar" +PKG_VERSION="7.1.8" +PKG_SHA256="9ec7765a948140758af12ed29e3e47db425df79a9c5cbb71b28769b256a7a014" +PKG_LICENSE="free" +PKG_SITE="https://www.rarlab.com/rar_add.htm" +PKG_URL="https://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 -sysroot -parallel" + +unpack() { + mkdir -p ${PKG_BUILD}/unrar lib + tar -xf ${SOURCES}/${PKG_NAME}/${PKG_NAME}-${PKG_VERSION}.tar.gz -C ${PKG_BUILD}/ + cp -a ${PKG_BUILD}/unrar ${PKG_BUILD}/lib +} + +make_target() { + make CXX="${CXX}" \ + CXXFLAGS="${TARGET_CXXFLAGS}" \ + RANLIB="${RANLIB}" \ + AR="${AR}" \ + STRIP="${STRIP}" \ + -C unrar \ + -f makefile + + make CXX="${CXX}" \ + CXXFLAGS="${TARGET_CXXFLAGS}" \ + RANLIB="${RANLIB}" \ + AR="${AR}" \ + -C lib \ + -f makefile lib +} + +post_make_target() { + rm -f libunrar.so +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/include/unrar ${INSTALL}/usr/lib ${INSTALL}/usr/bin + cp -p lib/*.hpp ${INSTALL}/usr/include/unrar/ + cp -p lib/libunrar.a ${INSTALL}/usr/lib/ + cp -p unrar/unrar ${INSTALL}/usr/bin/ +} diff --git a/packages/addons/addon-depends/system-tools-depends/usb-modeswitch/package.mk b/packages/addons/addon-depends/system-tools-depends/usb-modeswitch/package.mk new file mode 100644 index 0000000000..284a310a21 --- /dev/null +++ b/packages/addons/addon-depends/system-tools-depends/usb-modeswitch/package.mk @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="usb-modeswitch" +PKG_VERSION="2.6.2" +PKG_SHA256="f7abd337784a9d1bd39cb8a587518aff6f2a43d916145eafd80b1b8b7146db66" +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" +PKG_BUILD_FLAGS="-sysroot" diff --git a/packages/addons/addon-depends/system-tools-depends/vim/package.mk b/packages/addons/addon-depends/system-tools-depends/vim/package.mk new file mode 100644 index 0000000000..4271bebd5f --- /dev/null +++ b/packages/addons/addon-depends/system-tools-depends/vim/package.mk @@ -0,0 +1,55 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="vim" +PKG_VERSION="9.1.0" +PKG_SHA256="ddb435f6e386c53799a3025bdc5a3533beac735a0ee596cb27ada97366a1c725" +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 -cfg-libs" + +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/.kodi/addons/virtual.system-tools/data \ + --disable-canberra \ + --disable-nls \ + --enable-selinux=no \ + --enable-gui=no \ + --with-compiledby=LibreELEC \ + --with-features=huge \ + --with-tlib=ncurses \ + --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 +} + +post_makeinstall_target() { + ( + cd ${INSTALL}/storage/.kodi/addons/virtual.system-tools/data/vim + rm -r doc tutor gvimrc_example.vim + mv vimrc_example.vim vimrc + ) +} diff --git a/packages/addons/addon-depends/tinc-depends/miniupnpc/package.mk b/packages/addons/addon-depends/tinc-depends/miniupnpc/package.mk new file mode 100644 index 0000000000..50d667340d --- /dev/null +++ b/packages/addons/addon-depends/tinc-depends/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.3.3" +PKG_SHA256="d52a0afa614ad6c088cc9ddff1ae7d29c8c595ac5fdd321170a05f41e634bd1a" +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/addons/addon-depends/tntnet/package.mk b/packages/addons/addon-depends/tntnet/package.mk new file mode 100644 index 0000000000..013a8040c7 --- /dev/null +++ b/packages/addons/addon-depends/tntnet/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) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="tntnet" +PKG_VERSION="3.0" +PKG_SHA256="718e5519b0a403f7f766358bf66a85c008119c48189d1c2b7651fd0af9018e27" +PKG_LICENSE="GPL-2" +PKG_SITE="http://www.tntnet.org/" +PKG_URL="http://www.tntnet.org/download/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="cxxtools:host zlib:host" +PKG_DEPENDS_TARGET="toolchain tntnet:host libtool cxxtools zlib" +PKG_LONGDESC="A web application server for C++." + +PKG_CONFIGURE_OPTS_HOST="--disable-unittest \ + --disable-server \ + --enable-sdk \ + --disable-demos" + +PKG_CONFIGURE_OPTS_TARGET="--disable-unittest \ + --with-sysroot=${SYSROOT_PREFIX} \ + --disable-server \ + --disable-sdk \ + --disable-demos" + +post_configure_target() { + libtool_remove_rpath libtool +} + +post_makeinstall_target() { + rm -rf ${INSTALL}/usr/bin + rm -rf ${INSTALL}/usr/share +} diff --git a/packages/addons/addon-depends/ttyd-depends/libuv/package.mk b/packages/addons/addon-depends/ttyd-depends/libuv/package.mk new file mode 100644 index 0000000000..0d14575fe1 --- /dev/null +++ b/packages/addons/addon-depends/ttyd-depends/libuv/package.mk @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2020-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libuv" +PKG_VERSION="1.51.0" +PKG_SHA256="27e55cf7083913bfb6826ca78cde9de7647cded648d35f24163f2d31bb9f51cd" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/libuv/libuv" +PKG_URL="https://github.com/libuv/libuv/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Multi-platform support library with a focus on asynchronous I/O" + +PKG_CMAKE_OPTS_TARGET="-DLIBUV_BUILD_TESTS=OFF" diff --git a/packages/addons/addon-depends/ttyd-depends/libwebsockets/package.mk b/packages/addons/addon-depends/ttyd-depends/libwebsockets/package.mk new file mode 100644 index 0000000000..121d66b877 --- /dev/null +++ b/packages/addons/addon-depends/ttyd-depends/libwebsockets/package.mk @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libwebsockets" +PKG_VERSION="4.3.5" +PKG_SHA256="87f99ad32803ed325fceac5327aae1f5c1b417d54ee61ad36cffc8df5f5ab276" +PKG_LICENSE="MIT" +PKG_SITE="https://libwebsockets.org" +PKG_URL="https://github.com/warmcat/libwebsockets/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain openssl json-c libuv" +PKG_LONGDESC="Library for implementing network protocols with a tiny footprint." + +PKG_CMAKE_OPTS_TARGET="-DLWS_WITH_LIBUV=ON \ + -DLWS_WITHOUT_TESTAPPS=ON" diff --git a/packages/addons/addon-depends/vdr-plugins/vdr-plugin-ddci2/package.mk b/packages/addons/addon-depends/vdr-plugins/vdr-plugin-ddci2/package.mk new file mode 100644 index 0000000000..cd2711a47a --- /dev/null +++ b/packages/addons/addon-depends/vdr-plugins/vdr-plugin-ddci2/package.mk @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="vdr-plugin-ddci2" +PKG_VERSION="05dd98824092859afd2aa7a4996c8f258affd975" +PKG_SHA256="b8ed2787e9140eb00a68397eaeb14862ba88a6e73480dc3220a098faffb14833" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/jasmin-j/vdr-plugin-ddci2" +PKG_URL="https://github.com/jasmin-j/vdr-plugin-ddci2/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain vdr" +PKG_NEED_UNPACK="$(get_pkg_directory vdr)" +PKG_LONGDESC="Support for stand alone CI by Digital Devices." +PKG_TOOLCHAIN="manual" + +make_target() { + VDR_DIR=$(get_build_dir vdr) + export PKG_CONFIG_PATH=${VDR_DIR}:${PKG_CONFIG_PATH} + export CPLUS_INCLUDE_PATH=${VDR_DIR}/include + + make \ + LIBDIR="." \ + LOCDIR="./locale" \ + all +} + +post_make_target() { + VDR_DIR=$(get_build_dir vdr) + VDR_APIVERSION=$(sed -ne '/define APIVERSION/s/^.*"\(.*\)".*$/\1/p' ${VDR_DIR}/config.h) + LIB_NAME=lib${PKG_NAME/-plugin/} + + cp --remove-destination ${PKG_BUILD}/${LIB_NAME}.so ${PKG_BUILD}/${LIB_NAME}.so.${VDR_APIVERSION} + ${STRIP} libvdr-*.so* +} diff --git a/packages/addons/addon-depends/vdr-plugins/vdr-plugin-dummydevice/package.mk b/packages/addons/addon-depends/vdr-plugins/vdr-plugin-dummydevice/package.mk new file mode 100644 index 0000000000..bca3e14f02 --- /dev/null +++ b/packages/addons/addon-depends/vdr-plugins/vdr-plugin-dummydevice/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) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="vdr-plugin-dummydevice" +PKG_VERSION="2.0.0" +PKG_SHA256="5c0049824415bd463d3abc728a3136ee064b60a37b5d3a1986cf282b0d757085" +PKG_LICENSE="GPL" +PKG_SITE="http://www.vdr-wiki.de/wiki/index.php/Dummydevice-plugin" +PKG_URL="http://phivdr.dyndns.org/vdr/vdr-dummydevice/${PKG_NAME/-plugin/}-${PKG_VERSION}.tgz" +PKG_DEPENDS_TARGET="toolchain vdr" +PKG_NEED_UNPACK="$(get_pkg_directory vdr)" +PKG_LONGDESC="This plugin can be used to run vdr as recording server without any output devices." +PKG_TOOLCHAIN="manual" + +make_target() { + VDR_DIR=$(get_build_dir vdr) + export PKG_CONFIG_PATH=${VDR_DIR}:${PKG_CONFIG_PATH} + export CPLUS_INCLUDE_PATH=${VDR_DIR}/include + + make \ + LIBDIR="." \ + LOCDIR="./locale" \ + all install-i18n +} + +post_make_target() { + VDR_DIR=$(get_build_dir vdr) + VDR_APIVERSION=$(sed -ne '/define APIVERSION/s/^.*"\(.*\)".*$/\1/p' ${VDR_DIR}/config.h) + LIB_NAME=lib${PKG_NAME/-plugin/} + + cp --remove-destination ${LIB_NAME}.so ${LIB_NAME}.so.${VDR_APIVERSION} +} diff --git a/packages/addons/addon-depends/vdr-plugins/vdr-plugin-dvbapi/package.mk b/packages/addons/addon-depends/vdr-plugins/vdr-plugin-dvbapi/package.mk new file mode 100644 index 0000000000..df208b48d8 --- /dev/null +++ b/packages/addons/addon-depends/vdr-plugins/vdr-plugin-dvbapi/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) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="vdr-plugin-dvbapi" +PKG_VERSION="2.2.6" +PKG_SHA256="dba435f6d9172189de4059d796d9020109997d51370e49ec0398d40ef8e08f69" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/manio/vdr-plugin-dvbapi" +PKG_URL="https://github.com/manio/vdr-plugin-dvbapi/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain vdr libdvbcsa" +PKG_NEED_UNPACK="$(get_pkg_directory vdr)" +PKG_LONGDESC="VDR dvbapi plugin for use with OSCam" +PKG_TOOLCHAIN="manual" + +make_target() { + VDR_DIR=$(get_build_dir vdr) + export PKG_CONFIG_PATH=${VDR_DIR}:${PKG_CONFIG_PATH} + export CPLUS_INCLUDE_PATH=${VDR_DIR}/include + + make \ + LIBDIR="." \ + LOCDIR="./locale" \ + LIBDVBCSA=1 \ + all install-i18n +} + +post_make_target() { + VDR_DIR=$(get_build_dir vdr) + VDR_APIVERSION=$(sed -ne '/define APIVERSION/s/^.*"\(.*\)".*$/\1/p' ${VDR_DIR}/config.h) + LIB_NAME=lib${PKG_NAME/-plugin/} + + cp --remove-destination ${PKG_BUILD}/${LIB_NAME}.so ${PKG_BUILD}/${LIB_NAME}.so.${VDR_APIVERSION} +} diff --git a/packages/addons/addon-depends/vdr-plugins/vdr-plugin-eepg/package.mk b/packages/addons/addon-depends/vdr-plugins/vdr-plugin-eepg/package.mk new file mode 100644 index 0000000000..aa21a65201 --- /dev/null +++ b/packages/addons/addon-depends/vdr-plugins/vdr-plugin-eepg/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) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="vdr-plugin-eepg" +PKG_VERSION="0.0.7" +PKG_SHA256="7ef5ffb0eb26895561215a7e24e4a33123d626c19d59cc0d1ea013c07209bc40" +PKG_LICENSE="GPL" +PKG_SITE="http://projects.vdr-developer.org/projects/plg-eepg" +PKG_URL="https://github.com/vdr-projects/vdr-plugin-eepg/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain vdr" +PKG_NEED_UNPACK="$(get_pkg_directory vdr)" +PKG_LONGDESC="This plugin parses the Extended EPG data which is send by providers on their portal channels." +PKG_TOOLCHAIN="manual" + +make_target() { + VDR_DIR=$(get_build_dir vdr) + export PKG_CONFIG_PATH=${VDR_DIR}:${PKG_CONFIG_PATH} + export CPLUS_INCLUDE_PATH=${VDR_DIR}/include + + make \ + LIBDIR="." \ + LOCDIR="./locale" \ + all install-i18n +} + +post_make_target() { + VDR_DIR=$(get_build_dir vdr) + VDR_APIVERSION=$(sed -ne '/define APIVERSION/s/^.*"\(.*\)".*$/\1/p' ${VDR_DIR}/config.h) + LIB_NAME=lib${PKG_NAME/-plugin/} + + cp --remove-destination ${PKG_BUILD}/${LIB_NAME}.so ${PKG_BUILD}/${LIB_NAME}.so.${VDR_APIVERSION} +} diff --git a/packages/addons/addon-depends/vdr-plugins/vdr-plugin-epgfixer/package.mk b/packages/addons/addon-depends/vdr-plugins/vdr-plugin-epgfixer/package.mk new file mode 100644 index 0000000000..c496b454e0 --- /dev/null +++ b/packages/addons/addon-depends/vdr-plugins/vdr-plugin-epgfixer/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) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="vdr-plugin-epgfixer" +PKG_VERSION="e88b67b9e9c8ed98b78a6214ab54247020d3b302" +PKG_SHA256="80ae82ec568781e84baa753b522309a76f239da1e02eba3d73c59422345bd7a9" +PKG_LICENSE="GPL" +PKG_SITE="http://projects.vdr-developer.org/projects/plg-epgfixer" +PKG_URL="https://github.com/vdr-projects/vdr-plugin-epgfixer/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain vdr pcre2" +PKG_NEED_UNPACK="$(get_pkg_directory vdr)" +PKG_LONGDESC="Plugin for modifying EPG data using regular expressions." +PKG_TOOLCHAIN="manual" + +make_target() { + VDR_DIR=$(get_build_dir vdr) + export PKG_CONFIG_PATH=${VDR_DIR}:${PKG_CONFIG_PATH} + export CPLUS_INCLUDE_PATH=${VDR_DIR}/include + + make \ + LIBDIR="." \ + LOCDIR="./locale" \ + all install-i18n +} + +post_make_target() { + VDR_DIR=$(get_build_dir vdr) + VDR_APIVERSION=$(sed -ne '/define APIVERSION/s/^.*"\(.*\)".*$/\1/p' ${VDR_DIR}/config.h) + LIB_NAME=lib${PKG_NAME/-plugin/} + + cp --remove-destination ${PKG_BUILD}/${LIB_NAME}.so ${PKG_BUILD}/${LIB_NAME}.so.${VDR_APIVERSION} +} diff --git a/packages/addons/addon-depends/vdr-plugins/vdr-plugin-epgsearch/package.mk b/packages/addons/addon-depends/vdr-plugins/vdr-plugin-epgsearch/package.mk new file mode 100644 index 0000000000..2c1c6f1a95 --- /dev/null +++ b/packages/addons/addon-depends/vdr-plugins/vdr-plugin-epgsearch/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) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="vdr-plugin-epgsearch" +PKG_VERSION="2.4.3" +PKG_SHA256="3824a72be529391ce26d00f0323b9d71572855c1c660bae9d30064f42366aadf" +PKG_LICENSE="GPL" +PKG_SITE="http://winni.vdr-developer.org/epgsearch/" +PKG_URL="https://github.com/vdr-projects/vdr-plugin-epgsearch/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain vdr pcre2" +PKG_NEED_UNPACK="$(get_pkg_directory vdr)" +PKG_LONGDESC="EPGSearch is a plugin for the Video-Disc-Recorder (VDR)." +PKG_TOOLCHAIN="manual" + +make_target() { + VDR_DIR=$(get_build_dir vdr) + export PKG_CONFIG_PATH=${VDR_DIR}:${PKG_CONFIG_PATH} + export CPLUS_INCLUDE_PATH=${VDR_DIR}/include + + make \ + LIBDIR="." \ + LOCDIR="./locale" \ + all install-i18n +} + +post_make_target() { + VDR_DIR=$(get_build_dir vdr) + VDR_APIVERSION=$(sed -ne '/define APIVERSION/s/^.*"\(.*\)".*$/\1/p' ${VDR_DIR}/config.h) + LIB_NAME=lib${PKG_NAME/-plugin/} + + cp --remove-destination ${PKG_BUILD}/${LIB_NAME}.so ${PKG_BUILD}/${LIB_NAME}.so.${VDR_APIVERSION} +} diff --git a/packages/addons/addon-depends/vdr-plugins/vdr-plugin-iptv/package.mk b/packages/addons/addon-depends/vdr-plugins/vdr-plugin-iptv/package.mk new file mode 100644 index 0000000000..d0519aa97b --- /dev/null +++ b/packages/addons/addon-depends/vdr-plugins/vdr-plugin-iptv/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) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="vdr-plugin-iptv" +PKG_VERSION="f80cd74389576abea552311bade45363247a1c32" +PKG_SHA256="b26ac5b96f573cf405ad8a6f2fe81cced67c261fcb941f74a588f99fe2fef464" +PKG_LICENSE="GPL" +PKG_SITE="http://www.saunalahti.fi/~rahrenbe/vdr/iptv/" +PKG_URL="https://github.com/Zabrimus/vdr-plugin-iptv/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain vdr curl" +PKG_NEED_UNPACK="$(get_pkg_directory vdr)" +PKG_LONGDESC="vdr-iptv is an IPTV plugin for the Video Disk Recorder (VDR)" +PKG_TOOLCHAIN="manual" + +make_target() { + VDR_DIR=$(get_build_dir vdr) + export PKG_CONFIG_PATH=${VDR_DIR}:${PKG_CONFIG_PATH} + export CPLUS_INCLUDE_PATH=${VDR_DIR}/include + + make \ + LIBDIR="." \ + LOCDIR="./locale" \ + all install-i18n +} + +post_make_target() { + VDR_DIR=$(get_build_dir vdr) + VDR_APIVERSION=$(sed -ne '/define APIVERSION/s/^.*"\(.*\)".*$/\1/p' ${VDR_DIR}/config.h) + LIB_NAME=lib${PKG_NAME/-plugin/} + + cp --remove-destination ${PKG_BUILD}/${LIB_NAME}.so ${PKG_BUILD}/${LIB_NAME}.so.${VDR_APIVERSION} +} diff --git a/packages/addons/addon-depends/vdr-plugins/vdr-plugin-live/package.mk b/packages/addons/addon-depends/vdr-plugins/vdr-plugin-live/package.mk new file mode 100644 index 0000000000..1c31f4322d --- /dev/null +++ b/packages/addons/addon-depends/vdr-plugins/vdr-plugin-live/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) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="vdr-plugin-live" +PKG_VERSION="3.5.1" +PKG_SHA256="364a6b0deed95bbcb41fa5360ad2c0a1fb40d3a47dae9aed78d7aae468d976b3" +PKG_LICENSE="GPL" +PKG_SITE="http://live.vdr-developer.org/en/index.php" +PKG_URL="https://github.com/MarkusEh/vdr-plugin-live/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain vdr tntnet pcre2" +PKG_NEED_UNPACK="$(get_pkg_directory vdr)" +PKG_LONGDESC="Allows a comfortable operation of VDR and some of its plugins through a web interface." +PKG_TOOLCHAIN="manual" +PKG_BUILD_FLAGS="+pic -parallel" + +pre_configure_target() { + export LDFLAGS="${LDFLAGS} -L${SYSROOT_PREFIX}/usr/lib/iconv" +} + +make_target() { + VDR_DIR=$(get_build_dir vdr) + export CPLUS_INCLUDE_PATH=${VDR_DIR}/include + VDR_APIVERSION=$(sed -ne '/define APIVERSION/s/^.*"\(.*\)".*$/\1/p' ${VDR_DIR}/config.h) + LIB_NAME=lib${PKG_NAME/-plugin/} + + make VDRDIR=${VDR_DIR} \ + LIBDIR="." \ + LOCALEDIR="./locale" \ + all install-i18n + + cp --remove-destination ${PKG_BUILD}/${LIB_NAME}.so ${PKG_BUILD}/${LIB_NAME}.so.${VDR_APIVERSION} +} diff --git a/packages/addons/addon-depends/vdr-plugins/vdr-plugin-restfulapi/package.mk b/packages/addons/addon-depends/vdr-plugins/vdr-plugin-restfulapi/package.mk new file mode 100644 index 0000000000..ac4dab3be3 --- /dev/null +++ b/packages/addons/addon-depends/vdr-plugins/vdr-plugin-restfulapi/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="vdr-plugin-restfulapi" +PKG_VERSION="be8a3a60af7e8926cb28c06e6b6d2adc2c2ed968" +PKG_SHA256="18cb9b6735f5ac2060ecedd6043a09bc742bd5132f33ef8a0155ddfe266b9dc2" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/yavdr/vdr-plugin-restfulapi" +PKG_URL="https://github.com/yavdr/${PKG_NAME}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain vdr cxxtools vdr-plugin-wirbelscan" +PKG_NEED_UNPACK="$(get_pkg_directory vdr) $(get_pkg_directory vdr-plugin-wirbelscan)" +PKG_LONGDESC="Allows to access many internals of the VDR via a restful API." +PKG_TOOLCHAIN="manual" + +pre_build_target() { + cp $(get_build_dir vdr-plugin-wirbelscan)/wirbelscan_services.h ${PKG_BUILD}/wirbelscan/ +} + +make_target() { + VDR_DIR=$(get_build_dir vdr) + export PKG_CONFIG_PATH=${VDR_DIR}:${PKG_CONFIG_PATH} + export CPLUS_INCLUDE_PATH=${VDR_DIR}/include + + make \ + LIBDIR="." \ + LOCDIR="./locale" \ + all install-i18n \ + USE_LIBMAGICKPLUSPLUS=0 +} + +post_make_target() { + VDR_DIR=$(get_build_dir vdr) + VDR_APIVERSION=$(sed -ne '/define APIVERSION/s/^.*"\(.*\)".*$/\1/p' ${VDR_DIR}/config.h) + LIB_NAME=lib${PKG_NAME/-plugin/} + + cp --remove-destination ${PKG_BUILD}/${LIB_NAME}.so ${PKG_BUILD}/${LIB_NAME}.so.${VDR_APIVERSION} +} diff --git a/packages/addons/addon-depends/vdr-plugins/vdr-plugin-robotv/package.mk b/packages/addons/addon-depends/vdr-plugins/vdr-plugin-robotv/package.mk new file mode 100644 index 0000000000..843b0c5ef2 --- /dev/null +++ b/packages/addons/addon-depends/vdr-plugins/vdr-plugin-robotv/package.mk @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="vdr-plugin-robotv" +PKG_VERSION="0.15.0" +PKG_SHA256="96ca5136ec8d82e4f8100889f3099f677dffdd0e85a1239d623c66420114dd36" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/pipelka/roboTV" +PKG_URL="https://github.com/pipelka/vdr-plugin-robotv/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain vdr avahi" +PKG_NEED_UNPACK="$(get_pkg_directory vdr)" +PKG_LONGDESC="RoboTV is a Android TV based frontend for VDR." + +pre_configure_target() { + VDR_DIR=$(get_build_dir vdr) + export PKG_CONFIG_PATH=${VDR_DIR}:${PKG_CONFIG_PATH} + export CPLUS_INCLUDE_PATH=${VDR_DIR}/include + export VDRDIR=${VDR_DIR} +} + +post_make_target() { + VDR_DIR=$(get_build_dir vdr) + VDR_APIVERSION=$(sed -ne '/define APIVERSION/s/^.*"\(.*\)".*$/\1/p' ${VDR_DIR}/config.h) + LIB_NAME=lib${PKG_NAME/-plugin/} + + cp --remove-destination ${PKG_BUILD}/.${TARGET_NAME}/${LIB_NAME}.so ${PKG_BUILD}/${LIB_NAME}.so.${VDR_APIVERSION} +} diff --git a/packages/addons/addon-depends/vdr-plugins/vdr-plugin-satip/package.mk b/packages/addons/addon-depends/vdr-plugins/vdr-plugin-satip/package.mk new file mode 100644 index 0000000000..91da3372d4 --- /dev/null +++ b/packages/addons/addon-depends/vdr-plugins/vdr-plugin-satip/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) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="vdr-plugin-satip" +PKG_VERSION="20250621" +PKG_SHA256="25e91ca2cd22fdb9f445395579f39054fddab31c06982a7c5a96fa851c56067f" +PKG_LICENSE="GPL" +PKG_SITE="https://vdr-projects.github.io/" +PKG_URL="https://github.com/wirbel-at-vdr-portal/vdr-plugin-satip/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain vdr curl librepfunc tinyxml" +PKG_NEED_UNPACK="$(get_pkg_directory vdr)" +PKG_LONGDESC="This is an SAT>IP plugin for the Video Disk Recorder (VDR)." +PKG_TOOLCHAIN="manual" + +make_target() { + VDR_DIR=$(get_build_dir vdr) + export PKG_CONFIG_PATH=${VDR_DIR}:${PKG_CONFIG_PATH} + export CPLUS_INCLUDE_PATH=${VDR_DIR}/include:$(get_install_dir librepfunc)/usr/include + export LDFLAGS+=" -L$(get_install_dir librepfunc)/usr/lib" + + make \ + SATIP_USE_TINYXML=1 \ + LIBDIR="." \ + LOCDIR="./locale" \ + all install-i18n +} + +post_make_target() { + VDR_DIR=$(get_build_dir vdr) + VDR_APIVERSION=$(sed -ne '/define APIVERSION/s/^.*"\(.*\)".*$/\1/p' ${VDR_DIR}/config.h) + LIB_NAME=lib${PKG_NAME/-plugin/} + + cp --remove-destination ${PKG_BUILD}/${LIB_NAME}.so ${PKG_BUILD}/${LIB_NAME}.so.${VDR_APIVERSION} +} diff --git a/packages/addons/addon-depends/vdr-plugins/vdr-plugin-streamdev/package.mk b/packages/addons/addon-depends/vdr-plugins/vdr-plugin-streamdev/package.mk new file mode 100644 index 0000000000..61e5ea6d44 --- /dev/null +++ b/packages/addons/addon-depends/vdr-plugins/vdr-plugin-streamdev/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) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="vdr-plugin-streamdev" +PKG_VERSION="0.6.4" +PKG_SHA256="1698afccb5fde1ea4e40794ae187fa42ce7fc38af48c12ecd3fa1d3154c6c794" +PKG_LICENSE="GPL" +PKG_SITE="http://projects.vdr-developer.org/projects/plg-streamdev" +PKG_URL="https://github.com/vdr-projects/vdr-plugin-streamdev/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain vdr openssl" +PKG_NEED_UNPACK="$(get_pkg_directory vdr)" +PKG_LONGDESC="This PlugIn is a VDR implementation of Video Transfer and a basic HTTP Streaming Protocol." +PKG_TOOLCHAIN="manual" + +make_target() { + VDR_DIR=$(get_build_dir vdr) + export PKG_CONFIG_PATH=${VDR_DIR}:${PKG_CONFIG_PATH} + export CPLUS_INCLUDE_PATH=${VDR_DIR}/include + + make \ + LIBDIR="." \ + LOCDIR="./locale" \ + all +} + +post_make_target() { + VDR_DIR=$(get_build_dir vdr) + VDR_APIVERSION=$(sed -ne '/define APIVERSION/s/^.*"\(.*\)".*$/\1/p' ${VDR_DIR}/config.h) + LIB_NAME=lib${PKG_NAME/-plugin/} + cp --remove-destination ${PKG_BUILD}/server/${LIB_NAME}-server.so ${PKG_BUILD}/server/${LIB_NAME}-server.so.${VDR_APIVERSION} + cp --remove-destination ${PKG_BUILD}/client/${LIB_NAME}-client.so ${PKG_BUILD}/client/${LIB_NAME}-client.so.${VDR_APIVERSION} +} diff --git a/packages/addons/addon-depends/vdr-plugins/vdr-plugin-vnsiserver/package.mk b/packages/addons/addon-depends/vdr-plugins/vdr-plugin-vnsiserver/package.mk new file mode 100644 index 0000000000..fc3235048b --- /dev/null +++ b/packages/addons/addon-depends/vdr-plugins/vdr-plugin-vnsiserver/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="vdr-plugin-vnsiserver" +PKG_VERSION="65bfc62b16ffd278f40eb35a749fb3d1f467e112" +PKG_SHA256="e34533c0aed3f6e1dac3bfb608509df532089736ff04632d762438d796d339db" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/vdr-projects/vdr-plugin-vnsiserver" +PKG_URL="https://github.com/vdr-projects/vdr-plugin-vnsiserver/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain vdr" +PKG_DEPENDS_UNPACK="vdr-plugin-wirbelscan" +PKG_NEED_UNPACK="$(get_pkg_directory vdr) $(get_pkg_directory vdr-plugin-wirbelscan)" +PKG_LONGDESC="VDR plugin to handle Kodi clients." +PKG_TOOLCHAIN="manual" + +pre_build_target() { + WIRBELSCAN_DIR=$(get_build_dir vdr-plugin-wirbelscan) + ln -sf ${WIRBELSCAN_DIR}/wirbelscan_services.h ${PKG_BUILD} +} + +make_target() { + VDR_DIR=$(get_build_dir vdr) + export PKG_CONFIG_PATH=${VDR_DIR}:${PKG_CONFIG_PATH} + export CPLUS_INCLUDE_PATH=${VDR_DIR}/include + + make \ + LIBDIR="." \ + LOCDIR="./locale" \ + all install-i18n +} + +post_make_target() { + VDR_DIR=$(get_build_dir vdr) + VDR_APIVERSION=$(sed -ne '/define APIVERSION/s/^.*"\(.*\)".*$/\1/p' ${VDR_DIR}/config.h) + LIB_NAME=lib${PKG_NAME/-plugin/} + + cp --remove-destination ${PKG_BUILD}/${LIB_NAME}.so ${PKG_BUILD}/${LIB_NAME}.so.${VDR_APIVERSION} +} diff --git a/packages/addons/addon-depends/vdr-plugins/vdr-plugin-wirbelscan/package.mk b/packages/addons/addon-depends/vdr-plugins/vdr-plugin-wirbelscan/package.mk new file mode 100644 index 0000000000..23f02ef05e --- /dev/null +++ b/packages/addons/addon-depends/vdr-plugins/vdr-plugin-wirbelscan/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="vdr-plugin-wirbelscan" +PKG_VERSION="2024.09.15" +PKG_SHA256="22317c5a919834d70aee309248e7fb8b9f458819dee0e5ccdbedee7fdada8913" +PKG_LICENSE="GPL" +PKG_SITE="https://www.gen2vdr.de/wirbel/wirbelscan/index2.html" +PKG_URL="https://www.gen2vdr.de/wirbel/wirbelscan/vdr-wirbelscan-${PKG_VERSION}.tgz" +PKG_DEPENDS_TARGET="toolchain vdr librepfunc" +PKG_NEED_UNPACK="$(get_pkg_directory vdr)" +PKG_LONGDESC="Performs a channel scans for DVB-T, DVB-C and DVB-S" +PKG_TOOLCHAIN="manual" +PKG_BUILD_FLAGS="+pic" + +configure_target() { + export PKG_CONFIG_PATH="$(get_install_dir librepfunc)/usr/lib/pkgconfig:${PKG_CONFIG_PATH}" +} + +make_target() { + VDR_DIR=$(get_build_dir vdr) + make VDRDIR=${VDR_DIR} \ + LIBDIR="." \ + LOCALEDIR="./locale" +} diff --git a/packages/addons/addon-depends/vdr-plugins/vdr-plugin-wirbelscancontrol/package.mk b/packages/addons/addon-depends/vdr-plugins/vdr-plugin-wirbelscancontrol/package.mk new file mode 100644 index 0000000000..f3ad5b79db --- /dev/null +++ b/packages/addons/addon-depends/vdr-plugins/vdr-plugin-wirbelscancontrol/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) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="vdr-plugin-wirbelscancontrol" +PKG_VERSION="0.0.3" +PKG_SHA256="93418d31bb757cccea9f81edd13a3e84ca0cf239c30252afbf0ced68e9ef6bd5" +PKG_LICENSE="GPL" +PKG_SITE="https://www.gen2vdr.de/wirbel/wirbelscancontrol/index2.html" +PKG_URL="https://www.gen2vdr.de/wirbel/wirbelscancontrol/${PKG_NAME/-plugin/}-${PKG_VERSION}.tgz" +PKG_DEPENDS_TARGET="toolchain vdr gettext:host vdr-plugin-wirbelscan" +PKG_NEED_UNPACK="$(get_pkg_directory vdr)" +PKG_LONGDESC="Adds menu entry for wirbelscan at VDR." +PKG_TOOLCHAIN="manual" +PKG_BUILD_FLAGS="+pic" + +pre_build_target() { + WIRBELSCAN_DIR=$(get_build_dir vdr-plugin-wirbelscan) + ln -sf ${WIRBELSCAN_DIR}/wirbelscan_services.h ${PKG_BUILD} + ln -sf $(get_build_dir vdr) ${PKG_BUILD}/vdr +} + +make_target() { + VDR_DIR=$(get_build_dir vdr) + make VDRDIR=${VDR_DIR} \ + INCLUDES="-I." \ + LIBDIR="." \ + LOCALEDIR="./locale" \ + install +} diff --git a/packages/addons/addon-depends/vdr-plugins/vdr-plugin-xmltv2vdr/package.mk b/packages/addons/addon-depends/vdr-plugins/vdr-plugin-xmltv2vdr/package.mk new file mode 100644 index 0000000000..dcf13af746 --- /dev/null +++ b/packages/addons/addon-depends/vdr-plugins/vdr-plugin-xmltv2vdr/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) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="vdr-plugin-xmltv2vdr" +PKG_VERSION="0.2.4" +PKG_SHA256="6ed8886f5f6fc97b136cbe26e380ed3a8083300318db934e001a4918617a9785" +PKG_LICENSE="GPL" +PKG_SITE="http://projects.vdr-developer.org/projects/plg-xmltv2vdr" +PKG_URL="https://github.com/vdr-projects/vdr-plugin-xmltv2vdr/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain vdr sqlite openssl curl libzip libxml2 libxslt enca" +PKG_NEED_UNPACK="$(get_pkg_directory vdr)" +PKG_LONGDESC="xmltv2vdr imports data in xmltv format" +PKG_TOOLCHAIN="manual" +PKG_BUILD_FLAGS="+pic" + +pre_configure_target() { + export CXXFLAGS="${CXXFLAGS} -Wno-narrowing" + export LIBS="-L${SYSROOT_PREFIX}/usr/lib/iconv -lssl -lcrypto -lbz2" +} + +make_target() { + VDR_DIR=$(get_build_dir vdr) + make VDRDIR=${VDR_DIR} \ + LIBDIR="." \ + LOCALEDIR="./locale" \ + install +} + +post_make_target() { + cd dist/epgdata2xmltv + make -j1 + cd - + ${STRIP} dist/epgdata2xmltv/epgdata2xmltv +} diff --git a/packages/addons/addon-depends/vdr/package.mk b/packages/addons/addon-depends/vdr/package.mk new file mode 100644 index 0000000000..f577fbeb72 --- /dev/null +++ b/packages/addons/addon-depends/vdr/package.mk @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2011 Anthony Nash (nash.ant@gmail.com) +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="vdr" +PKG_VERSION="2.7.6" +PKG_SHA256="06c8ba921277129970308fb15db1c66d7c2874fd77fcff3aa1ca77b82ccb03de" +PKG_LICENSE="GPL" +PKG_SITE="http://www.tvdr.de" +PKG_URL="http://git.tvdr.de/?p=vdr.git;a=snapshot;h=refs/tags/${PKG_VERSION};sf=tbz2" +PKG_SOURCE_NAME="${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain bzip2 fontconfig freetype libcap libiconv libjpeg-turbo" +PKG_LONGDESC="A DVB TV server application." +PKG_TOOLCHAIN="manual" + +post_unpack() { + rm -rf ${PKG_BUILD}/PLUGINS/src/skincurses +} + +pre_configure_target() { + export LDFLAGS="$(echo ${LDFLAGS} | sed -e "s|-Wl,--as-needed||") -L${SYSROOT_PREFIX}/usr/lib/iconv" +} + +pre_make_target() { + cat >Make.config </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 audio devices + case $(dtsoc) in + amlogic,g12* | amlogic,sm1) + # AXG HDMI // Logic assumes TDMOUT_A is not present in device-tree when TDMOUT_B is used + TDMOUT=$(awk '/TDMOUT/ && $2=="OUT" {print substr($1,length($1),1)}' /sys/firmware/devicetree/base/sound/audio-routing | sort | head -n 1) + if [ "${TDMOUT}" = "A" ]; then + 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' + elif [ "${TDMOUT}" = "B" ]; then + 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' + fi + # AXG S/PDIF + SPDIFOUT=$(awk '/SPDIF/' /sys/firmware/devicetree/base/sound/audio-routing | sort | head -n 1) + if [ -n "${SPDIFOUT}" ]; then + 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 + fi + # AXG Headphone Jack + ACODEC=$(awk '/ACODEC/' /sys/firmware/devicetree/base/sound/audio-routing | sort | head -n 1) + if [ -n "${ACODEC}" ]; then + mixer "$card" 'TOACODEC OUT EN' on + mixer "$card" 'TOACODEC SRC' 'I2S ${TDMOUT}' + mixer "$card" 'ACODEC Playback Switch' on + mixer "$card" 'ACODEC Playback Channel Mode' Stereo + fi + ;; + amlogic,meson-gx*) + # AIU HDMI and S/PDIF + mixer "$card" 'AIU HDMI CTRL SRC' 'I2S' + mixer "$card" 'AIU SPDIF SRC SEL' 'SPDIF' + # AIU ACODEC headphone jack + mixer "$card" 'ACODEC' 80% on + mixer "$card" 'AIU ACODEC SRC' 'I2S' + mixer "$card" 'AIU ACODEC OUT EN' on + ;; + esac + + # ES8316 headphone jack + mixer "$card" 'Right Headphone Mixer Right DAC' on + mixer "$card" 'Left Headphone Mixer Left DAC' on + 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 0000000000..3fa0a600bf --- /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-ng/package.mk b/packages/audio/espeak-ng/package.mk new file mode 100644 index 0000000000..bd070246e5 --- /dev/null +++ b/packages/audio/espeak-ng/package.mk @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="espeak-ng" +PKG_VERSION="348599e02bf0db105ac6fd07693e4047f614a58e" +PKG_SHA256="f12884158f1e6c3727bcc340f2459a0a5481f8e02f7c35dbd69dae936f064d1c" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/espeak-ng/espeak-ng" +PKG_URL="https://github.com/espeak-ng/espeak-ng/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="gcc:host" +PKG_DEPENDS_TARGET="toolchain espeak-ng:host" +PKG_LONGDESC="eSpeak NG is an open source speech synthesizer that supports more than a hundred languages and accents" +PKG_BUILD_FLAGS="+pic" + +PKG_CMAKE_OPTS_HOST="-DBUILD_SHARED_LIBS=OFF \ + -DCOMPILE_INTONATIONS=OFF \ + -DENABLE_TESTS=OFF" + +PKG_CMAKE_OPTS_TARGET="-DBUILD_SHARED_LIBS=ON \ + -DCOMPILE_INTONATIONS=ON \ + -DENABLE_TESTS=OFF \ + -DNativeBuild_DIR=${TOOLCHAIN}/bin" + +post_makeinstall_target() { + safe_remove ${INSTALL}/usr/share/vim + + # add symlink for backwards compatibility with old programs + ln -sf espeak-ng ${INSTALL}/usr/bin/espeak +} diff --git a/packages/audio/fdk-aac/package.mk b/packages/audio/fdk-aac/package.mk new file mode 100644 index 0000000000..3c9a52409b --- /dev/null +++ b/packages/audio/fdk-aac/package.mk @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2023-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="fdk-aac" +PKG_VERSION="2.0.3" +PKG_SHA256="e25671cd96b10bad896aa42ab91a695a9e573395262baed4e4a2ff178d6a3a78" +PKG_LICENSE="fdk-aac" +PKG_SITE="https://github.com/mstorsjo/fdk-aac" +PKG_URL="https://github.com/mstorsjo/fdk-aac/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A standalone library of the Fraunhofer FDK AAC code from Android." diff --git a/packages/audio/flac/package.mk b/packages/audio/flac/package.mk new file mode 100644 index 0000000000..aec918f989 --- /dev/null +++ b/packages/audio/flac/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) 2020-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="flac" +PKG_VERSION="1.5.0" +PKG_SHA256="f2c1c76592a82ffff8413ba3c4a1299b6c7ab06c734dee03fd88630485c2b920" +PKG_LICENSE="GPLv2" +PKG_SITE="https://xiph.org/flac/" +PKG_URL="https://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 -cfg-libs" + +# package specific configure options +PKG_CONFIGURE_OPTS_TARGET="--enable-static \ + --disable-shared \ + --disable-rpath \ + --disable-doxygen-docs \ + --disable-thorough-tests \ + --disable-cpplibs \ + --disable-oggtest \ + --with-ogg=${SYSROOT_PREFIX}/usr \ + --with-gnu-ld" + +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 0000000000..3280223d77 --- /dev/null +++ b/packages/audio/fluidsynth/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="fluidsynth" +PKG_VERSION="2.4.6" +PKG_SHA256="a6be90fd4842b9e7246500597180af5cf213c11bfa3998a3236dd8ff47961ea8" +PKG_LICENSE="GPL" +PKG_SITE="http://fluidsynth.org/" +PKG_URL="https://github.com/FluidSynth/fluidsynth/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain glib libsndfile" +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 \ + -Denable-libsndfile=1 \ + -Denable-pulseaudio=0 \ + -Denable-readline=0" diff --git a/packages/audio/fluidsynth/patches/libsndfile-use-static-libraries.patch b/packages/audio/fluidsynth/patches/libsndfile-use-static-libraries.patch new file mode 100644 index 0000000000..e9a9432ca9 --- /dev/null +++ b/packages/audio/fluidsynth/patches/libsndfile-use-static-libraries.patch @@ -0,0 +1,10 @@ +--- a/CMakeLists.txt 2023-04-02 15:54:17.000000000 +0000 ++++ b/CMakeLists.txt 2023-04-14 15:18:28.037536898 +0000 +@@ -539,6 +539,7 @@ + list( APPEND PC_REQUIRES_PRIV "sndfile") + if ( SndFile_WITH_EXTERNAL_LIBS ) + set ( LIBSNDFILE_HASVORBIS 1 ) ++ set ( LIBSNDFILE_LIBRARIES ${LIBSNDFILE_STATIC_LIBRARIES} ) + else (SndFile_WITH_EXTERNAL_LIBS) + message ( NOTICE "Seems like libsndfile was compiled without OGG/Vorbis support." ) + endif (SndFile_WITH_EXTERNAL_LIBS) diff --git a/packages/audio/lame/package.mk b/packages/audio/lame/package.mk new file mode 100644 index 0000000000..f15b34b017 --- /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.100" +PKG_SHA256="ddfe36cab873794038ae2c1210557ad34857a4b6bdc515785d1da9e175b1da1e" +PKG_LICENSE="LGPL" +PKG_SITE="http://lame.sourceforge.net/" +PKG_URL="${SOURCEFORGE_SRC}/lame/lame/3.100/${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/ldacBT/package.mk b/packages/audio/ldacBT/package.mk new file mode 100644 index 0000000000..00000989ce --- /dev/null +++ b/packages/audio/ldacBT/package.mk @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="ldacBT" +PKG_VERSION="2.0.2.3" +PKG_SHA256="c02998718f9c4620437d7594b4d121b3ab4c5cfeba8d41fa31dd5c71db09edca" +PKG_LICENSE="Apache" +PKG_SITE="https://github.com/EHfive/ldacBT" +PKG_URL="https://github.com/EHfive/ldacBT/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_DEPENDS_UNPACK="libldac" +PKG_LONGDESC="LDAC Bluetooth encoder library (build tools)" + +PKG_CMAKE_OPTS_TARGET="-DLDAC_SOFT_FLOAT=OFF" + +post_unpack() { + rm -rf ${PKG_BUILD}/libldac + ln -sf $(get_build_dir libldac) ${PKG_BUILD}/libldac +} diff --git a/packages/audio/ldacBT/patches/ldacBT-1-build-with-cmake-4.0.0.patch b/packages/audio/ldacBT/patches/ldacBT-1-build-with-cmake-4.0.0.patch new file mode 100644 index 0000000000..ab3c66fc83 --- /dev/null +++ b/packages/audio/ldacBT/patches/ldacBT-1-build-with-cmake-4.0.0.patch @@ -0,0 +1,22 @@ +From 7c6911cd9dc4459807c345f693bcbeafb4307059 Mon Sep 17 00:00:00 2001 +From: Rudi Heitbaum +Date: Tue, 15 Apr 2025 00:01:39 +1000 +Subject: [PATCH] Allow build with CMake 4.0.0 + +use min...max syntax to allow build with newer cmake. + +ref: https://cmake.org/cmake/help/latest/command/cmake_minimum_required.html +--- + CMakeLists.txt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 7739887..ecbf6da 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -1,4 +1,4 @@ +-cmake_minimum_required(VERSION 3.0) ++cmake_minimum_required(VERSION 3.0...3.10) + project(libldac + LANGUAGES C + VERSION 2.0.2.3) diff --git a/packages/audio/libcdio/package.mk b/packages/audio/libcdio/package.mk new file mode 100644 index 0000000000..7a21196a35 --- /dev/null +++ b/packages/audio/libcdio/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) 2020-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libcdio" +PKG_VERSION="2.2.0" +PKG_SHA256="6f8fbdf4d189cf63f2a7a1549c516cd720c7b222c7aaadbc924a26e745a48539" +PKG_LICENSE="GPLv3" +PKG_SITE="https://www.gnu.org/software/libcdio/" +PKG_URL="https://github.com/libcdio/libcdio/releases/download/${PKG_VERSION}/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +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/libcdio/patches/0002-remove-lfs-shms.patch b/packages/audio/libcdio/patches/0002-remove-lfs-shms.patch new file mode 100644 index 0000000000..afe1310477 --- /dev/null +++ b/packages/audio/libcdio/patches/0002-remove-lfs-shms.patch @@ -0,0 +1,87 @@ +From 79a15b760e0b5e81b29953acada3a963c3f8eba9 Mon Sep 17 00:00:00 2001 +From: Alfred Wingate +Date: Mon, 20 May 2024 22:02:08 +0300 +Subject: [PATCH] Do not use LFS shims, rely on _FILE_OFFSET_BITS=64 + +See https://savannah.gnu.org/bugs/?65751 and https://bugs.gentoo.org/918988 + +Setting _FILE_OFFSET_BITS=64 is enough to get the LFS interface, +using LFS shims is unnecessary on 64-bit systems and they may +not be available on 32-bit systems on glibc. + +Signed-off-by: Alfred Wingate +--- + configure.ac | 8 ++++---- + lib/driver/_cdio_generic.c | 12 +----------- + lib/driver/_cdio_stdio.c | 6 +----- + 3 files changed, 6 insertions(+), 20 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 0399a718..5ea300fe 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -547,10 +547,10 @@ AC_DEFINE_UNQUOTED(LIBCDIO_SOURCE_PATH, "$LIBCDIO_SOURCE_PATH", + [Full path to libcdio top_sourcedir.]) + AC_SUBST(LIBCDIO_SOURCE_PATH) + +-AC_CHECK_FUNCS( [chdir drand48 fseeko fseeko64 ftruncate geteuid getgid \ +- getuid getpwuid gettimeofday lseek64 lstat memcpy memset mkstemp rand \ +- seteuid setegid snprintf setenv strndup unsetenv tzset sleep \ +- _stati64 usleep vsnprintf readlink realpath gmtime_r localtime_r] ) ++AC_CHECK_FUNCS( [chdir drand48 fseeko ftruncate geteuid getgid getuid \ ++ getpwuid gettimeofday lstat memcpy memset mkstemp rand seteuid \ ++ setegid snprintf setenv strndup unsetenv tzset sleep _stati64 \ ++ usleep vsnprintf readlink realpath gmtime_r localtime_r] ) + + # check for timegm() support + AC_CHECK_FUNC(timegm, AC_DEFINE(HAVE_TIMEGM,1, +diff --git a/lib/driver/_cdio_generic.c b/lib/driver/_cdio_generic.c +index 4a7fcadf..f5c8c402 100644 +--- a/lib/driver/_cdio_generic.c ++++ b/lib/driver/_cdio_generic.c +@@ -55,16 +55,6 @@ + #define PATH_MAX 4096 + #endif + +-/* If available and LFS is enabled, try to use lseek64 */ +-#if defined(HAVE_LSEEK64) && defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64) +-#if defined(_MSC_VER) +-#include +-#endif +-#define CDIO_LSEEK lseek64 +-#else +-#define CDIO_LSEEK lseek +-#endif +- + /*! + Eject media -- there's nothing to do here. We always return -2. + Should we also free resources? +@@ -170,7 +160,7 @@ off_t + cdio_generic_lseek (void *user_data, off_t offset, int whence) + { + generic_img_private_t *p_env = user_data; +- return CDIO_LSEEK(p_env->fd, offset, whence); ++ return lseek(p_env->fd, offset, whence); + } + + /*! +diff --git a/lib/driver/_cdio_stdio.c b/lib/driver/_cdio_stdio.c +index 1d46b156..c26a35d0 100644 +--- a/lib/driver/_cdio_stdio.c ++++ b/lib/driver/_cdio_stdio.c +@@ -47,11 +47,7 @@ + #include "_cdio_stdio.h" + #include "cdio_assert.h" + +-/* On 32 bit platforms, fseek can only access streams of 2 GB or less. +- Prefer fseeko/fseeko64, that take a 64 bit offset when LFS is enabled */ +-#if defined(HAVE_FSEEKO64) && defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64) +-#define CDIO_FSEEK fseeko64 +-#elif defined(HAVE_FSEEKO) ++#if defined(HAVE_FSEEKO) + #define CDIO_FSEEK fseeko + #else + #define CDIO_FSEEK fseek +-- +2.45.1 + diff --git a/packages/audio/libfreeaptx/package.mk b/packages/audio/libfreeaptx/package.mk new file mode 100644 index 0000000000..861cc56407 --- /dev/null +++ b/packages/audio/libfreeaptx/package.mk @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libfreeaptx" +PKG_VERSION="0.2.2" +PKG_SHA256="c0ed01b7e535878cc34bd1321f335e2617f2d51496b13e1036fc675c799be3b5" +PKG_LICENSE="LGPL" +PKG_SITE="https://github.com/iamthehorker/libfreeaptx" +PKG_URL="https://github.com/iamthehorker/libfreeaptx/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Open Source aptX codec library" +PKG_TOOLCHAIN="manual" +PKG_BUILD_FLAGS="+pic" + +make_target() { + ${CC} ${CFLAGS} -I${PKG_BUILD} -c -o ${PKG_NAME##*lib}.o ${PKG_NAME##*lib}.c + ${AR} -rcs ${PKG_NAME}.a ${PKG_NAME##*lib}.o +} + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib + cp -a ${PKG_NAME}.a ${SYSROOT_PREFIX}/usr/lib/ + + mkdir -p ${SYSROOT_PREFIX}/usr/include + cp -a ${PKG_NAME##*lib}.h ${SYSROOT_PREFIX}/usr/include/ + + mkdir -p ${SYSROOT_PREFIX}/usr/lib/pkgconfig + cat >${SYSROOT_PREFIX}/usr/lib/pkgconfig/${PKG_NAME}.pc <= 3.15 + # This policy still need to be set even with cmake_minimum_required() command above. diff --git a/packages/audio/libsndfile/patches/libsndfile-add-required-static-libaries-to-pkg-config.patch b/packages/audio/libsndfile/patches/libsndfile-add-required-static-libaries-to-pkg-config.patch new file mode 100644 index 0000000000..e5220c098d --- /dev/null +++ b/packages/audio/libsndfile/patches/libsndfile-add-required-static-libaries-to-pkg-config.patch @@ -0,0 +1,10 @@ +--- a/sndfile.pc.in 2021-01-24 23:22:23.000000000 +1100 ++++ b/sndfile.pc.in 2021-09-12 14:30:47.763655089 +1000 +@@ -8,6 +8,6 @@ + Requires: + Requires.private: @EXTERNAL_XIPH_REQUIRE@ @EXTERNAL_MPEG_REQUIRE@ + Version: @VERSION@ +-Libs: -L${libdir} -lsndfile ++Libs: -L${libdir} -lsndfile -lFLAC -lvorbis -logg -lvorbisenc -lopus + Libs.private: @EXTERNAL_MPEG_LIBS@ + Cflags: -I${includedir} diff --git a/packages/audio/libvorbis/package.mk b/packages/audio/libvorbis/package.mk new file mode 100644 index 0000000000..2b72481931 --- /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="b33cc4934322bcbf6efcbacf49e3ca01aadbea4114ec9589d1b1e9d20f72954b" +PKG_LICENSE="BSD" +PKG_SITE="http://www.vorbis.com/" +PKG_URL="http://downloads.xiph.org/releases/vorbis/libvorbis-${PKG_VERSION}.tar.xz" +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 \ + --disable-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 0000000000..ccd5e89360 --- /dev/null +++ b/packages/audio/openal-soft/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="openal-soft" +PKG_VERSION="1.24.3" +PKG_SHA256="7e1fecdeb45e7f78722b776c5cf30bd33934b961d7fd2a11e0494e064cc631ce" +PKG_LICENSE="GPL" +PKG_SITE="http://www.openal.org/" +PKG_URL="https://github.com/kcat/openal-soft/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain alsa-lib" +PKG_LONGDESC="OpenAL Soft is a software implementation of the OpenAL 3D audio API." + +PKG_CMAKE_OPTS_TARGET="-DALSOFT_BACKEND_OSS=off \ + -DALSOFT_BACKEND_PULSEAUDIO=off \ + -DALSOFT_BACKEND_WAVE=off \ + -DALSOFT_EXAMPLES=off \ + -DALSOFT_UTILS=off" diff --git a/packages/audio/opus/package.mk b/packages/audio/opus/package.mk new file mode 100644 index 0000000000..0d7be28c40 --- /dev/null +++ b/packages/audio/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.5.2" +PKG_SHA256="65c1d2f78b9f2fb20082c38cbe47c951ad5839345876e46941612ee87f9a7ce1" +PKG_LICENSE="BSD" +PKG_SITE="http://www.opus-codec.org" +PKG_URL="https://github.com/xiph/opus/releases/download/v${PKG_VERSION}/${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/audio/pipewire/package.mk b/packages/audio/pipewire/package.mk new file mode 100644 index 0000000000..db4d0a7601 --- /dev/null +++ b/packages/audio/pipewire/package.mk @@ -0,0 +1,91 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="pipewire" +PKG_VERSION="1.4.6" +PKG_SHA256="0470a38cf62485f53899896efc94f538cc4e7ad69704a67d70004024a3e478ea" +PKG_LICENSE="LGPL" +PKG_SITE="https://pipewire.org" +PKG_URL="https://github.com/PipeWire/pipewire/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain alsa-lib dbus glib libpthread-stubs libsndfile libusb ncurses systemd" +PKG_LONGDESC="PipeWire is a server and user space API to deal with multimedia pipeline" + +if [ "${BLUETOOTH_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" bluez fdk-aac sbc ldacBT libfreeaptx" + PKG_PIPEWIRE_BLUETOOTH="-Dbluez5=enabled \ + -Dbluez5-backend-hsp-native=disabled \ + -Dbluez5-backend-hfp-native=disabled \ + -Dbluez5-backend-ofono=disabled \ + -Dbluez5-backend-hsphfpd=disabled \ + -Dbluez5-codec-aptx=enabled \ + -Dbluez5-codec-ldac=enabled \ + -Dbluez5-codec-aac=enabled" +else + PKG_PIPEWIRE_BLUETOOTH="-Dbluez5=disabled" +fi + +PKG_MESON_OPTS_TARGET="-Ddocs=disabled \ + -Dexamples=disabled \ + -Dman=disabled \ + -Dtests=disabled \ + -Dinstalled_tests=disabled \ + -Dgstreamer=disabled \ + -Dgstreamer-device-provider=disabled \ + -Dsystemd=enabled \ + -Dsystemd-system-service=enabled \ + -Dsystemd-user-service=disabled \ + -Dpipewire-alsa=enabled \ + -Dpipewire-jack=disabled \ + -Dpipewire-v4l2=disabled \ + -Djack-devel=false + -Dspa-plugins=enabled \ + -Dalsa=enabled \ + -Daudiomixer=enabled \ + -Daudioconvert=enabled \ + ${PKG_PIPEWIRE_BLUETOOTH} \ + -Dcontrol=enabled \ + -Daudiotestsrc=disabled \ + -Dffmpeg=disabled \ + -Djack=disabled \ + -Dsupport=enabled \ + -Devl=disabled \ + -Dtest=disabled \ + -Dv4l2=disabled \ + -Ddbus=enabled \ + -Dlibcamera=disabled \ + -Dvideoconvert=disabled \ + -Dvideotestsrc=disabled \ + -Dvolume=enabled \ + -Dvulkan=disabled \ + -Dpw-cat=enabled \ + -Dudev=enabled \ + -Dudevrulesdir=/usr/lib/udev/rules.d \ + -Dsdl2=disabled \ + -Dsndfile=enabled \ + -Dlibpulse=disabled \ + -Droc=disabled \ + -Davahi=disabled \ + -Decho-cancel-webrtc=disabled \ + -Dlibusb=enabled \ + -Dsession-managers=[] \ + -Draop=disabled \ + -Dlv2=disabled \ + -Dx11=disabled \ + -Dx11-xfixes=disabled \ + -Dlibcanberra=disabled \ + -Dlegacy-rtkit=false" + +post_makeinstall_target() { + # connect to the system bus + sed '/^\[Service\]/a Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/dbus/system_bus_socket' -i ${INSTALL}/usr/lib/systemd/system/pipewire.service +} + +post_install() { + add_user pipewire x 982 980 "pipewire-daemon" "/var/run/pipewire" "/bin/sh" + add_group pipewire 980 + # note that the pipewire user is added to the audio and video groups in systemd/package.mk + # todo: maybe there is a better way to add users to groups in the future? + + enable_service pipewire.socket + enable_service pipewire.service +} 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 0000000000..350761ed58 --- /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/system.pa b/packages/audio/pulseaudio/config/system.pa new file mode 100644 index 0000000000..653361e807 --- /dev/null +++ b/packages/audio/pulseaudio/config/system.pa @@ -0,0 +1,59 @@ +#!/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 +load-module module-native-protocol-unix + +### Automatically restore the volume of streams and devices +load-module module-stream-restore +load-module module-device-restore +load-module module-card-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 + +### 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 + +### 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 0000000000..d994b85620 --- /dev/null +++ b/packages/audio/pulseaudio/package.mk @@ -0,0 +1,102 @@ +# 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="17.0" +PKG_SHA256="053794d6671a3e397d849e478a80b82a63cb9d8ca296bd35b73317bb5ceb87b5" +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 glib libcap libsndfile libtool openssl soxr speexdsp systemd" +PKG_LONGDESC="PulseAudio is a sound system for POSIX OSes, meaning that it is a proxy for your sound applications." + +if [ "${BLUETOOTH_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" sbc bluez" + PKG_PULSEAUDIO_BLUETOOTH="-Dbluez5=enabled" +else + PKG_PULSEAUDIO_BLUETOOTH="-Dbluez5=disabled" +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="-Ddaemon=true \ + -Ddoxygen=false \ + -Dgcov=false \ + -Dman=false \ + -Dtests=false \ + -Dsystem_user=root \ + -Dsystem_group=root \ + -Daccess_group=root \ + -Ddatabase=simple \ + -Dlegacy-database-entry-format=false \ + -Dstream-restore-clear-old-devices=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-gstreamer=disabled \ + -Dbluez5-native-headset=false \ + -Dbluez5-ofono-headset=false \ + -Ddbus=enabled \ + -Delogind=disabled \ + -Dfftw=disabled \ + -Dglib=enabled \ + -Dgsettings=disabled \ + -Dgstreamer=disabled \ + -Dgtk=disabled \ + -Dhal-compat=false \ + -Dipv6=true \ + -Djack=disabled \ + -Dlirc=disabled \ + -Dopenssl=enabled \ + -Dorc=disabled \ + -Doss-output=disabled \ + -Dsamplerate=disabled \ + -Dsoxr=enabled \ + -Dspeex=enabled \ + -Dsystemd=enabled \ + -Dtcpwrap=disabled \ + -Dudev=enabled \ + -Dvalgrind=disabled \ + -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 +} + +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/ + + sed 's/user="pulse"/user="root"/' -i ${INSTALL}/usr/share/dbus-1/system.d/pulseaudio-system.conf + + 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 0000000000..8bea8d95fb --- /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 0000000000..df92750890 --- /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 0000000000..7e7b95357b --- /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 0000000000..1ec4269550 --- /dev/null +++ b/packages/audio/pulseaudio/system.d/pulseaudio.service @@ -0,0 +1,14 @@ +[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 --enable-memfd --realtime +Restart=on-failure +Environment=PULSE_STATE_PATH=/storage/.config/pulse +Environment=PULSE_CONFIG_PATH=/storage/.config/pulse + +[Install] +WantedBy=multi-user.target diff --git a/packages/audio/sbc/package.mk b/packages/audio/sbc/package.mk new file mode 100644 index 0000000000..c3b8b05832 --- /dev/null +++ b/packages/audio/sbc/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="sbc" +PKG_VERSION="2.1" +PKG_SHA256="426633cabd7c798236443516dfa8335b47e004b0ef37ff107e0c7ead3299fcc2" +PKG_LICENSE="GPL" +PKG_SITE="http://www.bluez.org/" +PKG_URL="https://www.kernel.org/pub/linux/bluetooth/sbc-${PKG_VERSION}.tar.xz" +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" + +post_makeinstall_target() { + # fix static library + sed -i 's/-lsbc/-lsbc -lbluetooth/' ${SYSROOT_PREFIX}/usr/lib/pkgconfig/sbc.pc +} diff --git a/packages/audio/sidplay-libs/package.mk b/packages/audio/sidplay-libs/package.mk new file mode 100644 index 0000000000..06640b45d6 --- /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 -cfg-libs" + +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 0000000000..88592b0b7c --- /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 0000000000..0e86eedf80 --- /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 0000000000..88af8ccd34 --- /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 0000000000..ef9cf06017 --- /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 0000000000..ebc3aa55a5 --- /dev/null +++ b/packages/audio/soxr/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="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 \ + -DWITH_OPENMP=OFF \ + -DBUILD_SHARED_LIBS=OFF \ + -DBUILD_TESTS=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/soxr-0001-build-with-cmake-4.0.0.patch b/packages/audio/soxr/patches/soxr-0001-build-with-cmake-4.0.0.patch new file mode 100644 index 0000000000..c6b01a18bc --- /dev/null +++ b/packages/audio/soxr/patches/soxr-0001-build-with-cmake-4.0.0.patch @@ -0,0 +1,11 @@ +--- a/CMakeLists.txt 2018-02-23 21:39:25.000000000 +0000 ++++ b/CMakeLists.txt 2025-03-28 00:22:35.418513539 +0000 +@@ -1,7 +1,7 @@ + # SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net + # Licence for this file: LGPL v2.1 See LICENCE for details. + +-cmake_minimum_required (VERSION 3.1 FATAL_ERROR) ++cmake_minimum_required (VERSION 3.1...3.10 FATAL_ERROR) + + project (soxr C) + set (DESCRIPTION_SUMMARY diff --git a/packages/audio/speex/package.mk b/packages/audio/speex/package.mk new file mode 100644 index 0000000000..0b9b2232a7 --- /dev/null +++ b/packages/audio/speex/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="speex" +PKG_VERSION="1.2.1" +PKG_SHA256="cc55cce69d8753940d56936f7a1fe6db4b302df144aec93a92de1c65b1a87681" +PKG_LICENSE="BSD" +PKG_SITE="https://speex.org" +PKG_URL="https://gitlab.xiph.org/xiph/speex/-/archive/Speex-${PKG_VERSION}/speex-Speex-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="An Open Source Software patent-free audio compression format designed for speech." +PKG_TOOLCHAIN="autotools" diff --git a/packages/audio/speexdsp/package.mk b/packages/audio/speexdsp/package.mk new file mode 100644 index 0000000000..d9be03381f --- /dev/null +++ b/packages/audio/speexdsp/package.mk @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="speexdsp" +PKG_VERSION="1.2.1" +PKG_SHA256="b36d4f16e42b7103b7fc3e4a8f98b6bf889dd1f70f65c2365af07be82844db29" +PKG_LICENSE="BSD" +PKG_SITE="https://speex.org" +PKG_URL="https://gitlab.xiph.org/xiph/speexdsp/-/archive/SpeexDSP-${PKG_VERSION}/speexdsp-SpeexDSP-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Speex audio processing library" +PKG_TOOLCHAIN="autotools" diff --git a/packages/audio/taglib/package.mk b/packages/audio/taglib/package.mk new file mode 100644 index 0000000000..8ec240ff4b --- /dev/null +++ b/packages/audio/taglib/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) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="taglib" +PKG_VERSION="2.1.1" +PKG_SHA256="3716d31f7c83cbf17b67c8cf44dd82b2a2f17e6780472287a16823e70305ddba" +PKG_LICENSE="LGPL" +PKG_SITE="https://taglib.org" +PKG_URL="https://taglib.org/releases/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain cmake:host utfcpp zlib" +PKG_LONGDESC="TagLib is a library for reading and editing the meta-data of several popular audio formats." + +PKG_CMAKE_OPTS_TARGET="-DBUILD_EXAMPLES=OFF \ + -DBUILD_SHARED_LIBS=OFF \ + -DBUILD_TESTING=OFF \ + -DENABLE_CCACHE=ON \ + -DWITH_ZLIB=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/wavpack/package.mk b/packages/audio/wavpack/package.mk new file mode 100644 index 0000000000..e4ec39e27f --- /dev/null +++ b/packages/audio/wavpack/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2020-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="wavpack" +PKG_VERSION="5.8.1" +PKG_SHA256="7322775498602c8850afcfc1ae38f99df4cbcd51386e873d6b0f8047e55c0c26" +PKG_LICENSE="BSD" +PKG_SITE="https://www.wavpack.com" +PKG_URL="https://www.wavpack.com/wavpack-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain libiconv" +PKG_LONGDESC="Audio compression format providing lossless, high-quality lossy and hybrid compression mode." + +PKG_CMAKE_OPTS_TARGET="-DBUILD_TESTING=OFF \ + -DCMAKE_INSTALL_INCLUDEDIR=include/wavpack \ + -DWAVPACK_BUILD_PROGRAMS=OFF \ + -DWAVPACK_ENABLE_ASM=OFF \ + -DWAVPACK_INSTALL_DOCS=OFF" diff --git a/packages/audio/wireplumber/package.mk b/packages/audio/wireplumber/package.mk new file mode 100644 index 0000000000..eaebe9588e --- /dev/null +++ b/packages/audio/wireplumber/package.mk @@ -0,0 +1,57 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="wireplumber" +PKG_VERSION="0.5.10" +PKG_SHA256="c2e021d8e6ef1db644facd4a97f5a644b67481c641da9100e851aab6752ba446" +PKG_LICENSE="MIT" +PKG_SITE="https://gitlab.freedesktop.org/pipewire/wireplumber" +PKG_URL="https://gitlab.freedesktop.org/pipewire/wireplumber/-/archive/${PKG_VERSION}/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="pipewire glib lua54" +PKG_LONGDESC="Session / policy manager implementation for PipeWire" + +PKG_MESON_OPTS_TARGET="-Dintrospection=disabled \ + -Ddoc=disabled \ + -Dsystem-lua=true \ + -Delogind=disabled \ + -Dsystemd=enabled \ + -Dsystemd-system-service=true \ + -Dsystemd-user-service=false \ + -Dsystemd-system-unit-dir=/usr/lib/systemd/system \ + -Dtests=false" + +post_makeinstall_target() { + # connect to the system bus + sed '/^\[Service\]/a Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/dbus/system_bus_socket' -i ${INSTALL}/usr/lib/systemd/system/wireplumber.service + + # ref https://gitlab.freedesktop.org/pipewire/wireplumber/-/commit/0da29f38181e391160fa8702623050b8544ec775 + # ref https://github.com/PipeWire/wireplumber/blob/master/docs/rst/daemon/configuration/migration.rst + # ref https://github.com/PipeWire/wireplumber/blob/master/docs/rst/daemon/configuration/features.rst + cat >${INSTALL}/usr/share/wireplumber/wireplumber.conf.d/89-disable-session-dbus-dependent-features.conf <${INSTALL}/usr/share/wireplumber/wireplumber.conf.d/89-disable-v4l2.conf <${INSTALL}/usr/share/wireplumber/wireplumber.conf.d/89-disable-bluez-hfphsp-backend.conf < +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 0000000000..f485f4c5c1 --- /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="make:host gcc:host 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/zip/patches/fix-compile-with-gcc14.patch b/packages/compress/zip/patches/fix-compile-with-gcc14.patch new file mode 100644 index 0000000000..2b2ce346c1 --- /dev/null +++ b/packages/compress/zip/patches/fix-compile-with-gcc14.patch @@ -0,0 +1,121 @@ +--- a/timezone.c 2004-11-13 08:35:12.000000000 +0000 ++++ b/timezone.c 2024-05-01 09:22:13.780112533 +0000 +@@ -39,6 +39,7 @@ + + #include "zip.h" + #include "timezone.h" ++#include + #include + #include + +--- a/unix/configure 2008-06-20 03:32:20.000000000 +0000 ++++ b/unix/configure 2024-05-01 09:27:12.149292690 +0000 +@@ -509,17 +509,68 @@ + # Check for missing functions + # add NO_'function_name' to flags if missing + +-for func in rmdir strchr strrchr rename mktemp mktime mkstemp +-do +- echo Check for $func +- echo "int main(){ $func(); return 0; }" > conftest.c +- $CC $BFLAG -o conftest conftest.c >/dev/null 2>/dev/null +- [ $? -ne 0 ] && CFLAGS="${CFLAGS} -DNO_`echo $func | tr '[a-z]' '[A-Z]'`" +-done ++echo Check for rmdir ++cat > conftest.c << _EOF_ ++#include ++int main() { rmdir(""); return 0; } ++_EOF_ ++$CC -o conftest conftest.c >/dev/null 2>/dev/null ++[ $? -ne 0 ] && CFLAGS="${CFLAGS} -DNO_RMDIR" ++ ++echo Check for strchr ++cat > conftest.c << _EOF_ ++#include ++int main() { strchr("", 0); return 0; } ++_EOF_ ++$CC -o conftest conftest.c >/dev/null 2>/dev/null ++[ $? -ne 0 ] && CFLAGS="${CFLAGS} -DNO_STRCHR" ++ ++echo Check for strrchr ++cat > conftest.c << _EOF_ ++#include ++int main() { strrchr("",0); return 0; } ++_EOF_ ++$CC -o conftest conftest.c >/dev/null 2>/dev/null ++[ $? -ne 0 ] && CFLAGS="${CFLAGS} -DNO_STRRCHR" ++ ++echo Check for rename ++cat > conftest.c << _EOF_ ++#include ++int main() { rename("",""); return 0; } ++_EOF_ ++$CC -o conftest conftest.c >/dev/null 2>/dev/null ++[ $? -ne 0 ] && CFLAGS="${CFLAGS} -DNO_RENAME" ++ ++echo Check for mktemp ++cat > conftest.c << _EOF_ ++#include ++int main() { mktemp(""); return 0; } ++_EOF_ ++$CC -o conftest conftest.c >/dev/null 2>/dev/null ++[ $? -ne 0 ] && CFLAGS="${CFLAGS} -DNO_MKTEMP" ++ ++echo Check for mktime ++cat > conftest.c << _EOF_ ++#include ++int main() { struct tm *t; mktime(t); return 0; } ++_EOF_ ++$CC -o conftest conftest.c >/dev/null 2>/dev/null ++[ $? -ne 0 ] && CFLAGS="${CFLAGS} -DNO_MKTIME" ++ ++echo Check for mkstemp ++cat > conftest.c << _EOF_ ++#include ++int main() { mkstemp(""); return 0; } ++_EOF_ ++$CC -o conftest conftest.c >/dev/null 2>/dev/null ++[ $? -ne 0 ] && CFLAGS="${CFLAGS} -DNO_MKSTEMP" + + + echo Check for memset +-echo "int main(){ char k; memset(&k,0,0); return 0; }" > conftest.c ++cat > conftest.c << _EOF_ ++#include ++int main() { char k; memset(&k,0,0); return 0; } ++_EOF_ + $CC -o conftest conftest.c >/dev/null 2>/dev/null + [ $? -ne 0 ] && CFLAGS="${CFLAGS} -DZMEM" + +@@ -544,7 +595,7 @@ + echo Check for errno declaration + cat > conftest.c << _EOF_ + #include +-main() ++int main() + { + errno = 0; + return 0; +@@ -556,6 +607,7 @@ + + echo Check for directory libraries + cat > conftest.c << _EOF_ ++#include + int main() { return closedir(opendir(".")); } + _EOF_ + +@@ -621,11 +673,13 @@ + + echo Check for valloc + cat > conftest.c << _EOF_ +-main() ++#include ++int main() + { + #ifdef MMAP + valloc(); + #endif ++ return 0; + } + _EOF_ + $CC ${CFLAGS} -c conftest.c > /dev/null 2>/dev/null diff --git a/packages/compress/zlib/package.mk b/packages/compress/zlib/package.mk new file mode 100644 index 0000000000..74ead0aa58 --- /dev/null +++ b/packages/compress/zlib/package.mk @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2026 ArchR (https://github.com/archr-linux/Arch-R) + +# Drop-in zlib replacement using zlib-ng compiled with --zlib-compat. +# ABI/API identical to upstream zlib (libz.so.1), but ships SIMD-aware +# inflate/deflate paths that NEON-enabled the inner loops on Cortex-A35. +# Real impact: ROM zip extraction in PortMaster/RetroArch and ext2/ext4 +# compression utilities run noticeably faster. +# +# We keep PKG_NAME="zlib" so every other package's PKG_DEPENDS_*="zlib" +# transparently picks up the replacement. Source unpack is overridden +# because the upstream tarball expands to zlib-ng-${PKG_VERSION}/. + +PKG_NAME="zlib" +PKG_VERSION="2.2.4" +PKG_SHA256="a73343c3093e5cdc50d9377997c3815b878fd110bf6511c2c7759f2afb90f5a3" +PKG_LICENSE="OSS" +PKG_SITE="https://github.com/zlib-ng/zlib-ng" +PKG_URL="https://github.com/zlib-ng/zlib-ng/archive/refs/tags/${PKG_VERSION}.tar.gz" +PKG_SOURCE_NAME="zlib-ng-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="ccache:host cmake:host" +PKG_DEPENDS_TARGET="cmake:host gcc:host" +PKG_LONGDESC="zlib-ng compiled in --zlib-compat mode — drop-in libz with SIMD-accelerated inflate/deflate." +PKG_TOOLCHAIN="cmake-make" + +# zlib-ng reads CMAKE flags directly. ZLIB_COMPAT=ON is what makes this +# build emit libz.so.1 (instead of libz-ng.so.2) so existing pkgconfig +# pointers keep working. WITH_GZFILEOP keeps gzopen()/gzread()/etc. +# Tests/benchmarks off to avoid pulling gtest into the cross toolchain. +PKG_CMAKE_OPTS_HOST="-DZLIB_COMPAT=ON \ + -DZLIB_ENABLE_TESTS=OFF \ + -DZLIBNG_ENABLE_TESTS=OFF \ + -DWITH_GTEST=OFF \ + -DWITH_GZFILEOP=ON \ + -DINSTALL_PKGCONFIG_DIR=${TOOLCHAIN}/lib/pkgconfig" + +PKG_CMAKE_OPTS_TARGET="-DZLIB_COMPAT=ON \ + -DZLIB_ENABLE_TESTS=OFF \ + -DZLIBNG_ENABLE_TESTS=OFF \ + -DWITH_GTEST=OFF \ + -DWITH_GZFILEOP=ON \ + -DWITH_OPTIM=ON \ + -DWITH_NEON=ON \ + -DINSTALL_PKGCONFIG_DIR=/usr/lib/pkgconfig" + +unpack() { + mkdir -p "${PKG_BUILD}" + tar --strip-components=1 -xf "${SOURCES}/${PKG_NAME}/${PKG_SOURCE_NAME}" -C "${PKG_BUILD}" +} diff --git a/packages/compress/zstd/package.mk b/packages/compress/zstd/package.mk new file mode 100644 index 0000000000..aa64ec345c --- /dev/null +++ b/packages/compress/zstd/package.mk @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="zstd" +PKG_VERSION="1.5.7" +PKG_SHA256="5b331d961d6989dc21bb03397fc7a2a4d86bc65a14adc5ffbbce050354e30fd2" +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.zst" +PKG_DEPENDS_HOST="cmake:host make:host" +PKG_DEPENDS_TARGET="cmake:host gcc:host" +PKG_LONGDESC="A fast real-time compression algorithm." +# Override toolchain as meson and ninja are not built yet +# and zstd is a dependency of ccache +PKG_TOOLCHAIN="cmake-make" +PKG_BUILD_FLAGS="+local-cc" + +configure_package() { + PKG_CMAKE_SCRIPT="${PKG_BUILD}/build/cmake/CMakeLists.txt" +} + +configure_host() { + # custom cmake build to override the LOCAL_CC/CXX + cp ${CMAKE_CONF} cmake-zstd.conf + + echo "SET(CMAKE_C_COMPILER ${CC})" >>cmake-zstd.conf + echo "SET(CMAKE_CXX_COMPILER ${CXX})" >>cmake-zstd.conf + + cmake -DCMAKE_TOOLCHAIN_FILE=cmake-zstd.conf \ + -DCMAKE_INSTALL_PREFIX=${TOOLCHAIN} \ + -DZSTD_LEGACY_SUPPORT=0 \ + -DZSTD_BUILD_PROGRAMS=OFF \ + -DZSTD_BUILD_TESTS=OFF \ + ${PKG_CMAKE_SCRIPT%/*} +} diff --git a/packages/databases/mariadb-connector-c/package.mk b/packages/databases/mariadb-connector-c/package.mk new file mode 100644 index 0000000000..25463cf652 --- /dev/null +++ b/packages/databases/mariadb-connector-c/package.mk @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="mariadb-connector-c" +PKG_VERSION="3.4.6" +PKG_SHA256="27b57790896b7464e1b87fb29bad49e31ee36fdb6942e5c86284c6af9630be0e" +PKG_LICENSE="LGPL" +PKG_SITE="https://mariadb.org/" +PKG_URL="https://github.com/mariadb-corporation/mariadb-connector-c/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain zlib openssl" +PKG_LONGDESC="mariadb-connector: library to connect to mariadb/mysql database server" +PKG_BUILD_FLAGS="-gold" + +PKG_CMAKE_OPTS_TARGET="-DWITH_EXTERNAL_ZLIB=ON + -DWITH_UNIT_TESTS=OFF + -DCLIENT_PLUGIN_DIALOG=STATIC + -DCLIENT_PLUGIN_MYSQL_CLEAR_PASSWORD=STATIC + -DCLIENT_PLUGIN_MYSQL_OLD_PASSWORD=STATIC + -DCLIENT_PLUGIN_REMOTE_IO=OFF + -DDEFAULT_SSL_VERIFY_SERVER_CERT=OFF + " + +post_makeinstall_target() { + # keep modern authentication plugins + PLUGINP=${INSTALL}/usr/lib/mariadb/plugin + mkdir -p ${INSTALL}/.tmp + mv ${PLUGINP}/{caching_sha2_password,client_ed25519,sha256_password}.so ${INSTALL}/.tmp + + # drop all unneeded + rm -rf ${INSTALL}/usr + + mkdir -p ${PLUGINP} + mv ${INSTALL}/.tmp/* ${PLUGINP}/ + rmdir ${INSTALL}/.tmp +} diff --git a/packages/databases/mariadb-connector-c/patches/fix-build-error-on-32-bit-systems.patch b/packages/databases/mariadb-connector-c/patches/fix-build-error-on-32-bit-systems.patch new file mode 100644 index 0000000000..683870fd76 --- /dev/null +++ b/packages/databases/mariadb-connector-c/patches/fix-build-error-on-32-bit-systems.patch @@ -0,0 +1,55 @@ +From 0f2f30f3f4ba936d7adb14a194cea85b12203619 Mon Sep 17 00:00:00 2001 +From: Chad Wagner <47257594+wagnerch@users.noreply.github.com> +Date: Sat, 21 Oct 2023 07:35:57 -0400 +Subject: [PATCH 1/2] Fix "Bad handshake" issue introduced by CONC-668 on + 32-bit platforms. + +Cast size_t to ulonglong on call to int8store. On 64-bit platforms they are both 8 bytes, +and on 32-bit platforms size_t is 4 bytes. +--- + libmariadb/mariadb_stmt.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libmariadb/mariadb_stmt.c b/libmariadb/mariadb_stmt.c +index 1f4782e2291e..927cba8588ac 100644 +--- a/libmariadb/mariadb_stmt.c ++++ b/libmariadb/mariadb_stmt.c +@@ -511,7 +511,7 @@ unsigned char *mysql_net_store_length(unsigned char *packet, size_t length) + return packet + 3; + } + *packet++ = 254; +- int8store(packet, length); ++ int8store(packet,(ulonglong) length); + return packet + 8; + } + +-- +2.34.1 + + +From 91699d7a63bd4cc77dc19af1c32cc9cd289511fd Mon Sep 17 00:00:00 2001 +From: Rudi Heitbaum +Date: Sat, 23 Sep 2023 23:24:30 +1000 +Subject: [PATCH 2/2] Additional fix for CONC-668: + +Fix build error on 32-bit systems. +--- + libmariadb/ma_context.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/libmariadb/ma_context.c b/libmariadb/ma_context.c +index 94a406684bbc..fc8380a047cf 100644 +--- a/libmariadb/ma_context.c ++++ b/libmariadb/ma_context.c +@@ -90,6 +90,8 @@ my_context_spawn(struct my_context *c, void (*f)(void *), void *d) + { + int err; + union pass_void_ptr_as_2_int u; ++ u.a[0]= 0; ++ u.a[1]= 0; + + err= getcontext(&c->spawned_context); + if (err) +-- +2.34.1 + diff --git a/packages/databases/mariadb-connector-c/patches/mariadb-connector-c-0001-fix-build-with-gcc-15.patch b/packages/databases/mariadb-connector-c/patches/mariadb-connector-c-0001-fix-build-with-gcc-15.patch new file mode 100644 index 0000000000..50482e860d --- /dev/null +++ b/packages/databases/mariadb-connector-c/patches/mariadb-connector-c-0001-fix-build-with-gcc-15.patch @@ -0,0 +1,21 @@ ++++ a/include/ma_global.h 2024-11-22 10:01:02.006088573 +0000 ++++ b/include/ma_global.h 2024-11-22 10:01:02.006088573 +0000 +@@ -684,7 +684,6 @@ + typedef char my_bool; /* Small bool */ + typedef unsigned long long my_ulonglong; + #if !defined(bool) && !defined(bool_defined) && (!defined(HAVE_BOOL) || !defined(__cplusplus)) +-typedef char bool; /* Ordinary boolean values 0 1 */ + #endif + /* Macros for converting *constants* to the right type */ + #define INT8(v) (int8) (v) +--- a/libmariadb/ma_alloc.c 2024-11-22 10:08:46.473445080 +0000 ++++ b/libmariadb/ma_alloc.c 2024-11-22 10:08:46.473445080 +0000 +@@ -170,7 +170,7 @@ + va_list args; + char **ptr,*start,*res; + size_t tot_length,length; +- ++if(myFlags){} + va_start(args,myFlags); + tot_length=0; + while ((ptr=va_arg(args, char **))) diff --git a/packages/databases/sqlite/package.mk b/packages/databases/sqlite/package.mk new file mode 100644 index 0000000000..09541e623b --- /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="3.50.2" +PKG_VERSION_SQLITE="${PKG_VERSION/./}00" +PKG_SHA256="84a616ffd31738e4590b65babb3a9e1ef9370f3638e36db220ee0e73f8ad2156" +PKG_LICENSE="PublicDomain" +PKG_SITE="https://www.sqlite.org/" +PKG_URL="https://www.sqlite.org/2025/${PKG_NAME}-autoconf-${PKG_VERSION_SQLITE/./0}.tar.gz" +PKG_DEPENDS_HOST="ccache:host autoconf:host automake:host" +PKG_DEPENDS_TARGET="autotools:host gcc:host 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 \ + --soname=legacy" + +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_stat4 table. The query planner will then use the histogram + # data to help it make better index choices. + CFLAGS+=" -DSQLITE_ENABLE_STAT4" + + # 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+=" -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+=" -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 0000000000..f07ddb2563 --- /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 +@@ -43925,7 +43925,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); +@@ -43944,7 +43944,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/gdb/package.mk b/packages/debug/gdb/package.mk new file mode 100644 index 0000000000..a67b96f50d --- /dev/null +++ b/packages/debug/gdb/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) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="gdb" +PKG_VERSION="16.3" +PKG_SHA256="bcfcd095528a987917acf9fff3f1672181694926cc18d609c99d0042c00224c5" +PKG_LICENSE="GPL" +PKG_SITE="https://www.gnu.org/software/gdb/" +PKG_URL="https://mirrors.kernel.org/gnu/gdb/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain expat gmp mpfr ncurses zlib" +PKG_DEPENDS_HOST="toolchain:host expat:host gmp:host mpfr:host ncurses:host zlib:host" +PKG_LONGDESC="GNU Project debugger, allows you to see what is going on inside another program while it executes." +PKG_BUILD_FLAGS="+size" + +PKG_CONFIGURE_OPTS_COMMON="bash_cv_have_mbstate_t=set \ + --disable-shared \ + --enable-static \ + --with-auto-load-safe-path=/ \ + --with-python=no \ + --with-guile=no \ + --with-intel-pt=no \ + --with-babeltrace=no \ + --with-expat=yes \ + --disable-source-highlight \ + --disable-nls \ + --disable-rpath \ + --disable-sim \ + --without-x \ + --disable-tui \ + --disable-libada \ + --without-lzma \ + --disable-libquadmath \ + --disable-libquadmath-support \ + --enable-libada \ + --enable-libssp \ + --disable-werror" + +PKG_CONFIGURE_OPTS_TARGET="${PKG_CONFIGURE_OPTS_COMMON} \ + --with-libexpat-prefix=${SYSROOT_PREFIX}/usr \ + --with-libgmp-prefix=${SYSROOT_PREFIX}/usr" + +PKG_CONFIGURE_OPTS_HOST="${PKG_CONFIGURE_OPTS_COMMON} \ + --target=${TARGET_NAME}" + +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/0001-gdbserver-ctrl-c-handling.patch b/packages/debug/gdb/patches/0001-gdbserver-ctrl-c-handling.patch new file mode 100644 index 0000000000..7fa2c83386 --- /dev/null +++ b/packages/debug/gdb/patches/0001-gdbserver-ctrl-c-handling.patch @@ -0,0 +1,40 @@ +From 589e7f396af4c8e4a33dcd1b22be481f150b4fc0 Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Thu, 29 Nov 2018 18:00:23 -0800 +Subject: [PATCH] gdbserver ctrl-c handling + +This problem was created by the upstream commit 78708b7c8c +After applying the commit, it will send SIGINT to the process +group(-signal_pid). +But if we use gdbserver send SIGINT, and the attached process is not a +process +group leader, then the "kill (-signal_pid, SIGINT)" returns error and +fails to +interrupt the attached process. + +Upstream-Status: Submitted +[https://sourceware.org/bugzilla/show_bug.cgi?id=18945] + +Author: Josh Gao +Signed-off-by: Zhixiong Chi +Signed-off-by: Khem Raj +--- + gdbserver/linux-low.cc | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/gdbserver/linux-low.cc b/gdbserver/linux-low.cc +index 8b8614f6ed4..e71e6667c51 100644 +--- a/gdbserver/linux-low.cc ++++ b/gdbserver/linux-low.cc +@@ -5465,7 +5465,7 @@ linux_process_target::request_interrupt () + { + /* Send a SIGINT to the process group. This acts just like the user + typed a ^C on the controlling terminal. */ +- int res = ::kill (-signal_pid, SIGINT); ++ int res = ::kill (signal_pid, SIGINT); + if (res == -1) + warning (_("Sending SIGINT to process group of pid %ld failed: %s"), + signal_pid, safe_strerror (errno)); +-- +2.25.1 + 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 0000000000..0a9804e540 --- /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 0000000000..0899aa8a93 --- /dev/null +++ b/packages/debug/libunwind/package.mk @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libunwind" +PKG_VERSION="1.8.2" +PKG_SHA256="3b888e01f3d25f7914bbfd31139066bb4547e079322975134b03c92e4c6a2066" +PKG_LICENSE="GPL" +PKG_SITE="https://www.nongnu.org/libunwind/" +PKG_URL="https://github.com/libunwind/libunwind/archive/refs/tags/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="autotools:host gcc:host zlib" +PKG_LONGDESC="library to determine the call-chain of a program" +PKG_BUILD_FLAGS="+pic" +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="--enable-static \ + --disable-shared \ + --disable-minidebuginfo \ + --disable-documentation \ + --disable-tests" + +makeinstall_target() { + make DESTDIR=${SYSROOT_PREFIX} install +} diff --git a/packages/debug/libunwind/patches/libunwind-0001-fix-multiple-definition.patch b/packages/debug/libunwind/patches/libunwind-0001-fix-multiple-definition.patch new file mode 100644 index 0000000000..68eb5f70a0 --- /dev/null +++ b/packages/debug/libunwind/patches/libunwind-0001-fix-multiple-definition.patch @@ -0,0 +1,26 @@ +From f40db1e2562934fd21485ba7f62e4521945f17e4 Mon Sep 17 00:00:00 2001 +From: MilhouseVH +Date: Mon, 17 Feb 2020 05:52:10 +0000 +Subject: [PATCH] fix multiple definition + +https://lists.nongnu.org/archive/html/libunwind-devel/2017-08/msg00039.html +https://github.com/libunwind/libunwind/commit/0e74e583ae18d6852835f327921ee130a5fa3e6f +--- + include/tdep-arm/ex_tables.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/include/tdep-arm/ex_tables.h b/include/tdep-arm/ex_tables.h +index 9df5e0a..0b5388a 100644 +--- a/include/tdep-arm/ex_tables.h ++++ b/include/tdep-arm/ex_tables.h +@@ -47,6 +47,7 @@ struct arm_exbuf_data + #define arm_exidx_extract UNW_OBJ(arm_exidx_extract) + #define arm_exidx_decode UNW_OBJ(arm_exidx_decode) + #define arm_exidx_apply_cmd UNW_OBJ(arm_exidx_apply_cmd) ++#define arm_search_unwind_table UNW_OBJ(arm_search_unwind_table) + + int arm_exidx_extract (struct dwarf_cursor *c, uint8_t *buf); + int arm_exidx_decode (const uint8_t *buf, uint8_t len, struct dwarf_cursor *c); +-- +2.7.4 + diff --git a/packages/debug/libunwind/patches/libunwind-0002-add-dependant-static-libraries.patch b/packages/debug/libunwind/patches/libunwind-0002-add-dependant-static-libraries.patch new file mode 100644 index 0000000000..0c41417ec1 --- /dev/null +++ b/packages/debug/libunwind/patches/libunwind-0002-add-dependant-static-libraries.patch @@ -0,0 +1,10 @@ +--- a/src/unwind/libunwind.pc.in 2020-11-10 16:14:18.000000000 +0000 ++++ b/src/unwind/libunwind.pc.in 2021-12-05 08:16:04.467881118 +0000 +@@ -6,6 +6,6 @@ + Name: libunwind + Description: libunwind base library + Version: @VERSION@ +-Libs: -L${libdir} -lunwind ++Libs: -L${libdir} -lunwind @LIBLZMA@ @LIBZ@ + Libs.private: @LIBLZMA@ @LIBZ@ + Cflags: -I${includedir} diff --git a/packages/debug/libva-utils/package.mk b/packages/debug/libva-utils/package.mk new file mode 100644 index 0000000000..beef1d6ba6 --- /dev/null +++ b/packages/debug/libva-utils/package.mk @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libva-utils" +PKG_VERSION="2.22.0" +PKG_SHA256="7b57615c130427ec134bb5d2b80af516ce5bb19a40e89b1dab46a0d59760d96c" +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)" + +if [ "${DISPLAYSERVER}" = "x11" ]; then + PKG_DEPENDS_TARGET="toolchain libva libdrm libX11" + DISPLAYSERVER_LIBVA="-Dx11=true" +else + PKG_DEPENDS_TARGET="toolchain libva libdrm" + DISPLAYSERVER_LIBVA="-Dx11=false" +fi + +PKG_MESON_OPTS_TARGET="-Ddrm=true \ + ${DISPLAYSERVER_LIBVA} \ + -Dwayland=false \ + -Dtests=false" diff --git a/packages/debug/memtester/package.mk b/packages/debug/memtester/package.mk new file mode 100644 index 0000000000..a4010cc1d0 --- /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.7.1" +PKG_SHA256="e427de663f7bd22d1ebee8af12506a852c010bd4fcbca1e0e6b02972d298b5bb" +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 0000000000..3ff6decfc7 --- /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/strace/package.mk b/packages/debug/strace/package.mk new file mode 100644 index 0000000000..ed658abe01 --- /dev/null +++ b/packages/debug/strace/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="strace" +PKG_VERSION="6.15" +PKG_SHA256="8552dfab08abc22a0f2048c98fd9541fd4d71b6882507952780dab7c7c512f51" +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="-cfg-libs" + +if [ "${TARGET_ARCH}" = x86_64 -o "${TARGET_ARCH}" = "aarch64" ]; then + PKG_CONFIGURE_OPTS_TARGET="--enable-mpers=no" +fi diff --git a/packages/debug/strace/patches/strace-0001-autoreconf.patch b/packages/debug/strace/patches/strace-0001-autoreconf.patch new file mode 100644 index 0000000000..41dd01be4b --- /dev/null +++ b/packages/debug/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([./build-aux/git-version-gen .tarball-version]), +- [strace-devel@lists.strace.io], +- [strace], +- [https://strace.io]) ++AC_INIT([strace],[5.11]) + m4_define([copyright_year], st_esyscmd_s([./build-aux/copyright-year-gen .year])) + m4_define([manpage_date], st_esyscmd_s([./build-aux/file-date-gen doc/strace.1.in])) + AC_COPYRIGHT([Copyright (c) 1999-]copyright_year[ The strace developers.]) diff --git a/packages/debug/strace/patches/strace-0002-fix-autoconf-archive.patch b/packages/debug/strace/patches/strace-0002-fix-autoconf-archive.patch new file mode 100644 index 0000000000..4e0927da66 --- /dev/null +++ b/packages/debug/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/debug/vadumpcaps/package.mk b/packages/debug/vadumpcaps/package.mk new file mode 100644 index 0000000000..8d7596510d --- /dev/null +++ b/packages/debug/vadumpcaps/package.mk @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2020-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="vadumpcaps" +PKG_VERSION="38a446e33de5e65f0e5d263dd9a262a4e316a461" +PKG_SHA256="04847fcae7ed5529371c3ff27518e6ef4623db65955ad6c7633a538c6b2aeae8" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/fhvwy/vadumpcaps" +PKG_URL="https://github.com/fhvwy/vadumpcaps/archive/${PKG_VERSION}.tar.gz" +PKG_LONGDESC="This is a utility to show all capabilities of a VAAPI device/driver." +PKG_DEPENDS_TARGET="toolchain libva" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp vadumpcaps ${INSTALL}/usr/bin +} diff --git a/packages/debug/valgrind/package.mk b/packages/debug/valgrind/package.mk new file mode 100644 index 0000000000..30d6e6e35a --- /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.25.1" +PKG_SHA256="61deb8d0727b45c268efdc1b3b6c9e679cd97cbf5ee4b28d1dead7c8b7a271af" +PKG_LICENSE="GPL" +PKG_SITE="https://valgrind.org/" +PKG_URL="https://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/vdpauinfo/package.mk b/packages/debug/vdpauinfo/package.mk new file mode 100644 index 0000000000..6e373d1c3f --- /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/debug/xorg-intel-gpu-tools/package.mk b/packages/debug/xorg-intel-gpu-tools/package.mk new file mode 100644 index 0000000000..da2ae95980 --- /dev/null +++ b/packages/debug/xorg-intel-gpu-tools/package.mk @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="xorg-intel-gpu-tools" +PKG_VERSION="2.1" +PKG_SHA256="bf72beff71093db692f386c9359b557dfa8e8c45250439c952564b1b6fe343f8" +PKG_LICENSE="GPL" +PKG_DEPENDS_TARGET="toolchain cairo elfutils kmod libdrm procps-ng systemd" +PKG_SITE="https://gitlab.freedesktop.org/drm/igt-gpu-tools" +PKG_URL="https://www.x.org/releases/individual/app/igt-gpu-tools-${PKG_VERSION}.tar.xz" +PKG_LONGDESC="Test suite and tools for DRM/KMS drivers" + +PKG_MESON_OPTS_TARGET="-Dchamelium=disabled \ + -Ddocs=disabled \ + -Dlibdrm_drivers=auto \ + -Dlibunwind=disabled \ + -Dman=disabled \ + -Doverlay=disabled \ + -Drunner=disabled \ + -Dtests=enabled \ + -Dvalgrind=disabled" + +pre_configure_target() { + # xorg-intel-gpu-tools does not build with NDEBUG (requires assert for tests) + export TARGET_CFLAGS=$(echo ${TARGET_CFLAGS} | sed -e "s|-DNDEBUG||g") +} diff --git a/packages/devel/arm-mem/package.mk b/packages/devel/arm-mem/package.mk new file mode 100644 index 0000000000..ea40c76871 --- /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="ee8ac1d56adb7ceef4d39a5cc21a502e41982685" +PKG_SHA256="d1986f705abbe2b2e00912dbdc5e6b36e80cca2cc26a52e2489db7e7ff7873bc" +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/asn1c/package.mk b/packages/devel/asn1c/package.mk new file mode 100644 index 0000000000..1aed298d42 --- /dev/null +++ b/packages/devel/asn1c/package.mk @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="asn1c" +PKG_VERSION="0.9.28" +PKG_SHA256="8007440b647ef2dd9fb73d931c33ac11764e6afb2437dbe638bb4e5fc82386b9" +PKG_LICENSE="BSD" +PKG_SITE="http://lionet.info/asn1c/blog/" +PKG_URL="https://github.com/vlm/asn1c/releases/download/v${PKG_VERSION}/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="ccache:host" +PKG_LONGDESC="The ASN.1 Compiler" diff --git a/packages/devel/attr/package.mk b/packages/devel/attr/package.mk new file mode 100644 index 0000000000..ef8af654f4 --- /dev/null +++ b/packages/devel/attr/package.mk @@ -0,0 +1,30 @@ +# 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.5.2" +PKG_SHA256="39bf67452fa41d0948c2197601053f48b3d78a029389734332a6309a680c6c87" +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="autotools:host gcc:host" +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 + +post_makeinstall_target() { + safe_remove ${INSTALL}/etc + safe_remove ${INSTALL}/usr/bin +} diff --git a/packages/devel/autoconf-archive/package.mk b/packages/devel/autoconf-archive/package.mk new file mode 100644 index 0000000000..9db5a7890a --- /dev/null +++ b/packages/devel/autoconf-archive/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) 2020-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="autoconf-archive" +PKG_VERSION="2024.10.16" +PKG_SHA256="7bcd5d001916f3a50ed7436f4f700e3d2b1bade3ed803219c592d62502a57363" +PKG_LICENSE="GPL" +PKG_SITE="https://www.gnu.org/software/autoconf-archive/" +PKG_URL="https://mirrors.kernel.org/gnu/autoconf-archive/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_HOST="ccache:host" +PKG_LONGDESC="autoconf-archive is an package of m4 macros" +PKG_BUILD_FLAGS="-cfg-libs:host" + +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 0000000000..d91778d2fb --- /dev/null +++ b/packages/devel/autoconf/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="autoconf" +PKG_VERSION="2.72" +PKG_SHA256="ba885c1319578d6c94d46e9b0dceb4014caafe2490e437a0dbca3f270a223f5a" +PKG_LICENSE="GPL" +PKG_SITE="https://www.gnu.org/software/autoconf/" +PKG_URL="https://mirrors.kernel.org/gnu/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_BUILD_FLAGS="-cfg-libs:host" + +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-autoreconf-exclude.patch b/packages/devel/autoconf/patches/autoconf-autoreconf-exclude.patch new file mode 100644 index 0000000000..f3f239cbc3 --- /dev/null +++ b/packages/devel/autoconf/patches/autoconf-autoreconf-exclude.patch @@ -0,0 +1,143 @@ +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 +@@ -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,19 @@ + { + $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"; + } + + + # --------------------- # + # Running intltoolize. # + # --------------------- # +@@ -748,8 +748,11 @@ + } + elsif ($install) + { +- xsystem_hint ("gtkdocize is needed because this package uses Gtkdoc", +- $gtkdocize); ++ @ex = grep (/^autopoint$/, @exclude); ++ if ($#ex == -1) { ++ xsystem_hint ("gtkdocize is needed because this package uses Gtkdoc", ++ $gtkdocize); ++ } + } + else + { +@@ -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/autoconf/patches/man-exclude.patch b/packages/devel/autoconf/patches/man-exclude.patch new file mode 100644 index 0000000000..55e77ba0ad --- /dev/null +++ b/packages/devel/autoconf/patches/man-exclude.patch @@ -0,0 +1,10 @@ +--- a/Makefile.in 2021-02-28 12:25:11.000000000 +0000 ++++ b/Makefile.in 2021-02-28 12:25:11.000000000 +0000 +@@ -780,7 +780,6 @@ + man/autoconf.1 \ + man/autoheader.1 \ + man/autom4te.1 \ +- man/autoreconf.1 \ + man/autoscan.1 \ + man/autoupdate.1 \ + man/ifnames.1 diff --git a/packages/devel/automake/package.mk b/packages/devel/automake/package.mk new file mode 100644 index 0000000000..688daa6019 --- /dev/null +++ b/packages/devel/automake/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="automake" +PKG_VERSION="1.18.1" +PKG_SHA256="168aa363278351b89af56684448f525a5bce5079d0b6842bd910fdd3f1646887" +PKG_LICENSE="GPL" +PKG_SITE="http://sources.redhat.com/automake/" +PKG_URL="https://mirrors.kernel.org/gnu/automake/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_HOST="ccache:host autoconf:host" +PKG_LONGDESC="A GNU tool for automatically creating Makefiles." +PKG_BUILD_FLAGS="-parallel -cfg-libs:host" + +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 0000000000..924cb2d630 --- /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 +@@ -739,7 +739,7 @@ + $(MKDIR_P) doc \ + && AUTOMAKE_HELP2MAN=true ./pre-inst-env \ + $(PERL) $(srcdir)/doc/help2man --output=$@ --info-page=automake \ +- --name="$${HELP2MAN_NAME}" ++ --name="$${HELP2MAN_NAME}" --no-discard-stderr + + checklinkx = $(top_srcdir)/contrib/checklinkx + # that particular sleep seems to be what gnu.org likes. +-- +1.7.2.5 + diff --git a/packages/devel/binutils-aarch64/package.mk b/packages/devel/binutils-aarch64/package.mk new file mode 100644 index 0000000000..3c11c28f22 --- /dev/null +++ b/packages/devel/binutils-aarch64/package.mk @@ -0,0 +1,50 @@ +# 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-aarch64" +PKG_VERSION="$(get_pkg_version binutils)" +PKG_LICENSE="GPL" +PKG_URL="" +PKG_DEPENDS_HOST="toolchain:host" +PKG_LONGDESC="A GNU collection of binary utilities for 64-bit ARM." +PKG_DEPENDS_UNPACK+=" binutils" +PKG_PATCH_DIRS+=" $(get_pkg_directory binutils)/patches" + +PKG_CONFIGURE_OPTS_HOST="--target=aarch64-none-elf \ + --with-sysroot=${TOOLCHAIN}/aarch64-none-elf/sysroot \ + --without-ppl \ + --enable-static \ + --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" + +unpack() { + mkdir -p ${PKG_BUILD} + tar --strip-components=1 -xf ${SOURCES}/binutils/binutils-${PKG_VERSION}.tar.xz -C ${PKG_BUILD} +} + +pre_configure_host() { + unset CPPFLAGS + unset CFLAGS + unset CXXFLAGS + unset LDFLAGS +} + +make_host() { + make configure-host + # override the makeinfo binary with true - this does not build the documentation + make MAKEINFO=true +} + +makeinstall_host() { + make MAKEINFO=true install +} diff --git a/packages/devel/binutils-arm-none-eabi/package.mk b/packages/devel/binutils-arm-none-eabi/package.mk new file mode 100644 index 0000000000..9242ef8847 --- /dev/null +++ b/packages/devel/binutils-arm-none-eabi/package.mk @@ -0,0 +1,51 @@ +# 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-arm-none-eabi" +PKG_VERSION="$(get_pkg_version binutils)" +PKG_LICENSE="GPL" +PKG_URL="" +PKG_DEPENDS_HOST="toolchain:host" +PKG_LONGDESC="A GNU collection of binary utilities for ARM Cortex-R/M processors." +PKG_DEPENDS_UNPACK+=" binutils" +PKG_PATCH_DIRS+=" $(get_pkg_directory binutils)/patches" + +PKG_CONFIGURE_OPTS_HOST="--target=arm-none-eabi \ + --with-sysroot=${TOOLCHAIN}/arm-none-eabi/sysroot \ + --without-ppl \ + --enable-static \ + --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" + +unpack() { + mkdir -p ${PKG_BUILD} + tar --strip-components=1 -xf ${SOURCES}/binutils/binutils-${PKG_VERSION}.tar.xz -C ${PKG_BUILD} +} + +pre_configure_host() { + unset CPPFLAGS + unset CFLAGS + unset CXXFLAGS + unset LDFLAGS +} + +make_host() { + make configure-host + # override the makeinfo binary with true - this does not build the documentation + make MAKEINFO=true +} + +makeinstall_host() { + # override the makeinfo binary with true - this does not build the documentation + make MAKEINFO=true install +} diff --git a/packages/devel/binutils-bpf/package.mk b/packages/devel/binutils-bpf/package.mk new file mode 100644 index 0000000000..a607f5e771 --- /dev/null +++ b/packages/devel/binutils-bpf/package.mk @@ -0,0 +1,51 @@ +# 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-bpf" +PKG_VERSION="$(get_pkg_version binutils)" +PKG_LICENSE="GPL" +PKG_URL="" +PKG_DEPENDS_HOST="toolchain:host" +PKG_LONGDESC="A GNU collection of binary utilities for 64-bit ARM." +PKG_DEPENDS_UNPACK+=" binutils" +PKG_PATCH_DIRS+=" $(get_pkg_directory binutils)/patches" + +PKG_CONFIGURE_OPTS_HOST="--target=bpf \ + --with-sysroot=${TOOLCHAIN}/bpf/sysroot \ + --without-ppl \ + --enable-static \ + --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" + +unpack() { + mkdir -p ${PKG_BUILD} + tar --strip-components=1 -xf ${SOURCES}/binutils/binutils-${PKG_VERSION}.tar.xz -C ${PKG_BUILD} +} + +pre_configure_host() { + unset CPPFLAGS + unset CFLAGS + unset CXXFLAGS + unset LDFLAGS +} + +make_host() { + make configure-host + # override the makeinfo binary with true - this does not build the documentation + make MAKEINFO=true +} + +makeinstall_host() { + # override the makeinfo binary with true - this does not build the documentation + make MAKEINFO=true install +} diff --git a/packages/devel/binutils-or1k/package.mk b/packages/devel/binutils-or1k/package.mk new file mode 100644 index 0000000000..1ba2357131 --- /dev/null +++ b/packages/devel/binutils-or1k/package.mk @@ -0,0 +1,51 @@ +# 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-or1k" +PKG_VERSION="$(get_pkg_version binutils)" +PKG_LICENSE="GPL" +PKG_URL="" +PKG_DEPENDS_HOST="toolchain:host" +PKG_LONGDESC="A GNU collection of binary utilities for OpenRISC 1000." +PKG_DEPENDS_UNPACK+=" binutils" +PKG_PATCH_DIRS+=" $(get_pkg_directory binutils)/patches" + +PKG_CONFIGURE_OPTS_HOST="--target=or1k-none-elf \ + --with-sysroot=${TOOLCHAIN}/or1k-none-elf/sysroot \ + --without-ppl \ + --enable-static \ + --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" + +unpack() { + mkdir -p ${PKG_BUILD} + tar --strip-components=1 -xf ${SOURCES}/binutils/binutils-${PKG_VERSION}.tar.xz -C ${PKG_BUILD} +} + +pre_configure_host() { + unset CPPFLAGS + unset CFLAGS + unset CXXFLAGS + unset LDFLAGS +} + +make_host() { + make configure-host + # override the makeinfo binary with true - this does not build the documentation + make MAKEINFO=true +} + +makeinstall_host() { + # override the makeinfo binary with true - this does not build the documentation + make MAKEINFO=true install +} diff --git a/packages/devel/binutils/package.mk b/packages/devel/binutils/package.mk new file mode 100644 index 0000000000..c1850009c2 --- /dev/null +++ b/packages/devel/binutils/package.mk @@ -0,0 +1,87 @@ +# 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.44" +PKG_SHA256="67be9198476cc37436e2801de649f4ad80bf0d02430d86aff63c6b59b6e23987" +PKG_LICENSE="GPL" +PKG_SITE="https://www.gnu.org/software/binutils/" +PKG_URL="https://mirrors.kernel.org/gnu/binutils/${PKG_NAME}-with-gold-${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 \ + --enable-static \ + --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 + # override the makeinfo binary with true - this does not build the documentation + make MAKEINFO=true +} + +makeinstall_host() { + cp -v ../include/libiberty.h ${SYSROOT_PREFIX}/usr/include + make -C libsframe install # bfd is reliant on libsframe + make -C bfd install # fix parallel build with libctf requiring bfd + # override the makeinfo binary with true - this does not build the documentation + make HELP2MAN=true MAKEINFO=true 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 0000000000..9bd64e3872 --- /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 ++++ b/ld/ldfile.c +@@ -314,6 +314,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/binutils-02-binutils-2-39-dont-error-on-missing-makeinfo.patch b/packages/devel/binutils/patches/binutils-02-binutils-2-39-dont-error-on-missing-makeinfo.patch new file mode 100644 index 0000000000..e14501d4df --- /dev/null +++ b/packages/devel/binutils/patches/binutils-02-binutils-2-39-dont-error-on-missing-makeinfo.patch @@ -0,0 +1,11 @@ +--- a/bfd/Makefile.in 2022-08-05 09:53:59.000000000 +0000 ++++ b/bfd/Makefile.in 2022-08-07 11:22:25.397501975 +0000 +@@ -264,7 +264,7 @@ + am__v_texidevnull_0 = > /dev/null + am__v_texidevnull_1 = + am__dirstamp = $(am__leading_dot)dirstamp +-INFO_DEPS = doc/bfd.info ++INFO_DEPS = + am__TEXINFO_TEX_DIR = $(srcdir) + DVIS = doc/bfd.dvi + PDFS = doc/bfd.pdf diff --git a/packages/devel/bison/package.mk b/packages/devel/bison/package.mk new file mode 100644 index 0000000000..27c6d0dafb --- /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="https://mirrors.kernel.org/gnu/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 -cfg-libs:host" + +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 0000000000..f3bfce975f --- /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.88.0" +PKG_SHA256="46d9d2c06637b219270877c9e16155cbd015b6dc84349af064c088e9b5b12f7b" +PKG_LICENSE="OSS" +PKG_SITE="https://www.boost.org/" +PKG_URL="https://archives.boost.io/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 gcc --cxx=${HOST_CXX} --cxxflags=${HOST_CXXFLAGS} +} + +makeinstall_host() { + mkdir -p ${TOOLCHAIN}/bin + cp b2 ${TOOLCHAIN}/bin +} + +pre_configure_target() { + export CFLAGS="${CFLAGS} -I${SYSROOT_PREFIX}/usr/include/${PKG_PYTHON_VERSION}" + export CXXFLAGS="${CXXFLAGS} -I${SYSROOT_PREFIX}/usr/include/${PKG_PYTHON_VERSION}" +} + +configure_target() { + sh bootstrap.sh --prefix=/usr \ + --with-bjam=${TOOLCHAIN}/bin/b2 \ + --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/b2 -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 0000000000..9ec45fd947 --- /dev/null +++ b/packages/devel/ccache/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="ccache" +PKG_VERSION="4.11.3" +PKG_SHA256="d5a340e199977b7b1e89c0add794132c977fdc2ecc7ca5451e03d43627a1b1be" +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="cmake:host make:host zstd:host libfmt:host xxHash:host" +PKG_LONGDESC="A compiler cache to speed up re-compilation of C/C++ code by caching." +# Override toolchain as ninja is not built yet +PKG_TOOLCHAIN="cmake-make" +PKG_BUILD_FLAGS="+local-cc" + +configure_host() { + # custom cmake build to override the LOCAL_CC/CXX + cp ${CMAKE_CONF} cmake-ccache.conf + + echo "SET(CMAKE_C_COMPILER ${CC})" >>cmake-ccache.conf + echo "SET(CMAKE_CXX_COMPILER ${CXX})" >>cmake-ccache.conf + + cmake -DCMAKE_TOOLCHAIN_FILE=cmake-ccache.conf \ + -DCMAKE_INSTALL_PREFIX=${TOOLCHAIN} \ + -DENABLE_DOCUMENTATION=OFF \ + -DREDIS_STORAGE_BACKEND=OFF \ + -DENABLE_TESTING=OFF \ + -DDEPS=SYSTEM \ + .. +} + +post_makeinstall_host() { + # setup ccache + if [ -z "${CCACHE_DISABLE}" ]; then + CCACHE_DIR="${BUILD_CCACHE_DIR}" ${TOOLCHAIN}/bin/ccache --max-size=${CCACHE_CACHE_SIZE} + CCACHE_DIR="${BUILD_CCACHE_DIR}" ${TOOLCHAIN}/bin/ccache --set-config compression_level=${CCACHE_COMPRESSLEVEL} + CCACHE_DIR="${BUILD_CCACHE_DIR}" ${TOOLCHAIN}/bin/ccache --set-config sloppiness=${CCACHE_SLOPPINESS} + 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/commons-lang3/package.mk b/packages/devel/commons-lang3/package.mk new file mode 100644 index 0000000000..90d69fc662 --- /dev/null +++ b/packages/devel/commons-lang3/package.mk @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2023-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="commons-lang3" +PKG_VERSION="3.18.0" +PKG_SHA256="add5f9cd656437515d19c8af46058322f9bbc337591a811027f706df84ee5b14" +PKG_LICENSE="Apache-2.0" +PKG_SITE="https://commons.apache.org/proper/commons-lang/" +PKG_URL="https://archive.apache.org/dist/commons/lang/binaries/commons-lang3-${PKG_VERSION}-bin.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Apache Commons Lang provides a host of helper utilities for the java.lang API" +PKG_TOOLCHAIN="manual" diff --git a/packages/devel/commons-text/package.mk b/packages/devel/commons-text/package.mk new file mode 100644 index 0000000000..dfdace6851 --- /dev/null +++ b/packages/devel/commons-text/package.mk @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2023-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="commons-text" +PKG_VERSION="1.13.1" +PKG_SHA256="51236deae067ec2d97826f515a495e57002d749cfd9bdd0a19cc35cbeaaccb6d" +PKG_LICENSE="Apache-2.0" +PKG_SITE="https://commons.apache.org/proper/commons-text/" +PKG_URL="https://archive.apache.org/dist/commons/text/binaries/commons-text-${PKG_VERSION}-bin.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Apache Commons Text is a library focused on algorithms working on strings" +PKG_TOOLCHAIN="manual" diff --git a/packages/devel/configtools/package.mk b/packages/devel/configtools/package.mk new file mode 100644 index 0000000000..7a9569baec --- /dev/null +++ b/packages/devel/configtools/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) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="configtools" +PKG_VERSION="system" +PKG_LICENSE="GPL" +PKG_SITE="https://www.gnu.org/software/config/" +PKG_URL="" +PKG_DEPENDS_HOST="" +PKG_LONGDESC="GNU config.guess and config.sub from system automake" +PKG_TOOLCHAIN="manual" + +unpack() { + mkdir -p ${PKG_BUILD} + # Copy config.guess and config.sub from system automake + local automake_share=$(ls -d /usr/share/automake-* 2>/dev/null | head -1) + if [ -n "${automake_share}" ]; then + cp ${automake_share}/config.guess ${PKG_BUILD}/ + cp ${automake_share}/config.sub ${PKG_BUILD}/ + else + # Fallback: use the ones from /usr/share/libtool + cp /usr/share/libtool/build-aux/config.guess ${PKG_BUILD}/ 2>/dev/null || true + cp /usr/share/libtool/build-aux/config.sub ${PKG_BUILD}/ 2>/dev/null || true + fi +} + +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 0000000000..45a0c78be3 --- /dev/null +++ b/packages/devel/crossguid/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) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="crossguid" +PKG_VERSION="ca1bf4b810e2d188d04cb6286f957008ee1b7681" # 2019-05-30 +PKG_SHA256="6be27e0b3a4907f0cd3cfadec255ee1b925569e1bd06e67a4d2f4267299b69c4" +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_CMAKE_OPTS_TARGET="-DCROSSGUID_TESTS=OFF \ + -Wno-dev" diff --git a/packages/devel/crossguid/patches/crossguid-0001-pr67-include-missing-cstdint.patch b/packages/devel/crossguid/patches/crossguid-0001-pr67-include-missing-cstdint.patch new file mode 100644 index 0000000000..36176b9a83 --- /dev/null +++ b/packages/devel/crossguid/patches/crossguid-0001-pr67-include-missing-cstdint.patch @@ -0,0 +1,27 @@ +From 1eb9bea38c320b2b588635cffceaaa2a8d434780 Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Wed, 25 Jan 2023 22:09:26 -0800 +Subject: [PATCH] include missing + +gcc 13 moved some includes around and as a result is no longer transitively +included [1]. Explicitly include it for uint{32,64}_t. + +[1] https://gcc.gnu.org/gcc-13/porting_to.html#header-dep-changes + +Signed-off-by: Khem Raj +--- + include/crossguid/guid.hpp | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/include/crossguid/guid.hpp b/include/crossguid/guid.hpp +index 61e0f17..70966f2 100644 +--- a/include/crossguid/guid.hpp ++++ b/include/crossguid/guid.hpp +@@ -29,6 +29,7 @@ THE SOFTWARE. + #include + #endif + ++#include + #include + #include + #include diff --git a/packages/devel/elfutils/package.mk b/packages/devel/elfutils/package.mk new file mode 100644 index 0000000000..006150323e --- /dev/null +++ b/packages/devel/elfutils/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="elfutils" +PKG_VERSION="0.193" +PKG_SHA256="7857f44b624f4d8d421df851aaae7b1402cfe6bcdd2d8049f15fc07d3dde7635" +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="autoconf:host automake:host m4:host make:host zlib:host" +PKG_DEPENDS_TARGET="toolchain zlib elfutils:host libarchive" +PKG_LONGDESC="A collection of utilities to handle ELF objects." +PKG_TOOLCHAIN="autotools" +PKG_BUILD_FLAGS="+pic -cfg-libs -cfg-libs:host" + +if [ "${DISTRO_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" + +pre_configure_target() { + export PKG_CONFIG="${PKG_CONFIG} --static" +} + +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 0000000000..b6f8d1524e --- /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 +@@ -29,7 +29,11 @@ + pkginclude_HEADERS = version.h + + SUBDIRS = config lib libelf libcpu backends libebl libdwelf libdwfl \ +- libdwfl_stacktrace libdw libasm debuginfod src po doc tests ++ libdwfl_stacktrace libdw libasm debuginfod po doc tests ++ ++if BUILD_PROGRAMS ++ SUBDIRS += src ++endif + + EXTRA_DIST = elfutils.spec GPG-KEY NOTES CONTRIBUTING SECURITY \ + COPYING COPYING-GPLV2 COPYING-LGPLV3 CONDUCT +diff --git a/configure.ac b/configure.ac +index 5a2dc37..a1e856a 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -82,6 +82,11 @@ + + 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) ++ + # Provided by gnulib's m4/std-gnu11.m4 for autoconf pre 2.70 + AC_PROG_CC + AS_IF([test "x$ac_cv_prog_cc_c11" = "xno"], +-- +2.7.4 + diff --git a/packages/devel/elfutils/patches/elfutils-002-libelf--Add-libeu-objects-to-libelf.a-static-archive.patch b/packages/devel/elfutils/patches/elfutils-002-libelf--Add-libeu-objects-to-libelf.a-static-archive.patch new file mode 100644 index 0000000000..7868431a8b --- /dev/null +++ b/packages/devel/elfutils/patches/elfutils-002-libelf--Add-libeu-objects-to-libelf.a-static-archive.patch @@ -0,0 +1,36 @@ +From f5d6e088f84dd05278c4698a21cbf1ff4569978d Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Tue, 22 Oct 2024 15:03:42 +0200 +Subject: [PATCH] libelf: Add libeu objects to libelf.a static archive + +libelf might use some symbols from libeu.a, specifically the eu-search +wrappers. But we don't ship libeu.a separately. So include the libeu +objects in the libelf.a archive to facilitate static linking. + + * libelf/Makefile.am (libeu_objects): New variable. + (libelf_a_LIBADD): New, add libeu_objects. + +https://sourceware.org/bugzilla/show_bug.cgi?id=32293 + +Signed-off-by: Mark Wielaard +--- + libelf/Makefile.am | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/libelf/Makefile.am b/libelf/Makefile.am +index 3402863ef..2d3dbdf22 100644 +--- a/libelf/Makefile.am ++++ b/libelf/Makefile.am +@@ -122,6 +122,9 @@ libelf.so: $(srcdir)/libelf.map $(libelf_so_LIBS) $(libelf_so_DEPS) + @$(textrel_check) + $(AM_V_at)ln -fs $@ $@.$(VERSION) + ++libeu_objects = $(shell $(AR) t ../lib/libeu.a) ++libelf_a_LIBADD = $(addprefix ../lib/,$(libeu_objects)) ++ + install: install-am libelf.so + $(mkinstalldirs) $(DESTDIR)$(libdir) + $(INSTALL_PROGRAM) libelf.so $(DESTDIR)$(libdir)/libelf-$(PACKAGE_VERSION).so +-- +2.43.5 + diff --git a/packages/devel/fakeroot/package.mk b/packages/devel/fakeroot/package.mk new file mode 100644 index 0000000000..0500d4425c --- /dev/null +++ b/packages/devel/fakeroot/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="fakeroot" +PKG_VERSION="1.37.1.2" +PKG_SHA256="959496928c8a676ec8377f665ff6a19a707bfad693325f9cc4a4126642f53224" +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_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 0000000000..6d6b50a719 --- /dev/null +++ b/packages/devel/fakeroot/patches/fakeroot-001-disable-docs-tests.patch @@ -0,0 +1,23 @@ +--- a/configure.ac ++++ b/configure.ac +@@ -745,9 +745,7 @@ AM_CONDITIONAL([MACOSX], [test x$macosx + AC_CONFIG_FILES([ + Makefile + scripts/Makefile +- doc/Makefile +- doc/de/Makefile doc/es/Makefile doc/fr/Makefile doc/nl/Makefile doc/pt/Makefile doc/ro/Makefile doc/sv/Makefile +- test/Makefile test/defs]) ++ ]) + AC_OUTPUT + + dnl Local variables: +--- a/Makefile.am ++++ b/Makefile.am +@@ -1,6 +1,6 @@ + AUTOMAKE_OPTIONS=foreign + ACLOCAL_AMFLAGS = -I build-aux +-SUBDIRS=doc scripts test ++SUBDIRS=scripts + + noinst_LTLIBRARIES = libcommunicate.la libmacosx.la libfakeroot_time64.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 0000000000..fd53278d76 --- /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="25.2.10" +PKG_SHA256="b9c2df49707c57a48fc0923d52b8c73beb72d675f9d44b2211e4569be40a7421" +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="cmake:host ninja:host" +PKG_DEPENDS_TARGET="cmake:host ninja:host gcc:host" +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 0000000000..0d992066c2 --- /dev/null +++ b/packages/devel/flex/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="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 flex:host" +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="--disable-bootstrap \ + 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/flex-0001-use-flex-host-for-target-cross-compile.patch b/packages/devel/flex/patches/flex-0001-use-flex-host-for-target-cross-compile.patch new file mode 100644 index 0000000000..6d9ef2fd6c --- /dev/null +++ b/packages/devel/flex/patches/flex-0001-use-flex-host-for-target-cross-compile.patch @@ -0,0 +1,11 @@ +--- a/src/Makefile.am 2025-05-25 13:43:29.363027456 +0000 ++++ b/src/Makefile.am 2025-05-25 13:44:38.701129436 +0000 +@@ -100,7 +100,7 @@ + ./stage1flex$(EXEEXT) $(AM_LFLAGS) $(LFLAGS) -o $@ $(srcdir)/scan.l + else + stage1scan.c: scan.c +- sed 's|^\(#line .*\)"'`printf %s $< | sed 's|[][\\\\.*]|\\\\&|g'`'"|\1"$@"|g' $< > $@ ++ ../../.$(HOST_NAME)/src/stage1flex$(EXEEXT) $(AM_LFLAGS) $(LFLAGS) -o $@ $(srcdir)/scan.l + endif + + dist-hook: scan.l flex$(EXEEXT) 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 0000000000..e880345409 --- /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/flex/patches/flex-0262-AC_USE_SYSTEM_EXTENSIONS-in-configure-ac.patch b/packages/devel/flex/patches/flex-0262-AC_USE_SYSTEM_EXTENSIONS-in-configure-ac.patch new file mode 100644 index 0000000000..22592df348 --- /dev/null +++ b/packages/devel/flex/patches/flex-0262-AC_USE_SYSTEM_EXTENSIONS-in-configure-ac.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-0674-Match--malloc--signature-to-its-use.patch b/packages/devel/flex/patches/flex-0674-Match--malloc--signature-to-its-use.patch new file mode 100644 index 0000000000..9742b2317e --- /dev/null +++ b/packages/devel/flex/patches/flex-0674-Match--malloc--signature-to-its-use.patch @@ -0,0 +1,22 @@ +From 4b142954b54a57a9b0af0a9661056a9c39a8fa95 Mon Sep 17 00:00:00 2001 +From: Richard Barnes +Date: Wed, 2 Oct 2024 10:35:09 -0700 +Subject: [PATCH] Match `malloc` signature to its use + +--- + lib/malloc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/malloc.c b/lib/malloc.c +index 75e8ef97c..701b9b39d 100755 +--- a/lib/malloc.c ++++ b/lib/malloc.c +@@ -3,7 +3,7 @@ + + #include + +- void *malloc (); ++ void *malloc (size_t n); + + /* Allocate an N-byte block of memory from the heap. + If N is zero, allocate a 1-byte block. */ diff --git a/packages/devel/fribidi/package.mk b/packages/devel/fribidi/package.mk new file mode 100644 index 0000000000..a43e3f6930 --- /dev/null +++ b/packages/devel/fribidi/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="fribidi" +PKG_VERSION="1.0.16" +PKG_SHA256="1b1cde5b235d40479e91be2f0e88a309e3214c8ab470ec8a2744d82a5a9ea05c" +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_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 0000000000..120b3925d0 --- /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 0000000000..4f8f97944e --- /dev/null +++ b/packages/devel/gettext/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="gettext" +PKG_VERSION="0.25.1" +PKG_SHA256="2c8294be238f03fb3fa65b8051057e5b68167f3e21f08008070cf40a7051ba22" +PKG_LICENSE="GPL" +PKG_SITE="https://www.gnu.org/s/gettext/" +PKG_URL="https://mirrors.kernel.org/gnu/gettext/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_HOST="make:host" +PKG_DEPENDS_TARGET="autotools:host make:host gcc:host" +PKG_LONGDESC="A program internationalization library and tools." +PKG_BUILD_FLAGS="+local-cc" + +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" + +PKG_CONFIGURE_OPTS_TARGET="--disable-rpath" + +post_configure_target() { + libtool_remove_rpath gettext-runtime/libasprintf/libtool + libtool_remove_rpath gettext-tools/libtool +} diff --git a/packages/devel/gettext/patches/gettext-0001-0.18.2-non_interactive.patch b/packages/devel/gettext/patches/gettext-0001-0.18.2-non_interactive.patch new file mode 100644 index 0000000000..94182b8510 --- /dev/null +++ b/packages/devel/gettext/patches/gettext-0001-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 +@@ -1304,10 +1304,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-0002-dont_build_docs_and_examples.patch b/packages/devel/gettext/patches/gettext-0002-dont_build_docs_and_examples.patch new file mode 100644 index 0000000000..e428572f1c --- /dev/null +++ b/packages/devel/gettext/patches/gettext-0002-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 + ACLOCAL_AMFLAGS = -I m4 -I ../gettext-runtime/m4 -I ../m4 -I gnulib-m4 -I libgrep/gnulib-m4 -I libgettextpo/gnulib-m4 -I tests/gnulib-m4 + +-SUBDIRS = gnulib-lib libgrep src libgettextpo po its projects styles emacs misc man m4 tests system-tests gnulib-tests examples doc ++SUBDIRS = gnulib-lib libgrep src libgettextpo po its projects styles emacs misc man m4 tests system-tests gnulib-tests + + EXTRA_DIST = misc/disclaim-translations.txt + 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 +@@ -3673,7 +3673,7 @@ + top_srcdir = @top_srcdir@ + AUTOMAKE_OPTIONS = 1.5 gnu + ACLOCAL_AMFLAGS = -I m4 -I ../gettext-runtime/m4 -I ../m4 -I gnulib-m4 -I libgrep/gnulib-m4 -I libgettextpo/gnulib-m4 -I tests/gnulib-m4 +-SUBDIRS = gnulib-lib libgrep src libgettextpo po its projects styles emacs misc man m4 tests system-tests gnulib-tests examples doc ++SUBDIRS = 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 0000000000..c0c43543af --- /dev/null +++ b/packages/devel/glib/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) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="glib" +PKG_VERSION="2.85.1" +PKG_SHA256="d3f57bcd4202d93aa547ffa1d2a5dbd380a05dbaac04cc291bd7dfce93b4a8e5" +PKG_LICENSE="LGPL" +PKG_SITE="https://www.gtk.org/" +PKG_URL="https://download.gnome.org/sources/glib/$(get_pkg_version_maj_min)/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_HOST="libffi:host pcre2:host Python3:host meson:host ninja:host" +PKG_DEPENDS_TARGET="meson:host ninja:host gcc:host glib:host libffi pcre2 Python3:host util-linux zlib" +PKG_LONGDESC="A library which includes support routines for C such as lists, trees, hashes, memory allocation." + +PKG_MESON_OPTS_HOST="-Ddefault_library=static \ + -Dinstalled_tests=false \ + -Dlibmount=disabled \ + -Dintrospection=disabled \ + -Dtests=false" + +PKG_MESON_OPTS_TARGET="-Ddefault_library=shared \ + -Dinstalled_tests=false \ + -Dselinux=disabled \ + -Dxattr=true \ + -Dgtk_doc=false \ + -Dman=false \ + -Ddtrace=false \ + -Dsystemtap=false \ + -Dbsymbolic_functions=true \ + -Dforce_posix_threads=true \ + -Dtests=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 + + # glib binaries must be executed from toolchain + sed -e "s#bindir=\${prefix}/bin#bindir=${TOOLCHAIN}/bin#" -i "${SYSROOT_PREFIX}/usr/lib/pkgconfig/"{gio,glib}-2.0.pc +} diff --git a/packages/devel/glibc/config/gai.conf b/packages/devel/glibc/config/gai.conf new file mode 100644 index 0000000000..4616ed005b --- /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 0000000000..d1a59f73a9 --- /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 0000000000..eba159e8fc --- /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 0000000000..4391cdd21e --- /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 0000000000..c9e80a9d03 --- /dev/null +++ b/packages/devel/glibc/package.mk @@ -0,0 +1,157 @@ +# 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.41" +PKG_SHA256="a5a26b22f545d6b7d7b3dd828e11e428f24f4fac43c934fb071b6a7d0828e901" +PKG_LICENSE="GPL" +PKG_SITE="https://www.gnu.org/software/libc/" +PKG_URL="https://mirrors.kernel.org/gnu/glibc/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="ccache:host autotools:host linux:host gcc:bootstrap Python3:host" +PKG_DEPENDS_INIT="glibc" +PKG_LONGDESC="The Glibc package contains the main C library." +PKG_BUILD_FLAGS="+bfd" + +if [ "${TARGET_ARCH}" = "arm" ] || [ "${TARGET_ARCH}" = "aarch64" ]; then + PKG_PATCH_DIRS="widevine-arm" +fi + +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=6.12.0 \ + --without-cvs \ + --without-gd \ + --disable-build-nscd \ + --disable-nscd \ + --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_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") + + export CFLAGS=$(echo ${CFLAGS} | sed -e "s|-Wunused-but-set-variable||g") + export CFLAGS="${CFLAGS} -Wno-unused-variable" + + 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 + +--- a/nss/getaddrinfo.c ++++ b/nss/getaddrinfo.c +@@ -730,6 +730,38 @@ gaih_inet (const char *name, const struc + if (res_ctx == NULL) + no_more = 1; + ++ /* 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; +@@ -737,7 +769,7 @@ gaih_inet (const char *name, const struc + + /* 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) +@@ -826,25 +858,27 @@ gaih_inet (const char *name, const struc + + 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) + { + if ((result = gethosts (fct, AF_INET6, name, req, tmpbuf, + res, &status, &no_data)) != 0) + { + __resolv_context_put (res_ctx); + goto out; + } + 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) || !res->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) || !res->got_ipv6))) ++ && suppress_af != AF_INET) + { + if ((result = gethosts (fct, AF_INET, name, req, tmpbuf, + res, &status, &no_data)) != 0) +--- a/sysdeps/unix/sysv/linux/check_pf.c ++++ b/sysdeps/unix/sysv/linux/check_pf.c +@@ -224,7 +224,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/glibc/patches/widevine-arm/glibc-HACK-Don-t-check-GLIBC_ABI_DT_RELR-support-for-Chrom.patch b/packages/devel/glibc/patches/widevine-arm/glibc-HACK-Don-t-check-GLIBC_ABI_DT_RELR-support-for-Chrom.patch new file mode 100644 index 0000000000..8ed6ad59ca --- /dev/null +++ b/packages/devel/glibc/patches/widevine-arm/glibc-HACK-Don-t-check-GLIBC_ABI_DT_RELR-support-for-Chrom.patch @@ -0,0 +1,28 @@ +From 85892fbc0d6f64f564f0d4c9514a7183ad8eb985 Mon Sep 17 00:00:00 2001 +From: alex +Date: Sun, 17 Jul 2022 12:16:20 +0200 +Subject: [PATCH] HACK: Don't check GLIBC_ABI_DT_RELR support for ChromeOS + libwidevinecdm.so + +Required starting with glibc 2.36 +--- + elf/dl-version.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/elf/dl-version.c b/elf/dl-version.c +index cda0889209..058394f148 100644 +--- a/elf/dl-version.c ++++ b/elf/dl-version.c +@@ -373,7 +373,8 @@ _dl_check_map_versions (struct link_map *map, int verbose, int trace_mode) + if (d->d_tag == DT_NEEDED) + { + const char *name = strtab + d->d_un.d_val; +- if (strncmp (name, "libc.so.", 8) == 0) ++ if (strncmp (name, "libc.so.", 8) == 0 && ++ strstr (map->l_name, "libwidevinecdm.so") == NULL) + { + _dl_exception_create + (&exception, DSO_FILENAME (map->l_name), +-- +2.37.1 + diff --git a/packages/devel/glibc/patches/widevine-arm/glibc-tls-libwidevinecdm.so-since-4.10.2252.0-has-TLS-with.patch b/packages/devel/glibc/patches/widevine-arm/glibc-tls-libwidevinecdm.so-since-4.10.2252.0-has-TLS-with.patch new file mode 100644 index 0000000000..15f36bee8c --- /dev/null +++ b/packages/devel/glibc/patches/widevine-arm/glibc-tls-libwidevinecdm.so-since-4.10.2252.0-has-TLS-with.patch @@ -0,0 +1,28 @@ +From 61b3b546450ae0a70cb4a57fbb0e0fc47b331370 Mon Sep 17 00:00:00 2001 +From: Portisch +Date: Sat, 5 Jun 2021 19:41:25 +0200 +Subject: [PATCH] tls: libwidevinecdm.so: since 4.10.2252.0 has TLS with + 64-byte alignment Change the max_align to 64U instead 16 to make it possible + to use dlopen again. Tests by changing TLS_TCB_ALIGN directly showed up some + random crashes. Reverence: https://lkml.org/lkml/2020/7/3/754 + +Without this patch, a SEGV is encountered when dlopen(libwidevinecdm.so), +inside dl-init.c call_init() +--- + elf/dl-tls.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/elf/dl-tls.c ++++ b/elf/dl-tls.c +@@ -220,6 +220,11 @@ void + _dl_determine_tlsoffset (void) + { + size_t max_align = TCB_ALIGNMENT; ++ /* libwidevinecdm.so: since 4.10.2252.0 has TLS with 64-byte alignment. ++ Since TLS is initialized before audit modules are loaded and slotinfo ++ information is available, this is not taken into account below in ++ the audit case. */ ++ max_align = MAX (max_align, 64U); + size_t freetop = 0; + size_t freebottom = 0; + diff --git a/packages/devel/gmp/package.mk b/packages/devel/gmp/package.mk new file mode 100644 index 0000000000..a9177c79ee --- /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.3.0" +PKG_SHA256="a3c2b80201b89e68616f4ad30bc66aee4927c3ce50e33929ca819d5c43538898" +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="autotools:host gcc:host" +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/gmp/patches/0001-acinclude.m4-fix-std-c23-build-failure.patch b/packages/devel/gmp/patches/0001-acinclude.m4-fix-std-c23-build-failure.patch new file mode 100644 index 0000000000..70ee4a1fe4 --- /dev/null +++ b/packages/devel/gmp/patches/0001-acinclude.m4-fix-std-c23-build-failure.patch @@ -0,0 +1,73 @@ +From 396d0ca56134936a8b89cba07518bcf8c4c14dc6 Mon Sep 17 00:00:00 2001 +From: Rudi Heitbaum +Date: Tue, 21 Jan 2025 10:18:09 +0000 +Subject: [PATCH V2] acinclude.m4: fix -std=c23 build failure + +Add prototype to configure test function as c23 removes unprototyped +functions. + +gcc-15 switched to -std=c23 by default: + + https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=55e3bd376b2214e200fa76d12b67ff259b06c212 + +As a result `configure` fails with: + conftest.c: In function 'f': + conftest.c:12:48: error: too many arguments to function 'g'; expected 0, have 6 + 12 | for(i=0;i<1;i++){if(e(got,got,9,d[i].n)==0)h();g(i,d[i].src,d[i].n,got,d[i].want,9);if(d[i].n)h();}} + | ^ ~ + conftest.c:7:6: note: declared here + 7 | void g(){} + | ^ + +Upstream: hg log --patch --rev 18477:8e7bb4ae7a18 +Link: https://gmplib.org/list-archives/gmp-bugs/2024-November/005550.html +Link: https://gmplib.org/list-archives/gmp-devel/2025-January/006281.html +Signed-off-by: Rudi Heitbaum +--- +v2: +- update prototype to allow type checking +--- + acinclude.m4 | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/acinclude.m4 b/acinclude.m4 +index fddb5fb07a..2d41de6328 100644 +--- a/acinclude.m4 ++++ b/acinclude.m4 +@@ -609,7 +609,7 @@ GMP_PROG_CC_WORKS_PART([$1], [long long reliability test 1], + + #if defined (__GNUC__) && ! defined (__cplusplus) + typedef unsigned long long t1;typedef t1*t2; +-void g(){} ++void g(int,const t1 *,t1,t1 *,const t1 *,int){} + void h(){} + static __inline__ t1 e(t2 rp,t2 up,int n,t1 v0) + {t1 c,x,r;int i;if(v0){c=1;for(i=1;i +Date: Fri, 31 Jan 2025 04:24:59 +0000 +Subject: [PATCH] configure: fix -std=c23 build failure + +--- + configure | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/configure b/configure +index 7910aa0970..bd4342d124 100755 +--- a/configure ++++ b/configure +@@ -6568,7 +6568,7 @@ if test "$gmp_prog_cc_works" = yes; then + + #if defined (__GNUC__) && ! defined (__cplusplus) + typedef unsigned long long t1;typedef t1*t2; +-void g(){} ++void g(int i,const t1 *src,t1 n,t1 *got,const t1 *want,int j){} + void h(){} + static __inline__ t1 e(t2 rp,t2 up,int n,t1 v0) + {t1 c,x,r;int i;if(v0){c=1;for(i=1;i +Date: Sat, 10 Feb 2024 09:33:48 +0100 +Subject: [PATCH] cf/largefile.m4: Fix build with autoconf-2.72 + +Fixes https://github.com/heimdal/heimdal/issues/1201 +--- + cf/largefile.m4 | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/cf/largefile.m4 b/cf/largefile.m4 +index 5c54897be4..cdbbc55431 100644 +--- a/cf/largefile.m4 ++++ b/cf/largefile.m4 +@@ -10,7 +10,7 @@ dnl with generated code, such as lex + if test "$enable_largefile" != no -a "$ac_cv_sys_large_files" != no; then + CPPFLAGS="$CPPFLAGS -D_LARGE_FILES=$ac_cv_sys_large_files" + fi +-if test "$enable_largefile" != no -a "$ac_cv_sys_file_offset_bits" != no; then ++if test "$enable_largefile" != no -a "$ac_cv_sys_file_offset_bits" != no && test -n "$ac_cv_sys_file_offset_bits"; then + CPPFLAGS="$CPPFLAGS -D_FILE_OFFSET_BITS=$ac_cv_sys_file_offset_bits" + fi + ]) diff --git a/packages/devel/hwdata/package.mk b/packages/devel/hwdata/package.mk new file mode 100644 index 0000000000..0d2b656fd0 --- /dev/null +++ b/packages/devel/hwdata/package.mk @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2022-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="hwdata" +PKG_VERSION="0.397" +PKG_SHA256="09eee39e73a63ab27af651ab6afdd13d6e5c3485872f2cd406b35e4d80ffdb0b" +PKG_LICENSE="GPL-2.0" +PKG_SITE="https://github.com/vcrhonek/hwdata" +PKG_URL="https://github.com/vcrhonek/hwdata/archive/refs/tags/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="hwdata contains various hardware identification and configuration data, such as the pci.ids and usb.ids databases" + +pre_configure_target() { + # hwdata fails to build in subdirs + cd ${PKG_BUILD} + rm -rf .${TARGET_NAME} + + sed -i "s&@prefix@|&@prefix@|${PKG_INSTALL}&" Makefile + sed -i "s&prefix=@prefix@&prefix=/usr&" hwdata.pc.in +} diff --git a/packages/devel/intltool/package.mk b/packages/devel/intltool/package.mk new file mode 100644 index 0000000000..fefcb2299b --- /dev/null +++ b/packages/devel/intltool/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="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)." +PKG_BUILD_FLAGS="-cfg-libs:host" + +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 0000000000..dcf9105427 --- /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/json-c/package.mk b/packages/devel/json-c/package.mk new file mode 100644 index 0000000000..07a7057032 --- /dev/null +++ b/packages/devel/json-c/package.mk @@ -0,0 +1,13 @@ +# 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="json-c" +PKG_VERSION="0.18" +PKG_SHA256="876ab046479166b869afc6896d288183bbc0e5843f141200c677b3e8dfb11724" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/json-c/json-c" +PKG_URL="https://s3.amazonaws.com/json-c_releases/releases/json-c-${PKG_VERSION%-*}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Implements a reference counting object model that allows you to easily construct JSON objects in C." diff --git a/packages/devel/json-c/patches/json-c-888-build-with-cmake-4.0.0.patch b/packages/devel/json-c/patches/json-c-888-build-with-cmake-4.0.0.patch new file mode 100644 index 0000000000..b9c96ade22 --- /dev/null +++ b/packages/devel/json-c/patches/json-c-888-build-with-cmake-4.0.0.patch @@ -0,0 +1,21 @@ +From 42864e12b0d7af01b1cf989d6da9e9a4477775a1 Mon Sep 17 00:00:00 2001 +From: Rudi Heitbaum +Date: Fri, 28 Mar 2025 23:14:48 +1100 +Subject: [PATCH] Allow build with cmake 4.0.0 + +Update the min version to match parent CMakeLists.txt 3.9...3.12 +--- + apps/CMakeLists.txt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt +index f7c9dec633..ef2271d131 100644 +--- a/apps/CMakeLists.txt ++++ b/apps/CMakeLists.txt +@@ -1,5 +1,5 @@ + +-cmake_minimum_required(VERSION 2.8) # see ../CMakeLists.txt for why 2.8 ++cmake_minimum_required(VERSION 3.9...3.12) + + if(POLICY CMP0075) + cmake_policy(SET CMP0075 NEW) diff --git a/packages/devel/json-glib/package.mk b/packages/devel/json-glib/package.mk new file mode 100644 index 0000000000..74590cc630 --- /dev/null +++ b/packages/devel/json-glib/package.mk @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="json-glib" +PKG_VERSION="1.10.6" +PKG_SHA256="d23cbd4094a32cc05cf22cd87a83da1f799e182e286133b49fde3c9241a32006" +PKG_LICENSE="LGPL-2.1" +PKG_SITE="https://github.com/GNOME/json-glib" +PKG_URL="https://github.com/GNOME/json-glib/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain glib" +PKG_LONGDESC="JSON-GLib implements a full suite of JSON-related tools using GLib and GObject." + +PKG_MESON_OPTS_TARGET="-Dintrospection=disabled \ + -Dgtk_doc=disabled \ + -Dman=false \ + -Dtests=false" diff --git a/packages/devel/libaio/package.mk b/packages/devel/libaio/package.mk new file mode 100644 index 0000000000..5ea574884e --- /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.113" +PKG_SHA256="716c7059703247344eb066b54ecbc3ca2134f0103307192e6c2b7dab5f9528ab" +PKG_LICENSE="GPL" +PKG_SITE="https://pagure.io/libaio" +PKG_URL="https://pagure.io/${PKG_NAME}/archive/${PKG_NAME}-${PKG_VERSION}/${PKG_NAME}-${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="make:host gcc:host" +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/libbpf/package.mk b/packages/devel/libbpf/package.mk new file mode 100644 index 0000000000..520d0fe4c6 --- /dev/null +++ b/packages/devel/libbpf/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libbpf" +PKG_VERSION="1.5.1" +PKG_SHA256="e5ff89750e48ab5ecdfc02a759aa0dacd1e7980e98e16bdb4bfa8ff0b3b4b98f" +PKG_LICENSE="LGPL-2.1" +PKG_SITE="https://github.com/libbpf/libbpf" +PKG_URL="https://github.com/libbpf/libbpf/archive/refs/tags/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain elfutils" +PKG_LONGDESC="libbpf supports building BPF CO-RE-enabled applications" +PKG_TOOLCHAIN="make" + +make_target() { + make BUILD_STATIC_ONLY=1 \ + PREFIX=${SYSROOT_PREFIX}/usr \ + -C src +} + +makeinstall_target() { + make BUILD_STATIC_ONLY=1 \ + PREFIX=${SYSROOT_PREFIX}/usr \ + -C src install +} diff --git a/packages/devel/libbpf/patches/libbpf-fix-crosscompile-and-sysroot.patch b/packages/devel/libbpf/patches/libbpf-fix-crosscompile-and-sysroot.patch new file mode 100644 index 0000000000..07be822e60 --- /dev/null +++ b/packages/devel/libbpf/patches/libbpf-fix-crosscompile-and-sysroot.patch @@ -0,0 +1,43 @@ +diff --git a/src/Makefile b/src/Makefile +index 81ea6b8..7ab5f13 100644 +--- a/src/Makefile ++++ b/src/Makefile +@@ -67,15 +67,12 @@ INSTALL = install + DESTDIR ?= + + HOSTARCH = $(firstword $(subst -, ,$(shell $(CC) -dumpmachine))) +-ifeq ($(filter-out %64 %64be %64eb %64le %64el s390x, $(HOSTARCH)),) +- LIBSUBDIR := lib64 +-else +- LIBSUBDIR := lib +-endif ++LIBSUBDIR := lib + + # By default let the pc file itself use ${prefix} in includedir/libdir so that + # the prefix can be overridden at runtime (eg: --define-prefix) + ifndef LIBDIR ++ PREFIX_PC := /usr + LIBDIR_PC := $$\{prefix\}/$(LIBSUBDIR) + else + LIBDIR_PC := $(LIBDIR) +@@ -106,7 +103,7 @@ $(OBJDIR)/libbpf.so.$(LIBBPF_VERSION): $(SHARED_OBJS) + $^ $(ALL_LDFLAGS) -o $@ + + $(OBJDIR)/libbpf.pc: force | $(OBJDIR) +- $(Q)sed -e "s|@PREFIX@|$(PREFIX)|" \ ++ $(Q)sed -e "s|@PREFIX@|$(PREFIX_PC)|" \ + -e "s|@LIBDIR@|$(LIBDIR_PC)|" \ + -e "s|@VERSION@|$(LIBBPF_VERSION)|" \ + < libbpf.pc.template > $@ +diff --git a/src/libbpf.pc.template b/src/libbpf.pc.template +index b45ed53..fe6ddde 100644 +--- a/src/libbpf.pc.template ++++ b/src/libbpf.pc.template +@@ -7,6 +7,6 @@ includedir=${prefix}/include + Name: libbpf + Description: BPF library + Version: @VERSION@ +-Libs: -L${libdir} -lbpf ++Libs: -L${libdir} -lbpf -lz + Requires.private: libelf zlib + Cflags: -I${includedir} diff --git a/packages/devel/libcap-ng/package.mk b/packages/devel/libcap-ng/package.mk new file mode 100644 index 0000000000..77be842ab5 --- /dev/null +++ b/packages/devel/libcap-ng/package.mk @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2023-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libcap-ng" +PKG_VERSION="0.8.5" +PKG_SHA256="e4be07fdd234f10b866433f224d183626003c65634ed0552b02e654a380244c2" +PKG_LICENSE="LGPLv2.1" +PKG_SITE="https://github.com/stevegrubb/libcap-ng" +PKG_URL="https://github.com/stevegrubb/libcap-ng/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Libcap-ng is a library for Linux that makes using posix capabilities easy." +PKG_TOOLCHAIN="autotools" +PKG_BUILD_FLAGS="-cfg-libs" + +PKG_CONFIGURE_OPTS_TARGET="--enable-static --disable-shared --with-python3=no" diff --git a/packages/devel/libcap/package.mk b/packages/devel/libcap/package.mk new file mode 100644 index 0000000000..aa6e927537 --- /dev/null +++ b/packages/devel/libcap/package.mk @@ -0,0 +1,71 @@ +# 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.76" +PKG_SHA256="629da4ab29900d0f7fcc36227073743119925fd711c99a1689bbf5c9b40c8e6f" +PKG_LICENSE="GPL" +PKG_SITE="https://git.kernel.org/pub/scm/libs/libcap/libcap.git/log/" +PKG_URL="https://www.kernel.org/pub/linux/libs/security/linux-privs/libcap2/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_HOST="ccache:host" +PKG_DEPENDS_TARGET="make:host gcc:host" +PKG_LONGDESC="A library for getting and setting POSIX.1e capabilities." +PKG_BUILD_FLAGS="+pic" + +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 \ + USE_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 \ + USE_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/package.mk b/packages/devel/libcec/package.mk new file mode 100644 index 0000000000..736acf95ca --- /dev/null +++ b/packages/devel/libcec/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="libcec" +PKG_VERSION="7.1.1" +PKG_SHA256="7f7da95a4c1e7160d42ca37a3ac80cf6f389b317e14816949e0fa5e2edf4cc64" +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 \ + -DSKIP_PYTHON_WRAPPER=1 \ + -DHAVE_IMX_API=0 \ + -DHAVE_AOCEC_API=0 \ + -DGIT_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/libclc/package.mk b/packages/devel/libclc/package.mk new file mode 100644 index 0000000000..6d775676b7 --- /dev/null +++ b/packages/devel/libclc/package.mk @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2024-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libclc" +PKG_VERSION="$(get_pkg_version llvm)" +PKG_LICENSE="Apache-2.0" +PKG_URL="" +PKG_DEPENDS_HOST="toolchain:host llvm:host" +PKG_LONGDESC="Low-Level Virtual Machine (LLVM) is a compiler infrastructure." +PKG_DEPENDS_UNPACK+=" llvm" +PKG_PATCH_DIRS+=" $(get_pkg_directory llvm)/patches" +PKG_TOOLCHAIN="cmake" + +unpack() { + mkdir -p ${PKG_BUILD} + tar --strip-components=1 -xf ${SOURCES}/llvm/llvm-${PKG_VERSION}.tar.xz -C ${PKG_BUILD} +} + +pre_configure() { + PKG_CMAKE_SCRIPT="${PKG_BUILD}/libclc/CMakeLists.txt" +} + +pre_configure_host() { + LIBCLC_TARGETS_TO_BUILD="spirv64-mesa3d-" + + mkdir -p "${PKG_BUILD}/.${HOST_NAME}" + cd ${PKG_BUILD}/.${HOST_NAME} + PKG_CMAKE_OPTS_HOST="-DLIBCLC_TARGETS_TO_BUILD=${LIBCLC_TARGETS_TO_BUILD}" +} diff --git a/packages/devel/libdaemon/package.mk b/packages/devel/libdaemon/package.mk new file mode 100644 index 0000000000..93a42a7f3d --- /dev/null +++ b/packages/devel/libdaemon/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="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="autotools:host make:host sed:host gcc:host" +PKG_LONGDESC="A lightweight C library which eases the writing of UNIX daemons." +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="ac_cv_func_setpgrp_void=no \ + --enable-static \ + --disable-shared \ + --disable-lynx" diff --git a/packages/devel/libdisplay-info/package.mk b/packages/devel/libdisplay-info/package.mk new file mode 100644 index 0000000000..f01acd9f87 --- /dev/null +++ b/packages/devel/libdisplay-info/package.mk @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2023-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libdisplay-info" +PKG_VERSION="0.2.0" +PKG_SHA256="5a2f002a16f42dd3540c8846f80a90b8f4bdcd067a94b9d2087bc2feae974176" +PKG_LICENSE="MIT" +PKG_SITE="https://gitlab.freedesktop.org/emersion/libdisplay-info" +PKG_URL="https://gitlab.freedesktop.org/emersion/libdisplay-info/-/releases/${PKG_VERSION}/downloads/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain hwdata" +PKG_LONGDESC="EDID and DisplayID library" diff --git a/packages/devel/libevent/package.mk b/packages/devel/libevent/package.mk new file mode 100644 index 0000000000..21ee2552a9 --- /dev/null +++ b/packages/devel/libevent/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libevent" +PKG_VERSION="2.1.12" +PKG_SHA256="92e6de1be9ec176428fd2367677e61ceffc2ee1cb119035037a27d346b0403bb" +PKG_LICENSE="BSD-3-Clause" +PKG_SITE="https://libevent.org/" +PKG_URL="https://github.com/libevent/libevent/releases/download/release-${PKG_VERSION}-stable/libevent-${PKG_VERSION}-stable.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="libevent – an event notification library" + +PKG_CMAKE_OPTS_TARGET="-DEVENT__LIBRARY_TYPE=STATIC \ + -DEVENT__DISABLE_DEBUG_MODE=ON \ + -DEVENT__DISABLE_MM_REPLACEMENT=ON \ + -DEVENT__DISABLE_THREAD_SUPPORT=ON \ + -DEVENT__DISABLE_OPENSSL=ON \ + -DEVENT__DISABLE_BENCHMARK=ON \ + -DEVENT__DISABLE_TESTS=ON \ + -DEVENT__DISABLE_REGRESS=ON \ + -DEVENT__DISABLE_SAMPLES=ON" diff --git a/packages/devel/libevent/patches/libevent-0001-build-with-cmake-4.0.0.patch b/packages/devel/libevent/patches/libevent-0001-build-with-cmake-4.0.0.patch new file mode 100644 index 0000000000..f05079e043 --- /dev/null +++ b/packages/devel/libevent/patches/libevent-0001-build-with-cmake-4.0.0.patch @@ -0,0 +1,59 @@ +From bd2de4836b6b48d64da0cf010727209ad259a4f4 Mon Sep 17 00:00:00 2001 +From: Azat Khuzhin +Date: Wed, 26 Jun 2019 00:59:41 +0300 +Subject: [PATCH] Require cmake >= 3.1.2 (for correct openssl 1.0.2 detection) + +@ygj6 reported: + "My platform is MacOS 10.13.5, This problem only happens on Mac. + + As written in the file CMakeLists.txt, the minimum required version of cmake is 3.1: + cmake_minimum_required(VERSION 3.1 FATAL_ERROR) + So I built this project with cmake-3.1.0, but I got the following errors: + + CMake Error at /usr/local/cmake-3.1.0/share/cmake/Modules/FindOpenSSL.cmake:293 (list): + list GET given empty list + Call Stack (most recent call first): + CMakeLists.txt:824 (find_package) + + CMake Error at /usr/local/cmake-3.1.0/share/cmake/Modules/FindOpenSSL.cmake:294 (list): + list GET given empty list + Call Stack (most recent call first): + CMakeLists.txt:824 (find_package) + + CMake Error at /usr/local/cmake-3.1.0/share/cmake/Modules/FindOpenSSL.cmake:296 (list): + list GET given empty list + Call Stack (most recent call first): + CMakeLists.txt:824 (find_package) + + CMake Error at /usr/local/cmake-3.1.0/share/cmake/Modules/FindOpenSSL.cmake:298 (list): + list GET given empty list + Call Stack (most recent call first): + CMakeLists.txt:824 (find_package) + + I googled this error and got this answer: + https://bugs.archlinux.org/task/43688 + + It is a bug in FindOpenSSL.cmake on cmake-3.1.0 and fixed on cmake-3.1.2 . + Of course, It was successful when rebuilding with cmake-3.1.2 . + So I suggest setting the minimum version required for cmake to 3.1.2 or higher. + " + +Closes: #845 +Refs: https://github.com/Kitware/CMake/commit/de4ccee75a89519f95fcbcca75abc46577bfefea +--- + CMakeLists.txt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index e2089f832a..5aca8a9247 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -19,7 +19,7 @@ + # start libevent.sln + # + +-cmake_minimum_required(VERSION 3.1 FATAL_ERROR) ++cmake_minimum_required(VERSION 3.1.2 FATAL_ERROR) + + if (POLICY CMP0054) + cmake_policy(SET CMP0054 NEW) diff --git a/packages/devel/libevent/patches/libevent-0002-build-with-cmake-4.0.0.patch b/packages/devel/libevent/patches/libevent-0002-build-with-cmake-4.0.0.patch new file mode 100644 index 0000000000..4d6d713abe --- /dev/null +++ b/packages/devel/libevent/patches/libevent-0002-build-with-cmake-4.0.0.patch @@ -0,0 +1,58 @@ +From acfac7ae4a3edbbb7ce4ceee7208b4245a6e203e Mon Sep 17 00:00:00 2001 +From: Ingo Bauersachs +Date: Thu, 1 Dec 2022 18:39:52 +0100 +Subject: [PATCH] Make dependency paths relocatable + +The generated configurations for both CMake and pkg-config included +absolute paths to dependencies (OpenSSL, MbedTLS). This is contrary +to the general CMake advise to create relocatable packages [1]. + +Additionally, when building both mbedtls and libevent via CMake's +FetchContent in the same project, loading the project would fail with + + INTERFACE_INCLUDE_DIRECTORIES property contains path: + "/home/user/project/cmake-build/_deps/mbedtls-build/include" + which is prefixed in the source directory. + +The required changes include: +- Adding the outer includes only to the BUILD_INTERFACE solves the + makes the CMake paths relocatable and thus solves the FetchContent + problem. +- Updates to libevent_*.pc.in fixes the relocatable issues for + pkg-config and properly declares currently missing dependencies. +- Using components for linking to OpenSSL (requiring CMake 3.4) + and MbedTLS. The new MbedTLS target names now match the component + names of the MbedTLS' CMake project. +- Use the Threads CMake library reference instead of a direct + reference to support both built-in pthread and -lpthread. + +v2 (azat): get back CMAKE_REQUIRED_LIBRARIES + +[1] https://cmake.org/cmake/help/v3.25/manual/cmake-packages.7.html#creating-relocatable-packages +--- + CMakeLists.txt | 28 +++++++++++----------------- + cmake/AddEventLibrary.cmake | 31 ++++++++++--------------------- + cmake/FindMbedTLS.cmake | 20 +++++++++++--------- + cmake/LibeventConfig.cmake.in | 21 ++++++++++++++++++--- + libevent_core.pc.in | 5 +---- + libevent_extra.pc.in | 6 ++---- + libevent_mbedtls.pc.in | 8 +++----- + libevent_openssl.pc.in | 9 ++++----- + libevent_pthreads.pc.in | 8 +++----- + test-export/CMakeLists.txt | 3 ++- + test-export/test-export.py | 18 ++++++++++++++++-- + 11 files changed, 81 insertions(+), 76 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 7199ab820d..c0c1c2fa97 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -19,7 +19,7 @@ + # start libevent.sln + # + +-cmake_minimum_required(VERSION 3.1.2 FATAL_ERROR) ++cmake_minimum_required(VERSION 3.4 FATAL_ERROR) + + if (POLICY CMP0054) + cmake_policy(SET CMP0054 NEW) diff --git a/packages/devel/libevent/patches/libevent-0003-build-with-cmake-4.0.0.patch b/packages/devel/libevent/patches/libevent-0003-build-with-cmake-4.0.0.patch new file mode 100644 index 0000000000..6e94631ecc --- /dev/null +++ b/packages/devel/libevent/patches/libevent-0003-build-with-cmake-4.0.0.patch @@ -0,0 +1,23 @@ +From a9426941555ec52b25c3641ebb8af72d7d91ebf8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?C=C5=93ur?= +Date: Sun, 28 Apr 2024 13:16:54 +0800 +Subject: [PATCH] Fix CMake Deprecation Warning + +--- + CMakeLists.txt | 2 +- + test-export/CMakeLists.txt | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 2ba64403ca..1869fccd2d 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -19,7 +19,7 @@ + # start libevent.sln + # + +-cmake_minimum_required(VERSION 3.4 FATAL_ERROR) ++cmake_minimum_required(VERSION 3.5 FATAL_ERROR) + + if (POLICY CMP0042) + cmake_policy(SET CMP0042 NEW) # MACOSX_RPATH is enabled by default. diff --git a/packages/devel/libevent/patches/libevent-0004-build-with-cmake-4.0.0.patch b/packages/devel/libevent/patches/libevent-0004-build-with-cmake-4.0.0.patch new file mode 100644 index 0000000000..4fce606e16 --- /dev/null +++ b/packages/devel/libevent/patches/libevent-0004-build-with-cmake-4.0.0.patch @@ -0,0 +1,27 @@ +From 2d7a3b9b6a7c7ef0d651d866b4ab11fb1ea24664 Mon Sep 17 00:00:00 2001 +From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> +Date: Sat, 16 Nov 2024 21:26:55 +0000 +Subject: [PATCH] cmake: Update minimum required version + +Compatibility with versions of CMake older than 3.10 is now deprecated +and will be removed from a future version. + +See: https://cmake.org/cmake/help/v3.31/release/3.31.html +--- + CMakeLists.txt | 2 +- + test-export/CMakeLists.txt | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 25578930b4..04e6933bee 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -19,7 +19,7 @@ + # start libevent.sln + # + +-cmake_minimum_required(VERSION 3.5 FATAL_ERROR) ++cmake_minimum_required(VERSION 3.10 FATAL_ERROR) + + if (POLICY CMP0042) + cmake_policy(SET CMP0042 NEW) # MACOSX_RPATH is enabled by default. diff --git a/packages/devel/libffi/package.mk b/packages/devel/libffi/package.mk new file mode 100644 index 0000000000..0fb7d5d46f --- /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.5.1" +PKG_SHA256="f99eb68a67c7d54866b7706af245e87ba060d419a062474b456d3bc8d4abdbd1" +PKG_LICENSE="GPL" +PKG_SITE="http://sourceware.org/${PKG_NAME}/" +PKG_URL="https://github.com/libffi/libffi/releases/download/v${PKG_VERSION}/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="ccache:host autoconf:host automake:host libtool:host pkg-config:host" +PKG_DEPENDS_TARGET="autotools:host gcc:host" +PKG_LONGDESC="Foreign Function Interface Library." +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="--disable-debug \ + --enable-static --enable-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 0000000000..56e08f7363 --- /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 0000000000..9aa96a2fe0 --- /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 0000000000..942cca6603 --- /dev/null +++ b/packages/devel/libfmt/package.mk @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libfmt" +PKG_VERSION="11.2.0" +PKG_SHA256="bc23066d87ab3168f27cef3e97d545fa63314f5c79df5ea444d41d56f962c6af" +PKG_LICENSE="BSD" +PKG_SITE="https://github.com/fmtlib/fmt" +PKG_URL="https://github.com/fmtlib/fmt/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="cmake:host make:host" +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_TOOLCHAIN="cmake-make" +PKG_BUILD_FLAGS="+local-cc" + +PKG_CMAKE_OPTS_COMMON="-DCMAKE_CXX_STANDARD=14 \ + -DCMAKE_CXX_EXTENSIONS:BOOL=OFF \ + -DFMT_DOC=OFF \ + -DFMT_INSTALL=ON \ + -DFMT_TEST=OFF \ + -DBUILD_SHARED_LIBS=ON" + +PKG_CMAKE_OPTS_TARGET="${PKG_CMAKE_OPTS_COMMON}" + +configure_host() { + # custom cmake build to override the LOCAL_CC/CXX + cp ${CMAKE_CONF} cmake-ccache.conf + + echo "SET(CMAKE_C_COMPILER ${CC})" >>cmake-ccache.conf + echo "SET(CMAKE_CXX_COMPILER ${CXX})" >>cmake-ccache.conf + cmake -DCMAKE_TOOLCHAIN_FILE=cmake-ccache.conf \ + -DCMAKE_INSTALL_PREFIX=${TOOLCHAIN} \ + ${PKG_CMAKE_OPTS_COMMON} \ + .. +} diff --git a/packages/devel/libfstrcmp/package.mk b/packages/devel/libfstrcmp/package.mk new file mode 100644 index 0000000000..d464d03957 --- /dev/null +++ b/packages/devel/libfstrcmp/package.mk @@ -0,0 +1,24 @@ +# 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." +PKG_BUILD_FLAGS="-cfg-libs" + +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 0000000000..52da3f1c88 --- /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/libftdi1/patches/libftdi-0001-build-with-cmake-4.0.0.patch b/packages/devel/libftdi1/patches/libftdi-0001-build-with-cmake-4.0.0.patch new file mode 100644 index 0000000000..5c0167bddb --- /dev/null +++ b/packages/devel/libftdi1/patches/libftdi-0001-build-with-cmake-4.0.0.patch @@ -0,0 +1,2427 @@ +From cdb28383402d248dbc6062f4391b038375c52385 Mon Sep 17 00:00:00 2001 +From: Fabrice Fontaine +Date: Fri, 17 Jul 2020 21:25:03 +0200 +Subject: [PATCH 01/42] CMakeLists.txt: fix paths when FTDIPP is set + +Use the same project name (i.e. libftdi1 and not libftdipp1) when FTDIPP +is enabled as suggested by Aurelien Jarno in +http://developer.intra2net.com/mailarchive/html/libftdi/2020/msg00044.html + +Without this change, the libftdi1.pc config file defines the include +path as /usr/local/include/libftdipp1 while the ftdi.h file is actually +installed in /usr/local/include/libftdi1 + +This is an issue for example for libsigrok which will fail on: + +In file included from src/hardware/asix-sigma/protocol.c:27: +src/hardware/asix-sigma/protocol.h:28:10: fatal error: ftdi.h: No such file or directory + 28 | #include + | ^~~~~~~~ + +Fixes: + - http://autobuild.buildroot.org/results/1427f44e36752c337791597fab47a1889552a2fe + +Signed-off-by: Fabrice Fontaine +--- + CMakeLists.txt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 5aecafc..3b0b87c 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -136,7 +136,7 @@ endif () + + add_subdirectory(src) + if ( FTDIPP ) +- project(libftdipp1 C CXX) ++ project(libftdi1 C CXX) + add_subdirectory(ftdipp) + endif () + if ( PYTHON_BINDINGS ) +-- +2.43.0 + +From 7c5aa3b8c0fe0862886c7202cc1e2e44434ea4de Mon Sep 17 00:00:00 2001 +From: Xiaofan Chen +Date: Fri, 31 Jul 2020 10:25:45 +0800 +Subject: [PATCH 02/42] Ignore purge_test example build for MinGW + +termios.h is not available on MinGW. +--- + examples/CMakeLists.txt | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt +index 6fc3c09..dd8ffbe 100644 +--- a/examples/CMakeLists.txt ++++ b/examples/CMakeLists.txt +@@ -15,7 +15,9 @@ add_executable(baud_test baud_test.c) + add_executable(stream_test stream_test.c) + add_executable(eeprom eeprom.c) + add_executable(async async.c) +-add_executable(purge_test purge_test.c) ++if(NOT MINGW) ++ add_executable(purge_test purge_test.c) ++endif(NOT MINGW) + + # Linkage + target_link_libraries(simple ftdi1) +@@ -29,7 +31,9 @@ target_link_libraries(baud_test ftdi1) + target_link_libraries(stream_test ftdi1) + target_link_libraries(eeprom ftdi1) + target_link_libraries(async ftdi1) +-target_link_libraries(purge_test ftdi1) ++if(NOT MINGW) ++ target_link_libraries(purge_test ftdi1) ++endif(NOT MINGW) + + # libftdi++ examples + if( FTDIPP ) +-- +2.43.0 + +From 6dd18122a81e6030dd239391df6ffde8cb8c59c7 Mon Sep 17 00:00:00 2001 +From: Uwe Bonnes +Date: Fri, 31 Jul 2020 11:00:50 +0200 +Subject: [PATCH 03/42] Fix GCC fall-through warnings. + +When compiling ftdi.c in the context of blackmagic debug, more enabled +warnings and -Werror made me to add appended fixes. + +Fixing the signedness of baudrate would probably be more logically by +making all baudrate and clk unsigned, but would need more code changes. +I decided to make clk signed as a fix with minimal +impact. The FTDI chips are far away from 2 GHz clock rate... +--- + src/ftdi.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/src/ftdi.c b/src/ftdi.c +index f5b7018..03d7b07 100644 +--- a/src/ftdi.c ++++ b/src/ftdi.c +@@ -1328,7 +1328,7 @@ static int ftdi_to_clkbits_AM(int baudrate, unsigned long *encoded_divisor) + AM Type chips have only four fractional subdivisors at value[15:14] + for subdivisors 0, 0.5, 0.25, 0.125 + */ +-static int ftdi_to_clkbits(int baudrate, unsigned int clk, int clk_div, unsigned long *encoded_divisor) ++static int ftdi_to_clkbits(int baudrate, int clk, int clk_div, unsigned long *encoded_divisor) + { + static const char frac_code[8] = {0, 3, 2, 4, 1, 5, 6, 7}; + int best_baud = 0; +@@ -3044,10 +3044,13 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) + case TYPE_2232H: + case TYPE_4232H: + i += 2; ++ /* Fall through*/ + case TYPE_R: + i += 2; ++ /* Fall through*/ + case TYPE_2232C: + i += 2; ++ /* Fall through*/ + case TYPE_AM: + case TYPE_BM: + i += 0x94; +@@ -3438,15 +3441,20 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) + { + case TYPE_230X: + free_start += 2; ++ /* Fall through*/ + case TYPE_232H: + free_start += 6; ++ /* Fall through*/ + case TYPE_2232H: + case TYPE_4232H: + free_start += 2; ++ /* Fall through*/ + case TYPE_R: + free_start += 2; ++ /* Fall through*/ + case TYPE_2232C: + free_start++; ++ /* Fall through*/ + case TYPE_AM: + case TYPE_BM: + free_start += 0x14; +-- +2.43.0 + +From 11a50ae5b80b3e03694a19e84513345d0794e563 Mon Sep 17 00:00:00 2001 +From: Thomas Jarosch +Date: Mon, 24 Aug 2020 19:27:22 +0200 +Subject: [PATCH 04/42] Fix building unit tests without FTDIPP + +Needed to run the baudrate unit tests. + +Probably another fallout from: + +**************************** +commit 0209a3633dc877a577af07d883eb5059e22f6a91 + +cmake: do not check for g++ when FTDIPP is disabled +**************************** +--- + CMakeLists.txt | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 3b0b87c..58f664a 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -150,6 +150,7 @@ if ( EXAMPLES ) + endif () + add_subdirectory(packages) + if ( BUILD_TESTS ) ++ project(libftdi1 C CXX) + add_subdirectory(test) + endif () + +-- +2.43.0 + +From 45ebed3754aa2814583f4d433155f87f24f5351f Mon Sep 17 00:00:00 2001 +From: Thomas Jarosch +Date: Mon, 24 Aug 2020 19:45:41 +0200 +Subject: [PATCH 05/42] examples/bitbang_cbus.c: Check return value of fgets() + +--- + examples/bitbang_cbus.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/examples/bitbang_cbus.c b/examples/bitbang_cbus.c +index b902b50..359097e 100644 +--- a/examples/bitbang_cbus.c ++++ b/examples/bitbang_cbus.c +@@ -60,8 +60,9 @@ int main(void) + while (1) + { + // Set bitmask from input +- fgets(input, sizeof(input) - 1, stdin); +- if (input[0] == '\n') break; ++ char *s = fgets(input, sizeof(input) - 1, stdin); ++ if (s == NULL || input[0] == '\n') ++ break; + bitmask = strtol(input, NULL, 0); + printf("Using bitmask 0x%02x\n", bitmask); + f = ftdi_set_bitmode(ftdi, bitmask, BITMODE_CBUS); +-- +2.43.0 + +From cb9b8a53f1536640fe4d8dfccf79268fbbd49180 Mon Sep 17 00:00:00 2001 +From: Tomasz Wasilczyk +Date: Thu, 11 Mar 2021 15:43:12 -0800 +Subject: [PATCH 06/42] Don't spam stderr when flashing FT232H eeprom + +--- + src/ftdi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/ftdi.c b/src/ftdi.c +index 03d7b07..db66b87 100644 +--- a/src/ftdi.c ++++ b/src/ftdi.c +@@ -3421,7 +3421,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) + set_ft232h_cbus(eeprom, output); + + output[0x1e] = eeprom->chip; +- fprintf(stderr,"FIXME: Build FT232H specific EEPROM settings\n"); ++ /* FIXME: Build FT232H specific EEPROM settings */ + break; + case TYPE_230X: + output[0x00] = 0x80; /* Actually, leave the default value */ +-- +2.43.0 + +From 1050ad206d3ff01e5b5bac08a44b25ed0d9b5488 Mon Sep 17 00:00:00 2001 +From: Tomasz Wasilczyk +Date: Thu, 11 Mar 2021 15:47:06 -0800 +Subject: [PATCH 07/42] ftdi_eeprom_initdefaults const arguments + +This function don't need to modify its arguments. +--- + src/ftdi.c | 4 ++-- + src/ftdi.h | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/ftdi.c b/src/ftdi.c +index db66b87..88216bf 100644 +--- a/src/ftdi.c ++++ b/src/ftdi.c +@@ -2576,8 +2576,8 @@ int ftdi_set_error_char(struct ftdi_context *ftdi, + \retval -2: No struct ftdi_eeprom + \retval -3: No connected device or device not yet opened + */ +-int ftdi_eeprom_initdefaults(struct ftdi_context *ftdi, char * manufacturer, +- char * product, char * serial) ++int ftdi_eeprom_initdefaults(struct ftdi_context *ftdi, const char * manufacturer, ++ const char * product, const char * serial) + { + struct ftdi_eeprom *eeprom; + +diff --git a/src/ftdi.h b/src/ftdi.h +index fb45008..0603335 100644 +--- a/src/ftdi.h ++++ b/src/ftdi.h +@@ -609,8 +609,8 @@ extern "C" + + /* init eeprom for the given FTDI type */ + int ftdi_eeprom_initdefaults(struct ftdi_context *ftdi, +- char * manufacturer, char *product, +- char * serial); ++ const char * manufacturer, const char *product, ++ const char * serial); + int ftdi_eeprom_build(struct ftdi_context *ftdi); + int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose); + +-- +2.43.0 + +From 9d638dab09426be6349d41a269281921febcfa34 Mon Sep 17 00:00:00 2001 +From: Tomasz Wasilczyk +Date: Wed, 21 Apr 2021 12:39:52 -0700 +Subject: [PATCH 08/42] Don't fail reading missing strings. + +This happens i.e. when serial number is not set -- in such case the +string is missing from string descriptor list. +--- + src/ftdi.c | 24 ++++++++++++++++++------ + 1 file changed, 18 insertions(+), 6 deletions(-) + +diff --git a/src/ftdi.c b/src/ftdi.c +index 88216bf..5ec3e2c 100644 +--- a/src/ftdi.c ++++ b/src/ftdi.c +@@ -485,27 +485,39 @@ int ftdi_usb_get_strings2(struct ftdi_context *ftdi, struct libusb_device *dev, + if (libusb_get_device_descriptor(dev, &desc) < 0) + ftdi_error_return(-11, "libusb_get_device_descriptor() failed"); + +- if (manufacturer != NULL) ++ if (manufacturer != NULL && mnf_len > 0) + { +- if (libusb_get_string_descriptor_ascii(ftdi->usb_dev, desc.iManufacturer, (unsigned char *)manufacturer, mnf_len) < 0) ++ if (desc.iManufacturer == 0) ++ { ++ manufacturer[0] = '\0'; ++ } ++ else if (libusb_get_string_descriptor_ascii(ftdi->usb_dev, desc.iManufacturer, (unsigned char *)manufacturer, mnf_len) < 0) + { + ftdi_usb_close_internal (ftdi); + ftdi_error_return(-7, "libusb_get_string_descriptor_ascii() failed"); + } + } + +- if (description != NULL) ++ if (description != NULL && desc_len > 0) + { +- if (libusb_get_string_descriptor_ascii(ftdi->usb_dev, desc.iProduct, (unsigned char *)description, desc_len) < 0) ++ if (desc.iProduct == 0) ++ { ++ description[0] = '\0'; ++ } ++ else if (libusb_get_string_descriptor_ascii(ftdi->usb_dev, desc.iProduct, (unsigned char *)description, desc_len) < 0) + { + ftdi_usb_close_internal (ftdi); + ftdi_error_return(-8, "libusb_get_string_descriptor_ascii() failed"); + } + } + +- if (serial != NULL) ++ if (serial != NULL && serial_len > 0) + { +- if (libusb_get_string_descriptor_ascii(ftdi->usb_dev, desc.iSerialNumber, (unsigned char *)serial, serial_len) < 0) ++ if (desc.iSerialNumber == 0) ++ { ++ serial[0] = '\0'; ++ } ++ else if (libusb_get_string_descriptor_ascii(ftdi->usb_dev, desc.iSerialNumber, (unsigned char *)serial, serial_len) < 0) + { + ftdi_usb_close_internal (ftdi); + ftdi_error_return(-9, "libusb_get_string_descriptor_ascii() failed"); +-- +2.43.0 + +From 231d8d35405dd0423db6cb1950ae77df9f742aa6 Mon Sep 17 00:00:00 2001 +From: Tomasz Wasilczyk +Date: Wed, 21 Apr 2021 12:42:08 -0700 +Subject: [PATCH 09/42] Remove legacy EEPROM fields from FT4232H. + +These are not present when flashed with FT_Prog tool. +--- + src/ftdi.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/ftdi.c b/src/ftdi.c +index 5ec3e2c..2f77ac3 100644 +--- a/src/ftdi.c ++++ b/src/ftdi.c +@@ -3113,7 +3113,8 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) + } + + // Legacy port name and PnP fields for FT2232 and newer chips +- if (ftdi->type > TYPE_BM) ++ // It doesn't appear when written with FT_Prog for FT4232H chip. ++ if (ftdi->type > TYPE_BM && ftdi->type != TYPE_4232H) + { + output[i & eeprom_size_mask] = 0x02; /* as seen when written with FTD2XX */ + i++; +-- +2.43.0 + +From 31865800dffc58f2db3ae06a7bbba61bb279b265 Mon Sep 17 00:00:00 2001 +From: Tomasz Wasilczyk +Date: Wed, 21 Apr 2021 12:43:34 -0700 +Subject: [PATCH 10/42] Don't set EEPROM serial when it's not used. + +This makes a difference in USB enumeration -- if serial is missing, +its string is not present in string descriptor list. +--- + src/ftdi.c | 25 +++++++++++++------------ + 1 file changed, 13 insertions(+), 12 deletions(-) + +diff --git a/src/ftdi.c b/src/ftdi.c +index 2f77ac3..92c5fae 100644 +--- a/src/ftdi.c ++++ b/src/ftdi.c +@@ -2606,7 +2606,7 @@ int ftdi_eeprom_initdefaults(struct ftdi_context *ftdi, const char * manufacture + ftdi_error_return(-3, "No connected device or device not yet opened"); + + eeprom->vendor_id = 0x0403; +- eeprom->use_serial = 1; ++ eeprom->use_serial = (serial != NULL); + if ((ftdi->type == TYPE_AM) || (ftdi->type == TYPE_BM) || + (ftdi->type == TYPE_R)) + eeprom->product_id = 0x6001; +@@ -3101,15 +3101,18 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) + } + output[0x11] = product_size*2 + 2; + +- // Addr 12: Offset of the serial string + 0x80, calculated later +- // Addr 13: Length of serial string +- output[0x12] = i | 0x80; // calculate offset +- output[i & eeprom_size_mask] = serial_size*2 + 2, i++; +- output[i & eeprom_size_mask] = 0x03, i++; +- for (j = 0; j < serial_size; j++) +- { +- output[i & eeprom_size_mask] = eeprom->serial[j], i++; +- output[i & eeprom_size_mask] = 0x00, i++; ++ if (eeprom->use_serial) { ++ // Addr 12: Offset of the serial string + 0x80, calculated later ++ // Addr 13: Length of serial string ++ output[0x12] = i | 0x80; // calculate offset ++ output[i & eeprom_size_mask] = serial_size*2 + 2, i++; ++ output[i & eeprom_size_mask] = 0x03, i++; ++ for (j = 0; j < serial_size; j++) ++ { ++ output[i & eeprom_size_mask] = eeprom->serial[j], i++; ++ output[i & eeprom_size_mask] = 0x00, i++; ++ } ++ output[0x13] = serial_size*2 + 2; + } + + // Legacy port name and PnP fields for FT2232 and newer chips +@@ -3124,8 +3127,6 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) + i++; + } + +- output[0x13] = serial_size*2 + 2; +- + if (ftdi->type > TYPE_AM) /* use_serial not used in AM devices */ + { + if (eeprom->use_serial) +-- +2.43.0 + +From 32e899fa5ecd30aad0a25ea8d7e208d203aaa0ae Mon Sep 17 00:00:00 2001 +From: Thomas Jarosch +Date: Sun, 2 May 2021 09:32:02 +0200 +Subject: [PATCH 11/42] Add Tomasz Wasilczyk to AUTHORS + +--- + AUTHORS | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/AUTHORS b/AUTHORS +index e8f5a69..bd31f0a 100644 +--- a/AUTHORS ++++ b/AUTHORS +@@ -83,6 +83,7 @@ see Changelog for full details: + Thomas Klose + Tim Ansell + Tom Saunders ++ Tomasz Wasilczyk + Uwe Bonnes + Vladimir Yakovlev + Wilfried Holzke +-- +2.43.0 + +From 0684c1b1be9ccb893829c20a8505c91e101bbf43 Mon Sep 17 00:00:00 2001 +From: Thomas Jarosch +Date: Tue, 4 May 2021 18:51:15 +0200 +Subject: [PATCH 12/42] Fix indentation + +--- + src/ftdi.c | 20 ++++++++++---------- + 1 file changed, 10 insertions(+), 10 deletions(-) + +diff --git a/src/ftdi.c b/src/ftdi.c +index 92c5fae..0a7fb27 100644 +--- a/src/ftdi.c ++++ b/src/ftdi.c +@@ -3103,16 +3103,16 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) + + if (eeprom->use_serial) { + // Addr 12: Offset of the serial string + 0x80, calculated later +- // Addr 13: Length of serial string +- output[0x12] = i | 0x80; // calculate offset +- output[i & eeprom_size_mask] = serial_size*2 + 2, i++; +- output[i & eeprom_size_mask] = 0x03, i++; +- for (j = 0; j < serial_size; j++) +- { +- output[i & eeprom_size_mask] = eeprom->serial[j], i++; +- output[i & eeprom_size_mask] = 0x00, i++; +- } +- output[0x13] = serial_size*2 + 2; ++ // Addr 13: Length of serial string ++ output[0x12] = i | 0x80; // calculate offset ++ output[i & eeprom_size_mask] = serial_size*2 + 2, i++; ++ output[i & eeprom_size_mask] = 0x03, i++; ++ for (j = 0; j < serial_size; j++) ++ { ++ output[i & eeprom_size_mask] = eeprom->serial[j], i++; ++ output[i & eeprom_size_mask] = 0x00, i++; ++ } ++ output[0x13] = serial_size*2 + 2; + } + + // Legacy port name and PnP fields for FT2232 and newer chips +-- +2.43.0 + +From b5b8fab6063ad90bb5ef05a72708ecde1796bc81 Mon Sep 17 00:00:00 2001 +From: Fabrice Fontaine +Date: Fri, 13 May 2022 18:11:50 +0200 +Subject: [PATCH 13/42] CMakeLists.txt: fix static build with libusb and + -latomic + +Use pkg-config to retrieve libusb dependencies such as -latomic and +avoid the following static build failure: + +/nvmedata/autobuild/instance-29/output-1/per-package/libftdi1/host/bin/../lib/gcc/sparc-buildroot-linux-uclibc/10.3.0/../../../../sparc-buildroot-linux-uclibc/bin/ld: /nvmedata/autobuild/instance-29/output-1/per-package/libftdi1/host/sparc-buildroot-linux-uclibc/sysroot/lib/libusb-1.0.a(core.o): in function `libusb_unref_device': +/nvmedata/autobuild/instance-29/output-1/build/libusb-1.0.25/libusb/core.c:1186: undefined reference to `__atomic_fetch_add_4' + +Fixes: + - http://autobuild.buildroot.org/results/1ca7cd85ae60ad4797a6d8a83b2fb51d7eab96d9 + +Signed-off-by: Fabrice Fontaine +--- + CMakeLists.txt | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 58f664a..d20aa94 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -25,8 +25,16 @@ if(${CMAKE_BUILD_TYPE} STREQUAL Debug) + endif(${CMAKE_BUILD_TYPE} STREQUAL Debug) + + # find libusb +-find_package ( USB1 REQUIRED ) +-include_directories ( ${LIBUSB_INCLUDE_DIR} ) ++find_package( PkgConfig ) ++if (PkgConfig_FOUND) ++ pkg_check_modules( LIBUSB libusb-1.0 ) ++ if (LIBUSB_FOUND) ++ include_directories ( ${LIBUSB_INCLUDE_DIRS} ) ++ else() ++ find_package ( USB1 REQUIRED ) ++ include_directories ( ${LIBUSB_INCLUDE_DIR} ) ++ endif() ++endif() + + # Find Boost + if (FTDIPP OR BUILD_TESTS) +-- +2.43.0 + +From 7017c0dce1e251108d1bc8a41bfeef3ff9a89ba6 Mon Sep 17 00:00:00 2001 +From: Fabian Vogt +Date: Tue, 29 Aug 2023 14:57:27 +0200 +Subject: [PATCH 14/42] Fix race during build of python bindings + +The CMake documentation says about add_custom_command that the output must +not be used as dependency in more than one target, but this was the case +here: Both the doc_i target and the SWIG target depended on ftdi1_doc.i. +Make the SWIG target depend on doc_i instead. + +This fixes that ftdi1_doc.i was built twice with parallel builds, leading +to random errors. + +Signed-off-by: Fabian Vogt +--- + python/CMakeLists.txt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt +index 5b6f420..1a8142b 100644 +--- a/python/CMakeLists.txt ++++ b/python/CMakeLists.txt +@@ -25,7 +25,7 @@ link_directories ( ${CMAKE_CURRENT_BINARY_DIR}/../src ) + if ( DOCUMENTATION ) + set(CMAKE_SWIG_FLAGS -DDOXYGEN=${DOXYGEN_FOUND}) + # manually add dependency for new cmake / swig versions +- set_property(SOURCE ftdi1.i PROPERTY DEPENDS ftdi1_doc.i) ++ set_property(SOURCE ftdi1.i PROPERTY DEPENDS doc_i) + endif() + if(NOT CMAKE_VERSION VERSION_LESS 3.8.0) + swig_add_library ( ftdi1 LANGUAGE python SOURCES ftdi1.i ) +-- +2.43.0 + +From 3861e7dc9e83f2f6ff4e1579cf3bbf63a6827105 Mon Sep 17 00:00:00 2001 +From: Yegor Yefremov +Date: Tue, 1 Aug 2023 11:53:35 +0200 +Subject: [PATCH 15/42] CMake: bump the minimal required version to 2.8.12 + +The older CMake versions are deprecated. + +Remove support for CMake code compatible with CMake older than 2.8.8. + +Also move cmake_minimum_required() command before the project() +command invocation. +--- + CMakeLists.txt | 46 +++++++++++++++++++++------------------------- + 1 file changed, 21 insertions(+), 25 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index d20aa94..48a028c 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -1,3 +1,5 @@ ++cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR) ++ + # Project + project(libftdi1 C) + set(MAJOR_VERSION 1) +@@ -12,7 +14,6 @@ if("${CMAKE_BUILD_TYPE}" STREQUAL "") + set(CMAKE_BUILD_TYPE RelWithDebInfo) + endif("${CMAKE_BUILD_TYPE}" STREQUAL "") + set(CMAKE_COLOR_MAKEFILE ON) +-cmake_minimum_required(VERSION 2.6 FATAL_ERROR) + + add_definitions(-Wall) + +@@ -211,30 +212,25 @@ set ( LIBFTDI_VERSION_MINOR ${MINOR_VERSION} ) + + set ( LIBFTDI_USE_FILE ${CMAKE_INSTALL_PREFIX}/${LIBFTDI_CMAKE_CONFIG_DIR}/UseLibFTDI1.cmake ) + +-if(CMAKE_VERSION VERSION_LESS 2.8.8) +- configure_file ( cmake/LibFTDI1Config.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/LibFTDI1Config.cmake @ONLY ) +- configure_file ( cmake/LibFTDI1ConfigVersion.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/LibFTDI1ConfigVersion.cmake @ONLY ) +-else () +- include(CMakePackageConfigHelpers) +- +- configure_package_config_file ( +- cmake/LibFTDI1Config.cmake.in +- ${CMAKE_CURRENT_BINARY_DIR}/LibFTDI1Config.cmake +- INSTALL_DESTINATION ${LIBFTDI_CMAKE_CONFIG_DIR} +- PATH_VARS +- LIBFTDI_USE_FILE +- LIBFTDI_ROOT_DIR +- LIBFTDI_INCLUDE_DIR +- LIBFTDI_INCLUDE_DIRS +- LIBFTDI_LIBRARY_DIRS +- NO_CHECK_REQUIRED_COMPONENTS_MACRO +- ) +- write_basic_package_version_file ( +- LibFTDI1ConfigVersion.cmake +- VERSION ${LIBFTDI_VERSION_STRING} +- COMPATIBILITY AnyNewerVersion +- ) +-endif () ++include(CMakePackageConfigHelpers) ++ ++configure_package_config_file ( ++ cmake/LibFTDI1Config.cmake.in ++ ${CMAKE_CURRENT_BINARY_DIR}/LibFTDI1Config.cmake ++ INSTALL_DESTINATION ${LIBFTDI_CMAKE_CONFIG_DIR} ++ PATH_VARS ++ LIBFTDI_USE_FILE ++ LIBFTDI_ROOT_DIR ++ LIBFTDI_INCLUDE_DIR ++ LIBFTDI_INCLUDE_DIRS ++ LIBFTDI_LIBRARY_DIRS ++ NO_CHECK_REQUIRED_COMPONENTS_MACRO ++) ++write_basic_package_version_file ( ++ LibFTDI1ConfigVersion.cmake ++ VERSION ${LIBFTDI_VERSION_STRING} ++ COMPATIBILITY AnyNewerVersion ++) + + + install ( FILES +-- +2.43.0 + +From 2080e757c936392ae390c4accd1ae02a52b2f2d8 Mon Sep 17 00:00:00 2001 +From: Yegor Yefremov +Date: Thu, 3 Aug 2023 15:48:58 +0200 +Subject: [PATCH 16/42] Fix typos and harmonize spaces + +--- + src/ftdi.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +diff --git a/src/ftdi.c b/src/ftdi.c +index 0a7fb27..3a51b26 100644 +--- a/src/ftdi.c ++++ b/src/ftdi.c +@@ -83,7 +83,7 @@ static void ftdi_usb_close_internal (struct ftdi_context *ftdi) + + \retval 0: all fine + \retval -1: couldn't allocate read buffer +- \retval -2: couldn't allocate struct buffer ++ \retval -2: couldn't allocate struct buffer + \retval -3: libusb_init() failed + + \remark This should be called before all functions +@@ -112,7 +112,7 @@ int ftdi_init(struct ftdi_context *ftdi) + ftdi_error_return(-3, "libusb_init() failed"); + + ftdi_set_interface(ftdi, INTERFACE_ANY); +- ftdi->bitbang_mode = 1; /* when bitbang is enabled this holds the number of the mode */ ++ ftdi->bitbang_mode = 1; /* when bitbang is enabled this holds the number of the mode */ + + eeprom = (struct ftdi_eeprom *)malloc(sizeof(struct ftdi_eeprom)); + if (eeprom == 0) +@@ -298,7 +298,7 @@ struct ftdi_version_info ftdi_get_library_version(void) + /** + Finds all ftdi devices with given VID:PID on the usb bus. Creates a new + ftdi_device_list which needs to be deallocated by ftdi_list_free() after +- use. With VID:PID 0:0, search for the default devices ++ use. With VID:PID 0:0, search for the default devices + (0x403:0x6001, 0x403:0x6010, 0x403:0x6011, 0x403:0x6014, 0x403:0x6015) + + \param ftdi pointer to ftdi_context +@@ -639,7 +639,7 @@ int ftdi_usb_open_dev(struct ftdi_context *ftdi, libusb_device *dev) + ftdi_error_return(-12, "libusb_get_configuration () failed"); + // set configuration (needed especially for windows) + // tolerate EBUSY: one device with one configuration, but two interfaces +- // and libftdi sessions to both interfaces (e.g. FT2232) ++ // and libftdi sessions to both interfaces (e.g. FT2232) + if (desc.bNumConfigurations > 0 && cfg != cfg0) + { + if (libusb_set_configuration(ftdi->usb_dev, cfg0) < 0) +@@ -1316,7 +1316,7 @@ static int ftdi_to_clkbits_AM(int baudrate, unsigned long *encoded_divisor) + return best_baud; + } + +-/* ftdi_to_clkbits Convert a requested baudrate for a given system clock and predivisor ++/* ftdi_to_clkbits Convert a requested baudrate for a given system clock and predivisor + to encoded divisor and the achievable baudrate + Function is only used internally + \internal +@@ -3072,7 +3072,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) + i = 0xa0; + break; + } +- /* Wrap around 0x80 for 128 byte EEPROMS (Internale and 93x46) */ ++ /* Wrap around 0x80 for 128 byte EEPROMS (Internal and 93x46) */ + eeprom_size_mask = eeprom->size -1; + free_end = i & eeprom_size_mask; + +@@ -3136,7 +3136,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) + } + + /* Bytes and Bits specific to (some) types +- Write linear, as this allows easier fixing*/ ++ Write linear, as this allows easier fixing */ + switch (ftdi->type) + { + case TYPE_AM: +@@ -3208,7 +3208,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) + + if (eeprom->external_oscillator) + output[0x00] |= 0x02; +- output[0x01] = 0x40; /* Hard coded Endpoint Size*/ ++ output[0x01] = 0x40; /* Hard coded Endpoint Size */ + + if (eeprom->suspend_pull_downs) + output[0x0A] |= 0x4; +@@ -3440,7 +3440,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) + case TYPE_230X: + output[0x00] = 0x80; /* Actually, leave the default value */ + /*FIXME: Make DBUS & CBUS Control configurable*/ +- output[0x0c] = 0; /* DBUS drive 4mA, CBUS drive 4 mA like factory default */ ++ output[0x0c] = 0; /* DBUS drive 4mA, CBUS drive 4mA like factory default */ + for (j = 0; j <= 6; j++) + { + output[0x1a + j] = eeprom->cbus_function[j]; +-- +2.43.0 + +From b006371dbde50c000cd822143310d9b605b6dfe1 Mon Sep 17 00:00:00 2001 +From: Yegor Yefremov +Date: Sat, 5 Aug 2023 08:32:58 +0200 +Subject: [PATCH 17/42] Add .editorconfig for C and CMake files + +--- + .editorconfig | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + create mode 100644 .editorconfig + +diff --git a/.editorconfig b/.editorconfig +new file mode 100644 +index 0000000..40392cd +--- /dev/null ++++ b/.editorconfig +@@ -0,0 +1,16 @@ ++root = true ++ ++[*] ++end_of_line = lf ++trim_trailing_whitespace = true ++insert_final_newline = false ++ ++[{CMakeLists.txt,*.cmake}] ++indent_style = space ++indent_size = 2 ++tab_width = 2 ++ ++[{*.c,*.h}] ++indent_style = space ++indent_size = 4 ++tab_width = 4 +-- +2.43.0 + +From 0fad6f389a7cad0513b23f73b2439700e53d47b3 Mon Sep 17 00:00:00 2001 +From: Yegor Yefremov +Date: Wed, 9 Aug 2023 14:28:15 +0200 +Subject: [PATCH 18/42] EEPROM: fix checksum for FT230X series + +ftdi_eeprom_build() computes the checksum via reading the "Factory +Configuration Data" region. ftdi_eeprom_decode() computes the checksum +only on the EEPROM buffer. Hence, both checksums differ. + +Add the info from "Factory Configuration Data" to the EEPROM buffer. +--- + src/ftdi.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/ftdi.c b/src/ftdi.c +index 3a51b26..cf53e04 100644 +--- a/src/ftdi.c ++++ b/src/ftdi.c +@@ -3503,6 +3503,8 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) + i = 0x50; + } + value = data; ++ output[i * 2] = data; ++ output[(i * 2) + 1] = data >> 8; + } + else { + value = output[i*2]; +-- +2.43.0 + +From ee93e3056cd496221d2c701dfd92e67f888376f3 Mon Sep 17 00:00:00 2001 +From: Yegor Yefremov +Date: Wed, 9 Aug 2023 14:38:26 +0200 +Subject: [PATCH 19/42] EEPROM: mention FT230X in the dynamic content + calculation + +--- + src/ftdi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/ftdi.c b/src/ftdi.c +index cf53e04..349df8a 100644 +--- a/src/ftdi.c ++++ b/src/ftdi.c +@@ -3049,7 +3049,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) + // Dynamic content + // Strings start at 0x94 (TYPE_AM, TYPE_BM) + // 0x96 (TYPE_2232C), 0x98 (TYPE_R) and 0x9a (TYPE_x232H) +- // 0xa0 (TYPE_232H) ++ // 0xa0 (TYPE_232H, TYPE_230X) + i = 0; + switch (ftdi->type) + { +-- +2.43.0 + +From 4d12b998630865d3f631ec67011473657e75fb43 Mon Sep 17 00:00:00 2001 +From: Yegor Yefremov +Date: Wed, 9 Aug 2023 20:20:43 +0200 +Subject: [PATCH 20/42] examples: eeprom: add the missing newlines + +--- + examples/eeprom.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/examples/eeprom.c b/examples/eeprom.c +index 247589a..45f5dff 100644 +--- a/examples/eeprom.c ++++ b/examples/eeprom.c +@@ -151,14 +151,14 @@ int main(int argc, char **argv) + if (res > 1) + { + int i = 1; +- fprintf(stderr, "%d FTDI devices found: Only Readout on EEPROM done. ",res); ++ fprintf(stderr, "%d FTDI devices found: Only Readout on EEPROM done. \n",res); + fprintf(stderr, "Use VID/PID/desc/serial to select device\n"); + for (curdev = devlist; curdev != NULL; curdev= curdev->next, i++) + { + f = ftdi_usb_open_dev(ftdi, curdev->dev); + if (f<0) + { +- fprintf(stderr, "Unable to open device %d: (%s)", ++ fprintf(stderr, "Unable to open device %d: (%s)\n", + i, ftdi_get_error_string(ftdi)); + continue; + } +@@ -175,7 +175,7 @@ int main(int argc, char **argv) + f = ftdi_usb_open_dev(ftdi, devlist[0].dev); + if (f<0) + { +- fprintf(stderr, "Unable to open device %d: (%s)", ++ fprintf(stderr, "Unable to open device %d: (%s)\n", + i, ftdi_get_error_string(ftdi)); + } + } +@@ -210,7 +210,7 @@ int main(int argc, char **argv) + f = ftdi_erase_eeprom(ftdi); /* needed to determine EEPROM chip type */ + if (f < 0) + { +- fprintf(stderr, "Erase failed: %s", ++ fprintf(stderr, "Erase failed: %s\n", + ftdi_get_error_string(ftdi)); + retval = -2; + goto done; +@@ -277,7 +277,7 @@ int main(int argc, char **argv) + f=(ftdi_eeprom_build(ftdi)); + if (f < 0) + { +- fprintf(stderr, "Erase failed: %s", ++ fprintf(stderr, "Erase failed: %s\n", + ftdi_get_error_string(ftdi)); + retval = -2; + goto done; +-- +2.43.0 + +From 629ed337dcc50d73beccf2a7fe4c94c1d0efd9fb Mon Sep 17 00:00:00 2001 +From: Yegor Yefremov +Date: Tue, 29 Aug 2023 10:57:00 +0200 +Subject: [PATCH 21/42] Align is_not_pnp property + +As seen when written with FTD2XX. +--- + src/ftdi.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/ftdi.c b/src/ftdi.c +index 349df8a..3d16674 100644 +--- a/src/ftdi.c ++++ b/src/ftdi.c +@@ -3125,6 +3125,8 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) + i++; + output[i & eeprom_size_mask] = eeprom->is_not_pnp; /* as seen when written with FTD2XX */ + i++; ++ output[i & eeprom_size_mask] = 0x00; ++ i++; + } + + if (ftdi->type > TYPE_AM) /* use_serial not used in AM devices */ +-- +2.43.0 + +From 0b76f232305f15d8615d0f15f9f8bdab8210567c Mon Sep 17 00:00:00 2001 +From: Yegor Yefremov +Date: Tue, 29 Aug 2023 10:50:28 +0200 +Subject: [PATCH 22/42] FT4232: show mode for both C and D channels + +--- + src/ftdi.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/src/ftdi.c b/src/ftdi.c +index 3d16674..2fb3cf8 100644 +--- a/src/ftdi.c ++++ b/src/ftdi.c +@@ -3885,6 +3885,13 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) + channel_mode[eeprom->channel_b_type], + (eeprom->channel_b_driver)?" VCP":"", + (eeprom->high_current_b)?" High Current IO":""); ++ if (ftdi->type == TYPE_4232H) ++ { ++ fprintf(stdout,"Channel C has Mode UART%s\n", ++ (eeprom->channel_c_driver)?" VCP":""); ++ fprintf(stdout,"Channel D has Mode UART%s\n", ++ (eeprom->channel_d_driver)?" VCP":""); ++ } + if (((ftdi->type == TYPE_BM) || (ftdi->type == TYPE_2232C)) && + eeprom->use_usb_version) + fprintf(stdout,"Use explicit USB Version %04x\n",eeprom->usb_version); +-- +2.43.0 + +From 7dfd1d076f14a1b2adbb31e6e8e46aa9f46ba579 Mon Sep 17 00:00:00 2001 +From: Thomas Jarosch +Date: Tue, 29 Aug 2023 15:47:41 +0200 +Subject: [PATCH 23/42] FT2232C: show mode for B channel + +Idea by Yegor Yefremov. Thanks! +--- + src/ftdi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/ftdi.c b/src/ftdi.c +index 2fb3cf8..4b16468 100644 +--- a/src/ftdi.c ++++ b/src/ftdi.c +@@ -3880,7 +3880,7 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) + (eeprom->data_order)?"LSB":"MSB", + (eeprom->flow_control)?"":"No "); + } +- if ((ftdi->type == TYPE_2232H) || (ftdi->type == TYPE_4232H)) ++ if ((ftdi->type == TYPE_2232H) || (ftdi->type == TYPE_4232H) || (ftdi->type == TYPE_2232C)) + fprintf(stdout,"Channel B has Mode %s%s%s\n", + channel_mode[eeprom->channel_b_type], + (eeprom->channel_b_driver)?" VCP":"", +-- +2.43.0 + +From b7e2b9c53cb1bd4c42538dfb61502f805100bf89 Mon Sep 17 00:00:00 2001 +From: Yegor Yefremov +Date: Mon, 31 Jul 2023 12:23:41 +0200 +Subject: [PATCH 24/42] EEPROM: make user_data_addr value readable + +Before this change, the user_data_addr could be only written +but not read. +--- + src/ftdi.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/ftdi.c b/src/ftdi.c +index 4b16468..6b78fa3 100644 +--- a/src/ftdi.c ++++ b/src/ftdi.c +@@ -4183,6 +4183,9 @@ int ftdi_get_eeprom_value(struct ftdi_context *ftdi, enum ftdi_eeprom_value valu + case EXTERNAL_OSCILLATOR: + *value = ftdi->eeprom->external_oscillator; + break; ++ case USER_DATA_ADDR: ++ *value = ftdi->eeprom->user_data_addr; ++ break; + default: + ftdi_error_return(-1, "Request for unknown EEPROM value"); + } +-- +2.43.0 + +From 4de44fefc63f112f5c804c191da101cd8252978f Mon Sep 17 00:00:00 2001 +From: Chris Johnson +Date: Wed, 3 May 2023 08:52:01 -0500 +Subject: [PATCH 25/42] Introduce ftdi_set_module_detach_mode() + +Added a public setter to allow the usage of the +AUTO_DETACH_REATACH_SIO_MODULE feature added in +5bf1c1e3ff1616fda20c26cc3e3df7b807744c99. +--- + src/ftdi.c | 18 ++++++++++++++++++ + src/ftdi.h | 1 + + 2 files changed, 19 insertions(+) + +diff --git a/src/ftdi.c b/src/ftdi.c +index 6b78fa3..534e3dd 100644 +--- a/src/ftdi.c ++++ b/src/ftdi.c +@@ -2217,6 +2217,24 @@ int ftdi_set_bitmode(struct ftdi_context *ftdi, unsigned char bitmask, unsigned + return 0; + } + ++/** ++ Set module detach mode. ++ ++ \param ftdi pointer to ftdi_context ++ \param mode detach mode to use. ++ ++ \retval 0: all fine ++ \retval -1: can't enable bitbang mode ++*/ ++int ftdi_set_module_detach_mode(struct ftdi_context *ftdi, enum ftdi_module_detach_mode mode) ++{ ++ if (ftdi == NULL) ++ ftdi_error_return(-1, "FTDI context invalid"); ++ ++ ftdi->module_detach_mode = mode; ++ return 0; ++} ++ + /** + Disable bitbang mode. + +diff --git a/src/ftdi.h b/src/ftdi.h +index 0603335..ffeb452 100644 +--- a/src/ftdi.h ++++ b/src/ftdi.h +@@ -520,6 +520,7 @@ extern "C" + int ftdi_init(struct ftdi_context *ftdi); + struct ftdi_context *ftdi_new(void); + int ftdi_set_interface(struct ftdi_context *ftdi, enum ftdi_interface interface); ++ int ftdi_set_module_detach_mode(struct ftdi_context *ftdi, enum ftdi_module_detach_mode mode); + + void ftdi_deinit(struct ftdi_context *ftdi); + void ftdi_free(struct ftdi_context *ftdi); +-- +2.43.0 + +From 9c0949fff4d2e6dfdf6701fc481b46a337a051d8 Mon Sep 17 00:00:00 2001 +From: Matthias Klein +Date: Fri, 18 Nov 2022 09:59:40 +0100 +Subject: [PATCH 26/42] ftdi_readstream: fix timeout setting + +Divide the whole seconds into tv_sec, and the remaining microseconds into tv_usec. + +Signed-off-by: Matthias Klein +--- + src/ftdi_stream.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/ftdi_stream.c b/src/ftdi_stream.c +index f5f1287..4229d94 100644 +--- a/src/ftdi_stream.c ++++ b/src/ftdi_stream.c +@@ -241,7 +241,8 @@ ftdi_readstream(struct ftdi_context *ftdi, + { + FTDIProgressInfo *progress = &state.progress; + const double progressInterval = 1.0; +- struct timeval timeout = { 0, ftdi->usb_read_timeout * 1000}; ++ struct timeval timeout = { ftdi->usb_read_timeout / 1000, ++ (ftdi->usb_read_timeout % 1000) * 1000 }; + struct timeval now; + + int err = libusb_handle_events_timeout(ftdi->usb_ctx, &timeout); +-- +2.43.0 + +From 7828006e4d0fd4fd72b77151045aaa61c053ffc3 Mon Sep 17 00:00:00 2001 +From: Yegor Yefremov +Date: Wed, 30 Aug 2023 11:57:01 +0200 +Subject: [PATCH 27/42] CMake: fix indentation and normalize braces + +--- + CMakeLists.txt | 53 +++++++++++++-------------- + examples/CMakeLists.txt | 21 ++++++----- + examples/cmake_example/CMakeLists.txt | 4 +- + ftdipp/CMakeLists.txt | 35 +++++++++--------- + packages/CMakeLists.txt | 22 +++++------ + python/CMakeLists.txt | 28 +++++++------- + python/examples/CMakeLists.txt | 5 +-- + src/CMakeLists.txt | 12 +++--- + 8 files changed, 90 insertions(+), 90 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 48a028c..9d7f9b6 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -11,7 +11,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) + + # CMake + if("${CMAKE_BUILD_TYPE}" STREQUAL "") +- set(CMAKE_BUILD_TYPE RelWithDebInfo) ++ set(CMAKE_BUILD_TYPE RelWithDebInfo) + endif("${CMAKE_BUILD_TYPE}" STREQUAL "") + set(CMAKE_COLOR_MAKEFILE ON) + +@@ -22,7 +22,7 @@ include(CMakeOptions.txt) + # Debug build + message("-- Build type: ${CMAKE_BUILD_TYPE}") + if(${CMAKE_BUILD_TYPE} STREQUAL Debug) +- add_definitions(-DDEBUG) ++ add_definitions(-DDEBUG) + endif(${CMAKE_BUILD_TYPE} STREQUAL Debug) + + # find libusb +@@ -59,7 +59,7 @@ set(CPACK_COMPONENT_SHAREDLIBS_GROUP "Development") + set(CPACK_COMPONENT_STATICLIBS_GROUP "Development") + set(CPACK_COMPONENT_HEADERS_GROUP "Development") + +-# guess LIB_SUFFIX, don't take debian multiarch into account ++# guess LIB_SUFFIX, don't take debian multiarch into account + if ( NOT DEFINED LIB_SUFFIX ) + if( CMAKE_SYSTEM_NAME MATCHES "Linux" + AND NOT CMAKE_CROSSCOMPILING +@@ -73,9 +73,9 @@ endif () + + if(NOT APPLE) + if(CMAKE_SIZEOF_VOID_P EQUAL 4) +- SET(PACK_ARCH "") +- else(CMAKE_SIZEOF_VOID_P EQUAL 8) +- SET(PACK_ARCH .x86_64) ++ SET(PACK_ARCH "") ++ else(CMAKE_SIZEOF_VOID_P EQUAL 8) ++ SET(PACK_ARCH .x86_64) + endif(CMAKE_SIZEOF_VOID_P EQUAL 4) + else(NOT APPLE) + SET(PACK_ARCH "") +@@ -85,8 +85,8 @@ endif(NOT APPLE) + set(CPACK_PACKAGE_VERSION ${VERSION_STRING}) + set(CPACK_PACKAGE_CONTACT "Intra2net AG ") + set(CPACK_PACKAGE_DESCRIPTION "libftdi1 library.") +-set(CPACK_PACKAGE_DESCRIPTION_SUMMARY ${CPACK_PACKAGE_DESCRIPTION} +- ) ++set(CPACK_PACKAGE_DESCRIPTION_SUMMARY ${CPACK_PACKAGE_DESCRIPTION}) ++ + # Package settings + if ( UNIX ) + set(CPACK_GENERATOR "DEB;RPM") +@@ -125,22 +125,22 @@ add_custom_target(dist + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) + + if ( DOCUMENTATION ) +- find_package ( Doxygen REQUIRED) ++ find_package ( Doxygen REQUIRED) + +- # Copy doxy.config.in +- set(top_srcdir ${CMAKE_SOURCE_DIR}) +- configure_file(${CMAKE_SOURCE_DIR}/doc/Doxyfile.in ${CMAKE_BINARY_DIR}/Doxyfile ) +- configure_file(${CMAKE_SOURCE_DIR}/doc/Doxyfile.xml.in ${CMAKE_BINARY_DIR}/Doxyfile.xml ) ++ # Copy doxy.config.in ++ set(top_srcdir ${CMAKE_SOURCE_DIR}) ++ configure_file(${CMAKE_SOURCE_DIR}/doc/Doxyfile.in ${CMAKE_BINARY_DIR}/Doxyfile ) ++ configure_file(${CMAKE_SOURCE_DIR}/doc/Doxyfile.xml.in ${CMAKE_BINARY_DIR}/Doxyfile.xml ) + +- # Run doxygen +- add_custom_command( ++ # Run doxygen ++ add_custom_command( + OUTPUT ${CMAKE_BINARY_DIR}/doc/html/index.html + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/doc + COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_BINARY_DIR}/Doxyfile + DEPENDS ${c_headers};${c_sources};${cpp_sources};${cpp_headers} +- ) ++ ) + +- add_custom_target(docs ALL DEPENDS ${CMAKE_BINARY_DIR}/doc/html/index.html) ++ add_custom_target(docs ALL DEPENDS ${CMAKE_BINARY_DIR}/doc/html/index.html) + endif () + + add_subdirectory(src) +@@ -169,10 +169,10 @@ set(exec_prefix ${CMAKE_INSTALL_PREFIX}/bin) + set(includedir ${CMAKE_INSTALL_PREFIX}/include/${PROJECT_NAME}) + + if(${UNIX}) +- set(libdir ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}) ++ set(libdir ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}) + endif(${UNIX}) + if(${WIN32}) +- set(libdir ${CMAKE_INSTALL_PREFIX}/bin) ++ set(libdir ${CMAKE_INSTALL_PREFIX}/bin) + endif(${WIN32}) + + configure_file(${CMAKE_SOURCE_DIR}/libftdi1.pc.in ${CMAKE_BINARY_DIR}/libftdi1.pc @ONLY) +@@ -232,14 +232,13 @@ write_basic_package_version_file ( + COMPATIBILITY AnyNewerVersion + ) + +- +-install ( FILES +- ${CMAKE_CURRENT_BINARY_DIR}/LibFTDI1Config.cmake +- ${CMAKE_CURRENT_BINARY_DIR}/LibFTDI1ConfigVersion.cmake +- cmake/UseLibFTDI1.cmake +- +- DESTINATION ${LIBFTDI_CMAKE_CONFIG_DIR} +- ) ++install ( ++ FILES ++ ${CMAKE_CURRENT_BINARY_DIR}/LibFTDI1Config.cmake ++ ${CMAKE_CURRENT_BINARY_DIR}/LibFTDI1ConfigVersion.cmake ++ cmake/UseLibFTDI1.cmake ++ DESTINATION ${LIBFTDI_CMAKE_CONFIG_DIR} ++) + + include(CPack) + +diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt +index dd8ffbe..382cb33 100644 +--- a/examples/CMakeLists.txt ++++ b/examples/CMakeLists.txt +@@ -1,7 +1,7 @@ + # Includes + include_directories( ${CMAKE_CURRENT_SOURCE_DIR} +- ${CMAKE_CURRENT_BINARY_DIR} +- ) ++ ${CMAKE_CURRENT_BINARY_DIR} ++) + + # Targets + add_executable(simple simple.c) +@@ -16,7 +16,7 @@ add_executable(stream_test stream_test.c) + add_executable(eeprom eeprom.c) + add_executable(async async.c) + if(NOT MINGW) +- add_executable(purge_test purge_test.c) ++ add_executable(purge_test purge_test.c) + endif(NOT MINGW) + + # Linkage +@@ -32,19 +32,20 @@ target_link_libraries(stream_test ftdi1) + target_link_libraries(eeprom ftdi1) + target_link_libraries(async ftdi1) + if(NOT MINGW) +- target_link_libraries(purge_test ftdi1) ++ target_link_libraries(purge_test ftdi1) + endif(NOT MINGW) + + # libftdi++ examples + if( FTDIPP ) +- include_directories(BEFORE ${CMAKE_SOURCE_DIR}/ftdipp +- ${Boost_INCLUDE_DIRS}) ++ include_directories(BEFORE ${CMAKE_SOURCE_DIR}/ftdipp ++ ${Boost_INCLUDE_DIRS} ++ ) + +- # Target +- add_executable(find_all_pp find_all_pp.cpp) ++ # Target ++ add_executable(find_all_pp find_all_pp.cpp) + +- # Linkage +- target_link_libraries(find_all_pp ftdipp1) ++ # Linkage ++ target_link_libraries(find_all_pp ftdipp1) + endif( FTDIPP ) + + # Source includes +diff --git a/examples/cmake_example/CMakeLists.txt b/examples/cmake_example/CMakeLists.txt +index fe203ed..5a1e1a7 100644 +--- a/examples/cmake_example/CMakeLists.txt ++++ b/examples/cmake_example/CMakeLists.txt +@@ -9,5 +9,5 @@ add_executable ( example main.c ) + target_link_libraries( example ${LIBFTDI_LIBRARIES} ) + + install ( TARGETS example +- DESTINATION bin ) +- ++ DESTINATION bin ++) +diff --git a/ftdipp/CMakeLists.txt b/ftdipp/CMakeLists.txt +index fac5bcc..38932ae 100644 +--- a/ftdipp/CMakeLists.txt ++++ b/ftdipp/CMakeLists.txt +@@ -6,8 +6,9 @@ set(cpp_headers ${CMAKE_CURRENT_SOURCE_DIR}/ftdi.hpp CACHE INTERNAL "List of cpp + + # Includes + include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR} +- ${CMAKE_CURRENT_SOURCE_DIR} +- ${CMAKE_SOURCE_DIR}/src) ++ ${CMAKE_CURRENT_SOURCE_DIR} ++ ${CMAKE_SOURCE_DIR}/src ++) + + include_directories(${Boost_INCLUDE_DIRS}) + +@@ -24,24 +25,24 @@ set_target_properties(ftdipp1 PROPERTIES CLEAN_DIRECT_OUTPUT 1) + target_link_libraries(ftdipp1 ftdi1 ${LIBUSB_LIBRARIES} ${BOOST_LIBRARIES}) + + install ( TARGETS ftdipp1 +- RUNTIME DESTINATION bin +- LIBRARY DESTINATION lib${LIB_SUFFIX} +- ARCHIVE DESTINATION lib${LIB_SUFFIX} +- ) ++ RUNTIME DESTINATION bin ++ LIBRARY DESTINATION lib${LIB_SUFFIX} ++ ARCHIVE DESTINATION lib${LIB_SUFFIX} ++) + + # Static library + if ( STATICLIBS ) +- add_library(ftdipp1-static STATIC ${cpp_sources}) +- set_target_properties(ftdipp1-static PROPERTIES OUTPUT_NAME "ftdipp1") +- set_target_properties(ftdipp1-static PROPERTIES CLEAN_DIRECT_OUTPUT 1) +- +- install ( TARGETS ftdipp1-static +- ARCHIVE DESTINATION lib${LIB_SUFFIX} +- COMPONENT staticlibs +- ) ++ add_library(ftdipp1-static STATIC ${cpp_sources}) ++ set_target_properties(ftdipp1-static PROPERTIES OUTPUT_NAME "ftdipp1") ++ set_target_properties(ftdipp1-static PROPERTIES CLEAN_DIRECT_OUTPUT 1) ++ ++ install ( TARGETS ftdipp1-static ++ ARCHIVE DESTINATION lib${LIB_SUFFIX} ++ COMPONENT staticlibs ++ ) + endif () + + install ( FILES ${cpp_headers} +- DESTINATION include/${PROJECT_NAME} +- COMPONENT headers +- ) ++ DESTINATION include/${PROJECT_NAME} ++ COMPONENT headers ++) +diff --git a/packages/CMakeLists.txt b/packages/CMakeLists.txt +index 4bf58d2..204bbe0 100644 +--- a/packages/CMakeLists.txt ++++ b/packages/CMakeLists.txt +@@ -1,19 +1,19 @@ + # Debian + if("${PACKAGE}" STREQUAL "Debian") + +- # Settings +- set(REVISION 0) +- set(CPACK_GENERATOR "DEB" PARENT_SCOPE) +- set(CPACK_PACKAGE_VERSION ${CPACK_PACKAGE_VERSION}-${REVISION} PARENT_SCOPE) ++ # Settings ++ set(REVISION 0) ++ set(CPACK_GENERATOR "DEB" PARENT_SCOPE) ++ set(CPACK_PACKAGE_VERSION ${CPACK_PACKAGE_VERSION}-${REVISION} PARENT_SCOPE) + +- # Dependencies +- set(CPACK_DEBIAN_PACKAGE_DEPENDS "libusb-1.0-0" PARENT_SCOPE) +- set(DEBIAN_PACKAGE_BUILDS_DEPENDS "cmake, libusb2-dev" PARENT_SCOPE) ++ # Dependencies ++ set(CPACK_DEBIAN_PACKAGE_DEPENDS "libusb-1.0-0" PARENT_SCOPE) ++ set(DEBIAN_PACKAGE_BUILDS_DEPENDS "cmake, libusb2-dev" PARENT_SCOPE) + +- # Bundles +- message("-- Installing udev rules to /etc/udev/rules.d") +- install(FILES 99-libftdi.rules +- DESTINATION /etc/udev/rules.d) ++ # Bundles ++ message("-- Installing udev rules to /etc/udev/rules.d") ++ install(FILES 99-libftdi.rules ++ DESTINATION /etc/udev/rules.d) + + endif("${PACKAGE}" STREQUAL "Debian") + +diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt +index 1a8142b..f8ac423 100644 +--- a/python/CMakeLists.txt ++++ b/python/CMakeLists.txt +@@ -55,23 +55,23 @@ install ( FILES ${CMAKE_CURRENT_BINARY_DIR}/ftdi1.py DESTINATION ${PYTHON_MODULE + install ( TARGETS ${SWIG_MODULE_ftdi1_REAL_NAME} LIBRARY DESTINATION ${PYTHON_MODULE_PATH} ) + + if ( DOCUMENTATION ) +- # Run doxygen to only generate the xml +- add_custom_command ( OUTPUT ${CMAKE_BINARY_DIR}/doc/xml/ftdi_8c.xml +- COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/doc +- COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_BINARY_DIR}/Doxyfile.xml +- WORKING_DIRECTORY ${CMAKE_BINARY_DIR} +- DEPENDS ${c_headers};${c_sources};${cpp_sources};${cpp_headers} +- ) ++ # Run doxygen to only generate the xml ++ add_custom_command ( OUTPUT ${CMAKE_BINARY_DIR}/doc/xml/ftdi_8c.xml ++ COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/doc ++ COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_BINARY_DIR}/Doxyfile.xml ++ WORKING_DIRECTORY ${CMAKE_BINARY_DIR} ++ DEPENDS ${c_headers};${c_sources};${cpp_sources};${cpp_headers} ++ ) + +- # generate .i from doxygen .xml +- add_custom_command ( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/ftdi1_doc.i +- COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/doxy2swig.py -n ++ # generate .i from doxygen .xml ++ add_custom_command ( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/ftdi1_doc.i ++ COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/doxy2swig.py -n + ${CMAKE_BINARY_DIR}/doc/xml/ftdi_8c.xml + ${CMAKE_CURRENT_BINARY_DIR}/ftdi1_doc.i +- DEPENDS ${CMAKE_BINARY_DIR}/doc/xml/ftdi_8c.xml +- ) +- add_custom_target ( doc_i DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/ftdi1_doc.i ) +- add_dependencies( ${SWIG_MODULE_ftdi1_REAL_NAME} doc_i ) ++ DEPENDS ${CMAKE_BINARY_DIR}/doc/xml/ftdi_8c.xml ++ ) ++ add_custom_target ( doc_i DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/ftdi1_doc.i ) ++ add_dependencies( ${SWIG_MODULE_ftdi1_REAL_NAME} doc_i ) + + endif () + +diff --git a/python/examples/CMakeLists.txt b/python/examples/CMakeLists.txt +index b4ed93d..232595f 100644 +--- a/python/examples/CMakeLists.txt ++++ b/python/examples/CMakeLists.txt +@@ -1,5 +1,4 @@ + install ( FILES simple.py complete.py cbus.py + DESTINATION share/libftdi/examples +- PERMISSIONS OWNER_READ GROUP_READ WORLD_READ +- ) +- ++ PERMISSIONS OWNER_READ GROUP_READ WORLD_READ ++) +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index 17b3617..cf630ba 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -1,7 +1,7 @@ + # Includes + include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR} +- ${CMAKE_CURRENT_SOURCE_DIR} +- ) ++ ${CMAKE_CURRENT_SOURCE_DIR} ++) + + # Version information + set(SNAPSHOT_VERSION "unknown") +@@ -9,7 +9,7 @@ execute_process(COMMAND git describe + OUTPUT_VARIABLE GIT_DESCRIBE_OUTPUT + RESULT_VARIABLE GIT_DESCRIBE_RESULT + OUTPUT_STRIP_TRAILING_WHITESPACE +- ) ++) + if(${GIT_DESCRIBE_RESULT} STREQUAL 0) + set(SNAPSHOT_VERSION ${GIT_DESCRIBE_OUTPUT}) + endif () +@@ -36,7 +36,7 @@ install ( TARGETS ftdi1 + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib${LIB_SUFFIX} + ARCHIVE DESTINATION lib${LIB_SUFFIX} +- ) ++) + + if ( STATICLIBS ) + add_library(ftdi1-static STATIC ${c_sources}) +@@ -46,10 +46,10 @@ if ( STATICLIBS ) + install ( TARGETS ftdi1-static + ARCHIVE DESTINATION lib${LIB_SUFFIX} + COMPONENT staticlibs +- ) ++ ) + endif () + + install ( FILES ${c_headers} + DESTINATION include/${PROJECT_NAME} + COMPONENT headers +- ) ++) +-- +2.43.0 + +From d2c44d28fec89b22cb27e61d402087d229282a2a Mon Sep 17 00:00:00 2001 +From: Yegor Yefremov +Date: Thu, 31 Aug 2023 09:07:51 +0200 +Subject: [PATCH 28/42] examples/eeprom.c: use AUTO_DETACH_REATACH_SIO_MODULE + +This way, the device's state remains unchanged after the +eeprom invocation. + +Bonus: remove trailing white spaces. +--- + examples/eeprom.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/examples/eeprom.c b/examples/eeprom.c +index 45f5dff..3d03ac3 100644 +--- a/examples/eeprom.c ++++ b/examples/eeprom.c +@@ -90,6 +90,8 @@ int main(int argc, char **argv) + return EXIT_FAILURE; + } + ++ ftdi->module_detach_mode = AUTO_DETACH_REATACH_SIO_MODULE; ++ + while ((i = getopt(argc, argv, "d::ev:p:l:P:S:w")) != -1) + { + switch (i) +@@ -200,7 +202,7 @@ int main(int argc, char **argv) + fprintf(stderr, "\n"); + fprintf(stderr, "unable to open ftdi device: %d (%s)\n", + f, ftdi_get_error_string(ftdi)); +- ++ + retval = -1; + goto done; + } +-- +2.43.0 + +From 61a6bac98bbac623fb33b6153a063b6436f84721 Mon Sep 17 00:00:00 2001 +From: Yegor Yefremov +Date: Thu, 31 Aug 2023 09:23:29 +0200 +Subject: [PATCH 29/42] CMake: require 2.8.12 for cmake_example + +Make CMake minimal version requirement consistent for the entire +project. +--- + examples/cmake_example/CMakeLists.txt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/examples/cmake_example/CMakeLists.txt b/examples/cmake_example/CMakeLists.txt +index 5a1e1a7..36002df 100644 +--- a/examples/cmake_example/CMakeLists.txt ++++ b/examples/cmake_example/CMakeLists.txt +@@ -1,4 +1,4 @@ +-cmake_minimum_required ( VERSION 2.8 ) ++cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR) + + project ( example C ) + +-- +2.43.0 + +From 18bae9b40640804d0a35e9dca6787d6c34c66703 Mon Sep 17 00:00:00 2001 +From: Yegor Yefremov +Date: Thu, 31 Aug 2023 09:23:30 +0200 +Subject: [PATCH 30/42] CMake: rework documentation creation section + +Add comments and also make the if ( DOCUMENTATION ) section more +readable. +--- + CMakeLists.txt | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 9d7f9b6..1745dc8 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -137,11 +137,16 @@ if ( DOCUMENTATION ) + OUTPUT ${CMAKE_BINARY_DIR}/doc/html/index.html + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/doc + COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_BINARY_DIR}/Doxyfile ++ COMMENT "Generating API documentation" + DEPENDS ${c_headers};${c_sources};${cpp_sources};${cpp_headers} + ) + +- add_custom_target(docs ALL DEPENDS ${CMAKE_BINARY_DIR}/doc/html/index.html) +-endif () ++ add_custom_target( ++ docs ALL ++ COMMENT "Documentation target docs" ++ DEPENDS ${CMAKE_BINARY_DIR}/doc/html/index.html ++ ) ++endif ( DOCUMENTATION ) + + add_subdirectory(src) + if ( FTDIPP ) +-- +2.43.0 + +From 5a85740e9701abc4fd439bee10d31b039ea5ed3e Mon Sep 17 00:00:00 2001 +From: Yegor Yefremov +Date: Thu, 31 Aug 2023 09:34:10 +0200 +Subject: [PATCH 31/42] Doxygen: resolve warnings + +Remove obsolete values like MSCGEN_PATH, TCL_SUBST, etc. from the +configuration file. All these options used the default values, hence +it is safe to remove them. + +Paper type a4wide doesn't exist, so use a4. +--- + doc/Doxyfile.in | 30 +----------------------------- + 1 file changed, 1 insertion(+), 29 deletions(-) + +diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in +index a4f59ee..d7ddff8 100644 +--- a/doc/Doxyfile.in ++++ b/doc/Doxyfile.in +@@ -230,12 +230,6 @@ TAB_SIZE = 4 + + ALIASES = + +-# This tag can be used to specify a number of word-keyword mappings (TCL only). +-# A mapping has the form "name=value". For example adding "class=itcl::class" +-# will allow you to use the command class in the itcl::class meaning. +- +-TCL_SUBST = +- + # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources + # only. Doxygen will then generate output that is more tailored for C. For + # instance, some of the names that are used will be different. The list of all +@@ -1006,13 +1000,6 @@ VERBATIM_HEADERS = YES + + ALPHABETICAL_INDEX = NO + +-# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +-# which the alphabetical index list will be split. +-# Minimum value: 1, maximum value: 20, default value: 5. +-# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. +- +-COLS_IN_ALPHA_INDEX = 5 +- + # In case all classes in a project start with a common prefix, all classes will + # be put under the same header in the alphabetical index. The IGNORE_PREFIX tag + # can be used to specify a prefix (or a list of prefixes) that should be ignored +@@ -1615,7 +1602,7 @@ COMPACT_LATEX = NO + # The default value is: a4. + # This tag requires that the tag GENERATE_LATEX is set to YES. + +-PAPER_TYPE = a4wide ++PAPER_TYPE = a4 + + # The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names + # that should be included in the LaTeX output. The package can be specified just +@@ -2072,12 +2059,6 @@ EXTERNAL_GROUPS = YES + + EXTERNAL_PAGES = YES + +-# The PERL_PATH should be the absolute path and name of the perl script +-# interpreter (i.e. the result of 'which perl'). +-# The default file (with absolute path) is: /usr/bin/perl. +- +-PERL_PATH = /usr/bin/perl +- + #--------------------------------------------------------------------------- + # Configuration options related to the dot tool + #--------------------------------------------------------------------------- +@@ -2091,15 +2072,6 @@ PERL_PATH = /usr/bin/perl + + CLASS_DIAGRAMS = YES + +-# You can define message sequence charts within doxygen comments using the \msc +-# command. Doxygen will then run the mscgen tool (see: +-# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the +-# documentation. The MSCGEN_PATH tag allows you to specify the directory where +-# the mscgen tool resides. If left empty the tool is assumed to be found in the +-# default search path. +- +-MSCGEN_PATH = +- + # You can include diagrams made with dia in doxygen documentation. Doxygen will + # then run dia to produce the diagram and insert it in the documentation. The + # DIA_PATH tag allows you to specify the directory where the dia binary resides. +-- +2.43.0 + +From 91d2d1f1be6615a02f8d2ac0b90607fb7a3dd770 Mon Sep 17 00:00:00 2001 +From: Yegor Yefremov +Date: Fri, 1 Sep 2023 11:33:02 +0200 +Subject: [PATCH 32/42] CMake: disable deprecated behavior + +Set policies CMP0011, CMP0057, CMP0099 to the new behavior. Since +version 3.27.4 if the policy is not set to the new behavior, CMake +will generate a warning. +--- + CMakeLists.txt | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 1745dc8..f36912d 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -9,6 +9,23 @@ set(VERSION_STRING ${MAJOR_VERSION}.${MINOR_VERSION}) + set(VERSION ${VERSION_STRING}) + set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) + ++# Support new if() IN_LIST operator ++if(POLICY CMP0057) ++ cmake_policy(SET CMP0057 NEW) ++endif() ++ ++# Included scripts do automatic cmake_policy() PUSH and POP ++if(POLICY CMP0011) ++ cmake_policy(SET CMP0011 NEW) ++endif() ++ ++# Target link properties INTERFACE_LINK_OPTIONS, INTERFACE_LINK_DIRECTORIES ++# and INTERFACE_LINK_DEPENDS are now transitive over private dependencies ++# of static libraries ++if(POLICY CMP0099) ++ cmake_policy(SET CMP0099 NEW) ++endif() ++ + # CMake + if("${CMAKE_BUILD_TYPE}" STREQUAL "") + set(CMAKE_BUILD_TYPE RelWithDebInfo) +-- +2.43.0 + +From e5136ce5407ceffd388f69c1582a6b0d6167f61d Mon Sep 17 00:00:00 2001 +From: Yegor Yefremov +Date: Mon, 11 Sep 2023 10:03:59 +0200 +Subject: [PATCH 33/42] CMake: use dedicated recipe for documentation + generation + +Use PROJECT_SOURCE_DIR and PROJECT_BINARY_DIR to refer to the top +source directory. +--- + CMakeLists.txt | 22 +--------------------- + doc/CMakeLists.txt | 26 ++++++++++++++++++++++++++ + doc/Doxyfile.in | 8 ++++---- + doc/Doxyfile.xml.in | 2 +- + python/CMakeLists.txt | 22 +++++++++++++--------- + 5 files changed, 45 insertions(+), 35 deletions(-) + create mode 100644 doc/CMakeLists.txt + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index f36912d..24da84d 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -142,27 +142,7 @@ add_custom_target(dist + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) + + if ( DOCUMENTATION ) +- find_package ( Doxygen REQUIRED) +- +- # Copy doxy.config.in +- set(top_srcdir ${CMAKE_SOURCE_DIR}) +- configure_file(${CMAKE_SOURCE_DIR}/doc/Doxyfile.in ${CMAKE_BINARY_DIR}/Doxyfile ) +- configure_file(${CMAKE_SOURCE_DIR}/doc/Doxyfile.xml.in ${CMAKE_BINARY_DIR}/Doxyfile.xml ) +- +- # Run doxygen +- add_custom_command( +- OUTPUT ${CMAKE_BINARY_DIR}/doc/html/index.html +- COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/doc +- COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_BINARY_DIR}/Doxyfile +- COMMENT "Generating API documentation" +- DEPENDS ${c_headers};${c_sources};${cpp_sources};${cpp_headers} +- ) +- +- add_custom_target( +- docs ALL +- COMMENT "Documentation target docs" +- DEPENDS ${CMAKE_BINARY_DIR}/doc/html/index.html +- ) ++ add_subdirectory(doc) + endif ( DOCUMENTATION ) + + add_subdirectory(src) +diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt +new file mode 100644 +index 0000000..983301d +--- /dev/null ++++ b/doc/CMakeLists.txt +@@ -0,0 +1,26 @@ ++find_package ( Doxygen REQUIRED ) ++ ++# Copy doxy.config.in ++configure_file( ++ ${PROJECT_SOURCE_DIR}/doc/Doxyfile.in ++ ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile ++) ++ ++configure_file( ++ ${PROJECT_SOURCE_DIR}/doc/Doxyfile.xml.in ++ ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile.xml ++) ++ ++# Run doxygen ++add_custom_command( ++ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/html/index.html ++ COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile ++ COMMENT "Generating API documentation" ++ DEPENDS ${c_headers};${c_sources};${cpp_sources};${cpp_headers} ++) ++ ++add_custom_target( ++ docs ALL ++ COMMENT "Documentation target docs" ++ DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/html/index.html ++) +diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in +index d7ddff8..a05fe57 100644 +--- a/doc/Doxyfile.in ++++ b/doc/Doxyfile.in +@@ -58,7 +58,7 @@ PROJECT_LOGO = + # entered, it will be relative to the location where doxygen was started. If + # left blank the current directory will be used. + +-OUTPUT_DIRECTORY = doc ++OUTPUT_DIRECTORY = @CMAKE_CURRENT_BINARY_DIR@ + + # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- + # directories (in 2 levels) under the output directory of each output format and +@@ -759,8 +759,8 @@ WARN_LOGFILE = + # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING + # Note: If this tag is empty the current directory is searched. + +-INPUT = @top_srcdir@/src \ +- @top_srcdir@/ftdipp ++INPUT = @PROJECT_SOURCE_DIR@/src \ ++ @PROJECT_SOURCE_DIR@/ftdipp + + # This tag can be used to specify the character encoding of the source files + # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +@@ -833,7 +833,7 @@ EXCLUDE_SYMBOLS = + # that contain example code fragments that are included (see the \include + # command). + +-EXAMPLE_PATH = @top_srcdir@/examples ++EXAMPLE_PATH = @PROJECT_SOURCE_DIR@/examples + + # If the value of the EXAMPLE_PATH tag contains directories, you can use the + # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +diff --git a/doc/Doxyfile.xml.in b/doc/Doxyfile.xml.in +index 8a32509..ab57478 100644 +--- a/doc/Doxyfile.xml.in ++++ b/doc/Doxyfile.xml.in +@@ -2,7 +2,7 @@ + + # xml generation only + # keep settings but shut off all other generation +-@INCLUDE = Doxyfile ++@INCLUDE = doc/Doxyfile + + GENERATE_TODOLIST = NO + GENERATE_TESTLIST = NO +diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt +index f8ac423..6ab14cd 100644 +--- a/python/CMakeLists.txt ++++ b/python/CMakeLists.txt +@@ -56,24 +56,28 @@ install ( TARGETS ${SWIG_MODULE_ftdi1_REAL_NAME} LIBRARY DESTINATION ${PYTHON_MO + + if ( DOCUMENTATION ) + # Run doxygen to only generate the xml +- add_custom_command ( OUTPUT ${CMAKE_BINARY_DIR}/doc/xml/ftdi_8c.xml +- COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/doc +- COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_BINARY_DIR}/Doxyfile.xml +- WORKING_DIRECTORY ${CMAKE_BINARY_DIR} ++ add_custom_command ( OUTPUT ${PROJECT_BINARY_DIR}/doc/xml/ftdi_8c.xml ++ COMMAND ${DOXYGEN_EXECUTABLE} ${PROJECT_BINARY_DIR}/doc/Doxyfile.xml ++ WORKING_DIRECTORY ${PROJECT_BINARY_DIR} ++ COMMENT "Generating ftdi_8c.xml" + DEPENDS ${c_headers};${c_sources};${cpp_sources};${cpp_headers} + ) + + # generate .i from doxygen .xml + add_custom_command ( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/ftdi1_doc.i + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/doxy2swig.py -n +- ${CMAKE_BINARY_DIR}/doc/xml/ftdi_8c.xml +- ${CMAKE_CURRENT_BINARY_DIR}/ftdi1_doc.i +- DEPENDS ${CMAKE_BINARY_DIR}/doc/xml/ftdi_8c.xml ++ ${PROJECT_BINARY_DIR}/doc/xml/ftdi_8c.xml ++ ${CMAKE_CURRENT_BINARY_DIR}/ftdi1_doc.i ++ COMMENT "Generating ftdi1_doc.i from ftdi_8c.xml" ++ DEPENDS ${PROJECT_BINARY_DIR}/doc/xml/ftdi_8c.xml ++ ) ++ add_custom_target ( doc_i ++ COMMENT "Python API bindings documentation" ++ DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/ftdi1_doc.i + ) +- add_custom_target ( doc_i DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/ftdi1_doc.i ) + add_dependencies( ${SWIG_MODULE_ftdi1_REAL_NAME} doc_i ) + +-endif () ++endif ( DOCUMENTATION ) + + set ( LIBFTDI_PYTHON_MODULE_PATH ${CMAKE_INSTALL_PREFIX}/${PYTHON_MODULE_PATH} ) + set ( LIBFTDI_PYTHON_MODULE_PATH ${LIBFTDI_PYTHON_MODULE_PATH} PARENT_SCOPE ) # for ftdiconfig.cmake +-- +2.43.0 + +From 3dc444f99bbc780f06ee6115c086e30f2dda471a Mon Sep 17 00:00:00 2001 +From: Yegor Yefremov +Date: Mon, 11 Sep 2023 10:04:00 +0200 +Subject: [PATCH 34/42] CMake: report CMake version + +--- + CMakeLists.txt | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 24da84d..39857a2 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -1,5 +1,7 @@ + cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR) + ++message(STATUS "CMake version: ${CMAKE_VERSION}") ++ + # Project + project(libftdi1 C) + set(MAJOR_VERSION 1) +-- +2.43.0 + +From 161caf3db4e2ff1c18328c0f628614987e50ffcc Mon Sep 17 00:00:00 2001 +From: Yegor Yefremov +Date: Mon, 11 Sep 2023 10:04:01 +0200 +Subject: [PATCH 35/42] CMake: rework findlibusb module + +Rename the module to FindLibUSB.cmake and use it as the only way +of finding libusb. + +Bonus: perform CMake linting of the module. +--- + CMakeLists.txt | 14 +++----------- + cmake/{FindUSB1.cmake => FindLibUSB.cmake} | 13 +++++++------ + 2 files changed, 10 insertions(+), 17 deletions(-) + rename cmake/{FindUSB1.cmake => FindLibUSB.cmake} (77%) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 39857a2..947fb34 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -44,17 +44,9 @@ if(${CMAKE_BUILD_TYPE} STREQUAL Debug) + add_definitions(-DDEBUG) + endif(${CMAKE_BUILD_TYPE} STREQUAL Debug) + +-# find libusb +-find_package( PkgConfig ) +-if (PkgConfig_FOUND) +- pkg_check_modules( LIBUSB libusb-1.0 ) +- if (LIBUSB_FOUND) +- include_directories ( ${LIBUSB_INCLUDE_DIRS} ) +- else() +- find_package ( USB1 REQUIRED ) +- include_directories ( ${LIBUSB_INCLUDE_DIR} ) +- endif() +-endif() ++# Find libusb ++find_package ( LibUSB REQUIRED ) ++include_directories ( ${LIBUSB_INCLUDE_DIR} ) + + # Find Boost + if (FTDIPP OR BUILD_TESTS) +diff --git a/cmake/FindUSB1.cmake b/cmake/FindLibUSB.cmake +similarity index 77% +rename from cmake/FindUSB1.cmake +rename to cmake/FindLibUSB.cmake +index b90e297..766fc82 100644 +--- a/cmake/FindUSB1.cmake ++++ b/cmake/FindLibUSB.cmake +@@ -1,4 +1,4 @@ +-# - Try to find the freetype library ++# - Try to find the libusb library + # Once done this defines + # + # LIBUSB_FOUND - system has libusb +@@ -10,7 +10,6 @@ + # Redistribution and use is allowed according to the terms of the BSD license. + # For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +- + if (LIBUSB_INCLUDE_DIR AND LIBUSB_LIBRARIES) + + # in cache already +@@ -22,16 +21,18 @@ else (LIBUSB_INCLUDE_DIR AND LIBUSB_LIBRARIES) + find_package(PkgConfig) + pkg_check_modules(PC_LIBUSB libusb-1.0) + +- FIND_PATH(LIBUSB_INCLUDE_DIR libusb.h ++ find_path(LIBUSB_INCLUDE_DIR libusb.h + PATH_SUFFIXES libusb-1.0 + PATHS ${PC_LIBUSB_INCLUDEDIR} ${PC_LIBUSB_INCLUDE_DIRS}) + +- FIND_LIBRARY(LIBUSB_LIBRARIES NAMES usb-1.0 ++ find_library(LIBUSB_LIBRARIES NAMES usb-1.0 + PATHS ${PC_LIBUSB_LIBDIR} ${PC_LIBUSB_LIBRARY_DIRS}) + + include(FindPackageHandleStandardArgs) +- FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBUSB DEFAULT_MSG LIBUSB_LIBRARIES LIBUSB_INCLUDE_DIR) ++ find_package_handle_standard_args( ++ LibUSB DEFAULT_MSG LIBUSB_LIBRARIES LIBUSB_INCLUDE_DIR ++ ) + +- MARK_AS_ADVANCED(LIBUSB_INCLUDE_DIR LIBUSB_LIBRARIES) ++ mark_as_advanced(LIBUSB_INCLUDE_DIR LIBUSB_LIBRARIES) + + endif (LIBUSB_INCLUDE_DIR AND LIBUSB_LIBRARIES) +-- +2.43.0 + +From bc05652f65d4d5415d58e29ff525ddc7c8c1c8dd Mon Sep 17 00:00:00 2001 +From: Yegor Yefremov +Date: Mon, 11 Sep 2023 10:04:02 +0200 +Subject: [PATCH 36/42] CMake: rework subdirectory handling + +Move all mandatory subdirs to the top and also make if clauses more +readable. +--- + CMakeLists.txt | 21 +++++++++++++-------- + 1 file changed, 13 insertions(+), 8 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 947fb34..7f72e0c 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -135,29 +135,34 @@ add_custom_target(dist + | bzip2 > ${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}.tar.bz2 + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) + ++add_subdirectory(src) ++add_subdirectory(packages) ++ + if ( DOCUMENTATION ) + add_subdirectory(doc) + endif ( DOCUMENTATION ) + +-add_subdirectory(src) + if ( FTDIPP ) + project(libftdi1 C CXX) + add_subdirectory(ftdipp) +-endif () ++endif ( FTDIPP ) ++ + if ( PYTHON_BINDINGS ) +-add_subdirectory(python) +-endif () ++ add_subdirectory(python) ++endif ( PYTHON_BINDINGS ) ++ + if ( FTDI_EEPROM ) + add_subdirectory(ftdi_eeprom) +-endif () ++endif ( FTDI_EEPROM ) ++ + if ( EXAMPLES ) + add_subdirectory(examples) +-endif () +-add_subdirectory(packages) ++endif ( EXAMPLES ) ++ + if ( BUILD_TESTS ) + project(libftdi1 C CXX) + add_subdirectory(test) +-endif () ++endif ( BUILD_TESTS ) + + # PkgConfig + set(prefix ${CMAKE_INSTALL_PREFIX}) +-- +2.43.0 + +From 09203ccd2a8798ed246c6075be6ffe56c38be16a Mon Sep 17 00:00:00 2001 +From: Yegor Yefremov +Date: Mon, 11 Sep 2023 10:04:03 +0200 +Subject: [PATCH 37/42] ftdipp/CMakeLists.txt: remove VIM modline settings + +Indentation settings will be handled via the EditorConfig project. +--- + ftdipp/CMakeLists.txt | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/ftdipp/CMakeLists.txt b/ftdipp/CMakeLists.txt +index 38932ae..fa2711f 100644 +--- a/ftdipp/CMakeLists.txt ++++ b/ftdipp/CMakeLists.txt +@@ -1,5 +1,3 @@ +-# vim: ts=2:sw=2:sts=2 +- + # Targets + set(cpp_sources ${CMAKE_CURRENT_SOURCE_DIR}/ftdi.cpp CACHE INTERNAL "List of cpp sources" ) + set(cpp_headers ${CMAKE_CURRENT_SOURCE_DIR}/ftdi.hpp CACHE INTERNAL "List of cpp headers" ) +-- +2.43.0 + +From e7f734f82c69aea10f1f9bde57f228339fcb56f3 Mon Sep 17 00:00:00 2001 +From: Yegor Yefremov +Date: Mon, 11 Sep 2023 10:04:04 +0200 +Subject: [PATCH 38/42] CMake: make the project compatible with building as a + subproject + +Use CMAKE_CURRENT_*_DIR in the main CMakeLists.txt and PROJECT_*_DIR +in the subdirectories. +--- + CMakeLists.txt | 14 +++++++------- + examples/CMakeLists.txt | 4 ++-- + ftdi_eeprom/CMakeLists.txt | 2 +- + ftdipp/CMakeLists.txt | 2 +- + python/CMakeLists.txt | 2 +- + test/CMakeLists.txt | 2 +- + 6 files changed, 13 insertions(+), 13 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 7f72e0c..6284c8d 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -9,7 +9,7 @@ set(MINOR_VERSION 5) + set(PACKAGE libftdi1) + set(VERSION_STRING ${MAJOR_VERSION}.${MINOR_VERSION}) + set(VERSION ${VERSION_STRING}) +-set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) ++set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) + + # Support new if() IN_LIST operator + if(POLICY CMP0057) +@@ -117,7 +117,7 @@ if ( WIN32 ) + set ( CPACK_NSIS_MODIFY_PATH ON ) + endif () + +-set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_SOURCE_DIR}/LICENSE) ++set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE) + + set(CPACK_SOURCE_GENERATOR TGZ) + set(CPACK_SOURCE_IGNORE_FILES "\\\\.git;~$;build/") +@@ -132,8 +132,8 @@ endif () + set(ARCHIVE_NAME ${CMAKE_PROJECT_NAME}-${VERSION_STRING}) + add_custom_target(dist + COMMAND git archive --prefix=${ARCHIVE_NAME}/ HEAD +- | bzip2 > ${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}.tar.bz2 +- WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) ++ | bzip2 > ${PROJECT_BINARY_DIR}/${ARCHIVE_NAME}.tar.bz2 ++ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + + add_subdirectory(src) + add_subdirectory(packages) +@@ -176,9 +176,9 @@ if(${WIN32}) + set(libdir ${CMAKE_INSTALL_PREFIX}/bin) + endif(${WIN32}) + +-configure_file(${CMAKE_SOURCE_DIR}/libftdi1.pc.in ${CMAKE_BINARY_DIR}/libftdi1.pc @ONLY) +-configure_file(${CMAKE_SOURCE_DIR}/libftdipp1.pc.in ${CMAKE_BINARY_DIR}/libftdipp1.pc @ONLY) +-install(FILES ${CMAKE_BINARY_DIR}/libftdi1.pc ${CMAKE_BINARY_DIR}/libftdipp1.pc ++configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libftdi1.pc.in ${CMAKE_CURRENT_BINARY_DIR}/libftdi1.pc @ONLY) ++configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libftdipp1.pc.in ${CMAKE_CURRENT_BINARY_DIR}/libftdipp1.pc @ONLY) ++install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libftdi1.pc ${CMAKE_CURRENT_BINARY_DIR}/libftdipp1.pc + DESTINATION lib${LIB_SUFFIX}/pkgconfig) + + if (UNIX OR MINGW) +diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt +index 382cb33..9ec7bff 100644 +--- a/examples/CMakeLists.txt ++++ b/examples/CMakeLists.txt +@@ -37,7 +37,7 @@ endif(NOT MINGW) + + # libftdi++ examples + if( FTDIPP ) +- include_directories(BEFORE ${CMAKE_SOURCE_DIR}/ftdipp ++ include_directories(BEFORE ${PROJECT_SOURCE_DIR}/ftdipp + ${Boost_INCLUDE_DIRS} + ) + +@@ -49,4 +49,4 @@ if( FTDIPP ) + endif( FTDIPP ) + + # Source includes +-include_directories(BEFORE ${CMAKE_SOURCE_DIR}/src) ++include_directories(BEFORE ${PROJECT_SOURCE_DIR}/src) +diff --git a/ftdi_eeprom/CMakeLists.txt b/ftdi_eeprom/CMakeLists.txt +index 8737c4b..525421e 100644 +--- a/ftdi_eeprom/CMakeLists.txt ++++ b/ftdi_eeprom/CMakeLists.txt +@@ -27,7 +27,7 @@ set ( EEPROM_MAJOR_VERSION 0 ) + set ( EEPROM_MINOR_VERSION 17 ) + set ( EEPROM_VERSION_STRING ${EEPROM_MAJOR_VERSION}.${EEPROM_MINOR_VERSION} ) + +-include_directories ( BEFORE ${CMAKE_SOURCE_DIR}/src ) ++include_directories ( BEFORE ${PROJECT_SOURCE_DIR}/src ) + include_directories ( BEFORE ${CMAKE_CURRENT_BINARY_DIR} ) + + configure_file( +diff --git a/ftdipp/CMakeLists.txt b/ftdipp/CMakeLists.txt +index fa2711f..5e23a07 100644 +--- a/ftdipp/CMakeLists.txt ++++ b/ftdipp/CMakeLists.txt +@@ -5,7 +5,7 @@ set(cpp_headers ${CMAKE_CURRENT_SOURCE_DIR}/ftdi.hpp CACHE INTERNAL "List of cpp + # Includes + include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} +- ${CMAKE_SOURCE_DIR}/src ++ ${PROJECT_SOURCE_DIR}/src + ) + + include_directories(${Boost_INCLUDE_DIRS}) +diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt +index 6ab14cd..5e406ff 100644 +--- a/python/CMakeLists.txt ++++ b/python/CMakeLists.txt +@@ -18,7 +18,7 @@ find_package ( PythonInterp REQUIRED ) + find_package ( PythonLibs REQUIRED ) + + include ( UseSWIG ) +-include_directories ( BEFORE ${CMAKE_SOURCE_DIR}/src ) ++include_directories ( BEFORE ${PROJECT_SOURCE_DIR}/src ) + include_directories ( ${PYTHON_INCLUDE_DIRS} ) + link_directories ( ${CMAKE_CURRENT_BINARY_DIR}/../src ) + +diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt +index 392c910..c44c614 100644 +--- a/test/CMakeLists.txt ++++ b/test/CMakeLists.txt +@@ -2,7 +2,7 @@ find_package(Boost COMPONENTS unit_test_framework REQUIRED) + + enable_testing() + +-INCLUDE_DIRECTORIES(BEFORE ${CMAKE_SOURCE_DIR}/src ${Boost_INCLUDE_DIRS}) ++INCLUDE_DIRECTORIES(BEFORE ${PROJECT_SOURCE_DIR}/src ${Boost_INCLUDE_DIRS}) + + set(cpp_tests basic.cpp baudrate.cpp) + +-- +2.43.0 + +From 3c7141a77b6caa55375ad77239d8716c5f371f5d Mon Sep 17 00:00:00 2001 +From: Yegor Yefremov +Date: Thu, 12 Oct 2023 09:11:12 +0200 +Subject: [PATCH 39/42] CMake: fix multiarch support + +Let CMake determine the exact library destination path. + +Patch taken from the Debian package: +https://sources.debian.org/src/libftdi1/1.5-6/debian/patches/01-cmake-multiarch.diff/ +--- + CMakeLists.txt | 6 +++--- + ftdipp/CMakeLists.txt | 6 +++--- + src/CMakeLists.txt | 6 +++--- + 3 files changed, 9 insertions(+), 9 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 6284c8d..985e658 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -170,7 +170,7 @@ set(exec_prefix ${CMAKE_INSTALL_PREFIX}/bin) + set(includedir ${CMAKE_INSTALL_PREFIX}/include/${PROJECT_NAME}) + + if(${UNIX}) +- set(libdir ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}) ++ set(libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}) + endif(${UNIX}) + if(${WIN32}) + set(libdir ${CMAKE_INSTALL_PREFIX}/bin) +@@ -179,7 +179,7 @@ endif(${WIN32}) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libftdi1.pc.in ${CMAKE_CURRENT_BINARY_DIR}/libftdi1.pc @ONLY) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libftdipp1.pc.in ${CMAKE_CURRENT_BINARY_DIR}/libftdipp1.pc @ONLY) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libftdi1.pc ${CMAKE_CURRENT_BINARY_DIR}/libftdipp1.pc +- DESTINATION lib${LIB_SUFFIX}/pkgconfig) ++ DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) + + if (UNIX OR MINGW) + configure_file ( libftdi1-config.in ${CMAKE_CURRENT_BINARY_DIR}/libftdi1-config @ONLY ) +@@ -189,7 +189,7 @@ endif () + + # config script install path + if ( NOT DEFINED LIBFTDI_CMAKE_CONFIG_DIR ) +- set ( LIBFTDI_CMAKE_CONFIG_DIR lib${LIB_SUFFIX}/cmake/libftdi1 ) ++ set ( LIBFTDI_CMAKE_CONFIG_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/libftdi1 ) + endif () + + set ( LIBFTDI_INCLUDE_DIR ${includedir} ) +diff --git a/ftdipp/CMakeLists.txt b/ftdipp/CMakeLists.txt +index 5e23a07..360a831 100644 +--- a/ftdipp/CMakeLists.txt ++++ b/ftdipp/CMakeLists.txt +@@ -24,8 +24,8 @@ target_link_libraries(ftdipp1 ftdi1 ${LIBUSB_LIBRARIES} ${BOOST_LIBRARIES}) + + install ( TARGETS ftdipp1 + RUNTIME DESTINATION bin +- LIBRARY DESTINATION lib${LIB_SUFFIX} +- ARCHIVE DESTINATION lib${LIB_SUFFIX} ++ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ++ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + ) + + # Static library +@@ -35,7 +35,7 @@ if ( STATICLIBS ) + set_target_properties(ftdipp1-static PROPERTIES CLEAN_DIRECT_OUTPUT 1) + + install ( TARGETS ftdipp1-static +- ARCHIVE DESTINATION lib${LIB_SUFFIX} ++ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + COMPONENT staticlibs + ) + endif () +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index cf630ba..e145af1 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -34,8 +34,8 @@ target_link_libraries(ftdi1 ${LIBUSB_LIBRARIES}) + + install ( TARGETS ftdi1 + RUNTIME DESTINATION bin +- LIBRARY DESTINATION lib${LIB_SUFFIX} +- ARCHIVE DESTINATION lib${LIB_SUFFIX} ++ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ++ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + ) + + if ( STATICLIBS ) +@@ -44,7 +44,7 @@ if ( STATICLIBS ) + set_target_properties(ftdi1-static PROPERTIES OUTPUT_NAME "ftdi1") + set_target_properties(ftdi1-static PROPERTIES CLEAN_DIRECT_OUTPUT 1) + install ( TARGETS ftdi1-static +- ARCHIVE DESTINATION lib${LIB_SUFFIX} ++ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + COMPONENT staticlibs + ) + endif () +-- +2.43.0 + +From ed8aad3c13e0952476c4a70761246938cea9c81e Mon Sep 17 00:00:00 2001 +From: Yegor Yefremov +Date: Thu, 12 Oct 2023 09:11:13 +0200 +Subject: [PATCH 40/42] CMake: use ${PC_LIBUSB_LIBRARIES} instead of a library + name + +Patch taken from the Debian package: +https://sources.debian.org/src/libftdi1/1.5-6/debian/patches/02-kfreebsd.diff/ +--- + cmake/FindLibUSB.cmake | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/cmake/FindLibUSB.cmake b/cmake/FindLibUSB.cmake +index 766fc82..8bb3b11 100644 +--- a/cmake/FindLibUSB.cmake ++++ b/cmake/FindLibUSB.cmake +@@ -25,7 +25,7 @@ else (LIBUSB_INCLUDE_DIR AND LIBUSB_LIBRARIES) + PATH_SUFFIXES libusb-1.0 + PATHS ${PC_LIBUSB_INCLUDEDIR} ${PC_LIBUSB_INCLUDE_DIRS}) + +- find_library(LIBUSB_LIBRARIES NAMES usb-1.0 ++ find_library(LIBUSB_LIBRARIES NAMES ${PC_LIBUSB_LIBRARIES} + PATHS ${PC_LIBUSB_LIBDIR} ${PC_LIBUSB_LIBRARY_DIRS}) + + include(FindPackageHandleStandardArgs) +-- +2.43.0 + +From abd19b721f7e9b4d514ed319ece173ebc7b1ea72 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Dan=20Hor=C3=A1k?= +Date: Mon, 19 Dec 2022 17:40:43 +0100 +Subject: [PATCH 41/42] python: move from distutils to sysconfig + +The distutils module was deprecated in Python 3.10, and will be removed +in 3.12 [1], thus switch to the sysconfig module instead. + +[1] https://peps.python.org/pep-0632/ +--- + python/CMakeLists.txt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt +index 5e406ff..9358419 100644 +--- a/python/CMakeLists.txt ++++ b/python/CMakeLists.txt +@@ -42,7 +42,7 @@ endif () + + set_target_properties ( ${SWIG_MODULE_ftdi1_REAL_NAME} PROPERTIES NO_SONAME ON ) + +-execute_process ( COMMAND ${PYTHON_EXECUTABLE} -c "from distutils import sysconfig; print( sysconfig.get_python_lib( plat_specific=True, prefix='${CMAKE_INSTALL_PREFIX}' ) )" ++execute_process ( COMMAND ${PYTHON_EXECUTABLE} -c "import sysconfig; print( sysconfig.get_path( 'platlib', vars={'platbase': '${CMAKE_INSTALL_PREFIX}'} ) )" + OUTPUT_VARIABLE _ABS_PYTHON_MODULE_PATH + OUTPUT_STRIP_TRAILING_WHITESPACE ) + +-- +2.43.0 + +From de9f01ece34d2fe6e842e0250a38f4b16eda2429 Mon Sep 17 00:00:00 2001 +From: Yegor Yefremov +Date: Tue, 12 Dec 2023 14:20:36 +0100 +Subject: [PATCH 42/42] CMake: bump the minimal required version to 3.5 + +Older CMake versions are treated as deprecated. +--- + CMakeLists.txt | 2 +- + examples/cmake_example/CMakeLists.txt | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 985e658..2ce1ad4 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -1,4 +1,4 @@ +-cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR) ++cmake_minimum_required(VERSION 3.5 FATAL_ERROR) + + message(STATUS "CMake version: ${CMAKE_VERSION}") + +diff --git a/examples/cmake_example/CMakeLists.txt b/examples/cmake_example/CMakeLists.txt +index 36002df..7d60693 100644 +--- a/examples/cmake_example/CMakeLists.txt ++++ b/examples/cmake_example/CMakeLists.txt +@@ -1,4 +1,4 @@ +-cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR) ++cmake_minimum_required(VERSION 3.5 FATAL_ERROR) + + project ( example C ) + +-- +2.43.0 + diff --git a/packages/devel/libirman/package.mk b/packages/devel/libirman/package.mk new file mode 100644 index 0000000000..316e553509 --- /dev/null +++ b/packages/devel/libirman/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) 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_configure_target() { + libtool_remove_rpath libtool +} + +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 0000000000..5005724349 --- /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 0000000000..a38f87c582 --- /dev/null +++ b/packages/devel/libplist/package.mk @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="libplist" +PKG_VERSION="2.7.0" +PKG_SHA256="7ac42301e896b1ebe3c654634780c82baa7cb70df8554e683ff89f7c2643eb8b" +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_configure_target() { + libtool_remove_rpath libtool +} + +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 0000000000..c3d5f9359b --- /dev/null +++ b/packages/devel/libpthread-stubs/package.mk @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="libpthread-stubs" +PKG_VERSION="0.5" +PKG_SHA256="593196cc746173d1e25cb54a93a87fd749952df68699aab7e02c085530e87747" +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." +PKG_BUILD_FLAGS="-cfg-libs" diff --git a/packages/devel/libtool/package.mk b/packages/devel/libtool/package.mk new file mode 100644 index 0000000000..45e92110d1 --- /dev/null +++ b/packages/devel/libtool/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="libtool" +PKG_VERSION="2.5.4" +PKG_SHA256="f81f5860666b0bc7d84baddefa60d1cb9fa6fceb2398cc3baca6afaa60266675" +PKG_LICENSE="GPL" +PKG_SITE="https://www.gnu.org/software/libtool/" +PKG_URL="https://mirrors.kernel.org/gnu/libtool/${PKG_NAME}-${PKG_VERSION}.tar.xz" +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_unpack() { + chmod u+w ${PKG_BUILD}/build-aux/ltmain.sh +} + +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 0000000000..ea81981f1a --- /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 +@@ -8668,7 +8668,7 @@ + fi + else + # We cannot seem to hardcode it, guess we'll fake it. +- add_dir=-L$lt_sysroot$libdir ++ #add_dir=-L$lt_sysroot$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-03-remove-help2man-dependency.patch b/packages/devel/libtool/patches/libtool-03-remove-help2man-dependency.patch new file mode 100644 index 0000000000..401722966f --- /dev/null +++ b/packages/devel/libtool/patches/libtool-03-remove-help2man-dependency.patch @@ -0,0 +1,27 @@ +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 +@@ -408,23 +408,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) -n 'Provide generalized library-building support services' --help-option=--help-all libtool +-$(libtoolize_1): $(libtoolize_in) +- $(AM_V_GEN)$(update_mans) -n 'Prepare a package to use libtool' libtoolize +- +- +- + ## ------------- ## + ## Installation. ## + ## ------------- ## diff --git a/packages/devel/m4/package.mk b/packages/devel/m4/package.mk new file mode 100644 index 0000000000..a6262fc1ea --- /dev/null +++ b/packages/devel/m4/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="m4" +PKG_VERSION="1.4.20" +PKG_SHA256="ac6989ee5d2aed81739780630cc2ce097e2a6546feb96a4a54db37d46a1452e4" +PKG_LICENSE="GPL" +PKG_SITE="http://www.gnu.org/software/m4/" +PKG_URL="https://mirrors.kernel.org/gnu/m4/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_HOST="ccache:host" +PKG_LONGDESC="The m4 macro processor." +PKG_BUILD_FLAGS="-cfg-libs:host" + +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 0000000000..43404d9e9f --- /dev/null +++ b/packages/devel/make/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="make" +PKG_VERSION="4.4.1" +PKG_SHA256="dd16fb1d67bfab79a72f5e8390735c49e3e8e70b4945a15ab1f81ddb78658fb3" +PKG_LICENSE="GPLv3" +PKG_SITE="https://www.gnu.org/software/make/" +PKG_URL="https://mirrors.kernel.org/gnu/make/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="" +PKG_LONGDESC="Utility to maintain groups of programs." +PKG_BUILD_FLAGS="+local-cc -cfg-libs:host" + +post_makeinstall_host() { + ln -sf make ${TOOLCHAIN}/bin/gmake +} diff --git a/packages/devel/make/patches/make-02-fix-large-command-line-on-POSIX-systems.patch b/packages/devel/make/patches/make-02-fix-large-command-line-on-POSIX-systems.patch new file mode 100644 index 0000000000..12ac8b767a --- /dev/null +++ b/packages/devel/make/patches/make-02-fix-large-command-line-on-POSIX-systems.patch @@ -0,0 +1,170 @@ +From e249c43741779ae7dd6834f6840384257d4c3dd8 Mon Sep 17 00:00:00 2001 +From: Mike Crowe +Date: Fri, 6 Nov 2020 15:22:37 +0000 +Subject: [PATCH] [SV 45763] Fix large command line on POSIX systems + +When presented with a very long command line (as is common when linking +a large number of files with absolute paths in a deep subdirectory), +make fails to execute the command as it doesn't split the command line +to fit within the limits. + +This is based on a fix for Debian bug 688601[1] by Adam Conrad applied +by Manoj Srivastava originally applied for Debian make-dfsg 4.0-5 in +2014 but dropped in 2018 (it seems under the incorrect assumption that +it had been accepted upstream.) + +I've tweaked Adam's original patch so that it compiles successfully with +-Werror on top of current master. This required: + +* moving the eval_line declaration to the top of the block, so I moved + the macros too +* using a const variable when iterating over the shell +* adding a cast to avoid a signed/unsigned mismatch. + +As suggested in the Savannah bug report[2], I've added a test case that +fails without the rest of the patch. I'm not sure what the consequences +of running the test on non-POSIX targets would be and whether it needs +marking as an expected failure. + +* src/job.c (construct_command_argv_internal): support running commands +longer than MAX_ARG_STRLEN +* tests/scripts/features/long_command_line: add test for such a command +* configure.ac: check for now-required sys/user.h and linux/binfmts.h +headers + +[1] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=688601 +[2] https://savannah.gnu.org/bugs/?45763#comment2 +--- + src/job.c | 52 +++++++++++++++++++++++- + tests/scripts/features/long_command_line | 30 ++++++++++++++ + 2 files changed, 81 insertions(+), 1 deletions(-) + create mode 100644 tests/scripts/features/long_command_line + +diff --git a/src/job.c b/src/job.c +index 3bcec38..734c591 100644 +--- a/src/job.c ++++ b/src/job.c +@@ -26,6 +26,12 @@ this program. If not, see . */ + #include "variable.h" + #include "os.h" + ++#include ++#include ++#ifndef PAGE_SIZE ++# define PAGE_SIZE (sysconf(_SC_PAGESIZE)) ++#endif ++ + /* Default shell to use. */ + #ifdef WINDOWS32 + # ifdef HAVE_STRINGS_H +@@ -3228,6 +3236,15 @@ construct_command_argv_internal (char *line, char **restp, const char *shell, + size_t sflags_len = shellflags ? strlen (shellflags) : 0; + #ifdef WINDOWS32 + char *command_ptr = NULL; /* used for batch_mode_shell mode */ ++#endif ++ char *args_ptr; ++#ifdef MAX_ARG_STRLEN ++ static char eval_line[] = "eval\\ \\\"set\\ x\\;\\ shift\\;\\ "; ++#define ARG_NUMBER_DIGITS 5 ++#define EVAL_LEN (sizeof(eval_line)-1 + shell_len + 4 \ ++ + (7 + ARG_NUMBER_DIGITS) * 2 * line_len / (MAX_ARG_STRLEN - 2)) ++#else ++#define EVAL_LEN 0 + #endif + + # ifdef __EMX__ /* is this necessary? */ +@@ -3395,7 +3412,7 @@ construct_command_argv_internal (char *line, char **restp, const char *shell, + } + + new_line = xmalloc ((shell_len*2) + 1 + sflags_len + 1 +- + (line_len*2) + 1); ++ + (line_len*2) + 1 + EVAL_LEN); + ap = new_line; + /* Copy SHELL, escaping any characters special to the shell. If + we don't escape them, construct_command_argv_internal will +@@ -3415,6 +3432,31 @@ construct_command_argv_internal (char *line, char **restp, const char *shell, + #ifdef WINDOWS32 + command_ptr = ap; + #endif ++ ++#if !defined (WINDOWS32) && defined (MAX_ARG_STRLEN) ++ if (unixy_shell && line_len > MAX_ARG_STRLEN) ++ { ++ const char *q; ++ unsigned j; ++ memcpy (ap, eval_line, sizeof (eval_line) - 1); ++ ap += sizeof (eval_line) - 1; ++ for (j = 1; j <= 2 * line_len / (MAX_ARG_STRLEN - 2); j++) ++ ap += sprintf (ap, "\\$\\{%u\\}", j); ++ *ap++ = '\\'; ++ *ap++ = '"'; ++ *ap++ = ' '; ++ /* Copy only the first word of SHELL to $0. */ ++ for (q = shell; *q != '\0'; ++q) ++ { ++ if (isspace ((unsigned char)*q)) ++ break; ++ *ap++ = *q; ++ } ++ *ap++ = ' '; ++ } ++#endif ++ args_ptr = ap; ++ + for (p = line; *p != '\0'; ++p) + { + if (restp != NULL && *p == '\n') +@@ -3462,6 +3504,14 @@ construct_command_argv_internal (char *line, char **restp, const char *shell, + } + #endif + *ap++ = *p; ++#if !defined (WINDOWS32) && defined (MAX_ARG_STRLEN) ++ if (unixy_shell && line_len > MAX_ARG_STRLEN ++ && (ap - args_ptr > (long)(MAX_ARG_STRLEN - 2))) ++ { ++ *ap++ = ' '; ++ args_ptr = ap; ++ } ++#endif + } + if (ap == new_line + shell_len + sflags_len + 2) + { +diff --git a/tests/scripts/features/long_command_line b/tests/scripts/features/long_command_line +new file mode 100644 +index 0000000..3899ac8 +--- /dev/null ++++ b/tests/scripts/features/long_command_line +@@ -0,0 +1,30 @@ ++# -*-perl-*- ++$description = "Test long command line."; ++ ++$details = ""; ++ ++# Variable names containing UTF8 characters ++run_make_test(q! ++# 49 characters ++ARGS:=one two three four five six seven eight niner ten ++# 49*4+3 = 199 characters ++ARGS:=$(ARGS) $(ARGS) $(ARGS) $(ARGS) ++# 199*4+3 = 799 characters ++ARGS:=$(ARGS) $(ARGS) $(ARGS) $(ARGS) ++# 799*4+3 = 3199 characters ++ARGS:=$(ARGS) $(ARGS) $(ARGS) $(ARGS) ++# 3199*4+3 = 12799 characters ++ARGS:=$(ARGS) $(ARGS) $(ARGS) $(ARGS) ++# 12799*4+3 = 51199 characters ++ARGS:=$(ARGS) $(ARGS) $(ARGS) $(ARGS) ++# 51199*4+3 = 204799 characters ++ARGS:=$(ARGS) $(ARGS) $(ARGS) $(ARGS) ++# 24799*2+1 = 409599 characters ++#ARGS:=$(ARGS) $(ARGS) ++ ++test: ++ @: $(ARGS) ++!, ++ '', ""); ++ ++1; +-- +2.20.1 + diff --git a/packages/devel/mimalloc/package.mk b/packages/devel/mimalloc/package.mk new file mode 100644 index 0000000000..a6cb75a616 --- /dev/null +++ b/packages/devel/mimalloc/package.mk @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2022-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="mimalloc" +PKG_VERSION="3.1.5" +PKG_SHA256="1c6949032069d5ebea438ec5cedd602d06f40a92ddf0f0d9dcff0993e5f6635c" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/microsoft/mimalloc" +PKG_URL="https://github.com/microsoft/mimalloc/archive/refs/tags/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="cmake:host ninja:host" +PKG_LONGDESC="mimalloc (pronounced "me-malloc") is a general purpose allocator with excellent performance characteristics" + +PKG_CMAKE_OPTS_HOST="-DMI_SECURE=OFF \ + -DMI_DEBUG_FULL=OFF \ + -DMI_OVERRIDE=ON \ + -DMI_XMALLOC=OFF \ + -DMI_SHOW_ERRORS=OFF \ + -DMI_USE_CXX=OFF \ + -DMI_SEE_ASM=OFF \ + -DMI_LOCAL_DYNAMIC_TLS=OFF \ + -DMI_BUILD_SHARED=ON \ + -DMI_BUILD_STATIC=OFF \ + -DMI_BUILD_OBJECT=OFF \ + -DMI_BUILD_TESTS=OFF \ + -DMI_DEBUG_TSAN=OFF \ + -DMI_DEBUG_UBSAN=OFF \ + -DMI_SKIP_COLLECT_ON_EXIT=OFF" diff --git a/packages/devel/mold/package.mk b/packages/devel/mold/package.mk new file mode 100644 index 0000000000..16d98e58dc --- /dev/null +++ b/packages/devel/mold/package.mk @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2022-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="mold" +PKG_VERSION="2.40.1" +PKG_SHA256="d1ce09a69941f8158604c3edcc96c7178231e7dba2da66b20f5ef6e112c443b7" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/rui314/mold" +PKG_URL="https://github.com/rui314/mold/archive/refs/tags/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="cmake:host zlib:host zstd:host openssl:host tbb:host mimalloc:host" +PKG_LONGDESC="mold is a faster drop-in replacement for existing Unix linkers" + +PKG_CMAKE_OPTS_HOST="-DCMAKE_INSTALL_LIBDIR="${TOOLCHAIN}/${TARGET_NAME}/lib" + -DCMAKE_INSTALL_BINDIR="${TARGET_NAME}/bin" \ + -DCMAKE_INSTALL_LIBEXECDIR="${TARGET_NAME}" \ + -DMOLD_LTO=ON \ + -DMOLD_MOSTLY_STATIC=ON \ + -DMOLD_USE_SYSTEM_MIMALLOC=ON \ + -DMOLD_USE_SYSTEM_TBB=ON" + +post_makeinstall_host() { + ln -sf ${TOOLCHAIN}/${TARGET_NAME}/bin/mold ${TARGET_PREFIX}ld.mold +} diff --git a/packages/devel/mpc/package.mk b/packages/devel/mpc/package.mk new file mode 100644 index 0000000000..b9a078dcdd --- /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.3.1" +PKG_SHA256="ab642492f5cf882b74aa0cb730cd410a81edcdbec895183ce930e706c1c759b8" +PKG_LICENSE="LGPL" +PKG_SITE="https://www.multiprecision.org" +PKG_URL="https://mirrors.kernel.org/gnu/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 0000000000..2aad45c302 --- /dev/null +++ b/packages/devel/mpfr/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="mpfr" +PKG_VERSION="4.2.2" +PKG_SHA256="b67ba0383ef7e8a8563734e2e889ef5ec3c3b898a01d00fa0a6869ad81c6ce01" +PKG_LICENSE="LGPL" +PKG_SITE="http://www.mpfr.org/" +PKG_URL="https://mirrors.kernel.org/gnu/mpfr/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_HOST="ccache:host gmp:host" +PKG_DEPENDS_TARGET="gmp" +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" + +PKG_CONFIGURE_OPTS_TARGET="--target=${TARGET_NAME} \ + --enable-static --disable-shared" diff --git a/packages/devel/ncurses/package.mk b/packages/devel/ncurses/package.mk new file mode 100644 index 0000000000..0317d62d1c --- /dev/null +++ b/packages/devel/ncurses/package.mk @@ -0,0 +1,92 @@ +# 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.5-20250517" +PKG_SHA256="13e78548b31adef93e3b9735bf728fac5a84969873333c7833614db61891353e" +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="autotools:host gcc:host zlib ncurses:host" +PKG_LONGDESC="A library is a free software emulation of curses in System V Release 4.0, and more." +PKG_BUILD_FLAGS="+pic" + +PKG_CONFIGURE_OPTS_TARGET="--without-ada \ + --without-cxx \ + --without-cxx-binding \ + --disable-db-install \ + --without-manpages \ + --without-progs \ + --without-tests \ + --without-shared \ + --with-normal \ + --without-debug \ + --without-profile \ + --without-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 \ + --enable-hashmap \ + --disable-safe-sprintf \ + --disable-scroll-hints \ + --enable-widec \ + --disable-echo \ + --disable-warnings \ + --disable-home-terminfo \ + --disable-assertions \ + --enable-leaks \ + --enable-sigwinch \ + --cache-file=config.cache" + +PKG_CONFIGURE_OPTS_HOST="--enable-termcap \ + --with-termlib \ + --with-shared \ + --enable-pc-files \ + --without-manpages" + +pre_configure_target() { + cat >config.cache < +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/pkg-config/patches/0002-Do-not-use-bool-as-a-field-name.patch b/packages/devel/pkg-config/patches/0002-Do-not-use-bool-as-a-field-name.patch new file mode 100644 index 0000000000..bcb7e94d69 --- /dev/null +++ b/packages/devel/pkg-config/patches/0002-Do-not-use-bool-as-a-field-name.patch @@ -0,0 +1,36 @@ +From b3b26a7e125e5e4f5b69975cc17eb6d33198ebaa Mon Sep 17 00:00:00 2001 +From: Emmanuele Bassi +Date: Thu, 11 Apr 2024 14:40:21 +0100 +Subject: [PATCH] Do not use bool as a field name + +C99 aliases `bool` to `_Bool`, and C23 introduces `bool` as a reserved +keyword. Let's avoid using `bool` as a field name. + +Upstream-Status: Backport [Backport from glib to bunlded version in pkg-config https://github.com/GNOME/glib/commit/9e320e1c43a4770ed1532248fe5416eb0c618120] +Signed-off-by: Martin Jansa +--- + glib/glib/goption.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/glib/glib/goption.c b/glib/glib/goption.c +index 0a22f6f..f439fd4 100644 +--- a/glib/glib/goption.c ++++ b/glib/glib/goption.c +@@ -166,7 +166,7 @@ typedef struct + gpointer arg_data; + union + { +- gboolean bool; ++ gboolean boolean; + gint integer; + gchar *str; + gchar **array; +@@ -1600,7 +1600,7 @@ free_changes_list (GOptionContext *context, + switch (change->arg_type) + { + case G_OPTION_ARG_NONE: +- *(gboolean *)change->arg_data = change->prev.bool; ++ *(gboolean *)change->arg_data = change->prev.boolean; + break; + case G_OPTION_ARG_INT: + *(gint *)change->arg_data = change->prev.integer; diff --git a/packages/devel/popt/package.mk b/packages/devel/popt/package.mk new file mode 100644 index 0000000000..96870fcf77 --- /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.19" +PKG_SHA256="c25a4838fc8e4c1c8aacb8bd620edb3084a3d63bf8987fdad3ca2758c63240f9" +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="cmake:host gcc:host" +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 0000000000..bfaf3a9b7e --- /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 0000000000..51434ff52e --- /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/rapidjson/patches/rapidjson-0002-Removed-non-compiling-assignment-operator.-Fixed-718.patch b/packages/devel/rapidjson/patches/rapidjson-0002-Removed-non-compiling-assignment-operator.-Fixed-718.patch new file mode 100644 index 0000000000..ab02199baf --- /dev/null +++ b/packages/devel/rapidjson/patches/rapidjson-0002-Removed-non-compiling-assignment-operator.-Fixed-718.patch @@ -0,0 +1,25 @@ +From 3b2441b87f99ab65f37b141a7b548ebadb607b96 Mon Sep 17 00:00:00 2001 +From: Janusz Chorko +Date: Fri, 26 Aug 2016 21:17:38 +0200 +Subject: [PATCH] Removed non-compiling assignment operator. Fixed #718 + +--- + include/rapidjson/document.h | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h +index e3e20dfb..b0f1f70b 100644 +--- a/include/rapidjson/document.h ++++ b/include/rapidjson/document.h +@@ -316,8 +316,6 @@ struct GenericStringRef { + + GenericStringRef(const GenericStringRef& rhs) : s(rhs.s), length(rhs.length) {} + +- GenericStringRef& operator=(const GenericStringRef& rhs) { s = rhs.s; length = rhs.length; } +- + //! implicit conversion to plain CharType pointer + operator const Ch *() const { return s; } + +-- +2.43.0 + diff --git a/packages/devel/rapidjson/patches/rapidjson-0003-Explicitly-disable-copy-assignment-operator.patch b/packages/devel/rapidjson/patches/rapidjson-0003-Explicitly-disable-copy-assignment-operator.patch new file mode 100644 index 0000000000..4a3670d376 --- /dev/null +++ b/packages/devel/rapidjson/patches/rapidjson-0003-Explicitly-disable-copy-assignment-operator.patch @@ -0,0 +1,25 @@ +From 862c39be371278a45a88d4d1d75164be57bb7e2d Mon Sep 17 00:00:00 2001 +From: Janusz Chorko +Date: Fri, 26 Aug 2016 21:26:50 +0200 +Subject: [PATCH] Explicitly disable copy assignment operator + +--- + include/rapidjson/document.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h +index b0f1f70b..19f5a6a5 100644 +--- a/include/rapidjson/document.h ++++ b/include/rapidjson/document.h +@@ -326,6 +326,8 @@ private: + //! Disallow construction from non-const array + template + GenericStringRef(CharType (&str)[N]) /* = delete */; ++ //! Copy assignment operator not permitted - immutable type ++ GenericStringRef& operator=(const GenericStringRef& rhs) /* = delete */; + }; + + //! Mark a character pointer as constant string +-- +2.43.0 + diff --git a/packages/devel/rapidjson/patches/rapidjson-0004-build-with-cmake-4.0.0.patch b/packages/devel/rapidjson/patches/rapidjson-0004-build-with-cmake-4.0.0.patch new file mode 100644 index 0000000000..7be5078c0c --- /dev/null +++ b/packages/devel/rapidjson/patches/rapidjson-0004-build-with-cmake-4.0.0.patch @@ -0,0 +1,26 @@ +From ebd87cb468fb4cb060b37e579718c4a4125416c1 Mon Sep 17 00:00:00 2001 +From: Christian Fersch +Date: Mon, 15 Jan 2024 07:44:16 +0100 +Subject: [PATCH] Increase CMake minimum version to 3.5 (fixes #2159) + +--- + CMakeLists.txt | 16 ++-------------- + 1 file changed, 2 insertions(+), 14 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 1b3a79de9..c02301c98 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -1,11 +1,4 @@ +-CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +-if(POLICY CMP0025) +- # detect Apple's Clang +- cmake_policy(SET CMP0025 NEW) +-endif() +-if(POLICY CMP0054) +- cmake_policy(SET CMP0054 NEW) +-endif() ++CMAKE_MINIMUM_REQUIRED(VERSION 3.5) + + SET(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules) + diff --git a/packages/devel/readline/package.mk b/packages/devel/readline/package.mk new file mode 100644 index 0000000000..6bf2b04d9c --- /dev/null +++ b/packages/devel/readline/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="readline" +PKG_VERSION="8.3" +PKG_SHA256="fe5383204467828cd495ee8d1d3c037a7eba1389c22bc6a041f627976f9061cc" +PKG_LICENSE="MIT" +PKG_SITE="http://www.gnu.org/software/readline/" +PKG_URL="https://mirrors.kernel.org/gnu/readline/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="autotools:host gcc:host 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() { + # fix static library + sed -i 's/-lreadline/-lreadline -lncursesw/' ${SYSROOT_PREFIX}/usr/lib/pkgconfig/readline.pc + + rm -rf ${INSTALL}/usr/share/readline +} diff --git a/packages/devel/shared-mime-info/package.mk b/packages/devel/shared-mime-info/package.mk new file mode 100644 index 0000000000..436acb979a --- /dev/null +++ b/packages/devel/shared-mime-info/package.mk @@ -0,0 +1,30 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="shared-mime-info" +PKG_VERSION="2.4" +PKG_SHA256="32dc32ae39ff1c1bf8434dd3b36770b48538a1772bc0298509d034f057005992" +PKG_LICENSE="GPL-2.0-only" +PKG_SITE="https://freedesktop.org/wiki/Software/shared-mime-info/" +PKG_URL="https://gitlab.freedesktop.org/xdg/${PKG_NAME}/-/archive/${PKG_VERSION}/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_HOST="toolchain:host glib:host libxml2:host gettext:host itstool:host" +PKG_DEPENDS_TARGET="toolchain glib libxml2 gettext shared-mime-info:host" +PKG_LONGDESC="The shared-mime-info package contains the core database of common types." +PKG_BUILD_FLAGS="-parallel" + +configure_package() { + # Sway Support + if [ ! "${WINDOWMANAGER}" = "sway" ]; then + PKG_BUILD_FLAGS+=" -sysroot" + fi +} + +PKG_MESON_OPTS_HOST="-Dupdate-mimedb=false" +PKG_MESON_OPTS_TARGET="-Dupdate-mimedb=false" + +post_makeinstall_target() { + # Create /usr/share/mime/mime.cache + if [ "${WINDOWMANAGER}" = "sway" ]; then + ${TOOLCHAIN}/bin/update-mime-database ${INSTALL}/usr/share/mime + fi +} diff --git a/packages/devel/shared-mime-info/patches/shared-mime-info-219-fix-build-with-libxml2-2-12-0.patch b/packages/devel/shared-mime-info/patches/shared-mime-info-219-fix-build-with-libxml2-2-12-0.patch new file mode 100644 index 0000000000..530805e810 --- /dev/null +++ b/packages/devel/shared-mime-info/patches/shared-mime-info-219-fix-build-with-libxml2-2-12-0.patch @@ -0,0 +1,23 @@ +From c918fe77e255150938e83a6aec259f153d303573 Mon Sep 17 00:00:00 2001 +From: David Faure +Date: Sun, 19 Nov 2023 11:18:11 +0100 +Subject: [PATCH] Fix build with libxml2-2.12.0 and clang-17 + +Fixes #219 +--- + src/test-subclassing.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/test-subclassing.c b/src/test-subclassing.c +index dd099e44..0758164f 100644 +--- a/src/test-subclassing.c ++++ b/src/test-subclassing.c +@@ -1,4 +1,5 @@ + #include ++#include + #include + #include + +-- +GitLab + diff --git a/packages/devel/slang/package.mk b/packages/devel/slang/package.mk new file mode 100644 index 0000000000..31cb371a5e --- /dev/null +++ b/packages/devel/slang/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) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="slang" +PKG_VERSION="2.3.3" +PKG_SHA256="f9145054ae131973c61208ea82486d5dd10e3c5cdad23b7c4a0617743c8f5a18" +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 -cfg-libs" + +PKG_CONFIGURE_OPTS_TARGET="--without-pcre \ + --without-onig" + +pre_configure_target() { + # slang fails to build in subdirs + cd ${PKG_BUILD} + sed -i 's|RPATH=".*"|RPATH=""|' configure + 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 0000000000..d4b9762ec7 --- /dev/null +++ b/packages/devel/spdlog/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="spdlog" +PKG_VERSION="1.15.3" +PKG_SHA256="15a04e69c222eb6c01094b5c7ff8a249b36bb22788d72519646fb85feb267e67" +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_CMAKE_OPTS_TARGET="-DCMAKE_CXX_STANDARD=14 \ + -DCMAKE_CXX_EXTENSIONS:BOOL=OFF \ + -DSPDLOG_BUILD_SHARED=ON \ + -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 0000000000..b71c978da4 --- /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.3.1" +PKG_SHA256="44fc829f70f1e17d635a2b4d69acab38896699ecc24aa023e516e0eabbec61b8" +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_TOOLCHAIN="configure" + +PKG_CONFIGURE_OPTS_HOST="--program-suffix=4.0 \ + --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/talloc/config/talloc-cache.txt b/packages/devel/talloc/config/talloc-cache.txt new file mode 100644 index 0000000000..d4deb25508 --- /dev/null +++ b/packages/devel/talloc/config/talloc-cache.txt @@ -0,0 +1,48 @@ +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 +Checking for gnutls fips mode support: NO +Checking for readlink breakage: NO +Checking whether fcntl supports setting/getting hints: OK diff --git a/packages/devel/talloc/package.mk b/packages/devel/talloc/package.mk new file mode 100644 index 0000000000..e7f50e436d --- /dev/null +++ b/packages/devel/talloc/package.mk @@ -0,0 +1,63 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2024-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="talloc" +PKG_VERSION="2.4.3" +PKG_SHA256="dc46c40b9f46bb34dd97fe41f548b0e8b247b77a918576733c528e83abd854dd" +PKG_LICENSE="LGPL-3.0-or-later" +PKG_SITE="https://talloc.samba.org/" +PKG_URL="https://www.samba.org/ftp/talloc/talloc-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="talloc is a hierarchical, reference counted memory pool system with destructors" + +configure_package() { + PKG_WAF_VERBOSE="-v" + + PKG_CONFIGURE_OPTS="--prefix=/usr \ + --bindir=/usr/bin \ + --sbindir=/usr/sbin \ + --sysconfdir=/etc \ + --libdir=/usr/lib \ + --libexecdir=/usr/lib \ + --localstatedir=/var \ + --cross-compile \ + --cross-answers=${PKG_BUILD}/cache.txt \ + --hostcc=gcc \ + --disable-python \ + --disable-rpath \ + --disable-rpath-install \ + --disable-rpath-private-install" +} + +pre_configure_target() { + # talloc uses its own build directory + cd ${PKG_BUILD} + rm -rf .${TARGET_NAME} + + # 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/talloc-cache.txt ${PKG_BUILD}/cache.txt + echo "Checking uname machine type: \"${TARGET_ARCH}\"" >>${PKG_BUILD}/cache.txt + + PYTHON_CONFIG="${SYSROOT_PREFIX}/usr/bin/python3-config" \ + python_LDFLAGS="" python_LIBDIR="" \ + PYTHON=${TOOLCHAIN}/bin/python3 ./configure ${PKG_CONFIGURE_OPTS} +} + +make_target() { + make ${PKG_SAMBA_TARGET} -j${CONCURRENCY_MAKE_LEVEL} +} + +makeinstall_target() { + PYTHONHASHSEED=1 WAF_MAKE=1 ./buildtools/bin/waf install ${PKG_WAF_VERBOSE} --destdir=${SYSROOT_PREFIX} -j${CONCURRENCY_MAKE_LEVEL} +} + +post_makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib + cp -PR ${PKG_BUILD}/bin/default/libtalloc.so* ${INSTALL}/usr/lib +} diff --git a/packages/devel/tbb/package.mk b/packages/devel/tbb/package.mk new file mode 100644 index 0000000000..a3be8e24c5 --- /dev/null +++ b/packages/devel/tbb/package.mk @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2022-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="tbb" +PKG_VERSION="2022.2.0" +PKG_SHA256="f0f78001c8c8edb4bddc3d4c5ee7428d56ae313254158ad1eec49eced57f6a5b" +PKG_LICENSE="Apache-2.0" +PKG_SITE="https://github.com/oneapi-src/oneTBB" +PKG_URL="https://github.com/oneapi-src/oneTBB/archive/refs/tags/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="cmake:host ninja:host" +PKG_LONGDESC="oneTBB is a flexible C++ library that simplifies the work of adding parallelism to complex applications" + +PKG_CMAKE_OPTS_HOST="-DTBB_TEST=OFF \ + -DTBB_EXAMPLES=OFF \ + -DTBB_STRICT=OFF \ + -DTBB4PY_BUILD=OFF \ + -DTBB_BUILD=ON \ + -DTBBMALLOC_BUILD=ON \ + -DTBBMALLOC_PROXY_BUILD=ON \ + -DTBB_CPF=OFF \ + -DTBB_FIND_PACKAGE=OFF \ + -DTBB_DISABLE_HWLOC_AUTOMATIC_SEARCH=OFF \ + -DTBB_ENABLE_IPO=ON" + +pre_configure_host() { + export CXXFLAGS+=" -D__TBB_DYNAMIC_LOAD_ENABLED=0" +} diff --git a/packages/devel/utfcpp/package.mk b/packages/devel/utfcpp/package.mk new file mode 100644 index 0000000000..7077322462 --- /dev/null +++ b/packages/devel/utfcpp/package.mk @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2023-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="utfcpp" +PKG_VERSION="4.0.6" +PKG_SHA256="6920a6a5d6a04b9a89b2a89af7132f8acefd46e0c2a7b190350539e9213816c0" +PKG_LICENSE="BSL" +PKG_SITE="https://github.com/nemtrif/utfcpp" +PKG_URL="https://github.com/nemtrif/utfcpp/archive/refs/tags/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="UTF-8 with C++ in a Portable Way" diff --git a/packages/devel/xxHash/package.mk b/packages/devel/xxHash/package.mk new file mode 100644 index 0000000000..09ae92317b --- /dev/null +++ b/packages/devel/xxHash/package.mk @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2024-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="xxHash" +PKG_VERSION="0.8.3" +PKG_SHA256="aae608dfe8213dfd05d909a57718ef82f30722c392344583d3f39050c7f29a80" +PKG_LICENSE="BSD-2-Clause" +PKG_SITE="https://xxhash.com" +PKG_URL="https://github.com/Cyan4973/xxHash/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="make:host" +PKG_LONGDESC="Extremely fast non-cryptographic hash algorithm" +PKG_BUILD_FLAGS="+local-cc" + +pre_configure_host() { + export prefix=${TOOLCHAIN} +} diff --git a/packages/devel/xxd/package.mk b/packages/devel/xxd/package.mk new file mode 100644 index 0000000000..8e00bdd500 --- /dev/null +++ b/packages/devel/xxd/package.mk @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2022-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="xxd" +PKG_VERSION="$(get_pkg_version vim)" +PKG_LICENSE="VIM" +PKG_URL="" +PKG_DEPENDS_HOST="toolchain:host" +PKG_DEPENDS_UNPACK+=" vim" +PKG_LONGDESC="make a hexdump or do the reverse" +PKG_BUILD_FLAGS="-sysroot" +PKG_TOOLCHAIN="manual" + +unpack() { + mkdir -p ${PKG_BUILD} + tar --strip-components=1 -xf ${SOURCES}/vim/vim-${PKG_VERSION}.tar.gz -C ${PKG_BUILD} +} + +make_host() { + ${HOST_CXX} -x c -std=c11 -O3 -Wall -Wextra -Wpedantic -Wconversion -Wsign-conversion ../src/xxd/xxd.c -o xxd +} + +makeinstall_host() { + mkdir -p ${TOOLCHAIN}/bin + cp -p xxd ${TOOLCHAIN}/bin +} diff --git a/packages/emulation/cyclone68000/package.mk b/packages/emulation/cyclone68000/package.mk new file mode 100644 index 0000000000..52275404fd --- /dev/null +++ b/packages/emulation/cyclone68000/package.mk @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="cyclone68000" +PKG_VERSION="66dda842eae01f47f5389b931ec9567fb0bbb6a1" +PKG_SHA256="c59900531e35e7303e1172d9bd5d161491b4554983930ad855614252156ea0e0" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/notaz/cyclone68000" +PKG_URL="https://github.com/notaz/cyclone68000/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Motorola 68000 emulator written in ARM assembly" +PKG_TOOLCHAIN="manual" diff --git a/packages/emulation/libretro-2048/package.mk b/packages/emulation/libretro-2048/package.mk new file mode 100644 index 0000000000..e4d5976602 --- /dev/null +++ b/packages/emulation/libretro-2048/package.mk @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-2048" +PKG_VERSION="5474ed1ab880b3296c9860d0943d7de1970c79dd" +PKG_SHA256="d0dc119024c4b3283a85c88896009b917a4350f90fd783fd73bf3788c9d8a199" +PKG_LICENSE="Public domain" +PKG_SITE="https://github.com/libretro/libretro-2048" +PKG_URL="https://github.com/libretro/libretro-2048/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Port of 2048 puzzle game to the libretro API." +PKG_TOOLCHAIN="make" +PKG_MAKE_OPTS_TARGET="-f Makefile.libretro" + +PKG_LIBNAME="2048_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="2048_LIB" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-81/package.mk b/packages/emulation/libretro-81/package.mk new file mode 100644 index 0000000000..36f9cd5088 --- /dev/null +++ b/packages/emulation/libretro-81/package.mk @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2023-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-81" +PKG_VERSION="ffc99f27f092addc9ddd34dd0e3a3d4d1c053cbf" +PKG_SHA256="3db0e494cbd2afcc511cd7ba0e5eda104871301e26a74254bf4a08356d567181" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/libretro/81-libretro" +PKG_URL="https://github.com/libretro/81-libretro/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A port of the EightyOne ZX81 Emulator to libretro" +PKG_TOOLCHAIN="make" +PKG_MAKE_OPTS_TARGET="-f Makefile.libretro" + +PKG_LIBNAME="81_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="81_LIB" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-a5200/package.mk b/packages/emulation/libretro-a5200/package.mk new file mode 100644 index 0000000000..3f1ec5bd32 --- /dev/null +++ b/packages/emulation/libretro-a5200/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2023-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-a5200" +PKG_VERSION="526404072821bb2021fab16f8c5dbbca300512c8" +PKG_SHA256="920d6072d58456a05a80e09efa8b8780a1c7d67ec29500e873c3095321fe799a" +PKG_LICENSE="GPL2" +PKG_SITE="https://github.com/libretro/a5200" +PKG_URL="https://github.com/libretro/a5200/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Libretro port of Atari 5200 emulator version 2.0.2 for GCW0" +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="a5200_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="A5200_LIB" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-atari800/package.mk b/packages/emulation/libretro-atari800/package.mk new file mode 100644 index 0000000000..fadd8ab8df --- /dev/null +++ b/packages/emulation/libretro-atari800/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2020-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-atari800" +PKG_VERSION="6a18cb23cc4a7cecabd9b16143d2d7332ae8d44b" +PKG_SHA256="0fa8456f611975f80e0edba37a9cb4935918a94d30f6d42f8fa0679e76a9971a" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/libretro/libretro-atari800" +PKG_URL="https://github.com/libretro/libretro-atari800/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Libretro port of Atari800 emulator version 3.1.0" +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="atari800_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="ATARI800_LIB" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-beetle-bsnes/package.mk b/packages/emulation/libretro-beetle-bsnes/package.mk new file mode 100644 index 0000000000..151ff1ef7c --- /dev/null +++ b/packages/emulation/libretro-beetle-bsnes/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-beetle-bsnes" +PKG_VERSION="f7bfa217cf7150779902c3a998f7624d92a5f17d" +PKG_SHA256="a299383932e35d5030145e14c7fbab57ba6e1fa81e00c866b1bdcbc70bfac1c6" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/beetle-bsnes-libretro" +PKG_URL="https://github.com/libretro/beetle-bsnes-libretro/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Standalone port of Mednafen bSNES to libretro, itself a fork of bsnes 0.59." +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="mednafen_snes_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="BEETLE-BSNES_LIB" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-beetle-gba/package.mk b/packages/emulation/libretro-beetle-gba/package.mk new file mode 100644 index 0000000000..760188dec1 --- /dev/null +++ b/packages/emulation/libretro-beetle-gba/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-beetle-gba" +PKG_VERSION="6cee80685f735ea6c2373db2622a1f1ee9f39d39" +PKG_SHA256="33ef14eb0141e98323cc8c3e997f668df348fea7b7bf5a97766c2c91af075fa7" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/beetle-gba-libretro" +PKG_URL="https://github.com/libretro/beetle-gba-libretro/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="libretro implementation of Mednafen gba" +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="mednafen_gba_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="BEETLE-GBA_LIB" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-beetle-lynx/package.mk b/packages/emulation/libretro-beetle-lynx/package.mk new file mode 100644 index 0000000000..386cd41a04 --- /dev/null +++ b/packages/emulation/libretro-beetle-lynx/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-beetle-lynx" +PKG_VERSION="7fead71b49e0f08be5c4d4224fea73c6174763bf" +PKG_SHA256="ea2a0fe2a5061835a7c8d692e4f6b965f2a82660e027af759e3e963e2508cc43" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/beetle-lynx-libretro" +PKG_URL="https://github.com/libretro/beetle-lynx-libretro/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="libretro implementation of Mednafen Lynx" +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="mednafen_lynx_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="BEETLE-LYNX_LIB" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-beetle-ngp/package.mk b/packages/emulation/libretro-beetle-ngp/package.mk new file mode 100644 index 0000000000..35457ee337 --- /dev/null +++ b/packages/emulation/libretro-beetle-ngp/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-beetle-ngp" +PKG_VERSION="139fe34c8dfc5585d6ee1793a7902bca79d544de" +PKG_SHA256="5f0122405b18e0a95f4a5da2ef2f57b4bf1895a691370e65cc19fd5854a50412" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/beetle-ngp-libretro" +PKG_URL="https://github.com/libretro/beetle-ngp-libretro/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="libretro implementation of Mednafen Neo Geo Pocket." +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="mednafen_ngp_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="BEETLE-NGP_LIB" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-beetle-pce-fast/package.mk b/packages/emulation/libretro-beetle-pce-fast/package.mk new file mode 100644 index 0000000000..b0a7cd219f --- /dev/null +++ b/packages/emulation/libretro-beetle-pce-fast/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-beetle-pce-fast" +PKG_VERSION="931586f0512663f625a6e981d3047a6620281ab5" +PKG_SHA256="f3fe8e4a4130fe12ddd8b01526b724b8c0fd97e0036f0a50e3d2a0336c13356f" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/beetle-pce-fast-libretro" +PKG_URL="https://github.com/libretro/beetle-pce-fast-libretro/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Standalone port of Mednafen PCE Fast to libretro." +PKG_TOOLCHAIN="make" + +PKG_MAKE_OPTS_TARGET="HAVE_CDROM=1" + +PKG_LIBNAME="mednafen_pce_fast_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="BEETLE-PCE-FAST_LIB" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-beetle-pce/package.mk b/packages/emulation/libretro-beetle-pce/package.mk new file mode 100644 index 0000000000..6ef69aafb0 --- /dev/null +++ b/packages/emulation/libretro-beetle-pce/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2023-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-beetle-pce" +PKG_VERSION="af28fb0385d00e0292c4703b3aa7e72762b564d2" +PKG_SHA256="23c7f6524c18409aba60610db39f7b35b3af2cac1359c23b08901575da6bb154" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/beetle-pce-libretro" +PKG_URL="https://github.com/libretro/beetle-pce-libretro/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Standalone port of Mednafen PCE to libretro." +PKG_TOOLCHAIN="make" + +PKG_MAKE_OPTS_TARGET="HAVE_CDROM=1" + +PKG_LIBNAME="mednafen_pce_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="BEETLE-FAST_LIB" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-beetle-pcfx/package.mk b/packages/emulation/libretro-beetle-pcfx/package.mk new file mode 100644 index 0000000000..b32714b63f --- /dev/null +++ b/packages/emulation/libretro-beetle-pcfx/package.mk @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-beetle-pcfx" +PKG_VERSION="dd04cef9355286488a1d78ff18c4c848a1575540" +PKG_SHA256="8f1153206479a25e925981076758698e0c5f6e7f826213b2b3598dc33a7d8ea0" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/beetle-pcfx-libretro" +PKG_URL="https://github.com/libretro/beetle-pcfx-libretro/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="libretro implementation of Mednafen PC-FX." +PKG_TOOLCHAIN="make" + +if [ "${ARCH}" = "x86_64" ]; then + PKG_MAKE_OPTS_TARGET="platform=unix" +else + PKG_MAKE_OPTS_TARGET="platform=armv" +fi + +pre_make_target() { + PKG_MAKE_OPTS_TARGET+=" CC=${CC} CXX=${CXX} AR=${AR}" +} + +PKG_LIBNAME="mednafen_pcfx_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="BEETLE-PCFX_LIB" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-beetle-psx/package.mk b/packages/emulation/libretro-beetle-psx/package.mk new file mode 100644 index 0000000000..660c765151 --- /dev/null +++ b/packages/emulation/libretro-beetle-psx/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-beetle-psx" +PKG_VERSION="80d3eba272cf6efab6b76e4dc44ea2834c6f910d" +PKG_SHA256="9dcd9c5c1f5321e6e6f77fe1f20b4830b2e558569e8d264299c627920324d4f2" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/beetle-psx-libretro" +PKG_URL="https://github.com/libretro/beetle-psx-libretro/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Standalone port of Mednafen PSX to libretro." +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="mednafen_psx_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="BEETLE-PSX_LIB" + +PKG_MAKE_OPTS_TARGET="HAVE_CDROM=1 LINK_STATIC_LIBCPLUSPLUS=0" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-beetle-saturn/package.mk b/packages/emulation/libretro-beetle-saturn/package.mk new file mode 100644 index 0000000000..e5439ae0b9 --- /dev/null +++ b/packages/emulation/libretro-beetle-saturn/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2023-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-beetle-saturn" +PKG_VERSION="0a78a9a5ab0088ba19f21e028dda9f4b4d7c9e48" +PKG_SHA256="3d342a7b29640042af7e245b97375f4e287925c0f5b7f95144ae57b12f96bef8" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/beetle-saturn-libretro" +PKG_URL="https://github.com/libretro/beetle-saturn-libretro/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Standalone port of Mednafen Saturn to libretro." +PKG_TOOLCHAIN="make" + +PKG_MAKE_OPTS_TARGET="HAVE_CDROM=1" + +PKG_LIBNAME="mednafen_saturn_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="BEETLE-SATURN_LIB" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-beetle-supergrafx/package.mk b/packages/emulation/libretro-beetle-supergrafx/package.mk new file mode 100644 index 0000000000..071987c080 --- /dev/null +++ b/packages/emulation/libretro-beetle-supergrafx/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-beetle-supergrafx" +PKG_VERSION="a776133c34ae8da5daf7d9ccb43e3e292e2b07b0" +PKG_SHA256="f6a2d1cfeb170510eed437f939ae05d717a20b6e23626cff6ebd47f0c84f13ce" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/beetle-supergrafx-libretro" +PKG_URL="https://github.com/libretro/beetle-supergrafx-libretro/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Standalone port of Mednafen PCE Fast to libretro." +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="mednafen_supergrafx_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="BEETLE-SUPERGRAFX_LIB" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-beetle-vb/package.mk b/packages/emulation/libretro-beetle-vb/package.mk new file mode 100644 index 0000000000..4d83f27438 --- /dev/null +++ b/packages/emulation/libretro-beetle-vb/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-beetle-vb" +PKG_VERSION="8f837ebc077afdd6652efb2827fd8308a07113ca" +PKG_SHA256="d2733026bde2b8049b8258f68d49954687ab43e2639d6a879c79cca68e91dea6" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/beetle-vb-libretro" +PKG_URL="https://github.com/libretro/beetle-vb-libretro/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="libretro implementation of Mednafen VB (VirtualBoy)" +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="mednafen_vb_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="BEETLE-VB_LIB" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-beetle-wswan/package.mk b/packages/emulation/libretro-beetle-wswan/package.mk new file mode 100644 index 0000000000..f92c548813 --- /dev/null +++ b/packages/emulation/libretro-beetle-wswan/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-beetle-wswan" +PKG_VERSION="2aeb47d3a58bf0360c686f842d9bb5bd201306fe" +PKG_SHA256="035c0ebdad6740511cc395199db134d20c29611b830cf11831d6ec8744a33d42" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/beetle-wswan-libretro" +PKG_URL="https://github.com/libretro/beetle-wswan-libretro/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="libretro implementation of Mednafen wswan" +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="mednafen_wswan_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="BEETLE-WSWAN_LIB" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-bk/package.mk b/packages/emulation/libretro-bk/package.mk new file mode 100644 index 0000000000..d030b4efee --- /dev/null +++ b/packages/emulation/libretro-bk/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2023-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-bk" +PKG_VERSION="f95d929c8eca6c85075cd5c56a08aac9c58f3802" +PKG_SHA256="7ed9976abe5c235061a44884346426509231d1237c9b7ff23e8a7aa6894fcf5d" +PKG_LICENSE="NTP" +PKG_SITE="https://github.com/libretro/bk-emulator" +PKG_URL="https://github.com/libretro/bk-emulator/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="" +PKG_TOOLCHAIN="make" + +PKG_MAKE_OPTS_TARGET="-f Makefile.libretro" + +PKG_LIBNAME="bk_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="BK_LIB" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-blastem/package.mk b/packages/emulation/libretro-blastem/package.mk new file mode 100644 index 0000000000..c6e97d9c6d --- /dev/null +++ b/packages/emulation/libretro-blastem/package.mk @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2023-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-blastem" +PKG_VERSION="277e4a62668597d4f59cadda1cbafb844f981d45" +PKG_SHA256="1ad8eab6f528612d52f8310237d3e62a501e7449682369baa9eb5d4c73a6b90e" +PKG_ARCH="x86_64" +PKG_LICENSE="GPL3" +PKG_SITE="https://github.com/libretro/blastem" +PKG_URL="https://github.com/libretro/blastem/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A github mirror for BlastEm - The fast and accurate Genesis emulator" +PKG_TOOLCHAIN="make" + +PKG_MAKE_OPTS_TARGET="-f Makefile.libretro" + +PKG_LIBNAME="blastem_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="BLASTEM_LIB" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-bluemsx/package.mk b/packages/emulation/libretro-bluemsx/package.mk new file mode 100644 index 0000000000..de9a08af83 --- /dev/null +++ b/packages/emulation/libretro-bluemsx/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-bluemsx" +PKG_VERSION="572c91856a5288b7433c619af651e31f00f3ce7e" +PKG_SHA256="86625bb7f6d1a5abb22d4eaf4691906aa985352519ad8193e63995b010ed214d" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/blueMSX-libretro" +PKG_URL="https://github.com/libretro/blueMSX-libretro/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Port of blueMSX to the libretro API." +PKG_TOOLCHAIN="make" + +PKG_MAKE_OPTS_TARGET="-f Makefile.libretro" + +PKG_LIBNAME="bluemsx_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="BLUEMSX_LIB" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-bnes/package.mk b/packages/emulation/libretro-bnes/package.mk new file mode 100644 index 0000000000..d37daf3352 --- /dev/null +++ b/packages/emulation/libretro-bnes/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-bnes" +PKG_VERSION="8e26e89a93bef8eb8992d1921b539dce1792660a" +PKG_SHA256="c151e1296b8f6c035014dc62919692097feeebb19ae73294f1b9781edf1921b1" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/libretro/bnes-libretro" +PKG_URL="https://github.com/libretro/bnes-libretro/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="libretro implementation of bNES/higan. (Nintendo Entertainment System)" +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="bnes_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="BNES_LIB" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-bsnes-hd/package.mk b/packages/emulation/libretro-bsnes-hd/package.mk new file mode 100644 index 0000000000..d28e806e80 --- /dev/null +++ b/packages/emulation/libretro-bsnes-hd/package.mk @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2023-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-bsnes-hd" +PKG_VERSION="0bb7b8645e22ea2476cabd58f32e987b14686601" +PKG_SHA256="f7c498b927daca8c7d69124369670e749a4e13422411cf7136da695e60da3dc7" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/DerKoun/bsnes-hd" +PKG_URL="https://github.com/DerKoun/bsnes-hd/archive/${PKG_VERSION}.tar.gz" +PKG_BRANCH="master" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Fork of bsnes that adds HD video features." +PKG_TOOLCHAIN="make" + +make_target() { + make -C bsnes -f GNUmakefile target="libretro" compiler="${CXX}" CXXFLAGS="${CXXFLAGS}" platform=linux local=false binary=library +} + +PKG_LIBNAME="bsnes_hd_beta_libretro.so" +PKG_LIBPATH="bsnes/out/${PKG_LIBNAME}" +PKG_LIBVAR="BSNES-HD_LIB" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-bsnes-hd/patches/bsnes_hd-001-disable_openmp.patch b/packages/emulation/libretro-bsnes-hd/patches/bsnes_hd-001-disable_openmp.patch new file mode 100644 index 0000000000..68c176b15e --- /dev/null +++ b/packages/emulation/libretro-bsnes-hd/patches/bsnes_hd-001-disable_openmp.patch @@ -0,0 +1,37 @@ +diff --git a/bsnes/GNUmakefile b/bsnes/GNUmakefile +index 58466fb..eceb96c 100644 +--- a/bsnes/GNUmakefile ++++ b/bsnes/GNUmakefile +@@ -1,7 +1,7 @@ + target ?= bsnes + binary ?= application + build := performance +-openmp := true ++openmp := false + local := false + flags += -I. -I.. + +diff --git a/bsnes/target-libretro/GNUmakefile b/bsnes/target-libretro/GNUmakefile +index 340c40a..ddc2297 100644 +--- a/bsnes/target-libretro/GNUmakefile ++++ b/bsnes/target-libretro/GNUmakefile +@@ -1,6 +1,6 @@ + name := bsnes_libretro + local := false +-openmp := true ++openmp := false + flags += -Wno-narrowing -Wno-multichar -g -fPIC + + ifeq ($(platform), ios-arm64) +@@ -23,9 +23,9 @@ obj/libretro.o: target-libretro/libretro.cpp + + all: $(objects) + ifeq ($(platform),linux) +- $(strip $(compiler) -o out/bsnes_hd_beta_libretro.so -shared $(objects) -Wl,--no-undefined -Wl,--version-script=target-libretro/link.T -lgomp -Wl,-Bdynamic $(options)) ++ $(strip $(compiler) -o out/bsnes_hd_beta_libretro.so -shared $(objects) -Wl,--no-undefined -Wl,--version-script=target-libretro/link.T -Wl,-Bdynamic $(options)) + else ifeq ($(platform),windows) +- $(strip $(compiler) -o out/bsnes_hd_beta_libretro.dll -shared $(objects) -Wl,--no-undefined -Wl,--version-script=target-libretro/link.T -lgomp -Wl,-Bdynamic $(options)) ++ $(strip $(compiler) -o out/bsnes_hd_beta_libretro.dll -shared $(objects) -Wl,--no-undefined -Wl,--version-script=target-libretro/link.T -Wl,-Bdynamic $(options)) + else ifeq ($(platform),libnx) + $(strip $(AR) rcs out/bsnes_hd_beta_libretro_libnx.a $(objects)) + else ifeq ($(platform),macos) diff --git a/packages/emulation/libretro-bsnes-mercury-performance/package.mk b/packages/emulation/libretro-bsnes-mercury-performance/package.mk new file mode 100644 index 0000000000..ef93f3918b --- /dev/null +++ b/packages/emulation/libretro-bsnes-mercury-performance/package.mk @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-bsnes-mercury-performance" +PKG_VERSION="0f35d044bf2f2b879018a0500e676447e93a1db1" +PKG_SHA256="aba28b88898492239bbe752cc8fa5c62d89d5a9f6ddbafd4b4ae97b1d34c41ec" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/libretro/bsnes-mercury" +PKG_URL="https://github.com/libretro/bsnes-mercury/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Fork of bsnes with HLE DSP emulation restored." +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="bsnes_mercury_performance_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="BSNES-MERCURY-PERFORMANCE_LIB" + +PKG_MAKE_OPTS_TARGET="ui=target-libretro profile=performance" + +pre_make_target() { + PKG_MAKE_OPTS_TARGET+=" compiler=${CXX}" +} + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-bsnes-mercury-performance/patches/libretro-bsnes-mercury-performance-0001_fix-cross-compile.patch b/packages/emulation/libretro-bsnes-mercury-performance/patches/libretro-bsnes-mercury-performance-0001_fix-cross-compile.patch new file mode 100644 index 0000000000..a657f499c0 --- /dev/null +++ b/packages/emulation/libretro-bsnes-mercury-performance/patches/libretro-bsnes-mercury-performance-0001_fix-cross-compile.patch @@ -0,0 +1,25 @@ +From da71b9ec79482c31c37496019792da316626f1f2 Mon Sep 17 00:00:00 2001 +From: Lukas Rusak +Date: Sun, 5 Feb 2017 20:40:42 -0800 +Subject: [PATCH 2/2] no -O3 + +--- + Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Makefile b/Makefile +index 948f5fb..04e585d 100644 +--- a/Makefile ++++ b/Makefile +@@ -459,7 +459,7 @@ OBJECTS := $(SOURCES_CXX:.cpp=.o) $(SOURCES_C:.c=.o) + all: $(TARGET) + + ifeq ($(DEBUG),0) +- FLAGS += -O3 $(EXTRA_GCC_FLAGS) ++ FLAGS += $(EXTRA_GCC_FLAGS) + else + FLAGS += -O0 -g + endif +-- +2.9.3 + diff --git a/packages/emulation/libretro-bsnes/package.mk b/packages/emulation/libretro-bsnes/package.mk new file mode 100644 index 0000000000..ae02c5e819 --- /dev/null +++ b/packages/emulation/libretro-bsnes/package.mk @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2023-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-bsnes" +PKG_VERSION="a0bb11bbb1fc5d6b478baca53c3efe526c43986c" +PKG_SHA256="157dfba01ce80c7537d5576825dc36f1c9ff3cd1caa6f6caf3ee241164f0287a" +PKG_LICENSE="GPLv3/ISC" +PKG_SITE="https://github.com/libretro/bsnes" +PKG_URL="https://github.com/libretro/bsnes-libretro/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Super Nintendo (Super Famicom) emulator" +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="bsnes_libretro.so" +PKG_LIBPATH="bsnes/out/${PKG_LIBNAME}" +PKG_LIBVAR="BSNES_LIB" + +PKG_MAKE_OPTS_TARGET="-C bsnes -f GNUmakefile target=libretro platform=linux local=false" + +pre_make_target() { + PKG_MAKE_OPTS_TARGET+=" compiler=${CXX}" +} + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-bsnes/patches/0001-Disable-OpenMP.patch b/packages/emulation/libretro-bsnes/patches/0001-Disable-OpenMP.patch new file mode 100644 index 0000000000..5da46caf33 --- /dev/null +++ b/packages/emulation/libretro-bsnes/patches/0001-Disable-OpenMP.patch @@ -0,0 +1,63 @@ +From 43c1b5bd74f8e6355dd55d177ec66cece9c75900 Mon Sep 17 00:00:00 2001 +From: Garrett Brown +Date: Tue, 28 Mar 2023 19:00:04 -0700 +Subject: [PATCH] Disable OpenMP + +--- + bsnes/GNUmakefile | 5 ++--- + bsnes/target-libretro/GNUmakefile | 8 ++++---- + 2 files changed, 6 insertions(+), 7 deletions(-) + +diff --git a/bsnes/GNUmakefile b/bsnes/GNUmakefile +index ab0c1a76..1d7aa92b 100644 +--- a/bsnes/GNUmakefile ++++ b/bsnes/GNUmakefile +@@ -1,8 +1,8 @@ + target ?= bsnes + binary ?= application + build := performance +-openmp := true +-local ?= true ++openmp := false ++local ?= false + flags += -I. -I.. + + # in order for this to work, obj/lzma.o must be omitted or bsnes will hang on startup. +@@ -37,7 +37,6 @@ else ifeq ($(platform),macos) + else ifneq ($(filter $(platform),linux bsd unix unix-armv7-hardfloat-neon),) + ifeq ($(binary),application) + options += -Wl,-export-dynamic +- options += -lX11 -lXext + else ifeq ($(binary),library) + flags += -fPIC + options += -shared +diff --git a/bsnes/target-libretro/GNUmakefile b/bsnes/target-libretro/GNUmakefile +index a39bed5a..0e0a39f6 100644 +--- a/bsnes/target-libretro/GNUmakefile ++++ b/bsnes/target-libretro/GNUmakefile +@@ -1,6 +1,6 @@ + name := bsnes_libretro + local := false +-openmp := true ++openmp := false + flags += -Wno-narrowing -Wno-multichar -g -fPIC + + ifeq ($(platform), ios-arm64) +@@ -24,11 +24,11 @@ obj/program.o: target-libretro/program.cpp + + all: $(objects) + ifneq ($(filter $(platform),linux bsd unix unix-armv7-hardfloat-neon),) +- $(strip $(compiler) -o out/bsnes_libretro.so -shared $(objects) -Wl,--no-undefined -Wl,--version-script=target-libretro/link.T -lgomp -Wl,-Bdynamic $(options)) ++ $(strip $(compiler) -o out/bsnes_libretro.so -shared $(objects) -Wl,--no-undefined -Wl,--version-script=target-libretro/link.T -Wl,-Bdynamic $(options)) + else ifeq ($(platform),haiku) +- $(strip $(compiler) -o out/bsnes_libretro.so -shared $(objects) -Wl,--no-undefined -Wl,--version-script=target-libretro/link.T -lgomp -Wl,-Bdynamic $(options)) ++ $(strip $(compiler) -o out/bsnes_libretro.so -shared $(objects) -Wl,--no-undefined -Wl,--version-script=target-libretro/link.T -Wl,-Bdynamic $(options)) + else ifeq ($(platform),windows) +- $(strip $(compiler) -o out/bsnes_libretro.dll -shared $(objects) -Wl,--no-undefined -Wl,--version-script=target-libretro/link.T -lgomp -Wl,-Bdynamic $(options)) ++ $(strip $(compiler) -o out/bsnes_libretro.dll -shared $(objects) -Wl,--no-undefined -Wl,--version-script=target-libretro/link.T -Wl,-Bdynamic $(options)) + else ifeq ($(platform),libnx) + $(strip $(AR) rcs out/bsnes_libretro_libnx.a $(objects)) + else ifeq ($(platform),macos) +-- +2.34.1 + diff --git a/packages/emulation/libretro-bsnes2014-performance/package.mk b/packages/emulation/libretro-bsnes2014-performance/package.mk new file mode 100644 index 0000000000..9feea89cff --- /dev/null +++ b/packages/emulation/libretro-bsnes2014-performance/package.mk @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2023-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-bsnes2014-performance" +PKG_VERSION="3beff8ebfa91d6faaf8b854140fbcb7542a3c516" +PKG_SHA256="39b329918124d39f33267f04b5e7a1fec5561b9c37da47ffd7edcc59fc1abf49" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/libretro/bsnes2014" +PKG_URL="https://github.com/libretro/bsnes2014/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Libretro fork of bsnes. As close to upstream as possible." +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="bsnes2014_performance_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="BSNES2014-PERFORMANCE_LIB" + +pre_make_target() { + if [ "${ARCH}" = "aarch64" ]; then + LDFLAGS+=" -lgcc" + fi +} + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-cannonball/package.mk b/packages/emulation/libretro-cannonball/package.mk new file mode 100644 index 0000000000..de28a63a31 --- /dev/null +++ b/packages/emulation/libretro-cannonball/package.mk @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2023-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-cannonball" +PKG_VERSION="5137a791d229a5b9c7c089cf1edcce4db3c57d64" +PKG_SHA256="f066944897cde7bbf3df365ac75c2cc1ef5114059d1a0c51782f12bff5bcfa73" +PKG_LICENSE="MAME" +PKG_SITE="https://github.com/libretro/cannonball" +PKG_URL="https://github.com/libretro/cannonball/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Cannonball: An Enhanced OutRun Engine" +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="cannonball_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="CANNONBALL_LIB" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake + + mkdir -p ${SYSROOT_PREFIX}/usr/share/retroarch/system/cannonball/res/ + cp -v res/{tilemap.bin,tilepatch.bin} docs/license.txt ${SYSROOT_PREFIX}/usr/share/retroarch/system/cannonball/res/ + cp -v roms/roms.txt ${SYSROOT_PREFIX}/usr/share/retroarch/system/cannonball/ +} diff --git a/packages/emulation/libretro-cap32/package.mk b/packages/emulation/libretro-cap32/package.mk new file mode 100644 index 0000000000..572948c3aa --- /dev/null +++ b/packages/emulation/libretro-cap32/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-cap32" +PKG_VERSION="dbfa1aa2dc132f57289329252829174c1cea4230" +PKG_SHA256="7296917304e07a67a0fa66e5da30c8f855a9c0ed3cb65e6b8e50dd262f078bf0" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/libretro-cap32" +PKG_URL="https://github.com/libretro/libretro-cap32/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="caprice32 4.2.0 libretro" +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="cap32_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="CAP32_LIB" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-common/package.mk b/packages/emulation/libretro-common/package.mk new file mode 100644 index 0000000000..3fe9a6bbd7 --- /dev/null +++ b/packages/emulation/libretro-common/package.mk @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-common" +PKG_VERSION="50c15a88eb741cbe675743a282d8cc4c89421e3f" +PKG_SHA256="042986fad22dc37188df7a186d17a258edfe8e552353f9b509a47418e8dfa623" +PKG_LICENSE="Public domain" +PKG_SITE="https://github.com/libretro/libretro-common" +PKG_URL="https://github.com/libretro/libretro-common/archive/${PKG_VERSION}.tar.gz" +PKG_LONGDESC="Reusable coding blocks useful for libretro core and frontend development" +PKG_TOOLCHAIN="manual" + +makeinstall_target() { + mkdir -p "${SYSROOT_PREFIX}/usr/include/${PKG_NAME}" + cp -pR ${PKG_BUILD}/include/* "${SYSROOT_PREFIX}/usr/include/${PKG_NAME}/" +} diff --git a/packages/emulation/libretro-dinothawr/package.mk b/packages/emulation/libretro-dinothawr/package.mk new file mode 100644 index 0000000000..2a09cbf2a1 --- /dev/null +++ b/packages/emulation/libretro-dinothawr/package.mk @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-dinothawr" +PKG_VERSION="e57e780a963372b89736620d7e3b8608190f7581" +PKG_SHA256="e969f14628a0b7c49609bc98b5ddf6344b3fa4ad3389de77f59da2d2b6160480" +PKG_LICENSE="CC-BY-NC-SA-3.0" +PKG_SITE="https://github.com/libretro/Dinothawr" +PKG_URL="https://github.com/libretro/Dinothawr/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Dinothawr is a block pushing puzzle game on slippery surfaces" +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="dinothawr_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="DINOTHAWR_LIB" + +if target_has_feature neon; then + PKG_MAKE_OPTS_TARGET="HAVE_NEON=1" +fi + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake + + mkdir -p ${SYSROOT_PREFIX}/usr/share/retroarch/system + cp -rv dinothawr ${SYSROOT_PREFIX}/usr/share/retroarch/system/dinothawr +} diff --git a/packages/emulation/libretro-dosbox-pure/package.mk b/packages/emulation/libretro-dosbox-pure/package.mk new file mode 100644 index 0000000000..622d713726 --- /dev/null +++ b/packages/emulation/libretro-dosbox-pure/package.mk @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-dosbox-pure" +PKG_VERSION="64600697f5623c755eaf47f198fa0c5080084b32" +PKG_SHA256="bc2b1062383a5089723afdb67febedeb8b6d0d1e14080086a6e90021f60a67ae" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/dosbox-pure" +PKG_URL="https://github.com/libretro/dosbox-pure/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="DOSBox Pure is a fork of DOSBox, an emulator for DOS games, built for RetroArch/Libretro aiming for simplicity and ease of use." +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="dosbox_pure_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="DOSBOX-PURE_LIB" + +PKG_BUILD_FLAGS="+pic" + +make_target() { + # remove optimization from CFLAGS, set via Makefile + CFLAGS="${CFLAGS//-O3/}" + CFLAGS="${CFLAGS//-O2/}" + make CXX=${CXX} CPUFLAGS="${CFLAGS}" +} + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-dosbox-pure/patches/dosbox_pure-Makefile-optimization_and_libs.patch b/packages/emulation/libretro-dosbox-pure/patches/dosbox_pure-Makefile-optimization_and_libs.patch new file mode 100644 index 0000000000..b60459c5f2 --- /dev/null +++ b/packages/emulation/libretro-dosbox-pure/patches/dosbox_pure-Makefile-optimization_and_libs.patch @@ -0,0 +1,28 @@ +diff -Naur dosbox_pure-4fdb557e415698aae5bd90b076f76437f5e9b0b4/Makefile dosbox_pure-4fdb557e415698aae5bd90b076f76437f5e9b0b4-2/Makefile +--- dosbox_pure-4fdb557e415698aae5bd90b076f76437f5e9b0b4/Makefile 2022-12-13 22:22:26.391256258 +0100 ++++ dosbox_pure-4fdb557e415698aae5bd90b076f76437f5e9b0b4-2/Makefile 2022-12-13 22:38:22.894452324 +0100 +@@ -201,9 +201,9 @@ + ifeq ($(platform),vita) + CFLAGS := -DNDEBUG -O3 -fno-ident -fno-partial-inlining + else +- CFLAGS := -DNDEBUG -O2 -fno-ident ++ CFLAGS := -DNDEBUG -O3 -fno-ident + endif +- LDFLAGS += -O2 ++ LDFLAGS += -O3 -fno-ident + endif + + CFLAGS += $(CPUFLAGS) -std=gnu++11 -fomit-frame-pointer -fexceptions -Wno-address-of-packed-member -Wno-format -Wno-switch -Wno-psabi +@@ -245,9 +245,9 @@ + else + $(info Linking $@ ...) + $(CXX) $(LDFLAGS) -o $@ $^ $(LDLIBS) +-ifneq ($(BUILD),DEBUG) +- $(STRIPCMD) $@ +-endif ++#ifneq ($(BUILD),DEBUG) ++# $(STRIPCMD) $@ ++#endif + endif + + define COMPILE diff --git a/packages/emulation/libretro-dosbox-pure/patches/libretro-dosbox-pure-001-cross-compile-fix.patch b/packages/emulation/libretro-dosbox-pure/patches/libretro-dosbox-pure-001-cross-compile-fix.patch new file mode 100644 index 0000000000..116d107548 --- /dev/null +++ b/packages/emulation/libretro-dosbox-pure/patches/libretro-dosbox-pure-001-cross-compile-fix.patch @@ -0,0 +1,29 @@ +--- a/Makefile ++++ b/Makefile +@@ -33,7 +33,7 @@ SOURCES := \ + src/*/*/*.cpp + + CPUFLAGS := $(MAKE_CPUFLAGS) +-STRIPCMD := $(or $(STRIP),strip) --strip-all ++STRIPCMD := ${STRIP} + ifneq ($(ISWIN),) + OUTNAME := dosbox_pure_libretro.dll + CXX ?= g++ +@@ -152,6 +152,9 @@ else + CXX ?= g++ + LDFLAGS := -Wl,--gc-sections -fno-ident + COMMONFLAGS += -pthread ++ifeq (1,1) # always ++ CPUFLAGS := ++else + ifeq ($(CPUFLAGS),) + # ARM optimizations + PROCCPU := $(shell cat /proc/cpuinfo)) +@@ -180,6 +183,7 @@ else + CXX := g++-9 + endif + endif ++endif + + ifeq ($(BUILD),DEBUG) + BUILDDIR := debug diff --git a/packages/emulation/libretro-dosbox/package.mk b/packages/emulation/libretro-dosbox/package.mk new file mode 100644 index 0000000000..e9446ab074 --- /dev/null +++ b/packages/emulation/libretro-dosbox/package.mk @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-dosbox" +PKG_VERSION="b7b24262c282c0caef2368c87323ff8c381b3102" +PKG_SHA256="83d8b06eebc67f85ff7505271330b1f1c8ef6c4233ef85d070b0789eab83c33d" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/dosbox-libretro" +PKG_URL="https://github.com/libretro/dosbox-libretro/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="libretro wrapper for the DOSBox emulator" +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="dosbox_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="DOSBOX_LIB" + +PKG_MAKE_OPTS_TARGET="-f Makefile.libretro" + +pre_make_target() { + CXXFLAGS+=" -std=gnu++11" +} + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-fbneo/package.mk b/packages/emulation/libretro-fbneo/package.mk new file mode 100644 index 0000000000..741d22de69 --- /dev/null +++ b/packages/emulation/libretro-fbneo/package.mk @@ -0,0 +1,45 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-fbneo" +PKG_VERSION="6ff5e47def714175ac040acc6c49359e57a85607" +PKG_SHA256="9cc2370b48127657ff96f9993d7d16ff4025c7adf4b5e747e81398dd1f2ae6e7" +PKG_LICENSE="Non-commercial" +PKG_SITE="https://github.com/libretro/fbneo" +PKG_URL="https://github.com/libretro/FBNeo/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Port of Final Burn Neo to Libretro" +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="fbneo_libretro.so" +PKG_LIBPATH="src/burner/libretro/${PKG_LIBNAME}" +PKG_LIBVAR="FBNEO_LIB" + +PKG_MAKE_OPTS_TARGET="-C src/burner/libretro" + +if [ "${ARCH}" = "arm" ]; then + PKG_MAKE_OPTS_TARGET+=" profile=performance" + + if target_has_feature neon; then + PKG_MAKE_OPTS_TARGET+=" HAVE_NEON=1" + fi + + if [ "${PROJECT}" = "Rockchip" -a "${DEVICE}" = "OdroidGoAdvance" ]; then + PKG_MAKE_OPTS_TARGET+=" USE_CYCLONE=1" + fi + +else + PKG_MAKE_OPTS_TARGET+=" profile=accuracy" +fi + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake + + mkdir -p ${SYSROOT_PREFIX}/usr/share/libretro-database/fbneo + cp -vr dats/* ${SYSROOT_PREFIX}/usr/share/libretro-database/fbneo + + mkdir -p ${SYSROOT_PREFIX}/usr/share/retroarch/system/fbneo + cp metadata/hiscore.dat ${SYSROOT_PREFIX}/usr/share/retroarch/system/fbneo +} diff --git a/packages/emulation/libretro-fceumm/package.mk b/packages/emulation/libretro-fceumm/package.mk new file mode 100644 index 0000000000..118941f320 --- /dev/null +++ b/packages/emulation/libretro-fceumm/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-fceumm" +PKG_VERSION="449db5de6b56e9d44fc685e1b38399f0b233bd28" +PKG_SHA256="5cac184772421ec3cffa19f50737a5fdd481089007d21d79b3e2760f94c8fa87" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/libretro-fceumm" +PKG_URL="https://github.com/libretro/libretro-fceumm/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Port of FCEUmm / FCEUX to Libretro." +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="fceumm_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="FCEUMM_LIB" + +PKG_MAKE_OPTS_TARGET="-f Makefile.libretro" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-fmsx/package.mk b/packages/emulation/libretro-fmsx/package.mk new file mode 100644 index 0000000000..bdee69004b --- /dev/null +++ b/packages/emulation/libretro-fmsx/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-fmsx" +PKG_VERSION="9eb5f25df5397212a3e3088ca1a64db0740bbe5f" +PKG_SHA256="a20197dc2bf8ab01f79dc341233656053de8bd78cf8e597b6e375bf0722d2b28" +PKG_LICENSE="Non-commercial" +PKG_SITE="https://github.com/libretro/fmsx-libretro" +PKG_URL="https://github.com/libretro/fmsx-libretro/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Port of fMSX to the libretro API." +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="fmsx_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="FMSX_LIB" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-fuse/package.mk b/packages/emulation/libretro-fuse/package.mk new file mode 100644 index 0000000000..41348bfcec --- /dev/null +++ b/packages/emulation/libretro-fuse/package.mk @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-fuse" +PKG_VERSION="cad85b7b1b864c65734f71aa4a510b6f6536881c" +PKG_SHA256="6fda1a3ffc0d2faeebe27fae94e5b7790337dd96d1ea29922ad804a425d2852b" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/libretro/fuse-libretro" +PKG_URL="https://github.com/libretro/fuse-libretro/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain bzip2" +PKG_LONGDESC="A port of the Fuse Unix Spectrum Emulator to libretro " +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="fuse_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="FUSE_LIB" + +PKG_MAKE_OPTS_TARGET="-f Makefile.libretro" + +pre_make_target() { + CFLAGS+=" -DHAVE_LIBBZ2" + CXXFLAGS+=" -DHAVE_LIBBZ2" +} + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-gambatte/package.mk b/packages/emulation/libretro-gambatte/package.mk new file mode 100644 index 0000000000..bbcd5a0b8f --- /dev/null +++ b/packages/emulation/libretro-gambatte/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-gambatte" +PKG_VERSION="9d92381643a6aad186054fa6019a47b710f73d2c" +PKG_SHA256="48c8e6607b24204544a8f4a56eb64527a89676b00b04cd098b0f2517bd4aef6a" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/gambatte-libretro" +PKG_URL="https://github.com/libretro/gambatte-libretro/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="libretro implementation of libgambatte, an open-source Game Boy Color emulator written for fun and made available in the hope that it will be useful." +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="gambatte_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="GAMBATTE_LIB" + +PKG_MAKE_OPTS_TARGET="-f Makefile.libretro" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-genplus/package.mk b/packages/emulation/libretro-genplus/package.mk new file mode 100644 index 0000000000..86c1b4a423 --- /dev/null +++ b/packages/emulation/libretro-genplus/package.mk @@ -0,0 +1,34 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-genplus" +PKG_VERSION="3c1698778080541927f3d7011a00d2c9efe545af" +PKG_SHA256="533c5c71ba02cf7a6114015d1b9f163779f038f7ef66ed5c2ded363604f77b73" +PKG_LICENSE="Non-commercial" +PKG_SITE="https://github.com/ekeeke/Genesis-Plus-GX" +PKG_URL="https://github.com/libretro/Genesis-Plus-GX/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +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_TOOLCHAIN="make" + +PKG_LIBNAME="genesis_plus_gx_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="GENPLUS_LIB" + +PKG_MAKE_OPTS_TARGET="-f Makefile.libretro" + +if [ "${ARCH}" = "aarch64" ]; then + PKG_MAKE_OPTS_TARGET+=" NO_OPTIMIZE=1" +fi + +pre_make_target() { + if [ "${ARCH}" = "arm" -o "${ARCH}" = "aarch64" ]; then + CFLAGS+=" -DALIGN_LONG" + fi +} + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-gw/package.mk b/packages/emulation/libretro-gw/package.mk new file mode 100644 index 0000000000..67f181ed4f --- /dev/null +++ b/packages/emulation/libretro-gw/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-gw" +PKG_VERSION="435e5cfd4bf6aea03a84259e9b8dba3daf3ff5bd" +PKG_SHA256="610f613aedb6182b00bd4231e53d4350977b97e28f6f551cec138ef810cbb761" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/libretro/gw-libretro" +PKG_URL="https://github.com/libretro/gw-libretro/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A libretro core for Game & Watch simulators" +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="gw_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="GW_LIB" + +PKG_MAKE_OPTS_TARGET="-f Makefile.libretro" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-handy/package.mk b/packages/emulation/libretro-handy/package.mk new file mode 100644 index 0000000000..ded7738ca6 --- /dev/null +++ b/packages/emulation/libretro-handy/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-handy" +PKG_VERSION="4e9e072796e5552a9d57f6ab83b3f85f27b17fb6" +PKG_SHA256="7c21fe578d1ba4271ee07530552b3cfb7deb905147edc3fb7d8c33cf5f45ec4c" +PKG_LICENSE="Zlib" +PKG_SITE="https://github.com/libretro/libretro-handy" +PKG_URL="https://github.com/libretro/libretro-handy/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="K. Wilkins' Atari Lynx emulator Handy for libretro" +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="handy_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="HANDY_LIB" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-hatari/package.mk b/packages/emulation/libretro-hatari/package.mk new file mode 100644 index 0000000000..bea35f2883 --- /dev/null +++ b/packages/emulation/libretro-hatari/package.mk @@ -0,0 +1,30 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-hatari" +PKG_VERSION="7008194d3f951a157997f67a820578f56f7feee0" +PKG_SHA256="05f9da703fb5030aa5424e53a35d9b310d183b3b48aa777504e796c88fdd3da2" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/hatari" +PKG_URL="https://github.com/libretro/hatari/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain zlib" +PKG_LONGDESC="New rebasing of Hatari based on Mercurial upstream. Tries to be a shallow fork for easy upstreaming later on." +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="hatari_libretro.so" +PKG_LIBPATH="../${PKG_LIBNAME}" +PKG_LIBVAR="HATARI_LIB" + +PKG_MAKE_OPTS_TARGET="-C ../ -f Makefile.libretro" + +pre_make_target() { + if [ "${ARCH}" = "arm" ]; then + CFLAGS+=" -DNO_ASM -DARM -D__arm__ -DARM_ASM -DNOSSE -DARM_HARDFP" + fi +} + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-mame2000/package.mk b/packages/emulation/libretro-mame2000/package.mk new file mode 100644 index 0000000000..e153dd3278 --- /dev/null +++ b/packages/emulation/libretro-mame2000/package.mk @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-mame2000" +PKG_VERSION="2ec60f6e1078cf9ba173e80432cc28fd4eea200f" +PKG_SHA256="e9e39e0153970729a2b81898af140749118db56be2920600bcff29fe13c59658" +PKG_LICENSE="MAME" +PKG_SITE="https://github.com/libretro/mame2000-libretro" +PKG_URL="https://github.com/libretro/mame2000-libretro/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="MAME - Multiple Arcade Machine Emulator" +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="mame2000_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="MAME2000_LIB" + +if [ "${ARCH}" = "arm" ]; then + PKG_MAKE_OPTS_TARGET="ARM=1 USE_CYCLONE=1 USE_DRZ80=1" +fi + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-mame2003_plus/package.mk b/packages/emulation/libretro-mame2003_plus/package.mk new file mode 100644 index 0000000000..7f90d654a6 --- /dev/null +++ b/packages/emulation/libretro-mame2003_plus/package.mk @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-mame2003_plus" +PKG_VERSION="465e91a8d325dbf29ae668938cb9fa71715d1a2e" +PKG_SHA256="590c5cb06125655f456d315012a2959ad420b1e7c9520a6220867ac0ca2922a5" +PKG_LICENSE="MAME" +PKG_SITE="https://github.com/libretro/mame2003-plus-libretro" +PKG_URL="https://github.com/libretro/mame2003-plus-libretro/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="MAME - Multiple Arcade Machine Emulator" +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="mame2003_plus_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="MAME2003_PLUS_LIB" + +pre_make_target() { + PKG_MAKE_OPTS_TARGET="ARCH= CC=${CC} NATIVE_CC=${CC} LD=${CC}" +} + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake + + mkdir -p ${SYSROOT_PREFIX}/usr/share/libretro-database/mame2003-plus + cp -v metadata/mame2003-plus.xml ${SYSROOT_PREFIX}/usr/share/libretro-database/mame2003-plus/ + + mkdir -p ${SYSROOT_PREFIX}/usr/share/retroarch/system/mame2003-plus/samples + cp -rv metadata/artwork ${SYSROOT_PREFIX}/usr/share/retroarch/system/mame2003-plus + cp -v metadata/{cheat,hiscore,history}.dat ${SYSROOT_PREFIX}/usr/share/retroarch/system/mame2003-plus + # something must be in a folder in order to include it in the image, so why not some instructions + echo "Put your samples here." >${SYSROOT_PREFIX}/usr/share/retroarch/system/mame2003-plus/samples/readme.txt +} diff --git a/packages/emulation/libretro-mame2010/package.mk b/packages/emulation/libretro-mame2010/package.mk new file mode 100644 index 0000000000..4547750d82 --- /dev/null +++ b/packages/emulation/libretro-mame2010/package.mk @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-mame2010" +PKG_VERSION="c5b413b71e0a290c57fc351562cd47ba75bac105" +PKG_SHA256="38270732ef2b503583e96a3c83cd5ba8d4ca6510d1f24f2b00bf6703eb74070d" +PKG_LICENSE="MAME" +PKG_SITE="https://github.com/libretro/mame2010-libretro" +PKG_URL="https://github.com/libretro/mame2010-libretro/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain zlib" +PKG_LONGDESC="Late 2010 version of MAME (0.139) for libretro. Compatible with MAME 0.139 romsets." +PKG_TOOLCHAIN="manual" + +PKG_LIBNAME="mame2010_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="MAME2010_LIB" + +pre_make_target() { + PKG_MAKE_OPTS_TARGET="CC=${CC} LD=${CC}" + if [ "${ARCH}" = "arm" ]; then + PKG_MAKE_OPTS_TARGET+=" PTR64=0 ARM_ENABLED=1 LCPU=arm" + elif [ "${ARCH}" = "x86_64" ]; then + PKG_MAKE_OPTS_TARGET+=" PTR64=1 ARM_ENABLED=0 LCPU=x86_64" + elif [ "${ARCH}" = "aarch64" ]; then + PKG_MAKE_OPTS_TARGET+=" PTR64=1 ARM_ENABLED=1 LCPU=arm64" + fi + make ${PKG_MAKE_OPTS_TARGET} PLATCFLAGS="${CFLAGS}" maketree +} + +make_target() { + make ${PKG_MAKE_OPTS_TARGET} PLATCFLAGS="${CFLAGS}" +} + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake + + mkdir -p ${SYSROOT_PREFIX}/usr/share/libretro-database/mame2010 + cp -v metadata/mame2010.xml ${SYSROOT_PREFIX}/usr/share/libretro-database/mame2010/ +} diff --git a/packages/emulation/libretro-mame2010/patches/mame2010-dont_force_objdump.patch b/packages/emulation/libretro-mame2010/patches/mame2010-dont_force_objdump.patch new file mode 100644 index 0000000000..d39440c169 --- /dev/null +++ b/packages/emulation/libretro-mame2010/patches/mame2010-dont_force_objdump.patch @@ -0,0 +1,13 @@ +diff --git a/Makefile b/Makefile +index 65ece36..6fd017d 100644 +--- a/Makefile ++++ b/Makefile +@@ -633,7 +633,7 @@ endif + # utilities + MD = -mkdir$(EXE_EXT) + RM = @rm -f +-OBJDUMP = @objdump ++OBJDUMP ?= @objdump + + #------------------------------------------------- + # form the name of the executable diff --git a/packages/emulation/libretro-mesen-s/package.mk b/packages/emulation/libretro-mesen-s/package.mk new file mode 100644 index 0000000000..944a5cd7ef --- /dev/null +++ b/packages/emulation/libretro-mesen-s/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2023-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-mesen-s" +PKG_VERSION="d4fca31a6004041d99b02199688f84c009c55967" +PKG_SHA256="f9a601bcb518bf750b5674bc3990675245fe3cfae6d824be8fb4bd61d13cecc4" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/libretro/Mesen-S" +PKG_URL="https://github.com/libretro/Mesen-S/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Mesen-S is a cross-platform (Windows & Linux) SNES emulator built in C++ and C#" +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="mesen-s_libretro.so" +PKG_LIBPATH="Libretro/${PKG_LIBNAME}" +PKG_LIBVAR="MESEN-S_LIB" + +PKG_MAKE_OPTS_TARGET="-C Libretro/" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-mesen/package.mk b/packages/emulation/libretro-mesen/package.mk new file mode 100644 index 0000000000..e2611e28aa --- /dev/null +++ b/packages/emulation/libretro-mesen/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-mesen" +PKG_VERSION="791c5e8153ee6e29691d45b5df2cf1151ff416f9" +PKG_SHA256="b39cad667603a116b38ddea1b96b88001d8e469637bd0ff3838a7a536eff1bf4" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/libretro/Mesen" +PKG_URL="https://github.com/libretro/Mesen/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Mesen is a cross-platform (Windows & Linux) NES/Famicom emulator built in C++ and C#" +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="mesen_libretro.so" +PKG_LIBPATH="Libretro/${PKG_LIBNAME}" +PKG_LIBVAR="MESEN_LIB" + +PKG_MAKE_OPTS_TARGET="-C Libretro/" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-mgba/package.mk b/packages/emulation/libretro-mgba/package.mk new file mode 100644 index 0000000000..0fbe0c05a9 --- /dev/null +++ b/packages/emulation/libretro-mgba/package.mk @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-mgba" +PKG_VERSION="747362c02d2e71ee7c363e8dcb240925be8af906" +PKG_SHA256="9a49e66b28296f11e04161dacf8cfc89f113504b87f40f5857a884d513c394a8" +PKG_LICENSE="MPLv2.0" +PKG_SITE="https://github.com/libretro/mgba" +PKG_URL="https://github.com/libretro/mgba/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="mGBA Game Boy Advance Emulator" +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="mgba_libretro.so" +PKG_LIBPATH="../${PKG_LIBNAME}" +PKG_LIBVAR="MGBA_LIB" + +PKG_MAKE_OPTS_TARGET="-C ../ -f Makefile.libretro" + +if [ "${ARCH}" = "arm" ]; then + PKG_MAKE_OPTS_TARGET+=" platform=unix-armv" +fi + +if target_has_feature neon; then + PKG_MAKE_OPTS_TARGET+=" HAVE_NEON=1" +fi + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-mrboom/package.mk b/packages/emulation/libretro-mrboom/package.mk new file mode 100644 index 0000000000..f1bbad4c71 --- /dev/null +++ b/packages/emulation/libretro-mrboom/package.mk @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-mrboom" +PKG_VERSION="256caa125cdb94d99eea5a98d6b9bb14f90c34ff" +PKG_SHA256="8f41a29cd454a25ca9d828e2107000de88366f58f42cc51843e0f849574363eb" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/libretro/mrboom-libretro" +PKG_URL="https://github.com/kodi-game/mrboom-libretro/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Mr.Boom is a 8 players Bomberman clone for RetroArch/Libretro" +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="mrboom_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="MRBOOM_LIB" + +PKG_MAKE_OPTS_TARGET="" + +if target_has_feature neon; then + PKG_MAKE_OPTS_TARGET+=" HAVE_NEON=1" +fi + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-nestopia/package.mk b/packages/emulation/libretro-nestopia/package.mk new file mode 100644 index 0000000000..c3375be5d0 --- /dev/null +++ b/packages/emulation/libretro-nestopia/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-nestopia" +PKG_VERSION="e7b65504ffc7f14fc5c74954d02b18f44c3aaf43" +PKG_SHA256="5942ae48749b0f98cab11f5913d9dff09a46c556aa6d9bb5851bdb27dee09907" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/nestopia" +PKG_URL="https://github.com/libretro/nestopia/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Libretro implementation of NEStopia. (Nintendo Entertainment System)" +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="nestopia_libretro.so" +PKG_LIBPATH="libretro/${PKG_LIBNAME}" +PKG_LIBVAR="NESTOPIA_LIB" + +PKG_MAKE_OPTS_TARGET="-C libretro/" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-nx/package.mk b/packages/emulation/libretro-nx/package.mk new file mode 100644 index 0000000000..496229a425 --- /dev/null +++ b/packages/emulation/libretro-nx/package.mk @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-nx" +PKG_VERSION="9adc032a5f6aa913d71d22042bb72cb11cf0f4a2" +PKG_SHA256="bc065a4f82f3644888f01fcaca482e1ead03055df03d8453bd8efed62c176d26" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/libretro/nxengine-libretro" +PKG_URL="https://github.com/libretro/nxengine-libretro/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Port of NxEngine to libretro - Cave Story game engine clone" +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="nxengine_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="NX_LIB" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake + + mkdir -p ${SYSROOT_PREFIX}/usr/share/retroarch/system/nxengine + cp -vr datafiles/* ${SYSROOT_PREFIX}/usr/share/retroarch/system/nxengine +} diff --git a/packages/emulation/libretro-o2em/package.mk b/packages/emulation/libretro-o2em/package.mk new file mode 100644 index 0000000000..c6ab31085a --- /dev/null +++ b/packages/emulation/libretro-o2em/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-o2em" +PKG_VERSION="3ba4231c1dc8dcdf487428712856b790d2e4b8f3" +PKG_SHA256="a2aff1f017600eb3478a0e78b68d6bcf576c86164f75c0fdd05cae4b2af55eae" +PKG_LICENSE="Artistic-2.0" +PKG_SITE="https://github.com/libretro/libretro-o2em" +PKG_URL="https://github.com/libretro/libretro-o2em/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Port of O2EM to the libretro API, an Odyssey 2 / VideoPac emulator." +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="o2em_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="O2EM_LIB" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-opera/package.mk b/packages/emulation/libretro-opera/package.mk new file mode 100644 index 0000000000..8e1554d5c4 --- /dev/null +++ b/packages/emulation/libretro-opera/package.mk @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-opera" +PKG_VERSION="67a29e60a4d194b675c9272b21b61eaa022f3ba3" +PKG_SHA256="e4135d62160f84d3bc287d165ef514a3e4ea31b759888ee29bde05e8c899b666" +PKG_LICENSE="LGPL with additional notes" +PKG_SITE="https://github.com/libretro/opera-libretro" +PKG_URL="https://github.com/libretro/opera-libretro/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Port of 4DO/libfreedo to libretro." +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="opera_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="OPERA_LIB" + +pre_make_target() { + PKG_MAKE_OPTS_TARGET="CC=${CC} CXX=${CXX} AR=${AR}" +} + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-opera/patches/libretro-opera-995.01-crosscompile.patch b/packages/emulation/libretro-opera/patches/libretro-opera-995.01-crosscompile.patch new file mode 100644 index 0000000000..7794cad7cf --- /dev/null +++ b/packages/emulation/libretro-opera/patches/libretro-opera-995.01-crosscompile.patch @@ -0,0 +1,139 @@ +diff --git a/Makefile b/Makefile +index c62fee2..49b0e98 100644 +--- a/Makefile ++++ b/Makefile +@@ -49,8 +49,8 @@ unixpath = $(subst \,/,$1) + unixcygpath = /$(subst :,,$(call unixpath,$1)) + + ifneq (,$(findstring unix,$(platform))) +- AR = ${CC_PREFIX}ar +- CC = ${CC_PREFIX}gcc ++ AR ?= ${CC_PREFIX}ar ++ CC ?= ${CC_PREFIX}gcc + + TARGET := $(TARGET_NAME)_libretro.so + fpic := -fPIC +@@ -138,8 +138,8 @@ else ifeq ($(platform), classic_armv7_a7) + + # ARM + else ifneq (,$(findstring armv,$(platform))) +- AR = ${CC_PREFIX}ar +- CC = ${CC_PREFIX}gcc ++ AR ?= ${CC_PREFIX}ar ++ CC ?= ${CC_PREFIX}gcc + + TARGET := $(TARGET_NAME)_libretro.so + fpic := -fPIC +@@ -181,9 +181,9 @@ ifeq ($(IOSSDK),) + IOSSDK := $(shell xcodebuild -version -sdk iphoneos Path) + endif + ifeq ($(platform),ios-arm64) +- CC = cc -arch arm64 -isysroot $(IOSSDK) -stdlib=libc++ ++ CC ?= cc -arch arm64 -isysroot $(IOSSDK) -stdlib=libc++ + else +- CC = cc -arch armv7 -isysroot $(IOSSDK) ++ CC ?= cc -arch armv7 -isysroot $(IOSSDK) + endif + ifeq ($(platform),$(filter $(platform),ios9 ios-arm64)) + MINVERSION = -miphoneos-version-min=8.0 +@@ -216,18 +216,18 @@ else ifeq ($(platform), qnx) + TARGET := $(TARGET_NAME)_libretro_$(platform).so + fpic := -fPIC + SHARED := -shared -Wl,--no-undefined -Wl,--version-script=link.T +- CC = qcc -Vgcc_ntoarmv7le ++ CC ?= qcc -Vgcc_ntoarmv7le + else ifeq ($(platform), ps3) + TARGET := $(TARGET_NAME)_libretro_$(platform).a +- CC = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-gcc.exe +- AR = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-ar.exe ++ CC ?= $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-gcc.exe ++ AR ?= $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-ar.exe + STATIC_LINKING = 1 + FLAGS += -DMSB_FIRST -D__CELLOS_LV2__ + OLD_GCC = 1 + else ifeq ($(platform), sncps3) + TARGET := $(TARGET_NAME)_libretro_ps3.a +- CC = $(CELL_SDK)/host-win32/sn/bin/ps3ppusnc.exe +- AR = $(CELL_SDK)/host-win32/sn/bin/ps3snarl.exe ++ CC ?= $(CELL_SDK)/host-win32/sn/bin/ps3ppusnc.exe ++ AR ?= $(CELL_SDK)/host-win32/sn/bin/ps3snarl.exe + STATIC_LINKING = 1 + FLAGS += -DMSB_FIRST + NO_GCC = 1 +@@ -235,25 +235,25 @@ else ifeq ($(platform), sncps3) + # PSP1 + else ifeq ($(platform), psp1) + TARGET := $(TARGET_NAME)_libretro_$(platform).a +- CC = psp-gcc$(EXE_EXT) +- AR = psp-ar$(EXE_EXT) ++ CC ?= psp-gcc$(EXE_EXT) ++ AR ?= psp-ar$(EXE_EXT) + STATIC_LINKING = 1 + FLAGS += -G0 + + # Vita + else ifeq ($(platform), vita) + TARGET := $(TARGET_NAME)_libretro_$(platform).a +- CC = arm-vita-eabi-gcc$(EXE_EXT) +- AR = arm-vita-eabi-ar$(EXE_EXT) ++ CC ?= arm-vita-eabi-gcc$(EXE_EXT) ++ AR ?= arm-vita-eabi-ar$(EXE_EXT) + STATIC_LINKING = 1 + FLAGS += -DVITA + + # CTR (3DS) + else ifeq ($(platform), ctr) + TARGET := $(TARGET_NAME)_libretro_$(platform).a +- CC = $(DEVKITARM)/bin/arm-none-eabi-gcc$(EXE_EXT) +- CXX = $(DEVKITARM)/bin/arm-none-eabi-g++$(EXE_EXT) +- AR = $(DEVKITARM)/bin/arm-none-eabi-ar$(EXE_EXT) ++ CC ?= $(DEVKITARM)/bin/arm-none-eabi-gcc$(EXE_EXT) ++ CXX ?=$(DEVKITARM)/bin/arm-none-eabi-g++$(EXE_EXT) ++ AR ?= $(DEVKITARM)/bin/arm-none-eabi-ar$(EXE_EXT) + FLAGS += -march=armv6k -mtune=mpcore -mfloat-abi=hard + FLAGS += -Wall -mword-relocations + FLAGS += -fomit-frame-pointer -ffast-math +@@ -311,8 +311,8 @@ else ifeq ($(platform), emscripten) + # Windows MSVC 2003 Xbox 1 + else ifeq ($(platform), xbox1_msvc2003) + TARGET := $(TARGET_NAME)_libretro_xdk1.lib +-CC = CL.exe +-LD = lib.exe ++CC ?= CL.exe ++LD ?= lib.exe + + export INCLUDE := $(XDK)/xbox/include + export LIB := $(XDK)/xbox/lib +@@ -325,8 +325,8 @@ HAS_GCC := 0 + else ifeq ($(platform), xbox360_msvc2010) + TARGET := $(TARGET_NAME)_libretro_xdk360.lib + MSVCBINDIRPREFIX = $(XEDK)/bin/win32 +-CC = "$(MSVCBINDIRPREFIX)/cl.exe" +-LD = "$(MSVCBINDIRPREFIX)/lib.exe" ++CC ?= "$(MSVCBINDIRPREFIX)/cl.exe" ++LD ?= "$(MSVCBINDIRPREFIX)/lib.exe" + + export INCLUDE := $(XEDK)/include/xbox + export LIB := $(XEDK)/lib/xbox +@@ -461,9 +461,9 @@ else ifneq (,$(findstring windows_msvc2017,$(platform))) + + TargetArchMoniker = $(subst $(WinPartition)_,,$(PlatformSuffix)) + +- CC = cl.exe +- CXX = cl.exe +- LD = link.exe ++ CC ?= cl.exe ++ CXX ?= cl.exe ++ LD ?= link.exe + + reg_query = $(call filter_out2,$(subst $2,,$(shell reg query "$2" -v "$1" 2>nul))) + fix_path = $(subst $(SPACE),\ ,$(subst \,/,$1)) +@@ -617,7 +617,7 @@ ifeq ($(STATIC_LINKING),1) + LD ?= lib.exe + STATIC_LINKING=0 + else +- LD = link.exe ++ LD ?= link.exe + endif + else + LD = $(CC) diff --git a/packages/emulation/libretro-pcsx-rearmed/package.mk b/packages/emulation/libretro-pcsx-rearmed/package.mk new file mode 100644 index 0000000000..fcce98a94f --- /dev/null +++ b/packages/emulation/libretro-pcsx-rearmed/package.mk @@ -0,0 +1,56 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-pcsx-rearmed" +PKG_VERSION="67881efbca82517dd6044fed1bb4ea2a724940f5" +PKG_SHA256="4e040e24c447ad7635961b579d1192dd5112404f317fe36d4f8cd65232aad5bc" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/pcsx_rearmed" +PKG_URL="https://github.com/libretro/pcsx_rearmed/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="ARM optimized PCSX fork" +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="pcsx_rearmed_libretro.so" +PKG_LIBPATH="../${PKG_LIBNAME}" +PKG_LIBVAR="PCSX-REARMED_LIB" + +PKG_MAKE_OPTS_TARGET="-f Makefile.libretro -C ../" + +if [ "${OPENGL_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL}" +fi + +if [ "${OPENGLES_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" +fi + +if [ "${VULKAN_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${VULKAN}" +fi + +if [ "${ARCH}" = "arm" ]; then + PKG_MAKE_OPTS_TARGET+=" DYNAREC=ari64" + if target_has_feature neon; then + PKG_MAKE_OPTS_TARGET+=" HAVE_NEON_ASM=1 BUILTIN_GPU=neon" + else + PKG_MAKE_OPTS_TARGET+=" HAVE_NEON_ASM=0 BUILTIN_GPU=unai" + fi + if [ "${DEVICE}" = "OdroidGoAdvance" ]; then + sed -e "s|armv8-a|armv8-a+crc|" \ + -i ../Makefile.libretro + PKG_MAKE_OPTS_TARGET+=" platform=classic_armv8_a35" + else + PKG_MAKE_OPTS_TARGET+=" platform=unix" + fi +elif [ "${ARCH}" = "aarch64" ]; then + PKG_MAKE_OPTS_TARGET+=" platform=unix DYNAREC=ari64" +else + PKG_MAKE_OPTS_TARGET+=" platform=unix DYNAREC=none" +fi + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-picodrive/package.mk b/packages/emulation/libretro-picodrive/package.mk new file mode 100644 index 0000000000..b0ac7f6801 --- /dev/null +++ b/packages/emulation/libretro-picodrive/package.mk @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-picodrive" +PKG_VERSION="d96dd4cd76576a557c9e902b5f1e3f5f9dc22e3a" +PKG_SHA256="90db059f7b448a13f03a380519a7d4fec63a923d14430163c31958aeb9f1ec51" +PKG_LICENSE="MAME" +PKG_SITE="https://github.com/libretro/picodrive" +PKG_URL="https://github.com/kodi-game/picodrive/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain ${PKG_NAME}:host" +PKG_DEPENDS_HOST="toolchain:host" +PKG_LONGDESC="Libretro implementation of PicoDrive. (Sega Megadrive/Genesis/Sega Master System/Sega GameGear/Sega CD/32X)" +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="picodrive_libretro.so" +PKG_LIBPATH="../${PKG_LIBNAME}" +PKG_LIBVAR="PICODRIVE_LIB" + +PKG_MAKE_OPTS_TARGET="-f Makefile.libretro -C ../" + +make_host() { + if [ "${ARCH}" != "x86_64" ]; then + make -C ../cpu/cyclone CONFIG_FILE=../cyclone_config.h + fi +} + +makeinstall_host() { + : # nothing to do +} + +pre_make_target() { + CFLAGS+=" -I./" +} + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-picodrive/patches/picodrive-01-remove_temporary_getoffs.patch b/packages/emulation/libretro-picodrive/patches/picodrive-01-remove_temporary_getoffs.patch new file mode 100644 index 0000000000..3fd0745779 --- /dev/null +++ b/packages/emulation/libretro-picodrive/patches/picodrive-01-remove_temporary_getoffs.patch @@ -0,0 +1,9 @@ +diff --git a/tools/mkoffsets.sh b/tools/mkoffsets.sh +index d9a8db5..b82d6eb 100755 +--- a/tools/mkoffsets.sh ++++ b/tools/mkoffsets.sh +@@ -165,3 +165,4 @@ get_define OFS_SH2_ SH2_ p_rom ; echo "$line" >>$fn + get_define OFS_SH2_ SH2_ p_dram ; echo "$line" >>$fn + get_define OFS_SH2_ SH2_ p_drcblk_da ; echo "$line" >>$fn + get_define OFS_SH2_ SH2_ p_drcblk_ram ; echo "$line" >>$fn ++rm -f /tmp/getoffs.* diff --git a/packages/emulation/libretro-pokemini/package.mk b/packages/emulation/libretro-pokemini/package.mk new file mode 100644 index 0000000000..94e5c10f4f --- /dev/null +++ b/packages/emulation/libretro-pokemini/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-pokemini" +PKG_VERSION="78656d4615691c393e65e48672ce5fff5b1f97d3" +PKG_SHA256="ded9849c2bc8c3b9ca363202324760f4d967f1536eb557364ef94e757fa675d2" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/libretro/pokemini" +PKG_URL="https://github.com/libretro/PokeMini/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Obscure nintendo handheld emulator (functional,no color files or savestates currently)" +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="pokemini_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="POKEMINI_LIB" + +PKG_MAKE_OPTS_TARGET="-f Makefile.libretro" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-prboom/package.mk b/packages/emulation/libretro-prboom/package.mk new file mode 100644 index 0000000000..dd2039565d --- /dev/null +++ b/packages/emulation/libretro-prboom/package.mk @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-prboom" +PKG_VERSION="d25ccfb9739069824d8fff99e3ae78a58a09df01" +PKG_SHA256="b22b6449a6c8219a70abb13cc3b1170debe16eea076c907ad8c60f33f1e5b7d4" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/libretro-prboom" +PKG_URL="https://github.com/libretro/libretro-prboom/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="libretro implementation of Doom" +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="prboom_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="PRBOOM_LIB" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake + + mkdir -p ${SYSROOT_PREFIX}/usr/share/retroarch/system/ + cp -v prboom.wad ${SYSROOT_PREFIX}/usr/share/retroarch/system/ +} diff --git a/packages/emulation/libretro-prosystem/package.mk b/packages/emulation/libretro-prosystem/package.mk new file mode 100644 index 0000000000..2c75b18f6a --- /dev/null +++ b/packages/emulation/libretro-prosystem/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-prosystem" +PKG_VERSION="acae250da8d98b8b9707cd499e2a0bf6d8500652" +PKG_SHA256="5a376c6621678daff86977de12b1421f1599602683a8d7228f75281ab4274229" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/prosystem-libretro" +PKG_URL="https://github.com/libretro/prosystem-libretro/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Port of ProSystem to libretro." +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="prosystem_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="PROSYSTEM_LIB" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-quicknes/package.mk b/packages/emulation/libretro-quicknes/package.mk new file mode 100644 index 0000000000..8281679c86 --- /dev/null +++ b/packages/emulation/libretro-quicknes/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-quicknes" +PKG_VERSION="dbf19f73e3eb9701d1c7f5898f57c097e05c9fbd" +PKG_SHA256="3a2e3c564156a7e18b15b8ac04fc5aa10da3f44d8253a073cc42fdd74a1a48de" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/QuickNES_Core" +PKG_URL="https://github.com/libretro/QuickNES_Core/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="The QuickNES core library, originally by Shay Green, heavily modified" +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="quicknes_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="QUICKNES_LIB" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-sameboy/package.mk b/packages/emulation/libretro-sameboy/package.mk new file mode 100644 index 0000000000..2e6f44d253 --- /dev/null +++ b/packages/emulation/libretro-sameboy/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-sameboy" +PKG_VERSION="51433012a871a44555492273fd22f29867d12655" +PKG_SHA256="cb1b914ce29d250ed1b170b317c114106bdd9208d69100f3f761eeddd5fb472d" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/libretro/sameboy" +PKG_URL="https://github.com/libretro/SameBoy/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Gameboy and Gameboy Color emulator written in C" +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="sameboy_libretro.so" +PKG_LIBPATH="libretro/${PKG_LIBNAME}" +PKG_LIBVAR="SAMEBOY_LIB" + +PKG_MAKE_OPTS_TARGET="-C libretro/" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-scummvm/package.mk b/packages/emulation/libretro-scummvm/package.mk new file mode 100644 index 0000000000..d1f9cead2a --- /dev/null +++ b/packages/emulation/libretro-scummvm/package.mk @@ -0,0 +1,55 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-scummvm" +PKG_VERSION="7310d4e9f5d11553c6c5499911bd2f9b8ff3db3b" +PKG_SHA256="c764691df32d3670db2d5e90bb520940a0a4c4ceeed7e73b2faed50c8ab9aa13" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/libretro/scummvm" +PKG_URL="https://github.com/libretro/scummvm/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain faad2" +PKG_LONGDESC="ScummVM with libretro backend." +PKG_TOOLCHAIN="make" +PKG_LR_UPDATE_TAG="yes" + +PKG_LIBNAME="scummvm_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="SCUMMVM_LIB" + +PKG_MAKE_OPTS_TARGET="all" + +pre_make_target() { + CXXFLAGS+=" -DHAVE_POSIX_MEMALIGN=1" + + # use the system faad2 + INCLUDES+="-I$(get_install_dir faad2)/usr/include" + LIBS+=" -L$(get_install_dir faad2)/usr/lib -lfaad" + export USE_SYSTEM_faad=1 + + if [ "${DEVICE}" = "OdroidGoAdvance" ]; then + PKG_MAKE_OPTS_TARGET+=" platform=oga_a35_neon_hardfloat" + else + PKG_MAKE_OPTS_TARGET+=" platform=${TARGET_NAME}" + fi + + cd ${PKG_BUILD}/backends/platform/libretro +} + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + cp scummvm_libretro.info ${SYSROOT_PREFIX}/usr/lib/ + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake + + # unpack files to retroarch-system folder and create basic ini file + mkdir -p ${SYSROOT_PREFIX}/usr/share/retroarch/system + unzip scummvm.zip -d ${SYSROOT_PREFIX}/usr/share/retroarch/system + + cat <${SYSROOT_PREFIX}/usr/share/retroarch/system/scummvm.ini +[scummvm] +extrapath=/tmp/system/scummvm/extra +browser_lastpath=/tmp/system/scummvm/extra +themepath=/tmp/system/scummvm/theme +guitheme=scummmodern +EOF +} diff --git a/packages/emulation/libretro-scummvm/patches/0001-libretro-Fix-missing-library-version.patch b/packages/emulation/libretro-scummvm/patches/0001-libretro-Fix-missing-library-version.patch new file mode 100644 index 0000000000..9fa9ba600b --- /dev/null +++ b/packages/emulation/libretro-scummvm/patches/0001-libretro-Fix-missing-library-version.patch @@ -0,0 +1,25 @@ +From edd203bae0939789cf9f34281ad04f103b495e16 Mon Sep 17 00:00:00 2001 +From: Garrett Brown +Date: Tue, 17 Jan 2023 12:13:29 -0800 +Subject: [PATCH 1/2] libretro: Fix missing library version + +--- + backends/platform/libretro/src/libretro-core.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/backends/platform/libretro/src/libretro-core.cpp b/backends/platform/libretro/src/libretro-core.cpp +index 5b2830a..1aeb141 100644 +--- a/backends/platform/libretro/src/libretro-core.cpp ++++ b/backends/platform/libretro/src/libretro-core.cpp +@@ -748,7 +748,7 @@ void retro_get_system_info(struct retro_system_info *info) { + #else + #define __GIT_VERSION "" + #endif +- info->library_version = __GIT_VERSION; ++ info->library_version = SCUMMVM_VERSION; + info->valid_extensions = "scummvm"; + info->need_fullpath = true; + info->block_extract = false; +-- +2.34.1 + diff --git a/packages/emulation/libretro-scummvm/patches/0002-libretro-Move-scummvm.ini-to-writable-save-directory.patch b/packages/emulation/libretro-scummvm/patches/0002-libretro-Move-scummvm.ini-to-writable-save-directory.patch new file mode 100644 index 0000000000..72d1e0ecb4 --- /dev/null +++ b/packages/emulation/libretro-scummvm/patches/0002-libretro-Move-scummvm.ini-to-writable-save-directory.patch @@ -0,0 +1,29 @@ +From 9d4e078e96c950f6b2d8977d08390844cd9aa62c Mon Sep 17 00:00:00 2001 +From: Garrett Brown +Date: Thu, 28 Oct 2021 16:00:20 -0700 +Subject: [PATCH 2/2] libretro: Move scummvm.ini to writable save directory + +--- + backends/platform/libretro/src/libretro-os-utils.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/backends/platform/libretro/src/libretro-os-utils.cpp b/backends/platform/libretro/src/libretro-os-utils.cpp +index 27a442d..3b52467 100644 +--- a/backends/platform/libretro/src/libretro-os-utils.cpp ++++ b/backends/platform/libretro/src/libretro-os-utils.cpp +@@ -57,10 +57,10 @@ void OSystem_libretro::getTimeAndDate(Ti + } + + Common::Path OSystem_libretro::getDefaultConfigFileName() { +- if (s_systemDir.empty()) ++ if (s_saveDir.empty()) + return Common::Path("scummvm.ini"); + else +- return Common::Path(s_systemDir).appendComponent("scummvm.ini"); ++ return Common::Path(s_saveDir).appendComponent("scummvm.ini"); + } + + void OSystem_libretro::logMessage(LogMessageType::Type type, const char *message) { +-- +2.34.1 + diff --git a/packages/emulation/libretro-scummvm/patches/0003-libretro-fix-armv7-GCC-15.1-internal-compiler-error.patch b/packages/emulation/libretro-scummvm/patches/0003-libretro-fix-armv7-GCC-15.1-internal-compiler-error.patch new file mode 100644 index 0000000000..360ca9d8d6 --- /dev/null +++ b/packages/emulation/libretro-scummvm/patches/0003-libretro-fix-armv7-GCC-15.1-internal-compiler-error.patch @@ -0,0 +1,22 @@ +From e566a6432fd1951417bf78280cc7c741957fc419 Mon Sep 17 00:00:00 2001 +From: Giovanni Cascione +Date: Thu, 22 May 2025 20:51:47 +0200 +Subject: [PATCH] LIBRETRO: BUILD: fix armv7 GCC 15.1 internal compiler error + +--- + backends/platform/libretro/Makefile | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/backends/platform/libretro/Makefile b/backends/platform/libretro/Makefile +index 0181825bfbbc..383a25cab706 100644 +--- a/backends/platform/libretro/Makefile ++++ b/backends/platform/libretro/Makefile +@@ -552,6 +552,8 @@ ifneq (,$(findstring $(platform), wiiu vita)) + DEFINES += -Os + else ifneq (,$(findstring $(platform), ios osx)) + DEFINES += -O1 ++else ifneq (,$(findstring armv7, $(platform))) # fixes a GCC 15.1 internal compiler error. TODO check if it is fixed in GCC newer releases. ++ DEFINES += -O1 + else ifneq (,$(findstring $(platform), msvc genode rpi)) + DEFINES += -O2 + else diff --git a/packages/emulation/libretro-snes9x/package.mk b/packages/emulation/libretro-snes9x/package.mk new file mode 100644 index 0000000000..c630be6a9e --- /dev/null +++ b/packages/emulation/libretro-snes9x/package.mk @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-snes9x" +PKG_VERSION="49f484569ff2aec7ff08e7598a97d6c9e6eae72d" +PKG_SHA256="54036e672494f38d7a12a242ed9ddf124685c2cf3563ffc3ebf07c4882405cb0" +PKG_LICENSE="Non-commercial" +PKG_SITE="https://github.com/libretro/snes9x" +PKG_URL="https://github.com/libretro/snes9x/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Snes9x - Portable Super Nintendo Entertainment System (TM) emulator" +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="snes9x_libretro.so" +PKG_LIBPATH="libretro/${PKG_LIBNAME}" +PKG_LIBVAR="SNES9X_LIB" + +PKG_MAKE_OPTS_TARGET="-C libretro/" + +if [ "${DEVICE}" = "OdroidGoAdvance" ]; then + PKG_MAKE_OPTS_TARGET+=" platform=classic_armv8_a35" +fi + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-snes9x2002/package.mk b/packages/emulation/libretro-snes9x2002/package.mk new file mode 100644 index 0000000000..3ed6cdcb09 --- /dev/null +++ b/packages/emulation/libretro-snes9x2002/package.mk @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-snes9x2002" +PKG_VERSION="a0709ec7dcd6de2fbebb43106bd757b649e3b7cf" +PKG_SHA256="58abd84309d0fafacccd94920aa4b99eeb935c4157971487c1052b6104de2412" +PKG_LICENSE="Non-commercial" +PKG_SITE="https://github.com/libretro/snes9x2002" +PKG_URL="https://github.com/libretro/snes9x2002/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Snes9x 2002. Port of SNES9x 1.39 for libretro (was previously called PocketSNES). Heavily optimized for ARM." +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="snes9x2002_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="SNES9X2002_LIB" + +PKG_MAKE_OPTS_TARGET="platform=unix" + +if [ "${PROJECT}" = "RPi" ] && [ "${DEVICE}" = "RPi" -o "${DEVICE}" = "GPICase" ]; then + PKG_MAKE_OPTS_TARGET+=" ARM_ASM=1" +fi + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-snes9x2010/package.mk b/packages/emulation/libretro-snes9x2010/package.mk new file mode 100644 index 0000000000..debe0f98f0 --- /dev/null +++ b/packages/emulation/libretro-snes9x2010/package.mk @@ -0,0 +1,30 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-snes9x2010" +PKG_VERSION="f9ae8fd28b13070a945a829ccf41cbf90a21d0f7" +PKG_SHA256="730aa78b64c5c214454361c517b351ce7d225a89dd51705ebb94a8fedc3bd3e3" +PKG_LICENSE="Non-commercial" +PKG_SITE="https://github.com/libretro/snes9x2010" +PKG_URL="https://github.com/libretro/snes9x2010/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_LONGDESC="Snes9x 2010. Port of Snes9x 1.52+ to Libretro (previously called SNES9x Next). Rewritten in C and several optimizations and speedhacks." +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="snes9x2010_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="SNES9X2010_LIB" + +PKG_MAKE_OPTS_TARGET="-f Makefile.libretro" + +if [ "${PROJECT}" = "Rockchip" -a "${DEVICE}" = "OdroidGoAdvance" ]; then + PKG_MAKE_OPTS_TARGET+=" platform=goa_armv8_a35" +fi + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-stella/package.mk b/packages/emulation/libretro-stella/package.mk new file mode 100644 index 0000000000..de1fa6c369 --- /dev/null +++ b/packages/emulation/libretro-stella/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-stella" +PKG_VERSION="db3a38be7b77d5929daf00c5eba6ead167e974ec" +PKG_SHA256="f1ddd4826cedb16c3723e798e9b4bb21564080ef561f742d88120f1f999c6888" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/stella-emu/stella" +PKG_URL="https://github.com/stella-emu/stella/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Stella is a multi-platform Atari 2600 VCS emulator released under the GNU General Public License (GPL)." +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="stella_libretro.so" +PKG_LIBPATH="../src/os/libretro/${PKG_LIBNAME}" +PKG_LIBVAR="STELLA_LIB" + +PKG_MAKE_OPTS_TARGET="-C ../src/os/libretro -f Makefile" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-stella/patches/stella-01-do_not-use_static_libgcc_libstdc++.patch b/packages/emulation/libretro-stella/patches/stella-01-do_not-use_static_libgcc_libstdc++.patch new file mode 100644 index 0000000000..fd600eb236 --- /dev/null +++ b/packages/emulation/libretro-stella/patches/stella-01-do_not-use_static_libgcc_libstdc++.patch @@ -0,0 +1,21 @@ +diff --git a/src/libretro/Makefile b/src/libretro/Makefile +index a170992343..6a828521e5 100644 +--- a/src/os/libretro/Makefile ++++ b/src/os/libretro/Makefile +@@ -57,7 +57,6 @@ + CXXFLAGS += -DGIT_VERSION=\"$(GIT_VERSION)\" + endif + +-GET_STATIC_ARG=$(if $(filter $(shell $(CXX) -print-file-name=$1.a),$1.a),,-static-$1) + # Unix + ifneq (,$(findstring unix,$(platform))) + GPP_MAJOR := $(shell $(CXX) -dumpversion | cut -d '.' -f 1) +@@ -65,7 +64,7 @@ + $(error Unable to determine $(CXX) version) + endif + CXXFLAGS += $(LTO) +- LDFLAGS += $(LTO) $(PTHREAD_FLAGS) $(call GET_STATIC_ARG,libgcc) $(call GET_STATIC_ARG,libstdc++) ++ LDFLAGS += $(LTO) $(PTHREAD_FLAGS) + TARGET := $(TARGET_NAME)_libretro.so + fpic := -fPIC + ifneq ($(findstring SunOS,$(shell uname -a)),) diff --git a/packages/emulation/libretro-supafaust/package.mk b/packages/emulation/libretro-supafaust/package.mk new file mode 100644 index 0000000000..60a9e02a55 --- /dev/null +++ b/packages/emulation/libretro-supafaust/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-supafaust" +PKG_VERSION="e25f66765938d33f9ad5850e8d6cd597e55b7299" +PKG_SHA256="0b0ff644b780d1565e8f097998f371b1a4255213846c2082d8e8c143d0868ef1" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/supafaust" +PKG_URL="https://github.com/libretro/supafaust/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="SNES emulator for multicore ARM Cortex A7,A9,A15,A53 Linux platforms" +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="mednafen_supafaust_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="SUPAFAUST_LIB" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-swanstation/package.mk b/packages/emulation/libretro-swanstation/package.mk new file mode 100644 index 0000000000..aea81872af --- /dev/null +++ b/packages/emulation/libretro-swanstation/package.mk @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-swanstation" +PKG_VERSION="fc37fce91dedeba6e4007012cfed8de626fb45cf" +PKG_SHA256="d0b683021c079105c1f14be868390a6923614afdd36e6486a3b6b71b049922f4" +PKG_LICENSE="GPL-3.0-or-later" +PKG_SITE="https://github.com/kodi-game/swanstation" +PKG_URL="https://github.com/kodi-game/swanstation/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="SwanStation is a Libretro core implementation of DuckStation, which is an emulator of the Sony PlayStation console." +PKG_TOOLCHAIN="cmake" + +PKG_LIBNAME="swanstation_libretro.so" +PKG_LIBPATH="./${PKG_LIBNAME}" +PKG_LIBVAR="SWANSTATION_LIB" + +if [ "${OPENGL_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL}" +fi + +if [ "${OPENGLES_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" +fi + +if [ "${VULKAN_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${VULKAN}" +fi + +PKG_CMAKE_OPTS_TARGET="-DBUILD_NOGUI_FRONTEND=OFF \ + -DBUILD_QT_FRONTEND=OFF \ + -DBUILD_LIBRETRO_CORE=ON \ + -DENABLE_DISCORD_PRESENCE=OFF \ + -DUSE_DRMKMS=ON" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" > ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-tgbdual/package.mk b/packages/emulation/libretro-tgbdual/package.mk new file mode 100644 index 0000000000..d6944e2880 --- /dev/null +++ b/packages/emulation/libretro-tgbdual/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-tgbdual" +PKG_VERSION="8d305769eebd67266c284558f9d3a30498894d3d" +PKG_SHA256="c9286b91fd7840902075601749507e08f9e734aae5a9ccc37805324a348295c5" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/tgbdual-libretro" +PKG_URL="https://github.com/libretro/tgbdual-libretro/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="libretro port of TGB Dual" +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="tgbdual_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="TGBDUAL_LIB" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-tyrquake/package.mk b/packages/emulation/libretro-tyrquake/package.mk new file mode 100644 index 0000000000..f527b56054 --- /dev/null +++ b/packages/emulation/libretro-tyrquake/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-tyrquake" +PKG_VERSION="5486f35371ba7b495d00094e2c343b99f2cc0fa9" +PKG_SHA256="5defdaf1a9a708fa8ef1e630b508621e4541e060a07416686809372ae4d849ba" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/tyrquake" +PKG_URL="https://github.com/libretro/tyrquake/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Libretro port of Tyrquake (Quake 1 engine)" +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="tyrquake_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="TYRQUAKE_LIB" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-uae/package.mk b/packages/emulation/libretro-uae/package.mk new file mode 100644 index 0000000000..6c1835639d --- /dev/null +++ b/packages/emulation/libretro-uae/package.mk @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-uae" +PKG_VERSION="c60e42ef9ad474518d4be859b7c1da2c0c7e1d6f" +PKG_SHA256="933fd83ad42ceb558c2ae9c0d2ea0a7bb68f05f8ab828951bcabfe400ce8c50f" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/libretro/libretro-uae" +PKG_URL="https://github.com/libretro/libretro-uae/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Portable Commodore Amiga Emulator" +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="puae_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="UAE_LIB" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake + + mkdir -p ${SYSROOT_PREFIX}/usr/share/retroarch/system/uae_data + cp -vR ${PKG_BUILD}/sources/uae_data/* ${SYSROOT_PREFIX}/usr/share/retroarch/system/uae_data/ +} diff --git a/packages/emulation/libretro-uae4arm/package.mk b/packages/emulation/libretro-uae4arm/package.mk new file mode 100644 index 0000000000..98c0bd7f73 --- /dev/null +++ b/packages/emulation/libretro-uae4arm/package.mk @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-uae4arm" +PKG_VERSION="177c2f0e892adf2603ada9b150e31beffe0f76c3" +PKG_SHA256="0be54f926740333d1b2832d4bb78e6b1e47409c75f40e99e544b7265327c0708" +PKG_ARCH="arm aarch64" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/Chips-fr/uae4arm-rpi" +PKG_URL="https://github.com/Chips-fr/uae4arm-rpi/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain flac mpg123 zlib" +PKG_LONGDESC="Port of uae4arm for libretro (rpi/android)" +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="uae4arm_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="UAE4ARM_LIB" + +PKG_MAKE_OPTS_TARGET="-f Makefile.libretro" + +if [ "${ARCH}" = "aarch64" ]; then + PKG_MAKE_OPTS_TARGET+=" platform=unix-aarch64" +elif target_has_feature neon; then + PKG_MAKE_OPTS_TARGET+=" platform=unix-neon" +else + PKG_MAKE_OPTS_TARGET+=" platform=unix" +fi + +pre_configure_target() { + sed -e "s|LDFLAGS := -lz -lpthread -lFLAC -lmpg123 -ldl|& -L$(get_install_dir mpg123)/usr/lib|" \ + -i ${PKG_BUILD}/Makefile.libretro +} + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake + + cp -v capsimg.so ${SYSROOT_PREFIX}/usr/lib/ +} diff --git a/packages/emulation/libretro-vbam/package.mk b/packages/emulation/libretro-vbam/package.mk new file mode 100644 index 0000000000..ac8a128bbf --- /dev/null +++ b/packages/emulation/libretro-vbam/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-vbam" +PKG_VERSION="e8494b56d12216b571f08c4283523c08e2d3cb9f" +PKG_SHA256="e201a48843b82334b48590cc7801c1d11637bc30921eab40f003f2df17273c89" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/visualboyadvance-m/visualboyadvance-m" +PKG_URL="https://github.com/visualboyadvance-m/visualboyadvance-m/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="VBA-M with libretro integration" +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="vbam_libretro.so" +PKG_LIBPATH="../src/libretro/${PKG_LIBNAME}" +PKG_LIBVAR="VBAM_LIB" + +PKG_MAKE_OPTS_TARGET="-C ../src/libretro/" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-vecx/package.mk b/packages/emulation/libretro-vecx/package.mk new file mode 100644 index 0000000000..03995e7e90 --- /dev/null +++ b/packages/emulation/libretro-vecx/package.mk @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-vecx" +PKG_VERSION="841229a6a81a0461d08af6488f252dcec5266c6a" +PKG_SHA256="d564413e9611b16e49e076cadd719587b6712c3cb435eaf90597c2db157546f4" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/libretro/libretro-vecx" +PKG_URL="https://github.com/libretro/libretro-vecx/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="libretro adaptation of vecx" +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="vecx_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="VECX_LIB" + +PKG_MAKE_OPTS_TARGET="-f Makefile.libretro" + +if [ "${OPENGL_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL}" +fi + +if [ "${OPENGL_SUPPORT}" = "yes" ] && + [ "${DISPLAYSERVER}" != "x11" ]; then + PKG_MAKE_OPTS_TARGET+=" USE_GLVND=1" +fi + +if [ "${OPENGLES_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" +fi + +if [ "${VULKAN_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${VULKAN}" +fi + +if [ "${PROJECT}" = "RPi" ]; then + if [ "${OPENGLES}" = "mesa" ]; then + PKG_MAKE_OPTS_TARGET+=" platform=rpi-mesa" + else + PKG_MAKE_OPTS_TARGET+=" platform=rpi" + fi +elif [ "${OPENGLES_SUPPORT}" = "yes" ]; then + PKG_MAKE_OPTS_TARGET+=" HAS_GLES=1 GLES=1" +fi + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-vice_x128/package.mk b/packages/emulation/libretro-vice_x128/package.mk new file mode 100644 index 0000000000..5160f50497 --- /dev/null +++ b/packages/emulation/libretro-vice_x128/package.mk @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2023-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-vice_x128" +PKG_VERSION="8afb6a3a407e5ee40d48df45031c615507dd094e" +PKG_SHA256="3d0f24ff795241d56678f6cffb78875c8ea0274dfeb59e83b919ab0cca946c6d" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/vice-libretro" +PKG_URL="https://github.com/libretro/vice-libretro/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Versatile Commodore 8-bit Emulator version" +PKG_TOOLCHAIN="manual" + +PKG_LIBNAME="vice_x128_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="VICE-X128_LIB" + +make_target() { + make EMUTYPE=x128 +} + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-vice_x64/package.mk b/packages/emulation/libretro-vice_x64/package.mk new file mode 100644 index 0000000000..1bb6f3461f --- /dev/null +++ b/packages/emulation/libretro-vice_x64/package.mk @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-vice_x64" +PKG_VERSION="8afb6a3a407e5ee40d48df45031c615507dd094e" +PKG_SHA256="3d0f24ff795241d56678f6cffb78875c8ea0274dfeb59e83b919ab0cca946c6d" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/vice-libretro" +PKG_URL="https://github.com/libretro/vice-libretro/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Versatile Commodore 8-bit Emulator version" +PKG_TOOLCHAIN="manual" + +PKG_LIBNAME="vice_x64_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="VICE-X64_LIB" + +make_target() { + make EMUTYPE=x64 +} + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-vice_xplus4/package.mk b/packages/emulation/libretro-vice_xplus4/package.mk new file mode 100644 index 0000000000..045382314e --- /dev/null +++ b/packages/emulation/libretro-vice_xplus4/package.mk @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2023-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-vice_xplus4" +PKG_VERSION="8afb6a3a407e5ee40d48df45031c615507dd094e" +PKG_SHA256="3d0f24ff795241d56678f6cffb78875c8ea0274dfeb59e83b919ab0cca946c6d" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/vice-libretro" +PKG_URL="https://github.com/libretro/vice-libretro/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Versatile Commodore 8-bit Emulator version" +PKG_TOOLCHAIN="manual" + +PKG_LIBNAME="vice_xplus4_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="VICE-XPLUS4_LIB" + +make_target() { + make EMUTYPE=xplus4 +} + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-vice_xvic/package.mk b/packages/emulation/libretro-vice_xvic/package.mk new file mode 100644 index 0000000000..b086876e8a --- /dev/null +++ b/packages/emulation/libretro-vice_xvic/package.mk @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2023-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-vice_xvic" +PKG_VERSION="8afb6a3a407e5ee40d48df45031c615507dd094e" +PKG_SHA256="3d0f24ff795241d56678f6cffb78875c8ea0274dfeb59e83b919ab0cca946c6d" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/vice-libretro" +PKG_URL="https://github.com/libretro/vice-libretro/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Versatile Commodore 8-bit Emulator version" +PKG_TOOLCHAIN="manual" + +PKG_LIBNAME="vice_xvic_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="VICE-XVIC_LIB" + +make_target() { + make EMUTYPE=xvic +} + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-virtualjaguar/package.mk b/packages/emulation/libretro-virtualjaguar/package.mk new file mode 100644 index 0000000000..24336d3a03 --- /dev/null +++ b/packages/emulation/libretro-virtualjaguar/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-virtualjaguar" +PKG_VERSION="48096c1f6f8b98cfff048a5cb4e6a86686631072" +PKG_SHA256="2192ff7d093a76420b5dea2c694e7681ec6d388f7dd5b3df62ddec5a700afbe2" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/libretro/virtualjaguar-libretro" +PKG_URL="https://github.com/libretro/virtualjaguar-libretro/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Port of Virtual Jaguar to Libretro" +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="virtualjaguar_libretro.so" +PKG_LIBPATH="${PKG_LIBNAME}" +PKG_LIBVAR="VIRTUALJAGUAR_LIB" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/libretro-yabause/package.mk b/packages/emulation/libretro-yabause/package.mk new file mode 100644 index 0000000000..ff6125d8b7 --- /dev/null +++ b/packages/emulation/libretro-yabause/package.mk @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libretro-yabause" +PKG_VERSION="c35712c5ed33e18d77097f2059a036e19d1d66f2" +PKG_SHA256="2c2485bf76de138cf8a46fa8dd460f46f21b3abb38a432578c7f18b46fa6807e" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/yabause" +PKG_URL="https://github.com/libretro/yabause/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Port of Yabause to libretro." +PKG_TOOLCHAIN="make" + +PKG_LIBNAME="yabause_libretro.so" +PKG_LIBPATH="yabause/src/libretro/${PKG_LIBNAME}" +PKG_LIBVAR="YABAUSE_LIB" + +PKG_MAKE_OPTS_TARGET="-C yabause/src/libretro" + +if [ "${OPENGL_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL}" +fi + +if [ "${OPENGLES_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" +fi + +if [ "${VULKAN_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${VULKAN}" +fi + +if [ "${ARCH}" = "arm" -o "${ARCH}" = "aarch64" ]; then + PKG_MAKE_OPTS_TARGET+=" HAVE_SSE=0" +fi + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME} + cp ${PKG_LIBPATH} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME} + echo "set(${PKG_LIBVAR} ${SYSROOT_PREFIX}/usr/lib/${PKG_LIBNAME})" >${SYSROOT_PREFIX}/usr/lib/cmake/${PKG_NAME}/${PKG_NAME}-config.cmake +} diff --git a/packages/emulation/rcheevos/package.mk b/packages/emulation/rcheevos/package.mk new file mode 100644 index 0000000000..ec3070825e --- /dev/null +++ b/packages/emulation/rcheevos/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="rcheevos" +PKG_VERSION="9.2.0" +PKG_SHA256="c8ed6ca74f905ea0c256250e46cced579922880001337e7c3d3d68179ad89d4e" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/RetroAchievements/rcheevos" +PKG_URL="https://github.com/RetroAchievements/rcheevos/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Library to parse and evaluate achievements and leaderboards for RetroAchievements" +PKG_BUILD_FLAGS="+pic" + +post_unpack() { + # rcheevos doesn't come with any build files, use a copy of the cmake file in + # game.libretro (depends/common/rcheevos/CMakeLists.txt) + cp "${PKG_DIR}/source/CMakeLists.txt" "${PKG_BUILD}" +} diff --git a/packages/emulation/rcheevos/source/CMakeLists.txt b/packages/emulation/rcheevos/source/CMakeLists.txt new file mode 100644 index 0000000000..3915d50119 --- /dev/null +++ b/packages/emulation/rcheevos/source/CMakeLists.txt @@ -0,0 +1,64 @@ +project(rcheevos) + +cmake_minimum_required(VERSION 3.10) + +# Disable Lua for now +add_definitions(-DRC_DISABLE_LUA) + +include_directories( + include +) + +add_library(${PROJECT_NAME}lib + src/rcheevos/alloc.c + src/rcheevos/compat.c + src/rcheevos/condition.c + src/rcheevos/condset.c + src/rcheevos/consoleinfo.c + src/rcheevos/format.c + src/rcheevos/lboard.c + src/rcheevos/memref.c + src/rcheevos/operand.c + src/rcheevos/richpresence.c + src/rcheevos/runtime.c + src/rcheevos/runtime_progress.c + src/rcheevos/trigger.c + src/rcheevos/value.c + src/rhash/cdreader.c + src/rhash/hash.c + src/rhash/md5.c + src/rurl/url.c +) + +#add_dependencies(rcheevos +# lua # TODO +#) + +#target_link_libraries(rcheevos +# lua +#) + +install(TARGETS + ${PROJECT_NAME}lib + ARCHIVE DESTINATION + lib + DESTINATION + lib +) + +install( + FILES + include/rcheevos.h + include/rconsoles.h + include/rhash.h + include/rurl.h + DESTINATION + include/${PROJECT_NAME} +) + +#install( +# DIRECTORY +# include +# DESTINATION +# include +#) diff --git a/packages/graphics/assimp/package.mk b/packages/graphics/assimp/package.mk new file mode 100644 index 0000000000..54584c9865 --- /dev/null +++ b/packages/graphics/assimp/package.mk @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="assimp" +PKG_VERSION="6.0.2" +PKG_SHA256="d1822d9a19c9205d6e8bc533bf897174ddb360ce504680f294170cc1d6319751" +PKG_LICENSE="BSD" +PKG_SITE="https://github.com/assimp/assimp" +PKG_URL="https://github.com/assimp/assimp/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain zlib" +PKG_LONGDESC="A library to import and export various 3d-model-formats including scene-post-processing to generate missing render data." + +PKG_CMAKE_OPTS_TARGET="-DASSIMP_BUILD_ASSIMP_TOOLS=OFF \ + -DASSIMP_BUILD_TESTS=OFF \ + -DASSIMP_WARNINGS_AS_ERRORS=OFF" diff --git a/packages/graphics/cairo/package.mk b/packages/graphics/cairo/package.mk new file mode 100644 index 0000000000..a0ae7f3c65 --- /dev/null +++ b/packages/graphics/cairo/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) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="cairo" +PKG_VERSION="1.18.4" +PKG_SHA256="445ed8208a6e4823de1226a74ca319d3600e83f6369f99b14265006599c32ccb" +PKG_LICENSE="LGPL" +PKG_SITE="https://cairographics.org/" +PKG_URL="https://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." + +configure_package() { + if [ "${DISPLAYSERVER}" = "x11" ]; then + PKG_DEPENDS_TARGET+=" libXrender libX11 mesa" + fi +} + +pre_configure_target() { + PKG_MESON_OPTS_TARGET="-Ddwrite=disabled \ + -Dfontconfig=enabled \ + -Dfreetype=enabled \ + -Dpng=enabled \ + -Dquartz=disabled \ + -Dtee=disabled \ + -Dxcb=disabled \ + -Dxlib-xcb=disabled \ + -Dzlib=enabled \ + -Dtests=disabled \ + -Dgtk2-utils=disabled \ + -Dglib=enabled \ + -Dspectre=disabled \ + -Dsymbol-lookup=disabled \ + -Dgtk_doc=false" + + if [ "${DISPLAYSERVER}" = "x11" ]; then + PKG_MESON_OPTS_TARGET+=" -Dxlib=enabled" + else + PKG_MESON_OPTS_TARGET+=" -Dxlib=disabled" + fi +} diff --git a/packages/graphics/exiv2/package.mk b/packages/graphics/exiv2/package.mk new file mode 100644 index 0000000000..ab3890e4cb --- /dev/null +++ b/packages/graphics/exiv2/package.mk @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2024-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="exiv2" +PKG_VERSION="0.28.5" +PKG_SHA256="e1671f744e379a87ba0c984617406fdf8c0ad0c594e5122f525b2fb7c28d394d" +PKG_LICENSE="GPL-2.0-or-later" +PKG_SITE="https://exiv2.org" +PKG_URL="https://github.com/Exiv2/exiv2/archive/refs/tags/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Exiv2 is a Cross-platform C++ library to manage image metadata." +PKG_TOOLCHAIN="cmake" + +PKG_CMAKE_OPTS_TARGET="-DBUILD_SHARED_LIBS=OFF \ + -DEXIV2_ENABLE_WEBREADY=OFF \ + -DEXIV2_ENABLE_XMP=OFF \ + -DEXIV2_ENABLE_CURL=OFF \ + -DEXIV2_ENABLE_NLS=OFF \ + -DEXIV2_BUILD_SAMPLES=OFF \ + -DEXIV2_BUILD_UNIT_TESTS=OFF \ + -DEXIV2_ENABLE_VIDEO=OFF \ + -DEXIV2_ENABLE_BMFF=OFF \ + -DEXIV2_ENABLE_BROTLI=OFF \ + -DEXIV2_ENABLE_INIH=OFF \ + -DEXIV2_ENABLE_FILESYSTEM_ACCESS=OFF \ + -DEXIV2_BUILD_EXIV2_COMMAND=OFF \ + -DBUILD_WITH_CCACHE=ON" diff --git a/packages/graphics/gdk-pixbuf/package.mk b/packages/graphics/gdk-pixbuf/package.mk new file mode 100644 index 0000000000..ab4480b948 --- /dev/null +++ b/packages/graphics/gdk-pixbuf/package.mk @@ -0,0 +1,33 @@ +# 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="gdk-pixbuf" +PKG_VERSION="2.43.2" +PKG_SHA256="a386a85c74021fa62d22297db122d231cc68fdd342761fb978c446f73f2606dc" +PKG_LICENSE="OSS" +PKG_SITE="http://www.gtk.org/" +PKG_URL="https://ftp.gnome.org/pub/gnome/sources/gdk-pixbuf/${PKG_VERSION:0:4}/gdk-pixbuf-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain glib libjpeg-turbo libpng jasper shared-mime-info tiff" +PKG_DEPENDS_CONFIG="shared-mime-info" +PKG_LONGDESC="GdkPixbuf is a a GNOME library for image loading and manipulation." + +configure_package() { + if [ "${DISPLAYSERVER}" = "x11" ]; then + PKG_DEPENDS_TARGET+=" libX11" + fi +} + +pre_configure_target() { + PKG_MESON_OPTS_TARGET="--wrap-mode=nodownload \ + -Ddocumentation=false \ + -Dintrospection=disabled \ + -Dman=false \ + -Drelocatable=false \ + -Dinstalled_tests=false \ + -Dtests=false" + + if [ "${DISPLAYSERVER}" != "x11" ]; then + PKG_MESON_OPTS_TARGET+=" -Dbuiltin_loaders=all" + fi +} diff --git a/packages/graphics/giflib/package.mk b/packages/graphics/giflib/package.mk new file mode 100644 index 0000000000..d357015c96 --- /dev/null +++ b/packages/graphics/giflib/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="giflib" +PKG_VERSION="5.2.2" +PKG_SHA256="be7ffbd057cadebe2aa144542fd90c6838c6a083b5e8a9048b8ee3b66b29d5fb" +PKG_LICENSE="OSS" +PKG_SITE="http://giflib.sourceforge.net/" +PKG_URL="${SOURCEFORGE_SRC}/giflib/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="zlib:host" +PKG_DEPENDS_TARGET="toolchain zlib" +PKG_LONGDESC="giflib: giflib service library" +PKG_TOOLCHAIN="manual" + +make_host() { + make libgif.a CFLAGS="${CFLAGS}" LDFLAGS="${LDFLAGS}" +} + +makeinstall_host() { + make install-include PREFIX="${TOOLCHAIN}" + make install-lib PREFIX="${TOOLCHAIN}" +} diff --git a/packages/graphics/giflib/patches/giflib-01-static-lib.patch b/packages/graphics/giflib/patches/giflib-01-static-lib.patch new file mode 100644 index 0000000000..7a6e20134b --- /dev/null +++ b/packages/graphics/giflib/patches/giflib-01-static-lib.patch @@ -0,0 +1,12 @@ +--- a/Makefile ++++ b/Makefile +@@ -99,9 +99,6 @@ + install-lib: + $(INSTALL) -d "$(DESTDIR)$(LIBDIR)" + $(INSTALL) -m 644 libgif.a "$(DESTDIR)$(LIBDIR)/libgif.a" +- $(INSTALL) -m 755 $(LIBGIFSO) "$(DESTDIR)$(LIBDIR)/$(LIBGIFSOVER)" +- ln -sf $(LIBGIFSOVER) "$(DESTDIR)$(LIBDIR)/$(LIBGIFSOMAJOR)" +- ln -sf $(LIBGIFSOMAJOR) "$(DESTDIR)$(LIBDIR)/$(LIBGIFSO)" + install-man: + $(INSTALL) -d "$(DESTDIR)$(MANDIR)/man1" + $(INSTALL) -m 644 $(MANUAL_PAGES) "$(DESTDIR)$(MANDIR)/man1" diff --git a/packages/graphics/glew/package.mk b/packages/graphics/glew/package.mk new file mode 100644 index 0000000000..3a23c8c17e --- /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.2.0" +PKG_SHA256="d4fc82893cfb00109578d0a1a2337fb8ca335b3ceccf97b97e5cc7f08e4353e1" +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 0000000000..30c38f8199 --- /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/glm/config/glm.pc b/packages/graphics/glm/config/glm.pc new file mode 100644 index 0000000000..337af88dad --- /dev/null +++ b/packages/graphics/glm/config/glm.pc @@ -0,0 +1,7 @@ +prefix=/usr +includedir=${prefix}/include + +Name: GLM +Description: OpenGL Mathematics +Version: @@VERSION@@ +Cflags: -I${includedir} diff --git a/packages/graphics/glm/config/glmConfig.cmake b/packages/graphics/glm/config/glmConfig.cmake new file mode 100644 index 0000000000..cc25e3a129 --- /dev/null +++ b/packages/graphics/glm/config/glmConfig.cmake @@ -0,0 +1,20 @@ +set(GLM_VERSION "@@VERSION@@") + + +####### Expanded from @PACKAGE_INIT@ by configure_package_config_file() ####### +get_filename_component(PACKAGE_PREFIX_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../" ABSOLUTE) + +macro(set_and_check _var _file) + set(${_var} "${_file}") + if(NOT EXISTS "${_file}") + message(FATAL_ERROR "File or directory ${_file} referenced by variable ${_var} does not exist !") + endif() +endmacro() + +#################################################################################### + +set_and_check(GLM_INCLUDE_DIRS "${PACKAGE_PREFIX_DIR}/include") + +if (NOT CMAKE_VERSION VERSION_LESS "3.0") + include("${CMAKE_CURRENT_LIST_DIR}/glmTargets.cmake") +endif() diff --git a/packages/graphics/glm/config/glmConfigVersion.cmake b/packages/graphics/glm/config/glmConfigVersion.cmake new file mode 100644 index 0000000000..3673ca6273 --- /dev/null +++ b/packages/graphics/glm/config/glmConfigVersion.cmake @@ -0,0 +1,31 @@ +# This is a basic version file for the Config-mode of find_package(). +# It is used by write_basic_package_version_file() as input file for configure_file() +# to create a version-file which can be installed along a config.cmake file. +# +# The created file sets PACKAGE_VERSION_EXACT if the current version string and +# the requested version string are exactly the same and it sets +# PACKAGE_VERSION_COMPATIBLE if the current version is >= requested version. +# The variable CVF_VERSION must be set before calling configure_file(). + +set(PACKAGE_VERSION "@@VERSION@@") + +if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) + set(PACKAGE_VERSION_COMPATIBLE FALSE) +else() + set(PACKAGE_VERSION_COMPATIBLE TRUE) + if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION) + set(PACKAGE_VERSION_EXACT TRUE) + endif() +endif() + +# if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it: +if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "@@VOID_SIZE@@" STREQUAL "") + return() +endif() + +# check that the installed version has the same 32/64bit-ness as the one which is currently searching: +if(NOT CMAKE_SIZEOF_VOID_P STREQUAL "@@VOID_SIZE@@") + math(EXPR installedBits "@@VOID_SIZE@@ * 8") + set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)") + set(PACKAGE_VERSION_UNSUITABLE FALSE) +endif() diff --git a/packages/graphics/glm/config/glmTargets.cmake b/packages/graphics/glm/config/glmTargets.cmake new file mode 100644 index 0000000000..905b67731b --- /dev/null +++ b/packages/graphics/glm/config/glmTargets.cmake @@ -0,0 +1,107 @@ +# Generated by CMake + +if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.5) + message(FATAL_ERROR "CMake >= 2.6.0 required") +endif() +cmake_policy(PUSH) +cmake_policy(VERSION 2.6) +#---------------------------------------------------------------- +# Generated CMake target import file. +#---------------------------------------------------------------- + +# Commands may need to know the format version. +set(CMAKE_IMPORT_FILE_VERSION 1) + +# Protect against multiple inclusion, which would fail when already imported targets are added once more. +set(_targetsDefined) +set(_targetsNotDefined) +set(_expectedTargets) +foreach(_expectedTarget glm) + list(APPEND _expectedTargets ${_expectedTarget}) + if(NOT TARGET ${_expectedTarget}) + list(APPEND _targetsNotDefined ${_expectedTarget}) + endif() + if(TARGET ${_expectedTarget}) + list(APPEND _targetsDefined ${_expectedTarget}) + endif() +endforeach() +if("${_targetsDefined}" STREQUAL "${_expectedTargets}") + unset(_targetsDefined) + unset(_targetsNotDefined) + unset(_expectedTargets) + set(CMAKE_IMPORT_FILE_VERSION) + cmake_policy(POP) + return() +endif() +if(NOT "${_targetsDefined}" STREQUAL "") + message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_targetsDefined}\nTargets not yet defined: ${_targetsNotDefined}\n") +endif() +unset(_targetsDefined) +unset(_targetsNotDefined) +unset(_expectedTargets) + + +# Compute the installation prefix relative to this file. +get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH) +# Use original install prefix when loaded through a +# cross-prefix symbolic link such as /lib -> /usr/lib. +get_filename_component(_realCurr "${_IMPORT_PREFIX}" REALPATH) +get_filename_component(_realOrig "/usr/lib/cmake/glm" REALPATH) +if(_realCurr STREQUAL _realOrig) + set(_IMPORT_PREFIX "/usr/lib/cmake/glm") +endif() +unset(_realOrig) +unset(_realCurr) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +if(_IMPORT_PREFIX STREQUAL "/") + set(_IMPORT_PREFIX "") +endif() + +# Create imported target glm +add_library(glm INTERFACE IMPORTED) + +set_target_properties(glm PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include" +) + +if(CMAKE_VERSION VERSION_LESS 3.0.0) + message(FATAL_ERROR "This file relies on consumers using CMake 3.0.0 or greater.") +endif() + +# Load information for each installed configuration. +get_filename_component(_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) +file(GLOB CONFIG_FILES "${_DIR}/glmTargets-*.cmake") +foreach(f ${CONFIG_FILES}) + include(${f}) +endforeach() + +# Cleanup temporary variables. +set(_IMPORT_PREFIX) + +# Loop over all imported files and verify that they actually exist +foreach(target ${_IMPORT_CHECK_TARGETS} ) + foreach(file ${_IMPORT_CHECK_FILES_FOR_${target}} ) + if(NOT EXISTS "${file}" ) + message(FATAL_ERROR "The imported target \"${target}\" references the file + \"${file}\" +but this file does not exist. Possible reasons include: +* The file was deleted, renamed, or moved to another location. +* An install or uninstall procedure did not complete successfully. +* The installation package was faulty and contained + \"${CMAKE_CURRENT_LIST_FILE}\" +but not all the files it references. +") + endif() + endforeach() + unset(_IMPORT_CHECK_FILES_FOR_${target}) +endforeach() +unset(_IMPORT_CHECK_TARGETS) + +# This file does not depend on other imported targets which have +# been exported from the same project but in a separate export set. + +# Commands beyond this point should not need to know the version. +set(CMAKE_IMPORT_FILE_VERSION) +cmake_policy(POP) diff --git a/packages/graphics/glm/package.mk b/packages/graphics/glm/package.mk new file mode 100644 index 0000000000..9a6be60ab5 --- /dev/null +++ b/packages/graphics/glm/package.mk @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="glm" +PKG_VERSION="1.0.1" +PKG_SHA256="9f3174561fd26904b23f0db5e560971cbf9b3cbda0b280f04d5c379d03bf234c" +PKG_LICENSE="MIT" +PKG_SITE="https://glm.g-truc.net/" +PKG_URL="https://github.com/g-truc/glm/archive/refs/tags/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="OpenGL Mathematics (GLM)" + +PKG_CMAKE_OPTS_TARGET="-DGLM_BUILD_TESTS=OFF" + +# Not needed by GLM itself, but users will need it. So instead of adding this +# to every user, put it here once. +if [ "${OPENGLES_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" +fi + +if [ "${OPENGL_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL}" +fi + +# Hack install solution until cmake install restored in upstream package +makeinstall_target() { + target_has_feature 32bit && PKG_VOID_SIZE=4 || PKG_VOID_SIZE=8 + + for _dir in ${SYSROOT_PREFIX} ${INSTALL}; do + mkdir -p ${_dir}/usr/include ${_dir}/usr/lib/pkgconfig ${_dir}/usr/lib/cmake/glm + cp -r ${PKG_BUILD}/glm ${_dir}/usr/include + cp ${PKG_DIR}/config/glm.pc ${_dir}/usr/lib/pkgconfig + cp ${PKG_DIR}/config/*.cmake ${_dir}/usr/lib/cmake/glm + + sed -e "s/@@VERSION@@/${PKG_VERSION}/g" \ + -e "s/@@VOID_SIZE@@/${PKG_VOID_SIZE}/g" \ + -i ${_dir}/usr/lib/pkgconfig/glm.pc ${_dir}/usr/lib/cmake/glm/*.cmake + done +} diff --git a/packages/graphics/glmark2/package.mk b/packages/graphics/glmark2/package.mk new file mode 100644 index 0000000000..f2580d2f83 --- /dev/null +++ b/packages/graphics/glmark2/package.mk @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="glmark2" +PKG_VERSION="2023.01" +PKG_SHA256="8fece3fc323b643644a525be163dc4931a4189971eda1de8ad4c1712c5db3d67" +PKG_LICENSE="GPL-3.0-or-later" +PKG_SITE="https://github.com/glmark2/glmark2" +PKG_URL="https://github.com/glmark2/glmark2/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain libjpeg-turbo libpng" +PKG_LONGDESC="glmark2 is an OpenGL 2.0 and ES 2.0 benchmark" + +if [ "${OPENGL_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL}" +elif [ "${OPENGLES_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" +fi + +case ${DISPLAYSERVER} in + wl) + PKG_DEPENDS_TARGET+=" wayland wayland-protocols" + PKG_MESON_OPTS_TARGET="-Dflavors=wayland-glesv2" + ;; + x11) + PKG_DEPENDS_TARGET+=" libX11" + PKG_MESON_OPTS_TARGET="-Dflavors=x11-gl" + ;; + *) + PKG_DEPENDS_TARGET+=" systemd libdrm" + PKG_MESON_OPTS_TARGET="-Dflavors=drm-glesv2" + ;; +esac diff --git a/packages/graphics/glu/package.mk b/packages/graphics/glu/package.mk new file mode 100644 index 0000000000..701fc636f8 --- /dev/null +++ b/packages/graphics/glu/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="glu" +PKG_VERSION="9.0.3" +PKG_SHA256="bd43fe12f374b1192eb15fe20e45ff456b9bc26ab57f0eee919f96ca0f8a330f" +PKG_LICENSE="OSS" +PKG_SITE="https://gitlab.freedesktop.org/mesa/glu/" +PKG_URL="https://mesa.freedesktop.org/archive/glu/glu-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain libglvnd mesa" +PKG_NEED_UNPACK="$(get_pkg_directory mesa)" +PKG_LONGDESC="libglu is the The OpenGL utility library" + +if [ "${DISPLAYSERVER}" = "x11" ]; then + PKG_MESON_OPTS_TARGET="-Dgl_provider=gl" +else + PKG_MESON_OPTS_TARGET="-Dgl_provider=glvnd" +fi diff --git a/packages/graphics/harfbuzz/package.mk b/packages/graphics/harfbuzz/package.mk new file mode 100644 index 0000000000..54b87f6c1b --- /dev/null +++ b/packages/graphics/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="11.2.1" +PKG_SHA256="093714c8548a285094685f0bdc999e202d666b59eeb3df2ff921ab68b8336a49" +PKG_LICENSE="GPL" +PKG_SITE="http://www.freedesktop.org/wiki/Software/HarfBuzz" +PKG_URL="https://github.com/harfbuzz/harfbuzz/releases/download/${PKG_VERSION}/harfbuzz-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain cairo freetype glib" +PKG_LONGDESC="HarfBuzz is an OpenType text shaping engine." + +PKG_MESON_OPTS_TARGET="-Dbenchmark=disabled \ + -Dcairo=enabled \ + -Ddocs=disabled \ + -Dfreetype=enabled \ + -Dglib=enabled \ + -Dgobject=disabled \ + -Dgraphite=disabled \ + -Dicu=disabled \ + -Dtests=disabled" diff --git a/packages/graphics/jasper/package.mk b/packages/graphics/jasper/package.mk new file mode 100644 index 0000000000..7f884d2ee2 --- /dev/null +++ b/packages/graphics/jasper/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="jasper" +PKG_VERSION="4.2.5" +PKG_SHA256="3f4b1df7cab7a3cc67b9f6e28c730372f030b54b0faa8548a9ee04ae83fffd44" +PKG_LICENSE="OpenSource" +PKG_SITE="http://www.ece.uvic.ca/~mdadams/jasper/" +PKG_URL="https://github.com/jasper-software/jasper/archive/refs/tags/version-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain libjpeg-turbo" +PKG_LONGDESC="A implementation of the ISO/IEC 15444-1 also known as JPEG-2000 standard for image compression." +PKG_BUILD_FLAGS="+pic" + +PKG_CMAKE_OPTS_TARGET="-DJAS_ENABLE_DOC=false \ + -DJAS_ENABLE_PROGRAMS=false \ + -DJAS_ENABLE_SHARED=false \ + -DALLOW_IN_SOURCE_BUILD=ON \ + -DJAS_STDC_VERSION=201710L" + +pre_configure_target() { + export CFLAGS="${CFLAGS} -std=gnu17" +} diff --git a/packages/graphics/kmscube/package.mk b/packages/graphics/kmscube/package.mk new file mode 100644 index 0000000000..c858a2ce4f --- /dev/null +++ b/packages/graphics/kmscube/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="kmscube" +PKG_VERSION="9f63f359fab1b5d8e862508e4e51c9dfe339ccb0" +PKG_SHA256="896ac76671a9b89836a7014b16cc85b45b041e03fe34a8f529f4718aa2b15cef" +PKG_LICENSE="GPL" +PKG_SITE="https://gitlab.freedesktop.org/mesa/kmscube" +PKG_URL="https://gitlab.freedesktop.org/mesa/kmscube/-/archive/master/kmscube-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Example KMS/GBM/EGL application" + +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/kmsxx/package.mk b/packages/graphics/kmsxx/package.mk new file mode 100644 index 0000000000..b7c60269e7 --- /dev/null +++ b/packages/graphics/kmsxx/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="kmsxx" +PKG_VERSION="403c756c958c2a60adc6e8fa64aa0943b4dfda4e" +PKG_SHA256="f8836c2a7e771c9163b7d08f22c121f134697d7d4a66d7fe9631585aff54e8db" +PKG_LICENSE="MPL-2.0" +PKG_SITE="https://github.com/tomba/kmsxx" +PKG_URL="https://github.com/tomba/kmsxx/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain libdrm libfmt" +PKG_LONGDESC="Library and utilities for kernel mode setting" +PKG_BUILD_FLAGS="-sysroot" + +PKG_MESON_OPTS_TARGET="-Ddefault_library=shared \ + -Dkmscube=false \ + -Domap=disabled \ + -Dpykms=disabled" diff --git a/packages/graphics/lcms2/package.mk b/packages/graphics/lcms2/package.mk new file mode 100644 index 0000000000..10c14d0f73 --- /dev/null +++ b/packages/graphics/lcms2/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2020-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="lcms2" +PKG_VERSION="2.17" +PKG_SHA256="d11af569e42a1baa1650d20ad61d12e41af4fead4aa7964a01f93b08b53ab074" +PKG_LICENSE="MIT/GPLv3" +PKG_SITE="http://www.littlecms.com" +PKG_URL="https://github.com/mm2/Little-CMS/releases/download/lcms${PKG_VERSION}/lcms2-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain tiff" +PKG_LONGDESC="An small-footprint color management engine, with special focus on accuracy and performance." +PKG_BUILD_FLAGS="+pic" + +PKG_MESON_OPTS_TARGET="-Ddefault_library=static \ + -Dprefer_static=true \ + -Dtests=disabled \ + -Dutils=true" diff --git a/packages/graphics/libde265/package.mk b/packages/graphics/libde265/package.mk new file mode 100644 index 0000000000..e794221d12 --- /dev/null +++ b/packages/graphics/libde265/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libde265" +PKG_VERSION="1.0.16" +PKG_SHA256="b92beb6b53c346db9a8fae968d686ab706240099cdd5aff87777362d668b0de7" +PKG_LICENSE="LGPLv3" +PKG_SITE="http://www.libde265.org" +PKG_URL="https://github.com/strukturag/libde265/releases/download/v${PKG_VERSION}/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Open h.265 video codec implementation." +PKG_BUILD_FLAGS="+pic" + +PKG_CMAKE_OPTS_TARGET="-DBUILD_SHARED_LIBS=OFF \ + -DENABLE_SDL=OFF \ + -DENABLE_DECODER=OFF \ + -DENABLE_ENCODER=OFF" diff --git a/packages/graphics/libdrm/package.mk b/packages/graphics/libdrm/package.mk new file mode 100644 index 0000000000..b652745af5 --- /dev/null +++ b/packages/graphics/libdrm/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) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libdrm" +PKG_VERSION="2.4.125" +PKG_SHA256="d4bae92797a50f81a93524762e0410a49cd84cfa0f997795bc0172ac8fb1d96a" +PKG_LICENSE="GPL" +PKG_SITE="https://dri.freedesktop.org" +PKG_URL="https://dri.freedesktop.org/libdrm/libdrm-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_HOST="toolchain:host" +PKG_DEPENDS_TARGET="toolchain libpciaccess" +PKG_LONGDESC="The userspace interface library to kernel DRM services." + +get_graphicdrivers + +PKG_MESON_OPTS_COMMON="-Dnouveau=disabled \ + -Domap=disabled \ + -Dexynos=disabled \ + -Dtegra=disabled \ + -Dcairo-tests=disabled \ + -Dman-pages=disabled \ + -Dvalgrind=disabled \ + -Dfreedreno-kgsl=false \ + -Dudev=false" + +PKG_MESON_OPTS_HOST="${PKG_MESON_OPTS_COMMON} \ + -Damdgpu=disabled \ + -Detnaviv=disabled \ + -Dfreedreno=disabled \ + -Dintel=disabled \ + -Dradeon=disabled \ + -Dvc4=disabled \ + -Dvmwgfx=disabled \ + -Dtests=false \ + -Dinstall-test-programs=false" + +PKG_MESON_OPTS_TARGET="${PKG_MESON_OPTS_COMMON} \ + -Dtests=true \ + -Dinstall-test-programs=true" + +listcontains "${GRAPHIC_DRIVERS}" "(crocus|i915|iris)" && + PKG_MESON_OPTS_TARGET+=" -Dintel=enabled" || PKG_MESON_OPTS_TARGET+=" -Dintel=disabled" + +listcontains "${GRAPHIC_DRIVERS}" "(r300|r600|radeonsi)" && + PKG_MESON_OPTS_TARGET+=" -Dradeon=enabled" || PKG_MESON_OPTS_TARGET+=" -Dradeon=disabled" + +listcontains "${GRAPHIC_DRIVERS}" "radeonsi" && + PKG_MESON_OPTS_TARGET+=" -Damdgpu=enabled" || PKG_MESON_OPTS_TARGET+=" -Damdgpu=disabled" + +listcontains "${GRAPHIC_DRIVERS}" "vmware" && + PKG_MESON_OPTS_TARGET+=" -Dvmwgfx=enabled" || PKG_MESON_OPTS_TARGET+=" -Dvmwgfx=disabled" + +listcontains "${GRAPHIC_DRIVERS}" "vc4" && + PKG_MESON_OPTS_TARGET+=" -Dvc4=enabled" || PKG_MESON_OPTS_TARGET+=" -Dvc4=disabled" + +listcontains "${GRAPHIC_DRIVERS}" "freedreno" && + PKG_MESON_OPTS_TARGET+=" -Dfreedreno=enabled" || PKG_MESON_OPTS_TARGET+=" -Dfreedreno=disabled" + +listcontains "${GRAPHIC_DRIVERS}" "etnaviv" && + PKG_MESON_OPTS_TARGET+=" -Detnaviv=enabled" || PKG_MESON_OPTS_TARGET+=" -Detnaviv=disabled" + +post_makeinstall_target() { + # Remove all test programs installed by install-test-programs=true except modetest + PKG_LIBDRM_LIST="drmdevice modeprint proptest vbltest" + for PKG_LIBDRM_TEST in ${PKG_LIBDRM_LIST}; do + safe_remove ${INSTALL}/usr/bin/${PKG_LIBDRM_TEST} + done + + if listcontains "${GRAPHIC_DRIVERS}" "radeonsi"; then + safe_remove ${INSTALL}/usr/bin/amdgpu_stress + fi +} diff --git a/packages/graphics/libepoxy/package.mk b/packages/graphics/libepoxy/package.mk new file mode 100644 index 0000000000..964789c7d6 --- /dev/null +++ b/packages/graphics/libepoxy/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) 2018-present Team LibreELEC (https://libreelec.tv) + +# 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.10" +PKG_SHA256="a7ced37f4102b745ac86d6a70a9da399cc139ff168ba6b8002b4d8d43c900c15" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/anholt/libepoxy" +PKG_URL="https://github.com/anholt/libepoxy/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Epoxy is a library for handling OpenGL function pointer management for you." + +configure_package() { + if [ "${OPENGL_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL}" + fi + + if [ "${OPENGLES_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" + fi +} + +pre_configure_target() { + PKG_MESON_OPTS_TARGET="-Dtests=false" + + if [ "${DISPLAYSERVER}" != "x11" ]; then + PKG_MESON_OPTS_TARGET+=" -Dglx=no \ + -Dx11=false" + fi +} diff --git a/packages/graphics/libglvnd/package.mk b/packages/graphics/libglvnd/package.mk new file mode 100644 index 0000000000..14b9c5e472 --- /dev/null +++ b/packages/graphics/libglvnd/package.mk @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libglvnd" +PKG_VERSION="1.7.0" +PKG_SHA256="073e7292788d4d3eeb45ea6c7bdcce9bfdb3b3eef8d7dbd47f2f30dce046ef98" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/NVIDIA/libglvnd" +PKG_URL="https://github.com/NVIDIA/libglvnd/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="libglvnd is a vendor-neutral dispatch layer for arbitrating OpenGL API calls between multiple vendors." + +configure_package() { + if [ "${DISPLAYSERVER}" = "x11" ]; then + PKG_DEPENDS_TARGET+=" libX11 libXext xorgproto" + fi +} + +pre_configure_target() { + PKG_MESON_OPTS_TARGET="-Dgles1=false" + + if [ "${OPENGLES_SUPPORT}" = "no" ]; then + PKG_MESON_OPTS_TARGET+=" -Dgles2=false" + fi +} + +post_makeinstall_target() { + if [ "${DISPLAYSERVER}" = "x11" ]; then + # Remove old symlinks to libGL.so.1.7.0 (GLVND) + safe_remove ${INSTALL}/usr/lib/libGL.so + safe_remove ${INSTALL}/usr/lib/libGL.so.1 + # Create new symlinks to /var/lib/libGL.so + ln -sf libGL.so.1 ${INSTALL}/usr/lib/libGL.so + ln -sf /var/lib/libGL.so ${INSTALL}/usr/lib/libGL.so.1 + # Create new symlink to libGL.so.1.7.0 + ln -sf libGL.so.1.7.0 ${INSTALL}/usr/lib/libGL_glvnd.so.1 + + # Remove old symlinks to libGLX.so.0.0.0 (GLVND) + safe_remove ${INSTALL}/usr/lib/libGLX.so + safe_remove ${INSTALL}/usr/lib/libGLX.so.0 + # Create new symlinks to /var/lib/libGLX.so + ln -sf libGLX.so.0 ${INSTALL}/usr/lib/libGLX.so + ln -sf /var/lib/libGLX.so ${INSTALL}/usr/lib/libGLX.so.0 + # Create new symlink to libGLX.so.0.0.0 + ln -sf libGLX.so.0.0.0 ${INSTALL}/usr/lib/libGLX_glvnd.so.0 + + # indirect rendering + ln -sf /var/lib/libGLX_indirect.so.0 ${INSTALL}/usr/lib/libGLX_indirect.so.0 + fi +} diff --git a/packages/graphics/libheif/package.mk b/packages/graphics/libheif/package.mk new file mode 100644 index 0000000000..24eb011321 --- /dev/null +++ b/packages/graphics/libheif/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libheif" +PKG_VERSION="1.20.1" +PKG_SHA256="55cc76b77c533151fc78ba58ef5ad18562e84da403ed749c3ae017abaf1e2090" +PKG_LICENSE="LGPLv3" +PKG_SITE="https://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_CMAKE_OPTS_TARGET="-DBUILD_SHARED_LIBS=OFF \ + -DWITH_EXAMPLES=OFF \ + -DWITH_AOM_DECODER=OFF \ + -DWITH_AOM_ENCODER=OFF" + +pre_configure_target() { + export CXXFLAGS="${CXXFLAGS} -Wno-unused-variable" +} diff --git a/packages/graphics/libjpeg-turbo/package.mk b/packages/graphics/libjpeg-turbo/package.mk new file mode 100644 index 0000000000..556bc7b4e4 --- /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="3.1.1" +PKG_SHA256="aadc97ea91f6ef078b0ae3a62bba69e008d9a7db19b34e4ac973b19b71b4217c" +PKG_LICENSE="GPL" +PKG_SITE="https://libjpeg-turbo.org/" +PKG_URL="https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/${PKG_VERSION}/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="cmake:host ninja:host" +PKG_DEPENDS_TARGET="cmake:host ninja:host gcc:host" +PKG_LONGDESC="A JPEG image codec that uses SIMD instructions." +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/libpng/package.mk b/packages/graphics/libpng/package.mk new file mode 100644 index 0000000000..12a62d459a --- /dev/null +++ b/packages/graphics/libpng/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) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libpng" +PKG_VERSION="1.6.50" +PKG_SHA256="4df396518620a7aa3651443e87d1b2862e4e88cad135a8b93423e01706232307" +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 \ + --disable-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 + + sed -e 's|^Libs: -L${libdir} -lpng16|Libs: -L${libdir} -lpng16 -lz|g' \ + -i ${SYSROOT_PREFIX}/usr/lib/pkgconfig/libpng*.pc + + rm -rf ${INSTALL}/usr/bin +} diff --git a/packages/graphics/libprojectM/package.mk b/packages/graphics/libprojectM/package.mk new file mode 100644 index 0000000000..f9512a6f98 --- /dev/null +++ b/packages/graphics/libprojectM/package.mk @@ -0,0 +1,45 @@ +# 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="3.1.12" +PKG_SHA256="62b5b1b543b25cb8ad392d879378cfdc5c129165cf4d4f33fb159e364d42f135" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/projectM-visualizer/projectm" +PKG_URL="https://github.com/projectM-visualizer/projectm/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain freetype glm" +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 \ + --disable-sdl \ + --disable-llvm \ + --disable-emscripten \ + --enable-threading" + +if [ "${OPENGL_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL}" + PKG_CONFIGURE_OPTS_TARGET+=" --disable-gles \ + --enable-gl" +fi + +if [ "${OPENGLES_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" + PKG_CONFIGURE_OPTS_TARGET+=" --enable-gles \ + --disable-gl" +fi + +# workaround due broken release files, remove at next bump +pre_configure_target() { + ./autogen.sh + + if [ "${OPENGLES_SUPPORT}" = "yes" ]; then + export CFLAGS+=" -DSOIL_GLES2" + fi +} diff --git a/packages/graphics/libprojectM/patches/0001-add-enable-gl-switch.patch b/packages/graphics/libprojectM/patches/0001-add-enable-gl-switch.patch new file mode 100644 index 0000000000..1c94fee435 --- /dev/null +++ b/packages/graphics/libprojectM/patches/0001-add-enable-gl-switch.patch @@ -0,0 +1,13 @@ +diff --color -Naur a/configure.ac b/configure.ac +--- a/configure.ac 2021-02-20 11:40:39.000000000 -0800 ++++ b/configure.ac 2023-07-06 16:06:18.679702443 -0700 +@@ -37,7 +37,8 @@ + enable_sdl=yes + ], [ + dnl Running in a normal OS (not emscripten) +- AX_CHECK_GL ++ AC_ARG_ENABLE([gl], AS_HELP_STRING([--enable-gl], [OpenGL support]), [], [enable_gl=no]) ++ AS_IF([test "x$enable_gl" = "xyes"], [AX_CHECK_GL]) + + # check OS if mac or linux + AC_CANONICAL_HOST diff --git a/packages/graphics/libraw/package.mk b/packages/graphics/libraw/package.mk new file mode 100644 index 0000000000..5cbf28a348 --- /dev/null +++ b/packages/graphics/libraw/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libraw" +PKG_VERSION="0.21.4" +PKG_SHA256="6be43f19397e43214ff56aab056bf3ff4925ca14012ce5a1538a172406a09e63" +PKG_LICENSE="LGPL" +PKG_SITE="https://www.libraw.org/" +PKG_URL="https://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_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="--enable-static \ + --disable-shared \ + --disable-openmp \ + --enable-jpeg \ + --disable-jasper \ + --enable-lcms \ + --disable-examples" diff --git a/packages/graphics/mesa-reusable/package.mk b/packages/graphics/mesa-reusable/package.mk new file mode 100644 index 0000000000..30fb0da221 --- /dev/null +++ b/packages/graphics/mesa-reusable/package.mk @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2025-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="mesa-reusable" +PKG_LICENSE="OSS" +PKG_SITE="http://www.mesa3d.org/" +PKG_DEPENDS_HOST="toolchain:host" +PKG_LONGDESC="Mesa is a 3-D graphics library with an API." +PKG_TOOLCHAIN="manual" + +MESA_VERSION=$(get_pkg_version mesa) +PKG_VERSION="${OS_VERSION}-${MESA_VERSION}" +PKG_SOURCE_NAME="${PKG_NAME}-${PKG_VERSION}-${MACHINE_HARDWARE_NAME}.tar" +PKG_URL="https://github.com/LibreELEC/mesa-reusable/releases/download/${PKG_VERSION}/${PKG_SOURCE_NAME}" +PKG_SHA256="$(curl --fail --connect-timeout 30 --retry 3 --location --max-redirs 5 ${PKG_URL}.sha256)" + +unpack() { + mkdir -p ${TOOLCHAIN}/bin + tar -xf ${SOURCES}/${PKG_NAME}/${PKG_SOURCE_NAME} -C ${TOOLCHAIN}/bin +} diff --git a/packages/graphics/mesa/package.mk b/packages/graphics/mesa/package.mk new file mode 100644 index 0000000000..237dc765b4 --- /dev/null +++ b/packages/graphics/mesa/package.mk @@ -0,0 +1,149 @@ +# 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="26.0.5" +PKG_SHA256="d229c9937d9a25ca0a8958c59f425174563d300ec42acbea2dbe84a055023368" +PKG_LICENSE="OSS" +PKG_SITE="http://www.mesa3d.org/" +PKG_URL="https://mesa.freedesktop.org/archive/mesa-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_HOST="toolchain:host expat:host libclc:host libdrm:host Mako:host pyyaml:host spirv-tools:host" +PKG_DEPENDS_TARGET="toolchain expat libdrm Mako:host pyyaml:host" +PKG_LONGDESC="Mesa is a 3-D graphics library with an API." +PKG_BUILD_FLAGS="+speed +lto" + +get_graphicdrivers + +if [ "${DEVICE}" = "Dragonboard" ]; then + PKG_DEPENDS_TARGET+=" libarchive libxml2 lua54" +fi + +PKG_MESON_OPTS_HOST="-Dglvnd=disabled \ + -Dgallium-drivers=iris \ + -Dgallium-vdpau=disabled \ + -Dplatforms= \ + -Dglx=disabled \ + -Dvulkan-drivers= \ + -Dshared-llvm=disabled \ + -Dtools=panfrost" + +PKG_MESON_OPTS_TARGET="-Dgallium-drivers=${GALLIUM_DRIVERS// /,} \ + -Dgallium-extra-hud=false \ + -Dgallium-rusticl=false \ + -Dshader-cache=enabled \ + -Dopengl=true \ + -Dgbm=enabled \ + -Degl=enabled \ + -Dvalgrind=disabled \ + -Dlibunwind=disabled \ + -Dlmsensors=disabled \ + -Dbuild-tests=false \ + -Ddraw-use-llvm=false \ + -Dmicrosoft-clc=disabled" + +if [ "${DISPLAYSERVER}" = "x11" ]; then + PKG_DEPENDS_TARGET+=" xorgproto libXext libXdamage libXfixes libXxf86vm libxcb libX11 libxshmfence libXrandr" + export X11_INCLUDES= + PKG_MESON_OPTS_TARGET+=" -Dplatforms=x11 \ + -Dglx=dri" +elif [ "${DISPLAYSERVER}" = "wl" ]; then + PKG_DEPENDS_TARGET+=" wayland wayland-protocols" + PKG_MESON_OPTS_TARGET+=" -Dplatforms=wayland \ + -Dglx=disabled" +else + PKG_MESON_OPTS_TARGET+=" -Dplatforms="" \ + -Dglx=disabled" +fi + +if listcontains "${GRAPHIC_DRIVERS}" "etnaviv"; then + PKG_DEPENDS_TARGET+=" pycparser:host" +fi + +if listcontains "${GRAPHIC_DRIVERS}" "(iris|panfrost)"; then + if [ "${USE_REUSABLE}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" mesa-reusable" + else + PKG_DEPENDS_TARGET+=" mesa:host" + fi + PKG_MESON_OPTS_TARGET+=" -Dmesa-clc=system -Dprecomp-compiler=system" +fi + +if listcontains "${GRAPHIC_DRIVERS}" "(nvidia|nvidia-ng)" || + [ "${OPENGL_SUPPORT}" = "yes" -a "${DISPLAYSERVER}" != "x11" ]; then + PKG_DEPENDS_TARGET+=" libglvnd" + PKG_MESON_OPTS_TARGET+=" -Dglvnd=enabled" +else + PKG_MESON_OPTS_TARGET+=" -Dglvnd=disabled" +fi + +if [ "${LLVM_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" elfutils llvm" + PKG_MESON_OPTS_TARGET+=" -Dllvm=enabled" +else + PKG_MESON_OPTS_TARGET+=" -Dllvm=disabled" +fi + +if [ "${VDPAU_SUPPORT}" = "yes" -a "${DISPLAYSERVER}" = "x11" ]; then + PKG_DEPENDS_TARGET+=" libvdpau" + PKG_MESON_OPTS_TARGET+=" -Dgallium-vdpau=enabled" +else + PKG_MESON_OPTS_TARGET+=" -Dgallium-vdpau=disabled" +fi + +if [ "${VAAPI_SUPPORT}" = "yes" ] && listcontains "${GRAPHIC_DRIVERS}" "(r600|radeonsi)"; then + PKG_DEPENDS_TARGET+=" libva" + PKG_MESON_OPTS_TARGET+=" -Dgallium-va=enabled \ + -Dvideo-codecs=vc1dec,h264dec,h264enc,h265dec,h265enc,av1dec,av1enc,vp9dec" +else + PKG_MESON_OPTS_TARGET+=" -Dgallium-va=disabled" +fi + +if listcontains "${GRAPHIC_DRIVERS}" "vmware"; then + PKG_MESON_OPTS_TARGET+=" -Dgallium-xa=enabled" +else + PKG_MESON_OPTS_TARGET+=" -Dgallium-xa=disabled" +fi + +if [ "${OPENGLES_SUPPORT}" = "yes" ]; then + PKG_MESON_OPTS_TARGET+=" -Dgles1=disabled -Dgles2=enabled" +else + PKG_MESON_OPTS_TARGET+=" -Dgles1=disabled -Dgles2=disabled" +fi + +if [ "${VULKAN_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${VULKAN} vulkan-tools ply:host" + PKG_MESON_OPTS_TARGET+=" -Dvulkan-drivers=${VULKAN_DRIVERS_MESA// /,}" +else + PKG_MESON_OPTS_TARGET+=" -Dvulkan-drivers=" +fi + +makeinstall_host() { + host_files="src/compiler/clc/mesa_clc src/compiler/spirv/vtn_bindgen2 src/panfrost/clc/panfrost_compile" + + if listcontains "${BUILD_REUSABLE}" "(all|mesa:host)"; then + # Build the reusable mesa:host for both local and to be added to a GitHub release + strip ${host_files} + upx --lzma ${host_files} + + REUSABLE_SOURCES="${SOURCES}/mesa-reusable" + MESA_HOST="mesa-reusable-${OS_VERSION}-${PKG_VERSION}" + REUSABLE_SOURCE_NAME=${MESA_HOST}-${MACHINE_HARDWARE_NAME}.tar + + mkdir -p "${TARGET_IMG}" + + tar cf ${TARGET_IMG}/${REUSABLE_SOURCE_NAME} --transform='s|.*/||' ${host_files} + sha256sum ${TARGET_IMG}/${REUSABLE_SOURCE_NAME} | \ + cut -d" " -f1 >${TARGET_IMG}/${REUSABLE_SOURCE_NAME}.sha256 + + if listcontains "${BUILD_REUSABLE}" "save-local"; then + mkdir -p "${REUSABLE_SOURCES}" + cp -p ${TARGET_IMG}/${REUSABLE_SOURCE_NAME} ${REUSABLE_SOURCES} + cp -p ${TARGET_IMG}/${REUSABLE_SOURCE_NAME}.sha256 ${REUSABLE_SOURCES} + echo "save-local" >${REUSABLE_SOURCES}/${REUSABLE_SOURCE_NAME}.url + fi + fi + + mkdir -p "${TOOLCHAIN}/bin" + cp -a ${host_files} "${TOOLCHAIN}/bin" +} diff --git a/packages/graphics/pango/config/pango.modules b/packages/graphics/pango/config/pango.modules new file mode 100644 index 0000000000..2494e6cc12 --- /dev/null +++ b/packages/graphics/pango/config/pango.modules @@ -0,0 +1,18 @@ +# Pango Modules file +# Automatically generated file, do not edit +# +# ModulesPath = /usr/lib/pango/1.8.0/modules +# +/usr/lib/pango/1.8.0/modules/pango-arabic-lang.so ArabicScriptEngineLang PangoEngineLang PangoRenderNone arabic:* +/usr/lib/pango/1.8.0/modules/pango-basic-fc.so BasicScriptEngineFc PangoEngineShape PangoRenderFc common: +/usr/lib/pango/1.8.0/modules/pango-indic-lang.so devaIndicScriptEngineLang PangoEngineLang PangoRenderNone devanagari:* +/usr/lib/pango/1.8.0/modules/pango-indic-lang.so bengIndicScriptEngineLang PangoEngineLang PangoRenderNone bengali:* +/usr/lib/pango/1.8.0/modules/pango-indic-lang.so guruIndicScriptEngineLang PangoEngineLang PangoRenderNone gurmukhi:* +/usr/lib/pango/1.8.0/modules/pango-indic-lang.so gujrIndicScriptEngineLang PangoEngineLang PangoRenderNone gujarati:* +/usr/lib/pango/1.8.0/modules/pango-indic-lang.so oryaIndicScriptEngineLang PangoEngineLang PangoRenderNone oriya:* +/usr/lib/pango/1.8.0/modules/pango-indic-lang.so tamlIndicScriptEngineLang PangoEngineLang PangoRenderNone tamil:* +/usr/lib/pango/1.8.0/modules/pango-indic-lang.so teluIndicScriptEngineLang PangoEngineLang PangoRenderNone telugu:* +/usr/lib/pango/1.8.0/modules/pango-indic-lang.so kndaIndicScriptEngineLang PangoEngineLang PangoRenderNone kannada:* +/usr/lib/pango/1.8.0/modules/pango-indic-lang.so mlymIndicScriptEngineLang PangoEngineLang PangoRenderNone malayalam:* +/usr/lib/pango/1.8.0/modules/pango-indic-lang.so sinhIndicScriptEngineLang PangoEngineLang PangoRenderNone sinhala:* + diff --git a/packages/graphics/pango/config/pangorc b/packages/graphics/pango/config/pangorc new file mode 100644 index 0000000000..d37ff990ad --- /dev/null +++ b/packages/graphics/pango/config/pangorc @@ -0,0 +1,6 @@ +[Pango] +ModuleFiles = /etc/pango/pango.modules +ModulesPath = /usr/lib/pango/1.8.0/modules + +[PangoX] +AliasFiles = /etc/pango/pangox.aliases diff --git a/packages/graphics/pango/package.mk b/packages/graphics/pango/package.mk new file mode 100644 index 0000000000..83d5b93268 --- /dev/null +++ b/packages/graphics/pango/package.mk @@ -0,0 +1,27 @@ +# 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="pango" +PKG_VERSION="1.56.4" +PKG_SHA256="17065e2fcc5f5a5bdbffc884c956bfc7c451a96e8c4fb2f8ad837c6413cb5a01" +PKG_LICENSE="GPL" +PKG_SITE="http://www.pango.org/" +PKG_URL="https://download.gnome.org/sources/pango/${PKG_VERSION:0:4}/pango-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain cairo freetype fontconfig fribidi glib json-glib harfbuzz" +PKG_DEPENDS_CONFIG="cairo" +PKG_LONGDESC="The Pango library for layout and rendering of internationalized text." + +configure_package() { + # Build with X11 support + if [ ${DISPLAYSERVER} = "x11" ]; then + PKG_DEPENDS_TARGET+=" libX11 libXft" + PKG_DEPENDS_CONFIG+=" libXft" + PKG_BUILD_FLAGS="-sysroot" + fi +} + +pre_configure_target() { + PKG_MESON_OPTS_TARGET="-Dgtk_doc=false \ + -Dintrospection=disabled" +} diff --git a/packages/graphics/spirv-headers/package.mk b/packages/graphics/spirv-headers/package.mk new file mode 100644 index 0000000000..2e8e4d5731 --- /dev/null +++ b/packages/graphics/spirv-headers/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Frank Hartung (supervisedthinking (@) gmail.com) +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="spirv-headers" +# The SPIRV-Headers pkg_version needs to match the compatible (known_good) glslang pkg_version. +# https://raw.githubusercontent.com/KhronosGroup/glslang/${PKG_VERSION}/known_good.json +# When updating glslang pkg_version please update to the known_good spirv-headers pkg_version. +# When updating spirv-llvm-translator pkg_version validate the minimum githash from +# https://github.com/KhronosGroup/SPIRV-LLVM-Translator/blob/main/spirv-headers-tag.conf +PKG_VERSION="2a611a970fdbc41ac2e3e328802aed9985352dca" +PKG_SHA256="c2225a49c3d7efa5c4f4ce4a6b42081e6ea3daca376f3353d9d7c2722d77a28a" +PKG_LICENSE="Apache-2.0" +PKG_SITE="https://github.com/KhronosGroup/SPIRV-headers" +PKG_URL="https://github.com/KhronosGroup/SPIRV-headers/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="" +PKG_LONGDESC="SPIRV-Headers" +PKG_TOOLCHAIN="manual" diff --git a/packages/graphics/spirv-llvm-translator/package.mk b/packages/graphics/spirv-llvm-translator/package.mk new file mode 100644 index 0000000000..736a7d8a60 --- /dev/null +++ b/packages/graphics/spirv-llvm-translator/package.mk @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2024-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="spirv-llvm-translator" +PKG_VERSION="20.1.4" +PKG_SHA256="f6c414f9384c8f68775d9461e55e7c492f01759f5a1754f30dad4cbfb049c7d7" +PKG_LICENSE="LLVM" +PKG_SITE="https://github.com/KhronosGroup/SPIRV-LLVM-Translator" +PKG_URL="https://github.com/KhronosGroup/SPIRV-LLVM-Translator/archive/v${PKG_VERSION}.tar.gz" +PKG_LONGDESC="SPIRV-LLVM-Translator" +PKG_TOOLCHAIN="manual" diff --git a/packages/graphics/spirv-tools/package.mk b/packages/graphics/spirv-tools/package.mk new file mode 100644 index 0000000000..8e383967b0 --- /dev/null +++ b/packages/graphics/spirv-tools/package.mk @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Frank Hartung (supervisedthinking (@) gmail.com) +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="spirv-tools" +# The SPIRV-Tools pkg_version needs to match the compatible (known_good) glslang pkg_version. +# https://raw.githubusercontent.com/KhronosGroup/glslang/${PKG_VERSION}/known_good.json +# When updating glslang pkg_version please update to the known_good spirv-tools pkg_version. +PKG_VERSION="33e02568181e3312f49a3cf33df470bf96ef293a" +PKG_SHA256="44d1005880c583fc00a0fb41c839214c68214b000ea8dcb54d352732fee600ff" +PKG_LICENSE="Apache-2.0" +PKG_SITE="https://github.com/KhronosGroup/SPIRV-Tools" +PKG_URL="https://github.com/KhronosGroup/SPIRV-Tools/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="toolchain:host" +PKG_DEPENDS_UNPACK="spirv-headers" +PKG_LONGDESC="The SPIR-V Tools project provides an API and commands for processing SPIR-V modules." + +PKG_CMAKE_OPTS_HOST="-DSPIRV_SKIP_TESTS=ON" + +post_unpack() { + mkdir -p ${PKG_BUILD}/external/spirv-headers + tar --strip-components=1 \ + -xf "${SOURCES}/spirv-headers/spirv-headers-$(get_pkg_version spirv-headers).tar.gz" \ + -C "${PKG_BUILD}/external/spirv-headers" +} diff --git a/packages/graphics/tiff/package.mk b/packages/graphics/tiff/package.mk new file mode 100644 index 0000000000..b628b6f189 --- /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.7.0" +PKG_SHA256="67160e3457365ab96c5b3286a0903aa6e78bdc44c4bc737d2e486bcecb6ba976" +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 -gold" + +PKG_CMAKE_OPTS_TARGET="-DBUILD_SHARED_LIBS=OFF \ + -Dtiff-tools=OFF \ + -Dtiff-tests=OFF \ + -Dtiff-contrib=OFF \ + -Dtiff-docs=OFF \ + -Dmdi=OFF \ + -Djbig=OFF \ + -Dlzma=OFF \ + -Dzstd=OFF \ + -Dwebp=OFF \ + -Dcxx=ON \ + -Djpeg=ON" diff --git a/packages/graphics/tiff/patches/tiff-0001-cmake--Replace-CMath--CMath-with-direct-link-to-avoid-export-of-target.patch b/packages/graphics/tiff/patches/tiff-0001-cmake--Replace-CMath--CMath-with-direct-link-to-avoid-export-of-target.patch new file mode 100644 index 0000000000..e1be5f398a --- /dev/null +++ b/packages/graphics/tiff/patches/tiff-0001-cmake--Replace-CMath--CMath-with-direct-link-to-avoid-export-of-target.patch @@ -0,0 +1,87 @@ +From 67f73084ca824e6c2465c47a5b67b16b5beca569 Mon Sep 17 00:00:00 2001 +From: Roger Leigh +Date: Thu, 14 Dec 2023 18:30:31 +0000 +Subject: [PATCH] cmake: Replace CMath::CMath with direct link to avoid export + of target + +Link with CMATH_LIBRARIES instead of CMath::CMath. While this +will still be exported, it will be available on the host system. +--- + cmake/FindCMath.cmake | 12 +++--------- + contrib/dbs/CMakeLists.txt | 10 ++++++++-- + libtiff/CMakeLists.txt | 6 +++--- + tools/unsupported/CMakeLists.txt | 5 ++++- + 4 files changed, 18 insertions(+), 15 deletions(-) + +diff --git a/cmake/FindCMath.cmake b/cmake/FindCMath.cmake +index ad922180b..c4833af7e 100644 +--- a/cmake/FindCMath.cmake ++++ b/cmake/FindCMath.cmake +@@ -55,18 +55,12 @@ if(CMath_FOUND) + set(CMath_INCLUDE_DIRS) + endif() + if(NOT CMath_LIBRARIES) ++ if(NOT CMath_LIBRARY) ++ unset(CMath_LIBRARY) ++ endif() + if (CMath_LIBRARY) + set(CMath_LIBRARIES ${CMath_LIBRARY}) + endif() + endif() + +- if(NOT TARGET CMath::CMath) +- if(CMath_LIBRARIES) +- add_library(CMath::CMath UNKNOWN IMPORTED) +- set_target_properties(CMath::CMath PROPERTIES +- IMPORTED_LOCATION "${CMath_LIBRARY}") +- else() +- add_library(CMath::CMath INTERFACE IMPORTED) +- endif() +- endif() + endif() +diff --git a/contrib/dbs/CMakeLists.txt b/contrib/dbs/CMakeLists.txt +index 74b2a02a0..18b7ea8b4 100644 +--- a/contrib/dbs/CMakeLists.txt ++++ b/contrib/dbs/CMakeLists.txt +@@ -26,13 +26,19 @@ add_executable(tiff-bi tiff-bi.c) + target_link_libraries(tiff-bi tiff tiff_port) + + add_executable(tiff-grayscale tiff-grayscale.c) +-target_link_libraries(tiff-grayscale tiff tiff_port CMath::CMath) ++target_link_libraries(tiff-grayscale PRIVATE tiff tiff_port) ++if(CMath_LIBRARIES) ++ target_link_libraries(tiff-grayscale PRIVATE ${CMath_LIBRARIES}) ++endif() + + add_executable(tiff-palette tiff-palette.c) + target_link_libraries(tiff-palette tiff tiff_port) + + add_executable(tiff-rgb tiff-rgb.c) +-target_link_libraries(tiff-rgb tiff tiff_port CMath::CMath) ++target_link_libraries(tiff-rgb PRIVATE tiff tiff_port) ++if(CMath_LIBRARIES) ++ target_link_libraries(tiff-rgb PRIVATE ${CMath_LIBRARIES}) ++endif() + + if(WEBP_SUPPORT AND EMSCRIPTEN) + # Emscripten is pretty finnicky about linker flags. +diff --git a/libtiff/CMakeLists.txt b/libtiff/CMakeLists.txt +index a8aa0c320..a65f3c230 100755 +--- a/libtiff/CMakeLists.txt ++++ b/libtiff/CMakeLists.txt +@@ -184,9 +184,9 @@ if(WEBP_SUPPORT) + target_link_libraries(tiff PRIVATE WebP::webp) + string(APPEND tiff_requires_private " libwebp") + endif() +-if(CMath_LIBRARY) +- target_link_libraries(tiff PRIVATE CMath::CMath) +- list(APPEND tiff_libs_private_list "${CMath_LIBRARY}") ++if(CMath_LIBRARIES) ++ target_link_libraries(tiff PRIVATE ${CMath_LIBRARIES}) ++ list(APPEND tiff_libs_private_list "${CMath_LIBRARIES}") + endif() + + set(tiff_libs_private_list "${tiff_libs_private_list}" PARENT_SCOPE) +-- +GitLab + diff --git a/packages/graphics/vulkan/glslang/package.mk b/packages/graphics/vulkan/glslang/package.mk new file mode 100644 index 0000000000..a4a940f8d5 --- /dev/null +++ b/packages/graphics/vulkan/glslang/package.mk @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Frank Hartung (supervisedthinking (@) gmail.com) +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="glslang" +# The SPIRV-Tools & SPIRV-Headers pkg_version/s need to match the compatible (known_good) glslang pkg_version. +# https://raw.githubusercontent.com/KhronosGroup/glslang/${PKG_VERSION}/known_good.json +# When updating glslang pkg_version please update to the known_good spirv-tools & spirv-headers pkg_version/s. +PKG_VERSION="15.4.0" +PKG_SHA256="b16c78e7604b9be9f546ee35ad8b6db6f39bbbbfb19e8d038b6fe2ea5bba4ff4" +PKG_LICENSE="Apache-2.0" +PKG_SITE="https://github.com/KhronosGroup/glslang" +PKG_URL="https://github.com/KhronosGroup/glslang/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="toolchain:host Python3:host" +PKG_DEPENDS_TARGET="toolchain Python3" +PKG_LONGDESC="Khronos-reference front end for GLSL/ESSL, partial front end for HLSL, and a SPIR-V generator." +PKG_DEPENDS_UNPACK="spirv-headers spirv-tools" + +PKG_CMAKE_OPTS_COMMON="-DBUILD_EXTERNAL=ON \ + -DENABLE_SPVREMAPPER=OFF \ + -DENABLE_GLSLANG_JS=OFF \ + -DENABLE_RTTI=OFF \ + -DENABLE_EXCEPTIONS=OFF \ + -DENABLE_OPT=ON \ + -DENABLE_PCH=ON \ + -DGLSLANG_TESTS=OFF \ + -Wno-dev" + +post_unpack() { + # Enables SPIR-V optimizer capability needed for ENABLE_OPT CMake build option + mkdir -p ${PKG_BUILD}/External/spirv-tools + tar --strip-components=1 \ + -xf "${SOURCES}/spirv-tools/spirv-tools-$(get_pkg_version spirv-tools).tar.gz" \ + -C "${PKG_BUILD}/External/spirv-tools" + mkdir -p ${PKG_BUILD}/External/spirv-tools/external/spirv-headers + tar --strip-components=1 \ + -xf "${SOURCES}/spirv-headers/spirv-headers-$(get_pkg_version spirv-headers).tar.gz" \ + -C "${PKG_BUILD}/External/spirv-tools/external/spirv-headers" +} + +pre_configure_host() { + PKG_CMAKE_OPTS_HOST+="${PKG_CMAKE_OPTS_COMMON} \ + -DBUILD_SHARED_LIBS=OFF" + +} + +pre_configure_target() { + PKG_CMAKE_OPTS_TARGET+="${PKG_CMAKE_OPTS_COMMON} \ + -DBUILD_SHARED_LIBS=ON \ + -DENABLE_GLSLANG_BINARIES=OFF" +} diff --git a/packages/graphics/vulkan/glslang/patches/glslang-100.01-build-static-spirv-tools.patch b/packages/graphics/vulkan/glslang/patches/glslang-100.01-build-static-spirv-tools.patch new file mode 100644 index 0000000000..ab3ac57c9a --- /dev/null +++ b/packages/graphics/vulkan/glslang/patches/glslang-100.01-build-static-spirv-tools.patch @@ -0,0 +1,12 @@ +--- a/External/CMakeLists.txt ++++ b/External/CMakeLists.txt +@@ -71,7 +71,8 @@ endif() + if(ENABLE_OPT AND NOT TARGET SPIRV-Tools-opt) + if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/spirv-tools) + set(SPIRV_SKIP_TESTS ON CACHE BOOL "Skip building SPIRV-Tools tests") +- add_subdirectory(spirv-tools) ++ set(BUILD_SHARED_LIBS OFF CACHE BOOL "Disable build shared libs" FORCE) ++ add_subdirectory(spirv-tools EXCLUDE_FROM_ALL) + endif() + endif() + diff --git a/packages/graphics/vulkan/vkmark/package.mk b/packages/graphics/vulkan/vkmark/package.mk new file mode 100644 index 0000000000..b44e762e70 --- /dev/null +++ b/packages/graphics/vulkan/vkmark/package.mk @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="vkmark" +PKG_VERSION="2025.01" +PKG_SHA256="1ae362844344d0f9878b7a3f13005f77eae705108892a4e8abf237d452d37edc" +PKG_LICENSE="LGPL-2.1-or-later" +PKG_SITE="https://github.com/vkmark/vkmark" +PKG_URL="https://github.com/vkmark/vkmark/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain glm assimp vulkan-loader" +PKG_LONGDESC="Vulkan benchmark" +PKG_BUILD_FLAGS="-parallel +speed" + +case ${DISPLAYSERVER} in + wl) + PKG_DEPENDS_TARGET+=" wayland wayland-protocols" + PKG_MESON_OPTS_TARGET="-Dwayland=true" + ;; + x11) + PKG_DEPENDS_TARGET+=" libxcb xcb-util-wm" + PKG_MESON_OPTS_TARGET="-Dxcb=true" + ;; + *) + PKG_DEPENDS_TARGET+=" systemd libdrm mesa" + PKG_MESON_OPTS_TARGET="-Dkms=true" + ;; +esac diff --git a/packages/graphics/vulkan/vkmark/patches/vkmark-0001-fix-sysroot.patch b/packages/graphics/vulkan/vkmark/patches/vkmark-0001-fix-sysroot.patch new file mode 100644 index 0000000000..6f9d3f0eca --- /dev/null +++ b/packages/graphics/vulkan/vkmark/patches/vkmark-0001-fix-sysroot.patch @@ -0,0 +1,11 @@ +--- a/src/meson.build 2025-01-23 08:33:27.000000000 +0000 ++++ b/src/meson.build 2025-05-02 04:43:30.867280490 +0000 +@@ -1,7 +1,7 @@ + prog_python = find_program('python3') + + vk_xml = join_paths([ +- vulkan_dep.get_pkgconfig_variable('prefix'), ++ vulkan_dep.get_pkgconfig_variable('includedir'), '..', + 'share', 'vulkan', 'registry', + 'vk.xml' + ]) diff --git a/packages/graphics/vulkan/vkmark/patches/vkmark-0002-fix-custom-dispatchers.patch b/packages/graphics/vulkan/vkmark/patches/vkmark-0002-fix-custom-dispatchers.patch new file mode 100644 index 0000000000..c6470df34e --- /dev/null +++ b/packages/graphics/vulkan/vkmark/patches/vkmark-0002-fix-custom-dispatchers.patch @@ -0,0 +1,73 @@ +From 573820a061e9d76a4cbcccd23df82581ac9d193c Mon Sep 17 00:00:00 2001 +From: Philipp Zabel +Date: Wed, 10 Dec 2025 10:59:49 +0100 +Subject: [PATCH 1/2] core: Register custom dispatcher with isDispatchLoader + +Since Vulkan 1.4.333, custom dispatch loaders must be registered +with isDispatchLoader to be recognized. +--- + src/vulkan_state.cpp | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/src/vulkan_state.cpp b/src/vulkan_state.cpp +index a36b299..3dbb48b 100644 +--- a/src/vulkan_state.cpp ++++ b/src/vulkan_state.cpp +@@ -65,6 +65,18 @@ class DebugUtilsDispatcher + + } + ++#if VK_HEADER_VERSION >= 333 && VK_HEADER_VERSION <= 337 ++namespace vk::detail { ++ ++template <> ++struct isDispatchLoader<::DebugUtilsDispatcher> ++{ ++ static VULKAN_HPP_CONST_OR_CONSTEXPR bool value = true; ++}; ++ ++} ++#endif ++ + VulkanState::VulkanState(VulkanWSI& vulkan_wsi, ChoosePhysicalDeviceStrategy const& pd_strategy, bool debug) + : debug_enabled(debug) + { + +From 9bf505fff7a2825baf192d2d694f5f6a79470da6 Mon Sep 17 00:00:00 2001 +From: Philipp Zabel +Date: Wed, 10 Dec 2025 10:59:49 +0100 +Subject: [PATCH 2/2] kms: Register custom dispatcher with isDispatchLoader + +Since Vulkan 1.4.333, custom dispatch loaders must be registered +with isDispatchLoader to be recognized. +--- + src/ws/kms_window_system.cpp | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/src/ws/kms_window_system.cpp b/src/ws/kms_window_system.cpp +index 4bf7838..d378778 100644 +--- a/src/ws/kms_window_system.cpp ++++ b/src/ws/kms_window_system.cpp +@@ -474,6 +474,22 @@ class GetFormatProperties2Dispatcher + PFN_vkGetPhysicalDeviceFormatProperties2KHR vkGetPhysicalDeviceFormatProperties2KHR; + }; + ++} ++ ++#if VK_HEADER_VERSION >= 333 && VK_HEADER_VERSION <= 337 ++namespace vk::detail { ++ ++template <> ++struct isDispatchLoader<::GetFormatProperties2Dispatcher> ++{ ++ static VULKAN_HPP_CONST_OR_CONSTEXPR bool value = true; ++}; ++ ++} ++#endif ++ ++namespace { ++ + std::vector vk_get_supported_mods_for_format(VulkanState& vulkan, + vk::Format format) + { diff --git a/packages/graphics/vulkan/volk/package.mk b/packages/graphics/vulkan/volk/package.mk new file mode 100644 index 0000000000..51e99ffc88 --- /dev/null +++ b/packages/graphics/vulkan/volk/package.mk @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2023-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="volk" +PKG_VERSION="1.4.304" +PKG_SHA256="ab3d4a8ccaeb32652259cdd008399504a41792675b0421d90b67729ee274746f" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/zeux/volk" +PKG_URL="https://github.com/zeux/volk/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain vulkan-headers" +PKG_LONGDESC="Meta loader for Vulkan API" + +PKG_CMAKE_OPTS_TARGET="-DVOLK_INSTALL=on" diff --git a/packages/graphics/vulkan/vulkan-headers/package.mk b/packages/graphics/vulkan/vulkan-headers/package.mk new file mode 100644 index 0000000000..f12abc2653 --- /dev/null +++ b/packages/graphics/vulkan/vulkan-headers/package.mk @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Frank Hartung (supervisedthinking (@) gmail.com) +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="vulkan-headers" +PKG_VERSION="1.4.321" +PKG_SHA256="7c1874f9186d9e7d5245e279cdccaa77a66ed8f52871b428630aeb771dc7623c" +PKG_LICENSE="Apache-2.0" +PKG_SITE="https://github.com/KhronosGroup/Vulkan-Headers" +PKG_URL="https://github.com/KhronosGroup/Vulkan-Headers/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="toolchain:host" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Vulkan Header files and API registry" diff --git a/packages/graphics/vulkan/vulkan-loader/package.mk b/packages/graphics/vulkan/vulkan-loader/package.mk new file mode 100644 index 0000000000..3491b814d7 --- /dev/null +++ b/packages/graphics/vulkan/vulkan-loader/package.mk @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Frank Hartung (supervisedthinking (@) gmail.com) +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="vulkan-loader" +PKG_VERSION="1.4.321" +PKG_SHA256="00669f6bb2db35c8df07f0b118c09bfe0ebffecaad7d80647a429eece0e37ac3" +PKG_LICENSE="Apache-2.0" +PKG_SITE="https://github.com/KhronosGroup/Vulkan-Loader" +PKG_URL="https://github.com/KhronosGroup/Vulkan-Loader/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain Python3:host vulkan-headers" +PKG_LONGDESC="Vulkan Installable Client Driver (ICD) Loader." + +configure_package() { + # Displayserver Support + if [ "${DISPLAYSERVER}" = "x11" ]; then + PKG_DEPENDS_TARGET+=" libxcb libX11 libXrandr" + elif [ "${DISPLAYSERVER}" = "wl" ]; then + PKG_DEPENDS_TARGET+=" wayland" + fi +} + +pre_configure_target() { + PKG_CMAKE_OPTS_TARGET="-DBUILD_TESTS=OFF" + + # GAS / GNU Assembler is only supported by aarch64 & x86_64 + if [ "${ARCH}" = "arm" ]; then + PKG_CMAKE_OPTS_TARGET+=" -DUSE_GAS=OFF" + fi + + if [ "${DISPLAYSERVER}" = "x11" ]; then + PKG_CMAKE_OPTS_TARGET+=" -DBUILD_WSI_XCB_SUPPORT=ON \ + -DBUILD_WSI_XLIB_SUPPORT=ON \ + -DBUILD_WSI_WAYLAND_SUPPORT=OFF" + elif [ "${DISPLAYSERVER}" = "wl" ]; then + PKG_CMAKE_OPTS_TARGET+=" -DBUILD_WSI_XCB_SUPPORT=OFF \ + -DBUILD_WSI_XLIB_SUPPORT=OFF \ + -DBUILD_WSI_WAYLAND_SUPPORT=ON" + else + PKG_CMAKE_OPTS_TARGET+=" -DBUILD_WSI_XCB_SUPPORT=OFF \ + -DBUILD_WSI_XLIB_SUPPORT=OFF \ + -DBUILD_WSI_WAYLAND_SUPPORT=OFF" + fi +} diff --git a/packages/graphics/vulkan/vulkan-tools/package.mk b/packages/graphics/vulkan/vulkan-tools/package.mk new file mode 100644 index 0000000000..12a321a46b --- /dev/null +++ b/packages/graphics/vulkan/vulkan-tools/package.mk @@ -0,0 +1,64 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Frank Hartung (supervisedthinking (@) gmail.com) +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="vulkan-tools" +PKG_VERSION="1.4.321" +PKG_SHA256="f5f75413d21d1508b746a3d0594961d64c7155ee5f4f28245b9547c1b4697d8d" +PKG_LICENSE="Apache-2.0" +PKG_SITE="https://github.com/KhronosGroup/Vulkan-Tools" +PKG_URL="https://github.com/KhronosGroup/Vulkan-tools/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain volk vulkan-loader glslang:host Python3:host" +PKG_LONGDESC="This project provides Khronos official Vulkan Tools and Utilities." + +configure_package() { + # Displayserver Support + if [ "${DISPLAYSERVER}" = "x11" ]; then + PKG_DEPENDS_TARGET+=" libxcb libX11" + elif [ "${DISPLAYSERVER}" = "wl" ]; then + PKG_DEPENDS_TARGET+=" wayland wayland-protocols" + fi +} + +pre_configure_target() { + PKG_CMAKE_OPTS_TARGET="-DVULKAN_HEADERS_INSTALL_DIR=${SYSROOT_PREFIX}/usr \ + -DBUILD_VULKANINFO=ON \ + -DBUILD_ICD=OFF \ + -DBUILD_WSI_DIRECTFB_SUPPORT=OFF \ + -DPython3_EXECUTABLE=${TOOLCHAIN}/bin/python3 \ + -Wno-dev" + + if [ "${DISPLAYSERVER}" = "x11" ]; then + PKG_CMAKE_OPTS_TARGET+=" -DBUILD_CUBE=ON \ + -DCOMPILE_CUBE_SHADERS=ON \ + -DBUILD_WSI_XCB_SUPPORT=ON \ + -DBUILD_WSI_XLIB_SUPPORT=ON \ + -DBUILD_WSI_WAYLAND_SUPPORT=OFF \ + -DCUBE_WSI_SELECTION=XCB" + elif [ "${DISPLAYSERVER}" = "wl" ]; then + PKG_CMAKE_OPTS_TARGET+=" -DBUILD_CUBE=ON \ + -DCOMPILE_CUBE_SHADERS=ON \ + -DBUILD_WSI_XCB_SUPPORT=OFF \ + -DBUILD_WSI_XLIB_SUPPORT=OFF \ + -DBUILD_WSI_WAYLAND_SUPPORT=ON \ + -DCUBE_WSI_SELECTION=WAYLAND" + else + PKG_CMAKE_OPTS_TARGET+=" -DBUILD_CUBE=ON \ + -DCOMPILE_CUBE_SHADERS=ON \ + -DBUILD_WSI_XCB_SUPPORT=OFF \ + -DBUILD_WSI_XLIB_SUPPORT=OFF \ + -DBUILD_WSI_WAYLAND_SUPPORT=OFF \ + -DCUBE_WSI_SELECTION=DISPLAY" + 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" \{} \; +} + +post_makeinstall_target() { + # Clean up - two graphic test tools are superfluous + safe_remove ${INSTALL}/usr/bin/vkcubepp +} diff --git a/packages/graphics/vulkan/vulkan-tools/patches/vulkan-tools-995.01-cmakelists-opts.patch b/packages/graphics/vulkan/vulkan-tools/patches/vulkan-tools-995.01-cmakelists-opts.patch new file mode 100644 index 0000000000..2b81017f78 --- /dev/null +++ b/packages/graphics/vulkan/vulkan-tools/patches/vulkan-tools-995.01-cmakelists-opts.patch @@ -0,0 +1,25 @@ +From c9c7423f2d0ecfc7ab354d2a3d9ea9c2e4998416 Mon Sep 17 00:00:00 2001 +From: SupervisedThinking +Date: Thu, 18 Nov 2021 15:02:55 +0100 +Subject: [PATCH] CMakeLists: add CMake options for cube & vulkaninfo + +--- + CMakeLists.txt | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 422b7d2cc..d123c9dc5 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -47,6 +47,11 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake") + add_link_options(-fsanitize=address) + endif() + endif() ++option(BUILD_WSI_XCB_SUPPORT "Build XCB WSI support" ON) ++option(BUILD_WSI_XLIB_SUPPORT "Build Xlib WSI support" ON) ++option(BUILD_WSI_WAYLAND_SUPPORT "Build Wayland WSI support" ON) ++option(BUILD_WSI_DIRECTFB_SUPPORT "Build DirectFB WSI support" OFF) ++set(CUBE_WSI_SELECTION "XCB" CACHE STRING "Select WSI target for vkcube (XCB, XLIB, WAYLAND, DIRECTFB, DISPLAY)") + + set_property(GLOBAL PROPERTY USE_FOLDERS ON) + diff --git a/packages/lang/Python3/package.mk b/packages/lang/Python3/package.mk new file mode 100644 index 0000000000..7f2b44b895 --- /dev/null +++ b/packages/lang/Python3/package.mk @@ -0,0 +1,141 @@ +# 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.13.5" +PKG_SHA256="93e583f243454e6e9e4588ca2c2662206ad961659863277afcdb96801647d640" +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 xz:host libffi:host util-linux:host autoconf-archive:host openssl:host" +PKG_DEPENDS_TARGET="autotools:host gcc:host Python3:host sqlite expat zlib bzip2 xz openssl libffi readline ncurses util-linux" +PKG_LONGDESC="Python3 is an interpreted object-oriented programming language." +PKG_BUILD_FLAGS="-cfg-libs -cfg-libs:host" +PKG_TOOLCHAIN="autotools" + +PKG_PYTHON_VERSION="python3.13" + +PKG_CONFIGURE_OPTS_HOST="ac_cv_prog_HAS_HG=/bin/false + ac_cv_prog_SVNVERSION=/bin/false + py_cv_module_unicodedata=yes + py_cv_module__bz2=n/a + py_cv_module__codecs_cn=n/a + py_cv_module__codecs_hk=n/a + py_cv_module__codecs_iso2022=n/a + py_cv_module__codecs_jp=n/a + py_cv_module__codecs_kr=n/a + py_cv_module__codecs_tw=n/a + py_cv_module__decimal=n/a + py_cv_module_nis=n/a + py_cv_module_ossaudiodev=n/a + py_cv_module__dbm=n/a + py_cv_module__gdbm=n/a + --disable-pyc-build + --disable-sqlite3 + --without-readline + --disable-tk + --disable-curses + --disable-pydoc + --disable-test-modules + --disable-idle3 + --with-expat=builtin + --with-doc-strings + --without-pymalloc + --with-ensurepip=no + --enable-shared +" + +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 + py_cv_module_unicodedata=yes + py_cv_module__codecs_cn=n/a + py_cv_module__codecs_hk=n/a + py_cv_module__codecs_iso2022=n/a + py_cv_module__codecs_jp=n/a + py_cv_module__codecs_kr=n/a + py_cv_module__codecs_tw=n/a + py_cv_module__decimal=n/a + py_cv_module_nis=n/a + py_cv_module_ossaudiodev=n/a + py_cv_module__dbm=n/a + --disable-pyc-build + --enable-sqlite3 + --with-readline + --disable-tk + --enable-curses + --disable-pydoc + --disable-test-modules + --disable-idle3 + --with-expat=system + --with-doc-strings + --without-pymalloc + --without-ensurepip + --enable-ipv6 + --with-build-python=${TOOLCHAIN}/bin/python + --enable-shared +" + +pre_configure_host() { + # control patch Python3-0300-generate-legacy-pyc-bytecode + # this needs to be set when building host based py file + # do not set this for py compiles being done for target use + export DONT_BUILD_LEGACY_PYC=1 +} + +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 -fr ${PKG_BUILD}/.${HOST_NAME}/build/temp.* +} + +post_make_target() { + # fix sysconfig paths for cross compiling + PKG_SYSCONFIG_FILE=$(find ${PKG_BUILD}/.${TARGET_NAME} -not -path '*/__pycache__/*' -name '_sysconfigdata__*.py') + sed -e "s,\([\'|\ ]\)/usr/include,\1${SYSROOT_PREFIX}/usr/include,g" -i ${PKG_SYSCONFIG_FILE} + sed -e "s,\([\'|\ ]\)/usr/lib,\1${SYSROOT_PREFIX}/usr/lib,g" -i ${PKG_SYSCONFIG_FILE} +} + +pre_configure_target() { + export PYTHON_MODULES_INCLUDE="${TARGET_INCDIR}" + export PYTHON_MODULES_LIB="${TARGET_LIBDIR}" + export DISABLED_EXTENSIONS="${PKG_PY_DISABLED_MODULES}" + export PKG_CONFIG_PATH="$(get_install_dir xz)/usr/lib/pkgconfig:${PKG_CONFIG_PATH}" +} + +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 test; do + rm -rf ${PKG_INSTALL_PATH_LIB}/${dir} + done + + safe_remove ${INSTALL}/usr/bin/python*-config + + 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/0001-Make-the-build-of-pyc-files-conditional.patch b/packages/lang/Python3/patches/0001-Make-the-build-of-pyc-files-conditional.patch new file mode 100644 index 0000000000..fcfc261241 --- /dev/null +++ b/packages/lang/Python3/patches/0001-Make-the-build-of-pyc-files-conditional.patch @@ -0,0 +1,59 @@ +From 5d0f69ce7fc05adbd3c71e113c11da0aedbca33a 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 +[ Adam Duskett: ported to Python 3.12.0 ] +Signed-off-by: Adam Duskett +--- + Makefile.pre.in | 2 ++ + configure.ac | 6 ++++++ + 2 files changed, 8 insertions(+) + +diff --git a/Makefile.pre.in b/Makefile.pre.in +index 4a957fb004..9c5f3c031a 100644 +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -2576,6 +2576,7 @@ libinstall: all $(srcdir)/Modules/xxmodule.c + patch --force --reject-file "$(abs_builddir)/app-store-compliance.rej" --strip 2 --directory "$(DESTDIR)$(LIBDEST)" --input "$(abs_srcdir)/$(APP_STORE_COMPLIANCE_PATCH)" || true ; \ + fi + @ # Build PYC files for the 3 optimization levels (0, 1, 2) ++ifeq (@PYC_BUILD@,yes) + -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ + $(PYTHON_FOR_BUILD) -Wi $(DESTDIR)$(LIBDEST)/compileall.py \ + -o 0 -o 1 -o 2 $(COMPILEALL_OPTS) -d $(LIBDEST) -f \ +@@ -2585,7 +2586,8 @@ libinstall: all $(srcdir)/Modules/xxmodule.c + $(PYTHON_FOR_BUILD) -Wi $(DESTDIR)$(LIBDEST)/compileall.py \ + -o 0 -o 1 -o 2 $(COMPILEALL_OPTS) -d $(LIBDEST)/site-packages -f \ + -x badsyntax $(DESTDIR)$(LIBDEST)/site-packages ++endif + + # bpo-21536: Misc/python-config.sh is generated in the build directory + # from $(srcdir)Misc/python-config.sh.in. + python-config: $(srcdir)/Misc/python-config.in Misc/python-config.sh +diff --git a/configure.ac b/configure.ac +index 8a32cb58f4..611c33949a 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1510,6 +1510,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 ]) ++ + # Apple 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.34.1 + diff --git a/packages/lang/Python3/patches/0002-Disable-buggy_getaddrinfo-configure-test-when-cross-.patch b/packages/lang/Python3/patches/0002-Disable-buggy_getaddrinfo-configure-test-when-cross-.patch new file mode 100644 index 0000000000..e774e442dc --- /dev/null +++ b/packages/lang/Python3/patches/0002-Disable-buggy_getaddrinfo-configure-test-when-cross-.patch @@ -0,0 +1,27 @@ +From 3a0d7824f7ddd4dd0336c8419cb4246ba936d711 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 611c33949a..059ac2f883 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -5428,7 +5428,7 @@ fi])) + dnl if ac_cv_func_getaddrinfo + ]) + +-if test "$ac_cv_func_getaddrinfo" = no -o "$ac_cv_buggy_getaddrinfo" = yes ++if test "$ac_cv_func_getaddrinfo" = no || test "$cross_compiling" != "yes" -a "$ac_cv_buggy_getaddrinfo" = yes + then + AS_VAR_IF([ipv6], [yes], [ + AC_MSG_ERROR([m4_normalize([ +-- +2.34.1 + diff --git a/packages/lang/Python3/patches/0003-Add-an-option-to-disable-pydoc.patch b/packages/lang/Python3/patches/0003-Add-an-option-to-disable-pydoc.patch new file mode 100644 index 0000000000..6d33df7793 --- /dev/null +++ b/packages/lang/Python3/patches/0003-Add-an-option-to-disable-pydoc.patch @@ -0,0 +1,84 @@ +From f910bdee70b07792c136aaced3850a08eaaafdee 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 +[ Adam Duskett: ported to Python 3.10.0 ] +Signed-off-by: Adam Duskett +[ Adam Duskett: ported to Python 3.12.1 ] +Signed-off-by: Adam Duskett +--- + Makefile.pre.in | 9 ++++++++- + configure.ac | 6 ++++++ + 2 files changed, 14 insertions(+), 1 deletion(-) + +diff --git a/Makefile.pre.in b/Makefile.pre.in +index 9c5f3c031a..2243a658a9 100644 +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -2293,7 +2293,9 @@ bininstall: commoninstall 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 + 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)) \ +@@ -2343,7 +2345,6 @@ LIBSUBDIRS= asyncio \ + logging \ + multiprocessing multiprocessing/dummy \ + pathlib \ +- pydoc_data \ + re \ + site-packages \ + sqlite3 \ +@@ -2496,6 +2497,10 @@ TESTSUBDIRS= idlelib/idle_test \ + + COMPILEALL_OPTS=-j0 + ++ifeq (@PYDOC@,yes) ++LIBSUBDIRS += pydoc_data ++endif ++ + TEST_MODULES=@TEST_MODULES@ + + .PHONY: libinstall +@@ -2723,7 +2728,9 @@ libainstall: all scripts + $(INSTALL_SCRIPT) python-config.py $(DESTDIR)$(LIBPL)/python-config.py + $(INSTALL_SCRIPT) python-config $(DESTDIR)$(BINDIR)/python$(LDVERSION)-config + $(INSTALL_SCRIPT) $(SCRIPT_IDLE) $(DESTDIR)$(BINDIR)/idle$(VERSION) ++ifeq (@PYDOC@,yes) + $(INSTALL_SCRIPT) $(SCRIPT_PYDOC) $(DESTDIR)$(BINDIR)/pydoc$(VERSION) ++endif + @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:"; \ +diff --git a/configure.ac b/configure.ac +index 059ac2f883..1a2dd28d1e 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -4636,6 +4636,12 @@ AS_VAR_IF([posix_threads], [stub], [ + AC_DEFINE([HAVE_PTHREAD_STUBS], [1], [Define if platform requires stubbed pthreads support]) + ]) + ++AC_SUBST(PYDOC) ++ ++AC_ARG_ENABLE(pydoc, ++ AS_HELP_STRING([--disable-pydoc], [disable pydoc]), ++ [ PYDOC="${enableval}" ], [ PYDOC=yes ]) ++ + # Check for enable-ipv6 + AH_TEMPLATE([ENABLE_IPV6], [Define if --enable-ipv6 is specified]) + AC_MSG_CHECKING([if --enable-ipv6 is specified]) +-- +2.34.1 + diff --git a/packages/lang/Python3/patches/0005-Add-an-option-to-disable-IDLE.patch b/packages/lang/Python3/patches/0005-Add-an-option-to-disable-IDLE.patch new file mode 100644 index 0000000000..293c668254 --- /dev/null +++ b/packages/lang/Python3/patches/0005-Add-an-option-to-disable-IDLE.patch @@ -0,0 +1,83 @@ +From ffa7fbceb54918eb518474c8f821fda0a58cf181 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 +[ Adam Duskett: ported to Python 3.10.0 ] +Signed-off-by: Adam Duskett +[ Adam Duskett: ported to Python 3.12.1 ] +Signed-off-by: Adam Duskett +--- + Makefile.pre.in | 9 ++++++++- + configure.ac | 6 ++++++ + 2 files changed, 14 insertions(+), 1 deletion(-) + +diff --git a/Makefile.pre.in b/Makefile.pre.in +index 3f314d1354..5fad7f82fb 100644 +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -2291,7 +2291,9 @@ bininstall: commoninstall 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) +@@ -2339,7 +2341,6 @@ LIBSUBDIRS= asyncio \ + ensurepip ensurepip/_bundled \ + html \ + http \ +- idlelib idlelib/Icons \ + importlib importlib/resources importlib/metadata \ + json \ + logging \ +@@ -2501,6 +2502,10 @@ TESTSUBDIRS += test/test_lib2to3 \ + LIBSUBDIRS += pydoc_data + endif + ++ifeq (@IDLE@,yes) ++LIBSUBDIRS += idlelib idlelib/Icons ++endif ++ + TEST_MODULES=@TEST_MODULES@ + + .PHONY: libinstall +@@ -2727,7 +2732,9 @@ libainstall: all scripts + $(INSTALL_SCRIPT) $(srcdir)/install-sh $(DESTDIR)$(LIBPL)/install-sh + $(INSTALL_SCRIPT) python-config.py $(DESTDIR)$(LIBPL)/python-config.py + $(INSTALL_SCRIPT) python-config $(DESTDIR)$(BINDIR)/python$(LDVERSION)-config ++ifeq (@IDLE@,yes) + $(INSTALL_SCRIPT) $(SCRIPT_IDLE) $(DESTDIR)$(BINDIR)/idle$(VERSION) ++endif + ifeq (@PYDOC@,yes) + $(INSTALL_SCRIPT) $(SCRIPT_PYDOC) $(DESTDIR)$(BINDIR)/pydoc$(VERSION) + endif +diff --git a/configure.ac b/configure.ac +index f0354c580d..43086962e9 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -7788,6 +7788,12 @@ AC_ARG_ENABLE(lib2to3, + # substitute multiline block, must come after last PY_STDLIB_MOD() + AC_SUBST([MODULE_BLOCK]) + ++AC_SUBST(IDLE) ++ ++AC_ARG_ENABLE(idle3, ++ AS_HELP_STRING([--disable-idle3], [disable idle3 IDE]), ++ [ IDLE="${enableval}" ], [ IDLE=yes ]) ++ + # generate output files + AC_CONFIG_FILES(m4_normalize([ + Makefile.pre +-- +2.34.1 + diff --git a/packages/lang/Python3/patches/0006-configure.ac-move-PY_STDLIB_MOD_SET_NA-further-up.patch b/packages/lang/Python3/patches/0006-configure.ac-move-PY_STDLIB_MOD_SET_NA-further-up.patch new file mode 100644 index 0000000000..74719ef309 --- /dev/null +++ b/packages/lang/Python3/patches/0006-configure.ac-move-PY_STDLIB_MOD_SET_NA-further-up.patch @@ -0,0 +1,46 @@ +From 267516c76208e63b5a3ec7d4dead6c329d8763bb Mon Sep 17 00:00:00 2001 +From: Thomas Petazzoni +Date: Tue, 6 Feb 2024 22:46:59 +0100 +Subject: [PATCH] configure.ac: move PY_STDLIB_MOD_SET_NA further up + +We will need PY_STDLIB_MOD_SET_NA in next patches further up in the +configure.ac script. + +Signed-off-by: Thomas Petazzoni +--- + configure.ac | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 43086962e9..561e33f550 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -95,6 +95,12 @@ AC_DEFUN([PY_CHECK_EMSCRIPTEN_PORT], [ + AS_VAR_POPDEF([py_libs]) + ]) + ++# stdlib ++AC_DEFUN([PY_STDLIB_MOD_SET_NA], [ ++ m4_foreach([mod], [$@], [ ++ AS_VAR_SET([py_cv_module_]mod, [n/a])]) ++]) ++ + AC_SUBST([BASECPPFLAGS]) + if test "$srcdir" != . -a "$srcdir" != "$(pwd)"; then + # If we're building out-of-tree, we need to make sure the following +@@ -7457,12 +7463,6 @@ AC_ARG_ENABLE([test-modules], + _RESTORE_VAR([CPPFLAGS]) + + +-# stdlib +-AC_DEFUN([PY_STDLIB_MOD_SET_NA], [ +- m4_foreach([mod], [$@], [ +- AS_VAR_SET([py_cv_module_]mod, [n/a])]) +-]) +- + # stdlib not available + dnl Modules that are not available on some platforms + AS_CASE([$ac_sys_system], +-- +2.34.1 + diff --git a/packages/lang/Python3/patches/0007-Add-option-to-disable-the-sqlite3-module.patch b/packages/lang/Python3/patches/0007-Add-option-to-disable-the-sqlite3-module.patch new file mode 100644 index 0000000000..e797948114 --- /dev/null +++ b/packages/lang/Python3/patches/0007-Add-option-to-disable-the-sqlite3-module.patch @@ -0,0 +1,61 @@ +From a8566f6ee2a2b859ba5562f2d9f06cb4d271f277 Mon Sep 17 00:00:00 2001 +From: Thomas Petazzoni +Date: Tue, 6 Feb 2024 22:12:20 +0100 +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 +[ Adam Duskett: ported to Python 3.10.0 ] +Signed-off-by: Adam Duskett +Signed-off-by: Thomas Petazzoni +--- + Makefile.pre.in | 5 ++++- + configure.ac | 7 +++++++ + 2 files changed, 11 insertions(+), 1 deletion(-) + +diff --git a/Makefile.pre.in b/Makefile.pre.in +index 5fad7f82fb..7b6c9811a6 100644 +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -2348,7 +2348,6 @@ LIBSUBDIRS= asyncio \ + pathlib \ + re \ + site-packages \ +- sqlite3 \ + sysconfig \ + tkinter \ + tomllib \ +@@ -2506,6 +2505,10 @@ ifeq (@IDLE@,yes) + LIBSUBDIRS += idlelib idlelib/Icons + endif + ++ifeq (@SQLITE3@,yes) ++LIBSUBDIRS += sqlite3 ++endif ++ + TEST_MODULES=@TEST_MODULES@ + + .PHONY: libinstall +diff --git a/configure.ac b/configure.ac +index 561e33f550..d1c54bd67c 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -4642,6 +4642,13 @@ AS_VAR_IF([posix_threads], [stub], [ + AC_DEFINE([HAVE_PTHREAD_STUBS], [1], [Define if platform requires stubbed pthreads support]) + ]) + ++AC_SUBST(SQLITE3) ++AC_ARG_ENABLE(sqlite3, ++ AS_HELP_STRING([--disable-sqlite3], [disable sqlite3]), ++ [ SQLITE3="${enableval}" ], [ SQLITE3=yes ]) ++AS_IF([test "$SQLITE3" = "no"], ++ [PY_STDLIB_MOD_SET_NA([_sqlite3])]) ++ + AC_SUBST(PYDOC) + + AC_ARG_ENABLE(pydoc, +-- +2.34.1 + diff --git a/packages/lang/Python3/patches/0008-Add-an-option-to-disable-the-tk-module.patch b/packages/lang/Python3/patches/0008-Add-an-option-to-disable-the-tk-module.patch new file mode 100644 index 0000000000..82edfdf387 --- /dev/null +++ b/packages/lang/Python3/patches/0008-Add-an-option-to-disable-the-tk-module.patch @@ -0,0 +1,81 @@ +From c1ec9fa46cd7679fd009f66a3ebed8de95d84f10 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 +[ Adam Duskett: ported to Python 3.10.0 ] +Signed-off-by: Adam Duskett +[ Bernd Kuhls: ported to Python 3.11.4] +Signed-off-by: Bernd Kuhls +[ Adam Duskett: ported to Python 3.12.1 ] +Signed-off-by: Adam Duskett +--- + Makefile.pre.in | 8 +++++--- + configure.ac | 7 +++++++ + 2 files changed, 12 insertions(+), 3 deletions(-) + +diff --git a/Makefile.pre.in b/Makefile.pre.in +index 7b6c9811a6..6d9527ddd0 100644 +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -2349,7 +2349,6 @@ LIBSUBDIRS= asyncio \ + re \ + site-packages \ + sysconfig \ +- tkinter \ + tomllib \ + turtledemo \ + unittest \ +@@ -2457,7 +2456,6 @@ TESTSUBDIRS= idlelib/idle_test \ + test/test_pydoc \ + test/test_pyrepl \ + test/test_sqlite3 \ +- test/test_tkinter \ + test/test_tomllib \ + test/test_tomllib/data \ + test/test_tomllib/data/invalid \ +@@ -2478,7 +2476,6 @@ TESTSUBDIRS= idlelib/idle_test \ + test/test_tools \ + test/test_tools/i18n_data \ + test/test_tools/msgfmt_data \ +- test/test_ttk \ + test/test_unittest \ + test/test_unittest/testmock \ + test/test_warnings \ +@@ -2500,6 +2497,11 @@ TESTSUBDIRS= idlelib/idle_test \ + test/xmltestdata/c14n-20 \ + test/zipimport_data + ++ifeq (@TK@,yes) ++LIBSUBDIRS += tkinter ++TESTSUBDIRS += test/test_tkinter test/test_ttk ++endif ++ + COMPILEALL_OPTS=-j0 + + ifeq (@PYDOC@,yes) +diff --git a/configure.ac b/configure.ac +index d1c54bd67c..4c5cbe4153 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -4658,6 +4658,13 @@ AC_ARG_ENABLE(pydoc, + AS_HELP_STRING([--disable-pydoc], [disable pydoc]), + [ PYDOC="${enableval}" ], [ PYDOC=yes ]) + ++AC_SUBST(TK) ++AC_ARG_ENABLE(tk, ++ AS_HELP_STRING([--disable-tk], [disable tk]), ++ [ TK="${enableval}" ], [ TK=yes ]) ++AS_IF([test "$TK" = "no"], ++ [PY_STDLIB_MOD_SET_NA([_tkinter])]) ++ + # Check for enable-ipv6 + AH_TEMPLATE([ENABLE_IPV6], [Define if --enable-ipv6 is specified]) + AC_MSG_CHECKING([if --enable-ipv6 is specified]) +-- +2.34.1 + diff --git a/packages/lang/Python3/patches/0009-Add-an-option-to-disable-the-curses-module.patch b/packages/lang/Python3/patches/0009-Add-an-option-to-disable-the-curses-module.patch new file mode 100644 index 0000000000..139bf1544b --- /dev/null +++ b/packages/lang/Python3/patches/0009-Add-an-option-to-disable-the-curses-module.patch @@ -0,0 +1,60 @@ +From d7ea122e8ae506019761b92987b141fe7ea55f76 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 +[ Adam Duskett: ported to Python 3.10.0 ] +Signed-off-by: Adam Duskett +--- + Makefile.pre.in | 5 ++++- + configure.ac | 7 +++++++ + 2 files changed, 11 insertions(+), 1 deletion(-) + +diff --git a/Makefile.pre.in b/Makefile.pre.in +index 6d9527ddd0..283ca1bd60 100644 +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -2095,7 +2095,6 @@ LIBSUBDIRS= asyncio \ + concurrent concurrent/futures \ + csv \ + ctypes ctypes/macholib \ +- curses \ + dbm \ + email email/mime \ + encodings \ +@@ -2255,6 +2254,10 @@ LIBSUBDIRS += tkinter + TESTSUBDIRS += test/test_tkinter test/test_ttk + endif + ++ifeq (@CURSES@,yes) ++LIBSUBDIRS += curses ++endif ++ + COMPILEALL_OPTS=-j0 + + ifeq (@PYDOC@,yes) +diff --git a/configure.ac b/configure.ac +index 4c5cbe4153..92d663ed40 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -4523,6 +4523,13 @@ AC_ARG_ENABLE(sqlite3, + AS_IF([test "$SQLITE3" = "no"], + [PY_STDLIB_MOD_SET_NA([_sqlite3])]) + ++AC_SUBST(CURSES) ++AC_ARG_ENABLE(curses, ++ AS_HELP_STRING([--disable-curses], [disable curses]), ++ [ CURSES="${enableval}" ], [ CURSES=yes ]) ++AS_IF([test "$CURSES" = "no"], ++ [PY_STDLIB_MOD_SET_NA([_curses], [_curses_panel])]) ++ + AC_SUBST(PYDOC) + + AC_ARG_ENABLE(pydoc, +-- +2.34.1 + diff --git a/packages/lang/Python3/patches/0010-Add-an-option-to-disable-expat.patch b/packages/lang/Python3/patches/0010-Add-an-option-to-disable-expat.patch new file mode 100644 index 0000000000..2363aeb01d --- /dev/null +++ b/packages/lang/Python3/patches/0010-Add-an-option-to-disable-expat.patch @@ -0,0 +1,83 @@ +From d1701f1c89e9d2319ede200052319183fbb4ae18 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 +[ Adam Duskett: ported to Python 3.10.0 ] +Signed-off-by: Adam Duskett +--- + Makefile.pre.in | 5 ++++- + configure.ac | 24 +++++++++++++----------- + 2 files changed, 17 insertions(+), 12 deletions(-) + +diff --git a/Makefile.pre.in b/Makefile.pre.in +index 283ca1bd60..13f7512f42 100644 +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -2113,7 +2113,6 @@ LIBSUBDIRS= asyncio \ + urllib \ + venv venv/scripts venv/scripts/common venv/scripts/posix \ + wsgiref \ +- $(XMLLIBSUBDIRS) \ + xmlrpc \ + zipfile zipfile/_path \ + zoneinfo \ +@@ -2280,6 +2279,10 @@ ifeq (@SQLITE3@,yes) + LIBSUBDIRS += sqlite3 + endif + ++ifeq (@EXPAT@,yes) ++LIBSUBDIRS += $(XMLLIBSUBDIRS) ++endif ++ + TEST_MODULES=@TEST_MODULES@ + + .PHONY: libinstall +diff --git a/configure.ac b/configure.ac +index 92d663ed40..1cb95f41fd 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -3823,17 +3823,19 @@ LIBS="$withval $LIBS" + [AC_MSG_RESULT([no])]) + + # 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, see Doc/library/pyexpat.rst (default is no)] +- )], [], [with_system_expat="no"]) +- +-AC_MSG_RESULT([$with_system_expat]) +- +-AS_VAR_IF([with_system_expat], [yes], [ ++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_expat="builtin"]) ++AC_MSG_RESULT($with_expat) ++AS_IF([test "$with_expat" != "none"], ++ [EXPAT=yes], ++ [PY_STDLIB_MOD_SET_NA([pyexpat]) ++ EXPAT=no]) ++AC_SUBST(EXPAT) ++ ++AS_VAR_IF([with_expat], [system], [ + LIBEXPAT_CFLAGS=${LIBEXPAT_CFLAGS-""} + LIBEXPAT_LDFLAGS=${LIBEXPAT_LDFLAGS-"-lexpat"} + LIBEXPAT_INTERNAL= +-- +2.34.1 + diff --git a/packages/lang/Python3/patches/0011-configure.ac-fixup-CC-print-multiarch-output-for-mus.patch b/packages/lang/Python3/patches/0011-configure.ac-fixup-CC-print-multiarch-output-for-mus.patch new file mode 100644 index 0000000000..a92f78fe57 --- /dev/null +++ b/packages/lang/Python3/patches/0011-configure.ac-fixup-CC-print-multiarch-output-for-mus.patch @@ -0,0 +1,53 @@ +From 3eccbd53df3c51c1c6ece217d19f1d01eb9575a7 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 +[Peter: updated for 3.10.2] +Signed-off-by: Vincent Fazio +[Vincent: fixup offsets for 3.12.4] +--- + configure.ac | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/configure.ac b/configure.ac +index 1cb95f41fd..d142af404a 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1128,7 +1128,11 @@ AC_MSG_CHECKING([for multiarch]) + AS_CASE([$ac_sys_system], + [Darwin*], [MULTIARCH=""], + [FreeBSD*], [MULTIARCH=""], +- [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_RESULT([$MULTIARCH]) +-- +2.34.1 + 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 0000000000..e2d448bd3a --- /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 +@@ -153,7 +153,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-0300-generate-legacy-pyc-bytecode.patch b/packages/lang/Python3/patches/Python3-0300-generate-legacy-pyc-bytecode.patch new file mode 100644 index 0000000000..37c9e8d82c --- /dev/null +++ b/packages/lang/Python3/patches/Python3-0300-generate-legacy-pyc-bytecode.patch @@ -0,0 +1,38 @@ +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 | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/Lib/py_compile.py ++++ b/Lib/py_compile.py +@@ -121,6 +121,11 @@ def compile(file, cfile=None, dfile=None + the resulting file would be regular and thus not the same type of file as + it was previously. + """ ++ ++ if os.environ.get('DONT_BUILD_LEGACY_PYC') is None: ++ if cfile: ++ cfile = file + 'c' ++ + if invalidation_mode is None: + invalidation_mode = _get_default_invalidation_mode() + if cfile is None: diff --git a/packages/lang/gcc-aarch64/package.mk b/packages/lang/gcc-aarch64/package.mk new file mode 100644 index 0000000000..e59f6ec993 --- /dev/null +++ b/packages/lang/gcc-aarch64/package.mk @@ -0,0 +1,84 @@ +# 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-aarch64" +PKG_VERSION="$(get_pkg_version gcc)" +PKG_LICENSE="GPL-2.0-or-later" +PKG_URL="" +PKG_DEPENDS_HOST="toolchain:host ccache:host autoconf:host binutils-aarch64:host gmp:host mpfr:host mpc:host zstd:host" +PKG_LONGDESC="This package contains the GNU Compiler Collection for 64-bit ARM." +PKG_DEPENDS_UNPACK+=" gcc" +PKG_PATCH_DIRS+=" $(get_pkg_directory gcc)/patches" + +if [ "${MOLD_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_HOST+=" mold:host" +fi + +PKG_CONFIGURE_OPTS_HOST="--target=aarch64-none-elf \ + --with-sysroot=${TOOLCHAIN}/aarch64-none-elf/sysroot \ + --with-gmp=${TOOLCHAIN} \ + --with-mpfr=${TOOLCHAIN} \ + --with-mpc=${TOOLCHAIN} \ + --with-zstd=${TOOLCHAIN} \ + --with-gnu-as \ + --with-gnu-ld \ + --with-newlib \ + --without-ppl \ + --without-headers \ + --without-cloog \ + --enable-__cxa_atexit \ + --enable-checking=release \ + --enable-gold \ + --enable-languages=c \ + --enable-ld=default \ + --enable-lto \ + --enable-plugin \ + --enable-static \ + --disable-decimal-float \ + --disable-gcov \ + --disable-libada \ + --disable-libatomic \ + --disable-libgomp \ + --disable-libitm \ + --disable-libmpx \ + --disable-libmudflap \ + --disable-libquadmath \ + --disable-libquadmath-support \ + --disable-libsanitizer \ + --disable-libssp \ + --disable-multilib \ + --disable-nls \ + --disable-shared \ + --disable-threads" + +unpack() { + mkdir -p ${PKG_BUILD} + tar --strip-components=1 -xf ${SOURCES}/gcc/gcc-${PKG_VERSION}.tar.xz -C ${PKG_BUILD} +} + +pre_configure_host() { + unset CPPFLAGS + unset CFLAGS + unset CXXFLAGS + unset LDFLAGS +} + +post_makeinstall_host() { + PKG_GCC_PREFIX="${TOOLCHAIN}/bin/aarch64-none-elf-" + GCC_VERSION=$(${PKG_GCC_PREFIX}gcc -dumpversion) + DATE="0501$(echo ${GCC_VERSION} | sed 's/\./0/g')" + CROSS_CC=${PKG_GCC_PREFIX}gcc-${GCC_VERSION} + + rm -f ${PKG_GCC_PREFIX}gcc + + cat >${PKG_GCC_PREFIX}gcc <${PKG_GCC_PREFIX}gcc <${PKG_GCC_PREFIX}gcc <${TARGET_PREFIX}gcc <${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 0000000000..fc01ece219 --- /dev/null +++ b/packages/lang/gcc/patches/gcc-crosscompile-badness.patch @@ -0,0 +1,31 @@ +Index: gcc-4.4+svnr145550/gcc/incpath.cc +=================================================================== +--- gcc-4.4+svnr145550.orig/gcc/incpath.cc 2009-04-04 13:48:31.000000000 -0700 ++++ gcc-4.4+svnr145550/gcc/incpath.cc 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/llvm/package.mk b/packages/lang/llvm/package.mk new file mode 100644 index 0000000000..f08633f38d --- /dev/null +++ b/packages/lang/llvm/package.mk @@ -0,0 +1,141 @@ +# 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="20.1.8" +PKG_SHA256="6898f963c8e938981e6c4a302e83ec5beb4630147c7311183cf61069af16333d" +PKG_LICENSE="Apache-2.0" +PKG_SITE="http://llvm.org/" +PKG_URL="https://github.com/llvm/llvm-project/releases/download/llvmorg-${PKG_VERSION}/llvm-project-${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_TOOLCHAIN="cmake" + +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_BUILD_BENCHMARKS=OFF \ + -DLLVM_INCLUDE_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_ENABLE_ASSERTIONS=OFF \ + -DLLVM_ENABLE_WERROR=OFF \ + -DLLVM_ENABLE_ZLIB=OFF \ + -DLLVM_ENABLE_ZSTD=OFF \ + -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 \ + -DCMAKE_SKIP_RPATH=ON" + +if listcontains "${GRAPHIC_DRIVERS}" "(iris|panfrost)"; then + PKG_DEPENDS_UNPACK="spirv-headers spirv-llvm-translator" + PKG_CMAKE_OPTS_COMMON+=" -DLLVM_SPIRV_INCLUDE_TESTS=OFF" +fi + +post_unpack() { + if listcontains "${GRAPHIC_DRIVERS}" "(iris|panfrost)"; then + mkdir -p "${PKG_BUILD}"/llvm/projects/{SPIRV-Headers,SPIRV-LLVM-Translator} + tar --strip-components=1 \ + -xf "${SOURCES}/spirv-headers/spirv-headers-$(get_pkg_version spirv-headers).tar.gz" \ + -C "${PKG_BUILD}/llvm/projects/SPIRV-Headers" + tar --strip-components=1 \ + -xf "${SOURCES}/spirv-llvm-translator/spirv-llvm-translator-$(get_pkg_version spirv-llvm-translator).tar.gz" \ + -C "${PKG_BUILD}/llvm/projects/SPIRV-LLVM-Translator" + fi +} + +pre_configure() { + PKG_CMAKE_SCRIPT=${PKG_BUILD}/llvm/CMakeLists.txt +} + +pre_configure_host() { + case "${MACHINE_HARDWARE_NAME}" in + "aarch64") + LLVM_BUILD_TARGETS="AArch64" + ;; + "arm") + LLVM_BUILD_TARGETS="ARM" + ;; + "x86_64") + LLVM_BUILD_TARGETS="X86" + ;; + esac + + case "${TARGET_ARCH}" in + "aarch64") + LLVM_BUILD_TARGETS+="\;AArch64" + ;; + "arm") + LLVM_BUILD_TARGETS+="\;ARM" + ;; + "x86_64") + LLVM_BUILD_TARGETS+="\;X86\;AMDGPU" + ;; + esac + + mkdir -p ${PKG_BUILD}/.${HOST_NAME} + cd ${PKG_BUILD}/.${HOST_NAME} + PKG_CMAKE_OPTS_HOST="${PKG_CMAKE_OPTS_COMMON} \ + -DCMAKE_BINARY_DIR=${PKG_BUILD}/.${HOST_NAME} \ + -DLLVM_NATIVE_BUILD=${PKG_BUILD}/.${HOST_NAME}/native \ + -DLLVM_ENABLE_PROJECTS='clang' \ + -DCLANG_LINK_CLANG_DYLIB=ON \ + -DLLVM_TARGETS_TO_BUILD=${LLVM_BUILD_TARGETS}" +} + +post_make_host() { + ninja ${NINJA_OPTS} llvm-config llvm-objcopy llvm-tblgen + + if listcontains "${GRAPHIC_DRIVERS}" "(iris|panfrost)"; then + ninja ${NINJA_OPTS} llvm-as llvm-link llvm-spirv opt + fi +} + +post_makeinstall_host() { + mkdir -p ${TOOLCHAIN}/bin + cp -a bin/llvm-config ${TOOLCHAIN}/bin + cp -a bin/llvm-objcopy ${TOOLCHAIN}/bin + cp -a bin/llvm-tblgen ${TOOLCHAIN}/bin + + if listcontains "${GRAPHIC_DRIVERS}" "(iris|panfrost)"; then + cp -a bin/{llvm-as,llvm-link,llvm-spirv,opt} "${TOOLCHAIN}/bin" + fi +} + +pre_configure_target() { + mkdir -p ${PKG_BUILD}/.${TARGET_NAME} + cd ${PKG_BUILD}/.${TARGET_NAME} + PKG_CMAKE_OPTS_TARGET="${PKG_CMAKE_OPTS_COMMON} \ + -DCMAKE_BINARY_DIR=${PKG_BUILD}/.${TARGET_NAME} \ + -DLLVM_NATIVE_BUILD=${PKG_BUILD}/.${TARGET_NAME}/native \ + -DCMAKE_CROSSCOMPILING=ON \ + -DLLVM_ENABLE_PROJECTS='' \ + -DLLVM_TARGETS_TO_BUILD=AMDGPU \ + -DLLVM_TARGET_ARCH="${TARGET_ARCH}" \ + -DLLVM_TABLEGEN=${TOOLCHAIN}/bin/llvm-tblgen" +} + +post_makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/bin + cp -a ${TOOLCHAIN}/bin/llvm-config ${SYSROOT_PREFIX}/usr/bin + + 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-14.0.0-force-disable-cmakelist-options.patch b/packages/lang/llvm/patches/llvm-14.0.0-force-disable-cmakelist-options.patch new file mode 100644 index 0000000000..b2d77d4e40 --- /dev/null +++ b/packages/lang/llvm/patches/llvm-14.0.0-force-disable-cmakelist-options.patch @@ -0,0 +1,11 @@ +--- a/llvm/CMakeLists.txt 2022-04-02 06:26:04.688530539 +0000 ++++ b/llvm/CMakeLists.txt 2022-04-02 06:44:00.015717360 +0000 +@@ -616,7 +616,7 @@ + + option(LLVM_BUILD_BENCHMARKS "Add LLVM benchmark targets to the list of default + targets. If OFF, benchmarks still could be built using Benchmarks target." OFF) +-option(LLVM_INCLUDE_BENCHMARKS "Generate benchmark targets. If OFF, benchmarks can't be built." ON) ++option(LLVM_INCLUDE_BENCHMARKS "Generate benchmark targets. If OFF, benchmarks can't be built." OFF) + + option (LLVM_BUILD_DOCS "Build the llvm documentation." OFF) + option (LLVM_INCLUDE_DOCS "Generate build targets for llvm documentation." ON) diff --git a/packages/lang/lua52/config/lua52.pc b/packages/lang/lua52/config/lua52.pc new file mode 100644 index 0000000000..6645003e62 --- /dev/null +++ b/packages/lang/lua52/config/lua52.pc @@ -0,0 +1,10 @@ +prefix=/usr +libdir=${prefix}/lib +includedir=${prefix}/include/lua@@VERSION_MM@@ + +Name: Lua +Description: An Extensible Extension Language +Version: @@VERSION@@ +Requires: +Libs: -L${libdir} -llua@@VERSION_MM@@ -lm +Cflags: -I${includedir} diff --git a/packages/lang/lua52/package.mk b/packages/lang/lua52/package.mk new file mode 100644 index 0000000000..09a1f57e5a --- /dev/null +++ b/packages/lang/lua52/package.mk @@ -0,0 +1,30 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="lua52" +PKG_VERSION="5.2.4" +PKG_SHA256="b9e2e4aad6789b3b63a056d442f7b39f0ecfca3ae0f1fc0ae4e9614401b69f4b" +PKG_LICENSE="MIT" +PKG_SITE="https://www.lua.org" +PKG_URL="http://www.lua.org/ftp/lua-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Lua is a powerful, efficient, lightweight, embeddable scripting language." +PKG_BUILD_FLAGS="+pic" + +make_target() { + make CC=${CC} AR="${AR} rcu" MYCFLAGS="-fPIC" posix +} + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/include/lua$(get_pkg_version_maj_min) + cp src/lua.h src/luaconf.h src/lualib.h src/lauxlib.h ${SYSROOT_PREFIX}/usr/include/lua$(get_pkg_version_maj_min) + + mkdir -p ${SYSROOT_PREFIX}/usr/lib + cp src/liblua.a ${SYSROOT_PREFIX}/usr/lib/liblua$(get_pkg_version_maj_min).a + + mkdir -p ${SYSROOT_PREFIX}/usr/lib/pkgconfig + cp ${PKG_DIR}/config/lua52.pc ${SYSROOT_PREFIX}/usr/lib/pkgconfig + sed -e "s/@@VERSION@@/${PKG_VERSION}/g" \ + -e "s/@@VERSION_MM@@/$(get_pkg_version_maj_min)/g" \ + -i ${SYSROOT_PREFIX}/usr/lib/pkgconfig/lua52.pc +} diff --git a/packages/lang/lua54/config/lua54.pc b/packages/lang/lua54/config/lua54.pc new file mode 100644 index 0000000000..6645003e62 --- /dev/null +++ b/packages/lang/lua54/config/lua54.pc @@ -0,0 +1,10 @@ +prefix=/usr +libdir=${prefix}/lib +includedir=${prefix}/include/lua@@VERSION_MM@@ + +Name: Lua +Description: An Extensible Extension Language +Version: @@VERSION@@ +Requires: +Libs: -L${libdir} -llua@@VERSION_MM@@ -lm +Cflags: -I${includedir} diff --git a/packages/lang/lua54/package.mk b/packages/lang/lua54/package.mk new file mode 100644 index 0000000000..9f5c8f4c8b --- /dev/null +++ b/packages/lang/lua54/package.mk @@ -0,0 +1,30 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="lua54" +PKG_VERSION="5.4.8" +PKG_SHA256="4f18ddae154e793e46eeab727c59ef1c0c0c2b744e7b94219710d76f530629ae" +PKG_LICENSE="MIT" +PKG_SITE="https://www.lua.org" +PKG_URL="http://www.lua.org/ftp/lua-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Lua is a powerful, efficient, lightweight, embeddable scripting language." +PKG_BUILD_FLAGS="+pic" + +make_target() { + make CC=${CC} AR="${AR} rcu" MYCFLAGS="-fPIC" posix +} + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/include/lua$(get_pkg_version_maj_min) + cp src/lua.h src/luaconf.h src/lualib.h src/lauxlib.h ${SYSROOT_PREFIX}/usr/include/lua$(get_pkg_version_maj_min) + + mkdir -p ${SYSROOT_PREFIX}/usr/lib + cp src/liblua.a ${SYSROOT_PREFIX}/usr/lib/liblua$(get_pkg_version_maj_min).a + + mkdir -p ${SYSROOT_PREFIX}/usr/lib/pkgconfig + cp ${PKG_DIR}/config/lua54.pc ${SYSROOT_PREFIX}/usr/lib/pkgconfig + sed -e "s/@@VERSION@@/${PKG_VERSION}/g" \ + -e "s/@@VERSION_MM@@/$(get_pkg_version_maj_min)/g" \ + -i ${SYSROOT_PREFIX}/usr/lib/pkgconfig/lua54.pc +} diff --git a/packages/lang/nasm/package.mk b/packages/lang/nasm/package.mk new file mode 100644 index 0000000000..091bc02151 --- /dev/null +++ b/packages/lang/nasm/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="nasm" +PKG_VERSION="2.16.03" +PKG_SHA256="1412a1c760bbd05db026b6c0d1657affd6631cd0a63cddb6f73cc6d4aa616148" +PKG_ARCH="x86_64" +PKG_LICENSE="BSD" +PKG_SITE="https://www.nasm.us/" +PKG_URL="https://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." +PKG_BUILD_FLAGS="-cfg-libs:host" diff --git a/packages/linux-drivers/tm16xx/package.mk b/packages/linux-drivers/tm16xx/package.mk new file mode 100644 index 0000000000..3d4b2178ba --- /dev/null +++ b/packages/linux-drivers/tm16xx/package.mk @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="tm16xx" +PKG_VERSION="9148a4e12ba6cf4b375a7fd352667f7f27823426" +PKG_SHA256="e8fbbc5c8c36b3eb42f1f8d7c907106ccf3a2b5af4b2382c6ca4ea63e07fde70" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/jefflessard/tm16xx-display/" +PKG_URL="https://github.com/jefflessard/tm16xx-display/archive/${PKG_VERSION}.tar.gz" +PKG_LONGDESC="Linux kernel driver for auxiliary displays using TM1628 compatible controllers" +PKG_IS_KERNEL_PKG="yes" + +pre_make_target() { + unset LDFLAGS +} + +make_target() { + kernel_make V=1 KDIR=$(kernel_path) module +} + +makeinstall_target() { + mkdir -p ${INSTALL}/$(get_full_module_dir)/${PKG_NAME} + cp *.ko ${INSTALL}/$(get_full_module_dir)/${PKG_NAME} + mkdir -p ${INSTALL}/usr/sbin + cp display-service ${INSTALL}/usr/sbin + cp display-utils ${INSTALL}/usr/sbin + mkdir -p ${INSTALL}/usr/lib/systemd/system + cp display.service ${INSTALL}/usr/lib/systemd/system +} + +post_install() { + enable_service display.service +} diff --git a/packages/linux-firmware/kernel-firmware/firmwares/any.dat b/packages/linux-firmware/kernel-firmware/firmwares/any.dat new file mode 100644 index 0000000000..4c18cbdfce --- /dev/null +++ b/packages/linux-firmware/kernel-firmware/firmwares/any.dat @@ -0,0 +1,25 @@ +#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 +mediatek/*MT7961*.bin + +ath6k/AR6004/hw1.?/bdata.bin +ath9k_htc/* +brcm/* +rtl_bt/* +rtlwifi/* +rtw88/* +rtw89/* diff --git a/packages/linux-firmware/kernel-firmware/firmwares/x86_64.dat b/packages/linux-firmware/kernel-firmware/firmwares/x86_64.dat new file mode 100644 index 0000000000..c34157c84e --- /dev/null +++ b/packages/linux-firmware/kernel-firmware/firmwares/x86_64.dat @@ -0,0 +1,17 @@ +ath10k/* +ctefx.bin +lbtf_usb.bin +mrvl/sd8897_uapsta.bin +qca/*00000302.bin +mediatek/*MT7961*.bin +mediatek/*MT7922*.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/linux-firmware/kernel-firmware/package.mk b/packages/linux-firmware/kernel-firmware/package.mk new file mode 100644 index 0000000000..8f869ba626 --- /dev/null +++ b/packages/linux-firmware/kernel-firmware/package.mk @@ -0,0 +1,83 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="kernel-firmware" +PKG_VERSION="20250509" +PKG_SHA256="f2c60d66f226a28130cb5643e6e544d3229673460e127c91ba03f1080cbd703e" +PKG_LICENSE="other" +PKG_SITE="https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/" +PKG_URL="https://cdn.kernel.org/pub/linux/kernel/firmware/linux-firmware-${PKG_VERSION}.tar.xz" +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" + +configure_package() { + PKG_FW_SOURCE=${PKG_BUILD}/.copied-firmware +} + +post_patch() { + ( + cd ${PKG_BUILD} + + # Do not run check_whence.py against the copied firmware + echo '#!/usr/bin/python3' > check_whence.py + + mkdir -p "${PKG_FW_SOURCE}" + ./copy-firmware.sh --verbose "${PKG_FW_SOURCE}" + ) +} + +# 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 + + eval "(cd ${PKG_FW_SOURCE} && find "${fwline}" >/dev/null)" || die "ERROR: Firmware pattern does not exist: ${fwline}" + + while read -r fwfile; do + [ -d "${PKG_FW_SOURCE}/${fwfile}" ] && continue + + if [ -f "${PKG_FW_SOURCE}/${fwfile}" ]; then + mkdir -p "$(dirname "${FW_TARGET_DIR}/${fwfile}")" + cp -Lv "${PKG_FW_SOURCE}/${fwfile}" "${FW_TARGET_DIR}/${fwfile}" + else + echo "ERROR: Firmware file ${fwfile} does not exist - aborting" + exit 1 + fi + done <<<"$(cd ${PKG_FW_SOURCE} && 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/linux-firmware/misc-firmware/package.mk b/packages/linux-firmware/misc-firmware/package.mk new file mode 100644 index 0000000000..ba9c2964fa --- /dev/null +++ b/packages/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="868fb584096c17ddcbc85e472e71f9b8d27da91f" +PKG_SHA256="862a5a62b9794d7c6753ac0f7ae03fd34ee2564199afd61c42dc8f69d4c5b876" +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/linux-firmware/rtl8723bs_bt/package.mk b/packages/linux-firmware/rtl8723bs_bt/package.mk new file mode 100644 index 0000000000..3dda0316df --- /dev/null +++ b/packages/linux-firmware/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="09eb91f52a639ec5e4c5c4c98dc2afede046cf20" +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/linux-firmware/rtl8723bs_bt/patches/rtl8723bs_bt-001-Makefile.patch b/packages/linux-firmware/rtl8723bs_bt/patches/rtl8723bs_bt-001-Makefile.patch new file mode 100644 index 0000000000..e4296c08e2 --- /dev/null +++ b/packages/linux-firmware/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/linux-firmware/rtl8723bs_bt/patches/rtl8723bs_bt-002-firmware_path.patch b/packages/linux-firmware/rtl8723bs_bt/patches/rtl8723bs_bt-002-firmware_path.patch new file mode 100644 index 0000000000..cc57fbe371 --- /dev/null +++ b/packages/linux-firmware/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/linux-firmware/rtl8723bs_bt/system.d/rtl8723bs_bt-firmware.service b/packages/linux-firmware/rtl8723bs_bt/system.d/rtl8723bs_bt-firmware.service new file mode 100644 index 0000000000..44f74a35c4 --- /dev/null +++ b/packages/linux-firmware/rtl8723bs_bt/system.d/rtl8723bs_bt-firmware.service @@ -0,0 +1,8 @@ +[Unit] +Description=Realtek sdio firmware update + +[Service] +Type=simple +RemainAfterExit=yes +EnvironmentFile=/usr/share/bttty.conf +ExecStart=/usr/bin/rtk_hciattach -n -s 115200 ${BTTTY} rtk_h5 2000000 diff --git a/packages/linux-firmware/rtl8723bs_bt/udev.d/80-rtl8723_bt.rules b/packages/linux-firmware/rtl8723bs_bt/udev.d/80-rtl8723_bt.rules new file mode 100644 index 0000000000..742f49cd37 --- /dev/null +++ b/packages/linux-firmware/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/linux-firmware/wlan-firmware/package.mk b/packages/linux-firmware/wlan-firmware/package.mk new file mode 100644 index 0000000000..19f9651c41 --- /dev/null +++ b/packages/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="c0ad2587a8037ca430fd887602bd739d769fdbc5" +PKG_SHA256="cd019a209f1dd0c76caa9cf382231e86ef07e4448ff3c81b3d1d76b6bde6ca67" +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" +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/linux/package.mk b/packages/linux/package.mk new file mode 100644 index 0000000000..18ff59e0b1 --- /dev/null +++ b/packages/linux/package.mk @@ -0,0 +1,325 @@ +# 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="linux" +PKG_LICENSE="GPL" +PKG_SITE="http://www.kernel.org" +PKG_DEPENDS_HOST="ccache:host" +PKG_DEPENDS_TARGET="linux:host kmod:host keyutils openssl:host ${KERNEL_EXTRA_DEPENDS_TARGET}" +PKG_NEED_UNPACK="${LINUX_DEPENDS} $(get_pkg_directory initramfs) $(get_pkg_variable initramfs PKG_NEED_UNPACK)" +PKG_LONGDESC="This package contains a precompiled kernel image and the modules." +PKG_IS_KERNEL_PKG="yes" +PKG_STAMP="${KERNEL_TARGET} ${KERNEL_MAKE_EXTRACMD}" + +PKG_PATCH_DIRS="${LINUX}" + +case "${LINUX}" in + amlogic) + PKG_VERSION="86731a2a651e58953fc949573895f2fa6d456841" # 6.16-rc3 + PKG_SHA256="008b00968a8bfc0627580b82a2d30c7304336a4f92a58e80cdbc2d4723e01840" + PKG_URL="https://github.com/torvalds/linux/archive/${PKG_VERSION}.tar.gz" + PKG_SOURCE_NAME="linux-${LINUX}-${PKG_VERSION}.tar.gz" + PKG_PATCH_DIRS="default" + ;; + raspberrypi) + PKG_VERSION="ef8e31bd0d660ef06e98fcf6337d3374c8884038" # 6.12.35 + PKG_SHA256="6a86eab9a0ec7f8c8887f94b5c604c9546b60fcaf025c27de352b33edd20c3b8" + PKG_URL="https://github.com/raspberrypi/linux/archive/${PKG_VERSION}.tar.gz" + PKG_SOURCE_NAME="linux-${LINUX}-${PKG_VERSION}.tar.gz" + PKG_PATCH_DIRS="raspberrypi rtlwifi/6.13 rtlwifi/6.14 rtlwifi/6.15" + ;; + *) + PKG_VERSION="6.15.6" + PKG_SHA256="2bb586c954277d070c8fdf6d7275faa93b4807d9bf3353b491d8149cca02b4fc" + PKG_URL="https://www.kernel.org/pub/linux/kernel/v${PKG_VERSION/.*/}.x/${PKG_NAME}-${PKG_VERSION}.tar.xz" + PKG_PATCH_DIRS="default" + ;; +esac + +PKG_KERNEL_CFG_FILE=$(kernel_config_path) || die + +if [ -n "${KERNEL_TOOLCHAIN}" ]; then + PKG_DEPENDS_TARGET+=" gcc-${KERNEL_TOOLCHAIN}:host" + HEADERS_ARCH=${TARGET_ARCH} +else + PKG_DEPENDS_TARGET+=" toolchain" +fi + +if [ "${PKG_BUILD_PERF}" != "no" ] && grep -q ^CONFIG_PERF_EVENTS= ${PKG_KERNEL_CFG_FILE}; then + PKG_BUILD_PERF="yes" + PKG_DEPENDS_TARGET+=" binutils elfutils libunwind zlib openssl" +fi + +if [ "${TARGET_ARCH}" = "x86_64" ]; then + PKG_DEPENDS_TARGET+=" elfutils:host pciutils" + PKG_DEPENDS_UNPACK+=" intel-ucode kernel-firmware" +elif [ "${TARGET_ARCH}" = "arm" -a "${DEVICE}" = "iMX6" ]; then + PKG_DEPENDS_UNPACK+=" firmware-imx" +fi + +if [[ "${KERNEL_TARGET}" = uImage* ]]; then + PKG_DEPENDS_TARGET+=" u-boot-tools:host" +fi + +if [ "${BOOTLOADER}" = "bcm2835-bootloader" -a "${TARGET_KERNEL_ARCH}" = "arm64" ]; then + PKG_DEPENDS_TARGET+=" pigz:host" +fi + +# Ensure that the dependencies of initramfs:target are built correctly, but +# we don't want to add initramfs:target as a direct dependency as we install +# this "manually" from within linux:target +for pkg in $(get_pkg_variable initramfs PKG_DEPENDS_TARGET); do + ! listcontains "${PKG_DEPENDS_TARGET}" "${pkg}" && PKG_DEPENDS_TARGET+=" ${pkg}" || true +done + +post_patch() { + # linux was already built and its build dir autoremoved - prepare it again for kernel packages + if [ -d ${PKG_INSTALL}/.image ]; then + cp -p ${PKG_INSTALL}/.image/.config ${PKG_BUILD} + kernel_make -C ${PKG_BUILD} prepare + + # restore the required Module.symvers from an earlier build + cp -p ${PKG_INSTALL}/.image/Module.symvers ${PKG_BUILD} + fi +} + +make_host() { + : +} + +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() { + ( + cd ${ROOT} + rm -rf ${BUILD}/initramfs + rm -f ${STAMPS_INSTALL}/initramfs/install_target ${STAMPS_INSTALL}/*/install_init + ${SCRIPTS}/install initramfs + ) + pkg_lock_status "ACTIVE" "linux:target" "build" + + cp ${PKG_KERNEL_CFG_FILE} ${PKG_BUILD}/.config + + # set initramfs source + ${PKG_BUILD}/scripts/config --set-str CONFIG_INITRAMFS_SOURCE "$(kernel_initramfs_confs) ${BUILD}/initramfs" + + # set default hostname based on ${DISTRONAME} + ${PKG_BUILD}/scripts/config --set-str CONFIG_DEFAULT_HOSTNAME "${DISTRONAME}" + + # disable swap support if not enabled + if [ ! "${SWAP_SUPPORT}" = yes ]; then + ${PKG_BUILD}/scripts/config --disable CONFIG_SWAP + fi + + # disable nfs support if not enabled + if [ ! "${NFS_SUPPORT}" = yes ]; then + ${PKG_BUILD}/scripts/config --disable CONFIG_NFS_FS + fi + + # disable cifs support if not enabled + if [ ! "${SAMBA_SUPPORT}" = yes ]; then + ${PKG_BUILD}/scripts/config --disable CONFIG_CIFS + fi + + # enable/disable iscsi support + [ "${ISCSI_SUPPORT}" = yes ] && OPTION="--enable" || OPTION="--disable" + ${PKG_BUILD}/scripts/config ${OPTION} CONFIG_SCSI_ISCSI_ATTRS + ${PKG_BUILD}/scripts/config ${OPTION} CONFIG_ISCSI_TCP + ${PKG_BUILD}/scripts/config ${OPTION} CONFIG_ISCSI_BOOT_SYSFS + ${PKG_BUILD}/scripts/config ${OPTION} CONFIG_ISCSI_IBFT_FIND + ${PKG_BUILD}/scripts/config ${OPTION} CONFIG_ISCSI_IBFT + + # disable wireguard support if not enabled + if [ ! "${WIREGUARD_SUPPORT}" = yes ]; then + ${PKG_BUILD}/scripts/config --disable CONFIG_WIREGUARD + fi + + 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)/.copied-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)" + + ${PKG_BUILD}/scripts/config --set-str CONFIG_EXTRA_FIRMWARE "${FW_LIST}" + ${PKG_BUILD}/scripts/config --set-str CONFIG_EXTRA_FIRMWARE_DIR "external-firmware" + + elif [ "${TARGET_ARCH}" = "arm" -a "${DEVICE}" = "iMX6" ]; then + mkdir -p ${PKG_BUILD}/external-firmware/imx/sdma + cp -a $(get_build_dir firmware-imx)/firmware/sdma/*imx6*.bin ${PKG_BUILD}/external-firmware/imx/sdma + cp -a $(get_build_dir firmware-imx)/firmware/vpu/*imx6*.bin ${PKG_BUILD}/external-firmware + + FW_LIST="$(find ${PKG_BUILD}/external-firmware -type f | sed 's|.*external-firmware/||' | sort | xargs)" + + ${PKG_BUILD}/scripts/config --set-str CONFIG_EXTRA_FIRMWARE "${FW_LIST}" + ${PKG_BUILD}/scripts/config --set-str CONFIG_EXTRA_FIRMWARE_DIR "external-firmware" + fi + + kernel_make listnewconfig + if [ "${INTERACTIVE_CONFIG}" = "yes" ]; then + # manually answer .config changes + kernel_make oldconfig + else + # accept default answers for .config changes + yes "" | kernel_make oldconfig >/dev/null + fi + + if [ -f "${DISTRO_DIR}/${DISTRO}/kernel_options" ]; then + while read OPTION; do + [ -z "${OPTION}" -o -n "$(echo "${OPTION}" | grep '^#')" ] && continue + + if [ "${OPTION##*=}" == "n" -a "$(${PKG_BUILD}/scripts/config --state ${OPTION%%=*})" == "undef" ]; then + continue + fi + + if [ "$(${PKG_BUILD}/scripts/config --state ${OPTION%%=*})" != "$(echo ${OPTION##*=} | tr -d '"')" ]; then + MISSING_KERNEL_OPTIONS+="\t${OPTION}\n" + fi + done <${DISTRO_DIR}/${DISTRO}/kernel_options + + if [ -n "${MISSING_KERNEL_OPTIONS}" ]; then + print_color CLR_WARNING "LINUX: kernel options not correct: \n${MISSING_KERNEL_OPTIONS%%}\nPlease run ./tools/check_kernel_config\n" + fi + fi +} + +make_target() { + # 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 + + DTC_FLAGS=-@ kernel_make ${KERNEL_TARGET} ${KERNEL_MAKE_EXTRACMD} modules + + 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_LIBTRACEEVENT=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 + + if [ -n "${KERNEL_UIMAGE_TARGET}" ]; then + # determine compression used for kernel image + KERNEL_UIMAGE_COMP=${KERNEL_UIMAGE_TARGET:7} + KERNEL_UIMAGE_COMP=$(echo ${KERNEL_UIMAGE_COMP:-none} | sed 's/gz/gzip/; s/bz2/bzip2/') + + # 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() { + mkdir -p ${INSTALL}/.image + cp -p arch/${TARGET_KERNEL_ARCH}/boot/${KERNEL_TARGET} System.map .config Module.symvers ${INSTALL}/.image/ + + 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 [ "${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 \ + 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 + # RPi firmware will decompress gzipped kernels prior to booting + if [ "${TARGET_KERNEL_ARCH}" = "arm64" ]; then + pigz --best --force ${INSTALL}/.image/${KERNEL_TARGET} + mv ${INSTALL}/.image/${KERNEL_TARGET}.gz ${INSTALL}/.image/${KERNEL_TARGET} + fi + + 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 + for dtb in arch/${TARGET_KERNEL_ARCH}/boot/dts/*.dtb \ + 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 + rm -f ${INSTALL}/usr/share/bootloader/bcm283*.dtb + # duplicated in overlays below + safe_remove ${INSTALL}/usr/share/bootloader/overlay_map.dtb + + # install overlay dtbs + for dtb in arch/arm/boot/dts/overlays/*.dtb \ + arch/arm/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 +} diff --git a/packages/linux/patches/default/linux-062-imon_pad_ignore_diagonal.patch b/packages/linux/patches/default/linux-062-imon_pad_ignore_diagonal.patch new file mode 100644 index 0000000000..677de3ed7f --- /dev/null +++ b/packages/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/linux/patches/default/linux-999.02-0001-pm-disable-async-suspend-resume-by-default.patch b/packages/linux/patches/default/linux-999.02-0001-pm-disable-async-suspend-resume-by-default.patch new file mode 100644 index 0000000000..16ac49bee6 --- /dev/null +++ b/packages/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/linux/patches/rtlwifi/6.13/0001-wifi-rtw88-Constify-some-arrays-and-structs.patch b/packages/linux/patches/rtlwifi/6.13/0001-wifi-rtw88-Constify-some-arrays-and-structs.patch new file mode 100644 index 0000000000..8abc268b2e --- /dev/null +++ b/packages/linux/patches/rtlwifi/6.13/0001-wifi-rtw88-Constify-some-arrays-and-structs.patch @@ -0,0 +1,392 @@ +From c9cd7ebfe01ff6fe41e762db6a2b0f0e53ee8567 Mon Sep 17 00:00:00 2001 +From: Bitterblue Smith +Date: Wed, 18 Sep 2024 01:53:55 +0300 +Subject: [PATCH 01/24] wifi: rtw88: Constify some arrays and structs + +These are never modified, so make them const: + +card_enable_flow_8703b +card_disable_flow_8703b +rtw8703b_ops + +rtw8723d_ops +card_enable_flow_8723d +card_disable_flow_8723d + +trans_carddis_to_cardemu_8821c +trans_cardemu_to_act_8821c +trans_act_to_cardemu_8821c +trans_cardemu_to_carddis_8821c +card_enable_flow_8821c +card_disable_flow_8821c +rtw8821c_dig +page_table_8821c +rqpn_table_8821c +prioq_addrs_8821c +rtw8821c_ops + +card_enable_flow_8822b +card_disable_flow_8822b +prioq_addrs_8822b +rtw8822b_ops +rtw8822b_edcca_th + +card_enable_flow_8822c +card_disable_flow_8822c +prioq_addrs_8822c +rtw8822c_ops +rtw8822c_edcca_th + +Signed-off-by: Bitterblue Smith +--- + drivers/net/wireless/realtek/rtw88/fw.c | 2 +- + drivers/net/wireless/realtek/rtw88/mac.c | 4 ++-- + drivers/net/wireless/realtek/rtw88/main.h | 8 +++---- + drivers/net/wireless/realtek/rtw88/phy.c | 2 +- + drivers/net/wireless/realtek/rtw88/rtw8703b.c | 6 ++--- + drivers/net/wireless/realtek/rtw88/rtw8723d.c | 6 ++--- + drivers/net/wireless/realtek/rtw88/rtw8821c.c | 22 +++++++++---------- + drivers/net/wireless/realtek/rtw88/rtw8822b.c | 10 ++++----- + drivers/net/wireless/realtek/rtw88/rtw8822c.c | 10 ++++----- + 9 files changed, 35 insertions(+), 35 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c +index b9b0114e253b..813c12148819 100644 +--- a/drivers/net/wireless/realtek/rtw88/fw.c ++++ b/drivers/net/wireless/realtek/rtw88/fw.c +@@ -267,7 +267,7 @@ static void rtw_fw_scan_result(struct rtw_dev *rtwdev, u8 *payload, + static void rtw_fw_adaptivity_result(struct rtw_dev *rtwdev, u8 *payload, + u8 length) + { +- struct rtw_hw_reg_offset *edcca_th = rtwdev->chip->edcca_th; ++ const struct rtw_hw_reg_offset *edcca_th = rtwdev->chip->edcca_th; + struct rtw_c2h_adaptivity *result = (struct rtw_c2h_adaptivity *)payload; + + rtw_dbg(rtwdev, RTW_DBG_ADAPTIVITY, +diff --git a/drivers/net/wireless/realtek/rtw88/mac.c b/drivers/net/wireless/realtek/rtw88/mac.c +index efb1da198e74..5aa45592c2ac 100644 +--- a/drivers/net/wireless/realtek/rtw88/mac.c ++++ b/drivers/net/wireless/realtek/rtw88/mac.c +@@ -228,7 +228,7 @@ static int rtw_sub_pwr_seq_parser(struct rtw_dev *rtwdev, u8 intf_mask, + } + + static int rtw_pwr_seq_parser(struct rtw_dev *rtwdev, +- const struct rtw_pwr_seq_cmd **cmd_seq) ++ const struct rtw_pwr_seq_cmd * const *cmd_seq) + { + u8 cut_mask; + u8 intf_mask; +@@ -271,7 +271,7 @@ static int rtw_pwr_seq_parser(struct rtw_dev *rtwdev, + static int rtw_mac_power_switch(struct rtw_dev *rtwdev, bool pwr_on) + { + const struct rtw_chip_info *chip = rtwdev->chip; +- const struct rtw_pwr_seq_cmd **pwr_seq; ++ const struct rtw_pwr_seq_cmd * const *pwr_seq; + u32 imr = 0; + u8 rpwm; + bool cur_pwr; +diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h +index c808bb271e9d..81145f8571f3 100644 +--- a/drivers/net/wireless/realtek/rtw88/main.h ++++ b/drivers/net/wireless/realtek/rtw88/main.h +@@ -1167,7 +1167,7 @@ enum rtw_fwcd_item { + + /* hardware configuration for each IC */ + struct rtw_chip_info { +- struct rtw_chip_ops *ops; ++ const struct rtw_chip_ops *ops; + u8 id; + + const char *fw_name; +@@ -1209,8 +1209,8 @@ struct rtw_chip_info { + + /* init values */ + u8 sys_func_en; +- const struct rtw_pwr_seq_cmd **pwr_on_seq; +- const struct rtw_pwr_seq_cmd **pwr_off_seq; ++ const struct rtw_pwr_seq_cmd * const *pwr_on_seq; ++ const struct rtw_pwr_seq_cmd * const *pwr_off_seq; + const struct rtw_rqpn *rqpn_table; + const struct rtw_prioq_addrs *prioq_addrs; + const struct rtw_page_table *page_table; +@@ -1242,7 +1242,7 @@ struct rtw_chip_info { + u8 bfer_su_max_num; + u8 bfer_mu_max_num; + +- struct rtw_hw_reg_offset *edcca_th; ++ const struct rtw_hw_reg_offset *edcca_th; + s8 l2h_th_ini_cs; + s8 l2h_th_ini_ad; + +diff --git a/drivers/net/wireless/realtek/rtw88/phy.c b/drivers/net/wireless/realtek/rtw88/phy.c +index 37ef80c9091d..d57a2aabd89b 100644 +--- a/drivers/net/wireless/realtek/rtw88/phy.c ++++ b/drivers/net/wireless/realtek/rtw88/phy.c +@@ -123,7 +123,7 @@ static void rtw_phy_cck_pd_init(struct rtw_dev *rtwdev) + + void rtw_phy_set_edcca_th(struct rtw_dev *rtwdev, u8 l2h, u8 h2l) + { +- struct rtw_hw_reg_offset *edcca_th = rtwdev->chip->edcca_th; ++ const struct rtw_hw_reg_offset *edcca_th = rtwdev->chip->edcca_th; + + rtw_write32_mask(rtwdev, + edcca_th[EDCCA_TH_L2H_IDX].hw_reg.addr, +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8703b.c b/drivers/net/wireless/realtek/rtw88/rtw8703b.c +index a977aad9c650..86904cc94d6d 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8703b.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8703b.c +@@ -481,14 +481,14 @@ static const struct rtw_pwr_seq_cmd trans_act_to_lps_8703b[] = { + {TRANS_SEQ_END}, + }; + +-static const struct rtw_pwr_seq_cmd *card_enable_flow_8703b[] = { ++static const struct rtw_pwr_seq_cmd * const card_enable_flow_8703b[] = { + trans_pre_enable_8703b, + trans_carddis_to_cardemu_8703b, + trans_cardemu_to_act_8703b, + NULL + }; + +-static const struct rtw_pwr_seq_cmd *card_disable_flow_8703b[] = { ++static const struct rtw_pwr_seq_cmd * const card_disable_flow_8703b[] = { + trans_act_to_lps_8703b, + trans_act_to_reset_mcu_8703b, + trans_act_to_cardemu_8703b, +@@ -1941,7 +1941,7 @@ static const struct coex_tdma_para tdma_sant_8703b[] = { + { {0x61, 0x08, 0x03, 0x11, 0x11} }, + }; + +-static struct rtw_chip_ops rtw8703b_ops = { ++static const struct rtw_chip_ops rtw8703b_ops = { + .mac_init = rtw8723x_mac_init, + .dump_fw_crash = NULL, + .shutdown = NULL, +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c +index 3fba4054d45f..7f33e141e646 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c +@@ -1430,7 +1430,7 @@ static void rtw8723d_pwr_track(struct rtw_dev *rtwdev) + dm_info->pwr_trk_triggered = false; + } + +-static struct rtw_chip_ops rtw8723d_ops = { ++static const struct rtw_chip_ops rtw8723d_ops = { + .phy_set_param = rtw8723d_phy_set_param, + .read_efuse = rtw8723x_read_efuse, + .query_rx_desc = rtw8723d_query_rx_desc, +@@ -1788,7 +1788,7 @@ static const struct rtw_pwr_seq_cmd trans_cardemu_to_act_8723d[] = { + RTW_PWR_CMD_END, 0, 0}, + }; + +-static const struct rtw_pwr_seq_cmd *card_enable_flow_8723d[] = { ++static const struct rtw_pwr_seq_cmd * const card_enable_flow_8723d[] = { + trans_carddis_to_cardemu_8723d, + trans_cardemu_to_act_8723d, + NULL +@@ -2004,7 +2004,7 @@ static const struct rtw_pwr_seq_cmd trans_act_to_post_carddis_8723d[] = { + RTW_PWR_CMD_END, 0, 0}, + }; + +-static const struct rtw_pwr_seq_cmd *card_disable_flow_8723d[] = { ++static const struct rtw_pwr_seq_cmd * const card_disable_flow_8723d[] = { + trans_act_to_lps_8723d, + trans_act_to_pre_carddis_8723d, + trans_act_to_cardemu_8723d, +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.c b/drivers/net/wireless/realtek/rtw88/rtw8821c.c +index 526e8de77b3e..9d21c4b1450e 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8821c.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.c +@@ -1254,7 +1254,7 @@ static void rtw8821c_fill_txdesc_checksum(struct rtw_dev *rtwdev, + fill_txdesc_checksum_common(txdesc, 16); + } + +-static struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8821c[] = { ++static const struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8821c[] = { + {0x0086, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, +@@ -1292,7 +1292,7 @@ static struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8821c[] = { + RTW_PWR_CMD_END, 0, 0}, + }; + +-static struct rtw_pwr_seq_cmd trans_cardemu_to_act_8821c[] = { ++static const struct rtw_pwr_seq_cmd trans_cardemu_to_act_8821c[] = { + {0x0020, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK, +@@ -1396,7 +1396,7 @@ static struct rtw_pwr_seq_cmd trans_cardemu_to_act_8821c[] = { + RTW_PWR_CMD_END, 0, 0}, + }; + +-static struct rtw_pwr_seq_cmd trans_act_to_cardemu_8821c[] = { ++static const struct rtw_pwr_seq_cmd trans_act_to_cardemu_8821c[] = { + {0x0093, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, +@@ -1454,7 +1454,7 @@ static struct rtw_pwr_seq_cmd trans_act_to_cardemu_8821c[] = { + RTW_PWR_CMD_END, 0, 0}, + }; + +-static struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8821c[] = { ++static const struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8821c[] = { + {0x0007, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK, +@@ -1567,13 +1567,13 @@ static struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8821c[] = { + RTW_PWR_CMD_END, 0, 0}, + }; + +-static const struct rtw_pwr_seq_cmd *card_enable_flow_8821c[] = { ++static const struct rtw_pwr_seq_cmd * const card_enable_flow_8821c[] = { + trans_carddis_to_cardemu_8821c, + trans_cardemu_to_act_8821c, + NULL + }; + +-static const struct rtw_pwr_seq_cmd *card_disable_flow_8821c[] = { ++static const struct rtw_pwr_seq_cmd * const card_disable_flow_8821c[] = { + trans_act_to_cardemu_8821c, + trans_cardemu_to_carddis_8821c, + NULL +@@ -1629,7 +1629,7 @@ static const struct rtw_rfe_def rtw8821c_rfe_defs[] = { + [6] = RTW_DEF_RFE(8821c, 0, 0), + }; + +-static struct rtw_hw_reg rtw8821c_dig[] = { ++static const struct rtw_hw_reg rtw8821c_dig[] = { + [0] = { .addr = 0xc50, .mask = 0x7f }, + }; + +@@ -1639,7 +1639,7 @@ static const struct rtw_ltecoex_addr rtw8821c_ltecoex_addr = { + .rdata = LTECOEX_READ_DATA, + }; + +-static struct rtw_page_table page_table_8821c[] = { ++static const struct rtw_page_table page_table_8821c[] = { + /* not sure what [0] stands for */ + {16, 16, 16, 14, 1}, + {16, 16, 16, 14, 1}, +@@ -1648,7 +1648,7 @@ static struct rtw_page_table page_table_8821c[] = { + {16, 16, 16, 14, 1}, + }; + +-static struct rtw_rqpn rqpn_table_8821c[] = { ++static const struct rtw_rqpn rqpn_table_8821c[] = { + /* not sure what [0] stands for */ + {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL, + RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW, +@@ -1667,7 +1667,7 @@ static struct rtw_rqpn rqpn_table_8821c[] = { + RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH}, + }; + +-static struct rtw_prioq_addrs prioq_addrs_8821c = { ++static const struct rtw_prioq_addrs prioq_addrs_8821c = { + .prio[RTW_DMA_MAPPING_EXTRA] = { + .rsvd = REG_FIFOPAGE_INFO_4, .avail = REG_FIFOPAGE_INFO_4 + 2, + }, +@@ -1683,7 +1683,7 @@ static struct rtw_prioq_addrs prioq_addrs_8821c = { + .wsize = true, + }; + +-static struct rtw_chip_ops rtw8821c_ops = { ++static const struct rtw_chip_ops rtw8821c_ops = { + .phy_set_param = rtw8821c_phy_set_param, + .read_efuse = rtw8821c_read_efuse, + .query_rx_desc = rtw8821c_query_rx_desc, +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c +index 4a6c0a9266a0..c9e50756655c 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c +@@ -1980,13 +1980,13 @@ static const struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8822b[] = { + RTW_PWR_CMD_END, 0, 0}, + }; + +-static const struct rtw_pwr_seq_cmd *card_enable_flow_8822b[] = { ++static const struct rtw_pwr_seq_cmd * const card_enable_flow_8822b[] = { + trans_carddis_to_cardemu_8822b, + trans_cardemu_to_act_8822b, + NULL + }; + +-static const struct rtw_pwr_seq_cmd *card_disable_flow_8822b[] = { ++static const struct rtw_pwr_seq_cmd * const card_disable_flow_8822b[] = { + trans_act_to_cardemu_8822b, + trans_cardemu_to_carddis_8822b, + NULL +@@ -2158,7 +2158,7 @@ static const struct rtw_rqpn rqpn_table_8822b[] = { + RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH}, + }; + +-static struct rtw_prioq_addrs prioq_addrs_8822b = { ++static const struct rtw_prioq_addrs prioq_addrs_8822b = { + .prio[RTW_DMA_MAPPING_EXTRA] = { + .rsvd = REG_FIFOPAGE_INFO_4, .avail = REG_FIFOPAGE_INFO_4 + 2, + }, +@@ -2174,7 +2174,7 @@ static struct rtw_prioq_addrs prioq_addrs_8822b = { + .wsize = true, + }; + +-static struct rtw_chip_ops rtw8822b_ops = { ++static const struct rtw_chip_ops rtw8822b_ops = { + .phy_set_param = rtw8822b_phy_set_param, + .read_efuse = rtw8822b_read_efuse, + .query_rx_desc = rtw8822b_query_rx_desc, +@@ -2523,7 +2523,7 @@ static const struct rtw_reg_domain coex_info_hw_regs_8822b[] = { + {0xc50, MASKBYTE0, RTW_REG_DOMAIN_MAC8}, + }; + +-static struct rtw_hw_reg_offset rtw8822b_edcca_th[] = { ++static const struct rtw_hw_reg_offset rtw8822b_edcca_th[] = { + [EDCCA_TH_L2H_IDX] = {{.addr = 0x8a4, .mask = MASKBYTE0}, .offset = 0}, + [EDCCA_TH_H2L_IDX] = {{.addr = 0x8a4, .mask = MASKBYTE1}, .offset = 0}, + }; +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c +index 3157cd834233..9aae401722fb 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c +@@ -4875,13 +4875,13 @@ static const struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8822c[] = { + RTW_PWR_CMD_END, 0, 0}, + }; + +-static const struct rtw_pwr_seq_cmd *card_enable_flow_8822c[] = { ++static const struct rtw_pwr_seq_cmd * const card_enable_flow_8822c[] = { + trans_carddis_to_cardemu_8822c, + trans_cardemu_to_act_8822c, + NULL + }; + +-static const struct rtw_pwr_seq_cmd *card_disable_flow_8822c[] = { ++static const struct rtw_pwr_seq_cmd * const card_disable_flow_8822c[] = { + trans_act_to_cardemu_8822c, + trans_cardemu_to_carddis_8822c, + NULL +@@ -4973,7 +4973,7 @@ static const struct rtw_rqpn rqpn_table_8822c[] = { + RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH}, + }; + +-static struct rtw_prioq_addrs prioq_addrs_8822c = { ++static const struct rtw_prioq_addrs prioq_addrs_8822c = { + .prio[RTW_DMA_MAPPING_EXTRA] = { + .rsvd = REG_FIFOPAGE_INFO_4, .avail = REG_FIFOPAGE_INFO_4 + 2, + }, +@@ -4989,7 +4989,7 @@ static struct rtw_prioq_addrs prioq_addrs_8822c = { + .wsize = true, + }; + +-static struct rtw_chip_ops rtw8822c_ops = { ++static const struct rtw_chip_ops rtw8822c_ops = { + .phy_set_param = rtw8822c_phy_set_param, + .read_efuse = rtw8822c_read_efuse, + .query_rx_desc = rtw8822c_query_rx_desc, +@@ -5302,7 +5302,7 @@ static const struct rtw_pwr_track_tbl rtw8822c_rtw_pwr_track_tbl = { + .pwrtrk_2g_ccka_p = rtw8822c_pwrtrk_2g_cck_a_p, + }; + +-static struct rtw_hw_reg_offset rtw8822c_edcca_th[] = { ++static const struct rtw_hw_reg_offset rtw8822c_edcca_th[] = { + [EDCCA_TH_L2H_IDX] = { + {.addr = 0x84c, .mask = MASKBYTE2}, .offset = 0x80 + }, +-- +2.39.5 + diff --git a/packages/linux/patches/rtlwifi/6.13/0002-wifi-rtw88-Parse-the-RX-descriptor-with-a-single-fun.patch b/packages/linux/patches/rtlwifi/6.13/0002-wifi-rtw88-Parse-the-RX-descriptor-with-a-single-fun.patch new file mode 100644 index 0000000000..cc44d6951d --- /dev/null +++ b/packages/linux/patches/rtlwifi/6.13/0002-wifi-rtw88-Parse-the-RX-descriptor-with-a-single-fun.patch @@ -0,0 +1,582 @@ +From e88978bf9faea656241ce9b671ce76323015c896 Mon Sep 17 00:00:00 2001 +From: Bitterblue Smith +Date: Fri, 20 Sep 2024 22:27:30 +0300 +Subject: [PATCH 02/24] wifi: rtw88: Parse the RX descriptor with a single + function + +rtw8703b_query_rx_desc(), rtw8723d_query_rx_desc(), +rtw8821c_query_rx_desc(), rtw8822b_query_rx_desc(), and +rtw8822c_query_rx_desc() are almost identical, so replace them all with +a single function, rtw_rx_query_rx_desc(). + +Also, access the RX descriptor using a struct with __le32 members and +le32_get_bits(). + +Tested with RTL8811CU, RTL8811AU, and RTL8812AU. + +Signed-off-by: Bitterblue Smith +--- + drivers/net/wireless/realtek/rtw88/main.h | 5 +- + drivers/net/wireless/realtek/rtw88/pci.c | 2 +- + drivers/net/wireless/realtek/rtw88/rtw8703b.c | 56 +-------------- + drivers/net/wireless/realtek/rtw88/rtw8723d.c | 43 +----------- + drivers/net/wireless/realtek/rtw88/rtw8821c.c | 43 +----------- + drivers/net/wireless/realtek/rtw88/rtw8822b.c | 43 +----------- + drivers/net/wireless/realtek/rtw88/rtw8822c.c | 44 +----------- + drivers/net/wireless/realtek/rtw88/rx.c | 70 +++++++++++++++++-- + drivers/net/wireless/realtek/rtw88/rx.h | 64 ++++++++--------- + drivers/net/wireless/realtek/rtw88/sdio.c | 3 +- + drivers/net/wireless/realtek/rtw88/usb.c | 4 +- + 11 files changed, 106 insertions(+), 271 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h +index 81145f8571f3..c9efe9d66954 100644 +--- a/drivers/net/wireless/realtek/rtw88/main.h ++++ b/drivers/net/wireless/realtek/rtw88/main.h +@@ -848,9 +848,8 @@ struct rtw_chip_ops { + void (*phy_set_param)(struct rtw_dev *rtwdev); + void (*set_channel)(struct rtw_dev *rtwdev, u8 channel, + u8 bandwidth, u8 primary_chan_idx); +- void (*query_rx_desc)(struct rtw_dev *rtwdev, u8 *rx_desc, +- struct rtw_rx_pkt_stat *pkt_stat, +- struct ieee80211_rx_status *rx_status); ++ void (*query_phy_status)(struct rtw_dev *rtwdev, u8 *phy_status, ++ struct rtw_rx_pkt_stat *pkt_stat); + u32 (*read_rf)(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, + u32 addr, u32 mask); + bool (*write_rf)(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, +diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c +index fab9bb9257dd..729b270d5851 100644 +--- a/drivers/net/wireless/realtek/rtw88/pci.c ++++ b/drivers/net/wireless/realtek/rtw88/pci.c +@@ -1066,7 +1066,7 @@ static u32 rtw_pci_rx_napi(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci, + dma_sync_single_for_cpu(rtwdev->dev, dma, RTK_PCI_RX_BUF_SIZE, + DMA_FROM_DEVICE); + rx_desc = skb->data; +- chip->ops->query_rx_desc(rtwdev, rx_desc, &pkt_stat, &rx_status); ++ rtw_rx_query_rx_desc(rtwdev, rx_desc, &pkt_stat, &rx_status); + + /* offset from rx_desc to payload */ + pkt_offset = pkt_desc_sz + pkt_stat.drv_info_sz + +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8703b.c b/drivers/net/wireless/realtek/rtw88/rtw8703b.c +index 86904cc94d6d..fe09c23b51b5 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8703b.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8703b.c +@@ -29,9 +29,6 @@ + #define TBTT_PROHIBIT_HOLD_TIME 0x80 + #define TBTT_PROHIBIT_HOLD_TIME_STOP_BCN 0x64 + +-/* raw pkt_stat->drv_info_sz is in unit of 8-bytes */ +-#define RX_DRV_INFO_SZ_UNIT_8703B 8 +- + #define TRANS_SEQ_END \ + 0xFFFF, \ + RTW_PWR_CUT_ALL_MSK, \ +@@ -1032,57 +1029,6 @@ static void query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status, + query_phy_status_ofdm(rtwdev, phy_status, pkt_stat); + } + +-static void rtw8703b_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc, +- struct rtw_rx_pkt_stat *pkt_stat, +- struct ieee80211_rx_status *rx_status) +-{ +- struct ieee80211_hdr *hdr; +- u32 desc_sz = rtwdev->chip->rx_pkt_desc_sz; +- u8 *phy_status = NULL; +- +- memset(pkt_stat, 0, sizeof(*pkt_stat)); +- +- pkt_stat->phy_status = GET_RX_DESC_PHYST(rx_desc); +- pkt_stat->icv_err = GET_RX_DESC_ICV_ERR(rx_desc); +- pkt_stat->crc_err = GET_RX_DESC_CRC32(rx_desc); +- pkt_stat->decrypted = !GET_RX_DESC_SWDEC(rx_desc) && +- GET_RX_DESC_ENC_TYPE(rx_desc) != RX_DESC_ENC_NONE; +- pkt_stat->is_c2h = GET_RX_DESC_C2H(rx_desc); +- pkt_stat->pkt_len = GET_RX_DESC_PKT_LEN(rx_desc); +- pkt_stat->drv_info_sz = GET_RX_DESC_DRV_INFO_SIZE(rx_desc); +- pkt_stat->shift = GET_RX_DESC_SHIFT(rx_desc); +- pkt_stat->rate = GET_RX_DESC_RX_RATE(rx_desc); +- pkt_stat->cam_id = GET_RX_DESC_MACID(rx_desc); +- pkt_stat->ppdu_cnt = 0; +- pkt_stat->tsf_low = GET_RX_DESC_TSFL(rx_desc); +- +- pkt_stat->drv_info_sz *= RX_DRV_INFO_SZ_UNIT_8703B; +- +- if (pkt_stat->is_c2h) +- return; +- +- hdr = (struct ieee80211_hdr *)(rx_desc + desc_sz + pkt_stat->shift + +- pkt_stat->drv_info_sz); +- +- pkt_stat->bw = GET_RX_DESC_BW(rx_desc); +- +- if (pkt_stat->phy_status) { +- phy_status = rx_desc + desc_sz + pkt_stat->shift; +- query_phy_status(rtwdev, phy_status, pkt_stat); +- } +- +- rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status, phy_status); +- +- /* Rtl8723cs driver checks for size < 14 or size > 8192 and +- * simply drops the packet. Maybe this should go into +- * rtw_rx_fill_rx_status()? +- */ +- if (pkt_stat->pkt_len == 0) { +- rx_status->flag |= RX_FLAG_NO_PSDU; +- rtw_dbg(rtwdev, RTW_DBG_RX, "zero length packet"); +- } +-} +- + #define ADDA_ON_VAL_8703B 0x03c00014 + + static +@@ -1948,7 +1894,7 @@ static const struct rtw_chip_ops rtw8703b_ops = { + .read_efuse = rtw8703b_read_efuse, + .phy_set_param = rtw8703b_phy_set_param, + .set_channel = rtw8703b_set_channel, +- .query_rx_desc = rtw8703b_query_rx_desc, ++ .query_phy_status = query_phy_status, + .read_rf = rtw_phy_read_rf_sipi, + .write_rf = rtw_phy_write_rf_reg_sipi, + .set_tx_power_index = rtw8723x_set_tx_power_index, +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c +index 7f33e141e646..86a5e2497641 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c +@@ -227,47 +227,6 @@ static void query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status, + } + } + +-static void rtw8723d_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc, +- struct rtw_rx_pkt_stat *pkt_stat, +- struct ieee80211_rx_status *rx_status) +-{ +- struct ieee80211_hdr *hdr; +- u32 desc_sz = rtwdev->chip->rx_pkt_desc_sz; +- u8 *phy_status = NULL; +- +- memset(pkt_stat, 0, sizeof(*pkt_stat)); +- +- pkt_stat->phy_status = GET_RX_DESC_PHYST(rx_desc); +- pkt_stat->icv_err = GET_RX_DESC_ICV_ERR(rx_desc); +- pkt_stat->crc_err = GET_RX_DESC_CRC32(rx_desc); +- pkt_stat->decrypted = !GET_RX_DESC_SWDEC(rx_desc) && +- GET_RX_DESC_ENC_TYPE(rx_desc) != RX_DESC_ENC_NONE; +- pkt_stat->is_c2h = GET_RX_DESC_C2H(rx_desc); +- pkt_stat->pkt_len = GET_RX_DESC_PKT_LEN(rx_desc); +- pkt_stat->drv_info_sz = GET_RX_DESC_DRV_INFO_SIZE(rx_desc); +- pkt_stat->shift = GET_RX_DESC_SHIFT(rx_desc); +- pkt_stat->rate = GET_RX_DESC_RX_RATE(rx_desc); +- pkt_stat->cam_id = GET_RX_DESC_MACID(rx_desc); +- pkt_stat->ppdu_cnt = 0; +- pkt_stat->tsf_low = GET_RX_DESC_TSFL(rx_desc); +- +- /* drv_info_sz is in unit of 8-bytes */ +- pkt_stat->drv_info_sz *= 8; +- +- /* c2h cmd pkt's rx/phy status is not interested */ +- if (pkt_stat->is_c2h) +- return; +- +- hdr = (struct ieee80211_hdr *)(rx_desc + desc_sz + pkt_stat->shift + +- pkt_stat->drv_info_sz); +- if (pkt_stat->phy_status) { +- phy_status = rx_desc + desc_sz + pkt_stat->shift; +- query_phy_status(rtwdev, phy_status, pkt_stat); +- } +- +- rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status, phy_status); +-} +- + static bool rtw8723d_check_spur_ov_thres(struct rtw_dev *rtwdev, + u8 channel, u32 thres) + { +@@ -1433,7 +1392,7 @@ static void rtw8723d_pwr_track(struct rtw_dev *rtwdev) + static const struct rtw_chip_ops rtw8723d_ops = { + .phy_set_param = rtw8723d_phy_set_param, + .read_efuse = rtw8723x_read_efuse, +- .query_rx_desc = rtw8723d_query_rx_desc, ++ .query_phy_status = query_phy_status, + .set_channel = rtw8723d_set_channel, + .mac_init = rtw8723x_mac_init, + .shutdown = rtw8723d_shutdown, +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.c b/drivers/net/wireless/realtek/rtw88/rtw8821c.c +index 9d21c4b1450e..66c79956e8e5 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8821c.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.c +@@ -679,47 +679,6 @@ static void query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status, + } + } + +-static void rtw8821c_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc, +- struct rtw_rx_pkt_stat *pkt_stat, +- struct ieee80211_rx_status *rx_status) +-{ +- struct ieee80211_hdr *hdr; +- u32 desc_sz = rtwdev->chip->rx_pkt_desc_sz; +- u8 *phy_status = NULL; +- +- memset(pkt_stat, 0, sizeof(*pkt_stat)); +- +- pkt_stat->phy_status = GET_RX_DESC_PHYST(rx_desc); +- pkt_stat->icv_err = GET_RX_DESC_ICV_ERR(rx_desc); +- pkt_stat->crc_err = GET_RX_DESC_CRC32(rx_desc); +- pkt_stat->decrypted = !GET_RX_DESC_SWDEC(rx_desc) && +- GET_RX_DESC_ENC_TYPE(rx_desc) != RX_DESC_ENC_NONE; +- pkt_stat->is_c2h = GET_RX_DESC_C2H(rx_desc); +- pkt_stat->pkt_len = GET_RX_DESC_PKT_LEN(rx_desc); +- pkt_stat->drv_info_sz = GET_RX_DESC_DRV_INFO_SIZE(rx_desc); +- pkt_stat->shift = GET_RX_DESC_SHIFT(rx_desc); +- pkt_stat->rate = GET_RX_DESC_RX_RATE(rx_desc); +- pkt_stat->cam_id = GET_RX_DESC_MACID(rx_desc); +- pkt_stat->ppdu_cnt = GET_RX_DESC_PPDU_CNT(rx_desc); +- pkt_stat->tsf_low = GET_RX_DESC_TSFL(rx_desc); +- +- /* drv_info_sz is in unit of 8-bytes */ +- pkt_stat->drv_info_sz *= 8; +- +- /* c2h cmd pkt's rx/phy status is not interested */ +- if (pkt_stat->is_c2h) +- return; +- +- hdr = (struct ieee80211_hdr *)(rx_desc + desc_sz + pkt_stat->shift + +- pkt_stat->drv_info_sz); +- if (pkt_stat->phy_status) { +- phy_status = rx_desc + desc_sz + pkt_stat->shift; +- query_phy_status(rtwdev, phy_status, pkt_stat); +- } +- +- rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status, phy_status); +-} +- + static void + rtw8821c_set_tx_power_index_by_rate(struct rtw_dev *rtwdev, u8 path, u8 rs) + { +@@ -1686,7 +1645,7 @@ static const struct rtw_prioq_addrs prioq_addrs_8821c = { + static const struct rtw_chip_ops rtw8821c_ops = { + .phy_set_param = rtw8821c_phy_set_param, + .read_efuse = rtw8821c_read_efuse, +- .query_rx_desc = rtw8821c_query_rx_desc, ++ .query_phy_status = query_phy_status, + .set_channel = rtw8821c_set_channel, + .mac_init = rtw8821c_mac_init, + .read_rf = rtw_phy_read_rf, +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c +index c9e50756655c..8e1393ca3301 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c +@@ -934,47 +934,6 @@ static void query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status, + } + } + +-static void rtw8822b_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc, +- struct rtw_rx_pkt_stat *pkt_stat, +- struct ieee80211_rx_status *rx_status) +-{ +- struct ieee80211_hdr *hdr; +- u32 desc_sz = rtwdev->chip->rx_pkt_desc_sz; +- u8 *phy_status = NULL; +- +- memset(pkt_stat, 0, sizeof(*pkt_stat)); +- +- pkt_stat->phy_status = GET_RX_DESC_PHYST(rx_desc); +- pkt_stat->icv_err = GET_RX_DESC_ICV_ERR(rx_desc); +- pkt_stat->crc_err = GET_RX_DESC_CRC32(rx_desc); +- pkt_stat->decrypted = !GET_RX_DESC_SWDEC(rx_desc) && +- GET_RX_DESC_ENC_TYPE(rx_desc) != RX_DESC_ENC_NONE; +- pkt_stat->is_c2h = GET_RX_DESC_C2H(rx_desc); +- pkt_stat->pkt_len = GET_RX_DESC_PKT_LEN(rx_desc); +- pkt_stat->drv_info_sz = GET_RX_DESC_DRV_INFO_SIZE(rx_desc); +- pkt_stat->shift = GET_RX_DESC_SHIFT(rx_desc); +- pkt_stat->rate = GET_RX_DESC_RX_RATE(rx_desc); +- pkt_stat->cam_id = GET_RX_DESC_MACID(rx_desc); +- pkt_stat->ppdu_cnt = GET_RX_DESC_PPDU_CNT(rx_desc); +- pkt_stat->tsf_low = GET_RX_DESC_TSFL(rx_desc); +- +- /* drv_info_sz is in unit of 8-bytes */ +- pkt_stat->drv_info_sz *= 8; +- +- /* c2h cmd pkt's rx/phy status is not interested */ +- if (pkt_stat->is_c2h) +- return; +- +- hdr = (struct ieee80211_hdr *)(rx_desc + desc_sz + pkt_stat->shift + +- pkt_stat->drv_info_sz); +- if (pkt_stat->phy_status) { +- phy_status = rx_desc + desc_sz + pkt_stat->shift; +- query_phy_status(rtwdev, phy_status, pkt_stat); +- } +- +- rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status, phy_status); +-} +- + static void + rtw8822b_set_tx_power_index_by_rate(struct rtw_dev *rtwdev, u8 path, + u8 rs, u32 *phy_pwr_idx) +@@ -2177,7 +2136,7 @@ static const struct rtw_prioq_addrs prioq_addrs_8822b = { + static const struct rtw_chip_ops rtw8822b_ops = { + .phy_set_param = rtw8822b_phy_set_param, + .read_efuse = rtw8822b_read_efuse, +- .query_rx_desc = rtw8822b_query_rx_desc, ++ .query_phy_status = query_phy_status, + .set_channel = rtw8822b_set_channel, + .mac_init = rtw8822b_mac_init, + .read_rf = rtw_phy_read_rf, +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c +index 9aae401722fb..11dc14db822b 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c +@@ -2690,48 +2690,6 @@ static void query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status, + } + } + +-static void rtw8822c_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc, +- struct rtw_rx_pkt_stat *pkt_stat, +- struct ieee80211_rx_status *rx_status) +-{ +- struct ieee80211_hdr *hdr; +- u32 desc_sz = rtwdev->chip->rx_pkt_desc_sz; +- u8 *phy_status = NULL; +- +- memset(pkt_stat, 0, sizeof(*pkt_stat)); +- +- pkt_stat->phy_status = GET_RX_DESC_PHYST(rx_desc); +- pkt_stat->icv_err = GET_RX_DESC_ICV_ERR(rx_desc); +- pkt_stat->crc_err = GET_RX_DESC_CRC32(rx_desc); +- pkt_stat->decrypted = !GET_RX_DESC_SWDEC(rx_desc) && +- GET_RX_DESC_ENC_TYPE(rx_desc) != RX_DESC_ENC_NONE; +- pkt_stat->is_c2h = GET_RX_DESC_C2H(rx_desc); +- pkt_stat->pkt_len = GET_RX_DESC_PKT_LEN(rx_desc); +- pkt_stat->drv_info_sz = GET_RX_DESC_DRV_INFO_SIZE(rx_desc); +- pkt_stat->shift = GET_RX_DESC_SHIFT(rx_desc); +- pkt_stat->rate = GET_RX_DESC_RX_RATE(rx_desc); +- pkt_stat->cam_id = GET_RX_DESC_MACID(rx_desc); +- pkt_stat->ppdu_cnt = GET_RX_DESC_PPDU_CNT(rx_desc); +- pkt_stat->tsf_low = GET_RX_DESC_TSFL(rx_desc); +- +- /* drv_info_sz is in unit of 8-bytes */ +- pkt_stat->drv_info_sz *= 8; +- +- /* c2h cmd pkt's rx/phy status is not interested */ +- if (pkt_stat->is_c2h) +- return; +- +- hdr = (struct ieee80211_hdr *)(rx_desc + desc_sz + pkt_stat->shift + +- pkt_stat->drv_info_sz); +- pkt_stat->hdr = hdr; +- if (pkt_stat->phy_status) { +- phy_status = rx_desc + desc_sz + pkt_stat->shift; +- query_phy_status(rtwdev, phy_status, pkt_stat); +- } +- +- rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status, phy_status); +-} +- + static void + rtw8822c_set_write_tx_power_ref(struct rtw_dev *rtwdev, u8 *tx_pwr_ref_cck, + u8 *tx_pwr_ref_ofdm) +@@ -4992,7 +4950,7 @@ static const struct rtw_prioq_addrs prioq_addrs_8822c = { + static const struct rtw_chip_ops rtw8822c_ops = { + .phy_set_param = rtw8822c_phy_set_param, + .read_efuse = rtw8822c_read_efuse, +- .query_rx_desc = rtw8822c_query_rx_desc, ++ .query_phy_status = query_phy_status, + .set_channel = rtw8822c_set_channel, + .mac_init = rtw8822c_mac_init, + .dump_fw_crash = rtw8822c_dump_fw_crash, +diff --git a/drivers/net/wireless/realtek/rtw88/rx.c b/drivers/net/wireless/realtek/rtw88/rx.c +index 66f9419588cf..1de93fc9efe9 100644 +--- a/drivers/net/wireless/realtek/rtw88/rx.c ++++ b/drivers/net/wireless/realtek/rtw88/rx.c +@@ -187,11 +187,10 @@ void rtw_update_rx_freq_from_ie(struct rtw_dev *rtwdev, struct sk_buff *skb, + } + EXPORT_SYMBOL(rtw_update_rx_freq_from_ie); + +-void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev, +- struct rtw_rx_pkt_stat *pkt_stat, +- struct ieee80211_hdr *hdr, +- struct ieee80211_rx_status *rx_status, +- u8 *phy_status) ++static void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev, ++ struct rtw_rx_pkt_stat *pkt_stat, ++ struct ieee80211_hdr *hdr, ++ struct ieee80211_rx_status *rx_status) + { + struct ieee80211_hw *hw = rtwdev->hw; + u8 path; +@@ -242,5 +241,64 @@ void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev, + } + + rtw_rx_addr_match(rtwdev, pkt_stat, hdr); ++ ++ /* Rtl8723cs driver checks for size < 14 or size > 8192 and ++ * simply drops the packet. ++ */ ++ if (rtwdev->chip->id == RTW_CHIP_TYPE_8703B && pkt_stat->pkt_len == 0) { ++ rx_status->flag |= RX_FLAG_NO_PSDU; ++ rtw_dbg(rtwdev, RTW_DBG_RX, "zero length packet"); ++ } ++} ++ ++void rtw_rx_query_rx_desc(struct rtw_dev *rtwdev, void *rx_desc8, ++ struct rtw_rx_pkt_stat *pkt_stat, ++ struct ieee80211_rx_status *rx_status) ++{ ++ u32 desc_sz = rtwdev->chip->rx_pkt_desc_sz; ++ struct rtw_rx_desc *rx_desc = rx_desc8; ++ struct ieee80211_hdr *hdr; ++ u32 enc_type, swdec; ++ void *phy_status; ++ ++ memset(pkt_stat, 0, sizeof(*pkt_stat)); ++ ++ pkt_stat->pkt_len = le32_get_bits(rx_desc->w0, RTW_RX_DESC_W0_PKT_LEN); ++ pkt_stat->crc_err = le32_get_bits(rx_desc->w0, RTW_RX_DESC_W0_CRC32); ++ pkt_stat->icv_err = le32_get_bits(rx_desc->w0, RTW_RX_DESC_W0_ICV_ERR); ++ pkt_stat->drv_info_sz = le32_get_bits(rx_desc->w0, ++ RTW_RX_DESC_W0_DRV_INFO_SIZE); ++ enc_type = le32_get_bits(rx_desc->w0, RTW_RX_DESC_W0_ENC_TYPE); ++ pkt_stat->shift = le32_get_bits(rx_desc->w0, RTW_RX_DESC_W0_SHIFT); ++ pkt_stat->phy_status = le32_get_bits(rx_desc->w0, RTW_RX_DESC_W0_PHYST); ++ swdec = le32_get_bits(rx_desc->w0, RTW_RX_DESC_W0_SWDEC); ++ pkt_stat->decrypted = !swdec && enc_type != RX_DESC_ENC_NONE; ++ ++ pkt_stat->cam_id = le32_get_bits(rx_desc->w1, RTW_RX_DESC_W1_MACID); ++ ++ pkt_stat->is_c2h = le32_get_bits(rx_desc->w2, RTW_RX_DESC_W2_C2H); ++ pkt_stat->ppdu_cnt = le32_get_bits(rx_desc->w2, RTW_RX_DESC_W2_PPDU_CNT); ++ ++ pkt_stat->rate = le32_get_bits(rx_desc->w3, RTW_RX_DESC_W3_RX_RATE); ++ ++ pkt_stat->bw = le32_get_bits(rx_desc->w4, RTW_RX_DESC_W4_BW); ++ ++ pkt_stat->tsf_low = le32_get_bits(rx_desc->w5, RTW_RX_DESC_W5_TSFL); ++ ++ /* drv_info_sz is in unit of 8-bytes */ ++ pkt_stat->drv_info_sz *= 8; ++ ++ /* c2h cmd pkt's rx/phy status is not interested */ ++ if (pkt_stat->is_c2h) ++ return; ++ ++ phy_status = rx_desc8 + desc_sz + pkt_stat->shift; ++ hdr = phy_status + pkt_stat->drv_info_sz; ++ pkt_stat->hdr = hdr; ++ ++ if (pkt_stat->phy_status) ++ rtwdev->chip->ops->query_phy_status(rtwdev, phy_status, pkt_stat); ++ ++ rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status); + } +-EXPORT_SYMBOL(rtw_rx_fill_rx_status); ++EXPORT_SYMBOL(rtw_rx_query_rx_desc); +diff --git a/drivers/net/wireless/realtek/rtw88/rx.h b/drivers/net/wireless/realtek/rtw88/rx.h +index 9f0019112987..6b7dee245c0a 100644 +--- a/drivers/net/wireless/realtek/rtw88/rx.h ++++ b/drivers/net/wireless/realtek/rtw88/rx.h +@@ -14,42 +14,40 @@ enum rtw_rx_desc_enc { + RX_DESC_ENC_WEP104 = 5, + }; + +-#define GET_RX_DESC_PHYST(rxdesc) \ +- le32_get_bits(*((__le32 *)(rxdesc) + 0x00), BIT(26)) +-#define GET_RX_DESC_ICV_ERR(rxdesc) \ +- le32_get_bits(*((__le32 *)(rxdesc) + 0x00), BIT(15)) +-#define GET_RX_DESC_CRC32(rxdesc) \ +- le32_get_bits(*((__le32 *)(rxdesc) + 0x00), BIT(14)) +-#define GET_RX_DESC_SWDEC(rxdesc) \ +- le32_get_bits(*((__le32 *)(rxdesc) + 0x00), BIT(27)) +-#define GET_RX_DESC_C2H(rxdesc) \ +- le32_get_bits(*((__le32 *)(rxdesc) + 0x02), BIT(28)) +-#define GET_RX_DESC_PKT_LEN(rxdesc) \ +- le32_get_bits(*((__le32 *)(rxdesc) + 0x00), GENMASK(13, 0)) +-#define GET_RX_DESC_DRV_INFO_SIZE(rxdesc) \ +- le32_get_bits(*((__le32 *)(rxdesc) + 0x00), GENMASK(19, 16)) +-#define GET_RX_DESC_SHIFT(rxdesc) \ +- le32_get_bits(*((__le32 *)(rxdesc) + 0x00), GENMASK(25, 24)) +-#define GET_RX_DESC_ENC_TYPE(rxdesc) \ +- le32_get_bits(*((__le32 *)(rxdesc) + 0x00), GENMASK(22, 20)) +-#define GET_RX_DESC_RX_RATE(rxdesc) \ +- le32_get_bits(*((__le32 *)(rxdesc) + 0x03), GENMASK(6, 0)) +-#define GET_RX_DESC_MACID(rxdesc) \ +- le32_get_bits(*((__le32 *)(rxdesc) + 0x01), GENMASK(6, 0)) +-#define GET_RX_DESC_PPDU_CNT(rxdesc) \ +- le32_get_bits(*((__le32 *)(rxdesc) + 0x02), GENMASK(30, 29)) +-#define GET_RX_DESC_TSFL(rxdesc) \ +- le32_get_bits(*((__le32 *)(rxdesc) + 0x05), GENMASK(31, 0)) +-#define GET_RX_DESC_BW(rxdesc) \ +- (le32_get_bits(*((__le32 *)(rxdesc) + 0x04), GENMASK(5, 4))) ++struct rtw_rx_desc { ++ __le32 w0; ++ __le32 w1; ++ __le32 w2; ++ __le32 w3; ++ __le32 w4; ++ __le32 w5; ++} __packed; ++ ++#define RTW_RX_DESC_W0_PKT_LEN GENMASK(13, 0) ++#define RTW_RX_DESC_W0_CRC32 BIT(14) ++#define RTW_RX_DESC_W0_ICV_ERR BIT(15) ++#define RTW_RX_DESC_W0_DRV_INFO_SIZE GENMASK(19, 16) ++#define RTW_RX_DESC_W0_ENC_TYPE GENMASK(22, 20) ++#define RTW_RX_DESC_W0_SHIFT GENMASK(25, 24) ++#define RTW_RX_DESC_W0_PHYST BIT(26) ++#define RTW_RX_DESC_W0_SWDEC BIT(27) ++ ++#define RTW_RX_DESC_W1_MACID GENMASK(6, 0) ++ ++#define RTW_RX_DESC_W2_C2H BIT(28) ++#define RTW_RX_DESC_W2_PPDU_CNT GENMASK(30, 29) ++ ++#define RTW_RX_DESC_W3_RX_RATE GENMASK(6, 0) ++ ++#define RTW_RX_DESC_W4_BW GENMASK(5, 4) ++ ++#define RTW_RX_DESC_W5_TSFL GENMASK(31, 0) + + void rtw_rx_stats(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, + struct sk_buff *skb); +-void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev, +- struct rtw_rx_pkt_stat *pkt_stat, +- struct ieee80211_hdr *hdr, +- struct ieee80211_rx_status *rx_status, +- u8 *phy_status); ++void rtw_rx_query_rx_desc(struct rtw_dev *rtwdev, void *rx_desc8, ++ struct rtw_rx_pkt_stat *pkt_stat, ++ struct ieee80211_rx_status *rx_status); + void rtw_update_rx_freq_from_ie(struct rtw_dev *rtwdev, struct sk_buff *skb, + struct ieee80211_rx_status *rx_status, + struct rtw_rx_pkt_stat *pkt_stat); +diff --git a/drivers/net/wireless/realtek/rtw88/sdio.c b/drivers/net/wireless/realtek/rtw88/sdio.c +index 787fa09fd063..fe6f14290bdd 100644 +--- a/drivers/net/wireless/realtek/rtw88/sdio.c ++++ b/drivers/net/wireless/realtek/rtw88/sdio.c +@@ -979,8 +979,7 @@ static void rtw_sdio_rxfifo_recv(struct rtw_dev *rtwdev, u32 rx_len) + + while (true) { + rx_desc = skb->data; +- chip->ops->query_rx_desc(rtwdev, rx_desc, &pkt_stat, +- &rx_status); ++ rtw_rx_query_rx_desc(rtwdev, rx_desc, &pkt_stat, &rx_status); + pkt_offset = pkt_desc_sz + pkt_stat.drv_info_sz + + pkt_stat.shift; + +diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c +index a446be45f26e..83acb96b44ed 100644 +--- a/drivers/net/wireless/realtek/rtw88/usb.c ++++ b/drivers/net/wireless/realtek/rtw88/usb.c +@@ -625,8 +625,8 @@ static void rtw_usb_rx_handler(struct work_struct *work) + + do { + rx_desc = skb->data; +- chip->ops->query_rx_desc(rtwdev, rx_desc, &pkt_stat, +- &rx_status); ++ rtw_rx_query_rx_desc(rtwdev, rx_desc, &pkt_stat, ++ &rx_status); + pkt_offset = pkt_desc_sz + pkt_stat.drv_info_sz + + pkt_stat.shift; + +-- +2.39.5 + diff --git a/packages/linux/patches/rtlwifi/6.13/0003-wifi-rtw88-Add-some-definitions-for-RTL8821AU-RTL881.patch b/packages/linux/patches/rtlwifi/6.13/0003-wifi-rtw88-Add-some-definitions-for-RTL8821AU-RTL881.patch new file mode 100644 index 0000000000..41705fa87f --- /dev/null +++ b/packages/linux/patches/rtlwifi/6.13/0003-wifi-rtw88-Add-some-definitions-for-RTL8821AU-RTL881.patch @@ -0,0 +1,502 @@ +From 26496e78b747356fcbb88a23316625679697ba88 Mon Sep 17 00:00:00 2001 +From: Bitterblue Smith +Date: Wed, 23 Oct 2024 17:00:59 +0300 +Subject: [PATCH 03/24] wifi: rtw88: Add some definitions for + RTL8821AU/RTL8812AU + +Add 8821A and 8812A chip type enums. + +Add cck_high_power member to struct rtw_hal. This will be used to +calculate the RX signal strength of RTL8812AU. + +Add various register definitions which will be used by the new drivers. + +Move some existing register definitions from rtw8821c.h and rtw8822b.h. +They were duplicated in those headers and will also be used by the new +drivers. + +Signed-off-by: Bitterblue Smith +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/9279a9cd-6f86-4dc3-a095-7c36cb9b9d06@gmail.com +--- + drivers/net/wireless/realtek/rtw88/main.h | 3 + + drivers/net/wireless/realtek/rtw88/reg.h | 174 ++++++++++++++++++ + drivers/net/wireless/realtek/rtw88/rtw8821c.h | 24 --- + drivers/net/wireless/realtek/rtw88/rtw8822b.h | 12 -- + 4 files changed, 177 insertions(+), 36 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h +index c9efe9d66954..46935524783e 100644 +--- a/drivers/net/wireless/realtek/rtw88/main.h ++++ b/drivers/net/wireless/realtek/rtw88/main.h +@@ -189,6 +189,8 @@ enum rtw_chip_type { + RTW_CHIP_TYPE_8723D, + RTW_CHIP_TYPE_8821C, + RTW_CHIP_TYPE_8703B, ++ RTW_CHIP_TYPE_8821A, ++ RTW_CHIP_TYPE_8812A, + }; + + enum rtw_tx_queue_type { +@@ -1934,6 +1936,7 @@ struct rtw_hal { + u32 antenna_rx; + u8 bfee_sts_cap; + bool txrx_1ss; ++ bool cck_high_power; + + /* protect tx power section */ + struct mutex tx_power_mutex; +diff --git a/drivers/net/wireless/realtek/rtw88/reg.h b/drivers/net/wireless/realtek/rtw88/reg.h +index 2708ee2f12a4..946a6e6cc826 100644 +--- a/drivers/net/wireless/realtek/rtw88/reg.h ++++ b/drivers/net/wireless/realtek/rtw88/reg.h +@@ -9,6 +9,7 @@ + #define BIT_FEN_EN_25_1 BIT(13) + #define BIT_FEN_ELDR BIT(12) + #define BIT_FEN_CPUEN BIT(2) ++#define BIT_FEN_USBA BIT(2) + #define BIT_FEN_BB_GLB_RST BIT(1) + #define BIT_FEN_BB_RSTB BIT(0) + #define BIT_R_DIS_PRST BIT(6) +@@ -16,6 +17,10 @@ + #define REG_SYS_PW_CTRL 0x0004 + #define BIT_PFM_WOWL BIT(3) + #define BIT_APFM_OFFMAC BIT(9) ++#define REG_APS_FSMCO 0x0004 ++#define APS_FSMCO_MAC_ENABLE BIT(8) ++#define APS_FSMCO_MAC_OFF BIT(9) ++#define APS_FSMCO_HW_POWERDOWN BIT(15) + #define REG_SYS_CLK_CTRL 0x0008 + #define BIT_CPU_CLK_EN BIT(14) + +@@ -58,6 +63,8 @@ + #define BIT_SHIFT_LDO25_VOLTAGE 4 + #define BIT_LDO25_EN BIT(7) + ++#define REG_ACLK_MON 0x3e ++ + #define REG_GPIO_MUXCFG 0x0040 + #define BIT_FSPI_EN BIT(19) + #define BIT_EN_SIC BIT(12) +@@ -90,6 +97,8 @@ + #define BIT_USB_SUS_DIS BIT(8) + #define BIT_SDIO_PAD_E5 BIT(18) + ++#define REG_RF_B_CTRL 0x76 ++ + #define REG_AFE_CTRL_4 0x0078 + #define BIT_CK320M_AFE_EN BIT(4) + #define BIT_EN_SYN BIT(15) +@@ -135,6 +144,11 @@ + #define REG_PMC_DBG_CTRL1 0xa8 + #define BITS_PMC_BT_IQK_STS GENMASK(22, 21) + ++#define REG_HIMR0 0xb0 ++#define REG_HISR0 0xb4 ++#define REG_HIMR1 0xb8 ++#define REG_HISR1 0xbc ++ + #define REG_PAD_CTRL2 0x00C4 + #define BIT_RSM_EN_V1 BIT(16) + #define BIT_NO_PDN_CHIPOFF_V1 BIT(17) +@@ -186,6 +200,15 @@ + #define MAC_TRX_ENABLE (BIT_HCI_TXDMA_EN | BIT_HCI_RXDMA_EN | BIT_TXDMA_EN | \ + BIT_RXDMA_EN | BIT_PROTOCOL_EN | BIT_SCHEDULE_EN | \ + BIT_MACTXEN | BIT_MACRXEN) ++#define REG_PBP 0x104 ++#define PBP_RX_MASK 0x0f ++#define PBP_TX_MASK 0xf0 ++#define PBP_64 0x0 ++#define PBP_128 0x1 ++#define PBP_256 0x2 ++#define PBP_512 0x3 ++#define PBP_1024 0x4 ++ + #define BIT_SHIFT_TXDMA_VOQ_MAP 4 + #define BIT_MASK_TXDMA_VOQ_MAP 0x3 + #define BIT_TXDMA_VOQ_MAP(x) \ +@@ -257,6 +280,8 @@ + #define REG_HMEBOX1 0x01D4 + #define REG_HMEBOX2 0x01D8 + #define REG_HMEBOX3 0x01DC ++#define REG_LLT_INIT 0x01E0 ++#define BIT_LLT_WRITE_ACCESS BIT(30) + #define REG_HMEBOX0_EX 0x01F0 + #define REG_HMEBOX1_EX 0x01F4 + #define REG_HMEBOX2_EX 0x01F8 +@@ -299,6 +324,7 @@ + + #define REG_AUTO_LLT 0x0224 + #define BIT_AUTO_INIT_LLT BIT(16) ++#define REG_DWBCN1_CTRL 0x0228 + #define REG_RQPN_CTRL_1 0x0228 + #define REG_RQPN_CTRL_2 0x022C + #define BIT_LD_RQPN BIT(31) +@@ -330,6 +356,7 @@ + #define BIT_DMA_BURST_SIZE_1024 0 + + #define REG_RXPKTNUM 0x02B0 ++#define REG_EARLY_MODE_CONTROL 0x02BC + + #define REG_INT_MIG 0x0304 + #define REG_HCI_MIX_CFG 0x03FC +@@ -337,6 +364,7 @@ + + #define REG_BCNQ_INFO 0x0418 + #define BIT_MGQ_CPU_EMPTY BIT(24) ++#define REG_TXPKT_EMPTY 0x041A + #define REG_FWHW_TXQ_CTRL 0x0420 + #define BIT_EN_BCNQ_DL BIT(22) + #define BIT_EN_WR_FREE_TAIL BIT(20) +@@ -363,10 +391,12 @@ + #define REG_AMPDU_MAX_TIME_V1 0x0455 + #define REG_BCNQ1_BDNY_V1 0x0456 + #define REG_AMPDU_MAX_TIME 0x0456 ++#define REG_AMPDU_MAX_LENGTH 0x0458 + #define REG_WMAC_LBK_BF_HD 0x045D + #define REG_TX_HANG_CTRL 0x045E + #define BIT_EN_GNT_BT_AWAKE BIT(3) + #define BIT_EN_EOF_V1 BIT(2) ++#define REG_FAST_EDCA_CTRL 0x0460 + #define REG_DATA_SC 0x0483 + #define REG_ARFR2_V1 0x048C + #define REG_ARFRH2_V1 0x0490 +@@ -391,6 +421,8 @@ + #define REG_PRECNT_CTRL 0x04E5 + #define BIT_BTCCA_CTRL (BIT(0) | BIT(1)) + #define BIT_EN_PRECNT BIT(11) ++#define REG_TX_RPT_CTRL 0x04EC ++#define REG_TX_RPT_TIME 0x04F0 + #define REG_DUMMY_PAGE4_V1 0x04FC + + #define REG_EDCA_VO_PARAM 0x0500 +@@ -401,6 +433,7 @@ + #define BIT_MASK_CWMAX GENMASK(15, 12) + #define BIT_MASK_CWMIN GENMASK(11, 8) + #define BIT_MASK_AIFS GENMASK(7, 0) ++#define REG_BCNTCFG 0x0510 + #define REG_PIFS 0x0512 + #define REG_SIFS 0x0514 + #define BIT_SHIFT_SIFS_OFDM_CTX 8 +@@ -527,6 +560,8 @@ + #define REG_BT_COEX_V2 0x0762 + #define BIT_GNT_BT_POLARITY BIT(12) + #define BIT_LTE_COEX_EN BIT(7) ++#define REG_GNT_BT 0x0765 ++#define BIT_PTA_SW_CTL GENMASK(4, 3) + #define REG_BT_COEX_ENH_INTR_CTRL 0x76E + #define BIT_R_GRANTALL_WLMASK BIT(3) + #define BIT_STATIS_BT_EN BIT(2) +@@ -544,14 +579,43 @@ + #define REG_FPGA0_RFMOD 0x0800 + #define BIT_CCKEN BIT(24) + #define BIT_OFDMEN BIT(25) ++#define REG_CCK_RPT_FORMAT 0x0804 ++#define BIT_CCK_RPT_FORMAT BIT(16) ++#define REG_RXPSEL 0x0808 ++#define BIT_RX_PSEL_RST (BIT(28) | BIT(29)) ++#define REG_TXPSEL 0x080C + #define REG_RX_GAIN_EN 0x081c ++#define REG_CCASEL 0x082C ++#define REG_PDMFTH 0x0830 ++#define REG_BWINDICATION 0x0834 ++#define REG_CCA2ND 0x0838 ++#define REG_L1PKTH 0x0848 ++#define REG_CLKTRK 0x0860 ++#define REG_ADCCLK 0x08AC ++#define REG_HSSI_READ 0x08B0 ++#define REG_FPGA0_XCD_RF_PARA 0x08B4 ++#define REG_RX_MCS_LIMIT 0x08BC ++#define REG_ADC160 0x08C4 ++#define REG_ANTSEL_SW 0x0900 ++#define REG_DAC_RSTB 0x090c ++#define REG_SINGLE_TONE_CONT_TX 0x0914 + + #define REG_RFE_CTRL_E 0x0974 + #define REG_2ND_CCA_CTRL 0x0976 ++#define REG_IQK_COM00 0x0978 ++#define REG_IQK_COM32 0x097c ++#define REG_IQK_COM64 0x0980 ++#define REG_IQK_COM96 0x0984 ++ ++#define REG_FAS 0x09a4 ++#define REG_RXSB 0x0a00 ++#define REG_CCK_RX 0x0a04 ++#define REG_CCK_PD_TH 0x0a0a + + #define REG_CCK0_FAREPORT 0xa2c + #define BIT_CCK0_2RX BIT(18) + #define BIT_CCK0_MRC BIT(22) ++#define REG_FA_CCK 0x0a5c + + #define REG_DIS_DPD 0x0a70 + #define DIS_DPD_MASK GENMASK(9, 0) +@@ -567,13 +631,109 @@ + #define DIS_DPD_RATEVHT2SS_MCS1 BIT(9) + #define DIS_DPD_RATEALL GENMASK(9, 0) + ++#define REG_CNTRST 0x0b58 ++ ++#define REG_3WIRE_SWA 0x0c00 ++#define REG_RX_IQC_AB_A 0x0c10 ++#define REG_TXSCALE_A 0x0c1c ++#define BB_SWING_MASK GENMASK(31, 21) ++#define REG_TX_AGC_A_CCK_11_CCK_1 0xc20 ++#define REG_TX_AGC_A_OFDM18_OFDM6 0xc24 ++#define REG_TX_AGC_A_OFDM54_OFDM24 0xc28 ++#define REG_TX_AGC_A_MCS3_MCS0 0xc2c ++#define REG_TX_AGC_A_MCS7_MCS4 0xc30 ++#define REG_TX_AGC_A_MCS11_MCS8 0xc34 ++#define REG_TX_AGC_A_MCS15_MCS12 0xc38 ++#define REG_TX_AGC_A_NSS1_INDEX3_NSS1_INDEX0 0xc3c ++#define REG_TX_AGC_A_NSS1_INDEX7_NSS1_INDEX4 0xc40 ++#define REG_TX_AGC_A_NSS2_INDEX1_NSS1_INDEX8 0xc44 ++#define REG_TX_AGC_A_NSS2_INDEX5_NSS2_INDEX2 0xc48 ++#define REG_TX_AGC_A_NSS2_INDEX9_NSS2_INDEX6 0xc4c ++#define REG_RXIGI_A 0x0c50 ++#define REG_TX_PWR_TRAINING_A 0x0c54 ++#define REG_CK_MONHA 0x0c5c ++#define REG_AFE_PWR1_A 0x0c60 ++#define REG_AFE_PWR2_A 0x0c64 ++#define REG_RX_WAIT_CCA_TX_CCK_RFON_A 0x0c68 ++#define REG_OFDM0_XA_TX_IQ_IMBALANCE 0x0c80 ++#define REG_OFDM0_A_TX_AFE 0x0c84 ++#define REG_OFDM0_XB_TX_IQ_IMBALANCE 0x0c88 ++#define REG_TSSI_TRK_SW 0x0c8c ++#define REG_LSSI_WRITE_A 0x0c90 ++#define REG_PREDISTA 0x0c90 ++#define REG_TXAGCIDX 0x0c94 ++ ++#define REG_RFE_PINMUX_A 0x0cb0 ++#define REG_RFE_INV_A 0x0cb4 + #define REG_RFE_CTRL8 0x0cb4 + #define BIT_MASK_RFE_SEL89 GENMASK(7, 0) ++#define PTA_CTRL_PIN 0x66 ++#define DPDT_CTRL_PIN 0x77 ++#define RFE_INV_MASK 0x3ff00000 ++#define REG_RFECTL_A 0x0cb8 + #define REG_RFE_INV8 0x0cbd + #define BIT_MASK_RFE_INV89 GENMASK(1, 0) + #define REG_RFE_INV16 0x0cbe + #define BIT_RFE_BUF_EN BIT(3) + ++#define REG_IQK_DPD_CFG 0x0cc4 ++#define REG_CFG_PMPD 0x0cc8 ++#define REG_IQC_Y 0x0ccc ++#define REG_IQC_X 0x0cd4 ++#define REG_INTPO_SETA 0x0ce8 ++ ++#define REG_IQKA_END 0x0d00 ++#define REG_PI_READ_A 0x0d04 ++#define REG_SI_READ_A 0x0d08 ++#define REG_IQKB_END 0x0d40 ++#define REG_PI_READ_B 0x0d44 ++#define REG_SI_READ_B 0x0d48 ++ ++#define REG_3WIRE_SWB 0x0e00 ++#define REG_RX_IQC_AB_B 0x0e10 ++#define REG_TXSCALE_B 0x0e1c ++#define REG_TX_AGC_B_CCK_11_CCK_1 0xe20 ++#define REG_TX_AGC_B_OFDM18_OFDM6 0xe24 ++#define REG_TX_AGC_B_OFDM54_OFDM24 0xe28 ++#define REG_TX_AGC_B_MCS3_MCS0 0xe2c ++#define REG_TX_AGC_B_MCS7_MCS4 0xe30 ++#define REG_TX_AGC_B_MCS11_MCS8 0xe34 ++#define REG_TX_AGC_B_MCS15_MCS12 0xe38 ++#define REG_TX_AGC_B_NSS1_INDEX3_NSS1_INDEX0 0xe3c ++#define REG_TX_AGC_B_NSS1_INDEX7_NSS1_INDEX4 0xe40 ++#define REG_TX_AGC_B_NSS2_INDEX1_NSS1_INDEX8 0xe44 ++#define REG_TX_AGC_B_NSS2_INDEX5_NSS2_INDEX2 0xe48 ++#define REG_TX_AGC_B_NSS2_INDEX9_NSS2_INDEX6 0xe4c ++#define REG_RXIGI_B 0x0e50 ++#define REG_TX_PWR_TRAINING_B 0x0e54 ++#define REG_CK_MONHB 0x0e5c ++#define REG_AFE_PWR1_B 0x0e60 ++#define REG_AFE_PWR2_B 0x0e64 ++#define REG_RX_WAIT_CCA_TX_CCK_RFON_B 0x0e68 ++#define REG_TXTONEB 0x0e80 ++#define REG_RXTONEB 0x0e84 ++#define REG_TXPITMB 0x0e88 ++#define REG_RXPITMB 0x0e8c ++#define REG_LSSI_WRITE_B 0x0e90 ++#define REG_PREDISTB 0x0e90 ++#define REG_INIDLYB 0x0e94 ++#define REG_RFE_PINMUX_B 0x0eb0 ++#define REG_RFE_INV_B 0x0eb4 ++#define REG_RFECTL_B 0x0eb8 ++#define REG_BPBDB 0x0ec4 ++#define REG_PHYTXONB 0x0ec8 ++#define REG_IQKYB 0x0ecc ++#define REG_IQKXB 0x0ed4 ++#define REG_INTPO_SETB 0x0ee8 ++ ++#define REG_CRC_CCK 0x0f04 ++#define REG_CCA_OFDM 0x0f08 ++#define REG_CRC_VHT 0x0f0c ++#define REG_CRC_HT 0x0f10 ++#define REG_CRC_OFDM 0x0f14 ++#define REG_FA_OFDM 0x0f48 ++#define REG_CCA_CCK 0x0fcc ++ + #define REG_ANAPARSW_MAC_0 0x1010 + #define BIT_CF_L_V2 GENMASK(29, 28) + +@@ -710,6 +870,10 @@ + + #define REG_IGN_GNTBT4 0x4160 + ++#define REG_USB_MOD 0xf008 ++#define REG_USB3_RXITV 0xf050 ++#define REG_USB_HRPWM 0xfe58 ++ + #define RF_MODE 0x00 + #define RF_MODOPT 0x01 + #define RF_WLINT 0x01 +@@ -717,7 +881,13 @@ + #define RF_DTXLOK 0x08 + #define RF_CFGCH 0x18 + #define BIT_BAND GENMASK(18, 16) ++#define RF18_BAND_MASK (BIT(16) | BIT(9) | BIT(8)) ++#define RF18_CHANNEL_MASK (MASKBYTE0) ++#define RF18_RFSI_MASK (BIT(18) | BIT(17)) + #define RF_RCK 0x1d ++#define RF_MODE_TABLE_ADDR 0x30 ++#define RF_MODE_TABLE_DATA0 0x31 ++#define RF_MODE_TABLE_DATA1 0x32 + #define RF_LUTWA 0x33 + #define RF_LUTWD1 0x3e + #define RF_LUTWD0 0x3f +@@ -726,10 +896,14 @@ + #define RF_T_METER 0x42 + #define RF_BSPAD 0x54 + #define RF_GAINTX 0x56 ++#define RF_TXMOD 0x58 + #define RF_TXATANK 0x64 ++#define RF_TXA_PREPAD 0x65 + #define RF_TRXIQ 0x66 + #define RF_RXIQGEN 0x8d ++#define RF_RXBB2 0x8f + #define RF_SYN_PFD 0xb0 ++#define RF_LCK 0xb4 + #define RF_XTALX2 0xb8 + #define RF_SYN_CTRL 0xbb + #define RF_MALSEL 0xbe +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.h b/drivers/net/wireless/realtek/rtw88/rtw8821c.h +index 10172f4d74bf..954e93c8020d 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8821c.h ++++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.h +@@ -215,19 +215,10 @@ extern const struct rtw_chip_info rtw8821c_hw_spec; + #define BIT_FEN_EN BIT(26) + #define REG_INIRTS_RATE_SEL 0x0480 + #define REG_HTSTFWT 0x800 +-#define REG_RXPSEL 0x808 +-#define BIT_RX_PSEL_RST (BIT(28) | BIT(29)) +-#define REG_TXPSEL 0x80c + #define REG_RXCCAMSK 0x814 +-#define REG_CCASEL 0x82c +-#define REG_PDMFTH 0x830 +-#define REG_CCA2ND 0x838 + #define REG_L1WT 0x83c + #define REG_L1PKWT 0x840 + #define REG_MRC 0x850 +-#define REG_CLKTRK 0x860 +-#define REG_ADCCLK 0x8ac +-#define REG_ADC160 0x8c4 + #define REG_ADC40 0x8c8 + #define REG_CHFIR 0x8f0 + #define REG_CDDTXP 0x93c +@@ -235,14 +226,11 @@ extern const struct rtw_chip_info rtw8821c_hw_spec; + #define REG_ACBB0 0x948 + #define REG_ACBBRXFIR 0x94c + #define REG_ACGG2TBL 0x958 +-#define REG_FAS 0x9a4 +-#define REG_RXSB 0xa00 + #define REG_ADCINI 0xa04 + #define REG_PWRTH 0xa08 + #define REG_CCA_FLTR 0xa20 + #define REG_TXSF2 0xa24 + #define REG_TXSF6 0xa28 +-#define REG_FA_CCK 0xa5c + #define REG_RXDESC 0xa2c + #define REG_ENTXCCK 0xa80 + #define BTG_LNA 0xfc84 +@@ -253,12 +241,8 @@ extern const struct rtw_chip_info rtw8821c_hw_spec; + #define REG_PWRTH2 0xaa8 + #define REG_CSRATIO 0xaaa + #define REG_TXFILTER 0xaac +-#define REG_CNTRST 0xb58 + #define REG_AGCTR_A 0xc08 +-#define REG_TXSCALE_A 0xc1c + #define REG_TXDFIR 0xc20 +-#define REG_RXIGI_A 0xc50 +-#define REG_TXAGCIDX 0xc94 + #define REG_TRSW 0xca0 + #define REG_RFESEL0 0xcb0 + #define REG_RFESEL8 0xcb4 +@@ -270,14 +254,6 @@ extern const struct rtw_chip_info rtw8821c_hw_spec; + #define B_WLA_SWITCH BIT(23) + #define REG_RFEINV 0xcbc + #define REG_AGCTR_B 0xe08 +-#define REG_RXIGI_B 0xe50 +-#define REG_CRC_CCK 0xf04 +-#define REG_CRC_OFDM 0xf14 +-#define REG_CRC_HT 0xf10 +-#define REG_CRC_VHT 0xf0c +-#define REG_CCA_OFDM 0xf08 +-#define REG_FA_OFDM 0xf48 +-#define REG_CCA_CCK 0xfcc + #define REG_DMEM_CTRL 0x1080 + #define BIT_WL_RST BIT(16) + #define REG_ANTWT 0x1904 +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.h b/drivers/net/wireless/realtek/rtw88/rtw8822b.h +index e815bc97c218..9fca9ba67c90 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8822b.h ++++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.h +@@ -152,21 +152,12 @@ _rtw_write32s_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data) + #define RTW8822B_EDCCA_MAX 0x7f + #define RTW8822B_EDCCA_SRC_DEF 1 + #define REG_HTSTFWT 0x800 +-#define REG_RXPSEL 0x808 +-#define BIT_RX_PSEL_RST (BIT(28) | BIT(29)) +-#define REG_TXPSEL 0x80c + #define REG_RXCCAMSK 0x814 +-#define REG_CCASEL 0x82c +-#define REG_PDMFTH 0x830 +-#define REG_CCA2ND 0x838 + #define REG_L1WT 0x83c + #define REG_L1PKWT 0x840 + #define REG_MRC 0x850 +-#define REG_CLKTRK 0x860 + #define REG_EDCCA_POW_MA 0x8a0 + #define BIT_MA_LEVEL GENMASK(1, 0) +-#define REG_ADCCLK 0x8ac +-#define REG_ADC160 0x8c4 + #define REG_ADC40 0x8c8 + #define REG_EDCCA_DECISION 0x8dc + #define BIT_EDCCA_OPTION BIT(5) +@@ -177,7 +168,6 @@ _rtw_write32s_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data) + #define REG_ACBB0 0x948 + #define REG_ACBBRXFIR 0x94c + #define REG_ACGG2TBL 0x958 +-#define REG_RXSB 0xa00 + #define REG_ADCINI 0xa04 + #define REG_TXSF2 0xa24 + #define REG_TXSF6 0xa28 +@@ -185,14 +175,12 @@ _rtw_write32s_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data) + #define REG_ENTXCCK 0xa80 + #define REG_AGCTR_A 0xc08 + #define REG_TXDFIR 0xc20 +-#define REG_RXIGI_A 0xc50 + #define REG_TRSW 0xca0 + #define REG_RFESEL0 0xcb0 + #define REG_RFESEL8 0xcb4 + #define REG_RFECTL 0xcb8 + #define REG_RFEINV 0xcbc + #define REG_AGCTR_B 0xe08 +-#define REG_RXIGI_B 0xe50 + #define REG_ANTWT 0x1904 + #define REG_IQKFAILMSK 0x1bf0 + +-- +2.39.5 + diff --git a/packages/linux/patches/rtlwifi/6.13/0004-wifi-rtw88-Dump-the-HW-features-only-for-some-chips.patch b/packages/linux/patches/rtlwifi/6.13/0004-wifi-rtw88-Dump-the-HW-features-only-for-some-chips.patch new file mode 100644 index 0000000000..2b1fdb2cd9 --- /dev/null +++ b/packages/linux/patches/rtlwifi/6.13/0004-wifi-rtw88-Dump-the-HW-features-only-for-some-chips.patch @@ -0,0 +1,110 @@ +From 5f2999c9758d313579bc67cf8851c80b725df7ab Mon Sep 17 00:00:00 2001 +From: Bitterblue Smith +Date: Wed, 23 Oct 2024 17:02:05 +0300 +Subject: [PATCH 04/24] wifi: rtw88: Dump the HW features only for some chips + +RTL8821AU and RTL8812AU don't support this. They hit the "failed to read +hw feature report" error. + +Signed-off-by: Bitterblue Smith +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/8becd851-8760-4480-8e8c-c4869ce72507@gmail.com +--- + drivers/net/wireless/realtek/rtw88/main.c | 3 +++ + drivers/net/wireless/realtek/rtw88/main.h | 1 + + drivers/net/wireless/realtek/rtw88/rtw8703b.c | 1 + + drivers/net/wireless/realtek/rtw88/rtw8723d.c | 1 + + drivers/net/wireless/realtek/rtw88/rtw8821c.c | 1 + + drivers/net/wireless/realtek/rtw88/rtw8822b.c | 1 + + drivers/net/wireless/realtek/rtw88/rtw8822c.c | 1 + + 7 files changed, 9 insertions(+) + +diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c +index a808af2f085e..c314b2fc06ee 100644 +--- a/drivers/net/wireless/realtek/rtw88/main.c ++++ b/drivers/net/wireless/realtek/rtw88/main.c +@@ -1907,6 +1907,9 @@ static int rtw_dump_hw_feature(struct rtw_dev *rtwdev) + u8 bw; + int i; + ++ if (!rtwdev->chip->hw_feature_report) ++ return 0; ++ + id = rtw_read8(rtwdev, REG_C2HEVT); + if (id != C2H_HW_FEATURE_REPORT) { + rtw_err(rtwdev, "failed to read hw feature report\n"); +diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h +index 46935524783e..95b5acf975c6 100644 +--- a/drivers/net/wireless/realtek/rtw88/main.h ++++ b/drivers/net/wireless/realtek/rtw88/main.h +@@ -1200,6 +1200,7 @@ struct rtw_chip_info { + const struct rtw_fwcd_segs *fwcd_segs; + + u8 usb_tx_agg_desc_num; ++ bool hw_feature_report; + + u8 default_1ss_tx_path; + +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8703b.c b/drivers/net/wireless/realtek/rtw88/rtw8703b.c +index fe09c23b51b5..c4793e10d9dc 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8703b.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8703b.c +@@ -1960,6 +1960,7 @@ const struct rtw_chip_info rtw8703b_hw_spec = { + .max_power_index = 0x3f, + .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, + .usb_tx_agg_desc_num = 1, /* Not sure if this chip has USB interface */ ++ .hw_feature_report = true, + + .path_div_supported = false, + .ht_supported = true, +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c +index 86a5e2497641..bf87c92087da 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c +@@ -2131,6 +2131,7 @@ const struct rtw_chip_info rtw8723d_hw_spec = { + .page_size = TX_PAGE_SIZE, + .dig_min = 0x20, + .usb_tx_agg_desc_num = 1, ++ .hw_feature_report = true, + .ht_supported = true, + .vht_supported = false, + .lps_deep_mode_supported = 0, +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.c b/drivers/net/wireless/realtek/rtw88/rtw8821c.c +index 66c79956e8e5..44ef2e246724 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8821c.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.c +@@ -1968,6 +1968,7 @@ const struct rtw_chip_info rtw8821c_hw_spec = { + .page_size = TX_PAGE_SIZE, + .dig_min = 0x1c, + .usb_tx_agg_desc_num = 3, ++ .hw_feature_report = true, + .ht_supported = true, + .vht_supported = true, + .lps_deep_mode_supported = BIT(LPS_DEEP_MODE_LCLK), +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c +index 8e1393ca3301..3b25536a253e 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c +@@ -2511,6 +2511,7 @@ const struct rtw_chip_info rtw8822b_hw_spec = { + .page_size = TX_PAGE_SIZE, + .dig_min = 0x1c, + .usb_tx_agg_desc_num = 3, ++ .hw_feature_report = true, + .ht_supported = true, + .vht_supported = true, + .lps_deep_mode_supported = BIT(LPS_DEEP_MODE_LCLK), +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c +index 11dc14db822b..936d4bf82c8f 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c +@@ -5330,6 +5330,7 @@ const struct rtw_chip_info rtw8822c_hw_spec = { + .page_size = TX_PAGE_SIZE, + .dig_min = 0x20, + .usb_tx_agg_desc_num = 3, ++ .hw_feature_report = true, + .default_1ss_tx_path = BB_PATH_A, + .path_div_supported = true, + .ht_supported = true, +-- +2.39.5 + diff --git a/packages/linux/patches/rtlwifi/6.13/0005-wifi-rtw88-Allow-different-C2H-RA-report-sizes.patch b/packages/linux/patches/rtlwifi/6.13/0005-wifi-rtw88-Allow-different-C2H-RA-report-sizes.patch new file mode 100644 index 0000000000..30fbbab142 --- /dev/null +++ b/packages/linux/patches/rtlwifi/6.13/0005-wifi-rtw88-Allow-different-C2H-RA-report-sizes.patch @@ -0,0 +1,194 @@ +From 918d5d5a9a90d3c6e0f8920cec6818bd9d70eabf Mon Sep 17 00:00:00 2001 +From: Bitterblue Smith +Date: Wed, 23 Oct 2024 17:06:14 +0300 +Subject: [PATCH 05/24] wifi: rtw88: Allow different C2H RA report sizes + +The RTL8821AU and RTL8812AU have smaller RA report size, only 4 bytes. +Avoid the "invalid ra report c2h length" error. + +Also, use a struct and u8_get_bits() to access the RA report C2H. + +Signed-off-by: Bitterblue Smith +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/c3e73c3a-fb2f-4013-9f06-d5274211e282@gmail.com +--- + drivers/net/wireless/realtek/rtw88/fw.c | 21 +++++++++++++------ + drivers/net/wireless/realtek/rtw88/fw.h | 17 +++++++++++---- + drivers/net/wireless/realtek/rtw88/main.h | 1 + + drivers/net/wireless/realtek/rtw88/rtw8703b.c | 1 + + drivers/net/wireless/realtek/rtw88/rtw8723d.c | 1 + + drivers/net/wireless/realtek/rtw88/rtw8821c.c | 1 + + drivers/net/wireless/realtek/rtw88/rtw8822b.c | 1 + + drivers/net/wireless/realtek/rtw88/rtw8822c.c | 1 + + 8 files changed, 34 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c +index 813c12148819..168e19187ba7 100644 +--- a/drivers/net/wireless/realtek/rtw88/fw.c ++++ b/drivers/net/wireless/realtek/rtw88/fw.c +@@ -139,25 +139,30 @@ static u16 get_max_amsdu_len(u32 bit_rate) + struct rtw_fw_iter_ra_data { + struct rtw_dev *rtwdev; + u8 *payload; ++ u8 length; + }; + + static void rtw_fw_ra_report_iter(void *data, struct ieee80211_sta *sta) + { + struct rtw_fw_iter_ra_data *ra_data = data; ++ struct rtw_c2h_ra_rpt *ra_rpt = (struct rtw_c2h_ra_rpt *)ra_data->payload; + struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv; + u8 mac_id, rate, sgi, bw; + u8 mcs, nss; + u32 bit_rate; + +- mac_id = GET_RA_REPORT_MACID(ra_data->payload); ++ mac_id = ra_rpt->mac_id; + if (si->mac_id != mac_id) + return; + + si->ra_report.txrate.flags = 0; + +- rate = GET_RA_REPORT_RATE(ra_data->payload); +- sgi = GET_RA_REPORT_SGI(ra_data->payload); +- bw = GET_RA_REPORT_BW(ra_data->payload); ++ rate = u8_get_bits(ra_rpt->rate_sgi, RTW_C2H_RA_RPT_RATE); ++ sgi = u8_get_bits(ra_rpt->rate_sgi, RTW_C2H_RA_RPT_SGI); ++ if (ra_data->length >= offsetofend(typeof(*ra_rpt), bw)) ++ bw = ra_rpt->bw; ++ else ++ bw = si->bw_mode; + + if (rate < DESC_RATEMCS0) { + si->ra_report.txrate.legacy = rtw_desc_to_bitrate(rate); +@@ -197,14 +202,18 @@ static void rtw_fw_ra_report_iter(void *data, struct ieee80211_sta *sta) + static void rtw_fw_ra_report_handle(struct rtw_dev *rtwdev, u8 *payload, + u8 length) + { ++ struct rtw_c2h_ra_rpt *ra_rpt = (struct rtw_c2h_ra_rpt *)payload; + struct rtw_fw_iter_ra_data ra_data; + +- if (WARN(length < 7, "invalid ra report c2h length\n")) ++ if (WARN(length < rtwdev->chip->c2h_ra_report_size, ++ "invalid ra report c2h length %d\n", length)) + return; + +- rtwdev->dm_info.tx_rate = GET_RA_REPORT_RATE(payload); ++ rtwdev->dm_info.tx_rate = u8_get_bits(ra_rpt->rate_sgi, ++ RTW_C2H_RA_RPT_RATE); + ra_data.rtwdev = rtwdev; + ra_data.payload = payload; ++ ra_data.length = length; + rtw_iterate_stas_atomic(rtwdev, rtw_fw_ra_report_iter, &ra_data); + } + +diff --git a/drivers/net/wireless/realtek/rtw88/fw.h b/drivers/net/wireless/realtek/rtw88/fw.h +index e999c24e4634..404de1b0c407 100644 +--- a/drivers/net/wireless/realtek/rtw88/fw.h ++++ b/drivers/net/wireless/realtek/rtw88/fw.h +@@ -85,6 +85,19 @@ struct rtw_c2h_adaptivity { + u8 option; + } __packed; + ++struct rtw_c2h_ra_rpt { ++ u8 rate_sgi; ++ u8 mac_id; ++ u8 byte2; ++ u8 status; ++ u8 byte4; ++ u8 ra_ratio; ++ u8 bw; ++} __packed; ++ ++#define RTW_C2H_RA_RPT_RATE GENMASK(6, 0) ++#define RTW_C2H_RA_RPT_SGI BIT(7) ++ + struct rtw_h2c_register { + u32 w0; + u32 w1; +@@ -364,10 +377,6 @@ struct rtw_fw_hdr_legacy { + #define GET_CHAN_SWITCH_CENTRAL_CH(c2h_payload) (c2h_payload[2]) + #define GET_CHAN_SWITCH_ID(c2h_payload) (c2h_payload[3]) + #define GET_CHAN_SWITCH_STATUS(c2h_payload) (c2h_payload[4]) +-#define GET_RA_REPORT_RATE(c2h_payload) (c2h_payload[0] & 0x7f) +-#define GET_RA_REPORT_SGI(c2h_payload) ((c2h_payload[0] & 0x80) >> 7) +-#define GET_RA_REPORT_BW(c2h_payload) (c2h_payload[6]) +-#define GET_RA_REPORT_MACID(c2h_payload) (c2h_payload[1]) + + #define GET_BCN_FILTER_NOTIFY_TYPE(c2h_payload) (c2h_payload[1] & 0xf) + #define GET_BCN_FILTER_NOTIFY_EVENT(c2h_payload) (c2h_payload[1] & 0x10) +diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h +index 95b5acf975c6..9f474dbed965 100644 +--- a/drivers/net/wireless/realtek/rtw88/main.h ++++ b/drivers/net/wireless/realtek/rtw88/main.h +@@ -1201,6 +1201,7 @@ struct rtw_chip_info { + + u8 usb_tx_agg_desc_num; + bool hw_feature_report; ++ u8 c2h_ra_report_size; + + u8 default_1ss_tx_path; + +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8703b.c b/drivers/net/wireless/realtek/rtw88/rtw8703b.c +index c4793e10d9dc..e541443adb15 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8703b.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8703b.c +@@ -1961,6 +1961,7 @@ const struct rtw_chip_info rtw8703b_hw_spec = { + .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, + .usb_tx_agg_desc_num = 1, /* Not sure if this chip has USB interface */ + .hw_feature_report = true, ++ .c2h_ra_report_size = 7, + + .path_div_supported = false, + .ht_supported = true, +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c +index bf87c92087da..6a9115775faf 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c +@@ -2132,6 +2132,7 @@ const struct rtw_chip_info rtw8723d_hw_spec = { + .dig_min = 0x20, + .usb_tx_agg_desc_num = 1, + .hw_feature_report = true, ++ .c2h_ra_report_size = 7, + .ht_supported = true, + .vht_supported = false, + .lps_deep_mode_supported = 0, +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.c b/drivers/net/wireless/realtek/rtw88/rtw8821c.c +index 44ef2e246724..6cb7e9aaa437 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8821c.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.c +@@ -1969,6 +1969,7 @@ const struct rtw_chip_info rtw8821c_hw_spec = { + .dig_min = 0x1c, + .usb_tx_agg_desc_num = 3, + .hw_feature_report = true, ++ .c2h_ra_report_size = 7, + .ht_supported = true, + .vht_supported = true, + .lps_deep_mode_supported = BIT(LPS_DEEP_MODE_LCLK), +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c +index 3b25536a253e..ca8813fdf9fb 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c +@@ -2512,6 +2512,7 @@ const struct rtw_chip_info rtw8822b_hw_spec = { + .dig_min = 0x1c, + .usb_tx_agg_desc_num = 3, + .hw_feature_report = true, ++ .c2h_ra_report_size = 7, + .ht_supported = true, + .vht_supported = true, + .lps_deep_mode_supported = BIT(LPS_DEEP_MODE_LCLK), +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c +index 936d4bf82c8f..ca98da8e4000 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c +@@ -5331,6 +5331,7 @@ const struct rtw_chip_info rtw8822c_hw_spec = { + .dig_min = 0x20, + .usb_tx_agg_desc_num = 3, + .hw_feature_report = true, ++ .c2h_ra_report_size = 7, + .default_1ss_tx_path = BB_PATH_A, + .path_div_supported = true, + .ht_supported = true, +-- +2.39.5 + diff --git a/packages/linux/patches/rtlwifi/6.13/0006-wifi-rtw88-Extend-the-init-table-parsing-for-RTL8812.patch b/packages/linux/patches/rtlwifi/6.13/0006-wifi-rtw88-Extend-the-init-table-parsing-for-RTL8812.patch new file mode 100644 index 0000000000..c4dab736f2 --- /dev/null +++ b/packages/linux/patches/rtlwifi/6.13/0006-wifi-rtw88-Extend-the-init-table-parsing-for-RTL8812.patch @@ -0,0 +1,173 @@ +From 699321b4de81b1c6e0e8973f763f4d8ef9be583d Mon Sep 17 00:00:00 2001 +From: Bitterblue Smith +Date: Wed, 23 Oct 2024 17:08:24 +0300 +Subject: [PATCH 06/24] wifi: rtw88: Extend the init table parsing for + RTL8812AU + +The chips supported so far only use the first condition, and so the +parsing code ignores the second condition. RTL8812AU's init tables use +the second condition also. Make the parsing code check it. + +Signed-off-by: Bitterblue Smith +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/1bee6b74-6eab-44a3-9f40-794ca006c72d@gmail.com +--- + drivers/net/wireless/realtek/rtw88/main.h | 15 ++++++ + drivers/net/wireless/realtek/rtw88/phy.c | 62 ++++++++++++++++++++--- + 2 files changed, 69 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h +index 9f474dbed965..9dd8c459b014 100644 +--- a/drivers/net/wireless/realtek/rtw88/main.h ++++ b/drivers/net/wireless/realtek/rtw88/main.h +@@ -1835,6 +1835,20 @@ struct rtw_phy_cond { + #define BRANCH_ENDIF 3 + }; + ++struct rtw_phy_cond2 { ++#ifdef __LITTLE_ENDIAN ++ u8 type_glna; ++ u8 type_gpa; ++ u8 type_alna; ++ u8 type_apa; ++#else ++ u8 type_apa; ++ u8 type_alna; ++ u8 type_gpa; ++ u8 type_glna; ++#endif ++}; ++ + struct rtw_fifo_conf { + /* tx fifo information */ + u16 rsvd_boundary; +@@ -1916,6 +1930,7 @@ struct rtw_hal { + u8 oem_id; + u8 pkg_type; + struct rtw_phy_cond phy_cond; ++ struct rtw_phy_cond2 phy_cond2; + bool rfe_btg; + + u8 ps_mode; +diff --git a/drivers/net/wireless/realtek/rtw88/phy.c b/drivers/net/wireless/realtek/rtw88/phy.c +index d57a2aabd89b..739c619460ca 100644 +--- a/drivers/net/wireless/realtek/rtw88/phy.c ++++ b/drivers/net/wireless/realtek/rtw88/phy.c +@@ -18,7 +18,10 @@ struct phy_cfg_pair { + }; + + union phy_table_tile { +- struct rtw_phy_cond cond; ++ struct { ++ struct rtw_phy_cond cond; ++ struct rtw_phy_cond2 cond2; ++ } __packed; + struct phy_cfg_pair cfg; + }; + +@@ -1041,7 +1044,8 @@ void rtw_phy_setup_phy_cond(struct rtw_dev *rtwdev, u32 pkg) + { + struct rtw_hal *hal = &rtwdev->hal; + struct rtw_efuse *efuse = &rtwdev->efuse; +- struct rtw_phy_cond cond = {0}; ++ struct rtw_phy_cond cond = {}; ++ struct rtw_phy_cond2 cond2 = {}; + + cond.cut = hal->cut_version ? hal->cut_version : 15; + cond.pkg = pkg ? pkg : 15; +@@ -1061,15 +1065,34 @@ void rtw_phy_setup_phy_cond(struct rtw_dev *rtwdev, u32 pkg) + break; + } + ++ if (rtwdev->chip->id == RTW_CHIP_TYPE_8812A || ++ rtwdev->chip->id == RTW_CHIP_TYPE_8821A) { ++ cond.rfe = 0; ++ cond.rfe |= efuse->ext_lna_2g; ++ cond.rfe |= efuse->ext_pa_2g << 1; ++ cond.rfe |= efuse->ext_lna_5g << 2; ++ cond.rfe |= efuse->ext_pa_5g << 3; ++ cond.rfe |= efuse->btcoex << 4; ++ ++ cond2.type_alna = efuse->alna_type; ++ cond2.type_glna = efuse->glna_type; ++ cond2.type_apa = efuse->apa_type; ++ cond2.type_gpa = efuse->gpa_type; ++ } ++ + hal->phy_cond = cond; ++ hal->phy_cond2 = cond2; + +- rtw_dbg(rtwdev, RTW_DBG_PHY, "phy cond=0x%08x\n", *((u32 *)&hal->phy_cond)); ++ rtw_dbg(rtwdev, RTW_DBG_PHY, "phy cond=0x%08x cond2=0x%08x\n", ++ *((u32 *)&hal->phy_cond), *((u32 *)&hal->phy_cond2)); + } + +-static bool check_positive(struct rtw_dev *rtwdev, struct rtw_phy_cond cond) ++static bool check_positive(struct rtw_dev *rtwdev, struct rtw_phy_cond cond, ++ struct rtw_phy_cond2 cond2) + { + struct rtw_hal *hal = &rtwdev->hal; + struct rtw_phy_cond drv_cond = hal->phy_cond; ++ struct rtw_phy_cond2 drv_cond2 = hal->phy_cond2; + + if (cond.cut && cond.cut != drv_cond.cut) + return false; +@@ -1080,8 +1103,29 @@ static bool check_positive(struct rtw_dev *rtwdev, struct rtw_phy_cond cond) + if (cond.intf && cond.intf != drv_cond.intf) + return false; + +- if (cond.rfe != drv_cond.rfe) +- return false; ++ if (rtwdev->chip->id == RTW_CHIP_TYPE_8812A || ++ rtwdev->chip->id == RTW_CHIP_TYPE_8821A) { ++ if (!(cond.rfe & 0x0f)) ++ return true; ++ ++ if ((cond.rfe & drv_cond.rfe) != cond.rfe) ++ return false; ++ ++ if ((cond.rfe & BIT(0)) && cond2.type_glna != drv_cond2.type_glna) ++ return false; ++ ++ if ((cond.rfe & BIT(1)) && cond2.type_gpa != drv_cond2.type_gpa) ++ return false; ++ ++ if ((cond.rfe & BIT(2)) && cond2.type_alna != drv_cond2.type_alna) ++ return false; ++ ++ if ((cond.rfe & BIT(3)) && cond2.type_apa != drv_cond2.type_apa) ++ return false; ++ } else { ++ if (cond.rfe != drv_cond.rfe) ++ return false; ++ } + + return true; + } +@@ -1090,7 +1134,8 @@ void rtw_parse_tbl_phy_cond(struct rtw_dev *rtwdev, const struct rtw_table *tbl) + { + const union phy_table_tile *p = tbl->data; + const union phy_table_tile *end = p + tbl->size / 2; +- struct rtw_phy_cond pos_cond = {0}; ++ struct rtw_phy_cond pos_cond = {}; ++ struct rtw_phy_cond2 pos_cond2 = {}; + bool is_matched = true, is_skipped = false; + + BUILD_BUG_ON(sizeof(union phy_table_tile) != sizeof(struct phy_cfg_pair)); +@@ -1109,11 +1154,12 @@ void rtw_parse_tbl_phy_cond(struct rtw_dev *rtwdev, const struct rtw_table *tbl) + case BRANCH_ELIF: + default: + pos_cond = p->cond; ++ pos_cond2 = p->cond2; + break; + } + } else if (p->cond.neg) { + if (!is_skipped) { +- if (check_positive(rtwdev, pos_cond)) { ++ if (check_positive(rtwdev, pos_cond, pos_cond2)) { + is_matched = true; + is_skipped = true; + } else { +-- +2.39.5 + diff --git a/packages/linux/patches/rtlwifi/6.13/0007-wifi-rtw88-Allow-rtw_chip_info.ltecoex_addr-to-be-NU.patch b/packages/linux/patches/rtlwifi/6.13/0007-wifi-rtw88-Allow-rtw_chip_info.ltecoex_addr-to-be-NU.patch new file mode 100644 index 0000000000..3d6035d8b6 --- /dev/null +++ b/packages/linux/patches/rtlwifi/6.13/0007-wifi-rtw88-Allow-rtw_chip_info.ltecoex_addr-to-be-NU.patch @@ -0,0 +1,64 @@ +From 17e658bc7d856587cbd960c176a4a5d2e53b838b Mon Sep 17 00:00:00 2001 +From: Bitterblue Smith +Date: Wed, 23 Oct 2024 17:09:04 +0300 +Subject: [PATCH 07/24] wifi: rtw88: Allow rtw_chip_info.ltecoex_addr to be + NULL + +RTL8821A doesn't have this. Trying to use it results in error messages, +so don't try if ltecoex_addr is NULL. + +Signed-off-by: Bitterblue Smith +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/d1004817-1760-41d1-9136-3d799757c444@gmail.com +--- + drivers/net/wireless/realtek/rtw88/coex.c | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw88/coex.c b/drivers/net/wireless/realtek/rtw88/coex.c +index c476e65c4d71..901984ec026e 100644 +--- a/drivers/net/wireless/realtek/rtw88/coex.c ++++ b/drivers/net/wireless/realtek/rtw88/coex.c +@@ -950,12 +950,18 @@ static void rtw_coex_coex_ctrl_owner(struct rtw_dev *rtwdev, bool wifi_control) + + static void rtw_coex_set_gnt_bt(struct rtw_dev *rtwdev, u8 state) + { ++ if (!rtwdev->chip->ltecoex_addr) ++ return; ++ + rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0xc000, state); + rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0x0c00, state); + } + + static void rtw_coex_set_gnt_wl(struct rtw_dev *rtwdev, u8 state) + { ++ if (!rtwdev->chip->ltecoex_addr) ++ return; ++ + rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0x3000, state); + rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0x0300, state); + } +@@ -3904,7 +3910,7 @@ void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m) + u8 sys_lte; + u16 score_board_WB, score_board_BW; + u32 wl_reg_6c0, wl_reg_6c4, wl_reg_6c8, wl_reg_778, wl_reg_6cc; +- u32 lte_coex, bt_coex; ++ u32 lte_coex = 0, bt_coex = 0; + int i; + + score_board_BW = rtw_coex_read_scbd(rtwdev); +@@ -3916,8 +3922,10 @@ void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m) + wl_reg_778 = rtw_read8(rtwdev, REG_BT_STAT_CTRL); + + sys_lte = rtw_read8(rtwdev, 0x73); +- lte_coex = rtw_coex_read_indirect_reg(rtwdev, 0x38); +- bt_coex = rtw_coex_read_indirect_reg(rtwdev, 0x54); ++ if (rtwdev->chip->ltecoex_addr) { ++ lte_coex = rtw_coex_read_indirect_reg(rtwdev, 0x38); ++ bt_coex = rtw_coex_read_indirect_reg(rtwdev, 0x54); ++ } + + if (!coex_stat->wl_under_ips && + (!coex_stat->wl_under_lps || coex_stat->wl_force_lps_ctrl) && +-- +2.39.5 + diff --git a/packages/linux/patches/rtlwifi/6.13/0008-wifi-rtw88-Let-each-driver-control-the-power-on-off-.patch b/packages/linux/patches/rtlwifi/6.13/0008-wifi-rtw88-Let-each-driver-control-the-power-on-off-.patch new file mode 100644 index 0000000000..536970ba1e --- /dev/null +++ b/packages/linux/patches/rtlwifi/6.13/0008-wifi-rtw88-Let-each-driver-control-the-power-on-off-.patch @@ -0,0 +1,298 @@ +From fc1fcada274a5c5d73178ce30982f75771773d44 Mon Sep 17 00:00:00 2001 +From: Bitterblue Smith +Date: Wed, 23 Oct 2024 17:09:47 +0300 +Subject: [PATCH 08/24] wifi: rtw88: Let each driver control the power on/off + process + +RTL8821AU and RTL8812AU have to do some things differently, so let +them have full control. + +The other chips use the same functions as before. + +Signed-off-by: Bitterblue Smith +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/98ab839f-9100-44ae-9551-9af743a4aa3a@gmail.com +--- + drivers/net/wireless/realtek/rtw88/coex.c | 3 +++ + drivers/net/wireless/realtek/rtw88/mac.c | 11 +++++++---- + drivers/net/wireless/realtek/rtw88/mac.h | 3 +++ + drivers/net/wireless/realtek/rtw88/main.c | 13 ++++++++----- + drivers/net/wireless/realtek/rtw88/main.h | 5 +++++ + drivers/net/wireless/realtek/rtw88/rtw8703b.c | 2 ++ + drivers/net/wireless/realtek/rtw88/rtw8723d.c | 2 ++ + drivers/net/wireless/realtek/rtw88/rtw8821c.c | 2 ++ + drivers/net/wireless/realtek/rtw88/rtw8822b.c | 2 ++ + drivers/net/wireless/realtek/rtw88/rtw8822c.c | 2 ++ + 10 files changed, 36 insertions(+), 9 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw88/coex.c b/drivers/net/wireless/realtek/rtw88/coex.c +index 901984ec026e..3bd7f55f4b18 100644 +--- a/drivers/net/wireless/realtek/rtw88/coex.c ++++ b/drivers/net/wireless/realtek/rtw88/coex.c +@@ -2753,16 +2753,19 @@ void rtw_coex_power_on_setting(struct rtw_dev *rtwdev) + rtw_write8(rtwdev, 0xff1a, 0x0); + rtw_coex_set_gnt_debug(rtwdev); + } ++EXPORT_SYMBOL(rtw_coex_power_on_setting); + + void rtw_coex_power_off_setting(struct rtw_dev *rtwdev) + { + rtw_write16(rtwdev, REG_WIFI_BT_INFO, BIT_BT_INT_EN); + } ++EXPORT_SYMBOL(rtw_coex_power_off_setting); + + void rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only) + { + __rtw_coex_init_hw_config(rtwdev, wifi_only); + } ++EXPORT_SYMBOL(rtw_coex_init_hw_config); + + void rtw_coex_ips_notify(struct rtw_dev *rtwdev, u8 type) + { +diff --git a/drivers/net/wireless/realtek/rtw88/mac.c b/drivers/net/wireless/realtek/rtw88/mac.c +index 5aa45592c2ac..b5a1caf13997 100644 +--- a/drivers/net/wireless/realtek/rtw88/mac.c ++++ b/drivers/net/wireless/realtek/rtw88/mac.c +@@ -227,8 +227,8 @@ static int rtw_sub_pwr_seq_parser(struct rtw_dev *rtwdev, u8 intf_mask, + return 0; + } + +-static int rtw_pwr_seq_parser(struct rtw_dev *rtwdev, +- const struct rtw_pwr_seq_cmd * const *cmd_seq) ++int rtw_pwr_seq_parser(struct rtw_dev *rtwdev, ++ const struct rtw_pwr_seq_cmd * const *cmd_seq) + { + u8 cut_mask; + u8 intf_mask; +@@ -267,6 +267,7 @@ static int rtw_pwr_seq_parser(struct rtw_dev *rtwdev, + + return 0; + } ++EXPORT_SYMBOL(rtw_pwr_seq_parser); + + static int rtw_mac_power_switch(struct rtw_dev *rtwdev, bool pwr_on) + { +@@ -999,6 +1000,7 @@ int rtw_download_firmware(struct rtw_dev *rtwdev, struct rtw_fw_state *fw) + + return 0; + } ++EXPORT_SYMBOL(rtw_download_firmware); + + static u32 get_priority_queues(struct rtw_dev *rtwdev, u32 queues) + { +@@ -1132,7 +1134,7 @@ static int txdma_queue_mapping(struct rtw_dev *rtwdev) + return 0; + } + +-static int set_trx_fifo_info(struct rtw_dev *rtwdev) ++int rtw_set_trx_fifo_info(struct rtw_dev *rtwdev) + { + const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_fifo_conf *fifo = &rtwdev->fifo; +@@ -1184,6 +1186,7 @@ static int set_trx_fifo_info(struct rtw_dev *rtwdev) + + return 0; + } ++EXPORT_SYMBOL(rtw_set_trx_fifo_info); + + static int __priority_queue_cfg(struct rtw_dev *rtwdev, + const struct rtw_page_table *pg_tbl, +@@ -1261,7 +1264,7 @@ static int priority_queue_cfg(struct rtw_dev *rtwdev) + u16 pubq_num; + int ret; + +- ret = set_trx_fifo_info(rtwdev); ++ ret = rtw_set_trx_fifo_info(rtwdev); + if (ret) + return ret; + +diff --git a/drivers/net/wireless/realtek/rtw88/mac.h b/drivers/net/wireless/realtek/rtw88/mac.h +index 737c6d5d8da7..e92b1483728d 100644 +--- a/drivers/net/wireless/realtek/rtw88/mac.h ++++ b/drivers/net/wireless/realtek/rtw88/mac.h +@@ -30,6 +30,8 @@ + + void rtw_set_channel_mac(struct rtw_dev *rtwdev, u8 channel, u8 bw, + u8 primary_ch_idx); ++int rtw_pwr_seq_parser(struct rtw_dev *rtwdev, ++ const struct rtw_pwr_seq_cmd * const *cmd_seq); + int rtw_mac_power_on(struct rtw_dev *rtwdev); + void rtw_mac_power_off(struct rtw_dev *rtwdev); + void rtw_write_firmware_page(struct rtw_dev *rtwdev, u32 page, +@@ -37,6 +39,7 @@ void rtw_write_firmware_page(struct rtw_dev *rtwdev, u32 page, + int rtw_download_firmware(struct rtw_dev *rtwdev, struct rtw_fw_state *fw); + int rtw_mac_init(struct rtw_dev *rtwdev); + void rtw_mac_flush_queues(struct rtw_dev *rtwdev, u32 queues, bool drop); ++int rtw_set_trx_fifo_info(struct rtw_dev *rtwdev); + int rtw_ddma_to_fw_fifo(struct rtw_dev *rtwdev, u32 ocp_src, u32 size); + + static inline void rtw_mac_flush_all_queues(struct rtw_dev *rtwdev, bool drop) +diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c +index c314b2fc06ee..0b86a0a939c3 100644 +--- a/drivers/net/wireless/realtek/rtw88/main.c ++++ b/drivers/net/wireless/realtek/rtw88/main.c +@@ -1309,7 +1309,7 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si, + rtw_fw_send_ra_info(rtwdev, si, reset_ra_mask); + } + +-static int rtw_wait_firmware_completion(struct rtw_dev *rtwdev) ++int rtw_wait_firmware_completion(struct rtw_dev *rtwdev) + { + const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_fw_state *fw; +@@ -1329,6 +1329,7 @@ static int rtw_wait_firmware_completion(struct rtw_dev *rtwdev) + + return ret; + } ++EXPORT_SYMBOL(rtw_wait_firmware_completion); + + static enum rtw_lps_deep_mode rtw_update_lps_deep_mode(struct rtw_dev *rtwdev, + struct rtw_fw_state *fw) +@@ -1350,7 +1351,7 @@ static enum rtw_lps_deep_mode rtw_update_lps_deep_mode(struct rtw_dev *rtwdev, + return LPS_DEEP_MODE_NONE; + } + +-static int rtw_power_on(struct rtw_dev *rtwdev) ++int rtw_power_on(struct rtw_dev *rtwdev) + { + const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_fw_state *fw = &rtwdev->fw; +@@ -1413,6 +1414,7 @@ static int rtw_power_on(struct rtw_dev *rtwdev) + err: + return ret; + } ++EXPORT_SYMBOL(rtw_power_on); + + void rtw_core_fw_scan_notify(struct rtw_dev *rtwdev, bool start) + { +@@ -1485,7 +1487,7 @@ int rtw_core_start(struct rtw_dev *rtwdev) + { + int ret; + +- ret = rtw_power_on(rtwdev); ++ ret = rtwdev->chip->ops->power_on(rtwdev); + if (ret) + return ret; + +@@ -1505,12 +1507,13 @@ int rtw_core_start(struct rtw_dev *rtwdev) + return 0; + } + +-static void rtw_power_off(struct rtw_dev *rtwdev) ++void rtw_power_off(struct rtw_dev *rtwdev) + { + rtw_hci_stop(rtwdev); + rtw_coex_power_off_setting(rtwdev); + rtw_mac_power_off(rtwdev); + } ++EXPORT_SYMBOL(rtw_power_off); + + void rtw_core_stop(struct rtw_dev *rtwdev) + { +@@ -1535,7 +1538,7 @@ void rtw_core_stop(struct rtw_dev *rtwdev) + + mutex_lock(&rtwdev->mutex); + +- rtw_power_off(rtwdev); ++ rtwdev->chip->ops->power_off(rtwdev); + } + + static void rtw_init_ht_cap(struct rtw_dev *rtwdev, +diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h +index 9dd8c459b014..bf48ec42ffb9 100644 +--- a/drivers/net/wireless/realtek/rtw88/main.h ++++ b/drivers/net/wireless/realtek/rtw88/main.h +@@ -843,6 +843,8 @@ struct rtw_regd { + }; + + struct rtw_chip_ops { ++ int (*power_on)(struct rtw_dev *rtwdev); ++ void (*power_off)(struct rtw_dev *rtwdev); + int (*mac_init)(struct rtw_dev *rtwdev); + int (*dump_fw_crash)(struct rtw_dev *rtwdev); + void (*shutdown)(struct rtw_dev *rtwdev); +@@ -2209,6 +2211,7 @@ void rtw_core_scan_start(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif, + void rtw_core_scan_complete(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, + bool hw_scan); + int rtw_core_start(struct rtw_dev *rtwdev); ++void rtw_power_off(struct rtw_dev *rtwdev); + void rtw_core_stop(struct rtw_dev *rtwdev); + int rtw_chip_info_setup(struct rtw_dev *rtwdev); + int rtw_core_init(struct rtw_dev *rtwdev); +@@ -2223,6 +2226,8 @@ int rtw_sta_add(struct rtw_dev *rtwdev, struct ieee80211_sta *sta, + void rtw_sta_remove(struct rtw_dev *rtwdev, struct ieee80211_sta *sta, + bool fw_exist); + void rtw_fw_recovery(struct rtw_dev *rtwdev); ++int rtw_wait_firmware_completion(struct rtw_dev *rtwdev); ++int rtw_power_on(struct rtw_dev *rtwdev); + void rtw_core_fw_scan_notify(struct rtw_dev *rtwdev, bool start); + int rtw_dump_fw(struct rtw_dev *rtwdev, const u32 ocp_src, u32 size, + u32 fwcd_item); +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8703b.c b/drivers/net/wireless/realtek/rtw88/rtw8703b.c +index e541443adb15..f72e5042920c 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8703b.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8703b.c +@@ -1888,6 +1888,8 @@ static const struct coex_tdma_para tdma_sant_8703b[] = { + }; + + static const struct rtw_chip_ops rtw8703b_ops = { ++ .power_on = rtw_power_on, ++ .power_off = rtw_power_off, + .mac_init = rtw8723x_mac_init, + .dump_fw_crash = NULL, + .shutdown = NULL, +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c +index 6a9115775faf..f6a08b06f853 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c +@@ -1390,6 +1390,8 @@ static void rtw8723d_pwr_track(struct rtw_dev *rtwdev) + } + + static const struct rtw_chip_ops rtw8723d_ops = { ++ .power_on = rtw_power_on, ++ .power_off = rtw_power_off, + .phy_set_param = rtw8723d_phy_set_param, + .read_efuse = rtw8723x_read_efuse, + .query_phy_status = query_phy_status, +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.c b/drivers/net/wireless/realtek/rtw88/rtw8821c.c +index 6cb7e9aaa437..e17d0193ca6f 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8821c.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.c +@@ -1643,6 +1643,8 @@ static const struct rtw_prioq_addrs prioq_addrs_8821c = { + }; + + static const struct rtw_chip_ops rtw8821c_ops = { ++ .power_on = rtw_power_on, ++ .power_off = rtw_power_off, + .phy_set_param = rtw8821c_phy_set_param, + .read_efuse = rtw8821c_read_efuse, + .query_phy_status = query_phy_status, +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c +index ca8813fdf9fb..9bd269319795 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c +@@ -2134,6 +2134,8 @@ static const struct rtw_prioq_addrs prioq_addrs_8822b = { + }; + + static const struct rtw_chip_ops rtw8822b_ops = { ++ .power_on = rtw_power_on, ++ .power_off = rtw_power_off, + .phy_set_param = rtw8822b_phy_set_param, + .read_efuse = rtw8822b_read_efuse, + .query_phy_status = query_phy_status, +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c +index ca98da8e4000..36733c88102a 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c +@@ -4948,6 +4948,8 @@ static const struct rtw_prioq_addrs prioq_addrs_8822c = { + }; + + static const struct rtw_chip_ops rtw8822c_ops = { ++ .power_on = rtw_power_on, ++ .power_off = rtw_power_off, + .phy_set_param = rtw8822c_phy_set_param, + .read_efuse = rtw8822c_read_efuse, + .query_phy_status = query_phy_status, +-- +2.39.5 + diff --git a/packages/linux/patches/rtlwifi/6.13/0009-wifi-rtw88-Enable-data-rate-fallback-for-older-chips.patch b/packages/linux/patches/rtlwifi/6.13/0009-wifi-rtw88-Enable-data-rate-fallback-for-older-chips.patch new file mode 100644 index 0000000000..c27a1dcd10 --- /dev/null +++ b/packages/linux/patches/rtlwifi/6.13/0009-wifi-rtw88-Enable-data-rate-fallback-for-older-chips.patch @@ -0,0 +1,221 @@ +From 0ced33188bdc330299c80f4d1afd67278d9c2ded Mon Sep 17 00:00:00 2001 +From: Bitterblue Smith +Date: Wed, 23 Oct 2024 17:10:32 +0300 +Subject: [PATCH 09/24] wifi: rtw88: Enable data rate fallback for older chips + +RTL8811AU fails to perform the 4-way handshake when the AP is too far +because it transmits the EAPOL frames at MCS9 and when that doesn't +work it retries 48 times with the same rate, to no avail. + +Retrying 48 times with the same rate seems pointless. Set the +appropriate field in the TX descriptor to allow it to use lower rates +when retrying. + +Set it for RTL8723D and RTL8703B because they interpret this field the +same way as RTL8811A. + +The newer RTL8822C, RTL8822B, RTL8821C seem to interpret this field in +the TX descriptor differently, so leave it alone for those chips. + +Tested with RTL8811AU and RTL8723DU. + +Signed-off-by: Bitterblue Smith +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/2b3e3e6f-541b-4a3b-8ca3-65b267e6a95a@gmail.com +--- + drivers/net/wireless/realtek/rtw88/fw.c | 2 +- + drivers/net/wireless/realtek/rtw88/main.h | 1 + + drivers/net/wireless/realtek/rtw88/pci.c | 2 +- + drivers/net/wireless/realtek/rtw88/rtw8703b.c | 1 + + drivers/net/wireless/realtek/rtw88/rtw8723d.c | 1 + + drivers/net/wireless/realtek/rtw88/rtw8821c.c | 1 + + drivers/net/wireless/realtek/rtw88/rtw8822b.c | 1 + + drivers/net/wireless/realtek/rtw88/rtw8822c.c | 1 + + drivers/net/wireless/realtek/rtw88/sdio.c | 2 +- + drivers/net/wireless/realtek/rtw88/tx.c | 6 +++++- + drivers/net/wireless/realtek/rtw88/tx.h | 4 +++- + drivers/net/wireless/realtek/rtw88/usb.c | 4 ++-- + 12 files changed, 19 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c +index 168e19187ba7..19de5ba555a9 100644 +--- a/drivers/net/wireless/realtek/rtw88/fw.c ++++ b/drivers/net/wireless/realtek/rtw88/fw.c +@@ -1290,7 +1290,7 @@ static void rtw_fill_rsvd_page_desc(struct rtw_dev *rtwdev, struct sk_buff *skb, + rtw_tx_rsvd_page_pkt_info_update(rtwdev, &pkt_info, skb, type); + pkt_desc = skb_push(skb, chip->tx_pkt_desc_sz); + memset(pkt_desc, 0, chip->tx_pkt_desc_sz); +- rtw_tx_fill_tx_desc(&pkt_info, skb); ++ rtw_tx_fill_tx_desc(rtwdev, &pkt_info, skb); + } + + static inline u8 rtw_len_to_page(unsigned int len, u8 page_size) +diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h +index bf48ec42ffb9..a57680167144 100644 +--- a/drivers/net/wireless/realtek/rtw88/main.h ++++ b/drivers/net/wireless/realtek/rtw88/main.h +@@ -1204,6 +1204,7 @@ struct rtw_chip_info { + u8 usb_tx_agg_desc_num; + bool hw_feature_report; + u8 c2h_ra_report_size; ++ bool old_datarate_fb_limit; + + u8 default_1ss_tx_path; + +diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c +index 729b270d5851..08226b61b653 100644 +--- a/drivers/net/wireless/realtek/rtw88/pci.c ++++ b/drivers/net/wireless/realtek/rtw88/pci.c +@@ -825,7 +825,7 @@ static int rtw_pci_tx_write_data(struct rtw_dev *rtwdev, + pkt_desc = skb_push(skb, chip->tx_pkt_desc_sz); + memset(pkt_desc, 0, tx_pkt_desc_sz); + pkt_info->qsel = rtw_pci_get_tx_qsel(skb, queue); +- rtw_tx_fill_tx_desc(pkt_info, skb); ++ rtw_tx_fill_tx_desc(rtwdev, pkt_info, skb); + dma = dma_map_single(&rtwpci->pdev->dev, skb->data, skb->len, + DMA_TO_DEVICE); + if (dma_mapping_error(&rtwpci->pdev->dev, dma)) +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8703b.c b/drivers/net/wireless/realtek/rtw88/rtw8703b.c +index f72e5042920c..bff6e8b93650 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8703b.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8703b.c +@@ -1964,6 +1964,7 @@ const struct rtw_chip_info rtw8703b_hw_spec = { + .usb_tx_agg_desc_num = 1, /* Not sure if this chip has USB interface */ + .hw_feature_report = true, + .c2h_ra_report_size = 7, ++ .old_datarate_fb_limit = true, + + .path_div_supported = false, + .ht_supported = true, +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c +index f6a08b06f853..a0bf37a58632 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c +@@ -2135,6 +2135,7 @@ const struct rtw_chip_info rtw8723d_hw_spec = { + .usb_tx_agg_desc_num = 1, + .hw_feature_report = true, + .c2h_ra_report_size = 7, ++ .old_datarate_fb_limit = true, + .ht_supported = true, + .vht_supported = false, + .lps_deep_mode_supported = 0, +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.c b/drivers/net/wireless/realtek/rtw88/rtw8821c.c +index e17d0193ca6f..39dc8244f744 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8821c.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.c +@@ -1972,6 +1972,7 @@ const struct rtw_chip_info rtw8821c_hw_spec = { + .usb_tx_agg_desc_num = 3, + .hw_feature_report = true, + .c2h_ra_report_size = 7, ++ .old_datarate_fb_limit = false, + .ht_supported = true, + .vht_supported = true, + .lps_deep_mode_supported = BIT(LPS_DEEP_MODE_LCLK), +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c +index 9bd269319795..ccabbe85be6f 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c +@@ -2515,6 +2515,7 @@ const struct rtw_chip_info rtw8822b_hw_spec = { + .usb_tx_agg_desc_num = 3, + .hw_feature_report = true, + .c2h_ra_report_size = 7, ++ .old_datarate_fb_limit = false, + .ht_supported = true, + .vht_supported = true, + .lps_deep_mode_supported = BIT(LPS_DEEP_MODE_LCLK), +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c +index 36733c88102a..3fa72af40aa4 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c +@@ -5334,6 +5334,7 @@ const struct rtw_chip_info rtw8822c_hw_spec = { + .usb_tx_agg_desc_num = 3, + .hw_feature_report = true, + .c2h_ra_report_size = 7, ++ .old_datarate_fb_limit = false, + .default_1ss_tx_path = BB_PATH_A, + .path_div_supported = true, + .ht_supported = true, +diff --git a/drivers/net/wireless/realtek/rtw88/sdio.c b/drivers/net/wireless/realtek/rtw88/sdio.c +index fe6f14290bdd..df8b62fe4548 100644 +--- a/drivers/net/wireless/realtek/rtw88/sdio.c ++++ b/drivers/net/wireless/realtek/rtw88/sdio.c +@@ -862,7 +862,7 @@ static void rtw_sdio_tx_skb_prepare(struct rtw_dev *rtwdev, + + pkt_info->qsel = rtw_sdio_get_tx_qsel(rtwdev, skb, queue); + +- rtw_tx_fill_tx_desc(pkt_info, skb); ++ rtw_tx_fill_tx_desc(rtwdev, pkt_info, skb); + rtw_tx_fill_txdesc_checksum(rtwdev, pkt_info, pkt_desc); + } + +diff --git a/drivers/net/wireless/realtek/rtw88/tx.c b/drivers/net/wireless/realtek/rtw88/tx.c +index dae7ca148865..6ed470dd6f22 100644 +--- a/drivers/net/wireless/realtek/rtw88/tx.c ++++ b/drivers/net/wireless/realtek/rtw88/tx.c +@@ -32,7 +32,8 @@ void rtw_tx_stats(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, + } + } + +-void rtw_tx_fill_tx_desc(struct rtw_tx_pkt_info *pkt_info, struct sk_buff *skb) ++void rtw_tx_fill_tx_desc(struct rtw_dev *rtwdev, ++ struct rtw_tx_pkt_info *pkt_info, struct sk_buff *skb) + { + struct rtw_tx_desc *tx_desc = (struct rtw_tx_desc *)skb->data; + bool more_data = false; +@@ -67,6 +68,9 @@ void rtw_tx_fill_tx_desc(struct rtw_tx_pkt_info *pkt_info, struct sk_buff *skb) + + tx_desc->w4 = le32_encode_bits(pkt_info->rate, RTW_TX_DESC_W4_DATARATE); + ++ if (rtwdev->chip->old_datarate_fb_limit) ++ tx_desc->w4 |= le32_encode_bits(0x1f, RTW_TX_DESC_W4_DATARATE_FB_LIMIT); ++ + tx_desc->w5 = le32_encode_bits(pkt_info->short_gi, RTW_TX_DESC_W5_DATA_SHORT) | + le32_encode_bits(pkt_info->bw, RTW_TX_DESC_W5_DATA_BW) | + le32_encode_bits(pkt_info->ldpc, RTW_TX_DESC_W5_DATA_LDPC) | +diff --git a/drivers/net/wireless/realtek/rtw88/tx.h b/drivers/net/wireless/realtek/rtw88/tx.h +index 3d544fd7f60f..d34cdeca16f1 100644 +--- a/drivers/net/wireless/realtek/rtw88/tx.h ++++ b/drivers/net/wireless/realtek/rtw88/tx.h +@@ -44,6 +44,7 @@ struct rtw_tx_desc { + #define RTW_TX_DESC_W3_NAVUSEHDR BIT(15) + #define RTW_TX_DESC_W3_MAX_AGG_NUM GENMASK(21, 17) + #define RTW_TX_DESC_W4_DATARATE GENMASK(6, 0) ++#define RTW_TX_DESC_W4_DATARATE_FB_LIMIT GENMASK(12, 8) + #define RTW_TX_DESC_W4_RTSRATE GENMASK(28, 24) + #define RTW_TX_DESC_W5_DATA_SHORT BIT(4) + #define RTW_TX_DESC_W5_DATA_BW GENMASK(6, 5) +@@ -94,7 +95,8 @@ void rtw_tx_pkt_info_update(struct rtw_dev *rtwdev, + struct rtw_tx_pkt_info *pkt_info, + struct ieee80211_sta *sta, + struct sk_buff *skb); +-void rtw_tx_fill_tx_desc(struct rtw_tx_pkt_info *pkt_info, struct sk_buff *skb); ++void rtw_tx_fill_tx_desc(struct rtw_dev *rtwdev, ++ struct rtw_tx_pkt_info *pkt_info, struct sk_buff *skb); + void rtw_tx_report_enqueue(struct rtw_dev *rtwdev, struct sk_buff *skb, u8 sn); + void rtw_tx_report_handle(struct rtw_dev *rtwdev, struct sk_buff *skb, int src); + void rtw_tx_rsvd_page_pkt_info_update(struct rtw_dev *rtwdev, +diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c +index 83acb96b44ed..a0ce3a306221 100644 +--- a/drivers/net/wireless/realtek/rtw88/usb.c ++++ b/drivers/net/wireless/realtek/rtw88/usb.c +@@ -512,7 +512,7 @@ static int rtw_usb_write_data(struct rtw_dev *rtwdev, + skb_put_data(skb, buf, size); + skb_push(skb, chip->tx_pkt_desc_sz); + memset(skb->data, 0, chip->tx_pkt_desc_sz); +- rtw_tx_fill_tx_desc(pkt_info, skb); ++ rtw_tx_fill_tx_desc(rtwdev, pkt_info, skb); + rtw_tx_fill_txdesc_checksum(rtwdev, pkt_info, skb->data); + + ret = rtw_usb_write_port(rtwdev, qsel, skb, +@@ -579,7 +579,7 @@ static int rtw_usb_tx_write(struct rtw_dev *rtwdev, + pkt_desc = skb_push(skb, chip->tx_pkt_desc_sz); + memset(pkt_desc, 0, chip->tx_pkt_desc_sz); + ep = qsel_to_ep(rtwusb, pkt_info->qsel); +- rtw_tx_fill_tx_desc(pkt_info, skb); ++ rtw_tx_fill_tx_desc(rtwdev, pkt_info, skb); + rtw_tx_fill_txdesc_checksum(rtwdev, pkt_info, skb->data); + tx_data = rtw_usb_get_tx_data(skb); + tx_data->sn = pkt_info->sn; +-- +2.39.5 + diff --git a/packages/linux/patches/rtlwifi/6.13/0010-wifi-rtw88-Make-txagc_remnant_ofdm-an-array.patch b/packages/linux/patches/rtlwifi/6.13/0010-wifi-rtw88-Make-txagc_remnant_ofdm-an-array.patch new file mode 100644 index 0000000000..3acd6a656d --- /dev/null +++ b/packages/linux/patches/rtlwifi/6.13/0010-wifi-rtw88-Make-txagc_remnant_ofdm-an-array.patch @@ -0,0 +1,96 @@ +From d5bdea3831a848fa09f4d1cf6884e507839596b0 Mon Sep 17 00:00:00 2001 +From: Bitterblue Smith +Date: Wed, 23 Oct 2024 17:10:54 +0300 +Subject: [PATCH 10/24] wifi: rtw88: Make txagc_remnant_ofdm an array + +txagc_remnant_ofdm member of struct rtw_dm_info should be different for +each RF path, so make it an array of size RTW_RF_PATH_MAX (4). + +Until now all the chips using this had only one RF path, but RTL8812AU +has two, and RTL8814AU has four. + +Signed-off-by: Bitterblue Smith +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/68571ba9-e504-4b2d-bfa1-62f468753649@gmail.com +--- + drivers/net/wireless/realtek/rtw88/main.h | 2 +- + drivers/net/wireless/realtek/rtw88/phy.c | 4 ++-- + drivers/net/wireless/realtek/rtw88/rtw8703b.c | 4 ++-- + drivers/net/wireless/realtek/rtw88/rtw8723d.c | 4 ++-- + 4 files changed, 7 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h +index a57680167144..49bf20942ade 100644 +--- a/drivers/net/wireless/realtek/rtw88/main.h ++++ b/drivers/net/wireless/realtek/rtw88/main.h +@@ -1715,7 +1715,7 @@ struct rtw_dm_info { + bool pwr_trk_init_trigger; + struct ewma_thermal avg_thermal[RTW_RF_PATH_MAX]; + s8 txagc_remnant_cck; +- s8 txagc_remnant_ofdm; ++ s8 txagc_remnant_ofdm[RTW_RF_PATH_MAX]; + u8 rx_cck_agc_report_type; + + /* backup dack results for each path and I/Q */ +diff --git a/drivers/net/wireless/realtek/rtw88/phy.c b/drivers/net/wireless/realtek/rtw88/phy.c +index 739c619460ca..215e4af64da3 100644 +--- a/drivers/net/wireless/realtek/rtw88/phy.c ++++ b/drivers/net/wireless/realtek/rtw88/phy.c +@@ -2171,8 +2171,8 @@ void rtw_get_tx_power_params(struct rtw_dev *rtwdev, u8 path, u8 rate, u8 bw, + + *limit = rtw_phy_get_tx_power_limit(rtwdev, band, bw, path, + rate, ch, regd); +- *remnant = (rate <= DESC_RATE11M ? dm_info->txagc_remnant_cck : +- dm_info->txagc_remnant_ofdm); ++ *remnant = rate <= DESC_RATE11M ? dm_info->txagc_remnant_cck : ++ dm_info->txagc_remnant_ofdm[path]; + *sar = rtw_phy_get_tx_power_sar(rtwdev, hal->sar_band, path, rate); + } + +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8703b.c b/drivers/net/wireless/realtek/rtw88/rtw8703b.c +index bff6e8b93650..1a41f1c31a06 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8703b.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8703b.c +@@ -637,7 +637,7 @@ static void rtw8703b_pwrtrack_init(struct rtw_dev *rtwdev) + dm_info->pwr_trk_init_trigger = true; + dm_info->thermal_meter_k = rtwdev->efuse.thermal_meter_k; + dm_info->txagc_remnant_cck = 0; +- dm_info->txagc_remnant_ofdm = 0; ++ dm_info->txagc_remnant_ofdm[RF_PATH_A] = 0; + } + + static void rtw8703b_phy_set_param(struct rtw_dev *rtwdev) +@@ -1589,7 +1589,7 @@ static void rtw8703b_pwrtrack_set_ofdm_pwr(struct rtw_dev *rtwdev, s8 swing_idx, + { + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + +- dm_info->txagc_remnant_ofdm = txagc_idx; ++ dm_info->txagc_remnant_ofdm[RF_PATH_A] = txagc_idx; + + /* Only path A is calibrated for rtl8703b */ + rtw8703b_set_iqk_matrix(rtwdev, swing_idx, RF_PATH_A); +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c +index a0bf37a58632..1d99bb89ef1d 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c +@@ -79,7 +79,7 @@ static void rtw8723d_pwrtrack_init(struct rtw_dev *rtwdev) + dm_info->pwr_trk_init_trigger = true; + dm_info->thermal_meter_k = rtwdev->efuse.thermal_meter_k; + dm_info->txagc_remnant_cck = 0; +- dm_info->txagc_remnant_ofdm = 0; ++ dm_info->txagc_remnant_ofdm[RF_PATH_A] = 0; + } + + static void rtw8723d_phy_set_param(struct rtw_dev *rtwdev) +@@ -1265,7 +1265,7 @@ static void rtw8723d_pwrtrack_set_ofdm_pwr(struct rtw_dev *rtwdev, s8 swing_idx, + { + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + +- dm_info->txagc_remnant_ofdm = txagc_idx; ++ dm_info->txagc_remnant_ofdm[RF_PATH_A] = txagc_idx; + + rtw8723d_set_iqk_matrix(rtwdev, swing_idx, RF_PATH_A); + rtw8723d_set_iqk_matrix(rtwdev, swing_idx, RF_PATH_B); +-- +2.39.5 + diff --git a/packages/linux/patches/rtlwifi/6.13/0011-wifi-rtw88-Support-TX-page-sizes-bigger-than-128.patch b/packages/linux/patches/rtlwifi/6.13/0011-wifi-rtw88-Support-TX-page-sizes-bigger-than-128.patch new file mode 100644 index 0000000000..aac1d58b93 --- /dev/null +++ b/packages/linux/patches/rtlwifi/6.13/0011-wifi-rtw88-Support-TX-page-sizes-bigger-than-128.patch @@ -0,0 +1,126 @@ +From c1d505e4db7c5398ea3eff3815ebe4e586948a92 Mon Sep 17 00:00:00 2001 +From: Bitterblue Smith +Date: Wed, 23 Oct 2024 17:12:06 +0300 +Subject: [PATCH 11/24] wifi: rtw88: Support TX page sizes bigger than 128 + +All the chips supported so far have a TX page size of 128 bytes. + +Change the type of the page_size member of struct rtw_chip_info from u8 +to u16 in order to support RTL8821AU (page size of 256 bytes) and +RTL8812AU (page size of 512 bytes). Also change the types of several +related variables and function parameters from u8 to u16. + +The TX page size is used, among other things, to construct the beacon, +null data, QOS null data, and PS poll templates which are uploaded to +the chip's reserved page. Each template needs to be aligned on a +multiple of the TX page size. Power saving can't work if the TX page +size is wrong. + +Signed-off-by: Bitterblue Smith +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/acdefbb1-3daf-4349-9e03-9472754d5f1e@gmail.com +--- + drivers/net/wireless/realtek/rtw88/debug.c | 2 +- + drivers/net/wireless/realtek/rtw88/fw.c | 21 +++++++++++---------- + drivers/net/wireless/realtek/rtw88/mac.c | 2 +- + drivers/net/wireless/realtek/rtw88/main.h | 2 +- + 4 files changed, 14 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw88/debug.c b/drivers/net/wireless/realtek/rtw88/debug.c +index c26a6905fd15..364ec0436d0f 100644 +--- a/drivers/net/wireless/realtek/rtw88/debug.c ++++ b/drivers/net/wireless/realtek/rtw88/debug.c +@@ -308,7 +308,7 @@ static int rtw_debugfs_get_rsvd_page(struct seq_file *m, void *v) + { + struct rtw_debugfs_priv *debugfs_priv = m->private; + struct rtw_dev *rtwdev = debugfs_priv->rtwdev; +- u8 page_size = rtwdev->chip->page_size; ++ u16 page_size = rtwdev->chip->page_size; + u32 buf_size = debugfs_priv->rsvd_page.page_num * page_size; + u32 offset = debugfs_priv->rsvd_page.page_offset * page_size; + u8 *buf; +diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c +index 19de5ba555a9..e6e9946fbf44 100644 +--- a/drivers/net/wireless/realtek/rtw88/fw.c ++++ b/drivers/net/wireless/realtek/rtw88/fw.c +@@ -1293,13 +1293,13 @@ static void rtw_fill_rsvd_page_desc(struct rtw_dev *rtwdev, struct sk_buff *skb, + rtw_tx_fill_tx_desc(rtwdev, &pkt_info, skb); + } + +-static inline u8 rtw_len_to_page(unsigned int len, u8 page_size) ++static inline u8 rtw_len_to_page(unsigned int len, u16 page_size) + { + return DIV_ROUND_UP(len, page_size); + } + +-static void rtw_rsvd_page_list_to_buf(struct rtw_dev *rtwdev, u8 page_size, +- u8 page_margin, u32 page, u8 *buf, ++static void rtw_rsvd_page_list_to_buf(struct rtw_dev *rtwdev, u16 page_size, ++ u16 page_margin, u32 page, u8 *buf, + struct rtw_rsvd_page *rsvd_pkt) + { + struct sk_buff *skb = rsvd_pkt->skb; +@@ -1601,13 +1601,13 @@ static int __rtw_build_rsvd_page_from_vifs(struct rtw_dev *rtwdev) + + static u8 *rtw_build_rsvd_page(struct rtw_dev *rtwdev, u32 *size) + { +- struct ieee80211_hw *hw = rtwdev->hw; + const struct rtw_chip_info *chip = rtwdev->chip; +- struct sk_buff *iter; ++ struct ieee80211_hw *hw = rtwdev->hw; + struct rtw_rsvd_page *rsvd_pkt; +- u32 page = 0; ++ struct sk_buff *iter; ++ u16 page_size, page_margin, tx_desc_sz; + u8 total_page = 0; +- u8 page_size, page_margin, tx_desc_sz; ++ u32 page = 0; + u8 *buf; + int ret; + +@@ -2013,12 +2013,13 @@ static int _rtw_hw_scan_update_probe_req(struct rtw_dev *rtwdev, u8 num_probes, + { + const struct rtw_chip_info *chip = rtwdev->chip; + struct sk_buff *skb, *tmp; +- u8 page_offset = 1, *buf, page_size = chip->page_size; + u16 pg_addr = rtwdev->fifo.rsvd_h2c_info_addr, loc; +- u16 buf_offset = page_size * page_offset; + u8 tx_desc_sz = chip->tx_pkt_desc_sz; +- u8 page_cnt, pages; ++ u16 page_size = chip->page_size; ++ u8 page_offset = 1, *buf; ++ u16 buf_offset = page_size * page_offset; + unsigned int pkt_len; ++ u8 page_cnt, pages; + int ret; + + if (rtw_fw_feature_ext_check(&rtwdev->fw, FW_FEATURE_EXT_OLD_PAGE_NUM)) +diff --git a/drivers/net/wireless/realtek/rtw88/mac.c b/drivers/net/wireless/realtek/rtw88/mac.c +index b5a1caf13997..65f04bad215c 100644 +--- a/drivers/net/wireless/realtek/rtw88/mac.c ++++ b/drivers/net/wireless/realtek/rtw88/mac.c +@@ -1143,7 +1143,7 @@ int rtw_set_trx_fifo_info(struct rtw_dev *rtwdev) + + /* config rsvd page num */ + fifo->rsvd_drv_pg_num = chip->rsvd_drv_pg_num; +- fifo->txff_pg_num = chip->txff_size >> 7; ++ fifo->txff_pg_num = chip->txff_size / chip->page_size; + if (rtw_chip_wcpu_11n(rtwdev)) + fifo->rsvd_pg_num = fifo->rsvd_drv_pg_num; + else +diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h +index 49bf20942ade..4d5910afaf0f 100644 +--- a/drivers/net/wireless/realtek/rtw88/main.h ++++ b/drivers/net/wireless/realtek/rtw88/main.h +@@ -1187,7 +1187,7 @@ struct rtw_chip_info { + u32 fw_rxff_size; + u16 rsvd_drv_pg_num; + u8 band; +- u8 page_size; ++ u16 page_size; + u8 csi_buf_pg_num; + u8 dig_max; + u8 dig_min; +-- +2.39.5 + diff --git a/packages/linux/patches/rtlwifi/6.13/0012-wifi-rtw88-Move-pwr_track_tbl-to-struct-rtw_rfe_def.patch b/packages/linux/patches/rtlwifi/6.13/0012-wifi-rtw88-Move-pwr_track_tbl-to-struct-rtw_rfe_def.patch new file mode 100644 index 0000000000..8f3e8eec51 --- /dev/null +++ b/packages/linux/patches/rtlwifi/6.13/0012-wifi-rtw88-Move-pwr_track_tbl-to-struct-rtw_rfe_def.patch @@ -0,0 +1,316 @@ +From 3db94ce8fc4cd44f8211f3334c65f61320c722ad Mon Sep 17 00:00:00 2001 +From: Bitterblue Smith +Date: Wed, 23 Oct 2024 17:12:39 +0300 +Subject: [PATCH 12/24] wifi: rtw88: Move pwr_track_tbl to struct rtw_rfe_def + +RTL8812AU uses one set of TX power tracking tables for RFE 3, and +another set for everything else. + +Move pwr_track_tbl from struct rtw_chip_info to struct rtw_rfe_def in +order to load the right set of tables for each RFE (RF front end) type. + +Signed-off-by: Bitterblue Smith +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/904d0ab1-c046-40cd-a3a3-d4fdcf663c9d@gmail.com +--- + drivers/net/wireless/realtek/rtw88/main.h | 8 ++++--- + drivers/net/wireless/realtek/rtw88/phy.c | 3 ++- + drivers/net/wireless/realtek/rtw88/rtw8703b.c | 12 +++++----- + drivers/net/wireless/realtek/rtw88/rtw8723d.c | 12 +++++----- + drivers/net/wireless/realtek/rtw88/rtw8723x.c | 3 ++- + drivers/net/wireless/realtek/rtw88/rtw8821c.c | 17 +++++++------- + drivers/net/wireless/realtek/rtw88/rtw8822b.c | 15 ++++++------ + drivers/net/wireless/realtek/rtw88/rtw8822c.c | 23 +++++++++---------- + 8 files changed, 47 insertions(+), 46 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h +index 4d5910afaf0f..e01964db8f67 100644 +--- a/drivers/net/wireless/realtek/rtw88/main.h ++++ b/drivers/net/wireless/realtek/rtw88/main.h +@@ -1099,17 +1099,20 @@ enum rtw_rfe_fem { + struct rtw_rfe_def { + const struct rtw_table *phy_pg_tbl; + const struct rtw_table *txpwr_lmt_tbl; ++ const struct rtw_pwr_track_tbl *pwr_track_tbl; + const struct rtw_table *agc_btg_tbl; + }; + +-#define RTW_DEF_RFE(chip, bb_pg, pwrlmt) { \ ++#define RTW_DEF_RFE(chip, bb_pg, pwrlmt, track) { \ + .phy_pg_tbl = &rtw ## chip ## _bb_pg_type ## bb_pg ## _tbl, \ + .txpwr_lmt_tbl = &rtw ## chip ## _txpwr_lmt_type ## pwrlmt ## _tbl, \ ++ .pwr_track_tbl = &rtw ## chip ## _pwr_track_type ## track ## _tbl, \ + } + +-#define RTW_DEF_RFE_EXT(chip, bb_pg, pwrlmt, btg) { \ ++#define RTW_DEF_RFE_EXT(chip, bb_pg, pwrlmt, track, btg) { \ + .phy_pg_tbl = &rtw ## chip ## _bb_pg_type ## bb_pg ## _tbl, \ + .txpwr_lmt_tbl = &rtw ## chip ## _txpwr_lmt_type ## pwrlmt ## _tbl, \ ++ .pwr_track_tbl = &rtw ## chip ## _pwr_track_type ## track ## _tbl, \ + .agc_btg_tbl = &rtw ## chip ## _agc_btg_type ## btg ## _tbl, \ + } + +@@ -1243,7 +1246,6 @@ struct rtw_chip_info { + u16 dpd_ratemask; + u8 iqk_threshold; + u8 lck_threshold; +- const struct rtw_pwr_track_tbl *pwr_track_tbl; + + u8 bfer_su_max_num; + u8 bfer_mu_max_num; +diff --git a/drivers/net/wireless/realtek/rtw88/phy.c b/drivers/net/wireless/realtek/rtw88/phy.c +index 215e4af64da3..b52108f2b147 100644 +--- a/drivers/net/wireless/realtek/rtw88/phy.c ++++ b/drivers/net/wireless/realtek/rtw88/phy.c +@@ -2386,7 +2386,8 @@ void rtw_phy_init_tx_power(struct rtw_dev *rtwdev) + void rtw_phy_config_swing_table(struct rtw_dev *rtwdev, + struct rtw_swing_table *swing_table) + { +- const struct rtw_pwr_track_tbl *tbl = rtwdev->chip->pwr_track_tbl; ++ const struct rtw_rfe_def *rfe_def = rtw_get_rfe_def(rtwdev); ++ const struct rtw_pwr_track_tbl *tbl = rfe_def->pwr_track_tbl; + u8 channel = rtwdev->hal.current_channel; + + if (IS_CH_2G_BAND(channel)) { +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8703b.c b/drivers/net/wireless/realtek/rtw88/rtw8703b.c +index 1a41f1c31a06..1d232adbdd7e 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8703b.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8703b.c +@@ -493,11 +493,6 @@ static const struct rtw_pwr_seq_cmd * const card_disable_flow_8703b[] = { + NULL + }; + +-static const struct rtw_rfe_def rtw8703b_rfe_defs[] = { +- [0] = { .phy_pg_tbl = &rtw8703b_bb_pg_tbl, +- .txpwr_lmt_tbl = &rtw8703b_txpwr_lmt_tbl,}, +-}; +- + static const struct rtw_page_table page_table_8703b[] = { + {12, 2, 2, 0, 1}, + {12, 2, 2, 0, 1}, +@@ -1818,6 +1813,12 @@ static const struct rtw_pwr_track_tbl rtw8703b_rtw_pwr_track_tbl = { + .pwrtrk_xtal_p = rtw8703b_pwrtrk_xtal_p, + }; + ++static const struct rtw_rfe_def rtw8703b_rfe_defs[] = { ++ [0] = { .phy_pg_tbl = &rtw8703b_bb_pg_tbl, ++ .txpwr_lmt_tbl = &rtw8703b_txpwr_lmt_tbl, ++ .pwr_track_tbl = &rtw8703b_rtw_pwr_track_tbl, }, ++}; ++ + /* Shared-Antenna Coex Table */ + static const struct coex_table_para table_sant_8703b[] = { + {0xffffffff, 0xffffffff}, /* case-0 */ +@@ -1997,7 +1998,6 @@ const struct rtw_chip_info rtw8703b_hw_spec = { + .rfe_defs_size = ARRAY_SIZE(rtw8703b_rfe_defs), + + .iqk_threshold = 8, +- .pwr_track_tbl = &rtw8703b_rtw_pwr_track_tbl, + + /* WOWLAN firmware exists, but not implemented yet */ + .wow_fw_name = "rtw88/rtw8703b_wow_fw.bin", +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c +index 1d99bb89ef1d..eeca31bf71f1 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c +@@ -2020,11 +2020,6 @@ static const struct rtw_intf_phy_para_table phy_para_table_8723d = { + .n_gen1_para = ARRAY_SIZE(pcie_gen1_param_8723d), + }; + +-static const struct rtw_rfe_def rtw8723d_rfe_defs[] = { +- [0] = { .phy_pg_tbl = &rtw8723d_bb_pg_tbl, +- .txpwr_lmt_tbl = &rtw8723d_txpwr_lmt_tbl,}, +-}; +- + static const u8 rtw8723d_pwrtrk_2gb_n[] = { + 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 4, 4, 5, 5, 5, + 6, 6, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 10, 10 +@@ -2088,6 +2083,12 @@ static const struct rtw_pwr_track_tbl rtw8723d_rtw_pwr_track_tbl = { + .pwrtrk_xtal_n = rtw8723d_pwrtrk_xtal_n, + }; + ++static const struct rtw_rfe_def rtw8723d_rfe_defs[] = { ++ [0] = { .phy_pg_tbl = &rtw8723d_bb_pg_tbl, ++ .txpwr_lmt_tbl = &rtw8723d_txpwr_lmt_tbl, ++ .pwr_track_tbl = &rtw8723d_rtw_pwr_track_tbl, }, ++}; ++ + static const struct rtw_reg_domain coex_info_hw_regs_8723d[] = { + {0x948, MASKDWORD, RTW_REG_DOMAIN_MAC32}, + {0x67, BIT(7), RTW_REG_DOMAIN_MAC8}, +@@ -2159,7 +2160,6 @@ const struct rtw_chip_info rtw8723d_hw_spec = { + .rfe_defs = rtw8723d_rfe_defs, + .rfe_defs_size = ARRAY_SIZE(rtw8723d_rfe_defs), + .rx_ldpc = false, +- .pwr_track_tbl = &rtw8723d_rtw_pwr_track_tbl, + .iqk_threshold = 8, + .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, + .max_scan_ie_len = IEEE80211_MAX_DATA_LEN, +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723x.c b/drivers/net/wireless/realtek/rtw88/rtw8723x.c +index 0d0b6c2cb9aa..69f73cb5b4cd 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8723x.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8723x.c +@@ -595,7 +595,8 @@ void __rtw8723x_pwrtrack_set_xtal(struct rtw_dev *rtwdev, u8 therm_path, + u8 delta) + { + struct rtw_dm_info *dm_info = &rtwdev->dm_info; +- const struct rtw_pwr_track_tbl *tbl = rtwdev->chip->pwr_track_tbl; ++ const struct rtw_rfe_def *rfe_def = rtw_get_rfe_def(rtwdev); ++ const struct rtw_pwr_track_tbl *tbl = rfe_def->pwr_track_tbl; + const s8 *pwrtrk_xtal; + s8 xtal_cap; + +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.c b/drivers/net/wireless/realtek/rtw88/rtw8821c.c +index 39dc8244f744..0270225b9c20 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8821c.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.c +@@ -1581,13 +1581,6 @@ static const struct rtw_intf_phy_para_table phy_para_table_8821c = { + .n_gen2_para = ARRAY_SIZE(pcie_gen2_param_8821c), + }; + +-static const struct rtw_rfe_def rtw8821c_rfe_defs[] = { +- [0] = RTW_DEF_RFE(8821c, 0, 0), +- [2] = RTW_DEF_RFE_EXT(8821c, 0, 0, 2), +- [4] = RTW_DEF_RFE_EXT(8821c, 0, 0, 2), +- [6] = RTW_DEF_RFE(8821c, 0, 0), +-}; +- + static const struct rtw_hw_reg rtw8821c_dig[] = { + [0] = { .addr = 0xc50, .mask = 0x7f }, + }; +@@ -1899,7 +1892,7 @@ static const u8 rtw8821c_pwrtrk_2g_cck_a_p[] = { + 5, 6, 6, 7, 7, 7, 8, 8, 9, 9, 9, 9, 9, 9 + }; + +-static const struct rtw_pwr_track_tbl rtw8821c_rtw_pwr_track_tbl = { ++static const struct rtw_pwr_track_tbl rtw8821c_pwr_track_type0_tbl = { + .pwrtrk_5gb_n[0] = rtw8821c_pwrtrk_5gb_n[0], + .pwrtrk_5gb_n[1] = rtw8821c_pwrtrk_5gb_n[1], + .pwrtrk_5gb_n[2] = rtw8821c_pwrtrk_5gb_n[2], +@@ -1922,6 +1915,13 @@ static const struct rtw_pwr_track_tbl rtw8821c_rtw_pwr_track_tbl = { + .pwrtrk_2g_ccka_p = rtw8821c_pwrtrk_2g_cck_a_p, + }; + ++static const struct rtw_rfe_def rtw8821c_rfe_defs[] = { ++ [0] = RTW_DEF_RFE(8821c, 0, 0, 0), ++ [2] = RTW_DEF_RFE_EXT(8821c, 0, 0, 0, 2), ++ [4] = RTW_DEF_RFE_EXT(8821c, 0, 0, 0, 2), ++ [6] = RTW_DEF_RFE(8821c, 0, 0, 0), ++}; ++ + static const struct rtw_reg_domain coex_info_hw_regs_8821c[] = { + {0xCB0, MASKDWORD, RTW_REG_DOMAIN_MAC32}, + {0xCB4, MASKDWORD, RTW_REG_DOMAIN_MAC32}, +@@ -1994,7 +1994,6 @@ const struct rtw_chip_info rtw8821c_hw_spec = { + .rfe_defs = rtw8821c_rfe_defs, + .rfe_defs_size = ARRAY_SIZE(rtw8821c_rfe_defs), + .rx_ldpc = false, +- .pwr_track_tbl = &rtw8821c_rtw_pwr_track_tbl, + .iqk_threshold = 8, + .bfer_su_max_num = 2, + .bfer_mu_max_num = 1, +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c +index ccabbe85be6f..6f51b613e095 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c +@@ -2074,12 +2074,6 @@ static const struct rtw_intf_phy_para_table phy_para_table_8822b = { + .n_gen2_para = ARRAY_SIZE(pcie_gen2_param_8822b), + }; + +-static const struct rtw_rfe_def rtw8822b_rfe_defs[] = { +- [2] = RTW_DEF_RFE(8822b, 2, 2), +- [3] = RTW_DEF_RFE(8822b, 3, 0), +- [5] = RTW_DEF_RFE(8822b, 5, 5), +-}; +- + static const struct rtw_hw_reg rtw8822b_dig[] = { + [0] = { .addr = 0xc50, .mask = 0x7f }, + [1] = { .addr = 0xe50, .mask = 0x7f }, +@@ -2434,7 +2428,7 @@ static const u8 rtw8822b_pwrtrk_2g_cck_a_p[RTW_PWR_TRK_TBL_SZ] = { + 10, 11, 11, 12, 12, 13, 13, 14, 14, 15 + }; + +-static const struct rtw_pwr_track_tbl rtw8822b_rtw_pwr_track_tbl = { ++static const struct rtw_pwr_track_tbl rtw8822b_pwr_track_type0_tbl = { + .pwrtrk_5gb_n[RTW_PWR_TRK_5G_1] = rtw8822b_pwrtrk_5gb_n[RTW_PWR_TRK_5G_1], + .pwrtrk_5gb_n[RTW_PWR_TRK_5G_2] = rtw8822b_pwrtrk_5gb_n[RTW_PWR_TRK_5G_2], + .pwrtrk_5gb_n[RTW_PWR_TRK_5G_3] = rtw8822b_pwrtrk_5gb_n[RTW_PWR_TRK_5G_3], +@@ -2457,6 +2451,12 @@ static const struct rtw_pwr_track_tbl rtw8822b_rtw_pwr_track_tbl = { + .pwrtrk_2g_ccka_p = rtw8822b_pwrtrk_2g_cck_a_p, + }; + ++static const struct rtw_rfe_def rtw8822b_rfe_defs[] = { ++ [2] = RTW_DEF_RFE(8822b, 2, 2, 0), ++ [3] = RTW_DEF_RFE(8822b, 3, 0, 0), ++ [5] = RTW_DEF_RFE(8822b, 5, 5, 0), ++}; ++ + static const struct rtw_reg_domain coex_info_hw_regs_8822b[] = { + {0xcb0, MASKDWORD, RTW_REG_DOMAIN_MAC32}, + {0xcb4, MASKDWORD, RTW_REG_DOMAIN_MAC32}, +@@ -2537,7 +2537,6 @@ const struct rtw_chip_info rtw8822b_hw_spec = { + .rf_tbl = {&rtw8822b_rf_a_tbl, &rtw8822b_rf_b_tbl}, + .rfe_defs = rtw8822b_rfe_defs, + .rfe_defs_size = ARRAY_SIZE(rtw8822b_rfe_defs), +- .pwr_track_tbl = &rtw8822b_rtw_pwr_track_tbl, + .iqk_threshold = 8, + .bfer_su_max_num = 2, + .bfer_mu_max_num = 1, +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c +index 3fa72af40aa4..563a9faec556 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c +@@ -4884,16 +4884,6 @@ static const struct rtw_intf_phy_para_table phy_para_table_8822c = { + .n_gen2_para = ARRAY_SIZE(pcie_gen2_param_8822c), + }; + +-static const struct rtw_rfe_def rtw8822c_rfe_defs[] = { +- [0] = RTW_DEF_RFE(8822c, 0, 0), +- [1] = RTW_DEF_RFE(8822c, 0, 0), +- [2] = RTW_DEF_RFE(8822c, 0, 0), +- [3] = RTW_DEF_RFE(8822c, 0, 0), +- [4] = RTW_DEF_RFE(8822c, 0, 0), +- [5] = RTW_DEF_RFE(8822c, 0, 5), +- [6] = RTW_DEF_RFE(8822c, 0, 0), +-}; +- + static const struct rtw_hw_reg rtw8822c_dig[] = { + [0] = { .addr = 0x1d70, .mask = 0x7f }, + [1] = { .addr = 0x1d70, .mask = 0x7f00 }, +@@ -5239,7 +5229,7 @@ static const u8 rtw8822c_pwrtrk_2g_cck_a_p[RTW_PWR_TRK_TBL_SZ] = { + 18, 18, 19, 20, 21, 22, 23, 24, 24, 25 + }; + +-static const struct rtw_pwr_track_tbl rtw8822c_rtw_pwr_track_tbl = { ++static const struct rtw_pwr_track_tbl rtw8822c_pwr_track_type0_tbl = { + .pwrtrk_5gb_n[RTW_PWR_TRK_5G_1] = rtw8822c_pwrtrk_5gb_n[RTW_PWR_TRK_5G_1], + .pwrtrk_5gb_n[RTW_PWR_TRK_5G_2] = rtw8822c_pwrtrk_5gb_n[RTW_PWR_TRK_5G_2], + .pwrtrk_5gb_n[RTW_PWR_TRK_5G_3] = rtw8822c_pwrtrk_5gb_n[RTW_PWR_TRK_5G_3], +@@ -5262,6 +5252,16 @@ static const struct rtw_pwr_track_tbl rtw8822c_rtw_pwr_track_tbl = { + .pwrtrk_2g_ccka_p = rtw8822c_pwrtrk_2g_cck_a_p, + }; + ++static const struct rtw_rfe_def rtw8822c_rfe_defs[] = { ++ [0] = RTW_DEF_RFE(8822c, 0, 0, 0), ++ [1] = RTW_DEF_RFE(8822c, 0, 0, 0), ++ [2] = RTW_DEF_RFE(8822c, 0, 0, 0), ++ [3] = RTW_DEF_RFE(8822c, 0, 0, 0), ++ [4] = RTW_DEF_RFE(8822c, 0, 0, 0), ++ [5] = RTW_DEF_RFE(8822c, 0, 5, 0), ++ [6] = RTW_DEF_RFE(8822c, 0, 0, 0), ++}; ++ + static const struct rtw_hw_reg_offset rtw8822c_edcca_th[] = { + [EDCCA_TH_L2H_IDX] = { + {.addr = 0x84c, .mask = MASKBYTE2}, .offset = 0x80 +@@ -5361,7 +5361,6 @@ const struct rtw_chip_info rtw8822c_hw_spec = { + .rfe_defs_size = ARRAY_SIZE(rtw8822c_rfe_defs), + .en_dis_dpd = true, + .dpd_ratemask = DIS_DPD_RATEALL, +- .pwr_track_tbl = &rtw8822c_rtw_pwr_track_tbl, + .iqk_threshold = 8, + .lck_threshold = 8, + .bfer_su_max_num = 2, +-- +2.39.5 + diff --git a/packages/linux/patches/rtlwifi/6.13/0013-wifi-rtw88-usb-Set-pkt_info.ls-for-the-reserved-page.patch b/packages/linux/patches/rtlwifi/6.13/0013-wifi-rtw88-usb-Set-pkt_info.ls-for-the-reserved-page.patch new file mode 100644 index 0000000000..8c3c6b0f4d --- /dev/null +++ b/packages/linux/patches/rtlwifi/6.13/0013-wifi-rtw88-usb-Set-pkt_info.ls-for-the-reserved-page.patch @@ -0,0 +1,32 @@ +From ebadcb81bd3167f9360cb86b92eee02a43a224b2 Mon Sep 17 00:00:00 2001 +From: Bitterblue Smith +Date: Wed, 23 Oct 2024 17:13:10 +0300 +Subject: [PATCH 13/24] wifi: rtw88: usb: Set pkt_info.ls for the reserved page + +"ls" meaning "last segment". Without this RTL8812AU can't upload the +reserved page in USB 2 mode. (Somehow it's fine in USB 3 mode.) + +Also tested with RTL8822CU, RTL8812BU, RTL8811CU, RTL8723DU, RTL8811AU. + +Signed-off-by: Bitterblue Smith +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/e443f5d9-4b53-4f64-985c-64313ec80bef@gmail.com +--- + drivers/net/wireless/realtek/rtw88/usb.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c +index a0ce3a306221..05025fed5b68 100644 +--- a/drivers/net/wireless/realtek/rtw88/usb.c ++++ b/drivers/net/wireless/realtek/rtw88/usb.c +@@ -532,6 +532,7 @@ static int rtw_usb_write_data_rsvd_page(struct rtw_dev *rtwdev, u8 *buf, + pkt_info.tx_pkt_size = size; + pkt_info.qsel = TX_DESC_QSEL_BEACON; + pkt_info.offset = chip->tx_pkt_desc_sz; ++ pkt_info.ls = true; + + return rtw_usb_write_data(rtwdev, &pkt_info, buf); + } +-- +2.39.5 + diff --git a/packages/linux/patches/rtlwifi/6.13/0014-wifi-rtw88-Detect-beacon-loss-with-chips-other-than-.patch b/packages/linux/patches/rtlwifi/6.13/0014-wifi-rtw88-Detect-beacon-loss-with-chips-other-than-.patch new file mode 100644 index 0000000000..69d24635c7 --- /dev/null +++ b/packages/linux/patches/rtlwifi/6.13/0014-wifi-rtw88-Detect-beacon-loss-with-chips-other-than-.patch @@ -0,0 +1,69 @@ +From 753c741b4474db92b0a4598481fca3b8120aaca9 Mon Sep 17 00:00:00 2001 +From: Bitterblue Smith +Date: Wed, 23 Oct 2024 17:13:45 +0300 +Subject: [PATCH 14/24] wifi: rtw88: Detect beacon loss with chips other than + 8822c + +The driver is supposed to avoid entering LPS (power saving) when there +is beacon loss, but only RTL8822C detects the beacon loss (because it +has beacon filtering in the firmware). + +Detect beacon loss with the other chips by checking if we received less +than half the expected number of beacons in the last 2-second interval. + +This gets rid of the occasional "failed to get tx report from firmware" +warnings with RTL8821AU. It may also avoid some disconnections. + +Signed-off-by: Bitterblue Smith +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/f52b2fcf-bf94-48bc-89bd-e55ebc3a2f2d@gmail.com +--- + drivers/net/wireless/realtek/rtw88/main.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c +index 0b86a0a939c3..876d0b126ed7 100644 +--- a/drivers/net/wireless/realtek/rtw88/main.c ++++ b/drivers/net/wireless/realtek/rtw88/main.c +@@ -202,6 +202,21 @@ static void rtw_vif_watch_dog_iter(void *data, struct ieee80211_vif *vif) + rtwvif->stats.rx_cnt = 0; + } + ++static void rtw_sw_beacon_loss_check(struct rtw_dev *rtwdev, ++ struct rtw_vif *rtwvif, int received_beacons) ++{ ++ int watchdog_delay = 2000000 / 1024; /* TU */ ++ int beacon_int, expected_beacons; ++ ++ if (rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_BCN_FILTER) || !rtwvif) ++ return; ++ ++ beacon_int = rtwvif_to_vif(rtwvif)->bss_conf.beacon_int; ++ expected_beacons = DIV_ROUND_UP(watchdog_delay, beacon_int); ++ ++ rtwdev->beacon_loss = received_beacons < expected_beacons / 2; ++} ++ + /* process TX/RX statistics periodically for hardware, + * the information helps hardware to enhance performance + */ +@@ -212,6 +227,7 @@ static void rtw_watch_dog_work(struct work_struct *work) + struct rtw_traffic_stats *stats = &rtwdev->stats; + struct rtw_watch_dog_iter_data data = {}; + bool busy_traffic = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags); ++ int received_beacons = rtwdev->dm_info.cur_pkt_count.num_bcn_pkt; + u32 tx_unicast_mbps, rx_unicast_mbps; + bool ps_active; + +@@ -270,6 +286,8 @@ static void rtw_watch_dog_work(struct work_struct *work) + */ + rtw_iterate_vifs(rtwdev, rtw_vif_watch_dog_iter, &data); + ++ rtw_sw_beacon_loss_check(rtwdev, data.rtwvif, received_beacons); ++ + /* fw supports only one station associated to enter lps, if there are + * more than two stations associated to the AP, then we can not enter + * lps, because fw does not handle the overlapped beacon interval +-- +2.39.5 + diff --git a/packages/linux/patches/rtlwifi/6.13/0015-wifi-rtw88-coex-Support-chips-without-a-scoreboard.patch b/packages/linux/patches/rtlwifi/6.13/0015-wifi-rtw88-coex-Support-chips-without-a-scoreboard.patch new file mode 100644 index 0000000000..b72e9251cf --- /dev/null +++ b/packages/linux/patches/rtlwifi/6.13/0015-wifi-rtw88-coex-Support-chips-without-a-scoreboard.patch @@ -0,0 +1,73 @@ +From e79edfcfe5de7f916607ebb09c991bc1d5c8a8e7 Mon Sep 17 00:00:00 2001 +From: Bitterblue Smith +Date: Wed, 23 Oct 2024 17:14:12 +0300 +Subject: [PATCH 15/24] wifi: rtw88: coex: Support chips without a scoreboard + +All the chips currently supported have a "scoreboard": the chip keeps +track of certain things related to bluetooth, for example, whether +bluetooth is active. The information can be read from register 0xaa. + +RTL8821AU doesn't have this. Implement bluetooth activity detection in +rtw_coex_monitor_bt_enable() based on the bluetooth TX/RX counters. + +This is mostly important for RTL8811AU, the version of RTL8821AU without +bluetooth. Without this change, the driver thinks bluetooth is active +and the wifi speeds are low. + +Signed-off-by: Bitterblue Smith +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/5058f23d-2086-42cd-82ad-eef31a348467@gmail.com +--- + drivers/net/wireless/realtek/rtw88/coex.c | 18 ++++++++++++++++++ + drivers/net/wireless/realtek/rtw88/main.h | 1 + + 2 files changed, 19 insertions(+) + +diff --git a/drivers/net/wireless/realtek/rtw88/coex.c b/drivers/net/wireless/realtek/rtw88/coex.c +index 3bd7f55f4b18..e616c5271b84 100644 +--- a/drivers/net/wireless/realtek/rtw88/coex.c ++++ b/drivers/net/wireless/realtek/rtw88/coex.c +@@ -494,11 +494,29 @@ static void rtw_coex_monitor_bt_enable(struct rtw_dev *rtwdev) + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_coex_dm *coex_dm = &coex->dm; + bool bt_disabled = false; ++ bool bt_active = true; + u16 score_board; + + if (chip->scbd_support) { + score_board = rtw_coex_read_scbd(rtwdev); + bt_disabled = !(score_board & COEX_SCBD_ONOFF); ++ } else { ++ if (coex_stat->hi_pri_tx == 0 && coex_stat->hi_pri_rx == 0 && ++ coex_stat->lo_pri_tx == 0 && coex_stat->lo_pri_rx == 0) ++ bt_active = false; ++ ++ if (coex_stat->hi_pri_tx == 0xffff && coex_stat->hi_pri_rx == 0xffff && ++ coex_stat->lo_pri_tx == 0xffff && coex_stat->lo_pri_rx == 0xffff) ++ bt_active = false; ++ ++ if (bt_active) { ++ coex_stat->bt_disable_cnt = 0; ++ bt_disabled = false; ++ } else { ++ coex_stat->bt_disable_cnt++; ++ if (coex_stat->bt_disable_cnt >= 10) ++ bt_disabled = true; ++ } + } + + if (coex_stat->bt_disabled != bt_disabled) { +diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h +index e01964db8f67..65c7acea41af 100644 +--- a/drivers/net/wireless/realtek/rtw88/main.h ++++ b/drivers/net/wireless/realtek/rtw88/main.h +@@ -1494,6 +1494,7 @@ struct rtw_coex_stat { + u8 bt_hid_slot; + u8 bt_a2dp_bitpool; + u8 bt_iqk_state; ++ u8 bt_disable_cnt; + + u16 wl_beacon_interval; + u8 wl_noisy_level; +-- +2.39.5 + diff --git a/packages/linux/patches/rtlwifi/6.13/0016-wifi-rtw88-8821a-Regularly-ask-for-BT-info-updates.patch b/packages/linux/patches/rtlwifi/6.13/0016-wifi-rtw88-8821a-Regularly-ask-for-BT-info-updates.patch new file mode 100644 index 0000000000..76097eeb13 --- /dev/null +++ b/packages/linux/patches/rtlwifi/6.13/0016-wifi-rtw88-8821a-Regularly-ask-for-BT-info-updates.patch @@ -0,0 +1,76 @@ +From 30a80c5357062ce1008ae6ed279bce2b71aac244 Mon Sep 17 00:00:00 2001 +From: Bitterblue Smith +Date: Wed, 23 Oct 2024 17:14:45 +0300 +Subject: [PATCH 16/24] wifi: rtw88: 8821a: Regularly ask for BT info updates + +The RTL8821AU firmware sends C2H_BT_INFO by itself when bluetooth +headphones are connected, but not when they are disconnected. This leads +to the coexistence code still using the A2DP algorithm long after the +headphones are disconnected, which means the wifi speeds are much lower +than they should be. Work around this by asking for updates every two +seconds if the chip is RTL8821AU. + +Signed-off-by: Bitterblue Smith +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/358acdd2-6aae-46c1-9c66-fcce4e700b96@gmail.com +--- + drivers/net/wireless/realtek/rtw88/coex.c | 2 +- + drivers/net/wireless/realtek/rtw88/coex.h | 11 +++++++++++ + drivers/net/wireless/realtek/rtw88/main.c | 1 + + 3 files changed, 13 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/realtek/rtw88/coex.c b/drivers/net/wireless/realtek/rtw88/coex.c +index e616c5271b84..64904278ddad 100644 +--- a/drivers/net/wireless/realtek/rtw88/coex.c ++++ b/drivers/net/wireless/realtek/rtw88/coex.c +@@ -446,7 +446,7 @@ static void rtw_coex_check_rfk(struct rtw_dev *rtwdev) + } + } + +-static void rtw_coex_query_bt_info(struct rtw_dev *rtwdev) ++void rtw_coex_query_bt_info(struct rtw_dev *rtwdev) + { + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; +diff --git a/drivers/net/wireless/realtek/rtw88/coex.h b/drivers/net/wireless/realtek/rtw88/coex.h +index 57cf29da9ea4..c398be8391f7 100644 +--- a/drivers/net/wireless/realtek/rtw88/coex.h ++++ b/drivers/net/wireless/realtek/rtw88/coex.h +@@ -384,6 +384,7 @@ u32 rtw_coex_read_indirect_reg(struct rtw_dev *rtwdev, u16 addr); + void rtw_coex_write_indirect_reg(struct rtw_dev *rtwdev, u16 addr, + u32 mask, u32 val); + void rtw_coex_write_scbd(struct rtw_dev *rtwdev, u16 bitpos, bool set); ++void rtw_coex_query_bt_info(struct rtw_dev *rtwdev); + + void rtw_coex_bt_relink_work(struct work_struct *work); + void rtw_coex_bt_reenable_work(struct work_struct *work); +@@ -419,4 +420,14 @@ static inline bool rtw_coex_disabled(struct rtw_dev *rtwdev) + return coex_stat->bt_disabled; + } + ++static inline void rtw_coex_active_query_bt_info(struct rtw_dev *rtwdev) ++{ ++ /* The RTL8821AU firmware doesn't send C2H_BT_INFO by itself ++ * when bluetooth headphones are disconnected, so we have to ++ * ask for it regularly. ++ */ ++ if (rtwdev->chip->id == RTW_CHIP_TYPE_8821A && rtwdev->efuse.btcoex) ++ rtw_coex_query_bt_info(rtwdev); ++} ++ + #endif +diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c +index 876d0b126ed7..a36c861a3023 100644 +--- a/drivers/net/wireless/realtek/rtw88/main.c ++++ b/drivers/net/wireless/realtek/rtw88/main.c +@@ -274,6 +274,7 @@ static void rtw_watch_dog_work(struct work_struct *work) + rtw_leave_lps(rtwdev); + rtw_coex_wl_status_check(rtwdev); + rtw_coex_query_bt_hid_list(rtwdev); ++ rtw_coex_active_query_bt_info(rtwdev); + + rtw_phy_dynamic_mechanism(rtwdev); + +-- +2.39.5 + diff --git a/packages/linux/patches/rtlwifi/6.13/0017-wifi-rtw88-8812a-Mitigate-beacon-loss.patch b/packages/linux/patches/rtlwifi/6.13/0017-wifi-rtw88-8812a-Mitigate-beacon-loss.patch new file mode 100644 index 0000000000..9918a78770 --- /dev/null +++ b/packages/linux/patches/rtlwifi/6.13/0017-wifi-rtw88-8812a-Mitigate-beacon-loss.patch @@ -0,0 +1,42 @@ +From fa93ac195068575da6bb5484bac9f95561d3f92c Mon Sep 17 00:00:00 2001 +From: Bitterblue Smith +Date: Wed, 23 Oct 2024 17:15:13 +0300 +Subject: [PATCH 17/24] wifi: rtw88: 8812a: Mitigate beacon loss + +The RTL8812AU has a reception problem, maybe only in the 5 GHz band. +Sometimes, in some positions, it stops receiving anything even though +the distance to the AP is only ~3 meters and there are no obstacles. +Moving it a few centimeters fixes it. + +Switch the initial gain to maximum coverage when there is beacon loss. +This only helps sometimes. This is similar to what the official driver +does. + +Signed-off-by: Bitterblue Smith +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/203f5043-4fe1-4f35-8b8f-d3b6f44e1fd9@gmail.com +--- + drivers/net/wireless/realtek/rtw88/phy.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/net/wireless/realtek/rtw88/phy.c b/drivers/net/wireless/realtek/rtw88/phy.c +index b52108f2b147..40c36118f579 100644 +--- a/drivers/net/wireless/realtek/rtw88/phy.c ++++ b/drivers/net/wireless/realtek/rtw88/phy.c +@@ -530,6 +530,13 @@ static void rtw_phy_dig(struct rtw_dev *rtwdev) + */ + rtw_phy_dig_recorder(dm_info, cur_igi, fa_cnt); + ++ /* Mitigate beacon loss and connectivity issues, mainly (only?) ++ * in the 5 GHz band ++ */ ++ if (rtwdev->chip->id == RTW_CHIP_TYPE_8812A && rtwdev->beacon_loss && ++ linked && dm_info->total_fa_cnt < DIG_PERF_FA_TH_EXTRA_HIGH) ++ cur_igi = DIG_CVRG_MIN; ++ + if (cur_igi != pre_igi) + rtw_phy_dig_write(rtwdev, cur_igi); + } +-- +2.39.5 + diff --git a/packages/linux/patches/rtlwifi/6.13/0018-wifi-rtw88-Add-rtw8812a_table.-c-h.patch b/packages/linux/patches/rtlwifi/6.13/0018-wifi-rtw88-Add-rtw8812a_table.-c-h.patch new file mode 100644 index 0000000000..aab1edc655 --- /dev/null +++ b/packages/linux/patches/rtlwifi/6.13/0018-wifi-rtw88-Add-rtw8812a_table.-c-h.patch @@ -0,0 +1,2871 @@ +From f04edf8daab420baf2f7453cfce74260cbf03e29 Mon Sep 17 00:00:00 2001 +From: Bitterblue Smith +Date: Wed, 30 Oct 2024 20:24:33 +0200 +Subject: [PATCH 18/24] wifi: rtw88: Add rtw8812a_table.{c,h} + +These contain various arrays for initialising RTL8812AU. Also TX power +limits. + +Signed-off-by: Bitterblue Smith +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/086f476c-e832-4867-963c-a64a63252fd6@gmail.com +--- + .../wireless/realtek/rtw88/rtw8812a_table.c | 2812 +++++++++++++++++ + .../wireless/realtek/rtw88/rtw8812a_table.h | 26 + + 2 files changed, 2838 insertions(+) + create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8812a_table.c + create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8812a_table.h + +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8812a_table.c b/drivers/net/wireless/realtek/rtw88/rtw8812a_table.c +new file mode 100644 +index 000000000000..048efbbd49ed +--- /dev/null ++++ b/drivers/net/wireless/realtek/rtw88/rtw8812a_table.c +@@ -0,0 +1,2812 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause ++/* Copyright(c) 2024 Realtek Corporation ++ */ ++ ++#include "main.h" ++#include "phy.h" ++#include "rtw8812a_table.h" ++ ++static const u32 rtw8812a_mac[] = { ++ 0x010, 0x0000000C, ++ 0x80000200, 0x00000000, 0x40000000, 0x00000000, ++ 0x011, 0x00000066, ++ 0xA0000000, 0x00000000, ++ 0x011, 0x0000005A, ++ 0xB0000000, 0x00000000, ++ 0x025, 0x0000000F, ++ 0x072, 0x00000000, ++ 0x420, 0x00000080, ++ 0x428, 0x0000000A, ++ 0x429, 0x00000010, ++ 0x430, 0x00000000, ++ 0x431, 0x00000000, ++ 0x432, 0x00000000, ++ 0x433, 0x00000001, ++ 0x434, 0x00000002, ++ 0x435, 0x00000003, ++ 0x436, 0x00000005, ++ 0x437, 0x00000007, ++ 0x438, 0x00000000, ++ 0x439, 0x00000000, ++ 0x43A, 0x00000000, ++ 0x43B, 0x00000001, ++ 0x43C, 0x00000002, ++ 0x43D, 0x00000003, ++ 0x43E, 0x00000005, ++ 0x43F, 0x00000007, ++ 0x440, 0x0000005D, ++ 0x441, 0x00000001, ++ 0x442, 0x00000000, ++ 0x444, 0x00000010, ++ 0x445, 0x00000000, ++ 0x446, 0x00000000, ++ 0x447, 0x00000000, ++ 0x448, 0x00000000, ++ 0x449, 0x000000F0, ++ 0x44A, 0x0000000F, ++ 0x44B, 0x0000003E, ++ 0x44C, 0x00000010, ++ 0x44D, 0x00000000, ++ 0x44E, 0x00000000, ++ 0x44F, 0x00000000, ++ 0x450, 0x00000000, ++ 0x451, 0x000000F0, ++ 0x452, 0x0000000F, ++ 0x453, 0x00000000, ++ 0x45B, 0x00000080, ++ 0x460, 0x00000066, ++ 0x461, 0x00000066, ++ 0x4C8, 0x000000FF, ++ 0x4C9, 0x00000008, ++ 0x4CC, 0x000000FF, ++ 0x4CD, 0x000000FF, ++ 0x4CE, 0x00000001, ++ 0x500, 0x00000026, ++ 0x501, 0x000000A2, ++ 0x502, 0x0000002F, ++ 0x503, 0x00000000, ++ 0x504, 0x00000028, ++ 0x505, 0x000000A3, ++ 0x506, 0x0000005E, ++ 0x507, 0x00000000, ++ 0x508, 0x0000002B, ++ 0x509, 0x000000A4, ++ 0x50A, 0x0000005E, ++ 0x50B, 0x00000000, ++ 0x50C, 0x0000004F, ++ 0x50D, 0x000000A4, ++ 0x50E, 0x00000000, ++ 0x50F, 0x00000000, ++ 0x512, 0x0000001C, ++ 0x514, 0x0000000A, ++ 0x516, 0x0000000A, ++ 0x525, 0x0000004F, ++ 0x550, 0x00000010, ++ 0x551, 0x00000010, ++ 0x559, 0x00000002, ++ 0x55C, 0x00000050, ++ 0x55D, 0x000000FF, ++ 0x604, 0x00000009, ++ 0x605, 0x00000030, ++ 0x607, 0x00000003, ++ 0x608, 0x0000000E, ++ 0x609, 0x0000002A, ++ 0x620, 0x000000FF, ++ 0x621, 0x000000FF, ++ 0x622, 0x000000FF, ++ 0x623, 0x000000FF, ++ 0x624, 0x000000FF, ++ 0x625, 0x000000FF, ++ 0x626, 0x000000FF, ++ 0x627, 0x000000FF, ++ 0x638, 0x00000050, ++ 0x63C, 0x0000000A, ++ 0x63D, 0x0000000A, ++ 0x63E, 0x0000000E, ++ 0x63F, 0x0000000E, ++ 0x640, 0x00000080, ++ 0x642, 0x00000040, ++ 0x643, 0x00000000, ++ 0x652, 0x000000C8, ++ 0x66E, 0x00000005, ++ 0x700, 0x00000021, ++ 0x701, 0x00000043, ++ 0x702, 0x00000065, ++ 0x703, 0x00000087, ++ 0x708, 0x00000021, ++ 0x709, 0x00000043, ++ 0x70A, 0x00000065, ++ 0x70B, 0x00000087, ++ 0x718, 0x00000040, ++}; ++ ++RTW_DECL_TABLE_PHY_COND(rtw8812a_mac, rtw_phy_cfg_mac); ++ ++static const u32 rtw8812a_agc[] = { ++ 0x80000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x81C, 0xFC000001, ++ 0x81C, 0xFB020001, ++ 0x81C, 0xFA040001, ++ 0x81C, 0xF9060001, ++ 0x81C, 0xF8080001, ++ 0x81C, 0xF70A0001, ++ 0x81C, 0xF60C0001, ++ 0x81C, 0xF50E0001, ++ 0x81C, 0xF4100001, ++ 0x81C, 0xF3120001, ++ 0x81C, 0xF2140001, ++ 0x81C, 0xF1160001, ++ 0x81C, 0xF0180001, ++ 0x81C, 0xEF1A0001, ++ 0x81C, 0xEE1C0001, ++ 0x81C, 0xED1E0001, ++ 0x81C, 0xEC200001, ++ 0x81C, 0xEB220001, ++ 0x81C, 0xEA240001, ++ 0x81C, 0xCD260001, ++ 0x81C, 0xCC280001, ++ 0x81C, 0xCB2A0001, ++ 0x81C, 0xCA2C0001, ++ 0x81C, 0xC92E0001, ++ 0x81C, 0xC8300001, ++ 0x81C, 0xA6320001, ++ 0x81C, 0xA5340001, ++ 0x81C, 0xA4360001, ++ 0x81C, 0xA3380001, ++ 0x81C, 0xA23A0001, ++ 0x81C, 0x883C0001, ++ 0x81C, 0x873E0001, ++ 0x81C, 0x86400001, ++ 0x81C, 0x85420001, ++ 0x81C, 0x84440001, ++ 0x81C, 0x83460001, ++ 0x81C, 0x82480001, ++ 0x81C, 0x814A0001, ++ 0x81C, 0x484C0001, ++ 0x81C, 0x474E0001, ++ 0x81C, 0x46500001, ++ 0x81C, 0x45520001, ++ 0x81C, 0x44540001, ++ 0x81C, 0x43560001, ++ 0x81C, 0x42580001, ++ 0x81C, 0x415A0001, ++ 0x81C, 0x255C0001, ++ 0x81C, 0x245E0001, ++ 0x81C, 0x23600001, ++ 0x81C, 0x22620001, ++ 0x81C, 0x21640001, ++ 0x81C, 0x21660001, ++ 0x81C, 0x21680001, ++ 0x81C, 0x216A0001, ++ 0x81C, 0x216C0001, ++ 0x81C, 0x216E0001, ++ 0x81C, 0x21700001, ++ 0x81C, 0x21720001, ++ 0x81C, 0x21740001, ++ 0x81C, 0x21760001, ++ 0x81C, 0x21780001, ++ 0x81C, 0x217A0001, ++ 0x81C, 0x217C0001, ++ 0x81C, 0x217E0001, ++ 0x90000001, 0x00000005, 0x40000000, 0x00000000, ++ 0x81C, 0xF9000001, ++ 0x81C, 0xF8020001, ++ 0x81C, 0xF7040001, ++ 0x81C, 0xF6060001, ++ 0x81C, 0xF5080001, ++ 0x81C, 0xF40A0001, ++ 0x81C, 0xF30C0001, ++ 0x81C, 0xF20E0001, ++ 0x81C, 0xF1100001, ++ 0x81C, 0xF0120001, ++ 0x81C, 0xEF140001, ++ 0x81C, 0xEE160001, ++ 0x81C, 0xED180001, ++ 0x81C, 0xEC1A0001, ++ 0x81C, 0xEB1C0001, ++ 0x81C, 0xEA1E0001, ++ 0x81C, 0xCD200001, ++ 0x81C, 0xCC220001, ++ 0x81C, 0xCB240001, ++ 0x81C, 0xCA260001, ++ 0x81C, 0xC9280001, ++ 0x81C, 0xC82A0001, ++ 0x81C, 0xC72C0001, ++ 0x81C, 0xC62E0001, ++ 0x81C, 0xA5300001, ++ 0x81C, 0xA4320001, ++ 0x81C, 0xA3340001, ++ 0x81C, 0xA2360001, ++ 0x81C, 0x88380001, ++ 0x81C, 0x873A0001, ++ 0x81C, 0x863C0001, ++ 0x81C, 0x853E0001, ++ 0x81C, 0x84400001, ++ 0x81C, 0x83420001, ++ 0x81C, 0x82440001, ++ 0x81C, 0x81460001, ++ 0x81C, 0x48480001, ++ 0x81C, 0x474A0001, ++ 0x81C, 0x464C0001, ++ 0x81C, 0x454E0001, ++ 0x81C, 0x44500001, ++ 0x81C, 0x43520001, ++ 0x81C, 0x42540001, ++ 0x81C, 0x41560001, ++ 0x81C, 0x25580001, ++ 0x81C, 0x245A0001, ++ 0x81C, 0x235C0001, ++ 0x81C, 0x225E0001, ++ 0x81C, 0x21600001, ++ 0x81C, 0x21620001, ++ 0x81C, 0x21640001, ++ 0x81C, 0x21660001, ++ 0x81C, 0x21680001, ++ 0x81C, 0x216A0001, ++ 0x81C, 0x236C0001, ++ 0x81C, 0x226E0001, ++ 0x81C, 0x21700001, ++ 0x81C, 0x21720001, ++ 0x81C, 0x21740001, ++ 0x81C, 0x21760001, ++ 0x81C, 0x21780001, ++ 0x81C, 0x217A0001, ++ 0x81C, 0x217C0001, ++ 0x81C, 0x217E0001, ++ 0xA0000000, 0x00000000, ++ 0x81C, 0xFF000001, ++ 0x81C, 0xFF020001, ++ 0x81C, 0xFF040001, ++ 0x81C, 0xFF060001, ++ 0x81C, 0xFF080001, ++ 0x81C, 0xFE0A0001, ++ 0x81C, 0xFD0C0001, ++ 0x81C, 0xFC0E0001, ++ 0x81C, 0xFB100001, ++ 0x81C, 0xFA120001, ++ 0x81C, 0xF9140001, ++ 0x81C, 0xF8160001, ++ 0x81C, 0xF7180001, ++ 0x81C, 0xF61A0001, ++ 0x81C, 0xF51C0001, ++ 0x81C, 0xF41E0001, ++ 0x81C, 0xF3200001, ++ 0x81C, 0xF2220001, ++ 0x81C, 0xF1240001, ++ 0x81C, 0xF0260001, ++ 0x81C, 0xEF280001, ++ 0x81C, 0xEE2A0001, ++ 0x81C, 0xED2C0001, ++ 0x81C, 0xEC2E0001, ++ 0x81C, 0xEB300001, ++ 0x81C, 0xEA320001, ++ 0x81C, 0xE9340001, ++ 0x81C, 0xE8360001, ++ 0x81C, 0xE7380001, ++ 0x81C, 0xE63A0001, ++ 0x81C, 0xE53C0001, ++ 0x81C, 0xC73E0001, ++ 0x81C, 0xC6400001, ++ 0x81C, 0xC5420001, ++ 0x81C, 0xC4440001, ++ 0x81C, 0xC3460001, ++ 0x81C, 0xC2480001, ++ 0x81C, 0xC14A0001, ++ 0x81C, 0xA74C0001, ++ 0x81C, 0xA64E0001, ++ 0x81C, 0xA5500001, ++ 0x81C, 0xA4520001, ++ 0x81C, 0xA3540001, ++ 0x81C, 0xA2560001, ++ 0x81C, 0xA1580001, ++ 0x81C, 0x675A0001, ++ 0x81C, 0x665C0001, ++ 0x81C, 0x655E0001, ++ 0x81C, 0x64600001, ++ 0x81C, 0x63620001, ++ 0x81C, 0x48640001, ++ 0x81C, 0x47660001, ++ 0x81C, 0x46680001, ++ 0x81C, 0x456A0001, ++ 0x81C, 0x446C0001, ++ 0x81C, 0x436E0001, ++ 0x81C, 0x42700001, ++ 0x81C, 0x41720001, ++ 0x81C, 0x41740001, ++ 0x81C, 0x41760001, ++ 0x81C, 0x41780001, ++ 0x81C, 0x417A0001, ++ 0x81C, 0x417C0001, ++ 0x81C, 0x417E0001, ++ 0xB0000000, 0x00000000, ++ 0x80000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x81C, 0xFC800001, ++ 0x81C, 0xFB820001, ++ 0x81C, 0xFA840001, ++ 0x81C, 0xF9860001, ++ 0x81C, 0xF8880001, ++ 0x81C, 0xF78A0001, ++ 0x81C, 0xF68C0001, ++ 0x81C, 0xF58E0001, ++ 0x81C, 0xF4900001, ++ 0x81C, 0xF3920001, ++ 0x81C, 0xF2940001, ++ 0x81C, 0xF1960001, ++ 0x81C, 0xF0980001, ++ 0x81C, 0xEF9A0001, ++ 0x81C, 0xEE9C0001, ++ 0x81C, 0xED9E0001, ++ 0x81C, 0xECA00001, ++ 0x81C, 0xEBA20001, ++ 0x81C, 0xEAA40001, ++ 0x81C, 0xE9A60001, ++ 0x81C, 0xE8A80001, ++ 0x81C, 0xE7AA0001, ++ 0x81C, 0xE6AC0001, ++ 0x81C, 0xE5AE0001, ++ 0x81C, 0xE4B00001, ++ 0x81C, 0xE3B20001, ++ 0x81C, 0xA8B40001, ++ 0x81C, 0xA7B60001, ++ 0x81C, 0xA6B80001, ++ 0x81C, 0xA5BA0001, ++ 0x81C, 0xA4BC0001, ++ 0x81C, 0xA3BE0001, ++ 0x81C, 0xA2C00001, ++ 0x81C, 0xA1C20001, ++ 0x81C, 0x68C40001, ++ 0x81C, 0x67C60001, ++ 0x81C, 0x66C80001, ++ 0x81C, 0x65CA0001, ++ 0x81C, 0x64CC0001, ++ 0x81C, 0x47CE0001, ++ 0x81C, 0x46D00001, ++ 0x81C, 0x45D20001, ++ 0x81C, 0x44D40001, ++ 0x81C, 0x43D60001, ++ 0x81C, 0x42D80001, ++ 0x81C, 0x08DA0001, ++ 0x81C, 0x07DC0001, ++ 0x81C, 0x06DE0001, ++ 0x81C, 0x05E00001, ++ 0x81C, 0x04E20001, ++ 0x81C, 0x03E40001, ++ 0x81C, 0x02E60001, ++ 0x81C, 0x01E80001, ++ 0x81C, 0x01EA0001, ++ 0x81C, 0x01EC0001, ++ 0x81C, 0x01EE0001, ++ 0x81C, 0x01F00001, ++ 0x81C, 0x01F20001, ++ 0x81C, 0x01F40001, ++ 0x81C, 0x01F60001, ++ 0x81C, 0x01F80001, ++ 0x81C, 0x01FA0001, ++ 0x81C, 0x01FC0001, ++ 0x81C, 0x01FE0001, ++ 0xA0000000, 0x00000000, ++ 0x81C, 0xFF800001, ++ 0x81C, 0xFF820001, ++ 0x81C, 0xFF840001, ++ 0x81C, 0xFE860001, ++ 0x81C, 0xFD880001, ++ 0x81C, 0xFC8A0001, ++ 0x81C, 0xFB8C0001, ++ 0x81C, 0xFA8E0001, ++ 0x81C, 0xF9900001, ++ 0x81C, 0xF8920001, ++ 0x81C, 0xF7940001, ++ 0x81C, 0xF6960001, ++ 0x81C, 0xF5980001, ++ 0x81C, 0xF49A0001, ++ 0x81C, 0xF39C0001, ++ 0x81C, 0xF29E0001, ++ 0x81C, 0xF1A00001, ++ 0x81C, 0xF0A20001, ++ 0x81C, 0xEFA40001, ++ 0x81C, 0xEEA60001, ++ 0x81C, 0xEDA80001, ++ 0x81C, 0xECAA0001, ++ 0x81C, 0xEBAC0001, ++ 0x81C, 0xEAAE0001, ++ 0x81C, 0xE9B00001, ++ 0x81C, 0xE8B20001, ++ 0x81C, 0xE7B40001, ++ 0x81C, 0xE6B60001, ++ 0x81C, 0xE5B80001, ++ 0x81C, 0xE4BA0001, ++ 0x81C, 0xE3BC0001, ++ 0x81C, 0xA8BE0001, ++ 0x81C, 0xA7C00001, ++ 0x81C, 0xA6C20001, ++ 0x81C, 0xA5C40001, ++ 0x81C, 0xA4C60001, ++ 0x81C, 0xA3C80001, ++ 0x81C, 0xA2CA0001, ++ 0x81C, 0xA1CC0001, ++ 0x81C, 0x68CE0001, ++ 0x81C, 0x67D00001, ++ 0x81C, 0x66D20001, ++ 0x81C, 0x65D40001, ++ 0x81C, 0x64D60001, ++ 0x81C, 0x47D80001, ++ 0x81C, 0x46DA0001, ++ 0x81C, 0x45DC0001, ++ 0x81C, 0x44DE0001, ++ 0x81C, 0x43E00001, ++ 0x81C, 0x42E20001, ++ 0x81C, 0x08E40001, ++ 0x81C, 0x07E60001, ++ 0x81C, 0x06E80001, ++ 0x81C, 0x05EA0001, ++ 0x81C, 0x04EC0001, ++ 0x81C, 0x03EE0001, ++ 0x81C, 0x02F00001, ++ 0x81C, 0x01F20001, ++ 0x81C, 0x01F40001, ++ 0x81C, 0x01F60001, ++ 0x81C, 0x01F80001, ++ 0x81C, 0x01FA0001, ++ 0x81C, 0x01FC0001, ++ 0x81C, 0x01FE0001, ++ 0xB0000000, 0x00000000, ++ 0xC50, 0x00000022, ++ 0xC50, 0x00000020, ++ 0xE50, 0x00000022, ++ 0xE50, 0x00000020, ++}; ++ ++RTW_DECL_TABLE_PHY_COND(rtw8812a_agc, rtw_phy_cfg_agc); ++ ++static const u32 rtw8812a_agc_diff_lb[] = { ++ 0x80000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x81C, 0x47CE0001, ++ 0x81C, 0x46D00001, ++ 0x81C, 0x45D20001, ++ 0x81C, 0x44D40001, ++ 0x81C, 0x43D60001, ++ 0x81C, 0x42D80001, ++ 0x81C, 0x08DA0001, ++ 0x81C, 0x07DC0001, ++ 0x81C, 0x06DE0001, ++ 0x81C, 0x05E00001, ++ 0x81C, 0x04E20001, ++ 0x81C, 0x03E40001, ++ 0x81C, 0x02E60001, ++ 0xA0000000, 0x00000000, ++ 0x81C, 0x47D80001, ++ 0x81C, 0x46DA0001, ++ 0x81C, 0x45DC0001, ++ 0x81C, 0x44DE0001, ++ 0x81C, 0x43E00001, ++ 0x81C, 0x42E20001, ++ 0x81C, 0x08E40001, ++ 0x81C, 0x07E60001, ++ 0x81C, 0x06E80001, ++ 0x81C, 0x05EA0001, ++ 0x81C, 0x04EC0001, ++ 0x81C, 0x03EE0001, ++ 0x81C, 0x02F00001, ++ 0xB0000000, 0x00000000, ++}; ++ ++RTW_DECL_TABLE_PHY_COND(rtw8812a_agc_diff_lb, rtw_phy_cfg_agc); ++ ++static const u32 rtw8812a_agc_diff_hb[] = { ++ 0x80000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x81C, 0x45CE0001, ++ 0x81C, 0x44D00001, ++ 0x81C, 0x43D20001, ++ 0x81C, 0x42D40001, ++ 0x81C, 0x08D60001, ++ 0x81C, 0x07D80001, ++ 0x81C, 0x06DA0001, ++ 0x81C, 0x05DC0001, ++ 0x81C, 0x04DE0001, ++ 0x81C, 0x03E00001, ++ 0x81C, 0x02E20001, ++ 0x81C, 0x01E40001, ++ 0x81C, 0x01E60001, ++ 0xA0000000, 0x00000000, ++ 0x81C, 0x45D80001, ++ 0x81C, 0x44DA0001, ++ 0x81C, 0x43DC0001, ++ 0x81C, 0x42DE0001, ++ 0x81C, 0x08E00001, ++ 0x81C, 0x07E20001, ++ 0x81C, 0x06E40001, ++ 0x81C, 0x05E60001, ++ 0x81C, 0x04E80001, ++ 0x81C, 0x03EA0001, ++ 0x81C, 0x02EC0001, ++ 0x81C, 0x01EE0001, ++ 0x81C, 0x01F00001, ++ 0xB0000000, 0x00000000, ++}; ++ ++RTW_DECL_TABLE_PHY_COND(rtw8812a_agc_diff_hb, rtw_phy_cfg_agc); ++ ++static const u32 rtw8812a_bb[] = { ++ 0x800, 0x8020D010, ++ 0x804, 0x080112E0, ++ 0x808, 0x0E028233, ++ 0x80C, 0x12131113, ++ 0x810, 0x20101263, ++ 0x814, 0x020C3D10, ++ 0x818, 0x03A00385, ++ 0x820, 0x00000000, ++ 0x824, 0x00030FE0, ++ 0x828, 0x00000000, ++ 0x82C, 0x002083DD, ++ 0x830, 0x2EAAEEB8, ++ 0x834, 0x0037A706, ++ 0x838, 0x06C89B44, ++ 0x83C, 0x0000095B, ++ 0x840, 0xC0000001, ++ 0x844, 0x40003CDE, ++ 0x848, 0x6210FF8B, ++ 0x84C, 0x6CFDFFB8, ++ 0x850, 0x28874706, ++ 0x854, 0x0001520C, ++ 0x858, 0x8060E000, ++ 0x85C, 0x74210168, ++ 0x860, 0x6929C321, ++ 0x864, 0x79727432, ++ 0x868, 0x8CA7A314, ++ 0x86C, 0x338C2878, ++ 0x870, 0x03333333, ++ 0x874, 0x31602C2E, ++ 0x878, 0x00003152, ++ 0x87C, 0x000FC000, ++ 0x8A0, 0x00000013, ++ 0x8A4, 0x7F7F7F7F, ++ 0x8A8, 0xA202033E, ++ 0x8AC, 0x0FF0FA0A, ++ 0x8B0, 0x00000600, ++ 0x8B4, 0x000FC080, ++ 0x8B8, 0x6C10D7FF, ++ 0x8BC, 0x4CA520A3, ++ 0x8C0, 0x27F00020, ++ 0x8C4, 0x00000000, ++ 0x8C8, 0x00012D69, ++ 0x8CC, 0x08248492, ++ 0x8D0, 0x0000B800, ++ 0x8DC, 0x00000000, ++ 0x8D4, 0x940008A0, ++ 0x8D8, 0x290B5612, ++ 0x8F8, 0x400002C0, ++ 0x8FC, 0x00000000, ++ 0x900, 0x00000701, ++ 0x90C, 0x00000000, ++ 0x910, 0x0000FC00, ++ 0x914, 0x00000404, ++ 0x918, 0x1C1028C0, ++ 0x91C, 0x64B11A1C, ++ 0x920, 0xE0767233, ++ 0x924, 0x055AA500, ++ 0x928, 0x00000004, ++ 0x92C, 0xFFFE0000, ++ 0x930, 0xFFFFFFFE, ++ 0x934, 0x001FFFFF, ++ 0x960, 0x00000000, ++ 0x964, 0x00000000, ++ 0x968, 0x00000000, ++ 0x96C, 0x00000000, ++ 0x970, 0x801FFFFF, ++ 0x978, 0x00000000, ++ 0x97C, 0x00000000, ++ 0x980, 0x00000000, ++ 0x984, 0x00000000, ++ 0x988, 0x00000000, ++ 0x990, 0x27100000, ++ 0x994, 0xFFFF0100, ++ 0x998, 0xFFFFFF5C, ++ 0x99C, 0xFFFFFFFF, ++ 0x9A0, 0x000000FF, ++ 0x9A4, 0x00080080, ++ 0x9A8, 0x00000000, ++ 0x9AC, 0x00000000, ++ 0x9B0, 0x81081008, ++ 0x9B4, 0x00000000, ++ 0x9B8, 0x01081008, ++ 0x9BC, 0x01081008, ++ 0x9D0, 0x00000000, ++ 0x9D4, 0x00000000, ++ 0x9D8, 0x00000000, ++ 0x9DC, 0x00000000, ++ 0x9E4, 0x00000003, ++ 0x9E8, 0x000002D5, ++ 0xA00, 0x00D047C8, ++ 0xA04, 0x01FF000C, ++ 0xA08, 0x8C838300, ++ 0xA0C, 0x2E7F000F, ++ 0xA10, 0x9500BB78, ++ 0xA14, 0x11144028, ++ 0xA18, 0x00881117, ++ 0xA1C, 0x89140F00, ++ 0xA20, 0x1A1B0000, ++ 0xA24, 0x090E1217, ++ 0xA28, 0x00000305, ++ 0xA2C, 0x00900000, ++ 0xA70, 0x101FFF00, ++ 0xA74, 0x00000008, ++ 0xA78, 0x00000900, ++ 0xA7C, 0x225B0606, ++ 0xA80, 0x218075B2, ++ 0xA84, 0x001F8C80, ++ 0xB00, 0x03100000, ++ 0xB04, 0x0000B000, ++ 0xB08, 0xAE0201EB, ++ 0xB0C, 0x01003207, ++ 0xB10, 0x00009807, ++ 0xB14, 0x01000000, ++ 0xB18, 0x00000002, ++ 0xB1C, 0x00000002, ++ 0xB20, 0x0000001F, ++ 0xB24, 0x03020100, ++ 0xB28, 0x07060504, ++ 0xB2C, 0x0B0A0908, ++ 0xB30, 0x0F0E0D0C, ++ 0xB34, 0x13121110, ++ 0xB38, 0x17161514, ++ 0xB3C, 0x0000003A, ++ 0xB40, 0x00000000, ++ 0xB44, 0x00000000, ++ 0xB48, 0x13000032, ++ 0xB4C, 0x48080000, ++ 0xB50, 0x00000000, ++ 0xB54, 0x00000000, ++ 0xB58, 0x00000000, ++ 0xB5C, 0x00000000, ++ 0xC00, 0x00000007, ++ 0xC04, 0x00042020, ++ 0xC08, 0x80410231, ++ 0xC0C, 0x00000000, ++ 0xC10, 0x00000100, ++ 0xC14, 0x01000000, ++ 0xC1C, 0x40000003, ++ 0xC20, 0x12121212, ++ 0xC24, 0x12121212, ++ 0xC28, 0x12121212, ++ 0xC2C, 0x12121212, ++ 0xC30, 0x12121212, ++ 0xC34, 0x12121212, ++ 0xC38, 0x12121212, ++ 0xC3C, 0x12121212, ++ 0xC40, 0x12121212, ++ 0xC44, 0x12121212, ++ 0xC48, 0x12121212, ++ 0xC4C, 0x12121212, ++ 0xC50, 0x00000020, ++ 0xC54, 0x0008121C, ++ 0xC58, 0x30000C1C, ++ 0xC5C, 0x00000058, ++ 0xC60, 0x34344443, ++ 0xC64, 0x07003333, ++ 0x80000008, 0x00000000, 0x40000000, 0x00000000, ++ 0xC68, 0x59791979, ++ 0x90000008, 0x05000000, 0x40000000, 0x00000000, ++ 0xC68, 0x59791979, ++ 0x90000002, 0x00000000, 0x40000000, 0x00000000, ++ 0xC68, 0x59791979, ++ 0x90000004, 0x00000000, 0x40000000, 0x00000000, ++ 0xC68, 0x59791979, ++ 0x90000001, 0x00000000, 0x40000000, 0x00000000, ++ 0xC68, 0x59791979, ++ 0x90000001, 0x00000005, 0x40000000, 0x00000000, ++ 0xC68, 0x59791979, ++ 0xA0000000, 0x00000000, ++ 0xC68, 0x59799979, ++ 0xB0000000, 0x00000000, ++ 0xC6C, 0x59795979, ++ 0xC70, 0x19795979, ++ 0xC74, 0x19795979, ++ 0xC78, 0x19791979, ++ 0xC7C, 0x19791979, ++ 0xC80, 0x19791979, ++ 0xC84, 0x19791979, ++ 0xC94, 0x0100005C, ++ 0xC98, 0x00000000, ++ 0xC9C, 0x00000000, ++ 0xCA0, 0x00000029, ++ 0xCA4, 0x08040201, ++ 0xCA8, 0x80402010, ++ 0xCB0, 0x77547777, ++ 0xCB4, 0x00000077, ++ 0xCB8, 0x00508242, ++ 0xE00, 0x00000007, ++ 0xE04, 0x00042020, ++ 0xE08, 0x80410231, ++ 0xE0C, 0x00000000, ++ 0xE10, 0x00000100, ++ 0xE14, 0x01000000, ++ 0xE1C, 0x40000003, ++ 0xE20, 0x12121212, ++ 0xE24, 0x12121212, ++ 0xE28, 0x12121212, ++ 0xE2C, 0x12121212, ++ 0xE30, 0x12121212, ++ 0xE34, 0x12121212, ++ 0xE38, 0x12121212, ++ 0xE3C, 0x12121212, ++ 0xE40, 0x12121212, ++ 0xE44, 0x12121212, ++ 0xE48, 0x12121212, ++ 0xE4C, 0x12121212, ++ 0xE50, 0x00000020, ++ 0xE54, 0x0008121C, ++ 0xE58, 0x30000C1C, ++ 0xE5C, 0x00000058, ++ 0xE60, 0x34344443, ++ 0xE64, 0x07003333, ++ 0xE68, 0x59791979, ++ 0xE6C, 0x59795979, ++ 0xE70, 0x19795979, ++ 0xE74, 0x19795979, ++ 0xE78, 0x19791979, ++ 0xE7C, 0x19791979, ++ 0xE80, 0x19791979, ++ 0xE84, 0x19791979, ++ 0xE94, 0x0100005C, ++ 0xE98, 0x00000000, ++ 0xE9C, 0x00000000, ++ 0xEA0, 0x00000029, ++ 0xEA4, 0x08040201, ++ 0xEA8, 0x80402010, ++ 0xEB0, 0x77547777, ++ 0xEB4, 0x00000077, ++ 0xEB8, 0x00508242, ++}; ++ ++RTW_DECL_TABLE_PHY_COND(rtw8812a_bb, rtw_phy_cfg_bb); ++ ++static const struct rtw_phy_pg_cfg_pair rtw8812a_bb_pg[] = { ++ { 0, 0, 0, 0x00000c20, 0xffffffff, 0x34363840, }, ++ { 0, 0, 0, 0x00000c24, 0xffffffff, 0x42424444, }, ++ { 0, 0, 0, 0x00000c28, 0xffffffff, 0x30323638, }, ++ { 0, 0, 0, 0x00000c2c, 0xffffffff, 0x40424444, }, ++ { 0, 0, 0, 0x00000c30, 0xffffffff, 0x28303236, }, ++ { 0, 0, 1, 0x00000c34, 0xffffffff, 0x38404242, }, ++ { 0, 0, 1, 0x00000c38, 0xffffffff, 0x26283034, }, ++ { 0, 0, 0, 0x00000c3c, 0xffffffff, 0x40424444, }, ++ { 0, 0, 0, 0x00000c40, 0xffffffff, 0x28303236, }, ++ { 0, 0, 0, 0x00000c44, 0xffffffff, 0x42422426, }, ++ { 0, 0, 1, 0x00000c48, 0xffffffff, 0x30343840, }, ++ { 0, 0, 1, 0x00000c4c, 0xffffffff, 0x22242628, }, ++ { 0, 1, 0, 0x00000e20, 0xffffffff, 0x34363840, }, ++ { 0, 1, 0, 0x00000e24, 0xffffffff, 0x42424444, }, ++ { 0, 1, 0, 0x00000e28, 0xffffffff, 0x30323638, }, ++ { 0, 1, 0, 0x00000e2c, 0xffffffff, 0x40424444, }, ++ { 0, 1, 0, 0x00000e30, 0xffffffff, 0x28303236, }, ++ { 0, 1, 1, 0x00000e34, 0xffffffff, 0x38404242, }, ++ { 0, 1, 1, 0x00000e38, 0xffffffff, 0x26283034, }, ++ { 0, 1, 0, 0x00000e3c, 0xffffffff, 0x40424444, }, ++ { 0, 1, 0, 0x00000e40, 0xffffffff, 0x28303236, }, ++ { 0, 1, 0, 0x00000e44, 0xffffffff, 0x42422426, }, ++ { 0, 1, 1, 0x00000e48, 0xffffffff, 0x30343840, }, ++ { 0, 1, 1, 0x00000e4c, 0xffffffff, 0x22242628, }, ++ { 1, 0, 0, 0x00000c24, 0xffffffff, 0x42424444, }, ++ { 1, 0, 0, 0x00000c28, 0xffffffff, 0x30323640, }, ++ { 1, 0, 0, 0x00000c2c, 0xffffffff, 0x40424444, }, ++ { 1, 0, 0, 0x00000c30, 0xffffffff, 0x28303236, }, ++ { 1, 0, 1, 0x00000c34, 0xffffffff, 0x38404242, }, ++ { 1, 0, 1, 0x00000c38, 0xffffffff, 0x26283034, }, ++ { 1, 0, 0, 0x00000c3c, 0xffffffff, 0x40424444, }, ++ { 1, 0, 0, 0x00000c40, 0xffffffff, 0x28303236, }, ++ { 1, 0, 0, 0x00000c44, 0xffffffff, 0x42422426, }, ++ { 1, 0, 1, 0x00000c48, 0xffffffff, 0x30343840, }, ++ { 1, 0, 1, 0x00000c4c, 0xffffffff, 0x22242628, }, ++ { 1, 1, 0, 0x00000e24, 0xffffffff, 0x42424444, }, ++ { 1, 1, 0, 0x00000e28, 0xffffffff, 0x30323640, }, ++ { 1, 1, 0, 0x00000e2c, 0xffffffff, 0x40424444, }, ++ { 1, 1, 0, 0x00000e30, 0xffffffff, 0x28303236, }, ++ { 1, 1, 1, 0x00000e34, 0xffffffff, 0x38404242, }, ++ { 1, 1, 1, 0x00000e38, 0xffffffff, 0x26283034, }, ++ { 1, 1, 0, 0x00000e3c, 0xffffffff, 0x40424444, }, ++ { 1, 1, 0, 0x00000e40, 0xffffffff, 0x28303236, }, ++ { 1, 1, 0, 0x00000e44, 0xffffffff, 0x42422426, }, ++ { 1, 1, 1, 0x00000e48, 0xffffffff, 0x30343840, }, ++ { 1, 1, 1, 0x00000e4c, 0xffffffff, 0x22242628, }, ++}; ++ ++RTW_DECL_TABLE_BB_PG(rtw8812a_bb_pg); ++ ++static const struct rtw_phy_pg_cfg_pair rtw8812a_bb_pg_rfe3[] = { ++ { 0, 0, 0, 0x00000c20, 0xffffffff, 0x34343434, }, ++ { 0, 0, 0, 0x00000c24, 0xffffffff, 0x32323232, }, ++ { 0, 0, 0, 0x00000c28, 0xffffffff, 0x28303232, }, ++ { 0, 0, 0, 0x00000c2c, 0xffffffff, 0x32323232, }, ++ { 0, 0, 0, 0x00000c30, 0xffffffff, 0x28303232, }, ++ { 0, 0, 1, 0x00000c34, 0xffffffff, 0x32323232, }, ++ { 0, 0, 1, 0x00000c38, 0xffffffff, 0x26283032, }, ++ { 0, 0, 0, 0x00000c3c, 0xffffffff, 0x32323232, }, ++ { 0, 0, 0, 0x00000c40, 0xffffffff, 0x28303232, }, ++ { 0, 0, 0, 0x00000c44, 0xffffffff, 0x32322426, }, ++ { 0, 0, 1, 0x00000c48, 0xffffffff, 0x32323232, }, ++ { 0, 0, 1, 0x00000c4c, 0xffffffff, 0x24262830, }, ++ { 0, 1, 0, 0x00000e20, 0xffffffff, 0x34343434, }, ++ { 0, 1, 0, 0x00000e24, 0xffffffff, 0x32323232, }, ++ { 0, 1, 0, 0x00000e28, 0xffffffff, 0x28303232, }, ++ { 0, 1, 0, 0x00000e2c, 0xffffffff, 0x32323232, }, ++ { 0, 1, 0, 0x00000e30, 0xffffffff, 0x28303232, }, ++ { 0, 1, 1, 0x00000e34, 0xffffffff, 0x32323232, }, ++ { 0, 1, 1, 0x00000e38, 0xffffffff, 0x26283032, }, ++ { 0, 1, 0, 0x00000e3c, 0xffffffff, 0x32323232, }, ++ { 0, 1, 0, 0x00000e40, 0xffffffff, 0x28303232, }, ++ { 0, 1, 0, 0x00000e44, 0xffffffff, 0x32322426, }, ++ { 0, 1, 1, 0x00000e48, 0xffffffff, 0x32323232, }, ++ { 0, 1, 1, 0x00000e4c, 0xffffffff, 0x24262830, }, ++ { 1, 0, 0, 0x00000c24, 0xffffffff, 0x32323232, }, ++ { 1, 0, 0, 0x00000c28, 0xffffffff, 0x28303232, }, ++ { 1, 0, 0, 0x00000c2c, 0xffffffff, 0x32323232, }, ++ { 1, 0, 0, 0x00000c30, 0xffffffff, 0x24262830, }, ++ { 1, 0, 1, 0x00000c34, 0xffffffff, 0x32323232, }, ++ { 1, 0, 1, 0x00000c38, 0xffffffff, 0x24262830, }, ++ { 1, 0, 0, 0x00000c3c, 0xffffffff, 0x32323232, }, ++ { 1, 0, 0, 0x00000c40, 0xffffffff, 0x24262830, }, ++ { 1, 0, 0, 0x00000c44, 0xffffffff, 0x32322222, }, ++ { 1, 0, 1, 0x00000c48, 0xffffffff, 0x28303232, }, ++ { 1, 0, 1, 0x00000c4c, 0xffffffff, 0x22222426, }, ++ { 1, 1, 0, 0x00000e24, 0xffffffff, 0x32323232, }, ++ { 1, 1, 0, 0x00000e28, 0xffffffff, 0x28303232, }, ++ { 1, 1, 0, 0x00000e2c, 0xffffffff, 0x32323232, }, ++ { 1, 1, 0, 0x00000e30, 0xffffffff, 0x24262830, }, ++ { 1, 1, 1, 0x00000e34, 0xffffffff, 0x32323232, }, ++ { 1, 1, 1, 0x00000e38, 0xffffffff, 0x24262830, }, ++ { 1, 1, 0, 0x00000e3c, 0xffffffff, 0x32323232, }, ++ { 1, 1, 0, 0x00000e40, 0xffffffff, 0x24262830, }, ++ { 1, 1, 0, 0x00000e44, 0xffffffff, 0x32322222, }, ++ { 1, 1, 1, 0x00000e48, 0xffffffff, 0x28303232, }, ++ { 1, 1, 1, 0x00000e4c, 0xffffffff, 0x22222426, }, ++}; ++ ++RTW_DECL_TABLE_BB_PG(rtw8812a_bb_pg_rfe3); ++ ++static const u32 rtw8812a_rf_a[] = { ++ 0x000, 0x00010000, ++ 0x018, 0x0001712A, ++ 0x056, 0x00051CF2, ++ 0x066, 0x00040000, ++ 0x01E, 0x00080000, ++ 0x089, 0x00000080, ++ 0x80000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x086, 0x00014B3A, ++ 0x90000001, 0x00000005, 0x40000000, 0x00000000, ++ 0x086, 0x00014B3A, ++ 0xA0000000, 0x00000000, ++ 0x086, 0x00014B38, ++ 0xB0000000, 0x00000000, ++ 0x80000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x08B, 0x00080180, ++ 0xA0000000, 0x00000000, ++ 0x08B, 0x00087180, ++ 0xB0000000, 0x00000000, ++ 0x0B1, 0x0001FC1A, ++ 0x0B3, 0x000F0810, ++ 0x0B4, 0x0001A78D, ++ 0x0BA, 0x00086180, ++ 0x018, 0x00000006, ++ 0x0EF, 0x00002000, ++ 0x80000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03B, 0x0003F218, ++ 0x03B, 0x00030A58, ++ 0x03B, 0x0002FA58, ++ 0x03B, 0x00022590, ++ 0x03B, 0x0001FA50, ++ 0x03B, 0x00010248, ++ 0x03B, 0x00008240, ++ 0x90000001, 0x00000005, 0x40000000, 0x00000000, ++ 0x03B, 0x0003F218, ++ 0x03B, 0x00030A58, ++ 0x03B, 0x0002FA58, ++ 0x03B, 0x00022590, ++ 0x03B, 0x0001FA50, ++ 0x03B, 0x00010248, ++ 0x03B, 0x00008240, ++ 0xA0000000, 0x00000000, ++ 0x03B, 0x00038A58, ++ 0x03B, 0x00037A58, ++ 0x03B, 0x0002A590, ++ 0x03B, 0x00027A50, ++ 0x03B, 0x00018248, ++ 0x03B, 0x00010240, ++ 0x03B, 0x00008240, ++ 0xB0000000, 0x00000000, ++ 0x0EF, 0x00000100, ++ 0x80000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x0000A4EE, ++ 0x034, 0x00009076, ++ 0x034, 0x00008073, ++ 0x034, 0x00007070, ++ 0x034, 0x0000606D, ++ 0x034, 0x0000506A, ++ 0x034, 0x00004049, ++ 0x034, 0x00003046, ++ 0x034, 0x00002028, ++ 0x034, 0x00001025, ++ 0x034, 0x00000022, ++ 0xA0000000, 0x00000000, ++ 0x034, 0x0000ADF4, ++ 0x034, 0x00009DF1, ++ 0x034, 0x00008DEE, ++ 0x034, 0x00007DEB, ++ 0x034, 0x00006DE8, ++ 0x034, 0x00005DE5, ++ 0x034, 0x00004DE2, ++ 0x034, 0x00003CE6, ++ 0x034, 0x000024E7, ++ 0x034, 0x000014E4, ++ 0x034, 0x000004E1, ++ 0xB0000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x0EF, 0x000020A2, ++ 0x0DF, 0x00000080, ++ 0x035, 0x00000192, ++ 0x035, 0x00008192, ++ 0x035, 0x00010192, ++ 0x036, 0x00000024, ++ 0x036, 0x00008024, ++ 0x036, 0x00010024, ++ 0x036, 0x00018024, ++ 0x0EF, 0x00000000, ++ 0x051, 0x00000C21, ++ 0x052, 0x000006D9, ++ 0x053, 0x000FC649, ++ 0x054, 0x0000017E, ++ 0x0EF, 0x00000002, ++ 0x008, 0x00008400, ++ 0x018, 0x0001712A, ++ 0x0EF, 0x00001000, ++ 0x03A, 0x00000080, ++ 0x03B, 0x0003A02C, ++ 0x03C, 0x00004000, ++ 0x03A, 0x00000400, ++ 0x03B, 0x0003202C, ++ 0x03C, 0x00010000, ++ 0x03A, 0x000000A0, ++ 0x03B, 0x0002B064, ++ 0x03C, 0x00004000, ++ 0x03A, 0x000000D8, ++ 0x03B, 0x00023070, ++ 0x03C, 0x00004000, ++ 0x03A, 0x00000468, ++ 0x03B, 0x0001B870, ++ 0x03C, 0x00010000, ++ 0x03A, 0x00000098, ++ 0x03B, 0x00012085, ++ 0x03C, 0x000E4000, ++ 0x03A, 0x00000418, ++ 0x03B, 0x0000A080, ++ 0x03C, 0x000F0000, ++ 0x03A, 0x00000418, ++ 0x03B, 0x00002080, ++ 0x03C, 0x00010000, ++ 0x03A, 0x00000080, ++ 0x03B, 0x0007A02C, ++ 0x03C, 0x00004000, ++ 0x03A, 0x00000400, ++ 0x03B, 0x0007202C, ++ 0x03C, 0x00010000, ++ 0x03A, 0x000000A0, ++ 0x03B, 0x0006B064, ++ 0x03C, 0x00004000, ++ 0x03A, 0x000000D8, ++ 0x03B, 0x00063070, ++ 0x03C, 0x00004000, ++ 0x03A, 0x00000468, ++ 0x03B, 0x0005B870, ++ 0x03C, 0x00010000, ++ 0x03A, 0x00000098, ++ 0x03B, 0x00052085, ++ 0x03C, 0x000E4000, ++ 0x03A, 0x00000418, ++ 0x03B, 0x0004A080, ++ 0x03C, 0x000F0000, ++ 0x03A, 0x00000418, ++ 0x03B, 0x00042080, ++ 0x03C, 0x00010000, ++ 0x03A, 0x00000080, ++ 0x03B, 0x000BA02C, ++ 0x03C, 0x00004000, ++ 0x03A, 0x00000400, ++ 0x03B, 0x000B202C, ++ 0x03C, 0x00010000, ++ 0x03A, 0x000000A0, ++ 0x03B, 0x000AB064, ++ 0x03C, 0x00004000, ++ 0x03A, 0x000000D8, ++ 0x03B, 0x000A3070, ++ 0x03C, 0x00004000, ++ 0x03A, 0x00000468, ++ 0x03B, 0x0009B870, ++ 0x03C, 0x00010000, ++ 0x03A, 0x00000098, ++ 0x03B, 0x00092085, ++ 0x03C, 0x000E4000, ++ 0x03A, 0x00000418, ++ 0x03B, 0x0008A080, ++ 0x03C, 0x000F0000, ++ 0x03A, 0x00000418, ++ 0x03B, 0x00082080, ++ 0x03C, 0x00010000, ++ 0x0EF, 0x00001100, ++ 0x80000008, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x0004A0B2, ++ 0x034, 0x000490AF, ++ 0x034, 0x00048070, ++ 0x034, 0x0004706D, ++ 0x034, 0x00046050, ++ 0x034, 0x0004504D, ++ 0x034, 0x0004404A, ++ 0x034, 0x00043047, ++ 0x034, 0x0004200A, ++ 0x034, 0x00041007, ++ 0x034, 0x00040004, ++ 0x90000008, 0x05000000, 0x40000000, 0x00000000, ++ 0x034, 0x0004A0B2, ++ 0x034, 0x000490AF, ++ 0x034, 0x00048070, ++ 0x034, 0x0004706D, ++ 0x034, 0x0004604D, ++ 0x034, 0x0004504A, ++ 0x034, 0x00044047, ++ 0x034, 0x00043044, ++ 0x034, 0x00042007, ++ 0x034, 0x00041004, ++ 0x034, 0x00040001, ++ 0xA0000000, 0x00000000, ++ 0x034, 0x0004ADF5, ++ 0x034, 0x00049DF2, ++ 0x034, 0x00048DEF, ++ 0x034, 0x00047DEC, ++ 0x034, 0x00046DE9, ++ 0x034, 0x00045DE6, ++ 0x034, 0x00044DE3, ++ 0x034, 0x000438C8, ++ 0x034, 0x000428C5, ++ 0x034, 0x000418C2, ++ 0x034, 0x000408C0, ++ 0xB0000000, 0x00000000, ++ 0x80000008, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x0002A0B2, ++ 0x034, 0x000290AF, ++ 0x034, 0x00028070, ++ 0x034, 0x0002706D, ++ 0x034, 0x00026050, ++ 0x034, 0x0002504D, ++ 0x034, 0x0002404A, ++ 0x034, 0x00023047, ++ 0x034, 0x0002200A, ++ 0x034, 0x00021007, ++ 0x034, 0x00020004, ++ 0x90000008, 0x05000000, 0x40000000, 0x00000000, ++ 0x034, 0x0002A0B4, ++ 0x034, 0x000290B1, ++ 0x034, 0x00028072, ++ 0x034, 0x0002706F, ++ 0x034, 0x0002604F, ++ 0x034, 0x0002504C, ++ 0x034, 0x00024049, ++ 0x034, 0x00023046, ++ 0x034, 0x00022009, ++ 0x034, 0x00021006, ++ 0x034, 0x00020003, ++ 0xA0000000, 0x00000000, ++ 0x034, 0x0002ADF5, ++ 0x034, 0x00029DF2, ++ 0x034, 0x00028DEF, ++ 0x034, 0x00027DEC, ++ 0x034, 0x00026DE9, ++ 0x034, 0x00025DE6, ++ 0x034, 0x00024DE3, ++ 0x034, 0x000238C8, ++ 0x034, 0x000228C5, ++ 0x034, 0x000218C2, ++ 0x034, 0x000208C0, ++ 0xB0000000, 0x00000000, ++ 0x80000008, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x0000A0B2, ++ 0x034, 0x000090AF, ++ 0x034, 0x00008070, ++ 0x034, 0x0000706D, ++ 0x034, 0x00006050, ++ 0x034, 0x0000504D, ++ 0x034, 0x0000404A, ++ 0x034, 0x00003047, ++ 0x034, 0x0000200A, ++ 0x034, 0x00001007, ++ 0x034, 0x00000004, ++ 0x90000008, 0x05000000, 0x40000000, 0x00000000, ++ 0x034, 0x0000A0B2, ++ 0x034, 0x000090AF, ++ 0x034, 0x00008070, ++ 0x034, 0x0000706D, ++ 0x034, 0x0000604D, ++ 0x034, 0x0000504A, ++ 0x034, 0x00004047, ++ 0x034, 0x00003044, ++ 0x034, 0x00002007, ++ 0x034, 0x00001004, ++ 0x034, 0x00000001, ++ 0xA0000000, 0x00000000, ++ 0x034, 0x0000AFF7, ++ 0x034, 0x00009DF7, ++ 0x034, 0x00008DF4, ++ 0x034, 0x00007DF1, ++ 0x034, 0x00006DEE, ++ 0x034, 0x00005DEB, ++ 0x034, 0x00004DE8, ++ 0x034, 0x000038CC, ++ 0x034, 0x000028C9, ++ 0x034, 0x000018C6, ++ 0x034, 0x000008C3, ++ 0xB0000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x80000008, 0x00000000, 0x40000000, 0x00000000, ++ 0x018, 0x0001712A, ++ 0x0EF, 0x00000040, ++ 0x035, 0x000001D4, ++ 0x035, 0x000081D4, ++ 0x035, 0x000101D4, ++ 0x035, 0x000201B4, ++ 0x035, 0x000281B4, ++ 0x035, 0x000301B4, ++ 0x035, 0x000401B4, ++ 0x035, 0x000481B4, ++ 0x035, 0x000501B4, ++ 0x90000008, 0x05000000, 0x40000000, 0x00000000, ++ 0x018, 0x0001712A, ++ 0x0EF, 0x00000040, ++ 0x035, 0x000001D4, ++ 0x035, 0x000081D4, ++ 0x035, 0x000101D4, ++ 0x035, 0x000201B4, ++ 0x035, 0x000281B4, ++ 0x035, 0x000301B4, ++ 0x035, 0x000401B4, ++ 0x035, 0x000481B4, ++ 0x035, 0x000501B4, ++ 0xA0000000, 0x00000000, ++ 0x018, 0x0001712A, ++ 0x0EF, 0x00000040, ++ 0x035, 0x00000188, ++ 0x035, 0x00008147, ++ 0x035, 0x00010147, ++ 0x035, 0x000201D7, ++ 0x035, 0x000281D7, ++ 0x035, 0x000301D7, ++ 0x035, 0x000401D8, ++ 0x035, 0x000481D8, ++ 0x035, 0x000501D8, ++ 0xB0000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x80000008, 0x00000000, 0x40000000, 0x00000000, ++ 0x018, 0x0001712A, ++ 0x0EF, 0x00000010, ++ 0x036, 0x00004BFB, ++ 0x036, 0x0000CBFB, ++ 0x036, 0x00014BFB, ++ 0x036, 0x0001CBFB, ++ 0x036, 0x00024F4B, ++ 0x036, 0x0002CF4B, ++ 0x036, 0x00034F4B, ++ 0x036, 0x0003CF4B, ++ 0x036, 0x00044F4B, ++ 0x036, 0x0004CF4B, ++ 0x036, 0x00054F4B, ++ 0x036, 0x0005CF4B, ++ 0x90000008, 0x05000000, 0x40000000, 0x00000000, ++ 0x018, 0x0001712A, ++ 0x0EF, 0x00000010, ++ 0x036, 0x00004BFB, ++ 0x036, 0x0000CBFB, ++ 0x036, 0x00014BFB, ++ 0x036, 0x0001CBFB, ++ 0x036, 0x00024F4B, ++ 0x036, 0x0002CF4B, ++ 0x036, 0x00034F4B, ++ 0x036, 0x0003CF4B, ++ 0x036, 0x00044F4B, ++ 0x036, 0x0004CF4B, ++ 0x036, 0x00054F4B, ++ 0x036, 0x0005CF4B, ++ 0xA0000000, 0x00000000, ++ 0x018, 0x0001712A, ++ 0x0EF, 0x00000010, ++ 0x036, 0x00084EB4, ++ 0x036, 0x0008CC35, ++ 0x036, 0x00094C35, ++ 0x036, 0x0009CC35, ++ 0x036, 0x000A4C35, ++ 0x036, 0x000ACC35, ++ 0x036, 0x000B4C35, ++ 0x036, 0x000BCC35, ++ 0x036, 0x000C4C34, ++ 0x036, 0x000CCC35, ++ 0x036, 0x000D4C35, ++ 0x036, 0x000DCC35, ++ 0xB0000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x0EF, 0x00000008, ++ 0x80000008, 0x00000000, 0x40000000, 0x00000000, ++ 0x03C, 0x000002CC, ++ 0x03C, 0x00000522, ++ 0x03C, 0x00000902, ++ 0x90000008, 0x05000000, 0x40000000, 0x00000000, ++ 0x03C, 0x000002CC, ++ 0x03C, 0x00000522, ++ 0x03C, 0x00000902, ++ 0xA0000000, 0x00000000, ++ 0x03C, 0x000002A8, ++ 0x03C, 0x000005A2, ++ 0x03C, 0x00000880, ++ 0xB0000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x018, 0x0001712A, ++ 0x0EF, 0x00000002, ++ 0x0DF, 0x00000080, ++ 0x01F, 0x00000064, ++ 0x80000008, 0x00000000, 0x40000000, 0x00000000, ++ 0x061, 0x000FDD43, ++ 0x062, 0x00038F4B, ++ 0x063, 0x00032117, ++ 0x064, 0x000194AC, ++ 0x065, 0x000931D1, ++ 0x90000008, 0x05000000, 0x40000000, 0x00000000, ++ 0x061, 0x000FDD43, ++ 0x062, 0x00038F4B, ++ 0x063, 0x00032117, ++ 0x064, 0x000194AC, ++ 0x065, 0x000931D2, ++ 0xA0000000, 0x00000000, ++ 0x061, 0x000E5D53, ++ 0x062, 0x00038FCD, ++ 0x063, 0x000114EB, ++ 0x064, 0x000196AC, ++ 0x065, 0x000911D7, ++ 0xB0000000, 0x00000000, ++ 0x008, 0x00008400, ++ 0x01C, 0x000739D2, ++ 0x0B4, 0x0001E78D, ++ 0x018, 0x0001F12A, ++ 0xFFE, 0x00000000, ++ 0xFFE, 0x00000000, ++ 0xFFE, 0x00000000, ++ 0xFFE, 0x00000000, ++ 0x0B4, 0x0001A78D, ++ 0x018, 0x0001712A, ++}; ++ ++RTW_DECL_TABLE_RF_RADIO(rtw8812a_rf_a, A); ++ ++static const u32 rtw8812a_rf_b[] = { ++ 0x056, 0x00051CF2, ++ 0x066, 0x00040000, ++ 0x089, 0x00000080, ++ 0x80000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x086, 0x00014B3A, ++ 0x90000001, 0x00000005, 0x40000000, 0x00000000, ++ 0x086, 0x00014B3A, ++ 0xA0000000, 0x00000000, ++ 0x086, 0x00014B38, ++ 0xB0000000, 0x00000000, ++ 0x80000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x08B, 0x00080180, ++ 0xA0000000, 0x00000000, ++ 0x08B, 0x00087180, ++ 0xB0000000, 0x00000000, ++ 0x018, 0x00000006, ++ 0x0EF, 0x00002000, ++ 0x80000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03B, 0x0003F218, ++ 0x03B, 0x00030A58, ++ 0x03B, 0x0002FA58, ++ 0x03B, 0x00022590, ++ 0x03B, 0x0001FA50, ++ 0x03B, 0x00010248, ++ 0x03B, 0x00008240, ++ 0x90000001, 0x00000005, 0x40000000, 0x00000000, ++ 0x03B, 0x0003F218, ++ 0x03B, 0x00030A58, ++ 0x03B, 0x0002FA58, ++ 0x03B, 0x00022590, ++ 0x03B, 0x0001FA50, ++ 0x03B, 0x00010248, ++ 0x03B, 0x00008240, ++ 0xA0000000, 0x00000000, ++ 0x03B, 0x00038A58, ++ 0x03B, 0x00037A58, ++ 0x03B, 0x0002A590, ++ 0x03B, 0x00027A50, ++ 0x03B, 0x00018248, ++ 0x03B, 0x00010240, ++ 0x03B, 0x00008240, ++ 0xB0000000, 0x00000000, ++ 0x0EF, 0x00000100, ++ 0x80000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x0000A4EE, ++ 0x034, 0x00009076, ++ 0x034, 0x00008073, ++ 0x034, 0x00007070, ++ 0x034, 0x0000606D, ++ 0x034, 0x0000506A, ++ 0x034, 0x00004049, ++ 0x034, 0x00003046, ++ 0x034, 0x00002028, ++ 0x034, 0x00001025, ++ 0x034, 0x00000022, ++ 0xA0000000, 0x00000000, ++ 0x034, 0x0000ADF4, ++ 0x034, 0x00009DF1, ++ 0x034, 0x00008DEE, ++ 0x034, 0x00007DEB, ++ 0x034, 0x00006DE8, ++ 0x034, 0x00005DE5, ++ 0x034, 0x00004DE2, ++ 0x034, 0x00003CE6, ++ 0x034, 0x000024E7, ++ 0x034, 0x000014E4, ++ 0x034, 0x000004E1, ++ 0xB0000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x0EF, 0x000020A2, ++ 0x0DF, 0x00000080, ++ 0x035, 0x00000192, ++ 0x035, 0x00008192, ++ 0x035, 0x00010192, ++ 0x036, 0x00000024, ++ 0x036, 0x00008024, ++ 0x036, 0x00010024, ++ 0x036, 0x00018024, ++ 0x0EF, 0x00000000, ++ 0x051, 0x00000C21, ++ 0x052, 0x000006D9, ++ 0x053, 0x000FC649, ++ 0x054, 0x0000017E, ++ 0x0EF, 0x00000002, ++ 0x008, 0x00008400, ++ 0x018, 0x0001712A, ++ 0x0EF, 0x00001000, ++ 0x03A, 0x00000080, ++ 0x03B, 0x0003A02C, ++ 0x03C, 0x00004000, ++ 0x03A, 0x00000400, ++ 0x03B, 0x0003202C, ++ 0x03C, 0x00010000, ++ 0x03A, 0x000000A0, ++ 0x03B, 0x0002B064, ++ 0x03C, 0x00004000, ++ 0x03A, 0x000000D8, ++ 0x03B, 0x00023070, ++ 0x03C, 0x00004000, ++ 0x03A, 0x00000468, ++ 0x03B, 0x0001B870, ++ 0x03C, 0x00010000, ++ 0x03A, 0x00000098, ++ 0x03B, 0x00012085, ++ 0x03C, 0x000E4000, ++ 0x03A, 0x00000418, ++ 0x03B, 0x0000A080, ++ 0x03C, 0x000F0000, ++ 0x03A, 0x00000418, ++ 0x03B, 0x00002080, ++ 0x03C, 0x00010000, ++ 0x03A, 0x00000080, ++ 0x03B, 0x0007A02C, ++ 0x03C, 0x00004000, ++ 0x03A, 0x00000400, ++ 0x03B, 0x0007202C, ++ 0x03C, 0x00010000, ++ 0x03A, 0x000000A0, ++ 0x03B, 0x0006B064, ++ 0x03C, 0x00004000, ++ 0x03A, 0x000000D8, ++ 0x03B, 0x00063070, ++ 0x03C, 0x00004000, ++ 0x03A, 0x00000468, ++ 0x03B, 0x0005B870, ++ 0x03C, 0x00010000, ++ 0x03A, 0x00000098, ++ 0x03B, 0x00052085, ++ 0x03C, 0x000E4000, ++ 0x03A, 0x00000418, ++ 0x03B, 0x0004A080, ++ 0x03C, 0x000F0000, ++ 0x03A, 0x00000418, ++ 0x03B, 0x00042080, ++ 0x03C, 0x00010000, ++ 0x03A, 0x00000080, ++ 0x03B, 0x000BA02C, ++ 0x03C, 0x00004000, ++ 0x03A, 0x00000400, ++ 0x03B, 0x000B202C, ++ 0x03C, 0x00010000, ++ 0x03A, 0x000000A0, ++ 0x03B, 0x000AB064, ++ 0x03C, 0x00004000, ++ 0x03A, 0x000000D8, ++ 0x03B, 0x000A3070, ++ 0x03C, 0x00004000, ++ 0x03A, 0x00000468, ++ 0x03B, 0x0009B870, ++ 0x03C, 0x00010000, ++ 0x03A, 0x00000098, ++ 0x03B, 0x00092085, ++ 0x03C, 0x000E4000, ++ 0x03A, 0x00000418, ++ 0x03B, 0x0008A080, ++ 0x03C, 0x000F0000, ++ 0x03A, 0x00000418, ++ 0x03B, 0x00082080, ++ 0x03C, 0x00010000, ++ 0x0EF, 0x00001100, ++ 0x80000008, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x0004A0B2, ++ 0x034, 0x000490AF, ++ 0x034, 0x00048070, ++ 0x034, 0x0004706D, ++ 0x034, 0x00046050, ++ 0x034, 0x0004504D, ++ 0x034, 0x0004404A, ++ 0x034, 0x00043047, ++ 0x034, 0x0004200A, ++ 0x034, 0x00041007, ++ 0x034, 0x00040004, ++ 0x90000008, 0x05000000, 0x40000000, 0x00000000, ++ 0x034, 0x0004A0B1, ++ 0x034, 0x000490AE, ++ 0x034, 0x0004806F, ++ 0x034, 0x0004706C, ++ 0x034, 0x0004604C, ++ 0x034, 0x00045049, ++ 0x034, 0x00044046, ++ 0x034, 0x00043043, ++ 0x034, 0x00042006, ++ 0x034, 0x00041003, ++ 0x034, 0x00040000, ++ 0xA0000000, 0x00000000, ++ 0x034, 0x0004ADF5, ++ 0x034, 0x00049DF2, ++ 0x034, 0x00048DEF, ++ 0x034, 0x00047DEC, ++ 0x034, 0x00046DE9, ++ 0x034, 0x00045DE6, ++ 0x034, 0x00044DE3, ++ 0x034, 0x000438C8, ++ 0x034, 0x000428C5, ++ 0x034, 0x000418C2, ++ 0x034, 0x000408C0, ++ 0xB0000000, 0x00000000, ++ 0x80000008, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x0002A0B2, ++ 0x034, 0x000290AF, ++ 0x034, 0x00028070, ++ 0x034, 0x0002706D, ++ 0x034, 0x00026050, ++ 0x034, 0x0002504D, ++ 0x034, 0x0002404A, ++ 0x034, 0x00023047, ++ 0x034, 0x0002200A, ++ 0x034, 0x00021007, ++ 0x034, 0x00020004, ++ 0x90000008, 0x05000000, 0x40000000, 0x00000000, ++ 0x034, 0x0002A0B3, ++ 0x034, 0x000290B0, ++ 0x034, 0x00028071, ++ 0x034, 0x0002706E, ++ 0x034, 0x0002604E, ++ 0x034, 0x0002504B, ++ 0x034, 0x00024048, ++ 0x034, 0x00023045, ++ 0x034, 0x00022008, ++ 0x034, 0x00021005, ++ 0x034, 0x00020002, ++ 0xA0000000, 0x00000000, ++ 0x034, 0x0002ADF5, ++ 0x034, 0x00029DF2, ++ 0x034, 0x00028DEF, ++ 0x034, 0x00027DEC, ++ 0x034, 0x00026DE9, ++ 0x034, 0x00025DE6, ++ 0x034, 0x00024DE3, ++ 0x034, 0x000238C8, ++ 0x034, 0x000228C5, ++ 0x034, 0x000218C2, ++ 0x034, 0x000208C0, ++ 0xB0000000, 0x00000000, ++ 0x80000008, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x0000A0B2, ++ 0x034, 0x000090AF, ++ 0x034, 0x00008070, ++ 0x034, 0x0000706D, ++ 0x034, 0x00006050, ++ 0x034, 0x0000504D, ++ 0x034, 0x0000404A, ++ 0x034, 0x00003047, ++ 0x034, 0x0000200A, ++ 0x034, 0x00001007, ++ 0x034, 0x00000004, ++ 0x90000008, 0x05000000, 0x40000000, 0x00000000, ++ 0x034, 0x0000A0B3, ++ 0x034, 0x000090B0, ++ 0x034, 0x00008070, ++ 0x034, 0x0000706D, ++ 0x034, 0x0000604D, ++ 0x034, 0x0000504A, ++ 0x034, 0x00004047, ++ 0x034, 0x00003044, ++ 0x034, 0x00002007, ++ 0x034, 0x00001004, ++ 0x034, 0x00000001, ++ 0xA0000000, 0x00000000, ++ 0x034, 0x0000AFF7, ++ 0x034, 0x00009DF7, ++ 0x034, 0x00008DF4, ++ 0x034, 0x00007DF1, ++ 0x034, 0x00006DEE, ++ 0x034, 0x00005DEB, ++ 0x034, 0x00004DE8, ++ 0x034, 0x000038CC, ++ 0x034, 0x000028C9, ++ 0x034, 0x000018C6, ++ 0x034, 0x000008C3, ++ 0xB0000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x80000008, 0x00000000, 0x40000000, 0x00000000, ++ 0x018, 0x0001712A, ++ 0x0EF, 0x00000040, ++ 0x035, 0x000001C5, ++ 0x035, 0x000081C5, ++ 0x035, 0x000101C5, ++ 0x035, 0x00020174, ++ 0x035, 0x00028174, ++ 0x035, 0x00030174, ++ 0x035, 0x00040185, ++ 0x035, 0x00048185, ++ 0x035, 0x00050185, ++ 0x0EF, 0x00000000, ++ 0x90000008, 0x05000000, 0x40000000, 0x00000000, ++ 0x018, 0x0001712A, ++ 0x0EF, 0x00000040, ++ 0x035, 0x000001C5, ++ 0x035, 0x000081C5, ++ 0x035, 0x000101C5, ++ 0x035, 0x00020174, ++ 0x035, 0x00028174, ++ 0x035, 0x00030174, ++ 0x035, 0x00040185, ++ 0x035, 0x00048185, ++ 0x035, 0x00050185, ++ 0x0EF, 0x00000000, ++ 0xA0000000, 0x00000000, ++ 0x018, 0x0001712A, ++ 0x0EF, 0x00000040, ++ 0x035, 0x00000188, ++ 0x035, 0x00008147, ++ 0x035, 0x00010147, ++ 0x035, 0x000201D7, ++ 0x035, 0x000281D7, ++ 0x035, 0x000301D7, ++ 0x035, 0x000401D8, ++ 0x035, 0x000481D8, ++ 0x035, 0x000501D8, ++ 0x0EF, 0x00000000, ++ 0xB0000000, 0x00000000, ++ 0x80000008, 0x00000000, 0x40000000, 0x00000000, ++ 0x018, 0x0001712A, ++ 0x0EF, 0x00000010, ++ 0x036, 0x00005B8B, ++ 0x036, 0x0000DB8B, ++ 0x036, 0x00015B8B, ++ 0x036, 0x0001DB8B, ++ 0x036, 0x000262DB, ++ 0x036, 0x0002E2DB, ++ 0x036, 0x000362DB, ++ 0x036, 0x0003E2DB, ++ 0x036, 0x0004553B, ++ 0x036, 0x0004D53B, ++ 0x036, 0x0005553B, ++ 0x036, 0x0005D53B, ++ 0x90000008, 0x05000000, 0x40000000, 0x00000000, ++ 0x018, 0x0001712A, ++ 0x0EF, 0x00000010, ++ 0x036, 0x00005B8B, ++ 0x036, 0x0000DB8B, ++ 0x036, 0x00015B8B, ++ 0x036, 0x0001DB8B, ++ 0x036, 0x000262DB, ++ 0x036, 0x0002E2DB, ++ 0x036, 0x000362DB, ++ 0x036, 0x0003E2DB, ++ 0x036, 0x0004553B, ++ 0x036, 0x0004D53B, ++ 0x036, 0x0005553B, ++ 0x036, 0x0005D53B, ++ 0xA0000000, 0x00000000, ++ 0x018, 0x0001712A, ++ 0x0EF, 0x00000010, ++ 0x036, 0x00084EB4, ++ 0x036, 0x0008CC35, ++ 0x036, 0x00094C35, ++ 0x036, 0x0009CC35, ++ 0x036, 0x000A4C35, ++ 0x036, 0x000ACC35, ++ 0x036, 0x000B4C35, ++ 0x036, 0x000BCC35, ++ 0x036, 0x000C4C34, ++ 0x036, 0x000CCC35, ++ 0x036, 0x000D4C35, ++ 0x036, 0x000DCC35, ++ 0xB0000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x0EF, 0x00000008, ++ 0x80000008, 0x00000000, 0x40000000, 0x00000000, ++ 0x03C, 0x000002DC, ++ 0x03C, 0x00000524, ++ 0x03C, 0x00000902, ++ 0x90000008, 0x05000000, 0x40000000, 0x00000000, ++ 0x03C, 0x000002DC, ++ 0x03C, 0x00000524, ++ 0x03C, 0x00000902, ++ 0xA0000000, 0x00000000, ++ 0x03C, 0x000002A8, ++ 0x03C, 0x000005A2, ++ 0x03C, 0x00000880, ++ 0xB0000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x018, 0x0001712A, ++ 0x0EF, 0x00000002, ++ 0x0DF, 0x00000080, ++ 0x80000008, 0x00000000, 0x40000000, 0x00000000, ++ 0x061, 0x000EAC43, ++ 0x062, 0x00038F47, ++ 0x063, 0x00031157, ++ 0x064, 0x0001C4AC, ++ 0x065, 0x000931D1, ++ 0x90000008, 0x05000000, 0x40000000, 0x00000000, ++ 0x061, 0x000EAC43, ++ 0x062, 0x00038F47, ++ 0x063, 0x00031157, ++ 0x064, 0x0001C4AC, ++ 0x065, 0x000931D2, ++ 0x90000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x061, 0x000EAC43, ++ 0x062, 0x00038F47, ++ 0x063, 0x00031157, ++ 0x064, 0x0001C4AC, ++ 0x065, 0x000931D1, ++ 0xA0000000, 0x00000000, ++ 0x061, 0x000E5D53, ++ 0x062, 0x00038FCD, ++ 0x063, 0x000114EB, ++ 0x064, 0x000196AC, ++ 0x065, 0x000911D7, ++ 0xB0000000, 0x00000000, ++ 0x008, 0x00008400, ++}; ++ ++RTW_DECL_TABLE_RF_RADIO(rtw8812a_rf_b, B); ++ ++static const struct rtw_txpwr_lmt_cfg_pair rtw8812a_txpwr_lmt[] = { ++ { 0, 0, 0, 0, 1, 36, }, ++ { 2, 0, 0, 0, 1, 32, }, ++ { 1, 0, 0, 0, 1, 32, }, ++ { 0, 0, 0, 0, 2, 36, }, ++ { 2, 0, 0, 0, 2, 32, }, ++ { 1, 0, 0, 0, 2, 32, }, ++ { 0, 0, 0, 0, 3, 36, }, ++ { 2, 0, 0, 0, 3, 32, }, ++ { 1, 0, 0, 0, 3, 32, }, ++ { 0, 0, 0, 0, 4, 36, }, ++ { 2, 0, 0, 0, 4, 32, }, ++ { 1, 0, 0, 0, 4, 32, }, ++ { 0, 0, 0, 0, 5, 36, }, ++ { 2, 0, 0, 0, 5, 32, }, ++ { 1, 0, 0, 0, 5, 32, }, ++ { 0, 0, 0, 0, 6, 36, }, ++ { 2, 0, 0, 0, 6, 32, }, ++ { 1, 0, 0, 0, 6, 32, }, ++ { 0, 0, 0, 0, 7, 36, }, ++ { 2, 0, 0, 0, 7, 32, }, ++ { 1, 0, 0, 0, 7, 32, }, ++ { 0, 0, 0, 0, 8, 36, }, ++ { 2, 0, 0, 0, 8, 32, }, ++ { 1, 0, 0, 0, 8, 32, }, ++ { 0, 0, 0, 0, 9, 36, }, ++ { 2, 0, 0, 0, 9, 32, }, ++ { 1, 0, 0, 0, 9, 32, }, ++ { 0, 0, 0, 0, 10, 36, }, ++ { 2, 0, 0, 0, 10, 32, }, ++ { 1, 0, 0, 0, 10, 32, }, ++ { 0, 0, 0, 0, 11, 36, }, ++ { 2, 0, 0, 0, 11, 32, }, ++ { 1, 0, 0, 0, 11, 32, }, ++ { 0, 0, 0, 0, 12, 63, }, ++ { 2, 0, 0, 0, 12, 32, }, ++ { 1, 0, 0, 0, 12, 32, }, ++ { 0, 0, 0, 0, 13, 63, }, ++ { 2, 0, 0, 0, 13, 32, }, ++ { 1, 0, 0, 0, 13, 32, }, ++ { 0, 0, 0, 0, 14, 63, }, ++ { 2, 0, 0, 0, 14, 63, }, ++ { 1, 0, 0, 0, 14, 32, }, ++ { 0, 0, 0, 1, 1, 34, }, ++ { 2, 0, 0, 1, 1, 32, }, ++ { 1, 0, 0, 1, 1, 32, }, ++ { 0, 0, 0, 1, 2, 36, }, ++ { 2, 0, 0, 1, 2, 32, }, ++ { 1, 0, 0, 1, 2, 32, }, ++ { 0, 0, 0, 1, 3, 36, }, ++ { 2, 0, 0, 1, 3, 32, }, ++ { 1, 0, 0, 1, 3, 32, }, ++ { 0, 0, 0, 1, 4, 36, }, ++ { 2, 0, 0, 1, 4, 32, }, ++ { 1, 0, 0, 1, 4, 32, }, ++ { 0, 0, 0, 1, 5, 36, }, ++ { 2, 0, 0, 1, 5, 32, }, ++ { 1, 0, 0, 1, 5, 32, }, ++ { 0, 0, 0, 1, 6, 36, }, ++ { 2, 0, 0, 1, 6, 32, }, ++ { 1, 0, 0, 1, 6, 32, }, ++ { 0, 0, 0, 1, 7, 36, }, ++ { 2, 0, 0, 1, 7, 32, }, ++ { 1, 0, 0, 1, 7, 32, }, ++ { 0, 0, 0, 1, 8, 36, }, ++ { 2, 0, 0, 1, 8, 32, }, ++ { 1, 0, 0, 1, 8, 32, }, ++ { 0, 0, 0, 1, 9, 36, }, ++ { 2, 0, 0, 1, 9, 32, }, ++ { 1, 0, 0, 1, 9, 32, }, ++ { 0, 0, 0, 1, 10, 36, }, ++ { 2, 0, 0, 1, 10, 32, }, ++ { 1, 0, 0, 1, 10, 32, }, ++ { 0, 0, 0, 1, 11, 32, }, ++ { 2, 0, 0, 1, 11, 32, }, ++ { 1, 0, 0, 1, 11, 32, }, ++ { 0, 0, 0, 1, 12, 63, }, ++ { 2, 0, 0, 1, 12, 32, }, ++ { 1, 0, 0, 1, 12, 32, }, ++ { 0, 0, 0, 1, 13, 63, }, ++ { 2, 0, 0, 1, 13, 32, }, ++ { 1, 0, 0, 1, 13, 32, }, ++ { 0, 0, 0, 1, 14, 63, }, ++ { 2, 0, 0, 1, 14, 63, }, ++ { 1, 0, 0, 1, 14, 63, }, ++ { 0, 0, 0, 2, 1, 34, }, ++ { 2, 0, 0, 2, 1, 32, }, ++ { 1, 0, 0, 2, 1, 32, }, ++ { 0, 0, 0, 2, 2, 36, }, ++ { 2, 0, 0, 2, 2, 32, }, ++ { 1, 0, 0, 2, 2, 32, }, ++ { 0, 0, 0, 2, 3, 36, }, ++ { 2, 0, 0, 2, 3, 32, }, ++ { 1, 0, 0, 2, 3, 32, }, ++ { 0, 0, 0, 2, 4, 36, }, ++ { 2, 0, 0, 2, 4, 32, }, ++ { 1, 0, 0, 2, 4, 32, }, ++ { 0, 0, 0, 2, 5, 36, }, ++ { 2, 0, 0, 2, 5, 32, }, ++ { 1, 0, 0, 2, 5, 32, }, ++ { 0, 0, 0, 2, 6, 36, }, ++ { 2, 0, 0, 2, 6, 32, }, ++ { 1, 0, 0, 2, 6, 32, }, ++ { 0, 0, 0, 2, 7, 36, }, ++ { 2, 0, 0, 2, 7, 32, }, ++ { 1, 0, 0, 2, 7, 32, }, ++ { 0, 0, 0, 2, 8, 36, }, ++ { 2, 0, 0, 2, 8, 32, }, ++ { 1, 0, 0, 2, 8, 32, }, ++ { 0, 0, 0, 2, 9, 36, }, ++ { 2, 0, 0, 2, 9, 32, }, ++ { 1, 0, 0, 2, 9, 32, }, ++ { 0, 0, 0, 2, 10, 36, }, ++ { 2, 0, 0, 2, 10, 32, }, ++ { 1, 0, 0, 2, 10, 32, }, ++ { 0, 0, 0, 2, 11, 32, }, ++ { 2, 0, 0, 2, 11, 32, }, ++ { 1, 0, 0, 2, 11, 32, }, ++ { 0, 0, 0, 2, 12, 63, }, ++ { 2, 0, 0, 2, 12, 32, }, ++ { 1, 0, 0, 2, 12, 32, }, ++ { 0, 0, 0, 2, 13, 63, }, ++ { 2, 0, 0, 2, 13, 32, }, ++ { 1, 0, 0, 2, 13, 32, }, ++ { 0, 0, 0, 2, 14, 63, }, ++ { 2, 0, 0, 2, 14, 63, }, ++ { 1, 0, 0, 2, 14, 63, }, ++ { 0, 0, 0, 3, 1, 32, }, ++ { 2, 0, 0, 3, 1, 32, }, ++ { 1, 0, 0, 3, 1, 32, }, ++ { 0, 0, 0, 3, 2, 34, }, ++ { 2, 0, 0, 3, 2, 32, }, ++ { 1, 0, 0, 3, 2, 32, }, ++ { 0, 0, 0, 3, 3, 34, }, ++ { 2, 0, 0, 3, 3, 32, }, ++ { 1, 0, 0, 3, 3, 32, }, ++ { 0, 0, 0, 3, 4, 34, }, ++ { 2, 0, 0, 3, 4, 32, }, ++ { 1, 0, 0, 3, 4, 32, }, ++ { 0, 0, 0, 3, 5, 34, }, ++ { 2, 0, 0, 3, 5, 32, }, ++ { 1, 0, 0, 3, 5, 32, }, ++ { 0, 0, 0, 3, 6, 34, }, ++ { 2, 0, 0, 3, 6, 32, }, ++ { 1, 0, 0, 3, 6, 32, }, ++ { 0, 0, 0, 3, 7, 34, }, ++ { 2, 0, 0, 3, 7, 32, }, ++ { 1, 0, 0, 3, 7, 32, }, ++ { 0, 0, 0, 3, 8, 34, }, ++ { 2, 0, 0, 3, 8, 32, }, ++ { 1, 0, 0, 3, 8, 32, }, ++ { 0, 0, 0, 3, 9, 34, }, ++ { 2, 0, 0, 3, 9, 32, }, ++ { 1, 0, 0, 3, 9, 32, }, ++ { 0, 0, 0, 3, 10, 34, }, ++ { 2, 0, 0, 3, 10, 32, }, ++ { 1, 0, 0, 3, 10, 32, }, ++ { 0, 0, 0, 3, 11, 30, }, ++ { 2, 0, 0, 3, 11, 32, }, ++ { 1, 0, 0, 3, 11, 32, }, ++ { 0, 0, 0, 3, 12, 63, }, ++ { 2, 0, 0, 3, 12, 32, }, ++ { 1, 0, 0, 3, 12, 32, }, ++ { 0, 0, 0, 3, 13, 63, }, ++ { 2, 0, 0, 3, 13, 32, }, ++ { 1, 0, 0, 3, 13, 32, }, ++ { 0, 0, 0, 3, 14, 63, }, ++ { 2, 0, 0, 3, 14, 63, }, ++ { 1, 0, 0, 3, 14, 63, }, ++ { 0, 0, 1, 2, 1, 63, }, ++ { 2, 0, 1, 2, 1, 63, }, ++ { 1, 0, 1, 2, 1, 63, }, ++ { 0, 0, 1, 2, 2, 63, }, ++ { 2, 0, 1, 2, 2, 63, }, ++ { 1, 0, 1, 2, 2, 63, }, ++ { 0, 0, 1, 2, 3, 32, }, ++ { 2, 0, 1, 2, 3, 32, }, ++ { 1, 0, 1, 2, 3, 32, }, ++ { 0, 0, 1, 2, 4, 36, }, ++ { 2, 0, 1, 2, 4, 32, }, ++ { 1, 0, 1, 2, 4, 32, }, ++ { 0, 0, 1, 2, 5, 36, }, ++ { 2, 0, 1, 2, 5, 32, }, ++ { 1, 0, 1, 2, 5, 32, }, ++ { 0, 0, 1, 2, 6, 36, }, ++ { 2, 0, 1, 2, 6, 32, }, ++ { 1, 0, 1, 2, 6, 32, }, ++ { 0, 0, 1, 2, 7, 36, }, ++ { 2, 0, 1, 2, 7, 32, }, ++ { 1, 0, 1, 2, 7, 32, }, ++ { 0, 0, 1, 2, 8, 36, }, ++ { 2, 0, 1, 2, 8, 32, }, ++ { 1, 0, 1, 2, 8, 32, }, ++ { 0, 0, 1, 2, 9, 36, }, ++ { 2, 0, 1, 2, 9, 32, }, ++ { 1, 0, 1, 2, 9, 32, }, ++ { 0, 0, 1, 2, 10, 36, }, ++ { 2, 0, 1, 2, 10, 32, }, ++ { 1, 0, 1, 2, 10, 32, }, ++ { 0, 0, 1, 2, 11, 32, }, ++ { 2, 0, 1, 2, 11, 32, }, ++ { 1, 0, 1, 2, 11, 32, }, ++ { 0, 0, 1, 2, 12, 63, }, ++ { 2, 0, 1, 2, 12, 32, }, ++ { 1, 0, 1, 2, 12, 32, }, ++ { 0, 0, 1, 2, 13, 63, }, ++ { 2, 0, 1, 2, 13, 32, }, ++ { 1, 0, 1, 2, 13, 32, }, ++ { 0, 0, 1, 2, 14, 63, }, ++ { 2, 0, 1, 2, 14, 63, }, ++ { 1, 0, 1, 2, 14, 63, }, ++ { 0, 0, 1, 3, 1, 63, }, ++ { 2, 0, 1, 3, 1, 63, }, ++ { 1, 0, 1, 3, 1, 63, }, ++ { 0, 0, 1, 3, 2, 63, }, ++ { 2, 0, 1, 3, 2, 63, }, ++ { 1, 0, 1, 3, 2, 63, }, ++ { 0, 0, 1, 3, 3, 30, }, ++ { 2, 0, 1, 3, 3, 30, }, ++ { 1, 0, 1, 3, 3, 30, }, ++ { 0, 0, 1, 3, 4, 34, }, ++ { 2, 0, 1, 3, 4, 30, }, ++ { 1, 0, 1, 3, 4, 30, }, ++ { 0, 0, 1, 3, 5, 34, }, ++ { 2, 0, 1, 3, 5, 30, }, ++ { 1, 0, 1, 3, 5, 30, }, ++ { 0, 0, 1, 3, 6, 34, }, ++ { 2, 0, 1, 3, 6, 30, }, ++ { 1, 0, 1, 3, 6, 30, }, ++ { 0, 0, 1, 3, 7, 34, }, ++ { 2, 0, 1, 3, 7, 30, }, ++ { 1, 0, 1, 3, 7, 30, }, ++ { 0, 0, 1, 3, 8, 34, }, ++ { 2, 0, 1, 3, 8, 30, }, ++ { 1, 0, 1, 3, 8, 30, }, ++ { 0, 0, 1, 3, 9, 34, }, ++ { 2, 0, 1, 3, 9, 30, }, ++ { 1, 0, 1, 3, 9, 30, }, ++ { 0, 0, 1, 3, 10, 34, }, ++ { 2, 0, 1, 3, 10, 30, }, ++ { 1, 0, 1, 3, 10, 30, }, ++ { 0, 0, 1, 3, 11, 30, }, ++ { 2, 0, 1, 3, 11, 30, }, ++ { 1, 0, 1, 3, 11, 30, }, ++ { 0, 0, 1, 3, 12, 63, }, ++ { 2, 0, 1, 3, 12, 32, }, ++ { 1, 0, 1, 3, 12, 32, }, ++ { 0, 0, 1, 3, 13, 63, }, ++ { 2, 0, 1, 3, 13, 32, }, ++ { 1, 0, 1, 3, 13, 32, }, ++ { 0, 0, 1, 3, 14, 63, }, ++ { 2, 0, 1, 3, 14, 63, }, ++ { 1, 0, 1, 3, 14, 63, }, ++ { 0, 1, 0, 1, 36, 30, }, ++ { 2, 1, 0, 1, 36, 32, }, ++ { 1, 1, 0, 1, 36, 32, }, ++ { 0, 1, 0, 1, 40, 30, }, ++ { 2, 1, 0, 1, 40, 32, }, ++ { 1, 1, 0, 1, 40, 32, }, ++ { 0, 1, 0, 1, 44, 30, }, ++ { 2, 1, 0, 1, 44, 32, }, ++ { 1, 1, 0, 1, 44, 32, }, ++ { 0, 1, 0, 1, 48, 30, }, ++ { 2, 1, 0, 1, 48, 32, }, ++ { 1, 1, 0, 1, 48, 32, }, ++ { 0, 1, 0, 1, 52, 36, }, ++ { 2, 1, 0, 1, 52, 32, }, ++ { 1, 1, 0, 1, 52, 32, }, ++ { 0, 1, 0, 1, 56, 34, }, ++ { 2, 1, 0, 1, 56, 32, }, ++ { 1, 1, 0, 1, 56, 32, }, ++ { 0, 1, 0, 1, 60, 32, }, ++ { 2, 1, 0, 1, 60, 32, }, ++ { 1, 1, 0, 1, 60, 32, }, ++ { 0, 1, 0, 1, 64, 28, }, ++ { 2, 1, 0, 1, 64, 32, }, ++ { 1, 1, 0, 1, 64, 32, }, ++ { 0, 1, 0, 1, 100, 30, }, ++ { 2, 1, 0, 1, 100, 32, }, ++ { 1, 1, 0, 1, 100, 32, }, ++ { 0, 1, 0, 1, 104, 30, }, ++ { 2, 1, 0, 1, 104, 32, }, ++ { 1, 1, 0, 1, 104, 32, }, ++ { 0, 1, 0, 1, 108, 32, }, ++ { 2, 1, 0, 1, 108, 32, }, ++ { 1, 1, 0, 1, 108, 32, }, ++ { 0, 1, 0, 1, 112, 34, }, ++ { 2, 1, 0, 1, 112, 32, }, ++ { 1, 1, 0, 1, 112, 32, }, ++ { 0, 1, 0, 1, 116, 34, }, ++ { 2, 1, 0, 1, 116, 32, }, ++ { 1, 1, 0, 1, 116, 32, }, ++ { 0, 1, 0, 1, 120, 36, }, ++ { 2, 1, 0, 1, 120, 32, }, ++ { 1, 1, 0, 1, 120, 32, }, ++ { 0, 1, 0, 1, 124, 34, }, ++ { 2, 1, 0, 1, 124, 32, }, ++ { 1, 1, 0, 1, 124, 32, }, ++ { 0, 1, 0, 1, 128, 32, }, ++ { 2, 1, 0, 1, 128, 32, }, ++ { 1, 1, 0, 1, 128, 32, }, ++ { 0, 1, 0, 1, 132, 30, }, ++ { 2, 1, 0, 1, 132, 32, }, ++ { 1, 1, 0, 1, 132, 32, }, ++ { 0, 1, 0, 1, 136, 30, }, ++ { 2, 1, 0, 1, 136, 32, }, ++ { 1, 1, 0, 1, 136, 32, }, ++ { 0, 1, 0, 1, 140, 28, }, ++ { 2, 1, 0, 1, 140, 32, }, ++ { 1, 1, 0, 1, 140, 32, }, ++ { 0, 1, 0, 1, 149, 36, }, ++ { 2, 1, 0, 1, 149, 32, }, ++ { 1, 1, 0, 1, 149, 63, }, ++ { 0, 1, 0, 1, 153, 36, }, ++ { 2, 1, 0, 1, 153, 32, }, ++ { 1, 1, 0, 1, 153, 63, }, ++ { 0, 1, 0, 1, 157, 36, }, ++ { 2, 1, 0, 1, 157, 32, }, ++ { 1, 1, 0, 1, 157, 63, }, ++ { 0, 1, 0, 1, 161, 36, }, ++ { 2, 1, 0, 1, 161, 32, }, ++ { 1, 1, 0, 1, 161, 63, }, ++ { 0, 1, 0, 1, 165, 36, }, ++ { 2, 1, 0, 1, 165, 32, }, ++ { 1, 1, 0, 1, 165, 63, }, ++ { 0, 1, 0, 2, 36, 30, }, ++ { 2, 1, 0, 2, 36, 32, }, ++ { 1, 1, 0, 2, 36, 32, }, ++ { 0, 1, 0, 2, 40, 30, }, ++ { 2, 1, 0, 2, 40, 32, }, ++ { 1, 1, 0, 2, 40, 32, }, ++ { 0, 1, 0, 2, 44, 30, }, ++ { 2, 1, 0, 2, 44, 32, }, ++ { 1, 1, 0, 2, 44, 32, }, ++ { 0, 1, 0, 2, 48, 30, }, ++ { 2, 1, 0, 2, 48, 32, }, ++ { 1, 1, 0, 2, 48, 32, }, ++ { 0, 1, 0, 2, 52, 36, }, ++ { 2, 1, 0, 2, 52, 32, }, ++ { 1, 1, 0, 2, 52, 32, }, ++ { 0, 1, 0, 2, 56, 34, }, ++ { 2, 1, 0, 2, 56, 32, }, ++ { 1, 1, 0, 2, 56, 32, }, ++ { 0, 1, 0, 2, 60, 32, }, ++ { 2, 1, 0, 2, 60, 32, }, ++ { 1, 1, 0, 2, 60, 32, }, ++ { 0, 1, 0, 2, 64, 28, }, ++ { 2, 1, 0, 2, 64, 32, }, ++ { 1, 1, 0, 2, 64, 32, }, ++ { 0, 1, 0, 2, 100, 30, }, ++ { 2, 1, 0, 2, 100, 32, }, ++ { 1, 1, 0, 2, 100, 32, }, ++ { 0, 1, 0, 2, 104, 30, }, ++ { 2, 1, 0, 2, 104, 32, }, ++ { 1, 1, 0, 2, 104, 32, }, ++ { 0, 1, 0, 2, 108, 32, }, ++ { 2, 1, 0, 2, 108, 32, }, ++ { 1, 1, 0, 2, 108, 32, }, ++ { 0, 1, 0, 2, 112, 34, }, ++ { 2, 1, 0, 2, 112, 32, }, ++ { 1, 1, 0, 2, 112, 32, }, ++ { 0, 1, 0, 2, 116, 34, }, ++ { 2, 1, 0, 2, 116, 32, }, ++ { 1, 1, 0, 2, 116, 32, }, ++ { 0, 1, 0, 2, 120, 36, }, ++ { 2, 1, 0, 2, 120, 32, }, ++ { 1, 1, 0, 2, 120, 32, }, ++ { 0, 1, 0, 2, 124, 34, }, ++ { 2, 1, 0, 2, 124, 32, }, ++ { 1, 1, 0, 2, 124, 32, }, ++ { 0, 1, 0, 2, 128, 32, }, ++ { 2, 1, 0, 2, 128, 32, }, ++ { 1, 1, 0, 2, 128, 32, }, ++ { 0, 1, 0, 2, 132, 30, }, ++ { 2, 1, 0, 2, 132, 32, }, ++ { 1, 1, 0, 2, 132, 32, }, ++ { 0, 1, 0, 2, 136, 30, }, ++ { 2, 1, 0, 2, 136, 32, }, ++ { 1, 1, 0, 2, 136, 32, }, ++ { 0, 1, 0, 2, 140, 28, }, ++ { 2, 1, 0, 2, 140, 32, }, ++ { 1, 1, 0, 2, 140, 32, }, ++ { 0, 1, 0, 2, 149, 36, }, ++ { 2, 1, 0, 2, 149, 32, }, ++ { 1, 1, 0, 2, 149, 63, }, ++ { 0, 1, 0, 2, 153, 36, }, ++ { 2, 1, 0, 2, 153, 32, }, ++ { 1, 1, 0, 2, 153, 63, }, ++ { 0, 1, 0, 2, 157, 36, }, ++ { 2, 1, 0, 2, 157, 32, }, ++ { 1, 1, 0, 2, 157, 63, }, ++ { 0, 1, 0, 2, 161, 36, }, ++ { 2, 1, 0, 2, 161, 32, }, ++ { 1, 1, 0, 2, 161, 63, }, ++ { 0, 1, 0, 2, 165, 36, }, ++ { 2, 1, 0, 2, 165, 32, }, ++ { 1, 1, 0, 2, 165, 63, }, ++ { 0, 1, 0, 3, 36, 28, }, ++ { 2, 1, 0, 3, 36, 30, }, ++ { 1, 1, 0, 3, 36, 30, }, ++ { 0, 1, 0, 3, 40, 28, }, ++ { 2, 1, 0, 3, 40, 30, }, ++ { 1, 1, 0, 3, 40, 30, }, ++ { 0, 1, 0, 3, 44, 28, }, ++ { 2, 1, 0, 3, 44, 30, }, ++ { 1, 1, 0, 3, 44, 30, }, ++ { 0, 1, 0, 3, 48, 28, }, ++ { 2, 1, 0, 3, 48, 30, }, ++ { 1, 1, 0, 3, 48, 30, }, ++ { 0, 1, 0, 3, 52, 34, }, ++ { 2, 1, 0, 3, 52, 30, }, ++ { 1, 1, 0, 3, 52, 30, }, ++ { 0, 1, 0, 3, 56, 32, }, ++ { 2, 1, 0, 3, 56, 30, }, ++ { 1, 1, 0, 3, 56, 30, }, ++ { 0, 1, 0, 3, 60, 30, }, ++ { 2, 1, 0, 3, 60, 30, }, ++ { 1, 1, 0, 3, 60, 30, }, ++ { 0, 1, 0, 3, 64, 26, }, ++ { 2, 1, 0, 3, 64, 30, }, ++ { 1, 1, 0, 3, 64, 30, }, ++ { 0, 1, 0, 3, 100, 28, }, ++ { 2, 1, 0, 3, 100, 30, }, ++ { 1, 1, 0, 3, 100, 30, }, ++ { 0, 1, 0, 3, 104, 28, }, ++ { 2, 1, 0, 3, 104, 30, }, ++ { 1, 1, 0, 3, 104, 30, }, ++ { 0, 1, 0, 3, 108, 30, }, ++ { 2, 1, 0, 3, 108, 30, }, ++ { 1, 1, 0, 3, 108, 30, }, ++ { 0, 1, 0, 3, 112, 32, }, ++ { 2, 1, 0, 3, 112, 30, }, ++ { 1, 1, 0, 3, 112, 30, }, ++ { 0, 1, 0, 3, 116, 32, }, ++ { 2, 1, 0, 3, 116, 30, }, ++ { 1, 1, 0, 3, 116, 30, }, ++ { 0, 1, 0, 3, 120, 34, }, ++ { 2, 1, 0, 3, 120, 30, }, ++ { 1, 1, 0, 3, 120, 30, }, ++ { 0, 1, 0, 3, 124, 32, }, ++ { 2, 1, 0, 3, 124, 30, }, ++ { 1, 1, 0, 3, 124, 30, }, ++ { 0, 1, 0, 3, 128, 30, }, ++ { 2, 1, 0, 3, 128, 30, }, ++ { 1, 1, 0, 3, 128, 30, }, ++ { 0, 1, 0, 3, 132, 28, }, ++ { 2, 1, 0, 3, 132, 30, }, ++ { 1, 1, 0, 3, 132, 30, }, ++ { 0, 1, 0, 3, 136, 28, }, ++ { 2, 1, 0, 3, 136, 30, }, ++ { 1, 1, 0, 3, 136, 30, }, ++ { 0, 1, 0, 3, 140, 26, }, ++ { 2, 1, 0, 3, 140, 30, }, ++ { 1, 1, 0, 3, 140, 30, }, ++ { 0, 1, 0, 3, 149, 34, }, ++ { 2, 1, 0, 3, 149, 30, }, ++ { 1, 1, 0, 3, 149, 63, }, ++ { 0, 1, 0, 3, 153, 34, }, ++ { 2, 1, 0, 3, 153, 30, }, ++ { 1, 1, 0, 3, 153, 63, }, ++ { 0, 1, 0, 3, 157, 34, }, ++ { 2, 1, 0, 3, 157, 30, }, ++ { 1, 1, 0, 3, 157, 63, }, ++ { 0, 1, 0, 3, 161, 34, }, ++ { 2, 1, 0, 3, 161, 30, }, ++ { 1, 1, 0, 3, 161, 63, }, ++ { 0, 1, 0, 3, 165, 34, }, ++ { 2, 1, 0, 3, 165, 30, }, ++ { 1, 1, 0, 3, 165, 63, }, ++ { 0, 1, 1, 2, 38, 30, }, ++ { 2, 1, 1, 2, 38, 32, }, ++ { 1, 1, 1, 2, 38, 32, }, ++ { 0, 1, 1, 2, 46, 30, }, ++ { 2, 1, 1, 2, 46, 32, }, ++ { 1, 1, 1, 2, 46, 32, }, ++ { 0, 1, 1, 2, 54, 32, }, ++ { 2, 1, 1, 2, 54, 32, }, ++ { 1, 1, 1, 2, 54, 32, }, ++ { 0, 1, 1, 2, 62, 32, }, ++ { 2, 1, 1, 2, 62, 32, }, ++ { 1, 1, 1, 2, 62, 32, }, ++ { 0, 1, 1, 2, 102, 28, }, ++ { 2, 1, 1, 2, 102, 32, }, ++ { 1, 1, 1, 2, 102, 32, }, ++ { 0, 1, 1, 2, 110, 32, }, ++ { 2, 1, 1, 2, 110, 32, }, ++ { 1, 1, 1, 2, 110, 32, }, ++ { 0, 1, 1, 2, 118, 36, }, ++ { 2, 1, 1, 2, 118, 32, }, ++ { 1, 1, 1, 2, 118, 32, }, ++ { 0, 1, 1, 2, 126, 34, }, ++ { 2, 1, 1, 2, 126, 32, }, ++ { 1, 1, 1, 2, 126, 32, }, ++ { 0, 1, 1, 2, 134, 32, }, ++ { 2, 1, 1, 2, 134, 32, }, ++ { 1, 1, 1, 2, 134, 32, }, ++ { 0, 1, 1, 2, 151, 36, }, ++ { 2, 1, 1, 2, 151, 32, }, ++ { 1, 1, 1, 2, 151, 63, }, ++ { 0, 1, 1, 2, 159, 36, }, ++ { 2, 1, 1, 2, 159, 32, }, ++ { 1, 1, 1, 2, 159, 63, }, ++ { 0, 1, 1, 3, 38, 28, }, ++ { 2, 1, 1, 3, 38, 30, }, ++ { 1, 1, 1, 3, 38, 30, }, ++ { 0, 1, 1, 3, 46, 28, }, ++ { 2, 1, 1, 3, 46, 30, }, ++ { 1, 1, 1, 3, 46, 30, }, ++ { 0, 1, 1, 3, 54, 30, }, ++ { 2, 1, 1, 3, 54, 30, }, ++ { 1, 1, 1, 3, 54, 30, }, ++ { 0, 1, 1, 3, 62, 30, }, ++ { 2, 1, 1, 3, 62, 30, }, ++ { 1, 1, 1, 3, 62, 30, }, ++ { 0, 1, 1, 3, 102, 26, }, ++ { 2, 1, 1, 3, 102, 30, }, ++ { 1, 1, 1, 3, 102, 30, }, ++ { 0, 1, 1, 3, 110, 30, }, ++ { 2, 1, 1, 3, 110, 30, }, ++ { 1, 1, 1, 3, 110, 30, }, ++ { 0, 1, 1, 3, 118, 34, }, ++ { 2, 1, 1, 3, 118, 30, }, ++ { 1, 1, 1, 3, 118, 30, }, ++ { 0, 1, 1, 3, 126, 32, }, ++ { 2, 1, 1, 3, 126, 30, }, ++ { 1, 1, 1, 3, 126, 30, }, ++ { 0, 1, 1, 3, 134, 30, }, ++ { 2, 1, 1, 3, 134, 30, }, ++ { 1, 1, 1, 3, 134, 30, }, ++ { 0, 1, 1, 3, 151, 34, }, ++ { 2, 1, 1, 3, 151, 30, }, ++ { 1, 1, 1, 3, 151, 63, }, ++ { 0, 1, 1, 3, 159, 34, }, ++ { 2, 1, 1, 3, 159, 30, }, ++ { 1, 1, 1, 3, 159, 63, }, ++ { 0, 1, 2, 4, 42, 30, }, ++ { 2, 1, 2, 4, 42, 32, }, ++ { 1, 1, 2, 4, 42, 32, }, ++ { 0, 1, 2, 4, 58, 28, }, ++ { 2, 1, 2, 4, 58, 32, }, ++ { 1, 1, 2, 4, 58, 32, }, ++ { 0, 1, 2, 4, 106, 30, }, ++ { 2, 1, 2, 4, 106, 32, }, ++ { 1, 1, 2, 4, 106, 32, }, ++ { 0, 1, 2, 4, 122, 34, }, ++ { 2, 1, 2, 4, 122, 32, }, ++ { 1, 1, 2, 4, 122, 32, }, ++ { 0, 1, 2, 4, 155, 36, }, ++ { 2, 1, 2, 4, 155, 32, }, ++ { 1, 1, 2, 4, 155, 63, }, ++ { 0, 1, 2, 5, 42, 28, }, ++ { 2, 1, 2, 5, 42, 30, }, ++ { 1, 1, 2, 5, 42, 30, }, ++ { 0, 1, 2, 5, 58, 26, }, ++ { 2, 1, 2, 5, 58, 30, }, ++ { 1, 1, 2, 5, 58, 30, }, ++ { 0, 1, 2, 5, 106, 28, }, ++ { 2, 1, 2, 5, 106, 30, }, ++ { 1, 1, 2, 5, 106, 30, }, ++ { 0, 1, 2, 5, 122, 32, }, ++ { 2, 1, 2, 5, 122, 30, }, ++ { 1, 1, 2, 5, 122, 30, }, ++ { 0, 1, 2, 5, 155, 34, }, ++ { 2, 1, 2, 5, 155, 30, }, ++ { 1, 1, 2, 5, 155, 63, }, ++}; ++ ++RTW_DECL_TABLE_TXPWR_LMT(rtw8812a_txpwr_lmt); ++ ++static const struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8812a[] = { ++ {0x0012, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(0), BIT(0)}, ++ {0x0014, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, 0x80, 0}, ++ {0x0015, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, 0x01, 0}, ++ {0x0023, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, 0x10, 0}, ++ {0x0046, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, 0xFF, 0x00}, ++ {0x0043, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, 0xFF, 0x00}, ++ {0x0005, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_PCI_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(2), 0}, ++ {0x0005, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(3), 0}, ++ {0x0003, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(2), BIT(2)}, ++ {0x0301, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_PCI_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, 0xFF, 0}, ++ {0x0024, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_USB_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(1), BIT(1)}, ++ {0x0028, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_USB_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(3), BIT(3)}, ++ {0xFFFF, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ 0, ++ RTW_PWR_CMD_END, 0, 0}, ++}; ++ ++static const struct rtw_pwr_seq_cmd trans_cardemu_to_act_8812a[] = { ++ {0x0005, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(2), 0}, ++ {0x0006, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_POLLING, BIT(1), BIT(1)}, ++ {0x0005, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_PCI_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(7), 0}, ++ {0x0005, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(3), 0}, ++ {0x0005, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(0), BIT(0)}, ++ {0x0005, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_POLLING, BIT(0), 0}, ++ {0x0024, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_USB_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(1), 0}, ++ {0x0028, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_USB_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(3), 0}, ++ {0xFFFF, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ 0, ++ RTW_PWR_CMD_END, 0, 0}, ++}; ++ ++static const struct rtw_pwr_seq_cmd trans_act_to_lps_8812a[] = { ++ {0x0301, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_PCI_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, 0xFF, 0xFF}, ++ {0x0522, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, 0xFF, 0x7F}, ++ {0x05F8, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_POLLING, 0xFF, 0}, ++ {0x05F9, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_POLLING, 0xFF, 0}, ++ {0x05FA, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_POLLING, 0xFF, 0}, ++ {0x05FB, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_POLLING, 0xFF, 0}, ++ {0x0c00, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, 0xFF, 0x04}, ++ {0x0e00, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, 0xFF, 0x04}, ++ {0x0002, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(0), 0}, ++ {0x0002, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_DELAY, 0, RTW_PWR_DELAY_US}, ++ {0x0002, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_USB_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(1), 0}, ++ {0x0100, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, 0xFF, 0x03}, ++ {0x0101, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(1), 0}, ++ {0x0553, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(5), BIT(5)}, ++ {0xFFFF, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ 0, ++ RTW_PWR_CMD_END, 0, 0}, ++}; ++ ++static const struct rtw_pwr_seq_cmd trans_act_to_cardemu_8812a[] = { ++ {0x0c00, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, 0xFF, 0x04}, ++ {0x0e00, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, 0xFF, 0x04}, ++ {0x0002, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(0), 0}, ++ {0x0002, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_DELAY, 0, RTW_PWR_DELAY_US}, ++ {0x0002, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_PCI_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(1), 0}, ++ {0x0007, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, 0xFF, 0x2A}, ++ {0x0008, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_USB_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, 0x02, 0}, ++ {0x0005, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(1), BIT(1)}, ++ {0x0005, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_POLLING, BIT(1), 0}, ++ {0xFFFF, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ 0, ++ RTW_PWR_CMD_END, 0, 0}, ++}; ++ ++static const struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8812a[] = { ++ {0x0003, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(2), 0}, ++ {0x0080, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, 0xFF, 0x05}, ++ {0x0042, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_USB_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, 0xF0, 0xcc}, ++ {0x0042, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_PCI_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, 0xF0, 0xEC}, ++ {0x0043, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, 0xFF, 0x07}, ++ {0x0045, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, 0xFF, 0x00}, ++ {0x0046, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, 0xFF, 0xff}, ++ {0x0047, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, 0xFF, 0}, ++ {0x0014, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, 0x80, BIT(7)}, ++ {0x0015, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, 0x01, BIT(0)}, ++ {0x0012, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, 0x01, 0}, ++ {0x0023, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, 0x10, BIT(4)}, ++ {0x0008, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_USB_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, 0x02, 0}, ++ {0x0007, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_USB_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, 0xFF, 0x20}, ++ {0x001f, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_USB_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(1), 0}, ++ {0x0076, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_USB_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(1), 0}, ++ {0x0005, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(3), BIT(3)}, ++ {0xFFFF, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ 0, ++ RTW_PWR_CMD_END, 0, 0}, ++}; ++ ++const struct rtw_pwr_seq_cmd * const card_enable_flow_8812a[] = { ++ trans_carddis_to_cardemu_8812a, ++ trans_cardemu_to_act_8812a, ++ NULL ++}; ++ ++const struct rtw_pwr_seq_cmd * const enter_lps_flow_8812a[] = { ++ trans_act_to_lps_8812a, ++ NULL ++}; ++ ++const struct rtw_pwr_seq_cmd * const card_disable_flow_8812a[] = { ++ trans_act_to_cardemu_8812a, ++ trans_cardemu_to_carddis_8812a, ++ NULL ++}; ++ ++static const u8 rtw8812a_pwrtrk_5gb_n[][RTW_PWR_TRK_TBL_SZ] = { ++ {0, 1, 1, 2, 2, 3, 4, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, ++ 12, 13, 13, 14, 14, 14, 14, 14, 14}, ++ {0, 1, 1, 2, 2, 3, 4, 4, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, ++ 12, 13, 13, 14, 14, 14, 14, 14, 14}, ++ {0, 1, 1, 2, 2, 3, 4, 5, 6, 6, 7, 8, 8, 9, 10, 10, 11, 11, 12, 12, 13, ++ 13, 14, 14, 15, 16, 16, 16, 16, 16}, ++}; ++ ++static const u8 rtw8812a_pwrtrk_5gb_p[][RTW_PWR_TRK_TBL_SZ] = { ++ {0, 1, 1, 2, 2, 3, 3, 4, 5, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 11, ++ 11, 11, 11, 11, 11, 11, 11, 11, 11}, ++ {0, 1, 1, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 11, ++ 11, 11, 11, 11, 11, 11, 11, 11, 11}, ++ {0, 1, 1, 2, 3, 3, 4, 5, 6, 7, 7, 8, 8, 9, 9, 10, 11, 11, 11, 11, 11, ++ 11, 11, 11, 11, 11, 11, 11, 11, 11}, ++}; ++ ++static const u8 rtw8812a_pwrtrk_5ga_n[][RTW_PWR_TRK_TBL_SZ] = { ++ {0, 1, 1, 2, 2, 3, 4, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, ++ 12, 13, 13, 14, 15, 15, 15, 15, 15}, ++ {0, 1, 1, 2, 2, 3, 4, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, ++ 12, 13, 13, 14, 15, 15, 15, 15, 15}, ++ {0, 1, 1, 2, 2, 3, 4, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, ++ 12, 13, 13, 14, 15, 15, 15, 15, 15}, ++}; ++ ++static const u8 rtw8812a_pwrtrk_5ga_p[][RTW_PWR_TRK_TBL_SZ] = { ++ {0, 1, 1, 2, 2, 3, 4, 5, 6, 7, 7, 8, 8, 9, 10, 11, 11, 11, 11, 11, 11, ++ 11, 11, 11, 11, 11, 11, 11, 11, 11}, ++ {0, 1, 1, 2, 3, 3, 4, 5, 6, 7, 7, 8, 8, 9, 10, 11, 11, 11, 11, 11, 11, ++ 11, 11, 11, 11, 11, 11, 11, 11, 11}, ++ {0, 1, 1, 2, 3, 3, 4, 5, 6, 7, 7, 8, 8, 9, 10, 11, 11, 12, 12, 11, 11, ++ 11, 11, 11, 11, 11, 11, 11, 11, 11}, ++}; ++ ++static const u8 rtw8812a_pwrtrk_2gb_n[] = { ++ 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6, 6, ++ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 11, 11, 11, 11 ++}; ++ ++static const u8 rtw8812a_pwrtrk_2gb_p[] = { ++ 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, ++ 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 ++}; ++ ++static const u8 rtw8812a_pwrtrk_2ga_n[] = { ++ 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, ++ 6, 6, 7, 7, 7, 8, 8, 9, 10, 10, 10, 10, 10, 10 ++}; ++ ++static const u8 rtw8812a_pwrtrk_2ga_p[] = { ++ 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, ++ 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 ++}; ++ ++static const u8 rtw8812a_pwrtrk_2g_cck_b_n[] = { ++ 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6, 6, ++ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 11, 11, 11, 11 ++}; ++ ++static const u8 rtw8812a_pwrtrk_2g_cck_b_p[] = { ++ 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, ++ 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 ++}; ++ ++static const u8 rtw8812a_pwrtrk_2g_cck_a_n[] = { ++ 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, ++ 6, 6, 7, 7, 7, 8, 8, 9, 10, 10, 10, 10, 10, 10 ++}; ++ ++static const u8 rtw8812a_pwrtrk_2g_cck_a_p[] = { ++ 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, ++ 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 ++}; ++ ++const struct rtw_pwr_track_tbl rtw8812a_rtw_pwr_track_tbl = { ++ .pwrtrk_5gb_n[0] = rtw8812a_pwrtrk_5gb_n[0], ++ .pwrtrk_5gb_n[1] = rtw8812a_pwrtrk_5gb_n[1], ++ .pwrtrk_5gb_n[2] = rtw8812a_pwrtrk_5gb_n[2], ++ .pwrtrk_5gb_p[0] = rtw8812a_pwrtrk_5gb_p[0], ++ .pwrtrk_5gb_p[1] = rtw8812a_pwrtrk_5gb_p[1], ++ .pwrtrk_5gb_p[2] = rtw8812a_pwrtrk_5gb_p[2], ++ .pwrtrk_5ga_n[0] = rtw8812a_pwrtrk_5ga_n[0], ++ .pwrtrk_5ga_n[1] = rtw8812a_pwrtrk_5ga_n[1], ++ .pwrtrk_5ga_n[2] = rtw8812a_pwrtrk_5ga_n[2], ++ .pwrtrk_5ga_p[0] = rtw8812a_pwrtrk_5ga_p[0], ++ .pwrtrk_5ga_p[1] = rtw8812a_pwrtrk_5ga_p[1], ++ .pwrtrk_5ga_p[2] = rtw8812a_pwrtrk_5ga_p[2], ++ .pwrtrk_2gb_n = rtw8812a_pwrtrk_2gb_n, ++ .pwrtrk_2gb_p = rtw8812a_pwrtrk_2gb_p, ++ .pwrtrk_2ga_n = rtw8812a_pwrtrk_2ga_n, ++ .pwrtrk_2ga_p = rtw8812a_pwrtrk_2ga_p, ++ .pwrtrk_2g_cckb_n = rtw8812a_pwrtrk_2g_cck_b_n, ++ .pwrtrk_2g_cckb_p = rtw8812a_pwrtrk_2g_cck_b_p, ++ .pwrtrk_2g_ccka_n = rtw8812a_pwrtrk_2g_cck_a_n, ++ .pwrtrk_2g_ccka_p = rtw8812a_pwrtrk_2g_cck_a_p, ++}; ++ ++static const u8 rtw8812a_pwrtrk_rfe3_5gb_n[][RTW_PWR_TRK_TBL_SZ] = { ++ {0, 1, 1, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 12, 13, ++ 13, 14, 15, 16, 16, 17, 17, 18, 18}, ++ {0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 11, ++ 12, 14, 13, 13, 14, 14, 14, 15, 15}, ++ {0, 1, 1, 2, 2, 3, 4, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, ++ 12, 13, 13, 14, 14, 15, 15, 16, 16}, ++}; ++ ++static const u8 rtw8812a_pwrtrk_rfe3_5gb_p[][RTW_PWR_TRK_TBL_SZ] = { ++ {0, 1, 1, 2, 3, 3, 4, 5, 6, 7, 7, 8, 9, 9, 10, 10, 11, 11, 11, 11, 11, ++ 11, 11, 11, 11, 11, 11, 11, 11, 11}, ++ {0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 11, ++ 11, 11, 11, 11, 11, 11, 11, 11, 11}, ++ {0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6, 6, 7, 7, 8, 9, 10, 10, 11, 11, 11, ++ 11, 11, 11, 11, 11, 11, 11, 11, 11}, ++}; ++ ++static const u8 rtw8812a_pwrtrk_rfe3_5ga_n[][RTW_PWR_TRK_TBL_SZ] = { ++ {0, 1, 1, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, ++ 13, 14, 15, 16, 16, 17, 17, 18, 18}, ++ {0, 1, 1, 2, 3, 3, 4, 4, 5, 6, 6, 7, 7, 8, 9, 9, 10, 10, 11, 11, 12, ++ 12, 13, 13, 14, 15, 16, 16, 17, 17}, ++ {0, 1, 1, 2, 3, 3, 4, 4, 5, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 12, 13, ++ 13, 14, 14, 15, 15, 16, 17, 18, 18}, ++}; ++ ++static const u8 rtw8812a_pwrtrk_rfe3_5ga_p[][RTW_PWR_TRK_TBL_SZ] = { ++ {0, 1, 1, 2, 2, 3, 4, 5, 6, 7, 7, 8, 9, 9, 10, 10, 11, 11, 11, 11, 11, ++ 11, 11, 11, 11, 11, 11, 11, 11, 11}, ++ {0, 1, 2, 3, 4, 4, 5, 5, 6, 7, 7, 8, 9, 9, 10, 11, 11, 11, 11, 11, 11, ++ 11, 11, 11, 11, 11, 11, 11, 11, 11}, ++ {0, 1, 2, 3, 4, 4, 5, 5, 6, 7, 7, 8, 9, 9, 10, 11, 11, 11, 11, 11, 11, ++ 11, 11, 11, 11, 11, 11, 11, 11, 11}, ++}; ++ ++static const u8 rtw8812a_pwrtrk_rfe3_2gb_n[] = { ++ 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 7, ++ 7, 7, 8, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15, 15 ++}; ++ ++static const u8 rtw8812a_pwrtrk_rfe3_2gb_p[] = { ++ 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6, ++ 6, 7, 7, 8, 9, 10, 10, 10, 10, 11, 11, 11, 11, 11 ++}; ++ ++static const u8 rtw8812a_pwrtrk_rfe3_2ga_n[] = { ++ 0, 1, 1, 2, 2, 3, 4, 5, 6, 6, 6, 7, 7, 8, 8, 9, ++ 10, 10, 11, 11, 12, 12, 13, 13, 13, 13, 14, 14, 15, 15 ++}; ++ ++static const u8 rtw8812a_pwrtrk_rfe3_2ga_p[] = { ++ 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6, ++ 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 11, 11, 11 ++}; ++ ++static const u8 rtw8812a_pwrtrk_rfe3_2g_cck_b_n[] = { ++ 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 7, ++ 7, 7, 8, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15, 15 ++}; ++ ++static const u8 rtw8812a_pwrtrk_rfe3_2g_cck_b_p[] = { ++ 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6, ++ 6, 7, 7, 8, 9, 10, 10, 10, 10, 11, 11, 11, 11, 11 ++}; ++ ++static const u8 rtw8812a_pwrtrk_rfe3_2g_cck_a_n[] = { ++ 0, 1, 1, 2, 2, 3, 4, 5, 6, 6, 6, 7, 7, 8, 8, 9, ++ 10, 10, 11, 11, 12, 12, 13, 13, 13, 13, 14, 14, 15, 15 ++}; ++ ++static const u8 rtw8812a_pwrtrk_rfe3_2g_cck_a_p[] = { ++ 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6, ++ 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 11, 11, 11 ++}; ++ ++const struct rtw_pwr_track_tbl rtw8812a_rtw_pwr_track_rfe3_tbl = { ++ .pwrtrk_5gb_n[0] = rtw8812a_pwrtrk_rfe3_5gb_n[0], ++ .pwrtrk_5gb_n[1] = rtw8812a_pwrtrk_rfe3_5gb_n[1], ++ .pwrtrk_5gb_n[2] = rtw8812a_pwrtrk_rfe3_5gb_n[2], ++ .pwrtrk_5gb_p[0] = rtw8812a_pwrtrk_rfe3_5gb_p[0], ++ .pwrtrk_5gb_p[1] = rtw8812a_pwrtrk_rfe3_5gb_p[1], ++ .pwrtrk_5gb_p[2] = rtw8812a_pwrtrk_rfe3_5gb_p[2], ++ .pwrtrk_5ga_n[0] = rtw8812a_pwrtrk_rfe3_5ga_n[0], ++ .pwrtrk_5ga_n[1] = rtw8812a_pwrtrk_rfe3_5ga_n[1], ++ .pwrtrk_5ga_n[2] = rtw8812a_pwrtrk_rfe3_5ga_n[2], ++ .pwrtrk_5ga_p[0] = rtw8812a_pwrtrk_rfe3_5ga_p[0], ++ .pwrtrk_5ga_p[1] = rtw8812a_pwrtrk_rfe3_5ga_p[1], ++ .pwrtrk_5ga_p[2] = rtw8812a_pwrtrk_rfe3_5ga_p[2], ++ .pwrtrk_2gb_n = rtw8812a_pwrtrk_rfe3_2gb_n, ++ .pwrtrk_2gb_p = rtw8812a_pwrtrk_rfe3_2gb_p, ++ .pwrtrk_2ga_n = rtw8812a_pwrtrk_rfe3_2ga_n, ++ .pwrtrk_2ga_p = rtw8812a_pwrtrk_rfe3_2ga_p, ++ .pwrtrk_2g_cckb_n = rtw8812a_pwrtrk_rfe3_2g_cck_b_n, ++ .pwrtrk_2g_cckb_p = rtw8812a_pwrtrk_rfe3_2g_cck_b_p, ++ .pwrtrk_2g_ccka_n = rtw8812a_pwrtrk_rfe3_2g_cck_a_n, ++ .pwrtrk_2g_ccka_p = rtw8812a_pwrtrk_rfe3_2g_cck_a_p, ++}; +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8812a_table.h b/drivers/net/wireless/realtek/rtw88/rtw8812a_table.h +new file mode 100644 +index 000000000000..f7ab5e4cf059 +--- /dev/null ++++ b/drivers/net/wireless/realtek/rtw88/rtw8812a_table.h +@@ -0,0 +1,26 @@ ++/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ ++/* Copyright(c) 2024 Realtek Corporation ++ */ ++ ++#ifndef __RTW8812A_TABLE_H__ ++#define __RTW8812A_TABLE_H__ ++ ++extern const struct rtw_table rtw8812a_mac_tbl; ++extern const struct rtw_table rtw8812a_agc_tbl; ++extern const struct rtw_table rtw8812a_agc_diff_lb_tbl; ++extern const struct rtw_table rtw8812a_agc_diff_hb_tbl; ++extern const struct rtw_table rtw8812a_bb_tbl; ++extern const struct rtw_table rtw8812a_bb_pg_tbl; ++extern const struct rtw_table rtw8812a_bb_pg_rfe3_tbl; ++extern const struct rtw_table rtw8812a_rf_a_tbl; ++extern const struct rtw_table rtw8812a_rf_b_tbl; ++extern const struct rtw_table rtw8812a_txpwr_lmt_tbl; ++ ++extern const struct rtw_pwr_seq_cmd * const card_enable_flow_8812a[]; ++extern const struct rtw_pwr_seq_cmd * const enter_lps_flow_8812a[]; ++extern const struct rtw_pwr_seq_cmd * const card_disable_flow_8812a[]; ++ ++extern const struct rtw_pwr_track_tbl rtw8812a_rtw_pwr_track_tbl; ++extern const struct rtw_pwr_track_tbl rtw8812a_rtw_pwr_track_rfe3_tbl; ++ ++#endif +-- +2.39.5 + diff --git a/packages/linux/patches/rtlwifi/6.13/0019-wifi-rtw88-Add-rtw8821a_table.-c-h.patch b/packages/linux/patches/rtlwifi/6.13/0019-wifi-rtw88-Add-rtw8821a_table.-c-h.patch new file mode 100644 index 0000000000..3590255b02 --- /dev/null +++ b/packages/linux/patches/rtlwifi/6.13/0019-wifi-rtw88-Add-rtw8821a_table.-c-h.patch @@ -0,0 +1,2404 @@ +From 52e4007b9796a005fea7dc65796d43965c74d9d1 Mon Sep 17 00:00:00 2001 +From: Bitterblue Smith +Date: Wed, 30 Oct 2024 20:25:16 +0200 +Subject: [PATCH 19/24] wifi: rtw88: Add rtw8821a_table.{c,h} + +These contain various arrays for initialising RTL8821AU. Also TX power +limits. + +Signed-off-by: Bitterblue Smith +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/087c7260-fcc3-4e22-886b-ac477cad9198@gmail.com +--- + .../wireless/realtek/rtw88/rtw8821a_table.c | 2350 +++++++++++++++++ + .../wireless/realtek/rtw88/rtw8821a_table.h | 21 + + 2 files changed, 2371 insertions(+) + create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8821a_table.c + create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8821a_table.h + +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821a_table.c b/drivers/net/wireless/realtek/rtw88/rtw8821a_table.c +new file mode 100644 +index 000000000000..c8fd8e331f69 +--- /dev/null ++++ b/drivers/net/wireless/realtek/rtw88/rtw8821a_table.c +@@ -0,0 +1,2350 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause ++/* Copyright(c) 2024 Realtek Corporation ++ */ ++ ++#include "main.h" ++#include "phy.h" ++#include "rtw8821a_table.h" ++ ++static const u32 rtw8821a_mac[] = { ++ 0x421, 0x0000000F, ++ 0x428, 0x0000000A, ++ 0x429, 0x00000010, ++ 0x430, 0x00000000, ++ 0x431, 0x00000000, ++ 0x432, 0x00000000, ++ 0x433, 0x00000001, ++ 0x434, 0x00000004, ++ 0x435, 0x00000005, ++ 0x436, 0x00000007, ++ 0x437, 0x00000008, ++ 0x43C, 0x00000004, ++ 0x43D, 0x00000005, ++ 0x43E, 0x00000007, ++ 0x43F, 0x00000008, ++ 0x440, 0x0000005D, ++ 0x441, 0x00000001, ++ 0x442, 0x00000000, ++ 0x444, 0x00000010, ++ 0x445, 0x00000000, ++ 0x446, 0x00000000, ++ 0x447, 0x00000000, ++ 0x448, 0x00000000, ++ 0x449, 0x000000F0, ++ 0x44A, 0x0000000F, ++ 0x44B, 0x0000003E, ++ 0x44C, 0x00000010, ++ 0x44D, 0x00000000, ++ 0x44E, 0x00000000, ++ 0x44F, 0x00000000, ++ 0x450, 0x00000000, ++ 0x451, 0x000000F0, ++ 0x452, 0x0000000F, ++ 0x453, 0x00000000, ++ 0x456, 0x0000005E, ++ 0x460, 0x00000066, ++ 0x461, 0x00000066, ++ 0x4C8, 0x0000003F, ++ 0x4C9, 0x000000FF, ++ 0x4CC, 0x000000FF, ++ 0x4CD, 0x000000FF, ++ 0x4CE, 0x00000001, ++ 0x500, 0x00000026, ++ 0x501, 0x000000A2, ++ 0x502, 0x0000002F, ++ 0x503, 0x00000000, ++ 0x504, 0x00000028, ++ 0x505, 0x000000A3, ++ 0x506, 0x0000005E, ++ 0x507, 0x00000000, ++ 0x508, 0x0000002B, ++ 0x509, 0x000000A4, ++ 0x50A, 0x0000005E, ++ 0x50B, 0x00000000, ++ 0x50C, 0x0000004F, ++ 0x50D, 0x000000A4, ++ 0x50E, 0x00000000, ++ 0x50F, 0x00000000, ++ 0x512, 0x0000001C, ++ 0x514, 0x0000000A, ++ 0x516, 0x0000000A, ++ 0x525, 0x0000004F, ++ 0x550, 0x00000010, ++ 0x551, 0x00000010, ++ 0x559, 0x00000002, ++ 0x55C, 0x00000050, ++ 0x55D, 0x000000FF, ++ 0x605, 0x00000030, ++ 0x607, 0x00000007, ++ 0x608, 0x0000000E, ++ 0x609, 0x0000002A, ++ 0x620, 0x000000FF, ++ 0x621, 0x000000FF, ++ 0x622, 0x000000FF, ++ 0x623, 0x000000FF, ++ 0x624, 0x000000FF, ++ 0x625, 0x000000FF, ++ 0x626, 0x000000FF, ++ 0x627, 0x000000FF, ++ 0x638, 0x00000050, ++ 0x63C, 0x0000000A, ++ 0x63D, 0x0000000A, ++ 0x63E, 0x0000000E, ++ 0x63F, 0x0000000E, ++ 0x640, 0x00000040, ++ 0x642, 0x00000040, ++ 0x643, 0x00000000, ++ 0x652, 0x000000C8, ++ 0x66E, 0x00000005, ++ 0x700, 0x00000021, ++ 0x701, 0x00000043, ++ 0x702, 0x00000065, ++ 0x703, 0x00000087, ++ 0x708, 0x00000021, ++ 0x709, 0x00000043, ++ 0x70A, 0x00000065, ++ 0x70B, 0x00000087, ++ 0x718, 0x00000040, ++}; ++ ++RTW_DECL_TABLE_PHY_COND(rtw8821a_mac, rtw_phy_cfg_mac); ++ ++static const u32 rtw8821a_agc[] = { ++ 0x81C, 0xBF000001, ++ 0x81C, 0xBF020001, ++ 0x81C, 0xBF040001, ++ 0x81C, 0xBF060001, ++ 0x81C, 0xBE080001, ++ 0x81C, 0xBD0A0001, ++ 0x81C, 0xBC0C0001, ++ 0x81C, 0xBA0E0001, ++ 0x81C, 0xB9100001, ++ 0x81C, 0xB8120001, ++ 0x81C, 0xB7140001, ++ 0x81C, 0xB6160001, ++ 0x81C, 0xB5180001, ++ 0x81C, 0xB41A0001, ++ 0x81C, 0xB31C0001, ++ 0x81C, 0xB21E0001, ++ 0x81C, 0xB1200001, ++ 0x81C, 0xB0220001, ++ 0x81C, 0xAF240001, ++ 0x81C, 0xAE260001, ++ 0x81C, 0xAD280001, ++ 0x81C, 0xAC2A0001, ++ 0x81C, 0xAB2C0001, ++ 0x81C, 0xAA2E0001, ++ 0x81C, 0xA9300001, ++ 0x81C, 0xA8320001, ++ 0x81C, 0xA7340001, ++ 0x81C, 0xA6360001, ++ 0x81C, 0xA5380001, ++ 0x81C, 0xA43A0001, ++ 0x81C, 0x683C0001, ++ 0x81C, 0x673E0001, ++ 0x81C, 0x66400001, ++ 0x81C, 0x65420001, ++ 0x81C, 0x64440001, ++ 0x81C, 0x63460001, ++ 0x81C, 0x62480001, ++ 0x81C, 0x614A0001, ++ 0x81C, 0x474C0001, ++ 0x81C, 0x464E0001, ++ 0x81C, 0x45500001, ++ 0x81C, 0x44520001, ++ 0x81C, 0x43540001, ++ 0x81C, 0x42560001, ++ 0x81C, 0x41580001, ++ 0x81C, 0x285A0001, ++ 0x81C, 0x275C0001, ++ 0x81C, 0x265E0001, ++ 0x81C, 0x25600001, ++ 0x81C, 0x24620001, ++ 0x81C, 0x0A640001, ++ 0x81C, 0x09660001, ++ 0x81C, 0x08680001, ++ 0x81C, 0x076A0001, ++ 0x81C, 0x066C0001, ++ 0x81C, 0x056E0001, ++ 0x81C, 0x04700001, ++ 0x81C, 0x03720001, ++ 0x81C, 0x02740001, ++ 0x81C, 0x01760001, ++ 0x81C, 0x01780001, ++ 0x81C, 0x017A0001, ++ 0x81C, 0x017C0001, ++ 0x81C, 0x017E0001, ++ 0x8000020c, 0x00000000, 0x40000000, 0x00000000, ++ 0x81C, 0xFB000101, ++ 0x81C, 0xFA020101, ++ 0x81C, 0xF9040101, ++ 0x81C, 0xF8060101, ++ 0x81C, 0xF7080101, ++ 0x81C, 0xF60A0101, ++ 0x81C, 0xF50C0101, ++ 0x81C, 0xF40E0101, ++ 0x81C, 0xF3100101, ++ 0x81C, 0xF2120101, ++ 0x81C, 0xF1140101, ++ 0x81C, 0xF0160101, ++ 0x81C, 0xEF180101, ++ 0x81C, 0xEE1A0101, ++ 0x81C, 0xED1C0101, ++ 0x81C, 0xEC1E0101, ++ 0x81C, 0xEB200101, ++ 0x81C, 0xEA220101, ++ 0x81C, 0xE9240101, ++ 0x81C, 0xE8260101, ++ 0x81C, 0xE7280101, ++ 0x81C, 0xE62A0101, ++ 0x81C, 0xE52C0101, ++ 0x81C, 0xE42E0101, ++ 0x81C, 0xE3300101, ++ 0x81C, 0xA5320101, ++ 0x81C, 0xA4340101, ++ 0x81C, 0xA3360101, ++ 0x81C, 0x87380101, ++ 0x81C, 0x863A0101, ++ 0x81C, 0x853C0101, ++ 0x81C, 0x843E0101, ++ 0x81C, 0x69400101, ++ 0x81C, 0x68420101, ++ 0x81C, 0x67440101, ++ 0x81C, 0x66460101, ++ 0x81C, 0x49480101, ++ 0x81C, 0x484A0101, ++ 0x81C, 0x474C0101, ++ 0x81C, 0x2A4E0101, ++ 0x81C, 0x29500101, ++ 0x81C, 0x28520101, ++ 0x81C, 0x27540101, ++ 0x81C, 0x26560101, ++ 0x81C, 0x25580101, ++ 0x81C, 0x245A0101, ++ 0x81C, 0x235C0101, ++ 0x81C, 0x055E0101, ++ 0x81C, 0x04600101, ++ 0x81C, 0x03620101, ++ 0x81C, 0x02640101, ++ 0x81C, 0x01660101, ++ 0x81C, 0x01680101, ++ 0x81C, 0x016A0101, ++ 0x81C, 0x016C0101, ++ 0x81C, 0x016E0101, ++ 0x81C, 0x01700101, ++ 0x81C, 0x01720101, ++ 0x9000040c, 0x00000000, 0x40000000, 0x00000000, ++ 0x81C, 0xFB000101, ++ 0x81C, 0xFA020101, ++ 0x81C, 0xF9040101, ++ 0x81C, 0xF8060101, ++ 0x81C, 0xF7080101, ++ 0x81C, 0xF60A0101, ++ 0x81C, 0xF50C0101, ++ 0x81C, 0xF40E0101, ++ 0x81C, 0xF3100101, ++ 0x81C, 0xF2120101, ++ 0x81C, 0xF1140101, ++ 0x81C, 0xF0160101, ++ 0x81C, 0xEF180101, ++ 0x81C, 0xEE1A0101, ++ 0x81C, 0xED1C0101, ++ 0x81C, 0xEC1E0101, ++ 0x81C, 0xEB200101, ++ 0x81C, 0xEA220101, ++ 0x81C, 0xE9240101, ++ 0x81C, 0xE8260101, ++ 0x81C, 0xE7280101, ++ 0x81C, 0xE62A0101, ++ 0x81C, 0xE52C0101, ++ 0x81C, 0xE42E0101, ++ 0x81C, 0xE3300101, ++ 0x81C, 0xA5320101, ++ 0x81C, 0xA4340101, ++ 0x81C, 0xA3360101, ++ 0x81C, 0x87380101, ++ 0x81C, 0x863A0101, ++ 0x81C, 0x853C0101, ++ 0x81C, 0x843E0101, ++ 0x81C, 0x69400101, ++ 0x81C, 0x68420101, ++ 0x81C, 0x67440101, ++ 0x81C, 0x66460101, ++ 0x81C, 0x49480101, ++ 0x81C, 0x484A0101, ++ 0x81C, 0x474C0101, ++ 0x81C, 0x2A4E0101, ++ 0x81C, 0x29500101, ++ 0x81C, 0x28520101, ++ 0x81C, 0x27540101, ++ 0x81C, 0x26560101, ++ 0x81C, 0x25580101, ++ 0x81C, 0x245A0101, ++ 0x81C, 0x235C0101, ++ 0x81C, 0x055E0101, ++ 0x81C, 0x04600101, ++ 0x81C, 0x03620101, ++ 0x81C, 0x02640101, ++ 0x81C, 0x01660101, ++ 0x81C, 0x01680101, ++ 0x81C, 0x016A0101, ++ 0x81C, 0x016C0101, ++ 0x81C, 0x016E0101, ++ 0x81C, 0x01700101, ++ 0x81C, 0x01720101, ++ 0xA0000000, 0x00000000, ++ 0x81C, 0xFF000101, ++ 0x81C, 0xFF020101, ++ 0x81C, 0xFE040101, ++ 0x81C, 0xFD060101, ++ 0x81C, 0xFC080101, ++ 0x81C, 0xFD0A0101, ++ 0x81C, 0xFC0C0101, ++ 0x81C, 0xFB0E0101, ++ 0x81C, 0xFA100101, ++ 0x81C, 0xF9120101, ++ 0x81C, 0xF8140101, ++ 0x81C, 0xF7160101, ++ 0x81C, 0xF6180101, ++ 0x81C, 0xF51A0101, ++ 0x81C, 0xF41C0101, ++ 0x81C, 0xF31E0101, ++ 0x81C, 0xF2200101, ++ 0x81C, 0xF1220101, ++ 0x81C, 0xF0240101, ++ 0x81C, 0xEF260101, ++ 0x81C, 0xEE280101, ++ 0x81C, 0xED2A0101, ++ 0x81C, 0xEC2C0101, ++ 0x81C, 0xEB2E0101, ++ 0x81C, 0xEA300101, ++ 0x81C, 0xE9320101, ++ 0x81C, 0xE8340101, ++ 0x81C, 0xE7360101, ++ 0x81C, 0xE6380101, ++ 0x81C, 0xE53A0101, ++ 0x81C, 0xE43C0101, ++ 0x81C, 0xE33E0101, ++ 0x81C, 0xA5400101, ++ 0x81C, 0xA4420101, ++ 0x81C, 0xA3440101, ++ 0x81C, 0x87460101, ++ 0x81C, 0x86480101, ++ 0x81C, 0x854A0101, ++ 0x81C, 0x844C0101, ++ 0x81C, 0x694E0101, ++ 0x81C, 0x68500101, ++ 0x81C, 0x67520101, ++ 0x81C, 0x66540101, ++ 0x81C, 0x49560101, ++ 0x81C, 0x48580101, ++ 0x81C, 0x475A0101, ++ 0x81C, 0x2A5C0101, ++ 0x81C, 0x295E0101, ++ 0x81C, 0x28600101, ++ 0x81C, 0x27620101, ++ 0x81C, 0x26640101, ++ 0x81C, 0x25660101, ++ 0x81C, 0x24680101, ++ 0x81C, 0x236A0101, ++ 0x81C, 0x056C0101, ++ 0x81C, 0x046E0101, ++ 0x81C, 0x03700101, ++ 0x81C, 0x02720101, ++ 0xB0000000, 0x00000000, ++ 0x81C, 0x01740101, ++ 0x81C, 0x01760101, ++ 0x81C, 0x01780101, ++ 0x81C, 0x017A0101, ++ 0x81C, 0x017C0101, ++ 0x81C, 0x017E0101, ++ 0xC50, 0x00000022, ++ 0xC50, 0x00000020, ++}; ++ ++RTW_DECL_TABLE_PHY_COND(rtw8821a_agc, rtw_phy_cfg_agc); ++ ++static const u32 rtw8821a_bb[] = { ++ 0x800, 0x0020D090, ++ 0x804, 0x080112E0, ++ 0x808, 0x0E028211, ++ 0x80C, 0x92131111, ++ 0x810, 0x20101261, ++ 0x814, 0x020C3D10, ++ 0x818, 0x03A00385, ++ 0x820, 0x00000000, ++ 0x824, 0x00030FE0, ++ 0x828, 0x00000000, ++ 0x82C, 0x002081DD, ++ 0x830, 0x2AAAEEC8, ++ 0x834, 0x0037A706, ++ 0x838, 0x06489B44, ++ 0x83C, 0x0000095B, ++ 0x840, 0xC0000001, ++ 0x844, 0x40003CDE, ++ 0x848, 0x62103F8B, ++ 0x84C, 0x6CFDFFB8, ++ 0x850, 0x28874706, ++ 0x854, 0x0001520C, ++ 0x858, 0x8060E000, ++ 0x85C, 0x74210168, ++ 0x860, 0x6929C321, ++ 0x864, 0x79727432, ++ 0x868, 0x8CA7A314, ++ 0x86C, 0x888C2878, ++ 0x870, 0x08888888, ++ 0x874, 0x31612C2E, ++ 0x878, 0x00000152, ++ 0x87C, 0x000FD000, ++ 0x8A0, 0x00000013, ++ 0x8A4, 0x7F7F7F7F, ++ 0x8A8, 0xA2000338, ++ 0x8AC, 0x0FF0FA0A, ++ 0x8B4, 0x000FC080, ++ 0x8B8, 0x6C10D7FF, ++ 0x8BC, 0x0CA52090, ++ 0x8C0, 0x1BF00020, ++ 0x8C4, 0x00000000, ++ 0x8C8, 0x00013169, ++ 0x8CC, 0x08248492, ++ 0x8D4, 0x940008A0, ++ 0x8D8, 0x290B5612, ++ 0x8F8, 0x400002C0, ++ 0x8FC, 0x00000000, ++ 0x900, 0x00000700, ++ 0x90C, 0x00000000, ++ 0x910, 0x0000FC00, ++ 0x914, 0x00000404, ++ 0x918, 0x1C1028C0, ++ 0x91C, 0x64B11A1C, ++ 0x920, 0xE0767233, ++ 0x924, 0x055AA500, ++ 0x928, 0x00000004, ++ 0x92C, 0xFFFE0000, ++ 0x930, 0xFFFFFFFE, ++ 0x934, 0x001FFFFF, ++ 0x960, 0x00000000, ++ 0x964, 0x00000000, ++ 0x968, 0x00000000, ++ 0x96C, 0x00000000, ++ 0x970, 0x801FFFFF, ++ 0x974, 0x000003FF, ++ 0x978, 0x00000000, ++ 0x97C, 0x00000000, ++ 0x980, 0x00000000, ++ 0x984, 0x00000000, ++ 0x988, 0x00000000, ++ 0x990, 0x27100000, ++ 0x994, 0xFFFF0100, ++ 0x998, 0xFFFFFF5C, ++ 0x99C, 0xFFFFFFFF, ++ 0x9A0, 0x000000FF, ++ 0x9A4, 0x00480080, ++ 0x9A8, 0x00000000, ++ 0x9AC, 0x00000000, ++ 0x9B0, 0x81081008, ++ 0x9B4, 0x01081008, ++ 0x9B8, 0x01081008, ++ 0x9BC, 0x01081008, ++ 0x9D0, 0x00000000, ++ 0x9D4, 0x00000000, ++ 0x9D8, 0x00000000, ++ 0x9DC, 0x00000000, ++ 0x9E0, 0x00005D00, ++ 0x9E4, 0x00000003, ++ 0x9E8, 0x00000001, ++ 0xA00, 0x00D047C8, ++ 0xA04, 0x01FF800C, ++ 0xA08, 0x8C8A8300, ++ 0xA0C, 0x2E68000F, ++ 0xA10, 0x9500BB78, ++ 0xA14, 0x11144028, ++ 0xA18, 0x00881117, ++ 0xA1C, 0x89140F00, ++ 0xA20, 0x1A1B0000, ++ 0xA24, 0x090E1317, ++ 0xA28, 0x00000204, ++ 0xA2C, 0x00900000, ++ 0xA70, 0x101FFF00, ++ 0xA74, 0x00000008, ++ 0xA78, 0x00000900, ++ 0xA7C, 0x225B0606, ++ 0xA80, 0x21805490, ++ 0xA84, 0x001F0000, ++ 0XB00, 0x03100040, ++ 0XB04, 0x0000B000, ++ 0XB08, 0xAE0201EB, ++ 0XB0C, 0x01003207, ++ 0XB10, 0x00009807, ++ 0XB14, 0x01000000, ++ 0XB18, 0x00000002, ++ 0XB1C, 0x00000002, ++ 0XB20, 0x0000001F, ++ 0XB24, 0x03020100, ++ 0XB28, 0x07060504, ++ 0XB2C, 0x0B0A0908, ++ 0XB30, 0x0F0E0D0C, ++ 0XB34, 0x13121110, ++ 0XB38, 0x17161514, ++ 0XB3C, 0x0000003A, ++ 0XB40, 0x00000000, ++ 0XB44, 0x00000000, ++ 0XB48, 0x13000032, ++ 0XB4C, 0x48080000, ++ 0XB50, 0x00000000, ++ 0XB54, 0x00000000, ++ 0XB58, 0x00000000, ++ 0XB5C, 0x00000000, ++ 0xC00, 0x00000007, ++ 0xC04, 0x00042020, ++ 0xC08, 0x80410231, ++ 0xC0C, 0x00000000, ++ 0xC10, 0x00000100, ++ 0xC14, 0x01000000, ++ 0xC1C, 0x40000003, ++ 0xC20, 0x2C2C2C2C, ++ 0xC24, 0x30303030, ++ 0xC28, 0x30303030, ++ 0xC2C, 0x2C2C2C2C, ++ 0xC30, 0x2C2C2C2C, ++ 0xC34, 0x2C2C2C2C, ++ 0xC38, 0x2C2C2C2C, ++ 0xC3C, 0x2A2A2A2A, ++ 0xC40, 0x2A2A2A2A, ++ 0xC44, 0x2A2A2A2A, ++ 0xC48, 0x2A2A2A2A, ++ 0xC4C, 0x2A2A2A2A, ++ 0xC50, 0x00000020, ++ 0xC54, 0x001C1208, ++ 0xC58, 0x30000C1C, ++ 0xC5C, 0x00000058, ++ 0xC60, 0x34344443, ++ 0xC64, 0x07003333, ++ 0xC68, 0x19791979, ++ 0xC6C, 0x19791979, ++ 0xC70, 0x19791979, ++ 0xC74, 0x19791979, ++ 0xC78, 0x19791979, ++ 0xC7C, 0x19791979, ++ 0xC80, 0x19791979, ++ 0xC84, 0x19791979, ++ 0xC94, 0x0100005C, ++ 0xC98, 0x00000000, ++ 0xC9C, 0x00000000, ++ 0xCA0, 0x00000029, ++ 0xCA4, 0x08040201, ++ 0xCA8, 0x80402010, ++ 0xCB0, 0x77775747, ++ 0xCB4, 0x10000077, ++ 0xCB8, 0x00508240, ++}; ++ ++RTW_DECL_TABLE_PHY_COND(rtw8821a_bb, rtw_phy_cfg_bb); ++ ++static const struct rtw_phy_pg_cfg_pair rtw8821a_bb_pg[] = { ++ { 0, 0, 0, 0x00000c20, 0xffffffff, 0x32343638, }, ++ { 0, 0, 0, 0x00000c24, 0xffffffff, 0x36363838, }, ++ { 0, 0, 0, 0x00000c28, 0xffffffff, 0x28303234, }, ++ { 0, 0, 0, 0x00000c2c, 0xffffffff, 0x34363838, }, ++ { 0, 0, 0, 0x00000c30, 0xffffffff, 0x26283032, }, ++ { 0, 0, 0, 0x00000c3c, 0xffffffff, 0x32343636, }, ++ { 0, 0, 0, 0x00000c40, 0xffffffff, 0x24262830, }, ++ { 0, 0, 0, 0x00000c44, 0x0000ffff, 0x00002022, }, ++ { 1, 0, 0, 0x00000c24, 0xffffffff, 0x34343636, }, ++ { 1, 0, 0, 0x00000c28, 0xffffffff, 0x26283032, }, ++ { 1, 0, 0, 0x00000c2c, 0xffffffff, 0x32343636, }, ++ { 1, 0, 0, 0x00000c30, 0xffffffff, 0x24262830, }, ++ { 1, 0, 0, 0x00000c3c, 0xffffffff, 0x32343636, }, ++ { 1, 0, 0, 0x00000c40, 0xffffffff, 0x24262830, }, ++ { 1, 0, 0, 0x00000c44, 0x0000ffff, 0x00002022, }, ++}; ++ ++RTW_DECL_TABLE_BB_PG(rtw8821a_bb_pg); ++ ++static const u32 rtw8821a_rf_a[] = { ++ 0x018, 0x0001712A, ++ 0x056, 0x00051CF2, ++ 0x066, 0x00040000, ++ 0x000, 0x00010000, ++ 0x01E, 0x00080000, ++ 0x082, 0x00000830, ++ 0x083, 0x00021800, ++ 0x084, 0x00028000, ++ 0x085, 0x00048000, ++ 0x80000111, 0x00000000, 0x40000000, 0x00000000, ++ 0x086, 0x0009483A, ++ 0xA0000000, 0x00000000, ++ 0x086, 0x00094838, ++ 0xB0000000, 0x00000000, ++ 0x087, 0x00044980, ++ 0x088, 0x00048000, ++ 0x089, 0x0000D480, ++ 0x08A, 0x00042240, ++ 0x08B, 0x000F0380, ++ 0x08C, 0x00090000, ++ 0x08D, 0x00022852, ++ 0x08E, 0x00065540, ++ 0x08F, 0x00088001, ++ 0x0EF, 0x00020000, ++ 0x03E, 0x00000380, ++ 0x03F, 0x00090018, ++ 0x03E, 0x00020380, ++ 0x03F, 0x000A0018, ++ 0x03E, 0x00040308, ++ 0x03F, 0x000A0018, ++ 0x03E, 0x00060018, ++ 0x03F, 0x000A0018, ++ 0x0EF, 0x00000000, ++ 0x018, 0x0001712A, ++ 0x089, 0x00000080, ++ 0x08B, 0x00080180, ++ 0x0EF, 0x00001000, ++ 0x03A, 0x00000244, ++ 0x03B, 0x00038027, ++ 0x03C, 0x00082000, ++ 0x03A, 0x00000244, ++ 0x03B, 0x00030113, ++ 0x03C, 0x00082000, ++ 0x03A, 0x0000014C, ++ 0x03B, 0x00028027, ++ 0x03C, 0x00082000, ++ 0x03A, 0x000000CC, ++ 0x03B, 0x00027027, ++ 0x03C, 0x00042000, ++ 0x03A, 0x0000014C, ++ 0x03B, 0x0001F913, ++ 0x03C, 0x00042000, ++ 0x03A, 0x0000010C, ++ 0x03B, 0x00017F10, ++ 0x03C, 0x00012000, ++ 0x03A, 0x000000D0, ++ 0x03B, 0x00008027, ++ 0x03C, 0x000CA000, ++ 0x03A, 0x00000244, ++ 0x03B, 0x00078027, ++ 0x03C, 0x00082000, ++ 0x03A, 0x00000244, ++ 0x03B, 0x00070113, ++ 0x03C, 0x00082000, ++ 0x03A, 0x0000014C, ++ 0x03B, 0x00068027, ++ 0x03C, 0x00082000, ++ 0x03A, 0x000000CC, ++ 0x03B, 0x00067027, ++ 0x03C, 0x00042000, ++ 0x03A, 0x0000014C, ++ 0x03B, 0x0005F913, ++ 0x03C, 0x00042000, ++ 0x03A, 0x0000010C, ++ 0x03B, 0x00057F10, ++ 0x03C, 0x00012000, ++ 0x03A, 0x000000D0, ++ 0x03B, 0x00048027, ++ 0x03C, 0x000CA000, ++ 0x03A, 0x00000244, ++ 0x03B, 0x000B8027, ++ 0x03C, 0x00082000, ++ 0x03A, 0x00000244, ++ 0x03B, 0x000B0113, ++ 0x03C, 0x00082000, ++ 0x03A, 0x0000014C, ++ 0x03B, 0x000A8027, ++ 0x03C, 0x00082000, ++ 0x03A, 0x000000CC, ++ 0x03B, 0x000A7027, ++ 0x03C, 0x00042000, ++ 0x03A, 0x0000014C, ++ 0x03B, 0x0009F913, ++ 0x03C, 0x00042000, ++ 0x03A, 0x0000010C, ++ 0x03B, 0x00097F10, ++ 0x03C, 0x00012000, ++ 0x03A, 0x000000D0, ++ 0x03B, 0x00088027, ++ 0x03C, 0x000CA000, ++ 0x0EF, 0x00000000, ++ 0x0EF, 0x00001100, ++ 0x80000111, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x0004ADF3, ++ 0x034, 0x00049DF0, ++ 0x90000110, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x0004ADF3, ++ 0x034, 0x00049DF0, ++ 0x90000210, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x0004ADF5, ++ 0x034, 0x00049DF2, ++ 0x9000020c, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x0004A0F3, ++ 0x034, 0x000490B1, ++ 0x9000040c, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x0004A0F3, ++ 0x034, 0x000490B1, ++ 0x90000200, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x0004ADF5, ++ 0x034, 0x00049DF2, ++ 0x90000410, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x0004ADF3, ++ 0x034, 0x00049DF0, ++ 0xA0000000, 0x00000000, ++ 0x034, 0x0004ADF7, ++ 0x034, 0x00049DF3, ++ 0xB0000000, 0x00000000, ++ 0x80000111, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x00048DED, ++ 0x034, 0x00047DEA, ++ 0x034, 0x00046DE7, ++ 0x034, 0x00045CE9, ++ 0x034, 0x00044CE6, ++ 0x034, 0x000438C6, ++ 0x034, 0x00042886, ++ 0x034, 0x00041486, ++ 0x034, 0x00040447, ++ 0x90000110, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x00048DED, ++ 0x034, 0x00047DEA, ++ 0x034, 0x00046DE7, ++ 0x034, 0x00045CE9, ++ 0x034, 0x00044CE6, ++ 0x034, 0x000438C6, ++ 0x034, 0x00042886, ++ 0x034, 0x00041486, ++ 0x034, 0x00040447, ++ 0x9000020c, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x000480AE, ++ 0x034, 0x000470AB, ++ 0x034, 0x0004608B, ++ 0x034, 0x00045069, ++ 0x034, 0x00044048, ++ 0x034, 0x00043045, ++ 0x034, 0x00042026, ++ 0x034, 0x00041023, ++ 0x034, 0x00040002, ++ 0x9000040c, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x000480AE, ++ 0x034, 0x000470AB, ++ 0x034, 0x0004608B, ++ 0x034, 0x00045069, ++ 0x034, 0x00044048, ++ 0x034, 0x00043045, ++ 0x034, 0x00042026, ++ 0x034, 0x00041023, ++ 0x034, 0x00040002, ++ 0x90000410, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x00048DED, ++ 0x034, 0x00047DEA, ++ 0x034, 0x00046DE7, ++ 0x034, 0x00045CE9, ++ 0x034, 0x00044CE6, ++ 0x034, 0x000438C6, ++ 0x034, 0x00042886, ++ 0x034, 0x00041486, ++ 0x034, 0x00040447, ++ 0xA0000000, 0x00000000, ++ 0x034, 0x00048DEF, ++ 0x034, 0x00047DEC, ++ 0x034, 0x00046DE9, ++ 0x034, 0x00045CCB, ++ 0x034, 0x0004488D, ++ 0x034, 0x0004348D, ++ 0x034, 0x0004248A, ++ 0x034, 0x0004108D, ++ 0x034, 0x0004008A, ++ 0xB0000000, 0x00000000, ++ 0x80000210, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x0002ADF4, ++ 0x9000020c, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x0002A0F3, ++ 0x9000040c, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x0002A0F3, ++ 0x90000200, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x0002ADF4, ++ 0xA0000000, 0x00000000, ++ 0x034, 0x0002ADF7, ++ 0xB0000000, 0x00000000, ++ 0x80000111, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x00029DF4, ++ 0x90000110, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x00029DF4, ++ 0x90000210, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x00029DF1, ++ 0x9000020c, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x000290F0, ++ 0x9000040c, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x000290F0, ++ 0x90000200, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x00029DF1, ++ 0x90000410, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x00029DF4, ++ 0xA0000000, 0x00000000, ++ 0x034, 0x00029DF2, ++ 0xB0000000, 0x00000000, ++ 0x80000111, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x00028DF1, ++ 0x034, 0x00027DEE, ++ 0x034, 0x00026DEB, ++ 0x034, 0x00025CEC, ++ 0x034, 0x00024CE9, ++ 0x034, 0x000238CA, ++ 0x034, 0x00022889, ++ 0x034, 0x00021489, ++ 0x034, 0x0002044A, ++ 0x90000110, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x00028DF1, ++ 0x034, 0x00027DEE, ++ 0x034, 0x00026DEB, ++ 0x034, 0x00025CEC, ++ 0x034, 0x00024CE9, ++ 0x034, 0x000238CA, ++ 0x034, 0x00022889, ++ 0x034, 0x00021489, ++ 0x034, 0x0002044A, ++ 0x9000020c, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x000280AF, ++ 0x034, 0x000270AC, ++ 0x034, 0x0002608B, ++ 0x034, 0x00025069, ++ 0x034, 0x00024048, ++ 0x034, 0x00023045, ++ 0x034, 0x00022026, ++ 0x034, 0x00021023, ++ 0x034, 0x00020002, ++ 0x9000040c, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x000280AF, ++ 0x034, 0x000270AC, ++ 0x034, 0x0002608B, ++ 0x034, 0x00025069, ++ 0x034, 0x00024048, ++ 0x034, 0x00023045, ++ 0x034, 0x00022026, ++ 0x034, 0x00021023, ++ 0x034, 0x00020002, ++ 0x90000410, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x00028DF1, ++ 0x034, 0x00027DEE, ++ 0x034, 0x00026DEB, ++ 0x034, 0x00025CEC, ++ 0x034, 0x00024CE9, ++ 0x034, 0x000238CA, ++ 0x034, 0x00022889, ++ 0x034, 0x00021489, ++ 0x034, 0x0002044A, ++ 0xA0000000, 0x00000000, ++ 0x034, 0x00028DEE, ++ 0x034, 0x00027DEB, ++ 0x034, 0x00026CCD, ++ 0x034, 0x00025CCA, ++ 0x034, 0x0002488C, ++ 0x034, 0x0002384C, ++ 0x034, 0x00022849, ++ 0x034, 0x00021449, ++ 0x034, 0x0002004D, ++ 0xB0000000, 0x00000000, ++ 0x8000020c, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x0000A0D7, ++ 0x034, 0x000090D3, ++ 0x034, 0x000080B1, ++ 0x034, 0x000070AE, ++ 0x9000040c, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x0000A0D7, ++ 0x034, 0x000090D3, ++ 0x034, 0x000080B1, ++ 0x034, 0x000070AE, ++ 0xA0000000, 0x00000000, ++ 0x034, 0x0000ADF7, ++ 0x034, 0x00009DF4, ++ 0x034, 0x00008DF1, ++ 0x034, 0x00007DEE, ++ 0xB0000000, 0x00000000, ++ 0x80000111, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x00006DEB, ++ 0x034, 0x00005CEC, ++ 0x034, 0x00004CE9, ++ 0x034, 0x000038CA, ++ 0x034, 0x00002889, ++ 0x034, 0x00001489, ++ 0x034, 0x0000044A, ++ 0x90000110, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x00006DEB, ++ 0x034, 0x00005CEC, ++ 0x034, 0x00004CE9, ++ 0x034, 0x000038CA, ++ 0x034, 0x00002889, ++ 0x034, 0x00001489, ++ 0x034, 0x0000044A, ++ 0x9000020c, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x0000608D, ++ 0x034, 0x0000506B, ++ 0x034, 0x0000404A, ++ 0x034, 0x00003047, ++ 0x034, 0x00002044, ++ 0x034, 0x00001025, ++ 0x034, 0x00000004, ++ 0x9000040c, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x0000608D, ++ 0x034, 0x0000506B, ++ 0x034, 0x0000404A, ++ 0x034, 0x00003047, ++ 0x034, 0x00002044, ++ 0x034, 0x00001025, ++ 0x034, 0x00000004, ++ 0x90000410, 0x00000000, 0x40000000, 0x00000000, ++ 0x034, 0x00006DEB, ++ 0x034, 0x00005CEC, ++ 0x034, 0x00004CE9, ++ 0x034, 0x000038CA, ++ 0x034, 0x00002889, ++ 0x034, 0x00001489, ++ 0x034, 0x0000044A, ++ 0xA0000000, 0x00000000, ++ 0x034, 0x00006DCD, ++ 0x034, 0x00005CCD, ++ 0x034, 0x00004CCA, ++ 0x034, 0x0000388C, ++ 0x034, 0x00002888, ++ 0x034, 0x00001488, ++ 0x034, 0x00000486, ++ 0xB0000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x018, 0x0001712A, ++ 0x0EF, 0x00000040, ++ 0x80000111, 0x00000000, 0x40000000, 0x00000000, ++ 0x035, 0x00000187, ++ 0x035, 0x00008187, ++ 0x035, 0x00010187, ++ 0x035, 0x00020188, ++ 0x035, 0x00028188, ++ 0x035, 0x00030188, ++ 0x035, 0x00040188, ++ 0x035, 0x00048188, ++ 0x035, 0x00050188, ++ 0x90000110, 0x00000000, 0x40000000, 0x00000000, ++ 0x035, 0x00000187, ++ 0x035, 0x00008187, ++ 0x035, 0x00010187, ++ 0x035, 0x00020188, ++ 0x035, 0x00028188, ++ 0x035, 0x00030188, ++ 0x035, 0x00040188, ++ 0x035, 0x00048188, ++ 0x035, 0x00050188, ++ 0x90000210, 0x00000000, 0x40000000, 0x00000000, ++ 0x035, 0x00000128, ++ 0x035, 0x00008128, ++ 0x035, 0x00010128, ++ 0x035, 0x000201C8, ++ 0x035, 0x000281C8, ++ 0x035, 0x000301C8, ++ 0x035, 0x000401C8, ++ 0x035, 0x000481C8, ++ 0x035, 0x000501C8, ++ 0x9000040c, 0x00000000, 0x40000000, 0x00000000, ++ 0x035, 0x00000145, ++ 0x035, 0x00008145, ++ 0x035, 0x00010145, ++ 0x035, 0x00020196, ++ 0x035, 0x00028196, ++ 0x035, 0x00030196, ++ 0x035, 0x000401C7, ++ 0x035, 0x000481C7, ++ 0x035, 0x000501C7, ++ 0x90000200, 0x00000000, 0x40000000, 0x00000000, ++ 0x035, 0x00000128, ++ 0x035, 0x00008128, ++ 0x035, 0x00010128, ++ 0x035, 0x000201C8, ++ 0x035, 0x000281C8, ++ 0x035, 0x000301C8, ++ 0x035, 0x000401C8, ++ 0x035, 0x000481C8, ++ 0x035, 0x000501C8, ++ 0x90000410, 0x00000000, 0x40000000, 0x00000000, ++ 0x035, 0x00000187, ++ 0x035, 0x00008187, ++ 0x035, 0x00010187, ++ 0x035, 0x00020188, ++ 0x035, 0x00028188, ++ 0x035, 0x00030188, ++ 0x035, 0x00040188, ++ 0x035, 0x00048188, ++ 0x035, 0x00050188, ++ 0xA0000000, 0x00000000, ++ 0x035, 0x00000145, ++ 0x035, 0x00008145, ++ 0x035, 0x00010145, ++ 0x035, 0x00020196, ++ 0x035, 0x00028196, ++ 0x035, 0x00030196, ++ 0x035, 0x000401C7, ++ 0x035, 0x000481C7, ++ 0x035, 0x000501C7, ++ 0xB0000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x018, 0x0001712A, ++ 0x0EF, 0x00000010, ++ 0x80000111, 0x00000000, 0x40000000, 0x00000000, ++ 0x036, 0x00085733, ++ 0x036, 0x0008D733, ++ 0x036, 0x00095733, ++ 0x036, 0x0009D733, ++ 0x036, 0x000A64B4, ++ 0x036, 0x000AE4B4, ++ 0x036, 0x000B64B4, ++ 0x036, 0x000BE4B4, ++ 0x036, 0x000C64B4, ++ 0x036, 0x000CE4B4, ++ 0x036, 0x000D64B4, ++ 0x036, 0x000DE4B4, ++ 0x90000110, 0x00000000, 0x40000000, 0x00000000, ++ 0x036, 0x00085733, ++ 0x036, 0x0008D733, ++ 0x036, 0x00095733, ++ 0x036, 0x0009D733, ++ 0x036, 0x000A64B4, ++ 0x036, 0x000AE4B4, ++ 0x036, 0x000B64B4, ++ 0x036, 0x000BE4B4, ++ 0x036, 0x000C64B4, ++ 0x036, 0x000CE4B4, ++ 0x036, 0x000D64B4, ++ 0x036, 0x000DE4B4, ++ 0x90000210, 0x00000000, 0x40000000, 0x00000000, ++ 0x036, 0x000063B5, ++ 0x036, 0x0000E3B5, ++ 0x036, 0x000163B5, ++ 0x036, 0x0001E3B5, ++ 0x036, 0x000263B5, ++ 0x036, 0x0002E3B5, ++ 0x036, 0x000363B5, ++ 0x036, 0x0003E3B5, ++ 0x036, 0x000463B5, ++ 0x036, 0x0004E3B5, ++ 0x036, 0x000563B5, ++ 0x036, 0x0005E3B5, ++ 0x9000040c, 0x00000000, 0x40000000, 0x00000000, ++ 0x036, 0x000056B3, ++ 0x036, 0x0000D6B3, ++ 0x036, 0x000156B3, ++ 0x036, 0x0001D6B3, ++ 0x036, 0x00026634, ++ 0x036, 0x0002E634, ++ 0x036, 0x00036634, ++ 0x036, 0x0003E634, ++ 0x036, 0x000467B4, ++ 0x036, 0x0004E7B4, ++ 0x036, 0x000567B4, ++ 0x036, 0x0005E7B4, ++ 0x90000200, 0x00000000, 0x40000000, 0x00000000, ++ 0x036, 0x000063B5, ++ 0x036, 0x0000E3B5, ++ 0x036, 0x000163B5, ++ 0x036, 0x0001E3B5, ++ 0x036, 0x000263B5, ++ 0x036, 0x0002E3B5, ++ 0x036, 0x000363B5, ++ 0x036, 0x0003E3B5, ++ 0x036, 0x000463B5, ++ 0x036, 0x0004E3B5, ++ 0x036, 0x000563B5, ++ 0x036, 0x0005E3B5, ++ 0x90000410, 0x00000000, 0x40000000, 0x00000000, ++ 0x036, 0x00085733, ++ 0x036, 0x0008D733, ++ 0x036, 0x00095733, ++ 0x036, 0x0009D733, ++ 0x036, 0x000A64B4, ++ 0x036, 0x000AE4B4, ++ 0x036, 0x000B64B4, ++ 0x036, 0x000BE4B4, ++ 0x036, 0x000C64B4, ++ 0x036, 0x000CE4B4, ++ 0x036, 0x000D64B4, ++ 0x036, 0x000DE4B4, ++ 0xA0000000, 0x00000000, ++ 0x036, 0x000056B3, ++ 0x036, 0x0000D6B3, ++ 0x036, 0x000156B3, ++ 0x036, 0x0001D6B3, ++ 0x036, 0x00026634, ++ 0x036, 0x0002E634, ++ 0x036, 0x00036634, ++ 0x036, 0x0003E634, ++ 0x036, 0x000467B4, ++ 0x036, 0x0004E7B4, ++ 0x036, 0x000567B4, ++ 0x036, 0x0005E7B4, ++ 0xB0000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x0EF, 0x00000008, ++ 0x80000111, 0x00000000, 0x40000000, 0x00000000, ++ 0x03C, 0x000001C8, ++ 0x03C, 0x00000492, ++ 0x90000110, 0x00000000, 0x40000000, 0x00000000, ++ 0x03C, 0x000001C8, ++ 0x03C, 0x00000492, ++ 0x90000210, 0x00000000, 0x40000000, 0x00000000, ++ 0x03C, 0x000001B6, ++ 0x03C, 0x00000492, ++ 0x9000040c, 0x00000000, 0x40000000, 0x00000000, ++ 0x03C, 0x0000022A, ++ 0x03C, 0x00000594, ++ 0x90000200, 0x00000000, 0x40000000, 0x00000000, ++ 0x03C, 0x000001B6, ++ 0x03C, 0x00000492, ++ 0x90000410, 0x00000000, 0x40000000, 0x00000000, ++ 0x03C, 0x000001C8, ++ 0x03C, 0x00000492, ++ 0xA0000000, 0x00000000, ++ 0x03C, 0x0000022A, ++ 0x03C, 0x00000594, ++ 0xB0000000, 0x00000000, ++ 0x80000111, 0x00000000, 0x40000000, 0x00000000, ++ 0x03C, 0x00000800, ++ 0x90000110, 0x00000000, 0x40000000, 0x00000000, ++ 0x03C, 0x00000800, ++ 0x90000210, 0x00000000, 0x40000000, 0x00000000, ++ 0x03C, 0x00000800, ++ 0x9000020c, 0x00000000, 0x40000000, 0x00000000, ++ 0x03C, 0x00000820, ++ 0x9000040c, 0x00000000, 0x40000000, 0x00000000, ++ 0x03C, 0x00000820, ++ 0x90000200, 0x00000000, 0x40000000, 0x00000000, ++ 0x03C, 0x00000800, ++ 0x90000410, 0x00000000, 0x40000000, 0x00000000, ++ 0x03C, 0x00000800, ++ 0xA0000000, 0x00000000, ++ 0x03C, 0x00000900, ++ 0xB0000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x018, 0x0001712A, ++ 0x0EF, 0x00000002, ++ 0x80000111, 0x00000000, 0x40000000, 0x00000000, ++ 0x008, 0x0004E400, ++ 0x90000110, 0x00000000, 0x40000000, 0x00000000, ++ 0x008, 0x0004E400, ++ 0x90000210, 0x00000000, 0x40000000, 0x00000000, ++ 0x008, 0x00002000, ++ 0x9000020c, 0x00000000, 0x40000000, 0x00000000, ++ 0x008, 0x00002000, ++ 0x9000040c, 0x00000000, 0x40000000, 0x00000000, ++ 0x008, 0x00002000, ++ 0x90000200, 0x00000000, 0x40000000, 0x00000000, ++ 0x008, 0x00002000, ++ 0x90000410, 0x00000000, 0x40000000, 0x00000000, ++ 0x008, 0x0004E400, ++ 0xA0000000, 0x00000000, ++ 0x008, 0x00002000, ++ 0xB0000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x0DF, 0x000000C0, ++ 0x01F, 0x00000064, ++ 0x80000111, 0x00000000, 0x40000000, 0x00000000, ++ 0x058, 0x000A7284, ++ 0x059, 0x000600EC, ++ 0x90000110, 0x00000000, 0x40000000, 0x00000000, ++ 0x058, 0x000A7284, ++ 0x059, 0x000600EC, ++ 0x9000020c, 0x00000000, 0x40000000, 0x00000000, ++ 0x058, 0x00081184, ++ 0x059, 0x0006016C, ++ 0x9000040c, 0x00000000, 0x40000000, 0x00000000, ++ 0x058, 0x00081184, ++ 0x059, 0x0006016C, ++ 0x90000200, 0x00000000, 0x40000000, 0x00000000, ++ 0x058, 0x00081184, ++ 0x059, 0x0006016C, ++ 0x90000410, 0x00000000, 0x40000000, 0x00000000, ++ 0x058, 0x000A7284, ++ 0x059, 0x000600EC, ++ 0xA0000000, 0x00000000, ++ 0x058, 0x00081184, ++ 0x059, 0x0006016C, ++ 0xB0000000, 0x00000000, ++ 0x80000111, 0x00000000, 0x40000000, 0x00000000, ++ 0x061, 0x000E8D73, ++ 0x062, 0x00093FC5, ++ 0x90000110, 0x00000000, 0x40000000, 0x00000000, ++ 0x061, 0x000E8D73, ++ 0x062, 0x00093FC5, ++ 0x90000210, 0x00000000, 0x40000000, 0x00000000, ++ 0x061, 0x000EFD83, ++ 0x062, 0x00093FCC, ++ 0x9000040c, 0x00000000, 0x40000000, 0x00000000, ++ 0x061, 0x000EAD53, ++ 0x062, 0x00093BC4, ++ 0x90000200, 0x00000000, 0x40000000, 0x00000000, ++ 0x061, 0x000EFD83, ++ 0x062, 0x00093FCC, ++ 0x90000410, 0x00000000, 0x40000000, 0x00000000, ++ 0x061, 0x000E8D73, ++ 0x062, 0x00093FC5, ++ 0xA0000000, 0x00000000, ++ 0x061, 0x000EAD53, ++ 0x062, 0x00093BC4, ++ 0xB0000000, 0x00000000, ++ 0x80000111, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x000110E9, ++ 0x90000110, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x000110E9, ++ 0x90000210, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x000110EB, ++ 0x9000020c, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x000110E9, ++ 0x9000040c, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x000110E9, ++ 0x90000200, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x000110EB, ++ 0x90000410, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x000110E9, ++ 0xA0000000, 0x00000000, ++ 0x063, 0x000714E9, ++ 0xB0000000, 0x00000000, ++ 0x80000111, 0x00000000, 0x40000000, 0x00000000, ++ 0x064, 0x0001C27C, ++ 0x90000110, 0x00000000, 0x40000000, 0x00000000, ++ 0x064, 0x0001C27C, ++ 0x90000210, 0x00000000, 0x40000000, 0x00000000, ++ 0x064, 0x0001C27C, ++ 0x9000040c, 0x00000000, 0x40000000, 0x00000000, ++ 0x064, 0x0001C67C, ++ 0x90000200, 0x00000000, 0x40000000, 0x00000000, ++ 0x064, 0x0001C27C, ++ 0x90000410, 0x00000000, 0x40000000, 0x00000000, ++ 0x064, 0x0001C27C, ++ 0xA0000000, 0x00000000, ++ 0x064, 0x0001C67C, ++ 0xB0000000, 0x00000000, ++ 0x80000111, 0x00000000, 0x40000000, 0x00000000, ++ 0x065, 0x00091016, ++ 0x90000110, 0x00000000, 0x40000000, 0x00000000, ++ 0x065, 0x00091016, ++ 0x90000210, 0x00000000, 0x40000000, 0x00000000, ++ 0x065, 0x00093016, ++ 0x9000020c, 0x00000000, 0x40000000, 0x00000000, ++ 0x065, 0x00093015, ++ 0x9000040c, 0x00000000, 0x40000000, 0x00000000, ++ 0x065, 0x00093015, ++ 0x90000200, 0x00000000, 0x40000000, 0x00000000, ++ 0x065, 0x00093016, ++ 0xA0000000, 0x00000000, ++ 0x065, 0x00091016, ++ 0xB0000000, 0x00000000, ++ 0x018, 0x00000006, ++ 0x0EF, 0x00002000, ++ 0x03B, 0x0003824B, ++ 0x03B, 0x0003024B, ++ 0x03B, 0x0002844B, ++ 0x03B, 0x00020F4B, ++ 0x03B, 0x00018F4B, ++ 0x03B, 0x000104B2, ++ 0x03B, 0x00008049, ++ 0x03B, 0x00000148, ++ 0x03B, 0x0007824B, ++ 0x03B, 0x0007024B, ++ 0x03B, 0x0006824B, ++ 0x03B, 0x00060F4B, ++ 0x03B, 0x00058F4B, ++ 0x03B, 0x000504B2, ++ 0x03B, 0x00048049, ++ 0x03B, 0x00040148, ++ 0x0EF, 0x00000000, ++ 0x0EF, 0x00000100, ++ 0x034, 0x0000ADF3, ++ 0x034, 0x00009DF0, ++ 0x034, 0x00008D70, ++ 0x034, 0x00007D6D, ++ 0x034, 0x00006CEE, ++ 0x034, 0x00005CCC, ++ 0x034, 0x000044EC, ++ 0x034, 0x000034AC, ++ 0x034, 0x0000246D, ++ 0x034, 0x0000106F, ++ 0x034, 0x0000006C, ++ 0x0EF, 0x00000000, ++ 0x0ED, 0x00000010, ++ 0x044, 0x0000ADF2, ++ 0x044, 0x00009DEF, ++ 0x044, 0x00008DEC, ++ 0x044, 0x00007DE9, ++ 0x044, 0x00006CEC, ++ 0x044, 0x00005CE9, ++ 0x044, 0x000044EC, ++ 0x044, 0x000034E9, ++ 0x044, 0x0000246C, ++ 0x044, 0x00001469, ++ 0x044, 0x0000006C, ++ 0x0ED, 0x00000000, ++ 0x0ED, 0x00000001, ++ 0x040, 0x00038DA7, ++ 0x040, 0x000300C2, ++ 0x040, 0x000288E2, ++ 0x040, 0x000200B8, ++ 0x040, 0x000188A5, ++ 0x040, 0x00010FBC, ++ 0x040, 0x00008F71, ++ 0x040, 0x00000240, ++ 0x0ED, 0x00000000, ++ 0x0EF, 0x000020A2, ++ 0x0DF, 0x00000080, ++ 0x035, 0x00000120, ++ 0x035, 0x00008120, ++ 0x035, 0x00010120, ++ 0x036, 0x00000085, ++ 0x036, 0x00008085, ++ 0x036, 0x00010085, ++ 0x036, 0x00018085, ++ 0x0EF, 0x00000000, ++ 0x051, 0x00000C31, ++ 0x052, 0x00000622, ++ 0x053, 0x000FC70B, ++ 0x054, 0x0000017E, ++ 0x056, 0x00051DF3, ++ 0x051, 0x00000C01, ++ 0x052, 0x000006D6, ++ 0x053, 0x000FC649, ++ 0x070, 0x00049661, ++ 0x071, 0x0007843E, ++ 0x072, 0x00000382, ++ 0x074, 0x00051400, ++ 0x035, 0x00000160, ++ 0x035, 0x00008160, ++ 0x035, 0x00010160, ++ 0x036, 0x00000124, ++ 0x036, 0x00008124, ++ 0x036, 0x00010124, ++ 0x036, 0x00018124, ++ 0x0ED, 0x0000000C, ++ 0x045, 0x00000140, ++ 0x045, 0x00008140, ++ 0x045, 0x00010140, ++ 0x046, 0x00000124, ++ 0x046, 0x00008124, ++ 0x046, 0x00010124, ++ 0x046, 0x00018124, ++ 0x0DF, 0x00000088, ++ 0x0B3, 0x000F0E18, ++ 0x0B4, 0x0001214C, ++ 0x0B7, 0x0003000C, ++ 0x01C, 0x000539D2, ++ 0x0C4, 0x000AFE00, ++ 0x018, 0x0001F12A, ++ 0xFFE, 0x00000000, ++ 0xFFE, 0x00000000, ++ 0x018, 0x0001712A, ++}; ++ ++RTW_DECL_TABLE_RF_RADIO(rtw8821a_rf_a, A); ++ ++static const struct rtw_txpwr_lmt_cfg_pair rtw8821a_txpwr_lmt[] = { ++ { 0, 0, 0, 0, 1, 32, }, ++ { 2, 0, 0, 0, 1, 28, }, ++ { 1, 0, 0, 0, 1, 32, }, ++ { 0, 0, 0, 0, 2, 32, }, ++ { 2, 0, 0, 0, 2, 28, }, ++ { 1, 0, 0, 0, 2, 32, }, ++ { 0, 0, 0, 0, 3, 36, }, ++ { 2, 0, 0, 0, 3, 28, }, ++ { 1, 0, 0, 0, 3, 32, }, ++ { 0, 0, 0, 0, 4, 36, }, ++ { 2, 0, 0, 0, 4, 28, }, ++ { 1, 0, 0, 0, 4, 32, }, ++ { 0, 0, 0, 0, 5, 36, }, ++ { 2, 0, 0, 0, 5, 28, }, ++ { 1, 0, 0, 0, 5, 32, }, ++ { 0, 0, 0, 0, 6, 36, }, ++ { 2, 0, 0, 0, 6, 28, }, ++ { 1, 0, 0, 0, 6, 32, }, ++ { 0, 0, 0, 0, 7, 36, }, ++ { 2, 0, 0, 0, 7, 28, }, ++ { 1, 0, 0, 0, 7, 32, }, ++ { 0, 0, 0, 0, 8, 36, }, ++ { 2, 0, 0, 0, 8, 28, }, ++ { 1, 0, 0, 0, 8, 32, }, ++ { 0, 0, 0, 0, 9, 32, }, ++ { 2, 0, 0, 0, 9, 28, }, ++ { 1, 0, 0, 0, 9, 32, }, ++ { 0, 0, 0, 0, 10, 32, }, ++ { 2, 0, 0, 0, 10, 28, }, ++ { 1, 0, 0, 0, 10, 32, }, ++ { 0, 0, 0, 0, 11, 32, }, ++ { 2, 0, 0, 0, 11, 28, }, ++ { 1, 0, 0, 0, 11, 32, }, ++ { 0, 0, 0, 0, 12, 28, }, ++ { 2, 0, 0, 0, 12, 28, }, ++ { 1, 0, 0, 0, 12, 32, }, ++ { 0, 0, 0, 0, 13, 26, }, ++ { 2, 0, 0, 0, 13, 28, }, ++ { 1, 0, 0, 0, 13, 32, }, ++ { 0, 0, 0, 0, 14, 63, }, ++ { 2, 0, 0, 0, 14, 63, }, ++ { 1, 0, 0, 0, 14, 32, }, ++ { 0, 0, 0, 1, 1, 30, }, ++ { 2, 0, 0, 1, 1, 30, }, ++ { 1, 0, 0, 1, 1, 32, }, ++ { 0, 0, 0, 1, 2, 30, }, ++ { 2, 0, 0, 1, 2, 32, }, ++ { 1, 0, 0, 1, 2, 32, }, ++ { 0, 0, 0, 1, 3, 32, }, ++ { 2, 0, 0, 1, 3, 32, }, ++ { 1, 0, 0, 1, 3, 32, }, ++ { 0, 0, 0, 1, 4, 32, }, ++ { 2, 0, 0, 1, 4, 32, }, ++ { 1, 0, 0, 1, 4, 32, }, ++ { 0, 0, 0, 1, 5, 32, }, ++ { 2, 0, 0, 1, 5, 32, }, ++ { 1, 0, 0, 1, 5, 32, }, ++ { 0, 0, 0, 1, 6, 32, }, ++ { 2, 0, 0, 1, 6, 32, }, ++ { 1, 0, 0, 1, 6, 32, }, ++ { 0, 0, 0, 1, 7, 32, }, ++ { 2, 0, 0, 1, 7, 32, }, ++ { 1, 0, 0, 1, 7, 32, }, ++ { 0, 0, 0, 1, 8, 32, }, ++ { 2, 0, 0, 1, 8, 32, }, ++ { 1, 0, 0, 1, 8, 32, }, ++ { 0, 0, 0, 1, 9, 30, }, ++ { 2, 0, 0, 1, 9, 32, }, ++ { 1, 0, 0, 1, 9, 32, }, ++ { 0, 0, 0, 1, 10, 30, }, ++ { 2, 0, 0, 1, 10, 32, }, ++ { 1, 0, 0, 1, 10, 32, }, ++ { 0, 0, 0, 1, 11, 30, }, ++ { 2, 0, 0, 1, 11, 32, }, ++ { 1, 0, 0, 1, 11, 32, }, ++ { 0, 0, 0, 1, 12, 26, }, ++ { 2, 0, 0, 1, 12, 32, }, ++ { 1, 0, 0, 1, 12, 32, }, ++ { 0, 0, 0, 1, 13, 24, }, ++ { 2, 0, 0, 1, 13, 30, }, ++ { 1, 0, 0, 1, 13, 32, }, ++ { 0, 0, 0, 1, 14, 63, }, ++ { 2, 0, 0, 1, 14, 63, }, ++ { 1, 0, 0, 1, 14, 63, }, ++ { 0, 0, 0, 2, 1, 26, }, ++ { 2, 0, 0, 2, 1, 26, }, ++ { 1, 0, 0, 2, 1, 32, }, ++ { 0, 0, 0, 2, 2, 26, }, ++ { 2, 0, 0, 2, 2, 32, }, ++ { 1, 0, 0, 2, 2, 32, }, ++ { 0, 0, 0, 2, 3, 32, }, ++ { 2, 0, 0, 2, 3, 32, }, ++ { 1, 0, 0, 2, 3, 32, }, ++ { 0, 0, 0, 2, 4, 32, }, ++ { 2, 0, 0, 2, 4, 32, }, ++ { 1, 0, 0, 2, 4, 32, }, ++ { 0, 0, 0, 2, 5, 32, }, ++ { 2, 0, 0, 2, 5, 32, }, ++ { 1, 0, 0, 2, 5, 32, }, ++ { 0, 0, 0, 2, 6, 32, }, ++ { 2, 0, 0, 2, 6, 32, }, ++ { 1, 0, 0, 2, 6, 32, }, ++ { 0, 0, 0, 2, 7, 32, }, ++ { 2, 0, 0, 2, 7, 32, }, ++ { 1, 0, 0, 2, 7, 32, }, ++ { 0, 0, 0, 2, 8, 32, }, ++ { 2, 0, 0, 2, 8, 32, }, ++ { 1, 0, 0, 2, 8, 32, }, ++ { 0, 0, 0, 2, 9, 26, }, ++ { 2, 0, 0, 2, 9, 32, }, ++ { 1, 0, 0, 2, 9, 32, }, ++ { 0, 0, 0, 2, 10, 26, }, ++ { 2, 0, 0, 2, 10, 32, }, ++ { 1, 0, 0, 2, 10, 32, }, ++ { 0, 0, 0, 2, 11, 26, }, ++ { 2, 0, 0, 2, 11, 32, }, ++ { 1, 0, 0, 2, 11, 32, }, ++ { 0, 0, 0, 2, 12, 26, }, ++ { 2, 0, 0, 2, 12, 32, }, ++ { 1, 0, 0, 2, 12, 32, }, ++ { 0, 0, 0, 2, 13, 24, }, ++ { 2, 0, 0, 2, 13, 26, }, ++ { 1, 0, 0, 2, 13, 32, }, ++ { 0, 0, 0, 2, 14, 63, }, ++ { 2, 0, 0, 2, 14, 63, }, ++ { 1, 0, 0, 2, 14, 63, }, ++ { 0, 0, 0, 3, 1, 30, }, ++ { 2, 0, 0, 3, 1, 32, }, ++ { 1, 0, 0, 3, 1, 32, }, ++ { 0, 0, 0, 3, 2, 32, }, ++ { 2, 0, 0, 3, 2, 32, }, ++ { 1, 0, 0, 3, 2, 32, }, ++ { 0, 0, 0, 3, 3, 32, }, ++ { 2, 0, 0, 3, 3, 32, }, ++ { 1, 0, 0, 3, 3, 32, }, ++ { 0, 0, 0, 3, 4, 32, }, ++ { 2, 0, 0, 3, 4, 32, }, ++ { 1, 0, 0, 3, 4, 32, }, ++ { 0, 0, 0, 3, 5, 32, }, ++ { 2, 0, 0, 3, 5, 32, }, ++ { 1, 0, 0, 3, 5, 32, }, ++ { 0, 0, 0, 3, 6, 32, }, ++ { 2, 0, 0, 3, 6, 32, }, ++ { 1, 0, 0, 3, 6, 32, }, ++ { 0, 0, 0, 3, 7, 32, }, ++ { 2, 0, 0, 3, 7, 32, }, ++ { 1, 0, 0, 3, 7, 32, }, ++ { 0, 0, 0, 3, 8, 32, }, ++ { 2, 0, 0, 3, 8, 32, }, ++ { 1, 0, 0, 3, 8, 32, }, ++ { 0, 0, 0, 3, 9, 32, }, ++ { 2, 0, 0, 3, 9, 32, }, ++ { 1, 0, 0, 3, 9, 32, }, ++ { 0, 0, 0, 3, 10, 32, }, ++ { 2, 0, 0, 3, 10, 32, }, ++ { 1, 0, 0, 3, 10, 32, }, ++ { 0, 0, 0, 3, 11, 30, }, ++ { 2, 0, 0, 3, 11, 32, }, ++ { 1, 0, 0, 3, 11, 32, }, ++ { 0, 0, 0, 3, 12, 63, }, ++ { 2, 0, 0, 3, 12, 32, }, ++ { 1, 0, 0, 3, 12, 32, }, ++ { 0, 0, 0, 3, 13, 63, }, ++ { 2, 0, 0, 3, 13, 32, }, ++ { 1, 0, 0, 3, 13, 32, }, ++ { 0, 0, 0, 3, 14, 63, }, ++ { 2, 0, 0, 3, 14, 63, }, ++ { 1, 0, 0, 3, 14, 63, }, ++ { 0, 0, 1, 2, 1, 63, }, ++ { 2, 0, 1, 2, 1, 63, }, ++ { 1, 0, 1, 2, 1, 63, }, ++ { 0, 0, 1, 2, 2, 63, }, ++ { 2, 0, 1, 2, 2, 63, }, ++ { 1, 0, 1, 2, 2, 63, }, ++ { 0, 0, 1, 2, 3, 26, }, ++ { 2, 0, 1, 2, 3, 26, }, ++ { 1, 0, 1, 2, 3, 32, }, ++ { 0, 0, 1, 2, 4, 26, }, ++ { 2, 0, 1, 2, 4, 32, }, ++ { 1, 0, 1, 2, 4, 32, }, ++ { 0, 0, 1, 2, 5, 26, }, ++ { 2, 0, 1, 2, 5, 32, }, ++ { 1, 0, 1, 2, 5, 32, }, ++ { 0, 0, 1, 2, 6, 32, }, ++ { 2, 0, 1, 2, 6, 32, }, ++ { 1, 0, 1, 2, 6, 32, }, ++ { 0, 0, 1, 2, 7, 32, }, ++ { 2, 0, 1, 2, 7, 32, }, ++ { 1, 0, 1, 2, 7, 32, }, ++ { 0, 0, 1, 2, 8, 32, }, ++ { 2, 0, 1, 2, 8, 32, }, ++ { 1, 0, 1, 2, 8, 32, }, ++ { 0, 0, 1, 2, 9, 26, }, ++ { 2, 0, 1, 2, 9, 32, }, ++ { 1, 0, 1, 2, 9, 32, }, ++ { 0, 0, 1, 2, 10, 24, }, ++ { 2, 0, 1, 2, 10, 32, }, ++ { 1, 0, 1, 2, 10, 32, }, ++ { 0, 0, 1, 2, 11, 22, }, ++ { 2, 0, 1, 2, 11, 26, }, ++ { 1, 0, 1, 2, 11, 32, }, ++ { 0, 0, 1, 2, 12, 63, }, ++ { 2, 0, 1, 2, 12, 63, }, ++ { 1, 0, 1, 2, 12, 63, }, ++ { 0, 0, 1, 2, 13, 63, }, ++ { 2, 0, 1, 2, 13, 63, }, ++ { 1, 0, 1, 2, 13, 63, }, ++ { 0, 0, 1, 2, 14, 63, }, ++ { 2, 0, 1, 2, 14, 63, }, ++ { 1, 0, 1, 2, 14, 63, }, ++ { 0, 0, 1, 3, 1, 63, }, ++ { 2, 0, 1, 3, 1, 63, }, ++ { 1, 0, 1, 3, 1, 63, }, ++ { 0, 0, 1, 3, 2, 63, }, ++ { 2, 0, 1, 3, 2, 63, }, ++ { 1, 0, 1, 3, 2, 63, }, ++ { 0, 0, 1, 3, 3, 30, }, ++ { 2, 0, 1, 3, 3, 30, }, ++ { 1, 0, 1, 3, 3, 30, }, ++ { 0, 0, 1, 3, 4, 32, }, ++ { 2, 0, 1, 3, 4, 30, }, ++ { 1, 0, 1, 3, 4, 30, }, ++ { 0, 0, 1, 3, 5, 32, }, ++ { 2, 0, 1, 3, 5, 30, }, ++ { 1, 0, 1, 3, 5, 30, }, ++ { 0, 0, 1, 3, 6, 32, }, ++ { 2, 0, 1, 3, 6, 30, }, ++ { 1, 0, 1, 3, 6, 30, }, ++ { 0, 0, 1, 3, 7, 32, }, ++ { 2, 0, 1, 3, 7, 30, }, ++ { 1, 0, 1, 3, 7, 30, }, ++ { 0, 0, 1, 3, 8, 32, }, ++ { 2, 0, 1, 3, 8, 30, }, ++ { 1, 0, 1, 3, 8, 30, }, ++ { 0, 0, 1, 3, 9, 32, }, ++ { 2, 0, 1, 3, 9, 30, }, ++ { 1, 0, 1, 3, 9, 30, }, ++ { 0, 0, 1, 3, 10, 32, }, ++ { 2, 0, 1, 3, 10, 30, }, ++ { 1, 0, 1, 3, 10, 30, }, ++ { 0, 0, 1, 3, 11, 30, }, ++ { 2, 0, 1, 3, 11, 30, }, ++ { 1, 0, 1, 3, 11, 30, }, ++ { 0, 0, 1, 3, 12, 63, }, ++ { 2, 0, 1, 3, 12, 32, }, ++ { 1, 0, 1, 3, 12, 32, }, ++ { 0, 0, 1, 3, 13, 63, }, ++ { 2, 0, 1, 3, 13, 32, }, ++ { 1, 0, 1, 3, 13, 32, }, ++ { 0, 0, 1, 3, 14, 63, }, ++ { 2, 0, 1, 3, 14, 63, }, ++ { 1, 0, 1, 3, 14, 63, }, ++ { 0, 1, 0, 1, 36, 32, }, ++ { 2, 1, 0, 1, 36, 30, }, ++ { 1, 1, 0, 1, 36, 30, }, ++ { 0, 1, 0, 1, 40, 32, }, ++ { 2, 1, 0, 1, 40, 30, }, ++ { 1, 1, 0, 1, 40, 30, }, ++ { 0, 1, 0, 1, 44, 32, }, ++ { 2, 1, 0, 1, 44, 30, }, ++ { 1, 1, 0, 1, 44, 30, }, ++ { 0, 1, 0, 1, 48, 32, }, ++ { 2, 1, 0, 1, 48, 30, }, ++ { 1, 1, 0, 1, 48, 30, }, ++ { 0, 1, 0, 1, 52, 32, }, ++ { 2, 1, 0, 1, 52, 30, }, ++ { 1, 1, 0, 1, 52, 30, }, ++ { 0, 1, 0, 1, 56, 32, }, ++ { 2, 1, 0, 1, 56, 30, }, ++ { 1, 1, 0, 1, 56, 30, }, ++ { 0, 1, 0, 1, 60, 32, }, ++ { 2, 1, 0, 1, 60, 30, }, ++ { 1, 1, 0, 1, 60, 30, }, ++ { 0, 1, 0, 1, 64, 32, }, ++ { 2, 1, 0, 1, 64, 30, }, ++ { 1, 1, 0, 1, 64, 30, }, ++ { 0, 1, 0, 1, 100, 32, }, ++ { 2, 1, 0, 1, 100, 30, }, ++ { 1, 1, 0, 1, 100, 30, }, ++ { 0, 1, 0, 1, 104, 32, }, ++ { 2, 1, 0, 1, 104, 30, }, ++ { 1, 1, 0, 1, 104, 30, }, ++ { 0, 1, 0, 1, 108, 32, }, ++ { 2, 1, 0, 1, 108, 30, }, ++ { 1, 1, 0, 1, 108, 30, }, ++ { 0, 1, 0, 1, 112, 32, }, ++ { 2, 1, 0, 1, 112, 30, }, ++ { 1, 1, 0, 1, 112, 30, }, ++ { 0, 1, 0, 1, 116, 32, }, ++ { 2, 1, 0, 1, 116, 30, }, ++ { 1, 1, 0, 1, 116, 30, }, ++ { 0, 1, 0, 1, 120, 32, }, ++ { 2, 1, 0, 1, 120, 30, }, ++ { 1, 1, 0, 1, 120, 30, }, ++ { 0, 1, 0, 1, 124, 32, }, ++ { 2, 1, 0, 1, 124, 30, }, ++ { 1, 1, 0, 1, 124, 30, }, ++ { 0, 1, 0, 1, 128, 32, }, ++ { 2, 1, 0, 1, 128, 30, }, ++ { 1, 1, 0, 1, 128, 30, }, ++ { 0, 1, 0, 1, 132, 32, }, ++ { 2, 1, 0, 1, 132, 30, }, ++ { 1, 1, 0, 1, 132, 30, }, ++ { 0, 1, 0, 1, 136, 32, }, ++ { 2, 1, 0, 1, 136, 30, }, ++ { 1, 1, 0, 1, 136, 30, }, ++ { 0, 1, 0, 1, 140, 32, }, ++ { 2, 1, 0, 1, 140, 30, }, ++ { 1, 1, 0, 1, 140, 30, }, ++ { 0, 1, 0, 1, 149, 32, }, ++ { 2, 1, 0, 1, 149, 30, }, ++ { 1, 1, 0, 1, 149, 63, }, ++ { 0, 1, 0, 1, 153, 32, }, ++ { 2, 1, 0, 1, 153, 30, }, ++ { 1, 1, 0, 1, 153, 63, }, ++ { 0, 1, 0, 1, 157, 32, }, ++ { 2, 1, 0, 1, 157, 30, }, ++ { 1, 1, 0, 1, 157, 63, }, ++ { 0, 1, 0, 1, 161, 32, }, ++ { 2, 1, 0, 1, 161, 30, }, ++ { 1, 1, 0, 1, 161, 63, }, ++ { 0, 1, 0, 1, 165, 32, }, ++ { 2, 1, 0, 1, 165, 30, }, ++ { 1, 1, 0, 1, 165, 63, }, ++ { 0, 1, 0, 2, 36, 32, }, ++ { 2, 1, 0, 2, 36, 30, }, ++ { 1, 1, 0, 2, 36, 30, }, ++ { 0, 1, 0, 2, 40, 32, }, ++ { 2, 1, 0, 2, 40, 30, }, ++ { 1, 1, 0, 2, 40, 30, }, ++ { 0, 1, 0, 2, 44, 32, }, ++ { 2, 1, 0, 2, 44, 30, }, ++ { 1, 1, 0, 2, 44, 30, }, ++ { 0, 1, 0, 2, 48, 32, }, ++ { 2, 1, 0, 2, 48, 30, }, ++ { 1, 1, 0, 2, 48, 30, }, ++ { 0, 1, 0, 2, 52, 32, }, ++ { 2, 1, 0, 2, 52, 30, }, ++ { 1, 1, 0, 2, 52, 30, }, ++ { 0, 1, 0, 2, 56, 32, }, ++ { 2, 1, 0, 2, 56, 30, }, ++ { 1, 1, 0, 2, 56, 30, }, ++ { 0, 1, 0, 2, 60, 32, }, ++ { 2, 1, 0, 2, 60, 30, }, ++ { 1, 1, 0, 2, 60, 30, }, ++ { 0, 1, 0, 2, 64, 32, }, ++ { 2, 1, 0, 2, 64, 30, }, ++ { 1, 1, 0, 2, 64, 30, }, ++ { 0, 1, 0, 2, 100, 32, }, ++ { 2, 1, 0, 2, 100, 30, }, ++ { 1, 1, 0, 2, 100, 30, }, ++ { 0, 1, 0, 2, 104, 32, }, ++ { 2, 1, 0, 2, 104, 30, }, ++ { 1, 1, 0, 2, 104, 30, }, ++ { 0, 1, 0, 2, 108, 32, }, ++ { 2, 1, 0, 2, 108, 30, }, ++ { 1, 1, 0, 2, 108, 30, }, ++ { 0, 1, 0, 2, 112, 32, }, ++ { 2, 1, 0, 2, 112, 30, }, ++ { 1, 1, 0, 2, 112, 30, }, ++ { 0, 1, 0, 2, 116, 32, }, ++ { 2, 1, 0, 2, 116, 30, }, ++ { 1, 1, 0, 2, 116, 30, }, ++ { 0, 1, 0, 2, 120, 32, }, ++ { 2, 1, 0, 2, 120, 30, }, ++ { 1, 1, 0, 2, 120, 30, }, ++ { 0, 1, 0, 2, 124, 32, }, ++ { 2, 1, 0, 2, 124, 30, }, ++ { 1, 1, 0, 2, 124, 30, }, ++ { 0, 1, 0, 2, 128, 32, }, ++ { 2, 1, 0, 2, 128, 30, }, ++ { 1, 1, 0, 2, 128, 30, }, ++ { 0, 1, 0, 2, 132, 32, }, ++ { 2, 1, 0, 2, 132, 30, }, ++ { 1, 1, 0, 2, 132, 30, }, ++ { 0, 1, 0, 2, 136, 32, }, ++ { 2, 1, 0, 2, 136, 30, }, ++ { 1, 1, 0, 2, 136, 30, }, ++ { 0, 1, 0, 2, 140, 32, }, ++ { 2, 1, 0, 2, 140, 30, }, ++ { 1, 1, 0, 2, 140, 30, }, ++ { 0, 1, 0, 2, 149, 32, }, ++ { 2, 1, 0, 2, 149, 30, }, ++ { 1, 1, 0, 2, 149, 63, }, ++ { 0, 1, 0, 2, 153, 32, }, ++ { 2, 1, 0, 2, 153, 30, }, ++ { 1, 1, 0, 2, 153, 63, }, ++ { 0, 1, 0, 2, 157, 32, }, ++ { 2, 1, 0, 2, 157, 30, }, ++ { 1, 1, 0, 2, 157, 63, }, ++ { 0, 1, 0, 2, 161, 32, }, ++ { 2, 1, 0, 2, 161, 30, }, ++ { 1, 1, 0, 2, 161, 63, }, ++ { 0, 1, 0, 2, 165, 32, }, ++ { 2, 1, 0, 2, 165, 30, }, ++ { 1, 1, 0, 2, 165, 63, }, ++ { 0, 1, 0, 3, 36, 28, }, ++ { 2, 1, 0, 3, 36, 30, }, ++ { 1, 1, 0, 3, 36, 30, }, ++ { 0, 1, 0, 3, 40, 28, }, ++ { 2, 1, 0, 3, 40, 30, }, ++ { 1, 1, 0, 3, 40, 30, }, ++ { 0, 1, 0, 3, 44, 28, }, ++ { 2, 1, 0, 3, 44, 30, }, ++ { 1, 1, 0, 3, 44, 30, }, ++ { 0, 1, 0, 3, 48, 28, }, ++ { 2, 1, 0, 3, 48, 30, }, ++ { 1, 1, 0, 3, 48, 30, }, ++ { 0, 1, 0, 3, 52, 34, }, ++ { 2, 1, 0, 3, 52, 30, }, ++ { 1, 1, 0, 3, 52, 30, }, ++ { 0, 1, 0, 3, 56, 32, }, ++ { 2, 1, 0, 3, 56, 30, }, ++ { 1, 1, 0, 3, 56, 30, }, ++ { 0, 1, 0, 3, 60, 30, }, ++ { 2, 1, 0, 3, 60, 30, }, ++ { 1, 1, 0, 3, 60, 30, }, ++ { 0, 1, 0, 3, 64, 26, }, ++ { 2, 1, 0, 3, 64, 30, }, ++ { 1, 1, 0, 3, 64, 30, }, ++ { 0, 1, 0, 3, 100, 28, }, ++ { 2, 1, 0, 3, 100, 30, }, ++ { 1, 1, 0, 3, 100, 30, }, ++ { 0, 1, 0, 3, 104, 28, }, ++ { 2, 1, 0, 3, 104, 30, }, ++ { 1, 1, 0, 3, 104, 30, }, ++ { 0, 1, 0, 3, 108, 30, }, ++ { 2, 1, 0, 3, 108, 30, }, ++ { 1, 1, 0, 3, 108, 30, }, ++ { 0, 1, 0, 3, 112, 32, }, ++ { 2, 1, 0, 3, 112, 30, }, ++ { 1, 1, 0, 3, 112, 30, }, ++ { 0, 1, 0, 3, 116, 32, }, ++ { 2, 1, 0, 3, 116, 30, }, ++ { 1, 1, 0, 3, 116, 30, }, ++ { 0, 1, 0, 3, 120, 34, }, ++ { 2, 1, 0, 3, 120, 30, }, ++ { 1, 1, 0, 3, 120, 30, }, ++ { 0, 1, 0, 3, 124, 32, }, ++ { 2, 1, 0, 3, 124, 30, }, ++ { 1, 1, 0, 3, 124, 30, }, ++ { 0, 1, 0, 3, 128, 30, }, ++ { 2, 1, 0, 3, 128, 30, }, ++ { 1, 1, 0, 3, 128, 30, }, ++ { 0, 1, 0, 3, 132, 28, }, ++ { 2, 1, 0, 3, 132, 30, }, ++ { 1, 1, 0, 3, 132, 30, }, ++ { 0, 1, 0, 3, 136, 28, }, ++ { 2, 1, 0, 3, 136, 30, }, ++ { 1, 1, 0, 3, 136, 30, }, ++ { 0, 1, 0, 3, 140, 26, }, ++ { 2, 1, 0, 3, 140, 30, }, ++ { 1, 1, 0, 3, 140, 30, }, ++ { 0, 1, 0, 3, 149, 34, }, ++ { 2, 1, 0, 3, 149, 30, }, ++ { 1, 1, 0, 3, 149, 63, }, ++ { 0, 1, 0, 3, 153, 34, }, ++ { 2, 1, 0, 3, 153, 30, }, ++ { 1, 1, 0, 3, 153, 63, }, ++ { 0, 1, 0, 3, 157, 34, }, ++ { 2, 1, 0, 3, 157, 30, }, ++ { 1, 1, 0, 3, 157, 63, }, ++ { 0, 1, 0, 3, 161, 34, }, ++ { 2, 1, 0, 3, 161, 30, }, ++ { 1, 1, 0, 3, 161, 63, }, ++ { 0, 1, 0, 3, 165, 34, }, ++ { 2, 1, 0, 3, 165, 30, }, ++ { 1, 1, 0, 3, 165, 63, }, ++ { 0, 1, 1, 2, 38, 26, }, ++ { 2, 1, 1, 2, 38, 30, }, ++ { 1, 1, 1, 2, 38, 30, }, ++ { 0, 1, 1, 2, 46, 32, }, ++ { 2, 1, 1, 2, 46, 30, }, ++ { 1, 1, 1, 2, 46, 30, }, ++ { 0, 1, 1, 2, 54, 32, }, ++ { 2, 1, 1, 2, 54, 30, }, ++ { 1, 1, 1, 2, 54, 30, }, ++ { 0, 1, 1, 2, 62, 24, }, ++ { 2, 1, 1, 2, 62, 30, }, ++ { 1, 1, 1, 2, 62, 30, }, ++ { 0, 1, 1, 2, 102, 24, }, ++ { 2, 1, 1, 2, 102, 30, }, ++ { 1, 1, 1, 2, 102, 30, }, ++ { 0, 1, 1, 2, 110, 32, }, ++ { 2, 1, 1, 2, 110, 30, }, ++ { 1, 1, 1, 2, 110, 30, }, ++ { 0, 1, 1, 2, 118, 32, }, ++ { 2, 1, 1, 2, 118, 30, }, ++ { 1, 1, 1, 2, 118, 30, }, ++ { 0, 1, 1, 2, 126, 32, }, ++ { 2, 1, 1, 2, 126, 30, }, ++ { 1, 1, 1, 2, 126, 30, }, ++ { 0, 1, 1, 2, 134, 32, }, ++ { 2, 1, 1, 2, 134, 30, }, ++ { 1, 1, 1, 2, 134, 30, }, ++ { 0, 1, 1, 2, 151, 30, }, ++ { 2, 1, 1, 2, 151, 30, }, ++ { 1, 1, 1, 2, 151, 63, }, ++ { 0, 1, 1, 2, 159, 32, }, ++ { 2, 1, 1, 2, 159, 30, }, ++ { 1, 1, 1, 2, 159, 63, }, ++ { 0, 1, 1, 3, 38, 28, }, ++ { 2, 1, 1, 3, 38, 30, }, ++ { 1, 1, 1, 3, 38, 30, }, ++ { 0, 1, 1, 3, 46, 28, }, ++ { 2, 1, 1, 3, 46, 30, }, ++ { 1, 1, 1, 3, 46, 30, }, ++ { 0, 1, 1, 3, 54, 30, }, ++ { 2, 1, 1, 3, 54, 30, }, ++ { 1, 1, 1, 3, 54, 30, }, ++ { 0, 1, 1, 3, 62, 30, }, ++ { 2, 1, 1, 3, 62, 30, }, ++ { 1, 1, 1, 3, 62, 30, }, ++ { 0, 1, 1, 3, 102, 26, }, ++ { 2, 1, 1, 3, 102, 30, }, ++ { 1, 1, 1, 3, 102, 30, }, ++ { 0, 1, 1, 3, 110, 30, }, ++ { 2, 1, 1, 3, 110, 30, }, ++ { 1, 1, 1, 3, 110, 30, }, ++ { 0, 1, 1, 3, 118, 34, }, ++ { 2, 1, 1, 3, 118, 30, }, ++ { 1, 1, 1, 3, 118, 30, }, ++ { 0, 1, 1, 3, 126, 32, }, ++ { 2, 1, 1, 3, 126, 30, }, ++ { 1, 1, 1, 3, 126, 30, }, ++ { 0, 1, 1, 3, 134, 30, }, ++ { 2, 1, 1, 3, 134, 30, }, ++ { 1, 1, 1, 3, 134, 30, }, ++ { 0, 1, 1, 3, 151, 34, }, ++ { 2, 1, 1, 3, 151, 30, }, ++ { 1, 1, 1, 3, 151, 63, }, ++ { 0, 1, 1, 3, 159, 34, }, ++ { 2, 1, 1, 3, 159, 30, }, ++ { 1, 1, 1, 3, 159, 63, }, ++ { 0, 1, 2, 4, 42, 22, }, ++ { 2, 1, 2, 4, 42, 30, }, ++ { 1, 1, 2, 4, 42, 30, }, ++ { 0, 1, 2, 4, 58, 20, }, ++ { 2, 1, 2, 4, 58, 30, }, ++ { 1, 1, 2, 4, 58, 30, }, ++ { 0, 1, 2, 4, 106, 20, }, ++ { 2, 1, 2, 4, 106, 30, }, ++ { 1, 1, 2, 4, 106, 30, }, ++ { 0, 1, 2, 4, 122, 20, }, ++ { 2, 1, 2, 4, 122, 30, }, ++ { 1, 1, 2, 4, 122, 30, }, ++ { 0, 1, 2, 4, 155, 28, }, ++ { 2, 1, 2, 4, 155, 30, }, ++ { 1, 1, 2, 4, 155, 63, }, ++ { 0, 1, 2, 5, 42, 28, }, ++ { 2, 1, 2, 5, 42, 30, }, ++ { 1, 1, 2, 5, 42, 30, }, ++ { 0, 1, 2, 5, 58, 26, }, ++ { 2, 1, 2, 5, 58, 30, }, ++ { 1, 1, 2, 5, 58, 30, }, ++ { 0, 1, 2, 5, 106, 28, }, ++ { 2, 1, 2, 5, 106, 30, }, ++ { 1, 1, 2, 5, 106, 30, }, ++ { 0, 1, 2, 5, 122, 32, }, ++ { 2, 1, 2, 5, 122, 30, }, ++ { 1, 1, 2, 5, 122, 30, }, ++ { 0, 1, 2, 5, 155, 34, }, ++ { 2, 1, 2, 5, 155, 30, }, ++ { 1, 1, 2, 5, 155, 63, }, ++}; ++ ++RTW_DECL_TABLE_TXPWR_LMT(rtw8821a_txpwr_lmt); ++ ++static const struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8821a[] = { ++ {0x0005, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(3) | BIT(7), 0}, ++ {0x0086, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_SDIO_MSK, ++ RTW_PWR_ADDR_SDIO, ++ RTW_PWR_CMD_WRITE, BIT(0), 0}, ++ {0x0086, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_SDIO_MSK, ++ RTW_PWR_ADDR_SDIO, ++ RTW_PWR_CMD_POLLING, BIT(1), BIT(1)}, ++ {0x004A, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_USB_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(0), 0}, ++ {0x0005, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(3) | BIT(4), 0}, ++ {0x0023, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_SDIO_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(4), 0}, ++ {0x0301, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_PCI_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, 0xFF, 0}, ++ {0xFFFF, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ 0, ++ RTW_PWR_CMD_END, 0, 0}, ++}; ++ ++static const struct rtw_pwr_seq_cmd trans_cardemu_to_act_8821a[] = { ++ {0x0020, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(0), BIT(0)}, ++ {0x0067, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(4), 0}, ++ {0x0001, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_DELAY, 1, RTW_PWR_DELAY_MS}, ++ {0x0000, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(5), 0}, ++ {0x0005, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(4) | BIT(3) | BIT(2), 0}, ++ {0x0075, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_PCI_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(0), BIT(0)}, ++ {0x0006, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_POLLING, BIT(1), BIT(1)}, ++ {0x0075, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_PCI_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(0), 0}, ++ {0x0006, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(0), BIT(0)}, ++ {0x0005, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(7), 0}, ++ {0x0005, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(4) | BIT(3), 0}, ++ {0x0005, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(0), BIT(0)}, ++ {0x0005, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_POLLING, BIT(0), 0}, ++ {0x004F, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(0), BIT(0)}, ++ {0x0067, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(5) | BIT(4), BIT(5) | BIT(4)}, ++ {0x0025, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(6), 0}, ++ {0x0049, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(1), BIT(1)}, ++ {0x0063, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(1), BIT(1)}, ++ {0x0062, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(1), 0}, ++ {0x0058, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(0), BIT(0)}, ++ {0x005A, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(1), BIT(1)}, ++ {0x002E, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, 0xFF, 0x82}, ++ {0x0010, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(6), BIT(6)}, ++ {0xFFFF, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ 0, ++ RTW_PWR_CMD_END, 0, 0}, ++}; ++ ++static const struct rtw_pwr_seq_cmd trans_act_to_lps_8821a[] = { ++ {0x0301, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_PCI_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, 0xFF, 0xFF}, ++ {0x0522, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, 0xFF, 0xFF}, ++ {0x05F8, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_POLLING, 0xFF, 0}, ++ {0x05F9, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_POLLING, 0xFF, 0}, ++ {0x05FA, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_POLLING, 0xFF, 0}, ++ {0x05FB, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_POLLING, 0xFF, 0}, ++ {0x0002, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(0), 0}, ++ {0x0002, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_DELAY, 0, RTW_PWR_DELAY_US}, ++ {0x0002, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(1), 0}, ++ {0x0100, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, 0xFF, 0x03}, ++ {0x0101, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(1), 0}, ++ {0x0093, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_SDIO_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, 0xFF, 0x00}, ++ {0x0553, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(5), BIT(5)}, ++ {0xFFFF, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ 0, ++ RTW_PWR_CMD_END, 0, 0}, ++}; ++ ++static const struct rtw_pwr_seq_cmd trans_act_to_cardemu_8821a[] = { ++ {0x001F, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, 0xFF, 0}, ++ {0x004F, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(0), 0}, ++ {0x0049, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(1), 0}, ++ {0x0006, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_USB_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(0), BIT(0)}, ++ {0x0005, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(1), BIT(1)}, ++ {0x0005, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_POLLING, BIT(1), 0}, ++ {0x0000, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(5), BIT(5)}, ++ {0x0020, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(0), 0}, ++ {0xFFFF, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ 0, ++ RTW_PWR_CMD_END, 0, 0}, ++}; ++ ++static const struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8821a[] = { ++ {0x0007, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_SDIO_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, 0xFF, 0x20}, ++ {0x0005, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(3) | BIT(4), BIT(3)}, ++ {0x0005, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_PCI_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(2), BIT(2)}, ++ {0x004A, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_USB_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(0), 1}, ++ {0x0023, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_SDIO_MSK, ++ RTW_PWR_ADDR_MAC, ++ RTW_PWR_CMD_WRITE, BIT(4), BIT(4)}, ++ {0x0086, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_SDIO_MSK, ++ RTW_PWR_ADDR_SDIO, ++ RTW_PWR_CMD_WRITE, BIT(0), BIT(0)}, ++ {0x0086, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_SDIO_MSK, ++ RTW_PWR_ADDR_SDIO, ++ RTW_PWR_CMD_POLLING, BIT(1), 0}, ++ {0xFFFF, ++ RTW_PWR_CUT_ALL_MSK, ++ RTW_PWR_INTF_ALL_MSK, ++ 0, ++ RTW_PWR_CMD_END, 0, 0}, ++}; ++ ++const struct rtw_pwr_seq_cmd * const card_enable_flow_8821a[] = { ++ trans_carddis_to_cardemu_8821a, ++ trans_cardemu_to_act_8821a, ++ NULL ++}; ++ ++const struct rtw_pwr_seq_cmd * const enter_lps_flow_8821a[] = { ++ trans_act_to_lps_8821a, ++ NULL ++}; ++ ++const struct rtw_pwr_seq_cmd * const card_disable_flow_8821a[] = { ++ trans_act_to_cardemu_8821a, ++ trans_cardemu_to_carddis_8821a, ++ NULL ++}; ++ ++static const u8 rtw8821a_pwrtrk_5gb_n[][RTW_PWR_TRK_TBL_SZ] = { ++ {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15, ++ 15, 16, 16, 16, 16, 16, 16, 16, 16}, ++ {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15, ++ 15, 16, 16, 16, 16, 16, 16, 16, 16}, ++ {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15, ++ 15, 16, 16, 16, 16, 16, 16, 16, 16}, ++}; ++ ++static const u8 rtw8821a_pwrtrk_5gb_p[][RTW_PWR_TRK_TBL_SZ] = { ++ {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15, ++ 15, 16, 16, 16, 16, 16, 16, 16, 16}, ++ {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15, ++ 15, 16, 16, 16, 16, 16, 16, 16, 16}, ++ {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15, ++ 15, 16, 16, 16, 16, 16, 16, 16, 16}, ++}; ++ ++static const u8 rtw8821a_pwrtrk_5ga_n[][RTW_PWR_TRK_TBL_SZ] = { ++ {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15, ++ 15, 16, 16, 16, 16, 16, 16, 16, 16}, ++ {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15, ++ 15, 16, 16, 16, 16, 16, 16, 16, 16}, ++ {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15, ++ 15, 16, 16, 16, 16, 16, 16, 16, 16}, ++}; ++ ++static const u8 rtw8821a_pwrtrk_5ga_p[][RTW_PWR_TRK_TBL_SZ] = { ++ {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15, ++ 15, 16, 16, 16, 16, 16, 16, 16, 16}, ++ {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15, ++ 15, 16, 16, 16, 16, 16, 16, 16, 16}, ++ {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15, ++ 15, 16, 16, 16, 16, 16, 16, 16, 16}, ++}; ++ ++static const u8 rtw8821a_pwrtrk_2gb_n[] = { ++ 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, ++ 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10 ++}; ++ ++static const u8 rtw8821a_pwrtrk_2gb_p[] = { ++ 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, ++ 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 12, 12 ++}; ++ ++static const u8 rtw8821a_pwrtrk_2ga_n[] = { ++ 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, ++ 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10 ++}; ++ ++static const u8 rtw8821a_pwrtrk_2ga_p[] = { ++ 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, ++ 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 12, 12 ++}; ++ ++static const u8 rtw8821a_pwrtrk_2g_cck_b_n[] = { ++ 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, ++ 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10 ++}; ++ ++static const u8 rtw8821a_pwrtrk_2g_cck_b_p[] = { ++ 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, ++ 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 12, 12 ++}; ++ ++static const u8 rtw8821a_pwrtrk_2g_cck_a_n[] = { ++ 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, ++ 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10 ++}; ++ ++static const u8 rtw8821a_pwrtrk_2g_cck_a_p[] = { ++ 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, ++ 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 12, 12 ++}; ++ ++const struct rtw_pwr_track_tbl rtw8821a_rtw_pwr_track_tbl = { ++ .pwrtrk_5gb_n[0] = rtw8821a_pwrtrk_5gb_n[0], ++ .pwrtrk_5gb_n[1] = rtw8821a_pwrtrk_5gb_n[1], ++ .pwrtrk_5gb_n[2] = rtw8821a_pwrtrk_5gb_n[2], ++ .pwrtrk_5gb_p[0] = rtw8821a_pwrtrk_5gb_p[0], ++ .pwrtrk_5gb_p[1] = rtw8821a_pwrtrk_5gb_p[1], ++ .pwrtrk_5gb_p[2] = rtw8821a_pwrtrk_5gb_p[2], ++ .pwrtrk_5ga_n[0] = rtw8821a_pwrtrk_5ga_n[0], ++ .pwrtrk_5ga_n[1] = rtw8821a_pwrtrk_5ga_n[1], ++ .pwrtrk_5ga_n[2] = rtw8821a_pwrtrk_5ga_n[2], ++ .pwrtrk_5ga_p[0] = rtw8821a_pwrtrk_5ga_p[0], ++ .pwrtrk_5ga_p[1] = rtw8821a_pwrtrk_5ga_p[1], ++ .pwrtrk_5ga_p[2] = rtw8821a_pwrtrk_5ga_p[2], ++ .pwrtrk_2gb_n = rtw8821a_pwrtrk_2gb_n, ++ .pwrtrk_2gb_p = rtw8821a_pwrtrk_2gb_p, ++ .pwrtrk_2ga_n = rtw8821a_pwrtrk_2ga_n, ++ .pwrtrk_2ga_p = rtw8821a_pwrtrk_2ga_p, ++ .pwrtrk_2g_cckb_n = rtw8821a_pwrtrk_2g_cck_b_n, ++ .pwrtrk_2g_cckb_p = rtw8821a_pwrtrk_2g_cck_b_p, ++ .pwrtrk_2g_ccka_n = rtw8821a_pwrtrk_2g_cck_a_n, ++ .pwrtrk_2g_ccka_p = rtw8821a_pwrtrk_2g_cck_a_p, ++}; +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821a_table.h b/drivers/net/wireless/realtek/rtw88/rtw8821a_table.h +new file mode 100644 +index 000000000000..90379ac7a817 +--- /dev/null ++++ b/drivers/net/wireless/realtek/rtw88/rtw8821a_table.h +@@ -0,0 +1,21 @@ ++/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ ++/* Copyright(c) 2024 Realtek Corporation ++ */ ++ ++#ifndef __RTW8821A_TABLE_H__ ++#define __RTW8821A_TABLE_H__ ++ ++extern const struct rtw_table rtw8821a_mac_tbl; ++extern const struct rtw_table rtw8821a_agc_tbl; ++extern const struct rtw_table rtw8821a_bb_tbl; ++extern const struct rtw_table rtw8821a_bb_pg_tbl; ++extern const struct rtw_table rtw8821a_rf_a_tbl; ++extern const struct rtw_table rtw8821a_txpwr_lmt_tbl; ++ ++extern const struct rtw_pwr_seq_cmd * const card_enable_flow_8821a[]; ++extern const struct rtw_pwr_seq_cmd * const enter_lps_flow_8821a[]; ++extern const struct rtw_pwr_seq_cmd * const card_disable_flow_8821a[]; ++ ++extern const struct rtw_pwr_track_tbl rtw8821a_rtw_pwr_track_tbl; ++ ++#endif +-- +2.39.5 + diff --git a/packages/linux/patches/rtlwifi/6.13/0020-wifi-rtw88-Add-rtw88xxa.-c-h.patch b/packages/linux/patches/rtlwifi/6.13/0020-wifi-rtw88-Add-rtw88xxa.-c-h.patch new file mode 100644 index 0000000000..4c2884e819 --- /dev/null +++ b/packages/linux/patches/rtlwifi/6.13/0020-wifi-rtw88-Add-rtw88xxa.-c-h.patch @@ -0,0 +1,2196 @@ +From acb1602c05c12f37ca562e00ac3157ee11f52920 Mon Sep 17 00:00:00 2001 +From: Bitterblue Smith +Date: Wed, 30 Oct 2024 20:27:39 +0200 +Subject: [PATCH 20/24] wifi: rtw88: Add rtw88xxa.{c,h} + +These contain code shared by both RTL8821AU and RTL8812AU chips. + +Signed-off-by: Bitterblue Smith +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/b8590382-a954-412d-a96b-63e360b97acc@gmail.com +--- + drivers/net/wireless/realtek/rtw88/rtw88xxa.c | 1989 +++++++++++++++++ + drivers/net/wireless/realtek/rtw88/rtw88xxa.h | 175 ++ + 2 files changed, 2164 insertions(+) + create mode 100644 drivers/net/wireless/realtek/rtw88/rtw88xxa.c + create mode 100644 drivers/net/wireless/realtek/rtw88/rtw88xxa.h + +diff --git a/drivers/net/wireless/realtek/rtw88/rtw88xxa.c b/drivers/net/wireless/realtek/rtw88/rtw88xxa.c +new file mode 100644 +index 000000000000..71e61b9c0bec +--- /dev/null ++++ b/drivers/net/wireless/realtek/rtw88/rtw88xxa.c +@@ -0,0 +1,1989 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause ++/* Copyright(c) 2024 Realtek Corporation ++ */ ++ ++#include ++#include "main.h" ++#include "coex.h" ++#include "phy.h" ++#include "rtw88xxa.h" ++#include "mac.h" ++#include "reg.h" ++#include "sec.h" ++#include "debug.h" ++#include "bf.h" ++#include "efuse.h" ++#include "usb.h" ++ ++void rtw88xxa_efuse_grant(struct rtw_dev *rtwdev, bool on) ++{ ++ if (on) { ++ rtw_write8(rtwdev, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON); ++ ++ rtw_write16_set(rtwdev, REG_SYS_FUNC_EN, BIT_FEN_ELDR); ++ rtw_write16_set(rtwdev, REG_SYS_CLKR, ++ BIT_LOADER_CLK_EN | BIT_ANA8M); ++ } else { ++ rtw_write8(rtwdev, REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF); ++ } ++} ++EXPORT_SYMBOL(rtw88xxa_efuse_grant); ++ ++static void rtw8812a_read_amplifier_type(struct rtw_dev *rtwdev) ++{ ++ struct rtw_efuse *efuse = &rtwdev->efuse; ++ ++ efuse->ext_pa_2g = (efuse->pa_type_2g & BIT(5)) && ++ (efuse->pa_type_2g & BIT(4)); ++ efuse->ext_lna_2g = (efuse->lna_type_2g & BIT(7)) && ++ (efuse->lna_type_2g & BIT(3)); ++ ++ efuse->ext_pa_5g = (efuse->pa_type_5g & BIT(1)) && ++ (efuse->pa_type_5g & BIT(0)); ++ efuse->ext_lna_5g = (efuse->lna_type_5g & BIT(7)) && ++ (efuse->lna_type_5g & BIT(3)); ++ ++ /* For rtw_phy_cond2: */ ++ if (efuse->ext_pa_2g) { ++ u8 ext_type_pa_2g_a = u8_get_bits(efuse->lna_type_2g, BIT(2)); ++ u8 ext_type_pa_2g_b = u8_get_bits(efuse->lna_type_2g, BIT(6)); ++ ++ efuse->gpa_type = (ext_type_pa_2g_b << 2) | ext_type_pa_2g_a; ++ } ++ ++ if (efuse->ext_pa_5g) { ++ u8 ext_type_pa_5g_a = u8_get_bits(efuse->lna_type_5g, BIT(2)); ++ u8 ext_type_pa_5g_b = u8_get_bits(efuse->lna_type_5g, BIT(6)); ++ ++ efuse->apa_type = (ext_type_pa_5g_b << 2) | ext_type_pa_5g_a; ++ } ++ ++ if (efuse->ext_lna_2g) { ++ u8 ext_type_lna_2g_a = u8_get_bits(efuse->lna_type_2g, ++ BIT(1) | BIT(0)); ++ u8 ext_type_lna_2g_b = u8_get_bits(efuse->lna_type_2g, ++ BIT(5) | BIT(4)); ++ ++ efuse->glna_type = (ext_type_lna_2g_b << 2) | ext_type_lna_2g_a; ++ } ++ ++ if (efuse->ext_lna_5g) { ++ u8 ext_type_lna_5g_a = u8_get_bits(efuse->lna_type_5g, ++ BIT(1) | BIT(0)); ++ u8 ext_type_lna_5g_b = u8_get_bits(efuse->lna_type_5g, ++ BIT(5) | BIT(4)); ++ ++ efuse->alna_type = (ext_type_lna_5g_b << 2) | ext_type_lna_5g_a; ++ } ++} ++ ++static void rtw8812a_read_rfe_type(struct rtw_dev *rtwdev, ++ struct rtw88xxa_efuse *map) ++{ ++ struct rtw_efuse *efuse = &rtwdev->efuse; ++ ++ if (map->rfe_option == 0xff) { ++ if (rtwdev->hci.type == RTW_HCI_TYPE_USB) ++ efuse->rfe_option = 0; ++ else if (rtwdev->hci.type == RTW_HCI_TYPE_PCIE) ++ efuse->rfe_option = 2; ++ else ++ efuse->rfe_option = 4; ++ } else if (map->rfe_option & BIT(7)) { ++ if (efuse->ext_lna_5g) { ++ if (efuse->ext_pa_5g) { ++ if (efuse->ext_lna_2g && efuse->ext_pa_2g) ++ efuse->rfe_option = 3; ++ else ++ efuse->rfe_option = 0; ++ } else { ++ efuse->rfe_option = 2; ++ } ++ } else { ++ efuse->rfe_option = 4; ++ } ++ } else { ++ efuse->rfe_option = map->rfe_option & 0x3f; ++ ++ /* Due to other customer already use incorrect EFUSE map for ++ * their product. We need to add workaround to prevent to ++ * modify spec and notify all customer to revise the IC 0xca ++ * content. ++ */ ++ if (efuse->rfe_option == 4 && ++ (efuse->ext_pa_5g || efuse->ext_pa_2g || ++ efuse->ext_lna_5g || efuse->ext_lna_2g)) { ++ if (rtwdev->hci.type == RTW_HCI_TYPE_USB) ++ efuse->rfe_option = 0; ++ else if (rtwdev->hci.type == RTW_HCI_TYPE_PCIE) ++ efuse->rfe_option = 2; ++ } ++ } ++} ++ ++static void rtw88xxa_read_usb_type(struct rtw_dev *rtwdev) ++{ ++ struct rtw_efuse *efuse = &rtwdev->efuse; ++ struct rtw_hal *hal = &rtwdev->hal; ++ u8 antenna = 0; ++ u8 wmode = 0; ++ u8 val8, i; ++ ++ efuse->hw_cap.bw = BIT(RTW_CHANNEL_WIDTH_20) | ++ BIT(RTW_CHANNEL_WIDTH_40) | ++ BIT(RTW_CHANNEL_WIDTH_80); ++ efuse->hw_cap.ptcl = EFUSE_HW_CAP_PTCL_VHT; ++ ++ if (rtwdev->chip->id == RTW_CHIP_TYPE_8821A) ++ efuse->hw_cap.nss = 1; ++ else ++ efuse->hw_cap.nss = 2; ++ ++ if (rtwdev->chip->id == RTW_CHIP_TYPE_8821A) ++ goto print_hw_cap; ++ ++ for (i = 0; i < 2; i++) { ++ rtw_read8_physical_efuse(rtwdev, 1019 - i, &val8); ++ ++ antenna = u8_get_bits(val8, GENMASK(7, 5)); ++ if (antenna) ++ break; ++ antenna = u8_get_bits(val8, GENMASK(3, 1)); ++ if (antenna) ++ break; ++ } ++ ++ for (i = 0; i < 2; i++) { ++ rtw_read8_physical_efuse(rtwdev, 1021 - i, &val8); ++ ++ wmode = u8_get_bits(val8, GENMASK(3, 2)); ++ if (wmode) ++ break; ++ } ++ ++ if (antenna == 1) { ++ rtw_info(rtwdev, "This RTL8812AU says it is 1T1R.\n"); ++ ++ efuse->hw_cap.nss = 1; ++ hal->rf_type = RF_1T1R; ++ hal->rf_path_num = 1; ++ hal->rf_phy_num = 1; ++ hal->antenna_tx = BB_PATH_A; ++ hal->antenna_rx = BB_PATH_A; ++ } else { ++ /* Override rtw_chip_parameter_setup(). It detects 8812au as 1T1R. */ ++ efuse->hw_cap.nss = 2; ++ hal->rf_type = RF_2T2R; ++ hal->rf_path_num = 2; ++ hal->rf_phy_num = 2; ++ hal->antenna_tx = BB_PATH_AB; ++ hal->antenna_rx = BB_PATH_AB; ++ ++ if (antenna == 2 && wmode == 2) { ++ rtw_info(rtwdev, "This RTL8812AU says it can't do VHT.\n"); ++ ++ /* Can't be EFUSE_HW_CAP_IGNORE and can't be ++ * EFUSE_HW_CAP_PTCL_VHT, so make it 1. ++ */ ++ efuse->hw_cap.ptcl = 1; ++ efuse->hw_cap.bw &= ~BIT(RTW_CHANNEL_WIDTH_80); ++ } ++ } ++ ++print_hw_cap: ++ rtw_dbg(rtwdev, RTW_DBG_EFUSE, ++ "hw cap: hci=0x%02x, bw=0x%02x, ptcl=0x%02x, ant_num=%d, nss=%d\n", ++ efuse->hw_cap.hci, efuse->hw_cap.bw, efuse->hw_cap.ptcl, ++ efuse->hw_cap.ant_num, efuse->hw_cap.nss); ++} ++ ++int rtw88xxa_read_efuse(struct rtw_dev *rtwdev, u8 *log_map) ++{ ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ struct rtw_efuse *efuse = &rtwdev->efuse; ++ struct rtw88xxa_efuse *map; ++ int i; ++ ++ if (chip->id == RTW_CHIP_TYPE_8812A) ++ rtwdev->hal.cut_version += 1; ++ ++ if (rtw_dbg_is_enabled(rtwdev, RTW_DBG_EFUSE)) ++ print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1, ++ log_map, chip->log_efuse_size, true); ++ ++ map = (struct rtw88xxa_efuse *)log_map; ++ ++ efuse->rf_board_option = map->rf_board_option; ++ efuse->crystal_cap = map->xtal_k; ++ if (efuse->crystal_cap == 0xff) ++ efuse->crystal_cap = 0x20; ++ efuse->pa_type_2g = map->pa_type; ++ efuse->pa_type_5g = map->pa_type; ++ efuse->lna_type_2g = map->lna_type_2g; ++ efuse->lna_type_5g = map->lna_type_5g; ++ if (chip->id == RTW_CHIP_TYPE_8812A) { ++ rtw8812a_read_amplifier_type(rtwdev); ++ rtw8812a_read_rfe_type(rtwdev, map); ++ ++ efuse->usb_mode_switch = u8_get_bits(map->usb_mode, BIT(1)); ++ } ++ efuse->channel_plan = map->channel_plan; ++ efuse->country_code[0] = map->country_code[0]; ++ efuse->country_code[1] = map->country_code[1]; ++ efuse->bt_setting = map->rf_bt_setting; ++ efuse->regd = map->rf_board_option & 0x7; ++ efuse->thermal_meter[0] = map->thermal_meter; ++ efuse->thermal_meter[1] = map->thermal_meter; ++ efuse->thermal_meter_k = map->thermal_meter; ++ efuse->tx_bb_swing_setting_2g = map->tx_bb_swing_setting_2g; ++ efuse->tx_bb_swing_setting_5g = map->tx_bb_swing_setting_5g; ++ ++ rtw88xxa_read_usb_type(rtwdev); ++ ++ if (chip->id == RTW_CHIP_TYPE_8821A) ++ efuse->btcoex = rtw_read32_mask(rtwdev, REG_WL_BT_PWR_CTRL, ++ BIT_BT_FUNC_EN); ++ else ++ efuse->btcoex = (map->rf_board_option & 0xe0) == 0x20; ++ efuse->share_ant = !!(efuse->bt_setting & BIT(0)); ++ ++ /* No antenna diversity because it's disabled in the vendor driver */ ++ efuse->ant_div_cfg = 0; ++ ++ efuse->ant_div_type = map->rf_antenna_option; ++ if (efuse->ant_div_type == 0xff) ++ efuse->ant_div_type = 0x3; ++ ++ for (i = 0; i < 4; i++) ++ efuse->txpwr_idx_table[i] = map->txpwr_idx_table[i]; ++ ++ switch (rtw_hci_type(rtwdev)) { ++ case RTW_HCI_TYPE_USB: ++ if (chip->id == RTW_CHIP_TYPE_8821A) ++ ether_addr_copy(efuse->addr, map->rtw8821au.mac_addr); ++ else ++ ether_addr_copy(efuse->addr, map->rtw8812au.mac_addr); ++ break; ++ case RTW_HCI_TYPE_PCIE: ++ case RTW_HCI_TYPE_SDIO: ++ default: ++ /* unsupported now */ ++ return -EOPNOTSUPP; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(rtw88xxa_read_efuse); ++ ++static void rtw88xxa_reset_8051(struct rtw_dev *rtwdev) ++{ ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ u8 val8; ++ ++ /* Reset MCU IO Wrapper */ ++ rtw_write8_clr(rtwdev, REG_RSV_CTRL, BIT(1)); ++ if (chip->id == RTW_CHIP_TYPE_8812A) ++ rtw_write8_clr(rtwdev, REG_RSV_CTRL + 1, BIT(3)); ++ else ++ rtw_write8_clr(rtwdev, REG_RSV_CTRL + 1, BIT(0)); ++ ++ val8 = rtw_read8(rtwdev, REG_SYS_FUNC_EN + 1); ++ rtw_write8(rtwdev, REG_SYS_FUNC_EN + 1, val8 & ~BIT(2)); ++ ++ /* Enable MCU IO Wrapper */ ++ rtw_write8_clr(rtwdev, REG_RSV_CTRL, BIT(1)); ++ if (chip->id == RTW_CHIP_TYPE_8812A) ++ rtw_write8_set(rtwdev, REG_RSV_CTRL + 1, BIT(3)); ++ else ++ rtw_write8_set(rtwdev, REG_RSV_CTRL + 1, BIT(0)); ++ ++ rtw_write8(rtwdev, REG_SYS_FUNC_EN + 1, val8 | BIT(2)); ++} ++ ++/* A lightweight deinit function */ ++static void rtw88xxau_hw_reset(struct rtw_dev *rtwdev) ++{ ++ u8 val8; ++ ++ if (!(rtw_read8(rtwdev, REG_MCUFW_CTRL) & BIT_RAM_DL_SEL)) ++ return; ++ ++ rtw88xxa_reset_8051(rtwdev); ++ rtw_write8(rtwdev, REG_MCUFW_CTRL, 0x00); ++ ++ /* before BB reset should do clock gated */ ++ rtw_write32_set(rtwdev, REG_FPGA0_XCD_RF_PARA, BIT(6)); ++ ++ /* reset BB */ ++ rtw_write8_clr(rtwdev, REG_SYS_FUNC_EN, BIT(0) | BIT(1)); ++ ++ /* reset RF */ ++ rtw_write8(rtwdev, REG_RF_CTRL, 0); ++ ++ /* reset TRX path */ ++ rtw_write16(rtwdev, REG_CR, 0); ++ ++ /* reset MAC, reg0x5[1], auto FSM off */ ++ rtw_write8_set(rtwdev, REG_APS_FSMCO + 1, APS_FSMCO_MAC_OFF >> 8); ++ ++ /* check if reg0x5[1] auto cleared */ ++ if (read_poll_timeout_atomic(rtw_read8, val8, ++ !(val8 & (APS_FSMCO_MAC_OFF >> 8)), ++ 1, 5000, false, ++ rtwdev, REG_APS_FSMCO + 1)) ++ rtw_err(rtwdev, "%s: timed out waiting for 0x5[1]\n", __func__); ++ ++ /* reg0x5[0], auto FSM on */ ++ val8 |= APS_FSMCO_MAC_ENABLE >> 8; ++ rtw_write8(rtwdev, REG_APS_FSMCO + 1, val8); ++ ++ rtw_write8_clr(rtwdev, REG_SYS_FUNC_EN + 1, BIT(4) | BIT(7)); ++ rtw_write8_set(rtwdev, REG_SYS_FUNC_EN + 1, BIT(4) | BIT(7)); ++} ++ ++static int rtw88xxau_init_power_on(struct rtw_dev *rtwdev) ++{ ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ u16 val16; ++ int ret; ++ ++ ret = rtw_pwr_seq_parser(rtwdev, chip->pwr_on_seq); ++ if (ret) { ++ rtw_err(rtwdev, "power on flow failed\n"); ++ return ret; ++ } ++ ++ rtw_write16(rtwdev, REG_CR, 0); ++ val16 = BIT_HCI_TXDMA_EN | BIT_HCI_RXDMA_EN | BIT_TXDMA_EN | ++ BIT_RXDMA_EN | BIT_PROTOCOL_EN | BIT_SCHEDULE_EN | ++ BIT_MAC_SEC_EN | BIT_32K_CAL_TMR_EN; ++ rtw_write16_set(rtwdev, REG_CR, val16); ++ ++ if (chip->id == RTW_CHIP_TYPE_8821A) { ++ if (rtw_read8(rtwdev, REG_SYS_CFG1 + 3) & BIT(0)) ++ rtw_write8_set(rtwdev, REG_LDO_SWR_CTRL, BIT(6)); ++ } ++ ++ return ret; ++} ++ ++static int rtw88xxa_llt_write(struct rtw_dev *rtwdev, u32 address, u32 data) ++{ ++ u32 value = BIT_LLT_WRITE_ACCESS | (address << 8) | data; ++ int count = 0; ++ ++ rtw_write32(rtwdev, REG_LLT_INIT, value); ++ ++ do { ++ if (!rtw_read32_mask(rtwdev, REG_LLT_INIT, BIT(31) | BIT(30))) ++ break; ++ ++ if (count > 20) { ++ rtw_err(rtwdev, "Failed to poll write LLT done at %d!\n", ++ address); ++ return -EBUSY; ++ } ++ } while (++count); ++ ++ return 0; ++} ++ ++static int rtw88xxa_llt_init(struct rtw_dev *rtwdev, u32 boundary) ++{ ++ u32 last_entry = 255; ++ int status = 0; ++ u32 i; ++ ++ for (i = 0; i < boundary - 1; i++) { ++ status = rtw88xxa_llt_write(rtwdev, i, i + 1); ++ if (status) ++ return status; ++ } ++ ++ status = rtw88xxa_llt_write(rtwdev, boundary - 1, 0xFF); ++ if (status) ++ return status; ++ ++ for (i = boundary; i < last_entry; i++) { ++ status = rtw88xxa_llt_write(rtwdev, i, i + 1); ++ if (status) ++ return status; ++ } ++ ++ status = rtw88xxa_llt_write(rtwdev, last_entry, boundary); ++ ++ return status; ++} ++ ++static void rtw88xxau_init_queue_reserved_page(struct rtw_dev *rtwdev) ++{ ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ struct rtw_fifo_conf *fifo = &rtwdev->fifo; ++ const struct rtw_page_table *pg_tbl = NULL; ++ u16 pubq_num; ++ u32 val32; ++ ++ switch (rtw_hci_type(rtwdev)) { ++ case RTW_HCI_TYPE_PCIE: ++ pg_tbl = &chip->page_table[1]; ++ break; ++ case RTW_HCI_TYPE_USB: ++ if (rtwdev->hci.bulkout_num == 2) ++ pg_tbl = &chip->page_table[2]; ++ else if (rtwdev->hci.bulkout_num == 3) ++ pg_tbl = &chip->page_table[3]; ++ else if (rtwdev->hci.bulkout_num == 4) ++ pg_tbl = &chip->page_table[4]; ++ break; ++ case RTW_HCI_TYPE_SDIO: ++ pg_tbl = &chip->page_table[0]; ++ break; ++ default: ++ break; ++ } ++ ++ pubq_num = fifo->acq_pg_num - pg_tbl->hq_num - pg_tbl->lq_num - ++ pg_tbl->nq_num - pg_tbl->exq_num - pg_tbl->gapq_num; ++ ++ val32 = BIT_RQPN_NE(pg_tbl->nq_num, pg_tbl->exq_num); ++ rtw_write32(rtwdev, REG_RQPN_NPQ, val32); ++ ++ val32 = BIT_RQPN_HLP(pg_tbl->hq_num, pg_tbl->lq_num, pubq_num); ++ rtw_write32(rtwdev, REG_RQPN, val32); ++} ++ ++static void rtw88xxau_init_tx_buffer_boundary(struct rtw_dev *rtwdev) ++{ ++ struct rtw_fifo_conf *fifo = &rtwdev->fifo; ++ ++ rtw_write8(rtwdev, REG_BCNQ_BDNY, fifo->rsvd_boundary); ++ rtw_write8(rtwdev, REG_MGQ_BDNY, fifo->rsvd_boundary); ++ rtw_write8(rtwdev, REG_WMAC_LBK_BF_HD, fifo->rsvd_boundary); ++ rtw_write8(rtwdev, REG_TRXFF_BNDY, fifo->rsvd_boundary); ++ rtw_write8(rtwdev, REG_DWBCN0_CTRL + 1, fifo->rsvd_boundary); ++} ++ ++static int rtw88xxau_init_queue_priority(struct rtw_dev *rtwdev) ++{ ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ u8 bulkout_num = rtwdev->hci.bulkout_num; ++ const struct rtw_rqpn *rqpn = NULL; ++ u16 txdma_pq_map; ++ ++ switch (rtw_hci_type(rtwdev)) { ++ case RTW_HCI_TYPE_PCIE: ++ rqpn = &chip->rqpn_table[1]; ++ break; ++ case RTW_HCI_TYPE_USB: ++ if (bulkout_num == 2) ++ rqpn = &chip->rqpn_table[2]; ++ else if (bulkout_num == 3) ++ rqpn = &chip->rqpn_table[3]; ++ else if (bulkout_num == 4) ++ rqpn = &chip->rqpn_table[4]; ++ else ++ return -EINVAL; ++ break; ++ case RTW_HCI_TYPE_SDIO: ++ rqpn = &chip->rqpn_table[0]; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ rtwdev->fifo.rqpn = rqpn; ++ ++ txdma_pq_map = rtw_read16(rtwdev, REG_TXDMA_PQ_MAP) & 0x7; ++ txdma_pq_map |= BIT_TXDMA_HIQ_MAP(rqpn->dma_map_hi); ++ txdma_pq_map |= BIT_TXDMA_MGQ_MAP(rqpn->dma_map_mg); ++ txdma_pq_map |= BIT_TXDMA_BKQ_MAP(rqpn->dma_map_bk); ++ txdma_pq_map |= BIT_TXDMA_BEQ_MAP(rqpn->dma_map_be); ++ txdma_pq_map |= BIT_TXDMA_VIQ_MAP(rqpn->dma_map_vi); ++ txdma_pq_map |= BIT_TXDMA_VOQ_MAP(rqpn->dma_map_vo); ++ rtw_write16(rtwdev, REG_TXDMA_PQ_MAP, txdma_pq_map); ++ ++ /* Packet in Hi Queue Tx immediately (No constraint for ATIM Period). */ ++ if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_USB && bulkout_num == 4) ++ rtw_write8(rtwdev, REG_HIQ_NO_LMT_EN, 0xff); ++ ++ return 0; ++} ++ ++static void rtw88xxa_init_wmac_setting(struct rtw_dev *rtwdev) ++{ ++ rtw_write16(rtwdev, REG_RXFLTMAP0, 0xffff); ++ rtw_write16(rtwdev, REG_RXFLTMAP1, 0x0400); ++ rtw_write16(rtwdev, REG_RXFLTMAP2, 0xffff); ++ ++ rtw_write32(rtwdev, REG_MAR, 0xffffffff); ++ rtw_write32(rtwdev, REG_MAR + 4, 0xffffffff); ++} ++ ++static void rtw88xxa_init_adaptive_ctrl(struct rtw_dev *rtwdev) ++{ ++ rtw_write32_mask(rtwdev, REG_RRSR, 0xfffff, 0xffff1); ++ rtw_write16(rtwdev, REG_RETRY_LIMIT, 0x3030); ++} ++ ++static void rtw88xxa_init_edca(struct rtw_dev *rtwdev) ++{ ++ rtw_write16(rtwdev, REG_SPEC_SIFS, 0x100a); ++ rtw_write16(rtwdev, REG_MAC_SPEC_SIFS, 0x100a); ++ ++ rtw_write16(rtwdev, REG_SIFS, 0x100a); ++ rtw_write16(rtwdev, REG_SIFS + 2, 0x100a); ++ ++ rtw_write32(rtwdev, REG_EDCA_BE_PARAM, 0x005EA42B); ++ rtw_write32(rtwdev, REG_EDCA_BK_PARAM, 0x0000A44F); ++ rtw_write32(rtwdev, REG_EDCA_VI_PARAM, 0x005EA324); ++ rtw_write32(rtwdev, REG_EDCA_VO_PARAM, 0x002FA226); ++ ++ rtw_write8(rtwdev, REG_USTIME_TSF, 0x50); ++ rtw_write8(rtwdev, REG_USTIME_EDCA, 0x50); ++} ++ ++static void rtw88xxau_tx_aggregation(struct rtw_dev *rtwdev) ++{ ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ ++ rtw_write32_mask(rtwdev, REG_DWBCN0_CTRL, 0xf0, ++ chip->usb_tx_agg_desc_num); ++ ++ if (chip->id == RTW_CHIP_TYPE_8821A) ++ rtw_write8(rtwdev, REG_DWBCN1_CTRL, ++ chip->usb_tx_agg_desc_num << 1); ++} ++ ++static void rtw88xxa_init_beacon_parameters(struct rtw_dev *rtwdev) ++{ ++ u16 val16; ++ ++ val16 = (BIT_DIS_TSF_UDT << 8) | BIT_DIS_TSF_UDT; ++ if (rtwdev->efuse.btcoex) ++ val16 |= BIT_EN_BCN_FUNCTION; ++ rtw_write16(rtwdev, REG_BCN_CTRL, val16); ++ ++ rtw_write32_mask(rtwdev, REG_TBTT_PROHIBIT, 0xfffff, WLAN_TBTT_TIME); ++ rtw_write8(rtwdev, REG_DRVERLYINT, 0x05); ++ rtw_write8(rtwdev, REG_BCNDMATIM, WLAN_BCN_DMA_TIME); ++ rtw_write16(rtwdev, REG_BCNTCFG, 0x4413); ++} ++ ++static void rtw88xxa_phy_bb_config(struct rtw_dev *rtwdev) ++{ ++ u8 val8, crystal_cap; ++ ++ /* power on BB/RF domain */ ++ val8 = rtw_read8(rtwdev, REG_SYS_FUNC_EN); ++ val8 |= BIT_FEN_USBA; ++ rtw_write8(rtwdev, REG_SYS_FUNC_EN, val8); ++ ++ /* toggle BB reset */ ++ val8 |= BIT_FEN_BB_RSTB | BIT_FEN_BB_GLB_RST; ++ rtw_write8(rtwdev, REG_SYS_FUNC_EN, val8); ++ ++ rtw_write8(rtwdev, REG_RF_CTRL, ++ BIT_RF_EN | BIT_RF_RSTB | BIT_RF_SDM_RSTB); ++ rtw_write8(rtwdev, REG_RF_B_CTRL, ++ BIT_RF_EN | BIT_RF_RSTB | BIT_RF_SDM_RSTB); ++ ++ rtw_load_table(rtwdev, rtwdev->chip->bb_tbl); ++ rtw_load_table(rtwdev, rtwdev->chip->agc_tbl); ++ ++ crystal_cap = rtwdev->efuse.crystal_cap & 0x3F; ++ if (rtwdev->chip->id == RTW_CHIP_TYPE_8812A) ++ rtw_write32_mask(rtwdev, REG_AFE_CTRL3, 0x7FF80000, ++ crystal_cap | (crystal_cap << 6)); ++ else ++ rtw_write32_mask(rtwdev, REG_AFE_CTRL3, 0x00FFF000, ++ crystal_cap | (crystal_cap << 6)); ++} ++ ++static void rtw88xxa_phy_rf_config(struct rtw_dev *rtwdev) ++{ ++ u8 rf_path; ++ ++ for (rf_path = 0; rf_path < rtwdev->hal.rf_path_num; rf_path++) ++ rtw_load_table(rtwdev, rtwdev->chip->rf_tbl[rf_path]); ++} ++ ++static void rtw8812a_config_1t(struct rtw_dev *rtwdev) ++{ ++ /* BB OFDM RX Path_A */ ++ rtw_write32_mask(rtwdev, REG_RXPSEL, 0xff, 0x11); ++ ++ /* BB OFDM TX Path_A */ ++ rtw_write32_mask(rtwdev, REG_TXPSEL, MASKLWORD, 0x1111); ++ ++ /* BB CCK R/Rx Path_A */ ++ rtw_write32_mask(rtwdev, REG_CCK_RX, 0x0c000000, 0x0); ++ ++ /* MCS support */ ++ rtw_write32_mask(rtwdev, REG_RX_MCS_LIMIT, 0xc0000060, 0x4); ++ ++ /* RF Path_B HSSI OFF */ ++ rtw_write32_mask(rtwdev, REG_3WIRE_SWB, 0xf, 0x4); ++ ++ /* RF Path_B Power Down */ ++ rtw_write32_mask(rtwdev, REG_LSSI_WRITE_B, MASKDWORD, 0); ++ ++ /* ADDA Path_B OFF */ ++ rtw_write32_mask(rtwdev, REG_AFE_PWR1_B, MASKDWORD, 0); ++ rtw_write32_mask(rtwdev, REG_AFE_PWR2_B, MASKDWORD, 0); ++} ++ ++static const u32 rtw88xxa_txscale_tbl[] = { ++ 0x081, 0x088, 0x090, 0x099, 0x0a2, 0x0ac, 0x0b6, 0x0c0, 0x0cc, 0x0d8, ++ 0x0e5, 0x0f2, 0x101, 0x110, 0x120, 0x131, 0x143, 0x156, 0x16a, 0x180, ++ 0x197, 0x1af, 0x1c8, 0x1e3, 0x200, 0x21e, 0x23e, 0x261, 0x285, 0x2ab, ++ 0x2d3, 0x2fe, 0x32b, 0x35c, 0x38e, 0x3c4, 0x3fe ++}; ++ ++static u32 rtw88xxa_get_bb_swing(struct rtw_dev *rtwdev, u8 band, u8 path) ++{ ++ static const u32 swing2setting[4] = {0x200, 0x16a, 0x101, 0x0b6}; ++ struct rtw_efuse *efuse = &rtwdev->efuse; ++ u8 tx_bb_swing; ++ ++ if (band == RTW_BAND_2G) ++ tx_bb_swing = efuse->tx_bb_swing_setting_2g; ++ else ++ tx_bb_swing = efuse->tx_bb_swing_setting_5g; ++ ++ if (path == RF_PATH_B) ++ tx_bb_swing >>= 2; ++ tx_bb_swing &= 0x3; ++ ++ return swing2setting[tx_bb_swing]; ++} ++ ++static u8 rtw88xxa_get_swing_index(struct rtw_dev *rtwdev) ++{ ++ u32 swing, table_value; ++ u8 i; ++ ++ swing = rtw88xxa_get_bb_swing(rtwdev, rtwdev->hal.current_band_type, ++ RF_PATH_A); ++ ++ for (i = 0; i < ARRAY_SIZE(rtw88xxa_txscale_tbl); i++) { ++ table_value = rtw88xxa_txscale_tbl[i]; ++ if (swing == table_value) ++ return i; ++ } ++ ++ return 24; ++} ++ ++static void rtw88xxa_pwrtrack_init(struct rtw_dev *rtwdev) ++{ ++ struct rtw_dm_info *dm_info = &rtwdev->dm_info; ++ u8 path; ++ ++ dm_info->default_ofdm_index = rtw88xxa_get_swing_index(rtwdev); ++ ++ if (rtwdev->chip->id == RTW_CHIP_TYPE_8821A) ++ dm_info->default_cck_index = 0; ++ else ++ dm_info->default_cck_index = 24; ++ ++ for (path = RF_PATH_A; path < rtwdev->hal.rf_path_num; path++) { ++ ewma_thermal_init(&dm_info->avg_thermal[path]); ++ dm_info->delta_power_index[path] = 0; ++ dm_info->delta_power_index_last[path] = 0; ++ } ++ ++ dm_info->pwr_trk_triggered = false; ++ dm_info->pwr_trk_init_trigger = true; ++ dm_info->thermal_meter_k = rtwdev->efuse.thermal_meter_k; ++} ++ ++void rtw88xxa_power_off(struct rtw_dev *rtwdev, ++ const struct rtw_pwr_seq_cmd *const *enter_lps_flow) ++{ ++ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); ++ enum usb_device_speed speed = rtwusb->udev->speed; ++ u16 ori_fsmc0; ++ u8 reg_cr; ++ ++ reg_cr = rtw_read8(rtwdev, REG_CR); ++ ++ /* Already powered off */ ++ if (reg_cr == 0 || reg_cr == 0xEA) ++ return; ++ ++ rtw_hci_stop(rtwdev); ++ ++ if (!rtwdev->efuse.btcoex) ++ rtw_write16_clr(rtwdev, REG_GPIO_MUXCFG, BIT_EN_SIC); ++ ++ /* set Reg 0xf008[3:4] to 2'11 to enable U1/U2 Mode in USB3.0. */ ++ if (speed == USB_SPEED_SUPER) ++ rtw_write8_set(rtwdev, REG_USB_MOD, 0x18); ++ ++ rtw_write32(rtwdev, REG_HISR0, 0xffffffff); ++ rtw_write32(rtwdev, REG_HISR1, 0xffffffff); ++ rtw_write32(rtwdev, REG_HIMR0, 0); ++ rtw_write32(rtwdev, REG_HIMR1, 0); ++ ++ if (rtwdev->efuse.btcoex) ++ rtw_coex_power_off_setting(rtwdev); ++ ++ ori_fsmc0 = rtw_read16(rtwdev, REG_APS_FSMCO); ++ rtw_write16(rtwdev, REG_APS_FSMCO, ori_fsmc0 & ~APS_FSMCO_HW_POWERDOWN); ++ ++ /* Stop Tx Report Timer. */ ++ rtw_write8_clr(rtwdev, REG_TX_RPT_CTRL, BIT(1)); ++ ++ /* Stop Rx */ ++ rtw_write8(rtwdev, REG_CR, 0); ++ ++ rtw_pwr_seq_parser(rtwdev, enter_lps_flow); ++ ++ if (rtw_read8(rtwdev, REG_MCUFW_CTRL) & BIT_RAM_DL_SEL) ++ rtw88xxa_reset_8051(rtwdev); ++ ++ rtw_write8_clr(rtwdev, REG_SYS_FUNC_EN + 1, BIT(2)); ++ rtw_write8(rtwdev, REG_MCUFW_CTRL, 0); ++ ++ rtw_pwr_seq_parser(rtwdev, rtwdev->chip->pwr_off_seq); ++ ++ if (ori_fsmc0 & APS_FSMCO_HW_POWERDOWN) ++ rtw_write16_set(rtwdev, REG_APS_FSMCO, APS_FSMCO_HW_POWERDOWN); ++ ++ clear_bit(RTW_FLAG_POWERON, rtwdev->flags); ++} ++EXPORT_SYMBOL(rtw88xxa_power_off); ++ ++static void rtw88xxa_set_channel_bb_swing(struct rtw_dev *rtwdev, u8 band) ++{ ++ rtw_write32_mask(rtwdev, REG_TXSCALE_A, BB_SWING_MASK, ++ rtw88xxa_get_bb_swing(rtwdev, band, RF_PATH_A)); ++ rtw_write32_mask(rtwdev, REG_TXSCALE_B, BB_SWING_MASK, ++ rtw88xxa_get_bb_swing(rtwdev, band, RF_PATH_B)); ++ rtw88xxa_pwrtrack_init(rtwdev); ++} ++ ++static void rtw8821a_set_ext_band_switch(struct rtw_dev *rtwdev, u8 band) ++{ ++ rtw_write32_mask(rtwdev, REG_LED_CFG, BIT_DPDT_SEL_EN, 0); ++ rtw_write32_mask(rtwdev, REG_LED_CFG, BIT_DPDT_WL_SEL, 1); ++ rtw_write32_mask(rtwdev, REG_RFE_INV_A, 0xf, 7); ++ rtw_write32_mask(rtwdev, REG_RFE_INV_A, 0xf0, 7); ++ ++ if (band == RTW_BAND_2G) ++ rtw_write32_mask(rtwdev, REG_RFE_INV_A, BIT(29) | BIT(28), 1); ++ else ++ rtw_write32_mask(rtwdev, REG_RFE_INV_A, BIT(29) | BIT(28), 2); ++} ++ ++static void rtw8821a_phy_set_rfe_reg_24g(struct rtw_dev *rtwdev) ++{ ++ struct rtw_efuse *efuse = &rtwdev->efuse; ++ ++ /* Turn off RF PA and LNA */ ++ ++ /* 0xCB0[15:12] = 0x7 (LNA_On)*/ ++ rtw_write32_mask(rtwdev, REG_RFE_PINMUX_A, 0xF000, 0x7); ++ /* 0xCB0[7:4] = 0x7 (PAPE_A)*/ ++ rtw_write32_mask(rtwdev, REG_RFE_PINMUX_A, 0xF0, 0x7); ++ ++ if (efuse->ext_lna_2g) { ++ /* Turn on 2.4G External LNA */ ++ rtw_write32_mask(rtwdev, REG_RFE_INV_A, BIT(20), 1); ++ rtw_write32_mask(rtwdev, REG_RFE_INV_A, BIT(22), 0); ++ rtw_write32_mask(rtwdev, REG_RFE_PINMUX_A, GENMASK(2, 0), 0x2); ++ rtw_write32_mask(rtwdev, REG_RFE_PINMUX_A, GENMASK(10, 8), 0x2); ++ } else { ++ /* Bypass 2.4G External LNA */ ++ rtw_write32_mask(rtwdev, REG_RFE_INV_A, BIT(20), 0); ++ rtw_write32_mask(rtwdev, REG_RFE_INV_A, BIT(22), 0); ++ rtw_write32_mask(rtwdev, REG_RFE_PINMUX_A, GENMASK(2, 0), 0x7); ++ rtw_write32_mask(rtwdev, REG_RFE_PINMUX_A, GENMASK(10, 8), 0x7); ++ } ++} ++ ++static void rtw8821a_phy_set_rfe_reg_5g(struct rtw_dev *rtwdev) ++{ ++ /* Turn ON RF PA and LNA */ ++ ++ /* 0xCB0[15:12] = 0x7 (LNA_On)*/ ++ rtw_write32_mask(rtwdev, REG_RFE_PINMUX_A, 0xF000, 0x5); ++ /* 0xCB0[7:4] = 0x7 (PAPE_A)*/ ++ rtw_write32_mask(rtwdev, REG_RFE_PINMUX_A, 0xF0, 0x4); ++ ++ /* Bypass 2.4G External LNA */ ++ rtw_write32_mask(rtwdev, REG_RFE_INV_A, BIT(20), 0); ++ rtw_write32_mask(rtwdev, REG_RFE_INV_A, BIT(22), 0); ++ rtw_write32_mask(rtwdev, REG_RFE_PINMUX_A, GENMASK(2, 0), 0x7); ++ rtw_write32_mask(rtwdev, REG_RFE_PINMUX_A, GENMASK(10, 8), 0x7); ++} ++ ++static void rtw8812a_phy_set_rfe_reg_24g(struct rtw_dev *rtwdev) ++{ ++ switch (rtwdev->efuse.rfe_option) { ++ case 0: ++ case 2: ++ rtw_write32(rtwdev, REG_RFE_PINMUX_A, 0x77777777); ++ rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x77777777); ++ rtw_write32_mask(rtwdev, REG_RFE_INV_A, RFE_INV_MASK, 0x000); ++ rtw_write32_mask(rtwdev, REG_RFE_INV_B, RFE_INV_MASK, 0x000); ++ break; ++ case 1: ++ if (rtwdev->efuse.btcoex) { ++ rtw_write32_mask(rtwdev, REG_RFE_PINMUX_A, 0xffffff, 0x777777); ++ rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x77777777); ++ rtw_write32_mask(rtwdev, REG_RFE_INV_A, 0x33f00000, 0x000); ++ rtw_write32_mask(rtwdev, REG_RFE_INV_B, RFE_INV_MASK, 0x000); ++ } else { ++ rtw_write32(rtwdev, REG_RFE_PINMUX_A, 0x77777777); ++ rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x77777777); ++ rtw_write32_mask(rtwdev, REG_RFE_INV_A, RFE_INV_MASK, 0x000); ++ rtw_write32_mask(rtwdev, REG_RFE_INV_B, RFE_INV_MASK, 0x000); ++ } ++ break; ++ case 3: ++ rtw_write32(rtwdev, REG_RFE_PINMUX_A, 0x54337770); ++ rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x54337770); ++ rtw_write32_mask(rtwdev, REG_RFE_INV_A, RFE_INV_MASK, 0x010); ++ rtw_write32_mask(rtwdev, REG_RFE_INV_B, RFE_INV_MASK, 0x010); ++ rtw_write32_mask(rtwdev, REG_ANTSEL_SW, 0x00000303, 0x1); ++ break; ++ case 4: ++ rtw_write32(rtwdev, REG_RFE_PINMUX_A, 0x77777777); ++ rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x77777777); ++ rtw_write32_mask(rtwdev, REG_RFE_INV_A, RFE_INV_MASK, 0x001); ++ rtw_write32_mask(rtwdev, REG_RFE_INV_B, RFE_INV_MASK, 0x001); ++ break; ++ case 5: ++ rtw_write8(rtwdev, REG_RFE_PINMUX_A + 2, 0x77); ++ rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x77777777); ++ rtw_write8_clr(rtwdev, REG_RFE_INV_A + 3, BIT(0)); ++ rtw_write32_mask(rtwdev, REG_RFE_INV_B, RFE_INV_MASK, 0x000); ++ break; ++ case 6: ++ rtw_write32(rtwdev, REG_RFE_PINMUX_A, 0x07772770); ++ rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x07772770); ++ rtw_write32(rtwdev, REG_RFE_INV_A, 0x00000077); ++ rtw_write32(rtwdev, REG_RFE_INV_B, 0x00000077); ++ break; ++ default: ++ break; ++ } ++} ++ ++static void rtw8812a_phy_set_rfe_reg_5g(struct rtw_dev *rtwdev) ++{ ++ switch (rtwdev->efuse.rfe_option) { ++ case 0: ++ rtw_write32(rtwdev, REG_RFE_PINMUX_A, 0x77337717); ++ rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x77337717); ++ rtw_write32_mask(rtwdev, REG_RFE_INV_A, RFE_INV_MASK, 0x010); ++ rtw_write32_mask(rtwdev, REG_RFE_INV_B, RFE_INV_MASK, 0x010); ++ break; ++ case 1: ++ if (rtwdev->efuse.btcoex) { ++ rtw_write32_mask(rtwdev, REG_RFE_PINMUX_A, 0xffffff, 0x337717); ++ rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x77337717); ++ rtw_write32_mask(rtwdev, REG_RFE_INV_A, 0x33f00000, 0x000); ++ rtw_write32_mask(rtwdev, REG_RFE_INV_B, RFE_INV_MASK, 0x000); ++ } else { ++ rtw_write32(rtwdev, REG_RFE_PINMUX_A, 0x77337717); ++ rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x77337717); ++ rtw_write32_mask(rtwdev, REG_RFE_INV_A, RFE_INV_MASK, 0x000); ++ rtw_write32_mask(rtwdev, REG_RFE_INV_B, RFE_INV_MASK, 0x000); ++ } ++ break; ++ case 2: ++ case 4: ++ rtw_write32(rtwdev, REG_RFE_PINMUX_A, 0x77337777); ++ rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x77337777); ++ rtw_write32_mask(rtwdev, REG_RFE_INV_A, RFE_INV_MASK, 0x010); ++ rtw_write32_mask(rtwdev, REG_RFE_INV_B, RFE_INV_MASK, 0x010); ++ break; ++ case 3: ++ rtw_write32(rtwdev, REG_RFE_PINMUX_A, 0x54337717); ++ rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x54337717); ++ rtw_write32_mask(rtwdev, REG_RFE_INV_A, RFE_INV_MASK, 0x010); ++ rtw_write32_mask(rtwdev, REG_RFE_INV_B, RFE_INV_MASK, 0x010); ++ rtw_write32_mask(rtwdev, REG_ANTSEL_SW, 0x00000303, 0x1); ++ break; ++ case 5: ++ rtw_write8(rtwdev, REG_RFE_PINMUX_A + 2, 0x33); ++ rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x77337777); ++ rtw_write8_set(rtwdev, REG_RFE_INV_A + 3, BIT(0)); ++ rtw_write32_mask(rtwdev, REG_RFE_INV_B, RFE_INV_MASK, 0x010); ++ break; ++ case 6: ++ rtw_write32(rtwdev, REG_RFE_PINMUX_A, 0x07737717); ++ rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x07737717); ++ rtw_write32(rtwdev, REG_RFE_INV_A, 0x00000077); ++ rtw_write32(rtwdev, REG_RFE_INV_B, 0x00000077); ++ break; ++ default: ++ break; ++ } ++} ++ ++static void rtw88xxa_switch_band(struct rtw_dev *rtwdev, u8 new_band, u8 bw) ++{ ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ u16 basic_rates, reg_41a; ++ ++ /* 8811au one antenna module doesn't support antenna div, so driver must ++ * control antenna band, otherwise one of the band will have issue ++ */ ++ if (chip->id == RTW_CHIP_TYPE_8821A && !rtwdev->efuse.btcoex && ++ rtwdev->efuse.ant_div_cfg == 0) ++ rtw8821a_set_ext_band_switch(rtwdev, new_band); ++ ++ if (new_band == RTW_BAND_2G) { ++ rtw_write32_set(rtwdev, REG_RXPSEL, BIT_RX_PSEL_RST); ++ ++ if (chip->id == RTW_CHIP_TYPE_8821A) { ++ rtw8821a_phy_set_rfe_reg_24g(rtwdev); ++ ++ rtw_write32_mask(rtwdev, REG_TXSCALE_A, 0xf00, 0); ++ } else { ++ rtw_write32_mask(rtwdev, REG_BWINDICATION, 0x3, 0x1); ++ rtw_write32_mask(rtwdev, REG_PDMFTH, GENMASK(17, 13), 0x17); ++ ++ if (bw == RTW_CHANNEL_WIDTH_20 && ++ rtwdev->hal.rf_type == RF_1T1R && ++ !rtwdev->efuse.ext_lna_2g) ++ rtw_write32_mask(rtwdev, REG_PDMFTH, GENMASK(3, 1), 0x02); ++ else ++ rtw_write32_mask(rtwdev, REG_PDMFTH, GENMASK(3, 1), 0x04); ++ ++ rtw_write32_mask(rtwdev, REG_CCASEL, 0x3, 0); ++ ++ rtw8812a_phy_set_rfe_reg_24g(rtwdev); ++ } ++ ++ rtw_write32_mask(rtwdev, REG_TXPSEL, 0xf0, 0x1); ++ rtw_write32_mask(rtwdev, REG_CCK_RX, 0x0f000000, 0x1); ++ ++ basic_rates = BIT(DESC_RATE1M) | BIT(DESC_RATE2M) | ++ BIT(DESC_RATE5_5M) | BIT(DESC_RATE11M) | ++ BIT(DESC_RATE6M) | BIT(DESC_RATE12M) | ++ BIT(DESC_RATE24M); ++ rtw_write32_mask(rtwdev, REG_RRSR, 0xfffff, basic_rates); ++ ++ rtw_write8_clr(rtwdev, REG_CCK_CHECK, BIT_CHECK_CCK_EN); ++ } else { /* RTW_BAND_5G */ ++ if (chip->id == RTW_CHIP_TYPE_8821A) ++ rtw8821a_phy_set_rfe_reg_5g(rtwdev); ++ ++ rtw_write8_set(rtwdev, REG_CCK_CHECK, BIT_CHECK_CCK_EN); ++ ++ read_poll_timeout_atomic(rtw_read16, reg_41a, (reg_41a & 0x30) == 0x30, ++ 50, 2500, false, rtwdev, REG_TXPKT_EMPTY); ++ ++ rtw_write32_set(rtwdev, REG_RXPSEL, BIT_RX_PSEL_RST); ++ ++ if (chip->id == RTW_CHIP_TYPE_8821A) { ++ rtw_write32_mask(rtwdev, REG_TXSCALE_A, 0xf00, 1); ++ } else { ++ rtw_write32_mask(rtwdev, REG_BWINDICATION, 0x3, 0x2); ++ rtw_write32_mask(rtwdev, REG_PDMFTH, GENMASK(17, 13), 0x15); ++ rtw_write32_mask(rtwdev, REG_PDMFTH, GENMASK(3, 1), 0x04); ++ ++ rtw_write32_mask(rtwdev, REG_CCASEL, 0x3, 1); ++ ++ rtw8812a_phy_set_rfe_reg_5g(rtwdev); ++ } ++ ++ rtw_write32_mask(rtwdev, REG_TXPSEL, 0xf0, 0); ++ rtw_write32_mask(rtwdev, REG_CCK_RX, 0x0f000000, 0xf); ++ ++ basic_rates = BIT(DESC_RATE6M) | BIT(DESC_RATE12M) | ++ BIT(DESC_RATE24M); ++ rtw_write32_mask(rtwdev, REG_RRSR, 0xfffff, basic_rates); ++ } ++ ++ rtw88xxa_set_channel_bb_swing(rtwdev, new_band); ++} ++ ++int rtw88xxa_power_on(struct rtw_dev *rtwdev) ++{ ++ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ struct rtw_efuse *efuse = &rtwdev->efuse; ++ struct rtw_hal *hal = &rtwdev->hal; ++ int ret; ++ ++ if (test_bit(RTW_FLAG_POWERON, rtwdev->flags)) ++ return 0; ++ ++ /* Override rtw_chip_efuse_info_setup() */ ++ if (chip->id == RTW_CHIP_TYPE_8821A) ++ efuse->btcoex = rtw_read32_mask(rtwdev, REG_WL_BT_PWR_CTRL, ++ BIT_BT_FUNC_EN); ++ ++ /* Override rtw_chip_efuse_info_setup() */ ++ if (chip->id == RTW_CHIP_TYPE_8812A) ++ rtw8812a_read_amplifier_type(rtwdev); ++ ++ ret = rtw_hci_setup(rtwdev); ++ if (ret) { ++ rtw_err(rtwdev, "failed to setup hci\n"); ++ goto err; ++ } ++ ++ /* Revise for U2/U3 switch we can not update RF-A/B reset. ++ * Reset after MAC power on to prevent RF R/W error. ++ * Is it a right method? ++ */ ++ if (chip->id == RTW_CHIP_TYPE_8812A) { ++ rtw_write8(rtwdev, REG_RF_CTRL, 5); ++ rtw_write8(rtwdev, REG_RF_CTRL, 7); ++ rtw_write8(rtwdev, REG_RF_B_CTRL, 5); ++ rtw_write8(rtwdev, REG_RF_B_CTRL, 7); ++ } ++ ++ /* If HW didn't go through a complete de-initial procedure, ++ * it probably occurs some problem for double initial ++ * procedure. ++ */ ++ rtw88xxau_hw_reset(rtwdev); ++ ++ ret = rtw88xxau_init_power_on(rtwdev); ++ if (ret) { ++ rtw_err(rtwdev, "failed to power on\n"); ++ goto err; ++ } ++ ++ ret = rtw_set_trx_fifo_info(rtwdev); ++ if (ret) { ++ rtw_err(rtwdev, "failed to set trx fifo info\n"); ++ goto err; ++ } ++ ++ ret = rtw88xxa_llt_init(rtwdev, rtwdev->fifo.rsvd_boundary); ++ if (ret) { ++ rtw_err(rtwdev, "failed to init llt\n"); ++ goto err; ++ } ++ ++ rtw_write32_set(rtwdev, REG_TXDMA_OFFSET_CHK, BIT_DROP_DATA_EN); ++ ++ ret = rtw_wait_firmware_completion(rtwdev); ++ if (ret) { ++ rtw_err(rtwdev, "failed to wait firmware completion\n"); ++ goto err_off; ++ } ++ ++ ret = rtw_download_firmware(rtwdev, &rtwdev->fw); ++ if (ret) { ++ rtw_err(rtwdev, "failed to download firmware\n"); ++ goto err_off; ++ } ++ ++ rtw_write8(rtwdev, REG_HMETFR, 0xf); ++ ++ rtw_load_table(rtwdev, chip->mac_tbl); ++ ++ rtw88xxau_init_queue_reserved_page(rtwdev); ++ rtw88xxau_init_tx_buffer_boundary(rtwdev); ++ rtw88xxau_init_queue_priority(rtwdev); ++ ++ rtw_write16(rtwdev, REG_TRXFF_BNDY + 2, ++ chip->rxff_size - REPORT_BUF - 1); ++ ++ if (chip->id == RTW_CHIP_TYPE_8812A) ++ rtw_write8(rtwdev, REG_PBP, ++ u8_encode_bits(PBP_512, PBP_TX_MASK) | ++ u8_encode_bits(PBP_64, PBP_RX_MASK)); ++ ++ rtw_write8(rtwdev, REG_RX_DRVINFO_SZ, PHY_STATUS_SIZE); ++ ++ rtw_write32(rtwdev, REG_HIMR0, 0); ++ rtw_write32(rtwdev, REG_HIMR1, 0); ++ ++ rtw_write32_mask(rtwdev, REG_CR, 0x30000, 0x2); ++ ++ rtw88xxa_init_wmac_setting(rtwdev); ++ rtw88xxa_init_adaptive_ctrl(rtwdev); ++ rtw88xxa_init_edca(rtwdev); ++ ++ rtw_write8_set(rtwdev, REG_FWHW_TXQ_CTRL, BIT(7)); ++ rtw_write8(rtwdev, REG_ACKTO, 0x80); ++ ++ rtw88xxau_tx_aggregation(rtwdev); ++ ++ rtw88xxa_init_beacon_parameters(rtwdev); ++ rtw_write8(rtwdev, REG_BCN_MAX_ERR, 0xff); ++ ++ rtw_hci_interface_cfg(rtwdev); ++ ++ /* usb3 rx interval */ ++ rtw_write8(rtwdev, REG_USB3_RXITV, 0x01); ++ ++ /* burst length=4, set 0x3400 for burst length=2 */ ++ rtw_write16(rtwdev, REG_RXDMA_STATUS, 0x7400); ++ rtw_write8(rtwdev, REG_RXDMA_STATUS + 1, 0xf5); ++ ++ /* 0x456 = 0x70, sugguested by Zhilin */ ++ if (chip->id == RTW_CHIP_TYPE_8821A) ++ rtw_write8(rtwdev, REG_AMPDU_MAX_TIME, 0x5e); ++ else ++ rtw_write8(rtwdev, REG_AMPDU_MAX_TIME, 0x70); ++ ++ rtw_write32(rtwdev, REG_AMPDU_MAX_LENGTH, 0xffffffff); ++ rtw_write8(rtwdev, REG_USTIME_TSF, 0x50); ++ rtw_write8(rtwdev, REG_USTIME_EDCA, 0x50); ++ ++ if (rtwusb->udev->speed == USB_SPEED_SUPER) ++ /* Disable U1/U2 Mode to avoid 2.5G spur in USB3.0. */ ++ rtw_write8_clr(rtwdev, REG_USB_MOD, BIT(4) | BIT(3)); ++ ++ rtw_write8_set(rtwdev, REG_SINGLE_AMPDU_CTRL, BIT_EN_SINGLE_APMDU); ++ ++ /* for VHT packet length 11K */ ++ rtw_write8(rtwdev, REG_RX_PKT_LIMIT, 0x18); ++ ++ rtw_write8(rtwdev, REG_PIFS, 0x00); ++ ++ if (chip->id == RTW_CHIP_TYPE_8821A) { ++ /* 0x0a0a too small, it can't pass AC logo. change to 0x1f1f */ ++ rtw_write16(rtwdev, REG_MAX_AGGR_NUM, 0x1f1f); ++ rtw_write8(rtwdev, REG_FWHW_TXQ_CTRL, 0x80); ++ rtw_write32(rtwdev, REG_FAST_EDCA_CTRL, 0x03087777); ++ } else { ++ rtw_write16(rtwdev, REG_MAX_AGGR_NUM, 0x1f1f); ++ rtw_write8_clr(rtwdev, REG_FWHW_TXQ_CTRL, BIT(7)); ++ } ++ ++ /* to prevent mac is reseted by bus. */ ++ rtw_write8_set(rtwdev, REG_RSV_CTRL, BIT(5) | BIT(6)); ++ ++ /* ARFB table 9 for 11ac 5G 2SS */ ++ rtw_write32(rtwdev, REG_ARFR0, 0x00000010); ++ rtw_write32(rtwdev, REG_ARFRH0, 0xfffff000); ++ ++ /* ARFB table 10 for 11ac 5G 1SS */ ++ rtw_write32(rtwdev, REG_ARFR1_V1, 0x00000010); ++ rtw_write32(rtwdev, REG_ARFRH1_V1, 0x003ff000); ++ ++ /* ARFB table 11 for 11ac 24G 1SS */ ++ rtw_write32(rtwdev, REG_ARFR2_V1, 0x00000015); ++ rtw_write32(rtwdev, REG_ARFRH2_V1, 0x003ff000); ++ ++ /* ARFB table 12 for 11ac 24G 2SS */ ++ rtw_write32(rtwdev, REG_ARFR3_V1, 0x00000015); ++ rtw_write32(rtwdev, REG_ARFRH3_V1, 0xffcff000); ++ ++ rtw_write8_set(rtwdev, REG_CR, BIT_MACTXEN | BIT_MACRXEN); ++ ++ rtw88xxa_phy_bb_config(rtwdev); ++ rtw88xxa_phy_rf_config(rtwdev); ++ ++ if (chip->id == RTW_CHIP_TYPE_8812A && hal->rf_path_num == 1) ++ rtw8812a_config_1t(rtwdev); ++ ++ rtw88xxa_switch_band(rtwdev, RTW_BAND_2G, RTW_CHANNEL_WIDTH_20); ++ ++ rtw_write32(rtwdev, RTW_SEC_CMD_REG, BIT(31) | BIT(30)); ++ ++ rtw_write8(rtwdev, REG_HWSEQ_CTRL, 0xff); ++ rtw_write32(rtwdev, REG_BAR_MODE_CTRL, 0x0201ffff); ++ rtw_write8(rtwdev, REG_NAV_CTRL + 2, 0); ++ ++ rtw_write8_clr(rtwdev, REG_GPIO_MUXCFG, BIT(5)); ++ ++ rtw_phy_init(rtwdev); ++ ++ rtw88xxa_pwrtrack_init(rtwdev); ++ ++ /* 0x4c6[3] 1: RTS BW = Data BW ++ * 0: RTS BW depends on CCA / secondary CCA result. ++ */ ++ rtw_write8_clr(rtwdev, REG_QUEUE_CTRL, BIT(3)); ++ ++ /* enable Tx report. */ ++ rtw_write8(rtwdev, REG_FWHW_TXQ_CTRL + 1, 0x0f); ++ ++ /* Pretx_en, for WEP/TKIP SEC */ ++ rtw_write8(rtwdev, REG_EARLY_MODE_CONTROL + 3, 0x01); ++ ++ rtw_write16(rtwdev, REG_TX_RPT_TIME, 0x3df0); ++ ++ /* Reset USB mode switch setting */ ++ rtw_write8(rtwdev, REG_SYS_SDIO_CTRL, 0x0); ++ rtw_write8(rtwdev, REG_ACLK_MON, 0x0); ++ ++ rtw_write8(rtwdev, REG_USB_HRPWM, 0); ++ ++ /* ack for xmit mgmt frames. */ ++ rtw_write32_set(rtwdev, REG_FWHW_TXQ_CTRL, BIT(12)); ++ ++ hal->cck_high_power = rtw_read32_mask(rtwdev, REG_CCK_RPT_FORMAT, ++ BIT_CCK_RPT_FORMAT); ++ ++ ret = rtw_hci_start(rtwdev); ++ if (ret) { ++ rtw_err(rtwdev, "failed to start hci\n"); ++ goto err_off; ++ } ++ ++ if (efuse->btcoex) { ++ rtw_coex_power_on_setting(rtwdev); ++ rtw_coex_init_hw_config(rtwdev, false); ++ } ++ ++ set_bit(RTW_FLAG_POWERON, rtwdev->flags); ++ ++ return 0; ++ ++err_off: ++ chip->ops->power_off(rtwdev); ++ ++err: ++ return ret; ++} ++EXPORT_SYMBOL(rtw88xxa_power_on); ++ ++u32 rtw88xxa_phy_read_rf(struct rtw_dev *rtwdev, ++ enum rtw_rf_path rf_path, u32 addr, u32 mask) ++{ ++ static const u32 pi_addr[2] = { REG_3WIRE_SWA, REG_3WIRE_SWB }; ++ static const u32 read_addr[2][2] = { ++ { REG_SI_READ_A, REG_SI_READ_B }, ++ { REG_PI_READ_A, REG_PI_READ_B } ++ }; ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_hal *hal = &rtwdev->hal; ++ bool set_cca, pi_mode; ++ u32 val; ++ ++ if (rf_path >= hal->rf_phy_num) { ++ rtw_err(rtwdev, "unsupported rf path (%d)\n", rf_path); ++ return INV_RF_DATA; ++ } ++ ++ /* CCA off to avoid reading the wrong value. ++ * Toggling CCA would affect RF 0x0, skip it. ++ */ ++ set_cca = addr != 0x0 && chip->id == RTW_CHIP_TYPE_8812A && ++ hal->cut_version != RTW_CHIP_VER_CUT_C; ++ ++ if (set_cca) ++ rtw_write32_set(rtwdev, REG_CCA2ND, BIT(3)); ++ ++ addr &= 0xff; ++ ++ pi_mode = rtw_read32_mask(rtwdev, pi_addr[rf_path], 0x4); ++ ++ rtw_write32_mask(rtwdev, REG_HSSI_READ, MASKBYTE0, addr); ++ ++ if (chip->id == RTW_CHIP_TYPE_8821A || ++ hal->cut_version == RTW_CHIP_VER_CUT_C) ++ udelay(20); ++ ++ val = rtw_read32_mask(rtwdev, read_addr[pi_mode][rf_path], mask); ++ ++ /* CCA on */ ++ if (set_cca) ++ rtw_write32_clr(rtwdev, REG_CCA2ND, BIT(3)); ++ ++ return val; ++} ++EXPORT_SYMBOL(rtw88xxa_phy_read_rf); ++ ++static void rtw8812a_phy_fix_spur(struct rtw_dev *rtwdev, u8 channel, u8 bw) ++{ ++ /* C cut Item12 ADC FIFO CLOCK */ ++ if (rtwdev->hal.cut_version == RTW_CHIP_VER_CUT_C) { ++ if (bw == RTW_CHANNEL_WIDTH_40 && channel == 11) ++ rtw_write32_mask(rtwdev, REG_ADCCLK, 0xC00, 0x3); ++ else ++ rtw_write32_mask(rtwdev, REG_ADCCLK, 0xC00, 0x2); ++ ++ /* A workaround to resolve 2480Mhz spur by setting ADC clock ++ * as 160M. ++ */ ++ if (bw == RTW_CHANNEL_WIDTH_20 && (channel == 13 || channel == 14)) { ++ rtw_write32_mask(rtwdev, REG_ADCCLK, 0x300, 0x3); ++ rtw_write32_mask(rtwdev, REG_ADC160, BIT(30), 1); ++ } else if (bw == RTW_CHANNEL_WIDTH_40 && channel == 11) { ++ rtw_write32_mask(rtwdev, REG_ADC160, BIT(30), 1); ++ } else if (bw != RTW_CHANNEL_WIDTH_80) { ++ rtw_write32_mask(rtwdev, REG_ADCCLK, 0x300, 0x2); ++ rtw_write32_mask(rtwdev, REG_ADC160, BIT(30), 0); ++ } ++ } else { ++ /* A workaround to resolve 2480Mhz spur by setting ADC clock ++ * as 160M. ++ */ ++ if (bw == RTW_CHANNEL_WIDTH_20 && (channel == 13 || channel == 14)) ++ rtw_write32_mask(rtwdev, REG_ADCCLK, 0x300, 0x3); ++ else if (channel <= 14) /* 2.4G only */ ++ rtw_write32_mask(rtwdev, REG_ADCCLK, 0x300, 0x2); ++ } ++} ++ ++static void rtw88xxa_switch_channel(struct rtw_dev *rtwdev, u8 channel, u8 bw) ++{ ++ struct rtw_hal *hal = &rtwdev->hal; ++ u32 fc_area, rf_mod_ag; ++ u8 path; ++ ++ switch (channel) { ++ case 36 ... 48: ++ fc_area = 0x494; ++ break; ++ case 50 ... 64: ++ fc_area = 0x453; ++ break; ++ case 100 ... 116: ++ fc_area = 0x452; ++ break; ++ default: ++ if (channel >= 118) ++ fc_area = 0x412; ++ else ++ fc_area = 0x96a; ++ break; ++ } ++ ++ rtw_write32_mask(rtwdev, REG_CLKTRK, 0x1ffe0000, fc_area); ++ ++ for (path = 0; path < hal->rf_path_num; path++) { ++ switch (channel) { ++ case 36 ... 64: ++ rf_mod_ag = 0x101; ++ break; ++ case 100 ... 140: ++ rf_mod_ag = 0x301; ++ break; ++ default: ++ if (channel > 140) ++ rf_mod_ag = 0x501; ++ else ++ rf_mod_ag = 0x000; ++ break; ++ } ++ ++ rtw_write_rf(rtwdev, path, RF_CFGCH, ++ RF18_RFSI_MASK | RF18_BAND_MASK, rf_mod_ag); ++ ++ if (rtwdev->chip->id == RTW_CHIP_TYPE_8812A) ++ rtw8812a_phy_fix_spur(rtwdev, channel, bw); ++ ++ rtw_write_rf(rtwdev, path, RF_CFGCH, RF18_CHANNEL_MASK, channel); ++ } ++} ++ ++static void rtw88xxa_set_reg_bw(struct rtw_dev *rtwdev, u8 bw) ++{ ++ u16 val16 = rtw_read16(rtwdev, REG_WMAC_TRXPTCL_CTL); ++ ++ val16 &= ~BIT_RFMOD; ++ if (bw == RTW_CHANNEL_WIDTH_80) ++ val16 |= BIT_RFMOD_80M; ++ else if (bw == RTW_CHANNEL_WIDTH_40) ++ val16 |= BIT_RFMOD_40M; ++ ++ rtw_write16(rtwdev, REG_WMAC_TRXPTCL_CTL, val16); ++} ++ ++static void rtw88xxa_post_set_bw_mode(struct rtw_dev *rtwdev, u8 channel, ++ u8 bw, u8 primary_chan_idx) ++{ ++ struct rtw_hal *hal = &rtwdev->hal; ++ u8 txsc40 = 0, txsc20, txsc; ++ u8 reg_837, l1pkval; ++ ++ rtw88xxa_set_reg_bw(rtwdev, bw); ++ ++ txsc20 = primary_chan_idx; ++ if (bw == RTW_CHANNEL_WIDTH_80) { ++ if (txsc20 == RTW_SC_20_UPPER || txsc20 == RTW_SC_20_UPMOST) ++ txsc40 = RTW_SC_40_UPPER; ++ else ++ txsc40 = RTW_SC_40_LOWER; ++ } ++ ++ txsc = BIT_TXSC_20M(txsc20) | BIT_TXSC_40M(txsc40); ++ rtw_write8(rtwdev, REG_DATA_SC, txsc); ++ ++ reg_837 = rtw_read8(rtwdev, REG_BWINDICATION + 3); ++ ++ switch (bw) { ++ default: ++ case RTW_CHANNEL_WIDTH_20: ++ rtw_write32_mask(rtwdev, REG_ADCCLK, 0x003003C3, 0x00300200); ++ rtw_write32_mask(rtwdev, REG_ADC160, BIT(30), 0); ++ ++ if (hal->rf_type == RF_2T2R) ++ rtw_write32_mask(rtwdev, REG_L1PKTH, 0x03C00000, 7); ++ else ++ rtw_write32_mask(rtwdev, REG_L1PKTH, 0x03C00000, 8); ++ ++ break; ++ case RTW_CHANNEL_WIDTH_40: ++ rtw_write32_mask(rtwdev, REG_ADCCLK, 0x003003C3, 0x00300201); ++ rtw_write32_mask(rtwdev, REG_ADC160, BIT(30), 0); ++ rtw_write32_mask(rtwdev, REG_ADCCLK, 0x3C, txsc); ++ rtw_write32_mask(rtwdev, REG_CCA2ND, 0xf0000000, txsc); ++ ++ if (reg_837 & BIT(2)) { ++ l1pkval = 6; ++ } else { ++ if (hal->rf_type == RF_2T2R) ++ l1pkval = 7; ++ else ++ l1pkval = 8; ++ } ++ ++ rtw_write32_mask(rtwdev, REG_L1PKTH, 0x03C00000, l1pkval); ++ ++ if (txsc == RTW_SC_20_UPPER) ++ rtw_write32_set(rtwdev, REG_RXSB, BIT(4)); ++ else ++ rtw_write32_clr(rtwdev, REG_RXSB, BIT(4)); ++ ++ break; ++ case RTW_CHANNEL_WIDTH_80: ++ rtw_write32_mask(rtwdev, REG_ADCCLK, 0x003003C3, 0x00300202); ++ rtw_write32_mask(rtwdev, REG_ADC160, BIT(30), 1); ++ rtw_write32_mask(rtwdev, REG_ADCCLK, 0x3C, txsc); ++ rtw_write32_mask(rtwdev, REG_CCA2ND, 0xf0000000, txsc); ++ ++ if (reg_837 & BIT(2)) { ++ l1pkval = 5; ++ } else { ++ if (hal->rf_type == RF_2T2R) ++ l1pkval = 6; ++ else ++ l1pkval = 7; ++ } ++ ++ rtw_write32_mask(rtwdev, REG_L1PKTH, 0x03C00000, l1pkval); ++ ++ break; ++ } ++} ++ ++static void rtw88xxa_set_channel_rf(struct rtw_dev *rtwdev, u8 channel, u8 bw) ++{ ++ u8 path; ++ ++ for (path = RF_PATH_A; path < rtwdev->hal.rf_path_num; path++) { ++ switch (bw) { ++ case RTW_CHANNEL_WIDTH_5: ++ case RTW_CHANNEL_WIDTH_10: ++ case RTW_CHANNEL_WIDTH_20: ++ default: ++ rtw_write_rf(rtwdev, path, RF_CFGCH, RF18_BW_MASK, 3); ++ break; ++ case RTW_CHANNEL_WIDTH_40: ++ rtw_write_rf(rtwdev, path, RF_CFGCH, RF18_BW_MASK, 1); ++ break; ++ case RTW_CHANNEL_WIDTH_80: ++ rtw_write_rf(rtwdev, path, RF_CFGCH, RF18_BW_MASK, 0); ++ break; ++ } ++ } ++} ++ ++void rtw88xxa_set_channel(struct rtw_dev *rtwdev, u8 channel, u8 bw, ++ u8 primary_chan_idx) ++{ ++ u8 old_band, new_band; ++ ++ if (rtw_read8(rtwdev, REG_CCK_CHECK) & BIT_CHECK_CCK_EN) ++ old_band = RTW_BAND_5G; ++ else ++ old_band = RTW_BAND_2G; ++ ++ if (channel > 14) ++ new_band = RTW_BAND_5G; ++ else ++ new_band = RTW_BAND_2G; ++ ++ if (new_band != old_band) ++ rtw88xxa_switch_band(rtwdev, new_band, bw); ++ ++ rtw88xxa_switch_channel(rtwdev, channel, bw); ++ ++ rtw88xxa_post_set_bw_mode(rtwdev, channel, bw, primary_chan_idx); ++ ++ if (rtwdev->chip->id == RTW_CHIP_TYPE_8812A) ++ rtw8812a_phy_fix_spur(rtwdev, channel, bw); ++ ++ rtw88xxa_set_channel_rf(rtwdev, channel, bw); ++} ++EXPORT_SYMBOL(rtw88xxa_set_channel); ++ ++void rtw88xxa_query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status, ++ struct rtw_rx_pkt_stat *pkt_stat, ++ s8 (*cck_rx_pwr)(u8 lna_idx, u8 vga_idx)) ++{ ++ struct rtw_dm_info *dm_info = &rtwdev->dm_info; ++ struct rtw_jaguar_phy_status_rpt *rpt; ++ u8 gain[RTW_RF_PATH_MAX], rssi, i; ++ s8 rx_pwr_db, power_a, power_b; ++ const s8 min_rx_power = -120; ++ u8 lna_idx, vga_idx; ++ ++ rpt = (struct rtw_jaguar_phy_status_rpt *)phy_status; ++ ++ if (pkt_stat->rate <= DESC_RATE11M) { ++ lna_idx = le32_get_bits(rpt->w1, RTW_JGRPHY_W1_AGC_RPT_LNA_IDX); ++ vga_idx = le32_get_bits(rpt->w1, RTW_JGRPHY_W1_AGC_RPT_VGA_IDX); ++ ++ rx_pwr_db = cck_rx_pwr(lna_idx, vga_idx); ++ ++ pkt_stat->rx_power[RF_PATH_A] = rx_pwr_db; ++ pkt_stat->rssi = rtw_phy_rf_power_2_rssi(pkt_stat->rx_power, 1); ++ dm_info->rssi[RF_PATH_A] = pkt_stat->rssi; ++ pkt_stat->bw = RTW_CHANNEL_WIDTH_20; ++ pkt_stat->signal_power = rx_pwr_db; ++ } else { /* OFDM rate */ ++ gain[RF_PATH_A] = le32_get_bits(rpt->w0, RTW_JGRPHY_W0_GAIN_A); ++ gain[RF_PATH_B] = le32_get_bits(rpt->w0, RTW_JGRPHY_W0_GAIN_B); ++ ++ for (i = RF_PATH_A; i < rtwdev->hal.rf_path_num; i++) { ++ pkt_stat->rx_power[i] = gain[i] - 110; ++ rssi = rtw_phy_rf_power_2_rssi(&pkt_stat->rx_power[i], 1); ++ dm_info->rssi[i] = rssi; ++ } ++ ++ pkt_stat->rssi = rtw_phy_rf_power_2_rssi(pkt_stat->rx_power, ++ rtwdev->hal.rf_path_num); ++ ++ power_a = pkt_stat->rx_power[RF_PATH_A]; ++ power_b = pkt_stat->rx_power[RF_PATH_B]; ++ if (rtwdev->hal.rf_path_num == 1) ++ power_b = power_a; ++ ++ pkt_stat->signal_power = max3(power_a, power_b, min_rx_power); ++ } ++} ++EXPORT_SYMBOL(rtw88xxa_query_phy_status); ++ ++static void ++rtw88xxa_set_tx_power_index_by_rate(struct rtw_dev *rtwdev, u8 path, ++ u8 rs, u32 *phy_pwr_idx) ++{ ++ static const u32 offset_txagc[2] = { ++ REG_TX_AGC_A_CCK_11_CCK_1, REG_TX_AGC_B_CCK_11_CCK_1 ++ }; ++ u8 rate, rate_idx, pwr_index, shift; ++ struct rtw_hal *hal = &rtwdev->hal; ++ bool write_1ss_mcs9; ++ u32 mask; ++ int j; ++ ++ for (j = 0; j < rtw_rate_size[rs]; j++) { ++ rate = rtw_rate_section[rs][j]; ++ ++ pwr_index = hal->tx_pwr_tbl[path][rate]; ++ ++ shift = rate & 0x3; ++ *phy_pwr_idx |= ((u32)pwr_index << (shift * 8)); ++ ++ write_1ss_mcs9 = rate == DESC_RATEVHT1SS_MCS9 && ++ hal->rf_path_num == 1; ++ ++ if (write_1ss_mcs9) ++ mask = MASKLWORD; ++ else ++ mask = MASKDWORD; ++ ++ if (shift == 0x3 || write_1ss_mcs9) { ++ rate_idx = rate & 0xfc; ++ if (rate >= DESC_RATEVHT1SS_MCS0) ++ rate_idx -= 0x10; ++ ++ rtw_write32_mask(rtwdev, offset_txagc[path] + rate_idx, ++ mask, *phy_pwr_idx); ++ ++ *phy_pwr_idx = 0; ++ } ++ } ++} ++ ++static void rtw88xxa_tx_power_training(struct rtw_dev *rtwdev, u8 bw, ++ u8 channel, u8 path) ++{ ++ static const u32 write_offset[] = { ++ REG_TX_PWR_TRAINING_A, REG_TX_PWR_TRAINING_B, ++ }; ++ u32 power_level, write_data; ++ u8 i; ++ ++ power_level = rtwdev->hal.tx_pwr_tbl[path][DESC_RATEMCS7]; ++ write_data = 0; ++ ++ for (i = 0; i < 3; i++) { ++ if (i == 0) ++ power_level -= 10; ++ else if (i == 1) ++ power_level -= 8; ++ else ++ power_level -= 6; ++ ++ write_data |= max_t(u32, power_level, 2) << (i * 8); ++ } ++ ++ rtw_write32_mask(rtwdev, write_offset[path], 0xffffff, write_data); ++} ++ ++void rtw88xxa_set_tx_power_index(struct rtw_dev *rtwdev) ++{ ++ struct rtw_hal *hal = &rtwdev->hal; ++ u32 phy_pwr_idx = 0; ++ int rs, path; ++ ++ for (path = 0; path < hal->rf_path_num; path++) { ++ for (rs = 0; rs < RTW_RATE_SECTION_MAX; rs++) { ++ if (hal->rf_path_num == 1 && ++ (rs == RTW_RATE_SECTION_HT_2S || ++ rs == RTW_RATE_SECTION_VHT_2S)) ++ continue; ++ ++ if (test_bit(RTW_FLAG_SCANNING, rtwdev->flags) && ++ rs > RTW_RATE_SECTION_OFDM) ++ continue; ++ ++ if (hal->current_band_type == RTW_BAND_5G && ++ rs == RTW_RATE_SECTION_CCK) ++ continue; ++ ++ rtw88xxa_set_tx_power_index_by_rate(rtwdev, path, rs, ++ &phy_pwr_idx); ++ } ++ ++ rtw88xxa_tx_power_training(rtwdev, hal->current_band_width, ++ hal->current_channel, path); ++ } ++} ++EXPORT_SYMBOL(rtw88xxa_set_tx_power_index); ++ ++void rtw88xxa_false_alarm_statistics(struct rtw_dev *rtwdev) ++{ ++ struct rtw_dm_info *dm_info = &rtwdev->dm_info; ++ u32 cck_fa_cnt, ofdm_fa_cnt; ++ u32 crc32_cnt, cca32_cnt; ++ u32 cck_enable; ++ ++ cck_enable = rtw_read32(rtwdev, REG_RXPSEL) & BIT(28); ++ cck_fa_cnt = rtw_read16(rtwdev, REG_FA_CCK); ++ ofdm_fa_cnt = rtw_read16(rtwdev, REG_FA_OFDM); ++ ++ dm_info->cck_fa_cnt = cck_fa_cnt; ++ dm_info->ofdm_fa_cnt = ofdm_fa_cnt; ++ dm_info->total_fa_cnt = ofdm_fa_cnt; ++ if (cck_enable) ++ dm_info->total_fa_cnt += cck_fa_cnt; ++ ++ crc32_cnt = rtw_read32(rtwdev, REG_CRC_CCK); ++ dm_info->cck_ok_cnt = u32_get_bits(crc32_cnt, MASKLWORD); ++ dm_info->cck_err_cnt = u32_get_bits(crc32_cnt, MASKHWORD); ++ ++ crc32_cnt = rtw_read32(rtwdev, REG_CRC_OFDM); ++ dm_info->ofdm_ok_cnt = u32_get_bits(crc32_cnt, MASKLWORD); ++ dm_info->ofdm_err_cnt = u32_get_bits(crc32_cnt, MASKHWORD); ++ ++ crc32_cnt = rtw_read32(rtwdev, REG_CRC_HT); ++ dm_info->ht_ok_cnt = u32_get_bits(crc32_cnt, MASKLWORD); ++ dm_info->ht_err_cnt = u32_get_bits(crc32_cnt, MASKHWORD); ++ ++ crc32_cnt = rtw_read32(rtwdev, REG_CRC_VHT); ++ dm_info->vht_ok_cnt = u32_get_bits(crc32_cnt, MASKLWORD); ++ dm_info->vht_err_cnt = u32_get_bits(crc32_cnt, MASKHWORD); ++ ++ cca32_cnt = rtw_read32(rtwdev, REG_CCA_OFDM); ++ dm_info->ofdm_cca_cnt = u32_get_bits(cca32_cnt, MASKHWORD); ++ dm_info->total_cca_cnt = dm_info->ofdm_cca_cnt; ++ if (cck_enable) { ++ cca32_cnt = rtw_read32(rtwdev, REG_CCA_CCK); ++ dm_info->cck_cca_cnt = u32_get_bits(cca32_cnt, MASKLWORD); ++ dm_info->total_cca_cnt += dm_info->cck_cca_cnt; ++ } ++ ++ rtw_write32_set(rtwdev, REG_FAS, BIT(17)); ++ rtw_write32_clr(rtwdev, REG_FAS, BIT(17)); ++ rtw_write32_clr(rtwdev, REG_CCK0_FAREPORT, BIT(15)); ++ rtw_write32_set(rtwdev, REG_CCK0_FAREPORT, BIT(15)); ++ rtw_write32_set(rtwdev, REG_CNTRST, BIT(0)); ++ rtw_write32_clr(rtwdev, REG_CNTRST, BIT(0)); ++} ++EXPORT_SYMBOL(rtw88xxa_false_alarm_statistics); ++ ++void rtw88xxa_iqk_backup_mac_bb(struct rtw_dev *rtwdev, ++ u32 *macbb_backup, ++ const u32 *backup_macbb_reg, ++ u32 macbb_num) ++{ ++ u32 i; ++ ++ /* [31] = 0 --> Page C */ ++ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0); ++ ++ /* save MACBB default value */ ++ for (i = 0; i < macbb_num; i++) ++ macbb_backup[i] = rtw_read32(rtwdev, backup_macbb_reg[i]); ++} ++EXPORT_SYMBOL(rtw88xxa_iqk_backup_mac_bb); ++ ++void rtw88xxa_iqk_backup_afe(struct rtw_dev *rtwdev, u32 *afe_backup, ++ const u32 *backup_afe_reg, u32 afe_num) ++{ ++ u32 i; ++ ++ /* [31] = 0 --> Page C */ ++ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0); ++ ++ /* Save AFE Parameters */ ++ for (i = 0; i < afe_num; i++) ++ afe_backup[i] = rtw_read32(rtwdev, backup_afe_reg[i]); ++} ++EXPORT_SYMBOL(rtw88xxa_iqk_backup_afe); ++ ++void rtw88xxa_iqk_restore_mac_bb(struct rtw_dev *rtwdev, ++ u32 *macbb_backup, ++ const u32 *backup_macbb_reg, ++ u32 macbb_num) ++{ ++ u32 i; ++ ++ /* [31] = 0 --> Page C */ ++ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0); ++ ++ /* Reload MacBB Parameters */ ++ for (i = 0; i < macbb_num; i++) ++ rtw_write32(rtwdev, backup_macbb_reg[i], macbb_backup[i]); ++} ++EXPORT_SYMBOL(rtw88xxa_iqk_restore_mac_bb); ++ ++void rtw88xxa_iqk_configure_mac(struct rtw_dev *rtwdev) ++{ ++ /* [31] = 0 --> Page C */ ++ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0); ++ ++ rtw_write8(rtwdev, REG_TXPAUSE, 0x3f); ++ rtw_write32_mask(rtwdev, REG_BCN_CTRL, ++ (BIT_EN_BCN_FUNCTION << 8) | BIT_EN_BCN_FUNCTION, 0x0); ++ ++ /* RX ante off */ ++ rtw_write8(rtwdev, REG_RXPSEL, 0x00); ++ ++ /* CCA off */ ++ rtw_write32_mask(rtwdev, REG_CCA2ND, 0xf, 0xc); ++ ++ /* CCK RX path off */ ++ rtw_write8(rtwdev, REG_CCK_RX + 3, 0xf); ++} ++EXPORT_SYMBOL(rtw88xxa_iqk_configure_mac); ++ ++bool rtw88xxa_iqk_finish(int average, int threshold, ++ int *x_temp, int *y_temp, int *x, int *y, ++ bool break_inner, bool break_outer) ++{ ++ bool finish = false; ++ int i, ii, dx, dy; ++ ++ for (i = 0; i < average; i++) { ++ for (ii = i + 1; ii < average; ii++) { ++ dx = abs_diff(x_temp[i] >> 21, x_temp[ii] >> 21); ++ dy = abs_diff(y_temp[i] >> 21, y_temp[ii] >> 21); ++ ++ if (dx < threshold && dy < threshold) { ++ *x = ((x_temp[i] >> 21) + (x_temp[ii] >> 21)); ++ *y = ((y_temp[i] >> 21) + (y_temp[ii] >> 21)); ++ ++ *x /= 2; ++ *y /= 2; ++ ++ finish = true; ++ ++ if (break_inner) ++ break; ++ } ++ } ++ ++ if (finish && break_outer) ++ break; ++ } ++ ++ return finish; ++} ++EXPORT_SYMBOL(rtw88xxa_iqk_finish); ++ ++static void rtw88xxa_pwrtrack_set(struct rtw_dev *rtwdev, u8 tx_rate, u8 path) ++{ ++ static const u32 reg_txscale[2] = { REG_TXSCALE_A, REG_TXSCALE_B }; ++ struct rtw_dm_info *dm_info = &rtwdev->dm_info; ++ u8 cck_swing_idx, ofdm_swing_idx; ++ u8 pwr_tracking_limit; ++ ++ switch (tx_rate) { ++ case DESC_RATE1M ... DESC_RATE11M: ++ pwr_tracking_limit = 32; ++ break; ++ case DESC_RATE6M ... DESC_RATE48M: ++ case DESC_RATEMCS3 ... DESC_RATEMCS4: ++ case DESC_RATEMCS11 ... DESC_RATEMCS12: ++ case DESC_RATEVHT1SS_MCS3 ... DESC_RATEVHT1SS_MCS4: ++ case DESC_RATEVHT2SS_MCS3 ... DESC_RATEVHT2SS_MCS4: ++ pwr_tracking_limit = 30; ++ break; ++ case DESC_RATE54M: ++ case DESC_RATEMCS5 ... DESC_RATEMCS7: ++ case DESC_RATEMCS13 ... DESC_RATEMCS15: ++ case DESC_RATEVHT1SS_MCS5 ... DESC_RATEVHT1SS_MCS6: ++ case DESC_RATEVHT2SS_MCS5 ... DESC_RATEVHT2SS_MCS6: ++ pwr_tracking_limit = 28; ++ break; ++ case DESC_RATEMCS0 ... DESC_RATEMCS2: ++ case DESC_RATEMCS8 ... DESC_RATEMCS10: ++ case DESC_RATEVHT1SS_MCS0 ... DESC_RATEVHT1SS_MCS2: ++ case DESC_RATEVHT2SS_MCS0 ... DESC_RATEVHT2SS_MCS2: ++ pwr_tracking_limit = 34; ++ break; ++ case DESC_RATEVHT1SS_MCS7: ++ case DESC_RATEVHT2SS_MCS7: ++ pwr_tracking_limit = 26; ++ break; ++ default: ++ case DESC_RATEVHT1SS_MCS8: ++ case DESC_RATEVHT2SS_MCS8: ++ pwr_tracking_limit = 24; ++ break; ++ case DESC_RATEVHT1SS_MCS9: ++ case DESC_RATEVHT2SS_MCS9: ++ pwr_tracking_limit = 22; ++ break; ++ } ++ ++ cck_swing_idx = dm_info->delta_power_index[path] + dm_info->default_cck_index; ++ ofdm_swing_idx = dm_info->delta_power_index[path] + dm_info->default_ofdm_index; ++ ++ if (ofdm_swing_idx > pwr_tracking_limit) { ++ if (path == RF_PATH_A) ++ dm_info->txagc_remnant_cck = cck_swing_idx - pwr_tracking_limit; ++ dm_info->txagc_remnant_ofdm[path] = ofdm_swing_idx - pwr_tracking_limit; ++ ++ ofdm_swing_idx = pwr_tracking_limit; ++ } else if (ofdm_swing_idx == 0) { ++ if (path == RF_PATH_A) ++ dm_info->txagc_remnant_cck = cck_swing_idx; ++ dm_info->txagc_remnant_ofdm[path] = ofdm_swing_idx; ++ } else { ++ if (path == RF_PATH_A) ++ dm_info->txagc_remnant_cck = 0; ++ dm_info->txagc_remnant_ofdm[path] = 0; ++ } ++ ++ rtw_write32_mask(rtwdev, reg_txscale[path], GENMASK(31, 21), ++ rtw88xxa_txscale_tbl[ofdm_swing_idx]); ++} ++ ++void rtw88xxa_phy_pwrtrack(struct rtw_dev *rtwdev, ++ void (*do_lck)(struct rtw_dev *rtwdev), ++ void (*do_iqk)(struct rtw_dev *rtwdev)) ++{ ++ struct rtw_dm_info *dm_info = &rtwdev->dm_info; ++ struct rtw_hal *hal = &rtwdev->hal; ++ struct rtw_swing_table swing_table; ++ s8 remnant_pre[RTW_RF_PATH_MAX]; ++ u8 thermal_value, delta, path; ++ bool need_iqk; ++ ++ rtw_phy_config_swing_table(rtwdev, &swing_table); ++ ++ if (rtwdev->efuse.thermal_meter[0] == 0xff) { ++ pr_err_once("efuse thermal meter is 0xff\n"); ++ return; ++ } ++ ++ thermal_value = rtw_read_rf(rtwdev, RF_PATH_A, RF_T_METER, 0xfc00); ++ ++ rtw_phy_pwrtrack_avg(rtwdev, thermal_value, RF_PATH_A); ++ ++ need_iqk = rtw_phy_pwrtrack_need_iqk(rtwdev); ++ ++ if (need_iqk && do_lck) ++ do_lck(rtwdev); ++ ++ if (dm_info->pwr_trk_init_trigger) ++ dm_info->pwr_trk_init_trigger = false; ++ else if (!rtw_phy_pwrtrack_thermal_changed(rtwdev, thermal_value, ++ RF_PATH_A)) ++ goto iqk; ++ ++ delta = rtw_phy_pwrtrack_get_delta(rtwdev, RF_PATH_A); ++ ++ for (path = RF_PATH_A; path < hal->rf_path_num; path++) { ++ remnant_pre[path] = dm_info->txagc_remnant_ofdm[path]; ++ ++ dm_info->delta_power_index[path] = ++ rtw_phy_pwrtrack_get_pwridx(rtwdev, &swing_table, path, ++ RF_PATH_A, delta); ++ ++ if (dm_info->delta_power_index[path] != ++ dm_info->delta_power_index_last[path]) { ++ dm_info->delta_power_index_last[path] = ++ dm_info->delta_power_index[path]; ++ ++ rtw88xxa_pwrtrack_set(rtwdev, dm_info->tx_rate, path); ++ } ++ } ++ ++ for (path = RF_PATH_A; path < hal->rf_path_num; path++) { ++ if (remnant_pre[path] != dm_info->txagc_remnant_ofdm[path]) { ++ rtw_phy_set_tx_power_level(rtwdev, ++ hal->current_channel); ++ break; ++ } ++ } ++ ++iqk: ++ if (need_iqk) ++ do_iqk(rtwdev); ++} ++EXPORT_SYMBOL(rtw88xxa_phy_pwrtrack); ++ ++void rtw88xxa_phy_cck_pd_set(struct rtw_dev *rtwdev, u8 new_lvl) ++{ ++ static const u8 pd[CCK_PD_LV_MAX] = {0x40, 0x83, 0xcd, 0xdd, 0xed}; ++ struct rtw_dm_info *dm_info = &rtwdev->dm_info; ++ ++ /* Override rtw_phy_cck_pd_lv_link(). It implements something ++ * like type 2/3/4. We need type 1 here. ++ */ ++ if (rtw_is_assoc(rtwdev)) { ++ if (dm_info->min_rssi > 60) { ++ new_lvl = CCK_PD_LV3; ++ } else if (dm_info->min_rssi > 35) { ++ new_lvl = CCK_PD_LV2; ++ } else if (dm_info->min_rssi > 20) { ++ if (dm_info->cck_fa_avg > 500) ++ new_lvl = CCK_PD_LV2; ++ else if (dm_info->cck_fa_avg < 250) ++ new_lvl = CCK_PD_LV1; ++ else ++ return; ++ } else { ++ new_lvl = CCK_PD_LV1; ++ } ++ } ++ ++ rtw_dbg(rtwdev, RTW_DBG_PHY, "lv: (%d) -> (%d)\n", ++ dm_info->cck_pd_lv[RTW_CHANNEL_WIDTH_20][RF_PATH_A], new_lvl); ++ ++ if (dm_info->cck_pd_lv[RTW_CHANNEL_WIDTH_20][RF_PATH_A] == new_lvl) ++ return; ++ ++ dm_info->cck_fa_avg = CCK_FA_AVG_RESET; ++ dm_info->cck_pd_lv[RTW_CHANNEL_WIDTH_20][RF_PATH_A] = new_lvl; ++ ++ rtw_write8(rtwdev, REG_CCK_PD_TH, pd[new_lvl]); ++} ++EXPORT_SYMBOL(rtw88xxa_phy_cck_pd_set); ++ ++MODULE_AUTHOR("Realtek Corporation"); ++MODULE_DESCRIPTION("Realtek 802.11ac wireless 8821a/8811a/8812a common code"); ++MODULE_LICENSE("Dual BSD/GPL"); +diff --git a/drivers/net/wireless/realtek/rtw88/rtw88xxa.h b/drivers/net/wireless/realtek/rtw88/rtw88xxa.h +new file mode 100644 +index 000000000000..09a45c1a4129 +--- /dev/null ++++ b/drivers/net/wireless/realtek/rtw88/rtw88xxa.h +@@ -0,0 +1,175 @@ ++/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ ++/* Copyright(c) 2024 Realtek Corporation ++ */ ++ ++#ifndef __RTW88XXA_H__ ++#define __RTW88XXA_H__ ++ ++#include ++#include "reg.h" ++ ++struct rtw8821au_efuse { ++ u8 res4[48]; /* 0xd0 */ ++ u8 vid[2]; /* 0x100 */ ++ u8 pid[2]; ++ u8 res8[3]; ++ u8 mac_addr[ETH_ALEN]; /* 0x107 */ ++ u8 res9[243]; ++} __packed; ++ ++struct rtw8812au_efuse { ++ u8 vid[2]; /* 0xd0 */ ++ u8 pid[2]; /* 0xd2 */ ++ u8 res0[3]; ++ u8 mac_addr[ETH_ALEN]; /* 0xd7 */ ++ u8 res1[291]; ++} __packed; ++ ++struct rtw88xxa_efuse { ++ __le16 rtl_id; ++ u8 res0[6]; /* 0x02 */ ++ u8 usb_mode; /* 0x08 */ ++ u8 res1[7]; /* 0x09 */ ++ ++ /* power index for four RF paths */ ++ struct rtw_txpwr_idx txpwr_idx_table[4]; ++ ++ u8 channel_plan; /* 0xb8 */ ++ u8 xtal_k; ++ u8 thermal_meter; ++ u8 iqk_lck; ++ u8 pa_type; /* 0xbc */ ++ u8 lna_type_2g; /* 0xbd */ ++ u8 res2; ++ u8 lna_type_5g; /* 0xbf */ ++ u8 res3; ++ u8 rf_board_option; /* 0xc1 */ ++ u8 rf_feature_option; ++ u8 rf_bt_setting; ++ u8 eeprom_version; ++ u8 eeprom_customer_id; /* 0xc5 */ ++ u8 tx_bb_swing_setting_2g; ++ u8 tx_bb_swing_setting_5g; ++ u8 tx_pwr_calibrate_rate; ++ u8 rf_antenna_option; /* 0xc9 */ ++ u8 rfe_option; ++ u8 country_code[2]; ++ u8 res4[3]; ++ union { ++ struct rtw8821au_efuse rtw8821au; ++ struct rtw8812au_efuse rtw8812au; ++ }; ++} __packed; ++ ++static_assert(sizeof(struct rtw88xxa_efuse) == 512); ++ ++#define WLAN_BCN_DMA_TIME 0x02 ++#define WLAN_TBTT_PROHIBIT 0x04 ++#define WLAN_TBTT_HOLD_TIME 0x064 ++#define WLAN_TBTT_TIME (WLAN_TBTT_PROHIBIT |\ ++ (WLAN_TBTT_HOLD_TIME << BIT_SHIFT_TBTT_HOLD_TIME_AP)) ++ ++struct rtw_jaguar_phy_status_rpt { ++ __le32 w0; ++ __le32 w1; ++ __le32 w2; ++ __le32 w3; ++ __le32 w4; ++ __le32 w5; ++ __le32 w6; ++} __packed; ++ ++#define RTW_JGRPHY_W0_GAIN_A GENMASK(6, 0) ++#define RTW_JGRPHY_W0_TRSW_A BIT(7) ++#define RTW_JGRPHY_W0_GAIN_B GENMASK(14, 8) ++#define RTW_JGRPHY_W0_TRSW_B BIT(15) ++#define RTW_JGRPHY_W0_CHL_NUM GENMASK(25, 16) ++#define RTW_JGRPHY_W0_SUB_CHNL GENMASK(29, 26) ++#define RTW_JGRPHY_W0_R_RFMOD GENMASK(31, 30) ++ ++/* CCK: */ ++#define RTW_JGRPHY_W1_SIG_QUAL GENMASK(7, 0) ++#define RTW_JGRPHY_W1_AGC_RPT_VGA_IDX GENMASK(12, 8) ++#define RTW_JGRPHY_W1_AGC_RPT_LNA_IDX GENMASK(15, 13) ++#define RTW_JGRPHY_W1_BB_POWER GENMASK(23, 16) ++/* OFDM: */ ++#define RTW_JGRPHY_W1_PWDB_ALL GENMASK(7, 0) ++#define RTW_JGRPHY_W1_CFO_SHORT_A GENMASK(15, 8) /* s8 */ ++#define RTW_JGRPHY_W1_CFO_SHORT_B GENMASK(23, 16) /* s8 */ ++#define RTW_JGRPHY_W1_BT_RF_CH_MSB GENMASK(31, 30) ++ ++#define RTW_JGRPHY_W2_ANT_DIV_SW_A BIT(0) ++#define RTW_JGRPHY_W2_ANT_DIV_SW_B BIT(1) ++#define RTW_JGRPHY_W2_BT_RF_CH_LSB GENMASK(7, 2) ++#define RTW_JGRPHY_W2_CFO_TAIL_A GENMASK(15, 8) /* s8 */ ++#define RTW_JGRPHY_W2_CFO_TAIL_B GENMASK(23, 16) /* s8 */ ++#define RTW_JGRPHY_W2_PCTS_MSK_RPT_0 GENMASK(31, 24) ++ ++#define RTW_JGRPHY_W3_PCTS_MSK_RPT_1 GENMASK(7, 0) ++/* Stream 1 and 2 RX EVM: */ ++#define RTW_JGRPHY_W3_RXEVM_1 GENMASK(15, 8) /* s8 */ ++#define RTW_JGRPHY_W3_RXEVM_2 GENMASK(23, 16) /* s8 */ ++#define RTW_JGRPHY_W3_RXSNR_A GENMASK(31, 24) /* s8 */ ++ ++#define RTW_JGRPHY_W4_RXSNR_B GENMASK(7, 0) /* s8 */ ++#define RTW_JGRPHY_W4_PCTS_MSK_RPT_2 GENMASK(21, 8) ++#define RTW_JGRPHY_W4_PCTS_RPT_VALID BIT(22) ++#define RTW_JGRPHY_W4_RXEVM_3 GENMASK(31, 24) /* s8 */ ++ ++#define RTW_JGRPHY_W5_RXEVM_4 GENMASK(7, 0) /* s8 */ ++/* 8812a, stream 1 and 2 CSI: */ ++#define RTW_JGRPHY_W5_CSI_CURRENT_1 GENMASK(15, 8) ++#define RTW_JGRPHY_W5_CSI_CURRENT_2 GENMASK(23, 16) ++/* 8814a: */ ++#define RTW_JGRPHY_W5_RXSNR_C GENMASK(15, 8) /* s8 */ ++#define RTW_JGRPHY_W5_RXSNR_D GENMASK(23, 16) /* s8 */ ++#define RTW_JGRPHY_W5_GAIN_C GENMASK(30, 24) ++#define RTW_JGRPHY_W5_TRSW_C BIT(31) ++ ++#define RTW_JGRPHY_W6_GAIN_D GENMASK(6, 0) ++#define RTW_JGRPHY_W6_TRSW_D BIT(7) ++#define RTW_JGRPHY_W6_SIGEVM GENMASK(15, 8) /* s8 */ ++#define RTW_JGRPHY_W6_ANTIDX_ANTC GENMASK(18, 16) ++#define RTW_JGRPHY_W6_ANTIDX_ANTD GENMASK(21, 19) ++#define RTW_JGRPHY_W6_DPDT_CTRL_KEEP BIT(22) ++#define RTW_JGRPHY_W6_GNT_BT_KEEP BIT(23) ++#define RTW_JGRPHY_W6_ANTIDX_ANTA GENMASK(26, 24) ++#define RTW_JGRPHY_W6_ANTIDX_ANTB GENMASK(29, 27) ++#define RTW_JGRPHY_W6_HW_ANTSW_OCCUR GENMASK(31, 30) ++ ++#define RF18_BW_MASK (BIT(11) | BIT(10)) ++ ++void rtw88xxa_efuse_grant(struct rtw_dev *rtwdev, bool on); ++int rtw88xxa_read_efuse(struct rtw_dev *rtwdev, u8 *log_map); ++void rtw88xxa_power_off(struct rtw_dev *rtwdev, ++ const struct rtw_pwr_seq_cmd *const *enter_lps_flow); ++int rtw88xxa_power_on(struct rtw_dev *rtwdev); ++u32 rtw88xxa_phy_read_rf(struct rtw_dev *rtwdev, ++ enum rtw_rf_path rf_path, u32 addr, u32 mask); ++void rtw88xxa_set_channel(struct rtw_dev *rtwdev, u8 channel, u8 bw, ++ u8 primary_chan_idx); ++void rtw88xxa_query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status, ++ struct rtw_rx_pkt_stat *pkt_stat, ++ s8 (*cck_rx_pwr)(u8 lna_idx, u8 vga_idx)); ++void rtw88xxa_set_tx_power_index(struct rtw_dev *rtwdev); ++void rtw88xxa_false_alarm_statistics(struct rtw_dev *rtwdev); ++void rtw88xxa_iqk_backup_mac_bb(struct rtw_dev *rtwdev, ++ u32 *macbb_backup, ++ const u32 *backup_macbb_reg, ++ u32 macbb_num); ++void rtw88xxa_iqk_backup_afe(struct rtw_dev *rtwdev, u32 *afe_backup, ++ const u32 *backup_afe_reg, u32 afe_num); ++void rtw88xxa_iqk_restore_mac_bb(struct rtw_dev *rtwdev, ++ u32 *macbb_backup, ++ const u32 *backup_macbb_reg, ++ u32 macbb_num); ++void rtw88xxa_iqk_configure_mac(struct rtw_dev *rtwdev); ++bool rtw88xxa_iqk_finish(int average, int threshold, ++ int *x_temp, int *y_temp, int *x, int *y, ++ bool break_inner, bool break_outer); ++void rtw88xxa_phy_pwrtrack(struct rtw_dev *rtwdev, ++ void (*do_lck)(struct rtw_dev *rtwdev), ++ void (*do_iqk)(struct rtw_dev *rtwdev)); ++void rtw88xxa_phy_cck_pd_set(struct rtw_dev *rtwdev, u8 new_lvl); ++ ++#endif +-- +2.39.5 + diff --git a/packages/linux/patches/rtlwifi/6.13/0021-wifi-rtw88-Add-rtw8821a.-c-h.patch b/packages/linux/patches/rtlwifi/6.13/0021-wifi-rtw88-Add-rtw8821a.-c-h.patch new file mode 100644 index 0000000000..842a16f2c3 --- /dev/null +++ b/packages/linux/patches/rtlwifi/6.13/0021-wifi-rtw88-Add-rtw8821a.-c-h.patch @@ -0,0 +1,1239 @@ +From 5019a4cd40a4df52c691e5a46cda033a2fb37c0c Mon Sep 17 00:00:00 2001 +From: Bitterblue Smith +Date: Wed, 30 Oct 2024 20:28:15 +0200 +Subject: [PATCH 21/24] wifi: rtw88: Add rtw8821a.{c,h} + +These contain code specific to RTL8821AU. + +Signed-off-by: Bitterblue Smith +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/37218648-ada7-4fad-b7bd-d2aee28cefb9@gmail.com +--- + drivers/net/wireless/realtek/rtw88/rtw8821a.c | 1197 +++++++++++++++++ + drivers/net/wireless/realtek/rtw88/rtw8821a.h | 10 + + 2 files changed, 1207 insertions(+) + create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8821a.c + create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8821a.h + +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821a.c b/drivers/net/wireless/realtek/rtw88/rtw8821a.c +new file mode 100644 +index 000000000000..db242c9ad68f +--- /dev/null ++++ b/drivers/net/wireless/realtek/rtw88/rtw8821a.c +@@ -0,0 +1,1197 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause ++/* Copyright(c) 2024 Realtek Corporation ++ */ ++ ++#include "main.h" ++#include "coex.h" ++#include "phy.h" ++#include "reg.h" ++#include "rtw88xxa.h" ++#include "rtw8821a.h" ++#include "rtw8821a_table.h" ++#include "tx.h" ++ ++static void rtw8821a_power_off(struct rtw_dev *rtwdev) ++{ ++ rtw88xxa_power_off(rtwdev, enter_lps_flow_8821a); ++} ++ ++static s8 rtw8821a_cck_rx_pwr(u8 lna_idx, u8 vga_idx) ++{ ++ static const s8 lna_gain_table[] = {15, -1, -17, 0, -30, -38}; ++ s8 rx_pwr_all = 0; ++ s8 lna_gain; ++ ++ switch (lna_idx) { ++ case 5: ++ case 4: ++ case 2: ++ case 1: ++ case 0: ++ lna_gain = lna_gain_table[lna_idx]; ++ rx_pwr_all = lna_gain - 2 * vga_idx; ++ break; ++ default: ++ break; ++ } ++ ++ return rx_pwr_all; ++} ++ ++static void rtw8821a_query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status, ++ struct rtw_rx_pkt_stat *pkt_stat) ++{ ++ rtw88xxa_query_phy_status(rtwdev, phy_status, pkt_stat, ++ rtw8821a_cck_rx_pwr); ++} ++ ++static void rtw8821a_cfg_ldo25(struct rtw_dev *rtwdev, bool enable) ++{ ++} ++ ++#define CAL_NUM_8821A 3 ++#define MACBB_REG_NUM_8821A 8 ++#define AFE_REG_NUM_8821A 4 ++#define RF_REG_NUM_8821A 3 ++ ++static void rtw8821a_iqk_backup_rf(struct rtw_dev *rtwdev, u32 *rfa_backup, ++ const u32 *backup_rf_reg, u32 rf_num) ++{ ++ u32 i; ++ ++ /* [31] = 0 --> Page C */ ++ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0); ++ ++ /* Save RF Parameters */ ++ for (i = 0; i < rf_num; i++) ++ rfa_backup[i] = rtw_read_rf(rtwdev, RF_PATH_A, ++ backup_rf_reg[i], MASKDWORD); ++} ++ ++static void rtw8821a_iqk_restore_rf(struct rtw_dev *rtwdev, ++ const u32 *backup_rf_reg, ++ u32 *RF_backup, u32 rf_reg_num) ++{ ++ u32 i; ++ ++ /* [31] = 0 --> Page C */ ++ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0); ++ ++ for (i = 0; i < rf_reg_num; i++) ++ rtw_write_rf(rtwdev, RF_PATH_A, backup_rf_reg[i], ++ RFREG_MASK, RF_backup[i]); ++} ++ ++static void rtw8821a_iqk_restore_afe(struct rtw_dev *rtwdev, u32 *afe_backup, ++ const u32 *backup_afe_reg, u32 afe_num) ++{ ++ u32 i; ++ ++ /* [31] = 0 --> Page C */ ++ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0); ++ ++ /* Reload AFE Parameters */ ++ for (i = 0; i < afe_num; i++) ++ rtw_write32(rtwdev, backup_afe_reg[i], afe_backup[i]); ++ ++ /* [31] = 1 --> Page C1 */ ++ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1); ++ ++ rtw_write32(rtwdev, REG_OFDM0_XA_TX_IQ_IMBALANCE, 0x0); ++ rtw_write32(rtwdev, REG_OFDM0_A_TX_AFE, 0x0); ++ rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE, 0x0); ++ rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x3c000000); ++ rtw_write32(rtwdev, REG_LSSI_WRITE_A, 0x00000080); ++ rtw_write32(rtwdev, REG_TXAGCIDX, 0x00000000); ++ rtw_write32(rtwdev, REG_IQK_DPD_CFG, 0x20040000); ++ rtw_write32(rtwdev, REG_CFG_PMPD, 0x20000000); ++ rtw_write32(rtwdev, REG_RFECTL_A, 0x0); ++} ++ ++static void rtw8821a_iqk_rx_fill(struct rtw_dev *rtwdev, ++ unsigned int rx_x, unsigned int rx_y) ++{ ++ /* [31] = 0 --> Page C */ ++ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0); ++ ++ rtw_write32_mask(rtwdev, REG_RX_IQC_AB_A, ++ 0x000003ff, rx_x >> 1); ++ rtw_write32_mask(rtwdev, REG_RX_IQC_AB_A, ++ 0x03ff0000, (rx_y >> 1) & 0x3ff); ++} ++ ++static void rtw8821a_iqk_tx_fill(struct rtw_dev *rtwdev, ++ unsigned int tx_x, unsigned int tx_y) ++{ ++ /* [31] = 1 --> Page C1 */ ++ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1); ++ ++ rtw_write32(rtwdev, REG_LSSI_WRITE_A, 0x00000080); ++ rtw_write32(rtwdev, REG_IQK_DPD_CFG, 0x20040000); ++ rtw_write32(rtwdev, REG_CFG_PMPD, 0x20000000); ++ rtw_write32_mask(rtwdev, REG_IQC_Y, 0x000007ff, tx_y); ++ rtw_write32_mask(rtwdev, REG_IQC_X, 0x000007ff, tx_x); ++} ++ ++static void rtw8821a_iqk_tx_vdf_true(struct rtw_dev *rtwdev, u32 cal, ++ bool *tx0iqkok, ++ int tx_x0[CAL_NUM_8821A], ++ int tx_y0[CAL_NUM_8821A]) ++{ ++ u32 cal_retry, delay_count, iqk_ready, tx_fail; ++ int tx_dt[3], vdf_y[3], vdf_x[3]; ++ int k; ++ ++ for (k = 0; k < 3; k++) { ++ switch (k) { ++ case 0: ++ /* TX_Tone_idx[9:0], TxK_Mask[29] TX_Tone = 16 */ ++ rtw_write32(rtwdev, REG_OFDM0_XA_TX_IQ_IMBALANCE, ++ 0x18008c38); ++ /* RX_Tone_idx[9:0], RxK_Mask[29] */ ++ rtw_write32(rtwdev, REG_OFDM0_A_TX_AFE, 0x38008c38); ++ rtw_write32_mask(rtwdev, REG_INTPO_SETA, BIT(31), 0x0); ++ break; ++ case 1: ++ rtw_write32_mask(rtwdev, REG_OFDM0_XA_TX_IQ_IMBALANCE, ++ BIT(28), 0x0); ++ rtw_write32_mask(rtwdev, REG_OFDM0_A_TX_AFE, ++ BIT(28), 0x0); ++ rtw_write32_mask(rtwdev, REG_INTPO_SETA, BIT(31), 0x0); ++ break; ++ case 2: ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "vdf_y[1] = %x vdf_y[0] = %x\n", ++ vdf_y[1] >> 21 & 0x00007ff, ++ vdf_y[0] >> 21 & 0x00007ff); ++ ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "vdf_x[1] = %x vdf_x[0] = %x\n", ++ vdf_x[1] >> 21 & 0x00007ff, ++ vdf_x[0] >> 21 & 0x00007ff); ++ ++ tx_dt[cal] = (vdf_y[1] >> 20) - (vdf_y[0] >> 20); ++ tx_dt[cal] = (16 * tx_dt[cal]) * 10000 / 15708; ++ tx_dt[cal] = (tx_dt[cal] >> 1) + (tx_dt[cal] & BIT(0)); ++ ++ /* TX_Tone_idx[9:0], TxK_Mask[29] TX_Tone = 16 */ ++ rtw_write32(rtwdev, REG_OFDM0_XA_TX_IQ_IMBALANCE, ++ 0x18008c20); ++ /* RX_Tone_idx[9:0], RxK_Mask[29] */ ++ rtw_write32(rtwdev, REG_OFDM0_A_TX_AFE, 0x38008c20); ++ rtw_write32_mask(rtwdev, REG_INTPO_SETA, BIT(31), 0x1); ++ rtw_write32_mask(rtwdev, REG_INTPO_SETA, 0x3fff0000, ++ tx_dt[cal] & 0x00003fff); ++ break; ++ } ++ ++ rtw_write32(rtwdev, REG_RFECTL_A, 0x00100000); ++ ++ for (cal_retry = 0; cal_retry < 10; cal_retry++) { ++ /* one shot */ ++ rtw_write32(rtwdev, REG_IQK_COM64, 0xfa000000); ++ rtw_write32(rtwdev, REG_IQK_COM64, 0xf8000000); ++ ++ mdelay(10); ++ ++ rtw_write32(rtwdev, REG_RFECTL_A, 0x00000000); ++ ++ for (delay_count = 0; delay_count < 20; delay_count++) { ++ iqk_ready = rtw_read32_mask(rtwdev, ++ REG_IQKA_END, ++ BIT(10)); ++ ++ /* Originally: if (~iqk_ready || delay_count > 20) ++ * that looks like a typo so make it more explicit ++ */ ++ iqk_ready = true; ++ ++ if (iqk_ready) ++ break; ++ ++ mdelay(1); ++ } ++ ++ if (delay_count < 20) { ++ /* ============TXIQK Check============== */ ++ tx_fail = rtw_read32_mask(rtwdev, ++ REG_IQKA_END, ++ BIT(12)); ++ ++ /* Originally: if (~tx_fail) { ++ * It looks like a typo, so make it more explicit. ++ */ ++ tx_fail = false; ++ ++ if (!tx_fail) { ++ rtw_write32(rtwdev, REG_RFECTL_A, ++ 0x02000000); ++ vdf_x[k] = rtw_read32_mask(rtwdev, ++ REG_IQKA_END, ++ 0x07ff0000); ++ vdf_x[k] <<= 21; ++ ++ rtw_write32(rtwdev, REG_RFECTL_A, ++ 0x04000000); ++ vdf_y[k] = rtw_read32_mask(rtwdev, ++ REG_IQKA_END, ++ 0x07ff0000); ++ vdf_y[k] <<= 21; ++ ++ *tx0iqkok = true; ++ break; ++ } ++ ++ rtw_write32_mask(rtwdev, REG_IQC_Y, ++ 0x000007ff, 0x0); ++ rtw_write32_mask(rtwdev, REG_IQC_X, ++ 0x000007ff, 0x200); ++ } ++ ++ *tx0iqkok = false; ++ } ++ } ++ ++ if (k == 3) { ++ tx_x0[cal] = vdf_x[k - 1]; ++ tx_y0[cal] = vdf_y[k - 1]; ++ } ++} ++ ++static void rtw8821a_iqk_tx_vdf_false(struct rtw_dev *rtwdev, u32 cal, ++ bool *tx0iqkok, ++ int tx_x0[CAL_NUM_8821A], ++ int tx_y0[CAL_NUM_8821A]) ++{ ++ u32 cal_retry, delay_count, iqk_ready, tx_fail; ++ ++ /* TX_Tone_idx[9:0], TxK_Mask[29] TX_Tone = 16 */ ++ rtw_write32(rtwdev, REG_OFDM0_XA_TX_IQ_IMBALANCE, 0x18008c10); ++ /* RX_Tone_idx[9:0], RxK_Mask[29] */ ++ rtw_write32(rtwdev, REG_OFDM0_A_TX_AFE, 0x38008c10); ++ rtw_write32(rtwdev, REG_RFECTL_A, 0x00100000); ++ ++ for (cal_retry = 0; cal_retry < 10; cal_retry++) { ++ /* one shot */ ++ rtw_write32(rtwdev, REG_IQK_COM64, 0xfa000000); ++ rtw_write32(rtwdev, REG_IQK_COM64, 0xf8000000); ++ ++ mdelay(10); ++ rtw_write32(rtwdev, REG_RFECTL_A, 0x00000000); ++ ++ for (delay_count = 0; delay_count < 20; delay_count++) { ++ iqk_ready = rtw_read32_mask(rtwdev, REG_IQKA_END, BIT(10)); ++ ++ /* Originally: if (~iqk_ready || delay_count > 20) ++ * that looks like a typo so make it more explicit ++ */ ++ iqk_ready = true; ++ ++ if (iqk_ready) ++ break; ++ ++ mdelay(1); ++ } ++ ++ if (delay_count < 20) { ++ /* ============TXIQK Check============== */ ++ tx_fail = rtw_read32_mask(rtwdev, REG_IQKA_END, BIT(12)); ++ ++ /* Originally: if (~tx_fail) { ++ * It looks like a typo, so make it more explicit. ++ */ ++ tx_fail = false; ++ ++ if (!tx_fail) { ++ rtw_write32(rtwdev, REG_RFECTL_A, 0x02000000); ++ tx_x0[cal] = rtw_read32_mask(rtwdev, REG_IQKA_END, ++ 0x07ff0000); ++ tx_x0[cal] <<= 21; ++ ++ rtw_write32(rtwdev, REG_RFECTL_A, 0x04000000); ++ tx_y0[cal] = rtw_read32_mask(rtwdev, REG_IQKA_END, ++ 0x07ff0000); ++ tx_y0[cal] <<= 21; ++ ++ *tx0iqkok = true; ++ break; ++ } ++ ++ rtw_write32_mask(rtwdev, REG_IQC_Y, 0x000007ff, 0x0); ++ rtw_write32_mask(rtwdev, REG_IQC_X, 0x000007ff, 0x200); ++ } ++ ++ *tx0iqkok = false; ++ } ++} ++ ++static void rtw8821a_iqk_rx(struct rtw_dev *rtwdev, u32 cal, bool *rx0iqkok, ++ int rx_x0[CAL_NUM_8821A], ++ int rx_y0[CAL_NUM_8821A]) ++{ ++ u32 cal_retry, delay_count, iqk_ready, rx_fail; ++ ++ rtw_write32(rtwdev, REG_RFECTL_A, 0x00100000); ++ ++ for (cal_retry = 0; cal_retry < 10; cal_retry++) { ++ /* one shot */ ++ rtw_write32(rtwdev, REG_IQK_COM64, 0xfa000000); ++ rtw_write32(rtwdev, REG_IQK_COM64, 0xf8000000); ++ ++ mdelay(10); ++ ++ rtw_write32(rtwdev, REG_RFECTL_A, 0x00000000); ++ ++ for (delay_count = 0; delay_count < 20; delay_count++) { ++ iqk_ready = rtw_read32_mask(rtwdev, REG_IQKA_END, BIT(10)); ++ ++ /* Originally: if (~iqk_ready || delay_count > 20) ++ * that looks like a typo so make it more explicit ++ */ ++ iqk_ready = true; ++ ++ if (iqk_ready) ++ break; ++ ++ mdelay(1); ++ } ++ ++ if (delay_count < 20) { ++ /* ============RXIQK Check============== */ ++ rx_fail = rtw_read32_mask(rtwdev, REG_IQKA_END, BIT(11)); ++ if (!rx_fail) { ++ rtw_write32(rtwdev, REG_RFECTL_A, 0x06000000); ++ rx_x0[cal] = rtw_read32_mask(rtwdev, REG_IQKA_END, ++ 0x07ff0000); ++ rx_x0[cal] <<= 21; ++ ++ rtw_write32(rtwdev, REG_RFECTL_A, 0x08000000); ++ rx_y0[cal] = rtw_read32_mask(rtwdev, REG_IQKA_END, ++ 0x07ff0000); ++ rx_y0[cal] <<= 21; ++ ++ *rx0iqkok = true; ++ break; ++ } ++ ++ rtw_write32_mask(rtwdev, REG_RX_IQC_AB_A, ++ 0x000003ff, 0x200 >> 1); ++ rtw_write32_mask(rtwdev, REG_RX_IQC_AB_A, ++ 0x03ff0000, 0x0 >> 1); ++ } ++ ++ *rx0iqkok = false; ++ } ++} ++ ++static void rtw8821a_iqk(struct rtw_dev *rtwdev) ++{ ++ int tx_average = 0, rx_average = 0, rx_iqk_loop = 0; ++ const struct rtw_efuse *efuse = &rtwdev->efuse; ++ int tx_x = 0, tx_y = 0, rx_x = 0, rx_y = 0; ++ const struct rtw_hal *hal = &rtwdev->hal; ++ bool tx0iqkok = false, rx0iqkok = false; ++ int rx_x_temp = 0, rx_y_temp = 0; ++ int rx_x0[2][CAL_NUM_8821A]; ++ int rx_y0[2][CAL_NUM_8821A]; ++ int tx_x0[CAL_NUM_8821A]; ++ int tx_y0[CAL_NUM_8821A]; ++ bool rx_finish1 = false; ++ bool rx_finish2 = false; ++ bool vdf_enable; ++ u32 cal; ++ int i; ++ ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "band_width = %d, ext_pa = %d, ext_pa_5g = %d\n", ++ hal->current_band_width, efuse->ext_pa_2g, efuse->ext_pa_5g); ++ ++ vdf_enable = hal->current_band_width == RTW_CHANNEL_WIDTH_80; ++ ++ for (cal = 0; cal < CAL_NUM_8821A; cal++) { ++ /* path-A LOK */ ++ ++ /* [31] = 0 --> Page C */ ++ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0); ++ ++ /* ========path-A AFE all on======== */ ++ /* Port 0 DAC/ADC on */ ++ rtw_write32(rtwdev, REG_AFE_PWR1_A, 0x77777777); ++ rtw_write32(rtwdev, REG_AFE_PWR2_A, 0x77777777); ++ ++ rtw_write32(rtwdev, REG_RX_WAIT_CCA_TX_CCK_RFON_A, 0x19791979); ++ ++ /* hardware 3-wire off */ ++ rtw_write32_mask(rtwdev, REG_3WIRE_SWA, 0xf, 0x4); ++ ++ /* LOK setting */ ++ ++ /* 1. DAC/ADC sampling rate (160 MHz) */ ++ rtw_write32_mask(rtwdev, REG_CK_MONHA, GENMASK(26, 24), 0x7); ++ ++ /* 2. LoK RF setting (at BW = 20M) */ ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE, RFREG_MASK, 0x80002); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, 0x00c00, 0x3); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_ADDR, RFREG_MASK, ++ 0x20000); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_DATA0, RFREG_MASK, ++ 0x0003f); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_DATA1, RFREG_MASK, ++ 0xf3fc3); ++ ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_TXA_PREPAD, RFREG_MASK, ++ 0x931d5); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_RXBB2, RFREG_MASK, 0x8a001); ++ rtw_write32(rtwdev, REG_DAC_RSTB, 0x00008000); ++ rtw_write32_mask(rtwdev, REG_TXAGCIDX, BIT(0), 0x1); ++ /* TX (X,Y) */ ++ rtw_write32(rtwdev, REG_IQK_COM00, 0x29002000); ++ /* RX (X,Y) */ ++ rtw_write32(rtwdev, REG_IQK_COM32, 0xa9002000); ++ /* [0]:AGC_en, [15]:idac_K_Mask */ ++ rtw_write32(rtwdev, REG_IQK_COM96, 0x00462910); ++ ++ /* [31] = 1 --> Page C1 */ ++ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1); ++ ++ if (efuse->ext_pa_5g) ++ rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE, ++ 0x821403f7); ++ else ++ rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE, ++ 0x821403f4); ++ ++ if (hal->current_band_type == RTW_BAND_5G) ++ rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x68163e96); ++ else ++ rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x28163e96); ++ ++ /* TX_Tone_idx[9:0], TxK_Mask[29] TX_Tone = 16 */ ++ rtw_write32(rtwdev, REG_OFDM0_XA_TX_IQ_IMBALANCE, 0x18008c10); ++ /* RX_Tone_idx[9:0], RxK_Mask[29] */ ++ rtw_write32(rtwdev, REG_OFDM0_A_TX_AFE, 0x38008c10); ++ rtw_write32(rtwdev, REG_RFECTL_A, 0x00100000); ++ rtw_write32(rtwdev, REG_IQK_COM64, 0xfa000000); ++ rtw_write32(rtwdev, REG_IQK_COM64, 0xf8000000); ++ ++ mdelay(10); ++ rtw_write32(rtwdev, REG_RFECTL_A, 0x00000000); ++ ++ /* [31] = 0 --> Page C */ ++ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_TXMOD, 0x7fe00, ++ rtw_read_rf(rtwdev, RF_PATH_A, RF_DTXLOK, 0xffc00)); ++ ++ if (hal->current_band_width == RTW_CHANNEL_WIDTH_40) ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, ++ RF18_BW_MASK, 0x1); ++ else if (hal->current_band_width == RTW_CHANNEL_WIDTH_80) ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, ++ RF18_BW_MASK, 0x0); ++ ++ /* [31] = 1 --> Page C1 */ ++ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1); ++ ++ /* 3. TX RF setting */ ++ /* [31] = 0 --> Page C */ ++ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE, RFREG_MASK, 0x80000); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_ADDR, RFREG_MASK, ++ 0x20000); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_DATA0, RFREG_MASK, ++ 0x0003f); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_DATA1, RFREG_MASK, ++ 0xf3fc3); ++ ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_TXA_PREPAD, RFREG_MASK, 0x931d5); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_RXBB2, RFREG_MASK, 0x8a001); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE, RFREG_MASK, 0x00000); ++ rtw_write32(rtwdev, REG_DAC_RSTB, 0x00008000); ++ rtw_write32_mask(rtwdev, REG_TXAGCIDX, BIT(0), 0x1); ++ /* TX (X,Y) */ ++ rtw_write32(rtwdev, REG_IQK_COM00, 0x29002000); ++ /* RX (X,Y) */ ++ rtw_write32(rtwdev, REG_IQK_COM32, 0xa9002000); ++ /* [0]:AGC_en, [15]:idac_K_Mask */ ++ rtw_write32(rtwdev, REG_IQK_COM96, 0x0046a910); ++ ++ /* [31] = 1 --> Page C1 */ ++ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1); ++ ++ if (efuse->ext_pa_5g) ++ rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE, ++ 0x821403f7); ++ else ++ rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE, ++ 0x821403e3); ++ ++ if (hal->current_band_type == RTW_BAND_5G) ++ rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x40163e96); ++ else ++ rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x00163e96); ++ ++ if (vdf_enable) ++ rtw8821a_iqk_tx_vdf_true(rtwdev, cal, &tx0iqkok, ++ tx_x0, tx_y0); ++ else ++ rtw8821a_iqk_tx_vdf_false(rtwdev, cal, &tx0iqkok, ++ tx_x0, tx_y0); ++ ++ if (!tx0iqkok) ++ break; /* TXK fail, Don't do RXK */ ++ ++ /* ====== RX IQK ====== */ ++ /* [31] = 0 --> Page C */ ++ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0); ++ /* 1. RX RF setting */ ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE, RFREG_MASK, 0x80000); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_ADDR, RFREG_MASK, ++ 0x30000); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_DATA0, RFREG_MASK, ++ 0x0002f); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_DATA1, RFREG_MASK, ++ 0xfffbb); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_RXBB2, RFREG_MASK, 0x88001); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_TXA_PREPAD, RFREG_MASK, 0x931d8); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE, RFREG_MASK, 0x00000); ++ ++ rtw_write32_mask(rtwdev, REG_IQK_COM00, 0x03FF8000, ++ (tx_x0[cal] >> 21) & 0x000007ff); ++ rtw_write32_mask(rtwdev, REG_IQK_COM00, 0x000007FF, ++ (tx_y0[cal] >> 21) & 0x000007ff); ++ rtw_write32_mask(rtwdev, REG_IQK_COM00, BIT(31), 0x1); ++ rtw_write32_mask(rtwdev, REG_IQK_COM00, BIT(31), 0x0); ++ rtw_write32(rtwdev, REG_DAC_RSTB, 0x00008000); ++ rtw_write32(rtwdev, REG_IQK_COM96, 0x0046a911); ++ ++ /* [31] = 1 --> Page C1 */ ++ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1); ++ ++ /* TX_Tone_idx[9:0], TxK_Mask[29] TX_Tone = 16 */ ++ rtw_write32(rtwdev, REG_OFDM0_XA_TX_IQ_IMBALANCE, 0x38008c10); ++ /* RX_Tone_idx[9:0], RxK_Mask[29] */ ++ rtw_write32(rtwdev, REG_OFDM0_A_TX_AFE, 0x18008c10); ++ rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE, 0x02140119); ++ ++ if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_PCIE) ++ rx_iqk_loop = 2; /* for 2% fail; */ ++ else ++ rx_iqk_loop = 1; ++ ++ for (i = 0; i < rx_iqk_loop; i++) { ++ if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_PCIE && i == 0) ++ rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x28161100); /* Good */ ++ else ++ rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x28160d00); ++ ++ rtw8821a_iqk_rx(rtwdev, cal, &rx0iqkok, ++ rx_x0[i], rx_y0[i]); ++ } ++ ++ if (tx0iqkok) ++ tx_average++; ++ if (rx0iqkok) ++ rx_average++; ++ } ++ ++ /* FillIQK Result */ ++ ++ if (tx_average == 0) ++ return; ++ ++ for (i = 0; i < tx_average; i++) ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "tx_x0[%d] = %x ;; tx_y0[%d] = %x\n", ++ i, (tx_x0[i] >> 21) & 0x000007ff, ++ i, (tx_y0[i] >> 21) & 0x000007ff); ++ ++ if (rtw88xxa_iqk_finish(tx_average, 3, tx_x0, tx_y0, ++ &tx_x, &tx_y, true, true)) ++ rtw8821a_iqk_tx_fill(rtwdev, tx_x, tx_y); ++ else ++ rtw8821a_iqk_tx_fill(rtwdev, 0x200, 0x0); ++ ++ if (rx_average == 0) ++ return; ++ ++ for (i = 0; i < rx_average; i++) { ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "rx_x0[0][%d] = %x ;; rx_y0[0][%d] = %x\n", ++ i, (rx_x0[0][i] >> 21) & 0x000007ff, ++ i, (rx_y0[0][i] >> 21) & 0x000007ff); ++ ++ if (rx_iqk_loop == 2) ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "rx_x0[1][%d] = %x ;; rx_y0[1][%d] = %x\n", ++ i, (rx_x0[1][i] >> 21) & 0x000007ff, ++ i, (rx_y0[1][i] >> 21) & 0x000007ff); ++ } ++ ++ rx_finish1 = rtw88xxa_iqk_finish(rx_average, 4, rx_x0[0], rx_y0[0], ++ &rx_x_temp, &rx_y_temp, true, true); ++ ++ if (rx_finish1) { ++ rx_x = rx_x_temp; ++ rx_y = rx_y_temp; ++ } ++ ++ if (rx_iqk_loop == 2) { ++ rx_finish2 = rtw88xxa_iqk_finish(rx_average, 4, ++ rx_x0[1], rx_y0[1], ++ &rx_x, &rx_y, true, true); ++ ++ if (rx_finish1 && rx_finish2) { ++ rx_x = (rx_x + rx_x_temp) / 2; ++ rx_y = (rx_y + rx_y_temp) / 2; ++ } ++ } ++ ++ if (rx_finish1 || rx_finish2) ++ rtw8821a_iqk_rx_fill(rtwdev, rx_x, rx_y); ++ else ++ rtw8821a_iqk_rx_fill(rtwdev, 0x200, 0x0); ++} ++ ++static void rtw8821a_do_iqk(struct rtw_dev *rtwdev) ++{ ++ static const u32 backup_macbb_reg[MACBB_REG_NUM_8821A] = { ++ 0x520, 0x550, 0x808, 0xa04, 0x90c, 0xc00, 0x838, 0x82c ++ }; ++ static const u32 backup_afe_reg[AFE_REG_NUM_8821A] = { ++ 0xc5c, 0xc60, 0xc64, 0xc68 ++ }; ++ static const u32 backup_rf_reg[RF_REG_NUM_8821A] = { ++ 0x65, 0x8f, 0x0 ++ }; ++ u32 macbb_backup[MACBB_REG_NUM_8821A]; ++ u32 afe_backup[AFE_REG_NUM_8821A]; ++ u32 rfa_backup[RF_REG_NUM_8821A]; ++ ++ rtw88xxa_iqk_backup_mac_bb(rtwdev, macbb_backup, ++ backup_macbb_reg, MACBB_REG_NUM_8821A); ++ rtw88xxa_iqk_backup_afe(rtwdev, afe_backup, ++ backup_afe_reg, AFE_REG_NUM_8821A); ++ rtw8821a_iqk_backup_rf(rtwdev, rfa_backup, ++ backup_rf_reg, RF_REG_NUM_8821A); ++ ++ rtw88xxa_iqk_configure_mac(rtwdev); ++ ++ rtw8821a_iqk(rtwdev); ++ ++ rtw8821a_iqk_restore_rf(rtwdev, backup_rf_reg, ++ rfa_backup, RF_REG_NUM_8821A); ++ rtw8821a_iqk_restore_afe(rtwdev, afe_backup, ++ backup_afe_reg, AFE_REG_NUM_8821A); ++ rtw88xxa_iqk_restore_mac_bb(rtwdev, macbb_backup, ++ backup_macbb_reg, MACBB_REG_NUM_8821A); ++} ++ ++static void rtw8821a_phy_calibration(struct rtw_dev *rtwdev) ++{ ++ rtw8821a_do_iqk(rtwdev); ++} ++ ++static void rtw8821a_pwr_track(struct rtw_dev *rtwdev) ++{ ++ struct rtw_dm_info *dm_info = &rtwdev->dm_info; ++ ++ if (!dm_info->pwr_trk_triggered) { ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_T_METER, ++ GENMASK(17, 16), 0x03); ++ dm_info->pwr_trk_triggered = true; ++ return; ++ } ++ ++ rtw88xxa_phy_pwrtrack(rtwdev, NULL, rtw8821a_do_iqk); ++ dm_info->pwr_trk_triggered = false; ++} ++ ++static void rtw8821a_fill_txdesc_checksum(struct rtw_dev *rtwdev, ++ struct rtw_tx_pkt_info *pkt_info, ++ u8 *txdesc) ++{ ++ fill_txdesc_checksum_common(txdesc, 16); ++} ++ ++static void rtw8821a_coex_cfg_init(struct rtw_dev *rtwdev) ++{ ++ u8 val8; ++ ++ /* BT report packet sample rate */ ++ rtw_write8_mask(rtwdev, REG_BT_TDMA_TIME, BIT_MASK_SAMPLE_RATE, 0x5); ++ ++ val8 = BIT_STATIS_BT_EN; ++ if (rtwdev->efuse.share_ant) ++ val8 |= BIT_R_GRANTALL_WLMASK; ++ rtw_write8(rtwdev, REG_BT_COEX_ENH_INTR_CTRL, val8); ++ ++ /* enable BT counter statistics */ ++ rtw_write8(rtwdev, REG_BT_STAT_CTRL, 0x3); ++ ++ /* enable PTA */ ++ rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_BT_PTA_EN); ++} ++ ++static void rtw8821a_coex_cfg_ant_switch(struct rtw_dev *rtwdev, u8 ctrl_type, ++ u8 pos_type) ++{ ++ bool share_ant = rtwdev->efuse.share_ant; ++ struct rtw_coex *coex = &rtwdev->coex; ++ struct rtw_coex_dm *coex_dm = &coex->dm; ++ u32 phase = coex_dm->cur_ant_pos_type; ++ ++ if (!rtwdev->efuse.btcoex) ++ return; ++ ++ switch (phase) { ++ case COEX_SET_ANT_POWERON: ++ case COEX_SET_ANT_INIT: ++ rtw_write32_clr(rtwdev, REG_LED_CFG, BIT_DPDT_SEL_EN); ++ rtw_write32_set(rtwdev, REG_LED_CFG, BIT_DPDT_WL_SEL); ++ rtw_write8_set(rtwdev, REG_GNT_BT, BIT_PTA_SW_CTL); ++ ++ rtw_write8(rtwdev, REG_RFE_CTRL8, ++ share_ant ? PTA_CTRL_PIN : DPDT_CTRL_PIN); ++ rtw_write32_mask(rtwdev, REG_RFE_CTRL8, 0x30000000, 0x1); ++ break; ++ case COEX_SET_ANT_WONLY: ++ rtw_write32_clr(rtwdev, REG_LED_CFG, BIT_DPDT_SEL_EN); ++ rtw_write32_set(rtwdev, REG_LED_CFG, BIT_DPDT_WL_SEL); ++ rtw_write8_clr(rtwdev, REG_GNT_BT, BIT_PTA_SW_CTL); ++ ++ rtw_write8(rtwdev, REG_RFE_CTRL8, DPDT_CTRL_PIN); ++ rtw_write32_mask(rtwdev, REG_RFE_CTRL8, 0x30000000, 0x1); ++ break; ++ case COEX_SET_ANT_2G: ++ rtw_write32_clr(rtwdev, REG_LED_CFG, BIT_DPDT_SEL_EN); ++ rtw_write32_set(rtwdev, REG_LED_CFG, BIT_DPDT_WL_SEL); ++ rtw_write8_clr(rtwdev, REG_GNT_BT, BIT_PTA_SW_CTL); ++ ++ rtw_write8(rtwdev, REG_RFE_CTRL8, ++ share_ant ? PTA_CTRL_PIN : DPDT_CTRL_PIN); ++ rtw_write32_mask(rtwdev, REG_RFE_CTRL8, 0x30000000, 0x1); ++ break; ++ case COEX_SET_ANT_5G: ++ rtw_write32_clr(rtwdev, REG_LED_CFG, BIT_DPDT_SEL_EN); ++ rtw_write32_set(rtwdev, REG_LED_CFG, BIT_DPDT_WL_SEL); ++ rtw_write8_set(rtwdev, REG_GNT_BT, BIT_PTA_SW_CTL); ++ ++ rtw_write8(rtwdev, REG_RFE_CTRL8, DPDT_CTRL_PIN); ++ rtw_write32_mask(rtwdev, REG_RFE_CTRL8, 0x30000000, ++ share_ant ? 0x2 : 0x1); ++ break; ++ case COEX_SET_ANT_WOFF: ++ rtw_write32_clr(rtwdev, REG_LED_CFG, BIT_DPDT_SEL_EN); ++ rtw_write32_clr(rtwdev, REG_LED_CFG, BIT_DPDT_WL_SEL); ++ rtw_write8_set(rtwdev, REG_GNT_BT, BIT_PTA_SW_CTL); ++ ++ rtw_write8(rtwdev, REG_RFE_CTRL8, DPDT_CTRL_PIN); ++ rtw_write32_mask(rtwdev, REG_RFE_CTRL8, 0x30000000, ++ share_ant ? 0x2 : 0x1); ++ break; ++ default: ++ rtw_warn(rtwdev, "%s: not handling phase %d\n", ++ __func__, phase); ++ break; ++ } ++} ++ ++static void rtw8821a_coex_cfg_gnt_fix(struct rtw_dev *rtwdev) ++{ ++} ++ ++static void rtw8821a_coex_cfg_gnt_debug(struct rtw_dev *rtwdev) ++{ ++} ++ ++static void rtw8821a_coex_cfg_rfe_type(struct rtw_dev *rtwdev) ++{ ++ struct rtw_coex *coex = &rtwdev->coex; ++ struct rtw_coex_rfe *coex_rfe = &coex->rfe; ++ ++ coex_rfe->ant_switch_exist = true; ++} ++ ++static void rtw8821a_coex_cfg_wl_tx_power(struct rtw_dev *rtwdev, u8 wl_pwr) ++{ ++ struct rtw_coex *coex = &rtwdev->coex; ++ struct rtw_coex_dm *coex_dm = &coex->dm; ++ struct rtw_efuse *efuse = &rtwdev->efuse; ++ bool share_ant = efuse->share_ant; ++ ++ if (share_ant) ++ return; ++ ++ if (wl_pwr == coex_dm->cur_wl_pwr_lvl) ++ return; ++ ++ coex_dm->cur_wl_pwr_lvl = wl_pwr; ++} ++ ++static void rtw8821a_coex_cfg_wl_rx_gain(struct rtw_dev *rtwdev, bool low_gain) ++{ ++} ++ ++static const struct rtw_chip_ops rtw8821a_ops = { ++ .power_on = rtw88xxa_power_on, ++ .power_off = rtw8821a_power_off, ++ .phy_set_param = NULL, ++ .read_efuse = rtw88xxa_read_efuse, ++ .query_phy_status = rtw8821a_query_phy_status, ++ .set_channel = rtw88xxa_set_channel, ++ .mac_init = NULL, ++ .read_rf = rtw88xxa_phy_read_rf, ++ .write_rf = rtw_phy_write_rf_reg_sipi, ++ .set_antenna = NULL, ++ .set_tx_power_index = rtw88xxa_set_tx_power_index, ++ .cfg_ldo25 = rtw8821a_cfg_ldo25, ++ .efuse_grant = rtw88xxa_efuse_grant, ++ .false_alarm_statistics = rtw88xxa_false_alarm_statistics, ++ .phy_calibration = rtw8821a_phy_calibration, ++ .cck_pd_set = rtw88xxa_phy_cck_pd_set, ++ .pwr_track = rtw8821a_pwr_track, ++ .config_bfee = NULL, ++ .set_gid_table = NULL, ++ .cfg_csi_rate = NULL, ++ .fill_txdesc_checksum = rtw8821a_fill_txdesc_checksum, ++ .coex_set_init = rtw8821a_coex_cfg_init, ++ .coex_set_ant_switch = rtw8821a_coex_cfg_ant_switch, ++ .coex_set_gnt_fix = rtw8821a_coex_cfg_gnt_fix, ++ .coex_set_gnt_debug = rtw8821a_coex_cfg_gnt_debug, ++ .coex_set_rfe_type = rtw8821a_coex_cfg_rfe_type, ++ .coex_set_wl_tx_power = rtw8821a_coex_cfg_wl_tx_power, ++ .coex_set_wl_rx_gain = rtw8821a_coex_cfg_wl_rx_gain, ++}; ++ ++static const struct rtw_page_table page_table_8821a[] = { ++ /* hq_num, nq_num, lq_num, exq_num, gapq_num */ ++ {0, 0, 0, 0, 0}, /* SDIO */ ++ {0, 0, 0, 0, 0}, /* PCI */ ++ {8, 0, 0, 0, 1}, /* 2 bulk out endpoints */ ++ {8, 0, 8, 0, 1}, /* 3 bulk out endpoints */ ++ {8, 0, 8, 4, 1}, /* 4 bulk out endpoints */ ++}; ++ ++static const struct rtw_rqpn rqpn_table_8821a[] = { ++ {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL, ++ RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW, ++ RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH}, ++ ++ {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL, ++ RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW, ++ RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH}, ++ ++ {RTW_DMA_MAPPING_HIGH, RTW_DMA_MAPPING_HIGH, ++ RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL, ++ RTW_DMA_MAPPING_HIGH, RTW_DMA_MAPPING_HIGH}, ++ ++ {RTW_DMA_MAPPING_HIGH, RTW_DMA_MAPPING_NORMAL, ++ RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW, ++ RTW_DMA_MAPPING_HIGH, RTW_DMA_MAPPING_HIGH}, ++ ++ {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL, ++ RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW, ++ RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH}, ++}; ++ ++static const struct rtw_prioq_addrs prioq_addrs_8821a = { ++ .prio[RTW_DMA_MAPPING_EXTRA] = { ++ .rsvd = REG_RQPN_NPQ + 2, .avail = REG_RQPN_NPQ + 3, ++ }, ++ .prio[RTW_DMA_MAPPING_LOW] = { ++ .rsvd = REG_RQPN + 1, .avail = REG_FIFOPAGE_CTRL_2 + 1, ++ }, ++ .prio[RTW_DMA_MAPPING_NORMAL] = { ++ .rsvd = REG_RQPN_NPQ, .avail = REG_RQPN_NPQ + 1, ++ }, ++ .prio[RTW_DMA_MAPPING_HIGH] = { ++ .rsvd = REG_RQPN, .avail = REG_FIFOPAGE_CTRL_2, ++ }, ++ .wsize = false, ++}; ++ ++static const struct rtw_hw_reg rtw8821a_dig[] = { ++ [0] = { .addr = REG_RXIGI_A, .mask = 0x7f }, ++}; ++ ++static const struct rtw_rfe_def rtw8821a_rfe_defs[] = { ++ [0] = { .phy_pg_tbl = &rtw8821a_bb_pg_tbl, ++ .txpwr_lmt_tbl = &rtw8821a_txpwr_lmt_tbl, ++ .pwr_track_tbl = &rtw8821a_rtw_pwr_track_tbl, }, ++}; ++ ++/* TODO */ ++/* rssi in percentage % (dbm = % - 100) */ ++static const u8 wl_rssi_step_8821a[] = {101, 45, 101, 40}; ++static const u8 bt_rssi_step_8821a[] = {101, 101, 101, 101}; ++ ++/* table_sant_8821a, table_nsant_8821a, tdma_sant_8821a, and tdma_nsant_8821a ++ * are copied from rtw8821c.c because the 8821au driver's tables are not ++ * compatible with the coex code in rtw88. ++ * ++ * tdma case 112 (A2DP) byte 0 had to be modified from 0x61 to 0x51, ++ * otherwise the firmware gets confused after pausing the music: ++ * rtw_8821au 1-2:1.2: [BTCoex], Bt_info[1], len=7, data=[81 00 0a 01 00 00] ++ * - 81 means PAN (personal area network) when it should be 4x (A2DP) ++ * The music is not smooth with the PAN algorithm. ++ */ ++ ++/* Shared-Antenna Coex Table */ ++static const struct coex_table_para table_sant_8821a[] = { ++ {0x55555555, 0x55555555}, /* case-0 */ ++ {0x55555555, 0x55555555}, ++ {0x66555555, 0x66555555}, ++ {0xaaaaaaaa, 0xaaaaaaaa}, ++ {0x5a5a5a5a, 0x5a5a5a5a}, ++ {0xfafafafa, 0xfafafafa}, /* case-5 */ ++ {0x6a5a5555, 0xaaaaaaaa}, ++ {0x6a5a56aa, 0x6a5a56aa}, ++ {0x6a5a5a5a, 0x6a5a5a5a}, ++ {0x66555555, 0x5a5a5a5a}, ++ {0x66555555, 0x6a5a5a5a}, /* case-10 */ ++ {0x66555555, 0xaaaaaaaa}, ++ {0x66555555, 0x6a5a5aaa}, ++ {0x66555555, 0x6aaa6aaa}, ++ {0x66555555, 0x6a5a5aaa}, ++ {0x66555555, 0xaaaaaaaa}, /* case-15 */ ++ {0xffff55ff, 0xfafafafa}, ++ {0xffff55ff, 0x6afa5afa}, ++ {0xaaffffaa, 0xfafafafa}, ++ {0xaa5555aa, 0x5a5a5a5a}, ++ {0xaa5555aa, 0x6a5a5a5a}, /* case-20 */ ++ {0xaa5555aa, 0xaaaaaaaa}, ++ {0xffffffff, 0x55555555}, ++ {0xffffffff, 0x5a5a5a5a}, ++ {0xffffffff, 0x5a5a5a5a}, ++ {0xffffffff, 0x5a5a5aaa}, /* case-25 */ ++ {0x55555555, 0x5a5a5a5a}, ++ {0x55555555, 0xaaaaaaaa}, ++ {0x66555555, 0x6a5a6a5a}, ++ {0x66556655, 0x66556655}, ++ {0x66556aaa, 0x6a5a6aaa}, /* case-30 */ ++ {0xffffffff, 0x5aaa5aaa}, ++ {0x56555555, 0x5a5a5aaa} ++}; ++ ++/* Non-Shared-Antenna Coex Table */ ++static const struct coex_table_para table_nsant_8821a[] = { ++ {0xffffffff, 0xffffffff}, /* case-100 */ ++ {0xffff55ff, 0xfafafafa}, ++ {0x66555555, 0x66555555}, ++ {0xaaaaaaaa, 0xaaaaaaaa}, ++ {0x5a5a5a5a, 0x5a5a5a5a}, ++ {0xffffffff, 0xffffffff}, /* case-105 */ ++ {0x5afa5afa, 0x5afa5afa}, ++ {0x55555555, 0xfafafafa}, ++ {0x66555555, 0xfafafafa}, ++ {0x66555555, 0x5a5a5a5a}, ++ {0x66555555, 0x6a5a5a5a}, /* case-110 */ ++ {0x66555555, 0xaaaaaaaa}, ++ {0xffff55ff, 0xfafafafa}, ++ {0xffff55ff, 0x5afa5afa}, ++ {0xffff55ff, 0xaaaaaaaa}, ++ {0xffff55ff, 0xffff55ff}, /* case-115 */ ++ {0xaaffffaa, 0x5afa5afa}, ++ {0xaaffffaa, 0xaaaaaaaa}, ++ {0xffffffff, 0xfafafafa}, ++ {0xffff55ff, 0xfafafafa}, ++ {0xffffffff, 0xaaaaaaaa}, /* case-120 */ ++ {0xffff55ff, 0x5afa5afa}, ++ {0xffff55ff, 0x5afa5afa}, ++ {0x55ff55ff, 0x55ff55ff} ++}; ++ ++/* Shared-Antenna TDMA */ ++static const struct coex_tdma_para tdma_sant_8821a[] = { ++ { {0x00, 0x00, 0x00, 0x00, 0x00} }, /* case-0 */ ++ { {0x61, 0x45, 0x03, 0x11, 0x11} }, /* case-1 */ ++ { {0x61, 0x3a, 0x03, 0x11, 0x11} }, ++ { {0x61, 0x35, 0x03, 0x11, 0x11} }, ++ { {0x61, 0x20, 0x03, 0x11, 0x11} }, ++ { {0x61, 0x3a, 0x03, 0x11, 0x11} }, /* case-5 */ ++ { {0x61, 0x45, 0x03, 0x11, 0x10} }, ++ { {0x61, 0x35, 0x03, 0x11, 0x10} }, ++ { {0x61, 0x30, 0x03, 0x11, 0x10} }, ++ { {0x61, 0x20, 0x03, 0x11, 0x10} }, ++ { {0x61, 0x10, 0x03, 0x11, 0x10} }, /* case-10 */ ++ { {0x61, 0x08, 0x03, 0x11, 0x15} }, ++ { {0x61, 0x08, 0x03, 0x10, 0x14} }, ++ { {0x51, 0x08, 0x03, 0x10, 0x54} }, ++ { {0x51, 0x08, 0x03, 0x10, 0x55} }, ++ { {0x51, 0x08, 0x07, 0x10, 0x54} }, /* case-15 */ ++ { {0x51, 0x45, 0x03, 0x10, 0x50} }, ++ { {0x51, 0x3a, 0x03, 0x11, 0x50} }, ++ { {0x51, 0x30, 0x03, 0x10, 0x50} }, ++ { {0x51, 0x21, 0x03, 0x10, 0x50} }, ++ { {0x51, 0x10, 0x03, 0x10, 0x50} }, /* case-20 */ ++ { {0x51, 0x4a, 0x03, 0x10, 0x50} }, ++ { {0x51, 0x08, 0x03, 0x30, 0x54} }, ++ { {0x55, 0x08, 0x03, 0x10, 0x54} }, ++ { {0x65, 0x10, 0x03, 0x11, 0x10} }, ++ { {0x51, 0x10, 0x03, 0x10, 0x51} }, /* case-25 */ ++ { {0x51, 0x21, 0x03, 0x10, 0x50} }, ++ { {0x61, 0x08, 0x03, 0x11, 0x11} } ++}; ++ ++/* Non-Shared-Antenna TDMA */ ++static const struct coex_tdma_para tdma_nsant_8821a[] = { ++ { {0x00, 0x00, 0x00, 0x40, 0x00} }, /* case-100 */ ++ { {0x61, 0x45, 0x03, 0x11, 0x11} }, ++ { {0x61, 0x25, 0x03, 0x11, 0x11} }, ++ { {0x61, 0x35, 0x03, 0x11, 0x11} }, ++ { {0x61, 0x20, 0x03, 0x11, 0x11} }, ++ { {0x61, 0x10, 0x03, 0x11, 0x11} }, /* case-105 */ ++ { {0x61, 0x45, 0x03, 0x11, 0x10} }, ++ { {0x61, 0x30, 0x03, 0x11, 0x10} }, ++ { {0x61, 0x30, 0x03, 0x11, 0x10} }, ++ { {0x61, 0x20, 0x03, 0x11, 0x10} }, ++ { {0x61, 0x10, 0x03, 0x11, 0x10} }, /* case-110 */ ++ { {0x61, 0x10, 0x03, 0x11, 0x11} }, ++ { {0x51, 0x08, 0x03, 0x10, 0x14} }, /* a2dp high rssi */ ++ { {0x51, 0x08, 0x03, 0x10, 0x54} }, /* a2dp not high rssi */ ++ { {0x51, 0x08, 0x03, 0x10, 0x55} }, ++ { {0x51, 0x08, 0x07, 0x10, 0x54} }, /* case-115 */ ++ { {0x51, 0x45, 0x03, 0x10, 0x50} }, ++ { {0x51, 0x3a, 0x03, 0x10, 0x50} }, ++ { {0x51, 0x30, 0x03, 0x10, 0x50} }, ++ { {0x51, 0x21, 0x03, 0x10, 0x50} }, ++ { {0x51, 0x21, 0x03, 0x10, 0x50} }, /* case-120 */ ++ { {0x51, 0x10, 0x03, 0x10, 0x50} } ++}; ++ ++/* TODO */ ++static const struct coex_rf_para rf_para_tx_8821a[] = { ++ {0, 0, false, 7}, /* for normal */ ++ {0, 20, false, 7}, /* for WL-CPT */ ++ {8, 17, true, 4}, ++ {7, 18, true, 4}, ++ {6, 19, true, 4}, ++ {5, 20, true, 4} ++}; ++ ++static const struct coex_rf_para rf_para_rx_8821a[] = { ++ {0, 0, false, 7}, /* for normal */ ++ {0, 20, false, 7}, /* for WL-CPT */ ++ {3, 24, true, 5}, ++ {2, 26, true, 5}, ++ {1, 27, true, 5}, ++ {0, 28, true, 5} ++}; ++ ++static_assert(ARRAY_SIZE(rf_para_tx_8821a) == ARRAY_SIZE(rf_para_rx_8821a)); ++ ++static const struct coex_5g_afh_map afh_5g_8821a[] = { {0, 0, 0} }; ++ ++static const struct rtw_reg_domain coex_info_hw_regs_8821a[] = { ++ {0xCB0, MASKDWORD, RTW_REG_DOMAIN_MAC32}, ++ {0xCB4, MASKDWORD, RTW_REG_DOMAIN_MAC32}, ++ {0xCBA, MASKBYTE0, RTW_REG_DOMAIN_MAC8}, ++ {0, 0, RTW_REG_DOMAIN_NL}, ++ {0x430, MASKDWORD, RTW_REG_DOMAIN_MAC32}, ++ {0x434, MASKDWORD, RTW_REG_DOMAIN_MAC32}, ++ {0x42a, MASKLWORD, RTW_REG_DOMAIN_MAC16}, ++ {0x426, MASKBYTE0, RTW_REG_DOMAIN_MAC8}, ++ {0x45e, BIT(3), RTW_REG_DOMAIN_MAC8}, ++ {0x454, MASKLWORD, RTW_REG_DOMAIN_MAC16}, ++ {0, 0, RTW_REG_DOMAIN_NL}, ++ {0x4c, BIT(24) | BIT(23), RTW_REG_DOMAIN_MAC32}, ++ {0x64, BIT(0), RTW_REG_DOMAIN_MAC8}, ++ {0x4c6, BIT(4), RTW_REG_DOMAIN_MAC8}, ++ {0x40, BIT(5), RTW_REG_DOMAIN_MAC8}, ++ {0x1, RFREG_MASK, RTW_REG_DOMAIN_RF_A}, ++ {0, 0, RTW_REG_DOMAIN_NL}, ++ {0x550, MASKDWORD, RTW_REG_DOMAIN_MAC32}, ++ {0x522, MASKBYTE0, RTW_REG_DOMAIN_MAC8}, ++ {0x953, BIT(1), RTW_REG_DOMAIN_MAC8}, ++ {0xc50, MASKBYTE0, RTW_REG_DOMAIN_MAC8}, ++ {0x60A, MASKBYTE0, RTW_REG_DOMAIN_MAC8}, ++}; ++ ++const struct rtw_chip_info rtw8821a_hw_spec = { ++ .ops = &rtw8821a_ops, ++ .id = RTW_CHIP_TYPE_8821A, ++ .fw_name = "rtw88/rtw8821a_fw.bin", ++ .wlan_cpu = RTW_WCPU_11N, ++ .tx_pkt_desc_sz = 40, ++ .tx_buf_desc_sz = 16, ++ .rx_pkt_desc_sz = 24, ++ .rx_buf_desc_sz = 8, ++ .phy_efuse_size = 512, ++ .log_efuse_size = 512, ++ .ptct_efuse_size = 96 + 1, /* TODO or just 18? */ ++ .txff_size = 65536, ++ .rxff_size = 16128, ++ .rsvd_drv_pg_num = 8, ++ .txgi_factor = 1, ++ .is_pwr_by_rate_dec = true, ++ .max_power_index = 0x3f, ++ .csi_buf_pg_num = 0, ++ .band = RTW_BAND_2G | RTW_BAND_5G, ++ .page_size = 256, ++ .dig_min = 0x20, ++ .ht_supported = true, ++ .vht_supported = true, ++ .lps_deep_mode_supported = 0, ++ .sys_func_en = 0xFD, ++ .pwr_on_seq = card_enable_flow_8821a, ++ .pwr_off_seq = card_disable_flow_8821a, ++ .page_table = page_table_8821a, ++ .rqpn_table = rqpn_table_8821a, ++ .prioq_addrs = &prioq_addrs_8821a, ++ .intf_table = NULL, ++ .dig = rtw8821a_dig, ++ .rf_sipi_addr = {REG_LSSI_WRITE_A, REG_LSSI_WRITE_B}, ++ .ltecoex_addr = NULL, ++ .mac_tbl = &rtw8821a_mac_tbl, ++ .agc_tbl = &rtw8821a_agc_tbl, ++ .bb_tbl = &rtw8821a_bb_tbl, ++ .rf_tbl = {&rtw8821a_rf_a_tbl}, ++ .rfe_defs = rtw8821a_rfe_defs, ++ .rfe_defs_size = ARRAY_SIZE(rtw8821a_rfe_defs), ++ .rx_ldpc = false, ++ .hw_feature_report = false, ++ .c2h_ra_report_size = 4, ++ .old_datarate_fb_limit = true, ++ .usb_tx_agg_desc_num = 6, ++ .iqk_threshold = 8, ++ .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, ++ .max_scan_ie_len = IEEE80211_MAX_DATA_LEN, ++ ++ .coex_para_ver = 20190509, /* glcoex_ver_date_8821a_1ant */ ++ .bt_desired_ver = 0x62, /* But for 2 ant it's 0x5c */ ++ .scbd_support = false, ++ .new_scbd10_def = false, ++ .ble_hid_profile_support = false, ++ .wl_mimo_ps_support = false, ++ .pstdma_type = COEX_PSTDMA_FORCE_LPSOFF, ++ .bt_rssi_type = COEX_BTRSSI_RATIO, ++ .ant_isolation = 10, ++ .rssi_tolerance = 2, ++ .wl_rssi_step = wl_rssi_step_8821a, ++ .bt_rssi_step = bt_rssi_step_8821a, ++ .table_sant_num = ARRAY_SIZE(table_sant_8821a), ++ .table_sant = table_sant_8821a, ++ .table_nsant_num = ARRAY_SIZE(table_nsant_8821a), ++ .table_nsant = table_nsant_8821a, ++ .tdma_sant_num = ARRAY_SIZE(tdma_sant_8821a), ++ .tdma_sant = tdma_sant_8821a, ++ .tdma_nsant_num = ARRAY_SIZE(tdma_nsant_8821a), ++ .tdma_nsant = tdma_nsant_8821a, ++ .wl_rf_para_num = ARRAY_SIZE(rf_para_tx_8821a), ++ .wl_rf_para_tx = rf_para_tx_8821a, ++ .wl_rf_para_rx = rf_para_rx_8821a, ++ .bt_afh_span_bw20 = 0x20, ++ .bt_afh_span_bw40 = 0x30, ++ .afh_5g_num = ARRAY_SIZE(afh_5g_8821a), ++ .afh_5g = afh_5g_8821a, ++ ++ .coex_info_hw_regs_num = ARRAY_SIZE(coex_info_hw_regs_8821a), ++ .coex_info_hw_regs = coex_info_hw_regs_8821a, ++}; ++EXPORT_SYMBOL(rtw8821a_hw_spec); ++ ++MODULE_FIRMWARE("rtw88/rtw8821a_fw.bin"); ++ ++MODULE_AUTHOR("Realtek Corporation"); ++MODULE_DESCRIPTION("Realtek 802.11ac wireless 8821a/8811a driver"); ++MODULE_LICENSE("Dual BSD/GPL"); +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821a.h b/drivers/net/wireless/realtek/rtw88/rtw8821a.h +new file mode 100644 +index 000000000000..1b2e548f7234 +--- /dev/null ++++ b/drivers/net/wireless/realtek/rtw88/rtw8821a.h +@@ -0,0 +1,10 @@ ++/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ ++/* Copyright(c) 2024 Realtek Corporation ++ */ ++ ++#ifndef __RTW8821A_H__ ++#define __RTW8821A_H__ ++ ++extern const struct rtw_chip_info rtw8821a_hw_spec; ++ ++#endif +-- +2.39.5 + diff --git a/packages/linux/patches/rtlwifi/6.13/0022-wifi-rtw88-Add-rtw8812a.-c-h.patch b/packages/linux/patches/rtlwifi/6.13/0022-wifi-rtw88-Add-rtw8812a.-c-h.patch new file mode 100644 index 0000000000..db9f7994bf --- /dev/null +++ b/packages/linux/patches/rtlwifi/6.13/0022-wifi-rtw88-Add-rtw8812a.-c-h.patch @@ -0,0 +1,1144 @@ +From fb1567c60d2a22560353b03ae8a64d2d7c5aa536 Mon Sep 17 00:00:00 2001 +From: Bitterblue Smith +Date: Wed, 30 Oct 2024 20:28:49 +0200 +Subject: [PATCH 22/24] wifi: rtw88: Add rtw8812a.{c,h} + +These contain code specific to RTL8812AU. + +Signed-off-by: Bitterblue Smith +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/a0057683-79eb-4ab2-8f74-11a3bc58adfb@gmail.com +--- + drivers/net/wireless/realtek/rtw88/rtw8812a.c | 1102 +++++++++++++++++ + drivers/net/wireless/realtek/rtw88/rtw8812a.h | 10 + + 2 files changed, 1112 insertions(+) + create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8812a.c + create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8812a.h + +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8812a.c b/drivers/net/wireless/realtek/rtw88/rtw8812a.c +new file mode 100644 +index 000000000000..482edd31823d +--- /dev/null ++++ b/drivers/net/wireless/realtek/rtw88/rtw8812a.c +@@ -0,0 +1,1102 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause ++/* Copyright(c) 2024 Realtek Corporation ++ */ ++ ++#include "main.h" ++#include "coex.h" ++#include "phy.h" ++#include "reg.h" ++#include "rtw88xxa.h" ++#include "rtw8812a.h" ++#include "rtw8812a_table.h" ++#include "tx.h" ++ ++static void rtw8812a_power_off(struct rtw_dev *rtwdev) ++{ ++ rtw88xxa_power_off(rtwdev, enter_lps_flow_8812a); ++} ++ ++static s8 rtw8812a_cck_rx_pwr(u8 lna_idx, u8 vga_idx) ++{ ++ s8 rx_pwr_all = 0; ++ ++ switch (lna_idx) { ++ case 7: ++ if (vga_idx <= 27) ++ rx_pwr_all = -94 + 2 * (27 - vga_idx); ++ else ++ rx_pwr_all = -94; ++ break; ++ case 6: ++ rx_pwr_all = -42 + 2 * (2 - vga_idx); ++ break; ++ case 5: ++ rx_pwr_all = -36 + 2 * (7 - vga_idx); ++ break; ++ case 4: ++ rx_pwr_all = -30 + 2 * (7 - vga_idx); ++ break; ++ case 3: ++ rx_pwr_all = -18 + 2 * (7 - vga_idx); ++ break; ++ case 2: ++ rx_pwr_all = 2 * (5 - vga_idx); ++ break; ++ case 1: ++ rx_pwr_all = 14 - 2 * vga_idx; ++ break; ++ case 0: ++ rx_pwr_all = 20 - 2 * vga_idx; ++ break; ++ default: ++ break; ++ } ++ ++ return rx_pwr_all; ++} ++ ++static void rtw8812a_query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status, ++ struct rtw_rx_pkt_stat *pkt_stat) ++{ ++ rtw88xxa_query_phy_status(rtwdev, phy_status, pkt_stat, ++ rtw8812a_cck_rx_pwr); ++ ++ if (pkt_stat->rate >= DESC_RATE6M) ++ return; ++ ++ if (rtwdev->hal.cck_high_power) ++ return; ++ ++ if (pkt_stat->rssi >= 80) ++ pkt_stat->rssi = ((pkt_stat->rssi - 80) << 1) + ++ ((pkt_stat->rssi - 80) >> 1) + 80; ++ else if (pkt_stat->rssi <= 78 && pkt_stat->rssi >= 20) ++ pkt_stat->rssi += 3; ++} ++ ++static void rtw8812a_cfg_ldo25(struct rtw_dev *rtwdev, bool enable) ++{ ++} ++ ++static void rtw8812a_do_lck(struct rtw_dev *rtwdev) ++{ ++ u32 cont_tx, lc_cal, i; ++ ++ cont_tx = rtw_read32_mask(rtwdev, REG_SINGLE_TONE_CONT_TX, 0x70000); ++ ++ lc_cal = rtw_read_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK); ++ ++ if (!cont_tx) ++ rtw_write8(rtwdev, REG_TXPAUSE, 0xff); ++ ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_LCK, BIT(14), 1); ++ ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, 0x08000, 1); ++ ++ mdelay(150); ++ ++ for (i = 0; i < 5; i++) { ++ if (rtw_read_rf(rtwdev, RF_PATH_A, RF_CFGCH, 0x08000) != 1) ++ break; ++ ++ mdelay(10); ++ } ++ ++ if (i == 5) ++ rtw_dbg(rtwdev, RTW_DBG_RFK, "LCK timed out\n"); ++ ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK, lc_cal); ++ ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_LCK, BIT(14), 0); ++ ++ if (!cont_tx) ++ rtw_write8(rtwdev, REG_TXPAUSE, 0); ++ ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK, lc_cal); ++} ++ ++static void rtw8812a_iqk_backup_rf(struct rtw_dev *rtwdev, u32 *rfa_backup, ++ u32 *rfb_backup, const u32 *backup_rf_reg, ++ u32 rf_num) ++{ ++ u32 i; ++ ++ /* [31] = 0 --> Page C */ ++ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0); ++ ++ /* Save RF Parameters */ ++ for (i = 0; i < rf_num; i++) { ++ rfa_backup[i] = rtw_read_rf(rtwdev, RF_PATH_A, ++ backup_rf_reg[i], MASKDWORD); ++ rfb_backup[i] = rtw_read_rf(rtwdev, RF_PATH_B, ++ backup_rf_reg[i], MASKDWORD); ++ } ++} ++ ++static void rtw8812a_iqk_restore_rf(struct rtw_dev *rtwdev, ++ enum rtw_rf_path path, ++ const u32 *backup_rf_reg, ++ u32 *RF_backup, u32 rf_reg_num) ++{ ++ u32 i; ++ ++ /* [31] = 0 --> Page C */ ++ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0); ++ ++ for (i = 0; i < rf_reg_num; i++) ++ rtw_write_rf(rtwdev, path, backup_rf_reg[i], ++ RFREG_MASK, RF_backup[i]); ++ ++ rtw_write_rf(rtwdev, path, RF_LUTWE, RFREG_MASK, 0); ++} ++ ++static void rtw8812a_iqk_restore_afe(struct rtw_dev *rtwdev, u32 *afe_backup, ++ const u32 *backup_afe_reg, u32 afe_num) ++{ ++ u32 i; ++ ++ /* [31] = 0 --> Page C */ ++ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0); ++ ++ /* Reload AFE Parameters */ ++ for (i = 0; i < afe_num; i++) ++ rtw_write32(rtwdev, backup_afe_reg[i], afe_backup[i]); ++ ++ /* [31] = 1 --> Page C1 */ ++ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1); ++ ++ rtw_write32(rtwdev, REG_OFDM0_XA_TX_IQ_IMBALANCE, 0x0); ++ rtw_write32(rtwdev, REG_OFDM0_A_TX_AFE, 0x0); ++ rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE, 0x0); ++ rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x3c000000); ++ rtw_write32_mask(rtwdev, REG_LSSI_WRITE_A, BIT(7), 1); ++ rtw_write32_mask(rtwdev, REG_IQK_DPD_CFG, BIT(18), 1); ++ rtw_write32_mask(rtwdev, REG_IQK_DPD_CFG, BIT(29), 1); ++ rtw_write32_mask(rtwdev, REG_CFG_PMPD, BIT(29), 1); ++ ++ rtw_write32(rtwdev, REG_TXTONEB, 0x0); ++ rtw_write32(rtwdev, REG_RXTONEB, 0x0); ++ rtw_write32(rtwdev, REG_TXPITMB, 0x0); ++ rtw_write32(rtwdev, REG_RXPITMB, 0x3c000000); ++ rtw_write32_mask(rtwdev, REG_LSSI_WRITE_B, BIT(7), 1); ++ rtw_write32_mask(rtwdev, REG_BPBDB, BIT(18), 1); ++ rtw_write32_mask(rtwdev, REG_BPBDB, BIT(29), 1); ++ rtw_write32_mask(rtwdev, REG_PHYTXONB, BIT(29), 1); ++} ++ ++static void rtw8812a_iqk_rx_fill(struct rtw_dev *rtwdev, enum rtw_rf_path path, ++ unsigned int rx_x, unsigned int rx_y) ++{ ++ switch (path) { ++ case RF_PATH_A: ++ /* [31] = 0 --> Page C */ ++ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0); ++ if (rx_x >> 1 >= 0x112 || ++ (rx_y >> 1 >= 0x12 && rx_y >> 1 <= 0x3ee)) { ++ rtw_write32_mask(rtwdev, REG_RX_IQC_AB_A, ++ 0x000003ff, 0x100); ++ rtw_write32_mask(rtwdev, REG_RX_IQC_AB_A, ++ 0x03ff0000, 0); ++ } else { ++ rtw_write32_mask(rtwdev, REG_RX_IQC_AB_A, ++ 0x000003ff, rx_x >> 1); ++ rtw_write32_mask(rtwdev, REG_RX_IQC_AB_A, ++ 0x03ff0000, rx_y >> 1); ++ } ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "rx_x = %x;;rx_y = %x ====>fill to IQC\n", ++ rx_x >> 1 & 0x000003ff, rx_y >> 1 & 0x000003ff); ++ rtw_dbg(rtwdev, RTW_DBG_RFK, "0xc10 = %x ====>fill to IQC\n", ++ rtw_read32(rtwdev, REG_RX_IQC_AB_A)); ++ break; ++ case RF_PATH_B: ++ /* [31] = 0 --> Page C */ ++ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0); ++ if (rx_x >> 1 >= 0x112 || ++ (rx_y >> 1 >= 0x12 && rx_y >> 1 <= 0x3ee)) { ++ rtw_write32_mask(rtwdev, REG_RX_IQC_AB_B, ++ 0x000003ff, 0x100); ++ rtw_write32_mask(rtwdev, REG_RX_IQC_AB_B, ++ 0x03ff0000, 0); ++ } else { ++ rtw_write32_mask(rtwdev, REG_RX_IQC_AB_B, ++ 0x000003ff, rx_x >> 1); ++ rtw_write32_mask(rtwdev, REG_RX_IQC_AB_B, ++ 0x03ff0000, rx_y >> 1); ++ } ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "rx_x = %x;;rx_y = %x ====>fill to IQC\n", ++ rx_x >> 1 & 0x000003ff, rx_y >> 1 & 0x000003ff); ++ rtw_dbg(rtwdev, RTW_DBG_RFK, "0xe10 = %x====>fill to IQC\n", ++ rtw_read32(rtwdev, REG_RX_IQC_AB_B)); ++ break; ++ default: ++ break; ++ } ++} ++ ++static void rtw8812a_iqk_tx_fill(struct rtw_dev *rtwdev, enum rtw_rf_path path, ++ unsigned int tx_x, unsigned int tx_y) ++{ ++ switch (path) { ++ case RF_PATH_A: ++ /* [31] = 1 --> Page C1 */ ++ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1); ++ rtw_write32_mask(rtwdev, REG_PREDISTA, BIT(7), 0x1); ++ rtw_write32_mask(rtwdev, REG_IQK_DPD_CFG, BIT(18), 0x1); ++ rtw_write32_mask(rtwdev, REG_IQK_DPD_CFG, BIT(29), 0x1); ++ rtw_write32_mask(rtwdev, REG_CFG_PMPD, BIT(29), 0x1); ++ rtw_write32_mask(rtwdev, REG_IQC_Y, 0x000007ff, tx_y); ++ rtw_write32_mask(rtwdev, REG_IQC_X, 0x000007ff, tx_x); ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "tx_x = %x;;tx_y = %x =====> fill to IQC\n", ++ tx_x & 0x000007ff, tx_y & 0x000007ff); ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "0xcd4 = %x;;0xccc = %x ====>fill to IQC\n", ++ rtw_read32_mask(rtwdev, REG_IQC_X, 0x000007ff), ++ rtw_read32_mask(rtwdev, REG_IQC_Y, 0x000007ff)); ++ break; ++ case RF_PATH_B: ++ /* [31] = 1 --> Page C1 */ ++ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1); ++ rtw_write32_mask(rtwdev, REG_PREDISTB, BIT(7), 0x1); ++ rtw_write32_mask(rtwdev, REG_BPBDB, BIT(18), 0x1); ++ rtw_write32_mask(rtwdev, REG_BPBDB, BIT(29), 0x1); ++ rtw_write32_mask(rtwdev, REG_PHYTXONB, BIT(29), 0x1); ++ rtw_write32_mask(rtwdev, REG_IQKYB, 0x000007ff, tx_y); ++ rtw_write32_mask(rtwdev, REG_IQKXB, 0x000007ff, tx_x); ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "tx_x = %x;;tx_y = %x =====> fill to IQC\n", ++ tx_x & 0x000007ff, tx_y & 0x000007ff); ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "0xed4 = %x;;0xecc = %x ====>fill to IQC\n", ++ rtw_read32_mask(rtwdev, REG_IQKXB, 0x000007ff), ++ rtw_read32_mask(rtwdev, REG_IQKYB, 0x000007ff)); ++ break; ++ default: ++ break; ++ } ++} ++ ++static void rtw8812a_iqk(struct rtw_dev *rtwdev) ++{ ++ int tx_x0_temp[10], tx_y0_temp[10], tx_x1_temp[10], tx_y1_temp[10]; ++ int rx_x0_temp[10], rx_y0_temp[10], rx_x1_temp[10], rx_y1_temp[10]; ++ bool iqk0_ready = false, tx0_finish = false, rx0_finish = false; ++ bool iqk1_ready = false, tx1_finish = false, rx1_finish = false; ++ u8 tx0_avg = 0, tx1_avg = 0, rx0_avg = 0, rx1_avg = 0; ++ int tx_x0 = 0, tx_y0 = 0, tx_x1 = 0, tx_y1 = 0; ++ int rx_x0 = 0, rx_y0 = 0, rx_x1 = 0, rx_y1 = 0; ++ struct rtw_efuse *efuse = &rtwdev->efuse; ++ bool tx0_fail = true, rx0_fail = true; ++ bool tx1_fail = true, rx1_fail = true; ++ u8 cal0_retry, cal1_retry; ++ u8 delay_count; ++ ++ /* [31] = 0 --> Page C */ ++ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0); ++ ++ /* ========path-A AFE all on======== */ ++ /* Port 0 DAC/ADC on */ ++ rtw_write32(rtwdev, REG_AFE_PWR1_A, 0x77777777); ++ rtw_write32(rtwdev, REG_AFE_PWR2_A, 0x77777777); ++ ++ /* Port 1 DAC/ADC on */ ++ rtw_write32(rtwdev, REG_AFE_PWR1_B, 0x77777777); ++ rtw_write32(rtwdev, REG_AFE_PWR2_B, 0x77777777); ++ ++ rtw_write32(rtwdev, REG_RX_WAIT_CCA_TX_CCK_RFON_A, 0x19791979); ++ rtw_write32(rtwdev, REG_RX_WAIT_CCA_TX_CCK_RFON_B, 0x19791979); ++ ++ /* hardware 3-wire off */ ++ rtw_write32_mask(rtwdev, REG_3WIRE_SWA, 0xf, 0x4); ++ rtw_write32_mask(rtwdev, REG_3WIRE_SWB, 0xf, 0x4); ++ ++ /* DAC/ADC sampling rate (160 MHz) */ ++ rtw_write32_mask(rtwdev, REG_CK_MONHA, GENMASK(26, 24), 0x7); ++ rtw_write32_mask(rtwdev, REG_CK_MONHB, GENMASK(26, 24), 0x7); ++ ++ /* [31] = 0 --> Page C */ ++ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0); ++ /* ====== path A TX IQK RF setting ====== */ ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE, RFREG_MASK, 0x80002); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_ADDR, RFREG_MASK, 0x20000); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_DATA0, RFREG_MASK, 0x3fffd); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_DATA1, RFREG_MASK, 0xfe83f); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_TXA_PREPAD, RFREG_MASK, 0x931d5); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_RXBB2, RFREG_MASK, 0x8a001); ++ ++ /* ====== path B TX IQK RF setting ====== */ ++ rtw_write_rf(rtwdev, RF_PATH_B, RF_LUTWE, RFREG_MASK, 0x80002); ++ rtw_write_rf(rtwdev, RF_PATH_B, RF_MODE_TABLE_ADDR, RFREG_MASK, 0x20000); ++ rtw_write_rf(rtwdev, RF_PATH_B, RF_MODE_TABLE_DATA0, RFREG_MASK, 0x3fffd); ++ rtw_write_rf(rtwdev, RF_PATH_B, RF_MODE_TABLE_DATA1, RFREG_MASK, 0xfe83f); ++ rtw_write_rf(rtwdev, RF_PATH_B, RF_TXA_PREPAD, RFREG_MASK, 0x931d5); ++ rtw_write_rf(rtwdev, RF_PATH_B, RF_RXBB2, RFREG_MASK, 0x8a001); ++ ++ rtw_write32(rtwdev, REG_DAC_RSTB, 0x00008000); ++ rtw_write32_mask(rtwdev, REG_TXAGCIDX, BIT(0), 0x1); ++ rtw_write32_mask(rtwdev, REG_INIDLYB, BIT(0), 0x1); ++ rtw_write32(rtwdev, REG_IQK_COM00, 0x29002000); /* TX (X,Y) */ ++ rtw_write32(rtwdev, REG_IQK_COM32, 0xa9002000); /* RX (X,Y) */ ++ rtw_write32(rtwdev, REG_IQK_COM96, 0x00462910); /* [0]:AGC_en, [15]:idac_K_Mask */ ++ /* [31] = 1 --> Page C1 */ ++ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1); ++ ++ if (efuse->ext_pa_5g) { ++ if (efuse->rfe_option == 1) { ++ rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE, 0x821403e3); ++ rtw_write32(rtwdev, REG_TXPITMB, 0x821403e3); ++ } else { ++ rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE, 0x821403f7); ++ rtw_write32(rtwdev, REG_TXPITMB, 0x821403f7); ++ } ++ } else { ++ rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE, 0x821403f1); ++ rtw_write32(rtwdev, REG_TXPITMB, 0x821403f1); ++ } ++ ++ if (rtwdev->hal.current_band_type == RTW_BAND_5G) { ++ rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x68163e96); ++ rtw_write32(rtwdev, REG_RXPITMB, 0x68163e96); ++ } else { ++ rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x28163e96); ++ rtw_write32(rtwdev, REG_RXPITMB, 0x28163e96); ++ ++ if (efuse->rfe_option == 3) { ++ if (efuse->ext_pa_2g) ++ rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE, ++ 0x821403e3); ++ else ++ rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE, ++ 0x821403f7); ++ } ++ } ++ ++ /* TX_Tone_idx[9:0], TxK_Mask[29] TX_Tone = 16 */ ++ rtw_write32(rtwdev, REG_OFDM0_XA_TX_IQ_IMBALANCE, 0x18008c10); ++ /* RX_Tone_idx[9:0], RxK_Mask[29] */ ++ rtw_write32(rtwdev, REG_OFDM0_A_TX_AFE, 0x38008c10); ++ rtw_write32(rtwdev, REG_INTPO_SETA, 0x00000000); ++ /* TX_Tone_idx[9:0], TxK_Mask[29] TX_Tone = 16 */ ++ rtw_write32(rtwdev, REG_TXTONEB, 0x18008c10); ++ /* RX_Tone_idx[9:0], RxK_Mask[29] */ ++ rtw_write32(rtwdev, REG_RXTONEB, 0x38008c10); ++ rtw_write32(rtwdev, REG_INTPO_SETB, 0x00000000); ++ ++ cal0_retry = 0; ++ cal1_retry = 0; ++ while (1) { ++ /* one shot */ ++ rtw_write32(rtwdev, REG_RFECTL_A, 0x00100000); ++ rtw_write32(rtwdev, REG_RFECTL_B, 0x00100000); ++ rtw_write32(rtwdev, REG_IQK_COM64, 0xfa000000); ++ rtw_write32(rtwdev, REG_IQK_COM64, 0xf8000000); ++ ++ mdelay(10); ++ ++ rtw_write32(rtwdev, REG_RFECTL_A, 0x00000000); ++ rtw_write32(rtwdev, REG_RFECTL_B, 0x00000000); ++ ++ for (delay_count = 0; delay_count < 20; delay_count++) { ++ if (!tx0_finish) ++ iqk0_ready = rtw_read32_mask(rtwdev, ++ REG_IQKA_END, ++ BIT(10)); ++ if (!tx1_finish) ++ iqk1_ready = rtw_read32_mask(rtwdev, ++ REG_IQKB_END, ++ BIT(10)); ++ if (iqk0_ready && iqk1_ready) ++ break; ++ ++ mdelay(1); ++ } ++ ++ rtw_dbg(rtwdev, RTW_DBG_RFK, "TX delay_count = %d\n", ++ delay_count); ++ ++ if (delay_count < 20) { /* If 20ms No Result, then cal_retry++ */ ++ /* ============TXIQK Check============== */ ++ tx0_fail = rtw_read32_mask(rtwdev, REG_IQKA_END, BIT(12)); ++ tx1_fail = rtw_read32_mask(rtwdev, REG_IQKB_END, BIT(12)); ++ ++ if (!(tx0_fail || tx0_finish)) { ++ rtw_write32(rtwdev, REG_RFECTL_A, 0x02000000); ++ tx_x0_temp[tx0_avg] = rtw_read32_mask(rtwdev, ++ REG_IQKA_END, ++ 0x07ff0000); ++ rtw_write32(rtwdev, REG_RFECTL_A, 0x04000000); ++ tx_y0_temp[tx0_avg] = rtw_read32_mask(rtwdev, ++ REG_IQKA_END, ++ 0x07ff0000); ++ ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "tx_x0[%d] = %x ;; tx_y0[%d] = %x\n", ++ tx0_avg, tx_x0_temp[tx0_avg], ++ tx0_avg, tx_y0_temp[tx0_avg]); ++ ++ tx_x0_temp[tx0_avg] <<= 21; ++ tx_y0_temp[tx0_avg] <<= 21; ++ ++ tx0_avg++; ++ } else { ++ cal0_retry++; ++ if (cal0_retry == 10) ++ break; ++ } ++ ++ if (!(tx1_fail || tx1_finish)) { ++ rtw_write32(rtwdev, REG_RFECTL_B, 0x02000000); ++ tx_x1_temp[tx1_avg] = rtw_read32_mask(rtwdev, ++ REG_IQKB_END, ++ 0x07ff0000); ++ rtw_write32(rtwdev, REG_RFECTL_B, 0x04000000); ++ tx_y1_temp[tx1_avg] = rtw_read32_mask(rtwdev, ++ REG_IQKB_END, ++ 0x07ff0000); ++ ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "tx_x1[%d] = %x ;; tx_y1[%d] = %x\n", ++ tx1_avg, tx_x1_temp[tx1_avg], ++ tx1_avg, tx_y1_temp[tx1_avg]); ++ ++ tx_x1_temp[tx1_avg] <<= 21; ++ tx_y1_temp[tx1_avg] <<= 21; ++ ++ tx1_avg++; ++ } else { ++ cal1_retry++; ++ if (cal1_retry == 10) ++ break; ++ } ++ } else { ++ cal0_retry++; ++ cal1_retry++; ++ ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "delay 20ms TX IQK Not Ready!!!!!\n"); ++ ++ if (cal0_retry == 10) ++ break; ++ } ++ ++ if (tx0_avg >= 2) ++ tx0_finish = rtw88xxa_iqk_finish(tx0_avg, 4, ++ tx_x0_temp, tx_y0_temp, &tx_x0, &tx_y0, ++ false, false); ++ ++ if (tx1_avg >= 2) ++ tx1_finish = rtw88xxa_iqk_finish(tx1_avg, 4, ++ tx_x1_temp, tx_y1_temp, &tx_x1, &tx_y1, ++ false, false); ++ ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "tx0_average = %d, tx1_average = %d\n", ++ tx0_avg, tx1_avg); ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "tx0_finish = %d, tx1_finish = %d\n", ++ tx0_finish, tx1_finish); ++ ++ if (tx0_finish && tx1_finish) ++ break; ++ ++ if ((cal0_retry + tx0_avg) >= 10 || ++ (cal1_retry + tx1_avg) >= 10) ++ break; ++ } ++ ++ rtw_dbg(rtwdev, RTW_DBG_RFK, "TXA_cal_retry = %d\n", cal0_retry); ++ rtw_dbg(rtwdev, RTW_DBG_RFK, "TXB_cal_retry = %d\n", cal1_retry); ++ ++ /* [31] = 0 --> Page C */ ++ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0); ++ /* Load LOK */ ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_TXMOD, 0x7fe00, ++ rtw_read_rf(rtwdev, RF_PATH_A, RF_DTXLOK, 0xffc00)); ++ rtw_write_rf(rtwdev, RF_PATH_B, RF_TXMOD, 0x7fe00, ++ rtw_read_rf(rtwdev, RF_PATH_B, RF_DTXLOK, 0xffc00)); ++ /* [31] = 1 --> Page C1 */ ++ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1); ++ ++ /* [31] = 0 --> Page C */ ++ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0); ++ if (tx0_finish) { ++ /* ====== path A RX IQK RF setting====== */ ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE, RFREG_MASK, 0x80000); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_ADDR, RFREG_MASK, ++ 0x30000); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_DATA0, RFREG_MASK, ++ 0x3f7ff); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_DATA1, RFREG_MASK, ++ 0xfe7bf); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_RXBB2, RFREG_MASK, 0x88001); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_TXA_PREPAD, RFREG_MASK, 0x931d1); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE, RFREG_MASK, 0x00000); ++ } ++ if (tx1_finish) { ++ /* ====== path B RX IQK RF setting====== */ ++ rtw_write_rf(rtwdev, RF_PATH_B, RF_LUTWE, RFREG_MASK, 0x80000); ++ rtw_write_rf(rtwdev, RF_PATH_B, RF_MODE_TABLE_ADDR, RFREG_MASK, ++ 0x30000); ++ rtw_write_rf(rtwdev, RF_PATH_B, RF_MODE_TABLE_DATA0, RFREG_MASK, ++ 0x3f7ff); ++ rtw_write_rf(rtwdev, RF_PATH_B, RF_MODE_TABLE_DATA1, RFREG_MASK, ++ 0xfe7bf); ++ rtw_write_rf(rtwdev, RF_PATH_B, RF_RXBB2, RFREG_MASK, 0x88001); ++ rtw_write_rf(rtwdev, RF_PATH_B, RF_TXA_PREPAD, RFREG_MASK, 0x931d1); ++ rtw_write_rf(rtwdev, RF_PATH_B, RF_LUTWE, RFREG_MASK, 0x00000); ++ } ++ ++ rtw_write32_mask(rtwdev, REG_IQK_COM00, BIT(31), 0x1); ++ rtw_write32_mask(rtwdev, REG_IQK_COM00, BIT(31), 0x0); ++ rtw_write32(rtwdev, REG_DAC_RSTB, 0x00008000); ++ ++ if (rtwdev->hci.type == RTW_HCI_TYPE_PCIE) ++ rtw_write32(rtwdev, REG_IQK_COM96, 0x0046a911); ++ else ++ rtw_write32(rtwdev, REG_IQK_COM96, 0x0046a890); ++ ++ if (efuse->rfe_option == 1) { ++ rtw_write32(rtwdev, REG_RFE_PINMUX_A, 0x77777717); ++ rtw_write32(rtwdev, REG_RFE_INV_A, 0x00000077); ++ rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x77777717); ++ rtw_write32(rtwdev, REG_RFE_INV_B, 0x00000077); ++ } else { ++ rtw_write32(rtwdev, REG_RFE_PINMUX_A, 0x77777717); ++ rtw_write32(rtwdev, REG_RFE_INV_A, 0x02000077); ++ rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x77777717); ++ rtw_write32(rtwdev, REG_RFE_INV_B, 0x02000077); ++ } ++ ++ /* [31] = 1 --> Page C1 */ ++ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1); ++ ++ if (tx0_finish) { ++ /* TX_Tone_idx[9:0], TxK_Mask[29] TX_Tone = 16 */ ++ rtw_write32(rtwdev, REG_OFDM0_XA_TX_IQ_IMBALANCE, 0x38008c10); ++ /* RX_Tone_idx[9:0], RxK_Mask[29] */ ++ rtw_write32(rtwdev, REG_OFDM0_A_TX_AFE, 0x18008c10); ++ rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE, 0x82140119); ++ } ++ if (tx1_finish) { ++ /* TX_Tone_idx[9:0], TxK_Mask[29] TX_Tone = 16 */ ++ rtw_write32(rtwdev, REG_TXTONEB, 0x38008c10); ++ /* RX_Tone_idx[9:0], RxK_Mask[29] */ ++ rtw_write32(rtwdev, REG_RXTONEB, 0x18008c10); ++ rtw_write32(rtwdev, REG_TXPITMB, 0x82140119); ++ } ++ ++ cal0_retry = 0; ++ cal1_retry = 0; ++ while (1) { ++ /* one shot */ ++ /* [31] = 0 --> Page C */ ++ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0); ++ ++ if (tx0_finish) { ++ rtw_write32_mask(rtwdev, REG_IQK_COM00, 0x03FF8000, ++ tx_x0 & 0x000007ff); ++ rtw_write32_mask(rtwdev, REG_IQK_COM00, 0x000007FF, ++ tx_y0 & 0x000007ff); ++ /* [31] = 1 --> Page C1 */ ++ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1); ++ if (efuse->rfe_option == 1) ++ rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x28161500); ++ else ++ rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x28160cc0); ++ rtw_write32(rtwdev, REG_RFECTL_A, 0x00300000); ++ rtw_write32(rtwdev, REG_RFECTL_A, 0x00100000); ++ mdelay(5); ++ rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x3c000000); ++ rtw_write32(rtwdev, REG_RFECTL_A, 0x00000000); ++ } ++ ++ if (tx1_finish) { ++ /* [31] = 0 --> Page C */ ++ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0); ++ rtw_write32_mask(rtwdev, REG_IQK_COM00, 0x03FF8000, ++ tx_x1 & 0x000007ff); ++ rtw_write32_mask(rtwdev, REG_IQK_COM00, 0x000007FF, ++ tx_y1 & 0x000007ff); ++ /* [31] = 1 --> Page C1 */ ++ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1); ++ if (efuse->rfe_option == 1) ++ rtw_write32(rtwdev, REG_RXPITMB, 0x28161500); ++ else ++ rtw_write32(rtwdev, REG_RXPITMB, 0x28160ca0); ++ rtw_write32(rtwdev, REG_RFECTL_B, 0x00300000); ++ rtw_write32(rtwdev, REG_RFECTL_B, 0x00100000); ++ mdelay(5); ++ rtw_write32(rtwdev, REG_RXPITMB, 0x3c000000); ++ rtw_write32(rtwdev, REG_RFECTL_B, 0x00000000); ++ } ++ ++ for (delay_count = 0; delay_count < 20; delay_count++) { ++ if (!rx0_finish && tx0_finish) ++ iqk0_ready = rtw_read32_mask(rtwdev, ++ REG_IQKA_END, ++ BIT(10)); ++ if (!rx1_finish && tx1_finish) ++ iqk1_ready = rtw_read32_mask(rtwdev, ++ REG_IQKB_END, ++ BIT(10)); ++ if (iqk0_ready && iqk1_ready) ++ break; ++ ++ mdelay(1); ++ } ++ ++ rtw_dbg(rtwdev, RTW_DBG_RFK, "RX delay_count = %d\n", ++ delay_count); ++ ++ if (delay_count < 20) { /* If 20ms No Result, then cal_retry++ */ ++ /* ============RXIQK Check============== */ ++ rx0_fail = rtw_read32_mask(rtwdev, REG_IQKA_END, BIT(11)); ++ rx1_fail = rtw_read32_mask(rtwdev, REG_IQKB_END, BIT(11)); ++ ++ if (!(rx0_fail || rx0_finish) && tx0_finish) { ++ rtw_write32(rtwdev, REG_RFECTL_A, 0x06000000); ++ rx_x0_temp[rx0_avg] = rtw_read32_mask(rtwdev, ++ REG_IQKA_END, ++ 0x07ff0000); ++ rtw_write32(rtwdev, REG_RFECTL_A, 0x08000000); ++ rx_y0_temp[rx0_avg] = rtw_read32_mask(rtwdev, ++ REG_IQKA_END, ++ 0x07ff0000); ++ ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "rx_x0[%d] = %x ;; rx_y0[%d] = %x\n", ++ rx0_avg, rx_x0_temp[rx0_avg], ++ rx0_avg, rx_y0_temp[rx0_avg]); ++ ++ rx_x0_temp[rx0_avg] <<= 21; ++ rx_y0_temp[rx0_avg] <<= 21; ++ ++ rx0_avg++; ++ } else { ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "1. RXA_cal_retry = %d\n", cal0_retry); ++ ++ cal0_retry++; ++ if (cal0_retry == 10) ++ break; ++ } ++ ++ if (!(rx1_fail || rx1_finish) && tx1_finish) { ++ rtw_write32(rtwdev, REG_RFECTL_B, 0x06000000); ++ rx_x1_temp[rx1_avg] = rtw_read32_mask(rtwdev, ++ REG_IQKB_END, ++ 0x07ff0000); ++ rtw_write32(rtwdev, REG_RFECTL_B, 0x08000000); ++ rx_y1_temp[rx1_avg] = rtw_read32_mask(rtwdev, ++ REG_IQKB_END, ++ 0x07ff0000); ++ ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "rx_x1[%d] = %x ;; rx_y1[%d] = %x\n", ++ rx1_avg, rx_x1_temp[rx1_avg], ++ rx1_avg, rx_y1_temp[rx1_avg]); ++ ++ rx_x1_temp[rx1_avg] <<= 21; ++ rx_y1_temp[rx1_avg] <<= 21; ++ ++ rx1_avg++; ++ } else { ++ cal1_retry++; ++ if (cal1_retry == 10) ++ break; ++ } ++ } else { ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "2. RXA_cal_retry = %d\n", cal0_retry); ++ ++ cal0_retry++; ++ cal1_retry++; ++ ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "delay 20ms RX IQK Not Ready!!!!!\n"); ++ ++ if (cal0_retry == 10) ++ break; ++ } ++ ++ rtw_dbg(rtwdev, RTW_DBG_RFK, "3. RXA_cal_retry = %d\n", ++ cal0_retry); ++ ++ if (rx0_avg >= 2) ++ rx0_finish = rtw88xxa_iqk_finish(rx0_avg, 4, ++ rx_x0_temp, rx_y0_temp, ++ &rx_x0, &rx_y0, ++ true, false); ++ ++ if (rx1_avg >= 2) ++ rx1_finish = rtw88xxa_iqk_finish(rx1_avg, 4, ++ rx_x1_temp, rx_y1_temp, ++ &rx_x1, &rx_y1, ++ true, false); ++ ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "rx0_average = %d, rx1_average = %d\n", ++ rx0_avg, rx1_avg); ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "rx0_finish = %d, rx1_finish = %d\n", ++ rx0_finish, rx1_finish); ++ ++ if ((rx0_finish || !tx0_finish) && (rx1_finish || !tx1_finish)) ++ break; ++ ++ if ((cal0_retry + rx0_avg) >= 10 || ++ (cal1_retry + rx1_avg) >= 10 || ++ rx0_avg == 3 || rx1_avg == 3) ++ break; ++ } ++ ++ rtw_dbg(rtwdev, RTW_DBG_RFK, "RXA_cal_retry = %d\n", cal0_retry); ++ rtw_dbg(rtwdev, RTW_DBG_RFK, "RXB_cal_retry = %d\n", cal1_retry); ++ ++ /* FillIQK Result */ ++ rtw_dbg(rtwdev, RTW_DBG_RFK, "========Path_A =======\n"); ++ ++ if (tx0_finish) ++ rtw8812a_iqk_tx_fill(rtwdev, RF_PATH_A, tx_x0, tx_y0); ++ else ++ rtw8812a_iqk_tx_fill(rtwdev, RF_PATH_A, 0x200, 0x0); ++ ++ if (rx0_finish) ++ rtw8812a_iqk_rx_fill(rtwdev, RF_PATH_A, rx_x0, rx_y0); ++ else ++ rtw8812a_iqk_rx_fill(rtwdev, RF_PATH_A, 0x200, 0x0); ++ ++ rtw_dbg(rtwdev, RTW_DBG_RFK, "========Path_B =======\n"); ++ ++ if (tx1_finish) ++ rtw8812a_iqk_tx_fill(rtwdev, RF_PATH_B, tx_x1, tx_y1); ++ else ++ rtw8812a_iqk_tx_fill(rtwdev, RF_PATH_B, 0x200, 0x0); ++ ++ if (rx1_finish) ++ rtw8812a_iqk_rx_fill(rtwdev, RF_PATH_B, rx_x1, rx_y1); ++ else ++ rtw8812a_iqk_rx_fill(rtwdev, RF_PATH_B, 0x200, 0x0); ++} ++ ++#define MACBB_REG_NUM_8812A 9 ++#define AFE_REG_NUM_8812A 12 ++#define RF_REG_NUM_8812A 3 ++ ++static void rtw8812a_do_iqk(struct rtw_dev *rtwdev) ++{ ++ static const u32 backup_macbb_reg[MACBB_REG_NUM_8812A] = { ++ 0x520, 0x550, 0x808, 0xa04, 0x90c, 0xc00, 0xe00, 0x838, 0x82c ++ }; ++ static const u32 backup_afe_reg[AFE_REG_NUM_8812A] = { ++ 0xc5c, 0xc60, 0xc64, 0xc68, 0xcb0, 0xcb4, ++ 0xe5c, 0xe60, 0xe64, 0xe68, 0xeb0, 0xeb4 ++ }; ++ static const u32 backup_rf_reg[RF_REG_NUM_8812A] = { ++ 0x65, 0x8f, 0x0 ++ }; ++ u32 macbb_backup[MACBB_REG_NUM_8812A] = {}; ++ u32 afe_backup[AFE_REG_NUM_8812A] = {}; ++ u32 rfa_backup[RF_REG_NUM_8812A] = {}; ++ u32 rfb_backup[RF_REG_NUM_8812A] = {}; ++ u32 reg_cb8, reg_eb8; ++ ++ rtw88xxa_iqk_backup_mac_bb(rtwdev, macbb_backup, ++ backup_macbb_reg, MACBB_REG_NUM_8812A); ++ ++ rtw_write32_set(rtwdev, REG_CCASEL, BIT(31)); ++ reg_cb8 = rtw_read32(rtwdev, REG_RFECTL_A); ++ reg_eb8 = rtw_read32(rtwdev, REG_RFECTL_B); ++ rtw_write32_clr(rtwdev, REG_CCASEL, BIT(31)); ++ ++ rtw88xxa_iqk_backup_afe(rtwdev, afe_backup, ++ backup_afe_reg, AFE_REG_NUM_8812A); ++ rtw8812a_iqk_backup_rf(rtwdev, rfa_backup, rfb_backup, ++ backup_rf_reg, RF_REG_NUM_8812A); ++ ++ rtw88xxa_iqk_configure_mac(rtwdev); ++ ++ rtw8812a_iqk(rtwdev); ++ ++ rtw8812a_iqk_restore_rf(rtwdev, RF_PATH_A, backup_rf_reg, ++ rfa_backup, RF_REG_NUM_8812A); ++ rtw8812a_iqk_restore_rf(rtwdev, RF_PATH_B, backup_rf_reg, ++ rfb_backup, RF_REG_NUM_8812A); ++ ++ rtw8812a_iqk_restore_afe(rtwdev, afe_backup, ++ backup_afe_reg, AFE_REG_NUM_8812A); ++ ++ rtw_write32_set(rtwdev, REG_CCASEL, BIT(31)); ++ rtw_write32(rtwdev, REG_RFECTL_A, reg_cb8); ++ rtw_write32(rtwdev, REG_RFECTL_B, reg_eb8); ++ rtw_write32_clr(rtwdev, REG_CCASEL, BIT(31)); ++ ++ rtw88xxa_iqk_restore_mac_bb(rtwdev, macbb_backup, ++ backup_macbb_reg, MACBB_REG_NUM_8812A); ++} ++ ++static void rtw8812a_phy_calibration(struct rtw_dev *rtwdev) ++{ ++ u8 channel = rtwdev->hal.current_channel; ++ ++ rtw8812a_do_iqk(rtwdev); ++ ++ /* The official driver wants to do this after connecting ++ * but before first writing a new igi (phydm_get_new_igi). ++ * Here seems close enough. ++ */ ++ if (channel >= 36 && channel <= 64) ++ rtw_load_table(rtwdev, &rtw8812a_agc_diff_lb_tbl); ++ else if (channel >= 100) ++ rtw_load_table(rtwdev, &rtw8812a_agc_diff_hb_tbl); ++} ++ ++static void rtw8812a_pwr_track(struct rtw_dev *rtwdev) ++{ ++ struct rtw_dm_info *dm_info = &rtwdev->dm_info; ++ ++ if (!dm_info->pwr_trk_triggered) { ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_T_METER, ++ GENMASK(17, 16), 0x03); ++ dm_info->pwr_trk_triggered = true; ++ return; ++ } ++ ++ rtw88xxa_phy_pwrtrack(rtwdev, rtw8812a_do_lck, rtw8812a_do_iqk); ++ dm_info->pwr_trk_triggered = false; ++} ++ ++static void rtw8812a_fill_txdesc_checksum(struct rtw_dev *rtwdev, ++ struct rtw_tx_pkt_info *pkt_info, ++ u8 *txdesc) ++{ ++ fill_txdesc_checksum_common(txdesc, 16); ++} ++ ++static void rtw8812a_coex_cfg_init(struct rtw_dev *rtwdev) ++{ ++} ++ ++static void rtw8812a_coex_cfg_gnt_fix(struct rtw_dev *rtwdev) ++{ ++} ++ ++static void rtw8821a_coex_cfg_rfe_type(struct rtw_dev *rtwdev) ++{ ++} ++ ++static void rtw8821a_coex_cfg_wl_tx_power(struct rtw_dev *rtwdev, u8 wl_pwr) ++{ ++} ++ ++static void rtw8821a_coex_cfg_wl_rx_gain(struct rtw_dev *rtwdev, bool low_gain) ++{ ++} ++ ++static const struct rtw_chip_ops rtw8812a_ops = { ++ .power_on = rtw88xxa_power_on, ++ .power_off = rtw8812a_power_off, ++ .phy_set_param = NULL, ++ .read_efuse = rtw88xxa_read_efuse, ++ .query_phy_status = rtw8812a_query_phy_status, ++ .set_channel = rtw88xxa_set_channel, ++ .mac_init = NULL, ++ .read_rf = rtw88xxa_phy_read_rf, ++ .write_rf = rtw_phy_write_rf_reg_sipi, ++ .set_antenna = NULL, ++ .set_tx_power_index = rtw88xxa_set_tx_power_index, ++ .cfg_ldo25 = rtw8812a_cfg_ldo25, ++ .efuse_grant = rtw88xxa_efuse_grant, ++ .false_alarm_statistics = rtw88xxa_false_alarm_statistics, ++ .phy_calibration = rtw8812a_phy_calibration, ++ .cck_pd_set = rtw88xxa_phy_cck_pd_set, ++ .pwr_track = rtw8812a_pwr_track, ++ .config_bfee = NULL, ++ .set_gid_table = NULL, ++ .cfg_csi_rate = NULL, ++ .fill_txdesc_checksum = rtw8812a_fill_txdesc_checksum, ++ .coex_set_init = rtw8812a_coex_cfg_init, ++ .coex_set_ant_switch = NULL, ++ .coex_set_gnt_fix = rtw8812a_coex_cfg_gnt_fix, ++ .coex_set_gnt_debug = NULL, ++ .coex_set_rfe_type = rtw8821a_coex_cfg_rfe_type, ++ .coex_set_wl_tx_power = rtw8821a_coex_cfg_wl_tx_power, ++ .coex_set_wl_rx_gain = rtw8821a_coex_cfg_wl_rx_gain, ++}; ++ ++static const struct rtw_page_table page_table_8812a[] = { ++ /* hq_num, nq_num, lq_num, exq_num, gapq_num */ ++ {0, 0, 0, 0, 0}, /* SDIO */ ++ {0, 0, 0, 0, 0}, /* PCI */ ++ {16, 0, 0, 0, 1}, /* 2 bulk out endpoints */ ++ {16, 0, 16, 0, 1}, /* 3 bulk out endpoints */ ++ {16, 0, 16, 0, 1}, /* 4 bulk out endpoints */ ++}; ++ ++static const struct rtw_rqpn rqpn_table_8812a[] = { ++ {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL, ++ RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW, ++ RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH}, ++ ++ {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL, ++ RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW, ++ RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH}, ++ ++ {RTW_DMA_MAPPING_HIGH, RTW_DMA_MAPPING_HIGH, ++ RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL, ++ RTW_DMA_MAPPING_HIGH, RTW_DMA_MAPPING_HIGH}, ++ ++ {RTW_DMA_MAPPING_HIGH, RTW_DMA_MAPPING_NORMAL, ++ RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW, ++ RTW_DMA_MAPPING_HIGH, RTW_DMA_MAPPING_HIGH}, ++ ++ {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL, ++ RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW, ++ RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH}, ++}; ++ ++static const struct rtw_prioq_addrs prioq_addrs_8812a = { ++ .prio[RTW_DMA_MAPPING_EXTRA] = { ++ .rsvd = REG_RQPN_NPQ + 2, .avail = REG_RQPN_NPQ + 3, ++ }, ++ .prio[RTW_DMA_MAPPING_LOW] = { ++ .rsvd = REG_RQPN + 1, .avail = REG_FIFOPAGE_CTRL_2 + 1, ++ }, ++ .prio[RTW_DMA_MAPPING_NORMAL] = { ++ .rsvd = REG_RQPN_NPQ, .avail = REG_RQPN_NPQ + 1, ++ }, ++ .prio[RTW_DMA_MAPPING_HIGH] = { ++ .rsvd = REG_RQPN, .avail = REG_FIFOPAGE_CTRL_2, ++ }, ++ .wsize = false, ++}; ++ ++static const struct rtw_hw_reg rtw8812a_dig[] = { ++ [0] = { .addr = REG_RXIGI_A, .mask = 0x7f }, ++ [1] = { .addr = REG_RXIGI_B, .mask = 0x7f }, ++}; ++ ++static const struct rtw_rfe_def rtw8812a_rfe_defs[] = { ++ [0] = { .phy_pg_tbl = &rtw8812a_bb_pg_tbl, ++ .txpwr_lmt_tbl = &rtw8812a_txpwr_lmt_tbl, ++ .pwr_track_tbl = &rtw8812a_rtw_pwr_track_tbl, }, ++ [1] = { .phy_pg_tbl = &rtw8812a_bb_pg_tbl, ++ .txpwr_lmt_tbl = &rtw8812a_txpwr_lmt_tbl, ++ .pwr_track_tbl = &rtw8812a_rtw_pwr_track_tbl, }, ++ [3] = { .phy_pg_tbl = &rtw8812a_bb_pg_rfe3_tbl, ++ .txpwr_lmt_tbl = &rtw8812a_txpwr_lmt_tbl, ++ .pwr_track_tbl = &rtw8812a_rtw_pwr_track_rfe3_tbl, }, ++}; ++ ++static const u8 wl_rssi_step_8812a[] = {101, 45, 101, 40}; ++static const u8 bt_rssi_step_8812a[] = {101, 101, 101, 101}; ++ ++static const struct coex_rf_para rf_para_tx_8812a[] = { ++ {0, 0, false, 7}, /* for normal */ ++ {0, 20, false, 7}, /* for WL-CPT */ ++ {8, 17, true, 4}, ++ {7, 18, true, 4}, ++ {6, 19, true, 4}, ++ {5, 20, true, 4} ++}; ++ ++static const struct coex_rf_para rf_para_rx_8812a[] = { ++ {0, 0, false, 7}, /* for normal */ ++ {0, 20, false, 7}, /* for WL-CPT */ ++ {3, 24, true, 5}, ++ {2, 26, true, 5}, ++ {1, 27, true, 5}, ++ {0, 28, true, 5} ++}; ++ ++static_assert(ARRAY_SIZE(rf_para_tx_8812a) == ARRAY_SIZE(rf_para_rx_8812a)); ++ ++const struct rtw_chip_info rtw8812a_hw_spec = { ++ .ops = &rtw8812a_ops, ++ .id = RTW_CHIP_TYPE_8812A, ++ .fw_name = "rtw88/rtw8812a_fw.bin", ++ .wlan_cpu = RTW_WCPU_11N, ++ .tx_pkt_desc_sz = 40, ++ .tx_buf_desc_sz = 16, ++ .rx_pkt_desc_sz = 24, ++ .rx_buf_desc_sz = 8, ++ .phy_efuse_size = 512, ++ .log_efuse_size = 512, ++ .ptct_efuse_size = 96 + 1, /* TODO or just 18? */ ++ .txff_size = 131072, ++ .rxff_size = 16128, ++ .rsvd_drv_pg_num = 9, ++ .txgi_factor = 1, ++ .is_pwr_by_rate_dec = true, ++ .max_power_index = 0x3f, ++ .csi_buf_pg_num = 0, ++ .band = RTW_BAND_2G | RTW_BAND_5G, ++ .page_size = 512, ++ .dig_min = 0x20, ++ .ht_supported = true, ++ .vht_supported = true, ++ .lps_deep_mode_supported = 0, ++ .sys_func_en = 0xFD, ++ .pwr_on_seq = card_enable_flow_8812a, ++ .pwr_off_seq = card_disable_flow_8812a, ++ .page_table = page_table_8812a, ++ .rqpn_table = rqpn_table_8812a, ++ .prioq_addrs = &prioq_addrs_8812a, ++ .intf_table = NULL, ++ .dig = rtw8812a_dig, ++ .rf_sipi_addr = {REG_LSSI_WRITE_A, REG_LSSI_WRITE_B}, ++ .ltecoex_addr = NULL, ++ .mac_tbl = &rtw8812a_mac_tbl, ++ .agc_tbl = &rtw8812a_agc_tbl, ++ .bb_tbl = &rtw8812a_bb_tbl, ++ .rf_tbl = {&rtw8812a_rf_a_tbl, &rtw8812a_rf_b_tbl}, ++ .rfe_defs = rtw8812a_rfe_defs, ++ .rfe_defs_size = ARRAY_SIZE(rtw8812a_rfe_defs), ++ .rx_ldpc = false, ++ .hw_feature_report = false, ++ .c2h_ra_report_size = 4, ++ .old_datarate_fb_limit = true, ++ .usb_tx_agg_desc_num = 1, ++ .iqk_threshold = 8, ++ .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, ++ .max_scan_ie_len = IEEE80211_MAX_DATA_LEN, ++ ++ .coex_para_ver = 0, /* no coex code in 8812au driver */ ++ .bt_desired_ver = 0, ++ .scbd_support = false, ++ .new_scbd10_def = false, ++ .ble_hid_profile_support = false, ++ .wl_mimo_ps_support = false, ++ .pstdma_type = COEX_PSTDMA_FORCE_LPSOFF, ++ .bt_rssi_type = COEX_BTRSSI_RATIO, ++ .ant_isolation = 15, ++ .rssi_tolerance = 2, ++ .wl_rssi_step = wl_rssi_step_8812a, ++ .bt_rssi_step = bt_rssi_step_8812a, ++ .table_sant_num = 0, ++ .table_sant = NULL, ++ .table_nsant_num = 0, ++ .table_nsant = NULL, ++ .tdma_sant_num = 0, ++ .tdma_sant = NULL, ++ .tdma_nsant_num = 0, ++ .tdma_nsant = NULL, ++ .wl_rf_para_num = ARRAY_SIZE(rf_para_tx_8812a), ++ .wl_rf_para_tx = rf_para_tx_8812a, ++ .wl_rf_para_rx = rf_para_rx_8812a, ++ .bt_afh_span_bw20 = 0x20, ++ .bt_afh_span_bw40 = 0x30, ++ .afh_5g_num = 0, ++ .afh_5g = NULL, ++ .coex_info_hw_regs_num = 0, ++ .coex_info_hw_regs = NULL, ++}; ++EXPORT_SYMBOL(rtw8812a_hw_spec); ++ ++MODULE_FIRMWARE("rtw88/rtw8812a_fw.bin"); ++ ++MODULE_AUTHOR("Realtek Corporation"); ++MODULE_DESCRIPTION("Realtek 802.11ac wireless 8812a driver"); ++MODULE_LICENSE("Dual BSD/GPL"); +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8812a.h b/drivers/net/wireless/realtek/rtw88/rtw8812a.h +new file mode 100644 +index 000000000000..82dab59e341d +--- /dev/null ++++ b/drivers/net/wireless/realtek/rtw88/rtw8812a.h +@@ -0,0 +1,10 @@ ++/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ ++/* Copyright(c) 2024 Realtek Corporation ++ */ ++ ++#ifndef __RTW8812A_H__ ++#define __RTW8812A_H__ ++ ++extern const struct rtw_chip_info rtw8812a_hw_spec; ++ ++#endif +-- +2.39.5 + diff --git a/packages/linux/patches/rtlwifi/6.13/0023-wifi-rtw88-Add-rtw8821au.c-and-rtw8812au.c.patch b/packages/linux/patches/rtlwifi/6.13/0023-wifi-rtw88-Add-rtw8821au.c-and-rtw8812au.c.patch new file mode 100644 index 0000000000..21c24c3b24 --- /dev/null +++ b/packages/linux/patches/rtlwifi/6.13/0023-wifi-rtw88-Add-rtw8821au.c-and-rtw8812au.c.patch @@ -0,0 +1,89 @@ +From 1f08e8b01d83e04439f4c607d3daa94751ce2b90 Mon Sep 17 00:00:00 2001 +From: Bitterblue Smith +Date: Wed, 30 Oct 2024 20:29:28 +0200 +Subject: [PATCH 23/24] wifi: rtw88: Add rtw8821au.c and rtw8812au.c + +These are the entry points for the new modules rtw88_8821au +(RTL8821AU/RTL8811AU) and rtw88_8812au (RTL8812AU). + +Signed-off-by: Bitterblue Smith +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/91c495f8-a607-429b-8bc0-5a45d3c1393e@gmail.com +--- + .../net/wireless/realtek/rtw88/rtw8812au.c | 28 +++++++++++++++++++ + .../net/wireless/realtek/rtw88/rtw8821au.c | 28 +++++++++++++++++++ + 2 files changed, 56 insertions(+) + create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8812au.c + create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8821au.c + +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8812au.c b/drivers/net/wireless/realtek/rtw88/rtw8812au.c +new file mode 100644 +index 000000000000..4da69590a423 +--- /dev/null ++++ b/drivers/net/wireless/realtek/rtw88/rtw8812au.c +@@ -0,0 +1,28 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause ++/* Copyright(c) 2024 Realtek Corporation ++ */ ++ ++#include ++#include ++#include "main.h" ++#include "rtw8812a.h" ++#include "usb.h" ++ ++static const struct usb_device_id rtw_8812au_id_table[] = { ++ { USB_DEVICE_AND_INTERFACE_INFO(0x2604, 0x0012, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(usb, rtw_8812au_id_table); ++ ++static struct usb_driver rtw_8812au_driver = { ++ .name = "rtw_8812au", ++ .id_table = rtw_8812au_id_table, ++ .probe = rtw_usb_probe, ++ .disconnect = rtw_usb_disconnect, ++}; ++module_usb_driver(rtw_8812au_driver); ++ ++MODULE_AUTHOR("Bitterblue Smith "); ++MODULE_DESCRIPTION("Realtek 802.11ac wireless 8812au driver"); ++MODULE_LICENSE("Dual BSD/GPL"); +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821au.c b/drivers/net/wireless/realtek/rtw88/rtw8821au.c +new file mode 100644 +index 000000000000..730018773e1c +--- /dev/null ++++ b/drivers/net/wireless/realtek/rtw88/rtw8821au.c +@@ -0,0 +1,28 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause ++/* Copyright(c) 2024 Realtek Corporation ++ */ ++ ++#include ++#include ++#include "main.h" ++#include "rtw8821a.h" ++#include "usb.h" ++ ++static const struct usb_device_id rtw_8821au_id_table[] = { ++ { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x011e, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(usb, rtw_8821au_id_table); ++ ++static struct usb_driver rtw_8821au_driver = { ++ .name = "rtw_8821au", ++ .id_table = rtw_8821au_id_table, ++ .probe = rtw_usb_probe, ++ .disconnect = rtw_usb_disconnect, ++}; ++module_usb_driver(rtw_8821au_driver); ++ ++MODULE_AUTHOR("Bitterblue Smith "); ++MODULE_DESCRIPTION("Realtek 802.11ac wireless 8821au/8811au driver"); ++MODULE_LICENSE("Dual BSD/GPL"); +-- +2.39.5 + diff --git a/packages/linux/patches/rtlwifi/6.13/0024-wifi-rtw88-Enable-the-new-RTL8821AU-RTL8812AU-driver.patch b/packages/linux/patches/rtlwifi/6.13/0024-wifi-rtw88-Enable-the-new-RTL8821AU-RTL8812AU-driver.patch new file mode 100644 index 0000000000..2acca20488 --- /dev/null +++ b/packages/linux/patches/rtlwifi/6.13/0024-wifi-rtw88-Enable-the-new-RTL8821AU-RTL8812AU-driver.patch @@ -0,0 +1,123 @@ +From ed2463a8afecd7ca59d00256367ac0447b75d0dc Mon Sep 17 00:00:00 2001 +From: Bitterblue Smith +Date: Wed, 30 Oct 2024 20:31:28 +0200 +Subject: [PATCH 24/24] wifi: rtw88: Enable the new RTL8821AU/RTL8812AU drivers + +These are older Wifi 5 chips. RTL8821AU is 1x1, with or without +Bluetooth. RTL8812AU is 2x2, without Bluetooth. + +Beamforming is not implemented. It looks like these chips need a +different implementation than what is in bf.c. + +Speed tests with RTL8821AU: 137 Mbps download, 144 Mbps upload. +Speed tests with RTL8812AU: 344 Mbps download, 387 Mbps upload. + +Station mode and AP mode were tested. + +Bluetooth coexistence works. I used my Bluetooth headphones for +several days, listening to music and watching videos. There is only +a problem with the wifi speeds with one router: + +With ISP's HG6544C router: +Official driver: 3/5 Mbps. +rtw88: a bit more, but not steady at all. Not enough to watch a 1080p +Youtube video. + +With my D-Link Eagle R32 router running Openwrt, on the same channel: +Official driver: 6/10 Mbps. +rtw88: download starts around 30, climbs to 50 / upload is 10 Mbps. +I can watch a 1080p Youtube video. + +The music doesn't cut out during any speed tests. + +I also tested transferring files to and from my phone. I don't have +other types of Bluetooth devices to test. + +Signed-off-by: Bitterblue Smith +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/0b8e8093-8103-4999-86bf-0055ec52ea64@gmail.com +--- + drivers/net/wireless/realtek/rtw88/Kconfig | 33 +++++++++++++++++++++ + drivers/net/wireless/realtek/rtw88/Makefile | 15 ++++++++++ + 2 files changed, 48 insertions(+) + +diff --git a/drivers/net/wireless/realtek/rtw88/Kconfig b/drivers/net/wireless/realtek/rtw88/Kconfig +index 02b0d698413b..733b3e58da51 100644 +--- a/drivers/net/wireless/realtek/rtw88/Kconfig ++++ b/drivers/net/wireless/realtek/rtw88/Kconfig +@@ -43,6 +43,17 @@ config RTW88_8723D + config RTW88_8821C + tristate + ++config RTW88_88XXA ++ tristate ++ ++config RTW88_8821A ++ tristate ++ select RTW88_88XXA ++ ++config RTW88_8812A ++ tristate ++ select RTW88_88XXA ++ + config RTW88_8822BE + tristate "Realtek 8822BE PCI wireless network adapter" + depends on PCI +@@ -189,6 +200,28 @@ config RTW88_8821CU + + 802.11ac USB wireless network adapter + ++config RTW88_8821AU ++ tristate "Realtek 8821AU/8811AU USB wireless network adapter" ++ depends on USB ++ select RTW88_CORE ++ select RTW88_USB ++ select RTW88_8821A ++ help ++ Select this option will enable support for 8821AU and 8811AU chipset ++ ++ 802.11ac USB wireless network adapter ++ ++config RTW88_8812AU ++ tristate "Realtek 8812AU USB wireless network adapter" ++ depends on USB ++ select RTW88_CORE ++ select RTW88_USB ++ select RTW88_8812A ++ help ++ Select this option will enable support for 8812AU chipset ++ ++ 802.11ac USB wireless network adapter ++ + config RTW88_DEBUG + bool "Realtek rtw88 debug support" + depends on RTW88_CORE +diff --git a/drivers/net/wireless/realtek/rtw88/Makefile b/drivers/net/wireless/realtek/rtw88/Makefile +index 8f47359b4380..f0b49f5a8a5a 100644 +--- a/drivers/net/wireless/realtek/rtw88/Makefile ++++ b/drivers/net/wireless/realtek/rtw88/Makefile +@@ -77,6 +77,21 @@ rtw88_8821cs-objs := rtw8821cs.o + obj-$(CONFIG_RTW88_8821CU) += rtw88_8821cu.o + rtw88_8821cu-objs := rtw8821cu.o + ++obj-$(CONFIG_RTW88_88XXA) += rtw88_88xxa.o ++rtw88_88xxa-objs := rtw88xxa.o ++ ++obj-$(CONFIG_RTW88_8821A) += rtw88_8821a.o ++rtw88_8821a-objs := rtw8821a.o rtw8821a_table.o ++ ++obj-$(CONFIG_RTW88_8812A) += rtw88_8812a.o ++rtw88_8812a-objs := rtw8812a.o rtw8812a_table.o ++ ++obj-$(CONFIG_RTW88_8821AU) += rtw88_8821au.o ++rtw88_8821au-objs := rtw8821au.o ++ ++obj-$(CONFIG_RTW88_8812AU) += rtw88_8812au.o ++rtw88_8812au-objs := rtw8812au.o ++ + obj-$(CONFIG_RTW88_PCI) += rtw88_pci.o + rtw88_pci-objs := pci.o + +-- +2.39.5 + diff --git a/packages/linux/patches/rtlwifi/6.14/0025-wifi-rtw88-8821au-Add-additional-devices-to-the-USB_.patch b/packages/linux/patches/rtlwifi/6.14/0025-wifi-rtw88-8821au-Add-additional-devices-to-the-USB_.patch new file mode 100644 index 0000000000..97ab048172 --- /dev/null +++ b/packages/linux/patches/rtlwifi/6.14/0025-wifi-rtw88-8821au-Add-additional-devices-to-the-USB_.patch @@ -0,0 +1,84 @@ +From 7b5ce65d90187f0944e70dc5741aa0edfac926f4 Mon Sep 17 00:00:00 2001 +From: Larry Finger +Date: Wed, 6 Nov 2024 15:55:31 +0200 +Subject: [PATCH] wifi: rtw88: 8821au: Add additional devices to the USB_DEVICE + list + +These are the entries that Nick Morrow provided. From +https://github.com/morrownr/8821au-20210708 + +Signed-off-by: Larry Finger +Signed-off-by: Bitterblue Smith +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/da05b866-a9ff-428c-a008-35e8cf200a98@gmail.com +--- + .../net/wireless/realtek/rtw88/rtw8821au.c | 52 ++++++++++++++++++- + 1 file changed, 51 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821au.c b/drivers/net/wireless/realtek/rtw88/rtw8821au.c +index 730018773e1c..a01744b64e8d 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8821au.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8821au.c +@@ -9,8 +9,58 @@ + #include "usb.h" + + static const struct usb_device_id rtw_8821au_id_table[] = { +- { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x011e, 0xff, 0xff, 0xff), ++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x0811, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x0820, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x0821, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x8822, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x0823, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xa811, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(0x0411, 0x0242, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* Buffalo */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x0411, 0x029b, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* Buffalo */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x04bb, 0x0953, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* I-O DATA */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x056e, 0x4007, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* ELECOM */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x056e, 0x400e, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* ELECOM */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x056e, 0x400f, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* ELECOM */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9052, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* Netgear */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x0e66, 0x0023, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* HAWKING */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3314, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* D-Link */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3318, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* D-Link */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0xab32, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* Planex */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x20f4, 0x804b, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* TRENDnet */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x011e, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* TP Link */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x011f, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* TP Link */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0120, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* TP Link */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x3823, 0x6249, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* Obihai */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xa811, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* Edimax */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xa812, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* Edimax */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xa813, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* Edimax */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xb611, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* Edimax */ + {}, + }; + MODULE_DEVICE_TABLE(usb, rtw_8821au_id_table); +-- +2.43.0 + diff --git a/packages/linux/patches/rtlwifi/6.14/0026-wifi-rtw88-8812au-Add-more-device-IDs.patch b/packages/linux/patches/rtlwifi/6.14/0026-wifi-rtw88-8812au-Add-more-device-IDs.patch new file mode 100644 index 0000000000..3e41340cf3 --- /dev/null +++ b/packages/linux/patches/rtlwifi/6.14/0026-wifi-rtw88-8812au-Add-more-device-IDs.patch @@ -0,0 +1,98 @@ +From 1ee6ff9ae3c1a9eda9081f9db04f85d3a7352d38 Mon Sep 17 00:00:00 2001 +From: Nick Morrow +Date: Wed, 6 Nov 2024 15:57:10 +0200 +Subject: [PATCH] wifi: rtw88: 8812au: Add more device IDs + +From https://github.com/morrownr/8812au-20210820. + +Signed-off-by: Nick Morrow +Signed-off-by: Bitterblue Smith +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/31b7ee6b-f96d-43e0-a32f-a9eb1174a0c1@gmail.com +--- + .../net/wireless/realtek/rtw88/rtw8812au.c | 68 ++++++++++++++++++- + 1 file changed, 67 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8812au.c b/drivers/net/wireless/realtek/rtw88/rtw8812au.c +index 4da69590a423..e18995f4cc78 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8812au.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8812au.c +@@ -9,8 +9,74 @@ + #include "usb.h" + + static const struct usb_device_id rtw_8812au_id_table[] = { +- { USB_DEVICE_AND_INTERFACE_INFO(0x2604, 0x0012, 0xff, 0xff, 0xff), ++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x8812, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x881a, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x881b, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x881c, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(0x0409, 0x0408, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* NEC */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x0411, 0x025d, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Buffalo */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x04bb, 0x0952, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* I-O DATA */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x050d, 0x1106, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Belkin */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x050d, 0x1109, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Belkin */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x0586, 0x3426, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* ZyXEL */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x0789, 0x016e, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Logitec */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x07b8, 0x8812, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Abocom */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9051, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Netgear */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x17d2, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* ASUS */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x0df6, 0x0074, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Sitecom */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x0e66, 0x0022, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Hawking */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x1058, 0x0632, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* WD */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x13b1, 0x003f, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Linksys */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x148f, 0x9097, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Amped Wireless */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x1740, 0x0100, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* EnGenius */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x330e, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* D-Link */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3313, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* D-Link */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3315, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* D-Link */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3316, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* D-Link */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0xab30, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Planex */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x20f4, 0x805b, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* TRENDnet */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0101, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* TP-Link */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0103, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* TP-Link */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x010d, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* TP-Link */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x010e, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* TP-Link */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x010f, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* TP-Link */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0122, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* TP-Link */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x2604, 0x0012, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Tenda */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xa822, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Edimax */ + {}, + }; + MODULE_DEVICE_TABLE(usb, rtw_8812au_id_table); +-- +2.43.0 + diff --git a/packages/linux/patches/rtlwifi/6.14/0027-wifi-rtw88-usb-Support-USB-3-with-RTL8812AU.patch b/packages/linux/patches/rtlwifi/6.14/0027-wifi-rtw88-usb-Support-USB-3-with-RTL8812AU.patch new file mode 100644 index 0000000000..0014e6f4e3 --- /dev/null +++ b/packages/linux/patches/rtlwifi/6.14/0027-wifi-rtw88-usb-Support-USB-3-with-RTL8812AU.patch @@ -0,0 +1,90 @@ +From 82a35723a67c29f685d7b518962154a73b7163a2 Mon Sep 17 00:00:00 2001 +From: Bitterblue Smith +Date: Thu, 14 Nov 2024 17:46:08 +0200 +Subject: [PATCH] wifi: rtw88: usb: Support USB 3 with RTL8812AU + +Add the function to automatically switch the RTL8812AU into USB 3 mode. + +Signed-off-by: Bitterblue Smith +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/19cda72b-f1f1-4b69-8369-0e4376b646bf@gmail.com +--- + drivers/net/wireless/realtek/rtw88/usb.c | 44 ++++++++++++++++++++++-- + 1 file changed, 42 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c +index 8d6db68246f1..db1769a4b617 100644 +--- a/drivers/net/wireless/realtek/rtw88/usb.c ++++ b/drivers/net/wireless/realtek/rtw88/usb.c +@@ -930,6 +930,32 @@ static void rtw_usb_intf_deinit(struct rtw_dev *rtwdev, + usb_set_intfdata(intf, NULL); + } + ++static int rtw_usb_switch_mode_old(struct rtw_dev *rtwdev) ++{ ++ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); ++ enum usb_device_speed cur_speed = rtwusb->udev->speed; ++ u8 hci_opt; ++ ++ if (cur_speed == USB_SPEED_HIGH) { ++ hci_opt = rtw_read8(rtwdev, REG_HCI_OPT_CTRL); ++ ++ if ((hci_opt & (BIT(2) | BIT(3))) != BIT(3)) { ++ rtw_write8(rtwdev, REG_HCI_OPT_CTRL, 0x8); ++ rtw_write8(rtwdev, REG_SYS_SDIO_CTRL, 0x2); ++ rtw_write8(rtwdev, REG_ACLK_MON, 0x1); ++ rtw_write8(rtwdev, 0x3d, 0x3); ++ /* usb disconnect */ ++ rtw_write8(rtwdev, REG_SYS_PW_CTRL + 1, 0x80); ++ return 1; ++ } ++ } else if (cur_speed == USB_SPEED_SUPER) { ++ rtw_write8_clr(rtwdev, REG_SYS_SDIO_CTRL, BIT(1)); ++ rtw_write8_clr(rtwdev, REG_ACLK_MON, BIT(0)); ++ } ++ ++ return 0; ++} ++ + static int rtw_usb_switch_mode_new(struct rtw_dev *rtwdev) + { + enum usb_device_speed cur_speed; +@@ -979,11 +1005,22 @@ static int rtw_usb_switch_mode_new(struct rtw_dev *rtwdev) + return 1; + } + ++static bool rtw_usb3_chip_old(u8 chip_id) ++{ ++ return chip_id == RTW_CHIP_TYPE_8812A; ++} ++ ++static bool rtw_usb3_chip_new(u8 chip_id) ++{ ++ return chip_id == RTW_CHIP_TYPE_8822C || ++ chip_id == RTW_CHIP_TYPE_8822B; ++} ++ + static int rtw_usb_switch_mode(struct rtw_dev *rtwdev) + { + u8 id = rtwdev->chip->id; + +- if (id != RTW_CHIP_TYPE_8822C && id != RTW_CHIP_TYPE_8822B) ++ if (!rtw_usb3_chip_new(id) && !rtw_usb3_chip_old(id)) + return 0; + + if (!rtwdev->efuse.usb_mode_switch) { +@@ -998,7 +1035,10 @@ static int rtw_usb_switch_mode(struct rtw_dev *rtwdev) + return 0; + } + +- return rtw_usb_switch_mode_new(rtwdev); ++ if (rtw_usb3_chip_old(id)) ++ return rtw_usb_switch_mode_old(rtwdev); ++ else ++ return rtw_usb_switch_mode_new(rtwdev); + } + + int rtw_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) +-- +2.43.0 + diff --git a/packages/linux/patches/rtlwifi/6.14/0028-wifi-rtw88-usb-Enable-RX-aggregation-for-8821au-8812.patch b/packages/linux/patches/rtlwifi/6.14/0028-wifi-rtw88-usb-Enable-RX-aggregation-for-8821au-8812.patch new file mode 100644 index 0000000000..427e26103b --- /dev/null +++ b/packages/linux/patches/rtlwifi/6.14/0028-wifi-rtw88-usb-Enable-RX-aggregation-for-8821au-8812.patch @@ -0,0 +1,70 @@ +From ce5dea83ee8f945203144fb891fdcb978216e45a Mon Sep 17 00:00:00 2001 +From: Bitterblue Smith +Date: Thu, 14 Nov 2024 17:48:09 +0200 +Subject: [PATCH] wifi: rtw88: usb: Enable RX aggregation for 8821au/8812au + +USB RX aggregation improves the RX speed on certain ARM systems, like +the NanoPi NEO Core2. With RTL8811AU, before: 30 Mbps, after: 224 Mbps. + +The out-of-tree driver uses aggregation size of 7 in USB 3 mode, but +that doesn't work here. rtw88 advertises support for receiving AMSDU +in AMPDU, so the AP sends larger frames, up to ~5100 bytes. With a size +of 7 RTL8812AU frequently tries to aggregate more frames than will fit +in 32768 bytes. Use a size of 6 instead. + +Signed-off-by: Bitterblue Smith +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/63012163-a425-4b15-b830-43f279c06b73@gmail.com +--- + drivers/net/wireless/realtek/rtw88/usb.c | 28 ++++++++++++++++++++++++ + 1 file changed, 28 insertions(+) + +diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c +index db1769a4b617..be193c7add77 100644 +--- a/drivers/net/wireless/realtek/rtw88/usb.c ++++ b/drivers/net/wireless/realtek/rtw88/usb.c +@@ -789,6 +789,30 @@ static void rtw_usb_dynamic_rx_agg_v1(struct rtw_dev *rtwdev, bool enable) + rtw_write16(rtwdev, REG_RXDMA_AGG_PG_TH, val16); + } + ++static void rtw_usb_dynamic_rx_agg_v2(struct rtw_dev *rtwdev, bool enable) ++{ ++ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); ++ u8 size, timeout; ++ u16 val16; ++ ++ if (!enable) { ++ size = 0x0; ++ timeout = 0x1; ++ } else if (rtwusb->udev->speed == USB_SPEED_SUPER) { ++ size = 0x6; ++ timeout = 0x1a; ++ } else { ++ size = 0x5; ++ timeout = 0x20; ++ } ++ ++ val16 = u16_encode_bits(size, BIT_RXDMA_AGG_PG_TH) | ++ u16_encode_bits(timeout, BIT_DMA_AGG_TO_V1); ++ ++ rtw_write16(rtwdev, REG_RXDMA_AGG_PG_TH, val16); ++ rtw_write8_set(rtwdev, REG_TXDMA_PQ_MAP, BIT_RXDMA_AGG_EN); ++} ++ + static void rtw_usb_dynamic_rx_agg(struct rtw_dev *rtwdev, bool enable) + { + switch (rtwdev->chip->id) { +@@ -797,6 +821,10 @@ static void rtw_usb_dynamic_rx_agg(struct rtw_dev *rtwdev, bool enable) + case RTW_CHIP_TYPE_8821C: + rtw_usb_dynamic_rx_agg_v1(rtwdev, enable); + break; ++ case RTW_CHIP_TYPE_8821A: ++ case RTW_CHIP_TYPE_8812A: ++ rtw_usb_dynamic_rx_agg_v2(rtwdev, enable); ++ break; + case RTW_CHIP_TYPE_8723D: + /* Doesn't like aggregation. */ + break; +-- +2.43.0 + diff --git a/packages/linux/patches/rtlwifi/6.14/0031-wifi-rtw88-8812a-Support-RFE-type-2.patch b/packages/linux/patches/rtlwifi/6.14/0031-wifi-rtw88-8812a-Support-RFE-type-2.patch new file mode 100644 index 0000000000..cff4f7229a --- /dev/null +++ b/packages/linux/patches/rtlwifi/6.14/0031-wifi-rtw88-8812a-Support-RFE-type-2.patch @@ -0,0 +1,33 @@ +From 59ab27a9f20f8de6f7989e8a8c3d97c04ed8199c Mon Sep 17 00:00:00 2001 +From: Bitterblue Smith +Date: Wed, 18 Dec 2024 02:13:22 +0200 +Subject: [PATCH 31/35] wifi: rtw88: 8812a: Support RFE type 2 + +RF front end type 2 exists in the wild and can be treated like types +0 and 1. + +Signed-off-by: Bitterblue Smith +Acked-by: Ping-Ke Shih +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/2917c7fc-6d88-4007-b6a6-9130bd1991e5@gmail.com +--- + drivers/net/wireless/realtek/rtw88/rtw8812a.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8812a.c b/drivers/net/wireless/realtek/rtw88/rtw8812a.c +index 482edd31823d..d8f0ed70777f 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8812a.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8812a.c +@@ -985,6 +985,9 @@ static const struct rtw_rfe_def rtw8812a_rfe_defs[] = { + [1] = { .phy_pg_tbl = &rtw8812a_bb_pg_tbl, + .txpwr_lmt_tbl = &rtw8812a_txpwr_lmt_tbl, + .pwr_track_tbl = &rtw8812a_rtw_pwr_track_tbl, }, ++ [2] = { .phy_pg_tbl = &rtw8812a_bb_pg_tbl, ++ .txpwr_lmt_tbl = &rtw8812a_txpwr_lmt_tbl, ++ .pwr_track_tbl = &rtw8812a_rtw_pwr_track_tbl, }, + [3] = { .phy_pg_tbl = &rtw8812a_bb_pg_rfe3_tbl, + .txpwr_lmt_tbl = &rtw8812a_txpwr_lmt_tbl, + .pwr_track_tbl = &rtw8812a_rtw_pwr_track_rfe3_tbl, }, +-- +2.43.0 + diff --git a/packages/linux/patches/rtlwifi/6.14/0032-wifi-rtw88-8821a-8812a-Set-ptct_efuse_size-to-0.patch b/packages/linux/patches/rtlwifi/6.14/0032-wifi-rtw88-8821a-8812a-Set-ptct_efuse_size-to-0.patch new file mode 100644 index 0000000000..8d667f74e1 --- /dev/null +++ b/packages/linux/patches/rtlwifi/6.14/0032-wifi-rtw88-8821a-8812a-Set-ptct_efuse_size-to-0.patch @@ -0,0 +1,58 @@ +From 74a72c367573ad521becf6cc4d649e14387b3c64 Mon Sep 17 00:00:00 2001 +From: Bitterblue Smith +Date: Wed, 18 Dec 2024 02:16:11 +0200 +Subject: [PATCH 32/35] wifi: rtw88: 8821a/8812a: Set ptct_efuse_size to 0 + +Some RTL8812AU devices fail to probe: + +[ 12.478774] rtw_8812au 1-1.3:1.0: failed to dump efuse logical map +[ 12.487712] rtw_8812au 1-1.3:1.0: failed to setup chip efuse info +[ 12.487742] rtw_8812au 1-1.3:1.0: failed to setup chip information +[ 12.491077] rtw_8812au: probe of 1-1.3:1.0 failed with error -22 + +It turns out these chips don't need to "protect" any bytes at the end of +the efuse. + +The original value of 96 was copied from rtw8821c.c. + +No one reported any failures with RTL8821AU yet, but the vendor driver +uses the same efuse reading code for both chips. + +Signed-off-by: Bitterblue Smith +Acked-by: Ping-Ke Shih +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/1a477adb-60c3-463c-b158-3f86c94cb821@gmail.com +--- + drivers/net/wireless/realtek/rtw88/rtw8812a.c | 2 +- + drivers/net/wireless/realtek/rtw88/rtw8821a.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8812a.c b/drivers/net/wireless/realtek/rtw88/rtw8812a.c +index d8f0ed70777f..21795286a1a0 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8812a.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8812a.c +@@ -1027,7 +1027,7 @@ const struct rtw_chip_info rtw8812a_hw_spec = { + .rx_buf_desc_sz = 8, + .phy_efuse_size = 512, + .log_efuse_size = 512, +- .ptct_efuse_size = 96 + 1, /* TODO or just 18? */ ++ .ptct_efuse_size = 0, + .txff_size = 131072, + .rxff_size = 16128, + .rsvd_drv_pg_num = 9, +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821a.c b/drivers/net/wireless/realtek/rtw88/rtw8821a.c +index db242c9ad68f..dafab2af33bc 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8821a.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8821a.c +@@ -1118,7 +1118,7 @@ const struct rtw_chip_info rtw8821a_hw_spec = { + .rx_buf_desc_sz = 8, + .phy_efuse_size = 512, + .log_efuse_size = 512, +- .ptct_efuse_size = 96 + 1, /* TODO or just 18? */ ++ .ptct_efuse_size = 0, + .txff_size = 65536, + .rxff_size = 16128, + .rsvd_drv_pg_num = 8, +-- +2.43.0 + diff --git a/packages/linux/patches/rtlwifi/6.14/0033-wifi-rtw88-usb-Copy-instead-of-cloning-the-RX-skb.patch b/packages/linux/patches/rtlwifi/6.14/0033-wifi-rtw88-usb-Copy-instead-of-cloning-the-RX-skb.patch new file mode 100644 index 0000000000..1d1f7657d2 --- /dev/null +++ b/packages/linux/patches/rtlwifi/6.14/0033-wifi-rtw88-usb-Copy-instead-of-cloning-the-RX-skb.patch @@ -0,0 +1,135 @@ +From e9048e2935f7d797c2ba047c15b705b57c2fa99a Mon Sep 17 00:00:00 2001 +From: Bitterblue Smith +Date: Thu, 19 Dec 2024 00:33:20 +0200 +Subject: [PATCH 33/35] wifi: rtw88: usb: Copy instead of cloning the RX skb + +"iperf3 -c 192.168.0.1 -R --udp -b 0" shows about 40% of datagrams +are lost. Many torrents don't download faster than 3 MiB/s, probably +because the Bittorrent protocol uses UDP. This is somehow related to +the use of skb_clone() in the RX path. + +Don't use skb_clone(). Instead allocate a new skb for each 802.11 frame +received and copy the data from the big (32768 byte) skb. + +With this patch, "iperf3 -c 192.168.0.1 -R --udp -b 0" shows only 1-2% +of datagrams are lost, and torrents can reach download speeds of 36 +MiB/s. + +Tested with RTL8812AU and RTL8822CU. + +Signed-off-by: Bitterblue Smith +Acked-by: Ping-Ke Shih +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/8c9d4f9d-ebd8-4dc0-a0c4-9ebe430521dd@gmail.com +--- + drivers/net/wireless/realtek/rtw88/usb.c | 52 ++++++++++++++---------- + 1 file changed, 31 insertions(+), 21 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c +index be193c7add77..28679d9cdffc 100644 +--- a/drivers/net/wireless/realtek/rtw88/usb.c ++++ b/drivers/net/wireless/realtek/rtw88/usb.c +@@ -7,6 +7,7 @@ + #include + #include "main.h" + #include "debug.h" ++#include "mac.h" + #include "reg.h" + #include "tx.h" + #include "rx.h" +@@ -547,49 +548,58 @@ static void rtw_usb_rx_handler(struct work_struct *work) + { + struct rtw_usb *rtwusb = container_of(work, struct rtw_usb, rx_work); + struct rtw_dev *rtwdev = rtwusb->rtwdev; +- const struct rtw_chip_info *chip = rtwdev->chip; +- u32 pkt_desc_sz = chip->rx_pkt_desc_sz; + struct ieee80211_rx_status rx_status; +- u32 pkt_offset, next_pkt, urb_len; + struct rtw_rx_pkt_stat pkt_stat; +- struct sk_buff *next_skb; ++ struct sk_buff *rx_skb; + struct sk_buff *skb; ++ u32 pkt_desc_sz = rtwdev->chip->rx_pkt_desc_sz; ++ u32 max_skb_len = pkt_desc_sz + PHY_STATUS_SIZE * 8 + ++ IEEE80211_MAX_MPDU_LEN_VHT_11454; ++ u32 pkt_offset, next_pkt, skb_len; + u8 *rx_desc; + int limit; + + for (limit = 0; limit < 200; limit++) { +- skb = skb_dequeue(&rtwusb->rx_queue); +- if (!skb) ++ rx_skb = skb_dequeue(&rtwusb->rx_queue); ++ if (!rx_skb) + break; + + if (skb_queue_len(&rtwusb->rx_queue) >= RTW_USB_MAX_RXQ_LEN) { + dev_dbg_ratelimited(rtwdev->dev, "failed to get rx_queue, overflow\n"); +- dev_kfree_skb_any(skb); ++ dev_kfree_skb_any(rx_skb); + continue; + } + +- urb_len = skb->len; ++ rx_desc = rx_skb->data; + + do { +- rx_desc = skb->data; + rtw_rx_query_rx_desc(rtwdev, rx_desc, &pkt_stat, + &rx_status); + pkt_offset = pkt_desc_sz + pkt_stat.drv_info_sz + + pkt_stat.shift; + +- next_pkt = round_up(pkt_stat.pkt_len + pkt_offset, 8); ++ skb_len = pkt_stat.pkt_len + pkt_offset; ++ if (skb_len > max_skb_len) { ++ rtw_dbg(rtwdev, RTW_DBG_USB, ++ "skipping too big packet: %u\n", ++ skb_len); ++ goto skip_packet; ++ } + +- if (urb_len >= next_pkt + pkt_desc_sz) +- next_skb = skb_clone(skb, GFP_KERNEL); +- else +- next_skb = NULL; ++ skb = alloc_skb(skb_len, GFP_KERNEL); ++ if (!skb) { ++ rtw_dbg(rtwdev, RTW_DBG_USB, ++ "failed to allocate RX skb of size %u\n", ++ skb_len); ++ goto skip_packet; ++ } ++ ++ skb_put_data(skb, rx_desc, skb_len); + + if (pkt_stat.is_c2h) { +- skb_trim(skb, pkt_stat.pkt_len + pkt_offset); + rtw_fw_c2h_cmd_rx_irqsafe(rtwdev, pkt_offset, skb); + } else { + skb_pull(skb, pkt_offset); +- skb_trim(skb, pkt_stat.pkt_len); + rtw_update_rx_freq_for_invalid(rtwdev, skb, + &rx_status, + &pkt_stat); +@@ -598,12 +608,12 @@ static void rtw_usb_rx_handler(struct work_struct *work) + ieee80211_rx_irqsafe(rtwdev->hw, skb); + } + +- skb = next_skb; +- if (skb) +- skb_pull(skb, next_pkt); ++skip_packet: ++ next_pkt = round_up(skb_len, 8); ++ rx_desc += next_pkt; ++ } while (rx_desc + pkt_desc_sz < rx_skb->data + rx_skb->len); + +- urb_len -= next_pkt; +- } while (skb); ++ dev_kfree_skb_any(rx_skb); + } + } + +-- +2.43.0 + diff --git a/packages/linux/patches/rtlwifi/6.14/0034-wifi-rtw88-Handle-C2H_ADAPTIVITY-in-rtw_fw_c2h_cmd_h.patch b/packages/linux/patches/rtlwifi/6.14/0034-wifi-rtw88-Handle-C2H_ADAPTIVITY-in-rtw_fw_c2h_cmd_h.patch new file mode 100644 index 0000000000..64a4ee82e8 --- /dev/null +++ b/packages/linux/patches/rtlwifi/6.14/0034-wifi-rtw88-Handle-C2H_ADAPTIVITY-in-rtw_fw_c2h_cmd_h.patch @@ -0,0 +1,51 @@ +From 13221be72034d1c34630ab124c43438aefe7e656 Mon Sep 17 00:00:00 2001 +From: Bitterblue Smith +Date: Thu, 19 Dec 2024 00:34:42 +0200 +Subject: [PATCH 34/35] wifi: rtw88: Handle C2H_ADAPTIVITY in + rtw_fw_c2h_cmd_handle() + +The firmware message C2H_ADAPTIVITY is currently handled in +rtw_fw_c2h_cmd_rx_irqsafe(), which runs in the RX workqueue, but it's +not "irqsafe" with USB because it sleeps (reads hardware registers). +This becomes a problem after the next patch, which will create the RX +workqueue with the flag WQ_BH. + +To avoid sleeping when it's not allowed, handle C2H_ADAPTIVITY in +rtw_fw_c2h_cmd_handle(), which runs in the c2h workqueue. + +Signed-off-by: Bitterblue Smith +Acked-by: Ping-Ke Shih +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/96e52b03-be8d-4050-ae71-bfdb478ff42f@gmail.com +--- + drivers/net/wireless/realtek/rtw88/fw.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c +index e6e9946fbf44..02389b7c6876 100644 +--- a/drivers/net/wireless/realtek/rtw88/fw.c ++++ b/drivers/net/wireless/realtek/rtw88/fw.c +@@ -332,6 +332,9 @@ void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb) + case C2H_RA_RPT: + rtw_fw_ra_report_handle(rtwdev, c2h->payload, len); + break; ++ case C2H_ADAPTIVITY: ++ rtw_fw_adaptivity_result(rtwdev, c2h->payload, len); ++ break; + default: + rtw_dbg(rtwdev, RTW_DBG_FW, "C2H 0x%x isn't handled\n", c2h->id); + break; +@@ -367,10 +370,6 @@ void rtw_fw_c2h_cmd_rx_irqsafe(struct rtw_dev *rtwdev, u32 pkt_offset, + rtw_fw_scan_result(rtwdev, c2h->payload, len); + dev_kfree_skb_any(skb); + break; +- case C2H_ADAPTIVITY: +- rtw_fw_adaptivity_result(rtwdev, c2h->payload, len); +- dev_kfree_skb_any(skb); +- break; + default: + /* pass offset for further operation */ + *((u32 *)skb->cb) = pkt_offset; +-- +2.43.0 + diff --git a/packages/linux/patches/rtlwifi/6.14/0035-wifi-rtw88-usb-Preallocate-and-reuse-the-RX-skbs.patch b/packages/linux/patches/rtlwifi/6.14/0035-wifi-rtw88-usb-Preallocate-and-reuse-the-RX-skbs.patch new file mode 100644 index 0000000000..64936d5233 --- /dev/null +++ b/packages/linux/patches/rtlwifi/6.14/0035-wifi-rtw88-usb-Preallocate-and-reuse-the-RX-skbs.patch @@ -0,0 +1,230 @@ +From 3e3aa566dd1803f1697530de6c8489a8350765b3 Mon Sep 17 00:00:00 2001 +From: Bitterblue Smith +Date: Thu, 19 Dec 2024 00:35:49 +0200 +Subject: [PATCH 35/35] wifi: rtw88: usb: Preallocate and reuse the RX skbs + +The USB driver uses four USB Request Blocks for RX. Before submitting +one, it allocates a 32768 byte skb for the RX data. This allocation can +fail, maybe due to temporary memory fragmentation. When the allocation +fails, the corresponding URB is never submitted again. After four such +allocation failures, all RX stops because the driver is not requesting +data from the device anymore. + +Don't allocate a 32768 byte skb when submitting a USB Request Block +(which happens very often). Instead preallocate 8 such skbs, and reuse +them over and over. If all 8 are busy, allocate a new one. This is +pretty rare. If the allocation fails, use a work to try again later. +When there are enough free skbs again, free the excess skbs. + +Also, use WQ_BH for the RX workqueue. With a normal or high priority +workqueue the skbs are processed too slowly when the system is even a +little busy, like when opening a new page in a browser, and the driver +runs out of free skbs and allocates a lot of new ones. + +This is more or less what the out-of-tree Realtek drivers do, except +they use a tasklet instead of a BH workqueue. + +Tested with RTL8723DU, RTL8821AU, RTL8812AU, RTL8812BU, RTL8822CU, +RTL8811CU. + +Closes: https://lore.kernel.org/linux-wireless/6e7ecb47-7ea0-433a-a19f-05f88a2edf6b@gmail.com/ +Signed-off-by: Bitterblue Smith +Acked-by: Ping-Ke Shih +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/9cee7a34-c38d-4128-824d-0ec139ca5a4e@gmail.com +--- + drivers/net/wireless/realtek/rtw88/usb.c | 79 +++++++++++++++++++----- + drivers/net/wireless/realtek/rtw88/usb.h | 3 + + 2 files changed, 67 insertions(+), 15 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c +index 28679d9cdffc..1572b61cf877 100644 +--- a/drivers/net/wireless/realtek/rtw88/usb.c ++++ b/drivers/net/wireless/realtek/rtw88/usb.c +@@ -586,7 +586,7 @@ static void rtw_usb_rx_handler(struct work_struct *work) + goto skip_packet; + } + +- skb = alloc_skb(skb_len, GFP_KERNEL); ++ skb = alloc_skb(skb_len, GFP_ATOMIC); + if (!skb) { + rtw_dbg(rtwdev, RTW_DBG_USB, + "failed to allocate RX skb of size %u\n", +@@ -613,32 +613,70 @@ static void rtw_usb_rx_handler(struct work_struct *work) + rx_desc += next_pkt; + } while (rx_desc + pkt_desc_sz < rx_skb->data + rx_skb->len); + +- dev_kfree_skb_any(rx_skb); ++ if (skb_queue_len(&rtwusb->rx_free_queue) >= RTW_USB_RX_SKB_NUM) ++ dev_kfree_skb_any(rx_skb); ++ else ++ skb_queue_tail(&rtwusb->rx_free_queue, rx_skb); + } + } + + static void rtw_usb_read_port_complete(struct urb *urb); + +-static void rtw_usb_rx_resubmit(struct rtw_usb *rtwusb, struct rx_usb_ctrl_block *rxcb) ++static void rtw_usb_rx_resubmit(struct rtw_usb *rtwusb, ++ struct rx_usb_ctrl_block *rxcb, ++ gfp_t gfp) + { + struct rtw_dev *rtwdev = rtwusb->rtwdev; ++ struct sk_buff *rx_skb; + int error; + +- rxcb->rx_skb = alloc_skb(RTW_USB_MAX_RECVBUF_SZ, GFP_ATOMIC); +- if (!rxcb->rx_skb) +- return; ++ rx_skb = skb_dequeue(&rtwusb->rx_free_queue); ++ if (!rx_skb) ++ rx_skb = alloc_skb(RTW_USB_MAX_RECVBUF_SZ, gfp); ++ ++ if (!rx_skb) ++ goto try_later; ++ ++ skb_reset_tail_pointer(rx_skb); ++ rx_skb->len = 0; ++ ++ rxcb->rx_skb = rx_skb; + + usb_fill_bulk_urb(rxcb->rx_urb, rtwusb->udev, + usb_rcvbulkpipe(rtwusb->udev, rtwusb->pipe_in), + rxcb->rx_skb->data, RTW_USB_MAX_RECVBUF_SZ, + rtw_usb_read_port_complete, rxcb); + +- error = usb_submit_urb(rxcb->rx_urb, GFP_ATOMIC); ++ error = usb_submit_urb(rxcb->rx_urb, gfp); + if (error) { +- kfree_skb(rxcb->rx_skb); ++ skb_queue_tail(&rtwusb->rx_free_queue, rxcb->rx_skb); ++ + if (error != -ENODEV) + rtw_err(rtwdev, "Err sending rx data urb %d\n", + error); ++ ++ if (error == -ENOMEM) ++ goto try_later; ++ } ++ ++ return; ++ ++try_later: ++ rxcb->rx_skb = NULL; ++ queue_work(rtwusb->rxwq, &rtwusb->rx_urb_work); ++} ++ ++static void rtw_usb_rx_resubmit_work(struct work_struct *work) ++{ ++ struct rtw_usb *rtwusb = container_of(work, struct rtw_usb, rx_urb_work); ++ struct rx_usb_ctrl_block *rxcb; ++ int i; ++ ++ for (i = 0; i < RTW_USB_RXCB_NUM; i++) { ++ rxcb = &rtwusb->rx_cb[i]; ++ ++ if (!rxcb->rx_skb) ++ rtw_usb_rx_resubmit(rtwusb, rxcb, GFP_ATOMIC); + } + } + +@@ -654,15 +692,16 @@ static void rtw_usb_read_port_complete(struct urb *urb) + urb->actual_length < 24) { + rtw_err(rtwdev, "failed to get urb length:%d\n", + urb->actual_length); +- if (skb) +- dev_kfree_skb_any(skb); ++ skb_queue_tail(&rtwusb->rx_free_queue, skb); + } else { + skb_put(skb, urb->actual_length); + skb_queue_tail(&rtwusb->rx_queue, skb); + queue_work(rtwusb->rxwq, &rtwusb->rx_work); + } +- rtw_usb_rx_resubmit(rtwusb, rxcb); ++ rtw_usb_rx_resubmit(rtwusb, rxcb, GFP_ATOMIC); + } else { ++ skb_queue_tail(&rtwusb->rx_free_queue, skb); ++ + switch (urb->status) { + case -EINVAL: + case -EPIPE: +@@ -680,8 +719,6 @@ static void rtw_usb_read_port_complete(struct urb *urb) + rtw_err(rtwdev, "status %d\n", urb->status); + break; + } +- if (skb) +- dev_kfree_skb_any(skb); + } + } + +@@ -869,16 +906,26 @@ static struct rtw_hci_ops rtw_usb_ops = { + static int rtw_usb_init_rx(struct rtw_dev *rtwdev) + { + struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); ++ struct sk_buff *rx_skb; ++ int i; + +- rtwusb->rxwq = create_singlethread_workqueue("rtw88_usb: rx wq"); ++ rtwusb->rxwq = alloc_workqueue("rtw88_usb: rx wq", WQ_BH, 0); + if (!rtwusb->rxwq) { + rtw_err(rtwdev, "failed to create RX work queue\n"); + return -ENOMEM; + } + + skb_queue_head_init(&rtwusb->rx_queue); ++ skb_queue_head_init(&rtwusb->rx_free_queue); + + INIT_WORK(&rtwusb->rx_work, rtw_usb_rx_handler); ++ INIT_WORK(&rtwusb->rx_urb_work, rtw_usb_rx_resubmit_work); ++ ++ for (i = 0; i < RTW_USB_RX_SKB_NUM; i++) { ++ rx_skb = alloc_skb(RTW_USB_MAX_RECVBUF_SZ, GFP_KERNEL); ++ if (rx_skb) ++ skb_queue_tail(&rtwusb->rx_free_queue, rx_skb); ++ } + + return 0; + } +@@ -891,7 +938,7 @@ static void rtw_usb_setup_rx(struct rtw_dev *rtwdev) + for (i = 0; i < RTW_USB_RXCB_NUM; i++) { + struct rx_usb_ctrl_block *rxcb = &rtwusb->rx_cb[i]; + +- rtw_usb_rx_resubmit(rtwusb, rxcb); ++ rtw_usb_rx_resubmit(rtwusb, rxcb, GFP_KERNEL); + } + } + +@@ -903,6 +950,8 @@ static void rtw_usb_deinit_rx(struct rtw_dev *rtwdev) + + flush_workqueue(rtwusb->rxwq); + destroy_workqueue(rtwusb->rxwq); ++ ++ skb_queue_purge(&rtwusb->rx_free_queue); + } + + static int rtw_usb_init_tx(struct rtw_dev *rtwdev) +diff --git a/drivers/net/wireless/realtek/rtw88/usb.h b/drivers/net/wireless/realtek/rtw88/usb.h +index 86697a5c0103..9b695b688b24 100644 +--- a/drivers/net/wireless/realtek/rtw88/usb.h ++++ b/drivers/net/wireless/realtek/rtw88/usb.h +@@ -38,6 +38,7 @@ + #define RTW_USB_RXAGG_TIMEOUT 10 + + #define RTW_USB_RXCB_NUM 4 ++#define RTW_USB_RX_SKB_NUM 8 + + #define RTW_USB_EP_MAX 4 + +@@ -81,7 +82,9 @@ struct rtw_usb { + + struct rx_usb_ctrl_block rx_cb[RTW_USB_RXCB_NUM]; + struct sk_buff_head rx_queue; ++ struct sk_buff_head rx_free_queue; + struct work_struct rx_work; ++ struct work_struct rx_urb_work; + }; + + static inline struct rtw_usb_tx_data *rtw_usb_get_tx_data(struct sk_buff *skb) +-- +2.43.0 + diff --git a/packages/linux/patches/rtlwifi/6.14/0036-wifi-rtl8xxxu-Fix-RTL8188EU-firmware-upload-block-si.patch b/packages/linux/patches/rtlwifi/6.14/0036-wifi-rtl8xxxu-Fix-RTL8188EU-firmware-upload-block-si.patch new file mode 100644 index 0000000000..8ef4b5b1a3 --- /dev/null +++ b/packages/linux/patches/rtlwifi/6.14/0036-wifi-rtl8xxxu-Fix-RTL8188EU-firmware-upload-block-si.patch @@ -0,0 +1,34 @@ +From 93b3a45645f13290745ef58bf99ad0877af29381 Mon Sep 17 00:00:00 2001 +From: Bitterblue Smith +Date: Mon, 23 Dec 2024 17:01:57 +0200 +Subject: [PATCH 36/41] wifi: rtl8xxxu: Fix RTL8188EU firmware upload block + size + +A user reports that the firmware upload consistently fails when it's +uploaded in chunks of 128 bytes, but it works when uploaded in chunks +of 196 bytes. The official driver uses 196 bytes also. + +Link: https://github.com/a5a5aa555oo/rtl8xxxu/issues/2 +Signed-off-by: Bitterblue Smith +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/cba8e2f2-32c4-4174-90ba-0219f29dbdde@gmail.com +--- + drivers/net/wireless/realtek/rtl8xxxu/8188e.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/realtek/rtl8xxxu/8188e.c b/drivers/net/wireless/realtek/rtl8xxxu/8188e.c +index 3d04df0f5bf4..766a7a7c7d28 100644 +--- a/drivers/net/wireless/realtek/rtl8xxxu/8188e.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/8188e.c +@@ -1860,7 +1860,7 @@ struct rtl8xxxu_fileops rtl8188eu_fops = { + .set_crystal_cap = rtl8188f_set_crystal_cap, + .cck_rssi = rtl8188e_cck_rssi, + .led_classdev_brightness_set = rtl8188eu_led_brightness_set, +- .writeN_block_size = 128, ++ .writeN_block_size = 196, + .rx_desc_size = sizeof(struct rtl8xxxu_rxdesc16), + .tx_desc_size = sizeof(struct rtl8xxxu_txdesc32), + .has_tx_report = 1, +-- +2.43.0 + diff --git a/packages/linux/patches/rtlwifi/6.14/0037-wifi-rtw88-Add-USB-PHY-configuration.patch b/packages/linux/patches/rtlwifi/6.14/0037-wifi-rtw88-Add-USB-PHY-configuration.patch new file mode 100644 index 0000000000..e167ccb855 --- /dev/null +++ b/packages/linux/patches/rtlwifi/6.14/0037-wifi-rtw88-Add-USB-PHY-configuration.patch @@ -0,0 +1,148 @@ +From fc57e8bef80bbfaba1ce0554f3b3c8df825e30b9 Mon Sep 17 00:00:00 2001 +From: Bitterblue Smith +Date: Wed, 1 Jan 2025 18:16:32 +0200 +Subject: [PATCH 37/41] wifi: rtw88: Add USB PHY configuration + +Add some extra configuration for USB devices. Currently only RTL8822BU +version (cut) D needs this. The new code makes use of the existing +usb3_param_8822b array from rtw8822b.c. + +A user reported that TP-Link Archer T3U in USB 3 mode was randomly +disconnecting from USB: + +[ 26.036502] usb 2-2: new SuperSpeed USB device number 3 using xhci_hcd +... +[ 27.576491] usb 2-2: USB disconnect, device number 3 +[ 28.621528] usb 2-2: new SuperSpeed USB device number 4 using xhci_hcd +... +[ 45.984521] usb 2-2: USB disconnect, device number 4 +... +[ 46.845585] usb 2-2: new SuperSpeed USB device number 5 using xhci_hcd +... +[ 94.400380] usb 2-2: USB disconnect, device number 5 +... +[ 95.590421] usb 2-2: new SuperSpeed USB device number 6 using xhci_hcd + +This patch fixes that. + +Link: https://github.com/lwfinger/rtw88/issues/262 +Signed-off-by: Bitterblue Smith +Acked-by: Ping-Ke Shih +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/9d312b14-0146-4be8-9c50-ef432234db50@gmail.com +--- + drivers/net/wireless/realtek/rtw88/reg.h | 10 ++++ + drivers/net/wireless/realtek/rtw88/usb.c | 68 ++++++++++++++++++++++++ + 2 files changed, 78 insertions(+) + +diff --git a/drivers/net/wireless/realtek/rtw88/reg.h b/drivers/net/wireless/realtek/rtw88/reg.h +index e4d506cf9c33..95a39ae74cd3 100644 +--- a/drivers/net/wireless/realtek/rtw88/reg.h ++++ b/drivers/net/wireless/realtek/rtw88/reg.h +@@ -871,7 +871,17 @@ + + #define REG_USB_MOD 0xf008 + #define REG_USB3_RXITV 0xf050 ++#define REG_USB2_PHY_ADR 0xfe40 ++#define REG_USB2_PHY_DAT 0xfe41 ++#define REG_USB2_PHY_CMD 0xfe42 ++#define BIT_USB2_PHY_CMD_TRG 0x81 + #define REG_USB_HRPWM 0xfe58 ++#define REG_USB3_PHY_ADR 0xff0c ++#define REG_USB3_PHY_DAT_L 0xff0d ++#define REG_USB3_PHY_DAT_H 0xff0e ++#define BIT_USB3_PHY_ADR_WR BIT(7) ++#define BIT_USB3_PHY_ADR_RD BIT(6) ++#define BIT_USB3_PHY_ADR_MASK GENMASK(5, 0) + + #define RF_MODE 0x00 + #define RF_MODOPT 0x01 +diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c +index 1572b61cf877..c4908db4ff0e 100644 +--- a/drivers/net/wireless/realtek/rtw88/usb.c ++++ b/drivers/net/wireless/realtek/rtw88/usb.c +@@ -1128,6 +1128,71 @@ static int rtw_usb_switch_mode(struct rtw_dev *rtwdev) + return rtw_usb_switch_mode_new(rtwdev); + } + ++#define USB_REG_PAGE 0xf4 ++#define USB_PHY_PAGE0 0x9b ++#define USB_PHY_PAGE1 0xbb ++ ++static void rtw_usb_phy_write(struct rtw_dev *rtwdev, u8 addr, u16 data, ++ enum usb_device_speed speed) ++{ ++ if (speed == USB_SPEED_SUPER) { ++ rtw_write8(rtwdev, REG_USB3_PHY_DAT_L, data & 0xff); ++ rtw_write8(rtwdev, REG_USB3_PHY_DAT_H, data >> 8); ++ rtw_write8(rtwdev, REG_USB3_PHY_ADR, addr | BIT_USB3_PHY_ADR_WR); ++ } else if (speed == USB_SPEED_HIGH) { ++ rtw_write8(rtwdev, REG_USB2_PHY_DAT, data); ++ rtw_write8(rtwdev, REG_USB2_PHY_ADR, addr); ++ rtw_write8(rtwdev, REG_USB2_PHY_CMD, BIT_USB2_PHY_CMD_TRG); ++ } ++} ++ ++static void rtw_usb_page_switch(struct rtw_dev *rtwdev, ++ enum usb_device_speed speed, u8 page) ++{ ++ if (speed == USB_SPEED_SUPER) ++ return; ++ ++ rtw_usb_phy_write(rtwdev, USB_REG_PAGE, page, speed); ++} ++ ++static void rtw_usb_phy_cfg(struct rtw_dev *rtwdev, ++ enum usb_device_speed speed) ++{ ++ const struct rtw_intf_phy_para *para = NULL; ++ u16 offset; ++ ++ if (!rtwdev->chip->intf_table) ++ return; ++ ++ if (speed == USB_SPEED_SUPER) ++ para = rtwdev->chip->intf_table->usb3_para; ++ else if (speed == USB_SPEED_HIGH) ++ para = rtwdev->chip->intf_table->usb2_para; ++ ++ if (!para) ++ return; ++ ++ for ( ; para->offset != 0xffff; para++) { ++ if (!(para->cut_mask & BIT(rtwdev->hal.cut_version))) ++ continue; ++ ++ offset = para->offset; ++ ++ if (para->ip_sel == RTW_IP_SEL_MAC) { ++ rtw_write8(rtwdev, offset, para->value); ++ } else { ++ if (offset > 0x100) ++ rtw_usb_page_switch(rtwdev, speed, USB_PHY_PAGE1); ++ else ++ rtw_usb_page_switch(rtwdev, speed, USB_PHY_PAGE0); ++ ++ offset &= 0xff; ++ ++ rtw_usb_phy_write(rtwdev, offset, para->value, speed); ++ } ++ } ++} ++ + int rtw_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) + { + struct rtw_dev *rtwdev; +@@ -1183,6 +1248,9 @@ int rtw_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) + goto err_destroy_rxwq; + } + ++ rtw_usb_phy_cfg(rtwdev, USB_SPEED_HIGH); ++ rtw_usb_phy_cfg(rtwdev, USB_SPEED_SUPER); ++ + ret = rtw_usb_switch_mode(rtwdev); + if (ret) { + /* Not a fail, but we do need to skip rtw_register_hw. */ +-- +2.43.0 + diff --git a/packages/linux/patches/rtlwifi/6.14/0038-wifi-rtw88-Delete-rf_type-member-of-struct-rtw_sta_i.patch b/packages/linux/patches/rtlwifi/6.14/0038-wifi-rtw88-Delete-rf_type-member-of-struct-rtw_sta_i.patch new file mode 100644 index 0000000000..ef76961dcb --- /dev/null +++ b/packages/linux/patches/rtlwifi/6.14/0038-wifi-rtw88-Delete-rf_type-member-of-struct-rtw_sta_i.patch @@ -0,0 +1,68 @@ +From 254af62d5fc0f34512854eabc46591f48d387cbb Mon Sep 17 00:00:00 2001 +From: Bitterblue Smith +Date: Wed, 1 Jan 2025 18:27:35 +0200 +Subject: [PATCH 38/41] wifi: rtw88: Delete rf_type member of struct + rtw_sta_info + +It's not used for anything. + +Signed-off-by: Bitterblue Smith +Acked-by: Ping-Ke Shih +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/b80f7904-c6b4-4d12-a5f9-69ab9b965732@gmail.com +--- + drivers/net/wireless/realtek/rtw88/main.c | 9 ++------- + drivers/net/wireless/realtek/rtw88/main.h | 1 - + 2 files changed, 2 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c +index e91530ed05a0..6993f93c8f06 100644 +--- a/drivers/net/wireless/realtek/rtw88/main.c ++++ b/drivers/net/wireless/realtek/rtw88/main.c +@@ -1217,7 +1217,6 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si, + u8 wireless_set; + u8 bw_mode; + u8 rate_id; +- u8 rf_type = RF_1T1R; + u8 stbc_en = 0; + u8 ldpc_en = 0; + u8 tx_num = 1; +@@ -1302,13 +1301,10 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si, + break; + } + +- if (sta->deflink.vht_cap.vht_supported && ra_mask & 0xffc00000) { ++ if (sta->deflink.vht_cap.vht_supported && ra_mask & 0xffc00000) + tx_num = 2; +- rf_type = RF_2T2R; +- } else if (sta->deflink.ht_cap.ht_supported && ra_mask & 0xfff00000) { ++ else if (sta->deflink.ht_cap.ht_supported && ra_mask & 0xfff00000) + tx_num = 2; +- rf_type = RF_2T2R; +- } + + rate_id = get_rate_id(wireless_set, bw_mode, tx_num); + +@@ -1319,7 +1315,6 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si, + si->bw_mode = bw_mode; + si->stbc_en = stbc_en; + si->ldpc_en = ldpc_en; +- si->rf_type = rf_type; + si->sgi_enable = is_support_sgi; + si->vht_enable = is_vht_enable; + si->ra_mask = ra_mask; +diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h +index 65c7acea41af..6ba9e0dcf9fd 100644 +--- a/drivers/net/wireless/realtek/rtw88/main.h ++++ b/drivers/net/wireless/realtek/rtw88/main.h +@@ -757,7 +757,6 @@ struct rtw_sta_info { + u8 mac_id; + u8 rate_id; + enum rtw_bandwidth bw_mode; +- enum rtw_rf_type rf_type; + u8 stbc_en:2; + u8 ldpc_en:2; + bool sgi_enable; +-- +2.43.0 + diff --git a/packages/linux/patches/rtlwifi/6.14/0041-wifi-rtw88-Add-support-for-LED-blinking.patch b/packages/linux/patches/rtlwifi/6.14/0041-wifi-rtw88-Add-support-for-LED-blinking.patch new file mode 100644 index 0000000000..4a4422eee9 --- /dev/null +++ b/packages/linux/patches/rtlwifi/6.14/0041-wifi-rtw88-Add-support-for-LED-blinking.patch @@ -0,0 +1,451 @@ +From 43b890bc487226f22127d0a328b05ab017cbe9c0 Mon Sep 17 00:00:00 2001 +From: Bitterblue Smith +Date: Wed, 8 Jan 2025 13:41:23 +0200 +Subject: [PATCH 41/41] wifi: rtw88: Add support for LED blinking + +Register a struct led_classdev with the kernel's LED subsystem and +create a throughput-based trigger for it. Then mac80211 makes the LED +blink. + +Tested with Tenda U12 (RTL8812AU), Tenda U9 (RTL8811CU), TP-Link Archer +T2U Nano (RTL8811AU), TP-Link Archer T3U Plus (RTL8812BU), Edimax +EW-7611UCB (RTL8821AU), LM842 (RTL8822CU). + +Also tested with devices which don't have LEDs: the laptop's internal +RTL8822CE and a no-name RTL8723DU. + +Signed-off-by: Bitterblue Smith +Acked-by: Ping-Ke Shih +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/6c43451f-ab2f-4e76-ac6e-ff5a18dd981d@gmail.com +--- + drivers/net/wireless/realtek/rtw88/Makefile | 2 + + drivers/net/wireless/realtek/rtw88/led.c | 73 +++++++++++++++++++ + drivers/net/wireless/realtek/rtw88/led.h | 25 +++++++ + drivers/net/wireless/realtek/rtw88/main.c | 12 ++- + drivers/net/wireless/realtek/rtw88/main.h | 5 ++ + drivers/net/wireless/realtek/rtw88/reg.h | 12 +++ + drivers/net/wireless/realtek/rtw88/rtw8812a.c | 17 +++++ + drivers/net/wireless/realtek/rtw88/rtw8821a.c | 26 +++++++ + drivers/net/wireless/realtek/rtw88/rtw8821c.c | 19 +++++ + drivers/net/wireless/realtek/rtw88/rtw8822b.c | 19 +++++ + drivers/net/wireless/realtek/rtw88/rtw8822c.c | 19 +++++ + 11 files changed, 227 insertions(+), 2 deletions(-) + create mode 100644 drivers/net/wireless/realtek/rtw88/led.c + create mode 100644 drivers/net/wireless/realtek/rtw88/led.h + +diff --git a/drivers/net/wireless/realtek/rtw88/Makefile b/drivers/net/wireless/realtek/rtw88/Makefile +index f0b49f5a8a5a..e8bad9d099a4 100644 +--- a/drivers/net/wireless/realtek/rtw88/Makefile ++++ b/drivers/net/wireless/realtek/rtw88/Makefile +@@ -20,6 +20,8 @@ rtw88_core-y += main.o \ + + rtw88_core-$(CONFIG_PM) += wow.o + ++rtw88_core-$(CONFIG_LEDS_CLASS) += led.o ++ + obj-$(CONFIG_RTW88_8822B) += rtw88_8822b.o + rtw88_8822b-objs := rtw8822b.o rtw8822b_table.o + +diff --git a/drivers/net/wireless/realtek/rtw88/led.c b/drivers/net/wireless/realtek/rtw88/led.c +new file mode 100644 +index 000000000000..25aa6cbaa728 +--- /dev/null ++++ b/drivers/net/wireless/realtek/rtw88/led.c +@@ -0,0 +1,73 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause ++/* Copyright(c) 2025 Realtek Corporation ++ */ ++ ++#include "main.h" ++#include "debug.h" ++#include "led.h" ++ ++static int rtw_led_set_blocking(struct led_classdev *led, ++ enum led_brightness brightness) ++{ ++ struct rtw_dev *rtwdev = container_of(led, struct rtw_dev, led_cdev); ++ ++ rtwdev->chip->ops->led_set(led, brightness); ++ ++ return 0; ++} ++ ++void rtw_led_init(struct rtw_dev *rtwdev) ++{ ++ static const struct ieee80211_tpt_blink rtw_tpt_blink[] = { ++ { .throughput = 0 * 1024, .blink_time = 334 }, ++ { .throughput = 1 * 1024, .blink_time = 260 }, ++ { .throughput = 5 * 1024, .blink_time = 220 }, ++ { .throughput = 10 * 1024, .blink_time = 190 }, ++ { .throughput = 20 * 1024, .blink_time = 170 }, ++ { .throughput = 50 * 1024, .blink_time = 150 }, ++ { .throughput = 70 * 1024, .blink_time = 130 }, ++ { .throughput = 100 * 1024, .blink_time = 110 }, ++ { .throughput = 200 * 1024, .blink_time = 80 }, ++ { .throughput = 300 * 1024, .blink_time = 50 }, ++ }; ++ struct led_classdev *led = &rtwdev->led_cdev; ++ int err; ++ ++ if (!rtwdev->chip->ops->led_set) ++ return; ++ ++ if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_PCIE) ++ led->brightness_set = rtwdev->chip->ops->led_set; ++ else ++ led->brightness_set_blocking = rtw_led_set_blocking; ++ ++ snprintf(rtwdev->led_name, sizeof(rtwdev->led_name), ++ "rtw88-%s", dev_name(rtwdev->dev)); ++ ++ led->name = rtwdev->led_name; ++ led->max_brightness = LED_ON; ++ led->default_trigger = ++ ieee80211_create_tpt_led_trigger(rtwdev->hw, ++ IEEE80211_TPT_LEDTRIG_FL_RADIO, ++ rtw_tpt_blink, ++ ARRAY_SIZE(rtw_tpt_blink)); ++ ++ err = led_classdev_register(rtwdev->dev, led); ++ if (err) { ++ rtw_warn(rtwdev, "Failed to register the LED, error %d\n", err); ++ return; ++ } ++ ++ rtwdev->led_registered = true; ++} ++ ++void rtw_led_deinit(struct rtw_dev *rtwdev) ++{ ++ struct led_classdev *led = &rtwdev->led_cdev; ++ ++ if (!rtwdev->led_registered) ++ return; ++ ++ rtwdev->chip->ops->led_set(led, LED_OFF); ++ led_classdev_unregister(led); ++} +diff --git a/drivers/net/wireless/realtek/rtw88/led.h b/drivers/net/wireless/realtek/rtw88/led.h +new file mode 100644 +index 000000000000..c3bb6fe49b49 +--- /dev/null ++++ b/drivers/net/wireless/realtek/rtw88/led.h +@@ -0,0 +1,25 @@ ++/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ ++/* Copyright(c) 2025 Realtek Corporation ++ */ ++ ++#ifndef __RTW_LED_H ++#define __RTW_LED_H ++ ++#ifdef CONFIG_LEDS_CLASS ++ ++void rtw_led_init(struct rtw_dev *rtwdev); ++void rtw_led_deinit(struct rtw_dev *rtwdev); ++ ++#else ++ ++static inline void rtw_led_init(struct rtw_dev *rtwdev) ++{ ++} ++ ++static inline void rtw_led_deinit(struct rtw_dev *rtwdev) ++{ ++} ++ ++#endif ++ ++#endif +diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c +index 6993f93c8f06..0cee0fd8c0ef 100644 +--- a/drivers/net/wireless/realtek/rtw88/main.c ++++ b/drivers/net/wireless/realtek/rtw88/main.c +@@ -19,6 +19,7 @@ + #include "bf.h" + #include "sar.h" + #include "sdio.h" ++#include "led.h" + + bool rtw_disable_lps_deep_mode; + EXPORT_SYMBOL(rtw_disable_lps_deep_mode); +@@ -2292,16 +2293,18 @@ int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw) + return ret; + } + ++ rtw_led_init(rtwdev); ++ + ret = ieee80211_register_hw(hw); + if (ret) { + rtw_err(rtwdev, "failed to register hw\n"); +- return ret; ++ goto led_deinit; + } + + ret = rtw_regd_hint(rtwdev); + if (ret) { + rtw_err(rtwdev, "failed to hint regd\n"); +- return ret; ++ goto led_deinit; + } + + rtw_debugfs_init(rtwdev); +@@ -2310,6 +2313,10 @@ int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw) + rtwdev->bf_info.bfer_su_cnt = 0; + + return 0; ++ ++led_deinit: ++ rtw_led_deinit(rtwdev); ++ return ret; + } + EXPORT_SYMBOL(rtw_register_hw); + +@@ -2320,6 +2327,7 @@ void rtw_unregister_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw) + ieee80211_unregister_hw(hw); + rtw_unset_supported_band(hw, chip); + rtw_debugfs_deinit(rtwdev); ++ rtw_led_deinit(rtwdev); + } + EXPORT_SYMBOL(rtw_unregister_hw); + +diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h +index 6ba9e0dcf9fd..62cd4c526301 100644 +--- a/drivers/net/wireless/realtek/rtw88/main.h ++++ b/drivers/net/wireless/realtek/rtw88/main.h +@@ -887,6 +887,7 @@ struct rtw_chip_ops { + bool is_tx2_path); + void (*config_txrx_mode)(struct rtw_dev *rtwdev, u8 tx_path, + u8 rx_path, bool is_tx2_path); ++ void (*led_set)(struct led_classdev *led, enum led_brightness brightness); + /* for USB/SDIO only */ + void (*fill_txdesc_checksum)(struct rtw_dev *rtwdev, + struct rtw_tx_pkt_info *pkt_info, +@@ -2097,6 +2098,10 @@ struct rtw_dev { + struct completion fw_scan_density; + bool ap_active; + ++ bool led_registered; ++ char led_name[32]; ++ struct led_classdev led_cdev; ++ + /* hci related data, must be last */ + u8 priv[] __aligned(sizeof(void *)); + }; +diff --git a/drivers/net/wireless/realtek/rtw88/reg.h b/drivers/net/wireless/realtek/rtw88/reg.h +index 95a39ae74cd3..e438405fba56 100644 +--- a/drivers/net/wireless/realtek/rtw88/reg.h ++++ b/drivers/net/wireless/realtek/rtw88/reg.h +@@ -78,7 +78,19 @@ + #define BIT_PAPE_SEL_EN BIT(25) + #define BIT_DPDT_WL_SEL BIT(24) + #define BIT_DPDT_SEL_EN BIT(23) ++#define BIT_GPIO13_14_WL_CTRL_EN BIT(22) ++#define BIT_LED2_SV BIT(19) ++#define BIT_LED2_CM GENMASK(18, 16) ++#define BIT_LED1_SV BIT(11) ++#define BIT_LED1_CM GENMASK(10, 8) ++#define BIT_LED0_SV BIT(3) ++#define BIT_LED0_CM GENMASK(2, 0) ++#define BIT_LED_MODE_SW_CTRL 0 ++#define BIT_LED_MODE_RX 6 ++#define BIT_LED_MODE_TX 4 ++#define BIT_LED_MODE_TRX 2 + #define REG_LEDCFG2 0x004E ++#define REG_GPIO_PIN_CTRL_2 0x0060 + #define REG_PAD_CTRL1 0x0064 + #define BIT_BT_BTG_SEL BIT(31) + #define BIT_PAPE_WLBT_SEL BIT(29) +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8812a.c b/drivers/net/wireless/realtek/rtw88/rtw8812a.c +index 21795286a1a0..f9ba2aa2928a 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8812a.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8812a.c +@@ -868,6 +868,22 @@ static void rtw8812a_pwr_track(struct rtw_dev *rtwdev) + dm_info->pwr_trk_triggered = false; + } + ++static void rtw8812a_led_set(struct led_classdev *led, ++ enum led_brightness brightness) ++{ ++ struct rtw_dev *rtwdev = container_of(led, struct rtw_dev, led_cdev); ++ u8 ledcfg; ++ ++ ledcfg = rtw_read8(rtwdev, REG_LED_CFG); ++ ledcfg &= BIT(6) | BIT(4); ++ ledcfg |= BIT(5); ++ ++ if (brightness == LED_OFF) ++ ledcfg |= BIT(3); ++ ++ rtw_write8(rtwdev, REG_LED_CFG, ledcfg); ++} ++ + static void rtw8812a_fill_txdesc_checksum(struct rtw_dev *rtwdev, + struct rtw_tx_pkt_info *pkt_info, + u8 *txdesc) +@@ -916,6 +932,7 @@ static const struct rtw_chip_ops rtw8812a_ops = { + .config_bfee = NULL, + .set_gid_table = NULL, + .cfg_csi_rate = NULL, ++ .led_set = rtw8812a_led_set, + .fill_txdesc_checksum = rtw8812a_fill_txdesc_checksum, + .coex_set_init = rtw8812a_coex_cfg_init, + .coex_set_ant_switch = NULL, +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821a.c b/drivers/net/wireless/realtek/rtw88/rtw8821a.c +index dafab2af33bc..f68239b07319 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8821a.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8821a.c +@@ -706,6 +706,31 @@ static void rtw8821a_pwr_track(struct rtw_dev *rtwdev) + dm_info->pwr_trk_triggered = false; + } + ++static void rtw8821a_led_set(struct led_classdev *led, ++ enum led_brightness brightness) ++{ ++ struct rtw_dev *rtwdev = container_of(led, struct rtw_dev, led_cdev); ++ u32 gpio8_cfg; ++ u8 ledcfg; ++ ++ if (brightness == LED_OFF) { ++ gpio8_cfg = rtw_read32(rtwdev, REG_GPIO_PIN_CTRL_2); ++ gpio8_cfg &= ~BIT(24); ++ gpio8_cfg |= BIT(16) | BIT(8); ++ rtw_write32(rtwdev, REG_GPIO_PIN_CTRL_2, gpio8_cfg); ++ } else { ++ ledcfg = rtw_read8(rtwdev, REG_LED_CFG + 2); ++ gpio8_cfg = rtw_read32(rtwdev, REG_GPIO_PIN_CTRL_2); ++ ++ ledcfg &= BIT(7) | BIT(6); ++ rtw_write8(rtwdev, REG_LED_CFG + 2, ledcfg); ++ ++ gpio8_cfg &= ~(BIT(24) | BIT(8)); ++ gpio8_cfg |= BIT(16); ++ rtw_write32(rtwdev, REG_GPIO_PIN_CTRL_2, gpio8_cfg); ++ } ++} ++ + static void rtw8821a_fill_txdesc_checksum(struct rtw_dev *rtwdev, + struct rtw_tx_pkt_info *pkt_info, + u8 *txdesc) +@@ -853,6 +878,7 @@ static const struct rtw_chip_ops rtw8821a_ops = { + .config_bfee = NULL, + .set_gid_table = NULL, + .cfg_csi_rate = NULL, ++ .led_set = rtw8821a_led_set, + .fill_txdesc_checksum = rtw8821a_fill_txdesc_checksum, + .coex_set_init = rtw8821a_coex_cfg_init, + .coex_set_ant_switch = rtw8821a_coex_cfg_ant_switch, +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.c b/drivers/net/wireless/realtek/rtw88/rtw8821c.c +index 0270225b9c20..eb7e34c545d0 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8821c.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.c +@@ -1206,6 +1206,24 @@ static void rtw8821c_phy_cck_pd_set(struct rtw_dev *rtwdev, u8 new_lvl) + dm_info->cck_pd_default + new_lvl * 2); + } + ++static void rtw8821c_led_set(struct led_classdev *led, ++ enum led_brightness brightness) ++{ ++ struct rtw_dev *rtwdev = container_of(led, struct rtw_dev, led_cdev); ++ u32 ledcfg; ++ ++ ledcfg = rtw_read32(rtwdev, REG_LED_CFG); ++ u32p_replace_bits(&ledcfg, BIT_LED_MODE_SW_CTRL, BIT_LED2_CM); ++ ledcfg &= ~BIT_GPIO13_14_WL_CTRL_EN; ++ ++ if (brightness == LED_OFF) ++ ledcfg |= BIT_LED2_SV; ++ else ++ ledcfg &= ~BIT_LED2_SV; ++ ++ rtw_write32(rtwdev, REG_LED_CFG, ledcfg); ++} ++ + static void rtw8821c_fill_txdesc_checksum(struct rtw_dev *rtwdev, + struct rtw_tx_pkt_info *pkt_info, + u8 *txdesc) +@@ -1655,6 +1673,7 @@ static const struct rtw_chip_ops rtw8821c_ops = { + .config_bfee = rtw8821c_bf_config_bfee, + .set_gid_table = rtw_bf_set_gid_table, + .cfg_csi_rate = rtw_bf_cfg_csi_rate, ++ .led_set = rtw8821c_led_set, + .fill_txdesc_checksum = rtw8821c_fill_txdesc_checksum, + + .coex_set_init = rtw8821c_coex_cfg_init, +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c +index 739809f4cab5..7f03903ddf4b 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c +@@ -1566,6 +1566,24 @@ static void rtw8822b_adaptivity(struct rtw_dev *rtwdev) + rtw_phy_set_edcca_th(rtwdev, l2h, h2l); + } + ++static void rtw8822b_led_set(struct led_classdev *led, ++ enum led_brightness brightness) ++{ ++ struct rtw_dev *rtwdev = container_of(led, struct rtw_dev, led_cdev); ++ u32 ledcfg; ++ ++ ledcfg = rtw_read32(rtwdev, REG_LED_CFG); ++ u32p_replace_bits(&ledcfg, BIT_LED_MODE_SW_CTRL, BIT_LED2_CM); ++ ledcfg &= ~BIT_GPIO13_14_WL_CTRL_EN; ++ ++ if (brightness == LED_OFF) ++ ledcfg |= BIT_LED2_SV; ++ else ++ ledcfg &= ~BIT_LED2_SV; ++ ++ rtw_write32(rtwdev, REG_LED_CFG, ledcfg); ++} ++ + static void rtw8822b_fill_txdesc_checksum(struct rtw_dev *rtwdev, + struct rtw_tx_pkt_info *pkt_info, + u8 *txdesc) +@@ -2146,6 +2164,7 @@ static const struct rtw_chip_ops rtw8822b_ops = { + .cfg_csi_rate = rtw_bf_cfg_csi_rate, + .adaptivity_init = rtw8822b_adaptivity_init, + .adaptivity = rtw8822b_adaptivity, ++ .led_set = rtw8822b_led_set, + .fill_txdesc_checksum = rtw8822b_fill_txdesc_checksum, + + .coex_set_init = rtw8822b_coex_cfg_init, +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c +index af6b76937f1d..ec362a817f5f 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c +@@ -4537,6 +4537,24 @@ static void rtw8822c_adaptivity(struct rtw_dev *rtwdev) + rtw_phy_set_edcca_th(rtwdev, l2h, h2l); + } + ++static void rtw8822c_led_set(struct led_classdev *led, ++ enum led_brightness brightness) ++{ ++ struct rtw_dev *rtwdev = container_of(led, struct rtw_dev, led_cdev); ++ u32 ledcfg; ++ ++ ledcfg = rtw_read32(rtwdev, REG_LED_CFG); ++ u32p_replace_bits(&ledcfg, BIT_LED_MODE_SW_CTRL, BIT_LED2_CM); ++ ledcfg &= ~BIT_GPIO13_14_WL_CTRL_EN; ++ ++ if (brightness == LED_OFF) ++ ledcfg |= BIT_LED2_SV; ++ else ++ ledcfg &= ~BIT_LED2_SV; ++ ++ rtw_write32(rtwdev, REG_LED_CFG, ledcfg); ++} ++ + static void rtw8822c_fill_txdesc_checksum(struct rtw_dev *rtwdev, + struct rtw_tx_pkt_info *pkt_info, + u8 *txdesc) +@@ -4964,6 +4982,7 @@ static const struct rtw_chip_ops rtw8822c_ops = { + .cfo_track = rtw8822c_cfo_track, + .config_tx_path = rtw8822c_config_tx_path, + .config_txrx_mode = rtw8822c_config_trx_mode, ++ .led_set = rtw8822c_led_set, + .fill_txdesc_checksum = rtw8822c_fill_txdesc_checksum, + + .coex_set_init = rtw8822c_coex_cfg_init, +-- +2.43.0 + diff --git a/packages/linux/patches/rtlwifi/6.15/0043-wifi-rtw88-Don-t-use-static-local-variable-in-rtw882.patch b/packages/linux/patches/rtlwifi/6.15/0043-wifi-rtw88-Don-t-use-static-local-variable-in-rtw882.patch new file mode 100644 index 0000000000..c8022581d6 --- /dev/null +++ b/packages/linux/patches/rtlwifi/6.15/0043-wifi-rtw88-Don-t-use-static-local-variable-in-rtw882.patch @@ -0,0 +1,76 @@ +From 2031f4725fab8be5092d483281e92c9cb7a7bc68 Mon Sep 17 00:00:00 2001 +From: Bitterblue Smith +Date: Sun, 26 Jan 2025 16:04:21 +0200 +Subject: [PATCH 43/43] wifi: rtw88: Don't use static local variable in + rtw8821c_set_tx_power_index_by_rate + +Some users want to plug two identical USB devices at the same time. +This static variable could theoretically cause them to use incorrect +TX power values. + +Move the variable to the caller and pass a pointer to it to +rtw8821c_set_tx_power_index_by_rate(). + +Signed-off-by: Bitterblue Smith +Acked-by: Ping-Ke Shih +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/fe42858c-9b9f-4f03-9aaa-737472c2cd90@gmail.com +--- + drivers/net/wireless/realtek/rtw88/rtw8821c.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.c b/drivers/net/wireless/realtek/rtw88/rtw8821c.c +index eb7e34c545d0..cc152248407c 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8821c.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.c +@@ -680,11 +680,11 @@ static void query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status, + } + + static void +-rtw8821c_set_tx_power_index_by_rate(struct rtw_dev *rtwdev, u8 path, u8 rs) ++rtw8821c_set_tx_power_index_by_rate(struct rtw_dev *rtwdev, u8 path, ++ u8 rs, u32 *phy_pwr_idx) + { + struct rtw_hal *hal = &rtwdev->hal; + static const u32 offset_txagc[2] = {0x1d00, 0x1d80}; +- static u32 phy_pwr_idx; + u8 rate, rate_idx, pwr_index, shift; + int j; + +@@ -692,12 +692,12 @@ rtw8821c_set_tx_power_index_by_rate(struct rtw_dev *rtwdev, u8 path, u8 rs) + rate = rtw_rate_section[rs][j]; + pwr_index = hal->tx_pwr_tbl[path][rate]; + shift = rate & 0x3; +- phy_pwr_idx |= ((u32)pwr_index << (shift * 8)); ++ *phy_pwr_idx |= ((u32)pwr_index << (shift * 8)); + if (shift == 0x3 || rate == DESC_RATEVHT1SS_MCS9) { + rate_idx = rate & 0xfc; + rtw_write32(rtwdev, offset_txagc[path] + rate_idx, +- phy_pwr_idx); +- phy_pwr_idx = 0; ++ *phy_pwr_idx); ++ *phy_pwr_idx = 0; + } + } + } +@@ -705,6 +705,7 @@ rtw8821c_set_tx_power_index_by_rate(struct rtw_dev *rtwdev, u8 path, u8 rs) + static void rtw8821c_set_tx_power_index(struct rtw_dev *rtwdev) + { + struct rtw_hal *hal = &rtwdev->hal; ++ u32 phy_pwr_idx = 0; + int rs, path; + + for (path = 0; path < hal->rf_path_num; path++) { +@@ -712,7 +713,8 @@ static void rtw8821c_set_tx_power_index(struct rtw_dev *rtwdev) + if (rs == RTW_RATE_SECTION_HT_2S || + rs == RTW_RATE_SECTION_VHT_2S) + continue; +- rtw8821c_set_tx_power_index_by_rate(rtwdev, path, rs); ++ rtw8821c_set_tx_power_index_by_rate(rtwdev, path, rs, ++ &phy_pwr_idx); + } + } + } +-- +2.43.0 + diff --git a/packages/linux/sysctl.d/network.conf b/packages/linux/sysctl.d/network.conf new file mode 100644 index 0000000000..0bee2b1773 --- /dev/null +++ b/packages/linux/sysctl.d/network.conf @@ -0,0 +1,5 @@ +net.ipv4.tcp_no_metrics_save=1 + +# generate/use temporary IPv6 addresses +net.ipv6.conf.all.use_tempaddr = 2 +net.ipv6.conf.default.use_tempaddr = 2 diff --git a/packages/linux/sysctl.d/qdisc.conf b/packages/linux/sysctl.d/qdisc.conf new file mode 100644 index 0000000000..ffd7273d37 --- /dev/null +++ b/packages/linux/sysctl.d/qdisc.conf @@ -0,0 +1 @@ +net.core.default_qdisc = fq_codel diff --git a/packages/linux/udev.d/10-bfq-sched.rules b/packages/linux/udev.d/10-bfq-sched.rules new file mode 100644 index 0000000000..a206dadb78 --- /dev/null +++ b/packages/linux/udev.d/10-bfq-sched.rules @@ -0,0 +1 @@ +ACTION=="add|change", KERNEL=="mmcbl*", ATTR{queue/scheduler}="bfq" diff --git a/packages/linux/udev.d/30-disable-wakeup.rules b/packages/linux/udev.d/30-disable-wakeup.rules new file mode 100644 index 0000000000..817e5661e1 --- /dev/null +++ b/packages/linux/udev.d/30-disable-wakeup.rules @@ -0,0 +1,9 @@ +# 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) + +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/linux/udev.d/40-modeswitch.rules b/packages/linux/udev.d/40-modeswitch.rules new file mode 100644 index 0000000000..c200971379 --- /dev/null +++ b/packages/linux/udev.d/40-modeswitch.rules @@ -0,0 +1,17 @@ +# 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'" + +# Realtek RTL8821CU chipset 802.11ac NIC +# initial cdrom mode 0bda:1a2b, wlan mode 0bda:c811 +# Odroid WiFi Module 5B +# initial cdrom mode 0bda:1a2b, wlan mode 0bda:c820 +ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="1a2b", RUN+="/usr/bin/eject '/dev/%k'" + +LABEL="end_modeswitch" diff --git a/packages/multimedia/aom/package.mk b/packages/multimedia/aom/package.mk new file mode 100644 index 0000000000..12cc4be073 --- /dev/null +++ b/packages/multimedia/aom/package.mk @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="aom" +PKG_VERSION="3.12.1" +PKG_SHA256="9e9775180dec7dfd61a79e00bda3809d43891aee6b2e331ff7f26986207ea22e" +PKG_LICENSE="BSD" +PKG_SITE="https://www.webmproject.org" +PKG_URL="https://storage.googleapis.com/aom-releases/libaom-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="AV1 Codec Library" +PKG_BUILD_FLAGS="+pic" + +PKG_CMAKE_OPTS_TARGET="-DENABLE_CCACHE=1 \ + -DENABLE_DOCS=0 \ + -DENABLE_EXAMPLES=0 \ + -DENABLE_TESTS=0 \ + -DENABLE_TOOLS=0" + +#workaround gcc-14 erroring with neon declarations +if [ "${ARCH}" = "arm" ]; then + TARGET_CFLAGS+=" -Wno-implicit-function-declaration" +fi + +if [ "${TARGET_ARCH}" = "x86_64" ]; then + PKG_DEPENDS_TARGET+=" nasm:host" +elif ! target_has_feature neon; then + PKG_CMAKE_OPTS_TARGET+=" -DENABLE_NEON=0 -DENABLE_NEON_ASM=0" +fi diff --git a/packages/multimedia/bento4/package.mk b/packages/multimedia/bento4/package.mk new file mode 100644 index 0000000000..9ba68c640b --- /dev/null +++ b/packages/multimedia/bento4/package.mk @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="bento4" +PKG_VERSION="1.6.0-641-3-Omega" +PKG_SHA256="a9b231b63159b3a4d9e47c5328b476308852bf092ccb9ce98f7cf46a386465ce" +PKG_LICENSE="GPL" +PKG_SITE="https://www.bento4.com" +PKG_URL="https://github.com/xbmc/Bento4/archive/refs/tags/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_DEPENDS_UNPACK="inputstream.adaptive" +PKG_LONGDESC="C++ class library and tools designed to read and write ISO-MP4 files" +PKG_BUILD_FLAGS="+pic" + +PKG_CMAKE_OPTS_TARGET="-DBUILD_APPS=OFF" diff --git a/packages/multimedia/dav1d/package.mk b/packages/multimedia/dav1d/package.mk new file mode 100644 index 0000000000..a7cf219dfd --- /dev/null +++ b/packages/multimedia/dav1d/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="dav1d" +PKG_VERSION="1.5.1" +PKG_SHA256="401813f1f89fa8fd4295805aa5284d9aed9bc7fc1fdbe554af4292f64cbabe21" +PKG_LICENSE="BSD" +PKG_SITE="https://www.videolan.org/projects/dav1d.html" +PKG_URL="https://downloads.videolan.org/pub/videolan/dav1d/${PKG_VERSION}/dav1d-${PKG_VERSION}.tar.xz" +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_docs=false \ + -Denable_examples=false \ + -Denable_tests=false \ + -Denable_tools=false \ + -Dtestdata_tests=false" diff --git a/packages/multimedia/ffmpeg/package.mk b/packages/multimedia/ffmpeg/package.mk new file mode 100644 index 0000000000..cb77c35002 --- /dev/null +++ b/packages/multimedia/ffmpeg/package.mk @@ -0,0 +1,238 @@ +# 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="7.1.1" +PKG_SHA256="733984395e0dbbe5c046abda2dc49a5544e7e0e1e2366bba849222ae9e3a03b1" +PKG_LICENSE="GPL-3.0-only" +PKG_SITE="https://ffmpeg.org" +PKG_URL="http://ffmpeg.org/releases/ffmpeg-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain zlib bzip2 openssl speex libxml2" +PKG_LONGDESC="FFmpeg is a complete, cross-platform solution to record, convert and stream audio and video." +PKG_PATCH_DIRS="libreelec" + +case "${PROJECT}" in + Amlogic) + PKG_VERSION="6dbf87aefd7f491210abe1e043a1c228fa1439a0" + PKG_FFMPEG_BRANCH="test/7.1.1/main" + PKG_SHA256="66aead94c3884c9bc1ff2866f44d87f2f61d106bf203e1c723f83170b7e84297" + PKG_URL="https://github.com/jc-kynesim/rpi-ffmpeg/archive/${PKG_VERSION}.tar.gz" + ;; + RPi) + PKG_FFMPEG_RPI="--disable-mmal --enable-sand" + PKG_PATCH_DIRS+=" rpi" + ;; + *) + PKG_PATCH_DIRS+=" v4l2-request v4l2-drmprime" + case "${PROJECT}" in + Allwinner | Rockchip) + PKG_PATCH_DIRS+=" vf-deinterlace-v4l2m2m" + ;; + esac + ;; +esac + +post_unpack() { + # Fix FFmpeg version + if [ "${PROJECT}" = "Amlogic" ]; then + echo "${PKG_FFMPEG_BRANCH}-${PKG_VERSION:0:7}" >${PKG_BUILD}/VERSION + else + echo "${PKG_VERSION}" >${PKG_BUILD}/RELEASE + fi +} + +# Dependencies +get_graphicdrivers + +PKG_FFMPEG_HWACCEL="--enable-hwaccels" + +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" -o "${DEVICE}" = "RPi4" -o "${DEVICE}" = "RPi5" ]; then + PKG_V4L2_REQUEST="yes" + 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 [ "${DISPLAYSERVER}" != "x11" ]; then + PKG_DEPENDS_TARGET+=" libdrm" + PKG_NEED_UNPACK+=" $(get_pkg_directory libdrm)" + PKG_FFMPEG_VAAPI=" --enable-libdrm" +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} +} + +if [ "${FFMPEG_TESTING}" = "yes" ]; then + PKG_FFMPEG_TESTING="--enable-encoder=wrapped_avframe --enable-muxer=null" + PKG_FFMPEG_TESTING+=" --enable-encoder=rawvideo --enable-muxer=rawvideo" + PKG_FFMPEG_TESTING+=" --enable-muxer=image2 --enable-muxer=md5 --enable-muxer=framemd5" + if [ "${PROJECT}" = "RPi" ]; then + PKG_FFMPEG_TESTING+=" --enable-vout-drm --enable-outdev=vout_drm" + fi +else + PKG_FFMPEG_TESTING="--disable-programs" +fi + +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 \ + --enable-version3 \ + --enable-logging \ + --disable-doc \ + ${PKG_FFMPEG_DEBUG} \ + --enable-pic \ + --pkg-config="${TOOLCHAIN}/bin/pkg-config" \ + --enable-optimizations \ + --disable-extra-warnings \ + --enable-avdevice \ + --enable-avcodec \ + --enable-avformat \ + --enable-swscale \ + --enable-postproc \ + --enable-avfilter \ + --disable-devices \ + --enable-pthreads \ + --enable-network \ + --disable-gnutls --enable-openssl \ + --disable-gray \ + --enable-swscale-alpha \ + --disable-small \ + ${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 \ + --disable-libx264 \ + --disable-libxavs \ + --enable-libxml2 \ + --disable-libxvid \ + --enable-zlib \ + --enable-asm \ + --disable-altivec \ + ${PKG_FFMPEG_FPU} \ + --disable-symver \ + ${PKG_FFMPEG_TESTING} +} + +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 0000000000..ba2c73b8a9 --- /dev/null +++ b/packages/multimedia/ffmpeg/patches/libreelec/ffmpeg-001-libreelec.patch @@ -0,0 +1,73 @@ +From f3b90efacf67fb8e8ed07654a6c3f1bd807002a3 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 546b42e9c622..378231485900 100644 +--- a/libavcodec/libdav1d.c ++++ b/libavcodec/libdav1d.c +@@ -69,6 +69,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; +@@ -424,6 +434,7 @@ static int libdav1d_receive_frame(AVCodecContext *c, AVFrame *frame) + if (res < 0) + goto fail; + ++ 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 74d85efbbd5c9e92e7967d0a0200c41d8ce8a88e 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 52fe2093e7b1..b04934071542 100644 +--- a/libswscale/yuv2rgb.c ++++ b/libswscale/yuv2rgb.c +@@ -573,10 +573,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)); +- + if (c->srcFormat == AV_PIX_FMT_YUV422P) { + switch (c->dstFormat) { + case AV_PIX_FMT_BGR48BE: 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 0000000000..aad99bb03f --- /dev/null +++ b/packages/multimedia/ffmpeg/patches/rpi/ffmpeg-001-rpi.patch @@ -0,0 +1,24037 @@ +diff --git a/configure b/configure +index ffa407d53d55..ecbf267ba6ab 100755 +--- a/configure ++++ b/configure +@@ -202,6 +202,7 @@ External library support: + --disable-bzlib disable bzlib [autodetect] + --disable-coreimage disable Apple CoreImage framework [autodetect] + --enable-chromaprint enable audio fingerprinting with chromaprint [no] ++ --disable-epoxy disable epoxy [autodetect] + --enable-frei0r enable frei0r video filtering [no] + --enable-gcrypt enable gcrypt, needed for rtmp(t)e support + if openssl, librtmp or gmp is not used [no] +@@ -287,6 +288,7 @@ External library support: + --enable-libtorch enable Torch as one DNN backend [no] + --enable-libtwolame enable MP2 encoding via libtwolame [no] + --enable-libuavs3d enable AVS3 decoding via libuavs3d [no] ++ --disable-libudev disable libudev [autodetect] + --enable-libv4l2 enable libv4l2/v4l-utils [no] + --enable-libvidstab enable video stabilization using vid.stab [no] + --enable-libvmaf enable vmaf filter via libvmaf [no] +@@ -353,12 +355,16 @@ External library support: + --enable-libvpl enable Intel oneVPL code via libvpl if libmfx is not used [no] + --enable-libnpp enable Nvidia Performance Primitives-based code [no] + --enable-mmal enable Broadcom Multi-Media Abstraction Layer (Raspberry Pi) via MMAL [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] +@@ -1842,7 +1848,9 @@ EXTERNAL_AUTODETECT_LIBRARY_LIST=" + avfoundation + bzlib + coreimage ++ epoxy + iconv ++ libudev + libxcb + libxcb_shm + libxcb_shape +@@ -1916,6 +1924,7 @@ EXTERNAL_LIBRARY_LIST=" + libcodec2 + libdav1d + libdc1394 ++ libdrm + libflite + libfontconfig + libfreetype +@@ -2025,6 +2034,7 @@ HWACCEL_LIBRARY_LIST=" + mmal + omx + opencl ++ v4l2_request + " + + DOCUMENT_LIST=" +@@ -2042,10 +2052,14 @@ FEATURE_LIST=" + omx_rpi + runtime_cpudetect + safe_bitstream_reader ++ sand + shared + small + static + swscale_alpha ++ v4l2_req_hevc_vx ++ vout_drm ++ vout_egl + " + + # this list should be kept in linking order +@@ -2621,6 +2635,7 @@ CONFIG_EXTRA=" + rtpdec + rtpenc_chain + rv34dsp ++ sand + scene_sad + sinewin + snappy +@@ -3146,6 +3161,7 @@ dxva2_deps="dxva2api_h DXVA2_ConfigPictureDecode ole32 user32" + ffnvcodec_deps_any="libdl LoadLibrary" + mediacodec_deps="android mediandk" + nvdec_deps="ffnvcodec" ++v4l2_request_deps="linux_videodev2_h linux_media_h v4l2_timeval_to_ns libdrm libudev" + vaapi_x11_deps="xlib_x11" + videotoolbox_hwaccel_deps="videotoolbox pthreads" + videotoolbox_hwaccel_extralibs="-framework QuartzCore" +@@ -3200,6 +3216,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_v4l2request_hwaccel_select="hevc_decoder" + hevc_vaapi_hwaccel_deps="vaapi VAPictureParameterBufferHEVC" + hevc_vaapi_hwaccel_select="hevc_decoder" + hevc_vdpau_hwaccel_deps="vdpau VdpPictureInfoHEVC" +@@ -3746,8 +3764,11 @@ 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_egl_outdev_deps="xlib epoxy" + vfwcap_indev_deps="vfw32 vfwcap_defines" + xcbgrab_indev_deps="libxcb" + xcbgrab_indev_suggest="libxcb_shm libxcb_shape libxcb_xfixes" +@@ -3854,6 +3875,7 @@ cropdetect_filter_deps="gpl" + deinterlace_qsv_filter_deps="libmfx" + deinterlace_qsv_filter_select="qsvvpp" + deinterlace_vaapi_filter_deps="vaapi" ++deinterlace_v4l2m2m_filter_deps="libdrm v4l2_m2m" + delogo_filter_deps="gpl" + denoise_vaapi_filter_deps="vaapi" + derain_filter_select="dnn" +@@ -3962,6 +3984,7 @@ transpose_opencl_filter_deps="opencl" + transpose_vaapi_filter_deps="vaapi VAProcPipelineCaps_rotation_flags" + transpose_vt_filter_deps="videotoolbox VTPixelRotationSessionCreate" + transpose_vulkan_filter_deps="vulkan spirv_compiler" ++unsand_filter_select="sand" + unsharp_opencl_filter_deps="opencl" + uspp_filter_deps="gpl avcodec" + vaguedenoiser_filter_deps="gpl" +@@ -3973,6 +3996,7 @@ libvmaf_cuda_filter_deps="libvmaf libvmaf_cuda ffnvcodec" + zmq_filter_deps="libzmq" + zoompan_filter_deps="swscale" + zscale_filter_deps="libzimg const_nan" ++scale_v4l2m2m_filter_deps="libdrm v4l2_m2m" + scale_vaapi_filter_deps="vaapi" + scale_vt_filter_deps="videotoolbox VTPixelTransferSessionCreate" + scale_vulkan_filter_deps="vulkan spirv_compiler" +@@ -6623,6 +6647,12 @@ if enabled xlib; then + disable xlib + fi + ++enabled libudev && ++ check_pkg_config libudev libudev libudev.h udev_new ++ ++enabled epoxy && ++ check_pkg_config epoxy epoxy epoxy/egl.h epoxy_egl_version ++ + check_headers direct.h + check_headers dirent.h + check_headers dxgidebug.h +@@ -7113,8 +7143,16 @@ 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 libudev"; } + enabled vapoursynth && require_headers "vapoursynth/VSScript4.h vapoursynth/VapourSynth4.h" + ++enabled vout_drm && { enabled libdrm || die "ERROR: vout_drm requires --enable-libdrm"; } ++ ++enabled vout_egl && { enabled epoxy || die "ERROR: vout_egl requires epoxy"; } && ++ { enabled xlib || die "ERROR: vout_egl requires xlib"; } + + if enabled gcrypt; then + GCRYPT_CONFIG="${cross_prefix}libgcrypt-config" +@@ -7197,6 +7235,10 @@ 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 hevc_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_HEVC_SLICE;" ++disable v4l2_req_hevc_vx ++ + 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 + +@@ -7709,6 +7751,9 @@ enabled threads || warn \ + "that the libraries from this build MUST NOT be used in a multi-threaded"\ + "environment." + ++# Sub-feature of hevc_v4l2request_hwaccel - can only be set once deps are done ++enabled hevc_v4l2request_hwaccel && disabled hevc_v4l2_request && enable v4l2_req_hevc_vx ++ + case $target_os in + haiku) + disable memalign +diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h +index 733d551fa419..b3a3b00580a2 100644 +--- a/fftools/ffmpeg.h ++++ b/fftools/ffmpeg.h +@@ -715,6 +715,8 @@ extern enum VideoSyncMethod 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; + extern int copy_ts; +diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c +index 2723a0312e92..aee41267fb9c 100644 +--- a/fftools/ffmpeg_dec.c ++++ b/fftools/ffmpeg_dec.c +@@ -392,7 +392,7 @@ static int video_frame_process(DecoderPriv *dp, AVFrame *frame, + } + #endif + +- if (frame->format == dp->hwaccel_pix_fmt) { ++ if (!no_cvt_hw && frame->format == dp->hwaccel_pix_fmt) { + int err = hwaccel_retrieve_data(dp->dec_ctx, frame); + if (err < 0) + return err; +@@ -1333,12 +1333,15 @@ static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat + break; + + if (dp->hwaccel_id == HWACCEL_GENERIC || +- dp->hwaccel_id == HWACCEL_AUTO) { ++ dp->hwaccel_id == HWACCEL_AUTO || ++ no_cvt_hw) { + for (int i = 0;; i++) { + config = avcodec_get_hw_config(s->codec, i); + if (!config) + break; +- if (!(config->methods & ++ if (no_cvt_hw && (config->methods & AV_CODEC_HW_CONFIG_METHOD_INTERNAL)) ++ av_log(s, AV_LOG_DEBUG, "no_cvt_hw so trying pix_fmt %d with codec internal hwaccel\n", *p); ++ else if (!(config->methods & + AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX)) + continue; + if (config->pix_fmt == *p) +diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c +index 38c7676a7e08..727dfceccca4 100644 +--- a/fftools/ffmpeg_filter.c ++++ b/fftools/ffmpeg_filter.c +@@ -2787,8 +2787,8 @@ static int send_frame(FilterGraph *fg, FilterGraphThread *fgt, + break; + case AVMEDIA_TYPE_VIDEO: + if (ifp->format != frame->format || +- ifp->width != frame->width || +- ifp->height != frame->height || ++ ifp->width != av_frame_cropped_width(frame) || ++ ifp->height != av_frame_cropped_height(frame) || + ifp->color_space != frame->colorspace || + ifp->color_range != frame->color_range) + need_reinit |= VIDEO_CHANGED; +@@ -2809,6 +2809,9 @@ static int send_frame(FilterGraph *fg, FilterGraphThread *fgt, + (ifp->hw_frames_ctx && ifp->hw_frames_ctx->data != frame->hw_frames_ctx->data)) + need_reinit |= HWACCEL_CHANGED; + ++ if (no_cvt_hw && fgt->graph) ++ need_reinit = 0; ++ + if (need_reinit) { + ret = ifilter_parameters_from_frame(ifilter, frame); + if (ret < 0) +diff --git a/fftools/ffmpeg_hw.c b/fftools/ffmpeg_hw.c +index 5d4c06c28e85..f39bd29b6e4a 100644 +--- a/fftools/ffmpeg_hw.c ++++ b/fftools/ffmpeg_hw.c +@@ -73,6 +73,8 @@ static char *hw_device_default_name(enum AVHWDeviceType type) + char *name; + size_t index_pos; + int index, index_limit = 1000; ++ if (!type_name) ++ return NULL; + index_pos = strlen(type_name); + name = av_malloc(index_pos + 4); + if (!name) +diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c +index f639a1cf0aab..9670585821e8 100644 +--- a/fftools/ffmpeg_opt.c ++++ b/fftools/ffmpeg_opt.c +@@ -62,6 +62,7 @@ enum VideoSyncMethod video_sync_method = VSYNC_AUTO; + float frame_drop_threshold = 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; +@@ -1574,8 +1575,11 @@ const OptionDef options[] = { + { "benchmark_all", OPT_TYPE_BOOL, OPT_EXPERT, + { &do_benchmark_all }, + "add timings for each task" }, +- { "progress", OPT_TYPE_FUNC, OPT_FUNC_ARG | OPT_EXPERT, +- { .func_arg = opt_progress }, ++ { "no_cvt_hw", OPT_TYPE_BOOL, OPT_EXPERT, ++ { &no_cvt_hw }, ++ "do not auto-convert hw frames to sw" }, ++ { "progress", OPT_TYPE_FUNC, OPT_FUNC_ARG | OPT_EXPERT, ++ { .func_arg = opt_progress }, + "write program-readable progress information", "url" }, + { "stdin", OPT_TYPE_BOOL, OPT_EXPERT, + { &stdin_interaction }, +diff --git a/libavcodec/Makefile b/libavcodec/Makefile +index a4fcce3b4215..2ce880c3db63 100644 +--- a/libavcodec/Makefile ++++ b/libavcodec/Makefile +@@ -175,7 +175,10 @@ OBJS-$(CONFIG_VIDEODSP) += videodsp.o + 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_M2M) += v4l2_m2m.o v4l2_context.o v4l2_buffers.o v4l2_fmt.o\ ++ weak_link.o v4l2_req_dmabufs.o ++OBJS-$(CONFIG_V4L2_REQUEST) += v4l2_req_media.o v4l2_req_pollqueue.o v4l2_req_dmabufs.o\ ++ v4l2_req_devscan.o weak_link.o + OBJS-$(CONFIG_WMA_FREQS) += wma_freqs.o + OBJS-$(CONFIG_WMV2DSP) += wmv2dsp.o + +@@ -1025,6 +1028,8 @@ OBJS-$(CONFIG_HEVC_DXVA2_HWACCEL) += dxva2_hevc.o + OBJS-$(CONFIG_HEVC_D3D12VA_HWACCEL) += dxva2_hevc.o d3d12va_hevc.o + OBJS-$(CONFIG_HEVC_NVDEC_HWACCEL) += nvdec_hevc.o + OBJS-$(CONFIG_HEVC_QSV_HWACCEL) += qsvdec.o ++OBJS-$(CONFIG_HEVC_V4L2REQUEST_HWACCEL) += v4l2_request_hevc.o v4l2_req_decode_q.o v4l2_req_hevc_v4.o ++OBJS-$(CONFIG_V4L2_REQ_HEVC_VX) += v4l2_req_hevc_v1.o v4l2_req_hevc_v2.o v4l2_req_hevc_v3.o + OBJS-$(CONFIG_HEVC_VAAPI_HWACCEL) += vaapi_hevc.o h265_profile_level.o + OBJS-$(CONFIG_HEVC_VDPAU_HWACCEL) += vdpau_hevc.o h265_profile_level.o + OBJS-$(CONFIG_HEVC_VULKAN_HWACCEL) += vulkan_decode.o vulkan_hevc.o +diff --git a/libavcodec/hevc-ctrls-v1.h b/libavcodec/hevc-ctrls-v1.h +new file mode 100644 +index 000000000000..72cbba0953dc +--- /dev/null ++++ b/libavcodec/hevc-ctrls-v1.h +@@ -0,0 +1,229 @@ ++/* 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 sps_max_sub_layers_minus1; ++ ++ __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/hevc-ctrls-v2.h b/libavcodec/hevc-ctrls-v2.h +new file mode 100644 +index 000000000000..7cbbbf055f47 +--- /dev/null ++++ b/libavcodec/hevc-ctrls-v2.h +@@ -0,0 +1,257 @@ ++/* 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_CODEC_BASE + 1008) ++#define V4L2_CID_MPEG_VIDEO_HEVC_PPS (V4L2_CID_CODEC_BASE + 1009) ++#define V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS (V4L2_CID_CODEC_BASE + 1010) ++#define V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX (V4L2_CID_CODEC_BASE + 1011) ++#define V4L2_CID_MPEG_VIDEO_HEVC_DECODE_PARAMS (V4L2_CID_CODEC_BASE + 1012) ++#define V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE (V4L2_CID_CODEC_BASE + 1015) ++#define V4L2_CID_MPEG_VIDEO_HEVC_START_CODE (V4L2_CID_CODEC_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 ++#define V4L2_CTRL_TYPE_HEVC_DECODE_PARAMS 0x0124 ++ ++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 sps_max_sub_layers_minus1; ++ ++ __u64 flags; ++}; ++ ++#define V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT_ENABLED (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) ++#define V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT (1ULL << 19) ++#define V4L2_HEVC_PPS_FLAG_UNIFORM_SPACING (1ULL << 20) ++ ++struct v4l2_ctrl_hevc_pps { ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture parameter set */ ++ __u8 num_extra_slice_header_bits; ++ __u8 num_ref_idx_l0_default_active_minus1; ++ __u8 num_ref_idx_l1_default_active_minus1; ++ __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 ref_idx_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ __u8 ref_idx_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ ++ __u8 padding[5]; ++ ++ __u32 entry_point_offset_minus1[256]; ++ ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Weighted prediction parameter */ ++ struct v4l2_hevc_pred_weight_table pred_weight_table; ++ ++ __u64 flags; ++}; ++ ++#define V4L2_HEVC_DECODE_PARAM_FLAG_IRAP_PIC 0x1 ++#define V4L2_HEVC_DECODE_PARAM_FLAG_IDR_PIC 0x2 ++#define V4L2_HEVC_DECODE_PARAM_FLAG_NO_OUTPUT_OF_PRIOR 0x4 ++ ++struct v4l2_ctrl_hevc_decode_params { ++ __s32 pic_order_cnt_val; ++ __u8 num_active_dpb_entries; ++ struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ __u8 num_poc_st_curr_before; ++ __u8 num_poc_st_curr_after; ++ __u8 num_poc_lt_curr; ++ __u8 poc_st_curr_before[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ __u8 poc_st_curr_after[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ __u8 poc_lt_curr[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ __u64 flags; ++}; ++ ++/* MPEG-class control IDs specific to the Hantro driver as defined by V4L2 */ ++#define V4L2_CID_CODEC_HANTRO_BASE (V4L2_CTRL_CLASS_CODEC | 0x1200) ++/* ++ * V4L2_CID_HANTRO_HEVC_SLICE_HEADER_SKIP - ++ * the number of data (in bits) to skip in the ++ * slice segment header. ++ * If non-IDR, the bits to be skipped go from syntax element "pic_output_flag" ++ * to before syntax element "slice_temporal_mvp_enabled_flag". ++ * If IDR, the skipped bits are just "pic_output_flag" ++ * (separate_colour_plane_flag is not supported). ++ */ ++#define V4L2_CID_HANTRO_HEVC_SLICE_HEADER_SKIP (V4L2_CID_CODEC_HANTRO_BASE + 0) ++ ++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/hevc-ctrls-v3.h b/libavcodec/hevc-ctrls-v3.h +new file mode 100644 +index 000000000000..4e35bd583d58 +--- /dev/null ++++ b/libavcodec/hevc-ctrls-v3.h +@@ -0,0 +1,255 @@ ++/* 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_CODEC_BASE + 1008) ++#define V4L2_CID_MPEG_VIDEO_HEVC_PPS (V4L2_CID_CODEC_BASE + 1009) ++#define V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS (V4L2_CID_CODEC_BASE + 1010) ++#define V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX (V4L2_CID_CODEC_BASE + 1011) ++#define V4L2_CID_MPEG_VIDEO_HEVC_DECODE_PARAMS (V4L2_CID_CODEC_BASE + 1012) ++#define V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE (V4L2_CID_CODEC_BASE + 1015) ++#define V4L2_CID_MPEG_VIDEO_HEVC_START_CODE (V4L2_CID_CODEC_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 ++#define V4L2_CTRL_TYPE_HEVC_DECODE_PARAMS 0x0124 ++ ++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 sps_max_sub_layers_minus1; ++ ++ __u64 flags; ++}; ++ ++#define V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT_ENABLED (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) ++#define V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT (1ULL << 19) ++#define V4L2_HEVC_PPS_FLAG_UNIFORM_SPACING (1ULL << 20) ++ ++struct v4l2_ctrl_hevc_pps { ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture parameter set */ ++ __u8 num_extra_slice_header_bits; ++ __u8 num_ref_idx_l0_default_active_minus1; ++ __u8 num_ref_idx_l1_default_active_minus1; ++ __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_LONG_TERM_REFERENCE 0x01 ++ ++#define V4L2_HEVC_DPB_ENTRIES_NUM_MAX 16 ++ ++struct v4l2_hevc_dpb_entry { ++ __u64 timestamp; ++ __u8 flags; ++ __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 ref_idx_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ __u8 ref_idx_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ ++ __u8 padding[5]; ++ ++ __u32 entry_point_offset_minus1[256]; ++ ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Weighted prediction parameter */ ++ struct v4l2_hevc_pred_weight_table pred_weight_table; ++ ++ __u64 flags; ++}; ++ ++#define V4L2_HEVC_DECODE_PARAM_FLAG_IRAP_PIC 0x1 ++#define V4L2_HEVC_DECODE_PARAM_FLAG_IDR_PIC 0x2 ++#define V4L2_HEVC_DECODE_PARAM_FLAG_NO_OUTPUT_OF_PRIOR 0x4 ++ ++struct v4l2_ctrl_hevc_decode_params { ++ __s32 pic_order_cnt_val; ++ __u8 num_active_dpb_entries; ++ struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ __u8 num_poc_st_curr_before; ++ __u8 num_poc_st_curr_after; ++ __u8 num_poc_lt_curr; ++ __u8 poc_st_curr_before[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ __u8 poc_st_curr_after[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ __u8 poc_lt_curr[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ __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]; ++}; ++ ++/* MPEG-class control IDs specific to the Hantro driver as defined by V4L2 */ ++#define V4L2_CID_CODEC_HANTRO_BASE (V4L2_CTRL_CLASS_CODEC | 0x1200) ++/* ++ * V4L2_CID_HANTRO_HEVC_SLICE_HEADER_SKIP - ++ * the number of data (in bits) to skip in the ++ * slice segment header. ++ * If non-IDR, the bits to be skipped go from syntax element "pic_output_flag" ++ * to before syntax element "slice_temporal_mvp_enabled_flag". ++ * If IDR, the skipped bits are just "pic_output_flag" ++ * (separate_colour_plane_flag is not supported). ++ */ ++#define V4L2_CID_HANTRO_HEVC_SLICE_HEADER_SKIP (V4L2_CID_CODEC_HANTRO_BASE + 0) ++ ++#endif +diff --git a/libavcodec/hevc-ctrls-v4.h b/libavcodec/hevc-ctrls-v4.h +new file mode 100644 +index 000000000000..c02fdbe5a8e9 +--- /dev/null ++++ b/libavcodec/hevc-ctrls-v4.h +@@ -0,0 +1,524 @@ ++/* SPDX-License-Identifier: ((GPL-2.0+ WITH Linux-syscall-note) OR BSD-3-Clause) */ ++/* ++ * Video for Linux Two controls header file ++ * ++ * Copyright (C) 1999-2012 the contributors ++ * ++ * 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. ++ * ++ * Alternatively you can redistribute this file under the terms of the ++ * BSD license as stated below: ++ * ++ * 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 names of its contributors may not 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 ++ * OWNER 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. ++ * ++ * The contents of this header was split off from videodev2.h. All control ++ * definitions should be added to this header, which is included by ++ * videodev2.h. ++ */ ++ ++#ifndef AVCODEC_HEVC_CTRLS_V4_H ++#define AVCODEC_HEVC_CTRLS_V4_H ++ ++#include ++#include ++ ++#ifndef V4L2_CTRL_CLASS_CODEC_STATELESS ++#define V4L2_CTRL_CLASS_CODEC_STATELESS 0x00a40000 /* Stateless codecs controls */ ++#endif ++#ifndef V4L2_CID_CODEC_STATELESS_BASE ++#define V4L2_CID_CODEC_STATELESS_BASE (V4L2_CTRL_CLASS_CODEC_STATELESS | 0x900) ++#endif ++ ++#define V4L2_PIX_FMT_HEVC_SLICE v4l2_fourcc('S', '2', '6', '5') /* HEVC parsed slices */ ++ ++#define V4L2_CID_STATELESS_HEVC_SPS (V4L2_CID_CODEC_STATELESS_BASE + 400) ++#define V4L2_CID_STATELESS_HEVC_PPS (V4L2_CID_CODEC_STATELESS_BASE + 401) ++#define V4L2_CID_STATELESS_HEVC_SLICE_PARAMS (V4L2_CID_CODEC_STATELESS_BASE + 402) ++#define V4L2_CID_STATELESS_HEVC_SCALING_MATRIX (V4L2_CID_CODEC_STATELESS_BASE + 403) ++#define V4L2_CID_STATELESS_HEVC_DECODE_PARAMS (V4L2_CID_CODEC_STATELESS_BASE + 404) ++#define V4L2_CID_STATELESS_HEVC_DECODE_MODE (V4L2_CID_CODEC_STATELESS_BASE + 405) ++#define V4L2_CID_STATELESS_HEVC_START_CODE (V4L2_CID_CODEC_STATELESS_BASE + 406) ++#define V4L2_CID_STATELESS_HEVC_ENTRY_POINT_OFFSETS (V4L2_CID_CODEC_STATELESS_BASE + 407) ++ ++enum v4l2_stateless_hevc_decode_mode { ++ V4L2_STATELESS_HEVC_DECODE_MODE_SLICE_BASED, ++ V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED, ++}; ++ ++enum v4l2_stateless_hevc_start_code { ++ V4L2_STATELESS_HEVC_START_CODE_NONE, ++ V4L2_STATELESS_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) ++ ++/** ++ * struct v4l2_ctrl_hevc_sps - ITU-T Rec. H.265: Sequence parameter set ++ * ++ * @video_parameter_set_id: specifies the value of the ++ * vps_video_parameter_set_id of the active VPS ++ * @seq_parameter_set_id: provides an identifier for the SPS for ++ * reference by other syntax elements ++ * @pic_width_in_luma_samples: specifies the width of each decoded picture ++ * in units of luma samples ++ * @pic_height_in_luma_samples: specifies the height of each decoded picture ++ * in units of luma samples ++ * @bit_depth_luma_minus8: this value plus 8specifies the bit depth of the ++ * samples of the luma array ++ * @bit_depth_chroma_minus8: this value plus 8 specifies the bit depth of the ++ * samples of the chroma arrays ++ * @log2_max_pic_order_cnt_lsb_minus4: this value plus 4 specifies the value of ++ * the variable MaxPicOrderCntLsb ++ * @sps_max_dec_pic_buffering_minus1: this value plus 1 specifies the maximum ++ * required size of the decoded picture ++ * buffer for the codec video sequence ++ * @sps_max_num_reorder_pics: indicates the maximum allowed number of pictures ++ * @sps_max_latency_increase_plus1: not equal to 0 is used to compute the ++ * value of SpsMaxLatencyPictures array ++ * @log2_min_luma_coding_block_size_minus3: plus 3 specifies the minimum ++ * luma coding block size ++ * @log2_diff_max_min_luma_coding_block_size: specifies the difference between ++ * the maximum and minimum luma ++ * coding block size ++ * @log2_min_luma_transform_block_size_minus2: plus 2 specifies the minimum luma ++ * transform block size ++ * @log2_diff_max_min_luma_transform_block_size: specifies the difference between ++ * the maximum and minimum luma ++ * transform block size ++ * @max_transform_hierarchy_depth_inter: specifies the maximum hierarchy ++ * depth for transform units of ++ * coding units coded in inter ++ * prediction mode ++ * @max_transform_hierarchy_depth_intra: specifies the maximum hierarchy ++ * depth for transform units of ++ * coding units coded in intra ++ * prediction mode ++ * @pcm_sample_bit_depth_luma_minus1: this value plus 1 specifies the number of ++ * bits used to represent each of PCM sample ++ * values of the luma component ++ * @pcm_sample_bit_depth_chroma_minus1: this value plus 1 specifies the number ++ * of bits used to represent each of PCM ++ * sample values of the chroma components ++ * @log2_min_pcm_luma_coding_block_size_minus3: this value plus 3 specifies the ++ * minimum size of coding blocks ++ * @log2_diff_max_min_pcm_luma_coding_block_size: specifies the difference between ++ * the maximum and minimum size of ++ * coding blocks ++ * @num_short_term_ref_pic_sets: specifies the number of st_ref_pic_set() ++ * syntax structures included in the SPS ++ * @num_long_term_ref_pics_sps: specifies the number of candidate long-term ++ * reference pictures that are specified in the SPS ++ * @chroma_format_idc: specifies the chroma sampling ++ * @sps_max_sub_layers_minus1: this value plus 1 specifies the maximum number ++ * of temporal sub-layers ++ * @reserved: padding field. Should be zeroed by applications. ++ * @flags: see V4L2_HEVC_SPS_FLAG_{} ++ */ ++struct v4l2_ctrl_hevc_sps { ++ __u8 video_parameter_set_id; ++ __u8 seq_parameter_set_id; ++ __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 sps_max_sub_layers_minus1; ++ ++ __u8 reserved[6]; ++ __u64 flags; ++}; ++ ++#define V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT_ENABLED (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) ++#define V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT (1ULL << 19) ++#define V4L2_HEVC_PPS_FLAG_UNIFORM_SPACING (1ULL << 20) ++ ++/** ++ * struct v4l2_ctrl_hevc_pps - ITU-T Rec. H.265: Picture parameter set ++ * ++ * @pic_parameter_set_id: identifies the PPS for reference by other ++ * syntax elements ++ * @num_extra_slice_header_bits: specifies the number of extra slice header ++ * bits that are present in the slice header RBSP ++ * for coded pictures referring to the PPS. ++ * @num_ref_idx_l0_default_active_minus1: this value plus 1 specifies the ++ * inferred value of num_ref_idx_l0_active_minus1 ++ * @num_ref_idx_l1_default_active_minus1: this value plus 1 specifies the ++ * inferred value of num_ref_idx_l1_active_minus1 ++ * @init_qp_minus26: this value plus 26 specifies the initial value of SliceQp Y for ++ * each slice referring to the PPS ++ * @diff_cu_qp_delta_depth: specifies the difference between the luma coding ++ * tree block size and the minimum luma coding block ++ * size of coding units that convey cu_qp_delta_abs ++ * and cu_qp_delta_sign_flag ++ * @pps_cb_qp_offset: specify the offsets to the luma quantization parameter Cb ++ * @pps_cr_qp_offset: specify the offsets to the luma quantization parameter Cr ++ * @num_tile_columns_minus1: this value plus 1 specifies the number of tile columns ++ * partitioning the picture ++ * @num_tile_rows_minus1: this value plus 1 specifies the number of tile rows partitioning ++ * the picture ++ * @column_width_minus1: this value plus 1 specifies the width of the each tile column in ++ * units of coding tree blocks ++ * @row_height_minus1: this value plus 1 specifies the height of the each tile row in ++ * units of coding tree blocks ++ * @pps_beta_offset_div2: specify the default deblocking parameter offsets for ++ * beta divided by 2 ++ * @pps_tc_offset_div2: specify the default deblocking parameter offsets for tC ++ * divided by 2 ++ * @log2_parallel_merge_level_minus2: this value plus 2 specifies the value of ++ * the variable Log2ParMrgLevel ++ * @reserved: padding field. Should be zeroed by applications. ++ * @flags: see V4L2_HEVC_PPS_FLAG_{} ++ */ ++struct v4l2_ctrl_hevc_pps { ++ __u8 pic_parameter_set_id; ++ __u8 num_extra_slice_header_bits; ++ __u8 num_ref_idx_l0_default_active_minus1; ++ __u8 num_ref_idx_l1_default_active_minus1; ++ __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 reserved; ++ __u64 flags; ++}; ++ ++#define V4L2_HEVC_DPB_ENTRY_LONG_TERM_REFERENCE 0x01 ++ ++#define V4L2_HEVC_SEI_PIC_STRUCT_FRAME 0 ++#define V4L2_HEVC_SEI_PIC_STRUCT_TOP_FIELD 1 ++#define V4L2_HEVC_SEI_PIC_STRUCT_BOTTOM_FIELD 2 ++#define V4L2_HEVC_SEI_PIC_STRUCT_TOP_BOTTOM 3 ++#define V4L2_HEVC_SEI_PIC_STRUCT_BOTTOM_TOP 4 ++#define V4L2_HEVC_SEI_PIC_STRUCT_TOP_BOTTOM_TOP 5 ++#define V4L2_HEVC_SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM 6 ++#define V4L2_HEVC_SEI_PIC_STRUCT_FRAME_DOUBLING 7 ++#define V4L2_HEVC_SEI_PIC_STRUCT_FRAME_TRIPLING 8 ++#define V4L2_HEVC_SEI_PIC_STRUCT_TOP_PAIRED_PREVIOUS_BOTTOM 9 ++#define V4L2_HEVC_SEI_PIC_STRUCT_BOTTOM_PAIRED_PREVIOUS_TOP 10 ++#define V4L2_HEVC_SEI_PIC_STRUCT_TOP_PAIRED_NEXT_BOTTOM 11 ++#define V4L2_HEVC_SEI_PIC_STRUCT_BOTTOM_PAIRED_NEXT_TOP 12 ++ ++#define V4L2_HEVC_DPB_ENTRIES_NUM_MAX 16 ++ ++/** ++ * struct v4l2_hevc_dpb_entry - HEVC decoded picture buffer entry ++ * ++ * @timestamp: timestamp of the V4L2 capture buffer to use as reference. ++ * @flags: long term flag for the reference frame ++ * @field_pic: whether the reference is a field picture or a frame. ++ * @reserved: padding field. Should be zeroed by applications. ++ * @pic_order_cnt_val: the picture order count of the current picture. ++ */ ++struct v4l2_hevc_dpb_entry { ++ __u64 timestamp; ++ __u8 flags; ++ __u8 field_pic; ++ __u16 reserved; ++ __s32 pic_order_cnt_val; ++}; ++ ++/** ++ * struct v4l2_hevc_pred_weight_table - HEVC weighted prediction parameters ++ * ++ * @delta_luma_weight_l0: the difference of the weighting factor applied ++ * to the luma prediction value for list 0 ++ * @luma_offset_l0: the additive offset applied to the luma prediction value ++ * for list 0 ++ * @delta_chroma_weight_l0: the difference of the weighting factor applied ++ * to the chroma prediction values for list 0 ++ * @chroma_offset_l0: the difference of the additive offset applied to ++ * the chroma prediction values for list 0 ++ * @delta_luma_weight_l1: the difference of the weighting factor applied ++ * to the luma prediction value for list 1 ++ * @luma_offset_l1: the additive offset applied to the luma prediction value ++ * for list 1 ++ * @delta_chroma_weight_l1: the difference of the weighting factor applied ++ * to the chroma prediction values for list 1 ++ * @chroma_offset_l1: the difference of the additive offset applied to ++ * the chroma prediction values for list 1 ++ * @luma_log2_weight_denom: the base 2 logarithm of the denominator for ++ * all luma weighting factors ++ * @delta_chroma_log2_weight_denom: the difference of the base 2 logarithm ++ * of the denominator for all chroma ++ * weighting factors ++ */ ++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 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 - HEVC slice parameters ++ * ++ * This control is a dynamically sized 1-dimensional array, ++ * V4L2_CTRL_FLAG_DYNAMIC_ARRAY flag must be set when using it. ++ * ++ * @bit_size: size (in bits) of the current slice data ++ * @data_byte_offset: offset (in bytes) to the video data in the current slice data ++ * @num_entry_point_offsets: specifies the number of entry point offset syntax ++ * elements in the slice header. ++ * @nal_unit_type: specifies the coding type of the slice (B, P or I) ++ * @nuh_temporal_id_plus1: minus 1 specifies a temporal identifier for the NAL unit ++ * @slice_type: see V4L2_HEVC_SLICE_TYPE_{} ++ * @colour_plane_id: specifies the colour plane associated with the current slice ++ * @slice_pic_order_cnt: specifies the picture order count ++ * @num_ref_idx_l0_active_minus1: this value plus 1 specifies the maximum ++ * reference index for reference picture list 0 ++ * that may be used to decode the slice ++ * @num_ref_idx_l1_active_minus1: this value plus 1 specifies the maximum ++ * reference index for reference picture list 1 ++ * that may be used to decode the slice ++ * @collocated_ref_idx: specifies the reference index of the collocated picture used ++ * for temporal motion vector prediction ++ * @five_minus_max_num_merge_cand: specifies the maximum number of merging ++ * motion vector prediction candidates supported in ++ * the slice subtracted from 5 ++ * @slice_qp_delta: specifies the initial value of QpY to be used for the coding ++ * blocks in the slice ++ * @slice_cb_qp_offset: specifies a difference to be added to the value of pps_cb_qp_offset ++ * @slice_cr_qp_offset: specifies a difference to be added to the value of pps_cr_qp_offset ++ * @slice_act_y_qp_offset: screen content extension parameters ++ * @slice_act_cb_qp_offset: screen content extension parameters ++ * @slice_act_cr_qp_offset: screen content extension parameters ++ * @slice_beta_offset_div2: specify the deblocking parameter offsets for beta divided by 2 ++ * @slice_tc_offset_div2: specify the deblocking parameter offsets for tC divided by 2 ++ * @pic_struct: indicates whether a picture should be displayed as a frame or as one or ++ * more fields ++ * @reserved0: padding field. Should be zeroed by applications. ++ * @slice_segment_addr: specifies the address of the first coding tree block in ++ * the slice segment ++ * @ref_idx_l0: the list of L0 reference elements as indices in the DPB ++ * @ref_idx_l1: the list of L1 reference elements as indices in the DPB ++ * @short_term_ref_pic_set_size: specifies the size of short-term reference ++ * pictures set included in the SPS ++ * @long_term_ref_pic_set_size: specifies the size of long-term reference ++ * pictures set include in the SPS ++ * @pred_weight_table: the prediction weight coefficients for inter-picture ++ * prediction ++ * @reserved1: padding field. Should be zeroed by applications. ++ * @flags: see V4L2_HEVC_SLICE_PARAMS_FLAG_{} ++ */ ++struct v4l2_ctrl_hevc_slice_params { ++ __u32 bit_size; ++ __u32 data_byte_offset; ++ __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; ++ __s32 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; ++ ++ __u8 reserved0[3]; ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ ++ __u32 slice_segment_addr; ++ __u8 ref_idx_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ __u8 ref_idx_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ __u16 short_term_ref_pic_set_size; ++ __u16 long_term_ref_pic_set_size; ++ ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Weighted prediction parameter */ ++ struct v4l2_hevc_pred_weight_table pred_weight_table; ++ ++ __u8 reserved1[2]; ++ __u64 flags; ++}; ++ ++#define V4L2_HEVC_DECODE_PARAM_FLAG_IRAP_PIC 0x1 ++#define V4L2_HEVC_DECODE_PARAM_FLAG_IDR_PIC 0x2 ++#define V4L2_HEVC_DECODE_PARAM_FLAG_NO_OUTPUT_OF_PRIOR 0x4 ++ ++/** ++ * struct v4l2_ctrl_hevc_decode_params - HEVC decode parameters ++ * ++ * @pic_order_cnt_val: picture order count ++ * @short_term_ref_pic_set_size: specifies the size of short-term reference ++ * pictures set included in the SPS of the first slice ++ * @long_term_ref_pic_set_size: specifies the size of long-term reference ++ * pictures set include in the SPS of the first slice ++ * @num_active_dpb_entries: the number of entries in dpb ++ * @num_poc_st_curr_before: the number of reference pictures in the short-term ++ * set that come before the current frame ++ * @num_poc_st_curr_after: the number of reference pictures in the short-term ++ * set that come after the current frame ++ * @num_poc_lt_curr: the number of reference pictures in the long-term set ++ * @poc_st_curr_before: provides the index of the short term before references ++ * in DPB array ++ * @poc_st_curr_after: provides the index of the short term after references ++ * in DPB array ++ * @poc_lt_curr: provides the index of the long term references in DPB array ++ * @reserved: padding field. Should be zeroed by applications. ++ * @dpb: the decoded picture buffer, for meta-data about reference frames ++ * @flags: see V4L2_HEVC_DECODE_PARAM_FLAG_{} ++ */ ++struct v4l2_ctrl_hevc_decode_params { ++ __s32 pic_order_cnt_val; ++ __u16 short_term_ref_pic_set_size; ++ __u16 long_term_ref_pic_set_size; ++ __u8 num_active_dpb_entries; ++ __u8 num_poc_st_curr_before; ++ __u8 num_poc_st_curr_after; ++ __u8 num_poc_lt_curr; ++ __u8 poc_st_curr_before[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ __u8 poc_st_curr_after[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ __u8 poc_lt_curr[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ __u8 reserved[4]; ++ struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ __u64 flags; ++}; ++ ++/** ++ * struct v4l2_ctrl_hevc_scaling_matrix - HEVC scaling lists parameters ++ * ++ * @scaling_list_4x4: scaling list is used for the scaling process for ++ * transform coefficients. The values on each scaling ++ * list are expected in raster scan order ++ * @scaling_list_8x8: scaling list is used for the scaling process for ++ * transform coefficients. The values on each scaling ++ * list are expected in raster scan order ++ * @scaling_list_16x16: scaling list is used for the scaling process for ++ * transform coefficients. The values on each scaling ++ * list are expected in raster scan order ++ * @scaling_list_32x32: scaling list is used for the scaling process for ++ * transform coefficients. The values on each scaling ++ * list are expected in raster scan order ++ * @scaling_list_dc_coef_16x16: scaling list is used for the scaling process ++ * for transform coefficients. The values on each ++ * scaling list are expected in raster scan order. ++ * @scaling_list_dc_coef_32x32: scaling list is used for the scaling process ++ * for transform coefficients. The values on each ++ * scaling list are expected in raster scan order. ++ */ ++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/hevc/hevcdec.c b/libavcodec/hevc/hevcdec.c +index 6f0ae1255809..6dd5ecbd5910 100644 +--- a/libavcodec/hevc/hevcdec.c ++++ b/libavcodec/hevc/hevcdec.c +@@ -367,6 +367,19 @@ static void export_stream_params(HEVCContext *s, const HEVCSPS *sps) + else + avctx->color_range = AVCOL_RANGE_MPEG; + ++ if (sps->chroma_format_idc == 1) { ++ avctx->chroma_sample_location = sps->vui.common.chroma_loc_info_present_flag ? ++ sps->vui.common.chroma_sample_loc_type_top_field + 1 : ++ AVCHROMA_LOC_LEFT; ++ } ++ else if (sps->chroma_format_idc == 2 || ++ sps->chroma_format_idc == 3) { ++ avctx->chroma_sample_location = AVCHROMA_LOC_TOPLEFT;; ++ } ++ else { ++ avctx->chroma_sample_location = AVCHROMA_LOC_UNSPECIFIED; ++ } ++ + if (sps->vui.common.colour_description_present_flag) { + avctx->color_primaries = sps->vui.common.colour_primaries; + avctx->color_trc = sps->vui.common.transfer_characteristics; +@@ -528,6 +541,7 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps) + CONFIG_HEVC_D3D11VA_HWACCEL * 2 + \ + CONFIG_HEVC_D3D12VA_HWACCEL + \ + CONFIG_HEVC_NVDEC_HWACCEL + \ ++ CONFIG_HEVC_V4L2REQUEST_HWACCEL + \ + CONFIG_HEVC_VAAPI_HWACCEL + \ + CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL + \ + CONFIG_HEVC_VDPAU_HWACCEL + \ +@@ -562,6 +576,9 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps) + #endif + #if CONFIG_HEVC_VULKAN_HWACCEL + *fmt++ = AV_PIX_FMT_VULKAN; ++#endif ++#if CONFIG_HEVC_V4L2REQUEST_HWACCEL ++ *fmt++ = AV_PIX_FMT_DRM_PRIME; + #endif + break; + case AV_PIX_FMT_YUV420P10: +@@ -589,6 +606,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: +@@ -683,13 +703,16 @@ static int set_sps(HEVCContext *s, HEVCLayerContext *l, const HEVCSPS *sps) + if (!sps) + return 0; + +- ret = pic_arrays_init(l, sps); +- if (ret < 0) +- goto fail; ++ // If hwaccel then we don't need all the s/w decode helper arrays ++ if (!s->avctx->hwaccel) { ++ ret = pic_arrays_init(l, sps); ++ if (ret < 0) ++ goto fail; + +- ff_hevc_pred_init(&s->hpc, sps->bit_depth); +- ff_hevc_dsp_init (&s->hevcdsp, sps->bit_depth); +- ff_videodsp_init (&s->vdsp, sps->bit_depth); ++ ff_hevc_pred_init(&s->hpc, sps->bit_depth); ++ ff_hevc_dsp_init (&s->hevcdsp, sps->bit_depth); ++ ff_videodsp_init (&s->vdsp, sps->bit_depth); ++ } + + l->sps = ff_refstruct_ref_c(sps); + s->vps = ff_refstruct_ref_c(sps->vps); +@@ -3210,11 +3233,13 @@ static int hevc_frame_start(HEVCContext *s, HEVCLayerContext *l, + } + } + +- memset(l->horizontal_bs, 0, l->bs_width * l->bs_height); +- memset(l->vertical_bs, 0, l->bs_width * l->bs_height); +- memset(l->cbf_luma, 0, sps->min_tb_width * sps->min_tb_height); +- memset(l->is_pcm, 0, (sps->min_pu_width + 1) * (sps->min_pu_height + 1)); +- memset(l->tab_slice_address, -1, pic_size_in_ctb * sizeof(*l->tab_slice_address)); ++ if (l->horizontal_bs) { ++ memset(l->horizontal_bs, 0, l->bs_width * l->bs_height); ++ memset(l->vertical_bs, 0, l->bs_width * l->bs_height); ++ memset(l->cbf_luma, 0, sps->min_tb_width * sps->min_tb_height); ++ memset(l->is_pcm, 0, (sps->min_pu_width + 1) * (sps->min_pu_height + 1)); ++ memset(l->tab_slice_address, -1, pic_size_in_ctb * sizeof(*l->tab_slice_address)); ++ } + + if (IS_IDR(s)) + ff_hevc_clear_refs(l); +@@ -3782,8 +3807,13 @@ static int hevc_receive_frame(AVCodecContext *avctx, AVFrame *frame) + } + + ret = decode_nal_units(s, avpkt->data, avpkt->size); +- if (ret < 0) ++ if (ret < 0) { ++ // Ensure that hwaccel knows this frame is over ++ if (FF_HW_HAS_CB(avctx, abort_frame)) ++ FF_HW_SIMPLE_CALL(avctx, abort_frame); ++ + return ret; ++ } + + do_output: + if (ff_container_fifo_read(s->output_fifo, frame) >= 0) { +@@ -3812,8 +3842,10 @@ static int hevc_ref_frame(HEVCFrame *dst, const HEVCFrame *src) + } + + dst->pps = ff_refstruct_ref_c(src->pps); +- dst->tab_mvf = ff_refstruct_ref(src->tab_mvf); +- dst->rpl_tab = ff_refstruct_ref(src->rpl_tab); ++ if (src->tab_mvf) ++ dst->tab_mvf = ff_refstruct_ref(src->tab_mvf); ++ if (src->rpl_tab) ++ dst->rpl_tab = ff_refstruct_ref(src->rpl_tab); + dst->rpl = ff_refstruct_ref(src->rpl); + dst->nb_rpl_elems = src->nb_rpl_elems; + +@@ -4125,6 +4157,9 @@ const FFCodec ff_hevc_decoder = { + #if CONFIG_HEVC_NVDEC_HWACCEL + HWACCEL_NVDEC(hevc), + #endif ++#if CONFIG_HEVC_V4L2REQUEST_HWACCEL ++ HWACCEL_V4L2REQUEST(hevc), ++#endif + #if CONFIG_HEVC_VAAPI_HWACCEL + HWACCEL_VAAPI(hevc), + #endif +diff --git a/libavcodec/hevc/parser.c b/libavcodec/hevc/parser.c +index 16b40e2b10db..cf9830648a78 100644 +--- a/libavcodec/hevc/parser.c ++++ b/libavcodec/hevc/parser.c +@@ -93,6 +93,19 @@ static int hevc_parse_slice_header(AVCodecParserContext *s, H2645NAL *nal, + avctx->profile = sps->ptl.general_ptl.profile_idc; + avctx->level = sps->ptl.general_ptl.level_idc; + ++ if (sps->chroma_format_idc == 1) { ++ avctx->chroma_sample_location = sps->vui.common.chroma_loc_info_present_flag ? ++ sps->vui.common.chroma_sample_loc_type_top_field + 1 : ++ AVCHROMA_LOC_LEFT; ++ } ++ else if (sps->chroma_format_idc == 2 || ++ sps->chroma_format_idc == 3) { ++ avctx->chroma_sample_location = AVCHROMA_LOC_TOPLEFT;; ++ } ++ else { ++ avctx->chroma_sample_location = AVCHROMA_LOC_UNSPECIFIED; ++ } ++ + if (sps->vps->vps_timing_info_present_flag) { + num = sps->vps->vps_num_units_in_tick; + den = sps->vps->vps_time_scale; +diff --git a/libavcodec/hevc/refs.c b/libavcodec/hevc/refs.c +index 6ba667e9f520..fc7197ff2bcb 100644 +--- a/libavcodec/hevc/refs.c ++++ b/libavcodec/hevc/refs.c +@@ -140,16 +140,19 @@ static HEVCFrame *alloc_frame(HEVCContext *s, HEVCLayerContext *l) + goto fail; + frame->nb_rpl_elems = s->pkt.nb_nals; + +- frame->tab_mvf = ff_refstruct_pool_get(l->tab_mvf_pool); +- if (!frame->tab_mvf) +- goto fail; +- +- frame->rpl_tab = ff_refstruct_pool_get(l->rpl_tab_pool); +- if (!frame->rpl_tab) +- goto fail; +- frame->ctb_count = l->sps->ctb_width * l->sps->ctb_height; +- for (j = 0; j < frame->ctb_count; j++) +- frame->rpl_tab[j] = frame->rpl; ++ if (l->tab_mvf_pool) { ++ frame->tab_mvf = ff_refstruct_pool_get(l->tab_mvf_pool); ++ if (!frame->tab_mvf) ++ goto fail; ++ } ++ if (l->rpl_tab_pool) { ++ frame->rpl_tab = ff_refstruct_pool_get(l->rpl_tab_pool); ++ if (!frame->rpl_tab) ++ goto fail; ++ frame->ctb_count = l->sps->ctb_width * l->sps->ctb_height; ++ for (j = 0; j < frame->ctb_count; j++) ++ frame->rpl_tab[j] = frame->rpl; ++ } + + if (s->sei.picture_timing.picture_struct == AV_PICTURE_STRUCTURE_TOP_FIELD) + frame->f->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; +@@ -287,14 +290,17 @@ static int init_slice_rpl(HEVCContext *s) + int ctb_count = frame->ctb_count; + int ctb_addr_ts = s->pps->ctb_addr_rs_to_ts[s->sh.slice_segment_addr]; + int i; ++ RefPicListTab * const rpl = frame->rpl + s->slice_idx; + + if (s->slice_idx >= frame->nb_rpl_elems) + return AVERROR_INVALIDDATA; + +- for (i = ctb_addr_ts; i < ctb_count; i++) +- frame->rpl_tab[i] = frame->rpl + s->slice_idx; ++ if (frame->rpl_tab) { ++ for (i = ctb_addr_ts; i < ctb_count; i++) ++ frame->rpl_tab[i] = rpl; ++ } + +- frame->refPicList = (RefPicList *)frame->rpl_tab[ctb_addr_ts]; ++ frame->refPicList = (RefPicList *)rpl; + + return 0; + } +diff --git a/libavcodec/hwaccel_internal.h b/libavcodec/hwaccel_internal.h +index b0cc22bb6899..d319f2abe1f5 100644 +--- a/libavcodec/hwaccel_internal.h ++++ b/libavcodec/hwaccel_internal.h +@@ -161,6 +161,17 @@ typedef struct FFHWAccel { + * Callback to flush the hwaccel state. + */ + void (*flush)(AVCodecContext *avctx); ++ ++ /** ++ * 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); + } FFHWAccel; + + static inline const FFHWAccel *ffhwaccel(const AVHWAccel *codec) +diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h +index 5171e4c7d735..0b586f760d11 100644 +--- a/libavcodec/hwaccels.h ++++ b/libavcodec/hwaccels.h +@@ -43,6 +43,7 @@ extern const struct FFHWAccel ff_hevc_d3d11va2_hwaccel; + extern const struct FFHWAccel ff_hevc_d3d12va_hwaccel; + extern const struct FFHWAccel ff_hevc_dxva2_hwaccel; + extern const struct FFHWAccel ff_hevc_nvdec_hwaccel; ++extern const struct FFHWAccel ff_hevc_v4l2request_hwaccel; + extern const struct FFHWAccel ff_hevc_vaapi_hwaccel; + extern const struct FFHWAccel ff_hevc_vdpau_hwaccel; + extern const struct FFHWAccel ff_hevc_videotoolbox_hwaccel; +diff --git a/libavcodec/hwconfig.h b/libavcodec/hwconfig.h +index ee29ca631df0..a7cb81aa044f 100644 +--- a/libavcodec/hwconfig.h ++++ b/libavcodec/hwconfig.h +@@ -67,6 +67,8 @@ void ff_hwaccel_uninit(AVCodecContext *avctx); + HW_CONFIG_HWACCEL(1, 1, 0, D3D11, D3D11VA, ff_ ## codec ## _d3d11va2_hwaccel) + #define HWACCEL_NVDEC(codec) \ + HW_CONFIG_HWACCEL(1, 1, 0, CUDA, CUDA, ff_ ## codec ## _nvdec_hwaccel) ++#define HWACCEL_V4L2REQUEST(codec) \ ++ HW_CONFIG_HWACCEL(1, 0, 0, DRM_PRIME, DRM, ff_ ## codec ## _v4l2request_hwaccel) + #define HWACCEL_VAAPI(codec) \ + HW_CONFIG_HWACCEL(1, 1, 1, VAAPI, VAAPI, ff_ ## codec ## _vaapi_hwaccel) + #define HWACCEL_VDPAU(codec) \ +diff --git a/libavcodec/mmaldec.c b/libavcodec/mmaldec.c +index e42591110fec..70cc0ecabcb9 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/raw.c b/libavcodec/raw.c +index b73b80e5fdb1..7ca36ac84975 100644 +--- a/libavcodec/raw.c ++++ b/libavcodec/raw.c +@@ -297,6 +297,12 @@ static const PixelFormatTag raw_pix_fmt_tags[] = { + { 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 8c577006d922..b215577b7548 100644 +--- a/libavcodec/rawenc.c ++++ b/libavcodec/rawenc.c +@@ -24,6 +24,7 @@ + * Raw Video Encoder + */ + ++#include "config.h" + #include "avcodec.h" + #include "codec_internal.h" + #include "encode.h" +@@ -33,6 +34,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) + { +@@ -46,22 +51,114 @@ static av_cold int raw_encode_init(AVCodecContext *avctx) + 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_get_encode_buffer(avctx, pkt, size, 0)) < 0) ++ return ret; ++ ++ dst = pkt->data; ++ ++ av_rpi_sand_to_planar_y8(dst, width, frame->data[0], frame->linesize[0], av_rpi_sand_frame_stride2_y(frame), 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_c(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_get_encode_buffer(avctx, pkt, size, 0)) < 0) ++ return ret; ++ ++ dst = pkt->data; ++ ++ av_rpi_sand_to_planar_y16(dst, width * 2, frame->data[0], frame->linesize[0], av_rpi_sand_frame_stride2_y(frame), 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_c(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_get_encode_buffer(avctx, pkt, size, 0)) < 0) ++ return ret; ++ ++ dst = pkt->data; ++ ++ av_rpi_sand30_to_planar_y16(dst, width * 2, frame->data[0], frame->linesize[0], av_rpi_sand_frame_stride2_y(frame), 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_c(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) ++ const AVFrame *src_frame, int *got_packet) + { +- int ret = av_image_get_buffer_size(frame->format, +- frame->width, frame->height, 1); ++ int ret; ++ AVFrame * frame = NULL; + +- if (ret < 0) ++#if CONFIG_SAND ++ if (av_rpi_is_sand_frame(src_frame)) { ++ ret = av_rpi_is_sand8_frame(src_frame) ? raw_sand8_as_yuv420(avctx, pkt, src_frame) : ++ av_rpi_is_sand16_frame(src_frame) ? raw_sand16_as_yuv420(avctx, pkt, src_frame) : ++ av_rpi_is_sand30_frame(src_frame) ? raw_sand30_as_yuv420(avctx, pkt, src_frame) : -1; ++ *got_packet = (ret == 0); + return ret; ++ } ++#endif ++ ++ if ((frame = av_frame_clone(src_frame)) == NULL) { ++ ret = AVERROR(ENOMEM); ++ goto fail; ++ } ++ ++ if ((ret = av_frame_apply_cropping(frame, AV_FRAME_CROP_UNALIGNED)) < 0) ++ goto fail; ++ ++ ret = av_image_get_buffer_size(frame->format, ++ frame->width, frame->height, 1); ++ if (ret < 0) ++ goto fail; + + if ((ret = ff_get_encode_buffer(avctx, pkt, ret, 0)) < 0) +- return ret; ++ goto fail; + if ((ret = av_image_copy_to_buffer(pkt->data, pkt->size, + (const uint8_t **)frame->data, frame->linesize, + frame->format, + frame->width, frame->height, 1)) < 0) +- return ret; ++ goto fail; + + if(avctx->codec_tag == AV_RL32("yuv2") && ret > 0 && + frame->format == AV_PIX_FMT_YUYV422) { +@@ -77,8 +174,15 @@ static int raw_encode(AVCodecContext *avctx, AVPacket *pkt, + AV_WB64(&pkt->data[8 * x], v << 48 | v >> 16); + } + } ++ pkt->flags |= AV_PKT_FLAG_KEY; ++ av_frame_free(&frame); + *got_packet = 1; + return 0; ++ ++fail: ++ av_frame_free(&frame); ++ *got_packet = 0; ++ return ret; + } + + const FFCodec ff_rawvideo_encoder = { +diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c +index 23474ee1439e..5920463d0a65 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 "config.h" + #include + #include + #include +@@ -28,58 +29,94 @@ + #include + #include + #include "libavcodec/avcodec.h" ++#include "libavcodec/internal.h" ++#include "libavutil/avassert.h" ++#include "libavutil/mem.h" + #include "libavutil/pixdesc.h" +-#include "refstruct.h" ++#include "libavutil/hwcontext.h" + #include "v4l2_context.h" + #include "v4l2_buffers.h" + #include "v4l2_m2m.h" ++#include "v4l2_req_dmabufs.h" ++#include "weak_link.h" ++ ++#if CONFIG_LIBDRM ++#include ++#endif + + #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) ++static inline V4L2m2mContext *ctx_to_m2mctx(const V4L2Context *ctx) + { +- return V4L2_TYPE_IS_OUTPUT(buf->context->type) ? +- container_of(buf->context, V4L2m2mContext, output) : +- container_of(buf->context, V4L2m2mContext, capture); ++ return V4L2_TYPE_IS_OUTPUT(ctx->type) ? ++ container_of(ctx, V4L2m2mContext, output) : ++ container_of(ctx, V4L2m2mContext, capture); + } + +-static inline AVCodecContext *logger(V4L2Buffer *buf) ++static inline V4L2m2mContext *buf_to_m2mctx(const V4L2Buffer * const buf) + { +- return buf_to_m2mctx(buf)->avctx; ++ return ctx_to_m2mctx(buf->context); + } + +-static inline AVRational v4l2_get_timebase(V4L2Buffer *avbuf) ++static inline AVCodecContext *logger(const V4L2Buffer * const buf) + { +- V4L2m2mContext *s = buf_to_m2mctx(avbuf); ++ return buf_to_m2mctx(buf)->avctx; ++} + +- if (s->avctx->pkt_timebase.num) +- return s->avctx->pkt_timebase; +- return s->avctx->time_base; ++static inline AVRational v4l2_get_timebase(const V4L2Buffer * const avbuf) ++{ ++ const V4L2m2mContext *s = buf_to_m2mctx(avbuf); ++ 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 struct timeval tv_from_int(const int64_t t) + { +- int64_t v4l2_pts; ++ return (struct timeval){ ++ .tv_usec = t % USEC_PER_SEC, ++ .tv_sec = t / USEC_PER_SEC ++ }; ++} + +- if (pts == AV_NOPTS_VALUE) +- pts = 0; ++static inline int64_t int_from_tv(const struct timeval t) ++{ ++ return (int64_t)t.tv_sec * USEC_PER_SEC + t.tv_usec; ++} + ++static inline void v4l2_set_pts(V4L2Buffer * const out, const int64_t pts) ++{ + /* convert pts to v4l2 timebase */ +- v4l2_pts = 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; ++ const int64_t v4l2_pts = ++ pts == AV_NOPTS_VALUE ? 0 : ++ av_rescale_q(pts, v4l2_get_timebase(out), v4l2_timebase); ++ out->buf.timestamp = tv_from_int(v4l2_pts); + } + +-static inline int64_t v4l2_get_pts(V4L2Buffer *avbuf) ++static inline int64_t v4l2_get_pts(const V4L2Buffer * const avbuf) + { +- int64_t v4l2_pts; +- ++ const int64_t v4l2_pts = int_from_tv(avbuf->buf.timestamp); ++ return v4l2_pts != 0 ? v4l2_pts : AV_NOPTS_VALUE; ++#if 0 + /* convert pts back to encoder timebase */ +- v4l2_pts = (int64_t)avbuf->buf.timestamp.tv_sec * USEC_PER_SEC + +- avbuf->buf.timestamp.tv_usec; ++ return ++ avbuf->context->no_pts_rescale ? v4l2_pts : ++ v4l2_pts == 0 ? AV_NOPTS_VALUE : ++ av_rescale_q(v4l2_pts, v4l2_timebase, v4l2_get_timebase(avbuf)); ++#endif ++} + +- return 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) +@@ -116,6 +153,105 @@ static enum AVColorPrimaries v4l2_get_color_primaries(V4L2Buffer *buf) + return AVCOL_PRI_UNSPECIFIED; + } + ++static void v4l2_set_color(V4L2Buffer *buf, ++ const enum AVColorPrimaries avcp, ++ const enum AVColorSpace avcs, ++ const enum AVColorTransferCharacteristic avxc) ++{ ++ enum v4l2_ycbcr_encoding ycbcr = V4L2_YCBCR_ENC_DEFAULT; ++ enum v4l2_colorspace cs = V4L2_COLORSPACE_DEFAULT; ++ enum v4l2_xfer_func xfer = V4L2_XFER_FUNC_DEFAULT; ++ ++ switch (avcp) { ++ case AVCOL_PRI_BT709: ++ cs = V4L2_COLORSPACE_REC709; ++ ycbcr = V4L2_YCBCR_ENC_709; ++ break; ++ case AVCOL_PRI_BT470M: ++ cs = V4L2_COLORSPACE_470_SYSTEM_M; ++ ycbcr = V4L2_YCBCR_ENC_601; ++ break; ++ case AVCOL_PRI_BT470BG: ++ cs = V4L2_COLORSPACE_470_SYSTEM_BG; ++ break; ++ case AVCOL_PRI_SMPTE170M: ++ cs = V4L2_COLORSPACE_SMPTE170M; ++ break; ++ case AVCOL_PRI_SMPTE240M: ++ cs = V4L2_COLORSPACE_SMPTE240M; ++ break; ++ case AVCOL_PRI_BT2020: ++ cs = V4L2_COLORSPACE_BT2020; ++ break; ++ case AVCOL_PRI_SMPTE428: ++ case AVCOL_PRI_SMPTE431: ++ case AVCOL_PRI_SMPTE432: ++ case AVCOL_PRI_EBU3213: ++ case AVCOL_PRI_RESERVED: ++ case AVCOL_PRI_FILM: ++ case AVCOL_PRI_UNSPECIFIED: ++ default: ++ break; ++ } ++ ++ switch (avcs) { ++ case AVCOL_SPC_RGB: ++ cs = V4L2_COLORSPACE_SRGB; ++ break; ++ case AVCOL_SPC_BT709: ++ cs = V4L2_COLORSPACE_REC709; ++ break; ++ case AVCOL_SPC_FCC: ++ cs = V4L2_COLORSPACE_470_SYSTEM_M; ++ break; ++ case AVCOL_SPC_BT470BG: ++ cs = V4L2_COLORSPACE_470_SYSTEM_BG; ++ break; ++ case AVCOL_SPC_SMPTE170M: ++ cs = V4L2_COLORSPACE_SMPTE170M; ++ break; ++ case AVCOL_SPC_SMPTE240M: ++ cs = V4L2_COLORSPACE_SMPTE240M; ++ break; ++ case AVCOL_SPC_BT2020_CL: ++ cs = V4L2_COLORSPACE_BT2020; ++ ycbcr = V4L2_YCBCR_ENC_BT2020_CONST_LUM; ++ break; ++ case AVCOL_SPC_BT2020_NCL: ++ cs = V4L2_COLORSPACE_BT2020; ++ break; ++ default: ++ break; ++ } ++ ++ switch (xfer) { ++ case AVCOL_TRC_BT709: ++ xfer = V4L2_XFER_FUNC_709; ++ break; ++ case AVCOL_TRC_IEC61966_2_1: ++ xfer = V4L2_XFER_FUNC_SRGB; ++ break; ++ case AVCOL_TRC_SMPTE240M: ++ xfer = V4L2_XFER_FUNC_SMPTE240M; ++ break; ++ case AVCOL_TRC_SMPTE2084: ++ xfer = V4L2_XFER_FUNC_SMPTE2084; ++ break; ++ default: ++ break; ++ } ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(buf->buf.type)) { ++ buf->context->format.fmt.pix_mp.colorspace = cs; ++ buf->context->format.fmt.pix_mp.ycbcr_enc = ycbcr; ++ buf->context->format.fmt.pix_mp.xfer_func = xfer; ++ } else { ++ buf->context->format.fmt.pix.colorspace = cs; ++ buf->context->format.fmt.pix.ycbcr_enc = ycbcr; ++ buf->context->format.fmt.pix.xfer_func = xfer; ++ } ++} ++ + static enum AVColorRange v4l2_get_color_range(V4L2Buffer *buf) + { + enum v4l2_quantization qt; +@@ -134,6 +270,20 @@ static enum AVColorRange v4l2_get_color_range(V4L2Buffer *buf) + return AVCOL_RANGE_UNSPECIFIED; + } + ++static void v4l2_set_color_range(V4L2Buffer *buf, const enum AVColorRange avcr) ++{ ++ const enum v4l2_quantization q = ++ avcr == AVCOL_RANGE_MPEG ? V4L2_QUANTIZATION_LIM_RANGE : ++ avcr == AVCOL_RANGE_JPEG ? V4L2_QUANTIZATION_FULL_RANGE : ++ V4L2_QUANTIZATION_DEFAULT; ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(buf->buf.type)) { ++ buf->context->format.fmt.pix_mp.quantization = q; ++ } else { ++ buf->context->format.fmt.pix.quantization = q; ++ } ++} ++ + static enum AVColorSpace v4l2_get_color_space(V4L2Buffer *buf) + { + enum v4l2_ycbcr_encoding ycbcr; +@@ -210,71 +360,294 @@ static enum AVColorTransferCharacteristic v4l2_get_color_trc(V4L2Buffer *buf) + return AVCOL_TRC_UNSPECIFIED; + } + +-static void v4l2_free_buffer(void *opaque, uint8_t *unused) ++static int v4l2_buf_is_interlaced(const V4L2Buffer * const buf) + { +- V4L2Buffer* avbuf = opaque; +- V4L2m2mContext *s = buf_to_m2mctx(avbuf); ++ return V4L2_FIELD_IS_INTERLACED(buf->buf.field); ++} + +- if (atomic_fetch_sub(&avbuf->context_refcount, 1) == 1) { +- atomic_fetch_sub_explicit(&s->refcount, 1, memory_order_acq_rel); ++static int v4l2_buf_is_top_first(const V4L2Buffer * const buf) ++{ ++ return buf->buf.field == V4L2_FIELD_INTERLACED_TB; ++} + +- if (s->reinit) { +- if (!atomic_load(&s->refcount)) +- sem_post(&s->refsync); +- } else { +- if (s->draining && V4L2_TYPE_IS_OUTPUT(avbuf->context->type)) { +- /* no need to queue more buffers to the driver */ +- avbuf->status = V4L2BUF_AVAILABLE; +- } +- else if (avbuf->context->streamon) +- ff_v4l2_buffer_enqueue(avbuf); +- } ++static void v4l2_set_interlace(V4L2Buffer * const buf, const int is_interlaced, const int is_tff) ++{ ++ buf->buf.field = !is_interlaced ? V4L2_FIELD_NONE : ++ is_tff ? V4L2_FIELD_INTERLACED_TB : V4L2_FIELD_INTERLACED_BT; ++} + +- ff_refstruct_unref(&avbuf->context_ref); ++static inline void frame_set_interlace(AVFrame* frame, const int is_interlaced, const int is_tff) ++{ ++ if (!is_interlaced) { ++#if FF_API_INTERLACED_FRAME ++FF_DISABLE_DEPRECATION_WARNINGS ++ frame->interlaced_frame = 0; ++ frame->top_field_first = 0; ++FF_ENABLE_DEPRECATION_WARNINGS ++#endif ++ frame->flags &= ~(AV_FRAME_FLAG_TOP_FIELD_FIRST | AV_FRAME_FLAG_INTERLACED); ++ } ++ else { ++#if FF_API_INTERLACED_FRAME ++FF_DISABLE_DEPRECATION_WARNINGS ++ frame->interlaced_frame = 1; ++ frame->top_field_first = !!is_tff; ++FF_ENABLE_DEPRECATION_WARNINGS ++#endif ++ if (is_tff) ++ frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST | AV_FRAME_FLAG_INTERLACED; ++ else ++ frame->flags = (frame->flags & ~AV_FRAME_FLAG_TOP_FIELD_FIRST) | AV_FRAME_FLAG_INTERLACED; + } + } + +-static int v4l2_buf_increase_ref(V4L2Buffer *in) ++static inline int frame_is_interlaced(const AVFrame* const frame) + { +- V4L2m2mContext *s = buf_to_m2mctx(in); ++#if FF_API_INTERLACED_FRAME ++FF_DISABLE_DEPRECATION_WARNINGS ++ return frame->interlaced_frame || (frame->flags & AV_FRAME_FLAG_INTERLACED) != 0; ++FF_ENABLE_DEPRECATION_WARNINGS ++#else ++ return (frame->flags & AV_FRAME_FLAG_INTERLACED) != 0; ++#endif ++} + +- if (in->context_ref) +- atomic_fetch_add(&in->context_refcount, 1); +- else { +- in->context_ref = ff_refstruct_ref(s->self_ref); ++static inline int frame_is_tff(const AVFrame* const frame) ++{ ++#if FF_API_INTERLACED_FRAME ++FF_DISABLE_DEPRECATION_WARNINGS ++ return frame->top_field_first || (frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) != 0; ++FF_ENABLE_DEPRECATION_WARNINGS ++#else ++ return (frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) != 0; ++#endif ++} ++ ++static inline int frame_is_key(const AVFrame* const frame) ++{ ++#if FF_API_FRAME_KEY ++FF_DISABLE_DEPRECATION_WARNINGS ++ return frame->key_frame || (frame->flags & AV_FRAME_FLAG_KEY) != 0; ++FF_ENABLE_DEPRECATION_WARNINGS ++#else ++ return (frame->flags & AV_FRAME_FLAG_KEY) != 0; ++#endif ++} + +- in->context_refcount = 1; ++static inline void frame_set_key(AVFrame* const frame, const int is_key) ++{ ++#if FF_API_FRAME_KEY ++FF_DISABLE_DEPRECATION_WARNINGS ++ frame->key_frame = !!is_key; ++FF_ENABLE_DEPRECATION_WARNINGS ++#endif ++ frame->flags = is_key ? ++ frame->flags | AV_FRAME_FLAG_KEY : ++ frame->flags & ~AV_FRAME_FLAG_KEY; ++} ++ ++#if CONFIG_LIBDRM ++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 = avbuf->plane_info[i].offset; ++ layer->planes[i].pitch = avbuf->plane_info[i].bytesperline; + } + +- in->status = V4L2BUF_RET_USER; +- atomic_fetch_add_explicit(&s->refcount, 1, memory_order_relaxed); ++ switch (avbuf->context->av_pix_fmt) { ++ case AV_PIX_FMT_0BGR: ++ layer->format = DRM_FORMAT_RGBX8888; ++ break; ++ case AV_PIX_FMT_RGB0: ++ layer->format = DRM_FORMAT_XBGR8888; ++ break; ++ case AV_PIX_FMT_0RGB: ++ layer->format = DRM_FORMAT_BGRX8888; ++ break; ++ case AV_PIX_FMT_BGR0: ++ layer->format = DRM_FORMAT_XRGB8888; ++ break; + +- return 0; ++ case AV_PIX_FMT_ABGR: ++ layer->format = DRM_FORMAT_RGBA8888; ++ break; ++ case AV_PIX_FMT_RGBA: ++ layer->format = DRM_FORMAT_ABGR8888; ++ break; ++ case AV_PIX_FMT_ARGB: ++ layer->format = DRM_FORMAT_BGRA8888; ++ break; ++ case AV_PIX_FMT_BGRA: ++ layer->format = DRM_FORMAT_ARGB8888; ++ break; ++ ++ case AV_PIX_FMT_BGR24: ++ layer->format = DRM_FORMAT_BGR888; ++ break; ++ case AV_PIX_FMT_RGB24: ++ layer->format = DRM_FORMAT_RGB888; ++ break; ++ ++ 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; + } ++#endif + +-static int v4l2_buf_to_bufref(V4L2Buffer *in, int plane, AVBufferRef **buf) ++static void v4l2_free_bufref(void *opaque, uint8_t *data) + { +- int ret; ++ AVBufferRef * bufref = (AVBufferRef *)data; ++ V4L2Buffer *avbuf = (V4L2Buffer *)bufref->data; ++ struct V4L2Context *ctx = ff_weak_link_lock(&avbuf->context_wl); + +- if (plane >= in->num_planes) +- return AVERROR(EINVAL); ++ if (ctx != NULL) { ++ // Buffer still attached to context ++ V4L2m2mContext * const s = ctx_to_m2mctx(ctx); + +- /* even though most encoders return 0 in data_offset encoding vp8 does require this value */ +- *buf = av_buffer_create((char *)in->plane_info[plane].mm_addr + in->planes[plane].data_offset, +- in->plane_info[plane].length, v4l2_free_buffer, in, 0); +- if (!*buf) +- return AVERROR(ENOMEM); ++ if (!s->output_drm && avbuf->dmabuf[0] != NULL) { ++ for (unsigned int i = 0; i != avbuf->num_planes; ++i) ++ dmabuf_read_end(avbuf->dmabuf[i]); ++ } + +- ret = v4l2_buf_increase_ref(in); +- if (ret) +- av_buffer_unref(buf); ++ ff_mutex_lock(&ctx->lock); + +- return ret; ++ ff_v4l2_buffer_set_avail(avbuf); ++ avbuf->buf.timestamp.tv_sec = 0; ++ avbuf->buf.timestamp.tv_usec = 0; ++ ++ if (V4L2_TYPE_IS_OUTPUT(ctx->type)) { ++ av_log(logger(avbuf), AV_LOG_DEBUG, "%s: Buffer avail\n", ctx->name); ++ } ++ else if (ctx->streamon) { ++ av_log(logger(avbuf), AV_LOG_DEBUG, "%s: Buffer requeue\n", ctx->name); ++ ff_v4l2_buffer_enqueue(avbuf); // will set to IN_DRIVER ++ } ++ else { ++ av_log(logger(avbuf), AV_LOG_DEBUG, "%s: Buffer freed but streamoff\n", ctx->name); ++ } ++ ++ ff_mutex_unlock(&ctx->lock); ++ } ++ ++ ff_weak_link_unlock(avbuf->context_wl); ++ av_buffer_unref(&bufref); ++} ++ ++static inline uint32_t ff_v4l2_buf_len(const struct v4l2_buffer * b, unsigned int i) ++{ ++ return V4L2_TYPE_IS_MULTIPLANAR(b->type) ? b->m.planes[i].length : b->length; ++} ++ ++static int v4l2_buffer_export_drm(V4L2Buffer* avbuf) ++{ ++ int i, ret; ++ const V4L2m2mContext * const s = buf_to_m2mctx(avbuf); ++ ++ for (i = 0; i < avbuf->num_planes; i++) { ++ int dma_fd = -1; ++ const uint32_t blen = ff_v4l2_buf_len(&avbuf->buf, i); ++ ++ if (s->db_ctl != NULL) { ++ if ((avbuf->dmabuf[i] = dmabuf_alloc(s->db_ctl, blen)) == NULL) ++ return AVERROR(ENOMEM); ++ dma_fd = dmabuf_fd(avbuf->dmabuf[i]); ++ if (V4L2_TYPE_IS_MULTIPLANAR(avbuf->buf.type)) ++ avbuf->buf.m.planes[i].m.fd = dma_fd; ++ else ++ avbuf->buf.m.fd = dma_fd; ++ ++ if (!s->output_drm) ++ avbuf->plane_info[i].mm_addr = dmabuf_map(avbuf->dmabuf[i]); ++ } ++ else { ++ struct v4l2_exportbuffer expbuf; ++ memset(&expbuf, 0, sizeof(expbuf)); ++ ++ expbuf.index = avbuf->buf.index; ++ expbuf.type = avbuf->buf.type; ++ expbuf.plane = i; ++ ++ ret = ioctl(s->fd, VIDIOC_EXPBUF, &expbuf); ++ if (ret < 0) ++ return AVERROR(errno); ++ dma_fd = expbuf.fd; ++ } ++ ++ avbuf->drm_frame.objects[i].size = blen; ++ avbuf->drm_frame.objects[i].fd = dma_fd; ++#if !CONFIG_LIBDRM ++ avbuf->drm_frame.objects[i].format_modifier = 0; ++#else ++ avbuf->drm_frame.objects[i].format_modifier = DRM_FORMAT_MOD_LINEAR; ++#endif ++ } ++ ++ return 0; + } + + static int v4l2_bufref_to_buf(V4L2Buffer *out, int plane, const uint8_t* data, int size, int offset) + { + unsigned int bytesused, length; ++ int rv = 0; + + if (plane >= out->num_planes) + return AVERROR(EINVAL); +@@ -282,32 +655,65 @@ static int v4l2_bufref_to_buf(V4L2Buffer *out, int plane, const uint8_t* data, i + length = out->plane_info[plane].length; + bytesused = FFMIN(size+offset, length); + +- 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; ++ if (size > length - offset) { ++ size = length - offset; ++ rv = AVERROR(ENOMEM); + } + +- return 0; ++ memcpy((uint8_t*)out->plane_info[plane].mm_addr+offset, data, size); ++ ++ set_buf_length(out, plane, bytesused, length); ++ ++ return rv; ++} ++ ++static AVBufferRef * wrap_avbuf(V4L2Buffer * const avbuf) ++{ ++ AVBufferRef * bufref = av_buffer_ref(avbuf->context->bufrefs[avbuf->buf.index]); ++ AVBufferRef * newbuf; ++ ++ if (!bufref) ++ return NULL; ++ ++ newbuf = av_buffer_create((uint8_t *)bufref, sizeof(*bufref), v4l2_free_bufref, NULL, 0); ++ if (newbuf == NULL) ++ av_buffer_unref(&bufref); ++ ++ avbuf->status = V4L2BUF_RET_USER; ++ return newbuf; + } + + static int v4l2_buffer_buf_to_swframe(AVFrame *frame, V4L2Buffer *avbuf) + { +- int i, ret; ++ int i; + + 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 (ret) +- return ret; ++ frame->buf[0] = wrap_avbuf(avbuf); ++ if (frame->buf[0] == NULL) ++ return AVERROR(ENOMEM); ++ ++ if (buf_to_m2mctx(avbuf)->output_drm) { ++#if !CONFIG_LIBDRM ++ return AVERROR_OPTION_NOT_FOUND; ++#else ++ /* 1. get references to the actual data */ ++ const int rv = ff_v4l2_context_frames_set(avbuf->context); ++ if (rv != 0) ++ return rv; ++ ++ 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); ++ return 0; ++#endif ++ } ++ + ++ /* 1. get references to the actual data */ ++ for (i = 0; i < avbuf->num_planes; i++) { ++ frame->data[i] = (uint8_t *)avbuf->plane_info[i].mm_addr + avbuf->planes[i].data_offset; + frame->linesize[i] = avbuf->plane_info[i].bytesperline; +- frame->data[i] = frame->buf[i]->data; + } + + /* fixup special cases */ +@@ -316,88 +722,152 @@ static int v4l2_buffer_buf_to_swframe(AVFrame *frame, V4L2Buffer *avbuf) + case AV_PIX_FMT_NV21: + if (avbuf->num_planes > 1) + break; +- frame->linesize[1] = avbuf->plane_info[0].bytesperline; +- frame->data[1] = frame->buf[0]->data + avbuf->plane_info[0].bytesperline * avbuf->context->format.fmt.pix_mp.height; ++ frame->linesize[1] = frame->linesize[0]; ++ frame->data[1] = frame->data[0] + frame->linesize[0] * ff_v4l2_get_format_height(&avbuf->context->format); + break; + + case AV_PIX_FMT_YUV420P: + if (avbuf->num_planes > 1) + break; +- frame->linesize[1] = avbuf->plane_info[0].bytesperline >> 1; +- frame->linesize[2] = avbuf->plane_info[0].bytesperline >> 1; +- frame->data[1] = frame->buf[0]->data + avbuf->plane_info[0].bytesperline * avbuf->context->format.fmt.pix_mp.height; +- frame->data[2] = frame->data[1] + ((avbuf->plane_info[0].bytesperline * avbuf->context->format.fmt.pix_mp.height) >> 2); ++ frame->linesize[1] = frame->linesize[0] / 2; ++ frame->linesize[2] = frame->linesize[1]; ++ frame->data[1] = frame->data[0] + frame->linesize[0] * ff_v4l2_get_format_height(&avbuf->context->format); ++ frame->data[2] = frame->data[1] + frame->linesize[1] * ff_v4l2_get_format_height(&avbuf->context->format) / 2; + break; + + default: + break; + } + ++ if (avbuf->dmabuf[0] != NULL) { ++ for (unsigned int i = 0; i != avbuf->num_planes; ++i) ++ dmabuf_read_start(avbuf->dmabuf[i]); ++ } ++ ++ return 0; ++} ++ ++static void cpy_2d(uint8_t * dst, int dst_stride, const uint8_t * src, int src_stride, int w, int h) ++{ ++ 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)); ++} ++ ++static int v4l2_buffer_primeframe_to_buf(const AVFrame *frame, V4L2Buffer *out) ++{ ++ const AVDRMFrameDescriptor *const src = (const AVDRMFrameDescriptor *)frame->data[0]; ++ ++ if (frame->format != AV_PIX_FMT_DRM_PRIME || !src) ++ return AVERROR(EINVAL); ++ ++ av_assert0(out->buf.memory == V4L2_MEMORY_DMABUF); ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(out->buf.type)) { ++ // Only currently cope with single buffer types ++ if (out->buf.length != 1) ++ return AVERROR_PATCHWELCOME; ++ if (src->nb_objects != 1) ++ return AVERROR(EINVAL); ++ ++ out->planes[0].m.fd = src->objects[0].fd; ++ } ++ else { ++ if (src->nb_objects != 1) ++ return AVERROR(EINVAL); ++ ++ out->buf.m.fd = src->objects[0].fd; ++ } ++ ++ // No need to copy src AVDescriptor and if we did then we may confuse ++ // fd close on free ++ out->ref_buf = av_buffer_ref(frame->buf[0]); ++ + return 0; + } + + static int v4l2_buffer_swframe_to_buf(const AVFrame *frame, V4L2Buffer *out) + { +- 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 (!is_planar_format) { +- const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format); +- int planes_nb = 0; +- int offset = 0; +- +- for (i = 0; i < desc->nb_components; i++) +- planes_nb = FFMAX(planes_nb, desc->comp[i].plane + 1); +- +- for (i = 0; i < planes_nb; i++) { +- int size, h = height; +- if (i == 1 || i == 2) { ++ int i; ++ int num_planes = 0; ++ int pel_strides[4] = {0}; ++ ++ 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 != 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); +- 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 %u > buffer size %zu\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); +- 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; + } + +@@ -407,16 +877,31 @@ static int v4l2_buffer_swframe_to_buf(const AVFrame *frame, V4L2Buffer *out) + * + ******************************************************************************/ + +-int ff_v4l2_buffer_avframe_to_buf(const AVFrame *frame, V4L2Buffer *out) ++int ff_v4l2_buffer_avframe_to_buf(const AVFrame *frame, V4L2Buffer *out, const int64_t track_ts) + { +- v4l2_set_pts(out, frame->pts); +- +- return v4l2_buffer_swframe_to_buf(frame, out); ++ out->buf.flags = frame_is_key(frame) ? ++ (out->buf.flags | V4L2_BUF_FLAG_KEYFRAME) : ++ (out->buf.flags & ~V4L2_BUF_FLAG_KEYFRAME); ++ // Beware that colour info is held in format rather than the actual ++ // v4l2 buffer struct so this may not be as useful as you might hope ++ v4l2_set_color(out, frame->color_primaries, frame->colorspace, frame->color_trc); ++ v4l2_set_color_range(out, frame->color_range); ++ // PTS & interlace are buffer vars ++ if (track_ts) ++ out->buf.timestamp = tv_from_int(track_ts); ++ else ++ v4l2_set_pts(out, frame->pts); ++ v4l2_set_interlace(out, frame_is_interlaced(frame), frame_is_tff(frame)); ++ ++ return frame->format == AV_PIX_FMT_DRM_PRIME ? ++ v4l2_buffer_primeframe_to_buf(frame, out) : ++ v4l2_buffer_swframe_to_buf(frame, out); + } + + int ff_v4l2_buffer_buf_to_avframe(AVFrame *frame, V4L2Buffer *avbuf) + { + int ret; ++ V4L2Context * const ctx = avbuf->context; + + av_frame_unref(frame); + +@@ -426,19 +911,32 @@ int ff_v4l2_buffer_buf_to_avframe(AVFrame *frame, V4L2Buffer *avbuf) + return ret; + + /* 2. get frame information */ +- if (avbuf->buf.flags & V4L2_BUF_FLAG_KEYFRAME) +- frame->flags |= AV_FRAME_FLAG_KEY; ++ frame_set_key(frame, avbuf->buf.flags & V4L2_BUF_FLAG_KEYFRAME); ++ frame->pict_type = (avbuf->buf.flags & V4L2_BUF_FLAG_KEYFRAME) != 0 ? AV_PICTURE_TYPE_I : ++ (avbuf->buf.flags & V4L2_BUF_FLAG_PFRAME) != 0 ? AV_PICTURE_TYPE_P : ++ (avbuf->buf.flags & V4L2_BUF_FLAG_BFRAME) != 0 ? AV_PICTURE_TYPE_B : ++ AV_PICTURE_TYPE_NONE; + frame->color_primaries = v4l2_get_color_primaries(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->pkt_dts = AV_NOPTS_VALUE; ++ frame_set_interlace(frame, v4l2_buf_is_interlaced(avbuf), v4l2_buf_is_top_first(avbuf)); + + /* these values are updated also during re-init in v4l2_process_driver_event */ +- frame->height = avbuf->context->height; +- frame->width = avbuf->context->width; +- frame->sample_aspect_ratio = avbuf->context->sample_aspect_ratio; ++ frame->height = ctx->height; ++ frame->width = ctx->width; ++ frame->sample_aspect_ratio = ctx->sample_aspect_ratio; ++ ++ if (ctx->selection.height && ctx->selection.width) { ++ frame->crop_left = ctx->selection.left < frame->width ? ctx->selection.left : 0; ++ frame->crop_top = ctx->selection.top < frame->height ? ctx->selection.top : 0; ++ frame->crop_right = ctx->selection.left + ctx->selection.width < frame->width ? ++ frame->width - (ctx->selection.left + ctx->selection.width) : 0; ++ frame->crop_bottom = ctx->selection.top + ctx->selection.height < frame->height ? ++ frame->height - (ctx->selection.top + ctx->selection.height) : 0; ++ } + + /* 3. report errors upstream */ + if (avbuf->buf.flags & V4L2_BUF_FLAG_ERROR) { +@@ -451,15 +949,15 @@ int ff_v4l2_buffer_buf_to_avframe(AVFrame *frame, V4L2Buffer *avbuf) + + int ff_v4l2_buffer_buf_to_avpkt(AVPacket *pkt, V4L2Buffer *avbuf) + { +- int ret; +- + av_packet_unref(pkt); +- ret = v4l2_buf_to_bufref(avbuf, 0, &pkt->buf); +- if (ret) +- return ret; ++ ++ pkt->buf = wrap_avbuf(avbuf); ++ if (pkt->buf == NULL) ++ return AVERROR(ENOMEM); + + pkt->size = V4L2_TYPE_IS_MULTIPLANAR(avbuf->buf.type) ? avbuf->buf.m.planes[0].bytesused : avbuf->buf.bytesused; +- pkt->data = pkt->buf->data; ++ pkt->data = (uint8_t*)avbuf->plane_info[0].mm_addr + avbuf->planes[0].data_offset; ++ pkt->flags = 0; + + if (avbuf->buf.flags & V4L2_BUF_FLAG_KEYFRAME) + pkt->flags |= AV_PKT_FLAG_KEY; +@@ -474,39 +972,108 @@ int ff_v4l2_buffer_buf_to_avpkt(AVPacket *pkt, V4L2Buffer *avbuf) + return 0; + } + +-int ff_v4l2_buffer_avpkt_to_buf(const AVPacket *pkt, V4L2Buffer *out) ++int ff_v4l2_buffer_avpkt_to_buf_ext(const AVPacket * const pkt, V4L2Buffer * const out, ++ const void *extdata, size_t extlen, ++ const int64_t timestamp) + { + int ret; + +- ret = v4l2_bufref_to_buf(out, 0, pkt->data, pkt->size, 0); +- if (ret) ++ 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 && ret != AVERROR(ENOMEM)) + return ret; + +- v4l2_set_pts(out, pkt->pts); ++ if (timestamp) ++ out->buf.timestamp = tv_from_int(timestamp); ++ else ++ v4l2_set_pts(out, pkt->pts); + +- if (pkt->flags & AV_PKT_FLAG_KEY) +- out->flags = V4L2_BUF_FLAG_KEYFRAME; ++ out->buf.flags = (pkt->flags & AV_PKT_FLAG_KEY) != 0 ? ++ (out->buf.flags | V4L2_BUF_FLAG_KEYFRAME) : ++ (out->buf.flags & ~V4L2_BUF_FLAG_KEYFRAME); + +- return 0; ++ return ret; ++} ++ ++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); ++} ++ ++ ++static void v4l2_buffer_buffer_free(void *opaque, uint8_t *data) ++{ ++ V4L2Buffer * const avbuf = (V4L2Buffer *)data; ++ int i; ++ ++ for (i = 0; i != FF_ARRAY_ELEMS(avbuf->plane_info); ++i) { ++ struct V4L2Plane_info *p = avbuf->plane_info + i; ++ if (p->mm_addr != NULL) ++ munmap(p->mm_addr, p->length); ++ } ++ ++ if (avbuf->dmabuf[0] == NULL) { ++ for (i = 0; i != FF_ARRAY_ELEMS(avbuf->drm_frame.objects); ++i) { ++ if (avbuf->drm_frame.objects[i].fd != -1) ++ close(avbuf->drm_frame.objects[i].fd); ++ } ++ } ++ else { ++ for (i = 0; i != FF_ARRAY_ELEMS(avbuf->dmabuf); ++i) { ++ dmabuf_free(avbuf->dmabuf[i]); ++ } ++ } ++ ++ av_buffer_unref(&avbuf->ref_buf); ++ ++ ff_weak_link_unref(&avbuf->context_wl); ++ ++ av_free(avbuf); + } + +-int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index) ++ ++int ff_v4l2_buffer_initialize(AVBufferRef ** pbufref, int index, V4L2Context *ctx, enum v4l2_memory mem) + { +- V4L2Context *ctx = avbuf->context; + int ret, i; ++ V4L2Buffer * const avbuf = av_mallocz(sizeof(*avbuf)); ++ AVBufferRef * bufref; ++ V4L2m2mContext * const s = ctx_to_m2mctx(ctx); ++ int want_mmap; ++ ++ *pbufref = NULL; ++ if (avbuf == NULL) ++ return AVERROR(ENOMEM); + +- avbuf->buf.memory = V4L2_MEMORY_MMAP; ++ bufref = av_buffer_create((uint8_t*)avbuf, sizeof(*avbuf), v4l2_buffer_buffer_free, NULL, 0); ++ if (bufref == NULL) { ++ av_free(avbuf); ++ return AVERROR(ENOMEM); ++ } ++ ++ avbuf->context = ctx; ++ avbuf->buf.memory = mem; + avbuf->buf.type = ctx->type; + avbuf->buf.index = index; + ++ for (i = 0; i != FF_ARRAY_ELEMS(avbuf->drm_frame.objects); ++i) { ++ avbuf->drm_frame.objects[i].fd = -1; ++ } ++ ++ avbuf->context_wl = ff_weak_link_ref(ctx->wl_master); ++ + if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) { + avbuf->buf.length = VIDEO_MAX_PLANES; + avbuf->buf.m.planes = avbuf->planes; + } + +- ret = ioctl(buf_to_m2mctx(avbuf)->fd, VIDIOC_QUERYBUF, &avbuf->buf); ++ ret = ioctl(s->fd, VIDIOC_QUERYBUF, &avbuf->buf); + if (ret < 0) +- return AVERROR(errno); ++ goto fail; + + if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) { + avbuf->num_planes = 0; +@@ -518,33 +1085,41 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index) + } else + avbuf->num_planes = 1; + +- for (i = 0; i < avbuf->num_planes; i++) { ++ want_mmap = avbuf->buf.memory == V4L2_MEMORY_MMAP && ++ (V4L2_TYPE_IS_OUTPUT(ctx->type) || !buf_to_m2mctx(avbuf)->output_drm); + ++ for (i = 0; i < avbuf->num_planes; i++) { + avbuf->plane_info[i].bytesperline = V4L2_TYPE_IS_MULTIPLANAR(ctx->type) ? + ctx->format.fmt.pix_mp.plane_fmt[i].bytesperline : + ctx->format.fmt.pix.bytesperline; + + 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); ++ avbuf->plane_info[i].offset = avbuf->buf.m.planes[i].data_offset; ++ ++ if (want_mmap) ++ 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); ++ avbuf->plane_info[i].offset = 0; ++ ++ if (want_mmap) ++ 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) +- return AVERROR(ENOMEM); ++ if (avbuf->plane_info[i].mm_addr == MAP_FAILED) { ++ avbuf->plane_info[i].mm_addr = NULL; ++ ret = AVERROR(ENOMEM); ++ goto fail; ++ } + } + + 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; +@@ -554,20 +1129,52 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index) + avbuf->buf.length = avbuf->planes[0].length; + } + +- return ff_v4l2_buffer_enqueue(avbuf); ++ if (V4L2_TYPE_IS_CAPTURE(ctx->type) && !want_mmap) { ++ // export_drm does dmabuf alloc if we aren't using v4l2 alloc ++ ret = v4l2_buffer_export_drm(avbuf); ++ if (ret) { ++ av_log(logger(avbuf), AV_LOG_ERROR, "Failed to get exported drm handles\n"); ++ goto fail; ++ } ++ } ++ ++ *pbufref = bufref; ++ return 0; ++ ++fail: ++ av_buffer_unref(&bufref); ++ return ret; + } + + int ff_v4l2_buffer_enqueue(V4L2Buffer* avbuf) + { + int ret; ++ int qc; + +- avbuf->buf.flags = avbuf->flags; ++ if (avbuf->buf.timestamp.tv_sec || avbuf->buf.timestamp.tv_usec) { ++ av_log(logger(avbuf), AV_LOG_DEBUG, "--- %s pre VIDIOC_QBUF: index %d, ts=%ld.%06ld count=%d\n", ++ avbuf->context->name, avbuf->buf.index, ++ avbuf->buf.timestamp.tv_sec, avbuf->buf.timestamp.tv_usec, ++ avbuf->context->q_count); ++ } + + ret = ioctl(buf_to_m2mctx(avbuf)->fd, VIDIOC_QBUF, &avbuf->buf); +- if (ret < 0) +- return AVERROR(errno); ++ if (ret < 0) { ++ int err = errno; ++ av_log(logger(avbuf), AV_LOG_ERROR, "--- %s VIDIOC_QBUF: index %d FAIL err %d (%s)\n", ++ avbuf->context->name, avbuf->buf.index, ++ err, strerror(err)); ++ return AVERROR(err); ++ } + ++ // Lock not wanted - if called from buffer free then lock already obtained ++ qc = atomic_fetch_add(&avbuf->context->q_count, 1) + 1; + avbuf->status = V4L2BUF_IN_DRIVER; ++ pthread_cond_broadcast(&avbuf->context->cond); ++ ++ av_log(logger(avbuf), AV_LOG_DEBUG, "--- %s VIDIOC_QBUF: index %d, ts=%ld.%06ld count=%d\n", ++ avbuf->context->name, avbuf->buf.index, ++ avbuf->buf.timestamp.tv_sec, avbuf->buf.timestamp.tv_usec, qc); + + return 0; + } +diff --git a/libavcodec/v4l2_buffers.h b/libavcodec/v4l2_buffers.h +index e35b16130944..444ad94b145e 100644 +--- a/libavcodec/v4l2_buffers.h ++++ b/libavcodec/v4l2_buffers.h +@@ -28,31 +28,47 @@ + #include + #include + ++#include "avcodec.h" ++#include "libavutil/buffer.h" + #include "libavutil/frame.h" ++#include "libavutil/hwcontext_drm.h" + #include "packet.h" + + enum V4L2Buffer_status { + V4L2BUF_AVAILABLE, + V4L2BUF_IN_DRIVER, ++ V4L2BUF_IN_USE, + V4L2BUF_RET_USER, + }; + + /** + * V4L2Buffer (wrapper for v4l2_buffer management) + */ ++struct V4L2Context; ++struct ff_weak_link_client; ++struct dmabuf_h; ++ + typedef struct V4L2Buffer { +- /* each buffer needs to have a reference to its context */ ++ /* each buffer needs to have a reference to its context ++ * The pointer is good enough for most operation but once the buffer has ++ * been passed to the user the buffer may become orphaned so for free ops ++ * the weak link must be used to ensure that the context is actually ++ * there ++ */ + struct V4L2Context *context; ++ struct ff_weak_link_client *context_wl; + +- /* This object is refcounted per-plane, so we need to keep track +- * of how many context-refs we are holding. +- * This pointer is a RefStruct reference. */ +- const struct V4L2m2mContext *context_ref; +- atomic_uint context_refcount; ++ /* DRM descriptor */ ++ AVDRMFrameDescriptor drm_frame; ++ /* For DRM_PRIME encode - need to keep a ref to the source buffer till we ++ * are done ++ */ ++ AVBufferRef * ref_buf; + + /* keep track of the mmap address and mmap length */ + struct V4L2Plane_info { +- int bytesperline; ++ size_t bytesperline; ++ size_t offset; + void * mm_addr; + size_t length; + } plane_info[VIDEO_MAX_PLANES]; +@@ -63,9 +79,9 @@ typedef struct V4L2Buffer { + struct v4l2_buffer buf; + struct v4l2_plane planes[VIDEO_MAX_PLANES]; + +- int flags; + enum V4L2Buffer_status status; + ++ struct dmabuf_h * dmabuf[VIDEO_MAX_PLANES]; // If externally alloced dmabufs - stash other info here + } V4L2Buffer; + + /** +@@ -101,6 +117,10 @@ 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 * const pkt, V4L2Buffer * const out, ++ const void *extdata, size_t extlen, ++ const int64_t timestamp); ++ + /** + * Extracts the data from an AVFrame to a V4L2Buffer + * +@@ -109,7 +129,7 @@ int ff_v4l2_buffer_avpkt_to_buf(const AVPacket *pkt, V4L2Buffer *out); + * + * @returns 0 in case of success, a negative AVERROR code otherwise + */ +-int ff_v4l2_buffer_avframe_to_buf(const AVFrame *frame, V4L2Buffer *out); ++int ff_v4l2_buffer_avframe_to_buf(const AVFrame *frame, V4L2Buffer *out, const int64_t track_ts); + + /** + * Initializes a V4L2Buffer +@@ -119,7 +139,7 @@ int ff_v4l2_buffer_avframe_to_buf(const AVFrame *frame, V4L2Buffer *out); + * + * @returns 0 in case of success, a negative AVERROR code otherwise + */ +-int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index); ++int ff_v4l2_buffer_initialize(AVBufferRef **avbuf, int index, struct V4L2Context *ctx, enum v4l2_memory mem); + + /** + * Enqueues a V4L2Buffer +@@ -130,5 +150,12 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index); + */ + int ff_v4l2_buffer_enqueue(V4L2Buffer* avbuf); + ++static inline void ++ff_v4l2_buffer_set_avail(V4L2Buffer* const avbuf) ++{ ++ avbuf->status = V4L2BUF_AVAILABLE; ++ av_buffer_unref(&avbuf->ref_buf); ++} ++ + + #endif // AVCODEC_V4L2_BUFFERS_H +diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c +index be1df3785b28..e20e3e485c64 100644 +--- a/libavcodec/v4l2_context.c ++++ b/libavcodec/v4l2_context.c +@@ -28,11 +28,14 @@ + #include + #include + #include "libavutil/mem.h" ++#include "libavutil/avassert.h" ++#include "libavutil/pixdesc.h" + #include "libavcodec/avcodec.h" + #include "decode.h" + #include "v4l2_buffers.h" + #include "v4l2_fmt.h" + #include "v4l2_m2m.h" ++#include "weak_link.h" + + struct v4l2_format_update { + uint32_t v4l2_fmt; +@@ -42,26 +45,173 @@ struct v4l2_format_update { + int update_avfmt; + }; + +-static inline V4L2m2mContext *ctx_to_m2mctx(V4L2Context *ctx) ++ ++static inline int64_t track_to_pts(AVCodecContext *avctx, unsigned int n) + { +- return V4L2_TYPE_IS_OUTPUT(ctx->type) ? +- container_of(ctx, V4L2m2mContext, output) : +- container_of(ctx, V4L2m2mContext, capture); ++ return (int64_t)n; + } + +-static inline AVCodecContext *logger(V4L2Context *ctx) ++static inline unsigned int pts_to_track(AVCodecContext *avctx, const int64_t pts) + { +- return ctx_to_m2mctx(ctx)->avctx; ++ 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 int64_t ++xlat_pts_pkt_in(AVCodecContext *const avctx, xlat_track_t *const x, const AVPacket *const avpkt) ++{ ++ int64_t track_pts; ++ ++ // Avoid 0 ++ if (++x->track_no == 0) ++ x->track_no = 1; ++ ++ track_pts = track_to_pts(avctx, x->track_no); ++ ++ av_log(avctx, AV_LOG_TRACE, "In pkt PTS=%" PRId64 ", DTS=%" PRId64 ", track=%" PRId64 ", n=%u\n", avpkt->pts, avpkt->dts, track_pts, x->track_no); ++ x->track_els[x->track_no % FF_V4L2_M2M_TRACK_SIZE] = (V4L2m2mTrackEl){ ++ .discard = 0, ++ .pending = 1, ++ .pkt_size = avpkt->size, ++ .pts = avpkt->pts, ++ .dts = avpkt->dts, ++ .pkt_pos = avpkt->pos, ++ .duration = avpkt->duration, ++ .track_pts = track_pts ++ }; ++ return track_pts; ++} ++ ++static int64_t ++xlat_pts_frame_in(AVCodecContext *const avctx, xlat_track_t *const x, const AVFrame *const frame) ++{ ++ int64_t track_pts; ++ ++ // Avoid 0 ++ if (++x->track_no == 0) ++ x->track_no = 1; ++ ++ track_pts = track_to_pts(avctx, x->track_no); ++ ++ av_log(avctx, AV_LOG_TRACE, "In frame PTS=%" PRId64 ", track=%" PRId64 ", n=%u\n", frame->pts, track_pts, x->track_no); ++ x->track_els[x->track_no % FF_V4L2_M2M_TRACK_SIZE] = (V4L2m2mTrackEl){ ++ .discard = 0, ++ .pending = 1, ++ .pts = frame->pts, ++ .dts = AV_NOPTS_VALUE, ++ .duration = frame->duration, ++ .track_pts = track_pts ++ }; ++#if FF_API_FRAME_PKT ++FF_DISABLE_DEPRECATION_WARNINGS ++ x->track_els[x->track_no % FF_V4L2_M2M_TRACK_SIZE].pkt_pos = frame->pkt_pos; ++FF_ENABLE_DEPRECATION_WARNINGS ++#endif ++ return track_pts; ++} ++ ++ ++// Returns -1 if we should discard the frame ++static int ++xlat_pts_frame_out(AVCodecContext *const avctx, ++ xlat_track_t * const x, ++ AVFrame *const frame) ++{ ++ unsigned int n = pts_to_track(avctx, frame->pts) % FF_V4L2_M2M_TRACK_SIZE; ++ V4L2m2mTrackEl *const t = x->track_els + n; ++ if (frame->pts == AV_NOPTS_VALUE || frame->pts != t->track_pts) ++ { ++ av_log(avctx, frame->pts == AV_NOPTS_VALUE ? AV_LOG_DEBUG : AV_LOG_WARNING, ++ "Frame tracking failure: pts=%" PRId64 ", track[%d]=%" PRId64 "\n", frame->pts, n, t->track_pts); ++ frame->pts = AV_NOPTS_VALUE; ++ frame->pkt_dts = AV_NOPTS_VALUE; ++ frame->duration = 0; ++#if FF_API_FRAME_PKT ++FF_DISABLE_DEPRECATION_WARNINGS ++ frame->pkt_size = -1; ++ frame->pkt_pos = -1; ++FF_ENABLE_DEPRECATION_WARNINGS ++#endif ++ } ++ else if (!t->discard) ++ { ++ frame->pts = t->pending ? t->pts : AV_NOPTS_VALUE; ++ frame->pkt_dts = t->dts; ++ frame->duration = t->duration; ++#if FF_API_FRAME_PKT ++FF_DISABLE_DEPRECATION_WARNINGS ++ frame->pkt_pos = t->pkt_pos; ++ frame->pkt_size = t->pkt_size; ++FF_ENABLE_DEPRECATION_WARNINGS ++#endif ++ ++ if (frame->pts != AV_NOPTS_VALUE) ++ x->last_pts = frame->pts; ++ t->pending = 0; ++ } ++ else ++ { ++ av_log(avctx, AV_LOG_DEBUG, "Discard frame (flushed): pts=%" PRId64 ", track[%d]=%" PRId64 "\n", frame->pts, n, t->track_pts); ++ return -1; ++ } ++ ++ av_log(avctx, AV_LOG_TRACE, "Out frame PTS=%" PRId64 "/%"PRId64", DTS=%" PRId64 ", track=%"PRId64", n=%d\n", ++ frame->pts, frame->best_effort_timestamp, frame->pkt_dts, t->track_pts, n); ++ return 0; + } + +-static inline unsigned int v4l2_get_width(struct v4l2_format *fmt) ++// Returns -1 if we should discard the frame ++static int ++xlat_pts_pkt_out(AVCodecContext *const avctx, ++ xlat_track_t * const x, ++ AVPacket *const pkt) + { +- return V4L2_TYPE_IS_MULTIPLANAR(fmt->type) ? fmt->fmt.pix_mp.width : fmt->fmt.pix.width; ++ unsigned int n = pts_to_track(avctx, pkt->pts) % FF_V4L2_M2M_TRACK_SIZE; ++ V4L2m2mTrackEl *const t = x->track_els + n; ++ if (pkt->pts == AV_NOPTS_VALUE || pkt->pts != t->track_pts) ++ { ++ av_log(avctx, pkt->pts == AV_NOPTS_VALUE ? AV_LOG_DEBUG : AV_LOG_WARNING, ++ "Pkt tracking failure: pts=%" PRId64 ", track[%d]=%" PRId64 "\n", pkt->pts, n, t->track_pts); ++ pkt->pts = AV_NOPTS_VALUE; ++ } ++ else if (!t->discard) ++ { ++ pkt->pts = t->pending ? t->pts : AV_NOPTS_VALUE; ++ ++ if (pkt->pts != AV_NOPTS_VALUE) ++ x->last_pts = pkt->pts; ++ t->pending = 0; ++ } ++ else ++ { ++ av_log(avctx, AV_LOG_DEBUG, "Discard packet (flushed): pts=%" PRId64 ", track[%d]=%" PRId64 "\n", pkt->pts, n, t->track_pts); ++ return -1; ++ } ++ ++ // * Would like something much better than this...xlat(offset + out_count)? ++ pkt->dts = pkt->pts; ++ av_log(avctx, AV_LOG_TRACE, "Out pkt PTS=%" PRId64 ", track=%"PRId64", n=%d\n", ++ pkt->pts, t->track_pts, n); ++ return 0; ++} ++ ++ ++static inline V4L2m2mContext *ctx_to_m2mctx(const V4L2Context *ctx) ++{ ++ return V4L2_TYPE_IS_OUTPUT(ctx->type) ? ++ container_of(ctx, V4L2m2mContext, output) : ++ container_of(ctx, V4L2m2mContext, capture); + } + +-static inline unsigned int v4l2_get_height(struct v4l2_format *fmt) ++static inline AVCodecContext *logger(const V4L2Context *ctx) + { +- return V4L2_TYPE_IS_MULTIPLANAR(fmt->type) ? fmt->fmt.pix_mp.height : fmt->fmt.pix.height; ++ return ctx_to_m2mctx(ctx)->avctx; + } + + static AVRational v4l2_get_sar(V4L2Context *ctx) +@@ -82,21 +232,29 @@ static AVRational v4l2_get_sar(V4L2Context *ctx) + return sar; + } + +-static inline unsigned int v4l2_resolution_changed(V4L2Context *ctx, struct v4l2_format *fmt2) ++static inline int ctx_buffers_alloced(const V4L2Context * const ctx) + { +- struct v4l2_format *fmt1 = &ctx->format; +- int ret = V4L2_TYPE_IS_MULTIPLANAR(ctx->type) ? +- fmt1->fmt.pix_mp.width != fmt2->fmt.pix_mp.width || +- fmt1->fmt.pix_mp.height != fmt2->fmt.pix_mp.height +- : +- fmt1->fmt.pix.width != fmt2->fmt.pix.width || +- fmt1->fmt.pix.height != fmt2->fmt.pix.height; ++ return ctx->bufrefs != NULL; ++} ++ ++// Width/Height changed or we don't have an alloc in the first place? ++static int ctx_resolution_changed(const V4L2Context *ctx, const struct v4l2_format *fmt2) ++{ ++ const struct v4l2_format *fmt1 = &ctx->format; ++ int ret = !ctx_buffers_alloced(ctx) || ++ (V4L2_TYPE_IS_MULTIPLANAR(ctx->type) ? ++ fmt1->fmt.pix_mp.width != fmt2->fmt.pix_mp.width || ++ fmt1->fmt.pix_mp.height != fmt2->fmt.pix_mp.height ++ : ++ fmt1->fmt.pix.width != fmt2->fmt.pix.width || ++ fmt1->fmt.pix.height != fmt2->fmt.pix.height); + + if (ret) +- av_log(logger(ctx), AV_LOG_DEBUG, "%s changed (%dx%d) -> (%dx%d)\n", ++ av_log(logger(ctx), AV_LOG_DEBUG, "V4L2 %s changed: alloc=%d (%dx%d) -> (%dx%d)\n", + ctx->name, +- v4l2_get_width(fmt1), v4l2_get_height(fmt1), +- v4l2_get_width(fmt2), v4l2_get_height(fmt2)); ++ ctx_buffers_alloced(ctx), ++ ff_v4l2_get_format_width(fmt1), ff_v4l2_get_format_height(fmt1), ++ ff_v4l2_get_format_width(fmt2), ff_v4l2_get_format_height(fmt2)); + + return ret; + } +@@ -154,76 +312,100 @@ static inline void v4l2_save_to_context(V4L2Context* ctx, struct v4l2_format_upd + } + } + +-static int v4l2_start_decode(V4L2Context *ctx) ++static int get_default_selection(V4L2Context * const ctx, struct v4l2_rect *r) + { +- struct v4l2_decoder_cmd cmd = { +- .cmd = V4L2_DEC_CMD_START, +- .flags = 0, ++ V4L2m2mContext * const s = ctx_to_m2mctx(ctx); ++ struct v4l2_selection selection = { ++ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, ++ .target = V4L2_SEL_TGT_COMPOSE + }; +- int ret; + +- ret = ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_DECODER_CMD, &cmd); +- if (ret) ++ memset(r, 0, sizeof(*r)); ++ if (ioctl(s->fd, VIDIOC_G_SELECTION, &selection)) + return AVERROR(errno); + ++ *r = selection.r; + return 0; + } + +-/** +- * handle resolution change event and end of stream event +- * returns 1 if reinit was successful, negative if it failed +- * returns 0 if reinit was not executed +- */ +-static int v4l2_handle_event(V4L2Context *ctx) ++static int do_source_change(V4L2m2mContext * const s) + { +- V4L2m2mContext *s = ctx_to_m2mctx(ctx); +- struct v4l2_format cap_fmt = s->capture.format; +- struct v4l2_event evt = { 0 }; ++ AVCodecContext *const avctx = s->avctx; ++ + int ret; ++ int reinit; ++ struct v4l2_format cap_fmt = s->capture.format; + +- ret = ioctl(s->fd, VIDIOC_DQEVENT, &evt); +- if (ret < 0) { +- av_log(logger(ctx), AV_LOG_ERROR, "%s VIDIOC_DQEVENT\n", ctx->name); +- return 0; +- } ++ s->capture.done = 0; + +- if (evt.type == V4L2_EVENT_EOS) { +- ctx->done = 1; ++ ret = ioctl(s->fd, VIDIOC_G_FMT, &cap_fmt); ++ if (ret) { ++ av_log(avctx, AV_LOG_ERROR, "%s VIDIOC_G_FMT failed\n", s->capture.name); + return 0; + } + +- if (evt.type != V4L2_EVENT_SOURCE_CHANGE) +- return 0; ++ get_default_selection(&s->capture, &s->capture.selection); + +- ret = ioctl(s->fd, VIDIOC_G_FMT, &cap_fmt); +- if (ret) { +- av_log(logger(ctx), AV_LOG_ERROR, "%s VIDIOC_G_FMT\n", s->capture.name); +- return 0; ++ reinit = ctx_resolution_changed(&s->capture, &cap_fmt); ++ if ((s->quirks & FF_V4L2_QUIRK_REINIT_ALWAYS) != 0) ++ reinit = 1; ++ ++ s->capture.format = cap_fmt; ++ if (reinit) { ++ s->capture.height = ff_v4l2_get_format_height(&cap_fmt); ++ s->capture.width = ff_v4l2_get_format_width(&cap_fmt); + } + +- if (v4l2_resolution_changed(&s->capture, &cap_fmt)) { +- s->capture.height = v4l2_get_height(&cap_fmt); +- s->capture.width = v4l2_get_width(&cap_fmt); +- s->capture.sample_aspect_ratio = v4l2_get_sar(&s->capture); +- } else { +- v4l2_start_decode(ctx); +- return 0; ++ // If we don't support selection (or it is bust) and we obviously have HD then kludge ++ if ((s->capture.selection.width == 0 || s->capture.selection.height == 0) && ++ (s->capture.height == 1088 && s->capture.width == 1920)) { ++ s->capture.selection = (struct v4l2_rect){.width = 1920, .height = 1080}; + } + +- s->reinit = 1; ++ s->capture.sample_aspect_ratio = v4l2_get_sar(&s->capture); + +- if (s->avctx) +- ret = ff_set_dimensions(s->avctx, s->capture.width, s->capture.height); +- if (ret < 0) +- av_log(logger(ctx), AV_LOG_WARNING, "update avcodec height and width\n"); ++ av_log(avctx, AV_LOG_DEBUG, "Source change: Fmt: %s, SAR: %d/%d, wxh %dx%d crop %dx%d @ %d,%d, reinit=%d\n", ++ av_fourcc2str(ff_v4l2_get_format_pixelformat(&cap_fmt)), ++ s->capture.sample_aspect_ratio.num, s->capture.sample_aspect_ratio.den, ++ s->capture.width, s->capture.height, ++ s->capture.selection.width, s->capture.selection.height, ++ s->capture.selection.left, s->capture.selection.top, reinit); + +- ret = ff_v4l2_m2m_codec_reinit(s); +- if (ret) { +- av_log(logger(ctx), AV_LOG_ERROR, "v4l2_m2m_codec_reinit\n"); +- return AVERROR(EINVAL); ++ ret = ff_v4l2_context_set_status(&s->capture, VIDIOC_STREAMOFF); ++ if (ret) ++ av_log(avctx, AV_LOG_ERROR, "capture VIDIOC_STREAMOFF failed\n"); ++ s->draining = 0; ++ ++ if (!reinit) { ++ /* Buffers are OK so just stream off to ack */ ++ av_log(avctx, AV_LOG_DEBUG, "%s: Parameters only - restart decode\n", __func__); ++ } ++ else { ++ if (avctx) ++ ret = ff_set_dimensions(s->avctx, ++ s->capture.selection.width != 0 ? s->capture.selection.width : s->capture.width, ++ s->capture.selection.height != 0 ? s->capture.selection.height : s->capture.height); ++ if (ret < 0) ++ av_log(avctx, AV_LOG_WARNING, "update avcodec height and width failed\n"); ++ ++ ff_v4l2_context_release(&s->capture); ++ ++ if (s->capture.width > ff_v4l2_get_format_width(&s->capture.format) || ++ s->capture.height > ff_v4l2_get_format_height(&s->capture.format)) { ++ av_log(avctx, AV_LOG_ERROR, "Format post reinit too small: wanted %dx%d > got %dx%d\n", ++ s->capture.width, s->capture.height, ++ ff_v4l2_get_format_width(&s->capture.format), ff_v4l2_get_format_height(&s->capture.format)); ++ return AVERROR(EINVAL); ++ } ++ ++ // Update pixel format - should only actually do something on initial change ++ s->capture.av_pix_fmt = ++ ff_v4l2_format_v4l2_to_avfmt(ff_v4l2_get_format_pixelformat(&s->capture.format), AV_CODEC_ID_RAWVIDEO); ++ avctx->pix_fmt = s->output_drm ? AV_PIX_FMT_DRM_PRIME : s->capture.av_pix_fmt; ++ avctx->sw_pix_fmt = s->capture.av_pix_fmt; + } + +- /* reinit executed */ ++ ret = ff_v4l2_context_set_status(&s->capture, VIDIOC_STREAMON); + return 1; + } + +@@ -267,175 +449,293 @@ static int v4l2_stop_encode(V4L2Context *ctx) + return 0; + } + +-static V4L2Buffer* v4l2_dequeue_v4l2buf(V4L2Context *ctx, int timeout) ++// DQ a buffer ++// Amalgamates all the various ways there are of signalling EOS/Event to ++// generate a consistant EPIPE. ++// ++// Sets ctx->flag_last if next dq would produce EPIPE (i.e. stream has stopped) ++// ++// Returns: ++// 0 Success ++// AVERROR(EPIPE) Nothing more to read ++// AVERROR(ENOSPC) No buffers in Q to put result in ++// * AVERROR(..) ++ ++ static int ++dq_buf(V4L2Context * const ctx, V4L2Buffer ** const ppavbuf) + { +- struct v4l2_plane planes[VIDEO_MAX_PLANES]; +- struct v4l2_buffer buf = { 0 }; +- V4L2Buffer *avbuf; +- struct pollfd pfd = { +- .events = POLLIN | POLLRDNORM | POLLPRI | POLLOUT | POLLWRNORM, /* default blocking capture */ +- .fd = ctx_to_m2mctx(ctx)->fd, ++ V4L2m2mContext * const m = ctx_to_m2mctx(ctx); ++ AVCodecContext * const avctx = m->avctx; ++ V4L2Buffer * avbuf; ++ const int is_mp = V4L2_TYPE_IS_MULTIPLANAR(ctx->type); ++ ++ struct v4l2_plane planes[VIDEO_MAX_PLANES] = {{0}}; ++ ++ struct v4l2_buffer buf = { ++ .type = ctx->type, ++ .memory = V4L2_MEMORY_MMAP, + }; +- int i, ret; + +- if (!V4L2_TYPE_IS_OUTPUT(ctx->type) && ctx->buffers) { +- for (i = 0; i < ctx->num_buffers; i++) { +- if (ctx->buffers[i].status == V4L2BUF_IN_DRIVER) +- break; +- } +- if (i == ctx->num_buffers) +- av_log(logger(ctx), AV_LOG_WARNING, "All capture buffers returned to " +- "userspace. Increase num_capture_buffers " +- "to prevent device deadlock or dropped " +- "packets/frames.\n"); +- } +- +- /* if we are draining and there are no more capture buffers queued in the driver we are done */ +- if (!V4L2_TYPE_IS_OUTPUT(ctx->type) && ctx_to_m2mctx(ctx)->draining) { +- for (i = 0; i < ctx->num_buffers; i++) { +- /* capture buffer initialization happens during decode hence +- * detection happens at runtime +- */ +- if (!ctx->buffers) +- break; ++ *ppavbuf = NULL; ++ ++ if (ctx->flag_last) ++ return AVERROR(EPIPE); ++ ++ if (is_mp) { ++ buf.length = VIDEO_MAX_PLANES; ++ buf.m.planes = planes; ++ } ++ ++ while (ioctl(m->fd, VIDIOC_DQBUF, &buf) != 0) { ++ const int err = errno; ++ av_assert0(AVERROR(err) < 0); ++ if (err != EINTR) { ++ av_log(avctx, AV_LOG_DEBUG, "%s VIDIOC_DQBUF, errno (%s)\n", ++ ctx->name, av_err2str(AVERROR(err))); + +- if (ctx->buffers[i].status == V4L2BUF_IN_DRIVER) +- goto start; ++ if (err == EPIPE) ++ ctx->flag_last = 1; ++ ++ return AVERROR(err); + } +- ctx->done = 1; +- return NULL; + } ++ atomic_fetch_sub(&ctx->q_count, 1); ++ ++ avbuf = (V4L2Buffer *)ctx->bufrefs[buf.index]->data; ++ ff_v4l2_buffer_set_avail(avbuf); ++ avbuf->buf = buf; ++ if (is_mp) { ++ memcpy(avbuf->planes, planes, sizeof(planes)); ++ avbuf->buf.m.planes = avbuf->planes; ++ } ++ // Done with any attached buffer ++ av_buffer_unref(&avbuf->ref_buf); + +-start: +- if (V4L2_TYPE_IS_OUTPUT(ctx->type)) +- pfd.events = POLLOUT | POLLWRNORM; +- else { +- /* no need to listen to requests for more input while draining */ +- if (ctx_to_m2mctx(ctx)->draining) +- pfd.events = POLLIN | POLLRDNORM | POLLPRI; ++ if (V4L2_TYPE_IS_CAPTURE(ctx->type)) { ++ // Zero length cap buffer return == EOS ++ if ((is_mp ? buf.m.planes[0].bytesused : buf.bytesused) == 0) { ++ av_log(avctx, AV_LOG_DEBUG, "Buffer empty - reQ\n"); ++ ++ // Must reQ so we don't leak ++ // May not matter if the next thing we do is release all the ++ // buffers but better to be tidy. ++ ff_v4l2_buffer_enqueue(avbuf); ++ ++ ctx->flag_last = 1; ++ return AVERROR(EPIPE); ++ } ++ ++#ifdef V4L2_BUF_FLAG_LAST ++ // If flag_last set then this contains data but is the last frame ++ // so remember that but return OK ++ if ((buf.flags & V4L2_BUF_FLAG_LAST) != 0) ++ ctx->flag_last = 1; ++#endif + } + +- for (;;) { +- ret = poll(&pfd, 1, timeout); +- if (ret > 0) +- break; +- if (errno == EINTR) ++ *ppavbuf = avbuf; ++ return 0; ++} ++ ++/** ++ * handle resolution change event and end of stream event ++ * Expects to be called after the stream has stopped ++ * ++ * returns 1 if reinit was successful, negative if it failed ++ * returns 0 if reinit was not executed ++ */ ++static int ++get_event(V4L2m2mContext * const m) ++{ ++ AVCodecContext * const avctx = m->avctx; ++ struct v4l2_event evt = { 0 }; ++ ++ while (ioctl(m->fd, VIDIOC_DQEVENT, &evt) != 0) { ++ const int rv = AVERROR(errno); ++ if (rv == AVERROR(EINTR)) + continue; +- return NULL; ++ if (rv == AVERROR(EAGAIN)) { ++ av_log(avctx, AV_LOG_WARNING, "V4L2 failed to get expected event - assume EOS\n"); ++ return AVERROR_EOF; ++ } ++ av_log(avctx, AV_LOG_ERROR, "V4L2 VIDIOC_DQEVENT: %s\n", av_err2str(rv)); ++ return rv; + } + +- /* 0. handle errors */ +- if (pfd.revents & POLLERR) { +- /* if we are trying to get free buffers but none have been queued yet, +- * or if no buffers have been allocated yet, no need to raise a warning +- */ +- if (timeout == 0) { +- if (!ctx->buffers) +- return NULL; ++ av_log(avctx, AV_LOG_DEBUG, "Dq event %d\n", evt.type); + +- for (i = 0; i < ctx->num_buffers; i++) { +- if (ctx->buffers[i].status != V4L2BUF_AVAILABLE) +- av_log(logger(ctx), AV_LOG_WARNING, "%s POLLERR\n", ctx->name); +- } ++ if (evt.type == V4L2_EVENT_EOS) { ++ av_log(avctx, AV_LOG_TRACE, "V4L2 VIDIOC_EVENT_EOS\n"); ++ return AVERROR_EOF; ++ } ++ ++ if (evt.type == V4L2_EVENT_SOURCE_CHANGE) ++ return do_source_change(m); ++ ++ return 0; ++} ++ ++static inline int ++dq_ok(const V4L2Context * const c) ++{ ++ return c->streamon && atomic_load(&c->q_count) != 0; ++} ++ ++// Get a buffer ++// If output then just gets the buffer in the expected way ++// If capture then runs the capture state m/c to deal with res change etc. ++// If return value == 0 then *ppavbuf != NULL ++ ++static int ++get_qbuf(V4L2Context * const ctx, V4L2Buffer ** const ppavbuf, const int timeout) ++{ ++ V4L2m2mContext * const m = ctx_to_m2mctx(ctx); ++ AVCodecContext * const avctx = m->avctx; ++ const int is_cap = V4L2_TYPE_IS_CAPTURE(ctx->type); ++ ++ const unsigned int poll_cap = (POLLIN | POLLRDNORM); ++ const unsigned int poll_out = (POLLOUT | POLLWRNORM); ++ const unsigned int poll_event = POLLPRI; ++ ++ *ppavbuf = NULL; ++ ++ for (;;) { ++ struct pollfd pfd = { ++ .fd = m->fd, ++ // If capture && stream not started then assume we are waiting for the initial event ++ .events = !is_cap ? poll_out : ++ !ff_v4l2_ctx_eos(ctx) && ctx->streamon ? poll_cap : ++ poll_event, ++ }; ++ int ret; ++ ++ if (ctx->done) { ++ av_log(avctx, AV_LOG_TRACE, "V4L2 %s already done\n", ctx->name); ++ return AVERROR_EOF; + } +- else +- av_log(logger(ctx), AV_LOG_WARNING, "%s POLLERR\n", ctx->name); + +- return NULL; +- } ++ // If capture && timeout == -1 then also wait for rx buffer free ++ if (is_cap && timeout == -1 && dq_ok(&m->output) && !m->draining) ++ pfd.events |= poll_out; + +- /* 1. handle resolution changes */ +- if (pfd.revents & POLLPRI) { +- ret = v4l2_handle_event(ctx); +- if (ret < 0) { +- /* if re-init failed, abort */ +- ctx->done = 1; +- return NULL; ++ // If nothing Qed all we will get is POLLERR - avoid that ++ if ((pfd.events == poll_out && !dq_ok(&m->output)) || ++ (pfd.events == poll_cap && !dq_ok(&m->capture)) || ++ (pfd.events == (poll_cap | poll_out) && !dq_ok(&m->capture) && !dq_ok(&m->output))) { ++ av_log(avctx, AV_LOG_TRACE, "V4L2 poll %s empty\n", ctx->name); ++ return AVERROR(ENOSPC); + } +- if (ret) { +- /* if re-init was successful drop the buffer (if there was one) +- * since we had to reconfigure capture (unmap all buffers) +- */ +- return NULL; ++ ++ // Timeout kludged s.t. "forever" eventually gives up & produces logging ++ // If waiting for an event when we have seen a last_frame then we expect ++ // it to be ready already so force a short timeout ++ ret = poll(&pfd, 1, ++ ff_v4l2_ctx_eos(ctx) ? 10 : ++ timeout == -1 ? 3000 : timeout); ++ if (ret < 0) { ++ ret = AVERROR(errno); // Remember errno before logging etc. ++ av_assert0(ret < 0); + } +- } + +- /* 2. dequeue the buffer */ +- if (pfd.revents & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM)) { ++ av_log(avctx, AV_LOG_TRACE, "V4L2 poll %s ret=%d, timeout=%d, events=%#x, revents=%#x\n", ++ ctx->name, ret, timeout, pfd.events, pfd.revents); + +- if (!V4L2_TYPE_IS_OUTPUT(ctx->type)) { +- /* there is a capture buffer ready */ +- if (pfd.revents & (POLLIN | POLLRDNORM)) +- goto dequeue; ++ if (ret < 0) { ++ if (ret == AVERROR(EINTR)) ++ continue; ++ av_log(avctx, AV_LOG_ERROR, "V4L2 %s poll error %d (%s)\n", ctx->name, AVUNERROR(ret), av_err2str(ret)); ++ return ret; ++ } + +- /* the driver is ready to accept more input; instead of waiting for the capture +- * buffer to complete we return NULL so input can proceed (we are single threaded) +- */ +- if (pfd.revents & (POLLOUT | POLLWRNORM)) +- return NULL; ++ if (ret == 0) { ++ if (timeout == -1) ++ av_log(avctx, AV_LOG_ERROR, "V4L2 %s poll unexpected timeout: events=%#x\n", ctx->name, pfd.events); ++ if (ff_v4l2_ctx_eos(ctx)) { ++ av_log(avctx, AV_LOG_WARNING, "V4L2 %s poll event timeout\n", ctx->name); ++ ret = get_event(m); ++ if (ret < 0) { ++ ctx->done = 1; ++ return ret; ++ } ++ } ++ return AVERROR(EAGAIN); + } + +-dequeue: +- memset(&buf, 0, sizeof(buf)); +- buf.memory = V4L2_MEMORY_MMAP; +- buf.type = ctx->type; +- if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) { +- memset(planes, 0, sizeof(planes)); +- buf.length = VIDEO_MAX_PLANES; +- buf.m.planes = planes; ++ if ((pfd.revents & POLLERR) != 0) { ++ av_log(avctx, AV_LOG_WARNING, "V4L2 %s POLLERR\n", ctx->name); ++ return AVERROR_UNKNOWN; + } + +- ret = ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_DQBUF, &buf); +- if (ret) { +- if (errno != EAGAIN) { ++ if ((pfd.revents & poll_event) != 0) { ++ ret = get_event(m); ++ if (ret < 0) { + ctx->done = 1; +- if (errno != EPIPE) +- av_log(logger(ctx), AV_LOG_DEBUG, "%s VIDIOC_DQBUF, errno (%s)\n", +- ctx->name, av_err2str(AVERROR(errno))); ++ return ret; + } +- return NULL; ++ continue; + } + +- 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) { +- ctx->done = 1; +- return NULL; +- } +-#ifdef V4L2_BUF_FLAG_LAST +- if (buf.flags & V4L2_BUF_FLAG_LAST) +- ctx->done = 1; +-#endif ++ if ((pfd.revents & poll_cap) != 0) { ++ ret = dq_buf(ctx, ppavbuf); ++ if (ret == AVERROR(EPIPE)) ++ continue; ++ return ret; + } + +- avbuf = &ctx->buffers[buf.index]; +- avbuf->status = V4L2BUF_AVAILABLE; +- avbuf->buf = buf; +- if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) { +- memcpy(avbuf->planes, planes, sizeof(planes)); +- avbuf->buf.m.planes = avbuf->planes; ++ if ((pfd.revents & poll_out) != 0) { ++ if (is_cap) ++ return AVERROR(EAGAIN); ++ return dq_buf(ctx, ppavbuf); + } +- return avbuf; ++ ++ av_log(avctx, AV_LOG_ERROR, "V4L2 poll unexpected events=%#x, revents=%#x\n", pfd.events, pfd.revents); ++ return AVERROR_UNKNOWN; + } ++} + +- return NULL; ++// Clear out flags and timestamps that should should be set by the user ++// Returns the passed avbuf ++static V4L2Buffer * ++clean_v4l2_buffer(V4L2Buffer * const avbuf) ++{ ++ struct v4l2_buffer *const buf = &avbuf->buf; ++ ++ buf->flags = 0; ++ buf->field = V4L2_FIELD_ANY; ++ buf->timestamp = (struct timeval){0}; ++ buf->timecode = (struct v4l2_timecode){0}; ++ buf->sequence = 0; ++ ++ return avbuf; ++} ++ ++int ++ff_v4l2_dq_all(V4L2Context *const ctx, int timeout1) ++{ ++ V4L2Buffer * avbuf; ++ if (timeout1 != 0) { ++ int rv = get_qbuf(ctx, &avbuf, timeout1); ++ if (rv != 0) ++ return rv; ++ } ++ do { ++ get_qbuf(ctx, &avbuf, 0); ++ } while (avbuf); ++ return 0; + } + + static V4L2Buffer* v4l2_getfree_v4l2buf(V4L2Context *ctx) + { +- int timeout = 0; /* return when no more buffers to dequeue */ + int i; + + /* get back as many output buffers as possible */ +- if (V4L2_TYPE_IS_OUTPUT(ctx->type)) { +- do { +- } while (v4l2_dequeue_v4l2buf(ctx, timeout)); +- } ++ if (V4L2_TYPE_IS_OUTPUT(ctx->type)) ++ ff_v4l2_dq_all(ctx, 0); + + for (i = 0; i < ctx->num_buffers; i++) { +- if (ctx->buffers[i].status == V4L2BUF_AVAILABLE) +- return &ctx->buffers[i]; ++ V4L2Buffer * const avbuf = (V4L2Buffer *)ctx->bufrefs[i]->data; ++ if (avbuf->status == V4L2BUF_AVAILABLE) ++ return clean_v4l2_buffer(avbuf); + } + + return NULL; +@@ -443,25 +743,45 @@ static V4L2Buffer* v4l2_getfree_v4l2buf(V4L2Context *ctx) + + 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 */ +- }; +- int i, j; ++ int i; ++ int ret = 0; ++ const int fd = ctx_to_m2mctx(ctx)->fd; + +- for (i = 0; i < ctx->num_buffers; i++) { +- V4L2Buffer *buffer = &ctx->buffers[i]; ++ // Orphan any buffers in the wild ++ ff_weak_link_break(&ctx->wl_master); ++ ++ if (ctx->bufrefs) { ++ for (i = 0; i < ctx->num_buffers; i++) ++ av_buffer_unref(ctx->bufrefs + i); ++ } + +- for (j = 0; j < buffer->num_planes; j++) { +- struct V4L2Plane_info *p = &buffer->plane_info[j]; +- 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))); ++ if (fd != -1) { ++ struct v4l2_requestbuffers req = { ++ .memory = V4L2_MEMORY_MMAP, ++ .type = ctx->type, ++ .count = 0, /* 0 -> unmap all buffers from the driver */ ++ }; ++ ++ while ((ret = ioctl(fd, VIDIOC_REQBUFS, &req)) == -1) { ++ if (errno == EINTR) ++ continue; ++ ++ ret = AVERROR(errno); ++ ++ 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"); + } + } ++ atomic_store(&ctx->q_count, 0); + +- return ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_REQBUFS, &req); ++ return ret; + } + + static inline int v4l2_try_raw_format(V4L2Context* ctx, enum AVPixelFormat pixfmt) +@@ -490,6 +810,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; +@@ -503,21 +825,22 @@ static int v4l2_get_raw_format(V4L2Context* ctx, enum AVPixelFormat *p) + return 0; + } + +- for (;;) { ++ for (;; ++fdesc.index) { + ret = ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_ENUM_FMT, &fdesc); + 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)) ++ continue; ++ } ++ + pixfmt = ff_v4l2_format_v4l2_to_avfmt(fdesc.pixelformat, AV_CODEC_ID_RAWVIDEO); + ret = v4l2_try_raw_format(ctx, pixfmt); +- if (ret){ +- fdesc.index++; +- continue; ++ if (ret == 0) { ++ *p = pixfmt; ++ return 0; + } +- +- *p = pixfmt; +- +- return 0; + } + + return AVERROR(EINVAL); +@@ -560,30 +883,131 @@ static int v4l2_get_coded_format(V4L2Context* ctx, uint32_t *p) + * + *****************************************************************************/ + +-int ff_v4l2_context_set_status(V4L2Context* ctx, uint32_t cmd) ++ ++static void flush_all_buffers_status(V4L2Context* const ctx) ++{ ++ int i; ++ ++ if (!ctx->bufrefs) ++ return; ++ ++ for (i = 0; i < ctx->num_buffers; ++i) { ++ struct V4L2Buffer * const buf = (struct V4L2Buffer *)ctx->bufrefs[i]->data; ++ if (buf->status == V4L2BUF_IN_DRIVER) ++ ff_v4l2_buffer_set_avail(buf); ++ } ++ atomic_store(&ctx->q_count, 0); ++} ++ ++static int stuff_all_buffers(AVCodecContext * avctx, V4L2Context* ctx) ++{ ++ int i; ++ int rv; ++ ++ if (!ctx->bufrefs) { ++ rv = ff_v4l2_context_init(ctx); ++ if (rv) { ++ av_log(avctx, AV_LOG_ERROR, "can't request capture buffers\n"); ++ return rv; ++ } ++ } ++ ++ ff_mutex_lock(&ctx->lock); ++ for (i = 0; i < ctx->num_buffers; ++i) { ++ struct V4L2Buffer * const buf = (struct V4L2Buffer *)ctx->bufrefs[i]->data; ++ if (buf->status == V4L2BUF_AVAILABLE) { ++ rv = ff_v4l2_buffer_enqueue(buf); ++ if (rv < 0) ++ break; ++ } ++ } ++ ff_mutex_unlock(&ctx->lock); ++ return rv; ++} ++ ++static int set_streamon(AVCodecContext * const avctx, V4L2Context*const ctx) + { + int type = ctx->type; +- int ret; ++ int ret = 0; + +- ret = ioctl(ctx_to_m2mctx(ctx)->fd, cmd, &type); +- if (ret < 0) +- return AVERROR(errno); ++ if (!V4L2_TYPE_IS_OUTPUT(ctx->type)) ++ stuff_all_buffers(avctx, ctx); + +- ctx->streamon = (cmd == VIDIOC_STREAMON); ++ if (ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_STREAMON, &type) < 0) { ++ ret = AVERROR(errno); ++ av_log(avctx, AV_LOG_ERROR, "%s set status ON failed: err=%s\n", ctx->name, ++ av_err2str(ret)); ++ return ret; ++ } + +- return 0; ++ ctx->first_buf = 1; ++ ctx->streamon = 1; ++ ctx->flag_last = 0; ++ av_log(avctx, AV_LOG_DEBUG, "%s set status ON OK\n", ctx->name); ++ return ret; ++} ++ ++static int set_streamoff(AVCodecContext * const avctx, V4L2Context*const ctx) ++{ ++ int type = ctx->type; ++ int ret = 0; ++ const int has_bufs = ctx_buffers_alloced(ctx); ++ ++ // Avoid doing anything if there is nothing we can do ++ if (!has_bufs && !ctx->streamon) ++ return 0; ++ ++ if (has_bufs) ++ ff_mutex_lock(&ctx->lock); ++ ++ if (ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_STREAMOFF, &type) < 0) { ++ ret = AVERROR(errno); ++ av_log(avctx, AV_LOG_ERROR, "%s set status ON failed: err=%s\n", ctx->name, ++ av_err2str(ret)); ++ } ++ else { ++ flush_all_buffers_status(ctx); ++ ++ ctx->streamon = 0; ++ ctx->flag_last = 0; ++ ++ av_log(avctx, AV_LOG_DEBUG, "%s set status OFF OK\n", ctx->name); ++ } ++ ++ if (has_bufs) ++ ff_mutex_unlock(&ctx->lock); ++ return ret; ++} ++ ++ ++int ff_v4l2_context_set_status(V4L2Context* ctx, uint32_t cmd) ++{ ++ AVCodecContext * const avctx = logger(ctx); ++ ++ switch (cmd) { ++ case VIDIOC_STREAMOFF: ++ return set_streamoff(avctx, ctx); ++ case VIDIOC_STREAMON: ++ return set_streamon(avctx, ctx); ++ default: ++ av_log(avctx, AV_LOG_ERROR, "%s: Unexpected cmd: %d\n", __func__, cmd); ++ break; ++ } ++ return AVERROR_BUG; + } + + int ff_v4l2_context_enqueue_frame(V4L2Context* ctx, const AVFrame* frame) + { +- V4L2m2mContext *s = ctx_to_m2mctx(ctx); ++ V4L2m2mContext *const s = ctx_to_m2mctx(ctx); ++ AVCodecContext *const avctx = s->avctx; ++ int64_t track_ts; + V4L2Buffer* avbuf; + int ret; + + if (!frame) { + ret = v4l2_stop_encode(ctx); + if (ret) +- av_log(logger(ctx), AV_LOG_ERROR, "%s stop_encode\n", ctx->name); ++ av_log(avctx, AV_LOG_ERROR, "%s stop_encode\n", ctx->name); + s->draining= 1; + return 0; + } +@@ -592,23 +1016,29 @@ int ff_v4l2_context_enqueue_frame(V4L2Context* ctx, const AVFrame* frame) + if (!avbuf) + return AVERROR(EAGAIN); + +- ret = ff_v4l2_buffer_avframe_to_buf(frame, avbuf); ++ track_ts = xlat_pts_frame_in(avctx, &s->xlat, frame); ++ ++ ret = ff_v4l2_buffer_avframe_to_buf(frame, avbuf, track_ts); + if (ret) + return ret; + + 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) + { + V4L2m2mContext *s = ctx_to_m2mctx(ctx); ++ AVCodecContext *const avctx = s->avctx; + V4L2Buffer* avbuf; + int ret; ++ int64_t track_ts; + + 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(avctx, AV_LOG_ERROR, "%s stop_decode failed: err=%d\n", ctx->name, ret); + s->draining = 1; + return 0; + } +@@ -617,8 +1047,13 @@ 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); +- if (ret) ++ track_ts = xlat_pts_pkt_in(avctx, &s->xlat, pkt); ++ ++ ret = ff_v4l2_buffer_avpkt_to_buf_ext(pkt, avbuf, extdata, extlen, track_ts); ++ if (ret == AVERROR(ENOMEM)) ++ av_log(logger(ctx), AV_LOG_ERROR, "Buffer overflow in %s: pkt->size=%d > buf->length=%d\n", ++ __func__, pkt->size, avbuf->planes[0].length); ++ else if (ret) + return ret; + + return ff_v4l2_buffer_enqueue(avbuf); +@@ -626,42 +1061,77 @@ int ff_v4l2_context_enqueue_packet(V4L2Context* ctx, const AVPacket* pkt) + + int ff_v4l2_context_dequeue_frame(V4L2Context* ctx, AVFrame* frame, int timeout) + { ++ V4L2m2mContext *s = ctx_to_m2mctx(ctx); ++ AVCodecContext *const avctx = s->avctx; + V4L2Buffer *avbuf; ++ int rv; + +- /* +- * timeout=-1 blocks until: +- * 1. decoded frame available +- * 2. an input buffer is ready to be dequeued +- */ +- avbuf = v4l2_dequeue_v4l2buf(ctx, timeout); +- if (!avbuf) { +- if (ctx->done) +- return AVERROR_EOF; ++ do { ++ if ((rv = get_qbuf(ctx, &avbuf, timeout)) != 0) ++ return rv; ++ if ((rv = ff_v4l2_buffer_buf_to_avframe(frame, avbuf)) != 0) ++ return rv; ++ } while (xlat_pts_frame_out(avctx, &s->xlat, frame) != 0); + +- return AVERROR(EAGAIN); +- } +- +- return ff_v4l2_buffer_buf_to_avframe(frame, avbuf); ++ return 0; + } + +-int ff_v4l2_context_dequeue_packet(V4L2Context* ctx, AVPacket* pkt) ++int ff_v4l2_context_dequeue_packet(V4L2Context* ctx, AVPacket* pkt, int timeout) + { ++ V4L2m2mContext *s = ctx_to_m2mctx(ctx); ++ AVCodecContext *const avctx = s->avctx; + V4L2Buffer *avbuf; ++ int rv; + +- /* +- * blocks until: +- * 1. encoded packet available +- * 2. an input buffer ready to be dequeued +- */ +- avbuf = v4l2_dequeue_v4l2buf(ctx, -1); +- if (!avbuf) { +- if (ctx->done) +- return AVERROR_EOF; ++ do { ++ if ((rv = get_qbuf(ctx, &avbuf, timeout)) != 0) ++ return rv == AVERROR(ENOSPC) ? AVERROR(EAGAIN) : rv; // Caller not currently expecting ENOSPC ++ if ((rv = ff_v4l2_buffer_buf_to_avpkt(pkt, avbuf)) != 0) ++ return rv; ++ } while (xlat_pts_pkt_out(avctx, &s->xlat, pkt) != 0); + +- return AVERROR(EAGAIN); ++ return 0; ++} ++ ++// Return 0 terminated list of drm fourcc video formats for this context ++// NULL if none found or error ++// Returned list is malloced so must be freed ++uint32_t * ff_v4l2_context_enum_drm_formats(V4L2Context *ctx, unsigned int *pN) ++{ ++ unsigned int i; ++ unsigned int n = 0; ++ unsigned int size = 0; ++ uint32_t * e = NULL; ++ *pN = 0; ++ ++ for (i = 0; i < 1024; ++i) { ++ struct v4l2_fmtdesc fdesc = { ++ .index = i, ++ .type = ctx->type ++ }; ++ ++ if (ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_ENUM_FMT, &fdesc)) ++ return e; ++ ++ if (n + 1 >= size) { ++ unsigned int newsize = (size == 0) ? 16 : size * 2; ++ uint32_t * t = av_realloc(e, newsize * sizeof(*t)); ++ if (!t) ++ return e; ++ e = t; ++ size = newsize; ++ } ++ ++ e[n] = fdesc.pixelformat; ++ e[++n] = 0; ++ if (pN) ++ *pN = n; + } + +- return ff_v4l2_buffer_buf_to_avpkt(pkt, avbuf); ++ // If we've looped 1024 times we are clearly confused ++ *pN = 0; ++ av_free(e); ++ return NULL; + } + + int ff_v4l2_context_get_format(V4L2Context* ctx, int probe) +@@ -693,78 +1163,194 @@ int ff_v4l2_context_get_format(V4L2Context* ctx, int probe) + + int ff_v4l2_context_set_format(V4L2Context* ctx) + { +- return ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_S_FMT, &ctx->format); ++ int ret; ++ ++ ret = ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_S_FMT, &ctx->format); ++ if (ret != 0) ++ return ret; ++ ++ // Check returned size against min size and if smaller have another go ++ // Only worry about plane[0] as this is meant to enforce limits for ++ // encoded streams where we might know a bit more about the shape ++ // than the driver ++ if (V4L2_TYPE_IS_MULTIPLANAR(ctx->format.type)) { ++ if (ctx->min_buf_size <= ctx->format.fmt.pix_mp.plane_fmt[0].sizeimage) ++ return 0; ++ ctx->format.fmt.pix_mp.plane_fmt[0].sizeimage = ctx->min_buf_size; ++ } ++ else { ++ if (ctx->min_buf_size <= ctx->format.fmt.pix.sizeimage) ++ return 0; ++ ctx->format.fmt.pix.sizeimage = ctx->min_buf_size; ++ } ++ ++ ret = ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_S_FMT, &ctx->format); ++ return ret; + } + + void ff_v4l2_context_release(V4L2Context* ctx) + { + int ret; + +- if (!ctx->buffers) ++ if (!ctx->bufrefs) + return; + + ret = v4l2_release_buffers(ctx); + if (ret) + av_log(logger(ctx), AV_LOG_WARNING, "V4L2 failed to unmap the %s buffers\n", ctx->name); + +- av_freep(&ctx->buffers); ++ av_freep(&ctx->bufrefs); ++ av_buffer_unref(&ctx->frames_ref); ++ ++ ff_mutex_destroy(&ctx->lock); ++ pthread_cond_destroy(&ctx->cond); + } + +-int ff_v4l2_context_init(V4L2Context* ctx) ++ ++static int create_buffers(V4L2Context* const ctx, const unsigned int req_buffers, const enum v4l2_memory mem) + { +- V4L2m2mContext *s = ctx_to_m2mctx(ctx); ++ V4L2m2mContext * const s = ctx_to_m2mctx(ctx); + struct v4l2_requestbuffers req; +- int ret, i; ++ int ret; ++ int i; + +- if (!v4l2_type_supported(ctx)) { +- av_log(logger(ctx), AV_LOG_ERROR, "type %i not supported\n", ctx->type); +- return AVERROR_PATCHWELCOME; +- } +- +- ret = ioctl(s->fd, VIDIOC_G_FMT, &ctx->format); +- if (ret) +- av_log(logger(ctx), AV_LOG_ERROR, "%s VIDIOC_G_FMT failed\n", ctx->name); ++ av_assert0(ctx->bufrefs == NULL); + + memset(&req, 0, sizeof(req)); +- req.count = ctx->num_buffers; +- req.memory = V4L2_MEMORY_MMAP; ++ req.count = req_buffers; ++ req.memory = mem; + req.type = ctx->type; +- ret = ioctl(s->fd, VIDIOC_REQBUFS, &req); +- if (ret < 0) { +- av_log(logger(ctx), AV_LOG_ERROR, "%s VIDIOC_REQBUFS failed: %s\n", ctx->name, strerror(errno)); +- return AVERROR(errno); ++ while ((ret = ioctl(s->fd, VIDIOC_REQBUFS, &req)) == -1) { ++ if (errno != EINTR) { ++ ret = AVERROR(errno); ++ av_log(logger(ctx), AV_LOG_ERROR, "%s VIDIOC_REQBUFS failed: %s\n", ctx->name, av_err2str(ret)); ++ return ret; ++ } + } + + ctx->num_buffers = req.count; +- ctx->buffers = av_mallocz(ctx->num_buffers * sizeof(V4L2Buffer)); +- if (!ctx->buffers) { ++ ctx->bufrefs = av_mallocz(ctx->num_buffers * sizeof(*ctx->bufrefs)); ++ if (!ctx->bufrefs) { + av_log(logger(ctx), AV_LOG_ERROR, "%s malloc enomem\n", ctx->name); +- return AVERROR(ENOMEM); ++ goto fail_release; + } + +- for (i = 0; i < req.count; i++) { +- ctx->buffers[i].context = ctx; +- ret = ff_v4l2_buffer_initialize(&ctx->buffers[i], i); +- if (ret < 0) { ++ ctx->wl_master = ff_weak_link_new(ctx); ++ if (!ctx->wl_master) { ++ ret = AVERROR(ENOMEM); ++ goto fail_release; ++ } ++ ++ for (i = 0; i < ctx->num_buffers; i++) { ++ ret = ff_v4l2_buffer_initialize(&ctx->bufrefs[i], i, ctx, mem); ++ if (ret) { + av_log(logger(ctx), AV_LOG_ERROR, "%s buffer[%d] initialization (%s)\n", ctx->name, i, av_err2str(ret)); +- goto error; ++ goto fail_release; + } + } + + av_log(logger(ctx), AV_LOG_DEBUG, "%s: %s %02d buffers initialized: %04ux%04u, sizeimage %08u, bytesperline %08u\n", ctx->name, + V4L2_TYPE_IS_MULTIPLANAR(ctx->type) ? av_fourcc2str(ctx->format.fmt.pix_mp.pixelformat) : av_fourcc2str(ctx->format.fmt.pix.pixelformat), + req.count, +- v4l2_get_width(&ctx->format), +- v4l2_get_height(&ctx->format), ++ ff_v4l2_get_format_width(&ctx->format), ++ ff_v4l2_get_format_height(&ctx->format), + V4L2_TYPE_IS_MULTIPLANAR(ctx->type) ? ctx->format.fmt.pix_mp.plane_fmt[0].sizeimage : ctx->format.fmt.pix.sizeimage, + V4L2_TYPE_IS_MULTIPLANAR(ctx->type) ? ctx->format.fmt.pix_mp.plane_fmt[0].bytesperline : ctx->format.fmt.pix.bytesperline); + + return 0; + +-error: ++fail_release: + v4l2_release_buffers(ctx); ++ av_freep(&ctx->bufrefs); ++ return ret; ++} ++ ++int ff_v4l2_context_frames_set(V4L2Context *const ctx) ++{ ++ AVHWFramesContext *hwframes; ++ V4L2m2mContext * const s = ctx_to_m2mctx(ctx); ++ const int w = ctx->width != 0 ? ctx->width : s->avctx->width; ++ const int h = ctx->height != 0 ? ctx->height : s->avctx->height; ++ int ret; ++ ++ if (ctx->frames_ref != NULL) { ++ const AVHWFramesContext * const hwf = (AVHWFramesContext*)ctx->frames_ref->data; ++ if (hwf->sw_format == ctx->av_pix_fmt && hwf->width == w && hwf->height == h) ++ return 0; ++ av_buffer_unref(&ctx->frames_ref); ++ } ++ ++ ctx->frames_ref = av_hwframe_ctx_alloc(s->device_ref); ++ if (!ctx->frames_ref) ++ return AVERROR(ENOMEM); + +- av_freep(&ctx->buffers); ++ hwframes = (AVHWFramesContext*)ctx->frames_ref->data; ++ hwframes->format = AV_PIX_FMT_DRM_PRIME; ++ hwframes->sw_format = ctx->av_pix_fmt; ++ hwframes->width = w; ++ hwframes->height = h; ++ ret = av_hwframe_ctx_init(ctx->frames_ref); ++ if (ret < 0) { ++ av_log(s->avctx, AV_LOG_ERROR, "Failed to create hwframes context: %s\n", av_err2str(ret)); ++ av_buffer_unref(&ctx->frames_ref); ++ return ret; ++ } ++ ++ av_log(s->avctx, AV_LOG_DEBUG, "%s: HWFramesContext set to %s, %dx%d\n", __func__, ++ av_get_pix_fmt_name(ctx->av_pix_fmt), w, h); ++ return 0; ++} ++ ++int ff_v4l2_context_init(V4L2Context* ctx) ++{ ++ struct v4l2_queryctrl qctrl; ++ V4L2m2mContext * const s = ctx_to_m2mctx(ctx); ++ int ret; ++ ++ // It is not valid to reinit a context without a previous release ++ av_assert0(ctx->bufrefs == NULL); ++ ++ if (!v4l2_type_supported(ctx)) { ++ av_log(logger(ctx), AV_LOG_ERROR, "type %i not supported\n", ctx->type); ++ return AVERROR_PATCHWELCOME; ++ } ++ ++ ff_mutex_init(&ctx->lock, NULL); ++ pthread_cond_init(&ctx->cond, NULL); ++ atomic_init(&ctx->q_count, 0); ++ ++ ret = ioctl(s->fd, VIDIOC_G_FMT, &ctx->format); ++ if (ret) { ++ ret = AVERROR(errno); ++ av_log(logger(ctx), AV_LOG_ERROR, "%s VIDIOC_G_FMT failed: %s\n", ctx->name, av_err2str(ret)); ++ goto fail_unlock; ++ } ++ ++ memset(&qctrl, 0, sizeof(qctrl)); ++ qctrl.id = V4L2_CID_MIN_BUFFERS_FOR_OUTPUT; ++ if (ioctl(s->fd, VIDIOC_QUERYCTRL, &qctrl) != 0) { ++ ret = AVERROR(errno); ++ if (ret != AVERROR(EINVAL)) { ++ av_log(logger(ctx), AV_LOG_ERROR, "%s VIDIOC_QUERCTRL failed: %s\n", ctx->name, av_err2str(ret)); ++ goto fail_unlock; ++ } ++ // Control unsupported - set default if wanted ++ if (ctx->num_buffers < 2) ++ ctx->num_buffers = 4; ++ } ++ else { ++ if (ctx->num_buffers < 2) ++ ctx->num_buffers = qctrl.minimum + 2; ++ ctx->num_buffers = av_clip(ctx->num_buffers, qctrl.minimum, qctrl.maximum); ++ } ++ ++ ret = create_buffers(ctx, ctx->num_buffers, ctx->buf_mem); ++ if (ret < 0) ++ goto fail_unlock; ++ ++ return 0; + ++fail_unlock: ++ ff_mutex_destroy(&ctx->lock); + return ret; + } +diff --git a/libavcodec/v4l2_context.h b/libavcodec/v4l2_context.h +index 6f7460c89a9d..9f1c05a918ff 100644 +--- a/libavcodec/v4l2_context.h ++++ b/libavcodec/v4l2_context.h +@@ -32,6 +32,8 @@ + #include "libavutil/rational.h" + #include "codec_id.h" + #include "packet.h" ++#include "libavutil/buffer.h" ++#include "libavutil/thread.h" + #include "v4l2_buffers.h" + + typedef struct V4L2Context { +@@ -71,28 +73,57 @@ typedef struct V4L2Context { + */ + int width, height; + AVRational sample_aspect_ratio; ++ struct v4l2_rect selection; + + /** +- * Indexed array of V4L2Buffers ++ * If the default size of buffer is less than this then try to ++ * set to this. + */ +- V4L2Buffer *buffers; ++ uint32_t min_buf_size; ++ ++ /** ++ * Indexed array of pointers to V4L2Buffers ++ */ ++ AVBufferRef **bufrefs; + + /** + * Readonly after init. + */ + int num_buffers; + ++ /** ++ * Buffer memory type V4L2_MEMORY_MMAP or V4L2_MEMORY_DMABUF ++ */ ++ enum v4l2_memory buf_mem; ++ + /** + * Whether the stream has been started (VIDIOC_STREAMON has been sent). + */ + int streamon; + ++ /* 1st buffer after stream on */ ++ int first_buf; ++ + /** + * Either no more buffers available or an unrecoverable error was notified + * by the V4L2 kernel driver: once set the context has to be exited. + */ + int done; + ++ int flag_last; ++ ++ /** ++ * If NZ then when Qing frame/pkt use this rather than the ++ * "real" PTS ++ */ ++ uint64_t track_ts; ++ ++ AVBufferRef *frames_ref; ++ atomic_int q_count; ++ struct ff_weak_link_master *wl_master; ++ ++ AVMutex lock; ++ pthread_cond_t cond; + } V4L2Context; + + /** +@@ -103,6 +134,14 @@ typedef struct V4L2Context { + */ + int ff_v4l2_context_init(V4L2Context* ctx); + ++/** ++ * (re)set the hwframecontext from the current v4l2 context ++ * ++ * @param[in] ctx A pointer to a V4L2Context. See V4L2Context description for required variables. ++ * @return 0 in case of success, a negative value representing the error otherwise. ++ */ ++int ff_v4l2_context_frames_set(V4L2Context *const ctx); ++ + /** + * Sets the V4L2Context format in the v4l2 driver. + * +@@ -120,6 +159,19 @@ int ff_v4l2_context_set_format(V4L2Context* ctx); + */ + int ff_v4l2_context_get_format(V4L2Context* ctx, int probe); + ++/** ++ * Get the list of drm fourcc pixel formats for this context ++ * ++ * @param[in] ctx A pointer to a V4L2Context. See V4L2Context ++ * description for required variables. ++ * @param[in] pN A pointer to receive the number of formats ++ * found. May be NULL if not wanted. ++ * @return Pointer to malloced list of zero terminated formats, ++ * NULL if none or error. As list is malloced it must be ++ * freed. ++ */ ++uint32_t * ff_v4l2_context_enum_drm_formats(V4L2Context *ctx, unsigned int *pN); ++ + /** + * Releases a V4L2Context. + * +@@ -148,7 +200,7 @@ int ff_v4l2_context_set_status(V4L2Context* ctx, uint32_t cmd); + * @param[inout] pkt The AVPacket to dequeue to. + * @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_packet(V4L2Context* ctx, AVPacket* pkt); ++int ff_v4l2_context_dequeue_packet(V4L2Context* ctx, AVPacket* pkt, int timeout); + + /** + * Dequeues a buffer from a V4L2Context to an AVFrame. +@@ -157,7 +209,10 @@ 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) ++ * + * @return 0 in case of success, AVERROR(EAGAIN) if no buffer was ready, another negative error in case of error. ++ * AVERROR(ENOSPC) if no buffer availible to put ++ * the frame in + */ + int ff_v4l2_context_dequeue_frame(V4L2Context* ctx, AVFrame* f, int timeout); + +@@ -171,7 +226,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); + + /** + * Enqueues a buffer to a V4L2Context from an AVFrame +@@ -184,4 +239,28 @@ int ff_v4l2_context_enqueue_packet(V4L2Context* ctx, const AVPacket* pkt); + */ + int ff_v4l2_context_enqueue_frame(V4L2Context* ctx, const AVFrame* f); + ++/** ++ * Dequeue all buffers on this queue ++ * ++ * Used to recycle output buffers ++ * ++ * @param[in] ctx The V4L2Context to dequeue from. ++ * @param[in] timeout1 A timeout on dequeuing the 1st buffer, ++ * all others have a timeout of zero ++ * @return AVERROR(EAGAIN) if timeout1 non-zero then the return ++ * of the first dequeue operation, 0 otherwise. ++ */ ++int ff_v4l2_dq_all(V4L2Context *const ctx, int timeout1); ++ ++/** ++ * Returns the number of buffers currently queued ++ * ++ * @param[in] ctx The V4L2Context to evaluate ++ */ ++static inline int ++ff_v4l2_context_q_count(const V4L2Context* const ctx) ++{ ++ return atomic_load(&ctx->q_count); ++} ++ + #endif // AVCODEC_V4L2_CONTEXT_H +diff --git a/libavcodec/v4l2_fmt.c b/libavcodec/v4l2_fmt.c +index 6df47e3f5a3c..c820a1d5227b 100644 +--- a/libavcodec/v4l2_fmt.c ++++ b/libavcodec/v4l2_fmt.c +@@ -42,6 +42,14 @@ static const struct fmt_conversion { + { AV_FMT(RGB24), AV_CODEC(RAWVIDEO), V4L2_FMT(RGB24) }, + { AV_FMT(BGR0), AV_CODEC(RAWVIDEO), V4L2_FMT(BGR32) }, + { AV_FMT(0RGB), AV_CODEC(RAWVIDEO), V4L2_FMT(RGB32) }, ++ { AV_FMT(BGR0), AV_CODEC(RAWVIDEO), V4L2_FMT(BGRX32) }, ++ { AV_FMT(RGB0), AV_CODEC(RAWVIDEO), V4L2_FMT(RGBX32) }, ++ { AV_FMT(0BGR), AV_CODEC(RAWVIDEO), V4L2_FMT(XBGR32) }, ++ { AV_FMT(0RGB), AV_CODEC(RAWVIDEO), V4L2_FMT(XRGB32) }, ++ { AV_FMT(BGRA), AV_CODEC(RAWVIDEO), V4L2_FMT(BGRA32) }, ++ { AV_FMT(RGBA), AV_CODEC(RAWVIDEO), V4L2_FMT(RGBA32) }, ++ { AV_FMT(ABGR), AV_CODEC(RAWVIDEO), V4L2_FMT(ABGR32) }, ++ { AV_FMT(ARGB), AV_CODEC(RAWVIDEO), V4L2_FMT(ARGB32) }, + { AV_FMT(GRAY8), AV_CODEC(RAWVIDEO), V4L2_FMT(GREY) }, + { AV_FMT(YUV420P), AV_CODEC(RAWVIDEO), V4L2_FMT(YUV420) }, + { AV_FMT(YUYV422), AV_CODEC(RAWVIDEO), V4L2_FMT(YUYV) }, +diff --git a/libavcodec/v4l2_m2m.c b/libavcodec/v4l2_m2m.c +index 15415cfc4eea..286191f6620c 100644 +--- a/libavcodec/v4l2_m2m.c ++++ b/libavcodec/v4l2_m2m.c +@@ -36,6 +36,15 @@ + #include "v4l2_context.h" + #include "v4l2_fmt.h" + #include "v4l2_m2m.h" ++#include "v4l2_req_dmabufs.h" ++ ++static void ++xlat_init(xlat_track_t * const x) ++{ ++ memset(x, 0, sizeof(*x)); ++ x->last_pts = AV_NOPTS_VALUE; ++} ++ + + static inline int v4l2_splane_video(struct v4l2_capability *cap) + { +@@ -69,7 +78,9 @@ static int v4l2_prepare_contexts(V4L2m2mContext *s, int probe) + + s->capture.done = s->output.done = 0; + s->capture.name = "capture"; ++ s->capture.buf_mem = s->db_ctl != NULL ? V4L2_MEMORY_DMABUF : V4L2_MEMORY_MMAP; + s->output.name = "output"; ++ s->output.buf_mem = s->input_drm ? V4L2_MEMORY_DMABUF : V4L2_MEMORY_MMAP; + atomic_init(&s->refcount, 0); + sem_init(&s->refsync, 0, 0); + +@@ -86,18 +97,58 @@ static int v4l2_prepare_contexts(V4L2m2mContext *s, int probe) + if (v4l2_mplane_video(&cap)) { + s->capture.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + s->output.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; ++ s->output.format.type = s->output.type; + return 0; + } + + if (v4l2_splane_video(&cap)) { + s->capture.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + s->output.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; ++ s->output.format.type = s->output.type; + return 0; + } + + return AVERROR(EINVAL); + } + ++static int check_size(AVCodecContext * const avctx, V4L2m2mContext * const s) ++{ ++ struct v4l2_format fmt = {.type = s->output.type}; ++ int rv; ++ uint32_t pixfmt = ff_v4l2_format_avfmt_to_v4l2(avctx->pix_fmt); ++ unsigned int w; ++ unsigned int h; ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(fmt.type)) { ++ fmt.fmt.pix_mp.pixelformat = pixfmt; ++ fmt.fmt.pix_mp.width = avctx->width; ++ fmt.fmt.pix_mp.height = avctx->height; ++ } ++ else { ++ fmt.fmt.pix.pixelformat = pixfmt; ++ fmt.fmt.pix.width = avctx->width; ++ fmt.fmt.pix.height = avctx->height; ++ } ++ ++ rv = ioctl(s->fd, VIDIOC_TRY_FMT, &fmt); ++ ++ if (rv != 0) { ++ rv = AVERROR(errno); ++ av_log(avctx, AV_LOG_ERROR, "%s: Tryfmt failed: %s\n", __func__, av_err2str(rv)); ++ return rv; ++ } ++ ++ w = ff_v4l2_get_format_width(&fmt); ++ h = ff_v4l2_get_format_height(&fmt); ++ ++ if (w < avctx->width || h < avctx->height) { ++ av_log(avctx, AV_LOG_WARNING, "%s: Size check failed: asked for %dx%d, got: %dx%d\n", __func__, avctx->width, avctx->height, w, h); ++ return AVERROR(EINVAL); ++ } ++ ++ return 0; ++} ++ + static int v4l2_probe_driver(V4L2m2mContext *s) + { + void *log_ctx = s->avctx; +@@ -117,6 +168,11 @@ static int v4l2_probe_driver(V4L2m2mContext *s) + goto done; + } + ++ // If being given frames (encode) check that V4L2 can cope with the size ++ if (s->output.av_codec_id == AV_CODEC_ID_RAWVIDEO && ++ (ret = check_size(s->avctx, s)) != 0) ++ goto done; ++ + ret = ff_v4l2_context_get_format(&s->capture, 1); + if (ret) { + av_log(log_ctx, AV_LOG_DEBUG, "v4l2 capture format not supported\n"); +@@ -218,13 +274,7 @@ int ff_v4l2_m2m_codec_reinit(V4L2m2mContext *s) + av_log(log_ctx, AV_LOG_ERROR, "capture VIDIOC_STREAMOFF\n"); + + /* 2. unmap the capture buffers (v4l2 and ffmpeg): +- * we must wait for all references to be released before being allowed +- * to queue new buffers. + */ +- av_log(log_ctx, AV_LOG_DEBUG, "waiting for user to release AVBufferRefs\n"); +- if (atomic_load(&s->refcount)) +- while(sem_wait(&s->refsync) == -1 && errno == EINTR); +- + ff_v4l2_context_release(&s->capture); + + /* 3. get the new capture format */ +@@ -243,7 +293,6 @@ int ff_v4l2_m2m_codec_reinit(V4L2m2mContext *s) + + /* 5. complete reinit */ + s->draining = 0; +- s->reinit = 0; + + return 0; + } +@@ -259,6 +308,9 @@ static void v4l2_m2m_destroy_context(FFRefStructOpaque unused, void *context) + close(s->fd); + av_frame_free(&s->frame); + av_packet_unref(&s->buf_pkt); ++ av_freep(&s->extdata_data); ++ ++ av_log(s->avctx, AV_LOG_DEBUG, "V4L2 Context destroyed\n"); + } + + int ff_v4l2_m2m_codec_end(V4L2m2mPriv *priv) +@@ -269,6 +321,11 @@ int ff_v4l2_m2m_codec_end(V4L2m2mPriv *priv) + if (!s) + return 0; + ++ av_log(s->avctx, AV_LOG_DEBUG, "V4L2 Codec end\n"); ++ ++ if (s->avctx && 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) +@@ -280,6 +337,14 @@ int ff_v4l2_m2m_codec_end(V4L2m2mPriv *priv) + } + + ff_v4l2_context_release(&s->output); ++ av_buffer_unref(&s->device_ref); ++ ++ dmabufs_ctl_unref(&s->db_ctl); ++ ++ if (s->fd != -1) { ++ close(s->fd); ++ s->fd = -1; ++ } + + s->self_ref = NULL; + ff_refstruct_unref(&priv->context); +@@ -341,6 +406,7 @@ int ff_v4l2_m2m_create_context(V4L2m2mPriv *priv, V4L2m2mContext **s) + priv->context->output.num_buffers = priv->num_output_buffers; + priv->context->self_ref = priv->context; + priv->context->fd = -1; ++ xlat_init(&priv->context->xlat); + + priv->context->frame = av_frame_alloc(); + if (!priv->context->frame) { +diff --git a/libavcodec/v4l2_m2m.h b/libavcodec/v4l2_m2m.h +index 4ba33dc33593..cb49e0c2fe66 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) ({ \ +@@ -40,6 +41,38 @@ + { "num_output_buffers", "Number of buffers in the output context",\ + 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 pending; ++ int64_t pts; ++ int64_t dts; ++#if FF_API_FRAME_PKT ++ int64_t pkt_pos; ++ int pkt_size; ++#endif ++ int64_t duration; ++ int64_t track_pts; ++} V4L2m2mTrackEl; ++ ++typedef struct pts_stats_s ++{ ++ void * logctx; ++ const char * name; // For debug ++ unsigned int last_count; ++ unsigned int last_interval; ++ int64_t last_pts; ++ int64_t guess; ++} pts_stats_t; ++ ++typedef struct xlat_track_s { ++ unsigned int track_no; ++ int64_t last_pts; // Last valid PTS decoded ++ V4L2m2mTrackEl track_els[FF_V4L2_M2M_TRACK_SIZE]; ++} xlat_track_t; ++ ++struct dmabufs_ctl; ++ + typedef struct V4L2m2mContext { + char devname[PATH_MAX]; + int fd; +@@ -52,10 +85,10 @@ typedef struct V4L2m2mContext { + AVCodecContext *avctx; + sem_t refsync; + atomic_uint refcount; +- int reinit; + + /* null frame/packet received */ + int draining; ++ int running; + AVPacket buf_pkt; + + /* Reference to a frame. Only used during encoding */ +@@ -66,6 +99,36 @@ typedef struct V4L2m2mContext { + + /* reference back to V4L2m2mPriv */ + void *priv; ++ ++ AVBufferRef *device_ref; ++ ++ /* generate DRM frames */ ++ int output_drm; ++ ++ /* input frames are drmprime */ ++ int input_drm; ++ ++ /* Frame tracking */ ++ xlat_track_t xlat; ++ ++ pts_stats_t pts_stat; ++ ++ /* req pkt */ ++ int req_pkt; ++ int reorder_size; ++ ++ /* Ext data sent */ ++ int extdata_sent; ++ /* Ext data sent in packet - overrides ctx */ ++ void * extdata_data; ++ size_t extdata_size; ++ ++#define FF_V4L2_QUIRK_REINIT_ALWAYS 1 ++#define FF_V4L2_QUIRK_ENUM_FRAMESIZES_BROKEN 2 ++ /* Quirks */ ++ unsigned int quirks; ++ ++ struct dmabufs_ctl * db_ctl; + } V4L2m2mContext; + + typedef struct V4L2m2mPriv { +@@ -75,6 +138,8 @@ typedef struct V4L2m2mPriv { + + int num_output_buffers; + int num_capture_buffers; ++ const char * dmabuf_alloc; ++ enum AVPixelFormat pix_fmt; + } V4L2m2mPriv; + + /** +@@ -128,4 +193,26 @@ int ff_v4l2_m2m_codec_reinit(V4L2m2mContext *ctx); + */ + int ff_v4l2_m2m_codec_full_reinit(V4L2m2mContext *ctx); + ++ ++static inline unsigned int ff_v4l2_get_format_width(const struct v4l2_format * const fmt) ++{ ++ return V4L2_TYPE_IS_MULTIPLANAR(fmt->type) ? fmt->fmt.pix_mp.width : fmt->fmt.pix.width; ++} ++ ++static inline unsigned int ff_v4l2_get_format_height(const struct v4l2_format * const fmt) ++{ ++ return V4L2_TYPE_IS_MULTIPLANAR(fmt->type) ? fmt->fmt.pix_mp.height : fmt->fmt.pix.height; ++} ++ ++static inline uint32_t ff_v4l2_get_format_pixelformat(const struct v4l2_format * const fmt) ++{ ++ return V4L2_TYPE_IS_MULTIPLANAR(fmt->type) ? fmt->fmt.pix_mp.pixelformat : fmt->fmt.pix.pixelformat; ++} ++ ++static inline int ff_v4l2_ctx_eos(const V4L2Context * const ctx) ++{ ++ return ctx->flag_last; ++} ++ ++ + #endif /* AVCODEC_V4L2_M2M_H */ +diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c +index aa2d759e1ea5..d3c3820379dd 100644 +--- a/libavcodec/v4l2_m2m_dec.c ++++ b/libavcodec/v4l2_m2m_dec.c +@@ -21,8 +21,15 @@ + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + ++#include "config_components.h" ++ + #include + #include ++ ++#include "libavutil/avassert.h" ++#include "libavutil/hwcontext.h" ++#include "libavutil/hwcontext_drm.h" ++#include "libavutil/mem.h" + #include "libavutil/pixfmt.h" + #include "libavutil/pixdesc.h" + #include "libavutil/opt.h" +@@ -30,75 +37,279 @@ + #include "codec_internal.h" + #include "libavcodec/decode.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" ++#include "v4l2_req_dmabufs.h" + +-static int v4l2_try_start(AVCodecContext *avctx) ++#if CONFIG_H264_DECODER ++#include "h264_parse.h" ++#endif ++#if CONFIG_HEVC_DECODER ++#include "hevc/parse.h" ++#endif ++ ++// Pick 64 for max last count - that is >1sec at 60fps ++#define STATS_LAST_COUNT_MAX 64 ++#define STATS_INTERVAL_MAX (1 << 30) ++ ++#ifndef FF_API_BUFFER_SIZE_T ++#define FF_API_BUFFER_SIZE_T 1 ++#endif ++ ++#define DUMP_FAILED_EXTRADATA 0 ++ ++#if DUMP_FAILED_EXTRADATA ++static inline char hex1(unsigned int x) + { +- V4L2m2mContext *s = ((V4L2m2mPriv*)avctx->priv_data)->context; +- V4L2Context *const capture = &s->capture; +- V4L2Context *const output = &s->output; +- struct v4l2_selection selection = { 0 }; +- int ret; ++ x &= 0xf; ++ return x <= 9 ? '0' + x : 'a' + x - 10; ++} + +- /* 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; +- } ++static inline char * hex2(char * s, unsigned int x) ++{ ++ *s++ = hex1(x >> 4); ++ *s++ = hex1(x); ++ return s; ++} ++ ++static inline char * hex4(char * s, unsigned int x) ++{ ++ s = hex2(s, x >> 8); ++ s = hex2(s, x); ++ return s; ++} ++ ++static inline char * dash2(char * s) ++{ ++ *s++ = '-'; ++ *s++ = '-'; ++ return s; ++} ++ ++static void ++data16(char * s, const unsigned int offset, const uint8_t * m, const size_t len) ++{ ++ size_t i; ++ s = hex4(s, offset); ++ m += offset; ++ for (i = 0; i != 8; ++i) { ++ *s++ = ' '; ++ s = len > i + offset ? hex2(s, *m++) : dash2(s); + } ++ *s++ = ' '; ++ *s++ = ':'; ++ for (; i != 16; ++i) { ++ *s++ = ' '; ++ s = len > i + offset ? hex2(s, *m++) : dash2(s); ++ } ++ *s++ = 0; ++} + +- if (capture->streamon) +- return 0; ++static void ++log_dump(void * logctx, int lvl, const void * const data, const size_t len) ++{ ++ size_t i; ++ for (i = 0; i < len; i += 16) { ++ char buf[80]; ++ data16(buf, i, data, len); ++ av_log(logctx, lvl, "%s\n", buf); ++ } ++} ++#endif + +- /* 2. get the capture format */ +- capture->format.type = capture->type; +- ret = ioctl(s->fd, VIDIOC_G_FMT, &capture->format); +- if (ret) { +- av_log(avctx, AV_LOG_WARNING, "VIDIOC_G_FMT ioctl\n"); +- return ret; ++static unsigned int pts_stats_interval(const pts_stats_t * const stats) ++{ ++ return stats->last_interval; ++} ++ ++static int64_t pts_stats_guess(const pts_stats_t * const stats, const int fail_bad_guess) ++{ ++ if (stats->last_count <= 1) ++ return stats->last_pts; ++ if (stats->last_pts == AV_NOPTS_VALUE || ++ fail_bad_guess && (stats->last_interval == 0 || ++ stats->last_count >= STATS_LAST_COUNT_MAX)) ++ return AV_NOPTS_VALUE; ++ return stats->last_pts + (int64_t)(stats->last_count - 1) * (int64_t)stats->last_interval; ++} ++ ++static void pts_stats_add(pts_stats_t * const stats, int64_t pts) ++{ ++ if (pts == AV_NOPTS_VALUE || pts == stats->last_pts) { ++ if (stats->last_count < STATS_LAST_COUNT_MAX) ++ ++stats->last_count; ++ return; + } + +- /* 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; ++ if (stats->last_pts != AV_NOPTS_VALUE) { ++ const int64_t interval = pts - stats->last_pts; + +- /* 3. set the crop parameters */ +- selection.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; +- selection.r.height = avctx->coded_height; +- selection.r.width = avctx->coded_width; +- ret = ioctl(s->fd, VIDIOC_S_SELECTION, &selection); +- if (!ret) { +- ret = ioctl(s->fd, VIDIOC_G_SELECTION, &selection); +- if (ret) { +- av_log(avctx, AV_LOG_WARNING, "VIDIOC_G_SELECTION ioctl\n"); +- } else { +- av_log(avctx, AV_LOG_DEBUG, "crop output %dx%d\n", selection.r.width, selection.r.height); +- /* update the size of the resulting frame */ +- capture->height = selection.r.height; +- capture->width = selection.r.width; ++ if (interval < 0 || interval >= STATS_INTERVAL_MAX || ++ stats->last_count >= STATS_LAST_COUNT_MAX) { ++ if (stats->last_interval != 0) ++ av_log(stats->logctx, AV_LOG_DEBUG, "%s: %s: Bad interval: %" PRId64 "/%d\n", ++ __func__, stats->name, interval, stats->last_count); ++ stats->last_interval = 0; ++ } ++ else { ++ const int64_t frame_time = interval / (int64_t)stats->last_count; ++ ++ if (frame_time != stats->last_interval) ++ av_log(stats->logctx, AV_LOG_DEBUG, "%s: %s: New interval: %u->%" PRId64 "/%d=%" PRId64 "\n", ++ __func__, stats->name, stats->last_interval, interval, stats->last_count, frame_time); ++ stats->last_interval = frame_time; + } + } + +- /* 4. init the capture context now that we have the capture format */ +- if (!capture->buffers) { +- ret = ff_v4l2_context_init(capture); +- if (ret) { +- av_log(avctx, AV_LOG_ERROR, "can't request capture buffers\n"); +- return AVERROR(ENOMEM); ++ stats->last_pts = pts; ++ stats->last_count = 1; ++} ++ ++static void pts_stats_init(pts_stats_t * const stats, void * logctx, const char * name) ++{ ++ *stats = (pts_stats_t){ ++ .logctx = logctx, ++ .name = name, ++ .last_count = 1, ++ .last_interval = 0, ++ .last_pts = AV_NOPTS_VALUE ++ }; ++} ++ ++// If abdata == NULL then this just counts space required ++// Unpacks avcC if detected ++static int ++h264_xd_copy(const uint8_t * const extradata, const int extrasize, uint8_t * abdata) ++{ ++ const uint8_t * const xdend = extradata + extrasize; ++ const uint8_t * p = extradata; ++ uint8_t * d = abdata; ++ unsigned int n; ++ unsigned int len; ++ const unsigned int hdrlen = 4; ++ unsigned int need_pps = 1; ++ ++ if (extrasize < 8) ++ return AVERROR(EINVAL); ++ ++ if (p[0] == 0 && p[1] == 0) { ++ // Assume a couple of leading zeros are good enough to indicate NAL ++ if (abdata) ++ memcpy(d, p, extrasize); ++ return extrasize; ++ } ++ ++ // avcC starts with a 1 ++ if (p[0] != 1) ++ return AVERROR(EINVAL); ++ ++ p += 5; ++ n = *p++ & 0x1f; ++ ++doxps: ++ while (n--) { ++ if (xdend - p < 2) ++ return AVERROR(EINVAL); ++ len = (p[0] << 8) | p[1]; ++ p += 2; ++ if (xdend - p < (ptrdiff_t)len) ++ return AVERROR(EINVAL); ++ if (abdata) { ++ d[0] = 0; ++ d[1] = 0; ++ d[2] = 0; ++ d[3] = 1; ++ memcpy(d + 4, p, len); + } ++ d += len + hdrlen; ++ p += len; ++ } ++ if (need_pps) { ++ need_pps = 0; ++ if (p >= xdend) ++ return AVERROR(EINVAL); ++ n = *p++; ++ goto doxps; + } + +- /* 5. start the capture process */ +- ret = ff_v4l2_context_set_status(capture, VIDIOC_STREAMON); +- if (ret) { +- av_log(avctx, AV_LOG_DEBUG, "VIDIOC_STREAMON, on capture context\n"); ++ return d - abdata; ++} ++ ++static int ++copy_extradata(AVCodecContext * const avctx, ++ const void * const src_data, const int src_len, ++ void ** const pdst_data, size_t * const pdst_len) ++{ ++ int len; ++ ++ *pdst_len = 0; ++ av_freep(pdst_data); ++ ++ if (avctx->codec_id == AV_CODEC_ID_H264) ++ len = h264_xd_copy(src_data, src_len, NULL); ++ else ++ len = src_len < 0 ? AVERROR(EINVAL) : src_len; ++ ++ // Zero length is OK but we want to stop - -ve is error val ++ if (len <= 0) ++ return len; ++ ++ if ((*pdst_data = av_malloc(len + AV_INPUT_BUFFER_PADDING_SIZE)) == NULL) ++ return AVERROR(ENOMEM); ++ ++ if (avctx->codec_id == AV_CODEC_ID_H264) ++ h264_xd_copy(src_data, src_len, *pdst_data); ++ else ++ memcpy(*pdst_data, src_data, len); ++ *pdst_len = len; ++ ++ return 0; ++} ++ ++ ++ ++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: %s\n", av_err2str(ret)); + return ret; + } + ++ // STREAMON should do implicit START so this just for those that don't. ++ // It is optional so don't worry if it fails ++ if (ioctl(s->fd, VIDIOC_DECODER_CMD, &cmd) < 0) { ++ ret = AVERROR(errno); ++ av_log(avctx, AV_LOG_WARNING, "VIDIOC_DECODER_CMD start error: %s\n", av_err2str(ret)); ++ } ++ else { ++ av_log(avctx, AV_LOG_TRACE, "VIDIOC_DECODER_CMD start OK\n"); ++ } ++ return 0; ++} ++ ++static int v4l2_try_start(AVCodecContext *avctx) ++{ ++ V4L2m2mContext * const s = ((V4L2m2mPriv*)avctx->priv_data)->context; ++ int ret; ++ ++ /* 1. start the output process */ ++ if ((ret = check_output_streamon(avctx, s)) != 0) ++ return ret; + return 0; + } + +@@ -133,51 +344,822 @@ static int v4l2_prepare_decoder(V4L2m2mContext *s) + return 0; + } + +-static int v4l2_receive_frame(AVCodecContext *avctx, AVFrame *frame) ++static void ++set_best_effort_pts(AVCodecContext *const avctx, ++ pts_stats_t * const ps, ++ AVFrame *const frame) ++{ ++ pts_stats_add(ps, frame->pts); ++ ++ frame->best_effort_timestamp = pts_stats_guess(ps, 1); ++ // If we can't guess from just PTS - try DTS ++ if (frame->best_effort_timestamp == AV_NOPTS_VALUE) ++ frame->best_effort_timestamp = frame->pkt_dts; ++ ++ // We can't emulate what s/w does in a useful manner and using the ++ // "correct" answer seems to just confuse things. ++ frame->pkt_dts = frame->pts; ++ av_log(avctx, AV_LOG_TRACE, "Out PTS=%" PRId64 "/%"PRId64", DTS=%" PRId64 "\n", ++ frame->pts, frame->best_effort_timestamp, frame->pkt_dts); ++} ++ ++static void ++xlat_flush(xlat_track_t * const x) ++{ ++ unsigned int i; ++ // Do not reset track_no - this ensures that any frames left in the decoder ++ // that turn up later get discarded. ++ ++ x->last_pts = AV_NOPTS_VALUE; ++ for (i = 0; i != FF_V4L2_M2M_TRACK_SIZE; ++i) { ++ x->track_els[i].pending = 0; ++ x->track_els[i].discard = 1; ++ } ++} ++ ++static void ++xlat_init(xlat_track_t * const x) ++{ ++ memset(x, 0, sizeof(*x)); ++ xlat_flush(x); ++} ++ ++static int ++xlat_pending(const V4L2m2mContext * const s) ++{ ++ const xlat_track_t *const x = &s->xlat; ++ unsigned int n = x->track_no % FF_V4L2_M2M_TRACK_SIZE; ++ int i; ++ const int64_t now = pts_stats_guess(&s->pts_stat, 0); ++ int64_t first_dts = AV_NOPTS_VALUE; ++ int no_dts_count = 0; ++ unsigned int interval = pts_stats_interval(&s->pts_stat); ++ ++ for (i = 0; i < FF_V4L2_M2M_TRACK_SIZE; ++i, n = (n - 1) & (FF_V4L2_M2M_TRACK_SIZE - 1)) { ++ const V4L2m2mTrackEl * const t = x->track_els + n; ++ ++ if (first_dts == AV_NOPTS_VALUE) ++ if (t->dts == AV_NOPTS_VALUE) ++ ++no_dts_count; ++ else ++ first_dts = t->dts; ++ ++ // Discard only set on never-set or flushed entries ++ // So if we get here we've never successfully decoded a frame so allow ++ // more frames into the buffer before stalling ++ if (t->discard) ++ return i - 16; ++ ++ // If we've got this frame out then everything before this point ++ // must have entered the decoder ++ if (!t->pending) ++ break; ++ ++ // If we've never seen a pts all we can do is count frames ++ if (now == AV_NOPTS_VALUE) ++ continue; ++ ++ if (t->dts != AV_NOPTS_VALUE && now >= t->dts) ++ break; ++ } ++ ++ if (first_dts != AV_NOPTS_VALUE && now != AV_NOPTS_VALUE && interval != 0 && s->reorder_size != 0) { ++ const int iframes = (first_dts - now) / (int)interval; ++ const int t = iframes - s->reorder_size + no_dts_count; ++ ++// av_log(s->avctx, AV_LOG_DEBUG, "Last:%"PRId64", Now:%"PRId64", First:%"PRId64", delta=%"PRId64", frames=%d, nodts=%d\n", ++// x->last_dts, now, first_dts, first_dts - now, iframes, no_dts_count); ++ ++ if (iframes > 0 && iframes < 64 && t < i) { ++ return t; ++ } ++ } ++ ++ return i; ++} ++ ++static inline int stream_started(const V4L2m2mContext * const s) { ++ return s->output.streamon; ++} ++ ++#define NQ_OK 0 ++#define NQ_Q_FULL 1 ++#define NQ_SRC_EMPTY 2 ++#define NQ_NONE 3 ++#define NQ_DRAINING 4 ++#define NQ_DEAD 5 ++ ++#define TRY_DQ(nq_status) ((nq_status) >= NQ_OK && (nq_status) <= NQ_DRAINING) ++#define RETRY_NQ(nq_status) ((nq_status) == NQ_Q_FULL || (nq_status) == NQ_NONE) ++ ++// do_not_get If true then no new packet will be got but status will ++// be set appropriately ++ ++// 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_NONE Enqueue not attempted ++// 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, const int do_not_get) + { +- V4L2m2mContext *s = ((V4L2m2mPriv*)avctx->priv_data)->context; +- V4L2Context *const capture = &s->capture; +- V4L2Context *const output = &s->output; + int ret; + +- if (!s->buf_pkt.size) { +- ret = ff_decode_get_packet(avctx, &s->buf_pkt); ++ // If we don't already have a coded packet - get a new one ++ // We will already have a coded pkt if the output Q was full last time we ++ // tried to Q it ++ if (!s->buf_pkt.size && !do_not_get) { ++ unsigned int i; ++ ++ for (i = 0; i < 256; ++i) { ++ uint8_t * side_data; ++ size_t side_size; ++ ++ ret = ff_decode_get_packet(avctx, &s->buf_pkt); ++ if (ret != 0) ++ break; ++ ++ // New extradata is the only side-data we undertand ++ side_data = av_packet_get_side_data(&s->buf_pkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size); ++ if (side_data) { ++ av_log(avctx, AV_LOG_DEBUG, "New extradata\n"); ++ if ((ret = copy_extradata(avctx, side_data, (int)side_size, &s->extdata_data, &s->extdata_size)) < 0) ++ av_log(avctx, AV_LOG_WARNING, "Failed to copy new extra data: %s\n", av_err2str(ret)); ++ s->extdata_sent = 0; ++ } ++ ++ if (s->buf_pkt.size != 0) ++ break; ++ ++ if (s->buf_pkt.side_data_elems == 0) { ++ av_log(avctx, AV_LOG_WARNING, "Empty pkt from ff_decode_get_packet - treating as EOF\n"); ++ ret = AVERROR_EOF; ++ break; ++ } ++ ++ // Retry a side-data only pkt ++ } ++ // If i >= 256 something has gone wrong ++ if (i >= 256) { ++ av_log(avctx, AV_LOG_ERROR, "Too many side-data only packets\n"); ++ return AVERROR(EIO); ++ } ++ ++ 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); ++ if (ret) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to start drain: ret=%d\n", ret); ++ return ret; ++ } ++ } ++ return NQ_DRAINING; ++ } ++ + if (ret < 0) { +- if (ret == AVERROR(EAGAIN)) +- return ff_v4l2_context_dequeue_frame(capture, frame, 0); +- else if (ret != AVERROR_EOF) +- return ret; ++ av_log(avctx, AV_LOG_ERROR, "Failed to get coded packet: err=%d\n", ret); ++ return ret; + } + } + +- if (s->draining) +- goto dequeue; ++ if (s->draining) { ++ if (s->buf_pkt.size) { ++ av_log(avctx, AV_LOG_WARNING, "Unexpected input whilst draining\n"); ++ av_packet_unref(&s->buf_pkt); ++ } ++ return NQ_DRAINING; ++ } ++ ++ if (!s->buf_pkt.size) ++ return NQ_NONE; ++ ++ if ((ret = check_output_streamon(avctx, s)) != 0) ++ return ret; + +- ret = ff_v4l2_context_enqueue_packet(output, &s->buf_pkt); +- if (ret < 0 && ret != AVERROR(EAGAIN)) +- goto fail; ++ if (s->extdata_sent) ++ ret = ff_v4l2_context_enqueue_packet(&s->output, &s->buf_pkt, NULL, 0); ++ else ++ ret = ff_v4l2_context_enqueue_packet(&s->output, &s->buf_pkt, s->extdata_data, s->extdata_size); + +- /* if EAGAIN don't unref packet and try to enqueue in the next iteration */ +- if (ret != AVERROR(EAGAIN)) ++ 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 (!s->draining) { +- ret = v4l2_try_start(avctx); + if (ret) { +- /* cant recover */ +- if (ret != AVERROR(ENOMEM)) +- ret = 0; +- goto fail; ++ av_log(avctx, AV_LOG_ERROR, "Packet enqueue failure: err=%d\n", ret); ++ return ret; ++ } ++ } ++ ++ // Start if we haven't ++ { ++ const int 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; + } + } + +-dequeue: +- return ff_v4l2_context_dequeue_frame(capture, frame, -1); +-fail: +- av_packet_unref(&s->buf_pkt); + return ret; + } + ++static int qbuf_wait(AVCodecContext * const avctx, V4L2Context * const ctx) ++{ ++ int rv = 0; ++ ++ ff_mutex_lock(&ctx->lock); ++ ++ while (atomic_load(&ctx->q_count) == 0 && ctx->streamon) { ++ if (pthread_cond_wait(&ctx->cond, &ctx->lock) != 0) { ++ rv = AVERROR(errno); ++ av_log(avctx, AV_LOG_ERROR, "Cond wait failure: %s\n", av_err2str(rv)); ++ break; ++ } ++ } ++ ++ ff_mutex_unlock(&ctx->lock); ++ return rv; ++} ++ ++static int v4l2_receive_frame(AVCodecContext *avctx, AVFrame *frame) ++{ ++ V4L2m2mContext *const s = ((V4L2m2mPriv*)avctx->priv_data)->context; ++ int src_rv = -1; ++ int dst_rv = 1; // Non-zero (done), non-negative (error) number ++ unsigned int i = 0; ++ ++ do { ++ const int pending = xlat_pending(s); ++ const int prefer_dq = (pending > 4); ++ const int last_src_rv = src_rv; ++ ++ av_log(avctx, AV_LOG_TRACE, "Pending=%d, src_rv=%d, req_pkt=%d\n", pending, src_rv, s->req_pkt); ++ ++ // Enqueue another pkt for decode if ++ // (a) We don't have a lot of stuff in the buffer already OR ++ // (b) ... we (think we) do but we've failed to get a frame already OR ++ // (c) We've dequeued a lot of frames without asking for input ++ src_rv = try_enqueue_src(avctx, s, !(!prefer_dq || i != 0 || s->req_pkt > 2)); ++ ++ // If we got a frame last time or we've already tried to get a frame 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 ((i != 0 || s->req_pkt) && src_rv == NQ_SRC_EMPTY) ++ break; ++ ++ if (src_rv == NQ_Q_FULL && last_src_rv == NQ_Q_FULL) { ++ av_log(avctx, AV_LOG_WARNING, "Poll thinks src Q has space; none found\n"); ++ break; ++ } ++ ++ // 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)) { ++ // Pick a timeout depending on state ++ // The pending count isn't completely reliable so it is good enough ++ // hint that we want a frame but not good enough to require it in ++ // all cases; however if it has got > 31 that exceeds its margin of ++ // error so require a frame to prevent ridiculous levels of latency ++ const int t = ++ src_rv == NQ_Q_FULL ? -1 : ++ src_rv == NQ_DRAINING ? 300 : ++ prefer_dq ? (s->running && pending > 31 ? 100 : 5) : 0; ++ ++ // Dequeue frame will unref any previous contents of frame ++ // if it returns success so we don't need an explicit unref ++ // when discarding ++ // This returns AVERROR(EAGAIN) on timeout or if ++ // there is room in the input Q and timeout == -1 ++ dst_rv = ff_v4l2_context_dequeue_frame(&s->capture, frame, t); ++ ++ // Failure due to no buffer in Q? ++ if (dst_rv == AVERROR(ENOSPC)) { ++ // Wait & retry ++ if ((dst_rv = qbuf_wait(avctx, &s->capture)) == 0) { ++ dst_rv = ff_v4l2_context_dequeue_frame(&s->capture, frame, t); ++ } ++ } ++ ++ if (dst_rv == 0) { ++ set_best_effort_pts(avctx, &s->pts_stat, frame); ++ if (!s->running) { ++ s->running = 1; ++ av_log(avctx, AV_LOG_VERBOSE, "Decode running\n"); ++ } ++ } ++ ++ if (dst_rv == AVERROR(EAGAIN) && src_rv == NQ_DRAINING) { ++ av_log(avctx, AV_LOG_WARNING, "Timeout in drain - assume EOF"); ++ dst_rv = AVERROR_EOF; ++ s->capture.done = 1; ++ } ++ else 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); ++ } ++ ++ ++i; ++ if (i >= 256) { ++ av_log(avctx, AV_LOG_ERROR, "Unexpectedly large retry count: %d\n", i); ++ src_rv = AVERROR(EIO); ++ } ++ ++ // Continue trying to enqueue packets if either ++ // (a) we succeeded last time OR ++ // (b) we didn't ret a frame and we can retry the input ++ } while (src_rv == NQ_OK || (dst_rv == AVERROR(EAGAIN) && RETRY_NQ(src_rv))); ++ ++ // Ensure that the frame contains nothing if we aren't returning a frame ++ // (might happen when discarding) ++ 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) ? s->req_pkt + 1 : 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 ++ ++ 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 uint32_t ++avprofile_to_v4l2(const enum AVCodecID codec_id, const int avprofile) ++{ ++ switch (codec_id) { ++ case AV_CODEC_ID_H264: ++ switch (avprofile) { ++ case FF_PROFILE_H264_BASELINE: ++ return V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE; ++ case FF_PROFILE_H264_CONSTRAINED_BASELINE: ++ return V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE; ++ case FF_PROFILE_H264_MAIN: ++ return V4L2_MPEG_VIDEO_H264_PROFILE_MAIN; ++ case FF_PROFILE_H264_EXTENDED: ++ return V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED; ++ case FF_PROFILE_H264_HIGH: ++ return V4L2_MPEG_VIDEO_H264_PROFILE_HIGH; ++ case FF_PROFILE_H264_HIGH_10: ++ return V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10; ++ case FF_PROFILE_H264_HIGH_10_INTRA: ++ return V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10_INTRA; ++ case FF_PROFILE_H264_MULTIVIEW_HIGH: ++ case FF_PROFILE_H264_HIGH_422: ++ return V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422; ++ case FF_PROFILE_H264_HIGH_422_INTRA: ++ return V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422_INTRA; ++ case FF_PROFILE_H264_STEREO_HIGH: ++ return V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH; ++ case FF_PROFILE_H264_HIGH_444_PREDICTIVE: ++ return V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE; ++ case FF_PROFILE_H264_HIGH_444_INTRA: ++ return V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_INTRA; ++ case FF_PROFILE_H264_CAVLC_444: ++ return V4L2_MPEG_VIDEO_H264_PROFILE_CAVLC_444_INTRA; ++ case FF_PROFILE_H264_HIGH_444: ++ default: ++ break; ++// V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_BASELINE = 12, ++// V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH = 13, ++// V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH_INTRA = 14, ++// V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH = 16, ++// V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH = 17, ++ } ++ break; ++ case AV_CODEC_ID_MPEG2VIDEO: ++ case AV_CODEC_ID_MPEG4: ++ case AV_CODEC_ID_VC1: ++ case AV_CODEC_ID_VP8: ++ case AV_CODEC_ID_VP9: ++ case AV_CODEC_ID_AV1: ++ // Most profiles are a simple number that matches the V4L2 enum ++ return avprofile; ++ default: ++ break; ++ } ++ return ~(uint32_t)0; ++} ++ ++// This check mirrors Chrome's profile check by testing to see if the profile ++// exists as a possible value for the V4L2 profile control ++static int ++check_profile(AVCodecContext *const avctx, V4L2m2mContext *const s) ++{ ++ struct v4l2_queryctrl query_ctrl; ++ struct v4l2_querymenu query_menu; ++ uint32_t profile_id; ++ ++ // An unset profile is almost certainly zero or -99 - do not reject ++ if (avctx->profile <= 0) { ++ av_log(avctx, AV_LOG_VERBOSE, "Profile %d <= 0 - check skipped\n", avctx->profile); ++ return 0; ++ } ++ ++ memset(&query_ctrl, 0, sizeof(query_ctrl)); ++ switch (avctx->codec_id) { ++ case AV_CODEC_ID_MPEG2VIDEO: ++ profile_id = V4L2_CID_MPEG_VIDEO_MPEG2_PROFILE; ++ break; ++ case AV_CODEC_ID_MPEG4: ++ profile_id = V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE; ++ break; ++ case AV_CODEC_ID_H264: ++ profile_id = V4L2_CID_MPEG_VIDEO_H264_PROFILE; ++ break; ++ case AV_CODEC_ID_VP8: ++ profile_id = V4L2_CID_MPEG_VIDEO_VP8_PROFILE; ++ break; ++ case AV_CODEC_ID_VP9: ++ profile_id = V4L2_CID_MPEG_VIDEO_VP9_PROFILE; ++ break; ++#ifdef V4L2_CID_MPEG_VIDEO_AV1_PROFILE ++ case AV_CODEC_ID_AV1: ++ profile_id = V4L2_CID_MPEG_VIDEO_AV1_PROFILE; ++ break; ++#endif ++ default: ++ av_log(avctx, AV_LOG_VERBOSE, "Can't map profile for codec id %d; profile check skipped\n", avctx->codec_id); ++ return 0; ++ } ++ ++ query_ctrl = (struct v4l2_queryctrl){.id = profile_id}; ++ if (ioctl(s->fd, VIDIOC_QUERYCTRL, &query_ctrl) != 0) { ++ av_log(avctx, AV_LOG_VERBOSE, "Query profile ctrl (%#x) not supported: assume OK\n", query_ctrl.id); ++ } ++ else { ++ av_log(avctx, AV_LOG_DEBUG, "%s: Control supported: %#x\n", __func__, query_ctrl.id); ++ ++ query_menu = (struct v4l2_querymenu){ ++ .id = query_ctrl.id, ++ .index = avprofile_to_v4l2(avctx->codec_id, avctx->profile), ++ }; ++ ++ if (query_menu.index > query_ctrl.maximum || ++ query_menu.index < query_ctrl.minimum || ++ ioctl(s->fd, VIDIOC_QUERYMENU, &query_menu) != 0) { ++ return AVERROR(ENOENT); ++ } ++ } ++ ++ return 0; ++}; ++ ++static int ++check_size(AVCodecContext * const avctx, V4L2m2mContext * const s, const uint32_t fcc) ++{ ++ unsigned int i; ++ const uint32_t w = avctx->coded_width; ++ const uint32_t h = avctx->coded_height; ++ ++ if (w == 0 || h == 0 || fcc == 0) { ++ av_log(avctx, AV_LOG_TRACE, "%s: Size %dx%d or fcc %s empty\n", __func__, w, h, av_fourcc2str(fcc)); ++ return 0; ++ } ++ if ((s->quirks & FF_V4L2_QUIRK_ENUM_FRAMESIZES_BROKEN) != 0) { ++ av_log(avctx, AV_LOG_TRACE, "%s: Skipped (quirk): Size %dx%d, fcc %s\n", __func__, w, h, av_fourcc2str(fcc)); ++ return 0; ++ } ++ ++ for (i = 0;; ++i) { ++ struct v4l2_frmsizeenum fs = { ++ .index = i, ++ .pixel_format = fcc, ++ }; ++ ++ while (ioctl(s->fd, VIDIOC_ENUM_FRAMESIZES, &fs) != 0) { ++ const int err = AVERROR(errno); ++ if (err == AVERROR(EINTR)) ++ continue; ++ if (i == 0 && err == AVERROR(ENOTTY)) { ++ av_log(avctx, AV_LOG_DEBUG, "Framesize enum not supported\n"); ++ return 0; ++ } ++ if (err != AVERROR(EINVAL)) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to enum framesizes: %s", av_err2str(err)); ++ return err; ++ } ++ av_log(avctx, AV_LOG_WARNING, "Failed to find Size=%dx%d, fmt=%s in %u frame size enums\n", ++ w, h, av_fourcc2str(fcc), i); ++ return err; ++ } ++ ++ switch (fs.type) { ++ case V4L2_FRMSIZE_TYPE_DISCRETE: ++ av_log(avctx, AV_LOG_TRACE, "%s[%d]: Discrete: %dx%d\n", __func__, i, ++ fs.discrete.width,fs.discrete.height); ++ if (w == fs.discrete.width && h == fs.discrete.height) ++ return 0; ++ break; ++ case V4L2_FRMSIZE_TYPE_STEPWISE: ++ av_log(avctx, AV_LOG_TRACE, "%s[%d]: Stepwise: Min: %dx%d Max: %dx%d, Step: %dx%d\n", __func__, i, ++ fs.stepwise.min_width, fs.stepwise.min_height, ++ fs.stepwise.max_width, fs.stepwise.max_height, ++ fs.stepwise.step_width,fs.stepwise.step_height); ++ if (w >= fs.stepwise.min_width && w <= fs.stepwise.max_width && ++ h >= fs.stepwise.min_height && h <= fs.stepwise.max_height && ++ (w - fs.stepwise.min_width) % fs.stepwise.step_width == 0 && ++ (h - fs.stepwise.min_height) % fs.stepwise.step_height == 0) ++ return 0; ++ break; ++ case V4L2_FRMSIZE_TYPE_CONTINUOUS: ++ av_log(avctx, AV_LOG_TRACE, "%s[%d]: Continuous: Min: %dx%d Max: %dx%d, Step: %dx%d\n", __func__, i, ++ fs.stepwise.min_width, fs.stepwise.min_height, ++ fs.stepwise.max_width, fs.stepwise.max_height, ++ fs.stepwise.step_width,fs.stepwise.step_height); ++ if (w >= fs.stepwise.min_width && w <= fs.stepwise.max_width && ++ h >= fs.stepwise.min_height && h <= fs.stepwise.max_height) ++ return 0; ++ break; ++ default: ++ av_log(avctx, AV_LOG_ERROR, "Unexpected framesize enum: %d", fs.type); ++ return AVERROR(EINVAL); ++ } ++ } ++} ++ ++static int ++get_quirks(AVCodecContext * const avctx, V4L2m2mContext * const s) ++{ ++ struct v4l2_capability cap; ++ ++ memset(&cap, 0, sizeof(cap)); ++ while (ioctl(s->fd, VIDIOC_QUERYCAP, &cap) != 0) { ++ int err = errno; ++ if (err == EINTR) ++ continue; ++ av_log(avctx, AV_LOG_ERROR, "V4L2: Failed to get capabilities: %s\n", strerror(err)); ++ return AVERROR(err); ++ } ++ ++ // Could be made table driven if we have a few more but right now there ++ // seems no point ++ ++ // Meson (amlogic) always gives a resolution changed event after output ++ // streamon and userspace must (re)allocate capture buffers and streamon ++ // capture to clear the event even if the capture buffers were the right ++ // size in the first place. ++ if (strcmp(cap.driver, "meson-vdec") == 0) ++ s->quirks |= FF_V4L2_QUIRK_REINIT_ALWAYS | FF_V4L2_QUIRK_ENUM_FRAMESIZES_BROKEN; ++ ++ av_log(avctx, AV_LOG_DEBUG, "Driver '%s': Quirks=%#x\n", cap.driver, s->quirks); ++ return 0; ++} ++ ++// This heuristic is for H264 but use for everything ++static uint32_t max_coded_size(const AVCodecContext * const avctx) ++{ ++ uint32_t wxh = avctx->coded_width * avctx->coded_height; ++ uint32_t size; ++ ++ size = wxh * 3 / 2; ++ // H.264 Annex A table A-1 gives minCR which is either 2 or 4 ++ // unfortunately that doesn't yield an actually useful limit ++ // and it should be noted that frame 0 is special cased to allow ++ // a bigger number which really isn't helpful for us. So just pick ++ // frame_size / 2 ++ size /= 2; ++ // Add 64k to allow for any overheads and/or encoder hopefulness ++ // with small WxH ++ return size + (1 << 16); ++} ++ ++static void ++parse_extradata(AVCodecContext * const avctx, V4L2m2mContext * const s) ++{ ++ s->reorder_size = 0; ++ ++ if (!avctx->extradata || !avctx->extradata_size) ++ return; ++ ++ switch (avctx->codec_id) { ++#if CONFIG_H264_DECODER ++ case AV_CODEC_ID_H264: ++ { ++ H264ParamSets ps; ++ int is_avc = 0; ++ int nal_length_size = 0; ++ int ret; ++ ++ memset(&ps, 0, sizeof(ps)); ++ ++ ret = ff_h264_decode_extradata(avctx->extradata, avctx->extradata_size, ++ &ps, &is_avc, &nal_length_size, ++ avctx->err_recognition, avctx); ++ if (ret > 0) { ++ const SPS * sps = NULL; ++ unsigned int i; ++ for (i = 0; i != MAX_SPS_COUNT; ++i) { ++ if (ps.sps_list[i]) { ++ sps = ps.sps_list[i]; ++ break; ++ } ++ } ++ if (sps) { ++ avctx->profile = ff_h264_get_profile(sps); ++ avctx->level = sps->level_idc; ++ s->reorder_size = sps->num_reorder_frames; ++ } ++ } ++ ff_h264_ps_uninit(&ps); ++ break; ++ } ++#endif ++#if CONFIG_HEVC_DECODER ++ case AV_CODEC_ID_HEVC: ++ { ++ HEVCParamSets ps; ++ HEVCSEI sei; ++ int is_nalff = 0; ++ int nal_length_size = 0; ++ int ret; ++ ++ memset(&ps, 0, sizeof(ps)); ++ memset(&sei, 0, sizeof(sei)); ++ ++ ret = ff_hevc_decode_extradata(avctx->extradata, avctx->extradata_size, ++ &ps, &sei, &is_nalff, &nal_length_size, ++ avctx->err_recognition, 0, avctx); ++ if (ret > 0) { ++ const HEVCSPS * sps = NULL; ++ unsigned int i; ++ for (i = 0; i != HEVC_MAX_SPS_COUNT; ++i) { ++ if (ps.sps_list[i]) { ++ sps = ps.sps_list[i]; ++ break; ++ } ++ } ++ if (sps) { ++ avctx->profile = sps->ptl.general_ptl.profile_idc; ++ avctx->level = sps->ptl.general_ptl.level_idc; ++ s->reorder_size = sps->temporal_layer[sps->max_sub_layers - 1].max_dec_pic_buffering; ++ } ++ } ++ ff_hevc_ps_uninit(&ps); ++ ff_hevc_reset_sei(&sei); ++ break; ++ } ++#endif ++ default: ++ break; ++ } ++} ++ ++static int ++choose_capture_format(AVCodecContext * const avctx, V4L2m2mContext * const s) ++{ ++ const V4L2m2mPriv * const priv = avctx->priv_data; ++ unsigned int fmts_n; ++ uint32_t *fmts = ff_v4l2_context_enum_drm_formats(&s->capture, &fmts_n); ++ enum AVPixelFormat *fmts2 = NULL; ++ enum AVPixelFormat gf_pix_fmt; ++ unsigned int i; ++ unsigned int n = 0; ++ unsigned int pref_n = 1; ++ int rv = AVERROR(ENOENT); ++ ++ if (!fmts) ++ return AVERROR(ENOENT); ++ ++ if ((fmts2 = av_malloc(sizeof(*fmts2) * (fmts_n + 3))) == NULL) { ++ rv = AVERROR(ENOMEM); ++ goto error; ++ } ++ ++ // Filter for formats that are supported by ffmpeg and ++ // can accomodate the stream size ++ fmts2[n++] = AV_PIX_FMT_DRM_PRIME; ++ for (i = 0; i != fmts_n; ++i) { ++ const enum AVPixelFormat f = ff_v4l2_format_v4l2_to_avfmt(fmts[i], AV_CODEC_ID_RAWVIDEO); ++ av_log(avctx, AV_LOG_TRACE, "VLC pix %s -> %s\n", av_fourcc2str(fmts[i]), av_get_pix_fmt_name(f)); ++ if (f == AV_PIX_FMT_NONE) ++ continue; ++ ++ if (check_size(avctx, s, fmts[i]) != 0) ++ continue; ++ ++ if (f == priv->pix_fmt) ++ pref_n = n; ++ fmts2[n++] = f; ++ } ++ ++ if (n < 2) { ++ av_log(avctx, AV_LOG_DEBUG, "%s: No usable formats found\n", __func__); ++ goto error; ++ } ++ ++ if (n != 2) { ++ // ffmpeg.c really only expects one s/w format. It thinks that the ++ // last format in the list is the s/w format of the h/w format but ++ // also chooses the first non-h/w format as the preferred s/w format. ++ // The only way of reconciling this is to dup our preferred format into ++ // both last & first place :-( ++ const enum AVPixelFormat t = fmts2[pref_n]; ++ fmts2[pref_n] = fmts2[1]; ++ fmts2[1] = t; ++ fmts2[n++] = t; ++ } ++ ++ fmts2[n] = AV_PIX_FMT_NONE; ++ ++ gf_pix_fmt = ff_get_format(avctx, fmts2); ++ av_log(avctx, AV_LOG_DEBUG, "avctx requested=%d (%s) %dx%d; get_format requested=%d (%s)\n", ++ avctx->pix_fmt, av_get_pix_fmt_name(avctx->pix_fmt), ++ avctx->coded_width, avctx->coded_height, ++ gf_pix_fmt, av_get_pix_fmt_name(gf_pix_fmt)); ++ ++ if (gf_pix_fmt == AV_PIX_FMT_NONE) ++ goto error; ++ ++ if (gf_pix_fmt == AV_PIX_FMT_DRM_PRIME || avctx->pix_fmt == AV_PIX_FMT_DRM_PRIME) { ++ avctx->pix_fmt = AV_PIX_FMT_DRM_PRIME; ++ s->capture.av_pix_fmt = avctx->sw_pix_fmt; ++ s->output_drm = 1; ++ } ++ else { ++ avctx->pix_fmt = gf_pix_fmt; ++ s->capture.av_pix_fmt = gf_pix_fmt; ++ s->output_drm = 0; ++ } ++ ++ // Get format converts capture.av_pix_fmt back into a V4L2 format in the context ++ if ((rv = ff_v4l2_context_get_format(&s->capture, 0)) != 0) ++ goto error; ++ rv = ff_v4l2_context_set_format(&s->capture); ++ ++error: ++ av_free(fmts2); ++ av_free(fmts); ++ return rv; ++} ++ + static av_cold int v4l2_decode_init(AVCodecContext *avctx) + { + V4L2Context *capture, *output; +@@ -185,10 +1167,31 @@ 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__); ++ ++#if FF_API_FRAME_PKT ++FF_DISABLE_DEPRECATION_WARNINGS ++ if (avctx->codec_id == AV_CODEC_ID_H264) { ++ if (avctx->ticks_per_frame == 1) { ++ if(avctx->time_base.den < INT_MAX/2) { ++ avctx->time_base.den *= 2; ++ } else ++ avctx->time_base.num /= 2; ++ } ++ avctx->ticks_per_frame = 2; ++ } ++FF_ENABLE_DEPRECATION_WARNINGS ++#endif ++ + ret = ff_v4l2_m2m_create_context(priv, &s); + if (ret < 0) + return ret; + ++ parse_extradata(avctx, s); ++ ++ xlat_init(&s->xlat); ++ pts_stats_init(&s->pts_stat, avctx, "decoder"); ++ + capture = &s->capture; + output = &s->output; + +@@ -196,14 +1199,45 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx) + * by the v4l2 driver; this event will trigger a full pipeline reconfig and + * the proper values will be retrieved from the kernel driver. + */ +- output->height = capture->height = avctx->coded_height; +- output->width = capture->width = avctx->coded_width; ++// output->height = capture->height = avctx->coded_height; ++// output->width = capture->width = avctx->coded_width; ++ output->height = capture->height = 0; ++ output->width = capture->width = 0; + + output->av_codec_id = avctx->codec_id; + output->av_pix_fmt = AV_PIX_FMT_NONE; ++ output->min_buf_size = max_coded_size(avctx); + + capture->av_codec_id = AV_CODEC_ID_RAWVIDEO; + capture->av_pix_fmt = avctx->pix_fmt; ++ capture->min_buf_size = 0; ++ ++ capture->av_pix_fmt = AV_PIX_FMT_NONE; ++ s->output_drm = 0; ++ ++ s->db_ctl = NULL; ++ if (priv->dmabuf_alloc != NULL && strcmp(priv->dmabuf_alloc, "v4l2") != 0) { ++ if (strcmp(priv->dmabuf_alloc, "cma") == 0) ++ s->db_ctl = dmabufs_ctl_new(); ++ else { ++ av_log(avctx, AV_LOG_ERROR, "Unknown dmabuf alloc method: '%s'\n", priv->dmabuf_alloc); ++ return AVERROR(EINVAL); ++ } ++ if (!s->db_ctl) { ++ av_log(avctx, AV_LOG_ERROR, "Can't open dmabuf provider '%s'\n", priv->dmabuf_alloc); ++ return AVERROR(ENOMEM); ++ } ++ } ++ ++ 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); +@@ -212,12 +1246,90 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx) + return ret; + } + +- return v4l2_prepare_decoder(s); ++ if (avctx->extradata && ++ (ret = copy_extradata(avctx, avctx->extradata, avctx->extradata_size, &s->extdata_data, &s->extdata_size)) != 0) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to copy extradata from context: %s\n", av_err2str(ret)); ++#if DUMP_FAILED_EXTRADATA ++ log_dump(avctx, AV_LOG_INFO, avctx->extradata, avctx->extradata_size); ++#endif ++ return ret; ++ } ++ ++ if ((ret = get_quirks(avctx, s)) != 0) ++ return ret; ++ ++ if ((ret = check_profile(avctx, s)) != 0) { ++ av_log(avctx, AV_LOG_WARNING, "Profile %d not supported by decode\n", avctx->profile); ++ return ret; ++ } ++ ++ // Size check done as part of format filtering ++ if ((ret = choose_capture_format(avctx, s)) != 0) ++ return ret; ++ ++ if ((ret = v4l2_prepare_decoder(s)) < 0) ++ return ret; ++ ++ return 0; + } + + static av_cold int v4l2_decode_close(AVCodecContext *avctx) + { +- return ff_v4l2_m2m_codec_end(avctx->priv_data); ++ 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 * const priv = avctx->priv_data; ++ V4L2m2mContext * const s = priv->context; ++ V4L2Context * const output = &s->output; ++ V4L2Context * const capture = &s->capture; ++ ++ av_log(avctx, AV_LOG_TRACE, "<<< %s: streamon=%d\n", __func__, output->streamon); ++ ++ // Reflushing everything is benign, quick and avoids having to worry about ++ // states like EOS processing so don't try to optimize out (having got it ++ // wrong once) ++ ++ ff_v4l2_context_set_status(output, VIDIOC_STREAMOFF); ++ ++ // Clear any buffered input packet ++ av_packet_unref(&s->buf_pkt); ++ ++ // Clear a pending EOS ++ if (ff_v4l2_ctx_eos(capture)) { ++ // Arguably we could delay this but this is easy and doesn't require ++ // thought or extra vars ++ ff_v4l2_context_set_status(capture, VIDIOC_STREAMOFF); ++ ff_v4l2_context_set_status(capture, VIDIOC_STREAMON); ++ } ++ ++ // 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 ++ xlat_flush(&s->xlat); ++ ++ // resend extradata ++ s->extdata_sent = 0; ++ // clear status vars ++ s->running = 0; ++ s->draining = 0; ++ output->done = 0; ++ capture->done = 0; ++ ++ // Stream on will occur when we actually submit a new frame ++ av_log(avctx, AV_LOG_TRACE, ">>> %s\n", __func__); + } + + #define OFFSET(x) offsetof(V4L2m2mPriv, x) +@@ -227,9 +1339,16 @@ 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 }, ++ { "dmabuf_alloc", "Dmabuf alloc method", OFFSET(dmabuf_alloc), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, 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", \ +@@ -250,11 +1369,17 @@ static const AVOption options[] = { + .init = v4l2_decode_init, \ + FF_CODEC_RECEIVE_FRAME_CB(v4l2_receive_frame), \ + .close = v4l2_decode_close, \ ++ .flush = v4l2_decode_flush, \ + .bsfs = bsf_name, \ + .p.capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, \ + .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | \ + FF_CODEC_CAP_INIT_CLEANUP, \ + .p.wrapper_name = "v4l2m2m", \ ++ .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_DRM_PRIME, \ ++ AV_PIX_FMT_NV12, \ ++ AV_PIX_FMT_YUV420P, \ ++ AV_PIX_FMT_NONE}, \ ++ .hw_configs = v4l2_m2m_hw_configs, \ + } + + M2MDEC(h264, "H.264", AV_CODEC_ID_H264, "h264_mp4toannexb"); +diff --git a/libavcodec/v4l2_m2m_enc.c b/libavcodec/v4l2_m2m_enc.c +index 5770e87ea10b..6b00e113fa57 100644 +--- a/libavcodec/v4l2_m2m_enc.c ++++ b/libavcodec/v4l2_m2m_enc.c +@@ -21,13 +21,17 @@ + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + ++#include "config.h" ++ + #include + #include + #include ++ + #include "encode.h" + #include "libavcodec/avcodec.h" + #include "libavutil/pixdesc.h" + #include "libavutil/pixfmt.h" ++#include "libavutil/mem.h" + #include "libavutil/opt.h" + #include "codec_internal.h" + #include "profiles.h" +@@ -38,6 +42,39 @@ + #define MPEG_CID(x) V4L2_CID_MPEG_VIDEO_##x + #define MPEG_VIDEO(x) V4L2_MPEG_VIDEO_##x + ++#if CONFIG_LIBDRM ++#include ++ ++// 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 ++ ++#endif ++ ++#ifndef V4L2_CID_CODEC_BASE ++#define V4L2_CID_CODEC_BASE V4L2_CID_MPEG_BASE ++#endif ++ ++// V4L2_PIX_FMT_NV12_10_COL128 and V4L2_PIX_FMT_NV12_COL128 should be defined ++// in videodev2.h hopefully will be sometime in the future but until then... ++#ifndef V4L2_PIX_FMT_NV12_10_COL128 ++#define V4L2_PIX_FMT_NV12_10_COL128 v4l2_fourcc('N', 'C', '3', '0') ++#endif ++ ++#ifndef V4L2_PIX_FMT_NV12_COL128 ++#define V4L2_PIX_FMT_NV12_COL128 v4l2_fourcc('N', 'C', '1', '2') /* 12 Y/CbCr 4:2:0 128 pixel wide column */ ++#endif ++ + static inline void v4l2_set_timeperframe(V4L2m2mContext *s, unsigned int num, unsigned int den) + { + struct v4l2_streamparm parm = { 0 }; +@@ -148,15 +185,14 @@ static inline int v4l2_mpeg4_profile_from_ff(int p) + static int v4l2_check_b_frame_support(V4L2m2mContext *s) + { + if (s->avctx->max_b_frames) +- av_log(s->avctx, AV_LOG_WARNING, "Encoder does not support b-frames yet\n"); ++ av_log(s->avctx, AV_LOG_WARNING, "Encoder does not support %d b-frames yet\n", s->avctx->max_b_frames); + +- v4l2_set_ext_ctrl(s, MPEG_CID(B_FRAMES), 0, "number of B-frames", 0); ++ v4l2_set_ext_ctrl(s, MPEG_CID(B_FRAMES), s->avctx->max_b_frames, "number of B-frames", 1); + v4l2_get_ext_ctrl(s, MPEG_CID(B_FRAMES), &s->avctx->max_b_frames, "number of B-frames", 0); + if (s->avctx->max_b_frames == 0) + return 0; + + avpriv_report_missing_feature(s->avctx, "DTS/PTS calculation for V4L2 encoding"); +- + return AVERROR_PATCHWELCOME; + } + +@@ -271,17 +307,212 @@ static int v4l2_prepare_encoder(V4L2m2mContext *s) + return 0; + } + ++static int avdrm_to_v4l2(struct v4l2_format * const format, const AVFrame * const frame) ++{ ++#if !CONFIG_LIBDRM ++ return AVERROR_OPTION_NOT_FOUND; ++#else ++ const AVDRMFrameDescriptor *const src = (const AVDRMFrameDescriptor *)frame->data[0]; ++ ++ const uint32_t drm_fmt = src->layers[0].format; ++ // Treat INVALID as LINEAR ++ const uint64_t mod = src->objects[0].format_modifier == DRM_FORMAT_MOD_INVALID ? ++ DRM_FORMAT_MOD_LINEAR : src->objects[0].format_modifier; ++ uint32_t pix_fmt = 0; ++ uint32_t w = 0; ++ uint32_t h = 0; ++ uint32_t bpl = src->layers[0].planes[0].pitch; ++ ++ // We really don't expect multiple layers ++ // All formats that we currently cope with are single object ++ ++ if (src->nb_layers != 1 || src->nb_objects != 1) ++ return AVERROR(EINVAL); ++ ++ switch (drm_fmt) { ++ case DRM_FORMAT_YUV420: ++ if (mod == DRM_FORMAT_MOD_LINEAR) { ++ if (src->layers[0].nb_planes != 3) ++ break; ++ pix_fmt = V4L2_PIX_FMT_YUV420; ++ h = src->layers[0].planes[1].offset / bpl; ++ w = bpl; ++ } ++ break; ++ ++ case DRM_FORMAT_NV12: ++ if (mod == DRM_FORMAT_MOD_LINEAR) { ++ if (src->layers[0].nb_planes != 2) ++ break; ++ pix_fmt = V4L2_PIX_FMT_NV12; ++ h = src->layers[0].planes[1].offset / bpl; ++ w = bpl; ++ } ++ else if (fourcc_mod_broadcom_mod(mod) == DRM_FORMAT_MOD_BROADCOM_SAND128) { ++ if (src->layers[0].nb_planes != 2) ++ break; ++ pix_fmt = V4L2_PIX_FMT_NV12_COL128; ++ w = bpl; ++ h = src->layers[0].planes[1].offset / 128; ++ bpl = fourcc_mod_broadcom_param(mod); ++ } ++ break; ++ ++ case DRM_FORMAT_P030: ++ if (fourcc_mod_broadcom_mod(mod) == DRM_FORMAT_MOD_BROADCOM_SAND128) { ++ if (src->layers[0].nb_planes != 2) ++ break; ++ pix_fmt = V4L2_PIX_FMT_NV12_10_COL128; ++ w = bpl / 2; // Matching lie to how we construct this ++ h = src->layers[0].planes[1].offset / 128; ++ bpl = fourcc_mod_broadcom_param(mod); ++ } ++ break; ++ ++ default: ++ break; ++ } ++ ++ if (!pix_fmt) ++ return AVERROR(EINVAL); ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(format->type)) { ++ struct v4l2_pix_format_mplane *const pix = &format->fmt.pix_mp; ++ ++ pix->width = w; ++ pix->height = h; ++ pix->pixelformat = pix_fmt; ++ pix->plane_fmt[0].bytesperline = bpl; ++ pix->num_planes = 1; ++ } ++ else { ++ struct v4l2_pix_format *const pix = &format->fmt.pix; ++ ++ pix->width = w; ++ pix->height = h; ++ pix->pixelformat = pix_fmt; ++ pix->bytesperline = bpl; ++ } ++ ++ return 0; ++#endif ++} ++ ++// Do we have similar enough formats to be usable? ++static int fmt_eq(const struct v4l2_format * const a, const struct v4l2_format * const b) ++{ ++ if (a->type != b->type) ++ return 0; ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(a->type)) { ++ const struct v4l2_pix_format_mplane *const pa = &a->fmt.pix_mp; ++ const struct v4l2_pix_format_mplane *const pb = &b->fmt.pix_mp; ++ unsigned int i; ++ if (pa->pixelformat != pb->pixelformat || ++ pa->num_planes != pb->num_planes) ++ return 0; ++ for (i = 0; i != pa->num_planes; ++i) { ++ if (pa->plane_fmt[i].bytesperline != pb->plane_fmt[i].bytesperline) ++ return 0; ++ } ++ } ++ else { ++ const struct v4l2_pix_format *const pa = &a->fmt.pix; ++ const struct v4l2_pix_format *const pb = &b->fmt.pix; ++ if (pa->pixelformat != pb->pixelformat || ++ pa->bytesperline != pb->bytesperline) ++ return 0; ++ } ++ return 1; ++} ++ ++static inline int q_full(const V4L2Context *const output) ++{ ++ return ff_v4l2_context_q_count(output) == output->num_buffers; ++} ++ + static int v4l2_send_frame(AVCodecContext *avctx, const AVFrame *frame) + { + V4L2m2mContext *s = ((V4L2m2mPriv*)avctx->priv_data)->context; + V4L2Context *const output = &s->output; ++ int rv; ++ const int needs_slot = q_full(output); ++ ++ av_log(avctx, AV_LOG_TRACE, "<<< %s; needs_slot=%d\n", __func__, needs_slot); ++ ++ // Signal EOF if needed (doesn't need q slot) ++ if (!frame) { ++ av_log(avctx, AV_LOG_TRACE, "--- %s: EOS\n", __func__); ++ return ff_v4l2_context_enqueue_frame(output, frame); ++ } ++ ++ if ((rv = ff_v4l2_dq_all(output, needs_slot? 500 : 0)) != 0) { ++ // We should be able to return AVERROR(EAGAIN) to indicate buffer ++ // exhaustion, but ffmpeg currently treats that as fatal. ++ av_log(avctx, AV_LOG_WARNING, "Failed to get buffer for src frame: %s\n", av_err2str(rv)); ++ return rv; ++ } ++ ++ if (s->input_drm && !output->streamon) { ++ struct v4l2_format req_format = {.type = output->format.type}; ++ ++ // Set format when we first get a buffer ++ if ((rv = avdrm_to_v4l2(&req_format, frame)) != 0) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to get V4L2 format from DRM_PRIME frame\n"); ++ return rv; ++ } ++ ++ ff_v4l2_context_release(output); ++ ++ output->format = req_format; ++ ++ if ((rv = ff_v4l2_context_set_format(output)) != 0) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to set V4L2 format\n"); ++ return rv; ++ } ++ ++ if (!fmt_eq(&req_format, &output->format)) { ++ av_log(avctx, AV_LOG_ERROR, "Format mismatch after setup\n"); ++ return AVERROR(EINVAL); ++ } ++ ++ output->selection.top = frame->crop_top; ++ output->selection.left = frame->crop_left; ++ output->selection.width = av_frame_cropped_width(frame); ++ output->selection.height = av_frame_cropped_height(frame); ++ ++ if ((rv = ff_v4l2_context_init(output)) != 0) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to (re)init context\n"); ++ return rv; ++ } ++ ++ { ++ struct v4l2_selection selection = { ++ .type = V4L2_BUF_TYPE_VIDEO_OUTPUT, ++ .target = V4L2_SEL_TGT_CROP, ++ .r = output->selection ++ }; ++ if (ioctl(s->fd, VIDIOC_S_SELECTION, &selection) != 0) { ++ av_log(avctx, AV_LOG_WARNING, "S_SELECTION (CROP) %dx%d @ %d,%d failed: %s\n", ++ selection.r.width, selection.r.height, selection.r.left, selection.r.top, ++ av_err2str(AVERROR(errno))); ++ } ++ av_log(avctx, AV_LOG_TRACE, "S_SELECTION (CROP) %dx%d @ %d,%d OK\n", ++ selection.r.width, selection.r.height, selection.r.left, selection.r.top); ++ } ++ } + + #ifdef V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME +- if (frame && frame->pict_type == AV_PICTURE_TYPE_I) ++ if (frame->pict_type == AV_PICTURE_TYPE_I) + v4l2_set_ext_ctrl(s, MPEG_CID(FORCE_KEY_FRAME), 0, "force key frame", 1); + #endif + +- return ff_v4l2_context_enqueue_frame(output, frame); ++ rv = ff_v4l2_context_enqueue_frame(output, frame); ++ if (rv) { ++ av_log(avctx, AV_LOG_ERROR, "Enqueue frame failed: %s\n", av_err2str(rv)); ++ } ++ ++ return rv; + } + + static int v4l2_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) +@@ -292,6 +523,11 @@ static int v4l2_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) + AVFrame *frame = s->frame; + int ret; + ++ av_log(avctx, AV_LOG_TRACE, "<<< %s: qlen out %d cap %d\n", __func__, ++ ff_v4l2_context_q_count(output), ff_v4l2_context_q_count(capture)); ++ ++ ff_v4l2_dq_all(output, 0); ++ + if (s->draining) + goto dequeue; + +@@ -328,7 +564,115 @@ static int v4l2_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) + } + + dequeue: +- return ff_v4l2_context_dequeue_packet(capture, avpkt); ++ // Dequeue a frame ++ for (;;) { ++ int t = q_full(output) ? -1 : s->draining ? 300 : 0; ++ int rv2; ++ ++ // If output is full wait for either a packet or output to become not full ++ ret = ff_v4l2_context_dequeue_packet(capture, avpkt, t); ++ ++ // If output was full retry packet dequeue ++ t = (ret != AVERROR(EAGAIN) || t != -1) ? 0 : 300; ++ rv2 = ff_v4l2_dq_all(output, t); ++ if (t == 0 || rv2 != 0) ++ break; ++ } ++ if (ret) ++ return (s->draining && ret == AVERROR(EAGAIN)) ? AVERROR_EOF : ret; ++ ++ if (capture->first_buf == 1) { ++ uint8_t * data; ++ const int len = avpkt->size; ++ ++ // 1st buffer after streamon should be SPS/PPS ++ capture->first_buf = 2; ++ ++ // Clear both possible stores so there is no chance of confusion ++ av_freep(&s->extdata_data); ++ s->extdata_size = 0; ++ av_freep(&avctx->extradata); ++ avctx->extradata_size = 0; ++ ++ if ((data = av_malloc(len + AV_INPUT_BUFFER_PADDING_SIZE)) == NULL) ++ goto fail_no_mem; ++ ++ memcpy(data, avpkt->data, len); ++ av_packet_unref(avpkt); ++ ++ // We need to copy the header, but keep local if not global ++ if ((avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) != 0) { ++ avctx->extradata = data; ++ avctx->extradata_size = len; ++ } ++ else { ++ s->extdata_data = data; ++ s->extdata_size = len; ++ } ++ ++ ret = ff_v4l2_context_dequeue_packet(capture, avpkt, 0); ++ ff_v4l2_dq_all(output, 0); ++ if (ret) ++ return ret; ++ } ++ ++ // First frame must be key so mark as such even if encoder forgot ++ if (capture->first_buf == 2) { ++ avpkt->flags |= AV_PKT_FLAG_KEY; ++ ++ // Add any extradata to the 1st packet we emit as we cannot create it at init ++ if (avctx->extradata_size > 0 && avctx->extradata) { ++ void * const side = av_packet_new_side_data(avpkt, ++ AV_PKT_DATA_NEW_EXTRADATA, ++ avctx->extradata_size); ++ if (!side) ++ goto fail_no_mem; ++ ++ memcpy(side, avctx->extradata, avctx->extradata_size); ++ } ++ } ++ ++ // Add SPS/PPS to the start of every key frame if non-global headers ++ if ((avpkt->flags & AV_PKT_FLAG_KEY) != 0 && s->extdata_size != 0) { ++ const size_t newlen = s->extdata_size + avpkt->size; ++ AVBufferRef * const buf = av_buffer_alloc(newlen + AV_INPUT_BUFFER_PADDING_SIZE); ++ ++ if (buf == NULL) ++ goto fail_no_mem; ++ ++ memcpy(buf->data, s->extdata_data, s->extdata_size); ++ memcpy(buf->data + s->extdata_size, avpkt->data, avpkt->size); ++ ++ av_buffer_unref(&avpkt->buf); ++ avpkt->buf = buf; ++ avpkt->data = buf->data; ++ avpkt->size = newlen; ++ } ++ else if (ff_v4l2_context_q_count(capture) < 2) { ++ // Avoid running out of capture buffers ++ // In most cases the buffers will be returned quickly in which case ++ // we don't copy and can use the v4l2 buffers directly but sometimes ++ // ffmpeg seems to hold onto all of them for a long time (.mkv ++ // creation?) so avoid deadlock in those cases. ++ AVBufferRef * const buf = av_buffer_alloc(avpkt->size + AV_INPUT_BUFFER_PADDING_SIZE); ++ if (buf == NULL) ++ goto fail_no_mem; ++ ++ memcpy(buf->data, avpkt->data, avpkt->size); ++ av_buffer_unref(&avpkt->buf); // Will recycle the V4L2 buffer ++ ++ avpkt->buf = buf; ++ avpkt->data = buf->data; ++ } ++ ++ capture->first_buf = 0; ++ return 0; ++ ++fail_no_mem: ++ av_log(avctx, AV_LOG_ERROR, "Rx pkt failed: No memory\n"); ++ ret = AVERROR(ENOMEM); ++ av_packet_unref(avpkt); ++ return ret; + } + + static av_cold int v4l2_encode_init(AVCodecContext *avctx) +@@ -340,6 +684,8 @@ static av_cold int v4l2_encode_init(AVCodecContext *avctx) + uint32_t v4l2_fmt_output; + int ret; + ++ av_log(avctx, AV_LOG_INFO, " <<< %s: fmt=%d/%d\n", __func__, avctx->pix_fmt, avctx->sw_pix_fmt); ++ + ret = ff_v4l2_m2m_create_context(priv, &s); + if (ret < 0) + return ret; +@@ -347,13 +693,17 @@ static av_cold int v4l2_encode_init(AVCodecContext *avctx) + capture = &s->capture; + output = &s->output; + ++ s->input_drm = (avctx->pix_fmt == AV_PIX_FMT_DRM_PRIME); ++ + /* common settings output/capture */ + output->height = capture->height = avctx->height; + output->width = capture->width = avctx->width; + + /* output context */ + output->av_codec_id = AV_CODEC_ID_RAWVIDEO; +- output->av_pix_fmt = avctx->pix_fmt; ++ output->av_pix_fmt = !s->input_drm ? avctx->pix_fmt : ++ avctx->sw_pix_fmt != AV_PIX_FMT_NONE ? avctx->sw_pix_fmt : ++ AV_PIX_FMT_YUV420P; + + /* capture context */ + capture->av_codec_id = avctx->codec_id; +@@ -372,7 +722,7 @@ static av_cold int v4l2_encode_init(AVCodecContext *avctx) + v4l2_fmt_output = output->format.fmt.pix.pixelformat; + + pix_fmt_output = ff_v4l2_format_v4l2_to_avfmt(v4l2_fmt_output, AV_CODEC_ID_RAWVIDEO); +- if (pix_fmt_output != avctx->pix_fmt) { ++ if (!s->input_drm && pix_fmt_output != avctx->pix_fmt) { + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt_output); + av_log(avctx, AV_LOG_ERROR, "Encoder requires %s pixel format.\n", desc->name); + return AVERROR(EINVAL); +@@ -390,9 +740,10 @@ static av_cold int v4l2_encode_close(AVCodecContext *avctx) + #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM + + #define V4L_M2M_CAPTURE_OPTS \ +- V4L_M2M_DEFAULT_OPTS,\ ++ { "num_output_buffers", "Number of buffers in the output context",\ ++ OFFSET(num_output_buffers), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS },\ + { "num_capture_buffers", "Number of buffers in the capture context", \ +- OFFSET(num_capture_buffers), AV_OPT_TYPE_INT, {.i64 = 4 }, 4, INT_MAX, FLAGS } ++ OFFSET(num_capture_buffers), AV_OPT_TYPE_INT, {.i64 = 8 }, 8, INT_MAX, FLAGS } + + static const AVOption mpeg4_options[] = { + V4L_M2M_CAPTURE_OPTS, +diff --git a/libavcodec/v4l2_req_decode_q.c b/libavcodec/v4l2_req_decode_q.c +new file mode 100644 +index 000000000000..93c56ba13f85 +--- /dev/null ++++ b/libavcodec/v4l2_req_decode_q.c +@@ -0,0 +1,108 @@ ++/* ++ Copyright (C) 2024 John Cox john.cox@raspberrypi.com ++ ++ 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. ++ */ ++ ++#include ++#include ++#include ++ ++#include "v4l2_req_decode_q.h" ++ ++int decode_q_in_q(const req_decode_ent * const d) ++{ ++ return d->in_q; ++} ++ ++void decode_q_add(req_decode_q * const q, req_decode_ent * const d) ++{ ++ pthread_mutex_lock(&q->q_lock); ++ if (!q->head) { ++ q->head = d; ++ q->tail = d; ++ d->prev = NULL; ++ } ++ else { ++ q->tail->next = d; ++ d->prev = q->tail; ++ q->tail = d; ++ } ++ d->next = NULL; ++ d->in_q = 1; ++ pthread_mutex_unlock(&q->q_lock); ++} ++ ++// Remove entry from Q - if head wake-up anything that was waiting ++void decode_q_remove(req_decode_q * const q, req_decode_ent * const d) ++{ ++ int try_signal = 0; ++ ++ if (!d->in_q) ++ return; ++ ++ pthread_mutex_lock(&q->q_lock); ++ if (d->prev) ++ d->prev->next = d->next; ++ else { ++ try_signal = 1; // Only need to signal if we were head ++ q->head = d->next; ++ } ++ ++ if (d->next) ++ d->next->prev = d->prev; ++ else ++ q->tail = d->prev; ++ ++ // Not strictly needed but makes debug easier ++ d->next = NULL; ++ d->prev = NULL; ++ d->in_q = 0; ++ pthread_mutex_unlock(&q->q_lock); ++ ++ if (try_signal) ++ pthread_cond_broadcast(&q->q_cond); ++} ++ ++void decode_q_wait(req_decode_q * const q, req_decode_ent * const d) ++{ ++ pthread_mutex_lock(&q->q_lock); ++ ++ while (q->head != d) ++ pthread_cond_wait(&q->q_cond, &q->q_lock); ++ ++ pthread_mutex_unlock(&q->q_lock); ++} ++ ++void decode_q_uninit(req_decode_q * const q) ++{ ++ pthread_mutex_destroy(&q->q_lock); ++ pthread_cond_destroy(&q->q_cond); ++} ++ ++void decode_q_init(req_decode_q * const q) ++{ ++ memset(q, 0, sizeof(*q)); ++ pthread_mutex_init(&q->q_lock, NULL); ++ pthread_cond_init(&q->q_cond, NULL); ++} ++ ++ +diff --git a/libavcodec/v4l2_req_decode_q.h b/libavcodec/v4l2_req_decode_q.h +new file mode 100644 +index 000000000000..0ff8bbe88207 +--- /dev/null ++++ b/libavcodec/v4l2_req_decode_q.h +@@ -0,0 +1,51 @@ ++/* ++ Copyright (C) 2024 John Cox john.cox@raspberrypi.com ++ ++ 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. ++ */ ++ ++#ifndef AVCODEC_V4L2_REQ_DECODE_Q_H ++#define AVCODEC_V4L2_REQ_DECODE_Q_H ++ ++#include ++ ++typedef struct req_decode_ent { ++ struct req_decode_ent * next; ++ struct req_decode_ent * prev; ++ int in_q; ++} req_decode_ent; ++ ++typedef struct req_decode_q { ++ pthread_mutex_t q_lock; ++ pthread_cond_t q_cond; ++ req_decode_ent * head; ++ req_decode_ent * tail; ++} req_decode_q; ++ ++int decode_q_in_q(const req_decode_ent * const d); ++void decode_q_add(req_decode_q * const q, req_decode_ent * const d); ++void decode_q_remove(req_decode_q * const q, req_decode_ent * const d); ++void decode_q_wait(req_decode_q * const q, req_decode_ent * const d); ++void decode_q_uninit(req_decode_q * const q); ++void decode_q_init(req_decode_q * const q); ++ ++#endif ++ +diff --git a/libavcodec/v4l2_req_devscan.c b/libavcodec/v4l2_req_devscan.c +new file mode 100644 +index 000000000000..0416f3d4d104 +--- /dev/null ++++ b/libavcodec/v4l2_req_devscan.c +@@ -0,0 +1,474 @@ ++/* ++ Copyright (C) 2024 John Cox john.cox@raspberrypi.com ++ ++ 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++ ++#include "v4l2_req_devscan.h" ++#include "v4l2_req_utils.h" ++ ++struct decdev { ++ enum v4l2_buf_type src_type; ++ uint32_t src_fmt_v4l2; ++ const char * vname; ++ const char * mname; ++}; ++ ++struct devscan { ++ struct decdev env; ++ unsigned int dev_size; ++ unsigned int dev_count; ++ struct decdev *devs; ++}; ++ ++static int video_src_pixfmt_supported(uint32_t fmt) ++{ ++ return 1; ++} ++ ++static void v4l2_setup_format(struct v4l2_format *format, unsigned int type, ++ unsigned int width, unsigned int height, ++ unsigned int pixelformat) ++{ ++ unsigned int sizeimage; ++ ++ memset(format, 0, sizeof(*format)); ++ format->type = type; ++ ++ sizeimage = V4L2_TYPE_IS_OUTPUT(type) ? 4 * 1024 * 1024 : 0; ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(type)) { ++ format->fmt.pix_mp.width = width; ++ format->fmt.pix_mp.height = height; ++ format->fmt.pix_mp.plane_fmt[0].sizeimage = sizeimage; ++ format->fmt.pix_mp.pixelformat = pixelformat; ++ } else { ++ format->fmt.pix.width = width; ++ format->fmt.pix.height = height; ++ format->fmt.pix.sizeimage = sizeimage; ++ format->fmt.pix.pixelformat = pixelformat; ++ } ++} ++ ++static int v4l2_set_format(int video_fd, unsigned int type, unsigned int pixelformat, ++ unsigned int width, unsigned int height) ++{ ++ struct v4l2_format format; ++ ++ v4l2_setup_format(&format, type, width, height, pixelformat); ++ ++ return ioctl(video_fd, VIDIOC_S_FMT, &format) ? -errno : 0; ++} ++ ++static int v4l2_query_capabilities(int video_fd, unsigned int *capabilities) ++{ ++ struct v4l2_capability capability = { 0 }; ++ int rc; ++ ++ rc = ioctl(video_fd, VIDIOC_QUERYCAP, &capability); ++ if (rc < 0) ++ return -errno; ++ ++ if (capabilities != NULL) { ++ if ((capability.capabilities & V4L2_CAP_DEVICE_CAPS) != 0) ++ *capabilities = capability.device_caps; ++ else ++ *capabilities = capability.capabilities; ++ } ++ ++ return 0; ++} ++ ++static int devscan_add(struct devscan *const scan, ++ enum v4l2_buf_type src_type, ++ uint32_t src_fmt_v4l2, ++ const char * vname, ++ const char * mname) ++{ ++ struct decdev *d; ++ ++ if (scan->dev_size <= scan->dev_count) { ++ unsigned int n = !scan->dev_size ? 4 : scan->dev_size * 2; ++ d = realloc(scan->devs, n * sizeof(*d)); ++ if (!d) ++ return -ENOMEM; ++ scan->devs = d; ++ scan->dev_size = n; ++ } ++ ++ d = scan->devs + scan->dev_count; ++ d->src_type = src_type; ++ d->src_fmt_v4l2 = src_fmt_v4l2; ++ d->vname = strdup(vname); ++ if (!d->vname) ++ return -ENOMEM; ++ d->mname = strdup(mname); ++ if (!d->mname) { ++ free((char *)d->vname); ++ return -ENOMEM; ++ } ++ ++scan->dev_count; ++ return 0; ++} ++ ++void devscan_delete(struct devscan **const pScan) ++{ ++ unsigned int i; ++ struct devscan * const scan = *pScan; ++ ++ if (!scan) ++ return; ++ *pScan = NULL; ++ ++ for (i = 0; i < scan->dev_count; ++i) { ++ free((char*)scan->devs[i].mname); ++ free((char*)scan->devs[i].vname); ++ } ++ free(scan->devs); ++ free(scan); ++} ++ ++#define REQ_BUF_CAPS (\ ++ V4L2_BUF_CAP_SUPPORTS_REQUESTS |\ ++ 0) ++ ++static void probe_formats(void * const dc, ++ struct devscan *const scan, ++ const int fd, ++ const unsigned int type_v4l2, ++ const char *const mpath, ++ const char *const vpath) ++{ ++ unsigned int i; ++ for (i = 0;; ++i) { ++ struct v4l2_fmtdesc fmtdesc = { ++ .index = i, ++ .type = type_v4l2 ++ }; ++ struct v4l2_requestbuffers rbufs = { ++ .count = 0, ++ .type = type_v4l2, ++ .memory = V4L2_MEMORY_MMAP ++ }; ++ while (ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc)) { ++ if (errno == EINTR) ++ continue; ++ if (errno != EINVAL) ++ request_err(dc, "Enum[%d] failed for type=%d\n", i, type_v4l2); ++ return; ++ } ++ if (!video_src_pixfmt_supported(fmtdesc.pixelformat)) ++ continue; ++ ++ if (v4l2_set_format(fd, type_v4l2, fmtdesc.pixelformat, 720, 480)) { ++ request_debug(dc, "Set failed for type=%d, pf=%.4s\n", type_v4l2, (char*)&fmtdesc.pixelformat); ++ continue; ++ } ++ ++ while (ioctl(fd, VIDIOC_REQBUFS, &rbufs)) { ++ if (errno != EINTR) { ++ request_debug(dc, "%s: Reqbufs failed\n", vpath); ++ continue; ++ } ++ } ++ ++ if ((rbufs.capabilities & REQ_BUF_CAPS) != REQ_BUF_CAPS) { ++ request_debug(dc, "%s: Buf caps %#x insufficient\n", vpath, rbufs.capabilities); ++ continue; ++ } ++ ++ request_debug(dc, "Adding: %s,%s pix=%#x, type=%d\n", ++ mpath, vpath, fmtdesc.pixelformat, type_v4l2); ++ devscan_add(scan, type_v4l2, fmtdesc.pixelformat, vpath, mpath); ++ } ++} ++ ++ ++static int probe_video_device(void * const dc, ++ struct udev_device *const device, ++ struct devscan *const scan, ++ const char *const mpath) ++{ ++ int ret; ++ unsigned int capabilities = 0; ++ int video_fd = -1; ++ ++ const char *path = udev_device_get_devnode(device); ++ if (!path) { ++ request_err(dc, "%s: get video device devnode failed\n", __func__); ++ ret = -EINVAL; ++ goto fail; ++ } ++ ++ video_fd = open(path, O_RDWR, 0); ++ if (video_fd == -1) { ++ ret = -errno; ++ request_err(dc, "%s: opening %s failed, %s (%d)\n", __func__, path, strerror(errno), errno); ++ goto fail; ++ } ++ ++ ret = v4l2_query_capabilities(video_fd, &capabilities); ++ if (ret < 0) { ++ request_err(dc, "%s: get video capability failed, %s (%d)\n", __func__, strerror(-ret), -ret); ++ goto fail; ++ } ++ ++ request_debug(dc, "%s: path=%s capabilities=%#x\n", __func__, path, capabilities); ++ ++ if (!(capabilities & V4L2_CAP_STREAMING)) { ++ request_debug(dc, "%s: missing required streaming capability\n", __func__); ++ ret = -EINVAL; ++ goto fail; ++ } ++ ++ if (!(capabilities & (V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_VIDEO_M2M))) { ++ request_debug(dc, "%s: missing required mem2mem capability\n", __func__); ++ ret = -EINVAL; ++ goto fail; ++ } ++ ++ /* Should check capture formats too... */ ++ if ((capabilities & V4L2_CAP_VIDEO_M2M) != 0) ++ probe_formats(dc, scan, video_fd, V4L2_BUF_TYPE_VIDEO_OUTPUT, mpath, path); ++ if ((capabilities & V4L2_CAP_VIDEO_M2M_MPLANE) != 0) ++ probe_formats(dc, scan, video_fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, mpath, path); ++ ++ close(video_fd); ++ return 0; ++ ++fail: ++ if (video_fd >= 0) ++ close(video_fd); ++ return ret; ++} ++ ++static int probe_media_device(void * const dc, ++ struct udev_device *const device, ++ struct devscan *const scan) ++{ ++ int ret; ++ int rv; ++ 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; ++ int media_fd = -1; ++ ++ const char *path = udev_device_get_devnode(device); ++ if (!path) { ++ request_err(dc, "%s: get media device devnode failed\n", __func__); ++ ret = -EINVAL; ++ goto fail; ++ } ++ ++ media_fd = open(path, O_RDWR, 0); ++ if (media_fd < 0) { ++ ret = -errno; ++ request_err(dc, "%s: opening %s failed, %s (%d)\n", __func__, path, strerror(-ret), -ret); ++ goto fail; ++ } ++ ++ rv = ioctl(media_fd, MEDIA_IOC_DEVICE_INFO, &device_info); ++ if (rv < 0) { ++ ret = -errno; ++ request_err(dc, "%s: get media device info failed, %s (%d)\n", __func__, strerror(-ret), -ret); ++ goto fail; ++ } ++ ++ rv = ioctl(media_fd, MEDIA_IOC_G_TOPOLOGY, &topology); ++ if (rv < 0) { ++ ret = -errno; ++ request_err(dc, "%s: get media topology failed, %s (%d)\n", __func__, strerror(-ret), -ret); ++ goto fail; ++ } ++ ++ if (topology.num_interfaces <= 0) { ++ request_err(dc, "%s: media device has no interfaces\n", __func__); ++ ret = -EINVAL; ++ goto fail; ++ } ++ ++ interfaces = calloc(topology.num_interfaces, sizeof(*interfaces)); ++ if (!interfaces) { ++ request_err(dc, "%s: allocating media interface struct failed\n", __func__); ++ ret = -ENOMEM; ++ goto fail; ++ } ++ ++ topology.ptr_interfaces = (__u64)(uintptr_t)interfaces; ++ rv = ioctl(media_fd, MEDIA_IOC_G_TOPOLOGY, &topology); ++ if (rv < 0) { ++ ret = -errno; ++ request_err(dc, "%s: get media topology failed, %s (%d)\n", __func__, strerror(-ret), -ret); ++ goto fail; ++ } ++ ++ 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) { ++ ret = -errno; ++ request_err(dc, "%s: video_device[%d]=%p\n", __func__, i, video_device); ++ continue; ++ } ++ ++ ret = probe_video_device(dc, video_device, scan, path); ++ udev_device_unref(video_device); ++ ++ if (ret != 0) ++ goto fail; ++ } ++ ++fail: ++ free(interfaces); ++ if (media_fd != -1) ++ close(media_fd); ++ return ret; ++} ++ ++const char *decdev_media_path(const struct decdev *const dev) ++{ ++ return !dev ? NULL : dev->mname; ++} ++ ++const char *decdev_video_path(const struct decdev *const dev) ++{ ++ return !dev ? NULL : dev->vname; ++} ++ ++enum v4l2_buf_type decdev_src_type(const struct decdev *const dev) ++{ ++ return !dev ? 0 : dev->src_type; ++} ++ ++uint32_t decdev_src_pixelformat(const struct decdev *const dev) ++{ ++ return !dev ? 0 : dev->src_fmt_v4l2; ++} ++ ++ ++const struct decdev *devscan_find(struct devscan *const scan, ++ const uint32_t src_fmt_v4l2) ++{ ++ unsigned int i; ++ ++ if (scan->env.mname && scan->env.vname) ++ return &scan->env; ++ ++ if (!src_fmt_v4l2) ++ return scan->dev_count ? scan->devs + 0 : NULL; ++ ++ for (i = 0; i != scan->dev_count; ++i) { ++ if (scan->devs[i].src_fmt_v4l2 == src_fmt_v4l2) ++ return scan->devs + i; ++ } ++ return NULL; ++} ++ ++int devscan_build(void * const dc, struct devscan **pscan) ++{ ++ int ret; ++ struct udev *udev; ++ struct udev_enumerate *enumerate; ++ struct udev_list_entry *devices; ++ struct udev_list_entry *entry; ++ struct udev_device *device; ++ struct devscan * scan; ++ ++ *pscan = NULL; ++ ++ scan = calloc(1, sizeof(*scan)); ++ if (!scan) { ++ ret = -ENOMEM; ++ goto fail; ++ } ++ ++ scan->env.mname = getenv("LIBVA_V4L2_REQUEST_MEDIA_PATH"); ++ scan->env.vname = getenv("LIBVA_V4L2_REQUEST_VIDEO_PATH"); ++ if (scan->env.mname && scan->env.vname) { ++ request_info(dc, "Media/video device env overrides found: %s,%s\n", ++ scan->env.mname, scan->env.vname); ++ *pscan = scan; ++ return 0; ++ } ++ ++ udev = udev_new(); ++ if (!udev) { ++ request_err(dc, "%s: allocating udev context failed\n", __func__); ++ ret = -ENOMEM; ++ goto fail; ++ } ++ ++ enumerate = udev_enumerate_new(udev); ++ if (!enumerate) { ++ request_err(dc, "%s: allocating udev enumerator failed\n", __func__); ++ ret = -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; ++ ++ probe_media_device(dc, device, scan); ++ udev_device_unref(device); ++ } ++ ++ udev_enumerate_unref(enumerate); ++ udev_unref(udev); ++ ++ *pscan = scan; ++ return 0; ++ ++fail: ++ if (udev) ++ udev_unref(udev); ++ devscan_delete(&scan); ++ return ret; ++} ++ +diff --git a/libavcodec/v4l2_req_devscan.h b/libavcodec/v4l2_req_devscan.h +new file mode 100644 +index 000000000000..49b5bb44b2d7 +--- /dev/null ++++ b/libavcodec/v4l2_req_devscan.h +@@ -0,0 +1,47 @@ ++/* ++ Copyright (C) 2024 John Cox john.cox@raspberrypi.com ++ ++ 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. ++ */ ++ ++#ifndef AVCODEC_V4L2_REQ_DEVSCAN_H ++#define AVCODEC_V4L2_REQ_DEVSCAN_H ++ ++#include ++ ++struct devscan; ++struct decdev; ++enum v4l2_buf_type; ++ ++/* These return pointers to data in the devscan structure and so are vaild ++ * for the lifetime of that ++ */ ++const char *decdev_media_path(const struct decdev *const dev); ++const char *decdev_video_path(const struct decdev *const dev); ++enum v4l2_buf_type decdev_src_type(const struct decdev *const dev); ++uint32_t decdev_src_pixelformat(const struct decdev *const dev); ++ ++const struct decdev *devscan_find(struct devscan *const scan, const uint32_t src_fmt_v4l2); ++ ++int devscan_build(void * const dc, struct devscan **pscan); ++void devscan_delete(struct devscan **const pScan); ++ ++#endif +diff --git a/libavcodec/v4l2_req_dmabufs.c b/libavcodec/v4l2_req_dmabufs.c +new file mode 100644 +index 000000000000..e157d4d55749 +--- /dev/null ++++ b/libavcodec/v4l2_req_dmabufs.c +@@ -0,0 +1,433 @@ ++/* ++ Copyright (C) 2024 John Cox john.cox@raspberrypi.com ++ ++ 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "v4l2_req_dmabufs.h" ++#include "v4l2_req_utils.h" ++ ++#define TRACE_ALLOC 0 ++ ++#ifndef __O_CLOEXEC ++#define __O_CLOEXEC 0 ++#endif ++ ++struct dmabufs_ctl; ++struct dmabuf_h; ++ ++struct dmabuf_fns { ++ int (*buf_alloc)(struct dmabufs_ctl * dbsc, struct dmabuf_h * dh, size_t size); ++ void (*buf_free)(struct dmabuf_h * dh); ++ int (*ctl_new)(struct dmabufs_ctl * dbsc); ++ void (*ctl_free)(struct dmabufs_ctl * dbsc); ++}; ++ ++struct dmabufs_ctl { ++ atomic_int ref_count; ++ int fd; ++ size_t page_size; ++ void * v; ++ const struct dmabuf_fns * fns; ++}; ++ ++struct dmabuf_h { ++ int fd; ++ size_t size; ++ size_t len; ++ void * mapptr; ++ void * v; ++ const struct dmabuf_fns * fns; ++}; ++ ++#if TRACE_ALLOC ++static unsigned int total_bufs = 0; ++static size_t total_size = 0; ++#endif ++ ++struct dmabuf_h * dmabuf_import_mmap(void * mapptr, size_t size) ++{ ++ struct dmabuf_h *dh; ++ ++ if (mapptr == MAP_FAILED) ++ return NULL; ++ ++ dh = malloc(sizeof(*dh)); ++ if (!dh) ++ return NULL; ++ ++ *dh = (struct dmabuf_h) { ++ .fd = -1, ++ .size = size, ++ .mapptr = mapptr ++ }; ++ ++ return dh; ++} ++ ++struct dmabuf_h * dmabuf_import(int fd, size_t size) ++{ ++ struct dmabuf_h *dh; ++ ++ fd = dup(fd); ++ if (fd < 0 || size == 0) ++ return NULL; ++ ++ dh = malloc(sizeof(*dh)); ++ if (!dh) { ++ close(fd); ++ return NULL; ++ } ++ ++ *dh = (struct dmabuf_h) { ++ .fd = fd, ++ .size = size, ++ .mapptr = MAP_FAILED ++ }; ++ ++#if TRACE_ALLOC ++ ++total_bufs; ++ total_size += dh->size; ++ request_log("%s: Import: %zd, total=%zd, bufs=%d\n", __func__, dh->size, total_size, total_bufs); ++#endif ++ ++ return dh; ++} ++ ++struct dmabuf_h * dmabuf_realloc(struct dmabufs_ctl * dbsc, struct dmabuf_h * old, size_t size) ++{ ++ struct dmabuf_h * dh; ++ if (old != NULL) { ++ if (old->size >= size) { ++ return old; ++ } ++ dmabuf_free(old); ++ } ++ ++ if (size == 0 || ++ (dh = malloc(sizeof(*dh))) == NULL) ++ return NULL; ++ ++ *dh = (struct dmabuf_h){ ++ .fd = -1, ++ .mapptr = MAP_FAILED, ++ .fns = dbsc->fns ++ }; ++ ++ if (dh->fns->buf_alloc(dbsc, dh, size) != 0) ++ goto fail; ++ ++ ++#if TRACE_ALLOC ++ ++total_bufs; ++ total_size += dh->size; ++ request_log("%s: Alloc: %zd, total=%zd, bufs=%d\n", __func__, dh->size, total_size, total_bufs); ++#endif ++ ++ return dh; ++ ++fail: ++ free(dh); ++ return NULL; ++} ++ ++int dmabuf_sync(struct dmabuf_h * const dh, unsigned int flags) ++{ ++ struct dma_buf_sync sync = { ++ .flags = flags ++ }; ++ if (dh->fd == -1) ++ return 0; ++ while (ioctl(dh->fd, DMA_BUF_IOCTL_SYNC, &sync) == -1) { ++ const int err = errno; ++ if (errno == EINTR) ++ continue; ++ request_log("%s: ioctl failed: flags=%#x\n", __func__, flags); ++ return -err; ++ } ++ return 0; ++} ++ ++int dmabuf_write_start(struct dmabuf_h * const dh) ++{ ++ return dmabuf_sync(dh, DMA_BUF_SYNC_START | DMA_BUF_SYNC_WRITE); ++} ++ ++int dmabuf_write_end(struct dmabuf_h * const dh) ++{ ++ return dmabuf_sync(dh, DMA_BUF_SYNC_END | DMA_BUF_SYNC_WRITE); ++} ++ ++int dmabuf_read_start(struct dmabuf_h * const dh) ++{ ++ if (!dmabuf_map(dh)) ++ return -1; ++ return dmabuf_sync(dh, DMA_BUF_SYNC_START | DMA_BUF_SYNC_READ); ++} ++ ++int dmabuf_read_end(struct dmabuf_h * const dh) ++{ ++ return dmabuf_sync(dh, DMA_BUF_SYNC_END | DMA_BUF_SYNC_READ); ++} ++ ++ ++void * dmabuf_map(struct dmabuf_h * const dh) ++{ ++ if (!dh) ++ return NULL; ++ if (dh->mapptr != MAP_FAILED) ++ return dh->mapptr; ++ dh->mapptr = mmap(NULL, dh->size, ++ PROT_READ | PROT_WRITE, ++ MAP_SHARED | MAP_POPULATE, ++ dh->fd, 0); ++ if (dh->mapptr == MAP_FAILED) { ++ request_log("%s: Map failed\n", __func__); ++ return NULL; ++ } ++ return dh->mapptr; ++} ++ ++int dmabuf_fd(const struct dmabuf_h * const dh) ++{ ++ if (!dh) ++ return -1; ++ return dh->fd; ++} ++ ++size_t dmabuf_size(const struct dmabuf_h * const dh) ++{ ++ if (!dh) ++ return 0; ++ return dh->size; ++} ++ ++size_t dmabuf_len(const struct dmabuf_h * const dh) ++{ ++ if (!dh) ++ return 0; ++ return dh->len; ++} ++ ++void dmabuf_len_set(struct dmabuf_h * const dh, const size_t len) ++{ ++ dh->len = len; ++} ++ ++void dmabuf_free(struct dmabuf_h * dh) ++{ ++ if (!dh) ++ return; ++ ++#if TRACE_ALLOC ++ --total_bufs; ++ total_size -= dh->size; ++ request_log("%s: Free: %zd, total=%zd, bufs=%d\n", __func__, dh->size, total_size, total_bufs); ++#endif ++ ++ if (dh->fns != NULL && dh->fns->buf_free) ++ dh->fns->buf_free(dh); ++ ++ if (dh->mapptr != MAP_FAILED && dh->mapptr != NULL) ++ munmap(dh->mapptr, dh->size); ++ if (dh->fd != -1) ++ while (close(dh->fd) == -1 && errno == EINTR) ++ /* loop */; ++ free(dh); ++} ++ ++static struct dmabufs_ctl * dmabufs_ctl_new2(const struct dmabuf_fns * const fns) ++{ ++ struct dmabufs_ctl * dbsc = calloc(1, sizeof(*dbsc)); ++ ++ if (!dbsc) ++ return NULL; ++ ++ dbsc->fd = -1; ++ dbsc->fns = fns; ++ dbsc->page_size = (size_t)sysconf(_SC_PAGE_SIZE); ++ ++ if (fns->ctl_new(dbsc) != 0) ++ goto fail; ++ ++ return dbsc; ++ ++fail: ++ free(dbsc); ++ return NULL; ++} ++ ++static void dmabufs_ctl_free(struct dmabufs_ctl * const dbsc) ++{ ++ request_debug(NULL, "Free dmabuf ctl\n"); ++ ++ dbsc->fns->ctl_free(dbsc); ++ ++ free(dbsc); ++} ++ ++void dmabufs_ctl_unref(struct dmabufs_ctl ** const pDbsc) ++{ ++ struct dmabufs_ctl * const dbsc = *pDbsc; ++ ++ if (!dbsc) ++ return; ++ *pDbsc = NULL; ++ ++ if (atomic_fetch_sub(&dbsc->ref_count, 1) != 0) ++ return; ++ ++ dmabufs_ctl_free(dbsc); ++} ++ ++struct dmabufs_ctl * dmabufs_ctl_ref(struct dmabufs_ctl * const dbsc) ++{ ++ atomic_fetch_add(&dbsc->ref_count, 1); ++ return dbsc; ++} ++ ++//----------------------------------------------------------------------------- ++// ++// Alloc dmabuf via CMA ++ ++static int ctl_cma_new2(struct dmabufs_ctl * dbsc, const char * const * names) ++{ ++ for (; *names != NULL; ++names) ++ { ++ while ((dbsc->fd = open(*names, O_RDWR | __O_CLOEXEC)) == -1 && ++ errno == EINTR) ++ /* Loop */; ++ if (dbsc->fd != -1) ++ { ++ request_debug(NULL, "%s: Using dma_heap device %s\n", __func__, *names); ++ return 0; ++ } ++ request_debug(NULL, "%s: Not using dma_heap device %s: %s\n", __func__, *names, strerror(errno)); ++ } ++ request_log("Unable to open any dma_heap device\n"); ++ return -1; ++} ++ ++static int ctl_cma_new(struct dmabufs_ctl * dbsc) ++{ ++ static const char * const names[] = { ++ "/dev/dma_heap/linux,cma", ++ "/dev/dma_heap/reserved", ++ NULL ++ }; ++ ++ return ctl_cma_new2(dbsc, names); ++} ++ ++static void ctl_cma_free(struct dmabufs_ctl * dbsc) ++{ ++ if (dbsc->fd != -1) ++ while (close(dbsc->fd) == -1 && errno == EINTR) ++ /* loop */; ++} ++ ++static int buf_cma_alloc(struct dmabufs_ctl * const dbsc, struct dmabuf_h * dh, size_t size) ++{ ++ struct dma_heap_allocation_data data = { ++ .len = (size + dbsc->page_size - 1) & ~(dbsc->page_size - 1), ++ .fd = 0, ++ .fd_flags = O_RDWR, ++ .heap_flags = 0 ++ }; ++ ++ while (ioctl(dbsc->fd, DMA_HEAP_IOCTL_ALLOC, &data)) { ++ int err = errno; ++ request_log("Failed to alloc %" PRIu64 " from dma-heap(fd=%d): %d (%s)\n", ++ (uint64_t)data.len, ++ dbsc->fd, ++ err, ++ strerror(err)); ++ if (err == EINTR) ++ continue; ++ return -err; ++ } ++ ++ dh->fd = data.fd; ++ dh->size = (size_t)data.len; ++ ++// fprintf(stderr, "%s: size=%#zx, ftell=%#zx\n", __func__, ++// dh->size, (size_t)lseek(dh->fd, 0, SEEK_END)); ++ ++ return 0; ++} ++ ++static void buf_cma_free(struct dmabuf_h * dh) ++{ ++ // Nothing needed ++} ++ ++static const struct dmabuf_fns dmabuf_cma_fns = { ++ .buf_alloc = buf_cma_alloc, ++ .buf_free = buf_cma_free, ++ .ctl_new = ctl_cma_new, ++ .ctl_free = ctl_cma_free, ++}; ++ ++struct dmabufs_ctl * dmabufs_ctl_new(void) ++{ ++ request_debug(NULL, "Dmabufs using CMA\n"); ++ return dmabufs_ctl_new2(&dmabuf_cma_fns); ++} ++ ++static int ctl_cma_new_vidbuf_cached(struct dmabufs_ctl * dbsc) ++{ ++ static const char * const names[] = { ++ "/dev/dma_heap/vidbuf_cached", ++ "/dev/dma_heap/linux,cma", ++ "/dev/dma_heap/reserved", ++ NULL ++ }; ++ ++ return ctl_cma_new2(dbsc, names); ++} ++ ++static const struct dmabuf_fns dmabuf_vidbuf_cached_fns = { ++ .buf_alloc = buf_cma_alloc, ++ .buf_free = buf_cma_free, ++ .ctl_new = ctl_cma_new_vidbuf_cached, ++ .ctl_free = ctl_cma_free, ++}; ++ ++struct dmabufs_ctl * dmabufs_ctl_new_vidbuf_cached(void) ++{ ++ request_debug(NULL, "Dmabufs using Vidbuf\n"); ++ return dmabufs_ctl_new2(&dmabuf_vidbuf_cached_fns); ++} ++ +diff --git a/libavcodec/v4l2_req_dmabufs.h b/libavcodec/v4l2_req_dmabufs.h +new file mode 100644 +index 000000000000..9226ab2498a5 +--- /dev/null ++++ b/libavcodec/v4l2_req_dmabufs.h +@@ -0,0 +1,69 @@ ++/* ++ Copyright (C) 2024 John Cox john.cox@raspberrypi.com ++ ++ 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. ++ */ ++ ++#ifndef AVCODEC_V4L2_REQ_DMABUFS_H ++#define AVCODEC_V4L2_REQ_DMABUFS_H ++ ++#include ++ ++struct dmabufs_ctl; ++struct dmabuf_h; ++ ++struct dmabufs_ctl * dmabufs_ctl_new(void); ++struct dmabufs_ctl * dmabufs_ctl_new_vidbuf_cached(void); ++void dmabufs_ctl_unref(struct dmabufs_ctl ** const pdbsc); ++struct dmabufs_ctl * dmabufs_ctl_ref(struct dmabufs_ctl * const dbsc); ++ ++// Need not preserve old contents ++// On NULL return old buffer is freed ++struct dmabuf_h * dmabuf_realloc(struct dmabufs_ctl * dbsc, struct dmabuf_h *, size_t size); ++ ++static inline struct dmabuf_h * dmabuf_alloc(struct dmabufs_ctl * dbsc, size_t size) { ++ return dmabuf_realloc(dbsc, NULL, size); ++} ++/* Create from existing fd - dups(fd) */ ++struct dmabuf_h * dmabuf_import(int fd, size_t size); ++/* Import an MMAP - return NULL if mapptr = MAP_FAIL */ ++struct dmabuf_h * dmabuf_import_mmap(void * mapptr, size_t size); ++ ++void * dmabuf_map(struct dmabuf_h * const dh); ++ ++/* flags from linux/dmabuf.h DMA_BUF_SYNC_xxx */ ++int dmabuf_sync(struct dmabuf_h * const dh, unsigned int flags); ++ ++int dmabuf_write_start(struct dmabuf_h * const dh); ++int dmabuf_write_end(struct dmabuf_h * const dh); ++int dmabuf_read_start(struct dmabuf_h * const dh); ++int dmabuf_read_end(struct dmabuf_h * const dh); ++ ++int dmabuf_fd(const struct dmabuf_h * const dh); ++/* Allocated size */ ++size_t dmabuf_size(const struct dmabuf_h * const dh); ++/* Bytes in use */ ++size_t dmabuf_len(const struct dmabuf_h * const dh); ++/* Set bytes in use */ ++void dmabuf_len_set(struct dmabuf_h * const dh, const size_t len); ++void dmabuf_free(struct dmabuf_h * dh); ++ ++#endif +diff --git a/libavcodec/v4l2_req_hevc_v1.c b/libavcodec/v4l2_req_hevc_v1.c +new file mode 100644 +index 000000000000..4d908dac126e +--- /dev/null ++++ b/libavcodec/v4l2_req_hevc_v1.c +@@ -0,0 +1,27 @@ ++/* ++ Copyright (C) 2024 John Cox john.cox@raspberrypi.com ++ ++ 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. ++ */ ++ ++#define HEVC_CTRLS_VERSION 1 ++#include "v4l2_req_hevc_vx.c" ++ +diff --git a/libavcodec/v4l2_req_hevc_v2.c b/libavcodec/v4l2_req_hevc_v2.c +new file mode 100644 +index 000000000000..1874e20a5d8d +--- /dev/null ++++ b/libavcodec/v4l2_req_hevc_v2.c +@@ -0,0 +1,27 @@ ++/* ++ Copyright (C) 2024 John Cox john.cox@raspberrypi.com ++ ++ 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. ++ */ ++ ++#define HEVC_CTRLS_VERSION 2 ++#include "v4l2_req_hevc_vx.c" ++ +diff --git a/libavcodec/v4l2_req_hevc_v3.c b/libavcodec/v4l2_req_hevc_v3.c +new file mode 100644 +index 000000000000..1c5a84bea8d1 +--- /dev/null ++++ b/libavcodec/v4l2_req_hevc_v3.c +@@ -0,0 +1,27 @@ ++/* ++ Copyright (C) 2024 John Cox john.cox@raspberrypi.com ++ ++ 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. ++ */ ++ ++#define HEVC_CTRLS_VERSION 3 ++#include "v4l2_req_hevc_vx.c" ++ +diff --git a/libavcodec/v4l2_req_hevc_v4.c b/libavcodec/v4l2_req_hevc_v4.c +new file mode 100644 +index 000000000000..472df7cb0e39 +--- /dev/null ++++ b/libavcodec/v4l2_req_hevc_v4.c +@@ -0,0 +1,27 @@ ++/* ++ Copyright (C) 2024 John Cox john.cox@raspberrypi.com ++ ++ 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. ++ */ ++ ++#define HEVC_CTRLS_VERSION 4 ++#include "v4l2_req_hevc_vx.c" ++ +diff --git a/libavcodec/v4l2_req_hevc_vx.c b/libavcodec/v4l2_req_hevc_vx.c +new file mode 100644 +index 000000000000..d06ec854e584 +--- /dev/null ++++ b/libavcodec/v4l2_req_hevc_vx.c +@@ -0,0 +1,1442 @@ ++/* ++ Copyright (C) 2024 John Cox john.cox@raspberrypi.com ++ ++ 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. ++ */ ++ ++// File included by v4l2_req_hevc_v* - not compiled on its own ++ ++#include "decode.h" ++#include "hevc/hevcdec.h" ++#include "hwconfig.h" ++#include "internal.h" ++#include "thread.h" ++#include "v4l2_fmt.h" ++ ++#include "libavutil/mem.h" ++ ++#if HEVC_CTRLS_VERSION == 1 ++#include "hevc-ctrls-v1.h" ++ ++// Fixup renamed entries ++#define V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT_ENABLED V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT ++ ++#elif HEVC_CTRLS_VERSION == 2 ++#include "hevc-ctrls-v2.h" ++#elif HEVC_CTRLS_VERSION == 3 ++#include "hevc-ctrls-v3.h" ++#elif HEVC_CTRLS_VERSION == 4 ++#include ++#if !defined(V4L2_CID_STATELESS_HEVC_SPS) ++#include "hevc-ctrls-v4.h" ++#endif ++#else ++#error Unknown HEVC_CTRLS_VERSION ++#endif ++ ++#ifndef V4L2_CID_STATELESS_HEVC_SPS ++#define V4L2_CID_STATELESS_HEVC_SPS V4L2_CID_MPEG_VIDEO_HEVC_SPS ++#define V4L2_CID_STATELESS_HEVC_PPS V4L2_CID_MPEG_VIDEO_HEVC_PPS ++#define V4L2_CID_STATELESS_HEVC_SLICE_PARAMS V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS ++#define V4L2_CID_STATELESS_HEVC_SCALING_MATRIX V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX ++#define V4L2_CID_STATELESS_HEVC_DECODE_PARAMS V4L2_CID_MPEG_VIDEO_HEVC_DECODE_PARAMS ++#define V4L2_CID_STATELESS_HEVC_DECODE_MODE V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE ++#define V4L2_CID_STATELESS_HEVC_START_CODE V4L2_CID_MPEG_VIDEO_HEVC_START_CODE ++ ++#define V4L2_STATELESS_HEVC_DECODE_MODE_SLICE_BASED V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED ++#define V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_FRAME_BASED ++#define V4L2_STATELESS_HEVC_START_CODE_NONE V4L2_MPEG_VIDEO_HEVC_START_CODE_NONE ++#define V4L2_STATELESS_HEVC_START_CODE_ANNEX_B V4L2_MPEG_VIDEO_HEVC_START_CODE_ANNEX_B ++#endif ++ ++#include "v4l2_request_hevc.h" ++ ++#include "libavutil/hwcontext_drm.h" ++ ++#include ++#include ++ ++#include "v4l2_req_devscan.h" ++#include "v4l2_req_dmabufs.h" ++#include "v4l2_req_pollqueue.h" ++#include "v4l2_req_media.h" ++#include "v4l2_req_utils.h" ++ ++// Attached to buf[0] in frame ++// Pooled in hwcontext so generally create once - 1/frame ++typedef struct V4L2MediaReqDescriptor { ++ AVDRMFrameDescriptor drm; ++ ++ // Media ++ uint64_t timestamp; ++ struct qent_dst * qe_dst; ++ ++ // Refs to source frames ++ AVBufferRef * refs[18]; // 16 + 1 + 1 ++ ++ // Decode only - should be NULL by the time we emit the frame ++ struct req_decode_ent decode_ent; ++ ++#if HEVC_CTRLS_VERSION >= 2 ++ struct v4l2_ctrl_hevc_decode_params dec; ++#endif ++ ++ size_t num_slices; ++ size_t alloced_slices; ++ struct v4l2_ctrl_hevc_slice_params * slice_params; ++ struct slice_info * slices; ++ ++ size_t num_offsets; ++ size_t alloced_offsets; ++ uint32_t *offsets; ++ ++} V4L2MediaReqDescriptor; ++ ++struct slice_info { ++ const uint8_t * ptr; ++ size_t len; // bytes ++ size_t n_offsets; ++}; ++ ++// Handy container for accumulating controls before setting ++struct req_controls { ++ int has_scaling; ++ struct timeval tv; ++ struct v4l2_ctrl_hevc_sps sps; ++ struct v4l2_ctrl_hevc_pps pps; ++ struct v4l2_ctrl_hevc_scaling_matrix scaling_matrix; ++}; ++ ++//static uint8_t nalu_slice_start_code[] = { 0x00, 0x00, 0x01 }; ++ ++ ++// Get an FFmpeg format from the v4l2 format ++static enum AVPixelFormat pixel_format_from_format(const struct v4l2_format *const format) ++{ ++ const uint32_t vfmt = V4L2_TYPE_IS_MULTIPLANAR(format->type) ? ++ format->fmt.pix_mp.pixelformat : format->fmt.pix.pixelformat; ++ switch (vfmt) { ++#if CONFIG_SAND ++ case V4L2_PIX_FMT_NV12_COL128: ++ case V4L2_PIX_FMT_NV12_COL128M: ++ return AV_PIX_FMT_RPI4_8; ++ case V4L2_PIX_FMT_NV12_10_COL128: ++ case V4L2_PIX_FMT_NV12_10_COL128M: ++ return AV_PIX_FMT_RPI4_10; ++#endif ++ default: ++ break; ++ } ++ return ff_v4l2_format_v4l2_to_avfmt(vfmt, AV_CODEC_ID_RAWVIDEO); ++} ++ ++static inline uint64_t frame_capture_dpb(const AVFrame * const frame) ++{ ++ const V4L2MediaReqDescriptor *const rd = (V4L2MediaReqDescriptor *)frame->data[0]; ++ return rd->timestamp; ++} ++ ++static inline void frame_set_capture_dpb(AVFrame * const frame, const uint64_t dpb_stamp) ++{ ++ V4L2MediaReqDescriptor *const rd = (V4L2MediaReqDescriptor *)frame->data[0]; ++ rd->timestamp = dpb_stamp; ++} ++ ++static void fill_pred_table(const HEVCContext *h, struct v4l2_hevc_pred_weight_table *table) ++{ ++ int32_t luma_weight_denom, chroma_weight_denom; ++ const SliceHeader * const sh = &h->sh; ++ const HEVCPPS * const pps = h->pps; ++ const HEVCSPS * const sps = pps->sps; ++ ++ if (sh->slice_type == HEVC_SLICE_I || ++ (sh->slice_type == HEVC_SLICE_P && !pps->weighted_pred_flag) || ++ (sh->slice_type == HEVC_SLICE_B && !pps->weighted_bipred_flag)) ++ return; ++ ++ table->luma_log2_weight_denom = sh->luma_log2_weight_denom; ++ ++ if (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]; ++ } ++} ++ ++#if HEVC_CTRLS_VERSION <= 2 ++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 == frame_capture_dpb(frame->f)) ++ 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 == frame_capture_dpb(frame->f)) ++ 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 == frame_capture_dpb(frame->f)) ++ return V4L2_HEVC_DPB_ENTRY_RPS_LT_CURR; ++ } ++ ++ return 0; ++} ++#endif ++ ++static unsigned int ++get_ref_pic_index(const HEVCContext *h, const HEVCFrame *frame, ++ const struct v4l2_hevc_dpb_entry * const entries, ++ const unsigned int num_entries) ++{ ++ uint64_t timestamp; ++ ++ if (!frame) ++ return 0; ++ ++ timestamp = frame_capture_dpb(frame->f); ++ ++ for (unsigned int i = 0; i < num_entries; i++) { ++ if (entries[i].timestamp == timestamp) ++ return i; ++ } ++ ++ return 0; ++} ++ ++static const uint8_t * ptr_from_index(const uint8_t * b, unsigned int idx) ++{ ++ unsigned int z = 0; ++ while (idx--) { ++ if (*b++ == 0) { ++ ++z; ++ if (z >= 2 && *b == 3) { ++ ++b; ++ z = 0; ++ } ++ } ++ else { ++ z = 0; ++ } ++ } ++ return b; ++} ++ ++static int slice_add(V4L2MediaReqDescriptor * const rd) ++{ ++ if (rd->num_slices >= rd->alloced_slices) { ++ size_t n2 = rd->alloced_slices == 0 ? 8 : rd->alloced_slices * 2; ++ ++ if (av_reallocp_array(&rd->slice_params, n2, sizeof(*rd->slice_params))) ++ goto fail; ++ if (av_reallocp_array(&rd->slices, n2, sizeof(*rd->slices))) ++ goto fail; ++ rd->alloced_slices = n2; ++ } ++ ++rd->num_slices; ++ return 0; ++ ++fail: ++ av_freep(&rd->slices); ++ rd->alloced_slices = 0; ++ rd->num_slices = 0; ++ return AVERROR(ENOMEM); ++} ++ ++static int offsets_add(V4L2MediaReqDescriptor *const rd, const size_t n, const unsigned * const offsets) ++{ ++ if (rd->num_offsets + n > rd->alloced_offsets) { ++ size_t n2 = rd->alloced_slices == 0 ? 128 : rd->alloced_slices * 2; ++ void * p2; ++ while (rd->num_offsets + n > n2) ++ n2 *= 2; ++ if (av_reallocp_array(&rd->offsets, n2, sizeof(*rd->offsets))) { ++ rd->alloced_offsets = 0; ++ rd->num_offsets = 0; ++ return AVERROR(ENOMEM); ++ } ++ rd->offsets = p2; ++ rd->alloced_offsets = n2; ++ } ++ for (size_t i = 0; i != n; ++i) ++ rd->offsets[rd->num_offsets++] = offsets[i] - 1; ++ return 0; ++} ++ ++static unsigned int ++fill_dpb_entries(const HEVCContext * const h, struct v4l2_hevc_dpb_entry * const entries) ++{ ++ unsigned int i; ++ unsigned int n = 0; ++ const HEVCFrame * const pic = h->cur_frame; ++ const HEVCLayerContext * const layer = &h->layers[h->cur_layer]; ++ ++ for (i = 0; i < FF_ARRAY_ELEMS(layer->DPB); i++) { ++ const HEVCFrame * const frame = &layer->DPB[i]; ++ if (frame != pic && (frame->flags & (HEVC_FRAME_FLAG_LONG_REF | HEVC_FRAME_FLAG_SHORT_REF))) { ++ struct v4l2_hevc_dpb_entry * const entry = entries + n++; ++ ++ entry->timestamp = frame_capture_dpb(frame->f); ++#if HEVC_CTRLS_VERSION <= 2 ++ entry->rps = find_frame_rps_type(h, entry->timestamp); ++#else ++ entry->flags = (frame->flags & HEVC_FRAME_FLAG_LONG_REF) == 0 ? 0 : ++ V4L2_HEVC_DPB_ENTRY_LONG_TERM_REFERENCE; ++#endif ++ entry->field_pic = (frame->f->flags & AV_FRAME_FLAG_INTERLACED) != 0; ++ ++#if HEVC_CTRLS_VERSION <= 3 ++ /* TODO: Interleaved: Get the POC for each field. */ ++ entry->pic_order_cnt[0] = frame->poc; ++ entry->pic_order_cnt[1] = frame->poc; ++#else ++ entry->pic_order_cnt_val = frame->poc; ++#endif ++ } ++ } ++ return n; ++} ++ ++static void fill_slice_params(const HEVCContext * const h, ++#if HEVC_CTRLS_VERSION >= 2 ++ const struct v4l2_ctrl_hevc_decode_params * const dec, ++#endif ++ struct v4l2_ctrl_hevc_slice_params *slice_params, ++ uint32_t bit_size, uint32_t bit_offset) ++{ ++ const SliceHeader * const sh = &h->sh; ++#if HEVC_CTRLS_VERSION >= 2 ++ const struct v4l2_hevc_dpb_entry *const dpb = dec->dpb; ++ const unsigned int dpb_n = dec->num_active_dpb_entries; ++#else ++ struct v4l2_hevc_dpb_entry *const dpb = slice_params->dpb; ++ unsigned int dpb_n; ++#endif ++ unsigned int i; ++ RefPicList *rpl; ++ ++ *slice_params = (struct v4l2_ctrl_hevc_slice_params) { ++ .bit_size = bit_size, ++#if HEVC_CTRLS_VERSION <= 3 ++ .data_bit_offset = bit_offset, ++#else ++ .data_byte_offset = bit_offset / 8 + 1, ++#endif ++ /* 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 = h->cur_frame->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, ++ ++#if HEVC_CTRLS_VERSION < 2 ++ /* 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, ++#endif ++ }; ++ ++ 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; ++ ++#if HEVC_CTRLS_VERSION < 2 ++ dpb_n = fill_dpb_entries(h, dpb); ++ slice_params->num_active_dpb_entries = dpb_n; ++#endif ++ ++ if (sh->slice_type != HEVC_SLICE_I) { ++ rpl = &h->cur_frame->refPicList[0]; ++ for (i = 0; i < rpl->nb_refs; i++) ++ slice_params->ref_idx_l0[i] = get_ref_pic_index(h, rpl->ref[i], dpb, dpb_n); ++ } ++ ++ if (sh->slice_type == HEVC_SLICE_B) { ++ rpl = &h->cur_frame->refPicList[1]; ++ for (i = 0; i < rpl->nb_refs; i++) ++ slice_params->ref_idx_l1[i] = get_ref_pic_index(h, rpl->ref[i], dpb, dpb_n); ++ } ++ ++ fill_pred_table(h, &slice_params->pred_weight_table); ++ ++ slice_params->num_entry_point_offsets = sh->num_entry_point_offsets; ++#if HEVC_CTRLS_VERSION <= 3 ++ 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; ++#endif ++} ++ ++#if HEVC_CTRLS_VERSION >= 2 ++static void ++fill_decode_params(const HEVCContext * const h, ++ struct v4l2_ctrl_hevc_decode_params * const dec) ++{ ++ unsigned int i; ++ ++ *dec = (struct v4l2_ctrl_hevc_decode_params){ ++ .pic_order_cnt_val = h->poc, ++ .num_poc_st_curr_before = h->rps[ST_CURR_BEF].nb_refs, ++ .num_poc_st_curr_after = h->rps[ST_CURR_AFT].nb_refs, ++ .num_poc_lt_curr = h->rps[LT_CURR].nb_refs, ++ }; ++ ++ dec->num_active_dpb_entries = fill_dpb_entries(h, dec->dpb); ++ ++ // The docn does seem to ask that we fit our 32 bit signed POC into ++ // a U8 so... (To be fair 16 bits would be enough) ++ // Luckily we (Pi) don't use these fields ++ for (i = 0; i != h->rps[ST_CURR_BEF].nb_refs; ++i) ++ dec->poc_st_curr_before[i] = h->rps[ST_CURR_BEF].ref[i]->poc; ++ for (i = 0; i != h->rps[ST_CURR_AFT].nb_refs; ++i) ++ dec->poc_st_curr_after[i] = h->rps[ST_CURR_AFT].ref[i]->poc; ++ for (i = 0; i != h->rps[LT_CURR].nb_refs; ++i) ++ dec->poc_lt_curr[i] = h->rps[LT_CURR].ref[i]->poc; ++ ++ if (IS_IRAP(h)) ++ dec->flags |= V4L2_HEVC_DECODE_PARAM_FLAG_IRAP_PIC; ++ if (IS_IDR(h)) ++ dec->flags |= V4L2_HEVC_DECODE_PARAM_FLAG_IDR_PIC; ++ if (h->sh.no_output_of_prior_pics_flag) ++ dec->flags |= V4L2_HEVC_DECODE_PARAM_FLAG_NO_OUTPUT_OF_PRIOR; ++ ++} ++#endif ++ ++static void fill_sps(struct v4l2_ctrl_hevc_sps *ctrl, const HEVCSPS *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, ++ .chroma_format_idc = sps->chroma_format_idc, ++ .sps_max_sub_layers_minus1 = sps->max_sub_layers - 1, ++ }; ++ ++ if (sps->separate_colour_plane) ++ ctrl->flags |= V4L2_HEVC_SPS_FLAG_SEPARATE_COLOUR_PLANE; ++ ++ if (sps->scaling_list_enabled) ++ ctrl->flags |= V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED; ++ ++ if (sps->amp_enabled) ++ 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) ++ ctrl->flags |= V4L2_HEVC_SPS_FLAG_PCM_ENABLED; ++ ++ if (sps->pcm_loop_filter_disabled) ++ ctrl->flags |= V4L2_HEVC_SPS_FLAG_PCM_LOOP_FILTER_DISABLED; ++ ++ if (sps->long_term_ref_pics_present) ++ ctrl->flags |= V4L2_HEVC_SPS_FLAG_LONG_TERM_REF_PICS_PRESENT; ++ ++ if (sps->temporal_mvp_enabled) ++ ctrl->flags |= V4L2_HEVC_SPS_FLAG_SPS_TEMPORAL_MVP_ENABLED; ++ ++ if (sps->strong_intra_smoothing_enabled) ++ ctrl->flags |= V4L2_HEVC_SPS_FLAG_STRONG_INTRA_SMOOTHING_ENABLED; ++} ++ ++static void fill_scaling_matrix(const ScalingList * const sl, ++ struct v4l2_ctrl_hevc_scaling_matrix * const sm) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < 6; i++) { ++ unsigned int j; ++ ++ for (j = 0; j < 16; j++) ++ sm->scaling_list_4x4[i][j] = sl->sl[0][i][j]; ++ for (j = 0; j < 64; j++) { ++ sm->scaling_list_8x8[i][j] = sl->sl[1][i][j]; ++ sm->scaling_list_16x16[i][j] = sl->sl[2][i][j]; ++ if (i < 2) ++ sm->scaling_list_32x32[i][j] = sl->sl[3][i * 3][j]; ++ } ++ sm->scaling_list_dc_coef_16x16[i] = sl->sl_dc[0][i]; ++ if (i < 2) ++ sm->scaling_list_dc_coef_32x32[i] = sl->sl_dc[1][i * 3]; ++ } ++} ++ ++static void fill_pps(struct v4l2_ctrl_hevc_pps * const ctrl, const HEVCPPS * const pps) ++{ ++ uint64_t flags = 0; ++ ++ if (pps->dependent_slice_segments_enabled_flag) ++ flags |= V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT_ENABLED; ++ ++ if (pps->output_flag_present_flag) ++ flags |= V4L2_HEVC_PPS_FLAG_OUTPUT_FLAG_PRESENT; ++ ++ if (pps->sign_data_hiding_flag) ++ flags |= V4L2_HEVC_PPS_FLAG_SIGN_DATA_HIDING_ENABLED; ++ ++ if (pps->cabac_init_present_flag) ++ flags |= V4L2_HEVC_PPS_FLAG_CABAC_INIT_PRESENT; ++ ++ if (pps->constrained_intra_pred_flag) ++ flags |= V4L2_HEVC_PPS_FLAG_CONSTRAINED_INTRA_PRED; ++ ++ if (pps->transform_skip_enabled_flag) ++ flags |= V4L2_HEVC_PPS_FLAG_TRANSFORM_SKIP_ENABLED; ++ ++ if (pps->cu_qp_delta_enabled_flag) ++ flags |= V4L2_HEVC_PPS_FLAG_CU_QP_DELTA_ENABLED; ++ ++ if (pps->pic_slice_level_chroma_qp_offsets_present_flag) ++ flags |= V4L2_HEVC_PPS_FLAG_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT; ++ ++ if (pps->weighted_pred_flag) ++ flags |= V4L2_HEVC_PPS_FLAG_WEIGHTED_PRED; ++ ++ if (pps->weighted_bipred_flag) ++ flags |= V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED; ++ ++ if (pps->transquant_bypass_enable_flag) ++ flags |= V4L2_HEVC_PPS_FLAG_TRANSQUANT_BYPASS_ENABLED; ++ ++ if (pps->tiles_enabled_flag) ++ flags |= V4L2_HEVC_PPS_FLAG_TILES_ENABLED; ++ ++ if (pps->entropy_coding_sync_enabled_flag) ++ flags |= V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED; ++ ++ if (pps->loop_filter_across_tiles_enabled_flag) ++ flags |= V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED; ++ ++ if (pps->seq_loop_filter_across_slices_enabled_flag) ++ flags |= V4L2_HEVC_PPS_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED; ++ ++ if (pps->deblocking_filter_override_enabled_flag) ++ flags |= V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_OVERRIDE_ENABLED; ++ ++ if (pps->disable_dbf) ++ flags |= V4L2_HEVC_PPS_FLAG_PPS_DISABLE_DEBLOCKING_FILTER; ++ ++ if (pps->lists_modification_present_flag) ++ flags |= V4L2_HEVC_PPS_FLAG_LISTS_MODIFICATION_PRESENT; ++ ++ if (pps->slice_header_extension_present_flag) ++ flags |= V4L2_HEVC_PPS_FLAG_SLICE_SEGMENT_HEADER_EXTENSION_PRESENT; ++ ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture parameter set */ ++ *ctrl = (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, ++ .flags = flags ++ }; ++ ++ ++ if (pps->tiles_enabled_flag) { ++ ctrl->num_tile_columns_minus1 = pps->num_tile_columns - 1; ++ ctrl->num_tile_rows_minus1 = pps->num_tile_rows - 1; ++ ++ for (int i = 0; i < pps->num_tile_columns; i++) ++ ctrl->column_width_minus1[i] = pps->column_width[i] - 1; ++ ++ for (int i = 0; i < pps->num_tile_rows; i++) ++ ctrl->row_height_minus1[i] = pps->row_height[i] - 1; ++ } ++} ++ ++static int frame_finish(V4L2MediaReqDescriptor * const rd) ++{ ++ int rv = 0; ++ ++ if (rd->qe_dst) { ++ MediaBufsStatus stat = qent_dst_wait(rd->qe_dst); ++ if (stat != MEDIABUFS_STATUS_SUCCESS) ++ rv = -1; ++ } ++ ++ { ++ AVBufferRef **p = rd->refs; ++ for (; *p != NULL; ++p) ++ av_buffer_unref(p); ++ } ++ ++ 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 frame_post_process(void *logctx, AVFrame *frame) ++{ ++ V4L2MediaReqDescriptor *rd = (V4L2MediaReqDescriptor*)frame->data[0]; ++ ++// av_log(NULL, AV_LOG_INFO, "%s\n", __func__); ++ frame->flags &= ~AV_FRAME_FLAG_CORRUPT; ++ if (frame_finish(rd) != 0) { ++ av_log(logctx, AV_LOG_ERROR, "%s: Decode fail\n", __func__); ++ frame->flags |= AV_FRAME_FLAG_CORRUPT; ++ } ++ return 0; ++} ++ ++static inline struct timeval cvt_dpb_to_tv(uint64_t t) ++{ ++ t /= 1000; ++ return (struct timeval){ ++ .tv_usec = t % 1000000, ++ .tv_sec = t / 1000000 ++ }; ++} ++ ++static inline uint64_t cvt_timestamp_to_dpb(const unsigned int t) ++{ ++ return (uint64_t)t * 1000; ++} ++ ++static int v4l2_request_hevc_start_frame(AVCodecContext *avctx, ++ V4L2RequestContextHEVC *const ctx, ++ av_unused const uint8_t *buffer, ++ av_unused uint32_t size) ++{ ++ const HEVCContext *h = avctx->priv_data; ++ V4L2MediaReqDescriptor *const rd = (V4L2MediaReqDescriptor *)h->cur_frame->f->data[0]; ++ ++// av_log(NULL, AV_LOG_INFO, "%s\n", __func__); ++ decode_q_add(&ctx->decode_q, &rd->decode_ent); ++ ++ rd->num_slices = 0; ++ ctx->timestamp++; ++ rd->timestamp = cvt_timestamp_to_dpb(ctx->timestamp); ++ ++ { ++ FrameDecodeData * const fdd = (FrameDecodeData*)h->cur_frame->f->private_ref->data; ++ fdd->post_process = frame_post_process; ++ } ++ ++ // qe_dst needs to be bound to the data buffer and only returned when that is ++ if (!rd->qe_dst) ++ { ++ if ((rd->qe_dst = mediabufs_dst_qent_alloc(ctx->mbufs, ctx->dbufs)) == NULL) { ++ av_log(avctx, AV_LOG_ERROR, "%s: Failed to get dst buffer\n", __func__); ++ return AVERROR(ENOMEM); ++ } ++ } ++ ++ // ff_thread_finish_setup by caller ++ ++ return 0; ++} ++ ++// Object fd & size will be zapped by this & need setting later ++static int drm_from_format(AVDRMFrameDescriptor * const desc, const struct v4l2_format * const format) ++{ ++ AVDRMLayerDescriptor *layer = &desc->layers[0]; ++ unsigned int width; ++ unsigned int height; ++ unsigned int bpl; ++ unsigned int bpl2; ++ uint32_t pixelformat; ++ uint64_t mod = DRM_FORMAT_MOD_LINEAR; ++ unsigned int object_count = 1; ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(format->type)) { ++ width = format->fmt.pix_mp.width; ++ height = format->fmt.pix_mp.height; ++ pixelformat = format->fmt.pix_mp.pixelformat; ++ bpl = format->fmt.pix_mp.plane_fmt[0].bytesperline; ++ } ++ else { ++ width = format->fmt.pix.width; ++ height = format->fmt.pix.height; ++ pixelformat = format->fmt.pix.pixelformat; ++ bpl = format->fmt.pix.bytesperline; ++ } ++ bpl2 = bpl; ++ ++ switch (pixelformat) { ++ case V4L2_PIX_FMT_NV12: ++ layer->format = DRM_FORMAT_NV12; ++ break; ++ case V4L2_PIX_FMT_P010: ++ layer->format = DRM_FORMAT_P010; ++ break; ++#if CONFIG_SAND ++ case V4L2_PIX_FMT_NV12_COL128: ++ layer->format = DRM_FORMAT_NV12; ++ mod = DRM_FORMAT_MOD_BROADCOM_SAND128_COL_HEIGHT(bpl); ++ break; ++ case V4L2_PIX_FMT_NV12_10_COL128: ++ layer->format = DRM_FORMAT_P030; ++ mod = DRM_FORMAT_MOD_BROADCOM_SAND128_COL_HEIGHT(bpl); ++ break; ++ case V4L2_PIX_FMT_NV12_COL128M: ++ layer->format = DRM_FORMAT_NV12; ++ mod = DRM_FORMAT_MOD_BROADCOM_SAND128_COL_HEIGHT(0); ++ bpl = height; ++ bpl2 = height / 2; ++ object_count = 2; ++ break; ++ case V4L2_PIX_FMT_NV12_10_COL128M: ++ layer->format = DRM_FORMAT_P030; ++ mod = DRM_FORMAT_MOD_BROADCOM_SAND128_COL_HEIGHT(0); ++ bpl = height; ++ bpl2 = height / 2; ++ object_count = 2; ++ break; ++#endif ++#ifdef DRM_FORMAT_MOD_ALLWINNER_TILED ++ case V4L2_PIX_FMT_SUNXI_TILED_NV12: ++ layer->format = DRM_FORMAT_NV12; ++ mod = 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; ++ break; ++#endif ++ case V4L2_PIX_FMT_NV16: ++ layer->format = DRM_FORMAT_NV16; ++ break; ++#if defined(V4L2_PIX_FMT_NV20) && defined(DRM_FORMAT_NV20) ++ case V4L2_PIX_FMT_NV20: ++ layer->format = DRM_FORMAT_NV20; ++ break; ++#endif ++ default: ++ return -1; ++ } ++ ++ desc->nb_objects = object_count; ++ for (unsigned int i = 0; i != AV_DRM_MAX_PLANES; ++i) { ++ desc->objects[i].fd = -1; ++ desc->objects[i].size = 0; ++ desc->objects[i].format_modifier = (i >= object_count) ? DRM_FORMAT_MOD_INVALID : mod; ++ } ++ ++ desc->nb_layers = 1; ++ layer->nb_planes = 2; ++ ++ layer->planes[0].object_index = 0; ++ layer->planes[0].offset = 0; ++ layer->planes[0].pitch = bpl; ++#if CONFIG_SAND ++ if (pixelformat == V4L2_PIX_FMT_NV12_COL128) { ++ layer->planes[1].object_index = 0; ++ layer->planes[1].offset = height * 128; ++ layer->planes[0].pitch = width; ++ layer->planes[1].pitch = width; ++ } ++ else if (pixelformat == V4L2_PIX_FMT_NV12_10_COL128) { ++ layer->planes[1].object_index = 0; ++ layer->planes[1].offset = height * 128; ++ layer->planes[0].pitch = width * 2; // Lies but it keeps DRM import happy ++ layer->planes[1].pitch = width * 2; ++ } ++ else ++#endif ++ { ++ layer->planes[1].object_index = (object_count > 1) ? 1 : 0; ++ layer->planes[1].offset = (object_count > 1) ? 0 : layer->planes[0].pitch * height; ++ layer->planes[1].pitch = bpl2; ++ } ++ ++ return 0; ++} ++ ++static int ++set_req_ctls(V4L2RequestContextHEVC *ctx, struct media_request * const mreq, ++ struct req_controls *const controls, ++#if HEVC_CTRLS_VERSION >= 2 ++ struct v4l2_ctrl_hevc_decode_params * const dec, ++#endif ++ struct v4l2_ctrl_hevc_slice_params * const slices, const unsigned int slice_count, ++ void * const offsets, const size_t offset_count) ++{ ++ int rv; ++#if HEVC_CTRLS_VERSION >= 2 ++ unsigned int n = 3; ++#else ++ unsigned int n = 2; ++#endif ++ ++ struct v4l2_ext_control control[6] = { ++ { ++ .id = V4L2_CID_STATELESS_HEVC_SPS, ++ .ptr = &controls->sps, ++ .size = sizeof(controls->sps), ++ }, ++ { ++ .id = V4L2_CID_STATELESS_HEVC_PPS, ++ .ptr = &controls->pps, ++ .size = sizeof(controls->pps), ++ }, ++#if HEVC_CTRLS_VERSION >= 2 ++ { ++ .id = V4L2_CID_STATELESS_HEVC_DECODE_PARAMS, ++ .ptr = dec, ++ .size = sizeof(*dec), ++ }, ++#endif ++ }; ++ ++ if (slices) ++ control[n++] = (struct v4l2_ext_control) { ++ .id = V4L2_CID_STATELESS_HEVC_SLICE_PARAMS, ++ .ptr = slices, ++ .size = sizeof(*slices) * slice_count, ++ }; ++ ++ if (controls->has_scaling) ++ control[n++] = (struct v4l2_ext_control) { ++ .id = V4L2_CID_STATELESS_HEVC_SCALING_MATRIX, ++ .ptr = &controls->scaling_matrix, ++ .size = sizeof(controls->scaling_matrix), ++ }; ++ ++#if HEVC_CTRLS_VERSION >= 4 ++ if (offsets) ++ control[n++] = (struct v4l2_ext_control) { ++ .id = V4L2_CID_STATELESS_HEVC_ENTRY_POINT_OFFSETS, ++ .ptr = offsets, ++ .size = sizeof(((struct V4L2MediaReqDescriptor *)0)->offsets[0]) * offset_count, ++ }; ++#endif ++ ++ rv = mediabufs_ctl_set_ext_ctrls(ctx->mbufs, mreq, control, n); ++ ++ return rv; ++} ++ ++static void ++add_ref_once(V4L2MediaReqDescriptor * const rd, struct HEVCFrame * const ref) ++{ ++ AVBufferRef **p = rd->refs; ++ int i = 0; ++ while (*p != NULL) { ++ if (ref->f->buf[0]->data == (*p)->data) ++ return; ++ ++p; ++ av_assert0(++i < 16); ++ } ++ *p = av_buffer_ref(ref->f->buf[0]); ++} ++ ++// This only works because we started out from a single coded frame buffer ++// that will remain intact until after end_frame ++static int v4l2_request_hevc_decode_slice(AVCodecContext *avctx, V4L2RequestContextHEVC *const ctx, const uint8_t *buffer, uint32_t size) ++{ ++ const HEVCContext * const h = avctx->priv_data; ++ const SliceHeader * const sh = &h->sh; ++ V4L2MediaReqDescriptor * const rd = (V4L2MediaReqDescriptor*)h->cur_frame->f->data[0]; ++ uint32_t boff = (ptr_from_index(buffer, sh->data_offset) - buffer) * 8 - 1; ++ ++ const unsigned int n = rd->num_slices; ++ const unsigned int block_start = (n / ctx->max_slices) * ctx->max_slices; ++ ++ int rv; ++ struct slice_info * si; ++ ++ // This looks dodgy but we know that FFmpeg has parsed this from a buffer ++ // that contains the entire frame including the start code ++ if (ctx->start_code == V4L2_STATELESS_HEVC_START_CODE_ANNEX_B) { ++ buffer -= 3; ++ size += 3; ++ boff += 24; ++ if (buffer[0] != 0 || buffer[1] != 0 || buffer[2] != 1) { ++ av_log(avctx, AV_LOG_ERROR, "Start code requested but missing %02x:%02x:%02x\n", ++ buffer[0], buffer[1], buffer[2]); ++ } ++ } ++ ++ if ((rv = slice_add(rd)) != 0) ++ return rv; ++ ++ si = rd->slices + n; ++ si->ptr = buffer; ++ si->len = size; ++ si->n_offsets = rd->num_offsets; ++ ++ if (n != block_start) { ++ struct slice_info *const si0 = rd->slices + block_start; ++ const size_t offset = (buffer - si0->ptr); ++ boff += offset * 8; ++ size += offset; ++ si0->len = si->len + offset; ++ } ++ ++#if HEVC_CTRLS_VERSION >= 2 ++ if (n == 0) ++ fill_decode_params(h, &rd->dec); ++ fill_slice_params(h, &rd->dec, rd->slice_params + n, size * 8, boff); ++#else ++ fill_slice_params(h, rd->slice_params + n, size * 8, boff); ++#endif ++ ++ { ++ RefPicList *rpl; ++ int i; ++ ++ if (sh->slice_type != HEVC_SLICE_I) { ++ rpl = &h->cur_frame->refPicList[0]; ++ for (i = 0; i < rpl->nb_refs; i++) ++ add_ref_once(rd, rpl->ref[i]); ++ } ++ ++ if (sh->slice_type == HEVC_SLICE_B) { ++ rpl = &h->cur_frame->refPicList[1]; ++ for (i = 0; i < rpl->nb_refs; i++) ++ add_ref_once(rd, rpl->ref[i]); ++ } ++ } ++ ++ if (ctx->max_offsets != 0 && ++ (rv = offsets_add(rd, h->sh.num_entry_point_offsets, h->sh.entry_point_offset)) != 0) ++ return rv; ++ ++ return 0; ++} ++ ++static void v4l2_request_hevc_abort_frame(AVCodecContext * const avctx, V4L2RequestContextHEVC *const ctx) ++{ ++ const HEVCContext * const h = avctx->priv_data; ++ if (h->cur_frame != NULL) { ++ V4L2MediaReqDescriptor *const rd = (V4L2MediaReqDescriptor *)h->cur_frame->f->data[0]; ++ ++ decode_q_remove(&ctx->decode_q, &rd->decode_ent); ++ } ++} ++ ++static int send_slice(AVCodecContext * const avctx, ++ V4L2RequestContextHEVC * const ctx, ++ V4L2MediaReqDescriptor * const rd, ++ struct req_controls *const controls, ++ const unsigned int i, const unsigned int j) ++{ ++ const int is_last = (j == rd->num_slices); ++ struct slice_info *const si = rd->slices + i; ++ struct media_request * req = NULL; ++ struct qent_src * src = NULL; ++ MediaBufsStatus stat; ++ void * offsets = rd->offsets + rd->slices[i].n_offsets; ++ size_t n_offsets = (is_last ? rd->num_offsets : rd->slices[j].n_offsets) - rd->slices[i].n_offsets; ++ ++ if ((req = media_request_get(ctx->mpool)) == NULL) { ++ av_log(avctx, AV_LOG_ERROR, "%s: Failed to alloc media request\n", __func__); ++ return AVERROR(ENOMEM); ++ } ++ ++ if (set_req_ctls(ctx, req, ++ controls, ++#if HEVC_CTRLS_VERSION >= 2 ++ &rd->dec, ++#endif ++ rd->slice_params + i, j - i, ++ offsets, n_offsets)) { ++ av_log(avctx, AV_LOG_ERROR, "%s: Failed to set req ctls\n", __func__); ++ goto fail1; ++ } ++ ++ if ((src = mediabufs_src_qent_get(ctx->mbufs)) == NULL) { ++ av_log(avctx, AV_LOG_ERROR, "%s: Failed to get src buffer\n", __func__); ++ goto fail1; ++ } ++ ++ if (qent_src_data_copy(src, 0, si->ptr, si->len, ctx->dbufs) != 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: Failed data copy\n", __func__); ++ goto fail2; ++ } ++ ++ if (qent_src_params_set(src, &controls->tv)) { ++ av_log(avctx, AV_LOG_ERROR, "%s: Failed src param set\n", __func__); ++ goto fail2; ++ } ++ ++ stat = mediabufs_start_request(ctx->mbufs, &req, &src, ++ i == 0 ? rd->qe_dst : NULL, ++ is_last); ++ ++ if (stat != MEDIABUFS_STATUS_SUCCESS) { ++ av_log(avctx, AV_LOG_ERROR, "%s: Failed to start request\n", __func__); ++ return AVERROR_UNKNOWN; ++ } ++ return 0; ++ ++fail2: ++ mediabufs_src_qent_abort(ctx->mbufs, &src); ++fail1: ++ media_request_abort(&req); ++ return AVERROR_UNKNOWN; ++} ++ ++static int v4l2_request_hevc_end_frame(AVCodecContext *avctx, V4L2RequestContextHEVC *const ctx) ++{ ++ const HEVCContext * const h = avctx->priv_data; ++ V4L2MediaReqDescriptor *rd = (V4L2MediaReqDescriptor*)h->cur_frame->f->data[0]; ++ struct req_controls rc; ++ unsigned int i; ++ int rv; ++ ++ // It is possible, though maybe a bug, to get an end_frame without ++ // a previous start_frame. If we do then give up. ++ if (!decode_q_in_q(&rd->decode_ent)) { ++ av_log(avctx, AV_LOG_DEBUG, "%s: Frame not in decode Q\n", __func__); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ { ++ const HEVCPPS *pps = h->pps; ++ const HEVCSPS *sps = pps->sps; ++ const ScalingList *sl = pps->scaling_list_data_present_flag ? ++ &pps->scaling_list : ++ sps->scaling_list_enabled ? ++ &sps->scaling_list : NULL; ++ ++ ++ memset(&rc, 0, sizeof(rc)); ++ rc.tv = cvt_dpb_to_tv(rd->timestamp); ++ fill_sps(&rc.sps, sps); ++ fill_pps(&rc.pps, pps); ++ if (sl) { ++ rc.has_scaling = 1; ++ fill_scaling_matrix(sl, &rc.scaling_matrix); ++ } ++ } ++ ++ decode_q_wait(&ctx->decode_q, &rd->decode_ent); ++ ++ // qe_dst needs to be bound to the data buffer and only returned when that is ++ // Alloc almost certainly wants to be serialised if there is any chance of blocking ++ // so we get the next frame to be free in the thread that needs it for decode first. ++ // ++ // In our current world this probably isn't a concern but put it here anyway ++ if (!rd->qe_dst) ++ { ++ if ((rd->qe_dst = mediabufs_dst_qent_alloc(ctx->mbufs, ctx->dbufs)) == NULL) { ++ av_log(avctx, AV_LOG_ERROR, "%s: Failed to get dst buffer\n", __func__); ++ rv = AVERROR(ENOMEM); ++ goto fail; ++ } ++ } ++ ++ // Send as slices ++ for (i = 0; i < rd->num_slices; i += ctx->max_slices) { ++ const unsigned int e = FFMIN(rd->num_slices, i + ctx->max_slices); ++ if ((rv = send_slice(avctx, ctx, rd, &rc, i, e)) != 0) ++ goto fail; ++ } ++ ++ // Set the drm_prime desriptor ++ drm_from_format(&rd->drm, mediabufs_dst_fmt(ctx->mbufs)); ++ for (i = 0; i != rd->drm.nb_objects; ++i) { ++ rd->drm.objects[i].fd = dmabuf_fd(qent_dst_dmabuf(rd->qe_dst, i)); ++ rd->drm.objects[i].size = dmabuf_size(qent_dst_dmabuf(rd->qe_dst, i)); ++ } ++ ++ decode_q_remove(&ctx->decode_q, &rd->decode_ent); ++ return 0; ++ ++fail: ++ decode_q_remove(&ctx->decode_q, &rd->decode_ent); ++ return rv; ++} ++ ++static inline int ++ctrl_valid(const struct v4l2_query_ext_ctrl * const c, const int64_t v) ++{ ++ return v >= c->minimum && v <= c->maximum; ++} ++ ++// Initial check & init ++static int ++probe(AVCodecContext * const avctx, V4L2RequestContextHEVC * const ctx) ++{ ++ const HEVCContext *h = avctx->priv_data; ++ const HEVCSPS * const sps = h->pps->sps; ++ struct v4l2_ctrl_hevc_sps ctrl_sps; ++ unsigned int i; ++ ++ // Check for var slice array ++ struct v4l2_query_ext_ctrl qc[] = { ++ { .id = V4L2_CID_STATELESS_HEVC_SLICE_PARAMS }, ++ { .id = V4L2_CID_STATELESS_HEVC_DECODE_MODE, }, ++ { .id = V4L2_CID_STATELESS_HEVC_SPS }, ++ { .id = V4L2_CID_STATELESS_HEVC_PPS }, ++ { .id = V4L2_CID_STATELESS_HEVC_SCALING_MATRIX }, ++#if HEVC_CTRLS_VERSION >= 2 ++ { .id = V4L2_CID_STATELESS_HEVC_DECODE_PARAMS }, ++#endif ++ }; ++ // Order & size must match! ++ static const size_t ctrl_sizes[] = { ++ sizeof(struct v4l2_ctrl_hevc_slice_params), ++ sizeof(int32_t), ++ sizeof(struct v4l2_ctrl_hevc_sps), ++ sizeof(struct v4l2_ctrl_hevc_pps), ++ sizeof(struct v4l2_ctrl_hevc_scaling_matrix), ++#if HEVC_CTRLS_VERSION >= 2 ++ sizeof(struct v4l2_ctrl_hevc_decode_params), ++#endif ++ }; ++ const unsigned int noof_ctrls = FF_ARRAY_ELEMS(qc); ++ ++#if HEVC_CTRLS_VERSION == 2 ++ if (mediabufs_ctl_driver_version(ctx->mbufs) >= MEDIABUFS_DRIVER_VERSION(5, 18, 0)) ++ return AVERROR(EINVAL); ++#elif HEVC_CTRLS_VERSION == 3 ++ if (mediabufs_ctl_driver_version(ctx->mbufs) < MEDIABUFS_DRIVER_VERSION(5, 18, 0)) ++ return AVERROR(EINVAL); ++#endif ++ ++ mediabufs_ctl_query_ext_ctrls(ctx->mbufs, qc, noof_ctrls); ++ i = 0; ++#if HEVC_CTRLS_VERSION < 4 ++ // Fail frame mode silently for anything prior to V4 ++ if (qc[1].type == 0 || !ctrl_valid(qc + 1, V4L2_STATELESS_HEVC_DECODE_MODE_SLICE_BASED)) ++ return AVERROR(EINVAL); ++#endif ++ for (; i != noof_ctrls; ++i) { ++ if (qc[i].type == 0) { ++ av_log(avctx, AV_LOG_DEBUG, "Probed V%d control %#x missing\n", HEVC_CTRLS_VERSION, qc[i].id); ++ return AVERROR(EINVAL); ++ } ++ if (ctrl_sizes[i] != (size_t)qc[i].elem_size) { ++ av_log(avctx, AV_LOG_DEBUG, "Probed V%d control %d size mismatch %zu != %zu\n", ++ HEVC_CTRLS_VERSION, i, ctrl_sizes[i], (size_t)qc[i].elem_size); ++ return AVERROR(EINVAL); ++ } ++ } ++ ++ fill_sps(&ctrl_sps, sps); ++ ++ if (mediabufs_set_ext_ctrl(ctx->mbufs, NULL, V4L2_CID_STATELESS_HEVC_SPS, &ctrl_sps, sizeof(ctrl_sps))) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to set initial SPS\n"); ++ return AVERROR(EINVAL); ++ } ++ ++ return 0; ++} ++ ++// Final init ++static int ++set_controls(AVCodecContext * const avctx, V4L2RequestContextHEVC * const ctx) ++{ ++ int ret; ++ ++ struct v4l2_query_ext_ctrl querys[] = { ++ { .id = V4L2_CID_STATELESS_HEVC_DECODE_MODE, }, ++ { .id = V4L2_CID_STATELESS_HEVC_START_CODE, }, ++ { .id = V4L2_CID_STATELESS_HEVC_SLICE_PARAMS, }, ++#if HEVC_CTRLS_VERSION >= 4 ++ { .id = V4L2_CID_STATELESS_HEVC_ENTRY_POINT_OFFSETS, }, ++#endif ++ }; ++ ++ struct v4l2_ext_control ctrls[] = { ++ { .id = V4L2_CID_STATELESS_HEVC_DECODE_MODE, }, ++ { .id = V4L2_CID_STATELESS_HEVC_START_CODE, }, ++ }; ++ ++ mediabufs_ctl_query_ext_ctrls(ctx->mbufs, querys, FF_ARRAY_ELEMS(querys)); ++ ++ ctx->max_slices = (!(querys[2].flags & V4L2_CTRL_FLAG_DYNAMIC_ARRAY) || ++ querys[2].nr_of_dims != 1 || querys[2].dims[0] == 0) ? ++ 1 : querys[2].dims[0]; ++ av_log(avctx, AV_LOG_DEBUG, "%s: Max slices %d\n", __func__, ctx->max_slices); ++ ++#if HEVC_CTRLS_VERSION >= 4 ++ ctx->max_offsets = (querys[3].type == 0 || querys[3].nr_of_dims != 1) ? ++ 0 : querys[3].dims[0]; ++ av_log(avctx, AV_LOG_DEBUG, "%s: Entry point offsets %d\n", __func__, ctx->max_offsets); ++#else ++ ctx->max_offsets = 0; ++#endif ++ ++ if (querys[0].default_value == V4L2_STATELESS_HEVC_DECODE_MODE_SLICE_BASED || ++ querys[0].default_value == V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED) ++ ctx->decode_mode = querys[0].default_value; ++ else if (ctrl_valid(querys + 0, V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED)) ++ ctx->decode_mode = V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED; ++ else if (ctrl_valid(querys + 0, V4L2_STATELESS_HEVC_DECODE_MODE_SLICE_BASED)) ++ ctx->decode_mode = V4L2_STATELESS_HEVC_DECODE_MODE_SLICE_BASED; ++ else { ++ av_log(avctx, AV_LOG_ERROR, "%s: unsupported decode mode\n", __func__); ++ return AVERROR(EINVAL); ++ } ++ ++ if (querys[1].default_value == V4L2_STATELESS_HEVC_START_CODE_NONE || ++ querys[1].default_value == V4L2_STATELESS_HEVC_START_CODE_ANNEX_B) ++ ctx->start_code = querys[1].default_value; ++ else if (ctrl_valid(querys + 1, V4L2_STATELESS_HEVC_START_CODE_ANNEX_B)) ++ ctx->start_code = V4L2_STATELESS_HEVC_START_CODE_ANNEX_B; ++ else if (ctrl_valid(querys + 1, V4L2_STATELESS_HEVC_START_CODE_NONE)) ++ ctx->start_code = V4L2_STATELESS_HEVC_START_CODE_NONE; ++ else { ++ av_log(avctx, AV_LOG_ERROR, "%s: unsupported start code\n", __func__); ++ return AVERROR(EINVAL); ++ } ++ ++ // If we are in slice mode & START_CODE_NONE supported then pick that ++ // as it doesn't require the slightly dodgy look backwards in our raw buffer ++ if (ctx->decode_mode == V4L2_STATELESS_HEVC_DECODE_MODE_SLICE_BASED && ++ ctrl_valid(querys + 1, V4L2_STATELESS_HEVC_START_CODE_NONE)) ++ ctx->start_code = V4L2_STATELESS_HEVC_START_CODE_NONE; ++ ++ ctrls[0].value = ctx->decode_mode; ++ ctrls[1].value = ctx->start_code; ++ ++ ret = mediabufs_ctl_set_ext_ctrls(ctx->mbufs, NULL, ctrls, FF_ARRAY_ELEMS(ctrls)); ++ return !ret ? 0 : AVERROR(-ret); ++} ++ ++static void v4l2_req_frame_free(void *opaque, uint8_t *data) ++{ ++ AVCodecContext *avctx = opaque; ++ V4L2MediaReqDescriptor * const rd = (V4L2MediaReqDescriptor*)data; ++ ++ av_log(NULL, AV_LOG_DEBUG, "%s: avctx=%p data=%p\n", __func__, avctx, data); ++ ++ frame_finish(rd); ++ ++ qent_dst_unref(&rd->qe_dst); ++ ++ av_freep(&rd->slices); ++ av_freep(&rd->slice_params); ++ av_freep(&rd->offsets); ++ ++ av_free(rd); ++} ++ ++static AVBufferRef *v4l2_req_frame_alloc(void *opaque, int size) ++{ ++ AVCodecContext *avctx = opaque; ++// V4L2RequestContextHEVC *ctx = avctx->internal->hwaccel_priv_data; ++// V4L2MediaReqDescriptor *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_req_frame_free, avctx, 0); ++ if (!ref) { ++ av_freep(&data); ++ return NULL; ++ } ++ return ref; ++} ++ ++#if 0 ++static void v4l2_req_pool_free(void *opaque) ++{ ++ av_log(NULL, AV_LOG_DEBUG, "%s: opaque=%p\n", __func__, opaque); ++} ++ ++static void v4l2_req_hwframe_ctx_free(AVHWFramesContext *hwfc) ++{ ++ av_log(NULL, AV_LOG_DEBUG, "%s: hwfc=%p pool=%p\n", __func__, hwfc, hwfc->pool); ++ ++ av_buffer_pool_uninit(&hwfc->pool); ++} ++#endif ++ ++static int frame_params(AVCodecContext *avctx, V4L2RequestContextHEVC *const ctx, AVBufferRef *hw_frames_ctx) ++{ ++ AVHWFramesContext *hwfc = (AVHWFramesContext*)hw_frames_ctx->data; ++ const struct v4l2_format *vfmt = mediabufs_dst_fmt(ctx->mbufs); ++ ++ hwfc->format = AV_PIX_FMT_DRM_PRIME; ++ hwfc->sw_format = pixel_format_from_format(vfmt); ++ if (V4L2_TYPE_IS_MULTIPLANAR(vfmt->type)) { ++ hwfc->width = vfmt->fmt.pix_mp.width; ++ hwfc->height = vfmt->fmt.pix_mp.height; ++ } else { ++ hwfc->width = vfmt->fmt.pix.width; ++ hwfc->height = vfmt->fmt.pix.height; ++ } ++#if 0 ++ hwfc->pool = av_buffer_pool_init2(sizeof(V4L2MediaReqDescriptor), avctx, v4l2_req_frame_alloc, v4l2_req_pool_free); ++ if (!hwfc->pool) ++ return AVERROR(ENOMEM); ++ ++ hwfc->free = v4l2_req_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; ++ } ++#endif ++ 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; ++} ++ ++static int alloc_frame(AVCodecContext * avctx, V4L2RequestContextHEVC *const ctx, AVFrame *frame) ++{ ++ int rv; ++ ++ frame->buf[0] = v4l2_req_frame_alloc(avctx, sizeof(V4L2MediaReqDescriptor)); ++ if (!frame->buf[0]) ++ return AVERROR(ENOMEM); ++ ++ frame->data[0] = frame->buf[0]->data; ++ ++ frame->hw_frames_ctx = av_buffer_ref(avctx->hw_frames_ctx); ++ // Cropping will be applied by hevc_refs.c:ff_hevc_set_new_ref ++ // Mirrors hwaccel path in avcodec_default_get_buffer2 ++ frame->width = avctx->coded_width; ++ frame->height = avctx->coded_height; ++ ++ if ((rv = ff_attach_decode_data(frame)) != 0) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to attach decode data to frame\n"); ++ av_frame_unref(frame); ++ return rv; ++ } ++ ++ return 0; ++} ++ ++const v4l2_req_decode_fns V(ff_v4l2_req_hevc) = { ++ .src_pix_fmt_v4l2 = V4L2_PIX_FMT_HEVC_SLICE, ++ .name = "V4L2 HEVC stateless V" STR(HEVC_CTRLS_VERSION), ++ .probe = probe, ++ .set_controls = set_controls, ++ ++ .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_params = frame_params, ++ .alloc_frame = alloc_frame, ++}; ++ +diff --git a/libavcodec/v4l2_req_media.c b/libavcodec/v4l2_req_media.c +new file mode 100644 +index 000000000000..ba9ccb31cee2 +--- /dev/null ++++ b/libavcodec/v4l2_req_media.c +@@ -0,0 +1,1835 @@ ++/* ++ * Copyright (C) 2018 Paul Kocialkowski ++ * ++ * 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, sub license, 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 (including the ++ * next paragraph) 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 NON-INFRINGEMENT. ++ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "v4l2_req_dmabufs.h" ++#include "v4l2_req_media.h" ++#include "v4l2_req_pollqueue.h" ++#include "v4l2_req_utils.h" ++#include "weak_link.h" ++ ++ ++/* floor(log2(x)) */ ++static unsigned int log2_size(size_t x) ++{ ++ unsigned int n = 0; ++ ++ if (x & ~0xffff) { ++ n += 16; ++ x >>= 16; ++ } ++ if (x & ~0xff) { ++ n += 8; ++ x >>= 8; ++ } ++ if (x & ~0xf) { ++ n += 4; ++ x >>= 4; ++ } ++ if (x & ~3) { ++ n += 2; ++ x >>= 2; ++ } ++ return (x & ~1) ? n + 1 : n; ++} ++ ++static size_t round_up_size(const size_t x) ++{ ++ /* Admit no size < 256 */ ++ const unsigned int n = x < 256 ? 8 : log2_size(x) - 1; ++ ++ return x >= (3 << n) ? 4 << n : (3 << n); ++} ++ ++struct media_request; ++ ++struct media_pool { ++ int fd; ++ sem_t sem; ++ pthread_mutex_t lock; ++ unsigned int pool_n; ++ struct media_request * pool_reqs; ++ struct media_request * free_reqs; ++ struct pollqueue * pq; ++}; ++ ++struct media_request { ++ struct media_request * next; ++ struct media_pool * mp; ++ int fd; ++ struct polltask * pt; ++}; ++ ++static inline enum v4l2_memory ++mediabufs_memory_to_v4l2(const enum mediabufs_memory m) ++{ ++ return (enum v4l2_memory)m; ++} ++ ++const char * ++mediabufs_memory_name(const enum mediabufs_memory m) ++{ ++ switch (m) { ++ case MEDIABUFS_MEMORY_UNSET: ++ return "Unset"; ++ case MEDIABUFS_MEMORY_MMAP: ++ return "MMap"; ++ case MEDIABUFS_MEMORY_USERPTR: ++ return "UserPtr"; ++ case MEDIABUFS_MEMORY_OVERLAY: ++ return "Overlay"; ++ case MEDIABUFS_MEMORY_DMABUF: ++ return "DMABuf"; ++ default: ++ break; ++ } ++ return "Unknown"; ++} ++ ++ ++static inline int do_trywait(sem_t *const sem) ++{ ++ while (sem_trywait(sem)) { ++ if (errno != EINTR) ++ return -errno; ++ } ++ return 0; ++} ++ ++static inline int do_wait(sem_t *const sem) ++{ ++ while (sem_wait(sem)) { ++ if (errno != EINTR) ++ return -errno; ++ } ++ return 0; ++} ++ ++static int request_buffers(int video_fd, unsigned int type, ++ enum mediabufs_memory memory, unsigned int buffers_count) ++{ ++ struct v4l2_requestbuffers buffers; ++ int rc; ++ ++ memset(&buffers, 0, sizeof(buffers)); ++ buffers.type = type; ++ buffers.memory = mediabufs_memory_to_v4l2(memory); ++ buffers.count = buffers_count; ++ ++ rc = ioctl(video_fd, VIDIOC_REQBUFS, &buffers); ++ if (rc < 0) { ++ rc = -errno; ++ request_log("Unable to request %d type %d buffers: %s\n", buffers_count, type, strerror(-rc)); ++ return rc; ++ } ++ ++ return 0; ++} ++ ++ ++static int set_stream(int video_fd, unsigned int type, bool enable) ++{ ++ enum v4l2_buf_type buf_type = type; ++ int rc; ++ ++ rc = ioctl(video_fd, enable ? VIDIOC_STREAMON : VIDIOC_STREAMOFF, ++ &buf_type); ++ if (rc < 0) { ++ rc = -errno; ++ request_log("Unable to %sable stream: %s\n", ++ enable ? "en" : "dis", strerror(-rc)); ++ return rc; ++ } ++ ++ return 0; ++} ++ ++ ++ ++struct media_request * media_request_get(struct media_pool * const mp) ++{ ++ struct media_request *req = NULL; ++ ++ /* Timeout handled by poll code */ ++ if (do_wait(&mp->sem)) ++ return NULL; ++ ++ pthread_mutex_lock(&mp->lock); ++ req = mp->free_reqs; ++ if (req) { ++ mp->free_reqs = req->next; ++ req->next = NULL; ++ } ++ pthread_mutex_unlock(&mp->lock); ++ return req; ++} ++ ++int media_request_fd(const struct media_request * const req) ++{ ++ return req->fd; ++} ++ ++int media_request_start(struct media_request * const req) ++{ ++ while (ioctl(req->fd, MEDIA_REQUEST_IOC_QUEUE, NULL) == -1) ++ { ++ const int err = errno; ++ if (err == EINTR) ++ continue; ++ request_log("%s: Failed to Q media: (%d) %s\n", __func__, err, strerror(err)); ++ return -err; ++ } ++ ++ pollqueue_add_task(req->pt, 2000); ++ return 0; ++} ++ ++static void media_request_done(void *v, short revents) ++{ ++ struct media_request *const req = v; ++ struct media_pool *const mp = req->mp; ++ ++ /* ** Not sure what to do about timeout */ ++ ++ if (ioctl(req->fd, MEDIA_REQUEST_IOC_REINIT, NULL) < 0) ++ request_log("Unable to reinit media request: %s\n", ++ strerror(errno)); ++ ++ pthread_mutex_lock(&mp->lock); ++ req->next = mp->free_reqs; ++ mp->free_reqs = req; ++ pthread_mutex_unlock(&mp->lock); ++ sem_post(&mp->sem); ++} ++ ++int media_request_abort(struct media_request ** const preq) ++{ ++ struct media_request * const req = *preq; ++ ++ if (req == NULL) ++ return 0; ++ *preq = NULL; ++ ++ media_request_done(req, 0); ++ return 0; ++} ++ ++static void free_req_pool(struct media_request * const pool, const unsigned int n) ++{ ++ unsigned int i; ++ for (i = 0; i != n; ++i) { ++ struct media_request * const req = pool + i; ++ if (req->pt) ++ polltask_delete(&req->pt); ++ if (req->fd != -1) ++ close(req->fd); ++ } ++ free(pool); ++} ++ ++struct media_pool * media_pool_new(const char * const media_path, ++ struct pollqueue * const pq, ++ const unsigned int n) ++{ ++ struct media_pool * const mp = calloc(1, sizeof(*mp)); ++ unsigned int i; ++ ++ if (!mp) ++ goto fail0; ++ ++ mp->pq = pq; ++ pthread_mutex_init(&mp->lock, NULL); ++ mp->fd = open(media_path, O_RDWR | O_NONBLOCK); ++ if (mp->fd == -1) { ++ request_log("Failed to open '%s': %s\n", media_path, strerror(errno)); ++ goto fail1; ++ } ++ ++ if ((mp->pool_reqs = calloc(n, sizeof(*mp->pool_reqs))) == NULL) ++ goto fail3; ++ mp->pool_n = n; ++ for (i = 0; i != n; ++i) { ++ mp->pool_reqs[i].mp = mp; ++ mp->pool_reqs[i].fd = -1; ++ } ++ ++ for (i = 0; i != n; ++i) { ++ struct media_request * const req = mp->pool_reqs + i; ++ ++ if (ioctl(mp->fd, MEDIA_IOC_REQUEST_ALLOC, &req->fd) == -1) { ++ request_log("Failed to alloc request %d: %s\n", i, strerror(errno)); ++ goto fail4; ++ } ++ ++ req->pt = polltask_new(pq, req->fd, POLLPRI, media_request_done, req); ++ if (!req->pt) ++ goto fail4; ++ ++ req->next = mp->free_reqs, ++ mp->free_reqs = req; ++ } ++ ++ sem_init(&mp->sem, 0, n); ++ ++ return mp; ++ ++fail4: ++ free_req_pool(mp->pool_reqs, mp->pool_n); ++fail3: ++ close(mp->fd); ++ pthread_mutex_destroy(&mp->lock); ++fail1: ++ free(mp); ++fail0: ++ return NULL; ++} ++ ++void media_pool_delete(struct media_pool ** pMp) ++{ ++ struct media_pool * const mp = *pMp; ++ ++ if (!mp) ++ return; ++ *pMp = NULL; ++ ++ free_req_pool(mp->pool_reqs, mp->pool_n); ++ close(mp->fd); ++ sem_destroy(&mp->sem); ++ pthread_mutex_destroy(&mp->lock); ++ free(mp); ++} ++ ++ ++#define INDEX_UNSET (~(uint32_t)0) ++ ++enum qent_status { ++ QENT_NEW = 0, // Initial state - shouldn't last ++ QENT_FREE, // On free chain ++ QENT_PENDING, // User has ent ++ QENT_WAITING, // On inuse ++ QENT_DONE, // Frame rx ++ QENT_ERROR, // Error ++ QENT_IMPORT ++}; ++ ++struct qent_base { ++ atomic_int ref_count; ++ struct qent_base *next; ++ struct qent_base *prev; ++ enum qent_status status; ++ enum mediabufs_memory memtype; ++ uint32_t index; ++ struct dmabuf_h *dh[VIDEO_MAX_PLANES]; ++ struct timeval timestamp; ++}; ++ ++struct qent_src { ++ struct qent_base base; ++ int fixed_size; ++}; ++ ++struct qent_dst { ++ struct qent_base base; ++ bool waiting; ++ pthread_mutex_t lock; ++ pthread_cond_t cond; ++ struct ff_weak_link_client * mbc_wl; ++}; ++ ++struct qe_list_head { ++ struct qent_base *head; ++ struct qent_base *tail; ++}; ++ ++struct buf_pool { ++ enum mediabufs_memory memtype; ++ pthread_mutex_t lock; ++ pthread_cond_t cond; ++ struct qe_list_head free; ++ struct qe_list_head inuse; ++}; ++ ++ ++static inline struct qent_dst *base_to_dst(struct qent_base *be) ++{ ++ return (struct qent_dst *)be; ++} ++ ++static inline struct qent_src *base_to_src(struct qent_base *be) ++{ ++ return (struct qent_src *)be; ++} ++ ++ ++#define QENT_BASE_INITIALIZER(mtype) {\ ++ .ref_count = ATOMIC_VAR_INIT(0),\ ++ .status = QENT_NEW,\ ++ .memtype = (mtype),\ ++ .index = INDEX_UNSET\ ++} ++ ++static void qe_base_uninit(struct qent_base *const be) ++{ ++ unsigned int i; ++ for (i = 0; i != VIDEO_MAX_PLANES; ++i) { ++ dmabuf_free(be->dh[i]); ++ be->dh[i] = NULL; ++ } ++} ++ ++static void qe_src_free(struct qent_src *const be_src) ++{ ++ if (!be_src) ++ return; ++ qe_base_uninit(&be_src->base); ++ free(be_src); ++} ++ ++static struct qent_src * qe_src_new(enum mediabufs_memory mtype) ++{ ++ struct qent_src *const be_src = malloc(sizeof(*be_src)); ++ if (!be_src) ++ return NULL; ++ *be_src = (struct qent_src){ ++ .base = QENT_BASE_INITIALIZER(mtype) ++ }; ++ return be_src; ++} ++ ++static void qe_dst_free(struct qent_dst *const be_dst) ++{ ++ if (!be_dst) ++ return; ++ ++ ff_weak_link_unref(&be_dst->mbc_wl); ++ pthread_cond_destroy(&be_dst->cond); ++ pthread_mutex_destroy(&be_dst->lock); ++ qe_base_uninit(&be_dst->base); ++ free(be_dst); ++} ++ ++static struct qent_dst* qe_dst_new(struct ff_weak_link_master * const wl, const enum mediabufs_memory memtype) ++{ ++ struct qent_dst *const be_dst = malloc(sizeof(*be_dst)); ++ if (!be_dst) ++ return NULL; ++ *be_dst = (struct qent_dst){ ++ .base = QENT_BASE_INITIALIZER(memtype), ++ .lock = PTHREAD_MUTEX_INITIALIZER, ++ .cond = PTHREAD_COND_INITIALIZER, ++ .mbc_wl = ff_weak_link_ref(wl) ++ }; ++ return be_dst; ++} ++ ++static void ql_add_tail(struct qe_list_head * const ql, struct qent_base * be) ++{ ++ if (ql->tail) ++ ql->tail->next = be; ++ else ++ ql->head = be; ++ be->prev = ql->tail; ++ be->next = NULL; ++ ql->tail = be; ++} ++ ++static struct qent_base * ql_extract(struct qe_list_head * const ql, struct qent_base * be) ++{ ++ if (!be) ++ return NULL; ++ ++ if (be->next) ++ be->next->prev = be->prev; ++ else ++ ql->tail = be->prev; ++ if (be->prev) ++ be->prev->next = be->next; ++ else ++ ql->head = be->next; ++ be->next = NULL; ++ be->prev = NULL; ++ return be; ++} ++ ++ ++static void bq_put_free(struct buf_pool *const bp, struct qent_base * be) ++{ ++ ql_add_tail(&bp->free, be); ++} ++ ++static struct qent_base * bq_get_free(struct buf_pool *const bp) ++{ ++ return ql_extract(&bp->free, bp->free.head); ++} ++ ++static struct qent_base * bq_extract_inuse(struct buf_pool *const bp, struct qent_base *const be) ++{ ++ return ql_extract(&bp->inuse, be); ++} ++ ++static struct qent_base * bq_get_inuse(struct buf_pool *const bp) ++{ ++ return ql_extract(&bp->inuse, bp->inuse.head); ++} ++ ++static void bq_free_all_free_src(struct buf_pool *const bp) ++{ ++ struct qent_base *be; ++ while ((be = bq_get_free(bp)) != NULL) ++ qe_src_free(base_to_src(be)); ++} ++ ++static void bq_free_all_inuse_src(struct buf_pool *const bp) ++{ ++ struct qent_base *be; ++ while ((be = bq_get_inuse(bp)) != NULL) ++ qe_src_free(base_to_src(be)); ++} ++ ++static void bq_free_all_free_dst(struct buf_pool *const bp) ++{ ++ struct qent_base *be; ++ while ((be = bq_get_free(bp)) != NULL) ++ qe_dst_free(base_to_dst(be)); ++} ++ ++static void queue_put_free(struct buf_pool *const bp, struct qent_base *be) ++{ ++ unsigned int i; ++ ++ pthread_mutex_lock(&bp->lock); ++ /* Clear out state vars */ ++ be->timestamp.tv_sec = 0; ++ be->timestamp.tv_usec = 0; ++ be->status = QENT_FREE; ++ for (i = 0; i < VIDEO_MAX_PLANES && be->dh[i]; ++i) ++ dmabuf_len_set(be->dh[i], 0); ++ bq_put_free(bp, be); ++ pthread_cond_broadcast(&bp->cond); ++ pthread_mutex_unlock(&bp->lock); ++} ++ ++static bool queue_is_inuse(const struct buf_pool *const bp) ++{ ++ return bp->inuse.tail != NULL; ++} ++ ++static void queue_put_inuse(struct buf_pool *const bp, struct qent_base *be) ++{ ++ if (!be) ++ return; ++ pthread_mutex_lock(&bp->lock); ++ ql_add_tail(&bp->inuse, be); ++ be->status = QENT_WAITING; ++ pthread_mutex_unlock(&bp->lock); ++} ++ ++static struct qent_base *queue_get_free(struct buf_pool *const bp) ++{ ++ struct qent_base *buf; ++ ++ pthread_mutex_lock(&bp->lock); ++ while ((buf = bq_get_free(bp)) == NULL && pthread_cond_wait(&bp->cond, &bp->lock) == 0) ++ /* Loop */; ++ pthread_mutex_unlock(&bp->lock); ++ return buf; ++} ++ ++static struct qent_base *queue_tryget_free(struct buf_pool *const bp) ++{ ++ struct qent_base *buf; ++ ++ pthread_mutex_lock(&bp->lock); ++ buf = bq_get_free(bp); ++ pthread_mutex_unlock(&bp->lock); ++ return buf; ++} ++ ++static struct qent_base * queue_find_extract_index(struct buf_pool *const bp, const unsigned int index) ++{ ++ struct qent_base *be; ++ ++ pthread_mutex_lock(&bp->lock); ++ /* Expect 1st in Q, but allow anywhere */ ++ for (be = bp->inuse.head; be; be = be->next) { ++ if (be->index == index) { ++ bq_extract_inuse(bp, be); ++ break; ++ } ++ } ++ pthread_mutex_unlock(&bp->lock); ++ ++ return be; ++} ++ ++static void queue_delete(struct buf_pool *const bp) ++{ ++ pthread_cond_destroy(&bp->cond); ++ pthread_mutex_destroy(&bp->lock); ++ free(bp); ++} ++ ++static struct buf_pool* queue_new(const int vfd) ++{ ++ struct buf_pool *bp = calloc(1, sizeof(*bp)); ++ if (!bp) ++ return NULL; ++ pthread_mutex_init(&bp->lock, NULL); ++ pthread_cond_init(&bp->cond, NULL); ++ return bp; ++} ++ ++ ++struct mediabufs_ctl { ++ atomic_int ref_count; /* 0 is single ref for easier atomics */ ++ void * dc; ++ int vfd; ++ bool stream_on; ++ bool polling; ++ bool dst_fixed; // Dst Q is fixed size ++ pthread_mutex_t lock; ++ struct buf_pool * src; ++ struct buf_pool * dst; ++ struct polltask * pt; ++ struct pollqueue * pq; ++ struct ff_weak_link_master * this_wlm; ++ ++ enum mediabufs_memory src_memtype; ++ enum mediabufs_memory dst_memtype; ++ struct v4l2_format src_fmt; ++ struct v4l2_format dst_fmt; ++ struct v4l2_capability capability; ++}; ++ ++static int qe_v4l2_queue(struct qent_base *const be, ++ const int vfd, struct media_request *const mreq, ++ const struct v4l2_format *const fmt, ++ const bool is_dst, const bool hold_flag) ++{ ++ struct v4l2_buffer buffer = { ++ .type = fmt->type, ++ .memory = mediabufs_memory_to_v4l2(be->memtype), ++ .index = be->index ++ }; ++ struct v4l2_plane planes[VIDEO_MAX_PLANES] = {{0}}; ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(fmt->type)) { ++ unsigned int i; ++ for (i = 0; i < VIDEO_MAX_PLANES && be->dh[i]; ++i) { ++ if (is_dst) ++ dmabuf_len_set(be->dh[i], 0); ++ ++ /* *** Really need a pixdesc rather than a format so we can fill in data_offset */ ++ planes[i].length = dmabuf_size(be->dh[i]); ++ planes[i].bytesused = dmabuf_len(be->dh[i]); ++ if (be->memtype == MEDIABUFS_MEMORY_DMABUF) ++ planes[i].m.fd = dmabuf_fd(be->dh[i]); ++ else ++ planes[i].m.mem_offset = 0; ++ } ++ buffer.m.planes = planes; ++ buffer.length = i; ++ } ++ else { ++ if (is_dst) ++ dmabuf_len_set(be->dh[0], 0); ++ ++ buffer.bytesused = dmabuf_len(be->dh[0]); ++ buffer.length = dmabuf_size(be->dh[0]); ++ if (be->memtype == MEDIABUFS_MEMORY_DMABUF) ++ buffer.m.fd = dmabuf_fd(be->dh[0]); ++ else ++ buffer.m.offset = 0; ++ } ++ ++ if (!is_dst && mreq) { ++ buffer.flags |= V4L2_BUF_FLAG_REQUEST_FD; ++ buffer.request_fd = media_request_fd(mreq); ++ if (hold_flag) ++ buffer.flags |= V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF; ++ } ++ ++ if (is_dst) ++ be->timestamp = (struct timeval){0,0}; ++ ++ buffer.timestamp = be->timestamp; ++ ++ while (ioctl(vfd, VIDIOC_QBUF, &buffer)) { ++ const int err = errno; ++ if (err != EINTR) { ++ request_log("%s: Failed to Q buffer: err=%d (%s)\n", __func__, err, strerror(err)); ++ return -err; ++ } ++ } ++ return 0; ++} ++ ++static struct qent_base * qe_dequeue(struct buf_pool *const bp, ++ const int vfd, ++ const struct v4l2_format * const f) ++{ ++ struct qent_base *be; ++ int rc; ++ const bool mp = V4L2_TYPE_IS_MULTIPLANAR(f->type); ++ struct v4l2_plane planes[VIDEO_MAX_PLANES] = {{0}}; ++ struct v4l2_buffer buffer = { ++ .type = f->type, ++ .memory = mediabufs_memory_to_v4l2(bp->memtype) ++ }; ++ if (mp) { ++ buffer.length = f->fmt.pix_mp.num_planes; ++ buffer.m.planes = planes; ++ } ++ ++ while ((rc = ioctl(vfd, VIDIOC_DQBUF, &buffer)) != 0 && ++ errno == EINTR) ++ /* Loop */; ++ if (rc) { ++ request_log("Error DQing buffer type %d: %s\n", f->type, strerror(errno)); ++ return NULL; ++ } ++ ++ be = queue_find_extract_index(bp, buffer.index); ++ if (!be) { ++ request_log("Failed to find index %d in Q\n", buffer.index); ++ return NULL; ++ } ++ ++ if (mp) { ++ unsigned int i; ++ for (i = 0; i != buffer.length; ++i) ++ dmabuf_len_set(be->dh[i], V4L2_TYPE_IS_CAPTURE(f->type) ? planes[i].bytesused : 0); ++ } ++ else ++ dmabuf_len_set(be->dh[0], V4L2_TYPE_IS_CAPTURE(f->type) ? buffer.length : 0); ++ ++ be->timestamp = buffer.timestamp; ++ be->status = (buffer.flags & V4L2_BUF_FLAG_ERROR) ? QENT_ERROR : QENT_DONE; ++ return be; ++} ++ ++static void qe_dst_done(struct qent_dst * dst_be) ++{ ++ pthread_mutex_lock(&dst_be->lock); ++ dst_be->waiting = false; ++ pthread_cond_broadcast(&dst_be->cond); ++ pthread_mutex_unlock(&dst_be->lock); ++ ++ qent_dst_unref(&dst_be); ++} ++ ++static bool qe_dst_waiting(struct qent_dst *const dst_be) ++{ ++ bool waiting; ++ pthread_mutex_lock(&dst_be->lock); ++ waiting = dst_be->waiting; ++ dst_be->waiting = true; ++ pthread_mutex_unlock(&dst_be->lock); ++ return waiting; ++} ++ ++ ++static bool mediabufs_wants_poll(const struct mediabufs_ctl *const mbc) ++{ ++ return queue_is_inuse(mbc->src) || queue_is_inuse(mbc->dst); ++} ++ ++static void mediabufs_poll_cb(void * v, short revents) ++{ ++ struct mediabufs_ctl *mbc = v; ++ struct qent_src *src_be = NULL; ++ struct qent_dst *dst_be = NULL; ++ ++ if (!revents) ++ request_err(mbc->dc, "%s: Timeout\n", __func__); ++ ++ pthread_mutex_lock(&mbc->lock); ++ mbc->polling = false; ++ ++ if ((revents & POLLOUT) != 0) ++ src_be = base_to_src(qe_dequeue(mbc->src, mbc->vfd, &mbc->src_fmt)); ++ if ((revents & POLLIN) != 0) ++ dst_be = base_to_dst(qe_dequeue(mbc->dst, mbc->vfd, &mbc->dst_fmt)); ++ ++ /* Reschedule */ ++ if (mediabufs_wants_poll(mbc)) { ++ mbc->polling = true; ++ pollqueue_add_task(mbc->pt, 2000); ++ } ++ pthread_mutex_unlock(&mbc->lock); ++ ++ if (src_be) ++ queue_put_free(mbc->src, &src_be->base); ++ if (dst_be) ++ qe_dst_done(dst_be); ++} ++ ++int qent_src_params_set(struct qent_src *const be_src, const struct timeval * timestamp) ++{ ++ struct qent_base *const be = &be_src->base; ++ ++ be->timestamp = *timestamp; ++ return 0; ++} ++ ++struct timeval qent_dst_timestamp_get(const struct qent_dst *const be_dst) ++{ ++ return be_dst->base.timestamp; ++} ++ ++static int qent_base_realloc(struct qent_base *const be, const size_t len, struct dmabufs_ctl * dbsc) ++{ ++ if (!be->dh[0] || len > dmabuf_size(be->dh[0])) { ++ size_t newsize = round_up_size(len); ++ request_debug(NULL, "%s: Overrun %zd > %zd; trying %zd\n", __func__, len, dmabuf_size(be->dh[0]), newsize); ++ if (!dbsc) { ++ request_log("%s: No dmbabuf_ctrl for realloc\n", __func__); ++ return -ENOMEM; ++ } ++ if ((be->dh[0] = dmabuf_realloc(dbsc, be->dh[0], newsize)) == NULL) { ++ request_log("%s: Realloc %zd failed\n", __func__, newsize); ++ return -ENOMEM; ++ } ++ } ++ return 0; ++} ++ ++int qent_src_alloc(struct qent_src *const be_src, const size_t len, struct dmabufs_ctl * dbsc) ++{ ++ struct qent_base *const be = &be_src->base; ++ return qent_base_realloc(be, len, dbsc); ++} ++ ++ ++int qent_src_data_copy(struct qent_src *const be_src, const size_t offset, const void *const src, const size_t len, struct dmabufs_ctl * dbsc) ++{ ++ void * dst; ++ struct qent_base *const be = &be_src->base; ++ int rv; ++ ++ // Realloc doesn't copy so don't alloc if offset != 0 ++ if ((rv = qent_base_realloc(be, offset + len, ++ be_src->fixed_size || offset ? NULL : dbsc)) != 0) ++ return rv; ++ ++ dmabuf_write_start(be->dh[0]); ++ dst = dmabuf_map(be->dh[0]); ++ if (!dst) ++ return -1; ++ memcpy((char*)dst + offset, src, len); ++ dmabuf_len_set(be->dh[0], len); ++ dmabuf_write_end(be->dh[0]); ++ return 0; ++} ++ ++const struct dmabuf_h * qent_dst_dmabuf(const struct qent_dst *const be_dst, unsigned int plane) ++{ ++ const struct qent_base *const be = &be_dst->base; ++ ++ return (plane >= sizeof(be->dh)/sizeof(be->dh[0])) ? NULL : be->dh[plane]; ++} ++ ++int qent_dst_dup_fd(const struct qent_dst *const be_dst, unsigned int plane) ++{ ++ return dup(dmabuf_fd(qent_dst_dmabuf(be_dst, plane))); ++} ++ ++MediaBufsStatus mediabufs_start_request(struct mediabufs_ctl *const mbc, ++ struct media_request **const pmreq, ++ struct qent_src **const psrc_be, ++ struct qent_dst *const dst_be, ++ const bool is_final) ++{ ++ struct media_request * mreq = *pmreq; ++ struct qent_src *const src_be = *psrc_be; ++ ++ // Req & src are always both "consumed" ++ *pmreq = NULL; ++ *psrc_be = NULL; ++ ++ pthread_mutex_lock(&mbc->lock); ++ ++ if (!src_be) ++ goto fail1; ++ ++ if (dst_be) { ++ if (qe_dst_waiting(dst_be)) { ++ request_info(mbc->dc, "Request buffer already waiting on start\n"); ++ goto fail1; ++ } ++ dst_be->base.timestamp = (struct timeval){0,0}; ++ if (qe_v4l2_queue(&dst_be->base, mbc->vfd, NULL, &mbc->dst_fmt, true, false)) ++ goto fail1; ++ ++ qent_dst_ref(dst_be); ++ queue_put_inuse(mbc->dst, &dst_be->base); ++ } ++ ++ if (qe_v4l2_queue(&src_be->base, mbc->vfd, mreq, &mbc->src_fmt, false, !is_final)) ++ goto fail1; ++ queue_put_inuse(mbc->src, &src_be->base); ++ ++ if (!mbc->polling && mediabufs_wants_poll(mbc)) { ++ mbc->polling = true; ++ pollqueue_add_task(mbc->pt, 2000); ++ } ++ pthread_mutex_unlock(&mbc->lock); ++ ++ if (media_request_start(mreq)) ++ return MEDIABUFS_ERROR_OPERATION_FAILED; ++ ++ return MEDIABUFS_STATUS_SUCCESS; ++ ++fail1: ++ media_request_abort(&mreq); ++ if (src_be) ++ queue_put_free(mbc->src, &src_be->base); ++ ++// *** TODO: If src Q fails this doesnt unwind properly - separate dst Q from src Q ++ if (dst_be) { ++ dst_be->base.status = QENT_ERROR; ++ qe_dst_done(dst_be); ++ } ++ pthread_mutex_unlock(&mbc->lock); ++ return MEDIABUFS_ERROR_OPERATION_FAILED; ++} ++ ++ ++static int qe_alloc_from_fmt(struct qent_base *const be, ++ struct dmabufs_ctl *const dbsc, ++ const struct v4l2_format *const fmt) ++{ ++ if (V4L2_TYPE_IS_MULTIPLANAR(fmt->type)) { ++ unsigned int i; ++ for (i = 0; i != fmt->fmt.pix_mp.num_planes; ++i) { ++ be->dh[i] = dmabuf_realloc(dbsc, be->dh[i], ++ fmt->fmt.pix_mp.plane_fmt[i].sizeimage); ++ /* On failure tidy up and die */ ++ if (!be->dh[i]) { ++ while (i--) { ++ dmabuf_free(be->dh[i]); ++ be->dh[i] = NULL; ++ } ++ return -1; ++ } ++ } ++ } ++ else { ++// be->dh[0] = dmabuf_alloc(dbsc, fmt->fmt.pix.sizeimage); ++ size_t size = fmt->fmt.pix.sizeimage; ++ be->dh[0] = dmabuf_realloc(dbsc, be->dh[0], size); ++ if (!be->dh[0]) ++ return -1; ++ } ++ return 0; ++} ++ ++static MediaBufsStatus fmt_set(struct v4l2_format *const fmt, const int fd, ++ const enum v4l2_buf_type buftype, ++ uint32_t pixfmt, ++ const unsigned int width, const unsigned int height, ++ const size_t bufsize) ++{ ++ *fmt = (struct v4l2_format){.type = buftype}; ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(buftype)) { ++ fmt->fmt.pix_mp.width = width; ++ fmt->fmt.pix_mp.height = height; ++ fmt->fmt.pix_mp.pixelformat = pixfmt; ++ if (bufsize) { ++ fmt->fmt.pix_mp.num_planes = 1; ++ fmt->fmt.pix_mp.plane_fmt[0].sizeimage = bufsize; ++ } ++ } ++ else { ++ fmt->fmt.pix.width = width; ++ fmt->fmt.pix.height = height; ++ fmt->fmt.pix.pixelformat = pixfmt; ++ fmt->fmt.pix.sizeimage = bufsize; ++ } ++ ++ while (ioctl(fd, VIDIOC_S_FMT, fmt)) ++ if (errno != EINTR) ++ return MEDIABUFS_ERROR_OPERATION_FAILED; ++ ++ // Treat anything where we don't get at least what we asked for as a fail ++ if (V4L2_TYPE_IS_MULTIPLANAR(buftype)) { ++ if (fmt->fmt.pix_mp.width < width || ++ fmt->fmt.pix_mp.height < height || ++ fmt->fmt.pix_mp.pixelformat != pixfmt) { ++ return MEDIABUFS_ERROR_UNSUPPORTED_BUFFERTYPE; ++ } ++ } ++ else { ++ if (fmt->fmt.pix.width < width || ++ fmt->fmt.pix.height < height || ++ fmt->fmt.pix.pixelformat != pixfmt) { ++ return MEDIABUFS_ERROR_UNSUPPORTED_BUFFERTYPE; ++ } ++ } ++ ++ return MEDIABUFS_STATUS_SUCCESS; ++} ++ ++static MediaBufsStatus find_fmt_flags(struct v4l2_format *const fmt, ++ const int fd, ++ const unsigned int type_v4l2, ++ const uint32_t flags_must, ++ const uint32_t flags_not, ++ const unsigned int width, ++ const unsigned int height, ++ mediabufs_dst_fmt_accept_fn *const accept_fn, ++ void *const accept_v) ++{ ++ unsigned int i; ++ ++ for (i = 0;; ++i) { ++ struct v4l2_fmtdesc fmtdesc = { ++ .index = i, ++ .type = type_v4l2 ++ }; ++ while (ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc)) { ++ if (errno != EINTR) ++ return MEDIABUFS_ERROR_UNSUPPORTED_BUFFERTYPE; ++ } ++ if ((fmtdesc.flags & flags_must) != flags_must || ++ (fmtdesc.flags & flags_not)) ++ continue; ++ if (!accept_fn(accept_v, &fmtdesc)) ++ continue; ++ ++ if (fmt_set(fmt, fd, fmtdesc.type, fmtdesc.pixelformat, ++ width, height, 0) == MEDIABUFS_STATUS_SUCCESS) ++ return MEDIABUFS_STATUS_SUCCESS; ++ } ++ return 0; ++} ++ ++ ++/* Wait for qent done */ ++ ++MediaBufsStatus qent_dst_wait(struct qent_dst *const be_dst) ++{ ++ struct qent_base *const be = &be_dst->base; ++ enum qent_status estat; ++ ++ pthread_mutex_lock(&be_dst->lock); ++ while (be_dst->waiting && ++ !pthread_cond_wait(&be_dst->cond, &be_dst->lock)) ++ /* Loop */; ++ estat = be->status; ++ pthread_mutex_unlock(&be_dst->lock); ++ ++ return estat == QENT_DONE ? MEDIABUFS_STATUS_SUCCESS : ++ estat == QENT_ERROR ? MEDIABUFS_ERROR_DECODING_ERROR : ++ MEDIABUFS_ERROR_OPERATION_FAILED; ++} ++ ++const uint8_t * qent_dst_data(struct qent_dst *const be_dst, unsigned int buf_no) ++{ ++ struct qent_base *const be = &be_dst->base; ++ return dmabuf_map(be->dh[buf_no]); ++} ++ ++MediaBufsStatus qent_dst_read_start(struct qent_dst *const be_dst) ++{ ++ struct qent_base *const be = &be_dst->base; ++ unsigned int i; ++ for (i = 0; i != VIDEO_MAX_PLANES && be->dh[i]; ++i) { ++ if (dmabuf_read_start(be->dh[i])) { ++ while (i--) ++ dmabuf_read_end(be->dh[i]); ++ return MEDIABUFS_ERROR_ALLOCATION_FAILED; ++ } ++ } ++ return MEDIABUFS_STATUS_SUCCESS; ++} ++ ++MediaBufsStatus qent_dst_read_stop(struct qent_dst *const be_dst) ++{ ++ struct qent_base *const be = &be_dst->base; ++ unsigned int i; ++ MediaBufsStatus status = MEDIABUFS_STATUS_SUCCESS; ++ ++ for (i = 0; i != VIDEO_MAX_PLANES && be->dh[i]; ++i) { ++ if (dmabuf_read_end(be->dh[i])) ++ status = MEDIABUFS_ERROR_OPERATION_FAILED; ++ } ++ return status; ++} ++ ++struct qent_dst * qent_dst_ref(struct qent_dst * const be_dst) ++{ ++ if (be_dst) ++ atomic_fetch_add(&be_dst->base.ref_count, 1); ++ return be_dst; ++} ++ ++void qent_dst_unref(struct qent_dst ** const pbe_dst) ++{ ++ struct qent_dst * const be_dst = *pbe_dst; ++ struct mediabufs_ctl * mbc; ++ if (!be_dst) ++ return; ++ *pbe_dst = NULL; ++ ++ if (atomic_fetch_sub(&be_dst->base.ref_count, 1) != 0) ++ return; ++ ++ if ((mbc = ff_weak_link_lock(&be_dst->mbc_wl)) != NULL) { ++ queue_put_free(mbc->dst, &be_dst->base); ++ ff_weak_link_unlock(be_dst->mbc_wl); ++ } ++ else { ++ qe_dst_free(be_dst); ++ } ++} ++ ++MediaBufsStatus qent_dst_import_fd(struct qent_dst *const be_dst, ++ unsigned int plane, ++ int fd, size_t size) ++{ ++ struct qent_base *const be = &be_dst->base; ++ struct dmabuf_h * dh; ++ ++ if (be->status != QENT_IMPORT || be->dh[plane]) ++ return MEDIABUFS_ERROR_OPERATION_FAILED; ++ ++ dh = dmabuf_import(fd, size); ++ if (!dh) ++ return MEDIABUFS_ERROR_ALLOCATION_FAILED; ++ ++ be->dh[plane] = dh; ++ return MEDIABUFS_STATUS_SUCCESS; ++} ++ ++// Returns noof buffers created, -ve for error ++static int create_dst_bufs(struct mediabufs_ctl *const mbc, unsigned int n, struct qent_dst * const qes[]) ++{ ++ unsigned int i; ++ ++ struct v4l2_create_buffers cbuf = { ++ .count = n, ++ .memory = mediabufs_memory_to_v4l2(mbc->dst->memtype), ++ .format = mbc->dst_fmt, ++ }; ++ ++ while (ioctl(mbc->vfd, VIDIOC_CREATE_BUFS, &cbuf)) { ++ const int err = -errno; ++ if (err != EINTR) { ++ request_err(mbc->dc, "%s: Failed to create V4L2 buffer\n", __func__); ++ return -err; ++ } ++ } ++ ++ if (cbuf.count != n) ++ request_warn(mbc->dc, "%s: Created %d of %d V4L2 buffers requested\n", __func__, cbuf.count, n); ++ ++ for (i = 0; i != cbuf.count; ++i) ++ qes[i]->base.index = cbuf.index + i; ++ ++ return cbuf.count; ++} ++ ++static void queue_dst_wait_no_waiting(struct buf_pool *const bp) ++{ ++ // This is O(n^2), but n is not very big & shoudl only happen on shutdown ++ // so it isn't worth adding any processing to anything else to make this ++ // more efficient ++ for (;;) { ++ struct qent_base *be; ++ struct qent_dst *be_dst = NULL; ++ ++ pthread_mutex_lock(&bp->lock); ++ for (be = bp->inuse.head; be != NULL; be = be->next) { ++ be_dst = base_to_dst(be); ++ if (be_dst->waiting) { ++ qent_dst_ref(be_dst); ++ break; ++ } ++ } ++ pthread_mutex_unlock(&bp->lock); ++ ++ if (be == NULL) ++ break; ++ ++ qent_dst_wait(be_dst); ++ } ++} ++ ++static MediaBufsStatus ++qe_import_from_buf(struct mediabufs_ctl *const mbc, struct qent_base * const be, const struct v4l2_format *const fmt, ++ const unsigned int n, const bool x_dmabuf) ++{ ++ struct v4l2_buffer buf = { ++ .index = n, ++ .type = fmt->type, ++ }; ++ struct v4l2_plane planes[VIDEO_MAX_PLANES]; ++ int ret; ++ ++ if (be->dh[0]) ++ return 0; ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(fmt->type)) { ++ memset(planes, 0, sizeof(planes)); ++ buf.m.planes = planes; ++ buf.length = VIDEO_MAX_PLANES; ++ } ++ ++ if ((ret = ioctl(mbc->vfd, VIDIOC_QUERYBUF, &buf)) != 0) { ++ request_err(mbc->dc, "VIDIOC_QUERYBUF failed"); ++ return MEDIABUFS_ERROR_OPERATION_FAILED; ++ } ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(fmt->type)) ++ { ++ unsigned int i; ++ for (i = 0; i != buf.length; ++i) { ++ if (x_dmabuf) { ++ struct v4l2_exportbuffer xbuf = { ++ .type = buf.type, ++ .index = buf.index, ++ .plane = i, ++ .flags = O_RDWR, // *** Arguably O_RDONLY would be fine ++ }; ++ if (ioctl(mbc->vfd, VIDIOC_EXPBUF, &xbuf) == 0) { ++ be->dh[i] = dmabuf_import(xbuf.fd, planes[i].length); ++ close(xbuf.fd); // dmabuf_import dups the fd so close this one ++ } ++ } ++ else { ++ be->dh[i] = dmabuf_import_mmap( ++ mmap(NULL, planes[i].length, ++ PROT_READ | PROT_WRITE, ++ MAP_SHARED | MAP_POPULATE, ++ mbc->vfd, planes[i].m.mem_offset), ++ planes[i].length); ++ } ++ /* On failure tidy up and die */ ++ if (!be->dh[i]) { ++ while (i--) { ++ dmabuf_free(be->dh[i]); ++ be->dh[i] = NULL; ++ } ++ return MEDIABUFS_ERROR_OPERATION_FAILED; ++ } ++ } ++ } ++ else ++ { ++ if (x_dmabuf) { ++ struct v4l2_exportbuffer xbuf = { ++ .type = buf.type, ++ .index = buf.index, ++ .flags = O_RDWR, // *** Arguably O_RDONLY would be fine ++ }; ++ if (ioctl(mbc->vfd, VIDIOC_EXPBUF, &xbuf) == 0) ++ be->dh[0] = dmabuf_import(xbuf.fd, buf.length); ++ } ++ else { ++ be->dh[0] = dmabuf_import_mmap( ++ mmap(NULL, buf.length, ++ PROT_READ | PROT_WRITE, ++ MAP_SHARED | MAP_POPULATE, ++ mbc->vfd, buf.m.offset), ++ buf.length); ++ } ++ /* On failure tidy up and die */ ++ if (!be->dh[0]) { ++ return MEDIABUFS_ERROR_OPERATION_FAILED; ++ } ++ } ++ ++ return 0; ++} ++ ++struct qent_dst* mediabufs_dst_qent_alloc(struct mediabufs_ctl *const mbc, struct dmabufs_ctl *const dbsc) ++{ ++ struct qent_dst * be_dst; ++ ++ if (mbc == NULL) { ++ be_dst = qe_dst_new(NULL, MEDIABUFS_MEMORY_DMABUF); ++ if (be_dst) ++ be_dst->base.status = QENT_IMPORT; ++ return be_dst; ++ } ++ ++ if (mbc->dst_fixed) { ++ be_dst = base_to_dst(queue_get_free(mbc->dst)); ++ if (!be_dst) ++ return NULL; ++ } ++ else { ++ be_dst = base_to_dst(queue_tryget_free(mbc->dst)); ++ if (!be_dst) { ++ be_dst = qe_dst_new(mbc->this_wlm, mbc->dst->memtype); ++ if (!be_dst) ++ return NULL; ++ ++ if (create_dst_bufs(mbc, 1, &be_dst) != 1) { ++ qe_dst_free(be_dst); ++ // We can't extend any more - try again but wait ++ mbc->dst_fixed = true; ++ return mediabufs_dst_qent_alloc(mbc, dbsc); ++ } ++ } ++ } ++ ++ if (mbc->dst->memtype == MEDIABUFS_MEMORY_MMAP) { ++ if (qe_import_from_buf(mbc, &be_dst->base, &mbc->dst_fmt, be_dst->base.index, true)) { ++ request_err(mbc->dc, "Failed to export as dmabuf\n"); ++ queue_put_free(mbc->dst, &be_dst->base); ++ return NULL; ++ } ++ } ++ else { ++ if (qe_alloc_from_fmt(&be_dst->base, dbsc, &mbc->dst_fmt)) { ++ /* Given how create buf works we can't uncreate it on alloc failure ++ * all we can do is put it on the free Q ++ */ ++ queue_put_free(mbc->dst, &be_dst->base); ++ return NULL; ++ } ++ } ++ ++ be_dst->base.status = QENT_PENDING; ++ atomic_store(&be_dst->base.ref_count, 0); ++ return be_dst; ++} ++ ++const struct v4l2_format *mediabufs_dst_fmt(struct mediabufs_ctl *const mbc) ++{ ++ return &mbc->dst_fmt; ++} ++ ++MediaBufsStatus mediabufs_dst_fmt_set(struct mediabufs_ctl *const mbc, ++ const unsigned int width, ++ const unsigned int height, ++ mediabufs_dst_fmt_accept_fn *const accept_fn, ++ void *const accept_v) ++{ ++ MediaBufsStatus status; ++ unsigned int i; ++ const enum v4l2_buf_type buf_type = mbc->dst_fmt.type; ++ static const struct { ++ unsigned int flags_must; ++ unsigned int flags_not; ++ } trys[] = { ++ {0, V4L2_FMT_FLAG_EMULATED}, ++ {V4L2_FMT_FLAG_EMULATED, 0}, ++ }; ++ for (i = 0; i != sizeof(trys)/sizeof(trys[0]); ++i) { ++ status = find_fmt_flags(&mbc->dst_fmt, mbc->vfd, ++ buf_type, ++ trys[i].flags_must, ++ trys[i].flags_not, ++ width, height, accept_fn, accept_v); ++ if (status != MEDIABUFS_ERROR_UNSUPPORTED_BUFFERTYPE) ++ return status; ++ } ++ ++ if (status != MEDIABUFS_STATUS_SUCCESS) ++ return status; ++ ++ /* Try to create a buffer - don't alloc */ ++ return status; ++} ++ ++// ** This is a mess if we get partial alloc but without any way to remove ++// individual V4L2 Q members we are somewhat stuffed ++MediaBufsStatus mediabufs_dst_slots_create(struct mediabufs_ctl *const mbc, const unsigned int n, const bool fixed, const enum mediabufs_memory memtype) ++{ ++ unsigned int i; ++ int a = 0; ++ unsigned int qc; ++ struct qent_dst * qes[32]; ++ ++ if (n > 32) ++ return MEDIABUFS_ERROR_ALLOCATION_FAILED; ++ ++ mbc->dst->memtype = memtype; ++ ++ // Create qents first as it is hard to get rid of the V4L2 buffers on error ++ for (qc = 0; qc != n; ++qc) ++ { ++ if ((qes[qc] = qe_dst_new(mbc->this_wlm, mbc->dst->memtype)) == NULL) ++ goto fail; ++ } ++ ++ if ((a = create_dst_bufs(mbc, n, qes)) < 0) ++ goto fail; ++ ++ for (i = 0; i != a; ++i) ++ queue_put_free(mbc->dst, &qes[i]->base); ++ ++ if (a != n) ++ goto fail; ++ ++ mbc->dst_fixed = fixed; ++ return MEDIABUFS_STATUS_SUCCESS; ++ ++fail: ++ for (i = (a < 0 ? 0 : a); i != qc; ++i) ++ qe_dst_free(qes[i]); ++ ++ return MEDIABUFS_ERROR_ALLOCATION_FAILED; ++} ++ ++struct qent_src *mediabufs_src_qent_get(struct mediabufs_ctl *const mbc) ++{ ++ struct qent_base * buf = queue_get_free(mbc->src); ++ buf->status = QENT_PENDING; ++ return base_to_src(buf); ++} ++ ++void mediabufs_src_qent_abort(struct mediabufs_ctl *const mbc, struct qent_src **const pqe_src) ++{ ++ struct qent_src *const qe_src = *pqe_src; ++ if (!qe_src) ++ return; ++ *pqe_src = NULL; ++ queue_put_free(mbc->src, &qe_src->base); ++} ++ ++static MediaBufsStatus ++chk_memory_type(struct mediabufs_ctl *const mbc, ++ const struct v4l2_format * const f, ++ const enum mediabufs_memory m) ++{ ++ struct v4l2_create_buffers cbuf = { ++ .count = 0, ++ .memory = V4L2_MEMORY_MMAP, ++ .format = *f ++ }; ++ ++ if (ioctl(mbc->vfd, VIDIOC_CREATE_BUFS, &cbuf) != 0) ++ return MEDIABUFS_ERROR_OPERATION_FAILED; ++ ++ switch (m) { ++ case MEDIABUFS_MEMORY_DMABUF: ++ // 0 = Unknown but assume not in that case ++ if ((cbuf.capabilities & V4L2_BUF_CAP_SUPPORTS_DMABUF) == 0) ++ return MEDIABUFS_ERROR_UNSUPPORTED_MEMORY; ++ break; ++ case MEDIABUFS_MEMORY_MMAP: ++ break; ++ default: ++ return MEDIABUFS_ERROR_UNSUPPORTED_MEMORY; ++ } ++ ++ return MEDIABUFS_STATUS_SUCCESS; ++} ++ ++MediaBufsStatus ++mediabufs_src_chk_memtype(struct mediabufs_ctl *const mbc, const enum mediabufs_memory memtype) ++{ ++ return chk_memory_type(mbc, &mbc->src_fmt, memtype); ++} ++ ++MediaBufsStatus ++mediabufs_dst_chk_memtype(struct mediabufs_ctl *const mbc, const enum mediabufs_memory memtype) ++{ ++ return chk_memory_type(mbc, &mbc->dst_fmt, memtype); ++} ++ ++/* src format must have been set up before this */ ++MediaBufsStatus mediabufs_src_pool_create(struct mediabufs_ctl *const mbc, ++ struct dmabufs_ctl * const dbsc, ++ unsigned int n, const enum mediabufs_memory memtype) ++{ ++ unsigned int i; ++ struct v4l2_requestbuffers req = { ++ .count = n, ++ .type = mbc->src_fmt.type, ++ .memory = mediabufs_memory_to_v4l2(memtype) ++ }; ++ ++ bq_free_all_free_src(mbc->src); ++ ++ while (ioctl(mbc->vfd, VIDIOC_REQBUFS, &req) == -1) { ++ if (errno != EINTR) { ++ request_err(mbc->dc, "%s: Failed to request src bufs\n", __func__); ++ return MEDIABUFS_ERROR_OPERATION_FAILED; ++ } ++ } ++ ++ if (n > req.count) { ++ request_info(mbc->dc, "Only allocated %d of %d src buffers requested\n", req.count, n); ++ n = req.count; ++ } ++ ++ for (i = 0; i != n; ++i) { ++ struct qent_src *const be_src = qe_src_new(memtype); ++ if (!be_src) { ++ request_err(mbc->dc, "Failed to create src be %d\n", i); ++ goto fail; ++ } ++ switch (memtype) { ++ case MEDIABUFS_MEMORY_MMAP: ++ if (qe_import_from_buf(mbc, &be_src->base, &mbc->src_fmt, i, false)) { ++ qe_src_free(be_src); ++ goto fail; ++ } ++ be_src->fixed_size = 1; ++ break; ++ case MEDIABUFS_MEMORY_DMABUF: ++ if (qe_alloc_from_fmt(&be_src->base, dbsc, &mbc->src_fmt)) { ++ qe_src_free(be_src); ++ goto fail; ++ } ++ be_src->fixed_size = !mediabufs_src_resizable(mbc); ++ break; ++ default: ++ request_err(mbc->dc, "Unexpected memorty type\n"); ++ goto fail; ++ } ++ be_src->base.index = i; ++ ++ queue_put_free(mbc->src, &be_src->base); ++ } ++ ++ mbc->src->memtype = memtype; ++ return MEDIABUFS_STATUS_SUCCESS; ++ ++fail: ++ bq_free_all_free_src(mbc->src); ++ req.count = 0; ++ while (ioctl(mbc->vfd, VIDIOC_REQBUFS, &req) == -1 && ++ errno == EINTR) ++ /* Loop */; ++ ++ return MEDIABUFS_ERROR_OPERATION_FAILED; ++} ++ ++ ++ ++/* ++ * Set stuff order: ++ * Set src fmt ++ * Set parameters (sps) on vfd ++ * Negotiate dst format (dst_fmt_set) ++ * Create src buffers ++ * Alloc a dst buffer or Create dst slots ++*/ ++MediaBufsStatus mediabufs_stream_on(struct mediabufs_ctl *const mbc) ++{ ++ if (mbc->stream_on) ++ return MEDIABUFS_STATUS_SUCCESS; ++ ++ if (set_stream(mbc->vfd, mbc->src_fmt.type, true) < 0) { ++ request_log("Failed to set stream on src type %d\n", mbc->src_fmt.type); ++ return MEDIABUFS_ERROR_OPERATION_FAILED; ++ } ++ ++ if (set_stream(mbc->vfd, mbc->dst_fmt.type, true) < 0) { ++ request_log("Failed to set stream on dst type %d\n", mbc->dst_fmt.type); ++ set_stream(mbc->vfd, mbc->src_fmt.type, false); ++ return MEDIABUFS_ERROR_OPERATION_FAILED; ++ } ++ ++ mbc->stream_on = true; ++ return MEDIABUFS_STATUS_SUCCESS; ++} ++ ++MediaBufsStatus mediabufs_stream_off(struct mediabufs_ctl *const mbc) ++{ ++ MediaBufsStatus status = MEDIABUFS_STATUS_SUCCESS; ++ ++ if (!mbc->stream_on) ++ return MEDIABUFS_STATUS_SUCCESS; ++ ++ if (set_stream(mbc->vfd, mbc->dst_fmt.type, false) < 0) { ++ request_log("Failed to set stream off dst type %d\n", mbc->dst_fmt.type); ++ status = MEDIABUFS_ERROR_OPERATION_FAILED; ++ } ++ ++ if (set_stream(mbc->vfd, mbc->src_fmt.type, false) < 0) { ++ request_log("Failed to set stream off src type %d\n", mbc->src_fmt.type); ++ status = MEDIABUFS_ERROR_OPERATION_FAILED; ++ } ++ ++ mbc->stream_on = false; ++ return status; ++} ++ ++MediaBufsStatus mediabufs_stream_wait_dst_done(struct mediabufs_ctl *const mbc) ++{ ++ queue_dst_wait_no_waiting(mbc->dst); ++ return MEDIABUFS_STATUS_SUCCESS; ++} ++ ++int mediabufs_ctl_set_ext_ctrls(struct mediabufs_ctl * mbc, struct media_request * const mreq, struct v4l2_ext_control * const control_array, unsigned int n) ++{ ++ struct v4l2_ext_controls controls = { ++ .controls = control_array, ++ .count = n ++ }; ++ ++ if (mreq) { ++ controls.which = V4L2_CTRL_WHICH_REQUEST_VAL; ++ controls.request_fd = media_request_fd(mreq); ++ } ++ ++ while (ioctl(mbc->vfd, VIDIOC_S_EXT_CTRLS, &controls)) ++ { ++ const int err = errno; ++ if (err != EINTR) { ++ request_err(mbc->dc, "Unable to set controls: %s\n", strerror(err)); ++ return -err; ++ } ++ } ++ ++ return 0; ++} ++ ++MediaBufsStatus mediabufs_set_ext_ctrl(struct mediabufs_ctl *const mbc, ++ struct media_request * const mreq, ++ unsigned int id, void *data, ++ unsigned int size) ++{ ++ struct v4l2_ext_control control = { ++ .id = id, ++ .ptr = data, ++ .size = size ++ }; ++ ++ int rv = mediabufs_ctl_set_ext_ctrls(mbc, mreq, &control, 1); ++ return !rv ? MEDIABUFS_STATUS_SUCCESS : MEDIABUFS_ERROR_OPERATION_FAILED; ++} ++ ++MediaBufsStatus mediabufs_src_fmt_set(struct mediabufs_ctl *const mbc, ++ enum v4l2_buf_type buf_type, ++ const uint32_t pixfmt, ++ const uint32_t width, const uint32_t height, ++ const size_t bufsize) ++{ ++ MediaBufsStatus rv = fmt_set(&mbc->src_fmt, mbc->vfd, buf_type, pixfmt, width, height, bufsize); ++ if (rv != MEDIABUFS_STATUS_SUCCESS) ++ request_err(mbc->dc, "Failed to set src buftype %d, format %#x %dx%d\n", buf_type, pixfmt, width, height); ++ ++ return rv; ++} ++ ++int mediabufs_ctl_query_ext_ctrls(struct mediabufs_ctl * mbc, struct v4l2_query_ext_ctrl * ctrls, unsigned int n) ++{ ++ int rv = 0; ++ while (n--) { ++ while (ioctl(mbc->vfd, VIDIOC_QUERY_EXT_CTRL, ctrls)) { ++ const int err = errno; ++ if (err != EINTR) { ++ // Often used for probing - errors are to be expected ++ request_debug(mbc->dc, "Failed to query ext id=%#x, err=%d\n", ctrls->id, err); ++ ctrls->type = 0; // 0 is invalid ++ rv = -err; ++ break; ++ } ++ } ++ ++ctrls; ++ } ++ return rv; ++} ++ ++int mediabufs_src_resizable(const struct mediabufs_ctl *const mbc) ++{ ++ // Single planar OUTPUT can only take exact size buffers ++ // Multiplanar will take larger than negotiated ++ return V4L2_TYPE_IS_MULTIPLANAR(mbc->src_fmt.type); ++} ++ ++static void mediabufs_ctl_delete(struct mediabufs_ctl *const mbc) ++{ ++ if (!mbc) ++ return; ++ ++ // Break the weak link first ++ ff_weak_link_break(&mbc->this_wlm); ++ ++ polltask_delete(&mbc->pt); ++ ++ mediabufs_stream_off(mbc); ++ ++ // Empty v4l2 buffer stash ++ request_buffers(mbc->vfd, mbc->src_fmt.type, V4L2_MEMORY_MMAP, 0); ++ request_buffers(mbc->vfd, mbc->dst_fmt.type, V4L2_MEMORY_MMAP, 0); ++ ++ bq_free_all_free_src(mbc->src); ++ bq_free_all_inuse_src(mbc->src); ++ bq_free_all_free_dst(mbc->dst); ++ ++ { ++ struct qent_dst *dst_be; ++ while ((dst_be = base_to_dst(bq_get_inuse(mbc->dst))) != NULL) { ++ dst_be->base.timestamp = (struct timeval){0}; ++ dst_be->base.status = QENT_ERROR; ++ qe_dst_done(dst_be); ++ } ++ } ++ ++ queue_delete(mbc->dst); ++ queue_delete(mbc->src); ++ close(mbc->vfd); ++ pthread_mutex_destroy(&mbc->lock); ++ ++ free(mbc); ++} ++ ++struct mediabufs_ctl * mediabufs_ctl_ref(struct mediabufs_ctl *const mbc) ++{ ++ atomic_fetch_add(&mbc->ref_count, 1); ++ return mbc; ++} ++ ++void mediabufs_ctl_unref(struct mediabufs_ctl **const pmbc) ++{ ++ struct mediabufs_ctl *const mbc = *pmbc; ++ int n; ++ ++ if (!mbc) ++ return; ++ *pmbc = NULL; ++ n = atomic_fetch_sub(&mbc->ref_count, 1); ++ if (n) ++ return; ++ mediabufs_ctl_delete(mbc); ++} ++ ++unsigned int mediabufs_ctl_driver_version(struct mediabufs_ctl *const mbc) ++{ ++ return mbc->capability.version; ++} ++ ++static int set_capabilities(struct mediabufs_ctl *const mbc) ++{ ++ uint32_t caps; ++ ++ if (ioctl(mbc->vfd, VIDIOC_QUERYCAP, &mbc->capability)) { ++ int err = errno; ++ request_err(mbc->dc, "Failed to get capabilities: %s\n", strerror(err)); ++ return -err; ++ } ++ ++ caps = (mbc->capability.capabilities & V4L2_CAP_DEVICE_CAPS) != 0 ? ++ mbc->capability.device_caps : ++ mbc->capability.capabilities; ++ ++ if ((caps & V4L2_CAP_VIDEO_M2M_MPLANE) != 0) { ++ mbc->src_fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; ++ mbc->dst_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; ++ } ++ else if ((caps & V4L2_CAP_VIDEO_M2M) != 0) { ++ mbc->src_fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; ++ mbc->dst_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ } ++ else { ++ request_err(mbc->dc, "No M2M capabilities (%#x)\n", caps); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++/* One of these per context */ ++struct mediabufs_ctl * mediabufs_ctl_new(void * const dc, const char * vpath, struct pollqueue *const pq) ++{ ++ struct mediabufs_ctl *const mbc = calloc(1, sizeof(*mbc)); ++ ++ if (!mbc) ++ return NULL; ++ ++ mbc->dc = dc; ++ // Default mono planar ++ mbc->pq = pq; ++ pthread_mutex_init(&mbc->lock, NULL); ++ ++ /* Pick a default - could we scan for this? */ ++ if (vpath == NULL) ++ vpath = "/dev/media0"; ++ ++ while ((mbc->vfd = open(vpath, O_RDWR)) == -1) ++ { ++ const int err = errno; ++ if (err != EINTR) { ++ request_err(dc, "Failed to open video dev '%s': %s\n", vpath, strerror(err)); ++ goto fail0; ++ } ++ } ++ ++ if (set_capabilities(mbc)) { ++ request_err(dc, "Bad capabilities for video dev '%s'\n", vpath); ++ goto fail1; ++ } ++ ++ mbc->src = queue_new(mbc->vfd); ++ if (!mbc->src) ++ goto fail1; ++ mbc->dst = queue_new(mbc->vfd); ++ if (!mbc->dst) ++ goto fail2; ++ mbc->pt = polltask_new(pq, mbc->vfd, POLLIN | POLLOUT, mediabufs_poll_cb, mbc); ++ if (!mbc->pt) ++ goto fail3; ++ mbc->this_wlm = ff_weak_link_new(mbc); ++ if (!mbc->this_wlm) ++ goto fail4; ++ ++ /* Cannot add polltask now - polling with nothing pending ++ * generates infinite error polls ++ */ ++ return mbc; ++ ++fail4: ++ polltask_delete(&mbc->pt); ++fail3: ++ queue_delete(mbc->dst); ++fail2: ++ queue_delete(mbc->src); ++fail1: ++ close(mbc->vfd); ++fail0: ++ free(mbc); ++ request_info(dc, "%s: FAILED\n", __func__); ++ return NULL; ++} ++ ++ ++ +diff --git a/libavcodec/v4l2_req_media.h b/libavcodec/v4l2_req_media.h +new file mode 100644 +index 000000000000..f3023df9e830 +--- /dev/null ++++ b/libavcodec/v4l2_req_media.h +@@ -0,0 +1,179 @@ ++/* ++e.h ++* ++ * 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, sub license, 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 (including the ++ * next paragraph) 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 NON-INFRINGEMENT. ++ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. ++ */ ++ ++#ifndef AVCODEC_V4L2_REQ_MEDIA_H ++#define AVCODEC_V4L2_REQ_MEDIA_H ++ ++#include ++#include ++ ++struct v4l2_format; ++struct v4l2_fmtdesc; ++struct v4l2_query_ext_ctrl; ++ ++struct pollqueue; ++struct media_request; ++struct media_pool; ++ ++typedef enum media_buf_status { ++ MEDIABUFS_STATUS_SUCCESS = 0, ++ MEDIABUFS_ERROR_OPERATION_FAILED, ++ MEDIABUFS_ERROR_DECODING_ERROR, ++ MEDIABUFS_ERROR_UNSUPPORTED_BUFFERTYPE, ++ MEDIABUFS_ERROR_UNSUPPORTED_RT_FORMAT, ++ MEDIABUFS_ERROR_ALLOCATION_FAILED, ++ MEDIABUFS_ERROR_UNSUPPORTED_MEMORY, ++} MediaBufsStatus; ++ ++struct media_pool * media_pool_new(const char * const media_path, ++ struct pollqueue * const pq, ++ const unsigned int n); ++void media_pool_delete(struct media_pool ** pmp); ++ ++// Obtain a media request ++// Will block if none availible - has a 2sec timeout ++struct media_request * media_request_get(struct media_pool * const mp); ++int media_request_fd(const struct media_request * const req); ++ ++// Start this request ++// Request structure is returned to pool once done ++int media_request_start(struct media_request * const req); ++ ++// Return an *unstarted* media_request to the pool ++// May later be upgraded to allow for aborting a started req ++int media_request_abort(struct media_request ** const preq); ++ ++ ++struct mediabufs_ctl; ++struct qent_src; ++struct qent_dst; ++struct dmabuf_h; ++struct dmabufs_ctl; ++ ++struct timeval; ++enum v4l2_buf_type; ++struct v4l2_ext_control; ++struct v4l2_query_ext_ctrl; ++ ++// 1-1 mammping to V4L2 type - just defined separetely to avoid some include versioning difficulties ++enum mediabufs_memory { ++ MEDIABUFS_MEMORY_UNSET = 0, ++ MEDIABUFS_MEMORY_MMAP = 1, ++ MEDIABUFS_MEMORY_USERPTR = 2, ++ MEDIABUFS_MEMORY_OVERLAY = 3, ++ MEDIABUFS_MEMORY_DMABUF = 4, ++}; ++ ++int qent_src_params_set(struct qent_src *const be, const struct timeval * timestamp); ++struct timeval qent_dst_timestamp_get(const struct qent_dst *const be_dst); ++ ++// prealloc ++int qent_src_alloc(struct qent_src *const be_src, const size_t len, struct dmabufs_ctl * dbsc); ++// dbsc may be NULL if realloc not required ++int qent_src_data_copy(struct qent_src *const be_src, const size_t offset, const void *const src, const size_t len, struct dmabufs_ctl * dbsc); ++const struct dmabuf_h * qent_dst_dmabuf(const struct qent_dst *const be, unsigned int plane); ++int qent_dst_dup_fd(const struct qent_dst *const be, unsigned int plane); ++MediaBufsStatus qent_dst_wait(struct qent_dst *const be); ++void qent_dst_delete(struct qent_dst *const be); ++// Returns a qent_dst to its mbc free Q or deletes it if the mbc is dead ++void qent_dst_unref(struct qent_dst ** const pbe_dst); ++struct qent_dst * qent_dst_ref(struct qent_dst * const be_dst); ++ ++const uint8_t * qent_dst_data(struct qent_dst *const be, unsigned int buf_no); ++MediaBufsStatus qent_dst_read_start(struct qent_dst *const be); ++MediaBufsStatus qent_dst_read_stop(struct qent_dst *const be); ++/* Import an fd unattached to any mediabuf */ ++MediaBufsStatus qent_dst_import_fd(struct qent_dst *const be_dst, ++ unsigned int plane, ++ int fd, size_t size); ++ ++const char * mediabufs_memory_name(const enum mediabufs_memory m); ++ ++MediaBufsStatus mediabufs_start_request(struct mediabufs_ctl *const mbc, ++ struct media_request **const pmreq, ++ struct qent_src **const psrc_be, ++ struct qent_dst *const dst_be, ++ const bool is_final); ++// Get / alloc a dst buffer & associate with a slot ++// If the dst pool is empty then behaviour depends on the fixed flag passed to ++// dst_slots_create. Default is !fixed = unlimited alloc ++struct qent_dst* mediabufs_dst_qent_alloc(struct mediabufs_ctl *const mbc, ++ struct dmabufs_ctl *const dbsc); ++// Create dst slots without alloc ++// If fixed true then qent_alloc will only get slots from this pool and will ++// block until a qent has been unrefed ++MediaBufsStatus mediabufs_dst_slots_create(struct mediabufs_ctl *const mbc, const unsigned int n, const bool fixed, const enum mediabufs_memory memtype); ++ ++MediaBufsStatus mediabufs_stream_on(struct mediabufs_ctl *const mbc); ++MediaBufsStatus mediabufs_stream_off(struct mediabufs_ctl *const mbc); ++ ++MediaBufsStatus mediabufs_stream_wait_dst_done(struct mediabufs_ctl *const mbc); ++ ++const struct v4l2_format *mediabufs_dst_fmt(struct mediabufs_ctl *const mbc); ++ ++typedef int mediabufs_dst_fmt_accept_fn(void * v, const struct v4l2_fmtdesc *fmtdesc); ++ ++MediaBufsStatus mediabufs_dst_fmt_set(struct mediabufs_ctl *const mbc, ++ const unsigned int width, ++ const unsigned int height, ++ mediabufs_dst_fmt_accept_fn *const accept_fn, ++ void *const accept_v); ++struct qent_src *mediabufs_src_qent_get(struct mediabufs_ctl *const mbc); ++void mediabufs_src_qent_abort(struct mediabufs_ctl *const mbc, struct qent_src **const pqe_src); ++ ++int mediabufs_ctl_set_ext_ctrls(struct mediabufs_ctl * mbc, struct media_request * const mreq, ++ struct v4l2_ext_control * const control_array, unsigned int n); ++MediaBufsStatus mediabufs_set_ext_ctrl(struct mediabufs_ctl *const mbc, ++ struct media_request * const mreq, ++ unsigned int id, void *data, ++ unsigned int size); ++int mediabufs_ctl_query_ext_ctrls(struct mediabufs_ctl * mbc, struct v4l2_query_ext_ctrl * ctrls, unsigned int n); ++ ++int mediabufs_src_resizable(const struct mediabufs_ctl *const mbc); ++ ++MediaBufsStatus mediabufs_src_fmt_set(struct mediabufs_ctl *const mbc, ++ enum v4l2_buf_type buf_type, ++ const uint32_t pixfmt, ++ const uint32_t width, const uint32_t height, ++ const size_t bufsize); ++ ++MediaBufsStatus mediabufs_src_pool_create(struct mediabufs_ctl *const rw, ++ struct dmabufs_ctl * const dbsc, ++ unsigned int n, ++ const enum mediabufs_memory memtype); ++ ++// Want to have appropriate formats set first ++MediaBufsStatus mediabufs_src_chk_memtype(struct mediabufs_ctl *const mbc, const enum mediabufs_memory memtype); ++MediaBufsStatus mediabufs_dst_chk_memtype(struct mediabufs_ctl *const mbc, const enum mediabufs_memory memtype); ++ ++#define MEDIABUFS_DRIVER_VERSION(a, b, c) (((a) << 16) | ((b) << 8) | (c)) ++unsigned int mediabufs_ctl_driver_version(struct mediabufs_ctl *const mbc); ++ ++struct mediabufs_ctl * mediabufs_ctl_new(void * const dc, ++ const char *vpath, struct pollqueue *const pq); ++void mediabufs_ctl_unref(struct mediabufs_ctl **const pmbc); ++struct mediabufs_ctl * mediabufs_ctl_ref(struct mediabufs_ctl *const mbc); ++ ++ ++#endif +diff --git a/libavcodec/v4l2_req_pollqueue.c b/libavcodec/v4l2_req_pollqueue.c +new file mode 100644 +index 000000000000..4b4984e5b064 +--- /dev/null ++++ b/libavcodec/v4l2_req_pollqueue.c +@@ -0,0 +1,385 @@ ++/* ++ Copyright (C) 2024 John Cox john.cox@raspberrypi.com ++ ++ 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "v4l2_req_pollqueue.h" ++#include "v4l2_req_utils.h" ++ ++ ++struct pollqueue; ++ ++enum polltask_state { ++ POLLTASK_UNQUEUED = 0, ++ POLLTASK_QUEUED, ++ POLLTASK_RUNNING, ++ POLLTASK_Q_KILL, ++ POLLTASK_RUN_KILL, ++}; ++ ++struct polltask { ++ struct polltask *next; ++ struct polltask *prev; ++ struct pollqueue *q; ++ enum polltask_state state; ++ ++ int fd; ++ short events; ++ ++ void (*fn)(void *v, short revents); ++ void * v; ++ ++ uint64_t timeout; /* CLOCK_MONOTONIC time, 0 => never */ ++ sem_t kill_sem; ++}; ++ ++struct pollqueue { ++ atomic_int ref_count; ++ pthread_mutex_t lock; ++ ++ struct polltask *head; ++ struct polltask *tail; ++ ++ bool kill; ++ bool no_prod; ++ int prod_fd; ++ struct polltask *prod_pt; ++ pthread_t worker; ++}; ++ ++struct polltask *polltask_new(struct pollqueue *const pq, ++ const int fd, const short events, ++ void (*const fn)(void *v, short revents), ++ void *const v) ++{ ++ struct polltask *pt; ++ ++ if (!events) ++ return NULL; ++ ++ pt = malloc(sizeof(*pt)); ++ if (!pt) ++ return NULL; ++ ++ *pt = (struct polltask){ ++ .next = NULL, ++ .prev = NULL, ++ .q = pollqueue_ref(pq), ++ .fd = fd, ++ .events = events, ++ .fn = fn, ++ .v = v ++ }; ++ ++ sem_init(&pt->kill_sem, 0, 0); ++ ++ return pt; ++} ++ ++static void pollqueue_rem_task(struct pollqueue *const pq, struct polltask *const pt) ++{ ++ if (pt->prev) ++ pt->prev->next = pt->next; ++ else ++ pq->head = pt->next; ++ if (pt->next) ++ pt->next->prev = pt->prev; ++ else ++ pq->tail = pt->prev; ++ pt->next = NULL; ++ pt->prev = NULL; ++} ++ ++static void polltask_free(struct polltask * const pt) ++{ ++ sem_destroy(&pt->kill_sem); ++ free(pt); ++} ++ ++static int pollqueue_prod(const struct pollqueue *const pq) ++{ ++ static const uint64_t one = 1; ++ return write(pq->prod_fd, &one, sizeof(one)); ++} ++ ++void polltask_delete(struct polltask **const ppt) ++{ ++ struct polltask *const pt = *ppt; ++ struct pollqueue * pq; ++ enum polltask_state state; ++ bool prodme; ++ ++ if (!pt) ++ return; ++ ++ pq = pt->q; ++ pthread_mutex_lock(&pq->lock); ++ state = pt->state; ++ pt->state = (state == POLLTASK_RUNNING) ? POLLTASK_RUN_KILL : POLLTASK_Q_KILL; ++ prodme = !pq->no_prod; ++ pthread_mutex_unlock(&pq->lock); ++ ++ if (state != POLLTASK_UNQUEUED) { ++ if (prodme) ++ pollqueue_prod(pq); ++ while (sem_wait(&pt->kill_sem) && errno == EINTR) ++ /* loop */; ++ } ++ ++ // Leave zapping the ref until we have DQed the PT as might well be ++ // legitimately used in it ++ *ppt = NULL; ++ polltask_free(pt); ++ pollqueue_unref(&pq); ++} ++ ++static uint64_t pollqueue_now(int timeout) ++{ ++ struct timespec now; ++ uint64_t now_ms; ++ ++ if (clock_gettime(CLOCK_MONOTONIC, &now)) ++ return 0; ++ now_ms = (now.tv_nsec / 1000000) + (uint64_t)now.tv_sec * 1000 + timeout; ++ return now_ms ? now_ms : (uint64_t)1; ++} ++ ++void pollqueue_add_task(struct polltask *const pt, const int timeout) ++{ ++ bool prodme = false; ++ struct pollqueue * const pq = pt->q; ++ ++ pthread_mutex_lock(&pq->lock); ++ if (pt->state != POLLTASK_Q_KILL && pt->state != POLLTASK_RUN_KILL) { ++ if (pq->tail) ++ pq->tail->next = pt; ++ else ++ pq->head = pt; ++ pt->prev = pq->tail; ++ pt->next = NULL; ++ pt->state = POLLTASK_QUEUED; ++ pt->timeout = timeout < 0 ? 0 : pollqueue_now(timeout); ++ pq->tail = pt; ++ prodme = !pq->no_prod; ++ } ++ pthread_mutex_unlock(&pq->lock); ++ if (prodme) ++ pollqueue_prod(pq); ++} ++ ++static void *poll_thread(void *v) ++{ ++ struct pollqueue *const pq = v; ++ struct pollfd *a = NULL; ++ size_t asize = 0; ++ ++ pthread_mutex_lock(&pq->lock); ++ do { ++ unsigned int i; ++ unsigned int n = 0; ++ struct polltask *pt; ++ struct polltask *pt_next; ++ uint64_t now = pollqueue_now(0); ++ int timeout = -1; ++ int rv; ++ ++ for (pt = pq->head; pt; pt = pt_next) { ++ int64_t t; ++ ++ pt_next = pt->next; ++ ++ if (pt->state == POLLTASK_Q_KILL) { ++ pollqueue_rem_task(pq, pt); ++ sem_post(&pt->kill_sem); ++ continue; ++ } ++ ++ if (n >= asize) { ++ asize = asize ? asize * 2 : 4; ++ a = realloc(a, asize * sizeof(*a)); ++ if (!a) { ++ request_log("Failed to realloc poll array to %zd\n", asize); ++ goto fail_locked; ++ } ++ } ++ ++ a[n++] = (struct pollfd){ ++ .fd = pt->fd, ++ .events = pt->events ++ }; ++ ++ t = (int64_t)(pt->timeout - now); ++ if (pt->timeout && t < INT_MAX && ++ (timeout < 0 || (int)t < timeout)) ++ timeout = (t < 0) ? 0 : (int)t; ++ } ++ pthread_mutex_unlock(&pq->lock); ++ ++ if ((rv = poll(a, n, timeout)) == -1) { ++ if (errno != EINTR) { ++ request_log("Poll error: %s\n", strerror(errno)); ++ goto fail_unlocked; ++ } ++ } ++ ++ pthread_mutex_lock(&pq->lock); ++ now = pollqueue_now(0); ++ ++ /* Prodding in this loop is pointless and might lead to ++ * infinite looping ++ */ ++ pq->no_prod = true; ++ for (i = 0, pt = pq->head; i < n; ++i, pt = pt_next) { ++ pt_next = pt->next; ++ ++ /* Pending? */ ++ if (a[i].revents || ++ (pt->timeout && (int64_t)(now - pt->timeout) >= 0)) { ++ pollqueue_rem_task(pq, pt); ++ if (pt->state == POLLTASK_QUEUED) ++ pt->state = POLLTASK_RUNNING; ++ if (pt->state == POLLTASK_Q_KILL) ++ pt->state = POLLTASK_RUN_KILL; ++ pthread_mutex_unlock(&pq->lock); ++ ++ /* This can add new entries to the Q but as ++ * those are added to the tail our existing ++ * chain remains intact ++ */ ++ pt->fn(pt->v, a[i].revents); ++ ++ pthread_mutex_lock(&pq->lock); ++ if (pt->state == POLLTASK_RUNNING) ++ pt->state = POLLTASK_UNQUEUED; ++ if (pt->state == POLLTASK_RUN_KILL) ++ sem_post(&pt->kill_sem); ++ } ++ } ++ pq->no_prod = false; ++ ++ } while (!pq->kill); ++ ++fail_locked: ++ pthread_mutex_unlock(&pq->lock); ++fail_unlocked: ++ free(a); ++ return NULL; ++} ++ ++static void prod_fn(void *v, short revents) ++{ ++ struct pollqueue *const pq = v; ++ char buf[8]; ++ if (revents) ++ read(pq->prod_fd, buf, 8); ++ if (!pq->kill) ++ pollqueue_add_task(pq->prod_pt, -1); ++} ++ ++struct pollqueue * pollqueue_new(void) ++{ ++ struct pollqueue *pq = malloc(sizeof(*pq)); ++ if (!pq) ++ return NULL; ++ *pq = (struct pollqueue){ ++ .ref_count = ATOMIC_VAR_INIT(0), ++ .lock = PTHREAD_MUTEX_INITIALIZER, ++ .head = NULL, ++ .tail = NULL, ++ .kill = false, ++ .prod_fd = -1 ++ }; ++ ++ pq->prod_fd = eventfd(0, EFD_NONBLOCK); ++ if (pq->prod_fd == 1) ++ goto fail1; ++ pq->prod_pt = polltask_new(pq, pq->prod_fd, POLLIN, prod_fn, pq); ++ if (!pq->prod_pt) ++ goto fail2; ++ pollqueue_add_task(pq->prod_pt, -1); ++ if (pthread_create(&pq->worker, NULL, poll_thread, pq)) ++ goto fail3; ++ // Reset ref count which will have been inced by the add_task ++ atomic_store(&pq->ref_count, 0); ++ return pq; ++ ++fail3: ++ polltask_free(pq->prod_pt); ++fail2: ++ close(pq->prod_fd); ++fail1: ++ free(pq); ++ return NULL; ++} ++ ++static void pollqueue_free(struct pollqueue *const pq) ++{ ++ void *rv; ++ ++ pthread_mutex_lock(&pq->lock); ++ pq->kill = true; ++ pollqueue_prod(pq); ++ pthread_mutex_unlock(&pq->lock); ++ ++ pthread_join(pq->worker, &rv); ++ polltask_free(pq->prod_pt); ++ pthread_mutex_destroy(&pq->lock); ++ close(pq->prod_fd); ++ free(pq); ++} ++ ++struct pollqueue * pollqueue_ref(struct pollqueue *const pq) ++{ ++ atomic_fetch_add(&pq->ref_count, 1); ++ return pq; ++} ++ ++void pollqueue_unref(struct pollqueue **const ppq) ++{ ++ struct pollqueue * const pq = *ppq; ++ ++ if (!pq) ++ return; ++ *ppq = NULL; ++ ++ if (atomic_fetch_sub(&pq->ref_count, 1) != 0) ++ return; ++ ++ pollqueue_free(pq); ++} ++ ++ ++ +diff --git a/libavcodec/v4l2_req_pollqueue.h b/libavcodec/v4l2_req_pollqueue.h +new file mode 100644 +index 000000000000..9634f33d48fd +--- /dev/null ++++ b/libavcodec/v4l2_req_pollqueue.h +@@ -0,0 +1,42 @@ ++/* ++ Copyright (C) 2024 John Cox john.cox@raspberrypi.com ++ ++ 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. ++ */ ++ ++#ifndef AVCODEC_V4L2_REQ_POLLQUEUE_H ++#define AVCODEC_V4L2_REQ_POLLQUEUE_H ++ ++struct polltask; ++struct pollqueue; ++ ++struct polltask *polltask_new(struct pollqueue *const pq, ++ const int fd, const short events, ++ void (*const fn)(void *v, short revents), ++ void *const v); ++void polltask_delete(struct polltask **const ppt); ++ ++void pollqueue_add_task(struct polltask *const pt, const int timeout); ++struct pollqueue * pollqueue_new(void); ++void pollqueue_unref(struct pollqueue **const ppq); ++struct pollqueue * pollqueue_ref(struct pollqueue *const pq); ++ ++#endif /* AVCODEC_V4L2_REQ_POLLQUEUE_H_ */ +diff --git a/libavcodec/v4l2_req_utils.h b/libavcodec/v4l2_req_utils.h +new file mode 100644 +index 000000000000..a6160c5e1c3b +--- /dev/null ++++ b/libavcodec/v4l2_req_utils.h +@@ -0,0 +1,51 @@ ++/* ++ Copyright (C) 2024 John Cox john.cox@raspberrypi.com ++ ++ 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. ++ */ ++ ++#ifndef AVCODEC_V4L2_REQ_UTILS_H ++#define AVCODEC_V4L2_REQ_UTILS_H ++ ++#include ++#include "libavutil/log.h" ++ ++#define request_log(...) av_log(NULL, AV_LOG_INFO, __VA_ARGS__) ++ ++#define request_err(_ctx, ...) av_log(_ctx, AV_LOG_ERROR, __VA_ARGS__) ++#define request_warn(_ctx, ...) av_log(_ctx, AV_LOG_WARNING, __VA_ARGS__) ++#define request_info(_ctx, ...) av_log(_ctx, AV_LOG_INFO, __VA_ARGS__) ++#define request_debug(_ctx, ...) av_log(_ctx, AV_LOG_DEBUG, __VA_ARGS__) ++ ++static inline char safechar(char c) { ++ return c > 0x20 && c < 0x7f ? c : '.'; ++} ++ ++static inline const char * strfourcc(char tbuf[5], uint32_t fcc) { ++ tbuf[0] = safechar((fcc >> 0) & 0xff); ++ tbuf[1] = safechar((fcc >> 8) & 0xff); ++ tbuf[2] = safechar((fcc >> 16) & 0xff); ++ tbuf[3] = safechar((fcc >> 24) & 0xff); ++ tbuf[4] = '\0'; ++ return tbuf; ++} ++ ++#endif +diff --git a/libavcodec/v4l2_request_hevc.c b/libavcodec/v4l2_request_hevc.c +new file mode 100644 +index 000000000000..161a894c7bcc +--- /dev/null ++++ b/libavcodec/v4l2_request_hevc.c +@@ -0,0 +1,433 @@ ++/* ++ * 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 "decode.h" ++#include "hevc/hevcdec.h" ++#include "hwaccel_internal.h" ++#include "hwconfig.h" ++#include "internal.h" ++ ++#include "v4l2_fmt.h" ++#include "v4l2_request_hevc.h" ++ ++#include "libavutil/hwcontext_drm.h" ++#include "libavutil/mem.h" ++#include "libavutil/pixdesc.h" ++ ++#include "v4l2_req_devscan.h" ++#include "v4l2_req_dmabufs.h" ++#include "v4l2_req_pollqueue.h" ++#include "v4l2_req_media.h" ++#include "v4l2_req_utils.h" ++ ++static size_t bit_buf_size(unsigned int w, unsigned int h, unsigned int bits_minus8) ++{ ++ const size_t wxh = w * h; ++ size_t bits_alloc; ++ ++ /* Annex A gives a min compression of 2 @ lvl 3.1 ++ * (wxh <= 983040) and min 4 thereafter but avoid ++ * the odity of 983041 having a lower limit than ++ * 983040. ++ * Multiply by 3/2 for 4:2:0 ++ */ ++ bits_alloc = wxh < 983040 ? wxh * 3 / 4 : ++ wxh < 983040 * 2 ? 983040 * 3 / 4 : ++ wxh * 3 / 8; ++ /* Allow for bit depth */ ++ bits_alloc += (bits_alloc * bits_minus8) / 8; ++ /* Add a few bytes (16k) for overhead */ ++ bits_alloc += 0x4000; ++ return bits_alloc; ++} ++ ++int ff_v4l2_request_start_frame(AVCodecContext *avctx, ++ av_unused const uint8_t *buffer, ++ av_unused uint32_t size) ++{ ++ V4L2RequestPrivHEVC * const priv = avctx->internal->hwaccel_priv_data; ++ V4L2RequestContextHEVC *const ctx = priv->cctx; ++ return ctx->fns->start_frame(avctx, ctx, buffer, size); ++} ++ ++int ff_v4l2_request_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) ++{ ++ V4L2RequestPrivHEVC * const priv = avctx->internal->hwaccel_priv_data; ++ V4L2RequestContextHEVC *const ctx = priv->cctx; ++ return ctx->fns->decode_slice(avctx, ctx, buffer, size); ++} ++ ++int ff_v4l2_request_end_frame(AVCodecContext *avctx) ++{ ++ V4L2RequestPrivHEVC * const priv = avctx->internal->hwaccel_priv_data; ++ V4L2RequestContextHEVC *const ctx = priv->cctx; ++ return ctx->fns->end_frame(avctx, ctx); ++} ++ ++void ff_v4l2_request_abort_frame(AVCodecContext * const avctx) ++{ ++ V4L2RequestPrivHEVC * const priv = avctx->internal->hwaccel_priv_data; ++ V4L2RequestContextHEVC *const ctx = priv->cctx; ++ ctx->fns->abort_frame(avctx, ctx); ++} ++ ++int ff_v4l2_request_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx) ++{ ++ V4L2RequestPrivHEVC * const priv = avctx->internal->hwaccel_priv_data; ++ V4L2RequestContextHEVC *const ctx = priv->cctx; ++ return ctx->fns->frame_params(avctx, ctx, hw_frames_ctx); ++} ++ ++int ff_v4l2_request_alloc_frame(AVCodecContext * avctx, AVFrame *frame) ++{ ++ V4L2RequestPrivHEVC * const priv = avctx->internal->hwaccel_priv_data; ++ V4L2RequestContextHEVC *const ctx = priv->cctx; ++ return ctx->fns->alloc_frame(avctx, ctx, frame); ++} ++ ++ ++static void ++cctx_free(void * v, uint8_t * data) ++{ ++ V4L2RequestContextHEVC *const ctx = (V4L2RequestContextHEVC *)data; ++ ++ if (ctx->fns && ctx->fns->uninit) ++ ctx->fns->uninit(ctx); ++ ++ mediabufs_ctl_unref(&ctx->mbufs); ++ media_pool_delete(&ctx->mpool); ++ pollqueue_unref(&ctx->pq); ++ dmabufs_ctl_unref(&ctx->dbufs); ++ devscan_delete(&ctx->devscan); ++ ++ decode_q_uninit(&ctx->decode_q); ++ ++ av_free(ctx); ++} ++ ++int ff_v4l2_request_uninit(AVCodecContext *avctx) ++{ ++ V4L2RequestPrivHEVC * const priv = avctx->internal->hwaccel_priv_data; ++ ++ av_log(avctx, AV_LOG_DEBUG, "<<< %s\n", __func__); ++ ++ if (priv->cctx != NULL) { ++ V4L2RequestContextHEVC *const ctx = priv->cctx; ++ ++ decode_q_wait(&ctx->decode_q, NULL); // Wait for all other threads to be out of decode ++ mediabufs_stream_wait_dst_done(ctx->mbufs); // Now wait for processing to finish ++ ++ priv->cctx = NULL; ++ av_buffer_unref(&priv->cctx_buf); ++ } ++ ++// if (avctx->hw_frames_ctx) { ++// AVHWFramesContext *hwfc = (AVHWFramesContext*)avctx->hw_frames_ctx->data; ++// av_buffer_pool_flush(hwfc->pool); ++// } ++ return 0; ++} ++ ++static int dst_fmt_accept_cb(void * v, const struct v4l2_fmtdesc *fmtdesc) ++{ ++ const int bit_depth = *(int *)v; ++ ++ // SAND is currently confised as to whether it is s/w or hardware ++ // *** Current usage is probably wrong - it shouldn't be a h/w fmt ++ if (fmtdesc->pixelformat == V4L2_PIX_FMT_NV12_COL128 || ++ fmtdesc->pixelformat == V4L2_PIX_FMT_NV12_COL128M) { ++ return bit_depth == 8; ++ } ++ if (fmtdesc->pixelformat == V4L2_PIX_FMT_NV12_10_COL128 || ++ fmtdesc->pixelformat == V4L2_PIX_FMT_NV12_10_COL128M) { ++ return bit_depth == 10; ++ } ++ else { ++ const enum AVPixelFormat fmt = ff_v4l2_format_v4l2_to_avfmt(fmtdesc->pixelformat, AV_CODEC_ID_RAWVIDEO); ++ const AVPixFmtDescriptor * const desc = av_pix_fmt_desc_get(fmt); ++ ++ if (fmt == AV_PIX_FMT_NONE || desc == NULL) ++ return 0; ++ ++ return bit_depth == desc->comp[0].depth; ++ } ++} ++ ++int ff_v4l2_request_init(AVCodecContext *avctx, ++ const struct v4l2_req_decode_fns * const * const try_fns, ++ const int width, const int height, const int bit_depth, ++ const int dst_buffers) ++{ ++ V4L2RequestPrivHEVC * const priv = avctx->internal->hwaccel_priv_data; ++ V4L2RequestContextHEVC * ctx; ++ int ret; ++ const struct decdev * decdev; ++ const uint32_t src_pix_fmt = try_fns[0]->src_pix_fmt_v4l2; // Assuming constant for all APIs but avoiding V4L2 includes ++ size_t src_size; ++ enum mediabufs_memory src_memtype; ++ enum mediabufs_memory dst_memtype; ++ ++ av_log(avctx, AV_LOG_DEBUG, "<<< %s\n", __func__); ++ ++ if ((ctx = av_mallocz(sizeof(*ctx))) == NULL) { ++ av_log(avctx, AV_LOG_ERROR, "Unable to allocate context"); ++ return AVERROR(ENOMEM); ++ } ++ if ((priv->cctx_buf = av_buffer_create((uint8_t*)ctx, sizeof(*ctx), cctx_free, NULL, 0)) == NULL) { ++ av_log(avctx, AV_LOG_ERROR, "Unable to allocate context buffer"); ++ av_free(ctx); ++ return AVERROR(ENOMEM); ++ } ++ priv->cctx = ctx; ++ ++ decode_q_init(&ctx->decode_q); ++ ++ if ((ret = devscan_build(avctx, &ctx->devscan)) != 0) { ++ av_log(avctx, AV_LOG_WARNING, "Failed to find any V4L2 devices\n"); ++ ret = AVERROR(-ret); ++ goto fail0; ++ } ++ ret = AVERROR(ENOMEM); // Assume mem fail by default for these ++ ++ if ((decdev = devscan_find(ctx->devscan, src_pix_fmt)) == NULL) ++ { ++ av_log(avctx, AV_LOG_WARNING, "Failed to find a device for %s\n", try_fns[0]->name); ++ ret = AVERROR(ENODEV); ++ goto fail0; ++ } ++ av_log(avctx, AV_LOG_DEBUG, "Trying V4L2 devices: %s,%s\n", ++ decdev_media_path(decdev), decdev_video_path(decdev)); ++ ++ if ((ctx->pq = pollqueue_new()) == NULL) { ++ av_log(avctx, AV_LOG_ERROR, "Unable to create pollqueue\n"); ++ goto fail1; ++ } ++ ++ if ((ctx->mpool = media_pool_new(decdev_media_path(decdev), ctx->pq, 4)) == NULL) { ++ av_log(avctx, AV_LOG_ERROR, "Unable to create media pool\n"); ++ goto fail2; ++ } ++ ++ if ((ctx->mbufs = mediabufs_ctl_new(avctx, decdev_video_path(decdev), ctx->pq)) == NULL) { ++ av_log(avctx, AV_LOG_ERROR, "Unable to create media controls\n"); ++ goto fail3; ++ } ++ ++ // Version test for functional Pi5 HEVC iommu. ++ // rpivid kernel patch was merged in 6.1.57 ++ // *** Remove when it is unlikely that there are any broken kernels left ++ if (mediabufs_ctl_driver_version(ctx->mbufs) >= MEDIABUFS_DRIVER_VERSION(6,1,57)) ++ ctx->dbufs = dmabufs_ctl_new_vidbuf_cached(); ++ else ++ ctx->dbufs = dmabufs_ctl_new(); ++ ++ if (ctx->dbufs == NULL) { ++ av_log(avctx, AV_LOG_DEBUG, "Unable to open dmabufs - try mmap buffers\n"); ++ src_memtype = MEDIABUFS_MEMORY_MMAP; ++ dst_memtype = MEDIABUFS_MEMORY_MMAP; ++ } ++ else { ++ av_log(avctx, AV_LOG_DEBUG, "Dmabufs opened - try dmabuf buffers\n"); ++ src_memtype = MEDIABUFS_MEMORY_DMABUF; ++ dst_memtype = MEDIABUFS_MEMORY_DMABUF; ++ } ++ ++ // Ask for an initial bitbuf size of max size / 4 ++ // We will realloc if we need more ++ // Must use sps->h/w as avctx contains cropped size ++retry_src_memtype: ++ src_size = bit_buf_size(width, height, bit_depth - 8); ++ if (src_memtype == MEDIABUFS_MEMORY_DMABUF && mediabufs_src_resizable(ctx->mbufs)) ++ src_size /= 4; ++ // Kludge for conformance tests which break Annex A limits ++ else if (src_size < 0x40000) ++ src_size = 0x40000; ++ ++ if (mediabufs_src_fmt_set(ctx->mbufs, decdev_src_type(decdev), src_pix_fmt, ++ width, height, src_size)) { ++ char tbuf1[5]; ++ av_log(avctx, AV_LOG_ERROR, "Failed to set source format: %s %dx%d\n", strfourcc(tbuf1, src_pix_fmt), width, height); ++ goto fail4; ++ } ++ ++ if (mediabufs_src_chk_memtype(ctx->mbufs, src_memtype)) { ++ if (src_memtype == MEDIABUFS_MEMORY_DMABUF) { ++ src_memtype = MEDIABUFS_MEMORY_MMAP; ++ goto retry_src_memtype; ++ } ++ av_log(avctx, AV_LOG_ERROR, "Failed to get src memory type\n"); ++ goto fail4; ++ } ++ ++ for (const struct v4l2_req_decode_fns * const * tf = try_fns; (ctx->fns = *tf) != NULL; ++tf) ++ if (ctx->fns->probe(avctx, ctx) == 0) ++ break; ++ if (ctx->fns == NULL) { ++ av_log(avctx, AV_LOG_ERROR, "No %s version probed successfully\n", try_fns[0]->name); ++ ret = AVERROR(EINVAL); ++ goto fail4; ++ } ++ av_log(avctx, AV_LOG_DEBUG, "%s probed successfully: driver v %#x\n", ++ ctx->fns->name, mediabufs_ctl_driver_version(ctx->mbufs)); ++ ++ if (mediabufs_dst_fmt_set(ctx->mbufs, width, height, dst_fmt_accept_cb, (void*)&bit_depth)) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to set destination format: %dx%d %dbit\n", width, height, bit_depth); ++ goto fail4; ++ } ++ ++ if (mediabufs_src_pool_create(ctx->mbufs, ctx->dbufs, 6, src_memtype)) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to create source pool\n"); ++ goto fail4; ++ } ++ ++ { ++ unsigned int dst_slots = dst_buffers + ++ avctx->thread_count + (avctx->extra_hw_frames > 0 ? avctx->extra_hw_frames : 6); ++ av_log(avctx, AV_LOG_DEBUG, "Slots=%d: Reordering=%d, threads=%d, hw+=%d\n", dst_slots, ++ dst_buffers, ++ avctx->thread_count, avctx->extra_hw_frames); ++ ++ if (mediabufs_dst_chk_memtype(ctx->mbufs, dst_memtype)) { ++ if (dst_memtype != MEDIABUFS_MEMORY_DMABUF) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to get dst memory type\n"); ++ goto fail4; ++ } ++ av_log(avctx, AV_LOG_DEBUG, "Dst DMABUF not supported - trying mmap\n"); ++ dst_memtype = MEDIABUFS_MEMORY_MMAP; ++ } ++ ++ // extra_hw_frames is -1 if unset ++ if (mediabufs_dst_slots_create(ctx->mbufs, dst_slots, (avctx->extra_hw_frames > 0), dst_memtype)) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to create destination slots\n"); ++ goto fail4; ++ } ++ } ++ ++ if (mediabufs_stream_on(ctx->mbufs)) { ++ av_log(avctx, AV_LOG_ERROR, "Failed stream on\n"); ++ goto fail4; ++ } ++ ++ if ((ret = ff_decode_get_hw_frames_ctx(avctx, AV_HWDEVICE_TYPE_DRM)) != 0) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to create frame ctx\n"); ++ goto fail4; ++ } ++ ++ if ((ret = ctx->fns->set_controls(avctx, ctx)) != 0) { ++ av_log(avctx, AV_LOG_ERROR, "Failed set controls\n"); ++ goto fail5; ++ } ++ ++ // Set our s/w format ++ avctx->sw_pix_fmt = ((AVHWFramesContext *)avctx->hw_frames_ctx->data)->sw_format; ++ ++ av_log(avctx, AV_LOG_INFO, "Hwaccel %s; devices: %s,%s; buffers: src %s, dst %s; swfmt=%s\n", ++ ctx->fns->name, ++ decdev_media_path(decdev), decdev_video_path(decdev), ++ mediabufs_memory_name(src_memtype), mediabufs_memory_name(dst_memtype), ++ av_get_pix_fmt_name(avctx->sw_pix_fmt)); ++ ++ return 0; ++ ++fail5: ++ av_buffer_unref(&avctx->hw_frames_ctx); ++fail4: ++fail3: ++fail2: ++fail1: ++fail0: ++ priv->cctx = NULL; ++ av_buffer_unref(&priv->cctx_buf); ++ return ret; ++} ++ ++int ++ff_v4l2_request_update_thread_context(AVCodecContext *dst, const AVCodecContext *src) ++{ ++ V4L2RequestPrivHEVC * const spriv = src->internal->hwaccel_priv_data; ++ V4L2RequestPrivHEVC * const dpriv = dst->internal->hwaccel_priv_data; ++ int rv; ++ ++ av_log(dst, AV_LOG_DEBUG, "<<< %s (%s)\n", __func__, dpriv->cctx_buf ? "old" : "new"); ++ ++ if ((rv = av_buffer_replace(&dpriv->cctx_buf, spriv->cctx_buf)) != 0) ++ return rv; ++ ++ dpriv->cctx = spriv->cctx; ++ return 0; ++} ++ ++void ++ff_v4l2_request_free_frame_priv(FFRefStructOpaque hwctx, void *data) ++{ ++} ++ ++static int v4l2_request_hevc_init(AVCodecContext *avctx) ++{ ++ const HEVCContext *h = avctx->priv_data; ++ const HEVCPPS * const pps = h->pps; ++ const HEVCSPS * const sps = pps->sps; ++ ++ const struct v4l2_req_decode_fns * const try_fns[] = { ++ &V2(ff_v4l2_req_hevc, 4), ++#if CONFIG_V4L2_REQ_HEVC_VX ++ &V2(ff_v4l2_req_hevc, 3), ++ &V2(ff_v4l2_req_hevc, 2), ++ &V2(ff_v4l2_req_hevc, 1), ++#endif ++ NULL ++ }; ++ ++ // Give up immediately if this is something that we have no code to deal with ++ if (sps->chroma_format_idc != 1) { ++ av_log(avctx, AV_LOG_WARNING, "chroma_format_idc(%d) != 1: Not implemented\n", sps->chroma_format_idc); ++ return AVERROR_PATCHWELCOME; ++ } ++ if (!(sps->bit_depth == 10 || sps->bit_depth == 8) || ++ sps->bit_depth != sps->bit_depth_chroma) { ++ av_log(avctx, AV_LOG_WARNING, "Bit depth Y:%d C:%d: Not implemented\n", sps->bit_depth, sps->bit_depth_chroma); ++ return AVERROR_PATCHWELCOME; ++ } ++ ++ return ff_v4l2_request_init(avctx, try_fns, sps->width, sps->height, sps->bit_depth, ++ sps->temporal_layer[sps->max_sub_layers - 1].max_dec_pic_buffering); ++} ++ ++const FFHWAccel ff_hevc_v4l2request_hwaccel = { ++ .p = { ++ .name = "hevc_v4l2request", ++ .type = AVMEDIA_TYPE_VIDEO, ++ .id = AV_CODEC_ID_HEVC, ++ .pix_fmt = AV_PIX_FMT_DRM_PRIME, ++ }, ++ .alloc_frame = ff_v4l2_request_alloc_frame, ++ .start_frame = ff_v4l2_request_start_frame, ++ .decode_slice = ff_v4l2_request_decode_slice, ++ .end_frame = ff_v4l2_request_end_frame, ++ .abort_frame = ff_v4l2_request_abort_frame, ++ .init = v4l2_request_hevc_init, ++ .uninit = ff_v4l2_request_uninit, ++ .free_frame_priv = ff_v4l2_request_free_frame_priv, ++ .frame_priv_data_size = 128, ++ .update_thread_context = ff_v4l2_request_update_thread_context, ++ .priv_data_size = sizeof(V4L2RequestPrivHEVC), ++ .frame_params = ff_v4l2_request_frame_params, ++ .caps_internal = HWACCEL_CAP_ASYNC_SAFE | HWACCEL_CAP_THREAD_SAFE, ++}; +diff --git a/libavcodec/v4l2_request_hevc.h b/libavcodec/v4l2_request_hevc.h +new file mode 100644 +index 000000000000..4c145feb37cc +--- /dev/null ++++ b/libavcodec/v4l2_request_hevc.h +@@ -0,0 +1,160 @@ ++/* ++ Copyright (C) 2024 John Cox john.cox@raspberrypi.com ++ ++ 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. ++ */ ++ ++#ifndef AVCODEC_V4L2_REQUEST_HEVC_H ++#define AVCODEC_V4L2_REQUEST_HEVC_H ++ ++#include ++#include ++ ++#include "refstruct.h" ++#include "v4l2_req_decode_q.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 ++ ++#ifndef V4L2_PIX_FMT_NV12_COL128M ++#define V4L2_PIX_FMT_NV12_COL128M v4l2_fourcc('N', 'c', '1', '2') /* 12 Y/CbCr 4:2:0 128 pixel wide column */ ++#define V4L2_PIX_FMT_NV12_10_COL128M v4l2_fourcc('N', 'c', '3', '0') ++ /* Y/CbCr 4:2:0 10bpc, 3x10 packed as 4 bytes in ++ * a 128 bytes / 96 pixel wide column */ ++#endif ++ ++#include ++#ifndef V4L2_CID_CODEC_BASE ++#define V4L2_CID_CODEC_BASE V4L2_CID_MPEG_BASE ++#endif ++ ++// V4L2_PIX_FMT_NV12_10_COL128 and V4L2_PIX_FMT_NV12_COL128 should be defined ++// in drm_fourcc.h hopefully will be sometime in the future but until then... ++#ifndef V4L2_PIX_FMT_NV12_10_COL128 ++#define V4L2_PIX_FMT_NV12_10_COL128 v4l2_fourcc('N', 'C', '3', '0') ++#endif ++ ++#ifndef V4L2_PIX_FMT_NV12_COL128 ++#define V4L2_PIX_FMT_NV12_COL128 v4l2_fourcc('N', 'C', '1', '2') /* 12 Y/CbCr 4:2:0 128 pixel wide column */ ++#endif ++ ++#ifndef V4L2_CTRL_FLAG_DYNAMIC_ARRAY ++#define V4L2_CTRL_FLAG_DYNAMIC_ARRAY 0x0800 ++#endif ++ ++#define VCAT(name, version) name##_v##version ++#define V2(n,v) VCAT(n, v) ++#define V(n) V2(n, HEVC_CTRLS_VERSION) ++ ++#define S2(x) #x ++#define STR(x) S2(x) ++ ++// 1 per decoder ++struct v4l2_req_decode_fns; ++ ++typedef struct V4L2RequestContextHEVC { ++// V4L2RequestContext base; ++ const struct v4l2_req_decode_fns * fns; ++ ++ unsigned int timestamp; // ?? maybe uint64_t ++ ++ int decode_mode; ++ int start_code; ++ unsigned int max_slices; // 0 => not wanted (frame mode) ++ unsigned int max_offsets; // 0 => not wanted ++ ++ req_decode_q decode_q; ++ ++ struct devscan *devscan; ++ struct dmabufs_ctl *dbufs; ++ struct pollqueue *pq; ++ struct media_pool * mpool; ++ struct mediabufs_ctl *mbufs; ++ ++ void * decode_ctx; ++} V4L2RequestContextHEVC; ++ ++typedef struct V4L2RequestPrivHEVC { ++ V4L2RequestContextHEVC * cctx; // Common context ++ AVBufferRef * cctx_buf; // Buf for cctx ++ int bit_depth; ++} V4L2RequestPrivHEVC; ++ ++typedef struct v4l2_req_decode_fns { ++ int src_pix_fmt_v4l2; ++ const char * name; ++ ++ // Init setup ++ int (*probe)(AVCodecContext * const avctx, V4L2RequestContextHEVC * const ctx); ++ // Set controls & any other init (e.g. decode_ctx) ++ int (*set_controls)(AVCodecContext * const avctx, V4L2RequestContextHEVC * const ctx); ++ ++ // Called on shutdown - avctx may not exist ++ void (*uninit)(V4L2RequestContextHEVC * const ctx); ++ ++ // Passthrough of hwaccel fns ++ int (*start_frame)(AVCodecContext *avctx, V4L2RequestContextHEVC *const ctx, const uint8_t *buf, uint32_t buf_size); ++ int (*decode_slice)(AVCodecContext *avctx, V4L2RequestContextHEVC *const ctx, const uint8_t *buf, uint32_t buf_size); ++ int (*end_frame)(AVCodecContext *avctx, V4L2RequestContextHEVC *const ctx); ++ void (*abort_frame)(AVCodecContext *avctx, V4L2RequestContextHEVC *const ctx); ++ int (*frame_params)(AVCodecContext *avctx, V4L2RequestContextHEVC *const ctx, AVBufferRef *hw_frames_ctx); ++ int (*alloc_frame)(AVCodecContext * avctx, V4L2RequestContextHEVC *const ctx, AVFrame *frame); ++} v4l2_req_decode_fns; ++ ++int ff_v4l2_request_start_frame(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size); ++int ff_v4l2_request_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size); ++int ff_v4l2_request_end_frame(AVCodecContext *avctx); ++void ff_v4l2_request_abort_frame(AVCodecContext * const avctx); ++int ff_v4l2_request_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx); ++int ff_v4l2_request_alloc_frame(AVCodecContext * avctx, AVFrame *frame); ++int ff_v4l2_request_init(AVCodecContext *avctx, ++ const struct v4l2_req_decode_fns * const * const try_fns, ++ const int width, const int height, const int bit_depth, ++ const int dst_buffers); ++int ff_v4l2_request_uninit(AVCodecContext *avctx); ++int ff_v4l2_request_update_thread_context(AVCodecContext *dst, const AVCodecContext *src); ++void ff_v4l2_request_free_frame_priv(FFRefStructOpaque hwctx, void *data); ++ ++extern const v4l2_req_decode_fns V2(ff_v4l2_req_hevc, 1); ++extern const v4l2_req_decode_fns V2(ff_v4l2_req_hevc, 2); ++extern const v4l2_req_decode_fns V2(ff_v4l2_req_hevc, 3); ++extern const v4l2_req_decode_fns V2(ff_v4l2_req_hevc, 4); ++ ++#endif +diff --git a/libavcodec/weak_link.c b/libavcodec/weak_link.c +new file mode 100644 +index 000000000000..71f6cc356720 +--- /dev/null ++++ b/libavcodec/weak_link.c +@@ -0,0 +1,127 @@ ++/* ++ Copyright (C) 2024 John Cox john.cox@raspberrypi.com ++ ++ 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. ++ */ ++ ++#include ++#include ++#include ++#include "weak_link.h" ++ ++struct ff_weak_link_master { ++ atomic_int ref_count; /* 0 is single ref for easier atomics */ ++ pthread_rwlock_t lock; ++ void * ptr; ++}; ++ ++static inline struct ff_weak_link_master * weak_link_x(struct ff_weak_link_client * c) ++{ ++ return (struct ff_weak_link_master *)c; ++} ++ ++struct ff_weak_link_master * ff_weak_link_new(void * p) ++{ ++ struct ff_weak_link_master * w = malloc(sizeof(*w)); ++ if (!w) ++ return NULL; ++ atomic_init(&w->ref_count, 0); ++ w->ptr = p; ++ if (pthread_rwlock_init(&w->lock, NULL)) { ++ free(w); ++ return NULL; ++ } ++ return w; ++} ++ ++static void weak_link_do_unref(struct ff_weak_link_master * const w) ++{ ++ int n = atomic_fetch_sub(&w->ref_count, 1); ++ if (n) ++ return; ++ ++ pthread_rwlock_destroy(&w->lock); ++ free(w); ++} ++ ++// Unref & break link ++void ff_weak_link_break(struct ff_weak_link_master ** ppLink) ++{ ++ struct ff_weak_link_master * const w = *ppLink; ++ if (!w) ++ return; ++ ++ *ppLink = NULL; ++ pthread_rwlock_wrlock(&w->lock); ++ w->ptr = NULL; ++ pthread_rwlock_unlock(&w->lock); ++ ++ weak_link_do_unref(w); ++} ++ ++struct ff_weak_link_client* ff_weak_link_ref(struct ff_weak_link_master * w) ++{ ++ if (!w) ++ return NULL; ++ atomic_fetch_add(&w->ref_count, 1); ++ return (struct ff_weak_link_client*)w; ++} ++ ++void ff_weak_link_unref(struct ff_weak_link_client ** ppLink) ++{ ++ struct ff_weak_link_master * const w = weak_link_x(*ppLink); ++ if (!w) ++ return; ++ ++ *ppLink = NULL; ++ weak_link_do_unref(w); ++} ++ ++void * ff_weak_link_lock(struct ff_weak_link_client ** ppLink) ++{ ++ struct ff_weak_link_master * const w = weak_link_x(*ppLink); ++ ++ if (!w) ++ return NULL; ++ ++ if (pthread_rwlock_rdlock(&w->lock)) ++ goto broken; ++ ++ if (w->ptr) ++ return w->ptr; ++ ++ pthread_rwlock_unlock(&w->lock); ++ ++broken: ++ *ppLink = NULL; ++ weak_link_do_unref(w); ++ return NULL; ++} ++ ++// Ignores a NULL c (so can be on the return path of both broken & live links) ++void ff_weak_link_unlock(struct ff_weak_link_client * c) ++{ ++ struct ff_weak_link_master * const w = weak_link_x(c); ++ if (w) ++ pthread_rwlock_unlock(&w->lock); ++} ++ ++ +diff --git a/libavcodec/weak_link.h b/libavcodec/weak_link.h +new file mode 100644 +index 000000000000..5c66b29f9b61 +--- /dev/null ++++ b/libavcodec/weak_link.h +@@ -0,0 +1,46 @@ ++/* ++ Copyright (C) 2024 John Cox john.cox@raspberrypi.com ++ ++ 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. ++ */ ++ ++#ifndef AVCODEC_WEAK_LINK_H ++#define AVCODEC_WEAK_LINK_H ++ ++struct ff_weak_link_master; ++struct ff_weak_link_client; ++ ++struct ff_weak_link_master * ff_weak_link_new(void * p); ++void ff_weak_link_break(struct ff_weak_link_master ** ppLink); ++ ++struct ff_weak_link_client* ff_weak_link_ref(struct ff_weak_link_master * w); ++void ff_weak_link_unref(struct ff_weak_link_client ** ppLink); ++ ++// Returns NULL if link broken - in this case it will also zap ++// *ppLink and unref the weak_link. ++// Returns NULL if *ppLink is NULL (so a link once broken stays broken) ++// ++// The above does mean that there is a race if this is called simultainiously ++// by two threads using the same weak_link_client (so don't do that) ++void * ff_weak_link_lock(struct ff_weak_link_client ** ppLink); ++void ff_weak_link_unlock(struct ff_weak_link_client * c); ++ ++#endif +diff --git a/libavdevice/Makefile b/libavdevice/Makefile +index c30449201d47..d39dadb1dee1 100644 +--- a/libavdevice/Makefile ++++ b/libavdevice/Makefile +@@ -48,6 +48,8 @@ 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_VFWCAP_INDEV) += vfwcap.o ++OBJS-$(CONFIG_VOUT_DRM_OUTDEV) += drm_vout.o ++OBJS-$(CONFIG_VOUT_EGL_OUTDEV) += egl_vout.o + OBJS-$(CONFIG_XCBGRAB_INDEV) += xcbgrab.o + OBJS-$(CONFIG_XV_OUTDEV) += xv.o + +diff --git a/libavdevice/alldevices.c b/libavdevice/alldevices.c +index 9b9a9146c7d7..1b68c16e4f19 100644 +--- a/libavdevice/alldevices.c ++++ b/libavdevice/alldevices.c +@@ -56,6 +56,8 @@ extern const FFOutputFormat ff_sndio_muxer; + extern const FFInputFormat ff_v4l2_demuxer; + extern const FFOutputFormat ff_v4l2_muxer; + extern const FFInputFormat ff_vfwcap_demuxer; ++extern const FFOutputFormat ff_vout_drm_muxer; ++extern const FFOutputFormat ff_vout_egl_muxer; + extern const FFInputFormat ff_xcbgrab_demuxer; + extern const FFOutputFormat ff_xv_muxer; + +diff --git a/libavdevice/drm_vout.c b/libavdevice/drm_vout.c +new file mode 100644 +index 000000000000..6d11e98d7521 +--- /dev/null ++++ b/libavdevice/drm_vout.c +@@ -0,0 +1,684 @@ ++/* ++ * 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. ++ ++#include "libavutil/opt.h" ++#include "libavutil/frame.h" ++#include "libavutil/pixdesc.h" ++#include "libavutil/hwcontext.h" ++#include "libavutil/hwcontext_drm.h" ++#include "libavformat/mux.h" ++#include "avdevice.h" ++ ++#include "pthread.h" ++#include ++#include ++ ++#include ++#include ++#include ++ ++#define TRACE_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 { ++ unsigned int fb_handle; ++ uint32_t bo_handles[AV_DRM_MAX_PLANES]; ++ AVFrame * frame; ++} drm_aux_t; ++ ++// Aux size should only need to be 2, but on a few streams (Hobbit) under FKMS ++// we get initial flicker probably due to dodgy drm timing ++#define AUX_SIZE 3 ++typedef struct drm_display_env_s ++{ ++ AVClass *class; ++ ++ int drm_fd; ++ uint32_t con_id; ++ struct drm_setup setup; ++ enum AVPixelFormat avfmt; ++ ++ int show_all; ++ const char * drm_module; ++ ++ unsigned int ano; ++ drm_aux_t aux[AUX_SIZE]; ++ ++ pthread_t q_thread; ++ sem_t q_sem_in; ++ sem_t q_sem_out; ++ int q_terminate; ++ AVFrame * q_next; ++ ++} drm_display_env_t; ++ ++ ++static int drm_vout_write_trailer(AVFormatContext *s) ++{ ++#if TRACE_ALL ++ av_log(s, AV_LOG_DEBUG, "%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_DEBUG, "%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 find_plane(struct AVFormatContext * const avctx, ++ const int drmfd, const int crtcidx, const uint32_t format, ++ uint32_t * const pplane_id) ++{ ++ drmModePlaneResPtr planes; ++ drmModePlanePtr plane; ++ drmModeObjectPropertiesPtr props = NULL; ++ drmModePropertyPtr prop = NULL; ++ unsigned int i; ++ unsigned int j; ++ int ret = -1; ++ ++ 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 << crtcidx))) { ++ drmModeFreePlane(plane); ++ continue; ++ } ++ ++ for (j = 0; j < plane->count_formats; ++j) { ++ if (plane->formats[j] == format) ++ break; ++ } ++ ++ if (j == plane->count_formats) { ++ drmModeFreePlane(plane); ++ continue; ++ } ++ ++ *pplane_id = plane->plane_id; ++ drmModeFreePlane(plane); ++ break; ++ } ++ ++ if (i == planes->count_planes) { ++ ret = -1; ++ goto fail; ++ } ++ ++ props = drmModeObjectGetProperties(drmfd, *pplane_id, DRM_MODE_OBJECT_PLANE); ++ if (!props) ++ goto fail; ++ for (i = 0; i != props->count_props; ++i) { ++ if (prop) ++ drmModeFreeProperty(prop); ++ prop = drmModeGetProperty(drmfd, props->props[i]); ++ if (!prop) ++ goto fail; ++ if (strcmp("zpos", prop->name) == 0) { ++ if (drmModeObjectSetProperty(drmfd, *pplane_id, DRM_MODE_OBJECT_PLANE, props->props[i], prop->values[1]) == 0) ++ av_log(avctx, AV_LOG_DEBUG, "ZPOS set to %d\n", (int)prop->values[1]); ++ else ++ av_log(avctx, AV_LOG_WARNING, "Failed to set ZPOS on DRM plane\n"); ++ break; ++ } ++ } ++ ++ ret = 0; ++fail: ++ if (props) ++ drmModeFreeObjectProperties(props); ++ if (prop) ++ drmModeFreeProperty(prop); ++ drmModeFreePlaneResources(planes); ++ return ret; ++} ++ ++static void da_uninit(drm_display_env_t * const de, drm_aux_t * da) ++{ ++ if (da->fb_handle != 0) { ++ drmModeRmFB(de->drm_fd, da->fb_handle); ++ da->fb_handle = 0; ++ } ++ ++ for (unsigned int i = 0; i != AV_DRM_MAX_PLANES; ++i) { ++ if (da->bo_handles[i]) { ++ struct drm_gem_close gem_close = {.handle = da->bo_handles[i]}; ++ drmIoctl(de->drm_fd, DRM_IOCTL_GEM_CLOSE, &gem_close); ++ da->bo_handles[i] = 0; ++ } ++ } ++ av_frame_free(&da->frame); ++} ++ ++static int do_display(AVFormatContext * const s, drm_display_env_t * const de, AVFrame * frame) ++{ ++ const AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor*)frame->data[0]; ++ drm_aux_t * da = de->aux + de->ano; ++ const uint32_t format = desc->layers[0].format; ++ int ret = 0; ++ ++#if TRACE_ALL ++ av_log(s, AV_LOG_DEBUG, "<<< %s: fd=%d\n", __func__, desc->objects[0].fd); ++#endif ++ ++ if (de->setup.out_fourcc != format) { ++ if (find_plane(s, de->drm_fd, de->setup.crtcIdx, format, &de->setup.planeId)) { ++ av_frame_free(&frame); ++ av_log(s, AV_LOG_WARNING, "No plane for format: %#x\n", format); ++ return -1; ++ } ++ de->setup.out_fourcc = format; ++ } ++ ++ { ++ drmVBlank vbl = { ++ .request = { ++ .type = DRM_VBLANK_RELATIVE, ++ .sequence = 0 ++ } ++ }; ++ ++ while (drmWaitVBlank(de->drm_fd, &vbl)) { ++ if (errno != EINTR) { ++// av_log(s, AV_LOG_WARNING, "drmWaitVBlank failed: %s\n", ERRSTR); ++ break; ++ } ++ } ++ } ++ ++ da_uninit(de, da); ++ ++ { ++ uint32_t pitches[4] = {0}; ++ uint32_t offsets[4] = {0}; ++ uint64_t modifiers[4] = {0}; ++ uint32_t bo_handles[4] = {0}; ++ int has_mods = 0; ++ int i, j, n; ++ ++ da->frame = frame; ++ ++ 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[%d](%d) failed: %s\n", i, desc->objects[i].fd, ERRSTR); ++ return -1; ++ } ++ if (desc->objects[i].format_modifier != DRM_FORMAT_MOD_LINEAR && ++ desc->objects[i].format_modifier != DRM_FORMAT_MOD_INVALID) ++ has_mods = 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_handles[n] = da->bo_handles[p->object_index]; ++ ++n; ++ } ++ } ++ ++#if 1 && TRACE_ALL ++ av_log(s, AV_LOG_DEBUG, "%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_handles[0], ++ bo_handles[1], ++ bo_handles[2], ++ bo_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_handles, ++ pitches, offsets, ++ has_mods ? modifiers : NULL, ++ &da->fb_handle, ++ has_mods ? DRM_MODE_FB_MODIFIERS : 0) != 0) { ++ av_log(s, AV_LOG_WARNING, "drmModeAddFB2WithModifiers failed: %s\n", ERRSTR); ++ return -1; ++ } ++ } ++ ++ 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); ++ } ++ ++ de->ano = de->ano + 1 >= AUX_SIZE ? 0 : de->ano + 1; ++ ++ return ret; ++} ++ ++static int do_sem_wait(sem_t * const sem, const int nowait) ++{ ++ while (nowait ? sem_trywait(sem) : sem_wait(sem)) { ++ if (errno != EINTR) ++ return -errno; ++ } ++ return 0; ++} ++ ++static void * display_thread(void * v) ++{ ++ AVFormatContext * const s = v; ++ drm_display_env_t * const de = s->priv_data; ++ int i; ++ ++#if TRACE_ALL ++ av_log(s, AV_LOG_DEBUG, "<<< %s\n", __func__); ++#endif ++ ++ sem_post(&de->q_sem_out); ++ ++ for (;;) { ++ AVFrame * frame; ++ ++ do_sem_wait(&de->q_sem_in, 0); ++ ++ if (de->q_terminate) ++ break; ++ ++ frame = de->q_next; ++ de->q_next = NULL; ++ sem_post(&de->q_sem_out); ++ ++ do_display(s, de, frame); ++ } ++ ++#if TRACE_ALL ++ av_log(s, AV_LOG_DEBUG, ">>> %s\n", __func__); ++#endif ++ ++ for (i = 0; i != AUX_SIZE; ++i) ++ da_uninit(de, de->aux + i); ++ ++ av_frame_free(&de->q_next); ++ ++ 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; ++ int ret; ++ ++#if TRACE_ALL ++ av_log(s, AV_LOG_DEBUG, "%s\n", __func__); ++#endif ++ ++ if ((src_frame->flags & AV_FRAME_FLAG_CORRUPT) != 0) { ++ av_log(s, AV_LOG_WARNING, "Discard corrupt frame: fmt=%d, 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); ++ } ++ ++ ret = do_sem_wait(&de->q_sem_out, !de->show_all); ++ if (ret) { ++ av_frame_free(&frame); ++ } ++ else { ++ de->q_next = frame; ++ sem_post(&de->q_sem_in); ++ } ++ ++ return 0; ++} ++ ++static int drm_vout_write_frame(AVFormatContext *s, int stream_index, AVFrame **ppframe, ++ unsigned flags) ++{ ++ av_log(s, AV_LOG_ERROR, "%s: NIF: idx=%d, flags=%#x\n", __func__, stream_index, flags); ++ return AVERROR_PATCHWELCOME; ++} ++ ++static int drm_vout_control_message(AVFormatContext *s, int type, void *data, size_t data_size) ++{ ++#if TRACE_ALL ++ av_log(s, AV_LOG_DEBUG, "%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_DEBUG, "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 (crtc) ++ drmModeFreeCrtc(crtc); ++ if (enc) ++ drmModeFreeEncoder(enc); ++ if (con) ++ drmModeFreeConnector(con); ++ } ++ ++ 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; ++} ++ ++// 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; ++ int rv; ++ ++ av_log(s, AV_LOG_DEBUG, "<<< %s\n", __func__); ++ ++ de->drm_fd = -1; ++ de->con_id = 0; ++ de->setup = (struct drm_setup){0}; ++ de->q_terminate = 0; ++ ++ if ((de->drm_fd = drmOpen(de->drm_module, NULL)) < 0) ++ { ++ rv = AVERROR(errno); ++ av_log(s, AV_LOG_ERROR, "Failed to drmOpen %s: %s\n", de->drm_module, av_err2str(rv)); ++ return rv; ++ } ++ ++ 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"); ++ rv = AVERROR(EINVAL); ++ goto fail_close; ++ } ++ ++ sem_init(&de->q_sem_in, 0, 0); ++ sem_init(&de->q_sem_out, 0, 0); ++ if (pthread_create(&de->q_thread, NULL, display_thread, s)) { ++ rv = AVERROR(errno); ++ av_log(s, AV_LOG_ERROR, "Failed to create display thread: %s\n", av_err2str(rv)); ++ goto fail_close; ++ } ++ ++ av_log(s, AV_LOG_DEBUG, ">>> %s\n", __func__); ++ ++ return 0; ++ ++fail_close: ++ close(de->drm_fd); ++ de->drm_fd = -1; ++ av_log(s, AV_LOG_DEBUG, ">>> %s: FAIL\n", __func__); ++ ++ return rv; ++} ++ ++static void drm_vout_deinit(struct AVFormatContext * s) ++{ ++ drm_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_in); ++ pthread_join(de->q_thread, NULL); ++ sem_destroy(&de->q_sem_in); ++ sem_destroy(&de->q_sem_out); ++ ++ for (unsigned int i = 0; i != AUX_SIZE; ++i) ++ da_uninit(de, de->aux + i); ++ ++ av_frame_free(&de->q_next); ++ ++ if (de->drm_fd >= 0) { ++ close(de->drm_fd); ++ de->drm_fd = -1; ++ } ++ ++ av_log(s, AV_LOG_DEBUG, ">>> %s\n", __func__); ++} ++ ++ ++#define OFFSET(x) offsetof(drm_display_env_t, x) ++static const AVOption options[] = { ++ { "show_all", "show all frames", OFFSET(show_all), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_ENCODING_PARAM }, ++ { "drm_module", "drm_module name to use, default=" DRM_MODULE, OFFSET(drm_module), AV_OPT_TYPE_STRING, { .str = DRM_MODULE }, 0, 0, AV_OPT_FLAG_ENCODING_PARAM }, ++ { 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, ++}; ++ ++FFOutputFormat ff_vout_drm_muxer = { ++ .p = { ++ .name = "vout_drm", ++ .long_name = NULL_IF_CONFIG_SMALL("Drm video output device"), ++ .audio_codec = AV_CODEC_ID_NONE, ++ .video_codec = AV_CODEC_ID_WRAPPED_AVFRAME, ++ .flags = AVFMT_NOFILE | AVFMT_VARIABLE_FPS | AVFMT_NOTIMESTAMPS, ++ .priv_class = &drm_vout_class, ++ }, ++ .priv_data_size = sizeof(drm_display_env_t), ++ .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, ++ .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 000000000000..0c8c629852fb +--- /dev/null ++++ b/libavdevice/egl_vout.c +@@ -0,0 +1,784 @@ ++/* ++ * 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.h" ++#include "libavutil/hwcontext_drm.h" ++#include "libavformat/mux.h" ++#include "avdevice.h" ++ ++#include "pthread.h" ++#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; ++ ++ int show_all; ++ int window_width, window_height; ++ int window_x, window_y; ++ int fullscreen; ++ ++ 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, ++ egl_display_env_t *const de, ++ Display *dpy, EGLDisplay egl_dpy, const char *name, ++ Window *winRet, EGLContext *ctxRet, EGLSurface *surfRet) ++{ ++ int scrnum = DefaultScreen(dpy); ++ XSetWindowAttributes attr; ++ unsigned long mask; ++ Window root = RootWindow(dpy, scrnum); ++ Window win; ++ EGLContext ctx; ++ const int fullscreen = de->fullscreen; ++ EGLConfig config; ++ int x = de->window_x; ++ int y = de->window_y; ++ int width = de->window_width ? de->window_width : 1280; ++ int height = de->window_height ? de->window_height : 720; ++ ++ ++ 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, (EGLNativeWindowType)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; ++ } ++ ++ 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); ++ ++ glDeleteTextures(1, &da->texture); ++ da->texture = 0; ++ da->fd = -1; ++ ++ 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 (!de->window_width || !de->window_height) { ++ de->window_width = 1280; ++ de->window_height = 720; ++ } ++ if (make_window(s, de, de->setup.dpy, de->setup.egl_dpy, "ffmpeg-vout", ++ &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); ++ } ++ ++ // Really hacky sync ++ while (de->show_all && de->q_next) { ++ usleep(3000); ++ } ++ ++ 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) ++{ ++ av_log(s, AV_LOG_ERROR, "%s: NIF: idx=%d, flags=%#x\n", __func__, stream_index, flags); ++ return AVERROR_PATCHWELCOME; ++} ++ ++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[] = { ++ { "show_all", "show all frames", OFFSET(show_all), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, 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_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 }, ++ { "fullscreen", "set fullscreen display", OFFSET(fullscreen), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_ENCODING_PARAM }, ++ { 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, ++}; ++ ++FFOutputFormat ff_vout_egl_muxer = { ++ .p = { ++ .name = "vout_egl", ++ .long_name = NULL_IF_CONFIG_SMALL("Egl video output device"), ++ .audio_codec = AV_CODEC_ID_NONE, ++ .video_codec = AV_CODEC_ID_WRAPPED_AVFRAME, ++ .flags = AVFMT_NOFILE | AVFMT_VARIABLE_FPS | AVFMT_NOTIMESTAMPS, ++ .priv_class = &egl_vout_class, ++ }, ++ .priv_data_size = sizeof(egl_display_env_t), ++ .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, ++ .init = egl_vout_init, ++ .deinit = egl_vout_deinit, ++}; ++ +diff --git a/libavfilter/Makefile b/libavfilter/Makefile +index 91487afb2185..6dd422a9358c 100644 +--- a/libavfilter/Makefile ++++ b/libavfilter/Makefile +@@ -272,6 +272,7 @@ OBJS-$(CONFIG_DEFLATE_FILTER) += vf_neighbor.o + OBJS-$(CONFIG_DEFLICKER_FILTER) += vf_deflicker.o + OBJS-$(CONFIG_DEINTERLACE_QSV_FILTER) += vf_vpp_qsv.o + OBJS-$(CONFIG_DEINTERLACE_VAAPI_FILTER) += vf_deinterlace_vaapi.o vaapi_vpp.o ++OBJS-$(CONFIG_DEINTERLACE_V4L2M2M_FILTER) += vf_deinterlace_v4l2m2m.o + OBJS-$(CONFIG_DEJUDDER_FILTER) += vf_dejudder.o + OBJS-$(CONFIG_DELOGO_FILTER) += vf_delogo.o + OBJS-$(CONFIG_DENOISE_VAAPI_FILTER) += vf_misc_vaapi.o vaapi_vpp.o +@@ -536,6 +537,7 @@ OBJS-$(CONFIG_TRANSPOSE_VT_FILTER) += vf_transpose_vt.o + OBJS-$(CONFIG_TRANSPOSE_VULKAN_FILTER) += vf_transpose_vulkan.o vulkan.o vulkan_filter.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 9819f0f95b7f..a4ef3091157d 100644 +--- a/libavfilter/allfilters.c ++++ b/libavfilter/allfilters.c +@@ -256,6 +256,7 @@ extern const AVFilter ff_vf_derain; + extern const AVFilter ff_vf_deshake; + extern const AVFilter ff_vf_deshake_opencl; + extern const AVFilter ff_vf_despill; ++extern const AVFilter ff_vf_deinterlace_v4l2m2m; + extern const AVFilter ff_vf_detelecine; + extern const AVFilter ff_vf_dilation; + extern const AVFilter ff_vf_dilation_opencl; +@@ -434,6 +435,7 @@ extern const AVFilter ff_vf_scale; + extern const AVFilter ff_vf_scale_cuda; + extern const AVFilter ff_vf_scale_npp; + extern const AVFilter ff_vf_scale_qsv; ++extern const AVFilter ff_vf_scale_v4l2m2m; + extern const AVFilter ff_vf_scale_vaapi; + extern const AVFilter ff_vf_scale_vt; + extern const AVFilter ff_vf_scale_vulkan; +@@ -507,6 +509,7 @@ extern const AVFilter ff_vf_trim; + extern const AVFilter ff_vf_unpremultiply; + extern const AVFilter ff_vf_unsharp; + extern const AVFilter ff_vf_unsharp_opencl; ++extern const AVFilter ff_vf_unsand; + extern const AVFilter ff_vf_untile; + extern const AVFilter ff_vf_uspp; + extern const AVFilter ff_vf_v360; +diff --git a/libavfilter/buffersink.c b/libavfilter/buffersink.c +index 5811720c61ff..13e1f3446585 100644 +--- a/libavfilter/buffersink.c ++++ b/libavfilter/buffersink.c +@@ -60,6 +60,11 @@ typedef struct BufferSinkContext { + int sample_rates_size; + + AVFrame *peeked_frame; ++ ++ union { ++ av_buffersink_alloc_video_frame * video; ++ } alloc_cb; ++ void * alloc_v; + } BufferSinkContext; + + #define NB_ITEMS(list) (list ## _size / sizeof(*list)) +@@ -129,6 +134,22 @@ int attribute_align_arg av_buffersink_get_samples(AVFilterContext *ctx, + return get_frame_internal(ctx, frame, 0, nb_samples); + } + ++static AVFrame * alloc_video_buffer(AVFilterLink *link, int w, int h) ++{ ++ AVFilterContext * const ctx = link->dst; ++ BufferSinkContext * const bs = ctx->priv; ++ return bs->alloc_cb.video ? bs->alloc_cb.video(ctx, bs->alloc_v, w, h) : ++ ff_default_get_video_buffer(link, w, h); ++} ++ ++int av_buffersink_set_alloc_video_frame(AVFilterContext *ctx, av_buffersink_alloc_video_frame * cb, void * v) ++{ ++ BufferSinkContext * const bs = ctx->priv; ++ bs->alloc_cb.video = cb; ++ bs->alloc_v = v; ++ return 0; ++} ++ + static av_cold int common_init(AVFilterContext *ctx) + { + BufferSinkContext *buf = ctx->priv; +@@ -355,6 +376,14 @@ static const AVOption abuffersink_options[] = { + AVFILTER_DEFINE_CLASS(buffersink); + AVFILTER_DEFINE_CLASS(abuffersink); + ++static const AVFilterPad avfilter_vsink_buffer_inputs[] = { ++ { ++ .name = "default", ++ .type = AVMEDIA_TYPE_VIDEO, ++ .get_buffer = {.video = alloc_video_buffer}, ++ }, ++}; ++ + const AVFilter ff_vsink_buffer = { + .name = "buffersink", + .description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them available to the end of the filter graph."), +@@ -363,7 +392,7 @@ const AVFilter ff_vsink_buffer = { + .init = common_init, + .uninit = uninit, + .activate = activate, +- FILTER_INPUTS(ff_video_default_filterpad), ++ FILTER_INPUTS(avfilter_vsink_buffer_inputs), + .outputs = NULL, + FILTER_QUERY_FUNC(vsink_query_formats), + }; +diff --git a/libavfilter/buffersink.h b/libavfilter/buffersink.h +index 361d60367933..47a296cf5edb 100644 +--- a/libavfilter/buffersink.h ++++ b/libavfilter/buffersink.h +@@ -166,6 +166,9 @@ int av_buffersink_get_frame(AVFilterContext *ctx, AVFrame *frame); + */ + int av_buffersink_get_samples(AVFilterContext *ctx, AVFrame *frame, int nb_samples); + ++typedef AVFrame * av_buffersink_alloc_video_frame(AVFilterContext * ctx, void * v, int w, int h); ++int av_buffersink_set_alloc_video_frame(AVFilterContext *ctx, av_buffersink_alloc_video_frame * cb, void * v); ++ + /** + * @} + */ +diff --git a/libavfilter/buffersrc.c b/libavfilter/buffersrc.c +index ec5898fcf92c..1545dbb06eb6 100644 +--- a/libavfilter/buffersrc.c ++++ b/libavfilter/buffersrc.c +@@ -210,7 +210,7 @@ int attribute_align_arg av_buffersrc_add_frame_flags(AVFilterContext *ctx, AVFra + + 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->colorspace, + frame->color_range, frame->pts); + break; +diff --git a/libavfilter/vf_bwdif.c b/libavfilter/vf_bwdif.c +index d41a25f8ea99..233b17a21bde 100644 +--- a/libavfilter/vf_bwdif.c ++++ b/libavfilter/vf_bwdif.c +@@ -115,19 +115,28 @@ static void filter(AVFilterContext *ctx, AVFrame *dstpic, + YADIFContext *yadif = &bwdif->yadif; + ThreadData td = { .frame = dstpic, .parity = parity, .tff = tff }; + int i; ++ int last_plane = -1; + + for (i = 0; i < yadif->csp->nb_components; i++) { + int w = dstpic->width; + int h = dstpic->height; ++ const AVComponentDescriptor * const comp = yadif->csp->comp + i; ++ ++ // If the last plane was the same as this plane assume we've dealt ++ // with all the pels already ++ if (last_plane == comp->plane) ++ continue; ++ last_plane = comp->plane; + + if (i == 1 || i == 2) { + w = AV_CEIL_RSHIFT(w, yadif->csp->log2_chroma_w); + h = AV_CEIL_RSHIFT(h, yadif->csp->log2_chroma_h); + } + +- td.w = w; +- td.h = h; +- td.plane = i; ++ // comp step is in bytes but td.w is in pels ++ td.w = w * comp->step / ((comp->depth + 7) / 8); ++ td.h = h; ++ td.plane = comp->plane; + + ff_filter_execute(ctx, filter_slice, &td, NULL, + FFMIN((h+3)/4, ff_filter_get_nb_threads(ctx))); +@@ -151,6 +160,7 @@ static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9, + AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10, + AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16, ++ AV_PIX_FMT_NV12, + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, + AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, + AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP16, +diff --git a/libavfilter/vf_deinterlace_v4l2m2m.c b/libavfilter/vf_deinterlace_v4l2m2m.c +new file mode 100644 +index 000000000000..a5f3a776f824 +--- /dev/null ++++ b/libavfilter/vf_deinterlace_v4l2m2m.c +@@ -0,0 +1,2120 @@ ++/* ++ * 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 ++ * deinterlace video filter - V4L2 M2M ++ */ ++ ++#include ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "config.h" ++ ++#include "libavutil/avassert.h" ++#include "libavutil/avstring.h" ++#include "libavutil/common.h" ++#include "libavutil/hwcontext.h" ++#include "libavutil/hwcontext_drm.h" ++#include "libavutil/internal.h" ++#include "libavutil/mathematics.h" ++#include "libavutil/mem.h" ++#include "libavutil/opt.h" ++#include "libavutil/pixdesc.h" ++#include "libavutil/time.h" ++ ++#define FF_INTERNAL_FIELDS 1 ++#include "framequeue.h" ++#include "filters.h" ++#include "avfilter.h" ++#include "formats.h" ++#include "scale_eval.h" ++#include "video.h" ++ ++#ifndef DRM_FORMAT_P030 ++#define DRM_FORMAT_P030 fourcc_code('P', '0', '3', '0') /* 2x2 subsampled Cr:Cb plane 10 bits per channel packed */ ++#endif ++ ++// V4L2_PIX_FMT_NV12_10_COL128 and V4L2_PIX_FMT_NV12_COL128 should be defined ++// in drm_fourcc.h hopefully will be sometime in the future but until then... ++#ifndef V4L2_PIX_FMT_NV12_10_COL128 ++#define V4L2_PIX_FMT_NV12_10_COL128 v4l2_fourcc('N', 'C', '3', '0') ++#endif ++ ++#ifndef V4L2_PIX_FMT_NV12_COL128 ++#define V4L2_PIX_FMT_NV12_COL128 v4l2_fourcc('N', 'C', '1', '2') /* 12 Y/CbCr 4:2:0 128 pixel wide column */ ++#endif ++ ++typedef struct V4L2Queue V4L2Queue; ++typedef struct DeintV4L2M2MContextShared DeintV4L2M2MContextShared; ++ ++typedef enum filter_type_v4l2_e ++{ ++ FILTER_V4L2_DEINTERLACE = 1, ++ FILTER_V4L2_SCALE, ++} filter_type_v4l2_t; ++ ++typedef struct V4L2Buffer { ++ int enqueued; ++ int reenqueue; ++ struct v4l2_buffer buffer; ++ AVFrame frame; ++ struct v4l2_plane planes[VIDEO_MAX_PLANES]; ++ int num_planes; ++ AVDRMFrameDescriptor drm_frame; ++ V4L2Queue *q; ++} V4L2Buffer; ++ ++typedef struct V4L2Queue { ++ struct v4l2_format format; ++ struct v4l2_selection sel; ++ int eos; ++ int num_buffers; ++ V4L2Buffer *buffers; ++ const char * name; ++ DeintV4L2M2MContextShared *ctx; ++} V4L2Queue; ++ ++typedef struct pts_stats_s ++{ ++ void * logctx; ++ const char * name; // For debug ++ unsigned int last_count; ++ unsigned int last_interval; ++ int64_t last_pts; ++} pts_stats_t; ++ ++#define PTS_TRACK_SIZE 32 ++typedef struct pts_track_el_s ++{ ++ uint32_t n; ++ unsigned int interval; ++ AVFrame * props; ++} pts_track_el_t; ++ ++typedef struct pts_track_s ++{ ++ uint32_t n; ++ uint32_t last_n; ++ int got_2; ++ void * logctx; ++ pts_stats_t stats; ++ pts_track_el_t a[PTS_TRACK_SIZE]; ++} pts_track_t; ++ ++typedef enum drain_state_e ++{ ++ DRAIN_NONE = 0, // Not draining ++ DRAIN_TIMEOUT, // Drain until normal timeout setup yields no frame ++ DRAIN_LAST, // Drain with long timeout last_frame in received on output expected ++ DRAIN_EOS, // Drain with long timeout EOS expected ++ DRAIN_DONE // Drained ++} drain_state_t; ++ ++typedef struct DeintV4L2M2MContextShared { ++ void * logctx; // For logging - will be NULL when done ++ filter_type_v4l2_t filter_type; ++ ++ int fd; ++ int done; // fd closed - awating all refs dropped ++ int width; ++ int height; ++ ++ int drain; // EOS received (inlink status) ++ drain_state_t drain_state; ++ int64_t drain_pts; // PTS associated with inline status ++ ++ unsigned int frames_rx; ++ unsigned int frames_tx; ++ ++ // from options ++ int output_width; ++ int output_height; ++ enum AVPixelFormat output_format; ++ ++ int has_enc_stop; ++ // We expect to get exactly the same number of frames out as we put in ++ // We can drain by matching input to output ++ int one_to_one; ++ ++ int orig_width; ++ int orig_height; ++ atomic_uint refcount; ++ ++ AVBufferRef *hw_frames_ctx; ++ ++ unsigned int field_order; ++ ++ pts_track_t track; ++ ++ V4L2Queue output; ++ V4L2Queue capture; ++} DeintV4L2M2MContextShared; ++ ++typedef struct DeintV4L2M2MContext { ++ const AVClass *class; ++ ++ DeintV4L2M2MContextShared *shared; ++ ++ char * w_expr; ++ char * h_expr; ++ char * output_format_string;; ++ ++ int force_original_aspect_ratio; ++ int force_divisible_by; ++ ++ char *colour_primaries_string; ++ char *colour_transfer_string; ++ char *colour_matrix_string; ++ int colour_range; ++ char *chroma_location_string; ++ ++ enum AVColorPrimaries colour_primaries; ++ enum AVColorTransferCharacteristic colour_transfer; ++ enum AVColorSpace colour_matrix; ++ enum AVChromaLocation chroma_location; ++} DeintV4L2M2MContext; ++ ++ ++static inline void frame_set_progressive(AVFrame* frame) ++{ ++#if FF_API_INTERLACED_FRAME ++FF_DISABLE_DEPRECATION_WARNINGS ++ frame->interlaced_frame = 0; ++ frame->top_field_first = 0; ++FF_ENABLE_DEPRECATION_WARNINGS ++#endif ++ frame->flags &= ~(AV_FRAME_FLAG_TOP_FIELD_FIRST | AV_FRAME_FLAG_INTERLACED); ++} ++ ++static inline int frame_is_interlaced(const AVFrame* const frame) ++{ ++#if FF_API_INTERLACED_FRAME ++FF_DISABLE_DEPRECATION_WARNINGS ++ return frame->interlaced_frame || (frame->flags & AV_FRAME_FLAG_INTERLACED) != 0; ++FF_ENABLE_DEPRECATION_WARNINGS ++#else ++ return (frame->flags & AV_FRAME_FLAG_INTERLACED) != 0; ++#endif ++} ++ ++static inline int frame_is_tff(const AVFrame* const frame) ++{ ++#if FF_API_INTERLACED_FRAME ++FF_DISABLE_DEPRECATION_WARNINGS ++ return frame->top_field_first || (frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) != 0; ++FF_ENABLE_DEPRECATION_WARNINGS ++#else ++ return (frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) != 0; ++#endif ++} ++ ++static inline int drain_frame_expected(const drain_state_t d) ++{ ++ return d == DRAIN_EOS || d == DRAIN_LAST; ++} ++ ++// These just list the ones we know we can cope with ++static uint32_t ++fmt_av_to_v4l2(const enum AVPixelFormat avfmt) ++{ ++ switch (avfmt) { ++ case AV_PIX_FMT_YUV420P: ++ return V4L2_PIX_FMT_YUV420; ++ case AV_PIX_FMT_NV12: ++ return V4L2_PIX_FMT_NV12; ++#if CONFIG_SAND ++ case AV_PIX_FMT_RPI4_8: ++ case AV_PIX_FMT_SAND128: ++ return V4L2_PIX_FMT_NV12_COL128; ++#endif ++ default: ++ break; ++ } ++ return 0; ++} ++ ++static enum AVPixelFormat ++fmt_v4l2_to_av(const uint32_t pixfmt) ++{ ++ switch (pixfmt) { ++ case V4L2_PIX_FMT_YUV420: ++ return AV_PIX_FMT_YUV420P; ++ case V4L2_PIX_FMT_NV12: ++ return AV_PIX_FMT_NV12; ++#if CONFIG_SAND ++ case V4L2_PIX_FMT_NV12_COL128: ++ return AV_PIX_FMT_RPI4_8; ++#endif ++ default: ++ break; ++ } ++ return AV_PIX_FMT_NONE; ++} ++ ++static unsigned int pts_stats_interval(const pts_stats_t * const stats) ++{ ++ return stats->last_interval; ++} ++ ++// Pick 64 for max last count - that is >1sec at 60fps ++#define STATS_LAST_COUNT_MAX 64 ++#define STATS_INTERVAL_MAX (1 << 30) ++static void pts_stats_add(pts_stats_t * const stats, int64_t pts) ++{ ++ if (pts == AV_NOPTS_VALUE || pts == stats->last_pts) { ++ if (stats->last_count < STATS_LAST_COUNT_MAX) ++ ++stats->last_count; ++ return; ++ } ++ ++ if (stats->last_pts != AV_NOPTS_VALUE) { ++ const int64_t interval = pts - stats->last_pts; ++ ++ if (interval < 0 || interval >= STATS_INTERVAL_MAX || ++ stats->last_count >= STATS_LAST_COUNT_MAX) { ++ if (stats->last_interval != 0) ++ av_log(stats->logctx, AV_LOG_DEBUG, "%s: %s: Bad interval: %" PRId64 "/%d\n", ++ __func__, stats->name, interval, stats->last_count); ++ stats->last_interval = 0; ++ } ++ else { ++ const int64_t frame_time = interval / (int64_t)stats->last_count; ++ ++ if (frame_time != stats->last_interval) ++ av_log(stats->logctx, AV_LOG_DEBUG, "%s: %s: New interval: %u->%" PRId64 "/%d=%" PRId64 "\n", ++ __func__, stats->name, stats->last_interval, interval, stats->last_count, frame_time); ++ stats->last_interval = frame_time; ++ } ++ } ++ ++ stats->last_pts = pts; ++ stats->last_count = 1; ++} ++ ++static void pts_stats_init(pts_stats_t * const stats, void * logctx, const char * name) ++{ ++ *stats = (pts_stats_t){ ++ .logctx = logctx, ++ .name = name, ++ .last_count = 1, ++ .last_interval = 0, ++ .last_pts = AV_NOPTS_VALUE ++ }; ++} ++ ++static inline uint32_t pts_track_next_n(pts_track_t * const trk) ++{ ++ if (++trk->n == 0) ++ trk->n = 1; ++ return trk->n; ++} ++ ++static int pts_track_get_frame(pts_track_t * const trk, const struct timeval tv, AVFrame * const dst) ++{ ++ uint32_t n = (uint32_t)(tv.tv_usec / 2 + tv.tv_sec * 500000); ++ pts_track_el_t * t; ++ ++ // As a first guess assume that n==0 means last frame ++ if (n == 0) { ++ n = trk->last_n; ++ if (n == 0) ++ goto fail; ++ } ++ ++ t = trk->a + (n & (PTS_TRACK_SIZE - 1)); ++ ++ if (t->n != n) { ++ av_log(trk->logctx, AV_LOG_ERROR, "%s: track failure: got %u, expected %u\n", __func__, n, trk->n); ++ goto fail; ++ } ++ ++ // 1st frame is simple - just believe it ++ if (n != trk->last_n) { ++ trk->last_n = n; ++ trk->got_2 = 0; ++ return av_frame_copy_props(dst, t->props); ++ } ++ ++ // Only believe in a single interpolated frame ++ if (trk->got_2) ++ goto fail; ++ trk->got_2 = 1; ++ ++ av_frame_copy_props(dst, t->props); ++ ++ ++ // If we can't guess - don't ++ if (t->interval == 0) { ++ dst->best_effort_timestamp = AV_NOPTS_VALUE; ++ dst->pts = AV_NOPTS_VALUE; ++ dst->pkt_dts = AV_NOPTS_VALUE; ++ } ++ else { ++ if (dst->best_effort_timestamp != AV_NOPTS_VALUE) ++ dst->best_effort_timestamp += t->interval / 2; ++ if (dst->pts != AV_NOPTS_VALUE) ++ dst->pts += t->interval / 2; ++ if (dst->pkt_dts != AV_NOPTS_VALUE) ++ dst->pkt_dts += t->interval / 2; ++ } ++ ++ return 0; ++ ++fail: ++ trk->last_n = 0; ++ trk->got_2 = 0; ++ dst->pts = AV_NOPTS_VALUE; ++ dst->pkt_dts = AV_NOPTS_VALUE; ++ return 0; ++} ++ ++// We are only ever expecting in-order frames so nothing more clever is required ++static unsigned int ++pts_track_count(const pts_track_t * const trk) ++{ ++ return (trk->n - trk->last_n) & (PTS_TRACK_SIZE - 1); ++} ++ ++static struct timeval pts_track_add_frame(pts_track_t * const trk, const AVFrame * const src) ++{ ++ const uint32_t n = pts_track_next_n(trk); ++ pts_track_el_t * const t = trk->a + (n & (PTS_TRACK_SIZE - 1)); ++ ++ pts_stats_add(&trk->stats, src->pts); ++ ++ t->n = n; ++ t->interval = pts_stats_interval(&trk->stats); // guess that next interval is the same as the last ++ av_frame_unref(t->props); ++ av_frame_copy_props(t->props, src); ++ ++ // We now know what the previous interval was, rather than having to guess, ++ // so set it. There is a better than decent chance that this is before ++ // we use it. ++ if (t->interval != 0) { ++ pts_track_el_t * const prev_t = trk->a + ((n - 1) & (PTS_TRACK_SIZE - 1)); ++ prev_t->interval = t->interval; ++ } ++ ++ // In case deinterlace interpolates frames use every other usec ++ return (struct timeval){.tv_sec = n / 500000, .tv_usec = (n % 500000) * 2}; ++} ++ ++static void pts_track_uninit(pts_track_t * const trk) ++{ ++ unsigned int i; ++ for (i = 0; i != PTS_TRACK_SIZE; ++i) { ++ trk->a[i].n = 0; ++ av_frame_free(&trk->a[i].props); ++ } ++} ++ ++static int pts_track_init(pts_track_t * const trk, void *logctx) ++{ ++ unsigned int i; ++ trk->n = 1; ++ pts_stats_init(&trk->stats, logctx, "track"); ++ for (i = 0; i != PTS_TRACK_SIZE; ++i) { ++ trk->a[i].n = 0; ++ if ((trk->a[i].props = av_frame_alloc()) == NULL) { ++ pts_track_uninit(trk); ++ return AVERROR(ENOMEM); ++ } ++ } ++ return 0; ++} ++ ++static inline uint32_t ++fmt_bpl(const struct v4l2_format * const fmt, const unsigned int plane_n) ++{ ++ return V4L2_TYPE_IS_MULTIPLANAR(fmt->type) ? fmt->fmt.pix_mp.plane_fmt[plane_n].bytesperline : fmt->fmt.pix.bytesperline; ++} ++ ++static inline uint32_t ++fmt_height(const struct v4l2_format * const fmt) ++{ ++ return V4L2_TYPE_IS_MULTIPLANAR(fmt->type) ? fmt->fmt.pix_mp.height : fmt->fmt.pix.height; ++} ++ ++static inline uint32_t ++fmt_width(const struct v4l2_format * const fmt) ++{ ++ return V4L2_TYPE_IS_MULTIPLANAR(fmt->type) ? fmt->fmt.pix_mp.width : fmt->fmt.pix.width; ++} ++ ++static inline uint32_t ++fmt_pixelformat(const struct v4l2_format * const fmt) ++{ ++ return V4L2_TYPE_IS_MULTIPLANAR(fmt->type) ? fmt->fmt.pix_mp.pixelformat : fmt->fmt.pix.pixelformat; ++} ++ ++static inline uint32_t ++buf_bytesused0(const struct v4l2_buffer * const buf) ++{ ++ return V4L2_TYPE_IS_MULTIPLANAR(buf->type) ? buf->m.planes[0].bytesused : buf->bytesused; ++} ++ ++static void ++init_format(V4L2Queue * const q, const uint32_t format_type) ++{ ++ memset(&q->format, 0, sizeof(q->format)); ++ memset(&q->sel, 0, sizeof(q->sel)); ++ q->format.type = format_type; ++ q->sel.type = format_type; ++} ++ ++static int deint_v4l2m2m_prepare_context(DeintV4L2M2MContextShared *ctx) ++{ ++ struct v4l2_capability cap; ++ int ret; ++ ++ memset(&cap, 0, sizeof(cap)); ++ ret = ioctl(ctx->fd, VIDIOC_QUERYCAP, &cap); ++ if (ret < 0) ++ return ret; ++ ++ if (ctx->filter_type == FILTER_V4L2_SCALE && ++ strcmp("bcm2835-codec-isp", cap.card) != 0) ++ { ++ av_log(ctx->logctx, AV_LOG_DEBUG, "Not ISP\n"); ++ return AVERROR(EINVAL); ++ } ++ ++ if (!(cap.capabilities & V4L2_CAP_STREAMING)) { ++ av_log(ctx->logctx, AV_LOG_DEBUG, "No streaming\n"); ++ return AVERROR(EINVAL); ++ } ++ ++ if (cap.capabilities & V4L2_CAP_VIDEO_M2M_MPLANE) { ++ init_format(&ctx->capture, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); ++ init_format(&ctx->output, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); ++ } ++ else if (cap.capabilities & V4L2_CAP_VIDEO_M2M) { ++ init_format(&ctx->capture, V4L2_BUF_TYPE_VIDEO_CAPTURE); ++ init_format(&ctx->output, V4L2_BUF_TYPE_VIDEO_OUTPUT); ++ } ++ else { ++ av_log(ctx->logctx, AV_LOG_DEBUG, "Not M2M\n"); ++ return AVERROR(EINVAL); ++ } ++ ++ return 0; ++} ++ ++// Just use for probe - doesn't modify q format ++static int deint_v4l2m2m_try_format(V4L2Queue *queue, const uint32_t width, const uint32_t height, const enum AVPixelFormat avfmt) ++{ ++ struct v4l2_format fmt = {.type = queue->format.type}; ++ DeintV4L2M2MContextShared *ctx = queue->ctx; ++ int ret, field; ++ // Pick YUV to test with if not otherwise specified ++ uint32_t pixelformat = avfmt == AV_PIX_FMT_NONE ? V4L2_PIX_FMT_YUV420 : fmt_av_to_v4l2(avfmt); ++ enum AVPixelFormat r_avfmt; ++ ++ ++ ret = ioctl(ctx->fd, VIDIOC_G_FMT, &fmt); ++ if (ret) ++ av_log(ctx->logctx, AV_LOG_ERROR, "VIDIOC_G_FMT failed: %d\n", ret); ++ ++ if (ctx->filter_type == FILTER_V4L2_DEINTERLACE && V4L2_TYPE_IS_OUTPUT(fmt.type)) ++ field = V4L2_FIELD_INTERLACED_TB; ++ else ++ field = V4L2_FIELD_NONE; ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(fmt.type)) { ++ fmt.fmt.pix_mp.pixelformat = pixelformat; ++ fmt.fmt.pix_mp.field = field; ++ fmt.fmt.pix_mp.width = width; ++ fmt.fmt.pix_mp.height = height; ++ } else { ++ fmt.fmt.pix.pixelformat = pixelformat; ++ fmt.fmt.pix.field = field; ++ fmt.fmt.pix.width = width; ++ fmt.fmt.pix.height = height; ++ } ++ ++ av_log(ctx->logctx, AV_LOG_TRACE, "%s: Trying format for type %d, wxh: %dx%d, fmt: %08x, size %u bpl %u pre\n", __func__, ++ fmt.type, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height, ++ fmt.fmt.pix_mp.pixelformat, ++ fmt.fmt.pix_mp.plane_fmt[0].sizeimage, fmt.fmt.pix_mp.plane_fmt[0].bytesperline); ++ ++ ret = ioctl(ctx->fd, VIDIOC_TRY_FMT, &fmt); ++ if (ret) ++ return AVERROR(EINVAL); ++ ++ av_log(ctx->logctx, AV_LOG_TRACE, "%s: Trying format for type %d, wxh: %dx%d, fmt: %08x, size %u bpl %u post\n", __func__, ++ fmt.type, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height, ++ fmt.fmt.pix_mp.pixelformat, ++ fmt.fmt.pix_mp.plane_fmt[0].sizeimage, fmt.fmt.pix_mp.plane_fmt[0].bytesperline); ++ ++ r_avfmt = fmt_v4l2_to_av(fmt_pixelformat(&fmt)); ++ if (r_avfmt != avfmt && avfmt != AV_PIX_FMT_NONE) { ++ av_log(ctx->logctx, AV_LOG_DEBUG, "Unable to set format %s on %s port\n", av_get_pix_fmt_name(avfmt), V4L2_TYPE_IS_CAPTURE(fmt.type) ? "dest" : "src"); ++ return AVERROR(EINVAL); ++ } ++ if (r_avfmt == AV_PIX_FMT_NONE) { ++ av_log(ctx->logctx, AV_LOG_DEBUG, "No supported format on %s port\n", V4L2_TYPE_IS_CAPTURE(fmt.type) ? "dest" : "src"); ++ return AVERROR(EINVAL); ++ } ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(fmt.type)) { ++ if (fmt.fmt.pix_mp.field != field) { ++ av_log(ctx->logctx, AV_LOG_DEBUG, "format not supported for type %d\n", fmt.type); ++ ++ return AVERROR(EINVAL); ++ } ++ } else { ++ if (fmt.fmt.pix.field != field) { ++ av_log(ctx->logctx, AV_LOG_DEBUG, "format not supported for type %d\n", fmt.type); ++ ++ return AVERROR(EINVAL); ++ } ++ } ++ ++ return 0; ++} ++ ++static int ++do_s_fmt(V4L2Queue * const q) ++{ ++ DeintV4L2M2MContextShared * const ctx = q->ctx; ++ const uint32_t pixelformat = fmt_pixelformat(&q->format); ++ int ret; ++ ++ ret = ioctl(ctx->fd, VIDIOC_S_FMT, &q->format); ++ if (ret) { ++ ret = AVERROR(errno); ++ av_log(ctx->logctx, AV_LOG_ERROR, "VIDIOC_S_FMT failed: %s\n", av_err2str(ret)); ++ return ret; ++ } ++ ++ if (pixelformat != fmt_pixelformat(&q->format)) { ++ av_log(ctx->logctx, AV_LOG_ERROR, "Format not supported: %s; S_FMT returned %s\n", av_fourcc2str(pixelformat), av_fourcc2str(fmt_pixelformat(&q->format))); ++ return AVERROR(EINVAL); ++ } ++ ++ q->sel.target = V4L2_TYPE_IS_OUTPUT(q->sel.type) ? V4L2_SEL_TGT_CROP : V4L2_SEL_TGT_COMPOSE, ++ q->sel.flags = V4L2_TYPE_IS_OUTPUT(q->sel.type) ? V4L2_SEL_FLAG_LE : V4L2_SEL_FLAG_GE; ++ ++ ret = ioctl(ctx->fd, VIDIOC_S_SELECTION, &q->sel); ++ if (ret) { ++ ret = AVERROR(errno); ++ av_log(ctx->logctx, AV_LOG_WARNING, "VIDIOC_S_SELECTION failed: %s\n", av_err2str(ret)); ++ } ++ ++ return 0; ++} ++ ++static void ++set_fmt_color(struct v4l2_format *const fmt, ++ const enum AVColorPrimaries avcp, ++ const enum AVColorSpace avcs, ++ const enum AVColorTransferCharacteristic avxc) ++{ ++ enum v4l2_ycbcr_encoding ycbcr = V4L2_YCBCR_ENC_DEFAULT; ++ enum v4l2_colorspace cs = V4L2_COLORSPACE_DEFAULT; ++ enum v4l2_xfer_func xfer = V4L2_XFER_FUNC_DEFAULT; ++ ++ switch (avcp) { ++ case AVCOL_PRI_BT709: ++ cs = V4L2_COLORSPACE_REC709; ++ ycbcr = V4L2_YCBCR_ENC_709; ++ break; ++ case AVCOL_PRI_BT470M: ++ cs = V4L2_COLORSPACE_470_SYSTEM_M; ++ ycbcr = V4L2_YCBCR_ENC_601; ++ break; ++ case AVCOL_PRI_BT470BG: ++ cs = V4L2_COLORSPACE_470_SYSTEM_BG; ++ break; ++ case AVCOL_PRI_SMPTE170M: ++ cs = V4L2_COLORSPACE_SMPTE170M; ++ break; ++ case AVCOL_PRI_SMPTE240M: ++ cs = V4L2_COLORSPACE_SMPTE240M; ++ break; ++ case AVCOL_PRI_BT2020: ++ cs = V4L2_COLORSPACE_BT2020; ++ break; ++ case AVCOL_PRI_SMPTE428: ++ case AVCOL_PRI_SMPTE431: ++ case AVCOL_PRI_SMPTE432: ++ case AVCOL_PRI_EBU3213: ++ case AVCOL_PRI_RESERVED: ++ case AVCOL_PRI_FILM: ++ case AVCOL_PRI_UNSPECIFIED: ++ default: ++ break; ++ } ++ ++ switch (avcs) { ++ case AVCOL_SPC_RGB: ++ cs = V4L2_COLORSPACE_SRGB; ++ break; ++ case AVCOL_SPC_BT709: ++ cs = V4L2_COLORSPACE_REC709; ++ break; ++ case AVCOL_SPC_FCC: ++ cs = V4L2_COLORSPACE_470_SYSTEM_M; ++ break; ++ case AVCOL_SPC_BT470BG: ++ cs = V4L2_COLORSPACE_470_SYSTEM_BG; ++ break; ++ case AVCOL_SPC_SMPTE170M: ++ cs = V4L2_COLORSPACE_SMPTE170M; ++ break; ++ case AVCOL_SPC_SMPTE240M: ++ cs = V4L2_COLORSPACE_SMPTE240M; ++ break; ++ case AVCOL_SPC_BT2020_CL: ++ cs = V4L2_COLORSPACE_BT2020; ++ ycbcr = V4L2_YCBCR_ENC_BT2020_CONST_LUM; ++ break; ++ case AVCOL_SPC_BT2020_NCL: ++ cs = V4L2_COLORSPACE_BT2020; ++ break; ++ default: ++ break; ++ } ++ ++ switch (xfer) { ++ case AVCOL_TRC_BT709: ++ xfer = V4L2_XFER_FUNC_709; ++ break; ++ case AVCOL_TRC_IEC61966_2_1: ++ xfer = V4L2_XFER_FUNC_SRGB; ++ break; ++ case AVCOL_TRC_SMPTE240M: ++ xfer = V4L2_XFER_FUNC_SMPTE240M; ++ break; ++ case AVCOL_TRC_SMPTE2084: ++ xfer = V4L2_XFER_FUNC_SMPTE2084; ++ break; ++ default: ++ break; ++ } ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(fmt->type)) { ++ fmt->fmt.pix_mp.colorspace = cs; ++ fmt->fmt.pix_mp.ycbcr_enc = ycbcr; ++ fmt->fmt.pix_mp.xfer_func = xfer; ++ } else { ++ fmt->fmt.pix.colorspace = cs; ++ fmt->fmt.pix.ycbcr_enc = ycbcr; ++ fmt->fmt.pix.xfer_func = xfer; ++ } ++} ++ ++static void ++set_fmt_color_range(struct v4l2_format *const fmt, const enum AVColorRange avcr) ++{ ++ const enum v4l2_quantization q = ++ avcr == AVCOL_RANGE_MPEG ? V4L2_QUANTIZATION_LIM_RANGE : ++ avcr == AVCOL_RANGE_JPEG ? V4L2_QUANTIZATION_FULL_RANGE : ++ V4L2_QUANTIZATION_DEFAULT; ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(fmt->type)) { ++ fmt->fmt.pix_mp.quantization = q; ++ } else { ++ fmt->fmt.pix.quantization = q; ++ } ++} ++ ++static enum AVColorPrimaries get_color_primaries(const struct v4l2_format *const fmt) ++{ ++ enum v4l2_ycbcr_encoding ycbcr; ++ enum v4l2_colorspace cs; ++ ++ cs = V4L2_TYPE_IS_MULTIPLANAR(fmt->type) ? ++ fmt->fmt.pix_mp.colorspace : ++ fmt->fmt.pix.colorspace; ++ ++ ycbcr = V4L2_TYPE_IS_MULTIPLANAR(fmt->type) ? ++ fmt->fmt.pix_mp.ycbcr_enc: ++ fmt->fmt.pix.ycbcr_enc; ++ ++ switch(ycbcr) { ++ case V4L2_YCBCR_ENC_XV709: ++ case V4L2_YCBCR_ENC_709: return AVCOL_PRI_BT709; ++ case V4L2_YCBCR_ENC_XV601: ++ case V4L2_YCBCR_ENC_601:return AVCOL_PRI_BT470M; ++ default: ++ break; ++ } ++ ++ switch(cs) { ++ case V4L2_COLORSPACE_470_SYSTEM_BG: return AVCOL_PRI_BT470BG; ++ case V4L2_COLORSPACE_SMPTE170M: return AVCOL_PRI_SMPTE170M; ++ case V4L2_COLORSPACE_SMPTE240M: return AVCOL_PRI_SMPTE240M; ++ case V4L2_COLORSPACE_BT2020: return AVCOL_PRI_BT2020; ++ default: ++ break; ++ } ++ ++ return AVCOL_PRI_UNSPECIFIED; ++} ++ ++static enum AVColorSpace get_color_space(const struct v4l2_format *const fmt) ++{ ++ enum v4l2_ycbcr_encoding ycbcr; ++ enum v4l2_colorspace cs; ++ ++ cs = V4L2_TYPE_IS_MULTIPLANAR(fmt->type) ? ++ fmt->fmt.pix_mp.colorspace : ++ fmt->fmt.pix.colorspace; ++ ++ ycbcr = V4L2_TYPE_IS_MULTIPLANAR(fmt->type) ? ++ fmt->fmt.pix_mp.ycbcr_enc: ++ fmt->fmt.pix.ycbcr_enc; ++ ++ switch(cs) { ++ case V4L2_COLORSPACE_SRGB: return AVCOL_SPC_RGB; ++ case V4L2_COLORSPACE_REC709: return AVCOL_SPC_BT709; ++ case V4L2_COLORSPACE_470_SYSTEM_M: return AVCOL_SPC_FCC; ++ case V4L2_COLORSPACE_470_SYSTEM_BG: return AVCOL_SPC_BT470BG; ++ case V4L2_COLORSPACE_SMPTE170M: return AVCOL_SPC_SMPTE170M; ++ case V4L2_COLORSPACE_SMPTE240M: return AVCOL_SPC_SMPTE240M; ++ case V4L2_COLORSPACE_BT2020: ++ if (ycbcr == V4L2_YCBCR_ENC_BT2020_CONST_LUM) ++ return AVCOL_SPC_BT2020_CL; ++ else ++ return AVCOL_SPC_BT2020_NCL; ++ default: ++ break; ++ } ++ ++ return AVCOL_SPC_UNSPECIFIED; ++} ++ ++static enum AVColorTransferCharacteristic get_color_trc(const struct v4l2_format *const fmt) ++{ ++ enum v4l2_ycbcr_encoding ycbcr; ++ enum v4l2_xfer_func xfer; ++ enum v4l2_colorspace cs; ++ ++ cs = V4L2_TYPE_IS_MULTIPLANAR(fmt->type) ? ++ fmt->fmt.pix_mp.colorspace : ++ fmt->fmt.pix.colorspace; ++ ++ ycbcr = V4L2_TYPE_IS_MULTIPLANAR(fmt->type) ? ++ fmt->fmt.pix_mp.ycbcr_enc: ++ fmt->fmt.pix.ycbcr_enc; ++ ++ xfer = V4L2_TYPE_IS_MULTIPLANAR(fmt->type) ? ++ fmt->fmt.pix_mp.xfer_func: ++ fmt->fmt.pix.xfer_func; ++ ++ switch (xfer) { ++ case V4L2_XFER_FUNC_709: return AVCOL_TRC_BT709; ++ case V4L2_XFER_FUNC_SRGB: return AVCOL_TRC_IEC61966_2_1; ++ default: ++ break; ++ } ++ ++ switch (cs) { ++ case V4L2_COLORSPACE_470_SYSTEM_M: return AVCOL_TRC_GAMMA22; ++ case V4L2_COLORSPACE_470_SYSTEM_BG: return AVCOL_TRC_GAMMA28; ++ case V4L2_COLORSPACE_SMPTE170M: return AVCOL_TRC_SMPTE170M; ++ case V4L2_COLORSPACE_SMPTE240M: return AVCOL_TRC_SMPTE240M; ++ default: ++ break; ++ } ++ ++ switch (ycbcr) { ++ case V4L2_YCBCR_ENC_XV709: ++ case V4L2_YCBCR_ENC_XV601: return AVCOL_TRC_BT1361_ECG; ++ default: ++ break; ++ } ++ ++ return AVCOL_TRC_UNSPECIFIED; ++} ++ ++static enum AVColorRange get_color_range(const struct v4l2_format *const fmt) ++{ ++ enum v4l2_quantization qt; ++ ++ qt = V4L2_TYPE_IS_MULTIPLANAR(fmt->type) ? ++ fmt->fmt.pix_mp.quantization : ++ fmt->fmt.pix.quantization; ++ ++ switch (qt) { ++ case V4L2_QUANTIZATION_LIM_RANGE: return AVCOL_RANGE_MPEG; ++ case V4L2_QUANTIZATION_FULL_RANGE: return AVCOL_RANGE_JPEG; ++ default: ++ break; ++ } ++ ++ return AVCOL_RANGE_UNSPECIFIED; ++} ++ ++static int set_src_fmt(V4L2Queue * const q, const AVFrame * const frame) ++{ ++ struct v4l2_format *const format = &q->format; ++ const AVDRMFrameDescriptor *const src = (const AVDRMFrameDescriptor *)frame->data[0]; ++ ++ const uint32_t drm_fmt = src->layers[0].format; ++ // Treat INVALID as LINEAR ++ const uint64_t mod = src->objects[0].format_modifier == DRM_FORMAT_MOD_INVALID ? ++ DRM_FORMAT_MOD_LINEAR : src->objects[0].format_modifier; ++ uint32_t pix_fmt = 0; ++ uint32_t w = 0; ++ uint32_t h = 0; ++ uint32_t bpl = src->layers[0].planes[0].pitch; ++ ++ // We really don't expect multiple layers ++ // All formats that we currently cope with are single object ++ ++ if (src->nb_layers != 1 || src->nb_objects != 1) ++ return AVERROR(EINVAL); ++ ++ switch (drm_fmt) { ++ case DRM_FORMAT_YUV420: ++ if (mod == DRM_FORMAT_MOD_LINEAR) { ++ if (src->layers[0].nb_planes != 3) ++ break; ++ pix_fmt = V4L2_PIX_FMT_YUV420; ++ h = src->layers[0].planes[1].offset / bpl; ++ w = bpl; ++ } ++ break; ++ ++ case DRM_FORMAT_NV12: ++ if (mod == DRM_FORMAT_MOD_LINEAR) { ++ if (src->layers[0].nb_planes != 2) ++ break; ++ pix_fmt = V4L2_PIX_FMT_NV12; ++ h = src->layers[0].planes[1].offset / bpl; ++ w = bpl; ++ } ++#if CONFIG_SAND ++ else if (fourcc_mod_broadcom_mod(mod) == DRM_FORMAT_MOD_BROADCOM_SAND128) { ++ if (src->layers[0].nb_planes != 2) ++ break; ++ pix_fmt = V4L2_PIX_FMT_NV12_COL128; ++ w = bpl; ++ h = src->layers[0].planes[1].offset / 128; ++ bpl = fourcc_mod_broadcom_param(mod); ++ } ++#endif ++ break; ++ ++ case DRM_FORMAT_P030: ++#if CONFIG_SAND ++ if (fourcc_mod_broadcom_mod(mod) == DRM_FORMAT_MOD_BROADCOM_SAND128) { ++ if (src->layers[0].nb_planes != 2) ++ break; ++ pix_fmt = V4L2_PIX_FMT_NV12_10_COL128; ++ w = bpl / 2; // Matching lie to how we construct this ++ h = src->layers[0].planes[1].offset / 128; ++ bpl = fourcc_mod_broadcom_param(mod); ++ } ++#endif ++ break; ++ ++ default: ++ break; ++ } ++ ++ if (!pix_fmt) ++ return AVERROR(EINVAL); ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(format->type)) { ++ struct v4l2_pix_format_mplane *const pix = &format->fmt.pix_mp; ++ ++ pix->width = w; ++ pix->height = h; ++ pix->pixelformat = pix_fmt; ++ pix->plane_fmt[0].bytesperline = bpl; ++ pix->num_planes = 1; ++ } ++ else { ++ struct v4l2_pix_format *const pix = &format->fmt.pix; ++ ++ pix->width = w; ++ pix->height = h; ++ pix->pixelformat = pix_fmt; ++ pix->bytesperline = bpl; ++ } ++ ++ set_fmt_color(format, frame->color_primaries, frame->colorspace, frame->color_trc); ++ set_fmt_color_range(format, frame->color_range); ++ ++ q->sel.r.width = frame->width - (frame->crop_left + frame->crop_right); ++ q->sel.r.height = frame->height - (frame->crop_top + frame->crop_bottom); ++ q->sel.r.left = frame->crop_left; ++ q->sel.r.top = frame->crop_top; ++ ++ return 0; ++} ++ ++ ++static int set_dst_format(DeintV4L2M2MContext * const priv, V4L2Queue *queue, uint32_t pixelformat, uint32_t field, int width, int height) ++{ ++ struct v4l2_format * const fmt = &queue->format; ++ struct v4l2_selection *const sel = &queue->sel; ++ ++ memset(&fmt->fmt, 0, sizeof(fmt->fmt)); ++ ++ // Align w/h to 16 here in case there are alignment requirements at the next ++ // stage of the filter chain (also RPi deinterlace setup is bust and this ++ // fixes it) ++ if (V4L2_TYPE_IS_MULTIPLANAR(fmt->type)) { ++ fmt->fmt.pix_mp.pixelformat = pixelformat; ++ fmt->fmt.pix_mp.field = field; ++ fmt->fmt.pix_mp.width = FFALIGN(width, 16); ++ fmt->fmt.pix_mp.height = FFALIGN(height, 16); ++ } else { ++ fmt->fmt.pix.pixelformat = pixelformat; ++ fmt->fmt.pix.field = field; ++ fmt->fmt.pix.width = FFALIGN(width, 16); ++ fmt->fmt.pix.height = FFALIGN(height, 16); ++ } ++ ++ set_fmt_color(fmt, priv->colour_primaries, priv->colour_matrix, priv->colour_transfer); ++ set_fmt_color_range(fmt, priv->colour_range); ++ ++ sel->r.width = width; ++ sel->r.height = height; ++ sel->r.left = 0; ++ sel->r.top = 0; ++ ++ return do_s_fmt(queue); ++} ++ ++static int deint_v4l2m2m_probe_device(DeintV4L2M2MContextShared *ctx, char *node) ++{ ++ int ret; ++ ++ ctx->fd = open(node, O_RDWR | O_NONBLOCK, 0); ++ if (ctx->fd < 0) ++ return AVERROR(errno); ++ ++ ret = deint_v4l2m2m_prepare_context(ctx); ++ if (ret) { ++ av_log(ctx->logctx, AV_LOG_DEBUG, "Failed to prepare context\n"); ++ goto fail; ++ } ++ ++ ret = deint_v4l2m2m_try_format(&ctx->capture, ctx->output_width, ctx->output_height, ctx->output_format); ++ if (ret) { ++ av_log(ctx->logctx, AV_LOG_DEBUG, "Failed to try dst format\n"); ++ goto fail; ++ } ++ ++ ret = deint_v4l2m2m_try_format(&ctx->output, ctx->width, ctx->height, AV_PIX_FMT_NONE); ++ if (ret) { ++ av_log(ctx->logctx, AV_LOG_DEBUG, "Failed to try src format\n"); ++ goto fail; ++ } ++ ++ return 0; ++ ++fail: ++ close(ctx->fd); ++ ctx->fd = -1; ++ ++ return ret; ++} ++ ++static int deint_v4l2m2m_find_device(DeintV4L2M2MContextShared *ctx) ++{ ++ int ret = AVERROR(EINVAL); ++ struct dirent *entry; ++ char node[PATH_MAX]; ++ DIR *dirp; ++ ++ dirp = opendir("/dev"); ++ if (!dirp) ++ return AVERROR(errno); ++ ++ for (entry = readdir(dirp); entry; entry = readdir(dirp)) { ++ ++ if (strncmp(entry->d_name, "video", 5)) ++ continue; ++ ++ snprintf(node, sizeof(node), "/dev/%s", entry->d_name); ++ av_log(ctx->logctx, AV_LOG_DEBUG, "probing device %s\n", node); ++ ret = deint_v4l2m2m_probe_device(ctx, node); ++ if (!ret) ++ break; ++ } ++ ++ closedir(dirp); ++ ++ if (ret) { ++ av_log(ctx->logctx, AV_LOG_ERROR, "Could not find a valid device\n"); ++ ctx->fd = -1; ++ ++ return ret; ++ } ++ ++ av_log(ctx->logctx, AV_LOG_INFO, "Using device %s\n", node); ++ ++ return 0; ++} ++ ++static int deint_v4l2m2m_enqueue_buffer(V4L2Buffer *buf) ++{ ++ int ret; ++ ++ ret = ioctl(buf->q->ctx->fd, VIDIOC_QBUF, &buf->buffer); ++ if (ret < 0) ++ return AVERROR(errno); ++ ++ buf->enqueued = 1; ++ ++ return 0; ++} ++ ++static void ++drm_frame_init(AVDRMFrameDescriptor * const d) ++{ ++ unsigned int i; ++ for (i = 0; i != AV_DRM_MAX_PLANES; ++i) { ++ d->objects[i].fd = -1; ++ } ++} ++ ++static void ++drm_frame_uninit(AVDRMFrameDescriptor * const d) ++{ ++ unsigned int i; ++ for (i = 0; i != d->nb_objects; ++i) { ++ if (d->objects[i].fd != -1) { ++ close(d->objects[i].fd); ++ d->objects[i].fd = -1; ++ } ++ } ++} ++ ++static void ++avbufs_delete(V4L2Buffer** ppavbufs, const unsigned int n) ++{ ++ unsigned int i; ++ V4L2Buffer* const avbufs = *ppavbufs; ++ ++ if (avbufs == NULL) ++ return; ++ *ppavbufs = NULL; ++ ++ for (i = 0; i != n; ++i) { ++ V4L2Buffer* const avbuf = avbufs + i; ++ drm_frame_uninit(&avbuf->drm_frame); ++ } ++ ++ av_free(avbufs); ++} ++ ++static int v4l2_buffer_export_drm(V4L2Queue * const q, V4L2Buffer * const avbuf) ++{ ++ struct v4l2_exportbuffer expbuf; ++ int i, ret; ++ uint64_t mod = DRM_FORMAT_MOD_LINEAR; ++ ++ AVDRMFrameDescriptor * const drm_desc = &avbuf->drm_frame; ++ AVDRMLayerDescriptor * const layer = &drm_desc->layers[0]; ++ const struct v4l2_format *const fmt = &q->format; ++ const uint32_t height = fmt_height(fmt); ++ ptrdiff_t bpl0; ++ ++ /* fill the DRM frame descriptor */ ++ drm_desc->nb_layers = 1; ++ 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 = fmt_bpl(fmt, i); ++ } ++ bpl0 = layer->planes[0].pitch; ++ ++ switch (fmt_pixelformat(fmt)) { ++#if CONFIG_SAND ++ case V4L2_PIX_FMT_NV12_COL128: ++ mod = DRM_FORMAT_MOD_BROADCOM_SAND128_COL_HEIGHT(bpl0); ++ layer->format = V4L2_PIX_FMT_NV12; ++ ++ if (avbuf->num_planes > 1) ++ break; ++ ++ layer->nb_planes = 2; ++ layer->planes[1].object_index = 0; ++ layer->planes[1].offset = height * 128; ++ layer->planes[0].pitch = fmt_width(fmt); ++ layer->planes[1].pitch = layer->planes[0].pitch; ++ break; ++#endif ++ ++ case DRM_FORMAT_NV12: ++ layer->format = V4L2_PIX_FMT_NV12; ++ ++ if (avbuf->num_planes > 1) ++ break; ++ ++ layer->nb_planes = 2; ++ layer->planes[1].object_index = 0; ++ layer->planes[1].offset = bpl0 * height; ++ layer->planes[1].pitch = bpl0; ++ break; ++ ++ case V4L2_PIX_FMT_YUV420: ++ 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 = bpl0 * height; ++ layer->planes[1].pitch = bpl0 / 2; ++ layer->planes[2].object_index = 0; ++ layer->planes[2].offset = layer->planes[1].offset + ((bpl0 * height) / 4); ++ layer->planes[2].pitch = bpl0 / 2; ++ break; ++ ++ default: ++ drm_desc->nb_layers = 0; ++ return AVERROR(EINVAL); ++ } ++ ++ drm_desc->nb_objects = 0; ++ for (i = 0; i < avbuf->num_planes; i++) { ++ memset(&expbuf, 0, sizeof(expbuf)); ++ ++ expbuf.index = avbuf->buffer.index; ++ expbuf.type = avbuf->buffer.type; ++ expbuf.plane = i; ++ ++ ret = ioctl(avbuf->q->ctx->fd, VIDIOC_EXPBUF, &expbuf); ++ if (ret < 0) ++ return AVERROR(errno); ++ ++ drm_desc->objects[i].size = V4L2_TYPE_IS_MULTIPLANAR(avbuf->buffer.type) ? ++ avbuf->buffer.m.planes[i].length : avbuf->buffer.length; ++ drm_desc->objects[i].fd = expbuf.fd; ++ drm_desc->objects[i].format_modifier = mod; ++ drm_desc->nb_objects = i + 1; ++ } ++ ++ return 0; ++} ++ ++static int deint_v4l2m2m_allocate_buffers(V4L2Queue *queue) ++{ ++ struct v4l2_format *fmt = &queue->format; ++ DeintV4L2M2MContextShared *ctx = queue->ctx; ++ struct v4l2_requestbuffers req; ++ int ret, i, multiplanar; ++ uint32_t memory; ++ ++ memory = V4L2_TYPE_IS_OUTPUT(fmt->type) ? ++ V4L2_MEMORY_DMABUF : V4L2_MEMORY_MMAP; ++ ++ multiplanar = V4L2_TYPE_IS_MULTIPLANAR(fmt->type); ++ ++ memset(&req, 0, sizeof(req)); ++ req.count = queue->num_buffers; ++ req.memory = memory; ++ req.type = fmt->type; ++ ++ ret = ioctl(ctx->fd, VIDIOC_REQBUFS, &req); ++ if (ret < 0) { ++ av_log(ctx->logctx, AV_LOG_ERROR, "VIDIOC_REQBUFS failed: %s\n", strerror(errno)); ++ ++ return AVERROR(errno); ++ } ++ ++ queue->num_buffers = req.count; ++ queue->buffers = av_mallocz(queue->num_buffers * sizeof(V4L2Buffer)); ++ if (!queue->buffers) { ++ av_log(ctx->logctx, AV_LOG_ERROR, "malloc enomem\n"); ++ ++ return AVERROR(ENOMEM); ++ } ++ ++ for (i = 0; i < queue->num_buffers; i++) { ++ V4L2Buffer * const buf = &queue->buffers[i]; ++ ++ buf->enqueued = 0; ++ buf->q = queue; ++ ++ buf->buffer.type = fmt->type; ++ buf->buffer.memory = memory; ++ buf->buffer.index = i; ++ ++ if (multiplanar) { ++ buf->buffer.length = VIDEO_MAX_PLANES; ++ buf->buffer.m.planes = buf->planes; ++ } ++ ++ drm_frame_init(&buf->drm_frame); ++ } ++ ++ for (i = 0; i < queue->num_buffers; i++) { ++ V4L2Buffer * const buf = &queue->buffers[i]; ++ ++ ret = ioctl(ctx->fd, VIDIOC_QUERYBUF, &buf->buffer); ++ if (ret < 0) { ++ ret = AVERROR(errno); ++ ++ goto fail; ++ } ++ ++ buf->num_planes = multiplanar ? buf->buffer.length : 1; ++ ++ if (!V4L2_TYPE_IS_OUTPUT(fmt->type)) { ++ ret = deint_v4l2m2m_enqueue_buffer(buf); ++ if (ret) ++ goto fail; ++ ++ ret = v4l2_buffer_export_drm(queue, buf); ++ if (ret) ++ goto fail; ++ } ++ } ++ ++ return 0; ++ ++fail: ++ avbufs_delete(&queue->buffers, queue->num_buffers); ++ queue->num_buffers = 0; ++ return ret; ++} ++ ++static int deint_v4l2m2m_streamon(V4L2Queue *queue) ++{ ++ DeintV4L2M2MContextShared * const ctx = queue->ctx; ++ int type = queue->format.type; ++ int ret; ++ ++ ret = ioctl(ctx->fd, VIDIOC_STREAMON, &type); ++ av_log(ctx->logctx, AV_LOG_DEBUG, "%s: type:%d ret:%d errno:%d\n", __func__, type, ret, AVERROR(errno)); ++ if (ret < 0) ++ return AVERROR(errno); ++ ++ return 0; ++} ++ ++static int deint_v4l2m2m_streamoff(V4L2Queue *queue) ++{ ++ DeintV4L2M2MContextShared * const ctx = queue->ctx; ++ int type = queue->format.type; ++ int ret; ++ ++ ret = ioctl(ctx->fd, VIDIOC_STREAMOFF, &type); ++ av_log(ctx->logctx, AV_LOG_DEBUG, "%s: type:%d ret:%d errno:%d\n", __func__, type, ret, AVERROR(errno)); ++ if (ret < 0) ++ return AVERROR(errno); ++ ++ return 0; ++} ++ ++// timeout in ms ++static V4L2Buffer* deint_v4l2m2m_dequeue_buffer(V4L2Queue *queue, int timeout) ++{ ++ struct v4l2_plane planes[VIDEO_MAX_PLANES]; ++ DeintV4L2M2MContextShared *ctx = queue->ctx; ++ struct v4l2_buffer buf = { 0 }; ++ V4L2Buffer* avbuf = NULL; ++ struct pollfd pfd; ++ short events; ++ int ret; ++ ++ if (V4L2_TYPE_IS_OUTPUT(queue->format.type)) ++ events = POLLOUT | POLLWRNORM; ++ else ++ events = POLLIN | POLLRDNORM; ++ ++ pfd.events = events; ++ pfd.fd = ctx->fd; ++ ++ for (;;) { ++ ret = poll(&pfd, 1, timeout); ++ if (ret > 0) ++ break; ++ if (errno == EINTR) ++ continue; ++ return NULL; ++ } ++ ++ if (pfd.revents & POLLERR) ++ return NULL; ++ ++ if (pfd.revents & events) { ++ memset(&buf, 0, sizeof(buf)); ++ buf.memory = V4L2_MEMORY_MMAP; ++ buf.type = queue->format.type; ++ if (V4L2_TYPE_IS_MULTIPLANAR(queue->format.type)) { ++ memset(planes, 0, sizeof(planes)); ++ buf.length = VIDEO_MAX_PLANES; ++ buf.m.planes = planes; ++ } ++ ++ ret = ioctl(ctx->fd, VIDIOC_DQBUF, &buf); ++ if (ret) { ++ if (errno != EAGAIN) ++ av_log(ctx->logctx, AV_LOG_DEBUG, "VIDIOC_DQBUF, errno (%s)\n", ++ av_err2str(AVERROR(errno))); ++ return NULL; ++ } ++ ++ avbuf = &queue->buffers[buf.index]; ++ avbuf->enqueued = 0; ++ avbuf->buffer = buf; ++ if (V4L2_TYPE_IS_MULTIPLANAR(queue->format.type)) { ++ memcpy(avbuf->planes, planes, sizeof(planes)); ++ avbuf->buffer.m.planes = avbuf->planes; ++ } ++ return avbuf; ++ } ++ ++ return NULL; ++} ++ ++static V4L2Buffer *deint_v4l2m2m_find_free_buf(V4L2Queue *queue) ++{ ++ int i; ++ V4L2Buffer *buf = NULL; ++ ++ for (i = 0; i < queue->num_buffers; i++) ++ if (!queue->buffers[i].enqueued) { ++ buf = &queue->buffers[i]; ++ break; ++ } ++ return buf; ++} ++ ++static void deint_v4l2m2m_unref_queued(V4L2Queue *queue) ++{ ++ int i; ++ V4L2Buffer *buf = NULL; ++ ++ if (!queue || !queue->buffers) ++ return; ++ for (i = 0; i < queue->num_buffers; i++) { ++ buf = &queue->buffers[i]; ++ if (queue->buffers[i].enqueued) ++ av_frame_unref(&buf->frame); ++ } ++} ++ ++static void recycle_q(V4L2Queue * const queue) ++{ ++ V4L2Buffer* avbuf; ++ while (avbuf = deint_v4l2m2m_dequeue_buffer(queue, 0), avbuf) { ++ av_frame_unref(&avbuf->frame); ++ } ++} ++ ++static int count_enqueued(V4L2Queue *queue) ++{ ++ int i; ++ int n = 0; ++ ++ if (queue->buffers == NULL) ++ return 0; ++ ++ for (i = 0; i < queue->num_buffers; i++) ++ if (queue->buffers[i].enqueued) ++ ++n; ++ return n; ++} ++ ++static int deint_v4l2m2m_enqueue_frame(V4L2Queue * const queue, AVFrame * const frame) ++{ ++ DeintV4L2M2MContextShared *const ctx = queue->ctx; ++ AVDRMFrameDescriptor *drm_desc = (AVDRMFrameDescriptor *)frame->data[0]; ++ V4L2Buffer *buf; ++ int i; ++ ++ if (V4L2_TYPE_IS_OUTPUT(queue->format.type)) ++ recycle_q(queue); ++ ++ buf = deint_v4l2m2m_find_free_buf(queue); ++ if (!buf) { ++ av_log(ctx->logctx, AV_LOG_ERROR, "%s: error %d finding free buf\n", __func__, 0); ++ return AVERROR(EAGAIN); ++ } ++ if (V4L2_TYPE_IS_MULTIPLANAR(buf->buffer.type)) ++ for (i = 0; i < drm_desc->nb_objects; i++) ++ buf->buffer.m.planes[i].m.fd = drm_desc->objects[i].fd; ++ else ++ buf->buffer.m.fd = drm_desc->objects[0].fd; ++ ++ buf->buffer.field = !frame_is_interlaced(frame) ? V4L2_FIELD_NONE : ++ frame_is_tff(frame) ? V4L2_FIELD_INTERLACED_TB : ++ V4L2_FIELD_INTERLACED_BT; ++ ++ if (ctx->field_order != buf->buffer.field) { ++ av_log(ctx->logctx, AV_LOG_DEBUG, "%s: Field changed: %d->%d\n", __func__, ctx->field_order, buf->buffer.field); ++ ctx->field_order = buf->buffer.field; ++ } ++ ++ buf->buffer.timestamp = pts_track_add_frame(&ctx->track, frame); ++ ++ buf->drm_frame.objects[0].fd = drm_desc->objects[0].fd; ++ ++ av_frame_move_ref(&buf->frame, frame); ++ ++ return deint_v4l2m2m_enqueue_buffer(buf); ++} ++ ++static void deint_v4l2m2m_destroy_context(DeintV4L2M2MContextShared *ctx) ++{ ++ if (atomic_fetch_sub(&ctx->refcount, 1) == 1) { ++ V4L2Queue *capture = &ctx->capture; ++ V4L2Queue *output = &ctx->output; ++ ++ av_log(NULL, AV_LOG_DEBUG, "%s - destroying context\n", __func__); ++ ++ if (ctx->fd >= 0) { ++ deint_v4l2m2m_streamoff(capture); ++ deint_v4l2m2m_streamoff(output); ++ } ++ ++ avbufs_delete(&capture->buffers, capture->num_buffers); ++ ++ deint_v4l2m2m_unref_queued(output); ++ ++ av_buffer_unref(&ctx->hw_frames_ctx); ++ ++ if (capture->buffers) ++ av_free(capture->buffers); ++ ++ if (output->buffers) ++ av_free(output->buffers); ++ ++ if (ctx->fd >= 0) { ++ close(ctx->fd); ++ ctx->fd = -1; ++ } ++ ++ av_free(ctx); ++ } ++} ++ ++static void v4l2_free_buffer(void *opaque, uint8_t *unused) ++{ ++ V4L2Buffer *buf = opaque; ++ DeintV4L2M2MContextShared *ctx = buf->q->ctx; ++ ++ if (!ctx->done) ++ deint_v4l2m2m_enqueue_buffer(buf); ++ ++ deint_v4l2m2m_destroy_context(ctx); ++} ++ ++// timeout in ms ++static int deint_v4l2m2m_dequeue_frame(V4L2Queue *queue, AVFrame* frame, int timeout) ++{ ++ DeintV4L2M2MContextShared *ctx = queue->ctx; ++ V4L2Buffer* avbuf; ++ enum AVColorPrimaries color_primaries; ++ enum AVColorSpace colorspace; ++ enum AVColorTransferCharacteristic color_trc; ++ enum AVColorRange color_range; ++ ++ av_log(ctx->logctx, AV_LOG_TRACE, "<<< %s\n", __func__); ++ ++ if (queue->eos) { ++ av_log(ctx->logctx, AV_LOG_TRACE, ">>> %s: EOS\n", __func__); ++ return AVERROR_EOF; ++ } ++ ++ avbuf = deint_v4l2m2m_dequeue_buffer(queue, timeout); ++ if (!avbuf) { ++ av_log(ctx->logctx, AV_LOG_DEBUG, "%s: No buffer to dequeue (timeout=%d)\n", __func__, timeout); ++ return AVERROR(EAGAIN); ++ } ++ ++ if (V4L2_TYPE_IS_CAPTURE(avbuf->buffer.type)) { ++ if ((avbuf->buffer.flags & V4L2_BUF_FLAG_LAST) != 0) ++ queue->eos = 1; ++ if (buf_bytesused0(&avbuf->buffer) == 0) ++ return queue->eos ? AVERROR_EOF : AVERROR(EINVAL); ++ } ++ ++ // Fill in PTS and anciliary info from src frame ++ pts_track_get_frame(&ctx->track, avbuf->buffer.timestamp, frame); ++ ++ frame->buf[0] = av_buffer_create((uint8_t *) &avbuf->drm_frame, ++ sizeof(avbuf->drm_frame), v4l2_free_buffer, ++ avbuf, AV_BUFFER_FLAG_READONLY); ++ if (!frame->buf[0]) { ++ av_log(ctx->logctx, AV_LOG_ERROR, "%s: error %d creating buffer\n", __func__, 0); ++ return AVERROR(ENOMEM); ++ } ++ ++ atomic_fetch_add(&ctx->refcount, 1); ++ ++ frame->data[0] = (uint8_t *)&avbuf->drm_frame; ++ frame->format = AV_PIX_FMT_DRM_PRIME; ++ if (ctx->hw_frames_ctx) ++ frame->hw_frames_ctx = av_buffer_ref(ctx->hw_frames_ctx); ++ frame->height = ctx->output_height; ++ frame->width = ctx->output_width; ++ ++ color_primaries = get_color_primaries(&ctx->capture.format); ++ colorspace = get_color_space(&ctx->capture.format); ++ color_trc = get_color_trc(&ctx->capture.format); ++ color_range = get_color_range(&ctx->capture.format); ++ ++ // If the color parameters are unspecified by V4L2 then leave alone as they ++ // will have been copied from src ++ if (color_primaries != AVCOL_PRI_UNSPECIFIED) ++ frame->color_primaries = color_primaries; ++ if (colorspace != AVCOL_SPC_UNSPECIFIED) ++ frame->colorspace = colorspace; ++ if (color_trc != AVCOL_TRC_UNSPECIFIED) ++ frame->color_trc = color_trc; ++ if (color_range != AVCOL_RANGE_UNSPECIFIED) ++ frame->color_range = color_range; ++ ++ if (ctx->filter_type == FILTER_V4L2_DEINTERLACE) { ++ // Not interlaced now ++ frame_set_progressive(frame); ++ // Duration halved ++ frame->duration /= 2; ++ } ++ ++ if (avbuf->buffer.flags & V4L2_BUF_FLAG_ERROR) { ++ av_log(ctx->logctx, AV_LOG_ERROR, "driver decode error\n"); ++ frame->decode_error_flags |= FF_DECODE_ERROR_INVALID_BITSTREAM; ++ } ++ ++ av_log(ctx->logctx, AV_LOG_TRACE, ">>> %s: PTS=%"PRId64"\n", __func__, frame->pts); ++ return 0; ++} ++ ++static int deint_v4l2m2m_config_props(AVFilterLink *outlink) ++{ ++ AVFilterLink *inlink = outlink->src->inputs[0]; ++ AVFilterContext *avctx = outlink->src; ++ DeintV4L2M2MContext *priv = avctx->priv; ++ DeintV4L2M2MContextShared *ctx = priv->shared; ++ int ret; ++ ++ ctx->height = avctx->inputs[0]->h; ++ ctx->width = avctx->inputs[0]->w; ++ ++ if (ctx->filter_type == FILTER_V4L2_SCALE) { ++ if ((ret = ff_scale_eval_dimensions(priv, ++ priv->w_expr, priv->h_expr, ++ inlink, outlink, ++ &ctx->output_width, &ctx->output_height)) < 0) ++ return ret; ++ ++ ff_scale_adjust_dimensions(inlink, &ctx->output_width, &ctx->output_height, ++ priv->force_original_aspect_ratio, priv->force_divisible_by); ++ } ++ else { ++ ctx->output_width = ctx->width; ++ ctx->output_height = ctx->height; ++ } ++ ++ av_log(priv, AV_LOG_DEBUG, "%s: %dx%d->%dx%d\n", __func__, ++ ctx->width, ctx->height, ctx->output_width, ctx->output_height); ++ ++ outlink->time_base = inlink->time_base; ++ outlink->w = ctx->output_width; ++ outlink->h = ctx->output_height; ++ outlink->format = inlink->format; ++ ++ if (inlink->sample_aspect_ratio.num) ++ outlink->sample_aspect_ratio = av_mul_q((AVRational){outlink->h * inlink->w, outlink->w * inlink->h}, inlink->sample_aspect_ratio); ++ else ++ outlink->sample_aspect_ratio = inlink->sample_aspect_ratio; ++ ++ return deint_v4l2m2m_find_device(ctx); ++} ++ ++static uint32_t desc_pixelformat(const AVDRMFrameDescriptor * const drm_desc) ++{ ++ const uint64_t mod = drm_desc->objects[0].format_modifier; ++ const int is_linear = (mod == DRM_FORMAT_MOD_LINEAR || mod == DRM_FORMAT_MOD_INVALID); ++ ++ // Only currently support single object things ++ if (drm_desc->nb_objects != 1) ++ return 0; ++ ++ switch (drm_desc->layers[0].format) { ++ case DRM_FORMAT_YUV420: ++ return is_linear ? V4L2_PIX_FMT_YUV420 : 0; ++ case DRM_FORMAT_NV12: ++ return is_linear ? V4L2_PIX_FMT_NV12 : ++#if CONFIG_SAND ++ fourcc_mod_broadcom_mod(mod) == DRM_FORMAT_MOD_BROADCOM_SAND128 ? V4L2_PIX_FMT_NV12_COL128 : ++#endif ++ 0; ++ default: ++ break; ++ } ++ return 0; ++} ++ ++static int deint_v4l2m2m_filter_frame(AVFilterLink *link, AVFrame *in) ++{ ++ AVFilterContext *avctx = link->dst; ++ DeintV4L2M2MContext *priv = avctx->priv; ++ DeintV4L2M2MContextShared *ctx = priv->shared; ++ V4L2Queue *capture = &ctx->capture; ++ V4L2Queue *output = &ctx->output; ++ int ret; ++ ++ av_log(priv, AV_LOG_DEBUG, "<<< %s: input pts: %"PRId64" dts: %"PRId64" field :%d interlaced: %d aspect:%d/%d\n", ++ __func__, in->pts, in->pkt_dts, frame_is_tff(in), frame_is_interlaced(in), in->sample_aspect_ratio.num, in->sample_aspect_ratio.den); ++ ++ if (ctx->field_order == V4L2_FIELD_ANY) { ++ const AVDRMFrameDescriptor * const drm_desc = (AVDRMFrameDescriptor *)in->data[0]; ++ uint32_t pixelformat = desc_pixelformat(drm_desc); ++ ++ if (pixelformat == 0) { ++ av_log(avctx, AV_LOG_ERROR, "Unsupported DRM format %s in %d objects, modifier %#" PRIx64 "\n", ++ av_fourcc2str(drm_desc->layers[0].format), ++ drm_desc->nb_objects, drm_desc->objects[0].format_modifier); ++ return AVERROR(EINVAL); ++ } ++ ++ ctx->orig_width = drm_desc->layers[0].planes[0].pitch; ++ ctx->orig_height = drm_desc->layers[0].planes[1].offset / ctx->orig_width; ++ ++ av_log(priv, AV_LOG_DEBUG, "%s: %dx%d (%td,%td)\n", __func__, ctx->width, ctx->height, ++ drm_desc->layers[0].planes[0].pitch, drm_desc->layers[0].planes[1].offset); ++ ++ if ((ret = set_src_fmt(output, in)) != 0) { ++ av_log(avctx, AV_LOG_WARNING, "Unknown input DRM format: %s mod: %#" PRIx64 "\n", ++ av_fourcc2str(drm_desc->layers[0].format), drm_desc->objects[0].format_modifier); ++ return ret; ++ } ++ ++ ret = do_s_fmt(output); ++ if (ret) { ++ av_log(avctx, AV_LOG_WARNING, "Failed to set source format\n"); ++ return ret; ++ } ++ ++ if (ctx->output_format != AV_PIX_FMT_NONE) ++ pixelformat = fmt_av_to_v4l2(ctx->output_format); ++ ret = set_dst_format(priv, capture, pixelformat, V4L2_FIELD_NONE, ctx->output_width, ctx->output_height); ++ if (ret) { ++ av_log(avctx, AV_LOG_WARNING, "Failed to set destination format\n"); ++ return ret; ++ } ++ ++ ret = deint_v4l2m2m_allocate_buffers(capture); ++ if (ret) { ++ av_log(avctx, AV_LOG_WARNING, "Failed to allocate destination buffers\n"); ++ return ret; ++ } ++ ++ ret = deint_v4l2m2m_streamon(capture); ++ if (ret) { ++ av_log(avctx, AV_LOG_WARNING, "Failed set destination streamon: %s\n", av_err2str(ret)); ++ return ret; ++ } ++ ++ ret = deint_v4l2m2m_allocate_buffers(output); ++ if (ret) { ++ av_log(avctx, AV_LOG_WARNING, "Failed to allocate src buffers\n"); ++ return ret; ++ } ++ ++ ret = deint_v4l2m2m_streamon(output); ++ if (ret) { ++ av_log(avctx, AV_LOG_WARNING, "Failed set src streamon: %s\n", av_err2str(ret)); ++ return ret; ++ } ++ ++ if (frame_is_tff(in)) ++ ctx->field_order = V4L2_FIELD_INTERLACED_TB; ++ else ++ ctx->field_order = V4L2_FIELD_INTERLACED_BT; ++ ++ { ++ struct v4l2_encoder_cmd ecmd = { ++ .cmd = V4L2_ENC_CMD_STOP ++ }; ++ ctx->has_enc_stop = 0; ++ if (ioctl(ctx->fd, VIDIOC_TRY_ENCODER_CMD, &ecmd) == 0) { ++ av_log(ctx->logctx, AV_LOG_DEBUG, "Test encode stop succeeded\n"); ++ ctx->has_enc_stop = 1; ++ } ++ else { ++ av_log(ctx->logctx, AV_LOG_DEBUG, "Test encode stop fail: %s\n", av_err2str(AVERROR(errno))); ++ } ++ ++ } ++ } ++ ++ ret = deint_v4l2m2m_enqueue_frame(output, in); ++ ++ av_log(priv, AV_LOG_TRACE, ">>> %s: %s\n", __func__, av_err2str(ret)); ++ return ret; ++} ++ ++static int ++ack_inlink(AVFilterContext * const avctx, DeintV4L2M2MContextShared *const s, ++ AVFilterLink * const inlink) ++{ ++ int instatus; ++ int64_t inpts; ++ ++ if (ff_inlink_acknowledge_status(inlink, &instatus, &inpts) <= 0) ++ return 0; ++ ++ s->drain = instatus; ++ s->drain_pts = inpts; ++ s->drain_state = DRAIN_TIMEOUT; ++ ++ if (s->field_order == V4L2_FIELD_ANY) { // Not yet started ++ s->drain_state = DRAIN_DONE; ++ } ++ else if (s->one_to_one) { ++ s->drain_state = DRAIN_LAST; ++ } ++ else if (s->has_enc_stop) { ++ struct v4l2_encoder_cmd ecmd = { ++ .cmd = V4L2_ENC_CMD_STOP ++ }; ++ if (ioctl(s->fd, VIDIOC_ENCODER_CMD, &ecmd) == 0) { ++ av_log(avctx->priv, AV_LOG_DEBUG, "Do Encode stop\n"); ++ s->drain_state = DRAIN_EOS; ++ } ++ else { ++ av_log(avctx->priv, AV_LOG_WARNING, "Encode stop fail: %s\n", av_err2str(AVERROR(errno))); ++ } ++ } ++ return 1; ++} ++ ++static int deint_v4l2m2m_activate(AVFilterContext *avctx) ++{ ++ DeintV4L2M2MContext * const priv = avctx->priv; ++ DeintV4L2M2MContextShared *const s = priv->shared; ++ AVFilterLink * const outlink = avctx->outputs[0]; ++ AVFilterLink * const inlink = avctx->inputs[0]; ++ int n = 0; ++ int cn = 99; ++ int did_something = 0; ++ ++ av_log(priv, AV_LOG_TRACE, "<<< %s\n", __func__); ++ ++ FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, avctx); ++ ++ ack_inlink(avctx, s, inlink); ++ ++ if (s->field_order != V4L2_FIELD_ANY) // Can't DQ if no setup! ++ { ++ AVFrame * frame = av_frame_alloc(); ++ int rv; ++ ++ recycle_q(&s->output); ++ n = count_enqueued(&s->output); ++ ++ if (frame == NULL) { ++ av_log(priv, AV_LOG_ERROR, "%s: error allocating frame\n", __func__); ++ return AVERROR(ENOMEM); ++ } ++ ++ rv = deint_v4l2m2m_dequeue_frame(&s->capture, frame, ++ drain_frame_expected(s->drain_state) || n > 4 ? 300 : 0); ++ if (rv != 0) { ++ av_frame_free(&frame); ++ if (rv == AVERROR_EOF) { ++ av_log(priv, AV_LOG_DEBUG, "%s: --- DQ EOF\n", __func__); ++ s->drain_state = DRAIN_DONE; ++ } ++ else if (rv == AVERROR(EAGAIN)) { ++ if (s->drain_state != DRAIN_NONE) { ++ av_log(priv, AV_LOG_DEBUG, "%s: --- DQ empty - drain done\n", __func__); ++ s->drain_state = DRAIN_DONE; ++ } ++ } ++ else { ++ av_log(priv, AV_LOG_ERROR, ">>> %s: DQ fail: %s\n", __func__, av_err2str(rv)); ++ return rv; ++ } ++ } ++ else { ++ frame_set_progressive(frame); ++ // frame is always consumed by filter_frame - even on error despite ++ // a somewhat confusing comment in the header ++ rv = ff_filter_frame(outlink, frame); ++ ++s->frames_tx; ++ ++ av_log(priv, AV_LOG_TRACE, "%s: Filtered: %s\n", __func__, av_err2str(rv)); ++ did_something = 1; ++ ++ if (s->drain_state != DRAIN_NONE && pts_track_count(&s->track) == 0) { ++ av_log(priv, AV_LOG_DEBUG, "%s: --- DQ last - drain done\n", __func__); ++ s->drain_state = DRAIN_DONE; ++ } ++ } ++ ++ cn = count_enqueued(&s->capture); ++ } ++ ++ if (s->drain_state == DRAIN_DONE) { ++ ff_outlink_set_status(outlink, s->drain, s->drain_pts); ++ av_log(priv, AV_LOG_TRACE, ">>> %s: Status done: %s\n", __func__, av_err2str(s->drain)); ++ return 0; ++ } ++ ++ recycle_q(&s->output); ++ n = count_enqueued(&s->output); ++ ++ while (n < 6 && !s->drain) { ++ AVFrame * frame; ++ int rv; ++ ++ if ((rv = ff_inlink_consume_frame(inlink, &frame)) < 0) { ++ av_log(priv, AV_LOG_ERROR, "%s: consume in failed: %s\n", __func__, av_err2str(rv)); ++ return rv; ++ } ++ ++ if (frame == NULL) { ++ av_log(priv, AV_LOG_TRACE, "%s: No frame\n", __func__); ++ if (!ack_inlink(avctx, s, inlink)) { ++ ff_inlink_request_frame(inlink); ++ av_log(priv, AV_LOG_TRACE, "%s: req frame\n", __func__); ++ } ++ break; ++ } ++ ++s->frames_rx; ++ ++ rv = deint_v4l2m2m_filter_frame(inlink, frame); ++ av_frame_free(&frame); ++ ++ if (rv != 0) ++ return rv; ++ ++ av_log(priv, AV_LOG_TRACE, "%s: Q frame\n", __func__); ++ did_something = 1; ++ ++n; ++ } ++ ++ if ((n > 4 || s->drain) && ff_outlink_frame_wanted(outlink)) { ++ ff_filter_set_ready(avctx, 1); ++ did_something = 1; ++ av_log(priv, AV_LOG_TRACE, "%s: ready\n", __func__); ++ } ++ ++ av_log(priv, AV_LOG_TRACE, ">>> %s: OK (n=%d, cn=%d)\n", __func__, n, cn); ++ return did_something ? 0 : FFERROR_NOT_READY; ++} ++ ++static av_cold int common_v4l2m2m_init(AVFilterContext * const avctx, const filter_type_v4l2_t filter_type) ++{ ++ DeintV4L2M2MContext * const priv = avctx->priv; ++ DeintV4L2M2MContextShared * const ctx = av_mallocz(sizeof(DeintV4L2M2MContextShared)); ++ ++ if (!ctx) { ++ av_log(priv, AV_LOG_ERROR, "%s: error %d allocating context\n", __func__, 0); ++ return AVERROR(ENOMEM); ++ } ++ priv->shared = ctx; ++ ctx->logctx = priv; ++ ctx->filter_type = filter_type; ++ ctx->fd = -1; ++ ctx->output.ctx = ctx; ++ ctx->output.num_buffers = 8; ++ ctx->output.name = "OUTPUT"; ++ ctx->capture.ctx = ctx; ++ ctx->capture.num_buffers = 12; ++ ctx->capture.name = "CAPTURE"; ++ ctx->done = 0; ++ ctx->field_order = V4L2_FIELD_ANY; ++ ++ pts_track_init(&ctx->track, priv); ++ ++ atomic_init(&ctx->refcount, 1); ++ ++ if (priv->output_format_string) { ++ ctx->output_format = av_get_pix_fmt(priv->output_format_string); ++ if (ctx->output_format == AV_PIX_FMT_NONE) { ++ av_log(avctx, AV_LOG_ERROR, "Invalid ffmpeg output format '%s'.\n", priv->output_format_string); ++ return AVERROR(EINVAL); ++ } ++ if (fmt_av_to_v4l2(ctx->output_format) == 0) { ++ av_log(avctx, AV_LOG_ERROR, "Unsupported output format for V4L2: %s.\n", av_get_pix_fmt_name(ctx->output_format)); ++ return AVERROR(EINVAL); ++ } ++ } else { ++ // Use the input format once that is configured. ++ ctx->output_format = AV_PIX_FMT_NONE; ++ } ++ ++#define STRING_OPTION(var_name, func_name, default_value) do { \ ++ if (priv->var_name ## _string) { \ ++ int var = av_ ## func_name ## _from_name(priv->var_name ## _string); \ ++ if (var < 0) { \ ++ av_log(avctx, AV_LOG_ERROR, "Invalid %s.\n", #var_name); \ ++ return AVERROR(EINVAL); \ ++ } \ ++ priv->var_name = var; \ ++ } else { \ ++ priv->var_name = default_value; \ ++ } \ ++ } while (0) ++ ++ STRING_OPTION(colour_primaries, color_primaries, AVCOL_PRI_UNSPECIFIED); ++ STRING_OPTION(colour_transfer, color_transfer, AVCOL_TRC_UNSPECIFIED); ++ STRING_OPTION(colour_matrix, color_space, AVCOL_SPC_UNSPECIFIED); ++ STRING_OPTION(chroma_location, chroma_location, AVCHROMA_LOC_UNSPECIFIED); ++ ++ return 0; ++} ++ ++static av_cold int deint_v4l2m2m_init(AVFilterContext *avctx) ++{ ++ return common_v4l2m2m_init(avctx, FILTER_V4L2_DEINTERLACE); ++} ++ ++static av_cold int scale_v4l2m2m_init(AVFilterContext *avctx) ++{ ++ int rv; ++ DeintV4L2M2MContext * priv; ++ DeintV4L2M2MContextShared * ctx; ++ ++ if ((rv = common_v4l2m2m_init(avctx, FILTER_V4L2_SCALE)) != 0) ++ return rv; ++ ++ priv = avctx->priv; ++ ctx = priv->shared; ++ ++ ctx->one_to_one = 1; ++ return 0; ++} ++ ++static void deint_v4l2m2m_uninit(AVFilterContext *avctx) ++{ ++ DeintV4L2M2MContext *priv = avctx->priv; ++ DeintV4L2M2MContextShared *ctx = priv->shared; ++ ++ av_log(priv, AV_LOG_VERBOSE, "Frames Rx: %u, Frames Tx: %u\n", ++ ctx->frames_rx, ctx->frames_tx); ++ ctx->done = 1; ++ ctx->logctx = NULL; // Log to NULL works, log to missing crashes ++ pts_track_uninit(&ctx->track); ++ deint_v4l2m2m_destroy_context(ctx); ++} ++ ++static const AVOption deinterlace_v4l2m2m_options[] = { ++ { NULL }, ++}; ++ ++AVFILTER_DEFINE_CLASS(deinterlace_v4l2m2m); ++ ++#define OFFSET(x) offsetof(DeintV4L2M2MContext, x) ++#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM) ++ ++static const AVOption scale_v4l2m2m_options[] = { ++ { "w", "Output video width", ++ OFFSET(w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, .flags = FLAGS }, ++ { "h", "Output video height", ++ OFFSET(h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, .flags = FLAGS }, ++ { "format", "Output video format (software format of hardware frames)", ++ OFFSET(output_format_string), AV_OPT_TYPE_STRING, .flags = FLAGS }, ++ // These colour properties match the ones of the same name in vf_scale. ++ { "out_color_matrix", "Output colour matrix coefficient set", ++ OFFSET(colour_matrix_string), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = FLAGS }, ++ { "out_range", "Output colour range", ++ OFFSET(colour_range), AV_OPT_TYPE_INT, { .i64 = AVCOL_RANGE_UNSPECIFIED }, ++ AVCOL_RANGE_UNSPECIFIED, AVCOL_RANGE_JPEG, FLAGS, "range" }, ++ { "full", "Full range", ++ 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_JPEG }, 0, 0, FLAGS, "range" }, ++ { "limited", "Limited range", ++ 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_MPEG }, 0, 0, FLAGS, "range" }, ++ { "jpeg", "Full range", ++ 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_JPEG }, 0, 0, FLAGS, "range" }, ++ { "mpeg", "Limited range", ++ 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_MPEG }, 0, 0, FLAGS, "range" }, ++ { "tv", "Limited range", ++ 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_MPEG }, 0, 0, FLAGS, "range" }, ++ { "pc", "Full range", ++ 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_JPEG }, 0, 0, FLAGS, "range" }, ++ // These colour properties match the ones in the VAAPI scaler ++ { "out_color_primaries", "Output colour primaries", ++ OFFSET(colour_primaries_string), AV_OPT_TYPE_STRING, ++ { .str = NULL }, .flags = FLAGS }, ++ { "out_color_transfer", "Output colour transfer characteristics", ++ OFFSET(colour_transfer_string), AV_OPT_TYPE_STRING, ++ { .str = NULL }, .flags = FLAGS }, ++ { "out_chroma_location", "Output chroma sample location", ++ OFFSET(chroma_location_string), AV_OPT_TYPE_STRING, ++ { .str = NULL }, .flags = FLAGS }, ++ { "force_original_aspect_ratio", "decrease or increase w/h if necessary to keep the original AR", OFFSET(force_original_aspect_ratio), AV_OPT_TYPE_INT, { .i64 = 0}, 0, 2, FLAGS, "force_oar" }, ++ { "force_divisible_by", "enforce that the output resolution is divisible by a defined integer when force_original_aspect_ratio is used", OFFSET(force_divisible_by), AV_OPT_TYPE_INT, { .i64 = 1}, 1, 256, FLAGS }, ++ { NULL }, ++}; ++ ++AVFILTER_DEFINE_CLASS(scale_v4l2m2m); ++ ++static const AVFilterPad deint_v4l2m2m_inputs[] = { ++ { ++ .name = "default", ++ .type = AVMEDIA_TYPE_VIDEO, ++ }, ++}; ++ ++static const AVFilterPad deint_v4l2m2m_outputs[] = { ++ { ++ .name = "default", ++ .type = AVMEDIA_TYPE_VIDEO, ++ .config_props = deint_v4l2m2m_config_props, ++ }, ++}; ++ ++AVFilter ff_vf_deinterlace_v4l2m2m = { ++ .name = "deinterlace_v4l2m2m", ++ .description = NULL_IF_CONFIG_SMALL("V4L2 M2M deinterlacer"), ++ .priv_size = sizeof(DeintV4L2M2MContext), ++ .init = &deint_v4l2m2m_init, ++ .uninit = &deint_v4l2m2m_uninit, ++ FILTER_INPUTS(deint_v4l2m2m_inputs), ++ FILTER_OUTPUTS(deint_v4l2m2m_outputs), ++ FILTER_SINGLE_PIXFMT(AV_PIX_FMT_DRM_PRIME), ++ .priv_class = &deinterlace_v4l2m2m_class, ++ .activate = deint_v4l2m2m_activate, ++}; ++ ++AVFilter ff_vf_scale_v4l2m2m = { ++ .name = "scale_v4l2m2m", ++ .description = NULL_IF_CONFIG_SMALL("V4L2 M2M scaler"), ++ .priv_size = sizeof(DeintV4L2M2MContext), ++ .init = &scale_v4l2m2m_init, ++ .uninit = &deint_v4l2m2m_uninit, ++ FILTER_INPUTS(deint_v4l2m2m_inputs), ++ FILTER_OUTPUTS(deint_v4l2m2m_outputs), ++ FILTER_SINGLE_PIXFMT(AV_PIX_FMT_DRM_PRIME), ++ .priv_class = &scale_v4l2m2m_class, ++ .activate = deint_v4l2m2m_activate, ++}; ++ +diff --git a/libavfilter/vf_unsand.c b/libavfilter/vf_unsand.c +new file mode 100644 +index 000000000000..67750e4f12b8 +--- /dev/null ++++ b/libavfilter/vf_unsand.c +@@ -0,0 +1,227 @@ ++/* ++ * 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 "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; ++ ++ // 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]->incfg.formats == NULL) ++ return AVERROR(EAGAIN); ++ ++ // Accept anything ++ if (ctx->inputs[0]->outcfg.formats == NULL && ++ (ret = ff_formats_ref(ctx->inputs[0]->incfg.formats, &ctx->inputs[0]->outcfg.formats)) < 0) ++ return ret; ++ ++ // Filter out sand formats ++ ++ // Generate a container if we don't already have one ++ if (ctx->outputs[0]->incfg.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]->incfg.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]->outcfg.formats; ++ AVFilterFormats * const dst_ff = ctx->outputs[0]->incfg.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]->incfg.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 ++ }, ++}; ++ ++AVFilter ff_vf_unsand = { ++ .name = "unsand", ++ .description = NULL_IF_CONFIG_SMALL("Convert sand pix fmt to yuv"), ++ ++ .init = init, ++ .uninit = uninit, ++ ++ FILTER_QUERY_FUNC(query_formats), ++ ++ .priv_size = sizeof(UnsandContext), ++ .priv_class = &unsand_class, ++ ++ FILTER_INPUTS(avfilter_vf_unsand_inputs), ++ FILTER_OUTPUTS(avfilter_vf_unsand_outputs), ++}; ++ +diff --git a/libavformat/Makefile b/libavformat/Makefile +index 7ca68a703694..d267813a7ecd 100644 +--- a/libavformat/Makefile ++++ b/libavformat/Makefile +@@ -171,6 +171,7 @@ OBJS-$(CONFIG_CODEC2_MUXER) += codec2.o rawenc.o + OBJS-$(CONFIG_CODEC2RAW_DEMUXER) += codec2.o pcm.o + OBJS-$(CONFIG_CODEC2RAW_MUXER) += rawenc.o + OBJS-$(CONFIG_CONCAT_DEMUXER) += concatdec.o ++OBJS-$(CONFIG_CONFORM_MUXER) += conformenc.o + OBJS-$(CONFIG_CRC_MUXER) += crcenc.o + OBJS-$(CONFIG_DATA_DEMUXER) += rawdec.o + OBJS-$(CONFIG_DATA_MUXER) += rawenc.o +diff --git a/libavformat/allformats.c b/libavformat/allformats.c +index 305fa4653232..34e993280d14 100644 +--- a/libavformat/allformats.c ++++ b/libavformat/allformats.c +@@ -125,6 +125,7 @@ extern const FFOutputFormat ff_codec2_muxer; + extern const FFInputFormat ff_codec2raw_demuxer; + extern const FFOutputFormat ff_codec2raw_muxer; + extern const FFInputFormat ff_concat_demuxer; ++extern const FFOutputFormat ff_conform_muxer; + extern const FFOutputFormat ff_crc_muxer; + extern const FFInputFormat ff_dash_demuxer; + extern const FFOutputFormat ff_dash_muxer; +diff --git a/libavformat/conformenc.c b/libavformat/conformenc.c +new file mode 100644 +index 000000000000..abe74d1cf5cf +--- /dev/null ++++ b/libavformat/conformenc.c +@@ -0,0 +1,276 @@ ++/* ++ * 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. ++ ++#include "libavutil/opt.h" ++#include "libavutil/frame.h" ++#include "libavutil/md5.h" ++#include "libavutil/mem.h" ++#include "libavutil/pixdesc.h" ++#include "libavutil/hwcontext.h" ++#include "libavutil/hwcontext_drm.h" ++#include "mux.h" ++ ++#include "pthread.h" ++#include ++#include ++ ++#define TRACE_ALL 1 ++ ++#define DRM_MODULE "vc4" ++ ++// Aux size should only need to be 2, but on a few streams (Hobbit) under FKMS ++// we get initial flicker probably due to dodgy drm timing ++#define AUX_SIZE 3 ++typedef struct conform_display_env_s ++{ ++ AVClass *class; ++ ++ void * line_buf; ++ size_t line_size; ++ ++ struct AVMD5 * frame_md5; ++ struct AVMD5 * md5; ++ ++ int conform_file; ++ int frame_md5_flag; ++ ++ unsigned long long foffset; ++ unsigned int fno; ++} conform_display_env_t; ++ ++ ++static int conform_vout_write_trailer(AVFormatContext *s) ++{ ++ conform_display_env_t * const de = s->priv_data; ++ ++#if TRACE_ALL ++ av_log(s, AV_LOG_DEBUG, "%s\n", __func__); ++#endif ++ ++ if (de->md5) { ++ uint8_t m[16]; ++ av_md5_final(de->md5, m); ++ avio_printf(s->pb, "MD5=%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", ++ m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10], m[11], m[12], m[13], m[14], m[15]); ++ } ++ ++ return 0; ++} ++ ++static int conform_vout_write_header(AVFormatContext *s) ++{ ++ conform_display_env_t * const de = s->priv_data; ++ ++#if TRACE_ALL ++ av_log(s, AV_LOG_DEBUG, "%s\n", __func__); ++#endif ++ ++ if (de->md5) ++ av_md5_init(de->md5); ++ de->fno = 1; ++ de->foffset = 0; ++ ++ return 0; ++} ++ ++static int conform_vout_write_packet(AVFormatContext *s, AVPacket *pkt) ++{ ++ const AVFrame * const sf = (AVFrame *)pkt->data; ++ AVFrame * cf = NULL; ++ const AVFrame * f = sf; ++ ++ conform_display_env_t * const de = s->priv_data; ++ const AVPixFmtDescriptor * pix_desc = av_pix_fmt_desc_get(sf->format); ++ int is_hw = (pix_desc->flags & AV_PIX_FMT_FLAG_HWACCEL) != 0; ++ enum AVPixelFormat fmt = is_hw ? AV_PIX_FMT_NONE : sf->format; ++ unsigned int i; ++ ++ if (is_hw) { ++ enum AVPixelFormat *xfmts = NULL; ++ av_hwframe_transfer_get_formats(sf->hw_frames_ctx, AV_HWFRAME_TRANSFER_DIRECTION_FROM, &xfmts, 0); ++ fmt = *xfmts; ++ av_free(xfmts); ++ } ++ ++ av_log(s, AV_LOG_DEBUG, "%s: Frame %3d: %#08llx %dx%d crop(ltrb) %zd,%zd,%zd,%zd fmt %s -> %s\n", __func__, ++ de->fno, de->foffset, ++ sf->width, sf->height, sf->crop_left, sf->crop_top, sf->crop_right, sf->crop_bottom, ++ av_get_pix_fmt_name(sf->format), av_get_pix_fmt_name(fmt)); ++ ++ if ((sf->flags & AV_FRAME_FLAG_CORRUPT) != 0) { ++ av_log(s, AV_LOG_WARNING, "Discard corrupt frame: fmt=%d, ts=%" PRId64 "\n", sf->format, sf->pts); ++ if (de->frame_md5) ++ avio_printf(s->pb, "MD5-Frame-%d=*BAD*\n", de->fno); ++ ++de->fno; ++ return 0; ++ } ++ ++ if (!is_hw) ++ f = sf; ++ else ++ { ++ cf = av_frame_alloc(); ++ cf->format = fmt; ++ av_hwframe_transfer_data(cf, sf, AV_HWFRAME_TRANSFER_DIRECTION_FROM); ++ pix_desc = av_pix_fmt_desc_get(cf->format); ++ f = cf; ++ } ++ ++ if (de->frame_md5) ++ av_md5_init(de->frame_md5); ++ ++ // This is fully generic - much optimisation possible ++ for (i = 0; i != pix_desc->nb_components; ++i) { ++ const AVComponentDescriptor * const cd = pix_desc->comp + i; ++ const unsigned int srw = ((i == 1 || i == 2) ? pix_desc->log2_chroma_w : 0); ++ const unsigned int rndw = (1 << srw) - 1; ++ const unsigned int srh = ((i == 1 || i == 2) ? pix_desc->log2_chroma_h : 0); ++ const unsigned int rndh = (1 << srh) - 1; ++ const unsigned int srp = cd->shift; ++ const unsigned int bpp = cd->depth > 8 ? 2 : 1; ++ const unsigned int h = (f->height - (f->crop_top + f->crop_bottom) + rndh) >> srh; ++ unsigned int y; ++ for (y = 0; y < h; ++y) { ++ const void *const lstart = f->data[cd->plane] + (y + (f->crop_top >> srh)) * f->linesize[cd->plane] + cd->offset + (f->crop_left >> srw) * cd->step; ++ const unsigned int w = (f->width - (f->crop_left + f->crop_right) + rndw) >> srw; ++ unsigned int x; ++ if (bpp == 1) { ++ uint8_t *d = de->line_buf; ++ const uint8_t *s = lstart; ++ for (x = 0; x != w; ++x) { ++ *d++ = *s >> srp; ++ s += cd->step; ++ } ++ } ++ else { ++ uint16_t *d = de->line_buf; ++ const uint8_t *s = lstart; ++ for (x = 0; x != w; ++x) { ++ *d++ = *(uint16_t*)s >> srp; ++ s += cd->step; ++ } ++ } ++ ++ // We have one line ++ ++ if (de->frame_md5) ++ av_md5_update(de->frame_md5, de->line_buf, w * bpp); ++ if (de->md5) ++ av_md5_update(de->md5, de->line_buf, w * bpp); ++ else { ++ avio_write(s->pb, de->line_buf, w * bpp); ++ de->foffset += w * bpp; ++ } ++ } ++ } ++ ++ if (de->frame_md5) { ++ uint8_t m[16]; ++ av_md5_final(de->frame_md5, m); ++ avio_printf(s->pb, "MD5-Frame-%d=%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", ++ de->fno, ++ m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10], m[11], m[12], m[13], m[14], m[15]); ++ } ++ ++de->fno; ++ ++ av_frame_free(&cf); ++ ++ return 0; ++} ++ ++static int conform_vout_write_frame(AVFormatContext *s, int stream_index, AVFrame **ppframe, ++ unsigned flags) ++{ ++ av_log(s, AV_LOG_ERROR, "%s: NIF: idx=%d, flags=%#x\n", __func__, stream_index, flags); ++ return AVERROR_PATCHWELCOME; ++} ++ ++// deinit is called if init fails so no need to clean up explicity here ++static int conform_vout_init(struct AVFormatContext * s) ++{ ++ conform_display_env_t * const de = s->priv_data; ++ ++ av_log(s, AV_LOG_DEBUG, "<<< %s\n", __func__); ++ ++ de->line_size = (8192 * 4); // 4bpp * 8k seems plenty ++ de->line_buf = av_malloc(de->line_size); ++ ++ if (!de->conform_file) { ++ de->md5 = av_md5_alloc(); ++ if (de->frame_md5_flag) ++ de->frame_md5 = av_md5_alloc(); ++ } ++ ++ av_log(s, AV_LOG_DEBUG, ">>> %s\n", __func__); ++ ++ return 0; ++} ++ ++static void conform_vout_deinit(struct AVFormatContext * s) ++{ ++ conform_display_env_t * const de = s->priv_data; ++ ++ av_log(s, AV_LOG_DEBUG, "<<< %s\n", __func__); ++ ++ av_freep(&de->line_buf); ++ av_freep(&de->md5); ++ av_freep(&de->frame_md5); ++ ++ av_log(s, AV_LOG_DEBUG, ">>> %s\n", __func__); ++} ++ ++ ++#define OFFSET(x) offsetof(conform_display_env_t, x) ++static const AVOption options[] = { ++ { "conform_frame_md5", "Produce per-frame MD5s as well as final", OFFSET(frame_md5_flag), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_ENCODING_PARAM }, ++ { "conform_yuv", "Output yuv file rather than md5", OFFSET(conform_file), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_ENCODING_PARAM }, ++ { NULL } ++}; ++ ++static const AVClass conform_vid_class = { ++ .class_name = "conform vid muxer", ++ .item_name = av_default_item_name, ++ .option = options, ++ .version = LIBAVUTIL_VERSION_INT, ++ .category = AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT, ++}; ++ ++const FFOutputFormat ff_conform_muxer = { ++ .p = { ++ .name = "conform", ++ .long_name = NULL_IF_CONFIG_SMALL("Video out conformance test helper"), ++ .audio_codec = AV_CODEC_ID_NONE, ++ .video_codec = AV_CODEC_ID_WRAPPED_AVFRAME, ++ .flags = AVFMT_VARIABLE_FPS | AVFMT_NOTIMESTAMPS, ++ .priv_class = &conform_vid_class, ++ }, ++ .priv_data_size = sizeof(conform_display_env_t), ++ .write_header = conform_vout_write_header, ++ .write_packet = conform_vout_write_packet, ++ .write_uncoded_frame = conform_vout_write_frame, ++ .write_trailer = conform_vout_write_trailer, ++ .init = conform_vout_init, ++ .deinit = conform_vout_deinit, ++}; ++ +diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c +index 60c896e964eb..3967be997e86 100644 +--- a/libavformat/matroskaenc.c ++++ b/libavformat/matroskaenc.c +@@ -84,6 +84,10 @@ + + #define IS_WEBM(mkv) (CONFIG_WEBM_MUXER && CONFIG_MATROSKA_MUXER ? \ + ((mkv)->mode == MODE_WEBM) : CONFIG_WEBM_MUXER) ++ ++/* Reserved size for H264 headers if not extant at init time */ ++#define MAX_H264_HEADER_SIZE 1024 ++ + #define IS_SEEKABLE(pb, mkv) (((pb)->seekable & AVIO_SEEKABLE_NORMAL) && \ + !(mkv)->is_live) + +@@ -1136,8 +1140,12 @@ static int mkv_assemble_native_codecprivate(AVFormatContext *s, AVIOContext *dyn + case AV_CODEC_ID_WAVPACK: + return put_wv_codecpriv(dyn_cp, extradata, extradata_size); + case AV_CODEC_ID_H264: +- return ff_isom_write_avcc(dyn_cp, extradata, +- extradata_size); ++ if (extradata_size) ++ return ff_isom_write_avcc(dyn_cp, extradata, ++ extradata_size); ++ else ++ *size_to_reserve = MAX_H264_HEADER_SIZE; ++ break; + case AV_CODEC_ID_HEVC: + return ff_isom_write_hvcc(dyn_cp, extradata, + extradata_size, 0); +@@ -2966,8 +2974,8 @@ static int mkv_check_new_extra_data(AVFormatContext *s, const AVPacket *pkt) + } + break; + #endif +- // FIXME: Remove the following once libaom starts propagating proper extradata during init() +- // See https://bugs.chromium.org/p/aomedia/issues/detail?id=2208 ++ // FIXME: Remove the following once libaom starts propagating extradata during init() ++ // See https://bugs.chromium.org/p/aomedia/issues/detail?id=2012 + case AV_CODEC_ID_AV1: + if (side_data_size && mkv->track.bc && !par->extradata_size) { + // If the reserved space doesn't suffice, only write +@@ -2979,6 +2987,16 @@ static int mkv_check_new_extra_data(AVFormatContext *s, const AVPacket *pkt) + } else if (!par->extradata_size) + return AVERROR_INVALIDDATA; + break; ++ // H264 V4L2 has a similar issue ++ case AV_CODEC_ID_H264: ++ if (side_data_size && mkv->track.bc && !par->extradata_size) { ++ ret = mkv_update_codecprivate(s, mkv, side_data, side_data_size, ++ par, mkv->track.bc, track, 0); ++ if (ret < 0) ++ return ret; ++ } else if (!par->extradata_size) ++ return AVERROR_INVALIDDATA; ++ break; + default: + if (side_data_size) + av_log(s, AV_LOG_DEBUG, "Ignoring new extradata in a packet for stream %d.\n", pkt->stream_index); +@@ -3440,9 +3458,15 @@ static int mkv_init(struct AVFormatContext *s) + track->reformat = mkv_reformat_wavpack; + break; + case AV_CODEC_ID_H264: ++ // Default to reformat if no extradata as the only current ++ // encoder which does this is v4l2m2m which needs reformat ++ if (par->extradata_size == 0 || ++ (par->extradata_size > 3 && ++ (AV_RB24(par->extradata) == 1 || AV_RB32(par->extradata) == 1))) ++ track->reformat = mkv_reformat_h2645; ++ break; + case AV_CODEC_ID_HEVC: +- if ((par->codec_id == AV_CODEC_ID_H264 && par->extradata_size > 0 || +- par->codec_id == AV_CODEC_ID_HEVC && par->extradata_size > 6) && ++ if (par->extradata_size > 6 && + (AV_RB24(par->extradata) == 1 || AV_RB32(par->extradata) == 1)) + track->reformat = mkv_reformat_h2645; + break; +diff --git a/libavformat/movenc.c b/libavformat/movenc.c +index d6effda6fa86..57bd069dfd8a 100644 +--- a/libavformat/movenc.c ++++ b/libavformat/movenc.c +@@ -6906,6 +6906,7 @@ static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt) + if (trk->par->codec_id == AV_CODEC_ID_MP4ALS || + trk->par->codec_id == AV_CODEC_ID_AAC || + trk->par->codec_id == AV_CODEC_ID_AV1 || ++ trk->par->codec_id == AV_CODEC_ID_H264 || + trk->par->codec_id == AV_CODEC_ID_FLAC) { + size_t side_size; + uint8_t *side = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size); +diff --git a/libavformat/rtpenc.c b/libavformat/rtpenc.c +index 7b4ae37d1376..b026ed5bed4f 100644 +--- a/libavformat/rtpenc.c ++++ b/libavformat/rtpenc.c +@@ -19,6 +19,7 @@ + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + ++#include "avc.h" + #include "avformat.h" + #include "mpegts.h" + #include "internal.h" +@@ -586,8 +587,25 @@ static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt) + ff_rtp_send_vc2hq(s1, pkt->data, size, st->codecpar->field_order != AV_FIELD_PROGRESSIVE ? 1 : 0); + break; + case AV_CODEC_ID_H264: ++ { ++ uint8_t *side_data; ++ size_t side_data_size = 0; ++ ++ side_data = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, ++ &side_data_size); ++ ++ if (side_data_size != 0) { ++ int ps_size = side_data_size; ++ uint8_t * ps_buf = NULL; ++ ++ ff_avc_write_annexb_extradata(side_data, &ps_buf, &ps_size); ++ av_log(s1, AV_LOG_TRACE, "H264: write side data=%d\n", ps_size); ++ ff_rtp_send_h264_hevc(s1, ps_buf ? ps_buf : side_data, ps_size); ++ av_free(ps_buf); ++ } + ff_rtp_send_h264_hevc(s1, pkt->data, size); + break; ++ } + case AV_CODEC_ID_H261: + ff_rtp_send_h261(s1, pkt->data, size); + break; +diff --git a/libavutil/Makefile b/libavutil/Makefile +index 6e6fa8d800ca..8fa408850998 100644 +--- a/libavutil/Makefile ++++ b/libavutil/Makefile +@@ -76,6 +76,7 @@ HEADERS = adler32.h \ + rational.h \ + replaygain.h \ + ripemd.h \ ++ rpi_sand_fns.h \ + samplefmt.h \ + sha.h \ + sha512.h \ +@@ -201,6 +202,7 @@ OBJS-$(CONFIG_MACOS_KPERF) += macos_kperf.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 +@@ -222,6 +224,7 @@ SKIPHEADERS-$(CONFIG_D3D12VA) += hwcontext_d3d12va.h + SKIPHEADERS-$(CONFIG_DXVA2) += hwcontext_dxva2.h + SKIPHEADERS-$(CONFIG_QSV) += hwcontext_qsv.h + SKIPHEADERS-$(CONFIG_OPENCL) += hwcontext_opencl.h ++SKIPHEADERS-$(CONFIG-RPI) += rpi_sand_fn_pw.h + SKIPHEADERS-$(CONFIG_VAAPI) += hwcontext_vaapi.h + SKIPHEADERS-$(CONFIG_VIDEOTOOLBOX) += hwcontext_videotoolbox.h + SKIPHEADERS-$(CONFIG_VDPAU) += hwcontext_vdpau.h +diff --git a/libavutil/aarch64/Makefile b/libavutil/aarch64/Makefile +index eba01513379a..1b44beab3942 100644 +--- a/libavutil/aarch64/Makefile ++++ b/libavutil/aarch64/Makefile +@@ -4,3 +4,5 @@ OBJS += aarch64/cpu.o \ + + NEON-OBJS += aarch64/float_dsp_neon.o \ + aarch64/tx_float_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 000000000000..3a6bc3de74e5 +--- /dev/null ++++ b/libavutil/aarch64/rpi_sand_neon.S +@@ -0,0 +1,672 @@ ++/* ++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 ++ ++ cmp w8, #0 ++ beq no_main_y8 ++ ++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 ++no_main_y8: ++ 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 ++ // counts down ++ 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 ++ ++ // Skip at the end of the line to account for stride ++ sub w12, w1, w7 ++ ++ // 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 ++ ++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 ++ ++ cmp w8, #0 ++ beq no_main_c8 ++ ++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 ++ ++no_main_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 x0, x0, w12, sxtw ++ add x2, x2, w12, sxtw ++ ++ // jump to row_Loop_c8 iff the row count is small than the height ++ subs w15, w15, #1 ++ bgt row_loop_c8 ++ ++ ret ++endfunc ++ ++// Unzip chroma ++// ++// On entry: ++// a0 = V0, U2, ... ++// a1 = U0, V1, ... ++// a2 = U1, V2, ... ++// b0 = V8, U10, ... ++// b1 = U8, V9, ... ++// b2 = U9, V10, ... ++// ++// On exit: ++// d0 = U0, U3, ... ++// ... ++// a0 = V0, V3, .. ++// ... ++// ++// Reg order for USAND is a1, a0, a2 (i.e. swap natural order of 1st 2 dest regs) ++ ++.macro UZPH_C d0, d1, d2, a0, a1, a2, b0, b1, b2 ++ uzp1 \d0\().8h, \a1\().8h, \b1\().8h ++ uzp1 \d1\().8h, \a2\().8h, \b2\().8h ++ uzp2 \d2\().8h, \a0\().8h, \b0\().8h ++ ++ uzp1 \a0\().8h, \a0\().8h, \b0\().8h ++ uzp2 \a1\().8h, \a1\().8h, \b1\().8h ++ uzp2 \a2\().8h, \a2\().8h, \b2\().8h ++.endm ++ ++// SAND30 -> 10bit ++.macro USAND10 d0, d1, d2, a0, a1 ++ shrn \d2\().4h, \a0\().4s, #14 ++ shrn \d1\().4h, \a0\().4s, #10 ++ ++ shrn2 \d2\().8h, \a1\().4s, #14 ++ shrn2 \d1\().8h, \a1\().4s, #10 ++ uzp1 \d0\().8h, \a0\().8h, \a1\().8h ++ ++ ushr \d2\().8h, \d2\().8h, #6 ++ bic \d0\().8h, #0xfc, lsl #8 ++ bic \d1\().8h, #0xfc, lsl #8 ++.endm ++ ++// SAND30 -> 8bit ++.macro USAND8 d0, d1, d2, a0, a1, a2, a3, t0, t1, t2 ++ shrn \d1\().4h, \a0\().4s, #12 ++ shrn2 \d1\().8h, \a1\().4s, #12 ++ uzp1 \d0\().8h, \a0\().8h, \a1\().8h ++ uzp2 \d2\().8h, \a0\().8h, \a1\().8h ++ ++ shrn \t1\().4h, \a2\().4s, #12 ++ shrn2 \t1\().8h, \a3\().4s, #12 ++ uzp1 \t0\().8h, \a2\().8h, \a3\().8h ++ uzp2 \t2\().8h, \a2\().8h, \a3\().8h ++ ++ shrn \d0\().8b, \d0\().8h, #2 ++ shrn2 \d0\().16b, \t0\().8h, #2 ++ shrn \d2\().8b, \d2\().8h, #6 ++ shrn2 \d2\().16b, \t2\().8h, #6 ++ uzp1 \d1\().16b, \d1\().16b, \t1\().16b ++.endm ++ ++ ++// void ff_rpi_sand30_lines_to_planar_c16( ++// uint8_t * dst_u, // [x0] ++// unsigned int dst_stride_u, // [w1] ++// uint8_t * dst_v, // [x2] ++// unsigned int dst_stride_v, // [w3] ++// const uint8_t * src, // [x4] ++// unsigned int stride1, // [w5] 128 ++// unsigned int stride2, // [w6] ++// unsigned int _x, // [w7] 0 ++// unsigned int y, // [sp, #0] ++// unsigned int _w, // [sp, #8] w9 ++// unsigned int h); // [sp, #16] w10 ++ ++function ff_rpi_sand30_lines_to_planar_c16, export=1 ++ ldr w7, [sp, #0] // y ++ ldr w8, [sp, #8] // _w ++ ldr w10, [sp, #16] // h ++ lsl w6, w6, #7 // Fixup stride2 ++ sub w6, w6, #64 ++ uxtw x6, w6 ++ sub w1, w1, w8, LSL #1 // Fixup chroma strides ++ sub w3, w3, w8, LSL #1 ++ lsl w7, w7, #7 // Add y to src ++ add x4, x4, w7, UXTW ++10: ++ mov w13, #0 ++ mov x5, x4 ++ mov w9, w8 ++1: ++ ld1 {v0.4s-v3.4s}, [x5], #64 ++ ld1 {v4.4s-v7.4s}, [x5], x6 ++ subs w9, w9, #48 ++ ++ USAND10 v17, v16, v18, v0, v1 ++ USAND10 v20, v19, v21, v2, v3 ++ UZPH_C v0, v1, v2, v16, v17, v18, v19, v20, v21 ++ USAND10 v23, v22, v24, v4, v5 ++ USAND10 v26, v25, v27, v6, v7 ++ UZPH_C v4, v5, v6, v22, v23, v24, v25, v26, v27 ++ ++ blt 2f ++ ++ st3 {v0.8h-v2.8h}, [x0], #48 ++ st3 {v4.8h-v6.8h}, [x0], #48 ++ st3 {v16.8h-v18.8h}, [x2], #48 ++ st3 {v22.8h-v24.8h}, [x2], #48 ++ ++ bne 1b ++11: ++ subs w10, w10, #1 ++ add x4, x4, #128 ++ add x0, x0, w1, UXTW ++ add x2, x2, w3, UXTW ++ bne 10b ++99: ++ ret ++ ++// Partial final write ++2: ++ cmp w9, #24-48 ++ blt 1f ++ st3 {v0.8h - v2.8h}, [x0], #48 ++ st3 {v16.8h - v18.8h}, [x2], #48 ++ beq 11b ++ mov v0.16b, v4.16b ++ mov v1.16b, v5.16b ++ sub w9, w9, #24 ++ mov v2.16b, v6.16b ++ mov v16.16b, v22.16b ++ mov v17.16b, v23.16b ++ mov v18.16b, v24.16b ++1: ++ cmp w9, #12-48 ++ blt 1f ++ st3 {v0.4h - v2.4h}, [x0], #24 ++ st3 {v16.4h - v18.4h}, [x2], #24 ++ beq 11b ++ mov v0.d[0], v0.d[1] ++ sub w9, w9, #12 ++ mov v1.d[0], v1.d[1] ++ mov v2.d[0], v2.d[1] ++ mov v16.d[0], v16.d[1] ++ mov v17.d[0], v17.d[1] ++ mov v18.d[0], v18.d[1] ++1: ++ cmp w9, #6-48 ++ blt 1f ++ st3 {v0.h - v2.h}[0], [x0], #6 ++ st3 {v0.h - v2.h}[1], [x0], #6 ++ st3 {v16.h - v18.h}[0], [x2], #6 ++ st3 {v16.h - v18.h}[1], [x2], #6 ++ beq 11b ++ mov v0.s[0], v0.s[1] ++ sub w9, w9, #6 ++ mov v1.s[0], v1.s[1] ++ mov v2.s[0], v2.s[1] ++ mov v16.s[0], v16.s[1] ++ mov v17.s[0], v17.s[1] ++ mov v18.s[0], v18.s[1] ++1: ++ cmp w9, #3-48 ++ blt 1f ++ st3 {v0.h - v2.h}[0], [x0], #6 ++ st3 {v16.h - v18.h}[0], [x2], #6 ++ beq 11b ++ mov v0.h[0], v0.h[1] ++ sub w9, w9, #3 ++ mov v1.h[0], v1.h[1] ++ mov v16.h[0], v16.h[1] ++ mov v17.h[0], v17.h[1] ++1: ++ cmp w9, #2-48 ++ blt 1f ++ st2 {v0.h - v1.h}[0], [x0], #4 ++ st2 {v16.h - v17.h}[0], [x2], #4 ++ b 11b ++1: ++ st1 {v0.h}[0], [x0], #2 ++ st1 {v16.h}[0], [x2], #2 ++ b 11b ++endfunc ++ ++ ++//void ff_rpi_sand30_lines_to_planar_p010( ++// 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_sand30_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] ++// ++// 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 wri ++ ++function ff_rpi_sand30_lines_to_planar_y16, export=1 ++ lsl w4, w4, #7 ++ sub w4, w4, #64 ++ uxtw x4, w4 ++ sub w1, w1, w7, lsl #1 ++ uxtw x6, w6 ++ add x8, x2, x6, lsl #7 ++ ldr w6, [sp, #0] ++ ++10: ++ mov x2, x8 ++ mov w5, w7 ++1: ++ ld1 {v0.4s, v1.4s, v2.4s, v3.4s}, [x2], #64 ++ ld1 {v4.4s, v5.4s, v6.4s, v7.4s}, [x2], x4 ++ ++ subs w5, w5, #96 ++ ++ USAND10 v16, v17, v18, v0, v1 ++ USAND10 v19, v20, v21, v2, v3 ++ USAND10 v22, v23, v24, v4, v5 ++ USAND10 v25, v26, v27, v6, v7 ++ ++ blt 2f ++ ++ st3 {v16.8h, v17.8h, v18.8h}, [x0], #48 ++ st3 {v19.8h, v20.8h, v21.8h}, [x0], #48 ++ st3 {v22.8h, v23.8h, v24.8h}, [x0], #48 ++ st3 {v25.8h, v26.8h, v27.8h}, [x0], #48 ++ ++ bne 1b ++ ++11: ++ subs w6, w6, #1 ++ add x0, x0, w1, uxtw ++ add x8, x8, #128 ++ bne 10b ++ ++ ret ++ ++// Partial final write ++2: ++ cmp w5, #48-96 ++ blt 1f ++ st3 {v16.8h, v17.8h, v18.8h}, [x0], #48 ++ st3 {v19.8h, v20.8h, v21.8h}, [x0], #48 ++ beq 11b ++ mov v16.16b, v22.16b ++ mov v17.16b, v23.16b ++ sub w5, w5, #48 ++ mov v18.16b, v24.16b ++ mov v19.16b, v25.16b ++ mov v20.16b, v26.16b ++ mov v21.16b, v27.16b ++1: ++ cmp w5, #24-96 ++ blt 1f ++ st3 {v16.8h, v17.8h, v18.8h}, [x0], #48 ++ beq 11b ++ mov v16.16b, v19.16b ++ mov v17.16b, v20.16b ++ sub w5, w5, #24 ++ mov v18.16b, v21.16b ++1: ++ cmp w5, #12-96 ++ blt 1f ++ st3 {v16.4h, v17.4h, v18.4h}, [x0], #24 ++ beq 11b ++ mov v16.d[0], v16.d[1] ++ sub w5, w5, #12 ++ mov v17.d[0], v17.d[1] ++ mov v18.d[0], v18.d[1] ++1: ++ cmp w5, #6-96 ++ blt 1f ++ st3 {v16.h, v17.h, v18.h}[0], [x0], #6 ++ st3 {v16.h, v17.h, v18.h}[1], [x0], #6 ++ beq 11b ++ mov v16.s[0], v16.s[1] ++ sub w5, w5, #6 ++ mov v17.s[0], v17.s[1] ++ mov v18.s[0], v18.s[1] ++1: ++ cmp w5, #3-96 ++ blt 1f ++ st3 {v16.h, v17.h, v18.h}[0], [x0], #6 ++ beq 11b ++ mov v16.h[0], v16.h[1] ++ sub w5, w5, #3 ++ mov v17.h[0], v17.h[1] ++1: ++ cmp w5, #2-96 ++ blt 1f ++ st2 {v16.h, v17.h}[0], [x0], #4 ++ b 11b ++1: ++ st1 {v16.h}[0], [x0], #2 ++ b 11b ++ ++endfunc ++ ++// void ff_rpi_sand30_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] ++// ++// 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 wri ++ ++function ff_rpi_sand30_lines_to_planar_y8, export=1 ++ lsl w4, w4, #7 ++ sub w4, w4, #64 ++ uxtw x4, w4 ++ sub w1, w1, w7 ++ uxtw x6, w6 ++ add x8, x2, x6, lsl #7 ++ ldr w6, [sp, #0] ++ ++10: ++ mov x2, x8 ++ mov w5, w7 ++1: ++ ld1 {v0.4s, v1.4s, v2.4s, v3.4s}, [x2], #64 ++ ld1 {v4.4s, v5.4s, v6.4s, v7.4s}, [x2], x4 ++ ++ subs w5, w5, #96 ++ ++ // v0, v1 ++ USAND8 v16, v17, v18, v0, v1, v2, v3, v22, v23, v24 ++ USAND8 v19, v20, v21, v4, v5, v6, v7, v22, v23, v24 ++ ++ blt 2f ++ ++ st3 {v16.16b, v17.16b, v18.16b}, [x0], #48 ++ st3 {v19.16b, v20.16b, v21.16b}, [x0], #48 ++ ++ bne 1b ++ ++11: ++ subs w6, w6, #1 ++ add x0, x0, w1, uxtw ++ add x8, x8, #128 ++ bne 10b ++ ++ ret ++ ++// Partial final write ++2: ++ cmp w5, #48-96 ++ blt 1f ++ st3 {v16.16b, v17.16b, v18.16b}, [x0], #48 ++ beq 11b ++ mov v16.16b, v22.16b ++ mov v17.16b, v23.16b ++ sub w5, w5, #48 ++ mov v18.16b, v24.16b ++1: ++ cmp w5, #24-96 ++ blt 1f ++ st3 {v16.8b, v17.8b, v18.8b}, [x0], #24 ++ beq 11b ++ mov v16.d[0], v16.d[1] ++ sub w5, w5, #24 ++ mov v17.d[0], v17.d[1] ++ mov v18.d[0], v18.d[1] ++1: ++ cmp w5, #12-96 ++ blt 1f ++ st3 {v16.b, v17.b, v18.b}[0], [x0], #3 ++ st3 {v16.b, v17.b, v18.b}[1], [x0], #3 ++ st3 {v16.b, v17.b, v18.b}[2], [x0], #3 ++ st3 {v16.b, v17.b, v18.b}[3], [x0], #3 ++ beq 11b ++ mov v16.s[0], v16.s[1] ++ sub w5, w5, #12 ++ mov v17.s[0], v17.s[1] ++ mov v18.s[0], v18.s[1] ++1: ++ cmp w5, #6-96 ++ blt 1f ++ st3 {v16.b, v17.b, v18.b}[0], [x0], #3 ++ st3 {v16.b, v17.b, v18.b}[1], [x0], #3 ++ beq 11b ++ mov v16.h[0], v16.h[1] ++ sub w5, w5, #6 ++ mov v17.h[0], v17.h[1] ++ mov v18.h[0], v18.h[1] ++1: ++ cmp w5, #3-96 ++ blt 1f ++ st3 {v16.b, v17.b, v18.b}[0], [x0], #3 ++ beq 11b ++ mov v16.b[0], v16.b[1] ++ sub w5, w5, #3 ++ mov v17.b[0], v17.b[1] ++1: ++ cmp w5, #2-96 ++ blt 1f ++ st2 {v16.b, v17.b}[0], [x0], #2 ++ b 11b ++1: ++ st1 {v16.b}[0], [x0], #1 ++ b 11b ++ ++endfunc ++ +diff --git a/libavutil/aarch64/rpi_sand_neon.h b/libavutil/aarch64/rpi_sand_neon.h +new file mode 100644 +index 000000000000..e0e94f6aa1a2 +--- /dev/null ++++ b/libavutil/aarch64/rpi_sand_neon.h +@@ -0,0 +1,61 @@ ++/* ++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 ++*/ ++ ++#ifndef AVUTIL_AARCH64_RPI_SAND_NEON_H ++#define AVUTIL_AARCH64_RPI_SAND_NEON_H ++ ++#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); ++ ++void ff_rpi_sand30_lines_to_planar_y16(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_sand30_lines_to_planar_c16(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); ++ ++void ff_rpi_sand30_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); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* AVCODEC_SAND_NEON_H */ +diff --git a/libavutil/arm/Makefile b/libavutil/arm/Makefile +index 5da44b05427a..b74b7c4e2f25 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 000000000000..60e697f6819b +--- /dev/null ++++ b/libavutil/arm/rpi_sand_neon.S +@@ -0,0 +1,925 @@ ++/* ++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 ++ 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 ++ ++ vshrn.u32 d4 , q10, #14 @ Cannot vshrn.u32 #20! ++ ands lr, #127 ++ vshrn.u32 d2, q10, #10 ++ vmovn.u32 d0, q10 ++ ++ vshrn.u32 d5, q11, #14 ++ it eq ++ addeq r2, r3 ++ vshrn.u32 d3, q11, #10 ++ vmovn.u32 d1, q11 ++ ++ subs r5, #48 ++ vshr.u16 q2, #6 ++ vbic.u16 q0, #0xfc00 ++ vbic.u16 q1, #0xfc00 ++ ++ vshrn.u32 d20, q12, #14 ++ vshrn.u32 d18, q12, #10 ++ vmovn.u32 d16, q12 ++ ++ vshrn.u32 d21, q13, #14 ++ vshrn.u32 d19, q13, #10 ++ vmovn.u32 d17, q13 ++ ++ vshr.u16 q10, #6 ++ vbic.u16 q8, #0xfc00 ++ vbic.u16 q9 , #0xfc00 ++ 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 ++ 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 ++ vshrn.u32 d20, q0, #14 ++ vmovn.u32 d18, q0 ++ vshrn.u32 d0, q0, #10 ++ ands lr, #127 ++ ++ vshrn.u32 d21, q1, #14 ++ vmovn.u32 d19, q1 ++ vshrn.u32 d1, q1, #10 ++ ++ vshrn.u32 d22, q2, #10 ++ vmovn.u32 d2, q2 ++ vshrn.u32 d4, q2, #14 ++ ++ add r10, r0, #24 ++ vshrn.u32 d23, q3, #10 ++ vmovn.u32 d3, q3 ++ vshrn.u32 d5, q3, #14 ++ ++ it eq ++ addeq r4, r8 ++ vuzp.16 q0, q11 ++ vuzp.16 q9, q1 ++ vuzp.16 q10, q2 ++ ++ @ q0 V0, V3,.. ++ @ q9 U0, U3... ++ @ q10 U1, U4... ++ @ q11 U2, U5,.. ++ @ q1 V1, V4, ++ @ q2 V2, V5,.. ++ ++ subs r6, #24 ++ vbic.u16 q11, #0xfc00 ++ vbic.u16 q9, #0xfc00 ++ vshr.u16 q10, #6 ++ vshr.u16 q2, #6 ++ vbic.u16 q0, #0xfc00 ++ vbic.u16 q1, #0xfc00 ++ ++ 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 ++ ++ ++@ void ff_rpi_sand30_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 wri ++ ++function ff_rpi_sand30_lines_to_planar_y8, export=1 ++ push {r4-r8, lr} @ +24 ++ ldr r3, [sp, #24] ++ ldr r6, [sp, #36] ++ ldr r7, [sp, #32] @ y ++ mov r12, #48 ++ lsl r3, #7 ++ sub r1, r1, r6 ++ add r8, r2, r7, lsl #7 ++ ldr r7, [sp, #40] ++ ++10: ++ mov r2, r8 ++ add r4, r0, #24 ++ mov r5, r6 ++1: ++ vldm r2, {q8-q15} ++ ++ subs r5, #96 ++ ++ vmovn.u32 d0, q8 ++ vshrn.u32 d2, q8, #12 ++ vshrn.u32 d4, q8, #16 @ Cannot vshrn.u32 #20! ++ ++ add r2, r3 ++ ++ vmovn.u32 d1, q9 ++ vshrn.u32 d3, q9, #12 ++ vshrn.u32 d5, q9, #16 ++ ++ pld [r2, #0] ++ ++ vshrn.u16 d0, q0, #2 ++ vmovn.u16 d1, q1 ++ vshrn.u16 d2, q2, #6 ++ ++ vmovn.u32 d16, q10 ++ vshrn.u32 d18, q10, #12 ++ vshrn.u32 d20, q10, #16 ++ ++ vmovn.u32 d17, q11 ++ vshrn.u32 d19, q11, #12 ++ vshrn.u32 d21, q11, #16 ++ ++ pld [r2, #64] ++ ++ vshrn.u16 d4, q8, #2 ++ vmovn.u16 d5, q9 ++ vshrn.u16 d6, q10, #6 ++ ++ vmovn.u32 d16, q12 ++ vshrn.u32 d18, q12, #12 ++ vshrn.u32 d20, q12, #16 ++ ++ vmovn.u32 d17, q13 ++ vshrn.u32 d19, q13, #12 ++ vshrn.u32 d21, q13, #16 ++ ++ vshrn.u16 d16, q8, #2 ++ vmovn.u16 d17, q9 ++ vshrn.u16 d18, q10, #6 ++ ++ vmovn.u32 d20, q14 ++ vshrn.u32 d22, q14, #12 ++ vshrn.u32 d24, q14, #16 ++ ++ vmovn.u32 d21, q15 ++ vshrn.u32 d23, q15, #12 ++ vshrn.u32 d25, q15, #16 ++ ++ vshrn.u16 d20, q10, #2 ++ vmovn.u16 d21, q11 ++ vshrn.u16 d22, q12, #6 ++ ++ blt 2f ++ ++ vst3.8 {d0, d1, d2}, [r0], r12 ++ vst3.8 {d4, d5, d6}, [r4], r12 ++ vst3.8 {d16, d17, d18}, [r0], r12 ++ vst3.8 {d20, d21, d22}, [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, #48-96 ++ blt 1f ++ vst3.8 {d0, d1, d2}, [r0], r12 ++ vst3.8 {d4, d5, d6}, [r4], r12 ++ beq 11b ++ vmov q0, q8 ++ vmov q2, q10 ++ sub r5, #48 ++ vmov d2, d18 ++ vmov d6, d22 ++1: ++ cmp r5, #24-96 ++ blt 1f ++ vst3.8 {d0, d1, d2}, [r0]! ++ beq 11b ++ vmov q0, q2 ++ sub r5, #24 ++ vmov d2, d6 ++1: ++ cmp r5, #12-96 ++ blt 1f ++ vst3.8 {d0[0], d1[0], d2[0]}, [r0]! ++ vst3.8 {d0[1], d1[1], d2[1]}, [r0]! ++ vst3.8 {d0[2], d1[2], d2[2]}, [r0]! ++ vst3.8 {d0[3], d1[3], d2[3]}, [r0]! ++ beq 11b ++ vmov s0, s1 ++ sub r5, #12 ++ vmov s2, s3 ++ vmov s4, s5 ++1: ++ cmp r5, #6-96 ++ blt 1f ++ vst3.8 {d0[0], d1[0], d2[0]}, [r0]! ++ vst3.8 {d0[1], d1[1], d2[1]}, [r0]! ++ add r0, #12 ++ beq 11b ++ vshr.u32 d0, #16 ++ sub r5, #6 ++ vshr.u32 d1, #16 ++ vshr.u32 d2, #16 ++1: ++ cmp r5, #3-96 ++ blt 1f ++ vst3.8 {d0[0], d1[0], d2[0]}, [r0]! ++ beq 11b ++ sub r5, #3 ++ vshr.u32 d0, #8 ++ vshr.u32 d1, #8 ++1: ++ cmp r5, #2-96 ++ blt 1f ++ vst2.8 {d0[0], d1[0]}, [r0]! ++ b 11b ++1: ++ vst1.8 {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 000000000000..d8126676ee0c +--- /dev/null ++++ b/libavutil/arm/rpi_sand_neon.h +@@ -0,0 +1,110 @@ ++/* ++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_RPI_SAND_NEON_H ++#define AVUTIL_ARM_RPI_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 ++ ++void ff_rpi_sand30_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 ++ ++#endif // AVUTIL_ARM_SAND_NEON_H ++ +diff --git a/libavutil/frame.c b/libavutil/frame.c +index f0a0dba018a6..38458696c6ae 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" +@@ -27,6 +29,9 @@ + #include "mem.h" + #include "samplefmt.h" + #include "hwcontext.h" ++#if CONFIG_SAND ++#include "rpi_sand_fns.h" ++#endif + + static const AVSideDataDescriptor sd_props[] = { + [AV_FRAME_DATA_PANSCAN] = { "AVPanScan" }, +@@ -1077,6 +1082,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 f7806566d54c..00c5c925e31d 100644 +--- a/libavutil/frame.h ++++ b/libavutil/frame.h +@@ -1037,6 +1037,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); ++} ++ + /** + * @return side data descriptor corresponding to a given side data type, NULL + * when not available. +diff --git a/libavutil/hwcontext_drm.c b/libavutil/hwcontext_drm.c +index 0847db09a08b..73481d544e69 100644 +--- a/libavutil/hwcontext_drm.c ++++ b/libavutil/hwcontext_drm.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + + /* This was introduced in version 4.6. And may not exist all without an + * optional package. So to prevent a hard dependency on needing the Linux +@@ -31,6 +32,7 @@ + #endif + + #include ++#include + #include + + #include "avassert.h" +@@ -40,6 +42,9 @@ + #include "imgutils.h" + #include "mem.h" + ++#if CONFIG_SAND ++#include "libavutil/rpi_sand_fns.h" ++#endif + + static void drm_device_free(AVHWDeviceContext *hwdev) + { +@@ -54,6 +59,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); +@@ -140,6 +150,8 @@ 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; + #if HAVE_LINUX_DMA_BUF_H + if (flags & AV_HWFRAME_MAP_READ) + map->sync_flags |= DMA_BUF_SYNC_READ; +@@ -186,12 +198,34 @@ static int drm_map_frame(AVHWFramesContext *hwfc, + + dst->width = src->width; + dst->height = src->height; ++ // Crop copied with props ++ ++#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] ++ int mod_stride = fourcc_mod_broadcom_param(desc->objects[0].format_modifier); ++ if (mod_stride == 0) { ++ dst->linesize[3] = dst->linesize[0]; ++ dst->linesize[4] = dst->linesize[1]; ++ } ++ else { ++ dst->linesize[3] = mod_stride; ++ dst->linesize[4] = mod_stride; ++ } ++ dst->linesize[0] = 128; ++ dst->linesize[1] = 128; ++ } ++#endif + + err = ff_hwframe_map_create(src->hw_frames_ctx, dst, src, +- &drm_unmap_frame, map); ++ drm_unmap_frame, map); + if (err < 0) + goto fail; + ++ av_frame_copy_props(dst, src); + return 0; + + fail: +@@ -207,16 +241,29 @@ static int drm_transfer_get_formats(AVHWFramesContext *ctx, + enum AVHWFrameTransferDirection dir, + enum AVPixelFormat **formats) + { +- enum AVPixelFormat *pix_fmts; ++ enum AVPixelFormat *p; + +- pix_fmts = av_malloc_array(2, sizeof(*pix_fmts)); +- if (!pix_fmts) ++ p = *formats = av_malloc_array(3, sizeof(*p)); ++ if (!p) + return AVERROR(ENOMEM); + +- pix_fmts[0] = ctx->sw_format; +- pix_fmts[1] = AV_PIX_FMT_NONE; ++ // **** Offer native sand too ???? ++ *p++ = ++#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; ++ ++#if CONFIG_SAND ++ if (ctx->sw_format == AV_PIX_FMT_RPI4_10 || ++ ctx->sw_format == AV_PIX_FMT_RPI4_8 || ctx->sw_format == AV_PIX_FMT_SAND128) ++ *p++ = AV_PIX_FMT_NV12; ++#endif + +- *formats = pix_fmts; ++ *p = AV_PIX_FMT_NONE; + return 0; + } + +@@ -232,18 +279,62 @@ 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)) { ++ const unsigned int w = FFMIN(dst->width, map->width); ++ const unsigned int h = FFMIN(dst->height, map->height); ++ ++ map->crop_top = 0; ++ map->crop_bottom = 0; ++ map->crop_left = 0; ++ map->crop_right = 0; ++ ++ if (av_rpi_sand_to_planar_frame(dst, map) != 0) ++ { ++ 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; ++ // Cropping restored as part of props ++ } ++ else ++#endif ++ { ++ dst->width = map->width; ++ dst->height = map->height; ++ err = av_frame_copy(dst, map); ++ } ++ ++ av_frame_copy_props(dst, src); + +- err = av_frame_copy(dst, map); + if (err) ++ { ++ av_log(hwfc, AV_LOG_ERROR, "%s: Copy fail\n", __func__); + goto fail; ++ } + + err = 0; + fail: +@@ -258,7 +349,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/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c +index 6317ab7d0efa..7632ba7fa29f 100644 +--- a/libavutil/hwcontext_vulkan.c ++++ b/libavutil/hwcontext_vulkan.c +@@ -72,6 +72,14 @@ + #define CHECK_CU(x) FF_CUDA_CHECK_DL(cuda_cu, cu, x) + #endif + ++// Sometimes missing definitions ++#ifndef VK_EXT_VIDEO_DECODE_H264_EXTENSION_NAME ++#define VK_EXT_VIDEO_DECODE_H264_EXTENSION_NAME "VK_EXT_video_decode_h264" ++#endif ++#ifndef VK_EXT_VIDEO_DECODE_H265_EXTENSION_NAME ++#define VK_EXT_VIDEO_DECODE_H265_EXTENSION_NAME "VK_EXT_video_decode_h265" ++#endif ++ + typedef struct VulkanDevicePriv { + /** + * The public AVVulkanDeviceContext. See hwcontext_vulkan.h for it. +diff --git a/libavutil/pixdesc.c b/libavutil/pixdesc.c +index 1c0bcf2232be..c1d7dde0418d 100644 +--- a/libavutil/pixdesc.c ++++ b/libavutil/pixdesc.c +@@ -2791,6 +2791,50 @@ static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { + }, + .flags = AV_PIX_FMT_FLAG_PLANAR, + }, ++ [AV_PIX_FMT_SAND128] = { ++ .name = "sand128", ++ .nb_components = 3, ++ .log2_chroma_w = 1, ++ .log2_chroma_h = 1, ++ .comp = { ++ { 0, 1, 0, 0, 8 }, /* Y */ ++ { 1, 2, 0, 0, 8 }, /* U */ ++ { 1, 2, 1, 0, 8 }, /* 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 }, /* Y */ ++ { 1, 4, 0, 0, 10 }, /* U */ ++ { 1, 4, 2, 0, 10 }, /* V */ ++ }, ++ .flags = 0, ++ }, ++ [AV_PIX_FMT_SAND64_16] = { ++ .name = "sand64_16", ++ .nb_components = 3, ++ .log2_chroma_w = 1, ++ .log2_chroma_h = 1, ++ .comp = { ++ { 0, 2, 0, 0, 16 }, /* Y */ ++ { 1, 4, 0, 0, 16 }, /* U */ ++ { 1, 4, 2, 0, 16 }, /* V */ ++ }, ++ .flags = 0, ++ }, ++ [AV_PIX_FMT_RPI4_8] = { ++ .name = "rpi4_8", ++ .flags = AV_PIX_FMT_FLAG_HWACCEL, ++ }, ++ [AV_PIX_FMT_RPI4_10] = { ++ .name = "rpi4_10", ++ .flags = AV_PIX_FMT_FLAG_HWACCEL, ++ }, + }; + + static const char * const color_range_names[] = { +diff --git a/libavutil/pixfmt.h b/libavutil/pixfmt.h +index a7f50e169038..201d92db1ef7 100644 +--- a/libavutil/pixfmt.h ++++ b/libavutil/pixfmt.h +@@ -439,6 +439,15 @@ enum AVPixelFormat { + */ + AV_PIX_FMT_D3D12, + ++// RPI - not on ifdef so can be got at by calling progs ++// #define so code that uses this can know it is there ++#define AVUTIL_HAVE_PIX_FMT_SAND 1 ++ 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.c b/libavutil/rpi_sand_fn_pw.c +new file mode 100644 +index 000000000000..0d5d203dc3cd +--- /dev/null ++++ b/libavutil/rpi_sand_fn_pw.c +@@ -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 ++ 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 ++ 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 000000000000..5d3ea4db1e33 +--- /dev/null ++++ b/libavutil/rpi_sand_fns.c +@@ -0,0 +1,449 @@ ++/* ++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 "libavutil/arm/cpu.h" ++#include "libavutil/arm/rpi_sand_neon.h" ++#define HAVE_SAND_ASM 1 ++#elif ARCH_AARCH64 && HAVE_NEON ++#include "libavutil/aarch64/cpu.h" ++#include "libavutil/aarch64/rpi_sand_neon.h" ++#define HAVE_SAND_ASM 1 ++#else ++#define HAVE_SAND_ASM 0 ++#endif ++ ++#define PW 1 ++#include "rpi_sand_fn_pw.c" ++#undef PW ++ ++#define PW 2 ++#include "rpi_sand_fn_pw.c" ++#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 && have_neon(av_get_cpu_flags())) { ++ 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 && have_neon(av_get_cpu_flags())) { ++ 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; ++ } ++ } ++ } ++} ++ ++// Fetches a single patch - offscreen fixup not done here ++// w <= stride1 ++// single lose bottom 2 bits truncation ++// _x & _w in pixels, strides in bytes ++void av_rpi_sand30_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) ++{ ++ 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_y8(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; ++ uint8_t * d = dst; ++ ++ if (xskip0 != 0) { ++ const uint32_t p3 = *p++; ++ ++ if (xskip0 == 1) ++ *d++ = (p3 >> 12) & 0xff; ++ *d++ = (p3 >> 22) & 0xff; ++ ++ if (((x += 4) & mask) == 0) ++ p += slice_inc; ++ } ++ ++ while (x != x1) { ++ const uint32_t p3 = *p++; ++ *d++ = (p3 >> 2) & 0xff; ++ *d++ = (p3 >> 12) & 0xff; ++ *d++ = (p3 >> 22) & 0xff; ++ ++ if (((x += 4) & mask) == 0) ++ p += slice_inc; ++ } ++ ++ if (xrem1 != 0) { ++ const uint32_t p3 = *p; ++ ++ *d++ = (p3 >> 2) & 0xff; ++ if (xrem1 == 2) ++ *d++ = (p3 >> 12) & 0xff; ++ } ++ } ++} ++ ++ ++ ++// 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; ++ const unsigned int stride2_y = av_rpi_sand_frame_stride2_y(src); ++ const unsigned int stride2_c = av_rpi_sand_frame_stride2_c(src); ++ ++ // 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), stride2_y, ++ 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), stride2_c, ++ x/2, y/2, w/2, h/2); ++ break; ++ case AV_PIX_FMT_NV12: ++ av_rpi_sand_to_planar_y8(dst->data[0], dst->linesize[0], ++ src->data[0], ++ av_rpi_sand_frame_stride1(src), stride2_y, ++ x, y, w, h); ++ av_rpi_sand_to_planar_y8(dst->data[1], dst->linesize[1], ++ src->data[1], ++ av_rpi_sand_frame_stride1(src), stride2_c, ++ x/2, y/2, w, 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), stride2_y, ++ 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), stride2_c, ++ 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), stride2_y, ++ 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), stride2_c, ++ x/2, y/2, w/2, h/2); ++ break; ++ case AV_PIX_FMT_NV12: ++ av_rpi_sand30_to_planar_y8(dst->data[0], dst->linesize[0], ++ src->data[0], ++ av_rpi_sand_frame_stride1(src), stride2_y, ++ x, y, w, h); ++ av_rpi_sand30_to_planar_y8(dst->data[1], dst->linesize[1], ++ src->data[1], ++ av_rpi_sand_frame_stride1(src), stride2_c, ++ x/2, y/2, w, 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 000000000000..c4031fcb690d +--- /dev/null ++++ b/libavutil/rpi_sand_fns.h +@@ -0,0 +1,157 @@ ++/* ++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_H ++#define AVUTIL_RPI_SAND_FNS_H ++ ++#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); ++ ++void av_rpi_sand30_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); ++ ++// 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_y(const AVFrame * const frame) ++{ ++ return frame->linesize[3]; ++} ++ ++static inline unsigned int av_rpi_sand_frame_stride2_c(const AVFrame * const frame) ++{ ++ return frame->linesize[4]; ++} ++ ++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; ++} ++ ++#endif ++ +diff --git a/libswscale/aarch64/rgb2rgb.c b/libswscale/aarch64/rgb2rgb.c +index 20a25033cba2..ebbb5e04fc17 100644 +--- a/libswscale/aarch64/rgb2rgb.c ++++ b/libswscale/aarch64/rgb2rgb.c +@@ -57,6 +57,12 @@ void ff_interleave_bytes_neon(const uint8_t *src1, const uint8_t *src2, + void ff_deinterleave_bytes_neon(const uint8_t *src, uint8_t *dst1, uint8_t *dst2, + int width, int height, int srcStride, + int dst1Stride, int dst2Stride); ++void ff_bgr24toyv12_aarch64(const uint8_t *src, uint8_t *ydst, uint8_t *udst, ++ uint8_t *vdst, int width, int height, int lumStride, ++ int chromStride, int srcStride, int32_t *rgb2yuv); ++void ff_rgb24toyv12_aarch64(const uint8_t *src, uint8_t *ydst, uint8_t *udst, ++ uint8_t *vdst, int width, int height, int lumStride, ++ int chromStride, int srcStride, int32_t *rgb2yuv); + + av_cold void rgb2rgb_init_aarch64(void) + { +@@ -66,5 +72,7 @@ av_cold void rgb2rgb_init_aarch64(void) + ff_rgb24toyv12 = rgb24toyv12; + interleaveBytes = ff_interleave_bytes_neon; + deinterleaveBytes = ff_deinterleave_bytes_neon; ++ ff_rgb24toyv12 = ff_rgb24toyv12_aarch64; ++ ff_bgr24toyv12 = ff_bgr24toyv12_aarch64; + } + } +diff --git a/libswscale/aarch64/rgb2rgb_neon.S b/libswscale/aarch64/rgb2rgb_neon.S +index 1382e00261a9..a2bab11b34de 100644 +--- a/libswscale/aarch64/rgb2rgb_neon.S ++++ b/libswscale/aarch64/rgb2rgb_neon.S +@@ -296,3 +296,359 @@ function ff_deinterleave_bytes_neon, export=1 + 0: + ret + endfunc ++ ++// Expand rgb2 into r0+r1/g0+g1/b0+b1 ++.macro XRGB3Y r0, g0, b0, r1, g1, b1, r2, g2, b2 ++ uxtl \r0\().8h, \r2\().8b ++ uxtl \g0\().8h, \g2\().8b ++ uxtl \b0\().8h, \b2\().8b ++ ++ uxtl2 \r1\().8h, \r2\().16b ++ uxtl2 \g1\().8h, \g2\().16b ++ uxtl2 \b1\().8h, \b2\().16b ++.endm ++ ++// Expand rgb2 into r0+r1/g0+g1/b0+b1 ++// and pick every other el to put back into rgb2 for chroma ++.macro XRGB3YC r0, g0, b0, r1, g1, b1, r2, g2, b2 ++ XRGB3Y \r0, \g0, \b0, \r1, \g1, \b1, \r2, \g2, \b2 ++ ++ bic \r2\().8h, #0xff, LSL #8 ++ bic \g2\().8h, #0xff, LSL #8 ++ bic \b2\().8h, #0xff, LSL #8 ++.endm ++ ++.macro SMLAL3 d0, d1, s0, s1, s2, c0, c1, c2 ++ smull \d0\().4s, \s0\().4h, \c0 ++ smlal \d0\().4s, \s1\().4h, \c1 ++ smlal \d0\().4s, \s2\().4h, \c2 ++ smull2 \d1\().4s, \s0\().8h, \c0 ++ smlal2 \d1\().4s, \s1\().8h, \c1 ++ smlal2 \d1\().4s, \s2\().8h, \c2 ++.endm ++ ++// d0 may be s0 ++// s0, s2 corrupted ++.macro SHRN_Y d0, s0, s1, s2, s3, k128h ++ shrn \s0\().4h, \s0\().4s, #12 ++ shrn2 \s0\().8h, \s1\().4s, #12 ++ add \s0\().8h, \s0\().8h, \k128h\().8h // +128 (>> 3 = 16) ++ sqrshrun \d0\().8b, \s0\().8h, #3 ++ shrn \s2\().4h, \s2\().4s, #12 ++ shrn2 \s2\().8h, \s3\().4s, #12 ++ add \s2\().8h, \s2\().8h, \k128h\().8h ++ sqrshrun2 \d0\().16b, v28.8h, #3 ++.endm ++ ++.macro SHRN_C d0, s0, s1, k128b ++ shrn \s0\().4h, \s0\().4s, #14 ++ shrn2 \s0\().8h, \s1\().4s, #14 ++ sqrshrn \s0\().8b, \s0\().8h, #1 ++ add \d0\().8b, \s0\().8b, \k128b\().8b // +128 ++.endm ++ ++.macro STB2V s0, n, a ++ st1 {\s0\().b}[(\n+0)], [\a], #1 ++ st1 {\s0\().b}[(\n+1)], [\a], #1 ++.endm ++ ++.macro STB4V s0, n, a ++ STB2V \s0, (\n+0), \a ++ STB2V \s0, (\n+2), \a ++.endm ++ ++ ++// void ff_rgb24toyv12_aarch64( ++// const uint8_t *src, // x0 ++// uint8_t *ydst, // x1 ++// uint8_t *udst, // x2 ++// uint8_t *vdst, // x3 ++// int width, // w4 ++// int height, // w5 ++// int lumStride, // w6 ++// int chromStride, // w7 ++// int srcStr, // [sp, #0] ++// int32_t *rgb2yuv); // [sp, #8] ++ ++function ff_rgb24toyv12_aarch64, export=1 ++ ldr x15, [sp, #8] ++ ld3 {v3.s, v4.s, v5.s}[0], [x15], #12 ++ ld3 {v3.s, v4.s, v5.s}[1], [x15], #12 ++ ld3 {v3.s, v4.s, v5.s}[2], [x15] ++ mov v6.16b, v3.16b ++ mov v3.16b, v5.16b ++ mov v5.16b, v6.16b ++ b 99f ++endfunc ++ ++// void ff_bgr24toyv12_aarch64( ++// const uint8_t *src, // x0 ++// uint8_t *ydst, // x1 ++// uint8_t *udst, // x2 ++// uint8_t *vdst, // x3 ++// int width, // w4 ++// int height, // w5 ++// int lumStride, // w6 ++// int chromStride, // w7 ++// int srcStr, // [sp, #0] ++// int32_t *rgb2yuv); // [sp, #8] (including Mac) ++ ++// regs ++// v0-2 Src bytes - reused as chroma src ++// v3-5 Coeffs (packed very inefficiently - could be squashed) ++// v6 128b ++// v7 128h ++// v8-15 Reserved ++// v16-18 Lo Src expanded as H ++// v19 - ++// v20-22 Hi Src expanded as H ++// v23 - ++// v24 U out ++// v25 U tmp ++// v26 Y out ++// v27-29 Y tmp ++// v30 V out ++// v31 V tmp ++ ++function ff_bgr24toyv12_aarch64, export=1 ++ ldr x15, [sp, #8] ++ ld3 {v3.s, v4.s, v5.s}[0], [x15], #12 ++ ld3 {v3.s, v4.s, v5.s}[1], [x15], #12 ++ ld3 {v3.s, v4.s, v5.s}[2], [x15] ++ ++99: ++ ldr w14, [sp, #0] ++ movi v7.8b, #128 ++ uxtl v6.8h, v7.8b ++ // Ensure if nothing to do then we do nothing ++ cmp w4, #0 ++ b.le 90f ++ cmp w5, #0 ++ b.le 90f ++ // If w % 16 != 0 then -16 so we do main loop 1 fewer times with ++ // the remainder done in the tail ++ tst w4, #15 ++ b.eq 1f ++ sub w4, w4, #16 ++1: ++ ++// -------------------- Even line body - YUV ++11: ++ subs w9, w4, #0 ++ mov x10, x0 ++ mov x11, x1 ++ mov x12, x2 ++ mov x13, x3 ++ b.lt 12f ++ ++ ld3 {v0.16b, v1.16b, v2.16b}, [x10], #48 ++ subs w9, w9, #16 ++ b.le 13f ++ ++10: ++ XRGB3YC v16, v17, v18, v20, v21, v22, v0, v1, v2 ++ ++ // Testing shows it is faster to stack the smull/smlal ops together ++ // rather than interleave them between channels and indeed even the ++ // shift/add sections seem happier not interleaved ++ ++ // Y0 ++ SMLAL3 v26, v27, v16, v17, v18, v3.h[0], v4.h[0], v5.h[0] ++ // Y1 ++ SMLAL3 v28, v29, v20, v21, v22, v3.h[0], v4.h[0], v5.h[0] ++ SHRN_Y v26, v26, v27, v28, v29, v6 ++ ++ // U ++ // Vector subscript *2 as we loaded into S but are only using H ++ SMLAL3 v24, v25, v0, v1, v2, v3.h[2], v4.h[2], v5.h[2] ++ ++ // V ++ SMLAL3 v30, v31, v0, v1, v2, v3.h[4], v4.h[4], v5.h[4] ++ ++ ld3 {v0.16b, v1.16b, v2.16b}, [x10], #48 ++ ++ SHRN_C v24, v24, v25, v7 ++ SHRN_C v30, v30, v31, v7 ++ ++ subs w9, w9, #16 ++ ++ st1 {v26.16b}, [x11], #16 ++ st1 {v24.8b}, [x12], #8 ++ st1 {v30.8b}, [x13], #8 ++ ++ b.gt 10b ++ ++// -------------------- Even line tail - YUV ++// If width % 16 == 0 then simply runs once with preloaded RGB ++// If other then deals with preload & then does remaining tail ++ ++13: ++ // Body is simple copy of main loop body minus preload ++ ++ XRGB3YC v16, v17, v18, v20, v21, v22, v0, v1, v2 ++ // Y0 ++ SMLAL3 v26, v27, v16, v17, v18, v3.h[0], v4.h[0], v5.h[0] ++ // Y1 ++ SMLAL3 v28, v29, v20, v21, v22, v3.h[0], v4.h[0], v5.h[0] ++ SHRN_Y v26, v26, v27, v28, v29, v6 ++ // U ++ SMLAL3 v24, v25, v0, v1, v2, v3.h[2], v4.h[2], v5.h[2] ++ // V ++ SMLAL3 v30, v31, v0, v1, v2, v3.h[4], v4.h[4], v5.h[4] ++ ++ cmp w9, #-16 ++ ++ SHRN_C v24, v24, v25, v7 ++ SHRN_C v30, v30, v31, v7 ++ ++ // Here: ++ // w9 == 0 width % 16 == 0, tail done ++ // w9 > -16 1st tail done (16 pels), remainder still to go ++ // w9 == -16 shouldn't happen ++ // w9 > -32 2nd tail done ++ // w9 <= -32 shouldn't happen ++ ++ b.lt 2f ++ st1 {v26.16b}, [x11], #16 ++ st1 {v24.8b}, [x12], #8 ++ st1 {v30.8b}, [x13], #8 ++ cbz w9, 3f ++ ++12: ++ sub w9, w9, #16 ++ ++ tbz w9, #3, 1f ++ ld3 {v0.8b, v1.8b, v2.8b}, [x10], #24 ++1: tbz w9, #2, 1f ++ ld3 {v0.b, v1.b, v2.b}[8], [x10], #3 ++ ld3 {v0.b, v1.b, v2.b}[9], [x10], #3 ++ ld3 {v0.b, v1.b, v2.b}[10], [x10], #3 ++ ld3 {v0.b, v1.b, v2.b}[11], [x10], #3 ++1: tbz w9, #1, 1f ++ ld3 {v0.b, v1.b, v2.b}[12], [x10], #3 ++ ld3 {v0.b, v1.b, v2.b}[13], [x10], #3 ++1: tbz w9, #0, 13b ++ ld3 {v0.b, v1.b, v2.b}[14], [x10], #3 ++ b 13b ++ ++2: ++ tbz w9, #3, 1f ++ st1 {v26.8b}, [x11], #8 ++ STB4V v24, 0, x12 ++ STB4V v30, 0, x13 ++1: tbz w9, #2, 1f ++ STB4V v26 8, x11 ++ STB2V v24, 4, x12 ++ STB2V v30, 4, x13 ++1: tbz w9, #1, 1f ++ STB2V v26, 12, x11 ++ st1 {v24.b}[6], [x12], #1 ++ st1 {v30.b}[6], [x13], #1 ++1: tbz w9, #0, 1f ++ st1 {v26.b}[14], [x11] ++ st1 {v24.b}[7], [x12] ++ st1 {v30.b}[7], [x13] ++1: ++3: ++ ++// -------------------- Odd line body - Y only ++ ++ subs w5, w5, #1 ++ b.eq 90f ++ ++ subs w9, w4, #0 ++ add x0, x0, w14, sxtw ++ add x1, x1, w6, sxtw ++ mov x10, x0 ++ mov x11, x1 ++ b.lt 12f ++ ++ ld3 {v0.16b, v1.16b, v2.16b}, [x10], #48 ++ subs w9, w9, #16 ++ b.le 13f ++ ++10: ++ XRGB3Y v16, v17, v18, v20, v21, v22, v0, v1, v2 ++ // Y0 ++ SMLAL3 v26, v27, v16, v17, v18, v3.h[0], v4.h[0], v5.h[0] ++ // Y1 ++ SMLAL3 v28, v29, v20, v21, v22, v3.h[0], v4.h[0], v5.h[0] ++ ++ ld3 {v0.16b, v1.16b, v2.16b}, [x10], #48 ++ ++ SHRN_Y v26, v26, v27, v28, v29, v6 ++ ++ subs w9, w9, #16 ++ ++ st1 {v26.16b}, [x11], #16 ++ ++ b.gt 10b ++ ++// -------------------- Odd line tail - Y ++// If width % 16 == 0 then simply runs once with preloaded RGB ++// If other then deals with preload & then does remaining tail ++ ++13: ++ // Body is simple copy of main loop body minus preload ++ ++ XRGB3Y v16, v17, v18, v20, v21, v22, v0, v1, v2 ++ // Y0 ++ SMLAL3 v26, v27, v16, v17, v18, v3.h[0], v4.h[0], v5.h[0] ++ // Y1 ++ SMLAL3 v28, v29, v20, v21, v22, v3.h[0], v4.h[0], v5.h[0] ++ ++ cmp w9, #-16 ++ ++ SHRN_Y v26, v26, v27, v28, v29, v6 ++ ++ // Here: ++ // w9 == 0 width % 16 == 0, tail done ++ // w9 > -16 1st tail done (16 pels), remainder still to go ++ // w9 == -16 shouldn't happen ++ // w9 > -32 2nd tail done ++ // w9 <= -32 shouldn't happen ++ ++ b.lt 2f ++ st1 {v26.16b}, [x11], #16 ++ cbz w9, 3f ++ ++12: ++ sub w9, w9, #16 ++ ++ tbz w9, #3, 1f ++ ld3 {v0.8b, v1.8b, v2.8b}, [x10], #24 ++1: tbz w9, #2, 1f ++ ld3 {v0.b, v1.b, v2.b}[8], [x10], #3 ++ ld3 {v0.b, v1.b, v2.b}[9], [x10], #3 ++ ld3 {v0.b, v1.b, v2.b}[10], [x10], #3 ++ ld3 {v0.b, v1.b, v2.b}[11], [x10], #3 ++1: tbz w9, #1, 1f ++ ld3 {v0.b, v1.b, v2.b}[12], [x10], #3 ++ ld3 {v0.b, v1.b, v2.b}[13], [x10], #3 ++1: tbz w9, #0, 13b ++ ld3 {v0.b, v1.b, v2.b}[14], [x10], #3 ++ b 13b ++ ++2: ++ tbz w9, #3, 1f ++ st1 {v26.8b}, [x11], #8 ++1: tbz w9, #2, 1f ++ STB4V v26, 8, x11 ++1: tbz w9, #1, 1f ++ STB2V v26, 12, x11 ++1: tbz w9, #0, 1f ++ st1 {v26.b}[14], [x11] ++1: ++3: ++ ++// ------------------- Loop to start ++ ++ add x0, x0, w14, sxtw ++ add x1, x1, w6, sxtw ++ add x2, x2, w7, sxtw ++ add x3, x3, w7, sxtw ++ subs w5, w5, #1 ++ b.gt 11b ++90: ++ ret ++endfunc +diff --git a/libswscale/rgb2rgb.c b/libswscale/rgb2rgb.c +index e98fdac8ead6..c3b9079d2b3e 100644 +--- a/libswscale/rgb2rgb.c ++++ b/libswscale/rgb2rgb.c +@@ -83,6 +83,31 @@ void (*ff_rgb24toyv12)(const uint8_t *src, uint8_t *ydst, + int width, int height, + int lumStride, int chromStride, int srcStride, + int32_t *rgb2yuv); ++void (*ff_bgr24toyv12)(const uint8_t *src, uint8_t *ydst, ++ uint8_t *udst, uint8_t *vdst, ++ int width, int height, ++ int lumStride, int chromStride, int srcStride, ++ int32_t *rgb2yuv); ++void (*ff_rgbxtoyv12)(const uint8_t *src, uint8_t *ydst, ++ uint8_t *udst, uint8_t *vdst, ++ int width, int height, ++ int lumStride, int chromStride, int srcStride, ++ int32_t *rgb2yuv); ++void (*ff_bgrxtoyv12)(const uint8_t *src, uint8_t *ydst, ++ uint8_t *udst, uint8_t *vdst, ++ int width, int height, ++ int lumStride, int chromStride, int srcStride, ++ int32_t *rgb2yuv); ++void (*ff_xrgbtoyv12)(const uint8_t *src, uint8_t *ydst, ++ uint8_t *udst, uint8_t *vdst, ++ int width, int height, ++ int lumStride, int chromStride, int srcStride, ++ int32_t *rgb2yuv); ++void (*ff_xbgrtoyv12)(const uint8_t *src, uint8_t *ydst, ++ uint8_t *udst, uint8_t *vdst, ++ int width, int height, ++ int lumStride, int chromStride, int srcStride, ++ int32_t *rgb2yuv); + void (*planar2x)(const uint8_t *src, uint8_t *dst, int width, int height, + int srcStride, int dstStride); + void (*interleaveBytes)(const uint8_t *src1, const uint8_t *src2, uint8_t *dst, +diff --git a/libswscale/rgb2rgb.h b/libswscale/rgb2rgb.h +index e3b088390184..b8b1d649033e 100644 +--- a/libswscale/rgb2rgb.h ++++ b/libswscale/rgb2rgb.h +@@ -79,6 +79,9 @@ void rgb12to15(const uint8_t *src, uint8_t *dst, int src_size); + void ff_rgb24toyv12_c(const uint8_t *src, uint8_t *ydst, uint8_t *udst, + uint8_t *vdst, int width, int height, int lumStride, + int chromStride, int srcStride, int32_t *rgb2yuv); ++void ff_bgr24toyv12_c(const uint8_t *src, uint8_t *ydst, uint8_t *udst, ++ uint8_t *vdst, int width, int height, int lumStride, ++ int chromStride, int srcStride, int32_t *rgb2yuv); + + /** + * Height should be a multiple of 2 and width should be a multiple of 16. +@@ -126,6 +129,26 @@ extern void (*ff_rgb24toyv12)(const uint8_t *src, uint8_t *ydst, uint8_t *udst, + int width, int height, + int lumStride, int chromStride, int srcStride, + int32_t *rgb2yuv); ++extern void (*ff_bgr24toyv12)(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst, ++ int width, int height, ++ int lumStride, int chromStride, int srcStride, ++ int32_t *rgb2yuv); ++extern void (*ff_rgbxtoyv12)(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst, ++ int width, int height, ++ int lumStride, int chromStride, int srcStride, ++ int32_t *rgb2yuv); ++extern void (*ff_bgrxtoyv12)(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst, ++ int width, int height, ++ int lumStride, int chromStride, int srcStride, ++ int32_t *rgb2yuv); ++extern void (*ff_xrgbtoyv12)(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst, ++ int width, int height, ++ int lumStride, int chromStride, int srcStride, ++ int32_t *rgb2yuv); ++extern void (*ff_xbgrtoyv12)(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst, ++ int width, int height, ++ int lumStride, int chromStride, int srcStride, ++ int32_t *rgb2yuv); + extern void (*planar2x)(const uint8_t *src, uint8_t *dst, int width, int height, + int srcStride, int dstStride); + +diff --git a/libswscale/rgb2rgb_template.c b/libswscale/rgb2rgb_template.c +index d4204153db51..b25aa8506edb 100644 +--- a/libswscale/rgb2rgb_template.c ++++ b/libswscale/rgb2rgb_template.c +@@ -639,6 +639,12 @@ static inline void uyvytoyv12_c(const uint8_t *src, uint8_t *ydst, + } + } + ++#if 0 ++// This is the upstream version of this function. It has centre positioned ++// chroma rather than our simpler top-left and only covers one arrangement ++// of RGB. Left here for reference and to fix some ugly diffing by git. ++// If this version is wanted - lose the entire patchset ++ + /** + * width should be a multiple of 2. + * (If this is a problem for anyone then tell me, and I will fix it.) +@@ -705,6 +711,237 @@ void ff_rgb24toyv12_c(const uint8_t *src, uint8_t *ydst, uint8_t *udst, + vdst += chromStride; + } + } ++#endif ++ ++/** ++ * Chrominance data is only taken from every second line, ++ * others are ignored. This matches the ARM64 asm. ++ */ ++static void rgb24toyv12_x(const uint8_t *src, uint8_t *ydst, uint8_t *udst, ++ uint8_t *vdst, int width, int height, int lumStride, ++ int chromStride, int srcStride, int32_t *rgb2yuv, ++ const uint8_t x[9]) ++{ ++ int32_t ry = rgb2yuv[x[0]], gy = rgb2yuv[x[1]], by = rgb2yuv[x[2]]; ++ int32_t ru = rgb2yuv[x[3]], gu = rgb2yuv[x[4]], bu = rgb2yuv[x[5]]; ++ int32_t rv = rgb2yuv[x[6]], gv = rgb2yuv[x[7]], bv = rgb2yuv[x[8]]; ++ int y; ++ const int chromWidth = width >> 1; ++ ++ for (y = 0; y < height; y += 2) { ++ int i; ++ ++ for (i = 0; i < chromWidth; i++) { ++ unsigned int b = src[6 * i + 0]; ++ unsigned int g = src[6 * i + 1]; ++ unsigned int r = src[6 * i + 2]; ++ ++ unsigned int Y = ((ry * r + gy * g + by * b) >> RGB2YUV_SHIFT) + 16; ++ unsigned int V = ((rv * r + gv * g + bv * b) >> RGB2YUV_SHIFT) + 128; ++ unsigned int U = ((ru * r + gu * g + bu * b) >> RGB2YUV_SHIFT) + 128; ++ ++ udst[i] = U; ++ vdst[i] = V; ++ ydst[2 * i] = Y; ++ ++ b = src[6 * i + 3]; ++ g = src[6 * i + 4]; ++ r = src[6 * i + 5]; ++ ++ Y = ((ry * r + gy * g + by * b) >> RGB2YUV_SHIFT) + 16; ++ ydst[2 * i + 1] = Y; ++ } ++ if ((width & 1) != 0) { ++ unsigned int b = src[6 * i + 0]; ++ unsigned int g = src[6 * i + 1]; ++ unsigned int r = src[6 * i + 2]; ++ ++ unsigned int Y = ((ry * r + gy * g + by * b) >> RGB2YUV_SHIFT) + 16; ++ unsigned int V = ((rv * r + gv * g + bv * b) >> RGB2YUV_SHIFT) + 128; ++ unsigned int U = ((ru * r + gu * g + bu * b) >> RGB2YUV_SHIFT) + 128; ++ ++ udst[i] = U; ++ vdst[i] = V; ++ ydst[2 * i] = Y; ++ } ++ ydst += lumStride; ++ src += srcStride; ++ ++ if (y+1 == height) ++ break; ++ ++ for (i = 0; i < chromWidth; i++) { ++ unsigned int b = src[6 * i + 0]; ++ unsigned int g = src[6 * i + 1]; ++ unsigned int r = src[6 * i + 2]; ++ ++ unsigned int Y = ((ry * r + gy * g + by * b) >> RGB2YUV_SHIFT) + 16; ++ ++ ydst[2 * i] = Y; ++ ++ b = src[6 * i + 3]; ++ g = src[6 * i + 4]; ++ r = src[6 * i + 5]; ++ ++ Y = ((ry * r + gy * g + by * b) >> RGB2YUV_SHIFT) + 16; ++ ydst[2 * i + 1] = Y; ++ } ++ if ((width & 1) != 0) { ++ unsigned int b = src[6 * i + 0]; ++ unsigned int g = src[6 * i + 1]; ++ unsigned int r = src[6 * i + 2]; ++ ++ unsigned int Y = ((ry * r + gy * g + by * b) >> RGB2YUV_SHIFT) + 16; ++ ++ ydst[2 * i] = Y; ++ } ++ udst += chromStride; ++ vdst += chromStride; ++ ydst += lumStride; ++ src += srcStride; ++ } ++} ++ ++static const uint8_t x_rgb[9] = { ++ RY_IDX, GY_IDX, BY_IDX, ++ RU_IDX, GU_IDX, BU_IDX, ++ RV_IDX, GV_IDX, BV_IDX, ++}; ++ ++static const uint8_t x_bgr[9] = { ++ BY_IDX, GY_IDX, RY_IDX, ++ BU_IDX, GU_IDX, RU_IDX, ++ BV_IDX, GV_IDX, RV_IDX, ++}; ++ ++void ff_rgb24toyv12_c(const uint8_t *src, uint8_t *ydst, uint8_t *udst, ++ uint8_t *vdst, int width, int height, int lumStride, ++ int chromStride, int srcStride, int32_t *rgb2yuv) ++{ ++ rgb24toyv12_x(src, ydst, udst, vdst, width, height, lumStride, chromStride, srcStride, rgb2yuv, x_rgb); ++} ++ ++void ff_bgr24toyv12_c(const uint8_t *src, uint8_t *ydst, uint8_t *udst, ++ uint8_t *vdst, int width, int height, int lumStride, ++ int chromStride, int srcStride, int32_t *rgb2yuv) ++{ ++ rgb24toyv12_x(src, ydst, udst, vdst, width, height, lumStride, chromStride, srcStride, rgb2yuv, x_bgr); ++} ++ ++static void rgbxtoyv12_x(const uint8_t *src, uint8_t *ydst, uint8_t *udst, ++ uint8_t *vdst, int width, int height, int lumStride, ++ int chromStride, int srcStride, int32_t *rgb2yuv, ++ const uint8_t x[9]) ++{ ++ int32_t ry = rgb2yuv[x[0]], gy = rgb2yuv[x[1]], by = rgb2yuv[x[2]]; ++ int32_t ru = rgb2yuv[x[3]], gu = rgb2yuv[x[4]], bu = rgb2yuv[x[5]]; ++ int32_t rv = rgb2yuv[x[6]], gv = rgb2yuv[x[7]], bv = rgb2yuv[x[8]]; ++ int y; ++ const int chromWidth = width >> 1; ++ ++ for (y = 0; y < height; y += 2) { ++ int i; ++ for (i = 0; i < chromWidth; i++) { ++ unsigned int b = src[8 * i + 2]; ++ unsigned int g = src[8 * i + 1]; ++ unsigned int r = src[8 * i + 0]; ++ ++ unsigned int Y = ((ry * r + gy * g + by * b) >> RGB2YUV_SHIFT) + 16; ++ unsigned int V = ((rv * r + gv * g + bv * b) >> RGB2YUV_SHIFT) + 128; ++ unsigned int U = ((ru * r + gu * g + bu * b) >> RGB2YUV_SHIFT) + 128; ++ ++ udst[i] = U; ++ vdst[i] = V; ++ ydst[2 * i] = Y; ++ ++ b = src[8 * i + 6]; ++ g = src[8 * i + 5]; ++ r = src[8 * i + 4]; ++ ++ Y = ((ry * r + gy * g + by * b) >> RGB2YUV_SHIFT) + 16; ++ ydst[2 * i + 1] = Y; ++ } ++ if ((width & 1) != 0) { ++ unsigned int b = src[8 * i + 2]; ++ unsigned int g = src[8 * i + 1]; ++ unsigned int r = src[8 * i + 0]; ++ ++ unsigned int Y = ((ry * r + gy * g + by * b) >> RGB2YUV_SHIFT) + 16; ++ unsigned int V = ((rv * r + gv * g + bv * b) >> RGB2YUV_SHIFT) + 128; ++ unsigned int U = ((ru * r + gu * g + bu * b) >> RGB2YUV_SHIFT) + 128; ++ ++ udst[i] = U; ++ vdst[i] = V; ++ ydst[2 * i] = Y; ++ } ++ ydst += lumStride; ++ src += srcStride; ++ ++ if (y+1 == height) ++ break; ++ ++ for (i = 0; i < chromWidth; i++) { ++ unsigned int b = src[8 * i + 2]; ++ unsigned int g = src[8 * i + 1]; ++ unsigned int r = src[8 * i + 0]; ++ ++ unsigned int Y = ((ry * r + gy * g + by * b) >> RGB2YUV_SHIFT) + 16; ++ ++ ydst[2 * i] = Y; ++ ++ b = src[8 * i + 6]; ++ g = src[8 * i + 5]; ++ r = src[8 * i + 4]; ++ ++ Y = ((ry * r + gy * g + by * b) >> RGB2YUV_SHIFT) + 16; ++ ydst[2 * i + 1] = Y; ++ } ++ if ((width & 1) != 0) { ++ unsigned int b = src[8 * i + 2]; ++ unsigned int g = src[8 * i + 1]; ++ unsigned int r = src[8 * i + 0]; ++ ++ unsigned int Y = ((ry * r + gy * g + by * b) >> RGB2YUV_SHIFT) + 16; ++ ++ ydst[2 * i] = Y; ++ } ++ udst += chromStride; ++ vdst += chromStride; ++ ydst += lumStride; ++ src += srcStride; ++ } ++} ++ ++static void ff_rgbxtoyv12_c(const uint8_t *src, uint8_t *ydst, uint8_t *udst, ++ uint8_t *vdst, int width, int height, int lumStride, ++ int chromStride, int srcStride, int32_t *rgb2yuv) ++{ ++ rgbxtoyv12_x(src, ydst, udst, vdst, width, height, lumStride, chromStride, srcStride, rgb2yuv, x_rgb); ++} ++ ++static void ff_bgrxtoyv12_c(const uint8_t *src, uint8_t *ydst, uint8_t *udst, ++ uint8_t *vdst, int width, int height, int lumStride, ++ int chromStride, int srcStride, int32_t *rgb2yuv) ++{ ++ rgbxtoyv12_x(src, ydst, udst, vdst, width, height, lumStride, chromStride, srcStride, rgb2yuv, x_bgr); ++} ++ ++// As the general code does no SIMD-like ops simply adding 1 to the src address ++// will fix the ignored alpha position ++static void ff_xrgbtoyv12_c(const uint8_t *src, uint8_t *ydst, uint8_t *udst, ++ uint8_t *vdst, int width, int height, int lumStride, ++ int chromStride, int srcStride, int32_t *rgb2yuv) ++{ ++ rgbxtoyv12_x(src + 1, ydst, udst, vdst, width, height, lumStride, chromStride, srcStride, rgb2yuv, x_rgb); ++} ++ ++static void ff_xbgrtoyv12_c(const uint8_t *src, uint8_t *ydst, uint8_t *udst, ++ uint8_t *vdst, int width, int height, int lumStride, ++ int chromStride, int srcStride, int32_t *rgb2yuv) ++{ ++ rgbxtoyv12_x(src + 1, ydst, udst, vdst, width, height, lumStride, chromStride, srcStride, rgb2yuv, x_bgr); ++} ++ + + static void interleaveBytes_c(const uint8_t *src1, const uint8_t *src2, + uint8_t *dest, int width, int height, +@@ -979,6 +1216,11 @@ static av_cold void rgb2rgb_init_c(void) + yuy2toyv12 = yuy2toyv12_c; + planar2x = planar2x_c; + ff_rgb24toyv12 = ff_rgb24toyv12_c; ++ ff_bgr24toyv12 = ff_bgr24toyv12_c; ++ ff_rgbxtoyv12 = ff_rgbxtoyv12_c; ++ ff_bgrxtoyv12 = ff_bgrxtoyv12_c; ++ ff_xrgbtoyv12 = ff_xrgbtoyv12_c; ++ ff_xbgrtoyv12 = ff_xbgrtoyv12_c; + interleaveBytes = interleaveBytes_c; + deinterleaveBytes = deinterleaveBytes_c; + vu9_to_vu12 = vu9_to_vu12_c; +diff --git a/libswscale/swscale_unscaled.c b/libswscale/swscale_unscaled.c +index d403c953cc7d..766d8e21d7ea 100644 +--- a/libswscale/swscale_unscaled.c ++++ b/libswscale/swscale_unscaled.c +@@ -1698,6 +1698,91 @@ static int bgr24ToYv12Wrapper(SwsContext *c, const uint8_t *src[], + return srcSliceH; + } + ++static int rgb24ToYv12Wrapper(SwsContext *c, const uint8_t *src[], ++ int srcStride[], int srcSliceY, int srcSliceH, ++ uint8_t *dst[], int dstStride[]) ++{ ++ ff_bgr24toyv12( ++ src[0], ++ dst[0] + srcSliceY * dstStride[0], ++ dst[1] + (srcSliceY >> 1) * dstStride[1], ++ dst[2] + (srcSliceY >> 1) * dstStride[2], ++ c->srcW, srcSliceH, ++ dstStride[0], dstStride[1], srcStride[0], ++ c->input_rgb2yuv_table); ++ if (dst[3]) ++ fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255); ++ return srcSliceH; ++} ++ ++static int bgrxToYv12Wrapper(SwsContext *c, const uint8_t *src[], ++ int srcStride[], int srcSliceY, int srcSliceH, ++ uint8_t *dst[], int dstStride[]) ++{ ++ ff_bgrxtoyv12( ++ src[0], ++ dst[0] + srcSliceY * dstStride[0], ++ dst[1] + (srcSliceY >> 1) * dstStride[1], ++ dst[2] + (srcSliceY >> 1) * dstStride[2], ++ c->srcW, srcSliceH, ++ dstStride[0], dstStride[1], srcStride[0], ++ c->input_rgb2yuv_table); ++ if (dst[3]) ++ fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255); ++ return srcSliceH; ++} ++ ++static int rgbxToYv12Wrapper(SwsContext *c, const uint8_t *src[], ++ int srcStride[], int srcSliceY, int srcSliceH, ++ uint8_t *dst[], int dstStride[]) ++{ ++ ff_rgbxtoyv12( ++ src[0], ++ dst[0] + srcSliceY * dstStride[0], ++ dst[1] + (srcSliceY >> 1) * dstStride[1], ++ dst[2] + (srcSliceY >> 1) * dstStride[2], ++ c->srcW, srcSliceH, ++ dstStride[0], dstStride[1], srcStride[0], ++ c->input_rgb2yuv_table); ++ if (dst[3]) ++ fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255); ++ return srcSliceH; ++} ++ ++static int xbgrToYv12Wrapper(SwsContext *c, const uint8_t *src[], ++ int srcStride[], int srcSliceY, int srcSliceH, ++ uint8_t *dst[], int dstStride[]) ++{ ++ ff_xbgrtoyv12( ++ src[0], ++ dst[0] + srcSliceY * dstStride[0], ++ dst[1] + (srcSliceY >> 1) * dstStride[1], ++ dst[2] + (srcSliceY >> 1) * dstStride[2], ++ c->srcW, srcSliceH, ++ dstStride[0], dstStride[1], srcStride[0], ++ c->input_rgb2yuv_table); ++ if (dst[3]) ++ fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255); ++ return srcSliceH; ++} ++ ++static int xrgbToYv12Wrapper(SwsContext *c, const uint8_t *src[], ++ int srcStride[], int srcSliceY, int srcSliceH, ++ uint8_t *dst[], int dstStride[]) ++{ ++ ff_xrgbtoyv12( ++ src[0], ++ dst[0] + srcSliceY * dstStride[0], ++ dst[1] + (srcSliceY >> 1) * dstStride[1], ++ dst[2] + (srcSliceY >> 1) * dstStride[2], ++ c->srcW, srcSliceH, ++ dstStride[0], dstStride[1], srcStride[0], ++ c->input_rgb2yuv_table); ++ if (dst[3]) ++ fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255); ++ return srcSliceH; ++} ++ + static int yvu9ToYv12Wrapper(SwsContext *c, const uint8_t *src[], + int srcStride[], int srcSliceY, int srcSliceH, + uint8_t *dst[], int dstStride[]) +@@ -2021,7 +2106,6 @@ void ff_get_unscaled_swscale(SwsContext *c) + const enum AVPixelFormat dstFormat = c->dstFormat; + const int flags = c->flags; + const int dstH = c->dstH; +- const int dstW = c->dstW; + int needsDither; + + needsDither = isAnyRGB(dstFormat) && +@@ -2079,8 +2163,34 @@ void ff_get_unscaled_swscale(SwsContext *c) + /* bgr24toYV12 */ + if (srcFormat == AV_PIX_FMT_BGR24 && + (dstFormat == AV_PIX_FMT_YUV420P || dstFormat == AV_PIX_FMT_YUVA420P) && +- !(flags & SWS_ACCURATE_RND) && !(dstW&1)) ++ !(flags & SWS_ACCURATE_RND)) + c->convert_unscaled = bgr24ToYv12Wrapper; ++ /* rgb24toYV12 */ ++ if (srcFormat == AV_PIX_FMT_RGB24 && ++ (dstFormat == AV_PIX_FMT_YUV420P || dstFormat == AV_PIX_FMT_YUVA420P) && ++ !(flags & SWS_ACCURATE_RND)) ++ c->convert_unscaled = rgb24ToYv12Wrapper; ++ ++ /* bgrxtoYV12 */ ++ if (((srcFormat == AV_PIX_FMT_BGRA && dstFormat == AV_PIX_FMT_YUV420P) || ++ (srcFormat == AV_PIX_FMT_BGR0 && (dstFormat == AV_PIX_FMT_YUV420P || dstFormat == AV_PIX_FMT_YUVA420P))) && ++ !(flags & SWS_ACCURATE_RND)) ++ c->convert_unscaled = bgrxToYv12Wrapper; ++ /* rgbx24toYV12 */ ++ if (((srcFormat == AV_PIX_FMT_RGBA && dstFormat == AV_PIX_FMT_YUV420P) || ++ (srcFormat == AV_PIX_FMT_RGB0 && (dstFormat == AV_PIX_FMT_YUV420P || dstFormat == AV_PIX_FMT_YUVA420P))) && ++ !(flags & SWS_ACCURATE_RND)) ++ c->convert_unscaled = rgbxToYv12Wrapper; ++ /* xbgrtoYV12 */ ++ if (((srcFormat == AV_PIX_FMT_ABGR && dstFormat == AV_PIX_FMT_YUV420P) || ++ (srcFormat == AV_PIX_FMT_0BGR && (dstFormat == AV_PIX_FMT_YUV420P || dstFormat == AV_PIX_FMT_YUVA420P))) && ++ !(flags & SWS_ACCURATE_RND)) ++ c->convert_unscaled = xbgrToYv12Wrapper; ++ /* xrgb24toYV12 */ ++ if (((srcFormat == AV_PIX_FMT_ARGB && dstFormat == AV_PIX_FMT_YUV420P) || ++ (srcFormat == AV_PIX_FMT_0RGB && (dstFormat == AV_PIX_FMT_YUV420P || dstFormat == AV_PIX_FMT_YUVA420P))) && ++ !(flags & SWS_ACCURATE_RND)) ++ c->convert_unscaled = xrgbToYv12Wrapper; + + /* RGB/BGR -> RGB/BGR (no dither needed forms) */ + if (isAnyRGB(srcFormat) && isAnyRGB(dstFormat) && findRgbConvFn(c) +diff --git a/libswscale/tests/swscale.c b/libswscale/tests/swscale.c +index cf8d04de8983..97d5a4bd2ebc 100644 +--- a/libswscale/tests/swscale.c ++++ b/libswscale/tests/swscale.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + + #undef HAVE_AV_CONFIG_H + #include "libavutil/cpu.h" +@@ -98,6 +99,15 @@ struct Results { + uint32_t crc; + }; + ++static int time_rep = 0; ++ ++static uint64_t utime(void) ++{ ++ struct timespec ts; ++ clock_gettime(CLOCK_MONOTONIC, &ts); ++ return ts.tv_nsec / 1000 + (uint64_t)ts.tv_sec * 1000000; ++} ++ + // test by ref -> src -> dst -> out & compare out against ref + // ref & out are YV12 + static int doTest(const uint8_t * const ref[4], int refStride[4], int w, int h, +@@ -213,7 +223,7 @@ static int doTest(const uint8_t * const ref[4], int refStride[4], int w, int h, + goto end; + } + +- printf(" %s %dx%d -> %s %3dx%3d flags=%2d", ++ printf(" %s %4dx%4d -> %s %4dx%4d flags=%2d", + desc_src->name, srcW, srcH, + desc_dst->name, dstW, dstH, + flags); +@@ -221,6 +231,17 @@ static int doTest(const uint8_t * const ref[4], int refStride[4], int w, int h, + + sws_scale(dstContext, (const uint8_t * const*)src, srcStride, 0, srcH, dst, dstStride); + ++ if (time_rep != 0) ++ { ++ const uint64_t now = utime(); ++ uint64_t done; ++ for (i = 1; i != time_rep; ++i) { ++ sws_scale(dstContext, (const uint8_t * const*)src, srcStride, 0, srcH, dst, dstStride); ++ } ++ done = utime(); ++ printf(" T=%7"PRId64"us ", done-now); ++ } ++ + for (i = 0; i < 4 && dstStride[i]; i++) + crc = av_crc(av_crc_get_table(AV_CRC_32_IEEE), crc, dst[i], + dstStride[i] * dstH); +@@ -413,30 +434,31 @@ static int fileTest(const uint8_t * const ref[4], int refStride[4], + return 0; + } + +-#define W 96 +-#define H 96 +- + int main(int argc, char **argv) + { ++ unsigned int W = 96; ++ unsigned int H = 96; ++ unsigned int W2; ++ unsigned int H2; ++ unsigned int S; + enum AVPixelFormat srcFormat = AV_PIX_FMT_NONE; + enum AVPixelFormat dstFormat = AV_PIX_FMT_NONE; +- uint8_t *rgb_data = av_malloc(W * H * 4); +- const uint8_t * const rgb_src[4] = { rgb_data, NULL, NULL, NULL }; +- int rgb_stride[4] = { 4 * W, 0, 0, 0 }; +- uint8_t *data = av_malloc(4 * W * H); +- const uint8_t * const src[4] = { data, data + W * H, data + W * H * 2, data + W * H * 3 }; +- int stride[4] = { W, W, W, W }; + int x, y; + struct SwsContext *sws; + AVLFG rand; + int res = -1; + int i; + FILE *fp = NULL; +- +- if (!rgb_data || !data) +- return -1; ++ uint8_t *rgb_data; ++ uint8_t * rgb_src[4] = { NULL }; ++ int rgb_stride[4] = { 0 }; ++ uint8_t *data; ++ uint8_t * src[4] = { NULL }; ++ int stride[4] = { 0 }; + + for (i = 1; i < argc; i += 2) { ++ const char * const arg2 = argv[i+1]; ++ + if (!strcmp(argv[i], "-help") || !strcmp(argv[i], "--help")) { + fprintf(stderr, + "swscale [options...]\n" +@@ -459,29 +481,50 @@ int main(int argc, char **argv) + if (argv[i][0] != '-' || i + 1 == argc) + goto bad_option; + if (!strcmp(argv[i], "-ref")) { +- fp = fopen(argv[i + 1], "r"); ++ fp = fopen(arg2, "r"); + if (!fp) { +- fprintf(stderr, "could not open '%s'\n", argv[i + 1]); ++ fprintf(stderr, "could not open '%s'\n", arg2); + goto error; + } + } else if (!strcmp(argv[i], "-cpuflags")) { + unsigned flags = av_get_cpu_flags(); +- int ret = av_parse_cpu_caps(&flags, argv[i + 1]); ++ int ret = av_parse_cpu_caps(&flags, arg2); + if (ret < 0) { +- fprintf(stderr, "invalid cpu flags %s\n", argv[i + 1]); ++ fprintf(stderr, "invalid cpu flags %s\n", arg2); + return ret; + } + av_force_cpu_flags(flags); + } else if (!strcmp(argv[i], "-src")) { +- srcFormat = av_get_pix_fmt(argv[i + 1]); ++ srcFormat = av_get_pix_fmt(arg2); + if (srcFormat == AV_PIX_FMT_NONE) { +- fprintf(stderr, "invalid pixel format %s\n", argv[i + 1]); ++ fprintf(stderr, "invalid pixel format %s\n", arg2); + return -1; + } + } else if (!strcmp(argv[i], "-dst")) { +- dstFormat = av_get_pix_fmt(argv[i + 1]); ++ dstFormat = av_get_pix_fmt(arg2); + if (dstFormat == AV_PIX_FMT_NONE) { +- fprintf(stderr, "invalid pixel format %s\n", argv[i + 1]); ++ fprintf(stderr, "invalid pixel format %s\n", arg2); ++ return -1; ++ } ++ } else if (!strcmp(argv[i], "-w")) { ++ char * p = NULL; ++ W = strtoul(arg2, &p, 0); ++ if (!W || *p) { ++ fprintf(stderr, "bad width %s\n", arg2); ++ return -1; ++ } ++ } else if (!strcmp(argv[i], "-h")) { ++ char * p = NULL; ++ H = strtoul(arg2, &p, 0); ++ if (!H || *p) { ++ fprintf(stderr, "bad height '%s'\n", arg2); ++ return -1; ++ } ++ } else if (!strcmp(argv[i], "-t")) { ++ char * p = NULL; ++ time_rep = (int)strtol(arg2, &p, 0); ++ if (*p) { ++ fprintf(stderr, "bad time repetitions '%s'\n", arg2); + return -1; + } + } else if (!strcmp(argv[i], "-p")) { +@@ -495,15 +538,34 @@ bad_option: + + ff_sfc64_init(&prng_state, 0, 0, 0, 12); + +- sws = sws_getContext(W / 12, H / 12, AV_PIX_FMT_RGB32, W, H, ++ S = (W + 15) & ~15; ++ rgb_data = av_mallocz(S * H * 4); ++ rgb_src[0] = rgb_data; ++ rgb_stride[0] = 4 * S; ++ data = av_mallocz(4 * S * H); ++ src[0] = data; ++ src[1] = data + S * H; ++ src[2] = data + S * H * 2; ++ src[3] = data + S * H * 3; ++ stride[0] = S; ++ stride[1] = S; ++ stride[2] = S; ++ stride[3] = S; ++ H2 = H < 96 ? 8 : H / 12; ++ W2 = W < 96 ? 8 : W / 12; ++ ++ if (!rgb_data || !data) ++ return -1; ++ ++ sws = sws_getContext(W2, H2, AV_PIX_FMT_RGB32, W, H, + AV_PIX_FMT_YUVA420P, SWS_BILINEAR, NULL, NULL, NULL); + + av_lfg_init(&rand, 1); + + for (y = 0; y < H; y++) + for (x = 0; x < W * 4; x++) +- rgb_data[ x + y * 4 * W] = av_lfg_get(&rand); +- res = sws_scale(sws, rgb_src, rgb_stride, 0, H / 12, (uint8_t * const *) src, stride); ++ rgb_data[ x + y * 4 * S] = av_lfg_get(&rand); ++ res = sws_scale(sws, (const uint8_t * const *)rgb_src, rgb_stride, 0, H2, (uint8_t * const *) src, stride); + if (res < 0 || res != H) { + res = -1; + goto error; +@@ -512,10 +574,10 @@ bad_option: + av_free(rgb_data); + + if(fp) { +- res = fileTest(src, stride, W, H, fp, srcFormat, dstFormat); ++ res = fileTest((const uint8_t * const *)src, stride, W, H, fp, srcFormat, dstFormat); + fclose(fp); + } else { +- selfTest(src, stride, W, H, srcFormat, dstFormat); ++ selfTest((const uint8_t * const *)src, stride, W, H, srcFormat, dstFormat); + res = 0; + } + error: +diff --git a/pi-util/BUILD.txt b/pi-util/BUILD.txt +new file mode 100644 +index 000000000000..2b62d660c0d1 +--- /dev/null ++++ b/pi-util/BUILD.txt +@@ -0,0 +1,67 @@ ++Building Pi FFmpeg ++================== ++ ++Current only building on a Pi is supported. ++This builds ffmpeg the way I've tested it ++ ++Get all dependencies - the current package dependencies are good enough ++ ++$ sudo apt-get build-dep ffmpeg ++ ++Configure using the pi-util/conf_native.sh script ++------------------------------------------------- ++ ++This sets the normal release options and creates an ouutput dir to build into ++The directory name will depend on system and options but will be under out/ ++ ++There are a few choices here ++ --mmal build including the legacy mmal-based decoders and zero-copy code ++ this requires appropriate libraries which currently will exist for ++ armv7 but not arm64 ++ --noshared ++ Build a static image rather than a shared library one. Static is ++ easier for testing as there is no need to worry about library ++ paths being confused and therefore running the wrong code, Shared ++ is what is needed, in most cases, when building for use by other ++ programs. ++ --usr Set install dir to /usr (i.e. system default) rather than in ++ /install ++ ++So for a static build ++--------------------- ++ ++$ pi-util/conf_native.sh --noshared ++ ++$ make -j8 -C out/ ++ ++You can now run ffmpeg directly from where it was built ++ ++For a shared build ++------------------ ++ ++There are two choices here ++ ++$ pi-util/conf_native.sh ++$ make -j8 -C out/ install ++ ++This sets the install prefix to /install and is probably what you ++want if you don't want to overwrite the system files. ++ ++You can now set LD_LIBRARY_PATH appropriately and run ffmpeg from where it was ++built. You can copy the contents of /install to /usr and that mostly ++works. The only downside is that paths in pkgconfig end up being set to the ++install directory in your build directory which may be less than ideal when ++building other packages. ++ ++The alternative if you just want to replace the system libs is: ++ ++$ pi-util/conf_native.sh --usr ++$ make -j8 -C out/ ++$ sudo pi-util/clean_usr_libs.sh ++$ sudo make -j8 -C out/ install ++ ++The clean_usr_libs.sh step wipes any existing libs & includes (for all ++architectures) from the system which helps avoid confusion when running other ++progs as you can be sure you're not running old code which is unfortunately ++easy to do otherwise. ++ +diff --git a/pi-util/NOTES.txt b/pi-util/NOTES.txt +new file mode 100644 +index 000000000000..fcce72226a32 +--- /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/TESTMESA.txt b/pi-util/TESTMESA.txt +new file mode 100644 +index 000000000000..92bc13a3dfa1 +--- /dev/null ++++ b/pi-util/TESTMESA.txt +@@ -0,0 +1,82 @@ ++# 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 ++ ++sudo apt install meson libepoxy-dev libxcb-dri3-dev libxcb1-dev libx11-dev libx11-xcb-dev libdrm-dev ++ ++# Enable H265 V4L2 request decoder ++sudo su ++echo dtoverlay=rpivid-v4l2 >> /boot/config.txt ++# You may also want to add more CMA if you are going to try 4k videos ++# Change the dtoverlay=vc4-fkms-v3d line in config.txt to read ++# dtoverlay=vc4-fkms-v3d,cma-512 ++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 ++ ++# Currently on the Pi the linux headers from the debian distro don't match ++# the kernel that we ship and we need to update them - hopefully this step ++# will be unneeded in the future ++sudo apt install git bc bison flex libssl-dev make ++git clone --depth=1 https://github.com/raspberrypi/linux --branch rpi-5.10.y ++cd linux ++KERNEL=kernel7l ++make bcm2711_defconfig ++make headers_install ++sudo cp -r usr/include/linux /usr/include ++cd .. ++ ++# Config - this builds a staticly linked ffmpeg which is easier for testing ++pi-util/conf_native.sh --noshared ++ ++# Build (this is a bit dull) ++# If you want to poke the source the libavdevice/egl_vout.c contains the ++# output code - ++cd out/armv7-static-rel ++ ++# Check that you have actually configured V4L2 request ++grep HEVC_V4L2REQUEST config.h ++# You are hoping for ++# #define CONFIG_HEVC_V4L2REQUEST_HWACCEL 1 ++# if you get 0 then the config has failed ++ ++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 ++# The "show_all 1" forces vout to display every frame otherwise it drops any ++# frame that would cause it to block ++./ffmpeg -no_cvt_hw -hwaccel drm -vcodec hevc -i jellyfish-3-mbps-hd-hevc.mkv -show_all 1 -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/pi-util/clean_usr_libs.sh b/pi-util/clean_usr_libs.sh +new file mode 100755 +index 000000000000..01bd6a6a2254 +--- /dev/null ++++ b/pi-util/clean_usr_libs.sh +@@ -0,0 +1,42 @@ ++set -e ++U=/usr/include/arm-linux-gnueabihf ++rm -rf $U/libavcodec ++rm -rf $U/libavdevice ++rm -rf $U/libavfilter ++rm -rf $U/libavformat ++rm -rf $U/libavutil ++rm -rf $U/libswresample ++rm -rf $U/libswscale ++U=/usr/include/aarch64-linux-gnu ++rm -rf $U/libavcodec ++rm -rf $U/libavdevice ++rm -rf $U/libavfilter ++rm -rf $U/libavformat ++rm -rf $U/libavutil ++rm -rf $U/libswresample ++rm -rf $U/libswscale ++U=/usr/lib/arm-linux-gnueabihf ++rm -f $U/libavcodec.* ++rm -f $U/libavdevice.* ++rm -f $U/libavfilter.* ++rm -f $U/libavformat.* ++rm -f $U/libavutil.* ++rm -f $U/libswresample.* ++rm -f $U/libswscale.* ++U=/usr/lib/arm-linux-gnueabihf/neon/vfp ++rm -f $U/libavcodec.* ++rm -f $U/libavdevice.* ++rm -f $U/libavfilter.* ++rm -f $U/libavformat.* ++rm -f $U/libavutil.* ++rm -f $U/libswresample.* ++rm -f $U/libswscale.* ++U=/usr/lib/aarch64-linux-gnu ++rm -f $U/libavcodec.* ++rm -f $U/libavdevice.* ++rm -f $U/libavfilter.* ++rm -f $U/libavformat.* ++rm -f $U/libavutil.* ++rm -f $U/libswresample.* ++rm -f $U/libswscale.* ++ +diff --git a/pi-util/conf_arm64_native.sh b/pi-util/conf_arm64_native.sh +new file mode 100644 +index 000000000000..9e3bbfa1908a +--- /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 000000000000..177f1c8111fd +--- /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 ++2,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 000000000000..60826412715c +--- /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 000000000000..fc14f2a3c2bb +--- /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 000000000000..0dbaa53e97e0 +--- /dev/null ++++ b/pi-util/conf_native.sh +@@ -0,0 +1,135 @@ ++echo "Configure for native build" ++ ++FFSRC=`pwd` ++MC=`dpkg --print-architecture` ++BUILDBASE=$FFSRC/out ++ ++#RPI_KEEPS="-save-temps=obj" ++RPI_KEEPS="" ++ ++NOSHARED= ++MMAL= ++USR_PREFIX= ++TOOLCHAIN= ++R=rel ++ ++while [ "$1" != "" ] ; do ++ case $1 in ++ --noshared) ++ NOSHARED=1 ++ ;; ++ --mmal) ++ MMAL=1 ++ ;; ++ --usr) ++ USR_PREFIX=/usr ++ ;; ++ --tsan) ++ TOOLCHAIN="--toolchain=gcc-tsan" ++ R=tsan ++ ;; ++ *) ++ echo "Usage $0: [--noshared] [--mmal] [--usr]" ++ echo " noshared Build static libs and executable - good for testing" ++ echo " mmal Build mmal decoders" ++ echo " usr Set install prefix to /usr [default=/install]" ++ exit 1 ++ ;; ++ esac ++ shift ++done ++ ++ ++MCOPTS= ++RPI_INCLUDES= ++RPI_LIBDIRS= ++RPI_DEFINES= ++RPI_EXTRALIBS= ++ ++# uname -m gives kernel type which may not have the same ++# 32/64bitness as userspace :-( getconf shoudl provide the answer ++# but use uname to check we are on the right processor ++MC=`uname -m` ++LB=`getconf LONG_BIT` ++if [ "$MC" == "armv7l" ] || [ "$MC" == "aarch64" ]; then ++ if [ "$LB" == "32" ]; then ++ echo "M/C armv7" ++ A=arm-linux-gnueabihf ++ B=armv7 ++ MCOPTS="--arch=armv6t2 --cpu=cortex-a7" ++ RPI_DEFINES=-mfpu=neon-vfpv4 ++ elif [ "$LB" == "64" ]; then ++ echo "M/C aarch64" ++ A=aarch64-linux-gnu ++ B=arm64 ++ else ++ echo "Unknown LONG_BIT name: $LB" ++ exit 1 ++ fi ++else ++ echo "Unknown machine name: $MC" ++ exit 1 ++fi ++ ++if [ $MMAL ]; then ++ 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="$RPI_DEFINES -D__VCCOREVER__=0x4000000" ++ RPI_EXTRALIBS="-Wl,--start-group -lbcm_host -lmmal -lmmal_util -lmmal_core -lvcos -lvcsm -lvchostif -lvchiq_arm -Wl,--end-group" ++ RPIOPTS="--enable-mmal" ++else ++ RPIOPTS="--disable-mmal" ++fi ++ ++C=`lsb_release -sc` ++V=`cat RELEASE` ++ ++SHARED_LIBS="--enable-shared" ++if [ $NOSHARED ]; then ++ SHARED_LIBS="--disable-shared" ++ OUT=$BUILDBASE/$B-$C-$V-static-$R ++ echo Static libs ++else ++ echo Shared libs ++ OUT=$BUILDBASE/$B-$C-$V-shared-$R ++fi ++ ++if [ ! $USR_PREFIX ]; then ++ USR_PREFIX=$OUT/install ++fi ++LIB_PREFIX=$USR_PREFIX/lib/$A ++INC_PREFIX=$USR_PREFIX/include/$A ++ ++echo Destination directory: $OUT ++mkdir -p $OUT ++# Nothing under here need worry git - including this .gitignore! ++echo "**" > $BUILDBASE/.gitignore ++cd $OUT ++ ++$FFSRC/configure \ ++ --prefix=$USR_PREFIX\ ++ --libdir=$LIB_PREFIX\ ++ --incdir=$INC_PREFIX\ ++ $MCOPTS\ ++ $TOOLCHAIN\ ++ --disable-stripping\ ++ --disable-thumb\ ++ --enable-sand\ ++ --enable-v4l2-request\ ++ --enable-libdrm\ ++ --enable-vout-egl\ ++ --enable-vout-drm\ ++ --enable-gpl\ ++ $SHARED_LIBS\ ++ $RPIOPTS\ ++ --extra-cflags="-ggdb $RPI_KEEPS $RPI_DEFINES $RPI_INCLUDES"\ ++ --extra-cxxflags="$RPI_DEFINES $RPI_INCLUDES"\ ++ --extra-ldflags="$RPI_LIBDIRS"\ ++ --extra-libs="$RPI_EXTRALIBS"\ ++ --extra-version="rpi" ++ ++echo "Configured into $OUT" ++ ++# 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 000000000000..02af4583aeea +--- /dev/null ++++ b/pi-util/ffconf.py +@@ -0,0 +1,268 @@ ++#!/usr/bin/env python3 ++ ++import string ++import os ++import subprocess ++import re ++import argparse ++import sys ++import csv ++from stat import * ++ ++class DecodeType: ++ def __init__(self, textname, hwaccel): ++ self.textname = textname ++ self.hwaccel = hwaccel ++ ++hwaccel_rpi = DecodeType("RPI Test/Legacy", "rpi") ++hwaccel_sw = DecodeType("Software", None) ++hwaccel_drm = DecodeType("DRM Prime", "drm") ++hwaccel_vaapi = DecodeType("VAAPI", "vaapi") ++ ++def testone(fileroot, srcname, es_file, md5_file, pix, dectype, vcodec, args): ++ ffmpeg_exec = args.ffmpeg ++ gen_yuv = args.gen_yuv ++ valgrind = args.valgrind ++ rv = 0 ++ ++ 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 ++ ++ yuv_file = os.path.join(tmp_root, name + ".dec.yuv") ++ try: ++ os.remove(yuv_file) ++ except: ++ pass ++ ++ flog = open(os.path.join(tmp_root, name + ".log"), "w+t") ++ ++ ffargs = [ffmpeg_exec, "-flags", "unaligned"] +\ ++ ["-no_cvt_hw"] +\ ++ (["-hwaccel", dectype.hwaccel] if dectype.hwaccel else []) +\ ++ ["-vcodec", "hevc", "-i", os.path.join(fileroot, es_file)] +\ ++ (["-conform_yuv", "1", "-f", "conform", yuv_file] if gen_yuv else ["-f", "conform", dec_file]) ++ ++ if valgrind: ++ ffargs = ['valgrind', '--leak-check=full'] + ffargs ++ ++ # Unaligned needed for cropping conformance ++ rstr = subprocess.call(ffargs, stdout=flog, stderr=subprocess.STDOUT) ++ ++ if gen_yuv: ++ with open(dec_file, 'wt') as f: ++ subprocess.call(["md5sum", yuv_file], stdout=f, 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 valgrind: ++ flog.seek(0) ++ leak = True ++ valerr = True ++ ++ for line in flog: ++ if re.search("^==[0-9]+== All heap blocks were freed", line): ++ leak = False ++ if re.search("^==[0-9]+== ERROR SUMMARY: 0 errors", line): ++ valerr = False ++ if leak or valerr: ++ rv = 4 ++ ++ if m1 and m2 and m1.group() == m2.group(): ++ print("Match: " + m1.group(), file=flog) ++ elif not m1: ++ print("****** Cannot find m1", file=flog) ++ rv = 3 ++ elif not m2: ++ print("****** Cannot find m2", file=flog) ++ rv = 2 ++ else: ++ print("****** Mismatch: " + m1.group() + " != " + m2.group(), file=flog) ++ 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, args): ++ 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, end="") ++ sys.stdout.flush() ++ ++ rv = testone(os.path.join(test_root, name), name, a[2], a[3], a[4], dectype=dectype, vcodec=vcodec, args=args) ++ 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 *") ++ elif (rv == 4) : ++ print(": * VALGRIND *") ++ else : ++ print(": * BANG *") ++ ++ print() ++ print("Tested using decode type:", dectype.textname) ++ 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") ++ ++ return unx_failures + unx_success ++ ++ ++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("--sw", action='store_true', help="Use software decode") ++ 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") ++ argp.add_argument("--ffmpeg", default="./ffmpeg", help="ffmpeg exec name; if directory given use /ffmpeg") ++ argp.add_argument("--valgrind", action='store_true', help="Run valgrind on tests") ++ argp.add_argument("--gen_yuv", action='store_true', help="Create yuv file (stored with log under /tmp)") ++ argp.add_argument("--loop", default=0, type=int, help="Loop n times, or until unexpected result") ++ args = argp.parse_args() ++ ++ if not os.path.isdir(args.test_root): ++ print("Test root dir '%s' not found" % args.test_root) ++ exit(1) ++ ++ 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 = None ++ if os.path.exists("/dev/rpivid-hevcmem"): ++ dectype = hwaccel_rpi ++ if args.drm or os.path.exists("/sys/module/rpivid_hevc") or os.path.exists("/sys/module/rpi_hevc_dec"): ++ dectype = hwaccel_drm ++ ++ if args.pi4: ++ dectype = hwaccel_rpi ++ elif args.drm: ++ dectype = hwaccel_drm ++ elif args.vaapi: ++ dectype = hwaccel_vaapi ++ elif args.sw: ++ dectype = hwaccel_sw ++ ++ if os.path.isdir(args.ffmpeg): ++ args.ffmpeg = os.path.join(args.ffmpeg, "ffmpeg") ++ if not os.path.isfile(args.ffmpeg): ++ print("FFmpeg file '%s' not found" % args.ffmpeg) ++ exit(1) ++ ++ if not dectype: ++ print("No decode type selected and no h/w detected") ++ exit(1) ++ print("Running test using decode:", dectype.textname) ++ ++ i = 0 ++ while True: ++ i = i + 1 ++ if args.loop: ++ print("== Loop ", i) ++ if doconf(csva, args.tests, args.test_root, args.vcodec, dectype, args) or (args.loop >= 0 and i > args.loop): ++ break ++ +diff --git a/pi-util/ffperf.py b/pi-util/ffperf.py +new file mode 100755 +index 000000000000..767efe2de2fa +--- /dev/null ++++ b/pi-util/ffperf.py +@@ -0,0 +1,140 @@ ++#!/usr/bin/env python3 ++ ++import shlex ++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, args): ++ cmdargs = [args.ffmpeg] ++ for x in args.args : ++ if x == '{INPUT}': ++ cmdargs.append(prefix + name) ++ elif x == '{NULL}': ++ cmdargs.append(os.devnull) ++ else: ++ cmdargs.append(x) ++ ++ stats = tstats() ++ stats.name = name ++ start_time = time.clock_gettime(time.CLOCK_MONOTONIC); ++ cproc = subprocess.Popen(cmdargs, 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("--args", default='-t 30 -i {INPUT} -f null {NULL}', help=""" ++ffmpeg arguments, default='-t 30 -i {INPUT} -f null {NULL}'; ++ {INPUT} is replaced by current inputfile path; ++ {NULL} is replaced by the system null device""") ++ 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() ++ args.args = shlex.split(args.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) ++ 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 000000000000..0948a68a7ad7 +--- /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 000000000000..67b22d2d517f +--- /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 000000000000..271a39e8460a +--- /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 000000000000..dcd05a606e85 +--- /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 000000000000..e44cfa0c3c4d +--- /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 000000000000..a4dbb6eacd18 +--- /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/testfilt.py b/pi-util/testfilt.py +new file mode 100755 +index 000000000000..b322dac0c22d +--- /dev/null ++++ b/pi-util/testfilt.py +@@ -0,0 +1,83 @@ ++#!/usr/bin/env python3 ++ ++import string ++import os ++import subprocess ++import re ++import argparse ++import sys ++import csv ++from stat import * ++ ++class validator: ++ def __init__(self): ++ self.ok = False ++ ++ def isok(self): ++ return self.ok ++ ++ def setok(self): ++ self.ok = True ++ ++class valid_regex(validator): ++ def __init__(self, regex): ++ super().__init__() ++ self.regex = re.compile(regex) ++ ++ def scanline(self, line): ++ if self.isok() or self.regex.search(line): ++ self.setok() ++ ++ ++def validate(validators, flog): ++ for line in flog: ++ for v in validators: ++ v.scanline(line) ++ ++ ok = True ++ for v in validators: ++ if not v.isok(): ++ ok = False ++ # complain ++ print("Test failed") ++ ++ if ok: ++ print("OK") ++ return ok ++ ++def runtest(name, ffmpeg, args, suffix, validators): ++ log_root = os.path.join("/tmp", "testfilt", name) ++ ofilename = os.path.join(log_root, name + suffix) ++ ++ if not os.path.exists(log_root): ++ os.makedirs(log_root) ++ ++ try: ++ os.remove(ofilename) ++ except: ++ pass ++ ++ flog = open(os.path.join(log_root, name + ".log"), "wb") ++ ffargs = [ffmpeg] + args + [ofilename] ++ ++ subprocess.call(ffargs, stdout=flog, stderr=subprocess.STDOUT, text=False) ++ flog.close ++ ++ flog = open(os.path.join(log_root, name + ".log"), "rt") ++ return validate(validators, flog) ++ ++def sayok(log_root, flog): ++ print("Woohoo") ++ return True ++ ++if __name__ == '__main__': ++ ++ argp = argparse.ArgumentParser(description="FFmpeg filter tester") ++ argp.add_argument("--ffmpeg", default="./ffmpeg", help="ffmpeg exec name") ++ args = argp.parse_args() ++ ++ runtest("ATest", args.ffmpeg, ["-v", "verbose", "-no_cvt_hw", "-an", "-c:v", "h264_v4l2m2m", "-i", ++ "/home/johncox/server/TestMedia/Sony/jellyfish-10-mbps-hd-h264.mkv", ++# "/home/jc/rpi/streams/jellyfish-3-mbps-hd-h264.mkv", ++ "-c:v", "h264_v4l2m2m", "-b:v", "2M"], ".mkv", ++ [valid_regex(r'Output stream #0:0 \(video\): 900 frames encoded; 900 packets muxed')]) +diff --git a/pi-util/v3dusage.py b/pi-util/v3dusage.py +new file mode 100755 +index 000000000000..5935a11ca553 +--- /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/tests/checkasm/Makefile b/tests/checkasm/Makefile +index ae324ced3f0c..3d1004f934f9 100644 +--- a/tests/checkasm/Makefile ++++ b/tests/checkasm/Makefile +@@ -73,8 +73,9 @@ AVUTILOBJS += av_tx.o + AVUTILOBJS += fixed_dsp.o + AVUTILOBJS += float_dsp.o + AVUTILOBJS += lls.o ++AVUTILOBJS-$(CONFIG_SAND) += rpi_sand.o + +-CHECKASMOBJS-$(CONFIG_AVUTIL) += $(AVUTILOBJS) ++CHECKASMOBJS-$(CONFIG_AVUTIL) += $(AVUTILOBJS) $(AVUTILOBJS-yes) + + CHECKASMOBJS-$(ARCH_AARCH64) += aarch64/checkasm.o + CHECKASMOBJS-$(HAVE_ARMV5TE_EXTERNAL) += arm/checkasm.o +diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c +index 5b59cdf589a1..9f6021bbdb24 100644 +--- a/tests/checkasm/checkasm.c ++++ b/tests/checkasm/checkasm.c +@@ -290,6 +290,9 @@ static const struct { + { "float_dsp", checkasm_check_float_dsp }, + { "lls", checkasm_check_lls }, + { "av_tx", checkasm_check_av_tx }, ++ #if CONFIG_SAND ++ { "rpi_sand", checkasm_check_rpi_sand }, ++ #endif + #endif + { NULL } + }; +diff --git a/tests/checkasm/checkasm.h b/tests/checkasm/checkasm.h +index 866eef01e98d..17584bf9c4e1 100644 +--- a/tests/checkasm/checkasm.h ++++ b/tests/checkasm/checkasm.h +@@ -114,6 +114,7 @@ void checkasm_check_mpegvideoencdsp(void); + void checkasm_check_nlmeans(void); + void checkasm_check_opusdsp(void); + void checkasm_check_pixblockdsp(void); ++void checkasm_check_rpi_sand(void); + void checkasm_check_sbrdsp(void); + void checkasm_check_rv34dsp(void); + void checkasm_check_rv40dsp(void); +diff --git a/tests/checkasm/rpi_sand.c b/tests/checkasm/rpi_sand.c +new file mode 100644 +index 000000000000..dd9c1350bc2a +--- /dev/null ++++ b/tests/checkasm/rpi_sand.c +@@ -0,0 +1,122 @@ ++/* ++ * Copyright (c) 2023 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 General Public License as published by ++ * the Free Software Foundation; either version 2 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 General Public License for more details. ++ * ++ * You should have received a copy of the GNU 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 "checkasm.h" ++#include "libavutil/common.h" ++#include "libavutil/rpi_sand_fns.h" ++ ++#if ARCH_ARM ++#include "libavutil/arm/cpu.h" ++#include "libavutil/arm/rpi_sand_neon.h" ++#elif ARCH_AARCH64 ++#include "libavutil/aarch64/cpu.h" ++#include "libavutil/aarch64/rpi_sand_neon.h" ++#else ++#define have_neon(flags) 0 ++#define ff_rpi_sand30_lines_to_planar_y16 NULL ++#define ff_rpi_sand30_lines_to_planar_c16 NULL ++#endif ++ ++static inline uint32_t pack30(unsigned int a, unsigned int b, unsigned int c) ++{ ++ return (a & 0x3ff) | ((b & 0x3ff) << 10) | ((c & 0x3ff) << 20); ++} ++ ++void checkasm_check_rpi_sand(void) ++{ ++ const unsigned int w = 1280; ++ const unsigned int h = 66; ++ const unsigned int stride1 = 128; ++ const unsigned int stride2 = h*3/2; ++ const unsigned int ssize = ((w+95)/96)*128*h*3/2; ++ const unsigned int ysize = ((w + 32) * (h + 32) * 2); ++ ++ uint8_t * sbuf0 = malloc(ssize); ++ uint8_t * sbuf1 = malloc(ssize); ++ uint8_t * ybuf0 = malloc(ysize); ++ uint8_t * ybuf1 = malloc(ysize); ++ uint8_t * vbuf0 = malloc(ysize); ++ uint8_t * vbuf1 = malloc(ysize); ++ uint8_t * yframe0 = (w + 32) * 16 + ybuf0; ++ uint8_t * yframe1 = (w + 32) * 16 + ybuf1; ++ uint8_t * vframe0 = (w + 32) * 16 + vbuf0; ++ uint8_t * vframe1 = (w + 32) * 16 + vbuf1; ++ unsigned int i; ++ ++ for (i = 0; i != ssize; i += 4) ++ *(uint32_t*)(sbuf0 + i) = rnd(); ++ memcpy(sbuf1, sbuf0, ssize); ++ ++ if (check_func(have_neon(av_get_cpu_flags()) ? ff_rpi_sand30_lines_to_planar_y16 : av_rpi_sand30_to_planar_y16, "rpi_sand30_to_planar_y16")) { ++ declare_func(void, 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); ++ ++ memset(ybuf0, 0xbb, ysize); ++ memset(ybuf1, 0xbb, ysize); ++ ++ call_ref(yframe0, (w + 32) * 2, sbuf0, stride1, stride2, 0, 0, w, h); ++ call_new(yframe1, (w + 32) * 2, sbuf1, stride1, stride2, 0, 0, w, h); ++ ++ if (memcmp(sbuf0, sbuf1, ssize) ++ || memcmp(ybuf0, ybuf1, ysize)) ++ fail(); ++ ++ bench_new(ybuf1, (w + 32) * 2, sbuf1, stride1, stride2, 0, 0, w, h); ++ } ++ ++ if (check_func(have_neon(av_get_cpu_flags()) ? ff_rpi_sand30_lines_to_planar_c16 : av_rpi_sand30_to_planar_c16, "rpi_sand30_to_planar_c16")) { ++ declare_func(void, uint8_t * u_dst, const unsigned int u_stride, ++ uint8_t * v_dst, const unsigned int v_stride, ++ const uint8_t * src, ++ unsigned int stride1, unsigned int stride2, ++ unsigned int _x, unsigned int y, ++ unsigned int _w, unsigned int h); ++ ++ memset(ybuf0, 0xbb, ysize); ++ memset(ybuf1, 0xbb, ysize); ++ memset(vbuf0, 0xbb, ysize); ++ memset(vbuf1, 0xbb, ysize); ++ ++ call_ref(yframe0, (w + 32), vframe0, (w + 32), sbuf0, stride1, stride2, 0, 0, w/2, h/2); ++ call_new(yframe1, (w + 32), vframe1, (w + 32), sbuf1, stride1, stride2, 0, 0, w/2, h/2); ++ ++ if (memcmp(sbuf0, sbuf1, ssize) ++ || memcmp(ybuf0, ybuf1, ysize) ++ || memcmp(vbuf0, vbuf1, ysize)) ++ fail(); ++ ++ bench_new(yframe1, (w + 32), vframe1, (w + 32), sbuf1, stride1, stride2, 0, 0, w/2, h/2); ++ } ++ ++ ++ report("sand30"); ++ ++ free(sbuf0); ++ free(sbuf1); ++ free(ybuf0); ++ free(ybuf1); ++ free(vbuf0); ++ free(vbuf1); ++} ++ +diff --git a/tests/fate/checkasm.mak b/tests/fate/checkasm.mak +index d1396cb64161..7121d5461ef9 100644 +--- a/tests/fate/checkasm.mak ++++ b/tests/fate/checkasm.mak +@@ -36,6 +36,7 @@ FATE_CHECKASM = fate-checkasm-aacencdsp \ + fate-checkasm-mpegvideoencdsp \ + fate-checkasm-opusdsp \ + fate-checkasm-pixblockdsp \ ++ fate-checkasm-rpi_sand \ + fate-checkasm-sbrdsp \ + fate-checkasm-rv34dsp \ + fate-checkasm-rv40dsp \ +diff --git a/tests/fate/filter-video.mak b/tests/fate/filter-video.mak +index 5b8a294afd18..2d67ca68fcaa 100644 +--- a/tests/fate/filter-video.mak ++++ b/tests/fate/filter-video.mak +@@ -391,9 +391,9 @@ fate-filter-fps-down-eof-pass: CMD = framecrc -lavfi testsrc2=r=7:d=3.5,fps=3:eo + fate-filter-fps-start-drop: CMD = framecrc -lavfi testsrc2=r=7:d=3.5,fps=3:start_time=1.5 + fate-filter-fps-start-fill: CMD = framecrc -lavfi testsrc2=r=7:d=1.5,setpts=PTS+14,fps=3:start_time=1.5 + +-FATE_FILTER_SAMPLES-$(call FILTERDEMDEC, FPS SCALE, MOV, QTRLE) += fate-filter-fps-cfr fate-filter-fps +-fate-filter-fps-cfr: CMD = framecrc -auto_conversion_filters -i $(TARGET_SAMPLES)/qtrle/apple-animation-variable-fps-bug.mov -r 30 -fps_mode cfr -pix_fmt yuv420p +-fate-filter-fps: CMD = framecrc -auto_conversion_filters -i $(TARGET_SAMPLES)/qtrle/apple-animation-variable-fps-bug.mov -vf fps=30 -pix_fmt yuv420p ++#FATE_FILTER_SAMPLES-$(call FILTERDEMDEC, FPS SCALE, MOV, QTRLE) += fate-filter-fps-cfr fate-filter-fps ++#fate-filter-fps-cfr: CMD = framecrc -auto_conversion_filters -i $(TARGET_SAMPLES)/qtrle/apple-animation-variable-fps-bug.mov -r 30 -fps_mode cfr -pix_fmt yuv420p ++#fate-filter-fps: CMD = framecrc -auto_conversion_filters -i $(TARGET_SAMPLES)/qtrle/apple-animation-variable-fps-bug.mov -vf fps=30 -pix_fmt yuv420p + + FATE_FILTER_SAMPLES-$(call FILTERFRAMECRC, TESTSRC2 FSYNC, FILE_PROTOCOL) += fate-filter-fsync-up fate-filter-fsync-down + fate-filter-fsync-up: tests/data/maps/fsync-up +diff --git a/tests/ref/fate/imgutils b/tests/ref/fate/imgutils +index fb2ed6d158fa..61fd261b6088 100644 +--- a/tests/ref/fate/imgutils ++++ b/tests/ref/fate/imgutils +@@ -235,6 +235,9 @@ nv24 planes: 2, linesizes: 64 128 0 0, plane_sizes: 3072 6144 + nv42 planes: 2, linesizes: 64 128 0 0, plane_sizes: 3072 6144 0 0, plane_offsets: 3072 0 0, total_size: 9216 + y210be planes: 1, linesizes: 256 0 0 0, plane_sizes: 12288 0 0 0, plane_offsets: 0 0 0, total_size: 12288 + y210le planes: 1, linesizes: 256 0 0 0, plane_sizes: 12288 0 0 0, plane_offsets: 0 0 0, total_size: 12288 ++sand128 planes: 2, linesizes: 64 64 0 0, plane_sizes: 3072 1536 0 0, plane_offsets: 3072 0 0, total_size: 4608 ++sand64_10 planes: 2, linesizes: 128 128 0 0, plane_sizes: 6144 3072 0 0, plane_offsets: 6144 0 0, total_size: 9216 ++sand64_16 planes: 2, linesizes: 128 128 0 0, plane_sizes: 6144 3072 0 0, plane_offsets: 6144 0 0, total_size: 9216 + x2rgb10le planes: 1, linesizes: 256 0 0 0, plane_sizes: 12288 0 0 0, plane_offsets: 0 0 0, total_size: 12288 + x2rgb10be planes: 1, linesizes: 256 0 0 0, plane_sizes: 12288 0 0 0, plane_offsets: 0 0 0, total_size: 12288 + x2bgr10le planes: 1, linesizes: 256 0 0 0, plane_sizes: 12288 0 0 0, plane_offsets: 0 0 0, total_size: 12288 +@@ -451,6 +454,9 @@ nv24 total_size: 9216, black_unknown_crc: 0x1c302b58, black_tv_cr + nv42 total_size: 9216, black_unknown_crc: 0x1c302b58, black_tv_crc: 0x1c302b58, black_pc_crc: 0xdf792ea7 + y210be total_size: 12288, black_unknown_crc: 0x5483d935, black_tv_crc: 0x5483d935, black_pc_crc: 0x06397bf3 + y210le total_size: 12288, black_unknown_crc: 0x5d8e1cf6, black_tv_crc: 0x5d8e1cf6, black_pc_crc: 0x8fceec45 ++sand128 total_size: 4608, black_unknown_crc: 0xd00f6cc6, black_tv_crc: 0xd00f6cc6, black_pc_crc: 0x234969af ++sand64_10 total_size: 9216, black_unknown_crc: 0xee47624d, black_tv_crc: 0xee47624d, black_pc_crc: 0x7c6afe45 ++sand64_16 total_size: 9216, black_unknown_crc: 0xfff85b60, black_tv_crc: 0xfff85b60, black_pc_crc: 0xc03cff93 + x2rgb10le total_size: 12288, black_unknown_crc: 0x00000000, black_tv_crc: 0x00000000, black_pc_crc: 0x00000000 + x2rgb10be total_size: 12288, black_unknown_crc: 0x00000000, black_tv_crc: 0x00000000, black_pc_crc: 0x00000000 + x2bgr10le total_size: 12288, black_unknown_crc: 0x00000000, black_tv_crc: 0x00000000, black_pc_crc: 0x00000000 +diff --git a/tests/ref/fate/source b/tests/ref/fate/source +index 78d3a2e0fa58..a0ab58558556 100644 +--- a/tests/ref/fate/source ++++ b/tests/ref/fate/source +@@ -1,5 +1,8 @@ + Files without standard license headers: + libavcodec/file_open.c ++libavcodec/hevc-ctrls-v1.h ++libavcodec/hevc-ctrls-v2.h ++libavcodec/hevc-ctrls-v3.h + libavcodec/interplayacm.c + libavcodec/log2_tab.c + libavcodec/reverse.c +@@ -26,6 +29,9 @@ compat/float/float.h + compat/float/limits.h + compat/stdbit/stdbit.h + libavcodec/bitstream_template.h ++libavcodec/hevc-ctrls-v1.h ++libavcodec/hevc-ctrls-v2.h ++libavcodec/hevc-ctrls-v3.h + tools/decode_simple.h + Use of av_clip() where av_clip_uintp2() could be used: + Use of av_clip() where av_clip_intp2() could be used: +diff --git a/tests/ref/fate/sws-pixdesc-query b/tests/ref/fate/sws-pixdesc-query +index fff93bbf0efd..96fefd5b8ab7 100644 +--- a/tests/ref/fate/sws-pixdesc-query ++++ b/tests/ref/fate/sws-pixdesc-query +@@ -23,6 +23,7 @@ is16BPS: + rgba64le + rgbaf16be + rgbaf16le ++ sand64_16 + ya16be + ya16le + yuv420p16be +@@ -75,6 +76,7 @@ isNBPS: + p410le + p412be + p412le ++ sand64_10 + x2bgr10be + x2bgr10le + x2rgb10be +@@ -245,6 +247,9 @@ isYUV: + p412le + p416be + p416le ++ sand128 ++ sand64_10 ++ sand64_16 + uyvy422 + uyyvyy411 + vuya +@@ -818,6 +823,9 @@ Packed: + rgbaf32le + rgbf32be + rgbf32le ++ sand128 ++ sand64_10 ++ sand64_16 + uyvy422 + uyyvyy411 + vuya 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 0000000000..4a2f18f480 --- /dev/null +++ b/packages/multimedia/ffmpeg/patches/v4l2-drmprime/ffmpeg-001-v4l2-drmprime.patch @@ -0,0 +1,814 @@ +From cf29d984c17f56df0e41f33fb28fe72160cc7869 Mon Sep 17 00:00:00 2001 +From: Lukas Rusak +Date: Tue, 24 Apr 2018 23:00:23 -0700 +Subject: [PATCH 1/8] 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 23474ee143..0013f54caa 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 +@@ -28,6 +29,7 @@ + #include + #include + #include "libavcodec/avcodec.h" ++#include "libavutil/hwcontext.h" + #include "libavutil/pixdesc.h" + #include "refstruct.h" + #include "v4l2_context.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); +@@ -252,6 +356,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; +@@ -301,13 +423,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 */ +@@ -542,9 +675,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; +@@ -554,6 +684,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 e35b161309..b83f22152c 100644 +--- a/libavcodec/v4l2_buffers.h ++++ b/libavcodec/v4l2_buffers.h +@@ -29,6 +29,7 @@ + #include + + #include "libavutil/frame.h" ++#include "libavutil/hwcontext_drm.h" + #include "packet.h" + + enum V4L2Buffer_status { +@@ -44,6 +45,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. + * This pointer is a RefStruct reference. */ +diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c +index be1df3785b..4673d025c5 100644 +--- a/libavcodec/v4l2_context.c ++++ b/libavcodec/v4l2_context.c +@@ -446,22 +446,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 4ba33dc335..76ddbf1a26 100644 +--- a/libavcodec/v4l2_m2m.h ++++ b/libavcodec/v4l2_m2m.h +@@ -66,6 +66,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 aa2d759e1e..b8dc4eb81f 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 "codec_internal.h" + #include "libavcodec/decode.h" + ++#include "libavcodec/hwaccels.h" ++#include "libavcodec/internal.h" ++ + #include "v4l2_context.h" + #include "v4l2_m2m.h" + #include "v4l2_fmt.h" +@@ -205,6 +211,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) { +@@ -230,6 +245,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[] = { + .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | \ + FF_CODEC_CAP_INIT_CLEANUP, \ + .p.wrapper_name = "v4l2m2m", \ ++ .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_DRM_PRIME, \ ++ AV_PIX_FMT_NONE}, \ ++ .hw_configs = v4l2_m2m_hw_configs, \ + } + + M2MDEC(h264, "H.264", AV_CODEC_ID_H264, "h264_mp4toannexb"); + +From b1c53282fe4a9357f5a74feebd5a4c01954930b3 Mon Sep 17 00:00:00 2001 +From: Lukas Rusak +Date: Thu, 16 Aug 2018 21:09:40 -0700 +Subject: [PATCH 2/8] 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 d77a55b653..9db1921b99 100755 +--- a/configure ++++ b/configure +@@ -3746,6 +3746,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 0013f54caa..9069520556 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 659318a5f802b42be23eb95cebb01cfd46cfac21 Mon Sep 17 00:00:00 2001 +From: Lukas Rusak +Date: Thu, 16 Aug 2018 21:10:13 -0700 +Subject: [PATCH 3/8] 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 9069520556..066bf5b8c3 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 f84379aca3bff34205648e85e0c79fd544a20e39 Mon Sep 17 00:00:00 2001 +From: Lukas Rusak +Date: Thu, 16 Aug 2018 21:10:53 -0700 +Subject: [PATCH 4/8] 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 066bf5b8c3..3a65ced497 100644 +--- a/libavcodec/v4l2_buffers.c ++++ b/libavcodec/v4l2_buffers.c +@@ -661,14 +661,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 6c02dc58f69365fd1f3c5502b481e0fae6987ff7 Mon Sep 17 00:00:00 2001 +From: Lukas Rusak +Date: Thu, 16 Aug 2018 21:11:38 -0700 +Subject: [PATCH 5/8] 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 b8dc4eb81f..28b29c4522 100644 +--- a/libavcodec/v4l2_m2m_dec.c ++++ b/libavcodec/v4l2_m2m_dec.c +@@ -217,8 +217,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[] = { + FF_CODEC_CAP_INIT_CLEANUP, \ + .p.wrapper_name = "v4l2m2m", \ + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_DRM_PRIME, \ ++ AV_PIX_FMT_NV12, \ + AV_PIX_FMT_NONE}, \ + .hw_configs = v4l2_m2m_hw_configs, \ + } + +From 45cab2ebdbd00ce6eb683dd838956049e7fe9a3f Mon Sep 17 00:00:00 2001 +From: Lukas Rusak +Date: Mon, 24 Sep 2018 13:39:31 -0700 +Subject: [PATCH 6/8] 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 3a65ced497..7285705857 100644 +--- a/libavcodec/v4l2_buffers.c ++++ b/libavcodec/v4l2_buffers.c +@@ -433,6 +433,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++) { +@@ -634,6 +635,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 6f7460c89a..02fbb6eec3 100644 +--- a/libavcodec/v4l2_context.h ++++ b/libavcodec/v4l2_context.h +@@ -93,6 +93,8 @@ typedef struct V4L2Context { + */ + int done; + ++ AVBufferRef *frames_ref; ++ + } V4L2Context; + + /** +diff --git a/libavcodec/v4l2_m2m.h b/libavcodec/v4l2_m2m.h +index 76ddbf1a26..47dfe0905f 100644 +--- a/libavcodec/v4l2_m2m.h ++++ b/libavcodec/v4l2_m2m.h +@@ -67,6 +67,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 28b29c4522..a5dc926232 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" +@@ -228,6 +229,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 221ed816ded7c3a2b265a7c3e8c06e320ba791fb Mon Sep 17 00:00:00 2001 +From: Lukas Rusak +Date: Wed, 6 May 2020 11:12:58 -0700 +Subject: [PATCH 7/8] 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 4673d025c5..1f1fd6d982 100644 +--- a/libavcodec/v4l2_context.c ++++ b/libavcodec/v4l2_context.c +@@ -522,6 +522,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; +@@ -540,6 +542,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 47dfe0905f..7b020e2373 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) ({ \ +@@ -80,6 +81,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 a5dc926232..a8f707ba4e 100644 +--- a/libavcodec/v4l2_m2m_dec.c ++++ b/libavcodec/v4l2_m2m_dec.c +@@ -261,6 +261,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 0e747a21c508567cd6ea615dba1a0dd85d38c076 Mon Sep 17 00:00:00 2001 +From: Lukas Rusak +Date: Mon, 24 Sep 2018 13:39:56 -0700 +Subject: [PATCH 8/8] 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 a8f707ba4e..5f992f0e7f 100644 +--- a/libavcodec/v4l2_m2m_dec.c ++++ b/libavcodec/v4l2_m2m_dec.c +@@ -254,6 +254,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; ++ ++ struct v4l2_decoder_cmd cmd = { ++ .cmd = V4L2_DEC_CMD_START, ++ .flags = 0, ++ }; ++ ++ 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; ++ } ++ ++ 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 + +@@ -290,6 +325,7 @@ static const AVCodecHWConfigInternal *v4l2_m2m_hw_configs[] = { + .init = v4l2_decode_init, \ + FF_CODEC_RECEIVE_FRAME_CB(v4l2_receive_frame), \ + .close = v4l2_decode_close, \ ++ .flush = v4l2_decode_flush, \ + .bsfs = bsf_name, \ + .p.capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, \ + .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | \ 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 0000000000..663d4edcd4 --- /dev/null +++ b/packages/multimedia/ffmpeg/patches/v4l2-request/ffmpeg-001-v4l2-request.patch @@ -0,0 +1,5486 @@ +From b32bc2026a32f1dea2688b619f1547781da6bdaa Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Tue, 6 Aug 2024 09:06:00 +0000 +Subject: [PATCH 01/11] avutil/hwcontext: Add hwdevice type for V4L2 Request + API + +Add a hwdevice type for V4L2 Request API with transfer_data_from support +for AV_PIX_FMT_DRM_PRIME, based on AV_HWDEVICE_TYPE_DRM. + +AVV4L2RequestDeviceContext.media_fd can be set by the application or a +media device path can be supplied when hwdevice is created. When none +is supplied it default to -1 and hwaccel will auto-detect a media device +with a capable video device. + +Signed-off-by: Jonas Karlman +--- + configure | 7 + + libavutil/Makefile | 3 + + libavutil/hwcontext.c | 4 + + libavutil/hwcontext.h | 1 + + libavutil/hwcontext_internal.h | 1 + + libavutil/hwcontext_v4l2request.c | 261 ++++++++++++++++++++++++++++++ + libavutil/hwcontext_v4l2request.h | 41 +++++ + 7 files changed, 318 insertions(+) + create mode 100644 libavutil/hwcontext_v4l2request.c + create mode 100644 libavutil/hwcontext_v4l2request.h + +diff --git a/configure b/configure +index d77a55b653..b8f82f0fbf 100755 +--- a/configure ++++ b/configure +@@ -359,6 +359,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] +@@ -2025,6 +2026,7 @@ HWACCEL_LIBRARY_LIST=" + mmal + omx + opencl ++ v4l2_request + " + + DOCUMENT_LIST=" +@@ -3146,6 +3148,7 @@ dxva2_deps="dxva2api_h DXVA2_ConfigPictureDecode ole32 user32" + ffnvcodec_deps_any="libdl LoadLibrary" + mediacodec_deps="android mediandk" + nvdec_deps="ffnvcodec" ++v4l2_request_deps="linux_media_h v4l2_timeval_to_ns" + vaapi_x11_deps="xlib_x11" + videotoolbox_hwaccel_deps="videotoolbox pthreads" + videotoolbox_hwaccel_extralibs="-framework QuartzCore" +@@ -7197,6 +7200,10 @@ if enabled v4l2_m2m; then + check_cc vp9_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_VP9;" + fi + ++if enabled v4l2_request; then ++ check_func_headers "linux/media.h linux/videodev2.h" v4l2_timeval_to_ns ++fi ++ + 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/libavutil/Makefile b/libavutil/Makefile +index 6e6fa8d800..1ce46157dd 100644 +--- a/libavutil/Makefile ++++ b/libavutil/Makefile +@@ -48,6 +48,7 @@ HEADERS = adler32.h \ + hwcontext_qsv.h \ + hwcontext_mediacodec.h \ + hwcontext_opencl.h \ ++ hwcontext_v4l2request.h \ + hwcontext_vaapi.h \ + hwcontext_videotoolbox.h \ + hwcontext_vdpau.h \ +@@ -201,6 +202,7 @@ OBJS-$(CONFIG_MACOS_KPERF) += macos_kperf.o + OBJS-$(CONFIG_MEDIACODEC) += hwcontext_mediacodec.o + OBJS-$(CONFIG_OPENCL) += hwcontext_opencl.o + OBJS-$(CONFIG_QSV) += hwcontext_qsv.o ++OBJS-$(CONFIG_V4L2_REQUEST) += hwcontext_v4l2request.o + OBJS-$(CONFIG_VAAPI) += hwcontext_vaapi.o + OBJS-$(CONFIG_VIDEOTOOLBOX) += hwcontext_videotoolbox.o + OBJS-$(CONFIG_VDPAU) += hwcontext_vdpau.o +@@ -222,6 +224,7 @@ SKIPHEADERS-$(CONFIG_D3D12VA) += hwcontext_d3d12va.h + SKIPHEADERS-$(CONFIG_DXVA2) += hwcontext_dxva2.h + SKIPHEADERS-$(CONFIG_QSV) += hwcontext_qsv.h + SKIPHEADERS-$(CONFIG_OPENCL) += hwcontext_opencl.h ++SKIPHEADERS-$(CONFIG_V4L2_REQUEST) += hwcontext_v4l2request.h + SKIPHEADERS-$(CONFIG_VAAPI) += hwcontext_vaapi.h + SKIPHEADERS-$(CONFIG_VIDEOTOOLBOX) += hwcontext_videotoolbox.h + SKIPHEADERS-$(CONFIG_VDPAU) += hwcontext_vdpau.h +diff --git a/libavutil/hwcontext.c b/libavutil/hwcontext.c +index fa99a0d8a4..7fae9381da 100644 +--- a/libavutil/hwcontext.c ++++ b/libavutil/hwcontext.c +@@ -65,6 +65,9 @@ static const HWContextType * const hw_table[] = { + #endif + #if CONFIG_VULKAN + &ff_hwcontext_type_vulkan, ++#endif ++#if CONFIG_V4L2_REQUEST ++ &ff_hwcontext_type_v4l2request, + #endif + NULL, + }; +@@ -77,6 +80,7 @@ static const char *const hw_type_names[] = { + [AV_HWDEVICE_TYPE_D3D12VA] = "d3d12va", + [AV_HWDEVICE_TYPE_OPENCL] = "opencl", + [AV_HWDEVICE_TYPE_QSV] = "qsv", ++ [AV_HWDEVICE_TYPE_V4L2REQUEST] = "v4l2request", + [AV_HWDEVICE_TYPE_VAAPI] = "vaapi", + [AV_HWDEVICE_TYPE_VDPAU] = "vdpau", + [AV_HWDEVICE_TYPE_VIDEOTOOLBOX] = "videotoolbox", +diff --git a/libavutil/hwcontext.h b/libavutil/hwcontext.h +index bac30debae..8cf50ddbd0 100644 +--- a/libavutil/hwcontext.h ++++ b/libavutil/hwcontext.h +@@ -38,6 +38,7 @@ enum AVHWDeviceType { + AV_HWDEVICE_TYPE_MEDIACODEC, + AV_HWDEVICE_TYPE_VULKAN, + AV_HWDEVICE_TYPE_D3D12VA, ++ AV_HWDEVICE_TYPE_V4L2REQUEST, + }; + + /** +diff --git a/libavutil/hwcontext_internal.h b/libavutil/hwcontext_internal.h +index e32b786238..fd0cf29c6e 100644 +--- a/libavutil/hwcontext_internal.h ++++ b/libavutil/hwcontext_internal.h +@@ -158,6 +158,7 @@ extern const HWContextType ff_hwcontext_type_drm; + extern const HWContextType ff_hwcontext_type_dxva2; + extern const HWContextType ff_hwcontext_type_opencl; + extern const HWContextType ff_hwcontext_type_qsv; ++extern const HWContextType ff_hwcontext_type_v4l2request; + extern const HWContextType ff_hwcontext_type_vaapi; + extern const HWContextType ff_hwcontext_type_vdpau; + extern const HWContextType ff_hwcontext_type_videotoolbox; +diff --git a/libavutil/hwcontext_v4l2request.c b/libavutil/hwcontext_v4l2request.c +new file mode 100644 +index 0000000000..833fbf9f40 +--- /dev/null ++++ b/libavutil/hwcontext_v4l2request.c +@@ -0,0 +1,261 @@ ++/* ++ * 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 ++#include ++#include ++#include ++#include ++#include ++ ++#include "avassert.h" ++#include "hwcontext_drm.h" ++#include "hwcontext_internal.h" ++#include "hwcontext_v4l2request.h" ++#include "mem.h" ++ ++static void v4l2request_device_free(AVHWDeviceContext *hwdev) ++{ ++ AVV4L2RequestDeviceContext *hwctx = hwdev->hwctx; ++ ++ if (hwctx->media_fd >= 0) { ++ close(hwctx->media_fd); ++ hwctx->media_fd = -1; ++ } ++} ++ ++static int v4l2request_device_create(AVHWDeviceContext *hwdev, const char *device, ++ AVDictionary *opts, int flags) ++{ ++ AVV4L2RequestDeviceContext *hwctx = hwdev->hwctx; ++ ++ hwctx->media_fd = -1; ++ hwdev->free = v4l2request_device_free; ++ ++ // Use auto-detect ++ if (!device || !device[0]) ++ return 0; ++ ++ hwctx->media_fd = open(device, O_RDWR); ++ if (hwctx->media_fd < 0) ++ return AVERROR(errno); ++ ++ return 0; ++} ++ ++static int v4l2request_device_init(AVHWDeviceContext *hwdev) ++{ ++ AVV4L2RequestDeviceContext *hwctx = hwdev->hwctx; ++ struct media_device_info device_info; ++ ++ // Use auto-detect ++ if (hwctx->media_fd < 0) ++ return 0; ++ ++ if (ioctl(hwctx->media_fd, MEDIA_IOC_DEVICE_INFO, &device_info) < 0) ++ return AVERROR(errno); ++ ++ av_log(hwdev, AV_LOG_VERBOSE, "Using V4L2 media driver %s (%u.%u.%u)\n", ++ device_info.driver, ++ device_info.driver_version >> 16, ++ (device_info.driver_version >> 8) & 0xff, ++ device_info.driver_version & 0xff); ++ ++ return 0; ++} ++ ++static int v4l2request_get_buffer(AVHWFramesContext *hwfc, AVFrame *frame) ++{ ++ frame->buf[0] = av_buffer_pool_get(hwfc->pool); ++ if (!frame->buf[0]) ++ return AVERROR(ENOMEM); ++ ++ frame->data[0] = (uint8_t *)frame->buf[0]->data; ++ ++ frame->format = AV_PIX_FMT_DRM_PRIME; ++ frame->width = hwfc->width; ++ frame->height = hwfc->height; ++ ++ return 0; ++} ++ ++typedef struct DRMMapping { ++ // Address and length of each mmap()ed region. ++ int nb_regions; ++ int object[AV_DRM_MAX_PLANES]; ++ void *address[AV_DRM_MAX_PLANES]; ++ size_t length[AV_DRM_MAX_PLANES]; ++} DRMMapping; ++ ++static void v4l2request_unmap_frame(AVHWFramesContext *hwfc, ++ HWMapDescriptor *hwmap) ++{ ++ DRMMapping *map = hwmap->priv; ++ ++ for (int i = 0; i < map->nb_regions; i++) { ++ struct dma_buf_sync sync = { ++ .flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_READ, ++ }; ++ ioctl(map->object[i], DMA_BUF_IOCTL_SYNC, &sync); ++ munmap(map->address[i], map->length[i]); ++ } ++ ++ av_free(map); ++} ++ ++static int v4l2request_map_frame(AVHWFramesContext *hwfc, ++ AVFrame *dst, const AVFrame *src) ++{ ++ const AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor *)src->data[0]; ++ struct dma_buf_sync sync = { ++ .flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_READ, ++ }; ++ DRMMapping *map; ++ int ret, i, p, plane; ++ void *addr; ++ ++ map = av_mallocz(sizeof(*map)); ++ if (!map) ++ return AVERROR(ENOMEM); ++ ++ av_assert0(desc->nb_objects <= AV_DRM_MAX_PLANES); ++ for (i = 0; i < desc->nb_objects; i++) { ++ addr = mmap(NULL, desc->objects[i].size, AV_HWFRAME_MAP_READ, MAP_SHARED, ++ desc->objects[i].fd, 0); ++ if (addr == MAP_FAILED) { ++ av_log(hwfc, AV_LOG_ERROR, "Failed to map DRM object %d to memory: %s (%d)\n", ++ desc->objects[i].fd, strerror(errno), errno); ++ ret = AVERROR(errno); ++ goto fail; ++ } ++ ++ map->address[i] = addr; ++ map->length[i] = desc->objects[i].size; ++ map->object[i] = desc->objects[i].fd; ++ ++ /* ++ * We're not checking for errors here because the kernel may not ++ * support the ioctl, in which case its okay to carry on ++ */ ++ ioctl(desc->objects[i].fd, DMA_BUF_IOCTL_SYNC, &sync); ++ } ++ map->nb_regions = i; ++ ++ plane = 0; ++ for (i = 0; i < desc->nb_layers; i++) { ++ const AVDRMLayerDescriptor *layer = &desc->layers[i]; ++ for (p = 0; p < layer->nb_planes; p++) { ++ dst->data[plane] = ++ (uint8_t *)map->address[layer->planes[p].object_index] + ++ layer->planes[p].offset; ++ dst->linesize[plane] = layer->planes[p].pitch; ++ ++plane; ++ } ++ } ++ av_assert0(plane <= AV_DRM_MAX_PLANES); ++ ++ dst->width = src->width; ++ dst->height = src->height; ++ ++ ret = ff_hwframe_map_create(src->hw_frames_ctx, dst, src, ++ v4l2request_unmap_frame, map); ++ if (ret < 0) ++ goto fail; ++ ++ return 0; ++ ++fail: ++ for (i = 0; i < desc->nb_objects; i++) { ++ if (map->address[i]) ++ munmap(map->address[i], map->length[i]); ++ } ++ av_free(map); ++ return ret; ++} ++ ++static int v4l2request_transfer_get_formats(AVHWFramesContext *hwfc, ++ enum AVHWFrameTransferDirection dir, ++ enum AVPixelFormat **formats) ++{ ++ enum AVPixelFormat *pix_fmts; ++ ++ if (dir == AV_HWFRAME_TRANSFER_DIRECTION_TO) ++ return AVERROR(ENOSYS); ++ ++ pix_fmts = av_malloc_array(2, sizeof(*pix_fmts)); ++ if (!pix_fmts) ++ return AVERROR(ENOMEM); ++ ++ pix_fmts[0] = hwfc->sw_format; ++ pix_fmts[1] = AV_PIX_FMT_NONE; ++ ++ *formats = pix_fmts; ++ return 0; ++} ++ ++static int v4l2request_transfer_data_from(AVHWFramesContext *hwfc, ++ AVFrame *dst, const AVFrame *src) ++{ ++ AVFrame *map; ++ int ret; ++ ++ if (dst->width > hwfc->width || dst->height > hwfc->height) ++ return AVERROR(EINVAL); ++ ++ map = av_frame_alloc(); ++ if (!map) ++ return AVERROR(ENOMEM); ++ map->format = dst->format; ++ ++ ret = v4l2request_map_frame(hwfc, map, src); ++ if (ret) ++ goto fail; ++ ++ map->width = dst->width; ++ map->height = dst->height; ++ ++ ret = av_frame_copy(dst, map); ++ if (ret) ++ goto fail; ++ ++ ret = 0; ++fail: ++ av_frame_free(&map); ++ return ret; ++} ++ ++const HWContextType ff_hwcontext_type_v4l2request = { ++ .type = AV_HWDEVICE_TYPE_V4L2REQUEST, ++ .name = "V4L2 Request API", ++ ++ .device_hwctx_size = sizeof(AVV4L2RequestDeviceContext), ++ .device_create = v4l2request_device_create, ++ .device_init = v4l2request_device_init, ++ ++ .frames_get_buffer = v4l2request_get_buffer, ++ ++ .transfer_get_formats = v4l2request_transfer_get_formats, ++ .transfer_data_from = v4l2request_transfer_data_from, ++ ++ .pix_fmts = (const enum AVPixelFormat[]) { ++ AV_PIX_FMT_DRM_PRIME, ++ AV_PIX_FMT_NONE ++ }, ++}; +diff --git a/libavutil/hwcontext_v4l2request.h b/libavutil/hwcontext_v4l2request.h +new file mode 100644 +index 0000000000..0fe42f97b4 +--- /dev/null ++++ b/libavutil/hwcontext_v4l2request.h +@@ -0,0 +1,41 @@ ++/* ++ * 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 AVUTIL_HWCONTEXT_V4L2REQUEST_H ++#define AVUTIL_HWCONTEXT_V4L2REQUEST_H ++ ++/** ++ * @file ++ * An API-specific header for AV_HWDEVICE_TYPE_V4L2REQUEST. ++ */ ++ ++/** ++ * V4L2 Request API device details. ++ * ++ * Allocated as AVHWDeviceContext.hwctx ++ */ ++typedef struct AVV4L2RequestDeviceContext { ++ /** ++ * File descriptor of media device. ++ * ++ * Defaults to -1 for auto-detect. ++ */ ++ int media_fd; ++} AVV4L2RequestDeviceContext; ++ ++#endif /* AVUTIL_HWCONTEXT_V4L2REQUEST_H */ + +From 8b12b1ca49f86dee00a68d819990a2d63150ac1a Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Tue, 6 Aug 2024 09:06:01 +0000 +Subject: [PATCH 02/11] avcodec: Add common V4L2 Request API code + +Add common helpers for supporting V4L2 Request API hwaccels. + +Basic flow for initialization follow the kernel Memory-to-memory +Stateless Video Decoder Interface > Initialization [1]. + +In init video devices is probed and when a capable device is found it is +initialized for decoding. Codec specific CONTROLs may be set to assist +kernel driver. A supported CAPTURE format is selected. A hw frame ctx is +created and CAPTURE buffers is allocated. OUTPUT buffers and request +objects for a circular queue is also allocated. + +In frame_params a buffer pool is created and configured to allocate +CAPTURE buffers. + +In flush all queued OUTPUT and CAPTURE buffers is dequeued. + +In uninit any pending request is flushed, also video and media device is +closed. The media device is not closed when ownership of the media_fd +has been transfered to the hwdevice. + +[1] https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/dev-stateless-decoder.html#initialization + +Co-developed-by: Jernej Skrabec +Signed-off-by: Jernej Skrabec +Co-developed-by: Alex Bee +Signed-off-by: Alex Bee +Signed-off-by: Jonas Karlman +--- + MAINTAINERS | 1 + + libavcodec/Makefile | 1 + + libavcodec/v4l2_request.c | 441 +++++++++++++++++++++++++++++ + libavcodec/v4l2_request.h | 84 ++++++ + libavcodec/v4l2_request_internal.h | 42 +++ + 5 files changed, 569 insertions(+) + create mode 100644 libavcodec/v4l2_request.c + create mode 100644 libavcodec/v4l2_request.h + create mode 100644 libavcodec/v4l2_request_internal.h + +diff --git a/MAINTAINERS b/MAINTAINERS +index 76651d5ff8..391acfbe16 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -278,6 +278,7 @@ Hardware acceleration: + d3d11va* Steve Lhomme + d3d12va_encode* Tong Wu + mediacodec* Matthieu Bouron, Aman Gupta, Zhao Zhili ++ v4l2_request* Jonas Karlman (CC jonas@kwiboo.se) + vaapi* Haihao Xiang + vaapi_encode* Mark Thompson, Haihao Xiang + vdpau* Philip Langdale, Carl Eugen Hoyos +diff --git a/libavcodec/Makefile b/libavcodec/Makefile +index a4fcce3b42..af60923827 100644 +--- a/libavcodec/Makefile ++++ b/libavcodec/Makefile +@@ -176,6 +176,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/v4l2_request.c b/libavcodec/v4l2_request.c +new file mode 100644 +index 0000000000..436c8de4a4 +--- /dev/null ++++ b/libavcodec/v4l2_request.c +@@ -0,0 +1,441 @@ ++/* ++ * 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 ++#include ++#include ++#include ++ ++#include "libavutil/hwcontext_v4l2request.h" ++#include "libavutil/mem.h" ++#include "decode.h" ++#include "v4l2_request_internal.h" ++ ++static const AVClass v4l2_request_context_class = { ++ .class_name = "V4L2RequestContext", ++ .item_name = av_default_item_name, ++ .version = LIBAVUTIL_VERSION_INT, ++}; ++ ++int ff_v4l2_request_query_control(AVCodecContext *avctx, ++ struct v4l2_query_ext_ctrl *control) ++{ ++ V4L2RequestContext *ctx = v4l2_request_context(avctx); ++ ++ if (ioctl(ctx->video_fd, VIDIOC_QUERY_EXT_CTRL, control) < 0) { ++ // Skip error logging when driver does not support control id (EINVAL) ++ if (errno != EINVAL) { ++ av_log(ctx, AV_LOG_ERROR, "Failed to query control %u: %s (%d)\n", ++ control->id, strerror(errno), errno); ++ } ++ return AVERROR(errno); ++ } ++ ++ return 0; ++} ++ ++int ff_v4l2_request_query_control_default_value(AVCodecContext *avctx, ++ uint32_t id) ++{ ++ struct v4l2_query_ext_ctrl control = { ++ .id = id, ++ }; ++ int ret; ++ ++ ret = ff_v4l2_request_query_control(avctx, &control); ++ if (ret < 0) ++ return ret; ++ ++ return control.default_value; ++} ++ ++int ff_v4l2_request_set_request_controls(V4L2RequestContext *ctx, int request_fd, ++ 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; ++ ++ if (ioctl(ctx->video_fd, VIDIOC_S_EXT_CTRLS, &controls) < 0) ++ return AVERROR(errno); ++ ++ return 0; ++} ++ ++int ff_v4l2_request_set_controls(AVCodecContext *avctx, ++ struct v4l2_ext_control *control, int count) ++{ ++ V4L2RequestContext *ctx = v4l2_request_context(avctx); ++ int ret; ++ ++ ret = ff_v4l2_request_set_request_controls(ctx, -1, control, count); ++ if (ret < 0) { ++ av_log(ctx, AV_LOG_ERROR, "Failed to set %d control(s): %s (%d)\n", ++ count, strerror(errno), errno); ++ } ++ ++ return ret; ++} ++ ++static int v4l2_request_buffer_alloc(V4L2RequestContext *ctx, ++ V4L2RequestBuffer *buf, ++ enum v4l2_buf_type type) ++{ ++ struct v4l2_plane planes[1] = {}; ++ struct v4l2_create_buffers buffers = { ++ .count = 1, ++ .memory = V4L2_MEMORY_MMAP, ++ .format.type = type, ++ }; ++ ++ // Get format details for the buffer to be created ++ if (ioctl(ctx->video_fd, VIDIOC_G_FMT, &buffers.format) < 0) { ++ av_log(ctx, AV_LOG_ERROR, "Failed to get format of type %d: %s (%d)\n", ++ type, strerror(errno), errno); ++ return AVERROR(errno); ++ } ++ ++ // Create the buffer ++ if (ioctl(ctx->video_fd, VIDIOC_CREATE_BUFS, &buffers) < 0) { ++ av_log(ctx, AV_LOG_ERROR, "Failed to create buffer of type %d: %s (%d)\n", ++ type, strerror(errno), errno); ++ return AVERROR(errno); ++ } ++ ++ 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; ++ ++ // Query more details of the created buffer ++ if (ioctl(ctx->video_fd, VIDIOC_QUERYBUF, &buf->buffer) < 0) { ++ av_log(ctx, AV_LOG_ERROR, "Failed to query buffer %d of type %d: %s (%d)\n", ++ buf->index, type, strerror(errno), errno); ++ return AVERROR(errno); ++ } ++ ++ // Output buffers is mapped and capture buffers is exported ++ if (V4L2_TYPE_IS_OUTPUT(type)) { ++ off_t offset = V4L2_TYPE_IS_MULTIPLANAR(type) ? ++ buf->buffer.m.planes[0].m.mem_offset : ++ buf->buffer.m.offset; ++ void *addr = mmap(NULL, buf->size, PROT_READ | PROT_WRITE, MAP_SHARED, ++ ctx->video_fd, offset); ++ if (addr == MAP_FAILED) { ++ av_log(ctx, AV_LOG_ERROR, "Failed to map output buffer %d: %s (%d)\n", ++ buf->index, strerror(errno), errno); ++ return AVERROR(errno); ++ } ++ ++ // Raw bitstream data is appended to output buffers ++ buf->addr = (uint8_t *)addr; ++ } else { ++ struct v4l2_exportbuffer exportbuffer = { ++ .type = type, ++ .index = buf->index, ++ .flags = O_RDONLY, ++ }; ++ ++ if (ioctl(ctx->video_fd, VIDIOC_EXPBUF, &exportbuffer) < 0) { ++ av_log(ctx, AV_LOG_ERROR, "Failed to export capture buffer %d: %s (%d)\n", ++ buf->index, strerror(errno), errno); ++ return AVERROR(errno); ++ } ++ ++ // Used in the AVDRMFrameDescriptor for decoded frames ++ buf->fd = exportbuffer.fd; ++ ++ /* ++ * Use buffer index as base for V4L2 frame reference. ++ * This works because a capture buffer is closely tied to a AVFrame ++ * and FFmpeg handle all frame reference tracking for us. ++ */ ++ buf->buffer.timestamp.tv_usec = buf->index + 1; ++ } ++ ++ return 0; ++} ++ ++static void v4l2_request_buffer_free(V4L2RequestBuffer *buf) ++{ ++ // Unmap output buffers ++ if (buf->addr) { ++ munmap(buf->addr, buf->size); ++ buf->addr = NULL; ++ } ++ ++ // Close exported capture buffers or requests for output buffers ++ if (buf->fd >= 0) { ++ close(buf->fd); ++ buf->fd = -1; ++ } ++} ++ ++static void v4l2_request_frame_free(void *opaque, uint8_t *data) ++{ ++ V4L2RequestFrameDescriptor *desc = (V4L2RequestFrameDescriptor *)data; ++ ++ v4l2_request_buffer_free(&desc->capture); ++ ++ av_free(data); ++} ++ ++static AVBufferRef *v4l2_request_frame_alloc(void *opaque, size_t size) ++{ ++ V4L2RequestContext *ctx = opaque; ++ V4L2RequestFrameDescriptor *desc; ++ AVBufferRef *ref; ++ uint8_t *data; ++ ++ data = av_mallocz(size); ++ if (!data) ++ return NULL; ++ ++ ref = av_buffer_create(data, size, v4l2_request_frame_free, ctx, 0); ++ if (!ref) { ++ av_free(data); ++ return NULL; ++ } ++ ++ desc = (V4L2RequestFrameDescriptor *)data; ++ desc->capture.fd = -1; ++ ++ // Create a V4L2 capture buffer for this AVFrame ++ if (v4l2_request_buffer_alloc(ctx, &desc->capture, ctx->format.type) < 0) { ++ av_buffer_unref(&ref); ++ return NULL; ++ } ++ ++ // TODO: Set AVDRMFrameDescriptor of this AVFrame ++ ++ return ref; ++} ++ ++static void v4l2_request_hwframe_ctx_free(AVHWFramesContext *hwfc) ++{ ++ av_buffer_pool_uninit(&hwfc->pool); ++} ++ ++int ff_v4l2_request_frame_params(AVCodecContext *avctx, ++ AVBufferRef *hw_frames_ctx) ++{ ++ V4L2RequestContext *ctx = v4l2_request_context(avctx); ++ AVHWFramesContext *hwfc = (AVHWFramesContext *)hw_frames_ctx->data; ++ ++ hwfc->format = AV_PIX_FMT_DRM_PRIME; ++ // TODO: Set sw_format based on capture buffer format ++ hwfc->sw_format = AV_PIX_FMT_NONE; ++ ++ 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(V4L2RequestFrameDescriptor), ctx, ++ v4l2_request_frame_alloc, NULL); ++ 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; ++ } ++ ++ return 0; ++} ++ ++int ff_v4l2_request_uninit(AVCodecContext *avctx) ++{ ++ V4L2RequestContext *ctx = v4l2_request_context(avctx); ++ ++ if (ctx->video_fd >= 0) { ++ // TODO: Flush and wait on all pending requests ++ ++ // Stop output queue ++ if (ioctl(ctx->video_fd, VIDIOC_STREAMOFF, &ctx->output_type) < 0) { ++ av_log(ctx, AV_LOG_WARNING, "Failed to stop output streaming: %s (%d)\n", ++ strerror(errno), errno); ++ } ++ ++ // Stop capture queue ++ if (ioctl(ctx->video_fd, VIDIOC_STREAMOFF, &ctx->format.type) < 0) { ++ av_log(ctx, AV_LOG_WARNING, "Failed to stop capture streaming: %s (%d)\n", ++ strerror(errno), errno); ++ } ++ ++ // Release output buffers ++ for (int i = 0; i < FF_ARRAY_ELEMS(ctx->output); i++) { ++ v4l2_request_buffer_free(&ctx->output[i]); ++ } ++ ++ // Close video device file descriptor ++ close(ctx->video_fd); ++ ctx->video_fd = -1; ++ } ++ ++ // Ownership of media device file descriptor may belong to hwdevice ++ if (ctx->device_ref) { ++ av_buffer_unref(&ctx->device_ref); ++ ctx->media_fd = -1; ++ } else if (ctx->media_fd >= 0) { ++ close(ctx->media_fd); ++ ctx->media_fd = -1; ++ } ++ ++ ff_mutex_destroy(&ctx->mutex); ++ ++ return 0; ++} ++ ++static int v4l2_request_init_context(AVCodecContext *avctx) ++{ ++ V4L2RequestContext *ctx = v4l2_request_context(avctx); ++ int ret; ++ ++ // Initialize context state ++ ff_mutex_init(&ctx->mutex, NULL); ++ for (int i = 0; i < FF_ARRAY_ELEMS(ctx->output); i++) { ++ ctx->output[i].index = i; ++ ctx->output[i].fd = -1; ++ } ++ atomic_init(&ctx->next_output, 0); ++ atomic_init(&ctx->queued_output, 0); ++ atomic_init(&ctx->queued_request, 0); ++ atomic_init(&ctx->queued_capture, 0); ++ ++ // Get format details for capture buffers ++ if (ioctl(ctx->video_fd, VIDIOC_G_FMT, &ctx->format) < 0) { ++ av_log(ctx, AV_LOG_ERROR, "Failed to get capture format: %s (%d)\n", ++ strerror(errno), errno); ++ ret = AVERROR(errno); ++ goto fail; ++ } ++ ++ // Create frame context and allocate initial capture buffers ++ ret = ff_decode_get_hw_frames_ctx(avctx, AV_HWDEVICE_TYPE_V4L2REQUEST); ++ if (ret < 0) ++ goto fail; ++ ++ // Allocate output buffers for circular queue ++ for (int i = 0; i < FF_ARRAY_ELEMS(ctx->output); i++) { ++ ret = v4l2_request_buffer_alloc(ctx, &ctx->output[i], ctx->output_type); ++ if (ret < 0) ++ goto fail; ++ } ++ ++ // Allocate requests for circular queue ++ for (int i = 0; i < FF_ARRAY_ELEMS(ctx->output); i++) { ++ if (ioctl(ctx->media_fd, MEDIA_IOC_REQUEST_ALLOC, &ctx->output[i].fd) < 0) { ++ av_log(ctx, AV_LOG_ERROR, "Failed to allocate request %d: %s (%d)\n", ++ i, strerror(errno), errno); ++ ret = AVERROR(errno); ++ goto fail; ++ } ++ } ++ ++ // Start output queue ++ if (ioctl(ctx->video_fd, VIDIOC_STREAMON, &ctx->output_type) < 0) { ++ av_log(ctx, AV_LOG_ERROR, "Failed to start output streaming: %s (%d)\n", ++ strerror(errno), errno); ++ ret = AVERROR(errno); ++ goto fail; ++ } ++ ++ // Start capture queue ++ if (ioctl(ctx->video_fd, VIDIOC_STREAMON, &ctx->format.type) < 0) { ++ av_log(ctx, AV_LOG_ERROR, "Failed to start capture streaming: %s (%d)\n", ++ strerror(errno), errno); ++ ret = AVERROR(errno); ++ goto fail; ++ } ++ ++ return 0; ++ ++fail: ++ ff_v4l2_request_uninit(avctx); ++ return ret; ++} ++ ++int ff_v4l2_request_init(AVCodecContext *avctx, ++ uint32_t pixelformat, uint32_t buffersize, ++ struct v4l2_ext_control *control, int count) ++{ ++ V4L2RequestContext *ctx = v4l2_request_context(avctx); ++ AVV4L2RequestDeviceContext *hwctx = NULL; ++ ++ // Set initial default values ++ ctx->av_class = &v4l2_request_context_class; ++ ctx->media_fd = -1; ++ ctx->video_fd = -1; ++ ++ // Try to use media device file descriptor opened and owned by hwdevice ++ if (avctx->hw_device_ctx) { ++ AVHWDeviceContext *device_ctx = (AVHWDeviceContext *)avctx->hw_device_ctx->data; ++ if (device_ctx->type == AV_HWDEVICE_TYPE_V4L2REQUEST && device_ctx->hwctx) { ++ hwctx = device_ctx->hwctx; ++ ctx->media_fd = hwctx->media_fd; ++ } ++ } ++ ++ // TODO: Probe for a capable media and video device ++ ++ // Transfer (or return) ownership of media device file descriptor to hwdevice ++ if (hwctx) { ++ hwctx->media_fd = ctx->media_fd; ++ ctx->device_ref = av_buffer_ref(avctx->hw_device_ctx); ++ } ++ ++ // Create buffers and finalize init ++ return v4l2_request_init_context(avctx); ++} +diff --git a/libavcodec/v4l2_request.h b/libavcodec/v4l2_request.h +new file mode 100644 +index 0000000000..621caaf28c +--- /dev/null ++++ b/libavcodec/v4l2_request.h +@@ -0,0 +1,84 @@ ++/* ++ * 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 ++ ++#include ++ ++#include "libavutil/hwcontext_drm.h" ++#include "libavutil/thread.h" ++ ++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 V4L2RequestContext { ++ const AVClass *av_class; ++ AVBufferRef *device_ref; ++ int media_fd; ++ int video_fd; ++ struct v4l2_format format; ++ enum v4l2_buf_type output_type; ++ AVMutex mutex; ++ V4L2RequestBuffer output[4]; ++ atomic_int_least8_t next_output; ++ atomic_uint_least32_t queued_output; ++ atomic_uint_least32_t queued_request; ++ atomic_uint_least64_t queued_capture; ++ int (*post_probe)(AVCodecContext *avctx); ++} V4L2RequestContext; ++ ++typedef struct V4L2RequestPictureContext { ++ V4L2RequestBuffer *output; ++ V4L2RequestBuffer *capture; ++} V4L2RequestPictureContext; ++ ++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_set_request_controls(V4L2RequestContext *ctx, int request_fd, ++ struct v4l2_ext_control *control, int count); ++ ++int ff_v4l2_request_set_controls(AVCodecContext *avctx, ++ struct v4l2_ext_control *control, int count); ++ ++int ff_v4l2_request_frame_params(AVCodecContext *avctx, ++ AVBufferRef *hw_frames_ctx); ++ ++int ff_v4l2_request_uninit(AVCodecContext *avctx); ++ ++int ff_v4l2_request_init(AVCodecContext *avctx, ++ uint32_t pixelformat, uint32_t buffersize, ++ struct v4l2_ext_control *control, int count); ++ ++#endif /* AVCODEC_V4L2_REQUEST_H */ +diff --git a/libavcodec/v4l2_request_internal.h b/libavcodec/v4l2_request_internal.h +new file mode 100644 +index 0000000000..554b663ab4 +--- /dev/null ++++ b/libavcodec/v4l2_request_internal.h +@@ -0,0 +1,42 @@ ++/* ++ * 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_INTERNAL_H ++#define AVCODEC_V4L2_REQUEST_INTERNAL_H ++ ++#include ++ ++#include "internal.h" ++#include "v4l2_request.h" ++ ++typedef struct V4L2RequestFrameDescriptor { ++ AVDRMFrameDescriptor base; ++ V4L2RequestBuffer capture; ++} V4L2RequestFrameDescriptor; ++ ++static inline V4L2RequestContext *v4l2_request_context(AVCodecContext *avctx) ++{ ++ return (V4L2RequestContext *)avctx->internal->hwaccel_priv_data; ++} ++ ++static inline V4L2RequestFrameDescriptor *v4l2_request_framedesc(AVFrame *frame) ++{ ++ return (V4L2RequestFrameDescriptor *)frame->data[0]; ++} ++ ++#endif /* AVCODEC_V4L2_REQUEST_INTERNAL_H */ + +From f2779c95d7416be33aa3b50f1c7f1f33f5b9aad5 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Tue, 6 Aug 2024 09:06:02 +0000 +Subject: [PATCH 03/11] avcodec/v4l2request: Probe for a capable media and + video device + +Probe all media devices and its linked video devices to locate a video +device that support stateless decoding of the specific codec using the +V4L2 Request API. + +When AVV4L2RequestDeviceContext.media_fd is a valid file descriptor only +video devices for the opened media device is probed. +E.g. using a -init_hw_device v4l2request:/dev/media1 parameter. + +A video device is deemed capable when all tests pass, e.g. kernel driver +support the codec, FFmpeg v4l2-request code know about the buffer format +and kernel driver report that the frame size is supported. + +A codec specific hook, post_probe, is supported to e.g. test for codec +specific limitations, PROFILE and LEVEL controls. + +Basic flow for initialization follow the kernel Memory-to-memory +Stateless Video Decoder Interface > Initialization [1]. + +[1] https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/dev-stateless-decoder.html#initialization + +Co-developed-by: Jernej Skrabec +Signed-off-by: Jernej Skrabec +Co-developed-by: Alex Bee +Signed-off-by: Alex Bee +Signed-off-by: Jonas Karlman +--- + configure | 4 +- + libavcodec/Makefile | 2 +- + libavcodec/v4l2_request.c | 18 +- + libavcodec/v4l2_request_internal.h | 9 + + libavcodec/v4l2_request_probe.c | 614 +++++++++++++++++++++++++++++ + 5 files changed, 641 insertions(+), 6 deletions(-) + create mode 100644 libavcodec/v4l2_request_probe.c + +diff --git a/configure b/configure +index b8f82f0fbf..98a342d109 100755 +--- a/configure ++++ b/configure +@@ -1966,6 +1966,7 @@ EXTERNAL_LIBRARY_LIST=" + libtorch + libtwolame + libuavs3d ++ libudev + libv4l2 + libvmaf + libvorbis +@@ -3148,7 +3149,7 @@ dxva2_deps="dxva2api_h DXVA2_ConfigPictureDecode ole32 user32" + ffnvcodec_deps_any="libdl LoadLibrary" + mediacodec_deps="android mediandk" + nvdec_deps="ffnvcodec" +-v4l2_request_deps="linux_media_h v4l2_timeval_to_ns" ++v4l2_request_deps="linux_media_h v4l2_timeval_to_ns libdrm libudev" + vaapi_x11_deps="xlib_x11" + videotoolbox_hwaccel_deps="videotoolbox pthreads" + videotoolbox_hwaccel_extralibs="-framework QuartzCore" +@@ -7202,6 +7203,7 @@ fi + + if enabled v4l2_request; then + check_func_headers "linux/media.h linux/videodev2.h" v4l2_timeval_to_ns ++ check_pkg_config libudev libudev libudev.h udev_new + fi + + check_headers sys/videoio.h +diff --git a/libavcodec/Makefile b/libavcodec/Makefile +index af60923827..ebd2dc54b9 100644 +--- a/libavcodec/Makefile ++++ b/libavcodec/Makefile +@@ -176,7 +176,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_V4L2_REQUEST) += v4l2_request.o v4l2_request_probe.o + OBJS-$(CONFIG_WMA_FREQS) += wma_freqs.o + OBJS-$(CONFIG_WMV2DSP) += wmv2dsp.o + +diff --git a/libavcodec/v4l2_request.c b/libavcodec/v4l2_request.c +index 436c8de4a4..6f44c5d826 100644 +--- a/libavcodec/v4l2_request.c ++++ b/libavcodec/v4l2_request.c +@@ -244,7 +244,11 @@ static AVBufferRef *v4l2_request_frame_alloc(void *opaque, size_t size) + return NULL; + } + +- // TODO: Set AVDRMFrameDescriptor of this AVFrame ++ // Set AVDRMFrameDescriptor of this AVFrame ++ if (ff_v4l2_request_set_drm_descriptor(desc, &ctx->format) < 0) { ++ av_buffer_unref(&ref); ++ return NULL; ++ } + + return ref; + } +@@ -261,8 +265,7 @@ int ff_v4l2_request_frame_params(AVCodecContext *avctx, + AVHWFramesContext *hwfc = (AVHWFramesContext *)hw_frames_ctx->data; + + hwfc->format = AV_PIX_FMT_DRM_PRIME; +- // TODO: Set sw_format based on capture buffer format +- hwfc->sw_format = AV_PIX_FMT_NONE; ++ hwfc->sw_format = ff_v4l2_request_get_sw_format(&ctx->format); + + if (V4L2_TYPE_IS_MULTIPLANAR(ctx->format.type)) { + hwfc->width = ctx->format.fmt.pix_mp.width; +@@ -413,6 +416,7 @@ int ff_v4l2_request_init(AVCodecContext *avctx, + { + V4L2RequestContext *ctx = v4l2_request_context(avctx); + AVV4L2RequestDeviceContext *hwctx = NULL; ++ int ret; + + // Set initial default values + ctx->av_class = &v4l2_request_context_class; +@@ -428,7 +432,13 @@ int ff_v4l2_request_init(AVCodecContext *avctx, + } + } + +- // TODO: Probe for a capable media and video device ++ // Probe for a capable media and video device for the V4L2 codec pixelformat ++ ret = ff_v4l2_request_probe(avctx, pixelformat, buffersize, control, count); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_INFO, "No V4L2 video device found for %s\n", ++ av_fourcc2str(pixelformat)); ++ return ret; ++ } + + // Transfer (or return) ownership of media device file descriptor to hwdevice + if (hwctx) { +diff --git a/libavcodec/v4l2_request_internal.h b/libavcodec/v4l2_request_internal.h +index 554b663ab4..a5c3de22ef 100644 +--- a/libavcodec/v4l2_request_internal.h ++++ b/libavcodec/v4l2_request_internal.h +@@ -39,4 +39,13 @@ static inline V4L2RequestFrameDescriptor *v4l2_request_framedesc(AVFrame *frame) + return (V4L2RequestFrameDescriptor *)frame->data[0]; + } + ++enum AVPixelFormat ff_v4l2_request_get_sw_format(struct v4l2_format *format); ++ ++int ff_v4l2_request_set_drm_descriptor(V4L2RequestFrameDescriptor *framedesc, ++ struct v4l2_format *format); ++ ++int ff_v4l2_request_probe(AVCodecContext *avctx, uint32_t pixelformat, ++ uint32_t buffersize, struct v4l2_ext_control *control, ++ int count); ++ + #endif /* AVCODEC_V4L2_REQUEST_INTERNAL_H */ +diff --git a/libavcodec/v4l2_request_probe.c b/libavcodec/v4l2_request_probe.c +new file mode 100644 +index 0000000000..941042ec04 +--- /dev/null ++++ b/libavcodec/v4l2_request_probe.c +@@ -0,0 +1,614 @@ ++/* ++ * 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 ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "libavutil/hwcontext_v4l2request.h" ++#include "libavutil/mem.h" ++#include "v4l2_request_internal.h" ++ ++static const struct { ++ uint32_t pixelformat; ++ enum AVPixelFormat sw_format; ++ uint32_t drm_format; ++ uint64_t format_modifier; ++} v4l2_request_capture_pixelformats[] = { ++ { V4L2_PIX_FMT_NV12, AV_PIX_FMT_NV12, DRM_FORMAT_NV12, DRM_FORMAT_MOD_LINEAR }, ++#if defined(V4L2_PIX_FMT_NV12_32L32) ++ { V4L2_PIX_FMT_NV12_32L32, AV_PIX_FMT_NONE, DRM_FORMAT_NV12, DRM_FORMAT_MOD_ALLWINNER_TILED }, ++#endif ++#if defined(V4L2_PIX_FMT_NV15) && defined(DRM_FORMAT_NV15) ++ { V4L2_PIX_FMT_NV15, AV_PIX_FMT_NONE, DRM_FORMAT_NV15, DRM_FORMAT_MOD_LINEAR }, ++#endif ++ { V4L2_PIX_FMT_NV16, AV_PIX_FMT_NV16, DRM_FORMAT_NV16, DRM_FORMAT_MOD_LINEAR }, ++#if defined(V4L2_PIX_FMT_NV20) && defined(DRM_FORMAT_NV20) ++ { V4L2_PIX_FMT_NV20, AV_PIX_FMT_NONE, DRM_FORMAT_NV20, DRM_FORMAT_MOD_LINEAR }, ++#endif ++#if defined(V4L2_PIX_FMT_P010) && defined(DRM_FORMAT_P010) ++ { V4L2_PIX_FMT_P010, AV_PIX_FMT_P010, DRM_FORMAT_P010, DRM_FORMAT_MOD_LINEAR }, ++#endif ++#if defined(V4L2_PIX_FMT_NV12_COL128) && defined(V4L2_PIX_FMT_NV12_10_COL128) ++ { ++ .pixelformat = V4L2_PIX_FMT_NV12_COL128, ++ .sw_format = AV_PIX_FMT_NONE, ++ .drm_format = DRM_FORMAT_NV12, ++ .format_modifier = DRM_FORMAT_MOD_BROADCOM_SAND128, ++ }, ++#if defined(DRM_FORMAT_P030) ++ { ++ .pixelformat = V4L2_PIX_FMT_NV12_10_COL128, ++ .sw_format = AV_PIX_FMT_NONE, ++ .drm_format = DRM_FORMAT_P030, ++ .format_modifier = DRM_FORMAT_MOD_BROADCOM_SAND128, ++ }, ++#endif ++#endif ++#if defined(V4L2_PIX_FMT_YUV420_10_AFBC_16X16_SPLIT) ++ { ++ .pixelformat = V4L2_PIX_FMT_YUV420_10_AFBC_16X16_SPLIT, ++ .sw_format = AV_PIX_FMT_NONE, ++ .drm_format = DRM_FORMAT_YUV420_10BIT, ++ .format_modifier = DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | ++ AFBC_FORMAT_MOD_SPARSE | ++ AFBC_FORMAT_MOD_SPLIT), ++ }, ++#endif ++#if defined(V4L2_PIX_FMT_YUV420_8_AFBC_16X16_SPLIT) ++ { ++ .pixelformat = V4L2_PIX_FMT_YUV420_8_AFBC_16X16_SPLIT, ++ .sw_format = AV_PIX_FMT_NONE, ++ .drm_format = DRM_FORMAT_YUV420_8BIT, ++ .format_modifier = DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | ++ AFBC_FORMAT_MOD_SPARSE | ++ AFBC_FORMAT_MOD_SPLIT), ++ }, ++#endif ++}; ++ ++enum AVPixelFormat ff_v4l2_request_get_sw_format(struct v4l2_format *format) ++{ ++ uint32_t pixelformat = V4L2_TYPE_IS_MULTIPLANAR(format->type) ? ++ format->fmt.pix_mp.pixelformat : ++ format->fmt.pix.pixelformat; ++ ++ for (int i = 0; i < FF_ARRAY_ELEMS(v4l2_request_capture_pixelformats); i++) { ++ if (pixelformat == v4l2_request_capture_pixelformats[i].pixelformat) ++ return v4l2_request_capture_pixelformats[i].sw_format; ++ } ++ ++ return AV_PIX_FMT_NONE; ++} ++ ++int ff_v4l2_request_set_drm_descriptor(V4L2RequestFrameDescriptor *framedesc, ++ struct v4l2_format *format) ++{ ++ AVDRMFrameDescriptor *desc = &framedesc->base; ++ AVDRMLayerDescriptor *layer = &desc->layers[0]; ++ uint32_t pixelformat = V4L2_TYPE_IS_MULTIPLANAR(format->type) ? ++ format->fmt.pix_mp.pixelformat : ++ format->fmt.pix.pixelformat; ++ ++ // Set drm format and format modifier ++ layer->format = 0; ++ for (int i = 0; i < FF_ARRAY_ELEMS(v4l2_request_capture_pixelformats); i++) { ++ if (pixelformat == v4l2_request_capture_pixelformats[i].pixelformat) { ++ layer->format = v4l2_request_capture_pixelformats[i].drm_format; ++ desc->objects[0].format_modifier = ++ v4l2_request_capture_pixelformats[i].format_modifier; ++ break; ++ } ++ } ++ ++ if (!layer->format) ++ return AVERROR(ENOENT); ++ ++ desc->nb_objects = 1; ++ desc->objects[0].fd = framedesc->capture.fd; ++ desc->objects[0].size = framedesc->capture.size; ++ ++ desc->nb_layers = 1; ++ layer->nb_planes = 1; ++ ++ 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; ++ ++ // AFBC formats only use 1 plane, remaining use 2 planes ++ if ((desc->objects[0].format_modifier >> 56) != DRM_FORMAT_MOD_VENDOR_ARM) { ++ layer->nb_planes = 2; ++ 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; ++ } ++ ++#if defined(V4L2_PIX_FMT_NV12_COL128) && defined(V4L2_PIX_FMT_NV12_10_COL128) ++ // Raspberry Pi formats need special handling ++ if (pixelformat == V4L2_PIX_FMT_NV12_COL128 || ++ pixelformat == V4L2_PIX_FMT_NV12_10_COL128) { ++ desc->objects[0].format_modifier = ++ DRM_FORMAT_MOD_BROADCOM_SAND128_COL_HEIGHT(layer->planes[0].pitch); ++ layer->planes[1].offset = 128 * ++ (V4L2_TYPE_IS_MULTIPLANAR(format->type) ? ++ format->fmt.pix_mp.height : ++ format->fmt.pix.height); ++ layer->planes[0].pitch = (V4L2_TYPE_IS_MULTIPLANAR(format->type) ? ++ format->fmt.pix_mp.width : ++ format->fmt.pix.width); ++ if (pixelformat == V4L2_PIX_FMT_NV12_10_COL128) ++ layer->planes[0].pitch *= 2; ++ layer->planes[1].pitch = layer->planes[0].pitch; ++ } ++#endif ++ ++ return 0; ++} ++ ++static int v4l2_request_set_format(AVCodecContext *avctx, ++ enum v4l2_buf_type type, ++ uint32_t pixelformat, ++ uint32_t buffersize) ++{ ++ V4L2RequestContext *ctx = v4l2_request_context(avctx); ++ 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; ++ } ++ ++ if (ioctl(ctx->video_fd, VIDIOC_S_FMT, &format) < 0) ++ return AVERROR(errno); ++ ++ return 0; ++} ++ ++static int v4l2_request_select_capture_format(AVCodecContext *avctx) ++{ ++ V4L2RequestContext *ctx = v4l2_request_context(avctx); ++ enum v4l2_buf_type type = ctx->format.type; ++ struct v4l2_format format = { ++ .type = type, ++ }; ++ struct v4l2_fmtdesc fmtdesc = { ++ .index = 0, ++ .type = type, ++ }; ++ uint32_t pixelformat; ++ ++ // Get the driver preferred (or default) format ++ if (ioctl(ctx->video_fd, VIDIOC_G_FMT, &format) < 0) ++ return AVERROR(errno); ++ ++ pixelformat = V4L2_TYPE_IS_MULTIPLANAR(type) ? ++ format.fmt.pix_mp.pixelformat : ++ format.fmt.pix.pixelformat; ++ ++ // Use the driver preferred format when it is supported ++ for (int i = 0; i < FF_ARRAY_ELEMS(v4l2_request_capture_pixelformats); i++) { ++ if (pixelformat == v4l2_request_capture_pixelformats[i].pixelformat) ++ return v4l2_request_set_format(avctx, type, pixelformat, 0); ++ } ++ ++ // Otherwise, use first format that is supported ++ while (ioctl(ctx->video_fd, VIDIOC_ENUM_FMT, &fmtdesc) >= 0) { ++ for (int i = 0; i < FF_ARRAY_ELEMS(v4l2_request_capture_pixelformats); i++) { ++ if (fmtdesc.pixelformat == v4l2_request_capture_pixelformats[i].pixelformat) ++ return v4l2_request_set_format(avctx, type, fmtdesc.pixelformat, 0); ++ } ++ ++ fmtdesc.index++; ++ } ++ ++ return AVERROR(errno); ++} ++ ++static int v4l2_request_try_framesize(AVCodecContext *avctx, ++ uint32_t pixelformat) ++{ ++ V4L2RequestContext *ctx = v4l2_request_context(avctx); ++ struct v4l2_frmsizeenum frmsize = { ++ .index = 0, ++ .pixel_format = pixelformat, ++ }; ++ ++ // Enumerate and check if frame size is supported ++ while (ioctl(ctx->video_fd, VIDIOC_ENUM_FRAMESIZES, &frmsize) >= 0) { ++ if (frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE && ++ frmsize.discrete.width == avctx->coded_width && ++ frmsize.discrete.height == avctx->coded_height) { ++ return 0; ++ } else if ((frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE || ++ frmsize.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) && ++ avctx->coded_width <= frmsize.stepwise.max_width && ++ avctx->coded_height <= frmsize.stepwise.max_height && ++ avctx->coded_width % frmsize.stepwise.step_width == 0 && ++ avctx->coded_height % frmsize.stepwise.step_height == 0) { ++ return 0; ++ } ++ ++ frmsize.index++; ++ } ++ ++ return AVERROR(errno); ++} ++ ++static int v4l2_request_try_format(AVCodecContext *avctx, ++ enum v4l2_buf_type type, ++ uint32_t pixelformat) ++{ ++ V4L2RequestContext *ctx = v4l2_request_context(avctx); ++ struct v4l2_fmtdesc fmtdesc = { ++ .index = 0, ++ .type = type, ++ }; ++ ++ // Enumerate and check if format is supported ++ while (ioctl(ctx->video_fd, VIDIOC_ENUM_FMT, &fmtdesc) >= 0) { ++ if (fmtdesc.pixelformat == pixelformat) ++ return 0; ++ ++ fmtdesc.index++; ++ } ++ ++ return AVERROR(errno); ++} ++ ++static int v4l2_request_probe_video_device(const char *path, ++ AVCodecContext *avctx, ++ uint32_t pixelformat, ++ uint32_t buffersize, ++ struct v4l2_ext_control *control, ++ int count) ++{ ++ V4L2RequestContext *ctx = v4l2_request_context(avctx); ++ struct v4l2_capability capability; ++ struct v4l2_create_buffers buffers = { ++ .count = 0, ++ .memory = V4L2_MEMORY_MMAP, ++ }; ++ unsigned int capabilities; ++ int ret; ++ ++ /* ++ * Open video device in non-blocking mode to support decoding using ++ * multiple queued requests, required for e.g. multi stage decoding. ++ */ ++ ctx->video_fd = open(path, O_RDWR | O_NONBLOCK); ++ if (ctx->video_fd < 0) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to open video device %s: %s (%d)\n", ++ path, strerror(errno), errno); ++ return AVERROR(errno); ++ } ++ ++ // Query capabilities of the video device ++ if (ioctl(ctx->video_fd, VIDIOC_QUERYCAP, &capability) < 0) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to query capabilities of %s: %s (%d)\n", ++ path, strerror(errno), errno); ++ ret = AVERROR(errno); ++ goto fail; ++ } ++ ++ // Use device capabilities when needed ++ if (capability.capabilities & V4L2_CAP_DEVICE_CAPS) ++ capabilities = capability.device_caps; ++ else ++ capabilities = capability.capabilities; ++ ++ // Ensure streaming is supported on the video device ++ if ((capabilities & V4L2_CAP_STREAMING) != V4L2_CAP_STREAMING) { ++ av_log(ctx, AV_LOG_VERBOSE, "Device %s is missing streaming capability\n", path); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ // Ensure multi- or single-planar API can be used ++ 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(ctx, AV_LOG_VERBOSE, "Device %s is missing mem2mem capability\n", path); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ // Query output buffer capabilities ++ buffers.format.type = ctx->output_type; ++ if (ioctl(ctx->video_fd, VIDIOC_CREATE_BUFS, &buffers) < 0) { ++ av_log(avctx, AV_LOG_ERROR, ++ "Failed to query output buffer capabilities of %s: %s (%d)\n", ++ path, strerror(errno), errno); ++ ret = AVERROR(errno); ++ goto fail; ++ } ++ ++ // Ensure requests can be used ++ if ((buffers.capabilities & V4L2_BUF_CAP_SUPPORTS_REQUESTS) != ++ V4L2_BUF_CAP_SUPPORTS_REQUESTS) { ++ av_log(ctx, AV_LOG_VERBOSE, "Device %s is missing support for requests\n", path); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ // Ensure the codec pixelformat can be used ++ ret = v4l2_request_try_format(avctx, ctx->output_type, pixelformat); ++ if (ret < 0) { ++ av_log(ctx, AV_LOG_VERBOSE, "Device %s is missing support for pixelformat %s\n", ++ path, av_fourcc2str(pixelformat)); ++ goto fail; ++ } ++ ++ // Ensure frame size is supported, when driver support ENUM_FRAMESIZES ++ ret = v4l2_request_try_framesize(avctx, pixelformat); ++ if (ret < 0 && ret != AVERROR(ENOTTY)) { ++ av_log(ctx, AV_LOG_VERBOSE, ++ "Device %s is missing support for frame size %dx%d of pixelformat %s\n", ++ path, avctx->coded_width, avctx->coded_height, av_fourcc2str(pixelformat)); ++ goto fail; ++ } ++ ++ // Set the codec pixelformat and output buffersize to be used ++ ret = v4l2_request_set_format(avctx, ctx->output_type, pixelformat, buffersize); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, ++ "Failed to set output pixelformat %s of %s: %s (%d)\n", ++ av_fourcc2str(pixelformat), path, strerror(errno), errno); ++ goto fail; ++ } ++ ++ /* ++ * Set any codec specific controls that can help assist the driver ++ * make a decision on what capture buffer format can be used. ++ */ ++ ret = ff_v4l2_request_set_controls(avctx, control, count); ++ if (ret < 0) ++ goto fail; ++ ++ // Select a capture buffer format known to the hwaccel ++ ret = v4l2_request_select_capture_format(avctx); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_VERBOSE, ++ "Failed to select a capture format for %s of %s: %s (%d)\n", ++ av_fourcc2str(pixelformat), path, strerror(errno), errno); ++ goto fail; ++ } ++ ++ // Check codec specific controls, e.g. profile and level ++ if (ctx->post_probe) { ++ ret = ctx->post_probe(avctx); ++ if (ret < 0) ++ goto fail; ++ } ++ ++ // All tests passed, video device should be capable ++ return 0; ++ ++fail: ++ if (ctx->video_fd >= 0) { ++ close(ctx->video_fd); ++ ctx->video_fd = -1; ++ } ++ return ret; ++} ++ ++static int v4l2_request_probe_video_devices(struct udev *udev, ++ AVCodecContext *avctx, ++ uint32_t pixelformat, ++ uint32_t buffersize, ++ struct v4l2_ext_control *control, ++ int count) ++{ ++ V4L2RequestContext *ctx = v4l2_request_context(avctx); ++ struct media_device_info device_info; ++ struct media_v2_topology topology = {0}; ++ struct media_v2_interface *interfaces; ++ struct udev_device *device; ++ const char *path; ++ dev_t devnum; ++ int ret; ++ ++ if (ioctl(ctx->media_fd, MEDIA_IOC_DEVICE_INFO, &device_info) < 0) ++ return AVERROR(errno); ++ ++ if (ioctl(ctx->media_fd, MEDIA_IOC_G_TOPOLOGY, &topology) < 0) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to get media topology: %s (%d)\n", ++ strerror(errno), errno); ++ return AVERROR(errno); ++ } ++ ++ if (!topology.num_interfaces) ++ return AVERROR(ENOENT); ++ ++ interfaces = av_calloc(topology.num_interfaces, sizeof(struct media_v2_interface)); ++ if (!interfaces) ++ return AVERROR(ENOMEM); ++ ++ topology.ptr_interfaces = (__u64)(uintptr_t)interfaces; ++ if (ioctl(ctx->media_fd, MEDIA_IOC_G_TOPOLOGY, &topology) < 0) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to get media topology: %s (%d)\n", ++ strerror(errno), errno); ++ ret = AVERROR(errno); ++ goto fail; ++ } ++ ++ ret = AVERROR(ENOENT); ++ 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); ++ device = udev_device_new_from_devnum(udev, 'c', devnum); ++ if (!device) ++ continue; ++ ++ path = udev_device_get_devnode(device); ++ if (path) ++ ret = v4l2_request_probe_video_device(path, avctx, pixelformat, ++ buffersize, control, count); ++ udev_device_unref(device); ++ ++ // Stop when we have found a capable video device ++ if (!ret) { ++ av_log(avctx, AV_LOG_INFO, ++ "Using V4L2 media driver %s (%u.%u.%u) for %s\n", ++ device_info.driver, ++ device_info.driver_version >> 16, ++ (device_info.driver_version >> 8) & 0xff, ++ device_info.driver_version & 0xff, ++ av_fourcc2str(pixelformat)); ++ break; ++ } ++ } ++ ++fail: ++ av_free(interfaces); ++ 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 = v4l2_request_context(avctx); ++ const char *path; ++ int ret; ++ ++ path = udev_device_get_devnode(device); ++ if (!path) ++ return AVERROR(ENODEV); ++ ++ // Open enumerated media device ++ ctx->media_fd = open(path, O_RDWR); ++ if (ctx->media_fd < 0) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to open media device %s: %s (%d)\n", ++ path, strerror(errno), errno); ++ return AVERROR(errno); ++ } ++ ++ // Probe video devices of current media device ++ ret = v4l2_request_probe_video_devices(udev_device_get_udev(device), ++ avctx, pixelformat, ++ buffersize, control, count); ++ ++ // Cleanup when no capable video device was found ++ if (ret < 0) { ++ close(ctx->media_fd); ++ ctx->media_fd = -1; ++ } ++ ++ return ret; ++} ++ ++static int v4l2_request_probe_media_devices(struct udev *udev, ++ AVCodecContext *avctx, ++ uint32_t pixelformat, ++ uint32_t buffersize, ++ struct v4l2_ext_control *control, ++ int count) ++{ ++ struct udev_enumerate *enumerate; ++ struct udev_list_entry *devices; ++ struct udev_list_entry *entry; ++ struct udev_device *device; ++ int ret; ++ ++ enumerate = udev_enumerate_new(udev); ++ if (!enumerate) ++ return AVERROR(ENOMEM); ++ ++ udev_enumerate_add_match_subsystem(enumerate, "media"); ++ udev_enumerate_scan_devices(enumerate); ++ devices = udev_enumerate_get_list_entry(enumerate); ++ ++ ret = AVERROR(ENOENT); ++ 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; ++ ++ // Probe media device for a capable video device ++ ret = v4l2_request_probe_media_device(device, avctx, pixelformat, ++ buffersize, control, count); ++ udev_device_unref(device); ++ ++ // Stop when we have found a capable media and video device ++ if (!ret) ++ break; ++ } ++ ++ udev_enumerate_unref(enumerate); ++ return ret; ++} ++ ++int ff_v4l2_request_probe(AVCodecContext *avctx, ++ uint32_t pixelformat, uint32_t buffersize, ++ struct v4l2_ext_control *control, int count) ++{ ++ V4L2RequestContext *ctx = v4l2_request_context(avctx); ++ struct udev *udev; ++ int ret; ++ ++ udev = udev_new(); ++ if (!udev) ++ return AVERROR(ENOMEM); ++ ++ if (ctx->media_fd >= 0) { ++ // Probe video devices of current media device ++ ret = v4l2_request_probe_video_devices(udev, avctx, pixelformat, ++ buffersize, control, count); ++ } else { ++ // Probe all media devices (auto-detect) ++ ret = v4l2_request_probe_media_devices(udev, avctx, pixelformat, ++ buffersize, control, count); ++ } ++ ++ udev_unref(udev); ++ return ret; ++} + +From 917168b391fa76cff0b7b74050bd90fa60e07b8c Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Tue, 6 Aug 2024 09:06:03 +0000 +Subject: [PATCH 04/11] avcodec/v4l2request: Add common decode support for + hwaccels + +Add common support for decoding using the V4L2 Request API. + +Basic flow for decoding follow the kernel Memory-to-memory Stateless +Video Decoder Interface > Decoding [1]. + +A codec hwaccel typically handle decoding as follow: + +In start_frame next OUTPUT buffer and its related request object is +picked from a circular queue and any codec specific CONTROLs is prepared. + +In decode_slice the slice bitstream data is appended to the OUTPUT +buffer. + +In end_frame a CAPTURE buffer tied to the AVFrame is queued, it will be +used as the decoding target by the driver / hw decoder. The prepared +codec specific CONTROLs get queued as part of the request object. +Finally the request object is submitted for decoding. + +For slice based hw decoders only the request for the final slice of the +frame is submitted in end_frame, remaining is submitted in decode_slice. + +[1] https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/dev-stateless-decoder.html#decoding + +Co-developed-by: Jernej Skrabec +Signed-off-by: Jernej Skrabec +Co-developed-by: Alex Bee +Signed-off-by: Alex Bee +Signed-off-by: Jonas Karlman +--- + configure | 3 +- + libavcodec/Makefile | 2 +- + libavcodec/hwconfig.h | 2 + + libavcodec/v4l2_request.c | 3 +- + libavcodec/v4l2_request.h | 23 ++ + libavcodec/v4l2_request_decode.c | 459 +++++++++++++++++++++++++++++++ + 6 files changed, 489 insertions(+), 3 deletions(-) + create mode 100644 libavcodec/v4l2_request_decode.c + +diff --git a/configure b/configure +index 98a342d109..b74da32e8b 100755 +--- a/configure ++++ b/configure +@@ -3149,7 +3149,7 @@ dxva2_deps="dxva2api_h DXVA2_ConfigPictureDecode ole32 user32" + ffnvcodec_deps_any="libdl LoadLibrary" + mediacodec_deps="android mediandk" + nvdec_deps="ffnvcodec" +-v4l2_request_deps="linux_media_h v4l2_timeval_to_ns libdrm libudev" ++v4l2_request_deps="linux_media_h v4l2_timeval_to_ns v4l2_m2m_hold_capture_buf libdrm libudev" + vaapi_x11_deps="xlib_x11" + videotoolbox_hwaccel_deps="videotoolbox pthreads" + videotoolbox_hwaccel_extralibs="-framework QuartzCore" +@@ -7202,6 +7202,7 @@ if enabled v4l2_m2m; then + fi + + if enabled v4l2_request; then ++ check_cc v4l2_m2m_hold_capture_buf linux/videodev2.h "int i = V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF" + check_func_headers "linux/media.h linux/videodev2.h" v4l2_timeval_to_ns + check_pkg_config libudev libudev libudev.h udev_new + fi +diff --git a/libavcodec/Makefile b/libavcodec/Makefile +index ebd2dc54b9..6f2229b1b6 100644 +--- a/libavcodec/Makefile ++++ b/libavcodec/Makefile +@@ -176,7 +176,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_request_probe.o ++OBJS-$(CONFIG_V4L2_REQUEST) += v4l2_request.o v4l2_request_probe.o v4l2_request_decode.o + OBJS-$(CONFIG_WMA_FREQS) += wma_freqs.o + OBJS-$(CONFIG_WMV2DSP) += wmv2dsp.o + +diff --git a/libavcodec/hwconfig.h b/libavcodec/hwconfig.h +index ee29ca631d..159064a1f1 100644 +--- a/libavcodec/hwconfig.h ++++ b/libavcodec/hwconfig.h +@@ -79,6 +79,8 @@ void ff_hwaccel_uninit(AVCodecContext *avctx); + HW_CONFIG_HWACCEL(0, 0, 1, D3D11VA_VLD, NONE, ff_ ## codec ## _d3d11va_hwaccel) + #define HWACCEL_D3D12VA(codec) \ + HW_CONFIG_HWACCEL(1, 1, 0, D3D12, D3D12VA, ff_ ## codec ## _d3d12va_hwaccel) ++#define HWACCEL_V4L2REQUEST(codec) \ ++ HW_CONFIG_HWACCEL(1, 0, 0, DRM_PRIME, V4L2REQUEST, 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 +index 6f44c5d826..aae719ead6 100644 +--- a/libavcodec/v4l2_request.c ++++ b/libavcodec/v4l2_request.c +@@ -303,7 +303,8 @@ int ff_v4l2_request_uninit(AVCodecContext *avctx) + V4L2RequestContext *ctx = v4l2_request_context(avctx); + + if (ctx->video_fd >= 0) { +- // TODO: Flush and wait on all pending requests ++ // Flush and wait on all pending requests ++ ff_v4l2_request_flush(avctx); + + // Stop output queue + if (ioctl(ctx->video_fd, VIDIOC_STREAMOFF, &ctx->output_type) < 0) { +diff --git a/libavcodec/v4l2_request.h b/libavcodec/v4l2_request.h +index 621caaf28c..62248feb48 100644 +--- a/libavcodec/v4l2_request.h ++++ b/libavcodec/v4l2_request.h +@@ -81,4 +81,27 @@ int ff_v4l2_request_init(AVCodecContext *avctx, + uint32_t pixelformat, uint32_t buffersize, + struct v4l2_ext_control *control, int count); + ++uint64_t ff_v4l2_request_get_capture_timestamp(AVFrame *frame); ++ ++int ff_v4l2_request_append_output(AVCodecContext *avctx, ++ V4L2RequestPictureContext *pic, ++ const uint8_t *data, uint32_t size); ++ ++int ff_v4l2_request_decode_slice(AVCodecContext *avctx, ++ V4L2RequestPictureContext *pic, ++ struct v4l2_ext_control *control, int count, ++ bool first_slice, bool last_slice); ++ ++int ff_v4l2_request_decode_frame(AVCodecContext *avctx, ++ V4L2RequestPictureContext *pic, ++ struct v4l2_ext_control *control, int count); ++ ++int ff_v4l2_request_reset_picture(AVCodecContext *avctx, ++ V4L2RequestPictureContext *pic); ++ ++int ff_v4l2_request_start_frame(AVCodecContext *avctx, ++ V4L2RequestPictureContext *pic, AVFrame *frame); ++ ++void ff_v4l2_request_flush(AVCodecContext *avctx); ++ + #endif /* AVCODEC_V4L2_REQUEST_H */ +diff --git a/libavcodec/v4l2_request_decode.c b/libavcodec/v4l2_request_decode.c +new file mode 100644 +index 0000000000..8e7e241e36 +--- /dev/null ++++ b/libavcodec/v4l2_request_decode.c +@@ -0,0 +1,459 @@ ++/* ++ * 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 ++#include ++ ++#include "decode.h" ++#include "v4l2_request_internal.h" ++ ++#define INPUT_BUFFER_PADDING_SIZE (AV_INPUT_BUFFER_PADDING_SIZE * 4) ++ ++uint64_t ff_v4l2_request_get_capture_timestamp(AVFrame *frame) ++{ ++ V4L2RequestFrameDescriptor *desc = v4l2_request_framedesc(frame); ++ ++ /* ++ * The capture buffer index is used as a base for V4L2 frame reference. ++ * This works because frames are decoded into a capture buffer that is ++ * closely tied to an AVFrame. ++ */ ++ return desc ? v4l2_timeval_to_ns(&desc->capture.buffer.timestamp) : 0; ++} ++ ++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 = { ++ .index = buf->index, ++ .type = buf->buffer.type, ++ .memory = buf->buffer.memory, ++ .timestamp = buf->buffer.timestamp, ++ .bytesused = buf->used, ++ .request_fd = request_fd, ++ .flags = ((request_fd >= 0) ? V4L2_BUF_FLAG_REQUEST_FD : 0) | flags, ++ }; ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(buffer.type)) { ++ planes[0].bytesused = buf->used; ++ buffer.bytesused = 0; ++ buffer.length = 1; ++ buffer.m.planes = planes; ++ } ++ ++ // Queue the buffer ++ if (ioctl(ctx->video_fd, VIDIOC_QBUF, &buffer) < 0) ++ return AVERROR(errno); ++ ++ // Mark the buffer as queued ++ if (V4L2_TYPE_IS_OUTPUT(buffer.type)) ++ atomic_fetch_or(&ctx->queued_output, 1 << buffer.index); ++ else ++ atomic_fetch_or(&ctx->queued_capture, 1 << buffer.index); ++ ++ return 0; ++} ++ ++static int v4l2_request_dequeue_buffer(V4L2RequestContext *ctx, ++ enum v4l2_buf_type type) ++{ ++ struct v4l2_plane planes[1] = {}; ++ struct v4l2_buffer buffer = { ++ .type = type, ++ .memory = V4L2_MEMORY_MMAP, ++ }; ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(buffer.type)) { ++ buffer.length = 1; ++ buffer.m.planes = planes; ++ } ++ ++ // Dequeue next completed buffer ++ if (ioctl(ctx->video_fd, VIDIOC_DQBUF, &buffer) < 0) ++ return AVERROR(errno); ++ ++ // Mark the buffer as dequeued ++ if (V4L2_TYPE_IS_OUTPUT(buffer.type)) ++ atomic_fetch_and(&ctx->queued_output, ~(1 << buffer.index)); ++ else ++ atomic_fetch_and(&ctx->queued_capture, ~(1 << buffer.index)); ++ ++ return 0; ++} ++ ++static inline int v4l2_request_dequeue_completed_buffers(V4L2RequestContext *ctx, ++ enum v4l2_buf_type type) ++{ ++ int ret; ++ ++ do { ++ ret = v4l2_request_dequeue_buffer(ctx, type); ++ } while (!ret); ++ ++ return ret; ++} ++ ++static int v4l2_request_wait_on_capture(V4L2RequestContext *ctx, ++ V4L2RequestBuffer *capture) ++{ ++ struct pollfd pollfd = { ++ .fd = ctx->video_fd, ++ .events = POLLIN, ++ }; ++ ++ ff_mutex_lock(&ctx->mutex); ++ ++ // Dequeue all completed capture buffers ++ if (atomic_load(&ctx->queued_capture)) ++ v4l2_request_dequeue_completed_buffers(ctx, ctx->format.type); ++ ++ // Wait on the specific capture buffer, when needed ++ while (atomic_load(&ctx->queued_capture) & (1 << capture->index)) { ++ int ret = poll(&pollfd, 1, 2000); ++ if (ret <= 0) ++ goto fail; ++ ++ ret = v4l2_request_dequeue_buffer(ctx, ctx->format.type); ++ if (ret < 0 && ret != AVERROR(EAGAIN)) ++ goto fail; ++ } ++ ++ ff_mutex_unlock(&ctx->mutex); ++ return 0; ++ ++fail: ++ ff_mutex_unlock(&ctx->mutex); ++ av_log(ctx, AV_LOG_ERROR, "Failed waiting on capture buffer %d\n", ++ capture->index); ++ return AVERROR(EINVAL); ++} ++ ++static V4L2RequestBuffer *v4l2_request_next_output(V4L2RequestContext *ctx) ++{ ++ int index; ++ V4L2RequestBuffer *output; ++ struct pollfd pollfd = { ++ .fd = ctx->video_fd, ++ .events = POLLOUT, ++ }; ++ ++ ff_mutex_lock(&ctx->mutex); ++ ++ // Use next output buffer in the circular queue ++ index = atomic_load(&ctx->next_output); ++ output = &ctx->output[index]; ++ atomic_store(&ctx->next_output, (index + 1) % FF_ARRAY_ELEMS(ctx->output)); ++ ++ // Dequeue all completed output buffers ++ if (atomic_load(&ctx->queued_output)) ++ v4l2_request_dequeue_completed_buffers(ctx, ctx->output_type); ++ ++ // Wait on the specific output buffer, when needed ++ while (atomic_load(&ctx->queued_output) & (1 << output->index)) { ++ int ret = poll(&pollfd, 1, 2000); ++ if (ret <= 0) ++ goto fail; ++ ++ ret = v4l2_request_dequeue_buffer(ctx, ctx->output_type); ++ if (ret < 0 && ret != AVERROR(EAGAIN)) ++ goto fail; ++ } ++ ++ ff_mutex_unlock(&ctx->mutex); ++ ++ // Reset used state ++ output->used = 0; ++ ++ return output; ++ ++fail: ++ ff_mutex_unlock(&ctx->mutex); ++ av_log(ctx, AV_LOG_ERROR, "Failed waiting on output buffer %d\n", ++ output->index); ++ return NULL; ++} ++ ++static int v4l2_request_wait_on_request(V4L2RequestContext *ctx, ++ V4L2RequestBuffer *output) ++{ ++ struct pollfd pollfd = { ++ .fd = output->fd, ++ .events = POLLPRI, ++ }; ++ ++ // Wait on the specific request to complete, when needed ++ while (atomic_load(&ctx->queued_request) & (1 << output->index)) { ++ int ret = poll(&pollfd, 1, 2000); ++ if (ret <= 0) ++ break; ++ ++ // Mark request as dequeued ++ if (pollfd.revents & (POLLPRI | POLLERR)) { ++ atomic_fetch_and(&ctx->queued_request, ~(1 << output->index)); ++ break; ++ } ++ } ++ ++ // Reinit the request object ++ if (ioctl(output->fd, MEDIA_REQUEST_IOC_REINIT, NULL) < 0) { ++ av_log(ctx, AV_LOG_ERROR, "Failed to reinit request object %d: %s (%d)\n", ++ output->fd, strerror(errno), errno); ++ return AVERROR(errno); ++ } ++ ++ // Ensure request is marked as dequeued ++ atomic_fetch_and(&ctx->queued_request, ~(1 << output->index)); ++ ++ return 0; ++} ++ ++int ff_v4l2_request_append_output(AVCodecContext *avctx, ++ V4L2RequestPictureContext *pic, ++ const uint8_t *data, uint32_t size) ++{ ++ V4L2RequestContext *ctx = v4l2_request_context(avctx); ++ ++ // Append data to output buffer and ensure there is enough space for padding ++ if (pic->output->used + size + INPUT_BUFFER_PADDING_SIZE <= pic->output->size) { ++ memcpy(pic->output->addr + pic->output->used, data, size); ++ pic->output->used += size; ++ return 0; ++ } else { ++ av_log(ctx, AV_LOG_ERROR, ++ "Failed to append %u bytes data to output buffer %d (%u of %u used)\n", ++ size, pic->output->index, pic->output->used, pic->output->size); ++ return AVERROR(ENOMEM); ++ } ++} ++ ++static int v4l2_request_queue_decode(AVCodecContext *avctx, ++ V4L2RequestPictureContext *pic, ++ struct v4l2_ext_control *control, int count, ++ bool first_slice, bool last_slice) ++{ ++ V4L2RequestContext *ctx = v4l2_request_context(avctx); ++ uint32_t flags; ++ int ret; ++ ++ if (first_slice) { ++ /* ++ * Wait on dequeue of the target capture buffer, when needed. Otherwise ++ * V4L2 decoder may use a different capture buffer than hwaccel expects. ++ * ++ * Normally decoding has already completed when a capture buffer is ++ * reused so this is more or less a no-op, however in some situations ++ * FFmpeg may reuse an AVFrame early, i.e. when no output frame was ++ * produced prior time, and a syncronization is necessary. ++ */ ++ ret = v4l2_request_wait_on_capture(ctx, pic->capture); ++ if (ret < 0) ++ return ret; ++ } ++ ++ ff_mutex_lock(&ctx->mutex); ++ ++ /* ++ * The output buffer tied to prior use of current request object can ++ * independently be dequeued before the full decode request has been ++ * completed. This may happen when a decoder use multi stage decoding, ++ * e.g. rpivid. In such case we can start reusing the output buffer, ++ * however we must wait on the prior request to fully complete before we ++ * can reuse the request object, and a syncronization is necessary. ++ */ ++ ret = v4l2_request_wait_on_request(ctx, pic->output); ++ if (ret < 0) ++ goto fail; ++ ++ /* ++ * Dequeue any completed output buffers, this is strictly not necessary, ++ * however if a syncronization was necessary for the capture and/or request ++ * there is more than likely one or more output buffers that can be dequeued. ++ */ ++ if (atomic_load(&ctx->queued_output)) ++ v4l2_request_dequeue_completed_buffers(ctx, ctx->output_type); ++ ++ // Set codec controls for current request ++ ret = ff_v4l2_request_set_request_controls(ctx, pic->output->fd, control, count); ++ if (ret < 0) { ++ av_log(ctx, AV_LOG_ERROR, "Failed to set %d control(s) for request %d: %s (%d)\n", ++ count, pic->output->fd, strerror(errno), errno); ++ goto fail; ++ } ++ ++ // Ensure there is zero padding at the end of bitstream data ++ memset(pic->output->addr + pic->output->used, 0, INPUT_BUFFER_PADDING_SIZE); ++ ++ // Use timestamp of the capture buffer for V4L2 frame reference ++ pic->output->buffer.timestamp = pic->capture->buffer.timestamp; ++ ++ /* ++ * Queue the output buffer of current request. The capture buffer may be ++ * hold by the V4L2 decoder unless this is the last slice of a frame. ++ */ ++ flags = last_slice ? 0 : V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF; ++ ret = v4l2_request_queue_buffer(ctx, pic->output->fd, pic->output, flags); ++ if (ret < 0) { ++ av_log(ctx, AV_LOG_ERROR, "Failed to queue output buffer %d for request %d: %s (%d)\n", ++ pic->output->index, pic->output->fd, strerror(errno), errno); ++ ret = AVERROR(errno); ++ goto fail; ++ } ++ ++ if (first_slice) { ++ /* ++ * Queue the target capture buffer, hwaccel expect and depend on that ++ * this specific capture buffer will be used as decode target for ++ * current request, otherwise frames may be output in wrong order or ++ * wrong capture buffer could get used as a reference frame. ++ */ ++ ret = v4l2_request_queue_buffer(ctx, -1, pic->capture, 0); ++ if (ret < 0) { ++ av_log(ctx, AV_LOG_ERROR, "Failed to queue capture buffer %d for request %d: %s (%d)\n", ++ pic->capture->index, pic->output->fd, strerror(errno), errno); ++ ret = AVERROR(errno); ++ goto fail; ++ } ++ } ++ ++ // Queue current request ++ ret = ioctl(pic->output->fd, MEDIA_REQUEST_IOC_QUEUE, NULL); ++ if (ret < 0) { ++ av_log(ctx, AV_LOG_ERROR, "Failed to queue request object %d: %s (%d)\n", ++ pic->output->fd, strerror(errno), errno); ++ ret = AVERROR(errno); ++ goto fail; ++ } ++ ++ // Mark current request as queued ++ atomic_fetch_or(&ctx->queued_request, 1 << pic->output->index); ++ ++ ret = 0; ++fail: ++ ff_mutex_unlock(&ctx->mutex); ++ return ret; ++} ++ ++int ff_v4l2_request_decode_slice(AVCodecContext *avctx, ++ V4L2RequestPictureContext *pic, ++ struct v4l2_ext_control *control, int count, ++ bool first_slice, bool last_slice) ++{ ++ /* ++ * Fallback to queue each slice as a full frame when holding capture ++ * buffers is not supported by the driver. ++ */ ++ if ((pic->output->capabilities & V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF) != ++ V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF) ++ return v4l2_request_queue_decode(avctx, pic, control, count, true, true); ++ ++ return v4l2_request_queue_decode(avctx, pic, control, count, ++ first_slice, last_slice); ++} ++ ++int ff_v4l2_request_decode_frame(AVCodecContext *avctx, ++ V4L2RequestPictureContext *pic, ++ struct v4l2_ext_control *control, int count) ++{ ++ return v4l2_request_queue_decode(avctx, pic, control, count, true, true); ++} ++ ++static int v4l2_request_post_process(void *logctx, AVFrame *frame) ++{ ++ V4L2RequestFrameDescriptor *desc = v4l2_request_framedesc(frame); ++ FrameDecodeData *fdd = (FrameDecodeData*)frame->private_ref->data; ++ V4L2RequestContext *ctx = fdd->hwaccel_priv; ++ ++ // Wait on capture buffer before returning the frame to application ++ return v4l2_request_wait_on_capture(ctx, &desc->capture); ++} ++ ++int ff_v4l2_request_reset_picture(AVCodecContext *avctx, V4L2RequestPictureContext *pic) ++{ ++ V4L2RequestContext *ctx = v4l2_request_context(avctx); ++ ++ // Get and wait on next output buffer from circular queue ++ pic->output = v4l2_request_next_output(ctx); ++ if (!pic->output) ++ return AVERROR(EINVAL); ++ ++ return 0; ++} ++ ++int ff_v4l2_request_start_frame(AVCodecContext *avctx, ++ V4L2RequestPictureContext *pic, ++ AVFrame *frame) ++{ ++ V4L2RequestContext *ctx = v4l2_request_context(avctx); ++ V4L2RequestFrameDescriptor *desc = v4l2_request_framedesc(frame); ++ FrameDecodeData *fdd = (FrameDecodeData*)frame->private_ref->data; ++ int ret; ++ ++ // Get next output buffer from circular queue ++ ret = ff_v4l2_request_reset_picture(avctx, pic); ++ if (ret) ++ return ret; ++ ++ // Ensure capture buffer is dequeued before reuse ++ ret = v4l2_request_wait_on_capture(ctx, &desc->capture); ++ if (ret) ++ return ret; ++ ++ // Wait on capture buffer in post_process() before returning to application ++ fdd->hwaccel_priv = ctx; ++ fdd->post_process = v4l2_request_post_process; ++ ++ // Capture buffer used for current frame ++ pic->capture = &desc->capture; ++ ++ return 0; ++} ++ ++void ff_v4l2_request_flush(AVCodecContext *avctx) ++{ ++ V4L2RequestContext *ctx = v4l2_request_context(avctx); ++ struct pollfd pollfd = { ++ .fd = ctx->video_fd, ++ .events = POLLOUT, ++ }; ++ ++ ff_mutex_lock(&ctx->mutex); ++ ++ // Dequeue all completed output buffers ++ if (atomic_load(&ctx->queued_output)) ++ v4l2_request_dequeue_completed_buffers(ctx, ctx->output_type); ++ ++ // Wait on any remaining output buffer ++ while (atomic_load(&ctx->queued_output)) { ++ int ret = poll(&pollfd, 1, 2000); ++ if (ret <= 0) ++ break; ++ ++ ret = v4l2_request_dequeue_buffer(ctx, ctx->output_type); ++ if (ret < 0 && ret != AVERROR(EAGAIN)) ++ break; ++ } ++ ++ // Dequeue all completed capture buffers ++ if (atomic_load(&ctx->queued_capture)) ++ v4l2_request_dequeue_completed_buffers(ctx, ctx->format.type); ++ ++ ff_mutex_unlock(&ctx->mutex); ++} + +From 66cb225496620a953033096eb1013692be9cb931 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Tue, 6 Aug 2024 09:06:04 +0000 +Subject: [PATCH 05/11] avcodec: Add V4L2 Request API mpeg2 hwaccel + +Add a V4L2 Request API hwaccel for MPEG2. + +Support for MPEG2 is enabled when Linux kernel headers declare the +control id V4L2_CID_STATELESS_MPEG2_SEQUENCE, added in v5.14. + +This also change v4l2_request hwaccel to use autodetect in configure. + +Signed-off-by: Jonas Karlman +--- + configure | 7 +- + libavcodec/Makefile | 1 + + libavcodec/hwaccels.h | 1 + + libavcodec/mpeg12dec.c | 6 ++ + libavcodec/v4l2_request_mpeg2.c | 176 ++++++++++++++++++++++++++++++++ + 5 files changed, 189 insertions(+), 2 deletions(-) + create mode 100644 libavcodec/v4l2_request_mpeg2.c + +diff --git a/configure b/configure +index b74da32e8b..cbf0ee0ced 100755 +--- a/configure ++++ b/configure +@@ -359,7 +359,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-v4l2-request disable V4L2 Request API code [autodetect] + --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] +@@ -2006,6 +2006,7 @@ HWACCEL_AUTODETECT_LIBRARY_LIST=" + videotoolbox + vulkan + v4l2_m2m ++ v4l2_request + " + + # catchall list of things that require external libs to link +@@ -2027,7 +2028,6 @@ HWACCEL_LIBRARY_LIST=" + mmal + omx + opencl +- v4l2_request + " + + DOCUMENT_LIST=" +@@ -3232,6 +3232,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" +@@ -7202,6 +7204,7 @@ if enabled v4l2_m2m; then + fi + + if enabled v4l2_request; then ++ check_cc mpeg2_v4l2_request linux/videodev2.h "int i = V4L2_CID_STATELESS_MPEG2_SEQUENCE" + check_cc v4l2_m2m_hold_capture_buf linux/videodev2.h "int i = V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF" + check_func_headers "linux/media.h linux/videodev2.h" v4l2_timeval_to_ns + check_pkg_config libudev libudev libudev.h udev_new +diff --git a/libavcodec/Makefile b/libavcodec/Makefile +index 6f2229b1b6..2c69b747b1 100644 +--- a/libavcodec/Makefile ++++ b/libavcodec/Makefile +@@ -1039,6 +1039,7 @@ OBJS-$(CONFIG_MPEG2_DXVA2_HWACCEL) += dxva2_mpeg2.o + OBJS-$(CONFIG_MPEG2_D3D12VA_HWACCEL) += dxva2_mpeg2.o d3d12va_mpeg2.o + OBJS-$(CONFIG_MPEG2_NVDEC_HWACCEL) += nvdec_mpeg12.o + OBJS-$(CONFIG_MPEG2_QSV_HWACCEL) += qsvdec.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 5171e4c7d7..0cba7c71be 100644 +--- a/libavcodec/hwaccels.h ++++ b/libavcodec/hwaccels.h +@@ -57,6 +57,7 @@ extern const struct FFHWAccel ff_mpeg2_d3d11va2_hwaccel; + extern const struct FFHWAccel ff_mpeg2_d3d12va_hwaccel; + extern const struct FFHWAccel ff_mpeg2_dxva2_hwaccel; + extern const struct FFHWAccel ff_mpeg2_nvdec_hwaccel; ++extern const struct FFHWAccel ff_mpeg2_v4l2request_hwaccel; + extern const struct FFHWAccel ff_mpeg2_vaapi_hwaccel; + extern const struct FFHWAccel ff_mpeg2_vdpau_hwaccel; + extern const struct FFHWAccel ff_mpeg2_videotoolbox_hwaccel; +diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c +index 4f784611de..af8ffa5976 100644 +--- a/libavcodec/mpeg12dec.c ++++ b/libavcodec/mpeg12dec.c +@@ -839,6 +839,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 +@@ -2681,6 +2684,9 @@ const FFCodec ff_mpeg2video_decoder = { + #endif + #if CONFIG_MPEG2_VIDEOTOOLBOX_HWACCEL + HWACCEL_VIDEOTOOLBOX(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 0000000000..998c91355a +--- /dev/null ++++ b/libavcodec/v4l2_request_mpeg2.c +@@ -0,0 +1,176 @@ ++/* ++ * 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 "hwaccel_internal.h" ++#include "hwconfig.h" ++#include "mpegvideo.h" ++#include "v4l2_request.h" ++ ++typedef struct V4L2RequestControlsMPEG2 { ++ V4L2RequestPictureContext pic; ++ struct v4l2_ctrl_mpeg2_sequence sequence; ++ struct v4l2_ctrl_mpeg2_picture picture; ++ struct v4l2_ctrl_mpeg2_quantisation quantisation; ++} 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->cur_pic.ptr->hwaccel_picture_private; ++ int ret; ++ ++ ret = ff_v4l2_request_start_frame(avctx, &controls->pic, s->cur_pic.ptr->f); ++ if (ret) ++ return ret; ++ ++ controls->sequence = (struct v4l2_ctrl_mpeg2_sequence) { ++ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Sequence header */ ++ .horizontal_size = s->width, ++ .vertical_size = s->height, ++ .vbv_buffer_size = controls->pic.output->size, ++ ++ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Sequence extension */ ++ .profile_and_level_indication = 0, ++ .chroma_format = s->chroma_format, ++ }; ++ ++ if (s->progressive_sequence) ++ controls->sequence.flags |= V4L2_MPEG2_SEQ_FLAG_PROGRESSIVE; ++ ++ controls->picture = (struct v4l2_ctrl_mpeg2_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], ++ .picture_structure = s->picture_structure, ++ .intra_dc_precision = s->intra_dc_precision, ++ }; ++ ++ if (s->top_field_first) ++ controls->picture.flags |= V4L2_MPEG2_PIC_FLAG_TOP_FIELD_FIRST; ++ ++ if (s->frame_pred_frame_dct) ++ controls->picture.flags |= V4L2_MPEG2_PIC_FLAG_FRAME_PRED_DCT; ++ ++ if (s->concealment_motion_vectors) ++ controls->picture.flags |= V4L2_MPEG2_PIC_FLAG_CONCEALMENT_MV; ++ ++ if (s->intra_vlc_format) ++ controls->picture.flags |= V4L2_MPEG2_PIC_FLAG_INTRA_VLC; ++ ++ if (s->q_scale_type) ++ controls->picture.flags |= V4L2_MPEG2_PIC_FLAG_Q_SCALE_TYPE; ++ ++ if (s->alternate_scan) ++ controls->picture.flags |= V4L2_MPEG2_PIC_FLAG_ALT_SCAN; ++ ++ if (s->repeat_first_field) ++ controls->picture.flags |= V4L2_MPEG2_PIC_FLAG_REPEAT_FIRST; ++ ++ if (s->progressive_frame) ++ controls->picture.flags |= V4L2_MPEG2_PIC_FLAG_PROGRESSIVE; ++ ++ switch (s->pict_type) { ++ case AV_PICTURE_TYPE_B: ++ if (s->next_pic.ptr) ++ controls->picture.backward_ref_ts = ++ ff_v4l2_request_get_capture_timestamp(s->next_pic.ptr->f); ++ // fall-through ++ case AV_PICTURE_TYPE_P: ++ if (s->last_pic.ptr) ++ controls->picture.forward_ref_ts = ++ ff_v4l2_request_get_capture_timestamp(s->last_pic.ptr->f); ++ } ++ ++ for (int i = 0; i < 64; i++) { ++ int n = s->idsp.idct_permutation[ff_zigzag_direct[i]]; ++ controls->quantisation.intra_quantiser_matrix[i] = s->intra_matrix[n]; ++ controls->quantisation.non_intra_quantiser_matrix[i] = s->inter_matrix[n]; ++ controls->quantisation.chroma_intra_quantiser_matrix[i] = s->chroma_intra_matrix[n]; ++ controls->quantisation.chroma_non_intra_quantiser_matrix[i] = s->chroma_inter_matrix[n]; ++ } ++ ++ return 0; ++} ++ ++static int v4l2_request_mpeg2_decode_slice(AVCodecContext *avctx, ++ const uint8_t *buffer, uint32_t size) ++{ ++ const MpegEncContext *s = avctx->priv_data; ++ V4L2RequestControlsMPEG2 *controls = s->cur_pic.ptr->hwaccel_picture_private; ++ ++ return ff_v4l2_request_append_output(avctx, &controls->pic, buffer, size); ++} ++ ++static int v4l2_request_mpeg2_end_frame(AVCodecContext *avctx) ++{ ++ const MpegEncContext *s = avctx->priv_data; ++ V4L2RequestControlsMPEG2 *controls = s->cur_pic.ptr->hwaccel_picture_private; ++ ++ struct v4l2_ext_control control[] = { ++ { ++ .id = V4L2_CID_STATELESS_MPEG2_SEQUENCE, ++ .ptr = &controls->sequence, ++ .size = sizeof(controls->sequence), ++ }, ++ { ++ .id = V4L2_CID_STATELESS_MPEG2_PICTURE, ++ .ptr = &controls->picture, ++ .size = sizeof(controls->picture), ++ }, ++ { ++ .id = V4L2_CID_STATELESS_MPEG2_QUANTISATION, ++ .ptr = &controls->quantisation, ++ .size = sizeof(controls->quantisation), ++ }, ++ }; ++ ++ return ff_v4l2_request_decode_frame(avctx, &controls->pic, ++ 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 FFHWAccel ff_mpeg2_v4l2request_hwaccel = { ++ .p.name = "mpeg2_v4l2request", ++ .p.type = AVMEDIA_TYPE_VIDEO, ++ .p.id = AV_CODEC_ID_MPEG2VIDEO, ++ .p.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, ++ .flush = ff_v4l2_request_flush, ++ .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, ++}; + +From bccaf9b66ca4e1180c0d42bc95daf540e1e2ffb7 Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Tue, 6 Aug 2024 09:06:05 +0000 +Subject: [PATCH 06/11] avcodec/h264dec: add ref_pic_marking and pic_order_cnt + bit_size to slice context + +The V4L2_CID_STATELESS_H264_DECODE_PARAMS control require following: + +- dec_ref_pic_marking_bit_size + Size in bits of the dec_ref_pic_marking() syntax element. + +- pic_order_cnt_bit_size + Combined size in bits of the picture order count related syntax + elements: pic_order_cnt_lsb, delta_pic_order_cnt_bottom, + delta_pic_order_cnt0, and delta_pic_order_cnt1. + +Save the bit sizes while parsing for later use in hwaccel, similar to +short/long_term_ref_pic_set_size in hevcdec. + +Signed-off-by: Boris Brezillon +Signed-off-by: Jonas Karlman +--- + libavcodec/h264_slice.c | 6 +++++- + libavcodec/h264dec.h | 2 ++ + 2 files changed, 7 insertions(+), 1 deletion(-) + +diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c +index a66b75ca80..58a48f3fbe 100644 +--- a/libavcodec/h264_slice.c ++++ b/libavcodec/h264_slice.c +@@ -1690,7 +1690,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); +@@ -1781,6 +1781,7 @@ static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl, + + sl->poc_lsb = 0; + sl->delta_poc_bottom = 0; ++ pos = get_bits_left(&sl->gb); + if (sps->poc_type == 0) { + sl->poc_lsb = get_bits(&sl->gb, sps->log2_max_poc_lsb); + +@@ -1795,6 +1796,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 = pos - get_bits_left(&sl->gb); + + sl->redundant_pic_count = 0; + if (pps->redundant_pic_cnt_present) +@@ -1834,9 +1836,11 @@ static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl, + + sl->explicit_ref_marking = 0; + if (nal->ref_idc) { ++ pos = get_bits_left(&sl->gb); + 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_bit_size = pos - get_bits_left(&sl->gb); + } + + if (sl->slice_type_nos != AV_PICTURE_TYPE_I && pps->cabac) { +diff --git a/libavcodec/h264dec.h b/libavcodec/h264dec.h +index ccd7583bf4..71cbb0e0cc 100644 +--- a/libavcodec/h264dec.h ++++ b/libavcodec/h264dec.h +@@ -324,6 +324,7 @@ typedef struct H264SliceContext { + MMCO mmco[H264_MAX_MMCO_COUNT]; + int nb_mmco; + int explicit_ref_marking; ++ int ref_pic_marking_bit_size; + + int frame_num; + int idr_pic_id; +@@ -332,6 +333,7 @@ typedef struct H264SliceContext { + int delta_poc[2]; + int curr_pic_num; + int max_pic_num; ++ int pic_order_cnt_bit_size; + } H264SliceContext; + + /** + +From e7674a31a7bc8b37a8ba4be0fc59074333a95b2d Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Tue, 6 Aug 2024 09:06:06 +0000 +Subject: [PATCH 07/11] avcodec: Add V4L2 Request API h264 hwaccel + +Add a V4L2 Request API hwaccel for H.264, supporting both slice and +frame decoding modes. + +Support for H.264 is enabled when Linux kernel headers declare the +control id V4L2_CID_STATELESS_H264_DECODE_MODE, added in v5.11. + +Signed-off-by: Jernej Skrabec +Co-developed-by: Jonas Karlman +Signed-off-by: Jonas Karlman +--- + configure | 3 + + libavcodec/Makefile | 1 + + libavcodec/h264_slice.c | 7 + + libavcodec/h264dec.c | 3 + + libavcodec/hwaccels.h | 1 + + libavcodec/v4l2_request_h264.c | 522 +++++++++++++++++++++++++++++++++ + 6 files changed, 537 insertions(+) + create mode 100644 libavcodec/v4l2_request_h264.c + +diff --git a/configure b/configure +index cbf0ee0ced..6866a61153 100755 +--- a/configure ++++ b/configure +@@ -3186,6 +3186,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" +@@ -7204,6 +7206,7 @@ if enabled v4l2_m2m; then + fi + + if enabled v4l2_request; then ++ check_cc h264_v4l2_request linux/videodev2.h "int i = V4L2_CID_STATELESS_H264_DECODE_MODE" + check_cc mpeg2_v4l2_request linux/videodev2.h "int i = V4L2_CID_STATELESS_MPEG2_SEQUENCE" + check_cc v4l2_m2m_hold_capture_buf linux/videodev2.h "int i = V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF" + check_func_headers "linux/media.h linux/videodev2.h" v4l2_timeval_to_ns +diff --git a/libavcodec/Makefile b/libavcodec/Makefile +index 2c69b747b1..00bc1cf8f2 100644 +--- a/libavcodec/Makefile ++++ b/libavcodec/Makefile +@@ -1017,6 +1017,7 @@ OBJS-$(CONFIG_H264_DXVA2_HWACCEL) += dxva2_h264.o + OBJS-$(CONFIG_H264_D3D12VA_HWACCEL) += dxva2_h264.o d3d12va_h264.o + OBJS-$(CONFIG_H264_NVDEC_HWACCEL) += nvdec_h264.o + OBJS-$(CONFIG_H264_QSV_HWACCEL) += qsvdec.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 58a48f3fbe..259a2c307a 100644 +--- a/libavcodec/h264_slice.c ++++ b/libavcodec/h264_slice.c +@@ -781,6 +781,7 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback) + (CONFIG_H264_D3D11VA_HWACCEL * 2) + \ + CONFIG_H264_D3D12VA_HWACCEL + \ + CONFIG_H264_NVDEC_HWACCEL + \ ++ CONFIG_H264_V4L2REQUEST_HWACCEL + \ + CONFIG_H264_VAAPI_HWACCEL + \ + CONFIG_H264_VIDEOTOOLBOX_HWACCEL + \ + CONFIG_H264_VDPAU_HWACCEL + \ +@@ -806,6 +807,9 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback) + #endif + #if CONFIG_H264_VULKAN_HWACCEL + *fmt++ = AV_PIX_FMT_VULKAN; ++#endif ++#if CONFIG_H264_V4L2REQUEST_HWACCEL ++ *fmt++ = AV_PIX_FMT_DRM_PRIME; + #endif + if (CHROMA444(h)) { + if (h->avctx->colorspace == AVCOL_SPC_RGB) { +@@ -862,6 +866,9 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback) + #if CONFIG_H264_VIDEOTOOLBOX_HWACCEL + if (h->avctx->colorspace != AVCOL_SPC_RGB) + *fmt++ = AV_PIX_FMT_VIDEOTOOLBOX; ++#endif ++#if CONFIG_H264_V4L2REQUEST_HWACCEL ++ *fmt++ = AV_PIX_FMT_DRM_PRIME; + #endif + if (CHROMA444(h)) { + if (h->avctx->colorspace == AVCOL_SPC_RGB) +diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c +index 0154fe17b6..a5e89ebddd 100644 +--- a/libavcodec/h264dec.c ++++ b/libavcodec/h264dec.c +@@ -1160,6 +1160,9 @@ const FFCodec ff_h264_decoder = { + #endif + #if CONFIG_H264_VULKAN_HWACCEL + HWACCEL_VULKAN(h264), ++#endif ++#if CONFIG_H264_V4L2REQUEST_HWACCEL ++ HWACCEL_V4L2REQUEST(h264), + #endif + NULL + }, +diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h +index 0cba7c71be..024e021d73 100644 +--- a/libavcodec/hwaccels.h ++++ b/libavcodec/hwaccels.h +@@ -34,6 +34,7 @@ extern const struct FFHWAccel ff_h264_d3d11va2_hwaccel; + extern const struct FFHWAccel ff_h264_d3d12va_hwaccel; + extern const struct FFHWAccel ff_h264_dxva2_hwaccel; + extern const struct FFHWAccel ff_h264_nvdec_hwaccel; ++extern const struct FFHWAccel ff_h264_v4l2request_hwaccel; + extern const struct FFHWAccel ff_h264_vaapi_hwaccel; + extern const struct FFHWAccel ff_h264_vdpau_hwaccel; + extern const struct FFHWAccel ff_h264_videotoolbox_hwaccel; +diff --git a/libavcodec/v4l2_request_h264.c b/libavcodec/v4l2_request_h264.c +new file mode 100644 +index 0000000000..5affe309ac +--- /dev/null ++++ b/libavcodec/v4l2_request_h264.c +@@ -0,0 +1,522 @@ ++/* ++ * 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 "h264dec.h" ++#include "hwaccel_internal.h" ++#include "hwconfig.h" ++#include "internal.h" ++#include "v4l2_request.h" ++ ++typedef struct V4L2RequestContextH264 { ++ V4L2RequestContext base; ++ enum v4l2_stateless_h264_decode_mode decode_mode; ++ enum v4l2_stateless_h264_start_code start_code; ++} V4L2RequestContextH264; ++ ++typedef struct V4L2RequestControlsH264 { ++ V4L2RequestPictureContext pic; ++ 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; ++ bool pred_weights_required; ++ bool first_slice; ++ int num_slices; ++} V4L2RequestControlsH264; ++ ++static uint8_t nalu_slice_start_code[] = { 0x00, 0x00, 0x01 }; ++ ++static void fill_weight_factors(struct v4l2_h264_weight_factors *weight_factors, ++ int list, const H264SliceContext *sl) ++{ ++ for (int i = 0; i < sl->ref_count[list]; i++) { ++ if (sl->pwt.luma_weight_flag[list]) { ++ weight_factors->luma_weight[i] = sl->pwt.luma_weight[i][list][0]; ++ weight_factors->luma_offset[i] = sl->pwt.luma_weight[i][list][1]; ++ } else { ++ weight_factors->luma_weight[i] = 1 << sl->pwt.luma_log2_weight_denom; ++ weight_factors->luma_offset[i] = 0; ++ } ++ for (int j = 0; j < 2; j++) { ++ if (sl->pwt.chroma_weight_flag[list]) { ++ weight_factors->chroma_weight[i][j] = sl->pwt.chroma_weight[i][list][j][0]; ++ weight_factors->chroma_offset[i][j] = sl->pwt.chroma_weight[i][list][j][1]; ++ } else { ++ weight_factors->chroma_weight[i][j] = 1 << sl->pwt.chroma_log2_weight_denom; ++ weight_factors->chroma_offset[i][j] = 0; ++ } ++ } ++ } ++} ++ ++static void fill_dpb_entry(struct v4l2_h264_dpb_entry *entry, ++ const H264Picture *pic, int long_idx) ++{ ++ entry->reference_ts = ff_v4l2_request_get_capture_timestamp(pic->f); ++ entry->pic_num = pic->pic_id; ++ entry->frame_num = pic->long_ref ? long_idx : 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_params, ++ 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_params->dpb[entries++], pic, pic->pic_id); ++ } ++ ++ 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_params->dpb[entries++], pic, i); ++ } ++} ++ ++static void fill_ref_list(struct v4l2_h264_reference *reference, ++ struct v4l2_ctrl_h264_decode_params *decode_params, ++ 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_params->dpb); i++) { ++ struct v4l2_h264_dpb_entry *entry = &decode_params->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; ++ int ret; ++ ++ ret = ff_v4l2_request_start_frame(avctx, &controls->pic, h->cur_pic_ptr->f); ++ if (ret) ++ return ret; ++ ++ 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_bit_size, ++ /* 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; ++ ++#if defined(V4L2_H264_DECODE_PARAM_FLAG_PFRAME) ++ if (sl->slice_type_nos == AV_PICTURE_TYPE_P) ++ controls->decode_params.flags |= V4L2_H264_DECODE_PARAM_FLAG_PFRAME; ++#endif ++ ++#if defined(V4L2_H264_DECODE_PARAM_FLAG_BFRAME) ++ if (sl->slice_type_nos == AV_PICTURE_TYPE_B) ++ controls->decode_params.flags |= V4L2_H264_DECODE_PARAM_FLAG_BFRAME; ++#endif ++ ++ fill_dpb(&controls->decode_params, h); ++ ++ controls->first_slice = true; ++ controls->num_slices = 0; ++ ++ return 0; ++} ++ ++static int v4l2_request_h264_queue_decode(AVCodecContext *avctx, bool last_slice) ++{ ++ const H264Context *h = avctx->priv_data; ++ V4L2RequestContextH264 *ctx = avctx->internal->hwaccel_priv_data; ++ V4L2RequestControlsH264 *controls = h->cur_pic_ptr->hwaccel_picture_private; ++ ++ struct v4l2_ext_control control[] = { ++ { ++ .id = V4L2_CID_STATELESS_H264_SPS, ++ .ptr = &controls->sps, ++ .size = sizeof(controls->sps), ++ }, ++ { ++ .id = V4L2_CID_STATELESS_H264_PPS, ++ .ptr = &controls->pps, ++ .size = sizeof(controls->pps), ++ }, ++ { ++ .id = V4L2_CID_STATELESS_H264_SCALING_MATRIX, ++ .ptr = &controls->scaling_matrix, ++ .size = sizeof(controls->scaling_matrix), ++ }, ++ { ++ .id = V4L2_CID_STATELESS_H264_DECODE_PARAMS, ++ .ptr = &controls->decode_params, ++ .size = sizeof(controls->decode_params), ++ }, ++ { ++ .id = V4L2_CID_STATELESS_H264_SLICE_PARAMS, ++ .ptr = &controls->slice_params, ++ .size = sizeof(controls->slice_params), ++ }, ++ { ++ .id = V4L2_CID_STATELESS_H264_PRED_WEIGHTS, ++ .ptr = &controls->pred_weights, ++ .size = sizeof(controls->pred_weights), ++ }, ++ }; ++ ++ if (ctx->decode_mode == V4L2_STATELESS_H264_DECODE_MODE_SLICE_BASED) { ++ int count = FF_ARRAY_ELEMS(control) - (controls->pred_weights_required ? 0 : 1); ++ return ff_v4l2_request_decode_slice(avctx, &controls->pic, control, count, ++ controls->first_slice, last_slice); ++ } ++ ++ return ff_v4l2_request_decode_frame(avctx, &controls->pic, ++ 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]; ++ V4L2RequestContextH264 *ctx = avctx->internal->hwaccel_priv_data; ++ V4L2RequestControlsH264 *controls = h->cur_pic_ptr->hwaccel_picture_private; ++ int i, ret, count; ++ ++ if (ctx->decode_mode == V4L2_STATELESS_H264_DECODE_MODE_SLICE_BASED && ++ controls->num_slices) { ++ ret = v4l2_request_h264_queue_decode(avctx, false); ++ if (ret) ++ return ret; ++ ++ ff_v4l2_request_reset_picture(avctx, &controls->pic); ++ controls->first_slice = 0; ++ } ++ ++ if (ctx->start_code == V4L2_STATELESS_H264_START_CODE_ANNEX_B) { ++ ret = ff_v4l2_request_append_output(avctx, &controls->pic, ++ nalu_slice_start_code, 3); ++ if (ret) ++ return ret; ++ } ++ ++ ret = ff_v4l2_request_append_output(avctx, &controls->pic, buffer, size); ++ if (ret) ++ return ret; ++ ++ if (ctx->decode_mode != V4L2_STATELESS_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) ++{ ++ return v4l2_request_h264_queue_decode(avctx, true); ++} ++ ++static int v4l2_request_h264_post_probe(AVCodecContext *avctx) ++{ ++ V4L2RequestContextH264 *ctx = avctx->internal->hwaccel_priv_data; ++ ++ struct v4l2_ext_control control[] = { ++ { .id = V4L2_CID_STATELESS_H264_DECODE_MODE, }, ++ { .id = V4L2_CID_STATELESS_H264_START_CODE, }, ++ }; ++ ++ ctx->decode_mode = ff_v4l2_request_query_control_default_value(avctx, ++ V4L2_CID_STATELESS_H264_DECODE_MODE); ++ if (ctx->decode_mode != V4L2_STATELESS_H264_DECODE_MODE_SLICE_BASED && ++ ctx->decode_mode != V4L2_STATELESS_H264_DECODE_MODE_FRAME_BASED) { ++ av_log(ctx, AV_LOG_VERBOSE, "Unsupported decode mode: %d\n", ++ ctx->decode_mode); ++ return AVERROR(EINVAL); ++ } ++ ++ ctx->start_code = ff_v4l2_request_query_control_default_value(avctx, ++ V4L2_CID_STATELESS_H264_START_CODE); ++ if (ctx->start_code != V4L2_STATELESS_H264_START_CODE_NONE && ++ ctx->start_code != V4L2_STATELESS_H264_START_CODE_ANNEX_B) { ++ av_log(ctx, AV_LOG_VERBOSE, "Unsupported start code: %d\n", ++ ctx->start_code); ++ return AVERROR(EINVAL); ++ } ++ ++ // TODO: check V4L2_CID_MPEG_VIDEO_H264_PROFILE control ++ // TODO: check V4L2_CID_MPEG_VIDEO_H264_LEVEL control ++ ++ 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) ++{ ++ V4L2RequestContextH264 *ctx = avctx->internal->hwaccel_priv_data; ++ const H264Context *h = avctx->priv_data; ++ struct v4l2_ctrl_h264_sps sps; ++ ++ struct v4l2_ext_control control[] = { ++ { ++ .id = V4L2_CID_STATELESS_H264_SPS, ++ .ptr = &sps, ++ .size = sizeof(sps), ++ }, ++ }; ++ ++ fill_sps(&sps, h); ++ ++ ctx->base.post_probe = v4l2_request_h264_post_probe; ++ return ff_v4l2_request_init(avctx, V4L2_PIX_FMT_H264_SLICE, ++ 4 * 1024 * 1024, ++ control, FF_ARRAY_ELEMS(control)); ++} ++ ++const FFHWAccel ff_h264_v4l2request_hwaccel = { ++ .p.name = "h264_v4l2request", ++ .p.type = AVMEDIA_TYPE_VIDEO, ++ .p.id = AV_CODEC_ID_H264, ++ .p.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, ++ .flush = ff_v4l2_request_flush, ++ .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, ++}; + +From 0b3c85ab94619e449026145a9795f2013732977c Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Tue, 6 Aug 2024 09:06:07 +0000 +Subject: [PATCH 08/11] avcodec: Add V4L2 Request API hevc hwaccel + +Add a V4L2 Request API hwaccel for HEVC, supporting both slice and +frame decoding modes. + +Support for HEVC is enabled when Linux kernel headers declare the +control id V4L2_CID_STATELESS_HEVC_SPS, added in v6.0. + +Co-developed-by: Benjamin Gaignard +Signed-off-by: Benjamin Gaignard +Co-developed-by: Alex Bee +Signed-off-by: Alex Bee +Signed-off-by: Jernej Skrabec +Co-developed-by: Jonas Karlman +Signed-off-by: Jonas Karlman +--- + configure | 5 + + libavcodec/Makefile | 1 + + libavcodec/hevc/hevcdec.c | 10 + + libavcodec/hwaccels.h | 1 + + libavcodec/v4l2_request_hevc.c | 745 +++++++++++++++++++++++++++++++++ + 5 files changed, 762 insertions(+) + create mode 100644 libavcodec/v4l2_request_hevc.c + +diff --git a/configure b/configure +index 6866a61153..7a2901d960 100755 +--- a/configure ++++ b/configure +@@ -2491,6 +2491,7 @@ TYPES_LIST=" + struct_sockaddr_sa_len + struct_sockaddr_storage + struct_stat_st_mtim_tv_nsec ++ struct_v4l2_ctrl_hevc_decode_params_num_delta_pocs_of_ref_rps_idx + struct_v4l2_frmivalenum_discrete + struct_mfxConfigInterface + " +@@ -3206,6 +3207,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" +@@ -7207,10 +7210,12 @@ fi + + if enabled v4l2_request; then + check_cc h264_v4l2_request linux/videodev2.h "int i = V4L2_CID_STATELESS_H264_DECODE_MODE" ++ check_cc hevc_v4l2_request linux/videodev2.h "int i = V4L2_CID_STATELESS_HEVC_SPS" + check_cc mpeg2_v4l2_request linux/videodev2.h "int i = V4L2_CID_STATELESS_MPEG2_SEQUENCE" + check_cc v4l2_m2m_hold_capture_buf linux/videodev2.h "int i = V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF" + check_func_headers "linux/media.h linux/videodev2.h" v4l2_timeval_to_ns + check_pkg_config libudev libudev libudev.h udev_new ++ check_struct linux/videodev2.h "struct v4l2_ctrl_hevc_decode_params" num_delta_pocs_of_ref_rps_idx + fi + + check_headers sys/videoio.h +diff --git a/libavcodec/Makefile b/libavcodec/Makefile +index 00bc1cf8f2..fa78523b76 100644 +--- a/libavcodec/Makefile ++++ b/libavcodec/Makefile +@@ -1027,6 +1027,7 @@ OBJS-$(CONFIG_HEVC_DXVA2_HWACCEL) += dxva2_hevc.o + OBJS-$(CONFIG_HEVC_D3D12VA_HWACCEL) += dxva2_hevc.o d3d12va_hevc.o + OBJS-$(CONFIG_HEVC_NVDEC_HWACCEL) += nvdec_hevc.o + OBJS-$(CONFIG_HEVC_QSV_HWACCEL) += qsvdec.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 h265_profile_level.o + OBJS-$(CONFIG_HEVC_VULKAN_HWACCEL) += vulkan_decode.o vulkan_hevc.o +diff --git a/libavcodec/hevc/hevcdec.c b/libavcodec/hevc/hevcdec.c +index 0dc24f82f8..4b14a931a2 100644 +--- a/libavcodec/hevc/hevcdec.c ++++ b/libavcodec/hevc/hevcdec.c +@@ -527,6 +527,7 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps) + CONFIG_HEVC_D3D11VA_HWACCEL * 2 + \ + CONFIG_HEVC_D3D12VA_HWACCEL + \ + CONFIG_HEVC_NVDEC_HWACCEL + \ ++ CONFIG_HEVC_V4L2REQUEST_HWACCEL + \ + CONFIG_HEVC_VAAPI_HWACCEL + \ + CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL + \ + CONFIG_HEVC_VDPAU_HWACCEL + \ +@@ -561,6 +562,9 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps) + #endif + #if CONFIG_HEVC_VULKAN_HWACCEL + *fmt++ = AV_PIX_FMT_VULKAN; ++#endif ++#if CONFIG_HEVC_V4L2REQUEST_HWACCEL ++ *fmt++ = AV_PIX_FMT_DRM_PRIME; + #endif + break; + case AV_PIX_FMT_YUV420P10: +@@ -588,6 +592,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: +@@ -4107,6 +4114,9 @@ const FFCodec ff_hevc_decoder = { + #endif + #if CONFIG_HEVC_VULKAN_HWACCEL + HWACCEL_VULKAN(hevc), ++#endif ++#if CONFIG_HEVC_V4L2REQUEST_HWACCEL ++ HWACCEL_V4L2REQUEST(hevc), + #endif + NULL + }, +diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h +index 024e021d73..ad145fc07c 100644 +--- a/libavcodec/hwaccels.h ++++ b/libavcodec/hwaccels.h +@@ -44,6 +44,7 @@ extern const struct FFHWAccel ff_hevc_d3d11va2_hwaccel; + extern const struct FFHWAccel ff_hevc_d3d12va_hwaccel; + extern const struct FFHWAccel ff_hevc_dxva2_hwaccel; + extern const struct FFHWAccel ff_hevc_nvdec_hwaccel; ++extern const struct FFHWAccel ff_hevc_v4l2request_hwaccel; + extern const struct FFHWAccel ff_hevc_vaapi_hwaccel; + extern const struct FFHWAccel ff_hevc_vdpau_hwaccel; + extern const struct FFHWAccel ff_hevc_videotoolbox_hwaccel; +diff --git a/libavcodec/v4l2_request_hevc.c b/libavcodec/v4l2_request_hevc.c +new file mode 100644 +index 0000000000..9fabe468b7 +--- /dev/null ++++ b/libavcodec/v4l2_request_hevc.c +@@ -0,0 +1,745 @@ ++/* ++ * 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/mem.h" ++#include "hevc/hevcdec.h" ++#include "hwaccel_internal.h" ++#include "hwconfig.h" ++#include "internal.h" ++#include "v4l2_request.h" ++ ++#define V4L2_HEVC_CONTROLS_MAX 6 ++ ++typedef struct V4L2RequestContextHEVC { ++ V4L2RequestContext base; ++ enum v4l2_stateless_hevc_decode_mode decode_mode; ++ enum v4l2_stateless_hevc_start_code start_code; ++ unsigned int max_slice_params; ++ unsigned int max_entry_point_offsets; ++ bool has_scaling_matrix; ++} V4L2RequestContextHEVC; ++ ++typedef struct V4L2RequestControlsHEVC { ++ V4L2RequestPictureContext pic; ++ struct v4l2_ctrl_hevc_sps sps; ++ struct v4l2_ctrl_hevc_pps pps; ++ struct v4l2_ctrl_hevc_decode_params decode_params; ++ struct v4l2_ctrl_hevc_scaling_matrix scaling_matrix; ++ struct v4l2_ctrl_hevc_slice_params slice_params; ++ struct v4l2_ctrl_hevc_slice_params *frame_slice_params; ++ unsigned int allocated_slice_params; ++ unsigned int num_slice_params; ++ uint32_t *entry_point_offsets; ++ unsigned int allocated_entry_point_offsets; ++ unsigned int num_entry_point_offsets; ++ bool first_slice; ++} V4L2RequestControlsHEVC; ++ ++static uint8_t nalu_slice_start_code[] = { 0x00, 0x00, 0x01 }; ++ ++static void fill_pred_weight_table(struct v4l2_hevc_pred_weight_table *table, ++ const HEVCContext *h) ++{ ++ 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->pps->weighted_pred_flag) || ++ (sh->slice_type == HEVC_SLICE_B && !h->pps->weighted_bipred_flag)) ++ return; ++ ++ table->luma_log2_weight_denom = sh->luma_log2_weight_denom; ++ ++ if (h->pps->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 uint8_t get_ref_pic_index(const HEVCContext *h, const HEVCFrame *frame, ++ struct v4l2_ctrl_hevc_decode_params *decode_params) ++{ ++ uint64_t timestamp; ++ ++ if (!frame || !frame->f) ++ return 0; ++ ++ timestamp = ff_v4l2_request_get_capture_timestamp(frame->f); ++ ++ for (uint8_t i = 0; i < decode_params->num_active_dpb_entries; i++) { ++ struct v4l2_hevc_dpb_entry *entry = &decode_params->dpb[i]; ++ if (entry->timestamp == timestamp) ++ return i; ++ } ++ ++ return 0; ++} ++ ++static void fill_decode_params(struct v4l2_ctrl_hevc_decode_params *decode_params, ++ const HEVCContext *h) ++{ ++ const HEVCFrame *pic = h->cur_frame; ++ const HEVCLayerContext *l = &h->layers[h->cur_layer]; ++ const SliceHeader *sh = &h->sh; ++ int i, entries = 0; ++ ++ *decode_params = (struct v4l2_ctrl_hevc_decode_params) { ++ .pic_order_cnt_val = h->poc, ++ .short_term_ref_pic_set_size = sh->short_term_ref_pic_set_size, ++ .long_term_ref_pic_set_size = sh->long_term_ref_pic_set_size, ++ .num_poc_st_curr_before = h->rps[ST_CURR_BEF].nb_refs, ++ .num_poc_st_curr_after = h->rps[ST_CURR_AFT].nb_refs, ++ .num_poc_lt_curr = h->rps[LT_CURR].nb_refs, ++ }; ++ ++#if HAVE_STRUCT_V4L2_CTRL_HEVC_DECODE_PARAMS_NUM_DELTA_POCS_OF_REF_RPS_IDX ++ if (h->sh.short_term_ref_pic_set_sps_flag == 0 && h->sh.short_term_rps) ++ decode_params->num_delta_pocs_of_ref_rps_idx = ++ h->sh.short_term_rps->rps_idx_num_delta_pocs; ++#endif ++ ++ for (i = 0; i < FF_ARRAY_ELEMS(l->DPB); i++) { ++ const HEVCFrame *frame = &l->DPB[i]; ++ if (frame != pic && ++ (frame->flags & (HEVC_FRAME_FLAG_LONG_REF | HEVC_FRAME_FLAG_SHORT_REF))) { ++ struct v4l2_hevc_dpb_entry *entry = &decode_params->dpb[entries++]; ++ ++ entry->timestamp = ff_v4l2_request_get_capture_timestamp(frame->f); ++ entry->field_pic = !!(frame->f->flags & AV_FRAME_FLAG_INTERLACED); ++ entry->flags = 0; ++ if (frame->flags & HEVC_FRAME_FLAG_LONG_REF) ++ entry->flags |= V4L2_HEVC_DPB_ENTRY_LONG_TERM_REFERENCE; ++ ++ entry->pic_order_cnt_val = frame->poc; ++ } ++ } ++ ++ decode_params->num_active_dpb_entries = entries; ++ ++ if (IS_IRAP(h)) ++ decode_params->flags |= V4L2_HEVC_DECODE_PARAM_FLAG_IRAP_PIC; ++ ++ if (IS_IDR(h)) ++ decode_params->flags |= V4L2_HEVC_DECODE_PARAM_FLAG_IDR_PIC; ++ ++ if (sh->no_output_of_prior_pics_flag) ++ decode_params->flags |= V4L2_HEVC_DECODE_PARAM_FLAG_NO_OUTPUT_OF_PRIOR; ++ ++ for (i = 0; i < V4L2_HEVC_DPB_ENTRIES_NUM_MAX; i++) { ++ decode_params->poc_st_curr_before[i] = ++ get_ref_pic_index(h, h->rps[ST_CURR_BEF].ref[i], decode_params); ++ decode_params->poc_st_curr_after[i] = ++ get_ref_pic_index(h, h->rps[ST_CURR_AFT].ref[i], decode_params); ++ decode_params->poc_lt_curr[i] = ++ get_ref_pic_index(h, h->rps[LT_CURR].ref[i], decode_params); ++ } ++} ++ ++static int fill_slice_params(V4L2RequestControlsHEVC *controls, int slice, ++ bool max_entry_point_offsets, const HEVCContext *h) ++{ ++ struct v4l2_ctrl_hevc_slice_params *slice_params = &controls->frame_slice_params[slice]; ++ struct v4l2_ctrl_hevc_decode_params *decode_params = &controls->decode_params; ++ const SliceHeader *sh = &h->sh; ++ RefPicList *rpl; ++ int i, offsets; ++ ++ *slice_params = (struct v4l2_ctrl_hevc_slice_params) { ++ .bit_size = 0, ++ .data_byte_offset = controls->pic.output->used + sh->data_offset, ++ .num_entry_point_offsets = sh->num_entry_point_offsets, ++ ++ /* 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 = sh->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 */ ++ .slice_segment_addr = sh->slice_segment_addr, ++ .short_term_ref_pic_set_size = sh->short_term_ref_pic_set_size, ++ .long_term_ref_pic_set_size = sh->long_term_ref_pic_set_size, ++ }; ++ ++ if (h->pps->pps_slice_act_qp_offsets_present_flag) { ++ slice_params->slice_act_y_qp_offset = sh->slice_act_y_qp_offset; ++ slice_params->slice_act_cb_qp_offset = sh->slice_act_cb_qp_offset; ++ slice_params->slice_act_cr_qp_offset = sh->slice_act_cr_qp_offset; ++ } ++ ++ 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->use_integer_mv_flag) ++ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_USE_INTEGER_MV; ++ ++ 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; ++ ++ if (sh->slice_type != HEVC_SLICE_I) { ++ rpl = &h->cur_frame->refPicList[0]; ++ for (i = 0; i < rpl->nb_refs; i++) ++ slice_params->ref_idx_l0[i] = get_ref_pic_index(h, rpl->ref[i], decode_params); ++ } ++ ++ if (sh->slice_type == HEVC_SLICE_B) { ++ rpl = &h->cur_frame->refPicList[1]; ++ for (i = 0; i < rpl->nb_refs; i++) ++ slice_params->ref_idx_l1[i] = get_ref_pic_index(h, rpl->ref[i], decode_params); ++ } ++ ++ fill_pred_weight_table(&slice_params->pred_weight_table, h); ++ ++ if (!max_entry_point_offsets) ++ return 0; ++ ++ if (controls->allocated_entry_point_offsets < controls->num_entry_point_offsets + sh->num_entry_point_offsets) { ++ void *entry_point_offsets = controls->entry_point_offsets; ++ offsets = controls->allocated_entry_point_offsets == 0 ? 128 : controls->allocated_entry_point_offsets * 2; ++ while (controls->num_entry_point_offsets + sh->num_entry_point_offsets > offsets) ++ offsets *= 2; ++ entry_point_offsets = av_realloc_array(entry_point_offsets, offsets, sizeof(*controls->entry_point_offsets)); ++ if (!entry_point_offsets) ++ return AVERROR(ENOMEM); ++ controls->entry_point_offsets = entry_point_offsets; ++ controls->allocated_entry_point_offsets = offsets; ++ } ++ ++ for (i = 0, offsets = controls->num_entry_point_offsets; i < sh->num_entry_point_offsets; i++) ++ controls->entry_point_offsets[offsets + i] = sh->entry_point_offset[i]; ++ controls->num_entry_point_offsets += sh->num_entry_point_offsets; ++ ++ return 0; ++} ++ ++static void fill_sps(struct v4l2_ctrl_hevc_sps *ctrl, const HEVCContext *h) ++{ ++ const HEVCPPS *pps = h->pps; ++ const HEVCSPS *sps = pps->sps; ++ ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Sequence parameter set */ ++ *ctrl = (struct v4l2_ctrl_hevc_sps) { ++ .video_parameter_set_id = sps->vps_id, ++ .seq_parameter_set_id = pps->sps_id, ++ .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_chroma - 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, ++ .chroma_format_idc = sps->chroma_format_idc, ++ .sps_max_sub_layers_minus1 = sps->max_sub_layers - 1, ++ }; ++ ++ if (sps->separate_colour_plane) ++ ctrl->flags |= V4L2_HEVC_SPS_FLAG_SEPARATE_COLOUR_PLANE; ++ ++ if (sps->scaling_list_enabled) ++ ctrl->flags |= V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED; ++ ++ if (sps->amp_enabled) ++ 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) ++ ctrl->flags |= V4L2_HEVC_SPS_FLAG_PCM_ENABLED; ++ ++ if (sps->pcm_loop_filter_disabled) ++ ctrl->flags |= V4L2_HEVC_SPS_FLAG_PCM_LOOP_FILTER_DISABLED; ++ ++ if (sps->long_term_ref_pics_present) ++ ctrl->flags |= V4L2_HEVC_SPS_FLAG_LONG_TERM_REF_PICS_PRESENT; ++ ++ if (sps->temporal_mvp_enabled) ++ ctrl->flags |= V4L2_HEVC_SPS_FLAG_SPS_TEMPORAL_MVP_ENABLED; ++ ++ if (sps->strong_intra_smoothing_enabled) ++ 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 HEVCPPS *pps = h->pps; ++ const HEVCSPS *sps = pps->sps; ++ V4L2RequestContextHEVC *ctx = avctx->internal->hwaccel_priv_data; ++ V4L2RequestControlsHEVC *controls = h->cur_frame->hwaccel_picture_private; ++ const SliceHeader *sh = &h->sh; ++ int ret; ++ ++ ret = ff_v4l2_request_start_frame(avctx, &controls->pic, h->cur_frame->f); ++ if (ret) ++ return ret; ++ ++ fill_sps(&controls->sps, h); ++ fill_decode_params(&controls->decode_params, h); ++ ++ if (ctx->has_scaling_matrix) { ++ const ScalingList *sl = pps->scaling_list_data_present_flag ? ++ &pps->scaling_list : ++ sps->scaling_list_enabled ? ++ &sps->scaling_list : NULL; ++ 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) { ++ .pic_parameter_set_id = sh->pps_id, ++ .num_extra_slice_header_bits = pps->num_extra_slice_header_bits, ++ .num_ref_idx_l0_default_active_minus1 = pps->num_ref_idx_l0_default_active - 1, ++ .num_ref_idx_l1_default_active_minus1 = pps->num_ref_idx_l1_default_active - 1, ++ .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_ENABLED; ++ ++ 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->deblocking_filter_control_present_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT; ++ ++ if (pps->uniform_spacing_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_UNIFORM_SPACING; ++ ++ 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 = true; ++ controls->frame_slice_params = &controls->slice_params; ++ controls->allocated_slice_params = 0; ++ controls->num_slice_params = 0; ++ controls->allocated_entry_point_offsets = 0; ++ controls->num_entry_point_offsets = 0; ++ ++ return 0; ++} ++ ++static int v4l2_request_hevc_queue_decode(AVCodecContext *avctx, bool last_slice) ++{ ++ const HEVCContext *h = avctx->priv_data; ++ V4L2RequestContextHEVC *ctx = avctx->internal->hwaccel_priv_data; ++ V4L2RequestControlsHEVC *controls = h->cur_frame->hwaccel_picture_private; ++ int count = 0; ++ ++ struct v4l2_ext_control control[V4L2_HEVC_CONTROLS_MAX] = {}; ++ ++ control[count++] = (struct v4l2_ext_control) { ++ .id = V4L2_CID_STATELESS_HEVC_SPS, ++ .ptr = &controls->sps, ++ .size = sizeof(controls->sps), ++ }; ++ ++ control[count++] = (struct v4l2_ext_control) { ++ .id = V4L2_CID_STATELESS_HEVC_PPS, ++ .ptr = &controls->pps, ++ .size = sizeof(controls->pps), ++ }; ++ ++ control[count++] = (struct v4l2_ext_control) { ++ .id = V4L2_CID_STATELESS_HEVC_DECODE_PARAMS, ++ .ptr = &controls->decode_params, ++ .size = sizeof(controls->decode_params), ++ }; ++ ++ if (ctx->has_scaling_matrix) { ++ control[count++] = (struct v4l2_ext_control) { ++ .id = V4L2_CID_STATELESS_HEVC_SCALING_MATRIX, ++ .ptr = &controls->scaling_matrix, ++ .size = sizeof(controls->scaling_matrix), ++ }; ++ } ++ ++ if (ctx->max_slice_params && controls->num_slice_params) { ++ control[count++] = (struct v4l2_ext_control) { ++ .id = V4L2_CID_STATELESS_HEVC_SLICE_PARAMS, ++ .ptr = controls->frame_slice_params, ++ .size = sizeof(*controls->frame_slice_params) * ++ FFMIN(controls->num_slice_params, ctx->max_slice_params), ++ }; ++ } ++ ++ if (ctx->max_entry_point_offsets && controls->num_entry_point_offsets) { ++ control[count++] = (struct v4l2_ext_control) { ++ .id = V4L2_CID_STATELESS_HEVC_ENTRY_POINT_OFFSETS, ++ .ptr = controls->entry_point_offsets, ++ .size = sizeof(*controls->entry_point_offsets) * ++ FFMIN(controls->num_entry_point_offsets, ++ ctx->max_entry_point_offsets), ++ }; ++ } ++ ++ if (ctx->decode_mode == V4L2_STATELESS_HEVC_DECODE_MODE_SLICE_BASED) ++ return ff_v4l2_request_decode_slice(avctx, &controls->pic, control, count, ++ controls->first_slice, last_slice); ++ ++ return ff_v4l2_request_decode_frame(avctx, &controls->pic, control, count); ++} ++ ++static int v4l2_request_hevc_decode_slice(AVCodecContext *avctx, ++ const uint8_t *buffer, uint32_t size) ++{ ++ const HEVCContext *h = avctx->priv_data; ++ V4L2RequestContextHEVC *ctx = avctx->internal->hwaccel_priv_data; ++ V4L2RequestControlsHEVC *controls = h->cur_frame->hwaccel_picture_private; ++ const SliceHeader *sh = &h->sh; ++ int ret, slice = controls->num_slice_params; ++ uint32_t extra_size = 0; ++ ++ if (ctx->decode_mode == V4L2_STATELESS_HEVC_DECODE_MODE_SLICE_BASED && ++ (slice >= ctx->max_slice_params || (ctx->max_entry_point_offsets && ++ (controls->num_entry_point_offsets + sh->num_entry_point_offsets > ctx->max_entry_point_offsets)))) { ++ ret = v4l2_request_hevc_queue_decode(avctx, false); ++ if (ret) ++ return ret; ++ ++ ff_v4l2_request_reset_picture(avctx, &controls->pic); ++ slice = controls->num_slice_params = 0; ++ controls->num_entry_point_offsets = 0; ++ controls->first_slice = false; ++ } ++ ++ if (ctx->start_code == V4L2_STATELESS_HEVC_START_CODE_ANNEX_B) { ++ ret = ff_v4l2_request_append_output(avctx, &controls->pic, ++ nalu_slice_start_code, 3); ++ if (ret) ++ return ret; ++ extra_size = 3; ++ } ++ ++ if (ctx->max_slice_params) { ++ if (slice && controls->allocated_slice_params < slice + 1) { ++ void *slice_params = controls->allocated_slice_params == 0 ? NULL : controls->frame_slice_params; ++ int slices = controls->allocated_slice_params == 0 ? 8 : controls->allocated_slice_params * 2; ++ slice_params = av_realloc_array(slice_params, slices, sizeof(*controls->frame_slice_params)); ++ if (!slice_params) ++ return AVERROR(ENOMEM); ++ if (controls->allocated_slice_params == 0) ++ memcpy(slice_params, controls->frame_slice_params, sizeof(*controls->frame_slice_params)); ++ controls->frame_slice_params = slice_params; ++ controls->allocated_slice_params = slices; ++ } ++ ++ ret = fill_slice_params(controls, slice, !!ctx->max_entry_point_offsets, h); ++ if (ret) ++ return ret; ++ } ++ ++ ret = ff_v4l2_request_append_output(avctx, &controls->pic, buffer, size); ++ if (ret) ++ return ret; ++ ++ if (ctx->max_slice_params) ++ controls->frame_slice_params[slice].bit_size = (size + extra_size) * 8; ++ ++ controls->num_slice_params++; ++ return 0; ++} ++ ++static int v4l2_request_hevc_end_frame(AVCodecContext *avctx) ++{ ++ return v4l2_request_hevc_queue_decode(avctx, true); ++} ++ ++static void v4l2_request_hevc_free_frame_priv(FFRefStructOpaque hwctx, void *data) ++{ ++ V4L2RequestControlsHEVC *controls = data; ++ ++ if (controls->allocated_slice_params) ++ av_freep(&controls->frame_slice_params); ++ ++ av_freep(&controls->entry_point_offsets); ++} ++ ++static int v4l2_request_hevc_post_probe(AVCodecContext *avctx) ++{ ++ V4L2RequestContextHEVC *ctx = avctx->internal->hwaccel_priv_data; ++ int ret; ++ ++ struct v4l2_ext_control control[] = { ++ { .id = V4L2_CID_STATELESS_HEVC_DECODE_MODE, }, ++ { .id = V4L2_CID_STATELESS_HEVC_START_CODE, }, ++ }; ++ struct v4l2_query_ext_ctrl scaling_matrix = { ++ .id = V4L2_CID_STATELESS_HEVC_SCALING_MATRIX, ++ }; ++ struct v4l2_query_ext_ctrl entry_point_offsets = { ++ .id = V4L2_CID_STATELESS_HEVC_ENTRY_POINT_OFFSETS, ++ }; ++ struct v4l2_query_ext_ctrl slice_params = { ++ .id = V4L2_CID_STATELESS_HEVC_SLICE_PARAMS, ++ }; ++ ++ ctx->decode_mode = ff_v4l2_request_query_control_default_value(avctx, ++ V4L2_CID_STATELESS_HEVC_DECODE_MODE); ++ if (ctx->decode_mode != V4L2_STATELESS_HEVC_DECODE_MODE_SLICE_BASED && ++ ctx->decode_mode != V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED) { ++ av_log(ctx, AV_LOG_VERBOSE, "Unsupported decode mode: %d\n", ++ ctx->decode_mode); ++ return AVERROR(EINVAL); ++ } ++ ++ ctx->start_code = ff_v4l2_request_query_control_default_value(avctx, ++ V4L2_CID_STATELESS_HEVC_START_CODE); ++ if (ctx->start_code != V4L2_STATELESS_HEVC_START_CODE_NONE && ++ ctx->start_code != V4L2_STATELESS_HEVC_START_CODE_ANNEX_B) { ++ av_log(ctx, AV_LOG_VERBOSE, "Unsupported start code: %d\n", ++ ctx->start_code); ++ return AVERROR(EINVAL); ++ } ++ ++ // TODO: check V4L2_CID_MPEG_VIDEO_HEVC_PROFILE control ++ // TODO: check V4L2_CID_MPEG_VIDEO_HEVC_LEVEL control ++ ++ ret = ff_v4l2_request_query_control(avctx, &scaling_matrix); ++ if (!ret) ++ ctx->has_scaling_matrix = true; ++ else ++ ctx->has_scaling_matrix = false; ++ ++ ret = ff_v4l2_request_query_control(avctx, &entry_point_offsets); ++ if (!ret) ++ ctx->max_entry_point_offsets = FFMAX(entry_point_offsets.dims[0], 1); ++ else ++ ctx->max_entry_point_offsets = 0; ++ ++ ret = ff_v4l2_request_query_control(avctx, &slice_params); ++ if (!ret) ++ ctx->max_slice_params = FFMAX(slice_params.dims[0], 1); ++ else ++ ctx->max_slice_params = 0; ++ ++ av_log(ctx, AV_LOG_VERBOSE, "%s-based decoder with SLICE_PARAMS=%u, " ++ "ENTRY_POINT_OFFSETS=%u and SCALING_MATRIX=%d controls\n", ++ ctx->decode_mode == V4L2_STATELESS_HEVC_DECODE_MODE_SLICE_BASED ? "slice" : "frame", ++ ctx->max_slice_params, ctx->max_entry_point_offsets, ctx->has_scaling_matrix); ++ ++ 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) ++{ ++ V4L2RequestContextHEVC *ctx = avctx->internal->hwaccel_priv_data; ++ const HEVCContext *h = avctx->priv_data; ++ struct v4l2_ctrl_hevc_sps sps; ++ ++ struct v4l2_ext_control control[] = { ++ { ++ .id = V4L2_CID_STATELESS_HEVC_SPS, ++ .ptr = &sps, ++ .size = sizeof(sps), ++ }, ++ }; ++ ++ fill_sps(&sps, h); ++ ++ ctx->base.post_probe = v4l2_request_hevc_post_probe; ++ return ff_v4l2_request_init(avctx, V4L2_PIX_FMT_HEVC_SLICE, ++ 4 * 1024 * 1024, ++ control, FF_ARRAY_ELEMS(control)); ++} ++ ++const FFHWAccel ff_hevc_v4l2request_hwaccel = { ++ .p.name = "hevc_v4l2request", ++ .p.type = AVMEDIA_TYPE_VIDEO, ++ .p.id = AV_CODEC_ID_HEVC, ++ .p.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, ++ .flush = ff_v4l2_request_flush, ++ .free_frame_priv = v4l2_request_hevc_free_frame_priv, ++ .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, ++}; + +From 63716a8632a02eb3c9d7715a5dd0bf99d4296d48 Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Wed, 22 May 2019 14:46:58 +0200 +Subject: [PATCH 09/11] avcodec: Add V4L2 Request API vp8 hwaccel + +Add a V4L2 Request API hwaccel for VP8. + +Co-developed-by: Ezequiel Garcia +Signed-off-by: Ezequiel Garcia +Signed-off-by: Boris Brezillon +Co-developed-by: Jonas Karlman +Signed-off-by: Jonas Karlman +--- + configure | 3 + + libavcodec/Makefile | 1 + + libavcodec/hwaccels.h | 1 + + libavcodec/v4l2_request_vp8.c | 235 ++++++++++++++++++++++++++++++++++ + libavcodec/vp8.c | 6 + + 5 files changed, 246 insertions(+) + create mode 100644 libavcodec/v4l2_request_vp8.c + +diff --git a/configure b/configure +index 7a2901d960..3b1288eb98 100755 +--- a/configure ++++ b/configure +@@ -3271,6 +3271,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" +@@ -7213,6 +7215,7 @@ if enabled v4l2_request; then + check_cc hevc_v4l2_request linux/videodev2.h "int i = V4L2_CID_STATELESS_HEVC_SPS" + check_cc mpeg2_v4l2_request linux/videodev2.h "int i = V4L2_CID_STATELESS_MPEG2_SEQUENCE" + check_cc v4l2_m2m_hold_capture_buf linux/videodev2.h "int i = V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF" ++ check_cc vp8_v4l2_request linux/videodev2.h "int i = V4L2_CID_STATELESS_VP8_FRAME" + check_func_headers "linux/media.h linux/videodev2.h" v4l2_timeval_to_ns + check_pkg_config libudev libudev libudev.h udev_new + check_struct linux/videodev2.h "struct v4l2_ctrl_hevc_decode_params" num_delta_pocs_of_ref_rps_idx +diff --git a/libavcodec/Makefile b/libavcodec/Makefile +index fa78523b76..3fa9822594 100644 +--- a/libavcodec/Makefile ++++ b/libavcodec/Makefile +@@ -1057,6 +1057,7 @@ OBJS-$(CONFIG_VC1_QSV_HWACCEL) += qsvdec.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 ad145fc07c..cb2cdb3893 100644 +--- a/libavcodec/hwaccels.h ++++ b/libavcodec/hwaccels.h +@@ -76,6 +76,7 @@ extern const struct FFHWAccel ff_vc1_nvdec_hwaccel; + extern const struct FFHWAccel ff_vc1_vaapi_hwaccel; + extern const struct FFHWAccel ff_vc1_vdpau_hwaccel; + extern const struct FFHWAccel ff_vp8_nvdec_hwaccel; ++extern const struct FFHWAccel ff_vp8_v4l2request_hwaccel; + extern const struct FFHWAccel ff_vp8_vaapi_hwaccel; + extern const struct FFHWAccel ff_vp9_d3d11va_hwaccel; + extern const struct FFHWAccel ff_vp9_d3d11va2_hwaccel; +diff --git a/libavcodec/v4l2_request_vp8.c b/libavcodec/v4l2_request_vp8.c +new file mode 100644 +index 0000000000..551b6dc75f +--- /dev/null ++++ b/libavcodec/v4l2_request_vp8.c +@@ -0,0 +1,235 @@ ++/* ++ * 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 "hwaccel_internal.h" ++#include "hwconfig.h" ++#include "v4l2_request.h" ++#include "vp8.h" ++ ++typedef struct V4L2RequestControlsVP8 { ++ V4L2RequestPictureContext pic; ++ struct v4l2_ctrl_vp8_frame frame; ++} V4L2RequestControlsVP8; ++ ++static int v4l2_request_vp8_start_frame(AVCodecContext *avctx, ++ const uint8_t *buffer, ++ av_unused uint32_t size) ++{ ++ const VP8Context *s = avctx->priv_data; ++ V4L2RequestControlsVP8 *controls = s->framep[VP8_FRAME_CURRENT]->hwaccel_picture_private; ++ struct v4l2_ctrl_vp8_frame *ctrl = &controls->frame; ++ unsigned int header_size = 3 + 7 * s->keyframe; ++ const uint8_t *data = buffer + header_size; ++ int ret, i, j, k; ++ ++ ret = ff_v4l2_request_start_frame(avctx, &controls->pic, ++ s->framep[VP8_FRAME_CURRENT]->tf.f); ++ if (ret) ++ return ret; ++ ++ *ctrl = (struct v4l2_ctrl_vp8_frame) { ++ .lf = { ++ .sharpness_level = s->filter.sharpness, ++ .level = s->filter.level, ++ }, ++ ++ .quant = { ++ .y_ac_qi = s->quant.yac_qi, ++ .y_dc_delta = s->quant.ydc_delta, ++ .y2_dc_delta = s->quant.y2dc_delta, ++ .y2_ac_delta = s->quant.y2ac_delta, ++ .uv_dc_delta = s->quant.uvdc_delta, ++ .uv_ac_delta = s->quant.uvac_delta, ++ }, ++ ++ .coder_state = { ++ .range = s->coder_state_at_header_end.range, ++ .value = s->coder_state_at_header_end.value, ++ .bit_count = s->coder_state_at_header_end.bit_count, ++ }, ++ ++ .width = avctx->width, ++ .height = avctx->height, ++ ++ .horizontal_scale = 0, /* scale not supported by FFmpeg */ ++ .vertical_scale = 0, /* scale not supported by FFmpeg */ ++ ++ .version = s->profile & 0x3, ++ .prob_skip_false = s->prob->mbskip, ++ .prob_intra = s->prob->intra, ++ .prob_last = s->prob->last, ++ .prob_gf = s->prob->golden, ++ .num_dct_parts = s->num_coeff_partitions, ++ ++ .first_part_size = s->header_partition_size, ++ .first_part_header_bits = (8 * (s->coder_state_at_header_end.input - data) - ++ s->coder_state_at_header_end.bit_count - 8), ++ }; ++ ++ for (i = 0; i < 4; i++) { ++ ctrl->segment.quant_update[i] = s->segmentation.base_quant[i]; ++ ctrl->segment.lf_update[i] = s->segmentation.filter_level[i]; ++ } ++ ++ for (i = 0; i < 3; i++) ++ ctrl->segment.segment_probs[i] = s->prob->segmentid[i]; ++ ++ if (s->segmentation.enabled) ++ ctrl->segment.flags |= V4L2_VP8_SEGMENT_FLAG_ENABLED; ++ ++ if (s->segmentation.update_map) ++ ctrl->segment.flags |= V4L2_VP8_SEGMENT_FLAG_UPDATE_MAP; ++ ++ if (s->segmentation.update_feature_data) ++ ctrl->segment.flags |= V4L2_VP8_SEGMENT_FLAG_UPDATE_FEATURE_DATA; ++ ++ if (!s->segmentation.absolute_vals) ++ ctrl->segment.flags |= V4L2_VP8_SEGMENT_FLAG_DELTA_VALUE_MODE; ++ ++ for (i = 0; i < 4; i++) { ++ ctrl->lf.ref_frm_delta[i] = s->lf_delta.ref[i]; ++ ctrl->lf.mb_mode_delta[i] = s->lf_delta.mode[i + MODE_I4x4]; ++ } ++ ++ if (s->lf_delta.enabled) ++ ctrl->lf.flags |= V4L2_VP8_LF_ADJ_ENABLE; ++ ++ if (s->lf_delta.update) ++ ctrl->lf.flags |= V4L2_VP8_LF_DELTA_UPDATE; ++ ++ if (s->filter.simple) ++ ctrl->lf.flags |= V4L2_VP8_LF_FILTER_TYPE_SIMPLE; ++ ++ 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(ctrl->entropy.y_mode_probs, keyframe_y_mode_probs, 4); ++ memcpy(ctrl->entropy.uv_mode_probs, keyframe_uv_mode_probs, 3); ++ } else { ++ for (i = 0; i < 4; i++) ++ ctrl->entropy.y_mode_probs[i] = s->prob->pred16x16[i]; ++ for (i = 0; i < 3; i++) ++ ctrl->entropy.uv_mode_probs[i] = s->prob->pred8x8c[i]; ++ } ++ for (i = 0; i < 2; i++) ++ for (j = 0; j < 19; j++) ++ ctrl->entropy.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(ctrl->entropy.coeff_probs[i][j][k], ++ s->prob->token[i][coeff_pos][k], 11); ++ } ++ } ++ } ++ ++ for (i = 0; i < 8; i++) ++ ctrl->dct_part_sizes[i] = s->coeff_partition_size[i]; ++ ++ if (s->framep[VP8_FRAME_PREVIOUS]) ++ ctrl->last_frame_ts = ++ ff_v4l2_request_get_capture_timestamp(s->framep[VP8_FRAME_PREVIOUS]->tf.f); ++ if (s->framep[VP8_FRAME_GOLDEN]) ++ ctrl->golden_frame_ts = ++ ff_v4l2_request_get_capture_timestamp(s->framep[VP8_FRAME_GOLDEN]->tf.f); ++ if (s->framep[VP8_FRAME_ALTREF]) ++ ctrl->alt_frame_ts = ++ ff_v4l2_request_get_capture_timestamp(s->framep[VP8_FRAME_ALTREF]->tf.f); ++ ++ if (s->keyframe) ++ ctrl->flags |= V4L2_VP8_FRAME_FLAG_KEY_FRAME; ++ ++ if (s->profile & 0x4) ++ ctrl->flags |= V4L2_VP8_FRAME_FLAG_EXPERIMENTAL; ++ ++ if (!s->invisible) ++ ctrl->flags |= V4L2_VP8_FRAME_FLAG_SHOW_FRAME; ++ ++ if (s->mbskip_enabled) ++ ctrl->flags |= V4L2_VP8_FRAME_FLAG_MB_NO_SKIP_COEFF; ++ ++ if (s->sign_bias[VP8_FRAME_GOLDEN]) ++ ctrl->flags |= V4L2_VP8_FRAME_FLAG_SIGN_BIAS_GOLDEN; ++ ++ if (s->sign_bias[VP8_FRAME_ALTREF]) ++ ctrl->flags |= V4L2_VP8_FRAME_FLAG_SIGN_BIAS_ALT; ++ ++ return 0; ++} ++ ++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[VP8_FRAME_CURRENT]->hwaccel_picture_private; ++ ++ return ff_v4l2_request_append_output(avctx, &controls->pic, buffer, size); ++} ++ ++static int v4l2_request_vp8_end_frame(AVCodecContext *avctx) ++{ ++ const VP8Context *s = avctx->priv_data; ++ V4L2RequestControlsVP8 *controls = s->framep[VP8_FRAME_CURRENT]->hwaccel_picture_private; ++ ++ struct v4l2_ext_control control[] = { ++ { ++ .id = V4L2_CID_STATELESS_VP8_FRAME, ++ .ptr = &controls->frame, ++ .size = sizeof(controls->frame), ++ }, ++ }; ++ ++ return ff_v4l2_request_decode_frame(avctx, &controls->pic, ++ control, FF_ARRAY_ELEMS(control)); ++} ++ ++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 FFHWAccel ff_vp8_v4l2request_hwaccel = { ++ .p.name = "vp8_v4l2request", ++ .p.type = AVMEDIA_TYPE_VIDEO, ++ .p.id = AV_CODEC_ID_VP8, ++ .p.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, ++ .flush = ff_v4l2_request_flush, ++ .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, ++}; +diff --git a/libavcodec/vp8.c b/libavcodec/vp8.c +index d6df018655..04b16cc2e3 100644 +--- a/libavcodec/vp8.c ++++ b/libavcodec/vp8.c +@@ -184,6 +184,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, +@@ -2980,6 +2983,9 @@ const FFCodec ff_vp8_decoder = { + #endif + #if CONFIG_VP8_NVDEC_HWACCEL + HWACCEL_NVDEC(vp8), ++#endif ++#if CONFIG_VP8_V4L2REQUEST_HWACCEL ++ HWACCEL_V4L2REQUEST(vp8), + #endif + NULL + }, + +From 96c22879bbbfcbd57cd73a165ab6b1fb49663481 Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Thu, 12 Dec 2019 16:13:55 +0100 +Subject: [PATCH 10/11] avcodec: Add V4L2 Request API vp9 hwaccel + +FIXME: split patch + +Signed-off-by: Boris Brezillon +Co-developed-by: Jernej Skrabec +Signed-off-by: Jernej Skrabec +Co-developed-by: Jonas Karlman +Signed-off-by: Jonas Karlman +--- + configure | 3 + + libavcodec/Makefile | 1 + + libavcodec/hwaccels.h | 1 + + libavcodec/v4l2_request_vp9.c | 288 ++++++++++++++++++++++++++++++++++ + libavcodec/vp9.c | 187 +++++++++++++++------- + libavcodec/vp9dec.h | 4 + + libavcodec/vp9shared.h | 1 + + 7 files changed, 431 insertions(+), 54 deletions(-) + create mode 100644 libavcodec/v4l2_request_vp9.c + +diff --git a/configure b/configure +index 3b1288eb98..2904b67ef7 100755 +--- a/configure ++++ b/configure +@@ -3285,6 +3285,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" +@@ -7216,6 +7218,7 @@ if enabled v4l2_request; then + check_cc mpeg2_v4l2_request linux/videodev2.h "int i = V4L2_CID_STATELESS_MPEG2_SEQUENCE" + check_cc v4l2_m2m_hold_capture_buf linux/videodev2.h "int i = V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF" + check_cc vp8_v4l2_request linux/videodev2.h "int i = V4L2_CID_STATELESS_VP8_FRAME" ++ check_cc vp9_v4l2_request linux/videodev2.h "int i = V4L2_CID_STATELESS_VP9_FRAME" + check_func_headers "linux/media.h linux/videodev2.h" v4l2_timeval_to_ns + check_pkg_config libudev libudev libudev.h udev_new + check_struct linux/videodev2.h "struct v4l2_ctrl_hevc_decode_params" num_delta_pocs_of_ref_rps_idx +diff --git a/libavcodec/Makefile b/libavcodec/Makefile +index 3fa9822594..95c77d7bec 100644 +--- a/libavcodec/Makefile ++++ b/libavcodec/Makefile +@@ -1063,6 +1063,7 @@ OBJS-$(CONFIG_VP9_D3D11VA_HWACCEL) += dxva2_vp9.o + OBJS-$(CONFIG_VP9_DXVA2_HWACCEL) += dxva2_vp9.o + OBJS-$(CONFIG_VP9_D3D12VA_HWACCEL) += dxva2_vp9.o d3d12va_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_VP9_VIDEOTOOLBOX_HWACCEL) += videotoolbox_vp9.o +diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h +index cb2cdb3893..8571cc7e8b 100644 +--- a/libavcodec/hwaccels.h ++++ b/libavcodec/hwaccels.h +@@ -83,6 +83,7 @@ extern const struct FFHWAccel ff_vp9_d3d11va2_hwaccel; + extern const struct FFHWAccel ff_vp9_d3d12va_hwaccel; + extern const struct FFHWAccel ff_vp9_dxva2_hwaccel; + extern const struct FFHWAccel ff_vp9_nvdec_hwaccel; ++extern const struct FFHWAccel ff_vp9_v4l2request_hwaccel; + extern const struct FFHWAccel ff_vp9_vaapi_hwaccel; + extern const struct FFHWAccel ff_vp9_vdpau_hwaccel; + extern const struct FFHWAccel ff_vp9_videotoolbox_hwaccel; +diff --git a/libavcodec/v4l2_request_vp9.c b/libavcodec/v4l2_request_vp9.c +new file mode 100644 +index 0000000000..41ea4e37f5 +--- /dev/null ++++ b/libavcodec/v4l2_request_vp9.c +@@ -0,0 +1,288 @@ ++/* ++ * 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 "hwaccel_internal.h" ++#include "hwconfig.h" ++#include "v4l2_request.h" ++#include "vp9dec.h" ++ ++typedef struct V4L2RequestControlsVP9 { ++ V4L2RequestPictureContext pic; ++ struct v4l2_ctrl_vp9_frame frame; ++ struct v4l2_ctrl_vp9_compressed_hdr chp; ++} V4L2RequestControlsVP9; ++ ++static void v4l2_request_vp9_set_frame_ctx(AVCodecContext *avctx) ++{ ++ VP9Context *s = avctx->priv_data; ++ const VP9Frame *f = &s->s.frames[CUR_FRAME]; ++ V4L2RequestControlsVP9 *controls = f->hwaccel_picture_private; ++ struct v4l2_ctrl_vp9_compressed_hdr *chp = &controls->chp; ++ ++ memset(chp, 0, sizeof(&chp)); ++ ++ chp->tx_mode = s->s.h.txfmmode; ++ memcpy(chp->tx8, s->prob_raw.p.tx8p, sizeof(s->prob_raw.p.tx8p)); ++ memcpy(chp->tx16, s->prob_raw.p.tx16p, sizeof(s->prob_raw.p.tx16p)); ++ memcpy(chp->tx32, s->prob_raw.p.tx32p, sizeof(s->prob_raw.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(chp->coef[i][j][k][l][m], s->prob_raw.coef[i][j][k][l][m], sizeof(chp->coef[0][0][0][0][0])); ++ } ++ } ++ } ++ } ++ } ++ memcpy(chp->skip, s->prob_raw.p.skip, sizeof(s->prob_raw.p.skip)); ++ memcpy(chp->inter_mode, s->prob_raw.p.mv_mode, sizeof(s->prob_raw.p.mv_mode)); ++ memcpy(chp->interp_filter, s->prob_raw.p.filter, sizeof(s->prob_raw.p.filter)); ++ memcpy(chp->is_inter, s->prob_raw.p.intra, sizeof(s->prob_raw.p.intra)); ++ memcpy(chp->comp_mode, s->prob_raw.p.comp, sizeof(s->prob_raw.p.comp)); ++ memcpy(chp->single_ref, s->prob_raw.p.single_ref, sizeof(s->prob_raw.p.single_ref)); ++ memcpy(chp->comp_ref, s->prob_raw.p.comp_ref, sizeof(s->prob_raw.p.comp_ref)); ++ memcpy(chp->y_mode, s->prob_raw.p.y_mode, sizeof(s->prob_raw.p.y_mode)); ++ for (unsigned i = 0; i < 10; i++) ++ memcpy(chp->uv_mode[i], s->prob.p.uv_mode[i], sizeof(s->prob.p.uv_mode[0])); ++ for (unsigned i = 0; i < 4; i++) ++ memcpy(chp->partition[i * 4], s->prob_raw.p.partition[i], sizeof(s->prob_raw.p.partition[0])); ++ memcpy(chp->mv.joint, s->prob_raw.p.mv_joint, sizeof(s->prob_raw.p.mv_joint)); ++ for (unsigned i = 0; i < 2; i++) { ++ chp->mv.sign[i] = s->prob_raw.p.mv_comp[i].sign; ++ memcpy(chp->mv.classes[i], s->prob_raw.p.mv_comp[i].classes, sizeof(s->prob_raw.p.mv_comp[0].classes)); ++ chp->mv.class0_bit[i] = s->prob_raw.p.mv_comp[i].class0; ++ memcpy(chp->mv.bits[i], s->prob_raw.p.mv_comp[i].bits, sizeof(s->prob_raw.p.mv_comp[0].bits)); ++ memcpy(chp->mv.class0_fr[i], s->prob_raw.p.mv_comp[i].class0_fp, sizeof(s->prob_raw.p.mv_comp[0].class0_fp)); ++ memcpy(chp->mv.fr[i], s->prob_raw.p.mv_comp[i].fp, sizeof(s->prob_raw.p.mv_comp[0].fp)); ++ chp->mv.class0_hp[i] = s->prob_raw.p.mv_comp[i].class0_hp; ++ chp->mv.hp[i] = s->prob_raw.p.mv_comp[i].hp; ++ } ++} ++ ++static void fill_frame(struct v4l2_ctrl_vp9_frame *dec_params, AVCodecContext *avctx) ++{ ++ const VP9Context *s = avctx->priv_data; ++ AVFrame *ref; ++ ++ memset(dec_params, 0, sizeof(*dec_params)); ++ ++ 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->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; ++ ++ ref = s->s.refs[s->s.h.refidx[0]].f; ++ if (ref && ref->buf[0]) ++ dec_params->last_frame_ts = ff_v4l2_request_get_capture_timestamp(ref); ++ ref = s->s.refs[s->s.h.refidx[1]].f; ++ if (ref && ref->buf[0]) ++ dec_params->golden_frame_ts = ff_v4l2_request_get_capture_timestamp(ref); ++ ref = s->s.refs[s->s.h.refidx[2]].f; ++ if (ref && ref->buf[0]) ++ dec_params->alt_frame_ts = ff_v4l2_request_get_capture_timestamp(ref); ++ ++ if (s->s.h.signbias[0]) ++ dec_params->ref_frame_sign_bias |= V4L2_VP9_SIGN_BIAS_LAST; ++ if (s->s.h.signbias[1]) ++ dec_params->ref_frame_sign_bias |= V4L2_VP9_SIGN_BIAS_GOLDEN; ++ if (s->s.h.signbias[2]) ++ dec_params->ref_frame_sign_bias |= V4L2_VP9_SIGN_BIAS_ALT; ++ ++ 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]; ++ ++ 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_SEG_LVL_ALT_Q; ++ dec_params->seg.feature_data[i][V4L2_VP9_SEG_LVL_ALT_Q] = 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_SEG_LVL_ALT_L; ++ dec_params->seg.feature_data[i][V4L2_VP9_SEG_LVL_ALT_L] = 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_SEG_LVL_REF_FRAME; ++ dec_params->seg.feature_data[i][V4L2_VP9_SEG_LVL_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_SEG_LVL_SKIP; ++ } ++} ++ ++static int v4l2_request_vp9_start_frame(AVCodecContext *avctx, ++ av_unused const uint8_t *buffer, ++ av_unused uint32_t size) ++{ ++ const VP9SharedContext *h = avctx->priv_data; ++ const VP9Frame *f = &h->frames[CUR_FRAME]; ++ V4L2RequestControlsVP9 *controls = f->hwaccel_picture_private; ++ int ret; ++ ++ ret = ff_v4l2_request_start_frame(avctx, &controls->pic, f->tf.f); ++ if (ret) ++ return ret; ++ ++ v4l2_request_vp9_set_frame_ctx(avctx); ++ ++ fill_frame(&controls->frame, avctx); ++ ++ return 0; ++} ++ ++static int v4l2_request_vp9_decode_slice(AVCodecContext *avctx, ++ const uint8_t *buffer, uint32_t size) ++{ ++ const VP9SharedContext *h = avctx->priv_data; ++ V4L2RequestControlsVP9 *controls = h->frames[CUR_FRAME].hwaccel_picture_private; ++ ++ return ff_v4l2_request_append_output(avctx, &controls->pic, buffer, size); ++} ++ ++static int v4l2_request_vp9_end_frame(AVCodecContext *avctx) ++{ ++ const VP9SharedContext *h = avctx->priv_data; ++ V4L2RequestControlsVP9 *controls = h->frames[CUR_FRAME].hwaccel_picture_private; ++ ++ struct v4l2_ext_control control[] = { ++ { ++ .id = V4L2_CID_STATELESS_VP9_FRAME, ++ .ptr = &controls->frame, ++ .size = sizeof(controls->frame), ++ }, ++ { ++ .id = V4L2_CID_STATELESS_VP9_COMPRESSED_HDR, ++ .ptr = &controls->chp, ++ .size = sizeof(controls->chp), ++ }, ++ }; ++ ++ return ff_v4l2_request_decode_frame(avctx, &controls->pic, ++ control, FF_ARRAY_ELEMS(control)); ++} ++ ++static int v4l2_request_vp9_init(AVCodecContext *avctx) ++{ ++ struct v4l2_ctrl_vp9_frame frame; ++ ++ struct v4l2_ext_control control[] = { ++ { ++ .id = V4L2_CID_STATELESS_VP9_FRAME, ++ .ptr = &frame, ++ .size = sizeof(frame), ++ }, ++ }; ++ ++ fill_frame(&frame, avctx); ++ ++ // TODO: check V4L2_CID_MPEG_VIDEO_VP9_PROFILE ++ // TODO: check V4L2_CID_MPEG_VIDEO_VP9_LEVEL ++ ++ return ff_v4l2_request_init(avctx, V4L2_PIX_FMT_VP9_FRAME, ++ 3 * 1024 * 1024, ++ control, FF_ARRAY_ELEMS(control)); ++} ++ ++const FFHWAccel ff_vp9_v4l2request_hwaccel = { ++ .p.name = "vp9_v4l2request", ++ .p.type = AVMEDIA_TYPE_VIDEO, ++ .p.id = AV_CODEC_ID_VP9, ++ .p.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, ++ .flush = ff_v4l2_request_flush, ++ .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, ++}; +diff --git a/libavcodec/vp9.c b/libavcodec/vp9.c +index 8ede2e2eb3..17b611bfdd 100644 +--- a/libavcodec/vp9.c ++++ b/libavcodec/vp9.c +@@ -163,6 +163,7 @@ static int update_size(AVCodecContext *avctx, int w, int h) + CONFIG_VP9_D3D11VA_HWACCEL * 2 + \ + CONFIG_VP9_D3D12VA_HWACCEL + \ + CONFIG_VP9_NVDEC_HWACCEL + \ ++ CONFIG_VP9_V4L2REQUEST_HWACCEL + \ + CONFIG_VP9_VAAPI_HWACCEL + \ + CONFIG_VP9_VDPAU_HWACCEL + \ + CONFIG_VP9_VIDEOTOOLBOX_HWACCEL) +@@ -202,6 +203,9 @@ static int update_size(AVCodecContext *avctx, int w, int h) + #endif + #if CONFIG_VP9_VIDEOTOOLBOX_HWACCEL + *fmtp++ = AV_PIX_FMT_VIDEOTOOLBOX; ++#endif ++#if CONFIG_VP9_V4L2REQUEST_HWACCEL ++ *fmtp++ = AV_PIX_FMT_DRM_PRIME; + #endif + break; + case AV_PIX_FMT_YUV420P12: +@@ -375,7 +379,7 @@ static av_always_inline int inv_recenter_nonneg(int v, int m) + } + + // differential forward probability updates +-static int update_prob(VPXRangeCoder *c, int p) ++static int read_prob_delta(VPXRangeCoder *c) + { + static const uint8_t inv_map_table[255] = { + 7, 20, 33, 46, 59, 72, 85, 98, 111, 124, 137, 150, 163, 176, +@@ -429,8 +433,13 @@ static int update_prob(VPXRangeCoder *c, int p) + av_assert2(d < FF_ARRAY_ELEMS(inv_map_table)); + } + +- return p <= 128 ? 1 + inv_recenter_nonneg(inv_map_table[d], p - 1) : +- 255 - inv_recenter_nonneg(inv_map_table[d], 255 - p); ++ return inv_map_table[d]; ++} ++ ++static int update_prob(int p, int d) ++{ ++ return p <= 128 ? 1 + inv_recenter_nonneg(d, p - 1) : ++ 255 - inv_recenter_nonneg(d, 255 - p); + } + + static int read_colorspace_details(AVCodecContext *avctx) +@@ -697,7 +706,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))) +@@ -903,6 +913,8 @@ static int decode_frame_header(AVCodecContext *avctx, + * as explicit copies if the fw update is missing (and skip the copy upon + * fw update)? */ + s->prob.p = s->prob_ctx[c].p; ++ memset(&s->prob_raw.p, 0, sizeof(s->prob_raw.p)); ++ memset(&s->prob_raw.coef, 0, sizeof(s->prob_raw.coef)); + + // txfm updates + if (s->s.h.lossless) { +@@ -914,18 +926,25 @@ static int decode_frame_header(AVCodecContext *avctx, + + if (s->s.h.txfmmode == TX_SWITCHABLE) { + for (i = 0; i < 2; i++) +- if (vpx_rac_get_prob_branchy(&s->c, 252)) +- s->prob.p.tx8p[i] = update_prob(&s->c, s->prob.p.tx8p[i]); ++ if (vpx_rac_get_prob_branchy(&s->c, 252)) { ++ s->prob_raw.p.tx8p[i] = read_prob_delta(&s->c); ++ s->prob.p.tx8p[i] = update_prob(s->prob.p.tx8p[i], ++ s->prob_raw.p.tx8p[i]); ++ } + for (i = 0; i < 2; i++) + for (j = 0; j < 2; j++) +- if (vpx_rac_get_prob_branchy(&s->c, 252)) +- s->prob.p.tx16p[i][j] = +- update_prob(&s->c, s->prob.p.tx16p[i][j]); ++ if (vpx_rac_get_prob_branchy(&s->c, 252)) { ++ s->prob_raw.p.tx16p[i][j] = read_prob_delta(&s->c); ++ s->prob.p.tx16p[i][j] = update_prob(s->prob.p.tx16p[i][j], ++ s->prob_raw.p.tx16p[i][j]); ++ } + for (i = 0; i < 2; i++) + for (j = 0; j < 3; j++) +- if (vpx_rac_get_prob_branchy(&s->c, 252)) +- s->prob.p.tx32p[i][j] = +- update_prob(&s->c, s->prob.p.tx32p[i][j]); ++ if (vpx_rac_get_prob_branchy(&s->c, 252)) { ++ s->prob_raw.p.tx32p[i][j] = read_prob_delta(&s->c); ++ s->prob.p.tx32p[i][j] = update_prob(s->prob.p.tx32p[i][j], ++ s->prob_raw.p.tx32p[i][j]); ++ } + } + } + +@@ -937,15 +956,18 @@ static int decode_frame_header(AVCodecContext *avctx, + for (k = 0; k < 2; k++) + for (l = 0; l < 6; l++) + for (m = 0; m < 6; m++) { ++ uint8_t *pd = s->prob_raw.coef[i][j][k][l][m]; + uint8_t *p = s->prob.coef[i][j][k][l][m]; + uint8_t *r = ref[j][k][l][m]; + if (m >= 3 && l == 0) // dc only has 3 pt + break; + for (n = 0; n < 3; n++) { +- if (vpx_rac_get_prob_branchy(&s->c, 252)) +- p[n] = update_prob(&s->c, r[n]); +- else ++ if (vpx_rac_get_prob_branchy(&s->c, 252)) { ++ pd[n] = read_prob_delta(&s->c); ++ p[n] = update_prob(r[n], pd[n]); ++ } else { + p[n] = r[n]; ++ } + } + memcpy(&p[3], ff_vp9_model_pareto8[p[2]], 8); + } +@@ -968,25 +990,37 @@ static int decode_frame_header(AVCodecContext *avctx, + + // mode updates + for (i = 0; i < 3; i++) +- if (vpx_rac_get_prob_branchy(&s->c, 252)) +- s->prob.p.skip[i] = update_prob(&s->c, s->prob.p.skip[i]); ++ if (vpx_rac_get_prob_branchy(&s->c, 252)) { ++ s->prob_raw.p.skip[i] = read_prob_delta(&s->c); ++ s->prob.p.skip[i] = update_prob(s->prob.p.skip[i], ++ s->prob_raw.p.skip[i]); ++ } + if (!s->s.h.keyframe && !s->s.h.intraonly) { + for (i = 0; i < 7; i++) + for (j = 0; j < 3; j++) +- if (vpx_rac_get_prob_branchy(&s->c, 252)) ++ if (vpx_rac_get_prob_branchy(&s->c, 252)) { ++ s->prob_raw.p.mv_mode[i][j] = read_prob_delta(&s->c); + s->prob.p.mv_mode[i][j] = +- update_prob(&s->c, s->prob.p.mv_mode[i][j]); ++ update_prob(s->prob.p.mv_mode[i][j], ++ s->prob_raw.p.mv_mode[i][j]); ++ } + + if (s->s.h.filtermode == FILTER_SWITCHABLE) + for (i = 0; i < 4; i++) + for (j = 0; j < 2; j++) +- if (vpx_rac_get_prob_branchy(&s->c, 252)) ++ if (vpx_rac_get_prob_branchy(&s->c, 252)) { ++ s->prob_raw.p.filter[i][j] = read_prob_delta(&s->c); + s->prob.p.filter[i][j] = +- update_prob(&s->c, s->prob.p.filter[i][j]); ++ update_prob(s->prob.p.filter[i][j], ++ s->prob_raw.p.filter[i][j]); ++ } + + for (i = 0; i < 4; i++) +- if (vpx_rac_get_prob_branchy(&s->c, 252)) +- s->prob.p.intra[i] = update_prob(&s->c, s->prob.p.intra[i]); ++ if (vpx_rac_get_prob_branchy(&s->c, 252)) { ++ s->prob_raw.p.intra[i] = read_prob_delta(&s->c); ++ s->prob.p.intra[i] = update_prob(s->prob.p.intra[i], ++ s->prob_raw.p.intra[i]); ++ } + + if (s->s.h.allowcompinter) { + s->s.h.comppredmode = vp89_rac_get(&s->c); +@@ -994,92 +1028,134 @@ static int decode_frame_header(AVCodecContext *avctx, + s->s.h.comppredmode += vp89_rac_get(&s->c); + if (s->s.h.comppredmode == PRED_SWITCHABLE) + for (i = 0; i < 5; i++) +- if (vpx_rac_get_prob_branchy(&s->c, 252)) ++ if (vpx_rac_get_prob_branchy(&s->c, 252)) { ++ s->prob_raw.p.comp[i] = read_prob_delta(&s->c); + s->prob.p.comp[i] = +- update_prob(&s->c, s->prob.p.comp[i]); ++ update_prob(s->prob.p.comp[i], s->prob_raw.p.comp[i]); ++ } + } else { + s->s.h.comppredmode = PRED_SINGLEREF; + } + + if (s->s.h.comppredmode != PRED_COMPREF) { + for (i = 0; i < 5; i++) { +- if (vpx_rac_get_prob_branchy(&s->c, 252)) ++ if (vpx_rac_get_prob_branchy(&s->c, 252)) { ++ s->prob_raw.p.single_ref[i][0] = read_prob_delta(&s->c); + s->prob.p.single_ref[i][0] = +- update_prob(&s->c, s->prob.p.single_ref[i][0]); +- if (vpx_rac_get_prob_branchy(&s->c, 252)) ++ update_prob(s->prob.p.single_ref[i][0], ++ s->prob_raw.p.single_ref[i][0]); ++ } ++ if (vpx_rac_get_prob_branchy(&s->c, 252)) { ++ s->prob_raw.p.single_ref[i][1] = read_prob_delta(&s->c); + s->prob.p.single_ref[i][1] = +- update_prob(&s->c, s->prob.p.single_ref[i][1]); ++ update_prob(s->prob.p.single_ref[i][1], ++ s->prob_raw.p.single_ref[i][1]); ++ } + } + } + + if (s->s.h.comppredmode != PRED_SINGLEREF) { + for (i = 0; i < 5; i++) +- if (vpx_rac_get_prob_branchy(&s->c, 252)) ++ if (vpx_rac_get_prob_branchy(&s->c, 252)) { ++ s->prob_raw.p.comp_ref[i] = read_prob_delta(&s->c); + s->prob.p.comp_ref[i] = +- update_prob(&s->c, s->prob.p.comp_ref[i]); ++ update_prob(s->prob.p.comp_ref[i], ++ s->prob_raw.p.comp_ref[i]); ++ } + } + + for (i = 0; i < 4; i++) + for (j = 0; j < 9; j++) +- if (vpx_rac_get_prob_branchy(&s->c, 252)) ++ if (vpx_rac_get_prob_branchy(&s->c, 252)) { ++ s->prob_raw.p.y_mode[i][j] = read_prob_delta(&s->c); + s->prob.p.y_mode[i][j] = +- update_prob(&s->c, s->prob.p.y_mode[i][j]); ++ update_prob(s->prob.p.y_mode[i][j], ++ s->prob_raw.p.y_mode[i][j]); ++ } + + for (i = 0; i < 4; i++) + for (j = 0; j < 4; j++) + for (k = 0; k < 3; k++) +- if (vpx_rac_get_prob_branchy(&s->c, 252)) ++ if (vpx_rac_get_prob_branchy(&s->c, 252)) { ++ s->prob_raw.p.partition[i][j][k] = read_prob_delta(&s->c); + s->prob.p.partition[3 - i][j][k] = +- update_prob(&s->c, +- s->prob.p.partition[3 - i][j][k]); ++ update_prob(s->prob.p.partition[3 - i][j][k], ++ s->prob_raw.p.partition[i][j][k]); ++ } + + // mv fields don't use the update_prob subexp model for some reason + for (i = 0; i < 3; i++) +- if (vpx_rac_get_prob_branchy(&s->c, 252)) +- s->prob.p.mv_joint[i] = (vp89_rac_get_uint(&s->c, 7) << 1) | 1; ++ if (vpx_rac_get_prob_branchy(&s->c, 252)) { ++ s->prob_raw.p.mv_joint[i] = (vp89_rac_get_uint(&s->c, 7) << 1) | 1; ++ s->prob.p.mv_joint[i] = s->prob_raw.p.mv_joint[i]; ++ } + + for (i = 0; i < 2; i++) { +- if (vpx_rac_get_prob_branchy(&s->c, 252)) +- s->prob.p.mv_comp[i].sign = ++ if (vpx_rac_get_prob_branchy(&s->c, 252)) { ++ s->prob_raw.p.mv_comp[i].sign = + (vp89_rac_get_uint(&s->c, 7) << 1) | 1; ++ s->prob.p.mv_comp[i].sign = ++ s->prob_raw.p.mv_comp[i].sign; ++ } + + for (j = 0; j < 10; j++) +- if (vpx_rac_get_prob_branchy(&s->c, 252)) +- s->prob.p.mv_comp[i].classes[j] = ++ if (vpx_rac_get_prob_branchy(&s->c, 252)) { ++ s->prob_raw.p.mv_comp[i].classes[j] = + (vp89_rac_get_uint(&s->c, 7) << 1) | 1; ++ s->prob.p.mv_comp[i].classes[j] = ++ s->prob_raw.p.mv_comp[i].classes[j]; ++ } + +- if (vpx_rac_get_prob_branchy(&s->c, 252)) +- s->prob.p.mv_comp[i].class0 = ++ if (vpx_rac_get_prob_branchy(&s->c, 252)) { ++ s->prob_raw.p.mv_comp[i].class0 = + (vp89_rac_get_uint(&s->c, 7) << 1) | 1; ++ s->prob.p.mv_comp[i].class0 = ++ s->prob_raw.p.mv_comp[i].class0; ++ } + + for (j = 0; j < 10; j++) +- if (vpx_rac_get_prob_branchy(&s->c, 252)) +- s->prob.p.mv_comp[i].bits[j] = ++ if (vpx_rac_get_prob_branchy(&s->c, 252)) { ++ s->prob_raw.p.mv_comp[i].bits[j] = + (vp89_rac_get_uint(&s->c, 7) << 1) | 1; ++ s->prob.p.mv_comp[i].bits[j] = ++ s->prob_raw.p.mv_comp[i].bits[j]; ++ } + } + + for (i = 0; i < 2; i++) { + for (j = 0; j < 2; j++) + for (k = 0; k < 3; k++) +- if (vpx_rac_get_prob_branchy(&s->c, 252)) +- s->prob.p.mv_comp[i].class0_fp[j][k] = ++ if (vpx_rac_get_prob_branchy(&s->c, 252)) { ++ s->prob_raw.p.mv_comp[i].class0_fp[j][k] = + (vp89_rac_get_uint(&s->c, 7) << 1) | 1; ++ s->prob.p.mv_comp[i].class0_fp[j][k] = ++ s->prob_raw.p.mv_comp[i].class0_fp[j][k]; ++ } + + for (j = 0; j < 3; j++) +- if (vpx_rac_get_prob_branchy(&s->c, 252)) +- s->prob.p.mv_comp[i].fp[j] = ++ if (vpx_rac_get_prob_branchy(&s->c, 252)) { ++ s->prob_raw.p.mv_comp[i].fp[j] = + (vp89_rac_get_uint(&s->c, 7) << 1) | 1; ++ s->prob.p.mv_comp[i].fp[j] = ++ s->prob_raw.p.mv_comp[i].fp[j]; ++ } + } + + if (s->s.h.highprecisionmvs) { + for (i = 0; i < 2; i++) { +- if (vpx_rac_get_prob_branchy(&s->c, 252)) +- s->prob.p.mv_comp[i].class0_hp = ++ if (vpx_rac_get_prob_branchy(&s->c, 252)) { ++ s->prob_raw.p.mv_comp[i].class0_hp = + (vp89_rac_get_uint(&s->c, 7) << 1) | 1; ++ s->prob.p.mv_comp[i].class0_hp = ++ s->prob_raw.p.mv_comp[i].class0_hp; ++ } + +- if (vpx_rac_get_prob_branchy(&s->c, 252)) +- s->prob.p.mv_comp[i].hp = ++ if (vpx_rac_get_prob_branchy(&s->c, 252)) { ++ s->prob_raw.p.mv_comp[i].hp = + (vp89_rac_get_uint(&s->c, 7) << 1) | 1; ++ s->prob.p.mv_comp[i].hp = ++ s->prob_raw.p.mv_comp[i].hp; ++ } + } + } + } +@@ -1870,6 +1946,9 @@ const FFCodec ff_vp9_decoder = { + #endif + #if CONFIG_VP9_VIDEOTOOLBOX_HWACCEL + HWACCEL_VIDEOTOOLBOX(vp9), ++#endif ++#if CONFIG_VP9_V4L2REQUEST_HWACCEL ++ HWACCEL_V4L2REQUEST(vp9), + #endif + NULL + }, +diff --git a/libavcodec/vp9dec.h b/libavcodec/vp9dec.h +index 81dc801052..99df1cb730 100644 +--- a/libavcodec/vp9dec.h ++++ b/libavcodec/vp9dec.h +@@ -134,6 +134,10 @@ typedef struct VP9Context { + ProbContext p; + uint8_t coef[4][2][2][6][6][11]; + } prob; ++ struct { ++ ProbContext p; ++ uint8_t coef[4][2][2][6][6][11]; ++ } prob_raw; + + // contextual (above) cache + uint8_t *above_partition_ctx; +diff --git a/libavcodec/vp9shared.h b/libavcodec/vp9shared.h +index 8a450c26a6..37e389e9e1 100644 +--- a/libavcodec/vp9shared.h ++++ b/libavcodec/vp9shared.h +@@ -136,6 +136,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 904a85173fab816bb3c30652300efa93f2333657 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sun, 15 Dec 2024 01:16:13 +0100 +Subject: [PATCH 11/11] HACK: avcodec: Don't check VIDIOC_ENUM_FRAMESIZES + step_width / step_height + +Currently required, since hantro and rkvdec drivers expose wrong values. + +Signed-off-by: Alex Bee +--- + libavcodec/v4l2_request_probe.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/libavcodec/v4l2_request_probe.c b/libavcodec/v4l2_request_probe.c +index 941042ec04..b3b1af3744 100644 +--- a/libavcodec/v4l2_request_probe.c ++++ b/libavcodec/v4l2_request_probe.c +@@ -258,9 +258,7 @@ static int v4l2_request_try_framesize(AVCodecContext *avctx, + } else if ((frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE || + frmsize.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) && + avctx->coded_width <= frmsize.stepwise.max_width && +- avctx->coded_height <= frmsize.stepwise.max_height && +- avctx->coded_width % frmsize.stepwise.step_width == 0 && +- avctx->coded_height % frmsize.stepwise.step_height == 0) { ++ avctx->coded_height <= frmsize.stepwise.max_height) { + return 0; + } + diff --git a/packages/multimedia/ffmpeg/patches/vf-deinterlace-v4l2m2m/ffmpeg-001-vf-deinterlace-v4l2m2m.patch b/packages/multimedia/ffmpeg/patches/vf-deinterlace-v4l2m2m/ffmpeg-001-vf-deinterlace-v4l2m2m.patch new file mode 100644 index 0000000000..0720cc3491 --- /dev/null +++ b/packages/multimedia/ffmpeg/patches/vf-deinterlace-v4l2m2m/ffmpeg-001-vf-deinterlace-v4l2m2m.patch @@ -0,0 +1,1054 @@ +From accf519d251f366afbbbffb67ebac3553a3c7cbb Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Tue, 3 Dec 2019 21:01:18 +0100 +Subject: [PATCH] Add V4L2 m2m deinterlace filter + +Signed-off-by: Alex Bee +--- + libavfilter/Makefile | 1 + + libavfilter/allfilters.c | 1 + + libavfilter/vf_deinterlace_v4l2m2m.c | 1011 ++++++++++++++++++++++++++ + 3 files changed, 1013 insertions(+) + create mode 100644 libavfilter/vf_deinterlace_v4l2m2m.c + +diff --git a/libavfilter/Makefile b/libavfilter/Makefile +index 91487afb21..84adb9ba46 100644 +--- a/libavfilter/Makefile ++++ b/libavfilter/Makefile +@@ -272,6 +272,7 @@ OBJS-$(CONFIG_DEFLATE_FILTER) += vf_neighbor.o + OBJS-$(CONFIG_DEFLICKER_FILTER) += vf_deflicker.o + OBJS-$(CONFIG_DEINTERLACE_QSV_FILTER) += vf_vpp_qsv.o + OBJS-$(CONFIG_DEINTERLACE_VAAPI_FILTER) += vf_deinterlace_vaapi.o vaapi_vpp.o ++OBJS-$(CONFIG_DEINTERLACE_V4L2M2M_FILTER) += vf_deinterlace_v4l2m2m.o + OBJS-$(CONFIG_DEJUDDER_FILTER) += vf_dejudder.o + OBJS-$(CONFIG_DELOGO_FILTER) += vf_delogo.o + OBJS-$(CONFIG_DENOISE_VAAPI_FILTER) += vf_misc_vaapi.o vaapi_vpp.o +diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c +index 9819f0f95b..c6d93340e6 100644 +--- a/libavfilter/allfilters.c ++++ b/libavfilter/allfilters.c +@@ -248,6 +248,7 @@ extern const AVFilter ff_vf_dedot; + extern const AVFilter ff_vf_deflate; + extern const AVFilter ff_vf_deflicker; + extern const AVFilter ff_vf_deinterlace_qsv; ++extern const AVFilter ff_vf_deinterlace_v4l2m2m; + extern const AVFilter ff_vf_deinterlace_vaapi; + extern const AVFilter ff_vf_dejudder; + extern const AVFilter ff_vf_delogo; +diff --git a/libavfilter/vf_deinterlace_v4l2m2m.c b/libavfilter/vf_deinterlace_v4l2m2m.c +new file mode 100644 +index 0000000000..bf163279ce +--- /dev/null ++++ b/libavfilter/vf_deinterlace_v4l2m2m.c +@@ -0,0 +1,1011 @@ ++/* ++ * 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 ++ * deinterlace video filter - V4L2 M2M ++ */ ++ ++#include ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "libavutil/avassert.h" ++#include "libavutil/avstring.h" ++#include "libavutil/common.h" ++#include "libavutil/hwcontext.h" ++#include "libavutil/hwcontext_drm.h" ++#include "libavutil/internal.h" ++#include "libavutil/mathematics.h" ++#include "libavutil/mem.h" ++#include "libavutil/opt.h" ++#include "libavutil/pixdesc.h" ++#include "libavutil/time.h" ++ ++#include "avfilter.h" ++#include "formats.h" ++#include "video.h" ++ ++typedef struct V4L2Queue V4L2Queue; ++typedef struct DeintV4L2M2MContextShared DeintV4L2M2MContextShared; ++ ++typedef struct V4L2PlaneInfo { ++ int bytesperline; ++ size_t length; ++} V4L2PlaneInfo; ++ ++typedef struct V4L2Buffer { ++ int enqueued; ++ int reenqueue; ++ int fd; ++ struct v4l2_buffer buffer; ++ struct v4l2_plane planes[VIDEO_MAX_PLANES]; ++ int num_planes; ++ V4L2PlaneInfo plane_info[VIDEO_MAX_PLANES]; ++ AVDRMFrameDescriptor drm_frame; ++ V4L2Queue *q; ++} V4L2Buffer; ++ ++typedef struct V4L2Queue { ++ struct v4l2_format format; ++ int num_buffers; ++ V4L2Buffer *buffers; ++ DeintV4L2M2MContextShared *ctx; ++} V4L2Queue; ++ ++typedef struct DeintV4L2M2MContextShared { ++ int fd; ++ int done; ++ int width; ++ int height; ++ int orig_width; ++ int orig_height; ++ uint64_t drm_in_format; ++ uint64_t drm_out_format; ++ ++ atomic_uint refcount; ++ ++ AVBufferRef *hw_frames_ctx; ++ ++ /* ++ * TODO: check if its really neccessary to hold this ++ * ref, it's only used for freeing av_frame on decoding ++ * end/abort ++ */ ++ AVFrame *cur_in_frame; ++ AVFrame *prev_in_frame; ++ unsigned int field_order; ++ ++ V4L2Queue output; ++ V4L2Queue capture; ++} DeintV4L2M2MContextShared; ++ ++typedef struct DeintV4L2M2MContext { ++ const AVClass *class; ++ ++ DeintV4L2M2MContextShared *shared; ++} DeintV4L2M2MContext; ++ ++static inline uint32_t v4l2_pix_fmt_from_drm_format(uint64_t drm_format) ++{ ++ switch(drm_format) { ++#if defined(V4L2_PIX_FMT_SUNXI_TILED_NV12) && defined(DRM_FORMAT_MOD_ALLWINNER_TILED) ++ case DRM_FORMAT_MOD_ALLWINNER_TILED: ++ return V4L2_PIX_FMT_SUNXI_TILED_NV12; ++#endif ++ case DRM_FORMAT_NV12: ++ return V4L2_PIX_FMT_NV12; ++#if defined(V4L2_PIX_FMT_NV15) && defined(DRM_FORMAT_NV15) ++ case DRM_FORMAT_NV15: ++ return V4L2_PIX_FMT_NV15; ++#endif ++ case DRM_FORMAT_NV16: ++ return V4L2_PIX_FMT_NV16; ++#if defined(V4L2_PIX_FMT_NV20) && defined(DRM_FORMAT_NV20) ++ case DRM_FORMAT_NV20: ++ return V4L2_PIX_FMT_NV20; ++#endif ++ case DRM_FORMAT_NV21: ++ return V4L2_PIX_FMT_NV21; ++ case DRM_FORMAT_NV61: ++ return V4L2_PIX_FMT_NV61; ++ default: ++ av_log(NULL, AV_LOG_WARNING, "%s unknown drm format %s using default v4l2_pix_fmt %s\n", ++ __func__ , av_fourcc2str(drm_format), av_fourcc2str(V4L2_PIX_FMT_NV12)); ++ return V4L2_PIX_FMT_NV12; ++ } ++} ++ ++static inline uint64_t drm_format_from_v4l2_pix_fmt(uint32_t v4l2_pix_fmt) ++{ ++ switch(v4l2_pix_fmt) { ++ case V4L2_PIX_FMT_NV12: ++ return DRM_FORMAT_NV12; ++#if defined(V4L2_PIX_FMT_NV15) && defined(DRM_FORMAT_NV15) ++ case V4L2_PIX_FMT_NV15: ++ return DRM_FORMAT_NV15; ++#endif ++ case V4L2_PIX_FMT_NV16: ++ return DRM_FORMAT_NV16; ++#if defined(V4L2_PIX_FMT_NV20) && defined(DRM_FORMAT_NV20) ++ case V4L2_PIX_FMT_NV20: ++ return DRM_FORMAT_NV20; ++#endif ++ case V4L2_PIX_FMT_NV21: ++ return DRM_FORMAT_NV21; ++ case V4L2_PIX_FMT_NV61: ++ return DRM_FORMAT_NV61; ++#if defined(V4L2_PIX_FMT_SUNXI_TILED_NV12) && defined(DRM_FORMAT_MOD_ALLWINNER_TILED) ++ case V4L2_PIX_FMT_SUNXI_TILED_NV12: ++ return DRM_FORMAT_MOD_ALLWINNER_TILED; ++#endif ++ default: ++ av_log(NULL, AV_LOG_WARNING, "%s unknown v4l2_pix_fmt format 0x%x using default drm_format 0x%x\n", ++ __func__ , v4l2_pix_fmt, DRM_FORMAT_NV12); ++ return DRM_FORMAT_NV12; ++ } ++} ++ ++static inline uint64_t drm_format_modifier(uint64_t drm_format) ++{ ++#ifdef DRM_FORMAT_MOD_ALLWINNER_TILED ++ if (drm_format == DRM_FORMAT_MOD_ALLWINNER_TILED) ++ return DRM_FORMAT_MOD_ALLWINNER_TILED; ++#endif ++ return DRM_FORMAT_MOD_LINEAR; ++ ++} ++ ++static int deint_v4l2m2m_prepare_context(DeintV4L2M2MContextShared *ctx) ++{ ++ struct v4l2_capability cap; ++ int ret; ++ ++ memset(&cap, 0, sizeof(cap)); ++ ret = ioctl(ctx->fd, VIDIOC_QUERYCAP, &cap); ++ if (ret < 0) ++ return ret; ++ ++ if (!(cap.capabilities & V4L2_CAP_STREAMING)) ++ return AVERROR(EINVAL); ++ ++ if (cap.capabilities & V4L2_CAP_VIDEO_M2M) { ++ ctx->capture.format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ ctx->output.format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; ++ ++ return 0; ++ } ++ ++ if (cap.capabilities & V4L2_CAP_VIDEO_M2M_MPLANE) { ++ ctx->capture.format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; ++ ctx->output.format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; ++ ++ return 0; ++ } ++ ++ return AVERROR(EINVAL); ++} ++ ++static int deint_v4l2m2m_try_format(V4L2Queue *queue, uint64_t drm_format) ++{ ++ struct v4l2_format *fmt = &queue->format; ++ DeintV4L2M2MContextShared *ctx = queue->ctx; ++ int ret, field; ++ uint32_t v4l2_pix_fmt = v4l2_pix_fmt_from_drm_format(drm_format); ++ ++ ret = ioctl(ctx->fd, VIDIOC_G_FMT, fmt); ++ if (ret) ++ av_log(NULL, AV_LOG_ERROR, "VIDIOC_G_FMT failed: %d\n", ret); ++ ++ if (V4L2_TYPE_IS_OUTPUT(fmt->type)) ++ field = V4L2_FIELD_INTERLACED_TB; ++ else ++ field = V4L2_FIELD_NONE; ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(fmt->type)) { ++ fmt->fmt.pix_mp.pixelformat = v4l2_pix_fmt; ++ fmt->fmt.pix_mp.field = field; ++ fmt->fmt.pix_mp.width = ctx->width; ++ fmt->fmt.pix_mp.height = ctx->height; ++ } else { ++ fmt->fmt.pix.pixelformat = v4l2_pix_fmt; ++ fmt->fmt.pix.field = field; ++ fmt->fmt.pix.width = ctx->width; ++ fmt->fmt.pix.height = ctx->height; ++ } ++ ++ ret = ioctl(ctx->fd, VIDIOC_TRY_FMT, fmt); ++ if (ret) ++ return AVERROR(EINVAL); ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(fmt->type)) { ++ if (fmt->fmt.pix_mp.pixelformat != v4l2_pix_fmt || ++ fmt->fmt.pix_mp.field != field) { ++ av_log(NULL, AV_LOG_DEBUG, "format not supported for type %d\n", fmt->type); ++ ++ return AVERROR(EINVAL); ++ } ++ } else { ++ if (fmt->fmt.pix.pixelformat != v4l2_pix_fmt || ++ fmt->fmt.pix.field != field) { ++ av_log(NULL, AV_LOG_DEBUG, "format not supported for type %d\n", fmt->type); ++ ++ return AVERROR(EINVAL); ++ } ++ } ++ ++ return 0; ++} ++static int deint_v4l2m2m_set_format(V4L2Queue *queue, uint32_t field, int width, int height, uint64_t drm_format) ++{ ++ struct v4l2_format *fmt = &queue->format; ++ DeintV4L2M2MContextShared *ctx = queue->ctx; ++ int ret; ++ uint32_t v4l2_pix_fmt = v4l2_pix_fmt_from_drm_format(drm_format); ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(fmt->type)) { ++ fmt->fmt.pix_mp.pixelformat = v4l2_pix_fmt; ++ fmt->fmt.pix_mp.field = field; ++ fmt->fmt.pix_mp.width = width; ++ fmt->fmt.pix_mp.height = height; ++ /* TODO: bytesperline and imagesize */ ++ } else { ++ fmt->fmt.pix.pixelformat = v4l2_pix_fmt; ++ fmt->fmt.pix.field = field; ++ fmt->fmt.pix.width = width; ++ fmt->fmt.pix.height = height; ++ fmt->fmt.pix.sizeimage = 0; ++ fmt->fmt.pix.bytesperline = 0; ++ } ++ ++ ret = ioctl(ctx->fd, VIDIOC_S_FMT, fmt); ++ if (ret) ++ av_log(NULL, AV_LOG_ERROR, "VIDIOC_S_FMT failed: %d\n", ret); ++ ++ else if (!V4L2_TYPE_IS_OUTPUT(queue->format.type)) { ++ if (V4L2_TYPE_IS_MULTIPLANAR(fmt->type) && fmt->fmt.pix_mp.pixelformat != v4l2_pix_fmt) { ++ ctx->drm_out_format = drm_format_from_v4l2_pix_fmt(fmt->fmt.pix_mp.pixelformat); ++ av_log(NULL, AV_LOG_DEBUG, "%s driver updated v4l2_pixfmt from: %s to %s, so now using %s as drm output format\n", ++ __func__, av_fourcc2str(v4l2_pix_fmt), av_fourcc2str(fmt->fmt.pix_mp.pixelformat), av_fourcc2str(ctx->drm_out_format)); ++ } else if (fmt->fmt.pix.pixelformat != v4l2_pix_fmt) { ++ ctx->drm_out_format = drm_format_from_v4l2_pix_fmt(fmt->fmt.pix.pixelformat); ++ av_log(NULL, AV_LOG_DEBUG, "%s driver updated v4l2_pixfmt from: %s to %s, so now using %s as drm output format\n", ++ __func__, av_fourcc2str(v4l2_pix_fmt), av_fourcc2str(fmt->fmt.pix.pixelformat), av_fourcc2str(ctx->drm_out_format)); ++ } ++ } ++ ++ return ret; ++} ++ ++static int deint_v4l2m2m_probe_device(DeintV4L2M2MContextShared *ctx, char *node) ++{ ++ int ret; ++ ++ ctx->fd = open(node, O_RDWR | O_NONBLOCK, 0); ++ if (ctx->fd < 0) ++ return AVERROR(errno); ++ ++ ret = deint_v4l2m2m_prepare_context(ctx); ++ if (ret) ++ goto fail; ++ ++ ret = deint_v4l2m2m_try_format(&ctx->capture, ctx->drm_out_format); ++ if (ret) ++ goto fail; ++ ++ ret = deint_v4l2m2m_try_format(&ctx->output, ctx->drm_in_format); ++ if (ret) ++ goto fail; ++ ++ return 0; ++ ++fail: ++ close(ctx->fd); ++ ctx->fd = -1; ++ ++ return ret; ++} ++ ++static int deint_v4l2m2m_find_device(DeintV4L2M2MContextShared *ctx) ++{ ++ int ret = AVERROR(EINVAL); ++ struct dirent *entry; ++ char node[PATH_MAX]; ++ DIR *dirp; ++ ++ dirp = opendir("/dev"); ++ if (!dirp) ++ return AVERROR(errno); ++ ++ for (entry = readdir(dirp); entry; entry = readdir(dirp)) { ++ ++ if (strncmp(entry->d_name, "video", 5)) ++ continue; ++ ++ snprintf(node, sizeof(node), "/dev/%s", entry->d_name); ++ av_log(NULL, AV_LOG_DEBUG, "probing device %s\n", node); ++ ret = deint_v4l2m2m_probe_device(ctx, node); ++ if (!ret) ++ break; ++ } ++ ++ closedir(dirp); ++ ++ if (ret) { ++ av_log(NULL, AV_LOG_ERROR, "Could not find a valid device\n"); ++ ctx->fd = -1; ++ ++ return ret; ++ } ++ ++ av_log(NULL, AV_LOG_INFO, "Using device %s\n", node); ++ ++ return 0; ++} ++ ++static int deint_v4l2m2m_enqueue_buffer(V4L2Buffer *buf) ++{ ++ int ret; ++ ++ ret = ioctl(buf->q->ctx->fd, VIDIOC_QBUF, &buf->buffer); ++ if (ret < 0) ++ return AVERROR(errno); ++ ++ buf->enqueued = 1; ++ ++ return 0; ++} ++ ++static int v4l2_buffer_export_drm(V4L2Buffer* avbuf, uint64_t drm_format) ++{ ++ struct v4l2_exportbuffer expbuf; ++ int i, ret; ++ ++ for (i = 0; i < avbuf->num_planes; i++) { ++ memset(&expbuf, 0, sizeof(expbuf)); ++ ++ expbuf.index = avbuf->buffer.index; ++ expbuf.type = avbuf->buffer.type; ++ expbuf.plane = i; ++ ++ ret = ioctl(avbuf->q->ctx->fd, VIDIOC_EXPBUF, &expbuf); ++ if (ret < 0) ++ return AVERROR(errno); ++ ++ avbuf->fd = expbuf.fd; ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(avbuf->buffer.type)) { ++ /* drm frame */ ++ avbuf->drm_frame.objects[i].size = avbuf->buffer.m.planes[i].length; ++ avbuf->drm_frame.objects[i].fd = expbuf.fd; ++ avbuf->drm_frame.objects[i].format_modifier = drm_format_modifier(drm_format); ++ } else { ++ /* drm frame */ ++ avbuf->drm_frame.objects[0].size = avbuf->buffer.length; ++ avbuf->drm_frame.objects[0].fd = expbuf.fd; ++ avbuf->drm_frame.objects[0].format_modifier = drm_format_modifier(drm_format); ++ } ++ } ++ ++ return 0; ++} ++ ++static int deint_v4l2m2m_allocate_buffers(V4L2Queue *queue) ++{ ++ struct v4l2_format *fmt = &queue->format; ++ DeintV4L2M2MContextShared *ctx = queue->ctx; ++ struct v4l2_requestbuffers req; ++ int ret, i, j, multiplanar; ++ uint32_t memory; ++ ++ memory = V4L2_TYPE_IS_OUTPUT(fmt->type) ? ++ V4L2_MEMORY_DMABUF : V4L2_MEMORY_MMAP; ++ ++ multiplanar = V4L2_TYPE_IS_MULTIPLANAR(fmt->type); ++ ++ memset(&req, 0, sizeof(req)); ++ req.count = queue->num_buffers; ++ req.memory = memory; ++ req.type = fmt->type; ++ ++ ret = ioctl(ctx->fd, VIDIOC_REQBUFS, &req); ++ if (ret < 0) { ++ av_log(NULL, AV_LOG_ERROR, "VIDIOC_REQBUFS failed: %s\n", strerror(errno)); ++ ++ return AVERROR(errno); ++ } ++ ++ queue->num_buffers = req.count; ++ queue->buffers = av_mallocz(queue->num_buffers * sizeof(V4L2Buffer)); ++ if (!queue->buffers) { ++ av_log(NULL, AV_LOG_ERROR, "malloc enomem\n"); ++ ++ return AVERROR(ENOMEM); ++ } ++ ++ for (i = 0; i < queue->num_buffers; i++) { ++ V4L2Buffer *buf = &queue->buffers[i]; ++ ++ buf->enqueued = 0; ++ buf->fd = -1; ++ buf->q = queue; ++ ++ buf->buffer.type = fmt->type; ++ buf->buffer.memory = memory; ++ buf->buffer.index = i; ++ ++ if (multiplanar) { ++ buf->buffer.length = VIDEO_MAX_PLANES; ++ buf->buffer.m.planes = buf->planes; ++ } ++ ++ ret = ioctl(ctx->fd, VIDIOC_QUERYBUF, &buf->buffer); ++ if (ret < 0) { ++ ret = AVERROR(errno); ++ ++ goto fail; ++ } ++ ++ if (multiplanar) ++ buf->num_planes = buf->buffer.length; ++ else ++ buf->num_planes = 1; ++ ++ for (j = 0; j < buf->num_planes; j++) { ++ V4L2PlaneInfo *info = &buf->plane_info[j]; ++ ++ if (multiplanar) { ++ info->bytesperline = fmt->fmt.pix_mp.plane_fmt[j].bytesperline; ++ info->length = buf->buffer.m.planes[j].length; ++ } else { ++ info->bytesperline = fmt->fmt.pix.bytesperline; ++ info->length = buf->buffer.length; ++ } ++ } ++ ++ if (!V4L2_TYPE_IS_OUTPUT(fmt->type)) { ++ ret = deint_v4l2m2m_enqueue_buffer(buf); ++ if (ret) ++ goto fail; ++ ++ ret = v4l2_buffer_export_drm(buf, ctx->drm_out_format); ++ if (ret) ++ goto fail; ++ } ++ } ++ ++ return 0; ++ ++fail: ++ for (i = 0; i < queue->num_buffers; i++) ++ if (queue->buffers[i].fd >= 0) ++ close(queue->buffers[i].fd); ++ av_free(queue->buffers); ++ queue->buffers = NULL; ++ ++ return ret; ++} ++ ++static int deint_v4l2m2m_streamon(V4L2Queue *queue) ++{ ++ int type = queue->format.type; ++ int ret; ++ ++ ret = ioctl(queue->ctx->fd, VIDIOC_STREAMON, &type); ++ if (ret < 0) ++ return AVERROR(errno); ++ ++ return 0; ++} ++ ++static int deint_v4l2m2m_streamoff(V4L2Queue *queue) ++{ ++ int type = queue->format.type; ++ int ret; ++ ++ ret = ioctl(queue->ctx->fd, VIDIOC_STREAMOFF, &type); ++ if (ret < 0) ++ return AVERROR(errno); ++ ++ return 0; ++} ++ ++static V4L2Buffer* deint_v4l2m2m_dequeue_buffer(V4L2Queue *queue, int timeout) ++{ ++ struct v4l2_plane planes[VIDEO_MAX_PLANES]; ++ DeintV4L2M2MContextShared *ctx = queue->ctx; ++ struct v4l2_buffer buf = { 0 }; ++ V4L2Buffer* avbuf = NULL; ++ struct pollfd pfd; ++ short events; ++ int ret; ++ ++ if (V4L2_TYPE_IS_OUTPUT(queue->format.type)) ++ events = POLLOUT | POLLWRNORM; ++ else ++ events = POLLIN | POLLRDNORM; ++ ++ pfd.events = events; ++ pfd.fd = ctx->fd; ++ ++ for (;;) { ++ ret = poll(&pfd, 1, timeout); ++ if (ret > 0) ++ break; ++ if (errno == EINTR) ++ continue; ++ return NULL; ++ } ++ ++ if (pfd.revents & POLLERR) ++ return NULL; ++ ++ if (pfd.revents & events) { ++ memset(&buf, 0, sizeof(buf)); ++ buf.memory = V4L2_MEMORY_MMAP; ++ buf.type = queue->format.type; ++ if (V4L2_TYPE_IS_MULTIPLANAR(queue->format.type)) { ++ memset(planes, 0, sizeof(planes)); ++ buf.length = VIDEO_MAX_PLANES; ++ buf.m.planes = planes; ++ } ++ ++ ret = ioctl(ctx->fd, VIDIOC_DQBUF, &buf); ++ if (ret) { ++ if (errno != EAGAIN) ++ av_log(NULL, AV_LOG_DEBUG, "VIDIOC_DQBUF, errno (%s)\n", ++ av_err2str(AVERROR(errno))); ++ return NULL; ++ } ++ ++ avbuf = &queue->buffers[buf.index]; ++ avbuf->enqueued = 0; ++ avbuf->buffer = buf; ++ if (V4L2_TYPE_IS_MULTIPLANAR(queue->format.type)) { ++ memcpy(avbuf->planes, planes, sizeof(planes)); ++ avbuf->buffer.m.planes = avbuf->planes; ++ } ++ ++ return avbuf; ++ } ++ ++ return NULL; ++} ++ ++static V4L2Buffer *deint_v4l2m2m_find_free_buf(V4L2Queue *queue) ++{ ++ int i; ++ ++ for (i = 0; i < queue->num_buffers; i++) ++ if (!queue->buffers[i].enqueued) ++ return &queue->buffers[i]; ++ ++ return NULL; ++} ++ ++static int deint_v4l2m2m_enqueue(V4L2Queue *queue, const AVFrame* frame) ++{ ++ AVDRMFrameDescriptor *drm_desc = (AVDRMFrameDescriptor *)frame->data[0]; ++ V4L2Buffer *buf; ++ int i; ++ ++ if (V4L2_TYPE_IS_OUTPUT(queue->format.type)) ++ while (deint_v4l2m2m_dequeue_buffer(queue, 0)); ++ ++ buf = deint_v4l2m2m_find_free_buf(queue); ++ if (!buf) ++ return AVERROR(ENOMEM); ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(buf->buffer.type)) ++ for (i = 0; i < drm_desc->nb_objects; i++) ++ buf->buffer.m.planes[i].m.fd = drm_desc->objects[i].fd; ++ else ++ buf->buffer.m.fd = drm_desc->objects[0].fd; ++ ++ return deint_v4l2m2m_enqueue_buffer(buf); ++} ++ ++static void deint_v4l2m2m_destroy_context(DeintV4L2M2MContextShared *ctx) ++{ ++ if (atomic_fetch_sub(&ctx->refcount, 1) == 1) { ++ V4L2Queue *capture = &ctx->capture; ++ V4L2Queue *output = &ctx->output; ++ int i; ++ ++ av_log(NULL, AV_LOG_DEBUG, "%s - destroying context\n", __func__); ++ ++ if (ctx->fd >= 0) { ++ deint_v4l2m2m_streamoff(capture); ++ deint_v4l2m2m_streamoff(output); ++ } ++ ++ if (capture->buffers) ++ for (i = 0; i < capture->num_buffers; i++) { ++ capture->buffers[i].q = NULL; ++ if (capture->buffers[i].fd >= 0) ++ close(capture->buffers[i].fd); ++ } ++ ++ if (ctx->cur_in_frame) ++ av_frame_free(&ctx->cur_in_frame); ++ ++ if (ctx->prev_in_frame) ++ av_frame_free(&ctx->prev_in_frame); ++ ++ av_buffer_unref(&ctx->hw_frames_ctx); ++ ++ if (capture->buffers) ++ av_free(capture->buffers); ++ ++ if (output->buffers) ++ av_free(output->buffers); ++ ++ if (ctx->fd >= 0) { ++ close(ctx->fd); ++ ctx->fd = -1; ++ } ++ ++ av_free(ctx); ++ } ++} ++ ++static void v4l2_free_buffer(void *opaque, uint8_t *unused) ++{ ++ V4L2Buffer *buf = opaque; ++ DeintV4L2M2MContextShared *ctx = buf->q->ctx; ++ ++ if (!ctx->done) ++ deint_v4l2m2m_enqueue_buffer(buf); ++ ++ deint_v4l2m2m_destroy_context(ctx); ++} ++ ++static uint8_t *v4l2_get_drm_frame(V4L2Buffer *avbuf, int height, uint64_t drm_format) ++{ ++ 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; ++ } ++ ++ layer->format = drm_format; ++ ++ if (avbuf->num_planes == 1) { ++ layer->nb_planes = 2; ++ ++ layer->planes[1].object_index = 0; ++ layer->planes[1].offset = avbuf->plane_info[0].bytesperline * height; ++ layer->planes[1].pitch = avbuf->plane_info[0].bytesperline; ++ } ++ ++ return (uint8_t *)drm_desc; ++} ++ ++static int deint_v4l2m2m_dequeue_frame(V4L2Queue *queue, AVFrame* frame, int timeout) ++{ ++ DeintV4L2M2MContextShared *ctx = queue->ctx; ++ V4L2Buffer* avbuf; ++ ++ avbuf = deint_v4l2m2m_dequeue_buffer(queue, timeout); ++ if (!avbuf) { ++ av_log(NULL, AV_LOG_ERROR, "dequeueing failed\n"); ++ return AVERROR(EINVAL); ++ } ++ ++ frame->buf[0] = av_buffer_create((uint8_t *) &avbuf->drm_frame, ++ sizeof(avbuf->drm_frame), v4l2_free_buffer, ++ avbuf, AV_BUFFER_FLAG_READONLY); ++ if (!frame->buf[0]) ++ return AVERROR(ENOMEM); ++ ++ atomic_fetch_add(&ctx->refcount, 1); ++ ++ frame->data[0] = (uint8_t *)v4l2_get_drm_frame(avbuf, ctx->orig_height, ctx->drm_out_format); ++ frame->format = AV_PIX_FMT_DRM_PRIME; ++ frame->hw_frames_ctx = av_buffer_ref(ctx->hw_frames_ctx); ++ frame->height = ctx->height; ++ frame->width = ctx->width; ++ ++ if (avbuf->buffer.flags & V4L2_BUF_FLAG_ERROR) { ++ av_log(NULL, AV_LOG_ERROR, "driver decode error\n"); ++ frame->decode_error_flags |= FF_DECODE_ERROR_INVALID_BITSTREAM; ++ } ++ ++ return 0; ++} ++ ++static int deint_v4l2m2m_dequeue(AVFilterContext *avctx, AVFrame *input_frame) ++{ ++ DeintV4L2M2MContext *priv = avctx->priv; ++ DeintV4L2M2MContextShared *ctx = priv->shared; ++ AVFilterLink *outlink = avctx->outputs[0]; ++ AVFrame *output_frame_1, *output_frame_2; ++ int64_t first_pts = AV_NOPTS_VALUE; ++ int err; ++ ++ av_log(priv, AV_LOG_DEBUG, "input pts: %"PRId64" (field %d)\n", ++ input_frame->pts, ctx->field_order); ++ ++ output_frame_1 = av_frame_alloc(); ++ if (!output_frame_1) ++ return AVERROR(ENOMEM); ++ ++ err = deint_v4l2m2m_dequeue_frame(&ctx->capture, output_frame_1, 500); ++ if (err < 0) { ++ av_log(priv, AV_LOG_ERROR, "no 1st frame (field %d)\n", ctx->field_order); ++ goto fail_out1; ++ } ++ ++ err = av_frame_copy_props(output_frame_1, input_frame); ++ if (err < 0) ++ goto fail_out1; ++ ++ output_frame_1->flags &= ~AV_FRAME_FLAG_INTERLACED; ++ ++ output_frame_2 = av_frame_alloc(); ++ if (!output_frame_2) { ++ err = AVERROR(ENOMEM); ++ goto fail_out1; ++ } ++ ++ err = deint_v4l2m2m_dequeue_frame(&ctx->capture, output_frame_2, 500); ++ if (err < 0) { ++ av_log(priv, AV_LOG_ERROR, "no 2nd frame (field %d)\n", ctx->field_order); ++ goto fail_out2; ++ } ++ ++ err = av_frame_copy_props(output_frame_2, input_frame); ++ if (err < 0) ++ goto fail_out2; ++ ++ output_frame_2->flags &= ~AV_FRAME_FLAG_INTERLACED; ++ ++ if (ctx->prev_in_frame && ctx->prev_in_frame->pts != AV_NOPTS_VALUE ++ && input_frame->pts != AV_NOPTS_VALUE) { ++ first_pts = (ctx->prev_in_frame->pts + input_frame->pts) / 2; ++ av_log(priv, AV_LOG_DEBUG, "calculated first pts %"PRId64"\n", first_pts); ++ } ++ ++ output_frame_1->pts = first_pts; ++ ++ err = ff_filter_frame(outlink, output_frame_1); ++ if (err < 0) { ++ av_frame_free(&output_frame_2); ++ return err; ++ } ++ err = ff_filter_frame(outlink, output_frame_2); ++ ++ if (err < 0) ++ return err; ++ ++ av_log(priv, AV_LOG_DEBUG, "1st frame pts: %"PRId64" 2nd frame pts: %"PRId64" first pts: %"PRId64" (field %d)\n", ++ output_frame_1->pts, output_frame_2->pts, first_pts, ctx->field_order); ++ ++ return 0; ++ ++fail_out2: ++ av_frame_free(&output_frame_2); ++fail_out1: ++ av_frame_free(&output_frame_1); ++ return err; ++} ++ ++static int deint_v4l2m2m_config_props(AVFilterLink *outlink) ++{ ++ AVFilterLink *inlink = outlink->src->inputs[0]; ++ AVFilterContext *avctx = outlink->src; ++ DeintV4L2M2MContext *priv = avctx->priv; ++ DeintV4L2M2MContextShared *ctx = priv->shared; ++ FilterLink *fl_inlink = ff_filter_link(inlink); ++ FilterLink *fl_outlink = ff_filter_link(outlink); ++ int ret; ++ ++ ctx->height = avctx->inputs[0]->h; ++ ctx->width = avctx->inputs[0]->w; ++ ++ fl_outlink->frame_rate = av_mul_q(fl_inlink->frame_rate, ++ (AVRational){ 2, 1 }); ++ outlink->time_base = av_mul_q(inlink->time_base, ++ (AVRational){ 1, 2 }); ++ ++ ret = deint_v4l2m2m_find_device(ctx); ++ if (ret) ++ return ret; ++ ++ if (!fl_inlink->hw_frames_ctx) { ++ av_log(priv, AV_LOG_ERROR, "No hw context provided on input\n"); ++ return AVERROR(EINVAL); ++ } ++ ++ ctx->hw_frames_ctx = av_buffer_ref(fl_inlink->hw_frames_ctx); ++ if (!ctx->hw_frames_ctx) ++ return AVERROR(ENOMEM); ++ ++ return 0; ++} ++ ++static int deint_v4l2m2m_query_formats(AVFilterContext *avctx) ++{ ++ static const enum AVPixelFormat pixel_formats[] = { ++ AV_PIX_FMT_DRM_PRIME, ++ AV_PIX_FMT_NONE, ++ }; ++ ++ return ff_set_common_formats(avctx, ff_make_format_list(pixel_formats)); ++} ++ ++static int deint_v4l2m2m_filter_frame(AVFilterLink *link, AVFrame *in) ++{ ++ AVFilterContext *avctx = link->dst; ++ DeintV4L2M2MContext *priv = avctx->priv; ++ DeintV4L2M2MContextShared *ctx = priv->shared; ++ V4L2Queue *capture = &ctx->capture; ++ V4L2Queue *output = &ctx->output; ++ int ret; ++ ++ av_log(priv, AV_LOG_DEBUG, "input pts: %"PRId64" field :%d interlaced: %d\n", ++ in->pts, !!(in->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST), !!(in->flags & AV_FRAME_FLAG_INTERLACED)); ++ ++ ctx->cur_in_frame = in; ++ ++ if (ctx->field_order == V4L2_FIELD_ANY) { ++ AVDRMFrameDescriptor *drm_desc = (AVDRMFrameDescriptor *)in->data[0]; ++ ctx->orig_width = drm_desc->layers[0].planes[0].pitch; ++ ctx->orig_height = drm_desc->layers[0].planes[1].offset / ctx->orig_width; ++ ctx->drm_in_format = drm_desc->layers->format; ++ ctx->drm_out_format = drm_desc->layers->format; ++ ++ if (!!(in->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST)) ++ ctx->field_order = V4L2_FIELD_INTERLACED_TB; ++ else ++ ctx->field_order = V4L2_FIELD_INTERLACED_BT; ++ ++ ret = deint_v4l2m2m_set_format(output, ctx->field_order, ++ ctx->orig_width, ctx->orig_height, ++ ctx->drm_in_format); ++ if (ret) ++ return ret; ++ ++ ret = deint_v4l2m2m_set_format(capture, V4L2_FIELD_NONE, ++ ctx->orig_width, ctx->orig_height, ++ ctx->drm_out_format); ++ if (ret) ++ return ret; ++ ++ ret = deint_v4l2m2m_allocate_buffers(capture); ++ if (ret) ++ return ret; ++ ++ ret = deint_v4l2m2m_streamon(capture); ++ if (ret) ++ return ret; ++ ++ ret = deint_v4l2m2m_allocate_buffers(output); ++ if (ret) ++ return ret; ++ ++ ret = deint_v4l2m2m_streamon(output); ++ if (ret) ++ return ret; ++ } ++ ++ ret = deint_v4l2m2m_enqueue(output, in); ++ if (ret) ++ return ret; ++ ++ ret = deint_v4l2m2m_dequeue(avctx, in); ++ if (ret) ++ return ret; ++ ++ if (ctx->prev_in_frame) ++ av_frame_free(&ctx->prev_in_frame); ++ ++ ctx->prev_in_frame = in; ++ ctx->cur_in_frame = NULL; ++ ++ return 0; ++} ++ ++static av_cold int deint_v4l2m2m_init(AVFilterContext *avctx) ++{ ++ DeintV4L2M2MContext *priv = avctx->priv; ++ DeintV4L2M2MContextShared *ctx; ++ ++ ctx = av_mallocz(sizeof(DeintV4L2M2MContextShared)); ++ if (!ctx) ++ return AVERROR(ENOMEM); ++ ++ priv->shared = ctx; ++ ctx->fd = -1; ++ ctx->output.ctx = ctx; ++ ctx->output.num_buffers = 6; ++ ctx->capture.ctx = ctx; ++ ctx->capture.num_buffers = 6; ++ ctx->done = 0; ++ ctx->field_order = V4L2_FIELD_ANY; ++ ctx->cur_in_frame = NULL; ++ ctx->prev_in_frame = NULL; ++ ctx->drm_in_format = DRM_FORMAT_NV12; ++ ctx->drm_out_format = DRM_FORMAT_NV12; ++ atomic_init(&ctx->refcount, 1); ++ ++ return 0; ++} ++ ++static void deint_v4l2m2m_uninit(AVFilterContext *avctx) ++{ ++ DeintV4L2M2MContext *priv = avctx->priv; ++ DeintV4L2M2MContextShared *ctx = priv->shared; ++ ++ ctx->done = 1; ++ deint_v4l2m2m_destroy_context(ctx); ++} ++ ++static const AVOption deinterlace_v4l2m2m_options[] = { ++ { NULL }, ++}; ++ ++AVFILTER_DEFINE_CLASS(deinterlace_v4l2m2m); ++ ++static const AVFilterPad deint_v4l2m2m_inputs[] = { ++ { ++ .name = "default", ++ .type = AVMEDIA_TYPE_VIDEO, ++ .filter_frame = deint_v4l2m2m_filter_frame, ++ }, ++}; ++ ++static const AVFilterPad deint_v4l2m2m_outputs[] = { ++ { ++ .name = "default", ++ .type = AVMEDIA_TYPE_VIDEO, ++ .config_props = deint_v4l2m2m_config_props, ++ }, ++}; ++ ++AVFilter ff_vf_deinterlace_v4l2m2m = { ++ .name = "deinterlace_v4l2m2m", ++ .description = NULL_IF_CONFIG_SMALL("V4L2 M2M deinterlacer"), ++ .priv_size = sizeof(DeintV4L2M2MContext), ++ .init = &deint_v4l2m2m_init, ++ .uninit = &deint_v4l2m2m_uninit, ++ FILTER_QUERY_FUNC(&deint_v4l2m2m_query_formats), ++ FILTER_INPUTS(deint_v4l2m2m_inputs), ++ FILTER_OUTPUTS(deint_v4l2m2m_outputs), ++ .priv_class = &deinterlace_v4l2m2m_class, ++}; diff --git a/packages/multimedia/gstreamer/gst-plugins-bad/package.mk b/packages/multimedia/gstreamer/gst-plugins-bad/package.mk new file mode 100644 index 0000000000..7ad9d3bd20 --- /dev/null +++ b/packages/multimedia/gstreamer/gst-plugins-bad/package.mk @@ -0,0 +1,197 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="gst-plugins-bad" +PKG_VERSION="1.27.1" +PKG_SHA256="9730381c718b7d99042a5e02e33ca5eccad0c8a5c5325aca66491728de9ba64e" +PKG_LICENSE="LGPL-2.1-or-later" +PKG_SITE="https://gstreamer.freedesktop.org/modules/gst-plugins-bad.html" +PKG_URL="https://gstreamer.freedesktop.org/src/gst-plugins-bad/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain gst-plugins-base" +PKG_LONGDESC="GStreamer Bad Plug-ins is a set of plug-ins that aren't up to par compared to the rest." + +pre_configure_target() { + PKG_MESON_OPTS_TARGET="-Dgst_play_tests=false \ + -Daccurip=disabled \ + -Dadpcmdec=disabled \ + -Dadpcmenc=disabled \ + -Daiff=disabled \ + -Dasfmux=disabled \ + -Daudiobuffersplit=disabled \ + -Daudiofxbad=disabled \ + -Daudiolatency=disabled \ + -Daudiomixmatrix=disabled \ + -Daudiovisualizers=disabled \ + -Dautoconvert=disabled \ + -Dbayer=disabled \ + -Dcamerabin2=disabled \ + -Dcoloreffects=disabled \ + -Ddebugutils=disabled \ + -Ddvbsubenc=disabled \ + -Ddvbsuboverlay=disabled \ + -Ddvdspu=disabled \ + -Dfaceoverlay=disabled \ + -Dfestival=disabled \ + -Dfieldanalysis=disabled \ + -Dfreeverb=disabled \ + -Dfrei0r=disabled \ + -Dgaudieffects=disabled \ + -Dgdp=disabled \ + -Dgeometrictransform=disabled \ + -Did3tag=disabled \ + -Dinter=disabled \ + -Dinterlace=disabled \ + -Divfparse=disabled \ + -Divtc=disabled \ + -Djp2kdecimator=disabled \ + -Djpegformat=disabled \ + -Dlibrfb=disabled \ + -Dmidi=disabled \ + -Dmpegdemux=disabled \ + -Dmpegpsmux=disabled \ + -Dmpegtsdemux=disabled \ + -Dmpegtsmux=disabled \ + -Dmxf=disabled \ + -Dnetsim=disabled \ + -Donvif=disabled \ + -Dpcapparse=disabled \ + -Dpnm=disabled \ + -Dproxy=disabled \ + -Drawparse=disabled \ + -Dremovesilence=disabled \ + -Drist=disabled \ + -Drtmp2=disabled \ + -Drtp=disabled \ + -Dsdp=disabled \ + -Dsegmentclip=disabled \ + -Dsiren=disabled \ + -Dsmooth=disabled \ + -Dspeed=disabled \ + -Dsubenc=disabled \ + -Dswitchbin=disabled \ + -Dtimecode=disabled \ + -Dvideofilters=disabled \ + -Dvideoframe_audiolevel=disabled \ + -Dvideoparsers=enabled \ + -Dvideosignal=disabled \ + -Dvmnc=disabled \ + -Dopencv=disabled \ + -Dwayland=disabled \ + -Dx11=disabled \ + -Daom=disabled \ + -Davtp=disabled \ + -Dandroidmedia=disabled \ + -Dapplemedia=disabled \ + -Dassrender=disabled \ + -Dbluez=disabled \ + -Dbs2b=disabled \ + -Dbz2=disabled \ + -Dchromaprint=disabled \ + -Dclosedcaption=disabled \ + -Dcolormanagement=disabled \ + -Dcurl=disabled \ + -Dcurl-ssh2=disabled \ + -Dd3dvideosink=disabled \ + -Dd3d11=disabled \ + -Ddash=disabled \ + -Ddc1394=disabled \ + -Ddecklink=disabled \ + -Ddirectfb=disabled \ + -Ddirectsound=disabled \ + -Ddtls=disabled \ + -Ddts=disabled \ + -Ddvb=disabled \ + -Dfaac=disabled \ + -Dfaad=disabled \ + -Dfbdev=disabled \ + -Dfdkaac=disabled \ + -Dflite=disabled \ + -Dfluidsynth=disabled \ + -Dgl=disabled \ + -Dgme=disabled \ + -Dgsm=disabled \ + -Dipcpipeline=disabled \ + -Diqa=disabled \ + -Dkms=disabled \ + -Dladspa=disabled \ + -Dlibde265=disabled \ + -Dlv2=disabled \ + -Dmediafoundation=disabled \ + -Dmicrodns=disabled \ + -Dmodplug=disabled \ + -Dmpeg2enc=disabled \ + -Dmplex=disabled \ + -Dmsdk=disabled \ + -Dmusepack=disabled \ + -Dneon=disabled \ + -Dnvcodec=disabled \ + -Dopenal=disabled \ + -Dopenexr=disabled \ + -Dopenh264=disabled \ + -Dopenjpeg=disabled \ + -Dopenmpt=disabled \ + -Dopenni2=disabled \ + -Dopensles=disabled \ + -Dopus=disabled \ + -Dresindvd=disabled \ + -Drsvg=disabled \ + -Drtmp=disabled \ + -Dsbc=disabled \ + -Dsctp=disabled \ + -Dshm=disabled \ + -Dsmoothstreaming=disabled \ + -Dsndfile=disabled \ + -Dsoundtouch=disabled \ + -Dspandsp=disabled \ + -Dsrt=disabled \ + -Dsrtp=disabled \ + -Dsvthevcenc=disabled \ + -Dteletext=disabled \ + -Dtinyalsa=disabled \ + -Dtranscode=disabled \ + -Dttml=disabled \ + -Duvch264=disabled \ + -Dva=disabled \ + -Dvoaacenc=disabled \ + -Dvoamrwbenc=disabled \ + -Dvulkan=disabled \ + -Dwasapi=disabled \ + -Dwasapi2=disabled \ + -Dwebp=disabled \ + -Dwebrtc=disabled \ + -Dwebrtcdsp=disabled \ + -Dwildmidi=disabled \ + -Dwinks=disabled \ + -Dwinscreencap=disabled \ + -Dx265=disabled \ + -Dzbar=disabled \ + -Dzxing=disabled \ + -Dwpe=disabled \ + -Dmagicleap=disabled \ + -Dv4l2codecs=disabled \ + -Dhls=disabled \ + -Dsctp-internal-usrsctp=disabled \ + -Dexamples=disabled \ + -Dtests=disabled \ + -Dintrospection=disabled \ + -Dnls=disabled \ + -Dorc=disabled \ + -Dglib_debug=disabled \ + -Dglib_assert=false \ + -Dglib_checks=false \ + -Dpackage-name=gst-plugins-bad \ + -Dpackage-origin=LibreELEC.tv \ + -Ddoc=disabled" +} + +post_makeinstall_target() { + # clean up + safe_remove ${INSTALL}/usr/bin + PKG_GST_PLUGINS_BAD_LIST="libgstadaptivedemux libgstbadaudio libgstbasecamerabinsrc libgstcodecs \ + libgstinsertbin libgstisoff libgstmpegts libgstphotography libgstplayer \ + libgstsctp libgsttranscoder libgsturidownloader libgstwebrtc" + for PKG_GST_PLUGINS_BAD in ${PKG_GST_PLUGINS_BAD_LIST}; do + safe_remove ${INSTALL}/usr/lib/${PKG_GST_PLUGINS_BAD}-1.0* + done + safe_remove ${INSTALL}/usr/share +} diff --git a/packages/multimedia/gstreamer/gst-plugins-base/package.mk b/packages/multimedia/gstreamer/gst-plugins-base/package.mk new file mode 100644 index 0000000000..bc917985f5 --- /dev/null +++ b/packages/multimedia/gstreamer/gst-plugins-base/package.mk @@ -0,0 +1,68 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="gst-plugins-base" +PKG_VERSION="1.27.1" +PKG_SHA256="25ff354f63f3f4bf0a66cb938948eeb203be5e1d5ef8e0154fb54e553242e201" +PKG_LICENSE="GPL-2.1-or-later" +PKG_SITE="https://gstreamer.freedesktop.org/modules/gst-plugins-base.html" +PKG_URL="https://gstreamer.freedesktop.org/src/gst-plugins-base/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain gstreamer" +PKG_LONGDESC="Base GStreamer plugins and helper libraries" +PKG_BUILD_FLAGS="-gold" + +pre_configure_target() { + PKG_MESON_OPTS_TARGET="-Dgl=disabled \ + -Dadder=disabled \ + -Dapp=disabled \ + -Daudioconvert=disabled \ + -Daudiomixer=disabled \ + -Daudiorate=disabled \ + -Daudioresample=disabled \ + -Daudiotestsrc=disabled \ + -Dcompositor=disabled \ + -Dencoding=disabled \ + -Dgio=disabled \ + -Dgio-typefinder=disabled \ + -Doverlaycomposition=disabled \ + -Dpbtypes=disabled \ + -Dplayback=disabled \ + -Drawparse=enabled \ + -Dsubparse=enabled \ + -Dtcp=disabled \ + -Dtypefind=disabled \ + -Dvideoconvertscale=disabled \ + -Dvideorate=disabled \ + -Dvideotestsrc=disabled \ + -Dvolume=disabled \ + -Dalsa=disabled \ + -Dcdparanoia=disabled \ + -Dlibvisual=disabled \ + -Dogg=disabled \ + -Dopus=disabled \ + -Dpango=disabled \ + -Dtheora=disabled \ + -Dtremor=disabled \ + -Dvorbis=disabled \ + -Dx11=disabled \ + -Dxshm=disabled \ + -Dxi=disabled \ + -Dxvideo=disabled \ + -Dexamples=disabled \ + -Dtests=disabled \ + -Dtools=disabled \ + -Dintrospection=disabled \ + -Dnls=disabled \ + -Dorc=disabled \ + -Dglib_debug=disabled \ + -Dglib_assert=false \ + -Dglib_checks=false \ + -Dpackage-name=gst-plugins-base \ + -Dpackage-origin=LibreELEC.tv \ + -Ddoc=disabled" +} + +post_makeinstall_target() { + # clean up + safe_remove ${INSTALL} +} diff --git a/packages/multimedia/gstreamer/gstreamer/package.mk b/packages/multimedia/gstreamer/gstreamer/package.mk new file mode 100644 index 0000000000..dbb68b2f5a --- /dev/null +++ b/packages/multimedia/gstreamer/gstreamer/package.mk @@ -0,0 +1,46 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="gstreamer" +PKG_VERSION="1.27.1" +PKG_SHA256="ac89913f5c39c4b216515814e63b54e865953a37dacfe149afaacdfbeb39a9f1" +PKG_LICENSE="GPL-2.1-or-later" +PKG_SITE="https://gstreamer.freedesktop.org" +PKG_URL="https://gstreamer.freedesktop.org/src/gstreamer/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain glib" +PKG_LONGDESC="GStreamer open-source multimedia framework core library" + +pre_configure_target() { + PKG_MESON_OPTS_TARGET="-Dgst_debug=false \ + -Dgst_parse=true \ + -Dregistry=false \ + -Dtracer_hooks=false \ + -Doption-parsing=true \ + -Dpoisoning=false \ + -Dcheck=disabled \ + -Dlibunwind=disabled \ + -Dlibdw=disabled \ + -Ddbghelp=disabled \ + -Dbash-completion=disabled \ + -Dcoretracers=disabled \ + -Dexamples=disabled \ + -Dtests=disabled \ + -Dbenchmarks=disabled \ + -Dtools=disabled \ + -Ddoc=disabled \ + -Dintrospection=disabled \ + -Dnls=disabled \ + -Dglib_debug=disabled \ + -Dglib_assert=false \ + -Dglib_checks=false \ + -Dextra-checks=disabled \ + -Dpackage-name="gstreamer" + -Dpackage-origin="LibreELEC.tv" + -Ddoc=disabled" +} + +post_makeinstall_target() { + # clean up + safe_remove ${INSTALL}/usr/share + safe_remove ${INSTALL}/usr/lib/{libgstcontroller-1.0*,libgstnet-1.0*} +} diff --git a/packages/multimedia/libaacs/package.mk b/packages/multimedia/libaacs/package.mk new file mode 100644 index 0000000000..df3f9b7ba1 --- /dev/null +++ b/packages/multimedia/libaacs/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="libaacs" +PKG_VERSION="0.11.1" +PKG_SHA256="a88aa0ebe4c98a77f7aeffd92ab3ef64ac548c6b822e8248a8b926725bea0a39" +PKG_LICENSE="GPL" +PKG_SITE="http://www.videolan.org/developers/libaacs.html" +PKG_URL="https://download.videolan.org/pub/videolan/libaacs/${PKG_VERSION}/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain libgcrypt" +PKG_LONGDESC="Open implementation of the AACS (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_configure_target() { + libtool_remove_rpath libtool +} + +post_makeinstall_target() { + mkdir -p ${INSTALL}/usr/config/aacs + cp -P ../KEYDB.cfg ${INSTALL}/usr/config/aacs +} diff --git a/packages/multimedia/libass/package.mk b/packages/multimedia/libass/package.mk new file mode 100644 index 0000000000..ef61de937e --- /dev/null +++ b/packages/multimedia/libass/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) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libass" +PKG_VERSION="0.17.4" +PKG_SHA256="78f1179b838d025e9c26e8fef33f8092f65611444ffa1bfc0cfac6a33511a05a" +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 harfbuzz" +PKG_LONGDESC="A portable subtitle renderer for the ASS/SSA (Advanced Substation Alpha/Substation Alpha) subtitle format." +PKG_TOOLCHAIN="configure" + +PKG_CONFIGURE_OPTS_TARGET="--disable-test \ + --enable-fontconfig \ + --disable-libunibreak \ + --disable-silent-rules \ + --with-gnu-ld" + +if [ ${TARGET_ARCH} = "x86_64" ]; then + PKG_DEPENDS_TARGET+=" nasm:host" + PKG_CONFIGURE_OPTS_TARGET+=" --enable-asm" +fi + +post_configure_target() { + libtool_remove_rpath libtool +} diff --git a/packages/multimedia/libbdplus/package.mk b/packages/multimedia/libbdplus/package.mk new file mode 100644 index 0000000000..fbac5c8d66 --- /dev/null +++ b/packages/multimedia/libbdplus/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="libbdplus" +PKG_VERSION="0.2.0" +PKG_SHA256="b93eea3eaef33d6e9155d2c34b068c505493aa5a4936e63274f4342ab0f40a58" +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+=" libaacs" + PKG_CONFIGURE_OPTS_TARGET+=" --with-libaacs" +else + PKG_CONFIGURE_OPTS_TARGET+=" --without-libaacs" +fi + +post_configure_target() { + libtool_remove_rpath libtool +} diff --git a/packages/multimedia/libbluray/package.mk b/packages/multimedia/libbluray/package.mk new file mode 100644 index 0000000000..ea66d5e48b --- /dev/null +++ b/packages/multimedia/libbluray/package.mk @@ -0,0 +1,45 @@ +# 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.3.4" +PKG_SHA256="478ffd68a0f5dde8ef6ca989b7f035b5a0a22c599142e5cd3ff7b03bbebe5f2b" +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 libudfread" +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+=" libaacs" +fi + +if [ "${BLURAY_BDPLUS_SUPPORT}" = "yes" ]; then + 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" + +post_configure_target() { + libtool_remove_rpath libtool +} 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 0000000000..6bed54d3d0 --- /dev/null +++ b/packages/multimedia/libbluray/patches/libbluray-00-fix-build-with-autoconf-archive-2016-or-later.patch @@ -0,0 +1,25 @@ +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(-) + +--- 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 + diff --git a/packages/multimedia/libbluray/patches/libbluray-03-set-headless-false.patch b/packages/multimedia/libbluray/patches/libbluray-03-set-headless-false.patch new file mode 100644 index 0000000000..7c27413409 --- /dev/null +++ b/packages/multimedia/libbluray/patches/libbluray-03-set-headless-false.patch @@ -0,0 +1,27 @@ +From 29be28f8062baca2856742a8f7ad2594981cf128 Mon Sep 17 00:00:00 2001 +From: Peter Vicman +Date: Mon, 27 Sep 2021 19:59:20 +0200 +Subject: [PATCH] disable X11 check because it will not run in headless mode + +https://github.com/fandangos/libbluray/commit/47726b99922899bb9c4ea688356199f2068d156a +https://github.com/PojavLauncherTeam/PojavLauncher/issues/713#issuecomment-769816262 + +temporary folder is set to /storage/.kodi/userdata/addon_data/tools.jre.zulu/libbluray-bdj-cache + +--- + src/libbluray/bdj/bdj.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/src/libbluray/bdj/bdj.c ++++ b/src/libbluray/bdj/bdj.c +@@ -903,6 +903,10 @@ static int _create_jvm(void *jvm_lib, co + option[n++].optionString = str_dup ("-Xms256M"); + option[n++].optionString = str_dup ("-Xmx256M"); + option[n++].optionString = str_dup ("-Xss2048k"); ++ option[n++].optionString = str_dup ("-Djava.io.tmpdir=/storage/.kodi/userdata/addon_data/tools.jre.zulu"); ++ BD_DEBUG(DBG_BDJ | DBG_CRIT, "Use /storage/.kodi/userdata/addon_data/tools.jre.zulu as cache dir.\n"); ++ option[n++].optionString = str_dup ("-Djava.awt.headless=false"); ++ BD_DEBUG(DBG_CRIT | DBG_BDJ, "Disable X11 check\n"); + #ifdef HAVE_BDJ_J2ME + option[n++].optionString = str_printf("-Djava.home=%s", java_home); + option[n++].optionString = str_printf("-Xbootclasspath/a:%s/lib/xmlparser.jar", java_home); diff --git a/packages/multimedia/libdvdcss/package.mk b/packages/multimedia/libdvdcss/package.mk new file mode 100644 index 0000000000..ee588dec67 --- /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.3-Next-Nexus-Alpha2-2" +PKG_SHA256="f38c4a4e7a4f4da6d8e83b8852489aa3bb6588a915dc41f5ee89d9aad305a06e" +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 0000000000..18d47b251b --- /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="6.1.1-Next-Nexus-Alpha2-2" +PKG_SHA256="584f62a3896794408d46368e2ecf2c6217ab9c676ce85921b2d68b8961f49dfc" +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 0000000000..fb9a364e41 --- /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="6.1.3-Next-Nexus-Alpha2-2" +PKG_SHA256="719130091e3adc9725ba72df808f24a14737a009dca5a4c38c601c0c76449b62" +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+=" libdvdcss" +fi diff --git a/packages/multimedia/libmpeg2/package.mk b/packages/multimedia/libmpeg2/package.mk new file mode 100644 index 0000000000..7eef92c225 --- /dev/null +++ b/packages/multimedia/libmpeg2/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="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_HOST="toolchain:host" +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/libudfread/package.mk b/packages/multimedia/libudfread/package.mk new file mode 100644 index 0000000000..01f3f1efbc --- /dev/null +++ b/packages/multimedia/libudfread/package.mk @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2020-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libudfread" +PKG_VERSION="1.1.2" +PKG_SHA256="2bf16726ac98d093156195bb049a663e07d3323e079c26912546f4e05c77bac5" +PKG_LICENSE="LGPLv2.1" +PKG_SITE="https://code.videolan.org/videolan/libudfread" +PKG_URL="https://code.videolan.org/videolan/${PKG_NAME}/-/archive/${PKG_VERSION}/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="UDF reader" +PKG_TOOLCHAIN="autotools" +PKG_BUILD_FLAGS="+pic" + +PKG_CONFIGURE_OPTS_TARGET="--enable-static --disable-shared" diff --git a/packages/multimedia/libva/package.mk b/packages/multimedia/libva/package.mk new file mode 100644 index 0000000000..6497f8fc87 --- /dev/null +++ b/packages/multimedia/libva/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) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libva" +PKG_VERSION="2.22.0" +PKG_SHA256="467c418c2640a178c6baad5be2e00d569842123763b80507721ab87eb7af8735" +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)." + +if [ "${DISPLAYSERVER}" = "x11" ]; then + PKG_DEPENDS_TARGET="toolchain libX11 libXext libXfixes libdrm" + DISPLAYSERVER_LIBVA="-Dwith_x11=yes -Dwith_glx=no -Dwith_wayland=no" +elif [ "${DISPLAYSERVER}" = "wl" ]; then + DISPLAYSERVER_LIBVA="-Dwith_x11=no -Dwith_glx=no -Dwith_wayland=yes" + PKG_DEPENDS_TARGET="toolchain libdrm wayland" +else + PKG_DEPENDS_TARGET="toolchain libdrm" + DISPLAYSERVER_LIBVA="-Dwith_x11=no -Dwith_glx=no -Dwith_wayland=no" +fi + +PKG_MESON_OPTS_TARGET="-Ddisable_drm=false \ + -Denable_docs=false \ + ${DISPLAYSERVER_LIBVA}" diff --git a/packages/multimedia/libvdpau/package.mk b/packages/multimedia/libvdpau/package.mk new file mode 100644 index 0000000000..449ce3f4b4 --- /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.5" +PKG_SHA256="a5d50a42b8c288febc07151ab643ac8de06a18446965c7241f89b4e810821913" +PKG_LICENSE="MIT" +PKG_SITE="https://wiki.freedesktop.org/www/Software/VDPAU/" +PKG_URL="https://gitlab.freedesktop.org/vdpau/libvdpau/-/archive/${PKG_VERSION}/libvdpau-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain libX11 xorgproto libXext" +PKG_LONGDESC="VDPAU is the Video Decode and Presentation API for UNIX." + +PKG_MESON_OPTS_TARGET="-Ddocumentation=false \ + -Ddri2=true \ + -Dmoduledir=/usr/lib/vdpau" diff --git a/packages/multimedia/nv-codec-headers/package.mk b/packages/multimedia/nv-codec-headers/package.mk new file mode 100644 index 0000000000..bb430f9a60 --- /dev/null +++ b/packages/multimedia/nv-codec-headers/package.mk @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="nv-codec-headers" +PKG_VERSION="13.0.19.0" +PKG_SHA256="86d15d1a7c0ac73a0eafdfc57bebfeba7da8264595bf531cf4d8db1c22940116" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/FFmpeg/nv-codec-headers" +PKG_URL="https://github.com/FFmpeg/nv-codec-headers/archive/n${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="FFmpeg version of headers required to interface with Nvidias codec APIs." + +makeinstall_target() { + make DESTDIR=${SYSROOT_PREFIX} PREFIX=/usr install +} diff --git a/packages/multimedia/nvidia-vaapi-driver/package.mk b/packages/multimedia/nvidia-vaapi-driver/package.mk new file mode 100644 index 0000000000..bc5116bc9d --- /dev/null +++ b/packages/multimedia/nvidia-vaapi-driver/package.mk @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="nvidia-vaapi-driver" +PKG_VERSION="0.0.14" +PKG_SHA256="4ded132ec4164f3e05656061675dffce677327e4af0d8da33da5f8527609ad2a" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/elFarto/nvidia-vaapi-driver" +PKG_URL="https://github.com/elFarto/nvidia-vaapi-driver/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain libva nv-codec-headers gst-plugins-bad" +PKG_LONGDESC="A VA-API implementation using NVIDIA's NVDEC" diff --git a/packages/multimedia/rtmpdump/package.mk b/packages/multimedia/rtmpdump/package.mk new file mode 100644 index 0000000000..7b7449e2b2 --- /dev/null +++ b/packages/multimedia/rtmpdump/package.mk @@ -0,0 +1,72 @@ +# 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="rtmpdump" +PKG_VERSION="6f6bb1353fc84f4cc37138baa99f586750028a01" +PKG_SHA256="be2d9a4e0979509341a267d3bd44b303081f7916f2681bbc3f1b62cb44550218" +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/zvbi/package.mk b/packages/multimedia/zvbi/package.mk new file mode 100644 index 0000000000..3b97250b65 --- /dev/null +++ b/packages/multimedia/zvbi/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2020-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="zvbi" +PKG_VERSION="0.2.44" +PKG_SHA256="bca620ab670328ad732d161e4ce8d9d9fc832533cb7440e98c50e112b805ac5e" +PKG_LICENSE="GPL2" +PKG_SITE="https://github.com/zapping-vbi/zvbi" +PKG_URL="https://github.com/zapping-vbi/zvbi/archive/refs/tags/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain libpng zlib" +PKG_LONGDESC="Library to provide functions to capture and decode VBI data." +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="--disable-dvb \ + --disable-bktr \ + --disable-examples \ + --disable-nls \ + --disable-proxy \ + --disable-tests \ + --disable-examples \ + --without-doxygen \ + --without-x" diff --git a/packages/multimedia/zvbi/patches/zvbi-0010-fix-static-linking.patch b/packages/multimedia/zvbi/patches/zvbi-0010-fix-static-linking.patch new file mode 100644 index 0000000000..3bfa6fde15 --- /dev/null +++ b/packages/multimedia/zvbi/patches/zvbi-0010-fix-static-linking.patch @@ -0,0 +1,11 @@ +--- a/configure.ac ++++ b/configure.ac +@@ -244,7 +244,7 @@ dnl (PNG page export) + dnl + HAVE_PNG="yes" + AC_CHECK_LIB(png, png_destroy_write_struct, +- LIBS="$LIBS -lpng -lz", HAVE_PNG="no", -lz -lm) ++ LIBS="-lpng $LIBS -lz -lm", HAVE_PNG="no", -lz -lm) + if test "x$HAVE_PNG" = xyes; then + AC_DEFINE(HAVE_LIBPNG, 1, [Define if you have libpng]) + fi diff --git a/packages/multimedia/zvbi/patches/zvbi-0020-gettext.patch b/packages/multimedia/zvbi/patches/zvbi-0020-gettext.patch new file mode 100644 index 0000000000..88e72e2346 --- /dev/null +++ b/packages/multimedia/zvbi/patches/zvbi-0020-gettext.patch @@ -0,0 +1,11 @@ +--- a/configure.ac 2025-02-26 20:29:12.903050209 +0000 ++++ b/configure.ac 2025-02-26 20:29:06.246129502 +0000 +@@ -499,7 +499,7 @@ + # If issues found with using a different gettext version than below and + # performing a crossbuild, update AM_GNU_GETTEXT_VERSION to match and + # run autogen.sh to update necessary files. +-AM_GNU_GETTEXT_VERSION([0.21]) ++AM_GNU_GETTEXT_VERSION([0.24]) + AM_GNU_GETTEXT([external], [need-ngettext]) + LIBS="$LTLIBINTL $LIBS" + if test "x${prefix}" = xNONE; then diff --git a/packages/multimedia/zvbi/patches/zvbi-0030-ssize_max.patch b/packages/multimedia/zvbi/patches/zvbi-0030-ssize_max.patch new file mode 100644 index 0000000000..efad9aa898 --- /dev/null +++ b/packages/multimedia/zvbi/patches/zvbi-0030-ssize_max.patch @@ -0,0 +1,28 @@ +Linear memory extents over SSIZE_MAX are undefined, so there is no +point in protecting against them. +--- a/src/export.c ++++ b/src/export.c +@@ -1056,8 +1056,6 @@ + size_t count; + + count = src_size; +- if (unlikely (src_size > SSIZE_MAX)) +- count = SSIZE_MAX & -4096; + + for (retry = 10;; --retry) { + actual = write (e->_handle.fd, src, count); +@@ -1614,12 +1612,7 @@ + free (e->buffer.data); + } + +- if (unlikely (e->buffer.offset > (size_t) SSIZE_MAX)) { +- errno = EOVERFLOW; +- actual = -1; /* failed */ +- } else { +- actual = e->buffer.offset; +- } ++ actual = e->buffer.offset; + } else { + if (VBI_EXPORT_TARGET_ALLOC == e->target) + free (e->buffer.data); + diff --git a/packages/multimedia/zvbi/patches/zvbi-0040-fix-clang-support.patch b/packages/multimedia/zvbi/patches/zvbi-0040-fix-clang-support.patch new file mode 100644 index 0000000000..42ace29b2b --- /dev/null +++ b/packages/multimedia/zvbi/patches/zvbi-0040-fix-clang-support.patch @@ -0,0 +1,29 @@ +--- a/src/misc.h ++++ b/src/misc.h +@@ -52,17 +52,6 @@ + # define unlikely(expr) __builtin_expect(expr, 0) + #endif + +-#undef __i386__ +-#undef __i686__ +-/* FIXME #cpu is deprecated +-#if #cpu (i386) +-# define __i386__ 1 +-#endif +-#if #cpu (i686) +-# define __i686__ 1 +-#endif +-*/ +- + /* &x == PARENT (&x.tm_min, struct tm, tm_min), + safer than &x == (struct tm *) &x.tm_min. A NULL _ptr is safe and + will return NULL, not -offsetof(_member). */ +@@ -156,8 +145,6 @@ + + #define likely(expr) (expr) + #define unlikely(expr) (expr) +-#undef __i386__ +-#undef __i686__ + + static char * + PARENT_HELPER (char *p, unsigned int offset) diff --git a/packages/network/avahi/debug.d/avahi.conf b/packages/network/avahi/debug.d/avahi.conf new file mode 100644 index 0000000000..5917ec5ef0 --- /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 0000000000..e69de29bb2 diff --git a/packages/network/avahi/package.mk b/packages/network/avahi/package.mk new file mode 100644 index 0000000000..145ea80557 --- /dev/null +++ b/packages/network/avahi/package.mk @@ -0,0 +1,101 @@ +# 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="autotools:host gcc:host 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 \ + --disable-rpath \ + --with-xml=expat \ + --with-avahi-user=avahi \ + --with-avahi-group=avahi \ + --disable-nls" + +pre_configure_target() { + NOCONFIGURE=1 ./autogen.sh +} + +post_configure_target() { + libtool_remove_rpath libtool +} + +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 + if [ ! ${SFTP_SERVER} = "yes" ]; then + rm -rf ${INSTALL}/etc/avahi/services/ssh.service + 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 70 70 "avahi-daemon" "/var/run/avahi-daemon" "/bin/sh" + add_group avahi 70 + + enable_service avahi-defaults.service + enable_service avahi-daemon.service +} diff --git a/packages/network/avahi/patches/avahi-0001-dbus--Use-non-deprecated-installation-path.patch b/packages/network/avahi/patches/avahi-0001-dbus--Use-non-deprecated-installation-path.patch new file mode 100644 index 0000000000..419cbb2a62 --- /dev/null +++ b/packages/network/avahi/patches/avahi-0001-dbus--Use-non-deprecated-installation-path.patch @@ -0,0 +1,30 @@ +From 0ab222c6601535f078f88e9d72b2c70cba03de23 Mon Sep 17 00:00:00 2001 +From: Jan Tojnar +Date: Sat, 21 May 2022 19:02:11 +0200 +Subject: [PATCH] dbus: Use non-deprecated installation path + +Quoting from D-Bus 1.14.0 release notes: + +> Third-party software should install default dbus policies for the system +> bus into ${datadir}/dbus-1/system.d (this has been supported since dbus +> 1.10, released in August 2015). Installing default dbus policies in +> ${sysconfdir}/dbus-1/system.d is now considered to be deprecated. + +https://gitlab.freedesktop.org/dbus/dbus/-/blob/dbus-1.14.0/NEWS#L45-51 +--- + configure.ac | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/configure.ac b/configure.ac +index 58db8c70f..959e96768 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -674,7 +674,7 @@ if test "x$HAVE_DBUS" = "xyes" ; then + if ! test -z "$with_dbus_sys" ; then + DBUS_SYS_DIR="$with_dbus_sys" + else +- DBUS_SYS_DIR="${sysconfdir}/dbus-1/system.d" ++ DBUS_SYS_DIR="${datadir}/dbus-1/system.d" + fi + AC_SUBST(DBUS_SYS_DIR) + 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 0000000000..54e2a9d046 --- /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/archr/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 0000000000..2db5833be3 --- /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 0000000000..d0cf58bd73 --- /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 0000000000..b78fd35c02 --- /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 0000000000..e69de29bb2 diff --git a/packages/network/bluez/package.mk b/packages/network/bluez/package.mk new file mode 100644 index 0000000000..572047997b --- /dev/null +++ b/packages/network/bluez/package.mk @@ -0,0 +1,83 @@ +# 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="bluez" +PKG_VERSION="5.83" +PKG_SHA256="108522d909d220581399bfec93daab62035539ceef3dda3e79970785c63bd24c" +PKG_LICENSE="GPL" +PKG_SITE="http://www.bluez.org/" +PKG_URL="https://www.kernel.org/pub/linux/bluetooth/${PKG_NAME}-${PKG_VERSION}.tar.xz" +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+=" --enable-monitor --enable-test" + +PKG_CONFIGURE_OPTS_TARGET="--disable-dependency-tracking \ + --disable-silent-rules \ + --enable-library \ + --enable-udev \ + --disable-cups \ + --disable-obex \ + --enable-client \ + --enable-systemd \ + --enable-tools \ + --enable-deprecated \ + --enable-datafiles \ + --disable-manpages \ + --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_configure_target() { + libtool_remove_rpath libtool +} + +post_makeinstall_target() { + safe_remove ${INSTALL}/usr/lib/systemd + safe_remove ${INSTALL}/usr/bin/bluemoon + safe_remove ${INSTALL}/usr/bin/ciptool + + 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" \ + -e "s|^#JustWorksRepairing.*|JustWorksRepairing=always|g" + echo "[General]" >${INSTALL}/etc/bluetooth/input.conf + echo "ClassicBondedOnly=false" >>${INSTALL}/etc/bluetooth/input.conf + + 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 + + # pulseaudio checks for bluez via pkgconfig but lib is not actually needed + sed -i 's/-lbluetooth//g' ${PKG_BUILD}/lib/bluez.pc + cp -P ${PKG_BUILD}/lib/bluez.pc ${SYSROOT_PREFIX}/usr/lib/pkgconfig +} + +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 0000000000..6fd94b998e --- /dev/null +++ b/packages/network/bluez/patches/bluez-01_add-obexd-policy.patch @@ -0,0 +1,29 @@ +diff --git a/src/bluetooth.conf b/src/bluetooth.conf +index 8a1e258..31b7542 100644 +--- a/src/bluetooth.conf ++++ b/src/bluetooth.conf +@@ -21,10 +21,24 @@ + + + ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ + + + + ++ + + + 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 0000000000..6bad3b146f --- /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 0000000000..e583320ecc --- /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 0000000000..f9f827fe56 --- /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-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 0000000000..d3de493f2e --- /dev/null +++ b/packages/network/bluez/patches/bluez-11_sixaxis-fix-PID-navigation-controller.patch @@ -0,0 +1,57 @@ +From ccc0a0cba8a2fdb8cfb148276e7c9413a3e22dc8 Mon Sep 17 00:00:00 2001 +From: MilhouseVH +Date: Thu, 19 Sep 2019 22:48:19 +0100 +Subject: [PATCH] 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 | 8 +++++++- + profiles/input/sixaxis.h | 2 ++ + 2 files changed, 9 insertions(+), 1 deletion(-) + +diff --git a/plugins/sixaxis.c b/plugins/sixaxis.c +index 939fed7..f6baea7 100644 +--- a/plugins/sixaxis.c ++++ b/plugins/sixaxis.c +@@ -354,7 +354,13 @@ static bool setup_device(int fd, const char *sysfs_path, + 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); +diff --git a/profiles/input/sixaxis.h b/profiles/input/sixaxis.h +index 8e6f3cc..321a918 100644 +--- a/profiles/input/sixaxis.h ++++ b/profiles/input/sixaxis.h +@@ -25,6 +25,7 @@ struct cable_pairing { + uint16_t vid; + uint16_t pid; + uint16_t version; ++ uint16_t bt_pid; + CablePairingType type; + }; + +@@ -54,6 +55,7 @@ get_pairing(uint16_t vid, uint16_t pid) + .vid = 0x054c, + .pid = 0x042f, + .version = 0x0000, ++ .bt_pid = 0x0268, + .type = CABLE_PAIRING_SIXAXIS, + }, + { +-- +2.7.4 + diff --git a/packages/network/bluez/patches/bluez-12-fix-obexd-after-5_73.patch b/packages/network/bluez/patches/bluez-12-fix-obexd-after-5_73.patch new file mode 100644 index 0000000000..4023c97bd5 --- /dev/null +++ b/packages/network/bluez/patches/bluez-12-fix-obexd-after-5_73.patch @@ -0,0 +1,41 @@ +diff --git a/Makefile.obexd b/Makefile.obexd +index b7e9f2d33..9a9e9a0a0 100644 +--- a/Makefile.obexd ++++ b/Makefile.obexd +@@ -1,6 +1,4 @@ + # SPDX-License-Identifier: GPL-2.0 +-if OBEX +- + if SYSTEMD + systemduserunit_DATA += obexd/src/obex.service + +@@ -40,6 +38,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 + +@@ -56,6 +56,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 +@@ -107,11 +109,6 @@ obexd_src_obexd_CPPFLAGS = $(AM_CPPFLAGS) $(GLIB_CFLAGS) $(DBUS_CFLAGS) \ + -D_FILE_OFFSET_BITS=64 \ + -I$(builddir)/obexd/src + +-else +-obexd-add-service-symlink: +-obexd-remove-service-symlink: +-endif +- + if OBEX + if SYSTEMD + obexd_src_obexd_CPPFLAGS += -DSYSTEMD 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 0000000000..86839fa62c --- /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 +@@ -417,6 +417,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 +@@ -697,6 +697,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 +@@ -252,6 +252,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); +@@ -1082,6 +1087,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 }, +@@ -1134,6 +1143,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 +@@ -56,6 +56,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, (size_t *)&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 0000000000..7d751631ef --- /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 0000000000..171e204e02 --- /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/archr/debug/bluez.conf +ExecStart=/usr/lib/bluetooth/bluetoothd $BLUEZ_ARGS $BLUEZ_DEBUG +CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_FOWNER +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 0000000000..6e418d9cfe --- /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/archr/debug/obexd.conf +ExecStartPre=/bin/sh -c 'mkdir -p $OBEXD_ROOT' +ExecStart=/usr/lib/bluetooth/obexd -s -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 0000000000..f0df6f4b3e --- /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/cifs-utils/package.mk b/packages/network/cifs-utils/package.mk new file mode 100644 index 0000000000..dd2eadb894 --- /dev/null +++ b/packages/network/cifs-utils/package.mk @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="cifs-utils" +PKG_VERSION="7.4" +PKG_SHA256="53353d05c30b4fc9dac006a8f0c5054cdd8a1834c176313c91e4694025c4b891" +PKG_LICENSE="GPL-3.0-or-later" +PKG_SITE="https://wiki.samba.org/index.php/LinuxCIFS_utils" +PKG_URL="https://download.samba.org/pub/linux-cifs/cifs-utils/cifs-utils-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain talloc" +PKG_LONGDESC="Linux CIFS userspace utilities" +PKG_BUILD_FLAGS="-cfg-libs" +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="ac_cv_func_malloc_0_nonnull=yes \ + ac_cv_func_realloc_0_nonnull=yes \ + --disable-cifsupcall \ + --disable-cifscreds \ + --disable-cifsidmap \ + --disable-cifsacl \ + --disable-smbinfo \ + --disable-pythontools \ + --disable-pam \ + --disable-man \ + --disable-systemd" + +makeinstall_target() { + mkdir -p "${INSTALL}/usr/sbin/" + cp -PR mount.cifs "${INSTALL}/usr/sbin/" + ln -s mount.cifs "${INSTALL}/usr/sbin/mount.smb3" +} diff --git a/packages/network/connman/config/settings b/packages/network/connman/config/settings new file mode 100644 index 0000000000..632a97b7a0 --- /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 0000000000..86502aa3ea --- /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 0000000000..79254b6f1b --- /dev/null +++ b/packages/network/connman/package.mk @@ -0,0 +1,98 @@ +# 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="1.44" +PKG_SHA256="d751da9858a6e3dfe70d6c98e71ea4f5896e1c92c5e1b17f10d055eaeae0e452" +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="autotools:host gcc:host dbus glib iptables iwd readline" +PKG_LONGDESC="A modular network connection manager." +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="--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 \ + --disable-bluetooth \ + --disable-ofono \ + --disable-dundee \ + --disable-pacrunner \ + --disable-neard \ + --disable-wispr \ + --disable-tools \ + --disable-stats \ + --enable-client \ + --enable-datafiles \ + --with-dbusconfdir=/usr/share \ + --with-systemdunitdir=/usr/lib/systemd/system \ + --disable-silent-rules \ + --disable-wifi \ + --enable-iwd" + +if [ "${WIREGUARD_SUPPORT}" = "yes" ]; then + PKG_CONFIGURE_OPTS_TARGET+=" --enable-wireguard=builtin" +else + PKG_CONFIGURE_OPTS_TARGET+=" --disable-wireguard" +fi + +PKG_MAKE_OPTS_TARGET="storagedir=/storage/.cache/connman \ + vpn_storagedir=/storage/.config/wireguard \ + statedir=/run/connman" + +post_configure_target() { + libtool_remove_rpath libtool +} + +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 = ethernet,wifi|g" \ + -e "s|^# AllowHostnameUpdates.*|AllowHostnameUpdates = false|g" \ + -e "s|^# PersistentTetheringMode.*|PersistentTetheringMode = 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 0000000000..f78cc6d0e7 --- /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 +@@ -1490,8 +1490,6 @@ int __connman_device_init(const char *device, const char *nodevice) + if (nodevice) + 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 0000000000..92f5280bf9 --- /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 +@@ -1243,10 +1243,7 @@ static struct connman_ipconfig *create_ipv6config(int index) + ipv6config->index = index; + 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) 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 0000000000..4d4d4f8d9e --- /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 +@@ -312,7 +312,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 -ldl + endif + + noinst_PROGRAMS += 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 0000000000..361eb10351 --- /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/archr/resolv.conf ]; then + cat /run/archr/resolv.conf >/run/connman/resolv.conf +fi +rm -f /run/archr/resolv.conf +ln -s /run/connman/resolv.conf /run/archr/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 0000000000..6711bd4b68 --- /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 0000000000..702654a3fd --- /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/archr/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 0000000000..935f638938 --- /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 0000000000..ebadc7ae17 --- /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 0000000000..eed8f1bd8e --- /dev/null +++ b/packages/network/ethtool/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="ethtool" +PKG_VERSION="6.15" +PKG_SHA256="9477c365114d910120aaec5336a1d16196c833d8486f7c6da67bedef57880ade" +PKG_LICENSE="GPL" +PKG_SITE="https://www.kernel.org/pub/software/network/ethtool/" +PKG_URL="https://www.kernel.org/pub/software/network/ethtool/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain libmnl" +PKG_LONGDESC="Ethtool is used for querying settings of an ethernet device and changing them." +PKG_BUILD_FLAGS="-cfg-libs" 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 0000000000..add3a4a971 --- /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/ipset/package.mk b/packages/network/ipset/package.mk new file mode 100644 index 0000000000..de1c69f744 --- /dev/null +++ b/packages/network/ipset/package.mk @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2025-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="ipset" +PKG_VERSION="7.24" +PKG_SHA256="fbe3424dff222c1cb5e5c34d38b64524b2217ce80226c14fdcbb13b29ea36112" +PKG_LICENSE="GPL" +PKG_SITE="https://ipset.netfilter.org" +PKG_URL="https://ipset.netfilter.org/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="libmnl" +PKG_LONGDESC="IP sets are a framework inside the Linux kernel, which can be administered by the ipset utility" +PKG_IS_KERNEL_PKG="yes" + +PKG_CONFIGURE_OPTS_TARGET="--with-kbuild=$(kernel_path)" diff --git a/packages/network/iptables/config/README b/packages/network/iptables/config/README new file mode 100644 index 0000000000..77d75ff599 --- /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 0000000000..583a3e845e --- /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 0000000000..44074d0908 --- /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 0000000000..7872e8d4bd --- /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 0000000000..bddcccdd44 --- /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 0000000000..027b1c29ca --- /dev/null +++ b/packages/network/iptables/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="iptables" +PKG_VERSION="1.8.11" +PKG_SHA256="d87303d55ef8c92bcad4dd3f978b26d272013642b029425775f5bad1009fe7b2" +PKG_LICENSE="GPL" +PKG_SITE="https://www.netfilter.org/" +PKG_URL="https://www.netfilter.org/projects/iptables/files/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="autotools:host gcc:host linux:host libmnl libnftnl" +PKG_LONGDESC="IP packet filter administration." +PKG_TOOLCHAIN="autotools" + +post_configure_target() { + libtool_remove_rpath libtool +} + +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/archr + cp ${PKG_DIR}/scripts/iptables_helper ${INSTALL}/usr/lib/archr +} + +post_install() { + enable_service iptables.service +} diff --git a/packages/network/iptables/patches/iptables-0002-xshared-fix-for-build-in-sub-directory.patch b/packages/network/iptables/patches/iptables-0002-xshared-fix-for-build-in-sub-directory.patch new file mode 100644 index 0000000000..d008285449 --- /dev/null +++ b/packages/network/iptables/patches/iptables-0002-xshared-fix-for-build-in-sub-directory.patch @@ -0,0 +1,11 @@ +--- a/libxtables/xtables.c 2022-05-13 13:26:26.000000000 +0000 ++++ b/libxtables/xtables.c 2022-05-14 09:53:20.593250503 +0000 +@@ -49,7 +49,7 @@ + #include + #include + #include +-#include ++#include "../libiptc/linux_list.h" + + #ifndef NO_SHARED_LIBS + #include diff --git a/packages/network/iptables/scripts/iptables_helper b/packages/network/iptables/scripts/iptables_helper new file mode 100755 index 0000000000..f4edda01ec --- /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 0000000000..6a8c189ad1 --- /dev/null +++ b/packages/network/iptables/system.d/iptables.service @@ -0,0 +1,17 @@ +[Unit] +Description=IPTABLES Packet Filtering +ConditionPathExists=/usr/lib/archr/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/archr/iptables_helper enable +ExecReload=/usr/lib/archr/iptables_helper enable +ExecStop=/usr/lib/archr/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 0000000000..0271ff0a00 --- /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="6.9" +PKG_SHA256="3f2db22ad41c675242b98ae3942dbf3112548c60a42ff739210f2de4e98e4894" +PKG_LICENSE="PUBLIC_DOMAIN" +PKG_SITE="http://wireless.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 0000000000..538bfddb51 --- /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 0000000000..a9f929c45b --- /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/iwd/package.mk b/packages/network/iwd/package.mk new file mode 100644 index 0000000000..5e8327dde9 --- /dev/null +++ b/packages/network/iwd/package.mk @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="iwd" +PKG_VERSION="3.9" +PKG_SHA256="0cd7dc9b32b9d6809a4a5e5d063b5c5fd279f5ad3a0bf03d7799da66df5cad45" +PKG_LICENSE="GPL" +PKG_SITE="https://git.kernel.org/cgit/network/wireless/iwd.git/about/" +PKG_URL="https://www.kernel.org/pub/linux/network/wireless/iwd-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="autotools:host gcc:host readline dbus" +PKG_LONGDESC="Wireless daemon for Linux" +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="--enable-client \ + --enable-monitor \ + --enable-systemd-service \ + --enable-dbus-policy \ + --disable-manual-pages" + +pre_configure_target() { + export LIBS="-lncurses" +} + +post_makeinstall_target() { + # ProtectSystem et al seems to break the service when systemd isn't built with seccomp. + # investigate this more as it might be a systemd problem or kernel problem + sed -e 's|^\(PrivateTmp=.*\)$|#\1|g' \ + -e 's|^\(NoNewPrivileges=.*\)$|#\1|g' \ + -e 's|^\(PrivateDevices=.*\)$|#\1|g' \ + -e 's|^\(ProtectHome=.*\)$|#\1|g' \ + -e 's|^\(ProtectSystem=.*\)$|#\1|g' \ + -e 's|^\(ReadWritePaths=.*\)$|#\1|g' \ + -e 's|^\(ProtectControlGroups=.*\)$|#\1|g' \ + -e 's|^\(ProtectKernelModules=.*\)$|#\1|g' \ + -e 's|^\(ConfigurationDirectory=.*\)$|#\1|g' \ + -i ${INSTALL}/usr/lib/systemd/system/iwd.service +} + +post_install() { + enable_service iwd.service +} diff --git a/packages/network/libdnet/package.mk b/packages/network/libdnet/package.mk new file mode 100644 index 0000000000..53d6972644 --- /dev/null +++ b/packages/network/libdnet/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) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libdnet" +PKG_VERSION="1.18.0" +PKG_SHA256="a4a82275c7d83b85b1daac6ebac9461352731922161f1dcdcccd46c318f583c9" +PKG_LICENSE="BSD" +PKG_SITE="https://github.com/ofalk/libdnet" +PKG_URL="https://github.com/ofalk/libdnet/archive/${PKG_NAME}-${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" + +pre_configure_target() { + PKG_CONFIGURE_OPTS_TARGET="--enable-static \ + --disable-shared \ + --enable-check=no" + + 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 0000000000..08a0821e10 --- /dev/null +++ b/packages/network/libmnl/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) 2022-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libmnl" +PKG_VERSION="1.0.5" +PKG_SHA256="274b9b919ef3152bfb3da3a13c950dd60d6e2bcd54230ffeca298d03b40d0525" +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="autotools:host gcc:host" +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 0000000000..3555595236 --- /dev/null +++ b/packages/network/libnfs/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="libnfs" +PKG_VERSION="6.0.2" +PKG_SHA256="4e5459cc3e0242447879004e9ad28286d4d27daa42cbdcde423248fad911e747" +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 \ + --without-libkrb5" + +pre_configure_target() { + export CFLAGS="${CFLAGS} -D_FILE_OFFSET_BITS=64" +} diff --git a/packages/network/libnfs/patches/libnfs-514-socket-use-void-cast-to-allow-compile-for-arm32.patch b/packages/network/libnfs/patches/libnfs-514-socket-use-void-cast-to-allow-compile-for-arm32.patch new file mode 100644 index 0000000000..807569aa80 --- /dev/null +++ b/packages/network/libnfs/patches/libnfs-514-socket-use-void-cast-to-allow-compile-for-arm32.patch @@ -0,0 +1,62 @@ +From a01d42a0d9682d3e506d3c78680db8c7d158fe88 Mon Sep 17 00:00:00 2001 +From: Rudi Heitbaum +Date: Tue, 14 Jan 2025 14:09:36 +0000 +Subject: [PATCH] socket: use void cast to allow compile for arm32 + +When compiling for arm32 the error: cast increases required alignment +of target type occurs. + +/lib/socket.c: In function 'rpc_read_from_socket': +lib/socket.c:586:49: error: cast increases required alignment of target type [-Werror=cast-align] + 586 | rpc->rm_xid[1] = ntohl(*(uint32_t *)&buf[0]); + | ^ +lib/socket.c:587:61: error: cast increases required alignment of target type [-Werror=cast-align] + 587 | rpc->pdu = rpc_find_pdu(rpc, ntohl(*(uint32_t *)&buf[0])); + | ^ +lib/socket.c:799:35: error: cast increases required alignment of target type [-Werror=cast-align] + 799 | *((uint32_t *)rpc->inbuf) = htonl(rpc->rm_xid[1]); + | ^ +lib/socket.c:861:71: error: cast increases required alignment of target type [-Werror=cast-align] + 861 | const READ3res *res = (READ3res *) rpc->pdu->zdr_decode_buf; + | ^ + +cast via (void *) to allow the compile to suceed, as all of the source buffers should be 32bit aligned. + +Signed-off-by: Rudi Heitbaum +--- + lib/socket.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/lib/socket.c b/lib/socket.c +index 8f5835cc..df6f329b 100644 +--- a/lib/socket.c ++++ b/lib/socket.c +@@ -583,8 +583,8 @@ rpc_read_from_socket(struct rpc_context *rpc) + } + if (!rpc->is_server_context) { + rpc->rm_xid[0] = count; +- rpc->rm_xid[1] = ntohl(*(uint32_t *)&buf[0]); +- rpc->pdu = rpc_find_pdu(rpc, ntohl(*(uint32_t *)&buf[0])); ++ rpc->rm_xid[1] = ntohl(*(uint32_t *)(void *)&buf[0]); ++ rpc->pdu = rpc_find_pdu(rpc, ntohl(*(uint32_t *)(void *)&buf[0])); + if (rpc->pdu == NULL) { + rpc_set_error(rpc, "Failed to match incoming PDU/XID." + " Ignoring PDU"); +@@ -796,7 +796,7 @@ rpc_read_from_socket(struct rpc_context *rpc) + } + + /* Copy the next 4 bytes into inbuf */ +- *((uint32_t *)rpc->inbuf) = htonl(rpc->rm_xid[1]); ++ *((uint32_t *)(void *)rpc->inbuf) = htonl(rpc->rm_xid[1]); + + /* but set inpos to 0, we will update it above + * that we have already read these 4 bytes in +@@ -858,7 +858,7 @@ rpc_read_from_socket(struct rpc_context *rpc) + * If the READ failed, bail out here as there is no + * data. + */ +- const READ3res *res = (READ3res *) rpc->pdu->zdr_decode_buf; ++ const READ3res *res = (READ3res *)(void *) rpc->pdu->zdr_decode_buf; + if (res->status != NFS3_OK) { + goto payload_finished; + } diff --git a/packages/network/libnftnl/package.mk b/packages/network/libnftnl/package.mk new file mode 100644 index 0000000000..75c639a252 --- /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.2.9" +PKG_SHA256="e8c216255e129f26270639fee7775265665a31b11aa920253c3e5d5d62dfc4b8" +PKG_LICENSE="GPL" +PKG_SITE="https://netfilter.org/projects/libnftnl" +PKG_URL="https://netfilter.org/projects/libnftnl/files/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="autotools:host gcc:host 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 0000000000..2ee3362e37 --- /dev/null +++ b/packages/network/libnl/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="libnl" +PKG_VERSION="3.11.0" +PKG_SHA256="2a56e1edefa3e68a7c00879496736fdbf62fc94ed3232c0baba127ecfa76874d" +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_BUILD_FLAGS="+pic" + +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 0000000000..78d51a5eb3 --- /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+=" -I${SYSROOT_PREFIX}/usr/include/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 0000000000..d7ecbd0b77 --- /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 0000000000..6c31a21b0c --- /dev/null +++ b/packages/network/libssh/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="libssh" +PKG_VERSION="0.11.2" +PKG_SHA256="69529fc18f5b601f0baf0e5a4501a2bc26df5e2f116f5f8f07f19fafaa6d04e7" +PKG_LICENSE="LGPL" +PKG_SITE="http://www.libssh.org/" +PKG_URL="https://www.libssh.org/files/$(get_pkg_version_maj_min)/${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="-DBUILD_SHARED_LIBS=OFF \ + -DWITH_SERVER=OFF \ + -DWITH_GCRYPT=OFF \ + -DWITH_EXAMPLES=OFF \ + -DWITH_GSSAPI=OFF \ + -DWITH_GEX=OFF \ + -DWITH_INTERNAL_DOC=OFF" + +makeinstall_target() { + # install static library only + mkdir -p ${SYSROOT_PREFIX}/usr/lib + cp ${PKG_BUILD}/.${TARGET_NAME}/src/libssh.a ${SYSROOT_PREFIX}/usr/lib + + mkdir -p ${SYSROOT_PREFIX}/usr/lib/pkgconfig + cp ${PKG_BUILD}/.${TARGET_NAME}/libssh.pc ${SYSROOT_PREFIX}/usr/lib/pkgconfig + + mkdir -p ${SYSROOT_PREFIX}/usr/include/libssh + cp ${PKG_BUILD}/include/libssh/{callbacks.h,legacy.h,libssh.h,server.h,sftp.h,ssh2.h} \ + ${PKG_BUILD}/.${TARGET_NAME}/include/libssh/libssh_version.h \ + ${SYSROOT_PREFIX}/usr/include/libssh +} diff --git a/packages/network/libtirpc/package.mk b/packages/network/libtirpc/package.mk new file mode 100644 index 0000000000..0967550a5d --- /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.3.6" +PKG_SHA256="bbd26a8f0df5690a62a47f6aa30f797f3ef8d02560d1bc449a83066b5a1d3508" +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/libtirpc/patches/libtirpc-0001-fix-build-with-gcc-15.patch b/packages/network/libtirpc/patches/libtirpc-0001-fix-build-with-gcc-15.patch new file mode 100644 index 0000000000..71d4e0c976 --- /dev/null +++ b/packages/network/libtirpc/patches/libtirpc-0001-fix-build-with-gcc-15.patch @@ -0,0 +1,35 @@ +--- a/src/auth_none.c 2024-11-20 09:02:12.504925593 +0000 ++++ b/src/auth_none.c 2024-11-20 09:03:45.129971786 +0000 +@@ -62,7 +62,7 @@ + static bool_t authnone_refresh (AUTH *, void *); + static void authnone_destroy (AUTH *); + +-extern bool_t xdr_opaque_auth(); ++extern bool_t xdr_opaque_auth(XDR *, struct opaque_auth *); + + static struct auth_ops *authnone_ops(); + +--- a/src/svc_auth_none.c 2024-11-20 09:10:27.426038143 +0000 ++++ b/src/svc_auth_none.c 2024-11-20 09:10:27.426038143 +0000 +@@ -37,8 +37,8 @@ + + #include + +-static bool_t svcauth_none_destroy(); +-static bool_t svcauth_none_wrap(); ++static bool_t svcauth_none_destroy(SVCAUTH *); ++static bool_t svcauth_none_wrap(SVCAUTH *, XDR *, bool_t (*)(XDR *, ...), char *); + + struct svc_auth_ops svc_auth_none_ops = { + svcauth_none_wrap, +--- a/src/getpublickey.c 2024-11-20 09:16:57.168954233 +0000 ++++ b/src/getpublickey.c 2024-11-20 09:16:57.168954233 +0000 +@@ -52,7 +52,7 @@ + /* + * Hack to let ypserv/rpc.nisd use AUTH_DES. + */ +-int (*__getpublickey_LOCAL)() = 0; ++int (*__getpublickey_LOCAL)(const char *, char *) = 0; + + /* + * Get somebody's public key diff --git a/packages/network/libtirpc/patches/libtirpc-0002-fix-build-with-gcc-15.patch b/packages/network/libtirpc/patches/libtirpc-0002-fix-build-with-gcc-15.patch new file mode 100644 index 0000000000..b81851dbb6 --- /dev/null +++ b/packages/network/libtirpc/patches/libtirpc-0002-fix-build-with-gcc-15.patch @@ -0,0 +1,35 @@ +--- libtirpc-1.3.6/src/auth_time.c 2024-10-17 07:50:55.000000000 +0000 ++++ libtirpc-1.3.6/src/auth_time.c 2024-12-12 13:55:14.420375907 +0000 +@@ -248,7 +248,7 @@ + char ut[64], ipuaddr[64]; + endpoint teps[32]; + nis_server tsrv; +- void (*oldsig)() = NULL; /* old alarm handler */ ++ void (*oldsig)(int) = NULL; /* old alarm handler */ + struct sockaddr_in sin; + int s = RPC_ANYSOCK; + socklen_t len; +@@ -417,7 +417,7 @@ + } else { + int res; + +- oldsig = (void (*)())signal(SIGALRM, alarm_hndler); ++ oldsig = (void (*)(int))signal(SIGALRM, alarm_hndler); + saw_alarm = 0; /* global tracking the alarm */ + alarm(20); /* only wait 20 seconds */ + res = connect(s, (struct sockaddr *)&sin, sizeof(sin)); +--- libtirpc-1.3.6/src/key_call.c 2024-10-17 07:50:55.000000000 +0000 ++++ libtirpc-1.3.6/src/key_call.c 2024-12-12 13:49:15.720634534 +0000 +@@ -72,9 +72,9 @@ + * implementations of these functions, and to call those in key_call(). + */ + +-cryptkeyres *(*__key_encryptsession_pk_LOCAL)() = 0; +-cryptkeyres *(*__key_decryptsession_pk_LOCAL)() = 0; +-des_block *(*__key_gendes_LOCAL)() = 0; ++cryptkeyres *(*__key_encryptsession_pk_LOCAL)(uid_t, char *) = 0; ++cryptkeyres *(*__key_decryptsession_pk_LOCAL)(uid_t, char *) = 0; ++des_block *(*__key_gendes_LOCAL)(uid_t, char *) = 0; + + static int key_call( u_long, xdrproc_t, void *, xdrproc_t, void *); + diff --git a/packages/network/netbase/package.mk b/packages/network/netbase/package.mk new file mode 100644 index 0000000000..de8b13a31b --- /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="6.5" +PKG_SHA256="9116047aebbaa1698934052d01c6e09b4c3aed643e93df63d2ddcbec243c26d1" +PKG_LICENSE="GPL" +PKG_SITE="https://salsa.debian.org/md/netbase" +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 + cp etc/services ${INSTALL}/etc +} diff --git a/packages/network/nfs-utils/package.mk b/packages/network/nfs-utils/package.mk new file mode 100644 index 0000000000..f0703181f9 --- /dev/null +++ b/packages/network/nfs-utils/package.mk @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="nfs-utils" +PKG_VERSION="2.8.3" +PKG_SHA256="11e7c5847a8423a72931c865bd9296e7fd56ff270a795a849183900961711725" +PKG_LICENSE="GPL-2.0-or-later" +PKG_SITE="http://www.linux-nfs.org/" +PKG_URL="https://www.kernel.org/pub/linux/utils/nfs-utils/${PKG_VERSION}/nfs-utils-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain keyutils libevent libnl libtirpc libxml2 rpcbind sqlite util-linux" +PKG_LONGDESC="Linux NFS userland utility package" + +PKG_CONFIGURE_OPTS_TARGET="--disable-gss \ + --disable-nfsv41 \ + --disable-nfsdcld \ + --disable-nfsrahead \ + --disable-nfsdcltrack \ + --disable-ldap" + +pre_configure_target() { + cd ${PKG_BUILD} + rm -rf .${TARGET_NAME} +} + +makeinstall_target() { + mkdir -p "${INSTALL}/usr/sbin/" + cp -PR utils/mount/mount.nfs "${INSTALL}/usr/sbin/" + ln -s mount.nfs "${INSTALL}/usr/sbin/mount.nfs4" + ln -s mount.nfs "${INSTALL}/usr/sbin/umount.nfs" + ln -s mount.nfs "${INSTALL}/usr/sbin/umount.nfs4" +} diff --git a/packages/network/nss-mdns/config/nsswitch.conf b/packages/network/nss-mdns/config/nsswitch.conf new file mode 100644 index 0000000000..d399c0ff42 --- /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 systemd +group: files [SUCCESS=merge] systemd +shadow: files systemd +gshadow: files systemd + +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 0000000000..67c7a08a43 --- /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.15.1" +PKG_SHA256="2d1b8de2e9ed5526f51c8bb627b719c07668465b5315787e7cfeed776ab90b9a" +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 0000000000..80d08333e1 --- /dev/null +++ b/packages/network/openssh/package.mk @@ -0,0 +1,62 @@ +# 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="10.0p2" +PKG_SHA256="021a2e709a0edf4250b1256bd5a9e500411a90dddabea830ed59cef90eb9d85c" +PKG_LICENSE="OSS" +PKG_SITE="https://www.openssh.com/" +PKG_URL="https://cdn.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 -cfg-libs" + +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() { + if [ "${SSH_ENABLED_DEFAULT}" = "yes" ]; then + sed -e "\|^Condition.*|d" -i ${INSTALL}/usr/lib/systemd/system/sshd.service + fi + enable_service sshd.service +} diff --git a/packages/network/openssh/patches/openssh-8.9p1-keydir.patch b/packages/network/openssh/patches/openssh-8.9p1-keydir.patch new file mode 100644 index 0000000000..017b3022c4 --- /dev/null +++ b/packages/network/openssh/patches/openssh-8.9p1-keydir.patch @@ -0,0 +1,117 @@ +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 +@@ -5355,6 +5355,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, +@@ -5754,6 +5767,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:" +@@ -5777,6 +5791,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" +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 +@@ -33,8 +33,10 @@ + TEST_SHELL=@TEST_SHELL@ + BUILDDIR=@abs_top_builddir@ + SK_STANDALONE=@SK_STANDALONE@ ++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)\" \ +@@ -192,11 +194,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' \ +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,12 +40,12 @@ + */ + #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/patches/openssh-silence-missing-identity-error.patch b/packages/network/openssh/patches/openssh-silence-missing-identity-error.patch new file mode 100644 index 0000000000..e7b01daf6a --- /dev/null +++ b/packages/network/openssh/patches/openssh-silence-missing-identity-error.patch @@ -0,0 +1,15 @@ +diff --git a/sshconnect2.c b/sshconnect2.c +index d6af0b9..22c0aa6 100644 +--- a/sshconnect2.c ++++ b/sshconnect2.c +@@ -1524,9 +1524,7 @@ + struct stat st; + + if (stat(id->filename, &st) == -1) { +- do_log2(id->userprovided ? +- SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_DEBUG3, +- "no such identity: %s: %s", id->filename, strerror(errno)); ++ debug3("no such identity: %s", id->filename); + return NULL; + } + snprintf(prompt, sizeof prompt, diff --git a/packages/network/openssh/patches/openssh-source-etc-environment.patch b/packages/network/openssh/patches/openssh-source-etc-environment.patch new file mode 100644 index 0000000000..b23ee72b8e --- /dev/null +++ b/packages/network/openssh/patches/openssh-source-etc-environment.patch @@ -0,0 +1,32 @@ +From c05ee9208db5e25d550ec6dd4b5ff54a199959fd Mon Sep 17 00:00:00 2001 +From: MilhouseVH +Date: Mon, 16 Dec 2019 20:34:22 +0000 +Subject: [PATCH] openssh: source /etc/environment + +--- + session.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/session.c b/session.c +index ac06b08..0a1c59a 100644 +--- a/session.c ++++ b/session.c +@@ -1080,7 +1080,6 @@ do_setup_env(struct ssh *ssh, Session *s, const char *shell) + child_set_env(&env, &envsize, "KRB5CCNAME", cp); + } + +-#ifdef _AIX + { + char *cp; + +@@ -1089,7 +1088,6 @@ do_setup_env(struct ssh *ssh, Session *s, const char *shell) + read_environment_file(&env, &envsize, "/etc/environment", + options.permit_user_env_whitelist); + } +-#endif + #ifdef KRB5 + if (s->authctxt->krb5_ccname) + child_set_env(&env, &envsize, "KRB5CCNAME", +-- +2.7.4 + diff --git a/packages/network/openssh/system.d/sshd.service b/packages/network/openssh/system.d/sshd.service new file mode 100644 index 0000000000..2aa45f8a06 --- /dev/null +++ b/packages/network/openssh/system.d/sshd.service @@ -0,0 +1,18 @@ +[Unit] +Description=OpenSSH server daemon +After=network.target +ConditionKernelCommandLine=|ssh +ConditionPathExists=|/storage/.cache/services/sshd.conf + +[Service] +Restart=on-failure +EnvironmentFile=-/storage/.cache/services/sshd.conf +ExecStartPre=/usr/bin/ssh-keygen -A +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 0000000000..baae3c6626 --- /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 0000000000..755b26b49b --- /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.6.14" +PKG_SHA256="9eb6a6618352f9e7b771a9d38ae1631b5edfeed6d40233e243e602ddf2195e7a" +PKG_LICENSE="GPL" +PKG_SITE="https://openvpn.net" +PKG_URL="https://swupdate.openvpn.org/community/releases/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain libcap-ng lz4 lzo openssl" +PKG_LONGDESC="A full featured SSL VPN software solution that integrates OpenVPN server capabilities." +PKG_TOOLCHAIN="configure" + +PKG_CONFIGURE_OPTS_TARGET="ac_cv_have_decl_TUNSETPERSIST=no \ + --disable-plugins \ + --enable-iproute2 IPROUTE=/sbin/ip \ + --enable-management \ + --enable-fragment \ + --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/rpcbind/package.mk b/packages/network/rpcbind/package.mk new file mode 100644 index 0000000000..1c430edd28 --- /dev/null +++ b/packages/network/rpcbind/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="rpcbind" +PKG_VERSION="1.2.7" +PKG_SHA256="f6edf8cdf562aedd5d53b8bf93962d61623292bfc4d47eedd3f427d84d06f37e" +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_BUILD_FLAGS="-cfg-libs" + +PKG_CONFIGURE_OPTS_TARGET="ac_cv_header_rpcsvc_mount_h=no \ + --disable-warmstarts \ + --disable-libwrap \ + --enable-rmtcalls \ + --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 0000000000..7ac5dd7c4f --- /dev/null +++ b/packages/network/rpcbind/patches/rpcbind-01-drop-warm-start-as-it-fails.patch @@ -0,0 +1,11 @@ +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 +@@ -8,6 +8,7 @@ + # rpcbind.socket, no matter how this unit is started. + Requires=rpcbind.socket + Wants=rpcbind.target ++After=rpcbind.socket systemd-tmpfiles-setup.service + + [Service] + Type=notify diff --git a/packages/network/rpcbind/patches/rpcbind-1.2.6-vulnerability_fixes-1.patch b/packages/network/rpcbind/patches/rpcbind-1.2.6-vulnerability_fixes-1.patch new file mode 100644 index 0000000000..d8137d3c96 --- /dev/null +++ b/packages/network/rpcbind/patches/rpcbind-1.2.6-vulnerability_fixes-1.patch @@ -0,0 +1,29 @@ +Submitted By: Ken Moffat +Date: 2017-05-29 +Initial Package Version: 0.2.4 (also affects earlier versions) +Upstream Status: Unknown +Origin: Guido Vranken +Description: Fixes CVE-2017-8779 (DOS by remote attackers - memory consumption +without subsequent free). + +diff --git a/src/rpcb_svc_com.c b/src/rpcb_svc_com.c +index 5862c26..e11f61b 100644 +--- a/src/rpcb_svc_com.c ++++ b/src/rpcb_svc_com.c +@@ -48,6 +48,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -432,7 +433,7 @@ rpcbproc_taddr2uaddr_com(void *arg, struct svc_req *rqstp /*__unused*/, + static bool_t + xdr_encap_parms(XDR *xdrs, struct encap_parms *epp) + { +- return (xdr_bytes(xdrs, &(epp->args), (u_int *) &(epp->arglen), ~0)); ++ return (xdr_bytes(xdrs, &(epp->args), (u_int *) &(epp->arglen), RPC_MAXDATASIZE)); + } + + /* diff --git a/packages/network/rsync/package.mk b/packages/network/rsync/package.mk new file mode 100644 index 0000000000..f833174649 --- /dev/null +++ b/packages/network/rsync/package.mk @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="rsync" +PKG_VERSION="3.4.1" +PKG_SHA256="2924bcb3a1ed8b551fc101f740b9f0fe0a202b115027647cf69850d65fd88c52" +PKG_LICENSE="GPLv3" +PKG_SITE="https://rsync.samba.org" +PKG_URL="https://download.samba.org/pub/rsync/src/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="autotools:host zlib:host" +PKG_DEPENDS_TARGET="toolchain zlib openssl" +PKG_LONGDESC="A very fast method for bringing remote files into sync." +PKG_BUILD_FLAGS="-sysroot -cfg-libs -cfg-libs:host" + +PKG_CONFIGURE_OPTS_HOST="--disable-md2man \ + --disable-ipv6 \ + --disable-openssl \ + --disable-xxhash \ + --disable-zstd \ + --disable-lz4 \ + --disable-iconv \ + --with-included-popt \ + --without-included-zlib" + +PKG_CONFIGURE_OPTS_TARGET="--disable-acl-support \ + --disable-md5-asm \ + --enable-openssl \ + --disable-lz4 \ + --disable-md2man \ + --disable-roll-simd \ + --disable-xattr-support \ + --disable-xxhash \ + --disable-zstd \ + --with-included-popt \ + --without-included-zlib" + +pre_make_host() { + # do not detect LE git version + echo "#define RSYNC_GITVER \"${PKG_VERSION}\"" >git-version.h +} + +pre_make_target() { + pre_make_host +} diff --git a/packages/network/samba/config/samba4-cache.txt b/packages/network/samba/config/samba4-cache.txt new file mode 100644 index 0000000000..d4deb25508 --- /dev/null +++ b/packages/network/samba/config/samba4-cache.txt @@ -0,0 +1,48 @@ +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 +Checking for gnutls fips mode support: NO +Checking for readlink breakage: NO +Checking whether fcntl supports setting/getting hints: OK diff --git a/packages/network/samba/config/smb.conf b/packages/network/samba/config/smb.conf new file mode 100644 index 0000000000..910e86562f --- /dev/null +++ b/packages/network/samba/config/smb.conf @@ -0,0 +1,147 @@ +# 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 = LibreELEC + 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 + guest account = root + 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/.update + available = yes + browseable = yes + public = yes + writeable = yes + +[Videos] + path = /storage/videos + available = yes + browseable = yes + public = yes + writeable = yes + +[Music] + path = /storage/music + available = yes + browseable = yes + public = yes + writeable = yes + +[TV Shows] + path = /storage/tvshows + available = yes + browseable = yes + public = yes + writeable = yes + +[Recordings] + path = /storage/recordings + available = yes + browseable = yes + public = yes + writeable = yes + +[Downloads] + path = /storage/downloads + available = yes + browseable = yes + public = yes + writeable = yes + +[Pictures] + path = /storage/pictures + available = yes + browseable = yes + public = yes + writeable = yes + +[Emulators] + path = /storage/emulators + available = yes + browseable = yes + public = yes + writeable = yes + +[Configfiles] + path = /storage/.config + available = yes + browseable = yes + public = yes + writeable = yes + +[Userdata] + path = /storage/.kodi/userdata + available = yes + browseable = yes + public = yes + writeable = yes + +[Screenshots] + path = /storage/screenshots + available = yes + browseable = yes + public = yes + writeable = yes + +[Logfiles] + path = /storage/logfiles + available = yes + browseable = yes + public = yes + writeable = yes + root preexec = createlog + +[Backup] + path = /storage/backup + available = yes + browseable = yes + public = yes + writeable = yes + +[Picons] + path = /storage/picons + available = yes + browseable = yes + public = yes + writeable = yes diff --git a/packages/network/samba/default.d/samba.conf b/packages/network/samba/default.d/samba.conf new file mode 100644 index 0000000000..9ad00368c3 --- /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 0000000000..46c8abd7fd --- /dev/null +++ b/packages/network/samba/package.mk @@ -0,0 +1,208 @@ +# 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.22.3" +PKG_SHA256="8fd7092629a3596d935cd7567d934979f94272918ec3affd0cc807934ecf22ba" +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="autotools:host gcc:host heimdal:host attr connman e2fsprogs gnutls libaio libunwind popt Python3 readline talloc wsdd2 zlib" +PKG_NEED_UNPACK="$(get_pkg_directory heimdal) $(get_pkg_directory e2fsprogs)" +PKG_LONGDESC="A free SMB / CIFS fileserver and client." + +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 + + 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 \ + --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-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+=",nmbd,rpcd_classic,rpcd_epmapper,rpcd_winreg,samba-dcerpcd,smbpasswd,smbd/smbd,vfs_fruit,vfs_catia,vfs_streams_xattr" + 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" + + # 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() { + make ${PKG_SAMBA_TARGET} -j${CONCURRENCY_MAKE_LEVEL} +} + +makeinstall_target() { + PYTHONHASHSEED=1 WAF_MAKE=1 ./buildtools/bin/waf install ${PKG_WAF_VERBOSE} --destdir=${SYSROOT_PREFIX} --targets=smbclient -j${CONCURRENCY_MAKE_LEVEL} + PYTHONHASHSEED=1 WAF_MAKE=1 ./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 + + mkdir -p ${INSTALL}/usr/libexec/samba + cp -PR bin/default/source3/rpc_server/samba-dcerpcd ${INSTALL}/usr/libexec/samba + cp -PR bin/default/source3/rpc_server/rpcd_classic ${INSTALL}/usr/libexec/samba + cp -PR bin/default/source3/rpc_server/rpcd_epmapper ${INSTALL}/usr/libexec/samba + cp -PR bin/default/source3/rpc_server/rpcd_winreg ${INSTALL}/usr/libexec/samba + + mkdir -p ${INSTALL}/usr/lib/vfs + cp ${PKG_BUILD}/bin/modules/vfs/* ${INSTALL}/usr/lib/vfs/ + + 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/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 0000000000..38c14d7899 --- /dev/null +++ b/packages/network/samba/patches/samba-200-4.11-fix-ASN1-bso14164.patch @@ -0,0 +1,60 @@ +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 +++++++++++ + 1 files changed, 11 insertions(+) + +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 +@@ -15,3 +15,14 @@ + conf.define('HAVE_CLIENT_GSS_C_CHANNEL_BOUND_FLAG', 1) + + conf.define('HAVE_KRB5_INIT_CREDS_STEP', 1) ++ ++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") +-- +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 0000000000..79f0c560cf --- /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.16.patch b/packages/network/samba/patches/samba-951-no-man-4.16.patch new file mode 100644 index 0000000000..0a20aef158 --- /dev/null +++ b/packages/network/samba/patches/samba-951-no-man-4.16.patch @@ -0,0 +1,36 @@ +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 +@@ -175,32 +175,3 @@ + target=path_entities, + rule=generate_path_entity_file, + 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) +- +- if bld.CONFIG_SET('ENABLE_SELFTEST'): +- bld.SAMBAMANPAGES('manpages/vfstest.1') +- +- 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 0000000000..28e8629b01 --- /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 0000000000..e3fd682823 --- /dev/null +++ b/packages/network/samba/scripts/samba-config @@ -0,0 +1,121 @@ +#!/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_USERCONF="/storage/.config/samba.conf" +SMB_DEFCONF="/etc/samba/smb.conf" +SMB_CONF="/run/samba/smb.conf" + +SMB_DIR=$(dirname ${SMB_CONF}) +mkdir -p ${SMB_DIR} + +# exclusive access +SMB_LOCK="${SMB_DIR}/samba-config.lock" +exec 200>"${SMB_LOCK}" +flock 200 + +SMB_TMP=$(mktemp -p ${SMB_DIR}) + +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 + +if [ ${SMB_USERCONF_IS_VALID} = yes ]; then + cp ${SMB_USERCONF} ${SMB_TMP} +else + cp ${SMB_DEFCONF} ${SMB_TMP} +fi + +echo >>${SMB_TMP} + +if [ ! -f /storage/.cache/services/samba.disabled ]; then + + ### Generate smb.conf + + 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 -n "${SAMBA_USERNAME}" -a -n "${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 + 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} + + printf "%s\n%s" "${SAMBA_PASSWORD}" "${SAMBA_PASSWORD}" | smbpasswd -c ${SMB_TMP} -s -a root + printf 'nobody = root\nroot = "%s"\n' "${SAMBA_USERNAME}" > /run/samba/samba.map + + 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 +fi + +mv -f ${SMB_TMP} ${SMB_CONF} + +exit 0 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 0000000000..a2dc1b35a2 --- /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 0000000000..4353fa2667 --- /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 0000000000..fe02a96976 --- /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/sshpass/package.mk b/packages/network/sshpass/package.mk new file mode 100644 index 0000000000..e67e65450c --- /dev/null +++ b/packages/network/sshpass/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="sshpass" +PKG_VERSION="1.10" +PKG_SHA256="ad1106c203cbb56185ca3bad8c6ccafca3b4064696194da879f81c8d7bdfeeda" +PKG_LICENSE="GPLv2" +PKG_SITE="https://sourceforge.net/p/sshpass" +PKG_URL="https://downloads.sourceforge.net/sshpass/sshpass-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="sshpass: a tool for non-interactive ssh password auth" +PKG_BUILD_FLAGS="-cfg-libs" + +pre_configure_target() { + export ac_cv_func_malloc_0_nonnull=yes + export ac_cv_func_realloc_0_nonnull=yes +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp sshpass ${INSTALL}/usr/bin +} 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 0000000000..5f7145e49d --- /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 0000000000..39135b7d63 --- /dev/null +++ b/packages/network/wireguard-tools/config/wireguard/wireguard.config.sample @@ -0,0 +1,13 @@ +[provider_wireguard] +Type = WireGuard +Name = WireGuard VPN Tunnel +Host = 3.2.5.6 +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 0000000000..b1c5498cac --- /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="1.0.20250521" +PKG_SHA256="6afe492647c3b0b2f68ab6df524e9e4290d03c34c3027e069e5bbc486949960e" +PKG_LICENSE="GPLv2" +PKG_SITE="https://www.wireguard.com" +PKG_URL="https://git.zx2c4.com/wireguard-tools/snapshot/wireguard-tools-v${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain linux" +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 0000000000..3d6c723d40 --- /dev/null +++ b/packages/network/wireguard-tools/scripts/wg-keygen @@ -0,0 +1,34 @@ +#!/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 + echo "created /storage/.cache/wireguard/privatekey" + else + echo "error, /storage/.cache/wireguard/privatekey already exists" + fi + + if [ ! -f /storage/.cache/wireguard/publickey ]; then + wg pubkey /storage/.cache/wireguard/publickey + echo "created /storage/.cache/wireguard/publickey" + else + echo "error, /storage/.cache/wireguard/publickey already exists" + fi + + if [ ! -f /storage/.cache/wireguard/preshared ]; then + wg genpsk >/storage/.cache/wireguard/preshared + echo "created /storage/.cache/wireguard/preshared" + else + echo "error, /storage/.cache/wireguard/preshared already exists" + fi + +fi + +exit 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 0000000000..6557517671 --- /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 0000000000..2e926e187e --- /dev/null +++ b/packages/network/wireless-regdb/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="wireless-regdb" +PKG_VERSION="2025.07.10" +PKG_SHA256="a8340bcdcd1b5db6c79149879d122b170f3bb075381718d4f429ad831a6fa28d" +PKG_LICENSE="GPL" +PKG_SITE="https://wireless.wiki.kernel.org/en/developers/regulatory/wireless-regdb" +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" + +makeinstall_target() { + FW_TARGET_DIR=${INSTALL}/$(get_full_firmware_dir) + + mkdir -p ${FW_TARGET_DIR} + cp ${PKG_BUILD}/regulatory.db ${PKG_BUILD}/regulatory.db.p7s ${FW_TARGET_DIR} +} diff --git a/packages/network/wsdd2/package.mk b/packages/network/wsdd2/package.mk new file mode 100644 index 0000000000..eaf378a115 --- /dev/null +++ b/packages/network/wsdd2/package.mk @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="wsdd2" +PKG_VERSION="1.8.7" +PKG_SHA256="b0b6b31522f4a5e39d075b31d59d57af9a567f543e0b39b2fbdfec324d30310a" +PKG_LICENSE="GPL 3.0" +PKG_SITE="https://github.com/Netgear/wsdd2/" +PKG_URL="https://github.com/Netgear/wsdd2/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="make:host gcc:host" +PKG_LONGDESC="WSD/LLMNR Discovery/Name Service Daemon" +PKG_BUILD_FLAGS="+size" + +post_install() { + enable_service wsdd2.service +} diff --git a/packages/oem/package.mk b/packages/oem/package.mk new file mode 100644 index 0000000000..6b49c12178 --- /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/packages.mk.addon_template b/packages/packages.mk.addon_template new file mode 100644 index 0000000000..0eb3173680 --- /dev/null +++ b/packages/packages.mk.addon_template @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="[package name]" +PKG_VERSION="[package version identifier or unique githash]" +PKG_REV="100" +PKG_SHA256="[sha256 hash of the source file, downloaded from PKG_URL]" +PKG_ARCH="any" +PKG_LICENSE="[license of the upstream project]" +PKG_SITE="[url to the upstream project, e.g. http://example.com/libexample" +PKG_URL="[download url, e.g. https://github.com/example/libexample/archive/$PKG_VERSION.tar.gz]" +# PKG_MAINTAINER="John Doe" # Full name or forum/GitHub nickname, if you want to be identified as the addon maintainer +PKG_DEPENDS_TARGET="[build system dependencies, e.g. toolchain zlib openssl]" +PKG_SECTION="[location under packages, e.g. database]" +PKG_SHORTDESC="[short description of the package, e.g. libexample: library to calculate examples]" +PKG_LONGDESC="[long description of the package, often taken from the package/project website, e.g. libexample: this project is created to calculate examples for x and y, with maximum efficiency and fewer errors]" +# PKG_TOOLCHAIN="auto" or one of meson, cmake, cmake-make, configure, make, ninja, autotools, manual + +PKG_IS_ADDON="yes" +PKG_ADDON_NAME="[proper name of the addon that is shown at the repo]" +PKG_ADDON_TYPE="[type]" +# PKG_ADDON_PROJECTS="[project, only set when not any]" +# PKG_ADDON_PROVIDES="executable" +# PKG_ADDON_REQUIRES="some.addon:0.0.0" + +#PKG_CMAKE_OPTS_TARGET="-DWITH_EXAMPLE_PATH=/storage/.example +# " + +#pre_configure_target() { +# do something, or drop it +#} + +addon() { + # copy needed files from other packages (which are not in the image) +} + +# see https://github.com/LibreELEC/LibreELEC.tv/blob/master/packages/readme.md for more +# take a look to other packages, for inspiration diff --git a/packages/packages.mk.template b/packages/packages.mk.template new file mode 100644 index 0000000000..dc161f77b7 --- /dev/null +++ b/packages/packages.mk.template @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="[package name]" +PKG_VERSION="[package version identifier or unique githash]" +PKG_SHA256="[sha256 hash of the source file, downloaded from PKG_URL]" +PKG_ARCH="any" +PKG_LICENSE="[license of the upstream project]" +PKG_SITE="[url to the upstream project, e.g. http://example.com/libexample" +PKG_URL="[download url, e.g. https://github.com/example/libexample/archive/$PKG_VERSION.tar.gz]" +# PKG_MAINTAINER="John Doe" # Full name or forum/GitHub nickname, if you want to be identified as the addon maintainer +PKG_DEPENDS_TARGET="[build system dependencies, e.g. toolchain zlib openssl]" +PKG_SECTION="[location under packages, e.g. database]" +PKG_SHORTDESC="[short description of the package, e.g. libexample: library to calculate examples]" +PKG_LONGDESC="[long description of the package, often taken from the package/project website, e.g. libexample: this project is created to calculate examples for x and y, with maximum efficiency and fewer errors]" +# PKG_TOOLCHAIN="auto" + +#PKG_CMAKE_OPTS_TARGET="-DWITH_EXAMPLE_PATH=/storage/.example +# " + +#pre_configure_target() { +# do something, or drop it +#} + +# see https://github.com/LibreELEC/LibreELEC.tv/blob/master/packages/readme.md for more +# take a look to other packages, for inspiration diff --git a/packages/print/freetype/package.mk b/packages/print/freetype/package.mk new file mode 100644 index 0000000000..8d7089fa09 --- /dev/null +++ b/packages/print/freetype/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="freetype" +PKG_VERSION="2.13.3" +PKG_SHA256="0550350666d427c74daeb85d5ac7bb353acba5f76956395995311a9c6f063289" +PKG_LICENSE="GPL" +PKG_SITE="https://freetype.org" +PKG_URL="https://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() { + sed -e "s#prefix=/usr#prefix=${SYSROOT_PREFIX}/usr#" -i "${SYSROOT_PREFIX}/usr/lib/pkgconfig/freetype2.pc" + + cp -P "${PKG_BUILD}/.${TARGET_NAME}/freetype-config" "${SYSROOT_PREFIX}/usr/bin" +} diff --git a/packages/print/freetype/patches/freetype-01-fix-pkgconf.patch b/packages/print/freetype/patches/freetype-01-fix-pkgconf.patch new file mode 100644 index 0000000000..863d1623d5 --- /dev/null +++ b/packages/print/freetype/patches/freetype-01-fix-pkgconf.patch @@ -0,0 +1,14 @@ +diff -Naur freetype-2.6.1/builds/unix/freetype2.in freetype-2.6.1.patch/builds/unix/freetype2.in +--- freetype-2.6.1/builds/unix/freetype2.in 2015-09-25 07:58:57.000000000 +0200 ++++ freetype-2.6.1.patch/builds/unix/freetype2.in 2015-10-12 21:58:50.736816464 +0200 +@@ -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: FreeType 2 + URL: https://freetype.org diff --git a/packages/python/devel/Jinja2/package.mk b/packages/python/devel/Jinja2/package.mk new file mode 100644 index 0000000000..23aedda22f --- /dev/null +++ b/packages/python/devel/Jinja2/package.mk @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="Jinja2" +PKG_VERSION="3.1.6" +PKG_SHA256="0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d" +PKG_LICENSE="BSD" +PKG_SITE="https://pypi.org/project/Jinja2/" +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="Jinja is a fast, expressive, extensible templating engine." +PKG_TOOLCHAIN="python" diff --git a/packages/python/devel/Mako/package.mk b/packages/python/devel/Mako/package.mk new file mode 100644 index 0000000000..831b8046d5 --- /dev/null +++ b/packages/python/devel/Mako/package.mk @@ -0,0 +1,13 @@ +# 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.3.10" +PKG_SHA256="99579a6f39583fa7e5630a28c3c1f440e4e97a414b80372649c0ce338da2ea28" +PKG_LICENSE="GPL" +PKG_SITE="https://pypi.org/project/Mako" +PKG_URL="https://files.pythonhosted.org/packages/source/${PKG_NAME:0:1}/${PKG_NAME}/mako-${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="python" diff --git a/packages/python/devel/MarkupSafe/package.mk b/packages/python/devel/MarkupSafe/package.mk new file mode 100644 index 0000000000..b4b8d28ea7 --- /dev/null +++ b/packages/python/devel/MarkupSafe/package.mk @@ -0,0 +1,14 @@ +# 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="3.0.2" +PKG_SHA256="ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0" +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_URL="https://files.pythonhosted.org/packages/source/${PKG_NAME:0:1}/${PKG_NAME}/markupsafe-${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="python" diff --git a/packages/python/devel/flit/package.mk b/packages/python/devel/flit/package.mk new file mode 100644 index 0000000000..e157618899 --- /dev/null +++ b/packages/python/devel/flit/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="flit" +PKG_VERSION="3.12.0" +PKG_SHA256="18f63100d6f94385c6ed57a72073443e1a71a4acb4339491615d0f16d6ff01b2" +PKG_LICENSE="BSD" +PKG_SITE="https://pypi.org/project/flit-core/" +PKG_URL="https://files.pythonhosted.org/packages/source/f/flit_core/flit_core-${PKG_VERSION}.tar.gz" +PKG_SOURCE_DIR="flit_core-${PKG_VERSION}" +PKG_DEPENDS_HOST="Python3:host" +PKG_LONGDESC="flit provides a PEP 517 build backend for packages using Flit." +PKG_TOOLCHAIN="manual" + +make_host() { + export DONT_BUILD_LEGACY_PYC=1 + python3 -m flit_core.wheel +} + +makeinstall_host() { + exec_thread_safe python3 -m bootstrap_install dist/*.whl --installdir=${TOOLCHAIN}/lib/${PKG_PYTHON_VERSION}/site-packages +} diff --git a/packages/python/devel/meson/package.mk b/packages/python/devel/meson/package.mk new file mode 100644 index 0000000000..b7429c08eb --- /dev/null +++ b/packages/python/devel/meson/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="meson" +PKG_VERSION="1.8.2" +PKG_SHA256="c105816d8158c76b72adcb9ff60297719096da7d07f6b1f000fd8c013cd387af" +PKG_LICENSE="Apache" +PKG_SITE="https://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" +PKG_LONGDESC="High productivity build system" +PKG_TOOLCHAIN="python" + +post_makeinstall_target() { + # 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 0000000000..8d01f51027 --- /dev/null +++ b/packages/python/devel/ninja/package.mk @@ -0,0 +1,22 @@ +# 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.13.1" +PKG_SHA256="f0055ad0369bf2e372955ba55128d000cfcc21777057806015b45e4accbebf23" +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="manual" + +make_host() { + python3 ../configure.py --bootstrap +} + +makeinstall_host() { + mkdir -p ${TOOLCHAIN}/bin + cp ninja ${TOOLCHAIN}/bin +} diff --git a/packages/python/devel/ply/package.mk b/packages/python/devel/ply/package.mk new file mode 100644 index 0000000000..57547a367c --- /dev/null +++ b/packages/python/devel/ply/package.mk @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2025-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="ply" +PKG_VERSION="3.11" +PKG_SHA256="00c7c1aaa88358b9c765b6d3000c6eec0ba42abca5351b095321aef446081da3" +PKG_LICENSE="BSD-3-Clause" +PKG_SITE="https://pypi.org/project/ply" +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="PLY is yet another implementation of lex and yacc for Python." +PKG_TOOLCHAIN="python" diff --git a/packages/python/devel/pybuild/package.mk b/packages/python/devel/pybuild/package.mk new file mode 100644 index 0000000000..8f131acc32 --- /dev/null +++ b/packages/python/devel/pybuild/package.mk @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="pybuild" +PKG_VERSION="1.2.2" +PKG_SHA256="119b2fb462adef986483438377a13b2f42064a2a3a4161f24a0cca698a07ac8c" +PKG_LICENSE="BSD" +PKG_SITE="https://pypi.org/project/build/" +PKG_URL="https://files.pythonhosted.org/packages/source/b/build/build-${PKG_VERSION}.tar.gz" +PKG_SOURCE_DIR="build-${PKG_VERSION}" +PKG_DEPENDS_HOST="flit:host pyproject-hooks:host pyinstaller:host pypackaging:host" +PKG_LONGDESC="A simple, correct Python build frontend." +PKG_TOOLCHAIN="python-flit" diff --git a/packages/python/devel/pycparser/package.mk b/packages/python/devel/pycparser/package.mk new file mode 100644 index 0000000000..b3ea0be6b2 --- /dev/null +++ b/packages/python/devel/pycparser/package.mk @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2024-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="pycparser" +PKG_VERSION="2.22" +PKG_SHA256="491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6" +PKG_LICENSE="BSD-3-Clause" +PKG_SITE="https://pypi.org/project/pycparser/" +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="Complete C99 parser in pure Python" +PKG_TOOLCHAIN="python" diff --git a/packages/python/devel/pyelftools/package.mk b/packages/python/devel/pyelftools/package.mk new file mode 100644 index 0000000000..65b69ab088 --- /dev/null +++ b/packages/python/devel/pyelftools/package.mk @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2023-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="pyelftools" +PKG_VERSION="0.32" +PKG_SHA256="82d0399bce74d162fba75b3568ad47bf48ed2c5e028b72026bdc2f678903de7d" +PKG_LICENSE="Unlicense" +PKG_SITE="https://github.com/eliben/pyelftools" +PKG_URL="https://github.com/eliben/pyelftools/archive/refs/tags/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="Python3:host setuptools:host" +PKG_LONGDESC="Library for analyzing ELF files and DWARF debugging information" +PKG_TOOLCHAIN="python" diff --git a/packages/python/devel/pyinstaller/package.mk b/packages/python/devel/pyinstaller/package.mk new file mode 100644 index 0000000000..94f4334126 --- /dev/null +++ b/packages/python/devel/pyinstaller/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="pyinstaller" +PKG_VERSION="0.7.0" +PKG_SHA256="a26d3e3116289bb08216e0d0f7d925fcef0b0194eedfa0c944bcaaa106c4b631" +PKG_LICENSE="MIT" +PKG_SITE="https://pypi.org/project/installer/" +PKG_URL="https://files.pythonhosted.org/packages/source/i/installer/installer-${PKG_VERSION}.tar.gz" +PKG_SOURCE_DIR="installer-${PKG_VERSION}" +PKG_DEPENDS_HOST="flit:host" +PKG_LONGDESC="installer provides basic functionality and abstractions for handling wheels and installing packages from wheels." +PKG_TOOLCHAIN="python-flit" + +makeinstall_host() { + # simple bootstrap install, but should be able to call itself if needed + unzip -o -d ${TOOLCHAIN}/lib/${PKG_PYTHON_VERSION}/site-packages dist/*.whl +} diff --git a/packages/python/devel/pyinstaller/patches/0001-Add-overwrite-existing-option-that-overwrites-existi.patch b/packages/python/devel/pyinstaller/patches/0001-Add-overwrite-existing-option-that-overwrites-existi.patch new file mode 100644 index 0000000000..145d8687f2 --- /dev/null +++ b/packages/python/devel/pyinstaller/patches/0001-Add-overwrite-existing-option-that-overwrites-existi.patch @@ -0,0 +1,82 @@ +From 4628ef70e1159d3cbab58d395f647c3dff887650 Mon Sep 17 00:00:00 2001 +From: Carl Smedstad +Date: Tue, 13 Feb 2024 21:10:22 +0100 +Subject: [PATCH] Add --overwrite-existing option that overwrites existing + files + +Implement the --overwrite-existing option that, if supplied, will make +installer overwrite any already existing package files instead of +failing. With this flag, installer can be used in an idempotent manner, +i.e. the same command can be executed multiple times with the same +result: + + python -m installer --overwrite-existing --destdir=tmp dist/*.whl + python -m installer --overwrite-existing --destdir=tmp dist/*.whl + python -m installer --overwrite-existing --destdir=tmp dist/*.whl +--- + src/installer/__main__.py | 6 ++++++ + src/installer/destinations.py | 5 ++++- + tests/test_destinations.py | 22 ++++++++++++++++++++++ + 3 files changed, 32 insertions(+), 1 deletion(-) + +diff --git a/src/installer/__main__.py b/src/installer/__main__.py +index 7ece8d213fe4..b587232912f9 100644 +--- a/src/installer/__main__.py ++++ b/src/installer/__main__.py +@@ -51,6 +51,11 @@ def _get_main_parser() -> argparse.ArgumentParser: + choices=["all", "entries", "none"], + help="validate the wheel against certain part of its record (default=none)", + ) ++ parser.add_argument( ++ "--overwrite-existing", ++ action="store_true", ++ help="silently overwrite existing files", ++ ) + return parser + + +@@ -95,6 +100,7 @@ def _main(cli_args: Sequence[str], program: Optional[str] = None) -> None: + script_kind=get_launcher_kind(), + bytecode_optimization_levels=bytecode_levels, + destdir=args.destdir, ++ overwrite_existing=args.overwrite_existing, + ) + installer.install(source, destination, {}) + +diff --git a/src/installer/destinations.py b/src/installer/destinations.py +index 31a254c387be..982e6adfc218 100644 +--- a/src/installer/destinations.py ++++ b/src/installer/destinations.py +@@ -111,6 +111,7 @@ class SchemeDictionaryDestination(WheelDestination): + hash_algorithm: str = "sha256", + bytecode_optimization_levels: Collection[int] = (), + destdir: Optional[str] = None, ++ overwrite_existing: bool = False, + ) -> None: + """Construct a ``SchemeDictionaryDestination`` object. + +@@ -127,6 +128,7 @@ class SchemeDictionaryDestination(WheelDestination): + :param destdir: A staging directory in which to write all files. This + is expected to be the filesystem root at runtime, so embedded paths + will be written as though this was the root. ++ :param overwrite_existing: silently overwrite existing files. + """ + self.scheme_dict = scheme_dict + self.interpreter = interpreter +@@ -134,6 +136,7 @@ class SchemeDictionaryDestination(WheelDestination): + self.hash_algorithm = hash_algorithm + self.bytecode_optimization_levels = bytecode_optimization_levels + self.destdir = destdir ++ self.overwrite_existing = overwrite_existing + + def _path_with_destdir(self, scheme: Scheme, path: str) -> str: + file = os.path.join(self.scheme_dict[scheme], path) +@@ -161,7 +164,7 @@ class SchemeDictionaryDestination(WheelDestination): + - Hashes the written content, to determine the entry in the ``RECORD`` file. + """ + target_path = self._path_with_destdir(scheme, path) +- if os.path.exists(target_path): ++ if not self.overwrite_existing and os.path.exists(target_path): + message = f"File already exists: {target_path}" + raise FileExistsError(message) + diff --git a/packages/python/devel/pypackaging/package.mk b/packages/python/devel/pypackaging/package.mk new file mode 100644 index 0000000000..203dc1fd73 --- /dev/null +++ b/packages/python/devel/pypackaging/package.mk @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="pypackaging" +PKG_VERSION="25.0" +PKG_SHA256="d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f" +PKG_LICENSE="BSD" +PKG_SITE="https://pypi.org/project/build/" +PKG_URL="https://files.pythonhosted.org/packages/source/p/packaging/packaging-${PKG_VERSION}.tar.gz" +PKG_SOURCE_DIR="packaging-${PKG_VERSION}" +PKG_DEPENDS_HOST="flit:host pyinstaller:host" +PKG_LONGDESC="Reusable core utilities for various Python Packaging interoperability specifications." +PKG_TOOLCHAIN="python-flit" diff --git a/packages/python/devel/pyproject-hooks/package.mk b/packages/python/devel/pyproject-hooks/package.mk new file mode 100644 index 0000000000..dff4229097 --- /dev/null +++ b/packages/python/devel/pyproject-hooks/package.mk @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="pyproject-hooks" +PKG_VERSION="1.2.0" +PKG_SHA256="1e859bd5c40fae9448642dd871adf459e5e2084186e8d2c2a79a824c970da1f8" +PKG_LICENSE="BSD" +PKG_SITE="https://pypi.org/project/pyproject-hooks/" +PKG_URL="https://files.pythonhosted.org/packages/source/p/pyproject_hooks/pyproject_hooks-${PKG_VERSION}.tar.gz" +PKG_SOURCE_DIR="pyproject_hooks-${PKG_VERSION}" +PKG_DEPENDS_HOST="flit:host pyinstaller:host" +PKG_LONGDESC="pyproject-hooks provides the basic functionality to help write tooling that generates distribution files from Python projects." +PKG_TOOLCHAIN="python-flit" diff --git a/packages/python/devel/pyyaml/package.mk b/packages/python/devel/pyyaml/package.mk new file mode 100644 index 0000000000..7bd3c2b4bd --- /dev/null +++ b/packages/python/devel/pyyaml/package.mk @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2024-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="pyyaml" +PKG_VERSION="6.0.2" +PKG_SHA256="d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e" +PKG_LICENSE="MIT" +PKG_SITE="https://pypi.org/project/PyYAML/" +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="YAML parser and emitter for Python" +PKG_TOOLCHAIN="python" diff --git a/packages/python/devel/setuptools/package.mk b/packages/python/devel/setuptools/package.mk new file mode 100644 index 0000000000..9bc71c383d --- /dev/null +++ b/packages/python/devel/setuptools/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="setuptools" +PKG_VERSION="80.9.0" +PKG_SHA256="f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c" +PKG_LICENSE="OSS" +PKG_SITE="https://pypi.org/project/setuptools" +PKG_URL="https://files.pythonhosted.org/packages/source/${PKG_NAME:0:1}/${PKG_NAME}/${PKG_NAME,,}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="pybuild:host" +PKG_LONGDESC="Replaces Setuptools as the standard method for working with Python module distributions." +PKG_TOOLCHAIN="python" diff --git a/packages/python/devel/waf/package.mk b/packages/python/devel/waf/package.mk new file mode 100644 index 0000000000..adaaa8608a --- /dev/null +++ b/packages/python/devel/waf/package.mk @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="waf" +PKG_VERSION="2.1.6" +PKG_SHA256="f9f1a8495ab7470844a05dd2e838017bcff969d92a9aeede7811d6ad74e04707" +PKG_LICENSE="MIT" +PKG_SITE="https://waf.io" +PKG_URL="https://waf.io/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_LONGDESC="The Waf build system" +PKG_TOOLCHAIN="manual" + +makeinstall_host() { + cp -pf ${PKG_BUILD}/waf ${TOOLCHAIN}/bin/ +} diff --git a/packages/python/graphics/Pillow/package.mk b/packages/python/graphics/Pillow/package.mk new file mode 100644 index 0000000000..64fc8c556f --- /dev/null +++ b/packages/python/graphics/Pillow/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="Pillow" +PKG_VERSION="11.3.0" +PKG_SHA256="fa4aca745b1e1c733589ebf0ef19491b145dd4225c4aa06958963b4e7f0734cf" +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 zlib freetype libjpeg-turbo tiff" +PKG_LONGDESC="The Python Imaging Library adds image processing capabilities to your Python interpreter." +PKG_TOOLCHAIN="python" + +PKG_PYTHON_OPTS_TARGET="-C--build-option=build_ext -C--build-option=--disable-platform-guessing" + +post_makeinstall_target() { + python_remove_source + + rm -rf ${INSTALL}/usr/bin +} diff --git a/packages/python/graphics/glad/package.mk b/packages/python/graphics/glad/package.mk new file mode 100644 index 0000000000..0cf3b971f1 --- /dev/null +++ b/packages/python/graphics/glad/package.mk @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2023-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="glad" +PKG_VERSION="2.0.8" +PKG_SHA256="44f06f9195427c7017f5028d0894f57eb216b0a8f7c4eda7ce883732aeb2d0fc" +PKG_LICENSE="MIT" +PKG_SITE="https://glad.dav1d.de" +PKG_URL="https://github.com/Dav1dde/glad/archive/refs/tags/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="setuptools:host" +PKG_LONGDESC="Multi-Language Vulkan/GL/GLES/EGL/GLX/WGL Loader-Generator based on the official specs" +PKG_TOOLCHAIN="python" diff --git a/packages/python/security/pycryptodome/package.mk b/packages/python/security/pycryptodome/package.mk new file mode 100644 index 0000000000..8820c92ca3 --- /dev/null +++ b/packages/python/security/pycryptodome/package.mk @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="pycryptodome" +PKG_VERSION="3.23.0" +PKG_SHA256="5a905f0f4237b79aefee47f3e04568db2ecb70c55dd7cb118974c5260aa9e285" +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 setuptools:host" +PKG_LONGDESC="PyCryptodome is a self-contained Python package of low-level cryptographic primitives." +PKG_TOOLCHAIN="python" + +pre_configure_target() { + cd ${PKG_BUILD} + rm -rf .${TARGET_NAME} +} + +post_makeinstall_target() { + # 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 + + python_remove_source +} diff --git a/packages/python/system/dbussy/package.mk b/packages/python/system/dbussy/package.mk new file mode 100644 index 0000000000..3b0466f7c6 --- /dev/null +++ b/packages/python/system/dbussy/package.mk @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="dbussy" +PKG_VERSION="691a8a8a1914416b7ea1545fb931d74f2e381f09" +PKG_SHA256="857104ef2fd1978323d7c87b32c753d2d178b79adbd13f52cea23511f5195ded" +PKG_LICENSE="LGPLv2.1+" +PKG_SITE="https://gitlab.com/ldo/dbussy" +PKG_URL="https://github.com/ldo/${PKG_NAME}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain Python3 dbus setuptools:host" +PKG_LONGDESC="DBussy is a wrapper around libdbus, written in pure Python" +PKG_TOOLCHAIN="python" + +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 0000000000..66dffed2c7 --- /dev/null +++ b/packages/python/system/simplejson/package.mk @@ -0,0 +1,19 @@ +# 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.20.1" +PKG_SHA256="e64139b4ec4f1f24c142ff7dcafe55a22b811a74d86d66560c8815687143037d" +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 setuptools:host" +PKG_LONGDESC="A simple, fast, complete, correct and extensible JSON encoder and decoder for Python 2.5+." +PKG_TOOLCHAIN="python" + +post_makeinstall_target() { + python_remove_source + + rm -rf ${INSTALL}/usr/lib/python*/site-packages/*/tests +} diff --git a/packages/readme.md b/packages/readme.md new file mode 100644 index 0000000000..bff01342ee --- /dev/null +++ b/packages/readme.md @@ -0,0 +1,311 @@ +# Structure of package.mk files + +## Introduction + +The package.mk file defines variables and functions to build a package. + +## Variables +To control the build behaviour of your package, use variables in the top-down order listed here. + +#### Base + +| Variable | Default | Required |Description | +|-------------|---------|----------|------------| +| PKG_NAME | - | yes | Name of the packaged software application. Should be lowercase | +| PKG_VERSION | - | yes | Version of the packaged software application. If the version is a githash, please use the full githash, not the abbreviated form. | +| PKG_SHA256 | - | yes | SHA256 hashsum of the application download file | +| PKG_ARCH | any | no | Architectures for which the package builds. `any` or a space separated list of `aarch64`, `arm` or `x86_64` | +| PKG_LICENSE | - | yes | License of the software application. [Reference](https://github.com/LibreELEC/LibreELEC.tv/tree/master/licenses) | +| PKG_SITE | - | yes | Site of the software application | +| PKG_URL | - | yes | Address at which the source of the software application can be retrieved | +| PKG_MAINTAINER | - | no | Your name | +| PKG_DEPENDS_BOOTSTRAP
PKG_DEPENDS_HOST PKG_DEPENDS_INIT PKG_DEPENDS_TARGET | - | no | A space separated list of name of packages required to build the software application | +| PKG_SECTION | - | no | virtual if the package only defines dependencies | +| PKG_SHORTDESC | - | no
yes for addons | Short description of the software package | +| PKG_LONGDESC | - | yes | Long description of the package including purpose or function within LibreELEC or Kodi | + +#### Universal Build Option +| Variable | Default | Required |Description | +|-------------|---------|----------|------------| +| PKG_SOURCE_DIR | - | no | Force the folder name that application sources are unpacked to. Used when sources do not automatically unpack to a folder with the `PKG_NAME-PKG_VERSION` naming convention. | +| PKG_TAR_STRIP_COMPONENTS | - | no | When this option is set the top level directory is not get stripped off while extracting an archive. | +| PKG_SOURCE_NAME | - | no | Force the filename of the application sources. Used when the filename is not the basename of `PKG_URL` | +| PKG_PATCH_DIRS | - | no | Patches in `./patches` are automatically applied after package unpack. Use this option to include patches from an additional folder, e.g. `./patches/$PKG_PATCH_DIRS` | +| PKG_NEED_UNPACK | - | no | Space separated list of files or folders to include in package stamp calculation. If the stamp is invalidated through changes to package files or dependent files/folders the package is cleaned and rebuilt. e.g. `PKG_NEED_UNPACK="$(get_pkg_directory linux)"` will trigger clean/rebuild of a Linux kernel driver package when a change to the `linux` kernel package is detected. | +| PKG_TOOLCHAIN | auto | no | Control which build toolchain is used. For detailed information, see [Reference](#toolchain-options). | +| PKG_BUILD_FLAGS | - | no | A space separated list of flags with which to fine-tune the build process. Flags can be enabled or disabled with a `+` or `-` prefix. For detailed information, see [Reference](#build_flags-options). | +| PKG_PYTHON_VERSION | python3.8 | no | Define the Python version to be used. | +| PKG_IS_KERNEL_PKG | - | no | Set to `yes` for packages that include Linux kernel modules | +| PKG_DEPENDS_CONFIG | - | no | Space separated list of packages to add to PKG_CONFIG_PATH. Use this to build with support for `-sysroot` packages, see [Reference](#build_flags-options). | + +#### Meson Options +| Variable | Default | Required |Description | +|-------------|---------|----------|------------| +| PKG_MESON_SCRIPT | $PKG_BUILD/meson.build | no | Meson build file to use | +| PKG_MESON_OPTS_TARGET | - | no | Options directly passed to meson | + +#### CMAKE Options +| Variable | Default | Required |Description | +|-------------|---------|----------|------------| +| PKG_CMAKE_SCRIPT | $PKG_BUILD/CMakeLists.txt | no | CMake build file to use | +| PKG_CMAKE_OPTS_HOST
PKG_CMAKE_OPTS_TARGET | - | no | Options directly passed to cmake | + +#### Configure Options +| Variable | Default | Required |Description | +|-------------|---------|----------|------------| +| PKG_CONFIGURE_SCRIPT | $PKG_BUILD/configure | no | configure script to use | +| PKG_CONFIGURE_OPTS
PKG_CONFIGURE_OPTS_BOOTSTRAP
PKG_CONFIGURE_OPTS_HOST
PKG_CONFIGURE_OPTS_INIT
PKG_CONFIGURE_OPTS_TARGET | - | no | Options directly passed to configure | + +#### Make Options +| Variable | Default | Required |Description | +|-------------|---------|----------|------------| +| PKG_MAKE_OPTS
PKG_MAKE_OPTS_BOOTSTRP
PKG_MAKE_OPTS_HOST
PKG_MAKE_OPTS_INIT
PKG_MAKE_OPTS_TARGET | - | no | Options directly passed to make in the build step +| PKG_MAKEINSTALL_OPTS_HOST
PKG_MAKEINSTALL_OPTS_TARGET | - | no | Options directly passed to make in the install step + +#### Addons +Additional options used when the package builds an addon. + +| Variable | Default | Required |Description | +|-------------|---------|----------|------------| +| PKG_REV | - | yes | The revision number of the addon (starts at 100). Must be placed after `PKG_VERSION`. Must be incremented for each new version else Kodi clients will not detect version change and download the updated addon. | +| PKG_IS_ADDON | no | yes | Must be set to `yes`
or to `embedded` when this addon is part of the image | +| PKG_ADDON_NAME | - | yes | Proper name of the addon that is shown at the repo | +| PKG_ADDON_TYPE | - | yes | See LE/config/addon/ for other possibilities | +| PKG_ADDON_VERSION | - | no | The version of the addon, used in addon.xml | +| PKG_ADDON_PROVIDES | - | no | [Provides](http://kodi.wiki/view/addon.xml#.3Cprovides.3E_element) in addon-xml | +| PKG_ADDON_REQUIRES | - | no | [Requires](http://kodi.wiki/view/addon.xml#.3Crequires.3E) used in addon.xml | +| PKG_ADDON_PROJECTS | @PROJECTS@ | no | for available projects or devices, see projects subdirectory (note: Use RPi for RPi project, and RPi1 for RPi device) | +| PKG_DISCLAIMER | - | no | [Disclaimer](https://kodi.wiki/view/Addon.xml#.3Cdisclaimer.3E) in addon-xml | +| PKG_ADDON_IS_STANDALONE | - | no | Defines if an addon depends on Kodi (on) or is standalone (yes) | +| PKG_ADDON_BROKEN | - | no | Marks an addon as broken for the user | + +#### Detailed Information for Options + +##### TOOLCHAIN options + +Application/packages needs different toolchains for build. +For instance `cmake` or the classic `./configure` or same very different. + +For the most application/packages, the auto-detection of the toolchain works proper. +But not always. To select a specific toolchain, you only need to set the `PKG_TOOLCHAIN` variable. + +| Toolchain | Description (if needed) | +|----------- |-------------------------| +| meson | [Meson Build System](http://mesonbuild.com/) | +| cmake | [CMake](https://cmake.org/) with Ninja | +| cmake-make | [CMake](https://cmake.org/) with Make | +| autotools | [GNU Build System](https://en.wikipedia.org/wiki/GNU_Build_System) +| configure | preconfigured [GNU Build System](https://en.wikipedia.org/wiki/GNU_Build_System) | +| ninja | [Ninja Build](https://ninja-build.org/) | +| make | [Makefile Based](https://www.gnu.org/software/make/) | +| manual | only runs self written build steps, see [Functions](#functions) | + +###### Auto-Detection +The auto-detections looks for specific files in the source path. + +1. `meson.build` (PKG_MESON_SCRIPT) => meson toolchain +2. `CMakeLists.txt` (PKG_CMAKE_SCRIPT) => cmake toolchain +3. `configure` (PKG_CONFIGURE_SCRIPT) => configure toolchain +4. `Makefile` => make toolchain + +When none of these was found, the build abort and you have to set the toolchain via `PKG_TOOLCHAIN` + +##### BUILD_FLAGS options + +Build flags implement often used build options. Normally these are activated be default, but single applications/packages has problems to compile/run with these. + +Set the variable `PKG_BUILD_FLAGS` in the `package.mk` to enable/disable the single flags. It is a space separated list. The flags can enabled with a `+` prefix, and disabled with a `-`. + +| flag | default | affected stage(s) | description | +|----------|----------|-------------------|-------------| +| pic | disabled | target, init | [Position Independent Code](https://en.wikipedia.org/wiki/Position-independent_code) | +| pic:host | disabled | host, bootstrap | see above | +| speed | disabled | target, init | replaces default `-O2` compiler optimization with `-O3` (can only enable; overrules size) | +| size | disabled | target, init | replaces default `-O2` compiler optimization with `-Os` (can only enable) | +| lto | disabled | target, init | enable LTO (Link Time optimization) in the compiler and linker unless disabled via `LTO_SUPPORT`. Compiles non-fat LTO objects (only bytecode) and automatically determines number of threads to use for optimization at link stage | +| lto-fat | disabled | target, init | same as `lto` but compile fat LTO objects (bytecode plus optimized assembly). This increases compile time but can be useful to create static libraries suitable both for LTO and non-LTO linking | +| lto-off | disabled | target, init | explicitly disable LTO in the compiler and linker | +| bfd | - | target, init | `+bfd` prefers bfd linker over default linker, `-bfd` disables using bfd | +| gold | - | target, init | `+gold` prefers gold linker over default linker, `-gold` disables using gold | +| mold | - | target, init | `+mold` prefers mold linker over default linker, `-mold` disables using gold | +| parallel | enabled | all | `make` or `ninja` builds with multiple threads/processes (or not) | +| strip | enabled | target | strips executables (or not) | +| sysroot | enabled | target | installs the package to the sysroot folder (or not) | +| local-cc | disabled | host | use compiler from buildhost instead of host-gcc/g++ in toolchain | +| cfg-libs | enabled | all | `-cfg-libs` will not append --disable-static --enable-shared to CONFIGURE_OPTS | + +###### Example +``` +PKG_BUILD_FLAGS="+pic -gold" +PKG_BUILD_FLAGS="-parallel" +``` + +## Functions +All build steps in the LibreELEC build system are done by shell function. +These functions can be overwritten in the `package.mk`. However, this raises problems when the build system is updated. To reduce the impact, most functions are extended by `pre_` and `post_` scripts to use instead. + +When it is nesseary to replace configure, make and makeinstall, please use `PKG_TOOLCHAIN="manual"`. + +Some of the build steps needs to be run once, like `unpack`. Other steps needs to be run multiple times, to create the toolchain (stage bootstrap & host) or to create the LE image (stage init & target). These stage specific functions have the stage as suffix, like `make_target`. + +Full list of overwrittable functions. + +| function | stages specific | description | +|-------------------------|--------|-------------| +| configure_package | - | Optional function to implement late binding variable assignment (see below) | +| unpack
pre_unpack
post_unpack | - | Extract the source from the downloaded file | +| pre_patch
post_patch | - | Apply the patches to the source, after extraction. The patch function it self is not allowed to overwritten | +| pre_build_\[stage] | yes | Runs before of the start of the build | +| pre_configure
pre_configure_\[stage]
configure_\[stage]
post_configure_\[stage] | yes | Configure the package for the compile. This is only relevant for toolchain, that supports it (e.g. meson, cmake, configure, manual) | +| make_\[stage]
pre_make_\[stage]
post_make_\[stage] | yes | Build of the package | +| makeinstall_\[stage]
pre_makeinstall_\[stage]
post_makeinstall_\[stage] | yes | Installation of the files in the correct paths
host: TOOLCHAIN
target: SYSROOT and IMAGE
bootstrap and init: temporary destination +| addon | - | Copy all files together for addon creation. This is required for addons | +| post_install_addon | - | Post processing of installed addon files in `${INSTALL}` directory | + +## Directory structure +Every package has its own set of build and install directories. The sources are extracted and built in the former, and build artifacts are installed to the latter. +Usually an install target provided by the package build system will populate the install directory automatically, but it's important that you use the standard `usr/lib/`, `usr/bin/` etc. structure when doing so manually, because the contents of the install directory will be part of the final image (with the exception of top level hidden directories). + +Sometimes it's necessary to access build artifacts from different packages - like an addon collecting files of various other packages. In that case you need to access the files using the package's install directories (and not their build directories since they might not exist anymore). If you need additional files which should not be part of the final image, you can use a hidden directory for those - grep for `.noinstall` for some examples. + +## Late Binding variable assignment + +A package will be loaded only once, by the call to `config/options`. During this process, additional package specific variables will be initialised, such as: + +* `PKG_BUILD` - path to the build folder +* `PKG_SOURCE_NAME` - if not already specified, generated from `PKG_URL`, `PKG_NAME` and` PKG_VERSION` + +Since these variables will not exist at the time the package is loaded, they can only be referenced **after** package has loaded. This can be accomplished by referencing these variables in the `configure_package()` function which is executed once the additional variables have been assigned. + +If necessary, the following variables would be configured in `configure_package()` as they are normally relative to `${PKG_BUILD}`: +``` + PKG_CONFIGURE_SCRIPT + PKG_CMAKE_SCRIPT + PKG_MESON_SCRIPT +``` + +Further to this, toolchain variables that are defined in `setup_toolchain()` must not be referenced "globally" in the package as they will only be configured reliably after `setup_toolchain()` has been called during `scripts/build`. Any variable in the following list must instead be referenced in a package function such as `pre_build_*`, `pre_configure_*`, `pre_make_*` etc.: +``` + TARGET_CFLAGS TARGET_CXXFLAGS TARGET_LDFLAGS + NINJA_OPTS MAKEFLAGS + 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 +``` + +Lastly, the following variables are assigned during `scripts/build` but some packages may need to use alternative values for these variables. To do so, the package must assign alternative values in `pre_build_*`/`pre_configure_*`/`pre_make_*` etc. functions as these functions will be called after the variables are initialised with default values in `scripts/build` but before they are used by `scripts/build`. +``` + CMAKE_GENERATOR_NINJA + + TARGET_CONFIGURE_OPTS + 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 +``` + +#### Example +``` +configure_package() { + # now we know where we're building, assign a value + PKG_CONFIGURE_SCRIPT="${PKG_BUILD}/gettext-tools/configure" +} + +post_patch() { + # replace hardcoded stuff + sed -i ${PKG_CONFIGURE_SCRIPT} 's|hardcoded stuff|variable stuff|' +} + +pre_configure_target() { + # add extra flag to toolchain default + CFLAGS="$CFLAGS -DEXTRA_FLAG=yeah" +} + +post_makeinstall_target() { + # remove unused executable, install what remains + rm $INSTALL/usr/bin/bigexecutable +} +``` + +#### tools/pkgcheck + +Use `tools/pkgcheck` to verify packages. It detects the following issues: + +Issue | Level | Meaning | +| :--- | :----: | ---- | +| late binding violation | FAIL | Late binding variables referenced outside of a function - see [late binding](https://github.com/LibreELEC/LibreELEC.tv/blob/master/packages/readme.md#late-binding-variable-assignment) | +| duplicate function def | FAIL | Function defined multiple times, only last definition will be used | +| bad func - missing brace | FAIL | Opening brace (`{`) for function definition should be on same line as the function def, ie. `pre_configure_target() {` | +| intertwined vars & funcs | WARN | Variable assignments and logic is intertwined with functions - this is cosmetic, but variables and logic should be specified before all functions | +| unknown function | WARN | Could be a misspelled function, ie. `per_configure_target() {` which might fail silently.| +| ignored depends assign | WARN | Values assigned to `PKG_DEPENDS_*` outside of the global section or `configure_package()` will be ignored. | + + +## Add a new package to the Image +1. Think about, why you need it in the image. + * new multimedia tool + * add a new network tool + * new kernel driver + * ... +2. Find a place in the packages tree + * look into the package tree structure, which is generally self explanatory. + * do not place it in an existing package (directory that includes a `package.mk`) + * when you found a place, create a directory with the name of your package (use same value for `PKG_NAME`!!) +3. Create an initial `package.mk` + * you can find a template under `packages/package.mk.template`. Copy the template into the new directory and call it `package.mk` + * apply any required changes to your new `package.mk` +4. Find a place in the dependency tree + * when it extend an existing package, add it there to the `PKG_DEPENDS_TARGET`/`PKG_DEPENDS_HOST` etc. + * take a look into the path `packages/virtual`, there you should find a virtual packages, that match your new package (misc-packages should be the last option) +5. Now you can build your image + * after the build, inside the `BUILD_DIR` (normally build.*) folder you should find a directory with your package name and -version, eg. `widget-1.2.3`. + +## Example +``` +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="mariadb-connector-c" +PKG_VERSION="3.0.2" +PKG_SHA256="f44f436fc35e081db3a56516de9e3bb11ae96838e75d58910be28ddd2bc56d88" +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 connect 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/rust/bindgen-cli/package.mk b/packages/rust/bindgen-cli/package.mk new file mode 100644 index 0000000000..b97e80eb23 --- /dev/null +++ b/packages/rust/bindgen-cli/package.mk @@ -0,0 +1,27 @@ +# spdx-license-identifier: gpl-2.0-only +# copyright (c) 2024-present team libreelec (https://libreelec.tv) + +PKG_NAME="bindgen-cli" +PKG_VERSION="0.72.0" +PKG_SHA256="1da7050a17fdab0e20d5d8c20d48cddce2973e8b7cb0afc15185bfad22f8ce5b" +PKG_LICENSE="BSD-3-Clause" +PKG_SITE="https://rust-lang.github.io/rust-bindgen/" +PKG_URL="https://github.com/rust-lang/rust-bindgen/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="cargo:host" +PKG_LONGDESC="Automatically generates Rust FFI bindings to C and some C++ libraries" +PKG_TOOLCHAIN="manual" + +configure_host() { + cd ${PKG_BUILD} +} + +make_host() { + cd ${PKG_BUILD} + + cargo build -v --target ${RUST_HOST} --release +} + +makeinstall_host() { + mkdir -p ${TOOLCHAIN}/bin + cp -a ${PKG_BUILD}/.${RUST_HOST}/target/${RUST_HOST}/release/bindgen ${TOOLCHAIN}/bin/ +} diff --git a/packages/rust/cargo-snapshot/package.mk b/packages/rust/cargo-snapshot/package.mk new file mode 100644 index 0000000000..4c8efdf05c --- /dev/null +++ b/packages/rust/cargo-snapshot/package.mk @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="cargo-snapshot" +PKG_VERSION="$(get_pkg_version rust)" +PKG_LICENSE="MIT" +PKG_SITE="https://www.rust-lang.org" +PKG_LONGDESC="cargo bootstrap package" +PKG_TOOLCHAIN="manual" + +case "${MACHINE_HARDWARE_NAME}" in + "aarch64") + PKG_SHA256="5aa43865f2002914ce4fca8916b4403bfca62f17e779ad368f6a17553296a58b" + PKG_URL="https://static.rust-lang.org/dist/cargo-${PKG_VERSION}-${MACHINE_HARDWARE_NAME}-unknown-linux-gnu.tar.xz" + ;; + "arm") + PKG_SHA256="ad1b3737e7ac3a736a95f37ddd9a5d2d19f40dfc89197d544e9ca593c09f4dc7" + PKG_URL="https://static.rust-lang.org/dist/cargo-${PKG_VERSION}-${MACHINE_HARDWARE_NAME}-unknown-linux-gnueabihf.tar.xz" + ;; + "x86_64") + PKG_SHA256="856962610ee821648cee32e3d6abac667af7bb7ea6ec6f3d184cc31e66044f6b" + PKG_URL="https://static.rust-lang.org/dist/cargo-${PKG_VERSION}-${MACHINE_HARDWARE_NAME}-unknown-linux-gnu.tar.xz" + ;; +esac +PKG_SOURCE_NAME="cargo-snapshot_${PKG_VERSION}_${ARCH}.tar.xz" diff --git a/packages/rust/cargo/package.mk b/packages/rust/cargo/package.mk new file mode 100644 index 0000000000..1cabd949fa --- /dev/null +++ b/packages/rust/cargo/package.mk @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="cargo" +PKG_VERSION="$(get_pkg_version rust)" +PKG_LICENSE="MIT" +PKG_SITE="https://www.rust-lang.org" +PKG_DEPENDS_HOST="openssl:host rust:host" +PKG_DEPENDS_UNPACK="cargo-snapshot rust" +PKG_LONGDESC="Cargo is the Rust package manager" +PKG_TOOLCHAIN="manual" + +pre_configure_host() { + "$(get_build_dir cargo-snapshot)/install.sh" --prefix="${PKG_BUILD}/cargo-snapshot" --disable-ldconfig +} + +configure_host() { + cd ${PKG_BUILD} +} + +make_host() { + cd ${PKG_BUILD} + + export RUSTC_BOOTSTRAP="1" + + ./cargo-snapshot/bin/cargo build -v --target ${RUST_HOST} --release --manifest-path="$(get_build_dir rust)/src/tools/cargo/Cargo.toml" +} + +makeinstall_host() { + mkdir -p ${TOOLCHAIN}/bin + cp -a ${PKG_BUILD}/.${RUST_HOST}/target/${RUST_HOST}/release/cargo ${TOOLCHAIN}/bin/ +} diff --git a/packages/rust/cbindgen/package.mk b/packages/rust/cbindgen/package.mk new file mode 100644 index 0000000000..eba50b94bc --- /dev/null +++ b/packages/rust/cbindgen/package.mk @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2025-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="cbindgen" +PKG_VERSION="0.29.0" +PKG_SHA256="6697f449d4a15d814d991249a611af961c97e36d9344c7ced6df35c5c25b40cc" +PKG_LICENSE="MPL-2.0" +PKG_SITE="https://github.com/mozilla/bindgen" +PKG_URL="https://github.com/mozilla/cbindgen/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="cargo:host" +PKG_LONGDESC="A project for generating C bindings from Rust code" +PKG_TOOLCHAIN="manual" + +configure_host() { + cd ${PKG_BUILD} +} + +make_host() { + cd ${PKG_BUILD} + + cargo build -v --target ${RUST_HOST} --release +} + +makeinstall_host() { + mkdir -p ${TOOLCHAIN}/bin + cp -a ${PKG_BUILD}/.${RUST_HOST}/target/${RUST_HOST}/release/cbindgen ${TOOLCHAIN}/bin/ +} diff --git a/packages/rust/rust-std-snapshot/package.mk b/packages/rust/rust-std-snapshot/package.mk new file mode 100644 index 0000000000..a13fdbe98f --- /dev/null +++ b/packages/rust/rust-std-snapshot/package.mk @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="rust-std-snapshot" +PKG_VERSION="$(get_pkg_version rust)" +PKG_LICENSE="MIT" +PKG_SITE="https://www.rust-lang.org" +PKG_LONGDESC="rust std library bootstrap package" +PKG_TOOLCHAIN="manual" + +case "${MACHINE_HARDWARE_NAME}" in + "aarch64") + PKG_SHA256="e9ac4ff3c87247a2195fcceddbf1bdeee5c4fd337f014d8f4c4e3ac99002021f" + PKG_URL="https://static.rust-lang.org/dist/rust-std-${PKG_VERSION}-${MACHINE_HARDWARE_NAME}-unknown-linux-gnu.tar.xz" + ;; + "arm") + PKG_SHA256="b5e1f168fa02ad57e1ace9ac3d379a9c95f816a26f12156216521a22e192f123" + PKG_URL="https://static.rust-lang.org/dist/rust-std-${PKG_VERSION}-${MACHINE_HARDWARE_NAME}-unknown-linux-gnueabihf.tar.xz" + ;; + "x86_64") + PKG_SHA256="36d7eacf46bd5199cb433e49a9ed9c9b380d82f8a0ebc05e89b43b51c070c955" + PKG_URL="https://static.rust-lang.org/dist/rust-std-${PKG_VERSION}-${MACHINE_HARDWARE_NAME}-unknown-linux-gnu.tar.xz" + ;; +esac +PKG_SOURCE_NAME="rust-std-snapshot_${PKG_VERSION}_${ARCH}.tar.xz" diff --git a/packages/rust/rust/package.mk b/packages/rust/rust/package.mk new file mode 100644 index 0000000000..81efe2f8da --- /dev/null +++ b/packages/rust/rust/package.mk @@ -0,0 +1,131 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="rust" +PKG_VERSION="1.88.0" +PKG_SHA256="3a97544434848ae3d193d1d6bc83d6f24cb85c261ad95f955fde47ec64cfcfbe" +PKG_LICENSE="MIT" +PKG_SITE="https://www.rust-lang.org" +PKG_URL="https://static.rust-lang.org/dist/rustc-${PKG_VERSION}-src.tar.gz" +PKG_DEPENDS_HOST="toolchain llvm:host" +PKG_DEPENDS_UNPACK="rustc-snapshot rust-std-snapshot cargo-snapshot" +PKG_LONGDESC="A systems programming language that prevents segfaults, and guarantees thread safety." +PKG_TOOLCHAIN="manual" + +pre_configure_host() { + "$(get_build_dir rustc-snapshot)/install.sh" --prefix="${PKG_BUILD}/rust-snapshot" --disable-ldconfig + "$(get_build_dir rust-std-snapshot)/install.sh" --prefix="${PKG_BUILD}/rust-snapshot" --disable-ldconfig + "$(get_build_dir cargo-snapshot)/install.sh" --prefix="${PKG_BUILD}/rust-snapshot" --disable-ldconfig +} + +configure_host() { + + mkdir -p ${PKG_BUILD}/targets + + case "${TARGET_ARCH}" in + "arm") + # the arm target is special because we specify the subarch. ie armv8a + cp -a ${PKG_DIR}/targets/arm-libreelec-linux-gnueabihf.json ${PKG_BUILD}/targets/${TARGET_NAME}.json + ;; + "aarch64" | "x86_64") + cp -a ${PKG_DIR}/targets/${TARGET_NAME}.json ${PKG_BUILD}/targets/${TARGET_NAME}.json + ;; + esac + + cat >${PKG_BUILD}/config.toml <${CARGO_HOME}/config.toml </dev/null "/lib${ABI}"'$') \ +- && libdir='${exec_prefix}/'"lib${ABI}" ++ && libdir='${exec_prefix}/'"lib" + fi + ;; + # On freebsd, it seems 32-bit libraries are in lib32, +--- a/configure.ac 2023-06-01 18:40:35.000000000 +0000 ++++ b/configure.ac 2023-06-24 08:24:18.442874885 +0000 +@@ -431,7 +431,7 @@ + # symlink names. Use -P option, and hope it's portable enough. + test -d /usr/lib${ABI} \ + && (cd /usr/lib${ABI} && pwd -P | grep >/dev/null "/lib${ABI}"'$') \ +- && libdir='${exec_prefix}/'"lib${ABI}" ++ && libdir='${exec_prefix}/'"lib" + fi + ;; + # On freebsd, it seems 32-bit libraries are in lib32, diff --git a/packages/security/nspr/package.mk b/packages/security/nspr/package.mk new file mode 100644 index 0000000000..5d47bef9ef --- /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.36" +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="autotools:host gcc:host 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 -cfg-libs" + +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 0000000000..4a26b57311 --- /dev/null +++ b/packages/security/nss/package.mk @@ -0,0 +1,85 @@ +# 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.113.1" +PKG_SHA256="ae99a9a473f8117f542dfb33daa26a584db21776ef053b48cd24fa7b9d802dc7" +PKG_LICENSE="Mozilla Public License" +PKG_SITE="http://ftp.mozilla.org/" +PKG_URL="https://ftp.mozilla.org/pub/security/nss/releases/NSS_${PKG_VERSION//./_}_RTM/src/nss-${PKG_VERSION}-with-nspr-$(get_pkg_version nspr).tar.gz" +PKG_DEPENDS_HOST="nspr:host zlib:host" +PKG_DEPENDS_TARGET="make:host gcc:host 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" + +post_patch() { + echo "DEFINES += -DNSS_FIPS_DISABLED" >> ${PKG_BUILD}/nss/coreconf/config.mk +} + +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 + 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" + + local TARGET_x86_64="" + [ "${TARGET_ARCH}" != "x86_64" ] && TARGET_x86_64="NSS_DISABLE_AVX2=1" + + make ${TARGET_x86_64} clean || true + rm -rf ${PKG_BUILD}/dist + + make BUILD_OPT=1 ${TARGET_USE_64} ${TARGET_x86_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 + 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 ${PKG_INSTALL}/usr/lib + cp -PL dist/Linux*/lib/*.so ${PKG_INSTALL}/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 0000000000..46cc6c0321 --- /dev/null +++ b/packages/security/nss/patches/nss-02_3.15.5-standalone-1.patch @@ -0,0 +1,243 @@ +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.orig 2020-12-19 09:07:22.015285016 +0000 ++++ a/nss/Makefile 2020-12-19 09:17:06.966350898 +0000 +@@ -48,7 +48,6 @@ + ####################################################################### + + nss_build_all: +- $(MAKE) build_nspr + $(MAKE) all + $(MAKE) latest + +--- 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,7 +10,7 @@ + + RELEASE = nss + +-DIRS = coreconf lib cmd cpputil gtests ++DIRS = coreconf lib cmd config + + HAVE_ALL_TARGET := 1 + 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 0000000000..54234a54d3 --- /dev/null +++ b/packages/security/nss/patches/nss-04-skip_shlibsign.patch @@ -0,0 +1,13 @@ +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,7 +95,9 @@ + endif + endif + ++ifndef SKIP_SHLIBSIGN + libs: install + ifdef CHECKLOC + $(MAKE) $(CHECKLOC) + endif ++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 0000000000..67fb94c3cc --- /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-12-fix-build-of-cmd-with-nssutil.patch b/packages/security/nss/patches/nss-12-fix-build-of-cmd-with-nssutil.patch new file mode 100644 index 0000000000..1b0ebb431a --- /dev/null +++ b/packages/security/nss/patches/nss-12-fix-build-of-cmd-with-nssutil.patch @@ -0,0 +1,18 @@ +--- a/nss/cmd/platlibs.mk 2024-08-24 11:00:43.573034453 +0000 ++++ b/nss/cmd/platlibs.mk 2024-08-24 11:00:46.506390708 +0000 +@@ -181,6 +181,7 @@ + -l$(SQLITE_LIB_NAME) \ + -L$(NSSUTIL_LIB_DIR) \ + -lnssutil3 \ ++ -lnssutil \ + -L$(NSPR_LIB_DIR) \ + -lplc4 \ + -lplds4 \ +@@ -226,6 +227,7 @@ + -L$(DIST)/lib \ + -L$(NSSUTIL_LIB_DIR) \ + -lnssutil3 \ ++ -lnssutil \ + -L$(NSPR_LIB_DIR) \ + -lplc4 \ + -lplds4 \ diff --git a/packages/security/openssl/cert/cacert.pem b/packages/security/openssl/cert/cacert.pem new file mode 100644 index 0000000000..a51a66754f --- /dev/null +++ b/packages/security/openssl/cert/cacert.pem @@ -0,0 +1,3480 @@ +## +## Bundle of CA Root Certificates +## +## Certificate data from Mozilla as of: Tue Jul 8 11:42:16 2025 GMT +## +## Find updated versions here: https://curl.se/docs/caextract.html +## +## 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://raw.githubusercontent.com/mozilla-firefox/firefox/refs/heads/release/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.29. +## SHA256: 579f336ace2e5717b8ecc06002ce0cce96f70623d188e1999c34b0f77696d3e9 +## + + +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----- + +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----- +MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT +EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMzAeFw0wNjExMjQx +OTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4IC +DwAwggIKAoICAQDMV0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNgg +DhoB4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUrH556VOij +KTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd8lyyBTNvijbO0BNO/79K +DDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9CabwvvWhDFlaJKjdhkf2mrk7AyxRllDdLkgbv +BNDInIjbC3uBr7E9KsRlOni27tyAsdLTmZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwp +p5ijJUMv7/FfJuGITfhebtfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8 +nT8KKdjcT5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDtWAEX +MJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZc6tsgLjoC2SToJyM +Gf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A4iLItLRkT9a6fUg+qGkM17uGcclz +uD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYDVR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHT +BgkrBgEEAb5YAAMwgcUwgZMGCCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmlj +YXRlIGNvbnN0aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0 +aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVudC4wLQYIKwYB +BQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2NwczALBgNVHQ8EBAMCAQYwHQYD +VR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4GA1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4 +ywLQoUmkRzBFMQswCQYDVQQGEwJCTTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UE +AxMSUXVvVmFkaXMgUm9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZV +qyM07ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSemd1o417+s +hvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd+LJ2w/w4E6oM3kJpK27z +POuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2 +Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadNt54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp +8kokUvd0/bpO5qgdAm6xDYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBC +bjPsMZ57k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6szHXu +g/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0jWy10QJLZYxkNc91p +vGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeTmJlglFwjz1onl14LBQaTNx47aTbr +qZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK4SVhM7JZG+Ju1zdXtg2pEto= +-----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----- + +SwissSign Gold CA - G2 +====================== +-----BEGIN CERTIFICATE----- +MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkNIMRUw +EwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzIwHhcN +MDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBFMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dp +c3NTaWduIEFHMR8wHQYDVQQDExZTd2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUq +t2/876LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+bbqBHH5C +jCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c6bM8K8vzARO/Ws/BtQpg +vd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqEemA8atufK+ze3gE/bk3lUIbLtK/tREDF +ylqM2tIrfKjuvqblCqoOpd8FUrdVxyJdMmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvR +AiTysybUa9oEVeXBCsdtMDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuend +jIj3o02yMszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69yFGkO +peUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPiaG59je883WX0XaxR +7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxMgI93e2CaHt+28kgeDrpOVG2Y4OGi +GqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUWyV7lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64 +OfPAeGZe6Drn8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov +L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe645R88a7A3hfm +5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczOUYrHUDFu4Up+GC9pWbY9ZIEr +44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOf +Mke6UiI0HTJ6CVanfCU2qT1L2sCCbwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6m +Gu6uLftIdxf+u+yvGPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxp +mo/a77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCChdiDyyJk +vC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid392qgQmwLOM7XdVAyksLf +KzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEppLd6leNcG2mqeSz53OiATIgHQv2ieY2Br +NU0LbbqhPcCT4H8js1WtciVORvnSFu+wZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6Lqj +viOvrv1vA+ACOzB2+httQc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ +-----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----- + +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----- + +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----- + +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----- + +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----- + +Izenpe.com +========== +-----BEGIN CERTIFICATE----- +MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4MQswCQYDVQQG +EwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wHhcNMDcxMjEz +MTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMu +QS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ +03rKDx6sp4boFmVqscIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAK +ClaOxdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6HLmYRY2xU ++zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFXuaOKmMPsOzTFlUFpfnXC +PCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQDyCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxT +OTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbK +F7jJeodWLBoBHmy+E60QrLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK +0GqfvEyNBjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8Lhij+ +0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIBQFqNeb+Lz0vPqhbB +leStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+HMh3/1uaD7euBUbl8agW7EekFwID +AQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2luZm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+ +SVpFTlBFIFMuQS4gLSBDSUYgQTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBG +NjIgUzgxQzBBBgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx +MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O +BBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUAA4ICAQB4pgwWSp9MiDrAyw6l +Fn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWblaQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbga +kEyrkgPH7UIBzg/YsfqikuFgba56awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8q +hT/AQKM6WfxZSzwoJNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Cs +g1lwLDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCTVyvehQP5 +aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGkLhObNA5me0mrZJfQRsN5 +nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJbUjWumDqtujWTI6cfSN01RpiyEGjkpTHC +ClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZo +Q0iy2+tzJOeRf1SktoA+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1Z +WrOZyGlsQyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw== +-----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----- + +Actalis Authentication Root CA +============================== +-----BEGIN CERTIFICATE----- +MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCSVQxDjAM +BgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UE +AwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDky +MjExMjIwMlowazELMAkGA1UEBhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlz +IFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290 +IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNvUTufClrJ +wkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX4ay8IMKx4INRimlNAJZa +by/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9KK3giq0itFZljoZUj5NDKd45RnijMCO6 +zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1f +YVEiVRvjRuPjPdA1YprbrxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2 +oxgkg4YQ51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2Fbe8l +EfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxeKF+w6D9Fz8+vm2/7 +hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4Fv6MGn8i1zeQf1xcGDXqVdFUNaBr8 +EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbnfpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5 +jF66CyCU3nuDuP/jVo23Eek7jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLY +iDrIn3hm7YnzezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt +ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQALe3KHwGCmSUyI +WOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70jsNjLiNmsGe+b7bAEzlgqqI0 +JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDzWochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKx +K3JCaKygvU5a2hi/a5iB0P2avl4VSM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+ +Xlff1ANATIGk0k9jpwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC +4yyXX04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+OkfcvHlXHo +2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7RK4X9p2jIugErsWx0Hbhz +lefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btUZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXem +OR/qnuOf0GZvBeyqdn6/axag67XH/JJULysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9 +vwGYT7JZVEc+NHt4bVaTLnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg== +-----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----- + +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----- +MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCBhTELMAkGA1UE +BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG +A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwHhcNMTAwMTE5MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMC +R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE +ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR6FSS0gpWsawNJN3Fz0Rn +dJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8Xpz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZ +FGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+ +5eNu/Nio5JIk2kNrYrhV/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pG +x8cgoLEfZd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z+pUX +2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7wqP/0uK3pN/u6uPQL +OvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZahSL0896+1DSJMwBGB7FY79tOi4lu3 +sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVICu9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+C +GCe01a60y1Dma/RMhnEw6abfFobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5 +WdYgGq/yapiqcrxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E +FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w +DQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvlwFTPoCWOAvn9sKIN9SCYPBMt +rFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+ +nq6PK7o9mfjYcwlYRm6mnPTXJ9OV2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSg +tZx8jb8uk2IntznaFxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwW +sRqZCuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiKboHGhfKp +pC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmckejkk9u+UJueBPSZI9FoJA +zMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yLS0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHq +ZJx64SIDqZxubw5lT2yHh17zbqD5daWbQOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk52 +7RH89elWsn2/x20Kk4yl0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7I +LaZRfyHBNVOFBkpdn627G190 +-----END CERTIFICATE----- + +USERTrust RSA Certification Authority +===================================== +-----BEGIN CERTIFICATE----- +MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCBiDELMAkGA1UE +BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK +ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UE +BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK +ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCAEmUXNg7D2wiz +0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2j +Y0K2dvKpOyuR+OJv0OwWIJAJPuLodMkYtJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFn +RghRy4YUVD+8M/5+bJz/Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O ++T23LLb2VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT79uq +/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6c0Plfg6lZrEpfDKE +Y1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmTYo61Zs8liM2EuLE/pDkP2QKe6xJM +lXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97lc6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8 +yexDJtC/QV9AqURE9JnnV4eeUB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+ +eLf8ZxXhyVeEHg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd +BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPFUp/L+M+ZBn8b2kMVn54CVVeW +FPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KOVWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ +7l8wXEskEVX/JJpuXior7gtNn3/3ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQ +Eg9zKC7F4iRO/Fjs8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM +8WcRiQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYzeSf7dNXGi +FSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZXHlKYC6SQK5MNyosycdi +yA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9c +J2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRBVXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGw +sAvgnEzDHNb842m1R0aBL6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gx +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 - R5 +=========================== +-----BEGIN CERTIFICATE----- +MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEkMCIGA1UECxMb +R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD +EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb +R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD +EwpHbG9iYWxTaWduMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6 +SFkc8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8kehOvRnkmS +h5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd +BgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYIKoZIzj0EAwMDaAAwZQIxAOVpEslu28Yx +uglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7 +yFz9SO8NdCKoCOJuxUnOxwy8p2Fp8fc74SrL+SvzZpA3 +-----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----- + +SSL.com Root Certification Authority RSA +======================================== +-----BEGIN CERTIFICATE----- +MIIF3TCCA8WgAwIBAgIIeyyb0xaAMpkwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxDjAM +BgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24x +MTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBSU0EwHhcNMTYw +MjEyMTczOTM5WhcNNDEwMjEyMTczOTM5WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx +EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NM +LmNvbSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTCCAiIwDQYJKoZIhvcNAQEBBQAD +ggIPADCCAgoCggIBAPkP3aMrfcvQKv7sZ4Wm5y4bunfh4/WvpOz6Sl2RxFdHaxh3a3by/ZPkPQ/C +Fp4LZsNWlJ4Xg4XOVu/yFv0AYvUiCVToZRdOQbngT0aXqhvIuG5iXmmxX9sqAn78bMrzQdjt0Oj8 +P2FI7bADFB0QDksZ4LtO7IZl/zbzXmcCC52GVWH9ejjt/uIZALdvoVBidXQ8oPrIJZK0bnoix/ge +oeOy3ZExqysdBP+lSgQ36YWkMyv94tZVNHwZpEpox7Ko07fKoZOI68GXvIz5HdkihCR0xwQ9aqkp +k8zruFvh/l8lqjRYyMEjVJ0bmBHDOJx+PYZspQ9AhnwC9FwCTyjLrnGfDzrIM/4RJTXq/LrFYD3Z +fBjVsqnTdXgDciLKOsMf7yzlLqn6niy2UUb9rwPW6mBo6oUWNmuF6R7As93EJNyAKoFBbZQ+yODJ +gUEAnl6/f8UImKIYLEJAs/lvOCdLToD0PYFH4Ih86hzOtXVcUS4cK38acijnALXRdMbX5J+tB5O2 +UzU1/Dfkw/ZdFr4hc96SCvigY2q8lpJqPvi8ZVWb3vUNiSYE/CUapiVpy8JtynziWV+XrOvvLsi8 +1xtZPCvM8hnIk2snYxnP/Okm+Mpxm3+T/jRnhE6Z6/yzeAkzcLpmpnbtG3PrGqUNxCITIJRWCk4s +bE6x/c+cCbqiM+2HAgMBAAGjYzBhMB0GA1UdDgQWBBTdBAkHovV6fVJTEpKV7jiAJQ2mWTAPBgNV +HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFN0ECQei9Xp9UlMSkpXuOIAlDaZZMA4GA1UdDwEB/wQE +AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAIBgRlCn7Jp0cHh5wYfGVcpNxJK1ok1iOMq8bs3AD/CUr +dIWQPXhq9LmLpZc7tRiRux6n+UBbkflVma8eEdBcHadm47GUBwwyOabqG7B52B2ccETjit3E+ZUf +ijhDPwGFpUenPUayvOUiaPd7nNgsPgohyC0zrL/FgZkxdMF1ccW+sfAjRfSda/wZY52jvATGGAsl +u1OJD7OAUN5F7kR/q5R4ZJjT9ijdh9hwZXT7DrkT66cPYakylszeu+1jTBi7qUD3oFRuIIhxdRjq +erQ0cuAjJ3dctpDqhiVAq+8zD8ufgr6iIPv2tS0a5sKFsXQP+8hlAqRSAUfdSSLBv9jra6x+3uxj +MxW3IwiPxg+NQVrdjsW5j+VFP3jbutIbQLH+cU0/4IGiul607BXgk90IH37hVZkLId6Tngr75qNJ +vTYw/ud3sqB1l7UtgYgXZSD32pAAn8lSzDLKNXz1PQ/YK9f1JmzJBjSWFupwWRoyeXkLtoh/D1JI +Pb9s2KJELtFOt3JY04kTlf5Eq/jXixtunLwsoFvVagCvXzfh1foQC5ichucmj87w7G6KVwuA406y +wKBjYZC6VWg3dGq2ktufoYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NI +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----- + +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----- +MIIFzzCCA7egAwIBAgIUCBZfikyl7ADJk0DfxMauI7gcWqQwDQYJKoZIhvcNAQELBQAwbzELMAkG +A1UEBhMCSEsxEjAQBgNVBAgTCUhvbmcgS29uZzESMBAGA1UEBxMJSG9uZyBLb25nMRYwFAYDVQQK +Ew1Ib25na29uZyBQb3N0MSAwHgYDVQQDExdIb25na29uZyBQb3N0IFJvb3QgQ0EgMzAeFw0xNzA2 +MDMwMjI5NDZaFw00MjA2MDMwMjI5NDZaMG8xCzAJBgNVBAYTAkhLMRIwEAYDVQQIEwlIb25nIEtv +bmcxEjAQBgNVBAcTCUhvbmcgS29uZzEWMBQGA1UEChMNSG9uZ2tvbmcgUG9zdDEgMB4GA1UEAxMX +SG9uZ2tvbmcgUG9zdCBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz +iNfqzg8gTr7m1gNt7ln8wlffKWihgw4+aMdoWJwcYEuJQwy51BWy7sFOdem1p+/l6TWZ5Mwc50tf +jTMwIDNT2aa71T4Tjukfh0mtUC1Qyhi+AViiE3CWu4mIVoBc+L0sPOFMV4i707mV78vH9toxdCim +5lSJ9UExyuUmGs2C4HDaOym71QP1mbpV9WTRYA6ziUm4ii8F0oRFKHyPaFASePwLtVPLwpgchKOe +sL4jpNrcyCse2m5FHomY2vkALgbpDDtw1VAliJnLzXNg99X/NWfFobxeq81KuEXryGgeDQ0URhLj +0mRiikKYvLTGCAj4/ahMZJx2Ab0vqWwzD9g/KLg8aQFChn5pwckGyuV6RmXpwtZQQS4/t+TtbNe/ +JgERohYpSms0BpDsE9K2+2p20jzt8NYt3eEV7KObLyzJPivkaTv/ciWxNoZbx39ri1UbSsUgYT2u +y1DhCDq+sI9jQVMwCFk8mB13umOResoQUGC/8Ne8lYePl8X+l2oBlKN8W4UdKjk60FSh0Tlxnf0h ++bV78OLgAo9uliQlLKAeLKjEiafv7ZkGL7YKTE/bosw3Gq9HhS2KX8Q0NEwA/RiTZxPRN+ZItIsG +xVd7GYYKecsAyVKvQv83j+GjHno9UKtjBucVtT+2RTeUN7F+8kjDf8V1/peNRY8apxpyKBpADwID +AQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQXnc0e +i9Y5K3DTXNSguB+wAPzFYTAdBgNVHQ4EFgQUF53NHovWOStw01zUoLgfsAD8xWEwDQYJKoZIhvcN +AQELBQADggIBAFbVe27mIgHSQpsY1Q7XZiNc4/6gx5LS6ZStS6LG7BJ8dNVI0lkUmcDrudHr9Egw +W62nV3OZqdPlt9EuWSRY3GguLmLYauRwCy0gUCCkMpXRAJi70/33MvJJrsZ64Ee+bs7Lo3I6LWld +y8joRTnU+kLBEUx3XZL7av9YROXrgZ6voJmtvqkBZss4HTzfQx/0TW60uhdG/H39h4F5ag0zD/ov ++BS5gLNdTaqX4fnkGMX41TiMJjz98iji7lpJiCzfeT2OnpA8vUFKOt1b9pq0zj8lMH8yfaIDlNDc +eqFS3m6TjRgm/VWsvY+b0s+v54Ysyx8Jb6NvqYTUc79NoXQbTiNg8swOqn+knEwlqLJmOzj/2ZQw +9nKEvmhVEA/GcywWaZMH/rFF7buiVWqw2rVKAiUnhde3t4ZEFolsgCs+l6mc1X5VTMbeRRAc6uk7 +nwNT7u56AQIWeNTowr5GdogTPyK7SBIdUgC0An4hGh6cJfTzPV4e0hz5sy229zdcxsshTrD3mUcY +hcErulWuBurQB7Lcq9CClnXO0lD+mefPL5/ndtFhKvshuzHQqp9HpLIiyhY6UFfEW0NnxWViA0kB +60PZ2Pierc+xYw5F9KBaLJstxabArahH9CdMOA0uG0k7UvToiIMrVCjU8jVStDKDYmlkDJGcn5fq +dBb9HxEGmpv0 +-----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----- +MIIF2jCCA8KgAwIBAgIMBfcOhtpJ80Y1LrqyMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJV +UzERMA8GA1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xITAfBgNVBAoMGFRydXN0d2F2 +ZSBIb2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1c3R3YXZlIEdsb2JhbCBDZXJ0aWZpY2F0aW9u +IEF1dGhvcml0eTAeFw0xNzA4MjMxOTM0MTJaFw00MjA4MjMxOTM0MTJaMIGIMQswCQYDVQQGEwJV +UzERMA8GA1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xITAfBgNVBAoMGFRydXN0d2F2 +ZSBIb2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1c3R3YXZlIEdsb2JhbCBDZXJ0aWZpY2F0aW9u +IEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALldUShLPDeS0YLOvR29 +zd24q88KPuFd5dyqCblXAj7mY2Hf8g+CY66j96xz0XznswuvCAAJWX/NKSqIk4cXGIDtiLK0thAf +LdZfVaITXdHG6wZWiYj+rDKd/VzDBcdu7oaJuogDnXIhhpCujwOl3J+IKMujkkkP7NAP4m1ET4Bq +stTnoApTAbqOl5F2brz81Ws25kCI1nsvXwXoLG0R8+eyvpJETNKXpP7ScoFDB5zpET71ixpZfR9o +WN0EACyW80OzfpgZdNmcc9kYvkHHNHnZ9GLCQ7mzJ7Aiy/k9UscwR7PJPrhq4ufogXBeQotPJqX+ +OsIgbrv4Fo7NDKm0G2x2EOFYeUY+VM6AqFcJNykbmROPDMjWLBz7BegIlT1lRtzuzWniTY+HKE40 +Cz7PFNm73bZQmq131BnW2hqIyE4bJ3XYsgjxroMwuREOzYfwhI0Vcnyh78zyiGG69Gm7DIwLdVcE +uE4qFC49DxweMqZiNu5m4iK4BUBjECLzMx10coos9TkpoNPnG4CELcU9402x/RpvumUHO1jsQkUm ++9jaJXLE9gCxInm943xZYkqcBW89zubWR2OZxiRvchLIrH+QtAuRcOi35hYQcRfO3gZPSEF9NUqj +ifLJS3tBEW1ntwiYTOURGa5CgNz7kAXU+FDKvuStx8KU1xad5hePrzb7AgMBAAGjQjBAMA8GA1Ud +EwEB/wQFMAMBAf8wHQYDVR0OBBYEFJngGWcNYtt2s9o9uFvo/ULSMQ6HMA4GA1UdDwEB/wQEAwIB +BjANBgkqhkiG9w0BAQsFAAOCAgEAmHNw4rDT7TnsTGDZqRKGFx6W0OhUKDtkLSGm+J1WE2pIPU/H +PinbbViDVD2HfSMF1OQc3Og4ZYbFdada2zUFvXfeuyk3QAUHw5RSn8pk3fEbK9xGChACMf1KaA0H +ZJDmHvUqoai7PF35owgLEQzxPy0QlG/+4jSHg9bP5Rs1bdID4bANqKCqRieCNqcVtgimQlRXtpla +4gt5kNdXElE1GYhBaCXUNxeEFfsBctyV3lImIJgm4nb1J2/6ADtKYdkNy1GTKv0WBpanI5ojSP5R +vbbEsLFUzt5sQa0WZ37b/TjNuThOssFgy50X31ieemKyJo90lZvkWx3SD92YHJtZuSPTMaCm/zjd +zyBP6VhWOmfD0faZmZ26NraAL4hHT4a/RDqA5Dccprrql5gR0IRiR2Qequ5AvzSxnI9O4fKSTx+O +856X3vOmeWqJcU9LJxdI/uz0UA9PSX3MReO9ekDFQdxhVicGaeVyQYHTtgGJoC86cnn+OjC/QezH +Yj6RS8fZMXZC+fc8Y+wmjHMMfRod6qh8h6jCJ3zhM0EPz8/8AKAigJ5Kp28AsEFFtyLKaEjFQqKu +3R3y4G5OBVixwJAWKqQ9EEC+j2Jjg6mcgn0tAumDMHzLJ8n9HmYAsC7TIS+OMxZsmO0QqAfWzJPP +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----- + +NAVER Global Root Certification Authority +========================================= +-----BEGIN CERTIFICATE----- +MIIFojCCA4qgAwIBAgIUAZQwHqIL3fXFMyqxQ0Rx+NZQTQ0wDQYJKoZIhvcNAQEMBQAwaTELMAkG +A1UEBhMCS1IxJjAkBgNVBAoMHU5BVkVSIEJVU0lORVNTIFBMQVRGT1JNIENvcnAuMTIwMAYDVQQD +DClOQVZFUiBHbG9iYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MTgwODU4 +NDJaFw0zNzA4MTgyMzU5NTlaMGkxCzAJBgNVBAYTAktSMSYwJAYDVQQKDB1OQVZFUiBCVVNJTkVT +UyBQTEFURk9STSBDb3JwLjEyMDAGA1UEAwwpTkFWRVIgR2xvYmFsIFJvb3QgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC21PGTXLVAiQqrDZBb +UGOukJR0F0Vy1ntlWilLp1agS7gvQnXp2XskWjFlqxcX0TM62RHcQDaH38dq6SZeWYp34+hInDEW ++j6RscrJo+KfziFTowI2MMtSAuXaMl3Dxeb57hHHi8lEHoSTGEq0n+USZGnQJoViAbbJAh2+g1G7 +XNr4rRVqmfeSVPc0W+m/6imBEtRTkZazkVrd/pBzKPswRrXKCAfHcXLJZtM0l/aM9BhK4dA9WkW2 +aacp+yPOiNgSnABIqKYPszuSjXEOdMWLyEz59JuOuDxp7W87UC9Y7cSw0BwbagzivESq2M0UXZR4 +Yb8ObtoqvC8MC3GmsxY/nOb5zJ9TNeIDoKAYv7vxvvTWjIcNQvcGufFt7QSUqP620wbGQGHfnZ3z +VHbOUzoBppJB7ASjjw2i1QnK1sua8e9DXcCrpUHPXFNwcMmIpi3Ua2FzUCaGYQ5fG8Ir4ozVu53B +A0K6lNpfqbDKzE0K70dpAy8i+/Eozr9dUGWokG2zdLAIx6yo0es+nPxdGoMuK8u180SdOqcXYZai +cdNwlhVNt0xz7hlcxVs+Qf6sdWA7G2POAN3aCJBitOUt7kinaxeZVL6HSuOpXgRM6xBtVNbv8ejy +YhbLgGvtPe31HzClrkvJE+2KAQHJuFFYwGY6sWZLxNUxAmLpdIQM201GLQIDAQABo0IwQDAdBgNV +HQ4EFgQU0p+I36HNLL3s9TsBAZMzJ7LrYEswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMB +Af8wDQYJKoZIhvcNAQEMBQADggIBADLKgLOdPVQG3dLSLvCkASELZ0jKbY7gyKoNqo0hV4/GPnrK +21HUUrPUloSlWGB/5QuOH/XcChWB5Tu2tyIvCZwTFrFsDDUIbatjcu3cvuzHV+YwIHHW1xDBE1UB +jCpD5EHxzzp6U5LOogMFDTjfArsQLtk70pt6wKGm+LUx5vR1yblTmXVHIloUFcd4G7ad6Qz4G3bx +hYTeodoS76TiEJd6eN4MUZeoIUCLhr0N8F5OSza7OyAfikJW4Qsav3vQIkMsRIz75Sq0bBwcupTg +E34h5prCy8VCZLQelHsIJchxzIdFV4XTnyliIoNRlwAYl3dqmJLJfGBs32x9SuRwTMKeuB330DTH +D8z7p/8Dvq1wkNoL3chtl1+afwkyQf3NosxabUzyqkn+Zvjp2DXrDige7kgvOtB5CTh8piKCk5XQ +A76+AqAF3SAi428diDRgxuYKuQl1C/AH6GmWNcf7I4GOODm4RStDeKLRLBT/DShycpWbXgnbiUSY +qqFJu3FS8r/2/yehNq+4tneI3TqkbZs0kNwUXTC/t+sX5Ie3cdCh13cV1ELX8vMxmV2b3RZtP+oG +I/hGoiLtk/bdmuYqh7GYVPEi92tF4+KOdh2ajcQGjTa3FPOdVGm3jjzVpG2Tgbet9r1ke8LJaDmg +kpzNNIaRkPpkUZ3+/uul9XXeifdy +-----END CERTIFICATE----- + +AC RAIZ FNMT-RCM SERVIDORES SEGUROS +=================================== +-----BEGIN CERTIFICATE----- +MIICbjCCAfOgAwIBAgIQYvYybOXE42hcG2LdnC6dlTAKBggqhkjOPQQDAzB4MQswCQYDVQQGEwJF +UzERMA8GA1UECgwIRk5NVC1SQ00xDjAMBgNVBAsMBUNlcmVzMRgwFgYDVQRhDA9WQVRFUy1RMjgy +NjAwNEoxLDAqBgNVBAMMI0FDIFJBSVogRk5NVC1SQ00gU0VSVklET1JFUyBTRUdVUk9TMB4XDTE4 +MTIyMDA5MzczM1oXDTQzMTIyMDA5MzczM1oweDELMAkGA1UEBhMCRVMxETAPBgNVBAoMCEZOTVQt +UkNNMQ4wDAYDVQQLDAVDZXJlczEYMBYGA1UEYQwPVkFURVMtUTI4MjYwMDRKMSwwKgYDVQQDDCNB +QyBSQUlaIEZOTVQtUkNNIFNFUlZJRE9SRVMgU0VHVVJPUzB2MBAGByqGSM49AgEGBSuBBAAiA2IA +BPa6V1PIyqvfNkpSIeSX0oNnnvBlUdBeh8dHsVnyV0ebAAKTRBdp20LHsbI6GA60XYyzZl2hNPk2 +LEnb80b8s0RpRBNm/dfF/a82Tc4DTQdxz69qBdKiQ1oKUm8BA06Oi6NCMEAwDwYDVR0TAQH/BAUw +AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFAG5L++/EYZg8k/QQW6rcx/n0m5JMAoGCCqG +SM49BAMDA2kAMGYCMQCuSuMrQMN0EfKVrRYj3k4MGuZdpSRea0R7/DjiT8ucRRcRTBQnJlU5dUoD +zBOQn5ICMQD6SmxgiHPz7riYYqnOK8LZiqZwMR2vsJRM60/G49HzYqc8/5MuB1xJAWdpEgJyv+c= +-----END CERTIFICATE----- + +GlobalSign Root R46 +=================== +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgISEdK7udcjGJ5AXwqdLdDfJWfRMA0GCSqGSIb3DQEBDAUAMEYxCzAJBgNV +BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQDExNHbG9iYWxTaWduIFJv +b3QgUjQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAX +BgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBSNDYwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCsrHQy6LNl5brtQyYdpokNRbopiLKkHWPd08Es +CVeJOaFV6Wc0dwxu5FUdUiXSE2te4R2pt32JMl8Nnp8semNgQB+msLZ4j5lUlghYruQGvGIFAha/ +r6gjA7aUD7xubMLL1aa7DOn2wQL7Id5m3RerdELv8HQvJfTqa1VbkNud316HCkD7rRlr+/fKYIje +2sGP1q7Vf9Q8g+7XFkyDRTNrJ9CG0Bwta/OrffGFqfUo0q3v84RLHIf8E6M6cqJaESvWJ3En7YEt +bWaBkoe0G1h6zD8K+kZPTXhc+CtI4wSEy132tGqzZfxCnlEmIyDLPRT5ge1lFgBPGmSXZgjPjHvj +K8Cd+RTyG/FWaha/LIWFzXg4mutCagI0GIMXTpRW+LaCtfOW3T3zvn8gdz57GSNrLNRyc0NXfeD4 +12lPFzYE+cCQYDdF3uYM2HSNrpyibXRdQr4G9dlkbgIQrImwTDsHTUB+JMWKmIJ5jqSngiCNI/on +ccnfxkF0oE32kRbcRoxfKWMxWXEM2G/CtjJ9++ZdU6Z+Ffy7dXxd7Pj2Fxzsx2sZy/N78CsHpdls +eVR2bJ0cpm4O6XkMqCNqo98bMDGfsVR7/mrLZqrcZdCinkqaByFrgY/bxFn63iLABJzjqls2k+g9 +vXqhnQt2sQvHnf3PmKgGwvgqo6GDoLclcqUC4wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYD +VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA1yrc4GHqMywptWU4jaWSf8FmSwwDQYJKoZIhvcNAQEM +BQADggIBAHx47PYCLLtbfpIrXTncvtgdokIzTfnvpCo7RGkerNlFo048p9gkUbJUHJNOxO97k4Vg +JuoJSOD1u8fpaNK7ajFxzHmuEajwmf3lH7wvqMxX63bEIaZHU1VNaL8FpO7XJqti2kM3S+LGteWy +gxk6x9PbTZ4IevPuzz5i+6zoYMzRx6Fcg0XERczzF2sUyQQCPtIkpnnpHs6i58FZFZ8d4kuaPp92 +CC1r2LpXFNqD6v6MVenQTqnMdzGxRBF6XLE+0xRFFRhiJBPSy03OXIPBNvIQtQ6IbbjhVp+J3pZm +OUdkLG5NrmJ7v2B0GbhWrJKsFjLtrWhV/pi60zTe9Mlhww6G9kuEYO4Ne7UyWHmRVSyBQ7N0H3qq +JZ4d16GLuc1CLgSkZoNNiTW2bKg2SnkheCLQQrzRQDGQob4Ez8pn7fXwgNNgyYMqIgXQBztSvwye +qiv5u+YfjyW6hY0XHgL+XVAEV8/+LbzvXMAaq7afJMbfc2hIkCwU9D9SGuTSyxTDYWnP4vkYxboz +nxSjBF25cfe1lNj2M8FawTSLfJvdkzrnE6JwYZ+vj+vYxXX4M2bUdGc6N3ec592kD3ZDZopD8p/7 +DEJ4Y9HiD2971KE9dJeFt0g5QdYg/NA6s/rob8SKunE3vouXsXgxT7PntgMTzlSdriVZzH81Xwj3 +QEUxeCp6 +-----END CERTIFICATE----- + +GlobalSign Root E46 +=================== +-----BEGIN CERTIFICATE----- +MIICCzCCAZGgAwIBAgISEdK7ujNu1LzmJGjFDYQdmOhDMAoGCCqGSM49BAMDMEYxCzAJBgNVBAYT +AkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQDExNHbG9iYWxTaWduIFJvb3Qg +RTQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNV +BAoTEEdsb2JhbFNpZ24gbnYtc2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBFNDYwdjAQBgcq +hkjOPQIBBgUrgQQAIgNiAAScDrHPt+ieUnd1NPqlRqetMhkytAepJ8qUuwzSChDH2omwlwxwEwkB +jtjqR+q+soArzfwoDdusvKSGN+1wCAB16pMLey5SnCNoIwZD7JIvU4Tb+0cUB+hflGddyXqBPCCj +QjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQxCpCPtsad0kRL +gLWi5h+xEk8blTAKBggqhkjOPQQDAwNoADBlAjEA31SQ7Zvvi5QCkxeCmb6zniz2C5GMn0oUsfZk +vLtoURMMA/cVi4RguYv/Uo7njLwcAjA8+RHUjE7AwWHCFUyqqx0LMV87HOIAl0Qx5v5zli/altP+ +CAezNIm8BZ/3Hobui3A= +-----END CERTIFICATE----- + +GLOBALTRUST 2020 +================ +-----BEGIN CERTIFICATE----- +MIIFgjCCA2qgAwIBAgILWku9WvtPilv6ZeUwDQYJKoZIhvcNAQELBQAwTTELMAkGA1UEBhMCQVQx +IzAhBgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVT +VCAyMDIwMB4XDTIwMDIxMDAwMDAwMFoXDTQwMDYxMDAwMDAwMFowTTELMAkGA1UEBhMCQVQxIzAh +BgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVTVCAy +MDIwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAri5WrRsc7/aVj6B3GyvTY4+ETUWi +D59bRatZe1E0+eyLinjF3WuvvcTfk0Uev5E4C64OFudBc/jbu9G4UeDLgztzOG53ig9ZYybNpyrO +VPu44sB8R85gfD+yc/LAGbaKkoc1DZAoouQVBGM+uq/ufF7MpotQsjj3QWPKzv9pj2gOlTblzLmM +CcpL3TGQlsjMH/1WljTbjhzqLL6FLmPdqqmV0/0plRPwyJiT2S0WR5ARg6I6IqIoV6Lr/sCMKKCm +fecqQjuCgGOlYx8ZzHyyZqjC0203b+J+BlHZRYQfEs4kUmSFC0iAToexIiIwquuuvuAC4EDosEKA +A1GqtH6qRNdDYfOiaxaJSaSjpCuKAsR49GiKweR6NrFvG5Ybd0mN1MkGco/PU+PcF4UgStyYJ9OR +JitHHmkHr96i5OTUawuzXnzUJIBHKWk7buis/UDr2O1xcSvy6Fgd60GXIsUf1DnQJ4+H4xj04KlG +DfV0OoIu0G4skaMxXDtG6nsEEFZegB31pWXogvziB4xiRfUg3kZwhqG8k9MedKZssCz3AwyIDMvU +clOGvGBG85hqwvG/Q/lwIHfKN0F5VVJjjVsSn8VoxIidrPIwq7ejMZdnrY8XD2zHc+0klGvIg5rQ +mjdJBKuxFshsSUktq6HQjJLyQUp5ISXbY9e2nKd+Qmn7OmMCAwEAAaNjMGEwDwYDVR0TAQH/BAUw +AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFNwuH9FhN3nkq9XVsxJxaD1qaJwiMB8GA1Ud +IwQYMBaAFNwuH9FhN3nkq9XVsxJxaD1qaJwiMA0GCSqGSIb3DQEBCwUAA4ICAQCR8EICaEDuw2jA +VC/f7GLDw56KoDEoqoOOpFaWEhCGVrqXctJUMHytGdUdaG/7FELYjQ7ztdGl4wJCXtzoRlgHNQIw +4Lx0SsFDKv/bGtCwr2zD/cuz9X9tAy5ZVp0tLTWMstZDFyySCstd6IwPS3BD0IL/qMy/pJTAvoe9 +iuOTe8aPmxadJ2W8esVCgmxcB9CpwYhgROmYhRZf+I/KARDOJcP5YBugxZfD0yyIMaK9MOzQ0MAS +8cE54+X1+NZK3TTN+2/BT+MAi1bikvcoskJ3ciNnxz8RFbLEAwW+uxF7Cr+obuf/WEPPm2eggAe2 +HcqtbepBEX4tdJP7wry+UUTF72glJ4DjyKDUEuzZpTcdN3y0kcra1LGWge9oXHYQSa9+pTeAsRxS +vTOBTI/53WXZFM2KJVj04sWDpQmQ1GwUY7VA3+vA/MRYfg0UFodUJ25W5HCEuGwyEn6CMUO+1918 +oa2u1qsgEu8KwxCMSZY13At1XrFP1U80DhEgB3VDRemjEdqso5nCtnkn4rnvyOL2NSl6dPrFf4IF +YqYK6miyeUcGbvJXqBUzxvd4Sj1Ce2t+/vdG6tHrju+IaFvowdlxfv1k7/9nR4hYJS8+hge9+6jl +gqispdNpQ80xiEmEU5LAsTkbOYMBMMTyqfrQA71yN2BWHzZ8vTmR9W0Nv3vXkg== +-----END CERTIFICATE----- + +ANF Secure Server Root CA +========================= +-----BEGIN CERTIFICATE----- +MIIF7zCCA9egAwIBAgIIDdPjvGz5a7EwDQYJKoZIhvcNAQELBQAwgYQxEjAQBgNVBAUTCUc2MzI4 +NzUxMDELMAkGA1UEBhMCRVMxJzAlBgNVBAoTHkFORiBBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lv +bjEUMBIGA1UECxMLQU5GIENBIFJhaXoxIjAgBgNVBAMTGUFORiBTZWN1cmUgU2VydmVyIFJvb3Qg +Q0EwHhcNMTkwOTA0MTAwMDM4WhcNMzkwODMwMTAwMDM4WjCBhDESMBAGA1UEBRMJRzYzMjg3NTEw +MQswCQYDVQQGEwJFUzEnMCUGA1UEChMeQU5GIEF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uMRQw +EgYDVQQLEwtBTkYgQ0EgUmFpejEiMCAGA1UEAxMZQU5GIFNlY3VyZSBTZXJ2ZXIgUm9vdCBDQTCC +AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANvrayvmZFSVgpCjcqQZAZ2cC4Ffc0m6p6zz +BE57lgvsEeBbphzOG9INgxwruJ4dfkUyYA8H6XdYfp9qyGFOtibBTI3/TO80sh9l2Ll49a2pcbnv +T1gdpd50IJeh7WhM3pIXS7yr/2WanvtH2Vdy8wmhrnZEE26cLUQ5vPnHO6RYPUG9tMJJo8gN0pcv +B2VSAKduyK9o7PQUlrZXH1bDOZ8rbeTzPvY1ZNoMHKGESy9LS+IsJJ1tk0DrtSOOMspvRdOoiXse +zx76W0OLzc2oD2rKDF65nkeP8Nm2CgtYZRczuSPkdxl9y0oukntPLxB3sY0vaJxizOBQ+OyRp1RM +VwnVdmPF6GUe7m1qzwmd+nxPrWAI/VaZDxUse6mAq4xhj0oHdkLePfTdsiQzW7i1o0TJrH93PB0j +7IKppuLIBkwC/qxcmZkLLxCKpvR/1Yd0DVlJRfbwcVw5Kda/SiOL9V8BY9KHcyi1Swr1+KuCLH5z +JTIdC2MKF4EA/7Z2Xue0sUDKIbvVgFHlSFJnLNJhiQcND85Cd8BEc5xEUKDbEAotlRyBr+Qc5RQe +8TZBAQIvfXOn3kLMTOmJDVb3n5HUA8ZsyY/b2BzgQJhdZpmYgG4t/wHFzstGH6wCxkPmrqKEPMVO +Hj1tyRRM4y5Bu8o5vzY8KhmqQYdOpc5LMnndkEl/AgMBAAGjYzBhMB8GA1UdIwQYMBaAFJxf0Gxj +o1+TypOYCK2Mh6UsXME3MB0GA1UdDgQWBBScX9BsY6Nfk8qTmAitjIelLFzBNzAOBgNVHQ8BAf8E +BAMCAYYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEATh65isagmD9uw2nAalxJ +UqzLK114OMHVVISfk/CHGT0sZonrDUL8zPB1hT+L9IBdeeUXZ701guLyPI59WzbLWoAAKfLOKyzx +j6ptBZNscsdW699QIyjlRRA96Gejrw5VD5AJYu9LWaL2U/HANeQvwSS9eS9OICI7/RogsKQOLHDt +dD+4E5UGUcjohybKpFtqFiGS3XNgnhAY3jyB6ugYw3yJ8otQPr0R4hUDqDZ9MwFsSBXXiJCZBMXM +5gf0vPSQ7RPi6ovDj6MzD8EpTBNO2hVWcXNyglD2mjN8orGoGjR0ZVzO0eurU+AagNjqOknkJjCb +5RyKqKkVMoaZkgoQI1YS4PbOTOK7vtuNknMBZi9iPrJyJ0U27U1W45eZ/zo1PqVUSlJZS2Db7v54 +EX9K3BR5YLZrZAPbFYPhor72I5dQ8AkzNqdxliXzuUJ92zg/LFis6ELhDtjTO0wugumDLmsx2d1H +hk9tl5EuT+IocTUW0fJz/iUrB0ckYyfI+PbZa/wSMVYIwFNCr5zQM378BvAxRAMU8Vjq8moNqRGy +g77FGr8H6lnco4g175x2MjxNBiLOFeXdntiP2t7SxDnlF4HPOEfrf4htWRvfn0IUrn7PqLBmZdo3 +r5+qPeoott7VMVgWglvquxl1AnMaykgaIZOQCo6ThKd9OyMYkomgjaw= +-----END CERTIFICATE----- + +Certum EC-384 CA +================ +-----BEGIN CERTIFICATE----- +MIICZTCCAeugAwIBAgIQeI8nXIESUiClBNAt3bpz9DAKBggqhkjOPQQDAzB0MQswCQYDVQQGEwJQ +TDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2Vy +dGlmaWNhdGlvbiBBdXRob3JpdHkxGTAXBgNVBAMTEENlcnR1bSBFQy0zODQgQ0EwHhcNMTgwMzI2 +MDcyNDU0WhcNNDMwMzI2MDcyNDU0WjB0MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERh +dGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkx +GTAXBgNVBAMTEENlcnR1bSBFQy0zODQgQ0EwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATEKI6rGFtq +vm5kN2PkzeyrOvfMobgOgknXhimfoZTy42B4mIF4Bk3y7JoOV2CDn7TmFy8as10CW4kjPMIRBSqn +iBMY81CE1700LCeJVf/OTOffph8oxPBUw7l8t1Ot68KjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD +VR0OBBYEFI0GZnQkdjrzife81r1HfS+8EF9LMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNo +ADBlAjADVS2m5hjEfO/JUG7BJw+ch69u1RsIGL2SKcHvlJF40jocVYli5RsJHrpka/F2tNQCMQC0 +QoSZ/6vnnvuRlydd3LBbMHHOXjgaatkl5+r3YZJW+OraNsKHZZYuciUvf9/DE8k= +-----END CERTIFICATE----- + +Certum Trusted Root CA +====================== +-----BEGIN CERTIFICATE----- +MIIFwDCCA6igAwIBAgIQHr9ZULjJgDdMBvfrVU+17TANBgkqhkiG9w0BAQ0FADB6MQswCQYDVQQG +EwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0g +Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkxHzAdBgNVBAMTFkNlcnR1bSBUcnVzdGVkIFJvb3QgQ0Ew +HhcNMTgwMzE2MTIxMDEzWhcNNDMwMzE2MTIxMDEzWjB6MQswCQYDVQQGEwJQTDEhMB8GA1UEChMY +QXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkxHzAdBgNVBAMTFkNlcnR1bSBUcnVzdGVkIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQDRLY67tzbqbTeRn06TpwXkKQMlzhyC93yZn0EGze2jusDbCSzBfN8p +fktlL5On1AFrAygYo9idBcEq2EXxkd7fO9CAAozPOA/qp1x4EaTByIVcJdPTsuclzxFUl6s1wB52 +HO8AU5853BSlLCIls3Jy/I2z5T4IHhQqNwuIPMqw9MjCoa68wb4pZ1Xi/K1ZXP69VyywkI3C7Te2 +fJmItdUDmj0VDT06qKhF8JVOJVkdzZhpu9PMMsmN74H+rX2Ju7pgE8pllWeg8xn2A1bUatMn4qGt +g/BKEiJ3HAVz4hlxQsDsdUaakFjgao4rpUYwBI4Zshfjvqm6f1bxJAPXsiEodg42MEx51UGamqi4 +NboMOvJEGyCI98Ul1z3G4z5D3Yf+xOr1Uz5MZf87Sst4WmsXXw3Hw09Omiqi7VdNIuJGmj8PkTQk +fVXjjJU30xrwCSss0smNtA0Aq2cpKNgB9RkEth2+dv5yXMSFytKAQd8FqKPVhJBPC/PgP5sZ0jeJ +P/J7UhyM9uH3PAeXjA6iWYEMspA90+NZRu0PqafegGtaqge2Gcu8V/OXIXoMsSt0Puvap2ctTMSY +njYJdmZm/Bo/6khUHL4wvYBQv3y1zgD2DGHZ5yQD4OMBgQ692IU0iL2yNqh7XAjlRICMb/gv1SHK +HRzQ+8S1h9E6Tsd2tTVItQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSM+xx1 +vALTn04uSNn5YFSqxLNP+jAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQENBQADggIBAEii1QAL +LtA/vBzVtVRJHlpr9OTy4EA34MwUe7nJ+jW1dReTagVphZzNTxl4WxmB82M+w85bj/UvXgF2Ez8s +ALnNllI5SW0ETsXpD4YN4fqzX4IS8TrOZgYkNCvozMrnadyHncI013nR03e4qllY/p0m+jiGPp2K +h2RX5Rc64vmNueMzeMGQ2Ljdt4NR5MTMI9UGfOZR0800McD2RrsLrfw9EAUqO0qRJe6M1ISHgCq8 +CYyqOhNf6DR5UMEQGfnTKB7U0VEwKbOukGfWHwpjscWpxkIxYxeU72nLL/qMFH3EQxiJ2fAyQOaA +4kZf5ePBAFmo+eggvIksDkc0C+pXwlM2/KfUrzHN/gLldfq5Jwn58/U7yn2fqSLLiMmq0Uc9Nneo +WWRrJ8/vJ8HjJLWG965+Mk2weWjROeiQWMODvA8s1pfrzgzhIMfatz7DP78v3DSk+yshzWePS/Tj +6tQ/50+6uaWTRRxmHyH6ZF5v4HaUMst19W7l9o/HuKTMqJZ9ZPskWkoDbGs4xugDQ5r3V7mzKWmT +OPQD8rv7gmsHINFSH5pkAnuYZttcTVoP0ISVoDwUQwbKytu4QTbaakRnh6+v40URFWkIsr4WOZck +bxJF0WddCajJFdr60qZfE2Efv4WstK2tBZQIgx51F9NxO5NQI1mg7TyRVJ12AMXDuDjb +-----END CERTIFICATE----- + +TunTrust Root CA +================ +-----BEGIN CERTIFICATE----- +MIIFszCCA5ugAwIBAgIUEwLV4kBMkkaGFmddtLu7sms+/BMwDQYJKoZIhvcNAQELBQAwYTELMAkG +A1UEBhMCVE4xNzA1BgNVBAoMLkFnZW5jZSBOYXRpb25hbGUgZGUgQ2VydGlmaWNhdGlvbiBFbGVj +dHJvbmlxdWUxGTAXBgNVBAMMEFR1blRydXN0IFJvb3QgQ0EwHhcNMTkwNDI2MDg1NzU2WhcNNDQw +NDI2MDg1NzU2WjBhMQswCQYDVQQGEwJUTjE3MDUGA1UECgwuQWdlbmNlIE5hdGlvbmFsZSBkZSBD +ZXJ0aWZpY2F0aW9uIEVsZWN0cm9uaXF1ZTEZMBcGA1UEAwwQVHVuVHJ1c3QgUm9vdCBDQTCCAiIw +DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMPN0/y9BFPdDCA61YguBUtB9YOCfvdZn56eY+hz +2vYGqU8ftPkLHzmMmiDQfgbU7DTZhrx1W4eI8NLZ1KMKsmwb60ksPqxd2JQDoOw05TDENX37Jk0b +bjBU2PWARZw5rZzJJQRNmpA+TkBuimvNKWfGzC3gdOgFVwpIUPp6Q9p+7FuaDmJ2/uqdHYVy7BG7 +NegfJ7/Boce7SBbdVtfMTqDhuazb1YMZGoXRlJfXyqNlC/M4+QKu3fZnz8k/9YosRxqZbwUN/dAd +gjH8KcwAWJeRTIAAHDOFli/LQcKLEITDCSSJH7UP2dl3RxiSlGBcx5kDPP73lad9UKGAwqmDrViW +VSHbhlnUr8a83YFuB9tgYv7sEG7aaAH0gxupPqJbI9dkxt/con3YS7qC0lH4Zr8GRuR5KiY2eY8f +Tpkdso8MDhz/yV3A/ZAQprE38806JG60hZC/gLkMjNWb1sjxVj8agIl6qeIbMlEsPvLfe/ZdeikZ +juXIvTZxi11Mwh0/rViizz1wTaZQmCXcI/m4WEEIcb9PuISgjwBUFfyRbVinljvrS5YnzWuioYas +DXxU5mZMZl+QviGaAkYt5IPCgLnPSz7ofzwB7I9ezX/SKEIBlYrilz0QIX32nRzFNKHsLA4KUiwS +VXAkPcvCFDVDXSdOvsC9qnyW5/yeYa1E0wCXAgMBAAGjYzBhMB0GA1UdDgQWBBQGmpsfU33x9aTI +04Y+oXNZtPdEITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFAaamx9TffH1pMjThj6hc1m0 +90QhMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAqgVutt0Vyb+zxiD2BkewhpMl +0425yAA/l/VSJ4hxyXT968pk21vvHl26v9Hr7lxpuhbI87mP0zYuQEkHDVneixCwSQXi/5E/S7fd +Ao74gShczNxtr18UnH1YeA32gAm56Q6XKRm4t+v4FstVEuTGfbvE7Pi1HE4+Z7/FXxttbUcoqgRY +YdZ2vyJ/0Adqp2RT8JeNnYA/u8EH22Wv5psymsNUk8QcCMNE+3tjEUPRahphanltkE8pjkcFwRJp +adbGNjHh/PqAulxPxOu3Mqz4dWEX1xAZufHSCe96Qp1bWgvUxpVOKs7/B9dPfhgGiPEZtdmYu65x +xBzndFlY7wyJz4sfdZMaBBSSSFCp61cpABbjNhzI+L/wM9VBD8TMPN3pM0MBkRArHtG5Xc0yGYuP +jCB31yLEQtyEFpslbei0VXF/sHyz03FJuc9SpAQ/3D2gu68zngowYI7bnV2UqL1g52KAdoGDDIzM +MEZJ4gzSqK/rYXHv5yJiqfdcZGyfFoxnNidF9Ql7v/YQCvGwjVRDjAS6oz/v4jXH+XTgbzRB0L9z +ZVcg+ZtnemZoJE6AZb0QmQZZ8mWvuMZHu/2QeItBcy6vVR/cO5JyboTT0GFMDcx2V+IthSIVNg3r +AZ3r2OvEhJn7wAzMMujjd9qDRIueVSjAi1jTkD5OGwDxFa2DK5o= +-----END CERTIFICATE----- + +HARICA TLS RSA Root CA 2021 +=========================== +-----BEGIN CERTIFICATE----- +MIIFpDCCA4ygAwIBAgIQOcqTHO9D88aOk8f0ZIk4fjANBgkqhkiG9w0BAQsFADBsMQswCQYDVQQG +EwJHUjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9u +cyBDQTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBSU0EgUm9vdCBDQSAyMDIxMB4XDTIxMDIxOTEwNTUz +OFoXDTQ1MDIxMzEwNTUzN1owbDELMAkGA1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRl +bWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgUlNB +IFJvb3QgQ0EgMjAyMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAIvC569lmwVnlskN +JLnQDmT8zuIkGCyEf3dRywQRNrhe7Wlxp57kJQmXZ8FHws+RFjZiPTgE4VGC/6zStGndLuwRo0Xu +a2s7TL+MjaQenRG56Tj5eg4MmOIjHdFOY9TnuEFE+2uva9of08WRiFukiZLRgeaMOVig1mlDqa2Y +Ulhu2wr7a89o+uOkXjpFc5gH6l8Cct4MpbOfrqkdtx2z/IpZ525yZa31MJQjB/OCFks1mJxTuy/K +5FrZx40d/JiZ+yykgmvwKh+OC19xXFyuQnspiYHLA6OZyoieC0AJQTPb5lh6/a6ZcMBaD9YThnEv +dmn8kN3bLW7R8pv1GmuebxWMevBLKKAiOIAkbDakO/IwkfN4E8/BPzWr8R0RI7VDIp4BkrcYAuUR +0YLbFQDMYTfBKnya4dC6s1BG7oKsnTH4+yPiAwBIcKMJJnkVU2DzOFytOOqBAGMUuTNe3QvboEUH +GjMJ+E20pwKmafTCWQWIZYVWrkvL4N48fS0ayOn7H6NhStYqE613TBoYm5EPWNgGVMWX+Ko/IIqm +haZ39qb8HOLubpQzKoNQhArlT4b4UEV4AIHrW2jjJo3Me1xR9BQsQL4aYB16cmEdH2MtiKrOokWQ +CPxrvrNQKlr9qEgYRtaQQJKQCoReaDH46+0N0x3GfZkYVVYnZS6NRcUk7M7jAgMBAAGjQjBAMA8G +A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFApII6ZgpJIKM+qTW8VX6iVNvRLuMA4GA1UdDwEB/wQE +AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAPpBIqm5iFSVmewzVjIuJndftTgfvnNAUX15QvWiWkKQU +EapobQk1OUAJ2vQJLDSle1mESSmXdMgHHkdt8s4cUCbjnj1AUz/3f5Z2EMVGpdAgS1D0NTsY9FVq +QRtHBmg8uwkIYtlfVUKqrFOFrJVWNlar5AWMxajaH6NpvVMPxP/cyuN+8kyIhkdGGvMA9YCRotxD +QpSbIPDRzbLrLFPCU3hKTwSUQZqPJzLB5UkZv/HywouoCjkxKLR9YjYsTewfM7Z+d21+UPCfDtcR +j88YxeMn/ibvBZ3PzzfF0HvaO7AWhAw6k9a+F9sPPg4ZeAnHqQJyIkv3N3a6dcSFA1pj1bF1BcK5 +vZStjBWZp5N99sXzqnTPBIWUmAD04vnKJGW/4GKvyMX6ssmeVkjaef2WdhW+o45WxLM0/L5H9MG0 +qPzVMIho7suuyWPEdr6sOBjhXlzPrjoiUevRi7PzKzMHVIf6tLITe7pTBGIBnfHAT+7hOtSLIBD6 +Alfm78ELt5BGnBkpjNxvoEppaZS3JGWg/6w/zgH7IS79aPib8qXPMThcFarmlwDB31qlpzmq6YR/ +PFGoOtmUW4y/Twhx5duoXNTSpv4Ao8YWxw/ogM4cKGR0GQjTQuPOAF1/sdwTsOEFy9EgqoZ0njnn +kf3/W9b3raYvAwtt41dU63ZTGI0RmLo= +-----END CERTIFICATE----- + +HARICA TLS ECC Root CA 2021 +=========================== +-----BEGIN CERTIFICATE----- +MIICVDCCAdugAwIBAgIQZ3SdjXfYO2rbIvT/WeK/zjAKBggqhkjOPQQDAzBsMQswCQYDVQQGEwJH +UjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBD +QTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBFQ0MgUm9vdCBDQSAyMDIxMB4XDTIxMDIxOTExMDExMFoX +DTQ1MDIxMzExMDEwOVowbDELMAkGA1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRlbWlj +IGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgRUNDIFJv +b3QgQ0EgMjAyMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABDgI/rGgltJ6rK9JOtDA4MM7KKrxcm1l +AEeIhPyaJmuqS7psBAqIXhfyVYf8MLA04jRYVxqEU+kw2anylnTDUR9YSTHMmE5gEYd103KUkE+b +ECUqqHgtvpBBWJAVcqeht6NCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUyRtTgRL+BNUW +0aq8mm+3oJUZbsowDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2cAMGQCMBHervjcToiwqfAi +rcJRQO9gcS3ujwLEXQNwSaSS6sUUiHCm0w2wqsosQJz76YJumgIwK0eaB8bRwoF8yguWGEEbo/Qw +CZ61IygNnxS2PFOiTAZpffpskcYqSUXm7LcT4Tps +-----END CERTIFICATE----- + +Autoridad de Certificacion Firmaprofesional CIF A62634068 +========================================================= +-----BEGIN CERTIFICATE----- +MIIGFDCCA/ygAwIBAgIIG3Dp0v+ubHEwDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCRVMxQjBA +BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2 +MjYzNDA2ODAeFw0xNDA5MjMxNTIyMDdaFw0zNjA1MDUxNTIyMDdaMFExCzAJBgNVBAYTAkVTMUIw +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+JIwuwIDAQABo4HvMIHsMB0GA1Ud +DgQWBBRlzeurNR4APn7VdMActHNHDhpkLzASBgNVHRMBAf8ECDAGAQH/AgEBMIGmBgNVHSAEgZ4w +gZswgZgGBFUdIAAwgY8wLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuZmlybWFwcm9mZXNpb25hbC5j +b20vY3BzMFwGCCsGAQUFBwICMFAeTgBQAGEAcwBlAG8AIABkAGUAIABsAGEAIABCAG8AbgBhAG4A +bwB2AGEAIAA0ADcAIABCAGEAcgBjAGUAbABvAG4AYQAgADAAOAAwADEANzAOBgNVHQ8BAf8EBAMC +AQYwDQYJKoZIhvcNAQELBQADggIBAHSHKAIrdx9miWTtj3QuRhy7qPj4Cx2Dtjqn6EWKB7fgPiDL +4QjbEwj4KKE1soCzC1HA01aajTNFSa9J8OA9B3pFE1r/yJfY0xgsfZb43aJlQ3CTkBW6kN/oGbDb +LIpgD7dvlAceHabJhfa9NPhAeGIQcDq+fUs5gakQ1JZBu/hfHAsdCPKxsIl68veg4MSPi3i1O1il +I45PVf42O+AMt8oqMEEgtIDNrvx2ZnOorm7hfNoD6JQg5iKj0B+QXSBTFCZX2lSX3xZEEAEeiGaP +cjiT3SC3NL7X8e5jjkd5KAb881lFJWAiMxujX6i6KtoaPc1A6ozuBRWV1aUsIC+nmCjuRfzxuIgA +LI9C2lHVnOUTaHFFQ4ueCyE8S1wF3BqfmI7avSKecs2tCsvMo2ebKHTEm9caPARYpoKdrcd7b/+A +lun4jWq9GJAd/0kakFI3ky88Al2CdgtR5xbHV/g4+afNmyJU72OwFW1TZQNKXkqgsqeOSQBZONXH +9IBk9W6VULgRfhVwOEqwf9DEMnDAGf/JOC0ULGb0QkTmVXYbgBVX/8Cnp6o5qtjTcNAuuuuUavpf +NIbnYrX9ivAwhZTJryQCL2/W3Wf+47BVTwSYT6RBVuKT0Gro1vP7ZeDOdcQxWQzugsgMYDNKGbqE +ZycPvEJdvSRUDewdcAZfpLz6IHxV +-----END CERTIFICATE----- + +vTrus ECC Root CA +================= +-----BEGIN CERTIFICATE----- +MIICDzCCAZWgAwIBAgIUbmq8WapTvpg5Z6LSa6Q75m0c1towCgYIKoZIzj0EAwMwRzELMAkGA1UE +BhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xGjAYBgNVBAMTEXZUcnVzIEVDQyBS +b290IENBMB4XDTE4MDczMTA3MjY0NFoXDTQzMDczMTA3MjY0NFowRzELMAkGA1UEBhMCQ04xHDAa +BgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xGjAYBgNVBAMTEXZUcnVzIEVDQyBSb290IENBMHYw +EAYHKoZIzj0CAQYFK4EEACIDYgAEZVBKrox5lkqqHAjDo6LN/llWQXf9JpRCux3NCNtzslt188+c +ToL0v/hhJoVs1oVbcnDS/dtitN9Ti72xRFhiQgnH+n9bEOf+QP3A2MMrMudwpremIFUde4BdS49n +TPEQo0IwQDAdBgNVHQ4EFgQUmDnNvtiyjPeyq+GtJK97fKHbH88wDwYDVR0TAQH/BAUwAwEB/zAO +BgNVHQ8BAf8EBAMCAQYwCgYIKoZIzj0EAwMDaAAwZQIwV53dVvHH4+m4SVBrm2nDb+zDfSXkV5UT +QJtS0zvzQBm8JsctBp61ezaf9SXUY2sAAjEA6dPGnlaaKsyh2j/IZivTWJwghfqrkYpwcBE4YGQL +YgmRWAD5Tfs0aNoJrSEGGJTO +-----END CERTIFICATE----- + +vTrus Root CA +============= +-----BEGIN CERTIFICATE----- +MIIFVjCCAz6gAwIBAgIUQ+NxE9izWRRdt86M/TX9b7wFjUUwDQYJKoZIhvcNAQELBQAwQzELMAkG +A1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xFjAUBgNVBAMTDXZUcnVzIFJv +b3QgQ0EwHhcNMTgwNzMxMDcyNDA1WhcNNDMwNzMxMDcyNDA1WjBDMQswCQYDVQQGEwJDTjEcMBoG +A1UEChMTaVRydXNDaGluYSBDby4sTHRkLjEWMBQGA1UEAxMNdlRydXMgUm9vdCBDQTCCAiIwDQYJ +KoZIhvcNAQEBBQADggIPADCCAgoCggIBAL1VfGHTuB0EYgWgrmy3cLRB6ksDXhA/kFocizuwZots +SKYcIrrVQJLuM7IjWcmOvFjai57QGfIvWcaMY1q6n6MLsLOaXLoRuBLpDLvPbmyAhykUAyyNJJrI +ZIO1aqwTLDPxn9wsYTwaP3BVm60AUn/PBLn+NvqcwBauYv6WTEN+VRS+GrPSbcKvdmaVayqwlHeF +XgQPYh1jdfdr58tbmnDsPmcF8P4HCIDPKNsFxhQnL4Z98Cfe/+Z+M0jnCx5Y0ScrUw5XSmXX+6KA +YPxMvDVTAWqXcoKv8R1w6Jz1717CbMdHflqUhSZNO7rrTOiwCcJlwp2dCZtOtZcFrPUGoPc2BX70 +kLJrxLT5ZOrpGgrIDajtJ8nU57O5q4IikCc9Kuh8kO+8T/3iCiSn3mUkpF3qwHYw03dQ+A0Em5Q2 +AXPKBlim0zvc+gRGE1WKyURHuFE5Gi7oNOJ5y1lKCn+8pu8fA2dqWSslYpPZUxlmPCdiKYZNpGvu +/9ROutW04o5IWgAZCfEF2c6Rsffr6TlP9m8EQ5pV9T4FFL2/s1m02I4zhKOQUqqzApVg+QxMaPnu +1RcN+HFXtSXkKe5lXa/R7jwXC1pDxaWG6iSe4gUH3DRCEpHWOXSuTEGC2/KmSNGzm/MzqvOmwMVO +9fSddmPmAsYiS8GVP1BkLFTltvA8Kc9XAgMBAAGjQjBAMB0GA1UdDgQWBBRUYnBj8XWEQ1iO0RYg +scasGrz2iTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOC +AgEAKbqSSaet8PFww+SX8J+pJdVrnjT+5hpk9jprUrIQeBqfTNqK2uwcN1LgQkv7bHbKJAs5EhWd +nxEt/Hlk3ODg9d3gV8mlsnZwUKT+twpw1aA08XXXTUm6EdGz2OyC/+sOxL9kLX1jbhd47F18iMjr +jld22VkE+rxSH0Ws8HqA7Oxvdq6R2xCOBNyS36D25q5J08FsEhvMKar5CKXiNxTKsbhm7xqC5PD4 +8acWabfbqWE8n/Uxy+QARsIvdLGx14HuqCaVvIivTDUHKgLKeBRtRytAVunLKmChZwOgzoy8sHJn +xDHO2zTlJQNgJXtxmOTAGytfdELSS8VZCAeHvsXDf+eW2eHcKJfWjwXj9ZtOyh1QRwVTsMo554Wg +icEFOwE30z9J4nfrI8iIZjs9OXYhRvHsXyO466JmdXTBQPfYaJqT4i2pLr0cox7IdMakLXogqzu4 +sEb9b91fUlV1YvCXoHzXOP0l382gmxDPi7g4Xl7FtKYCNqEeXxzP4padKar9mK5S4fNBUvupLnKW +nyfjqnN9+BojZns7q2WwMgFLFT49ok8MKzWixtlnEjUwzXYuFrOZnk1PTi07NEPhmg4NpGaXutIc +SkwsKouLgU9xGqndXHt7CMUADTdA43x7VF8vhV929vensBxXVsFy6K2ir40zSbofitzmdHxghm+H +l3s= +-----END CERTIFICATE----- + +ISRG Root X2 +============ +-----BEGIN CERTIFICATE----- +MIICGzCCAaGgAwIBAgIQQdKd0XLq7qeAwSxs6S+HUjAKBggqhkjOPQQDAzBPMQswCQYDVQQGEwJV +UzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElT +UkcgUm9vdCBYMjAeFw0yMDA5MDQwMDAwMDBaFw00MDA5MTcxNjAwMDBaME8xCzAJBgNVBAYTAlVT +MSkwJwYDVQQKEyBJbnRlcm5ldCBTZWN1cml0eSBSZXNlYXJjaCBHcm91cDEVMBMGA1UEAxMMSVNS +RyBSb290IFgyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEzZvVn4CDCuwJSvMWSj5cz3es3mcFDR0H +ttwW+1qLFNvicWDEukWVEYmO6gbf9yoWHKS5xcUy4APgHoIYOIvXRdgKam7mAHf7AlF9ItgKbppb +d9/w+kHsOdx1ymgHDB/qo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQUfEKWrt5LSDv6kviejM9ti6lyN5UwCgYIKoZIzj0EAwMDaAAwZQIwe3lORlCEwkSHRhtF +cP9Ymd70/aTSVaYgLXTWNLxBo1BfASdWtL4ndQavEi51mI38AjEAi/V3bNTIZargCyzuFJ0nN6T5 +U6VR5CmD1/iQMVtCnwr1/q4AaOeMSQ+2b1tbFfLn +-----END CERTIFICATE----- + +HiPKI Root CA - G1 +================== +-----BEGIN CERTIFICATE----- +MIIFajCCA1KgAwIBAgIQLd2szmKXlKFD6LDNdmpeYDANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQG +EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xGzAZBgNVBAMMEkhpUEtJ +IFJvb3QgQ0EgLSBHMTAeFw0xOTAyMjIwOTQ2MDRaFw0zNzEyMzExNTU5NTlaME8xCzAJBgNVBAYT +AlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEbMBkGA1UEAwwSSGlQS0kg +Um9vdCBDQSAtIEcxMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA9B5/UnMyDHPkvRN0 +o9QwqNCuS9i233VHZvR85zkEHmpwINJaR3JnVfSl6J3VHiGh8Ge6zCFovkRTv4354twvVcg3Px+k +wJyz5HdcoEb+d/oaoDjq7Zpy3iu9lFc6uux55199QmQ5eiY29yTw1S+6lZgRZq2XNdZ1AYDgr/SE +YYwNHl98h5ZeQa/rh+r4XfEuiAU+TCK72h8q3VJGZDnzQs7ZngyzsHeXZJzA9KMuH5UHsBffMNsA +GJZMoYFL3QRtU6M9/Aes1MU3guvklQgZKILSQjqj2FPseYlgSGDIcpJQ3AOPgz+yQlda22rpEZfd +hSi8MEyr48KxRURHH+CKFgeW0iEPU8DtqX7UTuybCeyvQqww1r/REEXgphaypcXTT3OUM3ECoWqj +1jOXTyFjHluP2cFeRXF3D4FdXyGarYPM+l7WjSNfGz1BryB1ZlpK9p/7qxj3ccC2HTHsOyDry+K4 +9a6SsvfhhEvyovKTmiKe0xRvNlS9H15ZFblzqMF8b3ti6RZsR1pl8w4Rm0bZ/W3c1pzAtH2lsN0/ +Vm+h+fbkEkj9Bn8SV7apI09bA8PgcSojt/ewsTu8mL3WmKgMa/aOEmem8rJY5AIJEzypuxC00jBF +8ez3ABHfZfjcK0NVvxaXxA/VLGGEqnKG/uY6fsI/fe78LxQ+5oXdUG+3Se0CAwEAAaNCMEAwDwYD +VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU8ncX+l6o/vY9cdVouslGDDjYr7AwDgYDVR0PAQH/BAQD +AgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBQUfB13HAE4/+qddRxosuej6ip0691x1TPOhwEmSKsxBHi +7zNKpiMdDg1H2DfHb680f0+BazVP6XKlMeJ45/dOlBhbQH3PayFUhuaVevvGyuqcSE5XCV0vrPSl +tJczWNWseanMX/mF+lLFjfiRFOs6DRfQUsJ748JzjkZ4Bjgs6FzaZsT0pPBWGTMpWmWSBUdGSquE +wx4noR8RkpkndZMPvDY7l1ePJlsMu5wP1G4wB9TcXzZoZjmDlicmisjEOf6aIW/Vcobpf2Lll07Q +JNBAsNB1CI69aO4I1258EHBGG3zgiLKecoaZAeO/n0kZtCW+VmWuF2PlHt/o/0elv+EmBYTksMCv +5wiZqAxeJoBF1PhoL5aPruJKHJwWDBNvOIf2u8g0X5IDUXlwpt/L9ZlNec1OvFefQ05rLisY+Gpz +jLrFNe85akEez3GoorKGB1s6yeHvP2UEgEcyRHCVTjFnanRbEEV16rCf0OY1/k6fi8wrkkVbbiVg +hUbN0aqwdmaTd5a+g744tiROJgvM7XpWGuDpWsZkrUx6AEhEL7lAuxM+vhV4nYWBSipX3tUZQ9rb +yltHhoMLP7YNdnhzeSJesYAfz77RP1YQmCuVh6EfnWQUYDksswBVLuT1sw5XxJFBAJw/6KXf6vb/ +yPCtbVKoF6ubYfwSUTXkJf2vqmqGOQ== +-----END CERTIFICATE----- + +GlobalSign ECC Root CA - R4 +=========================== +-----BEGIN CERTIFICATE----- +MIIB3DCCAYOgAwIBAgINAgPlfvU/k/2lCSGypjAKBggqhkjOPQQDAjBQMSQwIgYDVQQLExtHbG9i +YWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds +b2JhbFNpZ24wHhcNMTIxMTEzMDAwMDAwWhcNMzgwMTE5MDMxNDA3WjBQMSQwIgYDVQQLExtHbG9i +YWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds +b2JhbFNpZ24wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAS4xnnTj2wlDp8uORkcA6SumuU5BwkW +ymOxuYb4ilfBV85C+nOh92VC/x7BALJucw7/xyHlGKSq2XE/qNS5zowdo0IwQDAOBgNVHQ8BAf8E +BAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVLB7rUW44kB/+wpu+74zyTyjhNUwCgYI +KoZIzj0EAwIDRwAwRAIgIk90crlgr/HmnKAWBVBfw147bmF0774BxL4YSFlhgjICICadVGNA3jdg +UM/I2O2dgq43mLyjj0xMqTQrbO/7lZsm +-----END CERTIFICATE----- + +GTS Root R1 +=========== +-----BEGIN CERTIFICATE----- +MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQGEwJV +UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg +UjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE +ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0G +CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaM +f/vo27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7wCl7raKb0 +xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjwTcLCeoiKu7rPWRnWr4+w +B7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0PfyblqAj+lug8aJRT7oM6iCsVlgmy4HqMLnXW +nOunVmSPlk9orj2XwoSPwLxAwAtcvfaHszVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk +9+aCEI3oncKKiPo4Zor8Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zq +kUspzBmkMiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92wO1A +K/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70paDPvOmbsB4om3xPX +V2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrNVjzRlwW5y0vtOUucxD/SVRNuJLDW +cfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0T +AQH/BAUwAwEB/zAdBgNVHQ4EFgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQAD +ggIBAJ+qQibbC5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe +QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuyh6f88/qBVRRi +ClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM47HLwEXWdyzRSjeZ2axfG34ar +J45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8JZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYci +NuaCp+0KueIHoI17eko8cdLiA6EfMgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5me +LMFrUKTX5hgUvYU/Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJF +fbdT6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ0E6yove+ +7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm2tIMPNuzjsmhDYAPexZ3 +FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bbbP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3 +gm3c +-----END CERTIFICATE----- + +GTS Root R2 +=========== +-----BEGIN CERTIFICATE----- +MIIFVzCCAz+gAwIBAgINAgPlrsWNBCUaqxElqjANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQGEwJV +UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg +UjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE +ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0G +CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3Lv +CvptnfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3KgGjSY6Dlo7JUl +e3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9BuXvAuMC6C/Pq8tBcKSOWIm8Wb +a96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOdre7kRXuJVfeKH2JShBKzwkCX44ofR5GmdFrS ++LFjKBC4swm4VndAoiaYecb+3yXuPuWgf9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7M +kogwTZq9TwtImoS1mKPV+3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJG +r61K8YzodDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqjx5RWIr9q +S34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsRnTKaG73VululycslaVNV +J1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0kzCqgc7dGtxRcw1PcOnlthYhGXmy5okL +dWTK1au8CcEYof/UVKGFPP0UJAOyh9OktwIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0T +AQH/BAUwAwEB/zAdBgNVHQ4EFgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQAD +ggIBAB/Kzt3HvqGf2SdMC9wXmBFqiN495nFWcrKeGk6c1SuYJF2ba3uwM4IJvd8lRuqYnrYb/oM8 +0mJhwQTtzuDFycgTE1XnqGOtjHsB/ncw4c5omwX4Eu55MaBBRTUoCnGkJE+M3DyCB19m3H0Q/gxh +swWV7uGugQ+o+MePTagjAiZrHYNSVc61LwDKgEDg4XSsYPWHgJ2uNmSRXbBoGOqKYcl3qJfEycel +/FVL8/B/uWU9J2jQzGv6U53hkRrJXRqWbTKH7QMgyALOWr7Z6v2yTcQvG99fevX4i8buMTolUVVn +jWQye+mew4K6Ki3pHrTgSAai/GevHyICc/sgCq+dVEuhzf9gR7A/Xe8bVr2XIZYtCtFenTgCR2y5 +9PYjJbigapordwj6xLEokCZYCDzifqrXPW+6MYgKBesntaFJ7qBFVHvmJ2WZICGoo7z7GJa7Um8M +7YNRTOlZ4iBgxcJlkoKM8xAfDoqXvneCbT+PHV28SSe9zE8P4c52hgQjxcCMElv924SgJPFI/2R8 +0L5cFtHvma3AH/vLrrw4IgYmZNralw4/KBVEqE8AyvCazM90arQ+POuV7LXTWtiBmelDGDfrs7vR +WGJB82bSj6p4lVQgw1oudCvV0b4YacCs1aTPObpRhANl6WLAYv7YTVWW4tAR+kg0Eeye7QUd5MjW +HYbL +-----END CERTIFICATE----- + +GTS Root R3 +=========== +-----BEGIN CERTIFICATE----- +MIICCTCCAY6gAwIBAgINAgPluILrIPglJ209ZjAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJVUzEi +MCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMw +HhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZ +R29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjO +PQIBBgUrgQQAIgNiAAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout +736GjOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2ADDL24CejQjBA +MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTB8Sa6oC2uhYHP0/Eq +Er24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEA9uEglRR7VKOQFhG/hMjqb2sXnh5GmCCbn9MN2azT +L818+FsuVbu/3ZL3pAzcMeGiAjEA/JdmZuVDFhOD3cffL74UOO0BzrEXGhF16b0DjyZ+hOXJYKaV +11RZt+cRLInUue4X +-----END CERTIFICATE----- + +GTS Root R4 +=========== +-----BEGIN CERTIFICATE----- +MIICCTCCAY6gAwIBAgINAgPlwGjvYxqccpBQUjAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJVUzEi +MCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQw +HhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZ +R29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjO +PQIBBgUrgQQAIgNiAATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzu +hXyiQHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvRHYqjQjBA +MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSATNbrdP9JNqPV2Py1 +PsVq8JQdjDAKBggqhkjOPQQDAwNpADBmAjEA6ED/g94D9J+uHXqnLrmvT/aDHQ4thQEd0dlq7A/C +r8deVl5c1RxYIigL9zC2L7F8AjEA8GE8p/SgguMh1YQdc4acLa/KNJvxn7kjNuK8YAOdgLOaVsjh +4rsUecrNIdSUtUlD +-----END CERTIFICATE----- + +Telia Root CA v2 +================ +-----BEGIN CERTIFICATE----- +MIIFdDCCA1ygAwIBAgIPAWdfJ9b+euPkrL4JWwWeMA0GCSqGSIb3DQEBCwUAMEQxCzAJBgNVBAYT +AkZJMRowGAYDVQQKDBFUZWxpYSBGaW5sYW5kIE95ajEZMBcGA1UEAwwQVGVsaWEgUm9vdCBDQSB2 +MjAeFw0xODExMjkxMTU1NTRaFw00MzExMjkxMTU1NTRaMEQxCzAJBgNVBAYTAkZJMRowGAYDVQQK +DBFUZWxpYSBGaW5sYW5kIE95ajEZMBcGA1UEAwwQVGVsaWEgUm9vdCBDQSB2MjCCAiIwDQYJKoZI +hvcNAQEBBQADggIPADCCAgoCggIBALLQPwe84nvQa5n44ndp586dpAO8gm2h/oFlH0wnrI4AuhZ7 +6zBqAMCzdGh+sq/H1WKzej9Qyow2RCRj0jbpDIX2Q3bVTKFgcmfiKDOlyzG4OiIjNLh9vVYiQJ3q +9HsDrWj8soFPmNB06o3lfc1jw6P23pLCWBnglrvFxKk9pXSW/q/5iaq9lRdU2HhE8Qx3FZLgmEKn +pNaqIJLNwaCzlrI6hEKNfdWV5Nbb6WLEWLN5xYzTNTODn3WhUidhOPFZPY5Q4L15POdslv5e2QJl +tI5c0BE0312/UqeBAMN/mUWZFdUXyApT7GPzmX3MaRKGwhfwAZ6/hLzRUssbkmbOpFPlob/E2wnW +5olWK8jjfN7j/4nlNW4o6GwLI1GpJQXrSPjdscr6bAhR77cYbETKJuFzxokGgeWKrLDiKca5JLNr +RBH0pUPCTEPlcDaMtjNXepUugqD0XBCzYYP2AgWGLnwtbNwDRm41k9V6lS/eINhbfpSQBGq6WT0E +BXWdN6IOLj3rwaRSg/7Qa9RmjtzG6RJOHSpXqhC8fF6CfaamyfItufUXJ63RDolUK5X6wK0dmBR4 +M0KGCqlztft0DbcbMBnEWg4cJ7faGND/isgFuvGqHKI3t+ZIpEYslOqodmJHixBTB0hXbOKSTbau +BcvcwUpej6w9GU7C7WB1K9vBykLVAgMBAAGjYzBhMB8GA1UdIwQYMBaAFHKs5DN5qkWH9v2sHZ7W +xy+G2CQ5MB0GA1UdDgQWBBRyrOQzeapFh/b9rB2e1scvhtgkOTAOBgNVHQ8BAf8EBAMCAQYwDwYD +VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAoDtZpwmUPjaE0n4vOaWWl/oRrfxn83EJ +8rKJhGdEr7nv7ZbsnGTbMjBvZ5qsfl+yqwE2foH65IRe0qw24GtixX1LDoJt0nZi0f6X+J8wfBj5 +tFJ3gh1229MdqfDBmgC9bXXYfef6xzijnHDoRnkDry5023X4blMMA8iZGok1GTzTyVR8qPAs5m4H +eW9q4ebqkYJpCh3DflminmtGFZhb069GHWLIzoBSSRE/yQQSwxN8PzuKlts8oB4KtItUsiRnDe+C +y748fdHif64W1lZYudogsYMVoe+KTTJvQS8TUoKU1xrBeKJR3Stwbbca+few4GeXVtt8YVMJAygC +QMez2P2ccGrGKMOF6eLtGpOg3kuYooQ+BXcBlj37tCAPnHICehIv1aO6UXivKitEZU61/Qrowc15 +h2Er3oBXRb9n8ZuRXqWk7FlIEA04x7D6w0RtBPV4UBySllva9bguulvP5fBqnUsvWHMtTy3EHD70 +sz+rFQ47GUGKpMFXEmZxTPpT41frYpUJnlTd0cI8Vzy9OK2YZLe4A5pTVmBds9hCG1xLEooc6+t9 +xnppxyd/pPiL8uSUZodL6ZQHCRJ5irLrdATczvREWeAWysUsWNc8e89ihmpQfTU2Zqf7N+cox9jQ +raVplI/owd8k+BsHMYeB2F326CjYSlKArBPuUBQemMc= +-----END CERTIFICATE----- + +D-TRUST BR Root CA 1 2020 +========================= +-----BEGIN CERTIFICATE----- +MIIC2zCCAmCgAwIBAgIQfMmPK4TX3+oPyWWa00tNljAKBggqhkjOPQQDAzBIMQswCQYDVQQGEwJE +RTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRSVVNUIEJSIFJvb3QgQ0EgMSAy +MDIwMB4XDTIwMDIxMTA5NDUwMFoXDTM1MDIxMTA5NDQ1OVowSDELMAkGA1UEBhMCREUxFTATBgNV +BAoTDEQtVHJ1c3QgR21iSDEiMCAGA1UEAxMZRC1UUlVTVCBCUiBSb290IENBIDEgMjAyMDB2MBAG +ByqGSM49AgEGBSuBBAAiA2IABMbLxyjR+4T1mu9CFCDhQ2tuda38KwOE1HaTJddZO0Flax7mNCq7 +dPYSzuht56vkPE4/RAiLzRZxy7+SmfSk1zxQVFKQhYN4lGdnoxwJGT11NIXe7WB9xwy0QVK5buXu +QqOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFHOREKv/VbNafAkl1bK6CKBrqx9t +MA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6gPKA6hjhodHRwOi8vY3JsLmQtdHJ1c3Qu +bmV0L2NybC9kLXRydXN0X2JyX3Jvb3RfY2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVj +dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwQlIlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxP +PUQtVHJ1c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjOPQQD +AwNpADBmAjEAlJAtE/rhY/hhY+ithXhUkZy4kzg+GkHaQBZTQgjKL47xPoFWwKrY7RjEsK70Pvom +AjEA8yjixtsrmfu3Ubgko6SUeho/5jbiA1czijDLgsfWFBHVdWNbFJWcHwHP2NVypw87 +-----END CERTIFICATE----- + +D-TRUST EV Root CA 1 2020 +========================= +-----BEGIN CERTIFICATE----- +MIIC2zCCAmCgAwIBAgIQXwJB13qHfEwDo6yWjfv/0DAKBggqhkjOPQQDAzBIMQswCQYDVQQGEwJE +RTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRSVVNUIEVWIFJvb3QgQ0EgMSAy +MDIwMB4XDTIwMDIxMTEwMDAwMFoXDTM1MDIxMTA5NTk1OVowSDELMAkGA1UEBhMCREUxFTATBgNV +BAoTDEQtVHJ1c3QgR21iSDEiMCAGA1UEAxMZRC1UUlVTVCBFViBSb290IENBIDEgMjAyMDB2MBAG +ByqGSM49AgEGBSuBBAAiA2IABPEL3YZDIBnfl4XoIkqbz52Yv7QFJsnL46bSj8WeeHsxiamJrSc8 +ZRCC/N/DnU7wMyPE0jL1HLDfMxddxfCxivnvubcUyilKwg+pf3VlSSowZ/Rk99Yad9rDwpdhQntJ +raOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFH8QARY3OqQo5FD4pPfsazK2/umL +MA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6gPKA6hjhodHRwOi8vY3JsLmQtdHJ1c3Qu +bmV0L2NybC9kLXRydXN0X2V2X3Jvb3RfY2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVj +dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwRVYlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxP +PUQtVHJ1c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjOPQQD +AwNpADBmAjEAyjzGKnXCXnViOTYAYFqLwZOZzNnbQTs7h5kXO9XMT8oi96CAy/m0sRtW9XLS/BnR +AjEAkfcwkz8QRitxpNA7RJvAKQIFskF3UfN5Wp6OFKBOQtJbgfM0agPnIjhQW+0ZT0MW +-----END CERTIFICATE----- + +DigiCert TLS ECC P384 Root G5 +============================= +-----BEGIN CERTIFICATE----- +MIICGTCCAZ+gAwIBAgIQCeCTZaz32ci5PhwLBCou8zAKBggqhkjOPQQDAzBOMQswCQYDVQQGEwJV +UzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJjAkBgNVBAMTHURpZ2lDZXJ0IFRMUyBFQ0MgUDM4 +NCBSb290IEc1MB4XDTIxMDExNTAwMDAwMFoXDTQ2MDExNDIzNTk1OVowTjELMAkGA1UEBhMCVVMx +FzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMSYwJAYDVQQDEx1EaWdpQ2VydCBUTFMgRUNDIFAzODQg +Um9vdCBHNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABMFEoc8Rl1Ca3iOCNQfN0MsYndLxf3c1Tzvd +lHJS7cI7+Oz6e2tYIOyZrsn8aLN1udsJ7MgT9U7GCh1mMEy7H0cKPGEQQil8pQgO4CLp0zVozptj +n4S1mU1YoI71VOeVyaNCMEAwHQYDVR0OBBYEFMFRRVBZqz7nLFr6ICISB4CIfBFqMA4GA1UdDwEB +/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMDA2gAMGUCMQCJao1H5+z8blUD2Wds +Jk6Dxv3J+ysTvLd6jLRl0mlpYxNjOyZQLgGheQaRnUi/wr4CMEfDFXuxoJGZSZOoPHzoRgaLLPIx +AJSdYsiJvRmEFOml+wG4DXZDjC5Ty3zfDBeWUA== +-----END CERTIFICATE----- + +DigiCert TLS RSA4096 Root G5 +============================ +-----BEGIN CERTIFICATE----- +MIIFZjCCA06gAwIBAgIQCPm0eKj6ftpqMzeJ3nzPijANBgkqhkiG9w0BAQwFADBNMQswCQYDVQQG +EwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0 +MDk2IFJvb3QgRzUwHhcNMjEwMTE1MDAwMDAwWhcNNDYwMTE0MjM1OTU5WjBNMQswCQYDVQQGEwJV +UzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0MDk2 +IFJvb3QgRzUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz0PTJeRGd/fxmgefM1eS8 +7IE+ajWOLrfn3q/5B03PMJ3qCQuZvWxX2hhKuHisOjmopkisLnLlvevxGs3npAOpPxG02C+JFvuU +AT27L/gTBaF4HI4o4EXgg/RZG5Wzrn4DReW+wkL+7vI8toUTmDKdFqgpwgscONyfMXdcvyej/Ces +tyu9dJsXLfKB2l2w4SMXPohKEiPQ6s+d3gMXsUJKoBZMpG2T6T867jp8nVid9E6P/DsjyG244gXa +zOvswzH016cpVIDPRFtMbzCe88zdH5RDnU1/cHAN1DrRN/BsnZvAFJNY781BOHW8EwOVfH/jXOnV +DdXifBBiqmvwPXbzP6PosMH976pXTayGpxi0KcEsDr9kvimM2AItzVwv8n/vFfQMFawKsPHTDU9q +TXeXAaDxZre3zu/O7Oyldcqs4+Fj97ihBMi8ez9dLRYiVu1ISf6nL3kwJZu6ay0/nTvEF+cdLvvy +z6b84xQslpghjLSR6Rlgg/IwKwZzUNWYOwbpx4oMYIwo+FKbbuH2TbsGJJvXKyY//SovcfXWJL5/ +MZ4PbeiPT02jP/816t9JXkGPhvnxd3lLG7SjXi/7RgLQZhNeXoVPzthwiHvOAbWWl9fNff2C+MIk +wcoBOU+NosEUQB+cZtUMCUbW8tDRSHZWOkPLtgoRObqME2wGtZ7P6wIDAQABo0IwQDAdBgNVHQ4E +FgQUUTMc7TZArxfTJc1paPKvTiM+s0EwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8w +DQYJKoZIhvcNAQEMBQADggIBAGCmr1tfV9qJ20tQqcQjNSH/0GEwhJG3PxDPJY7Jv0Y02cEhJhxw +GXIeo8mH/qlDZJY6yFMECrZBu8RHANmfGBg7sg7zNOok992vIGCukihfNudd5N7HPNtQOa27PShN +lnx2xlv0wdsUpasZYgcYQF+Xkdycx6u1UQ3maVNVzDl92sURVXLFO4uJ+DQtpBflF+aZfTCIITfN +MBc9uPK8qHWgQ9w+iUuQrm0D4ByjoJYJu32jtyoQREtGBzRj7TG5BO6jm5qu5jF49OokYTurWGT/ +u4cnYiWB39yhL/btp/96j1EuMPikAdKFOV8BmZZvWltwGUb+hmA+rYAQCd05JS9Yf7vSdPD3Rh9G +OUrYU9DzLjtxpdRv/PNn5AeP3SYZ4Y1b+qOTEZvpyDrDVWiakuFSdjjo4bq9+0/V77PnSIMx8IIh +47a+p6tv75/fTM8BuGJqIz3nCU2AG3swpMPdB380vqQmsvZB6Akd4yCYqjdP//fx4ilwMUc/dNAU +FvohigLVigmUdy7yWSiLfFCSCmZ4OIN1xLVaqBHG5cGdZlXPU8Sv13WFqUITVuwhd4GTWgzqltlJ +yqEI8pc7bZsEGCREjnwB8twl2F6GmrE52/WRMmrRpnCKovfepEWFJqgejF0pW8hL2JpqA15w8oVP +bEtoL8pU9ozaMv7Da4M/OMZ+ +-----END CERTIFICATE----- + +Certainly Root R1 +================= +-----BEGIN CERTIFICATE----- +MIIFRzCCAy+gAwIBAgIRAI4P+UuQcWhlM1T01EQ5t+AwDQYJKoZIhvcNAQELBQAwPTELMAkGA1UE +BhMCVVMxEjAQBgNVBAoTCUNlcnRhaW5seTEaMBgGA1UEAxMRQ2VydGFpbmx5IFJvb3QgUjEwHhcN +MjEwNDAxMDAwMDAwWhcNNDYwNDAxMDAwMDAwWjA9MQswCQYDVQQGEwJVUzESMBAGA1UEChMJQ2Vy +dGFpbmx5MRowGAYDVQQDExFDZXJ0YWlubHkgUm9vdCBSMTCCAiIwDQYJKoZIhvcNAQEBBQADggIP +ADCCAgoCggIBANA21B/q3avk0bbm+yLA3RMNansiExyXPGhjZjKcA7WNpIGD2ngwEc/csiu+kr+O +5MQTvqRoTNoCaBZ0vrLdBORrKt03H2As2/X3oXyVtwxwhi7xOu9S98zTm/mLvg7fMbedaFySpvXl +8wo0tf97ouSHocavFwDvA5HtqRxOcT3Si2yJ9HiG5mpJoM610rCrm/b01C7jcvk2xusVtyWMOvwl +DbMicyF0yEqWYZL1LwsYpfSt4u5BvQF5+paMjRcCMLT5r3gajLQ2EBAHBXDQ9DGQilHFhiZ5shGI +XsXwClTNSaa/ApzSRKft43jvRl5tcdF5cBxGX1HpyTfcX35pe0HfNEXgO4T0oYoKNp43zGJS4YkN +KPl6I7ENPT2a/Z2B7yyQwHtETrtJ4A5KVpK8y7XdeReJkd5hiXSSqOMyhb5OhaRLWcsrxXiOcVTQ +AjeZjOVJ6uBUcqQRBi8LjMFbvrWhsFNunLhgkR9Za/kt9JQKl7XsxXYDVBtlUrpMklZRNaBA2Cnb +rlJ2Oy0wQJuK0EJWtLeIAaSHO1OWzaMWj/Nmqhexx2DgwUMFDO6bW2BvBlyHWyf5QBGenDPBt+U1 +VwV/J84XIIwc/PH72jEpSe31C4SnT8H2TsIonPru4K8H+zMReiFPCyEQtkA6qyI6BJyLm4SGcprS +p6XEtHWRqSsjAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud +DgQWBBTgqj8ljZ9EXME66C6ud0yEPmcM9DANBgkqhkiG9w0BAQsFAAOCAgEAuVevuBLaV4OPaAsz +HQNTVfSVcOQrPbA56/qJYv331hgELyE03fFo8NWWWt7CgKPBjcZq91l3rhVkz1t5BXdm6ozTaw3d +8VkswTOlMIAVRQdFGjEitpIAq5lNOo93r6kiyi9jyhXWx8bwPWz8HA2YEGGeEaIi1wrykXprOQ4v +MMM2SZ/g6Q8CRFA3lFV96p/2O7qUpUzpvD5RtOjKkjZUbVwlKNrdrRT90+7iIgXr0PK3aBLXWopB +GsaSpVo7Y0VPv+E6dyIvXL9G+VoDhRNCX8reU9ditaY1BMJH/5n9hN9czulegChB8n3nHpDYT3Y+ +gjwN/KUD+nsa2UUeYNrEjvn8K8l7lcUq/6qJ34IxD3L/DCfXCh5WAFAeDJDBlrXYFIW7pw0WwfgH +JBu6haEaBQmAupVjyTrsJZ9/nbqkRxWbRHDxakvWOF5D8xh+UG7pWijmZeZ3Gzr9Hb4DJqPb1OG7 +fpYnKx3upPvaJVQTA945xsMfTZDsjxtK0hzthZU4UHlG1sGQUDGpXJpuHfUzVounmdLyyCwzk5Iw +x06MZTMQZBf9JBeW0Y3COmor6xOLRPIh80oat3df1+2IpHLlOR+Vnb5nwXARPbv0+Em34yaXOp/S +X3z7wJl8OSngex2/DaeP0ik0biQVy96QXr8axGbqwua6OV+KmalBWQewLK8= +-----END CERTIFICATE----- + +Certainly Root E1 +================= +-----BEGIN CERTIFICATE----- +MIIB9zCCAX2gAwIBAgIQBiUzsUcDMydc+Y2aub/M+DAKBggqhkjOPQQDAzA9MQswCQYDVQQGEwJV +UzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0YWlubHkgUm9vdCBFMTAeFw0yMTA0 +MDEwMDAwMDBaFw00NjA0MDEwMDAwMDBaMD0xCzAJBgNVBAYTAlVTMRIwEAYDVQQKEwlDZXJ0YWlu +bHkxGjAYBgNVBAMTEUNlcnRhaW5seSBSb290IEUxMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE3m/4 +fxzf7flHh4axpMCK+IKXgOqPyEpeKn2IaKcBYhSRJHpcnqMXfYqGITQYUBsQ3tA3SybHGWCA6TS9 +YBk2QNYphwk8kXr2vBMj3VlOBF7PyAIcGFPBMdjaIOlEjeR2o0IwQDAOBgNVHQ8BAf8EBAMCAQYw +DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU8ygYy2R17ikq6+2uI1g4hevIIgcwCgYIKoZIzj0E +AwMDaAAwZQIxALGOWiDDshliTd6wT99u0nCK8Z9+aozmut6Dacpps6kFtZaSF4fC0urQe87YQVt8 +rgIwRt7qy12a7DLCZRawTDBcMPPaTnOGBtjOiQRINzf43TNRnXCve1XYAS59BWQOhriR +-----END CERTIFICATE----- + +Security Communication ECC RootCA1 +================================== +-----BEGIN CERTIFICATE----- +MIICODCCAb6gAwIBAgIJANZdm7N4gS7rMAoGCCqGSM49BAMDMGExCzAJBgNVBAYTAkpQMSUwIwYD +VQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMSswKQYDVQQDEyJTZWN1cml0eSBDb21t +dW5pY2F0aW9uIEVDQyBSb290Q0ExMB4XDTE2MDYxNjA1MTUyOFoXDTM4MDExODA1MTUyOFowYTEL +MAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKzApBgNV +BAMTIlNlY3VyaXR5IENvbW11bmljYXRpb24gRUNDIFJvb3RDQTEwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAASkpW9gAwPDvTH00xecK4R1rOX9PVdu12O/5gSJko6BnOPpR27KkBLIE+CnnfdldB9sELLo +5OnvbYUymUSxXv3MdhDYW72ixvnWQuRXdtyQwjWpS4g8EkdtXP9JTxpKULGjQjBAMB0GA1UdDgQW +BBSGHOf+LaVKiwj+KBH6vqNm+GBZLzAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAK +BggqhkjOPQQDAwNoADBlAjAVXUI9/Lbu9zuxNuie9sRGKEkz0FhDKmMpzE2xtHqiuQ04pV1IKv3L +snNdo4gIxwwCMQDAqy0Obe0YottT6SXbVQjgUMzfRGEWgqtJsLKB7HOHeLRMsmIbEvoWTSVLY70e +N9k= +-----END CERTIFICATE----- + +BJCA Global Root CA1 +==================== +-----BEGIN CERTIFICATE----- +MIIFdDCCA1ygAwIBAgIQVW9l47TZkGobCdFsPsBsIDANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQG +EwJDTjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRIT1JJVFkxHTAbBgNVBAMMFEJK +Q0EgR2xvYmFsIFJvb3QgQ0ExMB4XDTE5MTIxOTAzMTYxN1oXDTQ0MTIxMjAzMTYxN1owVDELMAkG +A1UEBhMCQ04xJjAkBgNVBAoMHUJFSUpJTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQD +DBRCSkNBIEdsb2JhbCBSb290IENBMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAPFm +CL3ZxRVhy4QEQaVpN3cdwbB7+sN3SJATcmTRuHyQNZ0YeYjjlwE8R4HyDqKYDZ4/N+AZspDyRhyS +sTphzvq3Rp4Dhtczbu33RYx2N95ulpH3134rhxfVizXuhJFyV9xgw8O558dnJCNPYwpj9mZ9S1Wn +P3hkSWkSl+BMDdMJoDIwOvqfwPKcxRIqLhy1BDPapDgRat7GGPZHOiJBhyL8xIkoVNiMpTAK+BcW +yqw3/XmnkRd4OJmtWO2y3syJfQOcs4ll5+M7sSKGjwZteAf9kRJ/sGsciQ35uMt0WwfCyPQ10WRj +eulumijWML3mG90Vr4TqnMfK9Q7q8l0ph49pczm+LiRvRSGsxdRpJQaDrXpIhRMsDQa4bHlW/KNn +MoH1V6XKV0Jp6VwkYe/iMBhORJhVb3rCk9gZtt58R4oRTklH2yiUAguUSiz5EtBP6DF+bHq/pj+b +OT0CFqMYs2esWz8sgytnOYFcuX6U1WTdno9uruh8W7TXakdI136z1C2OVnZOz2nxbkRs1CTqjSSh +GL+9V/6pmTW12xB3uD1IutbB5/EjPtffhZ0nPNRAvQoMvfXnjSXWgXSHRtQpdaJCbPdzied9v3pK +H9MiyRVVz99vfFXQpIsHETdfg6YmV6YBW37+WGgHqel62bno/1Afq8K0wM7o6v0PvY1NuLxxAgMB +AAGjQjBAMB0GA1UdDgQWBBTF7+3M2I0hxkjk49cULqcWk+WYATAPBgNVHRMBAf8EBTADAQH/MA4G +A1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAUoKsITQfI/Ki2Pm4rzc2IInRNwPWaZ+4 +YRC6ojGYWUfo0Q0lHhVBDOAqVdVXUsv45Mdpox1NcQJeXyFFYEhcCY5JEMEE3KliawLwQ8hOnThJ +dMkycFRtwUf8jrQ2ntScvd0g1lPJGKm1Vrl2i5VnZu69mP6u775u+2D2/VnGKhs/I0qUJDAnyIm8 +60Qkmss9vk/Ves6OF8tiwdneHg56/0OGNFK8YT88X7vZdrRTvJez/opMEi4r89fO4aL/3Xtw+zuh +TaRjAv04l5U/BXCga99igUOLtFkNSoxUnMW7gZ/NfaXvCyUeOiDbHPwfmGcCCtRzRBPbUYQaVQNW +4AB+dAb/OMRyHdOoP2gxXdMJxy6MW2Pg6Nwe0uxhHvLe5e/2mXZgLR6UcnHGCyoyx5JO1UbXHfmp +GQrI+pXObSOYqgs4rZpWDW+N8TEAiMEXnM0ZNjX+VVOg4DwzX5Ze4jLp3zO7Bkqp2IRzznfSxqxx +4VyjHQy7Ct9f4qNx2No3WqB4K/TUfet27fJhcKVlmtOJNBir+3I+17Q9eVzYH6Eze9mCUAyTF6ps +3MKCuwJXNq+YJyo5UOGwifUll35HaBC07HPKs5fRJNz2YqAo07WjuGS3iGJCz51TzZm+ZGiPTx4S +SPfSKcOYKMryMguTjClPPGAyzQWWYezyr/6zcCwupvI= +-----END CERTIFICATE----- + +BJCA Global Root CA2 +==================== +-----BEGIN CERTIFICATE----- +MIICJTCCAaugAwIBAgIQLBcIfWQqwP6FGFkGz7RK6zAKBggqhkjOPQQDAzBUMQswCQYDVQQGEwJD +TjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRIT1JJVFkxHTAbBgNVBAMMFEJKQ0Eg +R2xvYmFsIFJvb3QgQ0EyMB4XDTE5MTIxOTAzMTgyMVoXDTQ0MTIxMjAzMTgyMVowVDELMAkGA1UE +BhMCQ04xJjAkBgNVBAoMHUJFSUpJTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQDDBRC +SkNBIEdsb2JhbCBSb290IENBMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABJ3LgJGNU2e1uVCxA/jl +SR9BIgmwUVJY1is0j8USRhTFiy8shP8sbqjV8QnjAyEUxEM9fMEsxEtqSs3ph+B99iK++kpRuDCK +/eHeGBIK9ke35xe/J4rUQUyWPGCWwf0VHKNCMEAwHQYDVR0OBBYEFNJKsVF/BvDRgh9Obl+rg/xI +1LCRMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMDA2gAMGUCMBq8 +W9f+qdJUDkpd0m2xQNz0Q9XSSpkZElaA94M04TVOSG0ED1cxMDAtsaqdAzjbBgIxAMvMh1PLet8g +UXOQwKhbYdDFUDn9hf7B43j4ptZLvZuHjw/l1lOWqzzIQNph91Oj9w== +-----END CERTIFICATE----- + +Sectigo Public Server Authentication Root E46 +============================================= +-----BEGIN CERTIFICATE----- +MIICOjCCAcGgAwIBAgIQQvLM2htpN0RfFf51KBC49DAKBggqhkjOPQQDAzBfMQswCQYDVQQGEwJH +QjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1YmxpYyBTZXJ2 +ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwHhcNMjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5 +WjBfMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0 +aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUr +gQQAIgNiAAR2+pmpbiDt+dd34wc7qNs9Xzjoq1WmVk/WSOrsfy2qw7LFeeyZYX8QeccCWvkEN/U0 +NSt3zn8gj1KjAIns1aeibVvjS5KToID1AZTc8GgHHs3u/iVStSBDHBv+6xnOQ6OjQjBAMB0GA1Ud +DgQWBBTRItpMWfFLXyY4qp3W7usNw/upYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB +/zAKBggqhkjOPQQDAwNnADBkAjAn7qRaqCG76UeXlImldCBteU/IvZNeWBj7LRoAasm4PdCkT0RH +lAFWovgzJQxC36oCMB3q4S6ILuH5px0CMk7yn2xVdOOurvulGu7t0vzCAxHrRVxgED1cf5kDW21U +SAGKcw== +-----END CERTIFICATE----- + +Sectigo Public Server Authentication Root R46 +============================================= +-----BEGIN CERTIFICATE----- +MIIFijCCA3KgAwIBAgIQdY39i658BwD6qSWn4cetFDANBgkqhkiG9w0BAQwFADBfMQswCQYDVQQG +EwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1YmxpYyBT +ZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYwHhcNMjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1 +OTU5WjBfMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1T +ZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYwggIiMA0GCSqGSIb3 +DQEBAQUAA4ICDwAwggIKAoICAQCTvtU2UnXYASOgHEdCSe5jtrch/cSV1UgrJnwUUxDaef0rty2k +1Cz66jLdScK5vQ9IPXtamFSvnl0xdE8H/FAh3aTPaE8bEmNtJZlMKpnzSDBh+oF8HqcIStw+Kxwf +GExxqjWMrfhu6DtK2eWUAtaJhBOqbchPM8xQljeSM9xfiOefVNlI8JhD1mb9nxc4Q8UBUQvX4yMP +FF1bFOdLvt30yNoDN9HWOaEhUTCDsG3XME6WW5HwcCSrv0WBZEMNvSE6Lzzpng3LILVCJ8zab5vu +ZDCQOc2TZYEhMbUjUDM3IuM47fgxMMxF/mL50V0yeUKH32rMVhlATc6qu/m1dkmU8Sf4kaWD5Qaz +Yw6A3OASVYCmO2a0OYctyPDQ0RTp5A1NDvZdV3LFOxxHVp3i1fuBYYzMTYCQNFu31xR13NgESJ/A +wSiItOkcyqex8Va3e0lMWeUgFaiEAin6OJRpmkkGj80feRQXEgyDet4fsZfu+Zd4KKTIRJLpfSYF +plhym3kT2BFfrsU4YjRosoYwjviQYZ4ybPUHNs2iTG7sijbt8uaZFURww3y8nDnAtOFr94MlI1fZ +EoDlSfB1D++N6xybVCi0ITz8fAr/73trdf+LHaAZBav6+CuBQug4urv7qv094PPK306Xlynt8xhW +6aWWrL3DkJiy4Pmi1KZHQ3xtzwIDAQABo0IwQDAdBgNVHQ4EFgQUVnNYZJX5khqwEioEYnmhQBWI +IUkwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAC9c +mTz8Bl6MlC5w6tIyMY208FHVvArzZJ8HXtXBc2hkeqK5Duj5XYUtqDdFqij0lgVQYKlJfp/imTYp +E0RHap1VIDzYm/EDMrraQKFz6oOht0SmDpkBm+S8f74TlH7Kph52gDY9hAaLMyZlbcp+nv4fjFg4 +exqDsQ+8FxG75gbMY/qB8oFM2gsQa6H61SilzwZAFv97fRheORKkU55+MkIQpiGRqRxOF3yEvJ+M +0ejf5lG5Nkc/kLnHvALcWxxPDkjBJYOcCj+esQMzEhonrPcibCTRAUH4WAP+JWgiH5paPHxsnnVI +84HxZmduTILA7rpXDhjvLpr3Etiga+kFpaHpaPi8TD8SHkXoUsCjvxInebnMMTzD9joiFgOgyY9m +pFuiTdaBJQbpdqQACj7LzTWb4OE4y2BThihCQRxEV+ioratF4yUQvNs+ZUH7G6aXD+u5dHn5Hrwd +Vw1Hr8Mvn4dGp+smWg9WY7ViYG4A++MnESLn/pmPNPW56MORcr3Ywx65LvKRRFHQV80MNNVIIb/b +E/FmJUNS0nAiNs2fxBx1IK1jcmMGDw4nztJqDby1ORrp0XZ60Vzk50lJLVU3aPAaOpg+VBeHVOmm +J1CJeyAvP/+/oYtKR5j/K3tJPsMpRmAYQqszKbrAKbkTidOIijlBO8n9pu0f9GBj39ItVQGL +-----END CERTIFICATE----- + +SSL.com TLS RSA Root CA 2022 +============================ +-----BEGIN CERTIFICATE----- +MIIFiTCCA3GgAwIBAgIQb77arXO9CEDii02+1PdbkTANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQG +EwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQDDBxTU0wuY29tIFRMUyBSU0Eg +Um9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzQyMloXDTQ2MDgxOTE2MzQyMVowTjELMAkGA1UEBhMC +VVMxGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgUlNBIFJv +b3QgQ0EgMjAyMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANCkCXJPQIgSYT41I57u +9nTPL3tYPc48DRAokC+X94xI2KDYJbFMsBFMF3NQ0CJKY7uB0ylu1bUJPiYYf7ISf5OYt6/wNr/y +7hienDtSxUcZXXTzZGbVXcdotL8bHAajvI9AI7YexoS9UcQbOcGV0insS657Lb85/bRi3pZ7Qcac +oOAGcvvwB5cJOYF0r/c0WRFXCsJbwST0MXMwgsadugL3PnxEX4MN8/HdIGkWCVDi1FW24IBydm5M +R7d1VVm0U3TZlMZBrViKMWYPHqIbKUBOL9975hYsLfy/7PO0+r4Y9ptJ1O4Fbtk085zx7AGL0SDG +D6C1vBdOSHtRwvzpXGk3R2azaPgVKPC506QVzFpPulJwoxJF3ca6TvvC0PeoUidtbnm1jPx7jMEW +TO6Af77wdr5BUxIzrlo4QqvXDz5BjXYHMtWrifZOZ9mxQnUjbvPNQrL8VfVThxc7wDNY8VLS+YCk +8OjwO4s4zKTGkH8PnP2L0aPP2oOnaclQNtVcBdIKQXTbYxE3waWglksejBYSd66UNHsef8JmAOSq +g+qKkK3ONkRN0VHpvB/zagX9wHQfJRlAUW7qglFA35u5CCoGAtUjHBPW6dvbxrB6y3snm/vg1UYk +7RBLY0ulBY+6uB0rpvqR4pJSvezrZ5dtmi2fgTIFZzL7SAg/2SW4BCUvAgMBAAGjYzBhMA8GA1Ud +EwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU+y437uOEeicuzRk1sTN8/9REQrkwHQYDVR0OBBYEFPsu +N+7jhHonLs0ZNbEzfP/UREK5MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAjYlt +hEUY8U+zoO9opMAdrDC8Z2awms22qyIZZtM7QbUQnRC6cm4pJCAcAZli05bg4vsMQtfhWsSWTVTN +j8pDU/0quOr4ZcoBwq1gaAafORpR2eCNJvkLTqVTJXojpBzOCBvfR4iyrT7gJ4eLSYwfqUdYe5by +iB0YrrPRpgqU+tvT5TgKa3kSM/tKWTcWQA673vWJDPFs0/dRa1419dvAJuoSc06pkZCmF8NsLzjU +o3KUQyxi4U5cMj29TH0ZR6LDSeeWP4+a0zvkEdiLA9z2tmBVGKaBUfPhqBVq6+AL8BQx1rmMRTqo +ENjwuSfr98t67wVylrXEj5ZzxOhWc5y8aVFjvO9nHEMaX3cZHxj4HCUp+UmZKbaSPaKDN7Egkaib +MOlqbLQjk2UEqxHzDh1TJElTHaE/nUiSEeJ9DU/1172iWD54nR4fK/4huxoTtrEoZP2wAgDHbICi +vRZQIA9ygV/MlP+7mea6kMvq+cYMwq7FGc4zoWtcu358NFcXrfA/rs3qr5nsLFR+jM4uElZI7xc7 +P0peYNLcdDa8pUNjyw9bowJWCZ4kLOGGgYz+qxcs+sjiMho6/4UIyYOf8kpIEFR3N+2ivEC+5BB0 +9+Rbu7nzifmPQdjH5FCQNYA+HLhNkNPU98OwoX6EyneSMSy4kLGCenROmxMmtNVQZlR4rmA= +-----END CERTIFICATE----- + +SSL.com TLS ECC Root CA 2022 +============================ +-----BEGIN CERTIFICATE----- +MIICOjCCAcCgAwIBAgIQFAP1q/s3ixdAW+JDsqXRxDAKBggqhkjOPQQDAzBOMQswCQYDVQQGEwJV +UzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQDDBxTU0wuY29tIFRMUyBFQ0MgUm9v +dCBDQSAyMDIyMB4XDTIyMDgyNTE2MzM0OFoXDTQ2MDgxOTE2MzM0N1owTjELMAkGA1UEBhMCVVMx +GDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgRUNDIFJvb3Qg +Q0EgMjAyMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABEUpNXP6wrgjzhR9qLFNoFs27iosU8NgCTWy +JGYmacCzldZdkkAZDsalE3D07xJRKF3nzL35PIXBz5SQySvOkkJYWWf9lCcQZIxPBLFNSeR7T5v1 +5wj4A4j3p8OSSxlUgaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBSJjy+j6CugFFR7 +81a4Jl9nOAuc0DAdBgNVHQ4EFgQUiY8vo+groBRUe/NWuCZfZzgLnNAwDgYDVR0PAQH/BAQDAgGG +MAoGCCqGSM49BAMDA2gAMGUCMFXjIlbp15IkWE8elDIPDAI2wv2sdDJO4fscgIijzPvX6yv/N33w +7deedWo1dlJF4AIxAMeNb0Igj762TVntd00pxCAgRWSGOlDGxK0tk/UYfXLtqc/ErFc2KAhl3zx5 +Zn6g6g== +-----END CERTIFICATE----- + +Atos TrustedRoot Root CA ECC TLS 2021 +===================================== +-----BEGIN CERTIFICATE----- +MIICFTCCAZugAwIBAgIQPZg7pmY9kGP3fiZXOATvADAKBggqhkjOPQQDAzBMMS4wLAYDVQQDDCVB +dG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgRUNDIFRMUyAyMDIxMQ0wCwYDVQQKDARBdG9zMQswCQYD +VQQGEwJERTAeFw0yMTA0MjIwOTI2MjNaFw00MTA0MTcwOTI2MjJaMEwxLjAsBgNVBAMMJUF0b3Mg +VHJ1c3RlZFJvb3QgUm9vdCBDQSBFQ0MgVExTIDIwMjExDTALBgNVBAoMBEF0b3MxCzAJBgNVBAYT +AkRFMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEloZYKDcKZ9Cg3iQZGeHkBQcfl+3oZIK59sRxUM6K +DP/XtXa7oWyTbIOiaG6l2b4siJVBzV3dscqDY4PMwL502eCdpO5KTlbgmClBk1IQ1SQ4AjJn8ZQS +b+/Xxd4u/RmAo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR2KCXWfeBmmnoJsmo7jjPX +NtNPojAOBgNVHQ8BAf8EBAMCAYYwCgYIKoZIzj0EAwMDaAAwZQIwW5kp85wxtolrbNa9d+F851F+ +uDrNozZffPc8dz7kUK2o59JZDCaOMDtuCCrCp1rIAjEAmeMM56PDr9NJLkaCI2ZdyQAUEv049OGY +a3cpetskz2VAv9LcjBHo9H1/IISpQuQo +-----END CERTIFICATE----- + +Atos TrustedRoot Root CA RSA TLS 2021 +===================================== +-----BEGIN CERTIFICATE----- +MIIFZDCCA0ygAwIBAgIQU9XP5hmTC/srBRLYwiqipDANBgkqhkiG9w0BAQwFADBMMS4wLAYDVQQD +DCVBdG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgUlNBIFRMUyAyMDIxMQ0wCwYDVQQKDARBdG9zMQsw +CQYDVQQGEwJERTAeFw0yMTA0MjIwOTIxMTBaFw00MTA0MTcwOTIxMDlaMEwxLjAsBgNVBAMMJUF0 +b3MgVHJ1c3RlZFJvb3QgUm9vdCBDQSBSU0EgVExTIDIwMjExDTALBgNVBAoMBEF0b3MxCzAJBgNV +BAYTAkRFMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtoAOxHm9BYx9sKOdTSJNy/BB +l01Z4NH+VoyX8te9j2y3I49f1cTYQcvyAh5x5en2XssIKl4w8i1mx4QbZFc4nXUtVsYvYe+W/CBG +vevUez8/fEc4BKkbqlLfEzfTFRVOvV98r61jx3ncCHvVoOX3W3WsgFWZkmGbzSoXfduP9LVq6hdK +ZChmFSlsAvFr1bqjM9xaZ6cF4r9lthawEO3NUDPJcFDsGY6wx/J0W2tExn2WuZgIWWbeKQGb9Cpt +0xU6kGpn8bRrZtkh68rZYnxGEFzedUlnnkL5/nWpo63/dgpnQOPF943HhZpZnmKaau1Fh5hnstVK +PNe0OwANwI8f4UDErmwh3El+fsqyjW22v5MvoVw+j8rtgI5Y4dtXz4U2OLJxpAmMkokIiEjxQGMY +sluMWuPD0xeqqxmjLBvk1cbiZnrXghmmOxYsL3GHX0WelXOTwkKBIROW1527k2gV+p2kHYzygeBY +Br3JtuP2iV2J+axEoctr+hbxx1A9JNr3w+SH1VbxT5Aw+kUJWdo0zuATHAR8ANSbhqRAvNncTFd+ +rrcztl524WWLZt+NyteYr842mIycg5kDcPOvdO3GDjbnvezBc6eUWsuSZIKmAMFwoW4sKeFYV+xa +fJlrJaSQOoD0IJ2azsct+bJLKZWD6TWNp0lIpw9MGZHQ9b8Q4HECAwEAAaNCMEAwDwYDVR0TAQH/ +BAUwAwEB/zAdBgNVHQ4EFgQUdEmZ0f+0emhFdcN+tNzMzjkz2ggwDgYDVR0PAQH/BAQDAgGGMA0G +CSqGSIb3DQEBDAUAA4ICAQAjQ1MkYlxt/T7Cz1UAbMVWiLkO3TriJQ2VSpfKgInuKs1l+NsW4AmS +4BjHeJi78+xCUvuppILXTdiK/ORO/auQxDh1MoSf/7OwKwIzNsAQkG8dnK/haZPso0UvFJ/1TCpl +Q3IM98P4lYsU84UgYt1UU90s3BiVaU+DR3BAM1h3Egyi61IxHkzJqM7F78PRreBrAwA0JrRUITWX +AdxfG/F851X6LWh3e9NpzNMOa7pNdkTWwhWaJuywxfW70Xp0wmzNxbVe9kzmWy2B27O3Opee7c9G +slA9hGCZcbUztVdF5kJHdWoOsAgMrr3e97sPWD2PAzHoPYJQyi9eDF20l74gNAf0xBLh7tew2Vkt +afcxBPTy+av5EzH4AXcOPUIjJsyacmdRIXrMPIWo6iFqO9taPKU0nprALN+AnCng33eU0aKAQv9q +TFsR0PXNor6uzFFcw9VUewyu1rkGd4Di7wcaaMxZUa1+XGdrudviB0JbuAEFWDlN5LuYo7Ey7Nmj +1m+UI/87tyll5gfp77YZ6ufCOB0yiJA8EytuzO+rdwY0d4RPcuSBhPm5dDTedk+SKlOxJTnbPP/l +PqYO5Wue/9vsL3SD3460s6neFE3/MaNFcyT6lSnMEpcEoji2jbDwN/zIIX8/syQbPYtuzE2wFg2W +HYMfRsCbvUOZ58SWLs5fyQ== +-----END CERTIFICATE----- + +TrustAsia Global Root CA G3 +=========================== +-----BEGIN CERTIFICATE----- +MIIFpTCCA42gAwIBAgIUZPYOZXdhaqs7tOqFhLuxibhxkw8wDQYJKoZIhvcNAQEMBQAwWjELMAkG +A1UEBhMCQ04xJTAjBgNVBAoMHFRydXN0QXNpYSBUZWNobm9sb2dpZXMsIEluYy4xJDAiBgNVBAMM +G1RydXN0QXNpYSBHbG9iYWwgUm9vdCBDQSBHMzAeFw0yMTA1MjAwMjEwMTlaFw00NjA1MTkwMjEw +MTlaMFoxCzAJBgNVBAYTAkNOMSUwIwYDVQQKDBxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMu +MSQwIgYDVQQDDBtUcnVzdEFzaWEgR2xvYmFsIFJvb3QgQ0EgRzMwggIiMA0GCSqGSIb3DQEBAQUA +A4ICDwAwggIKAoICAQDAMYJhkuSUGwoqZdC+BqmHO1ES6nBBruL7dOoKjbmzTNyPtxNST1QY4Sxz +lZHFZjtqz6xjbYdT8PfxObegQ2OwxANdV6nnRM7EoYNl9lA+sX4WuDqKAtCWHwDNBSHvBm3dIZwZ +Q0WhxeiAysKtQGIXBsaqvPPW5vxQfmZCHzyLpnl5hkA1nyDvP+uLRx+PjsXUjrYsyUQE49RDdT/V +P68czH5GX6zfZBCK70bwkPAPLfSIC7Epqq+FqklYqL9joDiR5rPmd2jE+SoZhLsO4fWvieylL1Ag +dB4SQXMeJNnKziyhWTXAyB1GJ2Faj/lN03J5Zh6fFZAhLf3ti1ZwA0pJPn9pMRJpxx5cynoTi+jm +9WAPzJMshH/x/Gr8m0ed262IPfN2dTPXS6TIi/n1Q1hPy8gDVI+lhXgEGvNz8teHHUGf59gXzhqc +D0r83ERoVGjiQTz+LISGNzzNPy+i2+f3VANfWdP3kXjHi3dqFuVJhZBFcnAvkV34PmVACxmZySYg +WmjBNb9Pp1Hx2BErW+Canig7CjoKH8GB5S7wprlppYiU5msTf9FkPz2ccEblooV7WIQn3MSAPmea +mseaMQ4w7OYXQJXZRe0Blqq/DPNL0WP3E1jAuPP6Z92bfW1K/zJMtSU7/xxnD4UiWQWRkUF3gdCF +TIcQcf+eQxuulXUtgQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFEDk5PIj +7zjKsK5Xf/IhMBY027ySMB0GA1UdDgQWBBRA5OTyI+84yrCuV3/yITAWNNu8kjAOBgNVHQ8BAf8E +BAMCAQYwDQYJKoZIhvcNAQEMBQADggIBACY7UeFNOPMyGLS0XuFlXsSUT9SnYaP4wM8zAQLpw6o1 +D/GUE3d3NZ4tVlFEbuHGLige/9rsR82XRBf34EzC4Xx8MnpmyFq2XFNFV1pF1AWZLy4jVe5jaN/T +G3inEpQGAHUNcoTpLrxaatXeL1nHo+zSh2bbt1S1JKv0Q3jbSwTEb93mPmY+KfJLaHEih6D4sTNj +duMNhXJEIlU/HHzp/LgV6FL6qj6jITk1dImmasI5+njPtqzn59ZW/yOSLlALqbUHM/Q4X6RJpstl +cHboCoWASzY9M/eVVHUl2qzEc4Jl6VL1XP04lQJqaTDFHApXB64ipCz5xUG3uOyfT0gA+QEEVcys ++TIxxHWVBqB/0Y0n3bOppHKH/lmLmnp0Ft0WpWIp6zqW3IunaFnT63eROfjXy9mPX1onAX1daBli +2MjN9LdyR75bl87yraKZk62Uy5P2EgmVtqvXO9A/EcswFi55gORngS1d7XB4tmBZrOFdRWOPyN9y +aFvqHbgB8X7754qz41SgOAngPN5C8sLtLpvzHzW2NtjjgKGLzZlkD8Kqq7HK9W+eQ42EVJmzbsAS +ZthwEPEGNTNDqJwuuhQxzhB/HIbjj9LV+Hfsm6vxL2PZQl/gZ4FkkfGXL/xuJvYz+NO1+MRiqzFR +JQJ6+N1rZdVtTTDIZbpoFGWsJwt0ivKH +-----END CERTIFICATE----- + +TrustAsia Global Root CA G4 +=========================== +-----BEGIN CERTIFICATE----- +MIICVTCCAdygAwIBAgIUTyNkuI6XY57GU4HBdk7LKnQV1tcwCgYIKoZIzj0EAwMwWjELMAkGA1UE +BhMCQ04xJTAjBgNVBAoMHFRydXN0QXNpYSBUZWNobm9sb2dpZXMsIEluYy4xJDAiBgNVBAMMG1Ry +dXN0QXNpYSBHbG9iYWwgUm9vdCBDQSBHNDAeFw0yMTA1MjAwMjEwMjJaFw00NjA1MTkwMjEwMjJa +MFoxCzAJBgNVBAYTAkNOMSUwIwYDVQQKDBxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMSQw +IgYDVQQDDBtUcnVzdEFzaWEgR2xvYmFsIFJvb3QgQ0EgRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNi +AATxs8045CVD5d4ZCbuBeaIVXxVjAd7Cq92zphtnS4CDr5nLrBfbK5bKfFJV4hrhPVbwLxYI+hW8 +m7tH5j/uqOFMjPXTNvk4XatwmkcN4oFBButJ+bAp3TPsUKV/eSm4IJijYzBhMA8GA1UdEwEB/wQF +MAMBAf8wHwYDVR0jBBgwFoAUpbtKl86zK3+kMd6Xg1mDpm9xy94wHQYDVR0OBBYEFKW7SpfOsyt/ +pDHel4NZg6ZvccveMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjBe8usGzEkxn0AA +bbd+NvBNEU/zy4k6LHiRUKNbwMp1JvK/kF0LgoxgKJ/GcJpo5PECMFxYDlZ2z1jD1xCMuo6u47xk +dUfFVZDj/bpV6wfEU6s3qe4hsiFbYI89MvHVI5TWWA== +-----END CERTIFICATE----- + +CommScope Public Trust ECC Root-01 +================================== +-----BEGIN CERTIFICATE----- +MIICHTCCAaOgAwIBAgIUQ3CCd89NXTTxyq4yLzf39H91oJ4wCgYIKoZIzj0EAwMwTjELMAkGA1UE +BhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29tbVNjb3BlIFB1YmxpYyBUcnVz +dCBFQ0MgUm9vdC0wMTAeFw0yMTA0MjgxNzM1NDNaFw00NjA0MjgxNzM1NDJaME4xCzAJBgNVBAYT +AlVTMRIwEAYDVQQKDAlDb21tU2NvcGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3Qg +RUNDIFJvb3QtMDEwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARLNumuV16ocNfQj3Rid8NeeqrltqLx +eP0CflfdkXmcbLlSiFS8LwS+uM32ENEp7LXQoMPwiXAZu1FlxUOcw5tjnSCDPgYLpkJEhRGnSjot +6dZoL0hOUysHP029uax3OVejQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G +A1UdDgQWBBSOB2LAUN3GGQYARnQE9/OufXVNMDAKBggqhkjOPQQDAwNoADBlAjEAnDPfQeMjqEI2 +Jpc1XHvr20v4qotzVRVcrHgpD7oh2MSg2NED3W3ROT3Ek2DS43KyAjB8xX6I01D1HiXo+k515liW +pDVfG2XqYZpwI7UNo5uSUm9poIyNStDuiw7LR47QjRE= +-----END CERTIFICATE----- + +CommScope Public Trust ECC Root-02 +================================== +-----BEGIN CERTIFICATE----- +MIICHDCCAaOgAwIBAgIUKP2ZYEFHpgE6yhR7H+/5aAiDXX0wCgYIKoZIzj0EAwMwTjELMAkGA1UE +BhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29tbVNjb3BlIFB1YmxpYyBUcnVz +dCBFQ0MgUm9vdC0wMjAeFw0yMTA0MjgxNzQ0NTRaFw00NjA0MjgxNzQ0NTNaME4xCzAJBgNVBAYT +AlVTMRIwEAYDVQQKDAlDb21tU2NvcGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3Qg +RUNDIFJvb3QtMDIwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAR4MIHoYx7l63FRD/cHB8o5mXxO1Q/M +MDALj2aTPs+9xYa9+bG3tD60B8jzljHz7aRP+KNOjSkVWLjVb3/ubCK1sK9IRQq9qEmUv4RDsNuE +SgMjGWdqb8FuvAY5N9GIIvejQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G +A1UdDgQWBBTmGHX/72DehKT1RsfeSlXjMjZ59TAKBggqhkjOPQQDAwNnADBkAjAmc0l6tqvmSfR9 +Uj/UQQSugEODZXW5hYA4O9Zv5JOGq4/nich/m35rChJVYaoR4HkCMHfoMXGsPHED1oQmHhS48zs7 +3u1Z/GtMMH9ZzkXpc2AVmkzw5l4lIhVtwodZ0LKOag== +-----END CERTIFICATE----- + +CommScope Public Trust RSA Root-01 +================================== +-----BEGIN CERTIFICATE----- +MIIFbDCCA1SgAwIBAgIUPgNJgXUWdDGOTKvVxZAplsU5EN0wDQYJKoZIhvcNAQELBQAwTjELMAkG +A1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29tbVNjb3BlIFB1YmxpYyBU +cnVzdCBSU0EgUm9vdC0wMTAeFw0yMTA0MjgxNjQ1NTRaFw00NjA0MjgxNjQ1NTNaME4xCzAJBgNV +BAYTAlVTMRIwEAYDVQQKDAlDb21tU2NvcGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1 +c3QgUlNBIFJvb3QtMDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwSGWjDR1C45Ft +nYSkYZYSwu3D2iM0GXb26v1VWvZVAVMP8syMl0+5UMuzAURWlv2bKOx7dAvnQmtVzslhsuitQDy6 +uUEKBU8bJoWPQ7VAtYXR1HHcg0Hz9kXHgKKEUJdGzqAMxGBWBB0HW0alDrJLpA6lfO741GIDuZNq +ihS4cPgugkY4Iw50x2tBt9Apo52AsH53k2NC+zSDO3OjWiE260f6GBfZumbCk6SP/F2krfxQapWs +vCQz0b2If4b19bJzKo98rwjyGpg/qYFlP8GMicWWMJoKz/TUyDTtnS+8jTiGU+6Xn6myY5QXjQ/c +Zip8UlF1y5mO6D1cv547KI2DAg+pn3LiLCuz3GaXAEDQpFSOm117RTYm1nJD68/A6g3czhLmfTif +BSeolz7pUcZsBSjBAg/pGG3svZwG1KdJ9FQFa2ww8esD1eo9anbCyxooSU1/ZOD6K9pzg4H/kQO9 +lLvkuI6cMmPNn7togbGEW682v3fuHX/3SZtS7NJ3Wn2RnU3COS3kuoL4b/JOHg9O5j9ZpSPcPYeo +KFgo0fEbNttPxP/hjFtyjMcmAyejOQoBqsCyMWCDIqFPEgkBEa801M/XrmLTBQe0MXXgDW1XT2mH ++VepuhX2yFJtocucH+X8eKg1mp9BFM6ltM6UCBwJrVbl2rZJmkrqYxhTnCwuwwIDAQABo0IwQDAP +BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUN12mmnQywsL5x6YVEFm4 +5P3luG0wDQYJKoZIhvcNAQELBQADggIBAK+nz97/4L1CjU3lIpbfaOp9TSp90K09FlxD533Ahuh6 +NWPxzIHIxgvoLlI1pKZJkGNRrDSsBTtXAOnTYtPZKdVUvhwQkZyybf5Z/Xn36lbQnmhUQo8mUuJM +3y+Xpi/SB5io82BdS5pYV4jvguX6r2yBS5KPQJqTRlnLX3gWsWc+QgvfKNmwrZggvkN80V4aCRck +jXtdlemrwWCrWxhkgPut4AZ9HcpZuPN4KWfGVh2vtrV0KnahP/t1MJ+UXjulYPPLXAziDslg+Mkf +Foom3ecnf+slpoq9uC02EJqxWE2aaE9gVOX2RhOOiKy8IUISrcZKiX2bwdgt6ZYD9KJ0DLwAHb/W +NyVntHKLr4W96ioDj8z7PEQkguIBpQtZtjSNMgsSDesnwv1B10A8ckYpwIzqug/xBpMu95yo9GA+ +o/E4Xo4TwbM6l4c/ksp4qRyv0LAbJh6+cOx69TOY6lz/KwsETkPdY34Op054A5U+1C0wlREQKC6/ +oAI+/15Z0wUOlV9TRe9rh9VIzRamloPh37MG88EU26fsHItdkJANclHnYfkUyq+Dj7+vsQpZXdxc +1+SWrVtgHdqul7I52Qb1dgAT+GhMIbA1xNxVssnBQVocicCMb3SgazNNtQEo/a2tiRc7ppqEvOuM +6sRxJKi6KfkIsidWNTJf6jn7MZrVGczw +-----END CERTIFICATE----- + +CommScope Public Trust RSA Root-02 +================================== +-----BEGIN CERTIFICATE----- +MIIFbDCCA1SgAwIBAgIUVBa/O345lXGN0aoApYYNK496BU4wDQYJKoZIhvcNAQELBQAwTjELMAkG +A1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29tbVNjb3BlIFB1YmxpYyBU +cnVzdCBSU0EgUm9vdC0wMjAeFw0yMTA0MjgxNzE2NDNaFw00NjA0MjgxNzE2NDJaME4xCzAJBgNV +BAYTAlVTMRIwEAYDVQQKDAlDb21tU2NvcGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1 +c3QgUlNBIFJvb3QtMDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDh+g77aAASyE3V +rCLENQE7xVTlWXZjpX/rwcRqmL0yjReA61260WI9JSMZNRTpf4mnG2I81lDnNJUDMrG0kyI9p+Kx +7eZ7Ti6Hmw0zdQreqjXnfuU2mKKuJZ6VszKWpCtYHu8//mI0SFHRtI1CrWDaSWqVcN3SAOLMV2MC +e5bdSZdbkk6V0/nLKR8YSvgBKtJjCW4k6YnS5cciTNxzhkcAqg2Ijq6FfUrpuzNPDlJwnZXjfG2W +Wy09X6GDRl224yW4fKcZgBzqZUPckXk2LHR88mcGyYnJ27/aaL8j7dxrrSiDeS/sOKUNNwFnJ5rp +M9kzXzehxfCrPfp4sOcsn/Y+n2Dg70jpkEUeBVF4GiwSLFworA2iI540jwXmojPOEXcT1A6kHkIf +hs1w/tkuFT0du7jyU1fbzMZ0KZwYszZ1OC4PVKH4kh+Jlk+71O6d6Ts2QrUKOyrUZHk2EOH5kQMr +eyBUzQ0ZGshBMjTRsJnhkB4BQDa1t/qp5Xd1pCKBXbCL5CcSD1SIxtuFdOa3wNemKfrb3vOTlycE +VS8KbzfFPROvCgCpLIscgSjX74Yxqa7ybrjKaixUR9gqiC6vwQcQeKwRoi9C8DfF8rhW3Q5iLc4t +Vn5V8qdE9isy9COoR+jUKgF4z2rDN6ieZdIs5fq6M8EGRPbmz6UNp2YINIos8wIDAQABo0IwQDAP +BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUR9DnsSL/nSz12Vdgs7Gx +cJXvYXowDQYJKoZIhvcNAQELBQADggIBAIZpsU0v6Z9PIpNojuQhmaPORVMbc0RTAIFhzTHjCLqB +KCh6krm2qMhDnscTJk3C2OVVnJJdUNjCK9v+5qiXz1I6JMNlZFxHMaNlNRPDk7n3+VGXu6TwYofF +1gbTl4MgqX67tiHCpQ2EAOHyJxCDut0DgdXdaMNmEMjRdrSzbymeAPnCKfWxkxlSaRosTKCL4BWa +MS/TiJVZbuXEs1DIFAhKm4sTg7GkcrI7djNB3NyqpgdvHSQSn8h2vS/ZjvQs7rfSOBAkNlEv41xd +gSGn2rtO/+YHqP65DSdsu3BaVXoT6fEqSWnHX4dXTEN5bTpl6TBcQe7rd6VzEojov32u5cSoHw2O +HG1QAk8mGEPej1WFsQs3BWDJVTkSBKEqz3EWnzZRSb9wO55nnPt7eck5HHisd5FUmrh1CoFSl+Nm +YWvtPjgelmFV4ZFUjO2MJB+ByRCac5krFk5yAD9UG/iNuovnFNa2RU9g7Jauwy8CTl2dlklyALKr +dVwPaFsdZcJfMw8eD/A7hvWwTruc9+olBdytoptLFwG+Qt81IR2tq670v64fG9PiO/yzcnMcmyiQ +iRM9HcEARwmWmjgb3bHPDcK0RPOWlc4yOo80nOAXx17Org3bhzjlP1v9mxnhMUF6cKojawHhRUzN +lM47ni3niAIi9G7oyOzWPPO5std3eqx7 +-----END CERTIFICATE----- + +Telekom Security TLS ECC Root 2020 +================================== +-----BEGIN CERTIFICATE----- +MIICQjCCAcmgAwIBAgIQNjqWjMlcsljN0AFdxeVXADAKBggqhkjOPQQDAzBjMQswCQYDVQQGEwJE +RTEnMCUGA1UECgweRGV1dHNjaGUgVGVsZWtvbSBTZWN1cml0eSBHbWJIMSswKQYDVQQDDCJUZWxl +a29tIFNlY3VyaXR5IFRMUyBFQ0MgUm9vdCAyMDIwMB4XDTIwMDgyNTA3NDgyMFoXDTQ1MDgyNTIz +NTk1OVowYzELMAkGA1UEBhMCREUxJzAlBgNVBAoMHkRldXRzY2hlIFRlbGVrb20gU2VjdXJpdHkg +R21iSDErMCkGA1UEAwwiVGVsZWtvbSBTZWN1cml0eSBUTFMgRUNDIFJvb3QgMjAyMDB2MBAGByqG +SM49AgEGBSuBBAAiA2IABM6//leov9Wq9xCazbzREaK9Z0LMkOsVGJDZos0MKiXrPk/OtdKPD/M1 +2kOLAoC+b1EkHQ9rK8qfwm9QMuU3ILYg/4gND21Ju9sGpIeQkpT0CdDPf8iAC8GXs7s1J8nCG6NC +MEAwHQYDVR0OBBYEFONyzG6VmUex5rNhTNHLq+O6zd6fMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P +AQH/BAQDAgEGMAoGCCqGSM49BAMDA2cAMGQCMHVSi7ekEE+uShCLsoRbQuHmKjYC2qBuGT8lv9pZ +Mo7k+5Dck2TOrbRBR2Diz6fLHgIwN0GMZt9Ba9aDAEH9L1r3ULRn0SyocddDypwnJJGDSA3PzfdU +ga/sf+Rn27iQ7t0l +-----END CERTIFICATE----- + +Telekom Security TLS RSA Root 2023 +================================== +-----BEGIN CERTIFICATE----- +MIIFszCCA5ugAwIBAgIQIZxULej27HF3+k7ow3BXlzANBgkqhkiG9w0BAQwFADBjMQswCQYDVQQG +EwJERTEnMCUGA1UECgweRGV1dHNjaGUgVGVsZWtvbSBTZWN1cml0eSBHbWJIMSswKQYDVQQDDCJU +ZWxla29tIFNlY3VyaXR5IFRMUyBSU0EgUm9vdCAyMDIzMB4XDTIzMDMyODEyMTY0NVoXDTQ4MDMy +NzIzNTk1OVowYzELMAkGA1UEBhMCREUxJzAlBgNVBAoMHkRldXRzY2hlIFRlbGVrb20gU2VjdXJp +dHkgR21iSDErMCkGA1UEAwwiVGVsZWtvbSBTZWN1cml0eSBUTFMgUlNBIFJvb3QgMjAyMzCCAiIw +DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAO01oYGA88tKaVvC+1GDrib94W7zgRJ9cUD/h3VC +KSHtgVIs3xLBGYSJwb3FKNXVS2xE1kzbB5ZKVXrKNoIENqil/Cf2SfHVcp6R+SPWcHu79ZvB7JPP +GeplfohwoHP89v+1VmLhc2o0mD6CuKyVU/QBoCcHcqMAU6DksquDOFczJZSfvkgdmOGjup5czQRx +UX11eKvzWarE4GC+j4NSuHUaQTXtvPM6Y+mpFEXX5lLRbtLevOP1Czvm4MS9Q2QTps70mDdsipWo +l8hHD/BeEIvnHRz+sTugBTNoBUGCwQMrAcjnj02r6LX2zWtEtefdi+zqJbQAIldNsLGyMcEWzv/9 +FIS3R/qy8XDe24tsNlikfLMR0cN3f1+2JeANxdKz+bi4d9s3cXFH42AYTyS2dTd4uaNir73Jco4v +zLuu2+QVUhkHM/tqty1LkCiCc/4YizWN26cEar7qwU02OxY2kTLvtkCJkUPg8qKrBC7m8kwOFjQg +rIfBLX7JZkcXFBGk8/ehJImr2BrIoVyxo/eMbcgByU/J7MT8rFEz0ciD0cmfHdRHNCk+y7AO+oML +KFjlKdw/fKifybYKu6boRhYPluV75Gp6SG12mAWl3G0eQh5C2hrgUve1g8Aae3g1LDj1H/1Joy7S +WWO/gLCMk3PLNaaZlSJhZQNg+y+TS/qanIA7AgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAdBgNV +HQ4EFgQUtqeXgj10hZv3PJ+TmpV5dVKMbUcwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS2 +p5eCPXSFm/c8n5OalXl1UoxtRzANBgkqhkiG9w0BAQwFAAOCAgEAqMxhpr51nhVQpGv7qHBFfLp+ +sVr8WyP6Cnf4mHGCDG3gXkaqk/QeoMPhk9tLrbKmXauw1GLLXrtm9S3ul0A8Yute1hTWjOKWi0Fp +kzXmuZlrYrShF2Y0pmtjxrlO8iLpWA1WQdH6DErwM807u20hOq6OcrXDSvvpfeWxm4bu4uB9tPcy +/SKE8YXJN3nptT+/XOR0so8RYgDdGGah2XsjX/GO1WfoVNpbOms2b/mBsTNHM3dA+VKq3dSDz4V4 +mZqTuXNnQkYRIer+CqkbGmVps4+uFrb2S1ayLfmlyOw7YqPta9BO1UAJpB+Y1zqlklkg5LB9zVtz +aL1txKITDmcZuI1CfmwMmm6gJC3VRRvcxAIU/oVbZZfKTpBQCHpCNfnqwmbU+AGuHrS+w6jv/naa +oqYfRvaE7fzbzsQCzndILIyy7MMAo+wsVRjBfhnu4S/yrYObnqsZ38aKL4x35bcF7DvB7L6Gs4a8 +wPfc5+pbrrLMtTWGS9DiP7bY+A4A7l3j941Y/8+LN+ljX273CXE2whJdV/LItM3z7gLfEdxquVeE +HVlNjM7IDiPCtyaaEBRx/pOyiriA8A4QntOoUAw3gi/q4Iqd4Sw5/7W0cwDk90imc6y/st53BIe0 +o82bNSQ3+pCTE4FCxpgmdTdmQRCsu/WU48IxK63nI1bMNSWSs1A= +-----END CERTIFICATE----- + +FIRMAPROFESIONAL CA ROOT-A WEB +============================== +-----BEGIN CERTIFICATE----- +MIICejCCAgCgAwIBAgIQMZch7a+JQn81QYehZ1ZMbTAKBggqhkjOPQQDAzBuMQswCQYDVQQGEwJF +UzEcMBoGA1UECgwTRmlybWFwcm9mZXNpb25hbCBTQTEYMBYGA1UEYQwPVkFURVMtQTYyNjM0MDY4 +MScwJQYDVQQDDB5GSVJNQVBST0ZFU0lPTkFMIENBIFJPT1QtQSBXRUIwHhcNMjIwNDA2MDkwMTM2 +WhcNNDcwMzMxMDkwMTM2WjBuMQswCQYDVQQGEwJFUzEcMBoGA1UECgwTRmlybWFwcm9mZXNpb25h +bCBTQTEYMBYGA1UEYQwPVkFURVMtQTYyNjM0MDY4MScwJQYDVQQDDB5GSVJNQVBST0ZFU0lPTkFM +IENBIFJPT1QtQSBXRUIwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARHU+osEaR3xyrq89Zfe9MEkVz6 +iMYiuYMQYneEMy3pA4jU4DP37XcsSmDq5G+tbbT4TIqk5B/K6k84Si6CcyvHZpsKjECcfIr28jlg +st7L7Ljkb+qbXbdTkBgyVcUgt5SjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUk+FD +Y1w8ndYn81LsF7Kpryz3dvgwHQYDVR0OBBYEFJPhQ2NcPJ3WJ/NS7Beyqa8s93b4MA4GA1UdDwEB +/wQEAwIBBjAKBggqhkjOPQQDAwNoADBlAjAdfKR7w4l1M+E7qUW/Runpod3JIha3RxEL2Jq68cgL +cFBTApFwhVmpHqTm6iMxoAACMQD94vizrxa5HnPEluPBMBnYfubDl94cT7iJLzPrSA8Z94dGXSaQ +pYXFuXqUPoeovQA= +-----END CERTIFICATE----- + +TWCA CYBER Root CA +================== +-----BEGIN CERTIFICATE----- +MIIFjTCCA3WgAwIBAgIQQAE0jMIAAAAAAAAAATzyxjANBgkqhkiG9w0BAQwFADBQMQswCQYDVQQG +EwJUVzESMBAGA1UEChMJVEFJV0FOLUNBMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJUV0NB +IENZQkVSIFJvb3QgQ0EwHhcNMjIxMTIyMDY1NDI5WhcNNDcxMTIyMTU1OTU5WjBQMQswCQYDVQQG +EwJUVzESMBAGA1UEChMJVEFJV0FOLUNBMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJUV0NB +IENZQkVSIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDG+Moe2Qkgfh1s +Ts6P40czRJzHyWmqOlt47nDSkvgEs1JSHWdyKKHfi12VCv7qze33Kc7wb3+szT3vsxxFavcokPFh +V8UMxKNQXd7UtcsZyoC5dc4pztKFIuwCY8xEMCDa6pFbVuYdHNWdZsc/34bKS1PE2Y2yHer43CdT +o0fhYcx9tbD47nORxc5zb87uEB8aBs/pJ2DFTxnk684iJkXXYJndzk834H/nY62wuFm40AZoNWDT +Nq5xQwTxaWV4fPMf88oon1oglWa0zbfuj3ikRRjpJi+NmykosaS3Om251Bw4ckVYsV7r8Cibt4LK +/c/WMw+f+5eesRycnupfXtuq3VTpMCEobY5583WSjCb+3MX2w7DfRFlDo7YDKPYIMKoNM+HvnKkH +IuNZW0CP2oi3aQiotyMuRAlZN1vH4xfyIutuOVLF3lSnmMlLIJXcRolftBL5hSmO68gnFSDAS9TM +fAxsNAwmmyYxpjyn9tnQS6Jk/zuZQXLB4HCX8SS7K8R0IrGsayIyJNN4KsDAoS/xUgXJP+92ZuJF +2A09rZXIx4kmyA+upwMu+8Ff+iDhcK2wZSA3M2Cw1a/XDBzCkHDXShi8fgGwsOsVHkQGzaRP6AzR +wyAQ4VRlnrZR0Bp2a0JaWHY06rc3Ga4udfmW5cFZ95RXKSWNOkyrTZpB0F8mAwIDAQABo2MwYTAO +BgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBSdhWEUfMFib5do5E83 +QOGt4A1WNzAdBgNVHQ4EFgQUnYVhFHzBYm+XaORPN0DhreANVjcwDQYJKoZIhvcNAQEMBQADggIB +AGSPesRiDrWIzLjHhg6hShbNcAu3p4ULs3a2D6f/CIsLJc+o1IN1KriWiLb73y0ttGlTITVX1olN +c79pj3CjYcya2x6a4CD4bLubIp1dhDGaLIrdaqHXKGnK/nZVekZn68xDiBaiA9a5F/gZbG0jAn/x +X9AKKSM70aoK7akXJlQKTcKlTfjF/biBzysseKNnTKkHmvPfXvt89YnNdJdhEGoHK4Fa0o635yDR +IG4kqIQnoVesqlVYL9zZyvpoBJ7tRCT5dEA7IzOrg1oYJkK2bVS1FmAwbLGg+LhBoF1JSdJlBTrq +/p1hvIbZv97Tujqxf36SNI7JAG7cmL3c7IAFrQI932XtCwP39xaEBDG6k5TY8hL4iuO/Qq+n1M0R +FxbIQh0UqEL20kCGoE8jypZFVmAGzbdVAaYBlGX+bgUJurSkquLvWL69J1bY73NxW0Qz8ppy6rBe +Pm6pUlvscG21h483XjyMnM7k8M4MZ0HMzvaAq07MTFb1wWFZk7Q+ptq4NxKfKjLji7gh7MMrZQzv +It6IKTtM1/r+t+FHvpw+PoP7UV31aPcuIYXcv/Fa4nzXxeSDwWrruoBa3lwtcHb4yOWHh8qgnaHl +IhInD0Q9HWzq1MKLL295q39QpsQZp6F6t5b5wR9iWqJDB0BeJsas7a5wFsWqynKKTbDPAYsDP27X +-----END CERTIFICATE----- + +SecureSign Root CA12 +==================== +-----BEGIN CERTIFICATE----- +MIIDcjCCAlqgAwIBAgIUZvnHwa/swlG07VOX5uaCwysckBYwDQYJKoZIhvcNAQELBQAwUTELMAkG +A1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28uLCBMdGQuMR0wGwYDVQQDExRT +ZWN1cmVTaWduIFJvb3QgQ0ExMjAeFw0yMDA0MDgwNTM2NDZaFw00MDA0MDgwNTM2NDZaMFExCzAJ +BgNVBAYTAkpQMSMwIQYDVQQKExpDeWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMU +U2VjdXJlU2lnbiBSb290IENBMTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6OcE3 +emhFKxS06+QT61d1I02PJC0W6K6OyX2kVzsqdiUzg2zqMoqUm048luT9Ub+ZyZN+v/mtp7JIKwcc +J/VMvHASd6SFVLX9kHrko+RRWAPNEHl57muTH2SOa2SroxPjcf59q5zdJ1M3s6oYwlkm7Fsf0uZl +fO+TvdhYXAvA42VvPMfKWeP+bl+sg779XSVOKik71gurFzJ4pOE+lEa+Ym6b3kaosRbnhW70CEBF +EaCeVESE99g2zvVQR9wsMJvuwPWW0v4JhscGWa5Pro4RmHvzC1KqYiaqId+OJTN5lxZJjfU+1Uef +NzFJM3IFTQy2VYzxV4+Kh9GtxRESOaCtAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P +AQH/BAQDAgEGMB0GA1UdDgQWBBRXNPN0zwRL1SXm8UC2LEzZLemgrTANBgkqhkiG9w0BAQsFAAOC +AQEAPrvbFxbS8hQBICw4g0utvsqFepq2m2um4fylOqyttCg6r9cBg0krY6LdmmQOmFxv3Y67ilQi +LUoT865AQ9tPkbeGGuwAtEGBpE/6aouIs3YIcipJQMPTw4WJmBClnW8Zt7vPemVV2zfrPIpyMpce +mik+rY3moxtt9XUa5rBouVui7mlHJzWhhpmA8zNL4WukJsPvdFlseqJkth5Ew1DgDzk9qTPxpfPS +vWKErI4cqc1avTc7bgoitPQV55FYxTpE05Uo2cBl6XLK0A+9H7MV2anjpEcJnuDLN/v9vZfVvhga +aaI5gdka9at/yOPiZwud9AzqVN/Ssq+xIvEg37xEHA== +-----END CERTIFICATE----- + +SecureSign Root CA14 +==================== +-----BEGIN CERTIFICATE----- +MIIFcjCCA1qgAwIBAgIUZNtaDCBO6Ncpd8hQJ6JaJ90t8sswDQYJKoZIhvcNAQEMBQAwUTELMAkG +A1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28uLCBMdGQuMR0wGwYDVQQDExRT +ZWN1cmVTaWduIFJvb3QgQ0ExNDAeFw0yMDA0MDgwNzA2MTlaFw00NTA0MDgwNzA2MTlaMFExCzAJ +BgNVBAYTAkpQMSMwIQYDVQQKExpDeWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMU +U2VjdXJlU2lnbiBSb290IENBMTQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDF0nqh +1oq/FjHQmNE6lPxauG4iwWL3pwon71D2LrGeaBLwbCRjOfHw3xDG3rdSINVSW0KZnvOgvlIfX8xn +bacuUKLBl422+JX1sLrcneC+y9/3OPJH9aaakpUqYllQC6KxNedlsmGy6pJxaeQp8E+BgQQ8sqVb +1MWoWWd7VRxJq3qdwudzTe/NCcLEVxLbAQ4jeQkHO6Lo/IrPj8BGJJw4J+CDnRugv3gVEOuGTgpa +/d/aLIJ+7sr2KeH6caH3iGicnPCNvg9JkdjqOvn90Ghx2+m1K06Ckm9mH+Dw3EzsytHqunQG+bOE +kJTRX45zGRBdAuVwpcAQ0BB8b8VYSbSwbprafZX1zNoCr7gsfXmPvkPx+SgojQlD+Ajda8iLLCSx +jVIHvXiby8posqTdDEx5YMaZ0ZPxMBoH064iwurO8YQJzOAUbn8/ftKChazcqRZOhaBgy/ac18iz +ju3Gm5h1DVXoX+WViwKkrkMpKBGk5hIwAUt1ax5mnXkvpXYvHUC0bcl9eQjs0Wq2XSqypWa9a4X0 +dFbD9ed1Uigspf9mR6XU/v6eVL9lfgHWMI+lNpyiUBzuOIABSMbHdPTGrMNASRZhdCyvjG817XsY +AFs2PJxQDcqSMxDxJklt33UkN4Ii1+iW/RVLApY+B3KVfqs9TC7XyvDf4Fg/LS8EmjijAQIDAQAB +o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUBpOjCl4oaTeq +YR3r6/wtbyPk86AwDQYJKoZIhvcNAQEMBQADggIBAJaAcgkGfpzMkwQWu6A6jZJOtxEaCnFxEM0E +rX+lRVAQZk5KQaID2RFPeje5S+LGjzJmdSX7684/AykmjbgWHfYfM25I5uj4V7Ibed87hwriZLoA +ymzvftAj63iP/2SbNDefNWWipAA9EiOWWF3KY4fGoweITedpdopTzfFP7ELyk+OZpDc8h7hi2/Ds +Hzc/N19DzFGdtfCXwreFamgLRB7lUe6TzktuhsHSDCRZNhqfLJGP4xjblJUK7ZGqDpncllPjYYPG +FrojutzdfhrGe0K22VoF3Jpf1d+42kd92jjbrDnVHmtsKheMYc2xbXIBw8MgAGJoFjHVdqqGuw6q +nsb58Nn4DSEC5MUoFlkRudlpcyqSeLiSV5sI8jrlL5WwWLdrIBRtFO8KvH7YVdiI2i/6GaX7i+B/ +OfVyK4XELKzvGUWSTLNhB9xNH27SgRNcmvMSZ4PPmz+Ln52kuaiWA3rF7iDeM9ovnhp6dB7h7sxa +OgTdsxoEqBRjrLdHEoOabPXm6RUVkRqEGQ6UROcSjiVbgGcZ3GOTEAtlLor6CZpO2oYofaphNdgO +pygau1LgePhsumywbrmHXumZNTfxPWQrqaA0k89jL9WB365jJ6UeTo3cKXhZ+PmhIIynJkBugnLN +eLLIjzwec+fBH7/PzqUqm9tEZDKgu39cJRNItX+S +-----END CERTIFICATE----- + +SecureSign Root CA15 +==================== +-----BEGIN CERTIFICATE----- +MIICIzCCAamgAwIBAgIUFhXHw9hJp75pDIqI7fBw+d23PocwCgYIKoZIzj0EAwMwUTELMAkGA1UE +BhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28uLCBMdGQuMR0wGwYDVQQDExRTZWN1 +cmVTaWduIFJvb3QgQ0ExNTAeFw0yMDA0MDgwODMyNTZaFw00NTA0MDgwODMyNTZaMFExCzAJBgNV +BAYTAkpQMSMwIQYDVQQKExpDeWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMUU2Vj +dXJlU2lnbiBSb290IENBMTUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQLUHSNZDKZmbPSYAi4Io5G +dCx4wCtELW1fHcmuS1Iggz24FG1Th2CeX2yF2wYUleDHKP+dX+Sq8bOLbe1PL0vJSpSRZHX+AezB +2Ot6lHhWGENfa4HL9rzatAy2KZMIaY+jQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD +AgEGMB0GA1UdDgQWBBTrQciu/NWeUUj1vYv0hyCTQSvT9DAKBggqhkjOPQQDAwNoADBlAjEA2S6J +fl5OpBEHvVnCB96rMjhTKkZEBhd6zlHp4P9mLQlO4E/0BdGF9jVg3PVys0Z9AjBEmEYagoUeYWmJ +SwdLZrWeqrqgHkHZAXQ6bkU6iYAZezKYVWOr62Nuk22rGwlgMU4= +-----END CERTIFICATE----- + +D-TRUST BR Root CA 2 2023 +========================= +-----BEGIN CERTIFICATE----- +MIIFqTCCA5GgAwIBAgIQczswBEhb2U14LnNLyaHcZjANBgkqhkiG9w0BAQ0FADBIMQswCQYDVQQG +EwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRSVVNUIEJSIFJvb3QgQ0Eg +MiAyMDIzMB4XDTIzMDUwOTA4NTYzMVoXDTM4MDUwOTA4NTYzMFowSDELMAkGA1UEBhMCREUxFTAT +BgNVBAoTDEQtVHJ1c3QgR21iSDEiMCAGA1UEAxMZRC1UUlVTVCBCUiBSb290IENBIDIgMjAyMzCC +AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK7/CVmRgApKaOYkP7in5Mg6CjoWzckjYaCT +cfKri3OPoGdlYNJUa2NRb0kz4HIHE304zQaSBylSa053bATTlfrdTIzZXcFhfUvnKLNEgXtRr90z +sWh81k5M/itoucpmacTsXld/9w3HnDY25QdgrMBM6ghs7wZ8T1soegj8k12b9py0i4a6Ibn08OhZ +WiihNIQaJZG2tY/vsvmA+vk9PBFy2OMvhnbFeSzBqZCTRphny4NqoFAjpzv2gTng7fC5v2Xx2Mt6 +++9zA84A9H3X4F07ZrjcjrqDy4d2A/wl2ecjbwb9Z/Pg/4S8R7+1FhhGaRTMBffb00msa8yr5LUL +QyReS2tNZ9/WtT5PeB+UcSTq3nD88ZP+npNa5JRal1QMNXtfbO4AHyTsA7oC9Xb0n9Sa7YUsOCIv +x9gvdhFP/Wxc6PWOJ4d/GUohR5AdeY0cW/jPSoXk7bNbjb7EZChdQcRurDhaTyN0dKkSw/bSuREV +MweR2Ds3OmMwBtHFIjYoYiMQ4EbMl6zWK11kJNXuHA7e+whadSr2Y23OC0K+0bpwHJwh5Q8xaRfX +/Aq03u2AnMuStIv13lmiWAmlY0cL4UEyNEHZmrHZqLAbWt4NDfTisl01gLmB1IRpkQLLddCNxbU9 +CZEJjxShFHR5PtbJFR2kWVki3PaKRT08EtY+XTIvAgMBAAGjgY4wgYswDwYDVR0TAQH/BAUwAwEB +/zAdBgNVHQ4EFgQUZ5Dw1t61GNVGKX5cq/ieCLxklRAwDgYDVR0PAQH/BAQDAgEGMEkGA1UdHwRC +MEAwPqA8oDqGOGh0dHA6Ly9jcmwuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3RfYnJfcm9vdF9jYV8y +XzIwMjMuY3JsMA0GCSqGSIb3DQEBDQUAA4ICAQA097N3U9swFrktpSHxQCF16+tIFoE9c+CeJyrr +d6kTpGoKWloUMz1oH4Guaf2Mn2VsNELZLdB/eBaxOqwjMa1ef67nriv6uvw8l5VAk1/DLQOj7aRv +U9f6QA4w9QAgLABMjDu0ox+2v5Eyq6+SmNMW5tTRVFxDWy6u71cqqLRvpO8NVhTaIasgdp4D/Ca4 +nj8+AybmTNudX0KEPUUDAxxZiMrcLmEkWqTqJwtzEr5SswrPMhfiHocaFpVIbVrg0M8JkiZmkdij +YQ6qgYF/6FKC0ULn4B0Y+qSFNueG4A3rvNTJ1jxD8V1Jbn6Bm2m1iWKPiFLY1/4nwSPFyysCu7Ff +/vtDhQNGvl3GyiEm/9cCnnRK3PgTFbGBVzbLZVzRHTF36SXDw7IyN9XxmAnkbWOACKsGkoHU6XCP +pz+y7YaMgmo1yEJagtFSGkUPFaUA8JR7ZSdXOUPPfH/mvTWze/EZTN46ls/pdu4D58JDUjxqgejB +WoC9EV2Ta/vH5mQ/u2kc6d0li690yVRAysuTEwrt+2aSEcr1wPrYg1UDfNPFIkZ1cGt5SAYqgpq/ +5usWDiJFAbzdNpQ0qTUmiteXue4Icr80knCDgKs4qllo3UCkGJCy89UDyibK79XH4I9TjvAA46jt +n/mtd+ArY0+ew+43u3gJhJ65bvspmZDogNOfJA== +-----END CERTIFICATE----- + +D-TRUST EV Root CA 2 2023 +========================= +-----BEGIN CERTIFICATE----- +MIIFqTCCA5GgAwIBAgIQaSYJfoBLTKCnjHhiU19abzANBgkqhkiG9w0BAQ0FADBIMQswCQYDVQQG +EwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRSVVNUIEVWIFJvb3QgQ0Eg +MiAyMDIzMB4XDTIzMDUwOTA5MTAzM1oXDTM4MDUwOTA5MTAzMlowSDELMAkGA1UEBhMCREUxFTAT +BgNVBAoTDEQtVHJ1c3QgR21iSDEiMCAGA1UEAxMZRC1UUlVTVCBFViBSb290IENBIDIgMjAyMzCC +AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANiOo4mAC7JXUtypU0w3uX9jFxPvp1sjW2l1 +sJkKF8GLxNuo4MwxusLyzV3pt/gdr2rElYfXR8mV2IIEUD2BCP/kPbOx1sWy/YgJ25yE7CUXFId/ +MHibaljJtnMoPDT3mfd/06b4HEV8rSyMlD/YZxBTfiLNTiVR8CUkNRFeEMbsh2aJgWi6zCudR3Mf +vc2RpHJqnKIbGKBv7FD0fUDCqDDPvXPIEysQEx6Lmqg6lHPTGGkKSv/BAQP/eX+1SH977ugpbzZM +lWGG2Pmic4ruri+W7mjNPU0oQvlFKzIbRlUWaqZLKfm7lVa/Rh3sHZMdwGWyH6FDrlaeoLGPaxK3 +YG14C8qKXO0elg6DpkiVjTujIcSuWMYAsoS0I6SWhjW42J7YrDRJmGOVxcttSEfi8i4YHtAxq910 +7PncjLgcjmgjutDzUNzPZY9zOjLHfP7KgiJPvo5iR2blzYfi6NUPGJ/lBHJLRjwQ8kTCZFZxTnXo +nMkmdMV9WdEKWw9t/p51HBjGGjp82A0EzM23RWV6sY+4roRIPrN6TagD4uJ+ARZZaBhDM7DS3LAa +QzXupdqpRlyuhoFBAUp0JuyfBr/CBTdkdXgpaP3F9ev+R/nkhbDhezGdpn9yo7nELC7MmVcOIQxF +AZRl62UJxmMiCzNJkkg8/M3OsD6Onov4/knFNXJHAgMBAAGjgY4wgYswDwYDVR0TAQH/BAUwAwEB +/zAdBgNVHQ4EFgQUqvyREBuHkV8Wub9PS5FeAByxMoAwDgYDVR0PAQH/BAQDAgEGMEkGA1UdHwRC +MEAwPqA8oDqGOGh0dHA6Ly9jcmwuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3RfZXZfcm9vdF9jYV8y +XzIwMjMuY3JsMA0GCSqGSIb3DQEBDQUAA4ICAQCTy6UfmRHsmg1fLBWTxj++EI14QvBukEdHjqOS +Mo1wj/Zbjb6JzkcBahsgIIlbyIIQbODnmaprxiqgYzWRaoUlrRc4pZt+UPJ26oUFKidBK7GB0aL2 +QHWpDsvxVUjY7NHss+jOFKE17MJeNRqrphYBBo7q3C+jisosketSjl8MmxfPy3MHGcRqwnNU73xD +UmPBEcrCRbH0O1P1aa4846XerOhUt7KR/aypH/KH5BfGSah82ApB9PI+53c0BFLd6IHyTS9URZ0V +4U/M5d40VxDJI3IXcI1QcB9WbMy5/zpaT2N6w25lBx2Eof+pDGOJbbJAiDnXH3dotfyc1dZnaVuo +dNv8ifYbMvekJKZ2t0dT741Jj6m2g1qllpBFYfXeA08mD6iL8AOWsKwV0HFaanuU5nCT2vFp4LJi +TZ6P/4mdm13NRemUAiKN4DV/6PEEeXFsVIP4M7kFMhtYVRFP0OUnR3Hs7dpn1mKmS00PaaLJvOwi +S5THaJQXfuKOKD62xur1NGyfN4gHONuGcfrNlUhDbqNPgofXNJhuS5N5YHVpD/Aa1VP6IQzCP+k/ +HxiMkl14p3ZnGbuy6n/pcAlWVqOwDAstNl7F6cTVg8uGF5csbBNvh1qvSaYd2804BC5f4ko1Di1L ++KIkBI3Y4WNeApI02phhXBxvWHZks/wCuPWdCg== +-----END CERTIFICATE----- diff --git a/packages/security/openssl/package.mk b/packages/security/openssl/package.mk new file mode 100644 index 0000000000..63299a68b8 --- /dev/null +++ b/packages/security/openssl/package.mk @@ -0,0 +1,112 @@ +# 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="3.5.1" +PKG_SHA256="529043b15cffa5f36077a4d0af83f3de399807181d607441d734196d889b641f" +PKG_LICENSE="Apache-2.0" +PKG_SITE="https://openssl-library.org" +PKG_URL="https://github.com/openssl/openssl/releases/download/${PKG_NAME}-${PKG_VERSION}/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="ccache:host" +PKG_DEPENDS_TARGET="autotools:host gcc:host" +PKG_LONGDESC="The Open Source toolkit for Secure Sockets Layer and Transport Layer Security" +PKG_TOOLCHAIN="configure" + +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 + mkdir -p ${TOOLCHAIN}/etc/ssl + cp ${PKG_DIR}/cert/cacert.pem ${TOOLCHAIN}/etc/ssl/cert.pem +} + +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/archr/cacert.pem ${INSTALL}/etc/ssl/cacert.pem + ln -sf /run/archr/cacert.pem ${INSTALL}/etc/ssl/cert.pem + + # backwards compatibility + mkdir -p ${INSTALL}/etc/pki/tls + ln -sf /run/archr/cacert.pem ${INSTALL}/etc/pki/tls/cacert.pem + mkdir -p ${INSTALL}/etc/pki/tls/certs + ln -sf /run/archr/cacert.pem ${INSTALL}/etc/pki/tls/certs/ca-bundle.crt + mkdir -p ${INSTALL}/usr/lib/ssl + ln -sf /run/archr/cacert.pem ${INSTALL}/usr/lib/ssl/cert.pem +} + +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 0000000000..5c77facba6 --- /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/archr/cacert.pem + +[ -f /storage/.config/cacert.pem ] && cat /storage/.config/cacert.pem >>/run/archr/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 0000000000..3bdc2319a0 --- /dev/null +++ b/packages/security/openssl/system.d/openssl-config.service @@ -0,0 +1,12 @@ +[Unit] +Description=OpenSSL configuration service +DefaultDependencies=no +After=systemd-tmpfiles-setup.service + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/usr/bin/openssl-config + +[Install] +WantedBy=sysinit.target diff --git a/packages/sysutils/bkeymaps/package.mk b/packages/sysutils/bkeymaps/package.mk new file mode 100644 index 0000000000..1ba5ceb97c --- /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-init.conf b/packages/sysutils/busybox/config/busybox-init.conf new file mode 100644 index 0000000000..bb92fc0e90 --- /dev/null +++ b/packages/sysutils/busybox/config/busybox-init.conf @@ -0,0 +1,1227 @@ +# +# Automatically generated make config: don't edit +# Busybox version: 1.37.0 +# Fri Sep 27 02:36:50 2024 +# +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_TIME64=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 +CONFIG_STATIC_LIBGCC=y + +# +# 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_SHA1_SMALL=0 +CONFIG_SHA1_HWACCEL=y +CONFIG_SHA256_HWACCEL=y +CONFIG_SHA3_SMALL=0 +# 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_MONOTONIC_SYSCALL is not set +# CONFIG_IOCTL_HEX2STR_ERROR 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_LOOP_CONFIGURE=y +# CONFIG_NO_LOOP_CONFIGURE is not set +# CONFIG_TRY_LOOP_CONFIGURE 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_FEATURE_CPIO_IGNORE_DEVNO is not set +# CONFIG_FEATURE_CPIO_RENUMBER_INODES 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_FEATURE_VERBOSE is not set + +# +# Common options for date and touch +# +# CONFIG_FEATURE_TIMEZONE 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 +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_CRC32 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_FEATURE_CUT_REGEX 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_FEATURE_SKIP_ROOTFS=y +# 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 is not set +# 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 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=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 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=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_TSORT 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_BASE32 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 + +# +# 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 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=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_COLON_EXPAND is not set +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_VI_VERBOSE_STATUS is not set +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_ATIME is not set +# CONFIG_FEATURE_FIND_CTIME is not set +# CONFIG_FEATURE_FIND_MMIN is not set +# CONFIG_FEATURE_FIND_AMIN is not set +# CONFIG_FEATURE_FIND_CMIN 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_SAMEFILE is not set +# CONFIG_FEATURE_FIND_EXEC is not set +# CONFIG_FEATURE_FIND_EXEC_PLUS is not set +# CONFIG_FEATURE_FIND_EXEC_OK 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 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=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_FEATURE_TASKSET_CPULIST 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_EROFS is not set +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_ASCII 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=y +# CONFIG_FLASH_LOCK is not set +# CONFIG_FLASH_UNLOCK is not set +# CONFIG_FLASHCP is not set +# CONFIG_GETFATTR 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_MIM 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_SEEDRNG=y +# CONFIG_SETFATTR is not set +# CONFIG_SETSERIAL is not set +# CONFIG_STRINGS is not set +# CONFIG_TIME is not set +# CONFIG_TREE 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 +# CONFIG_FEATURE_WATCHDOG_OPEN_TWICE 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_ETC_NETWORKS is not set +# CONFIG_FEATURE_ETC_SERVICES is not set +# CONFIG_FEATURE_HWIB 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_PORT_DEFAULT=0 +# 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_FEATURE_HTTPD_ETAG is not set +# CONFIG_FEATURE_HTTPD_LAST_MODIFIED is not set +# CONFIG_FEATURE_HTTPD_DATE is not set +# CONFIG_FEATURE_HTTPD_ACL_IP 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_LINK_CAN 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_PORT_DEFAULT=0 +# 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_FTP 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_BOOTP 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_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_UDHCPC_DEFAULT_INTERFACE="" +# 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_FEATURE_MIME_CHARSET="" +# 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 + +# +# Process Utilities +# +CONFIG_FEATURE_FAST_TOP=y +# CONFIG_FEATURE_SHOW_THREADS is not set +# 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 + +# +# 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_SHELL_ASH=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_SLEEP=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_BASH_SOURCE_CURDIR is not set +# CONFIG_HUSH_LINENO_VAR 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_PRECISE_TIMESTAMPS 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 0000000000..b4a3d93560 --- /dev/null +++ b/packages/sysutils/busybox/config/busybox-target.conf @@ -0,0 +1,1223 @@ +# +# Automatically generated make config: don't edit +# Busybox version: 1.37.0 +# Fri Sep 27 07:30:39 2024 +# +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_TIME64=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 +CONFIG_STATIC_LIBGCC=y + +# +# 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_SHA1_SMALL=0 +CONFIG_SHA1_HWACCEL=y +CONFIG_SHA256_HWACCEL=y +CONFIG_SHA3_SMALL=0 +CONFIG_FEATURE_NON_POSIX_CP=y +CONFIG_FEATURE_VERBOSE_CP_MESSAGE=y +CONFIG_FEATURE_USE_SENDFILE=y +CONFIG_FEATURE_COPYBUF_KB=4 +CONFIG_MONOTONIC_SYSCALL=y +# CONFIG_IOCTL_HEX2STR_ERROR is not set +CONFIG_FEATURE_EDITING=y +CONFIG_FEATURE_EDITING_MAX_LEN=1024 +# CONFIG_FEATURE_EDITING_VI is not set +CONFIG_FEATURE_EDITING_HISTORY=9999 +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_LOOP_CONFIGURE=y +# CONFIG_NO_LOOP_CONFIGURE is not set +# CONFIG_TRY_LOOP_CONFIGURE 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_FEATURE_CPIO_IGNORE_DEVNO=y +CONFIG_FEATURE_CPIO_RENUMBER_INODES=y +# CONFIG_DPKG is not set +# CONFIG_DPKG_DEB is not set +CONFIG_GZIP=y +CONFIG_FEATURE_GZIP_LONG_OPTIONS=y +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=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=y +CONFIG_FEATURE_UNZIP_CDF=y +# 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_FEATURE_VERBOSE=y + +# +# Common options for date and touch +# +CONFIG_FEATURE_TIMEZONE=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 +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_CRC32 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_FEATURE_CUT_REGEX is not set +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_FEATURE_SKIP_ROOTFS=y +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 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=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=y +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_TSORT 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_BASE32 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 + +# +# 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 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=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_COLON_EXPAND is not set +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_VI_VERBOSE_STATUS is not set +CONFIG_FEATURE_ALLOW_EXEC=y + +# +# Finding Utilities +# +CONFIG_FIND=y +CONFIG_FEATURE_FIND_PRINT0=y +CONFIG_FEATURE_FIND_MTIME=y +CONFIG_FEATURE_FIND_ATIME=y +CONFIG_FEATURE_FIND_CTIME=y +CONFIG_FEATURE_FIND_MMIN=y +CONFIG_FEATURE_FIND_AMIN=y +CONFIG_FEATURE_FIND_CMIN=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_SAMEFILE=y +CONFIG_FEATURE_FIND_EXEC=y +CONFIG_FEATURE_FIND_EXEC_PLUS=y +CONFIG_FEATURE_FIND_EXEC_OK=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=y +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 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=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 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=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_FEATURE_TASKSET_CPULIST is not set +CONFIG_UEVENT=y +# 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=y + +# +# Filesystem/Volume identification +# +# CONFIG_FEATURE_VOLUMEID_BCACHE is not set +CONFIG_FEATURE_VOLUMEID_BTRFS=y +CONFIG_FEATURE_VOLUMEID_CRAMFS=y +# CONFIG_FEATURE_VOLUMEID_EROFS is not set +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_ASCII 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=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_GETFATTR 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_MIM 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=y +# CONFIG_RUNLEVEL is not set +# CONFIG_RX is not set +CONFIG_SEEDRNG=y +# CONFIG_SETFATTR is not set +CONFIG_SETSERIAL=y +# CONFIG_STRINGS is not set +CONFIG_TIME=y +# CONFIG_TREE is not set +# 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 +# CONFIG_FEATURE_WATCHDOG_OPEN_TWICE 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_ETC_NETWORKS is not set +# CONFIG_FEATURE_ETC_SERVICES is not set +# CONFIG_FEATURE_HWIB 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 is not set +CONFIG_FEATURE_HTTPD_PORT_DEFAULT=0 +# 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_FEATURE_HTTPD_ETAG is not set +# CONFIG_FEATURE_HTTPD_LAST_MODIFIED is not set +# CONFIG_FEATURE_HTTPD_DATE is not set +# CONFIG_FEATURE_HTTPD_ACL_IP is not set +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_LINK_CAN is not set +CONFIG_FEATURE_IP_ROUTE=y +CONFIG_FEATURE_IP_ROUTE_DIR="/storage/.config/iproute2" +CONFIG_FEATURE_IP_TUNNEL=y +CONFIG_FEATURE_IP_RULE=y +CONFIG_FEATURE_IP_NEIGH=y +# 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_PORT_DEFAULT=0 +# 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=y +CONFIG_FEATURE_WGET_LONG_OPTIONS=y +CONFIG_FEATURE_WGET_STATUSBAR=y +# CONFIG_FEATURE_WGET_FTP is not set +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_BOOTP 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_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_UDHCPC_DEFAULT_INTERFACE="" +# 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_FEATURE_MIME_CHARSET="" +# 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 + +# +# Process Utilities +# +CONFIG_FEATURE_FAST_TOP=y +CONFIG_FEATURE_SHOW_THREADS=y +# 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 + +# +# 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_SHELL_ASH=y +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_SLEEP=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_BASH_SOURCE_CURDIR is not set +# CONFIG_HUSH_LINENO_VAR 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_PRECISE_TIMESTAMPS 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/inputrc b/packages/sysutils/busybox/config/inputrc new file mode 100644 index 0000000000..5253889c39 --- /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 0000000000..faf70f625f --- /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.archr ] ; 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 0000000000..10d1db19be --- /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 0000000000..e69de29bb2 diff --git a/packages/sysutils/busybox/package.mk b/packages/sysutils/busybox/package.mk new file mode 100644 index 0000000000..bddfd0019f --- /dev/null +++ b/packages/sysutils/busybox/package.mk @@ -0,0 +1,208 @@ +# 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="busybox" +PKG_VERSION="1.37.0" +PKG_SHA256="3311dff32e746499f4df0d5df04d7eb396382d7e108bb9250e7b519b837043a4" +PKG_LICENSE="GPL" +PKG_SITE="http://www.busybox.net" +PKG_URL="https://busybox.net/downloads/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain hdparm dosfstools e2fsprogs zip usbutils parted procps-ng libtirpc" +PKG_DEPENDS_INIT="toolchain libtirpc" +PKG_LONGDESC="BusyBox combines tiny versions of many common UNIX utilities into a single small executable." +PKG_BUILD_FLAGS="-parallel" + +# nano text editor +if [ "${NANO_EDITOR}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" nano" +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_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_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+=" -I${SYSROOT_PREFIX}/usr/include/tirpc" + + 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+=" -I${SYSROOT_PREFIX}/usr/include/tirpc" + + LDFLAGS+=" -fwhole-program" + + make oldconfig +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + if [ ${TARGET_ARCH} = x86_64 ]; then + cp ${PKG_DIR}/scripts/getedid ${INSTALL}/usr/bin + else + cp ${PKG_DIR}/scripts/dump-active-edids-drm ${INSTALL}/usr/bin/dump-active-edids + fi + cp ${PKG_DIR}/scripts/create-edid-cpio ${INSTALL}/usr/bin/ + if [ "${PROJECT}" = "RPi" ]; then + cp ${PKG_DIR}/scripts/update-bootloader-edid-rpi ${INSTALL}/usr/bin/update-bootloader-edid + cp ${PKG_DIR}/scripts/getedid-drm ${INSTALL}/usr/bin/getedid + fi + if [ "${PROJECT}" = "Amlogic" ]; then + cp ${PKG_DIR}/scripts/update-bootloader-edid-amlogic ${INSTALL}/usr/bin/getedid + fi + cp ${PKG_DIR}/scripts/createlog ${INSTALL}/usr/bin/ + cp ${PKG_DIR}/scripts/dthelper ${INSTALL}/usr/bin + ln -sf dthelper ${INSTALL}/usr/bin/dtfile + ln -sf dthelper ${INSTALL}/usr/bin/dtflag + ln -sf dthelper ${INSTALL}/usr/bin/dtname + ln -sf dthelper ${INSTALL}/usr/bin/dtsoc + cp ${PKG_DIR}/scripts/ledfix ${INSTALL}/usr/bin + cp ${PKG_DIR}/scripts/lsb_release ${INSTALL}/usr/bin/ + cp ${PKG_DIR}/scripts/apt-get ${INSTALL}/usr/bin/ + cp ${PKG_DIR}/scripts/sudo ${INSTALL}/usr/bin/ + cp ${PKG_DIR}/scripts/pastebinit ${INSTALL}/usr/bin/ + sed -e "s/@DISTRONAME@-@OS_VERSION@/${DISTRONAME}-${OS_VERSION}/g" \ + -i ${INSTALL}/usr/bin/pastebinit + ln -sf pastebinit ${INSTALL}/usr/bin/paste + + mkdir -p ${INSTALL}/usr/sbin + cp ${PKG_DIR}/scripts/kernel-overlays-setup ${INSTALL}/usr/sbin + + mkdir -p ${INSTALL}/usr/lib/archr + cp ${PKG_DIR}/scripts/functions ${INSTALL}/usr/lib/archr + cp ${PKG_DIR}/scripts/fs-resize ${INSTALL}/usr/lib/archr + sed -e "s/@DISTRONAME@/${DISTRONAME}/g" \ + -i ${INSTALL}/usr/lib/archr/fs-resize + + mkdir -p ${INSTALL}/usr/lib/systemd/system-generators/ + cp ${PKG_DIR}/scripts/libreelec-target-generator ${INSTALL}/usr/lib/systemd/system-generators/ + + mkdir -p ${INSTALL}/etc + cp ${PKG_DIR}/config/profile ${INSTALL}/etc + cp ${PKG_DIR}/config/inputrc ${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 +} + +post_install() { + echo "chmod 4755 ${INSTALL}/usr/bin/busybox" >>${FAKEROOT_SCRIPT} + echo "chmod 000 ${INSTALL}/usr/cache/shadow" >>${FAKEROOT_SCRIPT} + + add_user root "${ROOT_PASSWORD}" 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 fs-resize.service + enable_service ledfix.service + enable_service shell.service + enable_service show-version.service + enable_service var.mount + enable_service locale.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 + 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} + sed -e "s/@DISTRONAME@/${DISTRONAME}/g" \ + -e "s/@KERNEL_NAME@/${KERNEL_NAME}/g" \ + -e "s/@SYSTEM_SIZE@/${SYSTEM_SIZE}/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 0000000000..ce454f4c07 --- /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 0000000000..30105bdb18 --- /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 0000000000..ec7354f6d4 --- /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 0000000000..e5dabec86a --- /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 0000000000..b2698c9808 --- /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 0000000000..a8e5c706cf --- /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-90-tls-fix-not-x86-fix-CONFIG_FEATURE_TLS_SHA1-y-CONFIG.patch b/packages/sysutils/busybox/patches/busybox-90-tls-fix-not-x86-fix-CONFIG_FEATURE_TLS_SHA1-y-CONFIG.patch new file mode 100644 index 0000000000..59b0d2d174 --- /dev/null +++ b/packages/sysutils/busybox/patches/busybox-90-tls-fix-not-x86-fix-CONFIG_FEATURE_TLS_SHA1-y-CONFIG.patch @@ -0,0 +1,27 @@ +From ca2cc021326f3f846ead76675c419942633819f2 Mon Sep 17 00:00:00 2001 +From: Rudi Heitbaum +Date: Sun, 29 Sep 2024 17:45:43 +0000 +Subject: [PATCH] tls: fix not x86: fix CONFIG_FEATURE_TLS_SHA1=y + + CONFIG_SHA1_HWACCEL=y + +--- + libbb/hash_md5_sha.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/libbb/hash_md5_sha.c b/libbb/hash_md5_sha.c +index 57a801459..75a61c32c 100644 +--- a/libbb/hash_md5_sha.c ++++ b/libbb/hash_md5_sha.c +@@ -1313,7 +1313,9 @@ unsigned FAST_FUNC sha1_end(sha1_ctx_t *ctx, void *resbuf) + hash_size = 8; + if (ctx->process_block == sha1_process_block64 + #if ENABLE_SHA1_HWACCEL ++# if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) + || ctx->process_block == sha1_process_block64_shaNI ++# endif + #endif + ) { + hash_size = 5; +-- +2.43.0 + diff --git a/packages/sysutils/busybox/profile.d/10-locale.conf b/packages/sysutils/busybox/profile.d/10-locale.conf new file mode 100644 index 0000000000..31540b216c --- /dev/null +++ b/packages/sysutils/busybox/profile.d/10-locale.conf @@ -0,0 +1,5 @@ +# don't overwrite value set by Locale Kodi addon +if [ -z "${LOCPATH}" ]; then + export LANG="C.UTF-8" + export LOCPATH="/storage/.cache/locpath" +fi 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 0000000000..4fe823992c --- /dev/null +++ b/packages/sysutils/busybox/profile.d/98-busybox.conf @@ -0,0 +1,20 @@ +# 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;32m\]\h\[\e[1;32m\]:\[\e[1;34m\]\w \[\e[0m\]\\$ " +export HISTFILESIZE=200 +# k0p +case "$TERM" in + linux|nxterm|screen|xterm|xterm-color|st-256color) + ;; + "") + export TERM="linux" + ;; + *) + export TERM="xterm" + ;; +esac diff --git a/packages/sysutils/busybox/scripts/apt-get b/packages/sysutils/busybox/scripts/apt-get new file mode 100755 index 0000000000..c3c0b3fae6 --- /dev/null +++ b/packages/sysutils/busybox/scripts/apt-get @@ -0,0 +1,26 @@ +#!/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) + +message="$message\n There is no working 'apt-get'." +message="$message\n " +message="$message\n 'apt-get' is a command to install, update and remove software which" +message="$message\n is stored in a non local repo. 'apt-get' does nothing then connecting to such" +message="$message\n repo, downloads the software, unpacks the software, updates a big" +message="$message\n local database with all filepaths and other information about the" +message="$message\n installed software or removes or updates installed Software." +message="$message\n " +message="$message\n With LibreELEC it is not possible to change the system for security and" +message="$message\n stability reasons so even 'apt-get' would not be able to do this." +message="$message\n We also dont have and want to maintain such a repo for various other" +message="$message\n great reasons." +message="$message\n " +message="$message\n Also Ubuntu or Debian packages are often outdated and not compatible" +message="$message\n with LibreELEC" +message="$message\n " +message="$message\n TIP: use Kodi's addon browser to enhance your LibreELEC system" + +echo -e $message +exit 1 diff --git a/packages/sysutils/busybox/scripts/create-edid-cpio b/packages/sysutils/busybox/scripts/create-edid-cpio new file mode 100755 index 0000000000..07177fe6ec --- /dev/null +++ b/packages/sysutils/busybox/scripts/create-edid-cpio @@ -0,0 +1,36 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +EDID_DIR="/storage/.config/firmware/edid" +EDID_CPIO="/flash/edid.cpio" +TMPDIR="/tmp/edid-cpio" + +if [ "$1" = "-q" ]; then + VERBOSE=0 +else + VERBOSE=1 +fi + +if [ ! -d "${EDID_DIR}" ]; then + echo "error: ${EDID_DIR} does not exist" + exit 1 +fi + +set -e + +rm -rf "${TMPDIR}" +mkdir -p "${TMPDIR}/usr/lib/firmware" +cp -r "${EDID_DIR}" "${TMPDIR}/usr/lib/firmware" +cd "${TMPDIR}" +mount -o remount,rw /flash +find usr -print | cpio -ov -H newc >"${EDID_CPIO}" +sync +mount -o remount,ro /flash +cd /storage +rm -rf "${TMPDIR}" + +if [ "${VERBOSE}" = "1" ]; then + echo "successfully created ${EDID_CPIO}" +fi diff --git a/packages/sysutils/busybox/scripts/createlog b/packages/sysutils/busybox/scripts/createlog new file mode 100755 index 0000000000..1b2319e82b --- /dev/null +++ b/packages/sysutils/busybox/scripts/createlog @@ -0,0 +1,184 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2023-present Team LibreELEC (https://libreelec.tv) + +# create logfile + +DATE=$(date -u +%Y-%m-%d-%H.%M.%S) +BASEDIR=$(mktemp -d) +LOGDIR="log-$DATE" +RELEASE=$(cat /etc/release) + +getlog_cmd() { + if command -v $1 >/dev/null; then + { + echo "################################################################################" + echo "# ... output of $@" + echo "# LibreELEC release: $RELEASE" + 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 contain + # login credentials + for i in /storage/.config/system.d/*.service ; do + if [ -f "$i" ] && [ ! -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 -name journal -prune -o -type f -print); 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) +# only exists if using persistent journal + if [ -f "/storage/.cache/journald.conf.d/00_settings.conf" ]; then + LOGFILE="10_Journal-prev.log" + getlog_cmd journalctl --no-pager -b -1 + fi + +# 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/dthelper b/packages/sysutils/busybox/scripts/dthelper new file mode 100755 index 0000000000..a4af0d46c8 --- /dev/null +++ b/packages/sysutils/busybox/scripts/dthelper @@ -0,0 +1,93 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +COMPATIBLE=$(cat /proc/device-tree/compatible 2>/dev/null | tr -d '\000' | sed -n -e 's/.*\(allwinner\|amlogic\|fsl\|nxp\|qcom\|raspberrypi\|rockchip\|samsung\).*/\1/p') + +do_dtfile() { + if [[ -n $(find /flash -name extlinux.conf) ]]; then + EXTLINUX=$(find /flash -name extlinux.conf) + DTFILE=$(grep FDT "${EXTLINUX}" | sed 's,^ *FDT /,,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 + do_unknown + fi + echo "${DTFILE}" +} + +do_dtflag() { + if [ "${COMPATIBLE}" = "raspberrypi" ]; then + DTFLAG=$(cat /proc/device-tree/compatible | cut -f1,2 -d',' | head -n 1) + PIREV=$(awk '/^Revision/ {sub($3,-6, "", $3); print $3}' /proc/cpuinfo) # truncate to 6-chars + case "${PIREV}" in + d*) + MEMSIZE="-8g" + ;; + c*) + MEMSIZE="-4g" + ;; + b*) + MEMSIZE="-2g" + ;; + a*) + MEMSIZE="-1g" + ;; + *0002 | *0003 | *0004 | *0005 | *0006 | *0007 | *0008 | *0009 | *0012) + MEMSIZE="-256" + ;; + 0* | 9*) + MEMSIZE="-512" + ;; + *) + MEMSIZE="" + ;; + esac + else + DTFLAG=$(cat /proc/device-tree/compatible | cut -f1,2 -d',' | head -n 1) + MEMSIZE=$(awk -F " " '/MemTotal:/ {print $2}' /proc/meminfo) + if [ "${MEMSIZE}" -lt "524288" ]; then + MEMSIZE="-512" + else + MEMSIZE="" + fi + fi + echo "${DTFLAG}${MEMSIZE}" +} + +do_dtname() { + DTNAME=$(cat /proc/device-tree/compatible | cut -f1,2 -d',' | head -n 1) + echo "${DTNAME}" +} + +do_dtsoc() { + DTSOC=$(cat /proc/device-tree/compatible | cut -f1,2 -d',' | tail -n 1) + echo "${DTSOC}" +} + +do_unknown() { + echo "unknown" + exit 1 +} + +if [ -n "${COMPATIBLE}" ]; then + case $(basename "${0}") in + dtfile) + do_dtfile + ;; + dtflag) + do_dtflag + ;; + dtname) + do_dtname + ;; + dtsoc) + do_dtsoc + ;; + esac +else + do_unknown +fi diff --git a/packages/sysutils/busybox/scripts/dump-active-edids-drm b/packages/sysutils/busybox/scripts/dump-active-edids-drm new file mode 100755 index 0000000000..7e9cde045f --- /dev/null +++ b/packages/sysutils/busybox/scripts/dump-active-edids-drm @@ -0,0 +1,42 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +EDID_DIR="/storage/.config/firmware/edid" +CONNECTORS="" + +if [ "$1" = "-q" ]; then + VERBOSE=0 +else + VERBOSE=1 +fi + +info() { + [ "${VERBOSE}" = "1" ] && echo "$@" +} + +mkdir -p "${EDID_DIR}" + +for c in /sys/class/drm/card?-*; do + [ ! -d "$c" ] && continue + [ ! -e "$c/status" ] && continue + + if [ $(cat $c/status 2>/dev/null) = "connected" ]; then + CONNECTOR=$(basename $c | cut -c 7-) + EDID_NAME="edid-${CONNECTOR}.bin" + cat $c/edid >"${EDID_DIR}/${EDID_NAME}" 2>/dev/null + if [ $? -eq 0 ]; then + [ -n "${CONNECTORS}" ] && CONNECTORS="${CONNECTORS} " + CONNECTORS="${CONNECTORS}${CONNECTOR}" + fi + fi +done + +if [ -z "${CONNECTORS}" ]; then + info "error: no active connectors found" + exit 1 +else + info "found active connector(s) ${CONNECTORS}" + [ "${VERBOSE}" = "0" ] && echo "${CONNECTORS}" +fi diff --git a/packages/sysutils/busybox/scripts/fs-resize b/packages/sysutils/busybox/scripts/fs-resize new file mode 100755 index 0000000000..b964bb83e1 --- /dev/null +++ b/packages/sysutils/busybox/scripts/fs-resize @@ -0,0 +1,74 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) + +StartProgressLog() { + if [ "$1" = "spinner" ]; then + echo "*** $3" >>$LOG + fi + StartProgress "$@" +} + +if [ -e /storage/.please_resize_me ] ; then + . /usr/lib/archr/functions + + hidecursor + + mount -o remount,rw /flash + LOG=/flash/fs-resize.log + date -Iseconds >>$LOG + + # this sh** was never intended to be used + # on an already installed and running 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." | tee -a $LOG + mount -o remount,ro /flash + StartProgress countdown "Rebooting in 15s... " 15 "NOW" + reboot -f + fi + + # get the disk. /storage on 2nd partition + echo $(grep "/storage " /proc/mounts) >>$LOG + PART=$(grep "/storage " /proc/mounts | cut -d" " -f1 | grep '2$') + + # get disk: /dev/sdx2 -> /dev/sdx, /dev/mmcblkxp2 -> /dev/mmcblkx + case $PART in + "/dev/mmcblk"*|"/dev/nvme"*) + DISK=$(echo $PART | sed s/p2$//g) + ;; + *) + DISK=$(echo $PART | sed s/2$//g) + ;; + esac + + rm -f /storage/.please_resize_me + sync + + LABEL=$(blkid -o value -s LABEL $PART) + UUID=$(blkid -o value -s UUID $PART) + + echo "DISK: $DISK PART: $PART LABEL: $LABEL UUID: $UUID" >>$LOG + + # just in case + if [ ! -z "$DISK" -a ! -z "$PART" -a ! -z "$UUID" ] ; then + umount $PART + + echo "PARTITION RESIZING IN PROGRESS" + echo "" + echo "Please do not reboot or turn off your @DISTRONAME@ device!" + echo "" + + StartProgressLog spinner "Resizing partition... " "parted -s -f -m $DISK resizepart 2 100% >>$LOG 2>&1" + StartProgressLog spinner "Creating file system... " "mke2fs -F -q -t ext4 -T ext4 -m 0 -L \"$LABEL\" -U \"$UUID\" $PART >>$LOG 2>&1" + StartProgressLog spinner "Checking file system... " "e2fsck -f -p $PART >>$LOG 2>&1" + StartProgress countdown "Rebooting in 15s... " 15 "NOW" + else + echo "Partition was not detected - resizing aborted." + StartProgress countdown "Rebooting in 15s... " 15 "NOW" + fi + mount -o remount,ro /flash +fi +reboot -f &>/dev/null diff --git a/packages/sysutils/busybox/scripts/functions b/packages/sysutils/busybox/scripts/functions new file mode 100755 index 0000000000..216c6fb99b --- /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 0000000000..c11171ea61 --- /dev/null +++ b/packages/sysutils/busybox/scripts/getedid @@ -0,0 +1,231 @@ +#!/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 +} + +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 connected: + 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 + + # 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/getedid-drm b/packages/sysutils/busybox/scripts/getedid-drm new file mode 100755 index 0000000000..be66321f05 --- /dev/null +++ b/packages/sysutils/busybox/scripts/getedid-drm @@ -0,0 +1,55 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +usage() { + echo "$0 create|delete|help" +} + +delete_edid() { + update-bootloader-edid delete + if [ $? -eq 0 ]; then + echo "successfully removed edid override" + else + echo "error removing bootloader edid-override options" + exit 1 + fi +} + +create_edid() { + CONNECTORS=$(dump-active-edids -q) + if [ $? -ne 0 -o -z "${CONNECTORS}" ]; then + echo "error: cannot determine active connectors" + exit 1 + fi + create-edid-cpio -q + if [ $? -ne 0 ]; then + echo "error creating edid.cpio" + exit 1 + fi + update-bootloader-edid set ${CONNECTORS} + if [ $? -eq 0 ]; then + echo "successfully installed edid override for ${CONNECTORS}" + else + echo "error setting bootloader edid-override options" + exit 1 + fi +} + +case $1 in + create) + shift + create_edid "$@" + ;; + delete) + delete_edid + ;; + help) + usage + ;; + *) + usage + exit 1 + ;; +esac diff --git a/packages/sysutils/busybox/scripts/init b/packages/sysutils/busybox/scripts/init new file mode 100755 index 0000000000..cf40b4683d --- /dev/null +++ b/packages/sysutils/busybox/scripts/init @@ -0,0 +1,1140 @@ +#!/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-present Team LibreELEC (https://libreelec.tv) + +# 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 +/usr/bin/busybox mkdir -p /run + +# 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 +# /run options have to match what systemd uses by default +/usr/bin/busybox mount -t tmpfs -o mode=755,size=20%,nr_inodes=800k,nosuid,nodev,strictatime tmpfs /run + +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" + +# 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)" +[ -z "$MACHINE_UID" ] && MACHINE_UID="$(cat /sys/class/net/eth0/address 2>/dev/null | tr -d :)" + +# common functions +. /functions + +# script functions +progress() { + if test "$PROGRESS" = "yes"; then + echo "### $1 ###" >&2 + fi +} + +debug_msg() { + echo "$1" >&$SILENT_OUT +} + +debug_shell() { + 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_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" + ;; + *) + 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 [ -n "$root" ]; then + # ext4 root: mount root partition directly (read-write) + mount_part "$root" "/sysroot" "rw,noatime" + elif [ "$SYSTEM_TORAM" = "yes" ]; then + cp "/flash/$IMAGE_SYSTEM" /dev/SYSTEM + mount_part "/dev/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 "${DISTRO_ARCH}" + 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 +} + +update_file() { + if [ -f "$UPDATE_DIR/$2" -a -f "$3" ]; then + mount -o remount,rw /flash + + rm -f "$3" + 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" + 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 + StartProgress spinner "Updating Boot Files... " + result="$(sh $SYSTEM_ROOT/usr/share/bootloader/update.sh 2>&1)" + sync + StopProgress "done" + [ -n "${result}" ] && echo "${result}" + fi +} + +load_splash() { + local set_default_res=no + local vres + + if [ ! "$SPLASH" = "no" ]; then + progress "Loading bootsplash" + + 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 + 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 }')" + + for s in /flash/oemsplash-${vres}.png \ + /flash/oemsplash-1080.png \ + /flash/oemsplash.png \ + /splash/splash-${vres}.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..." + + # syncing filesystem + sync + + # unmount filesystems + if /usr/bin/busybox mountpoint -q /flash ; then + /usr/bin/busybox umount /flash + fi + + if /usr/bin/busybox mountpoint -q /storage ; then + /usr/bin/busybox umount /storage + 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 + + # 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 +} + +# 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; 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; 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 unnecessary 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 /update; then + umount /update + 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 + 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/.tmp &>/dev/null + rm -rf $UPDATE_ROOT/[0-9a-zA-Z]* &>/dev/null + rm -f $UPDATE_ROOT/.nocheck $UPDATE_ROOT/.nocompat &>/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 + + if [ "$UPDATE_DISABLED" = "yes" ]; then + echo "Updating is not supported on netboot" + do_cleanup + StartProgress countdown "Normal startup in 10s... " 10 "NOW" + return 0 + fi + + if [ -d $UPDATE_DIR/.tmp ]; then + echo "Failed update detected - performing recovery." + echo "" + do_cleanup + StartProgress countdown "Normal startup in 10s... " 10 "NOW" + return 0 + fi + + mkdir -p $UPDATE_DIR/.tmp &>/dev/null + sync + + 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 10s... " 10 "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 @SYSTEM_SIZE@MB in size." + echo "" + do_cleanup + StartProgress countdown "Normal startup in 60s... " 60 "NOW" + return 0 + fi + + # all ok, update + if [ -b "/$IMAGE_KERNEL" ]; then + update_partition "Kernel " "${UPDATE_KERNEL}" "/${IMAGE_KERNEL}" + update_partition "Kernel md5" "${UPDATE_KERNEL}.md5" "/${IMAGE_KERNEL}.md5" + else + update_file "Kernel " "${UPDATE_KERNEL}" "/flash/${IMAGE_KERNEL}" + update_file "Kernel md5" "${UPDATE_KERNEL}.md5" "/flash/${IMAGE_KERNEL}.md5" + fi + + umount /sysroot + update_file "System " "${UPDATE_SYSTEM}" "/flash/${IMAGE_SYSTEM}" + update_file "System md5" "${UPDATE_KERNEL}.md5" "/flash/${IMAGE_SYSTEM}.md5" + update_bootloader + do_cleanup + 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!" +} + +# Do init tasks to bring up system + +# hide kernel log messages on console +echo '1 4 1 7' > /proc/sys/kernel/printk + +# run platform_init script if exists +if [ -f "./platform_init" ]; then + ./platform_init +fi + +# clear screen and hide cursor +clear +hidecursor + +# 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" + ;; + esac + ;; + disk=*) + disk="${arg#*=}" + case $disk in + ISCSI=*|NBD=*|NFS=*) + STORAGE_NETBOOT=yes + ;; + /dev/*|LABEL=*|UUID=*) + RUN_FSCK_DISKS="$RUN_FSCK_DISKS $disk" + ;; + esac + ;; + root=*) + root="${arg#*=}" + case $root in + /dev/*|LABEL=*|UUID=*) + RUN_FSCK_DISKS="$RUN_FSCK_DISKS $root" + ;; + esac + ;; + wol_mac=*) + wol_mac="${arg#*=}" + ;; + wol_wait=*) + wol_wait="${arg#*=}" + ;; + installer) + SYSLINUX_DEFAULT="installer" + ;; + debugging) + DEBUG=yes + ;; + 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#*=}" + ;; + ip=*) + KERNEL_IPCONFIG="yes" + ;; + esac +done + +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 | 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 \ + check_disks \ + mount_flash \ + cleanup_flash \ + update_bootmenu \ + load_splash \ + mount_sysroot \ + mount_storage \ + check_update \ + prepare_sysroot; 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 " | awk '{print $1}' | awk -F '/' '{print $3}') +FLASH=$(cat /proc/mounts | grep " /sysroot/flash " | 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 mount --move /run /sysroot/run +/usr/bin/busybox rm -fr /tmp + +# setup kernel overlays +/usr/bin/busybox chroot /sysroot /usr/sbin/kernel-overlays-setup + +# 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 + +# switch to new sysroot and start real init +exec /usr/bin/busybox switch_root /sysroot /usr/lib/systemd/systemd $INIT_ARGS + +error "switch_root" "Error in initramfs. Could not switch to new root" diff --git a/packages/sysutils/busybox/scripts/kernel-overlays-setup b/packages/sysutils/busybox/scripts/kernel-overlays-setup new file mode 100755 index 0000000000..3d03414a73 --- /dev/null +++ b/packages/sysutils/busybox/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) +RUNTIME_DIR="/run/kernel-overlays" +MODULES_DIR="${RUNTIME_DIR}/modules/${KVER}" +FIRMWARE_DIR="${RUNTIME_DIR}/firmware" +USER_FIRMWARE_DIR="/storage/.config/firmware" + +mkdir -p "${MODULES_DIR}" +mkdir -p "${FIRMWARE_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 >/dev/kmsg 2>&1 + 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/busybox/scripts/ledfix b/packages/sysutils/busybox/scripts/ledfix new file mode 100755 index 0000000000..def286c9b0 --- /dev/null +++ b/packages/sysutils/busybox/scripts/ledfix @@ -0,0 +1,16 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2020-present Team LibreELEC (https://libreelec.tv) + +# find heartbeat triggers and set them to none +case $(dtsoc) in + amlogic*) + for triggerfile in $(find /sys/devices/platform/leds -name trigger); do + trigger=$(awk -F'[][]' '{print $2}' "$triggerfile") + if [ "$trigger" = "heartbeat" ]; then + echo "none" >"$triggerfile" + fi + done + ;; +esac diff --git a/packages/sysutils/busybox/scripts/libreelec-target-generator b/packages/sysutils/busybox/scripts/libreelec-target-generator new file mode 100755 index 0000000000..4a54c35f08 --- /dev/null +++ b/packages/sysutils/busybox/scripts/libreelec-target-generator @@ -0,0 +1,47 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Matthias Reichl +# Copyright (C) 2020-present Team LibreELEC (https://libreelec.tv) + +EARLY_DIR="$2" + +log() { + echo "libreelec-target-generator: $@" >/dev/kmsg +} + +if [ -z "$EARLY_DIR" ]; then + log "error: generator directory missing" + exit 1 +fi + +TARGET="" + +for arg in $(cat /proc/cmdline); do + case "$arg" in + textmode) + TARGET="textmode.target" + ;; + installer) + TARGET="installer.target" + ;; + esac +done + +BACKUP_EXTENSION_LIST=".tar .tar.gz .tar.bz2 .tar.xz" +for extension in $BACKUP_EXTENSION_LIST; do + BACKUP_FILE=$(ls -1 /storage/.restore/*${EXTENSION} 2>/dev/null | head -n 1) + [ -n "${BACKUP_FILE}" ] && break +done + +if [ -f /storage/.please_resize_me ]; then + TARGET="fs-resize.target" +elif [ -f /storage/.cache/reset_hard -o -f /storage/.cache/reset_soft ]; then + TARGET="factory-reset.target" +elif [ -f "$BACKUP_FILE" ]; then + TARGET="backup-restore.target" +fi + +if [ -n "$TARGET" ]; then + ln -sT "/usr/lib/systemd/system/$TARGET" "$EARLY_DIR/default.target" 2>/dev/kmsg || log "error creating symlink to $TARGET: $?" +fi diff --git a/packages/sysutils/busybox/scripts/lsb_release b/packages/sysutils/busybox/scripts/lsb_release new file mode 100755 index 0000000000..54e880e9f9 --- /dev/null +++ b/packages/sysutils/busybox/scripts/lsb_release @@ -0,0 +1,8 @@ +#!/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 +echo "$PRETTY_NAME" diff --git a/packages/sysutils/busybox/scripts/pastebinit b/packages/sysutils/busybox/scripts/pastebinit new file mode 100755 index 0000000000..3824aa6552 --- /dev/null +++ b/packages/sysutils/busybox/scripts/pastebinit @@ -0,0 +1,9 @@ +#!/bin/sh + +# 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) + +token=$(echo "@DISTRONAME@-@OS_VERSION@" | sha256sum | cut -d ' ' -f 1) + +cat "$@" | curl https://paste.libreelec.tv -F 'file=@-' -H "Authorization: Bearer ${token}" diff --git a/packages/sysutils/busybox/scripts/sudo b/packages/sysutils/busybox/scripts/sudo new file mode 100755 index 0000000000..42244a8959 --- /dev/null +++ b/packages/sysutils/busybox/scripts/sudo @@ -0,0 +1,12 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2025-present Team LibreELEC (https://libreelec.tv) + +message="$message\n You are 'root' so 'sudo' is not required or supported" +message="$message\n " + +echo -e $message + +exit 1 diff --git a/packages/sysutils/busybox/scripts/update-bootloader-edid-amlogic b/packages/sysutils/busybox/scripts/update-bootloader-edid-amlogic new file mode 100755 index 0000000000..5054c60e02 --- /dev/null +++ b/packages/sysutils/busybox/scripts/update-bootloader-edid-amlogic @@ -0,0 +1,89 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present Team LibreELEC (https://libreelec.tv) + +do_install() { + # create the persistent firmware dir + mkdir -p "/storage/.config/firmware/edid" + + # capture the raw edid file + if [ ! -e /storage/.config/firmware/edid/edid.bin ]; then + cat "/sys/class/drm/card0-HDMI-A-1/edid" >"/storage/.config/firmware/edid/edid.bin" + else + echo "info: using existing edid.bin" + fi + + # create the cpio file + mkdir -p "/storage/cpio/lib/firmware/edid" + cp "/storage/.config/firmware/edid/edid.bin" "/storage/cpio/lib/firmware/edid/" + cd "/storage/cpio" + find . -print | cpio -ov -H newc >"/storage/.config/firmware/edid/edid.cpio" + + # mount /flash rw + mount -o remount,rw /flash + + # copy the cpio file + cp "/storage/.config/firmware/edid/edid.cpio" "/flash/edid.cpio" + + # cleanup cpio dir + rm -rf "/storage/cpio" + + # determine boot method and set params + if [ -f "/flash/extlinux/extlinux.conf" ]; then + FILE="/flash/extlinux/extlinux.conf" + if grep -q "initrd=/edid.cpio" "${FILE}"; then + echo "error: ${FILE} already contains edid.cpio, aborting!" + exit 1 + else + cp "${FILE}" "${FILE}.backup" + sed -i "/ APPEND/s/$/ drm.edid_firmware=edid\/edid.bin video=HDMI-A-1:D/" "${FILE}" + echo "info: edid setup complete!" + exit 0 + fi + else + FILE="/flash/uEnv.ini" + if grep -q "initrd=/edid.cpio" "${FILE}"; then + echo "error: ${FILE} already contains edid.cpio info .. aborting!" + exit 1 + else + cp "${FILE}" "${FILE}.backup" + sed -i "/ bootargs/s/$/ drm.edid_firmware=edid\/edid.bin video=HDMI-A-1:D/" "${FILE}" + echo "info: edid setup complete!" + exit 0 + fi + fi +} + +do_cleanup() { + rm "/storage/.config/firmware/edid/edid.bin" + rm "/storage/.config/firmware/edid/edid.cpio" + mount -o remount,rw /flash + rm "/flash/edid.cpio" + if [ -f "/flash/extlinux/extlinux.conf" ]; then + FILE="/flash/extlinux/extlinux.conf" + else + FILE="/flash/uEnv.ini" + fi + cp "${FILE}.backup" "${FILE}" + mount -o remount,ro /flash +} + +do_usage() { + echo "usage: getedid {create|delete}" + exit 0 +} + +case $1 in + create) + do_install + ;; + delete) + do_cleanup + ;; + *) + do_usage + ;; +esac + +exit diff --git a/packages/sysutils/busybox/scripts/update-bootloader-edid-rpi b/packages/sysutils/busybox/scripts/update-bootloader-edid-rpi new file mode 100755 index 0000000000..0ca946a639 --- /dev/null +++ b/packages/sysutils/busybox/scripts/update-bootloader-edid-rpi @@ -0,0 +1,95 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +EDID_DIR="/storage/.config/firmware/edid" +EDID_CPIO="/flash/edid.cpio" +CONFIG_TXT="/flash/config.txt" +CMDLINE_TXT="/flash/cmdline.txt" + +usage() { + echo "$0 set CONNECTOR... | delete | help" +} + +check_args() { + if [ $# -eq 0 ]; then + echo "error: no connector(s) specified!" + exit 1 + fi + if [ ! -f "${EDID_CPIO}" ]; then + echo "error: ${EDID_CPIO} not present" + exit 1 + fi + for conn in "$@"; do + if [ ! -f "${EDID_DIR}/edid-${conn}.bin" ]; then + echo "error: ${EDID_DIR}/edid-${conn}.bin not present" + exit 1 + fi + done +} + +cleanup_config_txt() { + sed -i "/^initramfs edid\.cpio/d" ${CONFIG_TXT} +} + +get_cleaned_cmdline_txt() { + sed \ + -e 's| drm\.edid_firmware=[^ ]*||g' \ + -e 's| video=[^ ]*||g' \ + ${CMDLINE_TXT} +} + +add_initramfs() { + # make sure config.txt ends with a newline + if [ "$(tail -c 1 ${CONFIG_TXT} | tr -c -d '\n' | tr '\n' 'X')" != "X" ]; then + echo "" >>${CONFIG_TXT} + fi + echo "initramfs edid.cpio" >>${CONFIG_TXT} +} + +add_cmdline() { + CMDLINE=$(get_cleaned_cmdline_txt) + FIRMWARE="" + VIDEO="" + for conn in "$@"; do + VIDEO="${VIDEO} video=${conn}:D" + [ -n "${FIRMWARE}" ] && FIRMWARE="${FIRMWARE}," + FIRMWARE="${FIRMWARE}${conn}:edid/edid-${conn}.bin" + done + echo "${CMDLINE} drm.edid_firmware=${FIRMWARE}${VIDEO}" >${CMDLINE_TXT} +} + +set_edids() { + check_args "$@" + mount -o remount,rw /flash + cleanup_config_txt + add_initramfs + add_cmdline "$@" + mount -o remount,ro /flash +} + +delete_edids() { + mount -o remount,rw /flash + cleanup_config_txt + CMDLINE=$(get_cleaned_cmdline_txt) + echo "${CMDLINE}" >${CMDLINE_TXT} + mount -o remount,ro /flash +} + +case $1 in + set) + shift + set_edids "$@" + ;; + delete) + delete_edids + ;; + help) + usage + ;; + *) + usage + exit 1 + ;; +esac 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 0000000000..76e7b2a8cb --- /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/archr/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/archr/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/archr/suspend + mkdir -p /run/archr/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 0000000000..aa33f5f593 --- /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 0000000000..a9c22348a5 --- /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 0000000000..b2ccb5ba4a --- /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 0000000000..fdd14e95bd --- /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 0000000000..0cf6a1e8c6 --- /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 0000000000..673275f9ad --- /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/archr/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 0000000000..838c57c293 --- /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/ledfix.service b/packages/sysutils/busybox/system.d/ledfix.service new file mode 100644 index 0000000000..dade743d04 --- /dev/null +++ b/packages/sysutils/busybox/system.d/ledfix.service @@ -0,0 +1,12 @@ +[Unit] +Description=LEDfix Service +After=network-online.target + +[Service] +Type=oneshot +ExecStart=/bin/sh /usr/bin/ledfix +RemainAfterExit=yes +StartLimitInterval=0 + +[Install] +WantedBy=multi-user.target diff --git a/packages/sysutils/busybox/system.d/locale.service b/packages/sysutils/busybox/system.d/locale.service new file mode 100644 index 0000000000..689109ae63 --- /dev/null +++ b/packages/sysutils/busybox/system.d/locale.service @@ -0,0 +1,17 @@ +[Unit] +Description=Compile locale definition files +ConditionPathExists=!/storage/.cache/locpath +ConditionPathExists=!/storage/.kodi/addons/service.locale/locpath +Before=kodi.service + +[Service] +Type=oneshot +Environment=HOME=/storage +Environment=I18NPATH=/usr/share/i18n +ExecStartPre=/bin/mkdir /storage/.cache/locpath +ExecStart=/usr/bin/localedef --quiet -i POSIX -f UTF-8 /storage/.cache/locpath/C.UTF-8 +SuccessExitStatus=0 1 +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/packages/sysutils/busybox/system.d/shell.service b/packages/sysutils/busybox/system.d/shell.service new file mode 100644 index 0000000000..7b2a0da78b --- /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 0000000000..cc29cbad96 --- /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 0000000000..deb6f6a1c2 --- /dev/null +++ b/packages/sysutils/busybox/system.d/storage-log.service @@ -0,0 +1,10 @@ +[Unit] +Description=Create Persistent Log Directory on /storage and rotate large logs +DefaultDependencies=no +RequiresMountsFor=/storage + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/bin/mkdir -p /storage/.cache/log/journal /storage/.cache/journald.conf.d ; \ +/usr/bin/find /storage/.cache/log/ -maxdepth 1 -type f -size +512k ! -name '*.old' -exec mv {} {}.old \; diff --git a/packages/sysutils/busybox/system.d/textmode.target b/packages/sysutils/busybox/system.d/textmode.target new file mode 100644 index 0000000000..dad887acab --- /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 0000000000..a6c7ece004 --- /dev/null +++ b/packages/sysutils/busybox/system.d/var-log.mount @@ -0,0 +1,15 @@ +[Unit] +Description=Persistent Log Storage +RequiresMountsFor=/var /storage +Requires=storage-log.service +After=storage-log.service +DefaultDependencies=no +ConditionKernelCommandLine=!installer +ConditionKernelCommandLine=|debugging +ConditionPathExists=|/storage/.cache/debug.archr +ConditionPathExists=|/storage/.cache/journald.conf.d/00_settings.conf + +[Mount] +What=/storage/.cache/log +Where=/var/log +Options=bind diff --git a/packages/sysutils/busybox/system.d/var.mount b/packages/sysutils/busybox/system.d/var.mount new file mode 100644 index 0000000000..1eea76fa0d --- /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 0000000000..8bde38a420 --- /dev/null +++ b/packages/sysutils/busybox/tmpfiles.d/z_01_busybox.conf @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2023-present Team LibreELEC (https://libreelec.tv) + +d /var/media 0755 root root - - + +d /storage/backup 0755 root root - - +d /storage/logfiles 0755 root root - - +d /storage/.update 0755 root root - - +d /storage/.cache/cores 0755 root root - - +d /storage/.cache/kernel-overlays 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 0000000000..bc9788fbe4 --- /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.16.2" +PKG_SHA256="0ba2a1a4b16afe7bceb2c07e9ce99a8c2c3508e5dec290dbb643384bd6beb7e2" +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="meson:host gcc:host expat systemd" +PKG_LONGDESC="D-Bus is a message bus, used for sending messages between applications." + +PKG_MESON_OPTS_TARGET="--libexecdir=/usr/lib/dbus \ + -Dverbose_mode=false \ + -Dapparmor=disabled \ + -Dasserts=false \ + -Dchecks=true \ + -Dintrusive_tests=false \ + -Dinstalled_tests=false \ + -Dmodular_tests=disabled \ + -Dxml_docs=disabled \ + -Ddoxygen_docs=disabled \ + -Dducktype_docs=disabled \ + -Dx11_autolaunch=disabled \ + -Dselinux=disabled \ + -Dlibaudit=disabled \ + -Dsystemd=enabled \ + -Duser_session=false \ + -Dinotify=enabled \ + -Dvalgrind=disabled \ + -Ddbus_user=dbus \ + -Druntime_dir=/run \ + -Dsystem_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/dosfstools/package.mk b/packages/sysutils/dosfstools/package.mk new file mode 100644 index 0000000000..d52e719a2c --- /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.2" +PKG_SHA256="64926eebf90092dca21b14259a5301b7b98e7b1943e8a201c7d726084809b527" +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.gz" +PKG_DEPENDS_HOST="autotools:host" +PKG_DEPENDS_TARGET="autotools:host gcc:host" +PKG_DEPENDS_INIT="autotools:host gcc:host" +PKG_LONGDESC="dosfstools contains utilities for making and checking MS-DOS FAT filesystems." +PKG_BUILD_FLAGS="-cfg-libs -cfg-libs:host -cfg-libs:init" + +PKG_CONFIGURE_OPTS_TARGET="--enable-compat-symlinks" +PKG_MAKE_OPTS_TARGET="PREFIX=/usr" +PKG_MAKEINSTALL_OPTS_TARGET="PREFIX=/usr" + +PKG_CONFIGURE_OPTS_INIT="--enable-compat-symlinks --without-iconv" +PKG_MAKE_OPTS_INIT="PREFIX=/usr" + +makeinstall_init() { + mkdir -p ${INSTALL}/usr/sbin + cp -P src/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 0000000000..2fe329dc55 --- /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/e2fsprogs/package.mk b/packages/sysutils/e2fsprogs/package.mk new file mode 100644 index 0000000000..9d8884199c --- /dev/null +++ b/packages/sysutils/e2fsprogs/package.mk @@ -0,0 +1,118 @@ +# 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.47.3" +PKG_SHA256="857e6ef800feaa2bb4578fbc810214be5d3c88b072ea53c5384733a965737329" +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="autotools:host" +PKG_DEPENDS_TARGET="autotools:host gcc:host" +PKG_DEPENDS_INIT="autotools:host gcc:host" +PKG_LONGDESC="The filesystem utilities for the EXT2 filesystem, including e2fsck, mke2fs, dumpe2fs, fsck, and others." +PKG_BUILD_FLAGS="-parallel -cfg-libs -cfg-libs:host -cfg-libs:init" + +PKG_CONFIGURE_OPTS_HOST="--prefix=${TOOLCHAIN}/ \ + --bindir=${TOOLCHAIN}/bin \ + --sbindir=${TOOLCHAIN}/sbin \ + --disable-debugfs \ + --disable-defrag \ + --disable-e2initrd-helper \ + --disable-fsck \ + --disable-fuse2fs \ + --disable-imager \ + --disable-nls \ + --disable-resizer \ + --disable-rpath \ + --disable-subset \ + --disable-symlink-build \ + --disable-symlink-install \ + --enable-tls \ + --disable-uuidd \ + --enable-verbose-makecmds \ + --with-crond-dir=no \ + --with-gnu-ld \ + --without-pthread \ + --with-systemd-unit-dir=no \ + --with-udev-rules-dir=no" + +post_unpack() { + # Increase minimal inode size to avoid: + # "ext4 filesystem being mounted at xxx supports timestamps until 2038 (0x7fffffff)" + sed -i 's/inode_size = 128/inode_size = 256/g' ${PKG_BUILD}/misc/mke2fs.conf.in +} + +pre_configure() { + PKG_CONFIGURE_OPTS_INIT="BUILD_CC=${HOST_CC} \ + --disable-blkid-debug \ + --disable-bsd-shlibs \ + --disable-debugfs \ + --disable-e2initrd-helper \ + --disable-elf-shlibs \ + --enable-fsck \ + --disable-fuse2fs \ + --disable-imager \ + --disable-jbd-debug \ + --enable-libblkid \ + --enable-libuuid \ + --disable-nls \ + --disable-profile \ + --enable-resizer \ + --disable-rpath \ + --disable-subset \ + --enable-symlink-build \ + --enable-symlink-install \ + --disable-testio-debug \ + --enable-tls \ + --disable-uuidd \ + --enable-verbose-makecmds \ + --with-crond-dir=no \ + --with-gnu-ld \ + --without-pthread \ + --with-systemd-unit-dir=no \ + --with-udev-rules-dir=no" + + 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/e2mmpstatus + 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 + + 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 + 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 +} diff --git a/packages/sysutils/entropy/package.mk b/packages/sysutils/entropy/package.mk new file mode 100644 index 0000000000..defaecba16 --- /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="" +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 0000000000..e3af8fab48 --- /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 0000000000..967712e5a6 --- /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 0000000000..ddfb1bec31 --- /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 0000000000..61ab2f7243 --- /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 0000000000..9bfa0d71a4 --- /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 0000000000..b93546a715 --- /dev/null +++ b/packages/sysutils/ethmactool/scripts/ethmactool-config @@ -0,0 +1,83 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +case $DTNAME in + radxa,zero*) + echo "Skipping configuration, eth0 not detected" + exit 0 + ;; +esac + +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/secure-monitor/serial ]; then + MAC=$(cat /sys/bus/platform/devices/secure-monitor/serial 2>/dev/null | cut -b-12) + fixup_self_mac + elif [ -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/archr/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 0000000000..9bf83f99c4 --- /dev/null +++ b/packages/sysutils/ethmactool/system.d/ethmactool-config.service @@ -0,0 +1,12 @@ +[Unit] +Description=Configure eth0 MAC address +Requisite=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 0000000000..6da7459e54 --- /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 0000000000..a1eaeaf53b --- /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 0000000000..bb6da67c64 --- /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 0000000000..fcd08f468d --- /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 0000000000..9cb59bbfe2 --- /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 0000000000..ac672550a8 --- /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 0000000000..f46f570575 --- /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 Kodi + KEY_COMPOSE = KEY_EPG # More, remapped to Context Menu in Kodi + 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 0000000000..484df5657e --- /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 0000000000..9a8973638c --- /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 0000000000..2d67c32045 --- /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 Kodi's context menu) + KEY_K = KEY_EPG # Title (used for Kodi'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 0000000000..9358a9f625 --- /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 0000000000..f97c6130c9 --- /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 0000000000..eb8ec8373e --- /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/aftvsremote.evmap b/packages/sysutils/eventlircd/evmap/aftvsremote.evmap new file mode 100644 index 0000000000..917781622d --- /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 0000000000..9a4cc17854 --- /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 0000000000..86f5fb7ae3 --- /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 0000000000..1e502ed1da --- /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 0000000000..c453edacb9 --- /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/ps3remote.evmap b/packages/sysutils/eventlircd/evmap/ps3remote.evmap new file mode 100644 index 0000000000..bc391f5e8d --- /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/skyqremote.evmap b/packages/sysutils/eventlircd/evmap/skyqremote.evmap new file mode 100644 index 0000000000..9dbae115c3 --- /dev/null +++ b/packages/sysutils/eventlircd/evmap/skyqremote.evmap @@ -0,0 +1,25 @@ +# SKY Q bluetooth remote +# Bus=0005 Vendor=119b Product=212b Version=0001 +# Name="P218ruwido Sky Remote Keyboard" + +KEY_ESC = KEY_EXIT +KEY_HOME = KEY_MEDIA +KEY_F5 = KEY_MENU +KEY_F10 = KEY_REWIND +KEY_F11 = KEY_PLAY +KEY_F12 = KEY_FASTFORWARD +KEY_F1 = KEY_POWER +KEY_F3 = KEY_STOP +KEY_KPASTERISK = KEY_MUTE +KEY_F9 = KEY_INFO +KEY_PAGEUP = KEY_CHANNELUP +KEY_PAGEDOWN = KEY_CHANNELDOWN +KEY_F15 = KEY_TUNER +KEY_F2 = KEY_EPG +KEY_KPPLUS = KEY_VOLUMEUP +KEY_KPMINUS = KEY_VOLUMEDOWN +KEY_F4 = KEY_RED +KEY_DELETE = KEY_GREEN +KEY_INSERT = KEY_YELLOW +KEY_END = KEY_BLUE +KEY_F7 = KEY_RECORD diff --git a/packages/sysutils/eventlircd/evmap/spinelplus.evmap b/packages/sysutils/eventlircd/evmap/spinelplus.evmap new file mode 100644 index 0000000000..de59d094e5 --- /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 0000000000..35bc514b59 --- /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 0000000000..244a1296bd --- /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 0000000000..16d1999684 --- /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 0000000000..03b7014098 --- /dev/null +++ b/packages/sysutils/eventlircd/evmap/xiaomibtremote.evmap @@ -0,0 +1,4 @@ +KEY_POWER = KEY_MUTE +KEY_F5 = KEY_PLAYPAUSE +KEY_HOME = KEY_EPG +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 0000000000..4599b53859 --- /dev/null +++ b/packages/sysutils/eventlircd/evmap/xiaomibtremoteAM.evmap @@ -0,0 +1,3 @@ +KEY_POWER = KEY_MUTE +KEY_COMPOSE = KEY_STOPCD +KEY_BACK = KEY_EXIT diff --git a/packages/sysutils/eventlircd/package.mk b/packages/sysutils/eventlircd/package.mk new file mode 100644 index 0000000000..bef801e727 --- /dev/null +++ b/packages/sysutils/eventlircd/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="eventlircd" +PKG_VERSION="8f20b3196bf7085b6c90d86f1602fb29e3965cbc" +PKG_SHA256="029ad9eb554bdfd65fe285c9bef9f5eea7c3b0d97a84dd99a2eb65f80c1848fe" +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_BUILD_FLAGS="-cfg-libs" + +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 0000000000..15b6078315 --- /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 0000000000..be3a0035de --- /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 0000000000..340de71f96 --- /dev/null +++ b/packages/sysutils/eventlircd/udev.d/98-eventlircd.rules @@ -0,0 +1,220 @@ +################################################################################ +# An example udev rules file for eventlircd. +# +# This rules file does not start eventlircd. Many applications only check for +# the lircd socket at application launch. 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" + +SUBSYSTEMS=="input", ATTRS{name}=="*ruwido Sky Remote Keyboard", \ + ENV{eventlircd_enable}="true", \ + ENV{eventlircd_evmap}="skyqremote.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}=="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" + +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" + +# 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=="input", ATTRS{name}=="Nintendo Wii Remote", \ + ENV{eventlircd_enable}="true", \ + ENV{eventlircd_evmap}="wiimote.evmap" + +SUBSYSTEMS=="input", 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) +SUBSYSTEMS=="input", ATTRS{name}=="Sony Computer Entertainment Inc BD Remote Control", \ + ENV{eventlircd_enable}="true", \ + ENV{eventlircd_evmap}="ps3remote.evmap" + +# Amazon Fire TV stick remote +SUBSYSTEMS=="input", ATTRS{name}=="Amazon Fire TV Remote", \ + ENV{eventlircd_enable}="true", \ + ENV{eventlircd_evmap}="aftvsremote.evmap" + +# tell libinput to ignore devices handled by eventlircd +ENV{eventlircd_enable}=="true", ENV{LIBINPUT_IGNORE_DEVICE}="1" + +LABEL="end" diff --git a/packages/sysutils/evrepeat/package.mk b/packages/sysutils/evrepeat/package.mk new file mode 100644 index 0000000000..0a36ef5548 --- /dev/null +++ b/packages/sysutils/evrepeat/package.mk @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="evrepeat" +PKG_VERSION="0.0.1" +PKG_SHA256="f1d14a12d700b9650562f8ec8ca593e6033f2e18b3d1fd1f44af29875152547e" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/HiassofT/evrepeat" +PKG_URL="https://github.com/HiassofT/evrepeat/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Tool to view and change linux input device repeat settings" diff --git a/packages/sysutils/evrepeat/udev.d/70-input-repeat.rules b/packages/sysutils/evrepeat/udev.d/70-input-repeat.rules new file mode 100644 index 0000000000..58fb1386da --- /dev/null +++ b/packages/sysutils/evrepeat/udev.d/70-input-repeat.rules @@ -0,0 +1,14 @@ +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/evrepeat -d 500 $devnode" + +LABEL="end" diff --git a/packages/sysutils/exfatprogs/package.mk b/packages/sysutils/exfatprogs/package.mk new file mode 100644 index 0000000000..d3595cd2c5 --- /dev/null +++ b/packages/sysutils/exfatprogs/package.mk @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="exfatprogs" +PKG_VERSION="1.2.9" +PKG_SHA256="d9a42197c6ff9e6a8e923789413008e317415cf7a4ab85c486c5ffcaf49ca175" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/exfatprogs/exfatprogs" +PKG_URL="https://github.com/exfatprogs/exfatprogs/releases/download/${PKG_VERSION}/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="userspace utilities that contain all of the standard utilities for creating and fixing and debugging exfat filesystems." +PKG_TOOLCHAIN="autotools" + +post_makeinstall_target() { + rm -rf ${INSTALL}/usr/share +} diff --git a/packages/sysutils/fuse/package.mk b/packages/sysutils/fuse/package.mk new file mode 100644 index 0000000000..9b0ea4c685 --- /dev/null +++ b/packages/sysutils/fuse/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="fuse" +PKG_VERSION="5a43d0f724c56f8836f3f92411e0de1b5f82db32" # 2.9.9+ +PKG_SHA256="1df88a204e1673e29112f1ee4efe6b3cd4de2ae78945838e406ead0fe24ec5f1" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/libfuse/libfuse/" +PKG_URL="https://github.com/libfuse/libfuse/archive/${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." +PKG_TOOLCHAIN="autotools" + +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 0000000000..050d1146a9 --- /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 0000000000..66eabe3a25 --- /dev/null +++ b/packages/sysutils/fuse/patches/fuse-0002-dont-run-update-rc.d.patch @@ -0,0 +1,13 @@ +--- a/util/Makefile.am 2017-06-23 22:47:36.762827097 +0200 ++++ b/util/Makefile.am 2017-06-23 22:47:47.358852950 +0200 +@@ -39,10 +39,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/fuse/patches/fuse-0003-fix-configure-ac.patch b/packages/sysutils/fuse/patches/fuse-0003-fix-configure-ac.patch new file mode 100644 index 0000000000..f562c9c9fd --- /dev/null +++ b/packages/sysutils/fuse/patches/fuse-0003-fix-configure-ac.patch @@ -0,0 +1,11 @@ +--- a/configure.ac 2021-07-25 10:21:45.000000000 +0000 ++++ b/configure.ac 2024-12-30 12:29:55.969242866 +0000 +@@ -72,6 +72,8 @@ + done + ]) + AM_ICONV ++AM_GNU_GETTEXT([external]) ++AM_GNU_GETTEXT_VERSION([0.14.4]) + libfuse_libs="$libfuse_libs $LTLIBICONV" + AM_CONDITIONAL(ICONV, test "$am_cv_func_iconv" = yes) + AC_SUBST(libfuse_libs) diff --git a/packages/sysutils/fuse3/package.mk b/packages/sysutils/fuse3/package.mk new file mode 100644 index 0000000000..09911fa18c --- /dev/null +++ b/packages/sysutils/fuse3/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="fuse3" +PKG_VERSION="3.17.2" +PKG_SHA256="3d932431ad94e86179e5265cddde1d67aa3bb2fb09a5bd35c641f86f2b5ed06f" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/libfuse/libfuse/" +PKG_URL="https://github.com/libfuse/libfuse/releases/download/fuse-${PKG_VERSION}/fuse-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain systemd" +PKG_LONGDESC="FUSE is an interface for userspace programs to export a filesystem to the Linux kernel." + +PKG_MESON_OPTS_TARGET="-Ddisable-mtab=false \ + -Dutils=true \ + -Dexamples=false \ + -Duseroot=false \ + -Dtests=false" + +post_makeinstall_target() { + rm -rf ${INSTALL}/etc + rm -rf ${INSTALL}/usr/lib/udev +} diff --git a/packages/sysutils/ir-bpf-decoders/package.mk b/packages/sysutils/ir-bpf-decoders/package.mk new file mode 100644 index 0000000000..ab9cfe8220 --- /dev/null +++ b/packages/sysutils/ir-bpf-decoders/package.mk @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="ir-bpf-decoders" +PKG_VERSION="1.22.0" +PKG_SHA256="9743e49dd725f9fb7d0410f3481931156d69fd8305184baa883ed94038fc79fc" +PKG_LICENSE="GPLv2+" +PKG_SITE="https://linuxtv.org/" +PKG_URL="https://github.com/LibreELEC/ir-bpf-decoders/archive/v4l-utils-${PKG_VERSION}.tar.gz" +PKG_LONGDESC="ir-bpf-decoders: precompiled binaries of IR BPF decoders from v4l-utils utils/keytable/bpf_protocols" +PKG_TOOLCHAIN="manual" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/udev/rc_keymaps/protocols + cp ${PKG_BUILD}/*.o ${INSTALL}/usr/lib/udev/rc_keymaps/protocols +} diff --git a/packages/sysutils/keyutils/package.mk b/packages/sysutils/keyutils/package.mk new file mode 100644 index 0000000000..a1d9ddd198 --- /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.3" +PKG_SHA256="a61d5706136ae4c05bd48f86186bcfdbd88dd8bd5107e3e195c924cfc1b39bb4" +PKG_LICENSE="GPL" +PKG_SITE="https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/keyutils.git/" +PKG_URL="https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/keyutils.git/snapshot/${PKG_NAME}-${PKG_VERSION}.tar.gz" +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 0000000000..703dce5ec0 --- /dev/null +++ b/packages/sysutils/keyutils/patches/keyutils-02-cflags.patch @@ -0,0 +1,24 @@ +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 +-CXXFLAGS := -g -Wall -Werror ++CFLAGS += -g -Wall -Werror ++CXXFLAGS += -g -Wall -Werror + INSTALL := install + DESTDIR := +-- +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 0000000000..f7f20aa5b7 --- /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 0000000000..2a7da1c9ce --- /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 0000000000..c949319657 --- /dev/null +++ b/packages/sysutils/kmod/package.mk @@ -0,0 +1,54 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="kmod" +PKG_VERSION="34.2" +PKG_SHA256="5a5d5073070cc7e0c7a7a3c6ec2a0e1780850c8b47b3e3892226b93ffcb9cb54" +PKG_LICENSE="GPL" +PKG_SITE="https://git.kernel.org/pub/scm/utils/kernel/kmod/kmod.git" +PKG_URL="https://www.kernel.org/pub/linux/utils/kernel/kmod/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_HOST="meson:host ninja:host" +PKG_DEPENDS_TARGET="meson:host gcc:host openssl" +PKG_LONGDESC="kmod offers the needed flexibility and fine grained control over insertion, removal, configuration and listing of kernel modules." +PKG_BUILD_FLAGS="-gold -mold" + +PKG_MESON_OPTS_COMMON="-Dbashcompletiondir=no \ + -Dfishcompletiondir=no \ + -Dzshcompletiondir=no \ + -Dzstd=disabled \ + -Dxz=disabled \ + -Dzlib=disabled \ + -Dopenssl=enabled \ + -Dtools=true \ + -Ddebug-messages=false \ + -Dbuild-tests=false \ + -Dmanpages=false \ + -Ddocs=false" + +PKG_MESON_OPTS_HOST="${PKG_MESON_OPTS_COMMON} \ + -Dlogging=false" + +PKG_MESON_OPTS_TARGET="${PKG_MESON_OPTS_COMMON} \ + -Dlogging=true" + +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 + rmdir ${INSTALL}/etc/modprobe.d + 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 0000000000..8614e475cd --- /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 0000000000..0edea0bf7d --- /dev/null +++ b/packages/sysutils/libevdev/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="libevdev" +PKG_VERSION="1.13.4" +PKG_SHA256="f00ab8d42ad8b905296fab67e13b871f1a424839331516642100f82ad88127cd" +PKG_LICENSE="MIT" +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_MESON_OPTS_TARGET=" \ + -Ddefault_library=shared \ + -Ddocumentation=disabled \ + -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 0000000000..c368661517 --- /dev/null +++ b/packages/sysutils/libhid/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="libhid" +PKG_VERSION="9bbcb6484c91e2594614412e12ae85a144839634" # 0.2.17 + fixes +PKG_SHA256="983c6fa0b46b67805a81eb600a6c4728b645ac7b014b4897d5aa212576105567" +PKG_LICENSE="GPL" +PKG_SITE="http://libhid.alioth.debian.org/" +PKG_URL="https://github.com/chad3814/libhid/archive/${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 0000000000..eb2b2245c0 --- /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-disable_docs.patch b/packages/sysutils/libhid/patches/libhid-disable_docs.patch new file mode 100644 index 0000000000..08eca9ca3a --- /dev/null +++ b/packages/sysutils/libhid/patches/libhid-disable_docs.patch @@ -0,0 +1,11 @@ +--- a/doc/Makefile.am 2014-12-23 16:37:21.000000000 +0000 ++++ b/doc/Makefile.am 2020-12-27 02:49:58.084611309 +0000 +@@ -1,7 +1,7 @@ + # AM_MAKEFLAGS = @MAKEFLAGS@ + ACLOCAL_AMFLAGS = -I m4 + +-SUBDIRS = www man ++SUBDIRS = + + if DOXYGEN + all-local: html 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 0000000000..0d38057681 --- /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 0000000000..9903b06c0f --- /dev/null +++ b/packages/sysutils/libusb-compat/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="libusb-compat" +PKG_VERSION="0.1.8" +PKG_SHA256="b692dcf674c070c8c0bee3c8230ce4ee5903f926d77dc8b968a4dd1b70f9b05c" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/libusb/libusb-compat-0.1" +PKG_URL="https://github.com/libusb/libusb-compat-0.1/releases/download/v${PKG_VERSION}/${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_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="--disable-log \ + --disable-debug-log \ + --disable-examples-build" + +post_configure_target() { + libtool_remove_rpath libtool +} + +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 0000000000..2d99433c88 --- /dev/null +++ b/packages/sysutils/libusb/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="libusb" +PKG_VERSION="1.0.29" +PKG_SHA256="5977fc950f8d1395ccea9bd48c06b3f808fd3c2c961b44b0c2e6e29fc3a70a85" +PKG_LICENSE="LGPLv2.1" +PKG_SITE="http://libusb.info/" +PKG_URL="https://github.com/libusb/libusb/releases/download/v${PKG_VERSION}/libusb-${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." + +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 0000000000..3fb2bf94fb --- /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 0000000000..e69de29bb2 diff --git a/packages/sysutils/lirc/package.mk b/packages/sysutils/lirc/package.mk new file mode 100644 index 0000000000..2a90cbfc91 --- /dev/null +++ b/packages/sysutils/lirc/package.mk @@ -0,0 +1,66 @@ +# 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.2" +PKG_SHA256="3d44ec8274881cf262f160805641f0827ffcc20ade0d85e7e6f3b90e0d3d222a" +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_CONFIGURE_OPTS_TARGET="--enable-devinput \ + --enable-uinput \ + --with-gnu-ld \ + --without-x \ + --runstatedir=/run \ + --with-lockdir=/var/lock" + +post_unpack() { + # remove confusing static config.h in lirc 0.10.2 release package (temp fix) + # lead to "LIRC_LOCKDIR" redefined to "/var/lock/lockdir" + rm ${PKG_BUILD}/lib/lirc/config.h +} + +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_configure_target() { + libtool_remove_rpath libtool +} + +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/archr + cp ${PKG_DIR}/scripts/lircd_helper ${INSTALL}/usr/lib/archr + cp ${PKG_DIR}/scripts/lircd_uinput_helper ${INSTALL}/usr/lib/archr + + 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 0000000000..1c0be1f0e8 --- /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-0100-disable-python.patch b/packages/sysutils/lirc/patches/lirc-0100-disable-python.patch new file mode 100644 index 0000000000..c0b0efc0c8 --- /dev/null +++ b/packages/sysutils/lirc/patches/lirc-0100-disable-python.patch @@ -0,0 +1,137 @@ +diff --git a/Makefile.am b/Makefile.am +--- 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) +@@ -39,13 +41,17 @@ MANTAINERCLEANFILES = config.sub ins + 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 + +@@ -66,7 +72,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 +@@ -78,6 +86,7 @@ header_HEADERS = include/linux/ + mediadir = $(includedir)/lirc/media + media_HEADERS = include/media/lirc.h + ++if HAVE_PYTHON + py_pkgdir = $(pkgdatadir)/python-pkg + dist_py_pkg_DATA = python-pkg/setup.py \ + python-pkg/README.rst +@@ -143,6 +152,8 @@ all-local: + $(PYTHON) setup.py $(if $(VERBOSE),,-q) build + endif + ++endif ++ + install-data-hook: + $(SED) -i -e '/^plugindir/s|/usr/lib|$(libdir)|' \ + $(DESTDIR)$(lirc_confdir)/lirc_options.conf +@@ -177,6 +188,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 +@@ -202,6 +214,7 @@ python-pkg/lirc/config.py: Makefile $(a + @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 +--- a/configure.ac ++++ b/configure.ac +@@ -47,7 +47,8 @@ AC_CHECK_PROG([DOXYGEN],[doxygen],[yes], + 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_CFLAGS" && \ + PKG_CHECK_MODULES([PYTHON], [python-$PYTHON_VERSION],,[true]) +@@ -138,11 +139,7 @@ test -d "/var/lock/lockdev" || lockdir_d + enable_uinput_default="no" + test -e "/dev/uinput" && enable_uinput_default="yes" + +-version_nodots=$( $PYTHON << EOF +-v = "$VERSION".split("rc").pop(0).split("-").pop(0).split(".") +-print(int(v.pop(0)) * 10000 + int(v.pop(0)) * 100 + int(v.pop(0))) +-EOF +-) ++version_nodots=$( echo $VERSION|tr '.' ' '|(read m v r;echo $((m*10000+v*100+r))) ) + AC_DEFINE_UNQUOTED(VERSION_NODOTS, [$version_nodots]) + + AC_MSG_CHECKING([for linux kernel]) +@@ -572,6 +569,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]) + + AS_IF([test x$HAVE_PYMOD_YAML != xyes], AC_MSG_WARN([ +--- 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 lirc-postinstall + dist_sbin_SCRIPTS = lircd-setup + dist_noinst_SCRIPTS = make_rel_symlink.py check_configs.py +@@ -122,6 +127,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 0000000000..75be889c13 --- /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 0000000000..3c27b80be8 --- /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 0000000000..cddb243d68 --- /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/archr/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 0000000000..6c4ab2e4e8 --- /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/archr/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 0000000000..03a5c1bd5b --- /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 0000000000..d1f150c686 --- /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/open-iscsi/package.mk b/packages/sysutils/open-iscsi/package.mk new file mode 100644 index 0000000000..28a019a0a3 --- /dev/null +++ b/packages/sysutils/open-iscsi/package.mk @@ -0,0 +1,87 @@ +# 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="bf399411ed8a2f4047f928653ac8dd02ffd0f662" +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_DEPENDS_HOST="toolchain:host" +PKG_DEPENDS_TARGET="toolchain open-iscsi:host" +PKG_LONGDESC="The open-iscsi package allows you to mount iSCSI targets." +PKG_TOOLCHAIN="configure" +PKG_BUILD_FLAGS="-sysroot" + +PKG_MAKE_OPTS_INIT="user" + +PKG_MAKE_OPTS_TARGET="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 +} + +pre_configure_host() { + export OPTFLAGS="${CFLAGS} ${LDFLAGS}" +} + +configure_host() { + : +} + +make_host() { + cd ${PKG_BUILD}/utils + make iscsi-iname +} + +makeinstall_host() { + mkdir -p ${TOOLCHAIN}/bin + cp -P ${PKG_BUILD}/utils/iscsi-iname ${TOOLCHAIN}/bin +} + +pre_configure_target() { + export OPTFLAGS="${CFLAGS} ${LDFLAGS}" +} + +configure_target() { + cd utils/open-isns + ./configure --host=${TARGET_NAME} \ + --build=${HOST_NAME} \ + --with-security=no + + cd ${PKG_BUILD} +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/sbin + cp -P ${PKG_BUILD}/usr/iscsid ${INSTALL}/usr/sbin + cp -P ${PKG_BUILD}/usr/iscsiadm ${INSTALL}/usr/sbin + cp -P ${PKG_BUILD}/usr/iscsistart ${INSTALL}/usr/sbin + cp -P ${PKG_BUILD}/utils/iscsi-iname ${INSTALL}/usr/sbin + + mkdir -p ${INSTALL}/etc/iscsi + cp -P ${PKG_BUILD}/etc/iscsid.conf ${INSTALL}/etc/iscsi + + sed -i -e "s:= /sbin/iscsid:= /usr/sbin/iscsid:" ${INSTALL}/etc/iscsi/iscsid.conf + + echo "InitiatorName=$(${TOOLCHAIN}/bin/iscsi-iname)" >${INSTALL}/etc/iscsi/initiatorname.iscsi +} + +post_install() { + enable_service iscsi-initiator.service +} 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 0000000000..27d30311b8 --- /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 0000000000..38e82d7eae --- /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 0000000000..10ca6e23ef --- /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 0000000000..106e84a9e3 --- /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-iscsi/patches/open-iscsi-05-Updates-to-support-gcc-fno-common-option.patch b/packages/sysutils/open-iscsi/patches/open-iscsi-05-Updates-to-support-gcc-fno-common-option.patch new file mode 100644 index 0000000000..d1f9c9e91a --- /dev/null +++ b/packages/sysutils/open-iscsi/patches/open-iscsi-05-Updates-to-support-gcc-fno-common-option.patch @@ -0,0 +1,124 @@ +From a8ce860b4462fbb22634c34a5d30cd0d482acb22 Mon Sep 17 00:00:00 2001 +From: Lee Duncan +Date: Tue, 28 Jan 2020 16:36:56 -0800 +Subject: [PATCH] Updates to support gcc -fno-common option. + +This meant cleaning up the definition of some +global variables, so that they were only defined +in one place and refered to as external elsewhere. +--- + include/iscsi_err.h | 6 ++++-- + iscsiuio/configure | 2 +- + iscsiuio/configure.ac | 2 +- + iscsiuio/src/uip/uip.h | 4 ++-- + usr/iscsi_err.c | 2 ++ + usr/log.c | 1 + + usr/log.h | 2 +- + 7 files changed, 12 insertions(+), 7 deletions(-) + +diff --git a/include/iscsi_err.h b/include/iscsi_err.h +index 125f443a2f25..a08f0fbfcea6 100644 +--- a/include/iscsi_err.h ++++ b/include/iscsi_err.h +@@ -4,7 +4,7 @@ + #ifndef _ISCSI_ERR_ + #define _ISCSI_ERR_ + +-enum { ++enum iscsi_error_list { + ISCSI_SUCCESS = 0, + /* Generic error */ + ISCSI_ERR = 1, +@@ -69,7 +69,9 @@ enum { + + /* Always last. Indicates end of error code space */ + ISCSI_MAX_ERR_VAL, +-} iscsi_err; ++}; ++ ++extern enum iscsi_error_list iscsi_err; + + extern void iscsi_err_print_msg(int err); + extern char *iscsi_err_to_str(int err); +diff --git a/iscsiuio/configure b/iscsiuio/configure +index 2740598f5f87..e799c377b4ab 100755 +--- a/iscsiuio/configure ++++ b/iscsiuio/configure +@@ -22729,7 +22729,7 @@ echo "$as_me: error: cannot create directory $dirpart/$fdir" >&2;} + done + done + ;; +- default ) echo 'char *build_date = "'`date`'";' > src/unix/build_date.c && echo 'char *build_date;'> src/unix/build_date.h ;; ++ default ) echo 'char *build_date = "'`date`'";' > src/unix/build_date.c && echo 'extern char *build_date;'> src/unix/build_date.h ;; + esac + done + _ACEOF +diff --git a/iscsiuio/configure.ac b/iscsiuio/configure.ac +index e9a5e32399ea..f51687bf56b5 100644 +--- a/iscsiuio/configure.ac ++++ b/iscsiuio/configure.ac +@@ -62,7 +62,7 @@ AC_ARG_ENABLE(debug, + fi]) + AM_CONDITIONAL([DEBUG], [test x$debug = xtrue]) + +-AC_CONFIG_COMMANDS([default],[[ echo 'char *build_date = "'`date`'";' > src/unix/build_date.c && echo 'char *build_date;'> src/unix/build_date.h]],[[]]) ++AC_CONFIG_COMMANDS([default],[[ echo 'char *build_date = "'`date`'";' > src/unix/build_date.c && echo 'extern char *build_date;'> src/unix/build_date.h]],[[]]) + + AC_PREFIX_DEFAULT() + +diff --git a/iscsiuio/src/uip/uip.h b/iscsiuio/src/uip/uip.h +index 0225f6a456f5..d8e2220bf357 100644 +--- a/iscsiuio/src/uip/uip.h ++++ b/iscsiuio/src/uip/uip.h +@@ -70,8 +70,8 @@ struct uip_stack; + typedef u16_t uip_ip4addr_t[2]; + typedef u16_t uip_ip6addr_t[8]; + +-const uip_ip6addr_t all_zeroes_addr6; +-const uip_ip4addr_t all_zeroes_addr4; ++extern const uip_ip6addr_t all_zeroes_addr6; ++extern const uip_ip4addr_t all_zeroes_addr4; + + #define ETH_BUF(buf) ((struct uip_eth_hdr *)buf) + #define VLAN_ETH_BUF(buf) ((struct uip_vlan_eth_hdr *)buf) +diff --git a/usr/iscsi_err.c b/usr/iscsi_err.c +index 4fe1c53adce0..6b6a4124458a 100644 +--- a/usr/iscsi_err.c ++++ b/usr/iscsi_err.c +@@ -21,6 +21,8 @@ + #include "iscsi_err.h" + #include "log.h" + ++enum iscsi_error_list iscsi_err; ++ + static char *iscsi_err_msgs[] = { + /* 0 */ "", + /* 1 */ "unknown error", +diff --git a/usr/log.c b/usr/log.c +index 26c61d847793..f7c542eeb191 100644 +--- a/usr/log.c ++++ b/usr/log.c +@@ -33,6 +33,7 @@ + + char *log_name; + int log_level = 0; ++struct logarea *la = NULL; + + static int log_stop_daemon = 0; + static void (*log_func)(int prio, void *priv, const char *fmt, va_list ap); +diff --git a/usr/log.h b/usr/log.h +index 486a08ea08b2..c548791e73a1 100644 +--- a/usr/log.h ++++ b/usr/log.h +@@ -64,7 +64,7 @@ struct logarea { + union semun semarg; + }; + +-struct logarea *la; ++extern struct logarea *la; + + extern int log_init(char *program_name, int size, + void (*func)(int prio, void *priv, const char *fmt, va_list ap), +-- +2.27.0 + diff --git a/packages/sysutils/open-iscsi/patches/open-iscsi-06-Fix-attribute.patch b/packages/sysutils/open-iscsi/patches/open-iscsi-06-Fix-attribute.patch new file mode 100644 index 0000000000..41d3d3c2c4 --- /dev/null +++ b/packages/sysutils/open-iscsi/patches/open-iscsi-06-Fix-attribute.patch @@ -0,0 +1,25 @@ +From 61936357ef7d796c3f4fe95782309268be9e6a31 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 20 Jun 2020 19:37:42 +0200 +Subject: [PATCH] Fix attribute + +--- + include/iscsi_if.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/iscsi_if.h b/include/iscsi_if.h +index 20f2bc2961e9..6633bc528555 100644 +--- a/include/iscsi_if.h ++++ b/include/iscsi_if.h +@@ -327,7 +327,7 @@ struct iscsi_iface_param_info { + uint8_t iface_type; /* IPv4 or IPv6 */ + uint8_t param_type; /* iscsi_param_type */ + uint8_t value[0]; /* length sized value follows */ +-} __packed; ++} __attribute__((__packed__)); + + /* + * To keep the struct iscsi_uevent size the same for userspace code +-- +2.27.0 + diff --git a/packages/sysutils/open-iscsi/patches/open-iscsi-07-usr-run-for-config.patch b/packages/sysutils/open-iscsi/patches/open-iscsi-07-usr-run-for-config.patch new file mode 100644 index 0000000000..b2ae3defd4 --- /dev/null +++ b/packages/sysutils/open-iscsi/patches/open-iscsi-07-usr-run-for-config.patch @@ -0,0 +1,53 @@ +diff -Naur a/usr/idbm.c b/usr/idbm.c +--- a/usr/idbm.c 2013-07-29 12:13:36.000000000 -0700 ++++ b/usr/idbm.c 2022-05-03 15:16:35.006014572 -0700 +@@ -2647,9 +2647,9 @@ + int idbm_init(idbm_get_config_file_fn *fn) + { + /* make sure root db dir is there */ +- if (access(ISCSI_CONFIG_ROOT, F_OK) != 0) { +- if (mkdir(ISCSI_CONFIG_ROOT, 0660) != 0) { +- log_error("Could not make %s %d\n", ISCSI_CONFIG_ROOT, ++ if (access(ISCSIVAR, F_OK) != 0) { ++ if (mkdir(ISCSIVAR, 0770) != 0) { ++ log_error("Could not make %s %d", ISCSIVAR, + errno); + return errno; + } +diff -Naur a/usr/idbm.h b/usr/idbm.h +--- a/usr/idbm.h 2013-07-29 12:13:36.000000000 -0700 ++++ b/usr/idbm.h 2022-05-03 15:17:18.700644189 -0700 +@@ -29,12 +29,13 @@ + #include "list.h" + #include "flashnode.h" + +-#define NODE_CONFIG_DIR ISCSI_CONFIG_ROOT"nodes" +-#define SLP_CONFIG_DIR ISCSI_CONFIG_ROOT"slp" +-#define ISNS_CONFIG_DIR ISCSI_CONFIG_ROOT"isns" +-#define STATIC_CONFIG_DIR ISCSI_CONFIG_ROOT"static" +-#define FW_CONFIG_DIR ISCSI_CONFIG_ROOT"fw" +-#define ST_CONFIG_DIR ISCSI_CONFIG_ROOT"send_targets" ++#define ISCSIVAR "/run/iscsi/" ++#define NODE_CONFIG_DIR ISCSIVAR"nodes" ++#define SLP_CONFIG_DIR ISCSIVAR"slp" ++#define ISNS_CONFIG_DIR ISCSIVAR"isns" ++#define STATIC_CONFIG_DIR ISCSIVAR"static" ++#define FW_CONFIG_DIR ISCSIVAR"fw" ++#define ST_CONFIG_DIR ISCSIVAR"send_targets" + #define ST_CONFIG_NAME "st_config" + #define ISNS_CONFIG_NAME "isns_config" + +diff -Naur a/usr/iface.h b/usr/iface.h +--- a/usr/iface.h 2013-07-29 12:13:36.000000000 -0700 ++++ b/usr/iface.h 2022-05-03 15:18:31.164688356 -0700 +@@ -20,7 +20,9 @@ + #ifndef ISCSI_IFACE_H + #define ISCSI_IFACE_H + +-#define IFACE_CONFIG_DIR ISCSI_CONFIG_ROOT"ifaces" ++#include "idbm.h" ++ ++#define IFACE_CONFIG_DIR ISCSIVAR"ifaces" + + struct iface_rec; + struct list_head; diff --git a/packages/sysutils/open-iscsi/patches/open-iscsi-08-rename-local-strings--ch--to-local_strings--ch-.patch b/packages/sysutils/open-iscsi/patches/open-iscsi-08-rename-local-strings--ch--to-local_strings--ch-.patch new file mode 100644 index 0000000000..fa281e6885 --- /dev/null +++ b/packages/sysutils/open-iscsi/patches/open-iscsi-08-rename-local-strings--ch--to-local_strings--ch-.patch @@ -0,0 +1,63 @@ +From 0715d725fa2793b051f14509d07651a69bac81e7 Mon Sep 17 00:00:00 2001 +From: Lee Duncan +Date: Sat, 2 Dec 2017 13:42:27 -0800 +Subject: [PATCH] Rename local strings.[ch] to local_strings.[ch] + +This avoids linker and human confusion with +the include file. No functional +change. +--- + usr/Makefile | 2 +- + usr/discovery.c | 2 +- + usr/{strings.c => local_strings.c} | 2 +- + usr/{strings.h => local_strings.h} | 0 + 4 files changed, 3 insertions(+), 3 deletions(-) + rename usr/{strings.c => local_strings.c} (99%) + rename usr/{strings.h => local_strings.h} (100%) + +diff --git a/usr/Makefile b/usr/Makefile +index c1866b6a4..f0dcfe720 100644 +--- a/usr/Makefile ++++ b/usr/Makefile +@@ -49,7 +49,7 @@ + FW_BOOT_SRCS = $(wildcard ../utils/fwparam_ibft/*.o) + + # core discovery files +-DISCOVERY_SRCS = $(FW_BOOT_SRCS) strings.o discovery.o ++DISCOVERY_SRCS = $(FW_BOOT_SRCS) local_strings.o discovery.o + + all: $(PROGRAMS) + +diff --git a/usr/discovery.c b/usr/discovery.c +index 6ee8bd915..8001af6fe 100644 +--- a/usr/discovery.c ++++ b/usr/discovery.c +@@ -32,7 +32,7 @@ + #include + #include + +-#include "strings.h" ++#include "local_strings.h" + #include "types.h" + #include "iscsi_proto.h" + #include "initiator.h" +diff --git a/usr/strings.c b/usr/local_strings.c +similarity index 99% +rename from usr/strings.c +rename to usr/local_strings.c +index da5df288f..d0feb6d27 100644 +--- a/usr/strings.c ++++ b/usr/local_strings.c +@@ -23,7 +23,7 @@ + #include + #include + +-#include "strings.h" ++#include "local_strings.h" + #include "log.h" + + int str_init_buffer(struct str_buffer *s, size_t initial_allocation) +diff --git a/usr/strings.h b/usr/local_strings.h +similarity index 100% +rename from usr/strings.h +rename to usr/local_strings.h diff --git a/packages/sysutils/open-iscsi/patches/open-iscsi-09-Fix-undefined-call-to-writev----include--sys-uio.h.patch b/packages/sysutils/open-iscsi/patches/open-iscsi-09-Fix-undefined-call-to-writev----include--sys-uio.h.patch new file mode 100644 index 0000000000..8f8daa95b9 --- /dev/null +++ b/packages/sysutils/open-iscsi/patches/open-iscsi-09-Fix-undefined-call-to-writev----include--sys-uio.h.patch @@ -0,0 +1,21 @@ +From 621ad28e4a278445e674986c9ddbf589dffaf228 Mon Sep 17 00:00:00 2001 +From: Lee Duncan +Date: Sat, 2 Dec 2017 14:03:14 -0800 +Subject: [PATCH] Fix undefined call to writev(): include + +--- + usr/io.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/usr/io.c b/usr/io.c +index 48b233cf6..e4d00ae2c 100644 +--- a/usr/io.c ++++ b/usr/io.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + + #include "types.h" + #include "iscsi_proto.h" diff --git a/packages/sysutils/open-iscsi/system.d/iscsi-initiator.service b/packages/sysutils/open-iscsi/system.d/iscsi-initiator.service new file mode 100644 index 0000000000..a8b066f5e7 --- /dev/null +++ b/packages/sysutils/open-iscsi/system.d/iscsi-initiator.service @@ -0,0 +1,9 @@ +[Unit] +Description=Open-iSCSI initiator (i.e. client) service +After=syslog.target + +[Service] +ExecStart=/usr/sbin/iscsid -f + +[Install] +WantedBy=multi-user.target diff --git a/packages/sysutils/open-iscsi/tmpfiles.d/iscsi.conf b/packages/sysutils/open-iscsi/tmpfiles.d/iscsi.conf new file mode 100644 index 0000000000..713452811c --- /dev/null +++ b/packages/sysutils/open-iscsi/tmpfiles.d/iscsi.conf @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022 Team LibreELEC (https://libreelec.tv) + +d /run/lock/iscsi 0700 root root - +f /run/lock/iscsi/lock 0600 root root - diff --git a/packages/sysutils/parted/package.mk b/packages/sysutils/parted/package.mk new file mode 100644 index 0000000000..0218357ea5 --- /dev/null +++ b/packages/sysutils/parted/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) 2020-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="parted" +PKG_VERSION="3.6" +PKG_SHA256="3b43dbe33cca0f9a18601ebab56b7852b128ec1a3df3a9b30ccde5e73359e612" +PKG_LICENSE="GPL" +PKG_SITE="http://www.gnu.org/software/parted/" +PKG_URL="https://mirrors.kernel.org/gnu/parted/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_HOST="autotools:host util-linux:host" +PKG_DEPENDS_TARGET="autotools:host gcc:host util-linux parted:host" +PKG_DEPENDS_INIT="autotools:host gcc:host 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}" + +pre_configure_init() { + : # reuse pre_configure_target() +} + +post_configure_init() { + : # reuse post_configure_target() +} + +configure_init() { + : # reuse configure_target() +} + +make_init() { + : # reuse make_target() +} + +makeinstall_init() { + mkdir -p ${INSTALL}/usr/sbin + cp ../.${TARGET_NAME}/parted/parted ${INSTALL}/usr/sbin + cp ../.${TARGET_NAME}/partprobe/partprobe ${INSTALL}/usr/sbin +} + +pre_configure_target() { + export CFLAGS+=" -I${PKG_BUILD}/lib" +} + +post_configure_target() { + libtool_remove_rpath libtool +} diff --git a/packages/sysutils/parted/patches/parted-0001-fix-do_version-declaration.patch b/packages/sysutils/parted/patches/parted-0001-fix-do_version-declaration.patch new file mode 100644 index 0000000000..bbdec07a50 --- /dev/null +++ b/packages/sysutils/parted/patches/parted-0001-fix-do_version-declaration.patch @@ -0,0 +1,40 @@ +From 7dae5d837562a494e14f69702601bcc2240cab3e Mon Sep 17 00:00:00 2001 +From: Rudi Heitbaum +Date: Wed, 20 Nov 2024 12:17:07 +0000 +Subject: [PATCH] parted: fix do_version declaration + +With gcc 15-20241117 compile fails with the below error, update the +do_version declaration to match the header in command.h + +../../parted/parted.c: In function '_init_commands': +../../parted/parted.c:2469:9: error: passing argument 2 of 'command_create' from incompatible pointer type [-Wincompatible-pointer-types] + 2469 | do_version, + | ^~~~~~~~~~ + | | + | int (*)(void) +In file included from ../../parted/parted.c:28: +../../parted/command.h:35:39: note: expected 'int (*)(PedDevice **, PedDisk **)' {aka 'int (*)(struct _PedDevice **, struct _PedDisk **)'} but argument is of type 'int (*)(void)' + 35 | int (*method) (PedDevice** dev, PedDisk** diskp), + | ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Signed-off-by: Rudi Heitbaum +--- + parted/parted.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/parted/parted.c b/parted/parted.c +index 3abb52f..fc2aeba 100644 +--- a/parted/parted.c ++++ b/parted/parted.c +@@ -2172,7 +2172,7 @@ do_unit (PedDevice** dev, PedDisk** diskp) + } + + static int +-do_version () ++do_version (PedDevice** dev, PedDisk** diskp) + { + printf ("\n%s\n%s", + prog_name, +-- +2.43.0 + diff --git a/packages/sysutils/pciutils/package.mk b/packages/sysutils/pciutils/package.mk new file mode 100644 index 0000000000..1ae9c4e20e --- /dev/null +++ b/packages/sysutils/pciutils/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) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="pciutils" +PKG_VERSION="3.14.0" +PKG_SHA256="e7713409882813991d2269d125e40dad1f54a019a52b78b3962941c1d4a6f86f" +PKG_LICENSE="GPL" +PKG_SITE="http://mj.ucw.cz/pciutils.shtml" +PKG_URL="https://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 + make ${PKG_MAKE_OPTS} DESTDIR=${INSTALL} install +} + +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 0000000000..cee1da5094 --- /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/sed/package.mk b/packages/sysutils/sed/package.mk new file mode 100644 index 0000000000..d0e5966445 --- /dev/null +++ b/packages/sysutils/sed/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) 2020-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="sed" +PKG_VERSION="4.9" +PKG_SHA256="6e226b732e1cd739464ad6862bd1a1aba42d7982922da7a53519631d24975181" +PKG_LICENSE="GPL" +PKG_SITE="http://www.gnu.org/software/sed/" +PKG_URL="https://mirrors.kernel.org/gnu/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_BUILD_FLAGS="-cfg-libs:host" + +PKG_CONFIGURE_OPTS_HOST="--disable-nls --disable-acl --without-selinux" diff --git a/packages/sysutils/squashfs-tools/package.mk b/packages/sysutils/squashfs-tools/package.mk new file mode 100644 index 0000000000..a3a67b10fa --- /dev/null +++ b/packages/sysutils/squashfs-tools/package.mk @@ -0,0 +1,50 @@ +# 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.7" +PKG_SHA256="f1605ef720aa0b23939a49ef4491f6e734333ccc4bda4324d330da647e105328" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/plougher/squashfs-tools" +PKG_URL="https://github.com/plougher/squashfs-tools/releases/download/${PKG_VERSION}/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="ccache:host zlib:host lzo:host zstd:host" +PKG_DEPENDS_TARGET="toolchain zlib lzo zstd xz" +PKG_NEED_UNPACK="$(get_pkg_directory zlib) $(get_pkg_directory lzo) $(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=0 \ + LZO_SUPPORT=1 \ + LZ4_SUPPORT=0 \ + 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 +} + +make_target() { + make -C squashfs-tools clean + make -C squashfs-tools \ + mksquashfs unsquashfs \ + XZ_SUPPORT=1 \ + LZO_SUPPORT=1 \ + LZ4_SUPPORT=0 \ + ZSTD_SUPPORT=1 \ + XATTR_SUPPORT=0 \ + XATTR_DEFAULT=0 +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp squashfs-tools/mksquashfs ${INSTALL}/usr/bin/ + cp squashfs-tools/unsquashfs ${INSTALL}/usr/bin/ +} diff --git a/packages/sysutils/systemd/config/hosts.conf b/packages/sysutils/systemd/config/hosts.conf new file mode 100644 index 0000000000..d2aa073bb5 --- /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.mynetwork libreelec + +# 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 0000000000..6f31f02ec4 --- /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 0000000000..ea24105a8d --- /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 0000000000..e781928e95 --- /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 0000000000..403b99f7bd --- /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 0000000000..4ca7168beb --- /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 0000000000..fd69984474 --- /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.conf.d/10-shutdown-timeout.conf b/packages/sysutils/systemd/config/system.conf.d/10-shutdown-timeout.conf new file mode 100644 index 0000000000..c2005c986f --- /dev/null +++ b/packages/sysutils/systemd/config/system.conf.d/10-shutdown-timeout.conf @@ -0,0 +1,7 @@ +[Manager] +# Reduce default service stop timeout from 90s to 5s. +# ArchR uses ext4 root with persistent storage at /storage/. +# Network services don't need graceful shutdown — only filesystem sync matters, +# which is handled by systemd's built-in shutdown ordering. +DefaultTimeoutStopSec=5s +DefaultTimeoutAbortSec=5s diff --git a/packages/sysutils/systemd/config/system.d/README b/packages/sysutils/systemd/config/system.d/README new file mode 100644 index 0000000000..4546cb5224 --- /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 0000000000..7d23b00521 --- /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 network shares because we want them available *before* Kodi starts. +# so Kodi has access to mounts from the beginning. Note: this slows down the boot sequence! +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 0000000000..96890a4802 --- /dev/null +++ b/packages/sysutils/systemd/config/system.d/nfs.mount.sample @@ -0,0 +1,49 @@ +# 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 network shares because we want them available *before* Kodi starts. +# so Kodi has access to mounts from the beginning. Note: this slows down the boot sequence! +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 (for NFSv4 use Type=nfs4) +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 0000000000..e2e6f7e473 --- /dev/null +++ b/packages/sysutils/systemd/config/system.d/openvpn.service.sample @@ -0,0 +1,43 @@ +[Unit] +Description=OpenVPN Autorun Service +Requires=network-online.service +After=network-online.service + +[Service] +Type=forking +ExecStart=/usr/sbin/openvpn --daemon --config /storage/.config/openvpn.config +Restart=always +RestartSec=15 + +[Install] +WantedBy=kodi.target + +# NOTES: +# +# 1) Create /storage/.config/openvpn.config using the .config/.conf/.ovpn +# file from your VPN service provider and test the connection: +# +# /usr/sbin/openvpn --daemon --config /storage/.config/openvpn.config +# +# 2) The openvpn.service file must be enabled 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 0000000000..17537eb0c4 --- /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 0000000000..5ae2a93971 --- /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 0000000000..d6d9212035 --- /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 0000000000..6cd369b794 --- /dev/null +++ b/packages/sysutils/systemd/hwdb.d/70-local-keyboard.hwdb @@ -0,0 +1,123 @@ +# alfawise z1 remote +evdev:input:b0005v2B54p1603e* + KEYBOARD_KEY_c0041=enter + +# auvipal g9f +evdev:input:b0005v045Ep0041* + KEYBOARD_KEY_c0041=enter + KEYBOARD_KEY_70071=l + KEYBOARD_KEY_70070=g + KEYBOARD_KEY_7006f=x + KEYBOARD_KEY_7006e=i + +# bt250 remote +evdev:input:b0005v1D5ApC080e0000* + KEYBOARD_KEY_c0041=enter + +# buzztv bt-300/bt-400 smart remote +evdev:input:b0005v0957p1001* + KEYBOARD_KEY_c0041=enter + KEYBOARD_KEY_c0040=c + KEYBOARD_KEY_70040=z + KEYBOARD_KEY_70041=esc + KEYBOARD_KEY_70042=t + KEYBOARD_KEY_70043=e + KEYBOARD_KEY_70044=o + KEYBOARD_KEY_70045=volumeup + KEYBOARD_KEY_70069=volumedown + +# foxtel remote +evdev:input:b0005v06E7p8144* + KEYBOARD_KEY_c0041=enter + +# google tv remote +evdev:name:*Chromecast Remote*:* + KEYBOARD_KEY_c0041=enter + +# g7bts remote +evdev:input:b0005v045Ep0041e0300* + KEYBOARD_KEY_c0041=enter + +# g20bts remote +evdev:input:b0005v2B54p1600e0000* + KEYBOARD_KEY_c0041=enter + +# justboom smart remote +evdev:input:b0003v2252p0120* + KEYBOARD_KEY_c0041=enter + KEYBOARD_KEY_c0040=c + +# nvidia shield remotes +evdev:input:b0005v0955p7213* + KEYBOARD_KEY_c0041=enter + +evdev:input:b0005v0955p7217* + KEYBOARD_KEY_c0041=enter + +# o2.cz khamsin bluetooth remote +evdev:input:b0005v0217p0000e0110* + KEYBOARD_KEY_c0041=enter + KEYBOARD_KEY_c0040=c + +# all osmc remotes +evdev:input:b0003v2252p17* + KEYBOARD_KEY_7000c=kpleftparen + KEYBOARD_KEY_70006=kprightparen + +evdev:input:b0003v2252p1069* + KEYBOARD_KEY_7002e=volumeup + KEYBOARD_KEY_7002d=volumedown + KEYBOARD_KEY_7000c=kpleftparen + KEYBOARD_KEY_70006=kprightparen + +evdev:input:b0003v2017p1690* + KEYBOARD_KEY_7002e=volumeup + KEYBOARD_KEY_7002d=volumedown + KEYBOARD_KEY_7000c=kpleftparen + KEYBOARD_KEY_70006=kprightparen + +evdev:input:b0003v2017p1689* + KEYBOARD_KEY_7002e=volumeup + KEYBOARD_KEY_7002d=volumedown + KEYBOARD_KEY_7000c=kpleftparen + KEYBOARD_KEY_70006=kprightparen + +evdev:input:b0003v2017p1688* + KEYBOARD_KEY_7004a=esc + KEYBOARD_KEY_c0060=kpleftparen + KEYBOARD_KEY_10084=kprightparen + KEYBOARD_KEY_7002e=volumeup + KEYBOARD_KEY_7002d=volumedown + +evdev:input:b0003v2252p1037* + KEYBOARD_KEY_7004a=esc + KEYBOARD_KEY_c0060=kpleftparen + KEYBOARD_KEY_10084=kprightparen + +# ugoos ur01-ble remote +evdev:input:b0005v005Dp0001* + KEYBOARD_KEY_c0041=enter + +# UR02 remote +evdev:input:b0005v0508p1980* + KEYBOARD_KEY_c0041=enter + +# wechip g20 remote +evdev:input:b0003v4842p0001* + KEYBOARD_KEY_c0041=enter + +# xaomi remote +evdev:input:b0005v2717p32B9e4A4C* + KEYBOARD_KEY_c0041=enter + +# yyykq remote +evdev:input:b0005v0416p0300* + KEYBOARD_KEY_c0041=enter + +# zidoo v10 +evdev:input:b0005v2B54p1600* + KEYBOARD_KEY_c0041=enter + +# ZTERCR21 remote +evdev:input:b0005v0508p0110* + KEYBOARD_KEY_c0041=enter diff --git a/packages/sysutils/systemd/package.mk b/packages/sysutils/systemd/package.mk new file mode 100644 index 0000000000..c2a8824dcc --- /dev/null +++ b/packages/sysutils/systemd/package.mk @@ -0,0 +1,328 @@ +# 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="systemd" +PKG_VERSION="257.7" +PKG_SHA256="70ecf759260549486045d065555d2f8a0ac0b8523d8f58227559fbd6d7523b08" +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="meson:host ninja:host gcc:host libcap kmod util-linux entropy libidn2 wait-time-sync Jinja2:host" +PKG_LONGDESC="A system and session manager for Linux, compatible with SysV and LSB init scripts." + +PKG_MESON_OPTS_TARGET="--libdir=/usr/lib \ + -Dsplit-bin=true \ + -Dtty-gid=5 \ + -Dtests=false \ + -Dseccomp=disabled \ + -Dselinux=disabled \ + -Dapparmor=disabled \ + -Dpolkit=disabled \ + -Dacl=disabled \ + -Daudit=disabled \ + -Dblkid=enabled \ + -Dfdisk=disabled \ + -Dkmod=enabled \ + -Dpam=disabled \ + -Dpwquality=disabled \ + -Dmicrohttpd=disabled \ + -Dlibcryptsetup=disabled \ + -Dlibcurl=disabled \ + -Dlibidn=disabled \ + -Dlibidn2=enabled \ + -Dlibiptc=disabled \ + -Dqrencode=disabled \ + -Dgcrypt=disabled \ + -Dgnutls=disabled \ + -Dopenssl=disabled \ + -Dp11kit=disabled \ + -Delfutils=disabled \ + -Dzlib=disabled \ + -Dbzip2=disabled \ + -Dxz=disabled \ + -Dlz4=disabled \ + -Dzstd=disabled \ + -Dxkbcommon=disabled \ + -Dpcre2=disabled \ + -Dglib=disabled \ + -Ddbus=disabled \ + -Ddefault-dnssec=no \ + -Dimportd=disabled \ + -Dremote=disabled \ + -Dutmp=true \ + -Dhibernate=false \ + -Denvironment-d=false \ + -Dbinfmt=false \ + -Drepart=disabled \ + -Dcoredump=false \ + -Dresolve=false \ + -Dlogind=true \ + -Dhostnamed=true \ + -Dlocaled=false \ + -Dmachined=false \ + -Dportabled=false \ + -Duserdb=true \ + -Dnologin-path=/usr/sbin/nologin \ + -Dhomed=disabled \ + -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 \ + -Dtpm=false \ + -Dima=false \ + -Dsmack=false \ + -Dgshadow=false \ + -Didn=false \ + -Dnss-myhostname=false \ + -Dnss-mymachines=disabled \ + -Dnss-resolve=disabled \ + -Dnss-systemd=true \ + -Dman=disabled \ + -Dhtml=disabled \ + -Dlink-udev-shared=true \ + -Dlink-systemctl-shared=true \ + -Dlink-networkd-shared=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}" + +if [ "${PROJECT}" = "Generic" ]; then + PKG_MESON_OPTS_TARGET+=" -Defi=true" +else + PKG_MESON_OPTS_TARGET+=" -Defi=false" +fi + +pre_configure_target() { + export TARGET_CFLAGS="${TARGET_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/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 + + # remove Network adapter renaming rule, this is confusing + safe_remove ${INSTALL}/usr/lib/udev/rules.d/80-net-setup-link.rules + + safe_remove ${INSTALL}/usr/lib/udev/rules.d/71-seat.rules + safe_remove ${INSTALL}/usr/lib/udev/rules.d/73-seat-late.rules + + if [ "${LOCAL_LOGIN}" = "no" ]; then + # 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/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 + fi + + # 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 + # + safe_remove ${INSTALL}/usr/lib/systemd/system/dev-hugepages.mount + safe_remove ${INSTALL}/usr/lib/systemd/system/*.target.wants/dev-hugepages.mount + # + safe_remove ${INSTALL}/usr/lib/systemd/system/systemd-journald-audit.socket + + # adjust systemd-hwdb-update (we have read-only /etc). + sed '/^ConditionNeedsUpdate=.*$/d' -i ${INSTALL}/usr/lib/systemd/system/systemd-hwdb-update.service + + # remove systemd-creds + safe_remove ${INSTALL}/usr/bin/systemd-creds + safe_remove ${INSTALL}/usr/lib/tmpfiles.d/credstore.conf + + # remove nspawn + safe_remove ${INSTALL}/usr/bin/systemd-nspawn + safe_remove ${INSTALL}/usr/lib/systemd/system/systemd-nspawn@.service + + # remove timedatectl + safe_remove ${INSTALL}/usr/bin/timedatectl + + # 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,^.*MaxFileSec=.*$,MaxFileSec=0,g" -i ${INSTALL}/etc/systemd/journald.conf + sed -e "s,^.*MaxRetentionSec=.*$,MaxRetentionSec=0,g" -i ${INSTALL}/etc/systemd/journald.conf + sed -e "s,^.*RuntimeMaxUse=.*$,RuntimeMaxUse=2M,g" -i ${INSTALL}/etc/systemd/journald.conf + sed -e "s,^.*Storage=.*$,Storage=volatile,g" -i ${INSTALL}/etc/systemd/journald.conf + sed -e "s,^.*RuntimeMaxUse=.*$,RuntimeMaxUse=16M,g" -i ${INSTALL}/etc/systemd/journald.conf + sed -e "s,^.*RuntimeMaxFileSize=.*$,RuntimeMaxFileSize=128K,g" -i ${INSTALL}/etc/systemd/journald.conf + sed -e "s,^.*SplitMode=.*$,SplitMode=none,g" -i ${INSTALL}/etc/systemd/journald.conf + sed -e "s,^.*SystemMaxUse=.*$,SystemMaxUse=10M,g" -i ${INSTALL}/etc/systemd/journald.conf + sed -e "s,^.*RateLimitBurst=.*$,RateLimitBurst=1000,g" -i ${INSTALL}/etc/systemd/journald.conf + + # tune logind.conf + if [ "${LOCAL_LOGIN}" = "yes" ]; then + sed -e "s,^.*NAutoVTs=.*$,NAutoVTs=2,g" -i ${INSTALL}/etc/systemd/logind.conf + sed -e "s,^.*ReserveVT=.*$,ReserveVT=6,g" -i ${INSTALL}/etc/systemd/logind.conf + fi + sed -e "s,^.*HandleLidSwitch=.*$,HandleLidSwitch=ignore,g" -i ${INSTALL}/etc/systemd/logind.conf + if [ "${DISPLAYSERVER}" = "no" ]; then + sed -e "s,^.*HandlePowerKey=.*$,HandlePowerKey=poweroff,g" -i ${INSTALL}/etc/systemd/logind.conf + else + sed -e "s,^.*HandlePowerKey=.*$,HandlePowerKey=ignore,g" -i ${INSTALL}/etc/systemd/logind.conf + fi + + # replace systemd-machine-id-setup with ours + 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 + cp ${PKG_DIR}/scripts/environment-setup ${INSTALL}/usr/bin + + # use systemd to set cpufreq governor and tunables + find_file_path scripts/cpufreq && cp -PRv ${FOUND_PATH} ${INSTALL}/usr/bin + + mkdir -p ${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/archr/resolv.conf ${INSTALL}/etc/resolv.conf + ln -sf /run/archr/hosts ${INSTALL}/etc/hosts + ln -sf /run/archr/environment ${INSTALL}/etc/environment + + # 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 + ln -sf /storage/.config/logind.conf.d ${INSTALL}/etc/systemd/logind.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 + + # system manager timeout overrides + mkdir -p ${INSTALL}/etc/systemd/system.conf.d + cp -PR ${PKG_DIR}/config/system.conf.d/* ${INSTALL}/etc/systemd/system.conf.d/ + + # journald + ln -sf /storage/.cache/journald.conf.d ${INSTALL}/usr/lib/systemd/journald.conf.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 systemd-oom 194 + add_user systemd-oom x 194 194 "systemd Userspace OOM Killer" "/" "/bin/false" + + add_group adm 4 + add_group tty 5 + add_group disk 6 + add_group lp 7 + add_group kmem 9 + add_group wheel 10 + add_group cdrom 11 + add_group dialout 18 + add_group floppy 19 + add_group utmp 22 + add_group tape 33 + add_group kvm 36 + add_group video 39 pipewire + add_group audio 63 pipewire + add_group input 104 + add_group render 105 + add_group sgx 106 + + enable_service machine-id.service + enable_service debugconfig.service + enable_service userconfig.service + enable_service usercache.service + enable_service envconfig.service + enable_service cpufreq.service + enable_service network-base.service + enable_service systemd-timesyncd.service + enable_service systemd-timesyncd-setup.service + enable_service systemd-userdbd.socket + if [ "${LOCAL_LOGIN}" = "yes" ]; then + enable_service getty@tty0.service + fi +} 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 0000000000..cd0dda1517 --- /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 +@@ -253,7 +253,7 @@ + conf.set_quoted('SYSTEMD_UPDATE_HELPER_PATH', libexecdir / 'systemd-update-helper') + conf.set_quoted('SYSTEMD_USERWORK_PATH', libexecdir / 'systemd-userwork') + conf.set_quoted('SYSTEMD_VERITYSETUP_PATH', libexecdir / 'systemd-veritysetup') +-conf.set_quoted('SYSTEM_CONFIG_UNIT_DIR', pkgsysconfdir / 'system') ++conf.set_quoted('SYSTEM_CONFIG_UNIT_DIR', '/storage/.config/system.d') + conf.set_quoted('SYSTEM_DATA_UNIT_DIR', systemunitdir) + conf.set_quoted('SYSTEM_ENV_GENERATOR_DIR', systemenvgeneratordir) + conf.set_quoted('SYSTEM_GENERATOR_DIR', systemgeneratordir) 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 0000000000..ac11b21fd3 --- /dev/null +++ b/packages/sysutils/systemd/patches/systemd-0002-move-hwdb.bin-to-run.patch @@ -0,0 +1,53 @@ +From dd8a6a2af24e2d24fcc5cb9b114f8da05a69bdd0 Mon Sep 17 00:00:00 2001 +From: Rudi Heitbaum +Date: Fri, 7 Jul 2023 11:44:05 +0000 +Subject: [PATCH] move hwdb.bin to /run + +--- + src/libsystemd/sd-hwdb/hwdb-internal.h | 2 +- + src/shared/hwdb-util.c | 2 +- + units/systemd-hwdb-update.service.in | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/libsystemd/sd-hwdb/hwdb-internal.h b/src/libsystemd/sd-hwdb/hwdb-internal.h +index 5302679a62..4afdd6e306 100644 +--- a/src/libsystemd/sd-hwdb/hwdb-internal.h ++++ b/src/libsystemd/sd-hwdb/hwdb-internal.h +@@ -84,7 +84,7 @@ struct trie_value_entry2_f { + + #define 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" \ + _CONF_PATHS_SPLIT_USR_NULSTR("systemd/hwdb/hwdb.bin") \ + UDEVLIBEXECDIR "/hwdb.bin\0" +diff --git a/src/shared/hwdb-util.c b/src/shared/hwdb-util.c +index 12621b7f89..552b1dc008 100644 +--- a/src/shared/hwdb-util.c ++++ b/src/shared/hwdb-util.c +@@ -587,7 +587,7 @@ int hwdb_update(const char *root, const char *hwdb_bin_dir, bool strict, bool co + * source. If true, then hwdb.bin will be created without the information. systemd-hwdb command + * should set the argument false, and 'udevadm hwdb' command should set it true. */ + +- hwdb_bin = path_join(root, hwdb_bin_dir ?: "/etc/udev", "hwdb.bin"); ++ hwdb_bin = path_join(root, hwdb_bin_dir ?: "/run", "hwdb.bin"); + if (!hwdb_bin) + return -ENOMEM; + +diff --git a/units/systemd-hwdb-update.service.in b/units/systemd-hwdb-update.service.in +index 4ba36d1fc6..4848ae9661 100644 +--- a/units/systemd-hwdb-update.service.in ++++ b/units/systemd-hwdb-update.service.in +@@ -13,7 +13,7 @@ Documentation=man:hwdb(7) man:systemd-hwdb(8) + + ConditionNeedsUpdate=/etc + ConditionPathExists=|!{{UDEVLIBEXECDIR}}/hwdb.bin +-ConditionPathExists=|/etc/udev/hwdb.bin ++ConditionPathExists=|/run/hwdb.bin + ConditionDirectoryNotEmpty=|/etc/udev/hwdb.d/ + + DefaultDependencies=no +-- +2.34.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 0000000000..43f31b28ea --- /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 +@@ -11,7 +11,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 0000000000..89b071645f --- /dev/null +++ b/packages/sysutils/systemd/patches/systemd-0200-persist-persistent-timer-stamps.patch @@ -0,0 +1,30 @@ +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 +@@ -138,11 +138,11 @@ static int timer_setup_persistent(Timer *t) { + + if (MANAGER_IS_SYSTEM(UNIT(t)->manager)) { + +- r = unit_add_mounts_for(UNIT(t), "/var/lib/systemd/timers", UNIT_DEPENDENCY_FILE, UNIT_MOUNT_REQUIRES); ++ r = unit_add_mounts_for(UNIT(t), "/storage/.cache/systemd/timers", UNIT_DEPENDENCY_FILE, UNIT_MOUNT_REQUIRES); + if (r < 0) + return r; + +- stamp_path = strjoin("/var/lib/systemd/timers/stamp-", UNIT(t)->id); ++ 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 0000000000..17da76545a --- /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 +@@ -15,8 +15,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/profile.d/90-systemd.conf b/packages/sysutils/systemd/profile.d/90-systemd.conf new file mode 100644 index 0000000000..51962119f4 --- /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/cpufreq b/packages/sysutils/systemd/scripts/cpufreq new file mode 100755 index 0000000000..0d1bd69572 --- /dev/null +++ b/packages/sysutils/systemd/scripts/cpufreq @@ -0,0 +1,17 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2015 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +SYS_CPUFREQ_GOV=$(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor) +SYS_CPUFREQ_DIR="/sys/devices/system/cpu/cpufreq" + +# Configure frequency scaling properties +if [ $SYS_CPUFREQ_GOV = "ondemand" ]; then + for policy in ${SYS_CPUFREQ_DIR}/ondemand ${SYS_CPUFREQ_DIR}/policy*/; do + if [ -e $policy/up_threshold ]; then + echo 50 >$policy/up_threshold + fi + done +fi diff --git a/packages/sysutils/systemd/scripts/environment-setup b/packages/sysutils/systemd/scripts/environment-setup new file mode 100755 index 0000000000..ac34b30cce --- /dev/null +++ b/packages/sysutils/systemd/scripts/environment-setup @@ -0,0 +1,16 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +# read config files +for config in /etc/profile.d/*; do + if [ -f "$config" ]; then + . $config + fi +done + +# generate system-wide environment file +cat </run/archr/environment +PATH=${PATH} +LD_LIBRARY_PATH=${LD_LIBRARY_PATH} +EOF diff --git a/packages/sysutils/systemd/scripts/network-base-setup b/packages/sysutils/systemd/scripts/network-base-setup new file mode 100755 index 0000000000..f3fb864e2c --- /dev/null +++ b/packages/sysutils/systemd/scripts/network-base-setup @@ -0,0 +1,45 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +check_hosts() { + grep -v "^#" /run/archr/hosts | grep "${1}" +} + +# setup hostname +if [ -f /storage/.cache/hostname ]; then + cat /storage/.cache/hostname >/proc/sys/kernel/hostname +fi + +# setup /etc/hosts +rm -f /run/archr/hosts +if [ -f /storage/.config/hosts.conf ]; then + cat /storage/.config/hosts.conf >/run/archr/hosts + # add localhost to hosts if not present + LOCALHOST_HOSTS=$(check_hosts "localhost") + if [ -z "${LOCALHOST_HOSTS}" ]; then + { + echo "127.0.0.1 localhost" + echo "::1 localhost ip6-localhost ip6-loopback" + } >>/run/archr/hosts + fi + # add HOSTNAME to hosts if not present + HOSTNAME=$(cat /proc/sys/kernel/hostname) + HOSTNAME_HOSTS=$(check_hosts "${HOSTNAME}") + if [ -z "${HOSTNAME_HOSTS}" ]; then + echo "127.0.1.1 ${HOSTNAME}" >>/run/archr/hosts + fi +fi + +# setup /etc/resolv.conf +rm -f /run/archr/resolv.conf +if [ -f /storage/.config/resolv.conf ]; then + cat /storage/.config/resolv.conf >/run/archr/resolv.conf +elif [ -f /dev/.kernel_ipconfig ] && [ -f /proc/net/pnp ]; then + cat /proc/net/pnp >/run/archr/resolv.conf +else + cat </run/archr/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 0000000000..4d669eeee4 --- /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 + +# 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) + +# For first boot detection systemd may have overmounted the file +umount /storage/.cache/systemd-machine-id >/dev/null 2>&1 + +# 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 0000000000..0c6c254d69 --- /dev/null +++ b/packages/sysutils/systemd/scripts/systemd-timesyncd-setup @@ -0,0 +1,21 @@ +#!/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 </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 0000000000..9a0e7c9786 --- /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 0000000000..d07e257432 --- /dev/null +++ b/packages/sysutils/systemd/scripts/userconfig-setup @@ -0,0 +1,12 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +# Remove those sample files that we manage +for sample in $(find /storage/.config -name '*.sample' 2>/dev/null); do + [ -f /usr/config/${sample:17} ] && rm -f ${sample} +done + +# Copy config files, but don't overwrite - this should replace our sample files +false | cp -iRp /usr/config/* /storage/.config/ &>/dev/null diff --git a/packages/sysutils/systemd/system.d/cpufreq.service b/packages/sysutils/systemd/system.d/cpufreq.service new file mode 100644 index 0000000000..46c3cf0a6c --- /dev/null +++ b/packages/sysutils/systemd/system.d/cpufreq.service @@ -0,0 +1,11 @@ +[Unit] +Description=Set CPU frequency governor and its tunables +ConditionPathExists=/usr/bin/cpufreq + +[Service] +Type=oneshot +ExecStart=/usr/bin/cpufreq +RemainAfterExit=yes + +[Install] +WantedBy=basic.target diff --git a/packages/sysutils/systemd/system.d/debugconfig.service b/packages/sysutils/systemd/system.d/debugconfig.service new file mode 100644 index 0000000000..0c055fea0b --- /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.archr + +[Service] +Type=oneshot +ExecStart=/bin/sh -c 'cp /usr/share/debugconf/*.conf /run/archr/debug' +RemainAfterExit=yes + +[Install] +WantedBy=sysinit.target diff --git a/packages/sysutils/systemd/system.d/envconfig.service b/packages/sysutils/systemd/system.d/envconfig.service new file mode 100644 index 0000000000..83f3cfdfa1 --- /dev/null +++ b/packages/sysutils/systemd/system.d/envconfig.service @@ -0,0 +1,12 @@ +[Unit] +Description=Generate system-wide /etc/environment file +DefaultDependencies=no +After=systemd-tmpfiles-setup.service + +[Service] +Type=oneshot +ExecStart=/usr/bin/environment-setup +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 0000000000..911bbfa0ce --- /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/getty@tty0.service b/packages/sysutils/systemd/system.d/getty@tty0.service new file mode 100644 index 0000000000..3a91930297 --- /dev/null +++ b/packages/sysutils/systemd/system.d/getty@tty0.service @@ -0,0 +1,27 @@ +[Unit] +Description=Getty on %I +After=getty-pre.target +Before=getty.target +IgnoreOnIsolate=yes +ConditionPathExists=/dev/tty0 + +[Service] +ExecStart=-/sbin/agetty -o '-p -- \\u' --noissue --noclear --nohostname - $TERM +Type=idle +Restart=no +UtmpIdentifier=%I +StandardInput=tty +StandardOutput=tty +TTYPath=/dev/%I +TTYReset=yes +TTYVHangup=yes +TTYVTDisallocate=yes +IgnoreSIGPIPE=no +SendSIGHUP=yes +ImportCredential=agetty.* +ImportCredential=login.* +UnsetEnvironment=LANG LANGUAGE LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT LC_IDENTIFICATION + +[Install] +WantedBy=getty.target +DefaultInstance=tty1 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 0000000000..4fb809f1a1 --- /dev/null +++ b/packages/sysutils/systemd/system.d/machine-id.service @@ -0,0 +1,13 @@ +[Unit] +Description=Setup machine-id +DefaultDependencies=no +Conflicts=shutdown.target +Before=systemd-journald.service systemd-tmpfiles-setup-dev.service shutdown.target + +[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 0000000000..bc2c15947c --- /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 0000000000..911bbfa0ce --- /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 0000000000..852492e3e9 --- /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 0000000000..7a50036ce5 --- /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 0000000000..26e9b5836c --- /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 0000000000..2117d8957f --- /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 0000000000..be15677b1f --- /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/archr 0755 root root - - +d /run/archr/debug 0755 root root - - 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 0000000000..330c70f3c5 --- /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/tz/package.mk b/packages/sysutils/tz/package.mk new file mode 100644 index 0000000000..1503cd0348 --- /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="2025b" +PKG_SHA256="7e281b316b85e20c9a67289805aa2a2ee041b5a41ccf5d096af3386ba76cf9d5" +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} CFLAGS= 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 0000000000..d54d32b8bb --- /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 0000000000..b185941a2a --- /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 = /media, /var/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, noexec, nodev, noatime, fmask=0133, dmask=0022, uid=$UID, gid=$GID, utf8 +default_options_exfat = nosuid, noexec, nodev, noatime +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, fmask=0133, uid=$UID, gid=$GID +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 + + +# mount_point_mode, if present and set to a non-empty value, will cause udevil +# to set the mode (permissions) on the mount 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 privileges (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 0000000000..b489817583 --- /dev/null +++ b/packages/sysutils/udevil/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="udevil" +PKG_VERSION="f2b715d1d821e4b69b2fb0864a5a178dd67877f0" +PKG_SHA256="3351d56c553c518cb2ce7b24892a4b62d630ba4f6ebee2c3994c4be9828f0629" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/alpharde/udevil" +PKG_URL="https://github.com/alpharde/udevil/archive/${PKG_VERSION}.tar.gz" +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 + ln -sf /storage/.config/udevil.conf ${INSTALL}/etc/udevil/udevil-user-root.conf + + mkdir -p ${INSTALL}/usr/bin + cp -PR src/udevil ${INSTALL}/usr/bin + + mkdir -p ${INSTALL}/usr/sbin + echo -e '#!/bin/sh\nexec /usr/bin/mount -t ntfs3 "$@"' >${INSTALL}/usr/sbin/mount.ntfs + chmod 755 ${INSTALL}/usr/sbin/mount.ntfs +} + +post_install() { + enable_service udevil-mount@.service +} diff --git a/packages/sysutils/udevil/patches/0003-fix-update-command_interrupt-and-command_monitor_fin.patch b/packages/sysutils/udevil/patches/0003-fix-update-command_interrupt-and-command_monitor_fin.patch new file mode 100644 index 0000000000..a8c1d50f83 --- /dev/null +++ b/packages/sysutils/udevil/patches/0003-fix-update-command_interrupt-and-command_monitor_fin.patch @@ -0,0 +1,51 @@ +From 1c98aa82b0bc0f1ec37d0096c735d8ceb9e0b2b1 Mon Sep 17 00:00:00 2001 +From: Rudi Heitbaum +Date: Tue, 19 Nov 2024 22:50:46 +0000 +Subject: [PATCH] fix: update command_interrupt and command_monitor_finalize + functions to pass sigint + +This fixes compile error with gcc-15 + +/usr/include/signal.h:88:57: note: expected '__sighandler_t' {aka 'void (*)(int)'} but argument is of type 'void (*)(void)' + 88 | extern __sighandler_t signal (int __sig, __sighandler_t __handler) + | ~~~~~~~~~~~~~~~^~~~~~~~~ +../../src/udevil.c:5033:21: error: passing argument 2 of 'signal' from incompatible pointer type [-Wincompatible-pointer-types] + 5033 | signal(SIGINT, command_monitor_finalize ); + | ^~~~~~~~~~~~~~~~~~~~~~~~ + | | + | void (*)(void) +/usr/include/signal.h:88:57: note: expected '__sighandler_t' {aka 'void (*)(int)'} but argument is of type 'void (*)(void)' + 88 | extern __sighandler_t signal (int __sig, __sighandler_t __handler) + | ~~~~~~~~~~~~~~~^~~~~~~~~ +../../src/udevil.c: In function 'main': +../../src/udevil.c:5176:22: error: passing argument 2 of 'signal' from incompatible pointer type [-Wincompatible-pointer-types] + 5176 | signal( SIGTERM, command_interrupt ); + | ^~~~~~~~~~~~~~~~~ + | | + | void (*)(void) +--- + src/udevil.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/udevil.c b/src/udevil.c +index c9f03f0..d56ff70 100644 +--- a/src/udevil.c ++++ b/src/udevil.c +@@ -4950,7 +4950,7 @@ static int command_info( CommandData* data ) + return ret; + } + +-void command_monitor_finalize() ++void command_monitor_finalize(int signum) + { + //if (signal == SIGINT || signal == SIGTERM) + //printf( "\nudevil: SIGINT || SIGTERM\n"); +@@ -5068,7 +5068,7 @@ static int command_monitor() + return 1; + } + +-void command_interrupt() ++void command_interrupt(int signum) + { + if ( udev ) + { 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 0000000000..83d142c1ab --- /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 0000000000..35f99632fc --- /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*, /dev/mmc*, and /dev/nvme* +SUBSYSTEM!="block", KERNEL!="sd*|sr*|mmc*|nvme*", 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*, /dev/mmc*, and /dev/nvme* with partitions/disk and filesystems only, and /dev/sr* disks only +KERNEL=="sd*|mmc*|nvme*", 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/usbutils/package.mk b/packages/sysutils/usbutils/package.mk new file mode 100644 index 0000000000..d9bf67260c --- /dev/null +++ b/packages/sysutils/usbutils/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="usbutils" +PKG_VERSION="018" +PKG_SHA256="83f68b59b58547589c00266e82671864627593ab4362d8c807f50eea923cad93" +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 0000000000..a284ed1311 --- /dev/null +++ b/packages/sysutils/util-linux/config/swap.conf @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2022-present Team LibreELEC (https://libreelec.tv) + +# location with write access and no spaces +SWAPFILE="${HOME}/.cache/swapfile" + +# in MiB +SWAPFILESIZE="@SWAPFILESIZE@" + +# set to "yes" to enable +SWAP_ENABLED="@SWAP_ENABLED_DEFAULT@" diff --git a/packages/sysutils/util-linux/package.mk b/packages/sysutils/util-linux/package.mk new file mode 100644 index 0000000000..63a5ccf645 --- /dev/null +++ b/packages/sysutils/util-linux/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="util-linux" +PKG_VERSION="2.41" +PKG_SHA256="81ee93b3cfdfeb7d7c4090cedeba1d7bbce9141fd0b501b686b3fe475ddca4c6" +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="autotools:host gcc:host" +PKG_DEPENDS_INIT="autotools:host gcc:host" +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 \ + --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} \ + --disable-all-programs \ + --enable-libuuid \ + --enable-libblkid \ + --enable-libmount \ + --enable-libsmartcols \ + --enable-losetup \ + --enable-fsck \ + --enable-fstrim \ + --enable-blkid \ + --enable-lscpu \ + --enable-lsfd \ + --enable-mount \ + --enable-nologin" + +if [ "${LOCAL_LOGIN}" = "yes" ]; then + PKG_CONFIGURE_OPTS_TARGET+=" --enable-agetty" +fi + +if [ "${SWAP_SUPPORT}" = "yes" ]; then + PKG_CONFIGURE_OPTS_TARGET+=" --enable-swapon" +fi + +PKG_CONFIGURE_OPTS_HOST="--enable-static \ + --disable-shared \ + --enable-all-programs \ + ${UTILLINUX_CONFIG_DEFAULT} \ + --enable-uuidgen \ + --enable-libuuid" + +PKG_CONFIGURE_OPTS_INIT="${UTILLINUX_CONFIG_DEFAULT} \ + --disable-all-programs \ + --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/archr + cp -PR ${PKG_DIR}/scripts/mount-swap ${INSTALL}/usr/lib/archr + + 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 0000000000..cc82972bff --- /dev/null +++ b/packages/sysutils/util-linux/patches/util-linux-01-fix-pkgconf.patch @@ -0,0 +1,77 @@ +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 +@@ -10,9 +10,9 @@ + # (at your option) any later version. + # + 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-02-fix-gettext.patch b/packages/sysutils/util-linux/patches/util-linux-02-fix-gettext.patch new file mode 100644 index 0000000000..60ec5c88a0 --- /dev/null +++ b/packages/sysutils/util-linux/patches/util-linux-02-fix-gettext.patch @@ -0,0 +1,11 @@ +--- a/configure.ac 2025-03-18 12:50:51.818370378 +0000 ++++ b/configure.ac 2025-03-20 13:32:55.866881780 +0000 +@@ -300,7 +300,7 @@ + AC_SYS_YEAR2038_RECOMMENDED + + dnl Don't forget to maintain alternatively allowed versions in autogen.sh! +-AM_GNU_GETTEXT_VERSION([0.18.3]) ++AM_GNU_GETTEXT_VERSION([0.24]) + AM_GNU_GETTEXT([external]) + + AS_IF([test -d "$srcdir/po"], [ diff --git a/packages/sysutils/util-linux/scripts/mount-swap b/packages/sysutils/util-linux/scripts/mount-swap new file mode 100755 index 0000000000..6ecdef3891 --- /dev/null +++ b/packages/sysutils/util-linux/scripts/mount-swap @@ -0,0 +1,44 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2022-present Team LibreELEC (https://libreelec.tv) + +. /etc/swap.conf +. /etc/profile + +if [ -f /storage/.config/swap.conf ]; then + . /storage/.config/swap.conf +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}" ] && [ ! -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}" ] && [ -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 0000000000..b700b4d79f --- /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 0000000000..de22a82fe4 --- /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/archr/mount-swap create +ExecStart=/usr/lib/archr/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 0000000000..74b4005d1f --- /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_keymaps/protocols/README b/packages/sysutils/v4l-utils/config/rc_keymaps/protocols/README new file mode 100644 index 0000000000..ee1f0a3b50 --- /dev/null +++ b/packages/sysutils/v4l-utils/config/rc_keymaps/protocols/README @@ -0,0 +1,3 @@ +BPF protocol decoders user config dir + +put your BPF protocol decoders 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 0000000000..c8f6bca229 --- /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/beelink.toml b/packages/sysutils/v4l-utils/keymaps/beelink.toml new file mode 100644 index 0000000000..f8c3d844a4 --- /dev/null +++ b/packages/sysutils/v4l-utils/keymaps/beelink.toml @@ -0,0 +1,32 @@ +[[protocols]] +name = "beelink_x2" +protocol = "NEC" +[protocols.scancodes] +0x804d = "KEY_MUTE" +0x8009 = "KEY_MEDIA" +0x8011 = "KEY_AUDIO" +0x8054 = "KEY_WWW" +0x804e = "KEY_VOLUMEUP" +0x80bb = "KEY_REWIND" +0x80bd = "KEY_FORWARD" +0x8056 = "KEY_VOLUMEDOWN" +0x8053 = "KEY_HOME" +0x801b = "KEY_BACK" +0x8026 = "KEY_UP" +0x8025 = "KEY_LEFT" +0x800d = "KEY_OK" +0x8027 = "KEY_RIGHT" +0x8028 = "KEY_DOWN" +0x8049 = "KEY_MENU" +0x8030 = "KEY_NUMERIC_0" +0x8031 = "KEY_NUMERIC_1" +0x8032 = "KEY_NUMERIC_2" +0x8033 = "KEY_NUMERIC_3" +0x8034 = "KEY_NUMERIC_4" +0x8035 = "KEY_NUMERIC_5" +0x8036 = "KEY_NUMERIC_6" +0x8037 = "KEY_NUMERIC_7" +0x8038 = "KEY_NUMERIC_8" +0x8039 = "KEY_NUMERIC_9" +0x8044 = "KEY_BACKSPACE" +0x8051 = "KEY_POWER" diff --git a/packages/sysutils/v4l-utils/keymaps/cubox_i.toml b/packages/sysutils/v4l-utils/keymaps/cubox_i.toml new file mode 100644 index 0000000000..12f2b0af12 --- /dev/null +++ b/packages/sysutils/v4l-utils/keymaps/cubox_i.toml @@ -0,0 +1,13 @@ +[[protocols]] +name = "cubox_i" +protocol = "rc6" +[protocols.scancodes] +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/xbox_360.toml b/packages/sysutils/v4l-utils/keymaps/xbox_360.toml new file mode 100644 index 0000000000..9ad76abef1 --- /dev/null +++ b/packages/sysutils/v4l-utils/keymaps/xbox_360.toml @@ -0,0 +1,70 @@ +[[protocols]] +name = "Xbox 360" +protocol = "rc6" +variant = "rc6_mce" +[protocols.scancodes] +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_one.toml b/packages/sysutils/v4l-utils/keymaps/xbox_one.toml new file mode 100644 index 0000000000..d7c7114fc7 --- /dev/null +++ b/packages/sysutils/v4l-utils/keymaps/xbox_one.toml @@ -0,0 +1,37 @@ +[[protocols]] +name = "Xbox One" +protocol = "nec" +variant = "necx" +[protocols.scancodes] +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" +0x80d801 = "KEY_1" +0x80d802 = "KEY_2" +0x80d803 = "KEY_3" +0x80d804 = "KEY_4" +0x80d805 = "KEY_5" +0x80d806 = "KEY_6" +0x80d807 = "KEY_7" +0x80d808 = "KEY_8" +0x80d809 = "KEY_9" +0x80d800 = "KEY_0" +0x80d817 = "KEY_RECORD" diff --git a/packages/sysutils/v4l-utils/keymaps/xoro_hrk_7660.toml b/packages/sysutils/v4l-utils/keymaps/xoro_hrk_7660.toml new file mode 100644 index 0000000000..fd8a3224d2 --- /dev/null +++ b/packages/sysutils/v4l-utils/keymaps/xoro_hrk_7660.toml @@ -0,0 +1,44 @@ +[[protocols]] +name = "xoro_hrk_7660" +protocol = "nec" +variant = "nec" +[protocols.scancodes] +0xbf16 = "KEY_DOWN" +0xbf06 = "KEY_UP" +0xbf5a = "KEY_LEFT" +0xbf1b = "KEY_RIGHT" +0xbf0f = "KEY_NUMERIC_0" +0xbf52 = "KEY_NUMERIC_1" +0xbf50 = "KEY_NUMERIC_2" +0xbf10 = "KEY_NUMERIC_3" +0xbf56 = "KEY_NUMERIC_4" +0xbf54 = "KEY_NUMERIC_5" +0xbf14 = "KEY_NUMERIC_6" +0xbf4e = "KEY_NUMERIC_7" +0xbf4c = "KEY_NUMERIC_8" +0xbf0c = "KEY_NUMERIC_9" +0xbf01 = "KEY_VOLUMEUP" +0xbf02 = "KEY_VOLUMEDOWN" +0xbf0d = "KEY_CHANNELUP" +0xbf11 = "KEY_CHANNELDOWN" +0xbf1a = "KEY_OK" +0xbf04 = "KEY_STOP" +0xbf07 = "KEY_RECORD" +0xbf46 = "KEY_PLAY" +0xbf44 = "KEY_PAUSE" +0xbf4d = "KEY_EPG" +0xbf18 = "KEY_TEXT" +0xbf19 = "KEY_MUTE" +0xbf03 = "KEY_BLUE" +0xbf00 = "KEY_YELLOW" +0xbf42 = "KEY_RED" +0xbf40 = "KEY_GREEN" +0xbf15 = "KEY_RADIO" +0xbf59 = "KEY_POWER" +0xbf05 = "KEY_EXIT" +0xbf45 = "KEY_MENU" +0xbf08 = "KEY_PREVIOUS" +0xbf0b = "KEY_NEXT" +0xbf48 = "KEY_FASTFORWARD" +0xbf4a = "KEY_REWIND" +0xbf0e = "KEY_GOTO" \ No newline at end of file diff --git a/packages/sysutils/v4l-utils/keymaps/zotac.toml b/packages/sysutils/v4l-utils/keymaps/zotac.toml new file mode 100644 index 0000000000..cbd237d06c --- /dev/null +++ b/packages/sysutils/v4l-utils/keymaps/zotac.toml @@ -0,0 +1,48 @@ +[[protocols]] +name = "zotac" +protocol = "rc6" +variant = "rc6_mce" +[protocols.scancodes] +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 0000000000..2262816c29 --- /dev/null +++ b/packages/sysutils/v4l-utils/package.mk @@ -0,0 +1,88 @@ +# 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) + +# with 1.0.0 repeat delay is broken. test on upgrade + +PKG_NAME="v4l-utils" +PKG_VERSION="1.30.1" +PKG_SHA256="c1cf549c2ec3cf39eb5ec7bf15731349e61b26a21b5e963922db422333bae197" +PKG_LICENSE="GPL" +PKG_SITE="https://linuxtv.org/" +PKG_URL="https://linuxtv.org/downloads/v4l-utils/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain alsa-lib elfutils ir-bpf-decoders libbpf systemd zlib" +PKG_LONGDESC="Linux V4L2 and DVB API utilities and v4l libraries (libv4l)." + +PKG_MESON_OPTS_TARGET="-Dbpf=enabled \ + -Dgconv=disabled \ + -Djpeg=disabled \ + -Dqvidcap=disabled \ + -Dqv4l2=disabled \ + -Ddoxygen-doc=disabled" + +create_multi_keymap() { + local f name map + name="${1}" + shift 1 + ( + for f in "$@"; do + map="${INSTALL}/usr/lib/udev/rc_keymaps/${f}.toml" + [ -e "${map}" ] && cat "${map}" + done + ) >${INSTALL}/usr/lib/udev/rc_keymaps/${name}.toml +} + +post_makeinstall_target() { + local f keymap + + if [ ! "${DISTRO_VERSION}" == "devel" ]; then + rm ${INSTALL}/usr/bin/v4l2-compliance + fi + + cp ${PKG_BUILD}/contrib/lircd2toml.py ${INSTALL}/usr/bin/ + + rm -rf ${INSTALL}/usr/include + rm -rf ${INSTALL}/usr/lib/gconv + rm -rf ${INSTALL}/usr/lib/pkgconfig + + 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_KEYMAPS}" ]; then + create_multi_keymap libreelec_multi ${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 <>${INSTALL}/etc/rc_maps.cfg +# +# Custom LibreELEC configuration starts here +# +# use combined multi-table on MCE receivers +# * rc-rc6-mce rc6_mce.toml +* rc-rc6-mce libreelec_multi.toml +# multi-table for amlogic devices +meson-ir rc-empty libreelec_multi.toml +EOF + + fi +} diff --git a/packages/sysutils/v4l-utils/patches/v4l-utils-003-enable-bpf-without-clang.patch b/packages/sysutils/v4l-utils/patches/v4l-utils-003-enable-bpf-without-clang.patch new file mode 100644 index 0000000000..87852421b7 --- /dev/null +++ b/packages/sysutils/v4l-utils/patches/v4l-utils-003-enable-bpf-without-clang.patch @@ -0,0 +1,49 @@ +From ff65aa88a1ff3f02cc10e5a6e2af865b0c97f4fc Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +Date: Sat, 8 Feb 2020 21:42:06 +0100 +Subject: [PATCH] disable bpf decoder build and drop bpf dependency on clang + +Signed-off-by: Matthias Reichl +--- + meson.build | 2 +- + utils/keytable/meson.build | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/meson.build b/meson.build +index 233cbab0..be844f9c 100644 +--- a/meson.build ++++ b/meson.build +@@ -70,7 +70,7 @@ endif + v4l2_utils_incdir = include_directories(v4l2_utils_incdir_arr) + + prog_bash = find_program('bash') +-prog_clang = find_program('clang', required : get_option('bpf')) ++#prog_clang = find_program('clang', required : get_option('bpf')) + prog_doxygen = find_program('doxygen', required : get_option('doxygen-doc')) + prog_grep = find_program('grep') + prog_perl = find_program('perl') +diff --git a/utils/keytable/meson.build b/utils/keytable/meson.build +index 0ca08a18..fa8fbede 100644 +--- a/utils/keytable/meson.build ++++ b/utils/keytable/meson.build +@@ -21,7 +21,7 @@ ir_keytable_c_args = [ + '-DIR_KEYTABLE_USER_DIR="@0@"'.format(ir_keytable_user_dir), + ] + +-ir_bpf_enabled = prog_clang.found() and dep_libbpf.found() and dep_libelf.found() ++ir_bpf_enabled = dep_libbpf.found() and dep_libelf.found() + + if ir_bpf_enabled + ir_keytable_sources += files( +@@ -35,7 +35,7 @@ if ir_bpf_enabled + ir_keytable_c_args += [ + '-DHAVE_BPF', + ] +- subdir('bpf_protocols') ++ #subdir('bpf_protocols') + endif + + ir_keytable_incdir = [ +-- +2.34.1 + 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 0000000000..26728303b3 --- /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/wait-time-sync/package.mk b/packages/sysutils/wait-time-sync/package.mk new file mode 100644 index 0000000000..35a40c7dba --- /dev/null +++ b/packages/sysutils/wait-time-sync/package.mk @@ -0,0 +1,14 @@ +# 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="make:host gcc:host" +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 0000000000..1014a4452e --- /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 0000000000..8744e94f95 --- /dev/null +++ b/packages/sysutils/wait-time-sync/sources/wait-time-sync.c @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (C) 2020-present Team LibreELEC (https://libreelec.tv) */ + +#include +#include +#include +#include +#include +#include +#include + +#define POLL_FREQ 10 + +void usage(char *name) +{ + if (!name) + name = "wait-time-sync"; + + printf("Usage: %s [-t seconds | --timeout seconds]\n", name); + exit(2); +} + +int main(int argc, char** argv) +{ + unsigned timeout = UINT_MAX; + int rc = 0; + + if (argc == 3) + { + unsigned long val; + char *p; + + if (strcmp(argv[1], "-t") && strcmp(argv[1], "--timeout")) + usage(argv[0]); + val = strtoul(argv[2], &p, 0); + if (*p || val == 0 || val >= UINT_MAX / POLL_FREQ) + usage(argv[0]); + timeout = (unsigned)val * POLL_FREQ; + } + else if (argc != 1) + usage(argv[0]); + + for ( ; timeout; --timeout) + { + struct timex tx = {}; + + rc = adjtimex(&tx); + if (rc != TIME_ERROR) + break; + usleep(1000000U / POLL_FREQ); + } + + return rc == -1 ? errno : !timeout; +} 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 0000000000..71ca578caa --- /dev/null +++ b/packages/sysutils/wait-time-sync/system.d/wait-time-sync.service @@ -0,0 +1,27 @@ +# 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 Synchronisation +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=infinity +RemainAfterExit=yes + +[Install] +WantedBy=sysinit.target diff --git a/packages/testing/package.mk b/packages/testing/package.mk new file mode 100644 index 0000000000..50edb5b788 --- /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 0000000000..5f6142e8c5 --- /dev/null +++ b/packages/textproc/expat/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="expat" +PKG_VERSION="2.7.1" +PKG_SHA256="354552544b8f99012e5062f7d570ec77f14b412a3ff5c7d8d0dae62c0d217c30" +PKG_LICENSE="OSS" +PKG_SITE="https://libexpat.github.io" +PKG_URL="https://github.com/libexpat/libexpat/releases/download/R_${PKG_VERSION//./_}/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_HOST="cmake:host ninja:host" +PKG_DEPENDS_TARGET="cmake:host ninja:host gcc:host" +PKG_LONGDESC="Expat is an XML parser library written in C." + +PKG_CMAKE_OPTS_TARGET="-DEXPAT_BUILD_DOCS=OFF \ + -DEXPAT_BUILD_TOOLS=OFF \ + -DEXPAT_BUILD_EXAMPLES=OFF \ + -DEXPAT_BUILD_TESTS=OFF \ + -DEXPAT_SHARED_LIBS=ON" + +PKG_CMAKE_OPTS_HOST="-DEXPAT_BUILD_DOCS=OFF \ + -DEXPAT_BUILD_TOOLS=OFF \ + -DEXPAT_BUILD_EXAMPLES=OFF \ + -DEXPAT_BUILD_TESTS=OFF \ + -DEXPAT_SHARED_LIBS=ON" diff --git a/packages/textproc/itstool/package.mk b/packages/textproc/itstool/package.mk new file mode 100644 index 0000000000..32329210e4 --- /dev/null +++ b/packages/textproc/itstool/package.mk @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2020-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="itstool" +PKG_VERSION="2.0.7" +PKG_SHA256="6b9a7cd29a12bb95598f5750e8763cee78836a1a207f85b74d8b3275b27e87ca" +PKG_LICENSE="GPLv3" +PKG_SITE="http://itstool.org" +PKG_URL="http://files.itstool.org/itstool/itstool-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_HOST="toolchain libxml2:host" +PKG_LONGDESC="ITS Tool allows you to translate your XML documents with PO files." +PKG_BUILD_FLAGS="-cfg-libs:host" +PKG_TOOLCHAIN="autotools" diff --git a/packages/textproc/jsoncpp/package.mk b/packages/textproc/jsoncpp/package.mk new file mode 100644 index 0000000000..eee07679da --- /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.9.6" +PKG_SHA256="f93b6dd7ce796b13d02c108bc9f79812245a82e577581c4c9aabe57075c90ea2" +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_BUILD_FLAGS="+pic" + +PKG_MESON_OPTS_TARGET="-Dtests=false \ + --default-library static" diff --git a/packages/textproc/libiconv/package.mk b/packages/textproc/libiconv/package.mk new file mode 100644 index 0000000000..1cd7453dfe --- /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.18" +PKG_SHA256="3b08f5f4f9b4eb82f151a7040bfd6fe6c6fb922efe4b1659c66ea933276965e8" +PKG_LICENSE="GPL" +PKG_SITE="https://savannah.gnu.org/projects/libiconv/" +PKG_URL="https://mirrors.kernel.org/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 0000000000..e1b6a986da --- /dev/null +++ b/packages/textproc/libidn2/package.mk @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libidn2" +PKG_VERSION="2.3.8" +PKG_SHA256="f557911bf6171621e1f72ff35f5b1825bb35b52ed45325dcdee931e5d3c0787a" +PKG_LICENSE="LGPL3" +PKG_SITE="https://www.gnu.org/software/libidn/" +PKG_URL="https://mirrors.kernel.org/gnu/gnu/libidn/libidn2-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="autotools:host" +PKG_DEPENDS_TARGET="autotools:host gcc:host" +PKG_LONGDESC="Free software implementation of IDNA2008, Punycode and TR46." + +PKG_CONFIGURE_OPTS_COMMON="--disable-doc \ + --enable-shared \ + --disable-static" + +PKG_CONFIGURE_OPTS_HOST="${PKG_CONFIGURE_OPTS_COMMON}" +PKG_CONFIGURE_OPTS_TARGET="${PKG_CONFIGURE_OPTS_COMMON}" + +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 0000000000..5ab4d78445 --- /dev/null +++ b/packages/textproc/libxml2/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="libxml2" +PKG_VERSION="2.14.4" +PKG_SHA256="8e20c2ef2fc7965d7851e3ab3a756c3fc8b449ba47526269a9b4d7f0480550db" +PKG_LICENSE="MIT" +PKG_SITE="http://xmlsoft.org" +PKG_URL="https://gitlab.gnome.org/GNOME/${PKG_NAME}/-/archive/v${PKG_VERSION}/${PKG_NAME}-v${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_HOST="zlib:host ninja:host Python3:host" +PKG_DEPENDS_TARGET="toolchain zlib" +PKG_LONGDESC="The libxml package contains an XML library, which allows you to manipulate XML files." +PKG_TOOLCHAIN="cmake" + +PKG_CMAKE_OPTS_ALL="-DBUILD_SHARED_LIBS=ON \ + -DLIBXML2_WITH_ICONV=OFF \ + -DLIBXML2_WITH_ICU=OFF \ + -DLIBXML2_WITH_LZMA=OFF \ + -DLIBXML2_WITH_TESTS=OFF \ + -DLIBXML2_WITH_THREADS=ON \ + -DLIBXML2_WITH_ZLIB=OFF" + +PKG_CMAKE_OPTS_HOST="${PKG_CMAKE_OPTS_ALL} \ + -DLIBXML2_WITH_PYTHON=ON" + +PKG_CMAKE_OPTS_TARGET="${PKG_CMAKE_OPTS_ALL} \ + -DLIBXML2_WITH_PYTHON=OFF" + +post_makeinstall_target() { + sed -e "s:\(['= ]\)/usr:\\1${SYSROOT_PREFIX}/usr:g" -i ${SYSROOT_PREFIX}/usr/bin/xml2-config + + rm -rf ${INSTALL}/usr/bin + rm -rf ${INSTALL}/usr/lib/xml2Conf.sh +} diff --git a/packages/textproc/libxml2/patches/libxml2-0001-Revert-cmake-Fix-Python-installation.patch b/packages/textproc/libxml2/patches/libxml2-0001-Revert-cmake-Fix-Python-installation.patch new file mode 100644 index 0000000000..03a9b32add --- /dev/null +++ b/packages/textproc/libxml2/patches/libxml2-0001-Revert-cmake-Fix-Python-installation.patch @@ -0,0 +1,28 @@ +From fa437b9bccf42c194740fd22cb19f60963e6b6c5 Mon Sep 17 00:00:00 2001 +From: Rudi Heitbaum +Date: Tue, 16 Jan 2024 01:53:17 +0000 +Subject: [PATCH] Revert "cmake: Fix Python installation" + +This reverts commit 02e12371964ed10c2c84ebb49760bc11b34913e1. +--- + CMakeLists.txt | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index e68f3684..c0661a0e 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -68,9 +68,7 @@ if(LIBXML2_WITH_PYTHON) + check_include_files(unistd.h HAVE_UNISTD_H) + check_symbol_exists(F_GETFL fcntl.h HAVE_F_GETFL) + find_package(Python COMPONENTS Interpreter Development REQUIRED) +- #set(LIBXML2_PYTHON_INSTALL_DIR ${Python_SITEARCH} CACHE PATH "Python bindings install directory") +- set(LIBXML2_PYTHON_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/python" +- CACHE PATH "Python bindings install directory") ++ set(LIBXML2_PYTHON_INSTALL_DIR ${Python_SITEARCH} CACHE PATH "Python bindings install directory") + endif() + + foreach(VARIABLE IN ITEMS WITH_AUTOMATA WITH_C14N WITH_CATALOG WITH_DEBUG WITH_EXPR WITH_HTML WITH_HTTP WITH_ICONV WITH_ICU WITH_ISO8859X WITH_LEGACY WITH_LZMA WITH_MODULES WITH_OUTPUT WITH_PATTERN WITH_PUSH WITH_READER WITH_REGEXPS WITH_SAX1 WITH_SCHEMAS WITH_SCHEMATRON WITH_THREADS WITH_THREAD_ALLOC WITH_TREE WITH_UNICODE WITH_VALID WITH_WRITER WITH_XINCLUDE WITH_XPATH WITH_XPTR WITH_ZLIB) +-- +2.34.1 + diff --git a/packages/textproc/libxslt/package.mk b/packages/textproc/libxslt/package.mk new file mode 100644 index 0000000000..58f7308036 --- /dev/null +++ b/packages/textproc/libxslt/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="libxslt" +PKG_VERSION="1.1.43" +PKG_SHA256="5a3d6b383ca5afc235b171118e90f5ff6aa27e9fea3303065231a6d403f0183a" +PKG_LICENSE="MIT" +PKG_SITE="http://xmlsoft.org/xslt/" +PKG_URL="https://download.gnome.org/sources/libxslt/$(get_pkg_version_maj_min)/libxslt-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_HOST="libxml2:host" +PKG_DEPENDS_TARGET="toolchain libxml2" +PKG_LONGDESC="A XSLT C library." +PKG_BUILD_FLAGS="+pic" + +PKG_CMAKE_OPTS_ALL="-DBUILD_SHARED_LIBS=ON \ + -DLIBXSLT_WITH_DEBUGGER=OFF \ + -DLIBXSLT_WITH_CRYPTO=OFF \ + -DLIBXSLT_WITH_MODULES=OFF \ + -DLIBXSLT_WITH_PROFILER=ON \ + -DLIBXSLT_WITH_PYTHON=OFF \ + -DLIBXSLT_WITH_TESTS=OFF \ + -DLIBXSLT_WITH_THREADS=ON \ + -DLIBXSLT_WITH_XSLT_DEBUG=OFF" + +PKG_CMAKE_OPTS_HOST=${PKG_CMAKE_OPTS_ALL} + +PKG_CMAKE_OPTS_TARGET=${PKG_CMAKE_OPTS_ALL} + +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 0000000000..4f18be1791 --- /dev/null +++ b/packages/textproc/nlohmann-json/package.mk @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="nlohmann-json" +PKG_VERSION="3.12.0" +PKG_SHA256="4b92eb0c06d10683f7447ce9406cb97cd4b453be18d7279320f7b2f025c10187" +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++" +# Meson does not provide nlohmann_json*.cmake files which some projects rely on +PKG_TOOLCHAIN="cmake" + +PKG_CMAKE_OPTS_TARGET="-DJSON_BuildTests=OFF" diff --git a/packages/textproc/pugixml/package.mk b/packages/textproc/pugixml/package.mk new file mode 100644 index 0000000000..20d505f893 --- /dev/null +++ b/packages/textproc/pugixml/package.mk @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="pugixml" +PKG_VERSION="1.15" +PKG_SHA256="b39647064d9e28297a34278bfb897092bf33b7c487906ddfc094c9e8868bddcb" +PKG_LICENSE="MIT" +PKG_SITE="https://pugixml.org/" +PKG_URL="https://github.com/zeux/pugixml/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="toolchain:host" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Light-weight, simple and fast XML parser for C++ with XPath support." +PKG_BUILD_FLAGS="+pic" diff --git a/packages/textproc/tinyxml/package.mk b/packages/textproc/tinyxml/package.mk new file mode 100644 index 0000000000..36c3fe67d0 --- /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" +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}_2.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 0000000000..1ed3bae6bf --- /dev/null +++ b/packages/textproc/tinyxml2/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="tinyxml2" +PKG_VERSION="11.0.0" +PKG_SHA256="5556deb5081fb246ee92afae73efd943c889cef0cafea92b0b82422d6a18f289" +PKG_LICENSE="zlib" +PKG_SITE="http://www.grinninglizard.com/tinyxml2/index.html" +PKG_URL="https://github.com/leethomason/tinyxml2/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="TinyXML2 is a simple, small, C++ XML parser." + +PKG_MESON_OPTS_TARGET="-Ddefault_library=static \ + -Dtests=false" diff --git a/packages/textproc/xmlstarlet/package.mk b/packages/textproc/xmlstarlet/package.mk new file mode 100644 index 0000000000..d311cc5d57 --- /dev/null +++ b/packages/textproc/xmlstarlet/package.mk @@ -0,0 +1,43 @@ +# 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="https://downloads.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_BUILD_FLAGS="-cfg-libs -cfg-libs:host" + +pre_configure_host() { + export CFLAGS="${CFLAGS} -Wno-error -Wno-pointer-sign -Wno-incompatible-pointer-types" +} + +PKG_CONFIGURE_OPTS_HOST=" ac_cv_func_malloc_0_nonnull=yes \ + ac_cv_func_realloc_0_nonnull=yes \ + 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 \ + 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 0000000000..24b187f2ac --- /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/textproc/xmlstarlet/patches/xmlstarlet-0246-fix-compile-with-libxml-2-12-0.patch b/packages/textproc/xmlstarlet/patches/xmlstarlet-0246-fix-compile-with-libxml-2-12-0.patch new file mode 100644 index 0000000000..36abe641d0 --- /dev/null +++ b/packages/textproc/xmlstarlet/patches/xmlstarlet-0246-fix-compile-with-libxml-2-12-0.patch @@ -0,0 +1,66 @@ +From ac9f4ca6e3f2d4cfd4a3a8f08d09be81af8fdf92 Mon Sep 17 00:00:00 2001 +From: Rudi Heitbaum +Date: Tue, 21 Nov 2023 09:14:53 +0000 +Subject: [PATCH 1/2] xmlCleanupGlobals is a noop and not available in libxml2 + 2.12.0 + +--- + src/xml_edit.c | 2 -- + 1 files changed, 2 deletions(-) + +diff --git a/src/xml_edit.c b/src/xml_edit.c +index e199178e..85a0a9f4 100644 +--- a/src/xml_edit.c ++++ b/src/xml_edit.c +@@ -558,7 +558,6 @@ edOutput(const char* filename, const XmlEdAction* ops, int ops_count, + { + cleanupNSArr(ns_arr); + xmlCleanupParser(); +- xmlCleanupGlobals(); + exit(EXIT_BAD_FILE); + } + +@@ -752,6 +751,5 @@ edMain(int argc, char **argv) + xmlFree(ops); + cleanupNSArr(ns_arr); + xmlCleanupParser(); +- xmlCleanupGlobals(); + return 0; + } + +From 3c0eb2cf04848e902228bb147471c73803354fa8 Mon Sep 17 00:00:00 2001 +From: Rudi Heitbaum +Date: Tue, 21 Nov 2023 09:32:02 +0000 +Subject: [PATCH 2/2] missing headers since libxml2 2.12.0 + +--- + src/trans.c | 3 +++ + src/xml_format.c | 1 + + 2 files changed, 4 insertions(+) + +diff --git a/src/trans.c b/src/trans.c +index 3603436f..cb2b0709 100644 +--- a/src/trans.c ++++ b/src/trans.c +@@ -1,6 +1,9 @@ + /* $Id: trans.c,v 1.19 2004/11/22 02:28:21 mgrouch Exp $ */ + + #include ++ ++#include ++ + #include "trans.h" + #include "xmlstar.h" + +diff --git a/src/xml_format.c b/src/xml_format.c +index e9da4df8..32a5f3d6 100644 +--- a/src/xml_format.c ++++ b/src/xml_format.c +@@ -35,6 +35,7 @@ THE SOFTWARE. + #include + #include + #include ++#include + #include + #include + #include diff --git a/packages/textproc/xmlstarlet/patches/xmlstarlet-0900-fix-compile-with-libxml-2-14-0.patch b/packages/textproc/xmlstarlet/patches/xmlstarlet-0900-fix-compile-with-libxml-2-14-0.patch new file mode 100644 index 0000000000..209bdf56b3 --- /dev/null +++ b/packages/textproc/xmlstarlet/patches/xmlstarlet-0900-fix-compile-with-libxml-2-14-0.patch @@ -0,0 +1,26 @@ +From 10684eea54a2c3b0b3738dfd8d70014f54e8e282 Mon Sep 17 00:00:00 2001 +From: Rudi Heitbaum +Date: Sat, 29 Mar 2025 02:23:34 +1100 +Subject: [PATCH] Fix build with libxml2-2.14.0 + +--- + src/xml_pyx.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/src/xml_pyx.c b/src/xml_pyx.c +index ab295f12..e5ec64f1 100644 +--- a/src/xml_pyx.c ++++ b/src/xml_pyx.c +@@ -21,6 +21,12 @@ + + #include "xmlstar.h" + ++#if __GNUC__ * 100 + __GNUC_MINOR__ >= 207 ++ #define ATTRIBUTE_UNUSED __attribute__((unused)) ++#else ++ #define ATTRIBUTE_UNUSED ++#endif ++ + /** + * Output newline and tab characters as escapes + * Required both for attribute values and character data (#PCDATA) diff --git a/packages/tools/atf/package.mk b/packages/tools/atf/package.mk new file mode 100644 index 0000000000..c550836eea --- /dev/null +++ b/packages/tools/atf/package.mk @@ -0,0 +1,37 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC + +PKG_NAME="atf" +PKG_VERSION="2.13.0" +PKG_SHA256="28bc15daeeed000ecd30819ecc4851bf9ffc2d33e1d4553a71985c17f47a999e" +PKG_ARCH="arm aarch64" +PKG_LICENSE="BSD-3c" +PKG_SITE="https://github.com/ARM-software/arm-trusted-firmware" +PKG_URL="https://github.com/TrustedFirmware-A/trusted-firmware-a/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +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" + +[ -n "${KERNEL_TOOLCHAIN}" ] && PKG_DEPENDS_TARGET+=" gcc-${KERNEL_TOOLCHAIN}:host" + +if [ "${ATF_PLATFORM}" = "rk3399" ]; then + PKG_DEPENDS_TARGET+=" gcc-arm-none-eabi:host" + export M0_CROSS_COMPILE="${TOOLCHAIN}/bin/arm-none-eabi-" +fi + +make_target() { + # As of atf 2.11.0 - the supported compile for .S is gcc (not as.) + unset AR AS CC CPP CXX LD NM OBJCOPY OBJDUMP STRIP RANLIB + unset CPPFLAGS CFLAGS CXXFLAGS LDFLAGS + if [ "${ATF_PLATFORM}" = "imx8mq" ]; then + CROSS_COMPILE="${TARGET_KERNEL_PREFIX}" make PLAT=${ATF_PLATFORM} LOG_LEVEL=0 bl31 + else + # as of atf 2.12.0 - sun50i_a64 builds use LTO, include -ffat-lto-objects to support this + CROSS_COMPILE="${TARGET_KERNEL_PREFIX}" CFLAGS="-ffat-lto-objects" make PLAT=${ATF_PLATFORM} bl31 + fi +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/share/bootloader + cp -a build/${ATF_PLATFORM}/release/${ATF_BL31_BINARY:-bl31.bin} ${INSTALL}/usr/share/bootloader +} diff --git a/packages/tools/dt-overlays/package.mk b/packages/tools/dt-overlays/package.mk new file mode 100644 index 0000000000..d79af586d0 --- /dev/null +++ b/packages/tools/dt-overlays/package.mk @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="dt-overlays" +PKG_VERSION="4352d87db6e85d285673359e80cce87d5e025c64" +PKG_SHA256="754a0c37a41f8e5d9d179eb1df40b84eb48c0a505a37e39fed5f1ceb35e8e120" +PKG_LICENSE="GPLv2+ or MIT" +PKG_SITE="https://github.com/LibreELEC/dt-overlays" +PKG_URL="https://github.com/LibreELEC/dt-overlays/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="dtc:host" +PKG_LONGDESC="The Device Tree Overlays" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/share/bootloader/overlays + cp -p overlays/*/*.dtbo ${INSTALL}/usr/share/bootloader/overlays +} diff --git a/packages/tools/dtc/package.mk b/packages/tools/dtc/package.mk new file mode 100644 index 0000000000..36f0e26886 --- /dev/null +++ b/packages/tools/dtc/package.mk @@ -0,0 +1,51 @@ +# 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.7.2" +PKG_SHA256="92d8ca769805ae1f176204230438fe52808f4e1c7944053c9eec0e649b237539" +PKG_LICENSE="GPL" +PKG_SITE="https://git.kernel.org/pub/scm/utils/dtc/dtc.git/" +PKG_URL="https://www.kernel.org/pub/software/utils/dtc/dtc-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_HOST="make:host flex:host ninja:host" +PKG_DEPENDS_TARGET="make:host gcc:host ninja:host" +PKG_LONGDESC="The Device Tree Compiler" +PKG_TOOLCHAIN="make" + +PKG_MAKE_OPTS_TARGET="dtc fdtput fdtget libfdt" +PKG_MAKE_OPTS_HOST="dtc libfdt" + +pre_make_host() { + mkdir -p ${PKG_BUILD}/.${HOST_NAME} + cp -a ${PKG_BUILD}/* ${PKG_BUILD}/.${HOST_NAME} + + cd ${PKG_BUILD}/.${HOST_NAME} +} + +makeinstall_host() { + mkdir -p ${TOOLCHAIN}/bin + cp -P ${PKG_BUILD}/.${HOST_NAME}/dtc ${TOOLCHAIN}/bin + mkdir -p ${TOOLCHAIN}/lib + cp -P ${PKG_BUILD}/.${HOST_NAME}/libfdt/libfdt.so* ${TOOLCHAIN}/lib +} + +pre_make_target() { + mkdir -p ${PKG_BUILD}/.${TARGET_NAME} + cp -a ${PKG_BUILD}/* ${PKG_BUILD}/.${TARGET_NAME} + + cd ${PKG_BUILD}/.${TARGET_NAME} +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp -P ${PKG_BUILD}/.${TARGET_NAME}/dtc ${INSTALL}/usr/bin + cp -P ${PKG_BUILD}/.${TARGET_NAME}/fdtput ${INSTALL}/usr/bin/ + cp -P ${PKG_BUILD}/.${TARGET_NAME}/fdtget ${INSTALL}/usr/bin/ + mkdir -p ${INSTALL}/usr/lib + cp -P ${PKG_BUILD}/.${TARGET_NAME}/libfdt/libfdt.so* ${INSTALL}/usr/lib/ + mkdir -p ${SYSROOT_PREFIX}/usr/lib + cp -P ${PKG_BUILD}/.${TARGET_NAME}/libfdt/libfdt.so* ${SYSROOT_PREFIX}/usr/lib/ + mkdir -p ${SYSROOT_PREFIX}/usr/include + cp -P ${PKG_BUILD}/.${TARGET_NAME}/libfdt/*.h ${SYSROOT_PREFIX}/usr/include/ +} diff --git a/packages/tools/emmctool/package.mk b/packages/tools/emmctool/package.mk new file mode 100644 index 0000000000..e2a00c03a4 --- /dev/null +++ b/packages/tools/emmctool/package.mk @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="emmctool" +PKG_VERSION="1.0" +PKG_LICENSE="GPLv2" +PKG_LONGDESC="emmctool: simple tool for writing LibreELEC images to emmc on supported box/board devices" +PKG_TOOLCHAIN="manual" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp ${PKG_DIR}/scripts/emmctool ${INSTALL}/usr/bin +} diff --git a/packages/tools/emmctool/scripts/emmctool b/packages/tools/emmctool/scripts/emmctool new file mode 100755 index 0000000000..0cc5f04001 --- /dev/null +++ b/packages/tools/emmctool/scripts/emmctool @@ -0,0 +1,259 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +# ** !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!! ** +# This script is not supported on generic box devices. If you choose to +# modify it to run on other hardware and you brick your device you will +# receive no support to restore your device. You have been warned! + +do_backup() { + do_umount + echo "info: compressing ${EMMC} to ${2}, this will take time" + dd if="${EMMC}" | gzip >of="${2}" + echo "info: compressing completed" +} + +do_detect() { + # used on LibreComputer LePotato/LaFrite where pre-formatted modules + # must be attached after boot (LibreComputer supports this) else the + # device always boots to the pre-installed OS on the module. + echo "info: rebinding d0074000.mmc" + echo -n d0074000.mmc >/sys/bus/platform/drivers/meson-gx-mmc/unbind + echo -n d0074000.mmc >/sys/bus/platform/drivers/meson-gx-mmc/bind + sleep 1 + parted -s "${EMMC}" print +} + +do_info() { + BOOTINFO=$(dd if="${BOOT}" count=2048 2>/dev/null | strings | grep -e '^U-Boot ' | awk '{print $2}') + EMMCINFO=$(dd if="${EMMC}" count=2048 2>/dev/null | strings | grep -e '^U-Boot ' | awk '{print $2}') + echo "" + if [ -n "${BOOTINFO}" ]; then + echo "info: boot device is $BOOT, U-boot version is ${BOOTINFO}" + else + echo "info: boot device is $BOOT" + fi + if [ -n "${EMMCINFO}" ]; then + echo "info: emmc device is $EMMC, U-boot version is ${EMMCINFO}" + else + echo "info: emmc device is $EMMC" + fi + echo "" + parted -s "${EMMC}" print + echo "" +} + +do_labels() { + if [ -n "${2}" ] && [ -n "${3}" ]; then + BOOTLABEL=$(echo "${2}" | awk 'BEGIN { getline; print toupper($0) }') + DISKLABEL=$(echo "${3}" | awk 'BEGIN { getline; print toupper($0) }') + else + BOOTLABEL="BOOT" + DISKLABEL="DISK" + fi + echo "info: using boot=LABEL=${BOOTLABEL} and disk=LABEL=${DISKLABEL}" + do_umount + echo "info: changing label values on partitions" + fatlabel "${EMMC}p1" "${BOOTLABEL}" + e2label "${EMMC}p2" "${DISKLABEL}" + sleep 1 + echo "info: remounting ${EMMC}p1 to /var/media/${BOOTLABEL}" + mkdir -p "/var/media/${BOOTLABEL}" + mount "${EMMC}p1" "/var/media/${BOOTLABEL}" + echo "info: remounting ${EMMC}p2 to /var/media/${DISKLABEL}" + mkdir -p "/var/media/${DISKLABEL}" + mount "${EMMC}p2" "/var/media/${DISKLABEL}" + sleep 1 + echo "info: changing label values in extlinux.conf" + sed -i "s/boot=LABEL=\w*/boot=LABEL=${BOOTLABEL}/g" "/var/media/${BOOTLABEL}/extlinux/extlinux.conf" + sed -i "s/disk=LABEL=\w*/disk=LABEL=${DISKLABEL}/g" "/var/media/${BOOTLABEL}/extlinux/extlinux.conf" + sleep 1 + echo "" + blkid | grep "${EMMC}p" + echo "" + cat "/var/media/${BOOTLABEL}/extlinux/extlinux.conf" + echo "" +} + +do_resize() { + if [ -z "${DISKLABEL}" ]; then + DISKLABEL=$(blkid | grep "${EMMC}"p2 | awk -F'"' '{print $2}') + fi + do_umount + echo "info: resizing partition ${EMMC}p2 to 100%" + parted -s -m "${EMMC}" resizepart 2 100% || parted -s -m "${EMMC}" resizepart 2 yes 100% + sleep 5 + do_umount + echo "info: checking filesystem" + e2fsck -f "${EMMC}p2" + sleep 1 + echo "info: resizing filesystem" + resize2fs "${EMMC}p2" + sync + sleep 1 + echo "info: remounting ${EMMC}p2 to /var/media/${DISKLABEL}" + mkdir -p "/var/media/${DISKLABEL}" + mount "${EMMC}p2" "/var/media/${DISKLABEL}" + sleep 1 + if [ -f "/var/media/${DISKLABEL}/.please_resize_me" ]; then + rm "/var/media/${DISKLABEL}/.please_resize_me" + fi + parted -s "${EMMC}" print +} + +do_storage() { + if [ -n "${2}" ]; then + DISKLABEL=$(echo "${2}" | awk 'BEGIN { getline; print toupper($0) }') + else + DISKLABEL="DISK" + fi + do_umount + echo "info: converting emmc for /storage use" + parted -s "${EMMC}" mklabel gpt + parted -s "${EMMC}" -a min unit s mkpart EMMC_STORAGE ext4 34 100% + sleep 1 + mkfs.ext4 "${EMMC}p1" + sleep 1 + e2label "${EMMC}p1" EMMC_STORAGE + echo "info: changing label values in extlinux.conf" + mount -o remount,rw /flash + sleep 1 + sed -i "s/disk=LABEL=\w*/disk=LABEL=${DISKLABEL}/g" "/flash/extlinux/extlinux.conf" + mount -o remount,ro /flash + sleep 1 + echo "" + blkid | grep "${EMMC}p" + echo "" + cat "/flash/extlinux/extlinux.conf" + echo "" +} + +do_umount() { + for mount in $(grep "${EMMC}" /proc/mounts | awk '{print $1}'); do + echo "info: unmounting $mount" + umount -f "$mount" + sleep 2 + done +} + +do_writeprotect() { + echo "info: disabling emmc write protection" + echo 0 >"/sys/block/${EMMC}boot0/force_ro" + echo 0 >"/sys/block/${EMMC}boot1/force_ro" +} + +do_write() { + do_umount + + case $(dtname) in + radxa,zero*) + do_writeprotect + ;; + esac + + if [ -e "${2}" ]; then + case "${2}" in + *box.img.gz | *box.img) + echo "error: ${2} is not a bootable image, aborting!" + exit 1 + ;; + *.img.gz) + echo "info: writing ${2} to ${EMMC}" + gunzip -c "${2}" | dd of="${EMMC}" bs=1M + ;; + *.img) + echo "info: writing ${2} to ${EMMC}" + dd if="${2}" of="${EMMC}" bs=1M + ;; + *) + echo "error: ${2} is not a valid image file!" + exit 1 + ;; + esac + else + echo "error: ${2} not found!" + exit 1 + fi +} + +do_zero() { + do_umount + echo "info: zeroing ${EMMC}, be patient, this will take time" + dd if="/dev/zero" of="${EMMC}" bs=1M + echo "info: zeroing complete" +} + +do_help() { + echo "" + echo "usage: emmctool (w)rite : write .img/.img.gz to the eMMC module" + echo " (b)backup : dump the emmc partition to .img.gz file" + echo " (d)etect : detect an eMMC module attached after boot" + echo " (i)nfo : show info about the eMMC module" + echo " (l)abel : change eMMC disk labels to " + echo " (r)esize : resize the storage partition to 100%" + echo " (s)storage : convert emmc for use as /storage (boot from sdcard)" + echo " (z)ero : zero (erase/wipe) the eMMC module" + echo " (h)elp : displays this help message" + echo "" +} + +BOOT=$(grep /flash /proc/mounts | awk '{print $1}' | sed 's/p[012]//g') +EMMC=$(find /dev -name "mmcblk*rpmb" | sed 's/rpmb//g' | head -n 1) + +if [ -z "${EMMC}" ]; then + echo "error: no emmc module detected!" + exit 1 +fi + +case $(dtname) in + azw* | bananapi* | friendlyarm* | hardkernel* | khadas* | libretech* | radxa* | wetek*) + if [ "${BOOT}" = "${EMMC}" ]; then + do_info + echo "Your device is booted from the eMMC module!" + echo "" + exit 1 + fi + ;; + *) + echo "Your device is not supported!" + echo "" + exit 1 + ;; +esac + +case "${1}" in + backup) + do_backup "$@" + ;; + detect | d) + do_detect + ;; + info | i) + do_info + ;; + labels | l) + do_labels "$@" + ;; + resize | r) + do_resize + ;; + storage | s) + do_storage "$@" + ;; + write | w) + do_write "$@" + do_resize + do_labels + ;; + zero | z) + do_zero + ;; + *) + do_info + do_help + ;; +esac + +exit diff --git a/packages/tools/flashrom/package.mk b/packages/tools/flashrom/package.mk new file mode 100644 index 0000000000..d0621c6aa0 --- /dev/null +++ b/packages/tools/flashrom/package.mk @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="flashrom" +PKG_VERSION="1.5.1" +PKG_SHA256="1f934b076ed49eace203655ec249fc7861a6b8e87fe4aef732e47b6e485b6293" +PKG_LICENSE="GPL" +PKG_SITE="https://www.flashrom.org" +PKG_URL="https://download.flashrom.org/releases/${PKG_NAME}-v${PKG_VERSION}.tar.xz" +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_MESON_OPTS_TARGET="--wrap-mode=nodownload \ + -Dprogrammer=dummy,serprog,buspirate_spi,pony_spi,linux_mtd,linux_spi" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/sbin + cp flashrom ${INSTALL}/usr/sbin +} diff --git a/packages/tools/hdparm/package.mk b/packages/tools/hdparm/package.mk new file mode 100644 index 0000000000..36d2a0b3fc --- /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.65" +PKG_SHA256="d14929f910d060932e717e9382425d47c2e7144235a53713d55a94f7de535a4b" +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 0000000000..7fb69d971c --- /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 0000000000..eb6c8b38bb --- /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 0000000000..7f0fd56e67 --- /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 0000000000..dc0516be08 --- /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 0000000000..9967cbf89f --- /dev/null +++ b/packages/tools/installer/scripts/installer @@ -0,0 +1,505 @@ +#!/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 specified 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 2>>$LOGFILE + + 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/$IMAGE_KERNEL" $TMPDIR/part1/KERNEL >> $LOGFILE 2>&1 + + msg_progress_install "65" "Installing System" + cp "/flash/$IMAGE_SYSTEM" $TMPDIR/part1/SYSTEM >> $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="@DISTRONAME@" + +menuentry "@DISTRONAME@" { + 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" + +IMAGE_KERNEL="KERNEL" +IMAGE_SYSTEM="SYSTEM" +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}" + ;; + esac +done + +# 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 0000000000..bcf469d3a1 --- /dev/null +++ b/packages/tools/installer/system.d/installer.service @@ -0,0 +1,18 @@ +[Unit] +Description=Kodi 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 0000000000..cd1cb7f7f2 --- /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/mtools/package.mk b/packages/tools/mtools/package.mk new file mode 100644 index 0000000000..6e82bdb3d8 --- /dev/null +++ b/packages/tools/mtools/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="mtools" +PKG_VERSION="4.0.49" +PKG_SHA256="6fe5193583d6e7c59da75e63d7234f76c0b07caf33b103894f46f66a871ffc9f" +PKG_LICENSE="GPL" +PKG_SITE="http://www.gnu.org/software/mtools/" +PKG_URL="https://mirrors.kernel.org/gnu/${PKG_NAME}/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_HOST="autotools:host" +PKG_LONGDESC="mtools: A collection of utilities to access MS-DOS disks" +PKG_TOOLCHAIN="autotools" +PKG_BUILD_FLAGS="-cfg-libs:host" 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 0000000000..ee3f5815a3 --- /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 2025-02-05 12:30:43.000000000 +0000 ++++ b/Makefile.in 2025-02-23 04:28:25.663710133 +0000 +@@ -226,8 +226,8 @@ + uninstall-info: + cd $(DESTDIR)$(infodir) && rm -f mtools.info* + +-install: $(DESTDIR)$(bindir)/mtools$(EXEEXT) @BINFLOPPYD@ install-man install-links \ +- $(DESTDIR)$(bindir)/mkmanifest$(EXEEXT) install-scripts install-info ++install: $(DESTDIR)$(bindir)/mtools$(EXEEXT) install-links \ ++ $(DESTDIR)$(bindir)/mkmanifest$(EXEEXT) 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 0000000000..7fa0d6cc71 --- /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 0000000000..9290d4a80f --- /dev/null +++ b/packages/tools/nano/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="nano" +PKG_VERSION="8.5" +PKG_SHA256="000b011d339c141af9646d43288f54325ff5c6e8d39d6e482b787bbc6654c26a" +PKG_LICENSE="GPL" +PKG_SITE="https://www.nano-editor.org/" +PKG_URL="https://www.nano-editor.org/dist/v${PKG_VERSION%%.*}/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain ncurses" +PKG_LONGDESC="Nano is an enhanced clone of the Pico text editor." +PKG_BUILD_FLAGS="-cfg-libs" + +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 + + PKG_FILE_LIST="css html java javascript json php python sh xml" + for PKG_FILE_TYPES in ${PKG_FILE_LIST}; do + cp -a ${PKG_BUILD}/syntax/${PKG_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 0000000000..e5fddf678a --- /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 0000000000..6a95051d26 --- /dev/null +++ b/packages/tools/newt/package.mk @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="newt" +PKG_VERSION="0.52.25" +PKG_SHA256="ef0ca9ee27850d1a5c863bb7ff9aa08096c9ed312ece9087b30f3a426828de82" +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_BUILD_FLAGS="-cfg-libs" + +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 0000000000..f3cad5bef1 --- /dev/null +++ b/packages/tools/plymouth-lite/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="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 gcc:init libpng" +PKG_LONGDESC="Boot splash screen based on Fedora's Plymouth code" + +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 +} 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 0000000000..f9baa38536 --- /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 0000000000..cf5a08ac95 --- /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 0000000000..fc69b27811 --- /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 0000000000..4bebf11213 --- /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 0000000000..a1110aaaf8 --- /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 0000000000..d1b0ee88c6 --- /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 0000000000..e94a1f9160 --- /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 0000000000..e9b360ccae --- /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 0000000000..b450d2801a --- /dev/null +++ b/packages/tools/procps-ng/package.mk @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="procps-ng" +PKG_VERSION="4.0.5" +PKG_SHA256="7e4b385e8f3e426089f3bb04e3bf150c710b875bd005474f034486b2379ce221" +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="src/free src/top/top library/libproc2.la library/libproc2.pc" + +PKG_MAKEINSTALL_OPTS_TARGET="install-libLTLIBRARIES install-pkgconfigDATA install-library_libproc2_la_includeHEADERS" + +pre_configure_target() { + sed -i -e "s/UNKNOWN/${PKG_VERSION}/" ../configure +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp -P ${PKG_BUILD}/.${TARGET_NAME}/src/free ${INSTALL}/usr/bin + cp -P ${PKG_BUILD}/.${TARGET_NAME}/src/top/top ${INSTALL}/usr/bin + + make DESTDIR=${SYSROOT_PREFIX} -j1 ${PKG_MAKEINSTALL_OPTS_TARGET} + + sed 's@proc/misc.h@procps/misc.h@' \ + ${PKG_BUILD}/library/include/readproc.h \ + >${SYSROOT_PREFIX}/usr/include/libproc2/readproc.h +} diff --git a/packages/tools/qemu/package.mk b/packages/tools/qemu/package.mk new file mode 100644 index 0000000000..e51b9085f8 --- /dev/null +++ b/packages/tools/qemu/package.mk @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="qemu" +PKG_VERSION="10.0.2" +PKG_SHA256="ef786f2398cb5184600f69aef4d5d691efd44576a3cff4126d38d4c6fec87759" +PKG_LICENSE="GPL" +PKG_SITE="https://www.qemu.org" +PKG_URL="https://download.qemu.org/qemu-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_HOST="toolchain:host glib:host pixman:host Python3:host zlib:host" +PKG_LONGDESC="QEMU is a generic and open source machine emulator and virtualizer." +PKG_TOOLCHAIN="configure" + +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 \ + --sysconfdir=${TOOLCHAIN}/etc \ + --enable-tools \ + --enable-malloc=system \ + --disable-attr \ + --disable-auth-pam \ + --disable-install-blobs \ + --disable-capstone \ + --disable-curl \ + --disable-debug-info \ + --disable-debug-mutex \ + --disable-debug-tcg \ + --disable-docs \ + --disable-gcrypt \ + --disable-gnutls \ + --disable-system \ + --disable-user \ + --disable-vnc \ + --disable-werror \ + --disable-xkbcommon \ + --disable-zstd" + + export DONT_BUILD_LEGACY_PYC=1 +} + +makeinstall_host() { + mkdir -p ${TOOLCHAIN}/bin + cp ${PKG_BUILD}/.${HOST_NAME}/qemu-img ${TOOLCHAIN}/bin +} diff --git a/packages/tools/rkbin/package.mk b/packages/tools/rkbin/package.mk new file mode 100644 index 0000000000..386a0b8ed2 --- /dev/null +++ b/packages/tools/rkbin/package.mk @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="rkbin" +PKG_VERSION="b0c100f1a260d807df450019774993c761beb79d" +PKG_SHA256="c6ebf8ab556e071e3b067540e95aecff650143f0c97e129cd40c837a4f11a881" +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/syslinux/package.mk b/packages/tools/syslinux/package.mk new file mode 100644 index 0000000000..def5418dd3 --- /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" +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 0000000000..a39019e610 --- /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/syslinux/patches/syslinux-0002-fix-build-with-glibc_2.36.patch b/packages/tools/syslinux/patches/syslinux-0002-fix-build-with-glibc_2.36.patch new file mode 100644 index 0000000000..5bab310449 --- /dev/null +++ b/packages/tools/syslinux/patches/syslinux-0002-fix-build-with-glibc_2.36.patch @@ -0,0 +1,17 @@ +--- a/libinstaller/linuxioctl.h 2022-07-17 12:45:43.459729359 +0000 ++++ b/libinstaller/linuxioctl.h 2022-07-17 12:58:50.204815753 +0000 +@@ -16,7 +16,13 @@ + #include /* Floppy geometry */ + #include /* Hard disk geometry */ + +-#include /* FIGETBSZ, FIBMAP, FS_IOC_* */ ++#define FIBMAP _IO(0x00,1) /* bmap access */ ++#define FIGETBSZ _IO(0x00,2) /* get the block size used for bmap */ ++ ++#define FS_IOC_GETFLAGS _IOR('f', 1, long) ++#define FS_IOC_SETFLAGS _IOW('f', 2, long) ++ ++#define FS_IMMUTABLE_FL 0x00000010 /* Immutable file */ + + #undef SECTOR_SIZE /* Defined in msdos_fs.h for no good reason */ + #undef SECTOR_BITS diff --git a/packages/tools/texturecache.py/package.mk b/packages/tools/texturecache.py/package.mk new file mode 100644 index 0000000000..802f7b4537 --- /dev/null +++ b/packages/tools/texturecache.py/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="texturecache.py" +PKG_VERSION="2.5.4" +PKG_SHA256="0717c2e62dc3f809e8754be2c83d2c7d0f92188741eb425d5377c1d326d25276" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/MilhouseVH/texturecache.py" +PKG_URL="https://github.com/MilhouseVH/${PKG_NAME}/archive/${PKG_VERSION}.tar.gz" +PKG_LONGDESC="The Swiss Army knife for Kodi" +PKG_TOOLCHAIN="manual" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp -PRv texturecache.py ${INSTALL}/usr/bin + cp -PRv tools/mklocal.py ${INSTALL}/usr/bin + chmod +x ${INSTALL}/usr/bin/* +} diff --git a/packages/tools/u-boot-script/package.mk b/packages/tools/u-boot-script/package.mk new file mode 100644 index 0000000000..3ada32eeca --- /dev/null +++ b/packages/tools/u-boot-script/package.mk @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="u-boot-script" +PKG_VERSION="1.0" +PKG_LICENSE="GPL" +PKG_DEPENDS_TARGET="u-boot-tools:host" +PKG_TOOLCHAIN="manual" +PKG_LONGDESC="Compile scripts for u-boot environment." + +PKG_NEED_UNPACK="${PROJECT_DIR}/${PROJECT}/bootloader" +[ -n "${DEVICE}" ] && PKG_NEED_UNPACK+=" ${PROJECT_DIR}/${PROJECT}/devices/${DEVICE}/bootloader" + +make_target() { + if find_dir_path bootloader/scripts; then + for src in ${FOUND_PATH}/*.src; do + mkimage -A ${TARGET_KERNEL_ARCH} -O linux -T script -C none -d "${src}" "$(basename ${src} .src)" + done + fi +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/share/bootloader + cp -a ${PKG_BUILD}/* ${INSTALL}/usr/share/bootloader/ +} diff --git a/packages/tools/u-boot-tools/package.mk b/packages/tools/u-boot-tools/package.mk new file mode 100644 index 0000000000..9b9ca18a39 --- /dev/null +++ b/packages/tools/u-boot-tools/package.mk @@ -0,0 +1,30 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="u-boot-tools" +PKG_VERSION="$(get_pkg_version u-boot)" +PKG_LICENSE="GPL" +PKG_SITE="https://www.denx.de/wiki/U-Boot" +PKG_URL="" +PKG_DEPENDS_HOST="ccache:host bison:host flex:host gnutls:host openssl:host pkg-config:host" +PKG_LONGDESC="Das U-Boot is a cross-platform bootloader for embedded systems." +PKG_DEPENDS_UNPACK+=" u-boot" + +unpack() { + mkdir -p ${PKG_BUILD} + tar --strip-components=1 -xf ${SOURCES}/u-boot/u-boot-${PKG_VERSION}.tar.bz2 -C ${PKG_BUILD} +} + +make_host() { + make tools-only_defconfig HOSTCC="${HOST_CC}" HOSTCFLAGS="-I${TOOLCHAIN}/include" HOSTLDFLAGS="${HOST_LDFLAGS}" + make tools-only HOSTCC="${HOST_CC}" HOSTCFLAGS="-I${TOOLCHAIN}/include" HOSTLDFLAGS="${HOST_LDFLAGS}" +} + +make_target() { + : # host-only package +} + +makeinstall_host() { + mkdir -p ${TOOLCHAIN}/bin + cp tools/mkimage ${TOOLCHAIN}/bin +} diff --git a/packages/tools/u-boot/package.mk b/packages/tools/u-boot/package.mk new file mode 100644 index 0000000000..fce14a889b --- /dev/null +++ b/packages/tools/u-boot/package.mk @@ -0,0 +1,69 @@ +# 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_VERSION="2025.04" +PKG_SHA256="439d3bef296effd54130be6a731c5b118be7fddd7fcc663ccbc5fb18294d8718" +PKG_ARCH="arm aarch64" +PKG_LICENSE="GPL" +PKG_SITE="https://www.denx.de/wiki/U-Boot" +PKG_URL="https://ftp.denx.de/pub/u-boot/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain openssl:host pkg-config:host Python3:host swig:host pyelftools:host" +PKG_LONGDESC="Das U-Boot is a cross-platform bootloader for embedded systems." + +PKG_STAMP="${UBOOT_SYSTEM} ${UBOOT_TARGET}" + +[ -n "${KERNEL_TOOLCHAIN}" ] && PKG_DEPENDS_TARGET+=" gcc-${KERNEL_TOOLCHAIN}:host" + +if [ -n "${UBOOT_FIRMWARE}" ]; then + PKG_DEPENDS_TARGET+=" ${UBOOT_FIRMWARE}" + PKG_DEPENDS_UNPACK+=" ${UBOOT_FIRMWARE}" +fi + +PKG_NEED_UNPACK="${PROJECT_DIR}/${PROJECT}/bootloader" +[ -n "${DEVICE}" ] && PKG_NEED_UNPACK+=" ${PROJECT_DIR}/${PROJECT}/devices/${DEVICE}/bootloader" + +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() { + # U-Boot needs host openssl for tools - make sure it finds right one + # setup_pkg_config_host is required + setup_pkg_config_host + 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 + DEBUG=${PKG_DEBUG} CROSS_COMPILE="${TARGET_KERNEL_PREFIX}" LDFLAGS="" ARCH=arm make mrproper + [ -n "${UBOOT_FIRMWARE}" ] && find_file_path bootloader/firmware && . ${FOUND_PATH} + DEBUG=${PKG_DEBUG} CROSS_COMPILE="${TARGET_KERNEL_PREFIX}" LDFLAGS="" ARCH=arm make HOSTCC="${HOST_CC}" HOSTCFLAGS="-I${TOOLCHAIN}/include" HOSTLDFLAGS="${HOST_LDFLAGS}" $(${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 ${UBOOT_TARGET} HOSTCC="${HOST_CC}" HOSTCFLAGS="-I${TOOLCHAIN}/include" HOSTLDFLAGS="${HOST_LDFLAGS}" 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/packages/virtual/alsa/package.mk b/packages/virtual/alsa/package.mk new file mode 100644 index 0000000000..cf9072070c --- /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 alsa-topology-conf alsa-ucm-conf" +PKG_SECTION="virtual" +PKG_LONGDESC="Matapackage to install all alsa components." diff --git a/packages/virtual/autotools/package.mk b/packages/virtual/autotools/package.mk new file mode 100644 index 0000000000..e201e386bb --- /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 0000000000..b6bf482f6d --- /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+=" ${CUSTOM_FONTS}" +else + 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 0000000000..f88ff20212 --- /dev/null +++ b/packages/virtual/debug/package.mk @@ -0,0 +1,30 @@ +# 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 memtester strace kmsxx" +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+=" vdpauinfo" +fi + +if [ "${VAAPI_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" libva-utils" +fi + +if [ "${VALGRIND}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" valgrind" +fi + +if [ "${REMOTE_GDB}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" gdb:host" +fi diff --git a/packages/virtual/image/package.mk b/packages/virtual/image/package.mk new file mode 100644 index 0000000000..5ccc0c82fc --- /dev/null +++ b/packages/virtual/image/package.mk @@ -0,0 +1,46 @@ +# 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 pigz: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 exfatprogs coreutils bash grep sed gawk findutils diffutils" +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" + +[ "${PULSEAUDIO_SUPPORT}" = "yes" ] && PKG_DEPENDS_TARGET+=" pulseaudio" + +[ "${PIPEWIRE_SUPPORT}" = "yes" ] && PKG_DEPENDS_TARGET+=" pipewire wireplumber" + +if [ "${PULSEAUDIO_SUPPORT}" = "yes" -a "${PIPEWIRE_SUPPORT}" = "yes" ]; then + die "PULSEAUDIO_SUPPORT and PIPEWIRE_SUPPORT cannot be enabled together" +fi + +# Automounter support +[ "${UDEVIL}" = "yes" ] && PKG_DEPENDS_TARGET+=" udevil" + +# 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" + +true diff --git a/packages/virtual/initramfs/config/initramfs.conf b/packages/virtual/initramfs/config/initramfs.conf new file mode 100644 index 0000000000..a4c8e3289d --- /dev/null +++ b/packages/virtual/initramfs/config/initramfs.conf @@ -0,0 +1,7 @@ +dir /dev 0755 0 0 +nod /dev/console 0600 0 0 c 5 1 + +dir usr 0755 0 0 +slink lib usr/lib 0777 0 0 +slink bin usr/bin 0777 0 0 +slink sbin usr/sbin 0777 0 0 diff --git a/packages/virtual/initramfs/package.mk b/packages/virtual/initramfs/package.mk new file mode 100644 index 0000000000..204ea35cc9 --- /dev/null +++ b/packages/virtual/initramfs/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="initramfs" +PKG_VERSION="" +PKG_LICENSE="GPL" +PKG_SITE="http://www.openelec.tv" +PKG_URL="" +PKG_DEPENDS_INIT="libc:init busybox:init plymouth-lite:init util-linux:init e2fsprogs:init dosfstools:init" +PKG_DEPENDS_TARGET="toolchain initramfs:init" +PKG_SECTION="virtual" +PKG_LONGDESC="Metapackage for installing initramfs" + +if [ "${ISCSI_SUPPORT}" = yes ]; then + PKG_DEPENDS_INIT+=" open-iscsi:init" +fi + +if [ "${INITRAMFS_PARTED_SUPPORT}" = yes ]; then + PKG_DEPENDS_INIT+=" parted:init" +fi + +for i in ${PKG_DEPENDS_INIT}; do + PKG_NEED_UNPACK+=" $(get_pkg_directory ${i})" +done diff --git a/packages/virtual/libc/package.mk b/packages/virtual/libc/package.mk new file mode 100644 index 0000000000..2c07b6ec7b --- /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 libxcrypt 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 [ "${ARM_MEM_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" arm-mem" + 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 0000000000..56eb39c3ba --- /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+=" ${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 0000000000..4d9a2382e7 --- /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 0000000000..9fb7513a60 --- /dev/null +++ b/packages/virtual/mediacenter/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="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+=" ${MEDIACENTER}-theme-${SKIN_DEFAULT}" + + for i in ${SKINS}; do + PKG_DEPENDS_TARGET+=" ${MEDIACENTER}-theme-${i}" + done + + # python-based tool for kodi management + 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+=" ${DISTRO_PKG_SETTINGS}" + fi + + # other packages + PKG_DEPENDS_TARGET+=" xmlstarlet" + + if [ "${JOYSTICK_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" peripheral.joystick" + fi + + get_graphicdrivers + if listcontains "${GRAPHIC_DRIVERS}" "(crocus|i915|iris)"; then + PKG_DEPENDS_TARGET+=" intel-vaapi-driver media-driver" + fi + + if listcontains "${GRAPHIC_DRIVERS}" "nvidia-ng"; then + PKG_DEPENDS_TARGET+=" nvidia-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 0000000000..88afd339db --- /dev/null +++ b/packages/virtual/misc-packages/package.mk @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="misc-packages" +PKG_VERSION="" +PKG_LICENSE="GPL" +PKG_SITE="https://libreelec.tv" +PKG_URL="" +PKG_DEPENDS_TARGET="toolchain ${ADDITIONAL_PACKAGES}" +PKG_SECTION="virtual" +PKG_LONGDESC="misc-packages: Metapackage for miscellaneous packages" diff --git a/packages/virtual/network/package.mk b/packages/virtual/network/package.mk new file mode 100644 index 0000000000..244ca36005 --- /dev/null +++ b/packages/virtual/network/package.mk @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="network" +PKG_VERSION="" +PKG_LICENSE="various" +PKG_SITE="https://libreelec.tv" +PKG_URL="" +PKG_DEPENDS_TARGET="toolchain connman netbase ethtool openssh iw wireless-regdb nss ipset" +PKG_SECTION="virtual" +PKG_LONGDESC="Metapackage for various packages to install network support" + +if [ "${BLUETOOTH_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" bluez" +fi + +if [ "${SAMBA_SERVER}" = "yes" ] || [ "${SAMBA_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" samba" +fi + +if [ "${SAMBA_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" cifs-utils" +fi + +if [ "${OPENVPN_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" openvpn" +fi + +if [ "${WIREGUARD_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" wireguard-tools" +fi + +if [ "${ISCSI_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" open-iscsi" +fi + +if [ "${NFS_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" nfs-utils" +fi diff --git a/packages/virtual/remote/package.mk b/packages/virtual/remote/package.mk new file mode 100644 index 0000000000..b5a7f8f9ad --- /dev/null +++ b/packages/virtual/remote/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="remote" +PKG_VERSION="1" +PKG_LICENSE="GPL" +PKG_SITE="http://www.openelec.tv" +PKG_URL="" +PKG_DEPENDS_TARGET="toolchain eventlircd libirman v4l-utils evrepeat" +PKG_SECTION="virtual" +PKG_LONGDESC="Meta package for installing various tools needed for remote support" diff --git a/packages/virtual/toolchain/package.mk b/packages/virtual/toolchain/package.mk new file mode 100644 index 0000000000..f10083f444 --- /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="7-zip: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 openssl:host sed:host xmlstarlet:host" +PKG_DEPENDS_TARGET="toolchain:host gcc:host patchelf:host pax-utils: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 0000000000..ae5e381d42 --- /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/wl/package.mk b/packages/virtual/wl/package.mk new file mode 100644 index 0000000000..5bcacb8585 --- /dev/null +++ b/packages/virtual/wl/package.mk @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="wl" +PKG_VERSION="" +PKG_LICENSE="OSS" +PKG_SITE="https://wayland.freedesktop.org/" +PKG_URL="" +PKG_DEPENDS_TARGET="toolchain" +PKG_SECTION="virtual" +PKG_LONGDESC="Wayland is intended as a simpler replacement for X, easier to develop and maintain." + +# Compositor +if [ -n "${WINDOWMANAGER}" -a "${WINDOWMANAGER}" != "no" ]; then + PKG_DEPENDS_TARGET+=" ${WINDOWMANAGER}" +fi + +# Tools for wlroots based compositors +if [ "${WINDOWMANAGER}" = "sway" ]; then + PKG_DEPENDS_TARGET+=" wlr-randr" +fi + +# NVIDIA drivers for Linux +if listcontains "${GRAPHIC_DRIVERS}" "nvidia-ng"; then + PKG_DEPENDS_TARGET+=" nvidia" +fi diff --git a/packages/virtual/x11/package.mk b/packages/virtual/x11/package.mk new file mode 100644 index 0000000000..d70d0d9c87 --- /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+=" encodings font-xfree86-type1 font-bitstream-type1 font-misc-misc" + +# Server + PKG_DEPENDS_TARGET+=" xkeyboard-config xkbcomp" + +# Tools + PKG_DEPENDS_TARGET+=" xrandr setxkbmap" + +if [ -n "${WINDOWMANAGER}" -a "${WINDOWMANAGER}" != "no" ]; then + PKG_DEPENDS_TARGET+=" ${WINDOWMANAGER}" +fi + +get_graphicdrivers + +# Drivers +if [ -n "${LIBINPUT}" ]; then + PKG_DEPENDS_TARGET+=" xf86-input-libinput" +else + PKG_DEPENDS_TARGET+=" xf86-input-evdev xf86-input-synaptics" +fi + +for drv in ${XORG_DRIVERS}; do + PKG_DEPENDS_TARGET+=" xf86-video-${drv}" +done diff --git a/packages/wayland/compositor/sway/config/colorscheme b/packages/wayland/compositor/sway/config/colorscheme new file mode 100644 index 0000000000..be052853f4 --- /dev/null +++ b/packages/wayland/compositor/sway/config/colorscheme @@ -0,0 +1,20 @@ +## Base16 Black Metal (Dark Funeral) +# Author: metalelf0 (https://github.com/metalelf0) +# Source: base16-sway (https://github.com/rkubosz/base16-sway) + +set $base00 #000000 +set $base01 #121212 +set $base02 #222222 +set $base03 #333333 +set $base04 #999999 +set $base05 #c1c1c1 +set $base06 #999999 +set $base07 #c1c1c1 +set $base08 #5f8787 +set $base09 #aaaaaa +set $base0A #5f81a5 +set $base0B #d0dfee +set $base0C #aaaaaa +set $base0D #888888 +set $base0E #999999 +set $base0F #444444 diff --git a/packages/wayland/compositor/sway/config/config b/packages/wayland/compositor/sway/config/config new file mode 100644 index 0000000000..80e8d7f57d --- /dev/null +++ b/packages/wayland/compositor/sway/config/config @@ -0,0 +1,243 @@ +# Default config for sway +# +# Copy this to ~/.config/sway/config and edit it to your liking. +# +# Read `man 5 sway` for a complete reference. +# Load preferred color scheme +include colorscheme +# Logo key. Use Mod1 for Alt. +set $mod Mod4 +# Home row direction keys, like vim +set $left h +set $down j +set $up k +set $right l +# Your preferred terminal emulator +set $term foot.sh +# Your preferred application launcher +# Note: pass the final command to swaymsg so that the resulting window can be opened +# on the original workspace that the command was run on. +set $highlight $base0A +set $prompt $base0B +set $menu bemenu-run -p "#" -l 10 --scrollbar autohide -i -w --tf "$prompt" --hf "$highlight" --sf "$highlight" --scf "$highlight" --no-exec | xargs swaymsg exec -- + +### Output configuration +# +# Default wallpaper (more resolutions are available in /usr/share/sway/) +output * bg /usr/share/sway/libreelec-wallpaper-2160.png fill + +# hide_cursor hides the cursor image after the specified timeout (in milliseconds) has elapsed with no activity on that cursor +seat * hide_cursor 3000 + +# +# Example configuration: +# +# output HDMI-A-1 resolution 1920x1080 position 1920,0 +# +# You can get the names of your outputs by running: swaymsg -t get_outputs + +### Idle configuration +# +# Example configuration: +# +# exec swayidle -w \ +# timeout 300 'swaylock -f -c 000000' \ +# timeout 600 'swaymsg "output * dpms off"' resume 'swaymsg "output * dpms on"' \ +# before-sleep 'swaylock -f -c 000000' +# +# This will lock your screen after 300 seconds of inactivity, then turn off +# your displays after another 300 seconds, and turn your screens back on when +# resumed. It will also lock your screen before your computer goes to sleep. + +### Input configuration +# +# Example configuration: +# +# input "2:14:SynPS/2_Synaptics_TouchPad" { +# dwt enabled +# tap enabled +# natural_scroll enabled +# middle_emulation enabled +# } +# +# You can get the names of your inputs by running: swaymsg -t get_inputs +# Read `man 5 sway-input` for more information about this section. + +# Set keyboard layout (default US) +input * { + xkb_layout "us" +} + +### Key bindings +# +# Basics: +# + # Start a terminal + bindsym $mod+Return exec $term + + # Kill focused window + bindsym $mod+Shift+q kill + + # Start your launcher + bindsym $mod+d exec $menu + + # Drag floating windows by holding down $mod and left mouse button. + # Resize them with right mouse button + $mod. + # Despite the name, also works for non-floating windows. + # Change normal to inverse to use left mouse button for resizing and right + # mouse button for dragging. + floating_modifier $mod normal + + # Reload the configuration file + bindsym $mod+Shift+c reload + + # Exit sway (logs you out of your Wayland session) + bindsym $mod+Shift+e exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -b 'Yes, exit sway' 'swaymsg exit' +# +# Moving around: +# + # Move your focus around + bindsym $mod+$left focus left + bindsym $mod+$down focus down + bindsym $mod+$up focus up + bindsym $mod+$right focus right + # Or use $mod+[up|down|left|right] + bindsym $mod+Left focus left + bindsym $mod+Down focus down + bindsym $mod+Up focus up + bindsym $mod+Right focus right + + # Move the focused window with the same, but add Shift + bindsym $mod+Shift+$left move left + bindsym $mod+Shift+$down move down + bindsym $mod+Shift+$up move up + bindsym $mod+Shift+$right move right + # Ditto, with arrow keys + bindsym $mod+Shift+Left move left + bindsym $mod+Shift+Down move down + bindsym $mod+Shift+Up move up + bindsym $mod+Shift+Right move right +# +# Workspaces: +# + # Switch to workspace + bindsym $mod+1 workspace number 1 + bindsym $mod+2 workspace number 2 + bindsym $mod+3 workspace number 3 + bindsym $mod+4 workspace number 4 + bindsym $mod+5 workspace number 5 + bindsym $mod+6 workspace number 6 + bindsym $mod+7 workspace number 7 + bindsym $mod+8 workspace number 8 + bindsym $mod+9 workspace number 9 + bindsym $mod+0 workspace number 10 + # Move focused container to workspace + bindsym $mod+Shift+1 move container to workspace number 1 + bindsym $mod+Shift+2 move container to workspace number 2 + bindsym $mod+Shift+3 move container to workspace number 3 + bindsym $mod+Shift+4 move container to workspace number 4 + bindsym $mod+Shift+5 move container to workspace number 5 + bindsym $mod+Shift+6 move container to workspace number 6 + bindsym $mod+Shift+7 move container to workspace number 7 + bindsym $mod+Shift+8 move container to workspace number 8 + bindsym $mod+Shift+9 move container to workspace number 9 + bindsym $mod+Shift+0 move container to workspace number 10 + # Note: workspaces can have any name you want, not just numbers. + # We just use 1-10 as the default. +# +# Layout stuff: +# + # You can "split" the current object of your focus with + # $mod+b or $mod+v, for horizontal and vertical splits + # respectively. + bindsym $mod+b splith + bindsym $mod+v splitv + + # Switch the current container between different layout styles + bindsym $mod+s layout stacking + bindsym $mod+w layout tabbed + bindsym $mod+e layout toggle split + + # Make the current focus fullscreen + bindsym $mod+f fullscreen + + # Toggle the current focus between tiling and floating mode + bindsym $mod+Shift+space floating toggle + + # Swap focus between the tiling area and the floating area + bindsym $mod+space focus mode_toggle + + # Move focus to the parent container + bindsym $mod+a focus parent +# +# Scratchpad: +# + # Sway has a "scratchpad", which is a bag of holding for windows. + # You can send windows there and get them back later. + + # Move the currently focused window to the scratchpad + bindsym $mod+Shift+minus move scratchpad + + # Show the next scratchpad window or hide the focused scratchpad window. + # If there are multiple scratchpad windows, this command cycles through them. + bindsym $mod+minus scratchpad show +# +# Resizing containers: +# +mode "resize" { + # left will shrink the containers width + # right will grow the containers width + # up will shrink the containers height + # down will grow the containers height + bindsym $left resize shrink width 10px + bindsym $down resize grow height 10px + bindsym $up resize shrink height 10px + bindsym $right resize grow width 10px + + # Ditto, with arrow keys + bindsym Left resize shrink width 10px + bindsym Down resize grow height 10px + bindsym Up resize shrink height 10px + bindsym Right resize grow width 10px + + # Return to default mode + bindsym Return mode "default" + bindsym Escape mode "default" +} +bindsym $mod+r mode "resize" + +# +# Status Bar: +# +# Read `man 5 sway-bar` for more information about this section. +bar { + position top + + # When the status_command prints a new line to stdout, swaybar updates. + # The default just shows the current date and time. + status_command while date +'%a %e %b %G - %k:%M'; do sleep 1; done + + colors { + background $base00 + separator $base01 + statusline $base04 + + # State Border BG Text + focused_workspace $base05 $base0D $base00 + active_workspace $base05 $base03 $base00 + inactive_workspace $base03 $base01 $base05 + urgent_workspace $base08 $base08 $base00 + binding_mode $base00 $base0A $base00 } +} + +# Basic color configuration using the Base16 variables for windows and borders. +# Property Name Border BG Text Indicator Child Border +client.focused $base05 $base0D $base00 $base0D $base0D +client.focused_inactive $base01 $base01 $base05 $base03 $base01 +client.unfocused $base01 $base00 $base05 $base01 $base01 +client.urgent $base08 $base08 $base00 $base08 $base08 +client.placeholder $base00 $base00 $base05 $base00 $base00 +client.background $base07 + +# Load etc config +include /etc/sway/config.d/* diff --git a/packages/wayland/compositor/sway/config/sway-daemon.conf b/packages/wayland/compositor/sway/config/sway-daemon.conf new file mode 100644 index 0000000000..74c4414bf7 --- /dev/null +++ b/packages/wayland/compositor/sway/config/sway-daemon.conf @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) +# Pass config args to Sway e.g. --unsupported-gpu for NVIDIA GPUs +SWAY_DAEMON_CONF="" diff --git a/packages/wayland/compositor/sway/package.mk b/packages/wayland/compositor/sway/package.mk new file mode 100644 index 0000000000..e42d2f6718 --- /dev/null +++ b/packages/wayland/compositor/sway/package.mk @@ -0,0 +1,46 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="sway" +PKG_VERSION="1.11" +PKG_SHA256="034ec4519326d6af5275814700dde46e852c5174614109affe4c86b2fbee062a" +PKG_LICENSE="MIT" +PKG_SITE="https://swaywm.org/" +PKG_URL="https://github.com/swaywm/sway/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain wayland wayland-protocols libdrm libxkbcommon libinput cairo pango libjpeg-turbo dbus json-c wlroots gdk-pixbuf swaybg foot bemenu" +PKG_LONGDESC="i3-compatible Wayland compositor" + +PKG_MESON_OPTS_TARGET="-Ddefault-wallpaper=false \ + -Dzsh-completions=false \ + -Dbash-completions=false \ + -Dfish-completions=false \ + -Dswaybar=true \ + -Dswaynag=true \ + -Dtray=disabled \ + -Dgdk-pixbuf=enabled \ + -Dman-pages=disabled \ + -Dsd-bus-provider=auto" + +pre_configure_target() { + # sway does not build without -Wno flags as all warnings being treated as errors + export TARGET_CFLAGS=$(echo "${TARGET_CFLAGS} -Wno-unused-variable") +} + +post_makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/sway + cp ${PKG_DIR}/scripts/sway.sh ${INSTALL}/usr/bin + cp ${PKG_DIR}/scripts/sway-config ${INSTALL}/usr/lib/sway + + # install config & wallpaper + mkdir -p ${INSTALL}/usr/share/sway + cp ${PKG_DIR}/config/* ${INSTALL}/usr/share/sway + find_file_path "splash/splash-2160.png" && cp ${FOUND_PATH} ${INSTALL}/usr/share/sway/libreelec-wallpaper-2160.png + + # clean up + safe_remove ${INSTALL}/etc + safe_remove ${INSTALL}/usr/share/wayland-sessions +} + +post_install() { + enable_service sway.service +} diff --git a/packages/wayland/compositor/sway/patches/sway-100.01-static-ipc-socket.patch b/packages/wayland/compositor/sway/patches/sway-100.01-static-ipc-socket.patch new file mode 100644 index 0000000000..ef259ada0e --- /dev/null +++ b/packages/wayland/compositor/sway/patches/sway-100.01-static-ipc-socket.patch @@ -0,0 +1,11 @@ +--- a/sway/ipc-server.c ++++ b/sway/ipc-server.c +@@ -138,7 +138,7 @@ struct sockaddr_un *ipc_user_sockaddr(vo + dir = "/tmp"; + } + if (path_size <= snprintf(ipc_sockaddr->sun_path, path_size, +- "%s/sway-ipc.%u.%i.sock", dir, getuid(), getpid())) { ++ "%s/sway-ipc.%u.sock", dir, getuid())) { + sway_abort("Socket path won't fit into ipc_sockaddr->sun_path"); + } + diff --git a/packages/wayland/compositor/sway/patches/sway-100.02-allow-running-as-root.patch b/packages/wayland/compositor/sway/patches/sway-100.02-allow-running-as-root.patch new file mode 100644 index 0000000000..ab42ecc242 --- /dev/null +++ b/packages/wayland/compositor/sway/patches/sway-100.02-allow-running-as-root.patch @@ -0,0 +1,37 @@ +Since wayland requires XDG_RUNTIME_DIR--- a/sway/main.c ++++ b/sway/main.c +@@ -112,7 +112,8 @@ + } + + static bool detect_suid(void) { +- if (geteuid() != 0 && getegid() != 0) { ++ if (geteuid() == 0 && getegid() == 0) { ++ sway_log(SWAY_INFO, "Running sway as root user"); + return false; + } + +@@ -266,11 +267,6 @@ + } + } + +- // SUID operation is deprecated, so block it for now. +- if (detect_suid()) { +- exit(EXIT_FAILURE); +- } +- + // Since wayland requires XDG_RUNTIME_DIR to be set, abort with just the + // clear error message (when not running as an IPC client). + if (!getenv("XDG_RUNTIME_DIR") && optind == argc) { +@@ -320,6 +316,11 @@ + return 0; + } + ++ // SUID operation is deprecated, so block it for now. ++ if (detect_suid()) { ++ exit(EXIT_FAILURE); ++ } ++ + increase_nofile_limit(); + + // handle SIGTERM signals + diff --git a/packages/wayland/compositor/sway/patches/sway-100.03-do-not-use-git-version.patch b/packages/wayland/compositor/sway/patches/sway-100.03-do-not-use-git-version.patch new file mode 100644 index 0000000000..ae7804e759 --- /dev/null +++ b/packages/wayland/compositor/sway/patches/sway-100.03-do-not-use-git-version.patch @@ -0,0 +1,22 @@ +--- a/meson.build ++++ b/meson.build +@@ -158,18 +158,6 @@ + add_project_arguments('-DSYSCONFDIR="/@0@"'.format(join_paths(prefix, sysconfdir)), language : 'c') + + version = '"@0@"'.format(meson.project_version()) +-git = find_program('git', native: true, required: false) +-if git.found() +- git_commit = run_command([git, '--git-dir=.git', 'rev-parse', '--short', 'HEAD'], check: false) +- git_branch = run_command([git, '--git-dir=.git', 'rev-parse', '--abbrev-ref', 'HEAD'], check: false) +- if git_commit.returncode() == 0 and git_branch.returncode() == 0 +- version = '"@0@-@1@ (" __DATE__ ", branch \'@2@\')"'.format( +- meson.project_version(), +- git_commit.stdout().strip(), +- git_branch.stdout().strip(), +- ) +- endif +-endif + add_project_arguments('-DSWAY_VERSION=@0@'.format(version), language: 'c') + + # Compute the relative path used by compiler invocations. + diff --git a/packages/wayland/compositor/sway/profile.d/04-sway.conf b/packages/wayland/compositor/sway/profile.d/04-sway.conf new file mode 100644 index 0000000000..8fcea84a5e --- /dev/null +++ b/packages/wayland/compositor/sway/profile.d/04-sway.conf @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +export WAYLAND_DISPLAY=wayland-1 +export XDG_RUNTIME_DIR=/var/run/0-runtime-dir +export SWAYSOCK="${XDG_RUNTIME_DIR}/sway-ipc.0.sock" diff --git a/packages/wayland/compositor/sway/scripts/sway-config b/packages/wayland/compositor/sway/scripts/sway-config new file mode 100755 index 0000000000..62f4925f70 --- /dev/null +++ b/packages/wayland/compositor/sway/scripts/sway-config @@ -0,0 +1,47 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +export XDG_RUNTIME_DIR=/var/run/0-runtime-dir +export WAYLAND_DISPLAY=wayland-1 +SWAY_DAEMON_ARGS="" + +SWAY_RUNTIME_DIR=/var/run/sway +SWAY_CONFIG_BASEDIR=/storage/.config/sway +SWAY_CONFIG_SHAREDIR=/usr/share/sway + +SWAY_CONFIG_COLOR=${SWAY_CONFIG_BASEDIR}/colorscheme +SWAY_CONFIG_COLOR_DEFAULT=${SWAY_CONFIG_SHAREDIR}/colorscheme +SWAY_CONFIG_DAEMON=${SWAY_CONFIG_BASEDIR}/sway-daemon.conf +SWAY_CONFIG_DAEMON_DEFAULT=${SWAY_CONFIG_SHAREDIR}/sway-daemon.conf +SWAY_CONFIG_USER=${SWAY_CONFIG_BASEDIR}/config +SWAY_CONFIG_USER_DEFAULT=${SWAY_CONFIG_SHAREDIR}/config +SWAY_CONFIG_RUN=${SWAY_RUNTIME_DIR}/sway-daemon.conf + +if [ ! -d "$XDG_RUNTIME_DIR" ]; then + mkdir "$XDG_RUNTIME_DIR" + chmod 0700 "$XDG_RUNTIME_DIR" +fi + +if [ ! -d "$SWAY_RUNTIME_DIR" ]; then + mkdir "$SWAY_RUNTIME_DIR" +fi + +if [ ! -f ${SWAY_CONFIG_USER} ]; then + mkdir -p ${SWAY_CONFIG_BASEDIR} + cp ${SWAY_CONFIG_USER_DEFAULT} ${SWAY_CONFIG_BASEDIR} +fi + +if [ ! -f ${SWAY_CONFIG_COLOR} ]; then + cp ${SWAY_CONFIG_COLOR_DEFAULT} ${SWAY_CONFIG_BASEDIR} +fi + +if [ ! -f ${SWAY_CONFIG_DAEMON} ]; then + cp ${SWAY_CONFIG_DAEMON_DEFAULT} ${SWAY_CONFIG_BASEDIR} +fi + +if [ -f ${SWAY_CONFIG_DAEMON} ]; then + SWAY_DAEMON_CONF=$(cat ${SWAY_CONFIG_DAEMON} | grep -E '^SWAY_DAEMON_CONF=' | cut -d "\"" -f2) +fi + +echo SWAY_DAEMON_ARGS=\"${SWAY_DAEMON_CONF} ${SWAY_DAEMON_ARGS}\" >${SWAY_CONFIG_RUN} diff --git a/packages/wayland/compositor/sway/scripts/sway.sh b/packages/wayland/compositor/sway/scripts/sway.sh new file mode 100755 index 0000000000..a80ecced56 --- /dev/null +++ b/packages/wayland/compositor/sway/scripts/sway.sh @@ -0,0 +1,17 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +. /run/sway/sway-daemon.conf +SWAY_LOG_FILE=/var/log/sway.log + +if [ ! -z "$(lsmod | grep 'nvidia')" ]; then + export WLR_NO_HARDWARE_CURSORS=1 + SWAY_GPU_ARGS="--unsupported-gpu" +fi + +# start sway, even if no input devices are connected +export WLR_LIBINPUT_NO_DEVICES=1 + +logger -t Sway "### Starting Sway with -V ${SWAY_GPU_ARGS} ${SWAY_DAEMON_ARGS}" +/usr/bin/sway -V ${SWAY_GPU_ARGS} ${SWAY_DAEMON_ARGS} >${SWAY_LOG_FILE} 2>&1 diff --git a/packages/wayland/compositor/sway/system.d/sway.service b/packages/wayland/compositor/sway/system.d/sway.service new file mode 100644 index 0000000000..7fea2db30c --- /dev/null +++ b/packages/wayland/compositor/sway/system.d/sway.service @@ -0,0 +1,20 @@ +[Unit] +Description=Sway Wayland Compositor +Before=graphical.target kodi.service +After=multi-user.target +ConditionKernelCommandLine=!installer + +[Service] +Environment=HOME=/storage +Environment=XDG_RUNTIME_DIR=/var/run/0-runtime-dir +EnvironmentFile=/usr/share/sway/sway-daemon.conf +EnvironmentFile=-/run/sway/sway-daemon.conf +WorkingDirectory=/storage +ExecStartPre=-/usr/lib/sway/sway-config +ExecStart=/usr/bin/sway.sh +Restart=always +RestartSec=5 + +[Install] +Alias=display-manager.service +WantedBy=graphical.target diff --git a/packages/wayland/lib/fcft/package.mk b/packages/wayland/lib/fcft/package.mk new file mode 100644 index 0000000000..397b094a32 --- /dev/null +++ b/packages/wayland/lib/fcft/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="fcft" +PKG_VERSION="3.3.1" +PKG_SHA256="f18bf79562e06d41741690cd1e07a02eb2600ae39eb5752eef8a698f603a482c" +PKG_LICENSE="MIT" +PKG_SITE="https://codeberg.org/dnkl/fcft" +PKG_URL="https://codeberg.org/dnkl/fcft/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain pixman fontconfig freetype tllist" +PKG_LONGDESC="A simple library for font loading and glyph rasterization using FontConfig, FreeType and pixman." + +PKG_MESON_OPTS_TARGET="-Ddocs=disabled \ + -Dgrapheme-shaping=disabled \ + -Drun-shaping=disabled \ + -Dtest-text-shaping=false \ + -Dexamples=false" diff --git a/packages/wayland/lib/seatd/package.mk b/packages/wayland/lib/seatd/package.mk new file mode 100644 index 0000000000..409734a365 --- /dev/null +++ b/packages/wayland/lib/seatd/package.mk @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="seatd" +PKG_VERSION="0.9.1" +PKG_SHA256="819979c922a0be258aed133d93920bce6a3d3565a60588d6d372ce9db2712cd3" +PKG_LICENSE="MIT" +PKG_SITE="https://git.sr.ht/~kennylevinsen/seatd" +PKG_URL="https://git.sr.ht/~kennylevinsen/seatd/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain systemd" +PKG_LONGDESC="A minimal seat management daemon, and a universal seat management library." + +PKG_MESON_OPTS_TARGET="-Dlibseat-logind=systemd \ + -Dlibseat-seatd=enabled \ + -Dlibseat-builtin=disabled \ + -Dserver=enabled \ + -Dexamples=disabled \ + -Dman-pages=disabled" + +pre_configure_target() { + # seatd does not build without -Wno flags as all warnings being treated as errors + export TARGET_CFLAGS=$(echo "${TARGET_CFLAGS} -Wno-unused-parameter") +} + +post_install() { + enable_service seatd.service +} diff --git a/packages/wayland/lib/seatd/system.d/seatd.service b/packages/wayland/lib/seatd/system.d/seatd.service new file mode 100644 index 0000000000..ca01aa28cd --- /dev/null +++ b/packages/wayland/lib/seatd/system.d/seatd.service @@ -0,0 +1,14 @@ +[Unit] +Description=Seat Management Daemon +Before=graphical.target sway.service +After=multi-user.target +ConditionKernelCommandLine=!installer + +[Service] +ExecStart=/usr/bin/seatd -u root +Restart=always +RestartSec=1 + +[Install] +Alias=seat-management-daemon.service +WantedBy=graphical.target diff --git a/packages/wayland/lib/tllist/package.mk b/packages/wayland/lib/tllist/package.mk new file mode 100644 index 0000000000..8405d6c0a4 --- /dev/null +++ b/packages/wayland/lib/tllist/package.mk @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="tllist" +PKG_VERSION="1.1.0" +PKG_SHA256="0e7b7094a02550dd80b7243bcffc3671550b0f1d8ba625e4dff52517827d5d23" +PKG_LICENSE="MIT" +PKG_SITE="https://codeberg.org/dnkl/tllist" +PKG_URL="https://codeberg.org/dnkl/tllist/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A C header file only implementation of a typed linked list." diff --git a/packages/wayland/lib/wlroots/package.mk b/packages/wayland/lib/wlroots/package.mk new file mode 100644 index 0000000000..d25673ef2b --- /dev/null +++ b/packages/wayland/lib/wlroots/package.mk @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="wlroots" +PKG_VERSION="0.19.0" +PKG_SHA256="2f31ba9d4ae1ff3f5ac62f21b046fe31bb408c7f887c4dfafb2e09e98c991980" +PKG_LICENSE="MIT" +PKG_SITE="https://gitlab.freedesktop.org/wlroots/wlroots/" +PKG_URL="https://gitlab.freedesktop.org/wlroots/wlroots/-/archive/${PKG_VERSION}/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain hwdata libdisplay-info libinput libxkbcommon pixman libdrm wayland wayland-protocols seatd" +PKG_LONGDESC="A modular Wayland compositor library" + +configure_package() { + # OpenGLES Support + if [ "${OPENGLES_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" + fi +} + +PKG_MESON_OPTS_TARGET="-Dxcb-errors=disabled \ + -Dxwayland=disabled \ + -Dbackends=drm,libinput \ + -Dexamples=false \ + -Drenderers=gles2" + +pre_configure_target() { + # wlroots does not build without -Wno flags as all warnings being treated as errors + export TARGET_CFLAGS=$(echo "${TARGET_CFLAGS} -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-function") +} diff --git a/packages/wayland/libinput/package.mk b/packages/wayland/libinput/package.mk new file mode 100644 index 0000000000..f1269a430c --- /dev/null +++ b/packages/wayland/libinput/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="libinput" +PKG_VERSION="1.28.1" +PKG_SHA256="19e5337ec10fdf920c8d1f4ece63cd7d1c12279ee26e347e30e98e2942d9e1aa" +PKG_LICENSE="GPL" +PKG_SITE="https://www.freedesktop.org/wiki/Software/libinput/" +PKG_URL="https://gitlab.freedesktop.org/libinput/libinput/-/archive/${PKG_VERSION}/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +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 0000000000..7de2c2f32b --- /dev/null +++ b/packages/wayland/libxkbcommon/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="libxkbcommon" +PKG_VERSION="1.10.0" +PKG_SHA256="0427585a4d6ca17c9fc1ac4b539bf303348e9080af70c5ea402503bc370a9631" +PKG_LICENSE="MIT" +PKG_SITE="https://xkbcommon.org" +PKG_URL="https://github.com/xkbcommon/libxkbcommon/archive/refs/tags/xkbcommon-${PKG_VERSION}.tar.gz" +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}" = "wl" ]; then + PKG_DEPENDS_TARGET+=" wayland wayland-protocols" + 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 0000000000..062ffd82b8 --- /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.7" +PKG_SHA256="a107adad2101fecac54ac7f9f0e0a0dd155d954193da55c2340c97f2ff1d814e" +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/util/bemenu/package.mk b/packages/wayland/util/bemenu/package.mk new file mode 100644 index 0000000000..92409e38b0 --- /dev/null +++ b/packages/wayland/util/bemenu/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="bemenu" +PKG_VERSION="0.6.23" +PKG_SHA256="0e7878c3bf57e0e362efe89c59deddd33819cd62b980be7e0b7bb4da45478e44" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/Cloudef/bemenu" +PKG_URL="https://github.com/Cloudef/bemenu/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain glib wayland wayland-protocols cairo pango libxkbcommon" +PKG_LONGDESC="Dynamic menu library and client program inspired by dmenu" + +PKG_MAKE_OPTS_TARGET="PREFIX=/usr clients wayland" + +makeinstall_target() { + make DESTDIR=${INSTALL} PREFIX=/usr install-libs install-bins install-wayland install-pkgconfig +} + +post_makeinstall_target() { + ln -sf libbemenu.so.${PKG_VERSION} ${INSTALL}/usr/lib/libbemenu.so.0 +} diff --git a/packages/wayland/util/foot/config/foot.ini b/packages/wayland/util/foot/config/foot.ini new file mode 100644 index 0000000000..8c8608e416 --- /dev/null +++ b/packages/wayland/util/foot/config/foot.ini @@ -0,0 +1,197 @@ +# -*- conf -*- + +# shell=$SHELL (if set, otherwise user's default shell from /etc/passwd) +term=xterm +# login-shell=no + +# app-id=foot +title=foo terminal +# locked-title=no + +font=monospace:size=12 +# font-bold= +# font-italic= +# font-bold-italic= +# line-height= +# letter-spacing=0 +# horizontal-letter-offset=0 +# vertical-letter-offset=0 +# underline-offset= +# box-drawings-uses-font-glyphs=no +dpi-aware=auto + +# initial-window-size-pixels=700x500 # Or, +# initial-window-size-chars= +# initial-window-mode=windowed +# pad=2x2 # optionally append 'center' +# resize-delay-ms=100 + +# notify=notify-send -a ${app-id} -i ${app-id} ${title} ${body} + +# bold-text-in-bright=no +# bell=none +# word-delimiters=,│`|:"'()[]{}<> +# selection-target=primary +# workers= + +[bell] +# urgent=no +# notify=no +# command= +# command-focused=no + +[scrollback] +# lines=1000 +# multiplier=3.0 +# indicator-position=relative +# indicator-format= + +[url] +# launch=xdg-open ${url} +# label-letters=sadfjklewcmpgh +# osc8-underline=url-mode +# protocols=http, https, ftp, ftps, file, gemini, gopher +# uri-characters=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.,~:;/?#@!$&%*+="' + +[cursor] +style=beam +color=000000 eeeeee +blink=yes +# beam-thickness=1.5 +# underline-thickness= + +[mouse] +# hide-when-typing=no +# alternate-scroll-mode=yes + +[colors] +alpha=0.95 +background=000000 +foreground=eeeeee +regular0=1c1c1c # black +regular1=af005f # red +regular2=5faf00 # green +regular3=d7af5f # yellow +regular4=5fafd7 # blue +regular5=808080 # magenta +regular6=d7875f # cyan +regular7=d0d0d0 # white +bright0=bcbcbc # bright black +bright1=5faf5f # bright red +bright2=afd700 # bright green +bright3=af87d7 # bright yellow +bright4=ffaf00 # bright blue +bright5=ff5faf # bright magenta +bright6=00afaf # bright cyan +bright7=5f8787 # bright white +#selection-foreground=1c1c1c +#selection-background=af87d7 + +## Normal/regular colors (color palette 0-7) +# regular0=222222 # black +# regular1=cc9393 # red +# regular2=7f9f7f # green +# regular3=d0bf8f # yellow +# regular4=6ca0a3 # blue +# regular5=dc8cc3 # magenta +# regular6=93e0e3 # cyan +# regular7=dcdccc # white + +## Bright colors (color palette 8-15) +# bright0=666666 # bright black +# bright1=dca3a3 # bright red +# bright2=bfebbf # bright green +# bright3=f0dfaf # bright yellow +# bright4=8cd0d3 # bright blue +# bright5=fcace3 # bright magenta +# bright6=b3ffff # bright cyan +# bright7=ffffff # bright white + +## dimmed colors (see foot.ini(5) man page) +# dim0= +# ... +# dim7= + +## The remaining 256-color palette +# 16 = <256-color palette #16> +# ... +# 255 = <256-color palette #255> + +## Misc colors +# selection-foreground= +# selection-background= +# jump-labels= +# urls= +# scrollback-indicator= + +[csd] +# preferred=server +# size=26 +# font= +# color= +# border-width=0 +# border-color= +# button-width=26 +# button-color= +# button-minimize-color= +# button-maximize-color= +# button-close-color= + +[key-bindings] +# scrollback-up-page=Shift+Page_Up +# scrollback-up-half-page=none +# scrollback-up-line=none +# scrollback-down-page=Shift+Page_Down +# scrollback-down-half-page=none +# scrollback-down-line=none +# clipboard-copy=Control+Shift+c +# clipboard-paste=Control+Shift+v +# primary-paste=Shift+Insert +# search-start=Control+Shift+r +# font-increase=Control+plus Control+equal Control+KP_Add +# font-decrease=Control+minus Control+KP_Subtract +# font-reset=Control+0 Control+KP_0 +# spawn-terminal=Control+Shift+n +# minimize=none +# maximize=none +# fullscreen=none +# pipe-visible=[sh -c "xurls | fuzzel | xargs -r firefox"] none +# pipe-scrollback=[sh -c "xurls | fuzzel | xargs -r firefox"] none +# pipe-selected=[xargs -r firefox] none +# show-urls-launch=Control+Shift+u +# show-urls-copy=none +# noop=none + +[search-bindings] +# cancel=Control+g Control+c Escape +# commit=Return +# find-prev=Control+r +# find-next=Control+s +# cursor-left=Left Control+b +# cursor-left-word=Control+Left Mod1+b +# cursor-right=Right Control+f +# cursor-right-word=Control+Right Mod1+f +# cursor-home=Home Control+a +# cursor-end=End Control+e +# delete-prev=BackSpace +# delete-prev-word=Mod1+BackSpace Control+BackSpace +# delete-next=Delete +# delete-next-word=Mod1+d Control+Delete +# extend-to-word-boundary=Control+w +# extend-to-next-whitespace=Control+Shift+w +# clipboard-paste=Control+v Control+y +# primary-paste=Shift+Insert + +[url-bindings] +# cancel=Control+g Control+c Control+d Escape +# toggle-url-visible=t + +[mouse-bindings] +# primary-paste=BTN_MIDDLE +# select-begin=BTN_LEFT +# select-begin-block=Control+BTN_LEFT +# select-extend=BTN_RIGHT +# select-extend-character-wise=Control+BTN_RIGHT +# select-word=BTN_LEFT-2 +# select-word-whitespace=Control+BTN_LEFT-2 +# select-row=BTN_LEFT-3 diff --git a/packages/wayland/util/foot/package.mk b/packages/wayland/util/foot/package.mk new file mode 100644 index 0000000000..a6423ad044 --- /dev/null +++ b/packages/wayland/util/foot/package.mk @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="foot" +PKG_VERSION="1.22.3" +PKG_SHA256="1c9f09c119c5b24bd1934ce515e70f402b7d1b2c55f8218a16eddaa26e3f6fb0" +PKG_LICENSE="MIT" +PKG_SITE="https://codeberg.org/dnkl/foot/" +PKG_URL="https://codeberg.org/dnkl/foot/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain ncurses wayland wayland-protocols pixman fontconfig libxkbcommon fcft" +PKG_LONGDESC="A fast, lightweight and minimalistic Wayland terminal emulator" + +PKG_MESON_OPTS_TARGET="-Ddocs=disabled \ + -Dthemes=false \ + -Dime=false \ + -Dgrapheme-clustering=auto \ + -Dterminfo=disabled \ + -Ddefault-terminfo=xterm" + +post_makeinstall_target() { + # clean up + safe_remove ${INSTALL}/usr/share/* + + # install scripts + mkdir -p ${INSTALL}/usr/bin + cp ${PKG_DIR}/scripts/foot.sh ${INSTALL}/usr/bin + + # install config + mkdir -p ${INSTALL}/usr/share/foot + cp ${PKG_DIR}/config/foot.ini ${INSTALL}/usr/share/foot +} diff --git a/packages/wayland/util/foot/scripts/foot.sh b/packages/wayland/util/foot/scripts/foot.sh new file mode 100755 index 0000000000..d7c08f999e --- /dev/null +++ b/packages/wayland/util/foot/scripts/foot.sh @@ -0,0 +1,18 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +FOOT_CONFIG_DIR=/storage/.config/foot +FOOT_CONFIG_DEFAULT=/usr/share/foot/foot.ini +FOOT_LOG_FILE=/var/log/foot.log + +if [ ! -f ${FOOT_CONFIG_DIR}/foot.ini ]; then + mkdir -p ${FOOT_CONFIG_DIR} + cp ${FOOT_CONFIG_DEFAULT} ${FOOT_CONFIG_DIR} +fi + +if [ -z "${LOCPATH}" ]; then + export LOCPATH="/storage/.cache/locpath" +fi + +/usr/bin/foot >${FOOT_LOG_FILE} 2>&1 diff --git a/packages/wayland/util/swaybg/package.mk b/packages/wayland/util/swaybg/package.mk new file mode 100644 index 0000000000..0d2d620a12 --- /dev/null +++ b/packages/wayland/util/swaybg/package.mk @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="swaybg" +PKG_VERSION="1.2.1" +PKG_SHA256="45c4a1a3b83c86ddc321a6136402b708f195a022d0ccee4641b23d14c3a3c25e" +PKG_LICENSE="MIT" +PKG_SITE="https://swaywm.org/" +PKG_URL="https://github.com/swaywm/swaybg/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain wayland wayland-protocols cairo pango gdk-pixbuf" +PKG_LONGDESC="Wallpaper tool for Wayland compositors" + +PKG_MESON_OPTS_TARGET="-Dgdk-pixbuf=enabled \ + -Dman-pages=disabled" + +pre_configure_target() { + # swaybg does not build without -Wno flags as all warnings being treated as errors + export TARGET_CFLAGS=$(echo "${TARGET_CFLAGS} -Wno-maybe-uninitialized") +} diff --git a/packages/wayland/util/wlr-randr/package.mk b/packages/wayland/util/wlr-randr/package.mk new file mode 100644 index 0000000000..ed050dd6ee --- /dev/null +++ b/packages/wayland/util/wlr-randr/package.mk @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="wlr-randr" +PKG_VERSION="0.5.0" +PKG_SHA256="eae7dd785b2a19c82fd33ca281706616b12b1e5e62042156ab39407c39074b8c" +PKG_LICENSE="MIT" +PKG_SITE="https://gitlab.freedesktop.org/emersion/wlr-randr" +PKG_URL="https://gitlab.freedesktop.org/emersion/wlr-randr/-/archive/v${PKG_VERSION}/${PKG_NAME}-v${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain wayland" +PKG_LONGDESC="Utility to manage outputs of a Wayland compositor." diff --git a/packages/wayland/wayland-protocols/package.mk b/packages/wayland/wayland-protocols/package.mk new file mode 100644 index 0000000000..25030570ad --- /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.45" +PKG_SHA256="4d2b2a9e3e099d017dc8107bf1c334d27bb87d9e4aff19a0c8d856d17cd41ef0" +PKG_LICENSE="OSS" +PKG_SITE="https://wayland.freedesktop.org/" +PKG_URL="https://gitlab.freedesktop.org/wayland/${PKG_NAME}/-/releases/${PKG_VERSION}/downloads/${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 0000000000..ec93de287f --- /dev/null +++ b/packages/wayland/wayland/package.mk @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="wayland" +PKG_VERSION="1.24.0" +PKG_SHA256="82892487a01ad67b334eca83b54317a7c86a03a89cfadacfef5211f11a5d0536" +PKG_LICENSE="OSS" +PKG_SITE="https://wayland.freedesktop.org/" +PKG_URL="https://gitlab.freedesktop.org/wayland/wayland/-/releases/${PKG_VERSION}/downloads/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_HOST="libffi:host expat:host libxml2:host meson:host" +PKG_DEPENDS_TARGET="toolchain wayland:host libffi expat libxml2" +PKG_LONGDESC="a display server protocol" + +PKG_MESON_OPTS_HOST="-Dlibraries=false \ + -Dscanner=true \ + -Dtests=false \ + -Ddocumentation=false \ + -Ddtd_validation=false" + +PKG_MESON_OPTS_TARGET="-Dlibraries=true \ + -Dscanner=false \ + -Dtests=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/ + mkdir -p ${SYSROOT_PREFIX}/usr/share/wayland + cp ${TOOLCHAIN}/share/wayland/wayland.xml ${SYSROOT_PREFIX}/usr/share/wayland/ +} diff --git a/packages/wayland/waylandpp/package.mk b/packages/wayland/waylandpp/package.mk new file mode 100644 index 0000000000..533282b8e7 --- /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="1.0.0" +PKG_SHA256="b20b45917382c6b87e9380130c9a1a1c563da2f498de5830df12fbce326dd9f5" +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/waylandpp/patches/waylandpp-0001-PR71-support-build-with-gcc13.patch b/packages/wayland/waylandpp/patches/waylandpp-0001-PR71-support-build-with-gcc13.patch new file mode 100644 index 0000000000..b2d3755cf8 --- /dev/null +++ b/packages/wayland/waylandpp/patches/waylandpp-0001-PR71-support-build-with-gcc13.patch @@ -0,0 +1,57 @@ +From 3c441910aa25f57df2a4db55f75f5d99cea86620 Mon Sep 17 00:00:00 2001 +From: Sergei Trofimovich +Date: Sun, 8 Jan 2023 18:24:53 +0000 +Subject: [PATCH] add missing include + +Upcoming `gcc-13` made `` leaner and does not include `` +implicitly anymore. As a result build fails without the change as: + + [ 2%] Building CXX object CMakeFiles/wayland-scanner++.dir/scanner/scanner.cpp.o + scanner/scanner.cpp:378:3: error: 'uint32_t' does not name a type + 378 | uint32_t width = 0; + | ^~~~~~~~ +--- + include/wayland-client.hpp | 1 + + scanner/scanner.cpp | 3 +++ + 2 files changed, 4 insertions(+) + +diff --git a/include/wayland-client.hpp b/include/wayland-client.hpp +index a3f782b..4598a0e 100644 +--- a/include/wayland-client.hpp ++++ b/include/wayland-client.hpp +@@ -29,6 +29,7 @@ + /** \file */ + + #include ++#include + #include + #include + #include +diff --git a/scanner/scanner.cpp b/scanner/scanner.cpp +index bebd71e..37cf7ff 100644 +--- a/scanner/scanner.cpp ++++ b/scanner/scanner.cpp +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + #include + + #include "pugixml.hpp" +@@ -1106,6 +1107,7 @@ int main(int argc, char *argv[]) + wayland_hpp << "#pragma once" << std::endl + << std::endl + << "#include " << std::endl ++ << "#include " << std::endl + << "#include " << std::endl + << "#include " << std::endl + << "#include " << std::endl +@@ -1125,6 +1127,7 @@ int main(int argc, char *argv[]) + wayland_server_hpp << "#pragma once" << std::endl + << std::endl + << "#include " << std::endl ++ << "#include " << std::endl + << "#include " << std::endl + << "#include " << std::endl + << "#include " << std::endl diff --git a/packages/wayland/weston/config/weston.ini b/packages/wayland/weston/config/weston.ini new file mode 100644 index 0000000000..dbbb812c29 --- /dev/null +++ b/packages/wayland/weston/config/weston.ini @@ -0,0 +1,18 @@ +[core] +idle-time=0 + +[shell] + +background-image=/usr/share/weston/libreelec-wallpaper-2160.png +background-type=scale-crop +background-color=0x00000000 +clock-format=minutes-24h +locking=false + +[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 0000000000..05e8c35c1d --- /dev/null +++ b/packages/wayland/weston/package.mk @@ -0,0 +1,63 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="weston" +PKG_VERSION="14.0.2" +PKG_SHA256="b47216b3530da76d02a3a1acbf1846a9cd41d24caa86448f9c46f78f20b6e0ac" +PKG_LICENSE="MIT" +PKG_SITE="https://wayland.freedesktop.org/" +PKG_URL="https://gitlab.freedesktop.org/wayland/weston/-/releases/${PKG_VERSION}/downloads/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain wayland wayland-protocols libdrm libxkbcommon libinput cairo pango libjpeg-turbo dbus seatd" +PKG_LONGDESC="Reference implementation of a Wayland compositor" + +PKG_MESON_OPTS_TARGET="-Dbackend-drm=true \ + -Dbackend-drm-screencast-vaapi=false \ + -Dbackend-headless=false \ + -Dbackend-pipewire=false \ + -Dbackend-rdp=false \ + -Dscreenshare=false \ + -Dbackend-vnc=false \ + -Dbackend-wayland=false \ + -Dbackend-x11=false \ + -Dbackend-default=drm \ + -Drenderer-gl=true \ + -Dxwayland=false \ + -Dsystemd=true \ + -Dremoting=false \ + -Dpipewire=false \ + -Dshell-desktop=true \ + -Dshell-fullscreen=false \ + -Dshell-ivi=false \ + -Dshell-kiosk=false \ + -Ddesktop-shell-client-default="weston-desktop-shell" \ + -Dcolor-management-lcms=false \ + -Dimage-jpeg=true \ + -Dimage-webp=false \ + -Dtools=['terminal'] + -Ddemo-clients=false \ + -Dsimple-clients=[] \ + -Dresize-pool=false \ + -Dwcap-decode=false \ + -Dtest-junit-xml=false \ + -Dtest-skip-is-failure=false \ + -Ddoc=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/libreelec-wallpaper-2160.png + + safe_remove ${INSTALL}/usr/share/wayland-sessions +} + +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 0000000000..f175f0973b --- /dev/null +++ b/packages/wayland/weston/profile.d/04-weston.conf @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +export WAYLAND_DISPLAY=wayland-1 +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 0000000000..db28264db8 --- /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 0000000000..a776af3dfc --- /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 0000000000..37235909d0 --- /dev/null +++ b/packages/web/curl/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) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="curl" +PKG_VERSION="8.14.1" +PKG_SHA256="f4619a1e2474c4bbfedc88a7c2191209c8334b48fa1f4e53fd584cc12e9120dd" +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_CMAKE_OPTS_TARGET="-DENABLE_DEBUG=OFF \ + -DCURL_LTO=ON \ + -DCURL_WERROR=ON \ + -DENABLE_CURLDEBUG=OFF \ + -DENABLE_ARES=OFF \ + -DCURL_DISABLE_HTTP=OFF \ + -DCURL_DISABLE_FTP=OFF \ + -DCURL_DISABLE_FILE=OFF \ + -DCURL_DISABLE_LDAP=ON \ + -DCURL_DISABLE_LDAPS=ON \ + -DCURL_DISABLE_RTSP=OFF \ + -DCURL_DISABLE_PROXY=OFF \ + -DCURL_DISABLE_DICT=ON \ + -DCURL_DISABLE_TELNET=ON \ + -DCURL_DISABLE_TFTP=ON \ + -DCURL_DISABLE_POP3=ON \ + -DCURL_DISABLE_IMAP=ON \ + -DCURL_DISABLE_SMB=ON \ + -DCURL_DISABLE_SMTP=ON \ + -DCURL_DISABLE_GOPHER=ON \ + -DCURL_DISABLE_MQTT=ON \ + -DBUILD_LIBCURL_DOCS=OFF \ + -DENABLE_CURL_MANUAL=OFF \ + -DENABLE_IPV6=ON \ + -DENABLE_THREADED_RESOLVER=ON \ + -DCURL_DISABLE_VERBOSE_STRINGS=OFF \ + -DCURL_WINDOWS_SSPI=OFF \ + -DCURL_DISABLE_COOKIES=OFF \ + -DCURL_HIDDEN_SYMBOLS=ON \ + -DCURL_USE_GSSAPI=OFF \ + -DCURL_BROTLI=OFF \ + -DCURL_ZSTD=OFF \ + -DCURL_USE_GNUTLS=OFF \ + -DCURL_ENABLE_SSL=ON \ + -DCURL_USE_MBEDTLS=OFF \ + -DCURL_CA_BUNDLE=/run/archr/cacert.pem \ + -DCURL_CA_PATH=none \ + -DCURL_USE_LIBPSL=OFF \ + -DCURL_USE_LIBSSH2=OFF \ + -DUSE_LIBRTMP=ON \ + -DUSE_LIBIDN2=ON \ + -DUSE_NGHTTP2=ON" + +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 0000000000..103c994860 --- /dev/null +++ b/packages/web/libmicrohttpd/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="libmicrohttpd" +PKG_VERSION="1.0.1" +PKG_SHA256="a89e09fc9b4de34dde19f4fcb4faaa1ce10299b9908db1132bbfa1de47882b94" +PKG_LICENSE="LGPLv2.1" +PKG_SITE="https://www.gnu.org/software/libmicrohttpd/" +PKG_URL="https://mirrors.kernel.org/gnu/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="--enable-shared \ + --disable-static \ + --disable-examples \ + --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 0000000000..5fd5aab107 --- /dev/null +++ b/packages/web/nghttp2/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="nghttp2" +PKG_VERSION="1.66.0" +PKG_SHA256="00ba1bdf0ba2c74b2a4fe6c8b1069dc9d82f82608af24442d430df97c6f9e631" +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_CMAKE_OPTS_TARGET="-DENABLE_DOC=OFF \ + -DENABLE_FAILMALLOC=OFF \ + -DENABLE_LIB_ONLY=ON \ + -DBUILD_SHARED_LIBS=ON \ + -DBUILD_STATIC_LIBS=OFF" + +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 0000000000..5a4be9da9b --- /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.4" +PKG_SHA256="be8d8554d40e981d1b93b5ff82497c9ad2259f59f675b38f1b5e84624c07fade" +PKG_LICENSE="OSS" +PKG_SITE="https://www.X.org" +PKG_URL="https://xorg.freedesktop.org/archive/individual/app/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain libX11 libxkbfile xrandr" +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 0000000000..b6811876f7 --- /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 0000000000..7cffe36fa6 --- /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.7" +PKG_SHA256="0a288114e5f44e31987042c79aecff1ffad53a8154b8ec971c24a69a80f81f77" +PKG_LICENSE="OSS" +PKG_SITE="https://www.X.org" +PKG_URL="https://xorg.freedesktop.org/archive/individual/app/${PKG_NAME}-${PKG_VERSION}.tar.xz" +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 0000000000..89630c092d --- /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.3" +PKG_SHA256="f8dd7566adb74147fab9964680b6bbadee87cf406a7fcff51718a5e6949b841c" +PKG_LICENSE="OSS" +PKG_SITE="https://www.X.org" +PKG_URL="https://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 0000000000..fa9a51c128 --- /dev/null +++ b/packages/x11/data/xkeyboard-config/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="xkeyboard-config" +PKG_VERSION="2.45" +PKG_SHA256="169e075a92d957a57787c199e84e359df2931b7196c1c5b4a3d576ee6235a87c" +PKG_LICENSE="MIT" +PKG_SITE="https://www.X.org" +PKG_URL="https://www.x.org/releases/individual/data/${PKG_NAME}/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain util-macros" +PKG_LONGDESC="X keyboard extension data files." + +configure_package() { + if [ "${DISPLAYSERVER}" = "x11" ]; then + PKG_DEPENDS_TARGET+=" xkbcomp" + fi +} + +pre_configure_target() { + PKG_MESON_OPTS_TARGET="-Dcompat-rules=true" + + if [ "${DISPLAYSERVER}" = "x11" ]; then + PKG_MESON_OPTS_TARGET+=" -Dxorg-rules-symlinks=true" + else + PKG_MESON_OPTS_TARGET+=" -Dxorg-rules-symlinks=false" + fi +} 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 0000000000..de5246d405 --- /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.11.0" +PKG_SHA256="730022de934cc366bb12439daf202a7bfff52a028cf4573e457642e25a071315" +PKG_LICENSE="OSS" +PKG_SITE="https://www.X.org" +PKG_URL="https://xorg.freedesktop.org/archive/individual/driver/${PKG_NAME}-${PKG_VERSION}.tar.xz" +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 0000000000..dea96c769d --- /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.5.0" +PKG_SHA256="2524c35f196554ea11aef3bba1cf324759454e1d49f98ac026ace2f6003580e6" +PKG_LICENSE="MIT" +PKG_SITE="https://www.freedesktop.org/wiki/Software/libinput/" +PKG_URL="https://xorg.freedesktop.org/archive/individual/driver/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain libinput xorg-server" +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 0000000000..4ce47c3406 --- /dev/null +++ b/packages/x11/driver/xf86-input-synaptics/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="xf86-input-synaptics" +PKG_VERSION="1.10.0" +PKG_SHA256="e0c26adb068edd0869f87a87f5e9127922d61c0265d7692a247a91a5cc1bb5c2" +PKG_LICENSE="GPL" +PKG_SITE="https://lists.freedesktop.org/mailman/listinfo/xorg" +PKG_URL="https://xorg.freedesktop.org/archive/individual/driver/${PKG_NAME}-${PKG_VERSION}.tar.xz" +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}" + +post_configure_target() { + libtool_remove_rpath libtool +} 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 0000000000..f8847e1cb4 --- /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="23.0.0" +PKG_SHA256="4f04f0ea66f3ced0dcc58f617409860163a19c4e8c285cfb5285f36ba09cc061" +PKG_ARCH="x86_64" +PKG_LICENSE="OSS" +PKG_SITE="https://www.x.org/wiki/RadeonFeature/" +PKG_URL="https://www.x.org/archive/individual/driver/${PKG_NAME}-${PKG_VERSION}.tar.xz" +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-intel/package.mk b/packages/x11/driver/xf86-video-intel/package.mk new file mode 100644 index 0000000000..6242141f74 --- /dev/null +++ b/packages/x11/driver/xf86-video-intel/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="xf86-video-intel" +PKG_VERSION="4a64400ec6a7d8c0aba0e6a39b16a5e86d0af843" +PKG_SHA256="d01b788dd2506432d7b203ef80f0c96f28f129a0ef68a8371fe2e9346fc42d1d" +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-xorg-module-dir=${XORG_PATH_MODULES}" + +if [ "${VULKAN_SUPPORT}" = "yes" ]; then + PKG_CONFIGURE_OPTS_TARGET+=" --with-default-dri=3" +else + PKG_CONFIGURE_OPTS_TARGET+=" --with-default-dri=2" +fi + +post_configure_target() { + libtool_remove_rpath libtool +} + +post_makeinstall_target() { + rm -rf ${INSTALL}/usr/share/polkit-1 +} diff --git a/packages/x11/driver/xf86-video-intel/patches/xf86-video-intel-100.01-prefer-iris-and-crocus-over-i965.patch b/packages/x11/driver/xf86-video-intel/patches/xf86-video-intel-100.01-prefer-iris-and-crocus-over-i965.patch new file mode 100644 index 0000000000..d9fe821349 --- /dev/null +++ b/packages/x11/driver/xf86-video-intel/patches/xf86-video-intel-100.01-prefer-iris-and-crocus-over-i965.patch @@ -0,0 +1,15 @@ +--- /src/sna/sna_dri2.c ++++ /src/sna/sna_dri2.c +@@ -3707,8 +3707,10 @@ + return has_i830_dri() ? "i830" : "i915"; + else if (sna->kgem.gen < 040) + return "i915"; ++ else if (sna->kgem.gen < 0100) ++ return "crocus"; + else +- return "i965"; ++ return "iris"; + } + + return s; + 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 0000000000..cd1c69a439 --- /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/modprobe.d/nvidia-modesetting.conf b/packages/x11/driver/xf86-video-nvidia/modprobe.d/nvidia-modesetting.conf new file mode 100644 index 0000000000..0ea2309390 --- /dev/null +++ b/packages/x11/driver/xf86-video-nvidia/modprobe.d/nvidia-modesetting.conf @@ -0,0 +1 @@ +options nvidia-drm modeset=1 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 0000000000..c8f05bb8b4 --- /dev/null +++ b/packages/x11/driver/xf86-video-nvidia/package.mk @@ -0,0 +1,121 @@ +# 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" +PKG_VERSION="575.64.03" +PKG_SHA256="b158910ec52342db8d301d32b4e2d3e5798fb5f0b7b183ad59c71e6f89778eea" +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" + +if [ "${VULKAN_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${VULKAN} vulkan-tools" +fi + +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() { + # Linux kernel modules + mkdir -p ${INSTALL}/$(get_full_module_dir)/nvidia + cp -P kernel/*.ko ${INSTALL}/$(get_full_module_dir)/nvidia + + # GSP firmware files + mkdir -p ${INSTALL}/$(get_full_firmware_dir)/nvidia/${PKG_VERSION} + cp firmware/gsp*.bin ${INSTALL}/$(get_full_firmware_dir)/nvidia/${PKG_VERSION} + + # X driver + 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 + + # GLX extension module for X + 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 + + # Xorg config + mkdir -p ${INSTALL}/etc/X11 + cp ${PKG_DIR}/config/*.conf ${INSTALL}/etc/X11 + + # GLX + mkdir -p ${INSTALL}/usr/lib + cp -P libGLX_nvidia.so.${PKG_VERSION} ${INSTALL}/usr/lib/libGLX_nvidia.so.0 + + # GLVND + mkdir -p ${INSTALL}/usr/share/glvnd/egl_vendor.d + cp -p 10_nvidia.json ${INSTALL}/usr/share/glvnd/egl_vendor.d + + # OpenGL / EGL + mkdir -p ${INSTALL}/usr/lib + cp -p libEGL_nvidia.so.${PKG_VERSION} ${INSTALL}/usr/lib/ + ln -sf libEGL_nvidia.so.${PKG_VERSION} ${INSTALL}/usr/lib/libEGL_nvidia.so.0 + ln -sf libEGL_nvidia.so.0 ${INSTALL}/usr/lib/libEGL_nvidia.so + + # OpenGL core + mkdir -p ${INSTALL}/usr/lib + cp -p libnvidia-eglcore.so.${PKG_VERSION} ${INSTALL}/usr/lib/ + cp -P libnvidia-glcore.so.${PKG_VERSION} ${INSTALL}/usr/lib + cp -p libnvidia-glsi.so.${PKG_VERSION} ${INSTALL}/usr/lib + + # Install Vulkan ICD & SPIR-V lib + if [ "${VULKAN_SUPPORT}" = "yes" ]; then + mkdir -p ${INSTALL}/usr/lib + cp -P libnvidia-glvkspirv.so.${PKG_VERSION} ${INSTALL}/usr/lib + mkdir -p ${INSTALL}/usr/share/vulkan/icd.d + cp -P nvidia_icd.json ${INSTALL}/usr/share/vulkan/icd.d + mkdir -p ${INSTALL}/usr/share/vulkan/implicit_layer.d + cp -P nvidia_layers.json ${INSTALL}/usr/share/vulkan/icd.d + fi + + # nvidia-gpucomp + mkdir -p ${INSTALL}/usr/lib + cp -P libnvidia-gpucomp.so.${PKG_VERSION} ${INSTALL}/usr/lib + + # nvidia-tls + mkdir -p ${INSTALL}/usr/lib + cp -P libnvidia-tls.so.${PKG_VERSION} ${INSTALL}/usr/lib + + # NVIDIA Management Library (NVML) / System Management Interface + 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 + + mkdir -p ${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 + + # Tool for manipulating X server configuration files + mkdir -p ${INSTALL}/usr/bin + ln -s /var/lib/nvidia-xconfig ${INSTALL}/usr/bin/nvidia-xconfig + cp nvidia-xconfig ${INSTALL}/usr/bin/nvidia-main-xconfig + + # VDPAU + 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 + + # App profiles + mkdir -p ${INSTALL}/usr/share/nvidia + cp -P nvidia-application-profiles-${PKG_VERSION}-rc ${INSTALL}/usr/share/nvidia +} 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 0000000000..43525b8c12 --- /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/udev.d/96-nvidia.rules b/packages/x11/driver/xf86-video-nvidia/udev.d/96-nvidia.rules new file mode 100644 index 0000000000..f22410ec40 --- /dev/null +++ b/packages/x11/driver/xf86-video-nvidia/udev.d/96-nvidia.rules @@ -0,0 +1,9 @@ +ACTION!="add|change", GOTO="end_video" +SUBSYSTEM=="pci", ATTR{class}=="0x030000", ATTR{vendor}=="0x10de", GOTO="configure_nvidia" +GOTO="end_video" + +LABEL="configure_nvidia" +ENV{xorg_driver}="nvidia", TAG+="systemd", ENV{SYSTEMD_WANTS}+="xorg-configure@nvidia.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 0000000000..6735ee72bc --- /dev/null +++ b/packages/x11/driver/xf86-video-vmware/package.mk @@ -0,0 +1,21 @@ +# 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.4.0" +PKG_SHA256="aed31ee5ed5ecc6e2226705383e7ad06f7602c1376a295305f376b17af3eb81a" +PKG_ARCH="x86_64" +PKG_LICENSE="OSS" +PKG_SITE="https://www.vmware.com" +PKG_URL="https://xorg.freedesktop.org/releases/individual/driver/${PKG_NAME}-${PKG_VERSION}.tar.xz" +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}" + +post_configure_target() { + libtool_remove_rpath libtool +} diff --git a/packages/x11/font/encodings/package.mk b/packages/x11/font/encodings/package.mk new file mode 100644 index 0000000000..74fb4fc03c --- /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.1.0" +PKG_SHA256="9ff13c621756cfa12e95f32ba48a5b23839e8f577d0048beda66c67dab4de975" +PKG_LICENSE="OSS" +PKG_SITE="https://www.X.org" +PKG_URL="https://xorg.freedesktop.org/archive/individual/font/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain util-macros font-util:host" +PKG_LONGDESC="X font encoding meta files." + +PKG_MESON_OPTS_TARGET="-Dgzip-small-encodings=true \ + -Dgzip-large-encodings=true \ + -Dfontrootdir=/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 0000000000..2607006c66 --- /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.4" +PKG_SHA256="de2f238b4cd72db4228a0ba67829d76a2b7c039e22993d66a722ee385248c628" +PKG_LICENSE="OSS" +PKG_SITE="https://www.X.org" +PKG_URL="https://xorg.freedesktop.org/archive/individual/font/${PKG_NAME}-${PKG_VERSION}.tar.xz" +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 0000000000..501ef2d185 --- /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.4" +PKG_SHA256="25d9c9595013cb8ca08420509993a6434c917e53ca1fec3f63acd45a19d4f982" +PKG_LICENSE="OSS" +PKG_SITE="https://www.X.org" +PKG_URL="https://xorg.freedesktop.org/archive/individual/font/${PKG_NAME}-${PKG_VERSION}.tar.xz" +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 0000000000..0780bb2569 --- /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.3" +PKG_SHA256="79abe361f58bb21ade9f565898e486300ce1cc621d5285bec26e14b6a8618fed" +PKG_LICENSE="OSS" +PKG_SITE="https://www.X.org" +PKG_URL="https://xorg.freedesktop.org/archive/individual/font/${PKG_NAME}-${PKG_VERSION}.tar.xz" +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 0000000000..92e325dd65 --- /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.4.1" +PKG_SHA256="5c9f64123c194b150fee89049991687386e6ff36ef2af7b80ba53efaf368cc95" +PKG_LICENSE="OSS" +PKG_SITE="https://www.X.org" +PKG_URL="https://xorg.freedesktop.org/archive/individual/font/${PKG_NAME}-${PKG_VERSION}.tar.xz" +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 0000000000..7e605e8e68 --- /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.5" +PKG_SHA256="a93c2c788a5ea1c002af7c8662cf9d9821fb1df51b8d2b2c5e0026dfdfea4837" +PKG_LICENSE="OSS" +PKG_SITE="https://www.X.org" +PKG_URL="https://xorg.freedesktop.org/releases/individual/font/${PKG_NAME}-${PKG_VERSION}.tar.xz" +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 0000000000..95f20fa797 --- /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="OFL-1.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 0000000000..e76520b458 --- /dev/null +++ b/packages/x11/lib/libICE/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) 2020-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libICE" +PKG_VERSION="1.1.2" +PKG_SHA256="974e4ed414225eb3c716985df9709f4da8d22a67a2890066bc6dfc89ad298625" +PKG_LICENSE="OSS" +PKG_SITE="https://www.X.org" +PKG_URL="https://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain util-macros xtrans" +PKG_LONGDESC="X Inter-Client Exchange (ICE) protocol library." +PKG_BUILD_FLAGS="+pic" + +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 0000000000..4f8ae67c17 --- /dev/null +++ b/packages/x11/lib/libSM/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="libSM" +PKG_VERSION="1.2.6" +PKG_SHA256="be7c0abdb15cbfd29ac62573c1c82e877f9d4047ad15321e7ea97d1e43d835be" +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_TARGET="toolchain util-macros util-linux libICE" +PKG_LONGDESC="This package provides the main interface to the X11 Session Management library." +PKG_BUILD_FLAGS="+pic" + +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 0000000000..d632e7c6a3 --- /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.8.12" +PKG_SHA256="fa026f9bb0124f4d6c808f9aef4057aad65e7b35d8ff43951cef0abe06bb9a9a" +PKG_LICENSE="OSS" +PKG_SITE="https://www.x.org/" +PKG_URL="https://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.xz" +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 0000000000..3afa79a753 --- /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 0000000000..f2abf84fba --- /dev/null +++ b/packages/x11/lib/libXau/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="libXau" +PKG_VERSION="1.0.12" +PKG_SHA256="74d0e4dfa3d39ad8939e99bda37f5967aba528211076828464d2777d477fc0fb" +PKG_LICENSE="OSS" +PKG_SITE="https://www.X.org" +PKG_URL="https://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain util-macros xorgproto" +PKG_LONGDESC="X authorization file management library" +PKG_BUILD_FLAGS="+pic" + +PKG_MESON_OPTS_TARGET="-Ddefault_library=static \ + -Dprefer_static=true \ + -Dxthreads=true" diff --git a/packages/x11/lib/libXcomposite/package.mk b/packages/x11/lib/libXcomposite/package.mk new file mode 100644 index 0000000000..d4d3b3cc1f --- /dev/null +++ b/packages/x11/lib/libXcomposite/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="libXcomposite" +PKG_VERSION="0.4.6" +PKG_SHA256="fe40bcf0ae1a09070eba24088a5eb9810efe57453779ec1e20a55080c6dc2c87" +PKG_LICENSE="OSS" +PKG_SITE="https://www.X.org" +PKG_URL="https://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain util-macros libXfixes libXext libX11" +PKG_LONGDESC="X Composite Library" +PKG_BUILD_FLAGS="+pic" + +post_configure_target() { + libtool_remove_rpath libtool +} diff --git a/packages/x11/lib/libXdamage/package.mk b/packages/x11/lib/libXdamage/package.mk new file mode 100644 index 0000000000..0034358719 --- /dev/null +++ b/packages/x11/lib/libXdamage/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="libXdamage" +PKG_VERSION="1.1.6" +PKG_SHA256="52733c1f5262fca35f64e7d5060c6fcd81a880ba8e1e65c9621cf0727afb5d11" +PKG_LICENSE="OSS" +PKG_SITE="https://www.X.org" +PKG_URL="https://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.xz" +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" + +post_configure_target() { + libtool_remove_rpath libtool +} diff --git a/packages/x11/lib/libXext/package.mk b/packages/x11/lib/libXext/package.mk new file mode 100644 index 0000000000..460a5fc6cd --- /dev/null +++ b/packages/x11/lib/libXext/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) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libXext" +PKG_VERSION="1.3.6" +PKG_SHA256="edb59fa23994e405fdc5b400afdf5820ae6160b94f35e3dc3da4457a16e89753" +PKG_LICENSE="OSS" +PKG_SITE="https://www.X.org" +PKG_URL="https://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.xz" +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" + +post_configure_target() { + libtool_remove_rpath libtool +} diff --git a/packages/x11/lib/libXfixes/package.mk b/packages/x11/lib/libXfixes/package.mk new file mode 100644 index 0000000000..c18d541c24 --- /dev/null +++ b/packages/x11/lib/libXfixes/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="libXfixes" +PKG_VERSION="6.0.1" +PKG_SHA256="b695f93cd2499421ab02d22744458e650ccc88c1d4c8130d60200213abc02d58" +PKG_LICENSE="OSS" +PKG_SITE="https://www.X.org" +PKG_URL="https://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain util-macros libX11" +PKG_LONGDESC="X Fixes Library" +PKG_BUILD_FLAGS="+pic" + +post_configure_target() { + libtool_remove_rpath libtool +} diff --git a/packages/x11/lib/libXfont2/package.mk b/packages/x11/lib/libXfont2/package.mk new file mode 100644 index 0000000000..ccc3d20de6 --- /dev/null +++ b/packages/x11/lib/libXfont2/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="libXfont2" +PKG_VERSION="2.0.7" +PKG_SHA256="8b7b82fdeba48769b69433e8e3fbb984a5f6bf368b0d5f47abeec49de3e58efb" +PKG_LICENSE="OSS" +PKG_SITE="https://www.X.org" +PKG_URL="https://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.xz" +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" + +post_configure_target() { + libtool_remove_rpath libtool +} diff --git a/packages/x11/lib/libXi/package.mk b/packages/x11/lib/libXi/package.mk new file mode 100644 index 0000000000..06908f4e7b --- /dev/null +++ b/packages/x11/lib/libXi/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) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libXi" +PKG_VERSION="1.8.2" +PKG_SHA256="d0e0555e53d6e2114eabfa44226ba162d2708501a25e18d99cfb35c094c6c104" +PKG_LICENSE="OSS" +PKG_SITE="https://www.x.org/" +PKG_URL="https://www.x.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.xz" +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-malloc0returnsnull \ + --disable-silent-rules \ + --disable-docs \ + --disable-specs \ + --without-xmlto \ + --without-fop \ + --without-xsltproc \ + --without-asciidoc \ + --with-gnu-ld" + +post_configure_target() { + libtool_remove_rpath libtool +} diff --git a/packages/x11/lib/libXinerama/package.mk b/packages/x11/lib/libXinerama/package.mk new file mode 100644 index 0000000000..af6a5cbf01 --- /dev/null +++ b/packages/x11/lib/libXinerama/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) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libXinerama" +PKG_VERSION="1.1.5" +PKG_SHA256="5094d1f0fcc1828cb1696d0d39d9e866ae32520c54d01f618f1a3c1e30c2085c" +PKG_LICENSE="OSS" +PKG_SITE="https://www.X.org" +PKG_URL="https://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain util-macros libXext" +PKG_LONGDESC="libXinerama is the Xinerama library." + +PKG_CONFIGURE_OPTS_TARGET="--enable-static --disable-shared --enable-malloc0returnsnull" + +post_configure_target() { + libtool_remove_rpath libtool +} diff --git a/packages/x11/lib/libXrandr/package.mk b/packages/x11/lib/libXrandr/package.mk new file mode 100644 index 0000000000..67b54b2289 --- /dev/null +++ b/packages/x11/lib/libXrandr/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) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libXrandr" +PKG_VERSION="1.5.4" +PKG_SHA256="1ad5b065375f4a85915aa60611cc6407c060492a214d7f9daf214be752c3b4d3" +PKG_LICENSE="OSS" +PKG_SITE="https://www.X.org" +PKG_URL="https://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.xz" +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" + +post_configure_target() { + libtool_remove_rpath libtool +} diff --git a/packages/x11/lib/libXrender/package.mk b/packages/x11/lib/libXrender/package.mk new file mode 100644 index 0000000000..7a8528f82a --- /dev/null +++ b/packages/x11/lib/libXrender/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="libXrender" +PKG_VERSION="0.9.12" +PKG_SHA256="b832128da48b39c8d608224481743403ad1691bf4e554e4be9c174df171d1b97" +PKG_LICENSE="OSS" +PKG_SITE="https://www.X.org" +PKG_URL="https://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.xz" +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-malloc0returnsnull" + +post_configure_target() { + libtool_remove_rpath libtool +} diff --git a/packages/x11/lib/libXt/package.mk b/packages/x11/lib/libXt/package.mk new file mode 100644 index 0000000000..e4b07114e0 --- /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.3.1" +PKG_SHA256="e0a774b33324f4d4c05b199ea45050f87206586d81655f8bef4dba434d931288" +PKG_LICENSE="OSS" +PKG_SITE="https://www.X.org" +PKG_URL="https://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.xz" +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 0000000000..8678f57ef3 --- /dev/null +++ b/packages/x11/lib/libXtst/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) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libXtst" +PKG_VERSION="1.2.5" +PKG_SHA256="b50d4c25b97009a744706c1039c598f4d8e64910c9fde381994e1cae235d9242" +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_TARGET="toolchain util-macros libXext libXi libX11" +PKG_LONGDESC="The Xtst Library" + +PKG_CONFIGURE_OPTS_TARGET="--with-gnu-ld --without-xmlto" + +post_configure_target() { + libtool_remove_rpath libtool +} diff --git a/packages/x11/lib/libXxf86vm/package.mk b/packages/x11/lib/libXxf86vm/package.mk new file mode 100644 index 0000000000..7b6b2d1bbc --- /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.6" +PKG_SHA256="96af414c73ce1d5449ad04be7f9f27fa8330f844b6dda843ef22e3e1befb3ee3" +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_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 0000000000..942676fd0d --- /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.8" +PKG_SHA256="7b02c3d405236e0d86806b1de9d6868fe60c313628b38350b032914aa4fd14c6" +PKG_LICENSE="OSS" +PKG_SITE="https://www.X.org" +PKG_URL="https://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.xz" +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 0000000000..bd44e9c504 --- /dev/null +++ b/packages/x11/lib/libpciaccess/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="libpciaccess" +PKG_VERSION="0.18.1" +PKG_SHA256="4af43444b38adb5545d0ed1c2ce46d9608cc47b31c2387fc5181656765a6fa76" +PKG_LICENSE="OSS" +PKG_SITE="https://freedesktop.org" +PKG_URL="https://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain util-macros zlib" +PKG_LONGDESC="X.org libpciaccess library." + +PKG_MESON_OPTS_TARGET="-Dpci-ids=/usr/share \ + -Dzlib=enabled" + +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 0000000000..5590a6be91 --- /dev/null +++ b/packages/x11/lib/libxcb/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="libxcb" +PKG_VERSION="1.17.0" +PKG_SHA256="599ebf9996710fea71622e6e184f3a8ad5b43d0e5fa8c4e407123c88a59a6d55" +PKG_LICENSE="OSS" +PKG_SITE="https://xcb.freedesktop.org" +PKG_URL="https://xorg.freedesktop.org/archive/individual/lib/${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="--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 0000000000..8e570ebbd9 --- /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.3" +PKG_SHA256="a929998a8767de7dfa36d6da4751cdbeef34ed630714f2f4a767b351f2442e01" +PKG_LICENSE="OSS" +PKG_SITE="https://gitlab.freedesktop.org/xorg/lib/libxcvt" +PKG_URL="https://www.x.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.xz" +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 0000000000..17c486b6ac --- /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.3" +PKG_SHA256="a9b63eea997abb9ee6a8b4fbb515831c841f471af845a09de443b28003874bec" +PKG_LICENSE="OSS" +PKG_SITE="https://www.X.org" +PKG_URL="https://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.xz" +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_MESON_OPTS_TARGET="-Ddefault_library=static" diff --git a/packages/x11/lib/libxshmfence/package.mk b/packages/x11/lib/libxshmfence/package.mk new file mode 100644 index 0000000000..0a4cd3486c --- /dev/null +++ b/packages/x11/lib/libxshmfence/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="libxshmfence" +PKG_VERSION="1.3.3" +PKG_SHA256="d4a4df096aba96fea02c029ee3a44e11a47eb7f7213c1a729be83e85ec3fde10" +PKG_LICENSE="OSS" +PKG_SITE="https://www.X.org" +PKG_URL="https://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain util-macros xorgproto" +PKG_LONGDESC="libxshmfence is the Shared memory 'SyncFence' synchronization primitive." +PKG_TOOLCHAIN="autotools" +PKG_BUILD_FLAGS="+pic" diff --git a/packages/x11/lib/pixman/package.mk b/packages/x11/lib/pixman/package.mk new file mode 100644 index 0000000000..4230c63a90 --- /dev/null +++ b/packages/x11/lib/pixman/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="pixman" +PKG_VERSION="0.46.2" +PKG_SHA256="d075209d18728b1ca5d0bb864aa047a262a1fde206da8a677d6af75b2ee1ae98" +PKG_LICENSE="OSS" +PKG_SITE="https://www.x.org/" +PKG_URL="https://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." + +if [ "${TARGET_ARCH}" = arm ]; then + if target_has_feature neon; then + PIXMAN_NEON="-Dneon=enabled" + else + PIXMAN_NEON="-Dneon=disabled" + fi + PIXMAN_CONFIG="-Dmmx=disabled -Dsse2=disabled -Dvmx=disabled -Darm-simd=enabled ${PIXMAN_NEON}" +elif [ "${TARGET_ARCH}" = aarch64 ]; then + PIXMAN_CONFIG="-Dmmx=disabled -Dsse2=disabled -Dvmx=disabled -Darm-simd=disabled -Dneon=disabled" +elif [ "${TARGET_ARCH}" = x86_64 ]; then + PIXMAN_CONFIG="-Dmmx=enabled -Dsse2=enabled -Dssse3=disabled -Dvmx=disabled -Darm-simd=disabled -Dneon=disabled" +fi + +PKG_MESON_OPTS_HOST="-Dgtk=disabled \ + -Dtests=disabled \ + -Ddemos=disabled" + +PKG_MESON_OPTS_TARGET="-Dopenmp=disabled \ + -Dloongson-mmi=disabled \ + ${PIXMAN_CONFIG} \ + -Dmips-dspr2=disabled \ + -Dgnu-inline-asm=enabled \ + -Dtimers=false \ + -Dgtk=disabled \ + -Dlibpng=disabled \ + -Dtests=disabled \ + -Ddemos=disabled" + +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 0000000000..ddab6c8a16 --- /dev/null +++ b/packages/x11/lib/xtrans/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="xtrans" +PKG_VERSION="1.6.0" +PKG_SHA256="faafea166bf2451a173d9d593352940ec6404145c5d1da5c213423ce4d359e92" +PKG_LICENSE="OSS" +PKG_SITE="https://www.X.org" +PKG_URL="https://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain util-macros" +PKG_LONGDESC="Abstract network code for X." +PKG_BUILD_FLAGS="-cfg-libs" + +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 0000000000..fac0e6d4b0 --- /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 0000000000..0cb0ef0258 --- /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 0000000000..31ed934450 --- /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 0000000000..cfc1381b76 --- /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 0000000000..36bb562857 --- /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 0000000000..170d9fd93a --- /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: Mon, 2 Nov 2015 15:14:32 -0600 +Subject: fixes bug #1138 + +--- + util/fluxbox-remote.cc | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/util/fluxbox-remote.cc b/util/fluxbox-remote.cc +index 59852e6..504015b 100644 +--- a/util/fluxbox-remote.cc ++++ b/util/fluxbox-remote.cc +@@ -73,7 +73,7 @@ int main(int argc, char **argv) { + if (strcmp(cmd, "result") == 0) { + XTextProperty text_prop; + if (XGetTextProperty(disp, root, &text_prop, atom_result) != 0 +- && text_prop.value > 0 ++ && text_prop.value != 0 + && text_prop.nitems > 0) { + + printf("%s", text_prop.value); +-- +cgit v0.11.2 + diff --git a/packages/x11/other/fluxbox/patches/fluxbox-80-fix-gettext-build.patch b/packages/x11/other/fluxbox/patches/fluxbox-80-fix-gettext-build.patch new file mode 100644 index 0000000000..1d042c068b --- /dev/null +++ b/packages/x11/other/fluxbox/patches/fluxbox-80-fix-gettext-build.patch @@ -0,0 +1,22 @@ +From e9c3dacdbbd3d948c7c6aaa80ee65e0fb8d46d62 Mon Sep 17 00:00:00 2001 +From: Rudi Heitbaum +Date: Mon, 5 May 2025 19:33:06 +1000 +Subject: [PATCH] allow build with gettext 0.24.1 + +make sure iconv.m4 is available for autoconf to find it +--- + configure.ac | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/configure.ac b/configure.ac +index 5e8d09347..ef1a00b3a 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -186,6 +186,7 @@ AC_COMPILE_IFELSE([ + AC_MSG_RESULT([no]) + ]) + ++AM_GNU_GETTEXT_VERSION([0.11.5]) + AM_ICONV + AS_IF([test x$am_cv_proto_iconv_arg1 = "xconst"], [ + AC_DEFINE([HAVE_CONST_ICONV], [1], [Is second argument of iconv() is of type 'const char **' or 'char **']) diff --git a/packages/x11/other/fluxbox/patches/fluxbox-dont_build_fbrun.patch b/packages/x11/other/fluxbox/patches/fluxbox-dont_build_fbrun.patch new file mode 100644 index 0000000000..19fab52946 --- /dev/null +++ b/packages/x11/other/fluxbox/patches/fluxbox-dont_build_fbrun.patch @@ -0,0 +1,11 @@ +diff -Naur fluxbox-1.3.6/Makefile.am fluxbox-1.3.6.patch/Makefile.am +--- fluxbox-1.3.6/Makefile.am 2015-01-05 15:14:15.320478262 +0100 ++++ fluxbox-1.3.6.patch/Makefile.am 2015-01-10 20:39:20.376934793 +0100 +@@ -79,7 +79,6 @@ + include src/Makemodule.am + include src/tests/Makemodule.am + include util/Makemodule.am +-include util/fbrun/Makemodule.am + + uninstall-hook: + rmdir $(DESTDIR)$(pkgdatadir) diff --git a/packages/x11/other/fluxbox/system.d/windowmanager.service b/packages/x11/other/fluxbox/system.d/windowmanager.service new file mode 100644 index 0000000000..d97081e2b8 --- /dev/null +++ b/packages/x11/other/fluxbox/system.d/windowmanager.service @@ -0,0 +1,18 @@ +[Unit] +Description=Fluxbox Window Manager +Requires=xorg.service +After=xorg.service +Before=kodi.service + +[Service] +Environment=DISPLAY=:0 +Environment=HOME=/storage +ExecStart=/usr/bin/fluxbox +KillMode=process +Restart=always +RestartSec=1 +StartLimitInterval=0 +TimeoutStopSec=1s + +[Install] +WantedBy=graphical.target diff --git a/packages/x11/other/fontconfig/package.mk b/packages/x11/other/fontconfig/package.mk new file mode 100644 index 0000000000..44a1631abd --- /dev/null +++ b/packages/x11/other/fontconfig/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) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="fontconfig" +PKG_VERSION="2.17.1" +PKG_SHA256="9f5cae93f4fffc1fbc05ae99cdfc708cd60dfd6612ffc0512827025c026fa541" +PKG_LICENSE="OSS" +PKG_SITE="https://www.freedesktop.org/wiki/Software/fontconfig/" +PKG_URL="https://gitlab.freedesktop.org/api/v4/projects/890/packages/generic/fontconfig/${PKG_VERSION}/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain util-linux util-macros freetype libxml2 zlib expat" +PKG_LONGDESC="Fontconfig is a library for font customization and configuration." +PKG_TOOLCHAIN="configure" + +PKG_CONFIGURE_OPTS_TARGET="--with-arch=${TARGET_ARCH} \ + --with-cache-dir=/storage/.cache/fontconfig \ + --with-default-fonts=/usr/share/fonts \ + --without-add-fonts \ + --disable-dependency-tracking \ + --disable-docs \ + --disable-rpath" + +pre_configure_target() { + # ensure we dont use '-O3' optimization. + CFLAGS=$(echo ${CFLAGS} | sed -e "s|-O3|-O2|") + CXXFLAGS=$(echo ${CXXFLAGS} | sed -e "s|-O3|-O2|") + CFLAGS+=" -I${PKG_BUILD}" + CXXFLAGS+=" -I${PKG_BUILD}" +} + +post_configure_target() { + libtool_remove_rpath libtool +} + +post_makeinstall_target() { + rm -rf ${INSTALL}/usr/bin +} diff --git a/packages/x11/proto/xcb-proto/package.mk b/packages/x11/proto/xcb-proto/package.mk new file mode 100644 index 0000000000..422cc1b3a8 --- /dev/null +++ b/packages/x11/proto/xcb-proto/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="xcb-proto" +PKG_VERSION="1.17.0" +PKG_SHA256="2c1bacd2110f4799f74de6ebb714b94cf6f80fb112316b1219480fd22562148c" +PKG_LICENSE="OSS" +PKG_SITE="https://www.X.org" +PKG_URL="https://xorg.freedesktop.org/archive/individual/proto/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain util-macros Python3:host" +PKG_LONGDESC="X C-language Bindings protocol headers." +PKG_BUILD_FLAGS="-cfg-libs" + +post_makeinstall_target() { + python_remove_source +} diff --git a/packages/x11/proto/xorgproto/package.mk b/packages/x11/proto/xorgproto/package.mk new file mode 100644 index 0000000000..5ad31ffdc5 --- /dev/null +++ b/packages/x11/proto/xorgproto/package.mk @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="xorgproto" +PKG_VERSION="2024.1" +PKG_SHA256="372225fd40815b8423547f5d890c5debc72e88b91088fbfb13158c20495ccb59" +PKG_LICENSE="OSS" +PKG_SITE="https://www.X.org" +PKG_URL="https://xorg.freedesktop.org/archive/individual/proto/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain util-macros" +PKG_LONGDESC="combined X.Org X11 Protocol headers" + +PKG_MESON_OPTS_TARGET="-Dlegacy=false" diff --git a/packages/x11/util/util-macros/package.mk b/packages/x11/util/util-macros/package.mk new file mode 100644 index 0000000000..79491de5ae --- /dev/null +++ b/packages/x11/util/util-macros/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="util-macros" +PKG_VERSION="1.20.2" +PKG_SHA256="9ac269eba24f672d7d7b3574e4be5f333d13f04a7712303b1821b2a51ac82e8e" +PKG_LICENSE="OSS" +PKG_SITE="https://www.X.org" +PKG_URL="https://xorg.freedesktop.org/archive/individual/util/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="X.org autoconf utilities such as M4 macros." +PKG_BUILD_FLAGS="-cfg-libs" + +post_makeinstall_target() { + rm -rf ${INSTALL}/usr +} diff --git a/packages/x11/util/xorg-launch-helper/package.mk b/packages/x11/util/xorg-launch-helper/package.mk new file mode 100644 index 0000000000..efa10705a4 --- /dev/null +++ b/packages/x11/util/xorg-launch-helper/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="xorg-launch-helper" +PKG_VERSION="4" +PKG_SHA256="a7f8809a1810212506893ac5c62d8d17fee7a980fb10d59d1bef36f694767be5" +PKG_LICENSE="GPL-2" +PKG_SITE="https://github.com/sofar/xorg-launch-helper" +PKG_URL="http://foo-projects.org/~sofar/${PKG_NAME}/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain systemd" +PKG_LONGDESC="Xorg-launch-helper is a small utility that transforms the X server process (XOrg) into a daemon." +PKG_TOOLCHAIN="autotools" + +pre_configure_target() { + export LIBS="-lsystemd" +} + +post_makeinstall_target() { + # do not install systemd services + rm -rf ${INSTALL}/usr/lib + mkdir -p ${INSTALL}/usr/bin + cp -P ${PKG_DIR}/scripts/xorg-launch ${INSTALL}/usr/bin +} diff --git a/packages/x11/util/xorg-launch-helper/patches/xorg-launch-helper-automake-1.14.patch b/packages/x11/util/xorg-launch-helper/patches/xorg-launch-helper-automake-1.14.patch new file mode 100644 index 0000000000..cd32b73691 --- /dev/null +++ b/packages/x11/util/xorg-launch-helper/patches/xorg-launch-helper-automake-1.14.patch @@ -0,0 +1,12 @@ +diff -Naur xorg-launch-helper-4/configure.ac xorg-launch-helper-4.patch/configure.ac +--- xorg-launch-helper-4/configure.ac 2012-10-23 21:17:54.000000000 +0200 ++++ xorg-launch-helper-4.patch/configure.ac 2013-12-06 15:57:17.948725894 +0100 +@@ -3,7 +3,7 @@ + + AC_PREREQ([2.68]) + AC_INIT([xorg-launch-helper], [4], [auke-jan.h.kok@intel.com]) +-AM_INIT_AUTOMAKE([-Wall -Werror foreign]) ++AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects]) + AC_CONFIG_FILES([Makefile]) + AC_CONFIG_SRCDIR([src/main.c]) + AC_CONFIG_HEADERS([config.h]) diff --git a/packages/x11/util/xorg-launch-helper/patches/xorg-launch-helper-dont-check-for-libsystemd-daemon.patch b/packages/x11/util/xorg-launch-helper/patches/xorg-launch-helper-dont-check-for-libsystemd-daemon.patch new file mode 100644 index 0000000000..fbb869151c --- /dev/null +++ b/packages/x11/util/xorg-launch-helper/patches/xorg-launch-helper-dont-check-for-libsystemd-daemon.patch @@ -0,0 +1,26 @@ +From 9cd13bb39f2a8ce5d458f5a33010b5c9c5edf131 Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +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 0000000000..77dbc10a39 --- /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 0000000000..8ff4e9c804 --- /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/archr/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/archr/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 0000000000..43d9813298 --- /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 0000000000..126b9de4a3 --- /dev/null +++ b/packages/x11/xserver/xorg-server/package.mk @@ -0,0 +1,108 @@ +# 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.18" +PKG_SHA256="c878d1930d87725d4a5bf498c24f4be8130d5b2646a9fd0f2994deff90116352" +PKG_LICENSE="OSS" +PKG_SITE="http://www.X.org" +PKG_URL="https://www.x.org/releases/individual/xserver/${PKG_NAME}-${PKG_VERSION}.tar.xz" +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)" +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 + + 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 0000000000..a8bee6c428 --- /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 0000000000..a44f945d28 --- /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 0000000000..f206206cb3 --- /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 0000000000..976aee67f5 --- /dev/null +++ b/packages/x11/xserver/xorg-server/scripts/xorg-configure @@ -0,0 +1,90 @@ +#!/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/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/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 + # GL/GLX (GLVND) + ln -sf /usr/lib/libGL_glvnd.so.1 /var/lib/libGL.so + ln -sf /usr/lib/libGLX_glvnd.so.0 /var/lib/libGLX.so + # indirect rendering + ln -sf /usr/lib/libGLX_nvidia.so.0 /var/lib/libGLX_indirect.so.0 + XORG_ARGS="${XORG_ARGS} -ignoreABI" +# Used for AMD & Intel GPUs supported by MESA 3D +else + ln -sf /usr/lib/xorg/modules/extensions/libglx_mesa.so /var/lib/libglx.so + # GL/GLX (GLVND) + ln -sf /usr/lib/libGL_glvnd.so.1 /var/lib/libGL.so + ln -sf /usr/lib/libGLX_glvnd.so.0 /var/lib/libGLX.so + # indirect rendering + ln -sf /usr/lib/libGLX_mesa.so.0 /var/lib/libGLX_indirect.so.0 +fi + +################################################################################ +# setup xorg-settings.conf +################################################################################ + +logger -t Xorg "### starting Xorg with '${DISPLAY} vt01 ${XORG_ARGS}' ###" +mkdir -p /run/archr +echo "XORG_ARGS=\"${XORG_ARGS}\"" >/run/archr/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 0000000000..25725f647e --- /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 0000000000..1721ed6d9c --- /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/archr/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 0000000000..673e6de5d8 --- /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 0000000000..5a63260232 --- /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/ArchR/bootloader/mkimage b/projects/ArchR/bootloader/mkimage new file mode 100644 index 0000000000..de09352b9b --- /dev/null +++ b/projects/ArchR/bootloader/mkimage @@ -0,0 +1,133 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +. config/functions + +mkimage_uboot() { + if [ -f "${RELEASE_DIR}/3rdparty/bootloader/${SUBDEVICE}_uboot.bin" ]; then + # RK3566-Generic and RK3566-Powkiddy_x55 + echo "image: writing ${SUBDEVICE}_uboot.bin to $(basename "${DISK}")..." + dd if="${RELEASE_DIR}/3rdparty/bootloader/${SUBDEVICE}_uboot.bin" of="${DISK}" bs=512 seek=64 conv=sync,noerror,notrunc >"${SAVE_ERROR}" 2>&1 || show_error + elif [ -f "${RELEASE_DIR}/3rdparty/bootloader/uboot.bin" ]; then + echo "image: writing uboot.bin to $(basename "${DISK}")..." + dd if="${RELEASE_DIR}/3rdparty/bootloader/uboot.bin" of="${DISK}" bs=512 seek=64 conv=sync,noerror,notrunc >"${SAVE_ERROR}" 2>&1 || show_error + elif [ -f "${RELEASE_DIR}/3rdparty/bootloader/u-boot.bin" ]; then + # S922X + echo "image: writing u-boot.bin to $(basename "${DISK}")..." + dd if="${RELEASE_DIR}/3rdparty/bootloader/u-boot.bin" of="${DISK}" bs=512 seek=1 conv=sync,noerror,notrunc >"${SAVE_ERROR}" 2>&1 || show_error + elif [ -f "${RELEASE_DIR}/3rdparty/bootloader/u-boot-sunxi-with-spl.bin" ]; then + # H700 + echo "image: writing u-boot-sunxi-with-spl.bin to $(basename "${DISK}")..." + dd if="${RELEASE_DIR}/3rdparty/bootloader/u-boot-sunxi-with-spl.bin" of="${DISK}" bs=1K seek=8 conv=fsync,notrunc >"${SAVE_ERROR}" 2>&1 || show_error + elif [ -f "${RELEASE_DIR}/3rdparty/bootloader/archr-u-boot.img" ]; then + # SM8650 & SM8550 + echo "image: copying archr u-boot files..." + mcopy -o "${RELEASE_DIR}/3rdparty/bootloader/archr-u-boot.img" :: + mcopy -s -o "${RELEASE_DIR}/3rdparty/bootloader/device_trees" :: + else + echo "ERROR no u-boot file found for ${SUBDEVICE}" + fi +} + +mkimage_extlinux() { + if [ -d "${RELEASE_DIR}/3rdparty/bootloader/extlinux" ]; then + echo "image: copying custom extlinux.conf..." + mcopy -s -o "${RELEASE_DIR}/3rdparty/bootloader/extlinux" :: + else + local fdt_type + fdt_type=$(get_fdt_type) + + echo "image: set extlinux.conf to $fdt_type /$(get_fdt)..." + mkdir -p "${IMG_TMP}/extlinux" + + cat << EOF > "${IMG_TMP}/extlinux/extlinux.conf" +LABEL ${DISTRO} + LINUX /${KERNEL_NAME} + ${fdt_type} /$(get_fdt) + APPEND boot=LABEL=${DISTRO_BOOTLABEL} root=LABEL=${DISTRO_ROOTLABEL} disk=LABEL=${DISTRO_DISKLABEL} ${EXTRA_CMDLINE} +EOF + + echo "image: copying extlinux.conf..." + mcopy -s -o "${IMG_TMP}/extlinux" :: + fi +} + +mkimage_bootscr() { + if [ -f "${RELEASE_DIR}/3rdparty/bootloader/${SUBDEVICE}_boot.scr" ]; then + echo "image: copying ${SUBDEVICE}_boot.scr..." + mcopy "${RELEASE_DIR}/3rdparty/bootloader/${SUBDEVICE}_boot.scr" ::/boot.scr + else + echo "cannot find ${RELEASE_DIR}/3rdparty/bootloader/${SUBDEVICE}_boot.scr" + exit 2 + fi +} + +mkimage_dtb() { + echo "image: copying device trees..." + case "$DEVICE" in + RK3326) + mmd ::dtbs 2>/dev/null || true + # Copy only DTBs listed in config.xml for this SUBDEVICE + DTB_LIST=$(xmlstarlet sel -t -v "//archr/RK3326/${SUBDEVICE}/file" "${PROJECT_DIR}/${PROJECT}/config.xml" 2>/dev/null) + if [ -n "${DTB_LIST}" ]; then + for dtb_name in ${DTB_LIST}; do + DTB_FILE="${RELEASE_DIR}/3rdparty/bootloader/device_trees/rockchip/${dtb_name}.dtb" + [ ! -f "${DTB_FILE}" ] && DTB_FILE="${RELEASE_DIR}/3rdparty/bootloader/device_trees/${dtb_name}.dtb" + if [ -f "${DTB_FILE}" ]; then + mcopy "${DTB_FILE}" ::dtbs/ + else + echo "WARNING: DTB not found: ${dtb_name}.dtb" + fi + done + else + # Fallback: copy all DTBs if config.xml parsing fails + mcopy "${RELEASE_DIR}/3rdparty/bootloader/device_trees/"*.dtb ::dtbs/ + fi + mcopy "${RELEASE_DIR}/3rdparty/bootloader/stock" :: + # Copy SUBDEVICE-specific panel overlays, fallback to generic + if [ -d "${RELEASE_DIR}/3rdparty/bootloader/overlays_${SUBDEVICE}" ]; then + echo "image: copying ${SUBDEVICE} panel overlays..." + mmd ::overlays 2>/dev/null || true + mcopy "${RELEASE_DIR}/3rdparty/bootloader/overlays_${SUBDEVICE}/"*.dtbo ::overlays/ + fi + # Copy soysauce overlays into original image (soysauce shares ADC with original) + if [ "${SUBDEVICE}" = "original" ] && [ -d "${RELEASE_DIR}/3rdparty/bootloader/overlays_soysauce" ]; then + echo "image: copying soysauce panel overlays..." + mmd ::overlays/soysauce 2>/dev/null || true + mcopy "${RELEASE_DIR}/3rdparty/bootloader/overlays_soysauce/"*.dtbo ::overlays/soysauce/ + fi + ;; + SM8550|SM8650|SM8250|SDM845) + mcopy -s -o "${RELEASE_DIR}/3rdparty/bootloader/boot" :: + ;; + S922X) + mcopy "${RELEASE_DIR}/3rdparty/bootloader/"*.dtb :: + ;; + *) + mcopy -s "${RELEASE_DIR}/3rdparty/bootloader/device_trees" :: + ;; + esac + + # For devices not handled above (RK3326 handles overlays in its own case) + if [ "$DEVICE" != "RK3326" ] && [ -d "${RELEASE_DIR}/3rdparty/bootloader/overlays" ]; then + echo "image: copying device tree overlays..." + mcopy -s "${RELEASE_DIR}/3rdparty/bootloader/overlays" :: + fi +} + +mkimage_gou_extras() { + echo "image: copying res..." + mcopy "${RELEASE_DIR}/3rdparty/bootloader/res" :: +} + +mkimage_grub() { + echo "image: copying grub files and dtb..." + mcopy -s -o "${RELEASE_DIR}/3rdparty/bootloader/EFI" :: +} + +mkimage_abl() { + echo "image: copying ArchR ABL..." + mcopy "${RELEASE_DIR}/3rdparty/bootloader/archr_abl" :: +} + +mkimage_all diff --git a/projects/ArchR/bootloader/release b/projects/ArchR/bootloader/release new file mode 100644 index 0000000000..4a0cb20a50 --- /dev/null +++ b/projects/ArchR/bootloader/release @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +mkdir -p ${RELEASE_DIR}/3rdparty/bootloader + cp -a ${INSTALL}/usr/share/bootloader/* ${RELEASE_DIR}/3rdparty/bootloader diff --git a/projects/ArchR/bootloader/rkhelper b/projects/ArchR/bootloader/rkhelper new file mode 100644 index 0000000000..a4f4a869f6 --- /dev/null +++ b/projects/ArchR/bootloader/rkhelper @@ -0,0 +1,60 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://arch-r.io) + +PKG_SOC="${DEVICE/RK/rk}" + +# Make idbloader.img +case "${DEVICE}" in + RK3326) + # mkimage does not support packing second level bootloader on rk3326 + ${PKG_BUILD}/tools/mkimage -n px30 -T rksd -d "${PKG_DDR_BIN}" -C bzip2 idbloader.img + cat ${PKG_MINILOADER} >> idbloader.img + ;; + RK3399|RK3566|RK3588) + [ "${PKG_SOC}" = "rk3566" ] && PKG_SOC="rk3568" + ${PKG_BUILD}/tools/mkimage -n "${PKG_SOC}" -T rksd -d "${PKG_DDR_BIN}":"${PKG_MINILOADER}" -C bzip2 idbloader.img + ;; +esac + +# Pack uboot.img +case "${DEVICE}" in + RK3326|RK3399) + ${PKG_RKBIN}/tools/loaderimage --pack --uboot u-boot-dtb.bin uboot.img 0x00200000 + ;; +esac + +# Merge trust.img +case "${DEVICE}" in + RK3326) + cat >trust.ini < + + + rk3326-gameconsole-r36s + rk3326-gameconsole-r33s + rk3326-odroid-go2 + rk3326-odroid-go2-v11 + rk3326-odroid-go3 + rk3326-anbernic-rg351m + rk3326-anbernic-rg351v + rk3326-gameforce-chi + rk3326-magicx-xu10 + rk3326-powkiddy-rgb10 + rk3326-gameconsole-soysauce + + + rk3326-gameconsole-eeclone + rk3326-powkiddy-rgb10x + rk3326-magicx-xu-mini-m + rk3326-odroid-go2 + + + diff --git a/projects/ArchR/devices/RK3326/bootloader/update.sh b/projects/ArchR/devices/RK3326/bootloader/update.sh new file mode 100755 index 0000000000..39bd5bd99a --- /dev/null +++ b/projects/ArchR/devices/RK3326/bootloader/update.sh @@ -0,0 +1,98 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-24 JELOS (https://github.com/JustEnoughLinuxOS) +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +[ -z "$SYSTEM_ROOT" ] && SYSTEM_ROOT="" +[ -z "$BOOT_ROOT" ] && BOOT_ROOT="/flash" +[ -z "$BOOT_PART" ] && BOOT_PART=$(df "$BOOT_ROOT" | tail -1 | awk {' print $1 '}) + +# mount $BOOT_ROOT rw +mount -o remount,rw $BOOT_ROOT + +# Setup logging +echo -n > $BOOT_ROOT/update.log +log() { echo $*; echo $* >> $BOOT_ROOT/update.log; } +log "Starting bootloader update" + +# identify the boot device +if [ -z "$BOOT_DISK" ]; then + case $BOOT_PART in + /dev/mmcblk*) BOOT_DISK=$(echo $BOOT_PART | sed -e "s,p[0-9]*,,g");; + esac +fi + +SUBDEVICE=$(sed -n 's|^.* uboot.hwid_adc=\([^, ]\),.*$|\1|p' /proc/cmdline) +if [ -n "$SUBDEVICE" ]; then + log "Subdevice from cmdline: $SUBDEVICE" +elif [ -f $BOOT_ROOT/boot.scr ]; then + grep -q "rk3326-anbernic-rg351m.dtb" $BOOT_ROOT/boot.scr && SUBDEVICE=a || SUBDEVICE=b + log "Subdevice from boot.scr: $SUBDEVICE" +elif [ -f $BOOT_ROOT/boot.ini ]; then + grep -q "rk3326-anbernic-rg351m.dtb" $BOOT_ROOT/boot.ini && SUBDEVICE=a || SUBDEVICE=b + log "Subdevice from boot.ini: $SUBDEVICE" +else + SUBDEVICE=a + log "Subdevice fallback: $SUBDEVICE" +fi + +log "Updating device trees..." +if [ -d "$BOOT_ROOT/device_trees" ]; then + mv $BOOT_ROOT/device_trees/*.dtb $BOOT_ROOT + rm -rf $BOOT_ROOT/device_trees +fi +cp -f $SYSTEM_ROOT/usr/share/bootloader/device_trees/* $BOOT_ROOT + +if [ -d $SYSTEM_ROOT/usr/share/bootloader/overlays ]; then + log "Updating device tree overlays..." + mkdir -p $BOOT_ROOT/overlays + cp -f $SYSTEM_ROOT/usr/share/bootloader/overlays/* $BOOT_ROOT/overlays +fi + +if [ ! -f $BOOT_ROOT/extlinux/extlinux.conf ]; then + log "Creating extlinux.conf..." + mkdir -p $BOOT_ROOT/extlinux + cp -f $SYSTEM_ROOT/usr/share/bootloader/extlinux/* $BOOT_ROOT/extlinux/ +fi + +CONSOLEDEV=$(grep -l Y /sys/devices/platform/*/*/*/tty/tty*/console | head -1 | xargs -r dirname) +if [ "${SUBDEVICE}" == "original" ]; then + log "Using legacy u-boot " + UBOOT_VARIANT="original_uboot.bin" +elif [ -z "${CONSOLEDEV}" ]; then + log "Cannot find UART console" + UBOOT_VARIANT="clone_uboot.bin" +elif grep -qi ff178000 "${CONSOLEDEV}/iomem_base"; then + log "Detected UART5 console at ${CONSOLEDEV}" + UBOOT_VARIANT="clone_uboot.bin.uart5" +else + log "Assuming default (UART2) console at ${CONSOLEDEV}" + UBOOT_VARIANT="clone_uboot.bin" +fi + +for BOOT_IMAGE in ${UBOOT_VARIANT} uboot.bin clone_uboot.bin; do + if [ -f "$SYSTEM_ROOT/usr/share/bootloader/$BOOT_IMAGE" ]; then + log "Updating $BOOT_IMAGE on $BOOT_DISK..." + # instead of using small bs, read the missing part from target and do a perfectly aligned write + { + dd if=$BOOT_DISK bs=32K count=1 + cat $SYSTEM_ROOT/usr/share/bootloader/$BOOT_IMAGE + } | dd of=$BOOT_DISK bs=4M conv=fsync &>/dev/null + break + fi +done + +log "Updating boot.scr from ${SUBDEVICE}_boot.scr..." +cp -f $SYSTEM_ROOT/usr/share/bootloader/${SUBDEVICE}_boot.scr $BOOT_ROOT/boot.scr +# prevent interference (especially with legacy u-boot) +if [ -f $BOOT_ROOT/boot.ini ]; then + mv $BOOT_ROOT/boot.ini $BOOT_ROOT/boot.ini.bak +fi + +log "Finishing bootloader update..." +# mount $BOOT_ROOT ro +sync +mount -o remount,ro $BOOT_ROOT + +echo "UPDATE" > /storage/.boot.hint +echo "DONE" diff --git a/projects/ArchR/devices/RK3326/linux/dts/rockchip/retrogame_joypad_s2_f1.dtsi b/projects/ArchR/devices/RK3326/linux/dts/rockchip/retrogame_joypad_s2_f1.dtsi new file mode 100644 index 0000000000..7a0f231091 --- /dev/null +++ b/projects/ArchR/devices/RK3326/linux/dts/rockchip/retrogame_joypad_s2_f1.dtsi @@ -0,0 +1,122 @@ +/* + This is a skeleton of joypad with 2 sticks and FN (MODE) button. + Fits devices with 1 stick and 2 extra face buttons too. + By including this ans setting I/O properties only, + devices should get consistent controller id and mapping + thus reusing non-game configs: + * SDL gamecontrollerdb.txt + * ES es_input.cfg + * Retroarch gamepad +*/ + +/ { + joypad: retrogame_joypad_s2_f1 { + /* These drivers emit the same button set which makes this skeleton ADC-agnostic */ + /* compatible = "archr-joypad"; */ + /* compatible = "archr-singleadc-joypad"; */ + + /* These are constants making Joystick Guid the same */ + joypad-name = "retrogame_joypad_s2_f1"; + joypad-vendor = <0x484B>; + joypad-product = <0x1121>; /* 11 inherited, 2 for number of sticks, 1 for number of FN */ + joypad-revision = <0x0100>; + + /* require explicit status = "okay"; */ + status = "disabled"; + + /* adc calculate scale */ + button-adc-scale = <2>; + + /* adc deadzone range */ + button-adc-deadzone = <64>; + + /* + specifies fuzz value that is used to filter noise from + the event stream. + */ + button-adc-fuzz = <32>; + button-adc-flat = <32>; + + /* poll device interval (ms), adc read interval */ + poll-interval = <10>; + + /* gpio button auto repeat set value : default disable */ + /* + autorepeat; + */ + + /* meaningful node names for easier use */ + up { + label = "GPIO DPAD-UP"; + linux,code = ; + }; + down { + label = "GPIO DPAD-DOWN"; + linux,code = ; + }; + left { + label = "GPIO DPAD-LEFT"; + linux,code = ; + }; + right { + label = "GPIO DPAD-RIGHT"; + linux,code = ; + }; + + a { + label = "GPIO BTN-A"; + linux,code = ; + }; + b { + label = "GPIO BTN-B"; + linux,code = ; + }; + x { + label = "GPIO BTN-X"; + linux,code = ; + }; + y { + label = "GPIO BTN-Y"; + linux,code = ; + }; + + select { + label = "GPIO BTN_SELECT"; + linux,code = ; + }; + start { + label = "GPIO BTN_START"; + linux,code = ; + }; + mode { + label = "GPIO BTN_F"; + linux,code = ; + }; + + tl { + label = "GPIO BTN_TL"; + linux,code = ; + }; + tr { + label = "GPIO BTN_TR"; + linux,code = ; + }; + tl2 { + label = "GPIO BTN_TL2"; + linux,code = ; + }; + tr2 { + label = "GPIO BTN_TR2"; + linux,code = ; + }; + + thumbl { + label = "GPIO BTN_THUMBL"; + linux,code = ; + }; + thumbr { + label = "GPIO BTN_THUMBR"; + linux,code = ; + }; + }; +}; diff --git a/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-anbernic-rg351m.dts b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-anbernic-rg351m.dts new file mode 100644 index 0000000000..c12bb79944 --- /dev/null +++ b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-anbernic-rg351m.dts @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2019 Hardkernel Co., Ltd + * Copyright (c) 2020 Theobroma Systems Design und Consulting GmbH + * Copyright (c) 2022 Maya Matuszczyk + */ + +/dts-v1/; +#include "rk3326-odroid-go.dtsi" + +/ { + model = "Anbernic RG351M"; + compatible = "anbernic,rg351m", "rockchip,rk3326"; + + battery: battery { + compatible = "simple-battery"; + charge-full-design-microamp-hours = <3500000>; + charge-term-current-microamp = <350000>; + constant-charge-current-max-microamp = <2000000>; + constant-charge-voltage-max-microvolt = <4200000>; + factory-internal-resistance-micro-ohms = <180000>; + voltage-max-design-microvolt = <4100000>; + voltage-min-design-microvolt = <3500000>; + + ocv-capacity-celsius = <20>; + ocv-capacity-table-0 = <4046950 100>, <4001920 95>, <3967900 90>, <3919950 85>, + <3888450 80>, <3861850 75>, <3831540 70>, <3799130 65>, + <3768190 60>, <3745650 55>, <3726610 50>, <3711630 45>, + <3696720 40>, <3685660 35>, <3674950 30>, <3663050 25>, + <3649470 20>, <3635260 15>, <3616920 10>, <3592440 5>, + <3574170 0>; + }; + + vibrator { + compatible = "pwm-vibrator"; + pwms = <&pwm0 0 1000000 0>; + pwm-names = "enable"; + }; +}; + +/delete-node/ &vcc_host; /* conflicts with pwm vibration motor */ + +&internal_display { + compatible = "elida,kd35t133"; + iovcc-supply = <&vcc_lcd>; + vdd-supply = <&vcc_lcd>; + rotation = <270>; +}; + +&pwm0 { + status = "okay"; +}; + +&rk817_charger { + /* This device does not have a current sense resistor */ + //rockchip,resistor-sense-micro-ohms = <0>; + monitored-battery = <&battery>; +}; diff --git a/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-anbernic-rg351m.dtsi b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-anbernic-rg351m.dtsi new file mode 100644 index 0000000000..1dadde198c --- /dev/null +++ b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-anbernic-rg351m.dtsi @@ -0,0 +1,480 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2019 Hardkernel Co., Ltd + * Copyright (c) 2020 Theobroma Systems Design und Consulting GmbH + * Copyright (c) 2022 Maya Matuszczyk + */ + +/dts-v1/; +#include +#include +#include +#include +#include "rk3326.dtsi" + +/ { + aliases { + mmc0 = &sdmmc; + }; + + chosen { + stdout-path = "serial2:115200n8"; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + power-supply = <&vcc_bl>; + pwms = <&pwm1 0 25000 0>; + }; + + /* + * LED is a tri-state. Driven high it is red, driven low it is + * green, and not driven at all (pin set to input) it is amber. + * Additionally, there is a 2nd LED that is not controllable + * that is on (red) when plugged in to power. + */ + gpio_led: gpio-leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pin>; + + red_green_led: led-0 { + color = ; + gpios = <&gpio2 RK_PB5 GPIO_ACTIVE_HIGH>; + function = LED_FUNCTION_CHARGING; + }; + }; + + rk817-sound { + compatible = "simple-audio-card"; + simple-audio-card,name = "rk817_int"; + simple-audio-card,format = "i2s"; + simple-audio-card,hp-det-gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>; + simple-audio-card,mclk-fs = <256>; + simple-audio-card,widgets = + "Microphone", "Mic Jack", + "Headphone", "Headphones", + "Speaker", "Speaker"; + simple-audio-card,routing = + "MICL", "Mic Jack", + "Headphones", "HPOL", + "Headphones", "HPOR", + "Speaker", "SPKO"; + + simple-audio-card,codec { + sound-dai = <&rk817>; + }; + + simple-audio-card,cpu { + sound-dai = <&i2s1_2ch>; + }; + }; + + vccsys: regulator-vccsys { + compatible = "regulator-fixed"; + regulator-name = "vcc3v8_sys"; + regulator-always-on; + regulator-min-microvolt = <3800000>; + regulator-max-microvolt = <3800000>; + }; + + vibrator { + compatible = "pwm-vibrator"; + pwms = <&pwm0 0 1000000 0>; + pwm-names = "enable"; + }; +}; + +&cpu0 { + cpu-supply = <&vdd_arm>; +}; + +&cpu1 { + cpu-supply = <&vdd_arm>; +}; + +&cpu2 { + cpu-supply = <&vdd_arm>; +}; + +&cpu3 { + cpu-supply = <&vdd_arm>; +}; + +&cru { + assigned-clocks = <&cru PLL_NPLL>, + <&cru ACLK_BUS_PRE>, <&cru ACLK_PERI_PRE>, + <&cru HCLK_BUS_PRE>, <&cru HCLK_PERI_PRE>, + <&cru PCLK_BUS_PRE>, <&cru SCLK_GPU>; + + assigned-clock-rates = <1188000000>, + <200000000>, <200000000>, + <150000000>, <150000000>, + <100000000>, <200000000>; +}; + +&display_subsystem { + status = "okay"; +}; + +&dsi { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + ports { + mipi_out: port@1 { + reg = <1>; + + mipi_out_panel: endpoint { + remote-endpoint = <&mipi_in_panel>; + }; + }; + }; + + internal_display: panel@0 { + reg = <0>; + backlight = <&backlight>; + reset-gpios = <&gpio3 RK_PC0 GPIO_ACTIVE_LOW>; + + port { + mipi_in_panel: endpoint { + remote-endpoint = <&mipi_out_panel>; + }; + }; + }; +}; + +&dsi_dphy { + status = "okay"; +}; + +&gpu { + mali-supply = <&vdd_logic>; + status = "okay"; +}; + +&i2c0 { + clock-frequency = <400000>; + i2c-scl-falling-time-ns = <16>; + i2c-scl-rising-time-ns = <280>; + status = "okay"; + + rk817: pmic@20 { + compatible = "rockchip,rk817"; + reg = <0x20>; + #clock-cells = <1>; + clock-names = "mclk"; + clock-output-names = "rk808-clkout1", "xin32k"; + clocks = <&cru SCLK_I2S1_OUT>; + interrupt-parent = <&gpio0>; + interrupts = ; + pinctrl-0 = <&pmic_int>, <&i2s1_2ch_mclk>; + pinctrl-names = "default"; + #sound-dai-cells = <0>; + wakeup-source; + + vcc1-supply = <&vccsys>; + vcc2-supply = <&vccsys>; + vcc3-supply = <&vccsys>; + vcc4-supply = <&vccsys>; + vcc5-supply = <&vccsys>; + vcc6-supply = <&vccsys>; + vcc7-supply = <&vccsys>; + vcc8-supply = <&vccsys>; + + regulators { + vdd_logic: DCDC_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1150000>; + regulator-min-microvolt = <950000>; + regulator-name = "vdd_logic"; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vdd_arm: DCDC_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1350000>; + regulator-min-microvolt = <950000>; + regulator-name = "vdd_arm"; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc_ddr"; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_3v3: DCDC_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "vcc_3v3"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_1v8: LDO_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1800000>; + regulator-min-microvolt = <1800000>; + regulator-name = "vcc_1v8"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd_1v0: LDO_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1000000>; + regulator-min-microvolt = <1000000>; + regulator-name = "vdd_1v0"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vcc3v3_pmu: LDO_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "vcc3v3_pmu"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vccio_sd: LDO_REG5 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <1800000>; + regulator-name = "vccio_sd"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_sd: LDO_REG6 { + regulator-boot-on; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "vcc_sd"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_bl: LDO_REG7 { + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "vcc_bl"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_lcd: LDO_REG8 { + regulator-max-microvolt = <2800000>; + regulator-min-microvolt = <2800000>; + regulator-name = "vcc_lcd"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <2800000>; + }; + }; + + vcc_wifi: LDO_REG9 { + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "vcc_wifi"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + usb_midu: BOOST { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <5400000>; + regulator-min-microvolt = <5000000>; + regulator-name = "usb_midu"; + }; + }; + + rk817_codec: codec { + rockchip,mic-in-differential; + }; + }; +}; + +&i2s1_2ch { + status = "okay"; +}; + +&io_domains { + vccio1-supply = <&vcc_3v3>; + vccio2-supply = <&vccio_sd>; + vccio3-supply = <&vcc_3v3>; + vccio4-supply = <&vcc_3v3>; + vccio5-supply = <&vcc_3v3>; + vccio6-supply = <&vcc_3v3>; + status = "okay"; +}; + +&pmu_io_domains { + pmuio1-supply = <&vcc3v3_pmu>; + pmuio2-supply = <&vcc3v3_pmu>; + status = "okay"; +}; + +&pwm0 { + status = "okay"; +}; + +&pwm1 { + status = "okay"; +}; + +&saradc { + vref-supply = <&vcc_1v8>; + status = "okay"; +}; + +&sdmmc { + cap-sd-highspeed; + card-detect-delay = <200>; + cd-gpios = <&gpio0 RK_PA3 GPIO_ACTIVE_LOW>; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + vmmc-supply = <&vcc_sd>; + vqmmc-supply = <&vccio_sd>; + status = "okay"; +}; + +&sfc { + #address-cells = <1>; + pinctrl-0 = <&sfc_clk &sfc_cs0 &sfc_bus2>; + pinctrl-names = "default"; + #size-cells = <0>; + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <108000000>; + spi-rx-bus-width = <2>; + spi-tx-bus-width = <1>; + }; +}; + +&tsadc { + status = "okay"; +}; + +&u2phy { + status = "okay"; + + u2phy_host: host-port { + status = "okay"; + }; + + u2phy_otg: otg-port { + status = "disabled"; + }; +}; + +&usb20_otg { + status = "okay"; +}; + +&uart2 { + pinctrl-0 = <&uart2m1_xfer>; + pinctrl-names = "default"; + status = "okay"; +}; + +&vopb { + status = "okay"; +}; + +&vopb_mmu { + status = "okay"; +}; + +&pinctrl { + headphone { + hp_det: hp-det { + rockchip,pins = <2 RK_PC6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + + leds { + led_pin: led-pin { + rockchip,pins = <2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pmic { + dc_det: dc-det { + rockchip,pins = <0 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + pmic_int: pmic-int { + rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + soc_slppin_gpio: soc_slppin_gpio { + rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_output_low>; + }; + + soc_slppin_rst: soc_slppin_rst { + rockchip,pins = <0 RK_PA4 2 &pcfg_pull_none>; + }; + + soc_slppin_slp: soc_slppin_slp { + rockchip,pins = <0 RK_PA4 1 &pcfg_pull_none>; + }; + }; +}; diff --git a/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-anbernic-rg351v.dts b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-anbernic-rg351v.dts new file mode 100644 index 0000000000..26658a37f4 --- /dev/null +++ b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-anbernic-rg351v.dts @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2019 Hardkernel Co., Ltd + * Copyright (c) 2020 Theobroma Systems Design und Consulting GmbH + * Copyright (c) 2022 Maya Matuszczyk + */ + +/dts-v1/; +#include "rk3326-odroid-go.dtsi" + +/ { + model = "Anbernic RG351V"; + compatible = "anbernic,rg351v", "rockchip,rk3326"; + + aliases { + mmc0 = &sdio; + mmc1 = &sdmmc; + }; + + gpio-keys-vol { + compatible = "gpio-keys"; + autorepeat; + pinctrl-0 = <&btn_pins_vol>; + pinctrl-names = "default"; + + button-vol-down { + gpios = <&gpio2 RK_PA1 GPIO_ACTIVE_LOW>; + label = "VOLUMEDOWN"; + linux,code = ; + }; + + button-volume-up { + gpios = <&gpio2 RK_PA0 GPIO_ACTIVE_LOW>; + label = "VOLUMEUP"; + linux,code = ; + }; + }; + + battery: battery { + compatible = "simple-battery"; + charge-full-design-microamp-hours = <3500000>; + charge-term-current-microamp = <350000>; + constant-charge-current-max-microamp = <2000000>; + constant-charge-voltage-max-microvolt = <4200000>; + factory-internal-resistance-micro-ohms = <180000>; + voltage-max-design-microvolt = <4100000>; + voltage-min-design-microvolt = <3500000>; + + ocv-capacity-celsius = <20>; + ocv-capacity-table-0 = <4046950 100>, <4001920 95>, <3967900 90>, <3919950 85>, + <3888450 80>, <3861850 75>, <3831540 70>, <3799130 65>, + <3768190 60>, <3745650 55>, <3726610 50>, <3711630 45>, + <3696720 40>, <3685660 35>, <3674950 30>, <3663050 25>, + <3649470 20>, <3635260 15>, <3616920 10>, <3592440 5>, + <3574170 0>; + }; + + vibrator { + compatible = "pwm-vibrator"; + pwms = <&pwm0 0 1000000 0>; + pwm-names = "enable"; + }; +}; + +/* conflicts with pwm vibration motor */ +/delete-node/ &vcc_host; + +/* Device only has 1 LED compared to Odroid Go Advance */ +/delete-node/ &gpio_led; + +&internal_display { + compatible = "anbernic,rg351v-panel", "newvision,nv3051d"; + iovcc-supply = <&vcc_lcd>; + vdd-supply = <&vcc_lcd>; +}; + +&io_domains { + vccio1-supply = <&vccio_sd>; +}; + +/delete-node/ &pwm_led; + +&pwm0 { + status = "okay"; +}; + +/delete-node/ &pwm3; + +&rk817_charger { + /* This device does not have a current sense resistor */ + rockchip,resistor-sense-micro-ohms = <0>; + monitored-battery = <&battery>; +}; + +&sdio { + cap-sd-highspeed; + card-detect-delay = <200>; + cd-gpios = <&gpio3 RK_PB4 GPIO_ACTIVE_LOW>; /*[> CD GPIO <]*/ + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + vmmc-supply = <&vcc_sd>; + vqmmc-supply = <&vccio_sd>; + status = "okay"; +}; + +&vcc_sd { + regulator-max-microvolt = <3000000>; + regulator-min-microvolt = <1800000>; +}; + +&vccio_sd { + regulator-max-microvolt = <1800000>; +}; + +&pinctrl { + btns { + btn_pins_vol: btn-pins-vol { + rockchip,pins = <2 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +}; diff --git a/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-batlexp-g350.dts b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-batlexp-g350.dts new file mode 100644 index 0000000000..9cad95fc57 --- /dev/null +++ b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-batlexp-g350.dts @@ -0,0 +1,163 @@ +/// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* +* Copyright (c) 2025 lcdyk <2670878301@qq.com> +*/ + +/dts-v1/; +#include "rk3326-gameconsole-r3xs.dtsi" +#include "retrogame_joypad_s2_f1.dtsi" + +/ { + model = "BatleXP G350"; + compatible = "batlexp,g350", "rockchip,rk3326"; +}; + +&joypad { + compatible = "archr-singleadc-joypad"; + pwms = <&pwm0 0 200000000 0>; + pwm-names = "enable"; + rumble-boost-weak = <0x0000>; + rumble-boost-strong = <0x0000>; + joypad-name = "retrogame_joypad"; + joypad-vendor = <0x484B>; + joypad-product = <0x1101>; + joypad-revision = <0x0100>; + + status = "okay"; + + /* gpio pincontrol setup */ + pinctrl-names = "default"; + pinctrl-0 = <&btn_pins>; + pinctrl-1 = <&pwm0_pin>; + + /* Analog mux define */ + io-channel-names = "amux_adc"; + io-channels = <&saradc 1>; + + /* adc mux channel count */ + amux-count = <4>; + /* non-default wiring */ + amux-channel-mapping = <2 0 1 3>; + /* adc mux enable gpio */ + amux-a-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>; + amux-b-gpios = <&gpio3 RK_PB3 GPIO_ACTIVE_LOW>; + /* adc mux enable gpio */ + amux-en-gpios = <&gpio3 RK_PB5 GPIO_ACTIVE_LOW>; + + /* + Analog Stick data tuning value(precent) + p = positive direction, n = negative direction + report value = (real_adc_data * tuning_value) / 100 + */ + abs_x-p-tuning = <200>; + abs_x-n-tuning = <200>; + + abs_y-p-tuning = <200>; + abs_y-n-tuning = <200>; + + abs_rx-p-tuning = <200>; + abs_rx-n-tuning = <200>; + + abs_ry-p-tuning = <200>; + abs_ry-n-tuning = <200>; + + /* gpio button auto repeat set value : default disable */ + /* + autorepeat; + */ + invert-absx; + invert-absy; + invert-absrx; + + up { gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_LOW>; }; + down { gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_LOW>; }; + left { gpios = <&gpio1 RK_PB6 GPIO_ACTIVE_LOW>; }; + right { gpios = <&gpio1 RK_PB7 GPIO_ACTIVE_LOW>; }; + a { gpios = <&gpio1 RK_PA2 GPIO_ACTIVE_LOW>; }; + b { gpios = <&gpio1 RK_PA5 GPIO_ACTIVE_LOW>; }; + x { gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_LOW>; }; + y { gpios = <&gpio1 RK_PA6 GPIO_ACTIVE_LOW>; }; + select { gpios = <&gpio3 RK_PB1 GPIO_ACTIVE_LOW>; }; + start { gpios = <&gpio3 RK_PB4 GPIO_ACTIVE_LOW>; }; + mode { gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_LOW>; }; + tl { gpios = <&gpio2 RK_PA6 GPIO_ACTIVE_LOW>; }; + tr { gpios = <&gpio2 RK_PA7 GPIO_ACTIVE_LOW>; }; + tl2 { gpios = <&gpio3 RK_PB2 GPIO_ACTIVE_LOW>; }; + tr2 { gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; }; + thumbl { gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; }; + thumbr { gpios = <&gpio2 RK_PA3 GPIO_ACTIVE_LOW>; }; +}; + +&dsi { + internal_display: panel@0 { + compatible = "archr,generic-dsi"; + iovcc-supply = <&vcc_lcd>; + vcc-supply = <&vcc_lcd>; + reset-gpios = <&gpio3 RK_PC0 GPIO_ACTIVE_LOW>; + panel_description = + "G size=52,70 delays=20,150,20,120,20 format=rgb888 lanes=4 flags=0xe03", + + "M clock=50000 horizontal=640,450,70,450 vertical=480,17,5,13 default=1", + "M clock=50000 horizontal=640,450,85,450 vertical=480,17,106,13", + "M clock=50010 horizontal=640,450,127,450 vertical=480,17,90,13", + "M clock=50010 horizontal=640,450,73,450 vertical=480,17,110,13", + "M clock=50830 horizontal=640,450,85,450 vertical=480,17,34,13", + "M clock=53200 horizontal=640,450,128,450 vertical=480,17,24,13", + "M clock=50400 horizontal=640,450,77,450 vertical=480,17,10,13", + "M clock=50310 horizontal=640,450,85,450 vertical=480,17,6,13", + "M clock=54600 horizontal=640,450,94,450 vertical=480,17,46,13", + "M clock=65370 horizontal=640,450,113,450 vertical=480,17,14,13", + "M clock=76050 horizontal=640,450,85,450 vertical=480,17,10,13", + "M clock=100620 horizontal=640,450,85,450 vertical=480,17,6,13", + + "I seq=b9f11283", + "I seq=b1000000da80", + "I seq=b2001370", + "I seq=b31010282803ff00000000", + "I seq=b480", + "I seq=b50a0a", + "I seq=b67f7f", + "I seq=b82662f063", + "I seq=ba338105f90e0e2000000000000000442500900a0000014f01000037", + "I seq=bc47", + "I seq=bf021100", + "I seq=c0737350500000125000", + "I seq=c15300323277d1cccc77773333", + "I seq=c68200bfff00ff", + "I seq=c7b8000a000000", + "I seq=c810401e02", + "I seq=cc0b", + "I seq=e000070d37353f4144060c0d0f111012141a00070d37353f4144060c0d0f111012141a", + "I seq=e307070b0b0b0b00000000ff00c010", + "I seq=e9c810020000b0b11131232880b0b127080004020000000004020000008888ba60240888888888888888ba713518888888888800000001000000000000000000", + "I seq=ea970a820203070000000000008188ba17538888888888888088ba0642888888888888230000028000000000000000000000000000000000000000000000", + "I seq=efffff01", + "I seq=11 wait=200", + "I seq=29 wait=50"; + }; +}; + +&pinctrl { + btns { + btn_pins: btn-pins { + rockchip,pins = + <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +}; diff --git a/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-device-group-r36.dtsi b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-device-group-r36.dtsi new file mode 100644 index 0000000000..bfc399984a --- /dev/null +++ b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-device-group-r36.dtsi @@ -0,0 +1,7 @@ +/ { + archr,device_switch { + r33s = "rk3326-gameconsole-r33s"; + r36s = "rk3326-gameconsole-r36s"; + rgb10x = "rk3326-powkiddy-rgb10x"; + }; +}; diff --git a/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-gameconsole-eeclone.dts b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-gameconsole-eeclone.dts new file mode 100644 index 0000000000..bd3e69bc0e --- /dev/null +++ b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-gameconsole-eeclone.dts @@ -0,0 +1,961 @@ +/// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2024-present ROCKNIX (https://github.com/ROCKNIX) + * Copyright (c) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + * Copyright (c) 2025 Danil Zagoskin + */ + +/dts-v1/; +#include +#include +#include +#include +#include "rk3326.dtsi" + +/ { + model = "R36S Clone"; + compatible = "gameconsole,eeclone", "rockchip,rk3326"; + + aliases { + mmc0 = &emmc; + mmc1 = &sdmmc; + mmc2 = &sdio; + serial1 = &uart2; + serial2 = &uart5; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + pwms = <&pwm1 0 25000 0>; + brightness-levels = < + 0 1 2 3 4 5 6 7 + 8 9 10 11 12 13 14 15 + 16 17 18 19 20 21 22 23 + 24 25 26 27 28 29 30 31 + 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 + 48 49 50 51 52 53 54 55 + 56 57 58 59 60 61 62 63 + 64 65 66 67 68 69 70 71 + 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 + 88 89 90 91 92 93 94 95 + 96 97 98 99 100 101 102 103 + 104 105 106 107 108 109 110 111 + 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 + 128 129 130 131 132 133 134 135 + 136 137 138 139 140 141 142 143 + 144 145 146 147 148 149 150 151 + 152 153 154 155 156 157 158 159 + 160 161 162 163 164 165 166 167 + 168 169 170 171 172 173 174 175 + 176 177 178 179 180 181 182 183 + 184 185 186 187 188 189 190 191 + 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 + 208 209 210 211 212 213 214 215 + 216 217 218 219 220 221 222 223 + 224 225 226 227 228 229 230 231 + 232 233 234 235 236 237 238 239 + 240 241 242 243 244 245 246 247 + 248 249 250 251 252 253 254 255>; + default-brightness-level = <128>; + }; + + battery: battery { + compatible = "simple-battery"; + charge-full-design-microamp-hours = <4000000>; + charge-term-current-microamp = <200000>; + constant-charge-current-max-microamp = <1500000>; + constant-charge-voltage-max-microvolt = <4200000>; + factory-internal-resistance-micro-ohms = <100000>; + voltage-max-design-microvolt = <4100000>; + voltage-min-design-microvolt = <3300000>; + + ocv-capacity-celsius = <20>; + ocv-capacity-table-0 = + <4046950 100>, <4001920 95>, <3967900 90>, <3940000 85>, + <3910000 80>, <3870000 75>, <3830000 70>, <3790000 65>, + <3750000 60>, <3720000 55>, <3690000 50>, <3650000 45>, + <3610000 40>, <3570000 35>, <3540000 30>, <3500000 25>, + <3460000 20>, <3420000 15>, <3380000 10>, <3340000 5>, + <3300000 0>; + }; + + adc_keys: adc-keys { + compatible = "adc-keys"; + io-channels = <&saradc 2>; + io-channel-names = "buttons"; + keyup-threshold-microvolt = <1800000>; + poll-interval = <100>; + + /* disabled by default, dtbo may enable it when needed */ + status = "disabled"; + + button-vol-up { + press-threshold-microvolt = <15000>; + label = "VOLUMEUP"; + linux,code = ; + }; + + button-vol-down { + press-threshold-microvolt = <300000>; + label = "VOLUMEDOWN"; + linux,code = ; + }; + }; + + joypad: joypad { + compatible = "archr-singleadc-joypad"; + + joypad-name = "r36s_Gamepad"; + joypad-product = <0x1188>; + joypad-revision = <0x0188>; + + status = "okay"; + + /* gpio pincontrol setup */ + pinctrl-names = "default"; + pinctrl-0 = <&btn_pins>; + + /* Analog mux define */ + io-channel-names = "amux_adc"; + io-channels = <&saradc 1>; + + /* adc mux channel count */ + amux-count = <4>; + /* non-default wiring */ + amux-channel-mapping = <2 3 1 0>; + /* adc mux enable gpio */ + amux-en-gpios = <&gpio2 RK_PB4 GPIO_ACTIVE_LOW>; /* rocker0-gpios */ + /* adc mux select(a,b) gpio */ + amux-a-gpios = <&gpio2 RK_PC0 GPIO_ACTIVE_LOW>; /* rocker1-gpios */ + amux-b-gpios = <&gpio2 RK_PB7 GPIO_ACTIVE_LOW>; /* rocker-gpios */ + + /* adc calculate scale */ + button-adc-scale = <2>; + + /* adc deadzone range */ + button-adc-deadzone = <64>; + + /* + specifies fuzz value that is used to filter noise from + the event stream. + */ + button-adc-fuzz = <32>; + button-adc-flat = <32>; + + /* + Analog Stick data tuning value(precent) + p = positive direction, n = negative direction + report value = (real_adc_data * tuning_value) / 100 + */ + abs_x-p-tuning = <200>; + abs_x-n-tuning = <200>; + + abs_y-p-tuning = <200>; + abs_y-n-tuning = <200>; + + abs_rx-p-tuning = <200>; + abs_rx-n-tuning = <200>; + + abs_ry-p-tuning = <200>; + abs_ry-n-tuning = <200>; + + /* poll device interval (ms), adc read interval */ + poll-interval = <10>; + + /* gpio button auto repeat set value : default disable */ + /* + autorepeat; + */ + + /* + joypad driver is poll-device driver. + poll-device is does not support wakeup-source. + */ + sw1 { + gpios = <&gpio3 RK_PC6 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-UP"; + linux,code = ; // 0x220 + }; + sw2 { + gpios = <&gpio3 RK_PC7 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-DOWN"; + linux,code = ; // 0x221 + }; + sw3 { + gpios = <&gpio3 RK_PC4 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-LEFT"; + linux,code = ; // 0x222 + }; + sw4 { + gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-RIGHT"; + linux,code = ; // 0x223 + }; + + sw5 { + gpios = <&gpio3 RK_PC0 GPIO_ACTIVE_LOW>; + label = "GPIO KEY BTN-A"; + linux,code = ; // 0x131 + }; + sw6 { + gpios = <&gpio3 RK_PC1 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-B"; + linux,code = ; // 0x130 + }; + sw7 { + gpios = <&gpio3 RK_PC3 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-Y"; + linux,code = ; // 0x134 + }; + sw8 { + gpios = <&gpio3 RK_PC2 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-X"; + linux,code = ; // 0x133 + }; + + sw11 { + gpios = <&gpio2 RK_PB5 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_THUMBL"; + linux,code = ; // 0x2c2 + }; + sw12 { + gpios = <&gpio2 RK_PB6 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_THUMBR"; + linux,code = ; // 0x2c3 + }; + + sw13 { + gpios = <&gpio3 RK_PB2 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_FN"; + linux,code = ; // 0x2c4 + }; + + sw15 { + gpios = <&gpio3 RK_PB5 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-LEFT"; + linux,code = ; // 0x02 + }; + sw16 { + gpios = <&gpio3 RK_PB3 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-RIGHT"; + linux,code = ; // 0x05 + }; + sw19 { + gpios = <&gpio3 RK_PD0 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_SELECT"; + linux,code = ; + }; + sw20 { + gpios = <&gpio3 RK_PB4 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-RIGHT2"; + linux,code = ; + }; + sw21 { + gpios = <&gpio3 RK_PB6 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-LEFT2"; + linux,code = ; + }; + sw22 { + gpios = <&gpio3 RK_PD1 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_START"; + linux,code = ; + }; + }; + + leds: gpio-leds { + compatible = "gpio-leds"; + pinctrl-0 = <&led_pins>; + pinctrl-names = "default"; + + /* charge_red_gpio = <&gpio0 17 0>; */ + led-0 { + color = ; + default-state = "off"; + function = LED_FUNCTION_CHARGING; + linux,default-trigger = "none"; + gpios = <&gpio0 RK_PC1 GPIO_ACTIVE_HIGH>; + }; + + /* charge_blue_gpio = <&gpio0 0 0>; */ + led-1 { + color = ; + default-state = "on"; + function = LED_FUNCTION_POWER; + linux,default-trigger = "default-on"; + gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; + }; + }; + + spk_amp: audio-amplifier { + compatible = "simple-audio-amplifier"; + enable-gpios = <&gpio3 RK_PA7 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&spk_amp_enable_h>; + pinctrl-names = "default"; + sound-name-prefix = "Speaker Amp"; + }; + + rk817-sound-amplified { + compatible = "simple-audio-card"; + pinctrl-names = "default"; + pinctrl-0 = <&hp_det>; + simple-audio-card,name = "rk817_ext"; + simple-audio-card,aux-devs = <&spk_amp>; + simple-audio-card,format = "i2s"; + simple-audio-card,hp-det-gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>; + simple-audio-card,mclk-fs = <256>; + simple-audio-card,widgets = + "Headphone", "Headphones", + "Speaker", "Internal Speakers"; + /* despite it's just a mono speaker, we need to route both Speaker Amp channels + Otherwise, the second channel stays on and keeps amp enabled */ + simple-audio-card,routing = + "Headphones", "HPOL", + "Headphones", "HPOR", + "Internal Speakers", "Speaker Amp OUTL", + "Internal Speakers", "Speaker Amp OUTR", + "Speaker Amp INL", "HPOL", + "Speaker Amp INR", "HPOR"; + + simple-audio-card,pin-switches = "Internal Speakers"; + + status = "disabled"; + + simple-audio-card,codec { + sound-dai = <&rk817>; + }; + + simple-audio-card,cpu { + sound-dai = <&i2s1_2ch>; + }; + }; + + rk817-sound-simple { + compatible = "simple-audio-card"; + pinctrl-names = "default"; + pinctrl-0 = <&hp_det>; + simple-audio-card,name = "rk817_ext"; + simple-audio-card,format = "i2s"; + simple-audio-card,hp-det-gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>; + simple-audio-card,mclk-fs = <256>; + simple-audio-card,widgets = + "Headphone", "Headphones", + "Speaker", "Internal Speakers"; + simple-audio-card,routing = + "Headphones", "HPOL", + "Headphones", "HPOR", + "Internal Speakers", "SPKO"; + + status = "disabled"; + + simple-audio-card,codec { + sound-dai = <&rk817>; + }; + + simple-audio-card,cpu { + sound-dai = <&i2s1_2ch>; + }; + }; + + vccsys: vccsys { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + + vcc-phy-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_phy"; + regulator-always-on; + regulator-boot-on; + }; + + vcc18_lcd0: vcc18-lcd0 { + compatible = "regulator-fixed"; + regulator-name = "vcc18_lcd0_n"; + gpio = <&gpio0 RK_PB5 GPIO_ACTIVE_HIGH>; + enable-active-high; + pinctrl-0 = <&vcc18_lcd_n>; + pinctrl-names = "default"; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_host: vcc_host { + compatible = "regulator-fixed"; + regulator-name = "vcc_host"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio3 RK_PA4 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&vcc5_usb>; + pinctrl-names = "default"; + enable-active-high; + regulator-always-on; + regulator-boot-on; + vin-supply = <&usb_midu>; + }; +}; + +&dmc { + center-supply = <&vdd_logic>; +}; + +&cpu0 { + cpu-supply = <&vdd_arm>; +}; + +&cpu1 { + cpu-supply = <&vdd_arm>; +}; + +&cpu2 { + cpu-supply = <&vdd_arm>; +}; + +&cpu3 { + cpu-supply = <&vdd_arm>; +}; + +&cru { + assigned-clocks = <&cru PLL_NPLL>, + <&cru ACLK_BUS_PRE>, <&cru ACLK_PERI_PRE>, + <&cru HCLK_BUS_PRE>, <&cru HCLK_PERI_PRE>, + <&cru PCLK_BUS_PRE>, <&cru SCLK_GPU>; + + assigned-clock-rates = <1188000000>, + <200000000>, <200000000>, + <150000000>, <150000000>, + <100000000>, <200000000>; +}; + +&display_subsystem { + status = "okay"; +}; + +&dsi { + status = "okay"; + + ports { + mipi_out: port@1 { + reg = <1>; + + mipi_out_panel: endpoint { + remote-endpoint = <&mipi_in_panel>; + }; + }; + }; + + internal_display: panel@0 { + compatible = "magicx,xu10-panel", "sitronix,st7703"; + iovcc-supply = <&vcc18_lcd0>; + vcc-supply = <&vcc18_lcd0>; + reg = <0>; + backlight = <&backlight>; + reset-gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&lcd_rst>; + + port { + mipi_in_panel: endpoint { + remote-endpoint = <&mipi_out_panel>; + }; + }; + }; +}; + +&dsi_dphy { + status = "okay"; +}; + +&gpu { + mali-supply = <&vdd_logic>; + status = "okay"; +}; + +&i2c0 { + clock-frequency = <400000>; + i2c-scl-falling-time-ns = <16>; + i2c-scl-rising-time-ns = <280>; + status = "okay"; + + rk817: pmic@20 { + compatible = "rockchip,rk817"; + reg = <0x20>; + interrupt-parent = <&gpio0>; + interrupts = ; + clock-output-names = "rk808-clkout1", "xin32k"; + clock-names = "mclk"; + clocks = <&cru SCLK_I2S1_OUT>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int>, <&i2s1_2ch_mclk>; + rockchip,system-power-controller; + wakeup-source; + #clock-cells = <1>; + #sound-dai-cells = <0>; + + vcc1-supply = <&vccsys>; + vcc2-supply = <&vccsys>; + vcc3-supply = <&vccsys>; + vcc4-supply = <&vccsys>; + vcc5-supply = <&vccsys>; + vcc6-supply = <&vccsys>; + vcc7-supply = <&vcc_3v0>; + vcc8-supply = <&vccsys>; + + regulators { + vdd_logic: DCDC_REG1 { + regulator-name = "vdd_logic"; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1350000>; + regulator-initial-mode = <0x02>; + regulator-ramp-delay = <6001>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vdd_arm: DCDC_REG2 { + regulator-name = "vdd_arm"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-initial-mode = <0x02>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-name = "vcc_ddr"; + regulator-always-on; + regulator-boot-on; + regulator-initial-mode = <0x02>; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_3v0: DCDC_REG4 { + regulator-name = "vcc_3v0"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-initial-mode = <0x02>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcc_1v0: LDO_REG1 { + regulator-name = "vcc_1v0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vcc1v8_soc: LDO_REG2 { + regulator-name = "vcc1v8_soc"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc1v0_soc: LDO_REG3 { + regulator-name = "vcc1v0_soc"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vcc3v0_pmu: LDO_REG4 { + regulator-name = "vcc3v0_pmu"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vccio_sd: LDO_REG5 { + regulator-name = "vccio_sd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_sd: LDO_REG6 { + regulator-name = "vcc_sd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc2v8_dvp: LDO_REG7 { + regulator-name = "vcc2v8_dvp"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc3v0_dvp: LDO_REG8 { + regulator-name = "vcc3v0_dvp"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vdd1v5_dvp: LDO_REG9 { + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + regulator-name = "vdd1v5_dvp"; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <1500000>; + }; + }; + + usb_midu: BOOST { + regulator-name = "usb_midu"; + regulator-min-microvolt = <4900000>; + regulator-max-microvolt = <5400000>; + regulator-always-on; + regulator-boot-on; + }; + + /* + otg_switch: OTG_SWITCH { + regulator-name = "otg_switch"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + */ + }; + + rk817_charger: charger { + monitored-battery = <&battery>; + rockchip,resistor-sense-micro-ohms = <10000>; + rockchip,sleep-enter-current-microamp = <300000>; + rockchip,sleep-filter-current-microamp = <100000>; + }; + + rk817_codec: codec { + rockchip,mic-in-differential; + }; + }; +}; + +/* I2S 1 Channel Used Header(P2):1(GPIO2.C3),2(.C2), 3(.C1), 4(.C5), 5(.C4) */ +&i2s1_2ch { + status = "okay"; + #sound-dai-cells = <0>; +}; + +&io_domains { + vccio1-supply = <&vcc2v8_dvp>; + vccio2-supply = <&vccio_sd>; + vccio3-supply = <&vcc1v8_soc>; + vccio4-supply = <&vcc_3v0>; + vccio5-supply = <&vcc_3v0>; + vccio6-supply = <&vcc1v8_soc>; + status = "okay"; +}; + +&isp { + status = "okay"; +}; + +&isp_mmu { + status = "okay"; +}; + +&pmu_io_domains { + pmuio1-supply = <&vcc3v0_pmu>; + pmuio2-supply = <&vcc3v0_pmu>; + status = "okay"; +}; + +&csi_dphy { + status = "okay"; +}; + +&pwm1 { + status = "okay"; +}; + +&saradc { + vref-supply = <&vcc1v8_soc>; + status = "okay"; +}; + +&sdmmc { + cap-sd-highspeed; + card-detect-delay = <800>; + cd-gpios = <&gpio0 RK_PA3 GPIO_ACTIVE_LOW>; /*[> ff370000 PD_SDCARD CD GPIO <]*/ + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + vqmmc-supply = <&vccio_sd>; + vmmc-supply = <&vcc_sd>; + status = "okay"; +}; + +&sdio { + cap-sd-highspeed; + max-frequency = <100000000>; + cd-gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_LOW>; + card-detect-delay = <800>; + supports-sd; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + vqmmc-supply = <&vcc2v8_dvp>; + vmmc-supply = <&vcc3v0_dvp>; + status = "okay"; +}; + +&emmc { + status = "okay"; + no-sdio; + no-sd; + disable-wp; + non-removable; + num-slots = <1>; +}; + +&tsadc { + status = "okay"; +}; + +&u2phy { + status = "okay"; + + u2phy_host: host-port { + status = "okay"; + }; + + u2phy_otg: otg-port { + status = "disabled"; + }; +}; + +&usb20_otg { + status = "okay"; +}; + +&vopb { + status = "okay"; +}; + +&vopb_mmu { + status = "okay"; +}; +&pinctrl { + btns { + btn_pins: btn-pins { + rockchip,pins = + <2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB3 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PC0 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PC1 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PC2 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PC3 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PC4 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PC6 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PC7 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PD0 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PD1 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + headphone { + hp_det: hp-det { + rockchip,pins = <2 RK_PC6 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + gpio-lcd { + lcd_rst: lcd-rst { + rockchip,pins = <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + vcc18-lcd { + vcc18_lcd_n: vcc18-lcd-n { + rockchip,pins = <0 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + vcc5-usb { + vcc5_usb: vcc5-usb { + rockchip,pins = <3 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + gpio-led { + led_pins: led-pins { + rockchip,pins = + <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>, /* charge_blue_gpio = <&gpio0 0 0>; */ + <0 RK_PC1 RK_FUNC_GPIO &pcfg_pull_none>; /* charge_red_gpio = <&gpio0 17 0>; */ + }; + }; + + pmic { + dc_det: dc-det { + rockchip,pins = <0 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + pmic_int: pmic-int { + rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + soc_slppin_gpio: soc_slppin_gpio { + rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_output_low>; + }; + + soc_slppin_rst: soc_slppin_rst { + rockchip,pins = <0 RK_PA4 2 &pcfg_pull_none>; + }; + + soc_slppin_slp: soc_slppin_slp { + rockchip,pins = <0 RK_PA4 1 &pcfg_pull_none>; + }; + }; + + speaker { + spk_amp_enable_h: spk-amp-enable-h { + rockchip,pins = <3 RK_PA7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&uart5 { + status = "okay"; +}; +&uart2 { + status = "disabled"; +}; + + +&internal_display { + compatible = "archr,generic-dsi"; + panel_description = + "G size=153,85 delays=20,20,20,120,20 format=rgb888 lanes=4 flags=0xe03", + + "M clock=50000 horizontal=720,140,80,140 vertical=720,20,4,20 default=1", + "M clock=50000 horizontal=720,140,100,140 vertical=720,20,150,20", + "M clock=50040 horizontal=720,140,112,140 vertical=720,20,140,20", + "M clock=51400 horizontal=720,140,132,140 vertical=720,20,148,20", + "M clock=50140 horizontal=720,140,90,140 vertical=720,20,40,20", + "M clock=56900 horizontal=720,140,90,140 vertical=720,20,114,20", + "M clock=50400 horizontal=720,140,92,140 vertical=720,20,10,20", + "M clock=50220 horizontal=720,140,80,140 vertical=720,20,15,20", + "M clock=54600 horizontal=720,140,112,140 vertical=720,20,57,20", + "M clock=75450 horizontal=720,140,95,140 vertical=720,20,153,20", + "M clock=75330 horizontal=720,140,80,140 vertical=720,20,15,20", + "M clock=100440 horizontal=720,140,80,140 vertical=720,20,15,20", + + "I seq=b9f11283", + "I seq=b1000000da80", + "I seq=b23c1230", + "I seq=b31010282803ff00000000", + "I seq=b480", + "I seq=b50a0a", + "I seq=b69797", + "I seq=b82622f013", + "I seq=ba338105f90e0e2000000000000000442500900a0000014f01000037", + "I seq=bc47", + "I seq=bf021100", + "I seq=c0737350500000127000", + "I seq=c12500323277e4ffffcccc7777", + "I seq=c68200bfff00ff", + "I seq=c7b8000a000000", + "I seq=c810401e02", + "I seq=cc0b", + "I seq=e0000b102c3d3f423a070d0f131513140f16000b102c3d3f423a070d0f131513140f16", + "I seq=e307070b0b0b0b00000000ff00c010", + "I seq=e9c8100a000080811231234f86a000470800000c00000000000c00000098028baf4602888888888898138baf5713888888888800000000000000000000000000", + "I seq=ea970c090909780000000000009f318ba8317588888888889f208ba820648888888888230000027100000000000000000000000000000040808100000000", + "I seq=efffff01", + "I seq=11 wait=250", + "I seq=29 wait=50"; +}; + + diff --git a/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-gameconsole-r33s.dts b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-gameconsole-r33s.dts new file mode 100644 index 0000000000..21dbab6d19 --- /dev/null +++ b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-gameconsole-r33s.dts @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * # Copyright (C) 2022-24 JELOS (https://github.com/JustEnoughLinuxOS) + */ + +/dts-v1/; +#include "rk3326-gameconsole-r3xs.dtsi" +#include "rk3326-device-group-r36.dtsi" + +/ { + model = "Game Console R33S"; + compatible = "gameconsole,r33s", "rockchip,rk3326"; + + archr,device_switch { + this = "r33s"; + }; + + builtin_gamepad: r33s_joypad { + compatible = "archr-singleadc-joypad"; + pinctrl-names = "default"; + pinctrl-0 = <&btn_pins>; + joypad-name = "r33s_joypad"; + joypad-product = <0x0AA2>; + joypad-revision = <0x0100>; + joypad-vendor = <0x0001>; + + status = "okay"; + amux-count = <0>; + /* poll device interval (ms), adc read interval */ + poll-interval = <10>; + pwms = <&pwm0 0 1000000000 0>; + pwm-names = "enable"; + rumble-boost-weak = <0x0000>; + rumble-boost-strong = <0x0000>; + + button-sw1 { + gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_LOW>; + label = "DPAD-UP"; + linux,code = ; + }; + button-sw2 { + gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_LOW>; + label = "DPAD-DOWN"; + linux,code = ; + }; + button-sw3 { + gpios = <&gpio1 RK_PB6 GPIO_ACTIVE_LOW>; + label = "DPAD-LEFT"; + linux,code = ; + }; + button-sw4 { + gpios = <&gpio1 RK_PB7 GPIO_ACTIVE_LOW>; + label = "DPAD-RIGHT"; + linux,code = ; + }; + button-sw5 { + gpios = <&gpio1 RK_PA2 GPIO_ACTIVE_LOW>; + label = "BTN-A"; + linux,code = ; + }; + button-sw6 { + gpios = <&gpio1 RK_PA5 GPIO_ACTIVE_LOW>; + label = "BTN-B"; + linux,code = ; + }; + button-sw7 { + gpios = <&gpio1 RK_PA6 GPIO_ACTIVE_LOW>; + label = "BTN-Y"; + linux,code = ; + }; + button-sw8 { + gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_LOW>; + label = "BTN-X"; + linux,code = ; + }; + button-sw9 { + gpios = <&gpio2 RK_PA6 GPIO_ACTIVE_LOW>; + label = "TOP-LEFT"; + linux,code = ; + }; + button-sw10 { + gpios = <&gpio2 RK_PA7 GPIO_ACTIVE_LOW>; + label = "TOP-RIGHT"; + linux,code = ; + }; + button-sw11 { + gpios = <&gpio3 RK_PB1 GPIO_ACTIVE_LOW>; + label = "SELECT"; + linux,code = ; + }; + button-sw12 { + gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; + label = "TOP-RIGHT 2"; + linux,code = ; + }; + button-sw13 { + gpios = <&gpio3 RK_PB2 GPIO_ACTIVE_LOW>; + label = "TOP-LEFT 2"; + linux,code = ; + }; + button-sw14 { + gpios = <&gpio3 RK_PB4 GPIO_ACTIVE_LOW>; + label = "START"; + linux,code = ; + }; + }; +}; + +&pinctrl { + btns { + btn_pins: btn-pins { + rockchip,pins = <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + }; +}; diff --git a/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-gameconsole-r36s.dts b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-gameconsole-r36s.dts new file mode 100644 index 0000000000..86309e8534 --- /dev/null +++ b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-gameconsole-r36s.dts @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * # Copyright (C) 2022-24 JELOS (https://github.com/JustEnoughLinuxOS) + */ + +/dts-v1/; +#include "rk3326-gameconsole-r3xs.dtsi" +#include "rk3326-device-group-r36.dtsi" + +/ { + model = "Game Console R36S"; + compatible = "gameconsole,r35s", "gameconsole,r36s", "rockchip,rk3326"; + + archr,device_switch { + this = "r36s"; + }; + + joypad: odroidgo3-joypad { + compatible = "odroidgo3-joypad"; + pwms = <&pwm0 0 200000000 0>; + pwm-names = "enable"; + rumble-boost-weak = <0x0000>; + rumble-boost-strong = <0x0000>; + + joypad-name = "r36s_Gamepad"; + joypad-product = <0x1188>; + joypad-revision = <0x0188>; + + status = "okay"; + + /* gpio pincontrol setup */ + pinctrl-names = "default"; + pinctrl-0 = <&btn_pins>; + pinctrl-1 = <&pwm0_pin>; + + /* Analog mux define */ + io-channel-names = "amux_adc"; + io-channels = <&saradc 1>; + + /* adc mux channel count */ + amux-count = <4>; + /* adc mux select(a,b) gpio */ + amux-a-gpios = <&gpio3 RK_PB3 GPIO_ACTIVE_LOW>; + amux-b-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>; + /* adc mux enable gpio */ + amux-en-gpios = <&gpio3 RK_PB5 GPIO_ACTIVE_LOW>; + + /* adc calculate scale */ + button-adc-scale = <2>; + + /* adc deadzone range */ + button-adc-deadzone = <64>; + + /* + specifies fuzz value that is used to filter noise from + the event stream. + */ + button-adc-fuzz = <32>; + button-adc-flat = <32>; + + /* + Analog Stick data tuning value(precent) + p = positive direction, n = negative direction + report value = (real_adc_data * tuning_value) / 100 + */ + abs_x-p-tuning = <200>; + abs_x-n-tuning = <200>; + + abs_y-p-tuning = <200>; + abs_y-n-tuning = <200>; + + abs_rx-p-tuning = <200>; + abs_rx-n-tuning = <200>; + + abs_ry-p-tuning = <200>; + abs_ry-n-tuning = <200>; + + /* poll device interval (ms), adc read interval */ + poll-interval = <10>; + + /* required for RG36S */ + invert-absx; + invert-absy; + + /* gpio button auto repeat set value : default disable */ + /* + autorepeat; + */ + + /* + joypad driver is poll-device driver. + poll-device is does not support wakeup-source. + */ + sw1 { + gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-UP"; + linux,code = ; // 0x220 + }; + sw2 { + gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-DOWN"; + linux,code = ; // 0x221 + }; + sw3 { + gpios = <&gpio1 RK_PB6 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-LEFT"; + linux,code = ; // 0x222 + }; + sw4 { + gpios = <&gpio1 RK_PB7 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-RIGHT"; + linux,code = ; // 0x223 + }; + sw5 { + gpios = <&gpio1 RK_PA2 GPIO_ACTIVE_LOW>; + label = "GPIO KEY BTN-A"; + linux,code = ; // 0x131 + }; + sw6 { + gpios = <&gpio1 RK_PA5 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-B"; + linux,code = ; // 0x130 + }; + sw7 { + gpios = <&gpio1 RK_PA6 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-Y"; + linux,code = ; // 0x134 + }; + sw8 { + gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-X"; + linux,code = ; // 0x133 + }; + sw11 { + gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_THUMBL"; + linux,code = ; // 0x2c2 + }; + sw12 { + gpios = <&gpio2 RK_PA3 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_THUMBR"; + linux,code = ; // 0x2c3 + }; + sw13 { + gpios = <&gpio2 RK_PA4 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_FN"; + linux,code = ; // 0x2c4 + }; + sw15 { + gpios = <&gpio2 RK_PA6 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-LEFT"; + linux,code = ; // 0x02 + }; + sw16 { + gpios = <&gpio2 RK_PA7 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-RIGHT"; + linux,code = ; // 0x05 + }; + sw19 { + gpios = <&gpio3 RK_PB1 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_SELECT"; + linux,code = ; + }; + sw20 { + gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-RIGHT2"; + linux,code = ; + }; + sw21 { + gpios = <&gpio3 RK_PB2 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-LEFT2"; + linux,code = ; + }; + sw22 { + gpios = <&gpio3 RK_PB4 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_START"; + linux,code = ; + }; + }; +}; + +&pinctrl { + btns { + btn_pins: btn-pins { + rockchip,pins = <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>; + + }; + + }; +}; diff --git a/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-gameconsole-r3xs.dtsi b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-gameconsole-r3xs.dtsi new file mode 100644 index 0000000000..5e95dab3ab --- /dev/null +++ b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-gameconsole-r3xs.dtsi @@ -0,0 +1,545 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * # Copyright (C) 2022-24 JELOS (https://github.com/JustEnoughLinuxOS) + */ + +/dts-v1/; +#include +#include +#include +#include +#include "rk3326.dtsi" + +/ { + model = "Game Console R33S"; + compatible = "gameconsolec,r33s", "rockchip,rk3326"; + + aliases { + mmc0 = &sdio; + mmc1 = &sdmmc; + }; + + chosen { + stdout-path = "serial2:115200n8"; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + power-supply = <&vcc_bl>; + pwms = <&pwm1 0 25000 0>; + brightness-levels = < + 0 1 2 3 4 5 6 7 + 8 9 10 11 12 13 14 15 + 16 17 18 19 20 21 22 23 + 24 25 26 27 28 29 30 31 + 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 + 48 49 50 51 52 53 54 55 + 56 57 58 59 60 61 62 63 + 64 65 66 67 68 69 70 71 + 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 + 88 89 90 91 92 93 94 95 + 96 97 98 99 100 101 102 103 + 104 105 106 107 108 109 110 111 + 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 + 128 129 130 131 132 133 134 135 + 136 137 138 139 140 141 142 143 + 144 145 146 147 148 149 150 151 + 152 153 154 155 156 157 158 159 + 160 161 162 163 164 165 166 167 + 168 169 170 171 172 173 174 175 + 176 177 178 179 180 181 182 183 + 184 185 186 187 188 189 190 191 + 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 + 208 209 210 211 212 213 214 215 + 216 217 218 219 220 221 222 223 + 224 225 226 227 228 229 230 231 + 232 233 234 235 236 237 238 239 + 240 241 242 243 244 245 246 247 + 248 249 250 251 252 253 254 255>; + default-brightness-level = <128>; + }; + + gpio-keys-vol { + compatible = "gpio-keys"; + autorepeat; + pinctrl-0 = <&btn_pins_vol>; + pinctrl-names = "default"; + + button-vol-down { + gpios = <&gpio2 RK_PA1 GPIO_ACTIVE_LOW>; + label = "VOLUMEDOWN"; + linux,code = ; + }; + + button-volume-up { + gpios = <&gpio2 RK_PA0 GPIO_ACTIVE_LOW>; + label = "VOLUMEUP"; + linux,code = ; + }; + }; + + battery: battery { + compatible = "simple-battery"; + charge-full-design-microamp-hours = <3200000>; + charge-term-current-microamp = <320000>; + constant-charge-current-max-microamp = <2000000>; + constant-charge-voltage-max-microvolt = <4200000>; + factory-internal-resistance-micro-ohms = <180000>; + voltage-max-design-microvolt = <4100000>; + voltage-min-design-microvolt = <3500000>; + + ocv-capacity-celsius = <20>; + ocv-capacity-table-0 = <4046950 100>, <4001920 95>, <3967900 90>, <3919950 85>, + <3888450 80>, <3861850 75>, <3831540 70>, <3799130 65>, + <3768190 60>, <3745650 55>, <3726610 50>, <3711630 45>, + <3696720 40>, <3685660 35>, <3674950 30>, <3663050 25>, + <3649470 20>, <3635260 15>, <3616920 10>, <3592440 5>, + <3574170 0>; + + }; + + rk817-sound { + compatible = "simple-audio-card"; + simple-audio-card,name = "rk817_int"; + simple-audio-card,format = "i2s"; + simple-audio-card,hp-det-gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>; + simple-audio-card,mclk-fs = <256>; + simple-audio-card,widgets = + "Microphone", "Mic Jack", + "Headphone", "Headphones", + "Speaker", "Speaker"; + simple-audio-card,routing = + "MICL", "Mic Jack", + "Headphones", "HPOL", + "Headphones", "HPOR", + "Speaker", "SPKO"; + + simple-audio-card,codec { + sound-dai = <&rk817>; + }; + + simple-audio-card,cpu { + sound-dai = <&i2s1_2ch>; + }; + }; + + vccsys: vccsys { + compatible = "regulator-fixed"; + regulator-name = "vcc3v8_sys"; + regulator-always-on; + regulator-min-microvolt = <3800000>; + regulator-max-microvolt = <3800000>; + }; +}; + +&dmc { + center-supply = <&vdd_logic>; +}; + +&cpu0 { + cpu-supply = <&vdd_arm>; +}; + +&cpu1 { + cpu-supply = <&vdd_arm>; +}; + +&cpu2 { + cpu-supply = <&vdd_arm>; +}; + +&cpu3 { + cpu-supply = <&vdd_arm>; +}; + +&cru { + assigned-clocks = <&cru PLL_NPLL>, + <&cru ACLK_BUS_PRE>, <&cru ACLK_PERI_PRE>, + <&cru HCLK_BUS_PRE>, <&cru HCLK_PERI_PRE>, + <&cru PCLK_BUS_PRE>, <&cru SCLK_GPU>; + + assigned-clock-rates = <1188000000>, + <200000000>, <200000000>, + <150000000>, <150000000>, + <100000000>, <200000000>; +}; + +&display_subsystem { + status = "okay"; +}; + +&dsi { + status = "okay"; + + ports { + mipi_out: port@1 { + reg = <1>; + + mipi_out_panel: endpoint { + remote-endpoint = <&mipi_in_panel>; + }; + }; + }; + + internal_display: panel@0 { + reg = <0>; + backlight = <&backlight>; + reset-gpios = <&gpio3 RK_PC0 GPIO_ACTIVE_LOW>; + + port { + mipi_in_panel: endpoint { + remote-endpoint = <&mipi_out_panel>; + }; + }; + }; +}; + +&dsi_dphy { + status = "okay"; +}; + +&gpu { + mali-supply = <&vdd_logic>; + status = "okay"; +}; + +&internal_display { + compatible = "gameconsole,r36s-panel", "sitronix,st7703"; + iovcc-supply = <&vcc_lcd>; + vdd-supply = <&vcc_lcd>; +}; + +&i2c0 { + clock-frequency = <400000>; + i2c-scl-falling-time-ns = <16>; + i2c-scl-rising-time-ns = <280>; + status = "okay"; + + rk817: pmic@20 { + compatible = "rockchip,rk817"; + reg = <0x20>; + interrupt-parent = <&gpio0>; + interrupts = ; + clock-output-names = "rk808-clkout1", "xin32k"; + clock-names = "mclk"; + clocks = <&cru SCLK_I2S1_OUT>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int>, <&i2s1_2ch_mclk>; + rockchip,system-power-controller; + wakeup-source; + #clock-cells = <1>; + #sound-dai-cells = <0>; + + vcc1-supply = <&vccsys>; + vcc2-supply = <&vccsys>; + vcc3-supply = <&vccsys>; + vcc4-supply = <&vccsys>; + vcc5-supply = <&vccsys>; + vcc6-supply = <&vccsys>; + vcc7-supply = <&vccsys>; + vcc8-supply = <&vccsys>; + + regulators { + vdd_logic: DCDC_REG1 { + regulator-name = "vdd_logic"; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1150000>; + regulator-ramp-delay = <6001>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vdd_arm: DCDC_REG2 { + regulator-name = "vdd_arm"; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1450000>; + regulator-ramp-delay = <6001>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-name = "vcc_ddr"; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_3v3: DCDC_REG4 { + regulator-name = "vcc_3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_1v8: LDO_REG2 { + regulator-name = "vcc_1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd_1v0: LDO_REG3 { + regulator-name = "vdd_1v0"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vcc3v3_pmu: LDO_REG4 { + regulator-name = "vcc3v3_pmu"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vccio_sd: LDO_REG5 { + regulator-name = "vccio_sd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc_sd: LDO_REG6 { + regulator-name = "vcc_sd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3000000>; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcc_bl: LDO_REG7 { + regulator-name = "vcc_bl"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_lcd: LDO_REG8 { + regulator-name = "vcc_lcd"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <2800000>; + }; + }; + + LDO_REG9 { + /* unused */ + }; + + usb_midu: BOOST { + regulator-name = "usb_midu"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5400000>; + regulator-always-on; + regulator-boot-on; + }; + }; + + rk817_charger: charger { + rockchip,resistor-sense-micro-ohms = <10000>; + rockchip,sleep-enter-current-microamp = <300000>; + rockchip,sleep-filter-current-microamp = <100000>; + }; + + rk817_codec: codec { + rockchip,mic-in-differential; + }; + }; +}; + +&i2s1_2ch { + status = "okay"; +}; + +&io_domains { + vccio1-supply = <&vccio_sd>; + vccio2-supply = <&vccio_sd>; + vccio3-supply = <&vcc_3v3>; + vccio4-supply = <&vcc_3v3>; + vccio5-supply = <&vcc_3v3>; + vccio6-supply = <&vcc_3v3>; + status = "okay"; +}; + +&pmu_io_domains { + pmuio1-supply = <&vcc3v3_pmu>; + pmuio2-supply = <&vcc3v3_pmu>; + status = "okay"; +}; + +&pwm0 { + status = "okay"; +}; + +&pwm1 { + status = "okay"; +}; + +&saradc { + vref-supply = <&vcc_1v8>; + status = "okay"; +}; + +&sdmmc { + bus-width = <4>; + cap-sd-highspeed; + card-detect-delay = <800>; + cd-gpios = <&gpio0 RK_PA3 GPIO_ACTIVE_LOW>; /*[> CD GPIO <]*/ + disable-wp; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + vmmc-supply = <&vcc_sd>; + vqmmc-supply = <&vccio_sd>; + status = "okay"; +}; + +&sdio { + bus-width = <4>; + cap-sd-highspeed; + card-detect-delay = <800>; + cd-gpios = <&gpio3 RK_PB6 GPIO_ACTIVE_LOW>; /*[> CD GPIO <]*/ + disable-wp; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + vmmc-supply = <&vcc_sd>; + vqmmc-supply = <&vccio_sd>; + status = "okay"; +}; + +&tsadc { + status = "okay"; +}; + +&u2phy { + status = "okay"; + + u2phy_host: host-port { + status = "okay"; + }; + + u2phy_otg: otg-port { + status = "disabled"; + }; +}; + +&usb20_otg { + status = "okay"; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&uart2m1_xfer>; + status = "okay"; +}; + +&vopb { + status = "okay"; +}; + +&vopb_mmu { + status = "okay"; +}; + +&rk817_charger { + monitored-battery = <&battery>; +}; + +&pinctrl { + btns { + btn_pins_vol: btn-pins-vol { + rockchip,pins = <2 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + headphone { + hp_det: hp-det { + rockchip,pins = <2 RK_PC6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + + pmic { + dc_det: dc-det { + rockchip,pins = <0 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + pmic_int: pmic-int { + rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + soc_slppin_gpio: soc_slppin_gpio { + rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_output_low>; + }; + + soc_slppin_rst: soc_slppin_rst { + rockchip,pins = <0 RK_PA4 2 &pcfg_pull_none>; + }; + + soc_slppin_slp: soc_slppin_slp { + rockchip,pins = <0 RK_PA4 1 &pcfg_pull_none>; + }; + }; +}; diff --git a/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-gameconsole-soysauce.dts b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-gameconsole-soysauce.dts new file mode 100644 index 0000000000..74b236bd6f --- /dev/null +++ b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-gameconsole-soysauce.dts @@ -0,0 +1,243 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (C) 2026 ArchR (https://github.com/archr-linux/Arch-R) + * + * Device tree for R36S "soysauce" variant (Y3506 boards). + * Hardware differences from standard R36S: + * - All buttons on GPIO3 (standard uses GPIO1/GPIO2) + * - Analog mux on GPIO0 (standard uses GPIO3) + * - Panel reset GPIO: GPIO3_PB0 + * - Panel enable GPIO: GPIO1_PC2 + * - amux-channel-mapping reordered + * - Different joypad product ID (0x1100 "GO-Super Gamepad") + */ + +/dts-v1/; +#include "rk3326-gameconsole-r3xs.dtsi" +#include "rk3326-device-group-r36.dtsi" + +/ { + model = "Game Console R36S Soysauce"; + compatible = "gameconsole,soysauce", "gameconsole,r36s", "rockchip,rk3326"; + + archr,device_switch { + this = "soysauce"; + }; + + /* LED indicators (soysauce-specific) */ + leds { + compatible = "gpio-leds"; + + led-red { + gpios = <&gpio0 RK_PA5 GPIO_ACTIVE_LOW>; + label = "red"; + default-state = "off"; + }; + + led-blue { + gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_LOW>; + label = "blue"; + default-state = "off"; + }; + }; + + /* Volume buttons: GPIO3_PC6/PC5 on soysauce (base has GPIO2_PA0/PA1) */ + gpio-keys-vol { + button-vol-down { + gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_LOW>; + }; + + button-volume-up { + gpios = <&gpio3 RK_PC6 GPIO_ACTIVE_LOW>; + }; + }; + + joypad: odroidgo3-joypad { + compatible = "archr-joypad", "odroidgo3-joypad"; + pwms = <&pwm0 0 200000000 0>; + pwm-names = "enable"; + rumble-boost-weak = <0x0000>; + rumble-boost-strong = <0x0000>; + + joypad-name = "GO-Super Gamepad"; + joypad-product = <0x1100>; + joypad-revision = <0x0100>; + + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&btn_pins>; + pinctrl-1 = <&pwm0_pin>; + + /* Analog mux on GPIO0 (different from standard R36S) */ + io-channel-names = "amux_adc"; + io-channels = <&saradc 1>; + + amux-count = <4>; + amux-channel-mapping = <3 2 0 1>; + amux-a-gpios = <&gpio0 RK_PB5 GPIO_ACTIVE_LOW>; + amux-b-gpios = <&gpio0 RK_PB4 GPIO_ACTIVE_LOW>; + amux-en-gpios = <&gpio0 RK_PC1 GPIO_ACTIVE_LOW>; + + button-adc-scale = <2>; + button-adc-deadzone = <64>; + button-adc-fuzz = <32>; + button-adc-flat = <32>; + + abs_x-p-tuning = <200>; + abs_x-n-tuning = <200>; + abs_y-p-tuning = <200>; + abs_y-n-tuning = <200>; + abs_rx-p-tuning = <200>; + abs_rx-n-tuning = <200>; + abs_ry-p-tuning = <200>; + abs_ry-n-tuning = <200>; + + poll-interval = <10>; + + invert-absx; + invert-absy; + + /* All buttons on GPIO3 (soysauce layout) */ + sw1 { + gpios = <&gpio3 RK_PA7 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-UP"; + linux,code = ; + }; + sw2 { + gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-DOWN"; + linux,code = ; + }; + sw3 { + gpios = <&gpio3 RK_PB2 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-LEFT"; + linux,code = ; + }; + sw4 { + gpios = <&gpio3 RK_PB1 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-RIGHT"; + linux,code = ; + }; + sw5 { + gpios = <&gpio3 RK_PB6 GPIO_ACTIVE_LOW>; + label = "GPIO KEY BTN-A"; + linux,code = ; + }; + sw6 { + gpios = <&gpio3 RK_PB4 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-B"; + linux,code = ; + }; + sw7 { + gpios = <&gpio3 RK_PB3 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-Y"; + linux,code = ; + }; + sw8 { + gpios = <&gpio3 RK_PB5 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-X"; + linux,code = ; + }; + sw11 { + gpios = <&gpio0 RK_PB3 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_THUMBL"; + linux,code = ; + }; + sw12 { + gpios = <&gpio3 RK_PD3 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_THUMBR"; + linux,code = ; + }; + sw13 { + gpios = <&gpio3 RK_PA4 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_MODE"; + linux,code = ; + }; + sw15 { + gpios = <&gpio3 RK_PA3 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-LEFT"; + linux,code = ; + }; + sw16 { + gpios = <&gpio3 RK_PA0 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-RIGHT"; + linux,code = ; + }; + sw19 { + gpios = <&gpio3 RK_PA5 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_SELECT"; + linux,code = ; + }; + sw20 { + gpios = <&gpio3 RK_PA2 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-LEFT2"; + linux,code = ; + }; + sw21 { + gpios = <&gpio3 RK_PA1 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-RIGHT2"; + linux,code = ; + }; + sw22 { + gpios = <&gpio3 RK_PA6 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_START"; + linux,code = ; + }; + }; +}; + +/* Soysauce panel: same reset GPIO as base (GPIO3_PC0), add enable GPIO */ +&internal_display { + compatible = "archr,generic-dsi", "rocknix,generic-dsi"; + enable-gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_HIGH>; +}; + +/* Soysauce uses GPIO3_PB6 for BTN-A, not sdio card detect */ +&sdio { + /delete-property/ cd-gpios; + non-removable; +}; + +&rk817_codec { + spk-ctl-gpios = <&gpio3 RK_PC4 GPIO_ACTIVE_HIGH>; +}; + +&pinctrl { + btns { + btn_pins_vol: btn-pins-vol { + rockchip,pins = <3 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PC6 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + btn_pins: btn-pins { + rockchip,pins = + <3 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB3 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>, + <0 RK_PB3 RK_FUNC_GPIO &pcfg_pull_up>, + <0 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <0 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>, + <0 RK_PC1 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + panel { + panel_enable: panel-enable { + rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; diff --git a/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-gameforce-chi.dts b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-gameforce-chi.dts new file mode 100644 index 0000000000..7b47cf7017 --- /dev/null +++ b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-gameforce-chi.dts @@ -0,0 +1,811 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2024 Chris Morgan + */ + +/dts-v1/; +#include +#include +#include +#include +#include "rk3326.dtsi" + +/ { + model = "GameForce Chi"; + compatible = "gameforce,chi", "rockchip,rk3326"; + chassis-type = "handset"; + + aliases { + mmc0 = &sdmmc; + mmc1 = &sdio; + }; + + chosen { + stdout-path = "serial2:115200n8"; + }; + + adc_joystick: adc-joystick { + compatible = "adc-joystick"; + io-channels = <&saradc 0>, + <&saradc 1>; + poll-interval = <100>; + #address-cells = <1>; + #size-cells = <0>; + + axis@0 { + reg = <0>; + abs-flat = <10>; + abs-fuzz = <10>; + abs-range = <850 175>; + linux,code = ; + }; + + axis@1 { + reg = <1>; + abs-flat = <10>; + abs-fuzz = <10>; + abs-range = <800 190>; + linux,code = ; + }; + }; + + adc_keys: adc-keys { + compatible = "adc-keys"; + io-channels = <&saradc 2>; + io-channel-names = "buttons"; + keyup-threshold-microvolt = <1800000>; + poll-interval = <60>; + + button-1 { + label = "HAPPY1"; + linux,code = ; + press-threshold-microvolt = <15000>; + }; + + button-2 { + label = "HAPPY2"; + linux,code = ; + press-threshold-microvolt = <300000>; + }; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + power-supply = <&vcc_bl>; + pwms = <&pwm1 0 25000 0>; + }; + + battery: battery { + compatible = "simple-battery"; + charge-full-design-microamp-hours = <3000000>; + charge-term-current-microamp = <300000>; + constant-charge-current-max-microamp = <1500000>; + constant-charge-voltage-max-microvolt = <4200000>; + factory-internal-resistance-micro-ohms = <180000>; + ocv-capacity-celsius = <20>; + ocv-capacity-table-0 = <4106000 100>, <4071000 95>, <4018000 90>, <3975000 85>, + <3946000 80>, <3908000 75>, <3877000 70>, <3853000 65>, + <3834000 60>, <3816000 55>, <3802000 50>, <3788000 45>, + <3774000 40>, <3760000 35>, <3748000 30>, <3735000 25>, + <3718000 20>, <3697000 15>, <3685000 10>, <3625000 5>, + <3400000 0>; + voltage-max-design-microvolt = <4250000>; + voltage-min-design-microvolt = <3400000>; + }; + + gpio_leds: gpio-leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins>; + + red_led: led-0 { + color = ; + gpios = <&gpio3 RK_PC4 GPIO_ACTIVE_HIGH>; + }; + + green_led: led-1 { + color = ; + gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>; + }; + + blue_led: led-2 { + color = ; + gpios = <&gpio3 RK_PC6 GPIO_ACTIVE_HIGH>; + }; + + white_led: led-3 { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&gpio3 RK_PB3 GPIO_ACTIVE_HIGH>; + }; + + chg_led: led-4 { + color = ; + function = LED_FUNCTION_CHARGING; + gpios = <&gpio3 RK_PB2 GPIO_ACTIVE_HIGH>; + }; + + }; + + gpio_keys: gpio-keys { + compatible = "gpio-keys"; + pinctrl-0 = <&btn_pins_ctrl>; + pinctrl-names = "default"; + + button-a { + gpios = <&gpio2 RK_PB0 GPIO_ACTIVE_LOW>; + label = "EAST"; + linux,code = ; + }; + + button-b { + gpios = <&gpio2 RK_PB1 GPIO_ACTIVE_LOW>; + label = "SOUTH"; + linux,code = ; + }; + + button-down { + gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_LOW>; + label = "DPAD-DOWN"; + linux,code = ; + }; + + button-home { + gpios = <&gpio2 RK_PA0 GPIO_ACTIVE_LOW>; + label = "HOME"; + linux,code = ; + }; + + button-l1 { + gpios = <&gpio2 RK_PA6 GPIO_ACTIVE_LOW>; + label = "TL"; + linux,code = ; + }; + + button-l2 { + gpios = <&gpio2 RK_PA4 GPIO_ACTIVE_LOW>; + label = "TL2"; + linux,code = ; + }; + + button-left { + gpios = <&gpio1 RK_PB6 GPIO_ACTIVE_LOW>; + label = "DPAD-LEFT"; + linux,code = ; + }; + + button-r1 { + gpios = <&gpio2 RK_PA7 GPIO_ACTIVE_LOW>; + label = "TR"; + linux,code = ; + }; + + button-r2 { + gpios = <&gpio2 RK_PA5 GPIO_ACTIVE_LOW>; + label = "TR2"; + linux,code = ; + }; + + button-right { + gpios = <&gpio1 RK_PB7 GPIO_ACTIVE_LOW>; + label = "DPAD-RIGHT"; + linux,code = ; + }; + + button-select { + gpios = <&gpio2 RK_PA3 GPIO_ACTIVE_LOW>; + label = "SELECT"; + linux,code = ; + }; + + button-start { + gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; + label = "START"; + linux,code = ; + }; + + button-up { + gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_LOW>; + label = "DPAD-UP"; + linux,code = ; + }; + + button-x { + gpios = <&gpio2 RK_PB3 GPIO_ACTIVE_LOW>; + label = "NORTH"; + linux,code = ; + }; + + button-y { + gpios = <&gpio2 RK_PB2 GPIO_ACTIVE_LOW>; + label = "WEST"; + linux,code = ; + }; + }; + + multi-led { + compatible = "leds-group-multicolor"; + color = ; + function = LED_FUNCTION_KBD_BACKLIGHT; + leds = <&red_led>, <&green_led>, <&blue_led>; + }; + + spk_amp: audio-amplifier { + compatible = "simple-audio-amplifier"; + enable-gpios = <&gpio2 RK_PB5 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&spk_amp_enable_h>; + pinctrl-names = "default"; + sound-name-prefix = "Speaker Amp"; + }; + + sound { + compatible = "simple-audio-card"; + pinctrl-0 = <&hp_det>; + pinctrl-names = "default"; + simple-audio-card,name = "rk817_ext"; + simple-audio-card,aux-devs = <&spk_amp>; + simple-audio-card,format = "i2s"; + simple-audio-card,hp-det-gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>; + simple-audio-card,mclk-fs = <256>; + simple-audio-card,widgets = + "Microphone", "Mic Jack", + "Headphone", "Headphones", + "Speaker", "Internal Speakers"; + simple-audio-card,routing = + "MICL", "Mic Jack", + "Headphones", "HPOL", + "Headphones", "HPOR", + "Internal Speakers", "Speaker Amp OUTL", + "Internal Speakers", "Speaker Amp OUTR", + "Speaker Amp INL", "HPOL", + "Speaker Amp INR", "HPOR"; + simple-audio-card,pin-switches = "Internal Speakers"; + + simple-audio-card,codec { + sound-dai = <&rk817>; + }; + + simple-audio-card,cpu { + sound-dai = <&i2s1_2ch>; + }; + }; + + vibrator_left: pwm-vibrator-l { + compatible = "pwm-vibrator"; + pwm-names = "enable"; + pwms = <&pwm4 0 25000 0>; + }; + + vibrator_right: pwm-vibrator-r { + compatible = "pwm-vibrator"; + pwm-names = "enable"; + pwms = <&pwm5 0 25000 0>; + }; + + sdio_pwrseq: sdio-pwrseq { + compatible = "mmc-pwrseq-simple"; + clocks = <&rk817 1>; + clock-names = "ext_clock"; + pinctrl-0 = <&wifi_enable_h>; + pinctrl-names = "default"; + post-power-on-delay-ms = <200>; + reset-gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_LOW>; + }; + + vccsys: regulator-vccsys { + compatible = "regulator-fixed"; + regulator-name = "vcc3v8_sys"; + regulator-always-on; + regulator-min-microvolt = <3800000>; + regulator-max-microvolt = <3800000>; + }; +}; + +&cpu0 { + cpu-supply = <&vdd_arm>; +}; + +&cpu1 { + cpu-supply = <&vdd_arm>; +}; + +&cpu2 { + cpu-supply = <&vdd_arm>; +}; + +&cpu3 { + cpu-supply = <&vdd_arm>; +}; + +&display_subsystem { + status = "okay"; +}; + +&dsi { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + internal_display: panel@0 { + reg = <0>; + compatible = "gameforce,chi-panel"; + backlight = <&backlight>; + iovcc-supply = <&vcc_lcd>; + vcc-supply = <&vcc_lcd>; + reset-gpios = <&gpio3 RK_PA0 GPIO_ACTIVE_LOW>; + + port { + mipi_in_panel: endpoint { + remote-endpoint = <&mipi_out_panel>; + }; + }; + }; + + ports { + mipi_out: port@1 { + reg = <1>; + + mipi_out_panel: endpoint { + remote-endpoint = <&mipi_in_panel>; + }; + }; + }; +}; + +&dsi_dphy { + status = "okay"; +}; + +&gpu { + mali-supply = <&vdd_logic>; + status = "okay"; +}; + +&i2c0 { + clock-frequency = <400000>; + i2c-scl-falling-time-ns = <16>; + i2c-scl-rising-time-ns = <280>; + status = "okay"; + + rk817: pmic@20 { + compatible = "rockchip,rk817"; + reg = <0x20>; + #clock-cells = <1>; + clock-names = "mclk"; + clock-output-names = "rk808-clkout1", "xin32k"; + clocks = <&cru SCLK_I2S1_OUT>; + interrupt-parent = <&gpio0>; + interrupts = ; + pinctrl-0 = <&pmic_int>, <&i2s1_2ch_mclk>; + pinctrl-names = "default"; + #sound-dai-cells = <0>; + system-power-controller; + wakeup-source; + + vcc1-supply = <&vccsys>; + vcc2-supply = <&vccsys>; + vcc3-supply = <&vccsys>; + vcc4-supply = <&vccsys>; + vcc5-supply = <&vccsys>; + vcc6-supply = <&vccsys>; + vcc7-supply = <&vcc_3v0>; + vcc8-supply = <&vccsys>; + vcc9-supply = <&dcdc_boost>; + + regulators { + vdd_logic: DCDC_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1150000>; + regulator-min-microvolt = <950000>; + regulator-name = "vdd_logic"; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vdd_arm: DCDC_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1350000>; + regulator-min-microvolt = <950000>; + regulator-name = "vdd_arm"; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc_ddr"; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_3v0: DCDC_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <3000000>; + regulator-min-microvolt = <3000000>; + regulator-name = "vcc_3v0"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcc_1v8: LDO_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1800000>; + regulator-min-microvolt = <1800000>; + regulator-name = "vcc_1v8"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd_1v0: LDO_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1000000>; + regulator-min-microvolt = <1000000>; + regulator-name = "vdd_1v0"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vcc_3v0_pmu: LDO_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <3000000>; + regulator-min-microvolt = <3000000>; + regulator-name = "vcc_3v0_pmu"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vccio_sd: LDO_REG5 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <1800000>; + regulator-name = "vccio_sd"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_sd: LDO_REG6 { + regulator-boot-on; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "vcc_sd"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_bl: LDO_REG7 { + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "vcc_bl"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_lcd: LDO_REG8 { + regulator-max-microvolt = <2800000>; + regulator-min-microvolt = <2800000>; + regulator-name = "vcc_lcd"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <2800000>; + }; + }; + + vcc_wifi: LDO_REG9 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "vcc_wifi"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + dcdc_boost: BOOST { + regulator-max-microvolt = <5000000>; + regulator-min-microvolt = <5000000>; + regulator-name = "dcdc_boost"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + otg_switch: OTG_SWITCH { + regulator-name = "otg_switch"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + + rk817_charger: charger { + monitored-battery = <&battery>; + rockchip,resistor-sense-micro-ohms = <10000>; + rockchip,sleep-enter-current-microamp = <300000>; + rockchip,sleep-filter-current-microamp = <100000>; + }; + }; +}; + +&i2s1_2ch { + status = "okay"; +}; + +&io_domains { + vccio1-supply = <&vcc_3v0_pmu>; + vccio2-supply = <&vccio_sd>; + vccio3-supply = <&vcc_3v0>; + vccio4-supply = <&vcc_3v0>; + vccio5-supply = <&vcc_3v0>; + vccio6-supply = <&vcc_3v0>; + status = "okay"; +}; + +&pinctrl { + bluetooth-pins { + bt_reset: bt-reset { + rockchip,pins = + <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + bt_wake_dev: bt-wake-dev { + rockchip,pins = + <0 RK_PA1 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + bt_wake_host: bt-wake-host { + rockchip,pins = + <0 RK_PA7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + headphone { + hp_det: hp-det { + rockchip,pins = + <2 RK_PC6 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + gpio-btns { + btn_pins_ctrl: btn-pins-ctrl { + rockchip,pins = + <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PB3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + gpio-leds { + led_pins: led-pins { + rockchip,pins = + <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>, + <3 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>, + <3 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>, + <3 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>, + <3 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pmic { + pmic_int: pmic-int { + rockchip,pins = + <0 RK_PC1 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + soc_slppin_gpio: soc_slppin_gpio { + rockchip,pins = + <0 RK_PA4 RK_FUNC_GPIO &pcfg_output_low>; + }; + + soc_slppin_rst: soc_slppin_rst { + rockchip,pins = + <0 RK_PA4 2 &pcfg_pull_none>; + }; + + soc_slppin_slp: soc_slppin_slp { + rockchip,pins = + <0 RK_PA4 1 &pcfg_pull_none>; + }; + }; + + sdio-pwrseq { + wifi_enable_h: wifi-enable-h { + rockchip,pins = + <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + speaker { + spk_amp_enable_h: spk-amp-enable-h { + rockchip,pins = + <2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&pmu_io_domains { + pmuio1-supply = <&vcc_1v8>; + pmuio2-supply = <&vcc_3v0_pmu>; + status = "okay"; +}; + +&pwm1 { + status = "okay"; +}; + +&pwm4 { + status = "okay"; +}; + +&pwm5 { + status = "okay"; +}; + +&saradc { + vref-supply = <&vcc_1v8>; + status = "okay"; +}; + +&sdio { + bus-width = <4>; + cap-sd-highspeed; + cap-sdio-irq; + disable-wp; + keep-power-in-suspend; + mmc-pwrseq = <&sdio_pwrseq>; + no-mmc; + no-sd; + non-removable; + sd-uhs-sdr104; + status = "okay"; +}; + +&sdmmc { + cap-mmc-highspeed; + cap-sd-highspeed; + no-sdio; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + vmmc-supply = <&vcc_sd>; + vqmmc-supply = <&vccio_sd>; + status = "okay"; +}; + +&sfc { + #address-cells = <1>; + pinctrl-0 = <&sfc_clk &sfc_cs0 &sfc_bus2>; + pinctrl-names = "default"; + #size-cells = <0>; + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <108000000>; + spi-rx-bus-width = <2>; + spi-tx-bus-width = <1>; + }; +}; + +&tsadc { + status = "okay"; +}; + +&u2phy { + status = "okay"; + + u2phy_otg: otg-port { + status = "okay"; + }; +}; + +&usb20_otg { + status = "okay"; +}; + +/* + * The right ADC joystick exists connected to an unknown ADC + * controller which can be communicated with via uart0. This ADC device + * is an 8-pin SOIC with no markings located right next to the left ADC + * joystick ribbon cable. The pinout for this ADC controller appears to + * be pin 1 - VCC (2.8v), pin 2 - 1.8v (clk maybe?), pin 3 - GPIO 10, + * pin 4 - unknown, pin 5 - unknown, pin 6 - analog in, pin 7 - analog in, + * pin 8 - ground. There is currently a userspace UART driver for this + * device but it only works with the BSP joystick driver. + */ +&uart0 { + status = "okay"; +}; + +/* + * Bluetooth was not working on BSP and is not currently working on + * mainline due to missing firmware. Bluetooth requires removal of DMA + * or else it will not probe. + */ +&uart1 { + /delete-property/ dma-names; + /delete-property/ dmas; + uart-has-rtscts; + status = "okay"; + + bluetooth: bluetooth { + compatible = "realtek,rtl8723ds-bt"; + device-wake-gpios = <&gpio0 RK_PA1 GPIO_ACTIVE_HIGH>; + enable-gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; + host-wake-gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&bt_reset>, <&bt_wake_dev>, <&bt_wake_host>; + pinctrl-names = "default"; + }; +}; + +&uart2 { + pinctrl-0 = <&uart2m1_xfer>; + pinctrl-names = "default"; + status = "okay"; +}; + +&vopb { + status = "okay"; +}; + +&vopb_mmu { + status = "okay"; +}; diff --git a/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-magicx-xu-mini-m.dts b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-magicx-xu-mini-m.dts new file mode 100644 index 0000000000..c3a6aa31a9 --- /dev/null +++ b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-magicx-xu-mini-m.dts @@ -0,0 +1,110 @@ +/// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2024-present ROCKNIX (https://github.com/ROCKNIX) + * Copyright (c) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + * Copyright (c) 2024 Olivier Schonken + */ + +#include "rk3326-magicx-xu10.dts" + +/ { + model = "MagicX XU Mini M"; + compatible = "magicx,xu-mini-m", "rockchip,rk3326"; +}; + +&battery { + charge-full-design-microamp-hours = <2600000>; +}; + +&dsi { + internal_display: panel@0 { + compatible = "archr,generic-dsi"; + panel_description = + "G size=69,139 delays=5,20,20,120,20 format=rgb888 lanes=2 flags=0xe03", + + "M clock=25000 horizontal=480,60,10,54 vertical=640,20,10,20 default=1", + "M clock=25200 horizontal=480,60,22,54 vertical=640,20,139,20", + "M clock=25000 horizontal=480,60,31,54 vertical=640,20,120,20", + "M clock=25660 horizontal=480,60,22,54 vertical=640,20,153,20", + "M clock=25300 horizontal=480,60,31,54 vertical=640,20,24,20", + "M clock=28590 horizontal=480,60,15,54 vertical=640,20,106,20", + "M clock=25380 horizontal=480,60,17,54 vertical=640,20,13,20", + "M clock=25410 horizontal=480,60,11,54 vertical=640,20,20,20", + "M clock=29490 horizontal=480,60,24,54 vertical=640,20,114,20", + "M clock=33520 horizontal=480,60,36,54 vertical=640,20,25,20", + "M clock=38430 horizontal=480,60,16,54 vertical=640,20,20,20", + "M clock=50820 horizontal=480,60,11,54 vertical=640,20,20,20", + + "I seq=ff7701000013", + "I seq=ef08", + "I seq=ff7701000010", + "I seq=c04f00", "I seq=c11002", "I seq=c22002", "I seq=cc10", + "I seq=b006161e0e12060a0809230412102b311f", + "I seq=b1060f160d100704090720051210262f1f", + "I seq=ff7701000011", + "I seq=b065", "I seq=b185", "I seq=b282", "I seq=b380", "I seq=b542", "I seq=b785", + "I seq=b820", + "I seq=c178", "I seq=c278", + "I seq=d088", + "I seq=e0000002", + "I seq=e104a006a005a007a0004444", + "I seq=e2000000000000000000000000", + "I seq=e300002222", + "I seq=e44444", + "I seq=e50c90a0a00e92a0a0088ca0a00a8ea0a0", + "I seq=e600002222", + "I seq=e74444", + "I seq=e80d91a0a00f93a0a0098da0a00b8fa0a0", + "I seq=eb0000e4e4440040", + "I seq=edfff5476f0ba1abffffba1ab0f6745fff", + "I seq=ef080808403f64", + "I seq=ff7701000013", + "I seq=e6167c", "I seq=e8000e", + "I seq=e8000c wait=50", + "I seq=e80000", + "I seq=ff7701000000", + "I seq=11 wait=150", + "I seq=29 wait=120"; + rotation = <90>; + }; +}; + +&joypad { + joypad-name = "XU Mini M Gamepad"; + + invert-absrx; + /delete-property/ invert-absx; + + sw5 { + gpios = <&gpio2 RK_PA3 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-B"; + }; + sw6 { + gpios = <&gpio2 RK_PA1 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-A"; + }; + sw7 { + gpios = <&gpio2 RK_PA0 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-X"; + }; + sw8 { + gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-Y"; + }; + sw16 { + gpios = <&gpio3 RK_PB4 GPIO_ACTIVE_LOW>; + }; + sw17 { + gpios = <&gpio3 RK_PB2 GPIO_ACTIVE_LOW>; + }; +}; + +&pinctrl { + headphone { + hp_det: hp-det { + rockchip,pins = <2 RK_PC6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; +}; + + diff --git a/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-magicx-xu10.dts b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-magicx-xu10.dts new file mode 100644 index 0000000000..3fe532e06d --- /dev/null +++ b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-magicx-xu10.dts @@ -0,0 +1,872 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2019 Hardkernel Co., Ltd + * Copyright (c) 2020 Theobroma Systems Design und Consulting GmbH + * Copyright (c) 2022 Maya Matuszczyk + */ + +/dts-v1/; +#include +#include +#include +#include +#include "rk3326.dtsi" + +/ { + model = "MagicX XU10"; + compatible = "magicx,xu10", "rockchip,rk3326"; + + aliases { + mmc0 = &sdio; + mmc1 = &sdmmc; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + pwms = <&pwm1 0 25000 0>; + brightness-levels = < + 0 1 2 3 4 5 6 7 + 8 9 10 11 12 13 14 15 + 16 17 18 19 20 21 22 23 + 24 25 26 27 28 29 30 31 + 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 + 48 49 50 51 52 53 54 55 + 56 57 58 59 60 61 62 63 + 64 65 66 67 68 69 70 71 + 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 + 88 89 90 91 92 93 94 95 + 96 97 98 99 100 101 102 103 + 104 105 106 107 108 109 110 111 + 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 + 128 129 130 131 132 133 134 135 + 136 137 138 139 140 141 142 143 + 144 145 146 147 148 149 150 151 + 152 153 154 155 156 157 158 159 + 160 161 162 163 164 165 166 167 + 168 169 170 171 172 173 174 175 + 176 177 178 179 180 181 182 183 + 184 185 186 187 188 189 190 191 + 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 + 208 209 210 211 212 213 214 215 + 216 217 218 219 220 221 222 223 + 224 225 226 227 228 229 230 231 + 232 233 234 235 236 237 238 239 + 240 241 242 243 244 245 246 247 + 248 249 250 251 252 253 254 255>; + default-brightness-level = <128>; + }; + + joypad: xu10-joypad { + compatible = "xu10-joypad"; + + joypad-name = "XU10 Gamepad"; + joypad-product = <0x0200>; + joypad-revision = <0x0010>; + + status = "okay"; + /* + - xu10-joypad sysfs list - + * for poll device interval(ms) + /sys/devices/platform/odroidgo3_joypad/poll_interval [rw] + ex) echo 20 > poll_interval + * for button-adc-fuzz + /sys/devices/platform/odroidgo3_joypad/adc_fuzz [r] + * for button-adc-flat + /sys/devices/platform/odroidgo3_joypad/adc_flat [r] + + * for report control(1:enable, 0:disable) + /sys/devices/platform/odroidgo3_joypad/enable [rw] + * for adc calibration value setup(current adcs value -> cal value) + /sys/devices/platform/odroidgo3_joypad/adc_cal [rw] + ex) echo 0 > adc_cal + * for amux data debug + * Joypad driver is disabled when using this sysfs. + /sys/devices/platform/odroidgo3_joypad/amux_debug [rw] + ex) echo 0 > amux_debug --> select amux channel + ex) cat amux_debug --> get adc data of seleted channel + */ + + /* gpio pincontrol setup */ + pinctrl-names = "default"; + pinctrl-0 = <&btn_pins>; + + /* Analog mux define */ + io-channel-names = "joy_left", "joy_right"; + io-channels = <&saradc 1>, <&saradc 2>; + + /* adc mux channel count */ + amux-count = <4>; + + /* adc mux select(a,b) gpio */ + amux-a-gpios = <&gpio2 RK_PB3 GPIO_ACTIVE_LOW>; + amux-b-gpios = <&gpio2 RK_PB5 GPIO_ACTIVE_LOW>; + + /* adc mux enable gpio */ + amux-en-gpios = <&gpio1 RK_PB0 GPIO_ACTIVE_LOW>; + + /* adc calculate scale */ + button-adc-scale = <2>; + + /* adc deadzone range */ + button-adc-deadzone = <180>; + + /* + specifies fuzz value that is used to filter noise from + the event stream. + */ + button-adc-fuzz = <32>; + button-adc-flat = <32>; + + /* + Analog Stick data tuning value(precent) + p = positive direction, n = negative direction + report value = (real_adc_data * tuning_value) / 100 + */ + abs_x-p-tuning = <200>; + abs_x-n-tuning = <200>; + + abs_y-p-tuning = <200>; + abs_y-n-tuning = <200>; + + abs_rx-p-tuning = <200>; + abs_rx-n-tuning = <200>; + + abs_ry-p-tuning = <200>; + abs_ry-n-tuning = <200>; + + /* poll device interval (ms), adc read interval */ + poll-interval = <10>; + + /* required for XU10 */ + invert-absx; + invert-absy; + + /* gpio button auto repeat set value : default disable */ + /* + autorepeat; + */ + + /* + *** MagicX XU10 - layoout *** + |-------------------------------| + | sw14 sw17 sw16 sw15 | + |-----|-------------------|-----| + | | | | + |vol+ | | sw13| + |vol- | | | + | | LCD Display | | + | | | | + | | | | + | |-------------------| | + | sw9 sw10 | + | | + | sw1 sw7 | + | sw3 sw4 sw8 sw6 | + | sw2 sw5 | + | | + | sw11 sw12 | + | | + |-------|---------------|-------| + */ + + /* + joypad driver is poll-device driver. + poll-device is does not support wakeup-source. + */ + + sw1 { + gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-UP"; + linux,code = ; // 0x220 + }; + sw2 { + gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-DOWN"; + linux,code = ; // 0x221 + }; + sw3 { + gpios = <&gpio1 RK_PB6 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-LEFT"; + linux,code = ; // 0x222 + }; + sw4 { + gpios = <&gpio1 RK_PB7 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-RIGHT"; + linux,code = ; // 0x223 + }; + sw5 { + gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-A"; + linux,code = ; // 0x130 + }; + sw6 { + gpios = <&gpio2 RK_PA3 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-B"; + linux,code = ; // 0x131 + }; + sw7 { + gpios = <&gpio2 RK_PA1 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-Y"; + linux,code = ; // 0x133 + }; + sw8 { + gpios = <&gpio2 RK_PA0 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-X"; + linux,code = ; // 0x134 + }; + sw9 { + gpios = <&gpio2 RK_PB0 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-SELECT"; + linux,code = ; // 0x13a + }; + sw10 { + gpios = <&gpio2 RK_PA5 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-START"; + linux,code = ; // 0x13b + }; + sw11 { + gpios = <&gpio2 RK_PB1 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-THUMBL"; + linux,code = ; // 0x13d + }; + sw12 { + gpios = <&gpio2 RK_PB2 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-THUMBR"; + linux,code = ; // 0x13e + }; + sw13 { + gpios = <&gpio2 RK_PA4 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-G"; + linux,code = ; // 0x2c0 + }; + sw14 { + gpios = <&gpio2 RK_PA6 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-LEFT"; + linux,code = ; // 0x136 + }; + sw15 { + gpios = <&gpio2 RK_PA7 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-RIGHT"; + linux,code = ; // 0x137 + }; + sw16 { + gpios = <&gpio3 RK_PB2 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-RIGHT2"; + linux,code = ; // 0x139 + }; + sw17 { + gpios = <&gpio3 RK_PB4 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-LEFT2"; + linux,code = ; // 0x138 + }; + }; + + battery: battery { + compatible = "simple-battery"; + charge-full-design-microamp-hours = <3000000>; + charge-term-current-microamp = <200000>; + constant-charge-current-max-microamp = <1500000>; + constant-charge-voltage-max-microvolt = <4200000>; + factory-internal-resistance-micro-ohms = <100000>; + voltage-max-design-microvolt = <4100000>; + voltage-min-design-microvolt = <3300000>; + + ocv-capacity-celsius = <20>; + ocv-capacity-table-0 = + <4046950 100>, <4001920 95>, <3967900 90>, <3940000 85>, + <3910000 80>, <3870000 75>, <3830000 70>, <3790000 65>, + <3750000 60>, <3720000 55>, <3690000 50>, <3650000 45>, + <3610000 40>, <3570000 35>, <3540000 30>, <3500000 25>, + <3460000 20>, <3420000 15>, <3380000 10>, <3340000 5>, + <3300000 0>; + }; + + gpio-keys-vol { + compatible = "gpio-keys"; + autorepeat; + pinctrl-0 = <&btn_pins_vol>; + pinctrl-names = "default"; + + button-vol-down { + gpios = <&gpio0 RK_PC1 GPIO_ACTIVE_LOW>; + label = "VOLUMEDOWN"; + linux,code = ; + }; + + button-vol-up { + gpios = <&gpio0 RK_PB7 GPIO_ACTIVE_LOW>; + label = "VOLUMEUP"; + linux,code = ; + }; + }; + + leds: gpio-leds { + compatible = "gpio-leds"; + pinctrl-0 = <&led_pins>; + pinctrl-names = "default"; + + led-0 { + color = ; + default-state = "off"; + function = LED_FUNCTION_CHARGING; + gpios = <&gpio0 RK_PB3 GPIO_ACTIVE_HIGH>; + }; + + led-1 { + color = ; + default-state = "off"; + function = LED_FUNCTION_STATUS; + gpios = <&gpio0 RK_PB4 GPIO_ACTIVE_HIGH>; + }; + }; + + rk817-sound { + compatible = "simple-audio-card"; + pinctrl-names = "default"; + pinctrl-0 = <&hp_det>; + simple-audio-card,name = "rk817_int"; + simple-audio-card,format = "i2s"; + simple-audio-card,hp-det-gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_LOW>; + simple-audio-card,mclk-fs = <256>; + simple-audio-card,widgets = + "Microphone", "Mic Jack", + "Headphone", "Headphones", + "Speaker", "Speaker"; + simple-audio-card,routing = + "MICL", "Mic Jack", + "Headphones", "HPOL", + "Headphones", "HPOR", + "Speaker", "SPKO"; + + simple-audio-card,codec { + sound-dai = <&rk817>; + }; + + simple-audio-card,cpu { + sound-dai = <&i2s1_2ch>; + }; + }; + + vccsys: vccsys { + compatible = "regulator-fixed"; + regulator-name = "vcc3v8_sys"; + regulator-always-on; + regulator-min-microvolt = <3800000>; + regulator-max-microvolt = <3800000>; + }; + + vcc-phy-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_phy"; + regulator-always-on; + regulator-boot-on; + }; + + vcc18_lcd0: vcc18-lcd0 { + compatible = "regulator-fixed"; + regulator-name = "vcc18_lcd0_n"; + gpio = <&gpio0 RK_PB5 GPIO_ACTIVE_HIGH>; + enable-active-high; + pinctrl-0 = <&vcc18_lcd_n>; + pinctrl-names = "default"; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_host: vcc_host { + compatible = "regulator-fixed"; + regulator-name = "vcc_host"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-always-on; + regulator-boot-on; + vin-supply = <&usb_midu>; + }; +}; + +&dmc { + center-supply = <&vdd_logic>; +}; + +&cpu0 { + cpu-supply = <&vdd_arm>; +}; + +&cpu1 { + cpu-supply = <&vdd_arm>; +}; + +&cpu2 { + cpu-supply = <&vdd_arm>; +}; + +&cpu3 { + cpu-supply = <&vdd_arm>; +}; + +&cru { + assigned-clocks = <&cru PLL_NPLL>, + <&cru ACLK_BUS_PRE>, <&cru ACLK_PERI_PRE>, + <&cru HCLK_BUS_PRE>, <&cru HCLK_PERI_PRE>, + <&cru PCLK_BUS_PRE>, <&cru SCLK_GPU>; + + assigned-clock-rates = <1188000000>, + <200000000>, <200000000>, + <150000000>, <150000000>, + <100000000>, <200000000>; +}; + +&display_subsystem { + status = "okay"; +}; + +&dsi { + status = "okay"; + + ports { + mipi_out: port@1 { + reg = <1>; + + mipi_out_panel: endpoint { + remote-endpoint = <&mipi_in_panel>; + }; + }; + }; + + internal_display: panel@0 { + compatible = "magicx,xu10-panel", "sitronix,st7703"; + iovcc-supply = <&vcc18_lcd0>; + vcc-supply = <&vcc18_lcd0>; + reg = <0>; + backlight = <&backlight>; + reset-gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&lcd_rst>; + + port { + mipi_in_panel: endpoint { + remote-endpoint = <&mipi_out_panel>; + }; + }; + }; +}; + +&dsi_dphy { + status = "okay"; +}; + +&gpu { + mali-supply = <&vdd_logic>; + status = "okay"; +}; + +&i2c0 { + clock-frequency = <400000>; + i2c-scl-falling-time-ns = <16>; + i2c-scl-rising-time-ns = <280>; + status = "okay"; + + rk817: pmic@20 { + compatible = "rockchip,rk817"; + reg = <0x20>; + interrupt-parent = <&gpio0>; + interrupts = ; + clock-output-names = "rk808-clkout1", "xin32k"; + clock-names = "mclk"; + clocks = <&cru SCLK_I2S1_OUT>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int>, <&i2s1_2ch_mclk>; + rockchip,system-power-controller; + wakeup-source; + #clock-cells = <1>; + #sound-dai-cells = <0>; + + vcc1-supply = <&vccsys>; + vcc2-supply = <&vccsys>; + vcc3-supply = <&vccsys>; + vcc4-supply = <&vccsys>; + vcc5-supply = <&vccsys>; + vcc6-supply = <&vccsys>; + vcc7-supply = <&vcc_3v0>; + vcc8-supply = <&vccsys>; + vcc9-supply = <&usb_midu>; + + regulators { + vdd_logic: DCDC_REG1 { + regulator-name = "vdd_logic"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <1150000>; + regulator-ramp-delay = <6001>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vdd_arm: DCDC_REG2 { + regulator-name = "vdd_arm"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-name = "vcc_ddr"; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_3v0: DCDC_REG4 { + regulator-name = "vcc_3v0"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcc_1v0: LDO_REG1 { + regulator-name = "vcc_1v0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vcc1v8_soc: LDO_REG2 { + regulator-name = "vcc1v8_soc"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc1v0_soc: LDO_REG3 { + regulator-name = "vcc1v0_soc"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vcc3v0_pmu: LDO_REG4 { + regulator-name = "vcc3v0_pmu"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vccio_sd: LDO_REG5 { + regulator-name = "vccio_sd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_sd: LDO_REG6 { + regulator-name = "vcc_sd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3000000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcc2v8_dvp: LDO_REG7 { + regulator-name = "vcc2v8_dvp"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <2800000>; + }; + }; + + vcc3v0_dvp: LDO_REG8 { + regulator-name = "vcc3v0_dvp"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vdd1v5_dvp: LDO_REG9 { + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + regulator-name = "vdd1v5_dvp"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <1500000>; + }; + }; + + usb_midu: BOOST { + regulator-name = "usb_midu"; + regulator-min-microvolt = <4700000>; + regulator-max-microvolt = <5400000>; + regulator-always-on; + regulator-boot-on; + }; + + }; + + rk817_charger: charger { + monitored-battery = <&battery>; + rockchip,resistor-sense-micro-ohms = <10000>; + rockchip,sleep-enter-current-microamp = <300000>; + rockchip,sleep-filter-current-microamp = <100000>; + }; + + rk817_codec: codec { + rockchip,mic-in-differential; + }; + }; +}; + +/* I2S 1 Channel Used Header(P2):1(GPIO2.C3),2(.C2), 3(.C1), 4(.C5), 5(.C4) */ +&i2s1_2ch { + status = "okay"; + #sound-dai-cells = <0>; +}; + +&io_domains { + vccio1-supply = <&vcc1v8_soc>; + vccio2-supply = <&vccio_sd>; + vccio3-supply = <&vcc3v0_dvp>; + vccio4-supply = <&vcc_3v0>; + vccio5-supply = <&vcc_3v0>; + vccio6-supply = <&vcc_3v0>; + status = "okay"; +}; + +&isp { + status = "okay"; +}; + +&isp_mmu { + status = "okay"; +}; + +&pmu_io_domains { + pmuio1-supply = <&vcc3v0_pmu>; + pmuio2-supply = <&vcc3v0_pmu>; + status = "okay"; +}; + +&csi_dphy { + status = "okay"; +}; + +&pwm1 { + status = "okay"; +}; + +&saradc { + vref-supply = <&vcc1v8_soc>; + status = "okay"; +}; + +&sdmmc { + cap-sd-highspeed; + card-detect-delay = <200>; + cd-gpios = <&gpio0 RK_PA3 GPIO_ACTIVE_LOW>; /*[> ff370000 PD_SDCARD CD GPIO <]*/ + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + vmmc-supply = <&vcc_sd>; + vqmmc-supply = <&vccio_sd>; + status = "okay"; +}; + +&sdio { + cap-sd-highspeed; + card-detect-delay = <200>; + cd-gpios = <&gpio3 RK_PB6 GPIO_ACTIVE_LOW>; /*[> CD GPIO <]*/ + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + vmmc-supply = <&vcc_sd>; + vqmmc-supply = <&vccio_sd>; + status = "okay"; +}; + +&tsadc { + status = "okay"; +}; + +&u2phy { + status = "okay"; + + u2phy_host: host-port { + status = "okay"; + }; + + u2phy_otg: otg-port { + status = "disabled"; + }; +}; + +/* FIQ Header(P2): 2(RXD:GPIO2.B4),3(TXD:.B6) */ +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&uart2m1_xfer>; + status = "okay"; +}; + +&usb20_otg { + status = "okay"; + dr_mode = "host"; +}; + +&vopb { + status = "okay"; +}; + +&vopb_mmu { + status = "okay"; +}; + +&pinctrl { + btns { + btn_pins: btn-pins { + rockchip,pins = <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + btn_pins_vol: btn-pins-vol { + rockchip,pins = + <0 RK_PC1 RK_FUNC_GPIO &pcfg_pull_up>, + <0 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + headphone { + hp_det: hp-det { + rockchip,pins = <2 RK_PC6 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + gpio-lcd { + lcd_rst: lcd-rst { + rockchip,pins = <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + vcc18-lcd { + vcc18_lcd_n: vcc18-lcd-n { + rockchip,pins = <0 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + gpio-led { + led_pins: led-pins { + rockchip,pins = + <0 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>, + <0 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pmic { + dc_det: dc-det { + rockchip,pins = <0 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + pmic_int: pmic-int { + rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + soc_slppin_gpio: soc_slppin_gpio { + rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_output_low>; + }; + + soc_slppin_rst: soc_slppin_rst { + rockchip,pins = <0 RK_PA4 2 &pcfg_pull_none>; + }; + + soc_slppin_slp: soc_slppin_slp { + rockchip,pins = <0 RK_PA4 1 &pcfg_pull_none>; + }; + }; +}; diff --git a/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-odroid-go.dtsi b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-odroid-go.dtsi new file mode 100644 index 0000000000..b655d10598 --- /dev/null +++ b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-odroid-go.dtsi @@ -0,0 +1,568 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2019 Hardkernel Co., Ltd + * Copyright (c) 2020 Theobroma Systems Design und Consulting GmbH + * Copyright (c) 2022 Maya Matuszczyk + */ + +/dts-v1/; +#include +#include +#include +#include +#include "rk3326.dtsi" + +/ { + aliases { + mmc0 = &sdmmc; + }; + + chosen { + stdout-path = "serial2:115200n8"; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + power-supply = <&vcc_bl>; + pwms = <&pwm1 0 25000 0>; + brightness-levels = < + 0 1 2 3 4 5 6 7 + 8 9 10 11 12 13 14 15 + 16 17 18 19 20 21 22 23 + 24 25 26 27 28 29 30 31 + 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 + 48 49 50 51 52 53 54 55 + 56 57 58 59 60 61 62 63 + 64 65 66 67 68 69 70 71 + 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 + 88 89 90 91 92 93 94 95 + 96 97 98 99 100 101 102 103 + 104 105 106 107 108 109 110 111 + 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 + 128 129 130 131 132 133 134 135 + 136 137 138 139 140 141 142 143 + 144 145 146 147 148 149 150 151 + 152 153 154 155 156 157 158 159 + 160 161 162 163 164 165 166 167 + 168 169 170 171 172 173 174 175 + 176 177 178 179 180 181 182 183 + 184 185 186 187 188 189 190 191 + 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 + 208 209 210 211 212 213 214 215 + 216 217 218 219 220 221 222 223 + 224 225 226 227 228 229 230 231 + 232 233 234 235 236 237 238 239 + 240 241 242 243 244 245 246 247 + 248 249 250 251 252 253 254 255>; + default-brightness-level = <128>; + }; + + /* led-1 is wired directly to output of always-on regulator */ + + gpio_led: gpio-leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&red_led_pin>; + + red_led: led-3 { + color = ; + gpios = <&gpio0 RK_PB5 GPIO_ACTIVE_HIGH>; + function = LED_FUNCTION_CHARGING; + }; + }; + + pwm_led: led-controller { + compatible = "pwm-leds"; + + blue_led: led-2 { + color = ; + function = LED_FUNCTION_STATUS; + linux,default-trigger = "heartbeat"; + max-brightness = <255>; + pwms = <&pwm3 0 25000 0>; + }; + }; + + rk817-sound { + compatible = "simple-audio-card"; + simple-audio-card,name = "rk817_int"; + simple-audio-card,format = "i2s"; + simple-audio-card,hp-det-gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>; + simple-audio-card,mclk-fs = <256>; + simple-audio-card,widgets = + "Microphone", "Mic Jack", + "Headphone", "Headphones", + "Speaker", "Speaker"; + simple-audio-card,routing = + "MICL", "Mic Jack", + "Headphones", "HPOL", + "Headphones", "HPOR", + "Speaker", "SPKO"; + + simple-audio-card,codec { + sound-dai = <&rk817>; + }; + + simple-audio-card,cpu { + sound-dai = <&i2s1_2ch>; + }; + }; + + vccsys: regulator-vccsys { + compatible = "regulator-fixed"; + regulator-name = "vcc3v8_sys"; + regulator-always-on; + regulator-min-microvolt = <3800000>; + regulator-max-microvolt = <3800000>; + }; + + vcc_host: regulator-vcc-host { + compatible = "regulator-fixed"; + regulator-name = "vcc_host"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + + gpio = <&gpio0 RK_PB7 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-always-on; + regulator-boot-on; + vin-supply = <&usb_midu>; + }; +}; + +&dmc { + center-supply = <&vdd_logic>; +}; + +&cpu0 { + cpu-supply = <&vdd_arm>; +}; + +&cpu1 { + cpu-supply = <&vdd_arm>; +}; + +&cpu2 { + cpu-supply = <&vdd_arm>; +}; + +&cpu3 { + cpu-supply = <&vdd_arm>; +}; + +&cru { + assigned-clocks = <&cru PLL_NPLL>, + <&cru ACLK_BUS_PRE>, <&cru ACLK_PERI_PRE>, + <&cru HCLK_BUS_PRE>, <&cru HCLK_PERI_PRE>, + <&cru PCLK_BUS_PRE>, <&cru SCLK_GPU>; + + assigned-clock-rates = <1188000000>, + <200000000>, <200000000>, + <150000000>, <150000000>, + <100000000>, <200000000>; +}; + +&display_subsystem { + status = "okay"; +}; + +&dsi { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + ports { + mipi_out: port@1 { + reg = <1>; + + mipi_out_panel: endpoint { + remote-endpoint = <&mipi_in_panel>; + }; + }; + }; + + internal_display: panel@0 { + reg = <0>; + backlight = <&backlight>; + reset-gpios = <&gpio3 RK_PC0 GPIO_ACTIVE_LOW>; + + port { + mipi_in_panel: endpoint { + remote-endpoint = <&mipi_out_panel>; + }; + }; + }; +}; + +&dsi_dphy { + status = "okay"; +}; + +&gpu { + mali-supply = <&vdd_logic>; + status = "okay"; +}; + +&i2c0 { + clock-frequency = <400000>; + i2c-scl-falling-time-ns = <16>; + i2c-scl-rising-time-ns = <280>; + status = "okay"; + + rk817: pmic@20 { + compatible = "rockchip,rk817"; + reg = <0x20>; + interrupt-parent = <&gpio0>; + interrupts = ; + clock-output-names = "rk808-clkout1", "xin32k"; + clock-names = "mclk"; + clocks = <&cru SCLK_I2S1_OUT>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int>, <&i2s1_2ch_mclk>; + rockchip,system-power-controller; + wakeup-source; + #clock-cells = <1>; + #sound-dai-cells = <0>; + + vcc1-supply = <&vccsys>; + vcc2-supply = <&vccsys>; + vcc3-supply = <&vccsys>; + vcc4-supply = <&vccsys>; + vcc5-supply = <&vccsys>; + vcc6-supply = <&vccsys>; + vcc7-supply = <&vccsys>; + vcc8-supply = <&vccsys>; + + regulators { + vdd_logic: DCDC_REG1 { + regulator-name = "vdd_logic"; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1150000>; + regulator-ramp-delay = <6001>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vdd_arm: DCDC_REG2 { + regulator-name = "vdd_arm"; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-name = "vcc_ddr"; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_3v3: DCDC_REG4 { + regulator-name = "vcc_3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_1v8: LDO_REG2 { + regulator-name = "vcc_1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd_1v0: LDO_REG3 { + regulator-name = "vdd_1v0"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vcc3v3_pmu: LDO_REG4 { + regulator-name = "vcc3v3_pmu"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vccio_sd: LDO_REG5 { + regulator-name = "vccio_sd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_sd: LDO_REG6 { + regulator-name = "vcc_sd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_bl: LDO_REG7 { + regulator-name = "vcc_bl"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_lcd: LDO_REG8 { + regulator-name = "vcc_lcd"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <2800000>; + }; + }; + + LDO_REG9 { + /* unused */ + }; + + usb_midu: BOOST { + regulator-name = "usb_midu"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5400000>; + regulator-always-on; + regulator-boot-on; + }; + }; + + rk817_charger: charger { + rockchip,resistor-sense-micro-ohms = <10000>; + rockchip,sleep-enter-current-microamp = <300000>; + rockchip,sleep-filter-current-microamp = <100000>; + }; + + rk817_codec: codec { + rockchip,mic-in-differential; + }; + }; +}; + +/* EXT Header(P2): 7(SCL:GPIO0.C2), 8(SDA:GPIO0.C3) */ +&i2c1 { + clock-frequency = <400000>; + status = "okay"; +}; + +/* I2S 1 Channel Used */ +&i2s1_2ch { + status = "okay"; +}; + +&io_domains { + vccio1-supply = <&vcc_3v3>; + vccio2-supply = <&vccio_sd>; + vccio3-supply = <&vcc_3v3>; + vccio4-supply = <&vcc_3v3>; + vccio5-supply = <&vcc_3v3>; + vccio6-supply = <&vcc_3v3>; + status = "okay"; +}; + +&pmu_io_domains { + pmuio1-supply = <&vcc3v3_pmu>; + pmuio2-supply = <&vcc3v3_pmu>; + status = "okay"; +}; + +&pwm1 { + status = "okay"; +}; + +&pwm3 { + status = "okay"; +}; + +&saradc { + vref-supply = <&vcc_1v8>; + status = "okay"; +}; + +&sdmmc { + cap-sd-highspeed; + card-detect-delay = <200>; + cd-gpios = <&gpio0 RK_PA3 GPIO_ACTIVE_LOW>; /*[> CD GPIO <]*/ + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + vmmc-supply = <&vcc_sd>; + vqmmc-supply = <&vccio_sd>; + status = "okay"; +}; + +&sfc { + pinctrl-0 = <&sfc_clk &sfc_cs0 &sfc_bus2>; + pinctrl-names = "default"; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <108000000>; + spi-rx-bus-width = <2>; + spi-tx-bus-width = <1>; + }; +}; + +&tsadc { + status = "okay"; +}; + +&u2phy { + status = "okay"; + + u2phy_host: host-port { + status = "okay"; + }; + + u2phy_otg: otg-port { + status = "disabled"; + }; +}; + +&usb20_otg { + status = "okay"; +}; + +/* EXT Header(P2): 2(RXD:GPIO1.C0),3(TXD:.C1),4(CTS:.C2),5(RTS:.C3) */ +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_xfer &uart1_cts>; + status = "okay"; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&uart2m1_xfer>; + status = "okay"; +}; + +&vopb { + status = "okay"; +}; + +&vopb_mmu { + status = "okay"; +}; + +&pinctrl { + btns { + btn_pins: btn-pins { + rockchip,pins = <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + headphone { + hp_det: hp-det { + rockchip,pins = <2 RK_PC6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + + leds { + red_led_pin: red-led-pin { + rockchip,pins = <0 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pmic { + dc_det: dc-det { + rockchip,pins = <0 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + pmic_int: pmic-int { + rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + soc_slppin_gpio: soc_slppin_gpio { + rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_output_low>; + }; + + soc_slppin_rst: soc_slppin_rst { + rockchip,pins = <0 RK_PA4 2 &pcfg_pull_none>; + }; + + soc_slppin_slp: soc_slppin_slp { + rockchip,pins = <0 RK_PA4 1 &pcfg_pull_none>; + }; + }; +}; diff --git a/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-odroid-go2-v11.dts b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-odroid-go2-v11.dts new file mode 100644 index 0000000000..f96fb0645a --- /dev/null +++ b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-odroid-go2-v11.dts @@ -0,0 +1,308 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2019 Hardkernel Co., Ltd + * Copyright (c) 2020 Theobroma Systems Design und Consulting GmbH + * Copyright (c) 2022 Maya Matuszczyk + */ + +/dts-v1/; +#include "rk3326-odroid-go.dtsi" + +/ { + model = "ODROID-GO Advance Black Edition"; + compatible = "hardkernel,rk3326-odroid-go2-v11", "rockchip,rk3326"; + + aliases { + mmc1 = &sdio; + }; + + gpio_keys: volume-keys { + compatible = "gpio-keys"; + autorepeat; + pinctrl-0 = <&btn_pins_vol>; + pinctrl-names = "default"; + + volume-up-button { + label = "VOLUMEUP"; + linux,code = ; + gpios = <&gpio2 RK_PA3 GPIO_ACTIVE_LOW>; + + }; + volume-down-button { + label = "VOLUMEDOWN"; + linux,code = ; + gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; + + }; + }; + + joypad: odroidgo2-joypad { + compatible = "odroidgo2-v11-joypad"; + + /* + - odroidgo2-joypad sysfs list - + * for poll device interval(ms) + /sys/devices/platform/odroidgo2_joypad/poll_interval [rw] + * for button-adc-fuzz + /sys/devices/platform/odroidgo2_joypad/adc_fuzz [r] + * for button-adc-flat + /sys/devices/platform/odroidgo2_joypad/adc_flat [r] + + * for report control(1:enable, 0:disable) + /sys/devices/platform/odroidgo2_joypad/enable [rw] + * for adc calibration value setup(1:current adcs value -> cal value) + /sys/devices/platform/odroidgo2_joypad/adc_cal [rw] + */ + + /* gpio pincontrol setup */ + pinctrl-names = "default"; + pinctrl-0 = <&btn_pins>; + + /* JOY_X, JOY_Y Channel define */ + io-channel-names = "joy_x", "joy_y"; + io-channels = <&saradc 1>, <&saradc 2>; + + /* adc channel count */ + button-adc-count = <2>; + + /* adc calculate scale */ + button-adc-scale = <2>; + + /* adc deadzone range */ + button-adc-deadzone = <20>; + + /* + joy-stick voltage range + /sys/devices/platform/ff288000.saradc/iio:device0 + adc-x : in_voltage1_raw + adc-y : in_voltage2_raw + + range calculate. + (adc raw max value - adc raw min value) * scale * 1.7515 + */ + button-adc-x-range = <1800>; + button-adc-y-range = <1800>; + + /* + specifies fuzz value that is used to filter noise from + the event stream. + */ + button-adc-fuzz = <32>; + button-adc-flat = <32>; + + /* poll device interval (ms), adc read interval */ + poll-interval = <10>; + + /* gpio button auto repeat set value : default disable */ + /* + autorepeat; + */ + + /* + *** ODROIDGO2-Advance Switch layoout *** + |------------------------------------------------| + | sw15 sw16 | + | sw20 sw21 | + |------------------------------------------------| + | sw1 |-------------------| sw8 | + | sw3 sw4 | | sw7 sw5 | + | sw2 | LCD Display | sw6 | + | | | | + | |-------------------| | + | sw9 sw10 vol- vol+ sw13 sw14 | + |------------------------------------------------| + */ + /* + joypad driver is poll-device driver. + poll-device is does not support wakeup-source. + */ + sw1 { + gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-UP"; + linux,code = ; // 0x220 + }; + sw2 { + gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-DOWN"; + linux,code = ; // 0x221 + }; + sw3 { + gpios = <&gpio1 RK_PB6 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-LEFT"; + linux,code = ; // 0x222 + }; + sw4 { + gpios = <&gpio1 RK_PB7 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-RIGHT"; + linux,code = ; // 0x223 + }; + sw5 { + gpios = <&gpio1 RK_PA2 GPIO_ACTIVE_LOW>; + label = "GPIO KEY BTN-A"; + linux,code = ; // 0x131 + }; + sw6 { + gpios = <&gpio1 RK_PA5 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-B"; + linux,code = ; // 0x130 + }; + sw7 { + gpios = <&gpio1 RK_PA6 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-Y"; + linux,code = ; // 0x134 + }; + sw8 { + gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-X"; + linux,code = ; // 0x133 + }; + sw9 { + gpios = <&gpio2 RK_PA0 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-SELECT"; + linux,code = ; // 0x2c0 + }; + sw10 { + gpios = <&gpio2 RK_PA1 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-THUMBL"; + linux,code = ; // 0x2c1 + }; + sw13 { + gpios = <&gpio2 RK_PA4 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-THUMBR"; + linux,code = ; // 0x2c4 + }; + sw14 { + gpios = <&gpio2 RK_PA5 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-START"; + linux,code = ; // 0x13c + }; + sw15 { + gpios = <&gpio2 RK_PA6 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-LEFT"; + linux,code = ; // 0x02 + }; + sw16 { + gpios = <&gpio2 RK_PA7 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-RIGHT"; + linux,code = ; // 0x05 + }; + sw20 { + gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-LEFT2"; + linux,code = ; + }; + sw21 { + gpios = <&gpio3 RK_PB2 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-RIGHT2"; + linux,code = ; + }; + }; + + battery: battery { + compatible = "simple-battery"; + charge-full-design-microamp-hours = <3000000>; + charge-term-current-microamp = <300000>; + constant-charge-current-max-microamp = <2000000>; + constant-charge-voltage-max-microvolt = <4200000>; + factory-internal-resistance-micro-ohms = <180000>; + voltage-max-design-microvolt = <4100000>; + voltage-min-design-microvolt = <3500000>; + + ocv-capacity-celsius = <20>; + ocv-capacity-table-0 = <4046950 100>, <4001920 95>, <3967900 90>, <3919950 85>, + <3888450 80>, <3861850 75>, <3831540 70>, <3799130 65>, + <3768190 60>, <3745650 55>, <3726610 50>, <3711630 45>, + <3696720 40>, <3685660 35>, <3674950 30>, <3663050 25>, + <3649470 20>, <3635260 15>, <3616920 10>, <3592440 5>, + <3574170 0>; + }; + + wifi_pwrseq: wifi-pwrseq { + compatible = "mmc-pwrseq-simple"; + pinctrl-names = "default"; + pinctrl-0 = <&wifi_pwrseq_pins>; + reset-gpios = <&gpio3 RK_PB1 GPIO_ACTIVE_LOW>; + post-power-on-delay-ms = <300>; + power-off-delay-us = <200000>; + }; +}; + +&internal_display { + compatible = "elida,kd35t133"; + iovcc-supply = <&vcc_lcd>; + vdd-supply = <&vcc_lcd>; + rotation = <270>; +}; + +&rk817 { + regulators { + vcc_wifi: LDO_REG9 { + regulator-name = "vcc_wifi"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + }; +}; + +&rk817_charger { + monitored-battery = <&battery>; +}; + +&sdio { + bus-width = <4>; + cap-sd-highspeed; + cap-sdio-irq; + disable-wp; + keep-power-in-suspend; + non-removable; + vmmc-supply = <&vcc_wifi>; + mmc-pwrseq = <&wifi_pwrseq>; + status = "okay"; + + esp8089: wifi@1 { + compatible = "esp,esp8089"; + reg = <1>; + esp,crystal-26M-en = <1>; + }; +}; + +&pinctrl { + btns { + btn_pins: btn-pins { + rockchip,pins = <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + btn_pins_vol: btn-pins-vol { + rockchip,pins = <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + wifi { + wifi_pwrseq_pins: wifi-pwrseq-pins { + rockchip,pins = <3 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB6 RK_FUNC_GPIO &pcfg_output_high>; + }; + }; +}; diff --git a/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-odroid-go2.dts b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-odroid-go2.dts new file mode 100644 index 0000000000..f142737a01 --- /dev/null +++ b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-odroid-go2.dts @@ -0,0 +1,235 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2019 Hardkernel Co., Ltd + * Copyright (c) 2020 Theobroma Systems Design und Consulting GmbH + * Copyright (c) 2022 Maya Matuszczyk + */ + +/dts-v1/; +#include "rk3326-odroid-go.dtsi" + +/ { + model = "ODROID-GO Advance"; + compatible = "hardkernel,rk3326-odroid-go2", "rockchip,rk3326"; + + gpio_keys: volume-keys { + compatible = "gpio-keys-polled"; + poll-interval = <5>; + autorepeat; + + volume-up-button { + label = "VOLUME-UP"; + linux,code = ; + gpios = <&gpio2 RK_PA3 GPIO_ACTIVE_LOW>; + + }; + volume-down-button { + label = "VOLUME-DOWN"; + linux,code = ; + gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; + + }; + }; + + joypad: odroidgo2-joypad { + compatible = "odroidgo2-joypad"; + + /* + - odroidgo2-joypad sysfs list - + * for poll device interval(ms) + /sys/devices/platform/odroidgo2_joypad/poll_interval [rw] + * for button-adc-fuzz + /sys/devices/platform/odroidgo2_joypad/adc_fuzz [r] + * for button-adc-flat + /sys/devices/platform/odroidgo2_joypad/adc_flat [r] + + * for report control(1:enable, 0:disable) + /sys/devices/platform/odroidgo2_joypad/enable [rw] + * for adc calibration value setup(1:current adcs value -> cal value) + /sys/devices/platform/odroidgo2_joypad/adc_cal [rw] + */ + + /* gpio pincontrol setup */ + pinctrl-names = "default"; + pinctrl-0 = <&btn_pins>; + + /* JOY_X, JOY_Y Channel define */ + io-channel-names = "joy_x", "joy_y"; + io-channels = <&saradc 1>, <&saradc 2>; + + /* adc channel count */ + button-adc-count = <2>; + + /* adc calculate scale */ + button-adc-scale = <2>; + + /* adc deadzone range */ + button-adc-deadzone = <20>; + + /* + joy-stick voltage range + /sys/devices/platform/ff288000.saradc/iio:device0 + adc-x : in_voltage1_raw + adc-y : in_voltage2_raw + + range calculate. + (adc raw max value - adc raw min value) * scale * 1.7515 + */ + button-adc-x-range = <1800>; + button-adc-y-range = <1800>; + + /* + specifies fuzz value that is used to filter noise from + the event stream. + */ + button-adc-fuzz = <32>; + button-adc-flat = <32>; + + /* poll device interval (ms), adc read interval */ + poll-interval = <10>; + + /* gpio button auto repeat set value : default disable */ + /* + autorepeat; + */ + + /* + *** ODROIDGO2-Advance Switch layoout *** + |------------------------------------------------| + | sw15 sw16 | + |------------------------------------------------| + | sw1 |-------------------| sw8 | + | sw3 sw4 | | sw7 sw5 | + | sw2 | LCD Display | sw6 | + | | | | + | |-------------------| | + | sw9 sw10 vol- vol+ sw13 sw14 | + |------------------------------------------------| + */ + /* + joypad driver is poll-device driver. + poll-device is does not support wakeup-source. + */ + sw1 { + gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-UP"; + linux,code = ; // 0x220 + }; + sw2 { + gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-DOWN"; + linux,code = ; // 0x221 + }; + sw3 { + gpios = <&gpio1 RK_PB6 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-LEFT"; + linux,code = ; // 0x222 + }; + sw4 { + gpios = <&gpio1 RK_PB7 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-RIGHT"; + linux,code = ; // 0x223 + }; + sw5 { + gpios = <&gpio1 RK_PA2 GPIO_ACTIVE_LOW>; + label = "GPIO KEY BTN-A"; + linux,code = ; // 0x131 + }; + sw6 { + gpios = <&gpio1 RK_PA5 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-B"; + linux,code = ; // 0x130 + }; + sw7 { + gpios = <&gpio1 RK_PA6 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-Y"; + linux,code = ; // 0x134 + }; + sw8 { + gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-X"; + linux,code = ; // 0x133 + }; + sw9 { + gpios = <&gpio2 RK_PA0 GPIO_ACTIVE_LOW>; + label = "GPIO F1"; + linux,code = ; // 0x2c0 + }; + sw10 { + gpios = <&gpio2 RK_PA1 GPIO_ACTIVE_LOW>; + label = "GPIO F2"; + linux,code = ; // 0x2c1 + }; + sw13 { + gpios = <&gpio2 RK_PA4 GPIO_ACTIVE_LOW>; + label = "GPIO F5"; + linux,code = ; // 0x2c4 + }; + sw14 { + gpios = <&gpio2 RK_PA5 GPIO_ACTIVE_LOW>; + label = "GPIO F6"; + linux,code = ; // 0x13c + }; + sw15 { + gpios = <&gpio2 RK_PA6 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-LEFT"; + linux,code = ; // 0x02 + }; + sw16 { + gpios = <&gpio2 RK_PA7 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-RIGHT"; + linux,code = ; // 0x05 + }; + }; + + battery: battery { + compatible = "simple-battery"; + charge-full-design-microamp-hours = <3000000>; + charge-term-current-microamp = <300000>; + constant-charge-current-max-microamp = <2000000>; + constant-charge-voltage-max-microvolt = <4200000>; + factory-internal-resistance-micro-ohms = <180000>; + voltage-max-design-microvolt = <4100000>; + voltage-min-design-microvolt = <3500000>; + + ocv-capacity-celsius = <20>; + ocv-capacity-table-0 = <4046950 100>, <4001920 95>, <3967900 90>, <3919950 85>, + <3888450 80>, <3861850 75>, <3831540 70>, <3799130 65>, + <3768190 60>, <3745650 55>, <3726610 50>, <3711630 45>, + <3696720 40>, <3685660 35>, <3674950 30>, <3663050 25>, + <3649470 20>, <3635260 15>, <3616920 10>, <3592440 5>, + <3574170 0>; + }; +}; + +&internal_display { + compatible = "elida,kd35t133"; + iovcc-supply = <&vcc_lcd>; + vdd-supply = <&vcc_lcd>; + rotation = <270>; +}; + +&rk817_charger { + monitored-battery = <&battery>; +}; + +&pinctrl { + btns { + btn_pins: btn-pins { + rockchip,pins = <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +}; diff --git a/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-odroid-go3.dts b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-odroid-go3.dts new file mode 100644 index 0000000000..c3099f9cfe --- /dev/null +++ b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-odroid-go3.dts @@ -0,0 +1,289 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2019 Hardkernel Co., Ltd + * Copyright (c) 2020 Theobroma Systems Design und Consulting GmbH + * Copyright (c) 2022 Maya Matuszczyk + */ + +/dts-v1/; +#include "rk3326-odroid-go.dtsi" + +/ { + model = "ODROID-GO Super"; + compatible = "hardkernel,rk3326-odroid-go3", "rockchip,rk3326"; + + joypad: odroidgo3-joypad { + compatible = "odroidgo3-joypad"; + + joypad-name = "odroidgo3_joypad"; + joypad-product = <0x0001>; + joypad-revision = <0x0101>; + + status = "okay"; + /* + - odroidgo3-joypad sysfs list - + * for poll device interval(ms) + /sys/devices/platform/odroidgo3_joypad/poll_interval [rw] + ex) echo 20 > poll_interval + * for button-adc-fuzz + /sys/devices/platform/odroidgo3_joypad/adc_fuzz [r] + * for button-adc-flat + /sys/devices/platform/odroidgo3_joypad/adc_flat [r] + + * for report control(1:enable, 0:disable) + /sys/devices/platform/odroidgo3_joypad/enable [rw] + * for adc calibration value setup(current adcs value -> cal value) + /sys/devices/platform/odroidgo3_joypad/adc_cal [rw] + ex) echo 0 > adc_cal + * for amux data debug + * Joypad driver is disabled when using this sysfs. + /sys/devices/platform/odroidgo3_joypad/amux_debug [rw] + ex) echo 0 > amux_debug --> select amux channel + ex) cat amux_debug --> get adc data of seleted channel + */ + + /* gpio pincontrol setup */ + pinctrl-names = "default"; + pinctrl-0 = <&btn_pins>; + + /* Analog mux define */ + io-channel-names = "amux_adc"; + io-channels = <&saradc 1>; + + /* adc mux channel count */ + amux-count = <4>; + /* adc mux select(a,b) gpio */ + amux-a-gpios = <&gpio3 RK_PB3 GPIO_ACTIVE_LOW>; + amux-b-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>; + /* adc mux enable gpio */ + amux-en-gpios = <&gpio3 RK_PB5 GPIO_ACTIVE_LOW>; + + /* adc calculate scale */ + button-adc-scale = <2>; + + /* adc deadzone range */ + button-adc-deadzone = <64>; + + /* + specifies fuzz value that is used to filter noise from + the event stream. + */ + button-adc-fuzz = <32>; + button-adc-flat = <32>; + + /* + Analog Stick data tuning value(precent) + p = positive direction, n = negative direction + report value = (real_adc_data * tuning_value) / 100 + */ + abs_x-p-tuning = <180>; + abs_x-n-tuning = <180>; + + abs_y-p-tuning = <180>; + abs_y-n-tuning = <170>; + + abs_rx-p-tuning = <180>; + abs_rx-n-tuning = <180>; + + abs_ry-p-tuning = <180>; + abs_ry-n-tuning = <170>; + + /* poll device interval (ms), adc read interval */ + poll-interval = <10>; + + /* gpio button auto repeat set value : default disable */ + /* + autorepeat; + */ + + /* + *** ODROIDGO3-Advance Switch layoout *** + |------------------------------------------------| + | sw15 sw21 sw10 sw9 sw20 sw16 | + |------------------------------------------------| + | sw19 sw22 | + | |-------------------| | + | sw1 | | sw8 | + | sw3 sw4 | | sw7 sw5 | + | sw2 | LCD Display | sw6 | + | | | | + | | | | + | |-------------------| | + | sw11 sw12 | sd-slot | sw13 sw14 | + |-------------------| |------------------| + */ + /* + joypad driver is poll-device driver. + poll-device is does not support wakeup-source. + */ + sw1 { + gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-UP"; + linux,code = ; // 0x220 + }; + sw2 { + gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-DOWN"; + linux,code = ; // 0x221 + }; + sw3 { + gpios = <&gpio1 RK_PB6 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-LEFT"; + linux,code = ; // 0x222 + }; + sw4 { + gpios = <&gpio1 RK_PB7 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-RIGHT"; + linux,code = ; // 0x223 + }; + sw5 { + gpios = <&gpio1 RK_PA2 GPIO_ACTIVE_LOW>; + label = "GPIO KEY BTN-A"; + linux,code = ; // 0x131 + }; + sw6 { + gpios = <&gpio1 RK_PA5 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-B"; + linux,code = ; // 0x130 + }; + sw7 { + gpios = <&gpio1 RK_PA6 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-Y"; + linux,code = ; // 0x134 + }; + sw8 { + gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-X"; + linux,code = ; // 0x133 + }; + sw11 { + gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; + label = "GPIO F3"; + linux,code = ; // 0x2c2 + }; + sw12 { + gpios = <&gpio2 RK_PA3 GPIO_ACTIVE_LOW>; + label = "GPIO F4"; + linux,code = ; // 0x2c3 + }; + sw13 { + gpios = <&gpio2 RK_PA4 GPIO_ACTIVE_LOW>; + label = "GPIO F5"; + linux,code = ; // 0x2c4 + }; + sw14 { + gpios = <&gpio2 RK_PA5 GPIO_ACTIVE_LOW>; + label = "GPIO F6"; + linux,code = ; // 0x13c + }; + sw15 { + gpios = <&gpio2 RK_PA6 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-LEFT"; + linux,code = ; // 0x02 + }; + sw16 { + gpios = <&gpio2 RK_PA7 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-RIGHT"; + linux,code = ; // 0x05 + }; + sw19 { + gpios = <&gpio3 RK_PB1 GPIO_ACTIVE_LOW>; + label = "GPIO F1"; + linux,code = ; + }; + sw20 { + gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-RIGHT2"; + linux,code = ; + }; + sw21 { + gpios = <&gpio3 RK_PB2 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-LEFT2"; + linux,code = ; + }; + sw22 { + gpios = <&gpio3 RK_PB4 GPIO_ACTIVE_LOW>; + label = "GPIO F2"; + linux,code = ; + }; + }; + + battery: battery { + compatible = "simple-battery"; + charge-full-design-microamp-hours = <4000000>; + charge-term-current-microamp = <300000>; + constant-charge-current-max-microamp = <2000000>; + constant-charge-voltage-max-microvolt = <4200000>; + factory-internal-resistance-micro-ohms = <180000>; + voltage-max-design-microvolt = <4100000>; + voltage-min-design-microvolt = <3500000>; + + ocv-capacity-celsius = <20>; + ocv-capacity-table-0 = <4046950 100>, <4001920 95>, <3967900 90>, <3919950 85>, + <3888450 80>, <3861850 75>, <3831540 70>, <3799130 65>, + <3768190 60>, <3745650 55>, <3726610 50>, <3711630 45>, + <3696720 40>, <3685660 35>, <3674950 30>, <3663050 25>, + <3649470 20>, <3635260 15>, <3616920 10>, <3592440 5>, + <3574170 0>; + }; + + gpio-keys-vol { + compatible = "gpio-keys"; + autorepeat; + pinctrl-0 = <&btn_pins_vol>; + pinctrl-names = "default"; + + button-vol-down { + gpios = <&gpio2 RK_PA1 GPIO_ACTIVE_LOW>; + label = "VOLUMEDOWN"; + linux,code = ; + }; + + button-volume-up { + gpios = <&gpio2 RK_PA0 GPIO_ACTIVE_LOW>; + label = "VOLUMEUP"; + linux,code = ; + }; + }; +}; + +&internal_display { + compatible = "elida,kd50t048a", "sitronix,st7701"; + reset-gpios = <&gpio3 RK_PC0 GPIO_ACTIVE_HIGH>; + IOVCC-supply = <&vcc_lcd>; + VCC-supply = <&vcc_lcd>; + rotation = <270>; +}; + +&rk817_charger { + monitored-battery = <&battery>; +}; + +&pinctrl { + btns { + btn_pins: btn-pins { + rockchip,pins = <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + btn_pins_vol: btn-pins-vol { + rockchip,pins = <2 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +}; diff --git a/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-powkiddy-rgb10.dts b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-powkiddy-rgb10.dts new file mode 100644 index 0000000000..23a30542b9 --- /dev/null +++ b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-powkiddy-rgb10.dts @@ -0,0 +1,280 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2019 Hardkernel Co., Ltd + * Copyright (c) 2020 Theobroma Systems Design und Consulting GmbH + * Copyright (c) 2022 Maya Matuszczyk + */ + +/dts-v1/; +#include "rk3326-odroid-go.dtsi" + +/ { + model = "Powkiddy RGB10"; + compatible = "powkiddy,rk3326-rgb10", "rockchip,rk3326"; + + aliases { + mmc1 = &sdio; + }; + + joypad: odroidgo2-joypad { + compatible = "odroidgo2-v11-joypad"; + + /* + - odroidgo2-joypad sysfs list - + * for poll device interval(ms) + /sys/devices/platform/odroidgo2_joypad/poll_interval [rw] + * for button-adc-fuzz + /sys/devices/platform/odroidgo2_joypad/adc_fuzz [r] + * for button-adc-flat + /sys/devices/platform/odroidgo2_joypad/adc_flat [r] + + * for report control(1:enable, 0:disable) + /sys/devices/platform/odroidgo2_joypad/enable [rw] + * for adc calibration value setup(1:current adcs value -> cal value) + /sys/devices/platform/odroidgo2_joypad/adc_cal [rw] + */ + + /* gpio pincontrol setup */ + pinctrl-names = "default"; + pinctrl-0 = <&btn_pins>; + + /* JOY_X, JOY_Y Channel define */ + io-channel-names = "joy_x", "joy_y"; + io-channels = <&saradc 1>, <&saradc 2>; + + /* adc channel count */ + button-adc-count = <2>; + + /* adc calculate scale */ + button-adc-scale = <2>; + + /* adc deadzone range */ + button-adc-deadzone = <20>; + + /* + joy-stick voltage range + /sys/devices/platform/ff288000.saradc/iio:device0 + adc-x : in_voltage1_raw + adc-y : in_voltage2_raw + + range calculate. + (adc raw max value - adc raw min value) * scale * 1.7515 + */ + button-adc-x-range = <1800>; + button-adc-y-range = <1800>; + + /* + specifies fuzz value that is used to filter noise from + the event stream. + */ + button-adc-fuzz = <32>; + button-adc-flat = <32>; + + /* poll device interval (ms), adc read interval */ + poll-interval = <10>; + + /* gpio button auto repeat set value : default disable */ + /* + autorepeat; + */ + + /* + *** RGB10 Switch layoout *** + |------------------------------------------------| + | sw15 sw16 | + | sw20 sw21 | + |------------------------------------------------| + | sw1 sw10 |-------------------| sw13 sw8 | + | sw3 sw4 | | sw7 sw5 | + | sw2 | LCD Display | sw6 | + | | | | + | |-------------------| | + |------------------------------------------------| + */ + /* + joypad driver is poll-device driver. + poll-device is does not support wakeup-source. + */ + sw1 { + gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-UP"; + linux,code = ; // 0x220 + }; + sw2 { + gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-DOWN"; + linux,code = ; // 0x221 + }; + sw3 { + gpios = <&gpio1 RK_PB6 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-LEFT"; + linux,code = ; // 0x222 + }; + sw4 { + gpios = <&gpio1 RK_PB7 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-RIGHT"; + linux,code = ; // 0x223 + }; + sw5 { + gpios = <&gpio1 RK_PA2 GPIO_ACTIVE_LOW>; + label = "GPIO KEY BTN-A"; + linux,code = ; // 0x131 + }; + sw6 { + gpios = <&gpio1 RK_PA5 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-B"; + linux,code = ; // 0x130 + }; + sw7 { + gpios = <&gpio1 RK_PA6 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-Y"; + linux,code = ; // 0x134 + }; + sw8 { + gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-X"; + linux,code = ; // 0x133 + }; + sw9 { + gpios = <&gpio2 RK_PA0 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-SELECT"; + linux,code = ; // 0x2c0 + }; + sw10 { + gpios = <&gpio2 RK_PA1 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-THUMBL"; + linux,code = ; // 0x2c1 + }; + sw13 { + gpios = <&gpio2 RK_PA4 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-THUMBR"; + linux,code = ; // 0x2c4 + }; + sw14 { + gpios = <&gpio2 RK_PA5 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-START"; + linux,code = ; // 0x13c + }; + sw15 { + gpios = <&gpio2 RK_PA6 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-LEFT"; + linux,code = ; // 0x02 + }; + sw16 { + gpios = <&gpio2 RK_PA7 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-RIGHT"; + linux,code = ; // 0x05 + }; + sw20 { + gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-LEFT2"; + linux,code = ; + }; + sw21 { + gpios = <&gpio2 RK_PA3 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-RIGHT2"; + linux,code = ; + }; + }; + + battery: battery { + compatible = "simple-battery"; + charge-full-design-microamp-hours = <2800000>; + charge-term-current-microamp = <280000>; + constant-charge-current-max-microamp = <2000000>; + constant-charge-voltage-max-microvolt = <4200000>; + factory-internal-resistance-micro-ohms = <180000>; + voltage-max-design-microvolt = <4100000>; + voltage-min-design-microvolt = <3500000>; + + ocv-capacity-celsius = <20>; + ocv-capacity-table-0 = <4046950 100>, <4001920 95>, <3967900 90>, <3919950 85>, + <3888450 80>, <3861850 75>, <3831540 70>, <3799130 65>, + <3768190 60>, <3745650 55>, <3726610 50>, <3711630 45>, + <3696720 40>, <3685660 35>, <3674950 30>, <3663050 25>, + <3649470 20>, <3635260 15>, <3616920 10>, <3592440 5>, + <3574170 0>; + }; + + wifi_pwrseq: wifi-pwrseq { + compatible = "mmc-pwrseq-simple"; + pinctrl-names = "default"; + pinctrl-0 = <&wifi_pwrseq_pins>; + /*reset-gpios = <&gpio3 RK_PB1 GPIO_ACTIVE_LOW>;*/ + }; +}; + +&internal_display { + compatible = "elida,kd35t133"; + iovcc-supply = <&vcc_lcd>; + vdd-supply = <&vcc_lcd>; + rotation = <270>; +}; + +&rk817 { + regulators { + vcc_wifi: LDO_REG9 { + regulator-name = "vcc_wifi"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + }; +}; + +&rk817_charger { + monitored-battery = <&battery>; +}; + +&sdio { + bus-width = <4>; + cap-sd-highspeed; + cap-sdio-irq; + disable-wp; + keep-power-in-suspend; + non-removable; + vmmc-supply = <&vcc_wifi>; + status = "okay"; + + esp8089: wifi@1 { + compatible = "esp,esp8089"; + reg = <1>; + esp,crystal-26M-en = <2>; + }; +}; + +&pinctrl { + btns { + btn_pins: btn-pins { + rockchip,pins = <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + wifi { + wifi_pwrseq_pins: wifi-pwrseq-pins { + rockchip,pins = /*<3 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>,*/ + <3 RK_PB6 RK_FUNC_GPIO &pcfg_output_high>; + }; + }; +}; diff --git a/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-powkiddy-rgb10x.dts b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-powkiddy-rgb10x.dts new file mode 100644 index 0000000000..fe5f9571d6 --- /dev/null +++ b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-powkiddy-rgb10x.dts @@ -0,0 +1,215 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2024 ROCKNIX + * Copyright (c) 2024 ArchR + */ + +/dts-v1/; +#include "rk3326-odroid-go.dtsi" +#include "retrogame_joypad_s2_f1.dtsi" +#include "rk3326-device-group-r36.dtsi" + +/ { + model = "Powkiddy RGB10X"; + compatible = "powkiddy,rk3326-rgb10x", "rockchip,rk3326"; + + archr,device_switch { + this = "rgb10x"; + }; + + aliases { + mmc1 = &sdio; + }; + + battery: battery { + compatible = "simple-battery"; + charge-full-design-microamp-hours = <2800000>; + charge-term-current-microamp = <280000>; + constant-charge-current-max-microamp = <2000000>; + constant-charge-voltage-max-microvolt = <4200000>; + factory-internal-resistance-micro-ohms = <180000>; + voltage-max-design-microvolt = <4100000>; + voltage-min-design-microvolt = <3500000>; + + ocv-capacity-celsius = <20>; + ocv-capacity-table-0 = <4046950 100>, <4001920 95>, <3967900 90>, <3919950 85>, + <3888450 80>, <3861850 75>, <3831540 70>, <3799130 65>, + <3768190 60>, <3745650 55>, <3726610 50>, <3711630 45>, + <3696720 40>, <3685660 35>, <3674950 30>, <3663050 25>, + <3649470 20>, <3635260 15>, <3616920 10>, <3592440 5>, + <3574170 0>; + }; + + gpio-keys-vol { + compatible = "gpio-keys"; + autorepeat; + pinctrl-0 = <&btn_pins_vol>; + pinctrl-names = "default"; + + button-vol-down { + gpios = <&gpio2 RK_PA1 GPIO_ACTIVE_LOW>; + label = "VOLUMEDOWN"; + linux,code = ; + }; + + button-volume-up { + gpios = <&gpio2 RK_PA0 GPIO_ACTIVE_LOW>; + label = "VOLUMEUP"; + linux,code = ; + }; + }; +}; + +&joypad { + compatible = "archr-singleadc-joypad"; + joypad-name = "retrogame_joypad_s1_f2"; /* distinct name to indicate there is 1 stick and 2 fn buttons */ + joypad-product = <0x1112>; /* 11 inherited, 1 for number of sticks, 2 for number of FN */ + status = "okay"; + + /* gpio pincontrol setup */ + pinctrl-names = "default"; + pinctrl-0 = <&btn_pins>; + + /* Analog mux define */ + io-channel-names = "amux_adc"; + io-channels = <&saradc 1>; + + /* adc mux channel count */ + /* despite there is only left stick, amux-count needs to be 4, */ + /* because amux 0 and 1 are hardcoded as RX and RY in the driver */ + amux-count = <4>; + /* adc mux select(a,b) gpio */ + amux-a-gpios = <&gpio3 RK_PB3 GPIO_ACTIVE_LOW>; + amux-b-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>; + /* adc mux enable gpio */ + amux-en-gpios = <&gpio3 RK_PB5 GPIO_ACTIVE_LOW>; + + /* + Analog Stick data tuning value(precent) + p = positive direction, n = negative direction + report value = (real_adc_data * tuning_value) / 100 + */ + abs_x-p-tuning = <200>; + abs_x-n-tuning = <200>; + + abs_y-p-tuning = <200>; + abs_y-n-tuning = <200>; + + abs_rx-p-tuning = <200>; + abs_rx-n-tuning = <200>; + + abs_ry-p-tuning = <200>; + abs_ry-n-tuning = <200>; + + /* required for RGB10X */ + invert-absx; + invert-absy; + + /* + joypad driver is poll-device driver. + poll-device is does not support wakeup-source. + */ + up { gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_LOW>; }; + down { gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_LOW>; }; + left { gpios = <&gpio1 RK_PB6 GPIO_ACTIVE_LOW>; }; + right { gpios = <&gpio1 RK_PB7 GPIO_ACTIVE_LOW>; }; + + a { gpios = <&gpio1 RK_PA2 GPIO_ACTIVE_LOW>; }; + b { gpios = <&gpio1 RK_PA5 GPIO_ACTIVE_LOW>; }; + x { gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_LOW>; }; + y { gpios = <&gpio1 RK_PA6 GPIO_ACTIVE_LOW>; }; + + tl { gpios = <&gpio2 RK_PA6 GPIO_ACTIVE_LOW>; }; + tr { gpios = <&gpio2 RK_PA7 GPIO_ACTIVE_LOW>; }; + tr2 { gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; }; + tl2 { gpios = <&gpio3 RK_PB2 GPIO_ACTIVE_LOW>; }; + + select{ gpios = <&gpio3 RK_PB1 GPIO_ACTIVE_LOW>; }; + start { gpios = <&gpio3 RK_PB4 GPIO_ACTIVE_LOW>; }; + + thumbl{ gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; }; + + /* Plus and Minus face buttons are mapped to mode and thumbr */ + mode { + gpios = <&gpio2 RK_PA4 GPIO_ACTIVE_LOW>; + label = "GPIO MINUS"; + }; + thumbr { + gpios = <&gpio2 RK_PA3 GPIO_ACTIVE_LOW>; + label = "GPIO PLUS"; + }; +}; + +&internal_display { + compatible = "powkiddy,rk2023-panel", "newvision,nv3051d"; + vdd-supply = <&vcc_lcd>; +}; + +&io_domains { + vccio1-supply = <&vccio_sd>; +}; + +/delete-node/ &pwm3; +/delete-node/ &pwm_led; + +&red_led { + gpios = <&gpio2 RK_PB5 GPIO_ACTIVE_HIGH>; +}; + +&red_led_pin { + rockchip,pins = <2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; +}; + +&rk817_charger { + monitored-battery = <&battery>; +}; + +&sdio { + cap-sd-highspeed; + card-detect-delay = <200>; + cd-gpios = <&gpio3 RK_PB6 GPIO_ACTIVE_LOW>; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + vmmc-supply = <&vcc_sd>; + vqmmc-supply = <&vccio_sd>; + status = "okay"; +}; + +&vcc_sd { + regulator-max-microvolt = <3000000>; + regulator-min-microvolt = <1800000>; +}; + +&vccio_sd { + regulator-max-microvolt = <1800000>; +}; + +&pinctrl { + btns { + btn_pins: btn-pins { + rockchip,pins = <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + btn_pins_vol: btn-pins-vol { + rockchip,pins = <2 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +}; diff --git a/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-powkiddy-rgb20s.dts b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-powkiddy-rgb20s.dts new file mode 100644 index 0000000000..93f149e62a --- /dev/null +++ b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-powkiddy-rgb20s.dts @@ -0,0 +1,375 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2019 Hardkernel Co., Ltd + * Copyright (c) 2020 Theobroma Systems Design und Consulting GmbH + * Copyright (c) 2022 Maya Matuszczyk + */ + +/dts-v1/; +#include "rk3326-odroid-go.dtsi" + +/ { + model = "Powkiddy RGB20S"; + compatible = "powkiddy,rgb20s", "rockchip,rk3326"; + + aliases { + mmc0 = &sdio; + mmc1 = &sdmmc; + }; + + gpio-keys-vol { + compatible = "gpio-keys"; + autorepeat; + pinctrl-0 = <&btn_pins_vol>; + pinctrl-names = "default"; + + button-vol-down { + gpios = <&gpio2 RK_PA1 GPIO_ACTIVE_LOW>; + label = "VOLUMEDOWN"; + linux,code = ; + }; + + button-volume-up { + gpios = <&gpio2 RK_PA0 GPIO_ACTIVE_LOW>; + label = "VOLUMEUP"; + linux,code = ; + }; + }; + + joypad: joypad { + compatible = "archr-singleadc-joypad"; + + pwms = <&pwm0 0 200000000 0>; + pwm-names = "enable"; + rumble-boost-weak = <0x0000>; + rumble-boost-strong = <0x0000>; + + joypad-name = "r36s_Gamepad"; + joypad-product = <0x1188>; + joypad-revision = <0x0188>; + joypad-vendor = <0x0001>; + + status = "okay"; + + /* gpio pincontrol setup */ + pinctrl-names = "default"; + pinctrl-0 = <&btn_pins>; + pinctrl-1 = <&pwm0_pin>; + + /* Analog mux define */ + io-channel-names = "amux_adc"; + io-channels = <&saradc 1>; + + /* adc mux channel count */ + amux-count = <4>; + /* non-default wiring */ + amux-channel-mapping = <0 1 2 3>; + /* adc mux select(a,b) gpio */ + amux-a-gpios = <&gpio3 RK_PB3 GPIO_ACTIVE_LOW>; + amux-b-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>; + /* adc mux enable gpio */ + amux-en-gpios = <&gpio3 RK_PB5 GPIO_ACTIVE_LOW>; + + /* adc calculate scale */ + button-adc-scale = <2>; + + /* adc deadzone range */ + button-adc-deadzone = <64>; + + /* + specifies fuzz value that is used to filter noise from + the event stream. + */ + button-adc-fuzz = <32>; + button-adc-flat = <32>; + + /* + Analog Stick data tuning value(precent) + p = positive direction, n = negative direction + report value = (real_adc_data * tuning_value) / 100 + */ + abs_x-p-tuning = <400>; + abs_x-n-tuning = <400>; + + abs_y-p-tuning = <400>; + abs_y-n-tuning = <400>; + + abs_rx-p-tuning = <400>; + abs_rx-n-tuning = <400>; + + abs_ry-p-tuning = <400>; + abs_ry-n-tuning = <400>; + + /* poll device interval (ms), adc read interval */ + poll-interval = <10>; + + /* required for RG351MP */ + invert-absx; + invert-absy; + + /* gpio button auto repeat set value : default disable */ + /* + autorepeat; + */ + + /* + joypad driver is poll-device driver. + poll-device is does not support wakeup-source. + */ + sw1 { + gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-UP"; + linux,code = ; // 0x220 + }; + sw2 { + gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-DOWN"; + linux,code = ; // 0x221 + }; + sw3 { + gpios = <&gpio1 RK_PB6 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-LEFT"; + linux,code = ; // 0x222 + }; + sw4 { + gpios = <&gpio1 RK_PB7 GPIO_ACTIVE_LOW>; + label = "GPIO DPAD-RIGHT"; + linux,code = ; // 0x223 + }; + sw5 { + gpios = <&gpio1 RK_PA2 GPIO_ACTIVE_LOW>; + label = "GPIO KEY BTN-A"; + linux,code = ; // 0x131 + }; + sw6 { + gpios = <&gpio1 RK_PA5 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-B"; + linux,code = ; // 0x130 + }; + sw7 { + gpios = <&gpio1 RK_PA6 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-Y"; + linux,code = ; // 0x134 + }; + sw8 { + gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_LOW>; + label = "GPIO BTN-X"; + linux,code = ; // 0x133 + }; + sw11 { + gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_THUMBL"; + linux,code = ; // 0x2c2 + }; + sw12 { + gpios = <&gpio2 RK_PA3 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_THUMBR"; + linux,code = ; // 0x2c3 + }; + + sw13 { + gpios = <&gpio2 RK_PA4 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_FN"; + linux,code = ; // 0x2c4 + }; + + sw15 { + gpios = <&gpio2 RK_PA6 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-LEFT"; + linux,code = ; // 0x02 + }; + sw16 { + gpios = <&gpio2 RK_PA7 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-RIGHT"; + linux,code = ; // 0x05 + }; + sw19 { + gpios = <&gpio3 RK_PB1 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_SELECT"; + linux,code = ; + }; + sw20 { + gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-RIGHT2"; + linux,code = ; + }; + sw21 { + gpios = <&gpio3 RK_PB2 GPIO_ACTIVE_LOW>; + label = "GPIO TOP-LEFT2"; + linux,code = ; + }; + sw22 { + gpios = <&gpio3 RK_PB4 GPIO_ACTIVE_LOW>; + label = "GPIO BTN_START"; + linux,code = ; + }; + }; + + battery: battery { + compatible = "simple-battery"; + charge-full-design-microamp-hours = <3500000>; + charge-term-current-microamp = <350000>; + constant-charge-current-max-microamp = <2000000>; + constant-charge-voltage-max-microvolt = <4200000>; + factory-internal-resistance-micro-ohms = <180000>; + voltage-max-design-microvolt = <4100000>; + voltage-min-design-microvolt = <3500000>; + + ocv-capacity-celsius = <20>; + ocv-capacity-table-0 = <4046950 100>, <4001920 95>, <3967900 90>, <3919950 85>, + <3888450 80>, <3861850 75>, <3831540 70>, <3799130 65>, + <3768190 60>, <3745650 55>, <3726610 50>, <3711630 45>, + <3696720 40>, <3685660 35>, <3674950 30>, <3663050 25>, + <3649470 20>, <3635260 15>, <3616920 10>, <3592440 5>, + <3574170 0>; + }; +}; + +/* conflicts with pwm vibration motor */ +/delete-node/ &vcc_host; + +/* Device only has 1 LED compared to Odroid Go Advance */ +/delete-node/ &gpio_led; + +&internal_display { +// compatible = "anbernic,rg351v-panel", "newvision,nv3051d"; + // compatible = "powkiddy,rk2023-panel", "newvision,nv3051d"; + compatible = "archr,generic-dsi"; + iovcc-supply = <&vcc_lcd>; + vdd-supply = <&vcc_lcd>; + panel_description = + "G size=52,70 delays=2,1,20,120,20 format=rgb888 lanes=4 flags=0xe03", + + "M clock=26400 horizontal=640,119,2,119 vertical=480,13,2,5 default=1", + "M clock=27300 horizontal=640,207,24,207 vertical=480,13,9,5", + "M clock=26400 horizontal=640,207,2,207 vertical=480,13,2,5", + "M clock=27140 horizontal=640,119,45,119 vertical=480,13,90,5", + "M clock=26450 horizontal=640,119,42,119 vertical=480,13,2,5", + "M clock=28520 horizontal=640,119,3,119 vertical=480,13,44,5", + "M clock=31440 horizontal=640,119,39,119 vertical=480,13,74,5", + "M clock=26440 horizontal=640,31,30,31 vertical=480,13,103,5", + "M clock=31970 horizontal=640,31,36,31 vertical=480,13,76,5", + // "M clock=31680 horizontal=640,31,2,31 vertical=480,13,2,5", + "M clock=42240 horizontal=640,31,2,31 vertical=480,13,2,5", + + "I seq=ff30", "I seq=ff52", "I seq=ff01", + "I seq=e300", + "I seq=400a", + "I seq=0340", "I seq=0400", "I seq=0503", + "I seq=2412", "I seq=251e", "I seq=2628", "I seq=2752", + "I seq=2857", "I seq=2901", "I seq=2adf", + "I seq=389c", "I seq=39a7", "I seq=3a53", + "I seq=4400", + "I seq=493c", + "I seq=59fe", "I seq=5c00", + "I seq=9177", "I seq=9277", + "I seq=a055", "I seq=a150", "I seq=a49c", "I seq=a702", + "I seq=a801", "I seq=a901", "I seq=aafc", "I seq=ab28", "I seq=ac06", "I seq=ad06", "I seq=ae06", "I seq=af03", + "I seq=b008", "I seq=b126", "I seq=b228", "I seq=b328", "I seq=b433", "I seq=b508", "I seq=b626", "I seq=b708", + "I seq=b826", + "I seq=ff30", "I seq=ff52", "I seq=ff02", + "I seq=b00b", "I seq=b116", "I seq=b217", "I seq=b32c", "I seq=b432", "I seq=b53b", "I seq=b629", "I seq=b740", + "I seq=b80d", "I seq=b905", "I seq=ba12", "I seq=bb10", "I seq=bc12", "I seq=bd15", "I seq=be19", "I seq=bf0e", + "I seq=c016", "I seq=c10a", + "I seq=d00c", "I seq=d117", "I seq=d214", "I seq=d32e", "I seq=d432", "I seq=d53c", "I seq=d622", "I seq=d73d", + "I seq=d80d", "I seq=d907", "I seq=da13", "I seq=db13", "I seq=dc11", "I seq=dd15", "I seq=de19", "I seq=df10", + "I seq=e017", "I seq=e10a", + "I seq=ff30", "I seq=ff52", "I seq=ff03", + "I seq=002a", "I seq=012a", "I seq=022a", "I seq=032a", "I seq=0461", "I seq=0580", "I seq=06c7", "I seq=0701", + "I seq=0882", "I seq=0983", + "I seq=302a", "I seq=312a", "I seq=322a", "I seq=332a", "I seq=3461", "I seq=35c5", "I seq=3680", "I seq=3723", + "I seq=4082", "I seq=4183", "I seq=4280", "I seq=4381", "I seq=4411", "I seq=45e6", "I seq=46e5", "I seq=4711", + "I seq=48e8", "I seq=49e7", + "I seq=5002", "I seq=5101", "I seq=5204", "I seq=5303", "I seq=5411", "I seq=55ea", "I seq=56e9", "I seq=5711", + "I seq=58ec", "I seq=59eb", + "I seq=7e02", "I seq=7f80", + "I seq=e05a", + "I seq=b100", "I seq=b40e", "I seq=b50f", "I seq=b604", "I seq=b707", + "I seq=b806", "I seq=b905", "I seq=ba0f", + "I seq=c700", + "I seq=ca0e", "I seq=cb0f", "I seq=cc04", "I seq=cd07", "I seq=ce06", "I seq=cf05", + "I seq=d00f", + "I seq=810f", "I seq=840e", "I seq=850f", "I seq=8607", "I seq=8704", + "I seq=8805", "I seq=8906", "I seq=8a00", + "I seq=970f", + "I seq=9a0e", "I seq=9b0f", "I seq=9c07", "I seq=9d04", "I seq=9e05", "I seq=9f06", + "I seq=a000", + "I seq=ff30", "I seq=ff52", "I seq=ff02", + "I seq=0101", "I seq=02da", "I seq=03ba", "I seq=04a8", "I seq=059a", "I seq=0670", "I seq=07ff", + "I seq=0891", "I seq=0990", "I seq=0aff", "I seq=0b8f", "I seq=0c60", "I seq=0d58", "I seq=0e48", "I seq=0f38", + "I seq=102b", + "I seq=ff30", "I seq=ff52", "I seq=ff00", + "I seq=3602", + "I seq=3a70", + "I seq=11 wait=200", + "I seq=29 wait=10"; +}; + +&io_domains { + vccio1-supply = <&vccio_sd>; +}; + +/delete-node/ &pwm_led; + +&pwm0 { + status = "okay"; +}; + +/delete-node/ &pwm3; + +&rk817_charger { + /* This device does not have a current sense resistor */ + rockchip,resistor-sense-micro-ohms = <0>; + monitored-battery = <&battery>; +}; + +&sdio { + cap-sd-highspeed; + card-detect-delay = <200>; + cd-gpios = <&gpio3 RK_PB6 GPIO_ACTIVE_LOW>; /*[> CD GPIO <]*/ + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + vmmc-supply = <&vcc_sd>; + vqmmc-supply = <&vccio_sd>; + status = "okay"; +}; + +&vcc_sd { + regulator-max-microvolt = <3000000>; + regulator-min-microvolt = <1800000>; +}; + +&vccio_sd { + regulator-max-microvolt = <1800000>; +}; + +&pinctrl { + btns { + btn_pins_vol: btn-pins-vol { + rockchip,pins = <2 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + btn_pins: btn-pins { + rockchip,pins = <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <2 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +}; diff --git a/projects/ArchR/devices/RK3326/linux/linux.aarch64.conf b/projects/ArchR/devices/RK3326/linux/linux.aarch64.conf new file mode 100644 index 0000000000..7eb8a757a6 --- /dev/null +++ b/projects/ArchR/devices/RK3326/linux/linux.aarch64.conf @@ -0,0 +1,6914 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/arm64 6.12.79 Kernel Configuration +# +CONFIG_CC_VERSION_TEXT="aarch64-archr-linux-gnu-gcc-14.2.0 (GCC) 14.2.0" +CONFIG_CC_IS_GCC=y +CONFIG_GCC_VERSION=140200 +CONFIG_CLANG_VERSION=0 +CONFIG_AS_IS_GNU=y +CONFIG_AS_VERSION=24400 +CONFIG_LD_IS_BFD=y +CONFIG_LD_VERSION=24400 +CONFIG_LLD_VERSION=0 +CONFIG_RUSTC_VERSION=109401 +CONFIG_RUSTC_LLVM_VERSION=210108 +CONFIG_CC_CAN_LINK=y +CONFIG_CC_CAN_LINK_STATIC=y +CONFIG_CC_HAS_ASM_GOTO_OUTPUT=y +CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT=y +CONFIG_TOOLS_SUPPORT_RELR=y +CONFIG_CC_HAS_ASM_INLINE=y +CONFIG_CC_HAS_NO_PROFILE_FN_ATTR=y +CONFIG_LD_CAN_USE_KEEP_IN_OVERLAY=y +CONFIG_RUSTC_HAS_UNNECESSARY_TRANSMUTES=y +CONFIG_PAHOLE_VERSION=0 +CONFIG_IRQ_WORK=y +CONFIG_BUILDTIME_TABLE_SORT=y +CONFIG_THREAD_INFO_IN_TASK=y + +# +# General setup +# +CONFIG_INIT_ENV_ARG_LIMIT=32 +# CONFIG_COMPILE_TEST is not set +# CONFIG_WERROR is not set +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_BUILD_SALT="" +CONFIG_DEFAULT_INIT="" +CONFIG_DEFAULT_HOSTNAME="@DEVICENAME@" +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_SYSVIPC_COMPAT=y +CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MQUEUE_SYSCTL=y +# CONFIG_WATCH_QUEUE is not set +CONFIG_CROSS_MEMORY_ATTACH=y +# CONFIG_USELIB is not set +# 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_EFFECTIVE_AFF_MASK=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_IRQ_IPI=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_IRQ_MSI_IOMMU=y +CONFIG_GENERIC_IRQ_KEXEC_CLEAR_VM_FORWARD=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_SPARSE_IRQ=y +# CONFIG_GENERIC_IRQ_DEBUGFS is not set +# end of IRQ subsystem + +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_ARCH_HAS_TICK_BROADCAST=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_HAVE_POSIX_CPU_TIMERS_TASK_WORK=y +CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y +CONFIG_CONTEXT_TRACKING=y +CONFIG_CONTEXT_TRACKING_IDLE=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 +# end of Timers subsystem + +CONFIG_BPF=y +CONFIG_HAVE_EBPF_JIT=y +CONFIG_ARCH_WANT_DEFAULT_BPF_JIT=y + +# +# BPF subsystem +# +CONFIG_BPF_SYSCALL=y +CONFIG_BPF_JIT=y +# CONFIG_BPF_JIT_ALWAYS_ON is not set +CONFIG_BPF_JIT_DEFAULT_ON=y +CONFIG_BPF_UNPRIV_DEFAULT_OFF=y +# CONFIG_BPF_PRELOAD is not set +# end of BPF subsystem + +CONFIG_PREEMPT_BUILD=y +# CONFIG_PREEMPT_NONE is not set +# CONFIG_PREEMPT_VOLUNTARY is not set +CONFIG_PREEMPT=y +# CONFIG_PREEMPT_RT is not set +# CONFIG_PREEMPT_DYNAMIC is not set + +# +# CPU/Task time and stats accounting +# +CONFIG_TICK_CPU_ACCOUNTING=y +# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set +CONFIG_IRQ_TIME_ACCOUNTING=y +CONFIG_HAVE_SCHED_AVG_IRQ=y +CONFIG_SCHED_HW_PRESSURE=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_PSI=y +# CONFIG_PSI_DEFAULT_DISABLED is not set +# end of CPU/Task time and stats accounting + +CONFIG_CPU_ISOLATION=y + +# +# RCU Subsystem +# +CONFIG_TREE_RCU=y +# CONFIG_RCU_EXPERT is not set +CONFIG_TREE_SRCU=y +CONFIG_TASKS_RCU_GENERIC=y +CONFIG_NEED_TASKS_RCU=y +CONFIG_TASKS_TRACE_RCU=y +CONFIG_RCU_STALL_COMMON=y +CONFIG_RCU_NEED_SEGCBLIST=y +# end of RCU Subsystem + +# CONFIG_IKCONFIG is not set +# CONFIG_IKHEADERS is not set +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 +# CONFIG_PRINTK_INDEX is not set +CONFIG_GENERIC_SCHED_CLOCK=y + +# +# Scheduler features +# +# CONFIG_UCLAMP_TASK is not set +# end of Scheduler features + +CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y +CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH=y +CONFIG_CC_HAS_INT128=y +CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5" +CONFIG_GCC10_NO_ARRAY_BOUNDS=y +CONFIG_CC_NO_ARRAY_BOUNDS=y +CONFIG_GCC_NO_STRINGOP_OVERFLOW=y +CONFIG_CC_NO_STRINGOP_OVERFLOW=y +CONFIG_ARCH_SUPPORTS_INT128=y +CONFIG_SLAB_OBJ_EXT=y +CONFIG_CGROUPS=y +CONFIG_PAGE_COUNTER=y +# CONFIG_CGROUP_FAVOR_DYNMODS is not set +CONFIG_MEMCG=y +# CONFIG_MEMCG_V1 is not set +CONFIG_BLK_CGROUP=y +CONFIG_CGROUP_WRITEBACK=y +CONFIG_CGROUP_SCHED=y +CONFIG_GROUP_SCHED_WEIGHT=y +CONFIG_FAIR_GROUP_SCHED=y +# CONFIG_CFS_BANDWIDTH is not set +# CONFIG_RT_GROUP_SCHED is not set +CONFIG_SCHED_MM_CID=y +CONFIG_CGROUP_PIDS=y +# CONFIG_CGROUP_RDMA is not set +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_HUGETLB=y +CONFIG_CPUSETS=y +# CONFIG_CPUSETS_V1 is not set +CONFIG_PROC_PID_CPUSET=y +CONFIG_CGROUP_DEVICE=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_PERF=y +CONFIG_CGROUP_BPF=y +# CONFIG_CGROUP_MISC is not set +# CONFIG_CGROUP_DEBUG is not set +CONFIG_SOCK_CGROUP_DATA=y +CONFIG_NAMESPACES=y +CONFIG_UTS_NS=y +CONFIG_TIME_NS=y +CONFIG_IPC_NS=y +CONFIG_USER_NS=y +CONFIG_PID_NS=y +CONFIG_NET_NS=y +# CONFIG_CHECKPOINT_RESTORE is not set +# CONFIG_SCHED_AUTOGROUP is not set +CONFIG_RELAY=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="@INITRAMFS_SOURCE@" +CONFIG_INITRAMFS_ROOT_UID=0 +CONFIG_INITRAMFS_ROOT_GID=0 +# CONFIG_RD_GZIP is not set +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_XZ is not set +CONFIG_RD_LZO=y +# CONFIG_RD_LZ4 is not set +# CONFIG_RD_ZSTD is not set +CONFIG_INITRAMFS_COMPRESSION_LZO=y +# CONFIG_INITRAMFS_COMPRESSION_NONE is not set +# CONFIG_BOOT_CONFIG is not set +CONFIG_INITRAMFS_PRESERVE_MTIME=y +CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_LD_ORPHAN_WARN=y +CONFIG_LD_ORPHAN_WARN_LEVEL="warn" +CONFIG_SYSCTL=y +CONFIG_HAVE_UID16=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_EXPERT=y +CONFIG_UID16=y +CONFIG_MULTIUSER=y +# CONFIG_SGETMASK_SYSCALL is not set +CONFIG_SYSFS_SYSCALL=y +CONFIG_FHANDLE=y +CONFIG_POSIX_TIMERS=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +# CONFIG_BASE_SMALL is not set +CONFIG_FUTEX=y +CONFIG_FUTEX_PI=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_IO_URING=y +CONFIG_ADVISE_SYSCALLS=y +CONFIG_MEMBARRIER=y +CONFIG_KCMP=y +CONFIG_RSEQ=y +# CONFIG_DEBUG_RSEQ is not set +CONFIG_CACHESTAT_SYSCALL=y +# CONFIG_PC104 is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_SELFTEST is not set +# CONFIG_KALLSYMS_ALL is not set +CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y +CONFIG_HAVE_PERF_EVENTS=y + +# +# Kernel Performance Events And Counters +# +CONFIG_PERF_EVENTS=y +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set +# end of Kernel Performance Events And Counters + +CONFIG_SYSTEM_DATA_VERIFICATION=y +# CONFIG_PROFILING is not set + +# +# Kexec and crash features +# +# CONFIG_KEXEC is not set +# CONFIG_KEXEC_FILE is not set +# end of Kexec and crash features +# end of General setup + +CONFIG_ARM64=y +CONFIG_RUSTC_SUPPORTS_ARM64=y +CONFIG_GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS=y +CONFIG_64BIT=y +CONFIG_MMU=y +CONFIG_ARM64_CONT_PTE_SHIFT=4 +CONFIG_ARM64_CONT_PMD_SHIFT=4 +CONFIG_ARCH_MMAP_RND_BITS_MIN=18 +CONFIG_ARCH_MMAP_RND_BITS_MAX=33 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16 +CONFIG_NO_IOPORT_MAP=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 +CONFIG_LOCKDEP_SUPPORT=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_SMP=y +CONFIG_KERNEL_MODE_NEON=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_PGTABLE_LEVELS=4 +CONFIG_ARCH_SUPPORTS_UPROBES=y +CONFIG_ARCH_PROC_KCORE_TEXT=y +CONFIG_BUILTIN_RETURN_ADDRESS_STRIPS_PAC=y + +# +# Platform selection +# +# CONFIG_ARCH_ACTIONS is not set +# CONFIG_ARCH_AIROHA is not set +# CONFIG_ARCH_SUNXI is not set +# CONFIG_ARCH_ALPINE is not set +# CONFIG_ARCH_APPLE is not set +# CONFIG_ARCH_BCM is not set +# CONFIG_ARCH_BERLIN is not set +# CONFIG_ARCH_BITMAIN is not set +# CONFIG_ARCH_EXYNOS is not set +# CONFIG_ARCH_SPARX5 is not set +# CONFIG_ARCH_K3 is not set +# CONFIG_ARCH_LG1K is not set +# CONFIG_ARCH_HISI is not set +# CONFIG_ARCH_KEEMBAY is not set +# CONFIG_ARCH_MEDIATEK is not set +# CONFIG_ARCH_MESON is not set +# CONFIG_ARCH_MVEBU is not set +# CONFIG_ARCH_NXP is not set +# CONFIG_ARCH_MA35 is not set +# CONFIG_ARCH_NPCM is not set +# CONFIG_ARCH_PENSANDO is not set +# CONFIG_ARCH_QCOM is not set +# CONFIG_ARCH_REALTEK is not set +# CONFIG_ARCH_RENESAS is not set +CONFIG_ARCH_ROCKCHIP=y +# CONFIG_ARCH_SEATTLE is not set +# CONFIG_ARCH_INTEL_SOCFPGA is not set +# CONFIG_ARCH_STM32 is not set +# CONFIG_ARCH_SYNQUACER is not set +# CONFIG_ARCH_TEGRA is not set +# CONFIG_ARCH_SPRD is not set +# CONFIG_ARCH_THUNDER is not set +# CONFIG_ARCH_THUNDER2 is not set +# CONFIG_ARCH_UNIPHIER is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_VISCONTI is not set +# CONFIG_ARCH_XGENE is not set +# CONFIG_ARCH_ZYNQMP is not set +# end of Platform selection + +# +# Kernel Features +# + +# +# ARM errata workarounds via the alternatives framework +# +# CONFIG_AMPERE_ERRATUM_AC03_CPU_38 is not set +# 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_1742098 is not set +# CONFIG_ARM64_ERRATUM_845719 is not set +# CONFIG_ARM64_ERRATUM_843419 is not set +CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y +# CONFIG_ARM64_ERRATUM_1024718 is not set +# CONFIG_ARM64_ERRATUM_1418040 is not set +# CONFIG_ARM64_ERRATUM_1165522 is not set +# CONFIG_ARM64_ERRATUM_1319367 is not set +# CONFIG_ARM64_ERRATUM_1530923 is not set +# CONFIG_ARM64_ERRATUM_2441007 is not set +# CONFIG_ARM64_ERRATUM_1286807 is not set +# CONFIG_ARM64_ERRATUM_1463225 is not set +# CONFIG_ARM64_ERRATUM_1542419 is not set +# CONFIG_ARM64_ERRATUM_1508412 is not set +# CONFIG_ARM64_ERRATUM_2051678 is not set +# CONFIG_ARM64_ERRATUM_2077057 is not set +# CONFIG_ARM64_ERRATUM_2658417 is not set +# CONFIG_ARM64_ERRATUM_2054223 is not set +# CONFIG_ARM64_ERRATUM_2067961 is not set +# CONFIG_ARM64_ERRATUM_2441009 is not set +# CONFIG_ARM64_ERRATUM_2645198 is not set +CONFIG_ARM64_WORKAROUND_SPECULATIVE_UNPRIV_LOAD=y +# CONFIG_ARM64_ERRATUM_2966298 is not set +CONFIG_ARM64_ERRATUM_3117295=y +CONFIG_ARM64_ERRATUM_3194386=y +# CONFIG_CAVIUM_ERRATUM_22375 is not set +# CONFIG_CAVIUM_ERRATUM_23154 is not set +# CONFIG_CAVIUM_ERRATUM_27456 is not set +# CONFIG_CAVIUM_ERRATUM_30115 is not set +# CONFIG_CAVIUM_TX2_ERRATUM_219 is not set +# CONFIG_FUJITSU_ERRATUM_010001 is not set +# CONFIG_HISILICON_ERRATUM_161600802 is not set +CONFIG_HISILICON_ERRATUM_162100801=y +# CONFIG_QCOM_FALKOR_ERRATUM_1003 is not set +# CONFIG_QCOM_FALKOR_ERRATUM_1009 is not set +# CONFIG_QCOM_QDF2400_ERRATUM_0065 is not set +# CONFIG_QCOM_FALKOR_ERRATUM_E1041 is not set +# CONFIG_NVIDIA_CARMEL_CNP_ERRATUM is not set +# CONFIG_ROCKCHIP_ERRATUM_3588001 is not set +# CONFIG_SOCIONEXT_SYNQUACER_PREITS is not set +# end of ARM errata workarounds via the alternatives framework + +CONFIG_ARM64_4K_PAGES=y +# CONFIG_ARM64_16K_PAGES is not set +# CONFIG_ARM64_64K_PAGES is not set +# CONFIG_ARM64_VA_BITS_39 is not set +CONFIG_ARM64_VA_BITS_48=y +# CONFIG_ARM64_VA_BITS_52 is not set +CONFIG_ARM64_VA_BITS=48 +CONFIG_ARM64_PA_BITS_48=y +CONFIG_ARM64_PA_BITS=48 +# CONFIG_CPU_BIG_ENDIAN is not set +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_SCHED_MC=y +# CONFIG_SCHED_CLUSTER is not set +# CONFIG_SCHED_SMT is not set +CONFIG_NR_CPUS=4 +CONFIG_HOTPLUG_CPU=y +# CONFIG_NUMA is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_250 is not set +CONFIG_HZ_300=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=300 +CONFIG_SCHED_HRTICK=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_HW_PERF_EVENTS=y +CONFIG_CC_HAVE_SHADOW_CALL_STACK=y +# CONFIG_PARAVIRT is not set +# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set +CONFIG_ARCH_SUPPORTS_KEXEC=y +CONFIG_ARCH_SUPPORTS_KEXEC_FILE=y +CONFIG_ARCH_SUPPORTS_KEXEC_SIG=y +CONFIG_ARCH_SUPPORTS_KEXEC_IMAGE_VERIFY_SIG=y +CONFIG_ARCH_DEFAULT_KEXEC_IMAGE_VERIFY_SIG=y +CONFIG_ARCH_SUPPORTS_CRASH_DUMP=y +CONFIG_ARCH_DEFAULT_CRASH_DUMP=y +CONFIG_TRANS_TABLE=y +# CONFIG_XEN is not set +CONFIG_ARCH_FORCE_MAX_ORDER=10 +CONFIG_UNMAP_KERNEL_AT_EL0=y +# CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY is not set +CONFIG_RODATA_FULL_DEFAULT_ENABLED=y +# CONFIG_ARM64_SW_TTBR0_PAN is not set +CONFIG_ARM64_TAGGED_ADDR_ABI=y +CONFIG_COMPAT=y +CONFIG_KUSER_HELPERS=y +# CONFIG_COMPAT_ALIGNMENT_FIXUPS is not set +# CONFIG_ARMV8_DEPRECATED is not set + +# +# ARMv8.1 architectural features +# +CONFIG_ARM64_HW_AFDBM=y +CONFIG_ARM64_PAN=y +CONFIG_AS_HAS_LSE_ATOMICS=y +CONFIG_ARM64_LSE_ATOMICS=y +CONFIG_ARM64_USE_LSE_ATOMICS=y +# end of ARMv8.1 architectural features + +# +# ARMv8.2 architectural features +# +CONFIG_AS_HAS_ARMV8_2=y +CONFIG_AS_HAS_SHA3=y +# CONFIG_ARM64_PMEM is not set +# CONFIG_ARM64_RAS_EXTN is not set +# CONFIG_ARM64_CNP is not set +# end of ARMv8.2 architectural features + +# +# ARMv8.3 architectural features +# +# CONFIG_ARM64_PTR_AUTH is not set +CONFIG_CC_HAS_BRANCH_PROT_PAC_RET=y +CONFIG_CC_HAS_SIGN_RETURN_ADDRESS=y +CONFIG_AS_HAS_ARMV8_3=y +CONFIG_AS_HAS_CFI_NEGATE_RA_STATE=y +CONFIG_AS_HAS_LDAPR=y +# end of ARMv8.3 architectural features + +# +# ARMv8.4 architectural features +# +# CONFIG_ARM64_AMU_EXTN is not set +CONFIG_AS_HAS_ARMV8_4=y +# CONFIG_ARM64_TLB_RANGE is not set +# end of ARMv8.4 architectural features + +# +# ARMv8.5 architectural features +# +CONFIG_AS_HAS_ARMV8_5=y +# CONFIG_ARM64_BTI is not set +CONFIG_CC_HAS_BRANCH_PROT_PAC_RET_BTI=y +# CONFIG_ARM64_E0PD is not set +CONFIG_ARM64_AS_HAS_MTE=y +# CONFIG_ARM64_MTE is not set +# end of ARMv8.5 architectural features + +# +# ARMv8.7 architectural features +# +# CONFIG_ARM64_EPAN is not set +# end of ARMv8.7 architectural features + +# +# ARMv8.9 architectural features +# +CONFIG_ARM64_POE=y +CONFIG_ARCH_PKEY_BITS=3 +# end of ARMv8.9 architectural features + +CONFIG_ARM64_SVE=y +# CONFIG_ARM64_PSEUDO_NMI is not set +CONFIG_RELOCATABLE=y +# CONFIG_RANDOMIZE_BASE is not set +CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y +CONFIG_ARM64_CONTPTE=y +# end of Kernel Features + +# +# Boot options +# +CONFIG_CMDLINE="" +# CONFIG_EFI is not set +# CONFIG_COMPRESSED_INSTALL is not set +# end of Boot options + +# +# Power management options +# +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +# CONFIG_SUSPEND_SKIP_SYNC is not set +CONFIG_HIBERNATE_CALLBACKS=y +CONFIG_HIBERNATION=y +# CONFIG_HIBERNATION_SNAPSHOT_DEV is not set +CONFIG_HIBERNATION_COMP_LZO=y +CONFIG_HIBERNATION_DEF_COMP="lzo" +CONFIG_PM_STD_PARTITION="" +CONFIG_PM_SLEEP=y +CONFIG_PM_SLEEP_SMP=y +# CONFIG_PM_AUTOSLEEP is not set +# CONFIG_PM_USERSPACE_AUTOSLEEP is not set +# CONFIG_PM_WAKELOCKS is not set +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +# CONFIG_PM_ADVANCED_DEBUG is not set +# CONFIG_PM_TEST_SUSPEND is not set +# CONFIG_PM_SLEEP_DEBUG is not set +# CONFIG_DPM_WATCHDOG is not set +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_ENERGY_MODEL=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_HIBERNATION_HEADER=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +# end of Power management options + +# +# CPU Power Management +# + +# +# CPU Idle +# +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y +# CONFIG_CPU_IDLE_GOV_TEO is not set +CONFIG_DT_IDLE_STATES=y +CONFIG_DT_IDLE_GENPD=y + +# +# ARM CPU Idle Drivers +# +CONFIG_ARM_PSCI_CPUIDLE=y +CONFIG_ARM_PSCI_CPUIDLE_DOMAIN=y +# end of ARM CPU Idle Drivers +# end of CPU Idle + +# +# CPU Frequency scaling +# +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_GOV_ATTR_SET=y +CONFIG_CPU_FREQ_GOV_COMMON=y +CONFIG_CPU_FREQ_STAT=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_SCHEDUTIL is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +# CONFIG_CPU_FREQ_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y + +# +# CPU frequency scaling drivers +# +CONFIG_CPUFREQ_DT=y +CONFIG_CPUFREQ_DT_PLATDEV=y +CONFIG_ARM_SCPI_CPUFREQ=y +# CONFIG_ARM_SCMI_CPUFREQ is not set +# end of CPU Frequency scaling +# end of CPU Power Management + +# CONFIG_VIRTUALIZATION is not set +CONFIG_CPU_MITIGATIONS=y + +# +# General architecture-dependent options +# +CONFIG_HOTPLUG_CORE_SYNC=y +CONFIG_HOTPLUG_CORE_SYNC_DEAD=y +# CONFIG_KPROBES is not set +CONFIG_JUMP_LABEL=y +# CONFIG_STATIC_KEYS_SELFTEST is not set +CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y +CONFIG_HAVE_IOREMAP_PROT=y +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE=y +CONFIG_HAVE_FUNCTION_ERROR_INJECTION=y +CONFIG_HAVE_NMI=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_ARCH_HAS_FORTIFY_SOURCE=y +CONFIG_ARCH_HAS_KEEPINITRD=y +CONFIG_ARCH_HAS_SET_MEMORY=y +CONFIG_ARCH_HAS_SET_DIRECT_MAP=y +CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y +CONFIG_ARCH_WANTS_NO_INSTR=y +CONFIG_HAVE_ASM_MODVERSIONS=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_RSEQ=y +CONFIG_HAVE_RUST=y +CONFIG_HAVE_FUNCTION_ARG_ACCESS_API=y +CONFIG_HAVE_HW_BREAKPOINT=y +CONFIG_HAVE_PERF_REGS=y +CONFIG_HAVE_PERF_USER_STACK_DUMP=y +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_HAVE_ARCH_JUMP_LABEL_RELATIVE=y +CONFIG_MMU_GATHER_TABLE_FREE=y +CONFIG_MMU_GATHER_RCU_TABLE_FREE=y +CONFIG_MMU_LAZY_TLB_REFCOUNT=y +CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y +CONFIG_ARCH_HAS_NMI_SAFE_THIS_CPU_OPS=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=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_SECCOMP=y +CONFIG_SECCOMP_FILTER=y +# CONFIG_SECCOMP_CACHE_DEBUG is not set +CONFIG_HAVE_ARCH_STACKLEAK=y +CONFIG_HAVE_STACKPROTECTOR=y +# CONFIG_STACKPROTECTOR is not set +CONFIG_ARCH_SUPPORTS_SHADOW_CALL_STACK=y +# CONFIG_SHADOW_CALL_STACK is not set +CONFIG_ARCH_SUPPORTS_LTO_CLANG=y +CONFIG_ARCH_SUPPORTS_LTO_CLANG_THIN=y +CONFIG_LTO_NONE=y +CONFIG_ARCH_SUPPORTS_CFI_CLANG=y +CONFIG_HAVE_CONTEXT_TRACKING_USER=y +CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y +CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y +CONFIG_HAVE_MOVE_PUD=y +CONFIG_HAVE_MOVE_PMD=y +CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y +CONFIG_HAVE_ARCH_HUGE_VMAP=y +CONFIG_HAVE_ARCH_HUGE_VMALLOC=y +CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y +CONFIG_ARCH_WANT_PMD_MKWRITE=y +CONFIG_HAVE_MOD_ARCH_SPECIFIC=y +CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_ARCH_WANTS_EXECMEM_LATE=y +CONFIG_HAVE_SOFTIRQ_ON_OWN_STACK=y +CONFIG_SOFTIRQ_ON_OWN_STACK=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_HAVE_PAGE_SIZE_4KB=y +CONFIG_PAGE_SIZE_4KB=y +CONFIG_PAGE_SIZE_LESS_THAN_64KB=y +CONFIG_PAGE_SIZE_LESS_THAN_256KB=y +CONFIG_PAGE_SHIFT=12 +CONFIG_ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_COMPAT_OLD_SIGACTION=y +CONFIG_COMPAT_32BIT_TIME=y +CONFIG_ARCH_SUPPORTS_RT=y +CONFIG_HAVE_ARCH_VMAP_STACK=y +CONFIG_VMAP_STACK=y +CONFIG_HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET=y +CONFIG_RANDOMIZE_KSTACK_OFFSET=y +# CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT is not set +CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y +CONFIG_STRICT_KERNEL_RWX=y +CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y +CONFIG_STRICT_MODULE_RWX=y +CONFIG_HAVE_ARCH_COMPILER_H=y +CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y +# CONFIG_LOCK_EVENT_COUNTS is not set +CONFIG_ARCH_HAS_RELR=y +CONFIG_RELR=y +CONFIG_ARCH_HAS_MEM_ENCRYPT=y +CONFIG_HAVE_PREEMPT_DYNAMIC=y +CONFIG_HAVE_PREEMPT_DYNAMIC_KEY=y +CONFIG_ARCH_WANT_LD_ORPHAN_WARN=y +CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y +CONFIG_ARCH_SUPPORTS_PAGE_TABLE_CHECK=y +CONFIG_ARCH_HAVE_TRACE_MMIO_ACCESS=y +CONFIG_ARCH_HAS_HW_PTE_YOUNG=y +CONFIG_ARCH_HAS_KERNEL_FPU_SUPPORT=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y +# end of GCOV-based kernel profiling + +CONFIG_HAVE_GCC_PLUGINS=y +# CONFIG_GCC_PLUGINS is not set +CONFIG_FUNCTION_ALIGNMENT_4B=y +CONFIG_FUNCTION_ALIGNMENT=4 +CONFIG_CC_HAS_MIN_FUNCTION_ALIGNMENT=y +CONFIG_CC_HAS_SANE_FUNCTION_ALIGNMENT=y +# end of General architecture-dependent options + +CONFIG_RT_MUTEXES=y +CONFIG_MODULES=y +# CONFIG_MODULE_DEBUG is not set +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODULE_UNLOAD_TAINT_TRACKING is not set +CONFIG_MODVERSIONS=y +CONFIG_ASM_MODVERSIONS=y +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_MODULE_SIG is not set +# CONFIG_MODULE_COMPRESS is not set +# CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS is not set +CONFIG_MODPROBE_PATH="/sbin/modprobe" +# CONFIG_TRIM_UNUSED_KSYMS is not set +CONFIG_MODULES_TREE_LOOKUP=y +CONFIG_BLOCK=y +CONFIG_BLOCK_LEGACY_AUTOLOAD=y +CONFIG_BLK_CGROUP_PUNT_BIO=y +CONFIG_BLK_DEV_BSG_COMMON=y +# CONFIG_BLK_DEV_BSGLIB is not set +# CONFIG_BLK_DEV_INTEGRITY is not set +CONFIG_BLK_DEV_WRITE_MOUNTED=y +# CONFIG_BLK_DEV_ZONED is not set +# CONFIG_BLK_DEV_THROTTLING is not set +# CONFIG_BLK_WBT is not set +# CONFIG_BLK_CGROUP_IOLATENCY is not set +# CONFIG_BLK_CGROUP_IOCOST is not set +# CONFIG_BLK_CGROUP_IOPRIO is not set +CONFIG_BLK_CGROUP_RWSTAT=y +CONFIG_BLK_ICQ=y +CONFIG_BLK_DEBUG_FS=y +# CONFIG_BLK_SED_OPAL is not set +# CONFIG_BLK_INLINE_ENCRYPTION 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_CMDLINE_PARTITION is not set +# end of Partition Types + +CONFIG_BLK_PM=y + +# +# IO Schedulers +# +CONFIG_MQ_IOSCHED_DEADLINE=y +CONFIG_MQ_IOSCHED_KYBER=y +CONFIG_IOSCHED_BFQ=y +CONFIG_BFQ_GROUP_IOSCHED=y +# end of IO Schedulers + +CONFIG_PADATA=y +CONFIG_ASN1=y +CONFIG_ARCH_INLINE_SPIN_TRYLOCK=y +CONFIG_ARCH_INLINE_SPIN_TRYLOCK_BH=y +CONFIG_ARCH_INLINE_SPIN_LOCK=y +CONFIG_ARCH_INLINE_SPIN_LOCK_BH=y +CONFIG_ARCH_INLINE_SPIN_LOCK_IRQ=y +CONFIG_ARCH_INLINE_SPIN_LOCK_IRQSAVE=y +CONFIG_ARCH_INLINE_SPIN_UNLOCK=y +CONFIG_ARCH_INLINE_SPIN_UNLOCK_BH=y +CONFIG_ARCH_INLINE_SPIN_UNLOCK_IRQ=y +CONFIG_ARCH_INLINE_SPIN_UNLOCK_IRQRESTORE=y +CONFIG_ARCH_INLINE_READ_LOCK=y +CONFIG_ARCH_INLINE_READ_LOCK_BH=y +CONFIG_ARCH_INLINE_READ_LOCK_IRQ=y +CONFIG_ARCH_INLINE_READ_LOCK_IRQSAVE=y +CONFIG_ARCH_INLINE_READ_UNLOCK=y +CONFIG_ARCH_INLINE_READ_UNLOCK_BH=y +CONFIG_ARCH_INLINE_READ_UNLOCK_IRQ=y +CONFIG_ARCH_INLINE_READ_UNLOCK_IRQRESTORE=y +CONFIG_ARCH_INLINE_WRITE_LOCK=y +CONFIG_ARCH_INLINE_WRITE_LOCK_BH=y +CONFIG_ARCH_INLINE_WRITE_LOCK_IRQ=y +CONFIG_ARCH_INLINE_WRITE_LOCK_IRQSAVE=y +CONFIG_ARCH_INLINE_WRITE_UNLOCK=y +CONFIG_ARCH_INLINE_WRITE_UNLOCK_BH=y +CONFIG_ARCH_INLINE_WRITE_UNLOCK_IRQ=y +CONFIG_ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE=y +CONFIG_INLINE_SPIN_TRYLOCK=y +CONFIG_INLINE_SPIN_TRYLOCK_BH=y +CONFIG_INLINE_SPIN_LOCK=y +CONFIG_INLINE_SPIN_LOCK_BH=y +CONFIG_INLINE_SPIN_LOCK_IRQ=y +CONFIG_INLINE_SPIN_LOCK_IRQSAVE=y +CONFIG_INLINE_SPIN_UNLOCK_BH=y +CONFIG_INLINE_SPIN_UNLOCK_IRQ=y +CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE=y +CONFIG_INLINE_READ_LOCK=y +CONFIG_INLINE_READ_LOCK_BH=y +CONFIG_INLINE_READ_LOCK_IRQ=y +CONFIG_INLINE_READ_LOCK_IRQSAVE=y +CONFIG_INLINE_READ_UNLOCK=y +CONFIG_INLINE_READ_UNLOCK_BH=y +CONFIG_INLINE_READ_UNLOCK_IRQ=y +CONFIG_INLINE_READ_UNLOCK_IRQRESTORE=y +CONFIG_INLINE_WRITE_LOCK=y +CONFIG_INLINE_WRITE_LOCK_BH=y +CONFIG_INLINE_WRITE_LOCK_IRQ=y +CONFIG_INLINE_WRITE_LOCK_IRQSAVE=y +CONFIG_INLINE_WRITE_UNLOCK=y +CONFIG_INLINE_WRITE_UNLOCK_BH=y +CONFIG_INLINE_WRITE_UNLOCK_IRQ=y +CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE=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_ARCH_USE_QUEUED_SPINLOCKS=y +CONFIG_QUEUED_SPINLOCKS=y +CONFIG_ARCH_USE_QUEUED_RWLOCKS=y +CONFIG_QUEUED_RWLOCKS=y +CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE=y +CONFIG_ARCH_HAS_SYSCALL_WRAPPER=y +CONFIG_FREEZER=y + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +CONFIG_COMPAT_BINFMT_ELF=y +CONFIG_ARCH_BINFMT_ELF_STATE=y +CONFIG_ARCH_BINFMT_ELF_EXTRA_PHDRS=y +CONFIG_ARCH_HAVE_ELF_PROT=y +CONFIG_ARCH_USE_GNU_PROPERTY=y +CONFIG_ELFCORE=y +CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y +CONFIG_BINFMT_SCRIPT=y +CONFIG_BINFMT_MISC=y +CONFIG_COREDUMP=y +# end of Executable file formats + +# +# Memory Management options +# +CONFIG_SWAP=y +# CONFIG_ZSWAP is not set +CONFIG_ZSMALLOC=m +# CONFIG_ZSMALLOC_STAT is not set +CONFIG_ZSMALLOC_CHAIN_SIZE=8 + +# +# Slab allocator options +# +CONFIG_SLUB=y +# CONFIG_SLUB_TINY is not set +CONFIG_SLAB_MERGE_DEFAULT=y +# CONFIG_SLAB_FREELIST_RANDOM is not set +# CONFIG_SLAB_FREELIST_HARDENED is not set +# CONFIG_SLAB_BUCKETS is not set +# CONFIG_SLUB_STATS is not set +CONFIG_SLUB_CPU_PARTIAL=y +# CONFIG_RANDOM_KMALLOC_CACHES is not set +# end of Slab allocator options + +# CONFIG_SHUFFLE_PAGE_ALLOCATOR is not set +# CONFIG_COMPAT_BRK is not set +CONFIG_SPARSEMEM=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_HAVE_GUP_FAST=y +CONFIG_ARCH_KEEP_MEMBLOCK=y +CONFIG_MEMORY_ISOLATION=y +CONFIG_EXCLUSIVE_SYSTEM_RAM=y +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y +# CONFIG_MEMORY_HOTPLUG is not set +CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y +CONFIG_SPLIT_PTE_PTLOCKS=y +CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y +CONFIG_SPLIT_PMD_PTLOCKS=y +CONFIG_COMPACTION=y +CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 +# CONFIG_PAGE_REPORTING is not set +CONFIG_MIGRATION=y +CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION=y +CONFIG_ARCH_ENABLE_THP_MIGRATION=y +CONFIG_CONTIG_ALLOC=y +CONFIG_PCP_BATCH_SCALE_MAX=5 +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_KSM=y +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y +CONFIG_MEMORY_FAILURE=y +# CONFIG_HWPOISON_INJECT is not set +CONFIG_ARCH_WANTS_THP_SWAP=y +CONFIG_TRANSPARENT_HUGEPAGE=y +# CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS is not set +CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y +# CONFIG_TRANSPARENT_HUGEPAGE_NEVER is not set +CONFIG_THP_SWAP=y +CONFIG_READ_ONLY_THP_FOR_FS=y +CONFIG_PGTABLE_HAS_HUGE_LEAVES=y +CONFIG_ARCH_SUPPORTS_HUGE_PFNMAP=y +CONFIG_ARCH_SUPPORTS_PMD_PFNMAP=y +CONFIG_CMA=y +# CONFIG_CMA_DEBUGFS is not set +# CONFIG_CMA_SYSFS is not set +CONFIG_CMA_AREAS=7 +CONFIG_GENERIC_EARLY_IOREMAP=y +# CONFIG_DEFERRED_STRUCT_PAGE_INIT is not set +# CONFIG_IDLE_PAGE_TRACKING is not set +CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y +CONFIG_ARCH_HAS_CURRENT_STACK_POINTER=y +CONFIG_ARCH_HAS_PTE_DEVMAP=y +CONFIG_ARCH_HAS_ZONE_DMA_SET=y +CONFIG_ZONE_DMA=y +CONFIG_ZONE_DMA32=y +CONFIG_ARCH_USES_HIGH_VMA_FLAGS=y +CONFIG_ARCH_HAS_PKEYS=y +CONFIG_VM_EVENT_COUNTERS=y +# CONFIG_PERCPU_STATS is not set +# CONFIG_GUP_TEST is not set +# CONFIG_DMAPOOL_TEST is not set +CONFIG_ARCH_HAS_PTE_SPECIAL=y +CONFIG_MEMFD_CREATE=y +CONFIG_SECRETMEM=y +# CONFIG_ANON_VMA_NAME is not set +# CONFIG_USERFAULTFD is not set +CONFIG_LRU_GEN=y +CONFIG_LRU_GEN_ENABLED=y +# CONFIG_LRU_GEN_STATS is not set +CONFIG_LRU_GEN_WALKS_MMU=y +CONFIG_ARCH_SUPPORTS_PER_VMA_LOCK=y +CONFIG_PER_VMA_LOCK=y +CONFIG_LOCK_MM_AND_FIND_VMA=y +CONFIG_EXECMEM=y + +# +# Data Access Monitoring +# +# CONFIG_DAMON is not set +# end of Data Access Monitoring +# end of Memory Management options + +CONFIG_NET=y +CONFIG_COMPAT_NETLINK_MESSAGES=y +CONFIG_NET_INGRESS=y +CONFIG_NET_EGRESS=y +CONFIG_NET_XGRESS=y +CONFIG_SKB_EXTENSIONS=y +CONFIG_NET_DEVMEM=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_DIAG is not set +CONFIG_UNIX=y +CONFIG_AF_UNIX_OOB=y +# CONFIG_UNIX_DIAG is not set +# CONFIG_TLS is not set +# CONFIG_XFRM_USER is not set +# CONFIG_NET_KEY is not set +# CONFIG_XDP_SOCKETS is not set +CONFIG_NET_HANDSHAKE=y +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 is not set +# CONFIG_IP_ROUTE_VERBOSE is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE_DEMUX is not set +CONFIG_NET_IP_TUNNEL=m +CONFIG_IP_MROUTE_COMMON=y +CONFIG_IP_MROUTE=y +# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set +# CONFIG_IP_PIMSM_V1 is not set +# CONFIG_IP_PIMSM_V2 is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_NET_IPVTI is not set +CONFIG_NET_UDP_TUNNEL=m +CONFIG_NET_FOU=m +# CONFIG_NET_FOU_IP_TUNNELS is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +CONFIG_INET_TABLE_PERTURB_ORDER=16 +CONFIG_INET_TUNNEL=m +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_INET_UDP_DIAG is not set +# CONFIG_INET_RAW_DIAG is not set +# CONFIG_INET_DIAG_DESTROY is not set +CONFIG_TCP_CONG_ADVANCED=y +CONFIG_TCP_CONG_BIC=m +CONFIG_TCP_CONG_CUBIC=y +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_HTCP=m +# CONFIG_TCP_CONG_HSTCP is not set +# CONFIG_TCP_CONG_HYBLA is not set +# CONFIG_TCP_CONG_VEGAS is not set +# CONFIG_TCP_CONG_NV is not set +# CONFIG_TCP_CONG_SCALABLE is not set +# CONFIG_TCP_CONG_LP is not set +# CONFIG_TCP_CONG_VENO is not set +# CONFIG_TCP_CONG_YEAH is not set +# CONFIG_TCP_CONG_ILLINOIS is not set +# CONFIG_TCP_CONG_DCTCP is not set +# CONFIG_TCP_CONG_CDG is not set +CONFIG_TCP_CONG_BBR=y +# CONFIG_DEFAULT_CUBIC is not set +CONFIG_DEFAULT_BBR=y +# CONFIG_DEFAULT_RENO is not set +CONFIG_DEFAULT_TCP_CONG="bbr" +# CONFIG_TCP_AO is not set +# CONFIG_TCP_MD5SIG is not set +CONFIG_IPV6=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_IPV6_MIP6 is not set +# CONFIG_IPV6_ILA is not set +# CONFIG_IPV6_VTI is not set +CONFIG_IPV6_SIT=m +# CONFIG_IPV6_SIT_6RD is not set +CONFIG_IPV6_NDISC_NODETYPE=y +# CONFIG_IPV6_TUNNEL is not set +CONFIG_IPV6_FOU=m +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +# CONFIG_IPV6_MROUTE_MULTIPLE_TABLES is not set +CONFIG_IPV6_PIMSM_V2=y +# CONFIG_IPV6_SEG6_LWTUNNEL is not set +# CONFIG_IPV6_SEG6_HMAC is not set +# CONFIG_IPV6_RPL_LWTUNNEL is not set +# CONFIG_IPV6_IOAM6_LWTUNNEL is not set +# CONFIG_NETLABEL is not set +# CONFIG_MPTCP 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_ADVANCED=y +# CONFIG_BRIDGE_NETFILTER is not set + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_INGRESS=y +CONFIG_NETFILTER_EGRESS=y +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_FAMILY_BRIDGE=y +CONFIG_NETFILTER_BPF_LINK=y +# CONFIG_NETFILTER_NETLINK_HOOK is not set +# CONFIG_NETFILTER_NETLINK_ACCT is not set +# CONFIG_NETFILTER_NETLINK_QUEUE is not set +# CONFIG_NETFILTER_NETLINK_LOG is not set +# CONFIG_NETFILTER_NETLINK_OSF is not set +CONFIG_NF_CONNTRACK=y +CONFIG_NF_LOG_SYSLOG=m +# CONFIG_NF_CONNTRACK_MARK is not set +# CONFIG_NF_CONNTRACK_ZONES is not set +CONFIG_NF_CONNTRACK_PROCFS=y +CONFIG_NF_CONNTRACK_EVENTS=y +# CONFIG_NF_CONNTRACK_TIMEOUT is not set +# CONFIG_NF_CONNTRACK_TIMESTAMP is not set +# CONFIG_NF_CONNTRACK_LABELS is not set +CONFIG_NF_CT_PROTO_DCCP=y +CONFIG_NF_CT_PROTO_SCTP=y +CONFIG_NF_CT_PROTO_UDPLITE=y +# CONFIG_NF_CONNTRACK_AMANDA is not set +# CONFIG_NF_CONNTRACK_FTP is not set +# CONFIG_NF_CONNTRACK_H323 is not set +# CONFIG_NF_CONNTRACK_IRC is not set +# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set +# CONFIG_NF_CONNTRACK_SNMP is not set +# CONFIG_NF_CONNTRACK_PPTP is not set +# CONFIG_NF_CONNTRACK_SANE is not set +# CONFIG_NF_CONNTRACK_SIP is not set +# CONFIG_NF_CONNTRACK_TFTP is not set +# CONFIG_NF_CT_NETLINK is not set +CONFIG_NF_NAT=y +CONFIG_NF_NAT_REDIRECT=y +CONFIG_NF_NAT_MASQUERADE=y +CONFIG_NF_TABLES=m +CONFIG_NF_TABLES_INET=y +# CONFIG_NF_TABLES_NETDEV is not set +# CONFIG_NFT_NUMGEN is not set +# CONFIG_NFT_CT is not set +# CONFIG_NFT_CONNLIMIT is not set +# CONFIG_NFT_LOG is not set +# CONFIG_NFT_LIMIT is not set +CONFIG_NFT_MASQ=m +# CONFIG_NFT_REDIR is not set +CONFIG_NFT_NAT=m +# CONFIG_NFT_TUNNEL is not set +# CONFIG_NFT_QUOTA is not set +# CONFIG_NFT_REJECT is not set +# CONFIG_NFT_COMPAT is not set +# CONFIG_NFT_HASH is not set +# CONFIG_NFT_SOCKET is not set +# CONFIG_NFT_OSF is not set +# CONFIG_NFT_TPROXY is not set +# CONFIG_NFT_SYNPROXY is not set +# CONFIG_NF_FLOW_TABLE is not set +CONFIG_NETFILTER_XTABLES=y +CONFIG_NETFILTER_XTABLES_COMPAT=y + +# +# Xtables combined modules +# +# CONFIG_NETFILTER_XT_MARK is not set +# CONFIG_NETFILTER_XT_CONNMARK is not set + +# +# Xtables targets +# +CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m +# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set +# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set +# CONFIG_NETFILTER_XT_TARGET_DSCP is not set +# CONFIG_NETFILTER_XT_TARGET_HL is not set +# CONFIG_NETFILTER_XT_TARGET_HMARK is not set +# CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set +# CONFIG_NETFILTER_XT_TARGET_LED is not set +CONFIG_NETFILTER_XT_TARGET_LOG=m +# CONFIG_NETFILTER_XT_TARGET_MARK is not set +CONFIG_NETFILTER_XT_NAT=y +# CONFIG_NETFILTER_XT_TARGET_NETMAP is not set +# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set +# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set +# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set +CONFIG_NETFILTER_XT_TARGET_REDIRECT=m +CONFIG_NETFILTER_XT_TARGET_MASQUERADE=y +# CONFIG_NETFILTER_XT_TARGET_TEE is not set +# CONFIG_NETFILTER_XT_TARGET_TPROXY is not set +# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set +# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set + +# +# Xtables matches +# +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m +# CONFIG_NETFILTER_XT_MATCH_BPF is not set +# CONFIG_NETFILTER_XT_MATCH_CGROUP is not set +# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set +# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set +# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set +# CONFIG_NETFILTER_XT_MATCH_CONNLABEL is not set +# CONFIG_NETFILTER_XT_MATCH_CONNLIMIT is not set +# CONFIG_NETFILTER_XT_MATCH_CONNMARK is not set +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +# CONFIG_NETFILTER_XT_MATCH_CPU is not set +# CONFIG_NETFILTER_XT_MATCH_DCCP is not set +# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set +# CONFIG_NETFILTER_XT_MATCH_DSCP is not set +# CONFIG_NETFILTER_XT_MATCH_ECN is not set +# CONFIG_NETFILTER_XT_MATCH_ESP is not set +# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set +# CONFIG_NETFILTER_XT_MATCH_HELPER is not set +# CONFIG_NETFILTER_XT_MATCH_HL is not set +# CONFIG_NETFILTER_XT_MATCH_IPCOMP is not set +# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set +# CONFIG_NETFILTER_XT_MATCH_L2TP is not set +# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set +# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set +# CONFIG_NETFILTER_XT_MATCH_MAC is not set +# CONFIG_NETFILTER_XT_MATCH_MARK is not set +# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set +# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set +# CONFIG_NETFILTER_XT_MATCH_OSF is not set +# CONFIG_NETFILTER_XT_MATCH_OWNER is not set +# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set +# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set +# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set +# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set +# CONFIG_NETFILTER_XT_MATCH_REALM is not set +# CONFIG_NETFILTER_XT_MATCH_RECENT is not set +# CONFIG_NETFILTER_XT_MATCH_SCTP is not set +# CONFIG_NETFILTER_XT_MATCH_SOCKET is not set +# CONFIG_NETFILTER_XT_MATCH_STATE is not set +# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set +# CONFIG_NETFILTER_XT_MATCH_STRING is not set +# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set +# CONFIG_NETFILTER_XT_MATCH_TIME is not set +# CONFIG_NETFILTER_XT_MATCH_U32 is not set +# end of Core Netfilter Configuration + +# CONFIG_IP_SET is not set +# CONFIG_IP_VS is not set + +# +# IP: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV4=y +CONFIG_IP_NF_IPTABLES_LEGACY=y +# CONFIG_NF_SOCKET_IPV4 is not set +# CONFIG_NF_TPROXY_IPV4 is not set +CONFIG_NF_TABLES_IPV4=y +# CONFIG_NFT_DUP_IPV4 is not set +# CONFIG_NFT_FIB_IPV4 is not set +# CONFIG_NF_TABLES_ARP is not set +# CONFIG_NF_DUP_IPV4 is not set +# CONFIG_NF_LOG_ARP is not set +CONFIG_NF_LOG_IPV4=m +CONFIG_NF_REJECT_IPV4=y +CONFIG_IP_NF_IPTABLES=y +# CONFIG_IP_NF_MATCH_AH is not set +# CONFIG_IP_NF_MATCH_ECN is not set +# CONFIG_IP_NF_MATCH_RPFILTER is not set +# CONFIG_IP_NF_MATCH_TTL is not set +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +# CONFIG_IP_NF_TARGET_SYNPROXY is not set +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +# CONFIG_IP_NF_TARGET_NETMAP is not set +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_MANGLE=y +# CONFIG_IP_NF_TARGET_ECN is not set +# CONFIG_IP_NF_TARGET_TTL is not set +# CONFIG_IP_NF_RAW is not set +# CONFIG_IP_NF_SECURITY is not set +# CONFIG_IP_NF_ARPFILTER is not set +# end of IP: Netfilter Configuration + +# +# IPv6: Netfilter Configuration +# +CONFIG_IP6_NF_IPTABLES_LEGACY=m +# CONFIG_NF_SOCKET_IPV6 is not set +# CONFIG_NF_TPROXY_IPV6 is not set +CONFIG_NF_TABLES_IPV6=y +# CONFIG_NFT_DUP_IPV6 is not set +# CONFIG_NFT_FIB_IPV6 is not set +# CONFIG_NF_DUP_IPV6 is not set +CONFIG_NF_REJECT_IPV6=m +CONFIG_NF_LOG_IPV6=m +CONFIG_IP6_NF_IPTABLES=m +# CONFIG_IP6_NF_MATCH_AH is not set +# CONFIG_IP6_NF_MATCH_EUI64 is not set +# CONFIG_IP6_NF_MATCH_FRAG is not set +# CONFIG_IP6_NF_MATCH_OPTS is not set +# CONFIG_IP6_NF_MATCH_HL is not set +# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set +# CONFIG_IP6_NF_MATCH_MH is not set +# CONFIG_IP6_NF_MATCH_RPFILTER is not set +# CONFIG_IP6_NF_MATCH_RT is not set +# CONFIG_IP6_NF_MATCH_SRH is not set +# CONFIG_IP6_NF_TARGET_HL is not set +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_REJECT=m +# CONFIG_IP6_NF_TARGET_SYNPROXY is not set +CONFIG_IP6_NF_MANGLE=m +# CONFIG_IP6_NF_RAW is not set +# CONFIG_IP6_NF_SECURITY is not set +CONFIG_IP6_NF_NAT=m +CONFIG_IP6_NF_TARGET_MASQUERADE=m +# CONFIG_IP6_NF_TARGET_NPT is not set +# end of IPv6: Netfilter Configuration + +CONFIG_NF_DEFRAG_IPV6=y +# CONFIG_NF_TABLES_BRIDGE is not set +# CONFIG_NF_CONNTRACK_BRIDGE is not set +# CONFIG_BRIDGE_NF_EBTABLES is not set +# CONFIG_IP_DCCP is not set +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_OBJCNT is not set +CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5=y +# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_SHA1 is not set +# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_NONE is not set +CONFIG_SCTP_COOKIE_HMAC_MD5=y +# CONFIG_SCTP_COOKIE_HMAC_SHA1 is not set +CONFIG_INET_SCTP_DIAG=m +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_L2TP is not set +CONFIG_STP=m +# CONFIG_BRIDGE is not set +CONFIG_BRIDGE_IGMP_SNOOPING=y +# CONFIG_BRIDGE_VLAN_FILTERING is not set +# CONFIG_BRIDGE_MRP is not set +# CONFIG_BRIDGE_CFM is not set +# CONFIG_NET_DSA is not set +CONFIG_VLAN_8021Q=m +# CONFIG_VLAN_8021Q_GVRP is not set +# CONFIG_VLAN_8021Q_MVRP is not set +CONFIG_LLC=m +# CONFIG_LLC2 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_HTB is not set +# 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_CBS is not set +# CONFIG_NET_SCH_ETF is not set +# CONFIG_NET_SCH_TAPRIO is not set +# CONFIG_NET_SCH_GRED 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_SKBPRIO is not set +# CONFIG_NET_SCH_CHOKE is not set +# CONFIG_NET_SCH_QFQ is not set +# CONFIG_NET_SCH_CODEL is not set +CONFIG_NET_SCH_FQ_CODEL=y +# CONFIG_NET_SCH_CAKE is not set +# 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 +# CONFIG_NET_SCH_ETS is not set +CONFIG_NET_SCH_DEFAULT=y +CONFIG_DEFAULT_FQ_CODEL=y +# CONFIG_DEFAULT_PFIFO_FAST is not set +CONFIG_DEFAULT_NET_SCH="fq_codel" + +# +# Classification +# +# CONFIG_NET_CLS_BASIC is not set +# CONFIG_NET_CLS_ROUTE4 is not set +# CONFIG_NET_CLS_FW is not set +# CONFIG_NET_CLS_U32 is not set +# CONFIG_NET_CLS_FLOW is not set +# CONFIG_NET_CLS_CGROUP is not set +# CONFIG_NET_CLS_BPF is not set +# CONFIG_NET_CLS_FLOWER is not set +# CONFIG_NET_CLS_MATCHALL is not set +# CONFIG_NET_EMATCH is not set +# CONFIG_NET_CLS_ACT 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 is not set +# CONFIG_VSOCKETS is not set +# CONFIG_NETLINK_DIAG is not set +# CONFIG_MPLS is not set +# CONFIG_NET_NSH is not set +# CONFIG_HSR is not set +# CONFIG_NET_SWITCHDEV is not set +# CONFIG_NET_L3_MASTER_DEV is not set +# CONFIG_QRTR is not set +# CONFIG_NET_NCSI is not set +CONFIG_PCPU_DEV_REFCNT=y +CONFIG_MAX_SKB_FRAGS=17 +CONFIG_RPS=y +CONFIG_RFS_ACCEL=y +CONFIG_SOCK_RX_QUEUE_MAPPING=y +CONFIG_XPS=y +# CONFIG_CGROUP_NET_PRIO is not set +# CONFIG_CGROUP_NET_CLASSID is not set +CONFIG_NET_RX_BUSY_POLL=y +CONFIG_BQL=y +# CONFIG_BPF_STREAM_PARSER is not set +CONFIG_NET_FLOW_LIMIT=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# end of Network testing +# end of Networking options + +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +CONFIG_BT=m +CONFIG_BT_BREDR=y +# CONFIG_BT_RFCOMM is not set +# CONFIG_BT_BNEP is not set +CONFIG_BT_HIDP=m +# CONFIG_BT_LE is not set +CONFIG_BT_LEDS=y +# CONFIG_BT_MSFTEXT is not set +# CONFIG_BT_AOSPEXT is not set +# CONFIG_BT_DEBUGFS is not set +# CONFIG_BT_SELFTEST is not set + +# +# Bluetooth device drivers +# +CONFIG_BT_INTEL=m +CONFIG_BT_BCM=m +CONFIG_BT_RTL=m +CONFIG_BT_HCIBTUSB=m +# CONFIG_BT_HCIBTUSB_AUTOSUSPEND is not set +CONFIG_BT_HCIBTUSB_POLL_SYNC=y +CONFIG_BT_HCIBTUSB_BCM=y +# CONFIG_BT_HCIBTUSB_MTK is not set +CONFIG_BT_HCIBTUSB_RTL=y +# CONFIG_BT_HCIBTSDIO is not set +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_SERDEV=y +CONFIG_BT_HCIUART_H4=y +# CONFIG_BT_HCIUART_NOKIA is not set +# CONFIG_BT_HCIUART_BCSP is not set +# CONFIG_BT_HCIUART_ATH3K is not set +CONFIG_BT_HCIUART_LL=y +CONFIG_BT_HCIUART_3WIRE=y +# CONFIG_BT_HCIUART_INTEL is not set +CONFIG_BT_HCIUART_BCM=y +CONFIG_BT_HCIUART_RTL=y +# CONFIG_BT_HCIUART_QCA is not set +# CONFIG_BT_HCIUART_AG6XX is not set +# CONFIG_BT_HCIUART_MRVL is not set +# CONFIG_BT_HCIUART_AML is not set +# CONFIG_BT_HCIBCM203X is not set +# CONFIG_BT_HCIBPA10X is not set +# CONFIG_BT_HCIBFUSB is not set +# CONFIG_BT_HCIVHCI is not set +# CONFIG_BT_MRVL is not set +# CONFIG_BT_ATH3K is not set +# CONFIG_BT_MTKSDIO is not set +# CONFIG_BT_MTKUART is not set +# CONFIG_BT_NXPUART is not set +# end of Bluetooth device drivers + +# CONFIG_AF_RXRPC is not set +# CONFIG_AF_KCM is not set +# CONFIG_MCTP is not set +CONFIG_FIB_RULES=y +CONFIG_WIRELESS=y +CONFIG_WEXT_CORE=y +CONFIG_WEXT_PROC=y +CONFIG_CFG80211=y +# CONFIG_NL80211_TESTMODE is not set +# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set +# CONFIG_CFG80211_CERTIFICATION_ONUS is not set +CONFIG_CFG80211_REQUIRE_SIGNED_REGDB=y +CONFIG_CFG80211_USE_KERNEL_REGDB_KEYS=y +CONFIG_CFG80211_DEFAULT_PS=y +# CONFIG_CFG80211_DEBUGFS is not set +CONFIG_CFG80211_CRDA_SUPPORT=y +CONFIG_CFG80211_WEXT=y +CONFIG_LIB80211=m +# CONFIG_LIB80211_DEBUG is not set +CONFIG_MAC80211=y +CONFIG_MAC80211_HAS_RC=y +CONFIG_MAC80211_RC_MINSTREL=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_DEBUG_MENU is not set +CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 +CONFIG_RFKILL=y +CONFIG_RFKILL_LEDS=y +CONFIG_RFKILL_INPUT=y +CONFIG_RFKILL_GPIO=y +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set +# CONFIG_NFC is not set +# CONFIG_PSAMPLE is not set +# CONFIG_NET_IFE is not set +# CONFIG_LWTUNNEL is not set +CONFIG_DST_CACHE=y +CONFIG_GRO_CELLS=y +CONFIG_NET_SELFTESTS=y +CONFIG_NET_SOCK_MSG=y +CONFIG_PAGE_POOL=y +# CONFIG_PAGE_POOL_STATS is not set +CONFIG_FAILOVER=y +CONFIG_ETHTOOL_NETLINK=y + +# +# Device Drivers +# +CONFIG_ARM_AMBA=y +CONFIG_HAVE_PCI=y +CONFIG_GENERIC_PCI_IOMAP=y +# CONFIG_PCI is not set +# CONFIG_PCCARD is not set + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER=y +CONFIG_UEVENT_HELPER_PATH="" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +# CONFIG_DEVTMPFS_SAFE is not set +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y + +# +# Firmware loader +# +CONFIG_FW_LOADER=y +CONFIG_FW_LOADER_DEBUG=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_FW_LOADER_USER_HELPER is not set +# CONFIG_FW_LOADER_COMPRESS is not set +CONFIG_FW_CACHE=y +# CONFIG_FW_UPLOAD is not set +# end of Firmware loader + +CONFIG_WANT_DEV_COREDUMP=y +CONFIG_ALLOW_DEV_COREDUMP=y +CONFIG_DEV_COREDUMP=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set +# CONFIG_TEST_ASYNC_DRIVER_PROBE is not set +CONFIG_GENERIC_CPU_DEVICES=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_CPU_VULNERABILITIES=y +CONFIG_SOC_BUS=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_DMA_FENCE_TRACE is not set +CONFIG_GENERIC_ARCH_TOPOLOGY=y +# CONFIG_FW_DEVLINK_SYNC_STATE_TIMEOUT is not set +# end of Generic Driver Options + +# +# Bus devices +# +# CONFIG_MOXTET is not set +# CONFIG_VEXPRESS_CONFIG is not set +# CONFIG_MHI_BUS is not set +# CONFIG_MHI_BUS_EP is not set +# end of Bus devices + +# +# Cache Drivers +# +# end of Cache Drivers + +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y + +# +# Firmware Drivers +# + +# +# ARM System Control and Management Interface Protocol +# +CONFIG_ARM_SCMI_PROTOCOL=m +# CONFIG_ARM_SCMI_RAW_MODE_SUPPORT is not set +# CONFIG_ARM_SCMI_DEBUG_COUNTERS is not set + +# +# SCMI Transport Drivers +# +CONFIG_ARM_SCMI_HAVE_TRANSPORT=y +CONFIG_ARM_SCMI_HAVE_SHMEM=y +CONFIG_ARM_SCMI_HAVE_MSG=y +CONFIG_ARM_SCMI_TRANSPORT_MAILBOX=m +CONFIG_ARM_SCMI_TRANSPORT_SMC=m +# CONFIG_ARM_SCMI_TRANSPORT_SMC_ATOMIC_ENABLE is not set +CONFIG_ARM_SCMI_TRANSPORT_OPTEE=m +# end of SCMI Transport Drivers + +# +# ARM SCMI NXP i.MX Vendor Protocols +# +# CONFIG_IMX_SCMI_BBM_EXT is not set +# end of ARM SCMI NXP i.MX Vendor Protocols + +# CONFIG_ARM_SCMI_POWER_CONTROL is not set +# end of ARM System Control and Management Interface Protocol + +CONFIG_ARM_SCPI_PROTOCOL=y +# CONFIG_ARM_SDE_INTERFACE is not set +# CONFIG_FIRMWARE_MEMMAP is not set +# CONFIG_ARM_FFA_TRANSPORT is not set +# CONFIG_GOOGLE_FIRMWARE is not set +CONFIG_ARM_PSCI_FW=y +# CONFIG_ARM_PSCI_CHECKER is not set + +# +# Qualcomm firmware drivers +# +# end of Qualcomm firmware drivers + +CONFIG_HAVE_ARM_SMCCC=y +CONFIG_HAVE_ARM_SMCCC_DISCOVERY=y +CONFIG_ARM_SMCCC_SOC_ID=y + +# +# Tegra firmware driver +# +# end of Tegra firmware driver +# end of Firmware Drivers + +# CONFIG_GNSS is not set +CONFIG_MTD=y +# CONFIG_MTD_TESTS is not set + +# +# Partition parsers +# +# CONFIG_MTD_CMDLINE_PARTS is not set +CONFIG_MTD_OF_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +# end of Partition parsers + +# +# User Modules And Translation Layers +# +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y + +# +# Note that in some cases UBI block is preferred. See MTD_UBI_BLOCK. +# +# 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_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# end of RAM/ROM/Flash chip drivers + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PLATRAM is not set +# end of Mapping drivers for chip access + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_MCHP23K256 is not set +# CONFIG_MTD_MCHP48L640 is not set +# 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 +# end of Self-contained MTD device drivers + +# +# NAND +# +# CONFIG_MTD_ONENAND is not set +# CONFIG_MTD_RAW_NAND is not set +# CONFIG_MTD_SPI_NAND is not set + +# +# ECC engine support +# +# CONFIG_MTD_NAND_ECC_SW_HAMMING is not set +# CONFIG_MTD_NAND_ECC_SW_BCH is not set +# CONFIG_MTD_NAND_ECC_MXIC is not set +# end of ECC engine support +# end of NAND + +# +# LPDDR & LPDDR2 PCM memory drivers +# +# CONFIG_MTD_LPDDR is not set +# end of LPDDR & LPDDR2 PCM memory drivers + +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y +# CONFIG_MTD_SPI_NOR_SWP_DISABLE is not set +CONFIG_MTD_SPI_NOR_SWP_DISABLE_ON_VOLATILE=y +# CONFIG_MTD_SPI_NOR_SWP_KEEP is not set +# CONFIG_MTD_UBI is not set +# CONFIG_MTD_HYPERBUS 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_KOBJ=y +CONFIG_OF_DYNAMIC=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_IRQ=y +CONFIG_OF_RESERVED_MEM=y +CONFIG_OF_RESOLVE=y +CONFIG_OF_OVERLAY=y +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_NULL_BLK is not set +CONFIG_ZRAM=m +CONFIG_ZRAM_BACKEND_LZ4=y +CONFIG_ZRAM_BACKEND_LZ4HC=y +CONFIG_ZRAM_BACKEND_ZSTD=y +# CONFIG_ZRAM_BACKEND_DEFLATE is not set +# CONFIG_ZRAM_BACKEND_842 is not set +CONFIG_ZRAM_BACKEND_LZO=y +CONFIG_ZRAM_DEF_COMP_LZORLE=y +# CONFIG_ZRAM_DEF_COMP_LZO is not set +# CONFIG_ZRAM_DEF_COMP_LZ4 is not set +# CONFIG_ZRAM_DEF_COMP_LZ4HC is not set +# CONFIG_ZRAM_DEF_COMP_ZSTD is not set +CONFIG_ZRAM_DEF_COMP="lzo-rle" +CONFIG_ZRAM_WRITEBACK=y +# CONFIG_ZRAM_TRACK_ENTRY_ACTIME is not set +# CONFIG_ZRAM_MEMORY_TRACKING is not set +CONFIG_ZRAM_MULTI_COMP=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 +# CONFIG_BLK_DEV_DRBD is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_BLK_DEV_RBD is not set +# CONFIG_BLK_DEV_UBLK is not set + +# +# NVME Support +# +# CONFIG_NVME_FC is not set +# CONFIG_NVME_TCP is not set +# CONFIG_NVME_TARGET is not set +# end of NVME Support + +# +# Misc devices +# +# CONFIG_AD525X_DPOT is not set +# CONFIG_DUMMY_IRQ is not set +# CONFIG_RPMB is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_HI6421V600_IRQ 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_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_LATTICE_ECP3_CONFIG is not set +# CONFIG_SRAM is not set +# CONFIG_XILINX_SDFEC is not set +# CONFIG_HISI_HIKEY_USB is not set +# CONFIG_OPEN_DICE is not set +CONFIG_NTSYNC=y +# CONFIG_VCPU_STALL_DETECTOR is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +CONFIG_EEPROM_AT25=m +# CONFIG_EEPROM_MAX6875 is not set +CONFIG_EEPROM_93CX6=m +# CONFIG_EEPROM_93XX46 is not set +# CONFIG_EEPROM_IDT_89HPESX is not set +# CONFIG_EEPROM_EE1004 is not set +# end of EEPROM support + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set +# end of Texas Instruments shared transport line discipline + +# CONFIG_SENSORS_LIS3_SPI is not set +# CONFIG_SENSORS_LIS3_I2C is not set +# CONFIG_ALTERA_STAPL is not set +# CONFIG_ECHO is not set +# CONFIG_MISC_RTSX_USB is not set +# CONFIG_UACCE is not set +# CONFIG_PVPANIC is not set +# end of Misc devices + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI_COMMON=y +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_PROC_FS is not set + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +CONFIG_BLK_DEV_BSG=y +# CONFIG_CHR_DEV_SCH is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# 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 +# end of SCSI Transports + +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_ISCSI_BOOT_SYSFS is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_DH is not set +# end of SCSI device support + +# 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_WIREGUARD=m +# CONFIG_WIREGUARD_DEBUG is not set +# CONFIG_EQUALIZER 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_BAREUDP is not set +# CONFIG_GTP is not set +# CONFIG_PFCP is not set +# CONFIG_AMT is not set +# CONFIG_MACSEC is not set +CONFIG_NETCONSOLE=m +# CONFIG_NETCONSOLE_DYNAMIC is not set +# CONFIG_NETCONSOLE_EXTENDED_LOG 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 +# CONFIG_NETKIT is not set +# CONFIG_ETHERNET is not set +CONFIG_PHYLINK=m +CONFIG_PHYLIB=y +CONFIG_SWPHY=y +# CONFIG_LED_TRIGGER_PHY is not set +CONFIG_PHYLIB_LEDS=y +CONFIG_FIXED_PHY=y +# CONFIG_SFP is not set + +# +# MII PHY device drivers +# +# CONFIG_AIR_EN8811H_PHY is not set +# CONFIG_AMD_PHY is not set +# CONFIG_ADIN_PHY is not set +# CONFIG_ADIN1100_PHY is not set +# CONFIG_AQUANTIA_PHY is not set +CONFIG_AX88796B_PHY=m +# CONFIG_BROADCOM_PHY is not set +# CONFIG_BCM54140_PHY is not set +# CONFIG_BCM7XXX_PHY is not set +# CONFIG_BCM84881_PHY is not set +# CONFIG_BCM87XX_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_CORTINA_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_INTEL_XWAY_PHY is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MARVELL_PHY is not set +# CONFIG_MARVELL_10G_PHY is not set +# CONFIG_MARVELL_88Q2XXX_PHY is not set +# CONFIG_MARVELL_88X2222_PHY is not set +# CONFIG_MAXLINEAR_GPHY is not set +# CONFIG_MEDIATEK_GE_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_MICROCHIP_T1S_PHY is not set +CONFIG_MICROCHIP_PHY=m +# CONFIG_MICROCHIP_T1_PHY is not set +# CONFIG_MICROSEMI_PHY is not set +# CONFIG_MOTORCOMM_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_NXP_CBTX_PHY is not set +# CONFIG_NXP_C45_TJA11XX_PHY is not set +# CONFIG_NXP_TJA11XX_PHY is not set +# CONFIG_NCN26000_PHY is not set +# CONFIG_AT803X_PHY is not set +# CONFIG_QCA83XX_PHY is not set +# CONFIG_QCA808X_PHY is not set +# CONFIG_QCA807X_PHY is not set +# CONFIG_QSEMI_PHY is not set +CONFIG_REALTEK_PHY=y +# CONFIG_RENESAS_PHY is not set +CONFIG_ROCKCHIP_PHY=y +CONFIG_SMSC_PHY=m +# CONFIG_STE10XP is not set +# CONFIG_TERANETICS_PHY is not set +# CONFIG_DP83822_PHY is not set +# CONFIG_DP83TC811_PHY is not set +# CONFIG_DP83848_PHY is not set +# CONFIG_DP83867_PHY is not set +# CONFIG_DP83869_PHY is not set +# CONFIG_DP83TD510_PHY is not set +# CONFIG_DP83TG720_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_XILINX_GMII2RGMII is not set +# CONFIG_MICREL_KS8995MA is not set +# CONFIG_PSE_CONTROLLER is not set +CONFIG_MDIO_DEVICE=y +CONFIG_MDIO_BUS=y +CONFIG_FWNODE_MDIO=y +CONFIG_OF_MDIO=y +CONFIG_MDIO_DEVRES=y +CONFIG_MDIO_BITBANG=y +# CONFIG_MDIO_BCM_UNIMAC is not set +CONFIG_MDIO_GPIO=y +# CONFIG_MDIO_HISI_FEMAC is not set +# CONFIG_MDIO_MVUSB is not set +# CONFIG_MDIO_MSCC_MIIM is not set +# CONFIG_MDIO_OCTEON is not set +# CONFIG_MDIO_IPQ4019 is not set +# CONFIG_MDIO_IPQ8064 is not set + +# +# MDIO Multiplexers +# +CONFIG_MDIO_BUS_MUX=y +# CONFIG_MDIO_BUS_MUX_GPIO is not set +CONFIG_MDIO_BUS_MUX_MULTIPLEXER=y +CONFIG_MDIO_BUS_MUX_MMIOREG=y + +# +# PCS device drivers +# +# CONFIG_PCS_XPCS is not set +# end of PCS device drivers + +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +CONFIG_USB_NET_DRIVERS=m +# 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_USB_NET_AQC111 is not set +CONFIG_USB_RTL8153_ECM=m +CONFIG_WLAN=y +# CONFIG_WLAN_VENDOR_ADMTEK is not set +CONFIG_ATH_COMMON=m +CONFIG_WLAN_VENDOR_ATH=y +# 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_DYNACK is not set +# CONFIG_ATH9K_WOW is not set +CONFIG_ATH9K_RFKILL=y +CONFIG_ATH9K_CHANNEL_CONTEXT=y +CONFIG_ATH9K_PCOEM=y +CONFIG_ATH9K_HTC=m +# CONFIG_ATH9K_HTC_DEBUGFS is not set +CONFIG_ATH9K_HWRNG=y +CONFIG_CARL9170=m +CONFIG_CARL9170_LEDS=y +CONFIG_CARL9170_WPC=y +CONFIG_CARL9170_HWRNG=y +CONFIG_ATH6KL=m +# CONFIG_ATH6KL_SDIO is not set +CONFIG_ATH6KL_USB=m +# CONFIG_ATH6KL_DEBUG is not set +CONFIG_AR5523=m +CONFIG_ATH10K=m +CONFIG_ATH10K_CE=y +# CONFIG_ATH10K_SDIO is not set +CONFIG_ATH10K_USB=m +# CONFIG_ATH10K_DEBUG is not set +# CONFIG_ATH10K_DEBUGFS is not set +CONFIG_ATH10K_LEDS=y +CONFIG_WCN36XX=m +# CONFIG_WCN36XX_DEBUGFS is not set +# CONFIG_ATH11K is not set +# CONFIG_WLAN_VENDOR_ATMEL is not set +# CONFIG_WLAN_VENDOR_BROADCOM is not set +CONFIG_WLAN_VENDOR_INTEL=y +CONFIG_WLAN_VENDOR_INTERSIL=y +CONFIG_P54_COMMON=m +CONFIG_P54_USB=m +# CONFIG_P54_SPI is not set +CONFIG_P54_LEDS=y +CONFIG_WLAN_VENDOR_MARVELL=y +CONFIG_LIBERTAS=m +CONFIG_LIBERTAS_USB=m +# 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_LIBERTAS_THINFIRM=m +# CONFIG_LIBERTAS_THINFIRM_DEBUG is not set +CONFIG_LIBERTAS_THINFIRM_USB=m +CONFIG_MWIFIEX=m +# CONFIG_MWIFIEX_SDIO is not set +CONFIG_MWIFIEX_USB=m +CONFIG_WLAN_VENDOR_MEDIATEK=y +CONFIG_MT7601U=m +CONFIG_MT76_CORE=m +CONFIG_MT76_LEDS=y +CONFIG_MT76_USB=m +CONFIG_MT76_SDIO=m +CONFIG_MT76x02_LIB=m +CONFIG_MT76x02_USB=m +CONFIG_MT76_CONNAC_LIB=m +CONFIG_MT76x0_COMMON=m +CONFIG_MT76x0U=m +CONFIG_MT76x2_COMMON=m +CONFIG_MT76x2U=m +CONFIG_MT7615_COMMON=m +CONFIG_MT7663_USB_SDIO_COMMON=m +CONFIG_MT7663U=m +CONFIG_MT7663S=m +# CONFIG_MT7921S is not set +# CONFIG_MT7921U is not set +# CONFIG_MT7925U is not set +CONFIG_WLAN_VENDOR_MICROCHIP=y +# CONFIG_WILC1000_SDIO is not set +# CONFIG_WILC1000_SPI is not set +CONFIG_WLAN_VENDOR_PURELIFI=y +# CONFIG_PLFXLC is not set +CONFIG_WLAN_VENDOR_RALINK=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=y +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_WLAN_VENDOR_REALTEK=y +CONFIG_RTL8187=m +CONFIG_RTL8187_LEDS=y +CONFIG_RTL_CARDS=m +CONFIG_RTL8192CU=m +CONFIG_RTL8192DU=m +CONFIG_RTLWIFI=m +CONFIG_RTLWIFI_USB=m +# CONFIG_RTLWIFI_DEBUG is not set +CONFIG_RTL8192C_COMMON=m +CONFIG_RTL8XXXU=m +CONFIG_RTL8XXXU_UNTESTED=y +CONFIG_RTW88=m +CONFIG_RTW88_CORE=m +CONFIG_RTW88_SDIO=m +CONFIG_RTW88_8723X=m +CONFIG_RTW88_8723D=m +CONFIG_RTW88_USB=m +CONFIG_RTW88_8822BS=m +CONFIG_RTW88_8822BU=m +CONFIG_RTW88_8822B=m +CONFIG_RTW88_8822CS=m +CONFIG_RTW88_8822CU=m +CONFIG_RTW88_8822C=m +CONFIG_RTW88_8723DS=m +CONFIG_RTW88_8723CS=m +CONFIG_RTW88_8723DU=m +CONFIG_RTW88_8821CS=m +CONFIG_RTW88_8821CU=m +CONFIG_RTW88_8821C=m +# CONFIG_RTW88_DEBUG is not set +# CONFIG_RTW88_DEBUGFS is not set +CONFIG_RTW89=m +CONFIG_WLAN_VENDOR_RSI=y +# CONFIG_RSI_91X is not set +CONFIG_WLAN_VENDOR_SILABS=y +# CONFIG_WFX is not set +CONFIG_WLAN_VENDOR_ST=y +# CONFIG_CW1200 is not set +CONFIG_WLAN_VENDOR_TI=y +# CONFIG_WL1251 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_WLAN_VENDOR_ZYDAS is not set +CONFIG_WLAN_VENDOR_QUANTENNA=y +CONFIG_ESP8089=m +# CONFIG_ESP8089_DEBUG_FS is not set +# CONFIG_MAC80211_HWSIM is not set +# CONFIG_VIRT_WIFI is not set +# CONFIG_WAN is not set + +# +# Wireless WAN +# +# CONFIG_WWAN is not set +# end of Wireless WAN + +# CONFIG_NETDEVSIM is not set +CONFIG_NET_FAILOVER=y +# CONFIG_ISDN 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=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=y +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG 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_QT1050 is not set +# CONFIG_KEYBOARD_QT1070 is not set +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_DLINK_DIR685 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_MPR121 is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_PINEPHONE 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_TM2_TOUCHKEY is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_CAP11XX is not set +# CONFIG_KEYBOARD_BCM is not set +# CONFIG_KEYBOARD_CYPRESS_SF 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=y +# 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 is not set +CONFIG_JOYSTICK_ADC=y +# CONFIG_JOYSTICK_ADI is not set +# CONFIG_JOYSTICK_COBRA is not set +# CONFIG_JOYSTICK_GF2K is not set +# CONFIG_JOYSTICK_GRIP is not set +# CONFIG_JOYSTICK_GRIP_MP is not set +# CONFIG_JOYSTICK_GUILLEMOT is not set +# CONFIG_JOYSTICK_INTERACT is not set +# CONFIG_JOYSTICK_SIDEWINDER is not set +# CONFIG_JOYSTICK_TMDC is not set +# CONFIG_JOYSTICK_IFORCE is not set +# CONFIG_JOYSTICK_WARRIOR is not set +# CONFIG_JOYSTICK_MAGELLAN is not set +# CONFIG_JOYSTICK_SPACEORB is not set +# CONFIG_JOYSTICK_SPACEBALL is not set +# CONFIG_JOYSTICK_STINGER is not set +# CONFIG_JOYSTICK_TWIDJOY is not set +# CONFIG_JOYSTICK_ZHENHUA is not set +# CONFIG_JOYSTICK_AS5011 is not set +# CONFIG_JOYSTICK_JOYDUMP is not set +# CONFIG_JOYSTICK_XPAD is not set +# CONFIG_JOYSTICK_PSXPAD_SPI is not set +# CONFIG_JOYSTICK_PXRC is not set +# CONFIG_JOYSTICK_QWIIC is not set +# CONFIG_JOYSTICK_FSIA6B is not set +CONFIG_JOYSTICK_ODROIDGO2=y +CONFIG_JOYSTICK_ODROIDGO2_V11=y +CONFIG_JOYSTICK_ODROIDGO3=y +CONFIG_JOYSTICK_RGB20S=y +CONFIG_JOYSTICK_XU10=y +# CONFIG_JOYSTICK_GAMEFORCE_CHI is not set +# CONFIG_JOYSTICK_SENSEHAT is not set +# CONFIG_JOYSTICK_SEESAW is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_AD714X is not set +# CONFIG_INPUT_ATMEL_CAPTOUCH is not set +# CONFIG_INPUT_BMA150 is not set +# CONFIG_INPUT_E3X0_BUTTON is not set +# CONFIG_INPUT_MMA8450 is not set +# CONFIG_INPUT_GPIO_BEEPER is not set +CONFIG_INPUT_GPIO_DECODER=m +CONFIG_INPUT_GPIO_VIBRA=m +# CONFIG_INPUT_ATI_REMOTE2 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_UINPUT=y +# CONFIG_INPUT_PCF8574 is not set +# CONFIG_INPUT_PWM_BEEPER is not set +CONFIG_INPUT_PWM_VIBRA=y +CONFIG_INPUT_RK805_PWRKEY=y +# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set +# CONFIG_INPUT_DA7280_HAPTICS is not set +# CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_IMS_PCU is not set +# CONFIG_INPUT_IQS269A is not set +# CONFIG_INPUT_IQS626A is not set +# CONFIG_INPUT_IQS7222 is not set +# CONFIG_INPUT_CMA3000 is not set +# CONFIG_INPUT_DRV260X_HAPTICS is not set +# CONFIG_INPUT_DRV2665_HAPTICS is not set +# CONFIG_INPUT_DRV2667_HAPTICS is not set +CONFIG_RMI4_CORE=m +# CONFIG_RMI4_I2C is not set +# CONFIG_RMI4_SPI is not set +# CONFIG_RMI4_SMB is not set +CONFIG_RMI4_F03=y +CONFIG_RMI4_F03_SERIO=m +CONFIG_RMI4_2D_SENSOR=y +CONFIG_RMI4_F11=y +CONFIG_RMI4_F12=y +CONFIG_RMI4_F30=y +# CONFIG_RMI4_F34 is not set +# CONFIG_RMI4_F3A is not set +# CONFIG_RMI4_F54 is not set +# CONFIG_RMI4_F55 is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=m +# CONFIG_SERIO_AMBAKMI 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_SERIO_GPIO_PS2 is not set +# CONFIG_USERIO is not set +CONFIG_GAMEPORT=y +# end of Hardware I/O ports +# end of Input device support + +# +# Character devices +# +CONFIG_TTY=y +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_VT_CONSOLE_SLEEP=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set +CONFIG_LEGACY_TIOCSTI=y +CONFIG_LDISC_AUTOLOAD=y + +# +# Serial drivers +# +CONFIG_SERIAL_EARLYCON=y +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y +# CONFIG_SERIAL_8250_16550A_VARIANTS is not set +# CONFIG_SERIAL_8250_FINTEK is not set +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=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +# CONFIG_SERIAL_8250_RSA is not set +CONFIG_SERIAL_8250_DWLIB=y +CONFIG_SERIAL_8250_FSL=y +CONFIG_SERIAL_8250_DW=y +# CONFIG_SERIAL_8250_RT288X is not set +CONFIG_SERIAL_OF_PLATFORM=y + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_AMBA_PL010 is not set +# CONFIG_SERIAL_AMBA_PL011 is not set +# CONFIG_SERIAL_EARLYCON_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_SIFIVE is not set +# 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_XILINX_PS_UART=y +CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y +# CONFIG_SERIAL_ARC is not set +# CONFIG_SERIAL_FSL_LPUART is not set +# CONFIG_SERIAL_FSL_LINFLEXUART is not set +# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set +# CONFIG_SERIAL_SPRD is not set +# end of Serial drivers + +CONFIG_SERIAL_MCTRL_GPIO=y +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_N_GSM is not set +# CONFIG_NULL_TTY is not set +# CONFIG_HVC_DCC is not set +CONFIG_SERIAL_DEV_BUS=y +CONFIG_SERIAL_DEV_CTRL_TTYPORT=y +# CONFIG_TTY_PRINTK is not set +# CONFIG_VIRTIO_CONSOLE is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=m +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +# CONFIG_HW_RANDOM_BA431 is not set +CONFIG_HW_RANDOM_OPTEE=m +# CONFIG_HW_RANDOM_CCTRNG is not set +# CONFIG_HW_RANDOM_XIPHERA is not set +CONFIG_HW_RANDOM_ARM_SMCCC_TRNG=m +CONFIG_HW_RANDOM_ROCKCHIP=m +CONFIG_DEVMEM=y +CONFIG_DEVPORT=y +# CONFIG_TCG_TPM is not set +# CONFIG_XILLYBUS is not set +# CONFIG_XILLYUSB is not set +# end of Character devices + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=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_GPMUX is not set +# CONFIG_I2C_MUX_LTC4306 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_DEMUX_PINCTRL is not set +# CONFIG_I2C_MUX_MLXCPLD is not set +# end of Multiplexer I2C Chip support + +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_ALGOBIT=m + +# +# 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_CORE=y +# CONFIG_I2C_DESIGNWARE_SLAVE is not set +CONFIG_I2C_DESIGNWARE_PLATFORM=y +# CONFIG_I2C_EMEV2 is not set +CONFIG_I2C_GPIO=m +# CONFIG_I2C_GPIO_FAULT_INJECTOR is not set +# CONFIG_I2C_HISI is not set +# CONFIG_I2C_NOMADIK is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM 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_CP2615 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_VIRTIO is not set +# end of I2C Hardware Bus support + +# 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 +# end of I2C support + +# CONFIG_I3C is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_ALTERA is not set +# CONFIG_SPI_AXI_SPI_ENGINE is not set +CONFIG_SPI_BITBANG=y +# CONFIG_SPI_CADENCE is not set +# CONFIG_SPI_CADENCE_QUADSPI is not set +# CONFIG_SPI_CADENCE_XSPI is not set +# CONFIG_SPI_CH341 is not set +# CONFIG_SPI_DESIGNWARE is not set +CONFIG_SPI_GPIO=y +# CONFIG_SPI_FSL_SPI is not set +# CONFIG_SPI_MICROCHIP_CORE is not set +# CONFIG_SPI_MICROCHIP_CORE_QSPI is not set +# CONFIG_SPI_OC_TINY is not set +CONFIG_SPI_PL022=y +CONFIG_SPI_ROCKCHIP=y +CONFIG_SPI_ROCKCHIP_SFC=y +# CONFIG_SPI_SC18IS602 is not set +# CONFIG_SPI_SIFIVE is not set +# CONFIG_SPI_SN_F_OSPI is not set +# CONFIG_SPI_MXIC is not set +# CONFIG_SPI_XCOMM is not set +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_ZYNQMP_GQSPI is not set +# CONFIG_SPI_AMD is not set + +# +# SPI Multiplexer support +# +# CONFIG_SPI_MUX is not set + +# +# SPI Protocol Masters +# +CONFIG_SPI_SPIDEV=m +# CONFIG_SPI_LOOPBACK_TEST is not set +# CONFIG_SPI_TLE62X0 is not set +# CONFIG_SPI_SLAVE is not set +CONFIG_SPI_DYNAMIC=y +CONFIG_SPMI=y +# CONFIG_SPMI_HISI3670 is not set +# CONFIG_HSI is not set +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 +CONFIG_PTP_1588_CLOCK_OPTIONAL=y + +# +# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks. +# +CONFIG_PTP_1588_CLOCK_KVM=y +# CONFIG_PTP_1588_CLOCK_IDT82P33 is not set +# CONFIG_PTP_1588_CLOCK_IDTCM is not set +# CONFIG_PTP_1588_CLOCK_FC3W is not set +# CONFIG_PTP_1588_CLOCK_MOCK is not set +# end of PTP clock support + +CONFIG_PINCTRL=y +CONFIG_GENERIC_PINCTRL_GROUPS=y +CONFIG_PINMUX=y +CONFIG_GENERIC_PINMUX_FUNCTIONS=y +CONFIG_PINCONF=y +CONFIG_GENERIC_PINCONF=y +# CONFIG_DEBUG_PINCTRL is not set +# CONFIG_PINCTRL_AW9523 is not set +# CONFIG_PINCTRL_CY8C95X0 is not set +CONFIG_PINCTRL_MAX77620=y +# CONFIG_PINCTRL_MCP23S08 is not set +# CONFIG_PINCTRL_MICROCHIP_SGPIO is not set +# CONFIG_PINCTRL_OCELOT is not set +CONFIG_PINCTRL_RK805=y +CONFIG_PINCTRL_ROCKCHIP=y +# CONFIG_PINCTRL_SCMI is not set +CONFIG_PINCTRL_SINGLE=y +# CONFIG_PINCTRL_STMFX is not set +# CONFIG_PINCTRL_SX150X is not set +# CONFIG_PINCTRL_IMX_SCMI is not set + +# +# Renesas pinctrl drivers +# +# end of Renesas pinctrl drivers + +CONFIG_GPIOLIB=y +CONFIG_GPIOLIB_FASTPATH_LIMIT=512 +CONFIG_OF_GPIO=y +CONFIG_GPIOLIB_IRQCHIP=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_CDEV=y +CONFIG_GPIO_CDEV_V1=y +CONFIG_GPIO_GENERIC=y + +# +# Memory mapped GPIO drivers +# +# CONFIG_GPIO_74XX_MMIO is not set +# CONFIG_GPIO_ALTERA is not set +# CONFIG_GPIO_CADENCE is not set +CONFIG_GPIO_DWAPB=y +# CONFIG_GPIO_FTGPIO010 is not set +CONFIG_GPIO_GENERIC_PLATFORM=y +# CONFIG_GPIO_GRGPIO is not set +# CONFIG_GPIO_HISI is not set +# CONFIG_GPIO_HLWD is not set +# CONFIG_GPIO_LOGICVC is not set +# CONFIG_GPIO_MB86S7X is not set +CONFIG_GPIO_PL061=y +CONFIG_GPIO_ROCKCHIP=y +# CONFIG_GPIO_SIFIVE is not set +CONFIG_GPIO_SYSCON=y +# CONFIG_GPIO_XGENE is not set +# CONFIG_GPIO_XILINX is not set +# CONFIG_GPIO_AMD_FCH is not set +# end of Memory mapped GPIO drivers + +# +# I2C GPIO expanders +# +# CONFIG_GPIO_ADNP is not set +# CONFIG_GPIO_FXL6408 is not set +# CONFIG_GPIO_DS4520 is not set +# CONFIG_GPIO_GW_PLD is not set +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +CONFIG_GPIO_PCA953X=y +CONFIG_GPIO_PCA953X_IRQ=y +# CONFIG_GPIO_PCA9570 is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_TPIC2810 is not set +# end of I2C GPIO expanders + +# +# MFD GPIO expanders +# +CONFIG_GPIO_MAX77620=y +# end of MFD GPIO expanders + +# +# SPI GPIO expanders +# +# CONFIG_GPIO_74X164 is not set +# CONFIG_GPIO_MAX3191X is not set +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_PISOSR is not set +# CONFIG_GPIO_XRA1403 is not set +# end of SPI GPIO expanders + +# +# USB GPIO expanders +# +# end of USB GPIO expanders + +# +# Virtual GPIO drivers +# +# CONFIG_GPIO_AGGREGATOR is not set +# CONFIG_GPIO_LATCH is not set +# CONFIG_GPIO_MOCKUP is not set +# CONFIG_GPIO_SIM is not set +# end of Virtual GPIO drivers + +# +# GPIO Debugging utilities +# +# CONFIG_GPIO_SLOPPY_LOGIC_ANALYZER is not set +# CONFIG_GPIO_VIRTUSER is not set +# end of GPIO Debugging utilities + +# CONFIG_W1 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_REGULATOR is not set +# CONFIG_POWER_RESET_RESTART is not set +# CONFIG_POWER_RESET_XGENE is not set +CONFIG_POWER_RESET_SYSCON=y +CONFIG_POWER_RESET_SYSCON_POWEROFF=y +CONFIG_REBOOT_MODE=y +CONFIG_SYSCON_REBOOT_MODE=y +# CONFIG_NVMEM_REBOOT_MODE is not set +# CONFIG_POWER_SEQUENCING is not set +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +CONFIG_POWER_SUPPLY_HWMON=y +# CONFIG_GENERIC_ADC_BATTERY is not set +# CONFIG_IP5XXX_POWER is not set +# CONFIG_TEST_POWER is not set +# CONFIG_CHARGER_ADP5061 is not set +CONFIG_BATTERY_CW2015=y +# CONFIG_BATTERY_DS2780 is not set +# CONFIG_BATTERY_DS2781 is not set +# CONFIG_BATTERY_DS2782 is not set +# CONFIG_BATTERY_SAMSUNG_SDI is not set +# CONFIG_BATTERY_SBS is not set +# CONFIG_CHARGER_SBS is not set +# CONFIG_MANAGER_SBS is not set +# CONFIG_BATTERY_BQ27XXX is not set +# CONFIG_BATTERY_MAX17040 is not set +# CONFIG_BATTERY_MAX17042 is not set +# CONFIG_BATTERY_MAX1720X is not set +# CONFIG_CHARGER_ISP1704 is not set +# CONFIG_CHARGER_MAX8903 is not set +# CONFIG_CHARGER_LP8727 is not set +CONFIG_CHARGER_GPIO=m +# CONFIG_CHARGER_MANAGER is not set +# CONFIG_CHARGER_LT3651 is not set +# CONFIG_CHARGER_LTC4162L is not set +# CONFIG_CHARGER_DETECTOR_MAX14656 is not set +# CONFIG_CHARGER_MAX77976 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_BQ2515X is not set +# CONFIG_CHARGER_BQ25890 is not set +# CONFIG_CHARGER_BQ25980 is not set +# CONFIG_CHARGER_BQ256XX is not set +CONFIG_CHARGER_RK817=y +# CONFIG_CHARGER_SMB347 is not set +# CONFIG_BATTERY_GAUGE_LTC2941 is not set +# CONFIG_BATTERY_GOLDFISH is not set +# CONFIG_BATTERY_RT5033 is not set +# CONFIG_CHARGER_RT9455 is not set +# CONFIG_CHARGER_RT9467 is not set +# CONFIG_CHARGER_RT9471 is not set +# CONFIG_CHARGER_UCS1002 is not set +# CONFIG_CHARGER_BD99954 is not set +# CONFIG_BATTERY_UG3105 is not set +# CONFIG_FUEL_GAUGE_MM8013 is not set +CONFIG_HWMON=y +# 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_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM1177 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_AHT10 is not set +# CONFIG_SENSORS_AQUACOMPUTER_D5NEXT is not set +# CONFIG_SENSORS_AS370 is not set +# CONFIG_SENSORS_ASC7621 is not set +# CONFIG_SENSORS_ASUS_ROG_RYUJIN is not set +# CONFIG_SENSORS_AXI_FAN_CONTROL is not set +# CONFIG_SENSORS_ARM_SCMI is not set +# CONFIG_SENSORS_ARM_SCPI is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_CHIPCAP2 is not set +# CONFIG_SENSORS_CORSAIR_CPRO is not set +# CONFIG_SENSORS_CORSAIR_PSU 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_FTSTEUTATES is not set +# CONFIG_SENSORS_GIGABYTE_WATERFORCE 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_HS3001 is not set +# CONFIG_SENSORS_IIO_HWMON is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_JC42 is not set +# CONFIG_SENSORS_POWERZ is not set +# CONFIG_SENSORS_POWR1220 is not set +# CONFIG_SENSORS_LINEAGE is not set +# CONFIG_SENSORS_LTC2945 is not set +# CONFIG_SENSORS_LTC2947_I2C is not set +# CONFIG_SENSORS_LTC2947_SPI is not set +# CONFIG_SENSORS_LTC2990 is not set +# CONFIG_SENSORS_LTC2991 is not set +# CONFIG_SENSORS_LTC2992 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_LTC4282 is not set +# CONFIG_SENSORS_MAX1111 is not set +# CONFIG_SENSORS_MAX127 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_MAX31722 is not set +# CONFIG_SENSORS_MAX31730 is not set +# CONFIG_SENSORS_MAX31760 is not set +# CONFIG_MAX31827 is not set +# CONFIG_SENSORS_MAX6620 is not set +# CONFIG_SENSORS_MAX6621 is not set +# CONFIG_SENSORS_MAX6639 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_MAX6697 is not set +# CONFIG_SENSORS_MAX31790 is not set +# CONFIG_SENSORS_MC34VR500 is not set +# CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_TC654 is not set +# CONFIG_SENSORS_TPS23861 is not set +# CONFIG_SENSORS_MR75203 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_NCT6775_I2C is not set +# CONFIG_SENSORS_NCT7802 is not set +# CONFIG_SENSORS_NCT7904 is not set +# CONFIG_SENSORS_NPCM7XX is not set +# CONFIG_SENSORS_NZXT_KRAKEN2 is not set +# CONFIG_SENSORS_NZXT_KRAKEN3 is not set +# CONFIG_SENSORS_NZXT_SMART2 is not set +# CONFIG_SENSORS_OCC_P8_I2C is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_PMBUS is not set +# CONFIG_SENSORS_PT5161L is not set +# CONFIG_SENSORS_PWM_FAN is not set +# CONFIG_SENSORS_SBTSI is not set +# CONFIG_SENSORS_SBRMI is not set +# CONFIG_SENSORS_SHT15 is not set +# CONFIG_SENSORS_SHT21 is not set +# CONFIG_SENSORS_SHT3x is not set +# CONFIG_SENSORS_SHT4x 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_EMC2305 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_SCH5627 is not set +# CONFIG_SENSORS_SCH5636 is not set +# CONFIG_SENSORS_STTS751 is not set +# CONFIG_SENSORS_ADC128D818 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_INA238 is not set +# CONFIG_SENSORS_INA3221 is not set +# CONFIG_SENSORS_SPD5118 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_TMP108 is not set +# CONFIG_SENSORS_TMP401 is not set +# CONFIG_SENSORS_TMP421 is not set +# CONFIG_SENSORS_TMP464 is not set +# CONFIG_SENSORS_TMP513 is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_W83773G 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_NETLINK is not set +# CONFIG_THERMAL_STATISTICS is not set +# CONFIG_THERMAL_DEBUGFS is not set +# CONFIG_THERMAL_CORE_TESTING is not set +CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 +CONFIG_THERMAL_HWMON=y +CONFIG_THERMAL_OF=y +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set +# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set +# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set +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_CPU_FREQ_THERMAL=y +CONFIG_DEVFREQ_THERMAL=y +# CONFIG_THERMAL_EMULATION is not set +# CONFIG_THERMAL_MMIO is not set +# CONFIG_MAX77620_THERMAL is not set +CONFIG_ROCKCHIP_THERMAL=y +# CONFIG_GENERIC_ADC_THERMAL is not set +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_CORE=y +# CONFIG_WATCHDOG_NOWAYOUT is not set +CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED=y +CONFIG_WATCHDOG_OPEN_TIMEOUT=0 +# CONFIG_WATCHDOG_SYSFS is not set +# CONFIG_WATCHDOG_HRTIMER_PRETIMEOUT is not set + +# +# Watchdog Pretimeout Governors +# +# CONFIG_WATCHDOG_PRETIMEOUT_GOV 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_XILINX_WINDOW_WATCHDOG is not set +# CONFIG_ZIIRAVE_WATCHDOG is not set +# CONFIG_ARM_SP805_WATCHDOG is not set +# CONFIG_ARM_SBSA_WATCHDOG is not set +# CONFIG_CADENCE_WATCHDOG is not set +CONFIG_DW_WATCHDOG=y +# CONFIG_MAX63XX_WATCHDOG is not set +# CONFIG_MAX77620_WATCHDOG is not set +# CONFIG_ARM_SMC_WATCHDOG is not set +# CONFIG_MEN_A21_WDT is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set +CONFIG_BCMA_POSSIBLE=y +# CONFIG_BCMA is not set + +# +# Multifunction device drivers +# +CONFIG_MFD_CORE=y +# CONFIG_MFD_ADP5585 is not set +# CONFIG_MFD_ACT8945A is not set +# CONFIG_MFD_AS3711 is not set +# CONFIG_MFD_SMPRO 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_BD9571MWV is not set +# CONFIG_MFD_AXP20X_I2C is not set +# CONFIG_MFD_CS42L43_I2C is not set +# CONFIG_MFD_MADERA is not set +# CONFIG_MFD_MAX5970 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_GATEWORKS_GSC is not set +# CONFIG_MFD_MC13XXX_SPI is not set +# CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_MFD_MP2629 is not set +# CONFIG_MFD_HI6421_PMIC is not set +# CONFIG_MFD_HI6421_SPMI is not set +# CONFIG_MFD_IQS62X 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_88PM886_PMIC is not set +# CONFIG_MFD_MAX14577 is not set +# CONFIG_MFD_MAX77541 is not set +CONFIG_MFD_MAX77620=y +# CONFIG_MFD_MAX77650 is not set +# CONFIG_MFD_MAX77686 is not set +# CONFIG_MFD_MAX77693 is not set +# CONFIG_MFD_MAX77714 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_MT6360 is not set +# CONFIG_MFD_MT6370 is not set +# CONFIG_MFD_MT6397 is not set +# CONFIG_MFD_MENF21BMC is not set +# CONFIG_MFD_OCELOT is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_MFD_CPCAP is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_NTXEC is not set +# CONFIG_MFD_RETU is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_SY7636A is not set +# CONFIG_MFD_RT4831 is not set +# CONFIG_MFD_RT5033 is not set +# CONFIG_MFD_RT5120 is not set +# CONFIG_MFD_RC5T583 is not set +CONFIG_MFD_RK8XX=y +CONFIG_MFD_RK8XX_I2C=y +# CONFIG_MFD_RK8XX_SPI is not set +# CONFIG_MFD_RN5T618 is not set +CONFIG_MFD_SEC_CORE=y +# CONFIG_MFD_SI476X_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SKY81452 is not set +# CONFIG_MFD_STMPE is not set +CONFIG_MFD_SYSCON=y +# CONFIG_MFD_LP3943 is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_TI_LMU 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_TPS65086 is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TI_LP873X is not set +# CONFIG_MFD_TI_LP87565 is not set +# CONFIG_MFD_TPS65218 is not set +# CONFIG_MFD_TPS65219 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_MFD_TPS6594_I2C is not set +# CONFIG_MFD_TPS6594_SPI is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +CONFIG_MFD_WL1273_CORE=m +# CONFIG_MFD_LM3533 is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TQMX86 is not set +# CONFIG_MFD_LOCHNAGAR 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_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MFD_ROHM_BD718XX is not set +# CONFIG_MFD_ROHM_BD71828 is not set +# CONFIG_MFD_ROHM_BD957XMUF is not set +# CONFIG_MFD_ROHM_BD96801 is not set +# CONFIG_MFD_STPMIC1 is not set +# CONFIG_MFD_STMFX is not set +# CONFIG_MFD_ATC260X_I2C is not set +# CONFIG_MFD_KHADAS_MCU is not set +# CONFIG_MFD_QCOM_PM8008 is not set +# CONFIG_MFD_CS40L50_I2C is not set +# CONFIG_MFD_CS40L50_SPI is not set +# CONFIG_RAVE_SP_CORE is not set +# CONFIG_MFD_INTEL_M10_BMC_SPI is not set +# CONFIG_MFD_RSMU_I2C is not set +# CONFIG_MFD_RSMU_SPI is not set +# end of Multifunction device drivers + +CONFIG_REGULATOR=y +CONFIG_REGULATOR_DEBUG=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_VIRTUAL_CONSUMER=y +CONFIG_REGULATOR_USERSPACE_CONSUMER=y +# CONFIG_REGULATOR_NETLINK_EVENTS is not set +# CONFIG_REGULATOR_88PG86X is not set +# CONFIG_REGULATOR_ACT8865 is not set +# CONFIG_REGULATOR_AD5398 is not set +# CONFIG_REGULATOR_ARM_SCMI is not set +# CONFIG_REGULATOR_AW37503 is not set +# CONFIG_REGULATOR_DA9121 is not set +# CONFIG_REGULATOR_DA9210 is not set +# CONFIG_REGULATOR_DA9211 is not set +# CONFIG_REGULATOR_FAN53555 is not set +# CONFIG_REGULATOR_FAN53880 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_LP8755 is not set +# CONFIG_REGULATOR_LTC3589 is not set +# CONFIG_REGULATOR_LTC3676 is not set +# CONFIG_REGULATOR_MAX1586 is not set +# CONFIG_REGULATOR_MAX77503 is not set +# CONFIG_REGULATOR_MAX77620 is not set +# CONFIG_REGULATOR_MAX77857 is not set +# CONFIG_REGULATOR_MAX8649 is not set +# CONFIG_REGULATOR_MAX8660 is not set +# CONFIG_REGULATOR_MAX8893 is not set +# CONFIG_REGULATOR_MAX8952 is not set +# CONFIG_REGULATOR_MAX8973 is not set +# CONFIG_REGULATOR_MAX20086 is not set +# CONFIG_REGULATOR_MAX20411 is not set +# CONFIG_REGULATOR_MAX77826 is not set +# CONFIG_REGULATOR_MCP16502 is not set +# CONFIG_REGULATOR_MP5416 is not set +# CONFIG_REGULATOR_MP8859 is not set +# CONFIG_REGULATOR_MP886X is not set +# CONFIG_REGULATOR_MPQ7920 is not set +# CONFIG_REGULATOR_MT6311 is not set +# CONFIG_REGULATOR_MT6315 is not set +# CONFIG_REGULATOR_PCA9450 is not set +# CONFIG_REGULATOR_PF8X00 is not set +# CONFIG_REGULATOR_PFUZE100 is not set +# CONFIG_REGULATOR_PV88060 is not set +# CONFIG_REGULATOR_PV88080 is not set +# CONFIG_REGULATOR_PV88090 is not set +CONFIG_REGULATOR_PWM=y +# CONFIG_REGULATOR_QCOM_SPMI is not set +# CONFIG_REGULATOR_QCOM_USB_VBUS is not set +# CONFIG_REGULATOR_RAA215300 is not set +# CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY is not set +CONFIG_REGULATOR_RK808=y +# CONFIG_REGULATOR_RT4801 is not set +# CONFIG_REGULATOR_RT4803 is not set +# CONFIG_REGULATOR_RT5190A is not set +# CONFIG_REGULATOR_RT5739 is not set +# CONFIG_REGULATOR_RT5759 is not set +# CONFIG_REGULATOR_RT6160 is not set +# CONFIG_REGULATOR_RT6190 is not set +# CONFIG_REGULATOR_RT6245 is not set +# CONFIG_REGULATOR_RTQ2134 is not set +# CONFIG_REGULATOR_RTMV20 is not set +# CONFIG_REGULATOR_RTQ6752 is not set +# CONFIG_REGULATOR_RTQ2208 is not set +# CONFIG_REGULATOR_S2MPA01 is not set +# CONFIG_REGULATOR_S2MPS11 is not set +# CONFIG_REGULATOR_S5M8767 is not set +# CONFIG_REGULATOR_SLG51000 is not set +# CONFIG_REGULATOR_SY8106A is not set +# CONFIG_REGULATOR_SY8824X is not set +# CONFIG_REGULATOR_SY8827N is not set +# CONFIG_REGULATOR_TPS51632 is not set +# CONFIG_REGULATOR_TPS62360 is not set +# CONFIG_REGULATOR_TPS6286X is not set +# CONFIG_REGULATOR_TPS6287X 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_VCTRL is not set +# CONFIG_REGULATOR_QCOM_LABIBB is not set +# CONFIG_RC_CORE is not set +CONFIG_CEC_CORE=y +CONFIG_CEC_NOTIFIER=y + +# +# CEC support +# +# CONFIG_MEDIA_CEC_SUPPORT is not set +# end of CEC support + +CONFIG_MEDIA_SUPPORT=y +CONFIG_MEDIA_SUPPORT_FILTER=y +# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set + +# +# Media device types +# +# CONFIG_MEDIA_CAMERA_SUPPORT is not set +# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set +# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set +# CONFIG_MEDIA_RADIO_SUPPORT is not set +# CONFIG_MEDIA_SDR_SUPPORT is not set +CONFIG_MEDIA_PLATFORM_SUPPORT=y +# CONFIG_MEDIA_TEST_SUPPORT is not set +# end of Media device types + +CONFIG_VIDEO_DEV=y +CONFIG_MEDIA_CONTROLLER=y + +# +# Video4Linux options +# +CONFIG_VIDEO_V4L2_I2C=y +CONFIG_VIDEO_V4L2_SUBDEV_API=y +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set +CONFIG_V4L2_JPEG_HELPER=m +CONFIG_V4L2_H264=m +CONFIG_V4L2_VP9=m +CONFIG_V4L2_MEM2MEM_DEV=y +CONFIG_V4L2_FLASH_LED_CLASS=m +CONFIG_V4L2_ASYNC=m +# end of Video4Linux options + +# +# Media controller options +# +# end of Media controller options + +# +# Media drivers +# + +# +# Drivers filtered as selected at 'Filter media drivers' +# + +# +# Media drivers +# +CONFIG_MEDIA_USB_SUPPORT=y +CONFIG_MEDIA_PLATFORM_DRIVERS=y +# CONFIG_V4L_PLATFORM_DRIVERS is not set +CONFIG_V4L_MEM2MEM_DRIVERS=y +# CONFIG_VIDEO_MEM2MEM_DEINTERLACE is not set + +# +# Allegro DVT media platform drivers +# + +# +# Amlogic media platform drivers +# + +# +# Amphion drivers +# + +# +# Aspeed media platform drivers +# + +# +# Atmel media platform drivers +# + +# +# Cadence media platform drivers +# +# CONFIG_VIDEO_CADENCE_CSI2RX is not set +# CONFIG_VIDEO_CADENCE_CSI2TX is not set + +# +# Chips&Media media platform drivers +# + +# +# Intel media platform drivers +# + +# +# Marvell media platform drivers +# + +# +# Mediatek media platform drivers +# + +# +# Microchip Technology, Inc. media platform drivers +# + +# +# Nuvoton media platform drivers +# + +# +# NVidia media platform drivers +# + +# +# NXP media platform drivers +# + +# +# Qualcomm media platform drivers +# + +# +# Raspberry Pi media platform drivers +# + +# +# Renesas media platform drivers +# + +# +# Rockchip media platform drivers +# +CONFIG_VIDEO_ROCKCHIP_RGA=y + +# +# Samsung media platform drivers +# + +# +# STMicroelectronics media platform drivers +# + +# +# Sunxi media platform drivers +# + +# +# Texas Instruments drivers +# + +# +# Verisilicon media platform drivers +# +CONFIG_VIDEO_HANTRO=m +# CONFIG_VIDEO_HANTRO_HEVC_RFC is not set +CONFIG_VIDEO_HANTRO_ROCKCHIP=y + +# +# VIA media platform drivers +# + +# +# Xilinx media platform drivers +# +CONFIG_VIDEOBUF2_CORE=y +CONFIG_VIDEOBUF2_V4L2=y +CONFIG_VIDEOBUF2_MEMOPS=y +CONFIG_VIDEOBUF2_DMA_CONTIG=m +CONFIG_VIDEOBUF2_VMALLOC=m +CONFIG_VIDEOBUF2_DMA_SG=y +# end of Media drivers + +# +# Media ancillary drivers +# + +# +# Audio decoders, processors and mixers +# +# CONFIG_VIDEO_CS3308 is not set +# CONFIG_VIDEO_CS5345 is not set +# CONFIG_VIDEO_CS53L32A is not set +# CONFIG_VIDEO_MSP3400 is not set +# CONFIG_VIDEO_SONY_BTF_MPX is not set +# CONFIG_VIDEO_TDA1997X 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_TLV320AIC23B is not set +# CONFIG_VIDEO_TVAUDIO is not set +# CONFIG_VIDEO_UDA1342 is not set +# CONFIG_VIDEO_VP27SMPX is not set +# CONFIG_VIDEO_WM8739 is not set +# CONFIG_VIDEO_WM8775 is not set +# end of Audio decoders, processors and mixers + +# +# RDS decoders +# +# CONFIG_VIDEO_SAA6588 is not set +# end of RDS decoders + +# +# Video decoders +# +# CONFIG_VIDEO_ADV7180 is not set +# CONFIG_VIDEO_ADV7183 is not set +# CONFIG_VIDEO_ADV748X 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_ISL7998X is not set +# CONFIG_VIDEO_KS0127 is not set +# CONFIG_VIDEO_MAX9286 is not set +# CONFIG_VIDEO_ML86V7667 is not set +# CONFIG_VIDEO_SAA7110 is not set +# CONFIG_VIDEO_SAA711X is not set +# CONFIG_VIDEO_TC358743 is not set +# CONFIG_VIDEO_TC358746 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_TW9900 is not set +# CONFIG_VIDEO_TW9903 is not set +# CONFIG_VIDEO_TW9906 is not set +# CONFIG_VIDEO_TW9910 is not set +# CONFIG_VIDEO_VPX3220 is not set + +# +# Video and audio decoders +# +# CONFIG_VIDEO_SAA717X is not set +# CONFIG_VIDEO_CX25840 is not set +# end of Video decoders + +# +# Video encoders +# +# 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_AK881X is not set +# CONFIG_VIDEO_SAA7127 is not set +# CONFIG_VIDEO_SAA7185 is not set +# CONFIG_VIDEO_THS8200 is not set +# end of Video encoders + +# +# Video improvement chips +# +# CONFIG_VIDEO_UPD64031A is not set +# CONFIG_VIDEO_UPD64083 is not set +# end of Video improvement chips + +# +# Audio/Video compression chips +# +# CONFIG_VIDEO_SAA6752HS is not set +# end of Audio/Video compression chips + +# +# SDR tuner chips +# +# end of SDR tuner chips + +# +# Miscellaneous helper chips +# +# CONFIG_VIDEO_I2C is not set +# CONFIG_VIDEO_M52790 is not set +# CONFIG_VIDEO_ST_MIPID02 is not set +# CONFIG_VIDEO_THS7303 is not set +# end of Miscellaneous helper chips + +# +# Video serializers and deserializers +# +# CONFIG_VIDEO_DS90UB913 is not set +# CONFIG_VIDEO_DS90UB953 is not set +# CONFIG_VIDEO_DS90UB960 is not set +# CONFIG_VIDEO_MAX96714 is not set +# CONFIG_VIDEO_MAX96717 is not set +# end of Video serializers and deserializers + +# +# Media SPI Adapters +# +# CONFIG_VIDEO_GS1662 is not set +# end of Media SPI Adapters +# end of Media ancillary drivers + +# +# Graphics support +# +CONFIG_VIDEO=y +# CONFIG_AUXDISPLAY is not set +CONFIG_DRM=y +CONFIG_DRM_MIPI_DBI=y +CONFIG_DRM_MIPI_DSI=y +# CONFIG_DRM_DEBUG_MM is not set +CONFIG_DRM_KMS_HELPER=y +# CONFIG_DRM_PANIC is not set +# CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS is not set +# CONFIG_DRM_DEBUG_MODESET_LOCK is not set +CONFIG_DRM_CLIENT_SELECTION=y +CONFIG_DRM_CLIENT_SETUP=y +CONFIG_DRM_FBDEV_EMULATION=y +CONFIG_DRM_FBDEV_OVERALLOC=200 +# CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM is not set +# CONFIG_DRM_LOAD_EDID_FIRMWARE is not set +CONFIG_DRM_DISPLAY_HELPER=y +CONFIG_DRM_BRIDGE_CONNECTOR=y +# CONFIG_DRM_DISPLAY_DP_AUX_CEC is not set +# CONFIG_DRM_DISPLAY_DP_AUX_CHARDEV is not set +CONFIG_DRM_DISPLAY_DP_HELPER=y +CONFIG_DRM_DISPLAY_HDMI_HELPER=y +CONFIG_DRM_DISPLAY_HDMI_STATE_HELPER=y +CONFIG_DRM_GEM_DMA_HELPER=y +CONFIG_DRM_GEM_SHMEM_HELPER=m +CONFIG_DRM_SCHED=m + +# +# I2C encoder or helper chips +# +# CONFIG_DRM_I2C_CH7006 is not set +# CONFIG_DRM_I2C_SIL164 is not set +# CONFIG_DRM_I2C_NXP_TDA998X is not set +# CONFIG_DRM_I2C_NXP_TDA9950 is not set +# end of I2C encoder or helper chips + +# +# ARM devices +# +# CONFIG_DRM_HDLCD is not set +# CONFIG_DRM_MALI_DISPLAY is not set +# CONFIG_DRM_KOMEDA is not set +# end of ARM devices + +# CONFIG_DRM_VGEM is not set +# CONFIG_DRM_VKMS is not set +CONFIG_DRM_ROCKCHIP=y +CONFIG_ROCKCHIP_VOP=y +# CONFIG_ROCKCHIP_VOP2 is not set +CONFIG_ROCKCHIP_ANALOGIX_DP=y +CONFIG_ROCKCHIP_CDN_DP=y +CONFIG_ROCKCHIP_DW_HDMI=y +CONFIG_ROCKCHIP_DW_MIPI_DSI=y +CONFIG_ROCKCHIP_INNO_HDMI=y +CONFIG_ROCKCHIP_LVDS=y +CONFIG_ROCKCHIP_RGB=y +CONFIG_ROCKCHIP_RK3066_HDMI=y +# CONFIG_DRM_UDL is not set +CONFIG_DRM_PANEL=y + +# +# Display Panels +# +# CONFIG_DRM_PANEL_ABT_Y030XX067A is not set +# CONFIG_DRM_PANEL_ARM_VERSATILE is not set +# CONFIG_DRM_PANEL_ASUS_Z00T_TM5P5_NT35596 is not set +# CONFIG_DRM_PANEL_AUO_A030JTN01 is not set +# CONFIG_DRM_PANEL_BOE_BF060Y8M_AJ0 is not set +# CONFIG_DRM_PANEL_BOE_HIMAX8279D is not set +# CONFIG_DRM_PANEL_BOE_TH101MB31UIG002_28A is not set +# CONFIG_DRM_PANEL_BOE_TV101WUM_NL6 is not set +# CONFIG_DRM_PANEL_BOE_TV101WUM_LL2 is not set +# CONFIG_DRM_PANEL_EBBG_FT8719 is not set +CONFIG_DRM_PANEL_ELIDA_KD35T133=y +# CONFIG_DRM_PANEL_FEIXIN_K101_IM2BA02 is not set +# CONFIG_DRM_PANEL_FEIYANG_FY07024DI26A30D is not set +# CONFIG_DRM_PANEL_DSI_CM is not set +# CONFIG_DRM_PANEL_LVDS is not set +# CONFIG_DRM_PANEL_HIMAX_HX83102 is not set +# CONFIG_DRM_PANEL_HIMAX_HX83112A is not set +# CONFIG_DRM_PANEL_HIMAX_HX8394 is not set +# CONFIG_DRM_PANEL_ILITEK_IL9322 is not set +# CONFIG_DRM_PANEL_ILITEK_ILI9341 is not set +# CONFIG_DRM_PANEL_ILITEK_ILI9805 is not set +# CONFIG_DRM_PANEL_ILITEK_ILI9806E is not set +# CONFIG_DRM_PANEL_ILITEK_ILI9881C is not set +# CONFIG_DRM_PANEL_ILITEK_ILI9882T is not set +# CONFIG_DRM_PANEL_INNOLUX_EJ030NA is not set +# CONFIG_DRM_PANEL_INNOLUX_P079ZCA is not set +# CONFIG_DRM_PANEL_JADARD_JD9365DA_H3 is not set +# CONFIG_DRM_PANEL_JDI_LPM102A188A is not set +# CONFIG_DRM_PANEL_JDI_LT070ME05000 is not set +# CONFIG_DRM_PANEL_JDI_R63452 is not set +# CONFIG_DRM_PANEL_KHADAS_TS050 is not set +# CONFIG_DRM_PANEL_KINGDISPLAY_KD097D04 is not set +# CONFIG_DRM_PANEL_LEADTEK_LTK050H3146W is not set +# CONFIG_DRM_PANEL_LEADTEK_LTK500HD1829 is not set +# CONFIG_DRM_PANEL_LINCOLNTECH_LCD197 is not set +# CONFIG_DRM_PANEL_LG_LB035Q02 is not set +# CONFIG_DRM_PANEL_LG_LG4573 is not set +# CONFIG_DRM_PANEL_LG_SW43408 is not set +# CONFIG_DRM_PANEL_MAGNACHIP_D53E6EA8966 is not set +# CONFIG_DRM_PANEL_MANTIX_MLAF057WE51 is not set +# CONFIG_DRM_PANEL_NEC_NL8048HL11 is not set +CONFIG_DRM_PANEL_NEWVISION_NV3051D=y +# CONFIG_DRM_PANEL_NEWVISION_NV3052C is not set +# CONFIG_DRM_PANEL_NOVATEK_NT35510 is not set +# CONFIG_DRM_PANEL_NOVATEK_NT35560 is not set +# CONFIG_DRM_PANEL_NOVATEK_NT35950 is not set +# CONFIG_DRM_PANEL_NOVATEK_NT36523 is not set +# CONFIG_DRM_PANEL_NOVATEK_NT36672A is not set +# CONFIG_DRM_PANEL_NOVATEK_NT36672E is not set +# CONFIG_DRM_PANEL_NOVATEK_NT39016 is not set +# CONFIG_DRM_PANEL_OLIMEX_LCD_OLINUXINO is not set +# CONFIG_DRM_PANEL_ORISETECH_OTA5601A is not set +# CONFIG_DRM_PANEL_ORISETECH_OTM8009A is not set +# CONFIG_DRM_PANEL_OSD_OSD101T2587_53TS is not set +# CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00 is not set +# CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN is not set +# CONFIG_DRM_PANEL_RAYDIUM_RM67191 is not set +# CONFIG_DRM_PANEL_RAYDIUM_RM68200 is not set +# CONFIG_DRM_PANEL_RAYDIUM_RM692E5 is not set +# CONFIG_DRM_PANEL_RAYDIUM_RM69380 is not set +# CONFIG_DRM_PANEL_RONBO_RB070D30 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6E88A0_AMS452EF01 is not set +# CONFIG_DRM_PANEL_SAMSUNG_ATNA33XC20 is not set +# CONFIG_DRM_PANEL_SAMSUNG_DB7430 is not set +# CONFIG_DRM_PANEL_SAMSUNG_LD9040 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6E3FA7 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6D16D0 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6D27A1 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6D7AA0 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6E63M0 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0 is not set +# CONFIG_DRM_PANEL_SAMSUNG_SOFEF00 is not set +# CONFIG_DRM_PANEL_SEIKO_43WVF1G is not set +# CONFIG_DRM_PANEL_SHARP_LQ101R1SX01 is not set +# CONFIG_DRM_PANEL_SHARP_LS037V7DW01 is not set +# CONFIG_DRM_PANEL_SHARP_LS043T1LE01 is not set +# CONFIG_DRM_PANEL_SHARP_LS060T1SX01 is not set +CONFIG_DRM_PANEL_SITRONIX_ST7701=y +CONFIG_DRM_PANEL_SITRONIX_ST7703=y +# CONFIG_DRM_PANEL_SITRONIX_ST7789V is not set +# CONFIG_DRM_PANEL_SONY_ACX565AKM is not set +# CONFIG_DRM_PANEL_SONY_TD4353_JDI is not set +# CONFIG_DRM_PANEL_SONY_TULIP_TRULY_NT35521 is not set +# CONFIG_DRM_PANEL_STARTEK_KD070FHFID015 is not set +# CONFIG_DRM_PANEL_EDP is not set +CONFIG_DRM_PANEL_SIMPLE=y +# CONFIG_DRM_PANEL_SYNAPTICS_R63353 is not set +# CONFIG_DRM_PANEL_TDO_TL070WSH30 is not set +# CONFIG_DRM_PANEL_TPO_TD028TTEC1 is not set +# CONFIG_DRM_PANEL_TPO_TD043MTEA1 is not set +# CONFIG_DRM_PANEL_TPO_TPG110 is not set +# CONFIG_DRM_PANEL_TRULY_NT35597_WQXGA is not set +# CONFIG_DRM_PANEL_VISIONOX_R66451 is not set +# CONFIG_DRM_PANEL_VISIONOX_RM69299 is not set +# CONFIG_DRM_PANEL_VISIONOX_VTDR6130 is not set +# CONFIG_DRM_PANEL_WIDECHIPS_WS2401 is not set +# CONFIG_DRM_PANEL_XINPENG_XPP055C272 is not set +# end of Display Panels + +CONFIG_DRM_BRIDGE=y +CONFIG_DRM_PANEL_BRIDGE=y + +# +# Display Interface Bridges +# +# CONFIG_DRM_CHIPONE_ICN6211 is not set +# CONFIG_DRM_CHRONTEL_CH7033 is not set +CONFIG_DRM_DISPLAY_CONNECTOR=m +# CONFIG_DRM_ITE_IT6505 is not set +# CONFIG_DRM_LONTIUM_LT8912B is not set +# CONFIG_DRM_LONTIUM_LT9211 is not set +# CONFIG_DRM_LONTIUM_LT9611 is not set +# CONFIG_DRM_LONTIUM_LT9611UXC is not set +# CONFIG_DRM_ITE_IT66121 is not set +# CONFIG_DRM_LVDS_CODEC is not set +# CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW is not set +# CONFIG_DRM_NWL_MIPI_DSI is not set +# CONFIG_DRM_NXP_PTN3460 is not set +# CONFIG_DRM_PARADE_PS8622 is not set +# CONFIG_DRM_PARADE_PS8640 is not set +# CONFIG_DRM_SAMSUNG_DSIM is not set +# CONFIG_DRM_SIL_SII8620 is not set +# CONFIG_DRM_SII902X is not set +# CONFIG_DRM_SII9234 is not set +CONFIG_DRM_SIMPLE_BRIDGE=y +# CONFIG_DRM_THINE_THC63LVD1024 is not set +# CONFIG_DRM_TOSHIBA_TC358762 is not set +# CONFIG_DRM_TOSHIBA_TC358764 is not set +# CONFIG_DRM_TOSHIBA_TC358767 is not set +# CONFIG_DRM_TOSHIBA_TC358768 is not set +# CONFIG_DRM_TOSHIBA_TC358775 is not set +# CONFIG_DRM_TI_DLPC3433 is not set +# CONFIG_DRM_TI_TFP410 is not set +# CONFIG_DRM_TI_SN65DSI83 is not set +# CONFIG_DRM_TI_SN65DSI86 is not set +# CONFIG_DRM_TI_TPD12S015 is not set +# CONFIG_DRM_ANALOGIX_ANX6345 is not set +# CONFIG_DRM_ANALOGIX_ANX78XX is not set +CONFIG_DRM_ANALOGIX_DP=y +# CONFIG_DRM_ANALOGIX_ANX7625 is not set +# CONFIG_DRM_I2C_ADV7511 is not set +# CONFIG_DRM_CDNS_DSI is not set +# CONFIG_DRM_CDNS_MHDP8546 is not set +CONFIG_DRM_DW_HDMI=y +# CONFIG_DRM_DW_HDMI_AHB_AUDIO is not set +CONFIG_DRM_DW_HDMI_I2S_AUDIO=y +# CONFIG_DRM_DW_HDMI_GP_AUDIO is not set +CONFIG_DRM_DW_HDMI_CEC=y +CONFIG_DRM_DW_MIPI_DSI=y +# end of Display Interface Bridges + +# CONFIG_DRM_ETNAVIV is not set +# CONFIG_DRM_HISI_KIRIN is not set +# CONFIG_DRM_LOGICVC is not set +# CONFIG_DRM_ARCPGU is not set +# CONFIG_DRM_GM12U320 is not set +CONFIG_DRM_PANEL_MIPI_DBI=m +# CONFIG_DRM_SIMPLEDRM is not set +# CONFIG_TINYDRM_HX8357D is not set +# CONFIG_TINYDRM_ILI9163 is not set +# CONFIG_TINYDRM_ILI9225 is not set +# CONFIG_TINYDRM_ILI9341 is not set +# CONFIG_TINYDRM_ILI9486 is not set +# CONFIG_TINYDRM_MI0283QT is not set +# CONFIG_TINYDRM_REPAPER is not set +# CONFIG_TINYDRM_ST7586 is not set +# CONFIG_TINYDRM_ST7735R is not set +# CONFIG_DRM_PL111 is not set +# CONFIG_DRM_LIMA is not set +CONFIG_DRM_PANFROST=m +# CONFIG_DRM_PANTHOR is not set +# CONFIG_DRM_TIDSS is not set +# CONFIG_DRM_GUD is not set +# CONFIG_DRM_SSD130X is not set +# CONFIG_DRM_POWERVR is not set +# CONFIG_DRM_WERROR is not set +CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y + +# +# Frame buffer Devices +# +CONFIG_FB=y +# 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_SIMPLE is not set +# CONFIG_FB_SSD1307 is not set +CONFIG_FB_CORE=y +CONFIG_FB_NOTIFY=y +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB_DEVICE=y +CONFIG_FB_SYS_FILLRECT=y +CONFIG_FB_SYS_COPYAREA=y +CONFIG_FB_SYS_IMAGEBLIT=y +# CONFIG_FB_FOREIGN_ENDIAN is not set +CONFIG_FB_SYSMEM_FOPS=y +CONFIG_FB_DEFERRED_IO=y +CONFIG_FB_DMAMEM_HELPERS=y +CONFIG_FB_DMAMEM_HELPERS_DEFERRED=y +CONFIG_FB_SYSMEM_HELPERS=y +CONFIG_FB_SYSMEM_HELPERS_DEFERRED=y +CONFIG_FB_MODE_HELPERS=y +# CONFIG_FB_TILEBLITTING is not set +# end of Frame buffer Devices + +# +# Backlight & LCD device support +# +# CONFIG_LCD_CLASS_DEVICE is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=y +# CONFIG_BACKLIGHT_KTD253 is not set +# CONFIG_BACKLIGHT_KTD2801 is not set +# CONFIG_BACKLIGHT_KTZ8866 is not set +CONFIG_BACKLIGHT_PWM=y +# CONFIG_BACKLIGHT_QCOM_WLED is not set +# CONFIG_BACKLIGHT_ADP8860 is not set +# CONFIG_BACKLIGHT_ADP8870 is not set +# CONFIG_BACKLIGHT_LM3509 is not set +# CONFIG_BACKLIGHT_LM3630A is not set +# CONFIG_BACKLIGHT_LM3639 is not set +# CONFIG_BACKLIGHT_LP855X is not set +# CONFIG_BACKLIGHT_MP3309C is not set +# CONFIG_BACKLIGHT_GPIO is not set +# CONFIG_BACKLIGHT_LV5207LP is not set +# CONFIG_BACKLIGHT_BD6107 is not set +# CONFIG_BACKLIGHT_ARCXCNN is not set +# CONFIG_BACKLIGHT_LED is not set +# end of Backlight & LCD device support + +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_LEGACY_ACCELERATION is not set +CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +# CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER is not set +# end of Console display driver support + +# CONFIG_LOGO is not set +# end of Graphics support + +# CONFIG_DRM_ACCEL is not set +CONFIG_SOUND=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=m +CONFIG_SND_SEQ_DEVICE=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_JACK=y +CONFIG_SND_JACK_INPUT_DEV=y +# CONFIG_SND_OSSEMUL is not set +CONFIG_SND_PCM_TIMER=y +CONFIG_SND_HRTIMER=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_CTL_FAST_LOOKUP is not set +# CONFIG_SND_DEBUG is not set +# CONFIG_SND_CTL_INPUT_VALIDATION is not set +# CONFIG_SND_UTIMER is not set +CONFIG_SND_SEQUENCER=m +# CONFIG_SND_SEQ_DUMMY is not set +CONFIG_SND_SEQ_HRTIMER_DEFAULT=y +CONFIG_SND_SEQ_MIDI_EVENT=m +CONFIG_SND_SEQ_MIDI=m +# CONFIG_SND_SEQ_UMP is not set +# CONFIG_SND_DRIVERS is not set + +# +# HD-Audio +# +# end of HD-Audio + +CONFIG_SND_HDA_PREALLOC_SIZE=64 +# CONFIG_SND_SPI is not set +CONFIG_SND_USB=y +CONFIG_SND_USB_AUDIO=m +# CONFIG_SND_USB_AUDIO_MIDI_V2 is not set +CONFIG_SND_USB_AUDIO_USE_MEDIA_CONTROLLER=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_SOC_ADI is not set +# CONFIG_SND_SOC_AMD_ACP is not set +# CONFIG_SND_AMD_ACP_CONFIG is not set +# CONFIG_SND_ATMEL_SOC is not set +# CONFIG_SND_BCM63XX_I2S_WHISTLER 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_AUDMIX 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_FSL_MICFIL is not set +# CONFIG_SND_SOC_FSL_XCVR is not set +# CONFIG_SND_SOC_IMX_AUDMUX is not set +# end of SoC Audio for Freescale CPUs + +# CONFIG_SND_SOC_CHV3_I2S is not set +# CONFIG_SND_I2S_HI6210_I2S is not set +# CONFIG_SND_SOC_IMG is not set +# CONFIG_SND_SOC_MTK_BTCVSD is not set +CONFIG_SND_SOC_ROCKCHIP=y +CONFIG_SND_SOC_ROCKCHIP_I2S=y +# CONFIG_SND_SOC_ROCKCHIP_I2S_TDM is not set +CONFIG_SND_SOC_ROCKCHIP_PDM=m +# CONFIG_SND_SOC_ROCKCHIP_SPDIF is not set +# CONFIG_SND_SOC_ROCKCHIP_MAX98090 is not set +# CONFIG_SND_SOC_ROCKCHIP_RT5645 is not set +# CONFIG_SND_SOC_RK3288_HDMI_ANALOG is not set +# CONFIG_SND_SOC_RK3399_GRU_SOUND is not set +# CONFIG_SND_SOC_SOF_TOPLEVEL is not set + +# +# STMicroelectronics STM32 SOC audio support +# +# end of STMicroelectronics STM32 SOC audio support + +# CONFIG_SND_SOC_XILINX_I2S is not set +# CONFIG_SND_SOC_XILINX_AUDIO_FORMATTER is not set +# CONFIG_SND_SOC_XILINX_SPDIF 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_ADAU1372_I2C is not set +# CONFIG_SND_SOC_ADAU1372_SPI is not set +# CONFIG_SND_SOC_ADAU1701 is not set +# CONFIG_SND_SOC_ADAU1761_I2C is not set +# CONFIG_SND_SOC_ADAU1761_SPI is not set +# CONFIG_SND_SOC_ADAU7002 is not set +# CONFIG_SND_SOC_ADAU7118_HW is not set +# CONFIG_SND_SOC_ADAU7118_I2C is not set +# CONFIG_SND_SOC_AK4104 is not set +# CONFIG_SND_SOC_AK4118 is not set +# CONFIG_SND_SOC_AK4375 is not set +# CONFIG_SND_SOC_AK4458 is not set +# CONFIG_SND_SOC_AK4554 is not set +CONFIG_SND_SOC_AK4613=m +# CONFIG_SND_SOC_AK4619 is not set +# CONFIG_SND_SOC_AK4642 is not set +# CONFIG_SND_SOC_AK5386 is not set +# CONFIG_SND_SOC_AK5558 is not set +# CONFIG_SND_SOC_ALC5623 is not set +# CONFIG_SND_SOC_AUDIO_IIO_AUX is not set +# CONFIG_SND_SOC_AW8738 is not set +# CONFIG_SND_SOC_AW88395 is not set +# CONFIG_SND_SOC_AW88261 is not set +# CONFIG_SND_SOC_AW87390 is not set +# CONFIG_SND_SOC_AW88399 is not set +# CONFIG_SND_SOC_BD28623 is not set +# CONFIG_SND_SOC_BT_SCO is not set +# CONFIG_SND_SOC_CHV3_CODEC is not set +# CONFIG_SND_SOC_CS35L32 is not set +# CONFIG_SND_SOC_CS35L33 is not set +# CONFIG_SND_SOC_CS35L34 is not set +# CONFIG_SND_SOC_CS35L35 is not set +# CONFIG_SND_SOC_CS35L36 is not set +# CONFIG_SND_SOC_CS35L41_SPI is not set +# CONFIG_SND_SOC_CS35L41_I2C is not set +# CONFIG_SND_SOC_CS35L45_SPI is not set +# CONFIG_SND_SOC_CS35L45_I2C is not set +# CONFIG_SND_SOC_CS35L56_I2C is not set +# CONFIG_SND_SOC_CS35L56_SPI is not set +# CONFIG_SND_SOC_CS42L42 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_CS42L83 is not set +# CONFIG_SND_SOC_CS4234 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_CS43130 is not set +# CONFIG_SND_SOC_CS4341 is not set +# CONFIG_SND_SOC_CS4349 is not set +# CONFIG_SND_SOC_CS53L30 is not set +# CONFIG_SND_SOC_CS530X_I2C is not set +# CONFIG_SND_SOC_CX2072X is not set +# CONFIG_SND_SOC_DA7213 is not set +CONFIG_SND_SOC_DMIC=y +CONFIG_SND_SOC_HDMI_CODEC=y +# CONFIG_SND_SOC_ES7134 is not set +# CONFIG_SND_SOC_ES7241 is not set +# CONFIG_SND_SOC_ES8311 is not set +CONFIG_SND_SOC_ES8316=y +# CONFIG_SND_SOC_ES8326 is not set +CONFIG_SND_SOC_ES8328=y +CONFIG_SND_SOC_ES8328_I2C=y +CONFIG_SND_SOC_ES8328_SPI=y +# CONFIG_SND_SOC_GTM601 is not set +# CONFIG_SND_SOC_HDA is not set +# CONFIG_SND_SOC_ICS43432 is not set +# CONFIG_SND_SOC_IDT821034 is not set +# CONFIG_SND_SOC_INNO_RK3036 is not set +# CONFIG_SND_SOC_MAX98088 is not set +# CONFIG_SND_SOC_MAX98090 is not set +CONFIG_SND_SOC_MAX98357A=y +# CONFIG_SND_SOC_MAX98504 is not set +# CONFIG_SND_SOC_MAX9867 is not set +# CONFIG_SND_SOC_MAX98927 is not set +# CONFIG_SND_SOC_MAX98520 is not set +# CONFIG_SND_SOC_MAX98373_I2C is not set +# CONFIG_SND_SOC_MAX98388 is not set +# CONFIG_SND_SOC_MAX98390 is not set +# CONFIG_SND_SOC_MAX98396 is not set +# CONFIG_SND_SOC_MAX9860 is not set +# CONFIG_SND_SOC_MSM8916_WCD_ANALOG is not set +# CONFIG_SND_SOC_MSM8916_WCD_DIGITAL is not set +# CONFIG_SND_SOC_PCM1681 is not set +# CONFIG_SND_SOC_PCM1789_I2C is not set +# CONFIG_SND_SOC_PCM179X_I2C is not set +# CONFIG_SND_SOC_PCM179X_SPI is not set +# CONFIG_SND_SOC_PCM186X_I2C is not set +# CONFIG_SND_SOC_PCM186X_SPI is not set +# CONFIG_SND_SOC_PCM3060_I2C is not set +# CONFIG_SND_SOC_PCM3060_SPI is not set +# CONFIG_SND_SOC_PCM3168A_I2C is not set +# CONFIG_SND_SOC_PCM3168A_SPI is not set +# CONFIG_SND_SOC_PCM5102A is not set +# CONFIG_SND_SOC_PCM512x_I2C is not set +# CONFIG_SND_SOC_PCM512x_SPI is not set +# CONFIG_SND_SOC_PCM6240 is not set +# CONFIG_SND_SOC_PEB2466 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_RT5659 is not set +# CONFIG_SND_SOC_RT9120 is not set +# CONFIG_SND_SOC_RTQ9128 is not set +# CONFIG_SND_SOC_SGTL5000 is not set +CONFIG_SND_SOC_SIMPLE_AMPLIFIER=m +# CONFIG_SND_SOC_SIMPLE_MUX is not set +# CONFIG_SND_SOC_SMA1303 is not set +CONFIG_SND_SOC_SPDIF=y +# CONFIG_SND_SOC_SRC4XXX_I2C is not set +# CONFIG_SND_SOC_SSM2305 is not set +# CONFIG_SND_SOC_SSM2518 is not set +# CONFIG_SND_SOC_SSM2602_SPI is not set +# CONFIG_SND_SOC_SSM2602_I2C is not set +# CONFIG_SND_SOC_SSM3515 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_TAS2562 is not set +# CONFIG_SND_SOC_TAS2764 is not set +# CONFIG_SND_SOC_TAS2770 is not set +# CONFIG_SND_SOC_TAS2780 is not set +# CONFIG_SND_SOC_TAS2781_I2C is not set +# CONFIG_SND_SOC_TAS5086 is not set +# CONFIG_SND_SOC_TAS571X is not set +# CONFIG_SND_SOC_TAS5720 is not set +# CONFIG_SND_SOC_TAS5805M is not set +# CONFIG_SND_SOC_TAS6424 is not set +# CONFIG_SND_SOC_TDA7419 is not set +# CONFIG_SND_SOC_TFA9879 is not set +# CONFIG_SND_SOC_TFA989X is not set +# CONFIG_SND_SOC_TLV320ADC3XXX 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_TLV320AIC32X4_I2C is not set +# CONFIG_SND_SOC_TLV320AIC32X4_SPI is not set +# CONFIG_SND_SOC_TLV320AIC3X_I2C is not set +# CONFIG_SND_SOC_TLV320AIC3X_SPI is not set +# CONFIG_SND_SOC_TLV320ADCX140 is not set +CONFIG_SND_SOC_TS3A227E=m +# CONFIG_SND_SOC_TSCS42XX is not set +# CONFIG_SND_SOC_TSCS454 is not set +# CONFIG_SND_SOC_UDA1334 is not set +# CONFIG_SND_SOC_WM8510 is not set +# CONFIG_SND_SOC_WM8523 is not set +# CONFIG_SND_SOC_WM8524 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_I2C is not set +# CONFIG_SND_SOC_WM8731_SPI 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_WM8782 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_WM8904 is not set +# CONFIG_SND_SOC_WM8940 is not set +# CONFIG_SND_SOC_WM8960 is not set +# CONFIG_SND_SOC_WM8961 is not set +# CONFIG_SND_SOC_WM8962 is not set +# CONFIG_SND_SOC_WM8974 is not set +# CONFIG_SND_SOC_WM8978 is not set +# CONFIG_SND_SOC_WM8985 is not set +# CONFIG_SND_SOC_ZL38060 is not set +# CONFIG_SND_SOC_MAX9759 is not set +# CONFIG_SND_SOC_MT6351 is not set +# CONFIG_SND_SOC_MT6357 is not set +# CONFIG_SND_SOC_MT6358 is not set +# CONFIG_SND_SOC_MT6660 is not set +# CONFIG_SND_SOC_NAU8315 is not set +# CONFIG_SND_SOC_NAU8540 is not set +# CONFIG_SND_SOC_NAU8810 is not set +# CONFIG_SND_SOC_NAU8821 is not set +# CONFIG_SND_SOC_NAU8822 is not set +# CONFIG_SND_SOC_NAU8824 is not set +# CONFIG_SND_SOC_TPA6130A2 is not set +# CONFIG_SND_SOC_LPASS_WSA_MACRO is not set +# CONFIG_SND_SOC_LPASS_VA_MACRO is not set +# CONFIG_SND_SOC_LPASS_RX_MACRO is not set +# CONFIG_SND_SOC_LPASS_TX_MACRO is not set +# end of CODEC drivers + +CONFIG_SND_SIMPLE_CARD_UTILS=y +CONFIG_SND_SIMPLE_CARD=y +# CONFIG_SND_AUDIO_GRAPH_CARD is not set +# CONFIG_SND_AUDIO_GRAPH_CARD2 is not set +# CONFIG_SND_TEST_COMPONENT is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +CONFIG_HID_BATTERY_STRENGTH=y +CONFIG_HIDRAW=y +CONFIG_UHID=y +CONFIG_HID_GENERIC=y + +# +# Special HID drivers +# +CONFIG_HID_A4TECH=m +# CONFIG_HID_ACCUTOUCH is not set +CONFIG_HID_ACRUX=m +CONFIG_HID_ACRUX_FF=y +CONFIG_HID_APPLE=m +CONFIG_HID_APPLEIR=m +# CONFIG_HID_ASUS is not set +CONFIG_HID_AUREAL=m +CONFIG_HID_BELKIN=m +CONFIG_HID_BETOP_FF=m +# CONFIG_HID_BIGBEN_FF is not set +CONFIG_HID_CHERRY=m +CONFIG_HID_CHICONY=m +CONFIG_HID_CORSAIR=m +# CONFIG_HID_COUGAR is not set +# CONFIG_HID_MACALLY is not set +CONFIG_HID_PRODIKEYS=m +# CONFIG_HID_CMEDIA is not set +# CONFIG_HID_CP2112 is not set +# CONFIG_HID_CREATIVE_SB0540 is not set +CONFIG_HID_CYPRESS=m +CONFIG_HID_DRAGONRISE=m +CONFIG_DRAGONRISE_FF=y +CONFIG_HID_EMS_FF=m +# CONFIG_HID_ELAN is not set +CONFIG_HID_ELECOM=m +CONFIG_HID_ELO=m +# CONFIG_HID_EVISION is not set +CONFIG_HID_EZKEY=m +# CONFIG_HID_FT260 is not set +CONFIG_HID_GEMBIRD=m +CONFIG_HID_GFRM=m +# CONFIG_HID_GLORIOUS is not set +CONFIG_HID_HOLTEK=m +CONFIG_HOLTEK_FF=y +# CONFIG_HID_GOODIX_SPI is not set +# CONFIG_HID_GOOGLE_STADIA_FF is not set +# CONFIG_HID_VIVALDI is not set +CONFIG_HID_GT683R=m +CONFIG_HID_KEYTOUCH=m +CONFIG_HID_KYE=m +CONFIG_HID_UCLOGIC=m +CONFIG_HID_WALTOP=m +# CONFIG_HID_VIEWSONIC is not set +# CONFIG_HID_VRC2 is not set +# CONFIG_HID_XIAOMI is not set +CONFIG_HID_GYRATION=m +CONFIG_HID_ICADE=m +# CONFIG_HID_ITE is not set +# CONFIG_HID_JABRA is not set +CONFIG_HID_TWINHAN=m +CONFIG_HID_KENSINGTON=m +CONFIG_HID_LCPOWER=m +CONFIG_HID_LED=m +CONFIG_HID_LENOVO=m +# CONFIG_HID_LETSKETCH is not set +CONFIG_HID_LOGITECH=m +# CONFIG_HID_LOGITECH_DJ is not set +CONFIG_HID_LOGITECH_HIDPP=m +CONFIG_LOGITECH_FF=y +CONFIG_LOGIRUMBLEPAD2_FF=y +CONFIG_LOGIG940_FF=y +CONFIG_LOGIWHEELS_FF=y +CONFIG_HID_MAGICMOUSE=m +# CONFIG_HID_MALTRON is not set +# CONFIG_HID_MAYFLASH is not set +# CONFIG_HID_MEGAWORLD_FF is not set +# CONFIG_HID_REDRAGON is not set +CONFIG_HID_MICROSOFT=m +CONFIG_HID_MONTEREY=m +CONFIG_HID_MULTITOUCH=m +# CONFIG_HID_NINTENDO is not set +# CONFIG_HID_NTI is not set +CONFIG_HID_NTRIG=m +# CONFIG_HID_NVIDIA_SHIELD is not set +CONFIG_HID_ORTEK=m +CONFIG_HID_PANTHERLORD=m +CONFIG_PANTHERLORD_FF=y +CONFIG_HID_PENMOUNT=m +CONFIG_HID_PETALYNX=m +CONFIG_HID_PICOLCD=m +CONFIG_HID_PICOLCD_FB=y +CONFIG_HID_PICOLCD_BACKLIGHT=y +CONFIG_HID_PICOLCD_LEDS=y +CONFIG_HID_PLANTRONICS=m +# CONFIG_HID_PXRC is not set +# CONFIG_HID_RAZER is not set +CONFIG_HID_PRIMAX=m +# CONFIG_HID_RETRODE is not set +CONFIG_HID_ROCCAT=m +CONFIG_HID_SAITEK=m +CONFIG_HID_SAMSUNG=m +# CONFIG_HID_SEMITEK is not set +# CONFIG_HID_SIGMAMICRO is not set +CONFIG_HID_SONY=m +CONFIG_SONY_FF=y +CONFIG_HID_SPEEDLINK=m +# CONFIG_HID_STEAM is not set +CONFIG_HID_STEELSERIES=m +CONFIG_HID_SUNPLUS=m +CONFIG_HID_RMI=m +CONFIG_HID_GREENASIA=m +CONFIG_GREENASIA_FF=y +CONFIG_HID_SMARTJOYPLUS=m +CONFIG_SMARTJOYPLUS_FF=y +CONFIG_HID_TIVO=m +CONFIG_HID_TOPSEED=m +# CONFIG_HID_TOPRE is not set +CONFIG_HID_THINGM=m +CONFIG_HID_THRUSTMASTER=m +CONFIG_THRUSTMASTER_FF=y +# CONFIG_HID_UDRAW_PS3 is not set +# CONFIG_HID_U2FZERO is not set +CONFIG_HID_WACOM=m +CONFIG_HID_WIIMOTE=m +# CONFIG_HID_WINWING is not set +CONFIG_HID_XINMO=m +CONFIG_HID_ZEROPLUS=m +CONFIG_ZEROPLUS_FF=y +CONFIG_HID_ZYDACRON=m +CONFIG_HID_SENSOR_HUB=m +CONFIG_HID_SENSOR_CUSTOM_SENSOR=m +CONFIG_HID_ALPS=m +# CONFIG_HID_MCP2200 is not set +# CONFIG_HID_MCP2221 is not set +# end of Special HID drivers + +# +# HID-BPF support +# +# end of HID-BPF support + +# +# USB HID support +# +CONFIG_USB_HID=y +# CONFIG_HID_PID is not set +CONFIG_USB_HIDDEV=y +# end of USB HID support + +CONFIG_I2C_HID=y +CONFIG_I2C_HID_OF=y +# CONFIG_I2C_HID_OF_ELAN is not set +# CONFIG_I2C_HID_OF_GOODIX is not set +CONFIG_I2C_HID_CORE=y +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_COMMON=y +# CONFIG_USB_LED_TRIG is not set +CONFIG_USB_ULPI_BUS=y +# CONFIG_USB_CONN_GPIO is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y + +# +# Miscellaneous USB options +# +CONFIG_USB_DEFAULT_PERSIST=y +# CONFIG_USB_FEW_INIT_RETRIES is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +CONFIG_USB_OTG=y +# CONFIG_USB_OTG_PRODUCTLIST is not set +# CONFIG_USB_OTG_DISABLE_EXTERNAL_HUB is not set +# CONFIG_USB_OTG_FSM is not set +# CONFIG_USB_LEDS_TRIGGER_USBPORT is not set +CONFIG_USB_AUTOSUSPEND_DELAY=2 +CONFIG_USB_DEFAULT_AUTHORIZATION_MODE=1 +# CONFIG_USB_MON 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_FSL is not set +CONFIG_USB_EHCI_HCD_PLATFORM=y +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_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_TEST_MODE is not set + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=y +# CONFIG_USB_PRINTER is not set +CONFIG_USB_WDM=m +# 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 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=y + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USBIP_CORE is not set + +# +# USB dual-mode controller drivers +# +# CONFIG_USB_CDNS_SUPPORT is not set +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_DWC3 is not set +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_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 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_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_APPLE_MFI_FASTCHARGE 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 is not set +# CONFIG_USB_HUB_USB251XB is not set +# CONFIG_USB_HSIC_USB3503 is not set +# CONFIG_USB_HSIC_USB4604 is not set +# CONFIG_USB_LINK_LAYER_TEST is not set +# CONFIG_USB_CHAOSKEY is not set +# CONFIG_USB_ONBOARD_DEV is not set + +# +# USB Physical Layer drivers +# +CONFIG_USB_PHY=y +CONFIG_NOP_USB_XCEIV=y +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_USB_ISP1301 is not set +CONFIG_USB_ULPI=y +CONFIG_USB_ULPI_VIEWPORT=y +# end of USB Physical Layer drivers + +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_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_SNP_UDC_PLAT 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_MAX3420_UDC is not set +# CONFIG_USB_DUMMY_HCD is not set +# end of USB Peripheral Controller + +CONFIG_USB_LIBCOMPOSITE=y +CONFIG_USB_U_ETHER=y +CONFIG_USB_F_NCM=y +CONFIG_USB_F_ECM=y +CONFIG_USB_F_RNDIS=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 is not set +# CONFIG_USB_CONFIGFS_OBEX is not set +CONFIG_USB_CONFIGFS_NCM=y +CONFIG_USB_CONFIGFS_ECM=y +# CONFIG_USB_CONFIGFS_ECM_SUBSET is not set +CONFIG_USB_CONFIGFS_RNDIS=y +# 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_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_MIDI2 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 + +# +# USB Gadget precomposed configurations +# +# 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 +# CONFIG_USB_RAW_GADGET is not set +# end of USB Gadget precomposed configurations + +# CONFIG_TYPEC is not set +CONFIG_USB_ROLE_SWITCH=y +CONFIG_MMC=y +CONFIG_PWRSEQ_EMMC=y +# CONFIG_PWRSEQ_SD8787 is not set +CONFIG_PWRSEQ_SIMPLE=y +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=32 +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_ARMMMCI=y +CONFIG_MMC_STM32_SDMMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_OF_ARASAN=y +# CONFIG_MMC_SDHCI_OF_AT91 is not set +# CONFIG_MMC_SDHCI_OF_DWCMSHC is not set +# CONFIG_MMC_SDHCI_CADENCE is not set +# CONFIG_MMC_SDHCI_F_SDH30 is not set +# CONFIG_MMC_SDHCI_MILBEAUT is not set +CONFIG_MMC_SPI=y +CONFIG_MMC_DW=y +CONFIG_MMC_DW_PLTFM=y +# CONFIG_MMC_DW_BLUEFIELD is not set +# CONFIG_MMC_DW_EXYNOS is not set +# CONFIG_MMC_DW_HI3798CV200 is not set +# CONFIG_MMC_DW_HI3798MV200 is not set +CONFIG_MMC_DW_K3=y +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_CQHCI=y +# CONFIG_MMC_HSQ is not set +# CONFIG_MMC_MTK is not set +# CONFIG_MMC_SDHCI_XENON is not set +# CONFIG_SCSI_UFSHCD is not set +# CONFIG_MEMSTICK is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_CLASS_FLASH=m +# CONFIG_LEDS_CLASS_MULTICOLOR is not set +# CONFIG_LEDS_BRIGHTNESS_HW_CHANGED is not set + +# +# LED drivers +# +# CONFIG_LEDS_AN30259A is not set +# CONFIG_LEDS_AW200XX is not set +# CONFIG_LEDS_AW2013 is not set +# CONFIG_LEDS_BCM6328 is not set +# CONFIG_LEDS_BCM6358 is not set +# CONFIG_LEDS_CR0014114 is not set +# CONFIG_LEDS_EL15203000 is not set +# CONFIG_LEDS_LM3530 is not set +# CONFIG_LEDS_LM3532 is not set +# CONFIG_LEDS_LM3642 is not set +# CONFIG_LEDS_LM3692X is not set +# CONFIG_LEDS_PCA9532 is not set +CONFIG_LEDS_GPIO=y +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_LP3952 is not set +# CONFIG_LEDS_LP8860 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_PCA963X is not set +# CONFIG_LEDS_PCA995X is not set +# CONFIG_LEDS_DAC124S085 is not set +CONFIG_LEDS_PWM=y +# CONFIG_LEDS_REGULATOR is not set +# CONFIG_LEDS_BD2606MVV 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_IS31FL319X 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=y +# CONFIG_LEDS_MLXREG is not set +# CONFIG_LEDS_USER is not set +# CONFIG_LEDS_SPI_BYTE is not set +# CONFIG_LEDS_LM3697 is not set + +# +# Flash and Torch LED drivers +# +# CONFIG_LEDS_AAT1290 is not set +# CONFIG_LEDS_AS3645A is not set +# CONFIG_LEDS_KTD2692 is not set +# CONFIG_LEDS_LM3601X is not set +# CONFIG_LEDS_RT4505 is not set +# CONFIG_LEDS_RT8515 is not set +# CONFIG_LEDS_SGM3140 is not set +# CONFIG_LEDS_SY7802 is not set + +# +# RGB LED drivers +# + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_ONESHOT=y +# CONFIG_LEDS_TRIGGER_MTD is not set +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set +CONFIG_LEDS_TRIGGER_CPU=y +CONFIG_LEDS_TRIGGER_ACTIVITY=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_PANIC=y +# CONFIG_LEDS_TRIGGER_NETDEV is not set +# CONFIG_LEDS_TRIGGER_PATTERN is not set +# CONFIG_LEDS_TRIGGER_TTY is not set +# CONFIG_LEDS_TRIGGER_INPUT_EVENTS is not set + +# +# Simple LED drivers +# +# CONFIG_ACCESSIBILITY is not set +# CONFIG_INFINIBAND is not set +CONFIG_EDAC_SUPPORT=y +CONFIG_EDAC=y +CONFIG_EDAC_LEGACY_SYSFS=y +# CONFIG_EDAC_DEBUG is not set +# CONFIG_EDAC_XGENE is not set +# CONFIG_EDAC_DMC520 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 +CONFIG_RTC_NVMEM=y + +# +# 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_ABEOZ9 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_HYM8563 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_MAX31335 is not set +CONFIG_RTC_DRV_MAX77686=y +# CONFIG_RTC_DRV_NCT3018Y is not set +CONFIG_RTC_DRV_RK808=y +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_ISL12022 is not set +# CONFIG_RTC_DRV_ISL12026 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8523 is not set +# CONFIG_RTC_DRV_PCF85063 is not set +# CONFIG_RTC_DRV_PCF85363 is not set +# CONFIG_RTC_DRV_PCF8563 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_RX8010 is not set +# CONFIG_RTC_DRV_RX8111 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_RV3028 is not set +# CONFIG_RTC_DRV_RV3032 is not set +# CONFIG_RTC_DRV_RV8803 is not set +CONFIG_RTC_DRV_S5M=y +# CONFIG_RTC_DRV_SD2405AL is not set +# CONFIG_RTC_DRV_SD3078 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1302 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_MAX6916 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RX4581 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_PCF2123 is not set +# CONFIG_RTC_DRV_MCP795 is not set +CONFIG_RTC_I2C_AND_SPI=y + +# +# SPI and I2C RTC drivers +# +CONFIG_RTC_DRV_DS3232=y +CONFIG_RTC_DRV_DS3232_HWMON=y +# CONFIG_RTC_DRV_PCF2127 is not set +# CONFIG_RTC_DRV_RV3029C2 is not set +# CONFIG_RTC_DRV_RX6110 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_RP5C01 is not set +# CONFIG_RTC_DRV_OPTEE 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=y +# CONFIG_RTC_DRV_CADENCE is not set +# CONFIG_RTC_DRV_FTRTC010 is not set +# CONFIG_RTC_DRV_R7301 is not set + +# +# HID Sensor RTC drivers +# +# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set +# CONFIG_RTC_DRV_GOLDFISH is not set +CONFIG_DMADEVICES=y +# CONFIG_DMADEVICES_DEBUG is not set + +# +# DMA Devices +# +CONFIG_DMA_ENGINE=y +CONFIG_DMA_OF=y +# CONFIG_ALTERA_MSGDMA is not set +# CONFIG_AMBA_PL08X is not set +# CONFIG_BCM_SBA_RAID is not set +# CONFIG_DW_AXI_DMAC is not set +# CONFIG_FSL_EDMA is not set +# CONFIG_FSL_QDMA is not set +# CONFIG_INTEL_IDMA64 is not set +# CONFIG_MV_XOR_V2 is not set +CONFIG_PL330_DMA=y +# CONFIG_XILINX_DMA is not set +# CONFIG_XILINX_XDMA is not set +# CONFIG_XILINX_ZYNQMP_DMA is not set +# CONFIG_XILINX_ZYNQMP_DPDMA is not set +# CONFIG_AMD_QDMA is not set +# CONFIG_QCOM_HIDMA_MGMT is not set +# CONFIG_QCOM_HIDMA is not set +# CONFIG_DW_DMAC is not set +# CONFIG_SF_PDMA is not set + +# +# DMA Clients +# +# CONFIG_ASYNC_TX_DMA is not set +# CONFIG_DMATEST is not set + +# +# DMABUF options +# +CONFIG_SYNC_FILE=y +# CONFIG_SW_SYNC is not set +# CONFIG_UDMABUF is not set +# CONFIG_DMABUF_MOVE_NOTIFY is not set +# CONFIG_DMABUF_DEBUG is not set +# CONFIG_DMABUF_SELFTESTS is not set +CONFIG_DMABUF_HEAPS=y +# CONFIG_DMABUF_SYSFS_STATS is not set +CONFIG_DMABUF_HEAPS_SYSTEM=y +CONFIG_DMABUF_HEAPS_CMA=y +# end of DMABUF options + +# CONFIG_UIO is not set +CONFIG_VFIO=y +CONFIG_VFIO_GROUP=y +CONFIG_VFIO_CONTAINER=y +CONFIG_VFIO_IOMMU_TYPE1=y +# CONFIG_VFIO_NOIOMMU is not set +# CONFIG_VFIO_DEBUGFS is not set + +# +# VFIO support for platform devices +# +# CONFIG_VFIO_PLATFORM is not set +# CONFIG_VFIO_AMBA is not set +# end of VFIO support for platform devices + +# CONFIG_VIRT_DRIVERS is not set +# CONFIG_VIRTIO_MENU is not set +# CONFIG_VDPA is not set +CONFIG_VHOST_MENU=y +# CONFIG_VHOST_NET is not set +# CONFIG_VHOST_CROSS_ENDIAN_LEGACY is not set +CONFIG_VHOST_ENABLE_FORK_OWNER_CONTROL=y + +# +# Microsoft Hyper-V guest support +# +# end of Microsoft Hyper-V guest support + +# CONFIG_GREYBUS is not set +# CONFIG_COMEDI is not set +CONFIG_STAGING=y +# CONFIG_RTLLIB is not set +CONFIG_RTL8723BS=m +# CONFIG_VT6656 is not set + +# +# IIO staging drivers +# + +# +# Accelerometers +# +# CONFIG_ADIS16203 is not set +# CONFIG_ADIS16240 is not set +# end of Accelerometers + +# +# Analog to digital converters +# +# CONFIG_AD7816 is not set +# end of Analog to digital converters + +# +# Analog digital bi-direction converters +# +# CONFIG_ADT7316 is not set +# end of Analog digital bi-direction converters + +# +# Direct Digital Synthesis +# +# CONFIG_AD9832 is not set +# CONFIG_AD9834 is not set +# end of Direct Digital Synthesis + +# +# Network Analyzer, Impedance Converters +# +# CONFIG_AD5933 is not set +# end of Network Analyzer, Impedance Converters +# end of IIO staging drivers + +CONFIG_STAGING_MEDIA=y +# CONFIG_VIDEO_MAX96712 is not set +CONFIG_VIDEO_ROCKCHIP_VDEC=m + +# +# StarFive media platform drivers +# +# CONFIG_STAGING_MEDIA_DEPRECATED is not set +# CONFIG_LTE_GDM724X is not set +# CONFIG_FB_TFT is not set +# CONFIG_XIL_AXIS_FIFO is not set +# CONFIG_FIELDBUS_DEV is not set +# CONFIG_GOLDFISH is not set +# CONFIG_CHROME_PLATFORMS is not set +# CONFIG_MELLANOX_PLATFORM is not set +# CONFIG_SURFACE_PLATFORMS is not set +CONFIG_ARM64_PLATFORM_DEVICES=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_CLK_PREPARE=y +CONFIG_COMMON_CLK=y + +# +# Clock driver for ARM Reference designs +# +# CONFIG_CLK_ICST is not set +# CONFIG_CLK_SP810 is not set +# end of Clock driver for ARM Reference designs + +# CONFIG_LMK04832 is not set +# CONFIG_COMMON_CLK_MAX77686 is not set +# CONFIG_COMMON_CLK_MAX9485 is not set +CONFIG_COMMON_CLK_RK808=y +# CONFIG_COMMON_CLK_SCMI is not set +CONFIG_COMMON_CLK_SCPI=y +# CONFIG_COMMON_CLK_SI5341 is not set +# CONFIG_COMMON_CLK_SI5351 is not set +# CONFIG_COMMON_CLK_SI514 is not set +# CONFIG_COMMON_CLK_SI544 is not set +# CONFIG_COMMON_CLK_SI570 is not set +# CONFIG_COMMON_CLK_CDCE706 is not set +# CONFIG_COMMON_CLK_CDCE925 is not set +CONFIG_COMMON_CLK_CS2000_CP=y +CONFIG_COMMON_CLK_S2MPS11=y +# CONFIG_COMMON_CLK_AXI_CLKGEN is not set +CONFIG_COMMON_CLK_XGENE=y +CONFIG_COMMON_CLK_PWM=y +# CONFIG_COMMON_CLK_RS9_PCIE is not set +# CONFIG_COMMON_CLK_SI521XX is not set +# CONFIG_COMMON_CLK_VC3 is not set +# CONFIG_COMMON_CLK_VC5 is not set +# CONFIG_COMMON_CLK_VC7 is not set +# CONFIG_COMMON_CLK_FIXED_MMIO is not set +CONFIG_COMMON_CLK_ROCKCHIP=y +CONFIG_CLK_PX30=y +CONFIG_CLK_RK3308=y +CONFIG_CLK_RK3328=y +CONFIG_CLK_RK3368=y +CONFIG_CLK_RK3399=y +CONFIG_CLK_RK3568=y +CONFIG_CLK_RK3576=y +CONFIG_CLK_RK3588=y +# CONFIG_XILINX_VCU is not set +# CONFIG_COMMON_CLK_XLNX_CLKWZRD is not set +CONFIG_HWSPINLOCK=y + +# +# Clock Source drivers +# +CONFIG_TIMER_OF=y +CONFIG_TIMER_PROBE=y +CONFIG_CLKSRC_MMIO=y +CONFIG_ROCKCHIP_TIMER=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND=y +CONFIG_FSL_ERRATUM_A008585=y +CONFIG_HISILICON_ERRATUM_161010101=y +CONFIG_ARM64_ERRATUM_858921=y +# CONFIG_ARM_TIMER_SP804 is not set +# end of Clock Source drivers + +CONFIG_MAILBOX=y +CONFIG_ARM_MHU=y +# CONFIG_ARM_MHU_V2 is not set +# CONFIG_ARM_MHU_V3 is not set +CONFIG_PLATFORM_MHU=y +# CONFIG_PL320_MBOX is not set +CONFIG_ROCKCHIP_MBOX=y +# CONFIG_ALTERA_MBOX is not set +# CONFIG_MAILBOX_TEST is not set +CONFIG_IOMMU_IOVA=y +CONFIG_IOMMU_API=y +CONFIG_IOMMU_SUPPORT=y + +# +# Generic IOMMU Pagetable Support +# +CONFIG_IOMMU_IO_PGTABLE=y +CONFIG_IOMMU_IO_PGTABLE_LPAE=y +# CONFIG_IOMMU_IO_PGTABLE_LPAE_SELFTEST is not set +# CONFIG_IOMMU_IO_PGTABLE_ARMV7S is not set +# CONFIG_IOMMU_IO_PGTABLE_DART is not set +# end of Generic IOMMU Pagetable Support + +# CONFIG_IOMMU_DEBUGFS is not set +# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set +CONFIG_IOMMU_DEFAULT_DMA_LAZY=y +# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set +CONFIG_OF_IOMMU=y +CONFIG_IOMMU_DMA=y +# CONFIG_IOMMUFD is not set +CONFIG_ROCKCHIP_IOMMU=y +CONFIG_ARM_SMMU=y +# CONFIG_ARM_SMMU_LEGACY_DT_BINDINGS is not set +CONFIG_ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT=y +CONFIG_ARM_SMMU_V3=y +# CONFIG_ARM_SMMU_V3_SVA is not set + +# +# Remoteproc drivers +# +# CONFIG_REMOTEPROC is not set +# end of Remoteproc drivers + +# +# Rpmsg drivers +# +# CONFIG_RPMSG_QCOM_GLINK_RPM is not set +# CONFIG_RPMSG_VIRTIO is not set +# end of Rpmsg drivers + +# CONFIG_SOUNDWIRE is not set + +# +# SOC (System On Chip) specific Drivers +# + +# +# Amlogic SoC drivers +# +# end of Amlogic SoC drivers + +# +# Broadcom SoC drivers +# +# end of Broadcom SoC drivers + +# +# NXP/Freescale QorIQ SoC drivers +# +# CONFIG_QUICC_ENGINE is not set +# CONFIG_FSL_RCPM is not set +# end of NXP/Freescale QorIQ SoC drivers + +# +# fujitsu SoC drivers +# +# end of fujitsu SoC drivers + +# +# i.MX SoC drivers +# +# end of i.MX SoC drivers + +# +# Enable LiteX SoC Builder specific drivers +# +# CONFIG_LITEX_SOC_CONTROLLER is not set +# end of Enable LiteX SoC Builder specific drivers + +# CONFIG_WPCM450_SOC is not set + +# +# Qualcomm SoC drivers +# +# CONFIG_QCOM_PBS is not set +# end of Qualcomm SoC drivers + +CONFIG_ROCKCHIP_GRF=y +CONFIG_ROCKCHIP_IODOMAIN=y +# CONFIG_SOC_TI is not set + +# +# Xilinx SoC drivers +# +# end of Xilinx SoC drivers +# end of SOC (System On Chip) specific Drivers + +# +# PM Domains +# + +# +# Amlogic PM Domains +# +# end of Amlogic PM Domains + +CONFIG_ARM_SCMI_PERF_DOMAIN=m +CONFIG_ARM_SCMI_POWER_DOMAIN=m +CONFIG_ARM_SCPI_POWER_DOMAIN=y + +# +# Broadcom PM Domains +# +# end of Broadcom PM Domains + +# +# i.MX PM Domains +# +# end of i.MX PM Domains + +# +# Qualcomm PM Domains +# +# end of Qualcomm PM Domains + +CONFIG_ROCKCHIP_PM_DOMAINS=y +# end of PM Domains + +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 +CONFIG_DEVFREQ_GOV_PASSIVE=y + +# +# DEVFREQ Drivers +# +CONFIG_ARM_RK3399_DMC_DEVFREQ=y +CONFIG_PM_DEVFREQ_EVENT=y +CONFIG_DEVFREQ_EVENT_ROCKCHIP_DFI=y +CONFIG_EXTCON=y + +# +# Extcon Device Drivers +# +# CONFIG_EXTCON_ADC_JACK is not set +# CONFIG_EXTCON_FSA9480 is not set +# CONFIG_EXTCON_GPIO is not set +# CONFIG_EXTCON_LC824206XA is not set +# CONFIG_EXTCON_MAX3355 is not set +# CONFIG_EXTCON_PTN5150 is not set +# CONFIG_EXTCON_RT8973A is not set +# CONFIG_EXTCON_SM5502 is not set +CONFIG_EXTCON_USB_GPIO=y +# CONFIG_MEMORY is not set +CONFIG_IIO=y +CONFIG_IIO_BUFFER=y +CONFIG_IIO_BUFFER_CB=y +# CONFIG_IIO_BUFFER_DMA is not set +# CONFIG_IIO_BUFFER_DMAENGINE is not set +# CONFIG_IIO_BUFFER_HW_CONSUMER is not set +CONFIG_IIO_KFIFO_BUF=y +CONFIG_IIO_TRIGGERED_BUFFER=y +# CONFIG_IIO_CONFIGFS is not set +CONFIG_IIO_TRIGGER=y +CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 +# CONFIG_IIO_SW_DEVICE is not set +# CONFIG_IIO_SW_TRIGGER is not set +# CONFIG_IIO_TRIGGERED_EVENT is not set + +# +# Accelerometers +# +# CONFIG_ADIS16201 is not set +# CONFIG_ADIS16209 is not set +# CONFIG_ADXL313_I2C is not set +# CONFIG_ADXL313_SPI is not set +# CONFIG_ADXL345_I2C is not set +# CONFIG_ADXL345_SPI is not set +# CONFIG_ADXL355_I2C is not set +# CONFIG_ADXL355_SPI is not set +# CONFIG_ADXL367_SPI is not set +# CONFIG_ADXL367_I2C is not set +# CONFIG_ADXL372_SPI is not set +# CONFIG_ADXL372_I2C is not set +# CONFIG_ADXL380_SPI is not set +# CONFIG_ADXL380_I2C is not set +# CONFIG_BMA180 is not set +# CONFIG_BMA220 is not set +# CONFIG_BMA400 is not set +# CONFIG_BMC150_ACCEL is not set +# CONFIG_BMI088_ACCEL is not set +# CONFIG_DA280 is not set +# CONFIG_DA311 is not set +# CONFIG_DMARD06 is not set +# CONFIG_DMARD09 is not set +# CONFIG_DMARD10 is not set +# CONFIG_FXLS8962AF_I2C is not set +# CONFIG_FXLS8962AF_SPI is not set +# CONFIG_HID_SENSOR_ACCEL_3D is not set +# CONFIG_IIO_ST_ACCEL_3AXIS is not set +# CONFIG_IIO_KX022A_SPI is not set +# CONFIG_IIO_KX022A_I2C is not set +# CONFIG_KXSD9 is not set +# CONFIG_KXCJK1013 is not set +# CONFIG_MC3230 is not set +# CONFIG_MMA7455_I2C is not set +# CONFIG_MMA7455_SPI is not set +# CONFIG_MMA7660 is not set +# CONFIG_MMA8452 is not set +# CONFIG_MMA9551 is not set +# CONFIG_MMA9553 is not set +# CONFIG_MSA311 is not set +# CONFIG_MXC4005 is not set +# CONFIG_MXC6255 is not set +# CONFIG_SCA3000 is not set +# CONFIG_SCA3300 is not set +# CONFIG_STK8312 is not set +# CONFIG_STK8BA50 is not set +# end of Accelerometers + +# +# Analog to digital converters +# +# CONFIG_AD4000 is not set +# CONFIG_AD4130 is not set +# CONFIG_AD4695 is not set +# CONFIG_AD7091R5 is not set +# CONFIG_AD7091R8 is not set +# CONFIG_AD7124 is not set +# CONFIG_AD7173 is not set +# CONFIG_AD7192 is not set +# CONFIG_AD7266 is not set +# CONFIG_AD7280 is not set +# CONFIG_AD7291 is not set +# CONFIG_AD7292 is not set +# CONFIG_AD7298 is not set +# CONFIG_AD7380 is not set +# CONFIG_AD7476 is not set +# CONFIG_AD7606_IFACE_PARALLEL is not set +# CONFIG_AD7606_IFACE_SPI is not set +# CONFIG_AD7766 is not set +# CONFIG_AD7768_1 is not set +# CONFIG_AD7780 is not set +# CONFIG_AD7791 is not set +# CONFIG_AD7793 is not set +# CONFIG_AD7887 is not set +# CONFIG_AD7923 is not set +# CONFIG_AD7944 is not set +# CONFIG_AD7949 is not set +# CONFIG_AD799X is not set +# CONFIG_AD9467 is not set +# CONFIG_CC10001_ADC is not set +# CONFIG_ENVELOPE_DETECTOR is not set +# CONFIG_HI8435 is not set +# CONFIG_HX711 is not set +# CONFIG_INA2XX_ADC is not set +# CONFIG_LTC2309 is not set +# CONFIG_LTC2471 is not set +# CONFIG_LTC2485 is not set +# CONFIG_LTC2496 is not set +# CONFIG_LTC2497 is not set +# CONFIG_MAX1027 is not set +# CONFIG_MAX11100 is not set +# CONFIG_MAX1118 is not set +# CONFIG_MAX11205 is not set +# CONFIG_MAX11410 is not set +# CONFIG_MAX1241 is not set +# CONFIG_MAX1363 is not set +# CONFIG_MAX34408 is not set +# CONFIG_MAX9611 is not set +# CONFIG_MCP320X is not set +# CONFIG_MCP3422 is not set +# CONFIG_MCP3564 is not set +# CONFIG_MCP3911 is not set +# CONFIG_NAU7802 is not set +# CONFIG_PAC1921 is not set +# CONFIG_PAC1934 is not set +# CONFIG_QCOM_SPMI_IADC is not set +# CONFIG_QCOM_SPMI_VADC is not set +# CONFIG_QCOM_SPMI_ADC5 is not set +CONFIG_ROCKCHIP_SARADC=y +# CONFIG_RICHTEK_RTQ6056 is not set +# CONFIG_SD_ADC_MODULATOR is not set +# CONFIG_TI_ADC081C is not set +# CONFIG_TI_ADC0832 is not set +# CONFIG_TI_ADC084S021 is not set +# CONFIG_TI_ADC12138 is not set +# CONFIG_TI_ADC108S102 is not set +# CONFIG_TI_ADC128S052 is not set +# CONFIG_TI_ADC161S626 is not set +# CONFIG_TI_ADS1015 is not set +# CONFIG_TI_ADS1119 is not set +# CONFIG_TI_ADS7924 is not set +# CONFIG_TI_ADS1100 is not set +# CONFIG_TI_ADS1298 is not set +# CONFIG_TI_ADS7950 is not set +# CONFIG_TI_ADS8344 is not set +# CONFIG_TI_ADS8688 is not set +# CONFIG_TI_ADS124S08 is not set +# CONFIG_TI_ADS131E08 is not set +# CONFIG_TI_LMP92064 is not set +# CONFIG_TI_TLC4541 is not set +# CONFIG_TI_TSC2046 is not set +# CONFIG_VF610_ADC is not set +# CONFIG_XILINX_XADC is not set +# end of Analog to digital converters + +# +# Analog to digital and digital to analog converters +# +# CONFIG_AD74115 is not set +# CONFIG_AD74413R is not set +# end of Analog to digital and digital to analog converters + +# +# Analog Front Ends +# +# CONFIG_IIO_RESCALE is not set +# end of Analog Front Ends + +# +# Amplifiers +# +# CONFIG_AD8366 is not set +# CONFIG_ADA4250 is not set +# CONFIG_HMC425 is not set +# end of Amplifiers + +# +# Capacitance to digital converters +# +# CONFIG_AD7150 is not set +# CONFIG_AD7746 is not set +# end of Capacitance to digital converters + +# +# Chemical Sensors +# +# CONFIG_AOSONG_AGS02MA is not set +# CONFIG_ATLAS_PH_SENSOR is not set +# CONFIG_ATLAS_EZO_SENSOR is not set +# CONFIG_BME680 is not set +# CONFIG_CCS811 is not set +# CONFIG_ENS160 is not set +# CONFIG_IAQCORE is not set +# CONFIG_PMS7003 is not set +# CONFIG_SCD30_CORE is not set +# CONFIG_SCD4X is not set +# CONFIG_SENSIRION_SGP30 is not set +# CONFIG_SENSIRION_SGP40 is not set +# CONFIG_SPS30_I2C is not set +# CONFIG_SPS30_SERIAL is not set +# CONFIG_SENSEAIR_SUNRISE_CO2 is not set +# CONFIG_VZ89X is not set +# end of Chemical Sensors + +# +# Hid Sensor IIO Common +# +# CONFIG_HID_SENSOR_IIO_COMMON is not set +# end of Hid Sensor IIO Common + +# +# IIO SCMI Sensors +# +# CONFIG_IIO_SCMI is not set +# end of IIO SCMI Sensors + +# +# SSP Sensor Common +# +# CONFIG_IIO_SSP_SENSORHUB is not set +# end of SSP Sensor Common + +# +# Digital to analog converters +# +# CONFIG_AD3552R is not set +# 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_AD5592R is not set +# CONFIG_AD5593R is not set +# CONFIG_AD5504 is not set +# CONFIG_AD5624R_SPI is not set +# CONFIG_AD9739A is not set +# CONFIG_LTC2688 is not set +# CONFIG_AD5686_SPI is not set +# CONFIG_AD5696_I2C is not set +# CONFIG_AD5755 is not set +# CONFIG_AD5758 is not set +# CONFIG_AD5761 is not set +# CONFIG_AD5764 is not set +# CONFIG_AD5766 is not set +# CONFIG_AD5770R is not set +# CONFIG_AD5791 is not set +# CONFIG_AD7293 is not set +# CONFIG_AD7303 is not set +# CONFIG_AD8801 is not set +# CONFIG_DPOT_DAC is not set +# CONFIG_DS4424 is not set +# CONFIG_LTC1660 is not set +# CONFIG_LTC2632 is not set +# CONFIG_LTC2664 is not set +# CONFIG_M62332 is not set +# CONFIG_MAX517 is not set +# CONFIG_MAX5522 is not set +# CONFIG_MAX5821 is not set +# CONFIG_MCP4725 is not set +# CONFIG_MCP4728 is not set +# CONFIG_MCP4821 is not set +# CONFIG_MCP4922 is not set +# CONFIG_TI_DAC082S085 is not set +# CONFIG_TI_DAC5571 is not set +# CONFIG_TI_DAC7311 is not set +# CONFIG_TI_DAC7612 is not set +# CONFIG_VF610_DAC is not set +# end of Digital to analog converters + +# +# IIO dummy driver +# +# end of IIO dummy driver + +# +# Filters +# +# CONFIG_ADMV8818 is not set +# end of Filters + +# +# Frequency Synthesizers DDS/PLL +# + +# +# Clock Generator/Distribution +# +# CONFIG_AD9523 is not set +# end of Clock Generator/Distribution + +# +# Phase-Locked Loop (PLL) frequency synthesizers +# +# CONFIG_ADF4350 is not set +# CONFIG_ADF4371 is not set +# CONFIG_ADF4377 is not set +# CONFIG_ADMFM2000 is not set +# CONFIG_ADMV1013 is not set +# CONFIG_ADMV1014 is not set +# CONFIG_ADMV4420 is not set +# CONFIG_ADRF6780 is not set +# end of Phase-Locked Loop (PLL) frequency synthesizers +# end of Frequency Synthesizers DDS/PLL + +# +# Digital gyroscope sensors +# +# CONFIG_ADIS16080 is not set +# CONFIG_ADIS16130 is not set +# CONFIG_ADIS16136 is not set +# CONFIG_ADIS16260 is not set +# CONFIG_ADXRS290 is not set +# CONFIG_ADXRS450 is not set +# CONFIG_BMG160 is not set +# CONFIG_FXAS21002C is not set +# CONFIG_HID_SENSOR_GYRO_3D is not set +# CONFIG_MPU3050_I2C is not set +# CONFIG_IIO_ST_GYRO_3AXIS is not set +# CONFIG_ITG3200 is not set +# end of Digital gyroscope sensors + +# +# Health Sensors +# + +# +# Heart Rate Monitors +# +# CONFIG_AFE4403 is not set +# CONFIG_AFE4404 is not set +# CONFIG_MAX30100 is not set +# CONFIG_MAX30102 is not set +# end of Heart Rate Monitors +# end of Health Sensors + +# +# Humidity sensors +# +# CONFIG_AM2315 is not set +# CONFIG_DHT11 is not set +# CONFIG_ENS210 is not set +# CONFIG_HDC100X is not set +# CONFIG_HDC2010 is not set +# CONFIG_HDC3020 is not set +# CONFIG_HID_SENSOR_HUMIDITY is not set +# CONFIG_HTS221 is not set +# CONFIG_HTU21 is not set +# CONFIG_SI7005 is not set +# CONFIG_SI7020 is not set +# end of Humidity sensors + +# +# Inertial measurement units +# +# CONFIG_ADIS16400 is not set +# CONFIG_ADIS16460 is not set +# CONFIG_ADIS16475 is not set +# CONFIG_ADIS16480 is not set +# CONFIG_BMI160_I2C is not set +# CONFIG_BMI160_SPI is not set +# CONFIG_BMI323_I2C is not set +# CONFIG_BMI323_SPI is not set +# CONFIG_BOSCH_BNO055_SERIAL is not set +# CONFIG_BOSCH_BNO055_I2C is not set +# CONFIG_FXOS8700_I2C is not set +# CONFIG_FXOS8700_SPI is not set +# CONFIG_KMX61 is not set +# CONFIG_INV_ICM42600_I2C is not set +# CONFIG_INV_ICM42600_SPI is not set +# CONFIG_INV_MPU6050_I2C is not set +# CONFIG_INV_MPU6050_SPI is not set +# CONFIG_IIO_ST_LSM6DSX is not set +# CONFIG_IIO_ST_LSM9DS0 is not set +# end of Inertial measurement units + +# +# Light sensors +# +# CONFIG_ADJD_S311 is not set +# CONFIG_ADUX1020 is not set +# CONFIG_AL3010 is not set +# CONFIG_AL3320A is not set +# CONFIG_APDS9300 is not set +# CONFIG_APDS9306 is not set +# CONFIG_APDS9960 is not set +# CONFIG_AS73211 is not set +# CONFIG_BH1745 is not set +# CONFIG_BH1750 is not set +# CONFIG_BH1780 is not set +# CONFIG_CM32181 is not set +# CONFIG_CM3232 is not set +# CONFIG_CM3323 is not set +# CONFIG_CM3605 is not set +# CONFIG_CM36651 is not set +# CONFIG_GP2AP002 is not set +# CONFIG_GP2AP020A00F is not set +# CONFIG_SENSORS_ISL29018 is not set +# CONFIG_SENSORS_ISL29028 is not set +# CONFIG_ISL29125 is not set +# CONFIG_ISL76682 is not set +# CONFIG_HID_SENSOR_ALS is not set +# CONFIG_HID_SENSOR_PROX is not set +# CONFIG_JSA1212 is not set +# CONFIG_ROHM_BU27008 is not set +# CONFIG_ROHM_BU27034 is not set +# CONFIG_RPR0521 is not set +# CONFIG_LTR390 is not set +# CONFIG_LTR501 is not set +# CONFIG_LTRF216A is not set +# CONFIG_LV0104CS is not set +# CONFIG_MAX44000 is not set +# CONFIG_MAX44009 is not set +# CONFIG_NOA1305 is not set +# CONFIG_OPT3001 is not set +# CONFIG_OPT4001 is not set +# CONFIG_PA12203001 is not set +# CONFIG_SI1133 is not set +# CONFIG_SI1145 is not set +# CONFIG_STK3310 is not set +# CONFIG_ST_UVIS25 is not set +# CONFIG_TCS3414 is not set +# CONFIG_TCS3472 is not set +# CONFIG_SENSORS_TSL2563 is not set +# CONFIG_TSL2583 is not set +# CONFIG_TSL2591 is not set +# CONFIG_TSL2772 is not set +# CONFIG_TSL4531 is not set +# CONFIG_US5182D is not set +# CONFIG_VCNL4000 is not set +# CONFIG_VCNL4035 is not set +# CONFIG_VEML6030 is not set +# CONFIG_VEML6040 is not set +# CONFIG_VEML6070 is not set +# CONFIG_VEML6075 is not set +# CONFIG_VL6180 is not set +# CONFIG_ZOPT2201 is not set +# end of Light sensors + +# +# Magnetometer sensors +# +# CONFIG_AF8133J is not set +# CONFIG_AK8974 is not set +# CONFIG_AK8975 is not set +# CONFIG_AK09911 is not set +# CONFIG_BMC150_MAGN_I2C is not set +# CONFIG_BMC150_MAGN_SPI 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 +# CONFIG_SENSORS_HMC5843_I2C is not set +# CONFIG_SENSORS_HMC5843_SPI is not set +# CONFIG_SENSORS_RM3100_I2C is not set +# CONFIG_SENSORS_RM3100_SPI is not set +# CONFIG_TI_TMAG5273 is not set +# CONFIG_YAMAHA_YAS530 is not set +# end of Magnetometer sensors + +# +# Multiplexers +# +CONFIG_IIO_MUX=y +# end of Multiplexers + +# +# Inclinometer sensors +# +# CONFIG_HID_SENSOR_INCLINOMETER_3D is not set +# CONFIG_HID_SENSOR_DEVICE_ROTATION is not set +# end of Inclinometer sensors + +# +# Triggers - standalone +# +# CONFIG_IIO_INTERRUPT_TRIGGER is not set +# CONFIG_IIO_SYSFS_TRIGGER is not set +# end of Triggers - standalone + +# +# Linear and angular position sensors +# +# CONFIG_HID_SENSOR_CUSTOM_INTEL_HINGE is not set +# end of Linear and angular position sensors + +# +# Digital potentiometers +# +# CONFIG_AD5110 is not set +# CONFIG_AD5272 is not set +# CONFIG_DS1803 is not set +# CONFIG_MAX5432 is not set +# CONFIG_MAX5481 is not set +# CONFIG_MAX5487 is not set +# CONFIG_MCP4018 is not set +# CONFIG_MCP4131 is not set +# CONFIG_MCP4531 is not set +# CONFIG_MCP41010 is not set +# CONFIG_TPL0102 is not set +# CONFIG_X9250 is not set +# end of Digital potentiometers + +# +# Digital potentiostats +# +# CONFIG_LMP91000 is not set +# end of Digital potentiostats + +# +# Pressure sensors +# +# CONFIG_ABP060MG is not set +# CONFIG_ROHM_BM1390 is not set +# CONFIG_BMP280 is not set +# CONFIG_DLHL60D is not set +# CONFIG_DPS310 is not set +# CONFIG_HID_SENSOR_PRESS is not set +# CONFIG_HP03 is not set +# CONFIG_HSC030PA is not set +# CONFIG_ICP10100 is not set +# CONFIG_MPL115_I2C is not set +# CONFIG_MPL115_SPI is not set +# CONFIG_MPL3115 is not set +# CONFIG_MPRLS0025PA is not set +# CONFIG_MS5611 is not set +# CONFIG_MS5637 is not set +# CONFIG_SDP500 is not set +# CONFIG_IIO_ST_PRESS is not set +# CONFIG_T5403 is not set +# CONFIG_HP206C is not set +# CONFIG_ZPA2326 is not set +# end of Pressure sensors + +# +# Lightning sensors +# +# CONFIG_AS3935 is not set +# end of Lightning sensors + +# +# Proximity and distance sensors +# +# CONFIG_HX9023S is not set +# CONFIG_IRSD200 is not set +# CONFIG_ISL29501 is not set +# CONFIG_LIDAR_LITE_V2 is not set +# CONFIG_MB1232 is not set +# CONFIG_PING is not set +# CONFIG_RFD77402 is not set +# CONFIG_SRF04 is not set +# CONFIG_SX9310 is not set +# CONFIG_SX9324 is not set +# CONFIG_SX9360 is not set +# CONFIG_SX9500 is not set +# CONFIG_SRF08 is not set +# CONFIG_VCNL3020 is not set +# CONFIG_VL53L0X_I2C is not set +# CONFIG_AW96103 is not set +# end of Proximity and distance sensors + +# +# Resolver to digital converters +# +# CONFIG_AD2S90 is not set +# CONFIG_AD2S1200 is not set +# CONFIG_AD2S1210 is not set +# end of Resolver to digital converters + +# +# Temperature sensors +# +# CONFIG_LTC2983 is not set +# CONFIG_MAXIM_THERMOCOUPLE is not set +# CONFIG_HID_SENSOR_TEMP is not set +# CONFIG_MLX90614 is not set +# CONFIG_MLX90632 is not set +# CONFIG_MLX90635 is not set +# CONFIG_TMP006 is not set +# CONFIG_TMP007 is not set +# CONFIG_TMP117 is not set +# CONFIG_TSYS01 is not set +# CONFIG_TSYS02D is not set +# CONFIG_MAX30208 is not set +# CONFIG_MAX31856 is not set +# CONFIG_MAX31865 is not set +# CONFIG_MCP9600 is not set +# end of Temperature sensors + +CONFIG_PWM=y +# CONFIG_PWM_DEBUG is not set +# CONFIG_PWM_ATMEL_TCB is not set +# CONFIG_PWM_CLK 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_XILINX is not set + +# +# IRQ chip support +# +CONFIG_IRQCHIP=y +CONFIG_ARM_GIC=y +CONFIG_ARM_GIC_MAX_NR=1 +CONFIG_ARM_GIC_V3=y +CONFIG_ARM_GIC_V3_ITS=y +CONFIG_IRQ_MSI_LIB=y +# CONFIG_AL_FIC is not set +# CONFIG_XILINX_INTC is not set +CONFIG_PARTITION_PERCPU=y +# end of IRQ chip support + +# CONFIG_IPACK_BUS is not set +CONFIG_ARCH_HAS_RESET_CONTROLLER=y +CONFIG_RESET_CONTROLLER=y +# CONFIG_RESET_GPIO is not set +CONFIG_RESET_SCMI=m +# CONFIG_RESET_SIMPLE is not set +# CONFIG_RESET_TI_SYSCON is not set +# CONFIG_RESET_TI_TPS380X is not set + +# +# PHY Subsystem +# +CONFIG_GENERIC_PHY=y +CONFIG_GENERIC_PHY_MIPI_DPHY=y +# CONFIG_PHY_CAN_TRANSCEIVER is not set + +# +# PHY drivers for Broadcom platforms +# +# CONFIG_BCM_KONA_USB2_PHY is not set +# end of PHY drivers for Broadcom platforms + +# CONFIG_PHY_CADENCE_TORRENT is not set +# CONFIG_PHY_CADENCE_DPHY is not set +# CONFIG_PHY_CADENCE_DPHY_RX is not set +# CONFIG_PHY_CADENCE_SIERRA is not set +# CONFIG_PHY_CADENCE_SALVO is not set +# CONFIG_PHY_PXA_28NM_HSIC is not set +# CONFIG_PHY_PXA_28NM_USB2 is not set +# CONFIG_PHY_LAN966X_SERDES is not set +# CONFIG_PHY_CPCAP_USB is not set +# CONFIG_PHY_MAPPHONE_MDM6600 is not set +# CONFIG_PHY_OCELOT_SERDES is not set +# CONFIG_PHY_QCOM_USB_HS is not set +# CONFIG_PHY_QCOM_USB_HSIC is not set +CONFIG_PHY_ROCKCHIP_DP=y +CONFIG_PHY_ROCKCHIP_DPHY_RX0=y +CONFIG_PHY_ROCKCHIP_EMMC=y +CONFIG_PHY_ROCKCHIP_INNO_HDMI=y +CONFIG_PHY_ROCKCHIP_INNO_USB2=y +# CONFIG_PHY_ROCKCHIP_INNO_CSIDPHY is not set +CONFIG_PHY_ROCKCHIP_INNO_DSIDPHY=y +# CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY is not set +CONFIG_PHY_ROCKCHIP_PCIE=y +# CONFIG_PHY_ROCKCHIP_SAMSUNG_HDPTX is not set +# CONFIG_PHY_ROCKCHIP_SNPS_PCIE3 is not set +CONFIG_PHY_ROCKCHIP_TYPEC=y +CONFIG_PHY_ROCKCHIP_USB=y +# CONFIG_PHY_SAMSUNG_USB2 is not set +# CONFIG_PHY_TUSB1210 is not set +# end of PHY Subsystem + +# CONFIG_POWERCAP is not set +# CONFIG_MCB is not set + +# +# Performance monitor support +# +# CONFIG_ARM_CCI_PMU is not set +# CONFIG_ARM_CCN is not set +# CONFIG_ARM_CMN is not set +# CONFIG_ARM_NI is not set +CONFIG_ARM_PMU=y +# CONFIG_ARM_SMMU_V3_PMU is not set +CONFIG_ARM_PMUV3=y +# CONFIG_ARM_DSU_PMU is not set +# CONFIG_ARM_SPE_PMU is not set +# CONFIG_ARM_CORESIGHT_PMU_ARCH_SYSTEM_PMU is not set +# end of Performance monitor support + +CONFIG_RAS=y + +# +# Android +# +# CONFIG_ANDROID_BINDER_IPC is not set +# end of Android + +# CONFIG_LIBNVDIMM is not set +# CONFIG_DAX is not set +CONFIG_NVMEM=y +CONFIG_NVMEM_SYSFS=y +CONFIG_NVMEM_LAYOUTS=y + +# +# Layout Types +# +# CONFIG_NVMEM_LAYOUT_SL28_VPD is not set +# CONFIG_NVMEM_LAYOUT_ONIE_TLV is not set +# CONFIG_NVMEM_LAYOUT_U_BOOT_ENV is not set +# end of Layout Types + +# CONFIG_NVMEM_RMEM is not set +# CONFIG_NVMEM_ROCKCHIP_EFUSE is not set +CONFIG_NVMEM_ROCKCHIP_OTP=y +# CONFIG_NVMEM_SPMI_SDAM is not set +# CONFIG_NVMEM_U_BOOT_ENV is not set + +# +# HW tracing support +# +# CONFIG_STM is not set +# CONFIG_INTEL_TH is not set +# end of HW tracing support + +# CONFIG_FPGA is not set +# CONFIG_FSI is not set +CONFIG_TEE=y +CONFIG_OPTEE=m +# CONFIG_OPTEE_INSECURE_LOAD_IMAGE is not set +CONFIG_MULTIPLEXER=y + +# +# Multiplexer drivers +# +# CONFIG_MUX_ADG792A is not set +# CONFIG_MUX_ADGS1408 is not set +CONFIG_MUX_GPIO=y +CONFIG_MUX_MMIO=y +# end of Multiplexer drivers + +CONFIG_PM_OPP=y +# CONFIG_SIOX is not set +# CONFIG_SLIMBUS is not set +# CONFIG_INTERCONNECT is not set +# CONFIG_COUNTER is not set +# CONFIG_MOST is not set +# CONFIG_PECI is not set +# CONFIG_HTE is not set +# CONFIG_CDX_BUS is not set +# end of Device Drivers + +# +# File systems +# +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_VALIDATE_FS_PARSER=y +CONFIG_FS_IOMAP=y +CONFIG_FS_STACK=y +CONFIG_BUFFER_HEAD=y +CONFIG_LEGACY_DIRECT_IO=y +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +# CONFIG_EXT4_FS_SECURITY 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_BCACHEFS_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_EXPORTFS=y +# CONFIG_EXPORTFS_BLOCK_OPS is not set +CONFIG_FILE_LOCKING=y +# CONFIG_FS_ENCRYPTION is not set +# CONFIG_FS_VERITY is not set +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_FANOTIFY=y +CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y +CONFIG_QUOTA=y +# CONFIG_QUOTA_NETLINK_INTERFACE is not set +# CONFIG_QUOTA_DEBUG is not set +# CONFIG_QFMT_V1 is not set +# CONFIG_QFMT_V2 is not set +CONFIG_QUOTACTL=y +CONFIG_AUTOFS_FS=y +CONFIG_FUSE_FS=y +CONFIG_CUSE=m +# CONFIG_VIRTIO_FS is not set +CONFIG_FUSE_PASSTHROUGH=y +CONFIG_OVERLAY_FS=y +CONFIG_OVERLAY_FS_REDIRECT_DIR=y +CONFIG_OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW=y +# CONFIG_OVERLAY_FS_INDEX is not set +# CONFIG_OVERLAY_FS_XINO_AUTO is not set +# CONFIG_OVERLAY_FS_METACOPY is not set +# CONFIG_OVERLAY_FS_DEBUG is not set + +# +# Caches +# +# end of Caches + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +# CONFIG_UDF_FS is not set +# end of CD-ROM/DVD Filesystems + +# +# DOS/FAT/EXFAT/NT Filesystems +# +CONFIG_FAT_FS=y +# CONFIG_MSDOS_FS is not set +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_FAT_DEFAULT_UTF8 is not set +CONFIG_EXFAT_FS=m +CONFIG_EXFAT_DEFAULT_IOCHARSET="utf8" +# CONFIG_NTFS3_FS is not set +# CONFIG_NTFS_FS is not set +# end of DOS/FAT/EXFAT/NT Filesystems + +# +# 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_KERNFS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_TMPFS_XATTR=y +# CONFIG_TMPFS_INODE64 is not set +# CONFIG_TMPFS_QUOTA is not set +CONFIG_ARCH_SUPPORTS_HUGETLBFS=y +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE=y +CONFIG_HUGETLB_PMD_PAGE_TABLE_SHARING=y +CONFIG_ARCH_HAS_GIGANTIC_PAGE=y +CONFIG_CONFIGFS_FS=y +# end of Pseudo filesystems + +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ORANGEFS_FS is not set +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_ECRYPT_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_CRAMFS is not set +CONFIG_SQUASHFS=y +CONFIG_SQUASHFS_FILE_CACHE=y +# CONFIG_SQUASHFS_FILE_DIRECT is not set +CONFIG_SQUASHFS_DECOMP_SINGLE=y +# CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT is not set +CONFIG_SQUASHFS_COMPILE_DECOMP_SINGLE=y +# CONFIG_SQUASHFS_COMPILE_DECOMP_MULTI is not set +# CONFIG_SQUASHFS_COMPILE_DECOMP_MULTI_PERCPU is not set +CONFIG_SQUASHFS_XATTR=y +CONFIG_SQUASHFS_ZLIB=y +CONFIG_SQUASHFS_LZ4=y +CONFIG_SQUASHFS_LZO=y +CONFIG_SQUASHFS_XZ=y +CONFIG_SQUASHFS_ZSTD=y +CONFIG_SQUASHFS_4K_DEVBLK_SIZE=y +CONFIG_SQUASHFS_EMBEDDED=y +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_DEFAULT_KMSG_BYTES=10240 +CONFIG_PSTORE_COMPRESS=y +CONFIG_PSTORE_CONSOLE=y +CONFIG_PSTORE_PMSG=y +CONFIG_PSTORE_RAM=y +# CONFIG_PSTORE_BLK is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +# CONFIG_EROFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +# CONFIG_NFS_V2 is not set +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_SWAP is not set +# CONFIG_ROOT_NFS is not set +# CONFIG_NFS_FSCACHE is not set +CONFIG_NFS_DISABLE_UDP_SUPPORT=y +CONFIG_NFSD=m +# CONFIG_NFSD_V2 is not set +# CONFIG_NFSD_V3_ACL is not set +# CONFIG_NFSD_V4 is not set +CONFIG_GRACE_PERIOD=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +# CONFIG_NFS_LOCALIO is not set +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_SUNRPC_DEBUG is not set +# CONFIG_CEPH_FS is not set +# CONFIG_CIFS is not set +# CONFIG_SMB_SERVER 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 is not set +# 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=m +# CONFIG_DLM_DEBUG is not set +CONFIG_UNICODE=y +# CONFIG_UNICODE_NORMALIZATION_SELFTEST is not set +CONFIG_IO_WQ=y +# end of File systems + +# +# Security options +# +CONFIG_KEYS=y +# CONFIG_KEYS_REQUEST_CACHE is not set +# CONFIG_PERSISTENT_KEYRINGS is not set +# CONFIG_TRUSTED_KEYS is not set +# CONFIG_ENCRYPTED_KEYS is not set +CONFIG_KEY_DH_OPERATIONS=y +# CONFIG_SECURITY_DMESG_RESTRICT is not set +CONFIG_PROC_MEM_ALWAYS_FORCE=y +# CONFIG_PROC_MEM_FORCE_PTRACE is not set +# CONFIG_PROC_MEM_NO_FORCE is not set +CONFIG_SECURITY=y +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_NETWORK is not set +# CONFIG_SECURITY_PATH is not set +# CONFIG_HARDENED_USERCOPY is not set +# CONFIG_FORTIFY_SOURCE is not set +# CONFIG_STATIC_USERMODEHELPER is not set +# CONFIG_SECURITY_SMACK is not set +# CONFIG_SECURITY_TOMOYO is not set +# CONFIG_SECURITY_APPARMOR is not set +# CONFIG_SECURITY_LOADPIN is not set +# CONFIG_SECURITY_YAMA is not set +# CONFIG_SECURITY_SAFESETID is not set +# CONFIG_SECURITY_LOCKDOWN_LSM is not set +# CONFIG_SECURITY_LANDLOCK is not set +CONFIG_INTEGRITY=y +# CONFIG_INTEGRITY_SIGNATURE is not set +# CONFIG_IMA is not set +# CONFIG_EVM is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_LSM="yama,loadpin,safesetid,integrity" + +# +# Kernel hardening options +# + +# +# Memory initialization +# +CONFIG_CC_HAS_AUTO_VAR_INIT_PATTERN=y +CONFIG_CC_HAS_AUTO_VAR_INIT_ZERO_BARE=y +CONFIG_CC_HAS_AUTO_VAR_INIT_ZERO=y +CONFIG_INIT_STACK_NONE=y +# CONFIG_INIT_STACK_ALL_PATTERN is not set +# CONFIG_INIT_STACK_ALL_ZERO is not set +# CONFIG_INIT_ON_ALLOC_DEFAULT_ON is not set +# CONFIG_INIT_ON_FREE_DEFAULT_ON is not set +CONFIG_CC_HAS_ZERO_CALL_USED_REGS=y +# CONFIG_ZERO_CALL_USED_REGS is not set +# end of Memory initialization + +# +# Hardening of kernel data structures +# +# CONFIG_LIST_HARDENED is not set +# CONFIG_BUG_ON_DATA_CORRUPTION is not set +# end of Hardening of kernel data structures + +CONFIG_RANDSTRUCT_NONE=y +# end of Kernel hardening options +# end of Security options + +CONFIG_XOR_BLOCKS=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_SIG=y +CONFIG_CRYPTO_SIG2=y +CONFIG_CRYPTO_SKCIPHER=y +CONFIG_CRYPTO_SKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_RNG_DEFAULT=y +CONFIG_CRYPTO_AKCIPHER2=y +CONFIG_CRYPTO_AKCIPHER=y +CONFIG_CRYPTO_KPP2=y +CONFIG_CRYPTO_KPP=y +CONFIG_CRYPTO_ACOMP2=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +CONFIG_CRYPTO_USER=m +CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_NULL2=y +# CONFIG_CRYPTO_PCRYPT is not set +CONFIG_CRYPTO_CRYPTD=y +CONFIG_CRYPTO_AUTHENC=m +# CONFIG_CRYPTO_TEST is not set +CONFIG_CRYPTO_ENGINE=m +# end of Crypto core or helper + +# +# Public-key cryptography +# +CONFIG_CRYPTO_RSA=y +CONFIG_CRYPTO_DH=y +# CONFIG_CRYPTO_DH_RFC7919_GROUPS is not set +CONFIG_CRYPTO_ECC=m +CONFIG_CRYPTO_ECDH=m +# CONFIG_CRYPTO_ECDSA is not set +# CONFIG_CRYPTO_ECRDSA is not set +CONFIG_CRYPTO_CURVE25519=m +# end of Public-key cryptography + +# +# Block ciphers +# +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_AES_TI is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARIA is not set +# 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_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_SM4_GENERIC is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set +# end of Block ciphers + +# +# Length-preserving ciphers and modes +# +# CONFIG_CRYPTO_ADIANTUM is not set +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_CHACHA20=m +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_CTR=y +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=y +# CONFIG_CRYPTO_HCTR2 is not set +# CONFIG_CRYPTO_KEYWRAP is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set +CONFIG_CRYPTO_NHPOLY1305=m +# end of Length-preserving ciphers and modes + +# +# AEAD (authenticated encryption with associated data) ciphers +# +# CONFIG_CRYPTO_AEGIS128 is not set +# CONFIG_CRYPTO_CHACHA20POLY1305 is not set +CONFIG_CRYPTO_CCM=y +CONFIG_CRYPTO_GCM=y +CONFIG_CRYPTO_GENIV=y +CONFIG_CRYPTO_SEQIV=m +CONFIG_CRYPTO_ECHAINIV=y +# CONFIG_CRYPTO_ESSIV is not set +# end of AEAD (authenticated encryption with associated data) ciphers + +# +# Hashes, digests, and MACs +# +CONFIG_CRYPTO_BLAKE2B=y +CONFIG_CRYPTO_CMAC=y +CONFIG_CRYPTO_GHASH=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_MICHAEL_MIC is not set +CONFIG_CRYPTO_POLY1305=m +# CONFIG_CRYPTO_RMD160 is not set +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_SHA3=y +# CONFIG_CRYPTO_SM3_GENERIC is not set +# CONFIG_CRYPTO_STREEBOG is not set +# CONFIG_CRYPTO_VMAC is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_XCBC is not set +CONFIG_CRYPTO_XXHASH=y +# end of Hashes, digests, and MACs + +# +# CRCs (cyclic redundancy checks) +# +CONFIG_CRYPTO_CRC32C=y +# CONFIG_CRYPTO_CRC32 is not set +# CONFIG_CRYPTO_CRCT10DIF is not set +# end of CRCs (cyclic redundancy checks) + +# +# Compression +# +CONFIG_CRYPTO_DEFLATE=y +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=y +# end of Compression + +# +# 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_JITTERENTROPY_MEMORY_BLOCKS=64 +CONFIG_CRYPTO_JITTERENTROPY_MEMORY_BLOCKSIZE=32 +CONFIG_CRYPTO_JITTERENTROPY_OSR=1 +CONFIG_CRYPTO_KDF800108_CTR=y +# end of Random number generation + +# +# Userspace interface +# +CONFIG_CRYPTO_USER_API=y +CONFIG_CRYPTO_USER_API_HASH=y +CONFIG_CRYPTO_USER_API_SKCIPHER=y +CONFIG_CRYPTO_USER_API_RNG=y +# CONFIG_CRYPTO_USER_API_RNG_CAVP is not set +CONFIG_CRYPTO_USER_API_AEAD=m +CONFIG_CRYPTO_USER_API_ENABLE_OBSOLETE=y +# end of Userspace interface + +CONFIG_CRYPTO_HASH_INFO=y +CONFIG_CRYPTO_NHPOLY1305_NEON=m +CONFIG_CRYPTO_CHACHA20_NEON=m + +# +# Accelerated Cryptographic Algorithms for CPU (arm64) +# +CONFIG_CRYPTO_GHASH_ARM64_CE=y +CONFIG_CRYPTO_POLY1305_NEON=m +CONFIG_CRYPTO_SHA1_ARM64_CE=y +CONFIG_CRYPTO_SHA256_ARM64=y +CONFIG_CRYPTO_SHA2_ARM64_CE=y +CONFIG_CRYPTO_SHA512_ARM64=y +CONFIG_CRYPTO_SHA512_ARM64_CE=y +# CONFIG_CRYPTO_SHA3_ARM64 is not set +# CONFIG_CRYPTO_SM3_NEON is not set +# CONFIG_CRYPTO_SM3_ARM64_CE is not set +# CONFIG_CRYPTO_POLYVAL_ARM64_CE is not set +CONFIG_CRYPTO_AES_ARM64=y +CONFIG_CRYPTO_AES_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE_BLK=y +CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y +CONFIG_CRYPTO_AES_ARM64_BS=y +# CONFIG_CRYPTO_SM4_ARM64_CE is not set +# CONFIG_CRYPTO_SM4_ARM64_CE_BLK is not set +# CONFIG_CRYPTO_SM4_ARM64_NEON_BLK is not set +CONFIG_CRYPTO_AES_ARM64_CE_CCM=y +# CONFIG_CRYPTO_SM4_ARM64_CE_CCM is not set +# CONFIG_CRYPTO_SM4_ARM64_CE_GCM is not set +# end of Accelerated Cryptographic Algorithms for CPU (arm64) + +CONFIG_CRYPTO_HW=y +# CONFIG_CRYPTO_DEV_ATMEL_ECC is not set +# CONFIG_CRYPTO_DEV_ATMEL_SHA204A is not set +# CONFIG_CRYPTO_DEV_CCP is not set +CONFIG_CRYPTO_DEV_ROCKCHIP=m +# CONFIG_CRYPTO_DEV_ROCKCHIP_DEBUG is not set +# CONFIG_CRYPTO_DEV_SAFEXCEL is not set +# CONFIG_CRYPTO_DEV_CCREE is not set +# CONFIG_CRYPTO_DEV_HISI_SEC is not set +# CONFIG_CRYPTO_DEV_AMLOGIC_GXL is not set +CONFIG_ASYMMETRIC_KEY_TYPE=y +CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y +CONFIG_X509_CERTIFICATE_PARSER=y +CONFIG_PKCS8_PRIVATE_KEY_PARSER=y +CONFIG_PKCS7_MESSAGE_PARSER=y +# CONFIG_PKCS7_TEST_KEY is not set +# CONFIG_SIGNED_PE_FILE_VERIFICATION is not set +# CONFIG_FIPS_SIGNATURE_SELFTEST is not set + +# +# Certificates for signature checking +# +CONFIG_SYSTEM_TRUSTED_KEYRING=y +CONFIG_SYSTEM_TRUSTED_KEYS="" +# CONFIG_SYSTEM_EXTRA_CERTIFICATE is not set +# CONFIG_SECONDARY_TRUSTED_KEYRING is not set +# CONFIG_SYSTEM_BLACKLIST_KEYRING is not set +# end of Certificates for signature checking + +CONFIG_BINARY_PRINTF=y + +# +# Library routines +# +CONFIG_RAID6_PQ=y +CONFIG_RAID6_PQ_BENCHMARK=y +CONFIG_LINEAR_RANGES=y +# CONFIG_PACKING is not set +CONFIG_BITREVERSE=y +CONFIG_HAVE_ARCH_BITREVERSE=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_NET_UTILS=y +CONFIG_CORDIC=m +# CONFIG_PRIME_NUMBERS is not set +CONFIG_RATIONAL=y +CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y +CONFIG_ARCH_HAS_FAST_MULTIPLIER=y +CONFIG_ARCH_USE_SYM_ANNOTATIONS=y +# CONFIG_INDIRECT_PIO is not set + +# +# Crypto library routines +# +CONFIG_CRYPTO_LIB_UTILS=y +CONFIG_CRYPTO_LIB_AES=y +CONFIG_CRYPTO_LIB_ARC4=y +CONFIG_CRYPTO_LIB_GF128MUL=y +CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +CONFIG_CRYPTO_ARCH_HAVE_LIB_CHACHA=y +CONFIG_CRYPTO_LIB_CHACHA_GENERIC=m +CONFIG_CRYPTO_LIB_CHACHA_INTERNAL=m +CONFIG_CRYPTO_LIB_CHACHA=m +CONFIG_CRYPTO_LIB_CURVE25519_GENERIC=m +CONFIG_CRYPTO_LIB_CURVE25519_INTERNAL=m +CONFIG_CRYPTO_LIB_CURVE25519=m +CONFIG_CRYPTO_LIB_DES=y +CONFIG_CRYPTO_LIB_POLY1305_RSIZE=9 +CONFIG_CRYPTO_ARCH_HAVE_LIB_POLY1305=y +CONFIG_CRYPTO_LIB_POLY1305_GENERIC=m +CONFIG_CRYPTO_LIB_POLY1305_INTERNAL=m +CONFIG_CRYPTO_LIB_POLY1305=m +CONFIG_CRYPTO_LIB_CHACHA20POLY1305=m +CONFIG_CRYPTO_LIB_SHA1=y +CONFIG_CRYPTO_LIB_SHA256=y +# end of Crypto library routines + +CONFIG_CRC_CCITT=m +CONFIG_CRC16=y +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC64_ROCKSOFT is not set +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_CRC64 is not set +# CONFIG_CRC4 is not set +CONFIG_CRC7=y +CONFIG_LIBCRC32C=y +# CONFIG_CRC8 is not set +CONFIG_XXHASH=y +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=m +CONFIG_LZ4HC_COMPRESS=m +CONFIG_LZ4_DECOMPRESS=y +CONFIG_ZSTD_COMMON=y +CONFIG_ZSTD_COMPRESS=y +CONFIG_ZSTD_DECOMPRESS=y +CONFIG_XZ_DEC=y +CONFIG_XZ_DEC_X86=y +CONFIG_XZ_DEC_POWERPC=y +CONFIG_XZ_DEC_ARM=y +CONFIG_XZ_DEC_ARMTHUMB=y +CONFIG_XZ_DEC_ARM64=y +CONFIG_XZ_DEC_SPARC=y +CONFIG_XZ_DEC_RISCV=y +# CONFIG_XZ_DEC_MICROLZMA is not set +CONFIG_XZ_DEC_BCJ=y +# CONFIG_XZ_DEC_TEST is not set +CONFIG_DECOMPRESS_LZO=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_REED_SOLOMON=y +CONFIG_REED_SOLOMON_ENC8=y +CONFIG_REED_SOLOMON_DEC8=y +CONFIG_INTERVAL_TREE=y +CONFIG_XARRAY_MULTI=y +CONFIG_ASSOCIATIVE_ARRAY=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_DMA_OPS_HELPERS=y +CONFIG_NEED_SG_DMA_FLAGS=y +CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_DMA_DECLARE_COHERENT=y +CONFIG_ARCH_HAS_SETUP_DMA_OPS=y +CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE=y +CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU=y +CONFIG_ARCH_HAS_DMA_PREP_COHERENT=y +CONFIG_SWIOTLB=y +# CONFIG_SWIOTLB_DYNAMIC is not set +CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC=y +CONFIG_DMA_NEED_SYNC=y +# CONFIG_DMA_RESTRICTED_POOL is not set +CONFIG_DMA_NONCOHERENT_MMAP=y +CONFIG_DMA_COHERENT_POOL=y +CONFIG_DMA_DIRECT_REMAP=y +CONFIG_DMA_CMA=y + +# +# Default contiguous memory area size: +# +CONFIG_CMA_SIZE_MBYTES=96 +CONFIG_CMA_SIZE_SEL_MBYTES=y +# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set +# CONFIG_CMA_SIZE_SEL_MIN is not set +# CONFIG_CMA_SIZE_SEL_MAX is not set +CONFIG_CMA_ALIGNMENT=8 +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_DMA_MAP_BENCHMARK is not set +CONFIG_SGL_ALLOC=y +CONFIG_CPU_RMAP=y +CONFIG_DQL=y +CONFIG_GLOB=y +# CONFIG_GLOB_SELFTEST is not set +CONFIG_NLATTR=y +CONFIG_CLZ_TAB=y +# CONFIG_IRQ_POLL is not set +CONFIG_MPILIB=y +CONFIG_DIMLIB=y +CONFIG_LIBFDT=y +CONFIG_OID_REGISTRY=y +CONFIG_HAVE_GENERIC_VDSO=y +CONFIG_GENERIC_GETTIMEOFDAY=y +CONFIG_GENERIC_VDSO_TIME_NS=y +CONFIG_VDSO_GETRANDOM=y +CONFIG_FONT_SUPPORT=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +CONFIG_SG_POOL=y +CONFIG_ARCH_STACKWALK=y +CONFIG_SBITMAP=y +# CONFIG_LWQ_TEST is not set +# end of Library routines + +CONFIG_GENERIC_IOREMAP=y +CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y + +# +# Kernel hacking +# + +# +# printk and dmesg options +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_PRINTK_CALLER is not set +# CONFIG_STACKTRACE_BUILD_ID is not set +CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7 +CONFIG_CONSOLE_LOGLEVEL_QUIET=4 +CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 +# CONFIG_BOOT_PRINTK_DELAY is not set +CONFIG_DYNAMIC_DEBUG=y +CONFIG_DYNAMIC_DEBUG_CORE=y +CONFIG_SYMBOLIC_ERRNAME=y +CONFIG_DEBUG_BUGVERBOSE=y +# end of printk and dmesg options + +# CONFIG_DEBUG_KERNEL is not set +CONFIG_DEBUG_MISC=y + +# +# Compile-time checks and compiler options +# +CONFIG_AS_HAS_NON_CONST_ULEB128=y +CONFIG_DEBUG_INFO_NONE=y +# CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT is not set +# CONFIG_DEBUG_INFO_DWARF4 is not set +# CONFIG_DEBUG_INFO_DWARF5 is not set +CONFIG_FRAME_WARN=2048 +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_READABLE_ASM is not set +# CONFIG_HEADERS_INSTALL is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_SECTION_MISMATCH_WARN_ONLY=y +# CONFIG_DEBUG_FORCE_FUNCTION_ALIGN_64B is not set +CONFIG_ARCH_WANT_FRAME_POINTERS=y +CONFIG_FRAME_POINTER=y +# CONFIG_VMLINUX_MAP is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# end of Compile-time checks and compiler options + +# +# Generic Kernel Debugging Instruments +# +# CONFIG_MAGIC_SYSRQ is not set +CONFIG_DEBUG_FS=y +CONFIG_DEBUG_FS_ALLOW_ALL=y +# CONFIG_DEBUG_FS_DISALLOW_MOUNT is not set +# CONFIG_DEBUG_FS_ALLOW_NONE is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +CONFIG_ARCH_HAS_UBSAN=y +# CONFIG_UBSAN is not set +CONFIG_HAVE_ARCH_KCSAN=y +CONFIG_HAVE_KCSAN_COMPILER=y +# CONFIG_KCSAN is not set +# end of Generic Kernel Debugging Instruments + +# +# Networking Debugging +# +# CONFIG_NET_DEV_REFCNT_TRACKER is not set +# CONFIG_NET_NS_REFCNT_TRACKER is not set +# CONFIG_DEBUG_NET is not set +# end of Networking Debugging + +# +# Memory Debugging +# +# CONFIG_PAGE_EXTENSION is not set +# CONFIG_DEBUG_PAGEALLOC is not set +# CONFIG_SLUB_DEBUG is not set +# CONFIG_PAGE_OWNER is not set +# CONFIG_PAGE_TABLE_CHECK is not set +# CONFIG_PAGE_POISONING is not set +# CONFIG_DEBUG_RODATA_TEST is not set +CONFIG_ARCH_HAS_DEBUG_WX=y +# CONFIG_DEBUG_WX is not set +CONFIG_GENERIC_PTDUMP=y +# CONFIG_PTDUMP_DEBUGFS is not set +CONFIG_HAVE_DEBUG_KMEMLEAK=y +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_PER_VMA_LOCK_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SHRINKER_DEBUG is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_SCHED_STACK_END_CHECK is not set +CONFIG_ARCH_HAS_DEBUG_VM_PGTABLE=y +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_VM_PGTABLE is not set +CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y +# CONFIG_DEBUG_VIRTUAL is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_PER_CPU_MAPS is not set +# CONFIG_MEM_ALLOC_PROFILING is not set +CONFIG_HAVE_ARCH_KASAN=y +CONFIG_HAVE_ARCH_KASAN_SW_TAGS=y +CONFIG_HAVE_ARCH_KASAN_VMALLOC=y +CONFIG_CC_HAS_KASAN_GENERIC=y +CONFIG_CC_HAS_KASAN_SW_TAGS=y +CONFIG_CC_HAS_WORKING_NOSANITIZE_ADDRESS=y +# CONFIG_KASAN is not set +CONFIG_HAVE_ARCH_KFENCE=y +# CONFIG_KFENCE is not set +# end of Memory Debugging + +# CONFIG_DEBUG_SHIRQ is not set + +# +# Debug Oops, Lockups and Hangs +# +# CONFIG_PANIC_ON_OOPS is not set +CONFIG_PANIC_ON_OOPS_VALUE=0 +CONFIG_PANIC_TIMEOUT=1 +# CONFIG_SOFTLOCKUP_DETECTOR is not set +CONFIG_HAVE_HARDLOCKUP_DETECTOR_BUDDY=y +# CONFIG_HARDLOCKUP_DETECTOR is not set +# CONFIG_DETECT_HUNG_TASK is not set +# CONFIG_WQ_WATCHDOG is not set +# CONFIG_WQ_CPU_INTENSIVE_REPORT is not set +# CONFIG_TEST_LOCKUP is not set +# end of Debug Oops, Lockups and Hangs + +# +# Scheduler Debugging +# +# CONFIG_SCHED_DEBUG is not set +CONFIG_SCHED_INFO=y +# CONFIG_SCHEDSTATS is not set +# end of Scheduler Debugging + +# +# Lock Debugging (spinlocks, mutexes, etc...) +# +CONFIG_LOCK_DEBUGGING_SUPPORT=y +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set +# CONFIG_DEBUG_RWSEMS is not set +# CONFIG_DEBUG_LOCK_ALLOC 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_WW_MUTEX_SELFTEST is not set +# CONFIG_SCF_TORTURE_TEST is not set +# CONFIG_CSD_LOCK_WAIT_DEBUG is not set +# end of Lock Debugging (spinlocks, mutexes, etc...) + +# CONFIG_DEBUG_IRQFLAGS is not set +# CONFIG_STACKTRACE is not set +# CONFIG_WARN_ALL_UNSEEDED_RANDOM is not set +# CONFIG_DEBUG_KOBJECT is not set + +# +# Debug kernel data structures +# +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_PLIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_MAPLE_TREE is not set +# end of Debug kernel data structures + +# +# RCU Debugging +# +# CONFIG_RCU_SCALE_TEST is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_REF_SCALE_TEST is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=21 +CONFIG_RCU_EXP_CPU_STALL_TIMEOUT=0 +# CONFIG_RCU_CPU_STALL_CPUTIME is not set +# CONFIG_RCU_TRACE is not set +# CONFIG_RCU_EQS_DEBUG is not set +# end of RCU Debugging + +# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set +# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set +# CONFIG_LATENCYTOP is not set +CONFIG_USER_STACKTRACE_SUPPORT=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_FREGS=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_SAMPLE_FTRACE_DIRECT=y +CONFIG_HAVE_SAMPLE_FTRACE_DIRECT_MULTI=y +CONFIG_STRICT_DEVMEM=y +# CONFIG_IO_STRICT_DEVMEM is not set + +# +# arm64 Debugging +# +# CONFIG_PID_IN_CONTEXTIDR is not set +# CONFIG_ARM64_RELOC_TEST is not set +# CONFIG_CORESIGHT is not set +# end of arm64 Debugging + +# +# Kernel Testing and Coverage +# +# CONFIG_KUNIT is not set +# CONFIG_NOTIFIER_ERROR_INJECTION is not set +# CONFIG_FAULT_INJECTION is not set +CONFIG_ARCH_HAS_KCOV=y +CONFIG_CC_HAS_SANCOV_TRACE_PC=y +# CONFIG_KCOV is not set +# CONFIG_RUNTIME_TESTING_MENU is not set +CONFIG_ARCH_USE_MEMTEST=y +CONFIG_MEMTEST=y +# end of Kernel Testing and Coverage + +# +# Rust hacking +# +# end of Rust hacking +# end of Kernel hacking diff --git a/projects/ArchR/devices/RK3326/options b/projects/ArchR/devices/RK3326/options new file mode 100644 index 0000000000..4831265998 --- /dev/null +++ b/projects/ArchR/devices/RK3326/options @@ -0,0 +1,85 @@ +################################################################################ +# setup device defaults +################################################################################ + + # Device name for image filenames (overrides DEVICE in image name only) + DEVICE_NAME="R36S" + + # The TARGET_CPU variable controls which processor should be targeted for + # generated code. + case ${TARGET_ARCH} in + aarch64) + TARGET_KERNEL_ARCH="arm64" + TARGET_KERNEL_PATCH_ARCH="aarch64" + TARGET_CPU="cortex-a35" + TARGET_ARCH_FLAGS="+crc+fp+simd" + TARGET_FEATURES="64bit" + ;; + arm) + TARGET_KERNEL_ARCH="arm64" + TARGET_KERNEL_PATCH_ARCH="aarch64" + TARGET_FLOAT="hard" + TARGET_CPU="cortex-a35" + TARGET_ARCH_FLAGS="+crc" + TARGET_FPU="crypto-neon-fp-armv8" + TARGET_FEATURES="32bit" + ;; + esac + + PARTITION_TABLE="msdos" + HW_CPU="Rockchip RK3326" + + # Kernel target + KERNEL_TARGET="Image" + + # Kernel extra targets to build + KERNEL_MAKE_EXTRACMD=" $(get_kernel_make_extracmd)" + + # Kernel cmdline + EXTRA_CMDLINE="quiet console=ttyS2,1500000 console=tty0 loglevel=0 vt.global_cursor_default=0 consoleblank=0 net.ifnames=0 systemd.show_status=false mitigations=off audit=0 nowatchdog threadirqs zswap.enabled=0 loop.max_loop=16" + + # Bootloader to use (syslinux / u-boot) + BOOTLOADER="u-boot" + + # U-Boot firmware package(s) to use + UBOOT_FIRMWARE="rkbin" + + # Mali GPU family + MALI_FAMILY="bifrost-g31" + GRAPHIC_DRIVERS="mali panfrost" + + # For maximum cross compatbility + PREFER_GLES="yes" + + # Displayserver to use (wl / no) + DISPLAYSERVER="wl" + + # Windowmanager to use (weston / swaywm-env / no) + WINDOWMANAGER="swaywm-env" + + # 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 RTL8814AU RTL8821AU RTL8821CU RTL88x2BU RTL8831 AIC8800 mali-bifrost" + + # Additional Firmware to use ( ) + # Space separated list is supported, + # e.g. FIRMWARE="" + FIRMWARE="esp8089-firmware" + + # Additional packages to install + ADDITIONAL_PACKAGES="device-switch libmali generic-dsi" + ADDITIONAL_PACKAGES_32BIT="libmali" + + # Debug tty path + DEBUG_TTY="/dev/ttyS2" + + # ZRAM Algorithm + ZRAM_COMPRESSION_ALGO="lzo-rle" + + # ZRAM Size + ZRAM_SWAP_SIZE="512" + + # Disk Swap + SWAP_FILE_SIZE="0" diff --git a/projects/ArchR/devices/RK3326/packages/u-boot-legacy/package.mk b/projects/ArchR/devices/RK3326/packages/u-boot-legacy/package.mk new file mode 100644 index 0000000000..5ddaa4b7f6 --- /dev/null +++ b/projects/ArchR/devices/RK3326/packages/u-boot-legacy/package.mk @@ -0,0 +1,59 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="u-boot-legacy" +PKG_VERSION="2492a3e467e332e2350d987234ce6123700b3392" +PKG_LICENSE="GPL" +PKG_SITE="https://www.denx.de/wiki/U-Boot" +PKG_URL="https://github.com/archr-linux/hardkernel-uboot/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain Python3:host swig:host pyelftools:host" +PKG_LONGDESC="Das U-Boot is a cross-platform bootloader for embedded systems." +PKG_BUILD_FLAGS="-parallel" +PKG_TOOLCHAIN="manual" + +PKG_NEED_UNPACK="${PROJECT_DIR}/${PROJECT}/bootloader ${PROJECT_DIR}/${PROJECT}/devices/${DEVICE}/bootloader" +PKG_NEED_UNPACK+=" ${PROJECT_DIR}/${PROJECT}/options ${PROJECT_DIR}/${PROJECT}/devices/${DEVICE}/options" + +if [ -n "${UBOOT_FIRMWARE}" ]; then + PKG_DEPENDS_TARGET+=" ${UBOOT_FIRMWARE}" + PKG_DEPENDS_UNPACK+=" ${UBOOT_FIRMWARE}" +fi + +post_unpack() { + # Fix BSP U-Boot to load DTBs from dtbs/ subfolder and use correct DTB names + # board.c: fatload from dtbs/ instead of root + sed -i 's|fatload mmc 1:1 ${fdt_addr_r} ${dtb_name}|fatload mmc 1:1 ${fdt_addr_r} dtbs/${dtb_name}|' \ + ${PKG_BUILD}/arch/arm/mach-rockchip/board.c + + # hwrev.c: use correct DTB names matching kernel device trees + sed -i \ + -e 's|rk3326-odroidgo2-linux-v11.dtb|rk3326-odroid-go2-v11.dtb|' \ + -e 's|rk3326-odroidgo2-linux.dtb|rk3326-odroid-go2.dtb|' \ + -e 's|rk3326-odroidgo3-linux.dtb|rk3326-odroid-go3.dtb|' \ + ${PKG_BUILD}/cmd/hwrev.c +} + +pre_make_target() { + PKG_UBOOT_CONFIG="archr_rk3326_defconfig" + PKG_RKBIN="$(get_build_dir rkbin)" + PKG_MINILOADER="${PKG_RKBIN}/bin/rk33/rk3326_miniloader_v1.40.bin" + PKG_BL31="${PKG_RKBIN}/bin/rk33/rk3326_bl31_v1.34.elf" + PKG_DDR_BIN="${PKG_RKBIN}/bin/rk33/rk3326_ddr_333MHz_v2.11.bin" +} + +make_target() { + [ "${BUILD_WITH_DEBUG}" = "yes" ] && PKG_DEBUG=1 || PKG_DEBUG=0 + setup_pkg_config_host + + 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 ${PKG_UBOOT_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" + + find_file_path bootloader/rkhelper && . ${FOUND_PATH} +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/share/bootloader + + cp -av uboot.bin $INSTALL/usr/share/bootloader/original_uboot.bin +} diff --git a/projects/ArchR/devices/RK3326/packages/u-boot-legacy/sources/configs/archr_rk3326_defconfig b/projects/ArchR/devices/RK3326/packages/u-boot-legacy/sources/configs/archr_rk3326_defconfig new file mode 100644 index 0000000000..2ddff93ae3 --- /dev/null +++ b/projects/ArchR/devices/RK3326/packages/u-boot-legacy/sources/configs/archr_rk3326_defconfig @@ -0,0 +1,1369 @@ +# +# Automatically generated file; DO NOT EDIT. +# U-Boot 2017.09 Configuration +# +CONFIG_CREATE_ARCH_SYMLINK=y +# CONFIG_ARC is not set +CONFIG_ARM=y +# CONFIG_M68K is not set +# CONFIG_MICROBLAZE is not set +# CONFIG_MIPS is not set +# CONFIG_NDS32 is not set +# CONFIG_NIOS2 is not set +# CONFIG_PPC is not set +# CONFIG_SANDBOX is not set +# CONFIG_SH is not set +# CONFIG_X86 is not set +# CONFIG_XTENSA is not set +CONFIG_SYS_ARCH="arm" +CONFIG_SYS_CPU="armv8" +CONFIG_SYS_SOC="rockchip" +CONFIG_SYS_VENDOR="rockchip" +CONFIG_SYS_BOARD="odroidgoa" +CONFIG_SYS_CONFIG_NAME="odroidgoa" + +# +# ARM architecture +# +CONFIG_ARM64=y +# CONFIG_POSITION_INDEPENDENT is not set +CONFIG_STATIC_RELA=y +CONFIG_DMA_ADDR_T_64BIT=y +CONFIG_ARM_ASM_UNIFIED=y +CONFIG_SYS_ARM_ARCH=8 +CONFIG_SYS_CACHE_SHIFT_6=y +CONFIG_SYS_CACHELINE_SIZE=64 +CONFIG_ARM_SMCCC=y +CONFIG_ARM_CPU_SUSPEND=y +# CONFIG_SEMIHOSTING is not set +# CONFIG_SYS_L2CACHE_OFF is not set +CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK=y +# CONFIG_ARM_CORTEX_CPU_IS_UP is not set +CONFIG_ARM64_SUPPORT_AARCH32=y +# CONFIG_ARCH_AT91 is not set +# CONFIG_TARGET_EDB93XX is not set +# CONFIG_TARGET_ASPENITE is not set +# CONFIG_TARGET_GPLUGD is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_KIRKWOOD is not set +# CONFIG_ARCH_MVEBU is not set +# CONFIG_TARGET_DEVKIT3250 is not set +# CONFIG_TARGET_WORK_92105 is not set +# CONFIG_TARGET_MX25PDK is not set +# CONFIG_TARGET_ZMX25 is not set +# CONFIG_TARGET_APF27 is not set +# CONFIG_TARGET_APX4DEVKIT is not set +# CONFIG_TARGET_XFI3 is not set +# CONFIG_TARGET_M28EVK is not set +# CONFIG_TARGET_MX23EVK is not set +# CONFIG_TARGET_MX28EVK is not set +# CONFIG_TARGET_MX23_OLINUXINO is not set +# CONFIG_TARGET_BG0900 is not set +# CONFIG_TARGET_SANSA_FUZE_PLUS is not set +# CONFIG_TARGET_SC_SPS_1 is not set +# CONFIG_ORION5X is not set +# CONFIG_TARGET_SPEAR300 is not set +# CONFIG_TARGET_SPEAR310 is not set +# CONFIG_TARGET_SPEAR320 is not set +# CONFIG_TARGET_SPEAR600 is not set +# CONFIG_TARGET_STV0991 is not set +# CONFIG_TARGET_X600 is not set +# CONFIG_TARGET_IMX31_PHYCORE is not set +# CONFIG_TARGET_IMX31_PHYCORE_EET is not set +# CONFIG_TARGET_MX31ADS is not set +# CONFIG_TARGET_MX31PDK is not set +# CONFIG_TARGET_WOODBURN is not set +# CONFIG_TARGET_WOODBURN_SD is not set +# CONFIG_TARGET_FLEA3 is not set +# CONFIG_TARGET_MX35PDK is not set +# CONFIG_ARCH_BCM283X is not set +# CONFIG_TARGET_VEXPRESS_CA15_TC2 is not set +# CONFIG_TARGET_VEXPRESS_CA5X2 is not set +# CONFIG_TARGET_VEXPRESS_CA9X4 is not set +# CONFIG_TARGET_BCM23550_W1D is not set +# CONFIG_TARGET_BCM28155_AP is not set +# CONFIG_TARGET_BCMCYGNUS is not set +# CONFIG_TARGET_BCMNSP is not set +# CONFIG_TARGET_BCMNS2 is not set +# CONFIG_ARCH_EXYNOS is not set +# CONFIG_ARCH_S5PC1XX is not set +# CONFIG_ARCH_HIGHBANK is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_KEYSTONE is not set +# CONFIG_ARCH_OMAP2PLUS is not set +# CONFIG_ARCH_MESON is not set +# CONFIG_ARCH_MX7ULP is not set +# CONFIG_ARCH_MX7 is not set +# CONFIG_ARCH_MX6 is not set +CONFIG_SPL_LDSCRIPT="arch/arm/cpu/armv8/u-boot-spl.lds" +# CONFIG_ARCH_MX5 is not set +# CONFIG_ARCH_RMOBILE is not set +# CONFIG_TARGET_S32V234EVB is not set +# CONFIG_ARCH_SNAPDRAGON is not set +# CONFIG_ARCH_SOCFPGA is not set +# CONFIG_ARCH_SUNXI is not set +# CONFIG_TARGET_TS4600 is not set +# CONFIG_ARCH_VF610 is not set +# CONFIG_ARCH_ZYNQ is not set +# CONFIG_ARCH_ZYNQMP is not set +# CONFIG_TEGRA is not set +# CONFIG_TARGET_VEXPRESS64_AEMV8A is not set +# CONFIG_TARGET_VEXPRESS64_BASE_FVP is not set +# CONFIG_TARGET_VEXPRESS64_BASE_FVP_DRAM is not set +# CONFIG_TARGET_VEXPRESS64_JUNO is not set +# CONFIG_TARGET_LS2080A_EMU is not set +# CONFIG_TARGET_LS2080A_SIMU is not set +# CONFIG_TARGET_LS2080AQDS is not set +# CONFIG_TARGET_LS2080ARDB is not set +# CONFIG_TARGET_LS2081ARDB is not set +# CONFIG_TARGET_HIKEY is not set +# CONFIG_TARGET_POPLAR is not set +# CONFIG_TARGET_LS1012AQDS is not set +# CONFIG_TARGET_LS1012ARDB is not set +# CONFIG_TARGET_LS1012AFRDM is not set +# CONFIG_TARGET_LS1021AQDS is not set +# CONFIG_TARGET_LS1021ATWR is not set +# CONFIG_TARGET_LS1021AIOT is not set +# CONFIG_TARGET_LS1043AQDS is not set +# CONFIG_TARGET_LS1043ARDB is not set +# CONFIG_TARGET_LS1046AQDS is not set +# CONFIG_TARGET_LS1046ARDB is not set +# CONFIG_TARGET_H2200 is not set +# CONFIG_TARGET_ZIPITZ2 is not set +# CONFIG_TARGET_COLIBRI_PXA270 is not set +# CONFIG_ARCH_UNIPHIER is not set +# CONFIG_STM32 is not set +# CONFIG_ARCH_STI is not set +CONFIG_ARCH_ROCKCHIP=y +# CONFIG_TARGET_THUNDERX_88XX is not set +# CONFIG_ARCH_ASPEED is not set +# CONFIG_SPL_GPIO_SUPPORT is not set +CONFIG_SPL_LIBCOMMON_SUPPORT=y +CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_ROCKCHIP_PX30=y +CONFIG_TPL_LDSCRIPT="arch/arm/mach-rockchip/u-boot-tpl-v8.lds" +CONFIG_TPL_TEXT_BASE=0xff0e1000 +CONFIG_TPL_MAX_SIZE=10240 +CONFIG_ROCKCHIP_RK3326=y +# CONFIG_ROCKCHIP_RK3036 is not set +# CONFIG_ROCKCHIP_RK3128 is not set +# CONFIG_ROCKCHIP_RK3066 is not set +# CONFIG_ROCKCHIP_RK3188 is not set +# CONFIG_ROCKCHIP_RK322X is not set +# CONFIG_ROCKCHIP_RK3288 is not set +CONFIG_SPL_FIT_GENERATOR="arch/arm/mach-rockchip/make_fit_atf.py" +# CONFIG_ROCKCHIP_RK3308 is not set +# CONFIG_ROCKCHIP_RK3328 is not set +# CONFIG_ROCKCHIP_RK3368 is not set +# CONFIG_ROCKCHIP_RK3399 is not set +# CONFIG_ROCKCHIP_RK1808 is not set +# CONFIG_ROCKCHIP_RV1108 is not set +# CONFIG_SPL_ROCKCHIP_BACK_TO_BROM is not set +CONFIG_TPL_ROCKCHIP_BACK_TO_BROM=y +# CONFIG_ARM64_BOOT_AARCH32 is not set +CONFIG_ROCKCHIP_BOOT_MODE_REG=0xff010200 +CONFIG_ROCKCHIP_STIMER_BASE=0xff220020 +CONFIG_ROCKCHIP_IRAM_START_ADDR=0xff0e0000 +CONFIG_ROCKCHIP_SPL_RESERVE_IRAM=0x0 +CONFIG_ROCKCHIP_BROM_HELPER=y +# CONFIG_SPL_ROCKCHIP_EARLYRETURN_TO_BROM is not set +# CONFIG_TPL_ROCKCHIP_EARLYRETURN_TO_BROM is not set +CONFIG_SPL_MMC_SUPPORT=y +CONFIG_RKIMG_BOOTLOADER=y +# CONFIG_RKIMG_ANDROID_BOOTMODE_LEGACY is not set +CONFIG_ROCKCHIP_RESOURCE_IMAGE=y +# CONFIG_ROCKCHIP_EARLY_DISTRO_DTB is not set +CONFIG_ROCKCHIP_VENDOR_PARTITION=y +CONFIG_USING_KERNEL_DTB=y +# CONFIG_ROCKCHIP_CRC is not set +CONFIG_ROCKCHIP_SMCCC=y +# CONFIG_ROCKCHIP_DEBUGGER is not set +# CONFIG_ROCKCHIP_CRASH_DUMP is not set +CONFIG_ROCKCHIP_PRELOADER_ATAGS=y +CONFIG_ROCKCHIP_PRELOADER_SERIAL=y +CONFIG_GICV2=y +# CONFIG_GICV3 is not set +# CONFIG_TARGET_EVB_PX30 is not set +CONFIG_PLATFORM_ODROID_GOADV=y +CONFIG_TARGET_ODROIDGOA=y +CONFIG_SPL_SERIAL_SUPPORT=y +CONFIG_BOARD_SPECIFIC_OPTIONS=y +# CONFIG_TPL_LIBCOMMON_SUPPORT is not set +# CONFIG_TPL_LIBGENERIC_SUPPORT is not set +CONFIG_SPL_DRIVERS_MISC_SUPPORT=y +CONFIG_ENV_SIZE=0x8000 +CONFIG_ENV_OFFSET=0x3f8000 +# CONFIG_SPL_LIBDISK_SUPPORT is not set +# CONFIG_SPL_NAND_SUPPORT is not set +# CONFIG_SPL_SPI_FLASH_SUPPORT is not set +# CONFIG_SPL_SPI_SUPPORT is not set +# CONFIG_SPL_WATCHDOG_SUPPORT is not set +CONFIG_IDENT_STRING="" +CONFIG_SPL_STACK_R_ADDR=0x600000 +# CONFIG_SPL_FAT_SUPPORT is not set +# CONFIG_ARMV8_MULTIENTRY is not set +# CONFIG_ARMV8_SET_SMPEN is not set + +# +# ARMv8 secure monitor firmware +# +# CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT is not set +# CONFIG_SPL_ARMV8_SEC_FIRMWARE_SUPPORT is not set +CONFIG_PSCI_RESET=y +# CONFIG_ARMV8_PSCI is not set +# CONFIG_CMD_DEKBLOB is not set +# CONFIG_CMD_HDMIDETECT is not set + +# +# ARM debug +# +CONFIG_DEFAULT_DEVICE_TREE="odroidgoa" +CONFIG_SMBIOS_PRODUCT_NAME="odroidgoa" +CONFIG_DEBUG_UART=y +# CONFIG_AHCI is not set + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_DISTRO_DEFAULTS=y +CONFIG_SYS_MALLOC_F=y +CONFIG_SPL_SYS_MALLOC_F_LEN=0x2000 +CONFIG_TPL_SYS_MALLOC_F_LEN=0x600 +CONFIG_EXPERT=y +CONFIG_SYS_MALLOC_CLEAR_ON_INIT=y +# CONFIG_TOOLS_DEBUG is not set +CONFIG_PHYS_64BIT=y + +# +# Boot images +# +# CONFIG_ANDROID_BOOT_IMAGE is not set +CONFIG_FIT=y +CONFIG_FIT_ENABLE_SHA256_SUPPORT=y +# CONFIG_FIT_SIGNATURE is not set +CONFIG_FIT_VERBOSE=y +# CONFIG_FIT_BEST_MATCH is not set +CONFIG_SPL_FIT=y +# CONFIG_SPL_FIT_SIGNATURE is not set +CONFIG_SPL_LOAD_FIT=y +# CONFIG_SPL_FIT_IMAGE_POST_PROCESS is not set +CONFIG_SPL_FIT_SOURCE="" +# CONFIG_OF_BOARD_SETUP is not set +# CONFIG_OF_SYSTEM_SETUP is not set +# CONFIG_OF_STDOUT_VIA_ALIAS is not set +CONFIG_SYS_EXTRA_OPTIONS="" +CONFIG_ARCH_FIXUP_FDT_MEMORY=y + +# +# API +# +# CONFIG_API is not set + +# +# Boot timing +# +# CONFIG_BOOTSTAGE is not set +CONFIG_BOOTSTAGE_USER_COUNT=20 +CONFIG_BOOTSTAGE_RECORD_COUNT=30 +CONFIG_BOOTSTAGE_STASH_ADDR=0 +CONFIG_BOOTSTAGE_STASH_SIZE=0x1000 +# CONFIG_BOOTSTAGE_PRINTF_TIMESTAMP is not set + +# +# Boot media +# +# CONFIG_NAND_BOOT is not set +# CONFIG_ONENAND_BOOT is not set +# CONFIG_QSPI_BOOT is not set +# CONFIG_SATA_BOOT is not set +CONFIG_SD_BOOT=y +# CONFIG_SPI_BOOT is not set +CONFIG_PASS_DEVICE_SERIAL_BY_FDT=y +CONFIG_BOOTDELAY=0 +# CONFIG_USE_BOOTARGS is not set + +# +# Console +# +CONFIG_MENU=y +# CONFIG_CONSOLE_RECORD is not set +# CONFIG_CONSOLE_DISABLE_CTRLC is not set +# CONFIG_DISABLE_CONSOLE is not set +CONFIG_LOGLEVEL=4 +CONFIG_SPL_LOGLEVEL=4 +# CONFIG_SILENT_CONSOLE is not set +# CONFIG_PRE_CONSOLE_BUFFER is not set +CONFIG_CONSOLE_MUX=y +CONFIG_SYS_CONSOLE_IS_IN_ENV=y +# CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE is not set +# CONFIG_SYS_CONSOLE_ENV_OVERWRITE is not set +# CONFIG_SYS_CONSOLE_INFO_QUIET is not set +# CONFIG_SYS_STDIO_DEREGISTER is not set + +# +# Logging +# +# CONFIG_LOG is not set +# CONFIG_SPL_LOG is not set +CONFIG_DEFAULT_FDT_FILE="" +# CONFIG_VERSION_VARIABLE is not set +CONFIG_BOARD_LATE_INIT=y +# CONFIG_DISPLAY_CPUINFO is not set +CONFIG_DISPLAY_BOARDINFO=y + +# +# Start-up hooks +# +# CONFIG_ARCH_EARLY_INIT_R is not set +# CONFIG_ARCH_MISC_INIT is not set +# CONFIG_BOARD_EARLY_INIT_F is not set +# CONFIG_BOARD_EARLY_INIT_R is not set +# CONFIG_ANDROID_AB is not set +CONFIG_ANDROID_WRITE_KEYBOX=y +# CONFIG_ANDROID_AVB is not set +CONFIG_ANDROID_KEYMASTER_CA=y +# CONFIG_SKIP_RELOCATE_UBOOT is not set + +# +# Security support +# +CONFIG_HASH=y + +# +# SPL / TPL +# +CONFIG_SUPPORT_SPL=y +CONFIG_SUPPORT_TPL=y +CONFIG_SPL=y +# CONFIG_SPL_BOARD_INIT is not set +# CONFIG_SPL_BOOTROM_SUPPORT is not set +CONFIG_SPL_RAW_IMAGE_SUPPORT=y +CONFIG_SPL_LEGACY_IMAGE_SUPPORT=y +CONFIG_SPL_SYS_MALLOC_SIMPLE=y +# CONFIG_TPL_SYS_MALLOC_SIMPLE is not set +CONFIG_SPL_STACK_R=y +CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x100000 +# CONFIG_SPL_SEPARATE_BSS is not set +# CONFIG_SPL_DISPLAY_PRINT is not set +CONFIG_SPL_SKIP_RELOCATE=y +CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y +CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x4000 +# CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION is not set +# CONFIG_SPL_CRC32_SUPPORT is not set +# CONFIG_SPL_MD5_SUPPORT is not set +# CONFIG_SPL_SHA1_SUPPORT is not set +# CONFIG_SPL_SHA256_SUPPORT is not set +# CONFIG_SPL_FIT_IMAGE_TINY is not set +# CONFIG_SPL_CPU_SUPPORT is not set +# CONFIG_SPL_CRYPTO_SUPPORT is not set +# CONFIG_SPL_HASH_SUPPORT is not set +# CONFIG_SPL_DMA_SUPPORT is not set +# CONFIG_SPL_ENV_SUPPORT is not set +# CONFIG_SPL_EXT_SUPPORT is not set +# CONFIG_SPL_FPGA_SUPPORT is not set +# CONFIG_SPL_I2C_SUPPORT is not set +# CONFIG_SPL_MPC8XXX_INIT_DDR_SUPPORT is not set +# CONFIG_SPL_MTD_SUPPORT is not set +# CONFIG_SPL_MUSB_NEW_SUPPORT is not set +# CONFIG_SPL_NET_SUPPORT is not set +# CONFIG_SPL_NO_CPU_SUPPORT is not set +# CONFIG_SPL_NOR_SUPPORT is not set +# CONFIG_SPL_XIP_SUPPORT is not set +# CONFIG_SPL_ONENAND_SUPPORT is not set +# CONFIG_SPL_OS_BOOT is not set +# CONFIG_SPL_PCI_SUPPORT is not set +# CONFIG_SPL_PCH_SUPPORT is not set +# CONFIG_SPL_POST_MEM_SUPPORT is not set +# CONFIG_SPL_POWER_SUPPORT is not set +# CONFIG_SPL_RAM_SUPPORT is not set +# CONFIG_SPL_RTC_SUPPORT is not set +# CONFIG_SPL_SATA_SUPPORT is not set +# CONFIG_SPL_USB_HOST_SUPPORT is not set +# CONFIG_SPL_USB_GADGET_SUPPORT is not set +# CONFIG_SPL_YMODEM_SUPPORT is not set +CONFIG_SPL_ATF=y +# CONFIG_SPL_OPTEE_SUPPORT is not set +CONFIG_SPL_ATF_NO_PLATFORM_PARAM=y +# CONFIG_SPL_OPTEE is not set +# CONFIG_SPL_AB is not set +# CONFIG_SPL_LOAD_RKFW is not set +CONFIG_TPL=y +# CONFIG_TPL_BOARD_INIT is not set +# CONFIG_TPL_NEEDS_SEPARATE_TEXT_BASE is not set +# CONFIG_TPL_NEEDS_SEPARATE_STACK is not set +# CONFIG_TPL_BOOTROM_SUPPORT is not set +# CONFIG_TPL_DRIVERS_MISC_SUPPORT is not set +# CONFIG_TPL_ENV_SUPPORT is not set +# CONFIG_TPL_I2C_SUPPORT is not set +CONFIG_TPL_TINY_FRAMEWORK=y +# CONFIG_TPL_MPC8XXX_INIT_DDR_SUPPORT is not set +# CONFIG_TPL_MMC_SUPPORT is not set +# CONFIG_TPL_NAND_SUPPORT is not set +CONFIG_TPL_SERIAL_SUPPORT=y +# CONFIG_TPL_SPI_FLASH_SUPPORT is not set +# CONFIG_TPL_SPI_SUPPORT is not set + +# +# Command line interface +# +CONFIG_CMDLINE=y +CONFIG_HUSH_PARSER=y +CONFIG_SYS_PROMPT="=> " + +# +# Autoboot options +# +CONFIG_AUTOBOOT=y +# CONFIG_AUTOBOOT_KEYED is not set + +# +# FASTBOOT +# +# CONFIG_FASTBOOT is not set + +# +# Commands +# + +# +# Info commands +# +CONFIG_CMD_BDI=y +# CONFIG_CMD_CONFIG is not set +CONFIG_CMD_CONSOLE=y +# CONFIG_CMD_CPU is not set +# CONFIG_CMD_LICENSE is not set + +# +# Boot commands +# +CONFIG_CMD_BOOTD=y +CONFIG_CMD_BOOTM=y +# CONFIG_CMD_BOOTZ is not set +CONFIG_CMD_BOOTI=y +CONFIG_CMD_BOOTEFI=y +CONFIG_CMD_BOOTEFI_HELLO_COMPILE=y +# CONFIG_CMD_BOOTEFI_HELLO is not set +# CONFIG_CMD_BOOTMENU is not set +# CONFIG_CMD_DTIMG is not set +CONFIG_CMD_ELF=y +CONFIG_CMD_FDT=y +CONFIG_CMD_GO=y +CONFIG_CMD_RUN=y +CONFIG_CMD_IMI=y +# CONFIG_CMD_IMLS is not set +CONFIG_CMD_XIMG=y +CONFIG_CMD_POWEROFF=y +# CONFIG_CMD_SPL is not set +# CONFIG_CMD_THOR_DOWNLOAD is not set +# CONFIG_CMD_ZBOOT is not set + +# +# Environment commands +# +# CONFIG_CMD_ASKENV is not set +CONFIG_CMD_EXPORTENV=y +CONFIG_CMD_IMPORTENV=y +CONFIG_CMD_EDITENV=y +# CONFIG_CMD_GREPENV is not set +CONFIG_CMD_SAVEENV=y +CONFIG_CMD_ENV_EXISTS=y +# CONFIG_CMD_ENV_CALLBACK is not set +# CONFIG_CMD_ENV_FLAGS is not set + +# +# Memory commands +# +CONFIG_CMD_CRC32=y +# CONFIG_CRC32_VERIFY is not set +# CONFIG_CMD_EEPROM is not set +# CONFIG_LOOPW is not set +CONFIG_CMD_MD5SUM=y +CONFIG_MD5SUM_VERIFY=y +# CONFIG_CMD_MEMINFO is not set +CONFIG_CMD_MEMORY=y +# CONFIG_CMD_MEMTEST is not set +# CONFIG_CMD_MX_CYCLIC is not set +# CONFIG_CMD_SHA1SUM is not set +# CONFIG_CMD_STRINGS is not set + +# +# Compression commands +# +CONFIG_CMD_LZMADEC=y +CONFIG_CMD_UNZIP=y +# CONFIG_CMD_ZIP is not set + +# +# Device access commands +# +# CONFIG_CMD_ARMFLASH is not set +CONFIG_CMD_CLK=y +# CONFIG_CMD_DEMO is not set +# CONFIG_CMD_DFU is not set +CONFIG_CMD_DM=y +# CONFIG_CMD_FDC is not set +# CONFIG_CMD_FLASH is not set +# CONFIG_CMD_FPGA is not set +# CONFIG_CMD_FPGAD is not set +# CONFIG_CMD_FUSE is not set +CONFIG_CMD_GPIO=y +CONFIG_CMD_GPT=y +CONFIG_RANDOM_UUID=y +# CONFIG_CMD_GPT_RENAME is not set +# CONFIG_CMD_IDE is not set +# CONFIG_CMD_IO is not set +# CONFIG_CMD_IOTRACE is not set +CONFIG_CMD_I2C=y +CONFIG_CMD_LOADB=y +CONFIG_CMD_LOADS=y +CONFIG_CMD_BOOT_ROCKCHIP=y +CONFIG_CMD_MMC=y +# CONFIG_CMD_MTD is not set +# CONFIG_CMD_NAND is not set +# CONFIG_CMD_MMC_SPI is not set +# CONFIG_CMD_ONENAND is not set +CONFIG_CMD_PART=y +# CONFIG_CMD_PCI is not set +# CONFIG_CMD_PCMCIA is not set +# CONFIG_CMD_READ is not set +CONFIG_CMD_ROCKUSB=y +# CONFIG_CMD_RKNAND is not set +CONFIG_CMD_RKSFC=y +# CONFIG_CMD_RK_SECURE_STORAGE is not set +# CONFIG_CMD_SATA is not set +# CONFIG_CMD_SAVES is not set +# CONFIG_CMD_SDRAM is not set +CONFIG_CMD_SF=y +# CONFIG_CMD_SF_TEST is not set +CONFIG_CMD_SPI=y +# CONFIG_CMD_TSI148 is not set +# CONFIG_CMD_UNIVERSE is not set +CONFIG_CMD_USB=y +# CONFIG_CMD_USB_SDP is not set +CONFIG_CMD_USB_MASS_STORAGE=y + +# +# Shell scripting commands +# +CONFIG_CMD_ECHO=y +CONFIG_CMD_ITEST=y +CONFIG_CMD_SOURCE=y +CONFIG_CMD_SETEXPR=y + +# +# Network commands +# +CONFIG_CMD_NET=y +# CONFIG_CMD_TFTPPUT is not set +# CONFIG_CMD_TFTPSRV is not set +# CONFIG_CMD_RARP is not set +CONFIG_CMD_DHCP=y +CONFIG_CMD_PXE=y +CONFIG_CMD_NFS=y +CONFIG_CMD_MII=y +CONFIG_CMD_PING=y +CONFIG_CMD_CDP=y +CONFIG_CMD_SNTP=y +CONFIG_CMD_DNS=y +CONFIG_CMD_LINK_LOCAL=y +CONFIG_CMD_ETHSW=y +CONFIG_CMD_MEMTESTER=y +# CONFIG_CMD_DDR_TEST_TOOL is not set + +# +# Misc commands +# +CONFIG_CMD_BMP=y +# CONFIG_CMD_BSP is not set +# CONFIG_CMD_BKOPS_ENABLE is not set +# CONFIG_CMD_CACHE is not set +# CONFIG_CMD_DISPLAY is not set +CONFIG_CMD_LED=y +# CONFIG_CMD_DATE is not set +# CONFIG_CMD_TIME is not set +# CONFIG_CMD_GETTIME is not set +CONFIG_CMD_MISC=y +CONFIG_CMD_TIMER=y +CONFIG_CMD_SOUND=y +# CONFIG_CMD_QFW is not set +# CONFIG_CMD_TERMINAL is not set +# CONFIG_CMD_UUID is not set + +# +# Power commands +# +CONFIG_CMD_PMIC=y +CONFIG_CMD_REGULATOR=y +CONFIG_CMD_CHARGE_DISPLAY=y + +# +# Security commands +# +# CONFIG_CMD_AES is not set +# CONFIG_CMD_BLOB is not set +# CONFIG_CMD_HASH is not set + +# +# Firmware commands +# + +# +# Filesystem commands +# +CONFIG_CMD_EXT2=y +CONFIG_CMD_EXT4=y +CONFIG_CMD_EXT4_WRITE=y +CONFIG_CMD_FAT=y +CONFIG_CMD_FS_GENERIC=y +CONFIG_CMD_FS_UUID=y +# CONFIG_CMD_JFFS2 is not set +# CONFIG_CMD_MTDPARTS is not set +# CONFIG_CMD_MTD_BLK is not set +# CONFIG_CMD_REISER is not set +# CONFIG_CMD_SCSI is not set +# CONFIG_CMD_ZFS is not set + +# +# Debug commands +# +# CONFIG_CMD_BEDBUG is not set +# CONFIG_CMD_DIAG is not set +# CONFIG_CMD_KGDB is not set +# CONFIG_CMD_LOG is not set +# CONFIG_CMD_TRACE is not set +# CONFIG_CMD_UBI is not set + +# +# ODROID commands +# +CONFIG_CMD_ODROID_ADC=y +CONFIG_CMD_ODROID_CFGLOAD=y +CONFIG_CMD_ODROID_BATTERY=y +CONFIG_CMD_ODROID_TEST=y +CONFIG_CMD_ODROID_HWREV=y + +# +# Partition Types +# +CONFIG_PARTITIONS=y +# CONFIG_MAC_PARTITION is not set +# CONFIG_SPL_MAC_PARTITION is not set +CONFIG_DOS_PARTITION=y +CONFIG_SPL_DOS_PARTITION=y +CONFIG_ISO_PARTITION=y +CONFIG_SPL_ISO_PARTITION=y +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_SPL_AMIGA_PARTITION is not set +CONFIG_EFI_PARTITION=y +CONFIG_EFI_PARTITION_ENTRIES_NUMBERS=128 +CONFIG_EFI_PARTITION_ENTRIES_OFF=0 +CONFIG_SPL_EFI_PARTITION=y +CONFIG_PARTITION_UUIDS=y +CONFIG_SPL_PARTITION_UUIDS=y +# CONFIG_PARTITION_TYPE_GUID is not set +CONFIG_RKPARM_PARTITION=y +# CONFIG_SPL_ROCKCHIP_PARTITION is not set +CONFIG_SUPPORT_OF_CONTROL=y +CONFIG_DTC=y + +# +# Device Tree Control +# +CONFIG_OF_CONTROL=y +# CONFIG_OF_BOARD_FIXUP is not set +CONFIG_SPL_OF_CONTROL=y +# CONFIG_TPL_OF_CONTROL is not set +CONFIG_OF_LIVE=y +CONFIG_OF_SEPARATE=y +# CONFIG_OF_EMBED is not set +# CONFIG_OF_BOARD is not set +CONFIG_OF_LIST="odroidgoa" +# CONFIG_MULTI_DTB_FIT is not set +# CONFIG_SPL_MULTI_DTB_FIT is not set +CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" +# CONFIG_SPL_OF_PLATDATA is not set +CONFIG_MKIMAGE_DTC_PATH="dtc" + +# +# Environment +# +# CONFIG_ENV_IS_NOWHERE is not set +# CONFIG_ENV_IS_IN_EEPROM is not set +# CONFIG_ENV_IS_IN_FAT is not set +# CONFIG_ENV_IS_IN_FLASH is not set +CONFIG_ENV_IS_IN_MMC=y +# CONFIG_ENV_IS_IN_NAND is not set +# CONFIG_ENV_IS_IN_NVRAM is not set +# CONFIG_ENV_IS_IN_ONENAND is not set +# CONFIG_ENV_IS_IN_REMOTE is not set +# CONFIG_ENV_IS_IN_SPI_FLASH is not set +# CONFIG_ENV_IS_IN_UBI is not set +# CONFIG_ENV_IS_IN_BLK_DEV is not set +# CONFIG_ENV_AES is not set +CONFIG_NET=y +# CONFIG_NET_RANDOM_ETHADDR is not set +# CONFIG_NETCONSOLE is not set +CONFIG_NET_TFTP_VARS=y +CONFIG_BOOTP_PXE_CLIENTARCH=0x16 +CONFIG_BOOTP_VCI_STRING="U-Boot.armv8" + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_DM=y +CONFIG_SPL_DM=y +# CONFIG_TPL_DM is not set +CONFIG_DM_WARN=y +# CONFIG_DM_DEBUG is not set +CONFIG_DM_DEVICE_REMOVE=y +CONFIG_DM_STDIO=y +CONFIG_DM_SEQ_ALIAS=y +# CONFIG_SPL_DM_SEQ_ALIAS is not set +CONFIG_REGMAP=y +CONFIG_SPL_REGMAP=y +CONFIG_SYSCON=y +CONFIG_SPL_SYSCON=y +# CONFIG_DEVRES is not set +CONFIG_SIMPLE_BUS=y +CONFIG_SPL_SIMPLE_BUS=y +CONFIG_OF_TRANSLATE=y +# CONFIG_SPL_OF_TRANSLATE is not set +CONFIG_ADC=y +# CONFIG_ADC_EXYNOS is not set +# CONFIG_ADC_SANDBOX is not set +CONFIG_SARADC_ROCKCHIP=y +# CONFIG_SATA is not set + +# +# SATA/SCSI device support +# +CONFIG_BLK=y +CONFIG_SPL_BLK=y +# CONFIG_BLOCK_CACHE is not set +# CONFIG_IDE is not set + +# +# Boot count support +# +# CONFIG_BOOTCOUNT is not set + +# +# Clock +# +CONFIG_CLK=y +CONFIG_SPL_CLK=y +# CONFIG_CLK_AT91 is not set +# CONFIG_CPU is not set +# CONFIG_AMP is not set + +# +# Hardware crypto devices +# +# CONFIG_DM_CRYPTO is not set +# CONFIG_SPL_DM_CRYPTO is not set +# CONFIG_FSL_CAAM is not set +# CONFIG_SYS_FSL_SEC_BE is not set +# CONFIG_SYS_FSL_SEC_LE is not set + +# +# Demo for driver model +# +# CONFIG_DM_DEMO is not set + +# +# DFU support +# + +# +# DMA Support +# +# CONFIG_DMA is not set +# CONFIG_TI_EDMA3 is not set +CONFIG_FIRMWARE=y +CONFIG_ARM_PSCI_FW=y + +# +# FPGA support +# +# CONFIG_FPGA_ALTERA is not set +# CONFIG_FPGA_SOCFPGA is not set +# CONFIG_FPGA_XILINX is not set + +# +# GPIO Support +# +CONFIG_DM_GPIO=y +# CONFIG_ALTERA_PIO is not set +# CONFIG_DWAPB_GPIO is not set +# CONFIG_AT91_GPIO is not set +# CONFIG_ATMEL_PIO4 is not set +# CONFIG_INTEL_BROADWELL_GPIO is not set +# CONFIG_INTEL_ICH6_GPIO is not set +# CONFIG_IMX_RGPIO2P is not set +# CONFIG_LPC32XX_GPIO is not set +# CONFIG_MSM_GPIO is not set +# CONFIG_CMD_PCA953X is not set +# CONFIG_PCF8575_GPIO is not set +CONFIG_ROCKCHIP_GPIO=y +# CONFIG_CMD_TCA642X is not set +# CONFIG_TEGRA_GPIO is not set +# CONFIG_TEGRA186_GPIO is not set +# CONFIG_VYBRID_GPIO is not set +# CONFIG_DM_74X164 is not set +# CONFIG_DM_PCA953X is not set +# CONFIG_MPC85XX_GPIO is not set + +# +# I2C support +# +CONFIG_DM_I2C=y +# CONFIG_DM_I2C_COMPAT is not set +# CONFIG_I2C_SET_DEFAULT_BUS_NUM is not set +# CONFIG_DM_I2C_GPIO is not set +# CONFIG_SYS_I2C_FSL is not set +# CONFIG_SYS_I2C_CADENCE is not set +# CONFIG_SYS_I2C_DW is not set +# CONFIG_SYS_I2C_INTEL is not set +# CONFIG_SYS_I2C_IMX_LPI2C is not set +CONFIG_SYS_I2C_ROCKCHIP=y +# CONFIG_SYS_I2C_MVTWSI is not set +# CONFIG_I2C_MUX is not set +# CONFIG_DM_KEYBOARD is not set +CONFIG_DM_KEY=y +# CONFIG_DM_RC is not set +# CONFIG_CROS_EC_KEYB is not set +CONFIG_RK8XX_PWRKEY=y +CONFIG_ADC_KEY=y +CONFIG_GPIO_KEY=y +CONFIG_RK_KEY=y +CONFIG_PWRKEY_DNL_TRIGGER_NUM=0 + +# +# LED Support +# +CONFIG_LED=y +CONFIG_LED_BLINK=y +# CONFIG_SPL_LED is not set +CONFIG_LED_GPIO=y +# CONFIG_LED_STATUS is not set + +# +# Mailbox Controller Support +# +# CONFIG_DM_MAILBOX is not set + +# +# Memory Controller drivers +# + +# +# Multifunction device drivers +# +# CONFIG_MISC is not set +# CONFIG_SPL_MISC is not set +# CONFIG_CROS_EC is not set +# CONFIG_DS4510 is not set +# CONFIG_FSL_SEC_MON is not set +# CONFIG_MXC_OCOTP is not set +# CONFIG_NUVOTON_NCT6102D is not set +# CONFIG_PWRSEQ is not set +# CONFIG_PCA9551_LED is not set +# CONFIG_WINBOND_W83627 is not set + +# +# MMC Host controller Support +# +CONFIG_MMC=y +CONFIG_DM_MMC=y +CONFIG_SPL_DM_MMC=y +# CONFIG_SPL_MMC_TINY is not set +CONFIG_MMC_DW=y +# CONFIG_MMC_DW_K3 is not set +CONFIG_MMC_DW_ROCKCHIP=y +# CONFIG_MMC_MXC is not set +# CONFIG_MMC_PCI is not set +# CONFIG_MMC_OMAP_HS is not set +# CONFIG_MMC_SDHCI is not set + +# +# MTD Support +# +# CONFIG_MTD is not set +# CONFIG_MTD_NOR_FLASH is not set +# CONFIG_MTD_DEVICE is not set +# CONFIG_FLASH_CFI_DRIVER is not set +# CONFIG_NAND is not set + +# +# SPI Flash Support +# +CONFIG_DM_SPI_FLASH=y +CONFIG_SPI_FLASH=y +CONFIG_SF_DEFAULT_BUS=0 +CONFIG_SF_DEFAULT_CS=0 +CONFIG_SF_DEFAULT_MODE=3 +CONFIG_SF_DEFAULT_SPEED=1000000 +# CONFIG_SPI_FLASH_SFDP_SUPPORT is not set +# CONFIG_SPI_FLASH_BAR is not set +# CONFIG_SF_DUAL_FLASH is not set +# CONFIG_SPI_FLASH_ATMEL is not set +# CONFIG_SPI_FLASH_EON is not set +# CONFIG_SPI_FLASH_GIGADEVICE is not set +# CONFIG_SPI_FLASH_ISSI is not set +# CONFIG_SPI_FLASH_MACRONIX is not set +# CONFIG_SPI_FLASH_SPANSION is not set +# CONFIG_SPI_FLASH_STMICRO is not set +# CONFIG_SPI_FLASH_SST is not set +# CONFIG_SPI_FLASH_WINBOND is not set +# CONFIG_SPI_FLASH_XMC is not set +CONFIG_SPI_FLASH_XTX=y +CONFIG_SPI_FLASH_USE_4K_SECTORS=y +# CONFIG_SPI_FLASH_DATAFLASH is not set +# CONFIG_SPI_FLASH_MTD is not set + +# +# UBI support +# +# CONFIG_CONFIG_UBI_SILENCE_MSG is not set +# CONFIG_MTD_UBI is not set +# CONFIG_BITBANGMII is not set +# CONFIG_MV88E6352_SWITCH is not set +# CONFIG_PHYLIB is not set +# CONFIG_DM_ETH is not set +# CONFIG_NETDEVICES is not set +# CONFIG_PCI is not set + +# +# PHY Subsystem +# +CONFIG_PHY=y +# CONFIG_SPL_PHY is not set +# CONFIG_NOP_PHY is not set +CONFIG_PHY_ROCKCHIP_INNO_USB2=y +# CONFIG_MVEBU_COMPHY_SUPPORT is not set + +# +# Pin controllers +# +CONFIG_PINCTRL=y +CONFIG_PINCTRL_FULL=y +CONFIG_PINCTRL_GENERIC=y +CONFIG_PINMUX=y +# CONFIG_PINCONF is not set +# CONFIG_SPL_PINCTRL is not set +# CONFIG_PINCTRL_AT91 is not set +# CONFIG_PINCTRL_AT91PIO4 is not set +CONFIG_PINCTRL_ROCKCHIP=y +# CONFIG_PINCTRL_SINGLE is not set +# CONFIG_PINCTRL_STM32 is not set + +# +# Power +# + +# +# Power Domain Support +# +# CONFIG_POWER_DOMAIN is not set +CONFIG_DM_FUEL_GAUGE=y +# CONFIG_POWER_FG_CW201X is not set +# CONFIG_POWER_FG_RK818 is not set +CONFIG_POWER_FG_RK817=y +# CONFIG_POWER_FG_RK816 is not set + +# +# IO Domain Support +# +# CONFIG_IO_DOMAIN is not set +CONFIG_DM_PMIC=y +CONFIG_PMIC_CHILDREN=y +CONFIG_SPL_PMIC_CHILDREN=y +# CONFIG_PMIC_ACT8846 is not set +# CONFIG_PMIC_AS3722 is not set +# CONFIG_DM_PMIC_PFUZE100 is not set +# CONFIG_DM_PMIC_MAX77686 is not set +# CONFIG_DM_PMIC_MAX8998 is not set +# CONFIG_PMIC_MAX8997 is not set +# CONFIG_PMIC_PM8916 is not set +CONFIG_PMIC_RK8XX=y +# CONFIG_PMIC_S2MPS11 is not set +# CONFIG_DM_PMIC_SANDBOX is not set +# CONFIG_PMIC_S5M8767 is not set +# CONFIG_PMIC_RN5T567 is not set +# CONFIG_PMIC_TPS65090 is not set +# CONFIG_PMIC_PALMAS is not set +# CONFIG_PMIC_LP873X is not set +# CONFIG_PMIC_LP87565 is not set +# CONFIG_POWER_MC34VR500 is not set +CONFIG_DM_REGULATOR=y +# CONFIG_SPL_DM_REGULATOR is not set +# CONFIG_REGULATOR_FAN53555 is not set +CONFIG_REGULATOR_PWM=y +CONFIG_DM_REGULATOR_FIXED=y +# CONFIG_SPL_DM_REGULATOR_FIXED is not set +# CONFIG_DM_REGULATOR_GPIO is not set +CONFIG_REGULATOR_RK8XX=y +# CONFIG_DM_DVFS is not set +# CONFIG_CHARGER_BQ25700 is not set +CONFIG_DM_CHARGE_DISPLAY=y +CONFIG_CHARGE_ANIMATION=y +CONFIG_ROCKCHIP_PM=y +CONFIG_DM_PWM=y +# CONFIG_PWM_EXYNOS is not set +CONFIG_PWM_ROCKCHIP=y +# CONFIG_PWM_SANDBOX is not set +# CONFIG_PWM_TEGRA is not set +CONFIG_RAM=y +CONFIG_SPL_RAM=y +CONFIG_TPL_RAM=y +# CONFIG_STM32_SDRAM is not set +# CONFIG_DM_RAMDISK is not set +# CONFIG_ROCKCHIP_DMC is not set +CONFIG_ROCKCHIP_SDRAM_COMMON=y +CONFIG_SDRAM_COMMON_CAP_DETECT=y +CONFIG_SDRAM_COMMON_OSREG=y +# CONFIG_SDRAM_COMMON_MSCH_RK3399 is not set +CONFIG_SDRAM_COMMON_MSCH_PX30=y + +# +# Remote Processor drivers +# + +# +# Reset Controller Support +# +CONFIG_DM_RESET=y +CONFIG_RESET_ROCKCHIP=y +CONFIG_RKNAND=y +CONFIG_ZFTL=y +CONFIG_RKFLASH=y + +# +# Rockchip Flash Devices +# +CONFIG_RKSFC_NOR=y + +# +# Real Time Clock +# +# CONFIG_DM_RTC is not set +# CONFIG_SCSI is not set +# CONFIG_DM_SCSI is not set + +# +# Serial drivers +# +CONFIG_BAUDRATE=1500000 +CONFIG_REQUIRE_SERIAL_CONSOLE=y +CONFIG_SERIAL_PRESENT=y +CONFIG_SPL_SERIAL_PRESENT=y +CONFIG_DM_SERIAL=y +# CONFIG_SERIAL_RX_BUFFER is not set +CONFIG_SPL_DM_SERIAL=y +CONFIG_TPL_DM_SERIAL=y +# CONFIG_DEBUG_UART_ALTERA_JTAGUART is not set +# CONFIG_DEBUG_UART_ALTERA_UART is not set +# CONFIG_DEBUG_UART_ATMEL is not set +CONFIG_DEBUG_UART_NS16550=y +# CONFIG_DEBUG_UART_S5P is not set +# CONFIG_DEBUG_UART_UARTLITE is not set +# CONFIG_DEBUG_UART_ARM_DCC is not set +# CONFIG_DEBUG_MVEBU_A3700_UART is not set +# CONFIG_DEBUG_UART_ZYNQ is not set +# CONFIG_DEBUG_UART_PL010 is not set +# CONFIG_DEBUG_UART_PL011 is not set +# CONFIG_DEBUG_UART_OMAP is not set +CONFIG_DEBUG_UART_BASE=0xFF160000 +CONFIG_DEBUG_UART_CLOCK=24000000 +CONFIG_DEBUG_UART_SHIFT=2 +CONFIG_DEBUG_UART_BOARD_INIT=y +# CONFIG_DEBUG_UART_ANNOUNCE is not set +# CONFIG_DEBUG_UART_SKIP_INIT is not set +# CONFIG_ALTERA_JTAG_UART is not set +# CONFIG_ALTERA_UART is not set +# CONFIG_ATMEL_USART is not set +# CONFIG_FSL_LPUART is not set +# CONFIG_MVEBU_A3700_UART is not set +CONFIG_SYS_NS16550=y +# CONFIG_MSM_SERIAL is not set +# CONFIG_PXA_SERIAL is not set + +# +# Sound support +# +CONFIG_SOUND=y +# CONFIG_I2S is not set +# CONFIG_I2S_SAMSUNG is not set +CONFIG_I2S_ROCKCHIP=y +CONFIG_SOUND_RK817=y +CONFIG_SOUND_ROCKCHIP=y +CONFIG_SPI=y +CONFIG_DM_SPI=y +CONFIG_SPI_MEM=y +# CONFIG_ALTERA_SPI is not set +# CONFIG_ATCSPI200_SPI is not set +# CONFIG_ATMEL_SPI is not set +# CONFIG_CADENCE_QSPI is not set +# CONFIG_DESIGNWARE_SPI is not set +# CONFIG_EXYNOS_SPI is not set +# CONFIG_FSL_DSPI is not set +# CONFIG_ICH_SPI is not set +# CONFIG_MVEBU_A3700_SPI is not set +CONFIG_ROCKCHIP_SPI=y +# CONFIG_ROCKCHIP_SFC is not set +# CONFIG_TEGRA114_SPI is not set +# CONFIG_TEGRA20_SFLASH is not set +# CONFIG_TEGRA20_SLINK is not set +# CONFIG_TEGRA210_QSPI is not set +# CONFIG_XILINX_SPI is not set +# CONFIG_SOFT_SPI is not set +# CONFIG_CF_SPI is not set +# CONFIG_FSL_ESPI is not set +# CONFIG_FSL_QSPI is not set +# CONFIG_SH_SPI is not set +# CONFIG_SH_QSPI is not set +# CONFIG_TI_QSPI is not set +# CONFIG_KIRKWOOD_SPI is not set +# CONFIG_LPC32XX_SSP is not set +# CONFIG_MPC8XXX_SPI is not set +# CONFIG_MXC_SPI is not set +# CONFIG_MXS_SPI is not set +# CONFIG_OMAP3_SPI is not set + +# +# SPMI support +# +# CONFIG_SPMI is not set + +# +# System reset device drivers +# +CONFIG_SYSRESET=y +CONFIG_SPL_SYSRESET=y +CONFIG_SYSRESET_PSCI=y +# CONFIG_SYSRESET_SYSCON is not set +# CONFIG_SYSRESET_WATCHDOG is not set +# CONFIG_DM_THERMAL is not set + +# +# Timer Support +# +# CONFIG_TIMER is not set + +# +# TPM support +# +CONFIG_USB=y +CONFIG_DM_USB=y + +# +# USB Host Controller Drivers +# +CONFIG_USB_HOST=y +# CONFIG_USB_XHCI_HCD is not set +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_MSM is not set +# CONFIG_USB_EHCI_PCI is not set +CONFIG_USB_EHCI_GENERIC=y +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_GENERIC=y +# CONFIG_USB_UHCI_HCD is not set +CONFIG_USB_DWC2=y +# CONFIG_USB_DWC3 is not set + +# +# MUSB Controller Driver +# +# CONFIG_USB_MUSB_HOST is not set +# CONFIG_USB_MUSB_GADGET is not set +# CONFIG_USB_MUSB_TI is not set + +# +# ULPI drivers +# + +# +# USB peripherals +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_KEYBOARD is not set +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_ATMEL_USBA is not set +# CONFIG_USB_GADGET_BCM_UDC_OTG_PHY is not set +CONFIG_USB_GADGET_DWC2_OTG=y +# CONFIG_USB_GADGET_DWC2_OTG_PHY_BUS_WIDTH_8 is not set +# CONFIG_CI_UDC is not set +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_DUALSPEED=y +CONFIG_USB_GADGET_DOWNLOAD=y +# CONFIG_USB_FUNCTION_SDP is not set +CONFIG_G_DNL_MANUFACTURER="Rockchip" +CONFIG_G_DNL_VENDOR_NUM=0x2207 +CONFIG_G_DNL_PRODUCT_NUM=0x330d +CONFIG_USBNET_DEVADDR="de:ad:be:ef:00:01" +CONFIG_USB_HOST_ETHER=y +CONFIG_USB_ETHER_ASIX=y +CONFIG_USB_ETHER_ASIX88179=y +# CONFIG_USB_ETHER_LAN75XX is not set +# CONFIG_USB_ETHER_LAN78XX is not set +# CONFIG_USB_ETHER_MCS7830 is not set +CONFIG_USB_ETHER_RTL8152=y +CONFIG_USB_ETHER_SMSC95XX=y + +# +# Graphics support +# +CONFIG_DM_VIDEO=y +CONFIG_BACKLIGHT_PWM=y +# CONFIG_BACKLIGHT_GPIO is not set +CONFIG_VIDEO_BPP8=y +CONFIG_VIDEO_BPP16=y +CONFIG_VIDEO_BPP32=y +CONFIG_CONSOLE_NORMAL=y +CONFIG_CONSOLE_ROTATION=y +# CONFIG_CONSOLE_TRUETYPE is not set +CONFIG_SYS_WHITE_ON_BLACK=y + +# +# TrueType Fonts +# +# CONFIG_VIDCONSOLE_AS_LCD is not set +# CONFIG_VIDEO_VESA is not set +# CONFIG_VIDEO_LCD_ANX9804 is not set +# CONFIG_VIDEO_LCD_SSD2828 is not set +# CONFIG_VIDEO_MVEBU is not set +CONFIG_I2C_EDID=y +CONFIG_DISPLAY=y +# CONFIG_ATMEL_HLCD is not set +# CONFIG_VIDEO_ROCKCHIP is not set +CONFIG_DRM_ROCKCHIP=y +CONFIG_DRM_ROCKCHIP_PANEL=y +# CONFIG_DRM_ROCKCHIP_DW_HDMI is not set +# CONFIG_ROCKCHIP_INNO_HDMI_PHY is not set +# CONFIG_DRM_ROCKCHIP_INNO_MIPI_PHY is not set +# CONFIG_DRM_ROCKCHIP_INNO_VIDEO_PHY is not set +CONFIG_DRM_ROCKCHIP_INNO_VIDEO_COMBO_PHY=y +CONFIG_DRM_MIPI_DSI=y +CONFIG_DRM_ROCKCHIP_DW_MIPI_DSI=y +# CONFIG_DRM_ROCKCHIP_ANALOGIX_DP is not set +# CONFIG_DRM_ROCKCHIP_LVDS is not set +# CONFIG_DRM_ROCKCHIP_RGB is not set +# CONFIG_DRM_ROCKCHIP_RK618 is not set +# CONFIG_ROCKCHIP_DRM_TVE is not set +# CONFIG_VIDEO_TEGRA20 is not set +# CONFIG_VIDEO_TEGRA124 is not set +CONFIG_VIDEO_BRIDGE=y +# CONFIG_VIDEO_BRIDGE_PARADE_PS862X is not set +# CONFIG_VIDEO_BRIDGE_NXP_PTN3460 is not set +# CONFIG_VIDEO_BRIDGE_ANALOGIX_ANX6345 is not set +CONFIG_CONSOLE_SCROLL_LINES=1 +# CONFIG_LCD is not set + +# +# Watchdog Timer Support +# +# CONFIG_BCM2835_WDT is not set +# CONFIG_ULP_WATCHDOG is not set +# CONFIG_WDT is not set +CONFIG_IRQ=y +# CONFIG_PHYS_TO_BUS is not set + +# +# File systems +# +# CONFIG_FS_CBFS is not set +CONFIG_FS_FAT=y +CONFIG_FAT_WRITE=y +CONFIG_SUPPORT_VFAT=y +CONFIG_FS_FAT_MAX_CLUSTSIZE=65536 +# CONFIG_FS_JFFS2 is not set +# CONFIG_FS_CRAMFS is not set +# CONFIG_YAFFS2 is not set + +# +# Library routines +# +# CONFIG_BCH is not set +# CONFIG_CC_OPTIMIZE_LIBS_FOR_SPEED is not set +CONFIG_SYS_HZ=1000 +CONFIG_SYS_STACK_SIZE=0x200000 +CONFIG_USE_TINY_PRINTF=y +# CONFIG_PANIC_HANG is not set +CONFIG_REGEX=y +# CONFIG_LIB_RAND is not set +CONFIG_SPL_TINY_MEMSET=y +# CONFIG_TPL_TINY_MEMSET is not set +CONFIG_SYSMEM=y +CONFIG_BIDRAM=y +# CONFIG_CMD_DHRYSTONE is not set + +# +# Security support +# +# CONFIG_AES is not set +# CONFIG_RSA is not set +# CONFIG_TPM is not set + +# +# Hashing Support +# +CONFIG_SHA1=y +CONFIG_SHA256=y +# CONFIG_SHA512 is not set +# CONFIG_SHA_HW_ACCEL is not set +CONFIG_MD5=y + +# +# Compression Support +# +CONFIG_LZ4=y +CONFIG_LZMA=y +CONFIG_LZO=y +# CONFIG_SPL_LZO is not set +# CONFIG_SPL_GZIP is not set +CONFIG_ERRNO_STR=y +# CONFIG_HEXDUMP is not set +CONFIG_OF_LIBFDT=y +CONFIG_OF_LIBFDT_OVERLAY=y +CONFIG_SPL_OF_LIBFDT=y +# CONFIG_TPL_OF_LIBFDT is not set +# CONFIG_FDT_FIXUP_PARTITIONS is not set + +# +# System tables +# +CONFIG_GENERATE_SMBIOS_TABLE=y +CONFIG_SMBIOS_MANUFACTURER="rockchip" +CONFIG_EFI_LOADER=y +# CONFIG_EFI_LOADER_BOUNCE_BUFFER is not set +# CONFIG_AVB_LIBAVB is not set +# CONFIG_SPL_AVB_LIBAVB is not set +# CONFIG_TPL_AVB_LIBAVB is not set +# CONFIG_AVB_LIBAVB_AB is not set +# CONFIG_SPL_AVB_LIBAVB_AB is not set +# CONFIG_TPL_AVB_LIBAVB_AB is not set +# CONFIG_AVB_LIBAVB_ATX is not set +# CONFIG_SPL_AVB_LIBAVB_ATX is not set +# CONFIG_TPL_AVB_LIBAVB_ATX is not set +# CONFIG_AVB_LIBAVB_USER is not set +# CONFIG_SPL_AVB_LIBAVB_USER is not set +# CONFIG_TPL_AVB_LIBAVB_USER is not set +# CONFIG_RK_AVB_LIBAVB_USER is not set +# CONFIG_SPL_RK_AVB_LIBAVB_USER is not set +# CONFIG_TPL_RK_AVB_LIBAVB_USER is not set +CONFIG_OPTEE_CLIENT=y +# CONFIG_OPTEE_V1 is not set +CONFIG_OPTEE_V2=y +CONFIG_OPTEE_ALWAYS_USE_SECURITY_PARTITION=y +# CONFIG_UNIT_TEST is not set +CONFIG_TEST_ROCKCHIP=y +# CONFIG_LAVA_INFO is not set diff --git a/projects/ArchR/devices/RK3326/packages/u-boot/config/clone_boot.ini b/projects/ArchR/devices/RK3326/packages/u-boot/config/clone_boot.ini new file mode 100644 index 0000000000..4c646bb168 --- /dev/null +++ b/projects/ArchR/devices/RK3326/packages/u-boot/config/clone_boot.ini @@ -0,0 +1,52 @@ +# distro_storagepart=$((${distro_bootpart} + 1)) +if test ${distro_bootpart} = '0'; then setenv distro_storagepart 1 +elif test ${distro_bootpart} = '1'; then setenv distro_storagepart 2 +elif test ${distro_bootpart} = '2'; then setenv distro_storagepart 3 +elif test ${distro_bootpart} = '3'; then setenv distro_storagepart 4 +else setenv distro_storagepart 2 +fi + +# reduce copy-paste referring to active partition +setenv thispart "${devtype} ${devnum}:${distro_bootpart}" +setenv storagepart "${devtype} ${devnum}:${distro_storagepart}" + +# Clone hardware: SD card is mmcblk0 (U-Boot devnum=1 doesn't match kernel) +setenv mmcdev ${devnum} +setenv partition_boot "/dev/mmcblk${mmcdev}p${distro_bootpart}" +setenv partition_root "/dev/mmcblk${mmcdev}p2" +setenv partition_storage "/dev/mmcblk${mmcdev}p3" + +# Just in case this script is executed by (patched?) hardkernel u-boot, recover adc value from hwrev +if test -n "${hwid_adc}"; then setenv adc ${hwid_adc}; echo "ADC ${hwid_adc}" # mainline u-boot, just use real value +elif test ${hwrev} = 'v10'; then setenv adc 856 # OGA +elif test ${hwrev} = 'v11'; then setenv adc 677 # OGABE +elif test ${hwrev} = 'v10-go3';then setenv adc 85 # OGS +elif test ${hwrev} = 'rg351v'; then setenv adc 515 +elif test ${hwrev} = 'r33s'; then setenv adc 165 +elif test ${hwrev} = 'xu10'; then setenv adc 1025 +elif test ${hwrev} = 'chi'; then setenv adc 475 +else setenv adc 65000 +fi + +# this will be passed to cmdline so that userspace can analyze boot criteria +if test -n "${hwid_adc}"; then setenv hwid_adc b,${hwid_adc}; +else setenv hwid_adc b,${hwrev} +fi + +# Depending on ADC value select a proper DTB +if itest.w ${adc} > 139 && itest.w ${adc} < 191; then + setenv fdtfile "rk3326-powkiddy-rgb10x.dtb" +elif itest.w ${adc} > 999 && itest.w ${adc} < 1051; then + setenv fdtfile "rk3326-magicx-xu-mini-m.dtb" +elif itest.w ${adc} > 489 && itest.w ${adc} < 541; then + setenv fdtfile "rk3326-gameconsole-eeclone.dtb" +else + echo "Unexpected ADC value ${adc}, falling back to OGA dtb" + setenv fdtfile "rk3326-odroid-go2.dtb" +fi + +# Let syslinux do the load stuff. +# User will be able to edit extlinux.conf if needed +setenv kernel_addr_r "0x09000000" +setenv fdtoverlay_addr_r "0x08000000" +sysboot ${thispart} any 0x100000 /extlinux/extlinux.conf diff --git a/projects/ArchR/devices/RK3326/packages/u-boot/config/extlinux/README.txt b/projects/ArchR/devices/RK3326/packages/u-boot/config/extlinux/README.txt new file mode 100644 index 0000000000..3430626160 --- /dev/null +++ b/projects/ArchR/devices/RK3326/packages/u-boot/config/extlinux/README.txt @@ -0,0 +1,15 @@ +extlinux.conf is a file which has a final word when describing how to boot your device. + +Usually u-boot runs boot.scr which checks some hardware stuff (ADC voltage, some GPIO levels), +chooses a dtb based on collected data and passes that to extlinux. + +Thay may fail if you have a rare device or faulty hardware or something else unexpected. +In this case you can configure extlinux.conf manually. +Main things to edit: + * APPEND -- kernel cmdline. If you have UART soldered you may want to remove 'quiet' option. + Also this parameter can modify kernel behaviour (e.g. disable or configure drivers) + * FDT -- a path to .dtb file to use. Please note that uboot's extlinux has a poor parser, + and even a space after dtb file path breaks the boot. + * FDTOVERLAYS -- dtb overlays to apply. This line can point to non-existing files, that's ok. + Overlays may be used to apply configuration specific to your device + (e.g. joystic axis inversion, display init sequence, etc.) diff --git a/projects/ArchR/devices/RK3326/packages/u-boot/config/extlinux/extlinux.conf b/projects/ArchR/devices/RK3326/packages/u-boot/config/extlinux/extlinux.conf new file mode 100644 index 0000000000..9fcca88fe9 --- /dev/null +++ b/projects/ArchR/devices/RK3326/packages/u-boot/config/extlinux/extlinux.conf @@ -0,0 +1,7 @@ +LABEL ArchR + LINUX /KERNEL + FDTDIR /dtbs/ + ## FDT: don't forget the leading slash, remove all symbols after .dtb (including whitespace) + # FDT /dtbs/your-custom-devicetree.dtb + FDTOVERLAYS /overlays/mipi-panel.dtbo + APPEND boot=${partition_boot} root=${partition_root} disk=${partition_storage} @EXTRA_CMDLINE@ uboot.hwid_adc=${hwid_adc} diff --git a/projects/ArchR/devices/RK3326/packages/u-boot/config/original_boot.ini b/projects/ArchR/devices/RK3326/packages/u-boot/config/original_boot.ini new file mode 100644 index 0000000000..182dced0a1 --- /dev/null +++ b/projects/ArchR/devices/RK3326/packages/u-boot/config/original_boot.ini @@ -0,0 +1,75 @@ +# Legacy u-boot doesn't have distro_bootpart +if test -z "${distro_bootpart}"; then + echo "No distro_bootpart; setting it to 1" + setenv distro_bootpart 1 +fi + +# distro_storagepart=$((${distro_bootpart} + 1)) +if test ${distro_bootpart} = '0'; then setenv distro_storagepart 1 +elif test ${distro_bootpart} = '1'; then setenv distro_storagepart 2 +elif test ${distro_bootpart} = '2'; then setenv distro_storagepart 3 +elif test ${distro_bootpart} = '3'; then setenv distro_storagepart 4 +else setenv distro_storagepart 2 +fi + +# reduce copy-paste referring to active partition +setenv thispart "${devtype} ${devnum}:${distro_bootpart}" +setenv storagepart "${devtype} ${devnum}:${distro_storagepart}" + +# Use device paths based on U-Boot mmc device number +# mmc 1 in U-Boot = /dev/mmcblk1 in Linux (SD card on RK3326) +setenv mmcdev ${devnum} +setenv partition_boot "/dev/mmcblk${mmcdev}p${distro_bootpart}" +setenv partition_root "/dev/mmcblk${mmcdev}p2" +setenv partition_storage "/dev/mmcblk${mmcdev}p3" + +# Just in case this script is executed by (patched?) hardkernel u-boot, recover adc value from hwrev +if test -n "${hwid_adc}"; then setenv adc ${hwid_adc}; echo "ADC ${hwid_adc}" # mainline u-boot, just use real value +elif test ${hwrev} = 'v10'; then setenv adc 856 # OGA +elif test ${hwrev} = 'v11'; then setenv adc 677 # OGABE +elif test ${hwrev} = 'v10-go3';then setenv adc 85 # OGS +elif test ${hwrev} = 'rg351v'; then setenv adc 515 +elif test ${hwrev} = 'r33s'; then setenv adc 165 +elif test ${hwrev} = 'xu10'; then setenv adc 1025 +elif test ${hwrev} = 'chi'; then setenv adc 475 +else setenv adc 65000 +fi + +# this will be passed to cmdline so that userspace can analyze boot criteria +if test -n "${hwid_adc}"; then setenv hwid_adc a,${hwid_adc}; +else setenv hwid_adc a,${hwrev} +fi + +# Depending on ADC value select a proper DTB +if itest.w ${adc} > 59 && itest.w ${adc} < 111; then + setenv fdtfile "rk3326-odroid-go3.dtb" +elif itest.w ${adc} > 139 && itest.w ${adc} < 191; then + setenv fdtfile "rk3326-gameconsole-r36s.dtb" +elif itest.w ${adc} > 449 && itest.w ${adc} < 496; then + setenv fdtfile "rk3326-gameforce-chi.dtb" +elif itest.w ${adc} < 541; then + setenv fdtfile "rk3326-anbernic-rg351v.dtb" +elif itest.w ${adc} > 651 && itest.w ${adc} < 703; then + if gpio input c22; then + if gpio input d9; then + setenv fdtfile "rk3326-powkiddy-rgb10.dtb" + else + setenv fdtfile "rk3326-odroid-go2-v11.dtb" + fi + else + setenv fdtfile "rk3326-anbernic-rg351m.dtb" + fi +elif itest.w ${adc} > 830 && itest.w ${adc} < 882; then + setenv fdtfile "rk3326-odroid-go2.dtb" +elif itest.w ${adc} > 999 && itest.w ${adc} < 1051; then + setenv fdtfile "rk3326-magicx-xu10.dtb" +else + echo "Unexpected ADC value ${adc}, falling back to OGA dtb" + setenv fdtfile "rk3326-odroid-go2.dtb" +fi + +# Let syslinux do the load stuff. +# User will be able to edit extlinux.conf if needed +setenv kernel_addr_r "0x09000000" +setenv fdtoverlay_addr_r "0x08000000" +sysboot ${thispart} any 0x100000 /extlinux/extlinux.conf diff --git a/projects/ArchR/devices/RK3326/packages/u-boot/config/overlays/README.txt b/projects/ArchR/devices/RK3326/packages/u-boot/config/overlays/README.txt new file mode 100644 index 0000000000..0360b6d208 --- /dev/null +++ b/projects/ArchR/devices/RK3326/packages/u-boot/config/overlays/README.txt @@ -0,0 +1,12 @@ +Here your device tree overlays live. +Currently only mipi-panel.dtbo is expected which is intended for display driver stuff. + +For R36s, rg351*-v2 and maybe other devices you may need to put a proper mipi-panel.dtbo +to make display work. +See https://arch-r.io/devices/unbranded/game-console-r35s-r36s/#new-displays-r36s-of-year-2024 + +Despite the name, mipi-panel.dtbo is also abused for quite a complex tuning +of EE clones of year 2025, but in this case the overlay is usually generated automatically. +In some cases (something is misdetected) you may want to replace mipi-panel.dtbo +with whatever you need. +See https://arch-r.io/devices/unbranded/EE-clones/#in-case-of-issues-with-displaysoundetc diff --git a/projects/ArchR/devices/RK3326/packages/u-boot/config/stock/README.txt b/projects/ArchR/devices/RK3326/packages/u-boot/config/stock/README.txt new file mode 100644 index 0000000000..30bddee4c1 --- /dev/null +++ b/projects/ArchR/devices/RK3326/packages/u-boot/config/stock/README.txt @@ -0,0 +1,4 @@ +On some devices (EE clones) you can put your stock .dtb file +to this dir if the wizard could not locate it automatically. + +See https://arch-r.io/devices/unbranded/EE-clones/ for info diff --git a/projects/ArchR/devices/RK3326/packages/u-boot/package.mk b/projects/ArchR/devices/RK3326/packages/u-boot/package.mk new file mode 100644 index 0000000000..26de47a8aa --- /dev/null +++ b/projects/ArchR/devices/RK3326/packages/u-boot/package.mk @@ -0,0 +1,131 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="u-boot" +PKG_VERSION="v2025.10" +PKG_LICENSE="GPL" +PKG_SITE="https://www.denx.de/wiki/U-Boot" +PKG_URL="https://github.com/u-boot/u-boot/archive/refs/tags/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain Python3:host swig:host pyelftools:host u-boot-legacy" +PKG_LONGDESC="Das U-Boot is a cross-platform bootloader for embedded systems." +PKG_TOOLCHAIN="manual" + +PKG_NEED_UNPACK="${PROJECT_DIR}/${PROJECT}/bootloader ${PROJECT_DIR}/${PROJECT}/devices/${DEVICE}/bootloader" +PKG_NEED_UNPACK+=" ${PROJECT_DIR}/${PROJECT}/options ${PROJECT_DIR}/${PROJECT}/devices/${DEVICE}/options" + +if [ -n "${UBOOT_FIRMWARE}" ]; then + PKG_DEPENDS_TARGET+=" ${UBOOT_FIRMWARE}" + PKG_DEPENDS_UNPACK+=" ${UBOOT_FIRMWARE}" +fi + +pre_make_target() { + PKG_UBOOT_CONFIG="rk3326-handheld_defconfig" + PKG_RKBIN="$(get_build_dir rkbin)" + PKG_MINILOADER="${PKG_RKBIN}/bin/rk33/rk3326_miniloader_v1.40.bin" + PKG_BL31="${PKG_RKBIN}/bin/rk33/rk3326_bl31_v1.34.elf" + PKG_DDR_BIN="${PKG_RKBIN}/bin/rk33/rk3326_ddr_333MHz_v2.11.bin" + PKG_DDR_BIN_UART5="${PKG_RKBIN}/rk3326_ddr_uart5.bin" +} + +make_target() { + [ "${BUILD_WITH_DEBUG}" = "yes" ] && PKG_DEBUG=1 || PKG_DEBUG=0 + setup_pkg_config_host + + find_file_path bootloader/rkhelper || exit 4 + RKHELPER=${FOUND_PATH} + + 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 ${PKG_UBOOT_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" \ + u-boot-dtb.bin + . ${RKHELPER} + mv uboot.bin uboot.bin.default + + ./scripts/config --set-val CONFIG_DEBUG_UART_BASE 0xFF178000 + ./scripts/config --set-str CONFIG_DEVICE_TREE_INCLUDES "rk3326-odroid-go2-emmc.dtsi rk3326-odroid-go2-uart5.dtsi" + 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" \ + u-boot-dtb.bin + PKG_DDR_BIN=${PKG_DDR_BIN_UART5} . ${RKHELPER} + mv uboot.bin uboot.bin.uart5 +} + +generate_custom_extlinux_conf_files() { + INI_FILES="" + for SUBDEVICE in ${SUBDEVICES}; do + if find_file_path config/${SUBDEVICE}_boot.ini; then + INI_FILES="${INI_FILES} ${FOUND_PATH}" + fi + done + EXTLCONF0=${INSTALL}/usr/share/bootloader/extlinux/extlinux.conf + + echo "INI_FILES ${INI_FILES}" + for dtbase in $(xmlstarlet sel -t -v "//archr/${DEVICE}/*" ${CONFIGXML}); do + if ! grep -q "\<${dtbase}.dtb" ${INI_FILES}; then + EXTLCONF=${EXTLCONF0}.${dtbase##*-} + echo "Generating ${EXTLCONF} for ${dtbase}" + sed '/##/d;s|^.* FDT .*$| FDT /dtbs/'${dtbase}'.dtb|' ${EXTLCONF0} > ${EXTLCONF0}.${dtbase##*-} + fi + done +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/share/bootloader + + for SUBDEVICE in ${SUBDEVICES}; do + if find_file_path config/${SUBDEVICE}_boot.ini; then + cp -av ${FOUND_PATH} . + sed -e "s/@DISTRO_BOOTLABEL@/${DISTRO_BOOTLABEL}/" \ + -e "s/@DISTRO_ROOTLABEL@/${DISTRO_ROOTLABEL}/" \ + -e "s/@DISTRO_DISKLABEL@/${DISTRO_DISKLABEL}/" \ + -e "s/@EXTRA_CMDLINE@/${EXTRA_CMDLINE}/" \ + -i "${SUBDEVICE}_boot.ini" + ./tools/mkimage -T script -d "${SUBDEVICE}_boot.ini" "${SUBDEVICE}_boot.scr" + cp -av "${SUBDEVICE}_boot.scr" "${INSTALL}/usr/share/bootloader/" + fi + done + + cp -av uboot.bin.default "${INSTALL}/usr/share/bootloader/clone_uboot.bin" + cp -av uboot.bin.uart5 "${INSTALL}/usr/share/bootloader/clone_uboot.bin.uart5" + + find_dir_path config/extlinux || exit 3 + cp -av ${FOUND_PATH} "${INSTALL}/usr/share/bootloader/" + sed -e "s/@EXTRA_CMDLINE@/${EXTRA_CMDLINE}/" \ + -i ${INSTALL}/usr/share/bootloader/extlinux/* + + generate_custom_extlinux_conf_files + + find_dir_path config/stock && cp -av ${FOUND_PATH} "${INSTALL}/usr/share/bootloader/" + + # Generate MIPI panel overlays + MIPI_GEN="${ROOT}/config/mipi-generator" + MIPI_OUT="${MIPI_GEN}/output" + if [ -x "${MIPI_GEN}/generator.sh" ]; then + echo "Generating MIPI panel overlays..." + bash "${MIPI_GEN}/generator.sh" || echo "WARNING: Panel overlay generation failed (non-fatal)" + fi + + # Install per-SUBDEVICE panel overlays (original + clone) + for sd in ${SUBDEVICES}; do + mkdir -p "${INSTALL}/usr/share/bootloader/overlays_${sd}" + # First try pre-generated from mipi-generator output + if [ -d "${MIPI_OUT}/${sd}" ]; then + cp -av "${MIPI_OUT}/${sd}/"*.dtbo "${INSTALL}/usr/share/bootloader/overlays_${sd}/" 2>/dev/null || true + fi + # Then overlay with any from config dir (manual overrides) + if find_dir_path config/overlays_${sd}; then + cp -av ${FOUND_PATH}/*.dtbo "${INSTALL}/usr/share/bootloader/overlays_${sd}/" 2>/dev/null || true + fi + done + # Install soysauce panel overlays (included in original image) + if [ -d "${MIPI_OUT}/soysauce" ]; then + mkdir -p "${INSTALL}/usr/share/bootloader/overlays_soysauce" + cp -av "${MIPI_OUT}/soysauce/"*.dtbo "${INSTALL}/usr/share/bootloader/overlays_soysauce/" 2>/dev/null || true + fi + + # Also install generic overlays dir (README, fallback) + find_dir_path config/overlays && cp -av ${FOUND_PATH} "${INSTALL}/usr/share/bootloader/" +} diff --git a/projects/ArchR/devices/RK3326/packages/u-boot/patches/0001-add-support-for-k36-clone-with-emmc-rk3326.patch b/projects/ArchR/devices/RK3326/packages/u-boot/patches/0001-add-support-for-k36-clone-with-emmc-rk3326.patch new file mode 100644 index 0000000000..3d73d62fe9 --- /dev/null +++ b/projects/ArchR/devices/RK3326/packages/u-boot/patches/0001-add-support-for-k36-clone-with-emmc-rk3326.patch @@ -0,0 +1,62 @@ +From 8d4137bf6726fde54a60d84b393521a2145d349c Mon Sep 17 00:00:00 2001 +From: Danil Zagoskin +Date: Sat, 21 Jun 2025 15:38:11 +0300 +Subject: [PATCH] support for k36 clones with emmc and uart5 + +--- + board/hardkernel/odroid_go2/go2.c | 12 +- + +diff --git a/board/hardkernel/odroid_go2/go2.c b/board/hardkernel/odroid_go2/go2.c +index a0338ead3b..fe12532a5a 100644 +--- a/board/hardkernel/odroid_go2/go2.c ++++ b/board/hardkernel/odroid_go2/go2.c +@@ -23,6 +23,7 @@ enum oga_device_id { + OGA, + OGA_V11, + OGS, ++ GENERIC + }; + + /* +@@ -48,6 +49,12 @@ static const struct oga_model oga_model_details[] = { + "ODROID-GO Super", + DTB_DIR "rk3326-odroid-go3.dtb", + }, ++ [GENERIC] = { ++ 65000, ++ "rk3326-generic", ++ "UNKNOWN", ++ DTB_DIR "rk3326-generic.dtb", ++ }, + }; + + /* Detect which Odroid Go Advance device we are using so as to load the +@@ -72,15 +79,15 @@ int oga_detect_device(void) + * accounted for this with a 5% tolerance, so assume a +- value + * of 50 should be enough. + */ +- for (i = 0; i < ARRAY_SIZE(oga_model_details); i++) { ++ for (i = 0; i < ARRAY_SIZE(oga_model_details) - 1; i++) { + u32 adc_min = oga_model_details[i].adc_value - 50; + u32 adc_max = oga_model_details[i].adc_value + 50; + + if (adc_min < adc_info && adc_max > adc_info) { +- board_id = i; + break; + } + } ++ board_id = i; + + if (board_id < 0) + return board_id; +@@ -89,6 +96,7 @@ int oga_detect_device(void) + env_set("board_name", + oga_model_details[board_id].board_name); + env_set("fdtfile", oga_model_details[board_id].fdtfile); ++ env_set_ulong("hwid_adc", adc_info); + + return 0; + } +-- +2.49.0 + diff --git a/projects/ArchR/devices/RK3326/packages/u-boot/sources/arch/arm/dts/rk3326-odroid-go2-emmc.dtsi b/projects/ArchR/devices/RK3326/packages/u-boot/sources/arch/arm/dts/rk3326-odroid-go2-emmc.dtsi new file mode 100644 index 0000000000..b25e54d7bb --- /dev/null +++ b/projects/ArchR/devices/RK3326/packages/u-boot/sources/arch/arm/dts/rk3326-odroid-go2-emmc.dtsi @@ -0,0 +1,28 @@ +/* this should apply on top of rk3326-odroid-go2-u-boot.dtsi */ +/ { + chosen { + u-boot,spl-boot-order = &sdmmc, &emmc; + }; + + aliases { + mmc0 = &emmc; + mmc1 = &sdmmc; + mmc2 = &sdio; + }; +}; + +&emmc { + bootph-all; + + /* mmc to sram can't do dma, prevent aborts transferring TF-A parts */ + u-boot,spl-fifo-mode; + status = "okay"; +}; + +&sdio { + bootph-all; + + /* mmc to sram can't do dma, prevent aborts transferring TF-A parts */ + u-boot,spl-fifo-mode; + status = "okay"; +}; diff --git a/projects/ArchR/devices/RK3326/packages/u-boot/sources/arch/arm/dts/rk3326-odroid-go2-uart5.dtsi b/projects/ArchR/devices/RK3326/packages/u-boot/sources/arch/arm/dts/rk3326-odroid-go2-uart5.dtsi new file mode 100644 index 0000000000..b2bd0be717 --- /dev/null +++ b/projects/ArchR/devices/RK3326/packages/u-boot/sources/arch/arm/dts/rk3326-odroid-go2-uart5.dtsi @@ -0,0 +1,12 @@ +/ { + aliases { + serial1 = &uart1; + serial2 = &uart5; + }; +}; + +&uart5 { + clock-frequency = <24000000>; + bootph-all; + status = "okay"; +}; diff --git a/projects/ArchR/devices/RK3326/packages/u-boot/sources/configs/rk3326-handheld_defconfig b/projects/ArchR/devices/RK3326/packages/u-boot/sources/configs/rk3326-handheld_defconfig new file mode 100644 index 0000000000..72f1fb7ca9 --- /dev/null +++ b/projects/ArchR/devices/RK3326/packages/u-boot/sources/configs/rk3326-handheld_defconfig @@ -0,0 +1,127 @@ +CONFIG_ARM=y +CONFIG_SKIP_LOWLEVEL_INIT=y +CONFIG_COUNTER_FREQUENCY=24000000 +CONFIG_ARCH_ROCKCHIP=y +CONFIG_NR_DRAM_BANKS=1 +CONFIG_ENV_SIZE=0x4000 +CONFIG_ENV_OFFSET=0x4000 +CONFIG_DEFAULT_DEVICE_TREE="rockchip/rk3326-common-handheld" +CONFIG_DEVICE_TREE_INCLUDES="rk3326-odroid-go2-emmc.dtsi" +CONFIG_LAST_STAGE_INIT=y +CONFIG_DM_RESET=y +CONFIG_ROCKCHIP_PX30=y +# CONFIG_TPL_ROCKCHIP_COMMON_BOARD is not set +CONFIG_TARGET_ODROID_GO2=y +CONFIG_DEBUG_UART_CHANNEL=0 +# CONFIG_TPL_LIBCOMMON_SUPPORT is not set +CONFIG_SPL_DRIVERS_MISC=y +CONFIG_SYS_LOAD_ADDR=0x800800 +CONFIG_DEBUG_UART_BASE=0xFF160000 +CONFIG_DEBUG_UART_CLOCK=24000000 +CONFIG_DEBUG_UART=y +CONFIG_BAUDRATE=1500000 +CONFIG_BOOTDELAY=1 +CONFIG_BOOTSTD_FULL=y +CONFIG_BOOTSTD_BOOTCOMMAND=y +CONFIG_BOOTCOMMAND="bootmeth order script; bootflow scan -b" +CONFIG_DISTRO_DEFAULTS=y +# CONFIG_ANDROID_BOOT_IMAGE is not set +CONFIG_FIT=y +CONFIG_SPL_LOAD_FIT=y +CONFIG_DEFAULT_FDT_FILE="rockchip/rk3326-common-handheld.dtb" +# CONFIG_CONSOLE_MUX is not set +# CONFIG_DISPLAY_CPUINFO is not set +CONFIG_DISPLAY_BOARDINFO_LATE=y +CONFIG_BOARD_LATE_INIT=y +CONFIG_MISC_INIT_R=y +CONFIG_SPL_MAX_SIZE=0x20000 +CONFIG_SPL_PAD_TO=0x7f8000 +CONFIG_SPL_BOOTROM_SUPPORT=y +# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set +CONFIG_SPL_I2C=y +CONFIG_SPL_POWER=y +CONFIG_SPL_ATF=y +# CONFIG_TPL_FRAMEWORK is not set +# CONFIG_TPL_BANNER_PRINT is not set +# CONFIG_TPL_SYS_MALLOC_SIMPLE is not set +# CONFIG_CMD_BOOTD is not set +# CONFIG_CMD_ELF is not set +# CONFIG_CMD_IMI is not set +# CONFIG_CMD_XIMG is not set +# CONFIG_CMD_LZMADEC is not set +# CONFIG_CMD_UNZIP is not set +CONFIG_CMD_GPT=y +# CONFIG_CMD_LOADB is not set +# CONFIG_CMD_LOADS is not set +CONFIG_CMD_MMC=y +CONFIG_CMD_USB=y +CONFIG_CMD_USB_MASS_STORAGE=y +CONFIG_CMD_ITEST=y +CONFIG_CMD_ADC=y +CONFIG_CMD_GPIO=y +CONFIG_CMD_PMIC=y +CONFIG_CMD_REGULATOR=y +CONFIG_CMD_FS_UUID=y +# CONFIG_CMD_SLEEP is not set +# CONFIG_SPL_DOS_PARTITION is not set +# CONFIG_ISO_PARTITION is not set +CONFIG_EFI_PARTITION_ENTRIES_NUMBERS=64 +CONFIG_SPL_OF_CONTROL=y +CONFIG_OF_LIVE=y +CONFIG_OF_LIBFDT_OVERLAY=y +CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" +CONFIG_ENV_IS_IN_MMC=y +CONFIG_REGMAP=y +CONFIG_SPL_REGMAP=y +CONFIG_SYSCON=y +CONFIG_SPL_SYSCON=y +CONFIG_CLK=y +CONFIG_SPL_CLK=y +CONFIG_FASTBOOT_BUF_ADDR=0x800800 +CONFIG_FASTBOOT_BUF_SIZE=0x04000000 +CONFIG_ROCKCHIP_GPIO=y +CONFIG_SYS_I2C_ROCKCHIP=y +CONFIG_MISC=y +CONFIG_ROCKCHIP_OTP=y +CONFIG_MMC_DW=y +CONFIG_MMC_DW_ROCKCHIP=y +CONFIG_PHY_REALTEK=y +CONFIG_ETH_DESIGNWARE=y +CONFIG_GMAC_ROCKCHIP=y +CONFIG_PINCTRL=y +CONFIG_SPL_PINCTRL=y +CONFIG_DM_PMIC=y +CONFIG_PMIC_RK8XX=y +CONFIG_ROCKCHIP_RK8XX_DISABLE_BOOT_ON_POWERON=y +CONFIG_SPL_PMIC_RK8XX=y +CONFIG_REGULATOR_PWM=y +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_REGULATOR_RK8XX=y +CONFIG_PWM_ROCKCHIP=y +CONFIG_RAM=y +CONFIG_SPL_RAM=y +CONFIG_TPL_RAM=y +CONFIG_ROCKCHIP_SDRAM_COMMON=y +CONFIG_RAM_ROCKCHIP_LPDDR3=y +# CONFIG_SPECIFY_CONSOLE_INDEX is not set +CONFIG_DEBUG_UART_SHIFT=2 +CONFIG_SYS_NS16550_MEM32=y +CONFIG_ROCKCHIP_SFC=y +CONFIG_SYSRESET=y +CONFIG_DM_THERMAL=y +CONFIG_USB=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_GENERIC=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_DWC2_OTG=y +CONFIG_VIDEO=y +CONFIG_DISPLAY=y +CONFIG_SPL_TINY_MEMSET=y +CONFIG_TPL_TINY_MEMSET=y +CONFIG_LZO=y +CONFIG_ERRNO_STR=y +CONFIG_OPTEE_LIB=y +CONFIG_TOOLS_MKEFICAPSULE=n +CONFIG_EFI_LOADER=n +CONFIG_TOOLS_KWBIMAGE=n +CONFIG_TOOLS_LIBCRYPTO=n diff --git a/projects/ArchR/devices/RK3326/packages/u-boot/sources/dts/upstream/src/arm64/rockchip/rk3326-common-handheld.dts b/projects/ArchR/devices/RK3326/packages/u-boot/sources/dts/upstream/src/arm64/rockchip/rk3326-common-handheld.dts new file mode 100644 index 0000000000..c832fa8126 --- /dev/null +++ b/projects/ArchR/devices/RK3326/packages/u-boot/sources/dts/upstream/src/arm64/rockchip/rk3326-common-handheld.dts @@ -0,0 +1,398 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2019 Hardkernel Co., Ltd + * Copyright (c) 2020 Theobroma Systems Design und Consulting GmbH + * Copyright (c) 2022 Maya Matuszczyk + * Copyright (c) 2025 ROCKNIX https://github.com/ROCKNIX + * Copyright (c) 2025 ArchR https://github.com/ArchR + */ + +/dts-v1/; +#include +#include +#include "rk3326.dtsi" + +/ { + model = "Generic RK3326 Handheld"; + compatible = "generic,rk3326-handheld", "rockchip,rk3326"; + + aliases { + mmc0 = &sdmmc; + }; + + chosen { + stdout-path = "serial2:1500000n8"; + }; + + vccsys: regulator-vccsys { + compatible = "regulator-fixed"; + regulator-name = "vcc3v8_sys"; + regulator-always-on; + regulator-min-microvolt = <3800000>; + regulator-max-microvolt = <3800000>; + }; +}; + +&cpu0 { + cpu-supply = <&vdd_arm>; +}; + +&cpu1 { + cpu-supply = <&vdd_arm>; +}; + +&cpu2 { + cpu-supply = <&vdd_arm>; +}; + +&cpu3 { + cpu-supply = <&vdd_arm>; +}; + +&cru { + assigned-clocks = <&cru PLL_NPLL>, + <&cru ACLK_BUS_PRE>, <&cru ACLK_PERI_PRE>, + <&cru HCLK_BUS_PRE>, <&cru HCLK_PERI_PRE>, + <&cru PCLK_BUS_PRE>, <&cru SCLK_GPU>; + + assigned-clock-rates = <1188000000>, + <200000000>, <200000000>, + <150000000>, <150000000>, + <100000000>, <200000000>; +}; + +&display_subsystem { + status = "okay"; +}; + +&i2c0 { + clock-frequency = <400000>; + i2c-scl-falling-time-ns = <16>; + i2c-scl-rising-time-ns = <280>; + status = "okay"; + + rk817: pmic@20 { + compatible = "rockchip,rk817"; + reg = <0x20>; + interrupt-parent = <&gpio0>; + interrupts = ; + clock-output-names = "rk808-clkout1", "xin32k"; + clock-names = "mclk"; + clocks = <&cru SCLK_I2S1_OUT>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int>, <&i2s1_2ch_mclk>; + wakeup-source; + #clock-cells = <1>; + #sound-dai-cells = <0>; + + vcc1-supply = <&vccsys>; + vcc2-supply = <&vccsys>; + vcc3-supply = <&vccsys>; + vcc4-supply = <&vccsys>; + vcc5-supply = <&vccsys>; + vcc6-supply = <&vccsys>; + vcc7-supply = <&vccsys>; + vcc8-supply = <&vccsys>; + + regulators { + vdd_logic: DCDC_REG1 { + regulator-name = "vdd_logic"; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1150000>; + regulator-ramp-delay = <6001>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vdd_arm: DCDC_REG2 { + regulator-name = "vdd_arm"; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-name = "vcc_ddr"; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_3v3: DCDC_REG4 { + regulator-name = "vcc_3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_1v8: LDO_REG2 { + regulator-name = "vcc_1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd_1v0: LDO_REG3 { + regulator-name = "vdd_1v0"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vcc3v3_pmu: LDO_REG4 { + regulator-name = "vcc3v3_pmu"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vccio_sd: LDO_REG5 { + regulator-name = "vccio_sd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_sd: LDO_REG6 { + regulator-name = "vcc_sd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_bl: LDO_REG7 { + regulator-name = "vcc_bl"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_lcd: LDO_REG8 { + regulator-name = "vcc_lcd"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <2800000>; + }; + }; + + LDO_REG9 { + /* unused */ + }; + + usb_midu: BOOST { + regulator-name = "usb_midu"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5400000>; + regulator-always-on; + regulator-boot-on; + }; + }; + + rk817_charger: charger { + rockchip,resistor-sense-micro-ohms = <10000>; + rockchip,sleep-enter-current-microamp = <300000>; + rockchip,sleep-filter-current-microamp = <100000>; + }; + + rk817_codec: codec { + rockchip,mic-in-differential; + }; + }; +}; + +/* EXT Header(P2): 7(SCL:GPIO0.C2), 8(SDA:GPIO0.C3) */ +&i2c1 { + clock-frequency = <400000>; + status = "okay"; +}; + +&io_domains { + vccio1-supply = <&vcc_3v3>; + vccio2-supply = <&vccio_sd>; + vccio3-supply = <&vcc_3v3>; + vccio4-supply = <&vcc_3v3>; + vccio5-supply = <&vcc_3v3>; + vccio6-supply = <&vcc_3v3>; + status = "okay"; +}; + +&pmu_io_domains { + pmuio1-supply = <&vcc3v3_pmu>; + pmuio2-supply = <&vcc3v3_pmu>; + status = "okay"; +}; + +&saradc { + vref-supply = <&vcc_1v8>; + status = "okay"; +}; + +&sdmmc { + cap-sd-highspeed; + card-detect-delay = <200>; + cd-gpios = <&gpio0 RK_PA3 GPIO_ACTIVE_LOW>; /*[> CD GPIO <]*/ + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + + /* For some reason if u-boot tries to manage these voltages, + some (old? cheap? random?) SD cards fail to initialize. + Legacy u-boot has no supply specified, and you can see + "No vmmc supply" in debug log, and those cards work well */ + /* + vmmc-supply = <&vcc_sd>; + vqmmc-supply = <&vccio_sd>; + */ + status = "okay"; +}; + +&sdio { + cap-sd-highspeed; + non-removable; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + vmmc-supply = <&vcc_sd>; + vqmmc-supply = <&vccio_sd>; + status = "okay"; +}; + +&sfc { + pinctrl-0 = <&sfc_clk &sfc_cs0 &sfc_bus2>; + pinctrl-names = "default"; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <108000000>; + spi-rx-bus-width = <2>; + spi-tx-bus-width = <1>; + }; +}; + +&tsadc { + status = "okay"; +}; + +&u2phy { + status = "okay"; + + u2phy_host: host-port { + status = "okay"; + }; + + u2phy_otg: otg-port { + status = "disabled"; + }; +}; + +&usb20_otg { + status = "okay"; +}; + +/* EXT Header(P2): 2(RXD:GPIO1.C0),3(TXD:.C1),4(CTS:.C2),5(RTS:.C3) */ +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_xfer &uart1_cts>; + status = "okay"; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&uart2m1_xfer>; + status = "okay"; +}; + +&vopb { + status = "okay"; +}; + +&vopb_mmu { + status = "okay"; +}; + +&pinctrl { + pmic { + dc_det: dc-det { + rockchip,pins = <0 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + pmic_int: pmic-int { + rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + soc_slppin_gpio: soc_slppin_gpio { + rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_output_low>; + }; + + soc_slppin_rst: soc_slppin_rst { + rockchip,pins = <0 RK_PA4 2 &pcfg_pull_none>; + }; + + soc_slppin_slp: soc_slppin_slp { + rockchip,pins = <0 RK_PA4 1 &pcfg_pull_none>; + }; + }; +}; diff --git a/projects/ArchR/devices/RK3326/patches/linux/000-rk3326-dts.patch b/projects/ArchR/devices/RK3326/patches/linux/000-rk3326-dts.patch new file mode 100644 index 0000000000..28d2bae258 --- /dev/null +++ b/projects/ArchR/devices/RK3326/patches/linux/000-rk3326-dts.patch @@ -0,0 +1,127 @@ +--- a/arch/arm64/boot/dts/rockchip/px30.dtsi 2026-04-18 00:12:46.801599300 -0300 ++++ b/arch/arm64/boot/dts/rockchip/px30.dtsi 2026-04-18 00:15:35.235545979 -0300 +@@ -20,6 +20,7 @@ + #size-cells = <2>; + + aliases { ++ ethernet0 = &gmac; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; +@@ -112,9 +113,10 @@ + cpu0_opp_table: opp-table-0 { + compatible = "operating-points-v2"; + opp-shared; ++ rockchip,avs = <1>; + +- opp-600000000 { +- opp-hz = /bits/ 64 <600000000>; ++ opp-408000000 { ++ opp-hz = /bits/ 64 <408000000>; + opp-microvolt = <950000 950000 1350000>; + clock-latency-ns = <40000>; + opp-suspend; +@@ -129,15 +131,16 @@ + opp-microvolt = <1175000 1175000 1350000>; + clock-latency-ns = <40000>; + }; +- opp-1200000000 { +- opp-hz = /bits/ 64 <1200000000>; +- opp-microvolt = <1300000 1300000 1350000>; ++ opp-1416000000 { ++ opp-hz = /bits/ 64 <1416000000>; ++ opp-microvolt = <1350000 1350000 1350000>; + clock-latency-ns = <40000>; + }; +- opp-1296000000 { +- opp-hz = /bits/ 64 <1296000000>; +- opp-microvolt = <1350000 1350000 1350000>; ++ opp-1512000000 { ++ opp-hz = /bits/ 64 <1512000000>; ++ opp-microvolt = <1400000 1400000 1400000>; + clock-latency-ns = <40000>; ++ turbo-mode; + }; + }; + +@@ -348,6 +351,32 @@ + }; + }; + ++ dfi: dfi@ff610000 { ++ reg = <0x00 0xff610000 0x00 0x400>; ++ compatible = "rockchip,px30-dfi"; ++ rockchip,pmu = <&pmugrf>; ++ status = "okay"; ++ }; ++ ++ dmc: dmc { ++ compatible = "rockchip,px30-dmc"; ++ devfreq-events = <&dfi>; ++ clocks = <&cru SCLK_DDRCLK>; ++ clock-names = "dmc_clk"; ++ operating-points-v2 = <&dmc_opp_table>; ++ uptreshold = <40>; ++ downdifferential = <20>; ++ status = "okay"; ++ }; ++ ++ dmc_opp_table: dmc_opp_table { ++ compatible = "operating-points-v2"; ++ opp-924000000 { ++ opp-hz = /bits/ 64 <924000000>; ++ opp-microvolt = <1125000>; ++ }; ++ }; ++ + pmugrf: syscon@ff010000 { + compatible = "rockchip,px30-pmugrf", "syscon", "simple-mfd"; + reg = <0x0 0xff010000 0x0 0x1000>; +@@ -1077,10 +1106,19 @@ + opp-hz = /bits/ 64 <400000000>; + opp-microvolt = <1050000>; + }; +- opp-480000000 { +- opp-hz = /bits/ 64 <480000000>; ++ opp-560000000 { ++ opp-hz = /bits/ 64 <560000000>; + opp-microvolt = <1125000>; + }; ++ opp-600000000 { ++ opp-hz = /bits/ 64 <600000000>; ++ opp-microvolt = <1150000>; ++ }; ++ opp-650000000 { ++ opp-hz = /bits/ 64 <650000000>; ++ opp-microvolt = <1150000>; ++ turbo-mode; ++ }; + }; + + gpu: gpu@ff400000 { +@@ -1091,10 +1129,25 @@ + ; + interrupt-names = "job", "mmu", "gpu"; + clocks = <&cru SCLK_GPU>; ++ clock-names = "bus"; ++ resets = <&cru SRST_GPU>; + #cooling-cells = <2>; + power-domains = <&power PX30_PD_GPU>; ++ power_policy = "coarse_demand"; + operating-points-v2 = <&gpu_opp_table>; + status = "disabled"; ++ ++ power_model@0 { ++ compatible = "arm,mali-simple-power-model"; ++ static-coefficient = <100000>; ++ dynamic-coefficient = <953>; ++ ts = <(-108890) 63610 (-1355) 20>; ++ thermal-zone = "gpu-thermal"; ++ }; ++ power_model@1 { ++ compatible = "arm,mali-g31-power-model"; ++ scale = <5>; ++ }; + }; + + vpu: video-codec@ff442000 { diff --git a/projects/ArchR/devices/RK3326/patches/linux/001-panel-updates.patch b/projects/ArchR/devices/RK3326/patches/linux/001-panel-updates.patch new file mode 100644 index 0000000000..e29338fbfc --- /dev/null +++ b/projects/ArchR/devices/RK3326/patches/linux/001-panel-updates.patch @@ -0,0 +1,235 @@ +diff --git a/drivers/gpu/drm/panel/panel-newvision-nv3051d.c b/drivers/gpu/drm/panel/panel-newvision-nv3051d.c +index 5d115ecd5dd4..1b199662e7ed 100644 +--- a/drivers/gpu/drm/panel/panel-newvision-nv3051d.c ++++ b/drivers/gpu/drm/panel/panel-newvision-nv3051d.c +@@ -480,14 +480,14 @@ static const struct drm_display_mode nv3051d_rgxx3_modes[] = { + static const struct drm_display_mode nv3051d_rk2023_modes[] = { + { + .hdisplay = 640, +- .hsync_start = 640 + 40, +- .hsync_end = 640 + 40 + 2, +- .htotal = 640 + 40 + 2 + 80, ++ .hsync_start = 640 + 48, ++ .hsync_end = 640 + 48 + 2, ++ .htotal = 640 + 48 + 2 + 47, + .vdisplay = 480, +- .vsync_start = 480 + 18, +- .vsync_end = 480 + 18 + 2, +- .vtotal = 480 + 18 + 2 + 4, +- .clock = 24150, ++ .vsync_start = 480 + 2, ++ .vsync_end = 480 + 2 + 4, ++ .vtotal = 480 + 2 + 4 + 3, ++ .clock = 21600, + .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, + }, + }; +@@ -520,7 +520,8 @@ static const struct nv3051d_panel_info nv3051d_rk2023_info = { + .height_mm = 57, + .bus_flags = DRM_BUS_FLAG_DE_LOW | DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE, + .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | +- MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_NO_EOT_PACKET, ++ MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_NO_EOT_PACKET | ++ MIPI_DSI_CLOCK_NON_CONTINUOUS, + }; + + static const struct of_device_id newvision_nv3051d_of_match[] = { +diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7703.c b/drivers/gpu/drm/panel/panel-sitronix-st7703.c +index 67e8e45498cb..a9cc6c6c0fc1 100644 +--- a/drivers/gpu/drm/panel/panel-sitronix-st7703.c ++++ b/drivers/gpu/drm/panel/panel-sitronix-st7703.c +@@ -673,6 +673,182 @@ static const struct st7703_panel_desc gameforcechi_desc = { + .init_sequence = gameforcechi_init_sequence, + }; + ++static void xu10_init_sequence(struct mipi_dsi_multi_context *dsi_ctx) ++{ ++ /* ++ * Init sequence was supplied by the panel vendor. ++ */ ++ ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEXTC, 0xf1, 0x12, 0x83); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETAPID, 0x00, 0x00, 0x00, ++ 0xda, 0x80); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETDISP, 0x00, 0x03, 0xf0); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETRGBIF, 0x10, 0x10, 0x28, ++ 0x28, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETCYC, 0x80); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETBGP, 0x0a, 0x0a); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVCOM, 0x8e, 0x8e); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER_EXT, 0x26, 0x22, ++ 0xf0, 0x13); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETMIPI, 0x33, 0x81, 0x05, ++ 0xf9, 0x0e, 0x0e, 0x20, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x44, 0x25, 0x00, 0x90, 0x0a, ++ 0x00, 0x00, 0x01, 0x4f, 0x01, 0x00, 0x00, 0x37); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVDC, 0x47); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETSCR, 0x73, 0x73, 0x50, 0x50, ++ 0x00, 0x00, 0x12, 0x70, 0x00); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER, 0x53, 0x00, 0x32, ++ 0x32, 0x77, 0xd1, 0xcc, 0xcc, 0x77, 0x77, 0x33, ++ 0x33); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETECO, 0x82, 0x00, 0xbf, 0xff, ++ 0x00, 0xff); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETIO, 0xb8, 0x00, 0x0a, 0x00, ++ 0x00, 0x00); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETCABC, 0x10, 0x40, 0x1e, ++ 0x02); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPANEL, 0x0b); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGAMMA, 0x00, 0x06, 0x0a, ++ 0x2a, 0x3d, 0x3f, 0x3b, 0x37, 0x06, 0x0b, 0x0c, ++ 0x10, 0x11, 0x10, 0x13, 0x12, 0x18, 0x00, 0x06, ++ 0x0a, 0x2a, 0x3d, 0x3f, 0x3b, 0x37, 0x06, 0x0b, ++ 0x0c, 0x10, 0x11, 0x10, 0x13, 0x12, 0x18); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEQ, 0x07, 0x07, 0x0b, 0x0b, ++ 0x0b, 0x0b, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, ++ 0xc0, 0x10); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP1, 0xc8, 0x10, 0x02, 0x00, ++ 0x00, 0xb0, 0xb1, 0x11, 0x31, 0x23, 0x28, 0x80, ++ 0xb0, 0xb1, 0x27, 0x08, 0x00, 0x04, 0x02, 0x00, ++ 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00, ++ 0x88, 0x88, 0xba, 0x60, 0x24, 0x08, 0x88, 0x88, ++ 0x88, 0x88, 0x88, 0x88, 0x88, 0xba, 0x71, 0x35, ++ 0x18, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, ++ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP2, 0x97, 0x0a, 0x82, 0x02, ++ 0x03, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x81, 0x88, 0xba, 0x17, 0x53, 0x88, 0x88, 0x88, ++ 0x88, 0x88, 0x88, 0x80, 0x88, 0xba, 0x06, 0x42, ++ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x23, 0x00, ++ 0x00, 0x02, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_EF, 0xff, 0xff, 0x01, 0x05, 0x96, 0x01, 0x11, 0x05, 0x78, 0x01, 0x29); ++} ++ ++static const struct drm_display_mode xu10_mode = { ++ .hdisplay = 640, ++ .hsync_start = 640 + 120, ++ .hsync_end = 640 + 120 + 10, ++ .htotal = 640 + 120 + 10 + 120, ++ .vdisplay = 480, ++ .vsync_start = 480 + 17, ++ .vsync_end = 480 + 17 + 4, ++ .vtotal = 480 + 17 + 4 + 13, ++ .clock = 30000, ++ .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, ++ .width_mm = 52, ++ .height_mm = 70, ++}; ++ ++static const struct st7703_panel_desc xu10_desc = { ++ .mode = &xu10_mode, ++ .lanes = 4, ++ .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | ++ MIPI_DSI_MODE_NO_EOT_PACKET | MIPI_DSI_MODE_LPM, ++ .format = MIPI_DSI_FMT_RGB888, ++ .init_sequence = xu10_init_sequence, ++}; ++ ++static void r36s_init_sequence(struct mipi_dsi_multi_context *dsi_ctx) ++{ ++ /* ++ * Init sequence was supplied by the panel vendor. ++ */ ++ ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEXTC, 0xf1, 0x12, 0x83); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETAPID, 0x00, 0x00, 0x00, ++ 0xda, 0x80); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETDISP, 0x00, 0x13, 0x70); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETRGBIF, 0x10, 0x10, 0x28, ++ 0x28, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETCYC, 0x80); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETBGP, 0x0a, 0x0a); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVCOM, 0x7f, 0x7f); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER_EXT, 0x26, 0x62, ++ 0xf0, 0x63); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETMIPI, 0x33, 0x81, 0x05, ++ 0xf9, 0x0e, 0x0e, 0x20, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x44, 0x25, 0x00, 0x90, 0x0a, ++ 0x00, 0x00, 0x01, 0x4f, 0x01, 0x00, 0x00, 0x37); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVDC, 0x47); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETSCR, 0x73, 0x73, 0x50, 0x50, ++ 0x00, 0x00, 0x12, 0x50, 0x00); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER, 0x53, 0xc0, 0x32, ++ 0x32, 0x77, 0xe1, 0xdd, 0xdd, 0x77, 0x77, 0x33, ++ 0x33); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETECO, 0x82, 0x00, 0xbf, 0xff, ++ 0x00, 0xff); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETIO, 0xb8, 0x00, 0x0a, 0x00, ++ 0x00, 0x00); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETCABC, 0x10, 0x40, 0x1e, ++ 0x02); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPANEL, 0x0b); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGAMMA, 0x00, 0x07, 0x0d, ++ 0x37, 0x35, 0x3f, 0x41, 0x44, 0x06, 0x0c, 0x0d, ++ 0x0f, 0x11, 0x10, 0x12, 0x14, 0x1a, 0x00, 0x07, ++ 0x0d, 0x37, 0x35, 0x3f, 0x41, 0x44, 0x06, 0x0c, ++ 0x0d, 0x0f, 0x11, 0x10, 0x12, 0x14, 0x1a); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEQ, 0x07, 0x07, 0x0b, 0x0b, ++ 0x0b, 0x0b, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, ++ 0xc0, 0x10); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP1, 0xc8, 0x10, 0x02, 0x00, ++ 0x00, 0xb0, 0xb1, 0x11, 0x31, 0x23, 0x28, 0x80, ++ 0xb0, 0xb1, 0x27, 0x08, 0x00, 0x04, 0x02, 0x00, ++ 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00, ++ 0x88, 0x88, 0xba, 0x60, 0x24, 0x08, 0x88, 0x88, ++ 0x88, 0x88, 0x88, 0x88, 0x88, 0xba, 0x71, 0x35, ++ 0x18, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, ++ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP2, 0x97, 0x0a, 0x82, 0x02, ++ 0x03, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x81, 0x88, 0xba, 0x17, 0x53, 0x88, 0x88, 0x88, ++ 0x88, 0x88, 0x88, 0x80, 0x88, 0xba, 0x06, 0x42, ++ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x23, 0x00, ++ 0x00, 0x02, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00); ++ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_EF, 0xff, 0xff, 0x01, 0x05, 0xc8, 0x01, 0x11, 0x05, 0x32, 0x01, 0x29); ++} ++ ++static const struct drm_display_mode r36s_mode = { ++ .hdisplay = 640, ++ .hsync_start = 640 + 450, ++ .hsync_end = 640 + 450 + 70, ++ .htotal = 640 + 450 + 70 + 450, ++ .vdisplay = 480, ++ .vsync_start = 480 + 17, ++ .vsync_end = 480 + 17 + 5, ++ .vtotal = 480 + 17 + 5 + 13, ++ .clock = 50000, ++ .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, ++ .width_mm = 52, ++ .height_mm = 70, ++}; ++ ++static const struct st7703_panel_desc r36s_desc = { ++ .mode = &r36s_mode, ++ .lanes = 4, ++ .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | ++ MIPI_DSI_MODE_NO_EOT_PACKET | MIPI_DSI_MODE_LPM, ++ .format = MIPI_DSI_FMT_RGB888, ++ .init_sequence = r36s_init_sequence, ++}; ++ + static int st7703_enable(struct drm_panel *panel) + { + struct st7703 *ctx = panel_to_st7703(panel); +@@ -916,8 +1092,11 @@ static void st7703_remove(struct mipi_dsi_device *dsi) + } + + static const struct of_device_id st7703_of_match[] = { ++ { .compatible = "anbernic,rg351v-panel-v2", .data = &rg353v2_desc }, + { .compatible = "anbernic,rg353v-panel-v2", .data = &rg353v2_desc }, ++ { .compatible = "gameconsole,r36s-panel", .data = &r36s_desc }, + { .compatible = "gameforce,chi-panel", .data = &gameforcechi_desc }, ++ { .compatible = "magicx,xu10-panel", .data = &xu10_desc }, + { .compatible = "powkiddy,rgb10max3-panel", .data = &rgb10max3_panel_desc }, + { .compatible = "powkiddy,rgb30-panel", .data = &rgb30panel_desc }, + { .compatible = "rocktech,jh057n00900", .data = &jh057n00900_panel_desc }, diff --git a/projects/ArchR/devices/RK3326/patches/linux/004-input-drivers.patch b/projects/ArchR/devices/RK3326/patches/linux/004-input-drivers.patch new file mode 100644 index 0000000000..341f7a4457 --- /dev/null +++ b/projects/ArchR/devices/RK3326/patches/linux/004-input-drivers.patch @@ -0,0 +1,6816 @@ +diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig +index 7755e5b454d2..38355e3184fc 100644 +--- a/drivers/input/joystick/Kconfig ++++ b/drivers/input/joystick/Kconfig +@@ -400,6 +400,36 @@ config JOYSTICK_N64 + Say Y here if you want enable support for the four + built-in controller ports on the Nintendo 64 console. + ++config JOYSTICK_ODROIDGO2 ++ tristate "ODROIDGO2-Advance joypad driver" ++ help ++ Made for ODROIDGO2-Advance. ++ ++config JOYSTICK_ODROIDGO2_V11 ++ tristate "ODROIDGO2-Advance joypad driver" ++ help ++ Made for ODROIDGO2-Advance. ++ ++config JOYSTICK_ODROIDGO3 ++ tristate "ODROIDGO3 joypad driver" ++ help ++ Made for ODROIDGO3. ++ ++config JOYSTICK_RGB20S ++ tristate "RGB20S joypad driver" ++ help ++ Made for RGB20S. ++ ++config JOYSTICK_XU10 ++ tristate "XU10 joypad driver" ++ help ++ Made for XU10. ++ ++config JOYSTICK_GAMEFORCE_CHI ++ tristate "gameforce joypad driver" ++ help ++ Made for Gameforce CHI. ++ + config JOYSTICK_SENSEHAT + tristate "Raspberry Pi Sense HAT joystick" + depends on INPUT && I2C +diff --git a/drivers/input/joystick/Makefile b/drivers/input/joystick/Makefile +index 9976f596a920..2a0524b63ba0 100644 +--- a/drivers/input/joystick/Makefile ++++ b/drivers/input/joystick/Makefile +@@ -15,6 +15,7 @@ obj-$(CONFIG_JOYSTICK_COBRA) += cobra.o + obj-$(CONFIG_JOYSTICK_DB9) += db9.o + obj-$(CONFIG_JOYSTICK_FSIA6B) += fsia6b.o + obj-$(CONFIG_JOYSTICK_GAMECON) += gamecon.o ++obj-$(CONFIG_JOYSTICK_GAMEFORCE_CHI) += gameforce-joypad.o + obj-$(CONFIG_JOYSTICK_GF2K) += gf2k.o + obj-$(CONFIG_JOYSTICK_GRIP) += grip.o + obj-$(CONFIG_JOYSTICK_GRIP_MP) += grip_mp.o +@@ -25,6 +26,10 @@ obj-$(CONFIG_JOYSTICK_JOYDUMP) += joydump.o + obj-$(CONFIG_JOYSTICK_MAGELLAN) += magellan.o + obj-$(CONFIG_JOYSTICK_MAPLE) += maplecontrol.o + obj-$(CONFIG_JOYSTICK_N64) += n64joy.o ++obj-$(CONFIG_JOYSTICK_ODROIDGO2) += odroidgo2-joypad.o ++obj-$(CONFIG_JOYSTICK_ODROIDGO2_V11) += odroidgo2-v11-joypad.o ++obj-$(CONFIG_JOYSTICK_ODROIDGO3) += odroidgo3-joypad.o ++obj-$(CONFIG_JOYSTICK_RGB20S) += rgb20s-joypad.o + obj-$(CONFIG_JOYSTICK_PSXPAD_SPI) += psxpad-spi.o + obj-$(CONFIG_JOYSTICK_PXRC) += pxrc.o + obj-$(CONFIG_JOYSTICK_QWIIC) += qwiic-joystick.o +@@ -40,4 +45,5 @@ obj-$(CONFIG_JOYSTICK_TWIDJOY) += twidjoy.o + obj-$(CONFIG_JOYSTICK_WARRIOR) += warrior.o + obj-$(CONFIG_JOYSTICK_WALKERA0701) += walkera0701.o + obj-$(CONFIG_JOYSTICK_XPAD) += xpad.o ++obj-$(CONFIG_JOYSTICK_XU10) += xu10-joypad.o + obj-$(CONFIG_JOYSTICK_ZHENHUA) += zhenhua.o +diff --git a/drivers/input/joystick/gameforce-joypad.c b/drivers/input/joystick/gameforce-joypad.c +new file mode 100644 +index 000000000000..e2953433b491 +--- /dev/null ++++ b/drivers/input/joystick/gameforce-joypad.c +@@ -0,0 +1,1330 @@ ++/* ++ * SARADC joystick & GPIO Button driver for Linux(Gameforce CHI) ++ */ ++/* ++ * 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 ++ * ++ * Should you need to contact me, the author, you can do so either by ++ * e-mail - mail your message to , or by paper mail: ++ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic ++ */ ++ ++/*----------------------------------------------------------------------------*/ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define RIGHT_ADC_JOYSTICK ++#define VOLUME_ADC_KEYS ++#define VIBRATORS_FF ++ ++#ifdef RIGHT_ADC_JOYSTICK ++#include ++#include "../input-compat.h" ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++#define DRV_NAME "gameforce_gamepad" ++/*----------------------------------------------------------------------------*/ ++#ifdef VOLUME_ADC_KEYS ++struct of_device_id adckeys_of_match[] = { ++ { .compatible = "volume-keys", }, ++ {}, ++}; ++#endif ++ ++#ifdef VIBRATORS_FF ++struct of_device_id vibrators_of_match[] = { ++ { .compatible = "gpio,vibrators", }, ++ {}, ++}; ++ ++ ++struct gpio_vib { ++ struct work_struct work; ++ int speed; ++ int index; ++ int last_index; ++ bool active; ++ int gpio0; ++ int gpio1; ++}; ++#endif ++ ++#ifdef VOLUME_ADC_KEYS ++struct adc_keys_button { ++ u32 voltage; ++ u32 keycode; ++}; ++ ++struct adc_keys_state { ++ struct iio_channel *channel; ++ u32 num_keys; ++ u32 last_key; ++ u32 keyup_voltage; ++ const struct adc_keys_button *map; ++}; ++#endif ++ ++struct bt_adc { ++ /* IIO ADC Channel */ ++ struct iio_channel *channel; ++ /* report value (mV) */ ++ int old_value; ++ /* report type */ ++ int report_type; ++ /* input device init value (mV) */ ++ int max, min; ++ /* calibrated adc value */ ++ int cal; ++ /* adc scale value */ ++ int scale; ++ /* invert report */ ++ bool invert; ++}; ++ ++struct bt_gpio { ++ /* GPIO Request label */ ++ const char *label; ++ /* GPIO Number */ ++ int num; ++ /* report type */ ++ int report_type; ++ /* report linux code */ ++ int linux_code; ++ /* prev button value */ ++ bool old_value; ++ /* button press level */ ++ bool active_level; ++}; ++ ++struct joypad { ++ struct device *dev; ++ int poll_interval; ++ ++ /* report enable/disable */ ++ bool enable; ++ ++ /* report reference point */ ++ bool invert_absx; ++ bool invert_absy; ++ ++ /* report interval (ms) */ ++ int bt_gpio_count; ++ struct bt_gpio *gpios; ++ /* button auto repeat */ ++ int auto_repeat; ++ ++ /* report threshold (mV) */ ++ int bt_adc_fuzz, bt_adc_flat; ++ int bt_adc_x_range, bt_adc_y_range; ++ /* adc read value scale */ ++ int bt_adc_scale; ++ /* joystick deadzone control */ ++ int bt_adc_deadzone; ++ int bt_adc_count; ++ struct bt_adc *adcs; ++#ifdef VOLUME_ADC_KEYS ++ /*adc key saradc[2]*/ ++ struct adc_keys_state *st; ++#endif ++#ifdef VIBRATORS_FF ++ /* vibrator */ ++ struct gpio_vib *vib; ++#endif ++ struct mutex lock; ++}; ++ ++#ifdef RIGHT_ADC_JOYSTICK ++struct input_dev *global_input = NULL; ++#endif ++/*----------------------------------------------------------------------------*/ ++// ++// set to the value in the boot.ini file. (if exist) ++// ++/*----------------------------------------------------------------------------*/ ++static unsigned int g_button_adc_x_range = 0; ++static unsigned int g_button_adc_y_range = 0; ++static unsigned int g_button_adc_fuzz = 0; ++static unsigned int g_button_adc_flat = 0; ++static unsigned int g_button_adc_scale = 0; ++static unsigned int g_button_adc_deadzone = 0; ++ ++static int __init button_adcx_range_setup(char *str) ++{ ++ if (!str) ++ return -EINVAL; ++ ++ g_button_adc_x_range = simple_strtoul(str, NULL, 10); ++ ++ return 0; ++} ++__setup("button-adc-x-range=", button_adcx_range_setup); ++ ++static int __init button_adcy_range_setup(char *str) ++{ ++ if (!str) ++ return -EINVAL; ++ ++ g_button_adc_y_range = simple_strtoul(str, NULL, 10); ++ ++ return 0; ++} ++__setup("button-adc-y-range=", button_adcy_range_setup); ++ ++static int button_adc_fuzz(char *str) ++{ ++ if (!str) ++ return -EINVAL; ++ g_button_adc_fuzz = simple_strtoul(str, NULL, 10); ++ return 0; ++} ++__setup("button-adc-fuzz=", button_adc_fuzz); ++ ++static int button_adc_flat(char *str) ++{ ++ if (!str) ++ return -EINVAL; ++ g_button_adc_flat = simple_strtoul(str, NULL, 10); ++ return 0; ++} ++__setup("button-adc-flat=", button_adc_flat); ++ ++static int button_adc_scale(char *str) ++{ ++ if (!str) ++ return -EINVAL; ++ g_button_adc_scale = simple_strtoul(str, NULL, 10); ++ return 0; ++} ++__setup("button-adc-scale=", button_adc_scale); ++ ++static int button_adc_deadzone(char *str) ++{ ++ if (!str) ++ return -EINVAL; ++ g_button_adc_deadzone = simple_strtoul(str, NULL, 10); ++ return 0; ++} ++__setup("button-adc-deadzone=", button_adc_deadzone); ++ ++/*----------------------------------------------------------------------------*/ ++/*----------------------------------------------------------------------------*/ ++static int joypad_adc_read(struct bt_adc *adc) ++{ ++ int value; ++ ++ if (iio_read_channel_processed(adc->channel, &value)) ++ return 0; ++ ++ value *= adc->scale; ++ ++ return (adc->invert ? (adc->max - value) : value); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*----------------------------------------------------------------------------*/ ++/* ++ * ATTRIBUTES: ++ * ++ * /sys/devices/platform/DRV_NAME/poll_interval [rw] ++ */ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_store_poll_interval(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, ++ size_t count) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ mutex_lock(&joypad->lock); ++ joypad->poll_interval = simple_strtoul(buf, NULL, 10); ++ mutex_unlock(&joypad->lock); ++ ++ return count; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_show_poll_interval(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ return sprintf(buf, "%d\n", joypad->poll_interval); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static DEVICE_ATTR(poll_interval, S_IWUSR | S_IRUGO, ++ joypad_show_poll_interval, ++ joypad_store_poll_interval); ++ ++/*----------------------------------------------------------------------------*/ ++/* ++ * ATTRIBUTES: ++ * ++ * /sys/devices/platform/DRV_NAME/adc_fuzz [r] ++ */ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_show_adc_fuzz(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ return sprintf(buf, "%d\n", joypad->bt_adc_fuzz); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static DEVICE_ATTR(adc_fuzz, S_IWUSR | S_IRUGO, ++ joypad_show_adc_fuzz, ++ NULL); ++ ++/*----------------------------------------------------------------------------*/ ++/* ++ * ATTRIBUTES: ++ * ++ * /sys/devices/platform/DRV_NAME/adc_flat [r] ++ */ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_show_adc_flat(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ return sprintf(buf, "%d\n", joypad->bt_adc_flat); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static DEVICE_ATTR(adc_flat, S_IWUSR | S_IRUGO, ++ joypad_show_adc_flat, ++ NULL); ++ ++/*----------------------------------------------------------------------------*/ ++/* ++ * ATTRIBUTES: ++ * ++ * /sys/devices/platform/DRV_NAME/enable [rw] ++ */ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_store_enable(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, ++ size_t count) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ mutex_lock(&joypad->lock); ++ joypad->enable = simple_strtoul(buf, NULL, 10); ++ mutex_unlock(&joypad->lock); ++ ++ return count; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_show_enable(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ return sprintf(buf, "%d\n", joypad->enable); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO, ++ joypad_show_enable, ++ joypad_store_enable); ++ ++/*----------------------------------------------------------------------------*/ ++/* ++ * ATTRIBUTES: ++ * ++ * /sys/devices/platform/DRV_NAME/adc_cal [rw] ++ */ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_store_adc_cal(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, ++ size_t count) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ bool calibration; ++ ++ calibration = simple_strtoul(buf, NULL, 10); ++ ++ if (calibration) { ++ int nbtn; ++ ++ mutex_lock(&joypad->lock); ++ for (nbtn = 0; nbtn < joypad->bt_adc_count; nbtn++) { ++ struct bt_adc *adc = &joypad->adcs[nbtn]; ++ ++ adc->cal = joypad_adc_read(adc); ++ if (!adc->cal) { ++ dev_err(joypad->dev, "%s : saradc channels[%d]!\n", ++ __func__, nbtn); ++ continue; ++ } ++ adc->old_value = adc->cal; ++ } ++ mutex_unlock(&joypad->lock); ++ } ++ return count; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_show_adc_cal(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ int nbtn; ++ ssize_t pos; ++ ++ for (nbtn = 0, pos = 0; nbtn < joypad->bt_adc_count; nbtn++) { ++ struct bt_adc *adc = &joypad->adcs[nbtn]; ++ pos += sprintf(&buf[pos], "adc[%d]->cal = %d ", ++ nbtn, adc->cal); ++ } ++ pos += sprintf(&buf[pos], "\n"); ++ return pos; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static DEVICE_ATTR(adc_cal, S_IWUSR | S_IRUGO, ++ joypad_show_adc_cal, ++ joypad_store_adc_cal); ++ ++/*----------------------------------------------------------------------------*/ ++/*----------------------------------------------------------------------------*/ ++static struct attribute *joypad_attrs[] = { ++ &dev_attr_poll_interval.attr, ++ &dev_attr_adc_fuzz.attr, ++ &dev_attr_adc_flat.attr, ++ &dev_attr_enable.attr, ++ &dev_attr_adc_cal.attr, ++ NULL, ++}; ++ ++static struct attribute_group joypad_attr_group = { ++ .attrs = joypad_attrs, ++}; ++ ++/*----------------------------------------------------------------------------*/ ++/*----------------------------------------------------------------------------*/ ++static void joypad_gpio_check(struct input_polled_dev *poll_dev) ++{ ++ struct joypad *joypad = poll_dev->private; ++ int nbtn, value; ++ ++ for (nbtn = 0; nbtn < joypad->bt_gpio_count; nbtn++) { ++ struct bt_gpio *gpio = &joypad->gpios[nbtn]; ++ ++ if (gpio_get_value_cansleep(gpio->num) < 0) { ++ dev_err(joypad->dev, "failed to get gpio state\n"); ++ continue; ++ } ++ value = gpio_get_value(gpio->num); ++ if (value != gpio->old_value) { ++ input_event(poll_dev->input, ++ gpio->report_type, ++ gpio->linux_code, ++ (value == gpio->active_level) ? 1 : 0); ++ gpio->old_value = value; ++ } ++ } ++ input_sync(poll_dev->input); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static void joypad_adc_check(struct input_polled_dev *poll_dev) ++{ ++ struct joypad *joypad = poll_dev->private; ++ int nbtn, value; ++ ++ for (nbtn = 0; nbtn < joypad->bt_adc_count; nbtn++) { ++ struct bt_adc *adc = &joypad->adcs[nbtn]; ++ ++ value = joypad_adc_read(adc); ++ if (!value) { ++ dev_err(joypad->dev, "%s : saradc channels[%d]!\n", ++ __func__, nbtn); ++ continue; ++ } ++ ++ /* Joystick Deadzone check */ ++ if (joypad->bt_adc_deadzone) { ++ if ((value < adc->cal + joypad->bt_adc_deadzone) && ++ (value > adc->cal - joypad->bt_adc_deadzone)) ++ value = adc->cal; ++ } ++ value = value - adc->cal; ++ value = value > adc->max ? adc->max : value; ++ value = value < adc->min ? adc->min : value; ++ ++ if (nbtn == 0) ++ { ++ // adc-x value is default inverted(h/w) ++ input_report_abs(poll_dev->input, ++ adc->report_type, value); ++ } ++ else ++ { ++ input_report_abs(poll_dev->input, ++ adc->report_type, value * (-1)); ++ } ++ adc->old_value = value; ++ } ++ input_sync(poll_dev->input); ++} ++ ++/*----------------------------------------------------------------------------*/ ++#ifdef VOLUME_ADC_KEYS ++static int joypad_vol_check(struct input_polled_dev *poll_dev) ++{ ++ struct joypad *joypad = poll_dev->private; ++ //struct adc_keys_state *st = dev->private; ++ int i, value, ret; ++ u32 diff, closest = 0xffffffff; ++ int keycode = 0; ++ ++ ret = iio_read_channel_processed(joypad->st->channel, &value); ++ if (unlikely(ret < 0)) { ++ /* Forcibly release key if any was pressed */ ++ value = joypad->st->keyup_voltage; ++ } else { ++ for (i = 0; i < joypad->st->num_keys; i++) { ++ diff = abs(joypad->st->map[i].voltage - value); ++ if (diff < closest) { ++ closest = diff; ++ keycode = joypad->st->map[i].keycode; ++ } ++ } ++ } ++ ++ if (((157 320) && (value<1700))) ++ return -1; ++ if (abs(joypad->st->keyup_voltage - value) < closest) ++ keycode = 0; ++ ++ if (joypad->st->last_key && joypad->st->last_key != keycode) ++ input_report_key(poll_dev->input, joypad->st->last_key, 0); ++ ++ if (keycode) ++ input_report_key(poll_dev->input, keycode, 1); ++ ++ input_sync(poll_dev->input); ++ joypad->st->last_key = keycode; ++ ++ return 0; ++} ++#endif ++/*----------------------------------------------------------------------------*/ ++static void joypad_poll(struct input_polled_dev *poll_dev) ++{ ++ struct joypad *joypad = poll_dev->private; ++ ++ if (joypad->enable) { ++ joypad_adc_check(poll_dev); ++ joypad_gpio_check(poll_dev); ++ #ifdef VOLUME_ADC_KEYS ++ joypad_vol_check(poll_dev); ++ #endif ++ } ++ if (poll_dev->poll_interval != joypad->poll_interval) { ++ mutex_lock(&joypad->lock); ++ poll_dev->poll_interval = joypad->poll_interval; ++ mutex_unlock(&joypad->lock); ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++static void joypad_open(struct input_polled_dev *poll_dev) ++{ ++ struct joypad *joypad = poll_dev->private; ++ int nbtn; ++ ++ for (nbtn = 0; nbtn < joypad->bt_gpio_count; nbtn++) { ++ struct bt_gpio *gpio = &joypad->gpios[nbtn]; ++ gpio->old_value = gpio->active_level ? 0 : 1; ++ } ++ for (nbtn = 0; nbtn < joypad->bt_adc_count; nbtn++) { ++ struct bt_adc *adc = &joypad->adcs[nbtn]; ++ ++ adc->old_value = joypad_adc_read(adc); ++ if (!adc->old_value) { ++ dev_err(joypad->dev, "%s : saradc channels[%d]!\n", ++ __func__, nbtn); ++ continue; ++ } ++ adc->cal = adc->old_value; ++ dev_info(joypad->dev, "%s : adc[%d] adc->cal = %d\n", ++ __func__, nbtn, adc->cal); ++ } ++ /* buttons status sync */ ++ joypad_adc_check(poll_dev); ++ joypad_gpio_check(poll_dev); ++ ++ /* button report enable */ ++ mutex_lock(&joypad->lock); ++ joypad->enable = true; ++ mutex_unlock(&joypad->lock); ++ ++ dev_info(joypad->dev, "%s : opened\n", __func__); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static void joypad_close(struct input_polled_dev *poll_dev) ++{ ++ struct joypad *joypad = poll_dev->private; ++ ++ /* button report disable */ ++ mutex_lock(&joypad->lock); ++ joypad->enable = false; ++ mutex_unlock(&joypad->lock); ++ ++ dev_info(joypad->dev, "%s : closed\n", __func__); ++} ++#ifdef VIBRATORS_FF ++/** ++ * gpio_vib_set - handler to start/stop vibration ++ * @vib: pointer to vibrator structure ++ * @on: state to set ++ */ ++static int gpio_vib_set(struct gpio_vib *vib, bool on) ++{ ++ if (on) { ++ if (vib->last_index) { ++ gpio_direction_output(vib->gpio1, 1); ++ gpio_set_value(vib->gpio1, 1); ++ } else { ++ gpio_direction_output(vib->gpio0, 1); ++ gpio_set_value(vib->gpio0, 1); ++ } ++ } ++ else { ++ if (vib->last_index) { ++ gpio_direction_output(vib->gpio1, 0); ++ gpio_set_value(vib->gpio1, 0); ++ } else { ++ gpio_direction_output(vib->gpio0, 0); ++ gpio_set_value(vib->gpio0, 0); ++ } ++ } ++ ++ return 0; ++} ++ ++/** ++ * vib_work_handler - worker to set vibration level ++ * @work: pointer to work_struct ++ */ ++static void vib_work_handler(struct work_struct *work) ++{ ++ struct gpio_vib *vib = container_of(work, struct gpio_vib, work); ++ //struct joypad *joypad = container_of(vib, struct joypad, vib); ++ ++ /* ++ * pmic vibrator supports voltage ranges from 1.2 to 3.1V, so ++ * scale the level to fit into these ranges. ++ */ ++ printk("%s speed = %d\n", __func__, vib->speed); ++ if (vib->speed) { ++ vib->active = true; ++ } else { ++ vib->active = false; ++ } ++ ++ gpio_vib_set(vib, vib->active); ++} ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++static int joypad_adc_setup(struct device *dev, struct joypad *joypad) ++{ ++ int nbtn = 0; ++ ++ joypad->adcs = devm_kzalloc(dev, joypad->bt_adc_count * ++ sizeof(struct bt_adc), GFP_KERNEL); ++ ++ if (!joypad->adcs) { ++ dev_err(dev, "%s devm_kzmalloc error!", __func__); ++ return -ENOMEM; ++ } ++ ++ for (nbtn = 0; nbtn < joypad->bt_adc_count; nbtn++) { ++ struct bt_adc *adc = &joypad->adcs[nbtn]; ++ enum iio_chan_type type; ++ ++ adc->scale = joypad->bt_adc_scale; ++ if (nbtn) { ++ adc->channel = ++ devm_iio_channel_get(dev, "joy_y"); ++ adc->report_type = ABS_Y; ++ if (joypad->invert_absy) ++ adc->invert = true; ++ ++ adc->max = (joypad->bt_adc_y_range / 2) - 1; ++ adc->min = -(joypad->bt_adc_y_range / 2); ++ } ++ else { ++ adc->channel = ++ devm_iio_channel_get(dev, "joy_x"); ++ adc->report_type = ABS_X; ++ if (joypad->invert_absx) ++ adc->invert = true; ++ ++ adc->max = (joypad->bt_adc_x_range / 2) - 1; ++ adc->min = -(joypad->bt_adc_x_range / 2); ++ } ++ ++ if (IS_ERR(adc->channel)) { ++ dev_err(dev, "iio channel[%d] get error\n", nbtn); ++ return -EINVAL; ++ } ++ if (!adc->channel->indio_dev) ++ return -ENXIO; ++ ++ if (iio_get_channel_type(adc->channel, &type)) ++ return -EINVAL; ++ ++ if (type != IIO_VOLTAGE) { ++ dev_err(dev, "Incompatible channel %d type %d\n", ++ nbtn, type); ++ return -EINVAL; ++ } ++ } ++ if (nbtn == 0) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static int joypad_gpio_setup(struct device *dev, struct joypad *joypad) ++{ ++ struct device_node *node, *pp; ++ int nbtn; ++ ++ node = dev->of_node; ++ if (!node) ++ return -ENODEV; ++ ++ joypad->gpios = devm_kzalloc(dev, joypad->bt_gpio_count * ++ sizeof(struct bt_gpio), GFP_KERNEL); ++ ++ if (!joypad->gpios) { ++ dev_err(dev, "%s devm_kzmalloc error!", __func__); ++ return -ENOMEM; ++ } ++ ++ nbtn = 0; ++ for_each_child_of_node(node, pp) { ++ enum of_gpio_flags flags; ++ struct bt_gpio *gpio = &joypad->gpios[nbtn++]; ++ int error; ++ ++ gpio->num = of_get_gpio_flags(pp, 0, &flags); ++ if (gpio->num < 0) { ++ error = gpio->num; ++ dev_err(dev, "Failed to get gpio flags, error: %d\n", ++ error); ++ return error; ++ } ++ ++ /* gpio active level(key press level) */ ++ gpio->active_level = (flags & OF_GPIO_ACTIVE_LOW) ? 0 : 1; ++ ++ gpio->label = of_get_property(pp, "label", NULL); ++ ++ if (gpio_is_valid(gpio->num)) { ++ error = devm_gpio_request_one(dev, gpio->num, ++ GPIOF_IN, gpio->label); ++ if (error < 0) { ++ dev_err(dev, ++ "Failed to request GPIO %d, error %d\n", ++ gpio->num, error); ++ return error; ++ } ++ } ++ if (of_property_read_u32(pp, "linux,code", &gpio->linux_code)) { ++ dev_err(dev, "Button without keycode: 0x%x\n", ++ gpio->num); ++ return -EINVAL; ++ } ++ if (of_property_read_u32(pp, "linux,input-type", ++ &gpio->report_type)) ++ gpio->report_type = EV_KEY; ++ } ++ if (nbtn == 0) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++#ifdef VOLUME_ADC_KEYS ++static int joypad_vol_setup(struct device *dev, struct joypad *joypad) ++{ ++ struct device_node *node, *pp; ++ struct adc_keys_button *map; ++ //struct device *adckey_dev; ++ enum iio_chan_type type; ++ int i; ++ int error; ++ ++ node = NULL; ++ node = of_find_matching_node(NULL, adckeys_of_match); ++ ++ if(node) { ++ ++ printk("%s into ...\n", __func__); ++ //adckey_dev = container_of(node, struct device, of_node); ++ joypad->st = devm_kzalloc(dev, sizeof(*joypad->st), GFP_KERNEL); ++ ++ joypad->st->channel = devm_iio_channel_get(dev, "volume-buttons"); ++ if (IS_ERR(joypad->st->channel)) ++ return PTR_ERR(joypad->st->channel); ++ ++ if (!joypad->st->channel->indio_dev) ++ return -ENXIO; ++ ++ error = iio_get_channel_type(joypad->st->channel, &type); ++ if (error < 0) ++ return error; ++ ++ if (type != IIO_VOLTAGE) { ++ dev_err(dev, "Incompatible channel type %d\n", type); ++ return -EINVAL; ++ } ++ ++ if (of_property_read_u32(node, "keyup-threshold-microvolt", ++ &joypad->st->keyup_voltage)) { ++ dev_err(dev, "Invalid or missing keyup voltage\n"); ++ return -EINVAL; ++ } ++ joypad->st->keyup_voltage /= 1000; ++ printk("%s : keyup_voltage = %d\n", __func__, joypad->st->keyup_voltage); ++ ++ joypad->st->num_keys = of_get_child_count(node); ++ if (joypad->st->num_keys == 0) { ++ dev_err(dev, "keymap is missing\n"); ++ return -EINVAL; ++ } ++ printk("%s : adc_keys = %d\n", __func__, joypad->st->num_keys); ++ ++ map = devm_kmalloc_array(dev, joypad->st->num_keys, sizeof(*map), GFP_KERNEL); ++ if (!map) ++ return -ENOMEM; ++ ++ i = 0; ++ for_each_child_of_node(node, pp) { ++ if (of_property_read_u32(pp, "press-threshold-microvolt", &map[i].voltage)) { ++ dev_err(dev, "Key with invalid or missing voltage\n"); ++ return -EINVAL; ++ } ++ map[i].voltage /= 1000; ++ printk("%s : key[%d] voltage = %d\n", __func__, i, map[i].voltage); ++ ++ if (of_property_read_u32(pp, "linux,code", &map[i].keycode)) { ++ dev_err(dev, "Key with invalid or missing linux,code\n"); ++ return -EINVAL; ++ } ++ printk("%s : key[%d] keycode = %d\n", __func__, i, map[i].keycode); ++ ++ i++; ++ } ++ joypad->st->map = map; ++ ++ } ++ if (i == 0) ++ return -EINVAL; ++ ++ printk("%s end ...\n", __func__); ++ return 0; ++} ++#endif ++/*----------------------------------------------------------------------------*/ ++#ifdef VIBRATORS_FF ++static int joypad_vib_setup(struct device *dev, struct joypad *joypad) ++{ ++ struct device_node *node; ++ int ret = 0; ++ ++ node = NULL; ++ node = of_find_matching_node(NULL, vibrators_of_match); ++ ++ if(node) { ++ ++ printk("%s into ... joypad = %p\n", __func__, joypad); ++ joypad->vib = devm_kzalloc(dev, sizeof(*joypad->vib), GFP_KERNEL); ++ ++ joypad->vib->gpio0 = of_get_named_gpio_flags(node, "vibrator0-gpio", 0, NULL); ++ if (!gpio_is_valid(joypad->vib->gpio0)) ++ return -1; ++ ++ printk("%s get vibrator0-gpio = %d \n", __func__, joypad->vib->gpio0); ++ ret = devm_gpio_request(dev, joypad->vib->gpio0, "vibrator0"); ++ if (ret < 0) ++ return ret; ++ ++ joypad->vib->gpio1 = of_get_named_gpio_flags(node, "vibrator1-gpio", 0, NULL); ++ if (!gpio_is_valid(joypad->vib->gpio1)) ++ return -1; ++ ++ printk("%s get vibrator1-gpio = %d \n", __func__, joypad->vib->gpio1); ++ ret = devm_gpio_request(dev, joypad->vib->gpio1, "vibrator1"); ++ if (ret < 0) ++ return ret; ++ ++ INIT_WORK(&joypad->vib->work, vib_work_handler); ++ ++ } ++ ++ printk("%s end ...\n", __func__); ++ return 0; ++} ++ ++/** ++ * gpio_vib_play_effect - function to handle vib effects. ++ * @dev: input device pointer ++ * @data: data of effect ++ * @effect: effect to play ++ * ++ * Currently this driver supports only rumble effects. ++ */ ++static int gpio_vib_play_effect(struct input_dev *dev, void *data, ++ struct ff_effect *effect) ++{ ++ __u16 strong; ++ __u16 weak; ++ //struct joypad *joypad = input_get_drvdata(dev); ++ struct joypad *joypad = data; ++ ++ printk("%s joypad gpio key count = %d\n", __func__, joypad->bt_gpio_count); ++ printk("%s joypad = %p, get vibrator0-gpio = %d \n", __func__, joypad, joypad->vib->gpio0); ++ strong = effect->u.rumble.strong_magnitude; ++ weak = effect->u.rumble.weak_magnitude; ++ ++ printk("%s strong = 0x%x, weak = 0x%x\n", __func__, strong, weak); ++ #if 1 ++ if ((strong > 1) && ((weak == 0) || (weak == 1))) { ++ joypad->vib->speed = effect->u.rumble.strong_magnitude >> 8; ++ joypad->vib->index = weak; ++ joypad->vib->last_index = joypad->vib->index; ++ } ++ else if ((strong == 0) && ((weak == 0) || (weak == 1))) { ++ joypad->vib->speed = 0; ++ } ++ else if ((weak > 0) && ((strong == 0) || (strong == 1))) { ++ joypad->vib->speed = effect->u.rumble.weak_magnitude >> 8; ++ joypad->vib->index = strong; ++ joypad->vib->last_index = joypad->vib->index; ++ } ++ else if ((weak > 0) && ((strong == 0) || (strong == 1))) { ++ joypad->vib->speed = 0; ++ } ++ ++ printk("%s speed = %d, index = %d\n", __func__, joypad->vib->speed, joypad->vib->index); ++ schedule_work(&joypad->vib->work); ++ #endif ++ return 0; ++} ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++static int joypad_input_setup(struct device *dev, struct joypad *joypad) ++{ ++ struct input_polled_dev *poll_dev; ++ struct input_dev *input; ++ int nbtn, error; ++ ++ poll_dev = devm_input_allocate_polled_device(dev); ++ if (!poll_dev) { ++ dev_err(dev, "no memory for polled device\n"); ++ return -ENOMEM; ++ } ++ ++ poll_dev->private = joypad; ++ poll_dev->poll = joypad_poll; ++ poll_dev->poll_interval = joypad->poll_interval; ++ poll_dev->open = joypad_open; ++ poll_dev->close = joypad_close; ++ ++ input = poll_dev->input; ++ #ifdef RIGHT_ADC_JOYSTICK ++ global_input = poll_dev->input; ++ #endif ++ input->name = DRV_NAME; ++ input->phys = DRV_NAME"/input0"; ++ ++ input->id.bustype = BUS_HOST; ++ input->id.vendor = 0x0003; ++ input->id.product = 0x0003; ++ input->id.version = 0x0302; ++ ++ /* IIO ADC key setup (0 mv ~ 1800 mv) * adc->scale */ ++ __set_bit(EV_ABS, input->evbit); ++ for(nbtn = 0; nbtn < joypad->bt_adc_count; nbtn++) { ++ struct bt_adc *adc = &joypad->adcs[nbtn]; ++ input_set_abs_params(input, adc->report_type, ++ adc->min, adc->max, ++ joypad->bt_adc_fuzz, ++ joypad->bt_adc_flat); ++ dev_info(dev, ++ "%s : SCALE = %d, ABS min = %d, max = %d," ++ " fuzz = %d, flat = %d, deadzone = %d\n", ++ __func__, adc->scale, adc->min, adc->max, ++ joypad->bt_adc_fuzz, joypad->bt_adc_flat, ++ joypad->bt_adc_deadzone); ++ } ++ #ifdef RIGHT_ADC_JOYSTICK ++ /* Right Analog */ ++ input_set_abs_params(input, ABS_RX, -900, 899, 32, 32); ++ input_set_abs_params(input, ABS_RY, -900, 899, 32, 32); ++ #endif ++ ++ /* GPIO key setup */ ++ __set_bit(EV_KEY, input->evbit); ++ for(nbtn = 0; nbtn < joypad->bt_gpio_count; nbtn++) { ++ struct bt_gpio *gpio = &joypad->gpios[nbtn]; ++ input_set_capability(input, gpio->report_type, ++ gpio->linux_code); ++ } ++#ifdef VOLUME_ADC_KEYS ++ /* ADC key setup */ ++ for (nbtn = 0; nbtn < joypad->st->num_keys; nbtn++) ++ __set_bit(joypad->st->map[nbtn].keycode, input->keybit); ++#endif ++ if (joypad->auto_repeat) ++ __set_bit(EV_REP, input->evbit); ++#ifdef VIBRATORS_FF ++ /* vibrator for ff */ ++ input_set_capability(input, EV_FF, FF_RUMBLE); ++ error = input_ff_create_memless(input, joypad, gpio_vib_play_effect); ++ if (error) ++ return error; ++#endif ++ joypad->dev = dev; ++ ++ error = input_register_polled_device(poll_dev); ++ if (error) { ++ dev_err(dev, "unable to register polled device, err=%d\n", ++ error); ++ return error; ++ } ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static void joypad_setup_value_check(struct device *dev, struct joypad *joypad) ++{ ++ /* ++ fuzz: specifies fuzz value that is used to filter noise from ++ the event stream. ++ */ ++ if (g_button_adc_fuzz) ++ joypad->bt_adc_fuzz = g_button_adc_fuzz; ++ else ++ device_property_read_u32(dev, "button-adc-fuzz", ++ &joypad->bt_adc_fuzz); ++ /* ++ flat: values that are within this value will be discarded by ++ joydev interface and reported as 0 instead. ++ */ ++ if (g_button_adc_flat) ++ joypad->bt_adc_flat = g_button_adc_flat; ++ else ++ device_property_read_u32(dev, "button-adc-flat", ++ &joypad->bt_adc_flat); ++ ++ /* Joystick report value control */ ++ if (g_button_adc_scale) ++ joypad->bt_adc_scale = g_button_adc_scale; ++ else ++ device_property_read_u32(dev, "button-adc-scale", ++ &joypad->bt_adc_scale); ++ ++ /* Joystick deadzone value control */ ++ if (g_button_adc_deadzone) ++ joypad->bt_adc_deadzone = g_button_adc_deadzone; ++ else ++ device_property_read_u32(dev, "button-adc-deadzone", ++ &joypad->bt_adc_deadzone); ++ ++ if (g_button_adc_x_range) ++ joypad->bt_adc_x_range = g_button_adc_x_range; ++ else ++ device_property_read_u32(dev, "button-adc-x-range", ++ &joypad->bt_adc_x_range); ++ if (g_button_adc_y_range) ++ joypad->bt_adc_y_range = g_button_adc_y_range; ++ else ++ device_property_read_u32(dev, "button-adc-y-range", ++ &joypad->bt_adc_y_range); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static int joypad_dt_parse(struct device *dev, struct joypad *joypad) ++{ ++ int error = 0; ++ ++ /* initialize value check from boot.ini */ ++ joypad_setup_value_check(dev, joypad); ++ ++ device_property_read_u32(dev, "button-adc-count", ++ &joypad->bt_adc_count); ++ ++ device_property_read_u32(dev, "poll-interval", ++ &joypad->poll_interval); ++ ++ joypad->auto_repeat = device_property_present(dev, "autorepeat"); ++ ++ /* change the report reference point? (ADC MAX - read value) */ ++ joypad->invert_absx = device_property_present(dev, "invert-absx"); ++ joypad->invert_absy = device_property_present(dev, "invert-absy"); ++ dev_info(dev, "%s : invert-absx = %d, inveret-absy = %d\n", ++ __func__, joypad->invert_absx, joypad->invert_absy); ++ ++ joypad->bt_gpio_count = device_get_child_node_count(dev); ++ ++ if ((joypad->bt_adc_count == 0) || (joypad->bt_gpio_count == 0)) { ++ dev_err(dev, "adc key = %d, gpio key = %d error!", ++ joypad->bt_adc_count, joypad->bt_gpio_count); ++ return -EINVAL; ++ } ++ ++ error = joypad_adc_setup(dev, joypad); ++ if (error) ++ return error; ++ ++ error = joypad_gpio_setup(dev, joypad); ++ if (error) ++ return error; ++#ifdef VOLUME_ADC_KEYS ++ error = joypad_vol_setup(dev, joypad); ++ printk("222 %s : error = %d\n", __func__, error); ++ if (error) ++ return error; ++#endif ++#ifdef VIBRATORS_FF ++ error = joypad_vib_setup(dev, joypad); ++ printk("333 %s : error = %d\n", __func__, error); ++ if (error) ++ return error; ++#endif ++ return error; ++} ++ ++#ifdef RIGHT_ADC_JOYSTICK ++static int joypad_misc_open(struct inode *inode, struct file *file) ++{ ++ printk("%s ...\n", __func__); ++ ++ //file->private_data = global_input; ++ nonseekable_open(inode, file); ++ ++ return 0; ++} ++ ++static int joypad_misc_release(struct inode *inode, struct file *file) ++{ ++ //struct input_dev *dev = file->private_data; ++ ++ //input_unregister_device(dev); ++ //kfree(dev); ++ ++ return 0; ++} ++ ++//static ssize_t joypad_inject_events(struct input_dev *dev, const char __user *buffer, size_t count ++static ssize_t joypad_inject_events(const char __user *buffer, size_t count) ++{ ++ struct input_event ev; ++ size_t bytes = 0; ++ ++ if (count != 0 && count < input_event_size()) ++ return -EINVAL; ++ ++ while (bytes + input_event_size() <= count) { ++ /* ++ * Note that even if some events were fetched successfully ++ * we are still going to return EFAULT instead of partial ++ * count to let userspace know that it got it's buffers ++ * all wrong. ++ */ ++ if (input_event_from_user(buffer + bytes, &ev)) ++ return -EFAULT; ++ ++ //input_event(dev, ev.type, ev.code, ev.value); ++ input_event(global_input, ev.type, ev.code, ev.value); ++ bytes += input_event_size(); ++ } ++ ++ return bytes; ++} ++ ++static ssize_t joypad_misc_write(struct file *file, const char __user *buffer, ++ size_t count, loff_t *ppos) ++{ ++ //struct input_dev *dev = file->private_data; ++ int retval; ++ ++ if (count == 0) ++ return 0; ++ ++ retval = mutex_lock_interruptible(&global_input->mutex); ++ if (retval) ++ return retval; ++ ++ //retval = joypad_inject_events(dev, buffer, count); ++ retval = joypad_inject_events(buffer, count); ++ ++ mutex_unlock(&global_input->mutex); ++ ++ return retval; ++} ++ ++static long joypad_misc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ++{ ++ int ret = 0; ++ return ret; ++} ++ ++ ++static const struct file_operations joypad_fops = { ++ .owner = THIS_MODULE, ++ .open = joypad_misc_open, ++ .release = joypad_misc_release, ++ .write = joypad_misc_write, ++ .unlocked_ioctl = joypad_misc_ioctl, ++ .llseek = no_llseek, ++ ++}; ++ ++ ++static struct miscdevice joypad_misc_dev = { ++ .minor = MISC_DYNAMIC_MINOR, ++ .name = "joypad", ++ .fops = &joypad_fops, ++}; ++#endif ++/*----------------------------------------------------------------------------*/ ++static int joypad_probe(struct platform_device *pdev) ++{ ++ struct joypad *joypad; ++ struct device *dev = &pdev->dev; ++ int error; ++ ++ joypad = devm_kzalloc(dev, sizeof(struct joypad), GFP_KERNEL); ++ if (!joypad) { ++ dev_err(dev, "joypad devm_kzmalloc error!"); ++ return -ENOMEM; ++ } ++ ++ /* device tree data parse */ ++ error = joypad_dt_parse(dev, joypad); ++ if (error) { ++ dev_err(dev, "dt parse error!(err = %d)\n", error); ++ return error; ++ } ++ ++ mutex_init(&joypad->lock); ++ platform_set_drvdata(pdev, joypad); ++ ++ error = sysfs_create_group(&pdev->dev.kobj, &joypad_attr_group); ++ if (error) { ++ dev_err(dev, "create sysfs group fail, error: %d\n", ++ error); ++ return error; ++ } ++ ++ /* poll input device setup */ ++ error = joypad_input_setup(dev, joypad); ++ if (error) { ++ dev_err(dev, "input setup failed!(err = %d)\n", error); ++ return error; ++ } ++#ifdef RIGHT_ADC_JOYSTICK ++ error = misc_register(&joypad_misc_dev); ++ if (error < 0) ++ printk("%s :fail to register misc device.\n", __func__); ++#endif ++ dev_info(dev, "%s : probe success\n", __func__); ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static const struct of_device_id joypad_of_match[] = { ++ /*{ .compatible = "odroidgo2-joypad", },*/ ++ { .compatible = "gameforce-gamepad", }, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(of, joypad_of_match); ++ ++/*----------------------------------------------------------------------------*/ ++static struct platform_driver joypad_driver = { ++ .probe = joypad_probe, ++ .driver = { ++ .name = DRV_NAME, ++ .of_match_table = of_match_ptr(joypad_of_match), ++ }, ++}; ++ ++/*----------------------------------------------------------------------------*/ ++static int __init joypad_init(void) ++{ ++ return platform_driver_register(&joypad_driver); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static void __exit joypad_exit(void) ++{ ++ platform_driver_unregister(&joypad_driver); ++} ++ ++/*----------------------------------------------------------------------------*/ ++late_initcall(joypad_init); ++module_exit(joypad_exit); ++ ++/*----------------------------------------------------------------------------*/ ++MODULE_AUTHOR("Hardkernel Co.,LTD"); ++MODULE_DESCRIPTION("Keypad driver(ADC&GPIO) for Gameforce CHI"); ++MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("platform:" DRV_NAME); ++ ++/*----------------------------------------------------------------------------*/ +diff --git a/drivers/input/joystick/odroidgo2-joypad.c b/drivers/input/joystick/odroidgo2-joypad.c +new file mode 100644 +index 000000000000..1382d69eec5e +--- /dev/null ++++ b/drivers/input/joystick/odroidgo2-joypad.c +@@ -0,0 +1,878 @@ ++/* ++ * SARADC joystick & GPIO Button driver for Linux(Hardkernel ODROIDGO2-Advance) ++ */ ++/* ++ * 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 ++ * ++ * Should you need to contact me, the author, you can do so either by ++ * e-mail - mail your message to , or by paper mail: ++ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic ++ */ ++ ++/*----------------------------------------------------------------------------*/ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/*----------------------------------------------------------------------------*/ ++#define DRV_NAME "odroidgo2_joypad" ++ ++/*----------------------------------------------------------------------------*/ ++struct bt_adc { ++ /* IIO ADC Channel */ ++ struct iio_channel *channel; ++ /* report value (mV) */ ++ int old_value; ++ /* report type */ ++ int report_type; ++ /* input device init value (mV) */ ++ int max, min; ++ /* calibrated adc value */ ++ int cal; ++ /* adc scale value */ ++ int scale; ++ /* invert report */ ++ bool invert; ++}; ++ ++struct bt_gpio { ++ /* GPIO Request label */ ++ const char *label; ++ /* GPIO Number */ ++ int num; ++ /* report type */ ++ int report_type; ++ /* report linux code */ ++ int linux_code; ++ /* prev button value */ ++ bool old_value; ++ /* button press level */ ++ bool active_level; ++}; ++ ++struct joypad { ++ struct device *dev; ++ int poll_interval; ++ ++ /* report enable/disable */ ++ bool enable; ++ ++ /* report reference point */ ++ bool invert_absx; ++ bool invert_absy; ++ ++ /* report interval (ms) */ ++ int bt_gpio_count; ++ struct bt_gpio *gpios; ++ /* button auto repeat */ ++ int auto_repeat; ++ ++ /* report threshold (mV) */ ++ int bt_adc_fuzz, bt_adc_flat; ++ int bt_adc_x_range, bt_adc_y_range; ++ /* adc read value scale */ ++ int bt_adc_scale; ++ /* joystick deadzone control */ ++ int bt_adc_deadzone; ++ int bt_adc_count; ++ struct bt_adc *adcs; ++ ++ struct mutex lock; ++}; ++ ++/*----------------------------------------------------------------------------*/ ++// ++// set to the value in the boot.ini file. (if exist) ++// ++/*----------------------------------------------------------------------------*/ ++static unsigned int g_button_adc_x_range = 0; ++static unsigned int g_button_adc_y_range = 0; ++static unsigned int g_button_adc_fuzz = 0; ++static unsigned int g_button_adc_flat = 0; ++static unsigned int g_button_adc_scale = 0; ++static unsigned int g_button_adc_deadzone = 0; ++ ++static int __init button_adcx_range_setup(char *str) ++{ ++ if (!str) ++ return -EINVAL; ++ ++ g_button_adc_x_range = simple_strtoul(str, NULL, 10); ++ ++ return 0; ++} ++__setup("button-adc-x-range=", button_adcx_range_setup); ++ ++static int __init button_adcy_range_setup(char *str) ++{ ++ if (!str) ++ return -EINVAL; ++ ++ g_button_adc_y_range = simple_strtoul(str, NULL, 10); ++ ++ return 0; ++} ++__setup("button-adc-y-range=", button_adcy_range_setup); ++ ++static int button_adc_fuzz(char *str) ++{ ++ if (!str) ++ return -EINVAL; ++ g_button_adc_fuzz = simple_strtoul(str, NULL, 10); ++ return 0; ++} ++__setup("button-adc-fuzz=", button_adc_fuzz); ++ ++static int button_adc_flat(char *str) ++{ ++ if (!str) ++ return -EINVAL; ++ g_button_adc_flat = simple_strtoul(str, NULL, 10); ++ return 0; ++} ++__setup("button-adc-flat=", button_adc_flat); ++ ++static int button_adc_scale(char *str) ++{ ++ if (!str) ++ return -EINVAL; ++ g_button_adc_scale = simple_strtoul(str, NULL, 10); ++ return 0; ++} ++__setup("button-adc-scale=", button_adc_scale); ++ ++static int button_adc_deadzone(char *str) ++{ ++ if (!str) ++ return -EINVAL; ++ g_button_adc_deadzone = simple_strtoul(str, NULL, 10); ++ return 0; ++} ++__setup("button-adc-deadzone=", button_adc_deadzone); ++ ++/*----------------------------------------------------------------------------*/ ++/*----------------------------------------------------------------------------*/ ++static int joypad_adc_read(struct bt_adc *adc) ++{ ++ int value; ++ ++ if (iio_read_channel_processed(adc->channel, &value)) ++ return 0; ++ ++ value *= adc->scale; ++ ++ return (adc->invert ? (adc->max - value) : value); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*----------------------------------------------------------------------------*/ ++/* ++ * ATTRIBUTES: ++ * ++ * /sys/devices/platform/odroidgo2_joypad/poll_interval [rw] ++ */ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_store_poll_interval(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, ++ size_t count) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ mutex_lock(&joypad->lock); ++ joypad->poll_interval = simple_strtoul(buf, NULL, 10); ++ mutex_unlock(&joypad->lock); ++ ++ return count; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_show_poll_interval(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ return sprintf(buf, "%d\n", joypad->poll_interval); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static DEVICE_ATTR(poll_interval, S_IWUSR | S_IRUGO, ++ joypad_show_poll_interval, ++ joypad_store_poll_interval); ++ ++/*----------------------------------------------------------------------------*/ ++/* ++ * ATTRIBUTES: ++ * ++ * /sys/devices/platform/odroidgo2_joypad/adc_fuzz [r] ++ */ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_show_adc_fuzz(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ return sprintf(buf, "%d\n", joypad->bt_adc_fuzz); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static DEVICE_ATTR(adc_fuzz, S_IWUSR | S_IRUGO, ++ joypad_show_adc_fuzz, ++ NULL); ++ ++/*----------------------------------------------------------------------------*/ ++/* ++ * ATTRIBUTES: ++ * ++ * /sys/devices/platform/odroidgo2_joypad/adc_flat [r] ++ */ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_show_adc_flat(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ return sprintf(buf, "%d\n", joypad->bt_adc_flat); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static DEVICE_ATTR(adc_flat, S_IWUSR | S_IRUGO, ++ joypad_show_adc_flat, ++ NULL); ++ ++/*----------------------------------------------------------------------------*/ ++/* ++ * ATTRIBUTES: ++ * ++ * /sys/devices/platform/odroidgo2_joypad/enable [rw] ++ */ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_store_enable(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, ++ size_t count) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ mutex_lock(&joypad->lock); ++ joypad->enable = simple_strtoul(buf, NULL, 10); ++ mutex_unlock(&joypad->lock); ++ ++ return count; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_show_enable(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ return sprintf(buf, "%d\n", joypad->enable); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO, ++ joypad_show_enable, ++ joypad_store_enable); ++ ++/*----------------------------------------------------------------------------*/ ++/* ++ * ATTRIBUTES: ++ * ++ * /sys/devices/platform/odroidgo2_joypad/adc_cal [rw] ++ */ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_store_adc_cal(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, ++ size_t count) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ bool calibration; ++ ++ calibration = simple_strtoul(buf, NULL, 10); ++ ++ if (calibration) { ++ int nbtn; ++ ++ mutex_lock(&joypad->lock); ++ for (nbtn = 0; nbtn < joypad->bt_adc_count; nbtn++) { ++ struct bt_adc *adc = &joypad->adcs[nbtn]; ++ ++ adc->cal = joypad_adc_read(adc); ++ if (!adc->cal) { ++ dev_err(joypad->dev, "%s : saradc channels[%d]!\n", ++ __func__, nbtn); ++ continue; ++ } ++ adc->old_value = adc->cal; ++ } ++ mutex_unlock(&joypad->lock); ++ } ++ return count; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_show_adc_cal(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ int nbtn; ++ ssize_t pos; ++ ++ for (nbtn = 0, pos = 0; nbtn < joypad->bt_adc_count; nbtn++) { ++ struct bt_adc *adc = &joypad->adcs[nbtn]; ++ pos += sprintf(&buf[pos], "adc[%d]->cal = %d ", ++ nbtn, adc->cal); ++ } ++ pos += sprintf(&buf[pos], "\n"); ++ return pos; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static DEVICE_ATTR(adc_cal, S_IWUSR | S_IRUGO, ++ joypad_show_adc_cal, ++ joypad_store_adc_cal); ++ ++/*----------------------------------------------------------------------------*/ ++/*----------------------------------------------------------------------------*/ ++static struct attribute *joypad_attrs[] = { ++ &dev_attr_poll_interval.attr, ++ &dev_attr_adc_fuzz.attr, ++ &dev_attr_adc_flat.attr, ++ &dev_attr_enable.attr, ++ &dev_attr_adc_cal.attr, ++ NULL, ++}; ++ ++static struct attribute_group joypad_attr_group = { ++ .attrs = joypad_attrs, ++}; ++ ++/*----------------------------------------------------------------------------*/ ++/*----------------------------------------------------------------------------*/ ++static void joypad_gpio_check(struct input_polled_dev *poll_dev) ++{ ++ struct joypad *joypad = poll_dev->private; ++ int nbtn, value; ++ ++ for (nbtn = 0; nbtn < joypad->bt_gpio_count; nbtn++) { ++ struct bt_gpio *gpio = &joypad->gpios[nbtn]; ++ ++ if (gpio_get_value_cansleep(gpio->num) < 0) { ++ dev_err(joypad->dev, "failed to get gpio state\n"); ++ continue; ++ } ++ value = gpio_get_value(gpio->num); ++ if (value != gpio->old_value) { ++ input_event(poll_dev->input, ++ gpio->report_type, ++ gpio->linux_code, ++ (value == gpio->active_level) ? 1 : 0); ++ gpio->old_value = value; ++ } ++ } ++ input_sync(poll_dev->input); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static void joypad_adc_check(struct input_polled_dev *poll_dev) ++{ ++ struct joypad *joypad = poll_dev->private; ++ int nbtn, value; ++ ++ for (nbtn = 0; nbtn < joypad->bt_adc_count; nbtn++) { ++ struct bt_adc *adc = &joypad->adcs[nbtn]; ++ ++ value = joypad_adc_read(adc); ++ if (!value) { ++ dev_err(joypad->dev, "%s : saradc channels[%d]!\n", ++ __func__, nbtn); ++ continue; ++ } ++ ++ /* Joystick Deadzone check */ ++ if (joypad->bt_adc_deadzone) { ++ if ((value < adc->cal + joypad->bt_adc_deadzone) && ++ (value > adc->cal - joypad->bt_adc_deadzone)) ++ value = adc->cal; ++ } ++ value = value - adc->cal; ++ value = value > adc->max ? adc->max : value; ++ value = value < adc->min ? adc->min : value; ++ ++ if (nbtn == 0) ++ { ++ // adc-x value is default inverted(h/w) ++ input_report_abs(poll_dev->input, ++ adc->report_type, value * (-1)); ++ } ++ else ++ { ++ input_report_abs(poll_dev->input, ++ adc->report_type, value); ++ } ++ adc->old_value = value; ++ } ++ input_sync(poll_dev->input); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static void joypad_poll(struct input_polled_dev *poll_dev) ++{ ++ struct joypad *joypad = poll_dev->private; ++ ++ if (joypad->enable) { ++ joypad_adc_check(poll_dev); ++ joypad_gpio_check(poll_dev); ++ } ++ if (poll_dev->poll_interval != joypad->poll_interval) { ++ mutex_lock(&joypad->lock); ++ poll_dev->poll_interval = joypad->poll_interval; ++ mutex_unlock(&joypad->lock); ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++static void joypad_open(struct input_polled_dev *poll_dev) ++{ ++ struct joypad *joypad = poll_dev->private; ++ int nbtn; ++ ++ for (nbtn = 0; nbtn < joypad->bt_gpio_count; nbtn++) { ++ struct bt_gpio *gpio = &joypad->gpios[nbtn]; ++ gpio->old_value = gpio->active_level ? 0 : 1; ++ } ++ for (nbtn = 0; nbtn < joypad->bt_adc_count; nbtn++) { ++ struct bt_adc *adc = &joypad->adcs[nbtn]; ++ ++ adc->old_value = joypad_adc_read(adc); ++ if (!adc->old_value) { ++ dev_err(joypad->dev, "%s : saradc channels[%d]!\n", ++ __func__, nbtn); ++ continue; ++ } ++ adc->cal = adc->old_value; ++ dev_info(joypad->dev, "%s : adc[%d] adc->cal = %d\n", ++ __func__, nbtn, adc->cal); ++ } ++ /* buttons status sync */ ++ joypad_adc_check(poll_dev); ++ joypad_gpio_check(poll_dev); ++ ++ /* button report enable */ ++ mutex_lock(&joypad->lock); ++ joypad->enable = true; ++ mutex_unlock(&joypad->lock); ++ ++ dev_info(joypad->dev, "%s : opened\n", __func__); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static void joypad_close(struct input_polled_dev *poll_dev) ++{ ++ struct joypad *joypad = poll_dev->private; ++ ++ /* button report disable */ ++ mutex_lock(&joypad->lock); ++ joypad->enable = false; ++ mutex_unlock(&joypad->lock); ++ ++ dev_info(joypad->dev, "%s : closed\n", __func__); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static int joypad_adc_setup(struct device *dev, struct joypad *joypad) ++{ ++ int nbtn = 0; ++ ++ joypad->adcs = devm_kzalloc(dev, joypad->bt_adc_count * ++ sizeof(struct bt_adc), GFP_KERNEL); ++ ++ if (!joypad->adcs) { ++ dev_err(dev, "%s devm_kzmalloc error!", __func__); ++ return -ENOMEM; ++ } ++ ++ for (nbtn = 0; nbtn < joypad->bt_adc_count; nbtn++) { ++ struct bt_adc *adc = &joypad->adcs[nbtn]; ++ enum iio_chan_type type; ++ ++ adc->scale = joypad->bt_adc_scale; ++ if (nbtn) { ++ adc->channel = ++ devm_iio_channel_get(dev, "joy_y"); ++ adc->report_type = ABS_Y; ++ if (joypad->invert_absy) ++ adc->invert = true; ++ ++ adc->max = (joypad->bt_adc_y_range / 2) - 1; ++ adc->min = -(joypad->bt_adc_y_range / 2); ++ } ++ else { ++ adc->channel = ++ devm_iio_channel_get(dev, "joy_x"); ++ adc->report_type = ABS_X; ++ if (joypad->invert_absx) ++ adc->invert = true; ++ ++ adc->max = (joypad->bt_adc_x_range / 2) - 1; ++ adc->min = -(joypad->bt_adc_x_range / 2); ++ } ++ ++ if (IS_ERR(adc->channel)) { ++ dev_err(dev, "iio channel[%d] get error\n", nbtn); ++ return -EINVAL; ++ } ++ if (!adc->channel->indio_dev) ++ return -ENXIO; ++ ++ if (iio_get_channel_type(adc->channel, &type)) ++ return -EINVAL; ++ ++ if (type != IIO_VOLTAGE) { ++ dev_err(dev, "Incompatible channel %d type %d\n", ++ nbtn, type); ++ return -EINVAL; ++ } ++ } ++ if (nbtn == 0) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static int joypad_gpio_setup(struct device *dev, struct joypad *joypad) ++{ ++ struct device_node *node, *pp; ++ int nbtn; ++ ++ node = dev->of_node; ++ if (!node) ++ return -ENODEV; ++ ++ joypad->gpios = devm_kzalloc(dev, joypad->bt_gpio_count * ++ sizeof(struct bt_gpio), GFP_KERNEL); ++ ++ if (!joypad->gpios) { ++ dev_err(dev, "%s devm_kzmalloc error!", __func__); ++ return -ENOMEM; ++ } ++ ++ nbtn = 0; ++ for_each_child_of_node(node, pp) { ++ enum of_gpio_flags flags; ++ struct bt_gpio *gpio = &joypad->gpios[nbtn++]; ++ int error; ++ ++ gpio->num = of_get_gpio_flags(pp, 0, &flags); ++ if (gpio->num < 0) { ++ error = gpio->num; ++ dev_err(dev, "Failed to get gpio flags, error: %d\n", ++ error); ++ return error; ++ } ++ ++ /* gpio active level(key press level) */ ++ gpio->active_level = (flags & OF_GPIO_ACTIVE_LOW) ? 0 : 1; ++ ++ gpio->label = of_get_property(pp, "label", NULL); ++ ++ if (gpio_is_valid(gpio->num)) { ++ error = devm_gpio_request_one(dev, gpio->num, ++ GPIOF_IN, gpio->label); ++ if (error < 0) { ++ dev_err(dev, ++ "Failed to request GPIO %d, error %d\n", ++ gpio->num, error); ++ return error; ++ } ++ } ++ if (of_property_read_u32(pp, "linux,code", &gpio->linux_code)) { ++ dev_err(dev, "Button without keycode: 0x%x\n", ++ gpio->num); ++ return -EINVAL; ++ } ++ if (of_property_read_u32(pp, "linux,input-type", ++ &gpio->report_type)) ++ gpio->report_type = EV_KEY; ++ } ++ if (nbtn == 0) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static int joypad_input_setup(struct device *dev, struct joypad *joypad) ++{ ++ struct input_polled_dev *poll_dev; ++ struct input_dev *input; ++ int nbtn, error; ++ ++ poll_dev = devm_input_allocate_polled_device(dev); ++ if (!poll_dev) { ++ dev_err(dev, "no memory for polled device\n"); ++ return -ENOMEM; ++ } ++ ++ poll_dev->private = joypad; ++ poll_dev->poll = joypad_poll; ++ poll_dev->poll_interval = joypad->poll_interval; ++ poll_dev->open = joypad_open; ++ poll_dev->close = joypad_close; ++ ++ input = poll_dev->input; ++ ++ input->name = DRV_NAME; ++ input->phys = DRV_NAME"/input0"; ++ ++ input->id.bustype = BUS_HOST; ++ input->id.vendor = 0x0001; ++ input->id.product = 0x0001; ++ input->id.version = 0x0101; ++ ++ /* IIO ADC key setup (0 mv ~ 1800 mv) * adc->scale */ ++ __set_bit(EV_ABS, input->evbit); ++ for(nbtn = 0; nbtn < joypad->bt_adc_count; nbtn++) { ++ struct bt_adc *adc = &joypad->adcs[nbtn]; ++ input_set_abs_params(input, adc->report_type, ++ adc->min, adc->max, ++ joypad->bt_adc_fuzz, ++ joypad->bt_adc_flat); ++ dev_info(dev, ++ "%s : SCALE = %d, ABS min = %d, max = %d," ++ " fuzz = %d, flat = %d, deadzone = %d\n", ++ __func__, adc->scale, adc->min, adc->max, ++ joypad->bt_adc_fuzz, joypad->bt_adc_flat, ++ joypad->bt_adc_deadzone); ++ } ++ ++ /* GPIO key setup */ ++ __set_bit(EV_KEY, input->evbit); ++ for(nbtn = 0; nbtn < joypad->bt_gpio_count; nbtn++) { ++ struct bt_gpio *gpio = &joypad->gpios[nbtn]; ++ input_set_capability(input, gpio->report_type, ++ gpio->linux_code); ++ } ++ ++ if (joypad->auto_repeat) ++ __set_bit(EV_REP, input->evbit); ++ ++ joypad->dev = dev; ++ ++ error = input_register_polled_device(poll_dev); ++ if (error) { ++ dev_err(dev, "unable to register polled device, err=%d\n", ++ error); ++ return error; ++ } ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static void joypad_setup_value_check(struct device *dev, struct joypad *joypad) ++{ ++ /* ++ fuzz: specifies fuzz value that is used to filter noise from ++ the event stream. ++ */ ++ if (g_button_adc_fuzz) ++ joypad->bt_adc_fuzz = g_button_adc_fuzz; ++ else ++ device_property_read_u32(dev, "button-adc-fuzz", ++ &joypad->bt_adc_fuzz); ++ /* ++ flat: values that are within this value will be discarded by ++ joydev interface and reported as 0 instead. ++ */ ++ if (g_button_adc_flat) ++ joypad->bt_adc_flat = g_button_adc_flat; ++ else ++ device_property_read_u32(dev, "button-adc-flat", ++ &joypad->bt_adc_flat); ++ ++ /* Joystick report value control */ ++ if (g_button_adc_scale) ++ joypad->bt_adc_scale = g_button_adc_scale; ++ else ++ device_property_read_u32(dev, "button-adc-scale", ++ &joypad->bt_adc_scale); ++ ++ /* Joystick deadzone value control */ ++ if (g_button_adc_deadzone) ++ joypad->bt_adc_deadzone = g_button_adc_deadzone; ++ else ++ device_property_read_u32(dev, "button-adc-deadzone", ++ &joypad->bt_adc_deadzone); ++ ++ if (g_button_adc_x_range) ++ joypad->bt_adc_x_range = g_button_adc_x_range; ++ else ++ device_property_read_u32(dev, "button-adc-x-range", ++ &joypad->bt_adc_x_range); ++ if (g_button_adc_y_range) ++ joypad->bt_adc_y_range = g_button_adc_y_range; ++ else ++ device_property_read_u32(dev, "button-adc-y-range", ++ &joypad->bt_adc_y_range); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static int joypad_dt_parse(struct device *dev, struct joypad *joypad) ++{ ++ int error = 0; ++ ++ /* initialize value check from boot.ini */ ++ joypad_setup_value_check(dev, joypad); ++ ++ device_property_read_u32(dev, "button-adc-count", ++ &joypad->bt_adc_count); ++ ++ device_property_read_u32(dev, "poll-interval", ++ &joypad->poll_interval); ++ ++ joypad->auto_repeat = device_property_present(dev, "autorepeat"); ++ ++ /* change the report reference point? (ADC MAX - read value) */ ++ joypad->invert_absx = device_property_present(dev, "invert-absx"); ++ joypad->invert_absy = device_property_present(dev, "invert-absy"); ++ dev_info(dev, "%s : invert-absx = %d, inveret-absy = %d\n", ++ __func__, joypad->invert_absx, joypad->invert_absy); ++ ++ joypad->bt_gpio_count = device_get_child_node_count(dev); ++ ++ if ((joypad->bt_adc_count == 0) || (joypad->bt_gpio_count == 0)) { ++ dev_err(dev, "adc key = %d, gpio key = %d error!", ++ joypad->bt_adc_count, joypad->bt_gpio_count); ++ return -EINVAL; ++ } ++ ++ error = joypad_adc_setup(dev, joypad); ++ if (error) ++ return error; ++ ++ error = joypad_gpio_setup(dev, joypad); ++ if (error) ++ return error; ++ ++ return error; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static int joypad_probe(struct platform_device *pdev) ++{ ++ struct joypad *joypad; ++ struct device *dev = &pdev->dev; ++ int error; ++ ++ joypad = devm_kzalloc(dev, sizeof(struct joypad), GFP_KERNEL); ++ if (!joypad) { ++ dev_err(dev, "joypad devm_kzmalloc error!"); ++ return -ENOMEM; ++ } ++ ++ /* device tree data parse */ ++ error = joypad_dt_parse(dev, joypad); ++ if (error) { ++ dev_err(dev, "dt parse error!(err = %d)\n", error); ++ return error; ++ } ++ ++ mutex_init(&joypad->lock); ++ platform_set_drvdata(pdev, joypad); ++ ++ error = sysfs_create_group(&pdev->dev.kobj, &joypad_attr_group); ++ if (error) { ++ dev_err(dev, "create sysfs group fail, error: %d\n", ++ error); ++ return error; ++ } ++ ++ /* poll input device setup */ ++ error = joypad_input_setup(dev, joypad); ++ if (error) { ++ dev_err(dev, "input setup failed!(err = %d)\n", error); ++ return error; ++ } ++ dev_info(dev, "%s : probe success\n", __func__); ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static const struct of_device_id joypad_of_match[] = { ++ { .compatible = "odroidgo2-joypad", }, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(of, joypad_of_match); ++ ++/*----------------------------------------------------------------------------*/ ++static struct platform_driver joypad_driver = { ++ .probe = joypad_probe, ++ .driver = { ++ .name = DRV_NAME, ++ .of_match_table = of_match_ptr(joypad_of_match), ++ }, ++}; ++ ++/*----------------------------------------------------------------------------*/ ++static int __init joypad_init(void) ++{ ++ return platform_driver_register(&joypad_driver); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static void __exit joypad_exit(void) ++{ ++ platform_driver_unregister(&joypad_driver); ++} ++ ++/*----------------------------------------------------------------------------*/ ++late_initcall(joypad_init); ++module_exit(joypad_exit); ++ ++/*----------------------------------------------------------------------------*/ ++MODULE_AUTHOR("Hardkernel Co.,LTD"); ++MODULE_DESCRIPTION("Keypad driver(ADC&GPIO) for ODROIDGO-Advance"); ++MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("platform:" DRV_NAME); ++ ++/*----------------------------------------------------------------------------*/ +diff --git a/drivers/input/joystick/odroidgo2-v11-joypad.c b/drivers/input/joystick/odroidgo2-v11-joypad.c +new file mode 100644 +index 000000000000..b5bd7cb40a9b +--- /dev/null ++++ b/drivers/input/joystick/odroidgo2-v11-joypad.c +@@ -0,0 +1,878 @@ ++/* ++ * SARADC joystick & GPIO Button driver for Linux(Hardkernel ODROIDGO2-Advance) ++ */ ++/* ++ * 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 ++ * ++ * Should you need to contact me, the author, you can do so either by ++ * e-mail - mail your message to , or by paper mail: ++ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic ++ */ ++ ++/*----------------------------------------------------------------------------*/ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/*----------------------------------------------------------------------------*/ ++#define DRV_NAME "odroidgo2_v11_joypad" ++ ++/*----------------------------------------------------------------------------*/ ++struct bt_adc { ++ /* IIO ADC Channel */ ++ struct iio_channel *channel; ++ /* report value (mV) */ ++ int old_value; ++ /* report type */ ++ int report_type; ++ /* input device init value (mV) */ ++ int max, min; ++ /* calibrated adc value */ ++ int cal; ++ /* adc scale value */ ++ int scale; ++ /* invert report */ ++ bool invert; ++}; ++ ++struct bt_gpio { ++ /* GPIO Request label */ ++ const char *label; ++ /* GPIO Number */ ++ int num; ++ /* report type */ ++ int report_type; ++ /* report linux code */ ++ int linux_code; ++ /* prev button value */ ++ bool old_value; ++ /* button press level */ ++ bool active_level; ++}; ++ ++struct joypad { ++ struct device *dev; ++ int poll_interval; ++ ++ /* report enable/disable */ ++ bool enable; ++ ++ /* report reference point */ ++ bool invert_absx; ++ bool invert_absy; ++ ++ /* report interval (ms) */ ++ int bt_gpio_count; ++ struct bt_gpio *gpios; ++ /* button auto repeat */ ++ int auto_repeat; ++ ++ /* report threshold (mV) */ ++ int bt_adc_fuzz, bt_adc_flat; ++ int bt_adc_x_range, bt_adc_y_range; ++ /* adc read value scale */ ++ int bt_adc_scale; ++ /* joystick deadzone control */ ++ int bt_adc_deadzone; ++ int bt_adc_count; ++ struct bt_adc *adcs; ++ ++ struct mutex lock; ++}; ++ ++/*----------------------------------------------------------------------------*/ ++// ++// set to the value in the boot.ini file. (if exist) ++// ++/*----------------------------------------------------------------------------*/ ++static unsigned int g_button_adc_x_range = 0; ++static unsigned int g_button_adc_y_range = 0; ++static unsigned int g_button_adc_fuzz = 0; ++static unsigned int g_button_adc_flat = 0; ++static unsigned int g_button_adc_scale = 0; ++static unsigned int g_button_adc_deadzone = 0; ++ ++static int __init button_adcx_range_setup(char *str) ++{ ++ if (!str) ++ return -EINVAL; ++ ++ g_button_adc_x_range = simple_strtoul(str, NULL, 10); ++ ++ return 0; ++} ++__setup("button-adc-x-range=", button_adcx_range_setup); ++ ++static int __init button_adcy_range_setup(char *str) ++{ ++ if (!str) ++ return -EINVAL; ++ ++ g_button_adc_y_range = simple_strtoul(str, NULL, 10); ++ ++ return 0; ++} ++__setup("button-adc-y-range=", button_adcy_range_setup); ++ ++static int button_adc_fuzz(char *str) ++{ ++ if (!str) ++ return -EINVAL; ++ g_button_adc_fuzz = simple_strtoul(str, NULL, 10); ++ return 0; ++} ++__setup("button-adc-fuzz=", button_adc_fuzz); ++ ++static int button_adc_flat(char *str) ++{ ++ if (!str) ++ return -EINVAL; ++ g_button_adc_flat = simple_strtoul(str, NULL, 10); ++ return 0; ++} ++__setup("button-adc-flat=", button_adc_flat); ++ ++static int button_adc_scale(char *str) ++{ ++ if (!str) ++ return -EINVAL; ++ g_button_adc_scale = simple_strtoul(str, NULL, 10); ++ return 0; ++} ++__setup("button-adc-scale=", button_adc_scale); ++ ++static int button_adc_deadzone(char *str) ++{ ++ if (!str) ++ return -EINVAL; ++ g_button_adc_deadzone = simple_strtoul(str, NULL, 10); ++ return 0; ++} ++__setup("button-adc-deadzone=", button_adc_deadzone); ++ ++/*----------------------------------------------------------------------------*/ ++/*----------------------------------------------------------------------------*/ ++static int joypad_adc_read(struct bt_adc *adc) ++{ ++ int value; ++ ++ if (iio_read_channel_processed(adc->channel, &value)) ++ return 0; ++ ++ value *= adc->scale; ++ ++ return (adc->invert ? (adc->max - value) : value); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*----------------------------------------------------------------------------*/ ++/* ++ * ATTRIBUTES: ++ * ++ * /sys/devices/platform/odroidgo2_joypad/poll_interval [rw] ++ */ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_store_poll_interval(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, ++ size_t count) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ mutex_lock(&joypad->lock); ++ joypad->poll_interval = simple_strtoul(buf, NULL, 10); ++ mutex_unlock(&joypad->lock); ++ ++ return count; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_show_poll_interval(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ return sprintf(buf, "%d\n", joypad->poll_interval); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static DEVICE_ATTR(poll_interval, S_IWUSR | S_IRUGO, ++ joypad_show_poll_interval, ++ joypad_store_poll_interval); ++ ++/*----------------------------------------------------------------------------*/ ++/* ++ * ATTRIBUTES: ++ * ++ * /sys/devices/platform/odroidgo2_joypad/adc_fuzz [r] ++ */ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_show_adc_fuzz(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ return sprintf(buf, "%d\n", joypad->bt_adc_fuzz); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static DEVICE_ATTR(adc_fuzz, S_IWUSR | S_IRUGO, ++ joypad_show_adc_fuzz, ++ NULL); ++ ++/*----------------------------------------------------------------------------*/ ++/* ++ * ATTRIBUTES: ++ * ++ * /sys/devices/platform/odroidgo2_joypad/adc_flat [r] ++ */ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_show_adc_flat(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ return sprintf(buf, "%d\n", joypad->bt_adc_flat); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static DEVICE_ATTR(adc_flat, S_IWUSR | S_IRUGO, ++ joypad_show_adc_flat, ++ NULL); ++ ++/*----------------------------------------------------------------------------*/ ++/* ++ * ATTRIBUTES: ++ * ++ * /sys/devices/platform/odroidgo2_joypad/enable [rw] ++ */ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_store_enable(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, ++ size_t count) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ mutex_lock(&joypad->lock); ++ joypad->enable = simple_strtoul(buf, NULL, 10); ++ mutex_unlock(&joypad->lock); ++ ++ return count; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_show_enable(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ return sprintf(buf, "%d\n", joypad->enable); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO, ++ joypad_show_enable, ++ joypad_store_enable); ++ ++/*----------------------------------------------------------------------------*/ ++/* ++ * ATTRIBUTES: ++ * ++ * /sys/devices/platform/odroidgo2_joypad/adc_cal [rw] ++ */ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_store_adc_cal(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, ++ size_t count) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ bool calibration; ++ ++ calibration = simple_strtoul(buf, NULL, 10); ++ ++ if (calibration) { ++ int nbtn; ++ ++ mutex_lock(&joypad->lock); ++ for (nbtn = 0; nbtn < joypad->bt_adc_count; nbtn++) { ++ struct bt_adc *adc = &joypad->adcs[nbtn]; ++ ++ adc->cal = joypad_adc_read(adc); ++ if (!adc->cal) { ++ dev_err(joypad->dev, "%s : saradc channels[%d]!\n", ++ __func__, nbtn); ++ continue; ++ } ++ adc->old_value = adc->cal; ++ } ++ mutex_unlock(&joypad->lock); ++ } ++ return count; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_show_adc_cal(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ int nbtn; ++ ssize_t pos; ++ ++ for (nbtn = 0, pos = 0; nbtn < joypad->bt_adc_count; nbtn++) { ++ struct bt_adc *adc = &joypad->adcs[nbtn]; ++ pos += sprintf(&buf[pos], "adc[%d]->cal = %d ", ++ nbtn, adc->cal); ++ } ++ pos += sprintf(&buf[pos], "\n"); ++ return pos; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static DEVICE_ATTR(adc_cal, S_IWUSR | S_IRUGO, ++ joypad_show_adc_cal, ++ joypad_store_adc_cal); ++ ++/*----------------------------------------------------------------------------*/ ++/*----------------------------------------------------------------------------*/ ++static struct attribute *joypad_attrs[] = { ++ &dev_attr_poll_interval.attr, ++ &dev_attr_adc_fuzz.attr, ++ &dev_attr_adc_flat.attr, ++ &dev_attr_enable.attr, ++ &dev_attr_adc_cal.attr, ++ NULL, ++}; ++ ++static struct attribute_group joypad_attr_group = { ++ .attrs = joypad_attrs, ++}; ++ ++/*----------------------------------------------------------------------------*/ ++/*----------------------------------------------------------------------------*/ ++static void joypad_gpio_check(struct input_polled_dev *poll_dev) ++{ ++ struct joypad *joypad = poll_dev->private; ++ int nbtn, value; ++ ++ for (nbtn = 0; nbtn < joypad->bt_gpio_count; nbtn++) { ++ struct bt_gpio *gpio = &joypad->gpios[nbtn]; ++ ++ if (gpio_get_value_cansleep(gpio->num) < 0) { ++ dev_err(joypad->dev, "failed to get gpio state\n"); ++ continue; ++ } ++ value = gpio_get_value(gpio->num); ++ if (value != gpio->old_value) { ++ input_event(poll_dev->input, ++ gpio->report_type, ++ gpio->linux_code, ++ (value == gpio->active_level) ? 1 : 0); ++ gpio->old_value = value; ++ } ++ } ++ input_sync(poll_dev->input); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static void joypad_adc_check(struct input_polled_dev *poll_dev) ++{ ++ struct joypad *joypad = poll_dev->private; ++ int nbtn, value; ++ ++ for (nbtn = 0; nbtn < joypad->bt_adc_count; nbtn++) { ++ struct bt_adc *adc = &joypad->adcs[nbtn]; ++ ++ value = joypad_adc_read(adc); ++ if (!value) { ++ dev_err(joypad->dev, "%s : saradc channels[%d]!\n", ++ __func__, nbtn); ++ continue; ++ } ++ ++ /* Joystick Deadzone check */ ++ if (joypad->bt_adc_deadzone) { ++ if ((value < adc->cal + joypad->bt_adc_deadzone) && ++ (value > adc->cal - joypad->bt_adc_deadzone)) ++ value = adc->cal; ++ } ++ value = value - adc->cal; ++ value = value > adc->max ? adc->max : value; ++ value = value < adc->min ? adc->min : value; ++ ++ if (nbtn == 0) ++ { ++ // adc-x value is default inverted(h/w) ++ input_report_abs(poll_dev->input, ++ adc->report_type, value * (-1)); ++ } ++ else ++ { ++ input_report_abs(poll_dev->input, ++ adc->report_type, value); ++ } ++ adc->old_value = value; ++ } ++ input_sync(poll_dev->input); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static void joypad_poll(struct input_polled_dev *poll_dev) ++{ ++ struct joypad *joypad = poll_dev->private; ++ ++ if (joypad->enable) { ++ joypad_adc_check(poll_dev); ++ joypad_gpio_check(poll_dev); ++ } ++ if (poll_dev->poll_interval != joypad->poll_interval) { ++ mutex_lock(&joypad->lock); ++ poll_dev->poll_interval = joypad->poll_interval; ++ mutex_unlock(&joypad->lock); ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++static void joypad_open(struct input_polled_dev *poll_dev) ++{ ++ struct joypad *joypad = poll_dev->private; ++ int nbtn; ++ ++ for (nbtn = 0; nbtn < joypad->bt_gpio_count; nbtn++) { ++ struct bt_gpio *gpio = &joypad->gpios[nbtn]; ++ gpio->old_value = gpio->active_level ? 0 : 1; ++ } ++ for (nbtn = 0; nbtn < joypad->bt_adc_count; nbtn++) { ++ struct bt_adc *adc = &joypad->adcs[nbtn]; ++ ++ adc->old_value = joypad_adc_read(adc); ++ if (!adc->old_value) { ++ dev_err(joypad->dev, "%s : saradc channels[%d]!\n", ++ __func__, nbtn); ++ continue; ++ } ++ adc->cal = adc->old_value; ++ dev_info(joypad->dev, "%s : adc[%d] adc->cal = %d\n", ++ __func__, nbtn, adc->cal); ++ } ++ /* buttons status sync */ ++ joypad_adc_check(poll_dev); ++ joypad_gpio_check(poll_dev); ++ ++ /* button report enable */ ++ mutex_lock(&joypad->lock); ++ joypad->enable = true; ++ mutex_unlock(&joypad->lock); ++ ++ dev_info(joypad->dev, "%s : opened\n", __func__); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static void joypad_close(struct input_polled_dev *poll_dev) ++{ ++ struct joypad *joypad = poll_dev->private; ++ ++ /* button report disable */ ++ mutex_lock(&joypad->lock); ++ joypad->enable = false; ++ mutex_unlock(&joypad->lock); ++ ++ dev_info(joypad->dev, "%s : closed\n", __func__); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static int joypad_adc_setup(struct device *dev, struct joypad *joypad) ++{ ++ int nbtn = 0; ++ ++ joypad->adcs = devm_kzalloc(dev, joypad->bt_adc_count * ++ sizeof(struct bt_adc), GFP_KERNEL); ++ ++ if (!joypad->adcs) { ++ dev_err(dev, "%s devm_kzmalloc error!", __func__); ++ return -ENOMEM; ++ } ++ ++ for (nbtn = 0; nbtn < joypad->bt_adc_count; nbtn++) { ++ struct bt_adc *adc = &joypad->adcs[nbtn]; ++ enum iio_chan_type type; ++ ++ adc->scale = joypad->bt_adc_scale; ++ if (nbtn) { ++ adc->channel = ++ devm_iio_channel_get(dev, "joy_y"); ++ adc->report_type = ABS_Y; ++ if (joypad->invert_absy) ++ adc->invert = true; ++ ++ adc->max = (joypad->bt_adc_y_range / 2) - 1; ++ adc->min = -(joypad->bt_adc_y_range / 2); ++ } ++ else { ++ adc->channel = ++ devm_iio_channel_get(dev, "joy_x"); ++ adc->report_type = ABS_X; ++ if (joypad->invert_absx) ++ adc->invert = true; ++ ++ adc->max = (joypad->bt_adc_x_range / 2) - 1; ++ adc->min = -(joypad->bt_adc_x_range / 2); ++ } ++ ++ if (IS_ERR(adc->channel)) { ++ dev_err(dev, "iio channel[%d] get error\n", nbtn); ++ return -EINVAL; ++ } ++ if (!adc->channel->indio_dev) ++ return -ENXIO; ++ ++ if (iio_get_channel_type(adc->channel, &type)) ++ return -EINVAL; ++ ++ if (type != IIO_VOLTAGE) { ++ dev_err(dev, "Incompatible channel %d type %d\n", ++ nbtn, type); ++ return -EINVAL; ++ } ++ } ++ if (nbtn == 0) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static int joypad_gpio_setup(struct device *dev, struct joypad *joypad) ++{ ++ struct device_node *node, *pp; ++ int nbtn; ++ ++ node = dev->of_node; ++ if (!node) ++ return -ENODEV; ++ ++ joypad->gpios = devm_kzalloc(dev, joypad->bt_gpio_count * ++ sizeof(struct bt_gpio), GFP_KERNEL); ++ ++ if (!joypad->gpios) { ++ dev_err(dev, "%s devm_kzmalloc error!", __func__); ++ return -ENOMEM; ++ } ++ ++ nbtn = 0; ++ for_each_child_of_node(node, pp) { ++ enum of_gpio_flags flags; ++ struct bt_gpio *gpio = &joypad->gpios[nbtn++]; ++ int error; ++ ++ gpio->num = of_get_gpio_flags(pp, 0, &flags); ++ if (gpio->num < 0) { ++ error = gpio->num; ++ dev_err(dev, "Failed to get gpio flags, error: %d\n", ++ error); ++ return error; ++ } ++ ++ /* gpio active level(key press level) */ ++ gpio->active_level = (flags & OF_GPIO_ACTIVE_LOW) ? 0 : 1; ++ ++ gpio->label = of_get_property(pp, "label", NULL); ++ ++ if (gpio_is_valid(gpio->num)) { ++ error = devm_gpio_request_one(dev, gpio->num, ++ GPIOF_IN, gpio->label); ++ if (error < 0) { ++ dev_err(dev, ++ "Failed to request GPIO %d, error %d\n", ++ gpio->num, error); ++ return error; ++ } ++ } ++ if (of_property_read_u32(pp, "linux,code", &gpio->linux_code)) { ++ dev_err(dev, "Button without keycode: 0x%x\n", ++ gpio->num); ++ return -EINVAL; ++ } ++ if (of_property_read_u32(pp, "linux,input-type", ++ &gpio->report_type)) ++ gpio->report_type = EV_KEY; ++ } ++ if (nbtn == 0) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static int joypad_input_setup(struct device *dev, struct joypad *joypad) ++{ ++ struct input_polled_dev *poll_dev; ++ struct input_dev *input; ++ int nbtn, error; ++ ++ poll_dev = devm_input_allocate_polled_device(dev); ++ if (!poll_dev) { ++ dev_err(dev, "no memory for polled device\n"); ++ return -ENOMEM; ++ } ++ ++ poll_dev->private = joypad; ++ poll_dev->poll = joypad_poll; ++ poll_dev->poll_interval = joypad->poll_interval; ++ poll_dev->open = joypad_open; ++ poll_dev->close = joypad_close; ++ ++ input = poll_dev->input; ++ ++ input->name = DRV_NAME; ++ input->phys = DRV_NAME"/input0"; ++ ++ input->id.bustype = BUS_HOST; ++ input->id.vendor = 0x0001; ++ input->id.product = 0x0002; ++ input->id.version = 0x0101; ++ ++ /* IIO ADC key setup (0 mv ~ 1800 mv) * adc->scale */ ++ __set_bit(EV_ABS, input->evbit); ++ for(nbtn = 0; nbtn < joypad->bt_adc_count; nbtn++) { ++ struct bt_adc *adc = &joypad->adcs[nbtn]; ++ input_set_abs_params(input, adc->report_type, ++ adc->min, adc->max, ++ joypad->bt_adc_fuzz, ++ joypad->bt_adc_flat); ++ dev_info(dev, ++ "%s : SCALE = %d, ABS min = %d, max = %d," ++ " fuzz = %d, flat = %d, deadzone = %d\n", ++ __func__, adc->scale, adc->min, adc->max, ++ joypad->bt_adc_fuzz, joypad->bt_adc_flat, ++ joypad->bt_adc_deadzone); ++ } ++ ++ /* GPIO key setup */ ++ __set_bit(EV_KEY, input->evbit); ++ for(nbtn = 0; nbtn < joypad->bt_gpio_count; nbtn++) { ++ struct bt_gpio *gpio = &joypad->gpios[nbtn]; ++ input_set_capability(input, gpio->report_type, ++ gpio->linux_code); ++ } ++ ++ if (joypad->auto_repeat) ++ __set_bit(EV_REP, input->evbit); ++ ++ joypad->dev = dev; ++ ++ error = input_register_polled_device(poll_dev); ++ if (error) { ++ dev_err(dev, "unable to register polled device, err=%d\n", ++ error); ++ return error; ++ } ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static void joypad_setup_value_check(struct device *dev, struct joypad *joypad) ++{ ++ /* ++ fuzz: specifies fuzz value that is used to filter noise from ++ the event stream. ++ */ ++ if (g_button_adc_fuzz) ++ joypad->bt_adc_fuzz = g_button_adc_fuzz; ++ else ++ device_property_read_u32(dev, "button-adc-fuzz", ++ &joypad->bt_adc_fuzz); ++ /* ++ flat: values that are within this value will be discarded by ++ joydev interface and reported as 0 instead. ++ */ ++ if (g_button_adc_flat) ++ joypad->bt_adc_flat = g_button_adc_flat; ++ else ++ device_property_read_u32(dev, "button-adc-flat", ++ &joypad->bt_adc_flat); ++ ++ /* Joystick report value control */ ++ if (g_button_adc_scale) ++ joypad->bt_adc_scale = g_button_adc_scale; ++ else ++ device_property_read_u32(dev, "button-adc-scale", ++ &joypad->bt_adc_scale); ++ ++ /* Joystick deadzone value control */ ++ if (g_button_adc_deadzone) ++ joypad->bt_adc_deadzone = g_button_adc_deadzone; ++ else ++ device_property_read_u32(dev, "button-adc-deadzone", ++ &joypad->bt_adc_deadzone); ++ ++ if (g_button_adc_x_range) ++ joypad->bt_adc_x_range = g_button_adc_x_range; ++ else ++ device_property_read_u32(dev, "button-adc-x-range", ++ &joypad->bt_adc_x_range); ++ if (g_button_adc_y_range) ++ joypad->bt_adc_y_range = g_button_adc_y_range; ++ else ++ device_property_read_u32(dev, "button-adc-y-range", ++ &joypad->bt_adc_y_range); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static int joypad_dt_parse(struct device *dev, struct joypad *joypad) ++{ ++ int error = 0; ++ ++ /* initialize value check from boot.ini */ ++ joypad_setup_value_check(dev, joypad); ++ ++ device_property_read_u32(dev, "button-adc-count", ++ &joypad->bt_adc_count); ++ ++ device_property_read_u32(dev, "poll-interval", ++ &joypad->poll_interval); ++ ++ joypad->auto_repeat = device_property_present(dev, "autorepeat"); ++ ++ /* change the report reference point? (ADC MAX - read value) */ ++ joypad->invert_absx = device_property_present(dev, "invert-absx"); ++ joypad->invert_absy = device_property_present(dev, "invert-absy"); ++ dev_info(dev, "%s : invert-absx = %d, inveret-absy = %d\n", ++ __func__, joypad->invert_absx, joypad->invert_absy); ++ ++ joypad->bt_gpio_count = device_get_child_node_count(dev); ++ ++ if ((joypad->bt_adc_count == 0) || (joypad->bt_gpio_count == 0)) { ++ dev_err(dev, "adc key = %d, gpio key = %d error!", ++ joypad->bt_adc_count, joypad->bt_gpio_count); ++ return -EINVAL; ++ } ++ ++ error = joypad_adc_setup(dev, joypad); ++ if (error) ++ return error; ++ ++ error = joypad_gpio_setup(dev, joypad); ++ if (error) ++ return error; ++ ++ return error; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static int joypad_probe(struct platform_device *pdev) ++{ ++ struct joypad *joypad; ++ struct device *dev = &pdev->dev; ++ int error; ++ ++ joypad = devm_kzalloc(dev, sizeof(struct joypad), GFP_KERNEL); ++ if (!joypad) { ++ dev_err(dev, "joypad devm_kzmalloc error!"); ++ return -ENOMEM; ++ } ++ ++ /* device tree data parse */ ++ error = joypad_dt_parse(dev, joypad); ++ if (error) { ++ dev_err(dev, "dt parse error!(err = %d)\n", error); ++ return error; ++ } ++ ++ mutex_init(&joypad->lock); ++ platform_set_drvdata(pdev, joypad); ++ ++ error = sysfs_create_group(&pdev->dev.kobj, &joypad_attr_group); ++ if (error) { ++ dev_err(dev, "create sysfs group fail, error: %d\n", ++ error); ++ return error; ++ } ++ ++ /* poll input device setup */ ++ error = joypad_input_setup(dev, joypad); ++ if (error) { ++ dev_err(dev, "input setup failed!(err = %d)\n", error); ++ return error; ++ } ++ dev_info(dev, "%s : probe success\n", __func__); ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static const struct of_device_id joypad_of_match[] = { ++ { .compatible = "odroidgo2-v11-joypad", }, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(of, joypad_of_match); ++ ++/*----------------------------------------------------------------------------*/ ++static struct platform_driver joypad_driver = { ++ .probe = joypad_probe, ++ .driver = { ++ .name = DRV_NAME, ++ .of_match_table = of_match_ptr(joypad_of_match), ++ }, ++}; ++ ++/*----------------------------------------------------------------------------*/ ++static int __init joypad_init(void) ++{ ++ return platform_driver_register(&joypad_driver); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static void __exit joypad_exit(void) ++{ ++ platform_driver_unregister(&joypad_driver); ++} ++ ++/*----------------------------------------------------------------------------*/ ++late_initcall(joypad_init); ++module_exit(joypad_exit); ++ ++/*----------------------------------------------------------------------------*/ ++MODULE_AUTHOR("Hardkernel Co.,LTD"); ++MODULE_DESCRIPTION("Keypad driver(ADC&GPIO) for ODROIDGO-Advance"); ++MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("platform:" DRV_NAME); ++ ++/*----------------------------------------------------------------------------*/ +diff --git a/drivers/input/joystick/odroidgo3-joypad.c b/drivers/input/joystick/odroidgo3-joypad.c +new file mode 100644 +index 000000000000..34f182175bcd +--- /dev/null ++++ b/drivers/input/joystick/odroidgo3-joypad.c +@@ -0,0 +1,1112 @@ ++/* ++ * SARADC joystick & GPIO Button driver for Linux(Hardkernel ODROIDGO2-Advance) ++ */ ++/* ++ * 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 ++ * ++ * Should you need to contact me, the author, you can do so either by ++ * e-mail - mail your message to , or by paper mail: ++ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic ++ */ ++ ++/*----------------------------------------------------------------------------*/ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/*----------------------------------------------------------------------------*/ ++#define DRV_NAME "odroidgo3_joypad" ++ ++/*----------------------------------------------------------------------------*/ ++#define ADC_MAX_VOLTAGE 1800 ++#define ADC_DATA_TUNING(x, p) ((x * p) / 100) ++#define ADC_TUNING_DEFAULT 180 ++ ++/*----------------------------------------------------------------------------*/ ++/* ++ +--------------------------------+ ++ | IIO Channel : ADC_IN1 | ++ +--------------+-----------------+-----------------+--------+---------+ ++ | EN(GPIO3.B5) | SEL_A(GPIO3.B3) | SEL_B(GPIO3.B0) | SELECT | EVENT | ++ +--------------+-----------------+-----------------+--------+---------+ ++ | 0 | 0 | 0 | R-Y | ABS_RY | ++ +--------------+-----------------+-----------------+--------+---------+ ++ | 0 | 0 | 1 | R-X | ABS_RX | ++ +--------------+-----------------+-----------------+--------+---------+ ++ | 0 | 1 | 0 | L-Y | ABS_Y | ++ +--------------+-----------------+-----------------+--------+---------+ ++ | 0 | 1 | 1 | L-X | ABS_X | ++ +--------------+-----------------+-----------------+--------+---------+ ++ | 1 | X | X | XXXX | ++ +--------------+-----------------+-----------------+--------+ ++*/ ++/*----------------------------------------------------------------------------*/ ++struct bt_adc { ++ /* report value (mV) */ ++ int value; ++ /* report type */ ++ int report_type; ++ /* input device init value (mV) */ ++ int max, min; ++ /* calibrated adc value */ ++ int cal; ++ /* adc scale value */ ++ int scale; ++ /* invert report */ ++ bool invert; ++ /* amux channel */ ++ int amux_ch; ++ /* adc data tuning value([percent), p = positive, n = negative */ ++ int tuning_p, tuning_n; ++}; ++ ++struct analog_mux { ++ /* IIO ADC Channel : amux connect channel */ ++ struct iio_channel *iio_ch; ++ /* analog mux select(a,b) gpio */ ++ int sel_a_gpio, sel_b_gpio; ++ /* analog mux enable gpio */ ++ int en_gpio; ++}; ++ ++struct bt_gpio { ++ /* GPIO Request label */ ++ const char *label; ++ /* GPIO Number */ ++ int num; ++ /* report type */ ++ int report_type; ++ /* report linux code */ ++ int linux_code; ++ /* prev button value */ ++ bool old_value; ++ /* button press level */ ++ bool active_level; ++}; ++ ++struct joypad { ++ struct device *dev; ++ int poll_interval; ++ ++ /* report enable/disable */ ++ bool enable; ++ ++ /* analog mux & joystick control */ ++ struct analog_mux *amux; ++ /* analog mux max count */ ++ int amux_count; ++ /* analog button */ ++ struct bt_adc *adcs; ++ ++ /* report reference point */ ++ bool invert_absx; ++ bool invert_absy; ++ bool invert_absrx; ++ bool invert_absry; ++ ++ /* report interval (ms) */ ++ int bt_gpio_count; ++ struct bt_gpio *gpios; ++ ++ /* button auto repeat */ ++ int auto_repeat; ++ ++ /* report threshold (mV) */ ++ int bt_adc_fuzz, bt_adc_flat; ++ /* adc read value scale */ ++ int bt_adc_scale; ++ /* joystick deadzone control */ ++ int bt_adc_deadzone; ++ ++ struct mutex lock; ++ ++ /* amux debug channel */ ++ int debug_ch; ++}; ++ ++/*----------------------------------------------------------------------------*/ ++// ++// set to the value in the boot.ini file. (if exist) ++// ++/*----------------------------------------------------------------------------*/ ++static unsigned int g_button_adc_fuzz = 0; ++static unsigned int g_button_adc_flat = 0; ++static unsigned int g_button_adc_scale = 0; ++static unsigned int g_button_adc_deadzone = 0; ++ ++static int button_adc_fuzz(char *str) ++{ ++ if (!str) ++ return -EINVAL; ++ g_button_adc_fuzz = simple_strtoul(str, NULL, 10); ++ return 0; ++} ++__setup("button-adc-fuzz=", button_adc_fuzz); ++ ++static int button_adc_flat(char *str) ++{ ++ if (!str) ++ return -EINVAL; ++ g_button_adc_flat = simple_strtoul(str, NULL, 10); ++ return 0; ++} ++__setup("button-adc-flat=", button_adc_flat); ++ ++static int button_adc_scale(char *str) ++{ ++ if (!str) ++ return -EINVAL; ++ g_button_adc_scale = simple_strtoul(str, NULL, 10); ++ return 0; ++} ++__setup("button-adc-scale=", button_adc_scale); ++ ++static int button_adc_deadzone(char *str) ++{ ++ if (!str) ++ return -EINVAL; ++ g_button_adc_deadzone = simple_strtoul(str, NULL, 10); ++ return 0; ++} ++__setup("button-adc-deadzone=", button_adc_deadzone); ++ ++/*----------------------------------------------------------------------------*/ ++/*----------------------------------------------------------------------------*/ ++static int joypad_amux_select(struct analog_mux *amux, int channel) ++{ ++ /* select mux channel */ ++ gpio_set_value(amux->en_gpio, 0); ++ ++ switch(channel) { ++ case 0: /* EVENT (ABS_RY) */ ++ gpio_set_value(amux->sel_a_gpio, 0); ++ gpio_set_value(amux->sel_b_gpio, 0); ++ break; ++ case 1: /* EVENT (ABS_RX) */ ++ gpio_set_value(amux->sel_a_gpio, 0); ++ gpio_set_value(amux->sel_b_gpio, 1); ++ break; ++ case 2: /* EVENT (ABS_Y) */ ++ gpio_set_value(amux->sel_a_gpio, 1); ++ gpio_set_value(amux->sel_b_gpio, 0); ++ break; ++ case 3: /* EVENT (ABS_X) */ ++ gpio_set_value(amux->sel_a_gpio, 1); ++ gpio_set_value(amux->sel_b_gpio, 1); ++ break; ++ default: ++ /* amux disanle */ ++ gpio_set_value(amux->en_gpio, 1); ++ return -1; ++ } ++ /* mux swtiching speed : 35ns(on) / 9ns(off) */ ++ usleep_range(1, 2); ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static int joypad_adc_read(struct analog_mux *amux, struct bt_adc *adc) ++{ ++ int value; ++ ++ if (joypad_amux_select(amux, adc->amux_ch)) ++ return 0; ++ ++ if (iio_read_channel_processed(amux->iio_ch, &value)) ++ return 0; ++ ++ value *= adc->scale; ++ ++ return value; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*----------------------------------------------------------------------------*/ ++/* ++ * ATTRIBUTES: ++ * ++ * /sys/devices/platform/odroidgo2_joypad/poll_interval [rw] ++ */ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_store_poll_interval(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, ++ size_t count) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ mutex_lock(&joypad->lock); ++ joypad->poll_interval = simple_strtoul(buf, NULL, 10); ++ mutex_unlock(&joypad->lock); ++ ++ return count; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_show_poll_interval(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ return sprintf(buf, "%d\n", joypad->poll_interval); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static DEVICE_ATTR(poll_interval, S_IWUSR | S_IRUGO, ++ joypad_show_poll_interval, ++ joypad_store_poll_interval); ++ ++/*----------------------------------------------------------------------------*/ ++/* ++ * ATTRIBUTES: ++ * ++ * /sys/devices/platform/odroidgo2_joypad/adc_fuzz [r] ++ */ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_show_adc_fuzz(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ return sprintf(buf, "%d\n", joypad->bt_adc_fuzz); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static DEVICE_ATTR(adc_fuzz, S_IWUSR | S_IRUGO, ++ joypad_show_adc_fuzz, ++ NULL); ++ ++/*----------------------------------------------------------------------------*/ ++/* ++ * ATTRIBUTES: ++ * ++ * /sys/devices/platform/odroidgo2_joypad/adc_flat [r] ++ */ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_show_adc_flat(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ return sprintf(buf, "%d\n", joypad->bt_adc_flat); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static DEVICE_ATTR(adc_flat, S_IWUSR | S_IRUGO, ++ joypad_show_adc_flat, ++ NULL); ++ ++/*----------------------------------------------------------------------------*/ ++/* ++ * ATTRIBUTES: ++ * ++ * /sys/devices/platform/odroidgo2_joypad/enable [rw] ++ */ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_store_enable(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, ++ size_t count) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ mutex_lock(&joypad->lock); ++ joypad->enable = simple_strtoul(buf, NULL, 10); ++ mutex_unlock(&joypad->lock); ++ ++ return count; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_show_enable(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ return sprintf(buf, "%d\n", joypad->enable); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO, ++ joypad_show_enable, ++ joypad_store_enable); ++ ++/*----------------------------------------------------------------------------*/ ++/* ++ * ATTRIBUTES: ++ * ++ * /sys/devices/platform/odroidgo2_joypad/adc_cal [rw] ++ */ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_store_adc_cal(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, ++ size_t count) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ bool calibration; ++ ++ calibration = simple_strtoul(buf, NULL, 10); ++ ++ if (calibration) { ++ int nbtn; ++ ++ mutex_lock(&joypad->lock); ++ for (nbtn = 0; nbtn < joypad->amux_count; nbtn++) { ++ struct bt_adc *adc = &joypad->adcs[nbtn]; ++ ++ adc->value = joypad_adc_read(joypad->amux, adc); ++ if (!adc->value) { ++ dev_err(joypad->dev, "%s : saradc channels[%d]!\n", ++ __func__, nbtn); ++ continue; ++ } ++ adc->cal = adc->value; ++ } ++ mutex_unlock(&joypad->lock); ++ } ++ return count; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_show_adc_cal(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ int nbtn; ++ ssize_t pos; ++ ++ for (nbtn = 0, pos = 0; nbtn < joypad->amux_count; nbtn++) { ++ struct bt_adc *adc = &joypad->adcs[nbtn]; ++ pos += sprintf(&buf[pos], "adc[%d]->cal = %d\n", ++ nbtn, adc->cal); ++ } ++ pos += sprintf(&buf[pos], "adc scale = %d\n", joypad->bt_adc_scale); ++ return pos; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static DEVICE_ATTR(adc_cal, S_IWUSR | S_IRUGO, ++ joypad_show_adc_cal, ++ joypad_store_adc_cal); ++ ++/*----------------------------------------------------------------------------*/ ++/* ++ * ATTRIBUTES: ++ * ++ * /sys/devices/platform/odroidgo2_joypad/amux_debug [rw] ++ * ++ * echo [debug channel] > amux_debug ++ * cat amux_debug : debug channel mux set & adc read ++ */ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_store_amux_debug(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, ++ size_t count) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ joypad->debug_ch = simple_strtoul(buf, NULL, 10); ++ ++ /* if error than default setting(debug_ch = 0) */ ++ if (joypad->debug_ch > joypad->amux_count) ++ joypad->debug_ch = 0; ++ ++ return count; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_show_amux_debug(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ struct analog_mux *amux = joypad->amux; ++ ssize_t pos; ++ int value; ++ ++ mutex_lock(&joypad->lock); ++ ++ /* disable poll driver */ ++ if (joypad->enable) ++ joypad->enable = false; ++ ++ if (joypad_amux_select(amux, joypad->debug_ch)) ++ goto err_out; ++ ++ if (iio_read_channel_processed(amux->iio_ch, &value)) ++ goto err_out; ++ ++ pos = sprintf(buf, "amux ch[%d], adc scale = %d, adc value = %d\n", ++ joypad->debug_ch, joypad->bt_adc_scale, ++ value * joypad->bt_adc_scale); ++ goto out; ++ ++err_out: ++ pos = sprintf(buf, "error : amux setup & adc read!\n"); ++out: ++ mutex_unlock(&joypad->lock); ++ return pos; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static DEVICE_ATTR(amux_debug, S_IWUSR | S_IRUGO, ++ joypad_show_amux_debug, ++ joypad_store_amux_debug); ++ ++/*----------------------------------------------------------------------------*/ ++/*----------------------------------------------------------------------------*/ ++static struct attribute *joypad_attrs[] = { ++ &dev_attr_poll_interval.attr, ++ &dev_attr_adc_fuzz.attr, ++ &dev_attr_adc_flat.attr, ++ &dev_attr_enable.attr, ++ &dev_attr_adc_cal.attr, ++ &dev_attr_amux_debug.attr, ++ NULL, ++}; ++ ++static struct attribute_group joypad_attr_group = { ++ .attrs = joypad_attrs, ++}; ++ ++/*----------------------------------------------------------------------------*/ ++/*----------------------------------------------------------------------------*/ ++static void joypad_gpio_check(struct input_polled_dev *poll_dev) ++{ ++ struct joypad *joypad = poll_dev->private; ++ int nbtn, value; ++ ++ for (nbtn = 0; nbtn < joypad->bt_gpio_count; nbtn++) { ++ struct bt_gpio *gpio = &joypad->gpios[nbtn]; ++ ++ if (gpio_get_value_cansleep(gpio->num) < 0) { ++ dev_err(joypad->dev, "failed to get gpio state\n"); ++ continue; ++ } ++ value = gpio_get_value(gpio->num); ++ if (value != gpio->old_value) { ++ input_event(poll_dev->input, ++ gpio->report_type, ++ gpio->linux_code, ++ (value == gpio->active_level) ? 1 : 0); ++ gpio->old_value = value; ++ } ++ } ++ input_sync(poll_dev->input); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static void joypad_adc_check(struct input_polled_dev *poll_dev) ++{ ++ struct joypad *joypad = poll_dev->private; ++ int nbtn; ++ ++ for (nbtn = 0; nbtn < joypad->amux_count; nbtn++) { ++ struct bt_adc *adc = &joypad->adcs[nbtn]; ++ ++ adc->value = joypad_adc_read(joypad->amux, adc); ++ if (!adc->value) { ++ dev_err(joypad->dev, "%s : saradc channels[%d]!\n", ++ __func__, nbtn); ++ continue; ++ } ++ adc->value = adc->value - adc->cal; ++ ++ /* Joystick Deadzone check */ ++ if (joypad->bt_adc_deadzone) { ++ if (abs(adc->value) < joypad->bt_adc_deadzone) ++ adc->value = 0; ++ } ++ ++ /* adc data tuning */ ++ if (adc->tuning_n && adc->value < 0) ++ adc->value = ADC_DATA_TUNING(adc->value, adc->tuning_n); ++ if (adc->tuning_p && adc->value > 0) ++ adc->value = ADC_DATA_TUNING(adc->value, adc->tuning_p); ++ ++ adc->value = adc->value > adc->max ? adc->max : adc->value; ++ adc->value = adc->value < adc->min ? adc->min : adc->value; ++ ++ input_report_abs(poll_dev->input, ++ adc->report_type, ++ adc->invert ? adc->value * (-1) : adc->value); ++ } ++ input_sync(poll_dev->input); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static void joypad_poll(struct input_polled_dev *poll_dev) ++{ ++ struct joypad *joypad = poll_dev->private; ++ ++ if (joypad->enable) { ++ joypad_adc_check(poll_dev); ++ joypad_gpio_check(poll_dev); ++ } ++ if (poll_dev->poll_interval != joypad->poll_interval) { ++ mutex_lock(&joypad->lock); ++ poll_dev->poll_interval = joypad->poll_interval; ++ mutex_unlock(&joypad->lock); ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++static void joypad_open(struct input_polled_dev *poll_dev) ++{ ++ struct joypad *joypad = poll_dev->private; ++ int nbtn; ++ ++ for (nbtn = 0; nbtn < joypad->bt_gpio_count; nbtn++) { ++ struct bt_gpio *gpio = &joypad->gpios[nbtn]; ++ gpio->old_value = gpio->active_level ? 0 : 1; ++ } ++ for (nbtn = 0; nbtn < joypad->amux_count; nbtn++) { ++ struct bt_adc *adc = &joypad->adcs[nbtn]; ++ ++ adc->value = joypad_adc_read(joypad->amux, adc); ++ if (!adc->value) { ++ dev_err(joypad->dev, "%s : saradc channels[%d]!\n", ++ __func__, nbtn); ++ continue; ++ } ++ adc->cal = adc->value; ++ dev_info(joypad->dev, "%s : adc[%d] adc->cal = %d\n", ++ __func__, nbtn, adc->cal); ++ } ++ /* buttons status sync */ ++ joypad_adc_check(poll_dev); ++ joypad_gpio_check(poll_dev); ++ ++ /* button report enable */ ++ mutex_lock(&joypad->lock); ++ joypad->enable = true; ++ mutex_unlock(&joypad->lock); ++ ++ dev_info(joypad->dev, "%s : opened\n", __func__); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static void joypad_close(struct input_polled_dev *poll_dev) ++{ ++ struct joypad *joypad = poll_dev->private; ++ ++ /* button report disable */ ++ mutex_lock(&joypad->lock); ++ joypad->enable = false; ++ mutex_unlock(&joypad->lock); ++ ++ dev_info(joypad->dev, "%s : closed\n", __func__); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static int joypad_amux_setup(struct device *dev, struct joypad *joypad) ++{ ++ struct analog_mux *amux; ++ enum iio_chan_type type; ++ enum of_gpio_flags flags; ++ int ret; ++ ++ /* analog mux control struct init */ ++ joypad->amux = devm_kzalloc(dev, sizeof(struct analog_mux), ++ GFP_KERNEL); ++ if (!joypad->amux) { ++ dev_err(dev, "%s amux devm_kzmalloc error!", __func__); ++ return -ENOMEM; ++ } ++ amux = joypad->amux; ++ amux->iio_ch = devm_iio_channel_get(dev, "amux_adc"); ++ if (IS_ERR(amux->iio_ch)) { ++ dev_err(dev, "iio channel get error\n"); ++ return -EINVAL; ++ } ++ if (!amux->iio_ch->indio_dev) ++ return -ENXIO; ++ ++ if (iio_get_channel_type(amux->iio_ch, &type)) ++ return -EINVAL; ++ ++ if (type != IIO_VOLTAGE) { ++ dev_err(dev, "Incompatible channel type %d\n", type); ++ return -EINVAL; ++ } ++ ++ amux->sel_a_gpio = of_get_named_gpio_flags(dev->of_node, ++ "amux-a-gpios", 0, &flags); ++ if (gpio_is_valid(amux->sel_a_gpio)) { ++ ret = devm_gpio_request(dev, amux->sel_a_gpio, "amux-sel-a"); ++ if (ret < 0) { ++ dev_err(dev, "%s : failed to request amux-sel-a %d\n", ++ __func__, amux->sel_a_gpio); ++ goto err_out; ++ } ++ ret = gpio_direction_output(amux->sel_a_gpio, 0); ++ if (ret < 0) ++ goto err_out; ++ } ++ ++ amux->sel_b_gpio = of_get_named_gpio_flags(dev->of_node, ++ "amux-b-gpios", 0, &flags); ++ if (gpio_is_valid(amux->sel_b_gpio)) { ++ ret = devm_gpio_request(dev, amux->sel_b_gpio, "amux-sel-b"); ++ if (ret < 0) { ++ dev_err(dev, "%s : failed to request amux-sel-b %d\n", ++ __func__, amux->sel_b_gpio); ++ goto err_out; ++ } ++ ret = gpio_direction_output(amux->sel_b_gpio, 0); ++ if (ret < 0) ++ goto err_out; ++ } ++ ++ amux->en_gpio = of_get_named_gpio_flags(dev->of_node, ++ "amux-en-gpios", 0, &flags); ++ if (gpio_is_valid(amux->en_gpio)) { ++ ret = devm_gpio_request(dev, amux->en_gpio, "amux-en"); ++ if (ret < 0) { ++ dev_err(dev, "%s : failed to request amux-en %d\n", ++ __func__, amux->en_gpio); ++ goto err_out; ++ } ++ ret = gpio_direction_output(amux->en_gpio, 0); ++ if (ret < 0) ++ goto err_out; ++ } ++ return 0; ++err_out: ++ return ret; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static int joypad_adc_setup(struct device *dev, struct joypad *joypad) ++{ ++ int nbtn; ++ ++ /* adc button struct init */ ++ joypad->adcs = devm_kzalloc(dev, joypad->amux_count * ++ sizeof(struct bt_adc), GFP_KERNEL); ++ if (!joypad->adcs) { ++ dev_err(dev, "%s devm_kzmalloc error!", __func__); ++ return -ENOMEM; ++ } ++ ++ for (nbtn = 0; nbtn < joypad->amux_count; nbtn++) { ++ struct bt_adc *adc = &joypad->adcs[nbtn]; ++ ++ adc->scale = joypad->bt_adc_scale; ++ ++ adc->max = (ADC_MAX_VOLTAGE / 2); ++ adc->min = (ADC_MAX_VOLTAGE / 2) * (-1); ++ if (adc->scale) { ++ adc->max *= adc->scale; ++ adc->min *= adc->scale; ++ } ++ adc->amux_ch = nbtn; ++ adc->invert = false; ++ ++ switch (nbtn) { ++ case 0: ++ if (joypad->invert_absry) ++ adc->invert = true; ++ adc->report_type = ABS_RY; ++ if (device_property_read_u32(dev, ++ "abs_ry-p-tuning", ++ &adc->tuning_p)) ++ adc->tuning_p = ADC_TUNING_DEFAULT; ++ if (device_property_read_u32(dev, ++ "abs_ry-n-tuning", ++ &adc->tuning_n)) ++ adc->tuning_n = ADC_TUNING_DEFAULT; ++ break; ++ case 1: ++ if (joypad->invert_absrx) ++ adc->invert = true; ++ adc->report_type = ABS_RX; ++ if (device_property_read_u32(dev, ++ "abs_rx-p-tuning", ++ &adc->tuning_p)) ++ adc->tuning_p = ADC_TUNING_DEFAULT; ++ if (device_property_read_u32(dev, ++ "abs_rx-n-tuning", ++ &adc->tuning_n)) ++ adc->tuning_n = ADC_TUNING_DEFAULT; ++ break; ++ case 2: ++ if (joypad->invert_absy) ++ adc->invert = true; ++ adc->report_type = ABS_Y; ++ if (device_property_read_u32(dev, ++ "abs_y-p-tuning", ++ &adc->tuning_p)) ++ adc->tuning_p = ADC_TUNING_DEFAULT; ++ if (device_property_read_u32(dev, ++ "abs_y-n-tuning", ++ &adc->tuning_n)) ++ adc->tuning_n = ADC_TUNING_DEFAULT; ++ break; ++ case 3: ++ if (joypad->invert_absx) ++ adc->invert = true; ++ adc->report_type = ABS_X; ++ if (device_property_read_u32(dev, ++ "abs_x-p-tuning", ++ &adc->tuning_p)) ++ adc->tuning_p = ADC_TUNING_DEFAULT; ++ if (device_property_read_u32(dev, ++ "abs_x-n-tuning", ++ &adc->tuning_n)) ++ adc->tuning_n = ADC_TUNING_DEFAULT; ++ break; ++ default : ++ dev_err(dev, "%s amux count(%d) error!", ++ __func__, nbtn); ++ return -EINVAL; ++ } ++ } ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static int joypad_gpio_setup(struct device *dev, struct joypad *joypad) ++{ ++ struct device_node *node, *pp; ++ int nbtn; ++ ++ node = dev->of_node; ++ if (!node) ++ return -ENODEV; ++ ++ joypad->gpios = devm_kzalloc(dev, joypad->bt_gpio_count * ++ sizeof(struct bt_gpio), GFP_KERNEL); ++ ++ if (!joypad->gpios) { ++ dev_err(dev, "%s devm_kzmalloc error!", __func__); ++ return -ENOMEM; ++ } ++ ++ nbtn = 0; ++ for_each_child_of_node(node, pp) { ++ enum of_gpio_flags flags; ++ struct bt_gpio *gpio = &joypad->gpios[nbtn++]; ++ int error; ++ ++ gpio->num = of_get_gpio_flags(pp, 0, &flags); ++ if (gpio->num < 0) { ++ error = gpio->num; ++ dev_err(dev, "Failed to get gpio flags, error: %d\n", ++ error); ++ return error; ++ } ++ ++ /* gpio active level(key press level) */ ++ gpio->active_level = (flags & OF_GPIO_ACTIVE_LOW) ? 0 : 1; ++ ++ gpio->label = of_get_property(pp, "label", NULL); ++ ++ if (gpio_is_valid(gpio->num)) { ++ error = devm_gpio_request_one(dev, gpio->num, ++ GPIOF_IN, gpio->label); ++ if (error < 0) { ++ dev_err(dev, ++ "Failed to request GPIO %d, error %d\n", ++ gpio->num, error); ++ return error; ++ } ++ } ++ if (of_property_read_u32(pp, "linux,code", &gpio->linux_code)) { ++ dev_err(dev, "Button without keycode: 0x%x\n", ++ gpio->num); ++ return -EINVAL; ++ } ++ if (of_property_read_u32(pp, "linux,input-type", ++ &gpio->report_type)) ++ gpio->report_type = EV_KEY; ++ } ++ if (nbtn == 0) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static int joypad_input_setup(struct device *dev, struct joypad *joypad) ++{ ++ struct input_polled_dev *poll_dev; ++ struct input_dev *input; ++ int nbtn, error; ++ u32 joypad_revision = 0; ++ u32 joypad_product = 0; ++ ++ poll_dev = devm_input_allocate_polled_device(dev); ++ if (!poll_dev) { ++ dev_err(dev, "no memory for polled device\n"); ++ return -ENOMEM; ++ } ++ ++ poll_dev->private = joypad; ++ poll_dev->poll = joypad_poll; ++ poll_dev->poll_interval = joypad->poll_interval; ++ poll_dev->open = joypad_open; ++ poll_dev->close = joypad_close; ++ ++ input = poll_dev->input; ++ ++ device_property_read_string(dev, "joypad-name", &input->name); ++ input->phys = DRV_NAME"/input0"; ++ ++ device_property_read_u32(dev, "joypad-revision", &joypad_revision); ++ device_property_read_u32(dev, "joypad-product", &joypad_product); ++ input->id.bustype = BUS_HOST; ++ input->id.vendor = 0x0001; ++ input->id.product = (u16)joypad_product; ++ input->id.version = (u16)joypad_revision; ++ ++ /* IIO ADC key setup (0 mv ~ 1800 mv) * adc->scale */ ++ __set_bit(EV_ABS, input->evbit); ++ for(nbtn = 0; nbtn < joypad->amux_count; nbtn++) { ++ struct bt_adc *adc = &joypad->adcs[nbtn]; ++ input_set_abs_params(input, adc->report_type, ++ adc->min, adc->max, ++ joypad->bt_adc_fuzz, ++ joypad->bt_adc_flat); ++ dev_info(dev, ++ "%s : SCALE = %d, ABS min = %d, max = %d," ++ " fuzz = %d, flat = %d, deadzone = %d\n", ++ __func__, adc->scale, adc->min, adc->max, ++ joypad->bt_adc_fuzz, joypad->bt_adc_flat, ++ joypad->bt_adc_deadzone); ++ dev_info(dev, ++ "%s : adc tuning_p = %d, adc_tuning_n = %d\n\n", ++ __func__, adc->tuning_p, adc->tuning_n); ++ } ++ ++ /* GPIO key setup */ ++ __set_bit(EV_KEY, input->evbit); ++ for(nbtn = 0; nbtn < joypad->bt_gpio_count; nbtn++) { ++ struct bt_gpio *gpio = &joypad->gpios[nbtn]; ++ input_set_capability(input, gpio->report_type, ++ gpio->linux_code); ++ } ++ ++ if (joypad->auto_repeat) ++ __set_bit(EV_REP, input->evbit); ++ ++ joypad->dev = dev; ++ ++ error = input_register_polled_device(poll_dev); ++ if (error) { ++ dev_err(dev, "unable to register polled device, err=%d\n", ++ error); ++ return error; ++ } ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static void joypad_setup_value_check(struct device *dev, struct joypad *joypad) ++{ ++ /* ++ fuzz: specifies fuzz value that is used to filter noise from ++ the event stream. ++ */ ++ if (g_button_adc_fuzz) ++ joypad->bt_adc_fuzz = g_button_adc_fuzz; ++ else ++ device_property_read_u32(dev, "button-adc-fuzz", ++ &joypad->bt_adc_fuzz); ++ /* ++ flat: values that are within this value will be discarded by ++ joydev interface and reported as 0 instead. ++ */ ++ if (g_button_adc_flat) ++ joypad->bt_adc_flat = g_button_adc_flat; ++ else ++ device_property_read_u32(dev, "button-adc-flat", ++ &joypad->bt_adc_flat); ++ ++ /* Joystick report value control */ ++ if (g_button_adc_scale) ++ joypad->bt_adc_scale = g_button_adc_scale; ++ else ++ device_property_read_u32(dev, "button-adc-scale", ++ &joypad->bt_adc_scale); ++ ++ /* Joystick deadzone value control */ ++ if (g_button_adc_deadzone) ++ joypad->bt_adc_deadzone = g_button_adc_deadzone; ++ else ++ device_property_read_u32(dev, "button-adc-deadzone", ++ &joypad->bt_adc_deadzone); ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++static int joypad_dt_parse(struct device *dev, struct joypad *joypad) ++{ ++ int error = 0; ++ ++ /* initialize value check from boot.ini */ ++ joypad_setup_value_check(dev, joypad); ++ ++ device_property_read_u32(dev, "amux-count", ++ &joypad->amux_count); ++ ++ device_property_read_u32(dev, "poll-interval", ++ &joypad->poll_interval); ++ ++ joypad->auto_repeat = device_property_present(dev, "autorepeat"); ++ ++ /* change the report reference point? (read value * -1) */ ++ joypad->invert_absx = device_property_present(dev, "invert-absx"); ++ joypad->invert_absy = device_property_present(dev, "invert-absy"); ++ joypad->invert_absrx = device_property_present(dev, "invert-absrx"); ++ joypad->invert_absry = device_property_present(dev, "invert-absry"); ++ dev_info(dev, "%s : invert-absx = %d, inveret-absy = %d, invert-absrx = %d, invert-absry = %d\n", ++ __func__, joypad->invert_absx, joypad->invert_absy, joypad->invert_absrx, joypad->invert_absry); ++ ++ joypad->bt_gpio_count = device_get_child_node_count(dev); ++ ++ if ((joypad->amux_count == 0) || (joypad->bt_gpio_count == 0)) { ++ dev_err(dev, "adc key = %d, gpio key = %d error!", ++ joypad->amux_count, joypad->bt_gpio_count); ++ return -EINVAL; ++ } ++ ++ error = joypad_adc_setup(dev, joypad); ++ if (error) ++ return error; ++ ++ error = joypad_amux_setup(dev, joypad); ++ if (error) ++ return error; ++ ++ error = joypad_gpio_setup(dev, joypad); ++ if (error) ++ return error; ++ ++ dev_info(dev, "%s : adc key cnt = %d, gpio key cnt = %d\n", ++ __func__, joypad->amux_count, joypad->bt_gpio_count); ++ ++ return error; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static int joypad_probe(struct platform_device *pdev) ++{ ++ struct joypad *joypad; ++ struct device *dev = &pdev->dev; ++ int error; ++ ++ joypad = devm_kzalloc(dev, sizeof(struct joypad), GFP_KERNEL); ++ if (!joypad) { ++ dev_err(dev, "joypad devm_kzmalloc error!"); ++ return -ENOMEM; ++ } ++ ++ /* device tree data parse */ ++ error = joypad_dt_parse(dev, joypad); ++ if (error) { ++ dev_err(dev, "dt parse error!(err = %d)\n", error); ++ return error; ++ } ++ ++ mutex_init(&joypad->lock); ++ platform_set_drvdata(pdev, joypad); ++ ++ error = sysfs_create_group(&pdev->dev.kobj, &joypad_attr_group); ++ if (error) { ++ dev_err(dev, "create sysfs group fail, error: %d\n", ++ error); ++ return error; ++ } ++ ++ /* poll input device setup */ ++ error = joypad_input_setup(dev, joypad); ++ if (error) { ++ dev_err(dev, "input setup failed!(err = %d)\n", error); ++ return error; ++ } ++ dev_info(dev, "%s : probe success\n", __func__); ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static const struct of_device_id joypad_of_match[] = { ++ { .compatible = "odroidgo3-joypad", }, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(of, joypad_of_match); ++ ++/*----------------------------------------------------------------------------*/ ++static struct platform_driver joypad_driver = { ++ .probe = joypad_probe, ++ .driver = { ++ .name = DRV_NAME, ++ .of_match_table = of_match_ptr(joypad_of_match), ++ }, ++}; ++ ++/*----------------------------------------------------------------------------*/ ++static int __init joypad_init(void) ++{ ++ return platform_driver_register(&joypad_driver); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static void __exit joypad_exit(void) ++{ ++ platform_driver_unregister(&joypad_driver); ++} ++ ++/*----------------------------------------------------------------------------*/ ++late_initcall(joypad_init); ++module_exit(joypad_exit); ++ ++/*----------------------------------------------------------------------------*/ ++MODULE_AUTHOR("Hardkernel Co.,LTD"); ++MODULE_DESCRIPTION("Keypad driver(ADC&GPIO) for ODROIDGO-Advance"); ++MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("platform:" DRV_NAME); ++ ++/*----------------------------------------------------------------------------*/ +diff --git a/drivers/input/joystick/rgb20s-joypad.c b/drivers/input/joystick/rgb20s-joypad.c +new file mode 100644 +index 000000000000..a52981eee9fb +--- /dev/null ++++ b/drivers/input/joystick/rgb20s-joypad.c +@@ -0,0 +1,1373 @@ ++/* ++ * SARADC joystick & GPIO Button driver for Linux(Powkiddy RGB20S) ++ */ ++/* ++ * 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 ++ * ++ * Should you need to contact me, the author, you can do so either by ++ * e-mail - mail your message to , or by paper mail: ++ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic ++ */ ++ ++/*----------------------------------------------------------------------------*/ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/*----------------------------------------------------------------------------*/ ++#define DRV_NAME "rgb20s_joypad" ++ ++/*----------------------------------------------------------------------------*/ ++#define ADC_MAX_VOLTAGE 1800 ++#define ADC_DATA_TUNING(x, p) ((x * p) / 100) ++#define ADC_TUNING_DEFAULT 180 ++#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) ++ ++/*----------------------------------------------------------------------------*/ ++/* ++ +--------------------------------+ ++ | IIO Channel : ADC_IN1 | ++ +--------------+-----------------+-----------------+--------+---------+ ++ | EN(GPIO3.B5) | SEL_A(GPIO3.B3) | SEL_B(GPIO3.B0) | SELECT | EVENT | ++ +--------------+-----------------+-----------------+--------+---------+ ++ | 0 | 0 | 0 | R-Y | ABS_RY | ++ +--------------+-----------------+-----------------+--------+---------+ ++ | 0 | 0 | 1 | R-X | ABS_RX | ++ +--------------+-----------------+-----------------+--------+---------+ ++ | 0 | 1 | 0 | L-Y | ABS_Y | ++ +--------------+-----------------+-----------------+--------+---------+ ++ | 0 | 1 | 1 | L-X | ABS_X | ++ +--------------+-----------------+-----------------+--------+---------+ ++ | 1 | X | X | XXXX | ++ +--------------+-----------------+-----------------+--------+ ++*/ ++/*----------------------------------------------------------------------------*/ ++struct bt_adc { ++ /* report value (mV) */ ++ int value; ++ /* report type */ ++ int report_type; ++ /* input device init value (mV) */ ++ int max, min; ++ /* calibrated adc value */ ++ int cal; ++ /* adc scale value */ ++ int scale; ++ /* invert report */ ++ bool invert; ++ /* amux channel */ ++ int amux_ch; ++ /* adc data tuning value([percent), p = positive, n = negative */ ++ int tuning_p, tuning_n; ++}; ++ ++struct analog_mux { ++ /* IIO ADC Channel : amux connect channel */ ++ struct iio_channel *iio_ch; ++ /* analog mux select(a,b) gpio */ ++ int sel_a_gpio, sel_b_gpio; ++ /* analog mux enable gpio */ ++ int en_gpio; ++}; ++ ++struct bt_gpio { ++ /* GPIO Request label */ ++ const char *label; ++ /* GPIO Number */ ++ int num; ++ /* report type */ ++ int report_type; ++ /* report linux code */ ++ int linux_code; ++ /* prev button value */ ++ bool old_value; ++ /* button press level */ ++ bool active_level; ++}; ++ ++struct joypad { ++ struct device *dev; ++ int poll_interval; ++ ++ /* report enable/disable */ ++ bool enable; ++ ++ /* analog mux & joystick control */ ++ struct analog_mux *amux; ++ /* analog mux max count */ ++ int amux_count; ++ /* analog button */ ++ struct bt_adc *adcs; ++ ++ /* report reference point */ ++ bool invert_absx; ++ bool invert_absy; ++ bool invert_absrx; ++ bool invert_absry; ++ ++ /* report interval (ms) */ ++ int bt_gpio_count; ++ struct bt_gpio *gpios; ++ ++ /* button auto repeat */ ++ int auto_repeat; ++ ++ /* report threshold (mV) */ ++ int bt_adc_fuzz, bt_adc_flat; ++ /* adc read value scale */ ++ int bt_adc_scale; ++ /* joystick deadzone control */ ++ int bt_adc_deadzone; ++ ++ struct mutex lock; ++ ++ /* amux debug channel */ ++ int debug_ch; ++ ++ /* pwm device for rumble*/ ++ struct input_dev *input; ++ struct pwm_device *pwm; ++ struct work_struct play_work; ++ u16 level; ++ u16 boost_weak; ++ u16 boost_strong; ++}; ++ ++static int pwm_vibrator_start(struct joypad *joypad) ++{ ++ struct device *pdev = joypad->input->dev.parent; ++ struct pwm_state state; ++ int err; ++ ++ pwm_get_state(joypad->pwm, &state); ++ pwm_set_relative_duty_cycle(&state, joypad->level, 0xffff); ++ state.enabled = true; ++ ++ err = pwm_apply_might_sleep(joypad->pwm, &state); ++ if (err) { ++ dev_err(pdev, "failed to apply pwm state: %d", err); ++ return err; ++ } ++ ++ return 0; ++} ++ ++static void pwm_vibrator_stop(struct joypad *joypad) ++{ ++ pwm_disable(joypad->pwm); ++} ++ ++static void pwm_vibrator_play_work(struct work_struct *work) ++{ ++ struct joypad *joypad = container_of(work, ++ struct joypad, play_work); ++ ++ if (joypad->level) ++ pwm_vibrator_start(joypad); ++ else ++ pwm_vibrator_stop(joypad); ++} ++ ++ ++/*----------------------------------------------------------------------------*/ ++// ++// set to the value in the boot.ini file. (if exist) ++// ++/*----------------------------------------------------------------------------*/ ++static unsigned int g_button_adc_fuzz = 0; ++static unsigned int g_button_adc_flat = 0; ++static unsigned int g_button_adc_scale = 0; ++static unsigned int g_button_adc_deadzone = 0; ++ ++static int button_adc_fuzz(char *str) ++{ ++ if (!str) ++ return -EINVAL; ++ g_button_adc_fuzz = simple_strtoul(str, NULL, 10); ++ return 0; ++} ++__setup("button-adc-fuzz=", button_adc_fuzz); ++ ++static int button_adc_flat(char *str) ++{ ++ if (!str) ++ return -EINVAL; ++ g_button_adc_flat = simple_strtoul(str, NULL, 10); ++ return 0; ++} ++__setup("button-adc-flat=", button_adc_flat); ++ ++static int button_adc_scale(char *str) ++{ ++ if (!str) ++ return -EINVAL; ++ g_button_adc_scale = simple_strtoul(str, NULL, 10); ++ return 0; ++} ++__setup("button-adc-scale=", button_adc_scale); ++ ++static int button_adc_deadzone(char *str) ++{ ++ if (!str) ++ return -EINVAL; ++ g_button_adc_deadzone = simple_strtoul(str, NULL, 10); ++ return 0; ++} ++__setup("button-adc-deadzone=", button_adc_deadzone); ++ ++/*----------------------------------------------------------------------------*/ ++/*----------------------------------------------------------------------------*/ ++static int joypad_amux_select(struct analog_mux *amux, int channel) ++{ ++ /* select mux channel */ ++ gpio_set_value(amux->en_gpio, 0); ++ ++ switch(channel) { ++ case 0: /* EVENT (ABS_RY) */ ++ gpio_set_value(amux->sel_a_gpio, 0); ++ gpio_set_value(amux->sel_b_gpio, 0); ++ break; ++ case 1: /* EVENT (ABS_RX) */ ++ gpio_set_value(amux->sel_a_gpio, 0); ++ gpio_set_value(amux->sel_b_gpio, 1); ++ break; ++ case 2: /* EVENT (ABS_Y) */ ++ gpio_set_value(amux->sel_a_gpio, 1); ++ gpio_set_value(amux->sel_b_gpio, 0); ++ break; ++ case 3: /* EVENT (ABS_X) */ ++ gpio_set_value(amux->sel_a_gpio, 1); ++ gpio_set_value(amux->sel_b_gpio, 1); ++ break; ++ default: ++ /* amux disanle */ ++ gpio_set_value(amux->en_gpio, 1); ++ return -1; ++ } ++ /* mux swtiching speed : 35ns(on) / 9ns(off) */ ++ usleep_range(1, 2); ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static int joypad_adc_read(struct analog_mux *amux, struct bt_adc *adc) ++{ ++ int value; ++ ++ if (joypad_amux_select(amux, adc->amux_ch)) ++ return 0; ++ ++ if (iio_read_channel_processed(amux->iio_ch, &value)) ++ return 0; ++ ++ value *= adc->scale; ++ ++ return value; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*----------------------------------------------------------------------------*/ ++/* ++ * ATTRIBUTES: ++ * ++ * /sys/devices/platform/rgb20s_joypad/poll_interval [rw] ++ */ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_store_poll_interval(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, ++ size_t count) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ mutex_lock(&joypad->lock); ++ joypad->poll_interval = simple_strtoul(buf, NULL, 10); ++ mutex_unlock(&joypad->lock); ++ ++ return count; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_show_poll_interval(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ return sprintf(buf, "%d\n", joypad->poll_interval); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static DEVICE_ATTR(poll_interval, S_IWUSR | S_IRUGO, ++ joypad_show_poll_interval, ++ joypad_store_poll_interval); ++ ++/*----------------------------------------------------------------------------*/ ++/* ++ * ATTRIBUTES: ++ * ++ * /sys/devices/platform/rgb20s_joypad/adc_fuzz [r] ++ */ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_show_adc_fuzz(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ return sprintf(buf, "%d\n", joypad->bt_adc_fuzz); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static DEVICE_ATTR(adc_fuzz, S_IWUSR | S_IRUGO, ++ joypad_show_adc_fuzz, ++ NULL); ++ ++/*----------------------------------------------------------------------------*/ ++/* ++ * ATTRIBUTES: ++ * ++ * /sys/devices/platform/rgb20s_joypad/adc_flat [r] ++ */ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_show_adc_flat(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ return sprintf(buf, "%d\n", joypad->bt_adc_flat); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static DEVICE_ATTR(adc_flat, S_IWUSR | S_IRUGO, ++ joypad_show_adc_flat, ++ NULL); ++ ++/*----------------------------------------------------------------------------*/ ++/* ++ * ATTRIBUTES: ++ * ++ * /sys/devices/platform/rgb20s_joypad/enable [rw] ++ */ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_store_enable(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, ++ size_t count) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ mutex_lock(&joypad->lock); ++ joypad->enable = simple_strtoul(buf, NULL, 10); ++ mutex_unlock(&joypad->lock); ++ ++ return count; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_show_enable(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ return sprintf(buf, "%d\n", joypad->enable); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO, ++ joypad_show_enable, ++ joypad_store_enable); ++ ++/*----------------------------------------------------------------------------*/ ++/* ++ * ATTRIBUTES: ++ * ++ * /sys/devices/platform/rgb20s_joypad/adc_cal [rw] ++ */ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_store_adc_cal(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, ++ size_t count) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ bool calibration; ++ ++ calibration = simple_strtoul(buf, NULL, 10); ++ ++ if (calibration) { ++ int nbtn; ++ ++ mutex_lock(&joypad->lock); ++ for (nbtn = 0; nbtn < joypad->amux_count; nbtn++) { ++ struct bt_adc *adc = &joypad->adcs[nbtn]; ++ ++ adc->value = joypad_adc_read(joypad->amux, adc); ++ if (!adc->value) { ++ dev_err(joypad->dev, "%s : saradc channels[%d]!\n", ++ __func__, nbtn); ++ continue; ++ } ++ adc->cal = adc->value; ++ } ++ mutex_unlock(&joypad->lock); ++ } ++ return count; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_show_adc_cal(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ int nbtn; ++ ssize_t pos; ++ ++ for (nbtn = 0, pos = 0; nbtn < joypad->amux_count; nbtn++) { ++ struct bt_adc *adc = &joypad->adcs[nbtn]; ++ pos += sprintf(&buf[pos], "adc[%d]->cal = %d\n", ++ nbtn, adc->cal); ++ } ++ pos += sprintf(&buf[pos], "adc scale = %d\n", joypad->bt_adc_scale); ++ return pos; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static DEVICE_ATTR(adc_cal, S_IWUSR | S_IRUGO, ++ joypad_show_adc_cal, ++ joypad_store_adc_cal); ++ ++/*----------------------------------------------------------------------------*/ ++/* ++ * ATTRIBUTES: ++ * ++ * /sys/devices/platform/rgb20s_joypad/amux_debug [rw] ++ * ++ * echo [debug channel] > amux_debug ++ * cat amux_debug : debug channel mux set & adc read ++ */ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_store_amux_debug(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, ++ size_t count) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ joypad->debug_ch = simple_strtoul(buf, NULL, 10); ++ ++ /* if error than default setting(debug_ch = 0) */ ++ if (joypad->debug_ch > joypad->amux_count) ++ joypad->debug_ch = 0; ++ ++ return count; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_show_amux_debug(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ struct analog_mux *amux = joypad->amux; ++ ssize_t pos; ++ int value; ++ ++ mutex_lock(&joypad->lock); ++ ++ /* disable poll driver */ ++ if (joypad->enable) ++ joypad->enable = false; ++ ++ if (joypad_amux_select(amux, joypad->debug_ch)) ++ goto err_out; ++ ++ if (iio_read_channel_processed(amux->iio_ch, &value)) ++ goto err_out; ++ ++ pos = sprintf(buf, "amux ch[%d], adc scale = %d, adc value = %d\n", ++ joypad->debug_ch, joypad->bt_adc_scale, ++ value * joypad->bt_adc_scale); ++ goto out; ++ ++err_out: ++ pos = sprintf(buf, "error : amux setup & adc read!\n"); ++out: ++ mutex_unlock(&joypad->lock); ++ return pos; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static DEVICE_ATTR(amux_debug, S_IWUSR | S_IRUGO, ++ joypad_show_amux_debug, ++ joypad_store_amux_debug); ++ ++/*----------------------------------------------------------------------------*/ ++/*----------------------------------------------------------------------------*/ ++/* ++ * ATTRIBUTES: ++ * ++ * /sys/devices/platform/rgb20s_joypad/rumble_period [rw] ++ */ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_store_period(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, ++ size_t count) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ mutex_lock(&joypad->lock); ++ pwm_set_period(joypad->pwm, simple_strtoul(buf, NULL, 21)); ++ mutex_unlock(&joypad->lock); ++ ++ return count; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_show_period(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ return sprintf(buf, "%d\n", pwm_get_period(joypad->pwm)); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static DEVICE_ATTR(rumble_period, S_IWUSR | S_IRUGO, ++ joypad_show_period, ++ joypad_store_period); ++ ++ ++/*----------------------------------------------------------------------------*/ ++/*----------------------------------------------------------------------------*/ ++/* ++ * ATTRIBUTES: ++ * ++ * /sys/devices/platform/rgb20s_joypad/rumble_boost_strong [rw] ++ */ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_store_boost_strong(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, ++ size_t count) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ mutex_lock(&joypad->lock); ++ joypad->boost_strong = simple_strtoul(buf, NULL, 10); ++ mutex_unlock(&joypad->lock); ++ ++ return count; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_show_boost_strong(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ return sprintf(buf, "%d\n", joypad->boost_strong); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static DEVICE_ATTR(rumble_boost_strong, S_IWUSR | S_IRUGO, ++ joypad_show_boost_strong, ++ joypad_store_boost_strong); ++ ++/*----------------------------------------------------------------------------*/ ++/* ++ * ATTRIBUTES: ++ * ++ * /sys/devices/platform/rgb20s_joypad/rumble_boost_weak [rw] ++ */ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_store_boost_weak(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, ++ size_t count) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ mutex_lock(&joypad->lock); ++ joypad->boost_weak = simple_strtoul(buf, NULL, 10); ++ mutex_unlock(&joypad->lock); ++ ++ return count; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_show_boost_weak(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ return sprintf(buf, "%d\n", joypad->boost_weak); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static DEVICE_ATTR(rumble_boost_weak, S_IWUSR | S_IRUGO, ++ joypad_show_boost_weak, ++ joypad_store_boost_weak); ++ ++static struct attribute *joypad_attrs[] = { ++ &dev_attr_poll_interval.attr, ++ &dev_attr_adc_fuzz.attr, ++ &dev_attr_adc_flat.attr, ++ &dev_attr_enable.attr, ++ &dev_attr_adc_cal.attr, ++ &dev_attr_amux_debug.attr, ++ &dev_attr_rumble_period.attr, ++ &dev_attr_rumble_boost_strong.attr, ++ &dev_attr_rumble_boost_weak.attr, ++ NULL, ++}; ++ ++static struct attribute_group joypad_attr_group = { ++ .attrs = joypad_attrs, ++}; ++ ++/*----------------------------------------------------------------------------*/ ++/*----------------------------------------------------------------------------*/ ++static void joypad_gpio_check(struct input_polled_dev *poll_dev) ++{ ++ struct joypad *joypad = poll_dev->private; ++ int nbtn, value; ++ ++ for (nbtn = 0; nbtn < joypad->bt_gpio_count; nbtn++) { ++ struct bt_gpio *gpio = &joypad->gpios[nbtn]; ++ ++ if (gpio_get_value_cansleep(gpio->num) < 0) { ++ dev_err(joypad->dev, "failed to get gpio state\n"); ++ continue; ++ } ++ value = gpio_get_value(gpio->num); ++ if (value != gpio->old_value) { ++ input_event(poll_dev->input, ++ gpio->report_type, ++ gpio->linux_code, ++ (value == gpio->active_level) ? 1 : 0); ++ gpio->old_value = value; ++ } ++ } ++ input_sync(poll_dev->input); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static void joypad_adc_check(struct input_polled_dev *poll_dev) ++{ ++ struct joypad *joypad = poll_dev->private; ++ int nbtn; ++ ++ for (nbtn = 0; nbtn < joypad->amux_count; nbtn++) { ++ struct bt_adc *adc = &joypad->adcs[nbtn]; ++ ++ adc->value = joypad_adc_read(joypad->amux, adc); ++ if (!adc->value) { ++ dev_err(joypad->dev, "%s : saradc channels[%d]!\n", ++ __func__, nbtn); ++ continue; ++ } ++ adc->value = adc->value - adc->cal; ++ ++ /* Joystick Deadzone check */ ++ if (joypad->bt_adc_deadzone) { ++ if (abs(adc->value) < joypad->bt_adc_deadzone) ++ adc->value = 0; ++ } ++ ++ /* adc data tuning */ ++ if (adc->tuning_n && adc->value < 0) ++ adc->value = ADC_DATA_TUNING(adc->value, adc->tuning_n); ++ if (adc->tuning_p && adc->value > 0) ++ adc->value = ADC_DATA_TUNING(adc->value, adc->tuning_p); ++ ++ adc->value = adc->value > adc->max ? adc->max : adc->value; ++ adc->value = adc->value < adc->min ? adc->min : adc->value; ++ ++ input_report_abs(poll_dev->input, ++ adc->report_type, ++ adc->invert ? adc->value * (-1) : adc->value); ++ } ++ input_sync(poll_dev->input); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static void joypad_poll(struct input_polled_dev *poll_dev) ++{ ++ struct joypad *joypad = poll_dev->private; ++ ++ if (joypad->enable) { ++ joypad_adc_check(poll_dev); ++ joypad_gpio_check(poll_dev); ++ } ++ if (poll_dev->poll_interval != joypad->poll_interval) { ++ mutex_lock(&joypad->lock); ++ poll_dev->poll_interval = joypad->poll_interval; ++ mutex_unlock(&joypad->lock); ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++static void joypad_open(struct input_polled_dev *poll_dev) ++{ ++ struct joypad *joypad = poll_dev->private; ++ int nbtn; ++ ++ for (nbtn = 0; nbtn < joypad->bt_gpio_count; nbtn++) { ++ struct bt_gpio *gpio = &joypad->gpios[nbtn]; ++ gpio->old_value = gpio->active_level ? 0 : 1; ++ } ++ for (nbtn = 0; nbtn < joypad->amux_count; nbtn++) { ++ struct bt_adc *adc = &joypad->adcs[nbtn]; ++ ++ adc->value = joypad_adc_read(joypad->amux, adc); ++ if (!adc->value) { ++ dev_err(joypad->dev, "%s : saradc channels[%d]!\n", ++ __func__, nbtn); ++ continue; ++ } ++ adc->cal = adc->value; ++ dev_info(joypad->dev, "%s : adc[%d] adc->cal = %d\n", ++ __func__, nbtn, adc->cal); ++ } ++ /* buttons status sync */ ++ joypad_adc_check(poll_dev); ++ joypad_gpio_check(poll_dev); ++ ++ /* button report enable */ ++ mutex_lock(&joypad->lock); ++ joypad->enable = true; ++ mutex_unlock(&joypad->lock); ++ ++ dev_info(joypad->dev, "%s : opened\n", __func__); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static void joypad_close(struct input_polled_dev *poll_dev) ++{ ++ struct joypad *joypad = poll_dev->private; ++ ++ /* button report disable */ ++ mutex_lock(&joypad->lock); ++ joypad->enable = false; ++ mutex_unlock(&joypad->lock); ++ ++ cancel_work_sync(&joypad->play_work); ++ pwm_vibrator_stop(joypad); ++ ++ dev_info(joypad->dev, "%s : closed\n", __func__); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static int joypad_amux_setup(struct device *dev, struct joypad *joypad) ++{ ++ struct analog_mux *amux; ++ enum iio_chan_type type; ++ enum of_gpio_flags flags; ++ int ret; ++ ++ /* analog mux control struct init */ ++ joypad->amux = devm_kzalloc(dev, sizeof(struct analog_mux), ++ GFP_KERNEL); ++ if (!joypad->amux) { ++ dev_err(dev, "%s amux devm_kzmalloc error!", __func__); ++ return -ENOMEM; ++ } ++ amux = joypad->amux; ++ amux->iio_ch = devm_iio_channel_get(dev, "amux_adc"); ++ if (IS_ERR(amux->iio_ch)) { ++ dev_err(dev, "iio channel get error\n"); ++ return -EINVAL; ++ } ++ if (!amux->iio_ch->indio_dev) ++ return -ENXIO; ++ ++ if (iio_get_channel_type(amux->iio_ch, &type)) ++ return -EINVAL; ++ ++ if (type != IIO_VOLTAGE) { ++ dev_err(dev, "Incompatible channel type %d\n", type); ++ return -EINVAL; ++ } ++ ++ amux->sel_a_gpio = of_get_named_gpio_flags(dev->of_node, ++ "amux-a-gpios", 0, &flags); ++ if (gpio_is_valid(amux->sel_a_gpio)) { ++ ret = devm_gpio_request(dev, amux->sel_a_gpio, "amux-sel-a"); ++ if (ret < 0) { ++ dev_err(dev, "%s : failed to request amux-sel-a %d\n", ++ __func__, amux->sel_a_gpio); ++ goto err_out; ++ } ++ ret = gpio_direction_output(amux->sel_a_gpio, 0); ++ if (ret < 0) ++ goto err_out; ++ } ++ ++ amux->sel_b_gpio = of_get_named_gpio_flags(dev->of_node, ++ "amux-b-gpios", 0, &flags); ++ if (gpio_is_valid(amux->sel_b_gpio)) { ++ ret = devm_gpio_request(dev, amux->sel_b_gpio, "amux-sel-b"); ++ if (ret < 0) { ++ dev_err(dev, "%s : failed to request amux-sel-b %d\n", ++ __func__, amux->sel_b_gpio); ++ goto err_out; ++ } ++ ret = gpio_direction_output(amux->sel_b_gpio, 0); ++ if (ret < 0) ++ goto err_out; ++ } ++ ++ amux->en_gpio = of_get_named_gpio_flags(dev->of_node, ++ "amux-en-gpios", 0, &flags); ++ if (gpio_is_valid(amux->en_gpio)) { ++ ret = devm_gpio_request(dev, amux->en_gpio, "amux-en"); ++ if (ret < 0) { ++ dev_err(dev, "%s : failed to request amux-en %d\n", ++ __func__, amux->en_gpio); ++ goto err_out; ++ } ++ ret = gpio_direction_output(amux->en_gpio, 0); ++ if (ret < 0) ++ goto err_out; ++ } ++ return 0; ++err_out: ++ return ret; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static int joypad_adc_setup(struct device *dev, struct joypad *joypad) ++{ ++ int nbtn; ++ ++ /* adc button struct init */ ++ joypad->adcs = devm_kzalloc(dev, joypad->amux_count * ++ sizeof(struct bt_adc), GFP_KERNEL); ++ if (!joypad->adcs) { ++ dev_err(dev, "%s devm_kzmalloc error!", __func__); ++ return -ENOMEM; ++ } ++ ++ for (nbtn = 0; nbtn < joypad->amux_count; nbtn++) { ++ struct bt_adc *adc = &joypad->adcs[nbtn]; ++ ++ adc->scale = joypad->bt_adc_scale; ++ ++ adc->max = (ADC_MAX_VOLTAGE / 2); ++ adc->min = (ADC_MAX_VOLTAGE / 2) * (-1); ++ if (adc->scale) { ++ adc->max *= adc->scale; ++ adc->min *= adc->scale; ++ } ++ adc->amux_ch = nbtn; ++ adc->invert = false; ++ ++ switch (nbtn) { ++ case 0: ++ if (joypad->invert_absry) ++ adc->invert = true; ++ adc->report_type = ABS_RY; ++ if (device_property_read_u32(dev, ++ "abs_ry-p-tuning", ++ &adc->tuning_p)) ++ adc->tuning_p = ADC_TUNING_DEFAULT; ++ if (device_property_read_u32(dev, ++ "abs_ry-n-tuning", ++ &adc->tuning_n)) ++ adc->tuning_n = ADC_TUNING_DEFAULT; ++ break; ++ case 1: ++ if (joypad->invert_absrx) ++ adc->invert = true; ++ adc->report_type = ABS_RX; ++ if (device_property_read_u32(dev, ++ "abs_rx-p-tuning", ++ &adc->tuning_p)) ++ adc->tuning_p = ADC_TUNING_DEFAULT; ++ if (device_property_read_u32(dev, ++ "abs_rx-n-tuning", ++ &adc->tuning_n)) ++ adc->tuning_n = ADC_TUNING_DEFAULT; ++ break; ++ case 2: ++ if (joypad->invert_absy) ++ adc->invert = true; ++ adc->report_type = ABS_Y; ++ if (device_property_read_u32(dev, ++ "abs_y-p-tuning", ++ &adc->tuning_p)) ++ adc->tuning_p = ADC_TUNING_DEFAULT; ++ if (device_property_read_u32(dev, ++ "abs_y-n-tuning", ++ &adc->tuning_n)) ++ adc->tuning_n = ADC_TUNING_DEFAULT; ++ break; ++ case 3: ++ if (joypad->invert_absx) ++ adc->invert = true; ++ adc->report_type = ABS_X; ++ if (device_property_read_u32(dev, ++ "abs_x-p-tuning", ++ &adc->tuning_p)) ++ adc->tuning_p = ADC_TUNING_DEFAULT; ++ if (device_property_read_u32(dev, ++ "abs_x-n-tuning", ++ &adc->tuning_n)) ++ adc->tuning_n = ADC_TUNING_DEFAULT; ++ break; ++ default : ++ dev_err(dev, "%s amux count(%d) error!", ++ __func__, nbtn); ++ return -EINVAL; ++ } ++ } ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static int joypad_gpio_setup(struct device *dev, struct joypad *joypad) ++{ ++ struct device_node *node, *pp; ++ int nbtn; ++ ++ node = dev->of_node; ++ if (!node) ++ return -ENODEV; ++ ++ joypad->gpios = devm_kzalloc(dev, joypad->bt_gpio_count * ++ sizeof(struct bt_gpio), GFP_KERNEL); ++ ++ if (!joypad->gpios) { ++ dev_err(dev, "%s devm_kzmalloc error!", __func__); ++ return -ENOMEM; ++ } ++ ++ nbtn = 0; ++ for_each_child_of_node(node, pp) { ++ enum of_gpio_flags flags; ++ struct bt_gpio *gpio = &joypad->gpios[nbtn++]; ++ int error; ++ ++ gpio->num = of_get_gpio_flags(pp, 0, &flags); ++ if (gpio->num < 0) { ++ error = gpio->num; ++ dev_err(dev, "Failed to get gpio flags, error: %d\n", ++ error); ++ return error; ++ } ++ ++ /* gpio active level(key press level) */ ++ gpio->active_level = (flags & OF_GPIO_ACTIVE_LOW) ? 0 : 1; ++ ++ gpio->label = of_get_property(pp, "label", NULL); ++ ++ if (gpio_is_valid(gpio->num)) { ++ error = devm_gpio_request_one(dev, gpio->num, ++ GPIOF_IN, gpio->label); ++ if (error < 0) { ++ dev_err(dev, ++ "Failed to request GPIO %d, error %d\n", ++ gpio->num, error); ++ return error; ++ } ++ } ++ if (of_property_read_u32(pp, "linux,code", &gpio->linux_code)) { ++ dev_err(dev, "Button without keycode: 0x%x\n", ++ gpio->num); ++ return -EINVAL; ++ } ++ if (of_property_read_u32(pp, "linux,input-type", ++ &gpio->report_type)) ++ gpio->report_type = EV_KEY; ++ } ++ if (nbtn == 0) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++static int rumble_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect) ++{ ++ struct joypad *joypad = data; ++ u32 boosted_level; ++ if (effect->type != FF_RUMBLE) ++ return 0; ++ ++ if (effect->u.rumble.strong_magnitude) ++ boosted_level = effect->u.rumble.strong_magnitude + joypad->boost_strong; ++ else ++ boosted_level = effect->u.rumble.weak_magnitude + joypad->boost_weak; ++ ++ joypad->level = (u16)CLAMP(boosted_level, 0, 0xffff); ++ ++ dev_info(joypad->dev,"joypad->level = %d", joypad->level); ++ schedule_work(&joypad->play_work); ++ return 0; ++} ++/*----------------------------------------------------------------------------*/ ++static int joypad_rumble_setup(struct device *dev, struct joypad *joypad) ++{ ++ int err; ++ struct pwm_state state; ++ ++ joypad->pwm = devm_pwm_get(dev, "enable"); ++ if (IS_ERR(joypad->pwm)) ++ { ++ dev_err(dev, "rumble get error\n"); ++ return -EINVAL; ++ } ++ ++ INIT_WORK(&joypad->play_work, pwm_vibrator_play_work); ++ ++ /* Sync up PWM state and ensure it is off. */ ++ pwm_init_state(joypad->pwm, &state); ++ state.enabled = false; ++ err = pwm_apply_might_sleep(joypad->pwm, &state); ++ if (err) { ++ dev_err(dev, "failed to apply initial PWM state: %d", ++ err); ++ return err; ++ } ++ dev_info(dev, "rumble setup success!\n"); ++ return 0; ++} ++static int joypad_input_setup(struct device *dev, struct joypad *joypad) ++{ ++ struct input_polled_dev *poll_dev; ++ struct input_dev *input; ++ int nbtn, error; ++ u32 joypad_revision = 0; ++ u32 joypad_product = 0; ++ u32 boost_weak = 0; ++ u32 boost_strong = 0; ++ poll_dev = devm_input_allocate_polled_device(dev); ++ if (!poll_dev) { ++ dev_err(dev, "no memory for polled device\n"); ++ return -ENOMEM; ++ } ++ ++ poll_dev->private = joypad; ++ poll_dev->poll = joypad_poll; ++ poll_dev->poll_interval = joypad->poll_interval; ++ poll_dev->open = joypad_open; ++ poll_dev->close = joypad_close; ++ ++ input = poll_dev->input; ++ joypad->input = poll_dev->input; ++ ++ device_property_read_string(dev, "joypad-name", &input->name); ++ input->phys = DRV_NAME"/input0"; ++ ++ device_property_read_u32(dev, "joypad-revision", &joypad_revision); ++ device_property_read_u32(dev, "joypad-product", &joypad_product); ++ input->id.bustype = BUS_HOST; ++ input->id.vendor = 0x484B; ++ input->id.product = (u16)joypad_product; ++ input->id.version = (u16)joypad_revision; ++ ++ /* IIO ADC key setup (0 mv ~ 1800 mv) * adc->scale */ ++ __set_bit(EV_ABS, input->evbit); ++ for(nbtn = 0; nbtn < joypad->amux_count; nbtn++) { ++ struct bt_adc *adc = &joypad->adcs[nbtn]; ++ input_set_abs_params(input, adc->report_type, ++ adc->min, adc->max, ++ joypad->bt_adc_fuzz, ++ joypad->bt_adc_flat); ++ dev_info(dev, ++ "%s : SCALE = %d, ABS min = %d, max = %d," ++ " fuzz = %d, flat = %d, deadzone = %d\n", ++ __func__, adc->scale, adc->min, adc->max, ++ joypad->bt_adc_fuzz, joypad->bt_adc_flat, ++ joypad->bt_adc_deadzone); ++ dev_info(dev, ++ "%s : adc tuning_p = %d, adc_tuning_n = %d\n\n", ++ __func__, adc->tuning_p, adc->tuning_n); ++ } ++ ++ /* Rumble setip*/ ++ device_property_read_u32(dev, "rumble-boost-weak", &boost_weak); ++ device_property_read_u32(dev, "rumble-boost-strong", &boost_strong); ++ joypad->boost_weak = boost_weak; ++ joypad->boost_strong = boost_strong; ++ dev_info(dev, "Boost = %d, %d",boost_weak, boost_strong); ++ input_set_capability(input, EV_FF, FF_RUMBLE); ++ error = input_ff_create_memless(input, joypad, rumble_play_effect); ++ if (error) { ++ dev_err(dev, "unable to register rumble, err=%d\n", ++ error); ++ return error; ++ } ++ ++ /* GPIO key setup */ ++ __set_bit(EV_KEY, input->evbit); ++ for(nbtn = 0; nbtn < joypad->bt_gpio_count; nbtn++) { ++ struct bt_gpio *gpio = &joypad->gpios[nbtn]; ++ input_set_capability(input, gpio->report_type, ++ gpio->linux_code); ++ } ++ ++ if (joypad->auto_repeat) ++ __set_bit(EV_REP, input->evbit); ++ ++ joypad->dev = dev; ++ ++ error = input_register_polled_device(poll_dev); ++ if (error) { ++ dev_err(dev, "unable to register polled device, err=%d\n", ++ error); ++ return error; ++ } ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static void joypad_setup_value_check(struct device *dev, struct joypad *joypad) ++{ ++ /* ++ fuzz: specifies fuzz value that is used to filter noise from ++ the event stream. ++ */ ++ if (g_button_adc_fuzz) ++ joypad->bt_adc_fuzz = g_button_adc_fuzz; ++ else ++ device_property_read_u32(dev, "button-adc-fuzz", ++ &joypad->bt_adc_fuzz); ++ /* ++ flat: values that are within this value will be discarded by ++ joydev interface and reported as 0 instead. ++ */ ++ if (g_button_adc_flat) ++ joypad->bt_adc_flat = g_button_adc_flat; ++ else ++ device_property_read_u32(dev, "button-adc-flat", ++ &joypad->bt_adc_flat); ++ ++ /* Joystick report value control */ ++ if (g_button_adc_scale) ++ joypad->bt_adc_scale = g_button_adc_scale; ++ else ++ device_property_read_u32(dev, "button-adc-scale", ++ &joypad->bt_adc_scale); ++ ++ /* Joystick deadzone value control */ ++ if (g_button_adc_deadzone) ++ joypad->bt_adc_deadzone = g_button_adc_deadzone; ++ else ++ device_property_read_u32(dev, "button-adc-deadzone", ++ &joypad->bt_adc_deadzone); ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++static int joypad_dt_parse(struct device *dev, struct joypad *joypad) ++{ ++ int error = 0; ++ ++ /* initialize value check from boot.ini */ ++ joypad_setup_value_check(dev, joypad); ++ ++ device_property_read_u32(dev, "amux-count", ++ &joypad->amux_count); ++ ++ device_property_read_u32(dev, "poll-interval", ++ &joypad->poll_interval); ++ ++ joypad->auto_repeat = device_property_present(dev, "autorepeat"); ++ ++ /* change the report reference point? (ADC MAX - read value) */ ++ joypad->invert_absx = device_property_present(dev, "invert-absx"); ++ joypad->invert_absy = device_property_present(dev, "invert-absy"); ++ joypad->invert_absrx = device_property_present(dev, "invert-absrx"); ++ joypad->invert_absry = device_property_present(dev, "invert-absry"); ++ dev_info(dev, "%s : invert-absx = %d, inveret-absy = %d, invert-absrx = %d, inveret-absry = %d\n", ++ __func__, joypad->invert_absx, joypad->invert_absy, joypad->invert_absrx, joypad->invert_absry); ++ ++ joypad->bt_gpio_count = device_get_child_node_count(dev); ++ ++ if ((joypad->amux_count == 0) || (joypad->bt_gpio_count == 0)) { ++ dev_err(dev, "adc key = %d, gpio key = %d error!", ++ joypad->amux_count, joypad->bt_gpio_count); ++ return -EINVAL; ++ } ++ ++ error = joypad_adc_setup(dev, joypad); ++ if (error) ++ return error; ++ ++ error = joypad_amux_setup(dev, joypad); ++ if (error) ++ return error; ++ ++ error = joypad_gpio_setup(dev, joypad); ++ if (error) ++ return error; ++ ++ dev_info(dev, "%s : adc key cnt = %d, gpio key cnt = %d\n", ++ __func__, joypad->amux_count, joypad->bt_gpio_count); ++ ++ return error; ++} ++ ++static int __maybe_unused joypad_suspend(struct device *dev) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ cancel_work_sync(&joypad->play_work); ++ if (joypad->level) ++ pwm_vibrator_stop(joypad); ++ ++ return 0; ++} ++ ++static int __maybe_unused joypad_resume(struct device *dev) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ if (joypad->level) ++ pwm_vibrator_start(joypad); ++ ++ return 0; ++} ++ ++static SIMPLE_DEV_PM_OPS(joypad_pm_ops, ++ joypad_suspend, joypad_resume); ++/*----------------------------------------------------------------------------*/ ++static int joypad_probe(struct platform_device *pdev) ++{ ++ struct joypad *joypad; ++ struct device *dev = &pdev->dev; ++ int error; ++ ++ joypad = devm_kzalloc(dev, sizeof(struct joypad), GFP_KERNEL); ++ if (!joypad) { ++ dev_err(dev, "joypad devm_kzmalloc error!"); ++ return -ENOMEM; ++ } ++ ++ /* device tree data parse */ ++ error = joypad_dt_parse(dev, joypad); ++ if (error) { ++ dev_err(dev, "dt parse error!(err = %d)\n", error); ++ return error; ++ } ++ ++ mutex_init(&joypad->lock); ++ platform_set_drvdata(pdev, joypad); ++ ++ error = sysfs_create_group(&pdev->dev.kobj, &joypad_attr_group); ++ if (error) { ++ dev_err(dev, "create sysfs group fail, error: %d\n", ++ error); ++ return error; ++ } ++ ++ /* poll input device setup */ ++ error = joypad_input_setup(dev, joypad); ++ if (error) { ++ dev_err(dev, "input setup failed!(err = %d)\n", error); ++ return error; ++ } ++ ++ /* rumble setup */ ++ error = joypad_rumble_setup(dev, joypad); ++ if (error) { ++ dev_err(dev, "rumble setup failed!(err = %d)\n", error); ++ return error; ++ } ++ ++ dev_info(dev, "%s : probe success\n", __func__); ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static const struct of_device_id joypad_of_match[] = { ++ { .compatible = "rgb20s-joypad", }, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(of, joypad_of_match); ++ ++/*----------------------------------------------------------------------------*/ ++static struct platform_driver joypad_driver = { ++ .probe = joypad_probe, ++ .driver = { ++ .name = DRV_NAME, ++ .pm = &joypad_pm_ops, ++ .of_match_table = of_match_ptr(joypad_of_match), ++ }, ++}; ++ ++/*----------------------------------------------------------------------------*/ ++static int __init joypad_init(void) ++{ ++ return platform_driver_register(&joypad_driver); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static void __exit joypad_exit(void) ++{ ++ platform_driver_unregister(&joypad_driver); ++} ++ ++/*----------------------------------------------------------------------------*/ ++late_initcall(joypad_init); ++module_exit(joypad_exit); ++ ++/*----------------------------------------------------------------------------*/ ++MODULE_AUTHOR("Hardkernel Co.,LTD"); ++MODULE_DESCRIPTION("Keypad driver(ADC&GPIO) for Powkiddy RGB20S"); ++MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("platform:" DRV_NAME); ++ ++/*----------------------------------------------------------------------------*/ +diff --git a/drivers/input/joystick/xu10-joypad.c b/drivers/input/joystick/xu10-joypad.c +new file mode 100644 +index 000000000000..f7832a8158d4 +--- /dev/null ++++ b/drivers/input/joystick/xu10-joypad.c +@@ -0,0 +1,1139 @@ ++/* ++ * SARADC joystick & GPIO Button driver for Linux(Hardkernel MagicX-XU10) ++ */ ++/* ++ * 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 ++ * ++ * Should you need to contact me, the author, you can do so either by ++ * e-mail - mail your message to , or by paper mail: ++ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic ++ */ ++ ++/*----------------------------------------------------------------------------*/ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/*----------------------------------------------------------------------------*/ ++#define DRV_NAME "xu10_joypad" ++ ++/*----------------------------------------------------------------------------*/ ++#define ADC_MAX_VOLTAGE 1800 ++#define ADC_DATA_TUNING(x, p) ((x * p) / 100) ++#define ADC_TUNING_DEFAULT 180 ++ ++ ++/*----------------------------------------------------------------------------*/ ++struct bt_adc { ++ /* report value (mV) */ ++ int value; ++ /* report type */ ++ int report_type; ++ /* input device init value (mV) */ ++ int max, min; ++ /* calibrated adc value */ ++ int cal; ++ /* adc scale value */ ++ int scale; ++ /* invert report */ ++ bool invert; ++ /* amux channel */ ++ int amux_ch; ++ /* adc data tuning value([percent), p = positive, n = negative */ ++ int tuning_p, tuning_n; ++}; ++ ++struct analog_mux { ++ /* IIO ADC Channel : amux connect channel */ ++ struct iio_channel *iio_ch; ++ struct iio_channel *iio_ch_r; ++ /* analog mux select(a,b) gpio */ ++ int sel_a_gpio, sel_b_gpio; ++ /* analog mux enable gpio */ ++ int en_gpio; ++}; ++ ++struct bt_gpio { ++ /* GPIO Request label */ ++ const char *label; ++ /* GPIO Number */ ++ int num; ++ /* report type */ ++ int report_type; ++ /* report linux code */ ++ int linux_code; ++ /* prev button value */ ++ bool old_value; ++ /* button press level */ ++ bool active_level; ++}; ++ ++struct joypad { ++ struct device *dev; ++ int poll_interval; ++ ++ /* report enable/disable */ ++ bool enable; ++ ++ /* analog mux & joystick control */ ++ struct analog_mux *amux; ++ /* analog mux max count */ ++ int amux_count; ++ /* analog button */ ++ struct bt_adc *adcs; ++ ++ /* report reference point */ ++ bool invert_absx; ++ bool invert_absy; ++ bool invert_absrx; ++ bool invert_absry; ++ ++ /* report interval (ms) */ ++ int bt_gpio_count; ++ struct bt_gpio *gpios; ++ ++ /* button auto repeat */ ++ int auto_repeat; ++ ++ /* report threshold (mV) */ ++ int bt_adc_fuzz, bt_adc_flat; ++ /* adc read value scale */ ++ int bt_adc_scale; ++ /* joystick deadzone control */ ++ int bt_adc_deadzone; ++ ++ struct mutex lock; ++ ++ /* amux debug channel */ ++ int debug_ch; ++}; ++ ++/*----------------------------------------------------------------------------*/ ++// ++// set to the value in the boot.ini file. (if exist) ++// ++/*----------------------------------------------------------------------------*/ ++static unsigned int g_button_adc_fuzz = 0; ++static unsigned int g_button_adc_flat = 0; ++static unsigned int g_button_adc_scale = 0; ++static unsigned int g_button_adc_deadzone = 0; ++ ++static int button_adc_fuzz(char *str) ++{ ++ if (!str) ++ return -EINVAL; ++ g_button_adc_fuzz = simple_strtoul(str, NULL, 10); ++ return 0; ++} ++__setup("button-adc-fuzz=", button_adc_fuzz); ++ ++static int button_adc_flat(char *str) ++{ ++ if (!str) ++ return -EINVAL; ++ g_button_adc_flat = simple_strtoul(str, NULL, 10); ++ return 0; ++} ++__setup("button-adc-flat=", button_adc_flat); ++ ++static int button_adc_scale(char *str) ++{ ++ if (!str) ++ return -EINVAL; ++ g_button_adc_scale = simple_strtoul(str, NULL, 10); ++ return 0; ++} ++__setup("button-adc-scale=", button_adc_scale); ++ ++static int button_adc_deadzone(char *str) ++{ ++ if (!str) ++ return -EINVAL; ++ g_button_adc_deadzone = simple_strtoul(str, NULL, 10); ++ return 0; ++} ++__setup("button-adc-deadzone=", button_adc_deadzone); ++ ++/*----------------------------------------------------------------------------*/ ++/*----------------------------------------------------------------------------*/ ++static int joypad_amux_select(struct analog_mux *amux, int channel) ++{ ++ /* select mux channel */ ++ gpio_set_value(amux->en_gpio, 0); ++ ++ switch(channel) { ++ case 0: /* EVENT (ABS_RY) */ ++ gpio_set_value(amux->sel_a_gpio, 0); ++ gpio_set_value(amux->sel_b_gpio, 0); ++ break; ++ case 1: /* EVENT (ABS_RX) */ ++ gpio_set_value(amux->sel_a_gpio, 1); ++ gpio_set_value(amux->sel_b_gpio, 1); ++ break; ++ case 2: /* EVENT (ABS_Y) */ ++ gpio_set_value(amux->sel_a_gpio, 0); ++ gpio_set_value(amux->sel_b_gpio, 0); ++ break; ++ case 3: /* EVENT (ABS_X) */ ++ gpio_set_value(amux->sel_a_gpio, 1); ++ gpio_set_value(amux->sel_b_gpio, 1); ++ break; ++ default: ++ /* amux disable */ ++ gpio_set_value(amux->en_gpio, 1); ++ return -1; ++ } ++ /* mux swtiching speed : 35ns(on) / 9ns(off) */ ++ usleep_range(1, 2); ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static int joypad_adc_read(struct analog_mux *amux, struct bt_adc *adc) ++{ ++ int value; ++ int res; ++ ++ if (joypad_amux_select(amux, adc->amux_ch)) ++ return 0; ++ ++ switch(adc->amux_ch) { ++ case 0: ++ case 1: ++ res = iio_read_channel_processed(amux->iio_ch_r, &value); ++ break; ++ case 2: ++ case 3: ++ default: ++ res = iio_read_channel_processed(amux->iio_ch, &value); ++ break; ++ } ++ ++ if (res) ++ return 0; ++ ++ value *= adc->scale; ++ ++ return value; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*----------------------------------------------------------------------------*/ ++/* ++ * ATTRIBUTES: ++ * ++ * /sys/devices/platform/odroidgo2_joypad/poll_interval [rw] ++ */ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_store_poll_interval(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, ++ size_t count) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ mutex_lock(&joypad->lock); ++ joypad->poll_interval = simple_strtoul(buf, NULL, 10); ++ mutex_unlock(&joypad->lock); ++ ++ return count; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_show_poll_interval(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ return sprintf(buf, "%d\n", joypad->poll_interval); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static DEVICE_ATTR(poll_interval, S_IWUSR | S_IRUGO, ++ joypad_show_poll_interval, ++ joypad_store_poll_interval); ++ ++/*----------------------------------------------------------------------------*/ ++/* ++ * ATTRIBUTES: ++ * ++ * /sys/devices/platform/odroidgo2_joypad/adc_fuzz [r] ++ */ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_show_adc_fuzz(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ return sprintf(buf, "%d\n", joypad->bt_adc_fuzz); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static DEVICE_ATTR(adc_fuzz, S_IWUSR | S_IRUGO, ++ joypad_show_adc_fuzz, ++ NULL); ++ ++/*----------------------------------------------------------------------------*/ ++/* ++ * ATTRIBUTES: ++ * ++ * /sys/devices/platform/odroidgo2_joypad/adc_flat [r] ++ */ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_show_adc_flat(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ return sprintf(buf, "%d\n", joypad->bt_adc_flat); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static DEVICE_ATTR(adc_flat, S_IWUSR | S_IRUGO, ++ joypad_show_adc_flat, ++ NULL); ++ ++/*----------------------------------------------------------------------------*/ ++/* ++ * ATTRIBUTES: ++ * ++ * /sys/devices/platform/odroidgo2_joypad/enable [rw] ++ */ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_store_enable(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, ++ size_t count) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ mutex_lock(&joypad->lock); ++ joypad->enable = simple_strtoul(buf, NULL, 10); ++ mutex_unlock(&joypad->lock); ++ ++ return count; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_show_enable(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ return sprintf(buf, "%d\n", joypad->enable); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO, ++ joypad_show_enable, ++ joypad_store_enable); ++ ++/*----------------------------------------------------------------------------*/ ++/* ++ * ATTRIBUTES: ++ * ++ * /sys/devices/platform/odroidgo2_joypad/adc_cal [rw] ++ */ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_store_adc_cal(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, ++ size_t count) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ bool calibration; ++ ++ calibration = simple_strtoul(buf, NULL, 10); ++ ++ if (calibration) { ++ int nbtn; ++ ++ mutex_lock(&joypad->lock); ++ for (nbtn = 0; nbtn < joypad->amux_count; nbtn++) { ++ struct bt_adc *adc = &joypad->adcs[nbtn]; ++ ++ adc->value = joypad_adc_read(joypad->amux, adc); ++ if (!adc->value) { ++ dev_err(joypad->dev, "%s : saradc channels[%d]!\n", ++ __func__, nbtn); ++ continue; ++ } ++ adc->cal = adc->value; ++ } ++ mutex_unlock(&joypad->lock); ++ } ++ return count; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_show_adc_cal(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ int nbtn; ++ ssize_t pos; ++ ++ for (nbtn = 0, pos = 0; nbtn < joypad->amux_count; nbtn++) { ++ struct bt_adc *adc = &joypad->adcs[nbtn]; ++ pos += sprintf(&buf[pos], "adc[%d]->cal = %d\n", ++ nbtn, adc->cal); ++ } ++ pos += sprintf(&buf[pos], "adc scale = %d\n", joypad->bt_adc_scale); ++ return pos; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static DEVICE_ATTR(adc_cal, S_IWUSR | S_IRUGO, ++ joypad_show_adc_cal, ++ joypad_store_adc_cal); ++ ++/*----------------------------------------------------------------------------*/ ++/* ++ * ATTRIBUTES: ++ * ++ * /sys/devices/platform/odroidgo2_joypad/amux_debug [rw] ++ * ++ * echo [debug channel] > amux_debug ++ * cat amux_debug : debug channel mux set & adc read ++ */ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_store_amux_debug(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, ++ size_t count) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ ++ joypad->debug_ch = simple_strtoul(buf, NULL, 10); ++ ++ /* if error than default setting(debug_ch = 0) */ ++ if (joypad->debug_ch > joypad->amux_count) ++ joypad->debug_ch = 0; ++ ++ return count; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static ssize_t joypad_show_amux_debug(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct joypad *joypad = platform_get_drvdata(pdev); ++ struct analog_mux *amux = joypad->amux; ++ ssize_t pos; ++ int value; ++ int res; ++ ++ mutex_lock(&joypad->lock); ++ ++ /* disable poll driver */ ++ if (joypad->enable) ++ joypad->enable = false; ++ ++ if (joypad_amux_select(amux, joypad->debug_ch)) ++ goto err_out; ++ ++ switch(joypad->debug_ch) { ++ case 0: ++ case 1: ++ res = iio_read_channel_processed(amux->iio_ch_r, &value); ++ break; ++ case 2: ++ case 3: ++ default: ++ res = iio_read_channel_processed(amux->iio_ch, &value); ++ break; ++ } ++ ++ if (res) ++ goto err_out; ++ ++ pos = sprintf(buf, "amux ch[%d], adc scale = %d, adc value = %d\n", ++ joypad->debug_ch, joypad->bt_adc_scale, ++ value * joypad->bt_adc_scale); ++ goto out; ++ ++err_out: ++ pos = sprintf(buf, "error : amux setup & adc read!\n"); ++out: ++ mutex_unlock(&joypad->lock); ++ return pos; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static DEVICE_ATTR(amux_debug, S_IWUSR | S_IRUGO, ++ joypad_show_amux_debug, ++ joypad_store_amux_debug); ++ ++/*----------------------------------------------------------------------------*/ ++/*----------------------------------------------------------------------------*/ ++static struct attribute *joypad_attrs[] = { ++ &dev_attr_poll_interval.attr, ++ &dev_attr_adc_fuzz.attr, ++ &dev_attr_adc_flat.attr, ++ &dev_attr_enable.attr, ++ &dev_attr_adc_cal.attr, ++ &dev_attr_amux_debug.attr, ++ NULL, ++}; ++ ++static struct attribute_group joypad_attr_group = { ++ .attrs = joypad_attrs, ++}; ++ ++/*----------------------------------------------------------------------------*/ ++/*----------------------------------------------------------------------------*/ ++static void joypad_gpio_check(struct input_polled_dev *poll_dev) ++{ ++ struct joypad *joypad = poll_dev->private; ++ int nbtn, value; ++ ++ for (nbtn = 0; nbtn < joypad->bt_gpio_count; nbtn++) { ++ struct bt_gpio *gpio = &joypad->gpios[nbtn]; ++ ++ if (gpio_get_value_cansleep(gpio->num) < 0) { ++ dev_err(joypad->dev, "failed to get gpio state\n"); ++ continue; ++ } ++ value = gpio_get_value(gpio->num); ++ if (value != gpio->old_value) { ++ input_event(poll_dev->input, ++ gpio->report_type, ++ gpio->linux_code, ++ (value == gpio->active_level) ? 1 : 0); ++ gpio->old_value = value; ++ } ++ } ++ input_sync(poll_dev->input); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static void joypad_adc_check(struct input_polled_dev *poll_dev) ++{ ++ struct joypad *joypad = poll_dev->private; ++ int nbtn; ++ ++ for (nbtn = 0; nbtn < joypad->amux_count; nbtn++) { ++ struct bt_adc *adc = &joypad->adcs[nbtn]; ++ ++ adc->value = joypad_adc_read(joypad->amux, adc); ++ if (!adc->value) { ++ dev_err(joypad->dev, "%s : saradc channels[%d]!\n", ++ __func__, nbtn); ++ continue; ++ } ++ adc->value = adc->value - adc->cal; ++ ++ /* Joystick Deadzone check */ ++ if (joypad->bt_adc_deadzone) { ++ if (abs(adc->value) < joypad->bt_adc_deadzone) ++ adc->value = 0; ++ } ++ ++ /* adc data tuning */ ++ if (adc->tuning_n && adc->value < 0) ++ adc->value = ADC_DATA_TUNING(adc->value, adc->tuning_n); ++ if (adc->tuning_p && adc->value > 0) ++ adc->value = ADC_DATA_TUNING(adc->value, adc->tuning_p); ++ ++ adc->value = adc->value > adc->max ? adc->max : adc->value; ++ adc->value = adc->value < adc->min ? adc->min : adc->value; ++ ++ input_report_abs(poll_dev->input, ++ adc->report_type, ++ adc->invert ? adc->value * (-1) : adc->value); ++ } ++ input_sync(poll_dev->input); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static void joypad_poll(struct input_polled_dev *poll_dev) ++{ ++ struct joypad *joypad = poll_dev->private; ++ ++ if (joypad->enable) { ++ joypad_adc_check(poll_dev); ++ joypad_gpio_check(poll_dev); ++ } ++ if (poll_dev->poll_interval != joypad->poll_interval) { ++ mutex_lock(&joypad->lock); ++ poll_dev->poll_interval = joypad->poll_interval; ++ mutex_unlock(&joypad->lock); ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++static void joypad_open(struct input_polled_dev *poll_dev) ++{ ++ struct joypad *joypad = poll_dev->private; ++ int nbtn; ++ ++ for (nbtn = 0; nbtn < joypad->bt_gpio_count; nbtn++) { ++ struct bt_gpio *gpio = &joypad->gpios[nbtn]; ++ gpio->old_value = gpio->active_level ? 0 : 1; ++ } ++ for (nbtn = 0; nbtn < joypad->amux_count; nbtn++) { ++ struct bt_adc *adc = &joypad->adcs[nbtn]; ++ ++ adc->value = joypad_adc_read(joypad->amux, adc); ++ if (!adc->value) { ++ dev_err(joypad->dev, "%s : saradc channels[%d]!\n", ++ __func__, nbtn); ++ continue; ++ } ++ adc->cal = adc->value; ++ dev_info(joypad->dev, "%s : adc[%d] adc->cal = %d\n", ++ __func__, nbtn, adc->cal); ++ } ++ /* buttons status sync */ ++ joypad_adc_check(poll_dev); ++ joypad_gpio_check(poll_dev); ++ ++ /* button report enable */ ++ mutex_lock(&joypad->lock); ++ joypad->enable = true; ++ mutex_unlock(&joypad->lock); ++ ++ dev_info(joypad->dev, "%s : opened\n", __func__); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static void joypad_close(struct input_polled_dev *poll_dev) ++{ ++ struct joypad *joypad = poll_dev->private; ++ ++ /* button report disable */ ++ mutex_lock(&joypad->lock); ++ joypad->enable = false; ++ mutex_unlock(&joypad->lock); ++ ++ dev_info(joypad->dev, "%s : closed\n", __func__); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static int joypad_amux_setup(struct device *dev, struct joypad *joypad) ++{ ++ struct analog_mux *amux; ++ enum iio_chan_type type; ++ enum of_gpio_flags flags; ++ int ret; ++ ++ /* analog mux control struct init */ ++ joypad->amux = devm_kzalloc(dev, sizeof(struct analog_mux), ++ GFP_KERNEL); ++ if (!joypad->amux) { ++ dev_err(dev, "%s amux devm_kzmalloc error!", __func__); ++ return -ENOMEM; ++ } ++ amux = joypad->amux; ++ amux->iio_ch = devm_iio_channel_get(dev, "joy_left"); ++ amux->iio_ch_r = devm_iio_channel_get(dev, "joy_right"); ++ ++ if (IS_ERR(amux->iio_ch)) { ++ dev_err(dev, "iio channel get error\n"); ++ return -EINVAL; ++ } ++ ++ if (IS_ERR(amux->iio_ch_r)) { ++ dev_err(dev, "iio channel right get error\n"); ++ return -EINVAL; ++ } ++ ++ if (!amux->iio_ch->indio_dev || !amux->iio_ch_r->indio_dev) ++ return -ENXIO; ++ ++ if (iio_get_channel_type(amux->iio_ch, &type)) ++ return -EINVAL; ++ ++ if (type != IIO_VOLTAGE) { ++ dev_err(dev, "Incompatible channel type %d\n", type); ++ return -EINVAL; ++ } ++ ++ if (iio_get_channel_type(amux->iio_ch_r, &type)) ++ return -EINVAL; ++ ++ if (type != IIO_VOLTAGE) { ++ dev_err(dev, "Incompatible channel type %d\n", type); ++ return -EINVAL; ++ } ++ ++ amux->sel_a_gpio = of_get_named_gpio_flags(dev->of_node, ++ "amux-a-gpios", 0, &flags); ++ if (gpio_is_valid(amux->sel_a_gpio)) { ++ ret = devm_gpio_request(dev, amux->sel_a_gpio, "amux-sel-a"); ++ if (ret < 0) { ++ dev_err(dev, "%s : failed to request amux-sel-a %d\n", ++ __func__, amux->sel_a_gpio); ++ goto err_out; ++ } ++ ret = gpio_direction_output(amux->sel_a_gpio, 0); ++ if (ret < 0) ++ goto err_out; ++ } ++ ++ amux->sel_b_gpio = of_get_named_gpio_flags(dev->of_node, ++ "amux-b-gpios", 0, &flags); ++ if (gpio_is_valid(amux->sel_b_gpio)) { ++ ret = devm_gpio_request(dev, amux->sel_b_gpio, "amux-sel-b"); ++ if (ret < 0) { ++ dev_err(dev, "%s : failed to request amux-sel-b %d\n", ++ __func__, amux->sel_b_gpio); ++ goto err_out; ++ } ++ ret = gpio_direction_output(amux->sel_b_gpio, 0); ++ if (ret < 0) ++ goto err_out; ++ } ++ ++ amux->en_gpio = of_get_named_gpio_flags(dev->of_node, ++ "amux-en-gpios", 0, &flags); ++ if (gpio_is_valid(amux->en_gpio)) { ++ ret = devm_gpio_request(dev, amux->en_gpio, "amux-en"); ++ if (ret < 0) { ++ dev_err(dev, "%s : failed to request amux-en %d\n", ++ __func__, amux->en_gpio); ++ goto err_out; ++ } ++ ret = gpio_direction_output(amux->en_gpio, 0); ++ if (ret < 0) ++ goto err_out; ++ } ++ return 0; ++err_out: ++ return ret; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static int joypad_adc_setup(struct device *dev, struct joypad *joypad) ++{ ++ int nbtn; ++ ++ /* adc button struct init */ ++ joypad->adcs = devm_kzalloc(dev, joypad->amux_count * ++ sizeof(struct bt_adc), GFP_KERNEL); ++ if (!joypad->adcs) { ++ dev_err(dev, "%s devm_kzmalloc error!", __func__); ++ return -ENOMEM; ++ } ++ ++ for (nbtn = 0; nbtn < joypad->amux_count; nbtn++) { ++ struct bt_adc *adc = &joypad->adcs[nbtn]; ++ ++ adc->scale = joypad->bt_adc_scale; ++ ++ adc->max = (ADC_MAX_VOLTAGE / 2); ++ adc->min = (ADC_MAX_VOLTAGE / 2) * (-1); ++ if (adc->scale) { ++ adc->max *= adc->scale; ++ adc->min *= adc->scale; ++ } ++ adc->amux_ch = nbtn; ++ adc->invert = false; ++ ++ switch (nbtn) { ++ case 0: ++ if (joypad->invert_absry) ++ adc->invert = true; ++ adc->report_type = ABS_RY; ++ if (device_property_read_u32(dev, ++ "abs_ry-p-tuning", ++ &adc->tuning_p)) ++ adc->tuning_p = ADC_TUNING_DEFAULT; ++ if (device_property_read_u32(dev, ++ "abs_ry-n-tuning", ++ &adc->tuning_n)) ++ adc->tuning_n = ADC_TUNING_DEFAULT; ++ break; ++ case 1: ++ if (joypad->invert_absrx) ++ adc->invert = true; ++ adc->report_type = ABS_RX; ++ if (device_property_read_u32(dev, ++ "abs_rx-p-tuning", ++ &adc->tuning_p)) ++ adc->tuning_p = ADC_TUNING_DEFAULT; ++ if (device_property_read_u32(dev, ++ "abs_rx-n-tuning", ++ &adc->tuning_n)) ++ adc->tuning_n = ADC_TUNING_DEFAULT; ++ break; ++ case 2: ++ if (joypad->invert_absy) ++ adc->invert = true; ++ adc->report_type = ABS_Y; ++ if (device_property_read_u32(dev, ++ "abs_y-p-tuning", ++ &adc->tuning_p)) ++ adc->tuning_p = ADC_TUNING_DEFAULT; ++ if (device_property_read_u32(dev, ++ "abs_y-n-tuning", ++ &adc->tuning_n)) ++ adc->tuning_n = ADC_TUNING_DEFAULT; ++ break; ++ case 3: ++ if (joypad->invert_absx) ++ adc->invert = true; ++ adc->report_type = ABS_X; ++ if (device_property_read_u32(dev, ++ "abs_x-p-tuning", ++ &adc->tuning_p)) ++ adc->tuning_p = ADC_TUNING_DEFAULT; ++ if (device_property_read_u32(dev, ++ "abs_x-n-tuning", ++ &adc->tuning_n)) ++ adc->tuning_n = ADC_TUNING_DEFAULT; ++ break; ++ default : ++ dev_err(dev, "%s amux count(%d) error!", ++ __func__, nbtn); ++ return -EINVAL; ++ } ++ } ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static int joypad_gpio_setup(struct device *dev, struct joypad *joypad) ++{ ++ struct device_node *node, *pp; ++ int nbtn; ++ ++ node = dev->of_node; ++ if (!node) ++ return -ENODEV; ++ ++ joypad->gpios = devm_kzalloc(dev, joypad->bt_gpio_count * ++ sizeof(struct bt_gpio), GFP_KERNEL); ++ ++ if (!joypad->gpios) { ++ dev_err(dev, "%s devm_kzmalloc error!", __func__); ++ return -ENOMEM; ++ } ++ ++ nbtn = 0; ++ for_each_child_of_node(node, pp) { ++ enum of_gpio_flags flags; ++ struct bt_gpio *gpio = &joypad->gpios[nbtn++]; ++ int error; ++ ++ gpio->num = of_get_gpio_flags(pp, 0, &flags); ++ if (gpio->num < 0) { ++ error = gpio->num; ++ dev_err(dev, "Failed to get gpio flags, error: %d\n", ++ error); ++ return error; ++ } ++ ++ /* gpio active level(key press level) */ ++ gpio->active_level = (flags & OF_GPIO_ACTIVE_LOW) ? 0 : 1; ++ ++ gpio->label = of_get_property(pp, "label", NULL); ++ ++ if (gpio_is_valid(gpio->num)) { ++ error = devm_gpio_request_one(dev, gpio->num, ++ GPIOF_IN, gpio->label); ++ if (error < 0) { ++ dev_err(dev, ++ "Failed to request GPIO %d, error %d\n", ++ gpio->num, error); ++ return error; ++ } ++ } ++ if (of_property_read_u32(pp, "linux,code", &gpio->linux_code)) { ++ dev_err(dev, "Button without keycode: 0x%x\n", ++ gpio->num); ++ return -EINVAL; ++ } ++ if (of_property_read_u32(pp, "linux,input-type", ++ &gpio->report_type)) ++ gpio->report_type = EV_KEY; ++ } ++ if (nbtn == 0) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static int joypad_input_setup(struct device *dev, struct joypad *joypad) ++{ ++ struct input_polled_dev *poll_dev; ++ struct input_dev *input; ++ int nbtn, error; ++ u32 joypad_product = 0; ++ u32 joypad_revision = 0; ++ ++ poll_dev = devm_input_allocate_polled_device(dev); ++ if (!poll_dev) { ++ dev_err(dev, "no memory for polled device\n"); ++ return -ENOMEM; ++ } ++ ++ poll_dev->private = joypad; ++ poll_dev->poll = joypad_poll; ++ poll_dev->poll_interval = joypad->poll_interval; ++ poll_dev->open = joypad_open; ++ poll_dev->close = joypad_close; ++ ++ input = poll_dev->input; ++ ++ device_property_read_string(dev, "joypad-name", &input->name); ++ input->phys = DRV_NAME"/input0"; ++ ++ device_property_read_u32(dev, "joypad-product", &joypad_product); ++ device_property_read_u32(dev, "joypad-revision", &joypad_revision); ++ ++ input->id.bustype = BUS_HOST; ++ input->id.vendor = 0xC3B0; ++ input->id.product = (u16)joypad_product; ++ input->id.version = (u16)joypad_revision; ++ ++ /* IIO ADC key setup (0 mv ~ 1800 mv) * adc->scale */ ++ __set_bit(EV_ABS, input->evbit); ++ for(nbtn = 0; nbtn < joypad->amux_count; nbtn++) { ++ struct bt_adc *adc = &joypad->adcs[nbtn]; ++ input_set_abs_params(input, adc->report_type, ++ adc->min, adc->max, ++ joypad->bt_adc_fuzz, ++ joypad->bt_adc_flat); ++ dev_info(dev, ++ "%s : SCALE = %d, ABS min = %d, max = %d," ++ " fuzz = %d, flat = %d, deadzone = %d\n", ++ __func__, adc->scale, adc->min, adc->max, ++ joypad->bt_adc_fuzz, joypad->bt_adc_flat, ++ joypad->bt_adc_deadzone); ++ dev_info(dev, ++ "%s : adc tuning_p = %d, adc_tuning_n = %d\n\n", ++ __func__, adc->tuning_p, adc->tuning_n); ++ } ++ ++ /* GPIO key setup */ ++ __set_bit(EV_KEY, input->evbit); ++ for(nbtn = 0; nbtn < joypad->bt_gpio_count; nbtn++) { ++ struct bt_gpio *gpio = &joypad->gpios[nbtn]; ++ input_set_capability(input, gpio->report_type, ++ gpio->linux_code); ++ } ++ ++ if (joypad->auto_repeat) ++ __set_bit(EV_REP, input->evbit); ++ ++ joypad->dev = dev; ++ ++ error = input_register_polled_device(poll_dev); ++ if (error) { ++ dev_err(dev, "unable to register polled device, err=%d\n", ++ error); ++ return error; ++ } ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static void joypad_setup_value_check(struct device *dev, struct joypad *joypad) ++{ ++ /* ++ fuzz: specifies fuzz value that is used to filter noise from ++ the event stream. ++ */ ++ if (g_button_adc_fuzz) ++ joypad->bt_adc_fuzz = g_button_adc_fuzz; ++ else ++ device_property_read_u32(dev, "button-adc-fuzz", ++ &joypad->bt_adc_fuzz); ++ /* ++ flat: values that are within this value will be discarded by ++ joydev interface and reported as 0 instead. ++ */ ++ if (g_button_adc_flat) ++ joypad->bt_adc_flat = g_button_adc_flat; ++ else ++ device_property_read_u32(dev, "button-adc-flat", ++ &joypad->bt_adc_flat); ++ ++ /* Joystick report value control */ ++ if (g_button_adc_scale) ++ joypad->bt_adc_scale = g_button_adc_scale; ++ else ++ device_property_read_u32(dev, "button-adc-scale", ++ &joypad->bt_adc_scale); ++ ++ /* Joystick deadzone value control */ ++ if (g_button_adc_deadzone) ++ joypad->bt_adc_deadzone = g_button_adc_deadzone; ++ else ++ device_property_read_u32(dev, "button-adc-deadzone", ++ &joypad->bt_adc_deadzone); ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++static int joypad_dt_parse(struct device *dev, struct joypad *joypad) ++{ ++ int error = 0; ++ ++ /* initialize value check from boot.ini */ ++ joypad_setup_value_check(dev, joypad); ++ ++ device_property_read_u32(dev, "amux-count", ++ &joypad->amux_count); ++ ++ device_property_read_u32(dev, "poll-interval", ++ &joypad->poll_interval); ++ ++ joypad->auto_repeat = device_property_present(dev, "autorepeat"); ++ ++ /* change the report reference point? (read value * -1) */ ++ joypad->invert_absx = device_property_present(dev, "invert-absx"); ++ joypad->invert_absy = device_property_present(dev, "invert-absy"); ++ joypad->invert_absrx = device_property_present(dev, "invert-absrx"); ++ joypad->invert_absry = device_property_present(dev, "invert-absry"); ++ dev_info(dev, "%s : invert-absx = %d, inveret-absy = %d, invert-absrx = %d, invert-absry = %d\n", ++ __func__, joypad->invert_absx, joypad->invert_absy, joypad->invert_absrx, joypad->invert_absry); ++ ++ joypad->bt_gpio_count = device_get_child_node_count(dev); ++ ++ if ((joypad->amux_count == 0) || (joypad->bt_gpio_count == 0)) { ++ dev_err(dev, "adc key = %d, gpio key = %d error!", ++ joypad->amux_count, joypad->bt_gpio_count); ++ return -EINVAL; ++ } ++ ++ error = joypad_adc_setup(dev, joypad); ++ if (error) ++ return error; ++ ++ error = joypad_amux_setup(dev, joypad); ++ if (error) ++ return error; ++ ++ error = joypad_gpio_setup(dev, joypad); ++ if (error) ++ return error; ++ ++ dev_info(dev, "%s : adc key cnt = %d, gpio key cnt = %d\n", ++ __func__, joypad->amux_count, joypad->bt_gpio_count); ++ ++ return error; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static int joypad_probe(struct platform_device *pdev) ++{ ++ struct joypad *joypad; ++ struct device *dev = &pdev->dev; ++ int error; ++ ++ joypad = devm_kzalloc(dev, sizeof(struct joypad), GFP_KERNEL); ++ if (!joypad) { ++ dev_err(dev, "joypad devm_kzmalloc error!"); ++ return -ENOMEM; ++ } ++ ++ /* device tree data parse */ ++ error = joypad_dt_parse(dev, joypad); ++ if (error) { ++ dev_err(dev, "dt parse error!(err = %d)\n", error); ++ return error; ++ } ++ ++ mutex_init(&joypad->lock); ++ platform_set_drvdata(pdev, joypad); ++ ++ error = sysfs_create_group(&pdev->dev.kobj, &joypad_attr_group); ++ if (error) { ++ dev_err(dev, "create sysfs group fail, error: %d\n", ++ error); ++ return error; ++ } ++ ++ /* poll input device setup */ ++ error = joypad_input_setup(dev, joypad); ++ if (error) { ++ dev_err(dev, "input setup failed!(err = %d)\n", error); ++ return error; ++ } ++ dev_info(dev, "%s : probe success\n", __func__); ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++static const struct of_device_id joypad_of_match[] = { ++ { .compatible = "xu10-joypad", }, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(of, joypad_of_match); ++ ++/*----------------------------------------------------------------------------*/ ++static struct platform_driver joypad_driver = { ++ .probe = joypad_probe, ++ .driver = { ++ .name = DRV_NAME, ++ .of_match_table = of_match_ptr(joypad_of_match), ++ }, ++}; ++ ++/*----------------------------------------------------------------------------*/ ++static int __init joypad_init(void) ++{ ++ return platform_driver_register(&joypad_driver); ++} ++ ++/*----------------------------------------------------------------------------*/ ++static void __exit joypad_exit(void) ++{ ++ platform_driver_unregister(&joypad_driver); ++} ++ ++/*----------------------------------------------------------------------------*/ ++late_initcall(joypad_init); ++module_exit(joypad_exit); ++ ++/*----------------------------------------------------------------------------*/ ++MODULE_AUTHOR("Hardkernel Co.,LTD"); ++MODULE_DESCRIPTION("Keypad driver(ADC&GPIO) for MagicX-XU10"); ++MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("platform:" DRV_NAME); ++ ++/*----------------------------------------------------------------------------*/ diff --git a/projects/ArchR/devices/RK3326/patches/linux/005-unigue-gpio-guid.patch b/projects/ArchR/devices/RK3326/patches/linux/005-unigue-gpio-guid.patch new file mode 100644 index 0000000000..92cce0e352 --- /dev/null +++ b/projects/ArchR/devices/RK3326/patches/linux/005-unigue-gpio-guid.patch @@ -0,0 +1,14 @@ +diff -rupN linux.orig/drivers/input/keyboard/gpio_keys.c linux/drivers/input/keyboard/gpio_keys.c +--- linux.orig/drivers/input/keyboard/gpio_keys.c 2024-01-25 20:47:47.094097973 +0000 ++++ linux/drivers/input/keyboard/gpio_keys.c 2024-01-26 04:17:54.663672057 +0000 +@@ -847,8 +847,8 @@ static int gpio_keys_probe(struct platfo + + input->id.bustype = BUS_HOST; + input->id.vendor = 0x0001; +- input->id.product = 0x0001; +- input->id.version = 0x0100; ++ input->id.product = 0x7891; ++ input->id.version = 0x0500; + + input->keycode = ddata->keymap; + input->keycodesize = sizeof(ddata->keymap[0]); diff --git a/projects/ArchR/devices/RK3326/patches/linux/007-ogs-panel-timings.patch b/projects/ArchR/devices/RK3326/patches/linux/007-ogs-panel-timings.patch new file mode 100644 index 0000000000..c440a804de --- /dev/null +++ b/projects/ArchR/devices/RK3326/patches/linux/007-ogs-panel-timings.patch @@ -0,0 +1,32 @@ +diff -rupbN linux.orig/drivers/gpu/drm/panel/panel-sitronix-st7701.c linux/drivers/gpu/drm/panel/panel-sitronix-st7701.c +--- linux.orig/drivers/gpu/drm/panel/panel-sitronix-st7701.c 2025-01-09 12:33:55.000000000 +0000 ++++ linux/drivers/gpu/drm/panel/panel-sitronix-st7701.c 2025-01-15 14:14:08.794990319 +0000 +@@ -838,20 +838,20 @@ static const struct st7701_panel_desc dm + }; + + static const struct drm_display_mode kd50t048a_mode = { +- .clock = 27500, ++ .clock = 29170, + + .hdisplay = 480, +- .hsync_start = 480 + 2, +- .hsync_end = 480 + 2 + 10, +- .htotal = 480 + 2 + 10 + 2, ++ .hsync_start = 480 + 12, ++ .hsync_end = 480 + 12 + 12, ++ .htotal = 480 + 12 + 12 + 38, + + .vdisplay = 854, + .vsync_start = 854 + 2, +- .vsync_end = 854 + 2 + 2, +- .vtotal = 854 + 2 + 2 + 17, ++ .vsync_end = 854 + 2 + 19, ++ .vtotal = 854 + 2 + 19 + 22, + +- .width_mm = 69, +- .height_mm = 139, ++ .width_mm = 70, ++ .height_mm = 140, + + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, + }; diff --git a/projects/ArchR/devices/RK3326/patches/linux/008-esp-8089-wifi.patch b/projects/ArchR/devices/RK3326/patches/linux/008-esp-8089-wifi.patch new file mode 100644 index 0000000000..1ca6266df0 --- /dev/null +++ b/projects/ArchR/devices/RK3326/patches/linux/008-esp-8089-wifi.patch @@ -0,0 +1,10933 @@ +From 2d6165af6e9d5ed5026cdf250536c0a00d84fd75 Mon Sep 17 00:00:00 2001 +From: Paolo Sabatino +Date: Sat, 1 Oct 2022 12:43:53 +0000 +Subject: [PATCH] add esp8089 kernel driver + +--- + drivers/net/wireless/Kconfig | 1 + + drivers/net/wireless/Makefile | 1 + + drivers/net/wireless/esp8089/.gitignore | 7 + + drivers/net/wireless/esp8089/Kconfig | 13 + + drivers/net/wireless/esp8089/LICENSE | 340 +++ + drivers/net/wireless/esp8089/Makefile | 7 + + drivers/net/wireless/esp8089/Makefile.old | 99 + + drivers/net/wireless/esp8089/README.md | 31 + + drivers/net/wireless/esp8089/esp_ctrl.c | 801 ++++++ + drivers/net/wireless/esp8089/esp_ctrl.h | 58 + + drivers/net/wireless/esp8089/esp_debug.c | 297 ++ + drivers/net/wireless/esp8089/esp_debug.h | 101 + + drivers/net/wireless/esp8089/esp_ext.c | 542 ++++ + drivers/net/wireless/esp8089/esp_ext.h | 100 + + drivers/net/wireless/esp8089/esp_file.c | 258 ++ + drivers/net/wireless/esp8089/esp_file.h | 43 + + drivers/net/wireless/esp8089/esp_init_data.h | 7 + + drivers/net/wireless/esp8089/esp_io.c | 639 +++++ + drivers/net/wireless/esp8089/esp_mac80211.c | 1727 ++++++++++++ + drivers/net/wireless/esp8089/esp_mac80211.h | 38 + + drivers/net/wireless/esp8089/esp_main.c | 263 ++ + drivers/net/wireless/esp8089/esp_path.h | 6 + + drivers/net/wireless/esp8089/esp_pub.h | 222 ++ + drivers/net/wireless/esp8089/esp_sif.h | 207 ++ + drivers/net/wireless/esp8089/esp_sip.c | 2418 +++++++++++++++++ + drivers/net/wireless/esp8089/esp_sip.h | 171 ++ + drivers/net/wireless/esp8089/esp_utils.c | 262 ++ + drivers/net/wireless/esp8089/esp_utils.h | 41 + + drivers/net/wireless/esp8089/esp_version.h | 1 + + drivers/net/wireless/esp8089/esp_wl.h | 63 + + drivers/net/wireless/esp8089/esp_wmac.h | 92 + + .../wireless/esp8089/firmware/LICENSE-2.0.txt | 203 ++ + drivers/net/wireless/esp8089/sdio_sif_esp.c | 811 ++++++ + drivers/net/wireless/esp8089/sip2_common.h | 475 ++++ + .../net/wireless/esp8089/slc_host_register.h | 271 ++ + 35 files changed, 10616 insertions(+) + create mode 100644 drivers/net/wireless/esp8089/.gitignore + create mode 100644 drivers/net/wireless/esp8089/Kconfig + create mode 100644 drivers/net/wireless/esp8089/LICENSE + create mode 100644 drivers/net/wireless/esp8089/Makefile + create mode 100644 drivers/net/wireless/esp8089/Makefile.old + create mode 100644 drivers/net/wireless/esp8089/README.md + create mode 100644 drivers/net/wireless/esp8089/esp_ctrl.c + create mode 100644 drivers/net/wireless/esp8089/esp_ctrl.h + create mode 100644 drivers/net/wireless/esp8089/esp_debug.c + create mode 100644 drivers/net/wireless/esp8089/esp_debug.h + create mode 100644 drivers/net/wireless/esp8089/esp_ext.c + create mode 100644 drivers/net/wireless/esp8089/esp_ext.h + create mode 100644 drivers/net/wireless/esp8089/esp_file.c + create mode 100644 drivers/net/wireless/esp8089/esp_file.h + create mode 100644 drivers/net/wireless/esp8089/esp_init_data.h + create mode 100644 drivers/net/wireless/esp8089/esp_io.c + create mode 100644 drivers/net/wireless/esp8089/esp_mac80211.c + create mode 100644 drivers/net/wireless/esp8089/esp_mac80211.h + create mode 100644 drivers/net/wireless/esp8089/esp_main.c + create mode 100644 drivers/net/wireless/esp8089/esp_path.h + create mode 100644 drivers/net/wireless/esp8089/esp_pub.h + create mode 100644 drivers/net/wireless/esp8089/esp_sif.h + create mode 100644 drivers/net/wireless/esp8089/esp_sip.c + create mode 100644 drivers/net/wireless/esp8089/esp_sip.h + create mode 100644 drivers/net/wireless/esp8089/esp_utils.c + create mode 100644 drivers/net/wireless/esp8089/esp_utils.h + create mode 100644 drivers/net/wireless/esp8089/esp_version.h + create mode 100644 drivers/net/wireless/esp8089/esp_wl.h + create mode 100644 drivers/net/wireless/esp8089/esp_wmac.h + create mode 100644 drivers/net/wireless/esp8089/firmware/LICENSE-2.0.txt + create mode 100644 drivers/net/wireless/esp8089/sdio_sif_esp.c + create mode 100644 drivers/net/wireless/esp8089/sip2_common.h + create mode 100644 drivers/net/wireless/esp8089/slc_host_register.h + +diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig +index cb1c15012dd0..de5e37846397 100644 +--- a/drivers/net/wireless/Kconfig ++++ b/drivers/net/wireless/Kconfig +@@ -37,6 +37,7 @@ source "drivers/net/wireless/st/Kconfig" + source "drivers/net/wireless/ti/Kconfig" + source "drivers/net/wireless/zydas/Kconfig" + source "drivers/net/wireless/quantenna/Kconfig" ++source "drivers/net/wireless/esp8089/Kconfig" + + config PCMCIA_RAYCS + tristate "Aviator/Raytheon 2.4GHz wireless support" +diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile +index a61cf6c90343..92ffd2cef51c 100644 +--- a/drivers/net/wireless/Makefile ++++ b/drivers/net/wireless/Makefile +@@ -22,6 +22,7 @@ obj-$(CONFIG_WLAN_VENDOR_SILABS) += silabs/ + obj-$(CONFIG_WLAN_VENDOR_ST) += st/ + obj-$(CONFIG_WLAN_VENDOR_TI) += ti/ + obj-$(CONFIG_WLAN_VENDOR_ZYDAS) += zydas/ ++obj-$(CONFIG_ESP8089) += esp8089/ + + # 16-bit wireless PCMCIA client drivers + obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o +diff --git a/drivers/net/wireless/esp8089/.gitignore b/drivers/net/wireless/esp8089/.gitignore +new file mode 100644 +index 000000000000..eae6529085d0 +--- /dev/null ++++ b/drivers/net/wireless/esp8089/.gitignore +@@ -0,0 +1,7 @@ ++*.cmd ++*.o ++Module.symvers ++modules.order ++.tmp_versions ++*.ko ++*.mod.c +diff --git a/drivers/net/wireless/esp8089/Kconfig b/drivers/net/wireless/esp8089/Kconfig +new file mode 100644 +index 000000000000..8db1fc54712d +--- /dev/null ++++ b/drivers/net/wireless/esp8089/Kconfig +@@ -0,0 +1,13 @@ ++config ESP8089 ++ tristate "Espressif ESP8089 SDIO WiFi" ++ depends on MAC80211 ++ help ++ ESP8089 is a low-budget 2.4GHz WiFi chip by Espressif, used in many ++ cheap tablets with Allwinner or Rockchip SoC ++ ++config ESP8089_DEBUG_FS ++ bool "Enable DebugFS support for ESP8089" ++ depends on ESP8089 ++ default y ++ help ++ DebugFS support for ESP8089 +diff --git a/drivers/net/wireless/esp8089/LICENSE b/drivers/net/wireless/esp8089/LICENSE +new file mode 100644 +index 000000000000..d6a93266f748 +--- /dev/null ++++ b/drivers/net/wireless/esp8089/LICENSE +@@ -0,0 +1,340 @@ ++GNU GENERAL PUBLIC LICENSE ++ Version 2, June 1991 ++ ++ Copyright (C) 1989, 1991 Free Software Foundation, Inc., ++ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 Lesser 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. ++ ++ {description} ++ Copyright (C) {year} {fullname} ++ ++ 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. ++ ++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. ++ ++ {signature of Ty Coon}, 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 Lesser General ++Public License instead of this License. ++ +diff --git a/drivers/net/wireless/esp8089/Makefile b/drivers/net/wireless/esp8089/Makefile +new file mode 100644 +index 000000000000..36decfd20ecd +--- /dev/null ++++ b/drivers/net/wireless/esp8089/Makefile +@@ -0,0 +1,7 @@ ++MODULE_NAME = esp8089 ++ ++$(MODULE_NAME)-y := esp_debug.o sdio_sif_esp.o esp_io.o \ ++ esp_file.o esp_main.o esp_sip.o esp_ext.o esp_ctrl.o \ ++ esp_mac80211.o esp_debug.o esp_utils.o ++ ++obj-$(CONFIG_ESP8089) := esp8089.o +diff --git a/drivers/net/wireless/esp8089/Makefile.old b/drivers/net/wireless/esp8089/Makefile.old +new file mode 100644 +index 000000000000..b7b1a47b159c +--- /dev/null ++++ b/drivers/net/wireless/esp8089/Makefile.old +@@ -0,0 +1,99 @@ ++MODNAME = esp8089 ++ ++# By default, we try to compile the modules for the currently running ++# kernel. But it's the first approximation, as we will re-read the ++# version from the kernel sources. ++KVERS_UNAME ?= $(shell uname -r) ++ ++# KBUILD is the path to the Linux kernel build tree. It is usually the ++# same as the kernel source tree, except when the kernel was compiled in ++# a separate directory. ++KBUILD ?= $(shell readlink -f /lib/modules/$(KVERS_UNAME)/build) ++ ++ifeq (,$(KBUILD)) ++$(error Kernel build tree not found - please set KBUILD to configured kernel) ++endif ++ ++KCONFIG := $(KBUILD)/.config ++ifeq (,$(wildcard $(KCONFIG))) ++$(error No .config found in $(KBUILD), please set KBUILD to configured kernel) ++endif ++ ++ifneq (,$(wildcard $(KBUILD)/include/linux/version.h)) ++ifneq (,$(wildcard $(KBUILD)/include/generated/uapi/linux/version.h)) ++$(error Multiple copies of version.h found, please clean your build tree) ++endif ++endif ++ ++# Kernel Makefile doesn't always know the exact kernel version, so we ++# get it from the kernel headers instead and pass it to make. ++VERSION_H := $(KBUILD)/include/generated/utsrelease.h ++ifeq (,$(wildcard $(VERSION_H))) ++VERSION_H := $(KBUILD)/include/linux/utsrelease.h ++endif ++ifeq (,$(wildcard $(VERSION_H))) ++VERSION_H := $(KBUILD)/include/linux/version.h ++endif ++ifeq (,$(wildcard $(VERSION_H))) ++$(error Please run 'make modules_prepare' in $(KBUILD)) ++endif ++ ++KVERS := $(shell sed -ne 's/"//g;s/^\#define UTS_RELEASE //p' $(VERSION_H)) ++ ++ifeq (,$(KVERS)) ++$(error Cannot find UTS_RELEASE in $(VERSION_H), please report) ++endif ++ ++INST_DIR = /lib/modules/$(KVERS)/misc ++ ++SRC_DIR=$(shell pwd) ++ ++include $(KCONFIG) ++ ++EXTRA_CFLAGS += -DCONFIG_ESP8089_DEBUG_FS ++ ++OBJS = esp_debug.o sdio_sif_esp.o esp_io.o \ ++ esp_file.o esp_main.o esp_sip.o esp_ext.o esp_ctrl.o \ ++ esp_mac80211.o esp_debug.o esp_utils.o esp_pm.o ++ ++all: config_check modules ++ ++MODULE := $(MODNAME).ko ++obj-m := $(MODNAME).o ++ ++$(MODNAME)-objs := $(OBJS) ++ ++config_check: ++ @if [ -z "$(CONFIG_WIRELESS_EXT)$(CONFIG_NET_RADIO)" ]; then \ ++ echo; echo; \ ++ echo "*** WARNING: This kernel lacks wireless extensions."; \ ++ echo "Wireless drivers will not work properly."; \ ++ echo; echo; \ ++ fi ++ ++modules: ++ $(MAKE) -C $(KBUILD) M=$(SRC_DIR) ++ ++$(MODULE): ++ $(MAKE) modules ++ ++clean: ++ rm -f *.o *.ko .*.cmd *.mod.c *.symvers modules.order ++ rm -rf .tmp_versions ++ ++install: config_check $(MODULE) ++ @/sbin/modinfo $(MODULE) | grep -q "^vermagic: *$(KVERS) " || \ ++ { echo "$(MODULE)" is not for Linux $(KVERS); exit 1; } ++ mkdir -p -m 755 $(DESTDIR)$(INST_DIR) ++ install -m 0644 $(MODULE) $(DESTDIR)$(INST_DIR) ++ifndef DESTDIR ++ -/sbin/depmod -a $(KVERS) ++endif ++ ++uninstall: ++ rm -f $(DESTDIR)$(INST_DIR)/$(MODULE) ++ifndef DESTDIR ++ -/sbin/depmod -a $(KVERS) ++endif ++ ++.PHONY: all modules clean install config_check +diff --git a/drivers/net/wireless/esp8089/README.md b/drivers/net/wireless/esp8089/README.md +new file mode 100644 +index 000000000000..56b40db272f3 +--- /dev/null ++++ b/drivers/net/wireless/esp8089/README.md +@@ -0,0 +1,31 @@ ++esp8089 ++====== ++ ++ESP8089 Linux driver ++ ++v1.9 imported from the Rockchip Linux kernel github repo ++ ++Modified to build as a standalone module for SDIO devices. ++ ++ ++ ++ ++Building: ++ ++ make ++ ++Using: ++ ++Must load mac80211.ko first if not baked in. ++ ++ sudo modprobe esp8089.ko ++ ++If you get a wlan interface, but scanning shows no networks try using: ++ ++ sudo modprobe esp8089.ko config=crystal_26M_en=1 ++ ++or: ++ ++ sudo modprobe esp8089.ko config=crystal_26M_en=2 ++ ++To load the module. +diff --git a/drivers/net/wireless/esp8089/esp_ctrl.c b/drivers/net/wireless/esp8089/esp_ctrl.c +new file mode 100644 +index 000000000000..a19d2437dd82 +--- /dev/null ++++ b/drivers/net/wireless/esp8089/esp_ctrl.c +@@ -0,0 +1,801 @@ ++/* ++ * Copyright (c) 2009 - 2014 Espressif System. ++ * ++ * SIP ctrl packet parse and pack ++ * ++ * 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "esp_pub.h" ++#include "esp_sip.h" ++#include "esp_ctrl.h" ++#include "esp_sif.h" ++#include "esp_debug.h" ++#include "esp_wmac.h" ++#include "esp_utils.h" ++#include "esp_wl.h" ++#include "esp_file.h" ++#include "esp_path.h" ++#ifdef TEST_MODE ++#include "testmode.h" ++#endif /* TEST_MODE */ ++#include "esp_version.h" ++ ++extern struct completion *gl_bootup_cplx; ++ ++static void esp_tx_ba_session_op(struct esp_sip *sip, ++ struct esp_node *node, ++ trc_ampdu_state_t state, u8 tid) ++{ ++ struct esp_tx_tid *txtid; ++ ++ txtid = &node->tid[tid]; ++ if (state == TRC_TX_AMPDU_STOPPED) { ++ if (txtid->state == ESP_TID_STATE_OPERATIONAL) { ++ esp_dbg(ESP_DBG_TXAMPDU, ++ "%s tid %d TXAMPDU GOT STOP EVT\n", ++ __func__, tid); ++ ++ spin_lock_bh(&sip->epub->tx_ampdu_lock); ++ txtid->state = ESP_TID_STATE_WAIT_STOP; ++ spin_unlock_bh(&sip->epub->tx_ampdu_lock); ++ ieee80211_stop_tx_ba_session(node->sta, (u16) tid); ++ } else { ++ esp_dbg(ESP_DBG_TXAMPDU, ++ "%s tid %d TXAMPDU GOT STOP EVT IN WRONG STATE %d\n", ++ __func__, tid, txtid->state); ++ } ++ } else if (state == TRC_TX_AMPDU_OPERATIONAL) { ++ if (txtid->state == ESP_TID_STATE_STOP) { ++ esp_dbg(ESP_DBG_TXAMPDU, ++ "%s tid %d TXAMPDU GOT OPERATIONAL\n", ++ __func__, tid); ++ ++ spin_lock_bh(&sip->epub->tx_ampdu_lock); ++ txtid->state = ESP_TID_STATE_TRIGGER; ++ spin_unlock_bh(&sip->epub->tx_ampdu_lock); ++ ieee80211_start_tx_ba_session(node->sta, (u16) tid, ++ 0); ++ ++ } else if (txtid->state == ESP_TID_STATE_OPERATIONAL) { ++ sip_send_ampdu_action(sip->epub, ++ SIP_AMPDU_TX_OPERATIONAL, ++ node->sta->addr, tid, ++ node->ifidx, 0); ++ } else { ++ esp_dbg(ESP_DBG_TXAMPDU, ++ "%s tid %d TXAMPDU GOT OPERATIONAL EVT IN WRONG STATE %d\n", ++ __func__, tid, txtid->state); ++ } ++ } ++} ++ ++int sip_parse_events(struct esp_sip *sip, u8 * buf) ++{ ++ struct sip_hdr *hdr = (struct sip_hdr *) buf; ++ ++ switch (hdr->c_evtid) { ++ case SIP_EVT_TARGET_ON:{ ++ /* use rx work queue to send... */ ++ if (atomic_read(&sip->state) == SIP_PREPARE_BOOT ++ || atomic_read(&sip->state) == SIP_BOOT) { ++ atomic_set(&sip->state, SIP_SEND_INIT); ++ queue_work(sip->epub->esp_wkq, ++ &sip->rx_process_work); ++ } else { ++ esp_dbg(ESP_DBG_ERROR, ++ "%s boot during wrong state %d\n", ++ __func__, ++ atomic_read(&sip->state)); ++ } ++ break; ++ } ++ ++ case SIP_EVT_BOOTUP:{ ++ struct sip_evt_bootup2 *bootup_evt = ++ (struct sip_evt_bootup2 *) (buf + ++ SIP_CTRL_HDR_LEN); ++ if (sip->rawbuf) ++ kfree(sip->rawbuf); ++ ++ sip_post_init(sip, bootup_evt); ++ ++ if (gl_bootup_cplx) ++ complete(gl_bootup_cplx); ++ ++ break; ++ } ++ case SIP_EVT_RESETTING:{ ++ sip->epub->wait_reset = 1; ++ if (gl_bootup_cplx) ++ complete(gl_bootup_cplx); ++ break; ++ } ++ case SIP_EVT_SLEEP:{ ++ //atomic_set(&sip->epub->ps.state, ESP_PM_ON); ++ break; ++ } ++ case SIP_EVT_TXIDLE:{ ++ //struct sip_evt_txidle *txidle = (struct sip_evt_txidle *)(buf + SIP_CTRL_HDR_LEN); ++ //sip_txdone_clear(sip, txidle->last_seq); ++ break; ++ } ++ ++ case SIP_EVT_SCAN_RESULT:{ ++ struct sip_evt_scan_report *report = ++ (struct sip_evt_scan_report *) (buf + ++ SIP_CTRL_HDR_LEN); ++ if (atomic_read(&sip->epub->wl.off)) { ++ esp_dbg(ESP_DBG_ERROR, ++ "%s scan result while wlan off\n", ++ __func__); ++ return 0; ++ } ++ sip_scandone_process(sip, report); ++ ++ break; ++ } ++ ++ case SIP_EVT_ROC:{ ++ struct sip_evt_roc *report = ++ (struct sip_evt_roc *) (buf + ++ SIP_CTRL_HDR_LEN); ++ esp_rocdone_process(sip->epub->hw, report); ++ break; ++ } ++ ++ ++#ifdef ESP_RX_COPYBACK_TEST ++ ++ case SIP_EVT_COPYBACK:{ ++ u32 len = hdr->len - SIP_CTRL_HDR_LEN; ++ ++ esp_dbg(ESP_DBG_TRACE, ++ "%s copyback len %d seq %u\n", __func__, ++ len, hdr->seq); ++ ++ memcpy(copyback_buf + copyback_offset, ++ pkt->buf + SIP_CTRL_HDR_LEN, len); ++ copyback_offset += len; ++ ++ //show_buf(pkt->buf, 256); ++ ++ //how about totlen % 256 == 0?? ++ if (hdr->hdr.len < 256) { ++ kfree(copyback_buf); ++ } ++ } ++ break; ++#endif /* ESP_RX_COPYBACK_TEST */ ++ case SIP_EVT_CREDIT_RPT: ++ break; ++ ++#ifdef TEST_MODE ++ case SIP_EVT_WAKEUP:{ ++ u8 check_str[12]; ++ struct sip_evt_wakeup *wakeup_evt = ++ (struct sip_evt_wakeup *) (buf + ++ SIP_CTRL_HDR_LEN); ++ sprintf((char *) &check_str, "%d", ++ wakeup_evt->check_data); ++ esp_test_cmd_event(TEST_CMD_WAKEUP, ++ (char *) &check_str); ++ break; ++ } ++ ++ case SIP_EVT_DEBUG:{ ++ u8 check_str[640]; ++ sip_parse_event_debug(sip->epub, buf, check_str); ++ esp_dbg(ESP_DBG_TRACE, "%s", check_str); ++ esp_test_cmd_event(TEST_CMD_DEBUG, ++ (char *) &check_str); ++ break; ++ } ++ ++ case SIP_EVT_LOOPBACK:{ ++ u8 check_str[12]; ++ struct sip_evt_loopback *loopback_evt = ++ (struct sip_evt_loopback *) (buf + ++ SIP_CTRL_HDR_LEN); ++ esp_dbg(ESP_DBG_LOG, "%s loopback len %d seq %u\n", ++ __func__, hdr->len, hdr->seq); ++ ++ if (loopback_evt->pack_id != get_loopback_id()) { ++ sprintf((char *) &check_str, ++ "seq id error %d, expect %d", ++ loopback_evt->pack_id, ++ get_loopback_id()); ++ esp_test_cmd_event(TEST_CMD_LOOPBACK, ++ (char *) &check_str); ++ } ++ ++ if ((loopback_evt->pack_id + 1) < ++ get_loopback_num()) { ++ inc_loopback_id(); ++ sip_send_loopback_mblk(sip, ++ loopback_evt->txlen, ++ loopback_evt->rxlen, ++ get_loopback_id()); ++ } else { ++ sprintf((char *) &check_str, "test over!"); ++ esp_test_cmd_event(TEST_CMD_LOOPBACK, ++ (char *) &check_str); ++ } ++ break; ++ } ++#endif /*TEST_MODE */ ++ ++ case SIP_EVT_SNPRINTF_TO_HOST:{ ++ u8 *p = ++ (buf + sizeof(struct sip_hdr) + sizeof(u16)); ++ u16 *len = (u16 *) (buf + sizeof(struct sip_hdr)); ++ char test_res_str[560]; ++ sprintf(test_res_str, ++ "esp_host:%llx\nesp_target: %.*s", ++ DRIVER_VER, *len, p); ++ ++ esp_dbg(ESP_DBG_TRACE, "%s\n", test_res_str); ++ if (*len ++ && sip->epub->sdio_state == ++ ESP_SDIO_STATE_FIRST_INIT) { ++ char filename[256]; ++ if (mod_eagle_path_get() == NULL) ++ sprintf(filename, "%s/%s", FWPATH, ++ "test_results"); ++ else ++ sprintf(filename, "%s/%s", ++ mod_eagle_path_get(), ++ "test_results"); ++ esp_dbg(ESP_DBG_TRACE, ++ "SNPRINTF TO HOST: %s\n", ++ test_res_str); ++ } ++ break; ++ } ++ case SIP_EVT_TRC_AMPDU:{ ++ struct sip_evt_trc_ampdu *ep = ++ (struct sip_evt_trc_ampdu *) (buf + ++ SIP_CTRL_HDR_LEN); ++ struct esp_node *node = NULL; ++ int i = 0; ++ ++ if (atomic_read(&sip->epub->wl.off)) { ++ esp_dbg(ESP_DBG_ERROR, ++ "%s scan result while wlan off\n", ++ __func__); ++ return 0; ++ } ++ ++ node = esp_get_node_by_addr(sip->epub, ep->addr); ++ if (node == NULL) ++ break; ++ for (i = 0; i < 8; i++) { ++ if (ep->tid & (1 << i)) { ++ esp_tx_ba_session_op(sip, node, ++ ep->state, i); ++ } ++ } ++ break; ++ } ++ ++#ifdef TEST_MODE ++ case SIP_EVT_EP:{ ++ char *ep = (char *) (buf + SIP_CTRL_HDR_LEN); ++ static int counter = 0; ++ ++ esp_dbg(ESP_ATE, "%s EVT_EP \n\n", __func__); ++ if (counter++ < 2) { ++ esp_dbg(ESP_ATE, "ATE: %s \n", ep); ++ } ++ ++ esp_test_ate_done_cb(ep); ++ ++ break; ++ } ++#endif /*TEST_MODE */ ++ ++ case SIP_EVT_INIT_EP:{ ++ char *ep = (char *) (buf + SIP_CTRL_HDR_LEN); ++ esp_dbg(ESP_ATE, "Phy Init: %s \n", ep); ++ break; ++ } ++ ++ case SIP_EVT_NOISEFLOOR:{ ++ struct sip_evt_noisefloor *ep = ++ (struct sip_evt_noisefloor *) (buf + ++ SIP_CTRL_HDR_LEN); ++ atomic_set(&sip->noise_floor, ep->noise_floor); ++ break; ++ } ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++#include "esp_init_data.h" ++ ++void sip_send_chip_init(struct esp_sip *sip) ++{ ++ size_t size = 0; ++ size = sizeof(esp_init_data); ++ ++ esp_conf_upload_second(esp_init_data, size); ++ ++ atomic_sub(1, &sip->tx_credits); ++ ++ sip_send_cmd(sip, SIP_CMD_INIT, size, (void *) esp_init_data); ++ ++} ++ ++int sip_send_config(struct esp_pub *epub, struct ieee80211_conf *conf) ++{ ++ struct sk_buff *skb = NULL; ++ struct sip_cmd_config *configcmd; ++ ++ skb = ++ sip_alloc_ctrl_skbuf(epub->sip, ++ sizeof(struct sip_cmd_config) + ++ sizeof(struct sip_hdr), SIP_CMD_CONFIG); ++ if (!skb) ++ return -EINVAL; ++ esp_dbg(ESP_DBG_TRACE, "%s config center freq %d\n", __func__, ++ conf->chandef.chan->center_freq); ++ configcmd = ++ (struct sip_cmd_config *) (skb->data + sizeof(struct sip_hdr)); ++ configcmd->center_freq = conf->chandef.chan->center_freq; ++ configcmd->duration = 0; ++ return sip_cmd_enqueue(epub->sip, skb, ENQUEUE_PRIOR_TAIL); ++} ++ ++int sip_send_bss_info_update(struct esp_pub *epub, struct esp_vif *evif, ++ u8 * bssid, int assoc) ++{ ++ struct sk_buff *skb = NULL; ++ struct sip_cmd_bss_info_update *bsscmd; ++ ++ skb = ++ sip_alloc_ctrl_skbuf(epub->sip, ++ sizeof(struct sip_cmd_bss_info_update) + ++ sizeof(struct sip_hdr), ++ SIP_CMD_BSS_INFO_UPDATE); ++ if (!skb) ++ return -EINVAL; ++ ++ bsscmd = ++ (struct sip_cmd_bss_info_update *) (skb->data + ++ sizeof(struct sip_hdr)); ++ if (assoc == 2) { //hack for softAP mode ++ bsscmd->beacon_int = evif->beacon_interval; ++ } else if (assoc == 1) { ++ set_bit(ESP_WL_FLAG_CONNECT, &epub->wl.flags); ++ } else { ++ clear_bit(ESP_WL_FLAG_CONNECT, &epub->wl.flags); ++ } ++ bsscmd->bssid_no = evif->index; ++ bsscmd->isassoc = assoc; ++ bsscmd->beacon_int = evif->beacon_interval; ++ memcpy(bsscmd->bssid, bssid, ETH_ALEN); ++ return sip_cmd_enqueue(epub->sip, skb, ENQUEUE_PRIOR_TAIL); ++} ++ ++int sip_send_wmm_params(struct esp_pub *epub, u8 aci, ++ const struct ieee80211_tx_queue_params *params) ++{ ++ struct sk_buff *skb = NULL; ++ struct sip_cmd_set_wmm_params *bsscmd; ++ skb = ++ sip_alloc_ctrl_skbuf(epub->sip, ++ sizeof(struct sip_cmd_set_wmm_params) + ++ sizeof(struct sip_hdr), ++ SIP_CMD_SET_WMM_PARAM); ++ if (!skb) ++ return -EINVAL; ++ ++ bsscmd = ++ (struct sip_cmd_set_wmm_params *) (skb->data + ++ sizeof(struct sip_hdr)); ++ bsscmd->aci = aci; ++ bsscmd->aifs = params->aifs; ++ bsscmd->txop_us = params->txop * 32; ++ ++ bsscmd->ecw_min = 32 - __builtin_clz(params->cw_min); ++ bsscmd->ecw_max = 32 - __builtin_clz(params->cw_max); ++ ++ return sip_cmd_enqueue(epub->sip, skb, ENQUEUE_PRIOR_TAIL); ++} ++ ++int sip_send_ampdu_action(struct esp_pub *epub, u8 action_num, ++ const u8 * addr, u16 tid, u16 ssn, u8 buf_size) ++{ ++ int index = 0; ++ struct sk_buff *skb = NULL; ++ struct sip_cmd_ampdu_action *action; ++ if (action_num == SIP_AMPDU_RX_START) { ++ index = esp_get_empty_rxampdu(epub, addr, tid); ++ } else if (action_num == SIP_AMPDU_RX_STOP) { ++ index = esp_get_exist_rxampdu(epub, addr, tid); ++ } ++ if (index < 0) ++ return -EACCES; ++ skb = ++ sip_alloc_ctrl_skbuf(epub->sip, ++ sizeof(struct sip_cmd_ampdu_action) + ++ sizeof(struct sip_hdr), ++ SIP_CMD_AMPDU_ACTION); ++ if (!skb) ++ return -EINVAL; ++ ++ action = ++ (struct sip_cmd_ampdu_action *) (skb->data + ++ sizeof(struct sip_hdr)); ++ action->action = action_num; ++ //for TX, it means interface index ++ action->index = ssn; ++ ++ switch (action_num) { ++ case SIP_AMPDU_RX_START: ++ action->ssn = ssn; ++ // fall through ++ case SIP_AMPDU_RX_STOP: ++ action->index = index; ++ // fall through ++ case SIP_AMPDU_TX_OPERATIONAL: ++ case SIP_AMPDU_TX_STOP: ++ action->win_size = buf_size; ++ action->tid = tid; ++ memcpy(action->addr, addr, ETH_ALEN); ++ break; ++ } ++ ++ return sip_cmd_enqueue(epub->sip, skb, ENQUEUE_PRIOR_TAIL); ++} ++ ++#ifdef HW_SCAN ++/*send cmd to target, if aborted is true, inform target stop scan, report scan complete imediately ++ return 1: complete over, 0: success, still have next scan, -1: hardware failure ++ */ ++int sip_send_scan(struct esp_pub *epub) ++{ ++ struct cfg80211_scan_request *scan_req = epub->wl.scan_req; ++ struct sk_buff *skb = NULL; ++ struct sip_cmd_scan *scancmd; ++ u8 *ptr = NULL; ++ int i; ++ u8 append_len, ssid_len; ++ ++ ESSERT(scan_req != NULL); ++ ssid_len = scan_req->n_ssids == 0 ? 0 : ++ (scan_req->n_ssids == ++ 1 ? scan_req->ssids->ssid_len : scan_req->ssids->ssid_len + ++ (scan_req->ssids + 1)->ssid_len); ++ append_len = ssid_len + scan_req->n_channels + scan_req->ie_len; ++ ++ skb = ++ sip_alloc_ctrl_skbuf(epub->sip, ++ sizeof(struct sip_cmd_scan) + ++ sizeof(struct sip_hdr) + append_len, ++ SIP_CMD_SCAN); ++ ++ if (!skb) ++ return -EINVAL; ++ ++ ptr = skb->data; ++ scancmd = (struct sip_cmd_scan *) (ptr + sizeof(struct sip_hdr)); ++ ptr += sizeof(struct sip_hdr); ++ ++ scancmd->aborted = false; ++ ++ if (scancmd->aborted == false) { ++ ptr += sizeof(struct sip_cmd_scan); ++ if (scan_req->n_ssids <= 0 ++ || (scan_req->n_ssids == 1 && ssid_len == 0)) { ++ scancmd->ssid_len = 0; ++ } else { ++ scancmd->ssid_len = ssid_len; ++ if (scan_req->ssids->ssid_len == ssid_len) ++ memcpy(ptr, scan_req->ssids->ssid, ++ scancmd->ssid_len); ++ else ++ memcpy(ptr, (scan_req->ssids + 1)->ssid, ++ scancmd->ssid_len); ++ } ++ ++ ptr += scancmd->ssid_len; ++ scancmd->n_channels = scan_req->n_channels; ++ for (i = 0; i < scan_req->n_channels; i++) ++ ptr[i] = scan_req->channels[i]->hw_value; ++ ++ ptr += scancmd->n_channels; ++ if (scan_req->ie_len && scan_req->ie != NULL) { ++ scancmd->ie_len = scan_req->ie_len; ++ memcpy(ptr, scan_req->ie, scan_req->ie_len); ++ } else { ++ scancmd->ie_len = 0; ++ } ++ //add a flag that support two ssids, ++ if (scan_req->n_ssids > 1) ++ scancmd->ssid_len |= 0x80; ++ ++ } ++ ++ return sip_cmd_enqueue(epub->sip, skb, ENQUEUE_PRIOR_TAIL); ++} ++#endif ++ ++int sip_send_suspend_config(struct esp_pub *epub, u8 suspend) ++{ ++ struct sip_cmd_suspend *cmd = NULL; ++ struct sk_buff *skb = NULL; ++ ++ skb = ++ sip_alloc_ctrl_skbuf(epub->sip, ++ sizeof(struct sip_cmd_suspend) + ++ sizeof(struct sip_hdr), SIP_CMD_SUSPEND); ++ ++ if (!skb) ++ return -EINVAL; ++ ++ cmd = ++ (struct sip_cmd_suspend *) (skb->data + ++ sizeof(struct sip_hdr)); ++ cmd->suspend = suspend; ++ return sip_cmd_enqueue(epub->sip, skb, ENQUEUE_PRIOR_TAIL); ++} ++ ++int sip_send_ps_config(struct esp_pub *epub, struct esp_ps *ps) ++{ ++ struct sip_cmd_ps *pscmd = NULL; ++ struct sk_buff *skb = NULL; ++ struct sip_hdr *shdr = NULL; ++ ++ skb = ++ sip_alloc_ctrl_skbuf(epub->sip, ++ sizeof(struct sip_cmd_ps) + ++ sizeof(struct sip_hdr), SIP_CMD_PS); ++ ++ if (!skb) ++ return -EINVAL; ++ ++ ++ shdr = (struct sip_hdr *) skb->data; ++ pscmd = (struct sip_cmd_ps *) (skb->data + sizeof(struct sip_hdr)); ++ ++ pscmd->dtim_period = ps->dtim_period; ++ pscmd->max_sleep_period = ps->max_sleep_period; ++ ++ return sip_cmd_enqueue(epub->sip, skb, ENQUEUE_PRIOR_TAIL); ++} ++ ++void sip_scandone_process(struct esp_sip *sip, ++ struct sip_evt_scan_report *scan_report) ++{ ++ struct esp_pub *epub = sip->epub; ++ ++ esp_dbg(ESP_DBG_TRACE, "eagle hw scan report\n"); ++ ++ if (epub->wl.scan_req) { ++ hw_scan_done(epub, scan_report->aborted); ++ epub->wl.scan_req = NULL; ++ } ++} ++ ++int sip_send_setkey(struct esp_pub *epub, u8 bssid_no, u8 * peer_addr, ++ struct ieee80211_key_conf *key, u8 isvalid) ++{ ++ struct sip_cmd_setkey *setkeycmd; ++ struct sk_buff *skb = NULL; ++ ++ skb = ++ sip_alloc_ctrl_skbuf(epub->sip, ++ sizeof(struct sip_cmd_setkey) + ++ sizeof(struct sip_hdr), SIP_CMD_SETKEY); ++ ++ if (!skb) ++ return -EINVAL; ++ ++ setkeycmd = ++ (struct sip_cmd_setkey *) (skb->data + sizeof(struct sip_hdr)); ++ ++ if (peer_addr) { ++ memcpy(setkeycmd->addr, peer_addr, ETH_ALEN); ++ } else { ++ memset(setkeycmd->addr, 0, ETH_ALEN); ++ } ++ ++ setkeycmd->bssid_no = bssid_no; ++ setkeycmd->hw_key_idx = key->hw_key_idx; ++ ++ if (isvalid) { ++ setkeycmd->alg = esp_cipher2alg(key->cipher); ++ setkeycmd->keyidx = key->keyidx; ++ setkeycmd->keylen = key->keylen; ++ if (key->cipher == WLAN_CIPHER_SUITE_TKIP) { ++ memcpy(setkeycmd->key, key->key, 16); ++ memcpy(setkeycmd->key + 16, key->key + 24, 8); ++ memcpy(setkeycmd->key + 24, key->key + 16, 8); ++ } else { ++ memcpy(setkeycmd->key, key->key, key->keylen); ++ } ++ ++ setkeycmd->flags = 1; ++ } else { ++ setkeycmd->flags = 0; ++ } ++ return sip_cmd_enqueue(epub->sip, skb, ENQUEUE_PRIOR_TAIL); ++} ++ ++#ifdef FPGA_LOOPBACK ++#define LOOPBACK_PKT_LEN 200 ++int sip_send_loopback_cmd_mblk(struct esp_sip *sip) ++{ ++ int cnt, ret; ++ ++ for (cnt = 0; cnt < 4; cnt++) { ++ if (0 != ++ (ret = ++ sip_send_loopback_mblk(sip, LOOPBACK_PKT_LEN, ++ LOOPBACK_PKT_LEN, 0))) ++ return ret; ++ } ++ return 0; ++} ++#endif /* FPGA_LOOPBACK */ ++ ++int sip_send_loopback_mblk(struct esp_sip *sip, int txpacket_len, ++ int rxpacket_len, int packet_id) ++{ ++ struct sk_buff *skb = NULL; ++ struct sip_cmd_loopback *cmd; ++ u8 *ptr = NULL; ++ int i, ret; ++ ++ //send 100 loopback pkt ++ if (txpacket_len) ++ skb = ++ sip_alloc_ctrl_skbuf(sip, ++ sizeof(struct sip_cmd_loopback) + ++ sizeof(struct sip_hdr) + ++ txpacket_len, SIP_CMD_LOOPBACK); ++ else ++ skb = ++ sip_alloc_ctrl_skbuf(sip, ++ sizeof(struct sip_cmd_loopback) + ++ sizeof(struct sip_hdr), ++ SIP_CMD_LOOPBACK); ++ ++ if (!skb) ++ return -ENOMEM; ++ ++ ptr = skb->data; ++ cmd = (struct sip_cmd_loopback *) (ptr + sizeof(struct sip_hdr)); ++ ptr += sizeof(struct sip_hdr); ++ cmd->txlen = txpacket_len; ++ cmd->rxlen = rxpacket_len; ++ cmd->pack_id = packet_id; ++ ++ if (txpacket_len) { ++ ptr += sizeof(struct sip_cmd_loopback); ++ /* fill up pkt payload */ ++ for (i = 0; i < txpacket_len; i++) { ++ ptr[i] = i; ++ } ++ } ++ ++ ret = sip_cmd_enqueue(sip, skb, ENQUEUE_PRIOR_TAIL); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++//remain_on_channel ++int sip_send_roc(struct esp_pub *epub, u16 center_freq, u16 duration) ++{ ++ struct sk_buff *skb = NULL; ++ struct sip_cmd_config *configcmd; ++ ++ skb = ++ sip_alloc_ctrl_skbuf(epub->sip, ++ sizeof(struct sip_cmd_config) + ++ sizeof(struct sip_hdr), SIP_CMD_CONFIG); ++ if (!skb) ++ return -EINVAL; ++ ++ configcmd = ++ (struct sip_cmd_config *) (skb->data + sizeof(struct sip_hdr)); ++ configcmd->center_freq = center_freq; ++ configcmd->duration = duration; ++ return sip_cmd_enqueue(epub->sip, skb, ENQUEUE_PRIOR_TAIL); ++} ++ ++int sip_send_set_sta(struct esp_pub *epub, u8 ifidx, u8 set, ++ struct ieee80211_sta *sta, struct ieee80211_vif *vif, ++ u8 index) ++{ ++ struct sk_buff *skb = NULL; ++ struct sip_cmd_setsta *setstacmd; ++ skb = ++ sip_alloc_ctrl_skbuf(epub->sip, ++ sizeof(struct sip_cmd_setsta) + ++ sizeof(struct sip_hdr), SIP_CMD_SETSTA); ++ if (!skb) ++ return -EINVAL; ++ ++ setstacmd = ++ (struct sip_cmd_setsta *) (skb->data + sizeof(struct sip_hdr)); ++ setstacmd->ifidx = ifidx; ++ setstacmd->index = index; ++ setstacmd->set = set; ++ if (sta->aid == 0) ++ setstacmd->aid = vif->cfg.aid; ++ else ++ setstacmd->aid = sta->aid; ++ memcpy(setstacmd->mac, sta->addr, ETH_ALEN); ++ if (set) { ++ if (sta->deflink.ht_cap.ht_supported) { ++ if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ++ setstacmd->phymode = ++ ESP_IEEE80211_T_HT20_S; ++ else ++ setstacmd->phymode = ++ ESP_IEEE80211_T_HT20_L; ++ setstacmd->ampdu_factor = sta->deflink.ht_cap.ampdu_factor; ++ setstacmd->ampdu_density = ++ sta->deflink.ht_cap.ampdu_density; ++ } else { ++ if (sta->deflink.supp_rates[NL80211_BAND_2GHZ] & (~(u32) ++ CONF_HW_BIT_RATE_11B_MASK)) ++ { ++ setstacmd->phymode = ESP_IEEE80211_T_OFDM; ++ } else { ++ setstacmd->phymode = ESP_IEEE80211_T_CCK; ++ } ++ } ++ } ++ return sip_cmd_enqueue(epub->sip, skb, ENQUEUE_PRIOR_TAIL); ++} ++ ++int sip_send_recalc_credit(struct esp_pub *epub) ++{ ++ struct sk_buff *skb = NULL; ++ ++ skb = ++ sip_alloc_ctrl_skbuf(epub->sip, 0 + sizeof(struct sip_hdr), ++ SIP_CMD_RECALC_CREDIT); ++ if (!skb) ++ return -ENOMEM; ++ ++ return sip_cmd_enqueue(epub->sip, skb, ENQUEUE_PRIOR_HEAD); ++} ++ ++int sip_cmd(struct esp_pub *epub, enum sip_cmd_id cmd_id, u8 * cmd_buf, ++ u8 cmd_len) ++{ ++ struct sk_buff *skb = NULL; ++ ++ skb = ++ sip_alloc_ctrl_skbuf(epub->sip, ++ cmd_len + sizeof(struct sip_hdr), cmd_id); ++ if (!skb) ++ return -ENOMEM; ++ ++ memcpy(skb->data + sizeof(struct sip_hdr), cmd_buf, cmd_len); ++ ++ return sip_cmd_enqueue(epub->sip, skb, ENQUEUE_PRIOR_TAIL); ++} +diff --git a/drivers/net/wireless/esp8089/esp_ctrl.h b/drivers/net/wireless/esp8089/esp_ctrl.h +new file mode 100644 +index 000000000000..29c18caa9ede +--- /dev/null ++++ b/drivers/net/wireless/esp8089/esp_ctrl.h +@@ -0,0 +1,58 @@ ++/* ++ * Copyright (c) 2009- 2014 Espressif System. ++ * ++ * SIP ctrl packet parse and pack ++ * ++ * 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 _ESP_CTRL_H_ ++#define _ESP_CTRL_H_ ++ ++int sip_send_loopback_mblk(struct esp_sip *sip, int txpacket_len, ++ int rxpacket_len, int packet_id); ++ ++int sip_send_config(struct esp_pub *epub, struct ieee80211_conf *conf); ++ ++int sip_send_setkey(struct esp_pub *epub, u8 bssid_no, u8 * peer_addr, ++ struct ieee80211_key_conf *key, u8 isvalid); ++ ++int sip_send_scan(struct esp_pub *epub); ++ ++void sip_scandone_process(struct esp_sip *sip, ++ struct sip_evt_scan_report *scan_report); ++ ++int sip_send_bss_info_update(struct esp_pub *epub, struct esp_vif *evif, ++ u8 * bssid, int assoc); ++ ++int sip_send_wmm_params(struct esp_pub *epub, u8 aci, ++ const struct ieee80211_tx_queue_params *params); ++ ++int sip_send_ampdu_action(struct esp_pub *epub, u8 action_num, ++ const u8 * addr, u16 tid, u16 ssn, u8 buf_size); ++ ++int sip_send_roc(struct esp_pub *epub, u16 center_freq, u16 duration); ++ ++int sip_send_set_sta(struct esp_pub *epub, u8 ifidx, u8 set, ++ struct ieee80211_sta *sta, struct ieee80211_vif *vif, ++ u8 index); ++ ++int sip_send_suspend_config(struct esp_pub *epub, u8 suspend); ++ ++int sip_send_ps_config(struct esp_pub *epub, struct esp_ps *ps); ++ ++int sip_parse_events(struct esp_sip *sip, u8 * buf); ++ ++int sip_send_recalc_credit(struct esp_pub *epub); ++ ++int sip_cmd(struct esp_pub *epub, enum sip_cmd_id cmd_id, u8 * cmd_buf, ++ u8 cmd_len); ++ ++#endif /* _ESP_CTRL_H_ */ +diff --git a/drivers/net/wireless/esp8089/esp_debug.c b/drivers/net/wireless/esp8089/esp_debug.c +new file mode 100644 +index 000000000000..5ce8fd2ebd6b +--- /dev/null ++++ b/drivers/net/wireless/esp8089/esp_debug.c +@@ -0,0 +1,297 @@ ++/* ++ * Copyright (c) 2011-2014 Espressif System. ++ * ++ * esp debug interface ++ * - debugfs ++ * - debug level control ++ * ++ * 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. ++ */ ++ ++#include ++#include ++ ++#include ++#include "sip2_common.h" ++ ++#include "esp_debug.h" ++ ++#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_ESP8089_DEBUG_FS) ++ ++static struct dentry *esp_debugfs_root = NULL; ++ ++static int esp_debugfs_open(struct inode *inode, struct file *filp) ++{ ++ filp->private_data = inode->i_private; ++ return 0; ++} ++ ++static ssize_t esp_debugfs_read(struct file *filp, char __user * buffer, ++ size_t count, loff_t * ppos) ++{ ++ if (*ppos >= 32) ++ return 0; ++ if (*ppos + count > 32) ++ count = 32 - *ppos; ++ ++ if (copy_to_user(buffer, filp->private_data + *ppos, count)) ++ return -EFAULT; ++ ++ *ppos += count; ++ ++ return count; ++} ++ ++static ssize_t esp_debugfs_write(struct file *filp, ++ const char __user * buffer, size_t count, ++ loff_t * ppos) ++{ ++ if (*ppos >= 32) ++ return 0; ++ if (*ppos + count > 32) ++ count = 32 - *ppos; ++ ++ if (copy_from_user(filp->private_data + *ppos, buffer, count)) ++ return -EFAULT; ++ ++ *ppos += count; ++ ++ return count; ++} ++ ++struct file_operations esp_debugfs_fops = { ++ .owner = THIS_MODULE, ++ .open = esp_debugfs_open, ++ .read = esp_debugfs_read, ++ .write = esp_debugfs_write, ++}; ++ ++ ++void esp_dump_var(const char *name, struct dentry *parent, ++ void *value, esp_type type) ++{ ++ umode_t mode = 0644; ++ ++ if (!esp_debugfs_root) ++ return; ++ ++ if (!parent) ++ parent = esp_debugfs_root; ++ ++ switch (type) { ++ case ESP_U8: ++ debugfs_create_u8(name, mode, parent, (u8 *) value); ++ break; ++ case ESP_U16: ++ debugfs_create_u16(name, mode, parent, (u16 *) value); ++ break; ++ case ESP_U32: ++ debugfs_create_u32(name, mode, parent, (u32 *) value); ++ break; ++ case ESP_U64: ++ debugfs_create_u64(name, mode, parent, (u64 *) value); ++ break; ++ case ESP_BOOL: ++ debugfs_create_bool(name, mode, parent, ++ (bool *) value); ++ break; ++ default: //32 ++ debugfs_create_u32(name, mode, parent, (u32 *) value); ++ } ++ ++ return; ++ ++} ++ ++void esp_dump_array(const char *name, struct dentry *parent, ++ struct debugfs_blob_wrapper *blob) ++{ ++ umode_t mode = 0644; ++ ++ if (!esp_debugfs_root) ++ return; ++ ++ if (!parent) ++ parent = esp_debugfs_root; ++ ++ debugfs_create_blob(name, mode, parent, blob); ++ ++} ++ ++void esp_dump(const char *name, struct dentry *parent, ++ void *data, int size) ++{ ++ umode_t mode = 0644; ++ ++ if (!esp_debugfs_root) ++ return; ++ ++ if (!parent) ++ parent = esp_debugfs_root; ++ ++ debugfs_create_file(name, mode, parent, data, ++ &esp_debugfs_fops); ++ ++} ++ ++struct dentry *esp_debugfs_add_sub_dir(const char *name) ++{ ++ struct dentry *sub_dir = NULL; ++ ++ sub_dir = debugfs_create_dir(name, esp_debugfs_root); ++ ++ if (!sub_dir) ++ goto Fail; ++ ++ return sub_dir; ++ ++ Fail: ++ debugfs_remove_recursive(esp_debugfs_root); ++ esp_debugfs_root = NULL; ++ esp_dbg(ESP_DBG_ERROR, ++ "%s failed, debugfs root removed; dir name: %s\n", ++ __FUNCTION__, name); ++ return NULL; ++ ++} ++ ++int esp_debugfs_init(void) ++{ ++ esp_dbg(ESP_DBG, "esp debugfs init\n"); ++ esp_debugfs_root = debugfs_create_dir("esp_debug", NULL); ++ ++ if (!esp_debugfs_root || IS_ERR_OR_NULL(esp_debugfs_root)) { ++ return -ENOENT; ++ } ++ ++ return 0; ++} ++ ++void esp_debugfs_exit(void) ++{ ++ esp_dbg(ESP_DBG, "esp debugfs exit"); ++ ++ debugfs_remove_recursive(esp_debugfs_root); ++ ++ return; ++} ++ ++#else ++ ++inline struct dentry *esp_dump_var(const char *name, struct dentry *parent, ++ void *value, esp_type type) ++{ ++ return NULL; ++} ++ ++inline struct dentry *esp_dump_array(const char *name, ++ struct dentry *parent, ++ struct debugfs_blob_wrapper *blob) ++{ ++ return NULL; ++} ++ ++inline struct dentry *esp_dump(const char *name, struct dentry *parent, ++ void *data, int size) ++{ ++ return NULL; ++} ++ ++struct dentry *esp_debugfs_add_sub_dir(const char *name) ++{ ++ return NULL; ++} ++ ++inline int esp_debugfs_init(void) ++{ ++ return -EPERM; ++} ++ ++inline void esp_debugfs_exit(void) ++{ ++ ++} ++ ++#endif ++ ++ ++void show_buf(u8 * buf, u32 len) ++{ ++// print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 16, 1, buf, len, true); ++#if 1 ++ int i = 0, j; ++ ++ printk(KERN_INFO "\n++++++++++++++++show rbuf+++++++++++++++\n"); ++ for (i = 0; i < (len / 16); i++) { ++ j = i * 16; ++ printk(KERN_INFO ++ "0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x \n", ++ buf[j], buf[j + 1], buf[j + 2], buf[j + 3], ++ buf[j + 4], buf[j + 5], buf[j + 6], buf[j + 7], ++ buf[j + 8], buf[j + 9], buf[j + 10], buf[j + 11], ++ buf[j + 12], buf[j + 13], buf[j + 14], buf[j + 15]); ++ } ++ printk(KERN_INFO "\n++++++++++++++++++++++++++++++++++++++++\n"); ++#endif //0000 ++} ++ ++#ifdef HOST_RC ++static u8 get_cnt(u32 cnt_store, int idx) ++{ ++ int shift = idx << 2; ++ ++ return (u8) ((cnt_store >> shift) & 0xf); ++} ++ ++void esp_show_rcstatus(struct sip_rc_status *rcstatus) ++{ ++ int i; ++ char msg[82]; ++ char rcstr[16]; ++ u32 cnt_store = rcstatus->rc_cnt_store; ++ ++ memset(msg, 0, sizeof(msg)); ++ memset(rcstr, 0, sizeof(rcstr)); ++ ++ printk(KERN_INFO "rcstatus map 0x%08x cntStore 0x%08x\n", ++ rcstatus->rc_map, rcstatus->rc_cnt_store); ++ ++ for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { ++ if (rcstatus->rc_map & BIT(i)) { ++ sprintf(rcstr, "rcIdx %d, cnt %d ", i, ++ get_cnt(cnt_store, i)); ++ strcat(msg, rcstr); ++ } ++ } ++ printk(KERN_INFO "%s \n", msg); ++} ++ ++void esp_show_tx_rates(struct ieee80211_tx_rate *rates) ++{ ++ int i; ++ char msg[128]; ++ char rcstr[32]; ++ ++ memset(msg, 0, sizeof(msg)); ++ memset(rcstr, 0, sizeof(rcstr)); ++ ++ for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { ++ if (rates->idx != -1) { ++ sprintf(rcstr, "Idx %d, cnt %d, flag %02x ", ++ rates->idx, rates->count, rates->flags); ++ strcat(msg, rcstr); ++ } ++ rates++; ++ } ++ strcat(msg, "\n"); ++ printk(KERN_INFO "%s \n", msg); ++} ++#endif /* HOST_RC */ +diff --git a/drivers/net/wireless/esp8089/esp_debug.h b/drivers/net/wireless/esp8089/esp_debug.h +new file mode 100644 +index 000000000000..bab695d34bfb +--- /dev/null ++++ b/drivers/net/wireless/esp8089/esp_debug.h +@@ -0,0 +1,101 @@ ++/* ++ * Copyright (c) 2011-2014 Espressif System. ++ * ++ * esp debug ++ * ++ * 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 _DEBUG_H_ ++ ++#ifdef ASSERT_PANIC ++#define ESSERT(v) BUG_ON(!(v)) ++#else ++#define ESSERT(v) if(!(v)) printk("ESSERT:%s %d\n", __FILE__, __LINE__) ++#endif ++ ++ ++#include ++#include ++#include ++ ++typedef enum esp_type { ++ ESP_BOOL, ++ ESP_U8, ++ ESP_U16, ++ ESP_U32, ++ ESP_U64 ++} esp_type; ++ ++void esp_dump_var(const char *name, struct dentry *parent, ++ void *value, esp_type type); ++ ++void esp_dump_array(const char *name, struct dentry *parent, ++ struct debugfs_blob_wrapper *blob); ++ ++void esp_dump(const char *name, struct dentry *parent, ++ void *data, int size); ++ ++struct dentry *esp_debugfs_add_sub_dir(const char *name); ++ ++int esp_debugfs_init(void); ++ ++void esp_debugfs_exit(void); ++ ++enum { ++ ESP_DBG_ERROR = BIT(0), ++ ESP_DBG_TRACE = BIT(1), ++ ESP_DBG_LOG = BIT(2), ++ ESP_DBG = BIT(3), ++ ESP_SHOW = BIT(4), ++ ESP_DBG_TXAMPDU = BIT(5), ++ ESP_DBG_OP = BIT(6), ++ ESP_DBG_PS = BIT(7), ++ ESP_ATE = BIT(8), ++ ESP_DBG_ALL = 0xffffffff ++}; ++ ++extern unsigned int esp_msg_level; ++ ++#ifdef ESP_ANDROID_LOGGER ++extern bool log_off; ++#endif /* ESP_ANDROID_LOGGER */ ++ ++#ifdef ESP_ANDROID_LOGGER ++#include "esp_file.h" ++#define esp_dbg(mask, fmt, args...) do { \ ++ if (esp_msg_level & mask) \ ++ { \ ++ if (log_off) \ ++ printk(fmt, ##args); \ ++ else \ ++ logger_write(4, "esp_wifi", fmt, ##args); \ ++ } \ ++ } while (0) ++#else ++#define esp_dbg(mask, fmt, args...) do { \ ++ if (esp_msg_level & mask) \ ++ printk("esp8089: " fmt, ##args); \ ++ } while (0) ++#endif /* ESP_ANDROID_LOGGER */ ++ ++void show_buf(u8 * buf, u32 len); ++ ++#ifdef HOST_RC ++struct sip_rc_status; ++struct ieee80211_tx_rate; ++ ++void esp_show_rcstatus(struct sip_rc_status *rcstatus); ++ ++void esp_show_tx_rates(struct ieee80211_tx_rate *rates); ++#endif /* HOST_RC */ ++ ++#endif /* _DEBUG_H_ */ +diff --git a/drivers/net/wireless/esp8089/esp_ext.c b/drivers/net/wireless/esp8089/esp_ext.c +new file mode 100644 +index 000000000000..541f27a6853f +--- /dev/null ++++ b/drivers/net/wireless/esp8089/esp_ext.c +@@ -0,0 +1,542 @@ ++/* ++ * Copyright (c) 2010 -2013 Espressif System. ++ * ++ * extended gpio ++ * - interface for other driver or kernel ++ * - gpio control ++ * ++ * 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. ++ */ ++ ++#ifdef USE_EXT_GPIO ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "esp_ext.h" ++#include "esp_debug.h" ++#include "esp_sip.h" ++#include "esp_sif.h" ++ ++#ifdef EXT_GPIO_OPS ++extern void register_ext_gpio_ops(struct esp_ext_gpio_ops *ops); ++extern void unregister_ext_gpio_ops(void); ++ ++static struct esp_ext_gpio_ops ext_gpio_ops = { ++ .gpio_request = ext_gpio_request, /* gpio_request gpio_no from 0x0 to 0xf */ ++ .gpio_release = ext_gpio_release, /* gpio_release */ ++ .gpio_set_mode = ext_gpio_set_mode, /* gpio_set_mode, data is irq_func of irq_mode , default level of output_mode */ ++ .gpio_get_mode = ext_gpio_get_mode, /* gpio_get_mode, current mode */ ++ .gpio_set_state = ext_gpio_set_output_state, /* only output state, high level or low level */ ++ .gpio_get_state = ext_gpio_get_state, /* current state */ ++ .irq_ack = ext_irq_ack, /* ack interrupt */ ++}; ++ ++ ++#endif ++ ++static struct esp_pub *ext_epub = NULL; ++ ++static u16 intr_mask_reg = 0x0000; ++struct workqueue_struct *ext_irq_wkq = NULL; ++struct work_struct ext_irq_work; ++static struct mutex ext_mutex_lock; ++ ++static struct ext_gpio_info gpio_list[EXT_GPIO_MAX_NUM] = { ++ {0, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL}, ++ {1, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL}, ++ {2, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL}, ++ {3, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL}, ++ {4, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL}, ++ {5, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL}, ++ {6, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL}, ++ {7, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL}, ++ {8, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL}, ++ {9, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL}, ++ {10, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL}, ++ {11, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL}, ++ {12, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL}, ++ {13, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL}, ++ {14, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL}, ++ {15, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL}, ++}; ++ ++static struct pending_intr_list_info esp_pending_intr_list = { ++ .start_pos = 0, ++ .end_pos = 0, ++ .curr_num = 0, ++}; ++ ++u16 ext_gpio_get_int_mask_reg(void) ++{ ++ return intr_mask_reg; ++} ++ ++int ext_gpio_request(int gpio_no) ++{ ++ if (ext_epub == NULL || ext_epub->sip == NULL || ++ atomic_read(&ext_epub->sip->state) != SIP_RUN) { ++ esp_dbg(ESP_DBG_ERROR, "%s esp state is not ok\n", ++ __func__); ++ return -ENOTRECOVERABLE; ++ } ++ ++ mutex_lock(&ext_mutex_lock); ++ ++ if (gpio_no >= EXT_GPIO_MAX_NUM || gpio_no < 0) { ++ mutex_unlock(&ext_mutex_lock); ++ esp_dbg(ESP_DBG_ERROR, "%s unkown gpio num\n", __func__); ++ return -ERANGE; ++ } ++ ++ if (gpio_list[gpio_no].gpio_mode != EXT_GPIO_MODE_DISABLE) { ++ mutex_unlock(&ext_mutex_lock); ++ esp_dbg(ESP_DBG_ERROR, ++ "%s gpio is already in used by other\n", __func__); ++ return -EPERM; ++ } else { ++ gpio_list[gpio_no].gpio_mode = EXT_GPIO_MODE_MAX; ++ mutex_unlock(&ext_mutex_lock); ++ return 0; ++ } ++} ++ ++EXPORT_SYMBOL(ext_gpio_request); ++ ++int ext_gpio_release(int gpio_no) ++{ ++ int ret; ++ ++ if (ext_epub == NULL || ext_epub->sip == NULL || ++ atomic_read(&ext_epub->sip->state) != SIP_RUN) { ++ esp_dbg(ESP_DBG_ERROR, "%s esp state is not ok\n", ++ __func__); ++ return -ENOTRECOVERABLE; ++ } ++ ++ mutex_lock(&ext_mutex_lock); ++ ++ if (gpio_no >= EXT_GPIO_MAX_NUM || gpio_no < 0) { ++ mutex_unlock(&ext_mutex_lock); ++ esp_dbg(ESP_DBG_ERROR, "%s unkown gpio num\n", __func__); ++ return -ERANGE; ++ } ++ sif_lock_bus(ext_epub); ++ ret = ++ sif_config_gpio_mode(ext_epub, (u8) gpio_no, ++ EXT_GPIO_MODE_DISABLE); ++ sif_unlock_bus(ext_epub); ++ if (ret) { ++ esp_dbg(ESP_DBG_ERROR, "%s gpio release error\n", ++ __func__); ++ mutex_unlock(&ext_mutex_lock); ++ return ret; ++ } ++ ++ gpio_list[gpio_no].gpio_mode = EXT_GPIO_MODE_DISABLE; ++ gpio_list[gpio_no].gpio_state = EXT_GPIO_STATE_IDLE; ++ gpio_list[gpio_no].irq_handler = NULL; ++ intr_mask_reg &= ~(1 << gpio_no); ++ ++ mutex_unlock(&ext_mutex_lock); ++ ++ return 0; ++} ++ ++EXPORT_SYMBOL(ext_gpio_release); ++ ++int ext_gpio_set_mode(int gpio_no, int mode, void *data) ++{ ++ u8 gpio_mode; ++ int ret; ++ struct ext_gpio_info backup_info; ++ ++ if (ext_epub == NULL || ext_epub->sip == NULL || ++ atomic_read(&ext_epub->sip->state) != SIP_RUN) { ++ esp_dbg(ESP_DBG_LOG, "%s esp state is not ok\n", __func__); ++ return -ENOTRECOVERABLE; ++ } ++ ++ mutex_lock(&ext_mutex_lock); ++ ++ if (gpio_no >= EXT_GPIO_MAX_NUM || gpio_no < 0) { ++ mutex_unlock(&ext_mutex_lock); ++ esp_dbg(ESP_DBG_ERROR, "%s unkown gpio num\n", __func__); ++ return -ERANGE; ++ } ++ ++ if (gpio_list[gpio_no].gpio_mode == EXT_GPIO_MODE_DISABLE) { ++ mutex_unlock(&ext_mutex_lock); ++ esp_dbg(ESP_DBG_ERROR, ++ "%s gpio is not in occupy, please request gpio\n", ++ __func__); ++ return -ENOTRECOVERABLE; ++ } ++ ++ if (mode <= EXT_GPIO_MODE_OOB || mode >= EXT_GPIO_MODE_MAX) { ++ mutex_unlock(&ext_mutex_lock); ++ esp_dbg(ESP_DBG_ERROR, "%s gpio mode unknown\n", __func__); ++ return -EOPNOTSUPP; ++ } ++ ++ memcpy(&backup_info, &gpio_list[gpio_no], ++ sizeof(struct ext_gpio_info)); ++ ++ gpio_list[gpio_no].gpio_mode = mode; ++ gpio_mode = (u8) mode; ++ ++ switch (mode) { ++ case EXT_GPIO_MODE_INTR_POSEDGE: ++ case EXT_GPIO_MODE_INTR_NEGEDGE: ++ case EXT_GPIO_MODE_INTR_LOLEVEL: ++ case EXT_GPIO_MODE_INTR_HILEVEL: ++ if (!data) { ++ memcpy(&gpio_list[gpio_no], &backup_info, ++ sizeof(struct ext_gpio_info)); ++ esp_dbg(ESP_DBG_ERROR, "%s irq_handler is NULL\n", ++ __func__); ++ mutex_unlock(&ext_mutex_lock); ++ return -EINVAL; ++ } ++ gpio_list[gpio_no].irq_handler = (ext_irq_handler_t) data; ++ intr_mask_reg |= (1 << gpio_no); ++ break; ++ case EXT_GPIO_MODE_OUTPUT: ++ if (!data) { ++ memcpy(&gpio_list[gpio_no], &backup_info, ++ sizeof(struct ext_gpio_info)); ++ esp_dbg(ESP_DBG_ERROR, ++ "%s output default value is NULL\n", ++ __func__); ++ mutex_unlock(&ext_mutex_lock); ++ return -EINVAL; ++ } ++ *(int *) data = (*(int *) data == 0 ? 0 : 1); ++ gpio_mode = (u8) (((*(int *) data) << 4) | gpio_mode); ++ default: ++ gpio_list[gpio_no].irq_handler = NULL; ++ intr_mask_reg &= ~(1 << gpio_no); ++ break; ++ } ++ ++ sif_lock_bus(ext_epub); ++ ret = sif_config_gpio_mode(ext_epub, (u8) gpio_no, gpio_mode); ++ sif_unlock_bus(ext_epub); ++ if (ret) { ++ memcpy(&gpio_list[gpio_no], &backup_info, ++ sizeof(struct ext_gpio_info)); ++ esp_dbg(ESP_DBG_ERROR, "%s gpio set error\n", __func__); ++ mutex_unlock(&ext_mutex_lock); ++ return ret; ++ } ++ ++ mutex_unlock(&ext_mutex_lock); ++ return 0; ++} ++ ++EXPORT_SYMBOL(ext_gpio_set_mode); ++ ++int ext_gpio_get_mode(int gpio_no) ++{ ++ int gpio_mode; ++ ++ if (ext_epub == NULL || ext_epub->sip == NULL || ++ atomic_read(&ext_epub->sip->state) != SIP_RUN) { ++ esp_dbg(ESP_DBG_LOG, "%s esp state is not ok\n", __func__); ++ return -ENOTRECOVERABLE; ++ } ++ ++ mutex_lock(&ext_mutex_lock); ++ ++ if (gpio_no >= EXT_GPIO_MAX_NUM || gpio_no < 0) { ++ esp_dbg(ESP_DBG_ERROR, "%s unkown gpio num\n", __func__); ++ mutex_unlock(&ext_mutex_lock); ++ return -ERANGE; ++ } ++ ++ gpio_mode = gpio_list[gpio_no].gpio_mode; ++ ++ mutex_unlock(&ext_mutex_lock); ++ ++ return gpio_mode; ++} ++ ++EXPORT_SYMBOL(ext_gpio_get_mode); ++ ++ ++int ext_gpio_set_output_state(int gpio_no, int state) ++{ ++ int ret; ++ ++ if (ext_epub == NULL || ext_epub->sip == NULL || ++ atomic_read(&ext_epub->sip->state) != SIP_RUN) { ++ esp_dbg(ESP_DBG_LOG, "%s esp state is not ok\n", __func__); ++ return -ENOTRECOVERABLE; ++ } ++ ++ mutex_lock(&ext_mutex_lock); ++ ++ if (gpio_no >= EXT_GPIO_MAX_NUM || gpio_no < 0) { ++ mutex_unlock(&ext_mutex_lock); ++ esp_dbg(ESP_DBG_ERROR, "%s unkown gpio num\n", __func__); ++ return -ERANGE; ++ } ++ ++ if (gpio_list[gpio_no].gpio_mode != EXT_GPIO_MODE_OUTPUT) { ++ mutex_unlock(&ext_mutex_lock); ++ esp_dbg(ESP_DBG_ERROR, ++ "%s gpio is not in output state, please request gpio or set output state\n", ++ __func__); ++ return -EOPNOTSUPP; ++ } ++ ++ if (state != EXT_GPIO_STATE_LOW && state != EXT_GPIO_STATE_HIGH) { ++ mutex_unlock(&ext_mutex_lock); ++ esp_dbg(ESP_DBG_ERROR, "%s gpio state unknown\n", ++ __func__); ++ return -ENOTRECOVERABLE; ++ } ++ ++ sif_lock_bus(ext_epub); ++ ret = ++ sif_set_gpio_output(ext_epub, 1 << gpio_no, state << gpio_no); ++ sif_unlock_bus(ext_epub); ++ if (ret) { ++ esp_dbg(ESP_DBG_ERROR, "%s gpio state set error\n", ++ __func__); ++ mutex_unlock(&ext_mutex_lock); ++ return ret; ++ } ++ gpio_list[gpio_no].gpio_state = state; ++ ++ mutex_unlock(&ext_mutex_lock); ++ ++ return 0; ++} ++ ++EXPORT_SYMBOL(ext_gpio_set_output_state); ++ ++int ext_gpio_get_state(int gpio_no) ++{ ++ int ret; ++ u16 state; ++ u16 mask; ++ ++ if (ext_epub == NULL || ext_epub->sip == NULL || ++ atomic_read(&ext_epub->sip->state) != SIP_RUN) { ++ esp_dbg(ESP_DBG_LOG, "%s esp state is not ok\n", __func__); ++ return -ENOTRECOVERABLE; ++ } ++ ++ mutex_lock(&ext_mutex_lock); ++ ++ if (gpio_no >= EXT_GPIO_MAX_NUM || gpio_no < 0) { ++ esp_dbg(ESP_DBG_ERROR, "%s unkown gpio num\n", __func__); ++ mutex_unlock(&ext_mutex_lock); ++ return -ERANGE; ++ } ++ ++ if (gpio_list[gpio_no].gpio_mode == EXT_GPIO_MODE_OUTPUT) { ++ state = gpio_list[gpio_no].gpio_state; ++ } else if (gpio_list[gpio_no].gpio_mode == EXT_GPIO_MODE_INPUT) { ++ sif_lock_bus(ext_epub); ++ ret = sif_get_gpio_input(ext_epub, &mask, &state); ++ sif_unlock_bus(ext_epub); ++ if (ret) { ++ esp_dbg(ESP_DBG_ERROR, ++ "%s get gpio_input state error\n", ++ __func__); ++ mutex_unlock(&ext_mutex_lock); ++ return ret; ++ } ++ } else { ++ esp_dbg(ESP_DBG_ERROR, ++ "%s gpio_state is not input or output\n", ++ __func__); ++ mutex_unlock(&ext_mutex_lock); ++ return -EOPNOTSUPP; ++ } ++ mutex_unlock(&ext_mutex_lock); ++ ++ return (state & (1 << gpio_no)) ? 1 : 0; ++} ++ ++EXPORT_SYMBOL(ext_gpio_get_state); ++ ++int ext_irq_ack(int gpio_no) ++{ ++ int ret; ++ ++ if (ext_epub == NULL || ext_epub->sip == NULL || ++ atomic_read(&ext_epub->sip->state) != SIP_RUN) { ++ esp_dbg(ESP_DBG_LOG, "%s esp state is not ok\n", __func__); ++ return -ENOTRECOVERABLE; ++ } ++ ++ mutex_lock(&ext_mutex_lock); ++ if (gpio_no >= EXT_GPIO_MAX_NUM || gpio_no < 0) { ++ esp_dbg(ESP_DBG_ERROR, "%s unkown gpio num\n", __func__); ++ mutex_unlock(&ext_mutex_lock); ++ return -ERANGE; ++ } ++ ++ if (gpio_list[gpio_no].gpio_mode != EXT_GPIO_MODE_INTR_POSEDGE ++ && gpio_list[gpio_no].gpio_mode != EXT_GPIO_MODE_INTR_NEGEDGE ++ && gpio_list[gpio_no].gpio_mode != EXT_GPIO_MODE_INTR_LOLEVEL ++ && gpio_list[gpio_no].gpio_mode != ++ EXT_GPIO_MODE_INTR_HILEVEL) { ++ esp_dbg(ESP_DBG_ERROR, "%s gpio mode is not intr mode\n", ++ __func__); ++ mutex_unlock(&ext_mutex_lock); ++ return -ENOTRECOVERABLE; ++ } ++ ++ sif_lock_bus(ext_epub); ++ ret = sif_set_gpio_output(ext_epub, 0x00, 1 << gpio_no); ++ sif_unlock_bus(ext_epub); ++ if (ret) { ++ esp_dbg(ESP_DBG_ERROR, "%s gpio intr ack error\n", ++ __func__); ++ mutex_unlock(&ext_mutex_lock); ++ return ret; ++ } ++ ++ mutex_unlock(&ext_mutex_lock); ++ return 0; ++} ++ ++EXPORT_SYMBOL(ext_irq_ack); ++ ++void show_status(void) ++{ ++ int i = 0; ++ for (i = 0; i < MAX_PENDING_INTR_LIST; i++) ++ esp_dbg(ESP_DBG_ERROR, "status[%d] = [0x%04x]\n", i, ++ esp_pending_intr_list.pending_intr_list[i]); ++ ++ esp_dbg(ESP_DBG_ERROR, "start_pos[%d]\n", ++ esp_pending_intr_list.start_pos); ++ esp_dbg(ESP_DBG_ERROR, "end_pos[%d]\n", ++ esp_pending_intr_list.end_pos); ++ esp_dbg(ESP_DBG_ERROR, "curr_num[%d]\n", ++ esp_pending_intr_list.curr_num); ++ ++} ++void esp_tx_work(struct work_struct *work) ++{ ++ int i; ++ u16 tmp_intr_status_reg; ++ ++ esp_dbg(ESP_DBG_TRACE, "%s enter\n", __func__); ++ ++ spin_lock(&esp_pending_intr_list.spin_lock); ++ ++ tmp_intr_status_reg = ++ esp_pending_intr_list.pending_intr_list[esp_pending_intr_list. ++ start_pos]; ++ ++ esp_pending_intr_list.pending_intr_list[esp_pending_intr_list. ++ start_pos] = 0x0000; ++ esp_pending_intr_list.start_pos = ++ (esp_pending_intr_list.start_pos + 1) % MAX_PENDING_INTR_LIST; ++ esp_pending_intr_list.curr_num--; ++ ++ spin_unlock(&esp_pending_intr_list.spin_lock); ++ ++ for (i = 0; i < EXT_GPIO_MAX_NUM; i++) { ++ if (tmp_intr_status_reg & (1 << i) ++ && (gpio_list[i].irq_handler)) ++ gpio_list[i].irq_handler(); ++ } ++ ++ spin_lock(&esp_pending_intr_list.spin_lock); ++ if (esp_pending_intr_list.curr_num > 0) ++ queue_work(ext_irq_wkq, &ext_irq_work); ++ spin_unlock(&esp_pending_intr_list.spin_lock); ++} ++ ++void ext_gpio_int_process(u16 value) ++{ ++ if (value == 0x00) ++ return; ++ ++ esp_dbg(ESP_DBG_TRACE, "%s enter\n", __func__); ++ ++ /* intr cycle queue is full, wait */ ++ while (esp_pending_intr_list.curr_num >= MAX_PENDING_INTR_LIST) { ++ udelay(1); ++ } ++ ++ spin_lock(&esp_pending_intr_list.spin_lock); ++ ++ esp_pending_intr_list.pending_intr_list[esp_pending_intr_list. ++ end_pos] = value; ++ esp_pending_intr_list.end_pos = ++ (esp_pending_intr_list.end_pos + 1) % MAX_PENDING_INTR_LIST; ++ esp_pending_intr_list.curr_num++; ++ ++ queue_work(ext_irq_wkq, &ext_irq_work); ++ ++ spin_unlock(&esp_pending_intr_list.spin_lock); ++} ++ ++int ext_gpio_init(struct esp_pub *epub) ++{ ++ esp_dbg(ESP_DBG_ERROR, "%s enter\n", __func__); ++ ++ ext_irq_wkq = create_singlethread_workqueue("esp_ext_irq_wkq"); ++ if (ext_irq_wkq == NULL) { ++ esp_dbg(ESP_DBG_ERROR, "%s create workqueue error\n", ++ __func__); ++ return -EACCES; ++ } ++ ++ INIT_WORK(&ext_irq_work, esp_tx_work); ++ mutex_init(&ext_mutex_lock); ++ ++ ext_epub = epub; ++ ++ if (ext_epub == NULL) ++ return -EINVAL; ++ ++#ifdef EXT_GPIO_OPS ++ register_ext_gpio_ops(&ext_gpio_ops); ++#endif ++ ++ return 0; ++} ++ ++void ext_gpio_deinit(void) ++{ ++ esp_dbg(ESP_DBG_ERROR, "%s enter\n", __func__); ++ ++#ifdef EXT_GPIO_OPS ++ unregister_ext_gpio_ops(); ++#endif ++ ext_epub = NULL; ++ cancel_work_sync(&ext_irq_work); ++ ++ if (ext_irq_wkq) ++ destroy_workqueue(ext_irq_wkq); ++ ++} ++ ++#endif /* USE_EXT_GPIO */ +diff --git a/drivers/net/wireless/esp8089/esp_ext.h b/drivers/net/wireless/esp8089/esp_ext.h +new file mode 100644 +index 000000000000..0eeba4d22111 +--- /dev/null ++++ b/drivers/net/wireless/esp8089/esp_ext.h +@@ -0,0 +1,100 @@ ++#ifdef USE_EXT_GPIO ++ ++#ifndef _ESP_EXT_H_ ++#define _ESP_EXT_H_ ++ ++#include ++#include ++#include "esp_sip.h" ++ ++#define MAX_PENDING_INTR_LIST 16 ++ ++#ifdef EXT_GPIO_OPS ++typedef struct esp_ext_gpio_ops { ++ int (*gpio_request) (int gpio_no); /* gpio_request gpio_no from 0x0 to 0xf */ ++ int (*gpio_release) (int gpio_no); /* gpio_release */ ++ int (*gpio_set_mode) (int gpio_no, int mode, void *data); /* gpio_set_mode, data is irq_func of irq_mode , default level of output_mode */ ++ int (*gpio_get_mode) (int gpio_no); /* gpio_get_mode, current mode */ ++ int (*gpio_set_state) (int gpio_no, int state); /* only output state, high level or low level */ ++ int (*gpio_get_state) (int gpio_no); /* current state */ ++ int (*irq_ack) (int gpio_no); /* ack interrupt */ ++} esp_ext_gpio_ops_t; ++#endif ++ ++typedef enum EXT_GPIO_NO { ++ EXT_GPIO_GPIO0 = 0, ++ EXT_GPIO_U0TXD, ++ EXT_GPIO_GPIO2, ++ EXT_GPIO_U0RXD, ++ EXT_GPIO_GPIO4, ++ EXT_GPIO_GPIO5, ++ EXT_GPIO_SD_CLK, ++ EXT_GPIO_SD_DATA0, ++ EXT_GPIO_SD_DATA1, ++ EXT_GPIO_SD_DATA2, ++ EXT_GPIO_SD_DATA3, ++ EXT_GPIO_SD_CMD, ++ EXT_GPIO_MTDI, ++ EXT_GPIO_MTCK, ++ EXT_GPIO_MTMS, ++ EXT_GPIO_MTDO, ++ EXT_GPIO_MAX_NUM ++} EXT_GPIO_NO_T; ++ ++typedef enum EXT_GPIO_MODE { //dir def pullup mode wake ++ EXT_GPIO_MODE_OOB = 0, //output 1 0 n/a n/a ++ EXT_GPIO_MODE_OUTPUT, //output / 0 n/a n/a ++ EXT_GPIO_MODE_DISABLE, //input n/a 0 DIS n/a ++ EXT_GPIO_MODE_INTR_POSEDGE, //input n/a 0 POS 1 ++ EXT_GPIO_MODE_INTR_NEGEDGE, //input n/a 1 NEG 1 ++ EXT_GPIO_MODE_INPUT, //input n/a 0 ANY 1 ++ EXT_GPIO_MODE_INTR_LOLEVEL, //input n/a 1 LOW 1 ++ EXT_GPIO_MODE_INTR_HILEVEL, //input n/a 0 HIGH 1 ++ EXT_GPIO_MODE_MAX, ++} EXT_GPIO_MODE_T; ++ ++typedef enum EXT_GPIO_STATE { ++ EXT_GPIO_STATE_LOW, ++ EXT_GPIO_STATE_HIGH, ++ EXT_GPIO_STATE_IDLE ++} EXT_GPIO_STATE_T; ++ ++typedef irqreturn_t(*ext_irq_handler_t) (void); ++ ++struct ext_gpio_info { ++ int gpio_no; ++ int gpio_mode; ++ int gpio_state; ++ ext_irq_handler_t irq_handler; ++}; ++ ++struct pending_intr_list_info { ++ u16 pending_intr_list[MAX_PENDING_INTR_LIST]; ++ int start_pos; ++ int end_pos; ++ int curr_num; ++ spinlock_t spin_lock; ++}; ++ ++u16 ext_gpio_get_int_mask_reg(void); ++ ++/* for extern user start */ ++int ext_gpio_request(int gpio_no); ++int ext_gpio_release(int gpio_no); ++ ++int ext_gpio_set_mode(int gpio_no, int mode, void *data); ++int ext_gpio_get_mode(int gpio_no); ++ ++int ext_gpio_set_output_state(int gpio_no, int state); ++int ext_gpio_get_state(int gpio_no); ++ ++int ext_irq_ack(int gpio_no); ++/* for extern user end */ ++ ++void ext_gpio_int_process(u16 value); ++ ++int ext_gpio_init(struct esp_pub *epub); ++void ext_gpio_deinit(void); ++#endif /* _ESP_EXT_H_ */ ++ ++#endif /* USE_EXT_GPIO */ +diff --git a/drivers/net/wireless/esp8089/esp_file.c b/drivers/net/wireless/esp8089/esp_file.c +new file mode 100644 +index 000000000000..ea702f010eec +--- /dev/null ++++ b/drivers/net/wireless/esp8089/esp_file.c +@@ -0,0 +1,258 @@ ++/* ++ * Copyright (c) 2010 -2014 Espressif System. ++ * ++ * file operation in kernel space ++ * ++ * 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "esp_file.h" ++#include "esp_debug.h" ++#include "esp_sif.h" ++ ++static int mod_parm_crystal = -1; ++module_param_named(crystal, mod_parm_crystal, int, 0444); ++MODULE_PARM_DESC(crystal, "crystal frequency: 0=40MHz, 1=26MHz, 2=24MHz"); ++ ++struct esp_init_table_elem esp_init_table[MAX_ATTR_NUM] = { ++ /* ++ * Crystal type: ++ * 0: 40MHz (default) ++ * 1: 26MHz (ESP8266 ESP-12F) ++ * 2: 24MHz ++ */ ++ {"crystal_26M_en", 48, 0}, ++ /* ++ * Output crystal clock to pin: ++ * 0: None ++ * 1: GPIO1 ++ * 2: URXD0 ++ */ ++ {"test_xtal", 49, 0}, ++ /* ++ * Host SDIO mode: ++ * 0: Auto by pin strapping ++ * 1: SDIO data output on negative edges (SDIO v1.1) ++ * 2: SDIO data output on positive edges (SDIO v2.0) ++ */ ++ {"sdio_configure", 50, 2}, ++ /* ++ * WiFi/Bluetooth co-existence with BK3515A BT chip ++ * 0: None ++ * 1: GPIO0->WLAN_ACTIVE, MTMS->BT_ACTIVE, MTDI->BT_PRIORITY, ++ * U0TXD->ANT_SEL_BT, U0RXD->ANT_SEL_WIFI ++ */ ++ {"bt_configure", 51, 0}, ++ /* ++ * Antenna selection: ++ * 0: Antenna is for WiFi ++ * 1: Antenna is for Bluetooth ++ */ ++ {"bt_protocol", 52, 0}, ++ /* ++ * Dual antenna configuration mode: ++ * 0: None ++ * 1: U0RXD + XPD_DCDC ++ * 2: U0RXD + GPIO0 ++ * 3: U0RXD + U0TXD ++ */ ++ {"dual_ant_configure", 53, 0}, ++ /* ++ * Firmware debugging output pin: ++ * 0: None ++ * 1: UART TX on GPIO2 ++ * 2: UART TX on U0TXD ++ */ ++ {"test_uart_configure", 54, 2}, ++ /* ++ * Whether to share crystal clock with BT (in sleep mode): ++ * 0: no ++ * 1: always on ++ * 2: automatically on according to XPD_DCDC ++ */ ++ {"share_xtal", 55, 0}, ++ /* ++ * Allow chip to be woken up during sleep on pin: ++ * 0: None ++ * 1: XPD_DCDC ++ * 2: GPIO0 ++ * 3: Both XPD_DCDC and GPIO0 ++ */ ++ {"gpio_wake", 56, 0}, ++ {"no_auto_sleep", 57, 0}, ++ {"speed_suspend", 58, 0}, ++ {"attr11", -1, -1}, ++ {"attr12", -1, -1}, ++ {"attr13", -1, -1}, ++ {"attr14", -1, -1}, ++ {"attr15", -1, -1}, ++ //attr that is not send to target ++ /* ++ * Allow chip to be reset by GPIO pin: ++ * 0: no ++ * 1: yes ++ */ ++ {"ext_rst", -1, 0}, ++ {"wakeup_gpio", -1, 12}, ++ {"ate_test", -1, 0}, ++ {"attr19", -1, -1}, ++ {"attr20", -1, -1}, ++ {"attr21", -1, -1}, ++ {"attr22", -1, -1}, ++ {"attr23", -1, -1}, ++}; ++ ++/* ++ * Export part of the configuration related to first initiliazition to the esp8089 ++ */ ++void esp_conf_upload_first(void) ++{ ++ int i; ++ ++ for (i = 0; i < MAX_ATTR_NUM; i++) { ++ if (esp_init_table[i].value < 0) ++ continue; ++ ++ if (!strcmp(esp_init_table[i].attr, "share_xtal")) ++ sif_record_bt_config(esp_init_table[i].value); ++ else if (!strcmp(esp_init_table[i].attr, "ext_rst")) ++ sif_record_rst_config(esp_init_table[i].value); ++ else if (!strcmp(esp_init_table[i].attr, "wakeup_gpio")) ++ sif_record_wakeup_gpio_config(esp_init_table[i].value); ++ else if (!strcmp(esp_init_table[i].attr, "ate_test")) ++ sif_record_ate_config(esp_init_table[i].value); ++ } ++} ++ ++/* ++ * Export part of the configuration related to second initiliazition ++ */ ++void esp_conf_upload_second(u8 * init_data_buf, int buf_size) ++{ ++ int i; ++ ++ for (i = 0; i < MAX_FIX_ATTR_NUM; i++) { ++ if (esp_init_table[i].offset > -1 ++ && esp_init_table[i].offset < buf_size ++ && esp_init_table[i].value > -1) { ++ *(u8 *) (init_data_buf + ++ esp_init_table[i].offset) = ++ esp_init_table[i].value; ++ } else if (esp_init_table[i].offset > buf_size) { ++ esp_dbg(ESP_DBG_ERROR, ++ "%s: offset[%d] longer than init_data_buf len[%d] Ignore\n", ++ __FUNCTION__, esp_init_table[i].offset, ++ buf_size); ++ } ++ } ++ ++} ++ ++ ++void esp_conf_init(struct device *dev) ++{ ++ ++ struct device_node *np = dev->of_node; ++ ++ if (np) { ++ ++ u32 value; ++ ++ if (!of_property_read_u32(np, "esp,crystal-26M-en", &value)) ++ esp_conf_set_attr("crystal_26M_en", value); ++ ++ if (!of_property_read_u32(np, "esp,sdio-configure", &value)) ++ esp_conf_set_attr("sdio_configure", value); ++ ++ if (of_property_read_bool(np, "esp,shared-xtal")) ++ esp_conf_set_attr("share_xtal", 1); ++ ++ if (!of_property_read_u32(np, "esp,gpio-wake", &value)) ++ esp_conf_set_attr("gpio_wake", value); ++ ++ if (!of_property_read_u32(np, "esp,wakeup-gpio", &value)) ++ esp_conf_set_attr("wakeup_gpio", value); ++ ++ if (of_property_read_bool(np, "esp,configure-dual-antenna")) ++ esp_conf_set_attr("dual_ant_configure", 1); ++ ++ if (of_property_read_bool(np, "esp,no-auto-sleep")) ++ esp_conf_set_attr("no_auto_sleep", 1); ++ ++ if (of_property_read_bool(np, "esp,test-xtal")) ++ esp_conf_set_attr("test_xtal", 1); ++ ++ if (of_property_read_bool(np, "esp,bt-configure")) ++ esp_conf_set_attr("bt_configure", 1); ++ ++ if (!of_property_read_u32(np, "esp,bt-protocol", &value)) ++ esp_conf_set_attr("bt_protocol", value); ++ ++ if (of_property_read_bool(np, "esp,test-uart-configure")) ++ esp_conf_set_attr("test_uart_configure", 1); ++ ++ if (of_property_read_bool(np, "esp,speed-suspend")) ++ esp_conf_set_attr("speed_suspend", 1); ++ ++ if (of_property_read_bool(np, "esp,ate-test")) ++ esp_conf_set_attr("ate_test", 1); ++ ++ if (!of_property_read_u32(np, "esp,ext-rst", &value)) ++ esp_conf_set_attr("ext_rst", value); ++ ++ } ++ ++ if (mod_parm_crystal >= 0 && mod_parm_crystal <= 2) ++ esp_conf_set_attr("crystal_26M_en", mod_parm_crystal); ++ ++ ++ esp_conf_show_attrs(); ++ ++} ++ ++int esp_conf_set_attr(char *name, u8 value) { ++ ++ int i; ++ ++ for (i = 0; i < MAX_ATTR_NUM; i++) { ++ ++ if (strcmp(esp_init_table[i].attr, name) == 0) { ++ esp_dbg(ESP_DBG, "set config: %s value: %d", name, value); ++ esp_init_table[i].value = value; ++ return 0; ++ } ++ ++ } ++ ++ return -1; ++ ++} ++ ++void esp_conf_show_attrs(void) ++{ ++ int i; ++ for (i = 0; i < MAX_ATTR_NUM; i++) ++ if (esp_init_table[i].offset > -1) ++ esp_dbg(ESP_SHOW, "config parm:%s (id:%d), value: %d\n", ++ esp_init_table[i].attr, ++ esp_init_table[i].offset, ++ esp_init_table[i].value); ++} +diff --git a/drivers/net/wireless/esp8089/esp_file.h b/drivers/net/wireless/esp8089/esp_file.h +new file mode 100644 +index 000000000000..5ba39c626baa +--- /dev/null ++++ b/drivers/net/wireless/esp8089/esp_file.h +@@ -0,0 +1,43 @@ ++/* ++ * Copyright (c) 2010 -2014 Espressif System. ++ * ++ * file operation in kernel space ++ * ++ * 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 _ESP_FILE_H_ ++#define _ESP_FILE_H_ ++ ++#include ++#include ++ ++#define E_ROUND_UP(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) ++ ++#define CONF_ATTR_LEN 24 ++#define CONF_VAL_LEN 3 ++#define MAX_ATTR_NUM 24 ++#define MAX_FIX_ATTR_NUM 16 ++#define MAX_BUF_LEN ((CONF_ATTR_LEN + CONF_VAL_LEN + 2) * MAX_ATTR_NUM + 2) ++ ++struct esp_init_table_elem { ++ char attr[CONF_ATTR_LEN]; ++ int offset; ++ short value; ++}; ++ ++void esp_conf_init(struct device *dev); ++void esp_conf_upload_first(void); ++void esp_conf_upload_second(u8 * init_data_buf, int buf_size); ++int esp_conf_set_attr(char *name, u8 value); ++void esp_conf_show_attrs(void); ++ ++#endif /* _ESP_FILE_H_ */ +diff --git a/drivers/net/wireless/esp8089/esp_init_data.h b/drivers/net/wireless/esp8089/esp_init_data.h +new file mode 100644 +index 000000000000..16f451affd1e +--- /dev/null ++++ b/drivers/net/wireless/esp8089/esp_init_data.h +@@ -0,0 +1,7 @@ ++static char esp_init_data[] = ++ { 0x5, 0x0, 4, 2, 5, 5, 5, 2, 5, 0, 4, 5, 5, 4, 5, 5, 4, -2, -3, -1, ++-16, -16, -16, -32, -32, -32, 204, 1, 0xff, 0xff, 0, 0, 0, 0, 82, 78, 74, 68, 64, 56, 0, ++0, 1, 1, 2, 3, 4, 5, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 10, 0x0, 0x0, ++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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++0 }; +diff --git a/drivers/net/wireless/esp8089/esp_io.c b/drivers/net/wireless/esp8089/esp_io.c +new file mode 100644 +index 000000000000..6c5c01aad4e5 +--- /dev/null ++++ b/drivers/net/wireless/esp8089/esp_io.c +@@ -0,0 +1,639 @@ ++/* ++ * Copyright (c) 2009 - 2014 Espressif System. ++ * IO interface ++ * - sdio/spi common i/f driver ++ * - target sdio hal ++ * ++ * 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. ++ */ ++ ++#include ++#include "esp_sif.h" ++#include "slc_host_register.h" ++#include "esp_debug.h" ++ ++#ifdef SIF_DEBUG_DSR_DUMP_REG ++static void dump_slc_regs(struct slc_host_regs *regs); ++#endif /* SIF_DEBUG_DSR_DUMP_REG */ ++ ++int esp_common_read(struct esp_pub *epub, u8 * buf, u32 len, int sync, ++ bool noround) ++{ ++ if (sync) { ++ return sif_lldesc_read_sync(epub, buf, len); ++ } else { ++ return sif_lldesc_read_raw(epub, buf, len, noround); ++ } ++} ++ ++ ++int esp_common_write(struct esp_pub *epub, u8 * buf, u32 len, int sync) ++{ ++ if (sync) { ++ return sif_lldesc_write_sync(epub, buf, len); ++ } else { ++ return sif_lldesc_write_raw(epub, buf, len); ++ } ++} ++ ++ ++int esp_common_read_with_addr(struct esp_pub *epub, u32 addr, u8 * buf, ++ u32 len, int sync) ++{ ++ if (sync) { ++ return sif_io_sync(epub, addr, buf, len, ++ SIF_FROM_DEVICE | SIF_SYNC | ++ SIF_BYTE_BASIS | SIF_INC_ADDR); ++ } else { ++ return sif_io_raw(epub, addr, buf, len, ++ SIF_FROM_DEVICE | SIF_BYTE_BASIS | ++ SIF_INC_ADDR); ++ } ++ ++} ++ ++ ++int esp_common_write_with_addr(struct esp_pub *epub, u32 addr, u8 * buf, ++ u32 len, int sync) ++{ ++ if (sync) { ++ return sif_io_sync(epub, addr, buf, len, ++ SIF_TO_DEVICE | SIF_SYNC | ++ SIF_BYTE_BASIS | SIF_INC_ADDR); ++ } else { ++ return sif_io_raw(epub, addr, buf, len, ++ SIF_TO_DEVICE | SIF_BYTE_BASIS | ++ SIF_INC_ADDR); ++ } ++} ++ ++int esp_common_readbyte_with_addr(struct esp_pub *epub, u32 addr, u8 * buf, ++ int sync) ++{ ++ if (sync) { ++ int res; ++ sif_lock_bus(epub); ++ *buf = sdio_io_readb(epub, addr, &res); ++ sif_unlock_bus(epub); ++ return res; ++ } else { ++ int res; ++ *buf = sdio_io_readb(epub, addr, &res); ++ return res; ++ } ++ ++} ++ ++ ++ ++int esp_common_writebyte_with_addr(struct esp_pub *epub, u32 addr, u8 buf, ++ int sync) ++{ ++ if (sync) { ++ int res; ++ sif_lock_bus(epub); ++ sdio_io_writeb(epub, buf, addr, &res); ++ sif_unlock_bus(epub); ++ return res; ++ } else { ++ int res; ++ sdio_io_writeb(epub, buf, addr, &res); ++ return res; ++ } ++} ++ ++int sif_read_reg_window(struct esp_pub *epub, unsigned int reg_addr, ++ u8 * value) ++{ ++ u8 *p_tbuf = NULL; ++ int ret = 0; ++ int retry = 20; ++ ++ reg_addr >>= 2; ++ if (reg_addr > 0x1f) ++ return -1; ++ ++ p_tbuf = kzalloc(4, GFP_KERNEL); ++ if (p_tbuf == NULL) ++ return -ENOMEM; ++ ++ p_tbuf[0] = 0x80 | (reg_addr & 0x1f); ++ ++ ret = ++ esp_common_write_with_addr(epub, SLC_HOST_WIN_CMD, p_tbuf, 1, ++ ESP_SIF_NOSYNC); ++ ++ if (ret == 0) { ++ do { ++ if (retry < 20) ++ mdelay(10); ++ retry--; ++ ret = ++ esp_common_read_with_addr(epub, ++ SLC_HOST_STATE_W0, ++ p_tbuf, 4, ++ ESP_SIF_NOSYNC); ++ } while (retry > 0 && ret != 0); ++ } ++ ++ if (ret == 0) ++ memcpy(value, p_tbuf, 4); ++ ++ kfree(p_tbuf); ++ return ret; ++} ++ ++int sif_write_reg_window(struct esp_pub *epub, unsigned int reg_addr, ++ u8 * value) ++{ ++ u8 *p_tbuf = NULL; ++ int ret = 0; ++ ++ reg_addr >>= 2; ++ if (reg_addr > 0x1f) ++ return -1; ++ ++ p_tbuf = kzalloc(8, GFP_KERNEL); ++ if (p_tbuf == NULL) ++ return -ENOMEM; ++ memcpy(p_tbuf, value, 4); ++ p_tbuf[4] = 0xc0 | (reg_addr & 0x1f); ++ ++ ret = ++ esp_common_write_with_addr(epub, SLC_HOST_CONF_W5, p_tbuf, 5, ++ ESP_SIF_NOSYNC); ++ ++ kfree(p_tbuf); ++ return ret; ++} ++ ++int sif_ack_target_read_err(struct esp_pub *epub) ++{ ++ u32 value[1]; ++ int ret; ++ ++ ret = sif_read_reg_window(epub, SLC_RX_LINK, (u8 *) value); ++ if (ret) ++ return ret; ++ value[0] |= SLC_RXLINK_START; ++ ret = sif_write_reg_window(epub, SLC_RX_LINK, (u8 *) value); ++ return ret; ++} ++ ++int sif_had_io_enable(struct esp_pub *epub) ++{ ++ u32 *p_tbuf = NULL; ++ int ret; ++ ++ p_tbuf = kzalloc(sizeof(u32), GFP_KERNEL); ++ if (p_tbuf == NULL) ++ return -ENOMEM; ++ ++ *p_tbuf = ++ SLC_TXEOF_ENA | (0x4 << SLC_FIFO_MAP_ENA_S) | SLC_TX_DUMMY_MODE ++ | SLC_HDA_MAP_128K | (0xFE << SLC_TX_PUSH_IDLE_NUM_S); ++ ret = sif_write_reg_window(epub, SLC_BRIDGE_CONF, (u8 *) p_tbuf); ++ ++ if (ret) ++ goto _err; ++ ++ *p_tbuf = 0x30; ++ ret = ++ esp_common_write_with_addr((epub), SLC_HOST_CONF_W4 + 1, ++ (u8 *) p_tbuf, 1, ESP_SIF_NOSYNC); ++ ++ if (ret) ++ goto _err; ++ //set w3 0 ++ *p_tbuf = 0x1; ++ ret = ++ esp_common_write_with_addr((epub), SLC_HOST_CONF_W3, ++ (u8 *) p_tbuf, 1, ESP_SIF_NOSYNC); ++ ++ _err: ++ kfree(p_tbuf); ++ return ret; ++} ++ ++typedef enum _SDIO_INTR_MODE { ++ SDIO_INTR_IB = 0, ++ SDIO_INTR_OOB_TOGGLE, ++ SDIO_INTR_OOB_HIGH_LEVEL, ++ SDIO_INTR_OOB_LOW_LEVEL, ++} SDIO_INTR_MODE; ++ ++#define GEN_GPIO_SEL(_gpio_num, _sel_func, _intr_mode, _offset) (((_offset)<< 9 ) |((_intr_mode) << 7)|((_sel_func) << 4)|(_gpio_num)) ++//bit[3:0] = gpio num, 2 ++//bit[6:4] = gpio sel func, 0 ++//bit[8:7] = gpio intr mode, SDIO_INTR_OOB_TOGGLE ++//bit[15:9] = register offset, 0x38 ++ ++u16 gpio_sel_sets[17] = { ++ GEN_GPIO_SEL(0, 0, SDIO_INTR_OOB_TOGGLE, 0x34), //GPIO0 ++ GEN_GPIO_SEL(1, 3, SDIO_INTR_OOB_TOGGLE, 0x18), //U0TXD ++ GEN_GPIO_SEL(2, 0, SDIO_INTR_OOB_TOGGLE, 0x38), //GPIO2 ++ GEN_GPIO_SEL(3, 3, SDIO_INTR_OOB_TOGGLE, 0x14), //U0RXD ++ GEN_GPIO_SEL(4, 0, SDIO_INTR_OOB_TOGGLE, 0x3C), //GPIO4 ++ GEN_GPIO_SEL(5, 0, SDIO_INTR_OOB_TOGGLE, 0x40), //GPIO5 ++ GEN_GPIO_SEL(6, 3, SDIO_INTR_OOB_TOGGLE, 0x1C), //SD_CLK ++ GEN_GPIO_SEL(7, 3, SDIO_INTR_OOB_TOGGLE, 0x20), //SD_DATA0 ++ GEN_GPIO_SEL(8, 3, SDIO_INTR_OOB_TOGGLE, 0x24), //SD_DATA1 ++ GEN_GPIO_SEL(9, 3, SDIO_INTR_OOB_TOGGLE, 0x28), //SD_DATA2 ++ GEN_GPIO_SEL(10, 3, SDIO_INTR_OOB_TOGGLE, 0x2C), //SD_DATA3 ++ GEN_GPIO_SEL(11, 3, SDIO_INTR_OOB_TOGGLE, 0x30), //SD_CMD ++ GEN_GPIO_SEL(12, 3, SDIO_INTR_OOB_TOGGLE, 0x04), //MTDI ++ GEN_GPIO_SEL(13, 3, SDIO_INTR_OOB_TOGGLE, 0x08), //MTCK ++ GEN_GPIO_SEL(14, 3, SDIO_INTR_OOB_TOGGLE, 0x0C), //MTMS ++ GEN_GPIO_SEL(15, 3, SDIO_INTR_OOB_TOGGLE, 0x10), //MTDO ++ //pls do not change sel before, if you want to change intr mode,change the one blow ++ //GEN_GPIO_SEL(2, 0, SDIO_INTR_OOB_TOGGLE, 0x38) ++ GEN_GPIO_SEL(2, 0, SDIO_INTR_OOB_LOW_LEVEL, 0x38) ++}; ++ ++#if defined(USE_EXT_GPIO) ++u16 gpio_forbidden = 0; ++#endif ++ ++int sif_interrupt_target(struct esp_pub *epub, u8 index) ++{ ++ u8 low_byte = BIT(index); ++ return esp_common_writebyte_with_addr(epub, SLC_HOST_CONF_W4 + 2, ++ low_byte, ESP_SIF_NOSYNC); ++ ++} ++ ++#ifdef USE_EXT_GPIO ++int sif_config_gpio_mode(struct esp_pub *epub, u8 gpio_num, u8 gpio_mode) ++{ ++ u32 *p_tbuf = NULL; ++ int err; ++ ++ if ((BIT(gpio_num) & gpio_forbidden) || gpio_num > 15) ++ return -EINVAL; ++ ++ p_tbuf = kzalloc(sizeof(u32), GFP_KERNEL); ++ if (p_tbuf == NULL) ++ return -ENOMEM; ++ *p_tbuf = (gpio_mode << 16) | gpio_sel_sets[gpio_num]; ++ err = ++ esp_common_write_with_addr(epub, SLC_HOST_CONF_W1, ++ (u8 *) p_tbuf, sizeof(u32), ++ ESP_SIF_NOSYNC); ++ kfree(p_tbuf); ++ if (err) ++ return err; ++ ++ return sif_interrupt_target(epub, 4); ++} ++ ++int sif_set_gpio_output(struct esp_pub *epub, u16 mask, u16 value) ++{ ++ u32 *p_tbuf = NULL; ++ int err; ++ ++ mask &= ~gpio_forbidden; ++ p_tbuf = kzalloc(sizeof(u32), GFP_KERNEL); ++ if (p_tbuf == NULL) ++ return -ENOMEM; ++ *p_tbuf = (mask << 16) | value; ++ err = ++ esp_common_write_with_addr(epub, SLC_HOST_CONF_W2, ++ (u8 *) p_tbuf, sizeof(u32), ++ ESP_SIF_NOSYNC); ++ kfree(p_tbuf); ++ if (err) ++ return err; ++ ++ return sif_interrupt_target(epub, 5); ++} ++ ++int sif_get_gpio_intr(struct esp_pub *epub, u16 intr_mask, u16 * value) ++{ ++ u32 *p_tbuf = NULL; ++ int err; ++ ++ p_tbuf = kzalloc(sizeof(u32), GFP_KERNEL); ++ if (p_tbuf == NULL) ++ return -ENOMEM; ++ *p_tbuf = 0; ++ err = ++ esp_common_read_with_addr(epub, SLC_HOST_CONF_W3, ++ (u8 *) p_tbuf, sizeof(u32), ++ ESP_SIF_NOSYNC); ++ if (err) { ++ kfree(p_tbuf); ++ return err; ++ } ++ ++ *value = *p_tbuf & intr_mask; ++ kfree(p_tbuf); ++ if (*value == 0) ++ return 0; ++ return sif_interrupt_target(epub, 6); ++} ++ ++int sif_get_gpio_input(struct esp_pub *epub, u16 * mask, u16 * value) ++{ ++ u32 *p_tbuf = NULL; ++ int err; ++ ++ err = sif_interrupt_target(epub, 3); ++ if (err) ++ return err; ++ ++ udelay(20); ++ p_tbuf = kzalloc(sizeof(u32), GFP_KERNEL); ++ if (p_tbuf == NULL) ++ return -ENOMEM; ++ *p_tbuf = 0; ++ err = ++ esp_common_read_with_addr(epub, SLC_HOST_CONF_W3, ++ (u8 *) p_tbuf, sizeof(u32), ++ ESP_SIF_NOSYNC); ++ if (err) { ++ kfree(p_tbuf); ++ return err; ++ } ++ ++ *mask = *p_tbuf >> 16; ++ *value = *p_tbuf & *mask; ++ kfree(p_tbuf); ++ ++ return 0; ++} ++#endif ++ ++void check_target_id(struct esp_pub *epub) ++{ ++ u32 date; ++ int err = 0; ++ int i; ++ ++ EPUB_CTRL_CHECK(epub, _err); ++ ++ sif_lock_bus(epub); ++ ++ for (i = 0; i < 4; i++) { ++ err = ++ esp_common_readbyte_with_addr(epub, SLC_HOST_DATE + i, ++ (u8 *) & date + i, ++ ESP_SIF_NOSYNC); ++ err = ++ esp_common_readbyte_with_addr(epub, SLC_HOST_ID + i, ++ (u8 *) & ++ EPUB_TO_CTRL(epub)-> ++ target_id + i, ++ ESP_SIF_NOSYNC); ++ } ++ ++ sif_unlock_bus(epub); ++ ++ esp_dbg(ESP_DBG_LOG, "\n\n \t\t SLC data 0x%08x, ID 0x%08x\n\n", ++ date, EPUB_TO_CTRL(epub)->target_id); ++ ++ switch (EPUB_TO_CTRL(epub)->target_id) { ++ case 0x100: ++ EPUB_TO_CTRL(epub)->slc_window_end_addr = 0x20000; ++ break; ++ case 0x600: ++ EPUB_TO_CTRL(epub)->slc_window_end_addr = 0x20000 - 0x800; ++ ++ do { ++ u16 gpio_sel; ++ u8 low_byte = 0; ++ u8 high_byte = 0; ++ u8 byte2 = 0; ++ u8 byte3 = 0; ++#ifdef USE_OOB_INTR ++ gpio_sel = gpio_sel_sets[16]; ++ low_byte = gpio_sel; ++ high_byte = gpio_sel >> 8; ++#ifdef USE_EXT_GPIO ++ gpio_forbidden |= BIT(gpio_sel & 0xf); ++#endif /* USE_EXT_GPIO */ ++#endif /* USE_OOB_INTR */ ++ ++ if (sif_get_bt_config() == 1 ++ && sif_get_rst_config() != 1) { ++ u8 gpio_num = sif_get_wakeup_gpio_config(); ++ gpio_sel = gpio_sel_sets[gpio_num]; ++ byte2 = gpio_sel; ++ byte3 = gpio_sel >> 8; ++#ifdef USE_EXT_GPIO ++ gpio_forbidden |= BIT(gpio_num); ++#endif ++ } ++ sif_lock_bus(epub); ++ err = ++ esp_common_writebyte_with_addr(epub, ++ SLC_HOST_CONF_W1, ++ low_byte, ++ ESP_SIF_NOSYNC); ++ err = ++ esp_common_writebyte_with_addr(epub, ++ SLC_HOST_CONF_W1 ++ + 1, high_byte, ++ ESP_SIF_NOSYNC); ++ err = ++ esp_common_writebyte_with_addr(epub, ++ SLC_HOST_CONF_W1 ++ + 2, byte2, ++ ESP_SIF_NOSYNC); ++ err = ++ esp_common_writebyte_with_addr(epub, ++ SLC_HOST_CONF_W1 ++ + 3, byte3, ++ ESP_SIF_NOSYNC); ++ sif_unlock_bus(epub); ++ } while (0); ++ break; ++ default: ++ EPUB_TO_CTRL(epub)->slc_window_end_addr = 0x20000; ++ break; ++ } ++ _err: ++ return; ++} ++ ++u32 sif_get_blksz(struct esp_pub * epub) ++{ ++ EPUB_CTRL_CHECK(epub, _err); ++ ++ return EPUB_TO_CTRL(epub)->slc_blk_sz; ++ _err: ++ return 512; ++} ++ ++u32 sif_get_target_id(struct esp_pub * epub) ++{ ++ EPUB_CTRL_CHECK(epub, _err); ++ ++ return EPUB_TO_CTRL(epub)->target_id; ++ _err: ++ return 0x600; ++} ++ ++void sif_dsr(struct sdio_func *func) ++{ ++ struct esp_sdio_ctrl *sctrl = sdio_get_drvdata(func); ++ static int dsr_cnt = 0, real_intr_cnt = 0, bogus_intr_cnt = 0; ++ struct slc_host_regs *regs = &(sctrl->slc_regs); ++ esp_dbg(ESP_DBG_TRACE, " %s enter %d \n", __func__, dsr_cnt++); ++ ++ sdio_release_host(sctrl->func); ++ ++ ++ sif_lock_bus(sctrl->epub); ++ ++ ++ do { ++ int ret = 0; ++ ++ memset(regs, 0x0, sizeof(struct slc_host_regs)); ++ ++ ret = ++ esp_common_read_with_addr(sctrl->epub, ++ REG_SLC_HOST_BASE + 8, ++ (u8 *) regs, ++ sizeof(struct slc_host_regs), ++ ESP_SIF_NOSYNC); ++ ++ if ((regs->intr_raw & SLC_HOST_RX_ST) && (ret == 0)) { ++ esp_dbg(ESP_DBG_TRACE, "%s eal intr cnt: %d", ++ __func__, ++real_intr_cnt); ++ ++ esp_dsr(sctrl->epub); ++ ++ } else { ++ sif_unlock_bus(sctrl->epub); ++ ++ esp_dbg(ESP_DBG_TRACE, "%s bogus_intr_cnt %d\n", ++ __func__, ++bogus_intr_cnt); ++ } ++ ++#ifdef SIF_DEBUG_DSR_DUMP_REG ++ dump_slc_regs(regs); ++#endif /* SIF_DEBUG_DUMP_DSR */ ++ ++ } while (0); ++ ++ sdio_claim_host(func); ++ ++ atomic_set(&sctrl->irq_handling, 0); ++} ++ ++ ++struct slc_host_regs *sif_get_regs(struct esp_pub *epub) ++{ ++ EPUB_CTRL_CHECK(epub, _err); ++ ++ return &EPUB_TO_CTRL(epub)->slc_regs; ++ _err: ++ return NULL; ++} ++ ++void sif_disable_target_interrupt(struct esp_pub *epub) ++{ ++ EPUB_FUNC_CHECK(epub, _exit); ++ sif_lock_bus(epub); ++#ifdef HOST_RESET_BUG ++ mdelay(10); ++#endif ++ memset(EPUB_TO_CTRL(epub)->dma_buffer, 0x00, sizeof(u32)); ++ esp_common_write_with_addr(epub, SLC_HOST_INT_ENA, ++ EPUB_TO_CTRL(epub)->dma_buffer, ++ sizeof(u32), ESP_SIF_NOSYNC); ++#ifdef HOST_RESET_BUG ++ mdelay(10); ++#endif ++ ++ sif_unlock_bus(epub); ++ ++ mdelay(1); ++ ++ sif_lock_bus(epub); ++ sif_interrupt_target(epub, 7); ++ sif_unlock_bus(epub); ++ _exit: ++ return; ++} ++ ++#ifdef SIF_DEBUG_DSR_DUMP_REG ++static void dump_slc_regs(struct slc_host_regs *regs) ++{ ++ esp_dbg(ESP_DBG_TRACE, "\n\n ------- %s --------------\n", ++ __func__); ++ ++ esp_dbg(ESP_DBG_TRACE, " \ ++ intr_raw 0x%08X \t \n \ ++ state_w0 0x%08X \t state_w1 0x%08X \n \ ++ config_w0 0x%08X \t config_w1 0x%08X \n \ ++ intr_status 0x%08X \t config_w2 0x%08X \n \ ++ config_w3 0x%08X \t config_w4 0x%08X \n \ ++ token_wdata 0x%08X \t intr_clear 0x%08X \n \ ++ intr_enable 0x%08X \n\n", regs->intr_raw, regs->state_w0, regs->state_w1, regs->config_w0, regs->config_w1, regs->intr_status, regs->config_w2, regs->config_w3, regs->config_w4, regs->token_wdata, regs->intr_clear, regs->intr_enable); ++} ++#endif /* SIF_DEBUG_DSR_DUMP_REG */ ++ ++static int bt_config = 0; ++void sif_record_bt_config(int value) ++{ ++ bt_config = value; ++} ++ ++int sif_get_bt_config(void) ++{ ++ return bt_config; ++} ++ ++static int rst_config = 0; ++void sif_record_rst_config(int value) ++{ ++ rst_config = value; ++} ++ ++int sif_get_rst_config(void) ++{ ++ return rst_config; ++} ++ ++static int ate_test = 0; ++void sif_record_ate_config(int value) ++{ ++ ate_test = value; ++} ++ ++int sif_get_ate_config(void) ++{ ++ return ate_test; ++} ++ ++static int retry_reset = 0; ++void sif_record_retry_config(void) ++{ ++ retry_reset = 1; ++} ++ ++int sif_get_retry_config(void) ++{ ++ return retry_reset; ++} ++ ++static int wakeup_gpio = 12; ++void sif_record_wakeup_gpio_config(int value) ++{ ++ wakeup_gpio = value; ++} ++ ++int sif_get_wakeup_gpio_config(void) ++{ ++ return wakeup_gpio; ++} +diff --git a/drivers/net/wireless/esp8089/esp_mac80211.c b/drivers/net/wireless/esp8089/esp_mac80211.c +new file mode 100644 +index 000000000000..14186365fdd4 +--- /dev/null ++++ b/drivers/net/wireless/esp8089/esp_mac80211.c +@@ -0,0 +1,1731 @@ ++/* ++ * Copyright (c) 2011-2014 Espressif System. ++ * ++ * MAC80211 support module ++ * ++ * 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "esp_pub.h" ++#include "esp_sip.h" ++#include "esp_ctrl.h" ++#include "esp_sif.h" ++#include "esp_debug.h" ++#include "esp_wl.h" ++#include "esp_utils.h" ++ ++#define ESP_IEEE80211_DBG esp_dbg ++ ++#define GET_NEXT_SEQ(seq) (((seq) +1) & 0x0fff) ++ ++static u8 esp_mac_addr[ETH_ALEN * 2]; ++static u8 getaddr_index(u8 * addr, struct esp_pub *epub); ++ ++static ++void ++esp_op_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, ++ struct sk_buff *skb) ++{ ++ struct esp_pub *epub = (struct esp_pub *) hw->priv; ++ ++ ESP_IEEE80211_DBG(ESP_DBG_LOG, "%s enter\n", __func__); ++ if (!mod_support_no_txampdu() && ++ cfg80211_get_chandef_type(&epub->hw->conf.chandef) != ++ NL80211_CHAN_NO_HT) { ++ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); ++ struct ieee80211_hdr *wh = ++ (struct ieee80211_hdr *) skb->data; ++ if (ieee80211_is_data_qos(wh->frame_control)) { ++ if (!(tx_info->flags & IEEE80211_TX_CTL_AMPDU)) { ++ u8 tidno = ++ ieee80211_get_qos_ctl(wh)[0] & ++ IEEE80211_QOS_CTL_TID_MASK; ++ struct esp_node *node = ++ esp_get_node_by_addr(epub, wh->addr1); ++ { ++ struct esp_tx_tid *tid = ++ &node->tid[tidno]; ++ //record ssn ++ spin_lock_bh(&epub->tx_ampdu_lock); ++ tid->ssn = ++ GET_NEXT_SEQ(le16_to_cpu ++ (wh-> ++ seq_ctrl) >> 4); ++ ESP_IEEE80211_DBG(ESP_DBG_TRACE, ++ "tidno:%u,ssn:%u\n", ++ tidno, tid->ssn); ++ spin_unlock_bh(&epub-> ++ tx_ampdu_lock); ++ } ++ } else { ++ ESP_IEEE80211_DBG(ESP_DBG_TRACE, ++ "tx ampdu pkt, sn:%u, %u\n", ++ le16_to_cpu(wh-> ++ seq_ctrl) >> ++ 4, skb->len); ++ } ++ } ++ } ++#ifdef GEN_ERR_CHECKSUM ++ esp_gen_err_checksum(skb); ++#endif ++ ++ sip_tx_data_pkt_enqueue(epub, skb); ++ if (epub) ++ ieee80211_queue_work(hw, &epub->tx_work); ++} ++ ++static int esp_op_start(struct ieee80211_hw *hw) ++{ ++ struct esp_pub *epub; ++ ++ ESP_IEEE80211_DBG(ESP_DBG_OP, "%s\n", __func__); ++ ++ if (!hw) { ++ ESP_IEEE80211_DBG(ESP_DBG_ERROR, "%s no hw!\n", __func__); ++ return -EINVAL; ++ } ++ ++ epub = (struct esp_pub *) hw->priv; ++ ++ if (!epub) { ++ ESP_IEEE80211_DBG(ESP_DBG_ERROR, "%s no epub!\n", ++ __func__); ++ return EINVAL; ++ } ++ /*add rfkill poll function */ ++ ++ atomic_set(&epub->wl.off, 0); ++ wiphy_rfkill_start_polling(hw->wiphy); ++ return 0; ++} ++ ++static void esp_op_stop(struct ieee80211_hw *hw, bool flag) ++{ ++ struct esp_pub *epub; ++ ++ ESP_IEEE80211_DBG(ESP_DBG_OP, "%s\n", __func__); ++ ++ if (!hw) { ++ ESP_IEEE80211_DBG(ESP_DBG_ERROR, "%s no hw!\n", __func__); ++ return; ++ } ++ ++ epub = (struct esp_pub *) hw->priv; ++ ++ if (!epub) { ++ ESP_IEEE80211_DBG(ESP_DBG_ERROR, "%s no epub!\n", ++ __func__); ++ return; ++ } ++ ++ atomic_set(&epub->wl.off, 1); ++ ++#ifdef HOST_RESET_BUG ++ mdelay(200); ++#endif ++ ++ if (epub->wl.scan_req) { ++ hw_scan_done(epub, true); ++ epub->wl.scan_req = NULL; ++ //msleep(2); ++ } ++} ++ ++#ifdef CONFIG_PM ++static int esp_op_suspend(struct ieee80211_hw *hw, ++ struct cfg80211_wowlan *wowlan) ++{ ++ esp_dbg(ESP_DBG_OP, "%s\n", __func__); ++ ++ return 0; ++} ++ ++static int esp_op_resume(struct ieee80211_hw *hw) ++{ ++ esp_dbg(ESP_DBG_OP, "%s\n", __func__); ++ ++ return 0; ++} ++#endif //CONFIG_PM ++ ++static int esp_op_add_interface(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif) ++{ ++ struct esp_pub *epub = (struct esp_pub *) hw->priv; ++ struct esp_vif *evif = (struct esp_vif *) vif->drv_priv; ++ struct sip_cmd_setvif svif; ++ ++ ESP_IEEE80211_DBG(ESP_DBG_OP, "%s enter: type %d, addr %pM\n", ++ __func__, vif->type, vif->addr); ++ ++ memset(&svif, 0, sizeof(struct sip_cmd_setvif)); ++ memcpy(svif.mac, vif->addr, ETH_ALEN); ++ evif->index = svif.index = getaddr_index(vif->addr, epub); ++ evif->epub = epub; ++ epub->vif = vif; ++ svif.set = 1; ++ if ((1 << svif.index) & epub->vif_slot) { ++ ESP_IEEE80211_DBG(ESP_DBG_ERROR, ++ "%s interface %d already used\n", ++ __func__, svif.index); ++ return -EOPNOTSUPP; ++ } ++ epub->vif_slot |= 1 << svif.index; ++ ++ if (svif.index == ESP_PUB_MAX_VIF) { ++ ESP_IEEE80211_DBG(ESP_DBG_ERROR, ++ "%s only support MAX %d interface\n", ++ __func__, ESP_PUB_MAX_VIF); ++ return -EOPNOTSUPP; ++ } ++ ++ switch (vif->type) { ++ case NL80211_IFTYPE_STATION: ++ //if (svif.index == 1) ++ // vif->type = NL80211_IFTYPE_UNSPECIFIED; ++ ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s STA \n", __func__); ++ svif.op_mode = 0; ++ svif.is_p2p = 0; ++ break; ++ case NL80211_IFTYPE_AP: ++ ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s AP \n", __func__); ++ svif.op_mode = 1; ++ svif.is_p2p = 0; ++ break; ++ case NL80211_IFTYPE_P2P_CLIENT: ++ ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s P2P_CLIENT \n", __func__); ++ svif.op_mode = 0; ++ svif.is_p2p = 1; ++ break; ++ case NL80211_IFTYPE_P2P_GO: ++ ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s P2P_GO \n", __func__); ++ svif.op_mode = 1; ++ svif.is_p2p = 1; ++ break; ++ case NL80211_IFTYPE_UNSPECIFIED: ++ case NL80211_IFTYPE_ADHOC: ++ case NL80211_IFTYPE_AP_VLAN: ++ case NL80211_IFTYPE_WDS: ++ case NL80211_IFTYPE_MONITOR: ++ default: ++ ESP_IEEE80211_DBG(ESP_DBG_ERROR, ++ "%s does NOT support type %d\n", ++ __func__, vif->type); ++ return -EOPNOTSUPP; ++ } ++ ++ sip_cmd(epub, SIP_CMD_SETVIF, (u8 *) & svif, ++ sizeof(struct sip_cmd_setvif)); ++ return 0; ++} ++ ++static int esp_op_change_interface(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ enum nl80211_iftype new_type, bool p2p) ++{ ++ struct esp_pub *epub = (struct esp_pub *) hw->priv; ++ struct esp_vif *evif = (struct esp_vif *) vif->drv_priv; ++ struct sip_cmd_setvif svif; ++ ESP_IEEE80211_DBG(ESP_DBG_OP, "%s enter,change to if:%d \n", ++ __func__, new_type); ++ ++ if (new_type == NL80211_IFTYPE_AP) { ++ ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s enter,change to AP \n", ++ __func__); ++ } ++ ++ if (vif->type != new_type) { ++ ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s type from %d to %d\n", ++ __func__, vif->type, new_type); ++ } ++ ++ memset(&svif, 0, sizeof(struct sip_cmd_setvif)); ++ memcpy(svif.mac, vif->addr, ETH_ALEN); ++ svif.index = evif->index; ++ svif.set = 2; ++ ++ switch (new_type) { ++ case NL80211_IFTYPE_STATION: ++ svif.op_mode = 0; ++ svif.is_p2p = p2p; ++ break; ++ case NL80211_IFTYPE_AP: ++ svif.op_mode = 1; ++ svif.is_p2p = p2p; ++ break; ++ case NL80211_IFTYPE_P2P_CLIENT: ++ svif.op_mode = 0; ++ svif.is_p2p = 1; ++ break; ++ case NL80211_IFTYPE_P2P_GO: ++ svif.op_mode = 1; ++ svif.is_p2p = 1; ++ break; ++ case NL80211_IFTYPE_UNSPECIFIED: ++ case NL80211_IFTYPE_ADHOC: ++ case NL80211_IFTYPE_AP_VLAN: ++ case NL80211_IFTYPE_WDS: ++ case NL80211_IFTYPE_MONITOR: ++ default: ++ ESP_IEEE80211_DBG(ESP_DBG_ERROR, ++ "%s does NOT support type %d\n", ++ __func__, vif->type); ++ return -EOPNOTSUPP; ++ } ++ sip_cmd(epub, SIP_CMD_SETVIF, (u8 *) & svif, ++ sizeof(struct sip_cmd_setvif)); ++ return 0; ++} ++ ++static void esp_op_remove_interface(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif) ++{ ++ struct esp_pub *epub = (struct esp_pub *) hw->priv; ++ struct esp_vif *evif = (struct esp_vif *) vif->drv_priv; ++ struct sip_cmd_setvif svif; ++ ++ ESP_IEEE80211_DBG(ESP_DBG_OP, ++ "%s enter, vif addr %pM, beacon enable %x\n", ++ __func__, vif->addr, ++ vif->bss_conf.enable_beacon); ++ ++ memset(&svif, 0, sizeof(struct sip_cmd_setvif)); ++ svif.index = evif->index; ++ epub->vif_slot &= ~(1 << svif.index); ++ ++ if (evif->ap_up) { ++ evif->beacon_interval = 0; ++ del_timer_sync(&evif->beacon_timer); ++ evif->ap_up = false; ++ } ++ epub->vif = NULL; ++ evif->epub = NULL; ++ ++ sip_cmd(epub, SIP_CMD_SETVIF, (u8 *) & svif, ++ sizeof(struct sip_cmd_setvif)); ++ ++ /* clean up tx/rx queue */ ++ ++} ++ ++#define BEACON_TIM_SAVE_MAX 20 ++u8 beacon_tim_saved[BEACON_TIM_SAVE_MAX]; ++int beacon_tim_count; ++static void beacon_tim_init(void) ++{ ++ memset(beacon_tim_saved, 0, BEACON_TIM_SAVE_MAX); ++ beacon_tim_count = 0; ++} ++ ++static u8 beacon_tim_save(u8 this_tim) ++{ ++ u8 all_tim = 0; ++ int i; ++ beacon_tim_saved[beacon_tim_count] = this_tim; ++ if (++beacon_tim_count >= BEACON_TIM_SAVE_MAX) ++ beacon_tim_count = 0; ++ for (i = 0; i < BEACON_TIM_SAVE_MAX; i++) ++ all_tim |= beacon_tim_saved[i]; ++ return all_tim; ++} ++ ++static bool beacon_tim_alter(struct sk_buff *beacon) ++{ ++ u8 *p, *tim_end; ++ u8 tim_count; ++ int len; ++ int remain_len; ++ struct ieee80211_mgmt *mgmt; ++ ++ if (beacon == NULL) ++ return false; ++ ++ mgmt = (struct ieee80211_mgmt *) ((u8 *) beacon->data); ++ ++ remain_len = ++ beacon->len - ((u8 *) mgmt->u.beacon.variable - (u8 *) mgmt + ++ 12); ++ p = mgmt->u.beacon.variable; ++ ++ while (remain_len > 0) { ++ len = *(++p); ++ if (*p == WLAN_EID_TIM) { // tim field ++ tim_end = p + len; ++ tim_count = *(++p); ++ p += 2; ++ //multicast ++ if (tim_count == 0) ++ *p |= 0x1; ++ if ((*p & 0xfe) == 0 && tim_end >= p + 1) { // we only support 8 sta in this case ++ p++; ++ *p = beacon_tim_save(*p); ++ } ++ return tim_count == 0; ++ } ++ p += (len + 1); ++ remain_len -= (2 + len); ++ } ++ ++ return false; ++} ++ ++unsigned long init_jiffies; ++unsigned long cycle_beacon_count; ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) ++static void drv_handle_beacon(struct timer_list *t) ++#else ++static void drv_handle_beacon(unsigned long data) ++#endif ++{ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) ++ struct esp_vif *evif = from_timer(evif, t, beacon_timer); ++ struct ieee80211_vif *vif = evif->epub->vif; ++#else ++ struct ieee80211_vif *vif = (struct ieee80211_vif *) data; ++ struct esp_vif *evif = (struct esp_vif *) vif->drv_priv; ++#endif ++ struct sk_buff *beacon; ++ struct sk_buff *skb; ++ static int dbgcnt = 0; ++ bool tim_reach = false; ++ ++ if (evif->epub == NULL) ++ return; ++ ++ mdelay(2400 * (cycle_beacon_count % 25) % 10000 / 1000); ++ ++ beacon = ieee80211_beacon_get(evif->epub->hw, vif, 0); ++ ++ tim_reach = beacon_tim_alter(beacon); ++ ++ if (beacon && !(dbgcnt++ % 600)) { ++ ESP_IEEE80211_DBG(ESP_DBG_TRACE, " beacon length:%d,fc:0x%x\n", ++ beacon->len, ++ ((struct ieee80211_mgmt *) (beacon-> ++ data))-> ++ frame_control); ++ ++ } ++ ++ if (beacon) ++ sip_tx_data_pkt_enqueue(evif->epub, beacon); ++ ++ if (cycle_beacon_count++ == 100) { ++ init_jiffies = jiffies; ++ cycle_beacon_count -= 100; ++ } ++ mod_timer(&evif->beacon_timer, ++ init_jiffies + ++ msecs_to_jiffies(cycle_beacon_count * ++ vif->bss_conf.beacon_int * 1024 / ++ 1000)); ++ //FIXME:the packets must be sent at home channel ++ //send buffer mcast frames ++ if (tim_reach) { ++ skb = ieee80211_get_buffered_bc(evif->epub->hw, vif); ++ while (skb) { ++ sip_tx_data_pkt_enqueue(evif->epub, skb); ++ skb = ++ ieee80211_get_buffered_bc(evif->epub->hw, vif); ++ } ++ } ++} ++ ++static void init_beacon_timer(struct ieee80211_vif *vif) ++{ ++ struct esp_vif *evif = (struct esp_vif *) vif->drv_priv; ++ ++ ESP_IEEE80211_DBG(ESP_DBG_OP, " %s enter: beacon interval %x\n", ++ __func__, evif->beacon_interval); ++ ++ beacon_tim_init(); ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) ++ timer_setup(&evif->beacon_timer, drv_handle_beacon, 0); ++#else ++ init_timer(&evif->beacon_timer); //TBD, not init here... ++ evif->beacon_timer.data = (unsigned long) vif; ++ evif->beacon_timer.function = drv_handle_beacon; ++#endif ++ cycle_beacon_count = 1; ++ init_jiffies = jiffies; ++ evif->beacon_timer.expires = ++ init_jiffies + ++ msecs_to_jiffies(cycle_beacon_count * ++ vif->bss_conf.beacon_int * 1024 / 1000); ++ add_timer(&evif->beacon_timer); ++} ++ ++static int esp_op_config(struct ieee80211_hw *hw, u32 changed) ++{ ++ //struct ieee80211_conf *conf = &hw->conf; ++ ++ struct esp_pub *epub = (struct esp_pub *) hw->priv; ++ ++ ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s enter 0x%08x\n", __func__, ++ changed); ++ ++ if (changed & ++ (IEEE80211_CONF_CHANGE_CHANNEL | IEEE80211_CONF_CHANGE_IDLE)) { ++ sip_send_config(epub, &hw->conf); ++ } ++ ++ return 0; ++} ++ ++static void esp_op_bss_info_changed(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ struct ieee80211_bss_conf *info, ++ u64 changed) ++{ ++ struct esp_pub *epub = (struct esp_pub *) hw->priv; ++ struct esp_vif *evif = (struct esp_vif *) vif->drv_priv; ++ ++ // ieee80211_bss_conf(include/net/mac80211.h) is included in ieee80211_sub_if_data(net/mac80211/ieee80211_i.h) , does bssid=ieee80211_if_ap's ssid ? ++ // in 2.6.27, ieee80211_sub_if_data has ieee80211_bss_conf while in 2.6.32 ieee80211_sub_if_data don't have ieee80211_bss_conf ++ // in 2.6.27, ieee80211_bss_conf->enable_beacon don't exist, does it mean it support beacon always? ++ // ESP_IEEE80211_DBG(ESP_DBG_OP, " %s enter: vif addr %pM, changed %x, assoc %x, bssid %pM\n", __func__, vif->addr, changed, vif->cfg.assoc, info->bssid); ++ // sdata->u.sta.bssid ++ ++ ESP_IEEE80211_DBG(ESP_DBG_OP, ++ " %s enter: changed %llx, assoc %x, bssid %pM\n", ++ __func__, changed, vif->cfg.assoc, info->bssid); ++ ++ if (vif->type == NL80211_IFTYPE_STATION) { ++ if ((changed & BSS_CHANGED_BSSID) || ++ ((changed & BSS_CHANGED_ASSOC) && (vif->cfg.assoc))) { ++ ESP_IEEE80211_DBG(ESP_DBG_TRACE, ++ " %s STA change bssid or assoc\n", ++ __func__); ++ evif->beacon_interval = vif->cfg.aid; ++ memcpy(epub->wl.bssid, (u8 *) info->bssid, ++ ETH_ALEN); ++ sip_send_bss_info_update(epub, evif, ++ (u8 *) info->bssid, ++ vif->cfg.assoc); ++ } else if ((changed & BSS_CHANGED_ASSOC) && (!vif->cfg.assoc)) { ++ ESP_IEEE80211_DBG(ESP_DBG_TRACE, ++ " %s STA change disassoc\n", ++ __func__); ++ evif->beacon_interval = 0; ++ memset(epub->wl.bssid, 0, ETH_ALEN); ++ sip_send_bss_info_update(epub, evif, ++ (u8 *) info->bssid, ++ vif->cfg.assoc); ++ } else { ++ ESP_IEEE80211_DBG(ESP_DBG_TRACE, ++ "%s wrong mode of STA mode\n", ++ __func__); ++ } ++ } else if (vif->type == NL80211_IFTYPE_AP) { ++ if ((changed & BSS_CHANGED_BEACON_ENABLED) || ++ (changed & BSS_CHANGED_BEACON_INT)) { ++ ESP_IEEE80211_DBG(ESP_DBG_TRACE, ++ " %s AP change enable %d, interval is %d, bssid %pM\n", ++ __func__, info->enable_beacon, ++ info->beacon_int, info->bssid); ++ if (info->enable_beacon && evif->ap_up != true) { ++ evif->beacon_interval = info->beacon_int; ++ init_beacon_timer(vif); ++ sip_send_bss_info_update(epub, evif, ++ (u8 *) info-> ++ bssid, 2); ++ evif->ap_up = true; ++ } else if (!info->enable_beacon && evif->ap_up && ++ !(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) ++ ) { ++ ESP_IEEE80211_DBG(ESP_DBG_TRACE, ++ " %s AP disable beacon, interval is %d\n", ++ __func__, ++ info->beacon_int); ++ evif->beacon_interval = 0; ++ del_timer_sync(&evif->beacon_timer); ++ sip_send_bss_info_update(epub, evif, ++ (u8 *) info-> ++ bssid, 2); ++ evif->ap_up = false; ++ } ++ } ++ } else { ++ ESP_IEEE80211_DBG(ESP_DBG_ERROR, ++ "%s op mode unspecified\n", __func__); ++ } ++} ++ ++ ++static u64 esp_op_prepare_multicast(struct ieee80211_hw *hw, ++ struct netdev_hw_addr_list *mc_list) ++{ ++ ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s enter \n", __func__); ++ ++ return 0; ++} ++ ++static void esp_op_configure_filter(struct ieee80211_hw *hw, ++ unsigned int changed_flags, ++ unsigned int *total_flags, ++ u64 multicast) ++{ ++ struct esp_pub *epub = (struct esp_pub *) hw->priv; ++ ++ ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s enter \n", __func__); ++ ++ epub->rx_filter = 0; ++ ++ if (*total_flags & FIF_ALLMULTI) ++ epub->rx_filter |= FIF_ALLMULTI; ++ ++ *total_flags = epub->rx_filter; ++} ++ ++static int esp_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, ++ struct ieee80211_vif *vif, ++ struct ieee80211_sta *sta, ++ struct ieee80211_key_conf *key) ++{ ++ u8 i; ++ int ret; ++ struct esp_pub *epub = (struct esp_pub *) hw->priv; ++ struct esp_vif *evif = (struct esp_vif *) vif->drv_priv; ++ u8 ifidx = evif->index; ++ u8 *peer_addr, isvalid; ++ ++ ESP_IEEE80211_DBG(ESP_DBG_OP, ++ "%s enter, flags = %x keyindx = %x cmd = %x mac = %pM cipher = %x\n", ++ __func__, key->flags, key->keyidx, cmd, ++ vif->addr, key->cipher); ++ ++ key->flags = key->flags | IEEE80211_KEY_FLAG_GENERATE_IV; ++ ++ if (sta) { ++ if (memcmp(sta->addr, epub->wl.bssid, ETH_ALEN)) ++ peer_addr = sta->addr; ++ else ++ peer_addr = epub->wl.bssid; ++ } else { ++ peer_addr = epub->wl.bssid; ++ } ++ isvalid = (cmd == SET_KEY) ? 1 : 0; ++ ++ if ((key->flags & IEEE80211_KEY_FLAG_PAIRWISE) ++ || (key->cipher == WLAN_CIPHER_SUITE_WEP40 ++ || key->cipher == WLAN_CIPHER_SUITE_WEP104)) { ++ if (isvalid) { ++ for (i = 0; i < 19; i++) { ++ if (epub->hi_map[i].flag == 0) { ++ epub->hi_map[i].flag = 1; ++ key->hw_key_idx = i + 6; ++ memcpy(epub->hi_map[i].mac, ++ peer_addr, ETH_ALEN); ++ break; ++ } ++ } ++ } else { ++ u8 index = key->hw_key_idx - 6; ++ epub->hi_map[index].flag = 0; ++ memset(epub->hi_map[index].mac, 0, ETH_ALEN); ++ } ++ } else { ++ if (isvalid) { ++ for (i = 0; i < 2; i++) ++ if (epub->low_map[ifidx][i].flag == 0) { ++ epub->low_map[ifidx][i].flag = 1; ++ key->hw_key_idx = ++ i + ifidx * 2 + 2; ++ memcpy(epub->low_map[ifidx][i].mac, ++ peer_addr, ETH_ALEN); ++ break; ++ } ++ } else { ++ u8 index = key->hw_key_idx - 2 - ifidx * 2; ++ epub->low_map[ifidx][index].flag = 0; ++ memset(epub->low_map[ifidx][index].mac, 0, ++ ETH_ALEN); ++ } ++ //key->hw_key_idx = key->keyidx + ifidx * 2 + 1; ++ } ++ ++ if (key->hw_key_idx >= 6) { ++ /*send sub_scan task to target */ ++ //epub->wl.ptk = (cmd==SET_KEY) ? key : NULL; ++ if (isvalid) ++ atomic_inc(&epub->wl.ptk_cnt); ++ else ++ atomic_dec(&epub->wl.ptk_cnt); ++ if (key->cipher == WLAN_CIPHER_SUITE_WEP40 ++ || key->cipher == WLAN_CIPHER_SUITE_WEP104) { ++ if (isvalid) ++ atomic_inc(&epub->wl.gtk_cnt); ++ else ++ atomic_dec(&epub->wl.gtk_cnt); ++ } ++ } else { ++ /*send sub_scan task to target */ ++ if (isvalid) ++ atomic_inc(&epub->wl.gtk_cnt); ++ else ++ atomic_dec(&epub->wl.gtk_cnt); ++ ++ if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 ++ || key->cipher == WLAN_CIPHER_SUITE_WEP104)) { ++ if (isvalid) ++ atomic_inc(&epub->wl.ptk_cnt); ++ else ++ atomic_dec(&epub->wl.ptk_cnt); ++ //epub->wl.ptk = (cmd==SET_KEY) ? key : NULL; ++ } ++ } ++ ++ ret = sip_send_setkey(epub, ifidx, peer_addr, key, isvalid); ++ ++ if ((key->cipher == WLAN_CIPHER_SUITE_TKIP ++ || key->cipher == WLAN_CIPHER_SUITE_TKIP)) { ++ if (ret == 0) ++ atomic_set(&epub->wl.tkip_key_set, 1); ++ } ++ ++ ESP_IEEE80211_DBG(ESP_DBG_OP, "%s exit\n", __func__); ++ return ret; ++} ++ ++static void esp_op_update_tkip_key(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ struct ieee80211_key_conf *conf, ++ struct ieee80211_sta *sta, ++ u32 iv32, u16 * phase1key) ++{ ++ ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s enter \n", __func__); ++ ++} ++ ++void hw_scan_done(struct esp_pub *epub, bool aborted) ++{ ++ cancel_delayed_work_sync(&epub->scan_timeout_work); ++ ++ ESSERT(epub->wl.scan_req != NULL); ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) ++ { ++ struct cfg80211_scan_info info = { ++ .aborted = aborted, ++ }; ++ ++ ieee80211_scan_completed(epub->hw, &info); ++ } ++#else ++ ieee80211_scan_completed(epub->hw, aborted); ++#endif ++ if (test_and_clear_bit(ESP_WL_FLAG_STOP_TXQ, &epub->wl.flags)) { ++ sip_trigger_txq_process(epub->sip); ++ } ++} ++ ++static void hw_scan_timeout_report(struct work_struct *work) ++{ ++ struct esp_pub *epub = ++ container_of(work, struct esp_pub, scan_timeout_work.work); ++ bool aborted; ++ ++ ESP_IEEE80211_DBG(ESP_DBG_TRACE, "eagle hw scan done\n"); ++ ++ if (test_and_clear_bit(ESP_WL_FLAG_STOP_TXQ, &epub->wl.flags)) { ++ sip_trigger_txq_process(epub->sip); ++ } ++ /*check if normally complete or aborted like timeout/hw error */ ++ aborted = (epub->wl.scan_req) ? true : false; ++ ++ if (aborted == true) { ++ epub->wl.scan_req = NULL; ++ } ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) ++ { ++ struct cfg80211_scan_info info = { ++ .aborted = aborted, ++ }; ++ ++ ieee80211_scan_completed(epub->hw, &info); ++ } ++#else ++ ieee80211_scan_completed(epub->hw, aborted); ++#endif ++} ++ ++static int esp_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) ++{ ++ ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s enter \n", __func__); ++ ++ return 0; ++} ++ ++static int esp_node_attach(struct ieee80211_hw *hw, u8 ifidx, ++ struct ieee80211_sta *sta) ++{ ++ struct esp_pub *epub = (struct esp_pub *) hw->priv; ++ struct esp_node *node; ++ u8 tidno; ++ struct esp_tx_tid *tid; ++ int i; ++ ++ spin_lock_bh(&epub->tx_ampdu_lock); ++ ++ if (hweight32(epub->enodes_maps[ifidx]) < ESP_PUB_MAX_STA ++ && (i = ffz(epub->enodes_map)) < ESP_PUB_MAX_STA + 1) { ++ epub->enodes_map |= (1 << i); ++ epub->enodes_maps[ifidx] |= (1 << i); ++ node = (struct esp_node *) sta->drv_priv; ++ epub->enodes[i] = node; ++ node->sta = sta; ++ node->ifidx = ifidx; ++ node->index = i; ++ ++ for (tidno = 0, tid = &node->tid[tidno]; ++ tidno < WME_NUM_TID; tidno++) { ++ tid->ssn = 0; ++ tid->cnt = 0; ++ tid->state = ESP_TID_STATE_INIT; ++ } ++ ++ ++ } else { ++ i = -1; ++ } ++ ++ spin_unlock_bh(&epub->tx_ampdu_lock); ++ return i; ++} ++ ++static int esp_node_detach(struct ieee80211_hw *hw, u8 ifidx, ++ struct ieee80211_sta *sta) ++{ ++ struct esp_pub *epub = (struct esp_pub *) hw->priv; ++ u32 map; ++ int i; ++ struct esp_node *node = NULL; ++ ++ spin_lock_bh(&epub->tx_ampdu_lock); ++ map = epub->enodes_maps[ifidx]; ++ while (map != 0) { ++ i = ffs(map) - 1; ++ if (epub->enodes[i]->sta == sta) { ++ epub->enodes[i]->sta = NULL; ++ node = epub->enodes[i]; ++ epub->enodes[i] = NULL; ++ epub->enodes_map &= ~(1 << i); ++ epub->enodes_maps[ifidx] &= ~(1 << i); ++ ++ spin_unlock_bh(&epub->tx_ampdu_lock); ++ return i; ++ } ++ map &= ~(1 << i); ++ } ++ ++ spin_unlock_bh(&epub->tx_ampdu_lock); ++ return -1; ++} ++ ++struct esp_node *esp_get_node_by_addr(struct esp_pub *epub, ++ const u8 * addr) ++{ ++ int i; ++ u32 map; ++ struct esp_node *node = NULL; ++ if (addr == NULL) ++ return NULL; ++ spin_lock_bh(&epub->tx_ampdu_lock); ++ map = epub->enodes_map; ++ while (map != 0) { ++ i = ffs(map) - 1; ++ if (i < 0) { ++ spin_unlock_bh(&epub->tx_ampdu_lock); ++ return NULL; ++ } ++ map &= ~(1 << i); ++ if (memcmp(epub->enodes[i]->sta->addr, addr, ETH_ALEN) == ++ 0) { ++ node = epub->enodes[i]; ++ break; ++ } ++ } ++ ++ spin_unlock_bh(&epub->tx_ampdu_lock); ++ return node; ++} ++ ++struct esp_node *esp_get_node_by_index(struct esp_pub *epub, u8 index) ++{ ++ u32 map; ++ struct esp_node *node = NULL; ++ ++ if (epub == NULL) ++ return NULL; ++ ++ spin_lock_bh(&epub->tx_ampdu_lock); ++ map = epub->enodes_map; ++ if (map & BIT(index)) { ++ node = epub->enodes[index]; ++ } else { ++ spin_unlock_bh(&epub->tx_ampdu_lock); ++ return NULL; ++ } ++ ++ spin_unlock_bh(&epub->tx_ampdu_lock); ++ return node; ++} ++ ++int esp_get_empty_rxampdu(struct esp_pub *epub, const u8 * addr, u8 tid) ++{ ++ int index = -1; ++ if (addr == NULL) ++ return index; ++ spin_lock_bh(&epub->rx_ampdu_lock); ++ if ((index = ffz(epub->rxampdu_map)) < ESP_PUB_MAX_RXAMPDU) { ++ epub->rxampdu_map |= BIT(index); ++ epub->rxampdu_node[index] = ++ esp_get_node_by_addr(epub, addr); ++ epub->rxampdu_tid[index] = tid; ++ } else { ++ index = -1; ++ } ++ spin_unlock_bh(&epub->rx_ampdu_lock); ++ return index; ++} ++ ++int esp_get_exist_rxampdu(struct esp_pub *epub, const u8 * addr, u8 tid) ++{ ++ u8 map; ++ int index = -1; ++ int i; ++ if (addr == NULL) ++ return index; ++ spin_lock_bh(&epub->rx_ampdu_lock); ++ map = epub->rxampdu_map; ++ while (map != 0) { ++ i = ffs(map) - 1; ++ if (i < 0) { ++ spin_unlock_bh(&epub->rx_ampdu_lock); ++ return index; ++ } ++ map &= ~BIT(i); ++ if (epub->rxampdu_tid[i] == tid && ++ memcmp(epub->rxampdu_node[i]->sta->addr, addr, ++ ETH_ALEN) == 0) { ++ index = i; ++ break; ++ } ++ } ++ ++ epub->rxampdu_map &= ~BIT(index); ++ spin_unlock_bh(&epub->rx_ampdu_lock); ++ return index; ++ ++} ++ ++static int esp_op_sta_add(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ struct ieee80211_sta *sta) ++{ ++ struct esp_pub *epub = (struct esp_pub *) hw->priv; ++ struct esp_vif *evif = (struct esp_vif *) vif->drv_priv; ++ int index; ++ ESP_IEEE80211_DBG(ESP_DBG_OP, ++ "%s enter, vif addr %pM, sta addr %pM\n", ++ __func__, vif->addr, sta->addr); ++ index = esp_node_attach(hw, evif->index, sta); ++ ++ if (index < 0) ++ return -1; ++ sip_send_set_sta(epub, evif->index, 1, sta, vif, (u8) index); ++ return 0; ++} ++ ++static int esp_op_sta_remove(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ struct ieee80211_sta *sta) ++{ ++ struct esp_pub *epub = (struct esp_pub *) hw->priv; ++ struct esp_vif *evif = (struct esp_vif *) vif->drv_priv; ++ int index; ++ ++ ESP_IEEE80211_DBG(ESP_DBG_OP, ++ "%s enter, vif addr %pM, sta addr %pM\n", ++ __func__, vif->addr, sta->addr); ++ ++ //remove a connect in target ++ index = esp_node_detach(hw, evif->index, sta); ++ sip_send_set_sta(epub, evif->index, 0, sta, vif, (u8) index); ++ ++ return 0; ++} ++ ++ ++static void esp_op_sta_notify(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ enum sta_notify_cmd cmd, ++ struct ieee80211_sta *sta) ++{ ++ ++ ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s enter \n", __func__); ++ ++ switch (cmd) { ++ case STA_NOTIFY_SLEEP: ++ break; ++ ++ case STA_NOTIFY_AWAKE: ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++ ++static int esp_op_conf_tx(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ u32 link_id, u16 queue, ++ const struct ieee80211_tx_queue_params *params) ++{ ++ struct esp_pub *epub = (struct esp_pub *) hw->priv; ++ ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s enter \n", __func__); ++ return sip_send_wmm_params(epub, queue, params); ++} ++ ++static u64 esp_op_get_tsf(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif) ++{ ++ ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s enter \n", __func__); ++ ++ return 0; ++} ++ ++static void esp_op_set_tsf(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, u64 tsf) ++{ ++ ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s enter \n", __func__); ++} ++ ++static void esp_op_reset_tsf(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif) ++{ ++ ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s enter \n", __func__); ++ ++} ++ ++static void esp_op_rfkill_poll(struct ieee80211_hw *hw) ++{ ++ struct esp_pub *epub = (struct esp_pub *) hw->priv; ++ ++ ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s enter \n", __func__); ++ ++ wiphy_rfkill_set_hw_state(hw->wiphy, ++ test_bit(ESP_WL_FLAG_RFKILL, ++ &epub->wl. ++ flags) ? true : false); ++} ++ ++#ifdef HW_SCAN ++static int esp_op_hw_scan(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ struct cfg80211_scan_request *req) ++{ ++ struct esp_pub *epub = (struct esp_pub *) hw->priv; ++ int i, ret; ++ bool scan_often = true; ++ ++ ESP_IEEE80211_DBG(ESP_DBG_OP, "%s\n", __func__); ++ ++ ESP_IEEE80211_DBG(ESP_DBG_TRACE, "scan, %d\n", req->n_ssids); ++ ESP_IEEE80211_DBG(ESP_DBG_TRACE, "scan, len 1:%d,ssid 1:%s\n", ++ req->ssids->ssid_len, ++ req->ssids->ssid_len == ++ 0 ? "" : (char *) req->ssids->ssid); ++ if (req->n_ssids > 1) ++ ESP_IEEE80211_DBG(ESP_DBG_TRACE, ++ "scan, len 2:%d,ssid 2:%s\n", ++ (req->ssids + 1)->ssid_len, ++ (req->ssids + 1)->ssid_len == ++ 0 ? "" : (char *) (req->ssids + ++ 1)->ssid); ++ ++ /*scan_request is keep allocate untill scan_done,record it ++ to split request into multi sdio_cmd */ ++ if (atomic_read(&epub->wl.off)) { ++ esp_dbg(ESP_DBG_ERROR, "%s scan but wl off \n", __func__); ++ return -EPERM; ++ } ++ ++ if (req->n_ssids > 1) { ++ struct cfg80211_ssid *ssid2 = req->ssids + 1; ++ if ((req->ssids->ssid_len > 0 && ssid2->ssid_len > 0) ++ || req->n_ssids > 2) { ++ ESP_IEEE80211_DBG(ESP_DBG_ERROR, ++ "scan ssid num: %d, ssid1:%s, ssid2:%s,not support\n", ++ req->n_ssids, ++ req->ssids->ssid_len == ++ 0 ? "" : (char *) req->ssids-> ++ ssid, ++ ssid2->ssid_len == ++ 0 ? "" : (char *) ssid2->ssid); ++ return -EINVAL; ++ } ++ } ++ ++ epub->wl.scan_req = req; ++ ++ for (i = 0; i < req->n_channels; i++) ++ ESP_IEEE80211_DBG(ESP_DBG_TRACE, "eagle hw_scan freq %d\n", ++ req->channels[i]->center_freq); ++#if 0 ++ for (i = 0; i < req->n_ssids; i++) { ++ if (req->ssids->ssid_len > 0) { ++ req->ssids->ssid[req->ssids->ssid_len] = '\0'; ++ ESP_IEEE80211_DBG(ESP_DBG_TRACE, ++ "scan_ssid %d:%s\n", i, ++ req->ssids->ssid); ++ } ++ } ++#endif ++ ++ /*in connect state, suspend tx data */ ++ if (epub->sip->support_bgscan && ++ test_bit(ESP_WL_FLAG_CONNECT, &epub->wl.flags) && ++ req->n_channels > 0) { ++ ++ scan_often = epub->scan_permit_valid ++ && time_before(jiffies, epub->scan_permit); ++ epub->scan_permit_valid = true; ++ ++ if (!scan_often) { ++/* epub->scan_permit = jiffies + msecs_to_jiffies(900); ++ set_bit(ESP_WL_FLAG_STOP_TXQ, &epub->wl.flags); ++ if (atomic_read(&epub->txq_stopped) == false) { ++ atomic_set(&epub->txq_stopped, true); ++ ieee80211_stop_queues(hw); ++ } ++*/ ++ } else { ++ ESP_IEEE80211_DBG(ESP_DBG_LOG, "scan too often\n"); ++ return -EACCES; ++ } ++ } else { ++ scan_often = false; ++ } ++ ++ /*send sub_scan task to target */ ++ ret = sip_send_scan(epub); ++ ++ if (ret) { ++ ESP_IEEE80211_DBG(ESP_DBG_ERROR, ++ "fail to send scan_cmd\n"); ++ return ret; ++ } else { ++ if (!scan_often) { ++ epub->scan_permit = ++ jiffies + msecs_to_jiffies(900); ++ set_bit(ESP_WL_FLAG_STOP_TXQ, &epub->wl.flags); ++ if (atomic_read(&epub->txq_stopped) == false) { ++ atomic_set(&epub->txq_stopped, true); ++ ieee80211_stop_queues(hw); ++ } ++ /*force scan complete in case target fail to report in time */ ++ ieee80211_queue_delayed_work(hw, ++ &epub-> ++ scan_timeout_work, ++ req->n_channels * HZ / ++ 4); ++ } ++ } ++ ++ return 0; ++} ++ ++static int esp_op_remain_on_channel(struct ieee80211_hw *hw, ++ struct ieee80211_channel *chan, ++ enum nl80211_channel_type channel_type, ++ int duration) ++{ ++ struct esp_pub *epub = (struct esp_pub *) hw->priv; ++ ++ ESP_IEEE80211_DBG(ESP_DBG_OP, ++ "%s enter, center_freq = %d duration = %d\n", ++ __func__, chan->center_freq, duration); ++ sip_send_roc(epub, chan->center_freq, duration); ++ return 0; ++} ++ ++static int esp_op_cancel_remain_on_channel(struct ieee80211_hw *hw) ++{ ++ struct esp_pub *epub = (struct esp_pub *) hw->priv; ++ ++ ESP_IEEE80211_DBG(ESP_DBG_OP, "%s enter \n", __func__); ++ epub->roc_flags = 0; // to disable roc state ++ sip_send_roc(epub, 0, 0); ++ return 0; ++} ++#endif ++ ++void esp_rocdone_process(struct ieee80211_hw *hw, ++ struct sip_evt_roc *report) ++{ ++ struct esp_pub *epub = (struct esp_pub *) hw->priv; ++ ++ ESP_IEEE80211_DBG(ESP_DBG_OP, "%s enter, state = %d is_ok = %d\n", ++ __func__, report->state, report->is_ok); ++ ++ //roc process begin ++ if ((report->state == 1) && (report->is_ok == 1)) { ++ epub->roc_flags = 1; //flags in roc state, to fix channel, not change ++ ieee80211_ready_on_channel(hw); ++ } else if ((report->state == 0) && (report->is_ok == 1)) //roc process timeout ++ { ++ epub->roc_flags = 0; // to disable roc state ++ ieee80211_remain_on_channel_expired(hw); ++ } ++} ++ ++static int esp_op_set_bitrate_mask(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ const struct cfg80211_bitrate_mask ++ *mask) ++{ ++ ESP_IEEE80211_DBG(ESP_DBG_OP, "%s enter \n", __func__); ++ ESP_IEEE80211_DBG(ESP_DBG_OP, "%s vif->macaddr[%pM], mask[%d]\n", ++ __func__, vif->addr, mask->control[0].legacy); ++ ++ return 0; ++} ++ ++static void esp_op_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, ++ u32 queues, bool drop) ++{ ++ ++ ESP_IEEE80211_DBG(ESP_DBG_OP, "%s enter \n", __func__); ++ do { ++ ++ struct esp_pub *epub = (struct esp_pub *) hw->priv; ++ unsigned long time = jiffies + msecs_to_jiffies(15); ++ while (atomic_read(&epub->sip->tx_data_pkt_queued)) { ++ if (!time_before(jiffies, time)) { ++ break; ++ } ++ if (sif_get_ate_config() == 0) { ++ ieee80211_queue_work(epub->hw, ++ &epub->tx_work); ++ } else { ++ queue_work(epub->esp_wkq, &epub->tx_work); ++ } ++ //sip_txq_process(epub); ++ } ++ mdelay(10); ++ ++ } while (0); ++} ++ ++static int esp_op_ampdu_action(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ struct ieee80211_ampdu_params *params) ++{ ++ int ret = -EOPNOTSUPP; ++ enum ieee80211_ampdu_mlme_action action = params->action; ++ struct ieee80211_sta *sta = params->sta; ++ u16 tid = params->tid; ++ u16 *ssn = ¶ms->ssn; ++ u8 buf_size = params->buf_size; ++ struct esp_pub *epub = (struct esp_pub *) hw->priv; ++ struct esp_node *node = (struct esp_node *) sta->drv_priv; ++ struct esp_tx_tid *tid_info = &node->tid[tid]; ++ ++ ESP_IEEE80211_DBG(ESP_DBG_OP, "%s enter \n", __func__); ++ switch (action) { ++ case IEEE80211_AMPDU_TX_START: ++ if (mod_support_no_txampdu() || ++ cfg80211_get_chandef_type(&epub->hw->conf.chandef) == ++ NL80211_CHAN_NO_HT || !sta->deflink.ht_cap.ht_supported) ++ return ret; ++ ++ //if (vif->p2p || vif->type != NL80211_IFTYPE_STATION) ++ // return ret; ++ ++ ESP_IEEE80211_DBG(ESP_DBG_TRACE, ++ "%s TX START, addr:%pM,tid:%u,state:%d\n", ++ __func__, sta->addr, tid, ++ tid_info->state); ++ spin_lock_bh(&epub->tx_ampdu_lock); ++ ESSERT(tid_info->state == ESP_TID_STATE_TRIGGER); ++ *ssn = tid_info->ssn; ++ tid_info->state = ESP_TID_STATE_PROGRESS; ++ ++ ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); ++ spin_unlock_bh(&epub->tx_ampdu_lock); ++ ret = 0; ++ break; ++ case IEEE80211_AMPDU_TX_STOP_CONT: ++ ESP_IEEE80211_DBG(ESP_DBG_TRACE, ++ "%s TX STOP, addr:%pM,tid:%u,state:%d\n", ++ __func__, sta->addr, tid, ++ tid_info->state); ++ spin_lock_bh(&epub->tx_ampdu_lock); ++ if (tid_info->state == ESP_TID_STATE_WAIT_STOP) ++ tid_info->state = ESP_TID_STATE_STOP; ++ else ++ tid_info->state = ESP_TID_STATE_INIT; ++ ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); ++ spin_unlock_bh(&epub->tx_ampdu_lock); ++ ret = ++ sip_send_ampdu_action(epub, SIP_AMPDU_TX_STOP, ++ sta->addr, tid, node->ifidx, 0); ++ break; ++ case IEEE80211_AMPDU_TX_STOP_FLUSH: ++ case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: ++ if (tid_info->state == ESP_TID_STATE_WAIT_STOP) ++ tid_info->state = ESP_TID_STATE_STOP; ++ else ++ tid_info->state = ESP_TID_STATE_INIT; ++ ret = ++ sip_send_ampdu_action(epub, SIP_AMPDU_TX_STOP, ++ sta->addr, tid, node->ifidx, 0); ++ break; ++ case IEEE80211_AMPDU_TX_OPERATIONAL: ++ ESP_IEEE80211_DBG(ESP_DBG_TRACE, ++ "%s TX OPERATION, addr:%pM,tid:%u,state:%d\n", ++ __func__, sta->addr, tid, ++ tid_info->state); ++ spin_lock_bh(&epub->tx_ampdu_lock); ++ ++ if (tid_info->state != ESP_TID_STATE_PROGRESS) { ++ if (tid_info->state == ESP_TID_STATE_INIT) { ++ printk(KERN_ERR "%s WIFI RESET, IGNORE\n", ++ __func__); ++ spin_unlock_bh(&epub->tx_ampdu_lock); ++ return -ENETRESET; ++ } else { ++ ESSERT(0); ++ } ++ } ++ ++ tid_info->state = ESP_TID_STATE_OPERATIONAL; ++ spin_unlock_bh(&epub->tx_ampdu_lock); ++ ret = ++ sip_send_ampdu_action(epub, SIP_AMPDU_TX_OPERATIONAL, ++ sta->addr, tid, node->ifidx, ++ buf_size); ++ break; ++ case IEEE80211_AMPDU_RX_START: ++ if (mod_support_no_rxampdu() || ++ cfg80211_get_chandef_type(&epub->hw->conf.chandef) == ++ NL80211_CHAN_NO_HT || !sta->deflink.ht_cap.ht_supported) ++ return ret; ++ ++ if ((vif->p2p && false) ++ || (vif->type != NL80211_IFTYPE_STATION && false) ++ ) ++ return ret; ++ ESP_IEEE80211_DBG(ESP_DBG_TRACE, ++ "%s RX START %pM tid %u %u\n", __func__, ++ sta->addr, tid, *ssn); ++ ret = ++ sip_send_ampdu_action(epub, SIP_AMPDU_RX_START, ++ sta->addr, tid, *ssn, 64); ++ break; ++ case IEEE80211_AMPDU_RX_STOP: ++ ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s RX STOP %pM tid %u\n", ++ __func__, sta->addr, tid); ++ ret = ++ sip_send_ampdu_action(epub, SIP_AMPDU_RX_STOP, ++ sta->addr, tid, 0, 0); ++ break; ++ default: ++ break; ++ } ++ return ret; ++} ++ ++static void esp_tx_work(struct work_struct *work) ++{ ++ struct esp_pub *epub = container_of(work, struct esp_pub, tx_work); ++ ++ mutex_lock(&epub->tx_mtx); ++ sip_txq_process(epub); ++ mutex_unlock(&epub->tx_mtx); ++} ++ ++static const struct ieee80211_ops esp_mac80211_ops = { ++ .tx = esp_op_tx, ++ .start = esp_op_start, ++ .stop = esp_op_stop, ++#ifdef CONFIG_PM ++ .suspend = esp_op_suspend, ++ .resume = esp_op_resume, ++#endif ++ .add_interface = esp_op_add_interface, ++ .remove_interface = esp_op_remove_interface, ++ .config = esp_op_config, ++ ++ .bss_info_changed = esp_op_bss_info_changed, ++ .prepare_multicast = esp_op_prepare_multicast, ++ .configure_filter = esp_op_configure_filter, ++ .set_key = esp_op_set_key, ++ .update_tkip_key = esp_op_update_tkip_key, ++ //.sched_scan_start = esp_op_sched_scan_start, ++ //.sched_scan_stop = esp_op_sched_scan_stop, ++ .set_rts_threshold = esp_op_set_rts_threshold, ++ .sta_notify = esp_op_sta_notify, ++ .conf_tx = esp_op_conf_tx, ++ .change_interface = esp_op_change_interface, ++ .get_tsf = esp_op_get_tsf, ++ .set_tsf = esp_op_set_tsf, ++ .reset_tsf = esp_op_reset_tsf, ++ .rfkill_poll = esp_op_rfkill_poll, ++ .add_chanctx = ieee80211_emulate_add_chanctx, ++ .remove_chanctx = ieee80211_emulate_remove_chanctx, ++ .change_chanctx = ieee80211_emulate_change_chanctx, ++#ifdef HW_SCAN ++ .hw_scan = esp_op_hw_scan, ++ .remain_on_channel = esp_op_remain_on_channel, ++ .cancel_remain_on_channel = esp_op_cancel_remain_on_channel, ++#endif ++ .ampdu_action = esp_op_ampdu_action, ++ //.get_survey = esp_op_get_survey, ++ .sta_add = esp_op_sta_add, ++ .sta_remove = esp_op_sta_remove, ++#ifdef CONFIG_NL80211_TESTMODE ++ //CFG80211_TESTMODE_CMD(esp_op_tm_cmd) ++#endif ++ .set_bitrate_mask = esp_op_set_bitrate_mask, ++ .flush = esp_op_flush, ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, ++}; ++ ++struct esp_pub *esp_pub_alloc_mac80211(struct device *dev) ++{ ++ struct ieee80211_hw *hw; ++ struct esp_pub *epub; ++ int ret = 0; ++ ++ hw = ieee80211_alloc_hw(sizeof(struct esp_pub), &esp_mac80211_ops); ++ ++ if (hw == NULL) { ++ esp_dbg(ESP_DBG_ERROR, "ieee80211 can't alloc hw!\n"); ++ ret = -ENOMEM; ++ return ERR_PTR(ret); ++ } ++ hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; ++ ++ epub = hw->priv; ++ memset(epub, 0, sizeof(*epub)); ++ epub->hw = hw; ++ SET_IEEE80211_DEV(hw, dev); ++ epub->dev = dev; ++ ++ skb_queue_head_init(&epub->txq); ++ skb_queue_head_init(&epub->txdoneq); ++ skb_queue_head_init(&epub->rxq); ++ ++ spin_lock_init(&epub->tx_ampdu_lock); ++ spin_lock_init(&epub->rx_ampdu_lock); ++ spin_lock_init(&epub->tx_lock); ++ mutex_init(&epub->tx_mtx); ++ spin_lock_init(&epub->rx_lock); ++ ++ INIT_WORK(&epub->tx_work, esp_tx_work); ++ ++ //epub->esp_wkq = create_freezable_workqueue("esp_wkq"); ++ epub->esp_wkq = create_singlethread_workqueue("esp_wkq"); ++ ++ if (epub->esp_wkq == NULL) { ++ ret = -ENOMEM; ++ return ERR_PTR(ret); ++ } ++ epub->scan_permit_valid = false; ++ INIT_DELAYED_WORK(&epub->scan_timeout_work, ++ hw_scan_timeout_report); ++ ++ return epub; ++} ++ ++ ++int esp_pub_dealloc_mac80211(struct esp_pub *epub) ++{ ++ set_bit(ESP_WL_FLAG_RFKILL, &epub->wl.flags); ++ ++ destroy_workqueue(epub->esp_wkq); ++ mutex_destroy(&epub->tx_mtx); ++ ++#ifdef ESP_NO_MAC80211 ++ free_netdev(epub->net_dev); ++ wiphy_free(epub->wdev->wiphy); ++ kfree(epub->wdev); ++#else ++ if (epub->hw) { ++ ieee80211_free_hw(epub->hw); ++ } ++#endif ++ ++ return 0; ++} ++ ++#if 0 ++static int esp_reg_notifier(struct wiphy *wiphy, ++ struct regulatory_request *request) ++{ ++ struct ieee80211_supported_band *sband; ++ struct ieee80211_channel *ch; ++ int i; ++ ++ ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s enter %d\n", __func__, ++ request->initiator); ++ ++ //TBD ++} ++#endif ++ ++/* 2G band channels */ ++static struct ieee80211_channel esp_channels_2ghz[] = { ++ {.hw_value = 1,.center_freq = 2412,.max_power = 25}, ++ {.hw_value = 2,.center_freq = 2417,.max_power = 25}, ++ {.hw_value = 3,.center_freq = 2422,.max_power = 25}, ++ {.hw_value = 4,.center_freq = 2427,.max_power = 25}, ++ {.hw_value = 5,.center_freq = 2432,.max_power = 25}, ++ {.hw_value = 6,.center_freq = 2437,.max_power = 25}, ++ {.hw_value = 7,.center_freq = 2442,.max_power = 25}, ++ {.hw_value = 8,.center_freq = 2447,.max_power = 25}, ++ {.hw_value = 9,.center_freq = 2452,.max_power = 25}, ++ {.hw_value = 10,.center_freq = 2457,.max_power = 25}, ++ {.hw_value = 11,.center_freq = 2462,.max_power = 25}, ++ {.hw_value = 12,.center_freq = 2467,.max_power = 25}, ++ {.hw_value = 13,.center_freq = 2472,.max_power = 25}, ++ //{ .hw_value = 14, .center_freq = 2484, .max_power = 25 }, ++}; ++ ++/* 11G rate */ ++static struct ieee80211_rate esp_rates_2ghz[] = { ++ { ++ .bitrate = 10, ++ .hw_value = CONF_HW_BIT_RATE_1MBPS, ++ .hw_value_short = CONF_HW_BIT_RATE_1MBPS, ++ }, ++ { ++ .bitrate = 20, ++ .hw_value = CONF_HW_BIT_RATE_2MBPS, ++ .hw_value_short = CONF_HW_BIT_RATE_2MBPS, ++ .flags = IEEE80211_RATE_SHORT_PREAMBLE}, ++ { ++ .bitrate = 55, ++ .hw_value = CONF_HW_BIT_RATE_5_5MBPS, ++ .hw_value_short = CONF_HW_BIT_RATE_5_5MBPS, ++ .flags = IEEE80211_RATE_SHORT_PREAMBLE}, ++ { ++ .bitrate = 110, ++ .hw_value = CONF_HW_BIT_RATE_11MBPS, ++ .hw_value_short = CONF_HW_BIT_RATE_11MBPS, ++ .flags = IEEE80211_RATE_SHORT_PREAMBLE}, ++ { ++ .bitrate = 60, ++ .hw_value = CONF_HW_BIT_RATE_6MBPS, ++ .hw_value_short = CONF_HW_BIT_RATE_6MBPS, ++ }, ++ { ++ .bitrate = 90, ++ .hw_value = CONF_HW_BIT_RATE_9MBPS, ++ .hw_value_short = CONF_HW_BIT_RATE_9MBPS, ++ }, ++ { ++ .bitrate = 120, ++ .hw_value = CONF_HW_BIT_RATE_12MBPS, ++ .hw_value_short = CONF_HW_BIT_RATE_12MBPS, ++ }, ++ { ++ .bitrate = 180, ++ .hw_value = CONF_HW_BIT_RATE_18MBPS, ++ .hw_value_short = CONF_HW_BIT_RATE_18MBPS, ++ }, ++ { ++ .bitrate = 240, ++ .hw_value = CONF_HW_BIT_RATE_24MBPS, ++ .hw_value_short = CONF_HW_BIT_RATE_24MBPS, ++ }, ++ { ++ .bitrate = 360, ++ .hw_value = CONF_HW_BIT_RATE_36MBPS, ++ .hw_value_short = CONF_HW_BIT_RATE_36MBPS, ++ }, ++ { ++ .bitrate = 480, ++ .hw_value = CONF_HW_BIT_RATE_48MBPS, ++ .hw_value_short = CONF_HW_BIT_RATE_48MBPS, ++ }, ++ { ++ .bitrate = 540, ++ .hw_value = CONF_HW_BIT_RATE_54MBPS, ++ .hw_value_short = CONF_HW_BIT_RATE_54MBPS, ++ }, ++}; ++ ++static void esp_pub_init_mac80211(struct esp_pub *epub) ++{ ++ struct ieee80211_hw *hw = epub->hw; ++ ++ static const u32 cipher_suites[] = { ++ WLAN_CIPHER_SUITE_WEP40, ++ WLAN_CIPHER_SUITE_WEP104, ++ WLAN_CIPHER_SUITE_TKIP, ++ WLAN_CIPHER_SUITE_CCMP, ++ }; ++ ++ hw->max_listen_interval = 10; ++ ++ ieee80211_hw_set(hw, SIGNAL_DBM); ++ ieee80211_hw_set(hw, HAS_RATE_CONTROL); ++ ieee80211_hw_set(hw, SUPPORTS_PS); ++ ieee80211_hw_set(hw, AMPDU_AGGREGATION); ++ ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING); ++ //IEEE80211_HW_PS_NULLFUNC_STACK | ++ //IEEE80211_HW_CONNECTION_MONITOR | ++ //IEEE80211_HW_BEACON_FILTER | ++ //IEEE80211_HW_AMPDU_AGGREGATION | ++ //IEEE80211_HW_REPORTS_TX_ACK_STATUS; ++ hw->max_rx_aggregation_subframes = 0x40; ++ hw->max_tx_aggregation_subframes = 0x40; ++ ++ hw->wiphy->cipher_suites = cipher_suites; ++ hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); ++ hw->wiphy->max_scan_ie_len = ++ epub->sip->tx_blksz - sizeof(struct sip_hdr) - ++ sizeof(struct sip_cmd_scan); ++ ++ /* ONLY station for now, support P2P soon... */ ++ hw->wiphy->interface_modes = ++ BIT(NL80211_IFTYPE_P2P_GO) | ++ BIT(NL80211_IFTYPE_P2P_CLIENT) | ++ BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP); ++ ++ hw->wiphy->max_scan_ssids = 2; ++ //hw->wiphy->max_sched_scan_ssids = 16; ++ //hw->wiphy->max_match_sets = 16; ++ ++ hw->wiphy->max_remain_on_channel_duration = 5000; ++ ++ atomic_set(&epub->wl.off, 1); ++ ++ epub->wl.sbands[NL80211_BAND_2GHZ].band = NL80211_BAND_2GHZ; ++ epub->wl.sbands[NL80211_BAND_2GHZ].channels = esp_channels_2ghz; ++ epub->wl.sbands[NL80211_BAND_2GHZ].bitrates = esp_rates_2ghz; ++ epub->wl.sbands[NL80211_BAND_2GHZ].n_channels = ++ ARRAY_SIZE(esp_channels_2ghz); ++ epub->wl.sbands[NL80211_BAND_2GHZ].n_bitrates = ++ ARRAY_SIZE(esp_rates_2ghz); ++ /*add to support 11n */ ++ epub->wl.sbands[NL80211_BAND_2GHZ].ht_cap.ht_supported = true; ++ epub->wl.sbands[NL80211_BAND_2GHZ].ht_cap.cap = 0x116C; //IEEE80211_HT_CAP_RX_STBC; //IEEE80211_HT_CAP_SGI_20; ++ epub->wl.sbands[NL80211_BAND_2GHZ].ht_cap.ampdu_factor = ++ IEEE80211_HT_MAX_AMPDU_16K; ++ epub->wl.sbands[NL80211_BAND_2GHZ].ht_cap.ampdu_density = ++ IEEE80211_HT_MPDU_DENSITY_NONE; ++ memset(&epub->wl.sbands[NL80211_BAND_2GHZ].ht_cap.mcs, 0, ++ sizeof(epub->wl.sbands[NL80211_BAND_2GHZ].ht_cap.mcs)); ++ epub->wl.sbands[NL80211_BAND_2GHZ].ht_cap.mcs.rx_mask[0] = 0xff; ++ //epub->wl.sbands[NL80211_BAND_2GHZ].ht_cap.mcs.rx_highest = 7; ++ //epub->wl.sbands[NL80211_BAND_2GHZ].ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; ++ ++ /* BAND_5GHZ TBD */ ++ ++ hw->wiphy->bands[NL80211_BAND_2GHZ] = ++ &epub->wl.sbands[NL80211_BAND_2GHZ]; ++ /* BAND_5GHZ TBD */ ++ ++ /*no fragment */ ++ hw->wiphy->frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD; ++ ++ /* handle AC queue in f/w */ ++ hw->queues = 4; ++ hw->max_rates = 4; ++ //hw->wiphy->reg_notifier = esp_reg_notify; ++ ++ hw->vif_data_size = sizeof(struct esp_vif); ++ hw->sta_data_size = sizeof(struct esp_node); ++ ++ //hw->max_rx_aggregation_subframes = 8; ++} ++ ++int esp_register_mac80211(struct esp_pub *epub) ++{ ++ int ret = 0; ++ u8 *wlan_addr; ++ u8 *p2p_addr; ++ int idx; ++ ++ esp_pub_init_mac80211(epub); ++ ++ epub->hw->wiphy->addresses = (struct mac_address *) esp_mac_addr; ++ memcpy(&epub->hw->wiphy->addresses[0], epub->mac_addr, ETH_ALEN); ++ memcpy(&epub->hw->wiphy->addresses[1], epub->mac_addr, ETH_ALEN); ++ wlan_addr = (u8 *) & epub->hw->wiphy->addresses[0]; ++ p2p_addr = (u8 *) & epub->hw->wiphy->addresses[1]; ++ ++ for (idx = 0; idx < 64; idx++) { ++ p2p_addr[0] = wlan_addr[0] | 0x02; ++ p2p_addr[0] ^= idx << 2; ++ if (strncmp(p2p_addr, wlan_addr, 6) != 0) ++ break; ++ } ++ ++ epub->hw->wiphy->n_addresses = 2; ++ ++ ret = ieee80211_register_hw(epub->hw); ++ ++ if (ret < 0) { ++ ESP_IEEE80211_DBG(ESP_DBG_ERROR, ++ "unable to register mac80211 hw: %d\n", ++ ret); ++ return ret; ++ } else { ++#ifdef MAC80211_NO_CHANGE ++ rtnl_lock(); ++ if (epub->hw->wiphy->interface_modes & ++ (BIT(NL80211_IFTYPE_P2P_GO) | ++ BIT(NL80211_IFTYPE_P2P_CLIENT))) { ++ ret = ++ ieee80211_if_add(hw_to_local(epub->hw), ++ "p2p%d", NULL, ++ NL80211_IFTYPE_STATION, NULL); ++ if (ret) ++ wiphy_warn(epub->hw->wiphy, ++ "Failed to add default virtual iface\n"); ++ } ++ ++ rtnl_unlock(); ++#endif ++ } ++ ++ set_bit(ESP_WL_FLAG_HW_REGISTERED, &epub->wl.flags); ++ ++ return ret; ++} ++ ++static u8 getaddr_index(u8 * addr, struct esp_pub *epub) ++{ ++ int i; ++ for (i = 0; i < ESP_PUB_MAX_VIF; i++) ++ if (memcmp ++ (addr, (u8 *) & epub->hw->wiphy->addresses[i], ++ ETH_ALEN) == 0) ++ return i; ++ return ESP_PUB_MAX_VIF; ++} +diff --git a/drivers/net/wireless/esp8089/esp_mac80211.h b/drivers/net/wireless/esp8089/esp_mac80211.h +new file mode 100644 +index 000000000000..699b27dcadd1 +--- /dev/null ++++ b/drivers/net/wireless/esp8089/esp_mac80211.h +@@ -0,0 +1,38 @@ ++/* ++ * Copyright (c) 2011-2014 Espressif System. ++ * ++ * MAC80211 support module ++ * ++ * 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 _ESP_MAC80211_H_ ++#define _ESP_MAC80211_H_ ++ ++struct esp_80211_wmm_ac_param { ++ u8 aci_aifsn; /* AIFSN, ACM, ACI */ ++ u8 cw; /* ECWmin, ECWmax (CW = 2^ECW - 1) */ ++ u16 txop_limit; ++}; ++ ++struct esp_80211_wmm_param_element { ++ /* Element ID: 221 (0xdd); length: 24 */ ++ /* required fields for WMM version 1 */ ++ u8 oui[3]; /* 00:50:f2 */ ++ u8 oui_type; /* 2 */ ++ u8 oui_subtype; /* 1 */ ++ u8 version; /* 1 for WMM version 1.0 */ ++ u8 qos_info; /* AP/STA specif QoS info */ ++ u8 reserved; /* 0 */ ++ struct esp_80211_wmm_ac_param ac[4]; /* AC_BE, AC_BK, AC_VI, AC_VO */ ++}; ++ ++ ++#endif /* _ESP_MAC80211_H_ */ +diff --git a/drivers/net/wireless/esp8089/esp_main.c b/drivers/net/wireless/esp8089/esp_main.c +new file mode 100644 +index 000000000000..404e0d7a6f54 +--- /dev/null ++++ b/drivers/net/wireless/esp8089/esp_main.c +@@ -0,0 +1,263 @@ ++/* ++ * Copyright (c) 2010 - 2014 Espressif System. ++ * ++ * main routine ++ * ++ * 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "esp_pub.h" ++#include "esp_sip.h" ++#include "esp_sif.h" ++#include "esp_debug.h" ++#include "esp_file.h" ++#include "esp_wl.h" ++ ++struct completion *gl_bootup_cplx = NULL; ++ ++#ifndef FPGA_DEBUG ++static int esp_download_fw(struct esp_pub *epub); ++#endif /* !FGPA_DEBUG */ ++ ++static int modparam_no_txampdu = 0; ++static int modparam_no_rxampdu = 0; ++module_param_named(no_txampdu, modparam_no_txampdu, int, 0444); ++MODULE_PARM_DESC(no_txampdu, "Disable tx ampdu."); ++module_param_named(no_rxampdu, modparam_no_rxampdu, int, 0444); ++MODULE_PARM_DESC(no_rxampdu, "Disable rx ampdu."); ++ ++static char *modparam_eagle_path = "/lib/firmware"; ++module_param_named(eagle_path, modparam_eagle_path, charp, 0444); ++MODULE_PARM_DESC(eagle_path, "eagle path"); ++ ++bool mod_support_no_txampdu() ++{ ++ return modparam_no_txampdu; ++} ++ ++bool mod_support_no_rxampdu() ++{ ++ return modparam_no_rxampdu; ++} ++ ++void mod_support_no_txampdu_set(bool value) ++{ ++ modparam_no_txampdu = value; ++} ++ ++char *mod_eagle_path_get(void) ++{ ++ if (modparam_eagle_path[0] == '\0') ++ return NULL; ++ ++ return modparam_eagle_path; ++} ++ ++int esp_pub_init_all(struct esp_pub *epub) ++{ ++ int ret = 0; ++ ++ /* completion for bootup event poll */ ++ DECLARE_COMPLETION_ONSTACK(complete); ++ atomic_set(&epub->ps.state, ESP_PM_OFF); ++ if (epub->sdio_state == ESP_SDIO_STATE_FIRST_INIT) { ++ epub->sip = sip_attach(epub); ++ if (epub->sip == NULL) { ++ printk(KERN_ERR "%s sip alloc failed\n", __func__); ++ return -ENOMEM; ++ } ++ ++ esp_dump_var("esp_msg_level", NULL, &esp_msg_level, ++ ESP_U32); ++ ++#ifdef ESP_ANDROID_LOGGER ++ esp_dump_var("log_off", NULL, &log_off, ESP_U32); ++#endif /* ESP_ANDROID_LOGGER */ ++ } else { ++ atomic_set(&epub->sip->state, SIP_PREPARE_BOOT); ++ atomic_set(&epub->sip->tx_credits, 0); ++ } ++ ++ epub->sip->to_host_seq = 0; ++ ++#ifdef TEST_MODE ++ if (sif_get_ate_config() != 0 && sif_get_ate_config() != 1 ++ && sif_get_ate_config() != 6) { ++ esp_test_init(epub); ++ return -1; ++ } ++#endif ++ ++#ifndef FPGA_DEBUG ++ ret = esp_download_fw(epub); ++#ifdef TEST_MODE ++ if (sif_get_ate_config() == 6) { ++ sif_enable_irq(epub); ++ mdelay(500); ++ sif_disable_irq(epub); ++ mdelay(1000); ++ esp_test_init(epub); ++ return -1; ++ } ++#endif ++ if (ret) { ++ esp_dbg(ESP_DBG_ERROR, "download firmware failed\n"); ++ return ret; ++ } ++ ++ esp_dbg(ESP_DBG_TRACE, "download firmware OK \n"); ++#else ++ sip_send_bootup(epub->sip); ++#endif /* FPGA_DEBUG */ ++ ++ gl_bootup_cplx = &complete; ++ epub->wait_reset = 0; ++ sif_enable_irq(epub); ++ ++ if (epub->sdio_state == ESP_SDIO_STATE_SECOND_INIT ++ || sif_get_ate_config() == 1) { ++ ret = sip_poll_bootup_event(epub->sip); ++ } else { ++ ret = sip_poll_resetting_event(epub->sip); ++ if (ret == 0) { ++ sif_lock_bus(epub); ++ sif_interrupt_target(epub, 7); ++ sif_unlock_bus(epub); ++ } ++ ++ } ++ ++ gl_bootup_cplx = NULL; ++ ++ if (sif_get_ate_config() == 1) ++ ret = -EOPNOTSUPP; ++ ++ return ret; ++} ++ ++void esp_dsr(struct esp_pub *epub) ++{ ++ sip_rx(epub); ++} ++ ++ ++struct esp_fw_hdr { ++ u8 magic; ++ u8 blocks; ++ u8 pad[2]; ++ u32 entry_addr; ++} __packed; ++ ++struct esp_fw_blk_hdr { ++ u32 load_addr; ++ u32 data_len; ++} __packed; ++ ++#define ESP_FW_NAME1 "eagle_fw_ate_config_v19.bin" ++#define ESP_FW_NAME2 "eagle_fw_first_init_v19.bin" ++#define ESP_FW_NAME3 "eagle_fw_second_init_v19.bin" ++ ++#ifndef FPGA_DEBUG ++static int esp_download_fw(struct esp_pub *epub) ++{ ++ const struct firmware *fw_entry; ++ u8 *fw_buf = NULL; ++ u32 offset = 0; ++ int ret = 0; ++ u8 blocks; ++ struct esp_fw_hdr *fhdr; ++ struct esp_fw_blk_hdr *bhdr = NULL; ++ struct sip_cmd_bootup bootcmd; ++ char *esp_fw_name; ++ ++ if (sif_get_ate_config() == 1) { ++ esp_fw_name = ESP_FW_NAME3; ++ } else { ++ esp_fw_name = ++ epub->sdio_state == ++ ESP_SDIO_STATE_FIRST_INIT ? ESP_FW_NAME1 : ++ ESP_FW_NAME2; ++ } ++ ret = request_firmware(&fw_entry, esp_fw_name, epub->dev); ++ ++ if (ret) ++ return ret; ++ ++ fw_buf = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL); ++ ++ release_firmware(fw_entry); ++ ++ if (fw_buf == NULL) { ++ return -ENOMEM; ++ } ++ ++ fhdr = (struct esp_fw_hdr *) fw_buf; ++ ++ if (fhdr->magic != 0xE9) { ++ esp_dbg(ESP_DBG_ERROR, "%s wrong magic! \n", __func__); ++ goto _err; ++ } ++ ++ blocks = fhdr->blocks; ++ offset += sizeof(struct esp_fw_hdr); ++ ++ while (blocks) { ++ ++ bhdr = (struct esp_fw_blk_hdr *) (&fw_buf[offset]); ++ offset += sizeof(struct esp_fw_blk_hdr); ++ ++ ret = ++ sip_write_memory(epub->sip, bhdr->load_addr, ++ &fw_buf[offset], bhdr->data_len); ++ ++ if (ret) { ++ esp_dbg(ESP_DBG_ERROR, ++ "%s Failed to write fw, err: %d\n", ++ __func__, ret); ++ goto _err; ++ } ++ ++ blocks--; ++ offset += bhdr->data_len; ++ } ++ ++ /* TODO: last byte should be the checksum and skip checksum for now */ ++ ++ bootcmd.boot_addr = fhdr->entry_addr; ++ ret = ++ sip_send_cmd(epub->sip, SIP_CMD_BOOTUP, ++ sizeof(struct sip_cmd_bootup), &bootcmd); ++ ++ if (ret) ++ goto _err; ++ ++ _err: ++ kfree(fw_buf); ++ ++ return ret; ++ ++} ++ ++MODULE_FIRMWARE(ESP_FW_NAME1); ++MODULE_FIRMWARE(ESP_FW_NAME2); ++MODULE_FIRMWARE(ESP_FW_NAME3); ++#endif /* !FPGA_DEBUG */ +diff --git a/drivers/net/wireless/esp8089/esp_path.h b/drivers/net/wireless/esp8089/esp_path.h +new file mode 100644 +index 000000000000..1ceb14bc3b15 +--- /dev/null ++++ b/drivers/net/wireless/esp8089/esp_path.h +@@ -0,0 +1,6 @@ ++#ifndef _ESP_PATH_H_ ++#define _ESP_PATH_H_ ++#define FWPATH "/lib/firmware" ++//module_param_string(fwpath, fwpath, sizeof(fwpath), 0644); ++ ++#endif /* _ESP_PATH_H_ */ +diff --git a/drivers/net/wireless/esp8089/esp_pub.h b/drivers/net/wireless/esp8089/esp_pub.h +new file mode 100644 +index 000000000000..0d3ad3655cf4 +--- /dev/null ++++ b/drivers/net/wireless/esp8089/esp_pub.h +@@ -0,0 +1,222 @@ ++/* ++ * Copyright (c) 2011-2014 Espressif System. ++ * ++ * wlan device header file ++ * ++ * 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 _ESP_PUB_H_ ++#define _ESP_PUB_H_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "sip2_common.h" ++ ++enum esp_sdio_state { ++ ESP_SDIO_STATE_FIRST_INIT, ++ ESP_SDIO_STATE_FIRST_NORMAL_EXIT, ++ ESP_SDIO_STATE_FIRST_ERROR_EXIT, ++ ESP_SDIO_STATE_SECOND_INIT, ++ ESP_SDIO_STATE_SECOND_ERROR_EXIT, ++}; ++ ++enum esp_tid_state { ++ ESP_TID_STATE_INIT, ++ ESP_TID_STATE_TRIGGER, ++ ESP_TID_STATE_PROGRESS, ++ ESP_TID_STATE_OPERATIONAL, ++ ESP_TID_STATE_WAIT_STOP, ++ ESP_TID_STATE_STOP, ++}; ++ ++struct esp_tx_tid { ++ u8 state; ++ u8 cnt; ++ u16 ssn; ++}; ++ ++#define WME_NUM_TID 16 ++struct esp_node { ++ struct esp_tx_tid tid[WME_NUM_TID]; ++ struct ieee80211_sta *sta; ++ u8 ifidx; ++ u8 index; ++}; ++ ++#define WME_AC_BE 2 ++#define WME_AC_BK 3 ++#define WME_AC_VI 1 ++#define WME_AC_VO 0 ++ ++struct llc_snap_hdr { ++ u8 dsap; ++ u8 ssap; ++ u8 cntl; ++ u8 org_code[3]; ++ __be16 eth_type; ++} __packed; ++ ++struct esp_vif { ++ struct esp_pub *epub; ++ u8 index; ++ u32 beacon_interval; ++ bool ap_up; ++ struct timer_list beacon_timer; ++}; ++ ++/* WLAN related, mostly... */ ++/*struct hw_scan_timeout { ++ struct delayed_work w; ++ struct ieee80211_hw *hw; ++};*/ ++ ++typedef struct esp_wl { ++ u8 bssid[ETH_ALEN]; ++ u8 req_bssid[ETH_ALEN]; ++ ++ //struct hw_scan_timeout *hsd; ++ struct cfg80211_scan_request *scan_req; ++ atomic_t ptk_cnt; ++ atomic_t gtk_cnt; ++ atomic_t tkip_key_set; ++ ++ /* so far only 2G band */ ++ struct ieee80211_supported_band sbands[NUM_NL80211_BANDS]; ++ ++ unsigned long flags; ++ atomic_t off; ++} esp_wl_t; ++ ++typedef struct esp_hw_idx_map { ++ u8 mac[ETH_ALEN]; ++ u8 flag; ++} esp_hw_idx_map_t; ++ ++#define ESP_WL_FLAG_RFKILL BIT(0) ++#define ESP_WL_FLAG_HW_REGISTERED BIT(1) ++#define ESP_WL_FLAG_CONNECT BIT(2) ++#define ESP_WL_FLAG_STOP_TXQ BIT(3) ++ ++#define ESP_PUB_MAX_VIF 2 ++#define ESP_PUB_MAX_STA 16 //for one interface ++#define ESP_PUB_MAX_RXAMPDU 8 //for all interfaces ++ ++enum { ++ ESP_PM_OFF = 0, ++ ESP_PM_TURNING_ON, ++ ESP_PM_ON, ++ ESP_PM_TURNING_OFF, /* Do NOT change the order */ ++}; ++ ++struct esp_ps { ++ u32 dtim_period; ++ u32 max_sleep_period; ++ unsigned long last_config_time; ++ atomic_t state; ++ bool nulldata_pm_on; ++}; ++ ++struct esp_mac_prefix { ++ u8 mac_index; ++ u8 mac_addr_prefix[3]; ++}; ++ ++struct esp_pub { ++ struct device *dev; ++#ifdef ESP_NO_MAC80211 ++ struct net_device *net_dev; ++ struct wireless_dev *wdev; ++ struct net_device_stats *net_stats; ++#else ++ struct ieee80211_hw *hw; ++ struct ieee80211_vif *vif; ++ u8 vif_slot; ++#endif /* ESP_MAC80211 */ ++ ++ void *sif; /* serial interface control block, e.g. sdio */ ++ enum esp_sdio_state sdio_state; ++ struct esp_sip *sip; ++ struct esp_wl wl; ++ struct esp_hw_idx_map hi_map[19]; ++ struct esp_hw_idx_map low_map[ESP_PUB_MAX_VIF][2]; ++ //u32 flags; //flags to represent rfkill switch,start ++ u8 roc_flags; //0: not in remain on channel state, 1: in roc state ++ ++ struct work_struct tx_work; /* attach to ieee80211 workqueue */ ++ /* latest mac80211 has multiple tx queue, but we stick with single queue now */ ++ spinlock_t rx_lock; ++ spinlock_t tx_ampdu_lock; ++ spinlock_t rx_ampdu_lock; ++ spinlock_t tx_lock; ++ struct mutex tx_mtx; ++ struct sk_buff_head txq; ++ atomic_t txq_stopped; ++ ++ struct work_struct sendup_work; /* attach to ieee80211 workqueue */ ++ struct sk_buff_head txdoneq; ++ struct sk_buff_head rxq; ++ ++ struct workqueue_struct *esp_wkq; ++ ++ //u8 bssid[ETH_ALEN]; ++ u8 mac_addr[ETH_ALEN]; ++ ++ u32 rx_filter; ++ unsigned long scan_permit; ++ bool scan_permit_valid; ++ struct delayed_work scan_timeout_work; ++ u32 enodes_map; ++ u8 rxampdu_map; ++ u32 enodes_maps[ESP_PUB_MAX_VIF]; ++ struct esp_node *enodes[ESP_PUB_MAX_STA + 1]; ++ struct esp_node *rxampdu_node[ESP_PUB_MAX_RXAMPDU]; ++ u8 rxampdu_tid[ESP_PUB_MAX_RXAMPDU]; ++ struct esp_ps ps; ++ int enable_int; ++ int wait_reset; ++}; ++ ++typedef struct esp_pub esp_pub_t; ++ ++struct esp_pub *esp_pub_alloc_mac80211(struct device *dev); ++int esp_pub_dealloc_mac80211(struct esp_pub *epub); ++int esp_register_mac80211(struct esp_pub *epub); ++ ++int esp_pub_init_all(struct esp_pub *epub); ++ ++char *mod_eagle_path_get(void); ++ ++void esp_dsr(struct esp_pub *epub); ++void hw_scan_done(struct esp_pub *epub, bool aborted); ++void esp_rocdone_process(struct ieee80211_hw *hw, ++ struct sip_evt_roc *report); ++ ++void esp_ps_config(struct esp_pub *epub, struct esp_ps *ps, bool on); ++ ++struct esp_node *esp_get_node_by_addr(struct esp_pub *epub, ++ const u8 * addr); ++struct esp_node *esp_get_node_by_index(struct esp_pub *epub, u8 index); ++int esp_get_empty_rxampdu(struct esp_pub *epub, const u8 * addr, u8 tid); ++int esp_get_exist_rxampdu(struct esp_pub *epub, const u8 * addr, u8 tid); ++ ++#ifdef TEST_MODE ++int test_init_netlink(struct esp_sip *sip); ++void test_exit_netlink(void); ++void esp_test_cmd_event(u32 cmd_type, char *reply_info); ++void esp_test_init(struct esp_pub *epub); ++#endif ++#endif /* _ESP_PUB_H_ */ +diff --git a/drivers/net/wireless/esp8089/esp_sif.h b/drivers/net/wireless/esp8089/esp_sif.h +new file mode 100644 +index 000000000000..2d49f2bc8035 +--- /dev/null ++++ b/drivers/net/wireless/esp8089/esp_sif.h +@@ -0,0 +1,207 @@ ++/* ++ * Copyright (c) 2011 - 2014 Espressif System. ++ * ++ * Serial I/F wrapper layer for eagle WLAN device, ++ * abstraction of buses like SDIO/SIP, and provides ++ * flow control for tx/rx layer ++ * ++ * 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 _ESP_SIF_H_ ++#define _ESP_SIF_H_ ++ ++#include "esp_pub.h" ++#include ++#include ++ ++/* ++ * H/W SLC module definitions ++ */ ++ ++#define SIF_SLC_BLOCK_SIZE 512 ++ ++ ++/* S/W struct mapping to slc registers */ ++typedef struct slc_host_regs { ++ /* do NOT read token_rdata ++ * ++ u32 pf_data; ++ u32 token_rdata; ++ */ ++ u32 intr_raw; ++ u32 state_w0; ++ u32 state_w1; ++ u32 config_w0; ++ u32 config_w1; ++ u32 intr_status; ++ u32 config_w2; ++ u32 config_w3; ++ u32 config_w4; ++ u32 token_wdata; ++ u32 intr_clear; ++ u32 intr_enable; ++} sif_slc_reg_t; ++ ++ ++enum io_sync_type { ++ ESP_SIF_NOSYNC = 0, ++ ESP_SIF_SYNC, ++}; ++ ++typedef struct esp_sdio_ctrl { ++ struct sdio_func *func; ++ struct esp_pub *epub; ++ ++ ++ struct list_head free_req; ++ ++ u8 *dma_buffer; ++ ++ spinlock_t scat_lock; ++ struct list_head scat_req; ++ ++ bool off; ++ atomic_t irq_handling; ++ const struct sdio_device_id *id; ++ u32 slc_blk_sz; ++ u32 target_id; ++ u32 slc_window_end_addr; ++ ++ struct slc_host_regs slc_regs; ++ atomic_t irq_installed; ++ ++} esp_sdio_ctrl_t; ++ ++#define SIF_TO_DEVICE 0x1 ++#define SIF_FROM_DEVICE 0x2 ++ ++#define SIF_SYNC 0x00000010 ++#define SIF_ASYNC 0x00000020 ++ ++#define SIF_BYTE_BASIS 0x00000040 ++#define SIF_BLOCK_BASIS 0x00000080 ++ ++#define SIF_FIXED_ADDR 0x00000100 ++#define SIF_INC_ADDR 0x00000200 ++ ++#define EPUB_CTRL_CHECK(_epub, _go_err) do{\ ++ if (_epub == NULL) {\ ++ ESSERT(0);\ ++ goto _go_err;\ ++ }\ ++ if ((_epub)->sif == NULL) {\ ++ ESSERT(0);\ ++ goto _go_err;\ ++ }\ ++}while(0) ++ ++#define EPUB_FUNC_CHECK(_epub, _go_err) do{\ ++ if (_epub == NULL) {\ ++ ESSERT(0);\ ++ goto _go_err;\ ++ }\ ++ if ((_epub)->sif == NULL) {\ ++ ESSERT(0);\ ++ goto _go_err;\ ++ }\ ++ if (((struct esp_sdio_ctrl *)(_epub)->sif)->func == NULL) {\ ++ ESSERT(0);\ ++ goto _go_err;\ ++ }\ ++}while(0) ++ ++#define EPUB_TO_CTRL(_epub) (((struct esp_sdio_ctrl *)(_epub)->sif)) ++ ++#define EPUB_TO_FUNC(_epub) (((struct esp_sdio_ctrl *)(_epub)->sif)->func) ++ ++void sdio_io_writeb(struct esp_pub *epub, u8 value, int addr, int *res); ++u8 sdio_io_readb(struct esp_pub *epub, int addr, int *res); ++ ++ ++void sif_enable_irq(struct esp_pub *epub); ++void sif_disable_irq(struct esp_pub *epub); ++void sif_disable_target_interrupt(struct esp_pub *epub); ++ ++u32 sif_get_blksz(struct esp_pub *epub); ++u32 sif_get_target_id(struct esp_pub *epub); ++ ++void sif_dsr(struct sdio_func *func); ++int sif_io_raw(struct esp_pub *epub, u32 addr, u8 * buf, u32 len, ++ u32 flag); ++int sif_io_sync(struct esp_pub *epub, u32 addr, u8 * buf, u32 len, ++ u32 flag); ++int sif_io_async(struct esp_pub *epub, u32 addr, u8 * buf, u32 len, ++ u32 flag, void *context); ++int sif_lldesc_read_sync(struct esp_pub *epub, u8 * buf, u32 len); ++int sif_lldesc_write_sync(struct esp_pub *epub, u8 * buf, u32 len); ++int sif_lldesc_read_raw(struct esp_pub *epub, u8 * buf, u32 len, ++ bool noround); ++int sif_lldesc_write_raw(struct esp_pub *epub, u8 * buf, u32 len); ++ ++int sif_platform_get_irq_no(void); ++int sif_platform_is_irq_occur(void); ++void sif_platform_irq_clear(void); ++void sif_platform_irq_mask(int enable_mask); ++int sif_platform_irq_init(void); ++void sif_platform_irq_deinit(void); ++ ++int esp_common_read(struct esp_pub *epub, u8 * buf, u32 len, int sync, ++ bool noround); ++int esp_common_write(struct esp_pub *epub, u8 * buf, u32 len, int sync); ++int esp_common_read_with_addr(struct esp_pub *epub, u32 addr, u8 * buf, ++ u32 len, int sync); ++int esp_common_write_with_addr(struct esp_pub *epub, u32 addr, u8 * buf, ++ u32 len, int sync); ++ ++int esp_common_readbyte_with_addr(struct esp_pub *epub, u32 addr, u8 * buf, ++ int sync); ++int esp_common_writebyte_with_addr(struct esp_pub *epub, u32 addr, u8 buf, ++ int sync); ++ ++int sif_read_reg_window(struct esp_pub *epub, unsigned int reg_addr, ++ unsigned char *value); ++int sif_write_reg_window(struct esp_pub *epub, unsigned int reg_addr, ++ unsigned char *value); ++int sif_ack_target_read_err(struct esp_pub *epub); ++int sif_had_io_enable(struct esp_pub *epub); ++ ++struct slc_host_regs *sif_get_regs(struct esp_pub *epub); ++ ++void sif_lock_bus(struct esp_pub *epub); ++void sif_unlock_bus(struct esp_pub *epub); ++ ++int sif_interrupt_target(struct esp_pub *epub, u8 index); ++#ifdef USE_EXT_GPIO ++int sif_config_gpio_mode(struct esp_pub *epub, u8 gpio_num, u8 gpio_mode); ++int sif_set_gpio_output(struct esp_pub *epub, u16 mask, u16 value); ++int sif_get_gpio_intr(struct esp_pub *epub, u16 intr_mask, u16 * value); ++int sif_get_gpio_input(struct esp_pub *epub, u16 * mask, u16 * value); ++#endif ++ ++void check_target_id(struct esp_pub *epub); ++ ++void sif_record_bt_config(int value); ++int sif_get_bt_config(void); ++void sif_record_rst_config(int value); ++int sif_get_rst_config(void); ++void sif_record_ate_config(int value); ++int sif_get_ate_config(void); ++void sif_record_retry_config(void); ++int sif_get_retry_config(void); ++void sif_record_wakeup_gpio_config(int value); ++int sif_get_wakeup_gpio_config(void); ++ ++#define sif_reg_read_sync(epub, addr, buf, len) sif_io_sync((epub), (addr), (buf), (len), SIF_FROM_DEVICE | SIF_BYTE_BASIS | SIF_INC_ADDR) ++ ++#define sif_reg_write_sync(epub, addr, buf, len) sif_io_sync((epub), (addr), (buf), (len), SIF_TO_DEVICE | SIF_BYTE_BASIS | SIF_INC_ADDR) ++ ++#endif /* _ESP_SIF_H_ */ +diff --git a/drivers/net/wireless/esp8089/esp_sip.c b/drivers/net/wireless/esp8089/esp_sip.c +new file mode 100644 +index 000000000000..6602a1e22ab1 +--- /dev/null ++++ b/drivers/net/wireless/esp8089/esp_sip.c +@@ -0,0 +1,2420 @@ ++/* ++ * Copyright (c) 2009 - 2014 Espressif System. ++ * ++ * Serial Interconnctor Protocol ++ * ++ * 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "esp_mac80211.h" ++#include "esp_pub.h" ++#include "esp_sip.h" ++#include "esp_ctrl.h" ++#include "esp_sif.h" ++#include "esp_debug.h" ++#include "slc_host_register.h" ++#include "esp_wmac.h" ++#include "esp_utils.h" ++ ++#ifdef USE_EXT_GPIO ++#include "esp_ext.h" ++#endif /* USE_EXT_GPIO */ ++ ++extern struct completion *gl_bootup_cplx; ++ ++static int old_signal = -35; ++static int avg_signal = 0; ++static int signal_loop = 0; ++ ++struct esp_mac_prefix esp_mac_prefix_table[] = { ++ {0, {0x18, 0xfe, 0x34}}, ++ {1, {0xac, 0xd0, 0x74}}, ++ {255, {0x18, 0xfe, 0x34}}, ++}; ++ ++#define SIGNAL_COUNT 300 ++ ++#define TID_TO_AC(_tid) ((_tid)== 0||((_tid)==3)?WME_AC_BE:((_tid)<3)?WME_AC_BK:((_tid)<6)?WME_AC_VI:WME_AC_VO) ++ ++#ifdef SIP_DEBUG ++#define esp_sip_dbg esp_dbg ++struct sip_trace { ++ u32 tx_data; ++ u32 tx_cmd; ++ u32 rx_data; ++ u32 rx_evt; ++ u32 rx_tx_status; ++ u32 tx_out_of_credit; ++ u32 tx_one_shot_overflow; ++}; ++static struct sip_trace str; ++#define STRACE_TX_DATA_INC() (str.tx_data++) ++#define STRACE_TX_CMD_INC() (str.tx_cmd++) ++#define STRACE_RX_DATA_INC() (str.rx_data++) ++#define STRACE_RX_EVENT_INC() (str.rx_evt++) ++#define STRACE_RX_TXSTATUS_INC() (str.rx_tx_status++) ++#define STRACE_TX_OUT_OF_CREDIT_INC() (str.tx_out_of_credit++) ++#define STRACE_TX_ONE_SHOT_INC() (str.tx_one_shot_overflow++) ++#define STRACE_SHOW(sip) ++#else ++#define esp_sip_dbg(...) ++#define STRACE_TX_DATA_INC() ++#define STRACE_TX_CMD_INC() ++#define STRACE_RX_DATA_INC() ++#define STRACE_RX_EVENT_INC() ++#define STRACE_RX_TXSTATUS_INC() ++#define STRACE_TX_OUT_OF_CREDIT_INC() ++#define STRACE_TX_ONE_SHOT_INC() ++#define STRACE_SHOW(sip) ++#endif /* SIP_DEBUG */ ++ ++#define SIP_STOP_QUEUE_THRESHOLD 48 ++#define SIP_RESUME_QUEUE_THRESHOLD 12 ++ ++#define SIP_MIN_DATA_PKT_LEN (sizeof(struct esp_mac_rx_ctrl) + 24) //24 is min 80211hdr ++ ++#ifdef ESP_PREALLOC ++extern struct sk_buff *esp_get_sip_skb(int size); ++extern void esp_put_sip_skb(struct sk_buff **skb); ++ ++extern u8 *esp_get_tx_aggr_buf(void); ++extern void esp_put_tx_aggr_buf(u8 ** p); ++ ++#endif ++ ++static void sip_recalc_credit_init(struct esp_sip *sip); ++ ++static int sip_recalc_credit_claim(struct esp_sip *sip, int force); ++ ++static void sip_recalc_credit_release(struct esp_sip *sip); ++ ++static struct sip_pkt *sip_get_ctrl_buf(struct esp_sip *sip, ++ SIP_BUF_TYPE bftype); ++ ++static void sip_reclaim_ctrl_buf(struct esp_sip *sip, struct sip_pkt *pkt, ++ SIP_BUF_TYPE bftype); ++ ++static void sip_free_init_ctrl_buf(struct esp_sip *sip); ++ ++static int sip_pack_pkt(struct esp_sip *sip, struct sk_buff *skb, ++ int *pm_state); ++ ++static struct esp_mac_rx_ctrl *sip_parse_normal_mac_ctrl(struct sk_buff ++ *skb, ++ int *pkt_len_enc, ++ int *buf_len, ++ int *pulled_len); ++ ++static struct sk_buff *sip_parse_data_rx_info(struct esp_sip *sip, ++ struct sk_buff *skb, ++ int pkt_len_enc, int buf_len, ++ struct esp_mac_rx_ctrl ++ *mac_ctrl, int *pulled_len); ++ ++static inline void sip_rx_pkt_enqueue(struct esp_sip *sip, ++ struct sk_buff *skb); ++ ++static void sip_after_write_pkts(struct esp_sip *sip); ++ ++static void sip_update_tx_credits(struct esp_sip *sip, ++ u16 recycled_credits); ++ ++//static void sip_trigger_txq_process(struct esp_sip *sip); ++ ++static bool sip_rx_pkt_process(struct esp_sip *sip, struct sk_buff *skb); ++ ++static void sip_tx_status_report(struct esp_sip *sip, struct sk_buff *skb, ++ struct ieee80211_tx_info *tx_info, ++ bool success); ++ ++#ifdef FPGA_TXDATA ++int sip_send_tx_data(struct esp_sip *sip); ++#endif /* FPGA_TXDATA */ ++ ++#ifdef FPGA_LOOPBACK ++int sip_send_loopback_cmd_mblk(struct esp_sip *sip); ++#endif /* FPGA_LOOPBACK */ ++ ++static bool check_ac_tid(u8 * pkt, u8 ac, u8 tid) ++{ ++ struct ieee80211_hdr *wh = (struct ieee80211_hdr *) pkt; ++#ifdef TID_DEBUG ++ u16 real_tid = 0; ++#endif //TID_DEBUG ++ ++ if (ieee80211_is_data_qos(wh->frame_control)) { ++#ifdef TID_DEBUG ++ real_tid = ++ *ieee80211_get_qos_ctl(wh) & ++ IEEE80211_QOS_CTL_TID_MASK; ++ ++ esp_sip_dbg(ESP_SHOW, "ac:%u, tid:%u, tid in pkt:%u\n", ac, ++ tid, real_tid); ++ if (tid != real_tid) { ++ esp_sip_dbg(ESP_DBG_ERROR, ++ "111 ac:%u, tid:%u, tid in pkt:%u\n", ++ ac, tid, real_tid); ++ } ++ if (TID_TO_AC(tid) != ac) { ++ esp_sip_dbg(ESP_DBG_ERROR, ++ "222 ac:%u, tid:%u, tid in pkt:%u\n", ++ ac, tid, real_tid); ++ } ++#endif /* TID_DEBUG */ ++ } else if (ieee80211_is_mgmt(wh->frame_control)) { ++#ifdef TID_DEBUG ++ esp_sip_dbg(ESP_SHOW, "ac:%u, tid:%u\n", ac, tid); ++ if (tid != 7 || ac != WME_AC_VO) { ++ esp_sip_dbg(ESP_DBG_ERROR, "333 ac:%u, tid:%u\n", ++ ac, tid); ++ } ++#endif /* TID_DEBUG */ ++ } else { ++ if (ieee80211_is_ctl(wh->frame_control)) { ++#ifdef TID_DEBUG ++ esp_sip_dbg(ESP_SHOW, ++ "%s is ctrl pkt fc 0x%04x ac:%u, tid:%u, tid in pkt:%u\n", ++ __func__, wh->frame_control, ac, tid, ++ real_tid); ++#endif /* TID_DEBUG */ ++ } else { ++ if (tid != 0 || ac != WME_AC_BE) { ++ //show_buf(pkt, 24); ++ esp_sip_dbg(ESP_DBG_LOG, ++ "444 ac:%u, tid:%u \n", ac, ++ tid); ++ if (tid == 7 && ac == WME_AC_VO) ++ return false; ++ } ++ return true; //hack to modify non-qos null data. ++ ++ } ++ } ++ ++ return false; ++} ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) ++static void sip_recalc_credit_timeout(struct timer_list *t) ++#else ++static void sip_recalc_credit_timeout(unsigned long data) ++#endif ++{ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) ++ struct esp_sip *sip = from_timer(sip, t, credit_timer); ++#else ++ struct esp_sip *sip = (struct esp_sip *) data; ++#endif ++ ++ esp_dbg(ESP_DBG_ERROR, "rct"); ++ ++ sip_recalc_credit_claim(sip, 1); /* recalc again */ ++} ++ ++static void sip_recalc_credit_init(struct esp_sip *sip) ++{ ++ atomic_set(&sip->credit_status, RECALC_CREDIT_DISABLE); //set it disable ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) ++ timer_setup(&sip->credit_timer, sip_recalc_credit_timeout, 0); ++#else ++ init_timer(&sip->credit_timer); ++ sip->credit_timer.data = (unsigned long) sip; ++ sip->credit_timer.function = sip_recalc_credit_timeout; ++#endif ++} ++ ++static int sip_recalc_credit_claim(struct esp_sip *sip, int force) ++{ ++ int ret; ++ ++ if (atomic_read(&sip->credit_status) == RECALC_CREDIT_ENABLE ++ && force == 0) ++ return 1; ++ ++ atomic_set(&sip->credit_status, RECALC_CREDIT_ENABLE); ++ ret = sip_send_recalc_credit(sip->epub); ++ if (ret) { ++ esp_dbg(ESP_DBG_ERROR, "%s error %d", __func__, ret); ++ return ret; ++ } ++ /*setup a timer for handle the abs_credit not receive */ ++ mod_timer(&sip->credit_timer, jiffies + msecs_to_jiffies(2000)); ++ ++ esp_dbg(ESP_SHOW, "rcc"); ++ ++ return ret; ++} ++ ++static void sip_recalc_credit_release(struct esp_sip *sip) ++{ ++ esp_dbg(ESP_SHOW, "rcr"); ++ ++ if (atomic_read(&sip->credit_status) == RECALC_CREDIT_ENABLE) { ++ atomic_set(&sip->credit_status, RECALC_CREDIT_DISABLE); ++ del_timer_sync(&sip->credit_timer); ++ } else ++ esp_dbg(ESP_SHOW, "maybe bogus credit"); ++} ++ ++static void sip_update_tx_credits(struct esp_sip *sip, ++ u16 recycled_credits) ++{ ++ esp_sip_dbg(ESP_DBG_TRACE, "%s:before add, credits is %d\n", ++ __func__, atomic_read(&sip->tx_credits)); ++ ++ if (recycled_credits & 0x800) { ++ atomic_set(&sip->tx_credits, (recycled_credits & 0x7ff)); ++ sip_recalc_credit_release(sip); ++ } else ++ atomic_add(recycled_credits, &sip->tx_credits); ++ ++ esp_sip_dbg(ESP_DBG_TRACE, "%s:after add %d, credits is %d\n", ++ __func__, recycled_credits, ++ atomic_read(&sip->tx_credits)); ++} ++ ++void sip_trigger_txq_process(struct esp_sip *sip) ++{ ++ if (atomic_read(&sip->tx_credits) <= sip->credit_to_reserve + SIP_CTRL_CREDIT_RESERVE //no credits, do nothing ++ || atomic_read(&sip->credit_status) == RECALC_CREDIT_ENABLE) ++ return; ++ ++ if (sip_queue_may_resume(sip)) { ++ /* wakeup upper queue only if we have sufficient credits */ ++ esp_sip_dbg(ESP_DBG_TRACE, "%s wakeup ieee80211 txq \n", ++ __func__); ++ atomic_set(&sip->epub->txq_stopped, false); ++ ieee80211_wake_queues(sip->epub->hw); ++ } else if (atomic_read(&sip->epub->txq_stopped)) { ++ esp_sip_dbg(ESP_DBG_TRACE, ++ "%s can't wake txq, credits: %d \n", __func__, ++ atomic_read(&sip->tx_credits)); ++ } ++ ++ if (!skb_queue_empty(&sip->epub->txq)) { ++ /* try to send out pkt already in sip queue once we have credits */ ++ esp_sip_dbg(ESP_DBG_TRACE, "%s resume sip txq \n", ++ __func__); ++ ++#if !defined(FPGA_TXDATA) ++ if (sif_get_ate_config() == 0) { ++ ieee80211_queue_work(sip->epub->hw, ++ &sip->epub->tx_work); ++ } else { ++ queue_work(sip->epub->esp_wkq, ++ &sip->epub->tx_work); ++ } ++#else ++ queue_work(sip->epub->esp_wkq, &sip->epub->tx_work); ++#endif ++ } ++} ++ ++static bool sip_ampdu_occupy_buf(struct esp_sip *sip, ++ struct esp_rx_ampdu_len *ampdu_len) ++{ ++ return (ampdu_len->substate == 0 ++ || esp_wmac_rxsec_error(ampdu_len->substate) ++ || (sip->dump_rpbm_err ++ && ampdu_len->substate == RX_RPBM_ERR)); ++} ++ ++static bool sip_rx_pkt_process(struct esp_sip *sip, struct sk_buff *skb) ++{ ++#define DO_NOT_COPY false ++#define DO_COPY true ++ ++ struct sip_hdr *hdr = NULL; ++ struct sk_buff *rskb = NULL; ++ int remains_len = 0; ++ int first_pkt_len = 0; ++ u8 *bufptr = NULL; ++ int ret = 0; ++ bool trigger_rxq = false; ++ ++ if (skb == NULL) { ++ esp_sip_dbg(ESP_DBG_ERROR, "%s NULL SKB!!!!!!!! \n", ++ __func__); ++ return trigger_rxq; ++ } ++ ++ hdr = (struct sip_hdr *) skb->data; ++ bufptr = skb->data; ++ ++ ++ esp_sip_dbg(ESP_DBG_TRACE, "%s Hcredits 0x%08x, realCredits %d\n", ++ __func__, hdr->h_credits, ++ hdr->h_credits & SIP_CREDITS_MASK); ++ if (hdr->h_credits & SIP_CREDITS_MASK) { ++ sip_update_tx_credits(sip, ++ hdr->h_credits & SIP_CREDITS_MASK); ++ } ++ ++ hdr->h_credits &= ~SIP_CREDITS_MASK; /* clean credits in sip_hdr, prevent over-add */ ++ ++ esp_sip_dbg(ESP_DBG_TRACE, "%s credits %d\n", __func__, ++ hdr->h_credits); ++ ++ /* ++ * first pkt's length is stored in recycled_credits first 20 bits ++ * config w3 [31:12] ++ * repair hdr->len of first pkt ++ */ ++ remains_len = hdr->len; ++ first_pkt_len = hdr->h_credits >> 12; ++ hdr->len = first_pkt_len; ++ ++ esp_dbg(ESP_DBG_TRACE, "%s first_pkt_len %d, whole pkt len %d \n", ++ __func__, first_pkt_len, remains_len); ++ if (first_pkt_len > remains_len) { ++ sip_recalc_credit_claim(sip, 0); ++ esp_dbg(ESP_DBG_ERROR, ++ "first_pkt_len %d, whole pkt len %d\n", ++ first_pkt_len, remains_len); ++ show_buf((u8 *) hdr, first_pkt_len); ++ ESSERT(0); ++ goto _exit; ++ } ++ ++ /* ++ * pkts handling, including the first pkt, should alloc new skb for each data pkt. ++ * free the original whole skb after parsing is done. ++ */ ++ while (remains_len) { ++ if (remains_len < sizeof(struct sip_hdr)) { ++ sip_recalc_credit_claim(sip, 0); ++ ESSERT(0); ++ show_buf((u8 *) hdr, 512); ++ goto _exit; ++ } ++ ++ hdr = (struct sip_hdr *) bufptr; ++ if (hdr->len <= 0) { ++ sip_recalc_credit_claim(sip, 0); ++ show_buf((u8 *) hdr, 512); ++ ESSERT(0); ++ goto _exit; ++ } ++ ++ if ((hdr->len & 3) != 0) { ++ sip_recalc_credit_claim(sip, 0); ++ show_buf((u8 *) hdr, 512); ++ ESSERT(0); ++ goto _exit; ++ } ++ if (unlikely(hdr->seq != sip->rxseq++)) { ++ sip_recalc_credit_claim(sip, 0); ++ esp_dbg(ESP_DBG_ERROR, ++ "%s seq mismatch! got %u, expect %u\n", ++ __func__, hdr->seq, sip->rxseq - 1); ++ sip->rxseq = hdr->seq + 1; ++ show_buf(bufptr, 32); ++ ESSERT(0); ++ } ++ ++ if (SIP_HDR_IS_CTRL(hdr)) { ++ STRACE_RX_EVENT_INC(); ++ esp_sip_dbg(ESP_DBG_TRACE, "seq %u \n", hdr->seq); ++ ++ ret = sip_parse_events(sip, bufptr); ++ ++ skb_pull(skb, hdr->len); ++ ++ } else if (SIP_HDR_IS_DATA(hdr)) { ++ struct esp_mac_rx_ctrl *mac_ctrl = NULL; ++ int pkt_len_enc = 0, buf_len = 0, pulled_len = 0; ++ ++ STRACE_RX_DATA_INC(); ++ esp_sip_dbg(ESP_DBG_TRACE, "seq %u \n", hdr->seq); ++ mac_ctrl = ++ sip_parse_normal_mac_ctrl(skb, &pkt_len_enc, ++ &buf_len, ++ &pulled_len); ++ rskb = ++ sip_parse_data_rx_info(sip, skb, pkt_len_enc, ++ buf_len, mac_ctrl, ++ &pulled_len); ++ ++ if (rskb == NULL) ++ goto _move_on; ++ ++ if (likely(atomic_read(&sip->epub->wl.off) == 0)) { ++#ifdef RX_CHECKSUM_TEST ++ esp_rx_checksum_test(rskb); ++#endif ++ local_bh_disable(); ++ ieee80211_rx(sip->epub->hw, rskb); ++ local_bh_enable(); ++ } else { ++ /* still need go thro parsing as skb_pull should invoke */ ++ kfree_skb(rskb); ++ } ++ } else if (SIP_HDR_IS_AMPDU(hdr)) { ++ struct esp_mac_rx_ctrl *mac_ctrl = NULL; ++ struct esp_mac_rx_ctrl new_mac_ctrl; ++ struct esp_rx_ampdu_len *ampdu_len; ++ int pkt_num; ++ int pulled_len = 0; ++ static int pkt_dropped = 0; ++ static int pkt_total = 0; ++ bool have_rxabort = false; ++ bool have_goodpkt = false; ++ static u8 frame_head[16]; ++ static u8 frame_buf_ttl = 0; ++ ++ ampdu_len = ++ (struct esp_rx_ampdu_len *) (skb->data + ++ hdr->len / ++ sip->rx_blksz * ++ sip->rx_blksz); ++ esp_sip_dbg(ESP_DBG_TRACE, ++ "%s rx ampdu total len %u\n", __func__, ++ hdr->len); ++ if (skb->data != (u8 *) hdr) { ++ printk("%p %p\n", skb->data, hdr); ++ show_buf(skb->data, 512); ++ show_buf((u8 *) hdr, 512); ++ ESSERT(0); ++ goto _exit; ++ } ++ mac_ctrl = ++ sip_parse_normal_mac_ctrl(skb, NULL, NULL, ++ &pulled_len); ++ memcpy(&new_mac_ctrl, mac_ctrl, ++ sizeof(struct esp_mac_rx_ctrl)); ++ mac_ctrl = &new_mac_ctrl; ++ pkt_num = mac_ctrl->ampdu_cnt; ++ esp_sip_dbg(ESP_DBG_TRACE, ++ "%s %d rx ampdu %u pkts, %d pkts dumped, first len %u\n", ++ __func__, __LINE__, ++ (unsigned ++ int) ((hdr->len % sip->rx_blksz) / ++ sizeof(struct ++ esp_rx_ampdu_len)), ++ pkt_num, ++ (unsigned int) ampdu_len->sublen); ++ ++ pkt_total += mac_ctrl->ampdu_cnt; ++ //esp_sip_dbg(ESP_DBG_ERROR, "%s ampdu dropped %d/%d\n", __func__, pkt_dropped, pkt_total); ++ while (pkt_num > 0) { ++ esp_sip_dbg(ESP_DBG_TRACE, ++ "%s %d ampdu sub state %02x,\n", ++ __func__, __LINE__, ++ ampdu_len->substate); ++ ++ if (sip_ampdu_occupy_buf(sip, ampdu_len)) { //pkt is dumped ++ ++ rskb = ++ sip_parse_data_rx_info(sip, ++ skb, ++ ampdu_len-> ++ sublen - ++ FCS_LEN, ++ 0, ++ mac_ctrl, ++ &pulled_len); ++ if (!rskb) { ++ ESSERT(0); ++ goto _exit; ++ } ++ ++ if (likely ++ (atomic_read ++ (&sip->epub->wl.off) == 0) ++ && (ampdu_len->substate == 0 ++ || ampdu_len->substate == ++ RX_TKIPMIC_ERR ++ || (sip->sendup_rpbm_pkt ++ && ampdu_len-> ++ substate == ++ RX_RPBM_ERR)) ++ && (sip->rxabort_fixed ++ || !have_rxabort)) { ++ if (!have_goodpkt) { ++ have_goodpkt = ++ true; ++ memcpy(frame_head, ++ rskb->data, ++ 16); ++ frame_head[1] &= ++ ~0x80; ++ frame_buf_ttl = 3; ++ } ++#ifdef RX_CHECKSUM_TEST ++ esp_rx_checksum_test(rskb); ++#endif ++ local_bh_disable(); ++ ieee80211_rx(sip->epub->hw, ++ rskb); ++ local_bh_enable(); ++ ++ } else { ++ kfree_skb(rskb); ++ } ++ } else { ++ if (ampdu_len->substate == ++ RX_ABORT) { ++ u8 *a; ++ have_rxabort = true; ++ esp_sip_dbg(ESP_DBG_TRACE, ++ "rx abort %d %d\n", ++ frame_buf_ttl, ++ pkt_num); ++ if (frame_buf_ttl ++ && !sip-> ++ rxabort_fixed) { ++ struct ++ esp_rx_ampdu_len ++ *next_good_ampdu_len ++ = ++ ampdu_len + 1; ++ a = frame_head; ++ esp_sip_dbg ++ (ESP_DBG_TRACE, ++ "frame:%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", ++ a[0], a[1], ++ a[2], a[3], ++ a[4], a[5], ++ a[6], a[7], ++ a[8], a[9], ++ a[10], a[11], ++ a[12], a[13], ++ a[14], a[15]); ++ while ++ (!sip_ampdu_occupy_buf ++ (sip, ++ next_good_ampdu_len)) ++ { ++ if (next_good_ampdu_len > ampdu_len + pkt_num - 1) ++ break; ++ next_good_ampdu_len++; ++ ++ } ++ if (next_good_ampdu_len <= ampdu_len + pkt_num - 1) { ++ bool b0, ++ b10, ++ b11; ++ a = skb-> ++ data; ++ esp_sip_dbg ++ (ESP_DBG_TRACE, ++ "buf:%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", ++ a[0], ++ a[1], ++ a[2], ++ a[3], ++ a[4], ++ a[5], ++ a[6], ++ a[7], ++ a[8], ++ a[9], ++ a[10], ++ a[11], ++ a[12], ++ a[13], ++ a[14], ++ a ++ [15]); ++ b0 = memcmp ++ (frame_head ++ + 4, ++ skb-> ++ data + ++ 4, ++ 12) == ++ 0; ++ b10 = ++ memcmp ++ (frame_head ++ + 10, ++ skb-> ++ data, ++ 6) == ++ 0; ++ b11 = ++ memcpy ++ (frame_head ++ + 11, ++ skb-> ++ data, ++ 5) == ++ 0; ++ esp_sip_dbg ++ (ESP_DBG_TRACE, ++ "com %d %d %d\n", ++ b0, ++ b10, ++ b11); ++ if (b0 ++ && !b10 ++ && ++ !b11) { ++ have_rxabort ++ = ++ false; ++ esp_sip_dbg ++ (ESP_DBG_TRACE, ++ "repair 0\n"); ++ } else ++ if (!b0 ++ && ++ b10 ++ && ++ !b11) ++ { ++ skb_push ++ (skb, ++ 10); ++ memcpy ++ (skb-> ++ data, ++ frame_head, ++ 10); ++ have_rxabort ++ = ++ false; ++ pulled_len ++ -= ++ 10; ++ esp_sip_dbg ++ (ESP_DBG_TRACE, ++ "repair 10\n"); ++ } else ++ if (!b0 ++ && ++ !b10 ++ && ++ b11) ++ { ++ skb_push ++ (skb, ++ 11); ++ memcpy ++ (skb-> ++ data, ++ frame_head, ++ 11); ++ have_rxabort ++ = ++ false; ++ pulled_len ++ -= ++ 11; ++ esp_sip_dbg ++ (ESP_DBG_TRACE, ++ "repair 11\n"); ++ } ++ } ++ } ++ } ++ pkt_dropped++; ++ esp_sip_dbg(ESP_DBG_LOG, ++ "%s ampdu dropped %d/%d\n", ++ __func__, pkt_dropped, ++ pkt_total); ++ } ++ pkt_num--; ++ ampdu_len++; ++ } ++ if (frame_buf_ttl) ++ frame_buf_ttl--; ++ skb_pull(skb, hdr->len - pulled_len); ++ } else { ++ esp_sip_dbg(ESP_DBG_ERROR, "%s %d unknown type\n", ++ __func__, __LINE__); ++ } ++ ++ _move_on: ++ if (hdr->len < remains_len) { ++ remains_len -= hdr->len; ++ } else { ++ break; ++ } ++ bufptr += hdr->len; ++ } ++ ++ _exit: ++#ifdef ESP_PREALLOC ++ esp_put_sip_skb(&skb); ++#else ++ kfree_skb(skb); ++#endif ++ ++ return trigger_rxq; ++ ++#undef DO_NOT_COPY ++#undef DO_COPY ++} ++ ++static void _sip_rxq_process(struct esp_sip *sip) ++{ ++ struct sk_buff *skb = NULL; ++ bool sendup = false; ++ ++ while ((skb = skb_dequeue(&sip->rxq))) { ++ if (sip_rx_pkt_process(sip, skb)) ++ sendup = true; ++ } ++ if (sendup) { ++ queue_work(sip->epub->esp_wkq, &sip->epub->sendup_work); ++ } ++ ++ /* probably tx_credit is updated, try txq */ ++ sip_trigger_txq_process(sip); ++} ++ ++static void sip_rxq_process(struct work_struct *work) ++{ ++ struct esp_sip *sip = ++ container_of(work, struct esp_sip, rx_process_work); ++ if (sip == NULL) { ++ ESSERT(0); ++ return; ++ } ++ ++ if (unlikely(atomic_read(&sip->state) == SIP_SEND_INIT)) { ++ sip_send_chip_init(sip); ++ atomic_set(&sip->state, SIP_WAIT_BOOTUP); ++ return; ++ } ++ ++ mutex_lock(&sip->rx_mtx); ++ _sip_rxq_process(sip); ++ mutex_unlock(&sip->rx_mtx); ++} ++ ++static inline void sip_rx_pkt_enqueue(struct esp_sip *sip, ++ struct sk_buff *skb) ++{ ++ skb_queue_tail(&sip->rxq, skb); ++} ++ ++static inline struct sk_buff *sip_rx_pkt_dequeue(struct esp_sip *sip) ++{ ++ return skb_dequeue(&sip->rxq); ++} ++ ++static u32 sip_rx_count = 0; ++void sip_debug_show(struct esp_sip *sip) ++{ ++ esp_sip_dbg(ESP_DBG_ERROR, "txq left %d %d\n", ++ skb_queue_len(&sip->epub->txq), ++ atomic_read(&sip->tx_data_pkt_queued)); ++ esp_sip_dbg(ESP_DBG_ERROR, "tx queues stop ? %d\n", ++ atomic_read(&sip->epub->txq_stopped)); ++ esp_sip_dbg(ESP_DBG_ERROR, "txq stop? %d\n", ++ test_bit(ESP_WL_FLAG_STOP_TXQ, &sip->epub->wl.flags)); ++ esp_sip_dbg(ESP_DBG_ERROR, "tx credit %d\n", ++ atomic_read(&sip->tx_credits)); ++ esp_sip_dbg(ESP_DBG_ERROR, "rx collect %d\n", sip_rx_count); ++ sip_rx_count = 0; ++} ++ ++int sip_rx(struct esp_pub *epub) ++{ ++ struct sip_hdr *shdr = NULL; ++ struct esp_sip *sip = epub->sip; ++ int err = 0; ++ struct sk_buff *first_skb = NULL; ++ u8 *rx_buf = NULL; ++ u32 rx_blksz; ++ struct sk_buff *rx_skb = NULL; ++ ++ u32 first_sz; ++ ++ first_sz = sif_get_regs(epub)->config_w0; ++ ++ if (likely(sif_get_ate_config() != 1)) { ++ do { ++ u8 raw_seq = sif_get_regs(epub)->intr_raw & 0xff; ++ ++ if (raw_seq != sip->to_host_seq) { ++ if (raw_seq == sip->to_host_seq + 1) { /* when last read pkt crc err, this situation may occur, but raw_seq mustn't < to_host_Seq */ ++ sip->to_host_seq = raw_seq; ++ esp_dbg(ESP_DBG_TRACE, ++ "warn: to_host_seq reg 0x%02x, seq 0x%02x", ++ raw_seq, sip->to_host_seq); ++ break; ++ } ++ esp_dbg(ESP_DBG_ERROR, ++ "err: to_host_seq reg 0x%02x, seq 0x%02x", ++ raw_seq, sip->to_host_seq); ++ goto _err; ++ } ++ } while (0); ++ } ++ esp_sip_dbg(ESP_DBG_LOG, "%s enter\n", __func__); ++ ++ ++ /* first read one block out, if we luck enough, that's it ++ * ++ * To make design as simple as possible, we allocate skb(s) ++ * separately for each sif read operation to avoid global ++ * read_buf_pointe access. It coule be optimized late. ++ */ ++ rx_blksz = sif_get_blksz(epub); ++#ifdef ESP_PREALLOC ++ first_skb = esp_get_sip_skb(roundup(first_sz, rx_blksz)); ++#else ++ first_skb = ++ __dev_alloc_skb(roundup(first_sz, rx_blksz), GFP_KERNEL); ++#endif /* ESP_PREALLOC */ ++ ++ if (first_skb == NULL) { ++ sif_unlock_bus(epub); ++ esp_sip_dbg(ESP_DBG_ERROR, "%s first no memory \n", ++ __func__); ++ goto _err; ++ } ++ ++ rx_buf = skb_put(first_skb, first_sz); ++ esp_sip_dbg(ESP_DBG_LOG, "%s rx_buf ptr %p, first_sz %d\n", ++ __func__, rx_buf, first_sz); ++ ++ ++#ifdef USE_EXT_GPIO ++ do { ++ int err2 = 0; ++ u16 value = 0; ++ u16 intr_mask = ext_gpio_get_int_mask_reg(); ++ if (!intr_mask) ++ break; ++ value = sif_get_regs(epub)->config_w3 & intr_mask; ++ if (value) { ++ err2 = sif_interrupt_target(epub, 6); ++ esp_sip_dbg(ESP_DBG, "write gpio\n"); ++ } ++ ++ if (!err2 && value) { ++ esp_sip_dbg(ESP_DBG_TRACE, ++ "%s intr_mask[0x%04x] value[0x%04x]\n", ++ __func__, intr_mask, value); ++ ext_gpio_int_process(value); ++ } ++ } while (0); ++#endif ++ ++ err = ++ esp_common_read(epub, rx_buf, first_sz, ESP_SIF_NOSYNC, false); ++ sip_rx_count++; ++ if (unlikely(err)) { ++ esp_dbg(ESP_DBG_ERROR, " %s first read err %d %d\n", ++ __func__, err, sif_get_regs(epub)->config_w0); ++#ifdef ESP_PREALLOC ++ esp_put_sip_skb(&first_skb); ++#else ++ kfree_skb(first_skb); ++#endif /* ESP_PREALLOC */ ++ sif_unlock_bus(epub); ++ goto _err; ++ } ++ ++ shdr = (struct sip_hdr *) rx_buf; ++ if (SIP_HDR_IS_CTRL(shdr) && (shdr->c_evtid == SIP_EVT_SLEEP)) { ++ atomic_set(&sip->epub->ps.state, ESP_PM_ON); ++ esp_dbg(ESP_DBG_TRACE, "s\n"); ++ } ++ ++ if (likely(sif_get_ate_config() != 1)) { ++ sip->to_host_seq++; ++ } ++ ++ if ((shdr->len & 3) != 0) { ++ esp_sip_dbg(ESP_DBG_ERROR, "%s shdr->len[%d] error\n", ++ __func__, shdr->len); ++#ifdef ESP_PREALLOC ++ esp_put_sip_skb(&first_skb); ++#else ++ kfree_skb(first_skb); ++#endif /* ESP_PREALLOC */ ++ sif_unlock_bus(epub); ++ err = -EIO; ++ goto _err; ++ } ++ if (shdr->len != first_sz) { ++ esp_sip_dbg(ESP_DBG_ERROR, ++ "%s shdr->len[%d] first_size[%d] error\n", ++ __func__, shdr->len, first_sz); ++#ifdef ESP_PREALLOC ++ esp_put_sip_skb(&first_skb); ++#else ++ kfree_skb(first_skb); ++#endif /* ESP_PREALLOC */ ++ sif_unlock_bus(epub); ++ err = -EIO; ++ goto _err; ++ } else { ++ sif_unlock_bus(epub); ++ skb_trim(first_skb, shdr->len); ++ esp_dbg(ESP_DBG_TRACE, " %s first_skb only\n", __func__); ++ ++ rx_skb = first_skb; ++ } ++ ++ if (atomic_read(&sip->state) == SIP_STOP) { ++#ifdef ESP_PREALLOC ++ esp_put_sip_skb(&rx_skb); ++#else ++ kfree_skb(rx_skb); ++#endif /* ESP_PREALLOC */ ++ esp_sip_dbg(ESP_DBG_ERROR, "%s when sip stopped\n", ++ __func__); ++ return 0; ++ } ++ ++ sip_rx_pkt_enqueue(sip, rx_skb); ++ queue_work(sip->epub->esp_wkq, &sip->rx_process_work); ++ ++ _err: ++ return err; ++} ++ ++int sip_post_init(struct esp_sip *sip, struct sip_evt_bootup2 *bevt) ++{ ++ struct esp_pub *epub; ++ ++ u8 mac_id = bevt->mac_addr[0]; ++ int mac_index = 0; ++ int i = 0; ++ ++ if (sip == NULL) { ++ ESSERT(0); ++ return -EINVAL; ++ } ++ ++ epub = sip->epub; ++ ++ ++ sip->tx_aggr_write_ptr = sip->tx_aggr_buf; ++ ++ sip->tx_blksz = bevt->tx_blksz; ++ sip->rx_blksz = bevt->rx_blksz; ++ sip->credit_to_reserve = bevt->credit_to_reserve; ++ ++ sip->dump_rpbm_err = (bevt->options & SIP_DUMP_RPBM_ERR); ++ sip->rxabort_fixed = (bevt->options & SIP_RXABORT_FIXED); ++ sip->support_bgscan = (bevt->options & SIP_SUPPORT_BGSCAN); ++ ++ sip->sendup_rpbm_pkt = sip->dump_rpbm_err && false; ++ ++ /* print out MAC addr... */ ++ memcpy(epub->mac_addr, bevt->mac_addr, ETH_ALEN); ++ for (i = 0; ++ i < ++ sizeof(esp_mac_prefix_table) / sizeof(struct esp_mac_prefix); ++ i++) { ++ if (esp_mac_prefix_table[i].mac_index == mac_id) { ++ mac_index = i; ++ break; ++ } ++ } ++ ++ epub->mac_addr[0] = ++ esp_mac_prefix_table[mac_index].mac_addr_prefix[0]; ++ epub->mac_addr[1] = ++ esp_mac_prefix_table[mac_index].mac_addr_prefix[1]; ++ epub->mac_addr[2] = ++ esp_mac_prefix_table[mac_index].mac_addr_prefix[2]; ++ ++#ifdef SELF_MAC ++ epub->mac_addr[0] = 0xff; ++ epub->mac_addr[1] = 0xff; ++ epub->mac_addr[2] = 0xff; ++#endif ++ atomic_set(&sip->noise_floor, bevt->noise_floor); ++ ++ sip_recalc_credit_init(sip); ++ ++ esp_sip_dbg(ESP_DBG_TRACE, ++ "%s tx_blksz %d rx_blksz %d mac addr %pM\n", __func__, ++ sip->tx_blksz, sip->rx_blksz, epub->mac_addr); ++ ++ return 0; ++} ++ ++/* write pkts in aggr buf to target memory */ ++static void sip_write_pkts(struct esp_sip *sip, int pm_state) ++{ ++ int tx_aggr_len = 0; ++ struct sip_hdr *first_shdr = NULL; ++ int err = 0; ++ ++ tx_aggr_len = sip->tx_aggr_write_ptr - sip->tx_aggr_buf; ++ if (tx_aggr_len < sizeof(struct sip_hdr)) { ++ printk("%s tx_aggr_len %d \n", __func__, tx_aggr_len); ++ ESSERT(0); ++ return; ++ } ++ if ((tx_aggr_len & 0x3) != 0) { ++ ESSERT(0); ++ return; ++ } ++ ++ first_shdr = (struct sip_hdr *) sip->tx_aggr_buf; ++ ++ if (atomic_read(&sip->tx_credits) <= SIP_CREDITS_LOW_THRESHOLD) { ++ first_shdr->fc[1] |= SIP_HDR_F_NEED_CRDT_RPT; ++ } ++ ++ /* still use lock bus instead of sif_lldesc_write_sync since we want to protect several global varibles assignments */ ++ sif_lock_bus(sip->epub); ++ ++ err = ++ esp_common_write(sip->epub, sip->tx_aggr_buf, tx_aggr_len, ++ ESP_SIF_NOSYNC); ++ ++ sip->tx_aggr_write_ptr = sip->tx_aggr_buf; ++ sip->tx_tot_len = 0; ++ ++ sif_unlock_bus(sip->epub); ++ ++ if (err) ++ esp_sip_dbg(ESP_DBG_ERROR, "func %s err!!!!!!!!!: %d\n", ++ __func__, err); ++ ++} ++ ++/* setup sip header and tx info, copy pkt into aggr buf */ ++static int sip_pack_pkt(struct esp_sip *sip, struct sk_buff *skb, ++ int *pm_state) ++{ ++ struct ieee80211_tx_info *itx_info; ++ struct sip_hdr *shdr; ++ u32 tx_len = 0, offset = 0; ++ bool is_data = true; ++ ++ itx_info = IEEE80211_SKB_CB(skb); ++ ++ if (itx_info->flags == 0xffffffff) { ++ shdr = (struct sip_hdr *) skb->data; ++ is_data = false; ++ tx_len = skb->len; ++ } else { ++ struct ieee80211_hdr *wh = ++ (struct ieee80211_hdr *) skb->data; ++ struct esp_vif *evif = ++ (struct esp_vif *) itx_info->control.vif->drv_priv; ++ u8 sta_index; ++ struct esp_node *node; ++ /* update sip header */ ++ shdr = (struct sip_hdr *) sip->tx_aggr_write_ptr; ++ ++ shdr->fc[0] = 0; ++ shdr->fc[1] = 0; ++ ++ if ((itx_info->flags & IEEE80211_TX_CTL_AMPDU) ++ && (true || esp_is_ip_pkt(skb))) ++ SIP_HDR_SET_TYPE(shdr->fc[0], SIP_DATA_AMPDU); ++ else ++ SIP_HDR_SET_TYPE(shdr->fc[0], SIP_DATA); ++ ++ if (evif->epub == NULL) { ++ sip_tx_status_report(sip, skb, itx_info, false); ++ atomic_dec(&sip->tx_data_pkt_queued); ++ return -EINVAL; ++ } ++ ++ /* make room for encrypted pkt */ ++ if (itx_info->control.hw_key) { ++ int alg = ++ esp_cipher2alg(itx_info->control.hw_key-> ++ cipher); ++ if (unlikely(alg == -1)) { ++ sip_tx_status_report(sip, skb, itx_info, ++ false); ++ atomic_dec(&sip->tx_data_pkt_queued); ++ return -1; ++ } else { ++ shdr->d_enc_flag = alg + 1; ++ } ++ ++ shdr->d_hw_kid = ++ itx_info->control.hw_key->hw_key_idx | (evif-> ++ index ++ << 7); ++ } else { ++ shdr->d_enc_flag = 0; ++ shdr->d_hw_kid = (evif->index << 7 | evif->index); ++ } ++ ++ /* update sip tx info */ ++ node = esp_get_node_by_addr(sip->epub, wh->addr1); ++ if (node != NULL) ++ sta_index = node->index; ++ else ++ sta_index = ESP_PUB_MAX_STA + 1; ++ SIP_HDR_SET_IFIDX(shdr->fc[0], ++ evif->index << 3 | sta_index); ++ shdr->d_p2p = itx_info->control.vif->p2p; ++ if (evif->index == 1) ++ shdr->d_p2p = 1; ++ shdr->d_ac = skb_get_queue_mapping(skb); ++ shdr->d_tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; ++ wh = (struct ieee80211_hdr *) skb->data; ++ if (ieee80211_is_mgmt(wh->frame_control)) { ++ /* addba/delba/bar may use different tid/ac */ ++ if (shdr->d_ac == WME_AC_VO) { ++ shdr->d_tid = 7; ++ } ++ if (ieee80211_is_beacon(wh->frame_control)) { ++ shdr->d_tid = 8; ++ shdr->d_ac = 4; ++ } ++ } ++ if (check_ac_tid(skb->data, shdr->d_ac, shdr->d_tid)) { ++ shdr->d_ac = WME_AC_BE; ++ shdr->d_tid = 0; ++ } ++ ++ ++ /* make sure data is start at 4 bytes aligned addr. */ ++ offset = roundup(sizeof(struct sip_hdr), 4); ++ ++#ifdef HOST_RC ++ esp_sip_dbg(ESP_DBG_TRACE, "%s offset0 %d \n", __func__, ++ offset); ++ memcpy(sip->tx_aggr_write_ptr + offset, ++ (void *) &itx_info->control, ++ sizeof(struct sip_tx_rc)); ++ ++ offset += roundup(sizeof(struct sip_tx_rc), 4); ++ esp_show_tx_rates(&itx_info->control.rates[0]); ++ ++#endif /* HOST_RC */ ++ ++ if (SIP_HDR_IS_AMPDU(shdr)) { ++ memset(sip->tx_aggr_write_ptr + offset, 0, ++ sizeof(struct esp_tx_ampdu_entry)); ++ offset += ++ roundup(sizeof(struct esp_tx_ampdu_entry), 4); ++ } ++ ++ tx_len = offset + skb->len; ++ shdr->len = tx_len; /* actual len */ ++ ++ esp_sip_dbg(ESP_DBG_TRACE, ++ "%s offset %d skblen %d txlen %d\n", __func__, ++ offset, skb->len, tx_len); ++ ++ } ++ ++ shdr->seq = sip->txseq++; ++ //esp_sip_dbg(ESP_DBG_ERROR, "%s seq %u, %u %u\n", __func__, shdr->seq, SIP_HDR_GET_TYPE(shdr->fc[0]),shdr->c_cmdid); ++ ++ /* copy skb to aggr buf */ ++ memcpy(sip->tx_aggr_write_ptr + offset, skb->data, skb->len); ++ ++ if (is_data) { ++ spin_lock_bh(&sip->epub->tx_lock); ++ sip->txdataseq = shdr->seq; ++ spin_unlock_bh(&sip->epub->tx_lock); ++ /* fake a tx_status and report to mac80211 stack to speed up tx, may affect ++ * 1) rate control (now it's all in target, so should be OK) ++ * 2) ps mode, mac80211 want to check ACK of ps/nulldata to see if AP is awake ++ * 3) BAR, mac80211 do BAR by checking ACK ++ */ ++ /* ++ * XXX: need to adjust for 11n, e.g. report tx_status according to BA received in target ++ * ++ */ ++ sip_tx_status_report(sip, skb, itx_info, true); ++ atomic_dec(&sip->tx_data_pkt_queued); ++ ++ STRACE_TX_DATA_INC(); ++ } else { ++ /* check pm state here */ ++ ++ /* no need to hold ctrl skb */ ++ sip_free_ctrl_skbuff(sip, skb); ++ STRACE_TX_CMD_INC(); ++ } ++ ++ /* TBD: roundup here or whole aggr-buf */ ++ tx_len = roundup(tx_len, sip->tx_blksz); ++ ++ sip->tx_aggr_write_ptr += tx_len; ++ sip->tx_tot_len += tx_len; ++ ++ return 0; ++} ++ ++#ifdef HOST_RC ++static void sip_set_tx_rate_status(struct sip_rc_status *rcstatus, ++ struct ieee80211_tx_rate *irates) ++{ ++ int i; ++ u8 shift = 0; ++ u32 cnt = 0; ++ ++ for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { ++ if (rcstatus->rc_map & BIT(i)) { ++ shift = i << 2; ++ cnt = ++ (rcstatus-> ++ rc_cnt_store >> shift) & RC_CNT_MASK; ++ irates[i].idx = i; ++ irates[i].count = (u8) cnt; ++ } else { ++ irates[i].idx = -1; ++ irates[i].count = 0; ++ } ++ } ++ ++ esp_show_rcstatus(rcstatus); ++ esp_show_tx_rates(irates); ++} ++#endif /* HOST_RC */ ++ ++static void sip_tx_status_report(struct esp_sip *sip, struct sk_buff *skb, ++ struct ieee80211_tx_info *tx_info, ++ bool success) ++{ ++ if (!(tx_info->flags & IEEE80211_TX_CTL_AMPDU)) { ++ if (likely(success)) ++ tx_info->flags |= IEEE80211_TX_STAT_ACK; ++ else ++ tx_info->flags &= ~IEEE80211_TX_STAT_ACK; ++ ++ /* manipulate rate status... */ ++ tx_info->status.rates[0].idx = 11; ++ tx_info->status.rates[0].count = 1; ++ tx_info->status.rates[0].flags = 0; ++ tx_info->status.rates[1].idx = -1; ++ ++ } else { ++ tx_info->flags |= ++ IEEE80211_TX_STAT_AMPDU | IEEE80211_TX_STAT_ACK; ++ tx_info->status.ampdu_len = 1; ++ tx_info->status.ampdu_ack_len = 1; ++ ++ /* manipulate rate status... */ ++ tx_info->status.rates[0].idx = 7; ++ tx_info->status.rates[0].count = 1; ++ tx_info->status.rates[0].flags = ++ IEEE80211_TX_RC_MCS | IEEE80211_TX_RC_SHORT_GI; ++ tx_info->status.rates[1].idx = -1; ++ ++ } ++ ++ if (tx_info->flags & IEEE80211_TX_STAT_AMPDU) ++ esp_sip_dbg(ESP_DBG_TRACE, "%s ampdu status! \n", ++ __func__); ++ ++ if (!mod_support_no_txampdu() && ++ cfg80211_get_chandef_type(&sip->epub->hw->conf.chandef) != ++ NL80211_CHAN_NO_HT) { ++ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); ++ struct ieee80211_hdr *wh = ++ (struct ieee80211_hdr *) skb->data; ++ if (ieee80211_is_data_qos(wh->frame_control)) { ++ if (!(tx_info->flags & IEEE80211_TX_CTL_AMPDU)) { ++ u8 tidno = ++ ieee80211_get_qos_ctl(wh)[0] & ++ IEEE80211_QOS_CTL_TID_MASK; ++ struct esp_node *node; ++ struct esp_tx_tid *tid; ++ struct ieee80211_sta *sta; ++ ++ node = ++ esp_get_node_by_addr(sip->epub, ++ wh->addr1); ++ if (node == NULL) ++ goto _exit; ++ if (node->sta == NULL) ++ goto _exit; ++ sta = node->sta; ++ tid = &node->tid[tidno]; ++ spin_lock_bh(&sip->epub->tx_ampdu_lock); ++ //start session ++ if (tid == NULL) { ++ spin_unlock_bh(&sip->epub-> ++ tx_ampdu_lock); ++ ESSERT(0); ++ goto _exit; ++ } ++ if ((tid->state == ESP_TID_STATE_INIT) && ++ (TID_TO_AC(tidno) != WME_AC_VO) ++ && tid->cnt >= 10) { ++ tid->state = ESP_TID_STATE_TRIGGER; ++ esp_sip_dbg(ESP_DBG_ERROR, ++ "start tx ba session,addr:%pM,tid:%u\n", ++ wh->addr1, tidno); ++ spin_unlock_bh(&sip->epub-> ++ tx_ampdu_lock); ++ ieee80211_start_tx_ba_session(sta, ++ tidno, ++ 0); ++ } else { ++ if (tid->state == ++ ESP_TID_STATE_INIT) ++ tid->cnt++; ++ else ++ tid->cnt = 0; ++ spin_unlock_bh(&sip->epub-> ++ tx_ampdu_lock); ++ } ++ } ++ } ++ } ++ _exit: ++ ieee80211_tx_status_skb(sip->epub->hw, skb); ++} ++ ++/* ++ * NB: this routine should be locked when calling ++ */ ++void sip_txq_process(struct esp_pub *epub) ++{ ++ struct sk_buff *skb; ++ struct esp_sip *sip = epub->sip; ++ u32 pkt_len = 0, tx_len = 0; ++ int blknum = 0; ++ bool queued_back = false; ++ bool out_of_credits = false; ++ struct ieee80211_tx_info *itx_info; ++ int pm_state = 0; ++ ++ while ((skb = skb_dequeue(&epub->txq))) { ++ ++ /* cmd skb->len does not include sip_hdr too */ ++ pkt_len = skb->len; ++ itx_info = IEEE80211_SKB_CB(skb); ++ if (itx_info->flags != 0xffffffff) { ++ pkt_len += roundup(sizeof(struct sip_hdr), 4); ++ if ((itx_info->flags & IEEE80211_TX_CTL_AMPDU) ++ && (true || esp_is_ip_pkt(skb))) ++ pkt_len += ++ roundup(sizeof ++ (struct esp_tx_ampdu_entry), ++ 4); ++ } ++ ++ /* current design simply requires every sip_hdr must be at the begin of mblk, that definitely ++ * need to be optimized, e.g. calulate remain length in the previous mblk, if it larger than ++ * certain threshold (e.g, whole pkt or > 50% of pkt or 2 x sizeof(struct sip_hdr), append pkt ++ * to the previous mblk. This might be done in sip_pack_pkt() ++ */ ++ pkt_len = roundup(pkt_len, sip->tx_blksz); ++ blknum = pkt_len / sip->tx_blksz; ++ esp_dbg(ESP_DBG_TRACE, ++ "%s skb_len %d pkt_len %d blknum %d\n", __func__, ++ skb->len, pkt_len, blknum); ++ ++ if (unlikely(atomic_read(&sip->credit_status) == RECALC_CREDIT_ENABLE)) { /* need recalc credit */ ++ struct sip_hdr *hdr = (struct sip_hdr *) skb->data; ++ itx_info = IEEE80211_SKB_CB(skb); ++ if (!(itx_info->flags == 0xffffffff && SIP_HDR_GET_TYPE(hdr->fc[0]) == SIP_CTRL && hdr->c_cmdid == SIP_CMD_RECALC_CREDIT && blknum <= atomic_read(&sip->tx_credits) - sip->credit_to_reserve)) { /* except cmd recalc credit */ ++ esp_dbg(ESP_DBG_ERROR, ++ "%s recalc credits!\n", __func__); ++ STRACE_TX_OUT_OF_CREDIT_INC(); ++ queued_back = true; ++ out_of_credits = true; ++ break; ++ } ++ } else { /* normal situation */ ++ if (unlikely ++ (blknum > ++ (atomic_read(&sip->tx_credits) - ++ sip->credit_to_reserve - ++ SIP_CTRL_CREDIT_RESERVE))) { ++ itx_info = IEEE80211_SKB_CB(skb); ++ if (itx_info->flags == 0xffffffff) { /* priv ctrl pkt */ ++ if (blknum > ++ atomic_read(&sip->tx_credits) - ++ sip->credit_to_reserve) { ++ esp_dbg(ESP_DBG_TRACE, ++ "%s cmd pkt out of credits!\n", ++ __func__); ++ STRACE_TX_OUT_OF_CREDIT_INC ++ (); ++ queued_back = true; ++ out_of_credits = true; ++ break; ++ } ++ } else { ++ esp_dbg(ESP_DBG_TRACE, ++ "%s out of credits!\n", ++ __func__); ++ STRACE_TX_OUT_OF_CREDIT_INC(); ++ queued_back = true; ++ out_of_credits = true; ++ break; ++ } ++ } ++ } ++ tx_len += pkt_len; ++ if (tx_len >= SIP_TX_AGGR_BUF_SIZE) { ++ /* do we need to have limitation likemax 8 pkts in a row? */ ++ esp_dbg(ESP_DBG_TRACE, ++ "%s too much pkts in one shot!\n", ++ __func__); ++ STRACE_TX_ONE_SHOT_INC(); ++ tx_len -= pkt_len; ++ queued_back = true; ++ break; ++ } ++ ++ if (sip_pack_pkt(sip, skb, &pm_state) != 0) { ++ /* wrong pkt, won't send to target */ ++ tx_len -= pkt_len; ++ continue; ++ } ++ ++ esp_sip_dbg(ESP_DBG_TRACE, ++ "%s:before sub, credits is %d\n", __func__, ++ atomic_read(&sip->tx_credits)); ++ atomic_sub(blknum, &sip->tx_credits); ++ esp_sip_dbg(ESP_DBG_TRACE, ++ "%s:after sub %d,credits remains %d\n", ++ __func__, blknum, ++ atomic_read(&sip->tx_credits)); ++ ++ } ++ ++ if (queued_back) { ++ skb_queue_head(&epub->txq, skb); ++ } ++ ++ if (atomic_read(&sip->state) == SIP_STOP ++#ifdef HOST_RESET_BUG ++ || atomic_read(&epub->wl.off) == 1 ++#endif ++ ) { ++ queued_back = 1; ++ tx_len = 0; ++ sip_after_write_pkts(sip); ++ } ++ ++ if (tx_len) { ++ ++ sip_write_pkts(sip, pm_state); ++ ++ sip_after_write_pkts(sip); ++ } ++ ++ if (queued_back && !out_of_credits) { ++ ++ /* skb pending, do async process again */ ++ sip_trigger_txq_process(sip); ++ } ++} ++ ++static void sip_after_write_pkts(struct esp_sip *sip) ++{ ++ ++} ++ ++#ifndef NO_WMM_DUMMY ++static struct esp_80211_wmm_param_element esp_wmm_param = { ++ .oui = {0x00, 0x50, 0xf2}, ++ .oui_type = 0x02, ++ .oui_subtype = 0x01, ++ .version = 0x01, ++ .qos_info = 0x00, ++ .reserved = 0x00, ++ .ac = { ++ { ++ .aci_aifsn = 0x03, ++ .cw = 0xa4, ++ .txop_limit = 0x0000, ++ }, ++ { ++ .aci_aifsn = 0x27, ++ .cw = 0xa4, ++ .txop_limit = 0x0000, ++ }, ++ { ++ .aci_aifsn = 0x42, ++ .cw = 0x43, ++ .txop_limit = 0x005e, ++ }, ++ { ++ .aci_aifsn = 0x62, ++ .cw = 0x32, ++ .txop_limit = 0x002f, ++ }, ++ }, ++}; ++ ++static int esp_add_wmm(struct sk_buff *skb) ++{ ++ u8 *p; ++ int flag = 0; ++ int remain_len; ++ int base_len; ++ int len; ++ struct ieee80211_mgmt *mgmt; ++ struct ieee80211_hdr *wh; ++ ++ if (!skb) ++ return -1; ++ ++ wh = (struct ieee80211_hdr *) skb->data; ++ mgmt = (struct ieee80211_mgmt *) ((u8 *) skb->data); ++ ++ if (ieee80211_is_assoc_resp(wh->frame_control)) { ++ p = mgmt->u.assoc_resp.variable; ++ base_len = ++ (u8 *) mgmt->u.assoc_resp.variable - (u8 *) mgmt; ++ } else if (ieee80211_is_reassoc_resp(wh->frame_control)) { ++ p = mgmt->u.reassoc_resp.variable; ++ base_len = ++ (u8 *) mgmt->u.reassoc_resp.variable - (u8 *) mgmt; ++ } else if (ieee80211_is_probe_resp(wh->frame_control)) { ++ p = mgmt->u.probe_resp.variable; ++ base_len = ++ (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; ++ } else if (ieee80211_is_beacon(wh->frame_control)) { ++ p = mgmt->u.beacon.variable; ++ base_len = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt; ++ } else ++ return 1; ++ ++ ++ remain_len = skb->len - base_len; ++ ++ while (remain_len > 0) { ++ if (*p == 0xdd && *(p + 5) == 0x02) //wmm type ++ return 0; ++ else if (*p == 0x2d) //has ht cap ++ flag = 1; ++ ++ len = *(++p); ++ p += (len + 1); ++ remain_len -= (len + 2); ++ } ++ ++ if (remain_len < 0) { ++ esp_dbg(ESP_DBG_TRACE, ++ "%s remain_len %d, skb->len %d, base_len %d, flag %d", ++ __func__, remain_len, skb->len, base_len, flag); ++ return -2; ++ } ++ ++ if (flag == 1) { ++ skb_put(skb, 2 + sizeof(esp_wmm_param)); ++ ++ memset(p, 0xdd, sizeof(u8)); ++ memset(p + 1, sizeof(esp_wmm_param), sizeof(u8)); ++ memcpy(p + 2, &esp_wmm_param, sizeof(esp_wmm_param)); ++ ++ esp_dbg(ESP_DBG_TRACE, "esp_wmm_param"); ++ } ++ ++ return 0; ++} ++#endif /* NO_WMM_DUMMY */ ++ ++/* parse mac_rx_ctrl and return length */ ++static int sip_parse_mac_rx_info(struct esp_sip *sip, ++ struct esp_mac_rx_ctrl *mac_ctrl, ++ struct sk_buff *skb) ++{ ++ struct ieee80211_rx_status *rx_status = NULL; ++ struct ieee80211_hdr *hdr; ++ ++ rx_status = IEEE80211_SKB_RXCB(skb); ++ rx_status->freq = esp_ieee2mhz(mac_ctrl->channel); ++ ++ rx_status->signal = mac_ctrl->rssi + mac_ctrl->noise_floor; /* snr actually, need to offset noise floor e.g. -85 */ ++ ++ hdr = (struct ieee80211_hdr *) skb->data; ++ if (mac_ctrl->damatch0 == 1 && mac_ctrl->bssidmatch0 == 1 /*match bssid and da, but beacon package contain other bssid */ ++ && strncmp(hdr->addr2, sip->epub->wl.bssid, ETH_ALEN) == 0) { /* force match addr2 */ ++ if (++signal_loop >= SIGNAL_COUNT) { ++ avg_signal += rx_status->signal; ++ avg_signal /= SIGNAL_COUNT; ++ old_signal = rx_status->signal = (avg_signal + 5); ++ signal_loop = 0; ++ avg_signal = 0; ++ } else { ++ avg_signal += rx_status->signal; ++ rx_status->signal = old_signal; ++ } ++ } ++ ++ rx_status->antenna = 0; /* one antenna for now */ ++ rx_status->band = NL80211_BAND_2GHZ; ++ rx_status->flag = RX_FLAG_DECRYPTED | RX_FLAG_MMIC_STRIPPED; ++ if (mac_ctrl->sig_mode) { ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) ++ rx_status->encoding = RX_ENC_HT; ++#else ++ rx_status->flag |= RX_FLAG_HT; ++#endif ++ rx_status->rate_idx = mac_ctrl->MCS; ++ if (mac_ctrl->SGI) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) ++ rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI; ++#else ++ rx_status->flag |= RX_FLAG_SHORT_GI; ++#endif ++ } else { ++ rx_status->rate_idx = esp_wmac_rate2idx(mac_ctrl->rate); ++ } ++ if (mac_ctrl->rxend_state == RX_FCS_ERR) ++ rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; ++ ++ /* Mic error frame flag */ ++ if (mac_ctrl->rxend_state == RX_TKIPMIC_ERR ++ || mac_ctrl->rxend_state == RX_CCMPMIC_ERR) { ++ if (atomic_read(&sip->epub->wl.tkip_key_set) == 1) { ++ rx_status->flag |= RX_FLAG_MMIC_ERROR; ++ atomic_set(&sip->epub->wl.tkip_key_set, 0); ++ printk("mic err\n"); ++ } else { ++ printk("mic err discard\n"); ++ } ++ } ++ //esp_dbg(ESP_DBG_LOG, "%s freq: %u; signal: %d; rate_idx %d; flag: %d \n", __func__, rx_status->freq, rx_status->signal, rx_status->rate_idx, rx_status->flag); ++ ++ do { ++ struct ieee80211_hdr *wh = ++ (struct ieee80211_hdr *) ((u8 *) skb->data); ++ ++#ifndef NO_WMM_DUMMY ++ if (ieee80211_is_mgmt(wh->frame_control)) ++ esp_add_wmm(skb); ++#endif ++ ++ /* some kernel e.g. 3.0.8 wrongly handles non-encrypted pkt like eapol */ ++ if (ieee80211_is_data(wh->frame_control)) { ++ if (!ieee80211_has_protected(wh->frame_control)) { ++ esp_sip_dbg(ESP_DBG_TRACE, ++ "%s kiv_war, add iv_stripped flag \n", ++ __func__); ++ rx_status->flag |= RX_FLAG_IV_STRIPPED; ++ } else { ++ if ((atomic_read(&sip->epub->wl.ptk_cnt) == ++ 0 && !(wh->addr1[0] & 0x1)) ++ || (atomic_read(&sip->epub->wl.gtk_cnt) ++ == 0 && (wh->addr1[0] & 0x1))) { ++ esp_dbg(ESP_DBG_TRACE, ++ "%s ==kiv_war, got bogus enc pkt==\n", ++ __func__); ++ rx_status->flag |= ++ RX_FLAG_IV_STRIPPED; ++ //show_buf(skb->data, 32); ++ } ++ ++ esp_sip_dbg(ESP_DBG_TRACE, ++ "%s kiv_war, got enc pkt \n", ++ __func__); ++ } ++ } ++ } while (0); ++ ++ return 0; ++} ++ ++static struct esp_mac_rx_ctrl *sip_parse_normal_mac_ctrl(struct sk_buff ++ *skb, ++ int *pkt_len_enc, ++ int *buf_len, ++ int *pulled_len) ++{ ++ struct esp_mac_rx_ctrl *mac_ctrl = NULL; ++ struct sip_hdr *hdr = (struct sip_hdr *) skb->data; ++ int len_in_hdr = hdr->len; ++ ++ ESSERT(skb != NULL); ++ ESSERT(skb->len > SIP_MIN_DATA_PKT_LEN); ++ ++ skb_pull(skb, sizeof(struct sip_hdr)); ++ *pulled_len += sizeof(struct sip_hdr); ++ mac_ctrl = (struct esp_mac_rx_ctrl *) skb->data; ++ if (!mac_ctrl->Aggregation) { ++ ESSERT(pkt_len_enc != NULL); ++ ESSERT(buf_len != NULL); ++ *pkt_len_enc = ++ (mac_ctrl->sig_mode ? mac_ctrl->HT_length : mac_ctrl-> ++ legacy_length) - FCS_LEN; ++ *buf_len = ++ len_in_hdr - sizeof(struct sip_hdr) - ++ sizeof(struct esp_mac_rx_ctrl); ++ } ++ skb_pull(skb, sizeof(struct esp_mac_rx_ctrl)); ++ *pulled_len += sizeof(struct esp_mac_rx_ctrl); ++ ++ return mac_ctrl; ++} ++ ++/* ++ * for one MPDU (including subframe in AMPDU) ++ * ++ */ ++static struct sk_buff *sip_parse_data_rx_info(struct esp_sip *sip, ++ struct sk_buff *skb, ++ int pkt_len_enc, int buf_len, ++ struct esp_mac_rx_ctrl ++ *mac_ctrl, int *pulled_len) ++{ ++ /* ++ * | mac_rx_ctrl | real_data_payload | ampdu_entries | ++ */ ++ //without enc ++ int pkt_len = 0; ++ struct sk_buff *rskb = NULL; ++ int ret; ++ ++ if (mac_ctrl->Aggregation) { ++ struct ieee80211_hdr *wh = ++ (struct ieee80211_hdr *) skb->data; ++ pkt_len = pkt_len_enc; ++ if (ieee80211_has_protected(wh->frame_control)) //ampdu, it is CCMP enc ++ pkt_len -= 8; ++ buf_len = roundup(pkt_len, 4); ++ } else ++ pkt_len = buf_len - 3 + ((pkt_len_enc - 1) & 0x3); ++ esp_dbg(ESP_DBG_TRACE, ++ "%s pkt_len %u, pkt_len_enc %u!, delta %d \n", __func__, ++ pkt_len, pkt_len_enc, pkt_len_enc - pkt_len); ++ do { ++#ifndef NO_WMM_DUMMY ++ rskb = ++ __dev_alloc_skb(pkt_len_enc + sizeof(esp_wmm_param) + ++ 2, GFP_ATOMIC); ++#else ++ rskb = __dev_alloc_skb(pkt_len_enc, GFP_ATOMIC); ++#endif /* NO_WMM_DUMMY */ ++ if (unlikely(rskb == NULL)) { ++ esp_sip_dbg(ESP_DBG_ERROR, "%s no mem for rskb\n", ++ __func__); ++ return NULL; ++ } ++ skb_put(rskb, pkt_len_enc); ++ } while (0); ++ ++ do { ++ memcpy(rskb->data, skb->data, pkt_len); ++ if (pkt_len_enc > pkt_len) { ++ memset(rskb->data + pkt_len, 0, ++ pkt_len_enc - pkt_len); ++ } ++ /* strip out current pkt, move to the next one */ ++ skb_pull(skb, buf_len); ++ *pulled_len += buf_len; ++ } while (0); ++ ++ ret = sip_parse_mac_rx_info(sip, mac_ctrl, rskb); ++ if (ret == -1 && !mac_ctrl->Aggregation) { ++ kfree_skb(rskb); ++ return NULL; ++ } ++ ++ esp_dbg(ESP_DBG_LOG, ++ "%s after pull headers, skb->len %d rskb->len %d \n", ++ __func__, skb->len, rskb->len); ++ ++ return rskb; ++} ++ ++struct esp_sip *sip_attach(struct esp_pub *epub) ++{ ++ struct esp_sip *sip = NULL; ++ struct sip_pkt *pkt = NULL; ++ int i; ++#ifndef ESP_PREALLOC ++ int po = 0; ++#endif ++ ++ sip = kzalloc(sizeof(struct esp_sip), GFP_KERNEL); ++ if (sip == NULL) { ++ esp_dbg(ESP_DBG_ERROR, "no mem for sip! \n"); ++ goto _err_sip; ++ } ++#ifdef ESP_PREALLOC ++ sip->tx_aggr_buf = (u8 *) esp_get_tx_aggr_buf(); ++#else ++ po = get_order(SIP_TX_AGGR_BUF_SIZE); ++ sip->tx_aggr_buf = (u8 *) __get_free_pages(GFP_ATOMIC, po); ++#endif ++ if (sip->tx_aggr_buf == NULL) { ++ esp_dbg(ESP_DBG_ERROR, "no mem for tx_aggr_buf! \n"); ++ goto _err_aggr; ++ } ++ ++ spin_lock_init(&sip->lock); ++ ++ INIT_LIST_HEAD(&sip->free_ctrl_txbuf); ++ INIT_LIST_HEAD(&sip->free_ctrl_rxbuf); ++ ++ for (i = 0; i < SIP_CTRL_BUF_N; i++) { ++ pkt = kzalloc(sizeof(struct sip_pkt), GFP_KERNEL); ++ ++ if (!pkt) ++ goto _err_pkt; ++ ++ pkt->buf_begin = kzalloc(SIP_CTRL_BUF_SZ, GFP_KERNEL); ++ ++ if (pkt->buf_begin == NULL) { ++ kfree(pkt); ++ pkt = NULL; ++ goto _err_pkt; ++ } ++ ++ pkt->buf_len = SIP_CTRL_BUF_SZ; ++ pkt->buf = pkt->buf_begin; ++ ++ if (i < SIP_CTRL_TXBUF_N) { ++ list_add_tail(&pkt->list, &sip->free_ctrl_txbuf); ++ } else { ++ list_add_tail(&pkt->list, &sip->free_ctrl_rxbuf); ++ } ++ } ++ ++ mutex_init(&sip->rx_mtx); ++ skb_queue_head_init(&sip->rxq); ++ INIT_WORK(&sip->rx_process_work, sip_rxq_process); ++ ++ sip->epub = epub; ++ atomic_set(&sip->noise_floor, -96); ++ ++ atomic_set(&sip->state, SIP_INIT); ++ atomic_set(&sip->tx_credits, 0); ++ ++ if (sip->rawbuf == NULL) { ++ sip->rawbuf = kzalloc(SIP_BOOT_BUF_SIZE, GFP_KERNEL); ++ if (sip->rawbuf == NULL) { ++ esp_dbg(ESP_DBG_ERROR, "no mem for rawbuf! \n"); ++ goto _err_pkt; ++ } ++ } ++ ++ atomic_set(&sip->state, SIP_PREPARE_BOOT); ++ ++ return sip; ++ ++ _err_pkt: ++ sip_free_init_ctrl_buf(sip); ++ ++ if (sip->tx_aggr_buf) { ++#ifdef ESP_PREALLOC ++ esp_put_tx_aggr_buf(&sip->tx_aggr_buf); ++#else ++ po = get_order(SIP_TX_AGGR_BUF_SIZE); ++ free_pages((unsigned long) sip->tx_aggr_buf, po); ++ sip->tx_aggr_buf = NULL; ++#endif ++ } ++ _err_aggr: ++ if (sip) { ++ kfree(sip); ++ sip = NULL; ++ } ++ _err_sip: ++ return NULL; ++ ++} ++ ++static void sip_free_init_ctrl_buf(struct esp_sip *sip) ++{ ++ struct sip_pkt *pkt, *tpkt; ++ ++ list_for_each_entry_safe(pkt, tpkt, &sip->free_ctrl_txbuf, list) { ++ list_del(&pkt->list); ++ kfree(pkt->buf_begin); ++ kfree(pkt); ++ } ++ ++ list_for_each_entry_safe(pkt, tpkt, &sip->free_ctrl_rxbuf, list) { ++ list_del(&pkt->list); ++ kfree(pkt->buf_begin); ++ kfree(pkt); ++ } ++} ++ ++void sip_detach(struct esp_sip *sip) ++{ ++#ifndef ESP_PREALLOC ++ int po; ++#endif ++ if (sip == NULL) ++ return; ++ ++ esp_dbg(ESP_DBG_TRACE, "sip_detach: sip_free_init_ctrl_buf()"); ++ sip_free_init_ctrl_buf(sip); ++ ++ if (atomic_read(&sip->state) == SIP_RUN) { ++ ++ sif_disable_target_interrupt(sip->epub); ++ ++ atomic_set(&sip->state, SIP_STOP); ++ ++ /* disable irq here */ ++ sif_disable_irq(sip->epub); ++ cancel_work_sync(&sip->rx_process_work); ++ ++ skb_queue_purge(&sip->rxq); ++ mutex_destroy(&sip->rx_mtx); ++ cancel_work(&sip->epub->sendup_work); // Must be non-sync ++ skb_queue_purge(&sip->epub->rxq); ++ ++#ifdef ESP_NO_MAC80211 ++ unregister_netdev(sip->epub->net_dev); ++ wiphy_unregister(sip->epub->wdev->wiphy); ++#else ++ if (test_and_clear_bit ++ (ESP_WL_FLAG_HW_REGISTERED, &sip->epub->wl.flags)) { ++ ieee80211_unregister_hw(sip->epub->hw); ++ } ++#endif ++ ++ /* cancel all worker/timer */ ++ cancel_work_sync(&sip->epub->tx_work); ++ skb_queue_purge(&sip->epub->txq); ++ skb_queue_purge(&sip->epub->txdoneq); ++ ++#ifdef ESP_PREALLOC ++ esp_put_tx_aggr_buf(&sip->tx_aggr_buf); ++#else ++ po = get_order(SIP_TX_AGGR_BUF_SIZE); ++ free_pages((unsigned long) sip->tx_aggr_buf, po); ++ sip->tx_aggr_buf = NULL; ++#endif ++ ++ atomic_set(&sip->state, SIP_INIT); ++ } else if (atomic_read(&sip->state) >= SIP_BOOT ++ && atomic_read(&sip->state) <= SIP_WAIT_BOOTUP) { ++ ++ sif_disable_target_interrupt(sip->epub); ++ atomic_set(&sip->state, SIP_STOP); ++ ++ sif_disable_irq(sip->epub); ++ ++ if (sip->rawbuf) ++ kfree(sip->rawbuf); ++ ++ if (atomic_read(&sip->state) == SIP_SEND_INIT) { ++ cancel_work_sync(&sip->rx_process_work); ++ skb_queue_purge(&sip->rxq); ++ mutex_destroy(&sip->rx_mtx); ++ cancel_work_sync(&sip->epub->sendup_work); ++ skb_queue_purge(&sip->epub->rxq); ++ } ++#ifdef ESP_NO_MAC80211 ++ unregister_netdev(sip->epub->net_dev); ++ wiphy_unregister(sip->epub->wdev->wiphy); ++#else ++ if (test_and_clear_bit ++ (ESP_WL_FLAG_HW_REGISTERED, &sip->epub->wl.flags)) { ++ ieee80211_unregister_hw(sip->epub->hw); ++ } ++#endif ++ atomic_set(&sip->state, SIP_INIT); ++ } else ++ esp_dbg(ESP_DBG_ERROR, "%s wrong state %d\n", __func__, ++ atomic_read(&sip->state)); ++ ++ kfree(sip); ++} ++ ++int sip_write_memory(struct esp_sip *sip, u32 addr, u8 * buf, u16 len) ++{ ++ struct sip_cmd_write_memory *cmd; ++ struct sip_hdr *chdr; ++ u16 remains, hdrs, bufsize; ++ u32 loadaddr; ++ u8 *src; ++ int err = 0; ++ u32 *t = NULL; ++ ++ if (sip == NULL || sip->rawbuf == NULL) { ++ ESSERT(sip != NULL); ++ ESSERT(sip->rawbuf != NULL); ++ return -EINVAL; ++ } ++ ++ memset(sip->rawbuf, 0, SIP_BOOT_BUF_SIZE); ++ ++ chdr = (struct sip_hdr *) sip->rawbuf; ++ SIP_HDR_SET_TYPE(chdr->fc[0], SIP_CTRL); ++ chdr->c_cmdid = SIP_CMD_WRITE_MEMORY; ++ ++ remains = len; ++ hdrs = ++ sizeof(struct sip_hdr) + sizeof(struct sip_cmd_write_memory); ++ ++ while (remains) { ++ src = &buf[len - remains]; ++ loadaddr = addr + (len - remains); ++ ++ if (remains < (SIP_BOOT_BUF_SIZE - hdrs)) { ++ /* aligned with 4 bytes */ ++ bufsize = roundup(remains, 4); ++ memset(sip->rawbuf + hdrs, 0, bufsize); ++ remains = 0; ++ } else { ++ bufsize = SIP_BOOT_BUF_SIZE - hdrs; ++ remains -= bufsize; ++ } ++ ++ chdr->len = bufsize + hdrs; ++ chdr->seq = sip->txseq++; ++ cmd = ++ (struct sip_cmd_write_memory *) (sip->rawbuf + ++ SIP_CTRL_HDR_LEN); ++ cmd->len = bufsize; ++ cmd->addr = loadaddr; ++ memcpy(sip->rawbuf + hdrs, src, bufsize); ++ ++ t = (u32 *) sip->rawbuf; ++ esp_dbg(ESP_DBG_TRACE, ++ "%s t0: 0x%08x t1: 0x%08x t2:0x%08x loadaddr 0x%08x \n", ++ __func__, t[0], t[1], t[2], loadaddr); ++ ++ err = ++ esp_common_write(sip->epub, sip->rawbuf, chdr->len, ++ ESP_SIF_SYNC); ++ ++ if (err) { ++ esp_dbg(ESP_DBG_ERROR, "%s send buffer failed\n", ++ __func__); ++ return err; ++ } ++ // 1ms is enough, in fact on dell-d430, need not delay at all. ++ mdelay(1); ++ ++ } ++ ++ return err; ++} ++ ++int sip_send_cmd(struct esp_sip *sip, int cid, u32 cmdlen, void *cmd) ++{ ++ struct sip_hdr *chdr; ++ struct sip_pkt *pkt = NULL; ++ int ret = 0; ++ ++ pkt = sip_get_ctrl_buf(sip, SIP_TX_CTRL_BUF); ++ ++ if (pkt == NULL) ++ return -ENOMEM; ++ ++ chdr = (struct sip_hdr *) pkt->buf_begin; ++ chdr->len = SIP_CTRL_HDR_LEN + cmdlen; ++ chdr->seq = sip->txseq++; ++ chdr->c_cmdid = cid; ++ ++ ++ if (cmd) { ++ memset(pkt->buf, 0, cmdlen); ++ memcpy(pkt->buf, (u8 *) cmd, cmdlen); ++ } ++ ++ esp_dbg(ESP_DBG_TRACE, "cid %d, len %u, seq %u \n", chdr->c_cmdid, ++ chdr->len, chdr->seq); ++ ++ esp_dbg(ESP_DBG_TRACE, "c1 0x%08x c2 0x%08x\n", ++ *(u32 *) & pkt->buf[0], *(u32 *) & pkt->buf[4]); ++ ++ ret = ++ esp_common_write(sip->epub, pkt->buf_begin, chdr->len, ++ ESP_SIF_SYNC); ++ ++ if (ret) ++ esp_dbg(ESP_DBG_ERROR, "%s send cmd %d failed \n", ++ __func__, cid); ++ ++ sip_reclaim_ctrl_buf(sip, pkt, SIP_TX_CTRL_BUF); ++ ++ /* ++ * Hack here: reset tx/rx seq before target ram code is up... ++ */ ++ if (cid == SIP_CMD_BOOTUP) { ++ sip->rxseq = 0; ++ sip->txseq = 0; ++ sip->txdataseq = 0; ++ } ++ ++ return ret; ++} ++ ++struct sk_buff *sip_alloc_ctrl_skbuf(struct esp_sip *sip, u16 len, u32 cid) ++{ ++ struct sip_hdr *si = NULL; ++ struct ieee80211_tx_info *ti = NULL; ++ struct sk_buff *skb = NULL; ++ ++ ESSERT(len <= sip->tx_blksz); ++ ++ /* no need to reserve space for net stack */ ++ skb = __dev_alloc_skb(len, GFP_KERNEL); ++ ++ if (skb == NULL) { ++ esp_dbg(ESP_DBG_ERROR, "no skb for ctrl !\n"); ++ return NULL; ++ } ++ ++ skb->len = len; ++ ++ ti = IEEE80211_SKB_CB(skb); ++ /* set tx_info flags to 0xffffffff to indicate sip_ctrl pkt */ ++ ti->flags = 0xffffffff; ++ si = (struct sip_hdr *) skb->data; ++ memset(si, 0, sizeof(struct sip_hdr)); ++ SIP_HDR_SET_TYPE(si->fc[0], SIP_CTRL); ++ si->len = len; ++ si->c_cmdid = cid; ++ ++ return skb; ++} ++ ++void sip_free_ctrl_skbuff(struct esp_sip *sip, struct sk_buff *skb) ++{ ++ memset(IEEE80211_SKB_CB(skb), 0, sizeof(struct ieee80211_tx_info)); ++ kfree_skb(skb); ++} ++ ++static struct sip_pkt *sip_get_ctrl_buf(struct esp_sip *sip, ++ SIP_BUF_TYPE bftype) ++{ ++ struct sip_pkt *pkt = NULL; ++ struct list_head *bflist; ++ struct sip_hdr *chdr; ++ ++ bflist = ++ (bftype == ++ SIP_TX_CTRL_BUF) ? &sip->free_ctrl_txbuf : &sip-> ++ free_ctrl_rxbuf; ++ ++ spin_lock_bh(&sip->lock); ++ ++ if (list_empty(bflist)) { ++ spin_unlock_bh(&sip->lock); ++ return NULL; ++ } ++ ++ pkt = list_first_entry(bflist, struct sip_pkt, list); ++ list_del(&pkt->list); ++ spin_unlock_bh(&sip->lock); ++ ++ if (bftype == SIP_TX_CTRL_BUF) { ++ chdr = (struct sip_hdr *) pkt->buf_begin; ++ SIP_HDR_SET_TYPE(chdr->fc[0], SIP_CTRL); ++ pkt->buf = pkt->buf_begin + SIP_CTRL_HDR_LEN; ++ } else { ++ pkt->buf = pkt->buf_begin; ++ } ++ ++ return pkt; ++} ++ ++static void ++sip_reclaim_ctrl_buf(struct esp_sip *sip, struct sip_pkt *pkt, ++ SIP_BUF_TYPE bftype) ++{ ++ struct list_head *bflist = NULL; ++ ++ if (bftype == SIP_TX_CTRL_BUF) ++ bflist = &sip->free_ctrl_txbuf; ++ else if (bftype == SIP_RX_CTRL_BUF) ++ bflist = &sip->free_ctrl_rxbuf; ++ else ++ return; ++ ++ pkt->buf = pkt->buf_begin; ++ ++ spin_lock_bh(&sip->lock); ++ list_add_tail(&pkt->list, bflist); ++ spin_unlock_bh(&sip->lock); ++} ++ ++int sip_poll_bootup_event(struct esp_sip *sip) ++{ ++ int ret = 0; ++ ++ esp_dbg(ESP_DBG_TRACE, "polling bootup event... \n"); ++ ++ if (gl_bootup_cplx) ++ ret = wait_for_completion_timeout(gl_bootup_cplx, 2 * HZ); ++ ++ esp_dbg(ESP_DBG_TRACE, "******time remain****** = [%d]\n", ret); ++ if (ret <= 0) { ++ esp_dbg(ESP_DBG_ERROR, "bootup event timeout\n"); ++ return -ETIMEDOUT; ++ } ++ ++ if (sif_get_ate_config() == 0) { ++ ret = esp_register_mac80211(sip->epub); ++ } ++#ifdef TEST_MODE ++ ret = test_init_netlink(sip); ++ if (ret < 0) { ++ esp_sip_dbg(ESP_DBG_TRACE, ++ "esp_sdio: failed initializing netlink\n"); ++ return ret; ++ } ++#endif ++ ++ atomic_set(&sip->state, SIP_RUN); ++ esp_dbg(ESP_DBG_TRACE, "target booted up\n"); ++ ++ return ret; ++} ++ ++int sip_poll_resetting_event(struct esp_sip *sip) ++{ ++ int ret = 0; ++ ++ esp_dbg(ESP_DBG_TRACE, "polling resetting event... \n"); ++ ++ if (gl_bootup_cplx) ++ ret = wait_for_completion_timeout(gl_bootup_cplx, 10 * HZ); ++ ++ esp_dbg(ESP_DBG_TRACE, "******time remain****** = [%d]\n", ret); ++ if (ret <= 0) { ++ esp_dbg(ESP_DBG_ERROR, "resetting event timeout\n"); ++ return -ETIMEDOUT; ++ } ++ ++ esp_dbg(ESP_DBG_TRACE, "target resetting %d %p\n", ret, ++ gl_bootup_cplx); ++ ++ return 0; ++} ++ ++ ++#ifdef FPGA_DEBUG ++ ++/* bogus bootup cmd for FPGA debugging */ ++int sip_send_bootup(struct esp_sip *sip) ++{ ++ int ret; ++ struct sip_cmd_bootup bootcmd; ++ ++ esp_dbg(ESP_DBG_LOG, "sending bootup\n"); ++ ++ bootcmd.boot_addr = 0; ++ ret = ++ sip_send_cmd(sip, SIP_CMD_BOOTUP, ++ sizeof(struct sip_cmd_bootup), &bootcmd); ++ ++ return ret; ++} ++ ++#endif /* FPGA_DEBUG */ ++ ++bool sip_queue_need_stop(struct esp_sip * sip) ++{ ++ return atomic_read(&sip->tx_data_pkt_queued) >= ++ SIP_STOP_QUEUE_THRESHOLD || (atomic_read(&sip->tx_credits) < 8 ++ && atomic_read(&sip-> ++ tx_data_pkt_queued) ++ >= ++ SIP_STOP_QUEUE_THRESHOLD / 4 * 3); ++} ++ ++bool sip_queue_may_resume(struct esp_sip * sip) ++{ ++ return atomic_read(&sip->epub->txq_stopped) ++ && !test_bit(ESP_WL_FLAG_STOP_TXQ, &sip->epub->wl.flags) ++ && ((atomic_read(&sip->tx_credits) >= 16 ++ && atomic_read(&sip->tx_data_pkt_queued) < ++ SIP_RESUME_QUEUE_THRESHOLD * 2) ++ || atomic_read(&sip->tx_data_pkt_queued) < ++ SIP_RESUME_QUEUE_THRESHOLD); ++} ++ ++int sip_cmd_enqueue(struct esp_sip *sip, struct sk_buff *skb, int prior) ++{ ++ if (!sip || !sip->epub) { ++ esp_dbg(ESP_DBG_ERROR, "func %s, sip->epub->txq is NULL\n", ++ __func__); ++ return -EINVAL; ++ } ++ ++ if (!skb) { ++ esp_dbg(ESP_DBG_ERROR, "func %s, skb is NULL\n", __func__); ++ return -EINVAL; ++ } ++ ++ if (prior == ENQUEUE_PRIOR_HEAD) ++ skb_queue_head(&sip->epub->txq, skb); ++ else ++ skb_queue_tail(&sip->epub->txq, skb); ++ ++ if (sif_get_ate_config() == 0) { ++ ieee80211_queue_work(sip->epub->hw, &sip->epub->tx_work); ++ } else { ++ queue_work(sip->epub->esp_wkq, &sip->epub->tx_work); ++ } ++ return 0; ++} ++ ++void sip_tx_data_pkt_enqueue(struct esp_pub *epub, struct sk_buff *skb) ++{ ++ if (!epub || !epub->sip) { ++ if (!epub) ++ esp_dbg(ESP_DBG_ERROR, "func %s, epub is NULL\n", ++ __func__); ++ else ++ esp_dbg(ESP_DBG_ERROR, ++ "func %s, epub->sip is NULL\n", __func__); ++ ++ return; ++ } ++ if (!skb) { ++ esp_dbg(ESP_DBG_ERROR, "func %s, skb is NULL\n", __func__); ++ return; ++ } ++ skb_queue_tail(&epub->txq, skb); ++ atomic_inc(&epub->sip->tx_data_pkt_queued); ++ if (sip_queue_need_stop(epub->sip)) { ++ if (epub->hw) { ++ ieee80211_stop_queues(epub->hw); ++ atomic_set(&epub->txq_stopped, true); ++ } ++ ++ } ++} ++ ++#ifdef FPGA_TXDATA ++int sip_send_tx_data(struct esp_sip *sip) ++{ ++ struct sk_buff *skb = NULL; ++ struct sip_cmd_bss_info_update *bsscmd; ++ ++ skb = ++ sip_alloc_ctrl_skbuf(epub->sip, ++ sizeof(struct sip_cmd_bss_info_update), ++ SIP_CMD_BSS_INFO_UPDATE); ++ if (!skb) ++ return -EINVAL; ++ ++ bsscmd = ++ (struct sip_cmd_bss_info_update *) (skb->data + ++ sizeof(struct ++ sip_tx_info)); ++ bsscmd->isassoc = (assoc == true) ? 1 : 0; ++ memcpy(bsscmd->bssid, bssid, ETH_ALEN); ++ STRACE_SHOW(epub->sip); ++ return sip_cmd_enqueue(epub->sip, skb, ENQUEUE_PRIOR_TAIL); ++} ++#endif /* FPGA_TXDATA */ +diff --git a/drivers/net/wireless/esp8089/esp_sip.h b/drivers/net/wireless/esp8089/esp_sip.h +new file mode 100644 +index 000000000000..95cc42989b2c +--- /dev/null ++++ b/drivers/net/wireless/esp8089/esp_sip.h +@@ -0,0 +1,171 @@ ++/* ++ * Copyright (c) 2009- 2014 Espressif System. ++ * ++ * Serial Interconnctor Protocol ++ * ++ * 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 _ESP_SIP_H ++#define _ESP_SIP_H ++ ++#include "sip2_common.h" ++ ++#define SIP_CTRL_CREDIT_RESERVE 2 ++ ++#define SIP_PKT_MAX_LEN (1024*16) ++ ++/* 16KB on normal X86 system, should check before porting to orhters */ ++ ++#define SIP_TX_AGGR_BUF_SIZE (4 * PAGE_SIZE) ++#define SIP_RX_AGGR_BUF_SIZE (4 * PAGE_SIZE) ++ ++struct sk_buff; ++ ++struct sip_pkt { ++ struct list_head list; ++ ++ u8 *buf_begin; ++ u32 buf_len; ++ u8 *buf; ++}; ++ ++typedef enum RECALC_CREDIT_STATE { ++ RECALC_CREDIT_DISABLE = 0, ++ RECALC_CREDIT_ENABLE = 1, ++} RECALC_CREDIT_STATE; ++ ++typedef enum ENQUEUE_PRIOR { ++ ENQUEUE_PRIOR_TAIL = 0, ++ ENQUEUE_PRIOR_HEAD, ++} ENQUEUE_PRIOR; ++ ++typedef enum SIP_STATE { ++ SIP_INIT = 0, ++ SIP_PREPARE_BOOT, ++ SIP_BOOT, ++ SIP_SEND_INIT, ++ SIP_WAIT_BOOTUP, ++ SIP_RUN, ++ SIP_SUSPEND, ++ SIP_STOP ++} SIP_STATE; ++ ++enum sip_notifier { ++ SIP_TX_DONE = 1, ++ SIP_RX_DONE = 2, ++}; ++ ++#define SIP_CREDITS_LOW_THRESHOLD 64 //i.e. 4k ++ ++struct esp_sip { ++ struct list_head free_ctrl_txbuf; ++ struct list_head free_ctrl_rxbuf; ++ ++ u32 rxseq; /* sip pkt seq, should match target side */ ++ u32 txseq; ++ u32 txdataseq; ++ ++ u8 to_host_seq; ++ ++ atomic_t state; ++ spinlock_t lock; ++ atomic_t tx_credits; ++ ++ atomic_t tx_ask_credit_update; ++ ++ u8 *rawbuf; /* used in boot stage, free once chip is fully up */ ++ u8 *tx_aggr_buf; ++ u8 *tx_aggr_write_ptr; /* update after insertion of each pkt */ ++ u8 *tx_aggr_lastpkt_ptr; ++ ++ struct mutex rx_mtx; ++ struct sk_buff_head rxq; ++ struct work_struct rx_process_work; ++ ++ u16 tx_blksz; ++ u16 rx_blksz; ++ ++ bool dump_rpbm_err; ++ bool sendup_rpbm_pkt; ++ bool rxabort_fixed; ++ bool support_bgscan; ++ u8 credit_to_reserve; ++ ++ atomic_t credit_status; ++ struct timer_list credit_timer; ++ ++ atomic_t noise_floor; ++ ++ u32 tx_tot_len; /* total len for one transaction */ ++ u32 rx_tot_len; ++ ++ atomic_t rx_handling; ++ atomic_t tx_data_pkt_queued; ++ ++ atomic_t data_tx_stopped; ++ atomic_t tx_stopped; ++ ++ struct esp_pub *epub; ++}; ++ ++int sip_rx(struct esp_pub *epub); ++//int sip_download_fw(struct esp_sip *sip, u32 load_addr, u32 boot_addr); ++ ++ ++int sip_write_memory(struct esp_sip *, u32 addr, u8 * buf, u16 len); ++ ++void sip_credit_process(struct esp_pub *, u8 credits); ++ ++int sip_send_cmd(struct esp_sip *sip, int cid, u32 cmdlen, void *cmd); ++ ++struct esp_sip *sip_attach(struct esp_pub *); ++ ++int sip_post_init(struct esp_sip *sip, struct sip_evt_bootup2 *bevt); ++ ++void sip_detach(struct esp_sip *sip); ++ ++void sip_txq_process(struct esp_pub *epub); ++ ++struct sk_buff *sip_alloc_ctrl_skbuf(struct esp_sip *sip, u16 len, ++ u32 cid); ++ ++void sip_free_ctrl_skbuff(struct esp_sip *sip, struct sk_buff *skb); ++ ++bool sip_queue_need_stop(struct esp_sip *sip); ++bool sip_queue_may_resume(struct esp_sip *sip); ++bool sip_tx_data_need_stop(struct esp_sip *sip); ++bool sip_tx_data_may_resume(struct esp_sip *sip); ++ ++void sip_tx_data_pkt_enqueue(struct esp_pub *epub, struct sk_buff *skb); ++void sip_rx_data_pkt_enqueue(struct esp_pub *epub, struct sk_buff *skb); ++ ++int sip_cmd_enqueue(struct esp_sip *sip, struct sk_buff *skb, int prior); ++ ++int sip_poll_bootup_event(struct esp_sip *sip); ++ ++int sip_poll_resetting_event(struct esp_sip *sip); ++ ++void sip_trigger_txq_process(struct esp_sip *sip); ++ ++void sip_send_chip_init(struct esp_sip *sip); ++ ++bool mod_support_no_txampdu(void); ++ ++bool mod_support_no_rxampdu(void); ++ ++void mod_support_no_txampdu_set(bool value); ++ ++#ifdef FPGA_DEBUG ++int sip_send_bootup(struct esp_sip *sip); ++#endif /* FPGA_DEBUG */ ++void sip_debug_show(struct esp_sip *sip); ++#endif +diff --git a/drivers/net/wireless/esp8089/esp_utils.c b/drivers/net/wireless/esp8089/esp_utils.c +new file mode 100644 +index 000000000000..8b188de79b2c +--- /dev/null ++++ b/drivers/net/wireless/esp8089/esp_utils.c +@@ -0,0 +1,262 @@ ++/* ++ * Copyright (c) 2009 - 2014 Espressif System. ++ * ++ * 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. ++ */ ++ ++#include "linux/types.h" ++#include "linux/kernel.h" ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "esp_pub.h" ++#include "esp_utils.h" ++#include "esp_wmac.h" ++#include "esp_debug.h" ++ ++/* ++ * Convert IEEE channel number to MHz frequency. ++ */ ++u32 esp_ieee2mhz(u8 chan) ++{ ++ if (chan == 14) ++ return 2484; ++ ++ if (chan < 14) ++ return 2407 + chan * 5; ++ else ++ return 2512 + ((chan - 15) * 20); ++ //TODO, add 5GHz ++} ++ ++enum { ++ ESP_RATE_1_LONG = 0x0, ++ ESP_RATE_2_LONG = 0x1, ++ ESP_RATE_2_SHORT = 0x5, ++ ESP_RATE_5_SHORT = 0x6, ++ ESP_RATE_5_LONG = 0x2, ++ ESP_RATE_11_SHORT = 0x7, ++ ESP_RATE_11_LONG = 0x3, ++ ESP_RATE_6 = 0xb, ++ ESP_RATE_9 = 0xf, ++ ESP_RATE_12 = 0xa, ++ ESP_RATE_18 = 0xe, ++ ESP_RATE_24 = 0x9, ++ ESP_RATE_36 = 0xd, ++ ESP_RATE_48 = 0x8, ++ ESP_RATE_54 = 0xc, ++ /* ESP_RATE_MCS0 =0x10, ++ ESP_RATE_MCS1 =0x11, ++ ESP_RATE_MCS2 =0x12, ++ ESP_RATE_MCS3 =0x13, ++ ESP_RATE_MCS4 =0x14, ++ ESP_RATE_MCS5 =0x15, ++ ESP_RATE_MCS6 =0x16, ++ ESP_RATE_MCS7 =0x17, ++ */ ++}; ++ ++static u8 esp_rate_table[20] = { ++ ESP_RATE_1_LONG, ++ ESP_RATE_2_SHORT, ++ ESP_RATE_5_SHORT, ++ ESP_RATE_11_SHORT, ++ ESP_RATE_6, ++ ESP_RATE_9, ++ ESP_RATE_12, ++ ESP_RATE_18, ++ ESP_RATE_24, ++ ESP_RATE_36, ++ ESP_RATE_48, ++ ESP_RATE_54, ++ /* ESP_RATE_MCS0, ++ ESP_RATE_MCS1, ++ ESP_RATE_MCS2, ++ ESP_RATE_MCS3, ++ ESP_RATE_MCS4, ++ ESP_RATE_MCS5, ++ ESP_RATE_MCS6, ++ ESP_RATE_MCS7, ++ */ ++}; ++ ++s8 esp_wmac_rate2idx(u8 rate) ++{ ++ int i; ++ ++ if (rate == ESP_RATE_2_LONG) ++ return 1; ++ if (rate == ESP_RATE_5_LONG) ++ return 2; ++ if (rate == ESP_RATE_11_LONG) ++ return 3; ++ ++ for (i = 0; i < 20; i++) { ++ if (rate == esp_rate_table[i]) ++ return i; ++ } ++ ++ esp_dbg(ESP_DBG_ERROR, "%s unknown rate 0x%02x \n", __func__, ++ rate); ++ ++ return 0; ++} ++ ++bool esp_wmac_rxsec_error(u8 error) ++{ ++ return (error >= RX_SECOV_ERR && error <= RX_SECFIFO_TIMEOUT) ++ || (error >= RX_WEPICV_ERR && error <= RX_WAPIMIC_ERR); ++} ++ ++int esp_cipher2alg(int cipher) ++{ ++ if (cipher == WLAN_CIPHER_SUITE_TKIP) ++ return ALG_TKIP; ++ ++ if (cipher == WLAN_CIPHER_SUITE_CCMP) ++ return ALG_CCMP; ++ ++ if (cipher == WLAN_CIPHER_SUITE_WEP40 ++ || cipher == WLAN_CIPHER_SUITE_WEP104) ++ return ALG_WEP; ++ ++ if (cipher == WLAN_CIPHER_SUITE_AES_CMAC) ++ return ALG_AES_CMAC; ++ ++ //printk("%s wrong cipher 0x%x!\n",__func__,cipher); ++ ++ return -1; ++} ++ ++#ifdef RX_CHECKSUM_TEST ++atomic_t g_iv_len; ++void esp_rx_checksum_test(struct sk_buff *skb) ++{ ++ static u32 ip_err = 0; ++ static u32 tcp_err = 0; ++ struct ieee80211_hdr *pwh = (struct ieee80211_hdr *) skb->data; ++ int hdrlen = ieee80211_hdrlen(pwh->frame_control); ++ ++ if (ieee80211_has_protected(pwh->frame_control)) ++ hdrlen += atomic_read(&g_iv_len); ++ ++ if (ieee80211_is_data(pwh->frame_control)) { ++ struct llc_snap_hdr *llc = ++ (struct llc_snap_hdr *) (skb->data + hdrlen); ++ if (ntohs(llc->eth_type) == ETH_P_IP) { ++ int llclen = sizeof(struct llc_snap_hdr); ++ struct iphdr *iph = ++ (struct iphdr *) (skb->data + hdrlen + llclen); ++ __sum16 csum_bak = iph->check; ++ ++ iph->check = 0; ++ iph->check = ip_fast_csum(iph, iph->ihl); ++ if (iph->check != csum_bak) { ++ esp_dbg(ESP_DBG_ERROR, ++ "total ip checksum error %d\n", ++ ++ip_err); ++ } ++ iph->check = csum_bak; ++ ++ if (iph->protocol == 0x06) { ++ struct tcphdr *tcph = ++ (struct tcphdr *) (skb->data + hdrlen + ++ llclen + ++ iph->ihl * 4); ++ int datalen = ++ skb->len - (hdrlen + llclen + ++ iph->ihl * 4); ++ csum_bak = tcph->check; ++ ++ tcph->check = 0; ++ tcph->check = ++ tcp_v4_check(datalen, iph->saddr, ++ iph->daddr, ++ csum_partial((char *) ++ tcph, ++ datalen, 0)); ++ if (tcph->check != csum_bak) { ++ esp_dbg(ESP_DBG_ERROR, ++ "total tcp checksum error %d\n", ++ ++tcp_err); ++ } ++ tcph->check = csum_bak; ++ } ++ } ++ } ++} ++ ++#endif ++ ++#ifdef GEN_ERR_CHECKSUM ++ ++void esp_gen_err_checksum(struct sk_buff *skb) ++{ ++ static u32 tx_seq = 0; ++ if ((tx_seq++ % 16) == 0) { ++ struct ieee80211_hdr *hdr = ++ (struct ieee80211_hdr *) skb->data; ++ int hdrlen = ieee80211_hdrlen(hdr->frame_control); ++ ++ if (ieee80211_has_protected(pwh->frame_control)) ++ hdrlen += ++ IEEE80211_SKB_CB(skb)->control.hw_key->iv_len; ++ ++ struct llc_snap_hdr *llc = ++ (struct llc_snap_hdr *) (skb->data + hdrlen); ++ if (ntohs(llc->eth_type) == ETH_P_IP) { ++ int llclen = sizeof(struct llc_snap_hdr); ++ struct iphdr *iph = ++ (struct iphdr *) (skb->data + hdrlen + llclen); ++ ++ iph->check = ~iph->check; ++ ++ if (iph->protocol == 0x06) { ++ struct tcphdr *tcph = ++ (struct tcphdr *) (skb->data + hdrlen + ++ llclen + ++ iph->ihl * 4); ++ tcph->check = ~tcph->check; ++ } ++ } ++ } ++} ++#endif ++ ++bool esp_is_ip_pkt(struct sk_buff *skb) ++{ ++ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; ++ int hdrlen; ++ struct llc_snap_hdr *llc; ++ ++ if (!ieee80211_is_data(hdr->frame_control)) ++ return false; ++ ++ hdrlen = ieee80211_hdrlen(hdr->frame_control); ++ if (ieee80211_has_protected(hdr->frame_control)) ++ hdrlen += IEEE80211_SKB_CB(skb)->control.hw_key->iv_len; ++#ifdef RX_CHECKSUM_TEST ++ atomic_set(&g_iv_len, ++ IEEE80211_SKB_CB(skb)->control.hw_key->iv_len); ++#endif ++ if (skb->len < hdrlen + sizeof(struct llc_snap_hdr)) ++ return false; ++ llc = (struct llc_snap_hdr *) (skb->data + hdrlen); ++ if (ntohs(llc->eth_type) != ETH_P_IP) ++ return false; ++ else ++ return true; ++} +diff --git a/drivers/net/wireless/esp8089/esp_utils.h b/drivers/net/wireless/esp8089/esp_utils.h +new file mode 100644 +index 000000000000..ed16d9ca0a65 +--- /dev/null ++++ b/drivers/net/wireless/esp8089/esp_utils.h +@@ -0,0 +1,41 @@ ++/* ++ * Copyright (c) 2011-2012 Espressif System. ++ * ++ * 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 _ESP_UTILS_H_ ++#define _ESP_UTILS_H_ ++ ++#include "linux/types.h" ++#include ++ ++#ifndef BIT ++#define BIT(x) (0x1 << (x)) ++#endif ++ ++u32 esp_ieee2mhz(u8 chan); ++ ++enum ieee80211_key_alg { ++ ALG_WEP, ++ ALG_TKIP, ++ ALG_CCMP, ++ ALG_AES_CMAC ++}; ++ ++int esp_cipher2alg(int cipher); ++ ++void esp_rx_checksum_test(struct sk_buff *skb); ++void esp_gen_err_checksum(struct sk_buff *skb); ++ ++bool esp_is_ip_pkt(struct sk_buff *skb); ++ ++#endif +diff --git a/drivers/net/wireless/esp8089/esp_version.h b/drivers/net/wireless/esp8089/esp_version.h +new file mode 100644 +index 000000000000..481d98841fc2 +--- /dev/null ++++ b/drivers/net/wireless/esp8089/esp_version.h +@@ -0,0 +1 @@ ++#define DRIVER_VER 0xbdf5087c3debll +diff --git a/drivers/net/wireless/esp8089/esp_wl.h b/drivers/net/wireless/esp8089/esp_wl.h +new file mode 100644 +index 000000000000..e3e62a83d505 +--- /dev/null ++++ b/drivers/net/wireless/esp8089/esp_wl.h +@@ -0,0 +1,63 @@ ++#ifndef _ESP_WL_H_ ++#define _ESP_WL_H_ ++ ++//#define MAX_PROBED_SSID_INDEX 9 ++ ++ ++enum { ++ CONF_HW_BIT_RATE_1MBPS = BIT(0), ++ CONF_HW_BIT_RATE_2MBPS = BIT(1), ++ CONF_HW_BIT_RATE_5_5MBPS = BIT(2), ++ CONF_HW_BIT_RATE_11MBPS = BIT(3), ++ CONF_HW_BIT_RATE_6MBPS = BIT(4), ++ CONF_HW_BIT_RATE_9MBPS = BIT(5), ++ CONF_HW_BIT_RATE_12MBPS = BIT(6), ++ CONF_HW_BIT_RATE_18MBPS = BIT(7), ++ CONF_HW_BIT_RATE_22MBPS = BIT(8), ++ CONF_HW_BIT_RATE_24MBPS = BIT(9), ++ CONF_HW_BIT_RATE_36MBPS = BIT(10), ++ CONF_HW_BIT_RATE_48MBPS = BIT(11), ++ CONF_HW_BIT_RATE_54MBPS = BIT(12), ++ CONF_HW_BIT_RATE_11B_MASK = ++ (CONF_HW_BIT_RATE_1MBPS | CONF_HW_BIT_RATE_2MBPS | ++ CONF_HW_BIT_RATE_5_5MBPS | CONF_HW_BIT_RATE_11MBPS), ++}; ++ ++#if 0 ++enum { ++ CONF_HW_RATE_INDEX_1MBPS = 0, ++ CONF_HW_RATE_INDEX_2MBPS = 1, ++ CONF_HW_RATE_INDEX_5_5MBPS = 2, ++ CONF_HW_RATE_INDEX_6MBPS = 3, ++ CONF_HW_RATE_INDEX_9MBPS = 4, ++ CONF_HW_RATE_INDEX_11MBPS = 5, ++ CONF_HW_RATE_INDEX_12MBPS = 6, ++ CONF_HW_RATE_INDEX_18MBPS = 7, ++ CONF_HW_RATE_INDEX_22MBPS = 8, ++ CONF_HW_RATE_INDEX_24MBPS = 9, ++ CONF_HW_RATE_INDEX_36MBPS = 10, ++ CONF_HW_RATE_INDEX_48MBPS = 11, ++ CONF_HW_RATE_INDEX_54MBPS = 12, ++ CONF_HW_RATE_INDEX_MAX, ++}; ++ ++enum { ++ CONF_HW_RXTX_RATE_54 = 0, ++ CONF_HW_RXTX_RATE_48, ++ CONF_HW_RXTX_RATE_36, ++ CONF_HW_RXTX_RATE_24, ++ CONF_HW_RXTX_RATE_22, ++ CONF_HW_RXTX_RATE_18, ++ CONF_HW_RXTX_RATE_12, ++ CONF_HW_RXTX_RATE_11, ++ CONF_HW_RXTX_RATE_9, ++ CONF_HW_RXTX_RATE_6, ++ CONF_HW_RXTX_RATE_5_5, ++ CONF_HW_RXTX_RATE_2, ++ CONF_HW_RXTX_RATE_1, ++ CONF_HW_RXTX_RATE_MAX, ++ CONF_HW_RXTX_RATE_UNSUPPORTED = 0xff ++}; ++#endif ++ ++#endif /* _ESP_WL_H_ */ +diff --git a/drivers/net/wireless/esp8089/esp_wmac.h b/drivers/net/wireless/esp8089/esp_wmac.h +new file mode 100644 +index 000000000000..72d13cbfc0e5 +--- /dev/null ++++ b/drivers/net/wireless/esp8089/esp_wmac.h +@@ -0,0 +1,92 @@ ++/* ++ * Copyright (c) 2011-2012 Espressif System. ++ * ++ * MAC header ++ * ++ * 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 _ESP_WMAC_H_ ++#define _ESP_WMAC_H_ ++ ++struct esp_mac_rx_ctrl { ++ signed rssi:8; ++ unsigned rate:4; ++ unsigned is_group:1; ++ unsigned:1; ++ unsigned sig_mode:2; ++ unsigned legacy_length:12; ++ unsigned damatch0:1; ++ unsigned damatch1:1; ++ unsigned bssidmatch0:1; ++ unsigned bssidmatch1:1; ++ unsigned MCS:7; ++ unsigned CWB:1; ++ unsigned HT_length:16; ++ unsigned Smoothing:1; ++ unsigned Not_Sounding:1; ++ unsigned:1; ++ unsigned Aggregation:1; ++ unsigned STBC:2; ++ unsigned FEC_CODING:1; ++ unsigned SGI:1; ++ unsigned rxend_state:8; ++ unsigned ampdu_cnt:8; ++ unsigned channel:4; ++ unsigned:4; ++ signed noise_floor:8; ++}; ++ ++struct esp_rx_ampdu_len { ++ unsigned substate:8; ++ unsigned sublen:12; ++ unsigned:12; ++}; ++ ++struct esp_tx_ampdu_entry { ++ u32 sub_len:12, dili_num:7,:1, null_byte:2, data:1, enc:1, seq:8; ++}; ++ ++//rxend_state flags ++#define RX_PYH_ERR_MIN 0x42 ++#define RX_AGC_ERR_MIN 0x42 ++#define RX_AGC_ERR_MAX 0x47 ++#define RX_OFDM_ERR_MIN 0x50 ++#define RX_OFDM_ERR_MAX 0x58 ++#define RX_CCK_ERR_MIN 0x59 ++#define RX_CCK_ERR_MAX 0x5F ++#define RX_ABORT 0x80 ++#define RX_SF_ERR 0x40 ++#define RX_FCS_ERR 0x41 ++#define RX_AHBOV_ERR 0xC0 ++#define RX_BUFOV_ERR 0xC1 ++#define RX_BUFINV_ERR 0xC2 ++#define RX_AMPDUSF_ERR 0xC3 ++#define RX_AMPDUBUFOV_ERR 0xC4 ++#define RX_MACBBFIFOOV_ERR 0xC5 ++#define RX_RPBM_ERR 0xC6 ++#define RX_BTFORCE_ERR 0xC7 ++#define RX_SECOV_ERR 0xE1 ++#define RX_SECPROT_ERR0 0xE2 ++#define RX_SECPROT_ERR1 0xE3 ++#define RX_SECKEY_ERR 0xE4 ++#define RX_SECCRLEN_ERR 0xE5 ++#define RX_SECFIFO_TIMEOUT 0xE6 ++#define RX_WEPICV_ERR 0xF0 ++#define RX_TKIPICV_ERR 0xF4 ++#define RX_TKIPMIC_ERR 0xF5 ++#define RX_CCMPMIC_ERR 0xF8 ++#define RX_WAPIMIC_ERR 0xFC ++ ++s8 esp_wmac_rate2idx(u8 rate); ++bool esp_wmac_rxsec_error(u8 error); ++ ++#endif /* _ESP_WMAC_H_ */ +diff --git a/drivers/net/wireless/esp8089/firmware/LICENSE-2.0.txt b/drivers/net/wireless/esp8089/firmware/LICENSE-2.0.txt +new file mode 100644 +index 000000000000..0dd35c82a001 +--- /dev/null ++++ b/drivers/net/wireless/esp8089/firmware/LICENSE-2.0.txt +@@ -0,0 +1,203 @@ ++The esp8089 firmware files are licensed under the Apache License, Version 2.0: ++ ++ Apache License ++ Version 2.0, January 2004 ++ http://www.apache.org/licenses/ ++ ++ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION ++ ++ 1. Definitions. ++ ++ "License" shall mean the terms and conditions for use, reproduction, ++ and distribution as defined by Sections 1 through 9 of this document. ++ ++ "Licensor" shall mean the copyright owner or entity authorized by ++ the copyright owner that is granting the License. ++ ++ "Legal Entity" shall mean the union of the acting entity and all ++ other entities that control, are controlled by, or are under common ++ control with that entity. For the purposes of this definition, ++ "control" means (i) the power, direct or indirect, to cause the ++ direction or management of such entity, whether by contract or ++ otherwise, or (ii) ownership of fifty percent (50%) or more of the ++ outstanding shares, or (iii) beneficial ownership of such entity. ++ ++ "You" (or "Your") shall mean an individual or Legal Entity ++ exercising permissions granted by this License. ++ ++ "Source" form shall mean the preferred form for making modifications, ++ including but not limited to software source code, documentation ++ source, and configuration files. ++ ++ "Object" form shall mean any form resulting from mechanical ++ transformation or translation of a Source form, including but ++ not limited to compiled object code, generated documentation, ++ and conversions to other media types. ++ ++ "Work" shall mean the work of authorship, whether in Source or ++ Object form, made available under the License, as indicated by a ++ copyright notice that is included in or attached to the work ++ (an example is provided in the Appendix below). ++ ++ "Derivative Works" shall mean any work, whether in Source or Object ++ form, that is based on (or derived from) the Work and for which the ++ editorial revisions, annotations, elaborations, or other modifications ++ represent, as a whole, an original work of authorship. For the purposes ++ of this License, Derivative Works shall not include works that remain ++ separable from, or merely link (or bind by name) to the interfaces of, ++ the Work and Derivative Works thereof. ++ ++ "Contribution" shall mean any work of authorship, including ++ the original version of the Work and any modifications or additions ++ to that Work or Derivative Works thereof, that is intentionally ++ submitted to Licensor for inclusion in the Work by the copyright owner ++ or by an individual or Legal Entity authorized to submit on behalf of ++ the copyright owner. For the purposes of this definition, "submitted" ++ means any form of electronic, verbal, or written communication sent ++ to the Licensor or its representatives, including but not limited to ++ communication on electronic mailing lists, source code control systems, ++ and issue tracking systems that are managed by, or on behalf of, the ++ Licensor for the purpose of discussing and improving the Work, but ++ excluding communication that is conspicuously marked or otherwise ++ designated in writing by the copyright owner as "Not a Contribution." ++ ++ "Contributor" shall mean Licensor and any individual or Legal Entity ++ on behalf of whom a Contribution has been received by Licensor and ++ subsequently incorporated within the Work. ++ ++ 2. Grant of Copyright License. Subject to the terms and conditions of ++ this License, each Contributor hereby grants to You a perpetual, ++ worldwide, non-exclusive, no-charge, royalty-free, irrevocable ++ copyright license to reproduce, prepare Derivative Works of, ++ publicly display, publicly perform, sublicense, and distribute the ++ Work and such Derivative Works in Source or Object form. ++ ++ 3. Grant of Patent License. Subject to the terms and conditions of ++ this License, each Contributor hereby grants to You a perpetual, ++ worldwide, non-exclusive, no-charge, royalty-free, irrevocable ++ (except as stated in this section) patent license to make, have made, ++ use, offer to sell, sell, import, and otherwise transfer the Work, ++ where such license applies only to those patent claims licensable ++ by such Contributor that are necessarily infringed by their ++ Contribution(s) alone or by combination of their Contribution(s) ++ with the Work to which such Contribution(s) was submitted. If You ++ institute patent litigation against any entity (including a ++ cross-claim or counterclaim in a lawsuit) alleging that the Work ++ or a Contribution incorporated within the Work constitutes direct ++ or contributory patent infringement, then any patent licenses ++ granted to You under this License for that Work shall terminate ++ as of the date such litigation is filed. ++ ++ 4. Redistribution. You may reproduce and distribute copies of the ++ Work or Derivative Works thereof in any medium, with or without ++ modifications, and in Source or Object form, provided that You ++ meet the following conditions: ++ ++ (a) You must give any other recipients of the Work or ++ Derivative Works a copy of this License; and ++ ++ (b) You must cause any modified files to carry prominent notices ++ stating that You changed the files; and ++ ++ (c) You must retain, in the Source form of any Derivative Works ++ that You distribute, all copyright, patent, trademark, and ++ attribution notices from the Source form of the Work, ++ excluding those notices that do not pertain to any part of ++ the Derivative Works; and ++ ++ (d) If the Work includes a "NOTICE" text file as part of its ++ distribution, then any Derivative Works that You distribute must ++ include a readable copy of the attribution notices contained ++ within such NOTICE file, excluding those notices that do not ++ pertain to any part of the Derivative Works, in at least one ++ of the following places: within a NOTICE text file distributed ++ as part of the Derivative Works; within the Source form or ++ documentation, if provided along with the Derivative Works; or, ++ within a display generated by the Derivative Works, if and ++ wherever such third-party notices normally appear. The contents ++ of the NOTICE file are for informational purposes only and ++ do not modify the License. You may add Your own attribution ++ notices within Derivative Works that You distribute, alongside ++ or as an addendum to the NOTICE text from the Work, provided ++ that such additional attribution notices cannot be construed ++ as modifying the License. ++ ++ You may add Your own copyright statement to Your modifications and ++ may provide additional or different license terms and conditions ++ for use, reproduction, or distribution of Your modifications, or ++ for any such Derivative Works as a whole, provided Your use, ++ reproduction, and distribution of the Work otherwise complies with ++ the conditions stated in this License. ++ ++ 5. Submission of Contributions. Unless You explicitly state otherwise, ++ any Contribution intentionally submitted for inclusion in the Work ++ by You to the Licensor shall be under the terms and conditions of ++ this License, without any additional terms or conditions. ++ Notwithstanding the above, nothing herein shall supersede or modify ++ the terms of any separate license agreement you may have executed ++ with Licensor regarding such Contributions. ++ ++ 6. Trademarks. This License does not grant permission to use the trade ++ names, trademarks, service marks, or product names of the Licensor, ++ except as required for reasonable and customary use in describing the ++ origin of the Work and reproducing the content of the NOTICE file. ++ ++ 7. Disclaimer of Warranty. Unless required by applicable law or ++ agreed to in writing, Licensor provides the Work (and each ++ Contributor provides its Contributions) on an "AS IS" BASIS, ++ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or ++ implied, including, without limitation, any warranties or conditions ++ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A ++ PARTICULAR PURPOSE. You are solely responsible for determining the ++ appropriateness of using or redistributing the Work and assume any ++ risks associated with Your exercise of permissions under this License. ++ ++ 8. Limitation of Liability. In no event and under no legal theory, ++ whether in tort (including negligence), contract, or otherwise, ++ unless required by applicable law (such as deliberate and grossly ++ negligent acts) or agreed to in writing, shall any Contributor be ++ liable to You for damages, including any direct, indirect, special, ++ incidental, or consequential damages of any character arising as a ++ result of this License or out of the use or inability to use the ++ Work (including but not limited to damages for loss of goodwill, ++ work stoppage, computer failure or malfunction, or any and all ++ other commercial damages or losses), even if such Contributor ++ has been advised of the possibility of such damages. ++ ++ 9. Accepting Warranty or Additional Liability. While redistributing ++ the Work or Derivative Works thereof, You may choose to offer, ++ and charge a fee for, acceptance of support, warranty, indemnity, ++ or other liability obligations and/or rights consistent with this ++ License. However, in accepting such obligations, You may act only ++ on Your own behalf and on Your sole responsibility, not on behalf ++ of any other Contributor, and only if You agree to indemnify, ++ defend, and hold each Contributor harmless for any liability ++ incurred by, or claims asserted against, such Contributor by reason ++ of your accepting any such warranty or additional liability. ++ ++ END OF TERMS AND CONDITIONS ++ ++ APPENDIX: How to apply the Apache License to your work. ++ ++ To apply the Apache License to your work, attach the following ++ boilerplate notice, with the fields enclosed by brackets "[]" ++ replaced with your own identifying information. (Don't include ++ the brackets!) The text should be enclosed in the appropriate ++ comment syntax for the file format. We also recommend that a ++ file or class name and description of purpose be included on the ++ same "printed page" as the copyright notice for easier ++ identification within third-party archives. ++ ++ Copyright [yyyy] [name of copyright owner] ++ ++ 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. +diff --git a/drivers/net/wireless/esp8089/sdio_sif_esp.c b/drivers/net/wireless/esp8089/sdio_sif_esp.c +new file mode 100644 +index 000000000000..2bd2c63f5388 +--- /dev/null ++++ b/drivers/net/wireless/esp8089/sdio_sif_esp.c +@@ -0,0 +1,824 @@ ++/* ++ * Copyright (c) 2010 -2013 Espressif System. ++ * ++ * sdio serial i/f driver ++ * - sdio device control routines ++ * - sync/async DMA/PIO read/write ++ * ++ * 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. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "esp_pub.h" ++#include "esp_sif.h" ++#include "esp_sip.h" ++#include "esp_debug.h" ++#include "slc_host_register.h" ++#include "esp_version.h" ++#include "esp_ctrl.h" ++#include "esp_file.h" ++#ifdef USE_EXT_GPIO ++#include "esp_ext.h" ++#endif /* USE_EXT_GPIO */ ++ ++#define MANUFACTURER_ID_EAGLE_BASE 0x1110 ++#define MANUFACTURER_ID_EAGLE_BASE_MASK 0xFF00 ++#define MANUFACTURER_CODE 0x6666 ++ ++static const struct sdio_device_id esp_sdio_devices[] = { ++ {SDIO_DEVICE ++ (MANUFACTURER_CODE, (MANUFACTURER_ID_EAGLE_BASE | 0x1))}, ++ {}, ++}; ++ ++static const struct of_device_id esp_of_match_table[] = { ++ { .compatible = "esp,esp8089", .data = NULL}, ++ { } ++}; ++ ++static int /*__init*/ esp_sdio_init(void); ++static void /*__exit*/ esp_sdio_exit(void); ++ ++ ++#define ESP_DMA_IBUFSZ 2048 ++ ++//unsigned int esp_msg_level = 0; ++unsigned int esp_msg_level = ESP_DBG_ERROR | ESP_SHOW; ++ ++struct esp_sdio_ctrl *sif_sctrl = NULL; ++ ++#ifdef ESP_ANDROID_LOGGER ++bool log_off = false; ++#endif /* ESP_ANDROID_LOGGER */ ++ ++static int esdio_power_off(struct esp_sdio_ctrl *sctrl); ++static int esdio_power_on(struct esp_sdio_ctrl *sctrl); ++ ++void sif_set_clock(struct sdio_func *func, int clk); ++ ++void sif_lock_bus(struct esp_pub *epub) ++{ ++ EPUB_FUNC_CHECK(epub, _exit); ++ ++ sdio_claim_host(EPUB_TO_FUNC(epub)); ++ _exit: ++ return; ++} ++ ++void sif_unlock_bus(struct esp_pub *epub) ++{ ++ EPUB_FUNC_CHECK(epub, _exit); ++ ++ sdio_release_host(EPUB_TO_FUNC(epub)); ++ _exit: ++ return; ++} ++ ++static inline bool bad_buf(u8 * buf) ++{ ++ return ((unsigned long) buf & 0x3) || !virt_addr_valid(buf); ++} ++ ++u8 sdio_io_readb(struct esp_pub *epub, int addr, int *res) ++{ ++ struct esp_sdio_ctrl *sctrl = NULL; ++ struct sdio_func *func = NULL; ++ sctrl = (struct esp_sdio_ctrl *) epub->sif; ++ func = sctrl->func; ++ ++ if (func->num == 0) ++ return sdio_f0_readb(func, addr, res); ++ else ++ return sdio_readb(func, addr, res); ++} ++ ++void sdio_io_writeb(struct esp_pub *epub, u8 value, int addr, int *res) ++{ ++ struct esp_sdio_ctrl *sctrl = NULL; ++ struct sdio_func *func = NULL; ++ sctrl = (struct esp_sdio_ctrl *) epub->sif; ++ func = sctrl->func; ++ ++ if (func->num == 0) ++ sdio_f0_writeb(func, value, addr, res); ++ else ++ sdio_writeb(func, value, addr, res); ++} ++ ++int sif_io_raw(struct esp_pub *epub, u32 addr, u8 * buf, u32 len, u32 flag) ++{ ++ int err = 0; ++ u8 *ibuf = NULL; ++ bool need_ibuf = false; ++ struct esp_sdio_ctrl *sctrl = NULL; ++ struct sdio_func *func = NULL; ++ ++ if (epub == NULL || buf == NULL) { ++ ESSERT(0); ++ err = -EINVAL; ++ goto _exit; ++ } ++ ++ sctrl = (struct esp_sdio_ctrl *) epub->sif; ++ func = sctrl->func; ++ if (func == NULL) { ++ ESSERT(0); ++ err = -EINVAL; ++ goto _exit; ++ } ++ ++ if (bad_buf(buf)) { ++ esp_dbg(ESP_DBG_TRACE, "%s dst 0x%08x, len %d badbuf\n", ++ __func__, addr, len); ++ need_ibuf = true; ++ ibuf = sctrl->dma_buffer; ++ } else { ++ ibuf = buf; ++ } ++ ++ if (flag & SIF_BLOCK_BASIS) { ++ /* round up for block data transcation */ ++ } ++ ++ if (flag & SIF_TO_DEVICE) { ++ ++ if (need_ibuf) ++ memcpy(ibuf, buf, len); ++ ++ if (flag & SIF_FIXED_ADDR) ++ err = sdio_writesb(func, addr, ibuf, len); ++ else if (flag & SIF_INC_ADDR) { ++ err = sdio_memcpy_toio(func, addr, ibuf, len); ++ } ++ } else if (flag & SIF_FROM_DEVICE) { ++ ++ if (flag & SIF_FIXED_ADDR) ++ err = sdio_readsb(func, ibuf, addr, len); ++ else if (flag & SIF_INC_ADDR) { ++ err = sdio_memcpy_fromio(func, ibuf, addr, len); ++ } ++ ++ ++ if (!err && need_ibuf) ++ memcpy(buf, ibuf, len); ++ } ++ ++ _exit: ++ return err; ++} ++ ++int sif_io_sync(struct esp_pub *epub, u32 addr, u8 * buf, u32 len, ++ u32 flag) ++{ ++ int err = 0; ++ u8 *ibuf = NULL; ++ bool need_ibuf = false; ++ struct esp_sdio_ctrl *sctrl = NULL; ++ struct sdio_func *func = NULL; ++ ++ if (epub == NULL || buf == NULL) { ++ ESSERT(0); ++ err = -EINVAL; ++ goto _exit; ++ } ++ ++ sctrl = (struct esp_sdio_ctrl *) epub->sif; ++ func = sctrl->func; ++ if (func == NULL) { ++ ESSERT(0); ++ err = -EINVAL; ++ goto _exit; ++ } ++ ++ if (bad_buf(buf)) { ++ esp_dbg(ESP_DBG_TRACE, "%s dst 0x%08x, len %d badbuf\n", ++ __func__, addr, len); ++ need_ibuf = true; ++ ibuf = sctrl->dma_buffer; ++ } else { ++ ibuf = buf; ++ } ++ ++ if (flag & SIF_BLOCK_BASIS) { ++ /* round up for block data transcation */ ++ } ++ ++ if (flag & SIF_TO_DEVICE) { ++ ++ esp_dbg(ESP_DBG_TRACE, "%s to addr 0x%08x, len %d \n", ++ __func__, addr, len); ++ if (need_ibuf) ++ memcpy(ibuf, buf, len); ++ ++ sdio_claim_host(func); ++ ++ if (flag & SIF_FIXED_ADDR) ++ err = sdio_writesb(func, addr, ibuf, len); ++ else if (flag & SIF_INC_ADDR) { ++ err = sdio_memcpy_toio(func, addr, ibuf, len); ++ } ++ sdio_release_host(func); ++ } else if (flag & SIF_FROM_DEVICE) { ++ ++ esp_dbg(ESP_DBG_TRACE, "%s from addr 0x%08x, len %d \n", ++ __func__, addr, len); ++ ++ sdio_claim_host(func); ++ ++ if (flag & SIF_FIXED_ADDR) ++ err = sdio_readsb(func, ibuf, addr, len); ++ else if (flag & SIF_INC_ADDR) { ++ err = sdio_memcpy_fromio(func, ibuf, addr, len); ++ } ++ ++ sdio_release_host(func); ++ ++ if (!err && need_ibuf) ++ memcpy(buf, ibuf, len); ++ } ++ ++ _exit: ++ return err; ++} ++ ++int sif_lldesc_read_sync(struct esp_pub *epub, u8 * buf, u32 len) ++{ ++ struct esp_sdio_ctrl *sctrl = NULL; ++ u32 read_len; ++ ++ if (epub == NULL || buf == NULL) { ++ ESSERT(0); ++ return -EINVAL; ++ } ++ ++ sctrl = (struct esp_sdio_ctrl *) epub->sif; ++ ++ switch (sctrl->target_id) { ++ case 0x100: ++ read_len = len; ++ break; ++ case 0x600: ++ read_len = roundup(len, sctrl->slc_blk_sz); ++ break; ++ default: ++ read_len = len; ++ break; ++ } ++ ++ return sif_io_sync((epub), ++ (sctrl->slc_window_end_addr - 2 - (len)), (buf), ++ (read_len), ++ SIF_FROM_DEVICE | SIF_BYTE_BASIS | ++ SIF_INC_ADDR); ++} ++ ++int sif_lldesc_write_sync(struct esp_pub *epub, u8 * buf, u32 len) ++{ ++ struct esp_sdio_ctrl *sctrl = NULL; ++ u32 write_len; ++ ++ if (epub == NULL || buf == NULL) { ++ ESSERT(0); ++ return -EINVAL; ++ } ++ ++ sctrl = (struct esp_sdio_ctrl *) epub->sif; ++ ++ switch (sctrl->target_id) { ++ case 0x100: ++ write_len = len; ++ break; ++ case 0x600: ++ write_len = roundup(len, sctrl->slc_blk_sz); ++ break; ++ default: ++ write_len = len; ++ break; ++ } ++ ++ return sif_io_sync((epub), (sctrl->slc_window_end_addr - (len)), ++ (buf), (write_len), ++ SIF_TO_DEVICE | SIF_BYTE_BASIS | SIF_INC_ADDR); ++} ++ ++int sif_lldesc_read_raw(struct esp_pub *epub, u8 * buf, u32 len, ++ bool noround) ++{ ++ struct esp_sdio_ctrl *sctrl = NULL; ++ u32 read_len; ++ ++ if (epub == NULL || buf == NULL) { ++ ESSERT(0); ++ return -EINVAL; ++ } ++ ++ sctrl = (struct esp_sdio_ctrl *) epub->sif; ++ ++ switch (sctrl->target_id) { ++ case 0x100: ++ read_len = len; ++ break; ++ case 0x600: ++ if (!noround) ++ read_len = roundup(len, sctrl->slc_blk_sz); ++ else ++ read_len = len; ++ break; ++ default: ++ read_len = len; ++ break; ++ } ++ ++ return sif_io_raw((epub), (sctrl->slc_window_end_addr - 2 - (len)), ++ (buf), (read_len), ++ SIF_FROM_DEVICE | SIF_BYTE_BASIS | SIF_INC_ADDR); ++} ++ ++int sif_lldesc_write_raw(struct esp_pub *epub, u8 * buf, u32 len) ++{ ++ struct esp_sdio_ctrl *sctrl = NULL; ++ u32 write_len; ++ ++ if (epub == NULL || buf == NULL) { ++ ESSERT(0); ++ return -EINVAL; ++ } ++ ++ sctrl = (struct esp_sdio_ctrl *) epub->sif; ++ ++ switch (sctrl->target_id) { ++ case 0x100: ++ write_len = len; ++ break; ++ case 0x600: ++ write_len = roundup(len, sctrl->slc_blk_sz); ++ break; ++ default: ++ write_len = len; ++ break; ++ } ++ return sif_io_raw((epub), (sctrl->slc_window_end_addr - (len)), ++ (buf), (write_len), ++ SIF_TO_DEVICE | SIF_BYTE_BASIS | SIF_INC_ADDR); ++ ++} ++ ++static int esdio_power_on(struct esp_sdio_ctrl *sctrl) ++{ ++ int err = 0; ++ ++ if (sctrl->off == false) ++ return err; ++ ++ sdio_claim_host(sctrl->func); ++ err = sdio_enable_func(sctrl->func); ++ ++ if (err) { ++ esp_dbg(ESP_DBG_ERROR, "Unable to enable sdio func: %d\n", ++ err); ++ sdio_release_host(sctrl->func); ++ return err; ++ } ++ ++ sdio_release_host(sctrl->func); ++ ++ /* ensure device is up */ ++ msleep(5); ++ ++ sctrl->off = false; ++ ++ return err; ++} ++ ++static int esdio_power_off(struct esp_sdio_ctrl *sctrl) ++{ ++ int err; ++ ++ if (sctrl->off) ++ return 0; ++ ++ sdio_claim_host(sctrl->func); ++ err = sdio_disable_func(sctrl->func); ++ sdio_release_host(sctrl->func); ++ ++ if (err) ++ return err; ++ ++ sctrl->off = true; ++ ++ return err; ++} ++ ++void sif_enable_irq(struct esp_pub *epub) ++{ ++ int err; ++ struct esp_sdio_ctrl *sctrl = NULL; ++ ++ sctrl = (struct esp_sdio_ctrl *) epub->sif; ++ ++ sdio_claim_host(sctrl->func); ++ ++ err = sdio_claim_irq(sctrl->func, sif_dsr); ++ ++ if (err) ++ esp_dbg(ESP_DBG_ERROR, "sif %s failed\n", __func__); ++ ++ atomic_set(&epub->sip->state, SIP_BOOT); ++ ++ atomic_set(&sctrl->irq_installed, 1); ++ ++ sdio_release_host(sctrl->func); ++} ++ ++void sif_disable_irq(struct esp_pub *epub) ++{ ++ struct esp_sdio_ctrl *sctrl = (struct esp_sdio_ctrl *) epub->sif; ++ int i = 0; ++ ++ if (atomic_read(&sctrl->irq_installed) == 0) ++ return; ++ ++ sdio_claim_host(sctrl->func); ++ ++ while (atomic_read(&sctrl->irq_handling)) { ++ sdio_release_host(sctrl->func); ++ schedule_timeout(HZ / 100); ++ sdio_claim_host(sctrl->func); ++ if (i++ >= 400) { ++ esp_dbg(ESP_DBG_ERROR, "%s force to stop irq\n", ++ __func__); ++ break; ++ } ++ } ++ ++ /* Ignore errors, we don't always use an irq. */ ++ sdio_release_irq(sctrl->func); ++ ++ atomic_set(&sctrl->irq_installed, 0); ++ ++ sdio_release_host(sctrl->func); ++ ++} ++ ++void sif_set_clock(struct sdio_func *func, int clk) ++{ ++ struct mmc_host *host = NULL; ++ struct mmc_card *card = NULL; ++ ++ card = func->card; ++ host = card->host; ++ ++ sdio_claim_host(func); ++ ++ //currently only set clock ++ host->ios.clock = clk * 1000000; ++ ++ esp_dbg(ESP_SHOW, "%s clock is %u\n", __func__, host->ios.clock); ++ if (host->ios.clock > host->f_max) { ++ host->ios.clock = host->f_max; ++ } ++ host->ops->set_ios(host, &host->ios); ++ ++ mdelay(2); ++ ++ sdio_release_host(func); ++} ++ ++static int esp_sdio_probe(struct sdio_func *func, ++ const struct sdio_device_id *id); ++static void esp_sdio_remove(struct sdio_func *func); ++ ++static int esp_sdio_probe(struct sdio_func *func, ++ const struct sdio_device_id *id) ++{ ++ int err = 0; ++ struct esp_pub *epub = NULL; ++ struct esp_sdio_ctrl *sctrl; ++ ++ esp_dbg(ESP_DBG_TRACE, ++ "sdio_func_num: 0x%X, vendor id: 0x%X, dev id: 0x%X, block size: 0x%X/0x%X\n", ++ func->num, func->vendor, func->device, func->max_blksize, ++ func->cur_blksize); ++ ++ if (sif_sctrl == NULL) { ++ ++ esp_conf_init(&func->dev); ++ ++ esp_conf_upload_first(); ++ ++ sctrl = kzalloc(sizeof(struct esp_sdio_ctrl), GFP_KERNEL); ++ ++ if (sctrl == NULL) { ++ return -ENOMEM; ++ } ++ ++ /* temp buffer reserved for un-dma-able request */ ++ sctrl->dma_buffer = kzalloc(ESP_DMA_IBUFSZ, GFP_KERNEL); ++ ++ if (sctrl->dma_buffer == NULL) { ++ err = -ENOMEM; ++ goto _err_last; ++ } ++ sif_sctrl = sctrl; ++ sctrl->slc_blk_sz = SIF_SLC_BLOCK_SIZE; ++ ++ epub = esp_pub_alloc_mac80211(&func->dev); ++ ++ if (epub == NULL) { ++ esp_dbg(ESP_DBG_ERROR, "no mem for epub \n"); ++ err = -ENOMEM; ++ goto _err_dma; ++ } ++ epub->sif = (void *) sctrl; ++ epub->sdio_state = ESP_SDIO_STATE_FIRST_INIT; ++ sctrl->epub = epub; ++ ++#ifdef USE_EXT_GPIO ++ if (sif_get_ate_config() == 0) { ++ err = ext_gpio_init(epub); ++ if (err) { ++ esp_dbg(ESP_DBG_ERROR, ++ "ext_irq_work_init failed %d\n", ++ err); ++ goto _err_epub; ++ } ++ } ++#endif ++ ++ } else { ++ sctrl = sif_sctrl; ++ sif_sctrl = NULL; ++ epub = sctrl->epub; ++ epub->sdio_state = ESP_SDIO_STATE_SECOND_INIT; ++ SET_IEEE80211_DEV(epub->hw, &func->dev); ++ epub->dev = &func->dev; ++ } ++ ++ sctrl->func = func; ++ sdio_set_drvdata(func, sctrl); ++ ++ sctrl->id = id; ++ sctrl->off = true; ++ ++ /* give us some time to enable, in ms */ ++ func->enable_timeout = 100; ++ ++ err = esdio_power_on(sctrl); ++ esp_dbg(ESP_DBG_TRACE, " %s >> power_on err %d \n", __func__, err); ++ ++ if (err) { ++ if (epub->sdio_state == ESP_SDIO_STATE_FIRST_INIT) ++ goto _err_ext_gpio; ++ else ++ goto _err_second_init; ++ } ++ check_target_id(epub); ++ ++ sdio_claim_host(func); ++ ++ err = sdio_set_block_size(func, sctrl->slc_blk_sz); ++ ++ if (err) { ++ esp_dbg(ESP_DBG_ERROR, ++ "Set sdio block size %d failed: %d)\n", ++ sctrl->slc_blk_sz, err); ++ sdio_release_host(func); ++ if (epub->sdio_state == ESP_SDIO_STATE_FIRST_INIT) ++ goto _err_off; ++ else ++ goto _err_second_init; ++ } ++ ++ sdio_release_host(func); ++ ++#ifdef LOWER_CLK ++ /* fix clock for dongle */ ++ sif_set_clock(func, 23); ++#endif //LOWER_CLK ++ ++ err = esp_pub_init_all(epub); ++ ++ if (err) { ++ esp_dbg(ESP_DBG_ERROR, "esp_init_all failed: %d\n", err); ++ if (epub->sdio_state == ESP_SDIO_STATE_FIRST_INIT) { ++ err = 0; ++ goto _err_first_init; ++ } ++ if (epub->sdio_state == ESP_SDIO_STATE_SECOND_INIT) ++ goto _err_second_init; ++ } ++ ++ esp_dbg(ESP_DBG_TRACE, " %s return %d\n", __func__, err); ++ if (epub->sdio_state == ESP_SDIO_STATE_FIRST_INIT) { ++ esp_dbg(ESP_DBG_TRACE, "first normal exit\n"); ++ epub->sdio_state = ESP_SDIO_STATE_FIRST_NORMAL_EXIT; ++ /* Rescan the esp8089 after loading the initial firmware */ ++ sdio_claim_host(func); ++ mmc_sw_reset(func->card); ++ sdio_release_host(func); ++ msleep(10); ++ } ++ ++ return err; ++ ++ _err_off: ++ esdio_power_off(sctrl); ++ _err_ext_gpio: ++#ifdef USE_EXT_GPIO ++ if (sif_get_ate_config() == 0) ++ ext_gpio_deinit(); ++ _err_epub: ++#endif ++ esp_pub_dealloc_mac80211(epub); ++ _err_dma: ++ kfree(sctrl->dma_buffer); ++ _err_last: ++ kfree(sctrl); ++ _err_first_init: ++ if (epub && epub->sdio_state == ESP_SDIO_STATE_FIRST_INIT) { ++ esp_dbg(ESP_DBG_ERROR, "first error exit\n"); ++ epub->sdio_state = ESP_SDIO_STATE_FIRST_ERROR_EXIT; ++ } ++ return err; ++ _err_second_init: ++ epub->sdio_state = ESP_SDIO_STATE_SECOND_ERROR_EXIT; ++ esp_sdio_remove(func); ++ return err; ++} ++ ++static void esp_sdio_remove(struct sdio_func *func) ++{ ++ struct esp_sdio_ctrl *sctrl = NULL; ++ struct esp_pub *epub = NULL; ++ ++ esp_dbg(ESP_DBG_TRACE, "%s enter\n", __func__); ++ ++ sctrl = sdio_get_drvdata(func); ++ ++ if (sctrl == NULL) { ++ esp_dbg(ESP_DBG_ERROR, "%s no sctrl\n", __func__); ++ return; ++ } ++ ++ do { ++ epub = sctrl->epub; ++ if (epub == NULL) { ++ esp_dbg(ESP_DBG_ERROR, "%s epub null\n", __func__); ++ break; ++ } ++ if (epub->sdio_state != ESP_SDIO_STATE_FIRST_NORMAL_EXIT) { ++ if (epub->sip) { ++ sip_detach(epub->sip); ++ epub->sip = NULL; ++ esp_dbg(ESP_DBG_TRACE, ++ "%s sip detached \n", __func__); ++ } ++#ifdef USE_EXT_GPIO ++ if (sif_get_ate_config() == 0) ++ ext_gpio_deinit(); ++#endif ++ } else { ++ //sif_disable_target_interrupt(epub); ++ atomic_set(&epub->sip->state, SIP_STOP); ++ sif_disable_irq(epub); ++ } ++ ++ if (epub->sdio_state != ESP_SDIO_STATE_FIRST_NORMAL_EXIT) { ++ esp_pub_dealloc_mac80211(epub); ++ esp_dbg(ESP_DBG_TRACE, "%s dealloc mac80211 \n", ++ __func__); ++ ++ if (sctrl->dma_buffer) { ++ kfree(sctrl->dma_buffer); ++ sctrl->dma_buffer = NULL; ++ esp_dbg(ESP_DBG_TRACE, ++ "%s free dma_buffer \n", __func__); ++ } ++ ++ kfree(sctrl); ++ } ++ ++ } while (0); ++ ++ sdio_set_drvdata(func, NULL); ++ ++ /* ++ * Reset on sdio remove to leave the hardware in cold state, ++ * so a new module insertion will be possible ++ */ ++ if (epub->sdio_state == ESP_SDIO_STATE_SECOND_INIT) { ++ sdio_claim_host(func); ++ mmc_hw_reset(func->card); ++ sdio_release_host(func); ++ mdelay(10); ++ } ++ ++ esp_dbg(ESP_DBG_TRACE, "eagle sdio remove complete\n"); ++} ++ ++static int esp_sdio_suspend(struct device *dev) ++{ ++ struct sdio_func *func = dev_to_sdio_func(dev); ++ struct esp_sdio_ctrl *sctrl = sdio_get_drvdata(func); ++ struct esp_pub *epub = sctrl->epub; ++ ++ printk("%s", __func__); ++ atomic_set(&epub->ps.state, ESP_PM_ON); ++ ++ do { ++ u32 sdio_flags = 0; ++ int ret = 0; ++ sdio_flags = sdio_get_host_pm_caps(func); ++ ++ if (!(sdio_flags & MMC_PM_KEEP_POWER)) { ++ printk ++ ("%s can't keep power while host is suspended\n", ++ __func__); ++ } ++ ++ /* keep power while host suspended */ ++ ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); ++ if (ret) { ++ printk("%s error while trying to keep power\n", ++ __func__); ++ } ++ } while (0); ++ ++ ++ return 0; ++ ++} ++ ++static int esp_sdio_resume(struct device *dev) ++{ ++ esp_dbg(ESP_DBG_ERROR, "%s", __func__); ++ ++ return 0; ++} ++ ++static const struct dev_pm_ops esp_sdio_pm_ops = { ++ .suspend = esp_sdio_suspend, ++ .resume = esp_sdio_resume, ++}; ++ ++static struct sdio_driver esp_sdio_driver = { ++ .name = "eagle_sdio", ++ .id_table = esp_sdio_devices, ++ .probe = esp_sdio_probe, ++ .remove = esp_sdio_remove, ++ .drv = { ++ .pm = &esp_sdio_pm_ops, ++ .of_match_table = esp_of_match_table, ++ }, ++}; ++ ++static int /*__init*/ esp_sdio_init(void) ++{ ++ ++ esp_debugfs_init(); ++ sdio_register_driver(&esp_sdio_driver); ++ ++ msleep(1000); ++ ++ sdio_unregister_driver(&esp_sdio_driver); ++ msleep(100); ++ sdio_register_driver(&esp_sdio_driver); ++ ++ return 0; ++} ++ ++static void /*__exit*/ esp_sdio_exit(void) ++{ ++ sdio_unregister_driver(&esp_sdio_driver); ++ esp_debugfs_exit(); ++} ++ ++MODULE_DEVICE_TABLE(sdio, esp_sdio_devices); ++MODULE_DEVICE_TABLE(of, esp_of_match_table); ++MODULE_AUTHOR("Espressif System"); ++MODULE_DESCRIPTION ++ ("Driver for SDIO interconnected eagle low-power WLAN devices"); ++MODULE_LICENSE("GPL"); ++ ++module_init(esp_sdio_init); ++module_exit(esp_sdio_exit); +diff --git a/drivers/net/wireless/esp8089/sip2_common.h b/drivers/net/wireless/esp8089/sip2_common.h +new file mode 100644 +index 000000000000..d46e87589b0b +--- /dev/null ++++ b/drivers/net/wireless/esp8089/sip2_common.h +@@ -0,0 +1,475 @@ ++/* ++ * Copyright (c) 2010 - 2014 Espressif System. ++ * ++ * Common definitions of Serial Interconnctor Protocol ++ * ++ * little endian ++ * ++ * 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 _SIP2_COMMON_H ++#define _SIP2_COMMON_H ++ ++#ifdef __ets__ ++#include "utils.h" ++#endif /*__ets__*/ ++ ++/* max 16 types */ ++typedef enum { ++ SIP_CTRL = 0, ++ SIP_DATA, ++ SIP_DATA_AMPDU ++} SIP_TYPE; ++ ++typedef enum { ++ SIP_TX_CTRL_BUF = 0, /* from host */ ++ SIP_RX_CTRL_BUF, /* to host */ ++ SIP_TX_DATA_BUF, /* from host */ ++ SIP_RX_DATA_BUF /* to host */ ++} SIP_BUF_TYPE; ++ ++enum sip_cmd_id { ++ SIP_CMD_GET_VER = 0, ++ SIP_CMD_WRITE_MEMORY, //1 ROM code ++ SIP_CMD_READ_MEMORY, //2 ++ SIP_CMD_WRITE_REG, //3 ROM code ++ SIP_CMD_READ_REG, //4 ++ SIP_CMD_BOOTUP, //5 ROM code ++ SIP_CMD_COPYBACK, //6 ++ SIP_CMD_INIT, //7 ++ SIP_CMD_SCAN, //8 ++ SIP_CMD_SETKEY, //9 ++ SIP_CMD_CONFIG, //10 ++ SIP_CMD_BSS_INFO_UPDATE, //11 ++ SIP_CMD_LOOPBACK, //12 ROM code ++ //do not add cmd before this line ++ SIP_CMD_SET_WMM_PARAM, ++ SIP_CMD_AMPDU_ACTION, ++ SIP_CMD_HB_REQ, //15 ++ SIP_CMD_RESET_MAC, //16 ++ SIP_CMD_PRE_DOWN, //17 ++ SIP_CMD_SLEEP, /* for sleep testing */ ++ SIP_CMD_WAKEUP, /* for sleep testing */ ++ SIP_CMD_DEBUG, /* for general testing */ ++ SIP_CMD_GET_FW_VER, /* get fw rev. */ ++ SIP_CMD_SETVIF, ++ SIP_CMD_SETSTA, ++ SIP_CMD_PS, ++ SIP_CMD_ATE, ++ SIP_CMD_SUSPEND, ++ SIP_CMD_RECALC_CREDIT, ++ SIP_CMD_MAX, ++}; ++ ++enum { ++ SIP_EVT_TARGET_ON = 0, // ++ SIP_EVT_BOOTUP, //1 in ROM code ++ SIP_EVT_COPYBACK, //2 ++ SIP_EVT_SCAN_RESULT, //3 ++ SIP_EVT_TX_STATUS, //4 ++ SIP_EVT_CREDIT_RPT, //5, in ROM code ++ SIP_EVT_ERROR, //6 ++ SIP_EVT_LOOPBACK, //7, in ROM code ++ SIP_EVT_SNPRINTF_TO_HOST, //8 in ROM code ++ //do not add evt before this line ++ SIP_EVT_HB_ACK, //9 ++ SIP_EVT_RESET_MAC_ACK, //10 ++ SIP_EVT_WAKEUP, //11 /* for sleep testing */ ++ SIP_EVT_DEBUG, //12 /* for general testing */ ++ SIP_EVT_PRINT_TO_HOST, //13 ++ SIP_EVT_TRC_AMPDU, //14 ++ SIP_EVT_ROC, //15 ++ SIP_EVT_RESETTING, ++ SIP_EVT_ATE, ++ SIP_EVT_EP, ++ SIP_EVT_INIT_EP, ++ SIP_EVT_SLEEP, ++ SIP_EVT_TXIDLE, ++ SIP_EVT_NOISEFLOOR, ++ SIP_EVT_MAX ++}; ++ ++#define SIP_IFIDX_MASK 0xf0 ++#define SIP_IFIDX_S 4 ++#define SIP_TYPE_MASK 0x0f ++#define SIP_TYPE_S 0 ++ ++#define SIP_HDR_GET_IFIDX(fc0) (((fc0) & SIP_IFIDX_MASK) >> SIP_IFIDX_S) ++#define SIP_HDR_SET_IFIDX(fc0, ifidx) ( (fc0) = ((fc0) & ~SIP_IFIDX_MASK) | ((ifidx) << SIP_IFIDX_S & SIP_IFIDX_MASK) ) ++#define SIP_HDR_GET_TYPE(fc0) ((fc0) & SIP_TYPE_MASK ) ++/* assume type field is cleared */ ++#define SIP_HDR_SET_TYPE(fc0, type) ((fc0) = ((fc0) & ~ SIP_TYPE_MASK) | ((type) & SIP_TYPE_MASK)) ++ ++/* sip 2.0, not hybrid header so far */ ++#define SIP_HDR_IS_CTRL(hdr) (SIP_HDR_GET_TYPE((hdr)->fc[0]) == SIP_CTRL) ++#define SIP_HDR_IS_DATA(hdr) (SIP_HDR_GET_TYPE((hdr)->fc[0]) == SIP_DATA) ++#define SIP_HDR_IS_AMPDU(hdr) (SIP_HDR_GET_TYPE((hdr)->fc[0]) == SIP_DATA_AMPDU) ++ ++/* fc[1] flags, only for data pkt. Ctrl pkts use fc[1] as eventID */ ++#define SIP_HDR_SET_FLAGS(hdr, flags) ((hdr)->fc[1] |= (flags)) ++#define SIP_HDR_F_MORE_PKT 0x1 ++#define SIP_HDR_F_NEED_CRDT_RPT 0x2 ++#define SIP_HDR_F_SYNC 0x4 ++#define SIP_HDR_F_SYNC_RESET 0x8 ++#define SIP_HDR_F_PM_TURNING_ON 0x10 ++#define SIP_HDR_F_PM_TURNING_OFF 0x20 ++ ++#define SIP_HDR_NEED_CREDIT_UPDATE(hdr) ((hdr)->fc[1] & SIP_HDR_F_NEED_CRDT_RPT) ++#define SIP_HDR_IS_MORE_PKT(hdr) ((hdr)->fc[1] & SIP_HDR_F_MORE_PKT) ++#define SIP_HDR_IS_CRDT_RPT(hdr) ((hdr)->fc[1] & SIP_HDR_F_CRDT_RPT) ++#define SIP_HDR_IS_SYNC(hdr) ((hdr)->fc[1] & SIP_HDR_F_SYNC) ++#define SIP_HDR_IS_SYNC_RESET(hdr) ((hdr)->fc[1] & SIP_HDR_F_SYNC_RESET) ++#define SIP_HDR_IS_SYNC_PKT(hdr) (SIP_HDR_IS_SYNC(hdr) | SIP_HDR_IS_SYNC_RESET(hdr)) ++#define SIP_HDR_SET_SYNC(hdr) SIP_HDR_SET_FLAGS((hdr), SIP_HDR_F_SYNC) ++#define SIP_HDR_SET_SYNC_RESET(hdr) SIP_HDR_SET_FLAGS((hdr), SIP_HDR_F_SYNC_RESET) ++#define SIP_HDR_SET_MORE_PKT(hdr) SIP_HDR_SET_FLAGS((hdr), SIP_HDR_F_MORE_PKT) ++#define SIP_HDR_SET_PM_TURNING_ON(hdr) SIP_HDR_SET_FLAGS((hdr), SIP_HDR_F_PM_TURNING_ON) ++#define SIP_HDR_IS_PM_TURNING_ON(hdr) ((hdr)->fc[1] & SIP_HDR_F_PM_TURNING_ON) ++#define SIP_HDR_SET_PM_TURNING_OFF(hdr) SIP_HDR_SET_FLAGS((hdr), SIP_HDR_F_PM_TURNING_OFF) ++#define SIP_HDR_IS_PM_TURNING_OFF(hdr) ((hdr)->fc[1] & SIP_HDR_F_PM_TURNING_OFF) ++ ++/* ++ * fc[0]: first 4bit: ifidx; last 4bit: type ++ * fc[1]: flags ++ * ++ * Don't touch the header definitons ++ */ ++struct sip_hdr_min { ++ u8 fc[2]; ++ __le16 len; ++} __packed; ++ ++/* not more than 4byte long */ ++struct sip_tx_data_info { ++ u8 tid; ++ u8 ac; ++ u8 p2p:1, enc_flag:7; ++ u8 hw_kid; ++} __packed; ++ ++/* NB: this structure should be not more than 4byte !! */ ++struct sip_tx_info { ++ union { ++ u32 cmdid; ++ struct sip_tx_data_info dinfo; ++ } u; ++} __packed; ++ ++struct sip_hdr { ++ u8 fc[2]; //fc[0]: type and ifidx ; fc[1] is eventID if the first ctrl pkt in the chain. data pkt still can use fc[1] to set flag ++ __le16 len; ++ union { ++ volatile u32 recycled_credits; /* last 12bits is credits, first 20 bits is actual length of the first pkt in the chain */ ++ struct sip_tx_info tx_info; ++ } u; ++ u32 seq; ++} __packed; ++ ++#define h_credits u.recycled_credits ++#define c_evtid fc[1] ++#define c_cmdid u.tx_info.u.cmdid ++#define d_ac u.tx_info.u.dinfo.ac ++#define d_tid u.tx_info.u.dinfo.tid ++#define d_p2p u.tx_info.u.dinfo.p2p ++#define d_enc_flag u.tx_info.u.dinfo.enc_flag ++#define d_hw_kid u.tx_info.u.dinfo.hw_kid ++ ++#define SIP_CREDITS_MASK 0xfff /* last 12 bits */ ++ ++#ifdef HOST_RC ++ ++#define RC_CNT_MASK 0xf ++ ++struct sip_rc_status { ++ u32 rc_map; ++ union { ++ u32 rc_cnt1:4, rc_cnt2:4, rc_cnt3:4, rc_cnt4:4, rc_cnt5:4; ++ ++ u32 rc_cnt_store; ++ }; ++}; ++ ++/* copy from mac80211.h */ ++struct sip_tx_rc { ++ struct ieee80211_tx_rate rates[IEEE80211_TX_MAX_RATES]; ++ s8 rts_cts_rate_idx; ++}; ++#endif /* HOST_RC */ ++ ++#define SIP_HDR_MIN_LEN 4 ++#define SIP_HDR_LEN sizeof(struct sip_hdr) ++#define SIP_CTRL_HDR_LEN SIP_HDR_LEN /* same as sip_hdr in sip2 design */ ++#define SIP_BOOT_BUF_SIZE 256 ++#define SIP_CTRL_BUF_SZ 256 /* too much?? */ ++#define SIP_CTRL_BUF_N 6 ++#define SIP_CTRL_TXBUF_N 2 ++#define SIP_CTRL_RXBUF_N 4 ++ ++/* WAR for mblk */ ++#define SIP_RX_ADDR_PREFIX_MASK 0xfc000000 ++#define SIP_RX_ADDR_SHIFT 6 /* [31:5], shift 6 bits */ ++ ++struct sip_cmd_write_memory { ++ u32 addr; ++ u32 len; ++} __packed; ++ ++struct sip_cmd_read_memory { ++ u32 addr; ++ u32 len; ++} __packed; ++ ++struct sip_cmd_write_reg { ++ u32 addr; ++ u32 val; ++} __packed; ++ ++struct sip_cmd_bootup { ++ u32 boot_addr; ++} __packed; ++ ++struct sip_cmd_loopback { ++ u32 txlen; //host to target packet len, 0 means no txpacket ++ u32 rxlen; //target to host packet len, 0 means no rxpacket ++ u32 pack_id; //sequence of packet ++} __packed; ++ ++struct sip_evt_loopback { ++ u32 txlen; //host to target packet len, 0 means no txpacket ++ u32 rxlen; //target to host packet len, 0 means no rxpacket ++ u32 pack_id; //sequence of packet ++} __packed; ++ ++struct sip_cmd_copyback { ++ u32 addr; ++ u32 len; ++} __packed; ++ ++struct sip_cmd_scan { ++// u8 ssid[32]; ++ u8 ssid_len; ++// u8 hw_channel[14]; ++ u8 n_channels; ++ u8 ie_len; ++ u8 aborted; ++} __packed; // ie[] append at the end ++ ++ ++#ifndef ETH_ALEN ++#define ETH_ALEN 6 ++#endif /* ETH_ALEN */ ++ ++struct sip_cmd_setkey { ++ u8 bssid_no; ++ u8 addr[ETH_ALEN]; ++ u8 alg; ++ u8 keyidx; ++ u8 hw_key_idx; ++ u8 flags; ++ u8 keylen; ++ u8 key[32]; ++} __packed; ++ ++struct sip_cmd_config { ++ u16 center_freq; ++ u16 duration; ++} __packed; ++ ++struct sip_cmd_bss_info_update { ++ u8 bssid[ETH_ALEN]; ++ u16 isassoc; ++ u32 beacon_int; ++ u8 bssid_no; ++} __packed; ++ ++struct sip_evt_bootup { ++ u16 tx_blksz; ++ u8 mac_addr[ETH_ALEN]; ++ /* anything else ? */ ++} __packed; ++ ++struct sip_cmd_setvif { ++ u8 index; ++ u8 mac[ETH_ALEN]; ++ u8 set; ++ u8 op_mode; ++ u8 is_p2p; ++} __packed; ++ ++enum esp_ieee80211_phytype { ++ ESP_IEEE80211_T_CCK = 0, ++ ESP_IEEE80211_T_OFDM = 1, ++ ESP_IEEE80211_T_HT20_L = 2, ++ ESP_IEEE80211_T_HT20_S = 3, ++}; ++ ++struct sip_cmd_setsta { ++ u8 ifidx; ++ u8 index; ++ u8 set; ++ u8 phymode; ++ u8 mac[ETH_ALEN]; ++ u16 aid; ++ u8 ampdu_factor; ++ u8 ampdu_density; ++ u16 resv; ++} __packed; ++ ++struct sip_cmd_ps { ++ u8 dtim_period; ++ u8 max_sleep_period; ++ u8 on; ++ u8 resv; ++} __packed; ++ ++struct sip_cmd_suspend { ++ u8 suspend; ++ u8 resv[3]; ++} __packed; ++ ++#define SIP_DUMP_RPBM_ERR BIT(0) ++#define SIP_RXABORT_FIXED BIT(1) ++#define SIP_SUPPORT_BGSCAN BIT(2) ++struct sip_evt_bootup2 { ++ u16 tx_blksz; ++ u8 mac_addr[ETH_ALEN]; ++ u16 rx_blksz; ++ u8 credit_to_reserve; ++ u8 options; ++ s16 noise_floor; ++ u8 resv[2]; ++ /* anything else ? */ ++} __packed; ++ ++typedef enum { ++ TRC_TX_AMPDU_STOPPED = 1, ++ TRC_TX_AMPDU_OPERATIONAL, ++ TRC_TX_AMPDU_WAIT_STOP, ++ TRC_TX_AMPDU_WAIT_OPERATIONAL, ++ TRC_TX_AMPDU_START, ++} trc_ampdu_state_t; ++ ++struct sip_evt_trc_ampdu { ++ u8 state; ++ u8 tid; ++ u8 addr[ETH_ALEN]; ++} __packed; ++ ++struct sip_cmd_set_wmm_params { ++ u8 aci; ++ u8 aifs; ++ u8 ecw_min; ++ u8 ecw_max; ++ u16 txop_us; ++} __packed; ++ ++#define SIP_AMPDU_RX_START 0 ++#define SIP_AMPDU_RX_STOP 1 ++#define SIP_AMPDU_TX_OPERATIONAL 2 ++#define SIP_AMPDU_TX_STOP 3 ++struct sip_cmd_ampdu_action { ++ u8 action; ++ u8 index; ++ u8 tid; ++ u8 win_size; ++ u16 ssn; ++ u8 addr[ETH_ALEN]; ++} __packed; ++ ++#define SIP_TX_ST_OK 0 ++#define SIP_TX_ST_NOEB 1 ++#define SIP_TX_ST_ACKTO 2 ++#define SIP_TX_ST_ENCERR 3 ++ ++//NB: sip_tx_status must be 4 bytes aligned ++struct sip_tx_status { ++ u32 sip_seq; ++#ifdef HOST_RC ++ struct sip_rc_status rcstatus; ++#endif /* HOST_RC */ ++ u8 errno; /* success or failure code */ ++ u8 rate_index; ++ char ack_signal; ++ u8 pad; ++} __packed; ++ ++struct sip_evt_tx_report { ++ u32 pkts; ++ struct sip_tx_status status[0]; ++} __packed; ++ ++struct sip_evt_tx_mblk { ++ u32 mblk_map; ++} __packed; ++ ++struct sip_evt_scan_report { ++ u16 scan_id; ++ u16 aborted; ++} __packed; ++ ++struct sip_evt_roc { ++ u16 state; //start:1, end :0 ++ u16 is_ok; ++} __packed; ++ ++struct sip_evt_txidle { ++ u32 last_seq; ++} __packed; ++ ++struct sip_evt_noisefloor { ++ s16 noise_floor; ++ u16 pad; ++} __packed; ++/* ++ * for mblk direct memory access, no need for sip_hdr. tx: first 2k for contrl msg, ++ * rest of 14k for data. rx, same. ++ */ ++#ifdef TEST_MODE ++ ++struct sip_cmd_sleep { ++ u32 sleep_mode; ++ u32 sleep_tm_ms; ++ u32 wakeup_tm_ms; //zero: after receive bcn, then sleep, nozero: delay nozero ms to sleep ++ u32 sleep_times; //zero: always sleep, nozero: after nozero number sleep/wakeup, then end up sleep ++} __packed; ++ ++struct sip_cmd_wakeup { ++ u32 check_data; //0:copy to event ++} __packed; ++ ++struct sip_evt_wakeup { ++ u32 check_data; ++} __packed; ++ ++//general debug command ++struct sip_cmd_debug { ++ u32 cmd_type; ++ u32 para_num; ++ u32 para[10]; ++} __packed; ++ ++struct sip_evt_debug { ++ u16 len; ++ u32 results[12]; ++ u16 pad; ++} __packed; ++ ++struct sip_cmd_ate { ++ //u8 len; ++ u8 cmdstr[0]; ++} __packed; ++ ++ ++ ++#endif //ifdef TEST_MODE ++ ++#endif /* _SIP_COMMON_H_ */ +diff --git a/drivers/net/wireless/esp8089/slc_host_register.h b/drivers/net/wireless/esp8089/slc_host_register.h +new file mode 100644 +index 000000000000..2cdb2c856d15 +--- /dev/null ++++ b/drivers/net/wireless/esp8089/slc_host_register.h +@@ -0,0 +1,271 @@ ++//Generated at 2012-10-23 20:11:08 ++/* ++ * Copyright (c) 2011 Espressif System ++ * ++ * 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 SLC_HOST_REGISTER_H_INCLUDED ++#define SLC_HOST_REGISTER_H_INCLUDED ++ ++/* #define REG_SLC_HOST_BASE 0x00000000 */ ++/* skip the token1, since reading it will clean the credit */ ++#define REG_SLC_HOST_BASE 0x00000000 ++#define REG_SLC_BASE 0x00000000 ++ ++ ++#define SLC_HOST_PF (REG_SLC_HOST_BASE + 0x0) ++#define SLC_HOST_TOKEN_RDATA (REG_SLC_HOST_BASE + 0x4) ++#define SLC_HOST_RX_PF_EOF 0x0000000F ++#define SLC_HOST_RX_PF_EOF_S 28 ++#define SLC_HOST_TOKEN1 0x00000FFF ++#define SLC_HOST_TOKEN1_S 16 ++#define SLC_HOST_RX_PF_VALID (BIT(15)) ++#define SLC_HOST_TOKEN0 0x00000FFF ++#define SLC_HOST_TOKEN0_S 0 ++ ++#define SLC_HOST_TOKEN0_MASK SLC_HOST_TOKEN0 ++ ++#define SLC_HOST_INT_RAW (REG_SLC_HOST_BASE + 0x8) ++#define SLC_HOST_EXT_BIT3_INT_RAW (BIT(22)) ++#define SLC_HOST_EXT_BIT2_INT_RAW (BIT(21)) ++#define SLC_HOST_EXT_BIT1_INT_RAW (BIT(20)) ++#define SLC_HOST_RXFIFO_NOT_EMPTY_INT_RAW (BIT(19)) ++#define SLC_HOST_RX_PF_VALID_INT_RAW (BIT(18)) ++#define SLC_HOST_TX_OVF_INT_RAW (BIT(17)) ++#define SLC_HOST_RX_UDF_INT_RAW (BIT(16)) ++#define SLC_HOST_TX_START_INT_RAW (BIT(15)) ++#define SLC_HOST_RX_START_INT_RAW (BIT(14)) ++#define SLC_HOST_RX_EOF_INT_RAW (BIT(13)) ++#define SLC_HOST_RX_SOF_INT_RAW (BIT(12)) ++#define SLC_HOST_TOKEN1_0TO1_INT_RAW (BIT(11)) ++#define SLC_HOST_TOKEN0_0TO1_INT_RAW (BIT(10)) ++#define SLC_HOST_TOKEN1_1TO0_INT_RAW (BIT(9)) ++#define SLC_HOST_TOKEN0_1TO0_INT_RAW (BIT(8)) ++#define SLC_HOST_TOHOST_BIT7_INT_RAW (BIT(7)) ++#define SLC_HOST_TOHOST_BIT6_INT_RAW (BIT(6)) ++#define SLC_HOST_TOHOST_BIT5_INT_RAW (BIT(5)) ++#define SLC_HOST_TOHOST_BIT4_INT_RAW (BIT(4)) ++#define SLC_HOST_TOHOST_BIT3_INT_RAW (BIT(3)) ++#define SLC_HOST_TOHOST_BIT2_INT_RAW (BIT(2)) ++#define SLC_HOST_TOHOST_BIT1_INT_RAW (BIT(1)) ++#define SLC_HOST_TOHOST_BIT0_INT_RAW (BIT(0)) ++ ++#define SLC_HOST_STATE_W0 (REG_SLC_HOST_BASE + 0xC) ++#define SLC_HOST_STATE3 0x000000FF ++#define SLC_HOST_STATE3_S 24 ++#define SLC_HOST_STATE2 0x000000FF ++#define SLC_HOST_STATE2_S 16 ++#define SLC_HOST_STATE1 0x000000FF ++#define SLC_HOST_STATE1_S 8 ++#define SLC_HOST_STATE0 0x000000FF ++#define SLC_HOST_STATE0_S 0 ++ ++#define SLC_HOST_STATE_W1 (REG_SLC_HOST_BASE + 0x10) ++#define SLC_HOST_STATE7 0x000000FF ++#define SLC_HOST_STATE7_S 24 ++#define SLC_HOST_STATE6 0x000000FF ++#define SLC_HOST_STATE6_S 16 ++#define SLC_HOST_STATE5 0x000000FF ++#define SLC_HOST_STATE5_S 8 ++#define SLC_HOST_STATE4 0x000000FF ++#define SLC_HOST_STATE4_S 0 ++ ++#define SLC_HOST_CONF_W0 (REG_SLC_HOST_BASE + 0x14) ++#define SLC_HOST_CONF3 0x000000FF ++#define SLC_HOST_CONF3_S 24 ++#define SLC_HOST_CONF2 0x000000FF ++#define SLC_HOST_CONF2_S 16 ++#define SLC_HOST_CONF1 0x000000FF ++#define SLC_HOST_CONF1_S 8 ++#define SLC_HOST_CONF0 0x000000FF ++#define SLC_HOST_CONF0_S 0 ++ ++#define SLC_HOST_CONF_W1 (REG_SLC_HOST_BASE + 0x18) ++#define SLC_HOST_CONF7 0x000000FF ++#define SLC_HOST_CONF7_S 24 ++#define SLC_HOST_CONF6 0x000000FF ++#define SLC_HOST_CONF6_S 16 ++#define SLC_HOST_CONF5 0x000000FF ++#define SLC_HOST_CONF5_S 8 ++#define SLC_HOST_CONF4 0x000000FF ++#define SLC_HOST_CONF4_S 0 ++ ++#define SLC_HOST_INT_ST (REG_SLC_HOST_BASE + 0x1C) ++#define SLC_HOST_RX_ST (BIT(23)) ++#define SLC_HOST_EXT_BIT3_INT_ST (BIT(22)) ++#define SLC_HOST_EXT_BIT2_INT_ST (BIT(21)) ++#define SLC_HOST_EXT_BIT1_INT_ST (BIT(20)) ++#define SLC_HOST_RXFIFO_NOT_EMPTY_INT_ST (BIT(19)) ++#define SLC_HOST_RX_PF_VALID_INT_ST (BIT(18)) ++#define SLC_HOST_TX_OVF_INT_ST (BIT(17)) ++#define SLC_HOST_RX_UDF_INT_ST (BIT(16)) ++#define SLC_HOST_TX_START_INT_ST (BIT(15)) ++#define SLC_HOST_RX_START_INT_ST (BIT(14)) ++#define SLC_HOST_RX_EOF_INT_ST (BIT(13)) ++#define SLC_HOST_RX_SOF_INT_ST (BIT(12)) ++#define SLC_HOST_TOKEN1_0TO1_INT_ST (BIT(11)) ++#define SLC_HOST_TOKEN0_0TO1_INT_ST (BIT(10)) ++#define SLC_HOST_TOKEN1_1TO0_INT_ST (BIT(9)) ++#define SLC_HOST_TOKEN0_1TO0_INT_ST (BIT(8)) ++#define SLC_HOST_TOHOST_BIT7_INT_ST (BIT(7)) ++#define SLC_HOST_TOHOST_BIT6_INT_ST (BIT(6)) ++#define SLC_HOST_TOHOST_BIT5_INT_ST (BIT(5)) ++#define SLC_HOST_TOHOST_BIT4_INT_ST (BIT(4)) ++#define SLC_HOST_TOHOST_BIT3_INT_ST (BIT(3)) ++#define SLC_HOST_TOHOST_BIT2_INT_ST (BIT(2)) ++#define SLC_HOST_TOHOST_BIT1_INT_ST (BIT(1)) ++#define SLC_HOST_TOHOST_BIT0_INT_ST (BIT(0)) ++ ++#define SLC_HOST_CONF_W2 (REG_SLC_HOST_BASE + 0x20) ++#define SLC_HOST_CONF11 0x000000FF ++#define SLC_HOST_CONF11_S 24 ++#define SLC_HOST_CONF10 0x000000FF ++#define SLC_HOST_CONF10_S 16 ++#define SLC_HOST_CONF9 0x000000FF ++#define SLC_HOST_CONF9_S 8 ++#define SLC_HOST_CONF8 0x000000FF ++#define SLC_HOST_CONF8_S 0 ++ ++#define SLC_HOST_CONF_W3 (REG_SLC_HOST_BASE + 0x24) ++#define SLC_HOST_CONF15 0x000000FF ++#define SLC_HOST_CONF15_S 24 ++#define SLC_HOST_CONF14 0x000000FF ++#define SLC_HOST_CONF14_S 16 ++#define SLC_HOST_CONF13 0x000000FF ++#define SLC_HOST_CONF13_S 8 ++#define SLC_HOST_CONF12 0x000000FF ++#define SLC_HOST_CONF12_S 0 ++ ++#define SLC_HOST_GEN_TXDONE_INT BIT(16) ++#define SLC_HOST_GEN_RXDONE_INT BIT(17) ++ ++#define SLC_HOST_CONF_W4 (REG_SLC_HOST_BASE + 0x28) ++#define SLC_HOST_CONF19 0x000000FF ++#define SLC_HOST_CONF19_S 24 ++#define SLC_HOST_CONF18 0x000000FF ++#define SLC_HOST_CONF18_S 16 ++#define SLC_HOST_CONF17 0x000000FF ++#define SLC_HOST_CONF17_S 8 ++#define SLC_HOST_CONF16 0x000000FF ++#define SLC_HOST_CONF16_S 0 ++ ++#define SLC_HOST_TOKEN_WDATA (REG_SLC_HOST_BASE + 0x2C) ++#define SLC_HOST_TOKEN1_WD 0x00000FFF ++#define SLC_HOST_TOKEN1_WD_S 16 ++#define SLC_HOST_TOKEN0_WD 0x00000FFF ++#define SLC_HOST_TOKEN0_WD_S 0 ++ ++#define SLC_HOST_INT_CLR (REG_SLC_HOST_BASE + 0x30) ++#define SLC_HOST_TOKEN1_WR (BIT(31)) ++#define SLC_HOST_TOKEN0_WR (BIT(30)) ++#define SLC_HOST_TOKEN1_DEC (BIT(29)) ++#define SLC_HOST_TOKEN0_DEC (BIT(28)) ++#define SLC_HOST_EXT_BIT3_INT_CLR (BIT(22)) ++#define SLC_HOST_EXT_BIT2_INT_CLR (BIT(21)) ++#define SLC_HOST_EXT_BIT1_INT_CLR (BIT(20)) ++#define SLC_HOST_EXT_BIT0_INT_CLR (BIT(19)) ++#define SLC_HOST_RX_PF_VALID_INT_CLR (BIT(18)) ++#define SLC_HOST_TX_OVF_INT_CLR (BIT(17)) ++#define SLC_HOST_RX_UDF_INT_CLR (BIT(16)) ++#define SLC_HOST_TX_START_INT_CLR (BIT(15)) ++#define SLC_HOST_RX_START_INT_CLR (BIT(14)) ++#define SLC_HOST_RX_EOF_INT_CLR (BIT(13)) ++#define SLC_HOST_RX_SOF_INT_CLR (BIT(12)) ++#define SLC_HOST_TOKEN1_0TO1_INT_CLR (BIT(11)) ++#define SLC_HOST_TOKEN0_0TO1_INT_CLR (BIT(10)) ++#define SLC_HOST_TOKEN1_1TO0_INT_CLR (BIT(9)) ++#define SLC_HOST_TOKEN0_1TO0_INT_CLR (BIT(8)) ++#define SLC_HOST_TOHOST_BIT7_INT_CLR (BIT(7)) ++#define SLC_HOST_TOHOST_BIT6_INT_CLR (BIT(6)) ++#define SLC_HOST_TOHOST_BIT5_INT_CLR (BIT(5)) ++#define SLC_HOST_TOHOST_BIT4_INT_CLR (BIT(4)) ++#define SLC_HOST_TOHOST_BIT3_INT_CLR (BIT(3)) ++#define SLC_HOST_TOHOST_BIT2_INT_CLR (BIT(2)) ++#define SLC_HOST_TOHOST_BIT1_INT_CLR (BIT(1)) ++#define SLC_HOST_TOHOST_BIT0_INT_CLR (BIT(0)) ++ ++#define SLC_HOST_INT_ENA (REG_SLC_HOST_BASE + 0x34) ++#define SLC_HOST_EXT_BIT3_INT_ENA (BIT(22)) ++#define SLC_HOST_EXT_BIT2_INT_ENA (BIT(21)) ++#define SLC_HOST_EXT_BIT1_INT_ENA (BIT(20)) ++#define SLC_HOST_EXT_BIT0_INT_ENA (BIT(19)) ++#define SLC_HOST_RX_PF_VALID_INT_ENA (BIT(18)) ++#define SLC_HOST_TX_OVF_INT_ENA (BIT(17)) ++#define SLC_HOST_RX_UDF_INT_ENA (BIT(16)) ++#define SLC_HOST_TX_START_INT_ENA (BIT(15)) ++#define SLC_HOST_RX_START_INT_ENA (BIT(14)) ++#define SLC_HOST_RX_EOF_INT_ENA (BIT(13)) ++#define SLC_HOST_RX_SOF_INT_ENA (BIT(12)) ++#define SLC_HOST_TOKEN1_0TO1_INT_ENA (BIT(11)) ++#define SLC_HOST_TOKEN0_0TO1_INT_ENA (BIT(10)) ++#define SLC_HOST_TOKEN1_1TO0_INT_ENA (BIT(9)) ++#define SLC_HOST_TOKEN0_1TO0_INT_ENA (BIT(8)) ++#define SLC_HOST_TOHOST_BIT7_INT_ENA (BIT(7)) ++#define SLC_HOST_TOHOST_BIT6_INT_ENA (BIT(6)) ++#define SLC_HOST_TOHOST_BIT5_INT_ENA (BIT(5)) ++#define SLC_HOST_TOHOST_BIT4_INT_ENA (BIT(4)) ++#define SLC_HOST_TOHOST_BIT3_INT_ENA (BIT(3)) ++#define SLC_HOST_TOHOST_BIT2_INT_ENA (BIT(2)) ++#define SLC_HOST_TOHOST_BIT1_INT_ENA (BIT(1)) ++#define SLC_HOST_TOHOST_BIT0_INT_ENA (BIT(0)) ++ ++#define SLC_HOST_CONF_W5 (REG_SLC_HOST_BASE + 0x3C) ++#define SLC_HOST_CONF23 0x000000FF ++#define SLC_HOST_CONF23_S 24 ++#define SLC_HOST_CONF22 0x000000FF ++#define SLC_HOST_CONF22_S 16 ++#define SLC_HOST_CONF21 0x000000FF ++#define SLC_HOST_CONF21_S 8 ++#define SLC_HOST_CONF20 0x000000FF ++#define SLC_HOST_CONF20_S 0 ++ ++#define SLC_HOST_WIN_CMD (REG_SLC_HOST_BASE + 0x40) ++ ++ ++#define SLC_HOST_DATE (REG_SLC_HOST_BASE + 0x78) ++#define SLC_HOST_ID (REG_SLC_HOST_BASE + 0x7C) ++ ++#define SLC_ADDR_WINDOW_CLEAR_MASK (~(0xf<<12)) ++#define SLC_FROM_HOST_ADDR_WINDOW (0x1<<12) ++#define SLC_TO_HOST_ADDR_WINDOW (0x3<<12) ++ ++#define SLC_SET_FROM_HOST_ADDR_WINDOW(v) do { \ ++ (v) &= 0xffff; \ ++ (v) &= SLC_ADDR_WINDOW_CLEAR_MASK; \ ++ (v) |= SLC_FROM_HOST_ADDR_WINDOW; \ ++} while (0); ++ ++#define SLC_SET_TO_HOST_ADDR_WINDOW(v) do { \ ++ (v) &= 0xffff; \ ++ (v) &= SLC_ADDR_WINDOW_CLEAR_MASK; \ ++ (v) |= SLC_TO_HOST_ADDR_WINDOW; \ ++} while (0); ++ ++#define SLC_INT_ENA (REG_SLC_BASE + 0xC) ++#define SLC_RX_EOF_INT_ENA BIT(17) ++#define SLC_FRHOST_BIT2_INT_ENA BIT(2) ++ ++#define SLC_RX_LINK (REG_SLC_BASE + 0x24) ++#define SLC_RXLINK_START BIT(29) ++ ++#define SLC_BRIDGE_CONF (REG_SLC_BASE + 0x44) ++#define SLC_TX_PUSH_IDLE_NUM 0xFFFF ++#define SLC_TX_PUSH_IDLE_NUM_S 16 ++#define SLC_HDA_MAP_128K BIT(13) ++#define SLC_TX_DUMMY_MODE BIT(12) ++#define SLC_FIFO_MAP_ENA 0x0000000F ++#define SLC_FIFO_MAP_ENA_S 8 ++#define SLC_TXEOF_ENA 0x0000003F ++#define SLC_TXEOF_ENA_S ++ ++ ++#endif // SLC_HOST_REGISTER_H_INCLUDED +-- +2.34.1 diff --git a/projects/ArchR/devices/RK3326/patches/linux/009-esp8089-fix-debug-stubs.patch b/projects/ArchR/devices/RK3326/patches/linux/009-esp8089-fix-debug-stubs.patch new file mode 100644 index 0000000000..f695596627 --- /dev/null +++ b/projects/ArchR/devices/RK3326/patches/linux/009-esp8089-fix-debug-stubs.patch @@ -0,0 +1,36 @@ +From: ArchR +Subject: [PATCH] esp8089: fix conflicting types in debug stubs for kernel 6.12+ + +The non-debugfs stubs returned struct dentry* while the real functions +returned void, causing build failure with GCC 15. + +--- a/drivers/net/wireless/esp8089/esp_debug.c ++++ b/drivers/net/wireless/esp8089/esp_debug.c +@@ -186,21 +186,21 @@ + + #else + +-inline struct dentry *esp_dump_var(const char *name, struct dentry *parent, ++inline void esp_dump_var(const char *name, struct dentry *parent, + void *value, esp_type type) + { +- return NULL; ++ return; + } + +-inline struct dentry *esp_dump_array(const char *name, ++inline void esp_dump_array(const char *name, + struct dentry *parent, + struct debugfs_blob_wrapper *blob) + { +- return NULL; ++ return; + } + +-inline struct dentry *esp_dump(const char *name, struct dentry *parent, ++inline void esp_dump(const char *name, struct dentry *parent, + void *data, int size) + { +- return NULL; ++ return; + } diff --git a/projects/ArchR/devices/RK3326/patches/linux/010-rk817-battery-calibration.patch b/projects/ArchR/devices/RK3326/patches/linux/010-rk817-battery-calibration.patch new file mode 100644 index 0000000000..5eb79a3dde --- /dev/null +++ b/projects/ArchR/devices/RK3326/patches/linux/010-rk817-battery-calibration.patch @@ -0,0 +1,160 @@ +--- a/drivers/power/supply/rk817_charger.c 2026-04-02 16:24:36.709878954 -0300 ++++ b/drivers/power/supply/rk817_charger.c 2026-04-02 16:24:36.710727282 -0300 +@@ -240,9 +240,27 @@ + static int rk817_bat_calib_cap(struct rk817_charger *charger) + { + struct rk808 *rk808 = charger->rk808; +- int tmp, charge_now, charge_now_adc, volt_avg; ++ int charge_now, charge_now_adc; + u8 bulk_reg[4]; + ++ /* Don't do anything if there's no battery. */ ++ if (!charger->battery_present) ++ return 0; ++ ++ /* ++ * When resuming from suspend, sometimes the voltage value would be ++ * incorrect. Do not do any sort of calibration activity when the ++ * reported value is incorrect. Use 2.7v as the sanity value because ++ * per the datasheet the PMIC can in no way support a battery voltage ++ * lower than this, and 4.45v as the upper bound. ++ */ ++ if ((charger->volt_avg_uv < 2700000) || (charger->volt_avg_uv > 4450000)) { ++ dev_dbg(charger->dev, ++ "Battery voltage of %d is invalid, ignoring.\n", ++ charger->volt_avg_uv); ++ return -EINVAL; ++ } ++ + /* Calibrate the soc and fcc on a fully charged battery */ + + if (charger->charge_status == CHARGE_FINISH && (!charger->soc_cal)) { +@@ -304,51 +322,6 @@ + } + } + +- /* +- * Calibrate the fully charged capacity when we previously had a full +- * battery (soc_cal = 1) and are now empty (at or below minimum design +- * voltage). If our columb counter is still positive, subtract that +- * from our fcc value to get a calibrated fcc, and if our columb +- * counter is negative add that to our fcc (but not to exceed our +- * design capacity). +- */ +- regmap_bulk_read(charger->rk808->regmap, RK817_GAS_GAUGE_BAT_VOL_H, +- bulk_reg, 2); +- tmp = get_unaligned_be16(bulk_reg); +- volt_avg = (charger->voltage_k * tmp) + 1000 * charger->voltage_b; +- if (volt_avg <= charger->bat_voltage_min_design_uv && +- charger->soc_cal) { +- regmap_bulk_read(rk808->regmap, RK817_GAS_GAUGE_Q_PRES_H3, +- bulk_reg, 4); +- charge_now_adc = get_unaligned_be32(bulk_reg); +- charge_now = ADC_TO_CHARGE_UAH(charge_now_adc, +- charger->res_div); +- /* +- * Note, if charge_now is negative this will add it (what we +- * want) and if it's positive this will subtract (also what +- * we want). +- */ +- charger->fcc_mah = charger->fcc_mah - (charge_now / 1000); +- +- dev_dbg(charger->dev, +- "Recalibrating full charge capacity to %d uah\n", +- charger->fcc_mah * 1000); +- } +- +- /* +- * Set the SOC to 0 if we are below the minimum system voltage. +- */ +- if (volt_avg <= charger->bat_voltage_min_design_uv) { +- charger->soc = 0; +- charge_now_adc = CHARGE_TO_ADC(0, charger->res_div); +- put_unaligned_be32(charge_now_adc, bulk_reg); +- regmap_bulk_write(rk808->regmap, +- RK817_GAS_GAUGE_Q_INIT_H3, bulk_reg, 4); +- dev_warn(charger->dev, +- "Battery voltage %d below minimum voltage %d\n", +- volt_avg, charger->bat_voltage_min_design_uv); +- } +- + rk817_record_battery_nvram_values(charger); + + return 0; +@@ -648,6 +621,24 @@ + return IRQ_HANDLED; + } + ++static int rk817_bat_set_prop(struct power_supply *ps, ++ enum power_supply_property prop, ++ const union power_supply_propval *val) ++{ ++ struct rk817_charger *charger = power_supply_get_drvdata(ps); ++ ++ switch (prop) { ++ case POWER_SUPPLY_PROP_CHARGE_FULL: ++ if ((val->intval < 500000) || ++ (val->intval > charger->bat_charge_full_design_uah)) ++ return -EINVAL; ++ charger->fcc_mah = val->intval / 1000; ++ return rk817_bat_calib_cap(charger); ++ default: ++ return -EINVAL; ++ } ++} ++ + static enum power_supply_property rk817_bat_props[] = { + POWER_SUPPLY_PROP_PRESENT, + POWER_SUPPLY_PROP_STATUS, +@@ -673,12 +664,25 @@ + POWER_SUPPLY_PROP_VOLTAGE_AVG, + }; + ++static int rk817_bat_prop_writeable(struct power_supply *psy, ++ enum power_supply_property psp) ++{ ++ switch (psp) { ++ case POWER_SUPPLY_PROP_CHARGE_FULL: ++ return 1; ++ default: ++ return 0; ++ } ++} ++ + static const struct power_supply_desc rk817_bat_desc = { +- .name = "rk817-battery", ++ .name = "battery", + .type = POWER_SUPPLY_TYPE_BATTERY, + .properties = rk817_bat_props, ++ .property_is_writeable = rk817_bat_prop_writeable, + .num_properties = ARRAY_SIZE(rk817_bat_props), + .get_property = rk817_bat_get_prop, ++ .set_property = rk817_bat_set_prop, + }; + + static const struct power_supply_desc rk817_chg_desc = { +@@ -1202,6 +1206,15 @@ + return 0; + } + ++static int __maybe_unused rk817_suspend(struct device *dev) ++{ ++ struct rk817_charger *charger = dev_get_drvdata(dev); ++ ++ cancel_delayed_work_sync(&charger->work); ++ ++ return 0; ++} ++ + static int __maybe_unused rk817_resume(struct device *dev) + { + +@@ -1213,7 +1226,7 @@ + return 0; + } + +-static SIMPLE_DEV_PM_OPS(rk817_charger_pm, NULL, rk817_resume); ++static SIMPLE_DEV_PM_OPS(rk817_charger_pm, rk817_suspend, rk817_resume); + + static struct platform_driver rk817_charger_driver = { + .probe = rk817_charger_probe, diff --git a/projects/ArchR/devices/RK3326/patches/linux/020-elida-refresh-rates.patch b/projects/ArchR/devices/RK3326/patches/linux/020-elida-refresh-rates.patch new file mode 100644 index 0000000000..b96e429792 --- /dev/null +++ b/projects/ArchR/devices/RK3326/patches/linux/020-elida-refresh-rates.patch @@ -0,0 +1,79 @@ +diff --git a/drivers/gpu/drm/panel/panel-elida-kd35t133.c b/drivers/gpu/drm/panel/panel-elida-kd35t133.c +index b904d5437444..abbeb18eb6b4 100644 +--- a/drivers/gpu/drm/panel/panel-elida-kd35t133.c ++++ b/drivers/gpu/drm/panel/panel-elida-kd35t133.c +@@ -148,7 +148,8 @@ static int kd35t133_prepare(struct drm_panel *panel) + return dsi_ctx.accum_err; + } + +-static const struct drm_display_mode default_mode = { ++/* drm_display_mode template without clock as it is variable */ ++static const struct drm_display_mode mode_template = { + .hdisplay = 320, + .hsync_start = 320 + 130, + .hsync_end = 320 + 130 + 4, +@@ -157,33 +158,49 @@ static const struct drm_display_mode default_mode = { + .vsync_start = 480 + 2, + .vsync_end = 480 + 2 + 1, + .vtotal = 480 + 2 + 1 + 2, +- .clock = 17000, + .width_mm = 42, + .height_mm = 82, + }; + ++static const int pixel_clocks[] = { ++ 14118, /* 49.84 Hz PAL everything */ ++ 15545, /* 54.88 Hz Arcade: Midway, Toaplan, R-Type */ ++ 16300, /* 57.50 Hz Arcade: Toaplan, more? */ ++ 16900, /* 59.7 Hz GB/GBC/GBA */ ++ 17000, /* 60 Hz everything */ ++ 21375, /* 75.47 Hz Wonderswan(Color) */ ++}; ++ + static int kd35t133_get_modes(struct drm_panel *panel, + struct drm_connector *connector) + { + struct kd35t133 *ctx = panel_to_kd35t133(panel); ++ struct drm_display_mode mode_tmp; + struct drm_display_mode *mode; + +- mode = drm_mode_duplicate(connector->dev, &default_mode); +- if (!mode) { +- dev_err(ctx->dev, "Failed to add mode %ux%u@%u\n", +- default_mode.hdisplay, default_mode.vdisplay, +- drm_mode_vrefresh(&default_mode)); +- return -ENOMEM; ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(pixel_clocks); i++) { ++ mode_tmp = mode_template; ++ mode_tmp.clock = pixel_clocks[i]; ++ mode = drm_mode_duplicate(connector->dev, &mode_tmp); ++ if (!mode) { ++ dev_err(ctx->dev, "Failed to add mode %u\n", ++ drm_mode_vrefresh(mode)); ++ return -ENOMEM; ++ } ++ drm_mode_set_name(mode); ++ ++ mode->type = DRM_MODE_TYPE_DRIVER; ++ if (i == 4) ++ mode->type |= DRM_MODE_TYPE_PREFERRED; ++ ++ drm_mode_probed_add(connector, mode); ++ connector->display_info.width_mm = mode->width_mm; ++ connector->display_info.height_mm = mode->height_mm; + } + +- drm_mode_set_name(mode); +- +- mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; +- connector->display_info.width_mm = mode->width_mm; +- connector->display_info.height_mm = mode->height_mm; +- drm_mode_probed_add(connector, mode); +- +- return 1; ++ return ARRAY_SIZE(pixel_clocks); + } + + static enum drm_panel_orientation kd35t133_get_orientation(struct drm_panel *panel) diff --git a/projects/ArchR/devices/RK3326/patches/linux/022-usb-role-switch.patch b/projects/ArchR/devices/RK3326/patches/linux/022-usb-role-switch.patch new file mode 100644 index 0000000000..2231cc94ed --- /dev/null +++ b/projects/ArchR/devices/RK3326/patches/linux/022-usb-role-switch.patch @@ -0,0 +1,11 @@ +--- linux-6.11.9/arch/arm64/boot/dts/rockchip/px30.dtsi.orig 2024-11-29 21:08:01.000962112 +0000 ++++ linux-6.11.9/arch/arm64/boot/dts/rockchip/px30.dtsi 2024-11-29 20:20:01.012069647 +0000 +@@ -950,6 +950,8 @@ + clocks = <&cru HCLK_OTG>; + clock-names = "otg"; + dr_mode = "otg"; ++ usb-role-switch; ++ role-switch-default-mode = "host"; + g-np-tx-fifo-size = <16>; + g-rx-fifo-size = <280>; + g-tx-fifo-size = <256 128 128 64 32 16>; diff --git a/projects/ArchR/devices/RK3326/patches/mali-bifrost/001-single-regulator.patch b/projects/ArchR/devices/RK3326/patches/mali-bifrost/001-single-regulator.patch new file mode 100644 index 0000000000..0ebd0b68a5 --- /dev/null +++ b/projects/ArchR/devices/RK3326/patches/mali-bifrost/001-single-regulator.patch @@ -0,0 +1,31 @@ +--- a/product/kernel/drivers/gpu/arm/midgard/mali_kbase_defs.h 2024-02-19 17:24:21.000000000 +0300 ++++ b/product/kernel/drivers/gpu/arm/midgard/mali_kbase_defs.h 2024-03-18 23:51:35.201950500 +0300 +@@ -141,7 +141,7 @@ + * This is dependent on support for of_property_read_u64_array() in the + * kernel. + */ +-#define BASE_MAX_NR_CLOCKS_REGULATORS (2) ++#define BASE_MAX_NR_CLOCKS_REGULATORS (1) + + /* Forward declarations */ + struct kbase_context; +--- a/product/kernel/drivers/gpu/arm/midgard/mali_kbase_core_linux.c 2024-03-19 00:26:38.775395807 +0300 ++++ b/product/kernel/drivers/gpu/arm/midgard/mali_kbase_core_linux.c 2024-03-19 00:23:39.644058337 +0300 +@@ -4725,7 +4725,7 @@ + int err = 0; + unsigned int i; + #if defined(CONFIG_REGULATOR) +- static const char *const regulator_names[] = { "mali", "shadercores" }; ++ static const char *const regulator_names[] = { "mali", NULL }; + BUILD_BUG_ON(ARRAY_SIZE(regulator_names) < BASE_MAX_NR_CLOCKS_REGULATORS); + #endif /* CONFIG_REGULATOR */ + +@@ -4771,7 +4771,7 @@ + * operating with a partial initialization of clocks. + */ + for (i = 0; i < BASE_MAX_NR_CLOCKS_REGULATORS; i++) { +- kbdev->clocks[i] = of_clk_get(kbdev->dev->of_node, (int)i); ++ kbdev->clocks[i] = of_clk_get_by_name(kbdev->dev->of_node, "bus"); + if (IS_ERR(kbdev->clocks[i])) { + err = PTR_ERR(kbdev->clocks[i]); + kbdev->clocks[i] = NULL; diff --git a/projects/ArchR/devices/RK3326/patches/mali-bifrost/002-lowercase-interrupts-first.patch b/projects/ArchR/devices/RK3326/patches/mali-bifrost/002-lowercase-interrupts-first.patch new file mode 100644 index 0000000000..1360d86fcb --- /dev/null +++ b/projects/ArchR/devices/RK3326/patches/mali-bifrost/002-lowercase-interrupts-first.patch @@ -0,0 +1,30 @@ +diff -ur build.ArchR-RK3566.aarch64/mali-bifrost-r48p0-01eac0.orig/product/kernel/drivers/gpu/arm/midgard/mali_kbase_core_linux.c build.ArchR-RK3566.aarch64/mali-bifrost-r48p0-01eac0/product/kernel/drivers/gpu/arm/midgard/mali_kbase_core_linux.c +--- mali-bifrost-r48p0-01eac0.orig/product/kernel/drivers/gpu/arm/midgard/mali_kbase_core_linux.c 2024-04-10 00:29:25.679588022 +0300 ++++ mali-bifrost-r48p0-01eac0/product/kernel/drivers/gpu/arm/midgard/mali_kbase_core_linux.c 2024-04-10 00:33:32.693922486 +0300 +@@ -548,9 +548,9 @@ + static int get_irqs(struct kbase_device *kbdev, struct platform_device *pdev) + { + int i; +- static const char *const irq_names_caps[] = { "JOB", "MMU", "GPU" }; ++ static const char *const irq_names[] = { "job", "mmu", "gpu" }; + +- for (i = 0; i < ARRAY_SIZE(irq_names_caps); i++) { ++ for (i = 0; i < ARRAY_SIZE(irq_names); i++) { + struct irq_data *irqdata; + int irq; + +@@ -560,11 +560,11 @@ + * first then try using Lower case names. If both attempts fail then + * we assume there is no IRQ resource specified for the GPU. + */ +- irq = platform_get_irq_byname(pdev, irq_names_caps[i]); ++ irq = platform_get_irq_byname(pdev, irq_names[i]); + if (irq < 0) { +- static const char *const irq_names[] = { "job", "mmu", "gpu" }; ++ static const char *const irq_names_caps[] = { "JOB", "MMU", "GPU" }; + +- irq = platform_get_irq_byname(pdev, irq_names[i]); ++ irq = platform_get_irq_byname(pdev, irq_names_caps[i]); + } + + if (irq < 0) diff --git a/projects/ArchR/devices/RK3326/patches/mali-bifrost/003-midgard-refactor-power-init-and-fixed-unbalanced-run.patch b/projects/ArchR/devices/RK3326/patches/mali-bifrost/003-midgard-refactor-power-init-and-fixed-unbalanced-run.patch new file mode 100644 index 0000000000..125dc12649 --- /dev/null +++ b/projects/ArchR/devices/RK3326/patches/mali-bifrost/003-midgard-refactor-power-init-and-fixed-unbalanced-run.patch @@ -0,0 +1,199 @@ +From 5b1c50b3e181a57f5ce0a7d8c50f0f0823ac1609 Mon Sep 17 00:00:00 2001 +From: Paul Reioux +Date: Wed, 12 Jun 2024 07:36:52 -0700 +Subject: [PATCH] midgard: refactor power init and fixed unbalanced runtime PM + calls + +Signed-off-by: Paul Reioux +--- + .../gpu/arm/midgard/mali_kbase_core_linux.c | 124 ++++++++++++------ + .../platform/meson/mali_kbase_runtime_pm.c | 11 +- + 2 files changed, 88 insertions(+), 47 deletions(-) + +diff --git a/product/kernel/drivers/gpu/arm/midgard/mali_kbase_core_linux.c b/product/kernel/drivers/gpu/arm/midgard/mali_kbase_core_linux.c +index 0ad8a70..8db0c13 100644 +--- a/product/kernel/drivers/gpu/arm/midgard/mali_kbase_core_linux.c ++++ b/product/kernel/drivers/gpu/arm/midgard/mali_kbase_core_linux.c +@@ -4507,31 +4507,44 @@ int power_control_init(struct kbase_device *kbdev) + + pdev = to_platform_device(kbdev->dev); + +-#if defined(CONFIG_REGULATOR) +- /* Since the error code EPROBE_DEFER causes the entire probing +- * procedure to be restarted from scratch at a later time, +- * all regulators will be released before returning. +- * +- * Any other error is ignored and the driver will continue +- * operating with a partial initialization of regulators. +- */ +- for (i = 0; i < BASE_MAX_NR_CLOCKS_REGULATORS; i++) { +- kbdev->regulators[i] = regulator_get_optional(kbdev->dev, regulator_names[i]); +- if (IS_ERR(kbdev->regulators[i])) { +- err = PTR_ERR(kbdev->regulators[i]); +- kbdev->regulators[i] = NULL; +- break; +- } +- } +- if (err == -EPROBE_DEFER) { +- while (i > 0) +- regulator_put(kbdev->regulators[--i]); +- return err; ++// #if defined(CONFIG_REGULATOR) ++// /* Since the error code EPROBE_DEFER causes the entire probing ++// * procedure to be restarted from scratch at a later time, ++// * all regulators will be released before returning. ++// * ++// * Any other error is ignored and the driver will continue ++// * operating with a partial initialization of regulators. ++// */ ++// for (i = 0; i < BASE_MAX_NR_CLOCKS_REGULATORS; i++) { ++// kbdev->regulators[i] = regulator_get_optional(kbdev->dev, regulator_names[i]); ++// if (IS_ERR(kbdev->regulators[i])) { ++// err = PTR_ERR(kbdev->regulators[i]); ++// kbdev->regulators[i] = NULL; ++// break; ++// } ++// } ++// if (err == -EPROBE_DEFER) { ++// while (i > 0) ++// regulator_put(kbdev->regulators[--i]); ++// return err; ++// } ++ kbdev->regulators[0] = devm_regulator_get_optional(kbdev->dev, regulator_names[0]); ++ ++ if (IS_ERR(kbdev->regulators[0])) { ++ err = PTR_ERR(kbdev->regulators[0]); ++ kbdev->regulators[0] = NULL; ++ kbdev->nr_regulators = 0; ++ } else { ++ kbdev->nr_regulators = 1; ++ ++ err = regulator_enable(kbdev->regulators[0]); ++ if (err) ++ dev_dbg(&pdev->dev, "regulator_enable failed\n"); + } + +- kbdev->nr_regulators = i; + dev_dbg(&pdev->dev, "Regulators probed: %u\n", kbdev->nr_regulators); +-#endif ++ ++// #endif + + /* Having more clocks than regulators is acceptable, while the + * opposite shall not happen. +@@ -4543,30 +4556,55 @@ int power_control_init(struct kbase_device *kbdev) + * Any other error is ignored and the driver will continue + * operating with a partial initialization of clocks. + */ +- for (i = 0; i < BASE_MAX_NR_CLOCKS_REGULATORS; i++) { +- kbdev->clocks[i] = of_clk_get_by_name(kbdev->dev->of_node, "bus"); +- if (IS_ERR(kbdev->clocks[i])) { +- err = PTR_ERR(kbdev->clocks[i]); +- kbdev->clocks[i] = NULL; +- break; +- } + +- err = clk_prepare_enable(kbdev->clocks[i]); +- if (err) { +- dev_err(kbdev->dev, "Failed to prepare and enable clock (%d)\n", err); +- clk_put(kbdev->clocks[i]); +- break; +- } +- } +- if (err == -EPROBE_DEFER) { +- while (i > 0) { +- clk_disable_unprepare(kbdev->clocks[--i]); +- clk_put(kbdev->clocks[i]); +- } +- goto clocks_probe_defer; ++ kbdev->clocks[0] = devm_clk_get_optional(kbdev->dev, NULL); ++ if (!IS_ERR(kbdev->clocks[0])) ++ dev_dbg(kbdev->dev, "clk_get: %s\n", __clk_get_name(kbdev->clocks[0])); ++ else ++ dev_err(kbdev->dev, "clk_get: is NULL"); ++ ++ /* if platform device is enabled, disable it now */ ++ //if (__clk_is_enabled(kbdev->clocks[0])) { ++ // clk_disable(kbdev->clocks[0]); ++ //} ++ /* delete from clk tree */ ++ //clk_unprepare(kbdev->clocks[0]); ++ //clk_put(kbdev->clocks[0]); ++ ++ /* now grab the gpu clock node from device tree definition */ ++ //kbdev->clocks[0] = of_clk_get_by_name(kbdev->dev->of_node, "gpu"); ++ ++ /* we are kinda commited here.. if this fails, the system will lock up */ ++ err = clk_prepare_enable(kbdev->clocks[0]); ++ if (err) { ++ dev_err(kbdev->dev, "Failed to prepare and enable clock (%d)\n", err); ++ clk_put(kbdev->clocks[0]); + } + +- kbdev->nr_clocks = i; ++ // for (i = 0; i < BASE_MAX_NR_CLOCKS_REGULATORS; i++) { ++ // kbdev->clocks[i] = of_clk_get(kbdev->dev->of_node, (int)i); ++ // if (IS_ERR(kbdev->clocks[i])) { ++ // err = PTR_ERR(kbdev->clocks[i]); ++ // kbdev->clocks[i] = NULL; ++ // break; ++ // } ++ ++ // err = clk_prepare_enable(kbdev->clocks[i]); ++ // if (err) { ++ // dev_err(kbdev->dev, "Failed to prepare and enable clock (%d)\n", err); ++ // clk_put(kbdev->clocks[i]); ++ // break; ++ // } ++ // } ++ // if (err == -EPROBE_DEFER) { ++ // while (i > 0) { ++ // clk_disable_unprepare(kbdev->clocks[--i]); ++ // clk_put(kbdev->clocks[i]); ++ // } ++ // goto clocks_probe_defer; ++ // } ++ ++ kbdev->nr_clocks = 1; + dev_dbg(&pdev->dev, "Clocks probed: %u\n", kbdev->nr_clocks); + + /* Any error in parsing the OPP table from the device file +diff --git a/product/kernel/drivers/gpu/arm/midgard/platform/meson/mali_kbase_runtime_pm.c b/product/kernel/drivers/gpu/arm/midgard/platform/meson/mali_kbase_runtime_pm.c +index bd3b4b5..33a24bb 100644 +--- a/product/kernel/drivers/gpu/arm/midgard/platform/meson/mali_kbase_runtime_pm.c ++++ b/product/kernel/drivers/gpu/arm/midgard/platform/meson/mali_kbase_runtime_pm.c +@@ -113,7 +113,8 @@ static void enable_gpu_power_control(struct kbase_device *kbdev) + if (WARN_ON(kbdev->clocks[i] == NULL)) + ; + else if (!__clk_is_enabled(kbdev->clocks[i])) +- WARN_ON(clk_prepare_enable(kbdev->clocks[i])); ++ //WARN_ON(clk_prepare_enable(kbdev->clocks[i])); ++ ; + } + } + +@@ -125,8 +126,9 @@ static void disable_gpu_power_control(struct kbase_device *kbdev) + if (WARN_ON(kbdev->clocks[i] == NULL)) + ; + else if (__clk_is_enabled(kbdev->clocks[i])) { +- clk_disable_unprepare(kbdev->clocks[i]); +- WARN_ON(__clk_is_enabled(kbdev->clocks[i])); ++ //clk_disable_unprepare(kbdev->clocks[i]); ++ //WARN_ON(__clk_is_enabled(kbdev->clocks[i])); ++ ; + } + } + +@@ -135,7 +137,8 @@ static void disable_gpu_power_control(struct kbase_device *kbdev) + if (WARN_ON(kbdev->regulators[i] == NULL)) + ; + else if (regulator_is_enabled(kbdev->regulators[i])) +- WARN_ON(regulator_disable(kbdev->regulators[i])); ++ //WARN_ON(regulator_disable(kbdev->regulators[i])); ++ ; + } + #endif + } +-- +2.34.1 + diff --git a/projects/ArchR/options b/projects/ArchR/options new file mode 100644 index 0000000000..63fa8cefd5 --- /dev/null +++ b/projects/ArchR/options @@ -0,0 +1,44 @@ +################################################################################ +# setup build defaults +################################################################################ + + # Project FLAGS + PROJECT_CFLAGS="" + + # Root filesystem type (ext4 for ArchR, squashfs for legacy) + ROOTFS_TYPE="ext4" + + # SquashFS compression method (gzip / lzo / xz) - only used when ROOTFS_TYPE=squashfs + SQUASHFS_COMPRESSION="lzo" + +################################################################################ +# setup project defaults +################################################################################ + + # OpenGL(X) implementation to use (no / mesa) + OPENGL="mesa" + + # OpenGL-ES implementation to use (no / mesa) + OPENGLES="mesa" + + # Displayserver to use (no / wl) + DISPLAYSERVER="no" + + # Windowmanager to use (none / weston) + 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="" + + # Additional Firmware to use ( ) + # Space separated list is supported, + # e.g. FIRMWARE="" + FIRMWARE="" + + # Additional packages to install + ADDITIONAL_PACKAGES="" + + # Satisfy legacy build dependencies + SWAP_SUPPORT="yes" diff --git a/projects/ArchR/packages/apps/archr-hotkey/package.mk b/projects/ArchR/packages/apps/archr-hotkey/package.mk new file mode 100644 index 0000000000..661919e50b --- /dev/null +++ b/projects/ArchR/packages/apps/archr-hotkey/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="archr-hotkey" +PKG_VERSION="cc3a863199a71a350db05e9d0d0e646a8411332c" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/archr-linux/archr-hotkey" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain libevdev SDL2 control-gen" +PKG_TOOLCHAIN="make" +GET_HANDLER_SUPPORT="git" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp ${PKG_BUILD}/gptokeyb ${INSTALL}/usr/bin + + mkdir -p ${INSTALL}/usr/lib + cp ${PKG_BUILD}/inputfilter.so ${INSTALL}/usr/lib + + mkdir -p ${INSTALL}/usr/config/gptokeyb/ + cp ${PKG_BUILD}/configs/default.gptk ${INSTALL}/usr/config/gptokeyb/ +} diff --git a/projects/ArchR/packages/apps/archr-screenshot/package.mk b/projects/ArchR/packages/apps/archr-screenshot/package.mk new file mode 100644 index 0000000000..416d418242 --- /dev/null +++ b/projects/ArchR/packages/apps/archr-screenshot/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025 ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="archr-screenshot" +PKG_VERSION="1.0" +PKG_LICENSE="GPLv2" +PKG_SITE="" +PKG_URL="" +PKG_DEPENDS_TARGET="toolchain grim jq sway" +PKG_LONGDESC="ArchR screenshot utility" +PKG_TOOLCHAIN="manual" + +make_target() { + : +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp -rf ${PKG_DIR}/sources/archr-screenshot ${INSTALL}/usr/bin + chmod +x ${INSTALL}/usr/bin/archr-screenshot +} diff --git a/projects/ArchR/packages/apps/archr-screenshot/sources/archr-screenshot b/projects/ArchR/packages/apps/archr-screenshot/sources/archr-screenshot new file mode 100644 index 0000000000..8186047981 --- /dev/null +++ b/projects/ArchR/packages/apps/archr-screenshot/sources/archr-screenshot @@ -0,0 +1,48 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025-present ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile + +# Enable / Disable archr screenshot +ArchR_SCREENSHOT=$(get_setting "archr.screenshot.enabled") +if [ ! -n "${ArchR_SCREENSHOT}" ]; then + set_setting "archr.screenshot.enabled" "0" +fi + +if [ "${ArchR_SCREENSHOT}" == "1" ]; then + # Disable archr-screenshot while retroarch is running + if pgrep -f "retroarch" > /dev/null; then + echo "RetroArch is running, skipping screenshot." + # 'failure' (screenshot not taken) exit code + exit 1 + fi + + # Folder to save screenshots + SAVE_DIR="/storage/roms/screenshots" + + # Create the folder if it doesn't exist + mkdir -p "$SAVE_DIR" + + # Generate a timestamped filename + FILENAME="$(date +'%Y-%m-%d-%H%M%S').png" + FULL_PATH="${SAVE_DIR}/${FILENAME}" + + # Get focused window geometry + GEOMETRY=$(swaymsg -t get_tree | jq -r ' + .. + | select(.type? == "con" and .focused == true) + | "\(.rect.x),\(.rect.y) \(.rect.width)x\(.rect.height)"' + ) + + # Take screenshot of the focused window + grim -g "$GEOMETRY" "$FULL_PATH" + + # 'success' (screenshot taken) exit code + exit 0 +else + echo "archr-screenshot is not enabled, skipping screenshot." + # 'failure' (screenshot not taken) exit code + exit 1 +fi diff --git a/projects/ArchR/packages/apps/archr-touchscreen-keyboard/package.mk b/projects/ArchR/packages/apps/archr-touchscreen-keyboard/package.mk new file mode 100644 index 0000000000..4e75e73fa4 --- /dev/null +++ b/projects/ArchR/packages/apps/archr-touchscreen-keyboard/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2025-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="archr-touchscreen-keyboard" +PKG_VERSION="v0.17" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/jjsullivan5196/wvkbd" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_LONGDESC="wvkbd - On-screen keyboard for wlroots that sucks less" +PKG_DEPENDS_TARGET="toolchain wayland sway pango libxkbcommon cairo" +PKG_TOOLCHAIN="make" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp -rf ${PKG_BUILD}/wvkbd-mobintl ${INSTALL}/usr/bin + cp -rf ${PKG_DIR}/sources/* ${INSTALL}/usr/bin + chmod 0755 ${INSTALL}/usr/bin/* +} + +post_install() { + enable_service touchkeyboard.service +} diff --git a/projects/ArchR/packages/apps/archr-touchscreen-keyboard/patches/000-remove-scdoc-dependency.patch b/projects/ArchR/packages/apps/archr-touchscreen-keyboard/patches/000-remove-scdoc-dependency.patch new file mode 100644 index 0000000000..d69c2fd02e --- /dev/null +++ b/projects/ArchR/packages/apps/archr-touchscreen-keyboard/patches/000-remove-scdoc-dependency.patch @@ -0,0 +1,46 @@ +diff --git a/Makefile b/Makefile +index db17991..bbdc67e 100644 +--- a/Makefile ++++ b/Makefile +@@ -3,7 +3,6 @@ include config.mk + NAME=wvkbd + BIN=${NAME}-${LAYOUT} + SRC=. +-MAN1 = ${NAME}.1 + + PKGS = wayland-client xkbcommon pangocairo + +@@ -21,12 +20,9 @@ HDRS = $(WAYLAND_HEADERS:.xml=-client-protocol.h) + WAYLAND_SRC = $(HDRS:.h=.c) + SOURCES = $(WVKBD_SOURCES) $(WAYLAND_SRC) + +-SCDOC=scdoc +-DOCS = wvkbd.1 +- + OBJECTS = $(SOURCES:.c=.o) + +-all: ${BIN} ${DOCS} ++all: ${BIN} + + config.h: + cp config.def.h config.h +@@ -43,18 +39,12 @@ wvkbd-${LAYOUT}: config.h $(OBJECTS) layout.${LAYOUT}.h + $(CC) -o wvkbd-${LAYOUT} $(OBJECTS) $(LDFLAGS) + + clean: +- rm -f $(OBJECTS) $(HDRS) $(WAYLAND_SRC) ${BIN} ${DOCS} ++ rm -f $(OBJECTS) $(HDRS) $(WAYLAND_SRC) ${BIN} + + format: + clang-format -i $(WVKBD_SOURCES) $(WVKBD_HEADERS) + +-%: %.scd +- $(SCDOC) < $< > $@ +- + install: all + mkdir -p ${DESTDIR}${PREFIX}/bin + cp -f ${NAME}-${LAYOUT} ${DESTDIR}${PREFIX}/bin + chmod 755 ${DESTDIR}${PREFIX}/bin/${NAME}-${LAYOUT} +- mkdir -p "${DESTDIR}${MANPREFIX}/man1" +- sed "s/VERSION/${VERSION}/g" < ${MAN1} > ${DESTDIR}${MANPREFIX}/man1/${MAN1} +- chmod 644 ${DESTDIR}${MANPREFIX}/man1/${MAN1} diff --git a/projects/ArchR/packages/apps/archr-touchscreen-keyboard/patches/001-fix-special-chars.patch b/projects/ArchR/packages/apps/archr-touchscreen-keyboard/patches/001-fix-special-chars.patch new file mode 100644 index 0000000000..eb8e387c8f --- /dev/null +++ b/projects/ArchR/packages/apps/archr-touchscreen-keyboard/patches/001-fix-special-chars.patch @@ -0,0 +1,897 @@ +diff --git a/layout.mobintl.h b/layout.mobintl.h +index 913f392..6200c6e 100644 +--- a/layout.mobintl.h ++++ b/layout.mobintl.h +@@ -22,7 +22,6 @@ enum layout_id { + Greek, + Georgian, + Hebrew, +- Emoji, + Nav, + Landscape, + LandscapeSpecial, +@@ -51,6 +50,7 @@ enum layout_id { + ComposeB, + ComposeN, + ComposeM, ++ ComposeQ, + ComposeMath, + ComposePunctuation, + ComposeBracket, +@@ -70,13 +70,13 @@ enum layout_id { + + static struct key keys_full[], keys_full_wide[], keys_special[], keys_specialpad[], keys_simple[], + keys_cyrillic[], keys_arabic[], keys_persian[], keys_georgian[], keys_greek[], keys_hebrew[], +- keys_emoji[], keys_nav[], keys_landscape[], keys_landscape_special[], keys_compose_a[], ++ keys_nav[], keys_landscape[], keys_landscape_special[], keys_compose_a[], + keys_compose_e[], keys_compose_y[], keys_compose_u[], keys_compose_i[], + keys_compose_o[], keys_compose_w[], keys_compose_r[], keys_compose_t[], + keys_compose_p[], keys_compose_s[], keys_compose_d[], keys_compose_f[], + keys_compose_g[], keys_compose_h[], keys_compose_j[], keys_compose_k[], + keys_compose_l[], keys_compose_z[], keys_compose_x[], keys_compose_c[], +- keys_compose_v[], keys_compose_b[], keys_compose_n[], keys_compose_m[], ++ keys_compose_v[], keys_compose_b[], keys_compose_n[], keys_compose_m[], keys_compose_q[], + keys_compose_math[], keys_compose_punctuation[], keys_compose_bracket[], + keys_compose_cyr_i[], keys_compose_cyr_j[], keys_compose_cyr_e[], + keys_compose_cyr_u[], keys_compose_cyr_l[], keys_compose_cyr_n[], +@@ -98,7 +98,6 @@ static struct layout layouts[NumLayouts] = { + [Greek] = {keys_greek, "greek", "greek", true}, + [Georgian] = {keys_georgian, "georgian", "georgian", true}, + [Hebrew] = {keys_hebrew, "hebrew", "hebrew", true}, +- [Emoji] = {keys_emoji, "latin", "emoji", false}, + [Nav] = {keys_nav, "latin", "nav", false}, + [Landscape] = {keys_landscape, "latin", "landscape", true}, + [LandscapeSpecial] = {keys_landscape_special, "latin", "landscapespecial", true}, +@@ -127,6 +126,7 @@ static struct layout layouts[NumLayouts] = { + [ComposeB] = {keys_compose_b, "latin"}, + [ComposeN] = {keys_compose_n, "latin"}, + [ComposeM] = {keys_compose_m, "latin"}, ++ [ComposeQ] = {keys_compose_q, "latin"}, + [ComposeMath] = {keys_compose_math, "latin"}, + [ComposePunctuation] = {keys_compose_punctuation, "latin"}, + [ComposeBracket] = {keys_compose_bracket, "latin"}, +@@ -197,7 +197,7 @@ static struct key keys_full[] = { + {"0", ")", 1.0, Code, KEY_0, &layouts[ComposeBracket]}, + {"", "", 0.0, EndRow}, + +- {"q", "Q", 1.0, Code, KEY_Q, &layouts[Emoji]}, ++ {"q", "Q", 1.0, Code, KEY_Q, &layouts[ComposeQ]}, + {"w", "W", 1.0, Code, KEY_W, &layouts[ComposeW]}, + {"e", "E", 1.0, Code, KEY_E, &layouts[ComposeE]}, + {"r", "R", 1.0, Code, KEY_R, &layouts[ComposeR]}, +@@ -222,7 +222,7 @@ static struct key keys_full[] = { + {"", "", 0.5, Pad}, + {"", "", 0.0, EndRow}, + +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"z", "Z", 1.0, Code, KEY_Z, &layouts[ComposeZ]}, + {"x", "X", 1.0, Code, KEY_X, &layouts[ComposeX]}, + {"c", "C", 1.0, Code, KEY_C, &layouts[ComposeC]}, +@@ -230,10 +230,10 @@ static struct key keys_full[] = { + {"b", "B", 1.0, Code, KEY_B, &layouts[ComposeB]}, + {"n", "N", 1.0, Code, KEY_N, &layouts[ComposeN]}, + {"m", "M", 1.0, Code, KEY_M, &layouts[ComposeM]}, +- {"⌫", "⌫", 1.5, Code, KEY_BACKSPACE, .scheme = 1}, ++ {"Back", "Back", 1.5, Code, KEY_BACKSPACE, .scheme = 1}, + {"", "", 0.0, EndRow}, + +- {"⌨͕", "⌨͔", 1.5, NextLayer, .scheme = 1}, ++ {"123", "123", 1.5, NextLayer, .scheme = 1}, + {"Cmp", "Cmp", 1.0, Compose, .scheme = 1}, + {",", "'", 1.0, Code, KEY_COMMA, &layouts[ComposeMath]}, + {"", "Tab", 4.0, Code, KEY_SPACE}, +@@ -271,7 +271,7 @@ static struct key keys_full_wide[] = { + {"=", "+", 1.0, Code, KEY_EQUAL, &layouts[ComposeMath] }, + {"", "", 0.0, EndRow}, + +- {"q", "Q", 1.0, Code, KEY_Q, &layouts[Emoji]}, ++ {"q", "Q", 1.0, Code, KEY_Q, &layouts[ComposeQ]}, + {"w", "W", 1.0, Code, KEY_W, &layouts[ComposeW]}, + {"e", "E", 1.0, Code, KEY_E, &layouts[ComposeE]}, + {"r", "R", 1.0, Code, KEY_R, &layouts[ComposeR]}, +@@ -296,7 +296,7 @@ static struct key keys_full_wide[] = { + {"", "", 0.5, Pad}, + {"", "", 0.0, EndRow}, + +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"z", "Z", 1.0, Code, KEY_Z, &layouts[ComposeZ]}, + {"x", "X", 1.0, Code, KEY_X, &layouts[ComposeX]}, + {"c", "C", 1.0, Code, KEY_C, &layouts[ComposeC]}, +@@ -304,10 +304,10 @@ static struct key keys_full_wide[] = { + {"b", "B", 1.0, Code, KEY_B, &layouts[ComposeB]}, + {"n", "N", 1.0, Code, KEY_N, &layouts[ComposeN]}, + {"m", "M", 1.0, Code, KEY_M, &layouts[ComposeM]}, +- {"⌫", "⌫", 1.5, Code, KEY_BACKSPACE, .scheme = 1}, ++ {"Back", "Back", 1.5, Code, KEY_BACKSPACE, .scheme = 1}, + {"", "", 0.0, EndRow}, + +- {"⌨͕", "⌨͔", 1.5, NextLayer, .scheme = 1}, ++ {"123", "123", 1.5, NextLayer, .scheme = 1}, + {"Cmp", "Cmp", 1.0, Compose, .scheme = 1}, + {",", "'", 1.0, Code, KEY_COMMA, &layouts[ComposeMath]}, + {"", "Tab", 4.0, Code, KEY_SPACE}, +@@ -325,10 +325,10 @@ static struct key keys_special[] = { + {"↓", "↓", 1.0, Code, KEY_DOWN, .scheme = 1}, + {"←", "←", 1.0, Code, KEY_LEFT, .scheme = 1}, + {"→", "→", 1.0, Code, KEY_RIGHT, .scheme = 1}, +- {"⇈", "⇈", 1.0, Code, KEY_PAGEUP, .scheme = 1}, +- {"⇊", "⇊", 1.0, Code, KEY_PAGEDOWN, .scheme = 1}, +- {"⇤", "⇤", 1.0, Code, KEY_HOME, .scheme = 1}, +- {"⇥", "⇥", 1.0, Code, KEY_END, .scheme = 1}, ++ {"Up", "Up", 1.0, Code, KEY_PAGEUP, .scheme = 1}, ++ {"Down", "Down", 1.0, Code, KEY_PAGEDOWN, .scheme = 1}, ++ {"Home", "Home", 1.0, Code, KEY_HOME, .scheme = 1}, ++ {"End", "End", 1.0, Code, KEY_END, .scheme = 1}, + {"", "", 0.0, EndRow}, + + {"1", "!", 1.0, Code, KEY_1}, +@@ -355,19 +355,18 @@ static struct key keys_special[] = { + {"Del", "Del", 1.0, Code, KEY_DELETE, .scheme = 1}, + {"", "", 0.0, EndRow}, + +- {"⇧", "⇫", 2.0, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 2.0, Mod, Shift, .scheme = 1}, + {";", ":", 1.0, Code, KEY_SEMICOLON}, + {"/", ">", 1.0, Code, KEY_SLASH}, + {"<", "«", 1.0, Code, KEY_COMMA, 0, AltGr}, + {">", "»", 1.0, Code, KEY_DOT, 0, AltGr}, + {"¡", "¿", 1.0, Code, KEY_MENU}, +- {"🙂", "🙂", 1.0, Layout, 0, &layouts[Emoji]}, + {"AGr", "AGr", 1.0, Mod, AltGr, .scheme = 1}, +- {"⌫", "⌫", 1.0, Code, KEY_BACKSPACE, .scheme = 1}, ++ {"Back", "Back", 1.0, Code, KEY_BACKSPACE, .scheme = 1}, + {"", "", 0.0, EndRow}, + + {"Abc", "Abc", 1.0, BackLayer, .scheme = 1}, +- {"⌨͕", "⌨͔", 1.0, NextLayer, .scheme = 1}, ++ {"123", "123", 1.0, NextLayer, .scheme = 1}, + {",", "'", 1.0, Code, KEY_COMMA, &layouts[ComposeMath]}, + {"", "Tab", 4.0, Code, KEY_SPACE}, + {".", "?", 1.0, Code, KEY_DOT, &layouts[ComposePunctuation]}, +@@ -378,20 +377,20 @@ static struct key keys_special[] = { + }; + + static struct key keys_specialpad[] = { +- {"⎋", "⎋", 1.0, Code, KEY_ESC, .scheme = 1}, ++ {"Esc", "Esc", 1.0, Code, KEY_ESC, .scheme = 1}, + {"↑", "↑", 1.0, Code, KEY_UP, .scheme = 1}, +- {"⇈", "⇈", 1.0, Code, KEY_PAGEUP, .scheme = 1}, ++ {"Up", "Up", 1.0, Code, KEY_PAGEUP, .scheme = 1}, + {"`", "~", 1.0, Code, KEY_GRAVE}, + {"\\", "|", 1.0, Code, KEY_BACKSLASH}, + {"/", ">", 1.0, Code, KEY_SLASH}, + {"1", "!", 1.0, Code, KEY_1}, + {"2", "@", 1.0, Code, KEY_2}, + {"3", "#", 1.0, Code, KEY_3}, +- {"⌦", "⌦", 1.0, Code, KEY_DELETE, .scheme = 1}, ++ {"Del", "Del", 1.0, Code, KEY_DELETE, .scheme = 1}, + {"", "", 0.0, EndRow}, + //{"Tab", "Tab", 1.0, Code, KEY_TAB, .scheme = 1}, + {"←", "←", 1.0, Code, KEY_LEFT, .scheme = 1}, +- {"", "↹", 1.0, Code, KEY_SPACE}, ++ {"", "Space", 1.0, Code, KEY_SPACE}, + {"→", "→", 1.0, Code, KEY_RIGHT, .scheme = 1}, + {".", "?", 1.0, Code, KEY_DOT}, + {"[", "{", 1.0, Code, KEY_LEFTBRACE}, +@@ -401,25 +400,25 @@ static struct key keys_specialpad[] = { + {"6", "^", 1.0, Code, KEY_6}, + {"'", "\"", 1.0, Code, KEY_APOSTROPHE}, + {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.0, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.0, Mod, Shift, .scheme = 1}, + {"↓", "↓", 1.0, Code, KEY_DOWN, .scheme = 1}, +- {"⇊", "⇊", 1.0, Code, KEY_PAGEDOWN, .scheme = 1}, ++ {"Down", "Down", 1.0, Code, KEY_PAGEDOWN, .scheme = 1}, + {";", ":", 1.0, Code, KEY_SEMICOLON}, + {"<", "«", 1.0, Code, KEY_COMMA, 0, AltGr}, + {">", "»", 1.0, Code, KEY_DOT, 0, AltGr}, + {"7", "&", 1.0, Code, KEY_7}, + {"8", "*", 1.0, Code, KEY_8}, + {"9", "(", 1.0, Code, KEY_9}, +- {"⌫", "⌫", 1.0, Code, KEY_BACKSPACE, .scheme = 1}, ++ {"Back", "Back", 1.0, Code, KEY_BACKSPACE, .scheme = 1}, + {"", "", 0.0, EndRow}, + +- {"⌨͕", "⌨͔", 1.0, NextLayer, .scheme = 1}, ++ {"123", "123", 1.0, NextLayer, .scheme = 1}, + {"Ctr", "Ctr", 1.0, Mod, Ctrl, .scheme = 1}, + {"Alt", "Alt", 1.0, Mod, Alt, .scheme = 1}, + {"Sup", "Sup", 1.0, Mod, Super, .scheme = 1}, + +- {"⇤", "⇤", 1.0, Code, KEY_HOME, .scheme = 1}, +- {"⇥", "⇥", 1.0, Code, KEY_END, .scheme = 1}, ++ {"Home", "Home", 1.0, Code, KEY_HOME, .scheme = 1}, ++ {"End", "End", 1.0, Code, KEY_END, .scheme = 1}, + {"-", "_", 1.0, Code, KEY_MINUS}, + {"0", ")", 1.0, Code, KEY_0}, + {"=", "+", 1.0, Code, KEY_EQUAL}, +@@ -430,7 +429,7 @@ static struct key keys_specialpad[] = { + }; + + static struct key keys_simple[] = { +- {"q", "Q", 1.0, Code, KEY_Q, &layouts[Emoji]}, ++ {"q", "Q", 1.0, Code, KEY_Q, &layouts[ComposeQ]}, + {"w", "W", 1.0, Code, KEY_W, &layouts[ComposeW]}, + {"e", "E", 1.0, Code, KEY_E, &layouts[ComposeE]}, + {"r", "R", 1.0, Code, KEY_R, &layouts[ComposeR]}, +@@ -455,7 +454,7 @@ static struct key keys_simple[] = { + {"", "", 0.5, Pad}, + {"", "", 0.0, EndRow}, + +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"z", "Z", 1.0, Code, KEY_Z, &layouts[ComposeZ]}, + {"x", "X", 1.0, Code, KEY_X, &layouts[ComposeX]}, + {"c", "C", 1.0, Code, KEY_C, &layouts[ComposeC]}, +@@ -463,10 +462,10 @@ static struct key keys_simple[] = { + {"b", "B", 1.0, Code, KEY_B, &layouts[ComposeB]}, + {"n", "N", 1.0, Code, KEY_N, &layouts[ComposeN]}, + {"m", "M", 1.0, Code, KEY_M, &layouts[ComposeM]}, +- {"⌫", "⌫", 1.5, Code, KEY_BACKSPACE, .scheme = 1}, ++ {"Back", "Back", 1.5, Code, KEY_BACKSPACE, .scheme = 1}, + {"", "", 0.0, EndRow}, + +- {"⌨͕", "⌨͔", 1.0, NextLayer, .scheme = 1}, ++ {"123", "123", 1.0, NextLayer, .scheme = 1}, + {"Cmp", "Cmp", 1.0, Compose, .scheme = 1}, + {"Ctr", "Ctr", 1.0, Mod, Ctrl, .scheme = 1}, + {"-", "_", 0.75, Code, KEY_MINUS, &layouts[ComposeMath]}, +@@ -482,7 +481,7 @@ static struct key keys_simple[] = { + static struct key keys_dialer[] = { + {"Esc", "Esc", 1.0, Code, KEY_ESC}, + {"+","+", 1.0, Code, KEY_KPPLUS}, +- {"⌫", "⌫", 1.0, Code, KEY_BACKSPACE}, ++ {"Back", "Back", 1.0, Code, KEY_BACKSPACE}, + {"", "", 0.0, EndRow}, + {"1", "1", 1.0, Code, KEY_1}, + {"2", "2", 1.0, Code, KEY_2}, +@@ -500,7 +499,7 @@ static struct key keys_dialer[] = { + {"0", "0", 1.0, Code, KEY_0}, + {"#", "#", 1.0, Code, KEY_3, 0, Shift}, + {"", "", 0.0, EndRow}, +- {"⌨͕", "⌨͔", 1.0, NextLayer, .scheme = 1}, ++ {"123", "123", 1.0, NextLayer, .scheme = 1}, + {"Enter", "Enter", 2.0, Code, KEY_ENTER, .scheme = 1}, + + /* end of layout */ +@@ -549,7 +548,7 @@ static struct key keys_cyrillic[] = { + {"ж", "Ж", 1.0, Code, KEY_SEMICOLON}, + {"", "", 0.0, EndRow}, + +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"я", "Я", 1.0, Code, KEY_Z}, + {"ч", "Ч", 1.0, Code, KEY_X, &layouts[ComposeCyrChe]}, + {"c", "С", 1.0, Code, KEY_C}, +@@ -558,11 +557,11 @@ static struct key keys_cyrillic[] = { + {"т", "Т", 1.0, Code, KEY_N}, + {"ь", "Ь", 1.0, Code, KEY_M}, + {"б", "Б", 1.0, Code, KEY_COMMA}, +- {"⌫", "⌫", 1.5, Code, KEY_BACKSPACE, .scheme = 1}, ++ {"Back", "Back", 1.5, Code, KEY_BACKSPACE, .scheme = 1}, + + {"", "", 0.0, EndRow}, + +- {"⌨͕", "⌨͔", 1.0, NextLayer, .scheme = 1}, ++ {"123", "123", 1.0, NextLayer, .scheme = 1}, + {"Cmp", "Cmp", 1.0, Compose, .scheme = 1}, + {",", "'", 1.0, Code, KEY_EQUAL, &layouts[ComposeMath]}, + {"", "Tab", 4.0, Code, KEY_SPACE}, +@@ -586,7 +585,6 @@ static struct key keys_arabic[] = { + {"٠", ")", 1.0, Code, KEY_0, &layouts[ComposeBracket]}, + {"", "", 0.0, EndRow}, + +- {"ض", "ـَ", 1.0, Code, KEY_Q, &layouts[Emoji]}, + {"ص", "ـً", 1.0, Code, KEY_W}, + {"ث", "ـُ", 1.0, Code, KEY_E}, + {"ق", "ـٌ", 1.0, Code, KEY_R}, +@@ -622,12 +620,12 @@ static struct key keys_arabic[] = { + {"ز", "؟", 1.0, Code, KEY_COMMA}, + {"ظ", ".", 1.0, Code, KEY_DOT}, + {"د", ">", 1.0, Code, KEY_RIGHTBRACE}, +- {"⌫", "⌫", 1.0, Code, KEY_BACKSPACE, .scheme = 1}, ++ {"Back", "Back", 1.0, Code, KEY_BACKSPACE, .scheme = 1}, + + {"", "", 0.0, EndRow}, + +- {"⌨͕", "⌨͔", 1.0, NextLayer, .scheme = 1}, +- {"⇧", "⇫", 1.0, Mod, Shift, .scheme = 1}, ++ {"123", "123", 1.0, NextLayer, .scheme = 1}, ++ {"Shift", "Shift", 1.0, Mod, Shift, .scheme = 1}, + {"Cmp", "Cmp", 1.0, Compose, .scheme = 1}, + {"", "Tab", 5.0, Code, KEY_SPACE}, + {"Enter", "Enter", 2.0, Code, KEY_ENTER, .scheme = 1}, +@@ -682,12 +680,12 @@ static struct key keys_georgian[] = { + {"მ", "M", 1.0, Code, KEY_M}, + {",", "<", 1.0, Code, KEY_COMMA, &layouts[ComposeMath]}, + {".", ">", 1.0, Code, KEY_DOT, &layouts[ComposePunctuation]}, +- {"⌫", "⌫", 1.0, Code, KEY_BACKSPACE, .scheme = 1}, ++ {"Back", "Back", 1.0, Code, KEY_BACKSPACE, .scheme = 1}, + + {"", "", 0.0, EndRow}, + +- {"⌨͕", "⌨͔", 1.0, NextLayer, .scheme = 1}, +- {"⇧", "⇫", 1.0, Mod, Shift, .scheme = 1}, ++ {"123", "123", 1.0, NextLayer, .scheme = 1}, ++ {"Shift", "Shift", 1.0, Mod, Shift, .scheme = 1}, + {"Cmp", "Cmp", 1.0, Compose, .scheme = 1}, + {"", "Tab", 5.0, Code, KEY_SPACE}, + {"Enter", "Enter", 2.0, Code, KEY_ENTER, .scheme = 1}, +@@ -738,7 +736,7 @@ static struct key keys_persian[] = { + {"گ", "؛", 1.0, Code, KEY_APOSTROPHE}, + {"", "", 0.0, EndRow}, + +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"ظ", "ك", 1.0, Code, KEY_Z}, + {"ط", "ـٓ", 1.0, Code, KEY_X}, + {"ژ", ">", 1.0, Code, KEY_BACKSLASH}, +@@ -748,14 +746,14 @@ static struct key keys_persian[] = { + {"د", "ـٔ", 1.0, Code, KEY_N}, + {"پ", "ء", 1.0, Code, KEY_M}, + {"و", "\\", 1.0, Code, KEY_COMMA}, +- {"⌫", "⌫", 1.5, Code, KEY_BACKSPACE, .scheme = 1}, ++ {"Back", "Back", 1.5, Code, KEY_BACKSPACE, .scheme = 1}, + {"", "", 0.0, EndRow}, + +- {"⌨͕", "⌨͔", 1.0, NextLayer, .scheme = 1}, ++ {"123", "123", 1.0, NextLayer, .scheme = 1}, + {"Cmp", "Cmp", 1.0, Compose, .scheme = 1}, + {".", "،", 1.0, Code, KEY_DOT, &layouts[ComposePunctuation]}, + {"", "Tab", 4.0, Code, KEY_SPACE}, +- {"⥣", "↥", 1.0, Code, KEY_GRAVE}, ++ {"`", "~", 1.0, Code, KEY_GRAVE}, + {"؟", "!", 1.0, Code, KEY_SLASH, &layouts[ComposePunctuation]}, + {"Enter", "Enter", 2.0, Code, KEY_ENTER, .scheme = 1}, + +@@ -802,7 +800,7 @@ static struct key keys_greek[] = { + {"΄", "¨", 1.0, Code, KEY_SEMICOLON, &layouts[ComposeBracket]}, + {"", "", 0.0, EndRow}, + +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"ζ", "Ζ", 1.0, Code, KEY_Z}, + {"χ", "Χ", 1.0, Code, KEY_X}, + {"ψ", "Ψ", 1.0, Code, KEY_C}, +@@ -811,10 +809,10 @@ static struct key keys_greek[] = { + {"ν", "Ν", 1.0, Code, KEY_N}, + {"μ", "Μ", 1.0, Code, KEY_M}, + {"/", "\\", 1.0, Code, KEY_SLASH}, +- {"⌫", "⌫", 1.5, Code, KEY_BACKSPACE, .scheme = 1}, ++ {"Back", "Back", 1.5, Code, KEY_BACKSPACE, .scheme = 1}, + {"", "", 0.0, EndRow}, + +- {"⌨͕", "⌨͔", 1.5, NextLayer, .scheme = 1}, ++ {"123", "123", 1.5, NextLayer, .scheme = 1}, + {",", "'", 1.0, Code, KEY_COMMA, &layouts[ComposeMath]}, + {"", "Tab", 5, Code, KEY_SPACE}, + {".", "\"", 1.0, Code, KEY_DOT, &layouts[ComposePunctuation]}, +@@ -858,11 +856,11 @@ static struct key keys_hebrew[] = { + {"צ", "צ", 1.0, Code, KEY_M}, + {"ת", "ת", 1.0, Code, KEY_COMMA}, + {"ץ", "ץ", 1.0, Code, KEY_DOT}, +- {"⌫", "⌫", 1.0, Code, KEY_BACKSPACE, .scheme = 1}, ++ {"Back", "Back", 1.0, Code, KEY_BACKSPACE, .scheme = 1}, + + {"", "", 0.0, EndRow}, + +- {"⌨͕", "⌨͔", 1.0, NextLayer, .scheme = 1}, ++ {"123", "123", 1.0, NextLayer, .scheme = 1}, + {"Cmp", "Cmp", 1.0, Compose, .scheme = 1}, + {",", "\"", 1.0, Code, KEY_APOSTROPHE, &layouts[ComposeMath]}, + {"", "Tab", 3.5, Code, KEY_SPACE}, +@@ -889,7 +887,7 @@ static struct key keys_compose_a[] = { + {"α", "Α", 1.0, Copy, 0x03B1, 0, 0x0391}, + {"", "", 9.0, Pad}, + {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"", "", 8.5, Pad}, + {"", "", 0.0, EndRow}, + {"Abc", "Abc", 1.0, BackLayer, .scheme = 1}, +@@ -913,7 +911,7 @@ static struct key keys_compose_e[] = { + {"ǝ", "Ə", 1.0, Copy, 0x0259, 0, 0x018F}, + {"", "", 8.0, Pad}, + {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"", "", 8.5, Pad}, + {"", "", 0.0, EndRow}, + {"Abc", "Abc", 1.0, BackLayer, .scheme = 1}, +@@ -930,7 +928,7 @@ static struct key keys_compose_y[] = { + {"υ", "Υ", 1.0, Copy, 0x03C5, 0, 0x03A5}, + {"", "", 9.0, Pad}, + {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"", "", 8.5, Pad}, + {"", "", 0.0, EndRow}, + {"Abc", "Abc", 1.0, BackLayer, .scheme = 1}, +@@ -953,7 +951,7 @@ static struct key keys_compose_u[] = { + {"υ", "Υ", 1.0, Copy, 0x03C5, 0, 0x03A5}, + {"", "", 9.0, Pad}, + {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"", "", 8.5, Pad}, + {"", "", 0.0, EndRow}, + {"Abc", "Abc", 1.0, BackLayer, .scheme = 1}, +@@ -977,7 +975,7 @@ static struct key keys_compose_o[] = { + {"ω", "Ο", 1.0, Copy, 0x03C9, 0, 0x03A9}, + {"", "", 8.0, Pad}, + {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"", "", 8.5, Pad}, + {"", "", 0.0, EndRow}, + {"Abc", "Abc", 1.0, BackLayer, .scheme = 1}, +@@ -1001,7 +999,7 @@ static struct key keys_compose_i[] = { + {"η", "Η", 1.0, Copy, 0x03B7, 0, 0x0397}, + {"", "", 8.0, Pad}, + {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"", "", 8.5, Pad}, + {"", "", 0.0, EndRow}, + {"Abc", "Abc", 1.0, BackLayer, .scheme = 1}, +@@ -1009,58 +1007,11 @@ static struct key keys_compose_i[] = { + {"", "", 0.0, Last}, + }; + +-static struct key keys_emoji[] = { +- {"🙂", "🙏", 1.0, Copy, 0x1f642, 0, 0x1f64f}, // Emojis +- {"😀", "🙋", 1.0, Copy, 0x1f600, 0, 0x1f64b}, +- {"😁", "✋", 1.0, Copy, 0x1f601, 0, 0x270B}, +- {"😂", "🙇", 1.0, Copy, 0x1f602, 0, 0x1f647}, +- {"😃", "👨", 1.0, Copy, 0x1f603, 0, 0x1f468}, +- {"😄", "👩", 1.0, Copy, 0x1f604, 0, 0x1f469}, +- {"😅", "👶", 1.0, Copy, 0x1f605, 0, 0x1f476}, +- {"😆", "👻", 1.0, Copy, 0x1f606, 0, 0x1f47b}, +- {"😇", "✨", 1.0, Copy, 0x1f607, 0, 0x2728}, +- {"🤣", "💰", 1.0, Copy, 0x1f923, 0, 0x1f4b0}, +- {"", "", 0.0, EndRow}, +- {"😉", "🐕", 1.0, Copy, 0x1f609, 0, 0x1f415}, +- {"😊", "🐈", 1.0, Copy, 0x1f60a, 0, 0x1f408}, +- {"😋", "🐧", 1.0, Copy, 0x1f60b, 0, 0x1f427}, +- {"😌", "🐇", 1.0, Copy, 0x1f60c, 0, 0x1f407}, +- {"😍", "💔", 1.0, Copy, 0x1f60d, 0, 0x1f494}, +- {"😘", "💕", 1.0, Copy, 0x1f618, 0, 0x1f495}, +- {"😎", "❤", 1.0, Copy, 0x1f60e, 0, 0x2764}, +- {"😐", "😏", 1.0, Copy, 0x1f610, 0, 0x1f60f}, +- {"😒", "👀", 1.0, Copy, 0x1f612, 0, 0x1f440}, +- {"😓", "💀", 1.0, Copy, 0x1f613, 0, 0x1f480}, +- {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.0, Mod, Shift, .scheme = 1}, +- {"😛", "😜", 1.0, Copy, 0x1f61b, 0, 0x1f61c}, +- {"😮", "😝", 1.0, Copy, 0x1f62e, 0, 0x1f61d}, +- {"😟", "😞", 1.0, Copy, 0x1f61f, 0, 0x1f61e}, +- {"😠", "🥺", 1.0, Copy, 0x1f620, 0, 0x1f97a}, +- {"😢", "👿", 1.0, Copy, 0x1f622, 0, 0x1f47f}, +- {"😭", "😯", 1.0, Copy, 0x1f62d, 0, 0x1f62f}, +- {"😳", "😕", 1.0, Copy, 0x1f633, 0, 0x1f615}, +- {"😴", "😵", 1.0, Copy, 0x1f634, 0, 0x1f635}, +- {"⌫", "⌫", 1.0, Code, KEY_BACKSPACE, .scheme = 1}, +- {"", "", 0.0, EndRow}, +- {"Abc", "Abc", 1.0, BackLayer, .scheme = 1}, +- {"⌨͕", "⌨͔", 1.0, NextLayer, .scheme = 1}, +- {"👆", "👊", 1.0, Copy, 0x1f446, 0, 0x1f44a}, +- {"👇", "👌", 1.0, Copy, 0x1f447, 0, 0x1f44c}, +- {"👈", "👏", 1.0, Copy, 0x1f448, 0, 0x1f44f}, +- {"👉", "👐", 1.0, Copy, 0x1f449, 0, 0x1f450}, +- {"👋", "🙌", 1.0, Copy, 0x1f44b, 0, 0x1f64c}, +- {"👍", "✅", 1.0, Copy, 0x1f44d, 0, 0x2705}, +- {"👎", "💪", 1.0, Copy, 0x1f44e, 0, 0x1f4aa}, +- {"Enter", "Enter", 1.0, Code, KEY_ENTER, .scheme = 1}, +- {"", "", 0.0, Last}, +-}; +- + static struct key keys_nav[] = { + {"Esc", "Esc", 1.0, Code, KEY_ESC, .scheme = 1}, +- {"⌫", "⌫", 1.0, Code, KEY_BACKSPACE, .scheme = 1}, ++ {"Back", "Back", 1.0, Code, KEY_BACKSPACE, .scheme = 1}, + {"↑", "↑", 1.0, Code, KEY_UP, .scheme = 1}, +- {"⇈", "⇈", 1.0, Code, KEY_PAGEUP, .scheme = 1}, ++ {"Up", "Up", 1.0, Code, KEY_PAGEUP, .scheme = 1}, + {"", "", 0.0, EndRow}, + + {"q", "q", 1.0, Code, KEY_Q, .scheme = 1}, +@@ -1069,10 +1020,10 @@ static struct key keys_nav[] = { + {"→", "→", 1.0, Code, KEY_RIGHT, .scheme = 1}, + {"", "", 0.0, EndRow}, + +- {"⌨͕", "⌨͔", 1.0, NextLayer, .scheme = 1}, +- {"", "↹", 1.0, Code, KEY_SPACE, .scheme = 1}, ++ {"123", "123", 1.0, NextLayer, .scheme = 1}, ++ {"", "Space", 1.0, Code, KEY_SPACE, .scheme = 1}, + {"↓", "↓", 1.0, Code, KEY_DOWN, .scheme = 1}, +- {"⇊", "⇊", 1.0, Code, KEY_PAGEDOWN, .scheme = 1}, ++ {"Down", "Down", 1.0, Code, KEY_PAGEDOWN, .scheme = 1}, + {"", "", 0.0, Last}, + }; + +@@ -1089,7 +1040,6 @@ static struct key keys_index[] = { + {"Pad", "Pad", 1.0, Layout, 0, &layouts[SpecialPad]}, + {"Nav", "Nav", 1.0, Layout, 0, &layouts[Nav], .scheme = 1}, + {"123", "123", 1.0, Layout, 0, &layouts[Dialer], .scheme = 1}, +- {"🙂", "🙂", 1.0, Layout, 0, &layouts[Emoji], .scheme = 1}, + {"", "", 0.0, EndRow}, + + {"Абв", "Абв", 1.0, Layout, 0, &layouts[Cyrillic], .scheme = 1}, +@@ -1104,7 +1054,7 @@ static struct key keys_index[] = { + static struct key keys_landscape[] = { + {"Esc", "Esc", 1.0, Code, KEY_ESC, .scheme = 1}, + {"", "", 0.5, Pad, .scheme = 1}, +- {"q", "Q", 1.0, Code, KEY_Q, &layouts[Emoji]}, ++ {"q", "Q", 1.0, Code, KEY_Q, &layouts[ComposeQ]}, + {"w", "W", 1.0, Code, KEY_W, &layouts[ComposeW]}, + {"e", "E", 1.0, Code, KEY_E, &layouts[ComposeE]}, + {"r", "R", 1.0, Code, KEY_R, &layouts[ComposeR]}, +@@ -1136,7 +1086,7 @@ static struct key keys_landscape[] = { + + {"←", "←", 0.75, Code, KEY_LEFT, .scheme = 1}, + {"→", "→", 0.75, Code, KEY_RIGHT, .scheme = 1}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"z", "Z", 1.0, Code, KEY_Z, &layouts[ComposeZ]}, + {"x", "X", 1.0, Code, KEY_X, &layouts[ComposeX]}, + {"c", "C", 1.0, Code, KEY_C, &layouts[ComposeC]}, +@@ -1146,10 +1096,10 @@ static struct key keys_landscape[] = { + {"m", "M", 1.0, Code, KEY_M, &layouts[ComposeM]}, + {"", "", 0.5, Pad, .scheme = 1}, + {"-", "_", 1.0, Code, KEY_MINUS, &layouts[ComposeBracket]}, +- {"⌫", "⌫", 1.5, Code, KEY_BACKSPACE, .scheme = 1}, ++ {"Back", "Back", 1.5, Code, KEY_BACKSPACE, .scheme = 1}, + {"", "", 0.0, EndRow}, + +- {"⌨͕", "⌨͔", 1.0, NextLayer, .scheme = 1}, ++ {"123", "123", 1.0, NextLayer, .scheme = 1}, + {"Cmp", "Cmp", 1.0, Compose, .scheme = 1}, + {"Ctr", "Ctr", 1.0, Mod, Ctrl, .scheme = 1}, + {",", "'", 1.0, Code, KEY_COMMA, &layouts[ComposeMath]}, +@@ -1178,10 +1128,9 @@ static struct key keys_landscape_special[] = { + {"Tab", "Tab", 1.0, Code, KEY_TAB, .scheme = 1}, + {"", "", 0.0, EndRow}, + +- {"⇈", "⇈", 1.0, Code, KEY_PAGEUP, .scheme = 1}, +- {"⇊", "⇊", 1.0, Code, KEY_PAGEDOWN, .scheme = 1}, ++ {"Up", "Up", 1.0, Code, KEY_PAGEUP, .scheme = 1}, ++ {"Down", "Down", 1.0, Code, KEY_PAGEDOWN, .scheme = 1}, + {"CpL", "CpL", 1.0, Mod, CapsLock, .scheme = 1}, +- {"🙂", "🙂", 1.0, Layout, 0, &layouts[Emoji]}, + {"`", "~", 1.0, Code, KEY_GRAVE}, + {"'", "\"", 1.0, Code, KEY_APOSTROPHE}, + {"-", "_", 1.0, Code, KEY_MINUS}, +@@ -1193,9 +1142,9 @@ static struct key keys_landscape_special[] = { + {"Del", "Del", 1.0, Code, KEY_DELETE, .scheme = 1}, + {"", "", 0.0, EndRow}, + +- {"⇤", "⇤", 1.0, Code, KEY_HOME, .scheme = 1}, +- {"⇥", "⇥", 1.0, Code, KEY_END, .scheme = 1}, +- {"⇧", "⇫", 2.0, Mod, Shift, .scheme = 1}, ++ {"Home", "Home", 1.0, Code, KEY_HOME, .scheme = 1}, ++ {"End", "End", 1.0, Code, KEY_END, .scheme = 1}, ++ {"Shift", "Shift", 2.0, Mod, Shift, .scheme = 1}, + {";", ":", 1.0, Code, KEY_SEMICOLON}, + {"<", "«", 1.0, Code, KEY_COMMA, 0, AltGr}, + {">", "»", 1.0, Code, KEY_DOT, 0, AltGr}, +@@ -1204,11 +1153,11 @@ static struct key keys_landscape_special[] = { + {".", "?", 1.0, Code, KEY_DOT, &layouts[ComposePunctuation]}, + {"/", ">", 1.0, Code, KEY_SLASH}, + {"", "", 0.5, Pad, .scheme = 1}, +- {"⌫", "⌫", 1.5, Code, KEY_BACKSPACE, .scheme = 1}, ++ {"Back", "Back", 1.5, Code, KEY_BACKSPACE, .scheme = 1}, + {"", "", 0.0, EndRow}, + + {"Abc", "Abc", 1.0, BackLayer, .scheme = 1}, +- {"⌨͕", "⌨͔", 1.0, NextLayer, .scheme = 1}, ++ {"123", "123", 1.0, NextLayer, .scheme = 1}, + {"Ctr", "Ctr", 1.0, Mod, Ctrl, .scheme = 1}, + {"Sup", "Sup", 1.0, Mod, Super, .scheme = 1}, + {"", "Tab", 5.0, Code, KEY_SPACE}, +@@ -1225,7 +1174,7 @@ static struct key keys_compose_w[] = { + {"", "", 9.0, Pad}, + {"", "", 0.0, EndRow}, + {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"", "", 8.5, Pad}, + {"", "", 0.0, EndRow}, + {"Abc", "Abc", 1.0, BackLayer, .scheme = 1}, +@@ -1242,7 +1191,7 @@ static struct key keys_compose_r[] = { + {"ρ", "Ρ", 1.0, Copy, 0x03C1, 0, 0x03A1}, + {"", "", 9.0, Pad}, + {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"", "", 8.5, Pad}, + {"", "", 0.0, EndRow}, + {"Abc", "Abc", 1.0, BackLayer, .scheme = 1}, +@@ -1261,7 +1210,7 @@ static struct key keys_compose_t[] = { + {"θ", "Θ", 1.0, Copy, 0x03B8, 0, 0x0398}, + {"", "", 8.0, Pad}, + {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"", "", 8.5, Pad}, + {"", "", 0.0, EndRow}, + {"Abc", "Abc", 1.0, BackLayer, .scheme = 1}, +@@ -1274,7 +1223,7 @@ static struct key keys_compose_p[] = { + {"", "", 9.0, Pad}, + {"", "", 0.0, EndRow}, + {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"", "", 8.5, Pad}, + {"", "", 0.0, EndRow}, + {"Abc", "Abc", 1.0, BackLayer, .scheme = 1}, +@@ -1294,7 +1243,7 @@ static struct key keys_compose_s[] = { + {"ς", "Σ", 1.0, Copy, 0x03C2, 0, 0x03A3}, + {"", "", 9.0, Pad}, + {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"", "", 8.5, Pad}, + {"", "", 0.0, EndRow}, + {"Abc", "Abc", 1.0, BackLayer, .scheme = 1}, +@@ -1311,7 +1260,7 @@ static struct key keys_compose_d[] = { + {"δ", "Δ", 1.0, Copy, 0x03B4, 0, 0x0394}, + {"", "", 9.0, Pad}, + {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"", "", 8.5, Pad}, + {"", "", 0.0, EndRow}, + {"Abc", "Abc", 1.0, BackLayer, .scheme = 1}, +@@ -1324,7 +1273,7 @@ static struct key keys_compose_f[] = { + {"", "", 9.0, Pad}, + {"", "", 0.0, EndRow}, + {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"", "", 8.5, Pad}, + {"", "", 0.0, EndRow}, + {"Abc", "Abc", 1.0, BackLayer, .scheme = 1}, +@@ -1340,7 +1289,7 @@ static struct key keys_compose_g[] = { + {"γ", "Γ", 1.0, Copy, 0x03B3, 0, 0x0393}, + {"", "", 9.0, Pad}, + {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"", "", 8.5, Pad}, + {"", "", 0.0, EndRow}, + {"Abc", "Abc", 1.0, BackLayer, .scheme = 1}, +@@ -1356,7 +1305,7 @@ static struct key keys_compose_h[] = { + {"η", "Η", 1.0, Copy, 0x03B7, 0, 0x0397}, + {"", "", 9.0, Pad}, + {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"", "", 8.5, Pad}, + {"", "", 0.0, EndRow}, + {"Abc", "Abc", 1.0, BackLayer, .scheme = 1}, +@@ -1370,7 +1319,7 @@ static struct key keys_compose_j[] = { + {"", "", 0.0, EndRow}, + {"", "", 10.0, Pad}, + {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"", "", 8.5, Pad}, + {"", "", 0.0, EndRow}, + {"Abc", "Abc", 1.0, BackLayer, .scheme = 1}, +@@ -1386,7 +1335,7 @@ static struct key keys_compose_k[] = { + {"κ", "Κ", 1.0, Copy, 0x03BA, 0, 0x039A}, + {"", "", 9.0, Pad}, + {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"", "", 8.5, Pad}, + {"", "", 0.0, EndRow}, + {"Abc", "Abc", 1.0, BackLayer, .scheme = 1}, +@@ -1403,7 +1352,7 @@ static struct key keys_compose_l[] = { + {"λ", "Λ", 1.0, Copy, 0x03BB, 0, 0x039B}, + {"", "", 9.0, Pad}, + {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"", "", 8.5, Pad}, + {"", "", 0.0, EndRow}, + {"Abc", "Abc", 1.0, BackLayer, .scheme = 1}, +@@ -1420,7 +1369,7 @@ static struct key keys_compose_z[] = { + {"ζ", "Ζ", 1.0, Copy, 0x03B6, 0, 0x0396}, + {"", "", 9.0, Pad}, + {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"", "", 8.5, Pad}, + {"", "", 0.0, EndRow}, + {"Abc", "Abc", 1.0, BackLayer, .scheme = 1}, +@@ -1434,7 +1383,7 @@ static struct key keys_compose_x[] = { + {"", "", 9.0, Pad}, + {"", "", 0.0, EndRow}, + {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"", "", 8.5, Pad}, + {"", "", 0.0, EndRow}, + {"Abc", "Abc", 1.0, BackLayer, .scheme = 1}, +@@ -1453,7 +1402,7 @@ static struct key keys_compose_c[] = { + {"χ", "Χ", 1.0, Copy, 0x03C7, 0, 0x03A7}, + {"", "", 9.0, Pad}, + {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"", "", 8.5, Pad}, + {"", "", 0.0, EndRow}, + {"Abc", "Abc", 1.0, BackLayer, .scheme = 1}, +@@ -1464,7 +1413,7 @@ static struct key keys_compose_c[] = { + static struct key keys_compose_v[] = { + {"", "", 0.0, EndRow}, + {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"", "", 8.5, Pad}, + {"", "", 0.0, EndRow}, + {"Abc", "Abc", 1.0, BackLayer, .scheme = 1}, +@@ -1477,7 +1426,7 @@ static struct key keys_compose_b[] = { + {"", "", 9.0, Pad}, + {"", "", 0.0, EndRow}, + {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"", "", 8.5, Pad}, + {"", "", 0.0, EndRow}, + {"Abc", "Abc", 1.0, BackLayer, .scheme = 1}, +@@ -1496,7 +1445,7 @@ static struct key keys_compose_n[] = { + {"ν", "Ν", 1.0, Copy, 0x03BD, 0, 0x039D}, + {"", "", 9.0, Pad}, + {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"", "", 8.5, Pad}, + {"", "", 0.0, EndRow}, + {"Abc", "Abc", 1.0, BackLayer, .scheme = 1}, +@@ -1509,7 +1458,20 @@ static struct key keys_compose_m[] = { + {"", "", 9.0, Pad}, + {"", "", 0.0, EndRow}, + {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, ++ {"", "", 8.5, Pad}, ++ {"", "", 0.0, EndRow}, ++ {"Abc", "Abc", 1.0, BackLayer, .scheme = 1}, ++ {"", "", 9, Pad}, ++ {"", "", 0.0, Last}, ++}; ++ ++static struct key keys_compose_q[] = { ++ {"q", "Q", 1.0, Copy, 0x0071, 0, 0x0051}, ++ {"", "", 9.0, Pad}, ++ {"", "", 0.0, EndRow}, ++ {"", "", 0.0, EndRow}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"", "", 8.5, Pad}, + {"", "", 0.0, EndRow}, + {"Abc", "Abc", 1.0, BackLayer, .scheme = 1}, +@@ -1523,7 +1485,7 @@ static struct key keys_compose_cyr_i[] = { + {"", "", 8.0, Pad}, + {"", "", 0.0, EndRow}, + {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"", "", 8.5, Pad}, + {"", "", 0.0, EndRow}, + {"Абв", "Абв", 1.0, BackLayer, .scheme = 1}, +@@ -1536,7 +1498,7 @@ static struct key keys_compose_cyr_j[] = { + {"", "", 9.0, Pad}, + {"", "", 0.0, EndRow}, + {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"", "", 8.5, Pad}, + {"", "", 0.0, EndRow}, + {"Абв", "Абв", 1.0, BackLayer, .scheme = 1}, +@@ -1549,7 +1511,7 @@ static struct key keys_compose_cyr_e[] = { + {"", "", 9.0, Pad}, + {"", "", 0.0, EndRow}, + {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"", "", 8.5, Pad}, + {"", "", 0.0, EndRow}, + {"Абв", "Абв", 1.0, BackLayer, .scheme = 1}, +@@ -1562,7 +1524,7 @@ static struct key keys_compose_cyr_u[] = { + {"", "", 9.0, Pad}, + {"", "", 0.0, EndRow}, + {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"", "", 8.5, Pad}, + {"", "", 0.0, EndRow}, + {"Абв", "Абв", 1.0, BackLayer, .scheme = 1}, +@@ -1575,7 +1537,7 @@ static struct key keys_compose_cyr_l[] = { + {"", "", 9.0, Pad}, + {"", "", 0.0, EndRow}, + {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"", "", 8.5, Pad}, + {"", "", 0.0, EndRow}, + {"Абв", "Абв", 1.0, BackLayer, .scheme = 1}, +@@ -1588,7 +1550,7 @@ static struct key keys_compose_cyr_n[] = { + {"", "", 9.0, Pad}, + {"", "", 0.0, EndRow}, + {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"", "", 8.5, Pad}, + {"", "", 0.0, EndRow}, + {"Абв", "Абв", 1.0, BackLayer, .scheme = 1}, +@@ -1602,7 +1564,7 @@ static struct key keys_compose_cyr_che[] = { + {"", "", 8.0, Pad}, + {"", "", 0.0, EndRow}, + {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"", "", 8.5, Pad}, + {"", "", 0.0, EndRow}, + {"Абв", "Абв", 1.0, BackLayer, .scheme = 1}, +@@ -1616,7 +1578,7 @@ static struct key keys_compose_cyr_tse[] = { + {"", "", 8.0, Pad}, + {"", "", 0.0, EndRow}, + {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"", "", 8.5, Pad}, + {"", "", 0.0, EndRow}, + {"Абв", "Абв", 1.0, BackLayer, .scheme = 1}, +@@ -1630,7 +1592,7 @@ static struct key keys_compose_cyr_g[] = { + {"", "", 8.0, Pad}, + {"", "", 0.0, EndRow}, + {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"", "", 8.5, Pad}, + {"", "", 0.0, EndRow}, + {"Абв", "Абв", 1.0, BackLayer, .scheme = 1}, +@@ -1643,7 +1605,7 @@ static struct key keys_compose_cyr_k[] = { + {"", "", 9.0, Pad}, + {"", "", 0.0, EndRow}, + {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"", "", 8.5, Pad}, + {"", "", 0.0, EndRow}, + {"Абв", "Абв", 1.0, BackLayer, .scheme = 1}, +@@ -1654,7 +1616,7 @@ static struct key keys_compose_cyr_k[] = { + static struct key keys_compose_math[] = { + {"", "", 0.0, EndRow}, + {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"+", "+", 1, Code, KEY_EQUAL, 0, Shift}, + {"/", "/", 1, Code, KEY_SLASH}, + {"*", "*", 1, Code, KEY_8, 0, Shift}, +@@ -1679,7 +1641,7 @@ static struct key keys_compose_punctuation[] = { + {"⍽", "⍽", 1, Copy, 0x202F, 0, 0x00A0}, + {"", "", 0.5, Pad}, + {"", "", 0.0, EndRow}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"", "", 3, Pad}, + {"!", "!", 1, Code, KEY_1, 0, Shift}, + {"?", "?", 1, Code, KEY_DOT, 0, Shift}, +@@ -1701,10 +1663,10 @@ static struct key keys_compose_bracket[] = { + {"]", "]", 1, Code, KEY_RIGHTBRACE}, + {"", "", 4.5, Pad}, + {"", "", 0, EndRow}, +- {"⇧", "⇫", 1.5, Mod, Shift, .scheme = 1}, ++ {"Shift", "Shift", 1.5, Mod, Shift, .scheme = 1}, + {"<", "<", 1, Code, KEY_COMMA, 0, AltGr}, + {">", ">", 1, Code, KEY_SLASH, 0, Shift}, +- {"`", "`", 1, Code, KEY_GRAVE}, ++ {"`", "~", 1, Code, KEY_GRAVE}, + {"\"", "\"", 1, Code, KEY_APOSTROPHE, 0, Shift}, + {"'", "'", 1, Code, KEY_APOSTROPHE}, + {"", "", 3.5, Pad}, diff --git a/projects/ArchR/packages/apps/archr-touchscreen-keyboard/patches/002-Add-pin-keyboard-to-specific-output.patch b/projects/ArchR/packages/apps/archr-touchscreen-keyboard/patches/002-Add-pin-keyboard-to-specific-output.patch new file mode 100644 index 0000000000..b7df551866 --- /dev/null +++ b/projects/ArchR/packages/apps/archr-touchscreen-keyboard/patches/002-Add-pin-keyboard-to-specific-output.patch @@ -0,0 +1,407 @@ +From 6d897e736916d1e34dac1474225e81d84e7edb64 Mon Sep 17 00:00:00 2001 +From: tiopex +Date: Sun, 9 Nov 2025 22:47:57 +0100 +Subject: [PATCH] Add pin keyboard to specific output + +--- + main.c | 83 +++++++++++- + proto/xdg-output-unstable-v1.xml | 222 +++++++++++++++++++++++++++++++ + 2 files changed, 303 insertions(+), 2 deletions(-) + create mode 100644 proto/xdg-output-unstable-v1.xml + +diff --git a/main.c b/main.c +index 502d2f5..e85174e 100644 +--- a/main.c ++++ b/main.c +@@ -3,6 +3,7 @@ + #include "proto/xdg-shell-client-protocol.h" + #include "proto/fractional-scale-v1-client-protocol.h" + #include "proto/viewporter-client-protocol.h" ++#include "proto/xdg-output-unstable-v1-client-protocol.h" + #include + #include + #include +@@ -47,7 +48,7 @@ static struct wp_fractional_scale_manager_v1 *wfs_mgr; + static struct wp_viewport *draw_surf_viewport, *popup_draw_surf_viewport; + static struct wp_viewporter *viewporter; + static bool popup_xdg_surface_configured; +- ++static struct wl_output *preferred_output = NULL; + struct Output { + uint32_t name; + uint32_t w, h; +@@ -55,6 +56,9 @@ struct Output { + struct wl_output *data; + }; + static struct Output *current_output; ++struct zxdg_output_manager_v1 *xdg_output_manager = NULL; ++static char preferred_output_name[64] = {0}; ++static bool preferred_output_set = false; + + #define WL_OUTPUTS_LIMIT 8 + static struct Output wl_outputs[WL_OUTPUTS_LIMIT]; +@@ -135,6 +139,24 @@ static void layer_surface_closed(void *data, + static void flip_landscape(); + static void show(); + ++static void xdg_output_done(void *data, struct zxdg_output_v1 *xdg_output); ++ ++static void xdg_output_name(void *data, ++ struct zxdg_output_v1 *xdg_output, ++ const char *name); ++ ++static void xdg_output_logical_position(void *data, ++ struct zxdg_output_v1 *xdg_output, ++ int32_t x, int32_t y); ++ ++static void xdg_output_logical_size(void *data, ++ struct zxdg_output_v1 *xdg_output, ++ int32_t width, int32_t height); ++ ++static void xdg_output_description(void *data, ++ struct zxdg_output_v1 *xdg_output, ++ const char *desc); ++ + /* event handlers */ + static const struct wl_pointer_listener pointer_listener = { + .enter = wl_pointer_enter, +@@ -174,6 +196,14 @@ static const struct zwlr_layer_surface_v1_listener layer_surface_listener = { + .closed = layer_surface_closed, + }; + ++static const struct zxdg_output_v1_listener xdg_output_listener = { ++ .name = xdg_output_name, ++ .done = xdg_output_done, ++ .logical_position = xdg_output_logical_position, ++ .logical_size = xdg_output_logical_size, ++ .description = xdg_output_description, ++}; ++ + /* configuration, allows nested code to access above variables */ + + char * +@@ -438,6 +468,33 @@ display_handle_mode(void *data, struct wl_output *wl_output, uint32_t flags, + { + } + ++static void xdg_output_done(void *data, struct zxdg_output_v1 *xdg_output) ++{ ++} ++ ++static void xdg_output_name(void *data, ++ struct zxdg_output_v1 *xdg_output, ++ const char *name) ++{ ++ struct Output *out = data; ++ if (preferred_output_set && strcmp(name, preferred_output_name) == 0) { ++ preferred_output = out->data; ++ fprintf(stderr, "wvkbd: assigned preferred output to: %s\n", name); ++ } ++} ++ ++static void xdg_output_logical_position(void *data, ++ struct zxdg_output_v1 *xdg_output, ++ int32_t x, int32_t y) {} ++ ++static void xdg_output_logical_size(void *data, ++ struct zxdg_output_v1 *xdg_output, ++ int32_t width, int32_t height) {} ++ ++static void xdg_output_description(void *data, ++ struct zxdg_output_v1 *xdg_output, ++ const char *desc) {} ++ + static const struct wl_output_listener output_listener = { + .geometry = display_handle_geometry, + .mode = display_handle_mode, +@@ -461,6 +518,9 @@ handle_global(void *data, struct wl_registry *registry, uint32_t name, + if (strcmp(interface, wl_compositor_interface.name) == 0) { + compositor = + wl_registry_bind(registry, name, &wl_compositor_interface, 3); ++ } else if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0) { ++ xdg_output_manager = wl_registry_bind( ++ registry, name, &zxdg_output_manager_v1_interface, 3); + } else if (strcmp(interface, wl_shm_interface.name) == 0) { + draw_ctx.shm = wl_registry_bind(registry, name, &wl_shm_interface, 1); + } else if (strcmp(interface, wl_output_interface.name) == 0) { +@@ -471,6 +531,12 @@ handle_global(void *data, struct wl_registry *registry, uint32_t name, + output->name = name; + output->scale = 1; + wl_output_add_listener(output->data, &output_listener, output); ++ wl_display_roundtrip(display); ++ if (xdg_output_manager) { ++ struct zxdg_output_v1 *xdg_output = ++ zxdg_output_manager_v1_get_xdg_output(xdg_output_manager, output->data); ++ zxdg_output_v1_add_listener(xdg_output, &xdg_output_listener, output); ++ } + wl_outputs_size += 1; + } + } else if (strcmp(interface, wl_seat_interface.name) == 0) { +@@ -716,6 +782,8 @@ usage(char *argv0) + " -l - Comma separated list of layers\n"); + fprintf(stderr, " --landscape-layers - Comma separated list of " + "landscape layers\n"); ++ fprintf(stderr, ++ " --output [name] - Pin keyboard to specific output (e.g. DSI-1, HDMI-A-1)\n"); + } + + void +@@ -777,8 +845,9 @@ show() + if (current_output) + current_output_data = current_output->data; + ++ struct wl_output *target_output = preferred_output ? preferred_output : current_output_data; + layer_surface = zwlr_layer_shell_v1_get_layer_surface( +- layer_shell, draw_surf.surf, current_output_data, layer, namespace); ++ layer_shell, draw_surf.surf, target_output, layer, namespace); + + zwlr_layer_surface_v1_set_size(layer_surface, 0, height); + zwlr_layer_surface_v1_set_anchor(layer_surface, anchor); +@@ -986,6 +1055,16 @@ main(int argc, char **argv) + (!strcmp(argv[i], "--list-layers"))) { + list_layers(); + exit(0); ++ } else if ((!strcmp(argv[i], "-output")) ++ || (!strcmp(argv[i], "--output"))) { ++ if (i >= argc - 1) { ++ usage(argv[0]); ++ exit(1); ++ } ++ strncpy(preferred_output_name, argv[++i], sizeof(preferred_output_name) - 1); ++ preferred_output_name[sizeof(preferred_output_name) - 1] = '\0'; ++ preferred_output_set = true; ++ fprintf(stderr, "wvkbd: preferred output set to: \"%s\"\n", preferred_output_name); + } else { + fprintf(stderr, "Invalid argument: %s\n", argv[i]); + usage(argv[0]); +diff --git a/proto/xdg-output-unstable-v1.xml b/proto/xdg-output-unstable-v1.xml +new file mode 100644 +index 0000000..a7306e4 +--- /dev/null ++++ b/proto/xdg-output-unstable-v1.xml +@@ -0,0 +1,222 @@ ++ ++ ++ ++ ++ Copyright © 2017 Red Hat Inc. ++ ++ 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 (including the next ++ paragraph) shall be included in all copies or substantial portions of the ++ Software. ++ ++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ DEALINGS IN THE SOFTWARE. ++ ++ ++ ++ This protocol aims at describing outputs in a way which is more in line ++ with the concept of an output on desktop oriented systems. ++ ++ Some information are more specific to the concept of an output for ++ a desktop oriented system and may not make sense in other applications, ++ such as IVI systems for example. ++ ++ Typically, the global compositor space on a desktop system is made of ++ a contiguous or overlapping set of rectangular regions. ++ ++ The logical_position and logical_size events defined in this protocol ++ might provide information identical to their counterparts already ++ available from wl_output, in which case the information provided by this ++ protocol should be preferred to their equivalent in wl_output. The goal is ++ to move the desktop specific concepts (such as output location within the ++ global compositor space, etc.) out of the core wl_output protocol. ++ ++ Warning! The protocol described in this file is experimental and ++ backward incompatible changes may be made. Backward compatible ++ changes may be added together with the corresponding interface ++ version bump. ++ Backward incompatible changes are done by bumping the version ++ number in the protocol and interface names and resetting the ++ interface version. Once the protocol is to be declared stable, ++ the 'z' prefix and the version number in the protocol and ++ interface names are removed and the interface version number is ++ reset. ++ ++ ++ ++ ++ A global factory interface for xdg_output objects. ++ ++ ++ ++ ++ Using this request a client can tell the server that it is not ++ going to use the xdg_output_manager object anymore. ++ ++ Any objects already created through this instance are not affected. ++ ++ ++ ++ ++ ++ This creates a new xdg_output object for the given wl_output. ++ ++ ++ ++ ++ ++ ++ ++ ++ An xdg_output describes part of the compositor geometry. ++ ++ This typically corresponds to a monitor that displays part of the ++ compositor space. ++ ++ For objects version 3 onwards, after all xdg_output properties have been ++ sent (when the object is created and when properties are updated), a ++ wl_output.done event is sent. This allows changes to the output ++ properties to be seen as atomic, even if they happen via multiple events. ++ ++ ++ ++ ++ Using this request a client can tell the server that it is not ++ going to use the xdg_output object anymore. ++ ++ ++ ++ ++ ++ The position event describes the location of the wl_output within ++ the global compositor space. ++ ++ The logical_position event is sent after creating an xdg_output ++ (see xdg_output_manager.get_xdg_output) and whenever the location ++ of the output changes within the global compositor space. ++ ++ ++ ++ ++ ++ ++ ++ The logical_size event describes the size of the output in the ++ global compositor space. ++ ++ Most regular Wayland clients should not pay attention to the ++ logical size and would rather rely on xdg_shell interfaces. ++ ++ Some clients such as Xwayland, however, need this to configure ++ their surfaces in the global compositor space as the compositor ++ may apply a different scale from what is advertised by the output ++ scaling property (to achieve fractional scaling, for example). ++ ++ For example, for a wl_output mode 3840×2160 and a scale factor 2: ++ ++ - A compositor not scaling the monitor viewport in its compositing space ++ will advertise a logical size of 3840×2160, ++ ++ - A compositor scaling the monitor viewport with scale factor 2 will ++ advertise a logical size of 1920×1080, ++ ++ - A compositor scaling the monitor viewport using a fractional scale of ++ 1.5 will advertise a logical size of 2560×1440. ++ ++ For example, for a wl_output mode 1920×1080 and a 90 degree rotation, ++ the compositor will advertise a logical size of 1080x1920. ++ ++ The logical_size event is sent after creating an xdg_output ++ (see xdg_output_manager.get_xdg_output) and whenever the logical ++ size of the output changes, either as a result of a change in the ++ applied scale or because of a change in the corresponding output ++ mode(see wl_output.mode) or transform (see wl_output.transform). ++ ++ ++ ++ ++ ++ ++ ++ This event is sent after all other properties of an xdg_output ++ have been sent. ++ ++ This allows changes to the xdg_output properties to be seen as ++ atomic, even if they happen via multiple events. ++ ++ For objects version 3 onwards, this event is deprecated. Compositors ++ are not required to send it anymore and must send wl_output.done ++ instead. ++ ++ ++ ++ ++ ++ ++ ++ Many compositors will assign names to their outputs, show them to the ++ user, allow them to be configured by name, etc. The client may wish to ++ know this name as well to offer the user similar behaviors. ++ ++ The naming convention is compositor defined, but limited to ++ alphanumeric characters and dashes (-). Each name is unique among all ++ wl_output globals, but if a wl_output global is destroyed the same name ++ may be reused later. The names will also remain consistent across ++ sessions with the same hardware and software configuration. ++ ++ Examples of names include 'HDMI-A-1', 'WL-1', 'X11-1', etc. However, do ++ not assume that the name is a reflection of an underlying DRM ++ connector, X11 connection, etc. ++ ++ The name event is sent after creating an xdg_output (see ++ xdg_output_manager.get_xdg_output). This event is only sent once per ++ xdg_output, and the name does not change over the lifetime of the ++ wl_output global. ++ ++ This event is deprecated, instead clients should use wl_output.name. ++ Compositors must still support this event. ++ ++ ++ ++ ++ ++ ++ Many compositors can produce human-readable descriptions of their ++ outputs. The client may wish to know this description as well, to ++ communicate the user for various purposes. ++ ++ The description is a UTF-8 string with no convention defined for its ++ contents. Examples might include 'Foocorp 11" Display' or 'Virtual X11 ++ output via :1'. ++ ++ The description event is sent after creating an xdg_output (see ++ xdg_output_manager.get_xdg_output) and whenever the description ++ changes. The description is optional, and may not be sent at all. ++ ++ For objects of version 2 and lower, this event is only sent once per ++ xdg_output, and the description does not change over the lifetime of ++ the wl_output global. ++ ++ This event is deprecated, instead clients should use ++ wl_output.description. Compositors must still support this event. ++ ++ ++ ++ ++ ++ +-- +2.43.0 + diff --git a/projects/ArchR/packages/apps/archr-touchscreen-keyboard/sources/archr-touchscreen-keyboard b/projects/ArchR/packages/apps/archr-touchscreen-keyboard/sources/archr-touchscreen-keyboard new file mode 100644 index 0000000000..a5cee42355 --- /dev/null +++ b/projects/ArchR/packages/apps/archr-touchscreen-keyboard/sources/archr-touchscreen-keyboard @@ -0,0 +1,39 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025-present ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile + +TSKEY=$(get_setting "archr.touchscreen-keyboard.enabled") +if [ ! -n "${TSKEY}" ]; then + if [ "$DEVICE_HAS_TOUCHSCREEN" == "true" ]; then + set_setting "archr.touchscreen-keyboard.enabled" "1" + else + set_setting "archr.touchscreen-keyboard.enabled" "0" + fi +fi + + +while true; do + TSKEY=$(get_setting "archr.touchscreen-keyboard.enabled") + if [[ "${DEVICE_HAS_TOUCHSCREEN}" == "true" ]] && [[ "${TSKEY}" == "1" ]]; then + PID="$(pidof wvkbd-mobintl)" + if [ "$PID" != "" ]; then + killall wvkbd-mobintl + elif [[ "${DEVICE_HAS_DUAL_SCREEN}" == "true" ]]; then + secondary_output=$(swaymsg -t get_outputs -r | jq -r '.[] | select(.focused == false) | .name') + swaymsg output ${secondary_output} power on + if [[ ! "${QUIRK_DEVICE}" == "Anbernic RG DS" ]]; then + tskb_height=720 + tskb_legend_size=35 + else + tskb_height=350 + tskb_legend_size=18 + fi + /usr/bin/wvkbd-mobintl -L ${tskb_height} -fg 6b6b75 -fg-sp 6b6b75 -bg 1d1d1d --text ffffff --text-sp ffffff -fn ${tskb_legend_size} -l simple --hidden --output ${secondary_output} + else + /usr/bin/wvkbd-mobintl -L 350 -fg 6b6b75 -fg-sp 6b6b75 -bg 1d1d1d --text ffffff --text-sp ffffff -fn 50 -l simple --hidden + fi + fi + sleep 5 +done diff --git a/projects/ArchR/packages/apps/archr-touchscreen-keyboard/system.d/touchkeyboard.service b/projects/ArchR/packages/apps/archr-touchscreen-keyboard/system.d/touchkeyboard.service new file mode 100644 index 0000000000..59275d005c --- /dev/null +++ b/projects/ArchR/packages/apps/archr-touchscreen-keyboard/system.d/touchkeyboard.service @@ -0,0 +1,15 @@ +[Unit] +Description=touchscreen keyboard service +After=input.service +RequiresMountsFor=/storage +Before=archr.target +StartLimitIntervalSec=0 + +[Service] +Environment=HOME=/storage +ExecStart=/usr/bin/archr-touchscreen-keyboard +Restart=always +RestartSec=1 + +[Install] +WantedBy=multi-user.target diff --git a/projects/ArchR/packages/apps/commander/package.mk b/projects/ArchR/packages/apps/commander/package.mk new file mode 100644 index 0000000000..dab793edc1 --- /dev/null +++ b/projects/ArchR/packages/apps/commander/package.mk @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2025-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="commander" +PKG_VERSION="b3c008cac3bff9de54a3542cecc53cc271058744" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/ROCKNIX/commander" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain SDL2 SDL2_image SDL2_gfx SDL2_ttf dejavu" +PKG_LONGDESC="A minimal SDL2 file manager for embedded Linux devices." +PKG_TOOLCHAIN="cmake" + +PKG_CMAKE_OPTS_TARGET+=" -DCMAKE_BUILD_TYPE=Release" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + mkdir -p ${INSTALL}/usr/share/commander + + cp -rf ${PKG_BUILD}/.${TARGET_NAME}/commander ${INSTALL}/usr/bin/ + cp -rf ${PKG_BUILD}/res ${INSTALL}/usr/share/commander/res + + chmod 0755 ${INSTALL}/usr/bin/commander +} diff --git a/projects/ArchR/packages/apps/control-gen/Makefile b/projects/ArchR/packages/apps/control-gen/Makefile new file mode 100644 index 0000000000..2cbe7e5c77 --- /dev/null +++ b/projects/ArchR/packages/apps/control-gen/Makefile @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +CXX ?= gcc +CCFLAGS = -W -Wall -std=c++11 `sdl2-config --cflags` + +BINARY = control-gen +LIBRARIES = -lSDL2 +SOURCES = "control-gen.cpp" + +all: + $(CXX) $(CFLAGS) $(SOURCES) -o $(BINARY) $(LIBRARIES) + +clean: + rm -f $(BINARY) diff --git a/projects/ArchR/packages/apps/control-gen/control-gen.cpp b/projects/ArchR/packages/apps/control-gen/control-gen.cpp new file mode 100644 index 0000000000..3c06b15215 --- /dev/null +++ b/projects/ArchR/packages/apps/control-gen/control-gen.cpp @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +#include +#include +#include + +int main() +{ + + SDL_GameControllerAddMappingsFromFile("/storage/.config/SDL-GameControllerDB/gamecontrollerdb.txt"); + SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER); + atexit(SDL_Quit); + + int num_joysticks = SDL_NumJoysticks(); + int i; + for(i = 0; i < num_joysticks; ++i) + { + SDL_Joystick* js = SDL_JoystickOpen(i); + if (js) + { + SDL_JoystickGUID guid = SDL_JoystickGetGUID(js); + bool is_controller = SDL_IsGameController(i); + + char guid_str[1024]; + SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str)); + if (is_controller) + { + const char* name = SDL_JoystickName(js); + + printf("controlfolder=\"/storage/.config/gptokeyb\"\nESUDO=\"sudo\"\nESUDOKILL=\"-sudokill\"\nexport SDL_GAMECONTROLLERCONFIG_FILE=\"$controlfolder/gamecontrollerdb.txt\"\nSDLDBFILE=\"${SDL_GAMECONTROLLERCONFIG_FILE}\"\n[ -z \"${SDLDBFILE}\" ] && SDLDBFILE=\"${controlfolder}/gamecontrollerdb.txt\"\nSDLDBUSERFILE=\"/storage/.config/SDL-GameControllerDB/gamecontrollerdb.txt\"\nget_controls() {\nANALOGSTICKS=\"2\"\nDEVICE=\"%s\"\nparam_device=\"%s\"\n}\nGPTOKEYB=\"$controlfolder/gptokeyb $ESUDOKILL\"", + guid_str, name); + } + SDL_JoystickClose(js); + } + } + + return 0; +} diff --git a/projects/ArchR/packages/apps/control-gen/package.mk b/projects/ArchR/packages/apps/control-gen/package.mk new file mode 100644 index 0000000000..99adf811b8 --- /dev/null +++ b/projects/ArchR/packages/apps/control-gen/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="control-gen" +PKG_VERSION="ea44ab254d09d2d86eeb70289673418df2beee75" +PKG_LICENSE="GPLv2" +PKG_DEPENDS_TARGET="toolchain SDL2" +PKG_LONGDESC="Generates control.txt for gptokeyb" +PKG_TOOLCHAIN="make" + +pre_make_target() { + cp -f ${PKG_DIR}/Makefile ${PKG_BUILD} + cp -f ${PKG_DIR}/control-gen.cpp ${PKG_BUILD} + CFLAGS+=" -I$(get_build_dir SDL2)/include -D_REENTRANT" +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp ${PKG_BUILD}/control-gen ${INSTALL}/usr/bin + cp -rf ${PKG_DIR}/scripts/* ${INSTALL}/usr/bin + chmod 0755 ${INSTALL}/usr/bin/* +} diff --git a/projects/ArchR/packages/apps/control-gen/scripts/control-gen_init.sh b/projects/ArchR/packages/apps/control-gen/scripts/control-gen_init.sh new file mode 100644 index 0000000000..318bbe196b --- /dev/null +++ b/projects/ArchR/packages/apps/control-gen/scripts/control-gen_init.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +#Check if gptokeyb exists in .config +if [ ! -d "/storage/.config/gptokeyb" ]; then + mkdir -p "/storage/.config/gptokeyb" +fi + +#Link gamecontrollerdb.txt +ln -sf /usr/config/SDL-GameControllerDB/gamecontrollerdb.txt /storage/.config/gptokeyb/gamecontrollerdb.txt + +#Link gptokeyb +ln -sf /usr/bin/gptokeyb /storage/.config/gptokeyb/gptokeyb + +#Run control-gen +/usr/bin/control-gen > /storage/.config/gptokeyb/control.ini diff --git a/projects/ArchR/packages/apps/device-switch/package.mk b/projects/ArchR/packages/apps/device-switch/package.mk new file mode 100644 index 0000000000..a51c4678c9 --- /dev/null +++ b/projects/ArchR/packages/apps/device-switch/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024-present JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="device-switch" +PKG_VERSION="" +PKG_LICENSE="mix" +PKG_DEPENDS_TARGET="toolchain" +PKG_SITE="" +PKG_URL="" +PKG_LONGDESC="Support script for switching device dtbs" +PKG_TOOLCHAIN="manual" + +makeinstall_target() { + + mkdir -p ${INSTALL}/usr/bin + cp ${PKG_DIR}/scripts/${DEVICE}/device-switch ${INSTALL}/usr/bin + chmod 0755 ${INSTALL}/usr/bin/* +} diff --git a/projects/ArchR/packages/apps/device-switch/scripts/RK3326/device-switch b/projects/ArchR/packages/apps/device-switch/scripts/RK3326/device-switch new file mode 100644 index 0000000000..fbc708ec31 --- /dev/null +++ b/projects/ArchR/packages/apps/device-switch/scripts/RK3326/device-switch @@ -0,0 +1,35 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024-present JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile + +EXTLCONF=/flash/extlinux/extlinux.conf +EXTLCONFBAK=${EXTLCONF}.orig + +case "$1" in + "") + echo $(cat /sys/firmware/devicetree/base/archr,device_switch/this | tr -d '\0') + ;; + "--options") + echo $(ls /sys/firmware/devicetree/base/archr,device_switch/ | grep -Ev '^(name|this)$') + ;; + *) + DTB=$(cat /sys/firmware/devicetree/base/archr,device_switch/$1 | tr -d '\0').dtb + [[ $? -eq 0 ]] || { echo "Cannot resolve dtb name for $1" >&2; exit 2; } + [ -f "/flash/${DTB}" ] || { echo "dtb not found: /flash/${DTB}"; exit 3; } + + mount -o remount,rw /flash + + [ -f ${EXTLCONFBAK} ] || cp ${EXTLCONF} ${EXTLCONFBAK} + grep -q '^ *FDT ' ${EXTLCONF} || sed -i 's|^\(.* FDTDIR .*$\)|\1\n FDT todo.dtb|' ${EXTLCONF} + sed -i "s|^ *FDT .*$| FDT /${DTB}|" ${EXTLCONF} + + echo $1 > /flash/device.name + rm -r /storage/remappings/* + + sync + mount -o remount,ro /flash + ;; +esac + diff --git a/projects/ArchR/packages/apps/device-switch/scripts/RK3326/device-switch.save b/projects/ArchR/packages/apps/device-switch/scripts/RK3326/device-switch.save new file mode 100644 index 0000000000..afb5b818b1 --- /dev/null +++ b/projects/ArchR/packages/apps/device-switch/scripts/RK3326/device-switch.save @@ -0,0 +1,20 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile + +mount -o remount,rw /flash +case $1 in + R33S) + sed -i "s#rk3566-rg353v-linux.dtb#rk3566-rg353p-linux.dtb#g" /flash/extlinux/extlinux.conf + ;; + R36S) + sed -i "s#rk3566-rg353p-linux.dtb#rk3566-rg353v-linux.dtb#g" /flash/extlinux/extlinux.conf + ;; +esac + +set_setting system.hostname ${1} + +sync +reboot diff --git a/projects/ArchR/packages/apps/fileman/package.mk b/projects/ArchR/packages/apps/fileman/package.mk new file mode 100644 index 0000000000..f47e9397f1 --- /dev/null +++ b/projects/ArchR/packages/apps/fileman/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present 351ELEC (https://github.com/351elec) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="fileman" +PKG_VERSION="6be2347233dc331dfd4eb57ea36289036933fe64" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/archr-linux/fileman" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain SDL2 SDL2_image SDL2_gfx SDL2_ttf" +PKG_LONGDESC="A Single panel file Manager." + +make_target() { + MAKEDEVICE=$(echo ${DEVICE^^} | sed "s#-#_##g") + make DEVICE=${MAKEDEVICE^^} RES_PATH=/usr/share/fileman/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/fileman + cp fileman ${INSTALL}/usr/bin/ + cp -rf res ${INSTALL}/usr/share/fileman/ + chmod 0755 ${INSTALL}/usr/bin/fileman +} diff --git a/projects/ArchR/packages/apps/gamecontrollerdb/config/gamecontrollerdb.txt b/projects/ArchR/packages/apps/gamecontrollerdb/config/gamecontrollerdb.txt new file mode 100644 index 0000000000..c629c6258e --- /dev/null +++ b/projects/ArchR/packages/apps/gamecontrollerdb/config/gamecontrollerdb.txt @@ -0,0 +1,26 @@ +1900fcf27a65645f6a6f797374696300,zed_joystick,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:b15,dpdown:b14,dpright:b16,dpup:b13,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a2,righty:a3, +03002758091200000031000011010000,OpenSimHardware OSH PB Controller,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b7,start:b6,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,rightshoulder:b5,righttrigger:b11,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3, +19000226010000000100000001010000,odroidgo2_joypad,platform:Linux,x:b2,a:b1,b:b0,y:b3,back:b10,start:b13,dpleft:b8,dpdown:b7,dpright:b9,dpup:b6,leftshoulder:b4,lefttrigger:b11,rightshoulder:b5,righttrigger:b12,leftx:a0,lefty:a1, +1900dea8010000000200000001010000,odroidgo2_v11_joypad,platform:Linux,x:b2,a:b1,b:b0,y:b3,back:b8,start:b9,dpleft:b14,dpdown:b13,dpright:b15,dpup:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1, +03009b4d4b4800000111000000010000,retrogame_joypad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:b15,dpdown:b14,dpright:b16,dpup:b13,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a2,righty:a3, +19009b4d4b4800000111000000010000,retrogame_joypad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b8,guide:b10,start:b9,dpleft:b15,dpdown:b14,dpright:b16,dpup:b13,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a2,righty:a3, +1900adda4b4800001211000000010000,retrogame_joypad_s1_f2,platform:Linux,x:b2,a:b1,b:b0,y:b3,back:b8,guide:b10,start:b9,dpleft:b15,dpdown:b14,dpright:b16,dpup:b13,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a2,righty:a3, +19009321b0c300000002000010000000,XU10 Gamepad,platform:Linux,x:b3,a:b2,b:b1,y:b0,back:b8,guide:b16,start:b9,dpleft:b14,dpdown:b13,dpright:b15,dpup:b12,leftshoulder:b4,lefttrigger:b7,rightshoulder:b5,righttrigger:b6,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3, +190014b301000000a20a000000010000,r33s_joypad,platform:Linux,x:b2,a:b1,b:b0,y:b3,back:b8,start:b9,dpleft:b12,dpdown:b11,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7, +1900e5914b4800007711000077010000,RGB20S Gamepad,platform:Linux,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,rightstick:b15,leftx:a0,lefty:a1,rightx:a2,righty:a3, +1900e7444b4800000111000034020000,rg552_joypad,platform:Linux,x:b2,a:b1,b:b0,y:b3,back:b8,start:b9,dpleft:b15,dpdown:b14,dpright:b16,dpup:b13,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a2,righty:a3, +03001a3447616d65466f726365204100,GameForce ACE Gamepad,a:b1,b:b0,dpdown:b13,dpleft:b14,lefty:a1,leftx:a0,leftshoulder:b5,leftstick:b10,lefttrigger:-a2,dpright:b15,+righty:+a4,-rightx:-a3,+rightx:+a3,-righty:-a4,rightshoulder:b6,rightstick:b11,righttrigger:-a5,back:b7,guide:b9,start:b8,dpup:b12,x:b3,y:b4,platform:Linux, +1900c3ea010000000100000001010000,odroidgo3_joypad,a:b1,b:b0,dpdown:b13,dpleft:b14,+lefty:+a1,-leftx:-a0,+leftx:+a0,-lefty:-a1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,dpright:b15,+righty:+a3,-rightx:-a2,+rightx:+a2,-righty:-a3,rightshoulder:b5,rightstick:b11,righttrigger:b7,back:b8,start:b9,dpup:b12,x:b2,y:b3,platform:Linux, +03001354474f2d556c74726120476100,GO-Ultra Gamepad,platform:Linux,a:b1,b:b0,dpdown:b15,dpleft:b16,guide:b11,+lefty:+a1,-leftx:-a0,+leftx:+a0,-lefty:-a1,leftshoulder:b5,leftstick:b12,lefttrigger:b7,dpright:b17,+righty:+a3,-rightx:-a2,+rightx:+a2,-righty:-a3,rightshoulder:b6,rightstick:b13,righttrigger:b8,back:b9,start:b10,dpup:b14,x:b3,y:b4, +1900d632010000002c0a000000010000,rg_arc_joypad,platform:Linux,x:b4,a:b0,b:b1,y:b3,back:b10,start:b11,dpleft:b14,dpdown:b13,dpright:b15,dpup:b12,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,righttrigger:b9,rightstick:b2,leftstick:b5,platform:Linux, +0300879bfeca00000550000011010000,CM5 Gamepad,platform:Linux,a:b0,b:b1,x:b2,y:b3,back:b5,guide:b14,start:b4,leftstick:b12,rightstick:b13,leftshoulder:b11,rightshoulder:b10,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7, +1900c3bbb0c300000002000010000000,XU Mini M Gamepad,platform:Linux,x:b2,a:b1,b:b0,y:b3,back:b8,guide:b16,start:b9,dpleft:b14,dpdown:b13,dpright:b15,dpup:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3, +0300f353202000000130000001000000,Retroid Pocket Gamepad,platform:Linux,x:b2,a:b1,b:b0,y:b3,back:b6,guide:b8,start:b7,dpleft:b13,dpdown:b12,dpright:b14,dpup:b11,leftshoulder:b4,lefttrigger:a6,rightshoulder:b5,righttrigger:a7,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,misc1:b15, +19003982010000008811000088010000,r36s_Gamepad,platform:Linux,a:b1,b:b0,dpdown:b14,dpleft:b15,+lefty:+a1,-leftx:-a0,+leftx:+a0,-lefty:-a1,leftshoulder:b4,leftstick:b11,lefttrigger:b6,dpright:b16,+righty:+a3,-rightx:-a2,+rightx:+a2,-righty:-a3,rightshoulder:b5,rightstick:b12,righttrigger:b7,back:b8,start:b9,dpup:b13,x:b2,y:b3, +1900f6a24b480000df14000000010000,H700 Gamepad,platform:Linux,x:b3,a:b1,b:b0,y:b2,back:b8,guide:b10,start:b9,dpleft:b15,dpdown:b14,dpright:b16,dpup:b13,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a2,righty:a3, +0300b605202000000130000001000000,AYN Odin2 Gamepad,platform:Linux,x:b2,a:b1,b:b0,y:b3,back:b6,guide:b8,start:b7,dpleft:b13,dpdown:b12,dpright:b14,dpup:b11,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4, +1900365541594e204f64696e20476100,AYN Odin Gamepad,platform:Linux,x:b2,a:b1,b:b0,y:b3,back:b8,guide:b10,start:b9,dpleft:b15,dpdown:b14,dpright:b16,dpup:b13,leftshoulder:b4,lefttrigger:a5,rightshoulder:b5,righttrigger:a4,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a2,righty:a3, +030081b85e0400008e02000000020000,Xbox 360 Controller,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4, + +#InputPlumber Controller +0300f5a35e040000120b000001000000,InputPlumber GameController,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,misc1:b15,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4, diff --git a/projects/ArchR/packages/apps/gamecontrollerdb/package.mk b/projects/ArchR/packages/apps/gamecontrollerdb/package.mk new file mode 100644 index 0000000000..18793bf68a --- /dev/null +++ b/projects/ArchR/packages/apps/gamecontrollerdb/package.mk @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="gamecontrollerdb" +PKG_VERSION="e1efb4bad8730b2c0c6316617cbd06b9def1192e" +PKG_LICENSE="GPL" +PKG_DEPENDS_TARGET="toolchain SDL2" +PKG_SITE="https://github.com/gabomdq/SDL_GameControllerDB" +PKG_URL="${PKG_SITE}.git" +PKG_LONGDESC="SDL Game Controller DB" +PKG_TOOLCHAIN="manual" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/config/SDL-GameControllerDB + if [ -f "${PKG_DIR}/config/gamecontrollerdb.txt" ]; then + cat ${PKG_DIR}/config/gamecontrollerdb.txt >${INSTALL}/usr/config/SDL-GameControllerDB/gamecontrollerdb.txt + fi + cat ${PKG_BUILD}/gamecontrollerdb.txt >>${INSTALL}/usr/config/SDL-GameControllerDB/gamecontrollerdb.txt +} diff --git a/projects/ArchR/packages/apps/gamepadtester/package.mk b/projects/ArchR/packages/apps/gamepadtester/package.mk new file mode 100644 index 0000000000..8c6cc7f39d --- /dev/null +++ b/projects/ArchR/packages/apps/gamepadtester/package.mk @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="gamepadtester" +PKG_VERSION="6ac49e67aa98fe3dd5c27f73306d65d4b7a82daa" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/timre13/GamepadTester" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain SDL2 SDL2_gfx gamecontrollerdb" +PKG_LONGDESC="A simple SDL GUI Gamepad tester" +PKG_TOOLCHAIN="cmake" +PKG_PATCH_DIRS+="${DEVICE}" + +case ${DEVICE} in + SM8650|SM8550) + PKG_PATCH_DIRS+=" xbox" + ;; + *) + PKG_PATCH_DIRS+=" legacy" + ;; +esac + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp -rf ${PKG_BUILD}/.${TARGET_NAME}/gamepad_test ${INSTALL}/usr/bin/gamepad-tester + chmod 0755 ${INSTALL}/usr/bin/gamepad-tester + + mkdir -p ${INSTALL}/usr/config/modules + cp -rf ${PKG_DIR}/scripts/* ${INSTALL}/usr/config/modules + chmod 0755 ${INSTALL}/usr/config/modules/* +} diff --git a/projects/ArchR/packages/apps/gamepadtester/patches/RK3399/000-set-resolution.patch b/projects/ArchR/packages/apps/gamepadtester/patches/RK3399/000-set-resolution.patch new file mode 100644 index 0000000000..8c6ffab599 --- /dev/null +++ b/projects/ArchR/packages/apps/gamepadtester/patches/RK3399/000-set-resolution.patch @@ -0,0 +1,14 @@ +diff -rupN GamepadTester.orig/src/main.cpp GamepadTester/src/main.cpp +--- GamepadTester.orig/src/main.cpp 2024-04-26 21:31:53.731460755 +0000 ++++ GamepadTester/src/main.cpp 2024-04-26 22:29:53.239175112 +0000 +@@ -5,8 +5,8 @@ + #include + + #define STICK_MAX_VAL (float(0x7fff)) +-#define WIN_W 1100 +-#define WIN_H 800 ++#define WIN_W 1920 ++#define WIN_H 1152 + + std::string cStringToStdString(const char* str, const std::string& or_="N/A") + { diff --git a/projects/ArchR/packages/apps/gamepadtester/patches/RK3588/000-set-resolution.patch b/projects/ArchR/packages/apps/gamepadtester/patches/RK3588/000-set-resolution.patch new file mode 100644 index 0000000000..6ca1fc8f89 --- /dev/null +++ b/projects/ArchR/packages/apps/gamepadtester/patches/RK3588/000-set-resolution.patch @@ -0,0 +1,14 @@ +diff -rupN GamepadTester.orig/src/main.cpp GamepadTester/src/main.cpp +--- GamepadTester.orig/src/main.cpp 2024-04-26 21:31:53.731460755 +0000 ++++ GamepadTester/src/main.cpp 2024-04-26 22:30:25.679908246 +0000 +@@ -5,8 +5,8 @@ + #include + + #define STICK_MAX_VAL (float(0x7fff)) +-#define WIN_W 1100 +-#define WIN_H 800 ++#define WIN_W 1920 ++#define WIN_H 1080 + + std::string cStringToStdString(const char* str, const std::string& or_="N/A") + { diff --git a/projects/ArchR/packages/apps/gamepadtester/patches/legacy/000-gamepad-tester.patch b/projects/ArchR/packages/apps/gamepadtester/patches/legacy/000-gamepad-tester.patch new file mode 100644 index 0000000000..1f1fe71582 --- /dev/null +++ b/projects/ArchR/packages/apps/gamepadtester/patches/legacy/000-gamepad-tester.patch @@ -0,0 +1,118 @@ +diff -rupN GamepadTester.orig/CMakeLists.txt GamepadTester/CMakeLists.txt +--- GamepadTester.orig/CMakeLists.txt 2024-04-26 21:31:53.727460671 +0000 ++++ GamepadTester/CMakeLists.txt 2024-04-26 21:30:53.862216932 +0000 +@@ -6,7 +6,6 @@ set(CMAKE_CXX_STANDARD_REQUIRED TRUE) + project(gamepad_test VERSION 1.0) + + link_libraries(SDL2 SDL2_gfx) +-include_directories(/usr/include/SDL2) + + set(CMAKE_CXX_FLAGS "\ + -D_REENTRANT\ +diff -rupN GamepadTester.orig/src/main.cpp GamepadTester/src/main.cpp +--- GamepadTester.orig/src/main.cpp 2024-04-26 21:31:53.731460755 +0000 ++++ GamepadTester/src/main.cpp 2024-04-26 22:27:08.203425064 +0000 +@@ -38,7 +38,7 @@ int main() + SDL_Renderer* rend = SDL_CreateRenderer(window, 0, 0); + gfxPrimitivesSetFont(gfxPrimitivesFontdata, 8, 8); + +- SDL_GameControllerAddMappingsFromFile("../gamecontrollerdb.txt"); ++ SDL_GameControllerAddMappingsFromFile("/storage/.config/SDL-GameControllerDB/gamecontrollerdb.txt"); + + SDL_GameController* gcont = nullptr; + StickState leftStickState{}; +@@ -74,7 +74,6 @@ int main() + + case SDL_CONTROLLERBUTTONDOWN: + std::cout << "Controller button down: " << +event.cbutton.button << '\n'; +- SDL_GameControllerRumble(gcont, 0, 0xffff/2, 200); + buttonStates[event.cbutton.button] = true; + break; + +@@ -83,16 +82,6 @@ int main() + buttonStates[event.cbutton.button] = false; + break; + +- case SDL_JOYBUTTONDOWN: +- if (event.jbutton.button == 8) +- buttonStates[SDL_CONTROLLER_BUTTON_GUIDE] = true; +- break; +- +- case SDL_JOYBUTTONUP: +- if (event.jbutton.button == 8) +- buttonStates[SDL_CONTROLLER_BUTTON_GUIDE] = false; +- break; +- + case SDL_CONTROLLERAXISMOTION: + std::cout << "Controller axis movement\n"; + std::cout << "\tAxis: " << +event.caxis.axis << '\n'; +@@ -153,45 +142,57 @@ int main() + filledCircleColor(rend, WIN_W-300+rightStickState.x*30, WIN_H-300+rightStickState.y*30, 30, + (buttonStates[SDL_CONTROLLER_BUTTON_RIGHTSTICK] ? 0xffffffff : 0)); + +- // Y button ++ // X button + aacircleRGBA(rend, WIN_W-300, 300-40, 20, 255, 255, 0, 255); +- if (buttonStates[SDL_CONTROLLER_BUTTON_Y]) ++ if (buttonStates[SDL_CONTROLLER_BUTTON_X]) + filledCircleRGBA(rend, WIN_W-300, 300-40, 20, 255, 255, 0, 255); + +- // X button ++ // Y button + aacircleRGBA(rend, WIN_W-300-40, 300+40-40, 20, 100, 100, 255, 255); +- if (buttonStates[SDL_CONTROLLER_BUTTON_X]) ++ if (buttonStates[SDL_CONTROLLER_BUTTON_Y]) + filledCircleRGBA(rend, WIN_W-300-40, 300+40-40, 20, 100, 100, 255, 255); + +- // B button ++ // A button + aacircleRGBA(rend, WIN_W-300+40, 300+40-40, 20, 255, 0, 0, 255); +- if (buttonStates[SDL_CONTROLLER_BUTTON_B]) ++ if (buttonStates[SDL_CONTROLLER_BUTTON_A]) + filledCircleRGBA(rend, WIN_W-300+40, 300+40-40, 20, 255, 0, 0, 255); + +- // A button ++ // B button + aacircleRGBA(rend, WIN_W-300, 300+80-40, 20, 0, 255, 0, 255); +- if (buttonStates[SDL_CONTROLLER_BUTTON_A]) ++ if (buttonStates[SDL_CONTROLLER_BUTTON_B]) + filledCircleRGBA(rend, WIN_W-300, 300+80-40, 20, 0, 255, 0, 255); + + // D-pad up + aatrigonRGBA(rend, 300, WIN_H-360, 280, WIN_H-320, 320, WIN_H-320, 255, 255, 255, 255); +- if (dpadState & SDL_HAT_UP) ++ if (dpadState & SDL_HAT_UP) { ++ filledTrigonRGBA(rend, 300, WIN_H-360, 280, WIN_H-320, 320, WIN_H-320, 255, 255, 255, 255); ++ } else if (buttonStates[SDL_CONTROLLER_BUTTON_DPAD_UP]) { + filledTrigonRGBA(rend, 300, WIN_H-360, 280, WIN_H-320, 320, WIN_H-320, 255, 255, 255, 255); ++ } + + // D-pad down + aatrigonRGBA(rend, 300, WIN_H-240, 280, WIN_H-280, 320, WIN_H-280, 255, 255, 255, 255); +- if (dpadState & SDL_HAT_DOWN) ++ if (dpadState & SDL_HAT_DOWN) { + filledTrigonRGBA(rend, 300, WIN_H-240, 280, WIN_H-280, 320, WIN_H-280, 255, 255, 255, 255); ++ } else if (buttonStates[SDL_CONTROLLER_BUTTON_DPAD_DOWN]) { ++ filledTrigonRGBA(rend, 300, WIN_H-240, 280, WIN_H-280, 320, WIN_H-280, 255, 255, 255, 255); ++ } + + // D-pad left + aatrigonRGBA(rend, 240, WIN_H-300, 280, WIN_H-320, 280, WIN_H-280, 255, 255, 255, 255); +- if (dpadState & SDL_HAT_LEFT) ++ if (dpadState & SDL_HAT_LEFT) { ++ filledTrigonRGBA(rend, 240, WIN_H-300, 280, WIN_H-320, 280, WIN_H-280, 255, 255, 255, 255); ++ } else if (buttonStates[SDL_CONTROLLER_BUTTON_DPAD_LEFT]) { + filledTrigonRGBA(rend, 240, WIN_H-300, 280, WIN_H-320, 280, WIN_H-280, 255, 255, 255, 255); ++ } + + // D-pad right + aatrigonRGBA(rend, 360, WIN_H-300, 320, WIN_H-320, 320, WIN_H-280, 255, 255, 255, 255); +- if (dpadState & SDL_HAT_RIGHT) ++ if (dpadState & SDL_HAT_RIGHT) { ++ filledTrigonRGBA(rend, 360, WIN_H-300, 320, WIN_H-320, 320, WIN_H-280, 255, 255, 255, 255); ++ } else if (buttonStates[SDL_CONTROLLER_BUTTON_DPAD_RIGHT]) { + filledTrigonRGBA(rend, 360, WIN_H-300, 320, WIN_H-320, 320, WIN_H-280, 255, 255, 255, 255); ++ } + + // Left bumper + rectangleColor(rend, 300-50, 300-150-20, 300+50, 300-150+20, 0xffffffff); diff --git a/projects/ArchR/packages/apps/gamepadtester/patches/xbox/000-gamepad-tester.patch b/projects/ArchR/packages/apps/gamepadtester/patches/xbox/000-gamepad-tester.patch new file mode 100644 index 0000000000..a303cc4f92 --- /dev/null +++ b/projects/ArchR/packages/apps/gamepadtester/patches/xbox/000-gamepad-tester.patch @@ -0,0 +1,102 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 2df8fda..4ae98f1 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -6,7 +6,6 @@ set(CMAKE_CXX_STANDARD_REQUIRED TRUE) + project(gamepad_test VERSION 1.0) + + link_libraries(SDL2 SDL2_gfx) +-include_directories(/usr/include/SDL2) + + set(CMAKE_CXX_FLAGS "\ + -D_REENTRANT\ +diff --git a/src/main.cpp b/src/main.cpp +index 7381b9b..eb25c84 100644 +--- a/src/main.cpp ++++ b/src/main.cpp +@@ -38,7 +38,7 @@ int main() + SDL_Renderer* rend = SDL_CreateRenderer(window, 0, 0); + gfxPrimitivesSetFont(gfxPrimitivesFontdata, 8, 8); + +- SDL_GameControllerAddMappingsFromFile("../gamecontrollerdb.txt"); ++ SDL_GameControllerAddMappingsFromFile("/storage/.config/SDL-GameControllerDB/gamecontrollerdb.txt"); + + SDL_GameController* gcont = nullptr; + StickState leftStickState{}; +@@ -74,7 +74,6 @@ int main() + + case SDL_CONTROLLERBUTTONDOWN: + std::cout << "Controller button down: " << +event.cbutton.button << '\n'; +- SDL_GameControllerRumble(gcont, 0, 0xffff/2, 200); + buttonStates[event.cbutton.button] = true; + break; + +@@ -83,16 +82,6 @@ int main() + buttonStates[event.cbutton.button] = false; + break; + +- case SDL_JOYBUTTONDOWN: +- if (event.jbutton.button == 8) +- buttonStates[SDL_CONTROLLER_BUTTON_GUIDE] = true; +- break; +- +- case SDL_JOYBUTTONUP: +- if (event.jbutton.button == 8) +- buttonStates[SDL_CONTROLLER_BUTTON_GUIDE] = false; +- break; +- + case SDL_CONTROLLERAXISMOTION: + std::cout << "Controller axis movement\n"; + std::cout << "\tAxis: " << +event.caxis.axis << '\n'; +@@ -175,23 +164,35 @@ int main() + + // D-pad up + aatrigonRGBA(rend, 300, WIN_H-360, 280, WIN_H-320, 320, WIN_H-320, 255, 255, 255, 255); +- if (dpadState & SDL_HAT_UP) ++ if (dpadState & SDL_HAT_UP) { ++ filledTrigonRGBA(rend, 300, WIN_H-360, 280, WIN_H-320, 320, WIN_H-320, 255, 255, 255, 255); ++ } else if (buttonStates[SDL_CONTROLLER_BUTTON_DPAD_UP]) { + filledTrigonRGBA(rend, 300, WIN_H-360, 280, WIN_H-320, 320, WIN_H-320, 255, 255, 255, 255); ++ } + + // D-pad down + aatrigonRGBA(rend, 300, WIN_H-240, 280, WIN_H-280, 320, WIN_H-280, 255, 255, 255, 255); +- if (dpadState & SDL_HAT_DOWN) ++ if (dpadState & SDL_HAT_DOWN) { + filledTrigonRGBA(rend, 300, WIN_H-240, 280, WIN_H-280, 320, WIN_H-280, 255, 255, 255, 255); ++ } else if (buttonStates[SDL_CONTROLLER_BUTTON_DPAD_DOWN]) { ++ filledTrigonRGBA(rend, 300, WIN_H-240, 280, WIN_H-280, 320, WIN_H-280, 255, 255, 255, 255); ++ } + + // D-pad left + aatrigonRGBA(rend, 240, WIN_H-300, 280, WIN_H-320, 280, WIN_H-280, 255, 255, 255, 255); +- if (dpadState & SDL_HAT_LEFT) ++ if (dpadState & SDL_HAT_LEFT) { ++ filledTrigonRGBA(rend, 240, WIN_H-300, 280, WIN_H-320, 280, WIN_H-280, 255, 255, 255, 255); ++ } else if (buttonStates[SDL_CONTROLLER_BUTTON_DPAD_LEFT]) { + filledTrigonRGBA(rend, 240, WIN_H-300, 280, WIN_H-320, 280, WIN_H-280, 255, 255, 255, 255); ++ } + + // D-pad right + aatrigonRGBA(rend, 360, WIN_H-300, 320, WIN_H-320, 320, WIN_H-280, 255, 255, 255, 255); +- if (dpadState & SDL_HAT_RIGHT) ++ if (dpadState & SDL_HAT_RIGHT) { + filledTrigonRGBA(rend, 360, WIN_H-300, 320, WIN_H-320, 320, WIN_H-280, 255, 255, 255, 255); ++ } else if (buttonStates[SDL_CONTROLLER_BUTTON_DPAD_RIGHT]) { ++ filledTrigonRGBA(rend, 360, WIN_H-300, 320, WIN_H-320, 320, WIN_H-280, 255, 255, 255, 255); ++ } + + // Left bumper + rectangleColor(rend, 300-50, 300-150-20, 300+50, 300-150+20, 0xffffffff); +@@ -221,6 +222,11 @@ int main() + if (buttonStates[SDL_CONTROLLER_BUTTON_START]) + filledCircleColor(rend, WIN_W/2+40, WIN_H/2, 20, 0xffffffff); + ++ // Misc1 button (Share) ++ aacircleColor(rend, WIN_W/2, WIN_H/2 + 50, 18, 0xffffffff); ++ if (buttonStates[SDL_CONTROLLER_BUTTON_MISC1]) ++ filledCircleColor(rend, WIN_W/2, WIN_H/2 + 50, 18, 0xffffffff); ++ + // Guide button + aacircleColor(rend, WIN_W/2, WIN_H/2-60, 30, 0xffffffff); + if (buttonStates[SDL_CONTROLLER_BUTTON_GUIDE]) diff --git a/projects/ArchR/packages/apps/gamepadtester/scripts/Test Gamepad.sh b/projects/ArchR/packages/apps/gamepadtester/scripts/Test Gamepad.sh new file mode 100644 index 0000000000..9b2f768013 --- /dev/null +++ b/projects/ArchR/packages/apps/gamepadtester/scripts/Test Gamepad.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +source /etc/profile + +set_kill set "gamepad-tester" + +sway_fullscreen "gamepad-tester" & + +/usr/bin/gamepad-tester diff --git a/projects/ArchR/packages/apps/jstest-sdl/package.mk b/projects/ArchR/packages/apps/jstest-sdl/package.mk new file mode 100644 index 0000000000..75a868e383 --- /dev/null +++ b/projects/ArchR/packages/apps/jstest-sdl/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="jstest-sdl" +PKG_VERSION="f4fdf6daae687d19b303d8ba8809ff5a68bc33a4" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/archr-linux/jstest-sdl" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain SDL2 ncurses" +PKG_LONGDESC="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/projects/ArchR/packages/apps/jstest-sdl/patches/001-fix-building-with-gcc15.patch b/projects/ArchR/packages/apps/jstest-sdl/patches/001-fix-building-with-gcc15.patch new file mode 100644 index 0000000000..b2ae8cf390 --- /dev/null +++ b/projects/ArchR/packages/apps/jstest-sdl/patches/001-fix-building-with-gcc15.patch @@ -0,0 +1,24 @@ +From a621a74a5099612fbd4a0689aca4dc6ee7b4080f Mon Sep 17 00:00:00 2001 +From: spycat88 +Date: Sun, 16 Nov 2025 15:40:43 +0000 +Subject: [PATCH] fix building with gcc15 + +--- + jstest-sdl.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/jstest-sdl.c b/jstest-sdl.c +index d576029..b76ed08 100644 +--- a/jstest-sdl.c ++++ b/jstest-sdl.c +@@ -44,6 +44,7 @@ + #include + #include + #include ++#include + #include + #include + +-- +2.34.1 + diff --git a/projects/ArchR/packages/apps/list-guid/Makefile b/projects/ArchR/packages/apps/list-guid/Makefile new file mode 100644 index 0000000000..1388448f7c --- /dev/null +++ b/projects/ArchR/packages/apps/list-guid/Makefile @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +CXX ?= gcc +CCFLAGS = -W -Wall -std=c++11 `sdl2-config --cflags` + +BINARY = list-guid +LIBRARIES = -lSDL2 +SOURCES = "list-guid.cpp" + +all: + $(CXX) $(CFLAGS) $(SOURCES) -o $(BINARY) $(LIBRARIES) + +clean: + rm -f $(BINARY) diff --git a/projects/ArchR/packages/apps/list-guid/list-guid.cpp b/projects/ArchR/packages/apps/list-guid/list-guid.cpp new file mode 100644 index 0000000000..5a15f5d5de --- /dev/null +++ b/projects/ArchR/packages/apps/list-guid/list-guid.cpp @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +#include +#include +#include + +int main() +{ + + SDL_GameControllerAddMappingsFromFile("/storage/.config/SDL-GameControllerDB/gamecontrollerdb.txt"); + SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER); + atexit(SDL_Quit); + + int num_joysticks = SDL_NumJoysticks(); + int i; + for(i = 0; i < num_joysticks; ++i) + { + SDL_Joystick* js = SDL_JoystickOpen(i); + if (js) + { + SDL_JoystickGUID guid = SDL_JoystickGetGUID(js); + bool is_controller = SDL_IsGameController(i); + + char guid_str[1024]; + SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str)); + if (is_controller) + { + printf("%s\n", + guid_str); + } + SDL_JoystickClose(js); + } + } + + return 0; +} diff --git a/projects/ArchR/packages/apps/list-guid/package.mk b/projects/ArchR/packages/apps/list-guid/package.mk new file mode 100644 index 0000000000..1c88983718 --- /dev/null +++ b/projects/ArchR/packages/apps/list-guid/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="list-guid" +PKG_VERSION="ea44ab254d09d2d86eeb70289673418df2beee75" +PKG_LICENSE="GPLv2" +PKG_DEPENDS_TARGET="toolchain SDL2" +PKG_LONGDESC="Simple SDL tool to create a list off GUIDs for all connected gamepads." +PKG_TOOLCHAIN="make" + +pre_make_target() { + cp -f ${PKG_DIR}/Makefile ${PKG_BUILD} + cp -f ${PKG_DIR}/list-guid.cpp ${PKG_BUILD} + CFLAGS+=" -I$(get_build_dir SDL2)/include -D_REENTRANT" +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp ${PKG_BUILD}/list-guid ${INSTALL}/usr/bin + chmod 0755 ${INSTALL}/usr/bin/* +} diff --git a/projects/ArchR/packages/apps/m8c/config/H700/Anbernic RG CubeXX.ini b/projects/ArchR/packages/apps/m8c/config/H700/Anbernic RG CubeXX.ini new file mode 100644 index 0000000000..dd125a307a --- /dev/null +++ b/projects/ArchR/packages/apps/m8c/config/H700/Anbernic RG CubeXX.ini @@ -0,0 +1,50 @@ +[graphics] +fullscreen=false +use_gpu=true +idle_ms=10 +wait_for_device=true +wait_packets=1024 +[audio] +audio_enabled=false +audio_buffer_size=1024 +audio_device_name=Default +[keyboard] +;Ref: https://wiki.libsdl.org/SDL2/SDL_Scancode +key_up=82 +key_left=80 +key_down=81 +key_right=79 +key_select=225 +key_select_alt=29 +key_start=44 +key_start_alt=27 +key_opt=226 +key_opt_alt=4 +key_edit=224 +key_edit_alt=22 +key_delete=76 +key_reset=21 +key_jazz_inc_octave=85 +key_jazz_dec_octave=84 +key_jazz_inc_velocity=86 +key_jazz_dec_velocity=69 +key_toggle_audio=69 +[gamepad] +gamepad_up=11 +gamepad_left=13 +gamepad_down=12 +gamepad_right=14 +gamepad_select=9 ; L1 +gamepad_start=10 ; R1 +gamepad_opt=0 ; B +gamepad_edit=1 ; A +gamepad_quit=5 ; Menu/Guide +gamepad_reset=7 ; R2 +gamepad_analog_threshold=30000 +gamepad_analog_invert=false +gamepad_analog_axis_updown=1 +gamepad_analog_axis_leftright=0 +gamepad_analog_axis_select=4 +gamepad_analog_axis_start=5 +gamepad_analog_axis_opt=-1 +gamepad_analog_axis_edit=-1 diff --git a/projects/ArchR/packages/apps/m8c/config/H700/Anbernic RG34XX.ini b/projects/ArchR/packages/apps/m8c/config/H700/Anbernic RG34XX.ini new file mode 120000 index 0000000000..4c7e7a42fa --- /dev/null +++ b/projects/ArchR/packages/apps/m8c/config/H700/Anbernic RG34XX.ini @@ -0,0 +1 @@ +Anbernic RG CubeXX.ini \ No newline at end of file diff --git a/projects/ArchR/packages/apps/m8c/config/H700/Anbernic RG40XX H.ini b/projects/ArchR/packages/apps/m8c/config/H700/Anbernic RG40XX H.ini new file mode 120000 index 0000000000..4c7e7a42fa --- /dev/null +++ b/projects/ArchR/packages/apps/m8c/config/H700/Anbernic RG40XX H.ini @@ -0,0 +1 @@ +Anbernic RG CubeXX.ini \ No newline at end of file diff --git a/projects/ArchR/packages/apps/m8c/config/H700/config.ini b/projects/ArchR/packages/apps/m8c/config/H700/config.ini new file mode 100644 index 0000000000..7879affca9 --- /dev/null +++ b/projects/ArchR/packages/apps/m8c/config/H700/config.ini @@ -0,0 +1,50 @@ +[graphics] +fullscreen=false +use_gpu=true +idle_ms=10 +wait_for_device=true +wait_packets=1024 +[audio] +audio_enabled=false +audio_buffer_size=1024 +audio_device_name=Default +[keyboard] +;Ref: https://wiki.libsdl.org/SDL2/SDL_Scancode +key_up=82 +key_left=80 +key_down=81 +key_right=79 +key_select=225 +key_select_alt=29 +key_start=44 +key_start_alt=27 +key_opt=226 +key_opt_alt=4 +key_edit=224 +key_edit_alt=22 +key_delete=76 +key_reset=21 +key_jazz_inc_octave=85 +key_jazz_dec_octave=84 +key_jazz_inc_velocity=86 +key_jazz_dec_velocity=69 +key_toggle_audio=69 +[gamepad] +gamepad_up=11 +gamepad_left=13 +gamepad_down=12 +gamepad_right=14 +gamepad_select=4 ; Select +gamepad_start=6 ; Start +gamepad_opt=0 ; B +gamepad_edit=1 ; A +gamepad_quit=5 ; Menu/Guide +gamepad_reset=7 ; R2 +gamepad_analog_threshold=30000 +gamepad_analog_invert=false +gamepad_analog_axis_updown=1 +gamepad_analog_axis_leftright=0 +gamepad_analog_axis_select=4 +gamepad_analog_axis_start=5 +gamepad_analog_axis_opt=-1 +gamepad_analog_axis_edit=-1 diff --git a/projects/ArchR/packages/apps/m8c/package.mk b/projects/ArchR/packages/apps/m8c/package.mk new file mode 100644 index 0000000000..356ba412ba --- /dev/null +++ b/projects/ArchR/packages/apps/m8c/package.mk @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="m8c" +PKG_VERSION="v1.7.10" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/laamaa/m8c" +PKG_URL="${PKG_SITE}/archive/refs/tags/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain SDL2 libserialport" +PKG_LONGDESC="Cross-platform M8 tracker headless client" +PKG_TOOLCHAIN="cmake" + +makeinstall_target(){ + # Create directories + mkdir -p ${INSTALL}/usr/bin + mkdir -p ${INSTALL}/usr/config/m8c + mkdir -p ${INSTALL}/usr/config/modules + + cp -f m8c ${INSTALL}/usr/bin + chmod 0755 ${INSTALL}/usr/bin/m8c + + cp -rf ${PKG_DIR}/scripts/* ${INSTALL}/usr/config/modules + chmod 0755 ${INSTALL}/usr/config/modules/* + + if [ -d ${PKG_DIR}/config/${DEVICE} ] + then + cp -ra ${PKG_DIR}/config/${DEVICE}/* ${INSTALL}/usr/config/m8c/ + fi +} diff --git a/projects/ArchR/packages/apps/m8c/patches/0001-update-defaults-config.patch b/projects/ArchR/packages/apps/m8c/patches/0001-update-defaults-config.patch new file mode 100644 index 0000000000..f192924821 --- /dev/null +++ b/projects/ArchR/packages/apps/m8c/patches/0001-update-defaults-config.patch @@ -0,0 +1,32 @@ +From c2b17d28cf8800f3011c3c13492fa836d8c773f3 Mon Sep 17 00:00:00 2001 +From: Philippe Simons +Date: Sat, 28 Dec 2024 10:55:19 +0100 +Subject: [PATCH] update defaults config + +--- + src/config.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/config.c b/src/config.c +index 50848a9..95a36ba 100644 +--- a/src/config.c ++++ b/src/config.c +@@ -23,13 +23,13 @@ config_params_s init_config() { + + c.filename = "config.ini"; // default config file to load + +- c.init_fullscreen = 0; // default fullscreen state at load ++ c.init_fullscreen = 1; // default fullscreen state at load + c.init_use_gpu = 1; // default to use hardware acceleration + c.idle_ms = 10; // default to high performance + c.wait_for_device = 1; // default to exit if device disconnected + c.wait_packets = 1024; // default zero-byte attempts to disconnect (about 2 + // sec for default idle_ms) +- c.audio_enabled = 0; // route M8 audio to default output ++ c.audio_enabled = 1; // route M8 audio to default output + c.audio_buffer_size = 1024; // requested audio buffer size in samples + c.audio_device_name = NULL; // Use this device, leave NULL to use the default output device + +-- +2.47.1 + diff --git a/projects/ArchR/packages/apps/m8c/patches/0002-fix-building-with-gcc15.patch b/projects/ArchR/packages/apps/m8c/patches/0002-fix-building-with-gcc15.patch new file mode 100644 index 0000000000..1a5918406f --- /dev/null +++ b/projects/ArchR/packages/apps/m8c/patches/0002-fix-building-with-gcc15.patch @@ -0,0 +1,42 @@ +From 8e268b3e6501eb9dee62ae7a5d3982210ccd4212 Mon Sep 17 00:00:00 2001 +From: spycat88 +Date: Sun, 16 Nov 2025 15:19:10 +0000 +Subject: [PATCH] fix building with gcc15 + +--- + src/config.h | 2 +- + src/main.c | 5 ++++- + 2 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/src/config.h b/src/config.h +index 0a65907..caa90d5 100644 +--- a/src/config.h ++++ b/src/config.h +@@ -60,7 +60,7 @@ typedef struct config_params_s { + } config_params_s; + + +-config_params_s init_config(); ++config_params_s init_config(char *filename); + void read_config(config_params_s *conf); + void read_audio_config(const ini_t *ini, config_params_s *conf); + void read_graphics_config(const ini_t *ini, config_params_s *conf); +diff --git a/src/main.c b/src/main.c +index d7d60db..09cbd38 100644 +--- a/src/main.c ++++ b/src/main.c +@@ -24,7 +24,10 @@ enum state run = WAIT_FOR_DEVICE; + uint8_t need_display_reset = 0; + + // Handles CTRL+C / SIGINT +-void intHandler() { run = QUIT; } ++void intHandler(int sig) { ++ (void)sig; ++ run = QUIT; ++} + + void close_serial_port() { disconnect(); } + +-- +2.34.1 + diff --git a/projects/ArchR/packages/apps/m8c/scripts/Start M8C.sh b/projects/ArchR/packages/apps/m8c/scripts/Start M8C.sh new file mode 100755 index 0000000000..8e789bd80f --- /dev/null +++ b/projects/ArchR/packages/apps/m8c/scripts/Start M8C.sh @@ -0,0 +1,109 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present 351ELEC + +source /etc/profile + +set_kill set "-9 m8c" + +M8C_DIR="/storage/.local/share/m8c" +M8C_CONF_DIR="/usr/config/m8c" + +if [ ! -d ${M8C_DIR} ]; then + mkdir -p ${M8C_DIR} +fi + +if [ ! -f "${M8C_DIR}/config.ini" ]; then + if [ -f "${M8C_CONF_DIR}/${QUIRK_DEVICE}.ini" ]; then + cp "${M8C_CONF_DIR}/${QUIRK_DEVICE}.ini" "${M8C_DIR}/config.ini" + else + if [ -f "${M8C_CONF_DIR}/config.ini" ]; then + cp "${M8C_CONF_DIR}/config.ini" "${M8C_DIR}/config.ini" + fi + fi +fi + +modprobe cdc-acm +modprobe snd-hwdep +modprobe snd-usbmidi-lib +modprobe snd-usb-audio + +# Arrays to store connections for cleanup +MIDI_CONNECTIONS=() + +#Connect all MIDI ports to Dirtywave in both directions +M8_ID=$(aconnect -iol | awk '/client [0-9]+: .*M8/ {print $2}' | tr -d ':') +M8_PORT="$M8_ID:0" + +DEVICE_IDS=$(aconnect -iol | awk '/client [0-9]+:/ {print $2}' | tr -d ':' | grep -vE "^(0|$M8_ID)$") + +for DEVICE_ID in $DEVICE_IDS; do + DEVICE_PORT="$DEVICE_ID:0" + # Store connections for later cleanup + MIDI_CONNECTIONS+=("$DEVICE_PORT:$M8_PORT") + MIDI_CONNECTIONS+=("$M8_PORT:$DEVICE_PORT") + aconnect "$DEVICE_PORT" "$M8_PORT" + aconnect "$M8_PORT" "$DEVICE_PORT" +done + +#Capture M8 USB Source and Play it out the default audio sink +M8_AUDIO_SOURCE=$(pactl list sources | awk '/Name: alsa_input\.usb-DirtyWave/{print $2}') +pw-loopback -C $M8_AUDIO_SOURCE & + +#Connect each BT Source and Play it to the M8 Sink +BT_SOURCES=$(pactl list | awk -F. '/Name: bluez_card/{print $2}') +M8_AUDIO_SINK=$(pactl list sinks | awk '/Name: alsa_output\.usb-DirtyWave/{print $2}') +for BT_SOURCE in $BT_SOURCES; do + pw-loopback -C bluez_input.$BT_SOURCE.2 -P $M8_AUDIO_SINK & +done + +# Connect each audio source to the M8 Sink, excluding the M8 device itself + +# Get the M8 Audio Sink (your specific USB sink) +M8_AUDIO_SINK=$(pactl list sinks short | awk '/alsa_output\.usb-DirtyWave/{print $2}') + +# List all audio sources, excluding monitor sources +ALL_SOURCES=$(pactl list sources short | awk '$2 !~ /\.monitor/ {print $2}') + +# Loop over each source and connect it to the sink, but skip the M8 device's own source +for SRC in $ALL_SOURCES; do + if [[ "$SRC" == *"usb-DirtyWave"* ]]; then + continue + fi + pw-loopback -C "$SRC" -P "$M8_AUDIO_SINK" & +done + +# Function to cleanup MIDI connections and audio routing +cleanup() { + echo "Cleaning up MIDI connections and audio routing..." + + # Kill all pw-loopback processes + echo "Terminating PipeWire loopback processes..." + kill $(jobs -p) 2>/dev/null + + # Wait a moment for processes to terminate + sleep 1 + + # Force kill any remaining pw-loopback processes + pkill -f pw-loopback 2>/dev/null + + # Disconnect MIDI connections + echo "Disconnecting MIDI connections..." + for connection in "${MIDI_CONNECTIONS[@]}"; do + if [[ "$connection" == *":"* ]]; then + src_port="${connection%:*}" + dst_port="${connection#*:}" + aconnect -d "$src_port" "$dst_port" 2>/dev/null || true + fi + done + + echo "Cleanup completed." +} + +# Set up trap to cleanup on script exit +trap cleanup EXIT + +sway_fullscreen "m8c" & + +/usr/bin/m8c diff --git a/projects/ArchR/packages/apps/mako-osd/mako-notify/Makefile b/projects/ArchR/packages/apps/mako-osd/mako-notify/Makefile new file mode 100644 index 0000000000..c30404b6c4 --- /dev/null +++ b/projects/ArchR/packages/apps/mako-osd/mako-notify/Makefile @@ -0,0 +1,11 @@ +CXX ?= g++ +CCFLAGS = -W -Wall -std=c++11 `pkg-config --cflags dbus-1` +BINARY := mako-notify +LIBRARIES = `pkg-config --libs dbus-1` +SOURCES := mako-notify.cpp + +all: + $(CXX) $(CCFLAGS) $(SOURCES) -o $(BINARY) $(LIBRARIES) + +clean: + rm -f $(BINARY) diff --git a/projects/ArchR/packages/apps/mako-osd/mako-notify/mako-notify.cpp b/projects/ArchR/packages/apps/mako-osd/mako-notify/mako-notify.cpp new file mode 100644 index 0000000000..b25ccdaef0 --- /dev/null +++ b/projects/ArchR/packages/apps/mako-osd/mako-notify/mako-notify.cpp @@ -0,0 +1,174 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2026-present ArchR (https://github.com/archr-linux/Arch-R) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +const std::string CONFIG_DIR = "/storage/.config/mako"; +const std::string CONFIG_FILE = CONFIG_DIR + "/config"; + +void ensure_mako_config() { + // Check if directory exists + struct stat st{}; + if (stat(CONFIG_DIR.c_str(), &st) != 0) { + // Directory does not exist, create it + if (mkdir(CONFIG_DIR.c_str(), 0755) != 0) { + perror("Failed to create config directory"); + return; + } + } + + // Check if file exists + if (stat(CONFIG_FILE.c_str(), &st) != 0) { + // File does not exist, create it with default contents + std::ofstream ofs(CONFIG_FILE); + if (!ofs) { + std::cerr << "Failed to create config file at " << CONFIG_FILE << std::endl; + return; + } + + ofs << +"max-visible=1\n" +"layer=overlay\n" +"font=monospace 30\n" +"text-color=#ffffff\n" +"text-alignment=center\n" +"background-color=#000000\n" +"border-size=0\n" +"border-radius=10\n" +"default-timeout=1500\n" +"anchor=top-center\n" +"width=500\n"; + + ofs.close(); + } +} + +// Check focused app function +std::string get_focused_app() { + std::string result; + std::array buffer; + std::unique_ptr pipe( + popen("swaymsg -t get_tree | jq -r '.. | select(.focused?) | .app_id'", "r"), + [](FILE* f){ if(f) pclose(f); } + ); + if (!pipe) return ""; + while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) { + result += buffer.data(); + } + if (!result.empty() && result.back() == '\n') result.pop_back(); + return result; +} + +int main(int argc, char* argv[]) { + if (argc < 2) { + std::cerr << "Usage: " << argv[0] << " " << std::endl; + std::cerr << "Example: " << argv[0] << " \"Hello World\"" << std::endl; + return 1; + } + + // check for -no-es / -no-ra option + bool no_es_flag = false; + bool no_ra_flag = false; + for (int i = 2; i < argc; ++i) { + if (std::string(argv[i]) == "-no-es") { + no_es_flag = true; + } + if (std::string(argv[i]) == "-no-ra") { + no_ra_flag = true; + } + } + + if (no_es_flag || no_ra_flag) { + std::string focused_app = get_focused_app(); + // skip notification if -no-es and EmulationStation focused + if (no_es_flag && focused_app == "emulationstation") { + return 0; + } + // skip notification if -no-ra and Retorarch focused + if (no_ra_flag && focused_app == "com.libretro.RetroArch") { + return 0; + } + } + + // Ensure the Mako config exists + ensure_mako_config(); + + DBusError err; + dbus_error_init(&err); + + // Connect to the session bus + DBusConnection* conn = dbus_bus_get(DBUS_BUS_SESSION, &err); + if (dbus_error_is_set(&err)) { + std::cerr << "Connection Error: " << err.message << std::endl; + dbus_error_free(&err); + return 1; + } + if (!conn) return 1; + + // Create a method call + DBusMessage* msg = dbus_message_new_method_call( + "org.freedesktop.Notifications", // destination + "/org/freedesktop/Notifications", // object path + "org.freedesktop.Notifications", // interface + "Notify" // method + ); + + if (!msg) { + std::cerr << "Message Null" << std::endl; + return 1; + } + + // Build arguments + DBusMessageIter args; + dbus_message_iter_init_append(msg, &args); + + const char* app_name = "mako-notify"; + uint32_t replaces_id = 0; + const char* icon = ""; + const char* summary = argv[1]; + const char* body = argv[1]; + int32_t timeout = 2000; + + dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &app_name); + dbus_message_iter_append_basic(&args, DBUS_TYPE_UINT32, &replaces_id); + dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &icon); + dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &summary); + dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &body); + + // empty array of actions + DBusMessageIter array_iter; + dbus_message_iter_open_container(&args, DBUS_TYPE_ARRAY, "s", &array_iter); + dbus_message_iter_close_container(&args, &array_iter); + + // empty dictionary for hints + DBusMessageIter dict_iter; + dbus_message_iter_open_container(&args, DBUS_TYPE_ARRAY, "{sv}", &dict_iter); + dbus_message_iter_close_container(&args, &dict_iter); + + dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &timeout); + + // Send message + DBusPendingCall* pending = nullptr; + if (!dbus_connection_send_with_reply(conn, msg, &pending, -1)) { + std::cerr << "Failed to send message" << std::endl; + return 1; + } + + dbus_connection_flush(conn); + dbus_message_unref(msg); + + // Wait for reply + if (pending) dbus_pending_call_block(pending); + if (pending) dbus_pending_call_unref(pending); + + return 0; +} diff --git a/projects/ArchR/packages/apps/mako-osd/mako-notify/package.mk b/projects/ArchR/packages/apps/mako-osd/mako-notify/package.mk new file mode 100644 index 0000000000..20ed24065a --- /dev/null +++ b/projects/ArchR/packages/apps/mako-osd/mako-notify/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2026-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="mako-notify" +PKG_VERSION="v1.0" +PKG_LICENSE="GPLv2" +PKG_DEPENDS_TARGET="toolchain dbus" +PKG_LONGDESC="Tool to show onscreen messages in sway, via the mako-osd tool" +PKG_TOOLCHAIN="make" + +pre_make_target() { + cp -f ${PKG_DIR}/Makefile ${PKG_BUILD} + cp -f ${PKG_DIR}/mako-notify.cpp ${PKG_BUILD} + CFLAGS+=" -D_REENTRANT" +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp -r ${PKG_BUILD}/mako-notify ${INSTALL}/usr/bin + chmod +x ${INSTALL}/usr/bin +} diff --git a/projects/ArchR/packages/apps/mako-osd/package.mk b/projects/ArchR/packages/apps/mako-osd/package.mk new file mode 100644 index 0000000000..555a535b8f --- /dev/null +++ b/projects/ArchR/packages/apps/mako-osd/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2026-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="mako-osd" +PKG_VERSION="b131bc143f6b0f24d650f16bb88a11c7cb011c20" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/emersion/mako" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain cairo wayland sway pango glib mako-notify" +PKG_LONGDESC="Meso - A lightweight notification daemon for Wayland. Works on Sway." +PKG_TOOLCHAIN="meson" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp -r ${PKG_BUILD}/.${TARGET_NAME}/mako ${INSTALL}/usr/bin + cp -r ${PKG_BUILD}/.${TARGET_NAME}/makoctl ${INSTALL}/usr/bin + chmod +x ${INSTALL}/usr/bin +} diff --git a/projects/ArchR/packages/apps/mako-osd/patches/000-disable-placeholder-text.patch b/projects/ArchR/packages/apps/mako-osd/patches/000-disable-placeholder-text.patch new file mode 100644 index 0000000000..f1497c2341 --- /dev/null +++ b/projects/ArchR/packages/apps/mako-osd/patches/000-disable-placeholder-text.patch @@ -0,0 +1,22 @@ +diff --git a/render.c b/render.c +index 8fed6d8..b157323 100644 +--- a/render.c ++++ b/render.c +@@ -438,7 +438,7 @@ void render(struct mako_surface *surface, struct pool_buffer *buffer, int scale, + ++visible_count; + } + } +- ++/* + if (hidden_count > 0) { + struct mako_notification *hidden_notif = create_notification(state); + hidden_notif->surface = surface; +@@ -478,7 +478,7 @@ void render(struct mako_surface *surface, struct pool_buffer *buffer, int scale, + } + destroy_notification(hidden_notif); + } +- ++*/ + *rendered_width = max_width; + *rendered_height = total_height; + } diff --git a/projects/ArchR/packages/apps/mangohud/config/MangoHud.conf b/projects/ArchR/packages/apps/mangohud/config/MangoHud.conf new file mode 100644 index 0000000000..4acbedd055 --- /dev/null +++ b/projects/ArchR/packages/apps/mangohud/config/MangoHud.conf @@ -0,0 +1,409 @@ +### MangoHud configuration file +### Uncomment any options you wish to enable. Default options are left uncommented +### Use some_parameter=0 to disable a parameter (only works with on/off parameters) +### Everything below can be used / overridden with the environment variable MANGOHUD_CONFIG instead + +################ INFORMATIONAL ################# +## prints possible options on stdout +# help + +################ PERFORMANCE ################# + +### Limit the application FPS. Comma-separated list of one or more FPS values (e.g. 0,30,60). 0 means unlimited (unless VSynced) +# fps_limit=0 + +### early = wait before present, late = wait after present +# fps_limit_method= + +### VSync [0-3] 0 = adaptive; 1 = off; 2 = mailbox; 3 = on +# vsync=-1 + +### OpenGL VSync [0-N] 0 = off; >=1 = wait for N v-blanks, N > 1 acts as a FPS limiter (FPS = display refresh rate / N) +# gl_vsync=-2 + +### Mip-map LoD bias. Negative values will increase texture sharpness (and aliasing) +## Positive values will increase texture blurriness (-16 to 16) +# picmip=-17 + +### Anisotropic filtering level. Improves sharpness of textures viewed at an angle (0 to 16) +# af=-1 + +### Force bicubic filtering +# bicubic + +### Force trilinear filtering +# trilinear + +### Disable linear texture filtering. Makes textures look blocky +# retro + +################### VISUAL ################### + +### Legacy layout +# legacy_layout=0 + +### pre defined presets +# -1 = default +# 0 = no display +# 1 = fps only +# 2 = horizontal view +# 3 = extended +# 4 = high detailed information +# preset=-1 + +### Enable most of the toggleable parameters (currently excludes `histogram`) +# full + +### Show FPS only. ***Not meant to be used with other display params*** +# fps_only + +### Display custom centered text, useful for a header +# custom_text_center= + +### Display the current system time +# time +## removes the time label +# time_no_label + +### Time formatting examples +## %H:%M +## [ %T %F ] +## %X # locally formatted time, because of limited glyph range, missing characters may show as '?' (e.g. Japanese) +# time_format="%T" + +### Display MangoHud version +# version + +### Display the current GPU information +## Note: gpu_mem_clock and gpu_mem_temp also need "vram" to be enabled +# gpu_stats +gpu_temp +# gpu_junction_temp +gpu_core_clock +# gpu_mem_temp +# gpu_mem_clock +# gpu_power +# gpu_power_limit +# gpu_text= +# gpu_load_change +# gpu_load_value=60,90 +# gpu_load_color=39F900,FDFD09,B22222 +## GPU fan in rpm on AMD, FAN in percent on NVIDIA +# gpu_fan +## gpu_voltage only works on AMD GPUs +# gpu_voltage +## Select list of GPUs to display +# gpu_list=0,1 +# gpu_efficiency + +### Display the current CPU information +# cpu_stats +cpu_temp +# cpu_power +# cpu_text= +cpu_mhz +# cpu_load_change +# cpu_load_value=60,90 +# cpu_load_color=39F900,FDFD09,B22222 +# cpu_efficiency + +### Display the current CPU load & frequency for each core +# core_load +# core_load_change +# core_bars +# core_type + +### Display IO read and write for the app (not system) +# io_read +# io_write + +### Display system vram / ram / swap space usage +# vram +# ram +# swap + +### Display per process memory usage +## Show resident memory and other types, if enabled +procmem +# procmem_shared +# procmem_virt +# proc_vram + +### Display battery information +battery +# battery_icon +# device_battery=gamepad,mouse +# device_battery_icon +battery_watt +# battery_time + +### Display FPS and frametime +fps +# fps_sampling_period=500 +# fps_color_change +# fps_value=30,60 +# fps_color=B22222,FDFD09,39F900 +# fps_text="" +frametime +# frame_count +## fps_metrics takes a list of decimal values or the value avg +# fps_metrics=avg,0.01 + +### Display GPU throttling status based on Power, current, temp or "other" +## Only shows if throttling is currently happening +throttling_status +## Same as throttling_status but displays throttling on the frametime graph +#throttling_status_graph + +### Display miscellaneous information +# engine_version +# engine_short_names +# gpu_name +# vulkan_driver +# wine +# exec_name +# winesync +# present_mode + +### Display loaded MangoHud architecture +# arch + +### Display the frametime line graph +frame_timing +# frame_timing_detailed +# dynamic_frame_timing +# histogram + +### Display GameMode / vkBasalt running status +# gamemode +# vkbasalt + +### Gamescope related options +## Display the status of FSR (only works in gamescope) +# fsr +## Hides the sharpness info for the `fsr` option (only available in gamescope) +# hide_fsr_sharpness +## Shows the graph of gamescope app frametimes and latency (only on gamescope obviously) +# debug +## Display the status of HDR (only works in gamescope) +# hdr +## Display the current refresh rate (only works in gamescope) +# refresh_rate + + +### graphs displays one or more graphs that you chose +## separated by ",", available graphs are +## gpu_load,cpu_load,gpu_core_clock,gpu_mem_clock,vram,ram,cpu_temp,gpu_temp +# graphs= + +### mangoapp related options +## Enables mangoapp to be displayed above the Steam UI +# mangoapp_steam + +### Steam Deck options +## Shows the Steam Deck fan rpm +# fan + +### Display current FPS limit +# show_fps_limit + +### Display the current resolution +# resolution + +### Display current display session +# display_server + +### Display temperature in fahrenheit +# temp_fahrenheit + +## Display efficiency in joules per frame +# flip_efficiency + +### Display custom text +# custom_text= +### Display output of Bash command in next column +# exec= + +### Display media player metadata +# media_player +## for example spotify +# media_player_name= +## Format metadata, lines are delimited by ; (wip) +## example: {title};{artist};{album} +## example: Track:;{title};By:;{artist};From:;{album} +# media_player_format=title,artist,album + +### Network interface throughput +# network +## Network can take arguments but it's not required. +## without arguments it shows all interfaces +## arguments set which interfaces will be displayed +# network=eth0,wlo1 + + +### Change the hud font size +font_size=@FONT_SIZE@ +# font_scale=1.0 +# font_size_text=24 +# font_scale_media_player=0.55 +# no_small_font + +### Change default font (set location to TTF/OTF file) +## Set font for the whole hud +# font_file= + +## Set font only for text like media player metadata +# font_file_text= + +## Set font glyph ranges. Defaults to Latin-only. Don't forget to set font_file/font_file_text to font that supports these +## Probably don't enable all at once because of memory usage and hardware limits concerns +## If you experience crashes or text is just squares, reduce glyph range or reduce font size +# font_glyph_ranges=korean,chinese,chinese_simplified,japanese,cyrillic,thai,vietnamese,latin_ext_a,latin_ext_b + +### Outline text +text_outline +# text_outline_color = 000000 +# text_outline_thickness = 1.5 + +### Change the hud position +# position=top-left + +### Change the corner roundness +# round_corners=0 + +### Remove margins around MangoHud +# hud_no_margin + +### Display compact version of MangoHud +# hud_compact + +### Display MangoHud in a horizontal position +# horizontal +# horizontal_stretch + +### Disable / hide the hud by default +# no_display + +### Show FEX-Emu statistics +## Only useful for Arm64 devices running applications under emulation +# fex_stats + +### Hud position offset +# offset_x=0 +# offset_y=0 + +### Hud dimensions +# width=0 +# height=140 +# table_columns=3 +# cellpadding_y=-0.085 + +### Hud transparency / alpha +# background_alpha=0.5 +# alpha=1.0 + +### FCAT overlay +### This enables an FCAT overlay to perform frametime analysis on the final image stream. +### Enable the overlay +# fcat +### Set the width of the FCAT overlay. +### 24 is a performance optimization on AMD GPUs that should not have adverse effects on nVidia GPUs. +### A minimum of 20 pixels is recommended by nVidia. +# fcat_overlay_width=24 +### Set the screen edge, this can be useful for special displays that don't update from top edge to bottom. This goes from 0 (left side) to 3 (top edge), counter-clockwise. +# fcat_screen_edge=0 + +### Color customization +# text_color=FFFFFF +# gpu_color=2E9762 +# cpu_color=2E97CB +# vram_color=AD64C1 +# ram_color=C26693 +# engine_color=EB5B5B +# io_color=A491D3 +# frametime_color=00FF00 +# background_color=020202 +# media_player_color=FFFFFF +# wine_color=EB5B5B +# battery_color=FF9078 +# network_color=E07B85 +# horizontal_separator_color=AD64C1 + +### Specify GPU with PCI bus ID +### Set to 'domain:bus:slot.function' +### Example: +### $ lspci | grep A770 +### 03:00.0 VGA compatible controller: Intel Corporation DG2 [Arc A770] (rev 08) +# pci_dev=0000:03:00.0 + +### Blacklist +# blacklist= + +### Control over socket +### Enable and set socket name, '%p' is replaced with process id +## example: mangohud +## example: mangohud-%p +# control = -1 + +### ftrace tracepoint display +## Enable display of tracepoint information gathered from ftrace. MangoHud will parse +## out the necessary data from the ftrace pipe, ftrace itself still has to be configured +## manually (enabling the desired event, applying any filtering etc.). The user running +## MangoHud will require permission to access the default-mounted tracefs (expected at +## /sys/kernel/tracing/). +## +## When parsing ftrace output, currently only the `key=value` format for event fields is +## expected. This is the most common format used in events, but it's not standardized. +## +## Three types of display are available: +## - `histogram/drm_vblank_event`, a histogram of event occurrence +## - `linegraph/devfreq_monitor/freq`, a line graph of an event field's numerical value +## - `label/devfreq_frequency/dev_name`, a textual presentation of an event field's value +## +## The displays are set through the `ftrace` option. Multiple displays can be specified. +# ftrace=histogram/drm_vblank_event+linegraph/devfreq_monitor/freq + +################ WORKAROUNDS ################# +### Options starting with "gl_*" are for OpenGL +### Specify what to use for getting display size. Options are "viewport", "scissorbox" or disabled. Defaults to using glXQueryDrawable +# gl_size_query=viewport + +### (Re)bind given framebuffer before MangoHud gets drawn. Helps with Crusader Kings III +# gl_bind_framebuffer=0 + +### Don't swap origin if using GL_UPPER_LEFT. Helps with Ryujinx +# gl_dont_flip=1 + +################ INTERACTION ################# + +### Change toggle keybinds for the hud & logging +# toggle_hud=Shift_R+F12 +# toggle_hud_position=Shift_R+F11 +# toggle_preset=Shift_R+F10 +# toggle_fps_limit=Shift_L+F1 +# toggle_logging=Shift_L+F2 +# reload_cfg=Shift_L+F4 +# upload_log=Shift_L+F3 +# reset_fps_metrics=Shift_R+f9 + +#################### LOG ##################### +### Automatically start the log after X seconds +# autostart_log= +### Set amount of time in seconds that the logging will run for +# log_duration= +### Change the default log interval, 0 is default +# log_interval=0 +### Set location of the output files (required for logging) +# output_folder=/home//mangologs +### Permit uploading logs directly to FlightlessMango.com +## set to 1 to enable +# permit_upload=0 +### Define a '+'-separated list of percentiles shown in the benchmark results +### Use "AVG" to get a mean average. Default percentiles are 97+AVG+1+0.1 +## example: ['97', 'AVG', '1', '0.1'] +# benchmark_percentiles=97,AVG +## Adds more headers and information such as versioning to the log. This format is not supported on flightlessmango.com (yet) +# log_versioning +## Enable automatic uploads of logs to flightlessmango.com +# upload_logs +# output_file="" diff --git a/projects/ArchR/packages/apps/mangohud/meson-patches/imgui_patch_1.91.6-3.zip b/projects/ArchR/packages/apps/mangohud/meson-patches/imgui_patch_1.91.6-3.zip new file mode 100644 index 0000000000..353decf906 Binary files /dev/null and b/projects/ArchR/packages/apps/mangohud/meson-patches/imgui_patch_1.91.6-3.zip differ diff --git a/projects/ArchR/packages/apps/mangohud/meson-patches/implot_patch_0.16-1.zip b/projects/ArchR/packages/apps/mangohud/meson-patches/implot_patch_0.16-1.zip new file mode 100644 index 0000000000..6c64983d09 Binary files /dev/null and b/projects/ArchR/packages/apps/mangohud/meson-patches/implot_patch_0.16-1.zip differ diff --git a/projects/ArchR/packages/apps/mangohud/meson-patches/spdlog_patch_1.14.1-1.zip b/projects/ArchR/packages/apps/mangohud/meson-patches/spdlog_patch_1.14.1-1.zip new file mode 100644 index 0000000000..dd82a146ac Binary files /dev/null and b/projects/ArchR/packages/apps/mangohud/meson-patches/spdlog_patch_1.14.1-1.zip differ diff --git a/projects/ArchR/packages/apps/mangohud/meson-patches/vulkan-headers_patch_1.3.283-1.zip b/projects/ArchR/packages/apps/mangohud/meson-patches/vulkan-headers_patch_1.3.283-1.zip new file mode 100644 index 0000000000..677ba45978 Binary files /dev/null and b/projects/ArchR/packages/apps/mangohud/meson-patches/vulkan-headers_patch_1.3.283-1.zip differ diff --git a/projects/ArchR/packages/apps/mangohud/package.mk b/projects/ArchR/packages/apps/mangohud/package.mk new file mode 100644 index 0000000000..8880ee4730 --- /dev/null +++ b/projects/ArchR/packages/apps/mangohud/package.mk @@ -0,0 +1,91 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2025-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="mangohud" +PKG_VERSION="d7654ebcefb3bdb106d581c937417aa2007eaeeb" # v0.8.3-rc1 + a few fixes +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/flightlessmango/MangoHud" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain glslang mesa Python3 wayland libxcb dbus" +PKG_LONGDESC="A Vulkan and OpenGL overlay for monitoring FPS, temperatures, CPU/GPU load and more." +PKG_PATCH_DIRS+="${DEVICE}" + +if [ "${OPENGL_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL}" +fi + +if [ "${VULKAN_SUPPORT}" = "yes" ] +then + PKG_DEPENDS_TARGET+=" ${VULKAN}" +fi + +pre_configure_target() { + PKG_MESON_OPTS_TARGET+=" -Dwith_xnvctrl=disabled \ + -Dwith_x11=enabled \ + -Dmangoplot=disabled \ + -Dwith_wayland=enabled" + + # Download Sub Modules + mkdir -p ${PKG_BUILD}/subprojects/ + + ### vulkan-headers + curl -Lo ${PKG_BUILD}/subprojects/vulkan-headers.tar.gz https://github.com/KhronosGroup/Vulkan-Headers/archive/v1.3.283.tar.gz + tar -xvf ${PKG_BUILD}/subprojects/vulkan-headers.tar.gz -C ${PKG_BUILD}/subprojects/ + #curl -Lo ${PKG_BUILD}/subprojects/vulkan-headers_patch_1.3.283-1.zip https://wrapdb.mesonbuild.com/v2/vulkan-headers_1.3.283-1/get_patch + #unzip -o ${PKG_BUILD}/subprojects/vulkan-headers_patch_1.3.283-1.zip -d ${PKG_BUILD}/subprojects + unzip -o ${PKG_DIR}/meson-patches/vulkan-headers_patch_1.3.283-1.zip -d ${PKG_BUILD}/subprojects + rm -rf ${PKG_BUILD}/subprojects/vulkan-headers.tar.gz + rm -rf ${PKG_BUILD}/subprojects/vulkan-headers_patch_1.3.283-1.zip + + ### imgui + curl -Lo ${PKG_BUILD}/subprojects/imgui.tar.gz https://github.com/ocornut/imgui/archive/refs/tags/v1.91.6.tar.gz + tar -xvf ${PKG_BUILD}/subprojects/imgui.tar.gz -C ${PKG_BUILD}/subprojects/ + #curl -Lo ${PKG_BUILD}/subprojects/imgui_patch_1.91.6-3.zip https://wrapdb.mesonbuild.com/v2/imgui_1.91.6-3/get_patch + #unzip -o ${PKG_BUILD}/subprojects/imgui_patch_1.91.6-3.zip -d ${PKG_BUILD}/subprojects + unzip -o ${PKG_DIR}/meson-patches/imgui_patch_1.91.6-3.zip -d ${PKG_BUILD}/subprojects + rm -rf ${PKG_BUILD}/subprojects/imgui.tar.gz + rm -rf ${PKG_BUILD}/subprojects/imgui_patch_1.91.6-3.zip + + ### implot + curl -Lo ${PKG_BUILD}/subprojects/implot.zip https://github.com/epezent/implot/archive/refs/tags/v0.16.zip + unzip -o ${PKG_BUILD}/subprojects/implot.zip -d ${PKG_BUILD}/subprojects + #curl -Lo ${PKG_BUILD}/subprojects/implot_patch_0.16-1.zip https://wrapdb.mesonbuild.com/v2/implot_0.16-1/get_patch + #unzip -o ${PKG_BUILD}/subprojects/implot_patch_0.16-1.zip -d ${PKG_BUILD}/subprojects + unzip -o ${PKG_DIR}/meson-patches/implot_patch_0.16-1.zip -d ${PKG_BUILD}/subprojects + rm -rf ${PKG_BUILD}/subprojects/implot.zip + rm -rf ${PKG_BUILD}/subprojects/implot_patch_0.16-1.zip + + ### spdlog + curl -Lo ${PKG_BUILD}/subprojects/spdlog.tar.gz https://github.com/gabime/spdlog/archive/refs/tags/v1.14.1.tar.gz + tar -xvf ${PKG_BUILD}/subprojects/spdlog.tar.gz -C ${PKG_BUILD}/subprojects/ + #curl -Lo ${PKG_BUILD}/subprojects/spdlog_patch_1.14.1-1.zip https://wrapdb.mesonbuild.com/v2/spdlog_1.14.1-1/get_patch + #unzip -o ${PKG_BUILD}/subprojects/spdlog_patch_1.14.1-1.zip -d ${PKG_BUILD}/subprojects + unzip -o ${PKG_DIR}/meson-patches/spdlog_patch_1.14.1-1.zip -d ${PKG_BUILD}/subprojects + rm -rf ${PKG_BUILD}/subprojects/spdlog.tar.gz + rm -rf ${PKG_BUILD}/subprojects/spdlog_patch_1.14.1-1.zip +} + +post_makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp -rf ${PKG_DIR}/sources/* ${INSTALL}/usr/bin + chmod +x ${INSTALL}/usr/bin/* + + mkdir -p ${INSTALL}/usr/config/MangoHud + cp -rf ${PKG_DIR}/config/* ${INSTALL}/usr/config/MangoHud + + # Customize config per platform, eg set font size for display resolution + case ${DEVICE} in + RK3326) + sed -e "s/@FONT_SIZE@/30/g" -i ${INSTALL}/usr/config/MangoHud/MangoHud.conf + ;; + S922X) + sed -e "s/@FONT_SIZE@/30/g" -i ${INSTALL}/usr/config/MangoHud/MangoHud.conf + + # No GPU temperature sensor available + sed -i 's/^gpu_temp/\# gpu_temp/g' ${INSTALL}/usr/config/MangoHud/MangoHud.conf + ;; + *) + sed -e "s/@FONT_SIZE@/40/g" -i ${INSTALL}/usr/config/MangoHud/MangoHud.conf + ;; + esac +} diff --git a/projects/ArchR/packages/apps/mangohud/patches/0001-No-static-lib.patch b/projects/ArchR/packages/apps/mangohud/patches/0001-No-static-lib.patch new file mode 100644 index 0000000000..2c20c13641 --- /dev/null +++ b/projects/ArchR/packages/apps/mangohud/patches/0001-No-static-lib.patch @@ -0,0 +1,25 @@ +From 5911b0ea29e64c289cf8582c55d8892687149602 Mon Sep 17 00:00:00 2001 +From: John Williams +Date: Wed, 14 Jan 2026 22:18:16 +1100 +Subject: [PATCH 1/3] No static lib + +--- + src/meson.build | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/meson.build b/src/meson.build +index e500c0c..9ca3f5b 100644 +--- a/src/meson.build ++++ b/src/meson.build +@@ -176,7 +176,7 @@ if is_unixy + endif + endif + +-link_args = cc.get_supported_link_arguments(['-Wl,-Bsymbolic-functions', '-Wl,-z,relro', '-Wl,--exclude-libs,ALL', '-lGL', '-static-libstdc++']) ++link_args = cc.get_supported_link_arguments(['-Wl,-Bsymbolic-functions', '-Wl,-z,relro', '-Wl,--exclude-libs,ALL', '-lGL']) + # meson fails to check version-script so just force add + link_args += '-Wl,--version-script,@0@'.format(join_paths(meson.current_source_dir(), 'mangohud.version')) + +-- +2.47.3 + diff --git a/projects/ArchR/packages/apps/mangohud/patches/0002-Battery-name.patch b/projects/ArchR/packages/apps/mangohud/patches/0002-Battery-name.patch new file mode 100644 index 0000000000..a5a114428e --- /dev/null +++ b/projects/ArchR/packages/apps/mangohud/patches/0002-Battery-name.patch @@ -0,0 +1,25 @@ +From aed0afd4578c66194b85587f6904ee6457487d74 Mon Sep 17 00:00:00 2001 +From: John Williams +Date: Wed, 14 Jan 2026 22:18:41 +1100 +Subject: [PATCH 2/3] Battery name + +--- + src/battery.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/battery.cpp b/src/battery.cpp +index e5d311b..9cf8e5b 100644 +--- a/src/battery.cpp ++++ b/src/battery.cpp +@@ -13,7 +13,7 @@ void BatteryStats::numBattery() { + fs::path path("/sys/class/power_supply/"); + for (auto& p : fs::directory_iterator(path)) { + string fileName = p.path().filename(); +- if (fileName.find("BAT") != std::string::npos) { ++ if (fileName.find("battery") != std::string::npos) { + battPath[batteryCount] = p.path(); + batteryCount += 1; + } +-- +2.47.3 + diff --git a/projects/ArchR/packages/apps/mangohud/patches/0003-RAM-name.patch b/projects/ArchR/packages/apps/mangohud/patches/0003-RAM-name.patch new file mode 100644 index 0000000000..fd5449291b --- /dev/null +++ b/projects/ArchR/packages/apps/mangohud/patches/0003-RAM-name.patch @@ -0,0 +1,25 @@ +From d0ce0d7ed5d7b6122057976627f6761d70f1c59c Mon Sep 17 00:00:00 2001 +From: John Williams +Date: Wed, 14 Jan 2026 22:19:09 +1100 +Subject: [PATCH 3/3] RAM name + +--- + src/hud_elements.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/hud_elements.cpp b/src/hud_elements.cpp +index 3cac5af..86d5002 100644 +--- a/src/hud_elements.cpp ++++ b/src/hud_elements.cpp +@@ -804,7 +804,7 @@ void HudElements::procmem() + return; + + ImguiNextColumnFirstItem(); +- HUDElements.TextColored(HUDElements.colors.ram, "PMEM"); ++ HUDElements.TextColored(HUDElements.colors.ram, "RAM"); + ImguiNextColumnOrNewRow(); + right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, "%.1f", format_units(proc_mem_resident, unit)); + ImGui::SameLine(0, 1.0f); +-- +2.47.3 + diff --git a/projects/ArchR/packages/apps/mangohud/patches/RK3326/0001-RK3326-soc_thermal.patch b/projects/ArchR/packages/apps/mangohud/patches/RK3326/0001-RK3326-soc_thermal.patch new file mode 100644 index 0000000000..4029824991 --- /dev/null +++ b/projects/ArchR/packages/apps/mangohud/patches/RK3326/0001-RK3326-soc_thermal.patch @@ -0,0 +1,26 @@ +From 0e3eb106c43c640ddb3cc9863297153215913c15 Mon Sep 17 00:00:00 2001 +From: John Williams +Date: Sun, 11 Jan 2026 21:42:52 +1100 +Subject: [PATCH 1/2] RK3326 soc_thermal + +--- + src/cpu.cpp | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/cpu.cpp b/src/cpu.cpp +index f46faba..621e03e 100644 +--- a/src/cpu.cpp ++++ b/src/cpu.cpp +@@ -615,6 +615,9 @@ bool CPUStats::GetCpuFile() { + } else if (name == "apm_xgene") { + find_input(path, "temp", input, "SoC Temperature"); + break; ++ } else if (name == "soc_thermal") { ++ find_fallback_input(path, "temp1", input); ++ break; + } else { + path.clear(); + } +-- +2.47.3 + diff --git a/projects/ArchR/packages/apps/mangohud/patches/RK3326/0002-RK3326-battery_watt.patch b/projects/ArchR/packages/apps/mangohud/patches/RK3326/0002-RK3326-battery_watt.patch new file mode 100644 index 0000000000..060253aacf --- /dev/null +++ b/projects/ArchR/packages/apps/mangohud/patches/RK3326/0002-RK3326-battery_watt.patch @@ -0,0 +1,27 @@ +From 0941b7be6555286d60f3a551d100597d9b9640c9 Mon Sep 17 00:00:00 2001 +From: John Williams +Date: Mon, 19 Jan 2026 21:25:05 +1100 +Subject: [PATCH 2/2] RK3326 battery_watt + +--- + src/battery.cpp | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/battery.cpp b/src/battery.cpp +index 9cf8e5b..8a39d24 100644 +--- a/src/battery.cpp ++++ b/src/battery.cpp +@@ -92,8 +92,8 @@ float BatteryStats::getPower() { + float voltage = 0; + for(int i = 0; i < batt_count; i++) { + string syspath = battPath[i]; +- string current_power = syspath + "/current_now"; +- string current_voltage = syspath + "/voltage_now"; ++ string current_power = syspath + "/current_avg"; ++ string current_voltage = syspath + "/voltage_avg"; + string power_now = syspath + "/power_now"; + string status = syspath + "/status"; + +-- +2.47.3 + diff --git a/projects/ArchR/packages/apps/mangohud/patches/SM8250/0001-SM8250-GPU.patch b/projects/ArchR/packages/apps/mangohud/patches/SM8250/0001-SM8250-GPU.patch new file mode 100644 index 0000000000..1e25e165c3 --- /dev/null +++ b/projects/ArchR/packages/apps/mangohud/patches/SM8250/0001-SM8250-GPU.patch @@ -0,0 +1,162 @@ +From fd8d0808a5a7133aea277156065c8b9dd5277861 Mon Sep 17 00:00:00 2001 +From: John Williams +Date: Wed, 14 Jan 2026 21:18:03 +1100 +Subject: [PATCH 1/2] SM8250 GPU + +--- + src/gpu_fdinfo.cpp | 68 ++++++++++++++++++++++++++++++++++------------ + src/gpu_fdinfo.h | 2 ++ + 2 files changed, 53 insertions(+), 17 deletions(-) + +diff --git a/src/gpu_fdinfo.cpp b/src/gpu_fdinfo.cpp +index 0fdd99e..14445be 100644 +--- a/src/gpu_fdinfo.cpp ++++ b/src/gpu_fdinfo.cpp +@@ -55,7 +55,7 @@ void GPU_fdinfo::find_fd() + client_id = val; + } + +- if (!driver.empty() && driver == module) { ++ if ((module == "msm_dpu" || module == "msm_drm") && driver == "msm") { + total++; + SPDLOG_TRACE( + "driver = \"{}\", pdev = \"{}\", " +@@ -63,14 +63,30 @@ void GPU_fdinfo::find_fd() + driver, pdev, + client_id, client_ids.find(client_id) != client_ids.end() + ); +- } + +- if ( +- driver.empty() || client_id.empty() || +- driver != module || pdev != pci_dev || +- client_ids.find(client_id) != client_ids.end() +- ) +- continue; ++ if ( ++ driver.empty() || client_id.empty() || ++ client_ids.find(client_id) != client_ids.end() ++ ) ++ continue; ++ } else { ++ if (!driver.empty() && driver == module) { ++ total++; ++ SPDLOG_TRACE( ++ "driver = \"{}\", pdev = \"{}\", " ++ "client_id = \"{}\", client_id_exists = \"{}\"", ++ driver, pdev, ++ client_id, client_ids.find(client_id) != client_ids.end() ++ ); ++ } ++ ++ if ( ++ driver.empty() || client_id.empty() || ++ driver != module || pdev != pci_dev || ++ client_ids.find(client_id) != client_ids.end() ++ ) ++ continue; ++ } + + client_ids.insert(client_id); + open_fdinfo_fd(fd_path); +@@ -175,8 +191,9 @@ void GPU_fdinfo::find_hwmon_sensors() + { + std::string hwmon; + +- if (module == "msm") +- hwmon = find_hwmon_sensor_dir("gpu"); ++ if (module == "msm_drm" || module == "msm_dpu" ) ++ // gpuss_0_thermal, gpuss_1_thermal and gpuss_2_thermal are all candidates ++ hwmon = find_hwmon_sensor_dir("gpu_top_thermal"); + else if (module == "panfrost" || module == "panthor") + hwmon = find_hwmon_sensor_dir("gpu_thermal"); + else +@@ -538,6 +555,8 @@ int GPU_fdinfo::get_gpu_clock() + { + if (module == "panfrost" || module == "panthor") + return get_gpu_clock_mali(); ++ else if (module == "msm_dpu") ++ return get_kgsl_clock(); + + if (!gpu_clock_stream.is_open()) + return 0; +@@ -637,7 +656,7 @@ float GPU_fdinfo::amdgpu_helper_get_proc_vram() { + } + + void GPU_fdinfo::init_kgsl() { +- const std::string sys_path = "/sys/class/kgsl/kgsl-3d0"; ++ const std::string sys_path = "/sys/class/devfreq/3d00000.gpu"; + + try { + if (!fs::exists(sys_path)) { +@@ -649,7 +668,8 @@ void GPU_fdinfo::init_kgsl() { + return; + } + +- for (std::string metric : {"gpu_busy_percentage", "temp", "clock_mhz" }) { ++ // Only GPU clocks accessible ++ for (std::string metric : {"cur_freq" }) { + std::string p = sys_path + "/" + metric; + + if (!fs::exists(p)) { +@@ -658,11 +678,7 @@ void GPU_fdinfo::init_kgsl() { + } + + SPDLOG_DEBUG("kgsl: {} found", p); +- +- if (metric == "clock_mhz") +- gpu_clock_stream.open(p); +- else +- kgsl_streams[metric].open(p); ++ kgsl_streams[metric].open(p); + } + } + +@@ -702,6 +718,24 @@ int GPU_fdinfo::get_kgsl_temp() { + return std::round(std::stoi(temp_str) / 1'000.f); + } + ++int GPU_fdinfo::get_kgsl_clock() { ++ std::ifstream* s = &kgsl_streams["cur_freq"]; ++ ++ if (!s->is_open()) ++ return 0; ++ ++ std::string freq_str; ++ ++ s->seekg(0); ++ ++ std::getline(*s, freq_str); ++ ++ if (freq_str.empty()) ++ return 0; ++ ++ return std::round(std::stoi(freq_str) / 1'000'000.f); ++} ++ + void GPU_fdinfo::main_thread() + { + while (!stop_thread) { +diff --git a/src/gpu_fdinfo.h b/src/gpu_fdinfo.h +index 97e62e5..a5b1d9e 100644 +--- a/src/gpu_fdinfo.h ++++ b/src/gpu_fdinfo.h +@@ -119,6 +119,7 @@ private: + void init_kgsl(); + int get_kgsl_load(); + int get_kgsl_temp(); ++ int get_kgsl_clock(); + + public: + GPU_fdinfo( +@@ -146,6 +147,7 @@ public: + } else if (module == "msm_dpu") { + // msm driver does not report vram usage + drm_engine_type = "drm-engine-gpu"; ++ init_kgsl(); + } else if (module == "msm_drm") { + init_kgsl(); + } else if (module == "panfrost") { +-- +2.47.3 + diff --git a/projects/ArchR/packages/apps/mangohud/patches/SM8250/0002-SM8250-big-core.patch b/projects/ArchR/packages/apps/mangohud/patches/SM8250/0002-SM8250-big-core.patch new file mode 100644 index 0000000000..b834d2af1c --- /dev/null +++ b/projects/ArchR/packages/apps/mangohud/patches/SM8250/0002-SM8250-big-core.patch @@ -0,0 +1,28 @@ +From 60731bb7fd6002649580ab9c63f7f43159ecac10 Mon Sep 17 00:00:00 2001 +From: John Williams +Date: Wed, 14 Jan 2026 21:18:18 +1100 +Subject: [PATCH 2/2] SM8250 big core + +--- + src/cpu.cpp | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/src/cpu.cpp b/src/cpu.cpp +index f46faba..5174c75 100644 +--- a/src/cpu.cpp ++++ b/src/cpu.cpp +@@ -236,6 +236,11 @@ bool CPUStats::UpdateCPUData() + + m_cpuPeriod = (double)m_cpuData[0].totalPeriod / m_cpuData.size(); + m_updatedCPUs = true; ++ ++ if (m_cpuData.size() > 7) { ++ m_cpuDataTotal.percent = m_cpuData[7].percent; ++ } ++ + return ret; + } + +-- +2.47.3 + diff --git a/projects/ArchR/packages/apps/mangohud/patches/SM8550/0001-SM8550-GPU.patch b/projects/ArchR/packages/apps/mangohud/patches/SM8550/0001-SM8550-GPU.patch new file mode 100644 index 0000000000..05243ea567 --- /dev/null +++ b/projects/ArchR/packages/apps/mangohud/patches/SM8550/0001-SM8550-GPU.patch @@ -0,0 +1,162 @@ +From 8abf317204f876b19238c21f045b1d54fc77cd80 Mon Sep 17 00:00:00 2001 +From: John Williams +Date: Tue, 13 Jan 2026 21:46:12 +1100 +Subject: [PATCH 1/2] SM8550 GPU + +--- + src/gpu_fdinfo.cpp | 68 ++++++++++++++++++++++++++++++++++------------ + src/gpu_fdinfo.h | 2 ++ + 2 files changed, 53 insertions(+), 17 deletions(-) + +diff --git a/src/gpu_fdinfo.cpp b/src/gpu_fdinfo.cpp +index 0fdd99e..23cf6a2 100644 +--- a/src/gpu_fdinfo.cpp ++++ b/src/gpu_fdinfo.cpp +@@ -55,7 +55,7 @@ void GPU_fdinfo::find_fd() + client_id = val; + } + +- if (!driver.empty() && driver == module) { ++ if ((module == "msm_dpu" || module == "msm_drm") && driver == "msm") { + total++; + SPDLOG_TRACE( + "driver = \"{}\", pdev = \"{}\", " +@@ -63,14 +63,30 @@ void GPU_fdinfo::find_fd() + driver, pdev, + client_id, client_ids.find(client_id) != client_ids.end() + ); +- } + +- if ( +- driver.empty() || client_id.empty() || +- driver != module || pdev != pci_dev || +- client_ids.find(client_id) != client_ids.end() +- ) +- continue; ++ if ( ++ driver.empty() || client_id.empty() || ++ client_ids.find(client_id) != client_ids.end() ++ ) ++ continue; ++ } else { ++ if (!driver.empty() && driver == module) { ++ total++; ++ SPDLOG_TRACE( ++ "driver = \"{}\", pdev = \"{}\", " ++ "client_id = \"{}\", client_id_exists = \"{}\"", ++ driver, pdev, ++ client_id, client_ids.find(client_id) != client_ids.end() ++ ); ++ } ++ ++ if ( ++ driver.empty() || client_id.empty() || ++ driver != module || pdev != pci_dev || ++ client_ids.find(client_id) != client_ids.end() ++ ) ++ continue; ++ } + + client_ids.insert(client_id); + open_fdinfo_fd(fd_path); +@@ -175,8 +191,9 @@ void GPU_fdinfo::find_hwmon_sensors() + { + std::string hwmon; + +- if (module == "msm") +- hwmon = find_hwmon_sensor_dir("gpu"); ++ if (module == "msm_drm" || module == "msm_dpu" ) ++ // gpuss_0_thermal, gpuss_1_thermal and gpuss_2_thermal are all candidates ++ hwmon = find_hwmon_sensor_dir("gpuss_0_thermal"); + else if (module == "panfrost" || module == "panthor") + hwmon = find_hwmon_sensor_dir("gpu_thermal"); + else +@@ -538,6 +555,8 @@ int GPU_fdinfo::get_gpu_clock() + { + if (module == "panfrost" || module == "panthor") + return get_gpu_clock_mali(); ++ else if (module == "msm_dpu") ++ return get_kgsl_clock(); + + if (!gpu_clock_stream.is_open()) + return 0; +@@ -637,7 +656,7 @@ float GPU_fdinfo::amdgpu_helper_get_proc_vram() { + } + + void GPU_fdinfo::init_kgsl() { +- const std::string sys_path = "/sys/class/kgsl/kgsl-3d0"; ++ const std::string sys_path = "/sys/class/devfreq/3d00000.gpu"; + + try { + if (!fs::exists(sys_path)) { +@@ -649,7 +668,8 @@ void GPU_fdinfo::init_kgsl() { + return; + } + +- for (std::string metric : {"gpu_busy_percentage", "temp", "clock_mhz" }) { ++ // Only GPU clocks accessible ++ for (std::string metric : {"cur_freq" }) { + std::string p = sys_path + "/" + metric; + + if (!fs::exists(p)) { +@@ -658,11 +678,7 @@ void GPU_fdinfo::init_kgsl() { + } + + SPDLOG_DEBUG("kgsl: {} found", p); +- +- if (metric == "clock_mhz") +- gpu_clock_stream.open(p); +- else +- kgsl_streams[metric].open(p); ++ kgsl_streams[metric].open(p); + } + } + +@@ -702,6 +718,24 @@ int GPU_fdinfo::get_kgsl_temp() { + return std::round(std::stoi(temp_str) / 1'000.f); + } + ++int GPU_fdinfo::get_kgsl_clock() { ++ std::ifstream* s = &kgsl_streams["cur_freq"]; ++ ++ if (!s->is_open()) ++ return 0; ++ ++ std::string freq_str; ++ ++ s->seekg(0); ++ ++ std::getline(*s, freq_str); ++ ++ if (freq_str.empty()) ++ return 0; ++ ++ return std::round(std::stoi(freq_str) / 1'000'000.f); ++} ++ + void GPU_fdinfo::main_thread() + { + while (!stop_thread) { +diff --git a/src/gpu_fdinfo.h b/src/gpu_fdinfo.h +index 97e62e5..a5b1d9e 100644 +--- a/src/gpu_fdinfo.h ++++ b/src/gpu_fdinfo.h +@@ -119,6 +119,7 @@ private: + void init_kgsl(); + int get_kgsl_load(); + int get_kgsl_temp(); ++ int get_kgsl_clock(); + + public: + GPU_fdinfo( +@@ -146,6 +147,7 @@ public: + } else if (module == "msm_dpu") { + // msm driver does not report vram usage + drm_engine_type = "drm-engine-gpu"; ++ init_kgsl(); + } else if (module == "msm_drm") { + init_kgsl(); + } else if (module == "panfrost") { +-- +2.47.3 + diff --git a/projects/ArchR/packages/apps/mangohud/sources/mangohud_set b/projects/ArchR/packages/apps/mangohud/sources/mangohud_set new file mode 100644 index 0000000000..0975b07576 --- /dev/null +++ b/projects/ArchR/packages/apps/mangohud/sources/mangohud_set @@ -0,0 +1,85 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025-present ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile + +MHUD_SET=${1} + +### Enable logging +case $(get_setting system.loglevel) in + verbose) + DEBUG=true + ;; + *) + DEBUG=false + ;; +esac + +### Confirm MangoHud dir exists +if [ ! -d "/storage/.config/MangoHud" ]; then + cp -r "/usr/config/MangoHud" "/storage/.config/" +fi + +### Confirm MangoHud conf exists +if [ ! -f "/storage/.config/MangoHud/MangoHud.conf" ]; then + cp -r "/usr/config/MangoHud/MangoHud.conf" "/storage/.config/MangoHud" +fi + +# Enable MangoHud support +MANGOHUD_INIT_STATE=$(get_setting "archr.mangohud.state") +if [ ! -n "${MANGOHUD_INIT_STATE}" ]; then + MANGOHUD_INIT_STATE="off" + set_setting "archr.mangohud.state" "${MANGOHUD_INIT_STATE}" +fi + +### Check if a value was sent to mangohud_set +if [ ! -n "${MHUD_SET}" ]; then + MHUD_SET="NULL" +fi + +### Check that the value sent to manghud_set is a valid selection +if [[ "${MHUD_SET}" != "on" && "$MHUD_SET" != "off" && "${MHUD_SET}" != "toggle" && "$MHUD_SET" != "enable" && "$MHUD_SET" != "disable" ]]; then + ${DEBUG} && log $0 "$MHUD_SET is not a valid choice, valid options are on | off | toggle, setting MangoHud to off." + set_setting "archr.mangohud.state" "off" + MHUD_SET="off" +fi + +CONF_DIR="/storage/.config/MangoHud" +MANGOHUD_CONF="MangoHud.conf" + +case $MHUD_SET in + "disable") + set_setting "archr.mangohud.enabled" "0" + ${DEBUG} && log $0 "Disabling MangoHud." + ;; + "enable") + set_setting "archr.mangohud.enabled" "1" + ${DEBUG} && log $0 "Enabling MangoHud." + ;; + "off") + sed -i '/no_display/c\no_display' ${CONF_DIR}/${MANGOHUD_CONF} + set_setting "archr.mangohud.state" "off" + ${DEBUG} && log $0 "Turning MangoHud off." + ;; + "on") + sed -i '/no_display/c\# no_display' ${CONF_DIR}/${MANGOHUD_CONF} + set_setting "archr.mangohud.state" "on" + ${DEBUG} && log $0 "Turning MangoHud on." + ;; + "toggle") + MHUD_STATE=$(get_setting "archr.mangohud.state") + case ${MHUD_STATE} in + "on") + sed -i '/no_display/c\no_display' ${CONF_DIR}/${MANGOHUD_CONF} + set_setting "archr.mangohud.state" "off" + ${DEBUG} && log $0 "Toggle MangoHud, turning MangoHud off." + ;; + "off") + sed -i '/no_display/c\# no_display' ${CONF_DIR}/${MANGOHUD_CONF} + set_setting "archr.mangohud.state" "on" + ${DEBUG} && log $0 "Toggle MangoHud, turning MangoHud on." + ;; + esac + ;; +esac diff --git a/projects/ArchR/packages/apps/moonlight/autostart/010-moonlight b/projects/ArchR/packages/apps/moonlight/autostart/010-moonlight new file mode 100755 index 0000000000..1b30ba5547 --- /dev/null +++ b/projects/ArchR/packages/apps/moonlight/autostart/010-moonlight @@ -0,0 +1,15 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +if [ ! -f "/storage/.config/moonlight/moonlight.conf" ] +then + mkdir -p /storage/.config/moonlight + cp /usr/config/moonlight/moonlight.conf /storage/.config/moonlight/moonlight.conf +fi + +sed -i "s#@MWIDTH@#$(fbwidth)#g; + s#@MHEIGHT@#$(fbheight)#g" /storage/.config/moonlight/moonlight.conf diff --git a/projects/ArchR/packages/apps/moonlight/package.mk b/projects/ArchR/packages/apps/moonlight/package.mk new file mode 100644 index 0000000000..a4d9259e37 --- /dev/null +++ b/projects/ArchR/packages/apps/moonlight/package.mk @@ -0,0 +1,63 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="moonlight" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/moonlight-stream/moonlight-" +PKG_DEPENDS_TARGET="toolchain opus SDL2 libevdev alsa curl enet avahi libvdpau ffmpeg" +PKG_LONGDESC="Moonlight is an open source implementation of NVIDIA's GameStream, as used by the NVIDIA Shield, but built for Linux." +GET_HANDLER_SUPPORT="git" +PKG_PATCH_DIRS+="${DEVICE}" + +if [ "${TARGET_ARCH}" = "null" ] +then + PKG_SITE+="qt" + PKG_URL="${PKG_SITE}.git" + PKG_VERSION="8a87a09947f27dd2fe4bee7ae9faabe86873a5c4" + PKG_DEPENDS_TARGET+=" qt6" + PKG_TOOLCHAIN="manual" + make_target() { + qmake6 "CONFIG+=embedded" moonlight-qt.pro + make release + } + post_makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + mkdir -p ${INSTALL}/usr/config/modules + cp ${PKG_BUILD}/app/moonlight ${INSTALL}/usr/bin/ + cp ${PKG_BUILD}/start_moonlight.sh ${INSTALL}/usr/bin/ + chmod +x ${INSTALL}/usr/bin/* + mv ${INSTALL}/usr/bin/start_moonlight.sh ${INSTALL}/usr/config/modules/Start\ Moonlight.sh + } +else + PKG_SITE+="embedded" + PKG_URL="${PKG_SITE}.git" + PKG_VERSION="a6bf7154a743d4f74a1b377e730f188352a1b80c" + PKG_TOOLCHAIN="cmake" + + PKG_CMAKE_OPTS_TARGET+=" -DENABLE_CEC=OFF" + + post_makeinstall_target() { + mkdir -p ${INSTALL}/usr/config/moonlight + cp -R ${PKG_BUILD}/moonlight.conf ${INSTALL}/usr/config/moonlight + rm ${INSTALL}/usr/etc/moonlight.conf + rm ${INSTALL}/usr/share/moonlight/gamecontrollerdb.txt + } +fi + +if [[ "${DEVICE}" == RK* ]] +then + PKG_DEPENDS_TARGET+=" librga rkmpp" +fi + +if [ ! "${OPENGL}" = "no" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL} glu libglvnd" +fi + +if [ "${OPENGLES_SUPPORT}" = yes ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" +fi + +if [ "${VULKAN_SUPPORT}" = "yes" ] + then + PKG_DEPENDS_TARGET+=" ${VULKAN}" +fi diff --git a/projects/ArchR/packages/apps/moonlight/sources/moonlight.conf b/projects/ArchR/packages/apps/moonlight/sources/moonlight.conf new file mode 100644 index 0000000000..e766d0c615 --- /dev/null +++ b/projects/ArchR/packages/apps/moonlight/sources/moonlight.conf @@ -0,0 +1,82 @@ +## Hostname or IP-address of host to connect to +## By default host is autodiscovered using mDNS +#address = 1.2.3.4 + +## Video streaming configuration +width = @MWIDTH@ +height = @MHEIGHT@ +fps = 60 + +## Output rotation (independent of xrandr or framebuffer settings!) +## Allowed values: 0, 90, 180, 270 +#rotation = 0 + +## Bitrate depends by default on resolution and fps +## Set to -1 to enable default +## 20Mbps (20000) for 1080p (60 fps) +## 10Mbps (10000) for 1080p or 60 fps +## 5Mbps (5000) for lower resolution or fps +bitrate = 15000 + +## Size of network packets should be lower than MTU +## If streaming with WAN optimizations, this will be capped at 1024. +#packetsize = 1392 + +## Select video codec (auto/h264/h265) +codec = h264 + +## Default started application on host +#app = Steam + +## Default used mapping for streaming +## Searched for in $XDG_DATA_DIRS/moonlight or /usr/share/moonlight and /usr/local/share/moonlight +## Mapping can also be user overrided in $XDG_CONFIG_DIR/moonlight or ~/.config/moonlight or current directory +#mapping = gamecontrollerdb.txt + +## Enable selected input devices +## By default all available input devices should be used +## Only evdev devices /dev/input/event* are allowed +## To use a different mapping then default another mapping should be declared above the input +#input = /dev/input/event1 + +## Enable GFE for changing graphical game settings for optimal performance and quality +#sops = true + +## Play audio on host instead of streaming to client +#localaudio = false + +## Send quit app request to remote after quitting session +quitappafter = true + +## Disable all input processing (view-only mode) +#viewonly = false + +## Select audio device to play sound on +#audio = sysdefault + +## Select the audio and video decoder to use +## default - autodetect +## aml - hardware video decoder for ODROID-C1/C2 +## rk - hardware video decoder for ODROID-N1 Rockchip +## omx - hardware video decoder for Raspberry Pi +## imx - hardware video decoder for i.MX6 devices +## x11 - software decoder +## sdl - software decoder with SDL input and audio +## fake - no audio and video +platform = sdl + +## Directory to store encryption keys +## By default keys are stored in $XDG_CACHE_DIR/moonlight or ~/.cache/moonlight +#keydir = /dir/to/keys + +## Enable QOS settings to optimize for internet or local network +## yes - optimize for WAN streaming +## no - optimize for LAN streaming +## auto (default) - decide automatically based on target IP address +#remote = auto + +## Enable 5.1/7.1 surround sound +#surround = 5.1 + +## Load additional configuration files +#config = /path/to/config diff --git a/projects/ArchR/packages/apps/moonlight/sources/start_moonlight.sh b/projects/ArchR/packages/apps/moonlight/sources/start_moonlight.sh new file mode 100644 index 0000000000..515cb099c7 --- /dev/null +++ b/projects/ArchR/packages/apps/moonlight/sources/start_moonlight.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +. /etc/profile +set_kill set "moonlight" +QT_QPA_PLATFORM=wayland moonlight diff --git a/projects/ArchR/packages/apps/oga_controls/Makefile b/projects/ArchR/packages/apps/oga_controls/Makefile new file mode 100644 index 0000000000..8f3a37c82f --- /dev/null +++ b/projects/ArchR/packages/apps/oga_controls/Makefile @@ -0,0 +1,12 @@ +cc = gcc +CFLAGS += -W -Wall + +BINARY = oga_controls +LIBRARIES = -levdev -lSDL2 +SOURCES = "main.c" + +all: + $(CC) $(CFLAGS) $(SOURCES) -o $(BINARY) $(LIBRARIES) + +clean: + rm -f $(BINARY) diff --git a/projects/ArchR/packages/apps/oga_controls/package.mk b/projects/ArchR/packages/apps/oga_controls/package.mk new file mode 100644 index 0000000000..e1f9e9e28a --- /dev/null +++ b/projects/ArchR/packages/apps/oga_controls/package.mk @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="oga_controls" +PKG_VERSION="1604ee24150c1c5bb7c66bc4670919c2ad8f0064" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/christianhaitian/oga_controls" +PKG_URL="${PKG_SITE}.git" +PKG_GIT_CLONE_BRANCH="universal" +PKG_DEPENDS_TARGET="toolchain libevdev SDL2" +PKG_LONGDESC="Emulated keyboard / mouse / joystick for the RGB10/OGA 1.1 (BE), RG351 P/M/V, RK2020/OGA 1.0, OGS, and the Chi" +PKG_TOOLCHAIN="make" +GET_HANDLER_SUPPORT="git" +PKG_PATCH_DIRS+="${DEVICE}" + +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}/oga_controls* ${INSTALL}/usr/bin +} diff --git a/projects/ArchR/packages/apps/oga_controls/patches/000-fix-libevdev.patch b/projects/ArchR/packages/apps/oga_controls/patches/000-fix-libevdev.patch new file mode 100644 index 0000000000..d719f6acb4 --- /dev/null +++ b/projects/ArchR/packages/apps/oga_controls/patches/000-fix-libevdev.patch @@ -0,0 +1,15 @@ +diff --git a/main.c b/main.c +index 2e43de7..80999b8 100644 +--- a/main.c ++++ b/main.c +@@ -30,8 +30,8 @@ + #include + #include + +-#include +-#include ++#include ++#include + + #include "parser.h" + diff --git a/projects/ArchR/packages/apps/oga_controls/patches/RK3326/000-platform.patch b/projects/ArchR/packages/apps/oga_controls/patches/RK3326/000-platform.patch new file mode 100644 index 0000000000..70dee864a0 --- /dev/null +++ b/projects/ArchR/packages/apps/oga_controls/patches/RK3326/000-platform.patch @@ -0,0 +1,33 @@ +diff --git a/main.c b/main.c +index 2e43de7..27cbd65 100644 +--- a/main.c ++++ b/main.c +@@ -1455,7 +1455,7 @@ void handle_event_ogx(int type, int code, int value) { + } + } + +-void handle_event_rk2020(int type, int code, int value) { ++void handle_event_oga(int type, int code, int value) { + if (type == 1) { + if (code == back_key && value == 1) { + hold = 1; +@@ -2215,7 +2215,7 @@ int main(int argc, char* argv[]) { + deadzone_x = -300; + strcpy(inputstr, "/dev/input/by-path/platform-odroidgo2-joypad-event-joystick"); + } +- else if (strcmp(argv[2], "rk2020") == 0) { ++ else if (strcmp(argv[2], "oga") == 0) { + back_key = 704; + start_key = 709; + a_key = 305; +@@ -2456,8 +2456,8 @@ int main(int argc, char* argv[]) { + if (strcmp(argv[2], "anbernic") == 0) { + handle_event_anbernic(ev_joypad.type, ev_joypad.code, ev_joypad.value); + } +- else if (strcmp(argv[2], "rk2020") == 0) { +- handle_event_rk2020(ev_joypad.type, ev_joypad.code, ev_joypad.value); ++ else if (strcmp(argv[2], "oga") == 0) { ++ handle_event_oga(ev_joypad.type, ev_joypad.code, ev_joypad.value); + } + else if (strcmp(argv[2], "chi") == 0) { + handle_event_chi(ev_joypad.type, ev_joypad.code, ev_joypad.value); diff --git a/projects/ArchR/packages/apps/oga_controls/patches/S922X/000-platform.patch b/projects/ArchR/packages/apps/oga_controls/patches/S922X/000-platform.patch new file mode 100644 index 0000000000..54eff6a259 --- /dev/null +++ b/projects/ArchR/packages/apps/oga_controls/patches/S922X/000-platform.patch @@ -0,0 +1,42 @@ +diff --git a/main.c b/main.c +index 2e43de7..8ef2b8b 100644 +--- a/main.c ++++ b/main.c +@@ -113,7 +113,7 @@ void emit(int type, int code, int val) { + write(uinp_fd, &ev, sizeof(ev)); + } + +-void handle_event_rg552(int type, int code, int value) { ++void handle_event_s922x(int type, int code, int value) { + if (type == 1) { + if (code == back_key && value == 1) { + emit(EV_KEY, back, 1); +@@ -2276,7 +2276,7 @@ int main(int argc, char* argv[]) { + deadzone_x = -300; + strcpy(inputstr, "/dev/input/by-path/platform-gameforce-gamepad-event-joystick"); + } +- else if (strcmp(argv[2], "rg552") == 0) { ++ else if (strcmp(argv[2], "s922x") == 0) { + back_key = 314; + start_key = 315; + a_key = 305; +@@ -2295,7 +2295,7 @@ int main(int argc, char* argv[]) { + r3_key = 318; + deadzone_y = 300; + deadzone_x = -300; +- strcpy(inputstr, "/dev/input/by-path/platform-singleadc-joypad-event-joystick"); ++ strcpy(inputstr, "/dev/input/by-path/platform-platform-gou_joypad-event-joystick"); + } + else { + printf("Error launching, unrecognised parameters\n"); +@@ -2465,8 +2465,8 @@ int main(int argc, char* argv[]) { + else if (strcmp(argv[2], "ogs") == 0) { + handle_event_ogs(ev_joypad.type, ev_joypad.code, ev_joypad.value); + } +- else if (strcmp(argv[2], "rg552") == 0) { +- handle_event_rg552(ev_joypad.type, ev_joypad.code, ev_joypad.value); ++ else if (strcmp(argv[2], "s922x") == 0) { ++ handle_event_s922x(ev_joypad.type, ev_joypad.code, ev_joypad.value); + } + else { + handle_event_ogx(ev_joypad.type, ev_joypad.code, ev_joypad.value); diff --git a/projects/ArchR/packages/apps/portmaster/package.mk b/projects/ArchR/packages/apps/portmaster/package.mk new file mode 100644 index 0000000000..3357c3386d --- /dev/null +++ b/projects/ArchR/packages/apps/portmaster/package.mk @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="portmaster" +PKG_VERSION="2026.04.01-1426" +PKG_ARCH="arm aarch64" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/PortsMaster/PortMaster-GUI" +PKG_URL="https://github.com/PortsMaster/PortMaster-GUI/releases/download/${PKG_VERSION}/PortMaster.zip" +PKG_DEPENDS_TARGET="toolchain archr-hotkey gamecontrollerdb oga_controls control-gen xmlstarlet list-guid gst-plugins-base Python3 xz" +PKG_LONGDESC="Portmaster - a simple tool that allows you to download various game ports" +PKG_TOOLCHAIN="manual" + +COMPAT_URL="https://github.com/archr-linux/packages/raw/main/compat.zip" + +makeinstall_target() { + export STRIP=true + + mkdir -p ${INSTALL}/usr/config/PortMaster + cp -a ${PKG_DIR}/sources/* ${INSTALL}/usr/config/PortMaster + + mkdir -p ${INSTALL}/usr/bin + cp -a ${PKG_DIR}/scripts/* ${INSTALL}/usr/bin + + mkdir -p ${INSTALL}/usr/config/PortMaster/release + curl -Lo ${INSTALL}/usr/config/PortMaster/release/PortMaster.zip ${PKG_URL} + + mkdir -p ${INSTALL}/usr/lib/compat + curl -Lo ${PKG_BUILD}/compat.zip ${COMPAT_URL} + unzip -qq ${PKG_BUILD}/compat.zip -d ${INSTALL}/usr/lib/compat +} diff --git a/projects/ArchR/packages/apps/portmaster/scripts/portmaster_sway_fullscreen.sh b/projects/ArchR/packages/apps/portmaster/scripts/portmaster_sway_fullscreen.sh new file mode 100755 index 0000000000..ab734f4626 --- /dev/null +++ b/projects/ArchR/packages/apps/portmaster/scripts/portmaster_sway_fullscreen.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# Will be called by PortMaster mod_ArchR.txt + +. /etc/profile + +if echo "${UI_SERVICE}" | grep -q "sway"; then + # Call the function to fullscreen the window for app_id asynchronously + sway_fullscreen "${1}" & + + # Create a virtual touch keyboard device if there are two displays + if [[ "${DEVICE_HAS_DUAL_SCREEN}" == "true" ]]; then + TSKEY=$(get_setting "archr.touchscreen-keyboard.enabled") + if [[ "${TSKEY}" == "1" ]]; then + swaymsg 'output DSI-1 power on' + ( + sleep 2 + swaymsg 'seat seat1 fallback yes' + ) & + fi + fi +fi diff --git a/projects/ArchR/packages/apps/portmaster/scripts/start_portmaster.sh b/projects/ArchR/packages/apps/portmaster/scripts/start_portmaster.sh new file mode 100755 index 0000000000..ba787fe200 --- /dev/null +++ b/projects/ArchR/packages/apps/portmaster/scripts/start_portmaster.sh @@ -0,0 +1,73 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile +. /etc/os-release +set_kill set "PortMaster" + +#Make sure PortMaster exists in .config/PortMaster +if [ ! -d "/storage/.config/PortMaster" ]; then + mkdir -p "/storage/.config/PortMaster" + cp -r "/usr/config/PortMaster" "/storage/.config/" +fi + +cd /storage/.config/PortMaster + +#Grab the latest control.txt & mapper.txt, then set correct permissions +cp /usr/config/PortMaster/control.txt control.txt +chmod +x /storage/.config/PortMaster/control.txt +cp /usr/config/PortMaster/mapper.txt mapper.txt +chmod +x /storage/.config/PortMaster/mapper.txt + + +#Use our gamecontrollerdb.txt +rm -rf gamecontrollerdb.txt +ln -sf /usr/config/SDL-GameControllerDB/gamecontrollerdb.txt gamecontrollerdb.txt + +#Delete old PortMaster fold first (we can probably remove this later) +if [ -d "/storage/roms/ports/PortMaster" ] && [ ! -f "/storage/roms/ports/PortMaster/pugwash" ]; then + rm -rf /storage/roms/ports/PortMaster +fi + +#Make sure roms/ports/PortMaster folder exists +if [ ! -d "/storage/roms/ports/PortMaster" ]; then + unzip /usr/config/PortMaster/release/PortMaster.zip -d /storage/roms/ports/ + chmod +x /storage/roms/ports/PortMaster/PortMaster.sh +fi + +#We dont use tasksetter, delete it +rm -rf /storage/roms/ports/PortMaster/tasksetter + +#Use PortMasters gptokeyb +rm -f gptokeyb +[ -x /storage/roms/ports/PortMaster/gptokeyb ] && cp /storage/roms/ports/PortMaster/gptokeyb gptokeyb + +#Copy over required files for ports +cp /storage/.config/PortMaster/control.txt /storage/roms/ports/PortMaster/control.txt +cp /storage/.config/PortMaster/mapper.txt /storage/roms/ports/PortMaster/mapper.txt +cp /storage/.config/PortMaster/gamecontrollerdb.txt /storage/roms/ports/PortMaster/gamecontrollerdb.txt +cp /usr/bin/oga_controls* /storage/roms/ports/PortMaster/ + +#Hide PortMaster folder in ports +if [ ! -f /storage/roms/ports/gamelist.xml ]; then +echo " + + ./PortMaster + PortMaster + true + +" > /storage/roms/ports/gamelist.xml +else + xmlstarlet ed --inplace -d "/gameList/folder[name='PortMaster']" /storage/roms/ports/gamelist.xml + xmlstarlet ed --inplace -d "/gameList/game[name='PortMaster']" /storage/roms/ports/gamelist.xml + xmlstarlet ed --inplace --subnode "/gameList" --type elem -n folder -v "" /storage/roms/ports/gamelist.xml + xmlstarlet ed --inplace --subnode "/gameList/folder[last()]" --type elem -n path -v "./PortMaster" /storage/roms/ports/gamelist.xml + xmlstarlet ed --inplace --subnode "/gameList/folder[last()]" --type elem -n name -v "PortMaster" /storage/roms/ports/gamelist.xml + xmlstarlet ed --inplace --subnode "/gameList/folder[last()]" --type elem -n hidden -v "true" /storage/roms/ports/gamelist.xml +fi + +#Start PortMaster +cd /storage/roms/ports/PortMaster +./PortMaster.sh 2>/dev/null diff --git a/projects/ArchR/packages/apps/portmaster/sources/control.txt b/projects/ArchR/packages/apps/portmaster/sources/control.txt new file mode 100644 index 0000000000..640f2367d1 --- /dev/null +++ b/projects/ArchR/packages/apps/portmaster/sources/control.txt @@ -0,0 +1,110 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +# This file can and should be sourced by ports for various parameters to +# minimize script customizations and allow for easier future updates +# like adding additional supported devices. +# Thanks to JohnnyonFlame, dhwz, romadu, and shantigilbert for the +# suggestion and assistance with this. +# Source used for gptokeyb available at +# https://github.com/christianhaitian/gptokeyb +# Source used for oga_controls available at +# https://github.com/christianhaitian/oga_controls + +. /etc/profile + +directory="roms" +controlfolder="/$directory/ports/PortMaster" +ESUDO="" +ESUDOKILL="-1" +ESUDOKILL2="-1" +SDLDBUSERFILE="/storage/.config/SDL-GameControllerDB/gamecontrollerdb.txt" +clibs="/usr/lib/compat/" +raloc="/usr/bin" +raconf="--config /storage/.config/retroarch/retroarch.cfg" + +[[ -f "$controlfolder/device_info.txt" ]] && source $controlfolder/device_info.txt +[[ -f "$controlfolder/funcs.txt" ]] && source $controlfolder/funcs.txt + +# $param_device / $LOWRES / $ANALOG_STICKS (also set by device_info.txt) are used in port launch scripts +case "${QUIRK_DEVICE}" in + "Anbernic RG552") + param_device="rg552" + LOWRES="N" + ANALOG_STICKS="2" + ;; + "Hardkernel ODROID-GO-Ultra"|"Powkiddy RGB10 MAX 3 Pro") + param_device="s922x" + LOWRES="N" + ANALOG_STICKS="2" + ;; + "Powkiddy x55") + param_device="x55" + LOWRES="N" + ANALOG_STICKS="2" + ;; + "Anbernic RG351M") + param_device="anbernic" + LOWRES="Y" + ANALOG_STICKS="2" + ;; + "Anbernic RG351V") + param_device="anbernic" + LOWRES="N" + ANALOG_STICKS="1" + ;; + "ODROID-GO Advance*"|"Powkiddy RGB10") + param_device="oga" + LOWRES="Y" + ANALOG_STICKS="1" + ;; + "ODROID-GO Super") + param_device="ogs" + LOWRES="N" + ANALOG_STICKS="2" + ;; + "Anbernic RG35XX H"|"Anbernic RG40XX H"|"Anbernic RG CubeXX") + param_device="anbernic" + LOWRES="N" + ANALOG_STICKS="2" + ;; + "Anbernic RG40XX V") + param_device="anbernic" + LOWRES="N" + ANALOG_STICKS="1" + ;; + "Anbernic RG35XX Plus"|"Anbernic RG35XX 2024"|"Anbernic RG28XX") + param_device="anbernic" + LOWRES="N" + ANALOG_STICKS="0" + ;; + "Game Console R36S"*|"R36S Clone") + param_device="oga" + LOWRES="Y" + ANALOG_STICKS="2" + ;; + *) + param_device="oga" + LOWRES="Y" + ANALOG_STICKS="2" + ;; +esac + +get_controls() { + # Set controller file to be generated + export SDL_GAMECONTROLLERCONFIG_FILE="/tmp/gamecontrollerdb.txt" + + # Generate controller file for controllers mapped in emulationstation + /storage/.config/PortMaster/mapper.txt ${SDL_GAMECONTROLLERCONFIG_FILE} ${controlfolder} + + # Set compatability libs + export LD_LIBRARY_PATH=${clibs} + + # Some ports want sdl_controllerconfig (to set SDL_GAMECONTROLLERCONFIG), so let's fill it in + sdl_controllerconfig="$(< "${SDL_GAMECONTROLLERCONFIG_FILE}")" +} + +GPTOKEYB2="$ESUDO env LD_PRELOAD=$controlfolder/libinterpose.${DEVICE_ARCH}.so $controlfolder/gptokeyb2 $ESUDOKILL" +GPTOKEYB="$ESUDO $controlfolder/gptokeyb $ESUDOKILL" diff --git a/projects/ArchR/packages/apps/portmaster/sources/mapper.txt b/projects/ArchR/packages/apps/portmaster/sources/mapper.txt new file mode 100644 index 0000000000..c88f4fe746 --- /dev/null +++ b/projects/ArchR/packages/apps/portmaster/sources/mapper.txt @@ -0,0 +1,53 @@ +#!/bin/bash + +. /etc/profile.d/001-functions +. /etc/profile.d/100-gamecontroller-functions + +# -- Config & Setup -- +# Destination file +if [[ -z "$1" ]] && [[ -z "$2" ]]; then + echo "Usage: mapper.txt [gamecontrollerdb.txt] [controlfolder]" + exit -1 +fi + +CONTROLLER_DB="$1" +controlfolder="$2" + +#Scrub the CONTROLLER_DB file +echo "" > ${CONTROLLER_DB} + +# Where the emulationstation configuration file is +ES_CONFIG="/tmp/es_input.cfg" + +#Set layout via Emulation Station +ACTIVE_GAME="" +ACTIVE_PLATFORM="" +GAME="${ACTIVE_GAME##*/}" +PLATFORM="${ACTIVE_PLATFORM##*/}" +CONTROLLER_LAYOUT=$(get_setting controller_layout "${PLATFORM}" "${GAME}") + +#Default to nintendo if no value assigned +if [ ! -n "${CONTROLLER_LAYOUT}" ]; then + CONTROLLER_LAYOUT="nintendo" +fi + +scriptdir="controller_layout" + +if [ ! -d "${controlfolder}/${scriptdir}" ]; then + mkdir -p "${controlfolder}/${scriptdir}" +fi + +echo -e "# Xbox Layout\nABUT=\"b\"\nBBUT=\"a\"\nXBUT=\"y\"\nYBUT=\"x\"" > "${controlfolder}/${scriptdir}/xbox_layout.txt" +echo -e "# Nintendo Layout\nABUT=\"a\"\nBBUT=\"b\"\nXBUT=\"x\"\nYBUT=\"y\"" > "${controlfolder}/${scriptdir}/nintendo_layout.txt" +if [[ ! -e "${controlfolder}/${scriptdir}/custom_layout.txt" ]]; then + echo -e "# Custom Layout\nABUT=\"a\"\nBBUT=\"b\"\nXBUT=\"x\"\nYBUT=\"y\"" > "${controlfolder}/${scriptdir}/custom_layout.txt" +fi + +source "${controlfolder}/${scriptdir}/${CONTROLLER_LAYOUT}_layout.txt" + +# Call function to create controller db from ES input config file for only connected devices +create_controller_db ${CONTROLLER_LAYOUT} ${ES_CONFIG} ${CONTROLLER_DB} + +#Reset file for next run +sed -i '/^ACTIVE_GAME=/c\ACTIVE_GAME=""' /storage/.config/PortMaster/mapper.txt +sed -i '/^ACTIVE_PLATFORM=/c\ACTIVE_PLATFORM=""' /storage/.config/PortMaster/mapper.txt diff --git a/projects/ArchR/packages/apps/qterminal/layer-shell-qt/package.mk b/projects/ArchR/packages/apps/qterminal/layer-shell-qt/package.mk new file mode 100644 index 0000000000..a035f70c3b --- /dev/null +++ b/projects/ArchR/packages/apps/qterminal/layer-shell-qt/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2025-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="layer-shell-qt" +PKG_VERSION="v6.4.3" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/KDE/layer-shell-qt" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_LONGDESC="Layer-Shell-QT is meant for applications to be able to easily use clients based on wlr-layer-shell." +PKG_DEPENDS_TARGET="toolchain qt6 ecm" +PKG_TOOLCHAIN="cmake" + +post_makeinstall_target() { + rm -rf ${INSTALL}/usr + mkdir -p ${INSTALL}/usr/lib + cp -rf ${PKG_BUILD}/.${TARGET_NAME}/bin/libLayerShellQtInterface.so* ${INSTALL}/usr/lib +} diff --git a/projects/ArchR/packages/apps/qterminal/lxqt-build-tools/package.mk b/projects/ArchR/packages/apps/qterminal/lxqt-build-tools/package.mk new file mode 100644 index 0000000000..b9785f917a --- /dev/null +++ b/projects/ArchR/packages/apps/qterminal/lxqt-build-tools/package.mk @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2025-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="lxqt-build-tools" +PKG_VERSION="2.2.0" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/lxqt/lxqt-build-tools" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_LONGDESC="Several tools needed to build LXQt itself as well as other components maintained by the LXQt project." +PKG_DEPENDS_TARGET="toolchain qt6" +PKG_TOOLCHAIN="cmake" + +post_makeinstall_target() { + rm -rf ${INSTALL}/usr +} diff --git a/projects/ArchR/packages/apps/qterminal/lxqt-build-tools/patches/000-fix-build.patch b/projects/ArchR/packages/apps/qterminal/lxqt-build-tools/patches/000-fix-build.patch new file mode 100644 index 0000000000..2d6de3c8d6 --- /dev/null +++ b/projects/ArchR/packages/apps/qterminal/lxqt-build-tools/patches/000-fix-build.patch @@ -0,0 +1,13 @@ +diff --git a/cmake/FindInstallConfigPath.cmake b/cmake/FindInstallConfigPath.cmake +index 4ea6552..fbbf5ed 100644 +--- a/cmake/FindInstallConfigPath.cmake ++++ b/cmake/FindInstallConfigPath.cmake +@@ -6,7 +6,7 @@ + # + + find_package(Qt6 ${LXQTBT_QT_MINIMUM_VERSION} REQUIRED) +-find_package(Qt6CoreTools ${LXQTBT_QT_MINIMUM_VERSION} REQUIRED) ++#find_package(Qt6CoreTools ${LXQTBT_QT_MINIMUM_VERSION} REQUIRED) + + macro(print_set_lxqt_etc_xdg_dir_info) + message(STATUS "You can set it manually with -DLXQT_ETC_XDG_DIR=") diff --git a/projects/ArchR/packages/apps/qterminal/package.mk b/projects/ArchR/packages/apps/qterminal/package.mk new file mode 100644 index 0000000000..e5ccafedf4 --- /dev/null +++ b/projects/ArchR/packages/apps/qterminal/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2025-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="qterminal" +PKG_VERSION="2.2.1" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/lxqt/qterminal" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_LONGDESC="QTerminal is a lightweight Qt terminal emulator based on QTermWidget." +PKG_DEPENDS_TARGET="toolchain qt6 qtermwidget lxqt-build-tools layer-shell-qt" +PKG_TOOLCHAIN="cmake" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp -rf ${PKG_BUILD}/.${TARGET_NAME}/qterminal ${INSTALL}/usr/bin + chmod 0755 ${INSTALL}/usr/bin/qterminal + + mkdir -p ${INSTALL}/usr/config/modules + cp -rf ${PKG_DIR}/scripts/* ${INSTALL}/usr/config/modules + chmod 0755 ${INSTALL}/usr/config/modules/* +} diff --git a/projects/ArchR/packages/apps/qterminal/patches/000-build-fixes.patch b/projects/ArchR/packages/apps/qterminal/patches/000-build-fixes.patch new file mode 100644 index 0000000000..2744c1230d --- /dev/null +++ b/projects/ArchR/packages/apps/qterminal/patches/000-build-fixes.patch @@ -0,0 +1,13 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 0a431b7..683dc03 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -29,7 +29,7 @@ set(SHELLQT_MINIMUM_VERSION "6.0.0") + + find_package(Qt6Core ${QT_MINIMUM_VERSION} REQUIRED) + find_package(Qt6Gui ${QT_MINIMUM_VERSION} REQUIRED) +-find_package(Qt6LinguistTools ${QT_MINIMUM_VERSION} REQUIRED) ++find_package(Qt6Tools ${QT_MINIMUM_VERSION} REQUIRED) + find_package(Qt6Widgets ${QT_MINIMUM_VERSION} REQUIRED) + find_package(LayerShellQt ${SHELLQT_MINIMUM_VERSION} REQUIRED) + if(UNIX) diff --git a/projects/ArchR/packages/apps/qterminal/patches/001-fullscreen.patch b/projects/ArchR/packages/apps/qterminal/patches/001-fullscreen.patch new file mode 100644 index 0000000000..e3e1d00ffe --- /dev/null +++ b/projects/ArchR/packages/apps/qterminal/patches/001-fullscreen.patch @@ -0,0 +1,22 @@ +diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp +index d5163c8..c327bc9 100644 +--- a/src/mainwindow.cpp ++++ b/src/mainwindow.cpp +@@ -589,7 +589,7 @@ void MainWindow::toggleBorderless() + + void MainWindow::toggleMenu() + { +- m_menuBar->setVisible(!m_menuBar->isVisible()); ++ m_menuBar->setVisible(false); + Properties::Instance()->menuVisible = m_menuBar->isVisible(); + } + +@@ -748,7 +748,7 @@ void MainWindow::propertiesChanged() + } + } + +- m_menuBar->setVisible(Properties::Instance()->menuVisible); ++ m_menuBar->setVisible(false); + + m_bookmarksDock->setVisible(Properties::Instance()->useBookmarks + && Properties::Instance()->bookmarksVisible); diff --git a/projects/ArchR/packages/apps/qterminal/patches/002-font-and-theme.patch b/projects/ArchR/packages/apps/qterminal/patches/002-font-and-theme.patch new file mode 100644 index 0000000000..69956f0b68 --- /dev/null +++ b/projects/ArchR/packages/apps/qterminal/patches/002-font-and-theme.patch @@ -0,0 +1,31 @@ +diff --git a/src/properties.cpp b/src/properties.cpp +index 78cba0b..8201dfc 100644 +--- a/src/properties.cpp ++++ b/src/properties.cpp +@@ -69,7 +69,7 @@ QFont Properties::defaultFont() + { + QFont default_font = QApplication::font(); + default_font.setFamily(QLatin1String(DEFAULT_FONT)); +- default_font.setPointSize(12); ++ default_font.setPointSize(20); + default_font.setStyleHint(QFont::TypeWriter); + return default_font; + } +@@ -80,7 +80,7 @@ void Properties::loadSettings() + if (!guiStyle.isNull()) + QApplication::setStyle(guiStyle); + +- colorScheme = m_settings->value(QLatin1String("colorScheme"), QLatin1String("Linux")).toString(); ++ colorScheme = m_settings->value(QLatin1String("colorScheme"), QLatin1String("WhiteOnBlack")).toString(); + + highlightCurrentTerminal = m_settings->value(QLatin1String("highlightCurrentTerminal"), true).toBool(); + focusOnMoueOver = m_settings->value(QLatin1String("focusOnMoueOver"), false).toBool(); +@@ -126,7 +126,7 @@ void Properties::loadSettings() + /* default to BlockCursor */ + keyboardCursorShape = m_settings->value(QLatin1String("KeyboardCursorShape"), 0).toInt(); + keyboardCursorBlink = m_settings->value(QLatin1String("KeyboardCursorBlink"), false).toBool(); +- hideTabBarWithOneTab = m_settings->value(QLatin1String("HideTabBarWithOneTab"), false).toBool(); ++ hideTabBarWithOneTab = m_settings->value(QLatin1String("HideTabBarWithOneTab"), true).toBool(); + // For "Motion after paste", 2 (scrolling to bottom) makes more sense + m_motionAfterPaste = m_settings->value(QLatin1String("MotionAfterPaste"), 2).toInt(); + m_disableBracketedPasteMode = m_settings->value(QLatin1String("DisableBracketedPasteMode"), false).toBool(); diff --git a/projects/ArchR/packages/apps/qterminal/qtermwidget/package.mk b/projects/ArchR/packages/apps/qterminal/qtermwidget/package.mk new file mode 100644 index 0000000000..27ac3ca663 --- /dev/null +++ b/projects/ArchR/packages/apps/qterminal/qtermwidget/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2025-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="qtermwidget" +PKG_VERSION="2.2.0" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/lxqt/qtermwidget" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_LONGDESC="A terminal emulator widget for Qt 6." +PKG_DEPENDS_TARGET="toolchain qt6 lxqt-build-tools" +PKG_TOOLCHAIN="cmake" + +post_makeinstall_target() { + rm -rf ${INSTALL}/usr + + mkdir -p ${INSTALL}/usr/lib + cp -rf ${PKG_BUILD}/.${TARGET_NAME}/libqtermwidget6.so* ${INSTALL}/usr/lib + + mkdir -p ${INSTALL}/usr/config/qterminal.org/color-schemes + cp -rf ${PKG_BUILD}/lib/color-schemes/*.colorscheme ${INSTALL}/usr/config/qterminal.org/color-schemes/ +} diff --git a/projects/ArchR/packages/apps/qterminal/qtermwidget/patches/000-fix-build.patch b/projects/ArchR/packages/apps/qterminal/qtermwidget/patches/000-fix-build.patch new file mode 100644 index 0000000000..44c5817d93 --- /dev/null +++ b/projects/ArchR/packages/apps/qterminal/qtermwidget/patches/000-fix-build.patch @@ -0,0 +1,13 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index bf7aa04..bc7df47 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -36,7 +36,7 @@ set(QT_MINIMUM_VERSION "6.6.0") + set(LXQTBT_MINIMUM_VERSION "2.2.0") + + find_package(Qt6Widgets "${QT_MINIMUM_VERSION}" REQUIRED) +-find_package(Qt6LinguistTools "${QT_MINIMUM_VERSION}" REQUIRED) ++find_package(Qt6Tools "${QT_MINIMUM_VERSION}" REQUIRED) + find_package(lxqt2-build-tools ${LXQTBT_MINIMUM_VERSION} REQUIRED) + + if(USE_UTF8PROC) diff --git a/projects/ArchR/packages/apps/qterminal/scripts/qterminal.sh b/projects/ArchR/packages/apps/qterminal/scripts/qterminal.sh new file mode 100644 index 0000000000..e3d84f2584 --- /dev/null +++ b/projects/ArchR/packages/apps/qterminal/scripts/qterminal.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2025 ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile +set_kill set "qterminal" + +if [ ! -d "/storage/.config/qterminal.org" ]; then + cp -r "/usr/config/qterminal.org" "/storage/.config/" +fi + +sway_fullscreen "qterminal" & + +cd ~/ +/usr/bin/qterminal diff --git a/projects/ArchR/packages/apps/screen-switch/package.mk b/projects/ArchR/packages/apps/screen-switch/package.mk new file mode 100644 index 0000000000..48fe274118 --- /dev/null +++ b/projects/ArchR/packages/apps/screen-switch/package.mk @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2025 ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="screen-switch" +PKG_VERSION="1.0" +PKG_LICENSE="GPLv3" +PKG_DEPENDS_TARGET="toolchain sway" +PKG_LONGDESC="A simple script to swap sway output screens" +PKG_TOOLCHAIN="manual" +PKG_PATCH_DIRS+="${DEVICE}" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp -rf ${PKG_DIR}/scripts/screen_switch ${INSTALL}/usr/bin + chmod 0755 ${INSTALL}/usr/bin/* +} diff --git a/projects/ArchR/packages/apps/screen-switch/scripts/screen_switch b/projects/ArchR/packages/apps/screen-switch/scripts/screen_switch new file mode 100644 index 0000000000..dc2568228a --- /dev/null +++ b/projects/ArchR/packages/apps/screen-switch/scripts/screen_switch @@ -0,0 +1,51 @@ +#!/bin/bash + +source /etc/profile + +ACTIVE_APPID=$(swaymsg -t get_tree | awk ' + /"focused": true/ {focused=1} + focused && /"app_id":/ { + gsub(/.*"app_id": *"/,""); gsub(/".*/,""); print; exit + } +') + +if [[ -n "$ACTIVE_APPID" && "$ACTIVE_APPID" = "emulationstation" ]]; then + exit 0 +fi + +OUTPUTS=$(swaymsg -t get_outputs -r | jq -r '.[] | select(.active==true) | .name') + +if [ "$(echo "$OUTPUTS" | wc -l)" -lt 2 ]; then + exit 0 +fi + +BUSY_COUNT=$(swaymsg -t get_tree -r | jq '[.. | select(.type? == "output" and .name != "__i3") + | select([.. | select(.app_id? or .window_properties?) | .name] | length > 0) + | .name] | length') + +TOTAL_OUTPUTS=$(echo "$OUTPUTS" | wc -l) + +if [ "$BUSY_COUNT" -ge "$TOTAL_OUTPUTS" ]; then + exit 0 +fi + +OUT1=$(echo "$OUTPUTS" | sed -n '1p') +OUT2=$(echo "$OUTPUTS" | sed -n '2p') +CURRENT_WORKSPACE=$(swaymsg -t get_tree -r | jq -r ' + [ .nodes[] + | select(.type == "output" and .name != "__i3") + | .nodes[] # workspace...y + | select(.type == "workspace" and .name != "__i3_scratch") + | select(.. | select(.app_id? or .window_properties?) | length > 0) + | .name + ][0] +') + +CURRENT_OUTPUT=$(swaymsg -t get_workspaces -r | jq -r --arg ws "$CURRENT_WORKSPACE" '.[] | select(.name==$ws) | .output') + +if [ "$CURRENT_OUTPUT" = "$OUT1" ]; then + swaymsg workspace ${CURRENT_WORKSPACE}, move workspace to output "$OUT2" + swaymsg focus output "$OUT1" +else + swaymsg workspace ${CURRENT_WORKSPACE}, move workspace to output "$OUT1" +fi diff --git a/projects/ArchR/packages/apps/sdl2text/Makefile b/projects/ArchR/packages/apps/sdl2text/Makefile new file mode 100644 index 0000000000..1108d71a28 --- /dev/null +++ b/projects/ArchR/packages/apps/sdl2text/Makefile @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2025-present ArchR (https://github.com/archr-linux/Arch-R) + +CXX ?= gcc +CCFLAGS = -W -Wall -std=c++11 `sdl2-config --cflags` + +BINARY = sdl2text +LIBRARIES = -lSDL2 -lSDL2_ttf +SOURCES = "sdl2text.cpp" + +all: + $(CXX) $(CFLAGS) $(SOURCES) -o $(BINARY) $(LIBRARIES) + +clean: + rm -f $(BINARY) diff --git a/projects/ArchR/packages/apps/sdl2text/package.mk b/projects/ArchR/packages/apps/sdl2text/package.mk new file mode 100644 index 0000000000..f21ff781d7 --- /dev/null +++ b/projects/ArchR/packages/apps/sdl2text/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="sdl2text" +PKG_VERSION="v1.0" +PKG_LICENSE="GPLv2" +PKG_DEPENDS_TARGET="toolchain SDL2 SDL2_ttf" +PKG_LONGDESC="SDL2 text reader with gamepad controls" +PKG_TOOLCHAIN="make" + +pre_make_target() { + cp -f ${PKG_DIR}/Makefile ${PKG_BUILD} + cp -f ${PKG_DIR}/sdl2text.cpp ${PKG_BUILD} + CFLAGS+=" -I$(get_build_dir SDL2)/include -D_REENTRANT" +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp ${PKG_BUILD}/sdl2text ${INSTALL}/usr/bin + cp -rf ${PKG_DIR}/scripts/* ${INSTALL}/usr/bin + chmod 0755 ${INSTALL}/usr/bin/* +} diff --git a/projects/ArchR/packages/apps/sdl2text/scripts/game-guides-tool b/projects/ArchR/packages/apps/sdl2text/scripts/game-guides-tool new file mode 100644 index 0000000000..2ee09aba8d --- /dev/null +++ b/projects/ArchR/packages/apps/sdl2text/scripts/game-guides-tool @@ -0,0 +1,33 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2025-present ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile + +if [ -n "${1}" ]; then + # Make sure sdl2text dir exists + if [ ! -d "/storage/.config/sdl2text" ]; then + mkdir -p "/storage/.config/sdl2text" + fi + + # Check if guide exists for this game and output to temp path + GAME_GUIDE_CHECK="${1%.*}.txt" + + if [ -f "${GAME_GUIDE_CHECK}" ]; then +cat </storage/.config/sdl2text/game_guide.path +${GAME_GUIDE_CHECK} +EOF + else + rm -r "/storage/.config/sdl2text/game_guide.path" + fi +else + # Show game guide if exists + if [ -f "/storage/.config/sdl2text/game_guide.path" ]; then + export LD_PRELOAD=/usr/lib/compat/libSDL2-2.0.so.0 + GAME_GUIDE_PATH="$(cat /storage/.config/sdl2text/game_guide.path)" + /usr/bin/sdl2text "${GAME_GUIDE_PATH}" + else + exit 1 + fi +fi diff --git a/projects/ArchR/packages/apps/sdl2text/sdl2text.cpp b/projects/ArchR/packages/apps/sdl2text/sdl2text.cpp new file mode 100644 index 0000000000..de312d5eb5 --- /dev/null +++ b/projects/ArchR/packages/apps/sdl2text/sdl2text.cpp @@ -0,0 +1,489 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2025-present ArchR (https://github.com/archr-linux/Arch-R) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// -------------------- Config Helpers -------------------- +std::filesystem::path get_config_file() { + std::filesystem::path cfgDir = std::filesystem::path(std::getenv("HOME")) / ".config" / "sdl2text"; + std::filesystem::create_directories(cfgDir); + return cfgDir / "sdl2text.conf"; +} + +struct FileConfig { int scroll = 0; int fontSize = 40; }; // default font size 40 + +std::map load_config() { + std::map cfg; + std::ifstream f(get_config_file()); + if(!f.is_open()) return cfg; + std::string line; + while(std::getline(f,line)) { + size_t sep = line.find('='); + if(sep != std::string::npos) { + std::string key = line.substr(0,sep); + std::string val = line.substr(sep+1); + size_t comma = val.find(','); + int scroll = 0; + int font = 40; + if(comma != std::string::npos) { + try { + scroll = std::stoi(val.substr(0,comma)); + font = std::stoi(val.substr(comma+1)); + } catch(...) { } + } + cfg[key] = {scroll,font}; + } + } + return cfg; +} + +void save_config(const std::map& cfg) { + std::ofstream f(get_config_file()); + if(!f.is_open()) return; + for(const auto& [k,v]: cfg) { + f << k << "=" << v.scroll << "," << v.fontSize << "\n"; + } +} + +// -------------------- File & Font Helpers -------------------- +std::vector load_file_lines(const std::string& path) { + std::vector lines; + std::ifstream file(path); + std::string line; + while (std::getline(file, line)) lines.push_back(line); + return lines; +} + +std::string find_any_ttf_font() { + const char* dirs[] = { + "/usr/share/fonts/truetype/", + "/usr/share/fonts/truetype/dejavu/", + "/usr/share/fonts/", + "/usr/local/share/fonts/", + "/system/fonts/" + }; + for (auto dir : dirs) { + DIR* d = opendir(dir); + if (!d) continue; + struct dirent* ent; + while ((ent = readdir(d)) != nullptr) { + std::string name = ent->d_name; + if (name.size() > 4 && name.substr(name.size()-4) == ".ttf") { + closedir(d); + return std::string(dir) + name; + } + } + closedir(d); + } + return ""; +} + +// -------------------- UTF-8 safe filtering -------------------- +static bool font_can_render_codepoint(TTF_Font* font, uint32_t cp) { + if (cp <= 0xFFFF) return TTF_GlyphIsProvided(font, static_cast(cp)) != 0; + return false; +} + +std::string filter_invalid_chars(const std::string& s, TTF_Font* font) { + std::string out; + size_t i = 0; + while (i < s.size()) { + unsigned char c = static_cast(s[i]); + if (c < 0x80) { if (font_can_render_codepoint(font, c)) out.push_back(static_cast(c)); ++i; continue; } + uint32_t cp = 0; size_t seqLen = 0; + + if ((c & 0xE0) == 0xC0) { if (i+1 >= s.size()) { ++i; continue; } unsigned char c1 = s[i+1]; if ((c1 & 0xC0) != 0x80) { ++i; continue; } cp = ((c & 0x1F)<<6)|(c1&0x3F); seqLen=2; if(cp<0x80){i+=2;continue;} } + else if ((c & 0xF0) == 0xE0) { if(i+2>=s.size()){++i;continue;} unsigned char c1=s[i+1],c2=s[i+2]; if((c1&0xC0)!=0x80||(c2&0xC0)!=0x80){++i;continue;} cp=((c&0x0F)<<12)|((c1&0x3F)<<6)|(c2&0x3F); seqLen=3; } + else if ((c & 0xF8) == 0xF0) { if(i+3>=s.size()){++i;continue;} unsigned char c1=s[i+1],c2=s[i+2],c3=s[i+3]; if((c1&0xC0)!=0x80||(c2&0xC0)!=0x80||(c3&0xC0)!=0x80){++i;continue;} cp=((c&0x07)<<18)|((c1&0x3F)<<12)|((c2&0x3F)<<6)|(c3&0x3F); seqLen=4; } + else { ++i; continue; } + + if(seqLen==0){++i;continue;} + if(font_can_render_codepoint(font,cp)) out.append(s.substr(i,seqLen)); + i+=seqLen; + } + return out; +} + +// -------------------- Line wrapping -------------------- +std::vector wrap_line(const std::string& line, TTF_Font* font, int maxWidth) { + std::vector result; + size_t start=0,len=line.length(); + while(startmaxWidth) hi=mid-1; + else { best=mid; lo=mid+1; } + } + std::string chunk=line.substr(start,best); + if(chunk.empty()) chunk=line.substr(start,1); + result.push_back(chunk); + start+=chunk.length(); + } + return result; +} + +// -------------------- Pre-render textures -------------------- +struct LineTexture { SDL_Texture* tex; int w,h; }; + +std::vector create_textures(SDL_Renderer* ren, TTF_Font* font, const std::vector& wrapped, SDL_Color color) { + std::vector textures; + for(auto &line:wrapped) { + // Handle empty lines + if(line.empty()) { + int lineHeight = TTF_FontHeight(font); + textures.push_back({nullptr, 0, lineHeight}); + continue; + } + + SDL_Surface* surf=TTF_RenderUTF8_Blended(font,line.c_str(),color); + if(!surf) { + // If render fails, still add a placeholder for the line height + int lineHeight = TTF_FontHeight(font); + textures.push_back({nullptr, 0, lineHeight}); + continue; + } + + SDL_Texture* tex=SDL_CreateTextureFromSurface(ren,surf); + textures.push_back({tex,surf->w,surf->h}); + SDL_FreeSurface(surf); + } + return textures; +} + +// -------------------- Main -------------------- +int main(int argc,char* argv[]) { + if(argc<2) { std::cout << "Usage: " << argv[0] << " \n"; return 1; } + { + std::filesystem::path cfgDir = + std::filesystem::path(std::getenv("HOME")) / ".config" / "sdl2text"; + std::filesystem::create_directories(cfgDir); + } + + std::filesystem::path textFilePath=std::filesystem::absolute(argv[1]); + std::string textFile=textFilePath.string(); + auto lines=load_file_lines(textFile); + if(lines.empty()) { std::cout << "Failed to load file\n"; return 1; } + + if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_GAMECONTROLLER)!=0) { std::cerr << "SDL_Init error\n"; return 1; } + if(TTF_Init()!=0) { std::cerr << "TTF_Init error\n"; SDL_Quit(); return 1; } + + std::string fontPath=find_any_ttf_font(); + if(fontPath.empty()) { std::cout<<"No TTF font found\n"; TTF_Quit(); SDL_Quit(); return 1; } + + auto cfg=load_config(); + FileConfig fcfg=cfg[textFile]; + int fontSize=fcfg.fontSize; + auto loadFont=[&](int size)->TTF_Font* { TTF_Font* f=TTF_OpenFont(fontPath.c_str(),size); if(!f) std::cout<<"Failed to load font size "< wrapped; + for(auto &line:lines) { + if(line.empty()) { + // Preserve empty lines + wrapped.push_back(""); + } else { + std::string clean=filter_invalid_chars(line,font); + auto chunks=wrap_line(clean,font,WINDOW_W-20); + wrapped.insert(wrapped.end(),chunks.begin(),chunks.end()); + } + } + auto textures=create_textures(ren,font,wrapped,white); + + bool upPressed=false,downPressed=false,l1Pressed=false,r1Pressed=false,startPressed=false; + // Analog joystick axis state (left stick Y and right stick Y) + int16_t axisLeftY=0, axisRightY=0; + const int16_t AXIS_DEADZONE=8000; + const float AXIS_SCROLL_SCALE=0.002f; // pixels per frame at full deflection + + bool running=true,showHelp=false; + SDL_Event e; + bool touchActive=false; + float lastTouchY=0.0f; + const float TOUCH_MULTIPLIER=1.75f; + SDL_Color helpColor={255,255,255,255}, boxColor={0,0,0,200}; + + while(running) { + while(SDL_PollEvent(&e)) { + if(e.type==SDL_QUIT) { running=false; break; } + + if(e.type==SDL_CONTROLLERAXISMOTION) { + if(e.caxis.axis==SDL_CONTROLLER_AXIS_LEFTY) axisLeftY = e.caxis.value; + if(e.caxis.axis==SDL_CONTROLLER_AXIS_RIGHTY) axisRightY = e.caxis.value; + } + + if(e.type==SDL_CONTROLLERBUTTONDOWN) { + switch(e.cbutton.button) { + case SDL_CONTROLLER_BUTTON_DPAD_UP: upPressed=true; break; + case SDL_CONTROLLER_BUTTON_DPAD_DOWN: downPressed=true; break; + case SDL_CONTROLLER_BUTTON_LEFTSHOULDER: l1Pressed=true; break; + case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER: r1Pressed=true; break; + case SDL_CONTROLLER_BUTTON_START: startPressed=true; break; + case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: + fontSize+=2; TTF_CloseFont(font); font=loadFont(fontSize); if(!font){fontSize-=2; font=loadFont(fontSize);} + // Re-wrap with new font size, preserving empty lines + wrapped.clear(); + for(auto &line:lines) { + if(line.empty()) { + wrapped.push_back(""); + } else { + std::string clean=filter_invalid_chars(line,font); + auto chunks=wrap_line(clean,font,WINDOW_W-20); + wrapped.insert(wrapped.end(),chunks.begin(),chunks.end()); + } + } + for(auto <:textures) if(lt.tex) SDL_DestroyTexture(lt.tex); + textures=create_textures(ren,font,wrapped,white); + lineHeight=TTF_FontHeight(font); + break; + case SDL_CONTROLLER_BUTTON_DPAD_LEFT: + fontSize-=2; if(fontSize<8) fontSize=8; TTF_CloseFont(font); font=loadFont(fontSize); if(!font){fontSize+=2; font=loadFont(fontSize);} + // Re-wrap with new font size, preserving empty lines + wrapped.clear(); + for(auto &line:lines) { + if(line.empty()) { + wrapped.push_back(""); + } else { + std::string clean=filter_invalid_chars(line,font); + auto chunks=wrap_line(clean,font,WINDOW_W-20); + wrapped.insert(wrapped.end(),chunks.begin(),chunks.end()); + } + } + for(auto <:textures) if(lt.tex) SDL_DestroyTexture(lt.tex); + textures=create_textures(ren,font,wrapped,white); + lineHeight=TTF_FontHeight(font); + break; + case SDL_CONTROLLER_BUTTON_A: running=false; break; + case SDL_CONTROLLER_BUTTON_B: running=false; break; + case SDL_CONTROLLER_BUTTON_BACK: showHelp=!showHelp; break; + } + } + + if(e.type==SDL_CONTROLLERBUTTONUP) { + switch(e.cbutton.button) { + case SDL_CONTROLLER_BUTTON_DPAD_UP: upPressed=false; break; + case SDL_CONTROLLER_BUTTON_DPAD_DOWN: downPressed=false; break; + case SDL_CONTROLLER_BUTTON_LEFTSHOULDER: l1Pressed=false; break; + case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER: r1Pressed=false; break; + case SDL_CONTROLLER_BUTTON_START: startPressed=false; break; + } + } + + if(e.type==SDL_FINGERDOWN) { touchActive=true; lastTouchY=e.tfinger.y; } + if(e.type==SDL_FINGERMOTION && touchActive) { float y=e.tfinger.y; float dy_norm=y-lastTouchY; lastTouchY=y; scroll_y+=(int)(-dy_norm*WINDOW_H*TOUCH_MULTIPLIER); } + if(e.type==SDL_FINGERUP) touchActive=false; + } + + // D-pad continuous scrolling + if(upPressed) scroll_y-=SCROLL_SPEED; + if(downPressed) scroll_y+=SCROLL_SPEED; + if(l1Pressed) scroll_y-=SKIP_LINES*lineHeight; + if(r1Pressed) scroll_y+=SKIP_LINES*lineHeight; + + // Analog joystick scrolling (left stick or right stick, whichever is deflected) + // Apply deadzone, then scale linearly to scroll pixels + auto applyAxis = [&](int16_t raw) { + if(raw > AXIS_DEADZONE) + scroll_y += (int)((raw - AXIS_DEADZONE) * AXIS_SCROLL_SCALE); + else if(raw < -AXIS_DEADZONE) + scroll_y += (int)((raw + AXIS_DEADZONE) * AXIS_SCROLL_SCALE); + }; + applyAxis(axisLeftY); + applyAxis(axisRightY); + + // Secret kill combo: L1 + START + SELECT + if(l1Pressed && startPressed && SDL_GameControllerGetButton(pad, SDL_CONTROLLER_BUTTON_BACK)) running=false; + + // Clamp + int total_height=0; + for(const auto& tex : textures) total_height += tex.h; + if(total_heighttotal_height-WINDOW_H) scroll_y=total_height-WINDOW_H; + + // Render + SDL_SetRenderDrawColor(ren,0,0,0,255); SDL_RenderClear(ren); + + // Find starting line based on scroll position + int firstLine=0; + int accumulatedHeight=0; + for(size_t i=0;i scroll_y) { + firstLine=i; + break; + } + accumulatedHeight += textures[i].h; + } + + int offsetY = - (scroll_y - accumulatedHeight); + + for(size_t i=firstLine;i helpLines={ + "CONTROLS:", + "SELECT - Toggle Help Screen", + "STICK UP/DOWN - Scroll Up / Down", + "DPAD UP/DOWN - Scroll Up / Down", + "L1/R1 - Skip Up / Down", + "DPAD LEFT/RIGHT - + / - Text Size", + "TOUCHSCREEN - Scroll Up / Down", + "A / B - Exit" + }; + + // Calculate box height based on content + int lineHeight=TTF_FontLineSkip(font); // Get typical line height + int boxH=40+(helpLines.size()*(lineHeight+8)); // Top margin + all lines with spacing + int boxW=WINDOW_W/2; + int boxX=(WINDOW_W-boxW)/2, boxY=(WINDOW_H-boxH)/2; + + SDL_Rect helpBox={boxX,boxY,boxW,boxH}; + SDL_SetRenderDrawBlendMode(ren, SDL_BLENDMODE_BLEND); + SDL_SetRenderDrawColor(ren, boxColor.r, boxColor.g, boxColor.b, boxColor.a); + SDL_RenderFillRect(ren,&helpBox); + + int ty=boxY+20; + int columnSplit=375; + + for(auto &line:helpLines) { + size_t dashPos=line.find(" - "); + if(dashPos!=std::string::npos) { + std::string leftPart=line.substr(0,dashPos); + std::string rightPart=line.substr(dashPos); + + SDL_Surface* surf1=TTF_RenderUTF8_Blended(font,leftPart.c_str(),helpColor); + if(surf1) { + SDL_Texture* tex1=SDL_CreateTextureFromSurface(ren,surf1); + SDL_Rect dst1={boxX+20,ty,surf1->w,surf1->h}; + SDL_RenderCopy(ren,tex1,nullptr,&dst1); + int lineHeight=surf1->h; + SDL_DestroyTexture(tex1); + SDL_FreeSurface(surf1); + + SDL_Surface* surf2=TTF_RenderUTF8_Blended(font,rightPart.c_str(),helpColor); + if(surf2) { + SDL_Texture* tex2=SDL_CreateTextureFromSurface(ren,surf2); + SDL_Rect dst2={boxX+20+columnSplit,ty,surf2->w,surf2->h}; + SDL_RenderCopy(ren,tex2,nullptr,&dst2); + SDL_DestroyTexture(tex2); + SDL_FreeSurface(surf2); + } + ty+=lineHeight+8; + } + } else { + SDL_Surface* surf=TTF_RenderUTF8_Blended(font,line.c_str(),helpColor); + if(surf) { + SDL_Texture* tex=SDL_CreateTextureFromSurface(ren,surf); + SDL_Rect dst={boxX+20,ty,surf->w,surf->h}; + SDL_RenderCopy(ren,tex,nullptr,&dst); + ty+=surf->h+8; + SDL_DestroyTexture(tex); + SDL_FreeSurface(surf); + } + } + } + } + + // ---- Line Counter (bottom-right) ---- + { + // Calculate current line number based on scroll position + int currentLine = 1; + int accumulatedHeight = 0; + for(size_t i=0;i scroll_y) { + currentLine = i + 1; + break; + } + accumulatedHeight += textures[i].h; + } + + int totalLines = (int)textures.size(); + + if (currentLine < 1) currentLine = 1; + if (currentLine > totalLines) currentLine = totalLines; + + std::string lcText = std::to_string(currentLine) + "/" + std::to_string(totalLines); + + SDL_Color lcColor = {255,255,255,255}; + + SDL_Surface* lcSurf = TTF_RenderUTF8_Blended(font, lcText.c_str(), lcColor); + if (lcSurf) { + SDL_Texture* lcTex = SDL_CreateTextureFromSurface(ren, lcSurf); + if (lcTex) { + SDL_Rect textRect; + textRect.w = lcSurf->w; + textRect.h = lcSurf->h; + textRect.x = WINDOW_W - textRect.w - 15; + textRect.y = WINDOW_H - textRect.h - 10; + + // transparent background box + SDL_Rect bgRect; + bgRect.x = textRect.x - 8; + bgRect.y = textRect.y - 4; + bgRect.w = textRect.w + 16; + bgRect.h = textRect.h + 8; + + SDL_SetRenderDrawBlendMode(ren, SDL_BLENDMODE_BLEND); + SDL_SetRenderDrawColor(ren, 0, 0, 0, 200); + SDL_RenderFillRect(ren, &bgRect); + + SDL_RenderCopy(ren, lcTex, nullptr, &textRect); + + SDL_DestroyTexture(lcTex); + } + SDL_FreeSurface(lcSurf); + } + } + + SDL_RenderPresent(ren); + SDL_Delay(16); + } + + // Save config + cfg[textFile]={scroll_y,fontSize}; + save_config(cfg); + + for(auto <:textures) if(lt.tex) SDL_DestroyTexture(lt.tex); + if(pad) SDL_GameControllerClose(pad); + if(font) TTF_CloseFont(font); + if(ren) SDL_DestroyRenderer(ren); + if(win) SDL_DestroyWindow(win); + TTF_Quit(); + SDL_Quit(); + return 0; +} diff --git a/projects/ArchR/packages/apps/sdljoytest/package.mk b/projects/ArchR/packages/apps/sdljoytest/package.mk new file mode 100644 index 0000000000..f6eb15778b --- /dev/null +++ b/projects/ArchR/packages/apps/sdljoytest/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="sdljoytest" +PKG_VERSION="811d9875e0c13e0c87d93351e69169bf74d28270" +PKG_LICENSE="OSS" +PKG_SITE="https://github.com/Wintermute0110/sdljoytest" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain SDL2" +PKG_LONGDESC="Test joystick with SDL2 in Linux" +PKG_TOOLCHAIN="make" + +pre_configure_target() { +sed -i "s|gcc|${CC}|" Makefile +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp -rf test_gamepad_SDL2 ${INSTALL}/usr/bin + ln -s test_gamepad_SDL2 ${INSTALL}/usr/bin/sdljoytest + cp -rf map_gamepad_SDL2 ${INSTALL}/usr/bin + ln -s map_gamepad_SDL2 ${INSTALL}/usr/bin/sdljoymap +} diff --git a/projects/ArchR/packages/apps/sdltouchtest/package.mk b/projects/ArchR/packages/apps/sdltouchtest/package.mk new file mode 100644 index 0000000000..f49e5114ed --- /dev/null +++ b/projects/ArchR/packages/apps/sdltouchtest/package.mk @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="sdltouchtest" +PKG_VERSION="b62dae0d6233869a4c70a9472bc1e93dec391f94" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/realchonk/sdl2-touch-test" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain SDL2" +PKG_LONGDESC="SDL2 touchscreen tester" +PKG_TOOLCHAIN="make" + +pre_configure_target() { + sed -i "s|gcc|${CC}|" Makefile +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp ${PKG_BUILD}/test ${INSTALL}/usr/bin/sdltouchtest + chmod 0755 ${INSTALL}/usr/bin/* + +case ${DEVICE} in + RK3399|RK35*|SM8250|SM8550|SDM845) + mkdir -p ${INSTALL}/usr/config/modules + cp -rf ${PKG_DIR}/scripts/* ${INSTALL}/usr/config/modules + chmod 0755 ${INSTALL}/usr/config/modules/* + ;; +esac +} diff --git a/projects/ArchR/packages/apps/sdltouchtest/patches/000-sdltouchtest.patch b/projects/ArchR/packages/apps/sdltouchtest/patches/000-sdltouchtest.patch new file mode 100644 index 0000000000..19f125800d --- /dev/null +++ b/projects/ArchR/packages/apps/sdltouchtest/patches/000-sdltouchtest.patch @@ -0,0 +1,264 @@ +diff --git a/test.c b/test.c +index 8ff9eb3..9ec3be2 100644 +--- a/test.c ++++ b/test.c +@@ -3,105 +3,164 @@ + #include + #include + +-#define stop_timer(tid) \ +-do { \ +- if (tid) { \ +- SDL_RemoveTimer (tid); \ +- tid = 0; \ +- } \ ++#define MAX_FINGERS 10 ++ ++// Stop timer macro definition ++#define stop_timer(tid) \ ++do { \ ++ if (tid) { \ ++ SDL_RemoveTimer(tid); \ ++ tid = 0; \ ++ } \ + } while (0) + +- +-static Uint32 cb_haptic (Uint32 interval, void *arg) { +- SDL_Haptic *haptic = arg; +- +- if (haptic) { +- SDL_HapticRumblePlay (haptic, 0.5f, 250); +- } ++// Define a custom structure to store finger information ++typedef struct { ++ int touchId; ++ float x, y; ++} Finger; ++ ++// Haptic callback function ++static Uint32 cb_haptic(Uint32 interval, void *arg) { ++ SDL_Haptic *haptic = arg; ++ if (haptic) { ++ SDL_HapticRumblePlay(haptic, 0.5f, 250); // Trigger a short rumble ++ } ++ return 0; // No need to repeat + } + +-int main (void) { +- SDL_Init (SDL_INIT_EVERYTHING); +- SDL_Window *window = SDL_CreateWindow ( +- "Test", +- SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, +- 720, 1440, +- SDL_WINDOW_SHOWN +- ); +- if (!window) +- return 1; +- +- SDL_Renderer *renderer = SDL_CreateRenderer (window, -1, SDL_RENDERER_ACCELERATED); +- if (!renderer) +- return 1; +- +- SDL_Haptic *haptic = SDL_HapticOpen (0); +- if (haptic) { +- SDL_HapticRumbleInit (haptic); +- } else { +- +- printf ("No haptic device found.\n"); +- } +- +- int ww, wh, num_fingers = 0; +- SDL_GetWindowSize (window, &ww, &wh); +- float x = 0.0f, y = 0.0f; +- float scale = 50.0f; +- SDL_TimerID timerID = 0; +- +- while (1) { +- SDL_Event e; +- while (SDL_PollEvent (&e)) { +- switch (e.type) { +- case SDL_QUIT: +- goto end; +- +- case SDL_MULTIGESTURE: +- if (e.mgesture.numFingers == 2) { +- stop_timer (timerID); +- scale *= 1.0f + e.mgesture.dDist * 5.0f; +- } +- /*printf ("touchId = %u\n", (unsigned)e.mgesture.touchId); +- printf ("dTheta = %f\n", e.mgesture.dTheta); +- printf ("dDist = %f\n", e.mgesture.dDist); +- printf ("x = %f\n", e.mgesture.x); +- printf ("y = %f\n", e.mgesture.y); +- printf ("num_fingers = %u\n", (unsigned)e.mgesture.numFingers);*/ +- break; +- case SDL_FINGERDOWN: +- if (!timerID && num_fingers == 0) +- timerID = SDL_AddTimer (500, &cb_haptic, haptic); +- +- ++num_fingers; +- break; +- case SDL_FINGERUP: +- stop_timer (timerID); +- --num_fingers; +- break; +- case SDL_FINGERMOTION: +- if (num_fingers == 1) { +- stop_timer (timerID); +- x += e.tfinger.dx; +- y += e.tfinger.dy; +- } +- break; +- } +- } +- SDL_SetRenderDrawColor (renderer, 255, 255, 255, 255); +- SDL_RenderClear (renderer); +- +- const SDL_Rect rect = { x * ww, y * wh, scale, scale }; +- SDL_SetRenderDrawColor (renderer, 0, 0, 0, 255); +- SDL_RenderFillRect (renderer, &rect); +- +- SDL_RenderPresent (renderer); +- } ++int main() { ++ if (SDL_Init(SDL_INIT_EVERYTHING) != 0) { ++ printf("SDL_Init Error: %s\n", SDL_GetError()); ++ return 1; ++ } ++ ++ // Get the current screen resolution ++ SDL_DisplayMode mode; ++ if (SDL_GetDesktopDisplayMode(0, &mode) != 0) { ++ printf("SDL_GetDesktopDisplayMode Error: %s\n", SDL_GetError()); ++ return 1; ++ } ++ int screen_width = mode.w; ++ int screen_height = mode.h; ++ ++ // Create a fullscreen window ++ SDL_Window *window = SDL_CreateWindow( ++ "Test", ++ SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, ++ screen_width, screen_height, ++ SDL_WINDOW_FULLSCREEN ++ ); ++ ++ if (!window) { ++ printf("SDL_CreateWindow Error: %s\n", SDL_GetError()); ++ return 1; ++ } ++ ++ // Create the renderer ++ SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); ++ if (!renderer) { ++ printf("SDL_CreateRenderer Error: %s\n", SDL_GetError()); ++ return 1; ++ } ++ ++ // Check for haptic support ++ SDL_Haptic *haptic = SDL_HapticOpen(0); ++ if (haptic) { ++ SDL_HapticRumbleInit(haptic); ++ } else { ++ printf("No haptic device found.\n"); ++ } ++ ++ // Initialize variables ++ int ww, wh, num_fingers = 0; ++ SDL_GetWindowSize(window, &ww, &wh); ++ float scale = 50.0f; ++ SDL_TimerID timerID = 0; ++ ++ // Store positions of active fingers (custom structure) ++ Finger fingers[MAX_FINGERS]; ++ for (int i = 0; i < MAX_FINGERS; ++i) { ++ fingers[i].touchId = -1; // Mark all touchIds as unused initially ++ } ++ ++ // Variables for tracking the position of the square ++ float square_x = 0.0f, square_y = 0.0f; // To track the movement of the square ++ ++ // Main loop ++ while (1) { ++ SDL_Event e; ++ while (SDL_PollEvent(&e)) { ++ switch (e.type) { ++ case SDL_QUIT: ++ goto end; ++ ++ case SDL_FINGERDOWN: ++ // Ensure that we don't exceed MAX_FINGERS ++ if (num_fingers < MAX_FINGERS) { ++ if (!timerID && num_fingers == 0) ++ timerID = SDL_AddTimer(500, &cb_haptic, haptic); ++ ++ // Find an empty slot for the new finger ++ for (int i = 0; i < MAX_FINGERS; ++i) { ++ if (fingers[i].touchId == -1) { ++ fingers[i].touchId = e.tfinger.touchId; ++ fingers[i].x = e.tfinger.x; ++ fingers[i].y = e.tfinger.y; ++ ++num_fingers; ++ break; ++ } ++ } ++ } ++ break; ++ ++ case SDL_FINGERUP: ++ stop_timer(timerID); ++ ++ // Remove the finger from tracking ++ for (int i = 0; i < MAX_FINGERS; ++i) { ++ if (fingers[i].touchId == e.tfinger.touchId) { ++ fingers[i].touchId = -1; ++ --num_fingers; ++ break; ++ } ++ } ++ break; ++ ++ case SDL_FINGERMOTION: ++ // Handle finger motion for moving the square ++ for (int i = 0; i < MAX_FINGERS; ++i) { ++ if (fingers[i].touchId == e.tfinger.touchId) { ++ // Update the square position based on this finger ++ square_x = e.tfinger.x * ww; // Convert normalized X to pixel ++ square_y = e.tfinger.y * wh; // Convert normalized Y to pixel ++ break; ++ } ++ } ++ break; ++ } ++ } ++ ++ // Render ++ SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); ++ SDL_RenderClear(renderer); ++ ++ // Calculate the new position and scale of the square ++ const SDL_Rect rect = {(int)(square_x - scale / 2), (int)(square_y - scale / 2), (int)(scale), (int)(scale)}; ++ SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); ++ SDL_RenderFillRect(renderer, &rect); ++ ++ SDL_RenderPresent(renderer); ++ } + + end: +- if (haptic) +- SDL_HapticClose (haptic); +- SDL_DestroyRenderer (renderer); +- SDL_DestroyWindow (window); +- SDL_Quit (); ++ // Cleanup ++ if (haptic) { ++ SDL_HapticClose(haptic); ++ } ++ SDL_DestroyRenderer(renderer); ++ SDL_DestroyWindow(window); ++ SDL_Quit(); ++ ++ return 0; + } +- diff --git a/projects/ArchR/packages/apps/sdltouchtest/scripts/Test Touchscreen.sh b/projects/ArchR/packages/apps/sdltouchtest/scripts/Test Touchscreen.sh new file mode 100644 index 0000000000..493bf5d5fe --- /dev/null +++ b/projects/ArchR/packages/apps/sdltouchtest/scripts/Test Touchscreen.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +source /etc/profile + +set_kill set "-9 sdltouchtest" + +/usr/bin/sdltouchtest diff --git a/projects/ArchR/packages/archr/autostart/001-setup b/projects/ArchR/packages/archr/autostart/001-setup new file mode 100755 index 0000000000..a33b74e984 --- /dev/null +++ b/projects/ArchR/packages/archr/autostart/001-setup @@ -0,0 +1,42 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +if [ -d "/storage/cache/.cores" ] +then + rm -rf /storage/cache/.cores +fi + +if [ ! -d "/tmp/cache" ] +then + mkdir -p /tmp/cache +fi + +ln -sf /tmp/cache /storage/cache/.cores + +if [ ! -d "/storage/.config/profile.d" ] +then + mkdir -p /storage/.config/profile.d +fi + +### Inspect the system config and revert +### to last known good state if corrupt. +/usr/bin/chksysconfig verify + +### Clean up settings +sort_settings + +### We do not want to mount the cloud drive on startup +### so we'll reset the mount option to 0. +set_setting clouddrive.mounted 0 + +### Set up the runtime directory. +if [ ! -d "/var/run/0-runtime-dir" ] +then + mkdir -p /var/run/0-runtime-dir +fi + +chmod 0700 /var/run/0-runtime-dir diff --git a/projects/ArchR/packages/archr/autostart/003-upgrade b/projects/ArchR/packages/archr/autostart/003-upgrade new file mode 100755 index 0000000000..5021e7c280 --- /dev/null +++ b/projects/ArchR/packages/archr/autostart/003-upgrade @@ -0,0 +1,18 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +if [ "$(cat /storage/.boot.hint 2>/dev/null)" = "UPDATE" ] +then + if [ -e "/usr/share/post-update" ] + then + tocon "Performing post-update configuration..." + /usr/share/post-update >/var/log/upgrade.log 2>&1 + fi + rm /storage/.boot.hint +else + echo "No update hint found." >/var/log/upgrade.log 2>&1 +fi diff --git a/projects/ArchR/packages/archr/autostart/006-display b/projects/ArchR/packages/archr/autostart/006-display new file mode 100755 index 0000000000..339d96d19b --- /dev/null +++ b/projects/ArchR/packages/archr/autostart/006-display @@ -0,0 +1,29 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-24 JELOS (https://github.com/JustEnoughLinuxOS) +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +tocon "Configuring display..." + +BRIGHTNESS_1=$(get_setting display.brightness) +DEFAULT_BRIGHTNESS="10" +MIN_BRIGHTNESS="5" + +if [ -z "${BRIGHTNESS_1}" ] || [ "${BRIGHTNESS_1}" -lt "${MIN_BRIGHTNESS}" ]; then + BRIGHTNESS_1="${DEFAULT_BRIGHTNESS}" +fi + +brightness set "${BRIGHTNESS_1}" + +BRIGHTNESS_2=$(get_setting display.brightness2) + +if [ -n "${BRIGHTNESS_2}" ]; then + if [ "${BRIGHTNESS_2}" -lt "${MIN_BRIGHTNESS}" ]; then + BRIGHTNESS_2="${DEFAULT_BRIGHTNESS}" + fi + + brightness set 2 "${BRIGHTNESS_2}" +fi diff --git a/projects/ArchR/packages/archr/autostart/007-rootpw b/projects/ArchR/packages/archr/autostart/007-rootpw new file mode 100755 index 0000000000..7dea564e5c --- /dev/null +++ b/projects/ArchR/packages/archr/autostart/007-rootpw @@ -0,0 +1,17 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +tocon "Setting root password..." + +if [ ! -d "/storage/.cache/samba" ] +then + mkdir -p /storage/.cache/samba + touch /storage/.cache/samba/smbpasswd +fi + +ROOTPASS=$(get_setting root.password) +setrootpass "${ROOTPASS}" diff --git a/projects/ArchR/packages/archr/autostart/008-perfmode b/projects/ArchR/packages/archr/autostart/008-perfmode new file mode 100755 index 0000000000..5b1cab804e --- /dev/null +++ b/projects/ArchR/packages/archr/autostart/008-perfmode @@ -0,0 +1,37 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-24 JELOS (https://github.com/JustEnoughLinuxOS) +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions +. /etc/profile.d/099-freqfunctions + +tocon "Setting performance mode..." + +### Enable the desired number of threads. +tocon "Restoring cpu threads..." +NUMTHREADS=$(get_setting "system.threads") +if [ -n "${NUMTHREADS}" ]; then + onlinethreads ${NUMTHREADS} 0 +else + onlinethreads all 1 +fi + +### If we don't have a default governor set, set it +### to ondemand if the device supports it, otherwise +### set to performance, but don't enable it. +if [ -z "$(get_setting system.cpugovernor)" ]; then + GOVTEST="$(awk '/ondemand/ {print $1}' /sys/devices/system/cpu/cpufreq/policy0/scaling_available_governors)" + if [ -n "${GOVTEST}" ]; then + set_setting system.cpugovernor ondemand + else + set_setting system.cpugovernor performance + fi +fi + +### Set the default GPU performance mode +GPUPERF=$(get_setting system.gpuperf) +if [ -n "${GPUPERF}" ]; then + gpu_performance_level ${GPUPERF} +fi diff --git a/projects/ArchR/packages/archr/autostart/009-sleepmode b/projects/ArchR/packages/archr/autostart/009-sleepmode new file mode 100755 index 0000000000..74482f941c --- /dev/null +++ b/projects/ArchR/packages/archr/autostart/009-sleepmode @@ -0,0 +1,17 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +tocon "Configure suspend mode..." + +### Configure suspend mode. +MYSLEEPMODE=$(get_setting system.suspendmode) +if [ -n "${MYSLEEPMODE}" ] +then + /usr/bin/suspendmode ${MYSLEEPMODE} +else + /usr/bin/suspendmode mem +fi diff --git a/projects/ArchR/packages/archr/autostart/010-uimode b/projects/ArchR/packages/archr/autostart/010-uimode new file mode 100755 index 0000000000..9e9187d676 --- /dev/null +++ b/projects/ArchR/packages/archr/autostart/010-uimode @@ -0,0 +1,26 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +tocon "Configuring user interface..." + +UIMODE=$(get_setting desktop.enabled) +if [ "${UIMODE}" = "1" ] || \ + [ ! -e "/usr/bin/emulationstation" ] +then + cp -f /usr/share/weston/weston.ini /storage/.config/weston.ini +else + cp -f /usr/share/weston/kiosk.ini /storage/.config/weston.ini +fi + +STARTUP=$(get_setting weston.startup) +if [ -z "${STARTUP}" ] && \ + [ -e "/usr/bin/emulationstation" ] +then + STARTUP="/usr/bin/start_es.sh" + set_setting weston.startup "${STARTUP}" +fi +sed -i "s#@STARTUP@#${STARTUP}#g" /storage/.config/weston.ini diff --git a/projects/ArchR/packages/archr/autostart/050-audio b/projects/ArchR/packages/archr/autostart/050-audio new file mode 100755 index 0000000000..48c94cd3f5 --- /dev/null +++ b/projects/ArchR/packages/archr/autostart/050-audio @@ -0,0 +1,51 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +tocon "Configuring Audio..." + +STATE=$(systemctl is-active pipewire-pulse) +if [ "${STATE}" = "inactive" ] +then + systemctl start pipewire-pulse +fi + +### Auto switch between internal and bluetooth devices +pactl load-module module-switch-on-connect blocklist="DirtyWave_M8|hdmi" 2>/dev/null + +### Set up audio routing (Internal or HDMI) +/usr/bin/hdmi_sense 2>/dev/null + +### Set the default audio path, needed for some devices +if [ ! -z "${DEVICE_PLAYBACK_PATH_SPK}" ] +then + if [ -z "${DEVICE_PLAYBACK_PATH}" ] + then + export DEVICE_PLAYBACK_PATH="Playback Path" + fi + amixer -c ${ALSA_PRIMARY_CARD:-0} cset name="${DEVICE_PLAYBACK_PATH}" ${DEVICE_PLAYBACK_PATH_SPK} 2>/dev/null +fi + +VOLUME=$(get_setting audio.volume) +if [ -z ${VOLUME} ] +then + VOLUME="60" +elif [ -n "${DEVICE_VOLUME}" ] +then + VOLUME="${DEVICE_VOLUME}" +fi + +### Set the primary card volume to 100% +### to eliminate low audio on some devices. + amixer -c ${ALSA_PRIMARY_CARD:-0} -q sset "Master" 100% + +### Now set the pipewire mixer volume +/usr/bin/volume ${VOLUME} + +### Run quantum audio hack if exists +if [ -n "/usr/sbin/quantum" ]; then + /usr/sbin/quantum +fi diff --git a/projects/ArchR/packages/archr/autostart/055-hdmi-check b/projects/ArchR/packages/archr/autostart/055-hdmi-check new file mode 100755 index 0000000000..788716dc4d --- /dev/null +++ b/projects/ArchR/packages/archr/autostart/055-hdmi-check @@ -0,0 +1,36 @@ +#!/bin/bash +# SPDX-License-Identifier: MIT +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) +# Copyright (C) 2023-present christianhaitian (https://github.com/christianhaitian) +# Copyright (C) 2023-present Rocky5 (https://github.com/rocky5) + +# The purpose of this script is to permanently set the resolution +# output for hdmi when connected. + +# /sys/class/graphics/fb0/modes may not be populated yet if DRM is still +# probing. Default to 0 so the comparison below falls through cleanly +# instead of breaking arithmetic. +xres="$(cat /sys/class/graphics/fb0/modes 2>/dev/null | grep -o -P '(?<=:).*(?=p-)' | cut -dx -f1)" +[ -z "${xres}" ] && xres=0 + +# drm_tool source available at https://github.com/christianhaitian/drm_tool.git +# Wrap with a timeout: drm_tool can block on the DRM master if +# rockchipdrm is still binding, which on a slow microSD has been +# observed to hang this autostart script and (via Before=emustation) +# the entire boot. +mode="$(timeout 10 /usr/bin/drm_tool list 2>/dev/null | awk '/1280x720.*60/ {print substr($2,1,length($2)-1); exit}')" +mode2="$(timeout 10 /usr/bin/drm_tool list 2>/dev/null | awk '/1920x1080.*60/ {print substr($2,1,length($2)-1); exit}')" + +# Now we tell drm what the hdmi mode is by writing to /var/run/drmMode +# This will get picked up by SDL2 as long as it's been patched with the batocera +# drm resolution patch. This patch can be found at +# https://github.com/christianhaitian/rk3566_core_builds/raw/master/patches/sdl2-patch-0003-drm-resolution.patch + +if [ $xres -eq "1280" ]; then + echo $mode | tee /var/run/drmMode +elif [ $xres -eq "1920" ]; then + echo $mode2 | tee /var/run/drmConn +else + echo 0 | tee /var/run/drmMode + echo 1 | tee /var/run/drmConn +fi diff --git a/projects/ArchR/packages/archr/autostart/081-usbgadget b/projects/ArchR/packages/archr/autostart/081-usbgadget new file mode 100755 index 0000000000..3943419f94 --- /dev/null +++ b/projects/ArchR/packages/archr/autostart/081-usbgadget @@ -0,0 +1,5 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +/usr/bin/usbgadget --start diff --git a/projects/ArchR/packages/archr/autostart/099-networkservices b/projects/ArchR/packages/archr/autostart/099-networkservices new file mode 100755 index 0000000000..7b605c6496 --- /dev/null +++ b/projects/ArchR/packages/archr/autostart/099-networkservices @@ -0,0 +1,42 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +tocon "Starting services..." + +for SERVICE in /usr/lib/autostart/daemons/* +do + source ${SERVICE} + + + if [ ! -d "/storage/.cache/services" ] + then + mkdir -p "/storage/.cache/services" + fi + + if [ -n "${CONF}" ] && \ + [ -e "/storage/.cache/services/${CONF}" ] + then + rm -f "/storage/.cache/services/${CONF}" + fi + + statemgr() { + for daemon in ${DAEMONS[@]} + do + nohup systemctl ${1} ${daemon} & + done + } + + case "$STATE" in + "1") + touch "/storage/.cache/services/${CONF}" + statemgr start + ;; + *) + statemgr stop + ;; + esac +done diff --git a/projects/ArchR/packages/archr/config/system/configs/system.cfg b/projects/ArchR/packages/archr/config/system/configs/system.cfg new file mode 100644 index 0000000000..e105093a6b --- /dev/null +++ b/projects/ArchR/packages/archr/config/system/configs/system.cfg @@ -0,0 +1,220 @@ +3do.integerscale=0 +3do.ratio=4/3 +advmame_auto_gamepad=0 +amigacd32.integerscale=0 +amigacd32.ratio=4/3 +amiga.integerscale=0 +amiga.ratio=4/3 +amstradcpc.integerscale=0 +arcade.autosave=0 +atari2600.integerscale=0 +atari5200.integerscale=0 +atari7800.integerscale=0 +atari800.integerscale=0 +atarilynx.integerscale=0 +atarilynx.ratio=core +atarist.integerscale=0 +atomiswave.integerscale=0 +atomiswave.ratio=4/3 +audio.bgmusic=1 +audio.device=headphone +audio.display_titles=1 +audio.persystem=0 +audio.preamp=50 +audio.volume=60 +boot=Emulationstation +c128.integerscale=0 +c16.integerscale=0 +c64.integerscale=0 +cdi.integerscale=0 +cdi.ratio=4/3 +chip-8.integerscale=0 +cloud.backup=0 +colecovision.integerscale=0 +colecovision.ratio=4/3 +controllers.bluetooth.enabled=0 +cooling.profile=quiet +cps1.integerscale=0 +cps2.integerscale=0 +cps3.integerscale=0 +daphne.integerscale=0 +daphne.ratio=4/3 +desktop.enabled=0 +display.brightness=50 +display.contrast=50 +display.hue=50 +display.saturation=50 +dreamcast.integerscale=0 +dreamcast.ratio=4/3 +easyrpg.integerscale=0 +famicom.integerscale=0 +famicom.ratio=4/3 +fbn.integerscale=0 +fbn.ratio=core +fds.integerscale=0 +fds.ratio=4/3 +fstrim.enabled=0 +gamegear.integerscale=0 +gbah.ratio=3/2 +gba.ratio=3/2 +gbch.integerscale=0 +gbc.integerscale=0 +gbh.integerscale=0 +gb.integerscale=0 +genesis.integerscale=0 +genesis.ratio=4/3 +genh.integerscale=0 +genh.ratio=4/3 +ggh.integerscale=0 +global.analogue=1 +global.autosave=1 +global.bezel=thebezelproject +global.savestates=1 +global.incrementalsavestates=0 +global.netplay=0 +global.netplay.port=55435 +global.netplay.relay=none +global.ratio=core +global.retroachievements=0 +global.retroachievements.challengeindicators=0 +global.retroachievements.hardcore=0 +global.retroachievements.leaderboards=disabled +global.retroachievements.password= +global.retroachievements.richpresence=0 +global.retroachievements.screenshot=0 +global.retroachievements.soundenable=0 +global.retroachievements.testunofficial=0 +global.retroachievements.username= +global.retroachievements.verbose=0 +global.retroarch.menu_driver=ozone +global.rewind=0 +global.runahead=0 +global.secondinstance=0 +intellivision.integerscale=0 +intellivision.ratio=4/3 +mame.autosave=0 +mame.integerscale=0 +mastersystem.integerscale=0 +megacd.integerscale=0 +megacd.ratio=4/3 +megadrive.integerscale=0 +megadrive-japan.integerscale=0 +megadrive-japan.ratio=4/3 +megadrive.ratio=4/3 +megaduck.integerscale=0 +moto.integerscale=0 +moto.ratio=4/3 +msx2.integerscale=0 +msx2.ratio=4/3 +msx.integerscale=0 +msx.ratio=4/3 +mu.integerscale=0 +n64.controller_pak=2 +n64.game_aspect_ratio=4:3 +n64.input_configuration=zlswap +n64.integerscale=0 +n64.internal_resolution=1 +n64.parallel_n64_gamespeed=fullspeed +n64.parallel_n64_gfx_accuracy=medium +n64.parallel_n64_internal_resolution=480p +n64.parallel_n64_video_core=glide64 +n64.ratio=4/3 +n64.rsp_plugin=hle +n64.show_fps=0 +naomi.integerscale=0 +naomi.ratio=4/3 +neocd.integerscale=0 +neocd.ratio=core +neogeo.integerscale=0 +neogeo.ratio=core +nesh.integerscale=0 +nesh.ratio=4/3 +nes.integerscale=0 +nes.ratio=4/3 +ngpc.intergerscale=1 +ngp.integerscale=0 +odyssey2.integerscale=0 +odyssey2.ratio=4/3 +pc-9800.integerscale=0 +pc-9800.ratio=4/3 +pcenginecd.integerscale=0 +pcenginecd.ratio=4/3 +pcengine.integerscale=0 +pcengine.ratio=4/3 +pcfx.integerscale=0 +pcfx.ratio=4/3 +pc.integerscale=0 +pc.ratio=4/3 +pet.ratio=4/3 +pokemini.ratio=3/2 +psx.integerscale=0 +psx.ratio=4/3 +root.password=archr +samba.enabled=0 +saturn.integerscale=0 +saturn.ratio=4/3 +scv.integerscale=0 +scv.ratio=4/3 +sega32x.integerscale=0 +sega32x.ratio=4/3 +segacd.integerscale=0 +segacd.ratio=4/3 +sfc.integerscale=0 +sfc.ratio=4/3 +sg-1000.integerscale=0 +simplehttp.enabled=0 +snesh.integerscale=0 +snesh.ratio=4/3 +snes.integerscale=0 +snesmsu1.integerscale=0 +snesmsu1.ratio=4/3 +snes.ratio=4/3 +splash.enabled=0 +ssh.enabled=0 +supergrafx.integerscale=0 +supergrafx.ratio=4/3 +supervision.integerscale=0 +syncthing.enabled=0 +system.autohotkeys=1 +system.automount=1 +system.battery.warning=0 +system.battery.warning_threshold=25 +system.hostname=@DEVICENAME@ +system.language=en_US +enable.turbo-mode=0 +system.cpugovernor=ondemand +system.loglevel=none +system.merged.storage=0 +system.shutdown_delay=900 +system.shutdown_delay_running_game=900 +system.suspend.park_cores=1 +system.suspend.dpms=1 +system.timezone=America/Sao_Paulo +tg16cd.integerscale=0 +tg16cd.ratio=4/3 +tg16.integerscale=0 +tg16.ratio=4/3 +updates.branch=auto +updates.enabled=1 +updates.force=0 +uzebox.integerscale=0 +uzebox.integerscale=0 +vectrex.integerscale=0 +vectrex.ratio=3/4 +vic20.integerscale=0 +vic20.ratio=4/3 +videopac.integerscale=0 +videopac.ratio=4/3 +vircon32.integerscale=0 +virtualboy.integerscale=0 +weston.startup=/usr/bin/start_es.sh +wifi.enabled=0 +wonderswancolor.integerscale=0 +wonderswan.integerscale=0 +wts.enabled=1 +x68000.integerscale=0 +x68000.ratio=4/3 +zx81.integerscale=0 +zx81.ratio=4/3 +zxspectrum.integerscale=0 +zxspectrum.ratio=4/3 diff --git a/projects/ArchR/packages/archr/config/system/configs/tz b/projects/ArchR/packages/archr/config/system/configs/tz new file mode 100644 index 0000000000..fe39d982cc --- /dev/null +++ b/projects/ArchR/packages/archr/config/system/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/projects/ArchR/packages/archr/package.mk b/projects/ArchR/packages/archr/package.mk new file mode 100644 index 0000000000..0f6c3e3de5 --- /dev/null +++ b/projects/ArchR/packages/archr/package.mk @@ -0,0 +1,95 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) +# Copyright (C) 2024-present Arch R + +PKG_NAME="archr" +PKG_VERSION="" +PKG_LICENSE="GPLv2" +PKG_SITE="" +PKG_URL="" +PKG_DEPENDS_TARGET="toolchain autostart" +PKG_LONGDESC="Arch R Meta Package" +PKG_TOOLCHAIN="make" + +make_target() { + : +} + +makeinstall_target() { + + mkdir -p ${INSTALL}/usr/config/ + rsync -av ${PKG_DIR}/config/* ${INSTALL}/usr/config/ + ln -sf /storage/.config/system ${INSTALL}/system + find ${INSTALL}/usr/config/system/ -type f -exec chmod o+x {} \; + + mkdir -p ${INSTALL}/usr/bin/ + + ### Compatibility links for ports + ln -s /storage/roms ${INSTALL}/roms + + ### Add some quality of life customizations for hardworking devs. + if [ -n "${LOCAL_SSH_KEYS_FILE}" ] + then + mkdir -p ${INSTALL}/usr/config/ssh + cp ${LOCAL_SSH_KEYS_FILE} ${INSTALL}/usr/config/ssh/authorized_keys + fi + + if [ -n "${LOCAL_WIFI_SSID}" ] + then + sed -i "s#wifi.enabled=0#wifi.enabled=1#g" ${INSTALL}/usr/config/system/configs/system.cfg + mkdir -p ${INSTALL}/usr/config/iwd + cat <> ${INSTALL}/usr/config/iwd/${LOCAL_WIFI_SSID}.psk +[Security] +Passphrase=${LOCAL_WIFI_KEY} +EOF + fi + # Always install the update script + mkdir -p $INSTALL/usr/share/bootloader + find_file_path bootloader/update.sh && cp -av ${FOUND_PATH} ${INSTALL}/usr/share/bootloader +} + +post_install() { + ln -sf archr.target ${INSTALL}/usr/lib/systemd/system/default.target + + if [ ! -d "${INSTALL}/usr/share" ] + then + mkdir "${INSTALL}/usr/share" + fi + cp ${PKG_DIR}/sources/post-update ${INSTALL}/usr/share + chmod 755 ${INSTALL}/usr/share/post-update + + # Issue banner (no ASCII art - archr-splash handles the graphical logo) + cat <> ${INSTALL}/etc/issue + +... Version: ${OS_VERSION} (${OS_BUILD}) +... Built: ${BUILD_DATE} + +EOF + cp ${PKG_DIR}/sources/motd ${INSTALL}/etc + cat ${INSTALL}/etc/issue >> ${INSTALL}/etc/motd + + cp ${PKG_DIR}/sources/scripts/* ${INSTALL}/usr/bin + chmod 0755 ${INSTALL}/usr/bin/* 2>/dev/null ||: + + ### Fix and migrate to autostart package + enable_service archr-autostart.service + + ### ZRAM/Swap and Memory Manager Service + enable_service archr-memory-manager.service + + ### Take a backup of the system configuration on shutdown + enable_service save-sysconfig.service + + sed -i "s#@DEVICENAME@#${DEVICE}#g" ${INSTALL}/usr/config/system/configs/system.cfg + + ### Defaults for non-main builds. + BUILD_BRANCH="$(git branch --show-current)" + if [ ! "${BUILD_BRANCH}" = "main" ] + then + sed -i "s#samba.enabled=0#samba.enabled=1#g" ${INSTALL}/usr/config/system/configs/system.cfg + sed -i "s#ssh.enabled=0#ssh.enabled=1#g" ${INSTALL}/usr/config/system/configs/system.cfg + sed -i "s#wifi.enabled=0#wifi.enabled=1#g" ${INSTALL}/usr/config/system/configs/system.cfg + sed -i "s#system.loglevel=none#system.loglevel=verbose#g" ${INSTALL}/usr/config/system/configs/system.cfg + fi + +} diff --git a/projects/ArchR/packages/archr/profile.d/001-functions b/projects/ArchR/packages/archr/profile.d/001-functions new file mode 100644 index 0000000000..b34003bf99 --- /dev/null +++ b/projects/ArchR/packages/archr/profile.d/001-functions @@ -0,0 +1,236 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/os-release + +export XDG_RUNTIME_DIR=/var/run/0-runtime-dir +export PATH="/usr/bin:/usr/local/bin:/storage/bin:${PATH}" +export SDL_GAMECONTROLLERCONFIG_FILE="/storage/.config/SDL-GameControllerDB/gamecontrollerdb.txt" + +J_DIR="/storage/.config/system" +J_CONF="${J_DIR}/configs/system.cfg" +J_CONF_LOCK="/tmp/.system.cfg.lock" +ES_CONF="/storage/.emulationstation/es_settings.cfg" + +function tocon() { + echo -ne "\033[1000H\033[2K==> ${*}" >/dev/console +} + +function log() { + SOURCE=${1//\/*\//} + MESSAGE=${*#${1}} + MESSAGE=${MESSAGE# } + logger -t ${SOURCE} "${MESSAGE}" + echo "$(date) ${SOURCE}: ${MESSAGE}" >>/var/log/messages +} + +function get_setting() { + if [ -n "${3}" ] + then + ### Test to see if we have a game setting. + VAR="$2\[\"$(echo ${3} | sed -E "s~'~\\\x27~g"';s~[()&]~\\&~g')\"\]\.$1" + OUTPUT=$(awk 'BEGIN {FS="="} /^'"${VAR}"'/ {print $NF}' ${J_CONF}) + if [ ! -z "${OUTPUT}" ] + then + echo ${OUTPUT} + return + else + ### If not, check to see if we have a system setting. + LOCAL=$(awk -F: '/^'"${2}.${1}"'=/ { st = index($0,"=");print substr($0,st+1);exit}' ${J_CONF}) + if [ ! -z "${LOCAL}" ] + then + echo ${LOCAL} + return + fi + fi + fi + + if [ -z "${3}" ] && [ -n "${2}" ] + then + ### Check to see if we have a global setting. + LOCAL=$(awk -F: '/^'"${2}.${1}"'=/ { st = index($0,"=");print substr($0,st+1);exit}' ${J_CONF}) + if [ ! -z "${LOCAL}" ] + then + echo ${LOCAL} + return + fi + fi + + ### Check to see if we have a "system." global setting. + SYSTEM=$(awk -F: '/^system.'"${1}"='/ { st = index($0,"=");print substr($0,st+1);exit}' ${J_CONF}) + if [ -n "${SYSTEM}" ] + then + echo ${SYSTEM} + return + fi + + ### Check to see if we have a "global." global setting." + LOCAL=$(awk -F: '/^'"${1}"='/ { st = index($0,"=");print substr($0,st+1);exit}' ${J_CONF}) + if [ -z "${LOCAL}" ] + then + awk -F: '/^global.'"${1}"='/ { st = index($0,"=");print substr($0,st+1);exit}' ${J_CONF} + return + else + echo ${LOCAL} + fi + return +} + +function wait_lock() { + while true + do + if (set -o noclobber; echo "$$" > "${J_CONF_LOCK}") 2>/dev/null + then + trap 'rm -f "$lockfile"; exit $?' INT TERM EXIT + break + else + sleep 1 + fi + done +} + +function del_setting() { + wait_lock + if [[ "${1}" =~ ^[[:alnum:]] ]] + then + sed -i "/^${1}=/d" "${J_CONF}" + fi + rm -f "${J_CONF_LOCK}" +} + +function sort_settings() { + wait_lock + cat "${J_CONF}" | grep ^[a-z0-9] | sort >"${J_CONF}.tmp" + mv "${J_CONF}.tmp" "${J_CONF}" + rm -f "${J_CONF_LOCK}" +} + +function set_kill() { + if [ "${1}" = "set" ] + then + cat </tmp/.process-kill-data +${2} +EOF + elif [ "${1}" = "stop" ] + then + if [ -e "/tmp/.process-kill-data" ] + then + rm -f "/tmp/.process-kill-data" + fi + fi +} + +function set_setting() { + + if [ ! -d "/storage/.config/system/configs" ] + then + mkdir -p /storage/.config/system/configs + fi + if [ ! -e "/storage/.config/system/configs/system.cfg" ] + then + cp -f /usr/config/system/configs/system.cfg /storage/.config/system/configs/system.cfg + fi + + if [[ "${1}" =~ ^[[:alnum:]] ]] + then + del_setting "${1}" + if [ ! "${2}" = "default" ] + then + wait_lock + echo "${1}=${2}" >> "${J_CONF}" + rm -f "${J_CONF_LOCK}" + fi + fi +} + +function battery_percent() { + awk 'BEGIN {FS="="} /POWER_SUPPLY_CAPACITY=/ {print $2}' /sys/class/power_supply/[Bb][Aa][Tt]*/uevent 2>/dev/null +} + +function get_es_setting() { + echo $(sed -n "s|\s*<${1} name=\"${2}\" value=\"\(.*\)\" />|\1|p" ${ES_CONF}) +} + +function fbwidth() { + local ORIENTATION=$(/dev/null 2>&1 + done + + for thread in $(seq ${THREADS} 1 ${AVAILABLE_THREADS}); do + echo ${MODE} | tee /sys/devices/system/cpu/cpu${thread}/online >/dev/null 2>&1 + done +} + +set_cpu_gov() { + for POLICY in $(ls /sys/devices/system/cpu/cpufreq 2>/dev/null | grep policy[0-9]); do + if [ -e "/sys/devices/system/cpu/cpufreq/${POLICY}/scaling_governor" ]; then + echo $1 >/sys/devices/system/cpu/cpufreq/${POLICY}/scaling_governor 2>/dev/null + fi + done +} + +# Toggle the CPU turbo OPP. On RK3326 the 1512 MHz OPP is marked +# turbo-mode in the DT, which means cpufreq-dt excludes it from the +# regular ladder until cpufreq/boost=1. Without this the ondemand and +# performance governors top out at 1416 MHz, regardless of how the +# floor is pinned. +set_cpu_boost() { + [ -e /sys/devices/system/cpu/cpufreq/boost ] || return + case ${1} in + on|1) echo 1 >/sys/devices/system/cpu/cpufreq/boost 2>/dev/null ;; + off|0) echo 0 >/sys/devices/system/cpu/cpufreq/boost 2>/dev/null ;; + esac +} + +# Pin CPU max_freq across all policies to the highest available OPP. +# Turbo OPPs (DT `turbo-mode`) live in scaling_boost_frequencies, NOT in +# scaling_available_frequencies, even after cpufreq/boost=1. Combine +# both so "highest" really hits 1512 MHz on RK3326 when the user's +# turbo switch is on, and naturally falls back to 1416 when off (boost +# file then reports an empty list). +set_cpu_max_freq() { + for POLICY in /sys/devices/system/cpu/cpufreq/policy[0-9]*; do + [ -e "${POLICY}/scaling_max_freq" ] || continue + [ -e "${POLICY}/scaling_available_frequencies" ] || continue + + local target="" + case ${1} in + highest) + target=$( { + cat "${POLICY}/scaling_available_frequencies" 2>/dev/null + cat "${POLICY}/scaling_boost_frequencies" 2>/dev/null + } | tr ' ' '\n' | grep -E '^[0-9]+$' | sort -n | tail -n1) + ;; + *) + target=${1} + ;; + esac + + [ -n "${target}" ] && echo "${target}" >"${POLICY}/scaling_max_freq" 2>/dev/null + done +} + +set_cpu_min_freq() { + for POLICY in /sys/devices/system/cpu/cpufreq/policy[0-9]*; do + [ -e "${POLICY}/scaling_min_freq" ] || continue + [ -e "${POLICY}/scaling_available_frequencies" ] || continue + + local target="" + case ${1} in + highest) + target=$( { + cat "${POLICY}/scaling_available_frequencies" 2>/dev/null + cat "${POLICY}/scaling_boost_frequencies" 2>/dev/null + } | tr ' ' '\n' | grep -E '^[0-9]+$' | sort -n | tail -n1) + ;; + lowest) + target=$(tr ' ' '\n' <"${POLICY}/scaling_available_frequencies" | grep -E '^[0-9]+$' | sort -n | head -n1) + ;; + *) + target=${1} + ;; + esac + + [ -n "${target}" ] && echo "${target}" >"${POLICY}/scaling_min_freq" 2>/dev/null + done +} + +set_dmc_gov() { + if [ -e "${DMC_FREQ}/governor" ]; then + for governor in $1 dmc_$1 simple_$1; do + echo ${governor} >${DMC_FREQ}/governor 2>/dev/null + if [ "$?" = 0 ]; then + return + fi + done + fi +} + +set_gpu_gov() { + if [ -e "${GPU_FREQ}/governor" ]; then + for governor in $1 dmc_$1 simple_$1; do + echo ${governor} >${GPU_FREQ}/governor 2>/dev/null + if [ "$?" = 0 ]; then + return + fi + done + fi +} + +# Pin GPU min_freq to floor a workload at a given OPP. Without this, devfreq +# can sit at 200/300 MHz at the start of a frame and miss vsync; ROCKNIX +# achieves a similar effect by exposing only one OPP in DT. We do it at +# runtime so suspend/idle can still drop to low OPPs. +set_gpu_min_freq() { + [ -e "${GPU_FREQ}/min_freq" ] || return + [ -e "${GPU_FREQ}/available_frequencies" ] || return + + local target="" + case ${1} in + highest) + target=$(tr ' ' '\n' <"${GPU_FREQ}/available_frequencies" | sort -n | tail -n1) + ;; + lowest) + target=$(tr ' ' '\n' <"${GPU_FREQ}/available_frequencies" | sort -n | head -n1) + ;; + *) + target=${1} + ;; + esac + + [ -n "${target}" ] && echo "${target}" >"${GPU_FREQ}/min_freq" 2>/dev/null +} + +onlinethreads() { + set_online_threads ${1} ${2} +} + +# Restore the user-configured boost setting. Idle/menu paths call this so +# that turning the device's "Turbo Mode" toggle off in the UI is honored +# outside gameplay; gameplay always overrides it on for the duration of +# the run. +restore_cpu_boost() { + local TURBO_SETTING + TURBO_SETTING=$(get_setting "enable.turbo-mode" 2>/dev/null) + case ${TURBO_SETTING} in + 1) set_cpu_boost on ;; + *) set_cpu_boost off ;; + esac +} + +performance() { + # Honor the user's "Enable CPU Overclock" switch from ES even during + # gameplay: gameplay shouldn't silently enable turbo behind the user's + # back. If they want the 1512 MHz OPP, they toggle it on; if they + # prefer to stay at 1416 MHz for thermals/battery, gameplay respects + # that. set_cpu_max_freq highest then pins to the highest currently + # available frequency (1512 if boost on, 1416 if off). + restore_cpu_boost + set_cpu_gov performance + set_cpu_max_freq highest + set_dmc_gov performance +} + +ondemand() { + restore_cpu_boost + set_cpu_gov ondemand + set_dmc_gov ondemand + # Tune ondemand: stay at high freq longer, reduce switching overhead + for POLICY in $(ls /sys/devices/system/cpu/cpufreq 2>/dev/null | grep policy[0-9]); do + local ONDEMAND="/sys/devices/system/cpu/cpufreq/${POLICY}/ondemand" + if [ -d "${ONDEMAND}" ]; then + echo 85 > ${ONDEMAND}/up_threshold 2>/dev/null + echo 150 > ${ONDEMAND}/sampling_down_factor 2>/dev/null + fi + done +} + +schedutil() { + restore_cpu_boost + set_cpu_gov schedutil + set_dmc_gov ondemand +} + +powersave() { + set_cpu_gov powersave + set_dmc_gov powersave +} + +get_gpu_performance_level() { + get_setting system.gpuperf +} + +gpu_performance_level() { + case ${1} in + auto|default) + # Restore governor; do NOT lower min_freq here. Direct min_freq writes + # at game exit (especially while Panfrost is mid-teardown of the GL + # context) caused immediate kernel reboots on R36S V22 boards. Governor + # ondemand naturally drops cur_freq when idle, which is enough. + set_gpu_gov ondemand + ;; + performance) + set_gpu_gov performance + set_gpu_min_freq highest + ;; + *) + set_gpu_gov ${1} + ;; + esac +} + +get_available_gpu_governors() { + echo "default"; tr " " "\n" < $GPU_FREQ/available_governors | grep \[a-z\] +} diff --git a/projects/ArchR/packages/archr/profile.d/100-gamecontroller-functions b/projects/ArchR/packages/archr/profile.d/100-gamecontroller-functions new file mode 100644 index 0000000000..09667a2aed --- /dev/null +++ b/projects/ArchR/packages/archr/profile.d/100-gamecontroller-functions @@ -0,0 +1,157 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +# -- Helper functions -- +# Map the actual button/hat/axis - defaults to Nintendo layout mapping +function map_input_control { + local INPUT_NAME=$1 + local TYPE=$2 + local ID=$3 + local VALUE=$4 + + map_x_result="" + case "${INPUT_NAME}" in + "a") TR_NAME="${ABUT:-a}";; + "b") TR_NAME="${BBUT:-b}";; + "x") TR_NAME="${XBUT:-x}";; + "y") TR_NAME="${YBUT:-y}";; + "hotkeyenable") TR_NAME="guide";; + "up") TR_NAME="dpup";; + "down") TR_NAME="dpdown";; + "left") TR_NAME="dpleft";; + "right") TR_NAME="dpright";; + "leftshoulder") TR_NAME="${LEFTSHOULDER:-leftshoulder}";; + "leftthumb") TR_NAME="leftstick";; + "lefttrigger") TR_NAME="${LEFTTRIGGER:-lefttrigger}";; + "rightshoulder") TR_NAME="${RIGHTSHOULDER:-rightshoulder}";; + "rightthumb") TR_NAME="rightstick";; + "righttrigger") TR_NAME="${RIGHTTRIGGER:-righttrigger}";; + "select") TR_NAME="back";; + "start") TR_NAME="start";; + "leftanalogup") TR_NAME="-lefty";; + "leftanalogleft") TR_NAME="-leftx";; + "leftanalogdown") TR_NAME="+lefty";; + "leftanalogright") TR_NAME="+leftx";; + "rightanalogup") TR_NAME="-righty";; + "rightanalogleft") TR_NAME="-rightx";; + "rightanalogdown") TR_NAME="+righty";; + "rightanalogright") TR_NAME="+rightx";; + *) + return + ;; + esac + + case "${TYPE}" in + "axis") + if (( $VALUE < 0 )); then + map_x_result="${TR_NAME}:${map_x_result}-a${ID}," + else + # Most (save for a few misbehaved children...) triggers are [0, 1] instead of [-1, 1] + # Shitty workaround for an emulationstation issue + if [[ $INPUT_NAME =~ .*"trigger" ]]; then + map_x_result="${TR_NAME}:${map_x_result}a${ID}," + else + map_x_result="${TR_NAME}:${map_x_result}+a${ID}," + fi + fi + ;; + "button") + map_x_result="${TR_NAME}:${map_x_result}b${ID}," + ;; + "hat") + map_x_result="${TR_NAME}:${map_x_result}h${ID}.${VALUE}," + ;; + *) + echo "Invalid entry ${TYPE}" + ;; + esac +} + +function get_map_suffix { + map_suffix="platform:Linux," +} + +function get_map_prefix { + map_prefix="${GUID},${NAME}," +} + +function build_connected_devices_es_input { + local ES_CONFIG=${1} + # Clean up any old files + rm -rf /tmp/es_input + rm -rf "${ES_CONFIG}" + + # Dump connected device GUIDs + /usr/bin/list-guid > /tmp/list-guid + + # Loop through connected device and extract ES xml mapping + mkdir /tmp/es_input + while read DGUID; do + if [ ! -z "$(cat /storage/.config/emulationstation/es_input.cfg | grep ${DGUID})" ]; then + cp -r /storage/.config/emulationstation/es_input.cfg /tmp/es_input/${DGUID}.xml + xmlstarlet ed --inplace -d "inputList/inputConfig[@deviceGUID!='${DGUID}']" /tmp/es_input/${DGUID}.xml + fi + done ' > "${ES_CONFIG}" + grep -vh '>\|> "${ES_CONFIG}" + echo '' >> "${ES_CONFIG}" +} + +# Create a controller DB file for connected controllers witih mappings for desired layout +function create_controller_db { + local CONTROLLER_LAYOUT="${1}" + local ES_CONFIG="${2}" + local CONTROLLER_DB="${3}"; + + # Create an ES input config file containing only connected controllers + build_connected_devices_es_input ${ES_CONFIG} + + # Query controllers mapped in emulationstation, ignore devices without a GUID + local ES_QUERY="$(xmlstarlet sel -T -t -m "inputList/inputConfig[@deviceGUID!='']" -n -v "concat(@deviceName,';',@deviceGUID)" $ES_CONFIG)" + printf "# ${CONTROLLER_LAYOUT} layout\n" >> "${CONTROLLER_DB}" + + echo "## ES Dev Mapper ##" + while IFS=";" read -r NAME GUID; do + echo "$NAME :: $GUID" + # Ignore keyboards + if [[ "${GUID}" == -1 ]]; then + continue + fi + + # Query this specific GUID on the mappings + local MAPPING_CFG=$(xmlstarlet sel -T -t -m "//inputConfig[@deviceGUID = '${GUID}']/input" -n -v "concat(@name,';',@type,';',@id,';',@value)" $ES_CONFIG) + + # Grab the 'hotkeyenable' and 'select' button mappings to use later + unset HOTKEYENABLE_BUTTON + unset SELECT_BUTTON + + while IFS=";" read -r -e INPUT_NAME TYPE ID VALUE; do + [ ${INPUT_NAME} == "hotkeyenable" ] && HOTKEYENABLE_BUTTON="${ID}" + [ ${INPUT_NAME} == "select" ] && SELECT_BUTTON="${ID}" + done <<< ${MAPPING_CFG:1} + + local MAPPING="" + while IFS=";" read -r -e INPUT_NAME TYPE ID VALUE; do + # Map the controller - skip 'hotkeyenable' if it is the same as 'select' + if [ ${INPUT_NAME} == "hotkeyenable" -a ${HOTKEYENABLE_BUTTON} == ${SELECT_BUTTON} ]; then + echo "Skipping 'hotkeyenable', same mapping as 'select'" + else + map_input_control "${INPUT_NAME}" "${TYPE}" "${ID}" "${VALUE}" + + # Only concatenate valid mappings + if [[ ! -z ${map_x_result} ]]; then + MAPPING="${MAPPING}${map_x_result}" + fi + fi + done <<< ${MAPPING_CFG:1} + + get_map_prefix + get_map_suffix + if [[ ! -z "${MAPPING}" ]]; then + echo "${map_prefix}${MAPPING}${map_suffix}" >> "${CONTROLLER_DB}" + fi + done <<< ${ES_QUERY:1} +} \ No newline at end of file diff --git a/projects/ArchR/packages/archr/profile.d/101-gpu-functions b/projects/ArchR/packages/archr/profile.d/101-gpu-functions new file mode 100644 index 0000000000..1c81913f22 --- /dev/null +++ b/projects/ArchR/packages/archr/profile.d/101-gpu-functions @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2026-present ArchR (https://github.com/archr-linux/Arch-R) + +function gpu_profiling() { + local sysfs_node + local profiling_state=${1} + + case "${HW_DEVICE}" in + S922X|RK3326) + # Enable Panfrost profiling - see https://docs.kernel.org/gpu/panfrost.html + if [[ -e "/sys/bus/platform/drivers/panfrost" ]]; then + case "${profiling_state}" in + "on") + echo 1 > /sys/bus/platform/drivers/panfrost/[a-f0-9]*.gpu/profiling + ;; + "off") + echo 0 > /sys/bus/platform/drivers/panfrost/[a-f0-9]*.gpu/profiling + ;; + esac + fi + ;; + esac +} \ No newline at end of file diff --git a/projects/ArchR/packages/archr/sources/motd b/projects/ArchR/packages/archr/sources/motd new file mode 100644 index 0000000000..a4ca36832b --- /dev/null +++ b/projects/ArchR/packages/archr/sources/motd @@ -0,0 +1,13 @@ +╔════════════════════════════════════════════════════╗ +║ ║ +║ █████╗ ██████╗ ██████╗██╗ ██╗ ██████╗ ║ +║ ██╔══██╗██╔══██╗██╔════╝██║ ██║ ██╔══██╗ ║ +║ ███████║██████╔╝██║ ███████║ ██████╔╝ ║ +║ ██╔══██║██╔══██╗██║ ██╔══██║ ██╔══██╗ ║ +║ ██║ ██║██║ ██║╚██████╗██║ ██║ ██║ ██║ ║ +║ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ║ +║ ║ +║ Arch Linux Gaming Distribution for R36S ║ +║ ║ +╚════════════════════════════════════════════════════╝ + diff --git a/projects/ArchR/packages/archr/sources/post-update b/projects/ArchR/packages/archr/sources/post-update new file mode 100644 index 0000000000..8bd72abadb --- /dev/null +++ b/projects/ArchR/packages/archr/sources/post-update @@ -0,0 +1,300 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile + +LOG="/var/log/boot.log" + +### This script contains items that we only want to execute after a ArchR upgrade, +### or after a fresh installation. + +### Items in this block should always run after updates. +################################################################################ + +echo "Rebuild library cache..." >>${LOG} +tocon "Rebuilding library cache..." +### Rebuild the library cache +rm -f /storage/.cache/ld.so.cache +ldconfig -X + +echo "Sync configuration files..." >>${LOG} +tocon "Re-sync configuration files..." +### Sync configurations +if [ -d "/storage/.config/system/configs" ] +then + EXCLUDE="--exclude=configs" +fi + +### Remove and link es configs so they are managed with OS updates. +for es_cfg in es_features.cfg es_systems.cfg +do + mv /storage/.config/emulationstation/${es_cfg} /storage/.config/emulationstation/last_${es_cfg} >/dev/null 2>&1 + ln -s /usr/config/emulationstation/${es_cfg} /storage/.config/emulationstation/${es_cfg} >/dev/null 2>&1 +done + +rsync -a --delete ${EXCLUDE} /usr/config/system/ /storage/.config/system/ +rsync -a --ignore-existing /usr/config/game /storage/.config/ +rsync -a /usr/config/modules /storage/.config/ + +if [ -f "/storage/.config/emulationstation/resources/logo.png" ] +then + rm -f /storage/.config/emulationstation/resources/logo.png +fi + +echo "Sync modules..." >>${LOG} +tocon "Update tool modules..." +rsync -a /usr/config/modules/* /storage/.config/modules/ +cp -f /usr/config/retroarch/retroarch-core-options.cfg /storage/.config/retroarch/retroarch-core-options.cfg + +### Apply developer ssh keys if they exist +echo "Apply dev keys if available..." >>${LOG} +if [ -e /usr/config/ssh/authorized_keys ] +then + tocon "Update developer keys..." + cp /usr/config/ssh/authorized_keys /storage/.ssh +fi + +### Apply developer wifi config if they exist +echo "Apply dev wifi config if available..." >>${LOG} +if [ -d /usr/config/iwd ] +then + tocon "Update developer wifi config..." + cp /usr/config/iwd/* /storage/.cache/iwd/ +fi + +### Sync rsync configs +echo "Update rsync configuration files..." >>${LOG} +rsync --ignore-existing /usr/config/rsync-rules.conf /storage/.config/ +rsync --ignore-existing /usr/config/rsync.conf /storage/.config/ + +### Add cloud sync-related files if missing +echo "Update cloud sync files..." >>${LOG} +if [ -x "/usr/bin/cloud_sync_helper" ]; then + # Use the helper script to properly merge configurations + tocon "Updating cloud sync configuration..." + /usr/bin/cloud_sync_helper ${LOG} +else + # Fall back to the simple copy if helper is not available + tocon "Updating cloud sync files..." + # Copy default cloud sync files if they don't exist + for config_file in cloud_sync-rules.txt.defaults cloud_sync.conf.defaults; do + if [ -f "/usr/config/${config_file}" ]; then + rsync --ignore-existing /usr/config/${config_file} /storage/.config/ + fi + done + # Also copy the main config file if it doesn't exist + if [ -f "/usr/config/cloud_sync.conf" ]; then + rsync --ignore-existing /usr/config/cloud_sync.conf /storage/.config/ + # Always update defaults file to ensure latest version + rsync /usr/config/cloud_sync.conf.defaults /storage/.config/ + fi +fi + +### Sync locale data +tocon "Re-sync locale data..." +rsync -a --delete /usr/config/locale/* /storage/.config/locale/ >>/var/log/configure.log 2>&1 +rm -rf /storage/.config/emulationstation/locale >>/var/log/configure.log 2>&1 ||: +ln -sf /usr/share/locale /storage/.config/emulationstation/locale >>/var/log/configure.log 2>&1 ||: + +### Handle assets folder for ppsspp v1.20+ upgrade +if [ ! -d "/storage/.config/ppsspp/assets/ui_images" ] +then + rsync -a --delete /usr/config/ppsspp/assets/* /storage/.config/ppsspp/assets/ +fi + +### Fix Japanese language bug +if [ ! -e "/storage/.config/ppsspp/assets/NotoSansJP-Regular.ttf" ] +then + cd /storage/.config/ppsspp/assets + cp /usr/config/ppsspp/assets/NotoSansJP-Regular.ttf . + ln -s NotoSansJP-Regular.ttf Roboto-Condensed.ttf + cd - +fi + +### Add items below this line that are safe to remove after a period of time. +################################################################################ + +if echo ${HW_DEVICE} | grep -E 'H700'; then + rsync -a /usr/config/ppsspp /storage/.config/ + rsync -a /usr/config/flycast /storage/.config/ +fi + +# SM8250 / SM8550 - disable RA threaded video +if echo ${HW_DEVICE} | grep -E 'SM8250|SM8550'; then + sed -i '/video_threaded =/c\video_threaded = "false"' /storage/.config/retroarch/retroarch.cfg +fi + +# run the idtech script on update if folder does not exist +if [ ! -d "/storage/.config/idtech" ]; then + /usr/bin/generate-idtech.sh +fi + +# Clean up Dolphin +rm -r /storage/.config/dolphin-emu/GC +cp -rf /usr/config/dolphin-emu /storage/.config/ + +# Remove gamepad overlays +rm -r /tmp/overlays/gamepads + +# Clean hypseus/daphne mapping so the correct gets applied +if echo ${QUIRK_DEVICE} | grep ARC; then + rm /storage/.config/game/configs/hypseus/hypinput.ini +fi + +# Clean old dtb-overlays, they have been renamed to dtbo +if [ "${HW_DEVICE}" = "RK3566" ] && \ + [ $(ls -1 /flash/overlays/rk3566-undervolt-cpu*.dtb | wc -l) != 0 ]; then + mount -o remount,rw /flash + rm /flash/overlays/rk3566-undervolt-cpu*.dtb + sed -i '/FDTOVERLAYS/s/.dtb/.dtbo/g' /flash/extlinux/extlinux.conf + sed -i '/FDTOVERLAYS/s/.dtboo/.dtbo/g' /flash/extlinux/extlinux.conf + mount -o remount,ro /flash +fi + +if [ "$(uname -m)" = "aarch64" ] && \ + [ ! -d "/storage/roms/savestates/saturn/yabasanshiro" ]; then + mkdir "/storage/roms/savestates/saturn/yabasanshiro" + cp /storage/.config/yabasanshiro/*.yss /storage/roms/savestates/saturn/yabasanshiro/ + cp /storage/.config/yabasanshiro/*.png /storage/roms/savestates/saturn/yabasanshiro/ +fi + +# Rename network.enabled to wifi.enabled +sed -i 's/network.enabled/wifi.enabled/g' /storage/.config/system/configs/system.cfg + +# Add skip IPL/bios option tol dolphin config +DINI=/storage/.config/dolphin-emu/Dolphin.ini +grep -q "SkipIPL" "$DINI" +if [ $? -ne 0 ]; then + sed -i "/\[Core\]/a SkipIPL = True" $DINI +fi + +# Fix GUID Arc +if echo ${QUIRK_DEVICE} | grep ARC; then + for file in "\ + /storage/.config/emulationstation/es_input.cfg \ + /storage/.config/SDL-GameControllerDB/gamecontrollerdb.txt \ + /storage/.config/yabasanshiro/input.cfg \ + /storage/.config/yabasanshiro/keymapv2.json \ + yabasanshiro/devices/keymapv2_rg_arc_joypad.json"; do + sed -i "s/1900d632010000000100000000010000/1900d632010000002c0a000000010000/g" $file + done +fi + +# Fix GUID R33s +if echo ${QUIRK_DEVICE} | grep R33S; then + for file in "\ + /storage/.config/emulationstation/es_input.cfg \ + /storage/.config/SDL-GameControllerDB/gamecontrollerdb.txt \ + /storage/.config/yabasanshiro/input.cfg \ + /storage/.config/yabasanshiro/keymapv2.json \ + yabasanshiro/devices/keymapv2_rg_arc_joypad.json"; do + sed -i "s/190014b3010000009178000000050000/190014b301000000a20a000000010000/g" $file + done +fi + +# set the default global.bezel if it doesn't already exist +grep -q "^global\.bezel=" /storage/.config/system/configs/system.cfg || + sed -i '$ a\global.bezel=thebezelproject' /storage/.config/system/configs/system.cfg + +# set the default suspend shutdown delays if they doesn't already exist +grep -q "^system\.shutdown_delay=" /storage/.config/system/configs/system.cfg || + sed -i '$ a\system.shutdown_delay=900' /storage/.config/system/configs/system.cfg + +grep -q "^system\.shutdown_delay_running_game=" /storage/.config/system/configs/system.cfg || + sed -i '$ a\system.shutdown_delay_running_game=900' /storage/.config/system/configs/system.cfg + +# Set the flag to park cores on fake suspend if it doesn't already exist +grep -q "^system\.suspend\.park_cores=" /storage/.config/system/configs/system.cfg || + sed -i '$ a\system.suspend.park_cores=1' /storage/.config/system/configs/system.cfg + +# Set the flag to use DPMS on fake suspend if it doesn't already exist +grep -q "^system\.suspend\.dpms=" /storage/.config/system/configs/system.cfg || + sed -i '$ a\system.suspend.dpms=1' /storage/.config/system/configs/system.cfg + +# Wipe azahar gptokeyb mappings as they have changed +rm -rf /storage/.config/azahar/*.gptk + +# Clean RGB10X mupen64plus-sa config +if echo ${QUIRK_DEVICE} | grep RGB10X; then + rm -rf /storage/.config/mupen64plus +fi + +if [ ! -d "/storage/.config/mednafen/mednafen.cfg" ]; then + # Don't load cd images to RAM, doesn't work with CHD or is at least very slow on rk3566 + sed -i "s/cd.image_memcache 1/cd.image_memcache 0/" /storage/.config/mednafen/mednafen.cfg +fi + +# Clean melonds-sa Gallium HUD config +sed -i '/nds.show_fps=/d' /storage/.config/system/configs/system.cfg + +# Clean S922X melonds-sa config +if [[ "${HW_DEVICE}" == "S922X" ]]; then + rm -f /storage/.config/melonDS/melonDS.gptk + rm -f /storage/.config/melonDS/melonDS.ini +fi + +# S922X - by default, disable MangoHud for systems with problematic emulators +# (flycast-sa, dolphin-sa and ppsspp-sa) +if [[ "${HW_DEVICE}" == "S922X" ]]; then + grep -q "^dreamcast\.archr\.mangohud\.enabled=" /storage/.config/system/configs/system.cfg || + sed -i '$ a\dreamcast.archr.mangohud.enabled=0' /storage/.config/system/configs/system.cfg + + grep -q "^gamecube\.archr\.mangohud\.enabled=" /storage/.config/system/configs/system.cfg || + sed -i '$ a\gamecube.archr.mangohud.enabled=0' /storage/.config/system/configs/system.cfg + + grep -q "^psp\.archr\.mangohud\.enabled=" /storage/.config/system/configs/system.cfg || + sed -i '$ a\psp.archr.mangohud.enabled=0' /storage/.config/system/configs/system.cfg +fi + +# S922X - disable fake suspend DPMS as it causes crash / reboot on resume +[[ "${HW_DEVICE}" == "S922X" ]] && sed -i '/system.suspend.dpms/c\system.suspend.dpms=0' /storage/.config/system/configs/system.cfg + +# Make sure we are using the latest gamecontrollerdb file +cp -r "/usr/config/SDL-GameControllerDB/gamecontrollerdb.txt" "/storage/.config/SDL-GameControllerDB/gamecontrollerdb.txt" + +# Delete existing swap file - disabled by default on all platforms in https://github.com/archr-linux/Arch-R/pull/2223 +rm -f /storage/.cache/swapfile + +# Move existing azahar save states to /roms/savestates/3ds +if [[ -d "/storage/.config/azahar/states" && ! -d "/storage/roms/savestates/3ds" ]]; then + mkdir -p /storage/roms/savestates/3ds + cp -rf /storage/.config/azahar/states/* /storage/roms/savestates/3ds/ +fi + +# Clean input config for platforms migrated to inputplumber, with migration flag check +if [[ "${HW_DEVICE}" =~ SM8550|SM8650 && ! -e "/storage/.inputplumber_migration_complete" ]]; then + # Reset ES input / RA config + cp -f /usr/config/emulationstation/es_input.cfg /storage/.config/emulationstation/ + cp -f /usr/config/retroarch/retroarch.cfg /storage/.config/retroarch/ + + # Wipe standalone emulator config - it will be recreated from /usr/config on emulator launch + rm -rf /storage/.config/aethersx2 + rm -rf /storage/.config/dolphin-emu + rm -rf /storage/.config/azahar + rm -rf /storage/.config/duckstation + rm -rf /storage/.config/flycast + rm -rf /storage/.config/ppsspp + rm -rf /storage/.config/rpcs3 + rm -rf /storage/.config/Cemu + rm -rf /storage/.config/melonDS + rm -rf /storage/.config/mupen64plus + rm -rf /storage/.config/yabasanshiro + + # Mark migration as complete + touch /storage/.inputplumber_migration_complete +fi + +# Duckstation Qt +if [ -e "/storage/.config/duckstation/settings.ini" ]; then + # don't ask to create a desktop shortcut + grep -q "^NoDesktopFile =" /storage/.config/duckstation/settings.ini || + sed -i '/\[Main\]/a\NoDesktopFile = true' /storage/.config/duckstation/settings.ini + # no confirmation popup + sed -i 's/ConfirmPowerOff = true/ConfirmPowerOff = false/' /storage/.config/duckstation/settings.ini +fi + +# Clean old GPU 'governor' values +sed -i '/gpuperf=low/d' /storage/.config/system/configs/system.cfg +sed -i '/gpuperf=profile_standard/d' /storage/.config/system/configs/system.cfg +sed -i '/gpuperf=profile_peak/d' /storage/.config/system/configs/system.cfg diff --git a/projects/ArchR/packages/archr/sources/scripts/amionline b/projects/ArchR/packages/archr/sources/scripts/amionline new file mode 100755 index 0000000000..3551d04787 --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/amionline @@ -0,0 +1,20 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +ip route | awk '/default/ {print $3}' >/dev/null 2>&1 +if [ ! $? = 0 ] +then + echo false + exit 1 +else + ping www.google.com -c1 -w1 >/dev/null 2>&1 + if [ ! $? = 0 ] + then + echo false + exit 1 + else + echo true + exit 0 + fi +fi diff --git a/projects/ArchR/packages/archr/sources/scripts/archr-bluetooth b/projects/ArchR/packages/archr/sources/scripts/archr-bluetooth new file mode 100755 index 0000000000..e9d25a1900 --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/archr-bluetooth @@ -0,0 +1,371 @@ +#!/bin/sh + +# Source system-wide profile +. /etc/profile + +# Global variables +STORAGE_PATH="/storage" +CACHE_PATH="${STORAGE_PATH}/.cache" +BACKUP_DIR="${STORAGE_PATH}/roms/backups" +BACKUP_FILE="${BACKUP_DIR}/bluetooth.tar" +BT_DEVICE_FILE="/run/bt_device" +BT_LISTING_FILE="/run/bt_listing" +BT_LISTING_PID_FILE="/run/bt_listing.pid" +BT_CONTROL_FILE="/run/bt_discovery_control" +BT_AGENT_STATUS_FILE="/run/bt_agent_status" +BT_STATUS_FILE="/run/bt_status" + +# Action from command line +ACTION=$1 + +# Logging functions +log_error() { + echo "ERROR: $1" >&2 +} + +log_info() { + echo "INFO: $1" +} + +# Helper function to check MAC address format +validate_mac_address() { + echo "$1" | grep -qE "^([0-9A-F]{2}:){5}[0-9A-F]{2}$" + return $? +} + +# Display help information +do_help() { + cat >&2 < [options] + +Commands: + list - List trusted bluetooth devices + trust - Trust a specific device + trust input - Enter trust input mode + remove - Remove a device + save - Backup bluetooth configuration + restore - Restore bluetooth configuration + start_live_devices - Start monitoring devices + stop_live_devices - Stop monitoring devices + enable - Enable bluetooth + disable - Disable bluetooth + connect - Connect to a device + disconnect - Disconnect from a device +EOF +} + +# Check if bluetooth agent is running +check_agent_status() { + if [ ! -f "${BT_AGENT_STATUS_FILE}" ]; then + return 1 + fi + + local pid + pid=$(cat "${BT_AGENT_STATUS_FILE}") + if ! kill -0 "${pid}" 2>/dev/null; then + return 1 + fi + + return 0 +} + +# Backup bluetooth configuration +do_save() { + mkdir -p "${BACKUP_DIR}" + if (cd "${CACHE_PATH}" && tar cf "${BACKUP_FILE}" bluetooth); then + log_info "Bluetooth configuration backed up to ${BACKUP_FILE}" + return 0 + else + log_error "Failed to backup bluetooth configuration" + return 1 + fi +} + +# Restore bluetooth configuration +do_restore() { + if [ ! -f "${BACKUP_FILE}" ]; then + log_error "Backup file ${BACKUP_FILE} not found" + return 1 + fi + + if (cd "${CACHE_PATH}" && tar xf "${BACKUP_FILE}"); then + log_info "Bluetooth configuration restored from ${BACKUP_FILE}" + return 0 + else + log_error "Failed to restore bluetooth configuration" + return 1 + fi +} + +# List paired devices +do_list() { + find "${CACHE_PATH}/bluetooth" -type f -name info | while read -r FILE; do + if grep -qE '^Trusted=true$' "${FILE}"; then + DEVNAME=$(grep -E '^Name=' "${FILE}" | sed -e s+"^Name="++) + DEVCLASS=$(grep -E '^Class=' "${FILE}" | sed -e s+"^Class="++) + DEVADDR=$(basename "$(dirname "${FILE}")") + + DEVTYPE="" + case "${DEVCLASS}" in + "0x002508"|"0x000508") DEVTYPE="joystick" ;; + esac + + # Check connection status + if bluetoothctl -- info "${DEVADDR}" | grep -q "Connected: yes"; then + CONNECTED="yes" + else + CONNECTED="no" + fi + + echo "" + fi + done +} + +# Clean up device listing resources +cleanup_devlist() { + local tail_pid + + # Stop the tail process if running + if [ -f "${BT_LISTING_PID_FILE}" ]; then + tail_pid=$(cat "${BT_LISTING_PID_FILE}") + if [ -n "${tail_pid}" ]; then + kill -15 "${tail_pid}" 2>/dev/null + fi + rm -f "${BT_LISTING_PID_FILE}" + fi + + # Signal stop via control file + echo "stop" > "${BT_CONTROL_FILE}" + + # Clean up files + rm -f "${BT_LISTING_FILE}" "${BT_DEVICE_FILE}" +} + +# Start device listing +do_devlist() { + # Check if agent is running + if ! check_agent_status; then + log_error "Bluetooth agent is not running" + return 1 + fi + + # Initialize files + if ! > "${BT_DEVICE_FILE}"; then + log_error "Cannot create device file" + return 1 + fi + + if ! > "${BT_LISTING_FILE}"; then + log_error "Cannot create listing file" + return 1 + fi + + # Signal start via control file + echo "start" > "${BT_CONTROL_FILE}" + + # Start monitoring in background + tail -f "${BT_LISTING_FILE}" & + echo $! > "${BT_LISTING_PID_FILE}" + + # Set up cleanup on script exit + trap cleanup_devlist EXIT INT TERM + + # Wait for the tail process + wait $(cat "${BT_LISTING_PID_FILE}") +} + +# Stop device listing +do_stopdevlist() { + cleanup_devlist +} + +# Remove a device +do_remove() { + local DEV="$1" + + if ! validate_mac_address "${DEV}"; then + log_error "Invalid device address format" + return 1 + fi + + # Remove device using bluetoothctl + (echo "untrust ${DEV}"; echo "remove ${DEV}") | bluetoothctl >/dev/null 2>&1 + + # Remove device files + find "${CACHE_PATH}/bluetooth" -name "${DEV}" -exec rm -rf {} + + + # Backup new configuration + do_save + log_info "Device ${DEV} removed successfully" +} + +# Trust a device +do_trust() { + local TRUSTDEV="$1" + + # Check if agent is running + if ! check_agent_status; then + log_error "Bluetooth agent is not running" + return 1 + fi # This was the problem - had } instead of fi + + # Validate input for device address + if [ "${TRUSTDEV}" != "input" ]; then + if ! validate_mac_address "${TRUSTDEV}"; then + log_error "Invalid device address format" + return 1 + fi + fi + + # Write device to control file + echo "${TRUSTDEV}" > "${BT_DEVICE_FILE}" || return 1 + + local LAST_MSG="" + local NEW_MSG="" + local N=60 + + while [ $N -gt 0 ]; do + if [ -f "${BT_STATUS_FILE}" ]; then + NEW_MSG=$(cat "${BT_STATUS_FILE}") + if [ "${LAST_MSG}" != "${NEW_MSG}" ]; then + LAST_MSG="${NEW_MSG}" + echo "${NEW_MSG}" + fi + fi + + if [ "${TRUSTDEV}" != "input" ]; then + if do_list | grep -q "id=\"${TRUSTDEV}\""; then + break + fi + fi + + sleep 1 + N=$((N-1)) + done + + do_save +} + +# Enable bluetooth +do_enable() { + set_setting controllers.bluetooth.enabled 1 + systemctl start bluetooth + systemctl start bluetooth-agent + + # Wait for agent to start (up to 5 seconds) + local n=0 + while [ $n -lt 10 ]; do + if check_agent_status; then + log_info "Bluetooth agent started successfully" + return 0 + fi + sleep 0.5 + n=$((n + 1)) + done + + log_error "Failed to start bluetooth agent" + return 1 +} + +# Disable bluetooth +do_disable() { + set_setting controllers.bluetooth.enabled 0 + systemctl stop bluetooth-agent + systemctl stop bluetooth + log_info "Bluetooth disabled" +} + +# Connect to a device +do_connect() { + local DEV="$1" + + if ! validate_mac_address "${DEV}"; then + log_error "Invalid device address format" + return 1 + fi + + if bluetoothctl -- info "${DEV}" | grep -q "Connected: yes"; then + log_info "Device ${DEV} is already connected" + return 0 + fi + + log_info "Attempting to connect to device ${DEV}..." + if bluetoothctl -- connect "${DEV}"; then + log_info "Successfully connected to device ${DEV}" + return 0 + else + log_error "Failed to connect to device ${DEV}" + return 1 + fi +} + +# Disconnect from a device +do_disconnect() { + local DEV="$1" + + if ! validate_mac_address "${DEV}"; then + log_error "Invalid device address format" + return 1 + fi + + if ! bluetoothctl -- info "${DEV}" | grep -q "Connected: yes"; then + log_error "Device ${DEV} is not connected" + return 1 + fi + + if bluetoothctl -- disconnect "${DEV}"; then + log_info "Successfully disconnected device ${DEV}" + return 0 + else + log_error "Failed to disconnect device ${DEV}" + return 1 + fi +} + +# Main command processing +case "${ACTION}" in + "list") + do_list + ;; + "trust") + [ -z "$2" ] && { do_help "${0}"; exit 1; } + do_trust "$2" + ;; + "remove") + [ -z "$2" ] && { do_help "${0}"; exit 1; } + do_remove "$2" + ;; + "save") + do_save + ;; + "restore") + do_restore + ;; + "start_live_devices"|"live_devices") + do_devlist + ;; + "stop_live_devices") + do_stopdevlist + ;; + "enable") + do_enable + ;; + "disable") + do_disable + ;; + "connect") + [ -z "$2" ] && { do_help "${0}"; exit 1; } + do_connect "$2" + ;; + "disconnect") + [ -z "$2" ] && { do_help "${0}"; exit 1; } + do_disconnect "$2" + ;; + *) + do_help "${0}" + exit 1 + ;; +esac + +exit 0 diff --git a/projects/ArchR/packages/archr/sources/scripts/archr-bluetooth-agent b/projects/ArchR/packages/archr/sources/scripts/archr-bluetooth-agent new file mode 100755 index 0000000000..6bbe081806 --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/archr-bluetooth-agent @@ -0,0 +1,570 @@ +#!/usr/bin/python + +from __future__ import absolute_import, print_function + +from optparse import OptionParser, make_option +import asyncio +import dbussy as dbus +import ravel +import time +import os +import logging +import signal +import atexit + +# Constants and global variables +AGENT_INTERFACE = 'org.bluez.Agent1' +CONTROL_FILE = "/run/bt_discovery_control" +AGENT_STATUS_FILE = "/run/bt_agent_status" +LOG_FILE = "/var/log/bluetooth-agent.log" + +gadapter = None +gdiscovering = False +gdevices = {} +glisting_mode = False +glisting_devs = {} +gbus = None +g_shutdown_future = None + +# Configure logging +logging.basicConfig( + filename=LOG_FILE, + level=logging.DEBUG, + format='%(asctime)s [%(levelname)s] %(message)s', + datefmt='%Y-%m-%d %H:%M:%S' +) + +def bool2str(val, valiftrue, valiffalse): + return valiftrue if val else valiffalse + +def logging_status(msg): + try: + with open("/run/bt_status", "w") as file: + file.write(msg + "\n") + except Exception as e: + logging.error(f"Failed to write status: {e}") + +def prop2str(p): + val = p + if isinstance(p, (tuple, list)) and len(p) == 2 and isinstance(p[0], dbus.DBUS.Signature): + val = p[1] + + if isinstance(val, bytes): + return val.decode('UTF-8', 'replace') + + return val + +def getDevName(properties): + if "Name" in properties and "Address" in properties and "Icon" in properties: + return f"{prop2str(properties['Name'])} ({prop2str(properties['Address'])}, {prop2str(properties['Icon'])})" + if "Name" in properties and "Address" in properties: + return f"{prop2str(properties['Name'])} ({prop2str(properties['Address'])})" + if "Name" in properties: + return prop2str(properties["Name"]) + if "Address" in properties: + return prop2str(properties["Address"]) + return "unknown" + +def getShortDevName(properties): + if "Name" in properties: + return prop2str(properties["Name"]) + if "Address" in properties: + return prop2str(properties["Address"]) + return "unknown" + +def propertiesToStr(properties): + result = "" + for p in properties: + if p not in ["ServiceData", "RSSI", "UUIDs", "Adapter", "AddressType", + "Alias", "Bonded", "ServicesResolved", "ManufacturerData", + "AdvertisingFlags"]: + if result != "": + result = result + ", " + + val = prop2str(properties[p]) + + result = result + "{}={}".format(p, str(val)) + return result + +def getDevAddressNameType(properties): + if "Address" not in properties: + return None, None, None + + vaddr = prop2str(properties["Address"]) + vname = prop2str(properties["Name"]) if "Name" in properties else None + vtype = prop2str(properties["Icon"]) if "Icon" in properties else None + + return vaddr, vname, vtype + +def listing_dev_event(path, properties, adding): + global glisting_devs + + if (path in glisting_devs and adding) or (path not in glisting_devs and not adding): + return + + if adding: + glisting_devs[path] = True + else: + del glisting_devs[path] + + try: + devaddress, devname, devtype = getDevAddressNameType(properties) + + # Skip writing to file if the device address is None + if devaddress is None: + logging.debug(f"Skipping device with None address at path: {path}") + return + + with open("/run/bt_listing", "a") as file: + file.write(f'\n') + except Exception as e: + logging.error(f"Failed to write listing event: {e}") + +def icon2basicname(icon): + if icon is None: + return "unknown" + if icon == "input-gaming": + return "joystick" + if icon.startswith("audio-"): + return "audio" + return icon + +# Define the DBus signal handlers +async def interfaces_added(path, interfaces): + global gdevices + global glisting_mode + + 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 + + logging.info("Interface added: {}".format(propertiesToStr(properties))) + + if glisting_mode: + listing_dev_event(path, gdevices[path], True) + + if "Address" in gdevices[path]: + await connect_device(path, prop2str(properties["Address"]), gdevices[path], False, getBluetoothWantedAddr()) + else: + logging.info("No address. skip.") + +def interfaces_removed(path, interfaces): + global gdevices + + if "org.bluez.Device1" not in interfaces: + return + + if path in gdevices: + listing_dev_event(path, gdevices[path], False) + del gdevices[path] + +async def properties_changed(interface, changed, invalidated, path): + global gdevices + global glisting_mode + + if interface != "org.bluez.Device1": + return + + if path in gdevices: + gdevices[path] = merge2dicts(gdevices[path], changed) + else: + gdevices[path] = changed + + if glisting_mode: + listing_dev_event(path, gdevices[path], True) + + propstr = propertiesToStr(changed) + if propstr != "": + logging.info("Properties changed: {}".format(propstr)) + + if "Paired" in changed and changed["Paired"] == True: + await connect_device(path, gdevices[path]["Address"], gdevices[path], True, getBluetoothWantedAddr()) + return + + if "Connected" in changed: + if changed["Connected"] == True: + return + if changed["Connected"] == False: + logging.info("Skipping (property Connected changed to False)") + return + + if "Address" in gdevices[path]: + await connect_device(path, prop2str(gdevices[path]["Address"]), gdevices[path], False, getBluetoothWantedAddr()) + +def merge2dicts(d1, d2): + res = d1.copy() + res.update(d2) + return res + +def getBluetoothWantedAddr(): + addrDevice = None + if os.path.isfile("/run/bt_device"): + with open("/run/bt_device", "r") as file: + addrDevice = file.read().strip() + if addrDevice == "": + addrDevice = None + logging.info("bt_dev: {}".format(addrDevice)) + return addrDevice + +async def connect_device(path, address, properties, forceConnect, filter): + global gdiscovering + global gadapter + + if not filter: + logging.info(f"skipping {address}. No filter.") + return + + if "Trusted" not in properties or "Connected" not in properties: + logging.info(f"skipping {address}. Missing required properties.") + return + + trusted = prop2str(properties["Trusted"]) + paired = prop2str(properties["Paired"]) + devName = getDevName(properties) + shortDevName = getShortDevName(properties) + connected = prop2str(properties["Connected"]) + + if "Icon" not in properties: + logging.info(f"Skipping device {devName} (no type)") + return + + if not (filter == prop2str(properties["Address"]) or + (filter == "input" and prop2str(properties["Icon"]).startswith("input"))): + logging.info(f"Skipping device {devName} (not {filter})") + return + + logging.info(f"Event for {devName} (paired={bool2str(paired, 'paired', 'not paired')}, " + f"trusted={bool2str(trusted, 'trusted', 'untrusted')}, " + f"connected={bool2str(connected, 'connected', 'disconnected')})") + + if paired and trusted and connected: + logging.info(f"Skipping already connected device {devName}") + return + + if not paired and not connected and gdiscovering: + await doPairing(path, devName, shortDevName) + + if not trusted and (gdiscovering or forceConnect): + await doTrusting(path, devName, shortDevName) + + if not connected or forceConnect: + await doConnect(path, devName, shortDevName) + +async def check_discovery_control(): + try: + if os.path.exists(CONTROL_FILE): + with open(CONTROL_FILE, "r") as f: + command = f.read().strip() + + try: + os.remove(CONTROL_FILE) + except Exception as e: + logging.error(f"Failed to remove control file: {e}") + + if command == "start": + await handle_start_discovery() + elif command == "stop": + await handle_stop_discovery() + except Exception as e: + logging.error(f"Error in check_discovery_control: {e}") + return True + +async def handle_start_discovery(): + global gdiscovering, gadapter, glisting_mode, glisting_devs, gdevices + + if os.path.isfile("/run/bt_listing"): + glisting_mode = True + logging.info("Listing mode enabled") + glisting_devs = {} + for path in gdevices: + listing_dev_event(path, gdevices[path], True) + + try: + if not gdiscovering: + gdiscovering = True + logging.info("Starting discovery") + await gadapter.StartDiscovery() + except Exception as e: + logging.error(f"Failed to start discovery: {e}") + +async def handle_stop_discovery(): + global gdiscovering, gadapter, glisting_mode + + if glisting_mode: + logging.info("Listing mode disabled") + glisting_mode = False + + try: + if gdiscovering: + gdiscovering = False + logging.info("Stopping discovery") + await gadapter.StopDiscovery() + except Exception as e: + logging.error(f"Failed to stop discovery: {e}") + +async def doPairing(path, devName, shortDevName): + global gbus + logging.info(f"Pairing... ({devName})") + logging_status(f"Pairing {shortDevName}...") + try: + device_obj = gbus.get_proxy_object("org.bluez", path) + device_iface = await device_obj.get_async_interface("org.bluez.Device1") + await device_iface.Pair() + except Exception as e: + logging.error(f"Pairing failed ({devName}): {e}") + logging_status(f"Pairing failed ({shortDevName})") + +async def doTrusting(path, devName, shortDevName): + global gbus + logging.info(f"Trusting ({devName})") + logging_status(f"Trusting {shortDevName}...") + try: + device_obj = gbus.get_proxy_object("org.bluez", path) + device_iface = await device_obj.get_async_interface("org.bluez.Device1") + device_iface.Trusted = True + await ravel.set_prop_flush(device_iface) + except Exception as e: + logging.error(f"Trusting failed ({devName}): {e}") + logging_status(f"Trusting failed ({shortDevName})") + +async def doConnect(path, devName, shortDevName): + global gadapter, gdiscovering, gbus + + try: + if gdiscovering: + logging.info("Stopping discovery for connection") + await gadapter.StopDiscovery() + + device_obj = gbus.get_proxy_object("org.bluez", path) + device_iface = await device_obj.get_async_interface("org.bluez.Device1") + + for attempt in range(5): + try: + logging.info(f"Connecting... ({devName}) attempt {attempt + 1}") + logging_status(f"Connecting {shortDevName}...") + await device_iface.Connect() + logging.info(f"Connected successfully ({devName})") + logging_status(f"Connected successfully ({shortDevName})") + break + except Exception as e: + logging.error(f"Connection attempt {attempt + 1} failed: {e}") + if attempt < 4: + await asyncio.sleep(1) + else: + logging_status(f"Connection failed. Giving up. ({shortDevName})") + finally: + if gdiscovering: + logging.info("Restarting discovery") + try: + await gadapter.StartDiscovery() + except Exception as e: + logging.error(f"Failed to restart discovery: {e}") + +@ravel.interface(ravel.INTERFACE.SERVER, name=AGENT_INTERFACE) +class Agent: + def __init__(self): + self.exit_on_release = True + + def set_exit_on_release(self, exit_on_release): + self.exit_on_release = exit_on_release + + @ravel.method(in_signature="", out_signature="") + def Release(self): + global g_shutdown_future + logging.info("Agent Release") + if self.exit_on_release and g_shutdown_future: + g_shutdown_future.set_result(None) + + @ravel.method(in_signature="os", out_signature="") + def AuthorizeService(self, device, uuid): + logging.info("Agent AuthorizeService") + + @ravel.method(in_signature="o", out_signature="s") + def RequestPinCode(self, device): + logging.info(f"RequestPinCode ({device})") + return "0000" + + @ravel.method(in_signature="o", out_signature="u") + def RequestPasskey(self, device): + logging.info(f"RequestPasskey ({device})") + return 0 + + @ravel.method(in_signature="ouq", out_signature="") + def DisplayPasskey(self, device, passkey, entered): + logging.info(f"DisplayPasskey ({device}, {passkey:06d} entered {entered})") + + @ravel.method(in_signature="os", out_signature="") + def DisplayPinCode(self, device, pincode): + logging.info(f"DisplayPinCode ({device}, {pincode})") + + @ravel.method(in_signature="ou", out_signature="") + def RequestConfirmation(self, device, passkey): + logging.info("Agent RequestConfirmation") + return + + @ravel.method(in_signature="o", out_signature="") + def RequestAuthorization(self, device): + logging.info("Agent RequestAuthorization") + return + + @ravel.method(in_signature="", out_signature="") + def Cancel(self): + logging.info("Agent Cancel") + +def cleanup(): + try: + if os.path.exists(AGENT_STATUS_FILE): + os.remove(AGENT_STATUS_FILE) + except Exception as e: + logging.error(f"Cleanup failed: {e}") + +def write_status(): + try: + with open(AGENT_STATUS_FILE, "w") as f: + f.write(str(os.getpid())) + except Exception as e: + logging.error(f"Failed to write status file: {e}") + return False + return True + +async def find_adapter(bus, dev_id=None): + adapter_path = None + if dev_id: + adapter_path = f"/org/bluez/{dev_id}" + else: + try: + obj_manager_proxy = bus.get_proxy_object("org.bluez", "/") + obj_manager_iface = await obj_manager_proxy.get_async_interface(dbus.DBUSX.INTERFACE_OBJECT_MANAGER) + managed_objects = await obj_manager_iface.GetManagedObjects() + + for path, interfaces in managed_objects[0].items(): + if "org.bluez.Adapter1" in interfaces: + adapter_path = path + break + except Exception as e: + logging.error(f"Failed to find adapter via ObjectManager: {e}") + return None + + if not adapter_path: + return None + + logging.info(f"Using adapter at {adapter_path}") + adapter_obj = bus.get_proxy_object("org.bluez", adapter_path) + return await adapter_obj.get_async_interface("org.bluez.Adapter1") + +async def discovery_control_loop(): + """ Replaces GLib.timeout_add(500, check_discovery_control) """ + while True: + try: + await check_discovery_control() + except Exception as e: + logging.error(f"Error in discovery_control_loop: {e}") + await asyncio.sleep(0.5) + +@ravel.signal(in_signature="oa{sa{sv}}") +async def interfaces_added_wrapper(path, interfaces_and_properties, bus=None): + """ Wrapper to call the original async handler """ + try: + await interfaces_added(path, interfaces_and_properties) + except Exception as e: + logging.error(f"Error in interfaces_added_wrapper: {e}") + +@ravel.signal(in_signature="oas") +def interfaces_removed_wrapper(path, interfaces, bus=None): + """ Wrapper to call the original handler """ + try: + interfaces_removed(path, interfaces) + except Exception as e: + logging.error(f"Error in interfaces_removed_wrapper: {e}") + +@ravel.signal(in_signature="sa{sv}as", message_keyword="message") +async def properties_changed_wrapper(interface_name, changed_properties, invalidated_properties, message=None): + """ Wrapper to filter for Device1 and call the original async handler """ + if interface_name == "org.bluez.Device1": + try: + await properties_changed(interface_name, changed_properties, invalidated_properties, message.path) + except Exception as e: + logging.error(f"Error in properties_changed_wrapper: {e}") + + +async def main(): + global gbus, gadapter, g_shutdown_future + + atexit.register(cleanup) + + option_list = [ + make_option("-i", "--device", action="store", type="string", dest="dev_id") + ] + parser = OptionParser(option_list=option_list) + options, args = parser.parse_args() + + gbus = await ravel.system_bus_async() + + gbus.listen_objects_added(interfaces_added_wrapper) + gbus.listen_objects_removed(interfaces_removed_wrapper) + + gbus.listen_propchanged( + path="/", + fallback=True, + interface="org.bluez.Device1", + func=properties_changed_wrapper + ) + + agentpath = "/archr/agent" + agent = Agent() + gbus.register(path=agentpath, interface=agent, fallback=False) + + try: + agent_manager_obj = gbus.get_proxy_object("org.bluez", "/org/bluez") + manager = await agent_manager_obj.get_async_interface("org.bluez.AgentManager1") + await manager.RegisterAgent(agentpath, "NoInputNoOutput") + await manager.RequestDefaultAgent(agentpath) + logging.info("Agent registered") + except Exception as e: + logging.error(f"Failed to register agent: {e}") + raise + + if not write_status(): + raise Exception("Failed to write status file") + + logging.info("Waiting for Bluetooth adapter...") + await asyncio.sleep(5) + gadapter = await find_adapter(gbus, options.dev_id) + + if not gadapter: + raise Exception("No bluetooth adapter found") + + logging.info("Adapter initialized") + + discovery_task = asyncio.create_task(discovery_control_loop()) + + g_shutdown_future = asyncio.Future() + await g_shutdown_future + + discovery_task.cancel() + try: + await discovery_task + except asyncio.CancelledError: + pass + + logging.info("Shutdown future triggered, main loop terminating.") + + +if __name__ == '__main__': + try: + asyncio.run(main()) + except Exception as e: + logging.error(f"Fatal error: {e}", exc_info=True) + finally: + logging.error("Agent terminated") + cleanup() diff --git a/projects/ArchR/packages/archr/sources/scripts/archr-config b/projects/ArchR/packages/archr/sources/scripts/archr-config new file mode 100755 index 0000000000..3bb1e58ea6 --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/archr-config @@ -0,0 +1,296 @@ +#!/bin/bash + +. /etc/profile +. /etc/os-release + +if [ ! "$1" ];then + echo -e "usage : archr-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/system/configs/config.txt" +storageFile="/storage/.config/system/configs/archr-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/archr.log +#systemsetting="python /usr/lib/python2.7/site-packages/configgen/settings/archrSettings.py" + +log=/var/log/systemsettings.log +systemsetting="/usr/bin/archr-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 ! archr-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=$(archr-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" + archr-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 -c 0 -M 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 -c 0 -M set ${DEVICE_AUDIO_MIXER} unmute || exit 1 + amixer -c 0 -M set ${DEVICE_AUDIO_MIXER} -- ${mode}% || exit 1 + + # maximize the sound to be sure it's not 0, allow errors + amixer -c 0 -M set PCM -- 100% #|| exit 1 + amixer -c 0 -M 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 + system-upgrade + exit $? +fi + +if [[ "$command" == "storage" ]]; then + exit 0; +fi + +if [[ "$command" == "forgetBT" ]]; then + systemctl stop bluetooth bluetooth-agent + rm -rf /storage/.cache/bluetooth/* /storage/roms/backups/bluetooth.tar + systemctl start bluetooth bluetooth-agent + exit 0 +fi + +if [ "$command" == "tz" ];then + if test "$mode" == "" + then + cat /storage/.config/system/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/projects/ArchR/packages/archr/sources/scripts/archr-es-thebezelproject b/projects/ArchR/packages/archr/sources/scripts/archr-es-thebezelproject new file mode 100755 index 0000000000..d4537ef83e --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/archr-es-thebezelproject @@ -0,0 +1,641 @@ +#! /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 ' +# +# 20190801 Initial release +# 20191120 Rewite all script for incremential runtime +# 20200410 Fix : Support for daphne did not work +# 20200708 Fix : Default bezel was never copied +# 20200709 Add : Progress count (started from Terminal/SSH vs ES) +# 20210130 Add : Take bezels by systems from TheBezelProjet Github (Batocera 30+) +# 20211010 Fix : Recursive search in roms directory +# 20220524 Fix : Properly URL encode bezel file names +# 20220524 Add : Support symlinks to roms directories and roms themselves +# 20220524 Add : Output unmatched ROMs when requested +# 20220606 Add : Support installing all available systems +# + +readonly VERSION="20220606" +readonly TITLE="the BezelProject for ArchR" +readonly LOGS_DIR="/var/log" +readonly DECORATION_DIR="/storage/roms/bezels" +readonly ROMS_DIR="/storage/roms" +readonly BEZELPROJECT_DIR="thebezelproject" +readonly BEZELPROJECT_GAMES_DIR="$BEZELPROJECT_DIR/games" +readonly BEZELPROJECT_SYSTEMS_DIR="$BEZELPROJECT_DIR/systems" +readonly DEFAULT_BEZEL_URL="https://updates.batocera.org/thebezelproject" +readonly SYSTEMS_LIST="https://updates.batocera.org/tbp_systems.txt" +readonly LOCAL_SYSTEMS_LIST="/storage/.config/system/tbp_systems.txt" +readonly INDEX_LIST="https://updates.batocera.org/thebezelproject/tbp_" +readonly LOCAL_INDEX_LIST="/storage/.config/system/thebezelproject/tbp_" +readonly TMP_SYSTEMS_LIST=`mktemp` +readonly TMP_INDEX_LIST=`mktemp` +readonly TMP_PROGRESS_COUNT=`mktemp` +readonly MAX_NB_WARNING=10 +readonly _BADEXT=(jpg jpeg png bmp psd tga gif hdr pic ppm pgm mkv pdf mp4 avi cbz) +readonly BADEXT="$( IFS="|" ; echo "${_BADEXT[*]}" | sed 's/|/\\|/g' )" +NB_WARNING=0 + +# tbp_systems.txt must be a plain text file with the format +# 'system github_repository bezels_path system_bezel_file' (spaces or tabs) +# Example of tbp_systems.txt file: +# fbneo https://github.com/thebezelproject/bezelproject-MAME MAME MAME-Horizontal.cfg +# snes https://github.com/thebezelproject/bezelproject-SNES SNES Super-Nintendo-Entertainment-System.png + +# tbp_.txt is a plain text file with the format +# 'md5 rom_name' for each rom_name.png (spaces or tabs) +# An external script generates this file for each Batocera system +# available in the BezelProject (with monthly update, i hope) +# Example of tbp_snes.txt file: +# 29aa1cf6a91c472fd0e2db50ebf38 2020 Super Baseball (USA).png + +############################### +# +function usage() { + record "Showing usage for '$TITLE'" + record "$(basename $0) - downloads and installs $TITLE" "2" + record " " "2" + record "It accepts three modes: 'list', 'install' and 'remove' '" "2" + record "- 'list' to list systems installed locally, which are available within TheBezelProject:" "2" + record " [A]vailable to install, [I]nstalled or [?]unknown." "2" + record "- 'install [--show-unmatched]' to install the bezels for this ." "2" + record "- 'install all [--show-unmatched]' to install the bezels for all locally installed supported systems." "2" + record "- 'remove ' to remove the bezels for this ." "2" + record "- 'remove all' to remove all the bezels from TheBezelProject." "2" + record " " "2" + record "If you have a local system list $LOCAL_SYSTEMS_LIST file" "2" + record "and the corresponding index files $LOCAL_INDEX_LIST*.txt" "2" + record "they will override those hosted on Batocera website." "2" + return 1 +} + +############################### +# Cleanup process for exiting +function do_clean() { + record "* Cleanup and exiting" + + # kill job process + if [ -n "$PID" ]; then + record "Killing process: $PID" + kill -9 "$PID" + fi + + # remove temporary files + if [ -f "$TMP_SYSTEMS_LIST" ]; then + record "Removing systems list: $TMP_SYSTEMS_LIST" + rm "$TMP_SYSTEMS_LIST" + fi + + if [ -f "$TMP_INDEX_LIST" ]; then + record "Removing index list: $TMP_INDEX_LIST" + rm "$TMP_INDEX_LIST" + fi + + if [ -f "$TMP_PROGRESS_COUNT" ]; then + record "Removing progress count: $TMP_PROGRESS_COUNT" + rm "$TMP_PROGRESS_COUNT" + fi +} + +############################### +# log messages for debugging +function get_per() { + local system_name=$1 + local roms_filescount=$2 + while true + do + curval=$(cat "$TMP_PROGRESS_COUNT") + local per=$(expr "$curval" '*' 100 / "$roms_filescount") + record "[$system_name] Installing bezels >>> $per%" "2" + sleep 1 + done +} + +############################### +# log messages for debugging +function record() { + local STAMP_TIME="$(date "+%Y-%m-%d %T")" + local backup="$LOGS_DIR"/thebezelproject.log + local message="$1" + local show_msg="$2" + # 0 disables stdout output and enables log + # 1 enables stdout output and enables log + # 2 enables stdout output only + # -1 left empty nothing happens + [[ $show_msg -lt 0 ]] && return + [[ $show_msg -lt 2 ]] && echo "$STAMP_TIME $1" >> "$backup" + [[ $show_msg -gt 0 ]] && echo "$1" +} + +############################### +# check if url format is valid +function check_url() { + [[ "$1" =~ ^(https?|ftp)://.*$ ]] && echo "[A]" || echo "[?]" +} + +############################### +# +function url_encode() { + # Properly escape all URL special characters + local url=$(printf %s "$1" | jq -s -R -r @uri) + echo "$url" +} + +############################### +# return the git name +function git_name() { + echo "$1" | sed "s,.*/\(.*\),\1," +} + +############################### +# return the number of files in a directory +function files_count() { + # we want only files and not those starting with '.' or '_' or "gamelist*" + # support for daphne : there is a sub-folder called roms we want to parse + [[ $(grep "daphne" <<< "$1") && -d "$1"/roms ]] && echo `find "$1"/roms \( -type f -or -type l \) -iname "[!._]*" | wc -l` || echo `find "$1" \( -type f -or -type l \) -iname "[!._]*" -and ! -iname "gamelist*" -and ! -regex ".*\.\($BADEXT\)" | wc -l` +} + +############################### +# +function list() { + local systems_count=0 + local systems_available=0 + local roms_filescount + local system_name + local url + local path + local file + local dir + + record "* List" + record "Path to games bezels $DECORATION_DIR/$BEZELPROJECT_GAMES_DIR" + record "Path to systems bezels $DECORATION_DIR/$BEZELPROJECT_SYSTEMS_DIR" + + # create temporary file for systems list + if [ -f $LOCAL_SYSTEMS_LIST ]; then + record "File for local systems list $LOCAL_SYSTEMS_LIST" + cp -f "$LOCAL_SYSTEMS_LIST" "$TMP_SYSTEMS_LIST" + else + record "File for systems list $SYSTEMS_LIST" + url2="$SYSTEMS_LIST" + # check header only for HTTP 200 (OK) + if [[ $(curl -sIL "$url2" | head -n 1 | grep "200") ]]; then + curl -sfL "$url2" -o "$TMP_SYSTEMS_LIST" + else + record "Error : file $(basename $url2) could not be downloaded from $(dirname $url2)" "1" + return 1 + fi + fi + + # read systems list from configuration file + while IFS=$' \t' read system_name url path file; do + [ -z "$system_name" ] && continue + # Is this line a comment ? + [ "$system_name" = "#" ] && continue + # check if roms/ directory exists + dir=$(readlink -f "$ROMS_DIR/$system_name") + if [ ! -d "$dir" ]; then continue; fi + let systems_count+=1 + record "System #$systems_count $system_name" + # there is at least one ROM in the roms/ directory + roms_filescount=$(files_count "$dir") + if [ "$roms_filescount" -eq 0 ]; then continue; fi + let systems_available+=1 + # check if url is valid and returns [A] or [?] + ia=$(check_url "$url") + # if games/ directory exists, then we assume the bezels are already installed + if [ -d "$DECORATION_DIR/$BEZELPROJECT_GAMES_DIR/$system_name" ]; then ia="[I]"; fi + record "$ia $system_name - $url" "2" + record "$ia $system_name - $url - $path - $file" + done < "$TMP_SYSTEMS_LIST" + record "There are $systems_count systems ($systems_available availables)" + rm "$TMP_SYSTEMS_LIST" +} + +############################### +# +function install() { + local roms_filescount + local roms_count=0 + local systems_count=0 + local system_found=0 + local bezels_installed=0 + local matching_rom + local system_to_install="$1" + local daphne="" + local OS + local TERMINAL + + local git_name + local file_name + local rom_name + local bezel_md5 + + local rom_no_ext + local rom_no_brkts + + local index_ext + local index_no_ext + local index_no_brkts + + local index_bezel_name + local formated_index_bezel_name + local index_bezel_md5 + + local system_name + local url + local url2 + local path + local git_path + local file + + local show_unmatched="$2" + local unmatched=() + local unmatched_count + + record "* Install" + record "Path to games bezels $DECORATION_DIR/$BEZELPROJECT_GAMES_DIR" + record "Path to systems bezels $DECORATION_DIR/$BEZELPROJECT_SYSTEMS_DIR" + + # started from Terminal/SSH or from ES ? + [ -t 1 ] && TERMINAL=1 || TERMINAL=0 + + # create temporary file for systems list + if [ -f $LOCAL_SYSTEMS_LIST ]; then + record "File for local systems list $LOCAL_SYSTEMS_LIST" + cp -f "$LOCAL_SYSTEMS_LIST" "$TMP_SYSTEMS_LIST" + else + record "File for systems list $SYSTEMS_LIST" + url2="$SYSTEMS_LIST" + # check header only for HTTP 200 (OK) + if [[ $(curl -sIL "$url2" | head -n 1 | grep "200") ]]; then + curl -sfL "$url2" -o "$TMP_SYSTEMS_LIST" + else + record "Error : file $(basename $url2) could not be downloaded from $(dirname $url2)" "1" + return 1 + fi + fi + + # read systems list from configuration file + while IFS=$' \t' read system_name url path file; do + [ -z "$system_name" ] && continue + # Is this line a comment ? + [ "$system_name" = "#" ] && continue + let systems_count+=1 + # have we found the system we want to install ? + [ "$system_name" != "$system_to_install" ] && continue + # check if url is valid and return [A] else [?] + ia=$(check_url "$url") + if [ "$ia" != "[A]" ]; then + record "Error : invalid bezels URL $url" "1" + return 1 + else + record "Found system #$systems_count $system_name" + system_found=1 + break + fi + done < "$TMP_SYSTEMS_LIST" + rm "$TMP_SYSTEMS_LIST" + + # In case TheBezelProject doesn't provide the system we want to install + if [ "$system_found" -eq 0 ]; then + record "Error : system $system_to_install could not be found" "1" + return 1 + fi + + # check if roms/ directory exists + dir=$(readlink -f "$ROMS_DIR/$system_to_install") + if [ ! -d "$dir" ]; then + record "Error : ROMs directory for system $system_to_install could not be found" "1" + return 1 + fi + + # check that there is at least one ROM in roms/ directory + roms_filescount=$(files_count "$dir") + record "Found $roms_filescount ROMs in $ROMS_DIR/$system_to_install" + if [ "$roms_filescount" -eq 0 ]; then + record "Error : ROMs directory for system $system_to_install is empty" "1" + return 1 + fi + + # if it doesn't already exist, create the games bezels directory + if [ ! -d "$DECORATION_DIR/$BEZELPROJECT_GAMES_DIR/$system_to_install" ]; then + record "Creating $DECORATION_DIR/$BEZELPROJECT_GAMES_DIR/$system_to_install" + mkdir -p "$DECORATION_DIR/$BEZELPROJECT_GAMES_DIR/$system_to_install" + else + record "Directory $DECORATION_DIR/$BEZELPROJECT_GAMES_DIR/$system_to_install already exist" + fi + + # if it doesn't already exist, create the systems bezels directory + if [ ! -d "$DECORATION_DIR/$BEZELPROJECT_SYSTEMS_DIR" ]; then + record "Creating $DECORATION_DIR/$BEZELPROJECT_SYSTEMS_DIR" + mkdir -p "$DECORATION_DIR/$BEZELPROJECT_SYSTEMS_DIR" + else + record "Directory $DECORATION_DIR/$BEZELPROJECT_SYSTEMS_DIR already exist" + fi + + # create temporary file for index list + if [ -f "$LOCAL_INDEX_LIST$system_to_install.txt" ]; then + record "File for local index list $LOCAL_INDEX_LIST$system_to_install.txt" + cp -f "$LOCAL_INDEX_LIST$system_to_install.txt" "$TMP_INDEX_LIST" + else + record "File for index list $INDEX_LIST$system_to_install.txt" + url2="$INDEX_LIST$system_to_install.txt" + # check header only for HTTP 200 (OK) + if [[ $(curl -sIL "$url2" | head -n 1 | grep "200") ]]; then + curl -sfL "$url2" -o "$TMP_INDEX_LIST" + else + record "Error : file $(basename $url2) could not be downloaded from $(dirname $url2)" "1" + return 1 + fi + fi + + # does the path contains arcade bezels ? + if [ "$path" = "ArcadeBezels" ]; then + git_path="/raw/master/retroarch/overlay/ArcadeBezels/" + else + git_path="/raw/master/retroarch/overlay/GameBezels/$path/" + fi + + # extract git_name from the url + git_name=$(git_name "$url") + record "URL : $url" + record "Git repository : $git_name" + record "Git bezels path : $git_path" + record "Git default bezel file : $file" + record "[$system_to_install] $roms_filescount ROMs found" "1" + + # support for daphne : there is a sub-folder called roms we want to parse + [[ $(grep "daphne" <<< "$system_to_install") && -d "$dir/roms" ]] && daphne="/roms" + + # debug purpose (started from Terminal/SSH vs ES) + #TERMINAL=0 + + if [ "$TERMINAL" -eq 0 ]; then + # start job process (for background refresh) + echo "0" > "$TMP_PROGRESS_COUNT" + PID= + get_per "$system_to_install" "$roms_filescount" & + PID=$! + fi + + # check if running on a Mac or on Busybox + # (Mac for debug purposes, Batocera runs on Linux) + OS=`uname` + + # ******************************************* + # parse ROMs files in system_to_install + while read file_name; do + rom_name=$(basename "$file_name") + rom_no_ext="${rom_name%.*}" + rom_no_brkts="${rom_no_ext%% [*}" + rom_no_brkts="${rom_no_brkts%% (*}" + [ -z "$rom_name" ] && continue + let roms_count+=1 + echo $roms_count > "$TMP_PROGRESS_COUNT" + record "ROM: #$roms_count $rom_name" + + # ********************************************* + # parse index file for maching rom_name + matching_rom=0 + while IFS=$' \t' read index_bezel_md5 index_bezel_name; do + [ -z "$index_bezel_name" ] && continue + index_ext="${index_bezel_name##*.}" + index_no_ext="${index_bezel_name%.*}" + index_no_brkts="${index_no_ext%% [*}" + index_no_brkts="${index_no_brkts%% (*}" + + # ********************* + # is there a match ? + if [ "$rom_no_brkts" = "$index_no_brkts" ]; then + matching_rom=1 + + # ************************************************* + # does the bezel for this game already exist ? + if [ -f "$DECORATION_DIR/$BEZELPROJECT_GAMES_DIR/$system_to_install/$rom_no_ext.$index_ext" ]; then + + # ******************************************************************** + # Check MD5, in case the bezel has been modified/updated ? + if [ $OS = "Darwin" ]; then + # MacOS X version + bezel_md5=$(md5 -q "$DECORATION_DIR/$BEZELPROJECT_GAMES_DIR/$system_to_install/$rom_no_ext.$index_ext") + else + # Busybox version + bezel_md5=$(md5sum "$DECORATION_DIR/$BEZELPROJECT_GAMES_DIR/$system_to_install/$rom_no_ext.$index_ext" | cut -d ' ' -f 1) + fi + + if [ "$bezel_md5" != "$index_bezel_md5" ]; then + # MODIFIED (updated) + record "MODIFIED : $index_bezel_name" + # Clean up the URL for the bezel name + formated_index_bezel_name=$(url_encode "$index_bezel_name") + let bezels_installed+=1 + curl -sfL "$url$git_path$formated_index_bezel_name" -o "$DECORATION_DIR/$BEZELPROJECT_GAMES_DIR/$system_to_install/$rom_no_ext.$index_ext" + if [ "$?" -ne 0 ]; then + record "Warning : file $index_bezel_name could not be downloaded from $url" + let NB_WARNING+=1 + fi + else + # SKIPPED + record "SKIPPED : $index_bezel_name" + fi + + else + # COPIED + record "COPIED : $index_bezel_name" + # Clean up the URL for the bezel name + formated_index_bezel_name=$(url_encode "$index_bezel_name") + let bezels_installed+=1 + curl -sfL "$url$git_path$formated_index_bezel_name" -o "$DECORATION_DIR/$BEZELPROJECT_GAMES_DIR/$system_to_install/$rom_no_ext.$index_ext" + if [ "$?" -ne 0 ]; then + record "Warning : file $index_bezel_name could not be downloaded from $url" + let NB_WARNING+=1 + fi + fi + + # break loop from index (we found a match, go to next ROM) + break + + fi + + done < "$TMP_INDEX_LIST" + + # NOT MATCHING + if [ "$matching_rom" -eq 0 ]; then + record "NOT MATCHING : $rom_name" + [[ -n "$show_unmatched" ]] && unmatched+=("$rom_name") + fi + + # is there too many warning ? + if [ "$NB_WARNING" -gt "$MAX_NB_WARNING" ]; then + record "Error : too many warning ("$MAX_NB_WARNING") while downloading files, exiting..." "1" + break + fi + + # show one line progress count on Terminal/SSH only + if [ "$TERMINAL" -ne 0 ]; then + echo -ne "[$system_to_install] Installing bezel $roms_count / $roms_filescount\r" + fi + + done < <(find "$dir$daphne" \( -type f -or -type l \) -iname "[!._]*" -and ! -iname "gamelist*" -and ! -regex ".*\.\($BADEXT\)") + rm "$TMP_INDEX_LIST" + + if [ "$TERMINAL" -eq 0 ]; then + # kill job process + kill -9 "$PID" + PID= + fi + + if [ "$NB_WARNING" -gt "$MAX_NB_WARNING" ]; then + # sync disk + sync + return 1 + fi + + # summary (only show on stdout if started from Terminal/SSH) + record "[$system_to_install] $bezels_installed bezels ($roms_count ROMs) were installed/modified" "$TERMINAL" + + # install system bezel (i.e. system bezel from TheBezelProject) + record "[$system_to_install] Installing system bezel" "1" + if [ -d "$DECORATION_DIR/$BEZELPROJECT_SYSTEMS_DIR" ]; then + git_path="/raw/master/retroarch/overlay/" + curl -sfL "$url$git_path$file" -o "$DECORATION_DIR/$BEZELPROJECT_SYSTEMS_DIR/$system_to_install.png" + if [ "$?" -ne 0 ]; then + record "Warning : file $file could not be downloaded from $url" + fi + fi + + # install default bezel (i.e default bezel from BATOCERA website) + record "[$system_to_install] Installing default bezel" "1" + if [ -d "$DECORATION_DIR/$BEZELPROJECT_DIR" ]; then + url2="$DEFAULT_BEZEL_URL/default.png" + # check header only for HTTP 200 (OK) + if [[ $(curl -sIL "$url2" | head -n 1 | grep "200") ]]; then + curl -sfL "$url2" -o "$DECORATION_DIR/$BEZELPROJECT_DIR/default.png" + else + record "Warning : file $(basename $url2) could not be downloaded from $(dirname $url2)" + fi + url2="$DEFAULT_BEZEL_URL/default.info" + # check header only for HTTP 200 (OK) + if [[ $(curl -sIL "$url2" | head -n 1 | grep "200") ]]; then + curl -sfL "$url2" -o "$DECORATION_DIR/$BEZELPROJECT_DIR/default.info" + else + record "Warning : file $(basename $url2) could not be downloaded from $(dirname $url2)" + fi + fi + + # If requested (and any roms couldn't be matched), the output the list for easy lookup (only show on stdout if started from Terminal/SSH) + unmatched_count=${#unmatched[@]} + if [[ $unmatched_count != 0 ]]; then + local sorted=() + record "[$system_to_install] $unmatched_count unmatched ROM(s) (check $url$git_path to see if the bezel exists)" "$TERMINAL" + readarray -t sorted < <(for a in "${unmatched[@]}"; do echo "$a"; done | sort) + for (( i=0; i< "$unmatched_count"; i++ )); do + record "$(($i + 1)). ${sorted[$i]}" "$TERMINAL" + done + fi + + # sync disk + sync + + return 0 +} + +############################### +# +function install_all() { + local show_unmatched="$1" + local system + local systems=() + + # List returns the status of each local system one per line + readarray -t systems < <(list) + + record "${#systems[@]} local system(s) found." "2" + + for system_status in "${systems[@]}"; do + system=($system_status) + # The column for the system is the second one + install "${system[1]}" "$show_unmatched" + done +} + +############################### +# +function remove() { + local system_name="$1" + + # do you want to remove all bezels from TheBezelProject ? + record "* Remove" + if [ "$system_name" = "all" ]; then + if [ -d "$DECORATION_DIR/$BEZELPROJECT_DIR" ]; then + read -p "Do you wish to remove all bezels from TheBezelProject ? " yn + if [[ "$yn" = "y" || "$yn" = "Y" ]]; then + # all TheBezelProject sub-directories + rm -rf "$DECORATION_DIR/$BEZELPROJECT_DIR" + record "Deleting directory : $DECORATION_DIR/$BEZELPROJECT_DIR" + fi + else + record "Error : bezels directory $DECORATION_DIR/$BEZELPROJECT_DIR is not valid" "1" + return 1 + fi + else + # check if games/ directory exists + if [ ! -d "$DECORATION_DIR/$BEZELPROJECT_GAMES_DIR/$system_name" ]; then + record "Error : bezels for system $system_name could not be found" "1" + return 1 + else + # games bezels + rm -rf "$DECORATION_DIR/$BEZELPROJECT_GAMES_DIR/$system_name" + record "Deleting directory : $DECORATION_DIR/$BEZELPROJECT_GAMES_DIR/$system_name" + # system bezels + rm -f "$DECORATION_DIR/$BEZELPROJECT_SYSTEMS_DIR/$system_name.png" + record "Deleting file : $DECORATION_DIR/$BEZELPROJECT_SYSTEMS_DIR/$system_name.png" + # default bezel + rm -f "$DECORATION_DIR/$BEZELPROJECT_DIR/default.*" + record "Deleting files : $DECORATION_DIR/$BEZELPROJECT_DIR/default.*" + fi + fi + + # sync disk + sync + + return 0 +} + +############################### +#### Main loop +# +command="$1" +system="$2" + +trap do_clean EXIT +record "Starting script v$VERSION" + +if [ ! -d "$DECORATION_DIR" ]; then + record "Error : decorations directory $DECORATION_DIR is not valid" "1" + exit 1 +fi + +if [[ "$command" = "list" ]]; then + list +elif [[ "$command" = "install" && -n "$system" ]]; then + if [[ -n "$3" && "$3" != "--show-unmatched" ]]; then + record "Error : unknown argument for install: $3" "1" + record "" "1" + usage + elif [[ "$system" = "all" ]]; then + install_all "$3" + else + install "$system" "$3" + fi +elif [[ "$command" = "remove" && -n "$system" ]]; then + remove "$system" +else + usage +fi diff --git a/projects/ArchR/packages/archr/sources/scripts/archr-fake-suspend b/projects/ArchR/packages/archr/sources/scripts/archr-fake-suspend new file mode 100755 index 0000000000..02ace82f03 --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/archr-fake-suspend @@ -0,0 +1,434 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025-present ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile + +### Enable logging +case $(get_setting system.loglevel) in +verbose) + DEBUG=true + ;; +*) + DEBUG=false + ;; +esac + +check_hardware_suspend_enabled() { + local SUSPEND_MODE="$(get_setting system.suspendmode)" + + if [[ "${SUSPEND_MODE}" != "off" ]]; then + return 0 + else + return 1 + fi +} + +check_hdmi_connected() { + for status_file in /sys/class/drm/card*-HDMI-A-[0-9]/status; do + if [[ -f "$status_file" ]]; then + local HDMI_STATUS=$(cat "$status_file") + if [[ "${HDMI_STATUS}" = "connected" ]]; then + return 0 + fi + fi + done + + return 1 +} + +check_charging() { + local CHARGE_STATUS=$(cat /sys/class/power_supply/battery/status) + + if [[ "${CHARGE_STATUS}" = "Charging" ]]; then + return 0 + else + return 1 + fi +} + +check_es_running_game() { + local HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "http://localhost:1234/runningGame") + ${DEBUG} && log $0 "ES runningGame HTTP_STATUS - ${HTTP_STATUS}" + test $? != 0 && return 1 # call failed, assume no game running + test "${HTTP_STATUS}" = 201 && return 1 # 201 when no game running + test "${HTTP_STATUS}" = 200 && return 0 # 200 when game running +} + +display_off() { + if [[ "${ENABLE_DPMS}" == "1" ]]; then + # DPMS enabled, use it to turn off the display + ${DEBUG} && log $0 "DPMS - display off" + + if echo "${UI_SERVICE}" | grep "sway"; then + ${DEBUG} && log $0 "Display power off" + swaymsg "output * power off" + elif echo "${UI_SERVICE}" | grep "weston"; then + weston-dpms -m off + fi + else + # DPMS disabled, just turn off the backlight + ${DEBUG} && log $0 "Backlight off" + + for BL_POWER_DEVICE in "${BL_POWER_DEVICES[@]}"; do + echo 4 > "${BL_POWER_DEVICE}" + done + fi +} + +display_on() { + if [[ "${ENABLE_DPMS}" == "1" ]]; then + # DPMS enabled, use it to turn on the display + ${DEBUG} && log $0 "DPMS - display on" + + if echo "${UI_SERVICE}" | grep "sway"; then + ${DEBUG} && log $0 "Display power on" + swaymsg "output * power on" + elif echo "${UI_SERVICE}" | grep "weston"; then + weston-dpms -m on + fi + else + # DPMS disabled, just turn on the backlight + ${DEBUG} && log $0 "Backlight on" + + for BL_POWER_DEVICE in "${BL_POWER_DEVICES[@]}"; do + echo 0 > "${BL_POWER_DEVICE}" + done + fi +} + +mute_audio() { + ${DEBUG} && log $0 "Mute audio" + pactl set-sink-mute @DEFAULT_SINK@ true +} + +unmute_audio() { + ${DEBUG} && log $0 "Unmute audio" + pactl set-sink-mute @DEFAULT_SINK@ false +} + +disable_leds() { + ${DEBUG} && log $0 "disable leds" + /usr/bin/ledcontrol poweroff +} + +enable_leds() { + ${DEBUG} && log $0 "restore leds" + LED_STATE=$(get_setting "led.color") + /usr/bin/ledcontrol ${LED_STATE} +} + +powersave_governors() { + ${DEBUG} && log $0 "Set CPU/GPU governors to powersave" + + # Get the current cpu and gpu governor, save for restoration on resume + local CURR_CPU_GOVERNOR="$(cat ${CPU_FREQ}/scaling_governor)" + local CURR_GPU_GOVERNOR="$(cat ${GPU_FREQ}/governor)" + + set_setting sleep.cpugovernor "${CURR_CPU_GOVERNOR}" + set_setting sleep.gpugovernor "${CURR_GPU_GOVERNOR}" + + # Set all governors to powersave + set_cpu_gov powersave + set_gpu_gov powersave +} + +restore_governors() { + ${DEBUG} && log $0 "Restore CPU/GPU governors" + + # Grab the old governors + local PRE_SUSPEND_CPU_GOVERNOR=$(get_setting "sleep.cpugovernor") + [[ -z "${PRE_SUSPEND_CPU_GOVERNOR}" ]] && PRE_SUSPEND_CPU_GOVERNOR="ondemand" + + local PRE_SUSPEND_GPU_GOVERNOR=$(get_setting "sleep.gpugovernor") + [[ -z "${PRE_SUSPEND_GPU_GOVERNOR}" ]] && PRE_SUSPEND_GPU_GOVERNOR="simple_ondemand" + + # Restore old governors + set_cpu_gov "${PRE_SUSPEND_CPU_GOVERNOR}" + set_gpu_gov "${PRE_SUSPEND_GPU_GOVERNOR}" + + # Clean up + del_setting "sleep.cpugovernor" + del_setting "sleep.gpugovernor" +} + +park_cores() { + ${DEBUG} && log $0 "CPU core parking" + for x in /sys/devices/system/cpu/cpu*/online; do + if [[ ! $(echo "${x}" | grep "cpu0") ]]; then + echo 0 > "${x}" + fi + done +} + +unpark_cores() { + ${DEBUG} && log $0 "Undo CPU core parking" + for x in /sys/devices/system/cpu/cpu*/online; do + echo 1 > "${x}" + done +} + +block_input() { + for x in /dev/input/event*; do + local EVENT_INPUT=$(echo ${x} | awk 'BEGIN{FS="/"} {print $NF}') + local DEVICE_NAME=$(cat /sys/class/input/$EVENT_INPUT/device/name) + + # If device is not in whitelist, block input + local FOUND=0 + for WHITELIST_DEVICE in "${INPUT_WHITELIST[@]}"; do + if [[ "${WHITELIST_DEVICE}" = "${DEVICE_NAME}" ]]; then + FOUND=1 + break + fi + done + + if (( ! ${FOUND})); then + ${DEBUG} && log $0 "Blocking input for ${x} - ${DEVICE_NAME}" + /usr/bin/evtest --grab ${x} > /dev/null & + fi + done +} + +unblock_input() { + ${DEBUG} && log $0 "Unblocking input" + for x in $(pgrep -f "evtest --grab"); do + kill -9 ${x} + done +} + +do_suspend_actions() { + # Turn off display + display_off + + # Mute audio + mute_audio + + # Set CPU / GPU governors + powersave_governors + + # CPU core parking (if enabled) + [[ "${ENABLE_CORE_PARKING}" == "1" ]] && park_cores + + # Block input + block_input + + # Disable LEDs + disable_leds +} + +do_resume_actions() { + # Turn on display + display_on + + # Unmute audio + unmute_audio + + # Restore CPU / GPU governors + restore_governors + + # Undo CPU core parking (if enabled) + [[ "${ENABLE_CORE_PARKING}" == "1" ]] && unpark_cores + + # Unblock input + unblock_input + + # Restore LEDs + enable_leds +} + +do_shutdown() { + # Check if HDMI has been connected while suspended + check_hdmi_connected + local HDMI_CONNECTED=$? + + if [[ $HDMI_CONNECTED -eq 0 ]]; then + ${DEBUG} && log $0 "HDMI connected, not shutting down" + return 0 + fi + + # Check if charger has been connected while suspended + check_charging + local CHARGING=$? + + if [[ $CHARGING -eq 0 ]]; then + ${DEBUG} && log $0 "Charging, not shutting down" + return 0 + fi + + # Unmute audio - otherwise wireplumber will keep it muted on next boot + unmute_audio + + # Check whether a game is running + check_es_running_game + local RUNNING_GAME=$? + + if [[ $RUNNING_GAME -eq 0 ]]; then + # ES shutdown API won't work if a game is running + ${DEBUG} && log $0 "Shutting down now" + shutdown now + else + # Use ES shutdown API so metadata is saved + ${DEBUG} && log $0 "Shutting down via ES API" + curl "http://localhost:1234/shutdown" + fi +} + +suspend() { + # Create delay flag file + ${DEBUG} && log $0 "Creating ${DELAY_FLAG_FILE}" + touch "${DELAY_FLAG_FILE}" + + check_es_running_game + local RUNNING_GAME=$? + + check_charging + local CHARGING=$? + + # Determine shutdown delay + local DELAY=${SHUTDOWN_DELAY} + [[ $RUNNING_GAME -eq 0 ]] && DELAY=${SHUTDOWN_DELAY_RUNNING_GAME} + ${DEBUG} && log $0 "Shutdown delay - ${DELAY} seconds" + [[ ${CHARGING} -eq 0 ]] && ${DEBUG} && log $0 "Charging ..." + + if [[ "${DELAY}" -gt 0 || ${CHARGING} -eq 0 ]]; then + do_suspend_actions + fi + + # Delay shutdown + sleep ${DELAY} + + # Delay has completed - check whether the flag file is still present + if [[ -f "${DELAY_FLAG_FILE}" ]]; then + ${DEBUG} && log $0 "Delay expired, flag file found" + # Flag present - shutdown + do_shutdown + else + ${DEBUG} && log $0 "Delay expired, flag file not found" + fi +} + +resume() { + # Resume event - remove all flag files and kill processes + ${DEBUG} && log $0 "Removing flags" + rm -f "${DELAY_FLAG_FILE_PATTERN}".* + rm -f "${POWER_SUSPEND_ACTIVE_FLAG_FILE}" + rm -f "${LID_CLOSED_FLAG_FILE}" + + # Do resume actions + do_resume_actions + + ${DEBUG} && log $0 "Resume - killing ${TO_KILL} processes" + killall ${TO_KILL} +} + +# Main logic +# Only do something when hardware suspend is disabled +check_hardware_suspend_enabled +HW_SUSPEND_ENABLED=$? + +if [[ $HW_SUSPEND_ENABLED -eq 0 ]]; then + ${DEBUG} && log $0 "Hardware suspend enabled, exiting" + exit 0 +fi + +# If a game is not running, by default delay the shutdown for 15 minutes +SHUTDOWN_DELAY="$(get_setting system.shutdown_delay)" +[[ "${SHUTDOWN_DELAY}" = "" ]] && SHUTDOWN_DELAY=900 + +# If a game is running, by default delay the shutdown for 15 minutes +SHUTDOWN_DELAY_RUNNING_GAME="$(get_setting system.shutdown_delay_running_game)" +[[ "${SHUTDOWN_DELAY_RUNNING_GAME}" = "" ]] && SHUTDOWN_DELAY_RUNNING_GAME=900 + +# On suspend, should CPU cores be parked +ENABLE_CORE_PARKING="$(get_setting system.suspend.park_cores)" +[[ "${ENABLE_CORE_PARKING}" = "" ]] && ENABLE_CORE_PARKING="1" + +# On suspend, should DPMS be used +ENABLE_DPMS="$(get_setting system.suspend.dpms)" +[[ "${ENABLE_DPMS}" = "" ]] && ENABLE_DPMS="1" + +# flag files +PID=$$ +DELAY_FLAG_FILE_PATTERN="/var/run/shutdown-delay.flag" +DELAY_FLAG_FILE="${DELAY_FLAG_FILE_PATTERN}.${PID}" +POWER_SUSPEND_ACTIVE_FLAG_FILE="/var/run/power-fake-suspend-active.flag" +LID_CLOSED_FLAG_FILE="/var/run/lid-closed.flag" + +# Process to kill +TO_KILL="archr-fake-suspend" + +# Lid / power button - event input device whitelist +INPUT_WHITELIST=( + # H700 + "axp20x-pek" \ + "gpio-keys-lid" \ + # S922X + "rk805 pwrkey" \ + # SM8550 + "pmic_pwrkey" +) + +# Ayn Thor gpio-keys contains lid events +[[ "${QUIRK_DEVICE}" == "AYN Thor" ]] && INPUT_WHITELIST+=("gpio-keys") + +# Backlight power devices +declare -a BL_POWER_DEVICES=() +while IFS= read -r line; do + BL_POWER_DEVICES+=("$line") +done < <(find /sys/class/backlight/*/ -name bl_power 2>/dev/null) + +# Source = power / lid +SOURCE=$1 + +# Action = open / close +ACTION=$2 + +# Check if HDMI is connected +check_hdmi_connected +HDMI_CONNECTED=$? + +# Handle event +if [[ "${SOURCE}" = "power" ]]; then + ${DEBUG} && log $0 "Power button pressed ..." + + if [[ -f "${LID_CLOSED_FLAG_FILE}" ]]; then + ${DEBUG} && log $0 "Lid closed - no action" + elif [[ -f "${POWER_SUSPEND_ACTIVE_FLAG_FILE}" ]]; then + # In a 'suspend' state from power button, 'resume' + ${DEBUG} && log $0 "Power suspend active - resuming" + resume + else + if [[ $HDMI_CONNECTED -eq 0 ]]; then + ${DEBUG} && log $0 "HDMI connected, not suspending" + else + # Create flag file and suspend + ${DEBUG} && log $0 "Suspending" + touch ${POWER_SUSPEND_ACTIVE_FLAG_FILE} + suspend + fi + fi +elif [[ "${SOURCE}" = "lid" && "${ACTION}" = "close" ]]; then + ${DEBUG} && log $0 "Lid closed ..." + touch ${LID_CLOSED_FLAG_FILE} + + if [[ -f "${POWER_SUSPEND_ACTIVE_FLAG_FILE}" ]]; then + # In a 'suspend' state from power button, do nothing + ${DEBUG} && log $0 "Power suspend active - no action" + else + if [[ $HDMI_CONNECTED -eq 0 ]]; then + ${DEBUG} && log $0 "HDMI connected, not suspending" + else + # Suspend + ${DEBUG} && log $0 "Suspending" + suspend + fi + fi +elif [[ "${SOURCE}" = "lid" && "${ACTION}" = "open" ]]; then + rm -f "${LID_CLOSED_FLAG_FILE}" + + # Always resume on lid open - regardless of suspend source + ${DEBUG} && log $0 "Lid opened - resuming" + resume +fi + +exit 0 \ No newline at end of file diff --git a/projects/ArchR/packages/archr/sources/scripts/archr-info b/projects/ArchR/packages/archr/sources/scripts/archr-info new file mode 100755 index 0000000000..53fe4eae64 --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/archr-info @@ -0,0 +1,187 @@ +#!/bin/bash + +source /etc/profile + +### Apply device quirks +if [ -e "/sys/firmware/devicetree/base/model" ] +then + export QUIRK_DEVICE="$(tr -d '\0' /dev/null)" +else + export QUIRK_DEVICE="$(tr -d '\0' /dev/null) $(tr -d '\0' /dev/null)" +fi +export QUIRK_DEVICE="$(echo ${QUIRK_DEVICE} | sed -e "s#[/]#-#g")" + +info_quirks() { + for QUIRK in /usr/lib/autostart/quirks/platforms/"${HW_DEVICE}"/info.d/${1}/* \ + /usr/lib/autostart/quirks/devices/"${QUIRK_DEVICE}"/info.d/${1}/* + do + "${QUIRK}" 2>/dev/null + done +} + +### short version (for osd) +if test "$1" = "--short" +then + BATT=$(awk 'BEGIN {FS="="} /POWER_SUPPLY_CAPACITY=/ {print $2; exit}' /sys/class/power_supply/[Bb][Aa][Tt]*/uevent 2>/dev/null) + DT=$(date +%H:%M) + if test -n "${BATT}" + then + echo "Battery: ${BATT}% - ${DT}" + else + echo "${DT}" + fi + exit 0 +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}" + +# network +ip=$(ip -4 addr show dev eth0 2>/dev/null | grep inet | awk '{print $2}' | cut -d/ -f1) +if [ -z "$ip" ]; then + WIFI_DEV="$({ ls /sys/class/net; echo wlan0; } | grep -m1 ^wlan)" + ip=$(ip -4 addr show dev ${WIFI_DEV} 2>/dev/null | grep inet | awk '{print $2}' | cut -d/ -f1) +fi +if [ -z "$ip" ]; then + ip="Offline" +fi + +host=$(hostname) + +# gpu +CUR_FREQ=$(cat "$GPU_FREQ/cur_freq") +MAX_FREQ=$(cat "$GPU_FREQ/max_freq") +GPUCUR=$((CUR_FREQ / 1000000)) +GPUMAX=$((MAX_FREQ / 1000000)) + +# ram +MEMT=$(grep MemTotal /proc/meminfo | sed 's/[^0-9]*//g') +MEMT=$((${MEMT} / 1000)) +MEMAV=$(grep MemAvailable /proc/meminfo | sed 's/[^0-9]*//g') +MEMAV=$((${MEMAV} / 1000)) + +# battery +BATT=$(awk 'BEGIN {FS="="} /POWER_SUPPLY_CAPACITY=/ {print $2; exit}' /sys/class/power_supply/[Bb][Aa][Tt]*/uevent 2>/dev/null) + +case ${HW_ARCH} in + aarch64) + declare -a CF MF + + CNTR=0 + for CPUFREQ in /sys/devices/system/cpu/cpufreq/* + do + if [[ "${CPUFREQ}" =~ boost ]] + then + continue + fi + if [ "${CNTR}" -eq 0 ] + then + CF+=("CURRENT FREQUENCY:") + MF+=("MAXIMUM FREQUENCY:") + fi + RELCPUS=$(cat ${CPUFREQ}/related_cpus 2>/dev/null) + if [ "${#RELCPUS}" -gt 1 ] + then + FIELD="$(cat ${CPUFREQ}/related_cpus 2>/dev/null | awk '{print $1"-"$NF}')" + else + FIELD="$(cat ${CPUFREQ}/related_cpus 2>/dev/null)" + fi + if [ -e "${CPUFREQ}/scaling_cur_freq" ]; then + CF+=("THREADS ${FIELD}: $(( $(cat ${CPUFREQ}/scaling_cur_freq 2>/dev/null | sort | tail -n 1) / 1000))MHz") + fi + if [ -e "${CPUFREQ}/scaling_max_freq" ]; then + MF+=("THREADS ${FIELD}: $(( $(cat ${CPUFREQ}/scaling_max_freq 2>/dev/null | sort | tail -n 1) / 1000))MHz") + fi + CNTR=$(( CNTR + 1 )) + done + ;; +esac + +echo "SYSTEM INFORMATION:" +echo "DEVICE: ${QUIRK_DEVICE}" +echo "OPERATING SYSTEM: ${OS_NAME}" +echo "VERSION: ${OS_VERSION} (${OS_BUILD})" +echo "BUILD ID: ${BUILD_ID:0:7} (${BUILD_BRANCH})" +echo "KERNEL: ${V_SYSTEM} ($(uname -m))" +echo "NETWORK INFORMATION:" +echo "HOST NAME: ${host}" +echo "IP ADDRESS: ${ip}" +echo "DISK SPACE:" +echo "/storage/games-internal: $(df -h /storage/games-internal | awk '/dev/ {print $3"/"$2" ("$5")"}')" +echo "/storage/games-external: $(df -h /storage/games-external | awk '/dev/ {print $3"/"$2" ("$5")"}')" + +if test -n "${BATT}" +then + echo "BATTERY INFORMATION:" + echo "BATTERY REMAINING: ${BATT}%" + BAT_HEALTH=$(cat /sys/class/power_supply/[Bb][Aa][Tt]*/health 2>/dev/null) + if [ -n "${BAT_HEALTH}" ] + then + echo "BATTERY HEALTH: ${BAT_HEALTH}" + fi + BAT_STATUS=$(cat /sys/class/power_supply/[Bb][Aa][Tt]*/status 2>/dev/null) + if [ -n "${BAT_STATUS}" ] + then + echo "BATTERY STATE: ${BAT_STATUS}" + fi +fi +echo "CPU INFORMATION:" +echo "CPU: ${V_CPUMODEL1} (${V_CPUNB} Cores)" + +# temperature +# Unit: millidegree Celsius +if [ -n "${DEVICE_TEMP_SENSOR}" ] +then + TEMPE=$(awk '{total += $1; count++} END {printf "%d", total/count/1000}' ${DEVICE_TEMP_SENSOR}) + if [ -n "${TEMPE}" ] + then + echo "CPU TEMPERATURE: ${TEMPE}°" + fi +fi + +if [ "${DEVICE_HAS_FAN}" = "true" ] +then + FANSPEED=$(cat ${DEVICE_FAN_INPUT} 2>/dev/null) + if [ "${FANSPEED}" = "0" ] + then + FANSPEED="OFF" + else + FANSPEED="${FANSPEED} RPM" + fi + echo "CPU FAN: ${FANSPEED}" +fi +case ${HW_ARCH} in + aarch64) + for C in "${CF[@]}" + do + echo ${C} + done + for M in "${MF[@]}" + do + echo ${M} + done + ;; +esac +if [ -n "$GPUCUR" ]; then + echo "GPU INFORMATION:" +# GPU temperature +# Unit: millidegree Celsius + if [ -n "${DEVICE_GPU_TEMP_SENSOR}" ]; then + GTEMPE=$(awk '{total += $1; count++} END {printf "%d", total/count/1000}' ${DEVICE_GPU_TEMP_SENSOR}) + if [ -n "${GTEMPE}" ]; then + echo "GPU TEMPERATURE: ${GTEMPE}°" + fi +fi + echo "GPU CURRENT FREQUENCY: ${GPUCUR} MHz" + echo "GPU MAXIMUM FREQUENCY: ${GPUMAX} MHz" +fi +echo "RAM INFORMATION:" +echo "RAM AVAILABLE: ${MEMAV} MB" +echo "RAM CAPACITY: ${MEMT} MB" + +info_quirks diff --git a/projects/ArchR/packages/archr/sources/scripts/archr-keyboard b/projects/ArchR/packages/archr/sources/scripts/archr-keyboard new file mode 100755 index 0000000000..fef3f314cd --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/archr-keyboard @@ -0,0 +1,97 @@ +#!/bin/bash + +. /etc/profile.d/001-functions + +RULES_FILE="/usr/share/X11/xkb/rules/base.lst" +CONF_KEY_LAYOUT="system.kblayout" +CONF_KEY_VARIANT="system.kbvariant" + +# Check to make sure the rules file exists +if [ ! -f "$RULES_FILE" ]; then + echo "Error: $RULES_FILE not found" >&2 + exit 1 +fi + +function get_current_layout() { + local val=$(get_setting "$CONF_KEY_LAYOUT") + if [ -z "$val" ]; then echo "us"; else echo "$val"; fi +} + +function get_current_variant() { + local val=$(get_setting "$CONF_KEY_VARIANT") + if [ -z "$val" ] || [ "$val" == "none" ]; then echo ""; else echo "$val"; fi +} + +function list_layouts() { + awk ' + BEGIN { in_section=0 } + /^! layout/ { in_section=1; next } + /^!/ { in_section=0 } + in_section && NF > 0 { + code=$1; + $1=""; + sub(/^ */, "", $0); + print code " " $0 + } + ' "$RULES_FILE" | sort -k2 +} + +function list_variants() { + local layout="$1" + + # If no argument, get from config + if [ -z "$layout" ]; then + layout=$(get_current_layout) + fi + + if [ -z "$layout" ]; then return; fi + + awk -v layout="$layout" ' + BEGIN { in_section=0 } + /^! variant/ { in_section=1; next } + /^!/ { in_section=0 } + in_section && NF > 0 { + if ($2 == layout":") { + code=$1; + $1=""; $2=""; + sub(/^ */, "", $0); + print code " " $0 + } + } + ' "$RULES_FILE" | sort -k2 +} + +case "$1" in + list-layouts) + list_layouts + ;; + list-variants) + list_variants "$2" + ;; + get) + L=$(get_current_layout) + V=$(get_current_variant) + echo "$L $V" + ;; + set) + LAYOUT="$2" + VARIANT="$3" + + if [ -z "$LAYOUT" ]; then LAYOUT="us"; fi + if [ "$VARIANT" == "none" ] || [ -z "$VARIANT" ]; then VARIANT=""; fi + + set_setting "$CONF_KEY_LAYOUT" "$LAYOUT" + set_setting "$CONF_KEY_VARIANT" "$VARIANT" + + # Try to apply immediately (Runtime) + # We check if setxkbmap exists. This works for X11. + if command -v setxkbmap > /dev/null; then + setxkbmap -layout "$LAYOUT" -variant "$VARIANT" 2>/dev/null || true + fi + + ;; + *) + echo "Usage: $0 {list-layouts|list-variants [layout]|get|set }" + exit 1 + ;; +esac diff --git a/projects/ArchR/packages/archr/sources/scripts/archr-memory-manager b/projects/ArchR/packages/archr/sources/scripts/archr-memory-manager new file mode 100755 index 0000000000..a569ed5734 --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/archr-memory-manager @@ -0,0 +1,598 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2026-present Joel Wirāmu Pauling +# Copyright (C) 2026-present ArchR (https://arch-r.io) + +# ArchR Memory Manager +# Logic: 0/Empty = Off, "Auto" = Smart Calculation, "Resume" = Hibernation Sizing. + +# --- 1. CONFIGURATION CASCADE --- + +# A. Internal Safe Defaults (Hardcoded Fallback) +DEFAULT_ZRAM_SIZE="0" +DEFAULT_ZRAM_ALGO="zstd" +DEFAULT_SWAP_FILE_SIZE="0" +DEFAULT_SWAP_PRIORITY="auto" +DEFAULT_VM_WATERMARK_FACTOR="auto" +DEFAULT_VM_COMPACTION="auto" +DEFAULT_KSM_ENABLE="auto" + +# B. Load System Defaults (Distro Config) +if [ -f /etc/swap.conf ]; then + . /etc/swap.conf +fi + +# C. Load User Overrides (Partial Config Support) +if [ -f /storage/.config/swap.conf ]; then + . /storage/.config/swap.conf +fi + +# D. Variable Finalization +ZRAM_SIZE="${ZRAM_SIZE:-$DEFAULT_ZRAM_SIZE}" +ZRAM_ALGO="${ZRAM_ALGO:-$DEFAULT_ZRAM_ALGO}" +SWAP_FILE_SIZE="${SWAP_FILE_SIZE:-$DEFAULT_SWAP_FILE_SIZE}" +SWAP_PRIORITY="${SWAP_PRIORITY:-$DEFAULT_SWAP_PRIORITY}" +VM_WATERMARK_FACTOR="${VM_WATERMARK_FACTOR:-$DEFAULT_VM_WATERMARK_FACTOR}" +VM_COMPACTION="${VM_COMPACTION:-$DEFAULT_VM_COMPACTION}" +KSM_ENABLE="${KSM_ENABLE:-$DEFAULT_KSM_ENABLE}" + +# --- 2. ENVIRONMENT & TIER DETECTION --- + +# Source environment to ensure HW_DEVICE is available +if [ -f /etc/profile ]; then + . /etc/profile +fi + +# Global RAM calc (MB) +TOTAL_MEM_KB=$(awk '/MemTotal/ {print $2}' /proc/meminfo) +TOTAL_MEM_MB=$((TOTAL_MEM_KB / 1024)) + +# RAM Tiers +IS_LOW_RAM=false +IS_MID_RAM=false +IS_HIGH_RAM=false + +if [ "$TOTAL_MEM_MB" -lt 2048 ]; then + IS_LOW_RAM=true +elif [ "$TOTAL_MEM_MB" -le 8192 ]; then + IS_MID_RAM=true +else + IS_HIGH_RAM=true +fi + +# SoC Capability Tiers +# Detect High Performance SoCs that can handle aggressive background ops (KSM/Compaction) +# even with lower RAM. +IS_HIGH_PERF_SOC=false + +if [[ "${HW_DEVICE,,}" =~ rk3588|sm8|s922x|g12b|rk3399 ]]; then + IS_HIGH_PERF_SOC=true +fi + +# Basic mount check +if ! mountpoint -q /storage; then + if [[ "$*" != *"--help"* ]]; then + logger -t memory-manager "Error: /storage is not mounted." + exit 1 + fi +fi + +# --- 3. HELPER FUNCTIONS --- + +update_config() { + local key="$1" + local val="$2" + local file="/storage/.config/swap.conf" + + if [ ! -d "$(dirname "$file")" ]; then mkdir -p "$(dirname "$file")"; fi + if [ ! -f "$file" ]; then touch "$file"; fi + + if grep -q "^${key}=" "$file"; then + sed -i "s|^${key}=.*|${key}=\"${val}\"|" "$file" + else + echo "${key}=\"${val}\"" >> "$file" + fi + eval "${key}=\"${val}\"" +} + +show_status_json() { + # Generate machine-readable status + local ksm_status="false" + local ksm_saved=0 + if [ -f /sys/kernel/mm/ksm/run ] && [ "$(cat /sys/kernel/mm/ksm/run)" -eq 1 ]; then + ksm_status="true" + local sharing=$(cat /sys/kernel/mm/ksm/pages_sharing 2>/dev/null || echo 0) + ksm_saved=$(( (sharing * 4096) / 1024 / 1024 )) + fi + + local zram_enabled="false" + local zram_compr=0 + if [ -d /sys/block/zram0 ]; then + zram_enabled="true" + local stat=($(cat /sys/block/zram0/mm_stat 2>/dev/null)) + if [ ${#stat[@]} -ge 3 ]; then + zram_compr=$((stat[1] / 1024 / 1024)) + fi + fi + + local ram_tier="high" + [ "$IS_LOW_RAM" = true ] && ram_tier="low" + [ "$IS_MID_RAM" = true ] && ram_tier="mid" + + echo "{" + echo " \"ram_total_mb\": $TOTAL_MEM_MB," + echo " \"tier_ram\": \"$ram_tier\"," + echo " \"tier_soc\": \"$([ "$IS_HIGH_PERF_SOC" = true ] && echo "high" || echo "standard")\"," + echo " \"zram\": {" + echo " \"enabled\": $zram_enabled," + echo " \"size_mb\": $ZRAM_SIZE_VAL," + echo " \"algo\": \"$ZRAM_ALGO\"," + echo " \"compressed_size_mb\": $zram_compr" + echo " }," + echo " \"swap\": {" + echo " \"size_mb\": $SWAP_SIZE_VAL," + echo " \"priority\": \"$SWAP_PRIORITY\"" + echo " }," + echo " \"ksm\": {" + echo " \"enabled\": $ksm_status," + echo " \"saved_mb\": $ksm_saved" + echo " }" + echo "}" +} + +show_status() { + echo "--- ArchR Memory Manager Status ---" + printf "System RAM: %s MB\n" "$TOTAL_MEM_MB" + printf "RAM Tier: %s\n" "$([ "$IS_LOW_RAM" = true ] && echo "Low" || ([ "$IS_MID_RAM" = true ] && echo "Mid" || echo "High"))" + printf "SoC Tier: %s\n" "$([ "$IS_HIGH_PERF_SOC" = true ] && echo "High Performance" || echo "Standard")" + printf "ZRAM Config: %s [%s]\n" "$ZRAM_STATUS" "$ZRAM_ALGO" + printf "Swap Config: %s [Mode: %s]\n" "$SWAP_STATUS" "$SWAP_PRIORITY" + echo "" + echo "[ Tier 1: ZRAM Statistics ]" + if [ -d /sys/block/zram0 ]; then + local stat=($(cat /sys/block/zram0/mm_stat 2>/dev/null)) + if [ ${#stat[@]} -ge 3 ]; then + local orig=$((stat[0] / 1024 / 1024)) + local compr=$((stat[1] / 1024 / 1024)) + local total=$((stat[2] / 1024 / 1024)) + printf " Original Data: %s MB\n" "$orig" + printf " Compressed: %s MB\n" "$compr" + printf " Memory Used: %s MB\n" "$total" + [ "$compr" -gt 0 ] && printf " Ratio: %.2f:1\n" "$(echo "scale=2; $orig / $compr" | bc)" + fi + [ -f /sys/block/zram0/comp_algorithm ] && printf " Algorithms: %s\n" "$(cat /sys/block/zram0/comp_algorithm)" + else + echo " ZRAM device not initialized." + fi + echo "" + echo "[ Tier 2: Physical Swap ]" + swapon --show | grep -v "NAME" || echo " No physical swap active." + echo "" + echo "[ Memory Subsystem ]" + # KSM + if [ -f /sys/kernel/mm/ksm/run ]; then + local ksm_run=$(cat /sys/kernel/mm/ksm/run) + local ksm_status="Stopped" + [ "$ksm_run" -eq 1 ] && ksm_status="Running" + if [ "$ksm_run" -eq 1 ]; then + local sharing=$(cat /sys/kernel/mm/ksm/pages_sharing 2>/dev/null || echo 0) + local saved=$(( (sharing * 4096) / 1024 / 1024 )) + printf " KSM Status: %s (Saved: %s MB)\n" "$ksm_status" "$saved" + printf " KSM Setting: %s\n" "$KSM_ENABLE" + else + printf " KSM Status: %s\n" "$ksm_status" + fi + else + echo " KSM Status: Absent" + fi + + # MGLRU + if [ -f /sys/kernel/mm/lru_gen/enabled ]; then + printf " MGLRU: Enabled [0x%s]\n" "$(cat /sys/kernel/mm/lru_gen/enabled)" + else + printf " MGLRU: Absent\n" + fi + + # THP + if [ -f /sys/kernel/mm/transparent_hugepage/enabled ]; then + local thp=$(grep -o '\[.*\]' /sys/kernel/mm/transparent_hugepage/enabled | tr -d '[]') + local defrag=$(grep -o '\[.*\]' /sys/kernel/mm/transparent_hugepage/defrag | tr -d '[]') + printf " Huge Pages: %s (Defrag: %s)\n" "$thp" "$defrag" + else + printf " Huge Pages: Absent\n" + fi + + echo "" + echo "[ Advanced Tuning ]" + sysctl vm.swappiness \ + vm.page-cluster \ + vm.vfs_cache_pressure \ + vm.dirty_ratio \ + vm.dirty_background_ratio \ + vm.watermark_scale_factor \ + vm.compaction_proactiveness \ + 2>/dev/null | sed 's/^/ /' +} + +check_safety() { + local mem_avail_kb=$(awk '/MemAvailable/ {print $2}' /proc/meminfo) + local swap_total_kb=$(awk '/SwapTotal/ {print $2}' /proc/meminfo) + local swap_free_kb=$(awk '/SwapFree/ {print $2}' /proc/meminfo) + local swap_used_kb=$((swap_total_kb - swap_free_kb)) + + if [ "$swap_used_kb" -gt "$((mem_avail_kb - 51200))" ]; then + logger -t memory-manager "CRITICAL: Reload aborted. Active swap usage ($swap_used_kb kB) exceeds available RAM ($mem_avail_kb kB)." + return 1 + fi + return 0 +} + +stop_zram() { + if grep -q "/dev/zram0" /proc/swaps; then + swapoff /dev/zram0 || return 1 + fi + if [ -b /dev/zram0 ]; then + echo 1 > /sys/block/zram0/reset 2>/dev/null + fi +} + +stop_swapfile() { + TARGET_SWAP="${SWAPFILE:-/storage/.cache/swapfile}" + if grep -q "$TARGET_SWAP" /proc/swaps; then + swapoff "$TARGET_SWAP" || return 1 + fi +} + +setup_ksm() { + if [ -f /sys/kernel/mm/ksm/run ]; then + local should_run=0 + + if [[ "${KSM_ENABLE,,}" == "auto" ]]; then + should_run=1 + elif [[ "${KSM_ENABLE,,}" == "enable" || "$KSM_ENABLE" == "1" ]]; then + should_run=1 + fi + + if [ "$should_run" -eq 1 ]; then + echo 1 > /sys/kernel/mm/ksm/run + + # Smart Tuning: RAM Tier + SoC Capabilities + if [ "$IS_LOW_RAM" = true ]; then + if [ "$IS_HIGH_PERF_SOC" = true ]; then + # Low RAM but Strong CPU (e.g. S922X 2GB). + # Run KSM aggressively to maximize RAM availability. + echo 200 > /sys/kernel/mm/ksm/sleep_millisecs + echo 200 > /sys/kernel/mm/ksm/pages_to_scan + else + # Low RAM and Weak CPU (e.g. RK3326). + # Conservative to avoid CPU stutter. + echo 500 > /sys/kernel/mm/ksm/sleep_millisecs + echo 100 > /sys/kernel/mm/ksm/pages_to_scan + fi + elif [ "$IS_MID_RAM" = true ]; then + # Mid Range: Slower scan rate + echo 1000 > /sys/kernel/mm/ksm/sleep_millisecs + echo 100 > /sys/kernel/mm/ksm/pages_to_scan + else + # High End: Very lazy scan + echo 3000 > /sys/kernel/mm/ksm/sleep_millisecs + echo 100 > /sys/kernel/mm/ksm/pages_to_scan + fi + else + echo 0 > /sys/kernel/mm/ksm/run + fi + fi +} + +apply_vm_tuning() { + # 1. Watermark Scale Factor + local watermark_factor=10 + if [[ "${VM_WATERMARK_FACTOR,,}" == "auto" ]]; then + if [ "$IS_LOW_RAM" = true ]; then + watermark_factor=10 + else + watermark_factor=100 + fi + elif [[ "$VM_WATERMARK_FACTOR" =~ ^[0-9]+$ ]]; then + watermark_factor=$VM_WATERMARK_FACTOR + fi + if [ -f /proc/sys/vm/watermark_scale_factor ]; then + sysctl -w vm.watermark_scale_factor=$watermark_factor >/dev/null + fi + + # 2. Compaction Proactiveness + local compaction_val=20 + if [[ "${VM_COMPACTION,,}" == "auto" ]]; then + if [ "$IS_HIGH_PERF_SOC" = true ]; then + # High-end chips can afford background cleanup to keep THP ready. + compaction_val=40 + elif [ "$IS_LOW_RAM" = true ]; then + # Save CPU cycles on budget targets. + compaction_val=10 + else + compaction_val=20 + fi + elif [[ "$VM_COMPACTION" =~ ^[0-9]+$ ]]; then + compaction_val=$VM_COMPACTION + fi + if [ -f /proc/sys/vm/compaction_proactiveness ]; then + sysctl -w vm.compaction_proactiveness=$compaction_val >/dev/null + fi + + # 3. Transparent Huge Pages + # Tiered THP Logic (FS MADVISE Synergy) + if [ -f /sys/kernel/mm/transparent_hugepage/enabled ]; then + # Default to madvise for all to prevent bloat + echo madvise > /sys/kernel/mm/transparent_hugepage/enabled + + # Enable for Shared Memory (Crucial for Vulkan/Wayland textures) + if [ -f /sys/kernel/mm/transparent_hugepage/shmem_enabled ]; then + echo advise > /sys/kernel/mm/transparent_hugepage/shmem_enabled + fi + + # Budget vs Flagship Defrag Logic + # On Budget devices (e.g. H700, RK3326), we use 'defer' so the system + # never stalls while trying to find a contiguous 2MB block. + if [ "$IS_LOW_RAM" = true ] && [ "$IS_HIGH_PERF_SOC" = false ]; then + echo defer > /sys/kernel/mm/transparent_hugepage/defrag + logger -t memory-manager "THP: Budget mode enabled (defrag=defer)" + else + # Flagship (RK3588, SM8x) or powerful Mid-range (RK3399) + # Use defer+madvise to allow some synchronous compaction for + # applications that explicitly think it is worth the performance. + echo "defer+madvise" > /sys/kernel/mm/transparent_hugepage/defrag + logger -t memory-manager "THP: Flagship mode enabled (defrag=defer+madvise)" + fi + fi +} + +apply_tuning() { + sysctl -w vm.vfs_cache_pressure=100 >/dev/null + sysctl -w vm.dirty_ratio=10 >/dev/null + sysctl -w vm.dirty_background_ratio=5 >/dev/null + + apply_vm_tuning + setup_ksm + + if [ "$ZRAM_SIZE_VAL" -gt 0 ]; then + # With ZRAM + MGLRU + THP, high swappiness ensures the system swaps + # anonymous memory into compressed RAM, keeping physical RAM "unfragmented" + # for Huge Page allocations. + sysctl -w vm.swappiness=100 >/dev/null + sysctl -w vm.page-cluster=0 >/dev/null + + if [ -n "$SECONDARY_ALGO" ] && [ -f /sys/block/zram0/recompress ]; then + if grep -q "$SECONDARY_ALGO" /sys/block/zram0/comp_algorithm; then + echo "algo=$SECONDARY_ALGO priority=1" > /sys/block/zram0/recompress 2>/dev/null + fi + fi + elif [ "$SWAP_SIZE_VAL" -gt 0 ]; then + sysctl -w vm.swappiness=60 >/dev/null + sysctl -w vm.page-cluster=3 >/dev/null + fi +} + +perform_optimization() { + # Proactive Maintenance Logic + # 1. ZRAM Recompression (if Hybrid Tiering is active) + if [ "$ZRAM_SIZE_VAL" -gt 0 ] && [ -n "$SECONDARY_ALGO" ] && [ -f /sys/block/zram0/recompress ]; then + logger -t memory-manager "Optimizing: Triggering ZRAM recompression ($SECONDARY_ALGO)..." + if grep -q "$SECONDARY_ALGO" /sys/block/zram0/comp_algorithm; then + # Recompress huge/idle pages to secondary algo + echo "algo=$SECONDARY_ALGO type=huge_idle" > /sys/block/zram0/recompress 2>/dev/null + fi + fi + + # 2. Memory Compaction (if Fragmentation is high) + if [ -f /proc/sys/vm/compact_memory ]; then + logger -t memory-manager "Optimizing: Triggering Memory Compaction..." + echo 1 > /proc/sys/vm/compact_memory + fi +} + +setup_zram() { + [ "$ZRAM_SIZE_VAL" -le 0 ] && return + + modprobe zsmalloc 2>/dev/null + modprobe zram num_devices=1 2>/dev/null + + local timeout=0 + while [ ! -b /dev/zram0 ] && [ $timeout -lt 5 ]; do + sleep 0.1 + ((timeout++)) + done + + if [ ! -b /dev/zram0 ]; then + logger -t memory-manager "Error: ZRAM device node /dev/zram0 did not appear." + return + fi + + grep -q "zram0" /proc/swaps && return + + local algo_path="/sys/block/zram0/comp_algorithm" + [ -f "$algo_path" ] && echo "$PRIMARY_ALGO" > "$algo_path" 2>/dev/null + + echo $((ZRAM_SIZE_VAL * 1024 * 1024)) > /sys/block/zram0/disksize + mkswap /dev/zram0 >/dev/null + swapon -p 100 /dev/zram0 +} + +setup_swapfile() { + [ "$SWAP_SIZE_VAL" -le 0 ] && return + TARGET_SWAP="${SWAPFILE:-/storage/.cache/swapfile}" + mkdir -p "$(dirname "$TARGET_SWAP")" 2>/dev/null + local cur=0 + [ -f "$TARGET_SWAP" ] && cur=$(du -m "$TARGET_SWAP" | cut -f1) + + if [ "$cur" -ne "$SWAP_SIZE_VAL" ]; then + [ -f "$TARGET_SWAP" ] && swapoff "$TARGET_SWAP" 2>/dev/null && rm "$TARGET_SWAP" + fallocate -l ${SWAP_SIZE_VAL}M "$TARGET_SWAP" 2>/dev/null || \ + dd if=/dev/zero of="$TARGET_SWAP" bs=1M count=$SWAP_SIZE_VAL status=none + chmod 0600 "$TARGET_SWAP" + mkswap "$TARGET_SWAP" >/dev/null + fi + + local prio=-2 + if [[ "${SWAP_PRIORITY,,}" == "stripe" ]]; then + prio=100 + elif [[ "${SWAP_PRIORITY,,}" == "auto" ]]; then + if [ "$ZRAM_SIZE_VAL" -gt 0 ]; then + prio=-10 + else + prio=-2 + fi + elif [[ "$SWAP_PRIORITY" =~ ^-?[0-9]+$ ]]; then + prio=$SWAP_PRIORITY + fi + + swapon -p $prio "$TARGET_SWAP" 2>/dev/null +} + +drop_caches() { + sync + echo 3 > /proc/sys/vm/drop_caches + logger -t memory-manager "Caches dropped." + echo "Caches dropped." +} + +# --- 4. LOGIC RESOLUTION & ARG PARSING --- + +ACTION="" + +while [[ $# -gt 0 ]]; do + case "$1" in + --zram-size) update_config "ZRAM_SIZE" "$2"; shift 2 ;; + --zram-algo) update_config "ZRAM_ALGO" "$2"; shift 2 ;; + --swap-size) update_config "SWAP_FILE_SIZE" "$2"; shift 2 ;; + --swap-priority) update_config "SWAP_PRIORITY" "$2"; shift 2 ;; + --vm-watermark) update_config "VM_WATERMARK_FACTOR" "$2"; shift 2 ;; + --vm-compaction) update_config "VM_COMPACTION" "$2"; shift 2 ;; + --ksm) update_config "KSM_ENABLE" "$2"; shift 2 ;; + --setup) ACTION="setup"; shift ;; + --stop) ACTION="stop"; shift ;; + --reload) ACTION="reload"; shift ;; + --drop-caches) ACTION="drop-caches"; shift ;; + --optimize) ACTION="optimize"; shift ;; + --status) ACTION="status"; shift ;; + --json) ACTION="json"; shift ;; + --help|-h) + echo "Usage: archr-memory-manager [OPTIONS] [ACTION]" + echo "Config Options (Writes to .config/swap.conf):" + echo " --zram-size [0|Auto|MB] Set ZRAM size" + echo " --zram-algo [zstd|lzo|lz4] Set ZRAM compression" + echo " --swap-size [0|Auto|Resume] Set Disk Swap size" + echo " --swap-priority [Auto|Stripe] Set Swap priority" + echo " --vm-watermark [Auto|Val] Set VM watermark scale factor" + echo " --vm-compaction [Auto|Val] Set VM compaction proactiveness" + echo " --ksm [Auto|Enable|Disable] Set Kernel Samepage Merging" + echo "Actions:" + echo " --setup Initial setup" + echo " --reload Safe reload (teardown -> setup)" + echo " --optimize Run runtime optimizations (Recompress/Compact)" + echo " --status Show status (default interactive)" + echo " --json Show status in JSON" + exit 0 + ;; + *) if [ -z "$ACTION" ]; then ACTION="setup"; fi; shift ;; + esac +done + +if [ -z "$ACTION" ]; then + if [ -t 0 ]; then ACTION="status"; else ACTION="setup"; fi +fi + +# --- 5. RE-EVALUATE LOGIC WITH NEW CONFIGS --- + +# Calculate ZRAM Size +ZRAM_SIZE_VAL=0 +ZRAM_STATUS="Off" +if [[ "${ZRAM_SIZE,,}" == "auto" ]]; then + if [ "$IS_LOW_RAM" = true ]; then + ZRAM_SIZE_VAL=$((TOTAL_MEM_MB * 3 / 4)) + elif [ "$IS_MID_RAM" = true ]; then + ZRAM_SIZE_VAL=$((TOTAL_MEM_MB / 2)) + else + ZRAM_SIZE_VAL=6144 + fi + ZRAM_STATUS="Auto (${ZRAM_SIZE_VAL}MB)" +elif [[ "$ZRAM_SIZE" =~ ^[0-9]+$ ]] && [ "$ZRAM_SIZE" -gt 0 ]; then + ZRAM_SIZE_VAL=$ZRAM_SIZE + ZRAM_STATUS="${ZRAM_SIZE_VAL}MB" +fi + +# Calculate Swap File Size +SWAP_SIZE_VAL=0 +SWAP_STATUS="Off" +if [[ "${SWAP_FILE_SIZE,,}" == "auto" ]]; then + SWAP_SIZE_VAL=$TOTAL_MEM_MB + [ "$SWAP_SIZE_VAL" -gt 2048 ] && SWAP_SIZE_VAL=2048 + SWAP_STATUS="Auto (${SWAP_SIZE_VAL}MB)" +elif [[ "${SWAP_FILE_SIZE,,}" == "resume" ]]; then + SWAP_SIZE_VAL=$((TOTAL_MEM_MB + 512)) + SWAP_STATUS="Resume Target (${SWAP_SIZE_VAL}MB)" +elif [[ "$SWAP_FILE_SIZE" =~ ^[0-9]+$ ]] && [ "$SWAP_FILE_SIZE" -gt 0 ]; then + SWAP_SIZE_VAL=$SWAP_FILE_SIZE + SWAP_STATUS="${SWAP_SIZE_VAL}MB" +fi + +# Determine Algorithms +if [[ "$ZRAM_ALGO" == "@ZRAM_COMPRESSION_ALGO@" ]]; then + ZRAM_ALGO="zstd" +fi + +PRIMARY_ALGO="$ZRAM_ALGO" +SECONDARY_ALGO="" + +if [[ "$ZRAM_ALGO" == "zstd" ]]; then + PRIMARY_ALGO="lzo-rle" + SECONDARY_ALGO="zstd" +fi + +# Safety check for algorithm +if [ -e /sys/block/zram0/comp_algorithm ] && ! grep -q "$PRIMARY_ALGO" /sys/block/zram0/comp_algorithm 2>/dev/null; then + if grep -q "lzo-rle" /sys/block/zram0/comp_algorithm 2>/dev/null; then + PRIMARY_ALGO="lzo-rle" + else + PRIMARY_ALGO=$(awk '{print $1}' /sys/block/zram0/comp_algorithm | tr -d '[]') + fi +fi + +# --- 6. PERFORM ACTION --- + +case "$ACTION" in + setup) + exec 1> >(logger -s -t memory-manager) 2>&1 + apply_tuning + setup_zram + setup_swapfile + ;; + stop) + exec 1> >(logger -s -t memory-manager) 2>&1 + stop_zram + stop_swapfile + ;; + reload) + exec 1> >(logger -s -t memory-manager) 2>&1 + logger "Reloading memory configuration..." + if ! check_safety; then exit 1; fi + stop_swapfile + stop_zram + apply_tuning + setup_zram + setup_swapfile + ;; + optimize) + exec 1> >(logger -s -t memory-manager) 2>&1 + perform_optimization + ;; + drop-caches) + drop_caches + ;; + status) + show_status + ;; + json) + show_status_json + ;; +esac +exit 0 diff --git a/projects/ArchR/packages/archr/sources/scripts/archr-report-stats b/projects/ArchR/packages/archr/sources/scripts/archr-report-stats new file mode 100755 index 0000000000..63aead623b --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/archr-report-stats @@ -0,0 +1,48 @@ +#!/bin/sh +# This script reports non personally identifiable information to ArchR so that we can +# see active user statistics. + +. /etc/profile + +MACHINEIDFILE=/storage/.cache/systemd-machine-id +USERID=$(cat ${MACHINEIDFILE}) + +ENDPOINT_URL="https://stats.arch-r.io" +MAX_RETRIES=5 +RETRY_DELAY=60 + +send_stats() { + curl -s -S -X POST \ + -F "ArchR_UID=${USERID:(-12)}" \ + -F "ArchR_VERSION=${OS_VERSION}" \ + -F "ArchR_BUILD=${OS_BUILD}" \ + -F "ArchR_SOC=${HW_DEVICE}" \ + -F "ArchR_DEV=${QUIRK_DEVICE}" \ + $ENDPOINT_URL + return $? +} + +# Try to send stats with retries +retry_count=0 +while [ $retry_count -lt $MAX_RETRIES ]; do + # Check network connectivity first (ping DNS server) + if ping -c 1 8.8.8.8 >/dev/null 2>&1; then + send_stats + exit_code=$? + + if [ $exit_code -eq 0 ]; then + echo "Statistics reported successfully." + exit 0 + else + echo "Failed to send statistics (HTTP error). Retrying in $RETRY_DELAY seconds..." + fi + else + echo "Network connection unavailable. Retrying in $RETRY_DELAY seconds..." + fi + + sleep $RETRY_DELAY + retry_count=$((retry_count + 1)) +done + +echo "Maximum retry attempts reached. Failed to report statistics." +exit 1 diff --git a/projects/ArchR/packages/archr/sources/scripts/archr-retroachievements-info b/projects/ArchR/packages/archr/sources/scripts/archr-retroachievements-info new file mode 100755 index 0000000000..623eb37ee9 --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/archr-retroachievements-info @@ -0,0 +1,104 @@ +#!/bin/bash +# +# Get RetroAchievements information for ArchR +# +# @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: +# archr-retroachievements-info +# +CONFIGFILE="/storage/.config/system/configs/system.cfg" +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="(
|
)" '{print $2}' | uniq > "$tmpfile"_2 + idcard=$(cat "$tmpfile" | sed -e "/^[[:blank:]]*$/d" | 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/projects/ArchR/packages/archr/sources/scripts/archr-scraper b/projects/ArchR/packages/archr/sources/scripts/archr-scraper new file mode 100755 index 0000000000..5d03e3cf5e --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/archr-scraper @@ -0,0 +1,79 @@ +#!/bin/bash + +systemsetting="/usr/bin/archr-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/projects/ArchR/packages/archr/sources/scripts/archr-settings b/projects/ArchR/packages/archr/sources/scripts/archr-settings new file mode 100755 index 0000000000..c9d32e9b54 --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/archr-settings @@ -0,0 +1,267 @@ +#!/bin/bash + +# archr-settings can mimic archrSettings.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 system.cfg (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: +# 'archr-settings --command load --key wifi.enabled' will print out 0 or 1 +# 'archr-settings --command write --key wifi.ssid -value "This is my NET"' will set 'wlan.ssid=This is my NET' +# 'archr-settings enable wifi.ssid' will remove # from configfile (activate) +# 'archr-settings disable wifi.enabled' will set key wifi.enabled=0 +# 'archr-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 ##### +ArchR_CONFIGFILE="/storage/.config/system/configs/system.cfg" +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*=" $ArchR_CONFIGFILE)" + ret=$? + if [[ $ret -eq 1 ]]; then + val="$(grep -E -m1 "^$COMMENT_CHAR_SEARCH\s*$1\s*=" $ArchR_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/" "$ArchR_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/" "$ArchR_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/" "$ArchR_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 system.cfg (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/system.cfg'" + +echo "$val" + +} +##### Function Calls ##### + +##### MAIN FUNCTION ##### +function main() { + + #Filename parsed? + if [[ -f "$1" ]]; then + ArchR_CONFIGFILE="$1" + shift + else + [[ -f "$ArchR_CONFIGFILE" ]] || { echo "not found: $ArchR_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 "$ArchR_CONFIGFILE" ]] && echo "ok: found '$ArchR_CONFIGFILE'" >&2 || echo "error: not found '$ArchR_CONFIGFILE'" >&2 + [[ -w "$ArchR_CONFIGFILE" ]] && echo "ok: r/w file '$ArchR_CONFIGFILE'" >&2 || echo "error: r/o file '$ArchR_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 "$ArchR_CONFIGFILE" ]] || { echo "r/o file: $ArchR_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 + #archrSettings.py fob + readarray -t arr <<< "$1" + unset arr[0] +else + #regular call by shell + arr=("$@") +fi + +main "${arr[@]}" + +##### MAIN CALL ##### diff --git a/projects/ArchR/packages/archr/sources/scripts/archr-systems b/projects/ArchR/packages/archr/sources/scripts/archr-systems new file mode 100755 index 0000000000..ca4d00a3ae --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/archr-systems @@ -0,0 +1,971 @@ +#!/usr/bin/env python + +from __future__ import print_function + +from hashlib import md5 +from os.path import isfile +from collections import OrderedDict +import sys +import zipfile +import xml.etree.ElementTree as elementTree + +systems = { + + # ---------- Atari ---------- # + # https://docs.libretro.com/library/atari800/#bios + "atari800": { "name": "Atari 800", "biosFiles": [ { "md5": "eb1f32f5d9f382db1bbfb8d7f9cb343a", "file": "bios/ATARIOSA.ROM"}, + { "md5": "4177f386a3bac989a981d3fe3388cb6c", "file": "bios/ATARIOSB.ROM"}, + { "md5": "06daac977823773a3eea3422fd26a703", "file": "bios/ATARIXL.ROM" }, + # The BASIC cart came with all Atari computers. On the XL and XE, it was built-in, so it's required by those models. + { "md5": "0bac0c6a50104045d902df4503a4c30b", "file": "bios/ATARIBAS.ROM"} ] }, + + "atari5200": { "name": "Atari 5200", "biosFiles": [ { "md5": "281f20ea4320404ec820fb7ec0693b38", "file": "bios/5200.rom" } ] }, + + # https://github.com/libretro/libretro-super/blob/master/dist/info/hatari_libretro.info + "atarist": { "name": "Atari ST", "biosFiles": [ { "md5": "c1c57ce48e8ee4135885cee9e63a68a2", "file": "bios/tos.img"}, # TOS 1.02 US + # Atari ST / STf / STfm + { "md5": "25789a649faff0a1176dc7d9b98105c0", "file": "bios/tos100fr.img"}, + { "md5": "c87a52c277f7952b41c639fc7bf0a43b", "file": "bios/tos100uk.img"}, + { "md5": "d0f682ee6237497004339fb02172638b", "file": "bios/tos100us.img"}, + + { "md5": "a622cc35d8d78703905592dfaa4d2ccb", "file": "bios/tos102de.img"}, + { "md5": "d6521785627d20c51edc566808a6bf28", "file": "bios/tos102fr.img"}, + { "md5": "b2a8570de2e850c5acf81cb80512d9f6", "file": "bios/tos102uk.img"}, + #{ "md5": "c1c57ce48e8ee4135885cee9e63a68a2", "file": "bios/tos102us.img"}, + + { "md5": "41b7dae4e24735f330b63ad923a0bfbc", "file": "bios/tos104de.img"}, + { "md5": "143343f7b8e0b1162af206fe8f46b002", "file": "bios/tos104es.img"}, + { "md5": "0087e2707c57efa2106a0aa7576655c0", "file": "bios/tos104fr.img"}, + #{ "md5": "52248cc70ae48b3050e197e270917130", "file": "bios/tos104nl.img"}, + #{ "md5": "7c040857bdcfcd7d748ca82205463efa", "file": "bios/tos104se.img"}, + { "md5": "036c5ae4f885cbf62c9bed651c6c58a8", "file": "bios/tos104uk.img"}, + { "md5": "736adb2dc835df4d323191fdc8926cc9", "file": "bios/tos104us.img"}, + + # Atari STe + { "md5": "992bac38e01633a529121a2a65f0779e", "file": "bios/tos106de.img"}, + { "md5": "30f69d70fe7c210300ed83f991b12de9", "file": "bios/tos106es.img"}, + { "md5": "bc7b224d0dc3f0cc14c8897db89c5787", "file": "bios/tos106fr.img"}, + { "md5": "6033f2b9364edfed321c6931a8181fd2", "file": "bios/tos106uk.img"}, + { "md5": "a0982e760f9807d82667ff5a69e78f6b", "file": "bios/tos106us.img"}, + + { "md5": "94a75c1c65408d9f974b0463e15a3b11", "file": "bios/tos162de.img"}, + { "md5": "ed5fbaabe0219092df74c6c14cea3f8e", "file": "bios/tos162fr.img"}, + #{ "md5": "6f9471098a521214fad1e2c6f2dd3d08", "file": "bios/tos162se.img"}, + { "md5": "1cbc4f55295e469fc8cd72b7efdea1da", "file": "bios/tos162uk.img"}, + { "md5": "febb00ba8784798293a7ae709a1dafcb", "file": "bios/tos162us.img"}, + + # Atari Mega STe + { "md5": "7aeabdc25f8134590e25643a405210ca", "file": "bios/tos205de.img"}, + { "md5": "7449b131681f1dfe62ebed1392847057", "file": "bios/tos205es.img"}, + { "md5": "61b620ad951815a25cb37895c81a947c", "file": "bios/tos205fr.img"}, + { "md5": "7e87d8fe7e24e0b4c55ad1b7955beae3", "file": "bios/tos205it.img"}, + #{ "md5": "1c92855316a33faee602b8007f22d2cb", "file": "bios/tos205se.img"}, + { "md5": "7cdd45b6aac66a21bfb357d9334e46db", "file": "bios/tos205us.img"}, + + { "md5": "0604dbb85928f0598d04144a8b554bbe", "file": "bios/tos206de.img"}, + { "md5": "b2873004a408b8db36321f98daafa251", "file": "bios/tos206fr.img"}, + { "md5": "4a0d4f282c3f2a0196681adf88862dd4", "file": "bios/tos206.img"}, + #{ "md5": "332fe3803a7e20cd625b27a69f07ae69", "file": "bios/tos206ru.img"}, + #{ "md5": "a7dc40dc5c1086bce1a8f3d44fd29051", "file": "bios/tos206se.img"}, + { "md5": "e690bec90d902024beed549d22150755", "file": "bios/tos206uk.img"}, + { "md5": "c9093f27159e7d13ac0d1501a95e53d4", "file": "bios/tos206us.img"}, + + # Atari TT + { "md5": "066f39a7ea5789d5afd59dd7b3104fa6", "file": "bios/tos306de.img"}, + { "md5": "dd1010ec566efbd71047d6c4919feba5", "file": "bios/tos306uk.img"}, + + # Atari Falcon + { "md5": "ed2647936ce4bd283c4d7dfd7ae09d1c", "file": "bios/tos400.img"}, + { "md5": "9e880168d0a004f7f5e852be758f39e4", "file": "bios/tos402.img"}, + { "md5": "e5ea0f216fb446f1c4a4f476bc5f03d4", "file": "bios/tos404.img"} ] }, + + # https://docs.libretro.com/library/beetle_handy/#bios + "lynx": { "name": "Lynx", "biosFiles": [ { "md5": "fcd403db69f54290b51035d82f835e7b", "file": "bios/lynxboot.img"} ] }, + + # ---------- Magnavox and Philips ---------- # + # https://docs.libretro.com/library/o2em/#bios + "o2em": { "name": "Odyssey 2", "biosFiles": [ { "md5": "562d5ebf9e030a40d6fabfc2f33139fd", "file": "bios/o2rom.bin" }, + { "md5": "f1071cdb0b6b10dde94d3bc8a6146387", "file": "bios/c52.bin" } ] }, + + "videopacplus": { "name": "Videopac+ G7400", "biosFiles": [ { "md5": "c500ff71236068e0dc0d0603d265ae76", "file": "bios/g7400.bin" }, + { "md5": "279008e4a0db2dc5f1c048853b033828", "file": "bios/jopac.bin" } ] }, + + # ---------- Mattel ---------- # + # https://docs.libretro.com/library/freeintv/#bios + "intellivision": { "name": "Mattel Intellivision", "biosFiles": [ { "md5": "62e761035cb657903761800f4437b8af", "file": "bios/exec.bin" }, + { "md5": "0cd5946c6473e42e8e4c2137785e427f", "file": "bios/grom.bin" } ] }, + + # ---------- NEC ---------- # + # https://docs.libretro.com/library/beetle_pce_fast/#bios + "pcengine": { "name": "PC Engine", "biosFiles": [ { "md5": "38179df8f4ac870017db21ebcbf53114", "file": "bios/syscard3.pce" } ] }, + + # https://docs.libretro.com/library/beetle_pc_fx/#bios + "pcfx": { "name": "PC-FX", "biosFiles": [ { "md5": "08e36edbea28a017f79f8d4f7ff9b6d7", "file": "bios/pcfx.rom" } ] }, + + # https://docs.libretro.com/library/beetle_pce_fast/#bios + "supergrafx": { "name": "Supergrafx", "biosFiles": [ { "md5": "38179df8f4ac870017db21ebcbf53114", "file": "bios/syscard3.pce" } ] }, + + # ---------- SNK ----------# + "neogeo": { "name": "NeoGeo", "biosFiles": [ { "md5": "dffb72f116d36d025068b23970a4f6df", "file": "bios/neogeo.zip" } ] }, + "neogeocd": { "name": "NeoGeo CD", "biosFiles": [ { "md5": "8834880c33164ccbe6476b559f3e37de", "file": "bios/neocd/neocd_f.rom" }, + { "md5": "043d76d5f0ef836500700c34faef774d", "file": "bios/neocd/neocd_sf.rom" }, + { "md5": "de3cf45d227ad44645b22aa83b49f450", "file": "bios/neocd/neocd_t.rom" }, + { "md5": "f6325a33c6d63ea4b9162a3fa8c32727", "file": "bios/neocd/neocd_st.rom" }, + { "md5": "11526d58d4c524daef7d5d677dc6b004", "file": "bios/neocd/neocd_z.rom" }, + { "md5": "971ee8a36fb72da57aed01758f0a37f5", "file": "bios/neocd/neocd_sz.rom" }, + { "md5": "5c2366f25ff92d71788468ca492ebeca", "file": "bios/neocd/front-sp1.bin" }, + { "md5": "122aee210324c72e8a11116e6ef9c0d0", "file": "bios/neocd/top-sp1.bin" }, + { "md5": "f39572af7584cb5b3f70ae8cc848aba2", "file": "bios/neocd/neocd.bin"}, + { "md5": "08ca8b2dba6662e8024f9e789711c6fc", "file": "bios/neocd/uni-bioscd.rom"} ] }, + + # ---------- Sharp ---------- # + # https://github.com/libretro/libretro-super/blob/master/dist/info/px68k_libretro.info + "x68000": { "name": "Sharp x68000", "biosFiles": [ { "md5": "7fd4caabac1d9169e289f0f7bbf71d8e", "file": "bios/keropi/iplrom.dat" }, + { "md5": "cb0a5cfcf7247a7eab74bb2716260269", "file": "bios/keropi/cgrom.dat" } ] }, + + # ---------- Panasonic, Sanyo and Goldstar ---------- # + # https://github.com/libretro/libretro-super/blob/master/dist/info/opera_libretro.info + "3do": { "name": "3DO", "biosFiles": [ { "md5": "f47264dd47fe30f73ab3c010015c155b", "file": "bios/panafz1.bin" }, + { "md5": "51f2f43ae2f3508a14d9f56597e2d3ce", "file": "bios/panafz10.bin"}, + { "md5": "8639fd5e549bd6238cfee79e3e749114", "file": "bios/goldstar.bin"} ] }, + + # ---------- Sega ---------- # + # https://docs.libretro.com/library/flycast/#bios + "dreamcast": { "name": "Dreamcast", "biosFiles": [ { "md5": "e10c53c2f8b90bab96ead2d368858623", "file": "bios/dc_boot.bin" }, + { "md5": "0a93f7940c455905bea6e392dfde92a4", "file": "bios/dc_flash.bin" } ] }, + + # https://github.com/libretro/libretro-super/blob/master/dist/info/flycast_libretro.info + "naomi": { "name": "Naomi", "biosFiles": [ { "md5": "eb4099aeb42ef089cfe94f8fe95e51f6", "file": "bios/dc/naomi.zip" } ] }, + + "atomiswave": { "name": "Atomiswave", "biosFiles": [ { "md5": "85254fbe320ca82a768ec2c26bb08def", "file": "bios/dc/awbios.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" } ] }, + + # https://docs.libretro.com/library/genesis_plus_gx/#bios + "msu-md": { "name": "MSU-MD", "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" } ] }, + + # https://docs.libretro.com/library/beetle_saturn/#bios + # https://github.com/libretro/libretro-super/blob/master/dist/info/yabasanshiro_libretro.info + "saturn": { "name": "Sega Saturn", "biosFiles": [ { "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": "af5828fdff51384f99b3c4926be27762", "file": "bios/saturn_bios.bin" } ] }, + + # ---------- Sony Computer Entertainment ---------- # + # https://docs.libretro.com/library/pcsx_rearmed/#bios + "psx": { "name": "PSX", "biosFiles": [ { "md5": "c53ca5908936d412331790f4426c6c33", "file": "bios/psxonpsp660.bin" }, + { "md5": "6e3735ff4c7dc899ee98981385f6f3d0", "file": "bios/scph101.bin" }, + { "md5": "dc2b9bf8da62ec93e868cfd29f0d067d", "file": "bios/scph1001.bin" }, + { "md5": "8dd7d5296a650fac7319bce665a6a53c", "file": "bios/scph5500.bin" }, + { "md5": "490f666e1afb15b7362b406ed1cea246", "file": "bios/scph5501.bin" }, + { "md5": "32736f17079d0b2b7024407c39bd3050", "file": "bios/scph5502.bin" }, + { "md5": "1e68c231d0896b7eadcad1d7d8e76129", "file": "bios/scph7001.bin" } ] }, + + # https://pcsx2.net/config-guide/official-english-pcsx2-configuration-guide.html#Bios + # use the last USA bios which can run NTSC and PAL games + "ps2": { "name": "PS2", "biosFiles": [ { "md5": "21038400dc633070a78ad53090c53017", "file": "bios/ps2/ps2-0230a-20080220.bin" } ] }, + + # https://www.playstation.com/en-us/support/system-updates/ps3/ + "ps3": { "name": "PS3", "biosFiles": [ { "md5": "05fe32f5dc8c78acbcd84d36ee7fdc5b", "file": "bios/PS3UPDAT.PUP" } ] }, + + # ---------- Nintendo ---------- # + # https://docs.libretro.com/library/fceumm/#bios + "fds": { "name": "Nintendo Family Computer Disk System", "biosFiles": [ { "md5": "ca30b50f880eb660a320674ed365ef7a", "file": "bios/disksys.rom" } ] }, + + # https://docs.libretro.com/library/melonds/#bios + "nds": { "name": "Nintendo DS", "biosFiles": [ { "md5": "", "file": "bios/firmware.bin" }, # ideally - 94bc5094607c5e6598d50472c52f27f2 + { "md5": "df692a80a5b1bc90728bc3dfc76cd948", "file": "bios/bios7.bin" }, + { "md5": "a392174eb3e572fed6447e956bde4b25", "file": "bios/bios9.bin" }, + { "md5": "559dae4ea78eb9d67702c56c1d791e81", "file": "bios/dsi_bios7.bin" }, + { "md5": "87b665fce118f76251271c3732532777", "file": "bios/dsi_bios9.bin" }, + { "md5": "", "file": "bios/dsi_firmware.bin" }, # ideally - 74f23348012d7b3e1cc216c47192ffeb + { "md5": "", "file": "bios/dsi_nand.bin" } # ideally - d71edf897ddd06bf335feeb68edeb272 + ] }, + + # https://docs.libretro.com/library/mgba/#bios + "gba": { "name": "Nintendo Gameboy Advance", "biosFiles": [ { "md5": "a860e8c0b6d573d191e4ec7db1b1e4f6", "file": "bios/gba_bios.bin" }, + { "md5": "32fbbd84168d3482956eb3c5051637f5", "file": "bios/gb_bios.bin" }, # Optional + { "md5": "dbfce9db9deaa2567f6a84fde55f9680", "file": "bios/gbc_bios.bin" }, # Optional + { "md5": "d574d4f9c12f305074798f54c091a8b4", "file": "bios/sgb_bios.bin" } ] }, # Optional + + # https://docs.libretro.com/library/snes9x/#bios + "satellaview": { "name": "Satellaview", "biosFiles": [ { "md5": "96cf17bf589fcbfa6f8de2dc84f19fa2", "file": "bios/BS-X.bin" } ] }, + "sufami": { "name": "Sufami", "biosFiles": [ { "md5": "d3a44ba7d42a74d3ac58cb9c14c6a5ca", "file": "bios/STBIOS.bin" } ] }, + + # https://docs.libretro.com/library/mesen-s/#bios + "sgb": { "name": "Super Game Boy", "biosFiles": [ { "md5": "d574d4f9c12f305074798f54c091a8b4", "file": "bios/sgb_boot.bin" }, + { "md5": "e0430bca9925fb9882148fd2dc2418c1", "file": "bios/sgb2_boot.bin" }, + { "md5": "b15ddb15721c657d82c5bab6db982ee9", "file": "bios/SGB1.sfc" }, + { "md5": "8ecd73eb4edf7ed7e81aef1be80031d5", "file": "bios/SGB2.sfc" } ] }, + # ---------- Microsoft ---------- # + # https://docs.libretro.com/library/fmsx/#bios + "msx": { "name": "MSX", "biosFiles": [ { "md5": "364a1a579fe5cb8dba54519bcfcdac0d", "file": "bios/MSX.ROM" } ] }, + + "msx2": { "name": "MSX2", "biosFiles": [ { "md5": "ec3a01c91f24fbddcbcab0ad301bc9ef", "file": "bios/MSX2.ROM" }, + { "md5": "2183c2aff17cf4297bdb496de78c2e8a", "file": "bios/MSX2EXT.ROM" } ] }, + + "msx2+": { "name": "MSX2+", "biosFiles": [ { "md5": "847cc025ffae665487940ff2639540e5", "file": "bios/MSX2P.ROM" }, + { "md5": "7c8243c71d8f143b2531f01afa6a05dc", "file": "bios/MSX2PEXT.ROM" } ] }, + + "xbox": { "name": "Xbox", "biosFiles": [{ "md5": "d49c52a4102f6df7bcf8d0617ac475ed", "file": "bios/mcpx_1.0.bin" }, + { "md5": "39cee882148a87f93cb440b99dde3ceb", "file": "bios/Complex_4627.bin" }] }, + + # ---------- Commodore ---------- # + # https://github.com/libretro/libretro-super/blob/master/dist/info/puae_libretro.info + # https://github.com/midwan/amiberry/wiki/Kickstart-ROMs-(BIOS) + # https://fs-uae.net/docs/kickstarts + "amiga500": { "name": "Amiga 500", "biosFiles": [ { "md5": "85ad74194e87c08904327de1a9443b7a", "file": "bios/amiga/kick33180.A500" }, + { "md5": "dc10d7bdd1b6f450773dfb558477c230", "file": "bios/amiga/kick37175.A500" }, + { "md5": "82a21c1890cae844b3df741f2762d48d", "file": "bios/amiga/kick34005.A500" }, + # Amiga 600 kickstart. Not really needed but maybe someone out there will want to switch their model to Amiga 600. + { "md5": "465646c9b6729f77eea5314d1f057951", "file": "bios/amiga/kick37350.A600" }, + { "md5": "e40a5dfb3d017ba8779faba30cbd1c8e", "file": "bios/amiga/kick40063.A600" }, + # The Amiga Forever equivalents. Really are these actually needed? Just so people don't have to rename their stuff? + { "md5": "85ad74194e87c08904327de1a9443b7a", "file": "bios/amiga/amiga-os-120.rom" }, + { "md5": "82a21c1890cae844b3df741f2762d48d", "file": "bios/amiga/amiga-os-130.rom" }, + { "md5": "dc10d7bdd1b6f450773dfb558477c230", "file": "bios/amiga/amiga-os-204.rom" }, + { "md5": "465646c9b6729f77eea5314d1f057951", "file": "bios/amiga/amiga-os-205.rom" }, + { "md5": "e40a5dfb3d017ba8779faba30cbd1c8e", "file": "bios/amiga/amiga-os-310-a600.rom" }] }, + + "amigacdtv": { "name": "Amiga CDTV", "biosFiles": [ { "md5": "82a21c1890cae844b3df741f2762d48d", "file": "bios/amiga/kick34005.A500" }, + { "md5": "89da1838a24460e4b93f4f0c5d92d48d", "file": "bios/amiga/kick34005.CDTV" }, + # CDTV requires both the Amiga 500 kickstart and its own extended kickstart. + { "md5": "82a21c1890cae844b3df741f2762d48d", "file": "bios/amiga/amiga-os-130.rom" }, + { "md5": "89da1838a24460e4b93f4f0c5d92d48d", "file": "bios/amiga/amiga-ext-130-cdtv.rom" }] }, + + "amiga1200": { "name": "Amiga 1200", "biosFiles": [ { "md5": "b7cc148386aa631136f510cd29e42fc3", "file": "bios/amiga/kick39106.A1200" }, + { "md5": "646773759326fbac3b2311fd8c8793ee", "file": "bios/amiga/kick40068.A1200" }, + { "md5": "9bdedde6a4f33555b4a270c8ca53297d", "file": "bios/amiga/kick40068.A4000" }, + # The Amiga Forever equivalents. a3000 seems to not have a kickstart equivalent. amiga-os-310.rom doesn't match libretro's docs. + { "md5": "b7cc148386aa631136f510cd29e42fc3", "file": "bios/amiga/amiga-os-300-a1200.rom" }, + { "md5": "646773759326fbac3b2311fd8c8793ee", "file": "bios/amiga/amiga-os-310-a1200.rom" }, + { "md5": "413590e50098a056cfec418d3df0212d", "file": "bios/amiga/amiga-os-310-a3000.rom" }, + { "md5": "9bdedde6a4f33555b4a270c8ca53297d", "file": "bios/amiga/amiga-os-310-a4000.rom" }, + { "md5": "730888fb1bd9a3606d51f772ed136528", "file": "bios/amiga/amiga-os-310.rom" }] }, + + "amigacd32": { "name": "Amiga CD32", "biosFiles": [ { "md5": "5f8924d013dd57a89cf349f4cdedc6b1", "file": "bios/amiga/kick40060.CD32" }, + { "md5": "bb72565701b1b6faece07d68ea5da639", "file": "bios/amiga/kick40060.CD32.ext" }, + # Unlike the CDTV, CD32 does not need the Amiga 1200 kickstart. + # But, it has its own unique "base" anyway, which is required in addition to its extended. + { "md5": "5f8924d013dd57a89cf349f4cdedc6b1", "file": "bios/amiga/amiga-os-310-cd32.rom" }, + { "md5": "bb72565701b1b6faece07d68ea5da639", "file": "bios/amiga/amiga-ext-310-cd32.rom" }] }, + + # ---------- NEC PC-8800 ---------- # + # https://github.com/RetroPie/RetroPie-Setup/wiki/PC-8800 + "pc88": { "name": "NEC PC-8800", "biosFiles": [ { "md5": "4f984e04a99d56c4cfe36115415d6eb8", "file": "bios/quasi88/N88.ROM" }, + { "md5": "793f86784e5608352a5d7f03f03e0858", "file": "bios/quasi88/N88SUB.ROM" }, + { "md5": "2ff07b8769367321128e03924af668a0", "file": "bios/quasi88/N88N.ROM" }, + { "md5": "d81c6d5d7ad1a4bbbd6ae22a01257603", "file": "bios/quasi88/N88KNJ1.ROM" }, + { "md5": "d675a2ca186c6efcd6277b835de4c7e5", "file": "bios/quasi88/N88EXT0.ROM" }, + { "md5": "e844534dfe5744b381444dbe61ef1b66", "file": "bios/quasi88/N88EXT1.ROM" }, + { "md5": "6548fa45061274dee1ea8ae1e9e93910", "file": "bios/quasi88/N88EXT2.ROM" }, + { "md5": "fc4b76a402ba501e6ba6de4b3e8b4273", "file": "bios/quasi88/N88EXT3.ROM" } ] }, + + # ---------- NEC PC-9800 ---------- # + # https://github.com/RetroPie/RetroPie-Setup/wiki/PC-9800#bios + "pc98": { "name": "NEC PC-9800", "biosFiles": [ { "md5": "e246140dec5124c5e404869a84caefce", "file": "bios/np2kai/BIOS.ROM" }, + { "md5": "2af6179d7de4893ea0b705c00e9a98d6", "file": "bios/np2kai/FONT.ROM" }, + { "md5": "caf90f22197aed6f14c471c21e64658d", "file": "bios/np2kai/SOUND.ROM"}, + { "md5": "e9fc3890963b12cf15d0a2eea5815b72", "file": "bios/np2kai/ITF.ROM" }, + { "md5": "7da1e5b7c482d4108d22a5b09631d967", "file": "bios/np2kai/font.bmp" } ] }, + # ---------- Fairchild ChannelF ---------- # + # https://github.com/libretro/FreeChaF/blob/master/README.md#bios + "channelf": { "name": "Fairchild ChannelF", "biosFiles": [ { "md5": "ac9804d4c0e9d07e33472e3726ed15c3", "file": "bios/sl31253.bin" }, + { "md5": "da98f4bb3242ab80d76629021bb27585", "file": "bios/sl31254.bin" }, + { "md5": "95d339631d867c8f1d15a5f2ec26069d", "file": "bios/sl90025.bin" } ] }, + # ---------- Sharp X1 ---------- # + # https://github.com/libretro/xmil-libretro/blob/master/README.MD + "x1": { "name": "Sharp X1", "biosFiles": [ { "md5": "eeeea1cd29c6e0e8b094790ae969bfa7", "file": "bios/xmil/IPLROM.X1" }, + { "md5": "56c28adcf1f3a2f87cf3d57c378013f5", "file": "bios/xmil/iplrom.x1t" } ] }, + + # ---------- Fujistu FM-Towns ---------- # + # https://github.com/captainys/TOWNSEMU + "fmtowns": { "name": "Fujistu FM-Towns", "biosFiles": [ { "md5": "8fa4e553f28cfc0c30a0a1e589799942", "file": "bios/fmtowns/FMT_DIC.ROM" }, + { "md5": "0585b19930d4a7f4c71bcc8a33746588", "file": "bios/fmtowns/FMT_DOS.ROM" }, + { "md5": "ac0c7021e9bf48ca84b51ab651169a88", "file": "bios/fmtowns/FMT_F20.ROM" }, + { "md5": "b91300e55b70227ce98b59c5f02fa8dd", "file": "bios/fmtowns/FMT_FNT.ROM" }, + { "md5": "86fb6f7280689259f0ca839dd3dd6cde", "file": "bios/fmtowns/FMT_SYS.ROM" }, + { "md5": "", "file": "bios/fmtmarty.zip" }, + { "md5": "6618519b2c104cf9b7e71a48381b44a9", "zippedFile": "mrom.m36", "file": "bios/fmtmarty.zip"}, + { "md5": "75a5c7afb4bc8221bab8cf24db417950", "zippedFile": "mrom.m37", "file": "bios/fmtmarty.zip"}, + { "md5": "", "file": "bios/fmtowns.zip" }, + { "md5": "34847786d7de94b5d1133c956ab1d75d", "zippedFile": "fmt_dic.rom", "file": "bios/fmtowns.zip"}, + { "md5": "0585b19930d4a7f4c71bcc8a33746588", "zippedFile": "fmt_dos.rom", "file": "bios/fmtowns.zip"}, + { "md5": "eb44f2093f51eb7159f03e170b13af76", "zippedFile": "fmt_fnt.rom", "file": "bios/fmtowns.zip"}, + { "md5": "feaf8c5675151e00cfe3ad27673bff29", "zippedFile": "fmt_sys.rom", "file": "bios/fmtowns.zip"}, + { "md5": "", "file": "bios/fmtownsux.zip" }, + { "md5": "8fa4e553f28cfc0c30a0a1e589799942", "zippedFile": "fmt_dic.rom", "file": "bios/fmtownsux.zip"}, + { "md5": "03c8fac9a5f5f5f35fb5de5a5d0d018f", "zippedFile": "fmt_dos_a.rom", "file": "bios/fmtownsux.zip"}, + { "md5": "b91300e55b70227ce98b59c5f02fa8dd", "zippedFile": "fmt_fnt.rom", "file": "bios/fmtownsux.zip"}, + { "md5": "90b5e01d42aaa93e8f4503a5e94e120b", "zippedFile": "fmt_sys_a.rom", "file": "bios/fmtownsux.zip"}, + { "md5": "1a15f6c1b58ec7e5f850118610a787a7", "zippedFile": "mytownsux.rom", "file": "bios/fmtownsux.zip"} ] }, + + # ---------- GamePark GP32 ---------- # + "gp32": { "name": "GamePark GP32", "biosFiles": [ { "md5": "", "file": "bios/gp32.zip" }, + { "md5": "e64ad881b5e1d86547f2edc3034946d9", "zippedFile": "x2c32.jed", "file": "bios/gp32.zip"}, + { "md5": "f78092f15f6ffe15975901ee4e92c680", "zippedFile": "gp32166m.bin", "file": "bios/gp32.zip"}, + { "md5": "19021cc891119c0872d46e87fc0ffe35", "zippedFile": "gp32157e.bin", "file": "bios/gp32.zip"}, + { "md5": "1e4d3216719acea231b81dfcf6069aef", "zippedFile": "gp32156k.bin", "file": "bios/gp32.zip"}, + { "md5": "cac4b56c0db80922cae75403faef40af", "zippedFile": "gp32100k.bin", "file": "bios/gp32.zip"}, + { "md5": "d4af2bc352bdaf4972ea40902feda114", "zippedFile": "gp32mfv2.bin", "file": "bios/gp32.zip"} ] }, + + # ---------- VTech Laser 310 ---------- # + "laser310": { "name": "VTech Laser 310", "biosFiles": [ { "md5": "", "file": "bios/laser310.zip" }, + { "md5": "42c8f9e6c2133ae0e953b89ccbbdb7e2", "zippedFile": "vtechv20.u12", "file": "bios/laser310.zip"}, + { "md5": "f7e5d9a3eb2b57bf5f4e2a4565318a8f", "zippedFile": "vtechv21.u12", "file": "bios/laser310.zip"} ] }, + + + # ---------- Future Pinball ---------- # + "fpinball": { "name": "Future Pinball", "biosFiles": [ { "md5": "65a8ebf870420316a939ac44fd4c731d", "file": "bios/wsh57/scripten.exe" } ] }, + + # ---------- Super Cassette Vision ---------- # + "scv": { "name": "Super Cassette Vision", "biosFiles": [ { "md5": "635a978fd40db9a18ee44eff449fc126", "file": "bios/upd7801g.s01" } ] }, + + # ---------- Apple 2 GS ---------- # + "gsplus": { "name": "Apple 2 GS", "biosFiles": [ { "md5": "20a0334c447cb069a040ae5be1d938df", "file": "bios/ROM1" } ] }, + + # ---------- Zelda Classic ---------- # + "zc210": { "name": "Zelda Classic", "biosFiles": [ { "md5": "033d7392985841027909c4c32b9f2076", "file": "bios/zc210/zcdata.dat" }, + { "md5": "39e5bc84ce9aac3a2d297d8aeb2a0d05", "file": "bios/zc210/sf2/default.sf2" }, + { "md5": "e0ba7a8634b12cfee4b6760a6f89051a", "file": "bios/zc210/sf2/custom0.sf2" }, + { "md5": "c1dc781c34cff8f9a023c0192754dc6c", "file": "bios/zc210/sf2/custom1.sf2" }, + { "md5": "144fcdbb6a30f1f916f6963006c2da97", "file": "bios/zc210/sf2/custom2.sf2" }, + { "md5": "134d217fb99c3be1e89cfaf8f28280d8", "file": "bios/zc210/sf2/custom3.sf2" }, + { "md5": "b37366199c6df9ee5316f031755aa821", "file": "bios/zc210/sf2/custom4.sf2" }, + { "md5": "64068b84eb88dc85b75148bbe9b393fb", "file": "bios/zc210/sf2/custom5.sf2" }, + { "md5": "1241986de5b1d00b02d34f1e6651a1d1", "file": "bios/zc210/sf2/custom6.sf2" }, + { "md5": "386db0d538f372a9f1af622d1e934abf", "file": "bios/zc210/sf2/custom7.sf2" }, + { "md5": "6f68e4baf89c8ee4623c19617319184b", "file": "bios/zc210/sf2/custom8.sf2" }, + { "md5": "2010e5b85f9e1d60685ccb3d84a17115", "file": "bios/zc210/sf2/custom9.sf2" }, + { "md5": "e0ba7a8634b12cfee4b6760a6f89051a", "file": "bios/zcsf.sf2" } ] }, + # ---------- Apple Mac ---------- # + "macintosh": { "name": "Apple Macintosh", "biosFiles": [ { "md5": "66223be1497460f1e60885eeb35e03cc", "file": "bios/MacII.ROM", "emulator": "libretro", "core": "minivmac" }, + { "md5": "2a8a4c7f2a38e0ab0771f59a9a0f1ee4", "file": "bios/MacIIx.ROM", "emulator": "libretro", "core": "minivmac" }, + { "md5": "", "file": "bios/mac128k.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "bc04a4252ee96826c1f41f927c145225", "zippedFile": "342-0220-a.u6d", "file": "bios/mac128k.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "409d8b9a04db15b7bfbbd5fcb931bf2e", "zippedFile": "342-0221-a.u8d", "file": "bios/mac128k.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "", "file": "bios/mackbd_m0110.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "9d09a9a51c9ef3ea5719e19db22e7901", "zippedFile": "ip8021h_2173.bin", "file": "bios/mackbd_m0110.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "", "file": "bios/mackbd_m0120.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "9d09a9a51c9ef3ea5719e19db22e7901", "zippedFile": "ip8021h_2173.bin", "file": "bios/mackbd_m0120.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "", "file": "bios/mac512k.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "b4118b89fa68a913a225f0cf9a751fae", "zippedFile": "342-0220-b.u6d", "file": "bios/mac512k.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "ab4e461833e98ef7106f24455a07769d", "zippedFile": "342-0221-b.u8d", "file": "bios/mac512k.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "", "file": "bios/macplus.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "1467a42dee57ac265d063b3f351189fc", "zippedFile": "342-0341-a.u6d", "file": "bios/macplus.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "25b1bf85b3b072d957499cef4d7e313f", "zippedFile": "342-0341-b.u6d", "file": "bios/macplus.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "cf7c3259844245a8967556fa40d81243", "zippedFile": "342-0341-c.u6d", "file": "bios/macplus.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "d5584762b43a9b1cb24a981f9b9b4198", "zippedFile": "342-0342-a.u8d", "file": "bios/macplus.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "f83069fd7ff1fb011958f819cbff4c88", "zippedFile": "342-0342-b.u8d", "file": "bios/macplus.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "875919e2544644cd628f44b5c11db036", "zippedFile": "modplus-harp2.bin", "file": "bios/macplus.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "efcefe8f11c10541a503d48a07878201", "zippedFile": "rominator-20150225-hi.bin", "file": "bios/macplus.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "f4b06da98500df0747a764dfbf1862b9", "zippedFile": "rominator-20150225-lo.bin", "file": "bios/macplus.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "", "file": "bios/macse.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "9fb38bdcc0d53d9d380897ee53dc1322", "zippedFile": "macse.rom", "file": "bios/macse.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "", "file": "bios/macclasc.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "c229bb677cb41b84b780c9e38a09173e", "zippedFile": "341-0813__=c=1983-90_apple__japan__910d_d.27c4096_be.ue1", "file": "bios/macclasc.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "", "file": "bios/mac2fdhd.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "2a8a4c7f2a38e0ab0771f59a9a0f1ee4", "zippedFile": "97221136.rom", "file": "bios/mac2fdhd.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "", "file": "bios/nb_mdc824.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "7500a6a958247ee6e092f08715f2fff8", "zippedFile": "3410868.bin", "file": "bios/nb_mdc824.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "", "file": "bios/maciix.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "2a8a4c7f2a38e0ab0771f59a9a0f1ee4", "zippedFile": "97221136.rom", "file": "bios/maciix.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "", "file": "bios/maclc3.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "fa16d49527c4e6e9c0d9e46904133d39", "zippedFile": "ecbbc41c.rom", "file": "bios/maclc3.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "", "file": "bios/mackbd_m0110a.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "9e8ea1552153c5e0f895e247e7d3ec1c", "zippedFile": "341-0332-a.bin", "file": "bios/mackbd_m0110a.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "", "file": "bios/nb_image.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "93155ac7bad0fec36837252bb1e408f2", "zippedFile": "nb_fake.bin", "file": "bios/nb_image.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "", "file": "bios/egret.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "96665499f5cf2bb5b4aae6fdaf0a9fb5", "zippedFile": "341s0850.bin", "file": "bios/egret.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "b955ecbdf6d2f979f3683dd1d6884643", "zippedFile": "341s0851.bin", "file": "bios/egret.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "5035d321c5d5fa1eab5ce6bf986676e4", "zippedFile": "344s0100.bin", "file": "bios/egret.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "", "file": "bios/adbmodem.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "862b8598cecdbc934658c4cb599a8142", "zippedFile": "342s0440-b.bin", "file": "bios/adbmodem.zip", "emulator": "libretro", "core": "mame" }, + { "md5": "", "file": "bios/macos3.img", "emulator": "libretro", "core": "mame" }, + { "md5": "", "file": "bios/macos608.img", "emulator": "libretro", "core": "mame" }, + { "md5": "", "file": "bios/macos701.img", "emulator": "libretro", "core": "mame" }, + { "md5": "", "file": "bios/macos75.img", "emulator": "libretro", "core": "mame" }, + { "md5": "", "file": "bios/mac608.chd", "emulator": "libretro", "core": "mame" }, + { "md5": "", "file": "bios/mac701.chd", "emulator": "libretro", "core": "mame" }, + { "md5": "", "file": "bios/mac755.chd", "emulator": "libretro", "core": "mame" } ] }, + + # ---------- Tandy Color Conputer ---------- # + "coco": { "name": "Tandy Color Computer", "biosFiles": [ { "md5": "", "file": "bios/coco.zip" }, + { "md5": "a74f3d95b395dad7cdca19d560eeea74", "zippedFile": "bas10.rom", "file": "bios/coco.zip"}, + { "md5": "", "file": "bios/coco2.zip" }, + { "md5": "c933316c7d939532a13648850c1c2aa6", "zippedFile": "bas12.rom", "file": "bios/coco2.zip"}, + { "md5": "21070aa0496142b886c562bf76d7c113", "zippedFile": "extbas11.rom", "file": "bios/coco2.zip"}, + { "md5": "", "file": "bios/coco2b.zip" }, + { "md5": "c2fc43556eb6b7b25bdf5955bd9df825", "zippedFile": "bas13.rom", "file": "bios/coco2b.zip"}, + { "md5": "21070aa0496142b886c562bf76d7c113", "zippedFile": "extbas11.rom", "file": "bios/coco2.zip"}, + { "md5": "", "file": "bios/coco3.zip" }, + { "md5": "7233c6c429f3ce1c7392f28a933e0b6f", "zippedFile": "coco3.rom", "file": "bios/coco3.zip"}, + { "md5": "", "file": "bios/coco3p.zip" }, + { "md5": "4ae57e5a8e7494e5485446fefedb580b", "zippedFile": "coco3p.rom", "file": "bios/coco3p.zip"}, + { "md5": "", "file": "bios/coco_fdc_v11.zip" }, + { "md5": "8cab28f4b7311b8df63c07bb3b59bfd5", "zippedFile": "disk11.rom", "file": "bios/coco_fdc_v11.zip"} ] }, + + # ---------- Tomy Tutor ---------- # + "tutor": { "name": "Tomy Tutor", "biosFiles": [ { "md5": "", "file": "bios/tutor.zip" }, + { "md5": "196ba41dd1184fe754390534cc273116", "zippedFile": "tutor1.bin", "file": "bios/tutor.zip"}, + { "md5": "5770834c10946ac2c3617504ba530884", "zippedFile": "tutor2.bin", "file": "bios/tutor.zip"} ] }, + + # ---------- TI-99 ---------- # + "ti99": { "name": "Texas Instruments TI-99", "biosFiles": [ { "md5": "", "file": "bios/ti99_4a.zip" }, + { "md5": "9bb51dfab49b9a7cf832cc1fb6f203e6", "zippedFile": "994a_grom0.u500", "file": "bios/ti99_4a.zip"}, + { "md5": "7f1864c3dac31c86e2ae6ce43ccead07", "zippedFile": "994a_grom1.u501", "file": "bios/ti99_4a.zip"}, + { "md5": "a1f77a07243a334e13509a89bff944f2", "zippedFile": "994a_grom2.u502", "file": "bios/ti99_4a.zip"}, + { "md5": "6f495eef767b3f2821a2ec32d0047891", "zippedFile": "994a_rom_hb.u610", "file": "bios/ti99_4a.zip"}, + { "md5": "0dcb961cf84c69b2171a565427c7c6c7", "zippedFile": "994a_rom_lb.u611", "file": "bios/ti99_4a.zip"}, + { "md5": "", "file": "bios/ti99_speech.zip" }, + { "md5": "491c1195f6345cb6b725096b69d81ec9", "zippedFile": "cd2325a.u2a", "file": "bios/ti99_speech.zip"}, + { "md5": "206daf498ac5d0141de1d47d38afd899", "zippedFile": "cd2326a.u2b", "file": "bios/ti99_speech.zip"} ] }, + + # ---------- Bally Astrocade ---------- # + "astrocde": { "name": "Bally Astrocade", "biosFiles": [ { "md5": "", "file": "bios/astrocde.zip" }, + { "md5": "7d25a26e5c4841b364cfe6b1735eaf03", "zippedFile": "astro.bin", "file": "bios/astrocde.zip"}, ] }, + + # ---------- Game Master ---------- # + "gmaster": { "name": "Hartung Game Master", "biosFiles": [ { "md5": "", "file": "bios/gmaster.zip" }, + { "md5": "6bff08b5e5f96de405cd56d5f04a08f8", "zippedFile": "d78c11agf_e19.u1", "file": "bios/gmaster.zip"}, ] }, + + # ---------- Coleco Adam ---------- # + "adam": { "name": "Coleco Adam", "biosFiles": [ { "md5": "", "file": "bios/adam.zip" }, + { "md5": "01bba3bcd46d8a586dd6ec555accc133", "zippedFile": "alf @1 rev 57 e3d5.u8", "file": "bios/adam.zip"}, + { "md5": "feabe33e8f2dab88da1458b4d27f3faa", "zippedFile": "alf @2 rev 57 ae6a.u20", "file": "bios/adam.zip"}, + { "md5": "a720bc872a772ed471fac14e36ec8bcb", "zippedFile": "alf @3 rev 57 8534.u21", "file": "bios/adam.zip"}, + { "md5": "cf10b154f2e006a9740d7653cfc47cab", "zippedFile": "eos 6 rev 57 08dd.u22", "file": "bios/adam.zip"}, + { "md5": "7916bb9635d502366326ec39aea5fc89", "zippedFile": "master rev a 174b.u6", "file": "bios/adam.zip"}, + { "md5": "2c66f5911e5b42b8ebe113403548eee7", "zippedFile": "os7.u2", "file": "bios/adam.zip"}, + { "md5": "4fe4f6800076ea3d897d4285653447bd", "zippedFile": "wp_r80.rom", "file": "bios/adam.zip"}, + { "md5": "", "file": "bios/adam_ddp.zip" }, + { "md5": "0423e9e9bf5036aa1e9d656b6a1f842c", "zippedFile": "tape rev a 8865.u24", "file": "bios/adam_ddp.zip"}, + { "md5": "", "file": "bios/adam_fdc.zip" }, + { "md5": "ae12d0b83832b059cb6cb43029bbfdb3", "zippedFile": "1440k micro innovations hd-dd.u10", "file": "bios/adam_fdc.zip"}, + { "md5": "4c38a7df1e645c8d9f417bf7165c46d0", "zippedFile": "320ta.u10", "file": "bios/adam_fdc.zip"}, + { "md5": "afea14c826f3cfbc89b76725a4a41951", "zippedFile": "a720dipi 7607 mmsg =c= 1988.u10", "file": "bios/adam_fdc.zip"}, + { "md5": "976d2a7d85319d9104bc9ec176fbfa9c", "zippedFile": "adam disk u10 ad 31 rev a 09-27-84.u10", "file": "bios/adam_fdc.zip"}, + { "md5": "29569dc029e95e48907b3c81d636987f", "zippedFile": "dbl2-4.u10", "file": "bios/adam_fdc.zip"}, + { "md5": "a121855c20a638429bbfcf0448349515", "zippedFile": "doug.u10", "file": "bios/adam_fdc.zip"}, + { "md5": "e05ababa16e2d5cb92b678cb6e6e2004", "zippedFile": "fastpack 720a,t.u10", "file": "bios/adam_fdc.zip"}, + { "md5": "a1a2a353dea4b8769a2da733822abfdc", "zippedFile": "pmhdfdc.u10", "file": "bios/adam_fdc.zip"}, + { "md5": "", "file": "bios/adam_kb.zip" }, + { "md5": "d81e0b2bb6b98999541c5f40b489e88f", "zippedFile": "keyboard.u2", "file": "bios/adam_kb.zip"}, + { "md5": "", "file": "bios/adam_prn.zip" }, + { "md5": "3cdf2fe48ac4224b56f26c03f6c68982", "zippedFile": "printer.u2", "file": "bios/adam_prn.zip"}, ] }, + + # ---------- BBC Micro ---------- # + "bbc": { "name": "BBC Micro", "biosFiles": [ { "md5": "", "file": "bios/bbcb.zip" }, + { "md5": "521a197d3623682825f1042c1350feb4", "zippedFile": "basic1.rom", "file": "bios/bbcb.zip"}, + { "md5": "2cc67be4624df4dc66617742571a8e3d", "zippedFile": "basic2.rom", "file": "bios/bbcb.zip"}, + { "md5": "0cad3d0cf0d111aca2b158b9b605913f", "zippedFile": "os01.rom", "file": "bios/bbcb.zip"}, + { "md5": "46f920a170e88bab7faa96cf80b84324", "zippedFile": "os092.rom", "file": "bios/bbcb.zip"}, + { "md5": "0199bac73f1dbca291582834a3e61122", "zippedFile": "os10.rom", "file": "bios/bbcb.zip"}, + { "md5": "0a59a5ba15fe8557b5f7fee32bbd393a", "zippedFile": "os12.rom", "file": "bios/bbcb.zip"}, + { "md5": "35e9ab10bcf016bd24b4c716add009b9", "zippedFile": "phroma.bin", "file": "bios/bbcb.zip"}, + { "md5": "", "file": "bios/bbc_acorn8271.zip" }, + { "md5": "803530149c274994fabc6d28cbe03679", "zippedFile": "dfs090.rom", "file": "bios/bbc_acorn8271.zip"}, + { "md5": "5a3ddfae96178e025f27bf1f69bfa629", "zippedFile": "dfs098.rom", "file": "bios/bbc_acorn8271.zip"}, + { "md5": "d636ffb7a80fc29b133d32e4250fbab6", "zippedFile": "dnfs100.rom", "file": "bios/bbc_acorn8271.zip"}, + { "md5": "5daed103918277e2065dd7e8d23e57a5", "zippedFile": "dnfs120.rom", "file": "bios/bbc_acorn8271.zip"}, + { "md5": "79b31feacab0b1ccddf358be5dfb6241", "zippedFile": "wedfs130.rom", "file": "bios/bbc_acorn8271.zip"}, + { "md5": "24458ace9566a01d255bca16b46a960d", "zippedFile": "wedfs141.rom", "file": "bios/bbc_acorn8271.zip"}, + { "md5": "6e9356d0a5e7fbabb386824ec370d6f3", "zippedFile": "wedfs142.rom", "file": "bios/bbc_acorn8271.zip"}, + { "md5": "990b8a9755af25452c85f23ceb344be4", "zippedFile": "wedfs143.rom", "file": "bios/bbc_acorn8271.zip"}, + { "md5": "1d250b0242e447e9106e8bfd1f27ea84", "zippedFile": "wedfs144.rom", "file": "bios/bbc_acorn8271.zip"}, + { "md5": "", "file": "bios/saa5050.zip" }, + { "md5": "8b3c10a2317808ed94d6c6073b5b3327", "zippedFile": "saa5050", "file": "bios/saa5050.zip"}, + { "md5": "", "file": "bios/bbc_tube_80186.zip" }, + { "md5": "33d097349f12526584fcac21eccf3012", "zippedFile": "m512_hi_ic32.rom", "file": "bios/bbc_tube_80186.zip"}, + { "md5": "e6e84221c29b5d31d07055039583c8e7", "zippedFile": "m512_lo_ic31.rom", "file": "bios/bbc_tube_80186.zip"}, + { "md5": "", "file": "bios/bbcm.zip" }, + { "md5": "b159012f9f301bab33316fd3bf55db79", "zippedFile": "mos320.cmos", "file": "bios/bbcm.zip"}, + { "md5": "fed079c5e2c595b354529a8ea703b5fb", "zippedFile": "mos320.ic24", "file": "bios/bbcm.zip"}, + { "md5": "ca0527f13f83bc95ef4b6833ee440afa", "zippedFile": "mos329.ic24", "file": "bios/bbcm.zip"}, + { "md5": "ee9fc46252b7d7fe341b9c7f92575099", "zippedFile": "mos350.cmos", "file": "bios/bbcm.zip"}, + { "md5": "3f3dd4614db30f6e383794731272076a", "zippedFile": "mos350.ic24", "file": "bios/bbcm.zip"}, + { "md5": "", "file": "bios/bbcmc.zip" }, + { "md5": "55586a88477505d8fd28edfae646e2e3", "zippedFile": "mos500.ic49", "file": "bios/bbcmc.zip"}, + { "md5": "956bf71da840943050836ade2474ef7b", "zippedFile": "mos510.ic49", "file": "bios/bbcmc.zip"}, + { "md5": "", "file": "bios/bbc_bitstik1.zip" }, + { "md5": "baf5cb5564ff6e6b4400243e7612f323", "zippedFile": "bitstik1.rom", "file": "bios/bbc_bitstik1.zip"}, + { "md5": "", "file": "bios/bbc_bitstik2.zip" }, + { "md5": "c196c145b3de630f85f625ca762e5504", "zippedFile": "bitstik2.rom", "file": "bios/bbc_bitstik2.zip"}, + { "md5": "", "file": "bios/mame/samples/bbc.zip" }, + { "md5": "", "zippedFile": "motoroff.wav", "file": "bios/mame/samples/bbc.zip"}, + { "md5": "", "zippedFile": "motoron.wav", "file": "bios/mame/samples/bbc.zip"} ] }, + + # ---------- APF M-1000 ---------- # + "apfm1000": { "name": "APF M-1000", "biosFiles": [ { "md5": "", "file": "bios/apfm1000.zip" }, + { "md5": "1f4a976350202ee1e32c2b0477c3fc1b", "zippedFile": "apf_4000.rom", "file": "bios/apfm1000.zip"}, + { "md5": "b325543b36d37edf3fc20761f00c7a37", "zippedFile": "mod_bios.bin", "file": "bios/apfm1000.zip"}, + { "md5": "89a7cfa5469ce24773721d65b28f8544", "zippedFile": "trash-ii.bin", "file": "bios/apfm1000.zip"} ] }, + + # ---------- Fujitsu FM-7 ---------- # + "fm7": { "name": "Fujitsu FM-7", "biosFiles": [ { "md5": "", "file": "bios/fm7.zip" }, + { "md5": "9f9b7d5615ecdbde2cd26e9306ffef13", "zippedFile": "boot_bas.rom", "file": "bios/fm7.zip"}, + { "md5": "18a461ccaf7ef4e8ecad58cecd3a24b3", "zippedFile": "boot_dos_a.rom", "file": "bios/fm7.zip"}, + { "md5": "6a5da0404b7ee338df9002cdcabc3068", "zippedFile": "fbasic300.rom", "file": "bios/fm7.zip"}, + { "md5": "a330817f8f7ced752a7bcc8dfba8fd2e", "zippedFile": "kanji.rom", "file": "bios/fm7.zip"}, + { "md5": "d19ed5923aaae2ec43dffe7a0daa80cb", "zippedFile": "subsys_c.rom", "file": "bios/fm7.zip"}, + { "md5": "", "file": "bios/fm77av.zip" }, + { "md5": "71c96a45b78e88a39cb94c1aabd23d8a", "zippedFile": "fbasic30.rom", "file": "bios/fm77av.zip"}, + { "md5": "e0f4c0ebee60aee83e863826e59ae1de", "zippedFile": "initiate.rom", "file": "bios/fm77av.zip"}, + { "md5": "ae945a6dfb642b0a5d0529737e8ee5cd", "zippedFile": "subsys_a.rom", "file": "bios/fm77av.zip"}, + { "md5": "fb83a1a9725c8432acef0c3ce89492e3", "zippedFile": "subsys_b.rom", "file": "bios/fm77av.zip"}, + { "md5": "7db27dede3e358017d518101850bccfa", "zippedFile": "subsyscg.rom", "file": "bios/fm77av.zip"} ] }, + + # ---------- Acorn Archimedes ---------- # + "archimedes": { "name": "Acorn Archimedes", "biosFiles": [ { "md5": "", "file": "bios/aa310.zip" }, + { "md5": "374e4bcaa04cb98aad3b64a1555c3930", "zippedFile": "0270,251-01.rom", "file": "bios/aa310.zip"}, + { "md5": "b0b6a83029b6f85bb044bfc46bf3f0f6", "zippedFile": "0270,252-01.rom", "file": "bios/aa310.zip"}, + { "md5": "bf35bb799aa0278b7ee7719dd32f26bc", "zippedFile": "0270,253-01.rom", "file": "bios/aa310.zip"}, + { "md5": "e41af081535aae930d68ee4cbd672513", "zippedFile": "0270,254-01.rom", "file": "bios/aa310.zip"}, + { "md5": "7ecdccd760557ab0711edb37773faeb6", "zippedFile": "0270,601-01.rom", "file": "bios/aa310.zip"}, + { "md5": "c43bad04862ea03146ff5bf7441a1a24", "zippedFile": "0270,602-01.rom", "file": "bios/aa310.zip"}, + { "md5": "454c1977ad70a206f4f3a0bdca294d85", "zippedFile": "0270,603-01.rom", "file": "bios/aa310.zip"}, + { "md5": "6850da7a70b198eaf6fde5be503fa5cd", "zippedFile": "0270,604-01.rom", "file": "bios/aa310.zip"}, + { "md5": "84d305e248dab48a3a110af161dfb005", "zippedFile": "0276,146-01.rom", "file": "bios/aa310.zip"}, + { "md5": "64d7f085e6afb149ebc2e7f919429a19", "zippedFile": "0276,147-01.rom", "file": "bios/aa310.zip"}, + { "md5": "f7d0a9a4d1dae8eee057aa626b87715f", "zippedFile": "0276,148-01.rom", "file": "bios/aa310.zip"}, + { "md5": "763b015d85c7d9d17e06d5babc0a9d32", "zippedFile": "0276,149-01.rom", "file": "bios/aa310.zip"}, + { "md5": "b8fcd63c6a28d0c7034af2e6c5aff9a8", "zippedFile": "0276,322-01.rom", "file": "bios/aa310.zip"}, + { "md5": "6265551c5d6336f7ddd9f3fc78ceba93", "zippedFile": "0276,323-01.rom", "file": "bios/aa310.zip"}, + { "md5": "ca4379aeab4f7c7640c8ad34b27a9db6", "zippedFile": "0276,324-01.rom", "file": "bios/aa310.zip"}, + { "md5": "358d3c9d2685c076f6a141c26d45520c", "zippedFile": "0276,325-01.rom", "file": "bios/aa310.zip"}, + { "md5": "4ae429fbf23f8aa64ce2002cfb14c527", "zippedFile": "0277,022-02.rom", "file": "bios/aa310.zip"}, + { "md5": "83d0f0738468fdf9f23c13eef22dbeea", "zippedFile": "0277,023-02.rom", "file": "bios/aa310.zip"}, + { "md5": "636e4072c392916d2bf00865fee40984", "zippedFile": "0277,024-02.rom", "file": "bios/aa310.zip"}, + { "md5": "252b1993fdb66cac522a0edbeffc3407", "zippedFile": "0277,025-02.rom", "file": "bios/aa310.zip"}, + { "md5": "591f3bdd0f20a0a3d03c8748f2f75754", "zippedFile": "0283,022-01.rom", "file": "bios/aa310.zip"}, + { "md5": "f77f4a409c78c8495fc3876cd4e7d97c", "zippedFile": "0283,023-01.rom", "file": "bios/aa310.zip"}, + { "md5": "57d3a349407916f55129d6c8c0f56395", "zippedFile": "0283,024-01.rom", "file": "bios/aa310.zip"}, + { "md5": "ee4aa1ea0eebf88c5f6cae6315ed11a1", "zippedFile": "0283,025-01.rom", "file": "bios/aa310.zip"}, + { "md5": "a057124502e533ccd8865dc970cf7017", "zippedFile": "0296,041-01.rom", "file": "bios/aa310.zip"}, + { "md5": "3c40d2821595a7334a46ea3b46a5421d", "zippedFile": "0296,041-02.rom", "file": "bios/aa310.zip"}, + { "md5": "d1d51b8f603bba476d1f63bc5980040e", "zippedFile": "0296,042-01.rom", "file": "bios/aa310.zip"}, + { "md5": "7b096a93cc5ada80bcfb5249bca33768", "zippedFile": "0296,042-02.rom", "file": "bios/aa310.zip"}, + { "md5": "744e80abe4c6a845412f63a0f0b14e48", "zippedFile": "0296,043-01.rom", "file": "bios/aa310.zip"}, + { "md5": "9dac78cba6034c427d00f78fa94ab63d", "zippedFile": "0296,043-02.rom", "file": "bios/aa310.zip"}, + { "md5": "4c0b2e1fb29c8acd84e94d25c953173c", "zippedFile": "0296,044-01.rom", "file": "bios/aa310.zip"}, + { "md5": "f6bf5f8908a19a9aacf733633b1cd5cf", "zippedFile": "0296,044-02.rom", "file": "bios/aa310.zip"}, + { "md5": "eec46f5bd4cdb456b760b3cddf16a33c", "zippedFile": "0296,241-01.rom", "file": "bios/aa310.zip"}, + { "md5": "980e3be0c851a59d0f4602f4a94b2eef", "zippedFile": "0296,242-01.rom", "file": "bios/aa310.zip"}, + { "md5": "971a49d5c2dbb3fc01c17d1d5615781a", "zippedFile": "0296,243-01.rom", "file": "bios/aa310.zip"}, + { "md5": "9ce06a4d2a8331bc5b7fadb967d74f4f", "zippedFile": "0296,244-01.rom", "file": "bios/aa310.zip"}, + { "md5": "c74763f720c98e16dc3c6c421db21485", "zippedFile": "cmos_arthur.bin", "file": "bios/aa310.zip"}, + { "md5": "6f564c8917f04594bda7385f6de61061", "zippedFile": "cmos_riscos2.bin", "file": "bios/aa310.zip"}, + { "md5": "232a302efe19278d9df6ecbc8ea3dc6c", "zippedFile": "cmos_riscos3.bin", "file": "bios/aa310.zip"}, + { "md5": "", "file": "bios/archimedes_keyboard.zip" }, + { "md5": "1a8617c1abe3e0729d20ce844e1e12a8", "zippedFile": "acorn_0280,022-01_philips_8051ah-2.bin", "file": "bios/archimedes_keyboard.zip"} ] }, + + # ---------- Acorn Atom ---------- # + "atom": { "name": "Acorn Atom", "biosFiles": [ { "md5": "", "file": "bios/atom.zip" }, + { "md5": "b7b7f8a608339fa39d44a3bcfa2cc3f0", "zippedFile": "abasic.ic20", "file": "bios/atom.zip"}, + { "md5": "baa26f458acf5745388177ffc7368124", "zippedFile": "afloat.ic21", "file": "bios/atom.zip"}, + { "md5": "9627dfb5f8302db8dd5702dbf7c09f72", "zippedFile": "dosrom.u15", "file": "bios/atom.zip"} ] }, + + # ---------- Acorn Electron ---------- # + "electron": { "name": "Acorn Electron", "biosFiles": [ { "md5": "", "file": "bios/electron.zip" }, + { "md5": "4688a93aa298b9431c1788c9b90378c8", "zippedFile": "os_basic.ic2", "file": "bios/electron.zip"}, + { "md5": "", "file": "bios/electron64.zip" }, + { "md5": "2cc67be4624df4dc66617742571a8e3d", "zippedFile": "basic.rom", "file": "bios/electron64.zip"}, + { "md5": "df01cfe5894276de96bbd1c45b7e834c", "zippedFile": "os_300.rom", "file": "bios/electron64.zip"}, + { "md5": "", "file": "bios/electron_plus1.zip" }, + { "md5": "f3a39227b401a2ce8cdc7e4b7a860aaf", "zippedFile": "plus1.rom", "file": "bios/electron_plus1.zip"}, + { "md5": "", "file": "bios/electron_plus3.zip" }, + { "md5": "9aa334b4e8f6d7565e6323e0f77110de", "zippedFile": "acp_dfs1770_200.rom", "file": "bios/electron_plus3.zip"}, + { "md5": "83e15ca501899b0d5b2ce3f5ef696069", "zippedFile": "acp_dfs1770_210.rom", "file": "bios/electron_plus3.zip"}, + { "md5": "b60ee811f4b805638478acd5297b16e0", "zippedFile": "adfs.rom", "file": "bios/electron_plus3.zip"}, + { "md5": "62f5e1d3dae3a68d8fe4406a6f603dc3", "zippedFile": "pres_adfs_113.rom", "file": "bios/electron_plus3.zip"}, + { "md5": "5c39baa89fe8a40a5167a53cc5ae7791", "zippedFile": "pres_adfs_115.rom", "file": "bios/electron_plus3.zip"} ] }, + + # ---------- Apple ][ ---------- # + "apple2": { "name": "Apple II", "emulator": "libretro", "core": "mame", "biosFiles": [ { "md5": "", "file": "bios/apple2e.zip" }, + { "md5": "4431aea380185e3f509285540d7cb418", "zippedFile": "342-0132-c.e12", "file": "bios/apple2e.zip"}, + { "md5": "e6d453d8738e6df4f73df8c8051df3e8", "zippedFile": "342-0133-a.chr", "file": "bios/apple2e.zip"}, + { "md5": "72924019cf1719765e4fde35e59c1c7d", "zippedFile": "342-0134-a.64", "file": "bios/apple2e.zip"}, + { "md5": "0b150f4bfa090770a866cc5d214703f4", "zippedFile": "342-0135-b.64", "file": "bios/apple2e.zip"}, + { "md5": "", "file": "bios/apple2ee.zip" }, + { "md5": "b956c537e7b6b85ffa5c3493b1490d8a", "zippedFile": "341-0132-d.e12", "file": "bios/apple2ee.zip"}, + { "md5": "9123fff3442c0e688cc6816be88dd4ab", "zippedFile": "342-0265-a.chr", "file": "bios/apple2ee.zip"}, + { "md5": "6ac9338f6972eea01604f90d9a581f18", "zippedFile": "342-0303-a.e8", "file": "bios/apple2ee.zip"}, + { "md5": "6b11018a14668a7e3904319d2097dddc", "zippedFile": "342-0304-a.e10", "file": "bios/apple2ee.zip"}, + { "md5": "", "file": "bios/apple2p.zip" }, + { "md5": "89ca5cd551ffad9a557652a97dcb6627", "zippedFile": "341-0011.d0", "file": "bios/apple2p.zip"}, + { "md5": "42333f24cd6e70696b212b042f3166aa", "zippedFile": "341-0012.d8", "file": "bios/apple2p.zip"}, + { "md5": "5de50bebc41e59ae4eb27be4c24b6814", "zippedFile": "341-0013.e0", "file": "bios/apple2p.zip"}, + { "md5": "56d9bb6730735a3b2bbcc75d1da7a8de", "zippedFile": "341-0014.e8", "file": "bios/apple2p.zip"}, + { "md5": "cb63c41c5e72b5fda54feb5490efdefb", "zippedFile": "341-0015.f0", "file": "bios/apple2p.zip"}, + { "md5": "8925b695ae0177dd3919dbea2f2f202b", "zippedFile": "341-0020-00.f8", "file": "bios/apple2p.zip"}, + { "md5": "9ac0dc8c4d0002eb45b0b84be0bde5ec", "zippedFile": "341-0036.chr", "file": "bios/apple2p.zip"}, + { "md5": "", "file": "bios/a2diskiing.zip" }, + { "md5": "2020aa1413ff77fe29353f3ee72dc295", "zippedFile": "341-0027-a.p5", "file": "bios/a2diskiing.zip"}, + { "md5": "", "file": "bios/a2cffa02.zip" }, + { "md5": "80adbc2d79f347ec63f4b771ea32984d", "zippedFile": "cffa20ee02.bin", "file": "bios/a2cffa02.zip"}, + { "md5": "", "file": "bios/votrsc01.zip" }, + { "md5": "8ccf35a06f5e9a2131b0f42380ee5c15", "zippedFile": "sc01.bin", "file": "bios/votrsc01.zip"}, + { "md5": "", "file": "bios/votrsc01a.zip" }, + { "md5": "95b91e4a2fe7d6f13d353ba1827d37f9", "zippedFile": "sc01a.bin", "file": "bios/votrsc01a.zip"}, + { "md5": "", "file": "bios/d2fdc.zip" }, + { "md5": "5f1be0c1cdff26f5956eef9643911886", "zippedFile": "341-0028-a.rom", "file": "bios/d2fdc.zip"} ] }, + + # ---------- Apple IIgs ---------- # + "apple2gs": { "name": "Apple IIgs", "biosFiles": [ { "md5": "", "file": "bios/apple2gs.zip" }, + { "md5": "b956c537e7b6b85ffa5c3493b1490d8a", "zippedFile": "341-0132-d.e12", "file": "bios/apple2gs.zip"}, + { "md5": "b9f94f5d1be27dafcb8fe619ca3f4d15", "zippedFile": "341-0728", "file": "bios/apple2gs.zip"}, + { "md5": "e8e632aa592a61ef373b38af10ed54e1", "zippedFile": "341-0748", "file": "bios/apple2gs.zip"}, + { "md5": "c9e0e059faec0393fc429131a3af4ee9", "zippedFile": "341s0632-2.bin", "file": "bios/apple2gs.zip"}, + { "md5": "68ff96a624237d233e8d4c701f660dd1", "zippedFile": "apple2gs.chr", "file": "bios/apple2gs.zip"} ] }, + + # ---------- Camputers Lynx ---------- # + "camplynx": { "name": "Camputers Lynx", "biosFiles": [ { "md5": "", "file": "bios/lynx48k.zip" }, + { "md5": "b0ad5bf3070aea27b637e1998c81fa8c", "zippedFile": "lynx48-1.ic46", "file": "bios/lynx48k.zip"}, + { "md5": "b665e10211bbdbfaf2defb32d5580892", "zippedFile": "lynx48-2.ic45", "file": "bios/lynx48k.zip"}, + { "md5": "bc0760d8bf61c9683270266d259cd2ae", "zippedFile": "lynx4811.ic46", "file": "bios/lynx48k.zip"}, + { "md5": "dde90a794e5324002a9fd7f79cec3172", "zippedFile": "lynx4812.ic45", "file": "bios/lynx48k.zip"}, + { "md5": "", "file": "bios/lynx96k.zip" }, + { "md5": "a0a8f136f69b5891d33993627a185697", "zippedFile": "danish96k3.ic44", "file": "bios/lynx96k.zip"}, + { "md5": "fcb706b3ba2ba61f6f7af1c28f420f94", "zippedFile": "dosrom.rom", "file": "bios/lynx96k.zip"}, + { "md5": "815afa653b61cbe70936b01aff700912", "zippedFile": "lynx9644.ic44", "file": "bios/lynx96k.zip"}, + { "md5": "3ccdb9dfe6018892383fcbb1a9167d76", "zippedFile": "lynx9645.ic45", "file": "bios/lynx96k.zip"}, + { "md5": "01a9770efdab17f089bbbbe53f5d69fa", "zippedFile": "lynx9646.ic46", "file": "bios/lynx96k.zip"}, + { "md5": "89ba52f683cd79638646874e965476b6", "zippedFile": "skorprom.ic44", "file": "bios/lynx96k.zip"}, + { "md5": "", "file": "bios/lynx128k.zip" }, + { "md5": "fcb706b3ba2ba61f6f7af1c28f420f94", "zippedFile": "dosrom.rom", "file": "bios/lynx128k.zip"}, + { "md5": "5017fe3a2ea47038ae61e2aeb4f43d65", "zippedFile": "lynx128-1.ic1", "file": "bios/lynx128k.zip"}, + { "md5": "bf69d9538192f65571dbed43dc4a99bb", "zippedFile": "lynx128-2.ic2", "file": "bios/lynx128k.zip"}, + { "md5": "f9f54913cdedb22bb8f0c549ad121379", "zippedFile": "lynx128-3.ic3", "file": "bios/lynx128k.zip"} ] }, + + # ---------- Video Game Music Player ---------- # + "vgmplay": { "name": "Video Game Music Player", "biosFiles": [ { "md5": "", "file": "bios/qsound.zip" }, + { "md5": "108b113a596e800a02fece73f784eeb0", "zippedFile": "dl-1425.bin", "file": "bios/qsound.zip"}, + { "md5": "", "file": "bios/ym2413.zip" }, + { "md5": "96c11a92992bdff7f7e9d98a52621e1f", "zippedFile": "ym2413_instruments.bin", "file": "bios/ym2413.zip"}, + { "md5": "", "file": "bios/ym2608.zip" }, + { "md5": "8740932cda05e518a9955f1d08d6786f", "zippedFile": "ym2608_adpcm_rom.bin", "file": "bios/ym2608.zip"} ] }, + + # ---------- Epoch Game Pocket Computer ---------- # + "gamepock": { "name": "Epoch Game Pocket Computer", "biosFiles": [ { "md5": "", "file": "bios/gamepock.zip" }, + { "md5": "a0dd595eafb407a6a4b4ed800005a394", "zippedFile": "egpcboot.bin", "file": "bios/gamepock.zip"} ] }, + + # ---------- Tiger Game.com ---------- # + "gamecom": { "name": "Tiger Game.com", "biosFiles": [ { "md5": "", "file": "bios/gamecom.zip" }, + { "md5": "813364d4863b1d7b7b8fd6a97a416bcf", "zippedFile": "external.bin", "file": "bios/gamecom.zip"}, + { "md5": "f7bcefb6daf923c8e5ea2eb69f619efe", "zippedFile": "internal.bin", "file": "bios/gamecom.zip"} ] }, + + # ---------- Atari XEGS ---------- # + "xegs": { "name": "Atari XE Game System", "biosFiles": [ { "md5": "", "file": "bios/xegs.zip" }, + { "md5": "42cbd989802c17d0ac3731d33270d835", "zippedFile": "c101687.rom", "file": "bios/xegs.zip"} ] }, + + # ---------- VTech CreatiVision ---------- # + "crvision": { "name": "VTech CreatiVision", "biosFiles": [ { "md5": "", "file": "bios/crvision.zip" }, + { "md5": "3b1ef759d8e3fb4071582efd33dd05f9", "zippedFile": "crvision.u20", "file": "bios/crvision.zip"} ] }, + + # ---------- VTech V.Smile ---------- # + "vsmile": { "name": "VTech V.Smile", "biosFiles": [ { "md5": "", "file": "bios/vsmile.zip" }, + { "md5": "851ff77a89ec3f4f2793eb4aede30e5f", "zippedFile": "vsmile_v100.bin", "file": "bios/vsmile.zip"}, + { "md5": "f41fcc19ebe1e90fa359cd0df6293fab", "zippedFile": "vsmile_v102.bin", "file": "bios/vsmile.zip"}, + { "md5": "11e59253c578c8f16ea2375ec398e4e9", "zippedFile": "vsmile_v103.bin", "file": "bios/vsmile.zip"} ] }, + + # ---------- VTech Socrates ---------- # + "socrates": { "name": "VTech Socrates", "biosFiles": [ { "md5": "", "file": "bios/socrates.zip" }, + { "md5": "0efac0c2cc168c0d495e1c4e04ea9f5a", "zippedFile": "27-00817-000-000.u1", "file": "bios/socrates.zip"}, + { "md5": "99af124aa300ecd44f5dc9d5a2599778", "zippedFile": "speech_eng_internal.bin", "file": "bios/socrates.zip"}, + { "md5": "7046c2b27f51c9a5d33b4d6103f29acf", "zippedFile": "speech_eng_vsm1.bin", "file": "bios/socrates.zip"}, + { "md5": "6878302c362321eeee7e40d285cf7d30", "zippedFile": "speech_eng_vsm2.bin", "file": "bios/socrates.zip"}, + { "md5": "31c29c57e3d3e6788ba5817eaaa8b17a", "zippedFile": "speech_eng_vsm3.bin", "file": "bios/socrates.zip"} ] }, + + # ---------- Entex Aventure Vision ---------- # + "advision": { "name": "Entex Adventure Vision", "biosFiles": [ { "md5": "", "file": "bios/advision.zip" }, + { "md5": "5729638bd856c475678467a353bd921c", "zippedFile": "b225__ins8048-11kdp_n.u5", "file": "bios/advision.zip"}, + { "md5": "fc5e71445e4947a9d00eedbc66b13a8f", "zippedFile": "b8223__cop411l-kcn_n.u8", "file": "bios/advision.zip"} ] }, + + # ---------- Bitcorp Gamate ---------- # + "gamate": { "name": "Bitcorp Gamate", "biosFiles": [ { "md5": "", "file": "bios/gamate.zip" }, + { "md5": "b411167df6dd563111729296f4c547f6", "zippedFile": "gamate_bios_bit.bin", "file": "bios/gamate.zip"}, + { "md5": "ef67993a94503c4b7798b5901c7dda52", "zippedFile": "gamate_bios_umc.bin", "file": "bios/gamate.zip"} ] }, + + # ---------- Phillips CD-i ---------- # + "cdi": { "name": "Phillips CD-i", "biosFiles": [ { "md5": "", "file": "bios/cdimono1.zip" }, + { "md5": "2969341396aa61e0143dc2351aaa6ef6", "zippedFile": "cdi200.rom", "file": "bios/cdimono1.zip"}, + { "md5": "ac80a92c988ce07fbd6a8f21ded34cf1", "zippedFile": "cdi220.rom", "file": "bios/cdimono1.zip"}, + { "md5": "ac0d468be366779c9df633be98da250a", "zippedFile": "cdi220b.rom", "file": "bios/cdimono1.zip"}, + { "md5": "3e59b8a9a423d3ecd612a32fe4e2d748", "zippedFile": "zx405037p__cdi_servo_2.1__b43t__llek9215.mc68hc705c8a_withtestrom.7201", "file": "bios/cdimono1.zip"}, + { "md5": "3d20cf7550f1b723158b42a1fd5bac62", "zippedFile": "zx405042p__cdi_slave_2.0__b43t__zzmk9213.mc68hc705c8a_withtestrom.7206", "file": "bios/cdimono1.zip"} ] }, + + # ---------- Naomi 2 ---------- # + "naomi2": { "name": "Naomi 2", "biosFiles": [ { "md5": "", "file": "bios/dc/naomi2.zip" }, + { "md5": "728bfe038ce280872057e365ebfc0fee", "zippedFile": "315-6146.bin", "file": "bios/dc/naomi2.zip"}, + { "md5": "baf83367044924067e09856ba164aa6f", "zippedFile": "315-6215.bin", "file": "bios/dc/naomi2.zip"}, + { "md5": "6f8ad6e3ab04c8ae1cbcaa652b91cf4e", "zippedFile": "epr-23605.ic27", "file": "bios/dc/naomi2.zip"}, + { "md5": "f3f39513484df216d9979f6ae7577942", "zippedFile": "epr-23605a.ic27", "file": "bios/dc/naomi2.zip"}, + { "md5": "ab046e62c51d67fb89eade2b8d5f6a8d", "zippedFile": "epr-23605b.ic27", "file": "bios/dc/naomi2.zip"}, + { "md5": "096a5217ff6e6c6cafe65a03336760ab", "zippedFile": "epr-23605c.ic27", "file": "bios/dc/naomi2.zip"}, + { "md5": "659d579ba9aef5b025d87323044e83f4", "zippedFile": "epr-23605c_multi.ic27", "file": "bios/dc/naomi2.zip"}, + { "md5": "cbe0984d03d73869c23da5a3dd2ce207", "zippedFile": "epr-23607.ic27", "file": "bios/dc/naomi2.zip"}, + { "md5": "b624ec7b3b90fdf3be103cdfb1679d1d", "zippedFile": "epr-23607b.ic27", "file": "bios/dc/naomi2.zip"}, + { "md5": "a9d82db14b823a5a57885bea1a998eb7", "zippedFile": "epr-23607c.ic27", "file": "bios/dc/naomi2.zip"}, + { "md5": "3b1315be24dc8d17f4fa18f3bfc5fe5c", "zippedFile": "epr-23608.ic27", "file": "bios/dc/naomi2.zip"}, + { "md5": "0143cf852cb2a8a41f217bc688f62105", "zippedFile": "epr-23608a.ic27", "file": "bios/dc/naomi2.zip"}, + { "md5": "8b88c1f5a06e9b560e887c3b9f879237", "zippedFile": "epr-23608b.ic27", "file": "bios/dc/naomi2.zip"}, + { "md5": "b49702e4fadb3b5f9143a3d20afd04b5", "zippedFile": "epr-23608c.ic27", "file": "bios/dc/naomi2.zip"}, + { "md5": "ecadb008179ca1e6f4fe3fa091ab5df2", "zippedFile": "epr-23609b.ic27", "file": "bios/dc/naomi2.zip"}, + { "md5": "edeed38a9795e062a9af28c3eba22040", "zippedFile": "main_eeprom.bin", "file": "bios/dc/naomi2.zip"}, + { "md5": "14e6bffff0d4dff6a5a547e7c43680ff", "zippedFile": "sp5001.bin", "file": "bios/dc/naomi2.zip"}, + { "md5": "689d2228b00fb59781f82af6e8ecdb78", "zippedFile": "sp5001-a.bin", "file": "bios/dc/naomi2.zip"}, + { "md5": "8373a11106c1c2fc21ac839f75ea488f", "zippedFile": "sp5001-b.bin", "file": "bios/dc/naomi2.zip"}, + { "md5": "7eecfb8e8f82b47ffab92a0c5528100e", "zippedFile": "sp5002-a.bin", "file": "bios/dc/naomi2.zip"}, + { "md5": "960ece0dc22a7c5ff81c812a2993e7cc", "zippedFile": "x76f100_eeprom.bin", "file": "bios/dc/naomi2.zip"} ] }, + + # ---------- Hikaru ---------- # + "hikaru": { "name": "Hikaru", "biosFiles": [ { "md5": "aac601811a25d7b31a3d5f3f1f82f338", "file": "bios/hikaru.zip" }, + { "md5": "e95415b161121bef35ade12367138c63", "file": "bios/mie.zip"} ] }, + + # ---------- Playstation Vita ---------- # + # https://www.playstation.com/en-us/support/hardware/psvita/system-software/ + # http://dus01.psp2.update.playstation.net/update/psp2/image/2022_0209/sd_59dcf059d3328fb67be7e51f8aa33418/PSP2UPDAT.PUP?dest=us + "psvita": { "name": "PS Vita", "biosFiles": [ { "md5": "59dcf059d3328fb67be7e51f8aa33418", "file": "bios/psvita/PSP2UPDAT.PUP" }, + { "md5": "f2c7b12fe85496ec88a0391b514d6e3b", "file": "bios/psvita/PSVUPDAT.PUP"} ] }, + + # ---------- GCE Vectrex ---------- # + # Not required for libretro-vecx, the default emulator + "vectrex": { "name": "GCE Vectrex", "emulator": "libretro", "core": "mame", "biosFiles": [ { "md5": "", "file": "bios/vectrex.zip" }, + { "md5": "ab082fa8c8e632dd68589a8c7741388f", "zippedFile": "exec_rom.bin", "file": "bios/vectrex.zip"}, + { "md5": "a9c238473229912eb757ff3dfe6f4631", "zippedFile": "exec_rom_intl_284001-1.bin", "file": "bios/vectrex.zip"} ] }, + + # ---------- ScummVM ---------- # + "scummvm": { "name": "ScummVM", "biosFiles": [ { "md5": "89e42e386e82e0cacb4a2704a03706ca", "file": "bios/scummvm/extra/MT32_PCM.ROM" }, + { "md5": "5626206284b22c2734f3e9efefcd2675", "file": "bios/scummvm/extra/MT32_CONTROL.ROM" } ] }, + + # ---------- MSX1/MSX2 ---------- # + #https://github.com/openMSX/openMSX/blob/master/share/machines/Boosted_MSX2_EN.txt + "msx1": { "name": "MSX1/MS2", "biosFiles": [ { "md5": "01dd1d72ed9bb6afe8a9b441c198a1cd", "file": "bios/openmsx/nms8250_disk.rom" }, + { "md5": "ec3a01c91f24fbddcbcab0ad301bc9ef", "file": "bios/openmsx/nms8250_basic-bios2.rom" }, + { "md5": "2183c2aff17cf4297bdb496de78c2e8a", "file": "bios/openmsx/nms8250_msx2sub.rom" }, + { "md5": "6f69cc8b5ed761b03afd78000dfb0e19", "file": "bios/openmsx/fmpac.rom" }, + { "md5": "2ce20986da024e9a0e271961c6bc9f01", "file": "bios/openmsx/phc-70fd2_basickun.rom" }, + { "md5": "42af93619160ef2116416f74a6cb12f2", "file": "bios/openmsx/yrw801.rom" } ] }, + + # ---------- MSX LaserDisc ---------- # + #https://github.com/openMSX/openMSX/blob/master/share/machines/Pioneer_PX-7.xml + "msx1": { "name": "MSX LaserDisc", "biosFiles": [ { "md5": "281809cafe63437fc4bffb3033fbd0db", "file": "bios/openmsx/px-7_pbasic.rom" }, + { "md5": "9218f6dd89f7ba01e3090d44721b4260", "file": "bios/openmsx/px-7_basic-bios1.rom" } ] }, + + # ---------- MSX2+ ---------- # + #https://github.com/openMSX/openMSX/blob/master/share/machines/Boosted_MSX2+_JP.txt + "msx2+": { "name": "MSX2+", "biosFiles": [ { "md5": "acf53887c2d2783dc059a9b442c86b90", "file": "bios/openmsx/fs-a1wsx_kanjifont.rom" }, + { "md5": "c5c26c3e8bc6c485424818057f0507b9", "file": "bios/openmsx/fs-a1wsx_basic-bios2p.rom" }, + { "md5": "0c40e7db1c1fcc2405e4d0cdd215adb4", "file": "bios/openmsx/fs-a1wsx_fmbasic.rom" }, + { "md5": "7c8243c71d8f143b2531f01afa6a05dc", "file": "bios/openmsx/fs-a1wsx_msx2psub.rom" }, + { "md5": "9dfdebfaa6b547222a40aab8bb2e29f8", "file": "bios/openmsx/fs-a1wsx_kanjibasic.rom" }, + { "md5": "00aa02b6077de40a0b51d71a3c3e1d5f", "file": "bios/openmsx/fs-a1wsx_disk.rom" }, + { "md5": "fa8e7d4b999af058fe2864a5f2e014ec", "file": "bios/openmsx/fs-a1wsx_firmware.rom" }, + { "md5": "2ce20986da024e9a0e271961c6bc9f01", "file": "bios/openmsx/phc-70fd2_basickun.rom" }, + { "md5": "42af93619160ef2116416f74a6cb12f2", "file": "bios/openmsx/yrw801.rom" } ] }, + + # ---------- MSX-Turbo ---------- # + #https://github.com/openMSX/openMSX/blob/master/share/machines/Panasonic_FS-A1GT.xml + "msxturbor": { "name": "MSX-Turbo", "biosFiles": [ { "md5": "af17a344bcc177b97a4888c4c559f3ae", "file": "bios/openmsx/fs-a1gt_firmware.rom" }, + { "md5": "acf53887c2d2783dc059a9b442c86b90", "file": "bios/openmsx/fs-a1gt_kanjifont.rom" }, + { "md5": "afa4b5f2944334f84971af814a24bd5a", "file": "bios/openmsx/ide250.zip" }, + { "md5": "2ce20986da024e9a0e271961c6bc9f01", "file": "bios/openmsx/phc-70fd2_basickun.rom" }, + { "md5": "42af93619160ef2116416f74a6cb12f2", "file": "bios/openmsx/yrw801.rom" } ] }, + + # ---------- Supr'A'can ---------- # + "supracan": { "name": "Supr'A'can", "biosFiles": [ { "md5": "", "file": "bios/supracan.zip" }, + { "md5": "53c4343e062bb3b337370bbb58e64d16", "zippedFile": "internal_68k.bin", "file": "bios/supracan.zip" } ] }, + + # ---------- Tandy VIS ---------- # + "vis": { "name": "Tandy Video Information System", "biosFiles": [ { "md5": "", "file": "bios/vis.zip" }, + { "md5": "ebf432d3b09f694db1c62018eb2ab471", "zippedFile": "p513bk0b.bin", "file": "bios/vis.zip"}, + { "md5": "758f8fec271fbf526bb22b36e88f154b", "zippedFile": "p513bk1b.bin", "file": "bios/vis.zip"} ] }, + + # ---------- GameCube ---------- # + "n64dd": { "name": "Nintendo 64DD", "biosFiles": [ { "md5": "8d3d9f294b6e174bc7b1d2fd1c727530", "file": "bios/64DD_IPL.bin" } ] }, + + # ---------- GameCube ---------- # + "gamecube": { "name": "Nintendo GameCube", "biosFiles": [ { "md5": "db92574caab77a7ec99d4605fd6f2450", "file": "bios/GC/EUR/IPL.bin" }, + { "md5": "b17148254a5799684c7d783206504926", "file": "bios/GC/JAP/IPL.bin" }, + { "md5": "b17148254a5799684c7d783206504926", "file": "bios/GC/USA/IPL.bin" } ] }, + + # ---------- Sega Chihiro ---------- # + "chihiro": { "name": "Sega Chihiro", "biosFiles": [{ "md5": "d49c52a4102f6df7bcf8d0617ac475ed", "file": "bios/mcpx_1.0.bin" }, + { "md5": "f23d7e00ae8fbf88908ed1f9165f35eb", "file": "bios/cerbios.bin" }] }, +} + +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 checkInsideZip(container, fileName, md5sum): + # Check inside Zip files + try: + archive = zipfile.ZipFile(container) + except Exception as e: + print ('Error opening file {}: {}.'.format(container, e)) + return False + blocksize = 1024**2 #1M chunks + for fname in archive.namelist(): + # Only check if the file matches + if fname.casefold() == fileName.casefold(): + if md5sum == "": + return True + archive = zipfile.ZipFile(container) + blocksize = 1024**2 #1M chunks + for fname in archive.namelist(): + if fname == fileName: + entry = archive.open(fname) + zippedHash = md5() + while True: + block = entry.read(blocksize) + if not block: + break + zippedHash.update(block) + if zippedHash.hexdigest() == md5sum: + return True + else: + print('Mismatch inside .zip: File {} in {} has MD5 {} (expected {})'.format(fileName, container, zippedHash.hexdigest(), md5sum)) + return False + # File was not found in zip. + print('Missing file inside .zip: File {} not found in {}'.format(fileName, container)) + return False + +def coreExists(checkMe, emuDict): + if "emulator" in checkMe: + if checkMe["emulator"] in emuDict.keys(): + hasEmu = True + else: + hasEmu = False + else: + # Emulator not defined, check BIOS + hasEmu = True + if hasEmu and "core" in checkMe: + if checkMe["core"] in emuDict[checkMe["emulator"]]: + hasCore = True + else: + hasCore = False + else: + # Either core is undefined or emulator is not installed. + # Set core presence to emulator presence, we'll assume there's only one core or it applies to all. + hasCore = hasEmu + return hasCore + +def checkBios(systems, prefix, filterROMs): + systemDict = {} + emuDict = {} + systemName = "" + configFile = "/storage/.config/emulationstation/es_systems.cfg" + configData = elementTree.parse(configFile) + configRoot = configData.getroot() + + if filterROMs: + # Load systems & emulators from es_systems.cfg + # System full name stored but not currently used, may be useful for the readme function. + for activeSystem in configRoot: + for systemTag in activeSystem: + if systemTag.tag == "fullname": + systemName = systemTag.text + elif systemTag.tag == "name": + systemDict[systemTag.text] = systemName + systemName = "" + elif systemTag.tag == "emulators": + for emulatorTag in systemTag: + emulatorName = emulatorTag.attrib['name'] + for coreTag in emulatorTag[0]: + if emulatorName in emuDict.keys(): + if not coreTag.text in emuDict[emulatorName]: + emuDict[emulatorName].append(coreTag.text) + else: + emuDict[emulatorName] = [coreTag.text] + else: + for system in systems.keys(): + systemDict[system] = systems[system]['name'] + + missingBios = {} + for system in systems.keys(): + if system in systemDict.keys(): + if coreExists(systems[system], emuDict) or filterROMs == False: + for file in systems[system]["biosFiles"]: + if coreExists(file, emuDict) or filterROMs == False: + filepath = prefix + "/" + file["file"] + if isfile(filepath): + if not "zippedFile" in file: + md5 = md5sum(filepath) + if md5 != file["md5"] and file["md5"] != "": + if system not in missingBios: + missingBios[system] = {} + missingBios[system][file["file"]] = { "status": BiosStatus.UNTESTED, "md5": file["md5"], "file": file["file"] } + else: + if 'altmd5' in file: + if not checkInsideZip(filepath, file["zippedFile"], file["md5"], file["altmd5"]): + if system not in missingBios: + missingBios[system] = {} + missingBios[system][file["file"]] = { "status": BiosStatus.UNTESTED, "md5": file["md5"], "file": file["file"] } + else: + if not checkInsideZip(filepath, file["zippedFile"], file["md5"]): + if system not in missingBios: + missingBios[system] = {} + missingBios[system][file["file"]] = { "status": BiosStatus.UNTESTED, "md5": file["md5"], "file": file["file"] } + else: + if system not in missingBios: + missingBios[system] = {} + missingBios[system][file["file"]] = { "status": BiosStatus.MISSING, "md5": file["md5"], "file": file["file"] } + return missingBios + +def displayMissingBios(systems, missingBios): + sortedMissingBios = OrderedDict(sorted(missingBios.items())) + if sortedMissingBios: + for system in sortedMissingBios: + print("> {}".format(system)) + 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"])) + else: + print("No missing bios") + +def createReadme(systems): + for system in sorted(systems): + print("{}:".format(systems[system]["name"])) + for bios in systems[system]["biosFiles"]: + print("{} {}".format(bios["md5"], bios["file"])) + print("") + +if __name__ == '__main__': + if len(sys.argv) == 1: + prefix = "/storage/roms" + displayMissingBios(systems, checkBios(systems, prefix, True)) + elif sys.argv[1] == "--noFilter": + prefix = "/storage/roms" + displayMissingBios(systems, checkBios(systems, prefix, False)) + elif sys.argv[1] == "--createReadme": + createReadme(systems) + elif len(sys.argv) == 3 and sys.argv[1] == "--filter": + prefix = "/storage/roms" + lowered_name = sys.argv[2].lower() + + filtered_systems = {} + for system in systems: + if lowered_name in system.lower() or lowered_name in systems[system]['name'].lower(): + filtered_systems[system] = systems[system] + + if len(filtered_systems) == 0: + print("No system named {} found".format(sys.argv[2])) + exit(1) + + displayMissingBios(filtered_systems, checkBios(filtered_systems, prefix, True)) diff --git a/projects/ArchR/packages/archr/sources/scripts/archr-update b/projects/ArchR/packages/archr/sources/scripts/archr-update new file mode 100755 index 0000000000..7124053e38 --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/archr-update @@ -0,0 +1,188 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2026 ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile + +BRANCH="$(get_setting updates.branch)" +FORCE="$(get_setting updates.force)" + +ENDPOINT_URL="https://update.arch-r.io" + +MACHINEIDFILE=/storage/.cache/systemd-machine-id +USERID=$(cat ${MACHINEIDFILE}) + +# Function to check for an update. It returns a URL if an update is available. +check_update() { + custom_force="${1:-$FORCE}" + + update_url=$(curl -s -S -X POST \ + -F "OS=${OS_NAME}" \ + -F "ARCH=${HW_ARCH}" \ + -F "SOC=${HW_DEVICE}" \ + -F "VERSION=${OS_VERSION}" \ + -F "UID=${USERID:(-12)}" \ + -F "BUILD=${OS_BUILD}" \ + -F "DEV=${QUIRK_DEVICE}" \ + -F "FORCE=${custom_force}" \ + -F "BRANCH=${BRANCH}" \ + "$ENDPOINT_URL") + echo "$update_url" + return $? +} + +# Function to get list of releases +get_releases() { + releases=$(curl -s -S -X POST \ + -F "OS=${OS_NAME}" \ + -F "ARCH=${HW_ARCH}" \ + -F "SOC=${HW_DEVICE}" \ + -F "BRANCH=${BRANCH}" \ + -F "LIST=1" \ + "$ENDPOINT_URL") + echo "$releases" + return $? +} + +# Returns 0 if there is enough available free space at target_path in megabytes. +check_disk_space() { + target_path=$1 + required_mB=$2 + available_mB=$(df -m "$target_path" | awk 'NR==2 {print $4}') + if [ "$available_mB" -ge "$required_mB" ]; then + return 0 + else + return 1 + fi +} + +# Download a file from url to destination and show progress. +download_file() { + url=$1 + destination=$2 + curl --progress-bar -S -L "$url" -o "$destination" + return $? +} + +# Main update logic. +main_update() { + custom_force="${1:-$FORCE}" + update_url=$(check_update "$custom_force") + + # Check if the returned update_url looks like a URL (e.g., starts with http) + case "$update_url" in + http://*|https://*) + echo "Update available at: $update_url" ;; + *) + echo "No update available or invalid update URL." + exit 1 + ;; + esac + + # Check that there is at least 2GB of available free space on /storage. + if ! check_disk_space "/storage" "2048"; then + echo "Not enough free space on /storage (need at least 2GB)." + exit 1 + fi + + # Ensure that the /storage/.update folder exists. + if [ ! -d "/storage/.update" ]; then + mkdir -p /storage/.update || { echo "Failed to create /storage/.update directory."; exit 1; } + fi + + # Extract the file name from the update URL. + filename=$(basename "$update_url") + + # Define download destinations inside /storage/.update folder using the original file names. + update_file="/storage/.update/${filename}" + checksum_file="/storage/.update/${filename}.sha256" + + # Download the update file. + echo "Downloading update file..." + download_file "$update_url" "$update_file" + if [ $? -ne 0 ]; then + echo "Failed to download update file." + exit 1 + fi + + # Download the checksum file (append .sha256 to the update URL). + checksum_url="${update_url}.sha256" + echo "Downloading checksum file..." + download_file "$checksum_url" "$checksum_file" + if [ $? -ne 0 ]; then + echo "Failed to download checksum file." + rm -f "$update_file" + exit 1 + fi + + # Verify checksum. + echo "Verifying the downloaded update..." + expected_checksum=$(awk '{print $1}' "$checksum_file") + actual_checksum=$(sha256sum "$update_file" | awk '{print $1}') + if [ "$expected_checksum" = "$actual_checksum" ]; then + echo "Checksum verified successfully. Reboot to apply the update." + set_setting updates.force 0 + sync + else + echo "Checksum verification failed. Removing downloaded files." + rm -f "$update_file" "$checksum_file" + exit 1 + fi +} + +# Check network connectivity (ping DNS server) +if ! ping -c 1 8.8.8.8 >/dev/null 2>&1; then + echo "Network connection unavailable." + exit 1 +fi + +# Read the first argument to determine the mode. +mode=$1 + +# Check if the mode is a number (e.g., 20250101), which indicates forcing a specific version +if echo "$mode" | grep -q '^[0-9]\{8\}$'; then + # If mode is a date (8 digits), treat it as a forced version + echo "Forcing update to version $mode..." + main_update "$mode" + exit 0 +fi + +case "$mode" in + check) + update_url=$(check_update) + case "$update_url" in + http://*|https://*) + # Extract the filename from the URL. + filename=$(basename "$update_url") + # Use shell parameter expansion to remove everything up to the last dash, then remove the .tar suffix. + version=${filename##*-} + version=${version%.tar} + echo "$version" + exit 0 + ;; + *) + echo "No update available." + exit 1 + ;; + esac + ;; + releases) + # Get the list of available releases + echo "Checking available releases..." + releases=$(get_releases) + echo "$releases" + exit 0 + ;; + update|"") + # If mode is "update" or no argument is provided, proceed with the update. + main_update + ;; + *) + echo "Usage: $0 [check|update|releases|]" + echo " check - Check for available updates and print version" + echo " update - Update to the latest version" + echo " releases - Show available releases" + echo " - Force update to specific version (e.g., 20250101)" + exit 1 + ;; +esac diff --git a/projects/ArchR/packages/archr/sources/scripts/automount b/projects/ArchR/packages/archr/sources/scripts/automount new file mode 100755 index 0000000000..f6492d64d4 --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/automount @@ -0,0 +1,258 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile +. /etc/os-release + +### Vars +UPDATE_ROOT="/storage/.update" +MOUNT_GAMES=$(get_setting system.automount) +GAMES_DEVICE=$(get_setting system.gamesdevice) +MS_PATH="/storage/roms" + +function unmount() { + log $0 "Unmount ${1}." + umount -f "${1}" 2>/dev/null ||: +} + +function start_ms() { + ### Entrypoint will be either games card found (external), or not found (internal). + MOUNT_PATH="/storage/games-${1}" + + MS_DEVICE=$(get_setting system.merged.device) + ### If the merge target isn't defined and we have an external microsd, we should use the external card by default. + if [ -z "${MS_DEVICE}" ] && \ + [ "${1}" = "external" ] + then + set_setting system.merged.device external + fi + + ### Determine if internal or external is the primary target by configuration. + case ${MS_DEVICE} in + internal) + LOWER="external" + UPPER="internal" + ;; + *) + LOWER="internal" + UPPER="external" + ;; + esac + + # Ensure roms directory exists directly on the partition + if [ ! -d "/storage/roms" ]; then + mkdir -p "/storage/roms" + fi + + # Migrate: if games-internal/roms has content but roms/ is empty, move it + if [ -d "/storage/games-internal/roms" ] && [ "$(ls -A /storage/games-internal/roms 2>/dev/null)" ] && [ ! "$(ls -A /storage/roms 2>/dev/null)" ]; then + log $0 "Migrating ROMs from games-internal/roms/ to roms/" + mv /storage/games-internal/roms/* /storage/roms/ 2>/dev/null + rmdir /storage/games-internal/roms 2>/dev/null + ln -sf /storage/roms /storage/games-internal/roms 2>/dev/null + fi + + # Backwards compat: symlink games-internal/roms → roms if not already + if [ ! -L "/storage/games-internal/roms" ] && [ ! -d "/storage/games-internal/roms" ]; then + mkdir -p /storage/games-internal + ln -sf /storage/roms /storage/games-internal/roms + fi + + # Ensure external games dir exists for dual-SD support + if [ ! -d "/storage/games-external/roms" ]; then + mkdir -p "/storage/games-external/roms" + fi + + MS_ENABLED=$(get_setting system.merged.storage) + if [ -e "/storage/.ms_unsupported" ] || \ + [ ! "${MS_ENABLED}" = 1 ] + then + # Single SD: /storage/roms is used directly (no bind mount needed) + log $0 "Using /storage/roms directly" + else + log $0 "Enabling merged storage of /storage/games-${LOWER} and /storage/games-${UPPER} to ${MS_PATH}." + + for DIR in /storage/games-${UPPER}/.tmp/games-workdir /storage/games-${LOWER}/roms /storage/games-${UPPER}/roms + do + if [ ! -d "${DIR}" ] + then + mkdir -p "${DIR}" + fi + done + mount overlay -t overlay -o lowerdir=/storage/games-${LOWER}/roms,upperdir=/storage/games-${UPPER}/roms,workdir=/storage/games-${UPPER}/.tmp/games-workdir ${MS_PATH} + fi +} + +start_overlay() { + if [ -e "/storage/.overlay_unsupported" ] + then + # If we're not using the overlay, bind mount the external storage path + # so we don't need to change any configs. + grep ${MOUNT_PATH} /proc/mounts >/dev/null 2>&1 + if [ ! $? = 0 ] + then + MOUNT_PATH="/storage/games-internal" + fi + log $0 "Executing bind mount of ${MOUNT_PATH} to ${OVERLAY_PATH}" + mount --bind ${MOUNT_PATH} ${OVERLAY_PATH} + exit 0 + else + log $0 "Enabling overlay." + systemctl enable storage-roms.mount >/dev/null 2>&1 + systemctl start storage-roms.mount >/dev/null 2>&1 + fi +} + +if [[ ! "${MOUNT_GAMES}" =~ [0-9] ]] +then + set_setting system.automount 1 +elif [[ "${MOUNT_GAMES}" == "0" ]] +then + start_ms internal + exit 0 +fi + +function create_game_dirs() { + ### We don't want systemd to manage this or the directories could be created in the wrong location. + if [ -e "/usr/config/system-dirs.conf" ] + then + log $0 "Creating game directories." + systemd-tmpfiles --create /usr/config/system-dirs.conf >/dev/null 2>&1 ||: + fi +} + +function load_modules() { + for MODULE in exfat vfat ntfs ntfs3 + do + lsmod | grep ${MODULE} >/dev/null 2>&1 + if [ ! $? = 0 ] + then + log $0 "Loading ${MODULE}." + modprobe ${MODULE} >/dev/null 2>&1 + fi + done +} + +function mount_games() { + MOUNT_PATH="/storage/games-external" + FSTYPE=$(blkid -o export ${1} | awk 'BEGIN {FS="="} /TYPE/ {print $2}') + case ${FSTYPE} in + ext4 | btrfs) + log $0 "Found supported partition for overlayfs." + if [ -e "/storage/.ms_unsupported" ] + then + rm -f /storage/.ms_unsupported + fi + touch /storage/.ms_supported + ;; + *) + log $0 "Partition does not support overlayfs, disabling." + if [ -e "/storage/.ms_supported" ] + then + rm -f /storage/.ms_supported + fi + touch /storage/.ms_unsupported + ;; + esac + + # busybox has some weird behaviour with helpers. + # Despite mount.ntfs is present, it is not used, so just a stupid rewrite to use newer kernel ntfs3 driver + case ${FSTYPE} in + ntfs) MOUNT_ARGS="-t ntfs3" ;; + *) true ;; + esac + + if [ ! -d "${MOUNT_PATH}" ] + then + log $0 "Create directory ${MOUNT_PATH}" + /usr/bin/busybox mkdir -p ${MOUNT_PATH} >/dev/null 2>&1 + fi + + NULL=$(cat /proc/mounts | grep -v -e "/var/media" 2>/dev/null | grep ${1}) + if [ ! "$?" = "0" ] && \ + [ -e "${1}" ] && \ + [ ! -e "/storage/.please_resize_me" ] + then + + ### Udevil shouldn't mount it this early, but just in-case. + umount /var/media/* 2>/dev/null + + log $0 "Mounting ${1} on ${MOUNT_PATH}" + /usr/bin/busybox mount ${MOUNT_ARGS} ${1} ${MOUNT_PATH} >/dev/null 2>&1 + + log $0 "Checking filesystem ${1}." + if ! touch "${MOUNT_PATH}/.tmp-archr"; then + log $0 "Fixing filesystem ${1}." + /usr/bin/busybox umount ${1} >/dev/null 2>&1 + /usr/sbin/fsck -Mly ${1} >/dev/null 2>&1 + /usr/bin/busybox mount ${MOUNT_ARGS} ${1} ${MOUNT_PATH} >/dev/null 2>&1 + else + rm "${MOUNT_PATH}/.tmp-archr" + fi + fi + start_ms external + create_game_dirs + exit 0 +} + +function find_games() { + if /usr/bin/busybox mountpoint -q /storage + then + for DEV in $(for dev in mmcblk[0-9] sd[a-z] nvme[0-9]n[0-9]; do blkid | grep ${dev} | awk 'BEGIN {FS=":"}; /ext4/ || /btrfs/ || /fat/ || /ntfs/ {print $1}' | sort -r; done) + do + ROOTDEV=$(echo ${DEV} | sed -e "s#^/.*/##g" -e "s#p[0-9].*\$##g") + log $0 "Inspecting ${DEV}." + SIZE=$(awk '/'${ROOTDEV}'$/ {print $3}' /proc/partitions) + if (( ${SIZE} <= 8388608 )) + then + log $0 "Device ${ROOTDEV} is too small, ignoring." + # We don't want to mount partitions smaller than ~8GB. + continue + fi + if [ -L "/sys/class/block/${ROOTDEV}boot0" ] + then + log $0 "Device ${ROOTDEV} might be Android, ignoring." + # Assume this is an android boot device and ignore it. + continue + fi + ISMOUNTED="$(grep "${DEV}" /proc/mounts) >/dev/null 2>&1" + if [ ! "$?" = 0 ] && \ + [ -e "${DEV}" ] && \ + [ ! -e "/storage/.please_resize_me" ] + then + GAMES_DEVICE=${DEV} + log $0 "Found ${DEV} available to mount." + mount_games "${DEV}" + else + log $0 "${DEV} not available." + fi + done + log $0 "Could not find external card to mount, assume internal." + + MS_DEVICE=$(get_setting system.merged.device) + ### If the merge target isn't defined and we do not have an external microsd, we should use the internal card by default. + if [ -z "${MS_DEVICE}" ] + then + set_setting system.merged.device internal + fi + start_ms internal + create_game_dirs + exit 0 + fi +} + +## Main.. + +load_modules + +### Unmount any existing storage before beginning operations. +unmount /storage/games-external +unmount /storage/roms + +if [ -e "${GAMES_DEVICE}" ] +then + mount_games ${GAMES_DEVICE} +else + find_games +fi diff --git a/projects/ArchR/packages/archr/sources/scripts/backuptool b/projects/ArchR/packages/archr/sources/scripts/backuptool new file mode 100755 index 0000000000..805c960cf0 --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/backuptool @@ -0,0 +1,69 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile + +# NOTE: to customize your backups, create a backuptool.conf file in +# /storage/.config like this: + +# LOCATIONS=( +# /storage/.config/retroarch/* +# /storage/roms/savestates/* +# /some/other/folder/file.name* +# ) + +BACKUPFOLDER="/storage/roms/backup" +BACKUPFILE="${BACKUPFOLDER}/${OS_NAME}_BACKUP.zip" +mkdir -p ${BACKUPFOLDER} + +DEFAULT=( + /storage/.config/fancontrol.conf + /storage/.config/backuptool.conf + /storage/.cache/bluetooth/* + /storage/.cache/connman* + /storage/.config/system/configs/system.cfg + /storage/.config/ppsspp/* + /storage/.config/retroarch/* + /storage/.config/moonlight/* + /storage/.config/game/* + /storage/.emulationstation/es_*.cfg + /storage/.emulationstation/scripts/* + /storage/.emulationstation/themesettings/* + $(find /storage/.emulationstation/themes/* -type d -maxdepth 0 -not -path "*es-theme-art-book-next" -not -path "*system-theme") +) + +if [ -e "/storage/.config/backuptool.conf" ] +then + source /storage/.config/backuptool.conf + if [ ! $? = 0 ] + then + WARN="Error loading custom backuptool configs. Using defaults." + ${DEBUG} && echo "${WARN}" + logger -t backuptool "${WARN}" + COMPRESSLOCATIONS=(${DEFAULT[@]}) + else + COMPRESSLOCATIONS=(${LOCATIONS[@]}) + fi +else + COMPRESSLOCATIONS=(${DEFAULT[@]}) +fi + +case "${1}" in + "restore") + unzip -o ${BACKUPFILE} -d / + ;; + "backup") + if [ -f ${BACKUPFILE} ] + then + TODAY=`date +%y-%m-%d_%H_%M_%S` + ARCHIVEFILENAME="ARCHIVED_${OS_NAME}_BACKUP-${TODAY}.zip" + mv ${BACKUPFILE} "${BACKUPFOLDER}/${ARCHIVEFILENAME}" + fi + [ -f "${BACKUPFILE}" ] && rm "${BACKUPFILE}" + zip -9 -r ${BACKUPFILE} \ + ${COMPRESSLOCATIONS[@]} + ;; +esac diff --git a/projects/ArchR/packages/archr/sources/scripts/bezels.sh b/projects/ArchR/packages/archr/sources/scripts/bezels.sh new file mode 100755 index 0000000000..283e47415c --- /dev/null +++ b/projects/ArchR/packages/archr/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/system/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/system/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 AMD64 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 AMD64 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/projects/ArchR/packages/archr/sources/scripts/brightness b/projects/ArchR/packages/archr/sources/scripts/brightness new file mode 100755 index 0000000000..cb41a5fa0c --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/brightness @@ -0,0 +1,224 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-24 JELOS (https://github.com/JustEnoughLinuxOS) +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +## Load minimal distribution settings to improve +## performance. +. /etc/profile.d/001-functions + +declare -a BRIGHTNESS_DEVS=() +while IFS= read -r line; do + BRIGHTNESS_DEVS+=("$line") +done < <(find /sys/class/backlight/*/ -name brightness 2>/dev/null) + +NUM_DEVS="${#BRIGHTNESS_DEVS[@]}" + +if [ "${NUM_DEVS}" -eq 0 ]; then + echo "ERROR: No backlight devices found in /sys/class/backlight/." >&2 + exit 1 +fi + +declare -a MAX_VALUES=() +for dev_path in "${BRIGHTNESS_DEVS[@]}"; do + DIR="$(dirname "${dev_path}")" + MAX_FILE="${DIR}/max_brightness" + if [ -f "${MAX_FILE}" ]; then + MAX_VALUES+=("$(<"${MAX_FILE}")") + else + MAX_VALUES+=(100) + fi +done + +CURRENT_DEV_PATH="" +CURRENT_MAX=0 +CURRENT_SETTING_KEY="" +SCREEN_INPUT=1 + +_compute_raw() { + local percent="${1}" + local max_val="${2}" + echo "(${percent} / 100 * ${max_val})" | bc -l | cut -f1 -d. +} + +_resolve_config() { + SCREEN_INPUT="${1}" + + if ! [[ "${SCREEN_INPUT}" =~ ^[1-9][0-9]*$ ]]; then + echo "ERROR: Screen number must be a positive integer." >&2 + return 1 + fi + + local dev_index=$((SCREEN_INPUT - 1)) + + if [ "${dev_index}" -lt 0 ] || [ "${dev_index}" -ge "${NUM_DEVS}" ]; then + echo "ERROR: Screen number ${SCREEN_INPUT} is out of range (1-${NUM_DEVS})." >&2 + return 1 + fi + + CURRENT_DEV_PATH="${BRIGHTNESS_DEVS[dev_index]}" + CURRENT_MAX="${MAX_VALUES[dev_index]}" + + if [ "${SCREEN_INPUT}" -eq 1 ]; then + CURRENT_SETTING_KEY="display.brightness" + else + CURRENT_SETTING_KEY="display.brightness${SCREEN_INPUT}" + fi + + return 0 +} + +_write_brightness() { + local raw_value="${1}" + local percentage="${2}" + + echo "${raw_value}" > "${CURRENT_DEV_PATH}" + set_setting "${CURRENT_SETTING_KEY}" "${percentage}" +} + +stepUp() { + local current_percent + current_percent="$(get_setting "${CURRENT_SETTING_KEY}")" + + local next_percent=$((current_percent + 5)) + if (("${next_percent}" > 100)); then + next_percent=100 + fi + + if (("${current_percent}" < 5)) && (("${next_percent}" < 5)); then + next_percent=5 + fi + + local raw_value + raw_value="$(_compute_raw "${next_percent}" "${CURRENT_MAX}")" + + if (("${raw_value}" > "${CURRENT_MAX}")); then + raw_value="${CURRENT_MAX}" + fi + + _write_brightness "${raw_value}" "${next_percent}" + getBrightnessValue +} + +stepDown() { + local current_percent + current_percent="$(get_setting "${CURRENT_SETTING_KEY}")" + + local next_percent=$((current_percent - 5)) + + if (("${next_percent}" < 5)); then + next_percent=5 + fi + + local raw_value + raw_value="$(_compute_raw "${next_percent}" "${CURRENT_MAX}")" + + _write_brightness "${raw_value}" "${next_percent}" + getBrightnessValue +} + +setBrightnessValue() { + local percent="${1}" + + if ! [[ "${percent}" =~ ^[0-9]+$ ]] || (("${percent}" < 0)) || (("${percent}" > 100)); then + echo "ERROR: Invalid percentage value provided: ${percent}. Must be 0-100." >&2 + return 1 + fi + + if (("${percent}" < 5)); then + percent=5 + fi + + local raw_value + raw_value="$(_compute_raw "${percent}" "${CURRENT_MAX}")" + + _write_brightness "${raw_value}" "${percent}" +} + +getBrightnessValue() { + cat "${CURRENT_DEV_PATH}" +} + +# Helper: apply an action to all detected screens +_apply_all() { + local action="$1" + local value="$2" # only used for "set" + + for ((i=0; i" >&2 + echo "Example: $0 set 50 or $0 set 2 50" >&2 + exit 1 + fi + + if [ "${screen_num_val}" = "all" ]; then + _apply_all "set" "${percentage_val}" + else + if ! _resolve_config "${screen_num_val}"; then exit 1; fi + setBrightnessValue "${percentage_val}" + fi + getBrightnessValue + ;; + + "") + ;& + *) + screen_to_get="" + if [ -z "${ACTION}" ] || { [ "${ACTION}" != "up" ] && [ "${ACTION}" != "down" ] && [ "${ACTION}" != "set" ]; }; then + if [ -n "${1}" ] && [[ "${1}" =~ ^[0-9]+$ ]]; then + screen_to_get="${1}" + else + screen_to_get="1" + fi + + if ! _resolve_config "${screen_to_get}"; then exit 1; fi + getBrightnessValue + exit 0 + fi + + echo "Usage: $0 {up|down|set} [screen_num|all] [percentage]" >&2 + echo "Example 1: $0 up (Increase brightness on all screens)" >&2 + echo "Example 2: $0 down 2 (Decrease brightness on screen 2)" >&2 + echo "Example 3: $0 set all 75 (Set brightness on all to 75%)" >&2 + exit 1 + ;; +esac diff --git a/projects/ArchR/packages/archr/sources/scripts/chksysconfig b/projects/ArchR/packages/archr/sources/scripts/chksysconfig new file mode 100755 index 0000000000..682ec7db6d --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/chksysconfig @@ -0,0 +1,45 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile + +CFG_PATH="/storage/.config/system/configs" + +backup() { + TYPE=$(grep a ${CFG_PATH}/system.cfg 2>&1) + if [[ ! "${TYPE}" =~ binary ]] + then + cp ${CFG_PATH}/system.cfg ${CFG_PATH}/system.cfg.backup + fi +} + +restore() { + cp ${CFG_PATH}/system.cfg.backup ${CFG_PATH}/system.cfg +} + +verify() { + TYPE=$(grep a ${CFG_PATH}/system.cfg 2>&1) + if [[ "${TYPE}" =~ binary ]]; then + restore + fi + + # Check if any configs are missing and restore everything if they are + if [ ! -s /storage/.config/retroarch/retroarch-core-options.cfg ] || \ + [ ! -s /storage/.config/retroarch/retroarch.cfg ] || \ + ! grep -q system.hostname /storage/.config/system/configs/system.cfg; then + rsync -a /usr/config/ /storage/.config + fi +} + +case ${1} in + verify) + verify + ;; + backup) + backup + ;; + restore) + restore + ;; +esac diff --git a/projects/ArchR/packages/archr/sources/scripts/controller-layout b/projects/ArchR/packages/archr/sources/scripts/controller-layout new file mode 100644 index 0000000000..0d63ffc56e --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/controller-layout @@ -0,0 +1,60 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile.d/001-functions +. /etc/profile.d/100-gamecontroller-functions + +# -- Config & Setup -- +# Destination file +if [[ -z "$1" ]] && [[ -z "$2" ]] && [[ -z "$3" ]]; then + echo "Usage: controller-layout [platform] [game] [gamecontrollerdb.txt]" + exit -1 +fi + +PLATFORM="$1" +GAME="$2" +CONTROLLER_DB="$3" + +# Where the emulationstation configuration file is +ES_CONFIG="/tmp/es_input.cfg" + +# Scrub the CONTROLLER_DB file +echo "" > ${CONTROLLER_DB} + +# Set layout via EmulationStation +CONTROLLER_LAYOUT=$(get_setting controller_layout "${PLATFORM}" "${GAME}") + +if [ "${CONTROLLER_LAYOUT}" = "xbox" ]; then + # xbox layout + ABUT="b" + BBUT="a" + XBUT="y" + YBUT="x" + unset LEFTSHOULDER + unset LEFTTRIGGER + unset RIGHTSHOULDER + unset RIGHTTRIGGER +elif [ "${CONTROLLER_LAYOUT}" = "xbox_swap_shoulders_triggers" ]; then + # xbox layout - with shoulders and triggers swapped + ABUT="b" + BBUT="a" + XBUT="y" + YBUT="x" + LEFTSHOULDER="lefttrigger" + LEFTTRIGGER="leftshoulder" + RIGHTSHOULDER="righttrigger" + RIGHTTRIGGER="rightshoulder" +else + # nintendo layout + unset ABUT + unset BBUT + unset XBUT + unset YBUT + unset LEFTSHOULDER + unset LEFTTRIGGER + unset RIGHTSHOULDER + unset RIGHTTRIGGER +fi + +# Call function to create controller db from ES input config file for only connected devices +create_controller_db ${CONTROLLER_LAYOUT} ${ES_CONFIG} ${CONTROLLER_DB} \ No newline at end of file diff --git a/projects/ArchR/packages/archr/sources/scripts/error.sh b/projects/ArchR/packages/archr/sources/scripts/error.sh new file mode 100755 index 0000000000..db010efe2b --- /dev/null +++ b/projects/ArchR/packages/archr/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 +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 diff --git a/projects/ArchR/packages/archr/sources/scripts/factoryreset b/projects/ArchR/packages/archr/sources/scripts/factoryreset new file mode 100755 index 0000000000..2f7851a382 --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/factoryreset @@ -0,0 +1,86 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +case "${1}" in + "retroarch") + rm -f /storage/.config/retroarch/retroarch.cfg + cp -rf /usr/config/retroarch/retroarch.cfg /storage/.config/retroarch/retroarch.cfg + ;; + "retroarch-full") + rm -rf /storage/.config/retroarch + cp -rf /usr/config/retroarch /storage/.config/ + ;; + "mednafen") + rm -f /storage/.config/mednafen/mednafen.cfg + ;; + "standalone") + rm -rf /storage/.config/aethersx2 + cp -rf /usr/config/aethersx2 /storage/.config/ + + rm -rf /storage/.config/amiberry + cp -rf /usr/config/amiberry /storage/.config/ + + rm -rf /storage/.config/dolphin-emu + cp -rf /usr/config/dolphin-emu /storage/.config/ + + rm -rf /storage/.config/drastic + cp -rf /usr/config/drastic /storage/.config/ + + rm -rf /storage/.config/duckstation + cp -rf /usr/config/duckstation /storage/.config/ + + rm -rf /storage/.config/flycast + cp -rf /usr/config/flycast /storage/.config/ + + rm -rf /storage/.config/gzdoom + cp -rf /usr/config/gzdoom /storage/.config/ + + rm -rf /storage/.config/hatari + cp -rf /usr/config/hatari /storage/.config/ + + rm -rf /storage/.config/melonDS + cp -rf /usr/config/melonDS /storage/.config/ + + rm -rf /storage/.config/openbor + cp -rf /usr/config/openbor /storage/.config/ + + rm -rf /storage/.config/ppsspp + cp -rf /usr/config/ppsspp /storage/.config/ + + rm -rf /storage/.config/azahar + cp -rf /usr/config/azahar /storage/.config/ + + rm -rf /storage/.config/rpcs3 + cp -rf /usr/config/rpcs3 /storage/.config/ + ;; + "portmaster") + rm -rf /storage/.config/PortMaster + cp -rf /usr/config/PortMaster /storage/.config/ + rm -rf /storage/roms/ports/PortMaster + unzip /usr/config/PortMaster/release/PortMaster.zip -d /storage/roms/ports/ + chmod +x /storage/roms/ports/PortMaster/PortMaster.sh + ;; + "overlays") + rm -rf $(cat /usr/lib/systemd/system/tmp-*.mount | grep -Eo 'upperdir=.*,' | sed -e 's~upperdir=~~g; s~,~~g') + sync + systemctl reboot + ;; + "audio") + systemctl stop pipewire-pulse pipewire-pulse.socket pipewire pipewire.socket wireplumber + rm -rf /storage/.local/state /storage/.config/pulse /storage/asound* + systemctl reboot + ;; + "ALL") + swapoff -a 2>/dev/null + umount /storage/roms 2>/dev/null ||: + umount /storage/games-external 2>/dev/null ||: + cd / + find /storage -mindepth 1 \( ! -regex '^/storage/.update.*' -a ! -regex '^/storage/roms.*' -a ! -regex '^/storage/games-.*' \) -delete 2>/dev/null + mkdir /storage/.config/ + sync 2>/dev/null + systemctl reboot + ;; +esac diff --git a/projects/ArchR/packages/archr/sources/scripts/find.sh b/projects/ArchR/packages/archr/sources/scripts/find.sh new file mode 100755 index 0000000000..d363e3b2ed --- /dev/null +++ b/projects/ArchR/packages/archr/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/projects/ArchR/packages/archr/sources/scripts/getfilters b/projects/ArchR/packages/archr/sources/scripts/getfilters new file mode 100755 index 0000000000..1298d5637e --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/getfilters @@ -0,0 +1,11 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +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 | sort + diff --git a/projects/ArchR/packages/archr/sources/scripts/getoverlays b/projects/ArchR/packages/archr/sources/scripts/getoverlays new file mode 100755 index 0000000000..96f73aff92 --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/getoverlays @@ -0,0 +1,12 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + + +find /storage/overlays/ -name '*.cfg' -print0 | + while IFS= read -r -d '' line; do + echo ${line#/storage/overlays/}, +done | sort + diff --git a/projects/ArchR/packages/archr/sources/scripts/getshaders b/projects/ArchR/packages/archr/sources/scripts/getshaders new file mode 100755 index 0000000000..318fa59080 --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/getshaders @@ -0,0 +1,23 @@ +#!/bin/bash + +. /etc/profile + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +if [ -z "$UI_SHADER" ]; then + option=".*\.\(glslp\|slangp\)$" +else + option=".*\.\($UI_SHADER\)$" +fi + +for dir in /tmp/shaders +do + if [ -d "${dir}" ]; then + find ${dir} -regex "${option}" -print0 | + while IFS= read -r -d '' line; do + echo ${line#${dir}/}, + done | sort + fi +done diff --git a/projects/ArchR/packages/archr/sources/scripts/handle-hdmi-hotplug b/projects/ArchR/packages/archr/sources/scripts/handle-hdmi-hotplug new file mode 100755 index 0000000000..8bfba3b350 --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/handle-hdmi-hotplug @@ -0,0 +1,48 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025 ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile +if ! pgrep -x emulationstation > /dev/null; then + exit 0 +fi + +HDMI_OUTPUT=$(wlr-randr | awk '/^(HDMI-A|DP|DisplayPort)-[0-9]*/ {print $1}') +DSI_OUTPUT=$(wlr-randr | awk '/^DSI-[0-9]/ {print $1}') + +HDMI_STATE=$(cat /run/hdmi-status.last 2>/dev/null) + +case "${HDMI_STATE}" in + connected) + + # Stop USB gadget only if using USB-C (DisplayPort) video, as it conflicts with USB data lanes on some SoCs (e.g. RK3588/SM8250) + # Standard HDMI ports are unaffected. + if cat /sys/class/drm/card*-DP*/status /sys/class/drm/card*-DisplayPort*/status 2>/dev/null | grep -q "^connected"; then + if systemctl is-active --quiet usbgadget; then + systemctl stop usbgadget + fi + fi + if [ -n "${HDMI_OUTPUT}" ]; then + wlr-randr --output "${HDMI_OUTPUT}" --preferred --on + fi + if [ -n "${DSI_OUTPUT}" ]; then + wlr-randr --output "${DSI_OUTPUT}" --off + fi + killall emulationstation + ;; + disconnected) + + # Stop USB gadget only if using USB-C (DisplayPort) video, as it conflicts with USB data lanes on some SoCs (e.g. RK3588/SM8250) + # Standard HDMI ports are unaffected. + if cat /sys/class/drm/card*-DP*/status /sys/class/drm/card*-DisplayPort*/status 2>/dev/null | grep -q "^connected"; then + if systemctl is-active --quiet usbgadget; then + systemctl stop usbgadget + fi + fi + if [ -n "${DSI_OUTPUT}" ]; then + wlr-randr --output "${DSI_OUTPUT}" --preferred --on + fi + killall emulationstation + ;; +esac + diff --git a/projects/ArchR/packages/archr/sources/scripts/installtointernal b/projects/ArchR/packages/archr/sources/scripts/installtointernal new file mode 100755 index 0000000000..3c301b6c95 --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/installtointernal @@ -0,0 +1,212 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) +# +# This script will resize the Android userdata partition and install +# ArchR to the internal UFS. + +set -euo pipefail + +case "$HW_DEVICE" in + SM8250|SM8550|SM8650) + ;; + *) + echo "This script is not compatible with this device!" + exit 1 + ;; +esac + +DEVICE=/dev/sda +FLASH_DIR=/flash +OLD_STORAGE=/storage +TMP_ArchR=/tmp/archr +TMP_STORAGE=/tmp/storage + +# Helper: report a device's size in GiB +get_gb() { + local dev=$1 bytes + if bytes=$(blockdev --getsize64 "$dev" 2>/dev/null); then + echo $(( bytes / 1024**3 )) + else + echo "N/A" + fi +} + +# Helper: calculate storage size excluding specific folders +get_storage_size_kb() { + local storage_path="$1" + local total_kb=0 + local excluded_folders=("roms" "games-internal" "games-external" ".cache/cores") + + # Get total size first + total_kb=$(du -ks "$storage_path" | awk '{print $1}') + + # Subtract excluded folders if they exist + for folder in "${excluded_folders[@]}"; do + if [[ -d "$storage_path/$folder" ]]; then + local folder_kb=$(du -ks "$storage_path/$folder" | awk '{print $1}') + total_kb=$((total_kb - folder_kb)) + fi + done + + echo "$total_kb" +} + +# 1) Check for existing ArchR or STORAGE partitions +mapfile -t part_names < <(parted -m -s "$DEVICE" print | tail -n +2 | cut -d: -f6) +for name in "${part_names[@]}"; do + if [[ "$name" == "ArchR" || "$name" == "STORAGE" ]]; then + echo "An installation already exists (found partition named '$name'). Exiting." + exit 0 + fi +done + +# 2) Warn user +read -rp "WARNING: This will wipe Android userdata on ${DEVICE}. Proceed? [y/N]: " confirm +if [[ ! $confirm =~ ^[Yy]$ ]]; then + echo "Aborted by user." + exit 0 +fi + +# 3) Find current Android userdata partition +mapfile -t ud_line < <(parted -m -s "$DEVICE" unit B print | grep ':userdata:') +if [[ ${#ud_line[@]} -ne 1 ]]; then + echo "ERROR: Could not uniquely find a Android userdata partition labeled 'userdata'." + exit 1 +fi +IFS=':' read -r UD_NUM UD_STARTB UD_ENDB _ <<< "${ud_line[0]}" +UD_START=${UD_STARTB%B} +UD_END=${UD_ENDB%B} + +# Compute MiB-aligned boundaries for Android userdata +UD_START_MB=$(( (UD_START + 1048575) / 1048576 )) # round up to MiB +UD_END_MB=$(( UD_END / 1048576 )) # round down to MiB +ORIG_SIZE=$(( (UD_END_MB - UD_START_MB) * 1024**2 )) # bytes +MIN_SIZE=$((1 * 1024**3)) +RESERVE=$((8 * 1024**3)) +MAX_SIZE=$(( ORIG_SIZE - RESERVE )) +if (( MAX_SIZE < MIN_SIZE )); then + echo "ERROR: Not enough space to shrink by 8GB. Aborting." + exit 1 +fi + +# 4) Ask desired Android userdata size in GB +echo "Current Android userdata size: $((ORIG_SIZE / 1024**3)) GB" +echo "You may choose between 1 GB and $((MAX_SIZE / 1024**3)) GB" +while :; do + read -rp "Enter new Android userdata size in GB: " ud_gb + if ! [[ $ud_gb =~ ^[0-9]+$ ]]; then + echo "Please enter an integer." + continue + fi + ud_bytes=$(( ud_gb * 1024**3 )) + if (( ud_bytes < MIN_SIZE || ud_bytes > MAX_SIZE )); then + echo "Value out of range. Must be between 1 and $((MAX_SIZE / 1024**3)) GB." + continue + fi + break +done +NEW_UD_END_MB=$(( UD_START_MB + (ud_bytes / 1024**2) )) + +# 5) Delete and recreate Android userdata partition +echo "Deleting Android userdata partition #$UD_NUM..." +parted -s "$DEVICE" rm "$UD_NUM" +echo "Creating Android userdata partition #$UD_NUM (${UD_START_MB}MiB–${NEW_UD_END_MB}MiB)..." +parted -a optimal -s "$DEVICE" \ + mkpart primary ext4 "${UD_START_MB}MiB" "${NEW_UD_END_MB}MiB" +parted -s "$DEVICE" name "$UD_NUM" userdata + +# 5b) Wipe first 8 MiB of the new Android userdata partition +echo "Zeroing first 8 MiB of ${DEVICE}${UD_NUM}..." +dd if=/dev/zero of="${DEVICE}${UD_NUM}" bs=1M count=8 &>/dev/null + +# 6) Create ArchR partition +RK_NUM=$(( UD_NUM + 1 )) +RK_START_MB=$NEW_UD_END_MB +RK_END_MB=$(( RK_START_MB + 2048 )) # 2 GiB +echo "Creating ArchR partition #$RK_NUM (${RK_START_MB}MiB–${RK_END_MB}MiB)..." +parted -a optimal -s "$DEVICE" \ + mkpart primary fat32 "${RK_START_MB}MiB" "${RK_END_MB}MiB" +parted -s "$DEVICE" name "$RK_NUM" ArchR +parted -s "$DEVICE" set "$RK_NUM" msftdata on +parted -s "$DEVICE" set "$RK_NUM" boot on + +# 7) Format ArchR partition +if mount | grep -q "^${DEVICE}${RK_NUM} "; then + echo "Auto-unmounting ${DEVICE}${RK_NUM}..." + umount "${DEVICE}${RK_NUM}" +fi +mkfs.vfat -F 32 -S 4096 -s 4 -n ArchR "${DEVICE}${RK_NUM}" &>/dev/null + +# 8) Create STORAGE partition +ST_NUM=$(( UD_NUM + 2 )) +echo "Creating STORAGE partition #$ST_NUM (from ${RK_END_MB}MiB to end)..." +parted -a optimal -s "$DEVICE" \ + mkpart primary ext4 "${RK_END_MB}MiB" 100% +parted -s "$DEVICE" name "$ST_NUM" STORAGE + +# 9) Format STORAGE +if mount | grep -q "^${DEVICE}${ST_NUM} "; then + echo "Auto-unmounting ${DEVICE}${ST_NUM}..." + umount "${DEVICE}${ST_NUM}" +fi +mkfs.ext4 -F -q -L STORAGE -T ext4 -O ^orphan_file -m 0 "${DEVICE}${ST_NUM}" &>/dev/null + +# 10) Final mounts: unmount any auto-mounted, then mount fresh +for dev in "${DEVICE}${RK_NUM}" "${DEVICE}${ST_NUM}"; do + if mount | grep -q "^$dev "; then + echo "Auto-unmounting $dev..." + umount "$dev" + fi +done +mkdir -p "$TMP_ArchR" "$TMP_STORAGE" +mount "${DEVICE}${RK_NUM}" "$TMP_ArchR" +mount "${DEVICE}${ST_NUM}" "$TMP_STORAGE" + +# 11) Copy files to ArchR partition, then sync +echo "Copying flash files to ArchR..." +cp -a "$FLASH_DIR"/. "$TMP_ArchR"/ +sync + +# 12) Optionally copy /storage to STORAGE partition, then sync +read -rp "Copy existing /storage to new STORAGE? [y/N]: " copy_ans +if [[ $copy_ans =~ ^[Yy]$ ]]; then + avail_kb=$(df -k "$TMP_STORAGE" | awk 'NR==2 {print $4}') + used_kb=$(get_storage_size_kb "$OLD_STORAGE") + if (( used_kb <= avail_kb )); then + echo "Copying /storage to new STORAGE (excluding roms)..." + + # Copy everything except the excluded folders + find "$OLD_STORAGE" -mindepth 1 -maxdepth 1 \ + ! -name "roms" \ + ! -name "games-internal" \ + ! -name "games-external" \ + -exec cp -a {} "$TMP_STORAGE"/ \; + + sync + else + echo "Skipping copy: not enough free space ($((avail_kb*1024)) bytes available, $((used_kb*1024)) bytes needed)." + fi +fi + +# 13) Final sync +echo "Syncing final data to disk..." +sync + +# 14) Cleanup mounts +echo "Cleaning up..." +umount "$TMP_ArchR" +umount "$TMP_STORAGE" +rmdir "$TMP_ArchR" "$TMP_STORAGE" + +# 15) Final summary with sizes +ud_sz=$(get_gb "${DEVICE}${UD_NUM}") +rk_sz=$(get_gb "${DEVICE}${RK_NUM}") +st_sz=$(get_gb "${DEVICE}${ST_NUM}") + +echo "Done. New partitions:" +echo " Android userdata: ${DEVICE}${UD_NUM} (${ud_sz} GB)" +echo " ArchR : ${DEVICE}${RK_NUM} (${rk_sz} GB)" +echo " STORAGE : ${DEVICE}${ST_NUM} (${st_sz} GB)" +echo +echo "ArchR Installation to internal UFS was successful. You can now reboot and remove your SD card." diff --git a/projects/ArchR/packages/archr/sources/scripts/led_flash b/projects/ArchR/packages/archr/sources/scripts/led_flash new file mode 100755 index 0000000000..660e200013 --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/led_flash @@ -0,0 +1,42 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile + +COLOR=$(get_setting led.color) +BRI=$(get_setting led.brightness) + +if [ -z "${COLOR}" ] || \ + [ "${COLOR}" = "off" ] || \ + [ -n "${DEVICE_LED_CHARGING}" ] +then + FLASH_COLOR="red" +else + FLASH_COLOR="${COLOR}" +fi + +if [ "${DEVICE_LED_BRIGHTNESS}" = "true" ] +then + ledcontrol brightness mid +fi + +for i in $(seq 1 1 3) +do + ledcontrol ${FLASH_COLOR} + sleep .5 + ledcontrol poweroff + sleep .5 +done + +if [ -n "${COLOR}" ] +then + ledcontrol ${COLOR} +else + ledcontrol default +fi + +if [ "${DEVICE_LED_BRIGHTNESS}" = "true" ] +then + ledcontrol brightness ${BRI} +fi diff --git a/projects/ArchR/packages/archr/sources/scripts/migrate_roms b/projects/ArchR/packages/archr/sources/scripts/migrate_roms new file mode 100644 index 0000000000..b3ab9abbfe --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/migrate_roms @@ -0,0 +1,36 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +LOGFILE="/var/log/migrate.log" + +read -p "WARNING: This tool can cause data loss... Make sure you have a backup before proceeding... Press control-c now to cancel, or any other key to continue..." + +for GAMES in /storage/games-internal /storage/games-external +do + echo "Working on ${GAMES}..." + if [ ! -d "${GAMES}/roms" ] + then + echo "Making ${GAMES}/roms..." + mkdir -p "${GAMES}/roms" >>${LOGFILE} 2>&1 1|>>${LOGFILE} + fi + for DIR in $(find "${GAMES}/" -type d -maxdepth 1 -mindepth 1 2>/dev/null) + do + TARGET_DIR=$(basename ${DIR}) + echo "Working on ${DIR}..." + if [[ "${DIR}" =~ roms$ ]] + then + continue + fi + if [ ! -d "${GAMES}/roms/${TARGET_DIR}" ] + then + echo "Making ${GAMES}/roms/${TARGET_DIR}..." + mkdir -p "${GAMES}/roms/${TARGET_DIR}" >>${LOGFILE} 2>&1 + fi + mv "${DIR}"/* "${GAMES}/roms/${TARGET_DIR}" >>${LOGFILE} 2>&1 + rsync -av --remove-source-files "${DIR}"/* "${GAMES}/roms/${TARGET_DIR}" >>${LOGFILE} 2>&1 + done + echo "Clean empties in ${GAMES}..." + find "${GAMES}" -type d -empty -delete >>${LOGFILE} 2>&1 1|>>${LOGFILE} + echo "Your games have been migrated, however you will need to manually clean up stale directories. Please reboot your system now by running the `reboot` command." +done diff --git a/projects/ArchR/packages/archr/sources/scripts/paneladj b/projects/ArchR/packages/archr/sources/scripts/paneladj new file mode 100755 index 0000000000..2f25badde5 --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/paneladj @@ -0,0 +1,104 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile + +# ARGS: +# +# 1 - property to adjust (gamma (brightness)/contrast/saturation/hue) +# 2 - up/down or a defined value + +PROPERTY=${1} +NEWVAL=${2} + +# Command usage: +# drm_tool set /dev/dri/card0 133 saturation value + +# Define the basics +MIN=1 +MAX=100 +STEP=1 + +if [ ! -e /dev/dri/card0 ] +then + echo "ERROR: No display found." + exit 1 +fi + +log() { + $DEBUG && echo "Info: ${*}" >>/var/log/display.log +} + +getValue() { + MYVAL=$(get_setting display.${1}) + if [ -n "${MYVAL}" ] + then + if [ "${MYVAL}" > "${MAX}" ] + then + MYVAL=${MAX} + elif [ "${MYVAL}" < "${MIN}" ] + then + MYVAL=${MIN} + fi + echo ${MYVAL} + else + echo $(drm_tool list 2>/dev/null | sed -n '/Connector: '${CONNECTOR}'/,$p' | awk '/'${1}'/ {print $5}') + fi +} + +setValue() { + log "Set (${1}: ${2})" + drm_tool set /dev/dri/card0 ${CONNECTOR} ${1} ${2} 2>/dev/null + if [ $? = 0 ] + then + set_setting display.${1} ${2} + fi +} + +stepUp() { + LASTVAL=$(getValue ${PROPERTY}) + NEWVAL=$(expr ${LASTVAL} + 1) + log "Step up (${PROPERTY}: ${NEWVAL})" + setValue ${PROPERTY} ${NEWVAL} +} + +stepDown() { + LASTVAL=$(getValue ${PROPERTY}) + NEWVAL=$(expr ${LASTVAL} - 1) + log "Step down (${PROPERTY}: ${NEWVAL})" + setValue ${PROPERTY} ${NEWVAL} +} + +restoreSettings() { + for PROPERTY in brightness contrast saturation hue + do + RESTVAL=$(getValue ${PROPERTY}) + setValue ${PROPERTY} ${RESTVAL} + done +} + +CONNECTOR=$(drm_tool list | grep -B1 "mode.*:" | awk '/Connector/ {print $2}') + +case ${NEWVAL} in + "up") + stepUp + ;; + "down") + stepDown + ;; + "restore") + restoreSettings + ;; + *) + if [[ "${NEWVAL}" =~ ^[0-9] ]] && \ + [ "${NEWVAL}" -le "${MAX}" ] && \ + [ "${NEWVAL}" -ge "${MIN}" ] + then + setValue ${PROPERTY} ${NEWVAL} + else + echo "Error: Invalid value." + exit 1 + fi + ;; +esac diff --git a/projects/ArchR/packages/archr/sources/scripts/run b/projects/ArchR/packages/archr/sources/scripts/run new file mode 100755 index 0000000000..136d1c3eb2 --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/run @@ -0,0 +1,42 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile + +ui_state() { + clear >/dev/console + systemctl ${1} ${UI_SERVICE} +} + +if [ "${UI_SERVICE}" = "weston.service" ] +then + if [ -f "${*}" ] + then + RUN=$(echo ${*} | sed 's# #\\ #g') + weston-terminal --command="${RUN}" + else + weston-terminal --command="${*}" + fi +elif echo "${UI_SERVICE}" | grep "sway"; then + if [ -f "${*}" ] + then + foot -F "${*}" + else + foot -F ${*} + fi +else + ui_state stop + clear >/dev/console + $* >/dev/console + if [ "$?" == 0 ] + then + ui_state start + exit 0 + else + "$*" >/dev/console + ui_state start + exit 0 + fi +fi + diff --git a/projects/ArchR/packages/archr/sources/scripts/runemu.sh b/projects/ArchR/packages/archr/sources/scripts/runemu.sh new file mode 100755 index 0000000000..9a45eff3ea --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/runemu.sh @@ -0,0 +1,568 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Source predefined functions and variables +. /etc/profile +. /etc/os-release + +### Shell trace + persistent debug log are gated by system.loglevel=verbose. +### Default (off/none/quiet) writes nothing to microSD on launch. +if [ "$(get_setting system.loglevel)" = "verbose" ]; then + RUNEMU_DEBUG="/storage/.cache/log/runemu-debug.log" + mkdir -p "$(dirname "${RUNEMU_DEBUG}")" + exec 2>>"${RUNEMU_DEBUG}" + set -x +fi + +### Switch to performance mode early to speed up configuration and reduce time it takes to get into games. +performance + +# Command line schema +# $1 = Game/Port +# $2 = Platform +# $3 = Core +# $4 = Emulator + +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}}" + +### Define the variables used throughout the script +BLUETOOTH_STATE=$(get_setting controllers.bluetooth.enabled) +ES_CONFIG="/storage/.emulationstation/es_settings.cfg" +VERBOSE=false +LOG_DIRECTORY="/var/log" +LOG_FILE="exec.log" +RUN_SHELL="/usr/bin/bash" +RETROARCH_TEMP_CONFIG="/storage/.config/retroarch/retroarch.cfg" +RETROARCH_APPEND_CONFIG="/tmp/.retroarch.cfg" +NETWORK_PLAY="No" +SET_SETTINGS_TMP="/tmp/shader" +OUTPUT_LOG="${LOG_DIRECTORY}/${LOG_FILE}" +SCRIPT_NAME=$(basename "$0") + +### Export Game Guide Path +GAME_GUIDE_PATH_CHECK="${1%.*}.txt" +if [ ! -f "${GAME_GUIDE_PATH_CHECK}" ]; then + GAME_GUIDE_PATH_CHECK="No Game Guide Found" +fi + /usr/bin/game-guides-tool "${1}" + +### Function Library +function log() { + if [ ${LOG} == true ] + then + if [[ ! -d "$LOG_DIRECTORY" ]] + then + mkdir -p "$LOG_DIRECTORY" + fi + echo "${SCRIPT_NAME}: $*" 2>&1 | tee -a ${LOG_DIRECTORY}/${LOG_FILE} + else + echo "${SCRIPT_NAME}: $*" + fi +} + +function loginit() { + if [ ${LOG} == true ] + then + if [ -e ${LOG_DIRECTORY}/${LOG_FILE} ] + then + rm -f ${LOG_DIRECTORY}/${LOG_FILE} + fi + cat <${LOG_DIRECTORY}/${LOG_FILE} +Emulation Run Log - Started at $(date) + +ARG1: $1 +ARG2: $2 +ARG3: $3 +ARG4: $4 +ARGS: $* +EMULATOR: ${EMULATOR} +PLATFORM: ${PLATFORM} +CORE: ${CORE} +ROM NAME: ${ROMNAME} +BASE ROM NAME: ${ROMNAME##*/} +USING CONFIG: ${RETROARCH_TEMP_CONFIG} +USING APPENDCONFIG : ${RETROARCH_APPEND_CONFIG} +GAME GUIDE PATH: ${GAME_GUIDE_PATH_CHECK} + +EOF + else + log $0 "Emulation Run Log - Started at $(date)" + fi +} + +function quit() { + ${VERBOSE} && log $0 "Cleaning up and exiting" + bluetooth enable + resume_background_services + restore_ksm + set_kill set "emulationstation" + clear_screen + # Restore CPU governor to user pref (or ondemand fallback). Without + # the fallback the CPU stays in performance + boost after exit + # because performance() unconditionally turns boost on for the + # 1512 MHz turbo OPP, draining battery in the menu. + DEVICE_CPU_GOVERNOR=$(get_setting system.cpugovernor) + case "${DEVICE_CPU_GOVERNOR}" in + performance|ondemand|schedutil|powersave) + ${DEVICE_CPU_GOVERNOR} + ;; + *) + ondemand + ;; + esac + exit $1 +} + +# KSM (Kernel Same-page Merging) compares page contents across processes +# to deduplicate memory. On a Cortex-A35 in-order core it's a noticeable +# source of jitter — exactly the kind of background CPU eater that shows +# up as p99 frametime spikes during gameplay. Pause it for the duration +# of the run and put it back the way the user/memory-manager left it on +# exit. +KSM_RUN_FILE="/sys/kernel/mm/ksm/run" +KSM_PREVIOUS_STATE="" + +function pause_ksm() { + [ -e "${KSM_RUN_FILE}" ] || return + KSM_PREVIOUS_STATE="$(cat "${KSM_RUN_FILE}" 2>/dev/null)" + echo 0 > "${KSM_RUN_FILE}" 2>/dev/null +} + +function restore_ksm() { + [ -e "${KSM_RUN_FILE}" ] || return + [ -z "${KSM_PREVIOUS_STATE}" ] && return + echo "${KSM_PREVIOUS_STATE}" > "${KSM_RUN_FILE}" 2>/dev/null +} + +function clear_screen() { + ${VERBOSE} && log $0 "Clearing screen" + clear +} + +function bluetooth() { + if [ "$1" == "disable" ] + then + ${VERBOSE} && log $0 "Disabling BT" + if [[ "${BLUETOOTH_STATE}" == "1" ]] + then + NPID=$(pgrep -f archr-bluetooth-agent) + if [[ ! -z "$NPID" ]]; then + kill "$NPID" + fi + fi + elif [ "$1" == "enable" ] + then + ${VERBOSE} && log $0 "Enabling BT" + if [[ "${BLUETOOTH_STATE}" == "1" ]] + then + systemd-run archr-bluetooth-agent + fi + fi +} + +### Sync/VPN/HTTP daemons compete with the emulator for CPU, RAM and microSD +### I/O. Stop them on launch and restart only the ones that were running on +### exit (so we never enable a service the user had off). +GAMEPLAY_PAUSE_SERVICES="syncthing tailscaled zerotier-one simple-http-server" +SERVICES_PAUSED_DURING_GAME="" + +function pause_background_services() { + for svc in ${GAMEPLAY_PAUSE_SERVICES}; do + if systemctl is-active --quiet "${svc}" 2>/dev/null; then + ${VERBOSE} && log $0 "Pausing ${svc} for gameplay" + systemctl stop "${svc}" >/dev/null 2>&1 + SERVICES_PAUSED_DURING_GAME+=" ${svc}" + fi + done +} + +function resume_background_services() { + for svc in ${SERVICES_PAUSED_DURING_GAME}; do + ${VERBOSE} && log $0 "Resuming ${svc} after gameplay" + systemctl start "${svc}" >/dev/null 2>&1 & + done +} + +### Enable logging +case $(get_setting system.loglevel) in + off|none) + LOG=false + ;; + verbose) + LOG=true + VERBOSE=true + ;; + *) + LOG=true + ;; +esac + +### Prepare to load our emulator and game. +loginit "$1" "$2" "$3" "$4" +clear_screen +bluetooth disable +pause_background_services +pause_ksm +set_kill stop + +### Determine which emulator we're launching and make appropriate adjustments before launching. +${VERBOSE} && log $0 "Configuring for ${EMULATOR}" +case ${EMULATOR} in + mednafen) + set_kill set "-9 mednafen" + RUNTHIS='${RUN_SHELL} /usr/bin/start_mednafen.sh "${ROMNAME}" "${CORE}" "${PLATFORM}"' + ;; + retroarch) + # Make sure NETWORK_PLAY isn't defined before we start our tests/configuration. + del_setting netplay.mode + + case ${ARGUMENTS} in + *"--host"*) + ${VERBOSE} && log $0 "Setup netplay host." + NETWORK_PLAY="${ARGUMENTS##*--host}" # read from --host onwards + NETWORK_PLAY="${NETWORK_PLAY%%--nick*}" # until --nick is found + NETWORK_PLAY="--host ${NETWORK_PLAY} --nick" + set_setting netplay.mode "host" + ;; + *"--connect"*) + ${VERBOSE} && log $0 "Setup netplay client." + NETWORK_PLAY="${ARGUMENTS##*--connect}" # read from --connect onwards + NETWORK_PLAY="${NETWORK_PLAY%%--nick*}" # until --nick is found + NETWORK_PLAY="--connect ${NETWORK_PLAY} --nick" + set_setting netplay.mode "client" + ;; + *"--netplaymode spectator"*) + ${VERBOSE} && log $0 "Setup netplay spectator." + set_setting "netplay.mode" "spectator" + ;; + esac + + ### Set set_kill to kill the appropriate retroarch + set_kill set "retroarch retroarch32" + + ### Assume we're running 64bit Retroarch + RABIN="retroarch" + + case ${HW_ARCH} in + aarch64) + if [[ "${CORE}" =~ pcsx_rearmed32 ]] || \ + [[ "${CORE}" =~ gpsp ]] || \ + [[ "${CORE}" =~ desmume ]] + then + ### Configure for 32bit Retroarch + ${VERBOSE} && log $0 "Configuring for 32bit cores." + export RABIN="retroarch32" + fi + ;; + esac + + + ### Configure specific emulator requirements + case ${CORE} in + freej2me*) + ${VERBOSE} && log $0 "Setup freej2me requirements." + /usr/bin/freej2me.sh + JAVA_HOME='/storage/jdk' + export JAVA_HOME + PATH="$JAVA_HOME/bin:$PATH" + export PATH + export _JAVA_OPTIONS="-Djava.awt.headless=true" + ;; + easyrpg*) + # easyrpg needs runtime files to be downloaded on the first run + ${VERBOSE} && log $0 "Setup easyrpg requirements." + /usr/bin/easyrpg.sh + ;; + esac + + + RUNTHIS='${EMUPERF} /usr/bin/${RABIN} -L /tmp/cores/${CORE}_libretro.so --config ${RETROARCH_TEMP_CONFIG} --appendconfig ${RETROARCH_APPEND_CONFIG} "${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 + + # Configure platform specific requirements + case ${PLATFORM} in + "atomiswave") + rm ${ROMNAME}.nvmem* + ;; + "scummvm") + GAMEDIR=$(cat "${ROMNAME}" | awk 'BEGIN {FS="\""}; {print $2}') + cd "${GAMEDIR}" + RUNTHIS='${RUN_SHELL} /usr/bin/start_scummvm.sh libretro .' + ;; + esac + + ### Configure retroarch + if [ -e "${SET_SETTINGS_TMP}" ] + then + rm -f "${SET_SETTINGS_TMP}" + fi + ${VERBOSE} && log $0 "Execute setsettings (${PLATFORM} ${ROMNAME} ${CORE} --controllers=${CONTROLLERCONFIG} --autosave=${AUTOSAVE} --snapshot=${SNAPSHOT})" + (/usr/bin/setsettings.sh "${PLATFORM}" "${ROMNAME}" "${CORE}" --controllers="${CONTROLLERCONFIG}" --autosave="${AUTOSAVE}" --snapshot="${SNAPSHOT}" >${SET_SETTINGS_TMP}) + + ### If setsettings wrote data in the background, grab it and assign it to EXTRAOPTS + if [ -e "${SET_SETTINGS_TMP}" ] + then + EXTRAOPTS=$(cat ${SET_SETTINGS_TMP}) + rm -f ${SET_SETTINGS_TMP} + ${VERBOSE} && log $0 "Extra Options: ${EXTRAOPTS}" + fi + + if [[ ${EXTRAOPTS} != 0 ]]; then + RUNTHIS=$(echo ${RUNTHIS} | sed "s|--config|${EXTRAOPTS} --config|") + fi + ;; + *) + case ${PLATFORM} in + "setup") + RUNTHIS='${RUN_SHELL} "${ROMNAME}"' + ;; + "gamecube"|"triforce") + RUNTHIS='${RUN_SHELL} /usr/bin/start_dolphin_gc.sh "${ROMNAME}" "${PLATFORM}" "${CORE}"' + ;; + "wii"|"wiiware") + RUNTHIS='${RUN_SHELL} /usr/bin/start_dolphin_wii.sh "${ROMNAME}" "${PLATFORM}" "${CORE}"' + ;; + "ports") + RUNTHIS='${EMUPERF} ${RUN_SHELL} "${ROMNAME}"' + sed -i "/^ACTIVE_GAME=/c\ACTIVE_GAME=\"${ROMNAME}\"" /storage/.config/PortMaster/mapper.txt + sed -i "/^ACTIVE_PLATFORM=/c\ACTIVE_PLATFORM=\"${PLATFORM}\"" /storage/.config/PortMaster/mapper.txt + ;; + "windows") + RUNTHIS='${EMUPERF} ${RUN_SHELL} "${ROMNAME}"' + # Hook into Portmaster control mapping + sed -i "/^ACTIVE_GAME=/c\ACTIVE_GAME=\"${ROMNAME}\"" /storage/.config/PortMaster/mapper.txt + sed -i "/^ACTIVE_PLATFORM=/c\ACTIVE_PLATFORM=\"${PLATFORM}\"" /storage/.config/PortMaster/mapper.txt + ;; + "shell") + RUNTHIS='${RUN_SHELL} "${ROMNAME}"' + ;; + *) + RUNTHIS='${RUN_SHELL} "/usr/bin/start_${CORE%-*}.sh" "${ROMNAME}" "${PLATFORM}"' + ;; + esac + ;; +esac + +### Execution time. +clear_screen +${VERBOSE} && log $0 "executing game: ${ROMNAME}" +${VERBOSE} && log $0 "script to execute: ${RUNTHIS}" + +### Set the cores to use +CORES=$(get_setting "cores" "${PLATFORM}" "${ROMNAME##*/}") +${VERBOSE} && log $0 "Configure big.little (${CORES})" +case ${CORES} in + little) + EMUPERF="${SLOW_CORES}" + ;; + big) + EMUPERF="${FAST_CORES}" + ;; + *) + unset EMUPERF + ;; +esac + +### We need the original system cooling profile later so get it now! +COOLINGPROFILE=$(get_setting cooling.profile) + +### Configure GPU performance mode +### Default to "performance" during gameplay so devfreq pins min_freq at the +### highest OPP. ROCKNIX achieves the same effect by exposing only one GPU +### OPP (560 MHz) in their DT; we keep the full ladder for idle/menu and +### force the floor up here. Without this, simple_ondemand kept the GPU +### oscillating between 200-400 MHz mid-frame, costing ~50% of PSP/N64/DC +### performance versus competing distros. +GPUPERF=$(get_setting "gpuperf" "${PLATFORM}" "${ROMNAME##*/}") +GPUPERF="${GPUPERF:-performance}" +${VERBOSE} && log $0 "Set GPU performance to (${GPUPERF})" +gpu_performance_level ${GPUPERF} +get_gpu_performance_level >/tmp/.gpu_performance_level + +### Make sure Mesa's shader cache directory exists. Mesa won't create the +### root path itself when MESA_SHADER_CACHE_DIR points somewhere new; the +### result is silent fall-through to "no cache" and a stutter every time +### the user re-launches a game whose shaders should already be hot. +[ -d /storage/.cache/mesa_shader_cache ] || mkdir -p /storage/.cache/mesa_shader_cache 2>/dev/null + +if [ "${DEVICE_HAS_FAN}" = "true" ] +then + ### Set any custom fan profile (make this better!) + GAMEFAN=$(get_setting "cooling.profile" "${PLATFORM}" "${ROMNAME##*/}") + if [ ! -z "${GAMEFAN}" ] + then + ${VERBOSE} && log $0 "Set fan profile to (${GAMEFAN})" + set_setting cooling.profile ${GAMEFAN} + systemctl restart fancontrol + fi +fi + +### Display mode for emulation +DISPLAY_MODE=$(get_setting "display_mode" "${PLATFORM}" "${ROMNAME##*/}") +if [ ! -z "${DISPLAY_MODE}" ] && [ "${DISPLAY_MODE}" != "default" ] +then + set_refresh_rate "${DISPLAY_MODE}" +fi + +FORCEPACK=$(get_setting "forcepack" "${PLATFORM}" "${ROMNAME##*/}") +if [ ! -z "${FORCEPACK}" ] && [ "${FORCEPACK}" = "On" ] +then + ${VERBOSE} && log $0 "Enabling panfrost forcepack" + export PAN_MESA_DEBUG=forcepack +fi + +### Offline all but the number of threads we need for this game if configured. +NUMTHREADS=$(get_setting "threads" "${PLATFORM}" "${ROMNAME##*/}") +if [ -n "${NUMTHREADS}" ] && + [ ! ${NUMTHREADS} = "default" ] +then + ${VERBOSE} && log $0 "Configure active cores (${NUMTHREADS})" + onlinethreads ${NUMTHREADS} 0 +fi + +### Set the governor mode for emulation +CPU_GOVERNOR=$(get_setting "cpugovernor" "${PLATFORM}" "${ROMNAME##*/}") +${VERBOSE} && log $0 "Set emulation performance mode to (${CPU_GOVERNOR})" +${CPU_GOVERNOR} + +### Check whether MangoHud is supported and enabled +if [ "${DEVICE_MANGOHUD_SUPPORT}" == "true" ]; then + MANGOHUD_ENABLED=$(get_setting "archr.mangohud.enabled" "${PLATFORM}" "${ROMNAME##*/}") + if [ "${MANGOHUD_ENABLED}" = "1" ]; then + # Enable GPU profiling and MangoHud + gpu_profiling "on" + RUNTHIS="/usr/bin/mangohud ${RUNTHIS}" + ${VERBOSE} && log $0 "Enabling MangoHud" + fi +fi + +# If the rom is a shell script just execute it, useful for DOSBOX and ScummVM scan scripts +if [[ "${ROMNAME}" == *".sh" ]] && [ ! "${PLATFORM}" = "ports" ] && [ ! "${PLATFORM}" = "windows" ]; then + ${VERBOSE} && log $0 "Executing shell script ${ROMNAME}" + "${ROMNAME}" &>>${OUTPUT_LOG} + ret_error=$? +else + ${VERBOSE} && log $0 "Executing $(eval echo ${RUNTHIS})" + eval ${RUNTHIS} &>>${OUTPUT_LOG} + ret_error=$? +fi + +### Switch back to performance mode to clean up +performance + +clear_screen + +### Disable touch on the secondary screen for dual screen devices +if [[ "${DEVICE_HAS_DUAL_SCREEN}" == "true" ]]; then + # Disable touch events for Retroid Pocket devices to prevent focus loss + if [[ "${QUIRK_DEVICE}" == "Retroid Pocket 5" || "${QUIRK_DEVICE}" == "Retroid Pocket Flip2" || "${QUIRK_DEVICE}" == "Retroid Pocket Mini" || "${QUIRK_DEVICE}" == "Retroid Pocket Mini V2" ]]; then + swaymsg input "0:0:generic_ft5x06_(a0)" events disabled + swaymsg input "0:0:generic_ft5x06_(8d)" events disabled + fi +fi + +### Go back to system display mode , if we had specialized mode defined +DISPLAY_MODE=$(get_setting "display_mode" "${PLATFORM}" "${ROMNAME##*/}") +if [ ! -z "${DISPLAY_MODE}" ] && [ "${DISPLAY_MODE}" != "default" ] +then + DISPLAY_MODE=$(get_setting "system.display_mode") + DISPLAY_OUTPUT=$(/usr/bin/wlr-randr | awk 'NR==1{print $1;}') + if [ -z "${DISPLAY_MODE}" ]; then + # if we have no system mode use the displays preferred mode + /usr/bin/wlr-randr --output ${DISPLAY_OUTPUT} --preferred + else + # If we have user specifed system mode set that + set_refresh_rate "${DISPLAY_MODE}" + fi +fi + +### Restore cooling profile. +if [ "${DEVICE_HAS_FAN}" = "true" ] +then + ${VERBOSE} && log $0 "Restore system cooling profile (${COOLINGPROFILE})" + set_setting cooling.profile ${COOLINGPROFILE} + systemctl restart fancontrol & +fi + +### Restore system GPU performance mode. +### Honour an explicit per-system setting if the user picked one. Otherwise +### keep the governor at "performance" — every transition back to ondemand +### exercises a regulator/clock refcount path in mali_kbase that fires +### "unbalanced disables for vdd_logic" / "Enabling unprepared clk_gpu" +### kernel WARNs and occasionally takes the device down. Battery cost of +### staying performance in the menu is small; PM stability is worth it. +GPUPERF=$(get_setting "system.gpuperf") +if [ ! -z ${GPUPERF} ] +then + ${VERBOSE} && log $0 "Restore system GPU performance mode (${GPUPERF})" + gpu_performance_level ${GPUPERF} & +else + ${VERBOSE} && log $0 "Keeping GPU governor at performance (mali_kbase PM workaround)" + # No-op: leave whatever gameplay set in place. +fi +rm -f /tmp/.gpu_performance_level 2>/dev/null + +### Reset the number of cores to use. +NUMTHREADS=$(get_setting "system.threads") +${VERBOSE} && log $0 "Restore active threads (${NUMTHREADS})" +if [ -n "${NUMTHREADS}" ] +then + onlinethreads ${NUMTHREADS} 0 & +else + onlinethreads all 1 & +fi + +### Disable GPU profiling +gpu_profiling "off" + +### Backup save games +CLOUD_BACKUP=$(get_setting "cloud.backup") +if [ "${CLOUD_BACKUP}" = "1" ] +then + INETUP=$(/usr/bin/amionline >/dev/null 2>&1) + if [ $? == 0 ] + then + log $0 "backup saves to the cloud." + /usr/bin/run /usr/bin/cloud_backup + fi +fi + +${VERBOSE} && log $0 "Checking errors: ${ret_error} " +if [ "${ret_error}" == "0" ] +then + quit 0 +else + log $0 "exiting with ${ret_error}" + quit 1 +fi diff --git a/projects/ArchR/packages/archr/sources/scripts/say b/projects/ArchR/packages/archr/sources/scripts/say new file mode 100755 index 0000000000..9e4a0a6416 --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/say @@ -0,0 +1,22 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile + +AUDIOTEST=$(ps -ef | grep [p]ipewire) +if [ ! $? = 0 ] +then + PLAYCMD="aplay -q" +else + PLAYCMD="paplay" +fi + +case $1 in + -b) + espeak --stdout "$(battery_percent)%" | ${PLAYCMD} + ;; + *) + espeak --stdout "$*" | ${PLAYCMD} + ;; +esac diff --git a/projects/ArchR/packages/archr/sources/scripts/setemu.sh b/projects/ArchR/packages/archr/sources/scripts/setemu.sh new file mode 100755 index 0000000000..405aad50b9 --- /dev/null +++ b/projects/ArchR/packages/archr/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/system/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/projects/ArchR/packages/archr/sources/scripts/setrootpass b/projects/ArchR/packages/archr/sources/scripts/setrootpass new file mode 100755 index 0000000000..9f063a3462 --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/setrootpass @@ -0,0 +1,44 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile + +ROOTPASS="$1" + +LPC=$(awk -F: '/^root/{print $3}' /storage/.cache/shadow) +CURRENT=$(awk -F: '/^root/{print $2}' /storage/.cache/shadow) + +# 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 + +# Set the root user and password for SyncThing +syncthing generate --gui-user "root" --gui-password "${ROOTPASS}" >/dev/null 2>&1 + +# Save the password so we can display it in ES +set_setting root.password "${ROOTPASS}" + +# Restart syncthing if it was enabled. +SYNCSTATUS=$(get_setting syncthing.enabled) +SYNCACTIVE=$(systemctl status syncthing | awk '/active/ {print $2}') +if [ "${SYNCSTATUS}" = "1" ] && + [ "${SYNCACTIVE}" = "active" ] +then + systemctl restart syncthing >/dev/null 2>&1 +fi + +# Restart simple-http-server if it is enabled +SIMPLESTATUS=$(get_setting simplehttp.enabled) +SIMPLEACTIVE=$(systemctl status simple-http-server | awk '/active/ {print $2}') +if [ "${SIMPLESTATUS}" = "1" ] && + [ "${SIMPLEACTIVE}" = "active" ] +then + systemctl restart simple-http-server >/dev/null 2>&1 +fi + diff --git a/projects/ArchR/packages/archr/sources/scripts/setsettings.sh b/projects/ArchR/packages/archr/sources/scripts/setsettings.sh new file mode 100755 index 0000000000..3425b997e1 --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/setsettings.sh @@ -0,0 +1,1297 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile + +### +### System configuration variables +### + +SYSTEM_CONFIG="/storage/.config/system/configs/system.cfg" +RETROARCH_PATH="/storage/.config/retroarch" +RETROARCH_CONFIG="${RETROARCH_PATH}/retroarch.cfg" +RETROARCH_TEMPLATE="/usr/config/retroarch/retroarch.cfg" + +ROMS_DIR="/storage/roms" +SNAPSHOTS="${ROMS_DIR}/savestates" +BEZEL_DIR="/storage/roms/bezels" + +TMP_CONFIG="/tmp/.retroarch.cfg" +LOG_DIR="/var/log" +LOG_FILE="exec.log" +LOCK_FILE="/tmp/.retroarch.lock" + +### +### Variables parsed from the command line +### + +PLATFORM=${1,,} +ROM="${2##*/}" +CORE=${3,,} + + +#Autosave +AUTOSAVE="$@" +AUTOSAVE="${AUTOSAVE#*-autosave=*}" +AUTOSAVE="${AUTOSAVE% --*}" + +#Snapshot +SNAPSHOT="$@" +SNAPSHOT="${SNAPSHOT#*--snapshot=*}" + +#Controllers +CONTROLLERS="$@" +CONTROLLERS="${CONTROLLERS#*--controllers=*}" + +### +### Arrays containing various supported/non-supported attributes. +### + +declare -a HAS_CHEEVOS=( arcade + arduboy + atari2600 + atari7800 + atarilynx + cdi + colecovision + cps1 + cps2 + cps3 + dreamcast + famicom + fbn + fds + gamegear + gb + gbh + gba + gbah + gbav + gbc + gbch + gbh + genesis + genh + ggh + intellivision + mastersystem + megacd + megadrive + megadrive-japan + msx + msx2 + n64 + nds + neogeo + neogeocd + nes + nesh + ngp + ngpc + odyssey2 + 3do + pcengine + pcenginecd + pcfx + pokemini + psp + psx + ps2 + saturn + sega32x + segacd + sfc + sg-1000 + snes + snesh + snesmsu1 + supergrafx + supervision + tg16 + tg16cd + vectrex + virtualboy + wonderswan + wonderswancolor +) + +declare -a NO_REWIND=( atomiswave + dreamcast + mame + n64 + naomi + neogeocd + odyssey2 + psp + pspminis + saturn + sega32x + zxspectrum +) + +declare -a NO_RUNAHEAD=( atomiswave + dreamcast + n64 + naomi + neogeocd + psp + saturn + sega32x +) + +declare -a NO_ANALOG=( dreamcast + gc + n64 + nds + ps2 + psp + pspminis + psx + wii + wonderswan + wonderswancolor +) + +declare -a IS_32BIT=( gpsp + pcsx_rearmed +) + +declare -a CORE_RATIOS=( 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 + full +) + +declare -a LANG_CODES=( ["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" +) + +### +### Fetch common settings +### + +LOGGING=$(get_setting system.loglevel) +if [ -z "${LOGGING}" ] +then + LOGGING="none" +fi + +### +### Set up +### + +### Create log directory if it doesn't exist +if [ ! -d "${LOG_DIR}" ] +then + mkdir -p ${LOG_DIR} +fi + +if [ -e "${LOCK_FILE}" ] +then + rm -f "${LOCK_FILE}" +fi + +### Clean up temp files +for FILE in ${TMP_CONFIG} ${TMP_CONFIG}.sed +do + if [ -f "${FILE}" ] + then + rm -f "${FILE}" + fi +done + +### +### Core functions +### + +function log() { + if [ ${LOGGING} = "verbose" ] + then + echo "$(printf '%(%c)T\n' -1): setsettings: $*" >> ${LOG_DIR}/${LOG_FILE} 2>&1 + fi +} + +function cleanup() { + log "Work complete" + sync + exit +} + +function game_setting() { + if [ -n "${1}" ] + then + SETTING=$(get_setting "${1}" "${PLATFORM}" "${ROM}") + log "Fetch \"${1}\" \"${PLATFORM}\" \"${ROM}\"] (${SETTING})" + echo ${SETTING} + fi +} + +function clear_setting() { + log "Remove setting [${1}]" + if [ ! -f "${TMP_CONFIG}.sed" ] + then + echo -n 'sed -i "/^'${1}'/d;' >${TMP_CONFIG}.sed + else + echo -n ' /^'${1}'/d;' >>${TMP_CONFIG}.sed + fi +} + +function flush_settings() { + echo -n '" '${RETROARCH_CONFIG}' >/dev/null 2>&1' >>${TMP_CONFIG}.sed + chmod 0755 ${TMP_CONFIG}.sed + ${TMP_CONFIG}.sed >/dev/null 2>&1 ||: + rm -f ${TMP_CONFIG}.sed +} + +function add_setting() { + if [ ! "${1}" = "none" ] + then + local OS_SETTING="$(game_setting ${1})" + fi + local RETROARCH_KEY="${2}" + local RETROARCH_VALUE="${3}" + if [ -z "${RETROARCH_VALUE}" ]& \ + [ ! "${1}" = "none" ] + then + RETROARCH_VALUE="${OS_SETTING}" + fi + clear_setting "${RETROARCH_KEY}" + echo "${RETROARCH_KEY} = \"${RETROARCH_VALUE}\"" >>${TMP_CONFIG} + log "Added setting: ${RETROARCH_KEY} = \"${RETROARCH_VALUE}\"" +} + +function match() { + local seek="${1}" + shift + local myarray=(${@}) + if [[ "${myarray[*]}" =~ ${seek} ]] + then + local MATCH="1" + else + local MATCH="0" + fi + log "Match: [${seek}] [${MATCH}] (${myarray[*]})" + echo ${MATCH} +} + +### +### Game data functions +### + +### Configure retroarch paths +function set_retroarch_paths() { + for RPATH in assets_directory cache_directory \ + cheat_database_path content_database_path \ + content_database_path joypad_autoconfig_dir \ + libretro_directory libretro_info_path \ + overlay_directory video_shader_dir + do + clear_setting "${RPATH}" + done + flush_settings + cat <>${RETROARCH_CONFIG} +assets_directory = "/tmp/assets" +cache_directory = "/tmp/cache" +cheat_database_path = "/tmp/database/cht" +content_database_path = "/tmp/database/rdb" +joypad_autoconfig_dir = "/tmp/joypads" +libretro_directory = "/tmp/cores" +libretro_info_path = "/tmp/cores" +overlay_directory = "/tmp/overlays" +video_shader_dir = "/tmp/shaders" +EOF +} + +### Configure retroarch hotkeys +function configure_hotkeys() { + log "Configure hotkeys..." + local MY_CONTROLLER + if grep -q "js0" /proc/bus/input/devices; then + MY_CONTROLLER=$(grep -b4 js0 /proc/bus/input/devices | awk 'BEGIN {FS="\""}; /Name/ {printf $2}') + else + MY_CONTROLLER=$(grep -b4 joypad /proc/bus/input/devices | awk 'BEGIN {FS="\""}; /Name/ {printf $2}') + fi + + ### Remove any input settings retroarch may have added. + sed -i '/input_player[0-9]/d' ${RETROARCH_CONFIG} + + if [ "$(get_setting system.autohotkeys)" == "1" ] + then + if [ -e "/tmp/joypads/${MY_CONTROLLER}.cfg" ] + then + cp /tmp/joypads/"${MY_CONTROLLER}.cfg" /tmp + sed -i "s# = #=#g" /tmp/"${MY_CONTROLLER}.cfg" + source /tmp/"${MY_CONTROLLER}.cfg" + for HKEYSETTING in input_enable_hotkey_btn input_bind_hold \ + input_exit_emulator_btn input_fps_toggle_btn \ + input_menu_toggle_btn input_save_state_btn \ + input_load_state_btn input_toggle_fast_forward_btn \ + input_toggle_fast_forward_axis input_rewind_axis \ + input_rewind_btn + do + clear_setting "${HKEYSETTING}" + done + flush_settings + if [ -z ${input_enable_hotkey_btn+x} ] + then + echo 'input_enable_hotkey_btn = '\"${input_select_btn}\" >>${RETROARCH_CONFIG} + else + echo 'input_enable_hotkey_btn = '\"${input_enable_hotkey_btn}\" >>${RETROARCH_CONFIG} + fi + cat <>${RETROARCH_CONFIG} +input_bind_hold = "${input_select_btn}" +input_exit_emulator_btn = "${input_start_btn}" +input_fps_toggle_btn = "${input_y_btn}" +input_menu_toggle_btn = "${input_x_btn}" +input_save_state_btn = "${input_r_btn}" +input_load_state_btn = "${input_l_btn}" +EOF + if [ -n "${input_r2_btn}" ] && \ + [ -n "${input_l2_btn}" ] + then + cat <>${RETROARCH_CONFIG} +input_toggle_fast_forward_axis = "nul" +input_toggle_fast_forward_btn = "${input_r2_btn}" +input_rewind_axis = "nul" +input_rewind_btn = "${input_l2_btn}" +EOF + elif [ -n "${input_r2_axis}" ] && \ + [ -n "${input_l2_axis}" ] + then + cat <>${RETROARCH_CONFIG} +input_toggle_fast_forward_axis = "${input_r2_axis}" +input_toggle_fast_forward_btn = "nul" +input_rewind_axis = "${input_l2_axis}" +input_rewind_btn = "nul" +EOF + fi + rm -f /tmp/"${MY_CONTROLLER}.cfg" + fi + fi +} + +function set_ra_menudriver() { + add_setting "retroarch.menu_driver" "menu_driver" + local MENU_DRIVER=$(game_setting retroarch.menu_driver) + case ${MENU_DRIVER} in + rgui) + add_setting "none" "menu_linear_filter" "true" + ;; + esac +} + +function set_fps() { + add_setting "showFPS" "fps_show" +} + +function set_config_save() { + add_setting "config_save_on_exit" "false" +} + +function set_cheevos() { + local USE_CHEEVOS=$(game_setting "retroachievements") + local CHECK_CHEEVOS="$(match "${PLATFORM}" "${HAS_CHEEVOS[@]}")" + if [ "${USE_CHEEVOS}" = 1 ] && \ + [ "${CHECK_CHEEVOS}" = 1 ] + then + add_setting "none" "cheevos_enable" "true" + add_setting "retroachievements.username" "cheevos_username" + add_setting "retroachievements.password" "cheevos_password" + add_setting "none" "cheevos_cmd" "/usr/share/libretro/call_achievements_hooks.sh" + add_setting "retroachievements.hardcore" "cheevos_hardcore_mode_enable" + add_setting "retroachievements.leaderboards" "cheevos_leaderboards_enable" + add_setting "retroachievements.verbose" "cheevos_verbose_enable" + add_setting "retroachievements.screenshot" "cheevos_auto_screenshot" + add_setting "retroachievements.richpresence" "cheevos_richpresence_enable" + add_setting "retroachievements.challengeindicators" "cheevos_challenge_indicators" + add_setting "retroachievements.testunofficial" "cheevos_test_unofficial" + add_setting "retroachievements.badges" "cheevos_badges_enable" + add_setting "retroachievements.active" "cheevos_start_active" + local CHEEVOS_SOUND_ENABLE=$(game_setting "retroachievements.sound") + if [ "${CHEEVOS_SOUND_ENABLE}" != "none" ]; then + add_setting "none" "cheevos_unlock_sound_enable" "true" + add_setting "retroachievements.sound" "cheevos_unlock_sound" + else + add_setting "none" "cheevos_unlock_sound_enable" "false" + fi + else + add_setting "none" "cheevos_enable" "false" + fi +} + +function set_netplay() { + USE_NETPLAY=$(game_setting "netplay") + if [ "${USE_NETPLAY}" = 1 ] + then + add_setting "none" "savestate_auto_load" "false" + add_setting "none" "savestate_auto_save" "false" + add_setting "retroachievements.hardcore" "cheevos_hardcore_mode_enable" "false" + add_setting "global.netplay.nickname" "netplay_nickname" + add_setting "global.netplay.password" "netplay_password" + add_setting "netplay_public_announce" "netplay_public_announce" + local NETPLAY_MODE=$(game_setting "netplay.mode") + local NETPLAY_PORT=$(game_setting "global.netplay.port") + case ${NETPLAY_MODE} in + host) + add_setting "none" "netplay_mode" "false" + add_setting "none" "netplay_client_swap_input" "false" + add_setting "global.netplay.port" "netplay_ip_port" "${NETPLAY_PORT}" + case ${CORE} in + gambatte) + log "Configuring gameboy link server." + if [ ! -d "${RETROARCH_PATH}/config/Gambatte" ] + then + mkdir -p "${RETROARCH_PATH}/config/Gambatte" + fi + local GAMBATTE_CONF="${RETROARCH_PATH}/config/Gambatte/Gambatte.opt" + ### Rework this to use add_setting and be configurable in ES. + sed -i '/gambatte_gb_link_mode/d; \ + /gambatte_gb_link_network_port/d' ${GAMBATTE_CONF} + cat <>${GAMBATTE_CONF} +gambatte_gb_link_mode = "Network Server" +gambatte_gb_link_network_port = "$(( ${NETPLAY_PORT} + 1 ))" +EOF + ;; + tgbdual) + log "Configuring tgbdual for network play" + if [ ! -d "${RETROARCH_PATH}/config/TGB Dual" ] + then + mkdir -p "${RETROARCH_PATH}/config/TGB Dual" + fi + local TGBDUAL_CONF="${RETROARCH_PATH}/config/TGB Dual/TGB Dual.opt" + sed -i '/tgbdual_gblink_enable/d; \ + /tgbdual_single_screen_mp/d; \ + /tgbdual_switch_screens/d; \ + /tgbdual_audio_output/d' "${TGBDUAL_CONF}" + cat <>"${TGBDUAL_CONF}" +tgbdual_gblink_enable = "enabled" +tgbdual_single_screen_mp = "player 1 only" +tgbdual_switch_screens = "normal" +tgbdual_audio_output = "Game Boy #1" +EOF + echo -n " --host" + ;; + genesis_plus_gx) + log "Configure genesis_plus_gx 4 way play." + add_setting "none" "input_libretro_device_p2" "1025" + echo -n " --host" + ;; + + snes9x) + log "Configure snes9x multitap." + add_setting "none" "input_libretro_device_p2" "257" + echo -n " --host" + ;; + *) + echo -n " --host" + ;; + esac + ;; + client) + local NETPLAY_HOST_IP=$(get_setting global.netplay.host) + add_setting "global.netplay.port" "${NETPLAY_PORT}" + if [ ! -z "${NETPLAY_HOST_IP}" ] + then + add_setting "none" "netplay_ip_address" "${NETPLAY_HOST_IP}" + case ${CORE} in + gambatte) + log "Configuring gameboy link client." + if [ ! -d "${RETROARCH_PATH}/config/Gambatte" ] + then + mkdir -p "${RETROARCH_PATH}/config/Gambatte" + fi + add_setting "none" "netplay_mode" "false" + add_setting "none" "netplay_client_swap_input" "false" + local GAMBATTE_CONF="${RETROARCH_PATH}/config/Gambatte/Gambatte.opt" + sed -i '/gambatte_gb_link_mode/d; \ + /gambatte_gb_link_network_port/d' ${GAMBATTE_CONF} + cat <>${GAMBATTE_CONF} +gambatte_gb_link_mode = "Network Client" +gambatte_gb_link_network_port = "$(( ${NETPLAY_PORT} + 1 ))" +EOF + + sed -i '/gambatte_gb_link_network_server_ip_/d' ${GAMBATTE_CONF} + + local IPARRAY=(${NETPLAY_HOST_IP//./ }) + for ELEM in ${IPARRAY[*]} + do + ADDR="${ADDR}$(printf "%03d" "${ELEM}")" + done + + local COUNT=1 + for (( i=0; i<${#ADDR}; i++ )); + do + cat <>${GAMBATTE_CONF} +gambatte_gb_link_network_server_ip_${COUNT} = "${ADDR:$i:1}" +EOF + COUNT=$(( ${COUNT} + 1 )) + done + ;; + tgbdual) + log "Configuring tgbdual for network play" + if [ ! -d "${RETROARCH_PATH}/config/TGB Dual" ] + then + mkdir -p "${RETROARCH_PATH}/config/TGB Dual" + fi + local TGBDUAL_CONF="${RETROARCH_PATH}/config/TGB Dual/TGB Dual.opt" + local PLAYER=$(get_setting wifi.adhoc.id) + if [ -z "${PLAYER}" ] + then + PLAYER=2 + fi + sed -i '/tgbdual_gblink_enable/d; \ + /tgbdual_single_screen_mp/d; \ + /tgbdual_switch_screens/d; \ + /tgbdual_audio_output/d' "${TGBDUAL_CONF}" + cat <"${TGBDUAL_CONF}" +tgbdual_gblink_enable = "enabled" +tgbdual_single_screen_mp = "player ${PLAYER} only" +tgbdual_switch_screens = "normal" +tgbdual_audio_output = "Game Boy #${PLAYER}" +EOF + add_setting "none" "netplay_mode" "true" + add_setting "none" "netplay_client_swap_input" "true" + echo -n " --connect ${NETPLAY_HOST_IP}" + ;; + *) + add_setting "none" "netplay_mode" "true" + add_setting "none" "netplay_client_swap_input" "true" + echo -n " --connect ${NETPLAY_HOST_IP}" + ;; + esac + fi + ;; + esac + local NETPLAY_RELAY=$(game_setting global.netplay.relay) + if [ -n "${NETPLAY_RELAY}" ] + then + case ${NETPLAY_RELAY} in + none|false|0) + add_setting "none" "netplay_use_mitm_server" "false" + ;; + custom) + add_setting "none" "netplay_use_mitm_server" "true" + add_setting "none" "netplay_mitm_server" "${NETPLAY_RELAY}" + add_setting "global.netplay.customserver" "netplay_custom_mitm_server" + ;; + *) + add_setting "none" "netplay_use_mitm_server" "true" + add_setting "none" "netplay_mitm_server" "${NETPLAY_RELAY}" + ;; + esac + else + add_setting "none" "netplay_use_mitm_server" "false" + fi + else + add_setting "none" "netplay" "false" + fi +} + +function set_translation() { + local USE_AI_SERVICE="$(game_setting ai_service_enabled)" + case ${USE_AI_SERVICE} in + 0|false|none) + add_setting "none" "ai_service_enable" "false" + ;; + *) + add_setting "none" "ai_service_enable" "true" + local AI_LANG="$(game_setting ai_target_lang)" + local AI_URL="$(game_setting ai_service_url)" + case ${AI_URL} in + 0|false|none) + add_setting "none" "ai_service_url" "http://ztranslate.net/service?api_key=BATOCERA&mode=Fast&output=png&target_lang=${AI_LANG}" + ;; + *) + add_setting "none" "ai_service_url" "${AI_URL}&mode=Fast&output=png&target_lang=${AI_LANG}" + ;; + esac + ;; + esac +} + +function set_aspectratio() { + local ASPECT_RATIO="$(game_setting ratio)" + case ${ASPECT_RATIO} in + 0|false|none) + add_setting "none" "aspect_ratio_index" "22" + ;; + *) + for AR in ${!CORE_RATIOS[@]} + do + if [ "${CORE_RATIOS[${AR}]}" = "${ASPECT_RATIO}" ] + then + add_setting "none" "aspect_ratio_index" "${AR}" + break + fi + done + ;; + esac +# add_setting "positionx" "custom_viewport_x" +# add_setting "positiony" "custom_viewport_y" +# add_setting "width" "custom_viewport_width" +# add_setting "height" "custom_viewport_height" + add_setting "rotation" "video_rotation" +} + +function set_filtering() { + add_setting "smooth" "video_smooth" +} + +function set_integerscale() { + add_setting "integerscale" "video_scale_integer" + add_setting "integerscaleoverscale" "video_scale_integer_overscale" +} + +function set_rgascale() { + add_setting "rgascale" "video_ctx_scaling" +} + +function set_shader() { + local SHADER="$(game_setting shaderset)" + case ${SHADER} in + 0|false|none) + add_setting "none" "video_shader_enable" "false" + ;; + *) + add_setting "none" "video_shader_enable" "true" + add_setting "none" "video_shader" "${SHADER}" + echo -n " --set-shader /tmp/shaders/${SHADER}" + ;; + esac +} + +function set_filter() { + local FILTER="$(game_setting videofilter)" + case ${FILTER} in + 0|false|none) + add_setting "none" "video_filter" "" + ;; + *) + local FILTER_PATH="/usr/share/retroarch/filters" + add_setting "none" "video_ctx_scaling" "false" + local CHECK_BITNESS="$(match ${CORE} ${IS_32BIT[@]})" + if [ "${CHECK_BITNESS}" = 1 ] + then + BITS="32" + else + BITS="64" + fi + add_setting "none" "video_filter" "${FILTER_PATH}/${BITS}bit/video/${FILTER}" + add_setting "none" "video_filter_dir" "${FILTER_PATH}/${BITS}bit/video/" + add_setting "none" "audio_filter_dir" "${FILTER_PATH}/${BITS}bit/audio" + ;; + esac +} + +function set_overlay() { + local BEZEL="$(game_setting bezel)" + case ${BEZEL} in + 0|false|none) + ;; + *) + write_bezel_config + exit 0 + ;; + esac + + local OVERLAY="$(game_setting overlayset)" + case ${OVERLAY} in + 0|false|none) + add_setting "none" "input_overlay_enable" "false" + add_setting "none" "input_overlay" "" + ;; + *) + local OVERLAY_PATH="/storage/overlays" + add_setting "none" "input_overlay_enable" "true" + add_setting "none" "input_overlay" "${OVERLAY_PATH}/${OVERLAY}" + ;; + esac +} + +function set_rewind() { + local REWIND="$(game_setting rewind)" + case ${REWIND} in + 1) + case $(match ${PLATFORM} ${NO_REWIND[@]}) in + 0) + add_setting "none" "rewind_enable" "true" + ;; + *) + add_setting "none" "rewind_enable" "false" + ;; + esac + ;; + *) + add_setting "none" "rewind_enable" "false" + ;; + esac +} + +function set_savestates() { + local SAVESTATES="$(game_setting incrementalsavestates)" + local MAXINCREMENTALSAVES="$(game_setting maxincrementalsaves)" + case ${SAVESTATES} in + 0|false|none) + add_setting "none" "savestate_auto_index" "false" + ;; + *) + add_setting "none" "savestate_auto_index" "true" + ;; + esac + add_setting "none" "savestate_max_keep" "${MAXINCREMENTALSAVES}" +} + +function set_autosave() { + local SETAUTOSAVE=false + + # argument overrides user setting + case ${AUTOSAVE} in + 0) + SETAUTOSAVE=false + ;; + 1) + SETAUTOSAVE=true + ;; + *) + local AUTOSAVE_SETTING="$(game_setting autosave)" + case ${AUTOSAVE_SETTING} in + [1-3]) + SETAUTOSAVE=true + ;; + esac + ;; + esac + + add_setting "none" "savestate_directory" "${SNAPSHOTS}/${PLATFORM}" + if [ ! -d "${SNAPSHOTS}/${PLATFORM}" ] + then + mkdir "${SNAPSHOTS}/${PLATFORM}" + fi + + if [ ! -z "${SNAPSHOT}" ] + then + add_setting "none" "state_slot" "${SNAPSHOT}" + fi + + add_setting "none" "savestate_auto_load" "${SETAUTOSAVE}" + add_setting "none" "savestate_auto_save" "${SETAUTOSAVE}" +} + +function set_runahead() { + local RUNAHEAD="$(game_setting runahead)" + local HAS_RUNAHEAD="$(match ${PLATFORM} ${NO_RUNAHEAD[@]})" + case ${HAS_RUNAHEAD} in + 1) + add_setting "none" "run_ahead_enabled" "false" + add_setting "none" "run_ahead_frames" "0" + ;; + *) + if [ "${RUNAHEAD}" -gt 0 ] + then + add_setting "none" "run_ahead_enabled" "true" + add_setting "none" "run_ahead_frames" "${RUNAHEAD}" + add_setting "secondinstance" "run_ahead_secondary_instance" + else + add_setting "none" "run_ahead_enabled" "false" + add_setting "none" "run_ahead_frames" "0" + fi + ;; + esac +} + +function set_audiolatency() { + add_setting "audiolatency" "audio_latency" +} + +function set_analogsupport() { + local HAS_ANALOG="$(match ${PLATFORM} ${NO_ANALOG[@]})" + case ${HAS_ANALOG} in + 1) + add_setting "none" "input_player1_analog_dpad_mode" "0" + ;; + *) + add_setting "analogue" "input_player1_analog_dpad_mode" "1" + ;; + esac +} + +function set_tatemode() { + log "Setup tate mode..." + if [ "${CORE}" = "mame2003_plus" ] + then + local TATEMODE="$(game_setting tatemode)" + local MAME2003DIR="${RETROARCH_PATH}/config/MAME 2003-Plus" + local MAME2003REMAPDIR="/storage/remappings/MAME 2003-Plus" + if [ ! -d "${MAME2003DIR}" ] + then + mkdir -p "${MAME2003DIR}" + fi + if [ ! -d "${MAME2003REMAPDIR}" ] + then + mkdir -p "${MAME2003REMAPDIR}" + fi + case ${TATEMODE} in + 1|true) + cp "/usr/config/retroarch/TATE-MAME 2003-Plus.rmp" "${MAME2003REMAPDIR}/MAME 2003-Plus.rmp" + if [ "$(grep mame2003-plus_tate_mode "${MAME2003DIR}/MAME 2003-Plus.opt" > /dev/null 2>&1)" ] + then + sed -i 's#mame2003-plus_tate_mode.*$#mame2003-plus_tate_mode = "enabled"#' "${MAME2003DIR}/MAME 2003-Plus.opt" 2>/dev/null + else + echo 'mame2003-plus_tate_mode = "enabled"' > "${MAME2003DIR}/MAME 2003-Plus.opt" + fi + ;; + *) + if [ -e "${MAME2003DIR}/MAME 2003-Plus.opt" ] + then + sed -i 's#mame2003-plus_tate_mode.*$#mame2003-plus_tate_mode = "disabled"#' "${MAME2003DIR}/MAME 2003-Plus.opt" 2>/dev/null + fi + if [ -e "${MAME2003REMAPDIR}/MAME 2003-Plus.rmp" ] + then + rm -f "${MAME2003REMAPDIR}/MAME 2003-Plus.rmp" + fi + ;; + esac + fi +} + +function set_n64opts() { + log "Set up N64..." + if [ "${CORE}" = "parallel_n64" ] + then + local PARALLELN64DIR="${RETROARCH_PATH}/config/ParaLLEl N64" + if [ ! -d "${PARALLELN64DIR}" ] + then + mkdir -p "${PARALLELN64DIR}" + fi + + if [ ! -f "${PARALLELN64DIR}/ParaLLEl N64.opt" ] + then + cp "/usr/config/retroarch/ParaLLEl N64.opt" "${PARALLELN64DIR}/ParaLLEl N64.opt" + fi + local VIDEO_CORE="$(game_setting parallel_n64_video_core)" + sed -i '/parallel-n64-gfxplugin = /c\parallel-n64-gfxplugin = "'${VIDEO_CORE}'"' "${PARALLELN64DIR}/ParaLLEl N64.opt" + local SCREENSIZE="$(game_setting parallel_n64_internal_resolution)" + sed -i '/parallel-n64-screensize = /c\parallel-n64-screensize = "'${SCREENSIZE}'"' "${PARALLELN64DIR}/ParaLLEl N64.opt" + local GAMESPEED="$(game_setting parallel_n64_gamespeed)" + sed -i '/parallel-n64-framerate = /c\parallel-n64-framerate = "'${GAMESPEED}'"' "${PARALLELN64DIR}/ParaLLEl N64.opt" + local ACCURACY="$(game_setting parallel_n64_gfx_accuracy)" + sed -i '/parallel-n64-gfxplugin-accuracy = /c\parallel-n64-gfxplugin-accuracy = "'${ACCURACY}'"' "${PARALLELN64DIR}/ParaLLEl N64.opt" + local CONTROLLERPAK="$(game_setting parallel_n64_controller_pak)" + sed -i '/parallel-n64-pak1 = /c\parallel-n64-pak1 = "'${CONTROLLERPAK}'"' "${PARALLELN64DIR}/ParaLLEl N64.opt" + fi +} + +function set_saturnopts() { + log "Set up Saturn..." + if [ "${CORE}" = "kronos" ] + then + log "Set up Kronos..." + local KRONOSDIR="${RETROARCH_PATH}/Kronos/config/Kronos" + if [ ! -d "${KRONOSDIR}" ] + then + mkdir -p "${KRONOSDIR}" + fi + + if [ ! -f "${KRONOSDIR}/Kronos.opt" ] + then + cp "/usr/config/retroarch/Kronos.opt" "${KRONOSDIR}/Kronos.opt" + fi + local KRONOSOPT="${KRONOSDIR}/Kronos.opt" + local HLE_BIOS="$(game_setting force_hle_bios)" + sed -i '/kronos_force_hle_bios = /c\kronos_force_hle_bios = "'${HLE_BIOS}'"' "${KRONOSOPT}" + local ADDON_CART="$(game_setting addon_cartridge)" + sed -i '/kronos_addon_cartridge = /c\kronos_addon_cartridge = "'${ADDON_CART}'"' "${KRONOSOPT}" + local TESSELATION="$(game_setting tesselation)" + sed -i '/kronos_polygon_mode = /c\kronos_polygon_mode = "'${TESSELATION}'"' "${KRONOSOPT}" + local RESOLUTION="$(game_setting resolution)" + sed -i '/kronos_resolution_mode = /c\kronos_resolution_mode = "'${RESOLUTION}'"' "${KRONOSOPT}" + local COMPUTE_SHADER="$(game_setting compute_shader)" + sed -i '/kronos_use_cs = /c\kronos_use_cs = "'${COMPUTE_SHADER}'"' "${KRONOSOPT}" + local TRANSPARENCY="$(game_setting transparency)" + sed -i '/kronos_mesh_mode = /c\kronos_mesh_mode = "'${TRANSPARENCY}'"' "${KRONOSOPT}" + fi +} + +function set_snesopts() { + log "Set up SNES..." + if [ "${CORE}" = "beetle_supafaust" ] + then + log "Set up beetle_supafaust" + local FAUSTDIR="${RETROARCH_PATH}/config/Supafaust" + if [ ! -d "${FAUSTDIR}" ] + then + mkdir -p "${FAUSTDIR}" + fi + if [ ! -f "${FAUSTDIR}/Supafaust.opt" ] + then + cp "/usr/config/retroarch/Supafaust.opt" "${FAUSTDIR}/Supafaust.opt" + fi + fi +} + +function set_dreamcastopts() { + log "Set up Dreamcast..." + if [ "${CORE}" = "flycast" ] + then + local FLYCASTDIR="${RETROARCH_PATH}/config/Flycast" + if [ ! -d "${FLYCASTDIR}" ] + then + mkdir -p "${FLYCASTDIR}" + fi + + if [ ! -f "${FLYCASTDIR}/Flycast.opt" ] + then + cp "/usr/config/retroarch/Flycast.opt" "${FLYCASTDIR}/Flycast.opt" + fi + local FRAME_SKIP="$(game_setting frame_skip)" + sed -i '/flycast_auto_skip_frame = /c\flycast_auto_skip_frame = "'${FRAME_SKIP}'"' "${FLYCASTDIR}/Flycast.opt" + fi +} + +function set_melondsdsopts() { + log "Set up melonDS DS..." + if [ "${CORE}" = "melondsds" ] + then + local MELONDSDSDIR="${RETROARCH_PATH}/config/melonDS DS" + if [ ! -d "${MELONDSDSDIR}" ] + then + mkdir -p "${MELONDSDSDIR}" + fi + + if [ ! -f "${MELONDSDSDIR}/melonDS DS.opt" ] + then + cat <"${MELONDSDSDIR}/melonDS DS.opt" +melonds_boot_mode = "direct" +melonds_console_mode = "ds" +melonds_show_cursor = "timeout" +melonds_touch_mode = "auto" +EOF + fi + + if [ "${PLATFORM}" = "ndsiware" ] + then + sed -i '/melonds_console_mode = /c\melonds_console_mode = "dsi"' "${MELONDSDSDIR}/melonDS DS.opt" + else + sed -i '/melonds_console_mode = /c\melonds_console_mode = "ds"' "${MELONDSDSDIR}/melonDS DS.opt" + fi + + if [ "${DEVICE_HAS_TOUCHSCREEN}" = "true" ] + then + sed -i '/melonds_show_cursor = /c\melonds_show_cursor = "disabled"' "${MELONDSDSDIR}/melonDS DS.opt" + sed -i '/melonds_touch_mode = /c\melonds_touch_mode = "touch"' "${MELONDSDSDIR}/melonDS DS.opt" + fi + fi +} + +function set_atari() { + log "Set up Atari (FIXME)..." + if [ "${CORE}" = "atari800" ] + then + ATARICONF="/storage/.config/system/configs/atari800.cfg" + ATARI800CONF="${RETROARCH_PATH}/config/Atari800/Atari800.opt" + if [ ! -f "$ATARI800CONF" ] + then + touch "$ATARI800CONF" + fi + 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 + add_setting "none" "atari800_system" "5200" + echo "atari800_system = \"5200\"" >> ${ATARI800CONF} + echo "RAM_SIZE=16" >> ${ATARICONF} + echo "STEREO_POKEY=0" >> ${ATARICONF} + echo "BUILTIN_BASIC=0" >> ${ATARICONF} + else + add_setting "none" "atari800_system" "800XL (64K)" + echo "atari800_system = \"800XL (64K)\"" >> ${ATARI800CONF} + echo "RAM_SIZE=64" >> ${ATARICONF} + echo "STEREO_POKEY=1" >> ${ATARICONF} + echo "BUILTIN_BASIC=1" >> ${ATARICONF} + fi + flush_settings + fi +} + +function set_gambatte() { + log "Set up Gambatte..." + if [ "${CORE}" = "gambatte" ] + then + GAMBATTECONF="${RETROARCH_PATH}/config/Gambatte/Gambatte.opt" + if [ ! -f "GAMBATTECONF" ] + then + echo 'gambatte_gbc_color_correction = "disabled"' > ${GAMBATTECONF} + else + sed -i "/gambatte_gb_colorization =/d" ${GAMBATTECONF} + sed -i "/gambatte_gb_internal_palette =/d" ${GAMBATTECONF} + fi + local COLORIZATION=$(game_setting renderer.colorization) + local TWB1_COLORIZATION=$(game_setting renderer.twb1_colorization) + local TWB2_COLORIZATION=$(game_setting renderer.twb2_colorization) + local TWB3_COLORIZATION=$(game_setting renderer.twb3_colorization) + local PIXELSHIFT1_COLORIZATION=$(game_setting renderer.pixelshift1_colorization) + + if [ -n "${COLORIZATION}" ] + then + case ${COLORIZATION} in + 0|false|none) + echo 'gambatte_gb_colorization = "disabled"' >> ${GAMBATTECONF} + ;; + "Best Guess") + echo 'gambatte_gb_colorization = "auto"' >> ${GAMBATTECONF} + ;; + GBC|SGB) + echo 'gambatte_gb_colorization = "'${COLORIZATION}'"' >> ${GAMBATTECONF} + ;; + *) + echo 'gambatte_gb_colorization = "internal"' >> ${GAMBATTECONF} + echo 'gambatte_gb_internal_palette = "'${COLORIZATION}'"' >> ${GAMBATTECONF} + echo 'gambatte_gb_palette_twb64_1 = "'${TWB1_COLORIZATION}'"' >> ${GAMBATTECONF} + echo 'gambatte_gb_palette_twb64_2 = "'${TWB2_COLORIZATION}'"' >> ${GAMBATTECONF} + echo 'gambatte_gb_palette_twb64_3 = "'${TWB3_COLORIZATION}'"' >> ${GAMBATTECONF} + echo 'gambatte_gb_palette_pixelshift_1 = "'${PIXELSHIFT1_COLORIZATION}'"' >> ${GAMBATTECONF} + ;; + esac + fi + fi +} + +function setup_controllers() { + for i in $(seq 1 1 5) + do + log "Controller setup (${i})" + if [[ "$CONTROLLERS" == *p${i}* ]] + then + PINDEX="${CONTROLLERS#*-p${i}index }" + PINDEX="${PINDEX%% -p${i}guid*}" + log "Set up controller ($i) (${PINDEX})" + add_setting "none" "input_player${i}_joypad_index" "${PINDEX}" + case ${PLATFORM} in + atari5200) + add_setting "none" "input_libretro_device_p${i}" "513" + ;; + esac + fi + done + flush_settings +} + +# Function to write bezel configuration +write_bezel_config() { + RETROARCH_OVERLAY_CONFIG="/tmp/.overlay.cfg" + + local json_output + json_output=$(get_bezel_infos "${ROM}" "${BEZEL}" "${PLATFORM}" "retroarch") + + if [ $? -eq 0 ] && [ -n "$json_output" ]; then + local bezel_png + bezel_png=$(echo "$json_output" | jq -r '.png') + + if [ -n "$bezel_png" ] && [ -f "$bezel_png" ]; then + cat > "$RETROARCH_OVERLAY_CONFIG" << EOF +overlays = 1 +overlay0_overlay = "$bezel_png" +overlay0_full_screen = true +overlay0_descs = 0 +EOF + + add_setting "none" "input_overlay_enable" "true" + add_setting "none" "input_overlay" "${RETROARCH_OVERLAY_CONFIG}" + return 0 + fi + fi + + return 1 +} + +# Function to check bezel file existence +check_bezel_file() { + local base_path="$1" + local file_name="$2" + + if [ -f "${base_path}/${file_name}.png" ]; then + bezel_png="${base_path}/${file_name}.png" + if [ -f "${base_path}/${file_name}.info" ]; then + bezel_info="${base_path}/${file_name}.info" + elif [ -f "${base_path}/default.info" ]; then + bezel_info="${base_path}/default.info" + else + bezel_info="${bezel_png}" + fi + return 0 + fi + return 1 +} + +# Function to check decorations in a directory +check_decorations() { + local base_path="$1" + local system_name="$2" + local rom_name="$3" + + if [ -d "${base_path}/games/${system_name}" ]; then + if check_bezel_file "${base_path}/games/${system_name}" "${rom_name}"; then + specific_to_game="true" + return 0 + fi + fi + + if [ -d "${base_path}/systems" ]; then + if check_bezel_file "${base_path}/systems" "${system_name}"; then + return 0 + fi + fi + + if check_bezel_file "${base_path}" "default"; then + return 0 + fi + + return 1 +} + +# Function to get bezel information +get_bezel_infos() { + local rom="$1" + local bezel="$2" + local system="$3" + local target="$4" + + # Initialize variables + local bezel_info="" + local bezel_png="" + local layout_file="" + local mame_zip="" + local specific_to_game="false" + + # Check parameters + if [ -z "$rom" ] || [ -z "$system" ] || [ -z "$target" ]; then + return 1 + fi + + # Get ROM name without extension + local rom_name=$(basename "${rom}") + rom_name="${rom_name%.*}" + + # Check if bezel parameter is provided + if [ -n "$bezel" ]; then + local bezel_base_path="${BEZEL_DIR}/${bezel}" + + if check_decorations "${bezel_base_path}" "${system}" "${rom_name}"; then + cat << EOF +{ + "png": "$bezel_png", + "info": "${bezel_info}", + "layout": "${layout_file:-null}", + "mamezip": "${mame_zip:-null}", + "specific_to_game": $specific_to_game +} +EOF + return 0 + fi + fi + + return 1 +} + +### +### Execute functions +### + +### +### Functions that must be run without parallelization. +### + +set_retroarch_paths +setup_controllers +configure_hotkeys + +### +### Game specific functions +### + +set_atari & +set_gambatte & + +wait +flush_settings + +### +### Functions that can execute in parallel. +### + +set_ra_menudriver & +set_config_save & +set_fps & +set_cheevos & +set_translation & +set_aspectratio & +set_filtering & +set_integerscale & +set_rgascale & +set_shader & +set_filter & +set_overlay & +set_rewind & +set_savestates & +set_autosave & +set_netplay & +set_runahead & +set_audiolatency & +set_analogsupport & +set_tatemode & +set_n64opts & +set_saturnopts & +set_snesopts & +set_dreamcastopts & +set_melondsdsopts & + +### Sed operations are expensive, so they are staged and executed as +### a single process when all forks complete. +wait +flush_settings + +cleanup diff --git a/projects/ArchR/packages/archr/sources/scripts/show_changelog b/projects/ArchR/packages/archr/sources/scripts/show_changelog new file mode 100755 index 0000000000..98f2598faf --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/show_changelog @@ -0,0 +1,32 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile + +CHANGELOG="/storage/.cache/changelog" + +if [ ! -e "${CHANGELOG}" ] +then + exit 0 +fi + +WIDTH=$(fbwidth) + +if [ "${WIDTH}" -le "480" ] +then + FONTSIZE=8 +elif [ "${WIDTH}" -gt "480" ] && [ "${WIDTH}" -le "640" ] +then + FONTSIZE=12 +elif [ "${WIDTH}" -gt "640" ] && [ "${WIDTH}" -le "720" ] +then + FONTSIZE=14 +elif [ "${WIDTH}" -gt "720" ] && [ "${WIDTH}" -lt "1080" ] +then + FONTSIZE=20 +else + FONTSIZE=24 +fi + +/usr/bin/text_viewer -f ${FONTSIZE} ${CHANGELOG} diff --git a/projects/ArchR/packages/archr/sources/scripts/suspendmode b/projects/ArchR/packages/archr/sources/scripts/suspendmode new file mode 100755 index 0000000000..9fba960b99 --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/suspendmode @@ -0,0 +1,55 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile + +REQUESTED_MODE="${*}" +SUSPEND_MODE=$(get_setting system.suspendmode) + +if [ ! "${REQUESTED_MODE}" = "${SUSPEND_MODE}" ]; then + cat </storage/.config/sleep.conf.d/sleep.conf +[Sleep] +EOF + case ${REQUESTED_MODE} in + off) + cat <>/storage/.config/sleep.conf.d/sleep.conf +AllowSuspend=no +EOF + ;; + freeze) + cat <>/storage/.config/sleep.conf.d/sleep.conf +AllowSuspend=yes +SuspendState=freeze standby mem +EOF + ;; + standby) + cat <>/storage/.config/sleep.conf.d/sleep.conf +AllowSuspend=yes +SuspendState=standby mem freeze +EOF + ;; + mem) + cat <>/storage/.config/sleep.conf.d/sleep.conf +AllowSuspend=yes +SuspendState=mem standby freeze +EOF + ;; + default) + del_setting system.suspendmode + if [ -e "/usr/lib/autostart/quirks/devices/${QUIRK_DEVICE}/030-suspend_mode" ]; then + "/usr/lib/autostart/quirks/devices/${QUIRK_DEVICE}/030-suspend_mode" + elif [ -e "/usr/lib/autostart/quirks/platforms/${HW_DEVICE}/030-suspend_mode" ]; then + "/usr/lib/autostart/quirks/platforms/${HW_DEVICE}/030-suspend_mode" + fi + ;; + *) + cat <>/storage/.config/sleep.conf.d/sleep.conf +AllowSuspend=yes +SuspendState=${REQUESTED_MODE} +EOF + ;; + esac + set_setting system.suspendmode ${1} + systemctl restart systemd-logind +fi diff --git a/projects/ArchR/packages/archr/sources/scripts/timeinfo b/projects/ArchR/packages/archr/sources/scripts/timeinfo new file mode 100755 index 0000000000..8b43dbe090 --- /dev/null +++ b/projects/ArchR/packages/archr/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) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +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/projects/ArchR/packages/archr/sources/scripts/updateabl b/projects/ArchR/packages/archr/sources/scripts/updateabl new file mode 100755 index 0000000000..691398e31d --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/updateabl @@ -0,0 +1,46 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) +# +# This script will update the ABL on the internal eMMC/UFS. + +. $SYSTEM_ROOT/etc/os-release + +case "$HW_DEVICE" in + SM6115|SM8250|SM8550|SM8650) + ;; + *) + echo "This script is not compatible with this device!" + exit 1 + ;; +esac + +# ---- Sanity checks ---- +ELF="$SYSTEM_ROOT/usr/share/bootloader/archr_abl/abl_signed-${HW_DEVICE}.elf" +if [ ! -f "${ELF}" ]; then + echo "Error: ABL update not found" + exit 1 +fi + +ABL_A="$($SYSTEM_ROOT/usr/sbin/blkid -t PARTLABEL=abl_a -o device)" +ABL_B="$($SYSTEM_ROOT/usr/sbin/blkid -t PARTLABEL=abl_b -o device)" +if [ ! -b "${ABL_A}" ] || [ ! -b "${ABL_B}" ]; then + echo "Error: ABL partitions not found" + exit 1 +fi + +# ---- Get sector size ---- +SS="$($SYSTEM_ROOT/usr/sbin/blockdev --getss "${ABL_A}")" +if [ -z "${SS}" ]; then + echo "Error: failed to get sector size" + exit 1 +fi + +# ---- Flash ---- +echo "Updating ABL partitions..." +dd if="${ELF}" of="${ABL_A}" bs="${SS}" conv=fsync,notrunc status=none +dd if="${ELF}" of="${ABL_B}" bs="${SS}" conv=fsync,notrunc status=none + +sync + +echo "ABL update completed successfully..." diff --git a/projects/ArchR/packages/archr/sources/scripts/usbgadget b/projects/ArchR/packages/archr/sources/scripts/usbgadget new file mode 100755 index 0000000000..c39d48b270 --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/usbgadget @@ -0,0 +1,521 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +# gadget setup functions (prepare_usb_network and cleanup_usb_network) are derived from code from +# * https://pastebin.com/VtAusEmf (author unknown) +# * David Lechner https://github.com/ev3dev/ev3-systemd/blob/ev3dev-buster/scripts/ev3-usb.sh +# * rundekugel @github https://github.com/rundekugel/USBGadgetNetwork/blob/main/create-dual-rndis-and-cdcecm.sh + +# For implementation benchmark results, see the end of this file + +. /etc/os-release + +MACHINEIDFILE=/storage/.cache/systemd-machine-id +SERIAL=$(cat ${MACHINEIDFILE}) + +CACHEDIR=/storage/.cache/usbgadget +GADGETCONF=${CACHEDIR}/usbgadget.conf +GADGETNETCONF=${CACHEDIR}/network.conf +UDHCPCONF=/var/run/udhcpd.conf +UDHCPPIDFILE=/var/run/udhcpd.pid + +for mod in usb_f_ncm usb_f_fs; do + modprobe -q ${mod} +done + +mkdir -p ${CACHEDIR} + +if [ -r ${GADGETCONF} ] ; then + . ${GADGETCONF} +fi + +UDC_NAME=$(ls -1 /sys/class/udc |head -n1) +CURRENT_MODE=$(cat /sys/class/udc/${UDC_NAME}/function) +[ -z ${CURRENT_MODE} ] && CURRENT_MODE=disabled + + +usb_disable() { + echo "USB_MODE=disabled" > ${GADGETCONF} + if [[ "${CURRENT_MODE}" == "disabled" ]]; then return; fi + echo "" > /sys/kernel/config/usb_gadget/${CURRENT_MODE}/UDC + CURRENT_MODE=disabled +} + + +is_cable_connected() { + # https://developerhelp.microchip.com/xwiki/bin/view/applications/usb/power-delivery/battery-charging/ + PHY_NAME=$(ls -d /sys/devices/platform/${UDC_NAME}/supplier:platform:*usb2phy | sed 's|^.*:platform:||') + for cable in /sys/devices/platform/${PHY_NAME}/extcon/*/cable.*; do + cable_name="$(cat ${cable}/name)" + case "${cable_name}" in + SDP|CDP) + # Standard Downstream Port and Charging Downstream Port carry data + # these are different types of hub ports, okay for transfer + if grep -q 1 ${cable}/state; then + return 0 + fi + ;; + *) + # Dedicated Charging Port or anything else (derived), + # these do not (reliably) indicate data transfer capability + true + ;; + esac + done + return 1 +} + + +# This function issues soft disconnect and then connect on RK3566 devices +# If gadget is activated with cable unplugged, RK3566 prints 'dwc3 fcc00000.usb: failed to enable ep0out' +# and then host cannot enumerate the gadget. +# Always activating the gadget allows simple setup logic (e.g. start udhcpd immediately), +# and few seconds to soft-disconnect should be OK when done in background +# When cable is plugged, udev calls this function again, and the gadget is soft-connected. +usb_trigger() { + # On RK3326 (single USB port): if an OTG adapter is connected (host mode), + # stop the gadget so USB devices like WiFi dongles can be detected. + # Check if extcon reports USB-HOST state. + if [[ "${HW_DEVICE}" != "RK3566" ]]; then + PHY_NAME=$(ls -d /sys/devices/platform/${UDC_NAME}/supplier:platform:*usb2phy 2>/dev/null | sed 's|^.*:platform:||') + if [ -n "${PHY_NAME}" ]; then + for cable in /sys/devices/platform/${PHY_NAME}/extcon/*/cable.*; do + cable_name="$(cat ${cable}/name 2>/dev/null)" + if [ "${cable_name}" = "USB-HOST" ] && grep -q 1 ${cable}/state 2>/dev/null; then + # OTG adapter detected, switch to host mode + if [ "${CURRENT_MODE}" != "disabled" ]; then + usb_stop + echo "USB_MODE=disabled" > ${GADGETCONF} + fi + return + fi + done + fi + return + fi + # do the weird stuff only when ep0 failed + grep -q 'control' /sys/kernel/debug/usb/${UDC_NAME}/ep0out/transfer_type && return + + # initial disconnect takes few seconds, but later it's fast. + # After successful connect, ep0out/transfer_type is control, and we stop doing this stuff + if is_cable_connected; then + CONNECT_CMD=connect + else + CONNECT_CMD=disconnect + fi + if [ "$verbose" -gt "0" ]; then echo "quirk: $1 soft ${CONNECT_CMD} ${UDC_NAME}"; fi + if [[ "$1" == "async" ]]; then + echo ${CONNECT_CMD} > /sys/class/udc/${UDC_NAME}/soft_connect & + else + echo ${CONNECT_CMD} > /sys/class/udc/${UDC_NAME}/soft_connect + fi +} + +############################################# +# code below (prepare_usb_network and cleanup_usb_network) is derived from +# https://github.com/rundekugel/USBGadgetNetwork +# and adapted for ArchR +############################################# +g_cdc="/sys/kernel/config/usb_gadget/cdc" +verbose=${verbose:-0} +devversion=0x$(echo $OS_VERSION | cut -b 3-6) # 0xYYMM; 20241025 -> 0x2410 + +prepare_usb_network() { + set -e + usb_ver="0x0200" # USB 2.0 + dev_class="2" # Communications + attr="0xC0" # Self powered + pwr="0xfe" # + cfg1="CDC" + ms_vendor_code="0xcd" # Microsoft + ms_qw_sign="MSFT100" # also Microsoft (if you couldn't tell) + + if [ -d ${g_cdc} ]; then + if [ "$(cat ${g_cdc}/UDC)" != "" ]; then + if [ "$verbose" -gt "0" ];then echo "Gadget is already up."; fi + exit 1 + fi + if [ "$verbose" -gt "0" ];then echo "Cleaning up old directory..."; fi + cleanup_usb_network + fi + if [ "$verbose" -gt "0" ];then echo "Setting up gadget..."; fi + + # Create a new gadget + + mkdir ${g_cdc} + echo "${usb_ver}" > ${g_cdc}/bcdUSB + echo "${dev_class}" > ${g_cdc}/bDeviceClass + echo "0x1d6b" > ${g_cdc}/idVendor + echo "0x0104" > ${g_cdc}/idProduct + echo "${devversion}" > ${g_cdc}/bcdDevice + mkdir ${g_cdc}/strings/0x409 + echo "${OS_NAME}" > ${g_cdc}/strings/0x409/manufacturer + echo "${QUIRK_DEVICE}" > ${g_cdc}/strings/0x409/product + echo "${SERIAL}" > ${g_cdc}/strings/0x409/serialnumber + + # config 1 is for CDC + + mkdir ${g_cdc}/configs/c.1 + echo "${attr}" > ${g_cdc}/configs/c.1/bmAttributes + echo "${pwr}" > ${g_cdc}/configs/c.1/MaxPower + mkdir ${g_cdc}/configs/c.1/strings/0x409 + echo "${cfg1}" > ${g_cdc}/configs/c.1/strings/0x409/configuration + + # Create the CDC function + + mkdir ${g_cdc}/functions/ncm.usb0 + echo "WINNCM" > ${g_cdc}/functions/ncm.usb0/os_desc/interface.ncm/compatible_id + + echo "1" > ${g_cdc}/os_desc/use + echo "${ms_vendor_code}" > ${g_cdc}/os_desc/b_vendor_code + echo "${ms_qw_sign}" > ${g_cdc}/os_desc/qw_sign + + + smac=$(echo ${SERIAL} | cut -b 1-12) + # Change the first number for each MAC address - the second digit of 2 indicates + # that these are "locally assigned (b2=1), unicast (b1=0)" addresses. This is + # so that they don't conflict with any existing vendors. Care should be taken + # not to change these two bits. + dev_mac="82ba1c9278b1" # Static to make all devices the same network for Windows, switch to "Private" once for all + host_mac="12$(echo ${smac} | cut -b 3-)" + + echo "${dev_mac}" > ${g_cdc}/functions/ncm.usb0/dev_addr + echo "${host_mac}" > ${g_cdc}/functions/ncm.usb0/host_addr + # max_segment_size allows higher MTUs which lead to higher transfer rates and lower CPU usage. + # However it needs some more work to be done as host needs to set high MTU as well + #echo "8000" > ${g_cdc}/functions/ncm.usb0/max_segment_size # f_ncm.c: #define MAX_DATAGRAM_SIZE 8000 + + # Make NCM the first configuration + ln -s ${g_cdc}/functions/ncm.usb0 ${g_cdc}/configs/c.1 + + if [ -n "$verbose" ]; then echo "Done."; fi +} + +configure_iface() { + # Hope udev rule works well, and device gets the name 'gadget' + udevadm wait --timeout=5 --settle /sys/class/net/gadget + IFACE_NAME=$(cat "${g_cdc}/functions/ncm.usb0/ifname") + + OLDIPADDRFILE=${CACHEDIR}/ip_address.conf + if [ ! -f ${GADGETNETCONF} ] ; then + NETMASK="255.255.0.0" + # Migrate old configs + if [ -f "${OLDIPADDRFILE}" ] ; then + IP=$(cat "${OLDIPADDRFILE}") + # if IP has last octed modified, fall back to large netmask + [[ "${IP##*.}" == "2" ]] || NETMASK="255.255.255.0" + fi + [ -z "$IP" ] && IP="169.254.170.2" + + cat < ${GADGETNETCONF} +IP=${IP} +NETMASK=${NETMASK} +# Stupid calculator just subtracting 1 from last octet. +# Combined with /30 subnet only (4*N+2) numbers are valid in last octet +HOSTIP=\${IP%.*}.\$((\${IP##*.}-1)) +EOF + fi + rm -f ${OLDIPADDRFILE} ${CACHEDIR}/udhcpd.conf + + . ${GADGETNETCONF} + + + ip address add ${IP}/${NETMASK} dev ${IFACE_NAME} 2>/dev/null + ip -6 address add fe80::2/64 dev ${IFACE_NAME} scope link 2>/dev/null + ip link set ${IFACE_NAME} up + + cat < ${UDHCPCONF} +interface ${IFACE_NAME} +start ${HOSTIP} +end ${HOSTIP} +opt subnet ${NETMASK} + +# Windows needs some route to "indentify" network, this allows to make connection "private" and accept samba announces +option msstaticroutes 0.0.0.0/32 ${IP} + +opt lease 86400 +max_leases 1 +lease_file /dev/null +pidfile ${UDHCPPIDFILE} +remaining no +EOF + /usr/sbin/udhcpd -S ${UDHCPCONF} +} + + +cleanup_usb_network() { + if [ ! -d ${g_cdc} ]; then + if [ "$verbose" -gt "0" ];then echo "Gadget is already down."; fi + exit 1 + fi + if [ "$verbose" -gt "0" ];then echo "Taking down gadget..."; fi + + # Have to unlink and remove directories in reverse order. + # Checks allow to finish takedown after error. + + if [ "$(cat ${g_cdc}/UDC)" != "" ]; then + echo "" > ${g_cdc}/UDC + fi + rm -f ${g_cdc}/configs/c.1/ncm.usb0 + [ -d ${g_cdc}/functions/ncm.usb0 ] && rmdir ${g_cdc}/functions/ncm.usb0 + [ -d ${g_cdc}/configs/c.1/strings/0x409 ] && rmdir ${g_cdc}/configs/c.1/strings/0x409 + [ -d ${g_cdc}/configs/c.1 ] && rmdir ${g_cdc}/configs/c.1 + [ -d ${g_cdc}/strings/0x409 ] && rmdir ${g_cdc}/strings/0x409 + rmdir ${g_cdc} + + rm -f ${UDHCPCONF} + + if [ -n "$verbose" ]; then echo "Done."; fi +} + + + +g_mtp="/sys/kernel/config/usb_gadget/mtp" + +prepare_usb_mtp() { + usb_ver="0x0200" # USB 2.0 + dev_class="2" # Communications + attr="0xC0" # Self powered + pwr="0xfe" # + + mkdir ${g_mtp} + echo "${usb_ver}" > ${g_mtp}/bcdUSB + echo "${dev_class}" > ${g_mtp}/bDeviceClass + echo "0x1d6b" > ${g_mtp}/idVendor + echo "0x0104" > ${g_mtp}/idProduct + echo "${devversion}" > ${g_mtp}/bcdDevice + mkdir ${g_mtp}/strings/0x409 + echo "${OS_NAME}" > ${g_mtp}/strings/0x409/manufacturer + echo "${QUIRK_DEVICE}" > ${g_mtp}/strings/0x409/product + echo "${SERIAL}" > ${g_mtp}/strings/0x409/serialnumber + + # config 1 for MTP + mkdir ${g_mtp}/configs/c.1 + echo "${attr}" > ${g_mtp}/configs/c.1/bmAttributes + echo "${pwr}" > ${g_mtp}/configs/c.1/MaxPower + mkdir ${g_mtp}/configs/c.1/strings/0x409 + echo mtp > ${g_mtp}/configs/c.1/strings/0x409/configuration + + mkdir ${g_mtp}/functions/ffs.mtp + ln -s ${g_mtp}/functions/ffs.mtp ${g_mtp}/configs/c.1 +} + +cleanup_usb_mtp() { + rm -f \ + ${g_mtp}/configs/c.1/ffs.mtp + + rmdir \ + ${g_mtp}/configs/c.1/strings/0x409 \ + ${g_mtp}/configs/c.1 \ + ${g_mtp}/functions/ffs.mtp \ + ${g_mtp}/strings/0x409 \ + ${g_mtp} +} + +set_role() { + for sw in $(ls -1 /sys/class/udc/${UDC_NAME}/device/usb_role/*/role 2>/dev/null); do + if [ "$verbose" -gt "0" ]; then echo "swithing usb role to $1: $sw"; fi + echo $1 > $sw + done +} + +# USB_MODE is how the gadget was last configured (got from state file) +# CURRENT_MODE is USB gadget subsystem state -- which gadget has UDC +# $1 is desired mode, passed by caller +usb_start() { + if [ "$verbose" -gt "0" ];then echo "STORED=${USB_MODE}, CURRENT=${CURRENT_MODE}, DESIRED=$1"; fi + + # Exit with error if this UDC has a downstream device. Applies to RK3326 where we use a single port + # Switching to device mode in this case would break USB Wifi and USB gamepad + grep -q configured /sys/class/udc/${UDC_NAME}/device/usb1/1-0\:1.0/usb1-port1/state 2>/dev/null && exit 3 + + # with no argument setup previous mode + [[ -n "$1" ]] && USB_MODE=$1 + + # Avoid double start + if [ "${CURRENT_MODE}" == "${USB_MODE}" ]; then + if [ "$verbose" -gt "0" ]; then echo "Already in target mode: ${CURRENT_MODE}; skip"; fi + return + fi + + # This will reset both UDC and userspace when needed + if [ "${CURRENT_MODE}" != "disabled" ]; then + if [ "$verbose" -gt "0" ]; then echo "Stopping previous mode: ${CURRENT_MODE}"; fi + usb_stop + fi + + if [ "${USB_MODE}" == "disabled" ]; then + usb_disable + set_role host + return + else + set_role device + fi + + if [ "${USB_MODE}" = mtp ] ; then + if [ ! -d "${g_mtp}" ]; then + echo "MTP gadget not configured. Run '$0 prepare' first!" >&2 + exit 3 + fi + + mkdir /dev/ffs-umtp + mount mtp -t functionfs /dev/ffs-umtp + /usr/sbin/umtprd & + sleep 1 + + elif [ "${USB_MODE}" = cdc ] ; then + if [ ! -d "${g_cdc}" ]; then + echo "CDC gadget not configured. Run '$0 prepare' first!" >&2 + exit 3 + fi + else + exit 0 + fi + + # Enable selected mode + echo "${UDC_NAME}" > /sys/kernel/config/usb_gadget/${USB_MODE}/UDC + echo "USB_MODE=${USB_MODE}" > ${GADGETCONF} + + [[ "${USB_MODE}" == "cdc" ]] && configure_iface + + # For RK3566 we need to perform a soft disconnect when cable is not plugged + # This leaves network interface available for configuration, and will be re-connected later by udev + usb_trigger async +} + +usb_stop() { + # If there is a role switch, switch to host mode + set_role host + + ( + if [ -f ${UDHCPPIDFILE} ] ; then + cat ${UDHCPPIDFILE} | xargs -r -n 1 kill + fi + + usb_disable + + if [ -d /dev/ffs-umtp ] ; then + umount /dev/ffs-umtp + rmdir /dev/ffs-umtp + + killall umtprd + fi + ) >/dev/null 2>&1 +} + +set_usb_mode() { + case "${1}" in + cdc|mtp) + usb_start "${1}" + ;; + *) + usb_stop + ;; + esac +} + +case "$1" in + prepare) + prepare_usb_network + prepare_usb_mtp + ;; + cleanup) + cleanup_usb_network + cleanup_usb_mtp + ;; + start) + usb_start $2 + ;; + stop) + usb_stop + ;; + trigger) + usb_trigger + ;; + restart) + usb_stop + usb_start $2 + ;; + is_cable_connected) + is_cable_connected + ;; + + # + # API inspired by gpudriver + # + "--options") + echo "disabled network file_transfer" + ;; + "--start") + prepare_usb_network + prepare_usb_mtp + set_usb_mode "${USB_MODE}" + ;; + "") + case ${CURRENT_MODE} in + "cdc") echo "network"; ;; + "mtp") echo "file_transfer"; ;; + *) echo "disabled"; ;; + esac + ;; + "disabled") + usb_stop + ;; + "network") + usb_start cdc + ;; + "file_transfer") + usb_start mtp + ;; + "address") + . ${GADGETNETCONF} + echo ${IP} + ;; + *) + echo "Usage:" + echo "$0 --options List available modes" + echo "$0 --start Restore previously chosen mode" + echo "$0 Show current mode" + echo "$0 disabled Disable USB gadget" + echo "$0 Activate specified mode" + echo "$0 address Show network gadget IP address" + + echo "Deprecated usage: usbgadget [prepare|start|trigger|stop|restart|cleanup|address]" + ;; +esac + + + +# Benchmarks performed by @stolen with RK3326 Linux 6.11.9 as gadget and Linux 6.8.0 as host: +# +# Conditions: +# * performance governor: `echo performance | tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor` +# * server on gadget: `socat -b 4194304 /dev/null,ignoreeof tcp-listen:2003,fork,reuseaddr` +# * client on host: `dd if=/dev/urandom bs=1M status=progress | nc 10.1.1.2 2003` +# * switch NCM to direct mode: `brctl delif usbnet usb0; ip ad de 10.1.1.2/24 dev usbnet; ip ad ad 10.1.1.2/24 dev usb0` +# * back to bridge mode (restart): `usbgadget cleanup; usbgadget prepare; usbgadget start cdc` +# * switch to rndis: `sudo usb_modeswitch -v 1d6b -p 0104 -u 2` +# * top delay 10 seconds +# +# Measurements: +# * speed: as reported by dd after 90 seconds +# * socat: socat '%CPU' as reported by top +# * idle: total idle as reported by top in '%Cpu(s):' line +# * utilization (after '->'): `(100 - idle) * 4` +# * hidden: `utilization - socat` +# +# Results: +# * NCM direct: speed 30.3, socat 30.8%, idle 77.7% (x4) -> 89.2% (58.4% hidden) +# * NCM bridge: speed 30.4, socat 34.1%, idle 75.5% (x4) -> 98.0% (63.9% hidden) +# * RNDIS direct: speed 35.0, socat 80.3%, idle 55.7% (x4) -> 177.2% (96.9% hidden) +# * RNDIS bridge: speed 34.9, socat 80.2%, idle 54.9% (x4) -> 180.4% (100.2% hidden) +# +# With extra actions to increase MTU (9000 for RNDIS, 7986 for NCM): +# * NCM bridge : speed 35.7, socat 18.7%, idle 82.0% (x4) -> 72.0% (53.3% hidden) +# * NCM direct : speed 36.0, socat 17.5%, idle 83.1% (x4) -> 67.6% (50.1% hidden) +# * RNDIS direct: speed 36.0, socat 25.1%, idle 83.4% (x4) -> 66.4% (41.3% hidden) +# +# High MTU needs more research to announce, so host side sets it on connect without user intervention (via DHCP?) +# See `max_segment_size` for increasing possible MTU on NCM link diff --git a/projects/ArchR/packages/archr/sources/scripts/vertical-check b/projects/ArchR/packages/archr/sources/scripts/vertical-check new file mode 100644 index 0000000000..14f4175576 --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/vertical-check @@ -0,0 +1,84 @@ +#!/bin/sh + +. /etc/profile + +ARCADEROMS_XML="/usr/config/emulationstation/resources/arcaderoms.xml" + +RUNEMU_LINE=$(ps aux | grep '[r]unemu.sh' | head -n 1) +CURRENT_CORE=$(echo "${RUNEMU_LINE}" | sed -n 's/.*--core=\([^ ]*\).*/\1/p') +ROM_PATH=$(echo "${RUNEMU_LINE}" | sed -n 's|.*runemu\.sh \([^ ]*\).*|\1|p') + +if [ -z "${CURRENT_CORE}" ] || [ -z "${ROM_PATH}" ]; then + exit 0 +fi + +ROM_NAME=$(basename "${ROM_PATH}" | sed 's/\.[^.]*$//') +IS_VERTICAL=false + +case "${CURRENT_CORE}" in + # Unconditionally vertical + melonds*|desmume|vecx) + IS_VERTICAL=true + ;; + # Might not be vertical + mame*|fbneo|fbalpha*) + if grep -q "id=\"${ROM_NAME}\"[^>]*vert=\"true\"" "${ARCADEROMS_XML}" 2>/dev/null; then + IS_VERTICAL=true + fi + ;; +esac + +case "${ROM_NAME}" in + # Also check for some specific roms that aren't marked vert + punchout*|spnchout*|pc_*|mp_*) + IS_VERTICAL=true + ;; +esac + +if [ "${IS_VERTICAL}" = "true" ]; then + if [ "${QUIRK_DEVICE}" = "AYN Thor" ]; then + # Needs two separate swaymsg calls. Screen cannot move and have windows moved to it in the same line. + swaymsg '[title="RetroArch.*"] output DSI-2 pos 0 0, output DSI-1 pos 340 1080' + swaymsg '[title="RetroArch.*"] floating enable, fullscreen disable, resize set 1240 2160, move to output DSI-2, move absolute position 340 0' + # Additionally fix touch mapping for vertical stack. + swaymsg input "0:0:generic_ft5x06_(8d)" map_to_output DSI-1 + swaymsg -- input "0:0:generic_ft5x06_(8d)" calibration_matrix 0 -1 1 1 0 0 + elif [ "${QUIRK_DEVICE}" = "Anbernic RG DS" ]; then + # Same notes from above apply here. + swaymsg '[title="RetroArch.*"] output DSI-2 pos 0 0, output DSI-1 power on pos 0 480' + swaymsg '[title="RetroArch.*"] floating enable, fullscreen disable, resize set 640 960, move to output DSI-2, move absolute position 0 0' + swaymsg 'input "1046:911:Goodix_Capacitive_TouchScreen" calibration_matrix 1 0 0 0 0.5 0.5' + elif [ "${QUIRK_DEVICE}" = "AYANEO Pocket DS" ]; then + swaymsg output DSI-1 scale 1.40 + swaymsg output DSI-2 transform 270 + swaymsg '[title="RetroArch.*"] output DSI-1 pos 0 0, output DSI-2 power on pos 160 776' + swaymsg '[title="RetroArch.*"] floating enable, fullscreen disable, resize set 1024 1544, move to output DSI-1, move absolute position 160 0' + elif [[ "${QUIRK_DEVICE}" == "Retroid Pocket 5" || "${QUIRK_DEVICE}" == "Retroid Pocket Flip2" || "${QUIRK_DEVICE}" == "Retroid Pocket Mini" || "${QUIRK_DEVICE}" == "Retroid Pocket Mini V2" ]]; then + case "${QUIRK_DEVICE}" in + "Retroid Pocket 5" | "Retroid Pocket Flip2") + DSI_X="0" + RA_WIDTH="1920" + RA_HEIGHT="2160" # 1080 + 1080 + ;; + "Retroid Pocket Mini") + DSI_X="340" + RA_WIDTH="1240" + RA_HEIGHT="2010" # 1080 + 930 + ;; + "Retroid Pocket Mini V2") + DSI_X="340" + RA_WIDTH="1240" + RA_HEIGHT="2160" # 1080 + 1080 + ;; + esac + + # Setup vertical stack using external DP-1 as the top screen. + swaymsg "[title=\"RetroArch.*\"] output DP-1 pos 0 0, output DSI-1 pos ${DSI_X} 1080" + swaymsg "[title=\"RetroArch.*\"] floating enable, fullscreen disable, resize set ${RA_WIDTH} ${RA_HEIGHT}, move to output DP-1, move absolute position ${DSI_X} 0" + + swaymsg input "0:0:generic_ft5x06_(a0)" map_to_output DSI-1 + swaymsg input "0:0:generic_ft5x06_(a0)" events enabled + swaymsg input "0:0:generic_ft5x06_(8d)" map_to_output DSI-1 + swaymsg input "0:0:generic_ft5x06_(8d)" events enabled + fi +fi \ No newline at end of file diff --git a/projects/ArchR/packages/archr/sources/scripts/volume b/projects/ArchR/packages/archr/sources/scripts/volume new file mode 100755 index 0000000000..5a7bd9c708 --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/volume @@ -0,0 +1,43 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + + +# Source minimal predefined functions and variables +# to ensure as much performance as possible. +. /etc/profile.d/001-functions + +VOLUME=$(get_setting "audio.volume") +MAX_VOLUME=100 +MIN_VOLUME=0 +STEP=5 + +case ${1} in + "+"|"up") + VOLUME=$(( ${VOLUME} + ${STEP} )) + ;; + "-"|"down") + VOLUME=$(( ${VOLUME} - ${STEP} )) + ;; + "restore") + true + ;; + *) + VOLUME=${1} + ;; +esac + +if (( ${VOLUME} < ${MIN_VOLUME} )) +then + VOLUME=${MIN_VOLUME} +elif (( ${VOLUME} > ${MAX_VOLUME} )) +then + VOLUME=${MAX_VOLUME} +elif [ -z "${VOLUME}" ] +then + VOLUME=50 +fi + +pactl -- set-sink-volume @DEFAULT_SINK@ ${VOLUME}% +set_setting "audio.volume" ${VOLUME} diff --git a/projects/ArchR/packages/archr/sources/scripts/wifictl b/projects/ArchR/packages/archr/sources/scripts/wifictl new file mode 100755 index 0000000000..f5ccfeb71e --- /dev/null +++ b/projects/ArchR/packages/archr/sources/scripts/wifictl @@ -0,0 +1,176 @@ +#!/bin/bash +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) +# Copyright (C) 2022 kkoshelev (https://github.com/kkoshelev) +# Refactored for iwd (including AP mode) +# Symlink management added for read-only root filesystems. + +. /etc/profile + +### +### Basic WIFI properties used across the tool. +### +### Usage: +### wifictl command [ssid] [psk] +### + +IWD_AP_CFG_DIR="/storage/.cache/iwd/ap" +WIFI_TYPE=$(get_setting wifi.adhoc.enabled) +NETWORK_ADDRESS="192.168.80" +ADHOC_CLIENT_ID=$(get_setting wifi.adhoc.id) +# Detect any wireless interface (wlan*, wlx*, wlp*) +WIFI_DEV="$(ls /sys/class/net | grep -m1 '^wl')" +DEFAULT_CHAN="6" + +# Exit the script if the WiFi device isn't available +[ -z "${WIFI_DEV}" ] && exit 0 +[ ! -d "/sys/class/net/${WIFI_DEV}" ] && exit 0 + +SSID="${2:-$(get_setting wifi.ssid 2>/dev/null)}" +PSK="${3:-$(get_setting wifi.key 2>/dev/null)}" +COUNTRY="${4:-$(get_setting wifi.country | tr -d '[:space:]' 2>/dev/null)}" + +if [ "${WIFI_TYPE}" = "1" ]; then + SSID="NETPLAY_AP" + PSK="deadbeef" +fi + +ADHOC_CHAN=$(get_setting wifi.adhoc.channel) +if [ -z "${ADHOC_CHAN}" ]; then + ADHOC_CHAN="${DEFAULT_CHAN}" + set_setting wifi.adhoc.channel ${DEFAULT_CHAN} +fi + +### +### Functions... +### + +# Wait for iwd to start and have a device available +wait_for_wifi() { + for i in $(seq 1 15); do + iwctl device list 2>/dev/null | grep -q "${WIFI_DEV}" && break + sleep 1 + done + [ -n "${COUNTRY}" ] && iw reg set "${COUNTRY}" 2>/dev/null +} + +# lists all wifi networks +list_wifi() { + wait_for_wifi + /usr/bin/iwd_get-networks +} + +connect_wifi() { + wait_for_wifi + + iwctl device ${WIFI_DEV} set-property Mode station 2>/dev/null + sleep 1 + + # Create iwd network profile for persistent connection + IWD_DIR="/storage/.cache/iwd" + mkdir -p "${IWD_DIR}" + if [ -n "${PSK}" ]; then + printf '[Security]\nPassphrase=%s\n' "${PSK}" > "${IWD_DIR}/${SSID}.psk" + else + printf '[Security]\n' > "${IWD_DIR}/${SSID}.open" + fi + + # Scan and connect + iwctl station ${WIFI_DEV} scan 2>/dev/null + sleep 2 + iwctl station ${WIFI_DEV} connect "${SSID}" 2>/dev/null + + # Wait for connection + for i in $(seq 1 15); do + STATE=$(iwctl station ${WIFI_DEV} show 2>/dev/null | grep -i "state" | awk '{print $NF}') + [ "${STATE}" = "connected" ] && return 0 + sleep 1 + done + return 1 +} + +create_adhoc() { + wait_for_wifi + + # Create an iwd AP profile file + cat <"${IWD_AP_CFG_DIR}/${SSID}.ap" +[General] +Channel=${ADHOC_CHAN} +DisableHT=true + +[Security] +Passphrase=${PSK} + +[IPv4] +Address=${NETWORK_ADDRESS}.${ADHOC_CLIENT_ID} +Netmask=255.255.255.0 +Gateway=${NETWORK_ADDRESS}.${ADHOC_CLIENT_ID} +EOF + + iwctl device ${WIFI_DEV} set-property Mode ap + # Start the AP profile + iwctl ap ${WIFI_DEV} start-profile "${SSID}" 2>/dev/null +} + +destroy_adhoc() { + iwctl ap ${WIFI_DEV} stop 2>/dev/null + rm -f "${IWD_AP_CFG_DIR}/${SSID}.ap" 2>/dev/null +} + +has_ap_mode() { + wait_for_wifi + + PHY=$(basename "$(readlink /sys/class/net/${WIFI_DEV}/phy80211)") + if iwctl adapter "$PHY" show | grep -q 'SupportedModes.*ap'; then + exit 0 + else + exit 1 + fi +} + +case "${1}" in + enable) + rfkill unblock wifi + ;; + disable) + rfkill block wifi + ;; + connect) + if [ "${WIFI_TYPE}" = "1" ] && \ + [ "${ADHOC_CLIENT_ID}" = "1" ]; then + create_adhoc >/dev/null 2>&1 + else + destroy_adhoc >/dev/null 2>&1 + connect_wifi + fi + ;; + disconnect) + if [ "${WIFI_TYPE}" = "1" ]; then + destroy_adhoc >/dev/null 2>&1 + iwctl ap ${WIFI_DEV} stop 2>/dev/null + else + iwctl station ${WIFI_DEV} disconnect 2>/dev/null + fi + ;; + reconnect) + /usr/bin/wifictl disconnect + /usr/bin/wifictl connect + ;; + list) + list_wifi + ;; + channels) + iw list | awk '/[0-9] MHz \[/ && ! /disabled|radar|no IR/ { gsub(/^.*\[/,""); gsub(/\].*$/,""); print}' + ;; + has_ap_mode) + has_ap_mode + ;; + scan) + iwctl station ${WIFI_DEV} scan 2>/dev/null + ;; + scanlist) + iwctl station ${WIFI_DEV} scan 2>/dev/null + sleep 2 + list_wifi + ;; +esac diff --git a/projects/ArchR/packages/archr/system.d/archr-automount.service b/projects/ArchR/packages/archr/system.d/archr-automount.service new file mode 100644 index 0000000000..9e1df19286 --- /dev/null +++ b/projects/ArchR/packages/archr/system.d/archr-automount.service @@ -0,0 +1,15 @@ +[Unit] +Description=ArchR user autostart script +Before=autostart.service +After=systemd-tmpfiles-setup.service +RequiresMountsFor=/storage + +[Service] +Type=oneshot +Environment=HOME=/storage +EnvironmentFile=/etc/profile +ExecStart=/usr/bin/automount +RemainAfterExit=yes + +[Install] +WantedBy=archr.target diff --git a/projects/ArchR/packages/archr/system.d/archr-memory-manager.service b/projects/ArchR/packages/archr/system.d/archr-memory-manager.service new file mode 100644 index 0000000000..e8a38f66e2 --- /dev/null +++ b/projects/ArchR/packages/archr/system.d/archr-memory-manager.service @@ -0,0 +1,17 @@ +[Unit] +Description=ArchR Memory Manager +After=local-fs.target +DefaultDependencies=no +Conflicts=shutdown.target +Before=shutdown.target + +[Service] +Environment=HOME=/storage +Type=oneshot +ExecStart=/usr/bin/archr-memory-manager --setup +ExecReload=/usr/bin/archr-memory-manager --reload +ExecStop=/usr/bin/archr-memory-manager --stop +RemainAfterExit=yes + +[Install] +WantedBy=basic.target diff --git a/projects/ArchR/packages/archr/system.d/archr-report-stats.service b/projects/ArchR/packages/archr/system.d/archr-report-stats.service new file mode 100644 index 0000000000..b11faf971b --- /dev/null +++ b/projects/ArchR/packages/archr/system.d/archr-report-stats.service @@ -0,0 +1,9 @@ +[Unit] +Description=Report anonymous ArchR install statistics + +[Service] +Type=oneshot +ExecStart=/usr/bin/archr-report-stats + +[Install] +WantedBy=multi-user.target diff --git a/projects/ArchR/packages/archr/system.d/archr-report-stats.timer b/projects/ArchR/packages/archr/system.d/archr-report-stats.timer new file mode 100644 index 0000000000..b5fb640adf --- /dev/null +++ b/projects/ArchR/packages/archr/system.d/archr-report-stats.timer @@ -0,0 +1,9 @@ +[Unit] +Description=Timer to report anonymous ArchR install statistics +ConditionPathExists=/storage/.cache/services/stats.enabled + +[Timer] +OnBootSec=5min + +[Install] +WantedBy=timers.target diff --git a/projects/ArchR/packages/archr/system.d/archr.target b/projects/ArchR/packages/archr/system.d/archr.target new file mode 100644 index 0000000000..faa1c1d603 --- /dev/null +++ b/projects/ArchR/packages/archr/system.d/archr.target @@ -0,0 +1,9 @@ +[Unit] +Description=archr +Requires=multi-user.target graphical.target +After=graphical.target +Conflicts=rescue.target +AllowIsolate=yes + +[Install] +Alias=default.target diff --git a/projects/ArchR/packages/archr/system.d/bluetooth-agent.service b/projects/ArchR/packages/archr/system.d/bluetooth-agent.service new file mode 100644 index 0000000000..1405e50c2b --- /dev/null +++ b/projects/ArchR/packages/archr/system.d/bluetooth-agent.service @@ -0,0 +1,13 @@ +[Unit] +Description=Start bluetooth agent +After=bluetooth.service +PartOf=bluetooth.service + +[Service] +Type=simple +ExecStart=/usr/bin/archr-bluetooth-agent +Restart=on-failure +RestartSec=5 + +[Install] +WantedBy=bluetooth.service diff --git a/projects/ArchR/packages/archr/system.d/hdmi-hotplug.path b/projects/ArchR/packages/archr/system.d/hdmi-hotplug.path new file mode 100644 index 0000000000..183229ed26 --- /dev/null +++ b/projects/ArchR/packages/archr/system.d/hdmi-hotplug.path @@ -0,0 +1,8 @@ +[Unit] +Description=Monitor HDMI status + +[Path] +PathModified=/run/hdmi-status.last + +[Install] +WantedBy=multi-user.target diff --git a/projects/ArchR/packages/archr/system.d/hdmi-hotplug.service b/projects/ArchR/packages/archr/system.d/hdmi-hotplug.service new file mode 100644 index 0000000000..e9a7c32eaa --- /dev/null +++ b/projects/ArchR/packages/archr/system.d/hdmi-hotplug.service @@ -0,0 +1,6 @@ +[Unit] +Description=Handle HDMI hotplug +[Service] +ExecStartPre=/bin/sleep 1 +ExecStart=/usr/bin/handle-hdmi-hotplug +Type=oneshot diff --git a/projects/ArchR/packages/archr/system.d/save-sysconfig.service b/projects/ArchR/packages/archr/system.d/save-sysconfig.service new file mode 100644 index 0000000000..6c27eca17e --- /dev/null +++ b/projects/ArchR/packages/archr/system.d/save-sysconfig.service @@ -0,0 +1,13 @@ +[Unit] +Description=Back up the system config before shutting down +RequiresMountsFor=/storage +DefaultDependencies=no +Before=shutdown.target + +[Service] +Type=oneshot +ExecStart=/usr/bin/chksysconfig backup +TimeoutStartSec=0 + +[Install] +WantedBy=shutdown.target diff --git a/projects/ArchR/packages/archr/system.d/timers.target.wants/rocknix-report-stats.timer b/projects/ArchR/packages/archr/system.d/timers.target.wants/rocknix-report-stats.timer new file mode 120000 index 0000000000..4ae66d6f74 --- /dev/null +++ b/projects/ArchR/packages/archr/system.d/timers.target.wants/rocknix-report-stats.timer @@ -0,0 +1 @@ +../rocknix-report-stats.timer \ No newline at end of file diff --git a/projects/ArchR/packages/archr/udev.d/80-usbgadget.rules b/projects/ArchR/packages/archr/udev.d/80-usbgadget.rules new file mode 100644 index 0000000000..f9e5505bf1 --- /dev/null +++ b/projects/ArchR/packages/archr/udev.d/80-usbgadget.rules @@ -0,0 +1,4 @@ +# trigger for activating gadget after cable is plugged +SUBSYSTEMS=="extcon", ACTION=="change", RUN+="/usr/bin/usbgadget trigger" +# rename gadget interface to avoid ES displaying connected state +ACTION=="add", SUBSYSTEM=="net", ENV{DEVTYPE}=="gadget", NAME="gadget" diff --git a/projects/ArchR/packages/audio/SDL2_mixer/package.mk b/projects/ArchR/packages/audio/SDL2_mixer/package.mk new file mode 100644 index 0000000000..ff0b651519 --- /dev/null +++ b/projects/ArchR/packages/audio/SDL2_mixer/package.mk @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="SDL2_mixer" +PKG_VERSION="2.8.0" +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 fluidsynth opusfile alsa-lib SDL2 libogg libvorbis flac mpg123 libmodplug wavpack libxmp" +PKG_LONGDESC="SDL2 mixer" + +pre_configure_target() { + PKG_CONFIGURE_OPTS_TARGET="${PKG_CONFIGURE_OPTS_TARGET} --enable-music-mp3" +} diff --git a/projects/ArchR/packages/audio/alsa-lib/modprobe.d/alsa-base.conf b/projects/ArchR/packages/audio/alsa-lib/modprobe.d/alsa-base.conf new file mode 100644 index 0000000000..ee4bf79015 --- /dev/null +++ b/projects/ArchR/packages/audio/alsa-lib/modprobe.d/alsa-base.conf @@ -0,0 +1,25 @@ +############################# +# ALSA drivers load options # +############################# + +options snd cards_limit=3 + +# Prevent abnormal drivers from grabbing index 0 +options snd-hda-intel index=1 + +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-usx2y index=-2 +options snd-usb-caiaq index=-2 +options snd-cmipci mpu_port=0x330 fm_port=0x388 + +options snd-hda-codec-realtek index=-2 +options snd-hda-codec-hdmi index=-2 + +# 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/projects/ArchR/packages/audio/alsa-lib/modprobe.d/intel-audio.conf b/projects/ArchR/packages/audio/alsa-lib/modprobe.d/intel-audio.conf new file mode 100644 index 0000000000..d3198ed205 --- /dev/null +++ b/projects/ArchR/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/projects/ArchR/packages/audio/alsa-lib/package.mk b/projects/ArchR/packages/audio/alsa-lib/package.mk new file mode 100644 index 0000000000..7649fd03ee --- /dev/null +++ b/projects/ArchR/packages/audio/alsa-lib/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) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="alsa-lib" +PKG_VERSION="1.2.14" +PKG_LICENSE="GPL" +PKG_SITE="http://www.alsa-project.org/" +PKG_URL="https://www.alsa-project.org/files/pub/lib/alsa-lib-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain alsa-ucm-conf alsa-topology-conf" +PKG_LONGDESC="ALSA (Advanced Linux Sound Architecture) is the next generation Linux Sound API." +PKG_TOOLCHAIN="autotools" +PKG_BUILD_FLAGS="+pic" +PKG_PATCH_DIRS+=" ${DEVICE}" + +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 +} + diff --git a/projects/ArchR/packages/audio/alsa-lib/patches/001-silence-underruns.patch b/projects/ArchR/packages/audio/alsa-lib/patches/001-silence-underruns.patch new file mode 100644 index 0000000000..bf4253550c --- /dev/null +++ b/projects/ArchR/packages/audio/alsa-lib/patches/001-silence-underruns.patch @@ -0,0 +1,14 @@ +diff -rupN alsa-lib-1.2.8.orig/src/pcm/pcm.c alsa-lib-1.2.8/src/pcm/pcm.c +--- alsa-lib-1.2.8.orig/src/pcm/pcm.c 2023-02-08 15:16:54.463152310 -0500 ++++ alsa-lib-1.2.8/src/pcm/pcm.c 2023-02-08 15:17:08.347091741 -0500 +@@ -8566,8 +8566,8 @@ int snd_pcm_recover(snd_pcm_t *pcm, int + s = "underrun"; + else + s = "overrun"; +- if (!silent) +- SNDERR("%s occurred", s); ++ //if (!silent) ++ // SNDERR("%s occurred", s); + err = snd_pcm_prepare(pcm); + if (err < 0) { + SNDERR("cannot recovery from %s, prepare failed: %s", s, snd_strerror(err)); diff --git a/projects/ArchR/packages/audio/alsa-lib/patches/SM8250/0001-Enabled-extended-namehints-in-alsa.conf.patch b/projects/ArchR/packages/audio/alsa-lib/patches/SM8250/0001-Enabled-extended-namehints-in-alsa.conf.patch new file mode 100644 index 0000000000..aeba6d016f --- /dev/null +++ b/projects/ArchR/packages/audio/alsa-lib/patches/SM8250/0001-Enabled-extended-namehints-in-alsa.conf.patch @@ -0,0 +1,27 @@ +From 80965d8afd3241017b7dde8dcbd56ab2fd879973 Mon Sep 17 00:00:00 2001 +From: Elimar Riesebieter +Date: Wed, 11 Jan 2017 16:16:14 +0100 +Subject: [PATCH] Enabled extended namehints in alsa.conf + +--- + src/conf/alsa.conf | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +Index: alsa-lib/src/conf/alsa.conf +=================================================================== +--- alsa-lib.orig/src/conf/alsa.conf ++++ alsa-lib/src/conf/alsa.conf +@@ -53,11 +53,11 @@ cards.@hooks [ + # + + # show all name hints also for definitions without hint {} section +-defaults.namehint.showall off ++defaults.namehint.showall on + # show just basic name hints + defaults.namehint.basic on + # show extended name hints +-defaults.namehint.extended off ++defaults.namehint.extended on + # + defaults.ctl.card 0 + defaults.pcm.card 0 diff --git a/projects/ArchR/packages/audio/alsa-lib/patches/SM8550/0001-Enabled-extended-namehints-in-alsa.conf.patch b/projects/ArchR/packages/audio/alsa-lib/patches/SM8550/0001-Enabled-extended-namehints-in-alsa.conf.patch new file mode 100644 index 0000000000..aeba6d016f --- /dev/null +++ b/projects/ArchR/packages/audio/alsa-lib/patches/SM8550/0001-Enabled-extended-namehints-in-alsa.conf.patch @@ -0,0 +1,27 @@ +From 80965d8afd3241017b7dde8dcbd56ab2fd879973 Mon Sep 17 00:00:00 2001 +From: Elimar Riesebieter +Date: Wed, 11 Jan 2017 16:16:14 +0100 +Subject: [PATCH] Enabled extended namehints in alsa.conf + +--- + src/conf/alsa.conf | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +Index: alsa-lib/src/conf/alsa.conf +=================================================================== +--- alsa-lib.orig/src/conf/alsa.conf ++++ alsa-lib/src/conf/alsa.conf +@@ -53,11 +53,11 @@ cards.@hooks [ + # + + # show all name hints also for definitions without hint {} section +-defaults.namehint.showall off ++defaults.namehint.showall on + # show just basic name hints + defaults.namehint.basic on + # show extended name hints +-defaults.namehint.extended off ++defaults.namehint.extended on + # + defaults.ctl.card 0 + defaults.pcm.card 0 diff --git a/projects/ArchR/packages/audio/alsa-lib/patches/alsa-lib-asound.conf_configdir.patch b/projects/ArchR/packages/audio/alsa-lib/patches/alsa-lib-asound.conf_configdir.patch new file mode 100644 index 0000000000..efe2f1ae7c --- /dev/null +++ b/projects/ArchR/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/projects/ArchR/packages/audio/alsa-ucm-conf/package.mk b/projects/ArchR/packages/audio/alsa-ucm-conf/package.mk new file mode 100644 index 0000000000..8f571a1dcc --- /dev/null +++ b/projects/ArchR/packages/audio/alsa-ucm-conf/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="alsa-ucm-conf" +PKG_VERSION="1.2.13" +PKG_LICENSE="BSD-3c" +PKG_SITE="http://www.alsa-project.org/" +PKG_URL="https://www.alsa-project.org/files/pub/lib/alsa-ucm-conf-${PKG_VERSION}.tar.bz2" +PKG_LONGDESC="ALSA Use Case Manager configuration (and topologies)" +PKG_TOOLCHAIN="manual" +PKG_PATCH_DIRS+=" ${DEVICE}" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/share/alsa/ + cp -PR ${PKG_BUILD}/ucm2 ${INSTALL}/usr/share/alsa/ + # work around scripts/build removing empty directories, this leads to errors in ucm + touch ${INSTALL}/usr/share/alsa/ucm2/conf.virt.d/.dont_remove_this_dir +} diff --git a/projects/ArchR/packages/audio/alsa-ucm-conf/patches/001-steamdeck.patch b/projects/ArchR/packages/audio/alsa-ucm-conf/patches/001-steamdeck.patch new file mode 100644 index 0000000000..1f232c2d06 --- /dev/null +++ b/projects/ArchR/packages/audio/alsa-ucm-conf/patches/001-steamdeck.patch @@ -0,0 +1,299 @@ +diff -rupN alsa-ucm-conf.orig/ucm2/conf.d/acp5x/acp5x.conf alsa-ucm-conf/ucm2/conf.d/acp5x/acp5x.conf +--- alsa-ucm-conf.orig/ucm2/conf.d/acp5x/acp5x.conf 1969-12-31 19:00:00.000000000 -0500 ++++ alsa-ucm-conf/ucm2/conf.d/acp5x/acp5x.conf 2023-01-15 22:05:57.605619272 -0500 +@@ -0,0 +1,17 @@ ++Syntax 2 ++ ++Comment "Vangogh internal card" ++ ++SectionUseCase."HiFi" { ++ If.upstream { ++ Condition { ++ Type ControlExists ++ Control "name='Left Analog PCM Volume'" ++ } ++ True.File "HiFi-upstream.conf" ++ False.File "HiFi.conf" ++ } ++ ++ Comment "Default" ++} ++ +diff -rupN alsa-ucm-conf.orig/ucm2/conf.d/acp5x/HiFi.conf alsa-ucm-conf/ucm2/conf.d/acp5x/HiFi.conf +--- alsa-ucm-conf.orig/ucm2/conf.d/acp5x/HiFi.conf 1969-12-31 19:00:00.000000000 -0500 ++++ alsa-ucm-conf/ucm2/conf.d/acp5x/HiFi.conf 2023-01-15 22:05:57.609619224 -0500 +@@ -0,0 +1,140 @@ ++SectionVerb { ++ Value { ++ FullySpecifiedUCM "1" ++ } ++ EnableSequence [ ++ cdev "hw:acp5x" ++ ++ exec "echo Main Verb Config EnableSequence" ++ ++ cset "name='Left DSP Booted' 0" ++ cset "name='Right DSP Booted' 0" ++ cset "name='Left DSP1 Preload Switch' 0" ++ cset "name='Right DSP1 Preload Switch' 0" ++ cset "name='Headphone Volume' 0" ++ cset "name='Digital Playback Volume' 207" ++ cset "name='Frontend PGA Volume' 27" ++ cset "name='ADC Phase Switch' 1" ++ cset "name='BIQ Coefficients' 0x03,0x5a,0x00,0x06,0xfc,0xac,0x00,0x00,0xfe,0x58,0x00,0x00,0x03,0x50,0x00,0x06,0xfe,0x58,0x00,0x08" ++ cset "name='Left AMP PCM Gain' 17" ++ cset "name='Right AMP PCM Gain' 17" ++ cset "name='Left Digital PCM Volume' 817" ++ cset "name='Right Digital PCM Volume' 817" ++ cset "name='Left ASPRX1 Slot Position' 0" ++ cset "name='Left ASPRX2 Slot Position' 1" ++ cset "name='Left DSP RX1 Source' ASPRX1" ++ cset "name='Left DSP RX2 Source' ASPRX1" ++ cset "name='Right ASPRX1 Slot Position' 0" ++ cset "name='Right ASPRX2 Slot Position' 1" ++ cset "name='Right DSP RX1 Source' ASPRX2" ++ cset "name='Right DSP RX2 Source' ASPRX2" ++ ++ cset "name='Left Boost Converter Enable' 2" ++ cset "name='Right DSP RX1 Source' 2" ++ cset "name='Left DSP RX2 Source' 1" ++ ] ++ DisableSequence [ ++ cdev "hw:acp5x" ++ ++ exec "echo Main Verb Config DisableSequence" ++ cset "name='Left DSP Booted' 0" ++ cset "name='Right DSP Booted' 0" ++ cset "name='Left DSP1 Preload Switch' 0" ++ cset "name='Right DSP1 Preload Switch' 0" ++ ] ++} ++ ++SectionDevice."Headphones".0 { ++ Comment "Headphones" ++ ++ Value { ++ PlaybackPriority 200 ++ PlaybackPCM "hw:acp5x,0" ++ JackControl "Headphone Jack" ++ } ++ ConflictingDevice [ ++ ] ++ EnableSequence [ ++ cdev "hw:acp5x" ++ exec "echo Headphones EnableSequence" ++ cset "name='Headphone Switch' on" ++ ] ++ DisableSequence [ ++ cdev "hw:acp5x" ++ exec "echo Headphones DisableSequence" ++ cset "name='Headphone Switch' off" ++ ] ++} ++ ++SectionDevice."Speaker".0 { ++ Comment "Speaker" ++ ++ Value { ++ PlaybackPriority 100 ++ PlaybackPCM "hw:acp5x,1" ++ } ++ ConflictingDevice [ ++ ] ++ EnableSequence [ ++ cdev "hw:acp5x" ++ exec "echo Speaker EnableSequence" ++ cset "name='Left DSP1 Preload Switch' 1" ++ cset "name='Right DSP1 Preload Switch' 1" ++ cset "name='Left AMP Enable Switch' on" ++ cset "name='Right AMP Enable Switch' on" ++ cset "name='Left PCM Source' DSP" ++ cset "name='Right PCM Source' DSP" ++ ] ++ DisableSequence [ ++ cdev "hw:acp5x" ++ exec "echo Speaker DisableSequence" ++ cset "name='Left AMP Enable Switch' off" ++ cset "name='Right AMP Enable Switch' off" ++ ] ++} ++ ++SectionDevice."Internal Mic".0 { ++ Comment "Internal Microphone" ++ ++ Value { ++ CapturePriority 200 ++ CapturePCM "hw:acp5x,0" ++ } ++ ConflictingDevice [ ++ "Headset" ++ ] ++ EnableSequence [ ++ cdev "hw:acp5x" ++ cset "name='Int Mic Switch' on" ++ cset "name='DMIC Enable Switch' on" ++ cset "name='Mic Volume' 252" ++ ] ++ DisableSequence [ ++ cdev "hw:acp5x" ++ cset "name='Int Mic Switch' off" ++ cset "name='DMIC Enable Switch' off" ++ ] ++} ++ ++SectionDevice."Headset" { ++ Comment "Headset Microphone" ++ ++ Value { ++ CapturePriority 300 ++ CapturePCM "hw:acp5x,0" ++ JackControl "Headset Mic Jack" ++ } ++ ConflictingDevice [ ++ "Internal Mic" ++ ] ++ EnableSequence [ ++ cdev "hw:acp5x" ++ cset "name='Headset Mic Switch' on" ++ cset "name='Mic Volume' 200" ++ ] ++ DisableSequence [ ++ cdev "hw:acp5x" ++ cset "name='Headset Mic Switch' off" ++ ] ++} ++ +diff -rupN alsa-ucm-conf.orig/ucm2/conf.d/acp5x/HiFi-upstream.conf alsa-ucm-conf/ucm2/conf.d/acp5x/HiFi-upstream.conf +--- alsa-ucm-conf.orig/ucm2/conf.d/acp5x/HiFi-upstream.conf 1969-12-31 19:00:00.000000000 -0500 ++++ alsa-ucm-conf/ucm2/conf.d/acp5x/HiFi-upstream.conf 2023-01-15 22:05:57.609619224 -0500 +@@ -0,0 +1,130 @@ ++SectionVerb { ++ Value { ++ FullySpecifiedUCM "1" ++ } ++ EnableSequence [ ++ cdev "hw:acp5x" ++ ++ exec "echo Main Verb Config EnableSequence" ++ ++ cset "name='Left DSP1 Preload Switch' 0" ++ cset "name='Right DSP1 Preload Switch' 0" ++ cset "name='Digital Playback Volume' 207" ++ cset "name='Headphone Volume' 0" ++ cset "name='Frontend PGA Volume' 27" ++ cset "name='ADC Phase Switch' 1" ++ cset "name='BIQ Coefficients' 0x03,0x5a,0x00,0x06,0xfc,0xac,0x00,0x00,0xfe,0x58,0x00,0x00,0x03,0x50,0x00,0x06,0xfe,0x58,0x00,0x08" ++ cset "name='Left Analog PCM Volume' 17" ++ cset "name='Right Analog PCM Volume' 17" ++ cset "name='Left Digital PCM Volume' 817" ++ cset "name='Right Digital PCM Volume' 817" ++ cset "name='Left DSP RX1 Source' ASPRX1" ++ cset "name='Left DSP RX2 Source' ASPRX1" ++ cset "name='Right DSP RX1 Source' ASPRX2" ++ cset "name='Right DSP RX2 Source' ASPRX2" ++ ++ cset "name='Right DSP RX1 Source' 2" ++ cset "name='Left DSP RX2 Source' 1" ++ ] ++ DisableSequence [ ++ cdev "hw:acp5x" ++ ++ exec "echo Main Verb Config DisableSequence" ++ cset "name='Left DSP Booted' 0" ++ cset "name='Right DSP Booted' 0" ++ cset "name='Left DSP1 Preload Switch' 0" ++ cset "name='Right DSP1 Preload Switch' 0" ++ ] ++} ++ ++SectionDevice."Headphones".0 { ++ Comment "Headphones" ++ ++ Value { ++ PlaybackPriority 200 ++ PlaybackPCM "hw:acp5x,0" ++ JackControl "Headphone Jack" ++ } ++ ConflictingDevice [ ++ ] ++ EnableSequence [ ++ cdev "hw:acp5x" ++ exec "echo Headphones EnableSequence" ++ cset "name='Headphone Switch' on" ++ ] ++ DisableSequence [ ++ cdev "hw:acp5x" ++ exec "echo Headphones DisableSequence" ++ cset "name='Headphone Switch' off" ++ ] ++} ++ ++SectionDevice."Speaker".0 { ++ Comment "Speaker" ++ ++ Value { ++ PlaybackPriority 100 ++ PlaybackPCM "hw:acp5x,1" ++ } ++ ConflictingDevice [ ++ ] ++ EnableSequence [ ++ cdev "hw:acp5x" ++ exec "echo Speaker EnableSequence" ++ cset "name='Left DSP1 Preload Switch' 1" ++ cset "name='Right DSP1 Preload Switch' 1" ++ cset "name='Left PCM Source' DSP" ++ cset "name='Right PCM Source' DSP" ++ ] ++ DisableSequence [ ++ cdev "hw:acp5x" ++ exec "echo Speaker DisableSequence" ++ cset "name='Left AMP Enable Switch' off" ++ cset "name='Right AMP Enable Switch' off" ++ ] ++} ++ ++SectionDevice."Internal Mic".0 { ++ Comment "Internal Microphone" ++ ++ Value { ++ CapturePriority 200 ++ CapturePCM "hw:acp5x,0" ++ } ++ ConflictingDevice [ ++ "Headset" ++ ] ++ EnableSequence [ ++ cdev "hw:acp5x" ++ cset "name='Int Mic Switch' on" ++ cset "name='DMIC Enable Switch' on" ++ cset "name='Mic Volume' 252" ++ ] ++ DisableSequence [ ++ cdev "hw:acp5x" ++ cset "name='Int Mic Switch' off" ++ cset "name='DMIC Enable Switch' off" ++ ] ++} ++ ++SectionDevice."Headset" { ++ Comment "Headset Microphone" ++ ++ Value { ++ CapturePriority 300 ++ CapturePCM "hw:acp5x,0" ++ JackControl "Headset Mic Jack" ++ } ++ ConflictingDevice [ ++ "Internal Mic" ++ ] ++ EnableSequence [ ++ cdev "hw:acp5x" ++ cset "name='Headset Mic Switch' on" ++ cset "name='Mic Volume' 200" ++ ] ++ DisableSequence [ ++ cdev "hw:acp5x" ++ cset "name='Headset Mic Switch' off" ++ ] ++} diff --git a/projects/ArchR/packages/audio/alsa-ucm-conf/patches/H700/0002_Add-Allwinner-H616-configuration.patch b/projects/ArchR/packages/audio/alsa-ucm-conf/patches/H700/0002_Add-Allwinner-H616-configuration.patch new file mode 100644 index 0000000000..f6b824464e --- /dev/null +++ b/projects/ArchR/packages/audio/alsa-ucm-conf/patches/H700/0002_Add-Allwinner-H616-configuration.patch @@ -0,0 +1,85 @@ +From eccc3536e12a86434ced1529fcad5bbbb280ffeb Mon Sep 17 00:00:00 2001 +From: Ryan Walklin +Date: Sat, 21 Dec 2024 23:01:14 +1300 +Subject: [PATCH] sun4i-codec: add routing for headphones and internal speaker + +The sun4i-codec kernel driver covers a large number of Allwinner SoCs. +The H616 codec has a single line-out route, which is used in concert +with a Toshiba mux chip to send audio to either an internal speaker or +headphone jack on a number of Anbernic handheld gaming devices. + +Add a UCM configuration to allow enabling/disabling the speaker amp +depending on whether headphones are in use or not. + +Signed-off-by: Ryan Walklin +--- + ucm2/Allwinner/sun4i-h616/HiFi.conf | 35 +++++++++++++++++++ + ucm2/conf.d/sun4i-codec/h616-audio-codec.conf | 8 +++++ + 2 files changed, 43 insertions(+) + create mode 100644 ucm2/Allwinner/sun4i-h616/HiFi.conf + create mode 100644 ucm2/conf.d/sun4i-codec/h616-audio-codec.conf + +diff --git a/ucm2/Allwinner/sun4i-h616/HiFi.conf b/ucm2/Allwinner/sun4i-h616/HiFi.conf +new file mode 100644 +index 00000000..2cb9a31f +--- /dev/null ++++ b/ucm2/Allwinner/sun4i-h616/HiFi.conf +@@ -0,0 +1,40 @@ ++SectionDevice."Speaker" { ++ Comment "Internal Speaker" ++ ++ EnableSequence [ ++ cset "name='DAC Playback Volume' 63" ++ cset "name='Speaker Switch' on" ++ ] ++ ++ Value { ++ PlaybackMixerElem "Line Out" ++ PlaybackPCM "hw:${CardId},0" ++ } ++ ++ DisableSequence [ ++ cset "name='Speaker Switch' off" ++ ] ++ ++ ConflictingDevice [ ++ "Headphones" ++ ] ++} ++ ++ ++SectionDevice."Headphones" { ++ Comment "Headphones" ++ ++ EnableSequence [ ++ cset "name='DAC Playback Volume' 63" ++ ] ++ ++ Value { ++ PlaybackMixerElem "Line Out" ++ PlaybackPCM "hw:${CardId},0" ++ JackControl "Headphone Jack" ++ } ++ ++ ConflictingDevice [ ++ "Speaker" ++ ] ++} +diff --git a/ucm2/conf.d/sun4i-codec/h616-audio-codec.conf b/ucm2/conf.d/sun4i-codec/h616-audio-codec.conf +new file mode 100644 +index 00000000..240f41ab +--- /dev/null ++++ b/ucm2/conf.d/sun4i-codec/h616-audio-codec.conf +@@ -0,0 +1,12 @@ ++# UCM for Allwinner H616 Codec ++ ++Syntax 3 ++ ++SectionUseCase."HiFi" { ++ File "/Allwinner/sun4i-h616/HiFi.conf" ++ Comment "Play HiFi quality Music" ++} ++ ++FixedBootSequence [ ++ cset "name='DAC Playback Switch' on" ++] diff --git a/projects/ArchR/packages/audio/alsa-ucm-conf/patches/RK3326/0001_fix_speaker_when_booting_with_headphones.patch b/projects/ArchR/packages/audio/alsa-ucm-conf/patches/RK3326/0001_fix_speaker_when_booting_with_headphones.patch new file mode 100644 index 0000000000..c163d7dc1c --- /dev/null +++ b/projects/ArchR/packages/audio/alsa-ucm-conf/patches/RK3326/0001_fix_speaker_when_booting_with_headphones.patch @@ -0,0 +1,13 @@ +--- a/ucm2/Rockchip/rk817-sound/HiFi.conf.orig 2025-12-16 23:07:38.584854260 +0000 ++++ b/ucm2/Rockchip/rk817-sound/HiFi.conf 2025-12-16 23:08:28.880964760 +0000 +@@ -15,6 +15,10 @@ + SectionDevice."Speaker".DisableSequence [ + cset "name='Internal Speakers Switch' off" + ] ++ ++ SectionDevice."Headphones".EnableSequence [ ++ cset "name='Internal Speakers Switch' off" ++ ] + } + } + diff --git a/projects/ArchR/packages/audio/alsa-ucm-conf/patches/SDM845/0001-Add-Odin-configuration.patch b/projects/ArchR/packages/audio/alsa-ucm-conf/patches/SDM845/0001-Add-Odin-configuration.patch new file mode 100755 index 0000000000..9184102e1e --- /dev/null +++ b/projects/ArchR/packages/audio/alsa-ucm-conf/patches/SDM845/0001-Add-Odin-configuration.patch @@ -0,0 +1,142 @@ +From 1839c307004f9608fa47bc305a524964a03bfaaa Mon Sep 17 00:00:00 2001 +From: Teguh Sobirin +Date: Thu, 30 Jun 2022 22:23:34 +0700 +Subject: [PATCH] Add Odin configuration + +--- + ucm2/Odin/HiFi.conf | 82 +++++++++++++++++++ + ucm2/Odin/Odin.conf | 6 ++ + .../AYNTechnologiesCo.Ltd.-OdinBase-odin.conf | 1 + + .../AYNTechnologiesCo.Ltd.-OdinPro-odin.conf | 1 + + 4 files changed, 90 insertions(+) + create mode 100644 ucm2/Odin/HiFi.conf + create mode 100644 ucm2/Odin/Odin.conf + create mode 120000 ucm2/conf.d/sdm845/AYNTechnologiesCo.Ltd.-OdinBase-odin.conf + create mode 120000 ucm2/conf.d/sdm845/AYNTechnologiesCo.Ltd.-OdinPro-odin.conf + +diff --git a/ucm2/Odin/HiFi.conf b/ucm2/Odin/HiFi.conf +new file mode 100644 +index 0000000..6e432c1 +--- /dev/null ++++ b/ucm2/Odin/HiFi.conf +@@ -0,0 +1,82 @@ ++SectionVerb { ++ ++ EnableSequence [ ++ cset "name='SLIMBUS_0_RX Audio Mixer MultiMedia1' 1" ++ cset "name='SLIM RX1 MUX' AIF1_PB" ++ cset "name='SLIM RX2 MUX' AIF1_PB" ++ cset "name='SLIM RX6 MUX' ZERO" ++ cset "name='SLIM RX7 MUX' ZERO" ++ cset "name='SLIM RX3 MUX' ZERO" ++ cset "name='SLIM RX4 MUX' ZERO" ++ cset "name='SLIM RX5 MUX' ZERO" ++ cset "name='AIF1_CAP Mixer SLIM TX0' 1" ++ cset "name='RX INT7_1 MIX1 INP0' RX1" ++ cset "name='RX INT8_1 MIX1 INP0' RX2" ++ cset "name='RX INT1_2 MUX' RX1" ++ cset "name='RX INT2_2 MUX' RX2" ++ cset "name='CDC_IF TX0 MUX' DEC0" ++ cset "name='SpkrLeft COMP Switch' 1" ++ cset "name='SpkrLeft BOOST Switch' 1" ++ cset "name='SpkrLeft DAC Switch' 1" ++ cset "name='SpkrLeft VISENSE Switch' 0" ++ cset "name='SpkrRight COMP Switch' 1" ++ cset "name='SpkrRight BOOST Switch' 1" ++ cset "name='SpkrRight DAC Switch' 1" ++ cset "name='SpkrRight VISENSE Switch' 0" ++ ] ++ ++ DisableSequence [ ++ cset "name='RX INT7_1 MIX1 INP0' ZERO" ++ cset "name='RX INT8_1 MIX1 INP0' ZERO" ++ cset "name='RX INT1_2 MUX' ZERO" ++ cset "name='RX INT2_2 MUX' ZERO" ++ cset "name='CDC_IF TX0 MUX' ZERO" ++ cset "name='SLIMBUS_0_RX Audio Mixer MultiMedia1' 0" ++ ] ++ ++ Value { ++ TQ "HiFi" ++ } ++} ++ ++SectionDevice."Speaker" { ++ Comment "Speaker playback" ++ ++ EnableSequence [ ++ cset "name='COMP7 Switch' 1" ++ cset "name='COMP8 Switch' 1" ++ cset "name='RX7 Digital Volume' 120" ++ cset "name='RX8 Digital Volume' 120" ++ cset "name='SpkrLeft COMP Switch' 1" ++ cset "name='SpkrLeft BOOST Switch' 1" ++ cset "name='SpkrLeft DAC Switch' 1" ++ cset "name='SpkrLeft VISENSE Switch' 0" ++ cset "name='SpkrLeft PA Volume' 5" ++ cset "name='SpkrRight COMP Switch' 1" ++ cset "name='SpkrRight BOOST Switch' 1" ++ cset "name='SpkrRight DAC Switch' 1" ++ cset "name='SpkrRight VISENSE Switch' 0" ++ cset "name='SpkrRight PA Volume' 5" ++ ] ++ ++ DisableSequence [ ++ cset "name='SpkrLeft COMP Switch' 0" ++ cset "name='SpkrLeft BOOST Switch' 0" ++ cset "name='SpkrLeft DAC Switch' 0" ++ cset "name='SpkrLeft VISENSE Switch' 0" ++ cset "name='SpkrRight COMP Switch' 0" ++ cset "name='SpkrRight BOOST Switch' 0" ++ cset "name='SpkrRight DAC Switch' 0" ++ cset "name='SpkrRight VISENSE Switch' 0" ++ cset "name='RX7 Digital Volume' 0" ++ cset "name='RX8 Digital Volume' 0" ++ cset "name='COMP7 Switch' 0" ++ cset "name='COMP8 Switch' 0" ++ ] ++ ++ Value { ++ PlaybackPriority 100 ++ PlaybackPCM "hw:${CardId},0" ++ PlaybackChannels 2 ++ } ++} +diff --git a/ucm2/Odin/Odin.conf b/ucm2/Odin/Odin.conf +new file mode 100644 +index 0000000..ceba910 +--- /dev/null ++++ b/ucm2/Odin/Odin.conf +@@ -0,0 +1,6 @@ ++Syntax 3 ++ ++SectionUseCase."HiFi" { ++ File "/Odin/HiFi.conf" ++ Comment "HiFi quality Music." ++} +diff --git a/ucm2/conf.d/sdm845/AYNTechnologiesCo.Ltd.-OdinBase-odin.conf b/ucm2/conf.d/sdm845/AYNTechnologiesCo.Ltd.-OdinBase-odin.conf +new file mode 120000 +index 0000000..1a8d968 +--- /dev/null ++++ b/ucm2/conf.d/sdm845/AYNTechnologiesCo.Ltd.-OdinBase-odin.conf +@@ -0,0 +1 @@ ++../../Odin/Odin.conf +\ No newline at end of file +diff --git a/ucm2/conf.d/sdm845/AYNTechnologiesCo.Ltd.-OdinPro-odin.conf b/ucm2/conf.d/sdm845/AYNTechnologiesCo.Ltd.-OdinPro-odin.conf +new file mode 120000 +index 0000000..1a8d968 +--- /dev/null ++++ b/ucm2/conf.d/sdm845/AYNTechnologiesCo.Ltd.-OdinPro-odin.conf +@@ -0,0 +1 @@ ++../../Odin/Odin.conf +\ No newline at end of file +diff --git a/ucm2/conf.d/sdm845/ayn-AYNOdin-.conf b/ucm2/conf.d/sdm845/ayn-AYNOdin-.conf +new file mode 120000 +index 0000000..1a8d968 +--- /dev/null ++++ b/ucm2/conf.d/sdm845/ayn-AYNOdin-.conf +@@ -0,0 +1 @@ ++../../Odin/Odin.conf +\ No newline at end of file +-- +2.34.1 diff --git a/projects/ArchR/packages/audio/alsa-ucm-conf/patches/SM8250/0002_Add-Retroid-Pocket-SM8250-configuration.patch b/projects/ArchR/packages/audio/alsa-ucm-conf/patches/SM8250/0002_Add-Retroid-Pocket-SM8250-configuration.patch new file mode 100755 index 0000000000..77f4674a93 --- /dev/null +++ b/projects/ArchR/packages/audio/alsa-ucm-conf/patches/SM8250/0002_Add-Retroid-Pocket-SM8250-configuration.patch @@ -0,0 +1,184 @@ +From eae9ef3f5aed6679ac743e1a7314a7ff1d10f815 Mon Sep 17 00:00:00 2001 +From: Teguh Sobirin +Date: Wed, 9 Oct 2024 18:21:07 +0800 +Subject: [PATCH] Add Retroid Pocket SM8250 configuration + +--- + ucm2/Qualcomm/sm8250/HiFi-RP.conf | 67 +++++++++++++++++++ + ucm2/Qualcomm/sm8250/RetroidPocket.conf | 22 ++++++ + ucm2/codecs/wsa881x/init.conf | 12 ++++ + ucm2/conf.d/sm8250/RetroidPocket.conf | 1 + + .../sm8250/retroidpocket-RetroidPocket5-.conf | 1 + + .../retroidpocket-RetroidPocketFlip2-.conf | 1 + + .../retroidpocket-RetroidPocketMini-.conf | 1 + + .../retroidpocket-RetroidPocketMiniV2-.conf | 1 + + 8 files changed, 106 insertions(+) + create mode 100644 ucm2/Qualcomm/sm8250/HiFi-RP.conf + create mode 100644 ucm2/Qualcomm/sm8250/RetroidPocket.conf + create mode 100644 ucm2/codecs/wsa881x/init.conf + create mode 120000 ucm2/conf.d/sm8250/RetroidPocket.conf + create mode 120000 ucm2/conf.d/sm8250/retroidpocket-RetroidPocket5-.conf + create mode 120000 ucm2/conf.d/sm8250/retroidpocket-RetroidPocketFlip2-.conf + create mode 120000 ucm2/conf.d/sm8250/retroidpocket-RetroidPocketMini-.conf + create mode 120000 ucm2/conf.d/sm8250/retroidpocket-RetroidPocketMiniV2-.conf + +diff --git a/ucm2/Qualcomm/sm8250/HiFi-RP.conf b/ucm2/Qualcomm/sm8250/HiFi-RP.conf +new file mode 100644 +index 0000000..4a6c0a7 +--- /dev/null ++++ b/ucm2/Qualcomm/sm8250/HiFi-RP.conf +@@ -0,0 +1,65 @@ ++# Use case configuration for RetroidPocket 5 and Mini. ++# Author: Teguh Sobirin ++ ++SectionVerb { ++ ++ EnableSequence [ ++ cset "name='RX_CODEC_DMA_RX_0 Audio Mixer MultiMedia1' 1" ++ cset "name='WSA_CODEC_DMA_RX_0 Audio Mixer MultiMedia2' 1" ++ cset "name='MultiMedia3 Mixer TX_CODEC_DMA_TX_3' 1" ++ ] ++ ++ Value { ++ TQ "HiFi" ++ } ++} ++ ++SectionDevice."Headphones" { ++ Comment "Headphones Playback" ++ ++ Include.wcdhpe.File "/codecs/wcd938x/HeadphoneEnableSeq.conf" ++ Include.wcdhpd.File "/codecs/wcd938x/HeadphoneDisableSeq.conf" ++ Include.rxmhpe.File "/codecs/qcom-lpass/rx-macro/HeadphoneEnableSeq.conf" ++ Include.rxmhpd.File "/codecs/qcom-lpass/rx-macro/HeadphoneDisableSeq.conf" ++ ++ Value { ++ PlaybackPriority 200 ++ PlaybackPCM "hw:${CardId},0" ++ PlaybackMixer "default:${CardId}" ++ PlaybackMixerElem "HP" ++ JackControl "Headphone Jack" ++ JackHWMute "Speaker" ++ } ++} ++ ++SectionDevice."Speaker" { ++ Comment "Speaker Playback" ++ ++ Include.wsamspke.File "/codecs/qcom-lpass/wsa-macro/SpeakerEnableSeq.conf" ++ Include.wsamspkd.File "/codecs/qcom-lpass/wsa-macro/SpeakerDisableSeq.conf" ++ Include.wsaspke.File "/codecs/wsa881x/SpeakerEnableSeq.conf" ++ Include.wsaspkd.File "/codecs/wsa881x/SpeakerDisableSeq.conf" ++ ++ Value { ++ PlaybackPriority 100 ++ PlaybackPCM "hw:${CardId},1" ++ PlaybackMixer "default:${CardId}" ++ PlaybackMixerElem "Speakers" ++ } ++} ++ ++SectionDevice."Headset" { ++ Comment "Headphone Microphone" ++ ++ Include.wcdmice.File "/codecs/wcd938x/HeadphoneMicEnableSeq.conf" ++ Include.wcdmicd.File "/codecs/wcd938x/HeadphoneMicDisableSeq.conf" ++ Include.txmhpe.File "/codecs/qcom-lpass/tx-macro/HeadphoneMicEnableSeq.conf" ++ Include.txmhpd.File "/codecs/qcom-lpass/tx-macro/HeadphoneMicDisableSeq.conf" ++ ++ Value { ++ CapturePriority 100 ++ CapturePCM "hw:${CardId},2" ++ CaptureMixerElem "ADC2" ++ JackControl "Mic Jack" ++ } ++} +diff --git a/ucm2/Qualcomm/sm8250/RetroidPocket.conf b/ucm2/Qualcomm/sm8250/RetroidPocket.conf +new file mode 100644 +index 0000000..387d5a5 +--- /dev/null ++++ b/ucm2/Qualcomm/sm8250/RetroidPocket.conf +@@ -0,0 +1,22 @@ ++Syntax 4 ++ ++SectionUseCase."HiFi" { ++ File "/Qualcomm/sm8250/HiFi-RP.conf" ++ Comment "HiFi quality Music." ++} ++ ++BootSequence [ ++ cset "name='WSA_RX0 Digital Volume' 120" ++ cset "name='WSA_RX1 Digital Volume' 120" ++ cset "name='SpkrLeft PA Volume' 12" ++ cset "name='SpkrRight PA Volume' 12" ++ cset "name='HPHL Volume' 20" ++ cset "name='HPHR Volume' 20" ++ cset "name='ADC2 Volume' 10" ++] ++ ++Include.card-init.File "/lib/card-init.conf" ++Include.ctl-remap.File "/lib/ctl-remap.conf" ++Include.wcd-init.File "/codecs/wcd938x/init.conf" ++Include.wsa-init.File "/codecs/wsa881x/init.conf" ++Include.rxm-init.File "/codecs/qcom-lpass/rx-macro/init.conf" +diff --git a/ucm2/codecs/wsa881x/init.conf b/ucm2/codecs/wsa881x/init.conf +new file mode 100644 +index 0000000..fcb8988 +--- /dev/null ++++ b/ucm2/codecs/wsa881x/init.conf +@@ -0,0 +1,12 @@ ++# WSA881x specific volume control settings ++LibraryConfig.remap.Config { ++ ++ ctl.default.map { ++ # Merge two mono controls into one stereo ++ "name='Speakers Volume'" { ++ "name='SpkrLeft PA Volume'".vindex.0 0 ++ "name='SpkrRight PA Volume'".vindex.1 0 ++ } ++ } ++} ++ +diff --git a/ucm2/conf.d/sm8250/RetroidPocket.conf b/ucm2/conf.d/sm8250/RetroidPocket.conf +new file mode 120000 +index 0000000..8598750 +--- /dev/null ++++ b/ucm2/conf.d/sm8250/RetroidPocket.conf +@@ -0,0 +1 @@ ++../../Qualcomm/sm8250/RetroidPocket.conf +\ No newline at end of file +diff --git a/ucm2/conf.d/sm8250/retroidpocket-RetroidPocket5-.conf b/ucm2/conf.d/sm8250/retroidpocket-RetroidPocket5-.conf +new file mode 120000 +index 0000000..8598750 +--- /dev/null ++++ b/ucm2/conf.d/sm8250/retroidpocket-RetroidPocket5-.conf +@@ -0,0 +1 @@ ++../../Qualcomm/sm8250/RetroidPocket.conf +\ No newline at end of file +diff --git a/ucm2/conf.d/sm8250/retroidpocket-RetroidPocketFlip2-.conf b/ucm2/conf.d/sm8250/retroidpocket-RetroidPocketFlip2-.conf +new file mode 120000 +index 0000000..8598750 +--- /dev/null ++++ b/ucm2/conf.d/sm8250/retroidpocket-RetroidPocketFlip2-.conf +@@ -0,0 +1 @@ ++../../Qualcomm/sm8250/RetroidPocket.conf +\ No newline at end of file +diff --git a/ucm2/conf.d/sm8250/retroidpocket-RetroidPocketMini-.conf b/ucm2/conf.d/sm8250/retroidpocket-RetroidPocketMini-.conf +new file mode 120000 +index 0000000..8598750 +--- /dev/null ++++ b/ucm2/conf.d/sm8250/retroidpocket-RetroidPocketMini-.conf +@@ -0,0 +1 @@ ++../../Qualcomm/sm8250/RetroidPocket.conf +\ No newline at end of file +diff --git a/ucm2/conf.d/sm8250/retroidpocket-RetroidPocketMiniV2-.conf b/ucm2/conf.d/sm8250/retroidpocket-RetroidPocketMiniV2-.conf +new file mode 120000 +index 0000000..8598750 +--- /dev/null ++++ b/ucm2/conf.d/sm8250/retroidpocket-RetroidPocketMiniV2-.conf +@@ -0,0 +1 @@ ++../../Qualcomm/sm8250/RetroidPocket.conf +\ No newline at end of file +-- +2.34.1 + diff --git a/projects/ArchR/packages/audio/alsa-ucm-conf/patches/SM8250/0003_Maintain-compatibility-with-old-loader-u-boot.patch b/projects/ArchR/packages/audio/alsa-ucm-conf/patches/SM8250/0003_Maintain-compatibility-with-old-loader-u-boot.patch new file mode 100644 index 0000000000..f33d3cb801 --- /dev/null +++ b/projects/ArchR/packages/audio/alsa-ucm-conf/patches/SM8250/0003_Maintain-compatibility-with-old-loader-u-boot.patch @@ -0,0 +1,30 @@ +From 39caffb11de21215c9ae2d651c43869a73d04654 Mon Sep 17 00:00:00 2001 +From: Teguh Sobirin +Date: Sat, 12 Oct 2024 03:42:09 +0800 +Subject: [PATCH] Maintain compatibility with old loader (u-boot) + +--- + ucm2/conf.d/sm8250/retroid-RetroidPocket5-conf | 1 + + ucm2/conf.d/sm8250/retroid-RetroidPocketMini-.conf | 1 + + 2 files changed, 2 insertions(+) + create mode 120000 ucm2/conf.d/sm8250/retroid-RetroidPocket5-conf + create mode 120000 ucm2/conf.d/sm8250/retroid-RetroidPocketMini-.conf + +diff --git a/ucm2/conf.d/sm8250/retroid-RetroidPocket5-conf b/ucm2/conf.d/sm8250/retroid-RetroidPocket5-conf +new file mode 120000 +index 0000000..8598750 +--- /dev/null ++++ b/ucm2/conf.d/sm8250/retroid-RetroidPocket5-conf +@@ -0,0 +1 @@ ++../../Qualcomm/sm8250/RetroidPocket.conf +\ No newline at end of file +diff --git a/ucm2/conf.d/sm8250/retroid-RetroidPocketMini-.conf b/ucm2/conf.d/sm8250/retroid-RetroidPocketMini-.conf +new file mode 120000 +index 0000000..8598750 +--- /dev/null ++++ b/ucm2/conf.d/sm8250/retroid-RetroidPocketMini-.conf +@@ -0,0 +1 @@ ++../../Qualcomm/sm8250/RetroidPocket.conf +\ No newline at end of file +-- +2.34.1 diff --git a/projects/ArchR/packages/audio/alsa-ucm-conf/patches/SM8550/0001_Add-AYN-Odin2.patch b/projects/ArchR/packages/audio/alsa-ucm-conf/patches/SM8550/0001_Add-AYN-Odin2.patch new file mode 100644 index 0000000000..4c3b6b7549 --- /dev/null +++ b/projects/ArchR/packages/audio/alsa-ucm-conf/patches/SM8550/0001_Add-AYN-Odin2.patch @@ -0,0 +1,160 @@ +From d33738b93e9560e8d9e08a024cc84c8055bb7eb9 Mon Sep 17 00:00:00 2001 +From: Teguh Sobirin +Date: Mon, 24 Feb 2025 17:19:57 +0800 +Subject: [PATCH] Add AYN Odin2 + +Signed-off-by: Teguh Sobirin +--- + ucm2/AYN/Odin2/AYN-Odin2.conf | 31 +++++++++++ + ucm2/AYN/Odin2/HiFi.conf | 91 +++++++++++++++++++++++++++++++ + ucm2/conf.d/sm8550/AYN-Odin2.conf | 1 + + 3 files changed, 123 insertions(+) + create mode 100644 ucm2/AYN/Odin2/AYN-Odin2.conf + create mode 100644 ucm2/AYN/Odin2/HiFi.conf + create mode 120000 ucm2/conf.d/sm8550/AYN-Odin2.conf + +diff --git a/ucm2/AYN/Odin2/AYN-Odin2.conf b/ucm2/AYN/Odin2/AYN-Odin2.conf +new file mode 100644 +index 0000000..e4054ba +--- /dev/null ++++ b/ucm2/AYN/Odin2/AYN-Odin2.conf +@@ -0,0 +1,31 @@ ++# Use case configuration for AYN Odin2 ++# Author: Teguh Sobirin ++ ++Syntax 4 ++ ++SectionUseCase."HiFi" { ++ File "/AYN/Odin2/HiFi.conf" ++ Comment "HiFi quality Music." ++} ++ ++BootSequence [ ++ cset "name='RX_RX0 Digital Volume' 84" ++ cset "name='RX_RX1 Digital Volume' 84" ++ cset "name='HPHL Volume' 20" ++ cset "name='HPHR Volume' 20" ++ cset "name='ADC2 Volume' 10" ++] ++ ++LibraryConfig.remap.Config { ++ ++ ctl.default.map { ++ "name='HP Volume'" { ++ "name='HPHL Volume'".vindex.0 0 ++ "name='HPHR Volume'".vindex.1 0 ++ } ++ } ++} ++ ++Include.card-init.File "/lib/card-init.conf" ++Include.ctl-remap.File "/lib/ctl-remap.conf" ++Include.wcd-init.File "/codecs/wcd938x/init.conf" +diff --git a/ucm2/AYN/Odin2/HiFi.conf b/ucm2/AYN/Odin2/HiFi.conf +new file mode 100644 +index 0000000..dc5211e +--- /dev/null ++++ b/ucm2/AYN/Odin2/HiFi.conf +@@ -0,0 +1,91 @@ ++# Use case configuration for AYN Odin2 ++# Author: Teguh Sobirin ++ ++SectionVerb { ++ EnableSequence [ ++ cset "name='PRIMARY_MI2S_RX Audio Mixer MultiMedia1' 1" ++ cset "name='RX_CODEC_DMA_RX_0 Audio Mixer MultiMedia2' 1" ++ cset "name='DISPLAY_PORT_RX_0 Audio Mixer MultiMedia2' 0" ++ cset "name='MultiMedia3 Mixer TX_CODEC_DMA_TX_3' 1" ++ ] ++ ++ DisableSequence [ ++ cset "name='PRIMARY_MI2S_RX Audio Mixer MultiMedia1' 0" ++ cset "name='RX_CODEC_DMA_RX_0 Audio Mixer MultiMedia2' 0" ++ cset "name='DISPLAY_PORT_RX_0 Audio Mixer MultiMedia2' 0" ++ cset "name='MultiMedia3 Mixer TX_CODEC_DMA_TX_3' 0" ++ ] ++ ++ Value { ++ TQ "HiFi" ++ } ++} ++ ++SectionDevice."Speaker" { ++ Comment "Speaker playback" ++ ++ Value { ++ PlaybackPriority 150 ++ PlaybackPCM "hw:${CardId},0" ++ PlaybackChannels 2 ++ } ++} ++ ++SectionDevice."Headphones" { ++ Comment "Headphones Playback" ++ ++ Include.wcdhpe.File "/codecs/wcd938x/HeadphoneEnableSeq.conf" ++ Include.wcdhpd.File "/codecs/wcd938x/HeadphoneDisableSeq.conf" ++ Include.rxmhpe.File "/codecs/qcom-lpass/rx-macro/HeadphoneEnableSeq.conf" ++ Include.rxmhpd.File "/codecs/qcom-lpass/rx-macro/HeadphoneDisableSeq.conf" ++ ++ Value { ++ PlaybackPriority 200 ++ PlaybackPCM "hw:${CardId},1" ++ PlaybackMixer "default:${CardId}" ++ PlaybackMixerElem "HP" ++ PlaybackChannels 2 ++ JackControl "Headphone Jack" ++ JackHWMute "Speaker" ++ } ++} ++ ++#SectionDevice."Headset" { ++# Comment "Headphone Microphone" ++# ++# Include.wcdmice.File "/codecs/wcd938x/HeadphoneMicEnableSeq.conf" ++# Include.wcdmicd.File "/codecs/wcd938x/HeadphoneMicDisableSeq.conf" ++# Include.txmhpe.File "/codecs/qcom-lpass/tx-macro/SoundwireMic1EnableSeq.conf" ++# Include.txmhpd.File "/codecs/qcom-lpass/tx-macro/HeadphoneMicDisableSeq.conf" ++# ++# Value { ++# CapturePriority 200 ++# CapturePCM "hw:${CardId},2" ++# CaptureMixerElem "ADC2" ++# CaptureChannels 1 ++# JackControl "Mic Jack" ++# } ++#} ++ ++SectionDevice."DisplayPort" { ++ Comment "DisplayPort playback" ++ ++ EnableSequence [ ++ cset "name='PRIMARY_MI2S_RX Audio Mixer MultiMedia1' 0" ++ cset "name='RX_CODEC_DMA_RX_0 Audio Mixer MultiMedia2' 0" ++ cset "name='DISPLAY_PORT_RX_0 Audio Mixer MultiMedia2' 1" ++ ] ++ ++ DisableSequence [ ++ cset "name='PRIMARY_MI2S_RX Audio Mixer MultiMedia1' 1" ++ cset "name='DISPLAY_PORT_RX_0 Audio Mixer MultiMedia2' 0" ++ cset "name='RX_CODEC_DMA_RX_0 Audio Mixer MultiMedia2' 1" ++ ] ++ ++ Value { ++ PlaybackPriority 100 ++ PlaybackPCM "hw:${CardId},1" ++ JackControl "DP0 Jack" ++ JackHWMute "Speaker" ++ } ++} +diff --git a/ucm2/conf.d/sm8550/AYN-Odin2.conf b/ucm2/conf.d/sm8550/AYN-Odin2.conf +new file mode 120000 +index 0000000..414976a +--- /dev/null ++++ b/ucm2/conf.d/sm8550/AYN-Odin2.conf +@@ -0,0 +1 @@ ++../../AYN/Odin2/AYN-Odin2.conf +\ No newline at end of file +-- +2.34.1 + diff --git a/projects/ArchR/packages/audio/alsa-ucm-conf/patches/SM8550/0002_AYN-Odin2---Add-EFI-boot-compatibility.patch b/projects/ArchR/packages/audio/alsa-ucm-conf/patches/SM8550/0002_AYN-Odin2---Add-EFI-boot-compatibility.patch new file mode 100644 index 0000000000..7b5f549c08 --- /dev/null +++ b/projects/ArchR/packages/audio/alsa-ucm-conf/patches/SM8550/0002_AYN-Odin2---Add-EFI-boot-compatibility.patch @@ -0,0 +1,22 @@ +From 39a2034f56bc990059cf20d3d6ef3e85fdb0e924 Mon Sep 17 00:00:00 2001 +From: Teguh Sobirin +Date: Mon, 24 Feb 2025 17:20:50 +0800 +Subject: [PATCH] AYN Odin2 : Add EFI boot compatibility + +Signed-off-by: Teguh Sobirin +--- + ucm2/conf.d/sm8550/ayn-AYNOdin2-.conf | 1 + + 1 file changed, 1 insertion(+) + create mode 120000 ucm2/conf.d/sm8550/ayn-AYNOdin2-.conf + +diff --git a/ucm2/conf.d/sm8550/ayn-AYNOdin2-.conf b/ucm2/conf.d/sm8550/ayn-AYNOdin2-.conf +new file mode 120000 +index 0000000..414976a +--- /dev/null ++++ b/ucm2/conf.d/sm8550/ayn-AYNOdin2-.conf +@@ -0,0 +1 @@ ++../../AYN/Odin2/AYN-Odin2.conf +\ No newline at end of file +-- +2.34.1 + diff --git a/projects/ArchR/packages/audio/alsa-ucm-conf/patches/SM8550/0003_Add-AYANEO-Pocket-ACE.patch b/projects/ArchR/packages/audio/alsa-ucm-conf/patches/SM8550/0003_Add-AYANEO-Pocket-ACE.patch new file mode 100644 index 0000000000..1200a01542 --- /dev/null +++ b/projects/ArchR/packages/audio/alsa-ucm-conf/patches/SM8550/0003_Add-AYANEO-Pocket-ACE.patch @@ -0,0 +1,87 @@ +diff --git a/ucm2/AYANEO/Pocket/AYANEO-Pocket.conf b/ucm2/AYANEO/Pocket/AYANEO-Pocket.conf +new file mode 100644 +index 0000000..e4054ba +--- /dev/null ++++ b/ucm2/AYANEO/Pocket/AYANEO-Pocket.conf +@@ -0,0 +1,11 @@ ++Syntax 4 ++ ++SectionUseCase."HiFi" { ++ File "/AYANEO/Pocket/HiFi.conf" ++ Comment "HiFi quality Music." ++} ++ ++Include.card-init.File "/lib/card-init.conf" ++Include.ctl-remap.File "/lib/ctl-remap.conf" ++Include.wsa-init.File "/codecs/wsa884x/two-speakers/init.conf" ++Include.wsam-init.File "/codecs/qcom-lpass/wsa-macro/init.conf" +diff --git a/ucm2/AYANEO/Pocket/HiFi.conf b/ucm2/AYANEO/Pocket/HiFi.conf +new file mode 100644 +index 0000000..dc5211e +--- /dev/null ++++ b/ucm2/AYANEO/Pocket/HiFi.conf +@@ -0,0 +1,56 @@ ++SectionVerb { ++ EnableSequence [ ++ cset "name='WSA_CODEC_DMA_RX_0 Audio Mixer MultiMedia2' 1" ++ cset "name='MultiMedia3 Mixer VA_CODEC_DMA_TX_0' 1" ++ ] ++ ++ Include.wsae.File "/codecs/wsa884x/two-speakers/DefaultEnableSeq.conf" ++ ++ Value { ++ TQ "HiFi" ++ } ++} ++ ++SectionDevice."Speaker" { ++ Comment "Speaker playback" ++ ++ Include.wsmspk1e.File "/codecs/qcom-lpass/wsa-macro/SpeakerEnableSeq.conf" ++ Include.wsmspk1d.File "/codecs/qcom-lpass/wsa-macro/SpeakerDisableSeq.conf" ++ Include.wsaspkd.File "/codecs/wsa884x/two-speakers/SpeakerSeq.conf" ++ ++ Value { ++ PlaybackChannels 2 ++ PlaybackPriority 100 ++ PlaybackPCM "hw:${CardId},1" ++ PlaybackMixer "default:${CardId}" ++ PlaybackMixerElem "Speakers" ++ } ++} ++ ++SectionDevice."Mic1" { ++ Comment "Top microphones" ++ ++ Include.vadm0e.File "/codecs/qcom-lpass/va-macro/DMIC0EnableSeq.conf" ++ Include.vadm0d.File "/codecs/qcom-lpass/va-macro/DMIC0DisableSeq.conf" ++ Include.vadm1e.File "/codecs/qcom-lpass/va-macro/DMIC1EnableSeq.conf" ++ Include.vadm1d.File "/codecs/qcom-lpass/va-macro/DMIC1DisableSeq.conf" ++ ++ Value { ++ CapturePriority 100 ++ CapturePCM "hw:${CardId},2" ++ } ++} ++ ++#SectionDevice."Mic2" { ++# Comment "Bottom microphones" ++# ++# Include.vadm2e.File "/codecs/qcom-lpass/va-macro/DMIC2EnableSeq.conf" ++# Include.vadm2d.File "/codecs/qcom-lpass/va-macro/DMIC2DisableSeq.conf" ++# Include.vadm3e.File "/codecs/qcom-lpass/va-macro/DMIC3EnableSeq.conf" ++# Include.vadm3d.File "/codecs/qcom-lpass/va-macro/DMIC3DisableSeq.conf" ++# ++# Value { ++# CapturePriority 100 ++# CapturePCM "hw:${CardId},4" ++# } ++#} +diff --git a/ucm2/conf.d/sm8550/SM8550-APS.conf b/ucm2/conf.d/sm8550/SM8550-APS.conf +new file mode 120000 +index 0000000..414976a +--- /dev/null ++++ b/ucm2/conf.d/sm8550/SM8550-APS.conf +@@ -0,0 +1 @@ ++../../AYANEO/Pocket/AYANEO-Pocket.conf +\ No newline at end of file diff --git a/projects/ArchR/packages/audio/alsa-ucm-conf/patches/SM8550/0004_AYANEO-Pocket-ACE---Add-EFI-boot-compatibility.patch b/projects/ArchR/packages/audio/alsa-ucm-conf/patches/SM8550/0004_AYANEO-Pocket-ACE---Add-EFI-boot-compatibility.patch new file mode 100644 index 0000000000..344f64107e --- /dev/null +++ b/projects/ArchR/packages/audio/alsa-ucm-conf/patches/SM8550/0004_AYANEO-Pocket-ACE---Add-EFI-boot-compatibility.patch @@ -0,0 +1,8 @@ +diff --git a/ucm2/conf.d/sm8550/ayaneo-AYANEOPocketACE-.conf b/ucm2/conf.d/sm8550/ayaneo-AYANEOPocketACE-.conf +new file mode 120000 +index 0000000..414976a +--- /dev/null ++++ b/ucm2/conf.d/sm8550/ayaneo-AYANEOPocketACE-.conf +@@ -0,0 +1 @@ ++../../AYANEO/Pocket/AYANEO-Pocket.conf +\ No newline at end of file diff --git a/projects/ArchR/packages/audio/alsa-ucm-conf/patches/SM8550/0004_AYANEO-Pocket-DMG---Add-EFI-boot-compatibility.patch b/projects/ArchR/packages/audio/alsa-ucm-conf/patches/SM8550/0004_AYANEO-Pocket-DMG---Add-EFI-boot-compatibility.patch new file mode 100644 index 0000000000..962bf8c556 --- /dev/null +++ b/projects/ArchR/packages/audio/alsa-ucm-conf/patches/SM8550/0004_AYANEO-Pocket-DMG---Add-EFI-boot-compatibility.patch @@ -0,0 +1,8 @@ +diff --git a/ucm2/conf.d/sm8550/ayaneo-AYANEOPocketDMG-.conf b/ucm2/conf.d/sm8550/ayaneo-AYANEOPocketDMG-.conf +new file mode 120000 +index 0000000..414976a +--- /dev/null ++++ b/ucm2/conf.d/sm8550/ayaneo-AYANEOPocketDMG-.conf +@@ -0,0 +1 @@ ++../../AYANEO/Pocket/AYANEO-Pocket.conf +\ No newline at end of file diff --git a/projects/ArchR/packages/audio/alsa-ucm-conf/patches/SM8550/0004_AYANEO-Pocket-DS---Add-EFI-boot-compatibility.patch b/projects/ArchR/packages/audio/alsa-ucm-conf/patches/SM8550/0004_AYANEO-Pocket-DS---Add-EFI-boot-compatibility.patch new file mode 100644 index 0000000000..54b574b125 --- /dev/null +++ b/projects/ArchR/packages/audio/alsa-ucm-conf/patches/SM8550/0004_AYANEO-Pocket-DS---Add-EFI-boot-compatibility.patch @@ -0,0 +1,8 @@ +diff --git a/ucm2/conf.d/sm8550/ayaneo-AYANEOPocketDS-.conf b/ucm2/conf.d/sm8550/ayaneo-AYANEOPocketDS-.conf +new file mode 120000 +index 0000000..414976a +--- /dev/null ++++ b/ucm2/conf.d/sm8550/ayaneo-AYANEOPocketDS-.conf +@@ -0,0 +1 @@ ++../../AYANEO/Pocket/AYANEO-Pocket.conf +\ No newline at end of file diff --git a/projects/ArchR/packages/audio/alsa-ucm-conf/patches/SM8550/0004_AYANEO-Pocket-EVO---Add-EFI-boot-compatibility.patch b/projects/ArchR/packages/audio/alsa-ucm-conf/patches/SM8550/0004_AYANEO-Pocket-EVO---Add-EFI-boot-compatibility.patch new file mode 100644 index 0000000000..d3173ebcdb --- /dev/null +++ b/projects/ArchR/packages/audio/alsa-ucm-conf/patches/SM8550/0004_AYANEO-Pocket-EVO---Add-EFI-boot-compatibility.patch @@ -0,0 +1,8 @@ +diff --git a/ucm2/conf.d/sm8550/ayaneo-AYANEOPocketEVO-.conf b/ucm2/conf.d/sm8550/ayaneo-AYANEOPocketEVO-.conf +new file mode 120000 +index 0000000..414976a +--- /dev/null ++++ b/ucm2/conf.d/sm8550/ayaneo-AYANEOPocketEVO-.conf +@@ -0,0 +1 @@ ++../../AYANEO/Pocket/AYANEO-Pocket.conf +\ No newline at end of file diff --git a/projects/ArchR/packages/audio/alsa-ucm-conf/patches/SM8650/0001-AYANEO-Pocket-S2.patch b/projects/ArchR/packages/audio/alsa-ucm-conf/patches/SM8650/0001-AYANEO-Pocket-S2.patch new file mode 100644 index 0000000000..7125c09b4d --- /dev/null +++ b/projects/ArchR/packages/audio/alsa-ucm-conf/patches/SM8650/0001-AYANEO-Pocket-S2.patch @@ -0,0 +1,145 @@ +diff --git a/ucm2/Qualcomm/sm8650/APS2/SM8650-APS2.conf b/ucm2/Qualcomm/sm8650/APS2/SM8650-APS2.conf +new file mode 100644 +index 0000000..e4054ba +--- /dev/null ++++ b/ucm2/Qualcomm/sm8650/APS2/SM8650-APS2.conf +@@ -0,0 +1,13 @@ ++Syntax 4 ++ ++SectionUseCase."HiFi" { ++ File "/Qualcomm/sm8650/APS2/HiFi.conf" ++ Comment "HiFi quality Music." ++} ++ ++Include.card-init.File "/lib/card-init.conf" ++Include.ctl-remap.File "/lib/ctl-remap.conf" ++Include.wcd-init.File "/codecs/wcd939x/init.conf" ++Include.wsam-init.File "/codecs/qcom-lpass/wsa-macro/init.conf" ++Include.rxm-init.File "/codecs/qcom-lpass/rx-macro/init.conf" ++Include.wsa-init.File "/codecs/wsa884x/two-speakers/init.conf" +diff --git a/ucm2/Qualcomm/sm8650/APS2/HiFi.conf b/ucm2/Qualcomm/sm8650/APS2/HiFi.conf +new file mode 100644 +index 0000000..dc5211e +--- /dev/null ++++ b/ucm2/Qualcomm/sm8650/APS2/HiFi.conf +@@ -0,0 +1,112 @@ ++SectionVerb { ++ EnableSequence [ ++ cset "name='DISPLAY_PORT_RX_0 Audio Mixer MultiMedia1' 0" ++ cset "name='RX_CODEC_DMA_RX_0 Audio Mixer MultiMedia1' 1" ++ cset "name='WSA_CODEC_DMA_RX_0 Audio Mixer MultiMedia2' 1" ++ cset "name='MultiMedia3 Mixer TX_CODEC_DMA_TX_3' 1" ++ cset "name='MultiMedia4 Mixer VA_CODEC_DMA_TX_0' 1" ++ ] ++ ++ Include.wcde.File "/codecs/wcd939x/DefaultEnableSeq.conf" ++ Include.wsae.File "/codecs/wsa884x/two-speakers/DefaultEnableSeq.conf" ++ ++ Value { ++ TQ "HiFi" ++ } ++} ++ ++SectionDevice."Speaker" { ++ Comment "Speaker playback" ++ ++ Include.wcdspk1e.File "/codecs/qcom-lpass/wsa-macro/SpeakerEnableSeq.conf" ++ Include.wcdspk1d.File "/codecs/qcom-lpass/wsa-macro/SpeakerDisableSeq.conf" ++ Include.wsaspkd.File "/codecs/wsa884x/two-speakers/SpeakerSeq.conf" ++ ++ Value { ++ PlaybackChannels 2 ++ PlaybackPriority 100 ++ PlaybackPCM "hw:${CardId},1" ++ PlaybackMixer "default:${CardId}" ++ PlaybackMixerElem "Speakers" ++ } ++} ++ ++SectionDevice."Headphones" { ++ Comment "Headphones playback" ++ ++ EnableSequence [ ++ cset "name='RX_CODEC_DMA_RX_0 Audio Mixer MultiMedia1' 1" ++ cset "name='DISPLAY_PORT_RX_0 Audio Mixer MultiMedia1' 0" ++ ] ++ ++ Include.wcdhpe.File "/codecs/wcd939x/HeadphoneEnableSeq.conf" ++ Include.wcdhpd.File "/codecs/wcd939x/HeadphoneDisableSeq.conf" ++ Include.rxmhpe.File "/codecs/qcom-lpass/rx-macro/HeadphoneEnableSeq.conf" ++ Include.rxmhpd.File "/codecs/qcom-lpass/rx-macro/HeadphoneDisableSeq.conf" ++ ++ Value { ++ PlaybackPriority 200 ++ PlaybackPCM "hw:${CardId},0" ++ PlaybackMixer "default:${CardId}" ++ PlaybackMixerElem "HP" ++ JackControl "Headset Jack" ++ JackHWMute "Speaker" ++ } ++} ++ ++#SectionDevice."Headset" { ++# Comment "Headset microphone" ++# ++# #ConflictingDevice [ ++# # "Mic" ++# #] ++# ++# Include.wcdmice.File "/codecs/wcd939x/HeadphoneMicEnableSeq.conf" ++# Include.wcdmicd.File "/codecs/wcd939x/HeadphoneMicDisableSeq.conf" ++# Include.txmhpe.File "/codecs/qcom-lpass/tx-macro/SoundwireMic1EnableSeq.conf" ++# Include.txmhpd.File "/codecs/qcom-lpass/tx-macro/SoundwireMicDisableSeq.conf" ++# ++# Value { ++# CaptureChannels 1 ++# CapturePriority 200 ++# CapturePCM "hw:${CardId},2" ++# CaptureMixerElem "ADC2" ++# JackControl "Headset Jack" ++# } ++#} ++ ++#SectionDevice."Mic" { ++# Comment "Bottom Microphone" ++# ++# Include.txmhpe.File "/codecs/qcom-lpass/tx-macro/SoundwireMic8EnableSeq.conf" ++# Include.txmhpd.File "/codecs/qcom-lpass/tx-macro/SoundwireMicDisableSeq.conf" ++# ++# Value { ++# CaptureChannels 1 ++# CapturePriority 100 ++# CapturePCM "hw:${CardId},3" ++# CaptureMixerElem "SMIC8" ++# } ++#} ++ ++SectionDevice."HDMI0" { ++ Comment "DisplayPort 0 playback" ++ ++ ConflictingDevice [ ++ "Headphones" ++ ] ++ ++ EnableSequence [ ++ cset "name='DISPLAY_PORT_RX_0 Audio Mixer MultiMedia1' 1" ++ ] ++ ++ DisableSequence [ ++ cset "name='DISPLAY_PORT_RX_0 Audio Mixer MultiMedia1' 0" ++ ] ++ ++ Value { ++ PlaybackPriority 200 ++ PlaybackPCM "hw:${CardId},0" ++ JackControl "DP0 Jack" ++ } ++} +diff --git a/ucm2/conf.d/sm8650/SM8650-APS2.conf b/ucm2/conf.d/sm8650/SM8650-APS2.conf +new file mode 120000 +index 0000000..414976a +--- /dev/null ++++ b/ucm2/conf.d/sm8650/SM8650-APS2.conf +@@ -0,0 +1 @@ ++../../Qualcomm/sm8650/APS2/SM8650-APS2.conf +\ No newline at end of file diff --git a/projects/ArchR/packages/audio/alsa-ucm-conf/patches/SM8650/0002_AYANEO-Pocket-S2---Add-EFI-boot-compatibility.patch b/projects/ArchR/packages/audio/alsa-ucm-conf/patches/SM8650/0002_AYANEO-Pocket-S2---Add-EFI-boot-compatibility.patch new file mode 100644 index 0000000000..76ad34fd63 --- /dev/null +++ b/projects/ArchR/packages/audio/alsa-ucm-conf/patches/SM8650/0002_AYANEO-Pocket-S2---Add-EFI-boot-compatibility.patch @@ -0,0 +1,8 @@ +diff --git a/ucm2/conf.d/sm8650/ayaneo-AYANEOPocketS2-.conf b/ucm2/conf.d/sm8650/ayaneo-AYANEOPocketS2-.conf +new file mode 120000 +index 0000000..414976a +--- /dev/null ++++ b/ucm2/conf.d/sm8650/ayaneo-AYANEOPocketS2-.conf +@@ -0,0 +1 @@ ++../../Qualcomm/sm8650/APS2/SM8650-APS2.conf +\ No newline at end of file diff --git a/projects/ArchR/packages/audio/alsa-utils/package.mk b/projects/ArchR/packages/audio/alsa-utils/package.mk new file mode 100644 index 0000000000..82c8fff5ca --- /dev/null +++ b/projects/ArchR/packages/audio/alsa-utils/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) 2016-present Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="alsa-utils" +PKG_VERSION="1.2.14" +PKG_LICENSE="GPL" +PKG_SITE="http://www.alsa-project.org/" +PKG_URL="https://www.alsa-project.org/files/pub/utils/alsa-utils-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain alsa-lib ncurses systemd alsa-ucm-conf" +PKG_LONGDESC="This package includes the utilities for ALSA, like alsamixer, aplay, arecord, alsactl, iecset and speaker-test." +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="--disable-alsaconf \ + --disable-alsaloop \ + --enable-alsatest \ + --disable-bat \ + --disable-dependency-tracking \ + --disable-nls \ + --disable-rst2man \ + --disable-xmlto" + +pre_make_target() { + # Fix: po/Makefile references /config.status with wrong absolute path in cross-compile + # NLS is disabled anyway, so remove the po subdir from the build + sed -i 's/SUBDIRS = \(.*\) po\(.*\)/SUBDIRS = \1\2/' Makefile +} + +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 +} diff --git a/projects/ArchR/packages/audio/espeak/package.mk b/projects/ArchR/packages/audio/espeak/package.mk new file mode 100644 index 0000000000..6b20b6f07d --- /dev/null +++ b/projects/ArchR/packages/audio/espeak/package.mk @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +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/projects/ArchR/packages/audio/espeak/patches/espeak-1.47-ftbs-ld-libm.patch b/projects/ArchR/packages/audio/espeak/patches/espeak-1.47-ftbs-ld-libm.patch new file mode 100644 index 0000000000..446493fb40 --- /dev/null +++ b/projects/ArchR/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/projects/ArchR/packages/audio/espeak/patches/espeak-1.47-wav-close.patch b/projects/ArchR/packages/audio/espeak/patches/espeak-1.47-wav-close.patch new file mode 100644 index 0000000000..d0550d9458 --- /dev/null +++ b/projects/ArchR/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/projects/ArchR/packages/audio/espeak/patches/espeak-1.48-gcc-6-fix.patch b/projects/ArchR/packages/audio/espeak/patches/espeak-1.48-gcc-6-fix.patch new file mode 100644 index 0000000000..6e59c7892f --- /dev/null +++ b/projects/ArchR/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/projects/ArchR/packages/audio/fluidsynth/package.mk b/projects/ArchR/packages/audio/fluidsynth/package.mk new file mode 100644 index 0000000000..e45943a6cb --- /dev/null +++ b/projects/ArchR/packages/audio/fluidsynth/package.mk @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +. ${ROOT}/packages/audio/fluidsynth/package.mk + +PKG_CMAKE_OPTS_TARGET="-DBUILD_SHARED_LIBS=1 \ + -DLIB_SUFFIX= \ + -Denable-libsndfile=1 \ + -Denable-pkgconfig=1 \ + -Denable-pipewire=1 \ + -Denable-pulseaudio=1 \ + -Denable-systemd=1 \ + -Denable-readline=0" diff --git a/projects/ArchR/packages/audio/fluidsynth/system.d/fluidsynth.service b/projects/ArchR/packages/audio/fluidsynth/system.d/fluidsynth.service new file mode 100644 index 0000000000..8f865ec372 --- /dev/null +++ b/projects/ArchR/packages/audio/fluidsynth/system.d/fluidsynth.service @@ -0,0 +1,26 @@ +[Unit] +Description=FluidSynth Daemon +Documentation=man:fluidsynth(1) +After=sound.target +After=pipewire.service + +[Service] +# added automatically, for details please see +# https://en.opensuse.org/openSUSE:Security_Features#Systemd_hardening_effort +ProtectSystem=full +ProtectHome=read-only +ProtectHostname=true +ProtectKernelTunables=true +ProtectKernelModules=true +ProtectKernelLogs=true +ProtectControlGroups=true +# end of automatic additions +# required in order for the above sandboxing options to work on a user unit +PrivateUsers=yes +Type=simple +NotifyAccess=main +EnvironmentFile=-%h/.config/fluidsynth +ExecStart=/usr/bin/fluidsynth -is -a sdl2 /usr/share/soundfonts/GeneralUser.sf2 + +[Install] +WantedBy=default.target diff --git a/projects/ArchR/packages/audio/ldacBT/package.mk b/projects/ArchR/packages/audio/ldacBT/package.mk new file mode 100644 index 0000000000..a0f95227d7 --- /dev/null +++ b/projects/ArchR/packages/audio/ldacBT/package.mk @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +. ${ROOT}/packages/audio/ldacBT/package.mk + +PKG_CMAKE_OPTS_TARGET="-DCMAKE_POLICY_VERSION_MINIMUM=3.5 \ + -DLDAC_SOFT_FLOAT=OFF" diff --git a/projects/ArchR/packages/audio/libao/package.mk b/projects/ArchR/packages/audio/libao/package.mk new file mode 100644 index 0000000000..7bda398b96 --- /dev/null +++ b/projects/ArchR/packages/audio/libao/package.mk @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="libao" +PKG_VERSION="1.2.0" +PKG_LICENSE="GPLv2" +PKG_SITE="https://xiph.org/ao/" +PKG_URL="http://downloads.xiph.org/releases/ao/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain alsa-lib pulseaudio" +PKG_LONGDESC="Libao is a cross-platform audio library that allows programs to output +audio using a simple API on a wide variety of platforms." +PKG_BUILD_FLAGS="+pic" + +pre_configure_target() { +export CFLAGS="${CFLAGS} -Wno-implicit-function-declaration" +} diff --git a/projects/ArchR/packages/audio/libfreeaptx/package.mk b/projects/ArchR/packages/audio/libfreeaptx/package.mk new file mode 100644 index 0000000000..5a5f3dbdd3 --- /dev/null +++ b/projects/ArchR/packages/audio/libfreeaptx/package.mk @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +. ${ROOT}/packages/audio/libfreeaptx/package.mk + +PKG_SHA256="5ab5ebddf3f2eb7ce47a505b87460b00fc1ede99c70010796d3575ab31ea80bf" diff --git a/projects/ArchR/packages/audio/libogg/package.mk b/projects/ArchR/packages/audio/libogg/package.mk new file mode 100644 index 0000000000..01052294e8 --- /dev/null +++ b/projects/ArchR/packages/audio/libogg/package.mk @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +. ${ROOT}/packages/audio/libogg/package.mk + +PKG_CMAKE_OPTS_TARGET="-DBUILD_SHARED_LIBS=ON \ + -DINSTALL_DOCS=OFF" diff --git a/projects/ArchR/packages/audio/libsndfile/package.mk b/projects/ArchR/packages/audio/libsndfile/package.mk new file mode 100644 index 0000000000..4fd0f4aeae --- /dev/null +++ b/projects/ArchR/packages/audio/libsndfile/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) 2021-present Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="libsndfile" +PKG_VERSION="e486f20" +PKG_LICENSE="LGPL-2.1-or-later" +PKG_SITE="https://libsndfile.github.io/libsndfile/" +PKG_URL="https://github.com/libsndfile/libsndfile/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain alsa-lib flac libogg libvorbis opus" +PKG_LONGDESC="A C library for reading and writing sound files containing sampled audio data." +PKG_BUILD_FLAGS="+pic" + +PKG_CMAKE_OPTS_TARGET="-DBUILD_PROGRAMS=OFF \ + -DBUILD_EXAMPLES=OFF \ + -DBUILD_REGTEST=OFF \ + -DBUILD_TESTING=OFF \ + -DENABLE_EXTERNAL_LIBS=ON \ + -DBUILD_SHARED_LIBS=ON + -DINSTALL_MANPAGES=OFF \ + -DINSTALL_PKGCONFIG_MODULE=ON" diff --git a/projects/ArchR/packages/audio/libsndfile/patches/libsndfile-add-required-static-libraries-to-pkg-config.patch b/projects/ArchR/packages/audio/libsndfile/patches/libsndfile-add-required-static-libraries-to-pkg-config.patch new file mode 100644 index 0000000000..e5220c098d --- /dev/null +++ b/projects/ArchR/packages/audio/libsndfile/patches/libsndfile-add-required-static-libraries-to-pkg-config.patch @@ -0,0 +1,10 @@ +--- a/sndfile.pc.in 2021-01-24 23:22:23.000000000 +1100 ++++ b/sndfile.pc.in 2021-09-12 14:30:47.763655089 +1000 +@@ -8,6 +8,6 @@ + Requires: + Requires.private: @EXTERNAL_XIPH_REQUIRE@ @EXTERNAL_MPEG_REQUIRE@ + Version: @VERSION@ +-Libs: -L${libdir} -lsndfile ++Libs: -L${libdir} -lsndfile -lFLAC -lvorbis -logg -lvorbisenc -lopus + Libs.private: @EXTERNAL_MPEG_LIBS@ + Cflags: -I${includedir} diff --git a/projects/ArchR/packages/audio/libvorbis/package.mk b/projects/ArchR/packages/audio/libvorbis/package.mk new file mode 100644 index 0000000000..3ea1e65d24 --- /dev/null +++ b/projects/ArchR/packages/audio/libvorbis/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) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libvorbis" +PKG_VERSION="1.3.7" +PKG_SHA256="b33cc4934322bcbf6efcbacf49e3ca01aadbea4114ec9589d1b1e9d20f72954b" +PKG_LICENSE="BSD" +PKG_SITE="http://www.vorbis.com/" +PKG_URL="http://downloads.xiph.org/releases/vorbis/libvorbis-${PKG_VERSION}.tar.xz" +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="--with-ogg=${SYSROOT_PREFIX}/usr \ + --disable-docs \ + --disable-examples \ + --disable-oggtest" diff --git a/projects/ArchR/packages/audio/libxmp/package.mk b/projects/ArchR/packages/audio/libxmp/package.mk new file mode 100644 index 0000000000..ddf4b979b3 --- /dev/null +++ b/projects/ArchR/packages/audio/libxmp/package.mk @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="libxmp" +PKG_VERSION="8201d26cf933688a8be64292457c429fd8e654ab" #v4.6.0 +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/libxmp/libxmp" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Libxmp is a library that renders module files to PCM data." +PKG_TOOLCHAIN="cmake" + +PKG_CMAKE_OPTS_TARGET="-DCMAKE_POLICY_VERSION_MINIMUM=3.5" diff --git a/projects/ArchR/packages/audio/pipewire/package.mk b/projects/ArchR/packages/audio/pipewire/package.mk new file mode 100644 index 0000000000..b272aa0967 --- /dev/null +++ b/projects/ArchR/packages/audio/pipewire/package.mk @@ -0,0 +1,99 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="pipewire" +PKG_VERSION="1.2.6" +PKG_LICENSE="LGPL" +PKG_SITE="https://pipewire.org" +PKG_URL="https://github.com/PipeWire/pipewire/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain libpthread-stubs dbus ncurses alsa-lib pulseaudio systemd libsndfile libusb" +PKG_LONGDESC="PipeWire is a server and user space API to deal with multimedia pipeline" +PKG_PATCH_DIRS+=" ${DEVICE}" + +if [ "${BLUETOOTH_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" bluez sbc ldacBT libfreeaptx fdk-aac" + PKG_PIPEWIRE_BLUETOOTH="-Dbluez5=enabled \ + -Dbluez5-backend-hsp-native=disabled \ + -Dbluez5-backend-hfp-native=disabled \ + -Dbluez5-backend-ofono=disabled \ + -Dbluez5-backend-hsphfpd=disabled \ + -Dbluez5-codec-aptx=enabled \ + -Dbluez5-codec-lc3plus=disabled \ + -Dbluez5-codec-ldac=enabled \ + -Dbluez5-codec-aac=enabled" +else + PKG_PIPEWIRE_BLUETOOTH="-Dbluez5=disabled" +fi + +if [ "${VULKAN_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" vulkan-loader vulkan-headers" + PKG_PIPEWIRE_VULKAN+="-Dvulkan=enabled \ + -Dx11=disabled \ + -Dx11-xfixes=disabled" +fi + +PKG_MESON_OPTS_TARGET="-Ddocs=disabled \ + -Dexamples=disabled \ + -Dman=disabled \ + -Dtests=disabled \ + -Dinstalled_tests=disabled \ + -Dgstreamer=disabled \ + -Dgstreamer-device-provider=disabled \ + -Dsystemd=enabled \ + -Dsystemd-system-service=enabled \ + -Dsystemd-user-service=disabled \ + -Dpipewire-alsa=enabled \ + -Dpipewire-jack=disabled \ + -Dpipewire-v4l2=disabled \ + -Djack-devel=false + -Dspa-plugins=enabled \ + -Dalsa=enabled \ + -Daudiomixer=enabled \ + -Daudioconvert=enabled \ + ${PKG_PIPEWIRE_BLUETOOTH} \ + -Dcontrol=enabled \ + -Daudiotestsrc=disabled \ + -Dffmpeg=disabled \ + -Djack=disabled \ + -Dsupport=enabled \ + -Devl=disabled \ + -Dtest=disabled \ + -Dv4l2=disabled \ + -Ddbus=enabled \ + -Dlibcamera=disabled \ + -Dvideoconvert=disabled \ + -Dvideotestsrc=disabled \ + -Dvolume=enabled \ + ${PKG_PIPEWIRE_VULKAN} \ + -Dpw-cat=enabled \ + -Dudev=enabled \ + -Dudevrulesdir=/usr/lib/udev/rules.d \ + -Dsdl2=disabled \ + -Dsndfile=enabled \ + -Dlibpulse=enabled \ + -Droc=disabled \ + -Davahi=disabled \ + -Decho-cancel-webrtc=disabled \ + -Dlibusb=enabled \ + -Dsession-managers=[] \ + -Draop=disabled \ + -Dlv2=disabled \ + -Dlibcanberra=disabled \ + -Dlegacy-rtkit=false" + +pre_configure_target() { + export TARGET_CFLAGS="${TARGET_CFLAGS} -Wno-error=float-conversion" + export TARGET_LDFLAGS="${TARGET_LDFLAGS} -lncursesw -ltinfow" +} + +post_install() { + add_user pipewire x 982 980 "pipewire-daemon" "/var/run/pipewire" "/bin/sh" + add_group pipewire 980 + mkdir -p ${INSTALL}/etc/alsa/conf.d + ln -sf /usr/share/alsa/alsa.conf.d/50-pipewire.conf ${INSTALL}/etc/alsa/conf.d/50-pipewire.conf + ln -sf /usr/share/alsa/alsa.conf.d/99-pipewire-default.conf ${INSTALL}/etc/alsa/conf.d/99-pipewire-default.conf + enable_service pipewire.socket + enable_service pipewire.service + enable_service pipewire-pulse.socket + enable_service pipewire-pulse.service +} diff --git a/projects/ArchR/packages/audio/pipewire/patches/001-pipewire-pulse.patch b/projects/ArchR/packages/audio/pipewire/patches/001-pipewire-pulse.patch new file mode 100644 index 0000000000..bb7a5af626 --- /dev/null +++ b/projects/ArchR/packages/audio/pipewire/patches/001-pipewire-pulse.patch @@ -0,0 +1,66 @@ +diff -rupN pipewire-1.0.0.orig/src/daemon/pipewire-pulse.conf.in pipewire-1.0.0/src/daemon/pipewire-pulse.conf.in +--- pipewire-1.0.0.orig/src/daemon/pipewire-pulse.conf.in 2023-12-29 13:41:35.329947857 +0000 ++++ pipewire-1.0.0/src/daemon/pipewire-pulse.conf.in 2023-12-29 13:41:46.850669838 +0000 +@@ -92,11 +92,11 @@ pulse.properties = { + #"tcp:[::]:9999" # IPv6 on all addresses + #"tcp:127.0.0.1:8888" # IPv4 on a single address + # +- #{ address = "tcp:4713" # address +- # max-clients = 64 # maximum number of clients +- # listen-backlog = 32 # backlog in the server listen queue +- # client.access = "restricted" # permissions for clients +- #} ++ { address = "tcp:127.0.0.1:4713" # address ++ max-clients = 64 # maximum number of clients ++ listen-backlog = 32 # backlog in the server listen queue ++ client.access = "allowed" # permissions for clients ++ } + ] + #server.dbus-name = "org.pulseaudio.Server" + #pulse.min.req = 128/48000 # 2.7ms +diff -rupN pipewire-1.0.0.orig/src/daemon/systemd/system/pipewire.service.in pipewire-1.0.0/src/daemon/systemd/system/pipewire.service.in +--- pipewire-1.0.0.orig/src/daemon/systemd/system/pipewire.service.in 2023-12-29 13:41:35.329947857 +0000 ++++ pipewire-1.0.0/src/daemon/systemd/system/pipewire.service.in 2023-12-29 13:43:32.217227049 +0000 +@@ -21,15 +21,25 @@ NoNewPrivileges=yes + RestrictNamespaces=yes + SystemCallArchitectures=native + SystemCallFilter=@system-service ++Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/dbus/system_bus_socket ++User=root + Type=simple + AmbientCapabilities=CAP_SYS_NICE +-ExecStart=@PW_BINARY@ ++ExecStart=/usr/bin/pipewire + Restart=on-failure + RuntimeDirectory=pipewire + RuntimeDirectoryPreserve=yes +-User=pipewire + Environment=PIPEWIRE_RUNTIME_DIR=%t/pipewire ++# Add if you need debugging ++# Environment=PIPEWIRE_DEBUG=4 ++ ++# These hardcoded runtime and dbus paths must stay this way for a system service ++# as the User= is not resolved here 8( ++## NOTE we do not change PIPEWIRE_RUNTIME_DIR as this is the system socket dir... ++Environment=XDG_RUNTIME_DIR=/var/run/0-runtime-dir ++Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/dbus/system_bus_socket ++Environment=HOME=/storage + + [Install] +-Also=pipewire.socket pipewire-manager.socket ++Also=pipewire.socket pipewire-pulse.socket pipewire-manager.socket + WantedBy=default.target +diff -rupN pipewire-1.0.0.orig/src/daemon/systemd/system/pipewire.socket pipewire-1.0.0/src/daemon/systemd/system/pipewire.socket +--- pipewire-1.0.0.orig/src/daemon/systemd/system/pipewire.socket 2023-12-29 13:41:35.329947857 +0000 ++++ pipewire-1.0.0/src/daemon/systemd/system/pipewire.socket 2023-12-29 13:44:04.291208172 +0000 +@@ -4,8 +4,8 @@ Description=PipeWire Multimedia System S + [Socket] + Priority=6 + ListenStream=%t/pipewire/pipewire-0 +-SocketUser=pipewire +-SocketGroup=pipewire ++SocketUser=root ++SocketGroup=root + SocketMode=0660 + + [Install] diff --git a/projects/ArchR/packages/audio/pipewire/patches/SDM845/001-increase-pulse-buffer-size.patch b/projects/ArchR/packages/audio/pipewire/patches/SDM845/001-increase-pulse-buffer-size.patch new file mode 100644 index 0000000000..e4c8cdb343 --- /dev/null +++ b/projects/ArchR/packages/audio/pipewire/patches/SDM845/001-increase-pulse-buffer-size.patch @@ -0,0 +1,20 @@ +diff --git a/src/daemon/pipewire-pulse.conf.in b/src/daemon/pipewire-pulse.conf.in +index 0d54cf9b90..bdea2ca072 100644 +--- a/src/daemon/pipewire-pulse.conf.in ++++ b/src/daemon/pipewire-pulse.conf.in +@@ -102,12 +102,12 @@ pulse.properties = { + ] + #server.dbus-name = "org.pulseaudio.Server" + #pulse.allow-module-loading = true +- #pulse.min.req = 128/48000 # 2.7ms ++ pulse.min.req = 960/48000 # 20ms + #pulse.default.req = 960/48000 # 20 milliseconds +- #pulse.min.frag = 128/48000 # 2.7ms ++ pulse.min.frag = 960/48000 # 20ms + #pulse.default.frag = 96000/48000 # 2 seconds + #pulse.default.tlength = 96000/48000 # 2 seconds +- #pulse.min.quantum = 128/48000 # 2.7ms ++ pulse.min.quantum = 960/48000 # 20ms + #pulse.idle.timeout = 0 # don't pause after underruns + #pulse.default.format = F32 + #pulse.default.position = [ FL FR ] diff --git a/projects/ArchR/packages/audio/pipewire/patches/SM8250/000-increase-buffer.patch b/projects/ArchR/packages/audio/pipewire/patches/SM8250/000-increase-buffer.patch new file mode 100644 index 0000000000..74d57d7292 --- /dev/null +++ b/projects/ArchR/packages/audio/pipewire/patches/SM8250/000-increase-buffer.patch @@ -0,0 +1,28 @@ +diff -rupbN pipewire.orig/src/daemon/pipewire-pulse.conf.in pipewire/src/daemon/pipewire-pulse.conf.in +--- pipewire.orig/src/daemon/pipewire-pulse.conf.in 2024-10-08 04:01:35.119453036 +0000 ++++ pipewire/src/daemon/pipewire-pulse.conf.in 2024-10-08 04:03:35.898636383 +0000 +@@ -27,7 +27,7 @@ context.modules = [ + { name = libpipewire-module-rt + args = { + nice.level = -11 +- #rt.prio = @rtprio_client@ ++ rt.prio = 99 + #rt.time.soft = -1 + #rt.time.hard = -1 + #uclamp.min = 0 +@@ -102,12 +102,12 @@ pulse.properties = { + ] + #server.dbus-name = "org.pulseaudio.Server" + #pulse.allow-module-loading = true +- #pulse.min.req = 128/48000 # 2.7ms ++ pulse.min.req = 1024/48000 # 2.7ms + #pulse.default.req = 960/48000 # 20 milliseconds +- #pulse.min.frag = 128/48000 # 2.7ms ++ pulse.min.frag = 1024/48000 # 2.7ms + #pulse.default.frag = 96000/48000 # 2 seconds + #pulse.default.tlength = 96000/48000 # 2 seconds +- #pulse.min.quantum = 128/48000 # 2.7ms ++ pulse.min.quantum = 1024/48000 # 2.7ms + #pulse.idle.timeout = 0 # don't pause after underruns + #pulse.default.format = F32 + #pulse.default.position = [ FL FR ] diff --git a/projects/ArchR/packages/audio/pipewire/patches/SM8550/001-increase-pulse-buffer-size.patch b/projects/ArchR/packages/audio/pipewire/patches/SM8550/001-increase-pulse-buffer-size.patch new file mode 100644 index 0000000000..e4c8cdb343 --- /dev/null +++ b/projects/ArchR/packages/audio/pipewire/patches/SM8550/001-increase-pulse-buffer-size.patch @@ -0,0 +1,20 @@ +diff --git a/src/daemon/pipewire-pulse.conf.in b/src/daemon/pipewire-pulse.conf.in +index 0d54cf9b90..bdea2ca072 100644 +--- a/src/daemon/pipewire-pulse.conf.in ++++ b/src/daemon/pipewire-pulse.conf.in +@@ -102,12 +102,12 @@ pulse.properties = { + ] + #server.dbus-name = "org.pulseaudio.Server" + #pulse.allow-module-loading = true +- #pulse.min.req = 128/48000 # 2.7ms ++ pulse.min.req = 960/48000 # 20ms + #pulse.default.req = 960/48000 # 20 milliseconds +- #pulse.min.frag = 128/48000 # 2.7ms ++ pulse.min.frag = 960/48000 # 20ms + #pulse.default.frag = 96000/48000 # 2 seconds + #pulse.default.tlength = 96000/48000 # 2 seconds +- #pulse.min.quantum = 128/48000 # 2.7ms ++ pulse.min.quantum = 960/48000 # 20ms + #pulse.idle.timeout = 0 # don't pause after underruns + #pulse.default.format = F32 + #pulse.default.position = [ FL FR ] diff --git a/projects/ArchR/packages/audio/pipewire/patches/SM8550/002-increase-pipewire-buffer-size.patch b/projects/ArchR/packages/audio/pipewire/patches/SM8550/002-increase-pipewire-buffer-size.patch new file mode 100644 index 0000000000..cb77ba5f20 --- /dev/null +++ b/projects/ArchR/packages/audio/pipewire/patches/SM8550/002-increase-pipewire-buffer-size.patch @@ -0,0 +1,13 @@ +diff --git a/src/daemon/pipewire.conf.in b/src/daemon/pipewire.conf.in +index 0d54cf9b90..bdea2ca072 100644 +--- a/src/daemon/pipewire.conf.in ++++ b/src/daemon/pipewire.conf.in +@@ -43,7 +43,7 @@ context.properties = { + #default.clock.rate = 48000 + #default.clock.allowed-rates = [ 48000 ] + #default.clock.quantum = 1024 +- #default.clock.min-quantum = 32 ++ default.clock.min-quantum = 960 + #default.clock.max-quantum = 2048 + #default.clock.quantum-limit = 8192 + #default.clock.quantum-floor = 4 diff --git a/projects/ArchR/packages/audio/pipewire/patches/SM8650/001-increase-pulse-buffer-size.patch b/projects/ArchR/packages/audio/pipewire/patches/SM8650/001-increase-pulse-buffer-size.patch new file mode 100644 index 0000000000..e4c8cdb343 --- /dev/null +++ b/projects/ArchR/packages/audio/pipewire/patches/SM8650/001-increase-pulse-buffer-size.patch @@ -0,0 +1,20 @@ +diff --git a/src/daemon/pipewire-pulse.conf.in b/src/daemon/pipewire-pulse.conf.in +index 0d54cf9b90..bdea2ca072 100644 +--- a/src/daemon/pipewire-pulse.conf.in ++++ b/src/daemon/pipewire-pulse.conf.in +@@ -102,12 +102,12 @@ pulse.properties = { + ] + #server.dbus-name = "org.pulseaudio.Server" + #pulse.allow-module-loading = true +- #pulse.min.req = 128/48000 # 2.7ms ++ pulse.min.req = 960/48000 # 20ms + #pulse.default.req = 960/48000 # 20 milliseconds +- #pulse.min.frag = 128/48000 # 2.7ms ++ pulse.min.frag = 960/48000 # 20ms + #pulse.default.frag = 96000/48000 # 2 seconds + #pulse.default.tlength = 96000/48000 # 2 seconds +- #pulse.min.quantum = 128/48000 # 2.7ms ++ pulse.min.quantum = 960/48000 # 20ms + #pulse.idle.timeout = 0 # don't pause after underruns + #pulse.default.format = F32 + #pulse.default.position = [ FL FR ] diff --git a/projects/ArchR/packages/audio/pipewire/patches/SM8650/002-increase-pipewire-buffer-size.patch b/projects/ArchR/packages/audio/pipewire/patches/SM8650/002-increase-pipewire-buffer-size.patch new file mode 100644 index 0000000000..cb77ba5f20 --- /dev/null +++ b/projects/ArchR/packages/audio/pipewire/patches/SM8650/002-increase-pipewire-buffer-size.patch @@ -0,0 +1,13 @@ +diff --git a/src/daemon/pipewire.conf.in b/src/daemon/pipewire.conf.in +index 0d54cf9b90..bdea2ca072 100644 +--- a/src/daemon/pipewire.conf.in ++++ b/src/daemon/pipewire.conf.in +@@ -43,7 +43,7 @@ context.properties = { + #default.clock.rate = 48000 + #default.clock.allowed-rates = [ 48000 ] + #default.clock.quantum = 1024 +- #default.clock.min-quantum = 32 ++ default.clock.min-quantum = 960 + #default.clock.max-quantum = 2048 + #default.clock.quantum-limit = 8192 + #default.clock.quantum-floor = 4 diff --git a/projects/ArchR/packages/audio/pipewire/system.d/pipewire-pulse.service b/projects/ArchR/packages/audio/pipewire/system.d/pipewire-pulse.service new file mode 100644 index 0000000000..29e21a8c92 --- /dev/null +++ b/projects/ArchR/packages/audio/pipewire/system.d/pipewire-pulse.service @@ -0,0 +1,23 @@ +[Unit] +Description=PipeWire PulseAudio Service +Requires=pipewire-pulse.socket +After=pipewire.service wireplumber.service +RequiresMountsFor=/storage + +[Service] +User=root +Type=simple +ExecStart=/usr/bin/pipewire-pulse +Restart=on-failure +RuntimeDirectory=pipewire +RuntimeDirectoryPreserve=yes +ExecStartPre=/bin/mkdir -p /var/run/0-runtime-dir/pulse +Environment=PIPEWIRE_RUNTIME_DIR=%t/pipewire +Environment=XDG_RUNTIME_DIR=/var/run/0-runtime-dir +Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/dbus/system_bus_socket +Environment=HOME=/storage +# Environment=PIPEWIRE_DEBUG=4 + +[Install] +Also=pipewire-pulse.socket +WantedBy=default.target diff --git a/projects/ArchR/packages/audio/pipewire/system.d/pipewire-pulse.socket b/projects/ArchR/packages/audio/pipewire/system.d/pipewire-pulse.socket new file mode 100644 index 0000000000..d27fb0e261 --- /dev/null +++ b/projects/ArchR/packages/audio/pipewire/system.d/pipewire-pulse.socket @@ -0,0 +1,10 @@ +[Unit] +Description=PipeWire PulseAudio +Conflicts=pulseaudio.socket + +[Socket] +Priority=6 +ListenStream=%t/pulse/native + +[Install] +WantedBy=sockets.target diff --git a/projects/ArchR/packages/audio/pulseaudio/config/pulse-daemon.conf.d/README b/projects/ArchR/packages/audio/pulseaudio/config/pulse-daemon.conf.d/README new file mode 100644 index 0000000000..350761ed58 --- /dev/null +++ b/projects/ArchR/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/projects/ArchR/packages/audio/pulseaudio/config/system.pa b/projects/ArchR/packages/audio/pulseaudio/config/system.pa new file mode 100644 index 0000000000..653361e807 --- /dev/null +++ b/projects/ArchR/packages/audio/pulseaudio/config/system.pa @@ -0,0 +1,59 @@ +#!/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 +load-module module-native-protocol-unix + +### Automatically restore the volume of streams and devices +load-module module-stream-restore +load-module module-device-restore +load-module module-card-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 + +### 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 + +### 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/projects/ArchR/packages/audio/pulseaudio/package.mk b/projects/ArchR/packages/audio/pulseaudio/package.mk new file mode 100644 index 0000000000..738045dc51 --- /dev/null +++ b/projects/ArchR/packages/audio/pulseaudio/package.mk @@ -0,0 +1,90 @@ +# 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="17.0" +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 libcap libsndfile libtool soxr speexdsp glib:host glib" +PKG_LONGDESC="PulseAudio is a sound system for POSIX OSes, meaning that it is a proxy for your sound applications." + +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="-Ddaemon=false \ + -Ddoxygen=false \ + -Dgcov=false \ + -Dman=false \ + -Dtests=false \ + -Dsystem_user=root \ + -Dsystem_group=root \ + -Daccess_group=root \ + -Ddatabase=simple \ + -Dlegacy-database-entry-format=false \ + -Dstream-restore-clear-old-devices=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=disabled \ + -Dasyncns=disabled \ + ${PKG_PULSEAUDIO_AVAHI} \ + -Dbluez5=disabled + -Dbluez5-gstreamer=disabled \ + -Ddbus=disabled \ + -Delogind=disabled \ + -Dfftw=disabled \ + -Dglib=enabled \ + -Dgsettings=disabled \ + -Dgstreamer=disabled \ + -Dgtk=disabled \ + -Dhal-compat=false \ + -Dipv6=true \ + -Djack=disabled \ + -Dlirc=disabled \ + -Dopenssl=disabled \ + -Dorc=disabled \ + -Doss-output=disabled \ + -Dsamplerate=disabled \ + -Dsoxr=enabled \ + -Dspeex=enabled \ + -Dsystemd=disabled \ + -Dtcpwrap=disabled \ + -Dudev=disabled \ + -Dvalgrind=disabled \ + -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 +} + +post_makeinstall_target() { + safe_remove ${INSTALL}/usr/include + safe_remove ${INSTALL}/usr/lib/cmake + safe_remove ${INSTALL}/usr/lib/pkgconfig + 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/ + + # Sometimes apps cannot load `libpulsecommon`. It is located in ${libdir}/pulseaudio and is not intended to be loaded directly. + # Application loads `libpulse.so.0`, `libpulse` has `libpulsecommon` as a dep and RPATH set to ${libdir}/pulseaudio + # So, if there is error loading `libpulsecommon`, check RPATH of `libpulse` and `libpulse-simple` + # Adding pulseaudio subdir to `/etc/ld.so.conf.d/*.conf` may be a working hack for that, but please check/fix RPATH first +} + +# Deprecated by pipewire +#post_install() { +# enable_service pulseaudio.service +#} diff --git a/projects/ArchR/packages/audio/pulseaudio/patches/pulseaudio-100.01-never-append-dirty-to-server-module-version.patch b/projects/ArchR/packages/audio/pulseaudio/patches/pulseaudio-100.01-never-append-dirty-to-server-module-version.patch new file mode 100644 index 0000000000..8bea8d95fb --- /dev/null +++ b/projects/ArchR/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/projects/ArchR/packages/audio/pulseaudio/patches/pulseaudio-100.02-check_uid.patch b/projects/ArchR/packages/audio/pulseaudio/patches/pulseaudio-100.02-check_uid.patch new file mode 100644 index 0000000000..df92750890 --- /dev/null +++ b/projects/ArchR/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/projects/ArchR/packages/audio/sndio/package.mk b/projects/ArchR/packages/audio/sndio/package.mk new file mode 100644 index 0000000000..673f7226dd --- /dev/null +++ b/projects/ArchR/packages/audio/sndio/package.mk @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2026-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="sndio" +PKG_VERSION="1.10.0" +PKG_LICENSE="GPLv3" +PKG_SITE="https://sndio.org/" +PKG_URL="${PKG_SITE}/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain alsa-lib" +PKG_LONGDESC="Sndio is a small audio and MIDI framework" +PKG_BUILD_FLAGS="+pic" +PKG_TOOLCHAIN="configure" + +configure_target() { + cd ${PKG_BUILD} + ./configure \ + --prefix=/usr \ + --enable-static +} + +make_target() { + make +} + +makeinstall_target() { + make DESTDIR=${SYSROOT_PREFIX} install +} diff --git a/projects/ArchR/packages/audio/wavpack/package.mk b/projects/ArchR/packages/audio/wavpack/package.mk new file mode 100644 index 0000000000..cea5cde12e --- /dev/null +++ b/projects/ArchR/packages/audio/wavpack/package.mk @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +. ${ROOT}/packages/audio/wavpack/package.mk + +PKG_CMAKE_OPTS_TARGET+=" -DBUILD_SHARED_LIBS=ON" diff --git a/projects/ArchR/packages/audio/wireplumber/package.mk b/projects/ArchR/packages/audio/wireplumber/package.mk new file mode 100644 index 0000000000..c6a4cc7360 --- /dev/null +++ b/projects/ArchR/packages/audio/wireplumber/package.mk @@ -0,0 +1,97 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="wireplumber" +PKG_VERSION="0.5.7" +PKG_LICENSE="MIT" +PKG_SITE="https://gitlab.freedesktop.org/pipewire/wireplumber" +PKG_URL="https://gitlab.freedesktop.org/pipewire/wireplumber/-/archive/${PKG_VERSION}/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="pipewire glib lua54 glib:host" +PKG_LONGDESC="Session / policy manager implementation for PipeWire" + +PKG_MESON_OPTS_TARGET="-Dintrospection=disabled \ + -Ddoc=disabled \ + -Dsystem-lua=true \ + -Delogind=disabled \ + -Dsystemd=enabled \ + -Dsystemd-system-service=true \ + -Dsystemd-user-service=false \ + -Dsystemd-system-unit-dir=/usr/lib/systemd/system \ + -Dtests=false" + +post_makeinstall_target() { + # connect to the system bus + sed '/^\[Service\]/a Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/dbus/system_bus_socket' -i ${INSTALL}/usr/lib/systemd/system/wireplumber.service + + # ref https://gitlab.freedesktop.org/pipewire/wireplumber/-/commit/0da29f38181e391160fa8702623050b8544ec775 + # ref https://github.com/PipeWire/wireplumber/blob/master/docs/rst/daemon/configuration/migration.rst + # ref https://github.com/PipeWire/wireplumber/blob/master/docs/rst/daemon/configuration/features.rst + cat >${INSTALL}/usr/share/wireplumber/wireplumber.conf.d/89-disable-session-dbus-dependent-features.conf <${INSTALL}/usr/share/wireplumber/wireplumber.conf.d/89-disable-v4l2.conf <${INSTALL}/usr/share/wireplumber/wireplumber.conf.d/89-disable-bluez-hfphsp-backend.conf < ${INSTALL}/usr/share/wireplumber/wireplumber.conf.d/89-disable-libcamera.conf << EOF +wireplumber.profiles = { + main = { + monitor.libcamera = disabled + } +} +EOF + + cat >${INSTALL}/usr/share/wireplumber/wireplumber.conf.d/89-bluez-auto-connect.conf </dev/null 2>&1 + rsync -al ${LIBROOT}/usr/lib32/* ${INSTALL}/usr/lib32 >/dev/null 2>&1 + mkdir -p ${INSTALL}/usr/lib + ln -s /usr/lib32/${LDSO} ${INSTALL}/usr/lib/${LDSO} + + mkdir -p "${INSTALL}/etc/ld.so.conf.d" + echo "/usr/lib32" > "${INSTALL}/etc/ld.so.conf.d/${LIBARCH}-lib32.conf" + + mkdir -p ${INSTALL}/usr/bin + cp ${LIBROOT}/usr/bin/ldd ${INSTALL}/usr/bin/ldd32 +} diff --git a/projects/ArchR/packages/compat/wine/package.mk b/projects/ArchR/packages/compat/wine/package.mk new file mode 100644 index 0000000000..e62e8bd152 --- /dev/null +++ b/projects/ArchR/packages/compat/wine/package.mk @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024-present JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="wine" +PKG_VERSION="11.0" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/Kron4ek/Wine-Builds" +PKG_URL="${PKG_SITE}/releases/download/${PKG_VERSION}/wine-${PKG_VERSION}-amd64.tar.xz" + +PKG_DEPENDS_TARGET="toolchain libXcomposite libXdmcp cups" +PKG_LONGDESC="Wine is a compatibility layer capable of running Windows applications" +PKG_TOOLCHAIN="manual" +PKG_WINE_TRICKS="https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks" + +unpack() { + mkdir -p ${PKG_BUILD} + tar --strip-components=1 -xf ${SOURCES}/${PKG_NAME}/${PKG_NAME}-${PKG_VERSION}.tar.xz -C ${PKG_BUILD} +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp -rf ${PKG_BUILD}/bin/* ${INSTALL}/usr/bin + + mkdir -p ${INSTALL}/usr/lib + cp -rf ${PKG_BUILD}/lib/* ${INSTALL}/usr/lib + + mkdir -p ${INSTALL}/usr/share + cp -rf ${PKG_BUILD}/share/* ${INSTALL}/usr/share + + curl -Lo ${INSTALL}/usr/bin/winetricks ${PKG_WINE_TRICKS} + + chmod +x ${INSTALL}/usr/bin/* +} diff --git a/projects/ArchR/packages/compress/cabextract/package.mk b/projects/ArchR/packages/compress/cabextract/package.mk new file mode 100644 index 0000000000..7a56ce59c7 --- /dev/null +++ b/projects/ArchR/packages/compress/cabextract/package.mk @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="cabextract" +PKG_VERSION="1.11" +PKG_LICENSE="GPLv3" +PKG_SITE="https://www.cabextract.org.uk" +PKG_URL="https://github.com/archr-linux/packages/raw/main/cabextract.tar.xz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="cabextract is Free Software for extracting Microsoft cabinet file" +PKG_TOOLCHAIN="make" + +make_target() { + : +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + mkdir -p ${INSTALL}/usr/lib + + cp -rf ${PKG_BUILD}/usr/bin/* ${INSTALL}/usr/bin + cp -rf ${PKG_BUILD}/usr/lib/* ${INSTALL}/usr/lib + + chmod +x ${INSTALL}/usr/bin/* +} diff --git a/projects/ArchR/packages/compress/gzip/package.mk b/projects/ArchR/packages/compress/gzip/package.mk new file mode 100644 index 0000000000..6e0bced369 --- /dev/null +++ b/projects/ArchR/packages/compress/gzip/package.mk @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="gzip" +PKG_VERSION="1.13" +PKG_LICENSE="GPL" +PKG_SITE="https://mirrors.kernel.org/gnu/gzip" +PKG_URL="https://mirrors.kernel.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." + +# For some weird reason gzip wrappers default to /bin/dash which we don't have +CONFIG_SHELL=/bin/bash +PKG_CONFIGURE_OPTS_TARGET=" CONFIG_SHELL=/bin/bash" diff --git a/projects/ArchR/packages/compress/libarchive/package.mk b/projects/ArchR/packages/compress/libarchive/package.mk new file mode 100644 index 0000000000..3961a47084 --- /dev/null +++ b/projects/ArchR/packages/compress/libarchive/package.mk @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +. ${ROOT}/packages/compress/libarchive/package.mk + +PKG_CMAKE_OPTS_TARGET="${PKG_CMAKE_OPTS_TARGET/-DBUILD_SHARED_LIBS=OFF/-DBUILD_SHARED_LIBS=ON}" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib + cp -rf libarchive/libarchive.so* ${INSTALL}/usr/lib + + mkdir -p ${SYSROOT_PREFIX}/usr/lib + cp -rf libarchive/libarchive.so* ${SYSROOT_PREFIX}/usr/lib + + mkdir -p ${SYSROOT_PREFIX}/usr/lib/pkgconfig + cp build/pkgconfig/libarchive.pc ${SYSROOT_PREFIX}/usr/lib/pkgconfig + + mkdir -p ${SYSROOT_PREFIX}/usr/include + cp ${PKG_BUILD}/libarchive/{archive.h,archive_entry.h} ${SYSROOT_PREFIX}/usr/include +} diff --git a/projects/ArchR/packages/compress/libzip/package.mk b/projects/ArchR/packages/compress/libzip/package.mk new file mode 100644 index 0000000000..7fe44ce691 --- /dev/null +++ b/projects/ArchR/packages/compress/libzip/package.mk @@ -0,0 +1,11 @@ +# 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="1.11.1" +PKG_LICENSE="GPL" +PKG_SITE="https://libzip.org/download" +PKG_URL="${PKG_SITE}/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain zlib gnutls openssl" +PKG_LONGDESC="A C library for reading, creating, and modifying zip archives." diff --git a/projects/ArchR/packages/compress/p7zip/package.mk b/projects/ArchR/packages/compress/p7zip/package.mk new file mode 100644 index 0000000000..cabab8410b --- /dev/null +++ b/projects/ArchR/packages/compress/p7zip/package.mk @@ -0,0 +1,44 @@ +# 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="ccache:host" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="p7zip is a port of 7za.exe for POSIX systems like Unix." +PKG_TOOLCHAIN="manual" + +pre_build_host() { + rm -fr ${PKG_BUILD}/.${HOST_NAME} + mkdir -p ${PKG_BUILD}/.${HOST_NAME} + cp -RP ${PKG_BUILD}/* ${PKG_BUILD}/.${HOST_NAME} +} + +make_host() { + make CXX=${CXX} CC=${CC} -C ${PKG_BUILD}/.${HOST_NAME} 7za +} + +makeinstall_host() { + mkdir -p ${TOOLCHAIN}/bin + cp ${PKG_BUILD}/.${HOST_NAME}/bin/7za ${TOOLCHAIN}/bin +} + +pre_build_target() { + rm -fr ${PKG_BUILD}/.${TARGET_NAME} + mkdir -p ${PKG_BUILD}/.${TARGET_NAME} + cp -RP ${PKG_BUILD}/* ${PKG_BUILD}/.${TARGET_NAME} +} + +make_target() { + make CXX=${CXX} CC=${CC} -C ${PKG_BUILD}/.${TARGET_NAME} all3 +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp -pr ${PKG_BUILD}/.${TARGET_NAME}/bin/Codecs ${INSTALL}/usr/bin + cp -p ${PKG_BUILD}/.${TARGET_NAME}/bin/7z* ${INSTALL}/usr/bin +} diff --git a/projects/ArchR/packages/compress/p7zip/patches/p7zip-0100-CVE-2016-9296.patch b/projects/ArchR/packages/compress/p7zip/patches/p7zip-0100-CVE-2016-9296.patch new file mode 100644 index 0000000000..773f92a46e --- /dev/null +++ b/projects/ArchR/packages/compress/p7zip/patches/p7zip-0100-CVE-2016-9296.patch @@ -0,0 +1,12 @@ +--- ./CPP/7zip/Archive/7z/7zIn.cpp.orig 2016-11-21 01:42:29.460901230 +0000 ++++ ./CPP/7zip/Archive/7z/7zIn.cpp 2016-11-21 01:42:57.481197725 +0000 +@@ -1097,7 +1097,8 @@ HRESULT CInArchive::ReadAndDecodePackedS + if (CrcCalc(data, unpackSize) != folders.FolderCRCs.Vals[i]) + ThrowIncorrect(); + } +- HeadersSize += folders.PackPositions[folders.NumPackStreams]; ++ if (folders.PackPositions) ++ HeadersSize += folders.PackPositions[folders.NumPackStreams]; + return S_OK; + } + diff --git a/projects/ArchR/packages/compress/p7zip/patches/p7zip-0200-CVE-2017-17969.patch b/projects/ArchR/packages/compress/p7zip/patches/p7zip-0200-CVE-2017-17969.patch new file mode 100644 index 0000000000..ebc0ac93ef --- /dev/null +++ b/projects/ArchR/packages/compress/p7zip/patches/p7zip-0200-CVE-2017-17969.patch @@ -0,0 +1,26 @@ +From 79bca880ce7bcf07216c45f93afea545e0344418 Mon Sep 17 00:00:00 2001 +From: aone +Date: Mon, 5 Feb 2018 13:01:09 +0100 +Subject: [PATCH] Security fix CVE-2017-17969 + +--- + CPP/7zip/Compress/ShrinkDecoder.cpp | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/CPP/7zip/Compress/ShrinkDecoder.cpp b/CPP/7zip/Compress/ShrinkDecoder.cpp +index 80b7e67..5bb0559 100644 +--- a/CPP/7zip/Compress/ShrinkDecoder.cpp ++++ b/CPP/7zip/Compress/ShrinkDecoder.cpp +@@ -121,7 +121,12 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * + { + _stack[i++] = _suffixes[cur]; + cur = _parents[cur]; ++ if (cur >= kNumItems || i >= kNumItems) ++ break; + } ++ ++ if (cur >= kNumItems || i >= kNumItems) ++ break; + + _stack[i++] = (Byte)cur; + lastChar2 = (Byte)cur; diff --git a/projects/ArchR/packages/compress/p7zip/patches/p7zip-0300-CVE-2018-5996.patch b/projects/ArchR/packages/compress/p7zip/patches/p7zip-0300-CVE-2018-5996.patch new file mode 100644 index 0000000000..6733bff918 --- /dev/null +++ b/projects/ArchR/packages/compress/p7zip/patches/p7zip-0300-CVE-2018-5996.patch @@ -0,0 +1,221 @@ +From: Robert Luberda +Date: Sun, 28 Jan 2018 23:47:40 +0100 +Subject: CVE-2018-5996 + +Hopefully fix Memory Corruptions via RAR PPMd (CVE-2018-5996) by +applying a few changes from 7Zip 18.00-beta. + +Bug-Debian: https://bugs.debian.org/#888314 +--- + CPP/7zip/Compress/Rar1Decoder.cpp | 13 +++++++++---- + CPP/7zip/Compress/Rar1Decoder.h | 1 + + CPP/7zip/Compress/Rar2Decoder.cpp | 10 +++++++++- + CPP/7zip/Compress/Rar2Decoder.h | 1 + + CPP/7zip/Compress/Rar3Decoder.cpp | 23 ++++++++++++++++++++--- + CPP/7zip/Compress/Rar3Decoder.h | 2 ++ + 6 files changed, 42 insertions(+), 8 deletions(-) + +diff --git a/CPP/7zip/Compress/Rar1Decoder.cpp b/CPP/7zip/Compress/Rar1Decoder.cpp +index 1aaedcc..68030c7 100644 +--- a/CPP/7zip/Compress/Rar1Decoder.cpp ++++ b/CPP/7zip/Compress/Rar1Decoder.cpp +@@ -29,7 +29,7 @@ public: + }; + */ + +-CDecoder::CDecoder(): m_IsSolid(false) { } ++CDecoder::CDecoder(): m_IsSolid(false), _errorMode(false) { } + + void CDecoder::InitStructures() + { +@@ -406,9 +406,14 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * + InitData(); + if (!m_IsSolid) + { ++ _errorMode = false; + InitStructures(); + InitHuff(); + } ++ ++ if (_errorMode) ++ return S_FALSE; ++ + if (m_UnpackSize > 0) + { + GetFlagsBuf(); +@@ -477,9 +482,9 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) + { + try { return CodeReal(inStream, outStream, inSize, outSize, progress); } +- catch(const CInBufferException &e) { return e.ErrorCode; } +- catch(const CLzOutWindowException &e) { return e.ErrorCode; } +- catch(...) { return S_FALSE; } ++ catch(const CInBufferException &e) { _errorMode = true; return e.ErrorCode; } ++ catch(const CLzOutWindowException &e) { _errorMode = true; return e.ErrorCode; } ++ catch(...) { _errorMode = true; return S_FALSE; } + } + + STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size) +diff --git a/CPP/7zip/Compress/Rar1Decoder.h b/CPP/7zip/Compress/Rar1Decoder.h +index 630f089..01b606b 100644 +--- a/CPP/7zip/Compress/Rar1Decoder.h ++++ b/CPP/7zip/Compress/Rar1Decoder.h +@@ -39,6 +39,7 @@ public: + + Int64 m_UnpackSize; + bool m_IsSolid; ++ bool _errorMode; + + UInt32 ReadBits(int numBits); + HRESULT CopyBlock(UInt32 distance, UInt32 len); +diff --git a/CPP/7zip/Compress/Rar2Decoder.cpp b/CPP/7zip/Compress/Rar2Decoder.cpp +index b3f2b4b..0580c8d 100644 +--- a/CPP/7zip/Compress/Rar2Decoder.cpp ++++ b/CPP/7zip/Compress/Rar2Decoder.cpp +@@ -80,7 +80,8 @@ static const UInt32 kHistorySize = 1 << 20; + static const UInt32 kWindowReservSize = (1 << 22) + 256; + + CDecoder::CDecoder(): +- m_IsSolid(false) ++ m_IsSolid(false), ++ m_TablesOK(false) + { + } + +@@ -100,6 +101,8 @@ UInt32 CDecoder::ReadBits(unsigned numBits) { return m_InBitStream.ReadBits(numB + + bool CDecoder::ReadTables(void) + { ++ m_TablesOK = false; ++ + Byte levelLevels[kLevelTableSize]; + Byte newLevels[kMaxTableSize]; + m_AudioMode = (ReadBits(1) == 1); +@@ -170,6 +173,8 @@ bool CDecoder::ReadTables(void) + } + + memcpy(m_LastLevels, newLevels, kMaxTableSize); ++ m_TablesOK = true; ++ + return true; + } + +@@ -344,6 +349,9 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * + return S_FALSE; + } + ++ if (!m_TablesOK) ++ return S_FALSE; ++ + UInt64 startPos = m_OutWindowStream.GetProcessedSize(); + while (pos < unPackSize) + { +diff --git a/CPP/7zip/Compress/Rar2Decoder.h b/CPP/7zip/Compress/Rar2Decoder.h +index 3a0535c..0e9005f 100644 +--- a/CPP/7zip/Compress/Rar2Decoder.h ++++ b/CPP/7zip/Compress/Rar2Decoder.h +@@ -139,6 +139,7 @@ class CDecoder : + + UInt64 m_PackSize; + bool m_IsSolid; ++ bool m_TablesOK; + + void InitStructures(); + UInt32 ReadBits(unsigned numBits); +diff --git a/CPP/7zip/Compress/Rar3Decoder.cpp b/CPP/7zip/Compress/Rar3Decoder.cpp +index 3bf2513..6cb8a6a 100644 +--- a/CPP/7zip/Compress/Rar3Decoder.cpp ++++ b/CPP/7zip/Compress/Rar3Decoder.cpp +@@ -92,7 +92,8 @@ CDecoder::CDecoder(): + _writtenFileSize(0), + _vmData(0), + _vmCode(0), +- m_IsSolid(false) ++ m_IsSolid(false), ++ _errorMode(false) + { + Ppmd7_Construct(&_ppmd); + } +@@ -545,6 +546,9 @@ HRESULT CDecoder::ReadTables(bool &keepDecompressing) + return InitPPM(); + } + ++ TablesRead = false; ++ TablesOK = false; ++ + _lzMode = true; + PrevAlignBits = 0; + PrevAlignCount = 0; +@@ -606,6 +610,9 @@ HRESULT CDecoder::ReadTables(bool &keepDecompressing) + } + } + } ++ if (InputEofError()) ++ return S_FALSE; ++ + TablesRead = true; + + // original code has check here: +@@ -623,6 +630,9 @@ HRESULT CDecoder::ReadTables(bool &keepDecompressing) + RIF(m_LenDecoder.Build(&newLevels[kMainTableSize + kDistTableSize + kAlignTableSize])); + + memcpy(m_LastLevels, newLevels, kTablesSizesSum); ++ ++ TablesOK = true; ++ + return S_OK; + } + +@@ -824,7 +834,12 @@ HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress) + PpmEscChar = 2; + PpmError = true; + InitFilters(); ++ _errorMode = false; + } ++ ++ if (_errorMode) ++ return S_FALSE; ++ + if (!m_IsSolid || !TablesRead) + { + bool keepDecompressing; +@@ -838,6 +853,8 @@ HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress) + bool keepDecompressing; + if (_lzMode) + { ++ if (!TablesOK) ++ return S_FALSE; + RINOK(DecodeLZ(keepDecompressing)) + } + else +@@ -901,8 +918,8 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream + _unpackSize = outSize ? *outSize : (UInt64)(Int64)-1; + return CodeReal(progress); + } +- catch(const CInBufferException &e) { return e.ErrorCode; } +- catch(...) { return S_FALSE; } ++ catch(const CInBufferException &e) { _errorMode = true; return e.ErrorCode; } ++ catch(...) { _errorMode = true; return S_FALSE; } + // CNewException is possible here. But probably CNewException is caused + // by error in data stream. + } +diff --git a/CPP/7zip/Compress/Rar3Decoder.h b/CPP/7zip/Compress/Rar3Decoder.h +index c130cec..2f72d7d 100644 +--- a/CPP/7zip/Compress/Rar3Decoder.h ++++ b/CPP/7zip/Compress/Rar3Decoder.h +@@ -192,6 +192,7 @@ class CDecoder: + UInt32 _lastFilter; + + bool m_IsSolid; ++ bool _errorMode; + + bool _lzMode; + bool _unsupportedFilter; +@@ -200,6 +201,7 @@ class CDecoder: + UInt32 PrevAlignCount; + + bool TablesRead; ++ bool TablesOK; + + CPpmd7 _ppmd; + int PpmEscChar; diff --git a/projects/ArchR/packages/compress/p7zip/patches/p7zip-0400-CVE-2018-10115.patch b/projects/ArchR/packages/compress/p7zip/patches/p7zip-0400-CVE-2018-10115.patch new file mode 100644 index 0000000000..7d9c4bf81f --- /dev/null +++ b/projects/ArchR/packages/compress/p7zip/patches/p7zip-0400-CVE-2018-10115.patch @@ -0,0 +1,311 @@ +From: Robert Luberda +Date: Tue, 29 May 2018 23:59:09 +0200 +Subject: Fix CVE-2018-10115 + +Apply "patch" taken from https://landave.io/files/patch_7zip_CVE-2018-10115.txt + + +Bugs-Debian: https://bugs.debian.org/897674 +--- + CPP/7zip/Compress/Rar1Decoder.cpp | 16 +++++++++++----- + CPP/7zip/Compress/Rar1Decoder.h | 3 ++- + CPP/7zip/Compress/Rar2Decoder.cpp | 17 +++++++++++++---- + CPP/7zip/Compress/Rar2Decoder.h | 3 ++- + CPP/7zip/Compress/Rar3Decoder.cpp | 19 +++++++++++++++---- + CPP/7zip/Compress/Rar3Decoder.h | 3 ++- + CPP/7zip/Compress/Rar5Decoder.cpp | 8 ++++++++ + CPP/7zip/Compress/Rar5Decoder.h | 1 + + 8 files changed, 54 insertions(+), 16 deletions(-) + +diff --git a/CPP/7zip/Compress/Rar1Decoder.cpp b/CPP/7zip/Compress/Rar1Decoder.cpp +index 68030c7..8c890c8 100644 +--- a/CPP/7zip/Compress/Rar1Decoder.cpp ++++ b/CPP/7zip/Compress/Rar1Decoder.cpp +@@ -29,7 +29,7 @@ public: + }; + */ + +-CDecoder::CDecoder(): m_IsSolid(false), _errorMode(false) { } ++CDecoder::CDecoder(): _isSolid(false), _solidAllowed(false), _errorMode(false) { } + + void CDecoder::InitStructures() + { +@@ -345,7 +345,7 @@ void CDecoder::GetFlagsBuf() + + void CDecoder::InitData() + { +- if (!m_IsSolid) ++ if (!_isSolid) + { + AvrPlcB = AvrLn1 = AvrLn2 = AvrLn3 = NumHuf = Buf60 = 0; + AvrPlc = 0x3500; +@@ -391,6 +391,11 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * + if (inSize == NULL || outSize == NULL) + return E_INVALIDARG; + ++ if (_isSolid && !_solidAllowed) ++ return S_FALSE; ++ ++ _solidAllowed = false; ++ + if (!m_OutWindowStream.Create(kHistorySize)) + return E_OUTOFMEMORY; + if (!m_InBitStream.Create(1 << 20)) +@@ -398,13 +403,13 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * + + m_UnpackSize = (Int64)*outSize; + m_OutWindowStream.SetStream(outStream); +- m_OutWindowStream.Init(m_IsSolid); ++ m_OutWindowStream.Init(_isSolid); + m_InBitStream.SetStream(inStream); + m_InBitStream.Init(); + + // CCoderReleaser coderReleaser(this); + InitData(); +- if (!m_IsSolid) ++ if (!_isSolid) + { + _errorMode = false; + InitStructures(); +@@ -475,6 +480,7 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * + } + if (m_UnpackSize < 0) + return S_FALSE; ++ _solidAllowed = true; + return m_OutWindowStream.Flush(); + } + +@@ -491,7 +497,7 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size) + { + if (size < 1) + return E_INVALIDARG; +- m_IsSolid = ((data[0] & 1) != 0); ++ _isSolid = ((data[0] & 1) != 0); + return S_OK; + } + +diff --git a/CPP/7zip/Compress/Rar1Decoder.h b/CPP/7zip/Compress/Rar1Decoder.h +index 01b606b..8abb3a3 100644 +--- a/CPP/7zip/Compress/Rar1Decoder.h ++++ b/CPP/7zip/Compress/Rar1Decoder.h +@@ -38,7 +38,8 @@ public: + UInt32 LastLength; + + Int64 m_UnpackSize; +- bool m_IsSolid; ++ bool _isSolid; ++ bool _solidAllowed; + bool _errorMode; + + UInt32 ReadBits(int numBits); +diff --git a/CPP/7zip/Compress/Rar2Decoder.cpp b/CPP/7zip/Compress/Rar2Decoder.cpp +index 0580c8d..be8d842 100644 +--- a/CPP/7zip/Compress/Rar2Decoder.cpp ++++ b/CPP/7zip/Compress/Rar2Decoder.cpp +@@ -80,7 +80,8 @@ static const UInt32 kHistorySize = 1 << 20; + static const UInt32 kWindowReservSize = (1 << 22) + 256; + + CDecoder::CDecoder(): +- m_IsSolid(false), ++ _isSolid(false), ++ _solidAllowed(false), + m_TablesOK(false) + { + } +@@ -320,6 +321,10 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * + if (inSize == NULL || outSize == NULL) + return E_INVALIDARG; + ++ if (_isSolid && !_solidAllowed) ++ return S_FALSE; ++ _solidAllowed = false; ++ + if (!m_OutWindowStream.Create(kHistorySize)) + return E_OUTOFMEMORY; + if (!m_InBitStream.Create(1 << 20)) +@@ -330,12 +335,12 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * + UInt64 pos = 0, unPackSize = *outSize; + + m_OutWindowStream.SetStream(outStream); +- m_OutWindowStream.Init(m_IsSolid); ++ m_OutWindowStream.Init(_isSolid); + m_InBitStream.SetStream(inStream); + m_InBitStream.Init(); + + // CCoderReleaser coderReleaser(this); +- if (!m_IsSolid) ++ if (!_isSolid) + { + InitStructures(); + if (unPackSize == 0) +@@ -343,6 +348,7 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * + if (m_InBitStream.GetProcessedSize() + 2 <= m_PackSize) // test it: probably incorrect; + if (!ReadTables()) + return S_FALSE; ++ _solidAllowed = true; + return S_OK; + } + if (!ReadTables()) +@@ -386,6 +392,9 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * + + if (!ReadLastTables()) + return S_FALSE; ++ ++ _solidAllowed = true; ++ + return m_OutWindowStream.Flush(); + } + +@@ -402,7 +411,7 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size) + { + if (size < 1) + return E_INVALIDARG; +- m_IsSolid = ((data[0] & 1) != 0); ++ _isSolid = ((data[0] & 1) != 0); + return S_OK; + } + +diff --git a/CPP/7zip/Compress/Rar2Decoder.h b/CPP/7zip/Compress/Rar2Decoder.h +index 0e9005f..370bce2 100644 +--- a/CPP/7zip/Compress/Rar2Decoder.h ++++ b/CPP/7zip/Compress/Rar2Decoder.h +@@ -138,7 +138,8 @@ class CDecoder : + Byte m_LastLevels[kMaxTableSize]; + + UInt64 m_PackSize; +- bool m_IsSolid; ++ bool _isSolid; ++ bool _solidAllowed; + bool m_TablesOK; + + void InitStructures(); +diff --git a/CPP/7zip/Compress/Rar3Decoder.cpp b/CPP/7zip/Compress/Rar3Decoder.cpp +index 6cb8a6a..7b85833 100644 +--- a/CPP/7zip/Compress/Rar3Decoder.cpp ++++ b/CPP/7zip/Compress/Rar3Decoder.cpp +@@ -92,7 +92,8 @@ CDecoder::CDecoder(): + _writtenFileSize(0), + _vmData(0), + _vmCode(0), +- m_IsSolid(false), ++ _isSolid(false), ++ _solidAllowed(false), + _errorMode(false) + { + Ppmd7_Construct(&_ppmd); +@@ -821,7 +822,7 @@ HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress) + { + _writtenFileSize = 0; + _unsupportedFilter = false; +- if (!m_IsSolid) ++ if (!_isSolid) + { + _lzSize = 0; + _winPos = 0; +@@ -840,12 +841,15 @@ HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress) + if (_errorMode) + return S_FALSE; + +- if (!m_IsSolid || !TablesRead) ++ if (!_isSolid || !TablesRead) + { + bool keepDecompressing; + RINOK(ReadTables(keepDecompressing)); + if (!keepDecompressing) ++ { ++ _solidAllowed = true; + return S_OK; ++ } + } + + for (;;) +@@ -870,6 +874,9 @@ HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress) + if (!keepDecompressing) + break; + } ++ ++ _solidAllowed = true; ++ + RINOK(WriteBuf()); + UInt64 packSize = m_InBitStream.BitDecoder.GetProcessedSize(); + RINOK(progress->SetRatioInfo(&packSize, &_writtenFileSize)); +@@ -890,6 +897,10 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream + if (!inSize) + return E_INVALIDARG; + ++ if (_isSolid && !_solidAllowed) ++ return S_FALSE; ++ _solidAllowed = false; ++ + if (!_vmData) + { + _vmData = (Byte *)::MidAlloc(kVmDataSizeMax + kVmCodeSizeMax); +@@ -928,7 +939,7 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size) + { + if (size < 1) + return E_INVALIDARG; +- m_IsSolid = ((data[0] & 1) != 0); ++ _isSolid = ((data[0] & 1) != 0); + return S_OK; + } + +diff --git a/CPP/7zip/Compress/Rar3Decoder.h b/CPP/7zip/Compress/Rar3Decoder.h +index 2f72d7d..32c8943 100644 +--- a/CPP/7zip/Compress/Rar3Decoder.h ++++ b/CPP/7zip/Compress/Rar3Decoder.h +@@ -191,7 +191,8 @@ class CDecoder: + CRecordVector _tempFilters; + UInt32 _lastFilter; + +- bool m_IsSolid; ++ bool _isSolid; ++ bool _solidAllowed; + bool _errorMode; + + bool _lzMode; +diff --git a/CPP/7zip/Compress/Rar5Decoder.cpp b/CPP/7zip/Compress/Rar5Decoder.cpp +index dc8830f..a826d5a 100644 +--- a/CPP/7zip/Compress/Rar5Decoder.cpp ++++ b/CPP/7zip/Compress/Rar5Decoder.cpp +@@ -72,6 +72,7 @@ CDecoder::CDecoder(): + _writtenFileSize(0), + _dictSizeLog(0), + _isSolid(false), ++ _solidAllowed(false), + _wasInit(false), + _inputBuf(NULL) + { +@@ -801,7 +802,10 @@ HRESULT CDecoder::CodeReal() + */ + + if (res == S_OK) ++ { ++ _solidAllowed = true; + res = res2; ++ } + + if (res == S_OK && _unpackSize_Defined && _writtenFileSize != _unpackSize) + return S_FALSE; +@@ -821,6 +825,10 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream + { + try + { ++ if (_isSolid && !_solidAllowed) ++ return S_FALSE; ++ _solidAllowed = false; ++ + if (_dictSizeLog >= sizeof(size_t) * 8) + return E_NOTIMPL; + +diff --git a/CPP/7zip/Compress/Rar5Decoder.h b/CPP/7zip/Compress/Rar5Decoder.h +index b0a4dd1..3db5018 100644 +--- a/CPP/7zip/Compress/Rar5Decoder.h ++++ b/CPP/7zip/Compress/Rar5Decoder.h +@@ -271,6 +271,7 @@ class CDecoder: + Byte _dictSizeLog; + bool _tableWasFilled; + bool _isSolid; ++ bool _solidAllowed; + bool _wasInit; + + UInt32 _reps[kNumReps]; diff --git a/projects/ArchR/packages/compress/p7zip/patches/p7zip-0500-gcc10-build-fix.patch b/projects/ArchR/packages/compress/p7zip/patches/p7zip-0500-gcc10-build-fix.patch new file mode 100644 index 0000000000..45f9f84af4 --- /dev/null +++ b/projects/ArchR/packages/compress/p7zip/patches/p7zip-0500-gcc10-build-fix.patch @@ -0,0 +1,26 @@ +diff -Nrup a/CPP/Windows/ErrorMsg.cpp b/CPP/Windows/ErrorMsg.cpp +--- a/CPP/Windows/ErrorMsg.cpp 2015-01-18 11:20:28.000000000 -0700 ++++ b/CPP/Windows/ErrorMsg.cpp 2019-09-24 13:01:18.887289152 -0600 +@@ -14,14 +14,14 @@ UString MyFormatMessage(DWORD errorCode) + AString msg; + + switch(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 ; +- case E_ABORT : txt = "E_ABORT"; break ; +- case E_FAIL : txt = "E_FAIL"; break ; +- case STG_E_INVALIDFUNCTION : txt = "STG_E_INVALIDFUNCTION"; break ; +- case E_OUTOFMEMORY : txt = "E_OUTOFMEMORY"; break ; +- case E_INVALIDARG : txt = "E_INVALIDARG"; break ; ++ case unsigned (ERROR_NO_MORE_FILES) : txt = "No more files"; break ; ++ case unsigned (E_NOTIMPL) : txt = "E_NOTIMPL"; break ; ++ case unsigned (E_NOINTERFACE) : txt = "E_NOINTERFACE"; break ; ++ case unsigned (E_ABORT) : txt = "E_ABORT"; break ; ++ case unsigned (E_FAIL) : txt = "E_FAIL"; break ; ++ case unsigned (STG_E_INVALIDFUNCTION) : txt = "STG_E_INVALIDFUNCTION"; break ; ++ case unsigned (E_OUTOFMEMORY) : txt = "E_OUTOFMEMORY"; break ; ++ case unsigned (E_INVALIDARG) : txt = "E_INVALIDARG"; break ; + case ERROR_DIRECTORY : txt = "Error Directory"; break ; + default: + txt = strerror(errorCode); diff --git a/projects/ArchR/packages/compress/p7zip/patches/p7zip-0501-change-numMethods-from-bool-to-unsigned.patch b/projects/ArchR/packages/compress/p7zip/patches/p7zip-0501-change-numMethods-from-bool-to-unsigned.patch new file mode 100644 index 0000000000..93eb0588c0 --- /dev/null +++ b/projects/ArchR/packages/compress/p7zip/patches/p7zip-0501-change-numMethods-from-bool-to-unsigned.patch @@ -0,0 +1,34 @@ +From 0820ef4b9238c1e39ae5bda32cc08cce3fd3ce89 Mon Sep 17 00:00:00 2001 +From: Nisha Parrakat +Date: Wed, 26 May 2021 19:59:28 +0000 +Subject: [PATCH] fixes the below error + +| ../../../../CPP/7zip/Archive/Wim/WimHandler.cpp: In member function 'virtual LONG NArchive::NWim::CHandler::GetArchiveProperty(PROPID, PROPVARIANT*)': +| ../../../../CPP/7zip/Archive/Wim/WimHandler.cpp:308:11: error: use of an operand of type 'bool' in 'operator++' is forbidden in C++17 +| 308 | numMethods++; +| | ^~~~~~~~~~ +| ../../../../CPP/7zip/Archive/Wim/WimHandler.cpp:318:9: error: use of an operand of type 'bool' in 'operator++' is forbidden in C++17 +| 318 | numMethods++; + +use unsigned instead of bool +Signed-off-by: Nisha Parrakat + +Upstream-Status: Pending + +--- + CPP/7zip/Archive/Wim/WimHandler.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/CPP/7zip/Archive/Wim/WimHandler.cpp b/CPP/7zip/Archive/Wim/WimHandler.cpp +index 27d3298..4ff5cfe 100644 +--- a/CPP/7zip/Archive/Wim/WimHandler.cpp ++++ b/CPP/7zip/Archive/Wim/WimHandler.cpp +@@ -298,7 +298,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) + + AString res; + +- bool numMethods = 0; ++ unsigned numMethods = 0; + for (unsigned i = 0; i < ARRAY_SIZE(k_Methods); i++) + { + if (methodMask & ((UInt32)1 << i)) diff --git a/projects/ArchR/packages/compress/xz/package.mk b/projects/ArchR/packages/compress/xz/package.mk new file mode 100644 index 0000000000..f156fe0f74 --- /dev/null +++ b/projects/ArchR/packages/compress/xz/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) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="xz" +PKG_VERSION="5.8.1" +PKG_SHA256="0b54f79df85912504de0b14aec7971e3f964491af1812d83447005807513cd9e" +PKG_LICENSE="GPL" +PKG_SITE="https://tukaani.org/xz/" +PKG_URL="https://github.com/tukaani-project/xz/releases/download/v${PKG_VERSION}/${PKG_NAME}-${PKG_VERSION}.tar.xz" +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" +PKG_TOOLCHAIN="configure" + +# 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-nls \ + --disable-scripts \ + --enable-symbol-versions=no" + +PKG_CONFIGURE_OPTS_TARGET="--enable-shared \ + --disable-static \ + --enable-symbol-versions=yes" + +post_makeinstall_target() { + rm -rf ${INSTALL}/usr/bin +} diff --git a/projects/ArchR/packages/compress/xz/patches/xz-01-init-uninitialized-variables.patch b/projects/ArchR/packages/compress/xz/patches/xz-01-init-uninitialized-variables.patch new file mode 100644 index 0000000000..0d88880702 --- /dev/null +++ b/projects/ArchR/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/projects/ArchR/packages/debug/apitrace/package.mk b/projects/ArchR/packages/debug/apitrace/package.mk new file mode 100644 index 0000000000..5c27d518d1 --- /dev/null +++ b/projects/ArchR/packages/debug/apitrace/package.mk @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="apitrace" +PKG_VERSION="45a005875d348b055d5b88dca285c109dee90457" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/apitrace/apitrace" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain waffle Python3:host" +PKG_LONGDESC="A set of tools to trace, replay, and inspect OpenGL calls" +GET_HANDLER_SUPPORT="git" + +PKG_CMAKE_OPTS_TARGET=" -DENABLE_GUI=OFF -DENABLE_EGL=ON -DENABLE_WAFFLE=ON " diff --git a/projects/ArchR/packages/debug/strace/package.mk b/projects/ArchR/packages/debug/strace/package.mk new file mode 100644 index 0000000000..4cfffdaae6 --- /dev/null +++ b/projects/ArchR/packages/debug/strace/package.mk @@ -0,0 +1,30 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="strace" +PKG_LICENSE="BSD" +PKG_SITE="https://strace.io/" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="strace is a diagnostic, debugging and instructional userspace utility" +PKG_TOOLCHAIN="autotools" +PKG_BUILD_FLAGS="-cfg-libs" + +case "${DEVICE}" in + SM8650|SM8550|SM8250|H700) + PKG_VERSION="6.19" + PKG_SHA256="e076c851eec0972486ec842164fdc54547f9d17abd3d1449de8b120f5d299143" + ;; + RK3399|S922X|RK3566) + PKG_VERSION="6.18" + PKG_SHA256="0ad5dcba973a69e779650ef1cb335b12ee60716fc7326609895bd33e6d2a7325" + ;; + *) + PKG_VERSION="6.17" + PKG_SHA256="0a7c7bedc7efc076f3242a0310af2ae63c292a36dd4236f079e88a93e98cb9c0" + ;; +esac +PKG_URL="https://strace.io/files/${PKG_VERSION}/strace-${PKG_VERSION}.tar.xz" + +if [ "${TARGET_ARCH}" = x86_64 -o "${TARGET_ARCH}" = "aarch64" ]; then + PKG_CONFIGURE_OPTS_TARGET="--enable-mpers=no" +fi diff --git a/projects/ArchR/packages/debug/strace/patches/strace-0001-autoreconf.patch b/projects/ArchR/packages/debug/strace/patches/strace-0001-autoreconf.patch new file mode 100644 index 0000000000..41dd01be4b --- /dev/null +++ b/projects/ArchR/packages/debug/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([./build-aux/git-version-gen .tarball-version]), +- [strace-devel@lists.strace.io], +- [strace], +- [https://strace.io]) ++AC_INIT([strace],[5.11]) + m4_define([copyright_year], st_esyscmd_s([./build-aux/copyright-year-gen .year])) + m4_define([manpage_date], st_esyscmd_s([./build-aux/file-date-gen doc/strace.1.in])) + AC_COPYRIGHT([Copyright (c) 1999-]copyright_year[ The strace developers.]) diff --git a/projects/ArchR/packages/debug/strace/patches/strace-0002-fix-autoconf-archive.patch b/projects/ArchR/packages/debug/strace/patches/strace-0002-fix-autoconf-archive.patch new file mode 100644 index 0000000000..4e0927da66 --- /dev/null +++ b/projects/ArchR/packages/debug/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/projects/ArchR/packages/devel/SDL2_gfx/package.mk b/projects/ArchR/packages/devel/SDL2_gfx/package.mk new file mode 100644 index 0000000000..ab59b3b893 --- /dev/null +++ b/projects/ArchR/packages/devel/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="29927b3" +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" + +PKG_CONFIGURE_OPTS_TARGET=" --disable-mmx" + +pre_configure_target() { + export CC=${CC} +} + diff --git a/projects/ArchR/packages/devel/SDL2_image/package.mk b/projects/ArchR/packages/devel/SDL2_image/package.mk new file mode 100644 index 0000000000..bbb1fbda64 --- /dev/null +++ b/projects/ArchR/packages/devel/SDL2_image/package.mk @@ -0,0 +1,31 @@ +# 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.8.2" +PKG_LICENSE="GPL" +PKG_SITE="http://www.libsdl.org/" +PKG_URL="https://github.com/libsdl-org/SDL_image/releases/download/release-${PKG_VERSION}/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain SDL2 libjpeg-turbo libpng" +PKG_LONGDESC="SDL_image is an image file loading library. " +PKG_TOOLCHAIN="configure" + +PKG_CONFIGURE_OPTS_TARGET="--disable-sdltest \ + --enable-bmp \ + --enable-gif \ + --enable-jpg \ + --enable-lbm \ + --enable-pcx \ + --enable-png \ + --enable-pnm \ + --enable-tga \ + --enable-tif \ + --enable-xcf \ + --enable-xpm \ + --enable-xv \ + + --enable-webp" +pre_configure_target() { + export LDFLAGS="${LDFLAGS} -ljpeg -lz -lm" +} diff --git a/projects/ArchR/packages/devel/SDL2_net/package.mk b/projects/ArchR/packages/devel/SDL2_net/package.mk new file mode 100644 index 0000000000..2bc303387b --- /dev/null +++ b/projects/ArchR/packages/devel/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.2.0" +PKG_LICENSE="GPL" +PKG_SITE="https://www.libsdl.org/projects/SDL_net/" +PKG_URL="https://github.com/libsdl-org/SDL_net/releases/download/release-${PKG_VERSION}/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain SDL2" +PKG_LONGDESC="SDL2_net: network library" +PKG_TOOLCHAIN="autotools" diff --git a/projects/ArchR/packages/devel/SDL2_ttf/package.mk b/projects/ArchR/packages/devel/SDL2_ttf/package.mk new file mode 100644 index 0000000000..a45b8353bd --- /dev/null +++ b/projects/ArchR/packages/devel/SDL2_ttf/package.mk @@ -0,0 +1,14 @@ +# 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.20.2" +PKG_LICENSE="GPL" +PKG_SITE="http://www.libsdl.org/" +PKG_URL="https://github.com/libsdl-org/SDL_ttf/releases/download/release-${PKG_VERSION}/${PKG_NAME}-${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" +PKG_TOOLCHAIN="cmake" + +PKG_CMAKE_OPTS_TARGET="-DFREETYPE_INCLUDE_DIRS=${SYSROOT_PREFIX}/usr" diff --git a/projects/ArchR/packages/devel/binutils/package.mk b/projects/ArchR/packages/devel/binutils/package.mk new file mode 100644 index 0000000000..bac890a6d7 --- /dev/null +++ b/projects/ArchR/packages/devel/binutils/package.mk @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +. ${ROOT}/packages/devel/binutils/package.mk + +# gprofng fails to build with GCC 15 / glibc _Generic conflict +PKG_CONFIGURE_OPTS_HOST="${PKG_CONFIGURE_OPTS_HOST} --disable-gprofng" diff --git a/projects/ArchR/packages/devel/boost/package.mk b/projects/ArchR/packages/devel/boost/package.mk new file mode 100644 index 0000000000..8a6c26a17b --- /dev/null +++ b/projects/ArchR/packages/devel/boost/package.mk @@ -0,0 +1,68 @@ +# 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) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="boost" +PKG_VERSION="1.86.0" +PKG_LICENSE="OSS" +PKG_SITE="http://www.boost.org/" +PKG_URL="https://archives.boost.io/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" +PKG_B2_PARAM=" binary-format=elf link=static threading=multi toolset=gcc " +if [ "${TARGET_ARCH}" = "aarch64" ]; then + PKG_B2_PARAM+=" abi=aapcs address-model=64 architecture=arm " +fi + +make_host() { + cd tools/build/src/engine + sh build.sh +} + +makeinstall_host() { + mkdir -p ${TOOLCHAIN}/bin + cp b2 ${TOOLCHAIN}/bin +} + +pre_configure_target() { + export CFLAGS="${CFLAGS} -I${SYSROOT_PREFIX}/usr/include/${PKG_PYTHON_VERSION}" + export CXXFLAGS="${CXXFLAGS} -I${SYSROOT_PREFIX}/usr/include/${PKG_PYTHON_VERSION}" +} + +configure_target() { + sh bootstrap.sh --prefix=/usr \ + --with-bjam=${TOOLCHAIN}/bin/b2 \ + --with-python=${TOOLCHAIN}/bin/python \ + --with-python-root=${SYSROOT_PREFIX}/usr + + echo "using gcc : $(${CC} -v 2>&1 | tail -n 1 |awk '{print $3}') : ${CXX} : \"${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() { + ln -sf ${TOOLCHAIN}/bin/b2 ${TOOLCHAIN}/bin/bjam + ${TOOLCHAIN}/bin/bjam -d2 --ignore-site-config \ + ${PKG_B2_PARAM} \ + --layout=system \ + --prefix=${SYSROOT_PREFIX}/usr \ + --with-chrono \ + --with-date_time \ + --with-filesystem \ + --with-iostreams \ + --with-program_options \ + --with-python \ + --with-locale \ + --with-random \ + --with-regex -sICU_PATH="${SYSROOT_PREFIX}/usr" \ + --with-serialization \ + --with-system \ + --with-thread \ + --with-nowide \ + --with-context \ + install +} diff --git a/projects/ArchR/packages/devel/cmake/package.mk b/projects/ArchR/packages/devel/cmake/package.mk new file mode 100644 index 0000000000..888bae585c --- /dev/null +++ b/projects/ArchR/packages/devel/cmake/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) 2016-present Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="cmake" +PKG_VERSION="3.30.3" +PKG_LICENSE="BSD" +PKG_SITE="https://cmake.org/" +PKG_URL="https://cmake.org/files/v$(get_pkg_version_maj_min)/cmake-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="pkg-config:host openssl:host" +PKG_LONGDESC="A cross-platform, open-source make system." +PKG_TOOLCHAIN="configure" +PKG_BUILD_FLAGS="+local-cc" + +configure_host() { + ../configure --prefix=${TOOLCHAIN} \ + --no-qt-gui --no-system-libs \ + -- \ + -DCMAKE_C_FLAGS="-O2 -Wall -pipe -Wno-format-security" \ + -DCMAKE_CXX_FLAGS="-O2 -Wall -pipe -Wno-format-security" \ + -DCMAKE_EXE_LINKER_FLAGS="${HOST_LDFLAGS}" \ + -DCMAKE_USE_OPENSSL=ON \ + -DBUILD_CursesDialog=0 +} diff --git a/projects/ArchR/packages/devel/cmake/patches/cmake-001-disable-free-comp-methods.patch b/projects/ArchR/packages/devel/cmake/patches/cmake-001-disable-free-comp-methods.patch new file mode 100644 index 0000000000..79c961baf7 --- /dev/null +++ b/projects/ArchR/packages/devel/cmake/patches/cmake-001-disable-free-comp-methods.patch @@ -0,0 +1,14 @@ +--- a/Utilities/cmcurl/lib/vtls/openssl.c.orig 2016-10-19 19:17:49.615923691 +0200 ++++ b/Utilities/cmcurl/lib/vtls/openssl.c 2016-10-19 19:22:50.849565684 +0200 +@@ -134,6 +134,11 @@ + #define HAVE_SSL_COMP_FREE_COMPRESSION_METHODS 1 + #endif + ++#if !defined(OPENSSL_NO_COMP) || \ ++ OPENSSL_VERSION_NUMBER >= 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/projects/ArchR/packages/devel/ecm/package.mk b/projects/ArchR/packages/devel/ecm/package.mk new file mode 100644 index 0000000000..460e73c750 --- /dev/null +++ b/projects/ArchR/packages/devel/ecm/package.mk @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="ecm" +PKG_VERSION="v6.16.0" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/KDE/extra-cmake-modules" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_LONGDESC="KDE Extra CMake Modules" +PKG_DEPENDS_TARGET="toolchain" +PKG_TOOLCHAIN="cmake" + +PKG_CMAKE_OPTS_TARGET+=" -DBUILD_TESTING=OFF -DBUILD_HTML_DOCS=OFF -DBUILD_MAN_DOCS=OFF -DBUILD_QTHELP_DOCS=OFF" diff --git a/projects/ArchR/packages/devel/elfutils/package.mk b/projects/ArchR/packages/devel/elfutils/package.mk new file mode 100644 index 0000000000..6b461a347a --- /dev/null +++ b/projects/ArchR/packages/devel/elfutils/package.mk @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +. ${ROOT}/packages/devel/elfutils/package.mk + +pre_configure_host() { + # GCC 15 treats discarded-qualifiers as error with -Werror + export CFLAGS="${CFLAGS} -Wno-error=discarded-qualifiers" + # Fix -std=gnu17 invalid for C++ and same warning for C++ files + export CXXFLAGS="${CXXFLAGS//-std=gnu17/-std=gnu++17} -Wno-error=discarded-qualifiers" +} diff --git a/projects/ArchR/packages/devel/gettext/package.mk b/projects/ArchR/packages/devel/gettext/package.mk new file mode 100644 index 0000000000..6f71ba2fb2 --- /dev/null +++ b/projects/ArchR/packages/devel/gettext/package.mk @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2026 ArchR (https://github.com/archr-linux/Arch-R) +# Override: downgrade to 0.24 to avoid gnulib _Generic conflicts with GCC 15+ + +PKG_NAME="gettext" +PKG_VERSION="0.24" +PKG_SHA256="e1620d518b26d7d3b16ac570e5018206e8b0d725fb65c02d048397718b5cf318" +PKG_LICENSE="GPL" +PKG_SITE="https://www.gnu.org/s/gettext/" +PKG_URL="https://mirrors.kernel.org/gnu/gettext/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_HOST="make:host" +PKG_DEPENDS_TARGET="autotools:host make:host gcc:host" +PKG_LONGDESC="A program internationalization library and tools." +PKG_BUILD_FLAGS="+local-cc" diff --git a/projects/ArchR/packages/devel/glib/package.mk b/projects/ArchR/packages/devel/glib/package.mk new file mode 100644 index 0000000000..173f5fe4cc --- /dev/null +++ b/projects/ArchR/packages/devel/glib/package.mk @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +. ${ROOT}/packages/devel/glib/package.mk + +PKG_MESON_OPTS_HOST="-Ddefault_library=shared \ + -Dinstalled_tests=false \ + -Dlibmount=disabled \ + -Dintrospection=disabled \ + -Dtests=false" diff --git a/projects/ArchR/packages/devel/glib/patches/001-frexpl.patch b/projects/ArchR/packages/devel/glib/patches/001-frexpl.patch new file mode 100644 index 0000000000..bee2df918a --- /dev/null +++ b/projects/ArchR/packages/devel/glib/patches/001-frexpl.patch @@ -0,0 +1,23 @@ +diff --git a/glib/gnulib/meson.build b/glib/gnulib/meson.build +index 38b530aa0..4408a3dc6 100644 +--- a/glib/gnulib/meson.build ++++ b/glib/gnulib/meson.build +@@ -302,12 +302,12 @@ else + gl_cv_func_frexpl_broken_beyond_repair = true + endif + +-if not gl_cv_func_frexp_works and gl_cv_func_frexp_broken_beyond_repair +- error ('frexp() is missing or broken beyond repair, and we have nothing to replace it with') +-endif +-if not gl_cv_func_frexpl_works and gl_cv_func_frexpl_broken_beyond_repair +- error ('frexpl() is missing or broken beyond repair, and we have nothing to replace it with') +-endif ++#if not gl_cv_func_frexp_works and gl_cv_func_frexp_broken_beyond_repair ++# error ('frexp() is missing or broken beyond repair, and we have nothing to replace it with') ++#endif ++#if not gl_cv_func_frexpl_works and gl_cv_func_frexpl_broken_beyond_repair ++# error ('frexpl() is missing or broken beyond repair, and we have nothing to replace it with') ++#endif + + math_h_config.set ('REPLACE_FREXP', gl_cv_func_frexp_works ? 0 : 1) + math_h_config.set ('REPLACE_FREXPL', gl_cv_func_frexpl_works ? 0 : 1) diff --git a/projects/ArchR/packages/devel/glibc/config/gai.conf b/projects/ArchR/packages/devel/glibc/config/gai.conf new file mode 100644 index 0000000000..4616ed005b --- /dev/null +++ b/projects/ArchR/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/projects/ArchR/packages/devel/glibc/config/host.conf b/projects/ArchR/packages/devel/glibc/config/host.conf new file mode 100644 index 0000000000..d1a59f73a9 --- /dev/null +++ b/projects/ArchR/packages/devel/glibc/config/host.conf @@ -0,0 +1 @@ +multi on diff --git a/projects/ArchR/packages/devel/glibc/config/ld.so.conf b/projects/ArchR/packages/devel/glibc/config/ld.so.conf new file mode 100644 index 0000000000..83327c01bf --- /dev/null +++ b/projects/ArchR/packages/devel/glibc/config/ld.so.conf @@ -0,0 +1 @@ +include /etc/ld.so.conf.d/*.conf diff --git a/projects/ArchR/packages/devel/glibc/config/nsswitch-init.conf b/projects/ArchR/packages/devel/glibc/config/nsswitch-init.conf new file mode 100644 index 0000000000..eba159e8fc --- /dev/null +++ b/projects/ArchR/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/projects/ArchR/packages/devel/glibc/config/nsswitch-target.conf b/projects/ArchR/packages/devel/glibc/config/nsswitch-target.conf new file mode 100644 index 0000000000..4391cdd21e --- /dev/null +++ b/projects/ArchR/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/projects/ArchR/packages/devel/glibc/package.mk b/projects/ArchR/packages/devel/glibc/package.mk new file mode 100644 index 0000000000..2e68c82032 --- /dev/null +++ b/projects/ArchR/packages/devel/glibc/package.mk @@ -0,0 +1,161 @@ +# 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.40" +PKG_LICENSE="GPL" +PKG_SITE="https://www.gnu.org/software/libc/" +PKG_URL="https://mirrors.kernel.org/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="+bfd -gold" + +case "${DEVICE}" in + RK3588*) + OPT_ENABLE_KERNEL=6.1.0 + ;; + SDM845) + OPT_ENABLE_KERNEL=5.18.0 + ;; + *) + OPT_ENABLE_KERNEL=6.10.0 + ;; +esac + +case ${TARGET_ARCH} in + arm|aarch64) + PKG_PATCH_DIRS="widevine-arm" + ;; +esac + +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=${OPT_ENABLE_KERNEL} \ + --without-cvs \ + --without-gd \ + --disable-build-nscd \ + --disable-nscd \ + --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_configure_target() { +# Filter out some problematic *FLAGS + export CFLAGS=$(echo ${CFLAGS} | sed -e "s|-O.|-O3|g") + + export CFLAGS=$(echo ${CFLAGS} | sed -e "s|-Wunused-but-set-variable||g") + export CFLAGS="${CFLAGS} -Wno-unused-variable" + + if [ -n "${PROJECT_CFLAGS}" ]; then + export CFLAGS=$(echo ${CFLAGS} | sed -e "s|${PROJECT_CFLAGS}||g") + fi + + export LDFLAGS=$(echo ${LDFLAGS} | sed -e "s|-O.|-O3|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 </maps +Next message (by thread): [RFC PATCH] arm64/math-vec.h: guard off the vector types with CPP constants +Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] +When implementing a C parser, it's apparently common to use GCC as +preprocessor. However, those programs don't necessarily define the SIMD +intrinsic types exposed by GCC, resulting in failed compilations. + +This patch adds a way for those users to bypass entirely the vector +types, as they usually aren't interested in libmvec anyway. They can +just add -D__ARM_VEC_MATH_DISABLED=1 to the CPP_FLAGS they pass on to +GCC. + +Fixes: BZ #25422 + +Signed-off-by: Simon Chopin +--- + sysdeps/aarch64/fpu/bits/math-vector.h | 32 ++++++++++++++------------ + 1 file changed, 17 insertions(+), 15 deletions(-) + +diff --git a/sysdeps/aarch64/fpu/bits/math-vector.h b/sysdeps/aarch64/fpu/bits/math-vector.h +index 7c200599c1..c739e6bc5d 100644 +--- a/sysdeps/aarch64/fpu/bits/math-vector.h ++++ b/sysdeps/aarch64/fpu/bits/math-vector.h +@@ -25,29 +25,30 @@ + /* Get default empty definitions for simd declarations. */ + #include + +-#if __GNUC_PREREQ(9, 0) +-# define __ADVSIMD_VEC_MATH_SUPPORTED ++#if defined __ARM_ARCH_8A && !defined __ARM_VEC_MATH_DISABLED ++# if __GNUC_PREREQ(9, 0) ++# define __ADVSIMD_VEC_MATH_SUPPORTED + typedef __Float32x4_t __f32x4_t; + typedef __Float64x2_t __f64x2_t; +-#elif __glibc_clang_prereq(8, 0) +-# define __ADVSIMD_VEC_MATH_SUPPORTED ++# elif __glibc_clang_prereq(8, 0) ++# define __ADVSIMD_VEC_MATH_SUPPORTED + typedef __attribute__ ((__neon_vector_type__ (4))) float __f32x4_t; + typedef __attribute__ ((__neon_vector_type__ (2))) double __f64x2_t; +-#endif ++# endif + +-#if __GNUC_PREREQ(10, 0) || __glibc_clang_prereq(11, 0) +-# define __SVE_VEC_MATH_SUPPORTED ++# if __GNUC_PREREQ(10, 0) || __glibc_clang_prereq(11, 0) ++# define __SVE_VEC_MATH_SUPPORTED + typedef __SVFloat32_t __sv_f32_t; + typedef __SVFloat64_t __sv_f64_t; + typedef __SVBool_t __sv_bool_t; +-#endif ++# endif + + /* If vector types and vector PCS are unsupported in the working + compiler, no choice but to omit vector math declarations. */ + +-#ifdef __ADVSIMD_VEC_MATH_SUPPORTED ++# ifdef __ADVSIMD_VEC_MATH_SUPPORTED + +-# define __vpcs __attribute__ ((__aarch64_vector_pcs__)) ++# define __vpcs __attribute__ ((__aarch64_vector_pcs__)) + + __vpcs __f32x4_t _ZGVnN4v_cosf (__f32x4_t); + __vpcs __f32x4_t _ZGVnN4v_expf (__f32x4_t); +@@ -59,10 +60,10 @@ __vpcs __f64x2_t _ZGVnN2v_exp (__f64x2_t); + __vpcs __f64x2_t _ZGVnN2v_log (__f64x2_t); + __vpcs __f64x2_t _ZGVnN2v_sin (__f64x2_t); + +-# undef __ADVSIMD_VEC_MATH_SUPPORTED +-#endif /* __ADVSIMD_VEC_MATH_SUPPORTED */ ++# undef __ADVSIMD_VEC_MATH_SUPPORTED ++# endif /* __ADVSIMD_VEC_MATH_SUPPORTED */ + +-#ifdef __SVE_VEC_MATH_SUPPORTED ++# ifdef __SVE_VEC_MATH_SUPPORTED + + __sv_f32_t _ZGVsMxv_cosf (__sv_f32_t, __sv_bool_t); + __sv_f32_t _ZGVsMxv_expf (__sv_f32_t, __sv_bool_t); +@@ -74,5 +75,6 @@ __sv_f64_t _ZGVsMxv_exp (__sv_f64_t, __sv_bool_t); + __sv_f64_t _ZGVsMxv_log (__sv_f64_t, __sv_bool_t); + __sv_f64_t _ZGVsMxv_sin (__sv_f64_t, __sv_bool_t); + +-# undef __SVE_VEC_MATH_SUPPORTED +-#endif /* __SVE_VEC_MATH_SUPPORTED */ ++# undef __SVE_VEC_MATH_SUPPORTED ++# endif /* __SVE_VEC_MATH_SUPPORTED */ ++#endif /* _ARM_ARCH_8A && !__ARM_VEC_MATH_DISABLED */ + +base-commit: 64b1a44183a3094672ed304532bedb9acc707554 +-- +2.40.1 diff --git a/projects/ArchR/packages/devel/glibc/patches/glibc-fix-dns-with-broken-routers.patch b/projects/ArchR/packages/devel/glibc/patches/glibc-fix-dns-with-broken-routers.patch new file mode 100644 index 0000000000..d2ac670853 --- /dev/null +++ b/projects/ArchR/packages/devel/glibc/patches/glibc-fix-dns-with-broken-routers.patch @@ -0,0 +1,107 @@ +commit 45918e237cd32bb3d9a5fde83f81f83b52584771 +Author: Stefan Saraev +Date: Tue Oct 1 12:09:07 2013 +0300 + + fix dns with broken routers + + ref: https://fedoraproject.org/wiki/Networking/NameResolution/ADDRCONFIG + +--- a/nss/getaddrinfo.c ++++ b/nss/getaddrinfo.c +@@ -730,6 +730,38 @@ gaih_inet (const char *name, const struc + if (res_ctx == NULL) + no_more = 1; + ++ /* 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; +@@ -737,7 +769,7 @@ gaih_inet (const char *name, const struc + + /* 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) +@@ -826,25 +858,27 @@ gaih_inet (const char *name, const struc + + 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) + { + if ((result = gethosts (fct, AF_INET6, name, req, tmpbuf, + res, &status, &no_data)) != 0) + { + __resolv_context_put (res_ctx); + goto out; + } + 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) || !res->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) || !res->got_ipv6))) ++ && suppress_af != AF_INET) + { + if ((result = gethosts (fct, AF_INET, name, req, tmpbuf, + res, &status, &no_data)) != 0) +--- a/sysdeps/unix/sysv/linux/check_pf.c ++++ b/sysdeps/unix/sysv/linux/check_pf.c +@@ -224,7 +224,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/projects/ArchR/packages/devel/glibc/patches/glibc-ld.so.cache-to-writable-cache.patch b/projects/ArchR/packages/devel/glibc/patches/glibc-ld.so.cache-to-writable-cache.patch new file mode 100644 index 0000000000..1f38ff8849 --- /dev/null +++ b/projects/ArchR/packages/devel/glibc/patches/glibc-ld.so.cache-to-writable-cache.patch @@ -0,0 +1,25 @@ +From bfdcab6e5f8352d5a1ee9724244d98cfd1d1d309 Mon Sep 17 00:00:00 2001 +From: 7Ji +Date: Fri, 15 Jul 2022 11:30:30 +0800 +Subject: [PATCH] glibc: ld.so.cache to .cache + +--- + sysdeps/generic/dl-cache.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sysdeps/generic/dl-cache.h b/sysdeps/generic/dl-cache.h +index 93d4bea930..34aa313cf0 100644 +--- a/sysdeps/generic/dl-cache.h ++++ b/sysdeps/generic/dl-cache.h +@@ -35,7 +35,7 @@ + #endif + + #ifndef LD_SO_CACHE +-# define LD_SO_CACHE SYSCONFDIR "/ld.so.cache" ++# define LD_SO_CACHE "/storage/.cache/ld.so.cache" + #endif + + #ifndef add_system_dir +-- +2.37.1 + diff --git a/projects/ArchR/packages/devel/gnulib/package.mk b/projects/ArchR/packages/devel/gnulib/package.mk new file mode 100644 index 0000000000..8e4d3337d0 --- /dev/null +++ b/projects/ArchR/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="9f48fb992a3d7e96610c4ce8be969cff2d61a01b" +PKG_LICENSE="GPL" +PKG_SITE="https://savannah.gnu.org/git/?group=gnulib" +PKG_URL="http://git.savannah.gnu.org/gitweb/?p=${PKG_NAME}.git;a=snapshot;h=${PKG_VERSION};sf=tgz" +PKG_SOURCE_NAME="${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_LONGDESC="GNU portability library" +PKG_TOOLCHAIN="manual" diff --git a/projects/ArchR/packages/devel/json-glib/package.mk b/projects/ArchR/packages/devel/json-glib/package.mk new file mode 100644 index 0000000000..698d5bbebc --- /dev/null +++ b/projects/ArchR/packages/devel/json-glib/package.mk @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="json-glib" +PKG_VERSION="1.10.0" +PKG_LICENSE="LGPL-2.1" +PKG_SITE="https://github.com/GNOME/json-glib" +PKG_URL="https://github.com/GNOME/json-glib/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain glib glib:host" +PKG_LONGDESC="JSON-GLib implements a full suite of JSON-related tools using GLib and GObject." + +PKG_MESON_OPTS_TARGET="-Dintrospection=disabled \ + -Dgtk_doc=disabled \ + -Dman=false \ + -Dtests=false" diff --git a/projects/ArchR/packages/devel/libaio/package.mk b/projects/ArchR/packages/devel/libaio/package.mk new file mode 100644 index 0000000000..254deb2329 --- /dev/null +++ b/projects/ArchR/packages/devel/libaio/package.mk @@ -0,0 +1,17 @@ +# 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.113" +PKG_SHA256="716c7059703247344eb066b54ecbc3ca2134f0103307192e6c2b7dab5f9528ab" +PKG_LICENSE="GPL" +PKG_SITE="https://pagure.io/libaio" +PKG_URL="https://pagure.io/${PKG_NAME}/archive/${PKG_NAME}-${PKG_VERSION}/${PKG_NAME}-${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Kernel Asynchronous I/O (AIO) Support for Linux." +PKG_BUILD_FLAGS="-lto" + +make_target() { + make -C src +} diff --git a/projects/ArchR/packages/devel/libclc/package.mk b/projects/ArchR/packages/devel/libclc/package.mk new file mode 100644 index 0000000000..fd187b4318 --- /dev/null +++ b/projects/ArchR/packages/devel/libclc/package.mk @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2024-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libclc" +PKG_VERSION="$(get_pkg_version llvm)" +PKG_LICENSE="Apache-2.0" +PKG_URL="" +PKG_DEPENDS_HOST="toolchain:host llvm:host spirv-tools spirv-tools:host spirv-llvm-translator:host" +PKG_LONGDESC="Low-Level Virtual Machine (LLVM) is a compiler infrastructure." +PKG_DEPENDS_UNPACK+=" llvm" +PKG_PATCH_DIRS+=" $(get_pkg_directory llvm)/patches" +PKG_TOOLCHAIN="cmake" + +unpack() { + mkdir -p ${PKG_BUILD} + tar --strip-components=1 -xf ${SOURCES}/llvm/llvm-${PKG_VERSION}.tar.xz -C ${PKG_BUILD} +} + +pre_configure() { + PKG_CMAKE_SCRIPT="${PKG_BUILD}/libclc/CMakeLists.txt" +} + +pre_configure_host() { + LIBCLC_TARGETS_TO_BUILD="spirv64-mesa3d-;spirv-mesa3d-" + + mkdir -p "${PKG_BUILD}/.${HOST_NAME}" + cd ${PKG_BUILD}/.${HOST_NAME} + PKG_CMAKE_OPTS_HOST="-DLIBCLC_TARGETS_TO_BUILD=${LIBCLC_TARGETS_TO_BUILD}" +} diff --git a/projects/ArchR/packages/devel/libcom-err/package.mk b/projects/ArchR/packages/devel/libcom-err/package.mk new file mode 100644 index 0000000000..d21e9c7633 --- /dev/null +++ b/projects/ArchR/packages/devel/libcom-err/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) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libcom-err" +PKG_VERSION="$(get_pkg_version e2fsprogs)" +PKG_LICENSE="GPL" +PKG_SITE="http://e2fsprogs.sourceforge.net/" +PKG_URL="https://www.kernel.org/pub/linux/kernel/people/tytso/e2fsprogs/v${PKG_VERSION}/e2fsprogs-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="autotools:host gcc:host" +PKG_LONGDESC="The filesystem utilities for the EXT2 filesystem, including e2fsck, mke2fs, dumpe2fs, fsck, and others." + +pre_configure() { + PKG_CONFIGURE_OPTS_TARGET="BUILD_CC=${HOST_CC} \ + --with-udev-rules-dir=no \ + --with-crond-dir=no \ + --with-systemd-unit-dir=no \ + --enable-verbose-makecmds \ + --disable-subset \ + --enable-elf-shlibs \ + --disable-bsd-shlibs \ + --disable-profile \ + --disable-jbd-debug \ + --disable-blkid-debug \ + --disable-testio-debug \ + --enable-libuuid \ + --enable-libblkid \ + --disable-debugfs \ + --disable-imager \ + --disable-resizer \ + --disable-fsck \ + --disable-e2initrd-helper \ + --disable-tls \ + --disable-uuidd \ + --disable-nls \ + --disable-rpath \ + --disable-fuse2fs \ + --with-gnu-ld" +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib + cp -rf ${PKG_BUILD}/.${TARGET_NAME}/lib/libcom_err.so* ${INSTALL}/usr/lib +} diff --git a/projects/ArchR/packages/devel/libdatrie/package.mk b/projects/ArchR/packages/devel/libdatrie/package.mk new file mode 100644 index 0000000000..28467ec975 --- /dev/null +++ b/projects/ArchR/packages/devel/libdatrie/package.mk @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="libdatrie" +PKG_VERSION="0.2.13" +PKG_LICENSE="LGPLv2" +PKG_SITE="https://github.com/tlwg/libdatrie" +PKG_URL="${PKG_SITE}/releases/download/v${PKG_VERSION}/libdatrie-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain libtool" +PKG_BUILD_FLAGS="+pic" +PKG_TOOLCHAIN="configure" + diff --git a/projects/ArchR/packages/devel/libfmt/package.mk b/projects/ArchR/packages/devel/libfmt/package.mk new file mode 100644 index 0000000000..8e7f85262e --- /dev/null +++ b/projects/ArchR/packages/devel/libfmt/package.mk @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +. ${ROOT}/packages/devel/libfmt/package.mk + +case ${DEVICE} in + SM8250|SM8550|SDM845) + ;; + *) + PKG_VERSION="9.1.0" + PKG_SHA256="" + PKG_URL="https://github.com/fmtlib/fmt/archive/${PKG_VERSION}.tar.gz" + ;; +esac diff --git a/projects/ArchR/packages/devel/libpthread-stubs/package.mk b/projects/ArchR/packages/devel/libpthread-stubs/package.mk new file mode 100644 index 0000000000..61575af746 --- /dev/null +++ b/projects/ArchR/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.5" +PKG_LICENSE="OSS" +PKG_SITE="http://xcb.freedesktop.org/" +PKG_URL="http://xcb.freedesktop.org/dist/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="toolchain" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A library providing weak aliases for pthread functions." diff --git a/projects/ArchR/packages/devel/libserialport/package.mk b/projects/ArchR/packages/devel/libserialport/package.mk new file mode 100644 index 0000000000..adc4e7d857 --- /dev/null +++ b/projects/ArchR/packages/devel/libserialport/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0 + +PKG_NAME="libserialport" +PKG_VERSION="fd20b0fc5a34cd7f776e4af6c763f59041de223b" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/sigrokproject/libserialport" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A minimal, cross-platform shared library written in C that is intended to take care of the OS-specific details when writing software that uses serial ports." +PKG_TOOLCHAIN="make" + +make_target() { + cd ${PKG_BUILD} + + ./autogen.sh + ./configure --host=${TARGET_NAME} --with-sysroot=${SYSROOT_PREFIX} --prefix=/usr +} diff --git a/projects/ArchR/packages/devel/libthai/package.mk b/projects/ArchR/packages/devel/libthai/package.mk new file mode 100644 index 0000000000..fe52fd44eb --- /dev/null +++ b/projects/ArchR/packages/devel/libthai/package.mk @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="libthai" +PKG_VERSION="0.1.29" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/tlwg/libthai" +PKG_URL="${PKG_SITE}/releases/download/v${PKG_VERSION}/libthai-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain libtool libdatrie" +PKG_BUILD_FLAGS="+pic" +PKG_TOOLCHAIN="configure" + +PKG_CONFIGURE_OPTS_TARGET=" --disable-dict --disable-doxygen-doc" + diff --git a/projects/ArchR/packages/devel/m4/package.mk b/projects/ArchR/packages/devel/m4/package.mk new file mode 100644 index 0000000000..0c6c2f56dc --- /dev/null +++ b/projects/ArchR/packages/devel/m4/package.mk @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2026 ArchR (https://github.com/archr-linux/Arch-R) +# Override: downgrade to 1.4.19 to avoid gnulib _Generic conflicts with GCC 15+ +# m4 1.4.20 ships gnulib with _Generic macros that produce syntax errors on GCC 15 + +PKG_NAME="m4" +PKG_VERSION="1.4.19" +PKG_SHA256="63aede5c6d33b6d9b13511cd0be2cac046f2e70fd0a07aa9573a04a82783af96" +PKG_LICENSE="GPL" +PKG_SITE="http://www.gnu.org/software/m4/" +PKG_URL="https://mirrors.kernel.org/gnu/m4/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_HOST="ccache:host" +PKG_LONGDESC="The m4 macro processor." +PKG_BUILD_FLAGS="-cfg-libs:host" + +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/projects/ArchR/packages/devel/make/package.mk b/projects/ArchR/packages/devel/make/package.mk new file mode 100644 index 0000000000..467ccda2f0 --- /dev/null +++ b/projects/ArchR/packages/devel/make/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) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="make" +PKG_VERSION="4.4.1" +PKG_SHA256="dd16fb1d67bfab79a72f5e8390735c49e3e8e70b4945a15ab1f81ddb78658fb3" +PKG_LICENSE="GPLv3" +PKG_SITE="https://www.gnu.org/software/make/" +PKG_URL="https://mirrors.kernel.org/gnu/make/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="" +PKG_DEPENDS_TARGET="toolchain:host" +PKG_LONGDESC="Utility to maintain groups of programs." +PKG_BUILD_FLAGS="+local-cc -cfg-libs:host" + +post_makeinstall_host() { + ln -sf make ${TOOLCHAIN}/bin/gmake +} diff --git a/projects/ArchR/packages/devel/make/patches/make-02-fix-large-command-line-on-POSIX-systems.patch b/projects/ArchR/packages/devel/make/patches/make-02-fix-large-command-line-on-POSIX-systems.patch new file mode 100644 index 0000000000..12ac8b767a --- /dev/null +++ b/projects/ArchR/packages/devel/make/patches/make-02-fix-large-command-line-on-POSIX-systems.patch @@ -0,0 +1,170 @@ +From e249c43741779ae7dd6834f6840384257d4c3dd8 Mon Sep 17 00:00:00 2001 +From: Mike Crowe +Date: Fri, 6 Nov 2020 15:22:37 +0000 +Subject: [PATCH] [SV 45763] Fix large command line on POSIX systems + +When presented with a very long command line (as is common when linking +a large number of files with absolute paths in a deep subdirectory), +make fails to execute the command as it doesn't split the command line +to fit within the limits. + +This is based on a fix for Debian bug 688601[1] by Adam Conrad applied +by Manoj Srivastava originally applied for Debian make-dfsg 4.0-5 in +2014 but dropped in 2018 (it seems under the incorrect assumption that +it had been accepted upstream.) + +I've tweaked Adam's original patch so that it compiles successfully with +-Werror on top of current master. This required: + +* moving the eval_line declaration to the top of the block, so I moved + the macros too +* using a const variable when iterating over the shell +* adding a cast to avoid a signed/unsigned mismatch. + +As suggested in the Savannah bug report[2], I've added a test case that +fails without the rest of the patch. I'm not sure what the consequences +of running the test on non-POSIX targets would be and whether it needs +marking as an expected failure. + +* src/job.c (construct_command_argv_internal): support running commands +longer than MAX_ARG_STRLEN +* tests/scripts/features/long_command_line: add test for such a command +* configure.ac: check for now-required sys/user.h and linux/binfmts.h +headers + +[1] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=688601 +[2] https://savannah.gnu.org/bugs/?45763#comment2 +--- + src/job.c | 52 +++++++++++++++++++++++- + tests/scripts/features/long_command_line | 30 ++++++++++++++ + 2 files changed, 81 insertions(+), 1 deletions(-) + create mode 100644 tests/scripts/features/long_command_line + +diff --git a/src/job.c b/src/job.c +index 3bcec38..734c591 100644 +--- a/src/job.c ++++ b/src/job.c +@@ -26,6 +26,12 @@ this program. If not, see . */ + #include "variable.h" + #include "os.h" + ++#include ++#include ++#ifndef PAGE_SIZE ++# define PAGE_SIZE (sysconf(_SC_PAGESIZE)) ++#endif ++ + /* Default shell to use. */ + #ifdef WINDOWS32 + # ifdef HAVE_STRINGS_H +@@ -3228,6 +3236,15 @@ construct_command_argv_internal (char *line, char **restp, const char *shell, + size_t sflags_len = shellflags ? strlen (shellflags) : 0; + #ifdef WINDOWS32 + char *command_ptr = NULL; /* used for batch_mode_shell mode */ ++#endif ++ char *args_ptr; ++#ifdef MAX_ARG_STRLEN ++ static char eval_line[] = "eval\\ \\\"set\\ x\\;\\ shift\\;\\ "; ++#define ARG_NUMBER_DIGITS 5 ++#define EVAL_LEN (sizeof(eval_line)-1 + shell_len + 4 \ ++ + (7 + ARG_NUMBER_DIGITS) * 2 * line_len / (MAX_ARG_STRLEN - 2)) ++#else ++#define EVAL_LEN 0 + #endif + + # ifdef __EMX__ /* is this necessary? */ +@@ -3395,7 +3412,7 @@ construct_command_argv_internal (char *line, char **restp, const char *shell, + } + + new_line = xmalloc ((shell_len*2) + 1 + sflags_len + 1 +- + (line_len*2) + 1); ++ + (line_len*2) + 1 + EVAL_LEN); + ap = new_line; + /* Copy SHELL, escaping any characters special to the shell. If + we don't escape them, construct_command_argv_internal will +@@ -3415,6 +3432,31 @@ construct_command_argv_internal (char *line, char **restp, const char *shell, + #ifdef WINDOWS32 + command_ptr = ap; + #endif ++ ++#if !defined (WINDOWS32) && defined (MAX_ARG_STRLEN) ++ if (unixy_shell && line_len > MAX_ARG_STRLEN) ++ { ++ const char *q; ++ unsigned j; ++ memcpy (ap, eval_line, sizeof (eval_line) - 1); ++ ap += sizeof (eval_line) - 1; ++ for (j = 1; j <= 2 * line_len / (MAX_ARG_STRLEN - 2); j++) ++ ap += sprintf (ap, "\\$\\{%u\\}", j); ++ *ap++ = '\\'; ++ *ap++ = '"'; ++ *ap++ = ' '; ++ /* Copy only the first word of SHELL to $0. */ ++ for (q = shell; *q != '\0'; ++q) ++ { ++ if (isspace ((unsigned char)*q)) ++ break; ++ *ap++ = *q; ++ } ++ *ap++ = ' '; ++ } ++#endif ++ args_ptr = ap; ++ + for (p = line; *p != '\0'; ++p) + { + if (restp != NULL && *p == '\n') +@@ -3462,6 +3504,14 @@ construct_command_argv_internal (char *line, char **restp, const char *shell, + } + #endif + *ap++ = *p; ++#if !defined (WINDOWS32) && defined (MAX_ARG_STRLEN) ++ if (unixy_shell && line_len > MAX_ARG_STRLEN ++ && (ap - args_ptr > (long)(MAX_ARG_STRLEN - 2))) ++ { ++ *ap++ = ' '; ++ args_ptr = ap; ++ } ++#endif + } + if (ap == new_line + shell_len + sflags_len + 2) + { +diff --git a/tests/scripts/features/long_command_line b/tests/scripts/features/long_command_line +new file mode 100644 +index 0000000..3899ac8 +--- /dev/null ++++ b/tests/scripts/features/long_command_line +@@ -0,0 +1,30 @@ ++# -*-perl-*- ++$description = "Test long command line."; ++ ++$details = ""; ++ ++# Variable names containing UTF8 characters ++run_make_test(q! ++# 49 characters ++ARGS:=one two three four five six seven eight niner ten ++# 49*4+3 = 199 characters ++ARGS:=$(ARGS) $(ARGS) $(ARGS) $(ARGS) ++# 199*4+3 = 799 characters ++ARGS:=$(ARGS) $(ARGS) $(ARGS) $(ARGS) ++# 799*4+3 = 3199 characters ++ARGS:=$(ARGS) $(ARGS) $(ARGS) $(ARGS) ++# 3199*4+3 = 12799 characters ++ARGS:=$(ARGS) $(ARGS) $(ARGS) $(ARGS) ++# 12799*4+3 = 51199 characters ++ARGS:=$(ARGS) $(ARGS) $(ARGS) $(ARGS) ++# 51199*4+3 = 204799 characters ++ARGS:=$(ARGS) $(ARGS) $(ARGS) $(ARGS) ++# 24799*2+1 = 409599 characters ++#ARGS:=$(ARGS) $(ARGS) ++ ++test: ++ @: $(ARGS) ++!, ++ '', ""); ++ ++1; +-- +2.20.1 + diff --git a/projects/ArchR/packages/devel/ncurses/package.mk b/projects/ArchR/packages/devel/ncurses/package.mk new file mode 100644 index 0000000000..8daf772e58 --- /dev/null +++ b/projects/ArchR/packages/devel/ncurses/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) 2017-present Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="ncurses" +PKG_VERSION="6.4" +PKG_LICENSE="MIT" +PKG_SITE="http://www.gnu.org/software/ncurses/" +PKG_URL="http://invisible-island.net/archives/ncurses/ncurses-${PKG_VERSION}.tar.gz" +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." +PKG_BUILD_FLAGS="+pic +pic:host" +PKG_TOOLCHAIN="auto" + +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 \ + --enable-tcap-names \ + --without-develop \ + --disable-hard-tabs \ + --disable-xmc-glitch \ + --disable-hashmap \ + --disable-safe-sprintf \ + --disable-scroll-hints \ + --enable-widec \ + --disable-echo \ + --disable-warnings \ + --enable-home-terminfo \ + --enable-lib-suffixes \ + --disable-assertions" + +PKG_CONFIGURE_OPTS_HOST=" + --without-cxx-binding \ + --enable-termcap \ + --with-termlib \ + --without-shared \ + --enable-pc-files \ + --without-tests \ + --without-manpages" + +post_makeinstall_target() { + local f + cp misc/ncurses-config ${TOOLCHAIN}/bin + chmod +x ${TOOLCHAIN}/bin/ncurses-config + sed -e "s:\(['=\" ]\)/usr:\\1${PKG_ORIG_SYSROOT_PREFIX}/usr:g" -i ${TOOLCHAIN}/bin/ncurses-config + rm -f ${TOOLCHAIN}/bin/ncurses6-config + rm -rf ${INSTALL}/usr/bin + # create links to be compatible with any ncurses include path and lib names + ln -sf . ${SYSROOT_PREFIX}/usr/include/ncursesw + ln -sf . ${SYSROOT_PREFIX}/usr/include/ncurses + for f in form menu ncurses panel tinfo; do + ln -sf lib${f}w.a ${SYSROOT_PREFIX}/usr/lib/lib${f}.a + ln -sf ${f}w.pc ${SYSROOT_PREFIX}/usr/lib/pkgconfig/${f}.pc + done + cd ${INSTALL}/usr/lib + for LIB in *w*.so* + do + NOWLIB=$(echo ${LIB} | sed "s#w##g") + ln -sf ${LIB} ${INSTALL}/usr/lib/${NOWLIB} + done + cd - +} diff --git a/projects/ArchR/packages/devel/ncurses/patches/ncurses-001-terminfo-xterm.patch b/projects/ArchR/packages/devel/ncurses/patches/ncurses-001-terminfo-xterm.patch new file mode 100644 index 0000000000..3c2a9d0f0c --- /dev/null +++ b/projects/ArchR/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 2021-03-20 22:45:39.000000000 +0100 ++++ b/misc/terminfo.src 2021-06-01 23:53:10.335516419 +0200 +@@ -4808,8 +4808,8 @@ xterm-xfree86|xterm terminal emulator (X + xterm+nofkeys|building block for xterm fkey-variants, + npc, + kcbt=\E[Z, kent=\EOM, nel=\EE, use=ecma+index, +- use=ansi+rep, use=ecma+strikeout, use=vt420+lrmm, +- use=xterm+sm+1006, use=xterm+tmux, use=ecma+italics, ++ use=ecma+strikeout, use=vt420+lrmm, ++ use=xterm+sm+1005, use=xterm+tmux, use=ecma+italics, + use=xterm+keypad, use=xterm-basic, + + # This version reflects the current xterm features. diff --git a/projects/ArchR/packages/devel/ncurses/patches/ncurses-002-alloc-fallbacks.patch b/projects/ArchR/packages/devel/ncurses/patches/ncurses-002-alloc-fallbacks.patch new file mode 100644 index 0000000000..eaf093adb5 --- /dev/null +++ b/projects/ArchR/packages/devel/ncurses/patches/ncurses-002-alloc-fallbacks.patch @@ -0,0 +1,13 @@ +Fix freeing not allocated fallback entries by allocating a copy. + +--- 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 +@@ -180,6 +180,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/projects/ArchR/packages/devel/ncurses/patches/ncurses-003-fix_hints.patch b/projects/ArchR/packages/devel/ncurses/patches/ncurses-003-fix_hints.patch new file mode 100644 index 0000000000..8462304867 --- /dev/null +++ b/projects/ArchR/packages/devel/ncurses/patches/ncurses-003-fix_hints.patch @@ -0,0 +1,18 @@ +Fix USE_SCROLL_HINTS/USE_HASHMAP logic + +--- a/ncurses/curses.priv.h 2018-12-16 02:16:58.000000000 +0100 ++++ a/ncurses/curses.priv.h 2021-05-30 00:12:14.086528124 +0200 +@@ -258,10 +258,9 @@ extern NCURSES_EXPORT(void *) _nc_memmov + /* + * Scroll hints are useless when hashmap is used + */ +-#if !USE_SCROLL_HINTS +-#if !USE_HASHMAP +-#define USE_SCROLL_HINTS 1 +-#else ++#if USE_SCROLL_HINTS ++#if USE_HASHMAP ++#undef USE_SCROLL_HINTS + #define USE_SCROLL_HINTS 0 + #endif + #endif diff --git a/projects/ArchR/packages/devel/ncurses/patches/ncurses-004-fix_configure_pkgconfig.patch b/projects/ArchR/packages/devel/ncurses/patches/ncurses-004-fix_configure_pkgconfig.patch new file mode 100644 index 0000000000..171145cd09 --- /dev/null +++ b/projects/ArchR/packages/devel/ncurses/patches/ncurses-004-fix_configure_pkgconfig.patch @@ -0,0 +1,12 @@ +diff -rupN ncurses-6.4.orig/configure ncurses-6.4/configure +--- ncurses-6.4.orig/configure 2022-11-05 21:13:26.000000000 +0000 ++++ ncurses-6.4/configure 2023-05-09 11:21:38.765534941 +0000 +@@ -4236,7 +4236,7 @@ echo $ECHO_N "checking for first directo + cf_pkg_config_path=none + for cf_config in $cf_search_path + do +- if test -d "$cf_config" ++ if test -n "$cf_config" + then + cf_pkg_config_path=$cf_config + break diff --git a/projects/ArchR/packages/devel/patchelf/package.mk b/projects/ArchR/packages/devel/patchelf/package.mk new file mode 100644 index 0000000000..5205689e11 --- /dev/null +++ b/projects/ArchR/packages/devel/patchelf/package.mk @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2023-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="patchelf" +PKG_VERSION="0.18.0" +PKG_SHA256="1952b2a782ba576279c211ee942e341748fdb44997f704dd53def46cd055470b" +PKG_LICENSE="GPL-3.0-or-later" +PKG_SITE="https://github.com/NixOS/patchelf" +PKG_URL="https://github.com/NixOS/patchelf/releases/download/${PKG_VERSION}/patchelf-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_HOST="autotools:host" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A small utility to modify the dynamic linker and RPATH of ELF executables" +PKG_TOOLCHAIN="autotools" +PKG_BUILD_FLAGS="-cfg-libs:host" diff --git a/projects/ArchR/packages/devel/readline/package.mk b/projects/ArchR/packages/devel/readline/package.mk new file mode 100644 index 0000000000..796ca3679f --- /dev/null +++ b/projects/ArchR/packages/devel/readline/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +. ${ROOT}/packages/devel/readline/package.mk + +PKG_CONFIGURE_OPTS_TARGET="bash_cv_wcwidth_broken=no \ + --enable-shared \ + --disable-static \ + --with-curses" + +# Ensure shared libreadline.so links against ncurses (provides termcap symbols: BC, UP, tputs, etc.) +PKG_MAKE_OPTS_TARGET="SHLIB_LIBS=-lncursesw" +PKG_MAKEINSTALL_OPTS_TARGET="SHLIB_LIBS=-lncursesw" + +pre_configure_target() { + export LDFLAGS="${LDFLAGS} -lncursesw" +} diff --git a/projects/ArchR/packages/devel/readline/patches/01-fix-iwd.patch b/projects/ArchR/packages/devel/readline/patches/01-fix-iwd.patch new file mode 100644 index 0000000000..7458dd4545 --- /dev/null +++ b/projects/ArchR/packages/devel/readline/patches/01-fix-iwd.patch @@ -0,0 +1,15 @@ +*** a/display.c +--- b/display.c +*************** +*** 784,788 **** + /* Useful shorthand used by rl_redisplay, update_line, rl_move_cursor_relative */ + #define INVIS_FIRST() (local_prompt_invis_chars[0]) +! #define WRAP_OFFSET(line, offset) ((line <= prompt_last_screen_line) ? local_prompt_invis_chars[line] : 0) + + #define W_OFFSET(line, offset) ((line) == 0 ? offset : 0) +--- 784,788 ---- + /* Useful shorthand used by rl_redisplay, update_line, rl_move_cursor_relative */ + #define INVIS_FIRST() (local_prompt_invis_chars[0]) +! #define WRAP_OFFSET(line, offset) ((line <= prompt_last_screen_line && local_prompt_invis_chars) ? local_prompt_invis_chars[line] : 0) + + #define W_OFFSET(line, offset) ((line) == 0 ? offset : 0) diff --git a/projects/ArchR/packages/devel/shared-mime-info/package.mk b/projects/ArchR/packages/devel/shared-mime-info/package.mk new file mode 100644 index 0000000000..d0abba6de2 --- /dev/null +++ b/projects/ArchR/packages/devel/shared-mime-info/package.mk @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="shared-mime-info" +PKG_VERSION="2.4" +PKG_LICENSE="GPL-2.0-only" +PKG_SITE="https://freedesktop.org/wiki/Software/shared-mime-info/" +PKG_URL="https://gitlab.freedesktop.org/xdg/${PKG_NAME}/-/archive/${PKG_VERSION}/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_HOST="toolchain:host glib:host libxml2:host gettext:host itstool:host" +PKG_DEPENDS_TARGET="toolchain glib libxml2 gettext shared-mime-info:host" +PKG_LONGDESC="The shared-mime-info package contains the core database of common types." +PKG_BUILD_FLAGS="-parallel" + +configure_package() { + # Sway Support + if [ ! "${WINDOWMANAGER}" = "sway" ]; then + PKG_BUILD_FLAGS+=" -sysroot" + fi +} + +PKG_MESON_OPTS_HOST="-Dupdate-mimedb=false" +PKG_MESON_OPTS_TARGET="-Dupdate-mimedb=false" + +post_makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/pkgconfig + cp shared-mime-info.pc ${SYSROOT_PREFIX}/usr/lib/pkgconfig + + # Create /usr/share/mime/mime.cache + if [ "${WINDOWMANAGER}" = "sway" ]; then + ${TOOLCHAIN}/bin/update-mime-database ${INSTALL}/usr/share/mime + fi +} diff --git a/projects/ArchR/packages/devel/swig/package.mk b/projects/ArchR/packages/devel/swig/package.mk new file mode 100644 index 0000000000..829c79652d --- /dev/null +++ b/projects/ArchR/packages/devel/swig/package.mk @@ -0,0 +1,45 @@ +# 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.1.1" +PKG_SHA256="2af08aced8fcd65cdb5cc62426768914bedc735b1c250325203716f78e39ac9b" +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_TOOLCHAIN="configure" + +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/projects/ArchR/packages/devel/xa/package.mk b/projects/ArchR/packages/devel/xa/package.mk new file mode 100644 index 0000000000..df960f1750 --- /dev/null +++ b/projects/ArchR/packages/devel/xa/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="xa" +PKG_VERSION="2.4.1" +PKG_LICENSE="GPL" +PKG_SITE="http://tinycorelinux.net" +PKG_URL="${PKG_SITE}/15.x/x86/tcz/src/xa/xa-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_DEPENDS_HOST="ccache:host" +PKG_LONGDESC="xa is a high-speed, two-pass portable cross-assembler." + +makeinstall_host() { + mkdir -p ${TOOLCHAIN}/bin + cp -f file65 ldo65 mkrom.sh printcbm reloc65 uncpk xa ${TOOLCHAIN}/bin +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp -f file65 ldo65 mkrom.sh printcbm reloc65 uncpk xa ${INSTALL}/usr/bin +} diff --git a/projects/ArchR/packages/emulators/libretro/81-lr/package.mk b/projects/ArchR/packages/emulators/libretro/81-lr/package.mk new file mode 100644 index 0000000000..4040f6d0a4 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/81-lr/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="81-lr" +PKG_VERSION="ffc99f27f092addc9ddd34dd0e3a3d4d1c053cbf" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/libretro/81-libretro" +PKG_URL="https://github.com/libretro/81-libretro/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A port of the EightyOne ZX81 Emulator to libretro" + +PKG_TOOLCHAIN="make" + +make_target() { + make -f Makefile.libretro +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp 81_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/a5200-lr/package.mk b/projects/ArchR/packages/emulators/libretro/a5200-lr/package.mk new file mode 100644 index 0000000000..e5a111bea2 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/a5200-lr/package.mk @@ -0,0 +1,36 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) +# +# 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="a5200-lr" +PKG_VERSION="526404072821bb2021fab16f8c5dbbca300512c8" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/libretro/a5200" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Atari 5200 libretro core" +PKG_TOOLCHAIN="auto" +GET_HANDLER_SUPPORT="git" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp a5200_libretro.so ${INSTALL}/usr/lib/libretro/ +} + diff --git a/projects/ArchR/packages/emulators/libretro/arduous-lr/package.mk b/projects/ArchR/packages/emulators/libretro/arduous-lr/package.mk new file mode 100644 index 0000000000..18b5197914 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/arduous-lr/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="arduous-lr" +PKG_VERSION="50c1e48084f003dee582ed5f4f5c0f59eb30bc4c" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/libretro/arduous" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A Libretro emulator core for the Arduboy" + +PKG_CMAKE_OPTS_TARGET="-DCMAKE_POLICY_VERSION_MINIMUM=3.5" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp arduous_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/atari800-lr/package.mk b/projects/ArchR/packages/emulators/libretro/atari800-lr/package.mk new file mode 100644 index 0000000000..0985b7fee3 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/atari800-lr/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) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) +# +# 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="atari800-lr" +PKG_VERSION="6a18cb23cc4a7cecabd9b16143d2d7332ae8d44b" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/libretro/libretro-atari800" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="atari800 3.1.0 for libretro/libco WIP" +PKG_TOOLCHAIN="auto" +GET_HANDLER_SUPPORT="git" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp atari800_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/b2-lr/package.mk b/projects/ArchR/packages/emulators/libretro/b2-lr/package.mk new file mode 100644 index 0000000000..a97cf28ae9 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/b2-lr/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="b2-lr" +PKG_VERSION="ffcfcddc5ba05a97e04372672879bc25284ff653" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/zoltanvb/b2-libretro" +PKG_URL="https://github.com/zoltanvb/b2-libretro/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Adaptation of Tom Seddon's b2 emulator for BBC Micro" + +PKG_TOOLCHAIN="make" + +make_target() { + cd ${PKG_BUILD}/src/libretro + make -j$(getconf _NPROCESSORS_ONLN) clean + make -j$(getconf _NPROCESSORS_ONLN) +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp b2_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/b2-lr/patches/01-fix-gcc14.patch b/projects/ArchR/packages/emulators/libretro/b2-lr/patches/01-fix-gcc14.patch new file mode 100644 index 0000000000..843c8592a8 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/b2-lr/patches/01-fix-gcc14.patch @@ -0,0 +1,17 @@ +diff --git a/src/shared/h/shared/system.h b/src/shared/h/shared/system.h +index f5f38b34..2d765a07 100644 +--- a/src/shared/h/shared/system.h ++++ b/src/shared/h/shared/system.h +@@ -289,7 +289,11 @@ int vasprintf(char **buf, const char *fmt, va_list v); + // + // See https://lwn.net/Articles/612244/ + #ifndef HAVE_STRLCPY ++#if __GNUC__ >= 14 ++extern "C" size_t strlcpy(char *dest, const char *src, size_t size) noexcept; ++#else + size_t strlcpy(char *dest, const char *src, size_t size); ++#endif + #endif // HAVE_STRLCPY + #endif + + diff --git a/projects/ArchR/packages/emulators/libretro/beetle-gba-lr/package.mk b/projects/ArchR/packages/emulators/libretro/beetle-gba-lr/package.mk new file mode 100644 index 0000000000..3f5b322e09 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/beetle-gba-lr/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) +# 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="beetle-gba-lr" +PKG_VERSION="6cee80685f735ea6c2373db2622a1f1ee9f39d39" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/beetle-gba-libretro" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="libretro implementation of Mednafen VBA/GBA. (Game Boy Advance)" + +PKG_TOOLCHAIN="make" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp mednafen_gba_libretro.so ${INSTALL}/usr/lib/libretro/beetle_gba_libretro.so +} diff --git a/projects/ArchR/packages/emulators/libretro/beetle-lynx-lr/package.mk b/projects/ArchR/packages/emulators/libretro/beetle-lynx-lr/package.mk new file mode 100644 index 0000000000..6d29e845a8 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/beetle-lynx-lr/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) +# 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="beetle-lynx-lr" +PKG_VERSION="efd1797c7aa5a83c354507b1b61ac24222ebaa58" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/beetle-lynx-libretro" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="libretro implementation of Mednafen Lynx" + +PKG_TOOLCHAIN="make" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp mednafen_lynx_libretro.so ${INSTALL}/usr/lib/libretro/beetle_lynx_libretro.so +} diff --git a/projects/ArchR/packages/emulators/libretro/beetle-ngp-lr/package.mk b/projects/ArchR/packages/emulators/libretro/beetle-ngp-lr/package.mk new file mode 100644 index 0000000000..2b5f17ecd8 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/beetle-ngp-lr/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) +# 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="beetle-ngp-lr" +PKG_VERSION="139fe34c8dfc5585d6ee1793a7902bca79d544de" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/beetle-ngp-libretro" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="libretro implementation of Mednafen Neo Geo Pocket." + +PKG_TOOLCHAIN="make" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp mednafen_ngp_libretro.so ${INSTALL}/usr/lib/libretro/beetle_ngp_libretro.so +} diff --git a/projects/ArchR/packages/emulators/libretro/beetle-pce-fast-lr/package.mk b/projects/ArchR/packages/emulators/libretro/beetle-pce-fast-lr/package.mk new file mode 100644 index 0000000000..f3f14b2474 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/beetle-pce-fast-lr/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) +# 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="beetle-pce-fast-lr" +PKG_VERSION="7e9b257b8a591cb7e00f9e55371edba19db9799c" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/beetle-pce-fast-libretro" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Standalone port of Mednafen PCE Fast to libretro." + +PKG_TOOLCHAIN="make" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp mednafen_pce_fast_libretro.so ${INSTALL}/usr/lib/libretro/beetle_pce_fast_libretro.so +} diff --git a/projects/ArchR/packages/emulators/libretro/beetle-pce-lr/package.mk b/projects/ArchR/packages/emulators/libretro/beetle-pce-lr/package.mk new file mode 100644 index 0000000000..6bb8ea70e9 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/beetle-pce-lr/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) +# 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="beetle-pce-lr" +PKG_VERSION="9a301c0773c53702a882bbaa42ee9cbc6d523787" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/beetle-pce-libretro" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Standalone port of Mednafen PCE to libretro." + +PKG_TOOLCHAIN="make" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp mednafen_pce_libretro.so ${INSTALL}/usr/lib/libretro/beetle_pce_libretro.so +} diff --git a/projects/ArchR/packages/emulators/libretro/beetle-pcfx-lr/package.mk b/projects/ArchR/packages/emulators/libretro/beetle-pcfx-lr/package.mk new file mode 100644 index 0000000000..4a28c1a536 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/beetle-pcfx-lr/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="beetle-pcfx-lr" +PKG_VERSION="dd04cef9355286488a1d78ff18c4c848a1575540" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/beetle-pcfx-libretro" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="libretro implementation of Mednafen PC-FX." + +PKG_TOOLCHAIN="make" + +make_target() { + if [ "${ARCH}" == "i386" -o "${ARCH}" == "x86_64" ]; then + make platform=unix CC=${CC} CXX=${CXX} AR=${AR} + else + make platform=armv CC=${CC} CXX=${CXX} AR=${AR} + fi +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp mednafen_pcfx_libretro.so ${INSTALL}/usr/lib/libretro/beetle_pcfx_libretro.so +} diff --git a/projects/ArchR/packages/emulators/libretro/beetle-psx-lr/package.mk b/projects/ArchR/packages/emulators/libretro/beetle-psx-lr/package.mk new file mode 100644 index 0000000000..18874f1375 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/beetle-psx-lr/package.mk @@ -0,0 +1,30 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="beetle-psx-lr" +PKG_VERSION="4e0cb4ddf0c52ef802cd4f7f2b7d3a187ab9962d" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/beetle-psx-libretro" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Fork of Mednafen PSX" +PKG_TOOLCHAIN="make" + +if [ ! "${OPENGL}" = "no" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL} glu libglvnd" +fi + +if [ "${OPENGLES_SUPPORT}" = yes ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" +fi + +if [ "${VULKAN_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${VULKAN}" +fi + +PKG_MAKE_OPTS_TARGET+=" LINK_STATIC_LIBCPLUSPLUS=0" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp mednafen_psx_libretro.so ${INSTALL}/usr/lib/libretro/beetle_psx_libretro.so +} diff --git a/projects/ArchR/packages/emulators/libretro/beetle-saturn-lr/package.mk b/projects/ArchR/packages/emulators/libretro/beetle-saturn-lr/package.mk new file mode 100644 index 0000000000..fb6f6c7fdd --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/beetle-saturn-lr/package.mk @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="beetle-saturn-lr" +PKG_VERSION="06c9daa7ff6de42955437d29a80d8fc4ececc8d3" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/beetle-saturn-libretro" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Beetle Saturn libretro, a fork from mednafen" +PKG_TOOLCHAIN="make" + +if [ ! "${OPENGL}" = "no" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL} glu libglvnd" +fi + +if [ "${OPENGLES_SUPPORT}" = yes ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" +fi + +make_target() { + if [ "${ARCH}" == "i386" -o "${ARCH}" == "x86_64" ]; then + make platform=unix CC=${CC} CXX=${CXX} AR=${AR} + else + make platform=armv CC=${CC} CXX=${CXX} AR=${AR} + fi +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp mednafen_saturn_libretro.so ${INSTALL}/usr/lib/libretro/beetle_saturn_libretro.so +} diff --git a/projects/ArchR/packages/emulators/libretro/beetle-supafaust-lr/config/Supafaust.opt b/projects/ArchR/packages/emulators/libretro/beetle-supafaust-lr/config/Supafaust.opt new file mode 100644 index 0000000000..5c73e159c8 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/beetle-supafaust-lr/config/Supafaust.opt @@ -0,0 +1,19 @@ +supafaust_audio_rate = "disabled" +supafaust_correct_aspect = "enabled" +supafaust_cx4_clock_rate = "100" +supafaust_deinterlacer = "bob_offset" +supafaust_frame_begin_vblank = "enabled" +supafaust_h_filter = "phr256blend_auto512" +supafaust_multitap = "disabled" +supafaust_pixel_format = "rgb565" +supafaust_region = "auto" +supafaust_renderer = "mt" +supafaust_run_ahead = "disabled" +supafaust_slend = "223" +supafaust_slendp = "238" +supafaust_slstart = "0" +supafaust_slstartp = "0" +supafaust_superfx_clock_rate = "100" +supafaust_superfx_icache = "disabled" +supafaust_thread_affinity_emu = "0x3" +supafaust_thread_affinity_ppu = "0xc" diff --git a/projects/ArchR/packages/emulators/libretro/beetle-supafaust-lr/package.mk b/projects/ArchR/packages/emulators/libretro/beetle-supafaust-lr/package.mk new file mode 100644 index 0000000000..26abdf1c98 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/beetle-supafaust-lr/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) +# 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="beetle-supafaust-lr" +PKG_VERSION="e25f66765938d33f9ad5850e8d6cd597e55b7299" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/supafaust" +PKG_URL="${PKG_SITE}.git" +#PKG_GIT_CLONE_BRANCH="hd" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Super Nintendo (Super Famicom) emulator" +GET_HANDLER_SUPPORT="git" +PKG_TOOLCHAIN="make" + + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp ${PKG_BUILD}/mednafen_supafaust_libretro.so ${INSTALL}/usr/lib/libretro/beetle_supafaust_libretro.so + + mkdir -p ${INSTALL}/usr/config/retroarch + cp -rf ${PKG_DIR}/config/* ${INSTALL}/usr/config/retroarch/ +} diff --git a/projects/ArchR/packages/emulators/libretro/beetle-supergrafx-lr/package.mk b/projects/ArchR/packages/emulators/libretro/beetle-supergrafx-lr/package.mk new file mode 100644 index 0000000000..9d6d69037a --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/beetle-supergrafx-lr/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) +# 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="beetle-supergrafx-lr" +PKG_VERSION="a776133c34ae8da5daf7d9ccb43e3e292e2b07b0" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/beetle-supergrafx-libretro" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Standalone port of Mednafen PCE Fast to libretro." + +PKG_TOOLCHAIN="make" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp mednafen_supergrafx_libretro.so ${INSTALL}/usr/lib/libretro/beetle_supergrafx_libretro.so +} diff --git a/projects/ArchR/packages/emulators/libretro/beetle-vb-lr/package.mk b/projects/ArchR/packages/emulators/libretro/beetle-vb-lr/package.mk new file mode 100644 index 0000000000..9924eefd6f --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/beetle-vb-lr/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) +# 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="beetle-vb-lr" +PKG_VERSION="8f837ebc077afdd6652efb2827fd8308a07113ca" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/beetle-vb-libretro" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="libretro implementation of Mednafen VB. (VirtualBoy)" + +PKG_TOOLCHAIN="make" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp mednafen_vb_libretro.so ${INSTALL}/usr/lib/libretro/beetle_vb_libretro.so +} diff --git a/projects/ArchR/packages/emulators/libretro/beetle-wswan-lr/package.mk b/projects/ArchR/packages/emulators/libretro/beetle-wswan-lr/package.mk new file mode 100644 index 0000000000..83b4176936 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/beetle-wswan-lr/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) +# 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="beetle-wswan-lr" +PKG_VERSION="2aeb47d3a58bf0360c686f842d9bb5bd201306fe" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/beetle-wswan-libretro" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="libretro implementation of Mednafen wswan" + +PKG_TOOLCHAIN="make" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp mednafen_wswan_libretro.so ${INSTALL}/usr/lib/libretro/beetle_wswan_libretro.so +} diff --git a/projects/ArchR/packages/emulators/libretro/bluemsx-lr/package.mk b/projects/ArchR/packages/emulators/libretro/bluemsx-lr/package.mk new file mode 100644 index 0000000000..008b5ca8e3 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/bluemsx-lr/package.mk @@ -0,0 +1,39 @@ +################################################################################ +# 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="bluemsx-lr" +PKG_VERSION="036376d6679c9e153712dbbb3fdca774afc49706" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/blueMSX-libretro" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Port of blueMSX to the libretro API." + +PKG_TOOLCHAIN="make" + +make_target() { + make -f Makefile.libretro +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp bluemsx_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/boom3-lr/package.mk b/projects/ArchR/packages/emulators/libretro/boom3-lr/package.mk new file mode 100644 index 0000000000..d235d93512 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/boom3-lr/package.mk @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="boom3-lr" +PKG_VERSION="0bea79abf5ec8262dfe9af73cb8c54ea6e2aeb98" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/libretro/boom3" +PKG_URL="https://github.com/libretro/boom3/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Doom3 - dhewm3 port to libretro." +PKG_TOOLCHAIN="make" + +if [ "${OPENGL_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL}" +elif [ "${OPENGLES_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" +fi + +make_target() { + make -C neo BASE=1 + make -C neo D3XP=1 +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp -v ${PKG_BUILD}/neo/boom3_libretro.so ${INSTALL}/usr/lib/libretro/ + cp -v ${PKG_BUILD}/neo/boom3_xp_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/bsnes-hd-lr/package.mk b/projects/ArchR/packages/emulators/libretro/bsnes-hd-lr/package.mk new file mode 100644 index 0000000000..199267b926 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/bsnes-hd-lr/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2023-present Daedalia (https://github.com/daedalia) + +PKG_NAME="bsnes-hd-lr" +PKG_VERSION="0bb7b8645e22ea2476cabd58f32e987b14686601" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/DerKoun/bsnes-hd" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="bsnes-hd is a fork of bsnes that adds HD video features such as widescreen, HD Mode 7 and true color" + +PKG_TOOLCHAIN="make" + +PKG_MAKE_OPTS_TARGET+=" -C bsnes target=libretro compiler=${TARGET_NAME}-g++" + +pre_configure_target() { + sed -i 's/\-O[23]/-Ofast/' ${PKG_BUILD}/bsnes/GNUmakefile +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp bsnes/out/bsnes_hd_beta_libretro.so ${INSTALL}/usr/lib/libretro/ +} + diff --git a/projects/ArchR/packages/emulators/libretro/bsnes-hd-lr/patches/makefile-remove-build-flags.patch b/projects/ArchR/packages/emulators/libretro/bsnes-hd-lr/patches/makefile-remove-build-flags.patch new file mode 100644 index 0000000000..95a6901487 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/bsnes-hd-lr/patches/makefile-remove-build-flags.patch @@ -0,0 +1,12 @@ +diff --git a/bsnes/GNUmakefile b/bsnes/GNUmakefile +index 58466fb..578a916 100644 +--- a/bsnes/GNUmakefile ++++ b/bsnes/GNUmakefile +@@ -37,7 +37,6 @@ else ifeq ($(platform),macos) + else ifneq ($(filter $(platform),linux bsd),) + ifeq ($(binary),application) + options += -Wl,-export-dynamic +- options += -lX11 -lXext + else ifeq ($(binary),library) + flags += -fPIC + options += -shared diff --git a/projects/ArchR/packages/emulators/libretro/bsnes-lr/package.mk b/projects/ArchR/packages/emulators/libretro/bsnes-lr/package.mk new file mode 100644 index 0000000000..2945641f4a --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/bsnes-lr/package.mk @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="bsnes-lr" +PKG_VERSION="b102d6d5817b25aa059b573cd3b7675f2e375fa4" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/bsnes-libretro" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="BSNES Super Nintendo Libretro Core" +PKG_TOOLCHAIN="make" + +if [ ! "${OPENGL}" = "no" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL} glu libglvnd" +fi + +if [ "${OPENGLES_SUPPORT}" = yes ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" +fi + +pre_configure_target() { + sed -i 's/\-O[23]/-Ofast/' ${PKG_BUILD}/Makefile +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp bsnes_libretro.so ${INSTALL}/usr/lib/libretro/ +} + diff --git a/projects/ArchR/packages/emulators/libretro/bsnes-mercury-accuracy-lr/package.mk b/projects/ArchR/packages/emulators/libretro/bsnes-mercury-accuracy-lr/package.mk new file mode 100644 index 0000000000..168de285c5 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/bsnes-mercury-accuracy-lr/package.mk @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="bsnes-mercury-accuracy-lr" +PKG_VERSION="0f35d044bf2f2b879018a0500e676447e93a1db1" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/bsnes-mercury" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="BSNES Super Nintendo Libretro Core" +PKG_TOOLCHAIN="make" + +pre_configure_target() { + sed -i 's/\-O[23]/-Ofast/' ${PKG_BUILD}/Makefile +} + +pre_make_target() { + PKG_MAKE_OPTS_TARGET+=" platform=${DEVICE}" +} + +make_target() { + make PROFILE=accuracy +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp bsnes_mercury_accuracy_libretro.so ${INSTALL}/usr/lib/libretro/ +} + diff --git a/projects/ArchR/packages/emulators/libretro/bsnes-mercury-balanced-lr/package.mk b/projects/ArchR/packages/emulators/libretro/bsnes-mercury-balanced-lr/package.mk new file mode 100644 index 0000000000..4e3422d8bd --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/bsnes-mercury-balanced-lr/package.mk @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="bsnes-mercury-balanced-lr" +PKG_VERSION="0f35d044bf2f2b879018a0500e676447e93a1db1" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/bsnes-mercury" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="BSNES Super Nintendo Libretro Core" +PKG_TOOLCHAIN="make" + +pre_configure_target() { + sed -i 's/\-O[23]/-Ofast/' ${PKG_BUILD}/Makefile +} + +pre_make_target() { + PKG_MAKE_OPTS_TARGET+=" platform=${DEVICE}" +} + +make_target() { + make PROFILE=balanced +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp bsnes_mercury_balanced_libretro.so ${INSTALL}/usr/lib/libretro/ +} + diff --git a/projects/ArchR/packages/emulators/libretro/bsnes-mercury-performance-lr/package.mk b/projects/ArchR/packages/emulators/libretro/bsnes-mercury-performance-lr/package.mk new file mode 100644 index 0000000000..4a85b567b9 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/bsnes-mercury-performance-lr/package.mk @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="bsnes-mercury-performance-lr" +PKG_VERSION="0f35d044bf2f2b879018a0500e676447e93a1db1" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/bsnes-mercury" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="BSNES Super Nintendo Libretro Core" +PKG_TOOLCHAIN="make" + +pre_configure_target() { + sed -i 's/\-O[23]/-Ofast/' ${PKG_BUILD}/Makefile +} + +pre_make_target() { + PKG_MAKE_OPTS_TARGET+=" platform=${DEVICE}" +} + +make_target() { + make PROFILE=performance +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp bsnes_mercury_performance_libretro.so ${INSTALL}/usr/lib/libretro/ +} + diff --git a/projects/ArchR/packages/emulators/libretro/cap32-lr/package.mk b/projects/ArchR/packages/emulators/libretro/cap32-lr/package.mk new file mode 100644 index 0000000000..3aea395765 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/cap32-lr/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) +# 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="cap32-lr" +PKG_VERSION="a5d96c5ebbda3bc89a3bd1c1691a20f5eacc232d" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/libretro-cap32" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="caprice32 4.2.0 libretro" + +PKG_TOOLCHAIN="make" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp cap32_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/common-shaders/package.mk b/projects/ArchR/packages/emulators/libretro/common-shaders/package.mk new file mode 100644 index 0000000000..cc9c4e3432 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/common-shaders/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="common-shaders" +PKG_VERSION="86cfa146a8dfddf6377ddb5dbcff552feae2e5bf" +PKG_ARCH="aarch64" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/libretro/common-shaders" +PKG_URL="https://github.com/libretro/common-shaders/archive/${PKG_VERSION}.tar.gz" +PKG_LONGDESC="Libretro common shaders" +PKG_TOOLCHAIN="manual" + +make_target() { + : +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/share/common-shaders + cp -PR ${PKG_BUILD}/* ${INSTALL}/usr/share/common-shaders + rm -f ${INSTALL}/usr/share/common-shaders/{Makefile,configure} +} diff --git a/projects/ArchR/packages/emulators/libretro/core-info/package.mk b/projects/ArchR/packages/emulators/libretro/core-info/package.mk new file mode 100644 index 0000000000..8913096d9e --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/core-info/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) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) +# +# 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="core-info" +PKG_VERSION="20e7d555f911f5aa6712d5937f7b9b834015d88d" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/libretro/libretro-core-info" +PKG_URL="https://github.com/libretro/libretro-core-info/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Mirror of libretro's core info files" +PKG_TOOLCHAIN="manual" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + # Rename only if mednafen files still exist (idempotent for compat rebuilds) + if ls ${PKG_BUILD}/mednafen*.info 1>/dev/null 2>&1; then + ${TOOLCHAIN}/bin/rename -v mednafen beetle ${PKG_BUILD}/*.info + fi + cp ${PKG_BUILD}/*.info ${INSTALL}/usr/lib/libretro/ + cp ${PKG_BUILD}/pcsx_rearmed_libretro.info ${INSTALL}/usr/lib/libretro/pcsx_rearmed32_libretro.info + cp ${PKG_BUILD}/flycast_libretro.info ${INSTALL}/usr/lib/libretro/flycast2021_libretro.info +} diff --git a/projects/ArchR/packages/emulators/libretro/crocods-lr/package.mk b/projects/ArchR/packages/emulators/libretro/crocods-lr/package.mk new file mode 100644 index 0000000000..1fbafdac93 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/crocods-lr/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) +# 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="crocods-lr" +PKG_VERSION="a320f6e38af49af84a63f81329a1bdb9322022b4" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/libretro/libretro-crocods" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Amstrad CPC emulator" + +PKG_TOOLCHAIN="make" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp crocods_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/crocods-lr/patches/001-keyboard.patch b/projects/ArchR/packages/emulators/libretro/crocods-lr/patches/001-keyboard.patch new file mode 100644 index 0000000000..aad705c424 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/crocods-lr/patches/001-keyboard.patch @@ -0,0 +1,22 @@ +From 997a1f4851c53eca18c17ef753e284b3420ff871 Mon Sep 17 00:00:00 2001 +From: christianhaitian +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/projects/ArchR/packages/emulators/libretro/daphne-lr/package.mk b/projects/ArchR/packages/emulators/libretro/daphne-lr/package.mk new file mode 100644 index 0000000000..7af8d89a25 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/daphne-lr/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="daphne-lr" +PKG_VERSION="b5481bab34a51369b6749cd95f5f889e43aaa23f" +PKG_LICENSE="GPLv2+" +PKG_SITE="https://github.com/libretro/daphne" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="This is a Daphne core" +PKG_TOOLCHAIN="make" + +pre_configure_target() { + export CFLAGS="${CFLAGS} -Wno-use-after-free -Wno-unused-function -Wno-maybe-uninitialized -Wno-unused-variable -Wno-implicit-function-declaration -Wno-builtin-declaration-mismatch -Wno-unknown-pragmas -Wno-pointer-to-int-cast -Wno-pedantic -Wno-error=incompatible-pointer-types" +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp daphne_libretro.so ${INSTALL}/usr/lib/libretro/ +} + diff --git a/projects/ArchR/packages/emulators/libretro/desmume-lr/package.mk b/projects/ArchR/packages/emulators/libretro/desmume-lr/package.mk new file mode 100644 index 0000000000..cffcc60ce5 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/desmume-lr/package.mk @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="desmume-lr" +PKG_VERSION="7f05a8d447b00acd9e0798aee97b4f72eb505ef9" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/desmume" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain libpcap" +PKG_LONGDESC="DeSmuME - Nintendo DS libretro" +PKG_TOOLCHAIN="make" + +if [ "${OPENGL_SUPPORT}" = "yes" ] && [ ! "${PREFER_GLES}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL} glu libglvnd" + +elif [ "${OPENGLES_SUPPORT}" = yes ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" + PKG_PATCH_DIRS+=" gles" +fi + + +pre_configure_target() { + cd ${PKG_BUILD}/desmume/src/frontend/libretro +} + +if [ "${ARCH}" = "arm" ] +then + make_target() { + make CC=${CC} platform=armv-unix-${TARGET_FLOAT}float-${TARGET_CPU} + } +elif [ "${ARCH}" = "x86_64" ] +then + make_target() { + make CC=${CC} platform=unix + } +else + make_target() { + : + } +fi + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + if [ "${ARCH}" = "aarch64" ] + then + cp -vP ${ROOT}/build.${DISTRO}-${DEVICE}.arm/install_pkg/desmume-*/usr/lib/libretro/desmume_libretro.so ${INSTALL}/usr/lib/libretro/ + else + cp desmume_libretro.so ${INSTALL}/usr/lib/libretro/ + fi +} diff --git a/projects/ArchR/packages/emulators/libretro/desmume-lr/patches/gles/000-enable-gles.patch b/projects/ArchR/packages/emulators/libretro/desmume-lr/patches/gles/000-enable-gles.patch new file mode 100644 index 0000000000..1cef5bf6df --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/desmume-lr/patches/gles/000-enable-gles.patch @@ -0,0 +1,26 @@ +From 89112d650a16787a7b27fd176b976a67bf10f96d Mon Sep 17 00:00:00 2001 +From: SupervisedThinking +Date: Thu, 20 May 2021 15:57:36 +0200 +Subject: [PATCH] Makefile.libretro: disable OpenGL + +--- + desmume/src/frontend/libretro/Makefile.libretro | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +--- a/desmume/src/frontend/libretro/Makefile.libretro ++++ b/desmume/src/frontend/libretro/Makefile.libretro +@@ -75,10 +75,10 @@ ifneq (,$(findstring unix,$(platform))) + CXX = g++-x86 + endif + else +- LIBS := -lpthread -lGL -lpcap +- CXXFLAGS += -DHAVE_OPENGL -std=gnu++11 +- DESMUME_OPENGL = 1 +- DESMUME_OPENGL_CORE = 1 ++ LIBS := -lpthread -lpcap ++ CXXFLAGS += -std=gnu++11 ++ DESMUME_OPENGL = 0 ++ DESMUME_OPENGL_CORE = 0 + endif + + ifneq (,$(findstring clang,$(platform))) diff --git a/projects/ArchR/packages/emulators/libretro/dolphin-lr/package.mk b/projects/ArchR/packages/emulators/libretro/dolphin-lr/package.mk new file mode 100644 index 0000000000..bb805513c7 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/dolphin-lr/package.mk @@ -0,0 +1,65 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="dolphin-lr" +PKG_VERSION="89a4df725d4eb24537728f7d655cddb1add25c18" +PKG_LICENSE="GPLv2" +PKG_DEPENDS_TARGET="toolchain libevdev libdrm ffmpeg zlib libpng lzo libusb" +PKG_SITE="https://github.com/libretro/dolphin" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Dolphin Libretro, a Gamecube & Wii emulator core for Retroarch" +PKG_TOOLCHAIN="cmake" + +if [ ! "${OPENGL}" = "no" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL} glu libglvnd" + PKG_CMAKE_OPTS_TARGET+=" -DENABLE_X11=OFF \ + -DENABLE_EGL=ON" +fi + +if [ "${OPENGLES_SUPPORT}" = yes ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" + PKG_CMAKE_OPTS_TARGET+=" -DENABLE_X11=OFF \ + -DENABLE_EGL=ON" +fi + +if [ "${DISPLAYSERVER}" = "wl" ]; then + PKG_DEPENDS_TARGET+=" wayland ${WINDOWMANAGER} xwayland xrandr libXi" + PKG_CMAKE_OPTS_TARGET+=" -DENABLE_X11=ON \ + -DENABLE_EGL=ON" +fi + +if [ "${VULKAN_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${VULKAN}" + PKG_CMAKE_OPTS_TARGET+=" -DENABLE_VULKAN=ON" +fi + +PKG_CMAKE_OPTS_TARGET+=" -DENABLE_EGL=ON \ + -DUSE_SHARED_ENET=OFF \ + -DUSE_UPNP=ON \ + -DENABLE_NOGUI=ON \ + -DENABLE_QT=OFF \ + -DENABLE_LTO=ON \ + -DENABLE_GENERIC=OFF \ + -DENABLE_HEADLESS=ON \ + -DENABLE_ALSA=ALSA \ + -DENABLE_PULSEAUDIO=ON \ + -DENABLE_LLVM=OFF \ + -DENABLE_TESTS=OFF \ + -DUSE_DISCORD_PRESENCE=OFF \ + -DLIBRETRO=ON \ + -DCMAKE_POLICY_VERSION_MINIMUM=3.5" + +pre_configure_target() { + if [ "${ARCH}" = "aarch64" ]; then + # This is only needed for armv8.2-a targets where we don't use this flag + # as it prohibits the use of LSE-instructions, this is a package bug most likely + export CFLAGS="${CFLAGS} -mno-outline-atomics" + export CXXFLAGS="${CXXFLAGS} -mno-outline-atomics" + fi +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp ${PKG_BUILD}/.${TARGET_NAME}/dolphin_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/dolphin-lr/patches/fix-gcc14.patch b/projects/ArchR/packages/emulators/libretro/dolphin-lr/patches/fix-gcc14.patch new file mode 100644 index 0000000000..8d01e20b15 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/dolphin-lr/patches/fix-gcc14.patch @@ -0,0 +1,27 @@ +From b6c97e3158554f29c1467011e8d50ad2b2350bc1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Piotr=20Pawe=C5=82=20Stefaniak?= + <3462925+pstef@users.noreply.github.com> +Date: Sat, 11 May 2024 19:12:53 +0200 +Subject: [PATCH] Fix build on some systems +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The complaint was: error: ‘reverse’ is not a member of ‘std’ +--- + Source/Core/Core/Debugger/PPCDebugInterface.cpp | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/Source/Core/Core/Debugger/PPCDebugInterface.cpp b/Source/Core/Core/Debugger/PPCDebugInterface.cpp +index f44c20d7f28c..1ebd0f8d5b48 100644 +--- a/Source/Core/Core/Debugger/PPCDebugInterface.cpp ++++ b/Source/Core/Core/Debugger/PPCDebugInterface.cpp +@@ -4,6 +4,7 @@ + + #include "Core/Debugger/PPCDebugInterface.h" + ++#include + #include + #include + #include + diff --git a/projects/ArchR/packages/emulators/libretro/dolphin-lr/patches/fmt-10.patch b/projects/ArchR/packages/emulators/libretro/dolphin-lr/patches/fmt-10.patch new file mode 100644 index 0000000000..98419eea65 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/dolphin-lr/patches/fmt-10.patch @@ -0,0 +1,13 @@ +diff --git a/Source/Core/Core/IOS/FS/FileSystemProxy.cpp b/Source/Core/Core/IOS/FS/FileSystemProxy.cpp +index 181a739748..a8d8ba280c 100644 +--- a/Source/Core/Core/IOS/FS/FileSystemProxy.cpp ++++ b/Source/Core/Core/IOS/FS/FileSystemProxy.cpp +@@ -272,7 +272,7 @@ IPCCommandResult FS::Seek(const SeekRequest& request) + + const Result result = + m_ios.GetFS()->SeekFile(handle.fs_fd, request.offset, IOS::HLE::FS::SeekMode(request.mode)); +- LogResult(result, "Seek({}, 0x{:08x}, {})", handle.name.data(), request.offset, request.mode); ++ LogResult(result, "Seek({}, 0x{:08x}, {})", handle.name.data(), request.offset, static_cast(request.mode)); + if (!result) + return GetFSReply(ConvertResult(result.Error())); + return GetFSReply(*result); diff --git a/projects/ArchR/packages/emulators/libretro/dosbox-core-lr/package.mk b/projects/ArchR/packages/emulators/libretro/dosbox-core-lr/package.mk new file mode 100644 index 0000000000..7a02c63124 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/dosbox-core-lr/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) 2023 JELOS (https://github.com/JustEnoughLinuxOS) +# Copyright (C) 2025 ArchR (https://github.com/archr-linux/Arch-R) +# +# 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-core-lr" +PKG_VERSION="7bcf083e8309660e2c598d6f7d5982d3851f2178" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/realnc/dosbox-core" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_GIT_CLONE_BRANCH="libretro" +PKG_DEPENDS_TARGET="toolchain SDL2" +PKG_LONGDESC="Upstream port of DOSBox to libretro" +PKG_BUILD_FLAGS="-lto" +PKG_TOOLCHAIN="make" + +make_target() { + #export PKG_CONFIG_DEBUG_SPEW=1 + make -C libretro target=arm64 platform=unix WITH_FAKE_SDL=1 STATIC_LIBCXX=0 \ + WITH_DYNAREC=arm64 WITH_FLUIDSYNTH=0 BUNDLED_AUDIO_CODECS=0 BUNDLED_GLIB=0 \ + BUNDLED_LIBSNDFILE=0 WITH_PINHACK=0 WITH_VOODOO=0 WITH_BASSMIDI=0 +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp ${PKG_BUILD}/libretro/dosbox_core_libretro.so ${INSTALL}/usr/lib/libretro +} diff --git a/projects/ArchR/packages/emulators/libretro/dosbox-core-lr/patches/001-fix-pkgconfig-abuse-issue.patch b/projects/ArchR/packages/emulators/libretro/dosbox-core-lr/patches/001-fix-pkgconfig-abuse-issue.patch new file mode 100644 index 0000000000..5e58080837 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/dosbox-core-lr/patches/001-fix-pkgconfig-abuse-issue.patch @@ -0,0 +1,15 @@ +--- a/libretro/Makefile.common 2025-06-11 13:20:35.626175688 +0000 ++++ b/libretro/Makefile.common 2025-06-11 13:26:33.757777680 +0000 +@@ -20,8 +20,12 @@ + -I$(CORE_DIR)/libretro/src \ + -I$(CORE_DIR)/libretro/src/virtual_keyboard \ + -I$(CORE_DIR)/src \ ++ -I$(CORE_DIR)/libretro/deps_bin/include \ + -I$(LIBRETRO_COMM_DIR)/include + ++LDFLAGS += \ ++ -L$(CORE_DIR)/libretro/deps_bin/lib ++ + # common files + SOURCES_CXX += \ + $(CORE_DIR)/libretro/src/CoreOptionCategory.cpp \ diff --git a/projects/ArchR/packages/emulators/libretro/dosbox-core-lr/patches/002-fix-cmake-build.patch b/projects/ArchR/packages/emulators/libretro/dosbox-core-lr/patches/002-fix-cmake-build.patch new file mode 100644 index 0000000000..ee51233868 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/dosbox-core-lr/patches/002-fix-cmake-build.patch @@ -0,0 +1,8 @@ +--- a/libretro/deps/munt/mt32emu/CMakeLists.txt ++++ b/libretro/deps/munt/mt32emu/CMakeLists.txt +@@ -1,4 +1,4 @@ +-cmake_minimum_required(VERSION 2.8.12) ++cmake_minimum_required(VERSION 3.5) + + list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") + diff --git a/projects/ArchR/packages/emulators/libretro/dosbox-pure-lr/package.mk b/projects/ArchR/packages/emulators/libretro/dosbox-pure-lr/package.mk new file mode 100644 index 0000000000..23855364ae --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/dosbox-pure-lr/package.mk @@ -0,0 +1,36 @@ +################################################################################ +# 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-lr" +PKG_VERSION="b9f8bc681c55301b7430070b1c2057b3744ad480" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/schellingb/dosbox-pure" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A port of DOSBox to libretro" +GET_HANDLER_SUPPORT="git" +PKG_TOOLCHAIN="make" +PKG_PATCH_DIRS+="${DEVICE}" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + ${STRIP} --strip-debug dosbox_pure_libretro.so + cp dosbox_pure_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/doublecherrygb-lr/package.mk b/projects/ArchR/packages/emulators/libretro/doublecherrygb-lr/package.mk new file mode 100644 index 0000000000..5f474fc1bf --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/doublecherrygb-lr/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="doublecherrygb-lr" +PKG_VERSION="f6ffb9ae6230e6614066b887c7b269d44a00cab7" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/TimOelrichs/doublecherryGB-libretro" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="DoubleCherryGB is an open source (GPLv2) GB/GBC emulator." +PKG_TOOLCHAIN="make" + +if [ "${OPENGL_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL} glu libglvnd" +fi + +if [ "${OPENGLES_SUPPORT}" = yes ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" +fi + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp ${PKG_BUILD}/DoubleCherryGB_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/easyrpg-lr/easyrpg.sh b/projects/ArchR/packages/emulators/libretro/easyrpg-lr/easyrpg.sh new file mode 100644 index 0000000000..22e08951a4 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/easyrpg-lr/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." + 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}" + 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/projects/ArchR/packages/emulators/libretro/easyrpg-lr/liblcf/package.mk b/projects/ArchR/packages/emulators/libretro/easyrpg-lr/liblcf/package.mk new file mode 100644 index 0000000000..0d5535ce0c --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/easyrpg-lr/liblcf/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) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) +# +# 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="92c4450a1bc1acb58bd02bbb99b57e5036919cdf" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/EasyRPG/liblcf" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain expat icu inih" +PKG_LONGDESC="Library to handle RPG Maker 2000/2003 and EasyRPG projects" +GET_HANDLER_SUPPORT="git" + +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/projects/ArchR/packages/emulators/libretro/easyrpg-lr/libspeexdsp/package.mk b/projects/ArchR/packages/emulators/libretro/easyrpg-lr/libspeexdsp/package.mk new file mode 100644 index 0000000000..44be0c1e1d --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/easyrpg-lr/libspeexdsp/package.mk @@ -0,0 +1,28 @@ +################################################################################ +# 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="738e17905e1ca2a1fa932ddd9c2a85d089f4e845" +PKG_SITE="https://github.com/xiph/speexdsp" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Speex audio processing library" +GET_HANDLER_SUPPORT="git" +PKG_TOOLCHAIN="autotools" diff --git a/projects/ArchR/packages/emulators/libretro/easyrpg-lr/libxmp-lite/package.mk b/projects/ArchR/packages/emulators/libretro/easyrpg-lr/libxmp-lite/package.mk new file mode 100644 index 0000000000..6fcc3b972e --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/easyrpg-lr/libxmp-lite/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="libxmp-lite" +PKG_VERSION="4.5.0" +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_LONGDESC="Libxmp is a library that renders module files to PCM data." + + +PKG_TOOLCHAIN="configure" + +pre_configure_target() { + cd ${PKG_BUILD} +} + + diff --git a/projects/ArchR/packages/emulators/libretro/easyrpg-lr/libxmp-lite/sources/CMakeLists.txt b/projects/ArchR/packages/emulators/libretro/easyrpg-lr/libxmp-lite/sources/CMakeLists.txt new file mode 100644 index 0000000000..01033a2075 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/easyrpg-lr/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/projects/ArchR/packages/emulators/libretro/easyrpg-lr/package.mk b/projects/ArchR/packages/emulators/libretro/easyrpg-lr/package.mk new file mode 100644 index 0000000000..eb68fa7e6f --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/easyrpg-lr/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) 2023 JELOS (https://github.com/JustEnoughLinuxOS) +# +# 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-lr" +PKG_VERSION="31de2a75e2187360bc55b1b43f9524779485fe8a" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/easyrpg/player" +PKG_URL="${PKG_SITE}.git" +PKG_GIT_CLONE_BRANCH="0-8-0-stable" +PKG_DEPENDS_TARGET="toolchain zlib libfmt liblcf icu pixman libspeexdsp mpg123 libsndfile libvorbis opusfile wildmidi libxmp-lite fluidsynth harfbuzz libpng retroarch inih" +PKG_LONGDESC="An unofficial libretro port of the EasyRPG/Player." +GET_HANDLER_SUPPORT="git" +PKG_BUILD_FLAGS="+pic" + + +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 + chmod 0755 ${INSTALL}/usr/bin/easyrpg.sh +} diff --git a/projects/ArchR/packages/emulators/libretro/easyrpg-lr/wildmidi/package.mk b/projects/ArchR/packages/emulators/libretro/easyrpg-lr/wildmidi/package.mk new file mode 100644 index 0000000000..cf2b3a9d85 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/easyrpg-lr/wildmidi/package.mk @@ -0,0 +1,30 @@ +################################################################################ +# 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_SITE="https://github.com/Mindwerks/wildmidi" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="WildMIDI is a simple software midi player which has a core softsynth library that can be used with other applications." + +PKG_TOOLCHAIN="cmake" + +PKG_CMAKE_OPTS_TARGET="WANT_PLAYER=OFF -DWANT_ALSA=ON" diff --git a/projects/ArchR/packages/emulators/libretro/easyrpg-lr/wildmidi/sources/CMakeLists.txt b/projects/ArchR/packages/emulators/libretro/easyrpg-lr/wildmidi/sources/CMakeLists.txt new file mode 100644 index 0000000000..86687abca2 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/easyrpg-lr/wildmidi/sources/CMakeLists.txt @@ -0,0 +1,303 @@ +# ########## Project setup ########## +PROJECT(wildmidi C) +CMAKE_MINIMUM_REQUIRED(VERSION 3.5) + +# 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/projects/ArchR/packages/emulators/libretro/ecwolf-lr/package.mk b/projects/ArchR/packages/emulators/libretro/ecwolf-lr/package.mk new file mode 100644 index 0000000000..70629e0766 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/ecwolf-lr/package.mk @@ -0,0 +1,36 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="ecwolf-lr" +PKG_VERSION="5ddc1d0000df81a92378da2514da91e06de67922" +PKG_LICENSE="GPLv2" +# TODO revert PKG_SITE once https://github.com/libretro/ecwolf/pull/102 is merged +#PKG_SITE="https://github.com/libretro/ecwolf" +PKG_SITE="https://github.com/porschemad911/ecwolf" +PKG_URL="${PKG_SITE}.git" +# TODO remove PKG_GIT_CLONE_BRANCH once https://github.com/libretro/ecwolf/pull/102 is merged +PKG_GIT_CLONE_BRANCH="sdl-submodule-url" +PKG_DEPENDS_TARGET="toolchain SDL2 SDL2_mixer SDL2_net libjpeg-turbo bzip2" +PKG_LONGDESC="ECWolf is a port of the Wolfenstein 3D engine based of Wolf4SDL." +PKG_TOOLCHAIN="make" + +if [ "${OPENGL_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL}" +elif [ "${OPENGLES_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" +fi + +PKG_MAKE_OPTS_TARGET="-C src/libretro" + +pre_configure_target() { + CXXFLAGS="${CXXFLAGS} -Wno-error=int-conversion" +} + +pre_make_target() { + cd ${PKG_BUILD} +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp src/libretro/ecwolf_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/emuscv-lr/package.mk b/projects/ArchR/packages/emulators/libretro/emuscv-lr/package.mk new file mode 100644 index 0000000000..8fc9b23e0a --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/emuscv-lr/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-present AmberELEC (https://github.com/AmberELEC) + +PKG_NAME="emuscv-lr" +PKG_VERSION="dfce10df090ce3f5eb23bdbee289702ec1478246" +#PKG_ARCH="aarch64" +PKG_SITE="https://gitlab.com/MaaaX-EmuSCV/libretro-emuscv" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain bin2c:host SDL2" +PKG_LONGDESC="An EPOCH/YENO Super Cassette Vision (1984) home video game emulator for Libretro" +PKG_TOOLCHAIN="make" + +PKG_MAKE_OPTS_TARGET="-C . platform=unix" + +pre_configure_target() { + export TERM=xterm + CXXFLAGS+=" -I$(get_build_dir glibc)/sysdeps/unix/sysv/linux/x86" + sed -i 's~tools/bin2c/~'${TOOLCHAIN}'/usr/bin/~g' Makefile.libretro +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp ${PKG_BUILD}/emuscv_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/emuscv-lr/patches/emuscv_platform.patch b/projects/ArchR/packages/emulators/libretro/emuscv-lr/patches/emuscv_platform.patch new file mode 100644 index 0000000000..96cac8656d --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/emuscv-lr/patches/emuscv_platform.patch @@ -0,0 +1,16 @@ +diff --git a/Makefile.libretro b/Makefile.libretro +index e1df23a..0392c0c 100644 +--- a/Makefile.libretro ++++ b/Makefile.libretro +@@ -70,11 +70,6 @@ ifneq (,$(findstring unix,$(platform))) + ifneq (,$(findstring Haiku,$(shell uname -s))) + LDFLAGS += -lnetwork -lroot + endif +- CC = gcc +- CXX = gcc +- LDFLAGS += -I/usr/include/SDL2 -L/usr/lib/x86_64-linux-gnu -lSDL2 +- CFLAGS += -I/usr/include/SDL2 `sdl2-config --cflags` +- CXXFLAGS += -I/usr/include/SDL2 `sdl2-config --cflags` + + # Raspberry Pi + ifneq (,$(findstring rpi,$(platform))) diff --git a/projects/ArchR/packages/emulators/libretro/fake08-lr/package.mk b/projects/ArchR/packages/emulators/libretro/fake08-lr/package.mk new file mode 100644 index 0000000000..a98e84d746 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/fake08-lr/package.mk @@ -0,0 +1,19 @@ + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present Lakka (https://www.lakka.tv) + +PKG_NAME="fake08-lr" +PKG_VERSION="0d26fd59103941e5f95e0ee665c6e0fb8c6b6f03" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/jtothebell/fake-08" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A Pico-8 player/emulator for console homebrew" +PKG_TOOLCHAIN="make" + +PKG_MAKE_OPTS_TARGET="-C platform/libretro" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp -v platform/libretro/fake08_libretro.{so,info} ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/fbalpha2012-lr/package.mk b/projects/ArchR/packages/emulators/libretro/fbalpha2012-lr/package.mk new file mode 100644 index 0000000000..5dadaeb4c1 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/fbalpha2012-lr/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-lr" +PKG_VERSION="77167cea72e808384c136c8c163a6b4975ce7a84" +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_LONGDESC="Port of Final Burn Alpha 2012 to Libretro" +PKG_TOOLCHAIN="make" + +pre_configure_target() { +export CFLAGS="${CFLAGS} -Wno-maybe-uninitialized -Wno-unused-function -Wno-error=incompatible-pointer-types" +} + +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/projects/ArchR/packages/emulators/libretro/fbalpha2019-lr/fbalpha2019_libretro.info b/projects/ArchR/packages/emulators/libretro/fbalpha2019-lr/fbalpha2019_libretro.info new file mode 100644 index 0000000000..5a605e4845 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/fbalpha2019-lr/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/projects/ArchR/packages/emulators/libretro/fbalpha2019-lr/package.mk b/projects/ArchR/packages/emulators/libretro/fbalpha2019-lr/package.mk new file mode 100644 index 0000000000..d5297e3217 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/fbalpha2019-lr/package.mk @@ -0,0 +1,39 @@ +################################################################################ +# 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-lr" +PKG_VERSION="0581797db6fdffd826086b053ced4b6b29bb6678" +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_LONGDESC="Port of Final Burn Alpha to Libretro (v0.2.97.44)." +PKG_TOOLCHAIN="make" + +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/projects/ArchR/packages/emulators/libretro/fbneo-lr/package.mk b/projects/ArchR/packages/emulators/libretro/fbneo-lr/package.mk new file mode 100644 index 0000000000..599ba5890e --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/fbneo-lr/package.mk @@ -0,0 +1,30 @@ +# 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) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="fbneo-lr" +PKG_VERSION="012dbe9dc11fd5fd765ef92e0ad4c08583862f69" +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_LONGDESC="Port of Final Burn Neo to Libretro (v0.2.97.38)." +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/projects/ArchR/packages/emulators/libretro/fceumm-lr/package.mk b/projects/ArchR/packages/emulators/libretro/fceumm-lr/package.mk new file mode 100644 index 0000000000..e0d116753f --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/fceumm-lr/package.mk @@ -0,0 +1,39 @@ +################################################################################ +# 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-lr" +PKG_VERSION="5cd4a43e16a7f3cd35628d481c347a0a98cfdfa2" +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_LONGDESC="Port of FCEUmm / FCEUX to Libretro." + +PKG_TOOLCHAIN="make" + +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/projects/ArchR/packages/emulators/libretro/flycast-lr/config/Flycast.opt b/projects/ArchR/packages/emulators/libretro/flycast-lr/config/Flycast.opt new file mode 100644 index 0000000000..ac207c51ac --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/flycast-lr/config/Flycast.opt @@ -0,0 +1,74 @@ +flycast_allow_service_buttons = "disabled" +flycast_alpha_sorting = "per-strip (fast, least accurate)" +flycast_analog_stick_deadzone = "15%" +flycast_anisotropic_filtering = "off" +flycast_auto_skip_frame = "disabled" +flycast_boot_to_bios = "disabled" +flycast_broadcast = "NTSC" +flycast_cable_type = "TV (Composite)" +flycast_custom_textures = "disabled" +flycast_delay_frame_swapping = "disabled" +flycast_detect_vsync_swap_interval = "disabled" +flycast_digital_triggers = "disabled" +flycast_dump_textures = "disabled" +flycast_emulate_bba = "disabled" +flycast_emulate_framebuffer = "disabled" +flycast_enable_dsp = "disabled" +flycast_enable_purupuru = "enabled" +flycast_enable_rttb = "disabled" +flycast_fog = "enabled" +flycast_force_freeplay = "enabled" +flycast_force_wince = "disabled" +flycast_frame_skipping = "disabled" +flycast_gdrom_fast_loading = "disabled" +flycast_hle_bios = "disabled" +flycast_internal_resolution = "640x480" +flycast_language = "English" +flycast_lightgun1_crosshair = "disabled" +flycast_lightgun2_crosshair = "disabled" +flycast_lightgun3_crosshair = "disabled" +flycast_lightgun4_crosshair = "disabled" +flycast_mipmapping = "enabled" +flycast_native_depth_interpolation = "disabled" +flycast_network_output = "disabled" +flycast_per_content_vmus = "disabled" +flycast_pvr2_filtering = "disabled" +flycast_region = "USA" +flycast_screen_rotation = "horizontal" +flycast_sh4clock = "200" +flycast_show_lightgun_settings = "disabled" +flycast_show_vmu_screen_settings = "disabled" +flycast_texture_filtering = "0" +flycast_texupscale = "1" +flycast_texupscale_max_filtered_texture_size = "256" +flycast_threaded_rendering = "enabled" +flycast_trigger_deadzone = "0%" +flycast_upnp = "enabled" +flycast_vmu1_pixel_off_color = "DEFAULT_OFF 01" +flycast_vmu1_pixel_on_color = "DEFAULT_ON 00" +flycast_vmu1_screen_display = "disabled" +flycast_vmu1_screen_opacity = "100%" +flycast_vmu1_screen_position = "Upper Left" +flycast_vmu1_screen_size_mult = "1x" +flycast_vmu2_pixel_off_color = "DEFAULT_OFF 01" +flycast_vmu2_pixel_on_color = "DEFAULT_ON 00" +flycast_vmu2_screen_display = "disabled" +flycast_vmu2_screen_opacity = "100%" +flycast_vmu2_screen_position = "Upper Left" +flycast_vmu2_screen_size_mult = "1x" +flycast_vmu3_pixel_off_color = "DEFAULT_OFF 01" +flycast_vmu3_pixel_on_color = "DEFAULT_ON 00" +flycast_vmu3_screen_display = "disabled" +flycast_vmu3_screen_opacity = "100%" +flycast_vmu3_screen_position = "Upper Left" +flycast_vmu3_screen_size_mult = "1x" +flycast_vmu4_pixel_off_color = "DEFAULT_OFF 01" +flycast_vmu4_pixel_on_color = "DEFAULT_ON 00" +flycast_vmu4_screen_display = "disabled" +flycast_vmu4_screen_opacity = "100%" +flycast_vmu4_screen_position = "Upper Left" +flycast_vmu4_screen_size_mult = "1x" +flycast_vmu_sound = "disabled" +flycast_volume_modifier_enable = "enabled" +flycast_widescreen_cheats = "disabled" +flycast_widescreen_hack = "disabled" diff --git a/projects/ArchR/packages/emulators/libretro/flycast-lr/package.mk b/projects/ArchR/packages/emulators/libretro/flycast-lr/package.mk new file mode 100644 index 0000000000..9cee9234c7 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/flycast-lr/package.mk @@ -0,0 +1,54 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present AmberELEC (https://github.com/AmberELEC) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="flycast-lr" +PKG_VERSION="c57b2e1aa775c21f6ddcd090607f4b3ba1a1baa1" +PKG_SITE="https://github.com/flyinghead/flycast" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain zlib libzip" +PKG_LONGDESC="Flycast is a multi-platform Sega Dreamcast, Naomi and Atomiswave emulator" +PKG_TOOLCHAIN="cmake" +PKG_PATCH_DIRS+=" ${DEVICE}" +PKG_BUILD_FLAGS="-parallel" + +if [ "${OPENGL_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL} glu libglvnd" + PKG_CMAKE_OPTS_TARGET+=" -DUSE_OPENGL=ON" +else + PKG_CMAKE_OPTS_TARGET+=" -DUSE_OPENGL=OFF" +fi + +if [ "${OPENGLES_SUPPORT}" = yes ] && \ + [ "${PREFER_GLES}" = "yes" ] +then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" + ### Will fail to compile if USE_OPENGL=OFF and USE_GLES=ON as both options are required. + PKG_CMAKE_OPTS_TARGET+=" -DUSE_OPENGL=ON -DUSE_GLES=ON" +else + PKG_CMAKE_OPTS_TARGET+=" -DUSE_GLES=OFF" +fi + +if [ "${VULKAN_SUPPORT}" = "yes" ] +then + PKG_DEPENDS_TARGET+=" ${VULKAN}" + PKG_CMAKE_OPTS_TARGET+=" -DUSE_VULKAN=ON" +else + PKG_CMAKE_OPTS_TARGET+=" -DUSE_VULKAN=OFF" +fi + +pre_configure_target() { + sed -i 's/"reicast"/"flycast"/g' ${PKG_BUILD}/shell/libretro/libretro_core_option_defines.h + sed -i 's/\-O[23]/-Ofast/' ${PKG_BUILD}/CMakeLists.txt + PKG_CMAKE_OPTS_TARGET="${PKG_CMAKE_OPTS_TARGET} \ + -Wno-dev -DLIBRETRO=ON \ + -DWITH_SYSTEM_ZLIB=ON \ + -DUSE_OPENMP=ON" +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp flycast_libretro.so ${INSTALL}/usr/lib/libretro/flycast_libretro.so + mkdir -p ${INSTALL}/usr/config/retroarch + cp -rf ${PKG_DIR}/config/* ${INSTALL}/usr/config/retroarch/ +} diff --git a/projects/ArchR/packages/emulators/libretro/flycast-lr/patches/001-fix-building-with-gcc15.patch b/projects/ArchR/packages/emulators/libretro/flycast-lr/patches/001-fix-building-with-gcc15.patch new file mode 100644 index 0000000000..84157201e5 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/flycast-lr/patches/001-fix-building-with-gcc15.patch @@ -0,0 +1,10 @@ +--- a/core/deps/glslang/SPIRV/SpvBuilder.h ++++ b/core/deps/glslang/SPIRV/SpvBuilder.h +@@ -63,6 +63,7 @@ + #include + #include + #include ++#include + + namespace spv { + diff --git a/projects/ArchR/packages/emulators/libretro/flycast2021-lr/package.mk b/projects/ArchR/packages/emulators/libretro/flycast2021-lr/package.mk new file mode 100644 index 0000000000..0628a5da4e --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/flycast2021-lr/package.mk @@ -0,0 +1,65 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) +# +# 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="flycast2021-lr" +PKG_VERSION="603814c9f73b773c455d9a497f389d2f93a257fd" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/metallic77/flycast" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Flycast is a multiplatform Sega Dreamcast emulator " +PKG_TOOLCHAIN="make" +PKG_BUILD_FLAGS="-gold" +PKG_PATCH_DIRS+="${DEVICE}" + +if [ "${OPENGL_SUPPORT}" = "yes" ] && [ ! "${PREFER_GLES}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL} glu libglvnd" + PKG_MAKE_OPTS_TARGET+=" FORCE_GLES=0" +elif [ "${OPENGLES_SUPPORT}" = yes ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" + PKG_MAKE_OPTS_TARGET+=" FORCE_GLES=1" +fi + +if [ "${VULKAN_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${VULKAN}" + PKG_MAKE_OPTS_TARGET+=" HAVE_VULKAN=1" +fi + +pre_configure_target() { + export CXXFLAGS="${CXXFLAGS} -Wno-implicit-function-declaration" + sed -i 's/define CORE_OPTION_NAME "reicast"/define CORE_OPTION_NAME "flycast2021"/g' core/libretro/libretro_core_option_defines.h + sed -i 's/\-O[23]/-Ofast/' ${PKG_BUILD}/Makefile + PKG_MAKE_OPTS_TARGET="${PKG_MAKE_OPTS_TARGET} ARCH=${TARGET_ARCH} HAVE_OPENMP=0 GIT_VERSION=${PKG_VERSION:0:7} HAVE_LTCG=0" +} + +pre_make_target() { + export BUILD_SYSROOT=${SYSROOT_PREFIX} + case ${ARCH} in + aarch64) + PKG_MAKE_OPTS_TARGET+=" platform=${DEVICE}" + ;; + esac +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp flycast_libretro.so ${INSTALL}/usr/lib/libretro/flycast2021_libretro.so +} diff --git a/projects/ArchR/packages/emulators/libretro/flycast2021-lr/patches/01-fix-gcc14.patch b/projects/ArchR/packages/emulators/libretro/flycast2021-lr/patches/01-fix-gcc14.patch new file mode 100644 index 0000000000..6b5bf785ae --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/flycast2021-lr/patches/01-fix-gcc14.patch @@ -0,0 +1,28 @@ +diff --git a/core/deps/libzip/mkstemp.c b/core/deps/libzip/mkstemp.c +index 353f3f7..3776f91 100644 +--- a/core/deps/libzip/mkstemp.c ++++ b/core/deps/libzip/mkstemp.c +@@ -43,9 +43,7 @@ + #include + #include + +-#ifdef __APPLE__ + #include +-#endif + + #ifndef O_BINARY + #define O_BINARY 0 +diff --git a/core/deps/libzip/zip_close.c b/core/deps/libzip/zip_close.c +index 88265a0..89bb26d 100644 +--- a/core/deps/libzip/zip_close.c ++++ b/core/deps/libzip/zip_close.c +@@ -42,9 +42,7 @@ + + #include "zipint.h" + +-#ifdef __APPLE__ + #include +-#endif + + static int add_data(struct zip *, struct zip_source *, struct zip_dirent *, + FILE *); diff --git a/projects/ArchR/packages/emulators/libretro/flycast2021-lr/patches/aarch64/000-platform.patch b/projects/ArchR/packages/emulators/libretro/flycast2021-lr/patches/aarch64/000-platform.patch new file mode 100644 index 0000000000..8c1319c053 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/flycast2021-lr/patches/aarch64/000-platform.patch @@ -0,0 +1,54 @@ +diff --git a/Makefile b/Makefile +index 01d99c3..0b80603 100644 +--- a/Makefile ++++ b/Makefile +@@ -45,12 +45,9 @@ + + MFLAGS := + ASFLAGS := +-LDFLAGS := + LDFLAGS_END := + INCFLAGS := + LIBS := +-CFLAGS := +-CXXFLAGS := + + GIT_VERSION := " $(shell git rev-parse --short HEAD || echo unknown)" + ifneq ($(GIT_VERSION)," unknown") +@@ -403,25 +400,27 @@ else ifeq ($(platform), arm64_cortex_a53_gles2) + + ####################################### + +-# ARM64 SM1 Odroid C4 +-else ifeq ($(platform), odroidc4) ++# ArchR device ++else ifeq ($(platform), @DEVICE@) + EXT ?= so + TARGET := $(TARGET_NAME)_libretro.$(EXT) + SHARED += -shared -Wl,--version-script=link.T +- LDFLAGS += -Wl,--no-undefined + fpic = -fPIC + LIBS += -lrt + ARM_FLOAT_ABI_HARD = 0 +- FORCE_GLES = 1 + SINGLE_PREC_FLAGS = 1 ++ HAVE_OPENMP = 0 +- CPUFLAGS += -DHOST_CPU=0x20000006 -DTARGET_LINUX_ARMv8 -frename-registers +- CFLAGS += -mcpu=cortex-a55 -mtune=cortex-a55 $(CPUFLAGS) +- CXXFLAGS += -mcpu=cortex-a55 -mtune=cortex-a55 $(CPUFLAGS) +- ASFLAGS += $(CFLAGS) -c -frename-registers -fno-strict-aliasing -ffast-math -ftree-vectorize ++ CFLAGS += -Ofast \ ++ -fuse-linker-plugin \ ++ -fno-stack-protector -fno-ident -fomit-frame-pointer \ ++ -fmerge-all-constants -ffast-math -funroll-all-loops \ ++ -mno-outline-atomics -DTARGET_LINUX_ARMv8 -DNOSSE -D__NEON_OPT ++ CXXFLAGS += $(CFLAGS) ++ LDFLAGS += -Ofast -flto -fuse-linker-plugin + PLATFORM_EXT := unix ++ CORE_DEFINES += -DLOW_END -DLOW_RES + WITH_DYNAREC=arm64 + HAVE_GENERIC_JIT = 0 +- HAVE_VULKAN = 0 + HAVE_LTCG = 0 + + ####################################### diff --git a/projects/ArchR/packages/emulators/libretro/fmsx-lr/package.mk b/projects/ArchR/packages/emulators/libretro/fmsx-lr/package.mk new file mode 100644 index 0000000000..521c8aec09 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/fmsx-lr/package.mk @@ -0,0 +1,39 @@ +################################################################################ +# 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-lr" +PKG_VERSION="fbe4dfc4c3e3f7eb27089def3d663a905b181845" +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_LONGDESC="Port of fMSX 4.9 to the libretro API." + +PKG_TOOLCHAIN="make" + +make_target() { + make +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp fmsx_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/freechaf-lr/package.mk b/projects/ArchR/packages/emulators/libretro/freechaf-lr/package.mk new file mode 100644 index 0000000000..6e06639fb3 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/freechaf-lr/package.mk @@ -0,0 +1,18 @@ +PKG_NAME="freechaf-lr" +PKG_VERSION="cdb8ad6fcecb276761b193650f5ce9ae8b878067" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/FreeChaF" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain" +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/projects/ArchR/packages/emulators/libretro/freeintv-lr/package.mk b/projects/ArchR/packages/emulators/libretro/freeintv-lr/package.mk new file mode 100644 index 0000000000..f6a49931df --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/freeintv-lr/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) +# 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-lr" +PKG_VERSION="1b51f41238ef9691d9fe16722f7d093bb6a6e379" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/libretro/FreeIntv" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="FreeIntv is a libretro emulation core for the Mattel Intellivision." + +PKG_TOOLCHAIN="make" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp freeintv_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/freej2me-lr/freej2me.sh b/projects/ArchR/packages/emulators/libretro/freej2me-lr/freej2me.sh new file mode 100644 index 0000000000..66d9115f3e --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/freej2me-lr/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/game/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/game/freej2me/freej2me-lr.jar /storage/roms/bios +fi + +clear > /dev/console < /dev/null 2>&1 +exit 0 diff --git a/projects/ArchR/packages/emulators/libretro/freej2me-lr/package.mk b/projects/ArchR/packages/emulators/libretro/freej2me-lr/package.mk new file mode 100644 index 0000000000..c5ea9ac973 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/freej2me-lr/package.mk @@ -0,0 +1,36 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present 351ELEC (https://github.com/351ELEC) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="freej2me-lr" +PKG_VERSION="1.52" +PKG_SITE="https://github.com/TASEmulators/freej2me-plus" +PKG_URL="${PKG_SITE}/archive/refs/tags/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain apache-ant:host libXtst" +PKG_LONGDESC="J2ME emulator with libretro and AWT frontends, it aims to run on basically anything that can run a Java VM." +PKG_TOOLCHAIN="make" + +post_unpack() { + # Java 25 no longer supports source/target 1.6, upgrade to 1.8 + sed -i 's/value="1\.6"/value="1.8"/g' ${PKG_BUILD}/build.xml +} + +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/game/freej2me + cp ${PKG_BUILD}/build/freej2me-lr.jar ${INSTALL}/usr/config/game/freej2me + + mkdir -p ${INSTALL}/usr/bin + cp ${PKG_DIR}/freej2me.sh ${INSTALL}/usr/bin + chmod 0755 ${INSTALL}/usr/bin/freej2me.sh +} diff --git a/projects/ArchR/packages/emulators/libretro/fuse-lr/package.mk b/projects/ArchR/packages/emulators/libretro/fuse-lr/package.mk new file mode 100644 index 0000000000..31558f9364 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/fuse-lr/package.mk @@ -0,0 +1,39 @@ +################################################################################ +# 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-lr" +PKG_VERSION="cad85b7b1b864c65734f71aa4a510b6f6536881c" +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_LONGDESC="A port of the Fuse Unix Spectrum Emulator to libretro " + +PKG_TOOLCHAIN="make" + +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/projects/ArchR/packages/emulators/libretro/gambatte-lr/package.mk b/projects/ArchR/packages/emulators/libretro/gambatte-lr/package.mk new file mode 100644 index 0000000000..53e73457cf --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/gambatte-lr/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) +# 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-lr" +PKG_VERSION="6924c76ba03dadddc6e97fa3660f3d3bc08faa94" +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_LONGDESC="libretro implementation of libgambatte" + +PKG_TOOLCHAIN="make" +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/projects/ArchR/packages/emulators/libretro/gearboy-lr/package.mk b/projects/ArchR/packages/emulators/libretro/gearboy-lr/package.mk new file mode 100644 index 0000000000..4fa55188bf --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/gearboy-lr/package.mk @@ -0,0 +1,34 @@ +################################################################################ +# +# 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-lr" +PKG_VERSION="37c21f776a54a7bfac2b2135b1b776d2e31fa93d" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/drhelius/Gearboy" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Game Boy / Gameboy Color emulator for iOS, Mac, Raspberry Pi, Windows and Linux" + +PKG_TOOLCHAIN="make" + +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/projects/ArchR/packages/emulators/libretro/gearcoleco-lr/package.mk b/projects/ArchR/packages/emulators/libretro/gearcoleco-lr/package.mk new file mode 100644 index 0000000000..0602ffde12 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/gearcoleco-lr/package.mk @@ -0,0 +1,34 @@ +################################################################################ +# +# 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-lr" +PKG_VERSION="f3e3e1812a3421bf24fca26ff257fb36842d33a9" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/drhelius/Gearcoleco" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +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_TOOLCHAIN="make" + +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/projects/ArchR/packages/emulators/libretro/gearsystem-lr/package.mk b/projects/ArchR/packages/emulators/libretro/gearsystem-lr/package.mk new file mode 100644 index 0000000000..4cac87ecae --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/gearsystem-lr/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) +# 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-lr" +PKG_VERSION="af2652e4082ef23f6826b5acf8338900d08cab2a" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/drhelius/Gearsystem" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain" +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/projects/ArchR/packages/emulators/libretro/genesis-plus-gx-lr/package.mk b/projects/ArchR/packages/emulators/libretro/genesis-plus-gx-lr/package.mk new file mode 100644 index 0000000000..9eb30154ee --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/genesis-plus-gx-lr/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) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) +# +# 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-lr" +PKG_VERSION="e48a37173350b5aec2a6431add7c1a625d1f28bf" +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_LONGDESC="An enhanced port of Genesis Plus for Gamecube/Wii" + +PKG_TOOLCHAIN="make" + +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/projects/ArchR/packages/emulators/libretro/genesis-plus-gx-wide-lr/package.mk b/projects/ArchR/packages/emulators/libretro/genesis-plus-gx-wide-lr/package.mk new file mode 100644 index 0000000000..3f059024d8 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/genesis-plus-gx-wide-lr/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="genesis-plus-gx-wide-lr" +PKG_VERSION="b7d314220d755537aebb7bc1750ac21f764365c4" +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_LONGDESC="An enhanced port of Genesis Plus for Gamecube/Wii" + +PKG_TOOLCHAIN="make" + +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/projects/ArchR/packages/emulators/libretro/geolith-lr/package.mk b/projects/ArchR/packages/emulators/libretro/geolith-lr/package.mk new file mode 100644 index 0000000000..785ee6e8e3 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/geolith-lr/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="geolith-lr" +PKG_VERSION="1391cef3d373cd2aaf4f8a0478b9d6f831c7dfac" +PKG_ARCH="aarch64" +PKG_LICENSE="BSD" +PKG_SITE="https://github.com/libretro/geolith-libretro" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Geolith is a highly accurate emulator for the Neo Geo AES and MVS." +PKG_TOOLCHAIN="make" + +make_target() { +cd libretro + make -f ./Makefile platform=${DEVICE} +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp geolith_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/geolith-lr/patches/000-platform.patch b/projects/ArchR/packages/emulators/libretro/geolith-lr/patches/000-platform.patch new file mode 100644 index 0000000000..367b6d29c4 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/geolith-lr/patches/000-platform.patch @@ -0,0 +1,19 @@ +diff -rupN geolith-libretro.orig/libretro/Makefile geolith-libretro/libretro/Makefile +--- geolith-libretro.orig/libretro/Makefile 2024-04-18 21:11:00.166799951 +0000 ++++ geolith-libretro/libretro/Makefile 2024-04-18 22:08:26.503486311 +0000 +@@ -375,6 +375,15 @@ else ifeq ($(platform), rpi4) + FLAGS += -mcpu=cortex-a72 -mtune=cortex-a72 + FLAGS += -fomit-frame-pointer -ffast-math + ++# @DEVICE@ ++else ifeq ($(platform), @DEVICE@) ++ TARGET := $(TARGET_NAME)_libretro.so ++ fpic := -fPIC ++ SHARED := -shared -Wl,--no-undefined -Wl,--version-script=link.T ++ CFLAGS += -fsigned-char ++ FLAGS += -DARM ++ FLAGS += -fomit-frame-pointer -ffast-math ++ + else ifeq ($(platform), emscripten) + TARGET := $(TARGET_NAME)_libretro_$(platform).bc + STATIC_LINKING = 1 diff --git a/projects/ArchR/packages/emulators/libretro/glsl-shaders/package.mk b/projects/ArchR/packages/emulators/libretro/glsl-shaders/package.mk new file mode 100644 index 0000000000..34c225851e --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/glsl-shaders/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) +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) +# +# 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="7e1617b722f85466ad7dd4ddb4ac241fd02dc8d0" +PKG_ARCH="aarch64" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/libretro/glsl-shaders" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Common GSLS shaders for RetroArch" + +PKG_TOOLCHAIN="make" + +configure_target() { + cd ${PKG_BUILD} +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/share/glsl-shaders + make install INSTALLDIR="${INSTALL}/usr/share/glsl-shaders" +} diff --git a/projects/ArchR/packages/emulators/libretro/gpsp-lr/package.mk b/projects/ArchR/packages/emulators/libretro/gpsp-lr/package.mk new file mode 100644 index 0000000000..548c34a081 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/gpsp-lr/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) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) +# +# 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-lr" +PKG_VERSION="b0d5d27ae51c23f514974ddffa5760f1e1d05d9b" +PKG_ARCH="arm aarch64" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/gpsp" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="gameplaySP is a Gameboy Advance emulator for Playstation Portable" +PKG_PATCH_DIRS+="${DEVICE}" +PKG_TOOLCHAIN="make" + +if [ "${ARCH}" = "arm" ] +then + make_target() { + make CC=${CC} platform=${DEVICE} + } +else + make_target() { + : + } +fi + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + if [ "${ARCH}" = "aarch64" ] + then + cp -vP ${ROOT}/build.${DISTRO}-${DEVICE}.arm/install_pkg/gpsp-*/usr/lib/libretro/gpsp_libretro.so ${INSTALL}/usr/lib/libretro/ + else + cp ${PKG_BUILD}/gpsp_libretro.so ${INSTALL}/usr/lib/libretro/ + fi +} diff --git a/projects/ArchR/packages/emulators/libretro/gpsp-lr/patches/000-platform.patch b/projects/ArchR/packages/emulators/libretro/gpsp-lr/patches/000-platform.patch new file mode 100644 index 0000000000..47e5d2cd35 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/gpsp-lr/patches/000-platform.patch @@ -0,0 +1,29 @@ +diff --git a/Makefile b/Makefile +index c52b50b..5e7f2ec 100644 +--- a/Makefile ++++ b/Makefile +@@ -67,7 +67,6 @@ + endif + LIBM := -lm + CORE_DIR := . +-LDFLAGS := + + # Unix + ifeq ($(platform), unix) +@@ -289,6 +288,16 @@ else ifeq ($(platform), rpi1) + MMAP_JIT_CACHE = 1 + HAVE_DYNAREC = 1 + ++# @DEVICE@ ++else ifeq ($(platform), @DEVICE@) ++ CFLAGS += -marm -flto -fpic -ffast-math -fno-rtti -fno-exceptions ++ TARGET := $(TARGET_NAME)_libretro.so ++ fpic := -fPIC ++ SHARED := -shared -Wl,--version-script=link.T -Wl,--no-undefined ++ CPU_ARCH := arm ++ MMAP_JIT_CACHE = 1 ++ HAVE_DYNAREC = 1 ++ + # Classic Platforms #################### + # Platform affix = classic__<µARCH> + # Help at https://modmyclassic.com/comp diff --git a/projects/ArchR/packages/emulators/libretro/gw-lr/package.mk b/projects/ArchR/packages/emulators/libretro/gw-lr/package.mk new file mode 100644 index 0000000000..52171ad51c --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/gw-lr/package.mk @@ -0,0 +1,39 @@ +################################################################################ +# 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-lr" +PKG_VERSION="435e5cfd4bf6aea03a84259e9b8dba3daf3ff5bd" +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_LONGDESC="A libretro core for Game & Watch simulators " + +PKG_TOOLCHAIN="make" + +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/projects/ArchR/packages/emulators/libretro/handy-lr/package.mk b/projects/ArchR/packages/emulators/libretro/handy-lr/package.mk new file mode 100644 index 0000000000..cd2095e23e --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/handy-lr/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="handy-lr" +PKG_VERSION="fca239207e9c111da3e85d2faf0b1b9d7524e498" +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_LONGDESC="K. Wilkins' Atari Lynx emulator Handy for libretro" +PKG_TOOLCHAIN="make" + +case ${ARCH} in + aarch64) + PKG_MAKE_OPTS_TARGET=" platform=emuelec" + ;; + arm) + PKG_MAKE_OPTS_TARGET=" platform=classic_armv8_a35" + ;; +esac + + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp handy_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/handy-lr/patches/aarch64/handy-01-add-emuelec.patch b/projects/ArchR/packages/emulators/libretro/handy-lr/patches/aarch64/handy-01-add-emuelec.patch new file mode 100644 index 0000000000..e1975cbc69 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/handy-lr/patches/aarch64/handy-01-add-emuelec.patch @@ -0,0 +1,24 @@ +--- 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,10 +256,9 @@ + -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 -mtune=cortex-a35 -mfpu=neon-fp-armv8 -mfloat-abi=hard ++ -fmerge-all-constants -fno-math-errno + 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/projects/ArchR/packages/emulators/libretro/hatari-lr/config/conf/Atari-ST-default.cfg b/projects/ArchR/packages/emulators/libretro/hatari-lr/config/conf/Atari-ST-default.cfg new file mode 100644 index 0000000000..f242a8e4aa --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/hatari-lr/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/projects/ArchR/packages/emulators/libretro/hatari-lr/config/hatari.nvram b/projects/ArchR/packages/emulators/libretro/hatari-lr/config/hatari.nvram new file mode 100644 index 0000000000..e69de29bb2 diff --git a/projects/ArchR/packages/emulators/libretro/hatari-lr/package.mk b/projects/ArchR/packages/emulators/libretro/hatari-lr/package.mk new file mode 100644 index 0000000000..6b0e1dc9ad --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/hatari-lr/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="hatari-lr" +PKG_VERSION="7008194d3f951a157997f67a820578f56f7feee0" +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_LONGDESC="New rebasing of Hatari based on Mercurial upstream. Tries to be a shallow fork for easy upstreaming later on." + +PKG_TOOLCHAIN="make" +PKG_USE_CMAKE="no" + +configure_target() { + : +} + +make_target() { + make -C .. -f Makefile.libretro +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + mkdir -p ${INSTALL}/usr/config/game/configs/hatari + cp ../hatari_libretro.so ${INSTALL}/usr/lib/libretro/ + cp -rf ${PKG_DIR}/config/* ${INSTALL}/usr/config/game/configs/hatari/ +} diff --git a/projects/ArchR/packages/emulators/libretro/idtech-lr/package.mk b/projects/ArchR/packages/emulators/libretro/idtech-lr/package.mk new file mode 100644 index 0000000000..53c765b5cb --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/idtech-lr/package.mk @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="idtech-lr" +PKG_LICENSE="Apache-2.0" +PKG_SITE="https://arch-r.io" +PKG_LONGDESC="Package for all iD Software game engines." +PKG_TOOLCHAIN="manual" +PKG_DOOM_SHAREWARE="https://github.com/archr-linux/packages/raw/main/doom.tar.gz" + +if [ "${OPENGLES_SUPPORT}" = yes ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" + PKG_DEPENDS_TARGET+=" ecwolf-lr prboom-lr tyrquake-lr vitaquake2-lr" +fi + +if [ "${TARGET_ARCH}" = "x86_64" ]; then + PKG_DEPENDS_TARGET+=" vitaquake3-lr boom3-lr" +fi + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/config/idtech + mkdir -p ${INSTALL}/usr/bin + cp -rf ${PKG_DIR}/scripts/* ${INSTALL}/usr/bin + chmod +x ${INSTALL}/usr/bin/* + + mkdir -p ${INSTALL}/usr/share/idtech + cp -rf ${PKG_DIR}/sources/* ${INSTALL}/usr/share/idtech/ + curl -Lo ${INSTALL}/usr/share/idtech/doom.tar.gz ${PKG_DOOM_SHAREWARE} +} + +post_install() { + case ${TARGET_ARCH} in + aarch64) + sed -i '/doom3/d' ${INSTALL}/usr/share/idtech/idtech_dirs + sed -i '/quake3/d' ${INSTALL}/usr/share/idtech/idtech_dirs + ;; + esac +} diff --git a/projects/ArchR/packages/emulators/libretro/idtech-lr/scripts/generate-idtech.sh b/projects/ArchR/packages/emulators/libretro/idtech-lr/scripts/generate-idtech.sh new file mode 100644 index 0000000000..6568cc28ba --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/idtech-lr/scripts/generate-idtech.sh @@ -0,0 +1,229 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + + +# This scripts scans the /storage/roms/idtech folder for idtech game files +# and creates the necessary idtech launcher scripts + +# Source predefined variables +. /etc/os-release + +RA_BIN="/usr/bin/retroarch" +RA_DIR="/usr/lib/libretro" +SCRIPT_DIR="/storage/.config/idtech" +GAME_DIR="/storage/roms/idtech" + +### create .config/idtech if does not exist +if [ ! -d ${SCRIPT_DIR} ]; then + mkdir -p ${SCRIPT_DIR} +fi + +### Create game directories +while read IDTECH_DIR; do + if [ ! -d "${GAME_DIR}/${IDTECH_DIR}" ]; then + mkdir -p ${GAME_DIR}/${IDTECH_DIR} + fi +done
${SCRIPT_DIR}/Doom.sh +#!/bin/bash + +${RA_BIN} -L ${RA_DIR}/prboom_libretro.so ${GAME_DIR}/doom/doom/doom.wad +EOF +fi + +### The Ultimate Doom +if [[ -f "${GAME_DIR}/doom/doomu/doomu.wad" ]] && [[ ! -f ${SCRIPT_DIR}/The\ Ultimate\ Doom.sh ]]; then +cat <${SCRIPT_DIR}/The\ Ultimate\ Doom.sh +#!/bin/bash + +${RA_BIN} -L ${RA_DIR}/prboom_libretro.so ${GAME_DIR}/doom/doomu/doomu.wad +EOF +fi + +### Doom 2 +if [[ -f "${GAME_DIR}/doom/doom2/doom2.wad" ]] && [[ ! -f ${SCRIPT_DIR}/Doom\ II.sh ]]; then +cat <${SCRIPT_DIR}/Doom\ II.sh +#!/bin/bash + +${RA_BIN} -L ${RA_DIR}/prboom_libretro.so ${GAME_DIR}/doom/doom2/doom2.wad +EOF +fi + +### The Plutonia Experiment +if [[ -f "${GAME_DIR}/doom/plutonia/plutonia.wad" ]] && [[ ! -f ${SCRIPT_DIR}/The\ Plutonia\ Experiment.sh ]]; then +cat <${SCRIPT_DIR}/The\ Plutonia\ Experiment.sh +#!/bin/bash + +${RA_BIN} -L ${RA_DIR}/prboom_libretro.so ${GAME_DIR}/doom/plutonia/plutonia.wad +EOF +fi + +### TNT Evilution +if [[ -f "${GAME_DIR}/doom/tnt/tnt.wad" ]] && [[ ! -f ${SCRIPT_DIR}/TNT\ Evilution.sh ]]; then +cat <${SCRIPT_DIR}/TNT\ Evilution.sh +#!/bin/bash + +${RA_BIN} -L ${RA_DIR}/prboom_libretro.so ${GAME_DIR}/doom/tnt/tnt.wad +EOF +fi + +### SIGIL +if [[ -f "${GAME_DIR}/doom/sigil/sigil.wad" ]] && [[ ! -f ${SCRIPT_DIR}/Sigil.sh ]]; then +cat <${SCRIPT_DIR}/Sigil.sh +#!/bin/bash + +${RA_BIN} -L ${RA_DIR}/prboom_libretro.so ${GAME_DIR}/doom/sigil/sigil.wad +EOF +fi + +### SIGIL II +if [[ -f "${GAME_DIR}/doom/sigil2/sigil2.wad" ]] && [[ ! -f ${SCRIPT_DIR}/Sigil\ II.sh ]]; then +cat <${SCRIPT_DIR}/Sigil\ II.sh +#!/bin/bash + +${RA_BIN} -L ${RA_DIR}/prboom_libretro.so ${GAME_DIR}/doom/sigil2/sigil2.wad +EOF +fi + +### Doom 3 +if [[ ${HW_ARCH} = "x86_64" ]] && [[ -f "${GAME_DIR}/doom3/base/pak000.pk4" ]] && [[ ! -f ${SCRIPT_DIR}/Doom\ 3.sh ]]; then +cat <${SCRIPT_DIR}/Doom\ 3.sh +#!/bin/bash + +${RA_BIN} -L ${RA_DIR}/boom3_libretro.so ${GAME_DIR}/doom3/base/* +EOF +fi + +### Doom 3 - Resurrection of Evil +if [[ ${HW_ARCH} = "x86_64" ]] && [[ -f "${GAME_DIR}/doom3/d3xp/pak000.pk4" ]] && [[ ! -f ${SCRIPT_DIR}/Doom\ 3\ -\ Resurrection\ of\ Evil.sh ]]; then +cat <${SCRIPT_DIR}/Doom\ 3\ -\ Resurrection\ of\ Evil.sh +#!/bin/bash + +${RA_BIN} -L ${RA_DIR}/boom3_xp_libretro.so ${GAME_DIR}/doom3/d3xp/* +EOF +fi + +### Quake +if [[ -f "${GAME_DIR}/quake/id1/pak0.pak" ]] && [[ ! -f ${SCRIPT_DIR}/Quake.sh ]]; then +cat <${SCRIPT_DIR}/Quake.sh +#!/bin/bash + +${RA_BIN} -L ${RA_DIR}/tyrquake_libretro.so ${GAME_DIR}/quake/id1/pak0.pak +EOF +fi + +### Quake - Scourge of Armagon +if [[ -f "${GAME_DIR}/quake/hipnotic/pak0.pak" ]] && [[ ! -f ${SCRIPT_DIR}/Quake\ -\ Scourge\ of\ Armagon.sh ]]; then +cat <${SCRIPT_DIR}/Quake\ -\ Scourge\ of\ Armagon.sh +#!/bin/bash + +${RA_BIN} -L ${RA_DIR}/tyrquake_libretro.so ${GAME_DIR}/quake/hipnotic/pak0.pak +EOF +fi + +### Quake - Dissolution of Eternity +if [[ -f "${GAME_DIR}/quake/rogue/pak0.pak" ]] && [[ ! -f ${SCRIPT_DIR}/Quake\ -\ Dissolution\ of\ Eternity.sh ]]; then +cat <${SCRIPT_DIR}/Quake\ -\ Dissolution\ of\ Eternity.sh +#!/bin/bash + +${RA_BIN} -L ${RA_DIR}/tyrquake_libretro.so ${GAME_DIR}/quake/rogue/pak0.pak +EOF +fi + +### Quake - Dimension of the Past +if [[ -f "${GAME_DIR}/quake/dopa/pak0.pak" ]] && [[ ! -f ${SCRIPT_DIR}/Quake\ -\ Dimension\ of\ the\ Past.sh ]]; then +cat <${SCRIPT_DIR}/Quake\ -\ Dimension\ of\ the\ Past.sh +#!/bin/bash + +${RA_BIN} -L ${RA_DIR}/tyrquake_libretro.so ${GAME_DIR}/quake/dopa/pak0.pak +EOF +fi + +### Malice +if [[ -f "${GAME_DIR}/quake/malice/pak0.pak" ]] && [[ ! -f ${SCRIPT_DIR}/Malice.sh ]]; then +cat <${SCRIPT_DIR}/Malice.sh +#!/bin/bash + +${RA_BIN} -L ${RA_DIR}/tyrquake_libretro.so ${GAME_DIR}/quake/malice/pak0.pak +EOF +fi + +### Quake 2 +if [[ -f "${GAME_DIR}/quake2/baseq2/pak0.pak" ]] && [[ ! -f ${SCRIPT_DIR}/Quake\ II.sh ]]; then +cat <${SCRIPT_DIR}/Quake\ II.sh +#!/bin/bash + +${RA_BIN} -L ${RA_DIR}/vitaquake2_libretro.so ${GAME_DIR}/quake2/baseq2/* +EOF +fi + +### Quake 2 - The Reckoning +if [[ -f "${GAME_DIR}/quake2/xatrix/pak0.pak" ]] && [[ ! -f ${SCRIPT_DIR}/Quake\ II\ -\ The\ Reckoning.sh ]]; then +cat <${SCRIPT_DIR}/Quake\ II\ -\ The\ Reckoning.sh +#!/bin/bash + +${RA_BIN} -L ${RA_DIR}/vitaquake2-xatrix_libretro.so ${GAME_DIR}/quake2/xatrix/* +EOF +fi + +### Quake 2 - Ground Zero +if [[ -f "${GAME_DIR}/quake2/rogue/pak0.pak" ]] && [[ ! -f ${SCRIPT_DIR}/Quake\ II\ -\ Ground\ Zero.sh ]]; then +cat <${SCRIPT_DIR}/Quake\ II\ -\ Ground\ Zero.sh +#!/bin/bash + +${RA_BIN} -L ${RA_DIR}/vitaquake2-rogue_libretro.so ${GAME_DIR}/quake2/rogue/* +EOF +fi + +### Quake 2 - Zaero +if [[ -f "${GAME_DIR}/quake2/zaero/pak0.pak" ]] && [[ ! -f ${SCRIPT_DIR}/Quake\ II\ -\ Zaero.sh ]]; then +cat <${SCRIPT_DIR}/Quake\ II\ -\ Zaero.sh +#!/bin/bash + +${RA_BIN} -L ${RA_DIR}/vitaquake2-zaero_libretro.so ${GAME_DIR}/quake2/zaero/* +EOF +fi + +### Quake 3 +if [[ ${HW_ARCH} = "x86_64" ]] && [[ -f "${GAME_DIR}/quake3/baseq3/pak0.pk3" ]] && [[ ! -f ${SCRIPT_DIR}/Quake\ III.sh ]]; then +cat <${SCRIPT_DIR}/Quake\ III.sh +#!/bin/bash + +${RA_BIN} -L ${RA_DIR}/vitaquake3_libretro.so ${GAME_DIR}/quake3/baseq3/* +EOF +fi + +### Wolfenstein 3D +if [[ -f "${GAME_DIR}/wolf3d/wolf3d/VSWAP.WL6" ]] && [[ ! -f ${SCRIPT_DIR}/Wolfenstein\ 3D.sh ]]; then +cat <${SCRIPT_DIR}/Wolfenstein\ 3D.sh +#!/bin/bash + +${RA_BIN} -L ${RA_DIR}/ecwolf_libretro.so ${GAME_DIR}/wolf3d/wolf3d/* +EOF +fi + +### Wolfenstein 3D - Spear of Destiny +if [[ -f "${GAME_DIR}/wolf3d/sod/VSWAP.SOD" ]] && [[ ! -f ${SCRIPT_DIR}/Wolfenstein\ 3D\ -\ Spear\ of\ Destiny.sh ]]; then +cat <${SCRIPT_DIR}/Wolfenstein\ 3D\ -\ Spear\ of\ Destiny.sh +#!/bin/bash + +${RA_BIN} -L ${RA_DIR}/ecwolf_libretro.so ${GAME_DIR}/wolf3d/sod/* +EOF +fi + +### Set all launcher scripts to be executable ### +chmod +x ${SCRIPT_DIR}/* + +#Restart ES so games are displayed +systemctl restart ${UI_SERVICE} diff --git a/projects/ArchR/packages/emulators/libretro/idtech-lr/sources/idtech_dirs b/projects/ArchR/packages/emulators/libretro/idtech-lr/sources/idtech_dirs new file mode 100644 index 0000000000..1bf88d991e --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/idtech-lr/sources/idtech_dirs @@ -0,0 +1,21 @@ +doom/doom +doom/doomu +doom/doom2 +doom/plutonia +doom/tnt +doom/sigil +doom/sigil2 +doom3/base +doom3/d3xp +quake/id1 +quake/dopa +quake/hipnotic +quake/rogue +quake/malice +quake2/baseq2 +quake2/rogue +quake2/xatrix +quake2/zaero +quake3/baseq3 +wolf3d/wolf3d +wolf3d/sod diff --git a/projects/ArchR/packages/emulators/libretro/jaxe-lr/package.mk b/projects/ArchR/packages/emulators/libretro/jaxe-lr/package.mk new file mode 100644 index 0000000000..6a017231bc --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/jaxe-lr/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-present AmberELEC (https://github.com/AmberELEC) + +PKG_NAME="jaxe-lr" +PKG_VERSION="4825aad24716f67924cd949354aae490a14b4d2d" +PKG_ARCH="aarch64" +PKG_SITE="https://github.com/kurtjd/jaxe" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A fully-featured, cross platform XO-CHIP/S-CHIP/CHIP-8 emulator written in C and SDL" +PKG_TOOLCHAIN="make" + +make_target() { + cd ${PKG_BUILD} + make -f Makefile.libretro +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp ${PKG_BUILD}/jaxe_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/libretro-database/package.mk b/projects/ArchR/packages/emulators/libretro/libretro-database/package.mk new file mode 100644 index 0000000000..82d69642f2 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/libretro-database/package.mk @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="libretro-database" +PKG_VERSION="fbcc8c1c24d8b20b6aaca95b4da6a2f39ad85f05" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/libretro/libretro-database" +PKG_URL="https://github.com/libretro/libretro-database/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="" +PKG_LONGDESC="Repository containing cheatcode files, content data files, etc." +PKG_TOOLCHAIN="manual" + +post_unpack() { + sed -i '/cp -ar -t .* cht cursors/s/ rdb//' ${PKG_BUILD}/Makefile +} + +makeinstall_target() { + make install INSTALLDIR="${INSTALL}/usr/share/libretro-database" -C "${PKG_BUILD}" +} diff --git a/projects/ArchR/packages/emulators/libretro/mame-lr/package.mk b/projects/ArchR/packages/emulators/libretro/mame-lr/package.mk new file mode 100644 index 0000000000..7f2837163e --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/mame-lr/package.mk @@ -0,0 +1,69 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019 Trond Haugland (trondah@gmail.com) + +PKG_NAME="mame-lr" +PKG_VERSION="a90e86e100f79533f257ac2b30ccefe26a76daad" +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_LONGDESC="MAME - Multiple Arcade Machine Emulator" +PKG_TOOLCHAIN="make" +PKG_BUILD_FLAGS="-lto +pic" + +case ${TARGET_ARCH} in + arm|aarch64) + MAME_PLATFORM="PLATFORM=arm64" + CROSS_BUILD="1" + PTR64=0 + ;; + *) + CROSS_BUILD="0" + PTR64=1 + ;; +esac + +PKG_MAKE_OPTS_TARGET="REGENIE=1 \ + VERBOSE=1 \ + NOWERROR=1 \ + OPENMP=1 \ + CROSS_BUILD=${CROSS_BUILD} \ + TOOLS=0 \ + RETRO=1 \ + PTR64=${PTR64} \ + NOASM=0 \ + PYTHON_EXECUTABLE=python3 \ + CONFIG=libretro \ + LIBRETRO_OS=unix \ + LIBRETRO_CPU= \ + ${MAME_PLATFORM} \ + 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 + if [ "${PLATFORM}" = "arm64" ] + then + export ARCHOPTS="-D__aarch64__ -DASMJIT_BUILD_X86" + fi + 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/projects/ArchR/packages/emulators/libretro/mame-lr/patches/mame-crosscompile.patch b/projects/ArchR/packages/emulators/libretro/mame-lr/patches/mame-crosscompile.patch new file mode 100644 index 0000000000..c100e31b27 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/mame-lr/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 2025-01-04 19:13:10.550615500 +0100 ++++ b/3rdparty/genie/src/host/scripts.c 2025-01-04 21:29:13.629791709 +0100 +@@ -149,7 +149,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\",\nCpp20 = \"-std=c++20\",\nCppLatest = \"-std=c++2b\",\nNoExceptions = \"-fno-exceptions\",\nNoRTTI = \"-fno-rtti\",\nUnsignedChar = \"-funsigned-char\",\n}\nlocal objcflags =\n{\nObjcARC = \"-fobjc-arc\",\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},\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 " ++ "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},\nEmscripten = {\ncc = \"$(EMSCRIPTEN)/emcc\",\ncxx = \"$(EMSCRIPTEN)/em++\",\nar = \"$(EMSCRIPTEN)/emar\",\ncppflags = \"-MMD -MP\",\n},\nNX32 = {\ncc = \"clang\",\ncxx = \"clang++\",\nar = \"armv7l-nintendo-nx-eabihf-ar\",\ncppflags = \"-MMD -MP\",\nflags = \"-march=armv7l\",\n},\nNX64 = {\ncc = \"clang\",\ncxx = \"clang++\",\nar = \"aarch64-nintendo-nx-elf-ar\",\ncppflags = \"-MMD -MP\",\nflags = \"-march=aarch64\",\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\nt" + "able.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, platf" + "orm.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.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\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.inser" +--- 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/projects/ArchR/packages/emulators/libretro/mame2003-lr/package.mk b/projects/ArchR/packages/emulators/libretro/mame2003-lr/package.mk new file mode 100644 index 0000000000..e85d88ee18 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/mame2003-lr/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) +# 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-lr" +PKG_VERSION="c079e586e5ef54e084622863816f4f0439fdb870" +PKG_SHA256="a23579c5df4cadcf57740a4d64e10eff0e26805e304261902a4d891fd2a2662a" +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_LONGDESC="MAME - Multiple Arcade Machine Emulator" + +PKG_TOOLCHAIN="make" + +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/projects/ArchR/packages/emulators/libretro/mame2003-plus-lr/package.mk b/projects/ArchR/packages/emulators/libretro/mame2003-plus-lr/package.mk new file mode 100644 index 0000000000..44ee40229c --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/mame2003-plus-lr/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) +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) +# +# 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-lr" +PKG_VERSION="62c7089644966f6ac5fc79fe03592603579a409d" +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_LONGDESC="MAME - Multiple Arcade Machine Emulator" + +PKG_TOOLCHAIN="make" + +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/projects/ArchR/packages/emulators/libretro/mame2010-lr/package.mk b/projects/ArchR/packages/emulators/libretro/mame2010-lr/package.mk new file mode 100644 index 0000000000..c65cdf5faf --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/mame2010-lr/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="mame2010-lr" +PKG_VERSION="c5b413b71e0a290c57fc351562cd47ba75bac105" +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_LONGDESC="Late 2010 version of MAME (0.139) for libretro. Compatible with MAME 0.139 romsets." +PKG_BUILD_FLAGS="-parallel" +PKG_TOOLCHAIN="make" + +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/projects/ArchR/packages/emulators/libretro/mame2015-lr/package.mk b/projects/ArchR/packages/emulators/libretro/mame2015-lr/package.mk new file mode 100644 index 0000000000..0915d2272f --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/mame2015-lr/package.mk @@ -0,0 +1,51 @@ +################################################################################ +# 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-lr" +PKG_VERSION="316cd06349f2b34b4719f04f7c0d07569a74c764" +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_LONGDESC="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 -parallel" + +pre_make_target() { + export REALCC=${CC} + export CC=${CXX} + export LD=${CXX} + # Fix GCC 15 stricter template and implicit conversion checks + export CXXFLAGS="${CXXFLAGS} -fpermissive -Wno-template-body" +} + +pre_configure_target() { + case ${ARCH} in + arm|aarch64) + PKG_MAKE_OPTS_TARGET=" platform=armv8-neon-hardfloat-cortex-a53" + sed -i 's/LDFLAGS += -Wl,--fix-cortex-a8 -Wl,--no-as-needed//g' Makefile + sed -i 's/CCOMFLAGS += -mstructure-size-boundary=32//g' Makefile + ;; + esac +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp mame*_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/mame2015-lr/patches/001-python-3.11.patch b/projects/ArchR/packages/emulators/libretro/mame2015-lr/patches/001-python-3.11.patch new file mode 100644 index 0000000000..eb6df27b31 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/mame2015-lr/patches/001-python-3.11.patch @@ -0,0 +1,57 @@ +diff -rupN mame2015.orig/src/emu/cpu/m6502/m6502make.py mame2015/src/emu/cpu/m6502/m6502make.py +--- mame2015.orig/src/emu/cpu/m6502/m6502make.py 2022-12-06 11:09:35.970767689 -0500 ++++ mame2015/src/emu/cpu/m6502/m6502make.py 2022-12-06 11:10:17.918361583 -0500 +@@ -16,7 +16,7 @@ def load_opcodes(fname): + opcodes = [] + logging.info("load_opcodes: %s", fname) + try: +- f = open(fname, "rU") ++ f = open(fname, "r") + except Exception: + err = sys.exc_info()[1] + logging.error("cannot read opcodes file %s [%s]", fname, err) +@@ -39,7 +39,7 @@ def load_disp(fname): + logging.info("load_disp: %s", fname) + states = [] + try: +- f = open(fname, "rU") ++ f = open(fname, "r") + except Exception: + err = sys.exc_info()[1] + logging.error("cannot read display file %s [%s]", fname, err) +diff -rupN mame2015.orig/src/emu/cpu/m6809/m6809make.py mame2015/src/emu/cpu/m6809/m6809make.py +--- mame2015.orig/src/emu/cpu/m6809/m6809make.py 2022-12-06 11:09:35.974767650 -0500 ++++ mame2015/src/emu/cpu/m6809/m6809make.py 2022-12-06 11:10:02.046515086 -0500 +@@ -14,7 +14,7 @@ def load_file(fname, lines): + if path != "": + path += '/' + try: +- f = open(fname, "rU") ++ f = open(fname, "r") + except Exception: + err = sys.exc_info()[1] + sys.stderr.write("Cannot read opcodes file %s [%s]\n" % (fname, err)) +diff -rupN mame2015.orig/src/emu/cpu/mcs96/mcs96make.py mame2015/src/emu/cpu/mcs96/mcs96make.py +--- mame2015.orig/src/emu/cpu/mcs96/mcs96make.py 2022-12-06 11:09:35.974767650 -0500 ++++ mame2015/src/emu/cpu/mcs96/mcs96make.py 2022-12-06 11:10:07.230464929 -0500 +@@ -71,7 +71,7 @@ class OpcodeList: + self.ea = {} + self.macros = {} + try: +- f = open(fname, "rU") ++ f = open(fname, "r") + except Exception: + err = sys.exc_info()[1] + sys.stderr.write("Cannot read opcodes file %s [%s]\n" % (fname, err)) +diff -rupN mame2015.orig/src/emu/cpu/tms57002/tmsmake.py mame2015/src/emu/cpu/tms57002/tmsmake.py +--- mame2015.orig/src/emu/cpu/tms57002/tmsmake.py 2022-12-06 11:09:35.982767573 -0500 ++++ mame2015/src/emu/cpu/tms57002/tmsmake.py 2022-12-06 11:10:24.850294595 -0500 +@@ -326,7 +326,7 @@ def ins_cmp_dasm(a, b): + def LoadLst(filename): + instructions = [] + ins = None +- for n, line in enumerate(open(filename, "rU")): ++ for n, line in enumerate(open(filename, "r")): + line = line.rstrip() + if not line and ins: + # new lines separate intructions diff --git a/projects/ArchR/packages/emulators/libretro/melonds-ds-lr/package.mk b/projects/ArchR/packages/emulators/libretro/melonds-ds-lr/package.mk new file mode 100644 index 0000000000..61bd81ea73 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/melonds-ds-lr/package.mk @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="melonds-ds-lr" +PKG_VERSION="86986bfd82fb130d4d4739d93159acd986921808" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/JesseTG/melonds-ds" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_SHORTDESC="An enhanced remake of the melonDS core for libretro that prioritizes standalone parity, reliability, and usability." +PKG_TOOLCHAIN="cmake-make" + +PKG_CMAKE_OPTS_TARGET=" -DENABLE_OPENGL=ON" + +if [ "${OPENGL_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL}" + PKG_CMAKE_OPTS_TARGET+=" -DDEFAULT_OPENGL_PROFILE=OpenGL" +elif [ "${OPENGLES_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" + PKG_CMAKE_OPTS_TARGET+=" -DDEFAULT_OPENGL_PROFILE=OpenGLES2" +fi + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp ${PKG_BUILD}/.${TARGET_NAME}/src/libretro/melondsds_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/melonds-lr/package.mk b/projects/ArchR/packages/emulators/libretro/melonds-lr/package.mk new file mode 100644 index 0000000000..a2a58a917b --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/melonds-lr/package.mk @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="melonds-lr" +PKG_VERSION="7a3c11ff970cd36ca806961fae6db94b30dd5401" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/libretro/melonDS" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="MelonDS - Nintendo DS emulator for libretro" +PKG_TOOLCHAIN="make" + +if [ ! "${OPENGL}" = "no" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL} glu libglvnd" +fi + +if [ "${OPENGLES_SUPPORT}" = yes ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" +fi + +pre_make_target() { + + cd ${PKG_BUILD} + if [ -e "CMakeLists.txt" ] + then + rm CMakeLists.txt + fi +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp melonds_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/mesen-lr/package.mk b/projects/ArchR/packages/emulators/libretro/mesen-lr/package.mk new file mode 100644 index 0000000000..5fcd8da085 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/mesen-lr/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="mesen-lr" +PKG_VERSION="791c5e8153ee6e29691d45b5df2cf1151ff416f9" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/libretro/Mesen" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Mesen is a cross-platform NES/Famicom emulator for Windows & Linux built in C++ and C#." +PKG_TOOLCHAIN="make" + +make_target() { + make -C Libretro/ +} + + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp Libretro/mesen_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/mgba-lr/package.mk b/projects/ArchR/packages/emulators/libretro/mgba-lr/package.mk new file mode 100644 index 0000000000..97eec4c5a4 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/mgba-lr/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) +# +# 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-lr" +PKG_VERSION="c758314a639aa0066e7b65a8341448181b73c804" +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_LONGDESC="mGBA Game Boy Advance Emulator" +PKG_PATCH_DIRS+="${DEVICE}" + +PKG_TOOLCHAIN="make" +PKG_USE_CMAKE="no" + +make_target() { + cd ${PKG_BUILD} + case ${ARCH} in + arm) + make -f Makefile.libretro platform=unix-armv HAVE_NEON=1 + ;; + aarch64) + make -f Makefile.libretro platform=goadvance + ;; + *) + make -f Makefile.libretro + ;; + esac +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp mgba_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/minivmac-lr/package.mk b/projects/ArchR/packages/emulators/libretro/minivmac-lr/package.mk new file mode 100644 index 0000000000..2e97c8ef7a --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/minivmac-lr/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="minivmac-lr" +PKG_VERSION="6b468a9610aa422fe1b01bf56d73b636976d2b97" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/libretro-minivmac" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Virtual Macintosh" +PKG_TOOLCHAIN="make" + + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp ${PKG_BUILD}/minivmac_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/mojozork-lr/package.mk b/projects/ArchR/packages/emulators/libretro/mojozork-lr/package.mk new file mode 100644 index 0000000000..fc667b78a7 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/mojozork-lr/package.mk @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-present AmberELEC (https://github.com/AmberELEC) + +PKG_NAME="mojozork-lr" +PKG_VERSION="5c8d81f8db53c206ace6952472e7a7e68bd8e752" +PKG_SITE="https://github.com/icculus/mojozork" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain sqlite" +PKG_LONGDESC="A simple Z-Machine implementation in a single C file" +PKG_TOOLCHAIN="cmake" + +PKG_CMAKE_OPTS_TARGET="-DMOJOZORK_LIBRETRO=ON \ + -DMOJOZORK_STANDALONE_DEFAULT=OFF \ + -DMOJOZORK_MULTIZORK_DEFAULT=OFF \ + -DCMAKE_POLICY_VERSION_MINIMUM=3.5" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp ${PKG_BUILD}/.${TARGET_NAME}/mojozork_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/mu-lr/package.mk b/projects/ArchR/packages/emulators/libretro/mu-lr/package.mk new file mode 100644 index 0000000000..468aaad904 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/mu-lr/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="mu-lr" +PKG_VERSION="865acf3a2889dfe02863bbfb9c5b3cfee8620c22" +PKG_LICENSE="CC BY-NC 3.0 US" +PKG_SITE="https://github.com/libretro/Mu" +PKG_URL="${PKG_SITE}/-/archive/${PKG_VERSION}/Mu-${PKG_VERSION}.tar.gz" +PKG_GIT_CLONE_BRANCH="buildbot" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="An emulator for the Palm m515 OS ported to libretro." + +PKG_TOOLCHAIN="make" + +make_target() { + make -C ${PKG_BUILD}/libretroBuildSystem/ +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp ${PKG_BUILD}/libretroBuildSystem/mu_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/mupen64plus-lr/package.mk b/projects/ArchR/packages/emulators/libretro/mupen64plus-lr/package.mk new file mode 100644 index 0000000000..125a83648f --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/mupen64plus-lr/package.mk @@ -0,0 +1,56 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) +# +# 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-lr" +PKG_VERSION="ab8134ac90a567581df6de4fc427dd67bfad1b17" +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" +PKG_LONGDESC="mupen64plus + RSP-HLE + GLideN64 + libretro" +PKG_TOOLCHAIN="make" +PKG_BUILD_FLAGS="-lto" +PKG_PATCH_DIRS+=" ${DEVICE}" + +if [ "${OPENGL}" = "yes" ] && [ ! "${PREFER_GLES}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL} glu" + PKG_MAKE_OPTS_TARGET+=" GLES=0 GL_LIB=\"-lGL\"" +elif [ "${OPENGLES_SUPPORT}" = yes ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" + PKG_MAKE_OPTS_TARGET+=" GLES=1 GL_LIB=\"-lGLESv2\"" +fi + +pre_configure_target() { + export CFLAGS="${CFLAGS} -fcommon -Wno-error=incompatible-pointer-types -std=gnu17" + + case ${ARCH} in + aarch64) + PKG_MAKE_OPTS_TARGET+=" OS_LINUX=1 platform=${DEVICE}" + ;; + esac + + sed -i 's/\-O[23]/-Ofast/' ${PKG_BUILD}/Makefile +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp mupen64plus_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/mupen64plus-lr/patches/aarch64/001-optimizations.patch b/projects/ArchR/packages/emulators/libretro/mupen64plus-lr/patches/aarch64/001-optimizations.patch new file mode 100644 index 0000000000..f8afa9d651 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/mupen64plus-lr/patches/aarch64/001-optimizations.patch @@ -0,0 +1,20 @@ +diff -rupN mupen64plus.orig/Makefile mupen64plus/Makefile +--- mupen64plus.orig/Makefile 2022-02-27 09:19:06.080700288 -0500 ++++ mupen64plus/Makefile 2022-02-27 13:27:51.390268523 -0500 +@@ -238,6 +238,16 @@ else ifneq (,$(findstring osx,$(platform + + COREFLAGS += -DOS_LINUX + ASFLAGS = -f elf -d ELF_TYPE ++ ++# @DEVICE@ ++else ifneq (,$(findstring @DEVICE@,$(platform))) ++ TARGET := $(TARGET_NAME)_libretro.so ++ LDFLAGS += -shared -Wl,--version-script=$(LIBRETRO_DIR)/link.T -Wl,--no-undefined -ldl ++ COREFLAGS += -DOS_LINUX ++ HAVE_NEON = 0 ++ WITH_DYNAREC := aarch64 ++ ASFLAGS = -f elf -d ELF_TYPE ++ + # iOS + else ifneq (,$(findstring ios,$(platform))) + ifeq ($(IOSSDK),) diff --git a/projects/ArchR/packages/emulators/libretro/mupen64plus-lr/patches/mupen64plus-fixdouble.patch b/projects/ArchR/packages/emulators/libretro/mupen64plus-lr/patches/mupen64plus-fixdouble.patch new file mode 100644 index 0000000000..64070b5d25 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/mupen64plus-lr/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/projects/ArchR/packages/emulators/libretro/mupen64plus-lr/patches/mupen64plus-inc-string.patch b/projects/ArchR/packages/emulators/libretro/mupen64plus-lr/patches/mupen64plus-inc-string.patch new file mode 100644 index 0000000000..5c85488abe --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/mupen64plus-lr/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/projects/ArchR/packages/emulators/libretro/mupen64plus-nx-lr/package.mk b/projects/ArchR/packages/emulators/libretro/mupen64plus-nx-lr/package.mk new file mode 100755 index 0000000000..7be058f83d --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/mupen64plus-nx-lr/package.mk @@ -0,0 +1,53 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="mupen64plus-nx-lr" +PKG_VERSION="7c7f11061f29b2ccd5d0952e2373ae5b55cfea8f" +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" +PKG_LONGDESC="mupen64plus NX" +PKG_TOOLCHAIN="make" +PKG_BUILD_FLAGS="-lto" + +if [ "${OPENGL_SUPPORT}" = "yes" ] && [ ! "${PREFER_GLES}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL} glu libglvnd" + PKG_MAKE_OPTS_TARGET+=" GL_LIB=\"-lGL\" GLES3=0" +elif [ "${OPENGLES_SUPPORT}" = yes ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" + PKG_MAKE_OPTS_TARGET+=" GL_LIB=\"-lGLESv2\" GLES3=1" +fi + +if [ "${VULKAN_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${VULKAN}" + PKG_MAKE_OPTS_TARGET+=" HAVE_PARALLEL_RSP=1 HAVE_PARALLEL_RDP=1" +fi + +echo PKG_DEPENDS_TARGET ${PKG_DEPENDS_TARGET} + +pre_configure_target() { + export CFLAGS="${CFLAGS} -DHAVE_UNISTD_H -Wno-error=incompatible-pointer-types" + if [ "${ARCH}" = "aarch64" ]; then + # This is only needed for armv8.2-a targets where we don't use this flag + # as it prohibits the use of LSE-instructions, this is a package bug most likely + export CXXFLAGS="${CXXFLAGS} -mno-outline-atomics" + fi + for SOURCE in ${PKG_BUILD}/mupen64plus-rsp-paraLLEl/rsp_disasm.cpp ${PKG_BUILD}/mupen64plus-rsp-paraLLEl/rsp_disasm.hpp + do + sed -i '/include /a #include ' ${SOURCE} + done + sed -e "s|^GIT_VERSION ?.*$|GIT_VERSION := \" ${PKG_VERSION:0:7}\"|" -i Makefile + sed -i 's/\-O[23]/-Ofast/' ${PKG_BUILD}/Makefile + + case ${ARCH} in + aarch64) + PKG_MAKE_OPTS_TARGET+=" platform=${DEVICE}" + ;; + esac +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp mupen64plus_next_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/mupen64plus-nx-lr/patches/000-platform.patch b/projects/ArchR/packages/emulators/libretro/mupen64plus-nx-lr/patches/000-platform.patch new file mode 100644 index 0000000000..2e7a4489f3 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/mupen64plus-nx-lr/patches/000-platform.patch @@ -0,0 +1,44 @@ +diff --git a/Makefile b/Makefile +index 481e8b9..2a4e365 100644 +--- a/Makefile ++++ b/Makefile +@@ -366,34 +366,13 @@ else ifneq (,$(findstring arm64_cortex_a53_gles3,$(platform))) + COREFLAGS += -DOS_LINUX + ASFLAGS = -f elf64 -d ELF_TYPE + +-# Rockchip RK3288 e.g. Asus Tinker Board / RK3328 e.g. PINE64 Rock64 / RK3399 e.g. PINE64 RockPro64 - 32-bit userspace +-else ifneq (,$(findstring RK,$(platform))) ++# ArchR DEVICE ++else ifneq (,$(findstring @DEVICE@,$(platform))) + TARGET := $(TARGET_NAME)_libretro.so + LDFLAGS += -shared -Wl,--version-script=$(LIBRETRO_DIR)/link.T -Wl,--no-undefined -ldl +- +- ifneq (,$(findstring RK33,$(platform))) +- CPUFLAGS += -march=armv8-a+crc -mfloat-abi=hard -mfpu=neon-fp-armv8 +- ifneq (,$(findstring RK3399,$(platform))) +- CPUFLAGS += -mtune=cortex-a72.cortex-a53 +- GLES3 = 1 +- else ifneq (,$(findstring RK3328,$(platform))) +- CPUFLAGS += -mtune=cortex-a53 +- GLES = 1 +- endif +- else ifneq (,$(findstring RK3288,$(platform))) +- CPUFLAGS += -march=armv7ve -mtune=cortex-a17 -mfloat-abi=hard -mfpu=neon-vfpv4 +- GLES3 = 1 +- endif +- +- ifneq (,$(findstring mesa,$(platform))) +- COREFLAGS += -DEGL_NO_X11 +- endif +- +- GL_LIB := -lGLESv2 +- HAVE_NEON = 1 +- WITH_DYNAREC=arm +- COREFLAGS += -DUSE_GENERIC_GLESV2 -DOS_LINUX +- ASFLAGS = -f elf -d ELF_TYPE ++ WITH_DYNAREC := aarch64 ++ COREFLAGS += -DOS_LINUX ++ ASFLAGS = -f elf64 -d ELF_TYPE + + # OS X + else ifneq (,$(findstring osx,$(platform))) diff --git a/projects/ArchR/packages/emulators/libretro/mupen64plus-nx-lr/patches/001-fix-building-with-gcc15.patch b/projects/ArchR/packages/emulators/libretro/mupen64plus-nx-lr/patches/001-fix-building-with-gcc15.patch new file mode 100644 index 0000000000..12ba64fbb3 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/mupen64plus-nx-lr/patches/001-fix-building-with-gcc15.patch @@ -0,0 +1,19 @@ +--- a/GLideN64/src/GLideNHQ/TxHiResLoader.h ++++ b/GLideN64/src/GLideNHQ/TxHiResLoader.h +@@ -1,6 +1,8 @@ + #ifndef TXHIRESLOADER_H + #define TXHIRESLOADER_H + ++#include ++ + /* support hires textures + * 0: disable + * 1: enable +--- a/GLideN64/src/GLideNHQ/TxHiResLoader.cpp ++++ b/GLideN64/src/GLideNHQ/TxHiResLoader.cpp +@@ -1,3 +1,5 @@ ++#include ++ + #include "TxHiResLoader.h" + #include "TxDbg.h" + #include "TxDbg.h" diff --git a/projects/ArchR/packages/emulators/libretro/neocd_lr/package.mk b/projects/ArchR/packages/emulators/libretro/neocd_lr/package.mk new file mode 100644 index 0000000000..6265b5599b --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/neocd_lr/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="neocd_lr" +PKG_VERSION="5eca2c8fd567b5261251c65ecafa8cf5b179d1d2" +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_LONGDESC="Neo Geo CD emulator for libretro " +PKG_TOOLCHAIN="make" +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/projects/ArchR/packages/emulators/libretro/nestopia-lr/package.mk b/projects/ArchR/packages/emulators/libretro/nestopia-lr/package.mk new file mode 100644 index 0000000000..298350f2d7 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/nestopia-lr/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="nestopia-lr" +PKG_VERSION="5deada54077fae87e2873f5ad9ef77e3ab7af5e1" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/nestopia" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Libretro implementation of NEStopia. (Nintendo Entertainment System)" + +PKG_TOOLCHAIN="make" +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/projects/ArchR/packages/emulators/libretro/np2kai-lr/package.mk b/projects/ArchR/packages/emulators/libretro/np2kai-lr/package.mk new file mode 100644 index 0000000000..8074ff0f12 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/np2kai-lr/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="np2kai-lr" +PKG_VERSION="c2ca4046860264cb307e768f529f180caee5e224" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/AZO234/NP2kai" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Neko Project II kai" +PKG_TOOLCHAIN="make" + +pre_configure_target() { +export CFLAGS="${CFLAGS} -Wno-error=incompatible-pointer-types -Wno-int-conversion" +} + +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/projects/ArchR/packages/emulators/libretro/o2em-lr/package.mk b/projects/ArchR/packages/emulators/libretro/o2em-lr/package.mk new file mode 100644 index 0000000000..6f0b972f21 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/o2em-lr/package.mk @@ -0,0 +1,34 @@ +################################################################################ +# 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-lr" +PKG_VERSION="3ba4231c1dc8dcdf487428712856b790d2e4b8f3" +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_LONGDESC="Port of O2EM to the libretro API, an Odyssey 2 / VideoPac emulator." + +PKG_TOOLCHAIN="make" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp o2em_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/opera-lr/package.mk b/projects/ArchR/packages/emulators/libretro/opera-lr/package.mk new file mode 100644 index 0000000000..245501d306 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/opera-lr/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="opera-lr" +PKG_VERSION="67a29e60a4d194b675c9272b21b61eaa022f3ba3" +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_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/projects/ArchR/packages/emulators/libretro/panda3ds-lr/package.mk b/projects/ArchR/packages/emulators/libretro/panda3ds-lr/package.mk new file mode 100644 index 0000000000..4890db074e --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/panda3ds-lr/package.mk @@ -0,0 +1,34 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="panda3ds-lr" +PKG_VERSION="5591606177d7d595e19a18b3fdd33b8ffbbc1449" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/wheremyfoodat/Panda3DS" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Panda3DS is an HLE, red-panda-themed Nintendo 3DS emulator" +PKG_TOOLCHAIN="cmake" + +if [ "${OPENGL_SUPPORT}" = "yes" ] && [ ! "${PREFER_GLES}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL}" + PKG_CMAKE_OPTS_TARGET+=" -DOPENGL_PROFILE=OpenGL" +elif [ "${OPENGLES_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" + PKG_PATCH_DIRS+=" gles" + PKG_CMAKE_OPTS_TARGET+=" -DOPENGL_PROFILE=OpenGLES" +fi + +PKG_CMAKE_OPTS_TARGET+=" -DBUILD_LIBRETRO_CORE=ON \ + -DENABLE_USER_BUILD=ON \ + -DENABLE_DISCORD_RPC=OFF \ + -DENABLE_LUAJIT=OFF \ + -DSDL_VIDEO=OFF \ + -DSDL_AUDIO=OFF \ + -DENABLE_VULKAN=OFF \ + -DCMAKE_BUILD_TYPE=Release" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp -v ${PKG_BUILD}/.${TARGET_NAME}/panda3ds_libretro.so ${INSTALL}/usr/lib/libretro/panda3ds_libretro.so +} diff --git a/projects/ArchR/packages/emulators/libretro/panda3ds-lr/patches/gles/000-enable-gles.patch b/projects/ArchR/packages/emulators/libretro/panda3ds-lr/patches/gles/000-enable-gles.patch new file mode 100644 index 0000000000..c9de55daa6 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/panda3ds-lr/patches/gles/000-enable-gles.patch @@ -0,0 +1,270 @@ +diff -rupbN panda3ds.orig/src/host_shaders/opengl_display.frag panda3ds/src/host_shaders/opengl_display.frag +--- panda3ds.orig/src/host_shaders/opengl_display.frag 2024-08-28 21:01:16.674631846 +0000 ++++ panda3ds/src/host_shaders/opengl_display.frag 2024-08-28 22:09:19.387098916 +0000 +@@ -1,4 +1,5 @@ +-#version 410 core ++#version 320 es ++precision mediump float; + in vec2 UV; + out vec4 FragColor; + +diff -rupbN panda3ds.orig/src/host_shaders/opengl_display.vert panda3ds/src/host_shaders/opengl_display.vert +--- panda3ds.orig/src/host_shaders/opengl_display.vert 2024-08-28 21:01:16.674631846 +0000 ++++ panda3ds/src/host_shaders/opengl_display.vert 2024-08-28 22:09:19.387098916 +0000 +@@ -1,4 +1,5 @@ +-#version 410 core ++#version 320 es ++precision mediump float; + out vec2 UV; + + void main() { +diff -rupbN panda3ds.orig/src/host_shaders/opengl_fragment_shader.frag panda3ds/src/host_shaders/opengl_fragment_shader.frag +--- panda3ds.orig/src/host_shaders/opengl_fragment_shader.frag 2024-08-28 21:01:16.674631846 +0000 ++++ panda3ds/src/host_shaders/opengl_fragment_shader.frag 2024-08-28 22:09:19.387098916 +0000 +@@ -1,4 +1,5 @@ +-#version 410 core ++#version 320 es ++precision mediump float; + + in vec4 v_quaternion; + in vec4 v_colour; +@@ -41,8 +42,8 @@ vec3 normal; + const uint samplerEnabledBitfields[2] = uint[2](0x7170e645u, 0x7f013fefu); + + bool isSamplerEnabled(uint environment_id, uint lut_id) { +- uint index = 7 * environment_id + lut_id; +- uint arrayIndex = (index >> 5); ++ uint index = 7u * environment_id + lut_id; ++ uint arrayIndex = (index >> 5u); + return (samplerEnabledBitfields[arrayIndex] & (1u << (index & 31u))) != 0u; + } + +@@ -166,11 +167,17 @@ float lutLookup(uint lut, int index) { + return texelFetch(u_tex_luts, ivec2(index, int(lut)), 0).r; + } + ++// some gles versions have bitfieldExtractCompat and complain if you redefine it, some don't and compile error, using this instead ++uint bitfieldExtractCompat(uint val, int off, int size) { ++ uint mask = uint((1 << size) - 1); ++ return uint(val >> off) & mask; ++} ++ + vec3 regToColor(uint reg) { + // Normalization scale to convert from [0...255] to [0.0...1.0] + const float scale = 1.0 / 255.0; + +- return scale * vec3(float(bitfieldExtract(reg, 20, 8)), float(bitfieldExtract(reg, 10, 8)), float(bitfieldExtract(reg, 00, 8))); ++ return scale * vec3(float(bitfieldExtractCompat(reg, 20, 8)), float(bitfieldExtractCompat(reg, 10, 8)), float(bitfieldExtractCompat(reg, 00, 8))); + } + + // Convert an arbitrary-width floating point literal to an f32 +@@ -201,7 +208,7 @@ float lightLutLookup(uint environment_id + // These are the spotlight attenuation LUTs + bit_in_config1 = 8 + int(light_id & 7u); + lut_index = 8u + light_id; +- } else if (lut_id <= 6) { ++ } else if (lut_id <= 6u) { + bit_in_config1 = 16 + int(lut_id); + lut_index = lut_id; + } else { +@@ -210,16 +217,16 @@ float lightLutLookup(uint environment_id + + bool current_sampler_enabled = isSamplerEnabled(environment_id, lut_id); // 7 luts per environment + +- if (!current_sampler_enabled || (bitfieldExtract(GPUREG_LIGHTING_CONFIG1, bit_in_config1, 1) != 0u)) { ++ if (!current_sampler_enabled || (bitfieldExtractCompat(GPUREG_LIGHTING_CONFIG1, bit_in_config1, 1) != 0u)) { + return 1.0; + } + +- uint scale_id = bitfieldExtract(GPUREG_LIGHTING_LUTINPUT_SCALE, int(lut_id) << 2, 3); ++ uint scale_id = bitfieldExtractCompat(GPUREG_LIGHTING_LUTINPUT_SCALE, int(lut_id) << 2, 3); + float scale = float(1u << scale_id); + if (scale_id >= 6u) scale /= 256.0; + + float delta = 1.0; +- uint input_id = bitfieldExtract(GPUREG_LIGHTING_LUTINPUT_SELECT, int(lut_id) << 2, 3); ++ uint input_id = bitfieldExtractCompat(GPUREG_LIGHTING_LUTINPUT_SELECT, int(lut_id) << 2, 3); + switch (input_id) { + case 0u: { + delta = dot(normal, normalize(half_vector)); +@@ -243,9 +250,9 @@ float lightLutLookup(uint environment_id + + // Sign extend them. Normally bitfieldExtract would do that but it's missing on some versions + // of GLSL so we do it manually +- int se_x = bitfieldExtract(GPUREG_LIGHTi_SPOTDIR_LOW, 0, 13); +- int se_y = bitfieldExtract(GPUREG_LIGHTi_SPOTDIR_LOW, 16, 13); +- int se_z = bitfieldExtract(GPUREG_LIGHTi_SPOTDIR_HIGH, 0, 13); ++ int se_x = int(bitfieldExtractCompat(uint(GPUREG_LIGHTi_SPOTDIR_LOW), 0, 13)); ++ int se_y = int(bitfieldExtractCompat(uint(GPUREG_LIGHTi_SPOTDIR_LOW), 16, 13)); ++ int se_z = int(bitfieldExtractCompat(uint(GPUREG_LIGHTi_SPOTDIR_HIGH), 0, 13)); + + if ((se_x & 0x1000) == 0x1000) se_x |= 0xffffe000; + if ((se_y & 0x1000) == 0x1000) se_y |= 0xffffe000; +@@ -272,9 +279,9 @@ float lightLutLookup(uint environment_id + } + + // 0 = enabled +- if (bitfieldExtract(GPUREG_LIGHTING_LUTINPUT_ABS, 1 + (int(lut_id) << 2), 1) == 0u) { ++ if (bitfieldExtractCompat(GPUREG_LIGHTING_LUTINPUT_ABS, 1 + (int(lut_id) << 2), 1) == 0u) { + // Two sided diffuse +- if (bitfieldExtract(GPUREG_LIGHTi_CONFIG, 1, 1) == 0u) { ++ if (bitfieldExtractCompat(GPUREG_LIGHTi_CONFIG, 1, 1) == 0u) { + delta = max(delta, 0.0); + } else { + delta = abs(delta); +@@ -298,7 +305,7 @@ vec3 rotateVec3ByQuaternion(vec3 v, vec4 + // Implements the following algorthm: https://mathb.in/26766 + void calcLighting(out vec4 primary_color, out vec4 secondary_color) { + uint GPUREG_LIGHTING_ENABLE = readPicaReg(0x008Fu); +- if (bitfieldExtract(GPUREG_LIGHTING_ENABLE, 0, 1) == 0u) { ++ if (bitfieldExtractCompat(GPUREG_LIGHTING_ENABLE, 0, 1) == 0u) { + primary_color = secondary_color = vec4(0.0); + return; + } +@@ -315,7 +322,7 @@ void calcLighting(out vec4 primary_color + GPUREG_LIGHTING_LUTINPUT_ABS = readPicaReg(0x01D0u); + GPUREG_LIGHTING_LUTINPUT_SELECT = readPicaReg(0x01D1u); + +- uint bump_mode = bitfieldExtract(GPUREG_LIGHTING_CONFIG0, 28, 2); ++ uint bump_mode = bitfieldExtractCompat(GPUREG_LIGHTING_CONFIG0, 28, 2); + + // Bump mode is ignored for now because it breaks some games ie. Toad Treasure Tracker + switch (bump_mode) { +@@ -328,15 +335,15 @@ void calcLighting(out vec4 primary_color + vec4 diffuse_sum = vec4(0.0, 0.0, 0.0, 1.0); + vec4 specular_sum = vec4(0.0, 0.0, 0.0, 1.0); + +- uint environment_id = bitfieldExtract(GPUREG_LIGHTING_CONFIG0, 4, 4); +- bool clamp_highlights = bitfieldExtract(GPUREG_LIGHTING_CONFIG0, 27, 1) == 1u; ++ uint environment_id = bitfieldExtractCompat(GPUREG_LIGHTING_CONFIG0, 4, 4); ++ bool clamp_highlights = bitfieldExtractCompat(GPUREG_LIGHTING_CONFIG0, 27, 1) == 1u; + + uint light_id; + vec3 light_vector; + vec3 half_vector; + + for (uint i = 0u; i < GPUREG_LIGHTING_NUM_LIGHTS; i++) { +- light_id = bitfieldExtract(GPUREG_LIGHTING_LIGHT_PERMUTATION, int(i) << 2, 3); ++ light_id = bitfieldExtractCompat(GPUREG_LIGHTING_LIGHT_PERMUTATION, int(i) << 2, 3); + + uint GPUREG_LIGHTi_SPECULAR0 = readPicaReg(0x0140u + (light_id << 4u)); + uint GPUREG_LIGHTi_SPECULAR1 = readPicaReg(0x0141u + (light_id << 4u)); +@@ -348,12 +355,12 @@ void calcLighting(out vec4 primary_color + + float light_distance; + vec3 light_position = vec3( +- decodeFP(bitfieldExtract(GPUREG_LIGHTi_VECTOR_LOW, 0, 16), 5u, 10u), decodeFP(bitfieldExtract(GPUREG_LIGHTi_VECTOR_LOW, 16, 16), 5u, 10u), +- decodeFP(bitfieldExtract(GPUREG_LIGHTi_VECTOR_HIGH, 0, 16), 5u, 10u) ++ decodeFP(bitfieldExtractCompat(GPUREG_LIGHTi_VECTOR_LOW, 0, 16), 5u, 10u), decodeFP(bitfieldExtractCompat(GPUREG_LIGHTi_VECTOR_LOW, 16, 16), 5u, 10u), ++ decodeFP(bitfieldExtractCompat(GPUREG_LIGHTi_VECTOR_HIGH, 0, 16), 5u, 10u) + ); + + // Positional Light +- if (bitfieldExtract(GPUREG_LIGHTi_CONFIG, 0, 1) == 0u) { ++ if (bitfieldExtractCompat(GPUREG_LIGHTi_CONFIG, 0, 1) == 0u) { + light_vector = light_position + v_view; + } + +@@ -369,23 +376,23 @@ void calcLighting(out vec4 primary_color + float NdotL = dot(normal, light_vector); // N dot Li + + // Two sided diffuse +- if (bitfieldExtract(GPUREG_LIGHTi_CONFIG, 1, 1) == 0u) ++ if (bitfieldExtractCompat(GPUREG_LIGHTi_CONFIG, 1, 1) == 0u) + NdotL = max(0.0, NdotL); + else + NdotL = abs(NdotL); + + float geometric_factor; +- bool use_geo_0 = bitfieldExtract(GPUREG_LIGHTi_CONFIG, 2, 1) == 1u; +- bool use_geo_1 = bitfieldExtract(GPUREG_LIGHTi_CONFIG, 3, 1) == 1u; ++ bool use_geo_0 = bitfieldExtractCompat(GPUREG_LIGHTi_CONFIG, 2, 1) == 1u; ++ bool use_geo_1 = bitfieldExtractCompat(GPUREG_LIGHTi_CONFIG, 3, 1) == 1u; + if (use_geo_0 || use_geo_1) { + geometric_factor = dot(half_vector, half_vector); + geometric_factor = geometric_factor == 0.0 ? 0.0 : min(NdotL / geometric_factor, 1.0); + } + + float distance_attenuation = 1.0; +- if (bitfieldExtract(GPUREG_LIGHTING_CONFIG1, 24 + int(light_id), 1) == 0u) { +- uint GPUREG_LIGHTi_ATTENUATION_BIAS = bitfieldExtract(readPicaReg(0x014Au + (light_id << 4u)), 0, 20); +- uint GPUREG_LIGHTi_ATTENUATION_SCALE = bitfieldExtract(readPicaReg(0x014Bu + (light_id << 4u)), 0, 20); ++ if (bitfieldExtractCompat(GPUREG_LIGHTING_CONFIG1, 24 + int(light_id), 1) == 0u) { ++ uint GPUREG_LIGHTi_ATTENUATION_BIAS = bitfieldExtractCompat(readPicaReg(0x014Au + (light_id << 4u)), 0, 20); ++ uint GPUREG_LIGHTi_ATTENUATION_SCALE = bitfieldExtractCompat(readPicaReg(0x014Bu + (light_id << 4u)), 0, 20); + + float distance_attenuation_bias = decodeFP(GPUREG_LIGHTi_ATTENUATION_BIAS, 7u, 12u); + float distance_attenuation_scale = decodeFP(GPUREG_LIGHTi_ATTENUATION_SCALE, 7u, 12u); +@@ -430,8 +437,8 @@ void calcLighting(out vec4 primary_color + specular_sum.rgb += light_factor * clamp_factor * (specular0 + specular1); + } + +- uint fresnel_output1 = bitfieldExtract(GPUREG_LIGHTING_CONFIG0, 2, 1); +- uint fresnel_output2 = bitfieldExtract(GPUREG_LIGHTING_CONFIG0, 3, 1); ++ uint fresnel_output1 = bitfieldExtractCompat(GPUREG_LIGHTING_CONFIG0, 2, 1); ++ uint fresnel_output2 = bitfieldExtractCompat(GPUREG_LIGHTING_CONFIG0, 3, 1); + // Uses parameters from the last light as Fresnel is only applied to the last light + float fresnel_factor; + +diff -rupbN panda3ds.orig/src/host_shaders/opengl_vertex_shader.vert panda3ds/src/host_shaders/opengl_vertex_shader.vert +--- panda3ds.orig/src/host_shaders/opengl_vertex_shader.vert 2024-08-28 21:01:16.674631846 +0000 ++++ panda3ds/src/host_shaders/opengl_vertex_shader.vert 2024-08-28 22:09:19.387098916 +0000 +@@ -1,4 +1,6 @@ +-#version 410 core ++#version 320 es ++precision mediump float; ++precision mediump int; + + layout(location = 0) in vec4 a_coords; + layout(location = 1) in vec4 a_quaternion; +@@ -18,7 +20,7 @@ out vec2 v_texcoord2; + flat out vec4 v_textureEnvColor[6]; + flat out vec4 v_textureEnvBufferColor; + +-out float gl_ClipDistance[2]; ++// out float gl_ClipDistance[2]; + + // TEV uniforms + uniform uint u_textureEnvColor[6]; +@@ -81,8 +83,8 @@ void main() { + ); + + // There's also another, always-on clipping plane based on vertex z +- gl_ClipDistance[0] = -a_coords.z; +- gl_ClipDistance[1] = dot(clipData, a_coords); ++ // gl_ClipDistance[0] = -a_coords.z; ++ // gl_ClipDistance[1] = dot(clipData, a_coords); + + v_quaternion = a_quaternion; + } +diff -rupbN panda3ds.orig/third_party/opengl/opengl.hpp panda3ds/third_party/opengl/opengl.hpp +--- panda3ds.orig/third_party/opengl/opengl.hpp 2024-08-28 21:01:16.706632561 +0000 ++++ panda3ds/third_party/opengl/opengl.hpp 2024-08-28 22:09:19.387098916 +0000 +@@ -602,22 +602,22 @@ namespace OpenGL { + static void disableScissor() { glDisable(GL_SCISSOR_TEST); } + static void enableBlend() { glEnable(GL_BLEND); } + static void disableBlend() { glDisable(GL_BLEND); } +- static void enableLogicOp() { glEnable(GL_COLOR_LOGIC_OP); } +- static void disableLogicOp() { glDisable(GL_COLOR_LOGIC_OP); } ++ static void enableLogicOp() { /* glEnable(GL_COLOR_LOGIC_OP); */ } ++ static void disableLogicOp() { /* glDisable(GL_COLOR_LOGIC_OP); */ } + static void enableDepth() { glEnable(GL_DEPTH_TEST); } + static void disableDepth() { glDisable(GL_DEPTH_TEST); } + static void enableStencil() { glEnable(GL_STENCIL_TEST); } + static void disableStencil() { glDisable(GL_STENCIL_TEST); } + +- static void enableClipPlane(GLuint index) { glEnable(GL_CLIP_DISTANCE0 + index); } +- static void disableClipPlane(GLuint index) { glDisable(GL_CLIP_DISTANCE0 + index); } ++ static void enableClipPlane(GLuint index) { /* glEnable(GL_CLIP_DISTANCE0 + index); */ } ++ static void disableClipPlane(GLuint index) { /* glDisable(GL_CLIP_DISTANCE0 + index); */ } + + static void setDepthFunc(DepthFunc func) { glDepthFunc(static_cast(func)); } + static void setColourMask(GLboolean r, GLboolean g, GLboolean b, GLboolean a) { glColorMask(r, g, b, a); } + static void setDepthMask(GLboolean mask) { glDepthMask(mask); } + + // TODO: Add a proper enum for this +- static void setLogicOp(GLenum op) { glLogicOp(op); } ++ static void setLogicOp(GLenum op) { /* glLogicOp(op); */ } + + enum Primitives { + Triangle = GL_TRIANGLES, diff --git a/projects/ArchR/packages/emulators/libretro/parallel-n64-lr/config/ParaLLEl N64.opt b/projects/ArchR/packages/emulators/libretro/parallel-n64-lr/config/ParaLLEl N64.opt new file mode 100644 index 0000000000..6b9c6179b2 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/parallel-n64-lr/config/ParaLLEl N64.opt @@ -0,0 +1,30 @@ +parallel-n64-64dd-hardware = "disabled" +parallel-n64-alt-map = "disabled" +parallel-n64-angrylion-multithread = "all threads" +parallel-n64-angrylion-overscan = "disabled" +parallel-n64-angrylion-sync = "Low" +parallel-n64-angrylion-vioverlay = "Filtered" +parallel-n64-aspectratiohint = "normal" +parallel-n64-astick-deadzone = "15" +parallel-n64-astick-sensitivity = "100" +parallel-n64-audio-buffer-size = "2048" +parallel-n64-boot-device = "Default" +parallel-n64-bufferswap = "disabled" +parallel-n64-cpucore = "dynamic_recompiler" +parallel-n64-disable_expmem = "enabled" +parallel-n64-dithering = "enabled" +parallel-n64-filtering = "automatic" +parallel-n64-framerate = "original" +parallel-n64-gfxplugin = "auto" +parallel-n64-gfxplugin-accuracy = "low" +parallel-n64-pak1 = "none" +parallel-n64-pak2 = "none" +parallel-n64-pak3 = "none" +parallel-n64-pak4 = "none" +parallel-n64-polyoffset-factor = "-3.0" +parallel-n64-polyoffset-units = "-3.0" +parallel-n64-rspplugin = "auto" +parallel-n64-screensize = "640x480" +parallel-n64-send_allist_to_hle_rsp = "disabled" +parallel-n64-vcache-vbo = "disabled" +parallel-n64-virefresh = "auto" diff --git a/projects/ArchR/packages/emulators/libretro/parallel-n64-lr/package.mk b/projects/ArchR/packages/emulators/libretro/parallel-n64-lr/package.mk new file mode 100644 index 0000000000..e9fc63cbde --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/parallel-n64-lr/package.mk @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="parallel-n64-lr" +PKG_VERSION="f8605345e13c018a30c8f4ed03c05d8fc8f70be8" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/parallel-n64" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain core-info" +PKG_LONGDESC="Optimized/rewritten Nintendo 64 emulator made specifically for Libretro. Originally based on Mupen64 Plus." +PKG_TOOLCHAIN="make" +PKG_BUILD_FLAGS="-lto" + +if [ "${OPENGL_SUPPORT}" = "yes" ] && [ ! "${PREFER_GLES}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL} glu libglvnd" + PKG_MAKE_OPTS_TARGET+=" GLES=0 GL_LIB=\"-lGL\"" +elif [ "${OPENGLES_SUPPORT}" = yes ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" + PKG_MAKE_OPTS_TARGET+=" GLES=1 GL_LIB=\"-lGLESv2\"" +fi + +pre_configure_target() { + if [ "${ARCH}" = "aarch64" ]; then + # This is only needed for armv8.2-a targets where we don't use this flag + # as it prohibits the use of LSE-instructions, this is a package bug most likely + export CFLAGS="${CFLAGS} -mno-outline-atomics -std=gnu17" + export CXXFLAGS="${CXXFLAGS} -mno-outline-atomics" + PKG_MAKE_OPTS_TARGET+=" platform=${DEVICE}" + fi +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp parallel_n64_libretro.so ${INSTALL}/usr/lib/libretro/ + + mkdir -p ${INSTALL}/usr/config/retroarch + cp -rf ${PKG_DIR}/config/* ${INSTALL}/usr/config/retroarch/ +} + diff --git a/projects/ArchR/packages/emulators/libretro/parallel-n64-lr/patches/001-gcc-13.patch b/projects/ArchR/packages/emulators/libretro/parallel-n64-lr/patches/001-gcc-13.patch new file mode 100644 index 0000000000..1e6045345f --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/parallel-n64-lr/patches/001-gcc-13.patch @@ -0,0 +1,32 @@ +diff --git a/mupen64plus-core/src/r4300/r4300.c b/mupen64plus-core/src/r4300/r4300.c +index 744198d6..73cb1f27 100644 +--- a/mupen64plus-core/src/r4300/r4300.c ++++ b/mupen64plus-core/src/r4300/r4300.c +@@ -50,8 +50,8 @@ + unsigned int r4300emu = 0; + unsigned int count_per_op = COUNT_PER_OP_DEFAULT; + unsigned int llbit; +-int stop; + #if NEW_DYNAREC < NEW_DYNAREC_ARM ++int stop; + int64_t reg[32], hi, lo; + uint32_t next_interrupt; + struct precomp_instr *PC; +diff --git a/mupen64plus-rsp-paraLLEl/rsp_disasm.cpp b/mupen64plus-rsp-paraLLEl/rsp_disasm.cpp +index 9b1f6eda..bbb84e74 100644 +--- a/mupen64plus-rsp-paraLLEl/rsp_disasm.cpp ++++ b/mupen64plus-rsp-paraLLEl/rsp_disasm.cpp +@@ -1,5 +1,6 @@ + #include "rsp_disasm.hpp" + #include ++#include + + namespace RSP + { +@@ -582,4 +583,4 @@ std::string disassemble(uint32_t pc, uint32_t instr) + + return "???"; + } +-} +\ No newline at end of file ++} diff --git a/projects/ArchR/packages/emulators/libretro/parallel-n64-lr/patches/002-rk3588-make.patch b/projects/ArchR/packages/emulators/libretro/parallel-n64-lr/patches/002-rk3588-make.patch new file mode 100644 index 0000000000..f459bac308 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/parallel-n64-lr/patches/002-rk3588-make.patch @@ -0,0 +1,27 @@ +diff --git a/Makefile b/Makefile +index 8a719d55..0872e619 100644 +--- a/Makefile ++++ b/Makefile +@@ -60,6 +60,8 @@ else ifneq (,$(findstring rpi,$(platform))) + override platform += unix + else ifneq (,$(findstring odroid,$(platform))) + override platform += unix ++else ifneq (,$(findstring @DEVICE@,$(platform))) ++ override platform += unix + endif + + # system platform +@@ -171,6 +173,13 @@ ifneq (,$(findstring unix,$(platform))) + + endif + ++ #@DEVICE@ ++ ifneq (,$(findstring @DEVICE@,$(platform))) ++ TARGET := $(TARGET_NAME)_libretro.so ++ CPUFLAGS += -DARM_FIX -DCLASSIC -DARM64 ++ WITH_DYNAREC = aarch64 ++ endif ++ + # ODROIDs + ifneq (,$(findstring odroid,$(platform))) + BOARD ?= $(shell cat /proc/cpuinfo | grep -i odroid | awk '{print $$3}') diff --git a/projects/ArchR/packages/emulators/libretro/parallel-n64-lr/patches/003-libretro-cleanup.patch b/projects/ArchR/packages/emulators/libretro/parallel-n64-lr/patches/003-libretro-cleanup.patch new file mode 100644 index 0000000000..f02b641b54 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/parallel-n64-lr/patches/003-libretro-cleanup.patch @@ -0,0 +1,56 @@ +diff --git a/libretro/libretro.c b/libretro/libretro.c +index 16525703..0922084c 100644 +--- a/libretro/libretro.c ++++ b/libretro/libretro.c +@@ -406,10 +406,10 @@ static void setup_variables(void) + "Send audio lists to HLE RSP; disabled|enabled" }, + { "parallel-n64-gfxplugin", + "GFX Plugin; auto" +-#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) + "|glide64|gln64|rice" +-#endif ++#ifdef HAVE_THR_AL + "|angrylion" ++#endif + #ifdef HAVE_PARALLEL + "|parallel" + #endif +@@ -424,26 +424,23 @@ static void setup_variables(void) + "|parallel" + #endif + }, +-#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) || defined(HAVE_PARALLEL) + { "parallel-n64-screensize", +-#ifdef CLASSIC +- "Resolution (restart); 320x240|640x480|960x720|1280x960|1440x1080|1600x1200|1920x1440|2240x1680|2880x2160|5760x4320" }, +-#else +- "Resolution (restart); 640x480|960x720|1280x960|1440x1080|1600x1200|1920x1440|2240x1680|2880x2160|5760x4320|320x240" }, +-#endif ++ "Resolution (restart); 320x240|640x480|960x720|1440x1080" }, + { "parallel-n64-aspectratiohint", + "Aspect ratio hint (reinit); normal|widescreen" }, + { "parallel-n64-filtering", + "(Glide64) Texture Filtering; automatic|N64 3-point|bilinear|nearest" }, ++#ifdef HAVE_THR_AL + { "parallel-n64-dithering", + "(Angrylion) Dithering; enabled|disabled" }, ++#endif + { "parallel-n64-polyoffset-factor", + "(Glide64) Polygon Offset Factor; -3.0|-2.5|-2.0|-1.5|-1.0|-0.5|0.0|0.5|1.0|1.5|2.0|2.5|3.0|3.5|4.0|4.5|5.0|-3.5|-4.0|-4.5|-5.0" + }, + { "parallel-n64-polyoffset-units", + "(Glide64) Polygon Offset Units; -3.0|-2.5|-2.0|-1.5|-1.0|-0.5|0.0|0.5|1.0|1.5|2.0|2.5|3.0|3.5|4.0|4.5|5.0|-3.5|-4.0|-4.5|-5.0" + }, +-#endif ++#ifdef HAVE_THR_AL + { "parallel-n64-angrylion-vioverlay", + "(Angrylion) VI Overlay; Filtered|AA+Blur|AA+Dedither|AA only|Unfiltered|Depth|Coverage" + }, +@@ -454,6 +451,7 @@ static void setup_variables(void) + "(Angrylion) Multi-threading; all threads|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49|50|51|52|53|54|55|56|57|58|59|60|61|62|63" }, + { "parallel-n64-angrylion-overscan", + "(Angrylion) Hide overscan; disabled|enabled" }, ++#endif + { "parallel-n64-virefresh", + "VI Refresh (Overclock); auto|1500|2200" }, + { "parallel-n64-bufferswap", diff --git a/projects/ArchR/packages/emulators/libretro/pcsx_rearmed-lr/package.mk b/projects/ArchR/packages/emulators/libretro/pcsx_rearmed-lr/package.mk new file mode 100644 index 0000000000..0ff8bdec57 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/pcsx_rearmed-lr/package.mk @@ -0,0 +1,46 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020 Trond Haugland (trondah@gmail.com) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="pcsx_rearmed-lr" +PKG_VERSION="228c14e10e9a8fae0ead8adf30daad2cdd8655b9" +PKG_ARCH="arm aarch64" +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_LONGDESC="ARM optimized PCSX fork" +PKG_TOOLCHAIN="manual" + +pre_configure_target() { + sed -i 's/\-O[23]/-Ofast/' ${PKG_BUILD}/Makefile + export CFLAGS="${CFLAGS} -flto -fipa-pta" + export CXXFLAGS="${CXXFLAGS} -flto -fipa-pta" + export LDFLAGS="${LDFLAGS} -flto -fipa-pta" +} + +make_target() { + cd ${PKG_BUILD} + make -f Makefile.libretro GIT_VERSION=${PKG_VERSION} platform=${DEVICE} +} + +makeinstall_target32() { + case ${ARCH} in + aarch64) + if [ "${ENABLE_32BIT}" == "true" ] + then + cp -vP ${ROOT}/build.${DISTRO}-${DEVICE}.arm/install_pkg/${PKG_NAME}-*/usr/lib/libretro/${1}_libretro.so ${INSTALL}/usr/lib/libretro/${1}32_libretro.so + fi + ;; + esac +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp pcsx_rearmed_libretro.so ${INSTALL}/usr/lib/libretro/ + case ${TARGET_ARCH} in + aarch64) + makeinstall_target32 pcsx_rearmed + ;; + esac +} diff --git a/projects/ArchR/packages/emulators/libretro/pcsx_rearmed-lr/patches/aarch64/pcsx_rearmed-add_platform.patch b/projects/ArchR/packages/emulators/libretro/pcsx_rearmed-lr/patches/aarch64/pcsx_rearmed-add_platform.patch new file mode 100644 index 0000000000..e14f8bcf3c --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/pcsx_rearmed-lr/patches/aarch64/pcsx_rearmed-add_platform.patch @@ -0,0 +1,19 @@ +diff -rupN pcsx_rearmed.orig/Makefile.libretro pcsx_rearmed/Makefile.libretro +--- pcsx_rearmed.orig/Makefile.libretro 2022-08-16 15:19:42.928678600 +0200 ++++ pcsx_rearmed/Makefile.libretro 2022-08-17 18:08:41.346728698 +0200 +@@ -385,6 +385,15 @@ else ifeq ($(platform), rpi4_64) + fpic := -fPIC + CFLAGS += -march=armv8-a+crc+simd -mtune=cortex-a72 -ftree-vectorize + ++else ifeq ($(platform), @DEVICE@) ++ TARGET := $(TARGET_NAME)_libretro.so ++ fpic := -fPIC ++ ARCH = arm64 ++ DYNAREC = ari64 ++ BUILTIN_GPU = neon ++ HAVE_NEON = 1 ++ CFLAGS += -ftree-vectorize ++ + # Classic Platforms #################### + # Platform affix = classic__<µARCH> + # Help at https://modmyclassic.com/comp diff --git a/projects/ArchR/packages/emulators/libretro/pcsx_rearmed-lr/patches/aarch64/pcsx_rearmed-patch-enable-threaded-rendering.patch b/projects/ArchR/packages/emulators/libretro/pcsx_rearmed-lr/patches/aarch64/pcsx_rearmed-patch-enable-threaded-rendering.patch new file mode 100644 index 0000000000..d69f1c880a --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/pcsx_rearmed-lr/patches/aarch64/pcsx_rearmed-patch-enable-threaded-rendering.patch @@ -0,0 +1,13 @@ +diff --git a/frontend/libretro_core_options.h b/frontend/libretro_core_options.h +index 3e1daf2..06702a1 100644 +--- a/frontend/libretro_core_options.h ++++ b/frontend/libretro_core_options.h +@@ -848,7 +848,7 @@ struct retro_core_option_definition option_defs_us[] = { + { "async", NULL }, + { NULL, NULL}, + }, +- "disabled", ++ "sync", + }, + #endif + diff --git a/projects/ArchR/packages/emulators/libretro/pcsx_rearmed-lr/patches/arm/pcsx_rearmed-add_platform.patch b/projects/ArchR/packages/emulators/libretro/pcsx_rearmed-lr/patches/arm/pcsx_rearmed-add_platform.patch new file mode 100644 index 0000000000..524aca8bab --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/pcsx_rearmed-lr/patches/arm/pcsx_rearmed-add_platform.patch @@ -0,0 +1,20 @@ +diff -rupN pcsx_rearmed.orig/Makefile.libretro pcsx_rearmed/Makefile.libretro +--- pcsx_rearmed.orig/Makefile.libretro 2022-08-16 15:19:42.928678600 +0200 ++++ pcsx_rearmed/Makefile.libretro 2022-08-17 17:51:57.256712172 +0200 +@@ -385,6 +385,16 @@ else ifeq ($(platform), rpi4_64) + fpic := -fPIC + CFLAGS += -march=armv8-a+crc+simd -mtune=cortex-a72 -ftree-vectorize + ++else ifeq ($(platform), @DEVICE@) ++ TARGET := $(TARGET_NAME)_libretro.so ++ fpic := -fPIC ++ CFLAGS += -marm ++ HAVE_NEON = 1 ++ HAVE_NEON_ASM = 1 ++ ARCH = arm ++ BUILTIN_GPU = neon ++ DYNAREC = ari64 ++ + # Classic Platforms #################### + # Platform affix = classic__<µARCH> + # Help at https://modmyclassic.com/comp diff --git a/projects/ArchR/packages/emulators/libretro/pcsx_rearmed-lr/patches/arm/pcsx_rearmed-patch-enable-threaded-rendering.patch b/projects/ArchR/packages/emulators/libretro/pcsx_rearmed-lr/patches/arm/pcsx_rearmed-patch-enable-threaded-rendering.patch new file mode 100644 index 0000000000..d69f1c880a --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/pcsx_rearmed-lr/patches/arm/pcsx_rearmed-patch-enable-threaded-rendering.patch @@ -0,0 +1,13 @@ +diff --git a/frontend/libretro_core_options.h b/frontend/libretro_core_options.h +index 3e1daf2..06702a1 100644 +--- a/frontend/libretro_core_options.h ++++ b/frontend/libretro_core_options.h +@@ -848,7 +848,7 @@ struct retro_core_option_definition option_defs_us[] = { + { "async", NULL }, + { NULL, NULL}, + }, +- "disabled", ++ "sync", + }, + #endif + diff --git a/projects/ArchR/packages/emulators/libretro/picodrive-lr/package.mk b/projects/ArchR/packages/emulators/libretro/picodrive-lr/package.mk new file mode 100644 index 0000000000..f96f3a1f9b --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/picodrive-lr/package.mk @@ -0,0 +1,31 @@ +PKG_NAME="picodrive-lr" +PKG_VERSION="c4332d608c1005a46ce51236ade9894e0d32e52b" +PKG_LICENSE="MAME" +PKG_SITE="https://github.com/libretro/picodrive" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Libretro implementation of PicoDrive. (Sega Megadrive/Genesis/Sega Master System/Sega GameGear/Sega CD/32X)" +GET_HANDLER_SUPPORT="git" +PKG_BUILD_FLAGS="-gold" +PKG_TOOLCHAIN="make" + +PKG_PATCH_DIRS="${PROJECT}" + +pre_configure_target() { +export CFLAGS="${CFLAGS} -Wno-error=incompatible-pointer-types" +} + +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/projects/ArchR/packages/emulators/libretro/play-lr/package.mk b/projects/ArchR/packages/emulators/libretro/play-lr/package.mk new file mode 100644 index 0000000000..11d90b151e --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/play-lr/package.mk @@ -0,0 +1,43 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="play-lr" +PKG_VERSION="b3be9d4840ab947448aedf2228496510257726ac" +PKG_LICENSE="BSDv2" +PKG_SITE="https://github.com/jpd002/Play-" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain libevdev zstd" +PKG_LONGDESC="Play! is an attempt to create a PlayStation 2 emulator for Windows, macOS, UNIX, Android & iOS platforms." +PKG_TOOLCHAIN="cmake" + +if [ "${OPENGL_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL} glu" +fi + +if [ "${OPENGLES_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" +fi + +case ${TARGET_ARCH} in + aarch64) + PKG_CMAKE_OPTS_TARGET+=" -DUSE_GLEW=off \ + -DUSE_GLES=on + -DTARGET_PLATFORM_UNIX_AARCH64=yes" + ;; +esac + +PKG_CMAKE_OPTS_TARGET+=" -DBUILD_LIBRETRO_CORE=yes \ + -DBUILD_PLAY=off \ + -DBUILD_TESTS=no \ + -DENABLE_AMAZON_S3=no \ + -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}/Source/ui_libretro/play_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/play-lr/patches/000-fix-build.patch b/projects/ArchR/packages/emulators/libretro/play-lr/patches/000-fix-build.patch new file mode 100644 index 0000000000..b51e897223 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/play-lr/patches/000-fix-build.patch @@ -0,0 +1,13 @@ +diff --git a/Source/ui_libretro/CMakeLists.txt b/Source/ui_libretro/CMakeLists.txt +index cc195c1a..cf1acb44 100644 +--- a/Source/ui_libretro/CMakeLists.txt ++++ b/Source/ui_libretro/CMakeLists.txt +@@ -50,7 +50,7 @@ elseif(TARGET_PLATFORM_IOS) + list(APPEND PROJECT_LIBS "-ObjC -lsqlite3 -framework OpenGLES") + elseif(TARGET_PLATFORM_UNIX) + list(APPEND PROJECT_LIBS "-static-libgcc") +- list(APPEND PROJECT_LIBS "-static-libstdc++") ++# list(APPEND PROJECT_LIBS "-static-libstdc++") + endif() + + if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 8 AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9) diff --git a/projects/ArchR/packages/emulators/libretro/pokemini-lr/package.mk b/projects/ArchR/packages/emulators/libretro/pokemini-lr/package.mk new file mode 100644 index 0000000000..b17c8cf38a --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/pokemini-lr/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="pokemini-lr" +PKG_VERSION="19095803f1434eb980db6e4004187a4b786e20b6" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/libretro/pokemini" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Obscure nintendo AMD64 emulator (functional,no color files or savestates currently)" + +PKG_TOOLCHAIN="make" +PKG_PATCH_DIRS+="${DEVICE}" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp pokemini_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/potator-lr/package.mk b/projects/ArchR/packages/emulators/libretro/potator-lr/package.mk new file mode 100644 index 0000000000..be78651482 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/potator-lr/package.mk @@ -0,0 +1,18 @@ +PKG_NAME="potator-lr" +PKG_VERSION="ad87bc6068ef126e48339b440465fb0bf5a2794f" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/potator" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +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/projects/ArchR/packages/emulators/libretro/ppsspp-lr/package.mk b/projects/ArchR/packages/emulators/libretro/ppsspp-lr/package.mk new file mode 100644 index 0000000000..20a84452d1 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/ppsspp-lr/package.mk @@ -0,0 +1,108 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) +# +# 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-lr" +PKG_VERSION="afbc66a318b86432642b532c575241f3716642ef" # v1.20.2 +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/hrydgard/ppsspp" +PKG_URL="https://github.com/hrydgard/ppsspp.git" +PKG_DEPENDS_TARGET="toolchain SDL2 libzip zstd" +PKG_LONGDESC="A PSP emulator for Android, Windows, Mac, Linux and Blackberry 10, written in C++." +GET_HANDLER_SUPPORT="git" + + +pre_configure_target() { + PKG_LIBNAME="ppsspp_libretro.so" + PKG_LIBPATH="lib/${PKG_LIBNAME}" + + + if [ ! "${OPENGL}" = "no" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL} glu libglvnd glew glslang" + PKG_CMAKE_OPTS_TARGET+=" -DUSING_FBDEV=OFF \ + -DUSING_GLES2=OFF" + fi + + if [ "${OPENGLES_SUPPORT}" = yes ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" + PKG_CMAKE_OPTS_TARGET+=" -DUSING_FBDEV=ON \ + -DUSING_EGL=OFF \ + -DUSING_GLES2=ON \ + -DVULKAN=OFF \ + -DUSE_VULKAN_DISPLAY_KHR=OFF\ + -DUSING_X11_VULKAN=OFF" + fi + + if [ "${VULKAN_SUPPORT}" = "yes" ] + then + PKG_DEPENDS_TARGET+=" ${VULKAN}" + PKG_CMAKE_OPTS_TARGET+=" -DUSE_VULKAN_DISPLAY_KHR=ON \ + -DVULKAN=ON \ + -DEGL_NO_X11=1 \ + -DMESA_EGL_NO_X11_HEADERS=1" + else + PKG_CMAKE_OPTS_TARGET+=" -DVULKAN=OFF" + fi + + if [ "${DISPLAYSERVER}" = "wl" ]; then + PKG_DEPENDS_TARGET+=" wayland ${WINDOWMANAGER}" + PKG_CMAKE_OPTS_TARGET+=" -DUSE_WAYLAND_WSI=ON" + else + PKG_CMAKE_OPTS_TARGET+=" -DUSE_WAYLAND_WSI=OFF" + fi + + case ${TARGET_ARCH} in + aarch64) + PKG_CMAKE_OPTS_TARGET+=" -DFORCED_CPU=aarch64" + ;; + esac + + PKG_CMAKE_OPTS_TARGET+=" -DUSE_SYSTEM_FFMPEG=OFF \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_SYSTEM_NAME=Linux \ + -DBUILD_SHARED_LIBS=OFF \ + -DANDROID=OFF \ + -DWIN32=OFF \ + -DAPPLE=OFF \ + -DLIBRETRO=ON \ + -DCMAKE_CROSSCOMPILING=ON \ + -DUSING_QT_UI=OFF \ + -DUNITTEST=OFF \ + -DSIMULATOR=OFF \ + -DHEADLESS=OFF \ + -DUSE_DISCORD=OFF" +} + +pre_make_target() { + # This script should work on any board that has issues with system ffmpeg in ppsspp + if [ "${TARGET_ARCH}" = "aarch64" ]; then + sed -i "s|aarch64-linux-gnu-|${TARGET_PREFIX}|g" ${PKG_BUILD}/ffmpeg/linux_arm64.sh + (cd ${PKG_BUILD}/ffmpeg && ./linux_arm64.sh) + fi + + # 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/projects/ArchR/packages/emulators/libretro/ppsspp-lr/patches/000-armv8-build-fix.patch b/projects/ArchR/packages/emulators/libretro/ppsspp-lr/patches/000-armv8-build-fix.patch new file mode 100644 index 0000000000..f59ce50a92 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/ppsspp-lr/patches/000-armv8-build-fix.patch @@ -0,0 +1,33 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 90cd57ace..2ace6b70a 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -58,6 +58,10 @@ if(CMAKE_SYSTEM_PROCESSOR) + set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -target armv7a-none-linux-android") + endif() + endif() ++ if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "^armv8") ++ add_compile_options(-march=armv8-a+crc -mtune=cortex-a53 -mfloat-abi=hard -mfpu=neon-fp-armv8 -fomit-frame-pointer) ++ add_definitions(-DPPSSPP_ARCH_ARM_NEON=1 -DPPSSPP_ARCH_ARMV8=1) ++ endif() + elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "^amd64" OR ${CMAKE_SYSTEM_PROCESSOR} MATCHES "^x86_64" OR ${CMAKE_SYSTEM_PROCESSOR} MATCHES "^AMD64") + set(X86_DEVICE ON) + set(X86_64_DEVICE ON) +diff --git a/Common/ArmCPUDetect.cpp b/Common/ArmCPUDetect.cpp +index 437bd3158..d46cf19db 100644 +--- a/Common/ArmCPUDetect.cpp ++++ b/Common/ArmCPUDetect.cpp +@@ -337,6 +337,13 @@ void CPUInfo::Detect() + bNEON = true; + bASIMD = true; + #endif ++ ++#if PPSSPP_ARCH(ARMV8) ++ bNEON = true; ++ bASIMD = true; ++ bFP = true; ++#endif ++ + } + + // Turn the cpu info into a string we can show diff --git a/projects/ArchR/packages/emulators/libretro/ppsspp-lr/patches/001-x86_64-build-fix.patch b/projects/ArchR/packages/emulators/libretro/ppsspp-lr/patches/001-x86_64-build-fix.patch new file mode 100644 index 0000000000..e4aec51bab --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/ppsspp-lr/patches/001-x86_64-build-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/projects/ArchR/packages/emulators/libretro/ppsspp-lr/patches/002-psp-path.patch b/projects/ArchR/packages/emulators/libretro/ppsspp-lr/patches/002-psp-path.patch new file mode 100644 index 0000000000..e874b35d84 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/ppsspp-lr/patches/002-psp-path.patch @@ -0,0 +1,17 @@ +diff --git a/Core/Util/PathUtil.cpp b/Core/Util/PathUtil.cpp +--- a/Core/Util/PathUtil.cpp ++++ b/Core/Util/PathUtil.cpp +@@ -45,12 +45,7 @@ + Path GetSysDirectory(PSPDirectories directoryType) { + const Path &memStickDirectory = g_Config.memStickDirectory; + Path pspDirectory; +- if (!strcasecmp(memStickDirectory.GetFilename().c_str(), "PSP")) { +- // Let's strip this off, to easily allow choosing a root directory named "PSP" on Android. +- pspDirectory = memStickDirectory; +- } else { +- pspDirectory = memStickDirectory / "PSP"; +- } ++ pspDirectory = memStickDirectory / "PSP"; + + switch (directoryType) { + case DIRECTORY_PSP: diff --git a/projects/ArchR/packages/emulators/libretro/ppsspp-lr/patches/004-build-flags.patch b/projects/ArchR/packages/emulators/libretro/ppsspp-lr/patches/004-build-flags.patch new file mode 100644 index 0000000000..5d404f39dc --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/ppsspp-lr/patches/004-build-flags.patch @@ -0,0 +1,10 @@ +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -413,6 +413,7 @@ + # NEON optimizations in libpng17 seem to cause PNG load errors, see #14485. + add_compile_definitions(PNG_ARM_NEON_OPT=0) + ++ add_compile_options(-Ofast -fno-tree-slp-vectorize) + add_compile_options(-Wall -Werror=return-type -Wno-unused-function -Wno-sign-compare -Wno-unused-but-set-variable "$<$:-Wno-reorder>" -Wno-unknown-pragmas -Wno-unused-value -Wno-unused-variable -Wno-error=incompatible-pointer-types) + if(NOT CLANG) + # This one is very useful but has many false positives. diff --git a/projects/ArchR/packages/emulators/libretro/ppsspp-lr/patches/005-fix-atomics-arm64.patch b/projects/ArchR/packages/emulators/libretro/ppsspp-lr/patches/005-fix-atomics-arm64.patch new file mode 100644 index 0000000000..47aa78410c --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/ppsspp-lr/patches/005-fix-atomics-arm64.patch @@ -0,0 +1,10 @@ +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -414,6 +414,7 @@ + add_compile_definitions(PNG_ARM_NEON_OPT=0) + + add_compile_options(-Ofast -fno-tree-slp-vectorize) ++ add_compile_options(-mno-outline-atomics) + add_compile_options(-Wall -Werror=return-type -Wno-unused-function -Wno-sign-compare -Wno-unused-but-set-variable "$<$:-Wno-reorder>" -Wno-unknown-pragmas -Wno-unused-value -Wno-unused-variable -Wno-error=incompatible-pointer-types) + if(NOT CLANG) + # This one is very useful but has many false positives. diff --git a/projects/ArchR/packages/emulators/libretro/ppsspp-lr/patches/006-fix-ffmpeg-atomics.patch b/projects/ArchR/packages/emulators/libretro/ppsspp-lr/patches/006-fix-ffmpeg-atomics.patch new file mode 100644 index 0000000000..e5577de6e2 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/ppsspp-lr/patches/006-fix-ffmpeg-atomics.patch @@ -0,0 +1,11 @@ +--- a/ffmpeg/linux_arm64.sh ++++ b/ffmpeg/linux_arm64.sh +@@ -86,7 +86,7 @@ + ./configure --target-os=linux \ + --prefix=./linux/aarch64 \ + ${GENERAL} \ +- --extra-cflags=" -O3 -fasm -Wno-psabi -fno-short-enums -fno-strict-aliasing -finline-limit=300 " \ ++ --extra-cflags=" -O3 -fasm -Wno-psabi -mno-outline-atomics -fno-short-enums -fno-strict-aliasing -finline-limit=300 " \ + --disable-shared \ + --enable-static \ + --enable-zlib \ diff --git a/projects/ArchR/packages/emulators/libretro/ppsspp-lr/patches/007-fix-vulkan-on-libmali.patch b/projects/ArchR/packages/emulators/libretro/ppsspp-lr/patches/007-fix-vulkan-on-libmali.patch new file mode 100644 index 0000000000..9f5ab2b0c0 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/ppsspp-lr/patches/007-fix-vulkan-on-libmali.patch @@ -0,0 +1,45 @@ +--- a/libretro/libretro_vulkan.cpp ++++ b/libretro/libretro_vulkan.cpp +@@ -109,27 +109,34 @@ static VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice_libretro(VkPhysicalDevice p + newInfo.enabledExtensionCount = (uint32_t)enabledExtensionNames.size(); + newInfo.ppEnabledExtensionNames = newInfo.enabledExtensionCount ? enabledExtensionNames.data() : nullptr; + +- // Then check for VkPhysicalDeviceFeatures2 chaining or pEnabledFeatures to enable required features. Note that when both +- // structs are present Features2 takes precedence. vkCreateDevice parameters don't give us a simple way to detect +- // VK_KHR_get_physical_device_properties2 usage so we'll always try both paths. ++ // Check for VkPhysicalDeviceFeatures2 in pNext chain. Per Vulkan spec, pEnabledFeatures ++ // must be NULL when VkPhysicalDeviceFeatures2 is present in pNext. + std::unordered_map originalFeaturePointers; + VkPhysicalDeviceFeatures placeholderEnabledFeatures{}; ++ bool hasFeatures2InChain = false; + + for (const VkBaseOutStructure *next = (const VkBaseOutStructure *)pCreateInfo->pNext; next != nullptr;) { + if (next->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2) { + VkPhysicalDeviceFeatures *enabledFeatures = &((VkPhysicalDeviceFeatures2 *)next)->features; + originalFeaturePointers.try_emplace(enabledFeatures, *enabledFeatures); ++ hasFeatures2InChain = true; + } + + next = (const VkBaseOutStructure *)next->pNext; + } + +- if (newInfo.pEnabledFeatures) { +- placeholderEnabledFeatures = *newInfo.pEnabledFeatures; +- } ++ if (!hasFeatures2InChain) { ++ // Only use pEnabledFeatures when VkPhysicalDeviceFeatures2 is NOT in pNext chain. ++ if (newInfo.pEnabledFeatures) { ++ placeholderEnabledFeatures = *newInfo.pEnabledFeatures; ++ } + +- newInfo.pEnabledFeatures = &placeholderEnabledFeatures; +- originalFeaturePointers.try_emplace((VkPhysicalDeviceFeatures *)newInfo.pEnabledFeatures, *newInfo.pEnabledFeatures); ++ newInfo.pEnabledFeatures = &placeholderEnabledFeatures; ++ originalFeaturePointers.try_emplace((VkPhysicalDeviceFeatures *)newInfo.pEnabledFeatures, *newInfo.pEnabledFeatures); ++ } else { ++ // Ensure pEnabledFeatures is NULL when features2 is used (Vulkan spec requirement). ++ newInfo.pEnabledFeatures = nullptr; ++ } + + for (const auto& pair : originalFeaturePointers) { + for (uint32_t i = 0; i < sizeof(VkPhysicalDeviceFeatures) / sizeof(VkBool32); i++) { diff --git a/projects/ArchR/packages/emulators/libretro/prboom-lr/package.mk b/projects/ArchR/packages/emulators/libretro/prboom-lr/package.mk new file mode 100644 index 0000000000..ae22be85cc --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/prboom-lr/package.mk @@ -0,0 +1,32 @@ +################################################################################ +# 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-lr" +PKG_VERSION="9d412db570d3291829b308e6d1ac17f04acdda17" +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_LONGDESC="libretro implementation of Doom" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp prboom_libretro.so ${INSTALL}/usr/lib/libretro/prboom_libretro.so +} diff --git a/projects/ArchR/packages/emulators/libretro/prosystem-lr/package.mk b/projects/ArchR/packages/emulators/libretro/prosystem-lr/package.mk new file mode 100644 index 0000000000..6dea030719 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/prosystem-lr/package.mk @@ -0,0 +1,34 @@ +################################################################################ +# 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-lr" +PKG_VERSION="acae250da8d98b8b9707cd499e2a0bf6d8500652" +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_LONGDESC="Port of ProSystem to libretro." + +PKG_TOOLCHAIN="make" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp prosystem_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/puae-lr/package.mk b/projects/ArchR/packages/emulators/libretro/puae-lr/package.mk new file mode 100644 index 0000000000..3c9f9d8f7f --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/puae-lr/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) +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) +# +# 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-lr" +PKG_VERSION="0043cf9c061bd9b81dbc1869c2761017139cfc63" +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_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/projects/ArchR/packages/emulators/libretro/puae2021-lr/package.mk b/projects/ArchR/packages/emulators/libretro/puae2021-lr/package.mk new file mode 100644 index 0000000000..1882554baa --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/puae2021-lr/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) +# Copyright (C) 2023-present Ilmenit +# +# 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="puae2021-lr" +PKG_VERSION="87cbcb27809c2800418bf81da21a766de28029a0" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/libretro/libretro-uae" +PKG_URL="${PKG_SITE}.git" +PKG_GIT_CLONE_BRANCH="2.6.1" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="PUAE 2021 libretro port of UAE" +PKG_TOOLCHAIN="make" + +pre_configure_target() { + if [ "${ARCH}" == "arm" ]; then + CFLAGS="${CFLAGS} -DARM -marm" + fi +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp puae2021_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/px68k-lr/package.mk b/projects/ArchR/packages/emulators/libretro/px68k-lr/package.mk new file mode 100644 index 0000000000..b57f2ff7d6 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/px68k-lr/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="px68k-lr" +PKG_VERSION="9dfa6abc25ddd6e597790f7a535cd0a1d7f9c385" +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_LONGDESC="Portable SHARP X68000 Emulator for PSP, Android and other platforms" +PKG_PATCH_DIRS+="${DEVICE}" + +PKG_TOOLCHAIN="make" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp px68k_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/quasi88-lr/package.mk b/projects/ArchR/packages/emulators/libretro/quasi88-lr/package.mk new file mode 100644 index 0000000000..0093af8787 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/quasi88-lr/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present asakous (https://github.com/asakous) + +PKG_NAME="quasi88-lr" +PKG_VERSION="42be798db5585f62b4bd34ce49dd1e8063c9d7c1" +PKG_LICENSE="BSD3" +PKG_SITE="https://github.com/libretro/quasi88-libretro" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain" +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" + +pre_configure_target() { + CFLAGS="${CFLAGS} -std=gnu17" +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp quasi88_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/quicknes-lr/package.mk b/projects/ArchR/packages/emulators/libretro/quicknes-lr/package.mk new file mode 100644 index 0000000000..283f555044 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/quicknes-lr/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="quicknes-lr" +PKG_VERSION="dbf19f73e3eb9701d1c7f5898f57c097e05c9fbd" +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_LONGDESC="The QuickNES core library, originally by Shay Green, heavily modified" +PKG_BUILD_FLAGS="-gold" + +PKG_TOOLCHAIN="make" + +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/projects/ArchR/packages/emulators/libretro/race-lr/package.mk b/projects/ArchR/packages/emulators/libretro/race-lr/package.mk new file mode 100644 index 0000000000..141a5fa8a7 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/race-lr/package.mk @@ -0,0 +1,34 @@ +################################################################################ +# 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-lr" +PKG_VERSION="171950ea64c96ead503340ed60fa7ba18f56325c" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/RACE" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="This is the RACE NGPC emulator modified by theelf to run on the PSP." +PKG_TOOLCHAIN="make" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp race_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/autostart/003-logging b/projects/ArchR/packages/emulators/libretro/retroarch/autostart/003-logging new file mode 100755 index 0000000000..cfa5b7e723 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/autostart/003-logging @@ -0,0 +1,20 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +tocon "Configuring logging..." + +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/projects/ArchR/packages/emulators/libretro/retroarch/modprobe.d/usbhid.conf b/projects/ArchR/packages/emulators/libretro/retroarch/modprobe.d/usbhid.conf new file mode 100644 index 0000000000..a93b4222fe --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/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/projects/ArchR/packages/emulators/libretro/retroarch/package.mk b/projects/ArchR/packages/emulators/libretro/retroarch/package.mk new file mode 100644 index 0000000000..4b18fb3690 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/package.mk @@ -0,0 +1,186 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present 351ELEC (https://github.com/351ELEC) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="retroarch" +PKG_VERSION="fae7468de15b32a0e105e45325e5ca85e62ea7d4" # v1.22.2 + fixes +PKG_SITE="https://github.com/libretro/RetroArch" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_LICENSE="GPLv3" +PKG_DEPENDS_TARGET="toolchain SDL2 alsa-lib libass openssl freetype zlib retroarch-assets core-info ffmpeg libass joyutils nss-mdns openal-soft libogg libvorbisidec libvorbis libvpx libpng libdrm pulseaudio miniupnpc flac xz" +PKG_LONGDESC="Reference frontend for the libretro API." +PKG_BUILD_FLAGS="+speed +lto" + +if [ "${PIPEWIRE_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" pipewire" +fi + +case ${ARCH} in + arm) + true + ;; + *) + PKG_DEPENDS_TARGET+=" empty" + ;; +esac + +PKG_PATCH_DIRS+=" ${DEVICE}" + +PKG_CONFIGURE_OPTS_TARGET=" --disable-qt \ + --enable-alsa \ + --enable-udev \ + --disable-opengl1 \ + --disable-x11 \ + --enable-zlib \ + --enable-freetype \ + --disable-discord \ + --disable-vg \ + --disable-sdl \ + --enable-sdl2 \ + --enable-kms \ + --enable-ffmpeg" + +case ${ARCH} in + arm) + PKG_CONFIGURE_OPTS_TARGET+=" --enable-neon" + ;; + aarch64) + PKG_CONFIGURE_OPTS_TARGET+=" --disable-neon" + ;; +esac + +case ${DEVICE} in + RK*) + PKG_DEPENDS_TARGET+=" librga" + ;; +esac + +if [ "${DISPLAYSERVER}" = "wl" ]; then + PKG_DEPENDS_TARGET+=" wayland wayland-protocols wayland:host" + PKG_CONFIGURE_OPTS_TARGET+=" --enable-wayland" + case ${ARCH} in + arm) + true + ;; + *) + PKG_DEPENDS_TARGET+=" ${WINDOWMANAGER}" + ;; + esac +else + PKG_CONFIGURE_OPTS_TARGET+=" --disable-wayland" +fi + +if [ "${OPENGLES_SUPPORT}" = "yes" ] && \ + [ "${PREFER_GLES}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" + # --enable-opengles3 required for glcore, --enable-opengles3_1 doesn't auto-select it + PKG_CONFIGURE_OPTS_TARGET+=" --enable-opengles --enable-opengles3 --enable-opengles3_1" + PKG_CONFIGURE_OPTS_TARGET+=" --disable-opengl" +else + # Full OpenGL + PKG_DEPENDS_TARGET+=" ${OPENGL} glu libglvnd" + PKG_CONFIGURE_OPTS_TARGET+=" --enable-opengl" + PKG_CONFIGURE_OPTS_TARGET+=" --disable-opengles --disable-opengles3 --disable-opengles3_1 --disable-opengles3_2" +fi + +if [ "${VULKAN_SUPPORT}" = "yes" ] +then + PKG_DEPENDS_TARGET+=" ${VULKAN}" + PKG_CONFIGURE_OPTS_TARGET+=" --enable-vulkan --enable-vulkan_display" +else + PKG_CONFIGURE_OPTS_TARGET+=" --disable-vulkan" +fi + +pre_configure_target() { + CFLAGS+=" -DUDEV_TOUCH_SUPPORT -I${SYSROOT_PREFIX}/usr/include/spa-0.2 -I${SYSROOT_PREFIX}/usr/include/pipewire-0.3" + CXXFLAGS+=" -DUDEV_TOUCH_SUPPORT -I${SYSROOT_PREFIX}/usr/include/spa-0.2 -I${SYSROOT_PREFIX}/usr/include/pipewire-0.3" + TARGET_CONFIGURE_OPTS="" + + # Tell retroarch configure this is a cross-compilation + # Without this, qb/config.libs.sh adds -L/usr/lib64 from the host + export CROSS_COMPILE="${TARGET_PREFIX}" + + # Fix retroarch qb cross-compilation: patch config.libs.sh to use sysroot paths + if [ -n "${SYSROOT_PREFIX}" ]; then + sed -i "s|INCLUDES='usr/include usr/local/include'|INCLUDES='${SYSROOT_PREFIX}/usr/include ${SYSROOT_PREFIX}/usr/local/include'|" ${PKG_BUILD}/qb/config.libs.sh + fi + + # Ensure retroarch configure finds pkg-config (it looks for ${CROSS_COMPILE}pkg-config which doesn't exist) + export PKG_CONF_PATH="${TOOLCHAIN}/bin/pkg-config" + # Ensure pkg-config finds wayland-protocols in share/pkgconfig and wayland-scanner in toolchain + export PKG_CONFIG_PATH="${SYSROOT_PREFIX}/usr/lib/pkgconfig:${SYSROOT_PREFIX}/usr/share/pkgconfig:${TOOLCHAIN}/lib/pkgconfig:${TOOLCHAIN}/share/pkgconfig" + + # Disable pipewire for arm 32-bit compat (headers not in arm sysroot) + if [ "${TARGET_ARCH}" = "arm" ]; then + PKG_CONFIGURE_OPTS_TARGET+=" --disable-pipewire" + fi + + cd ${PKG_BUILD} +} + +make_target() { + make HAVE_UPDATE_ASSETS=0 HAVE_LIBRETRODB=1 HAVE_BLUETOOTH=0 HAVE_NETWORKING=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() { + mkdir -p ${INSTALL}/usr/bin + cp ${PKG_BUILD}/retroarch ${INSTALL}/usr/bin + mkdir -p ${INSTALL}/usr/share/retroarch/filters + + case ${ARCH} in + aarch64) + if [ -f ${ROOT}/build.${DISTRO}-${DEVICE}.arm/install_pkg/retroarch-*/usr/bin/retroarch ]; then + cp -vP ${ROOT}/build.${DISTRO}-${DEVICE}.arm/install_pkg/retroarch-*/usr/bin/retroarch ${INSTALL}/usr/bin/retroarch32 + mkdir -p ${INSTALL}/usr/share/retroarch/filters/32bit/ + cp -rvP ${ROOT}/build.${DISTRO}-${DEVICE}.arm/install_pkg/retroarch-*/usr/share/retroarch/filters/64bit/* ${INSTALL}/usr/share/retroarch/filters/32bit/ + fi + ;; + esac + + 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/ + if [ -d "${PKG_DIR}/sources/${DEVICE}" ]; then + cp -rf ${PKG_DIR}/sources/${DEVICE}/* ${INSTALL}/usr/config/retroarch/ + else + echo "Configure retroarch for ${DEVICE}" + exit 1 + fi + + # Make sure the shader directories exist for overlayfs. + for dir in common-shaders glsl-shaders slang-shaders + do + mkdir -p ${INSTALL}/usr/share/${dir} + touch ${INSTALL}/usr/share/${dir}/.overlay + done + + # Copy achievment sounds + mkdir -p ${INSTALL}/usr/share/libretro + cp -R ${PKG_DIR}/sounds ${INSTALL}/usr/share/libretro + + # Copy achievements hooks script + cp ${PKG_DIR}/scripts/call_achievements_hooks.sh ${INSTALL}/usr/share/libretro +} + +post_install() { + enable_service tmp-cores.mount + enable_service tmp-database.mount + enable_service tmp-assets.mount + enable_service tmp-shaders.mount + enable_service tmp-overlays.mount +} diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/patches/0001-Increase-glui-size.patch b/projects/ArchR/packages/emulators/libretro/retroarch/patches/0001-Increase-glui-size.patch new file mode 100644 index 0000000000..d62d7d4465 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/patches/0001-Increase-glui-size.patch @@ -0,0 +1,22 @@ +diff --git a/menu/drivers/materialui.c b/menu/drivers/materialui.c +index d3ae5ec997..5ff5405b2a 100644 +--- a/menu/drivers/materialui.c ++++ b/menu/drivers/materialui.c +@@ -3591,7 +3591,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) +@@ -8133,7 +8133,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; + mui->flags = 0; diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/patches/0001-Increase-ozone-size.patch b/projects/ArchR/packages/emulators/libretro/retroarch/patches/0001-Increase-ozone-size.patch new file mode 100644 index 0000000000..cc13c3f934 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/patches/0001-Increase-ozone-size.patch @@ -0,0 +1,22 @@ +diff --git a/menu/drivers/ozone.c b/menu/drivers/ozone.c +index 23a2d13245..45db0d5bf8 100644 +--- a/menu/drivers/ozone.c ++++ b/menu/drivers/ozone.c +@@ -9103,7 +9103,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; + ozone->last_thumbnail_scale_factor = settings->floats.ozone_thumbnail_scale_factor; + + ozone->selection_buf_old.list = NULL; +@@ -10256,7 +10256,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; + thumbnail_scale_factor = settings->floats.ozone_thumbnail_scale_factor; + padding_factor = settings->floats.ozone_padding_factor; + font_scale_factor_global = (font_scale == 1) ? (settings->floats.ozone_font_scale_factor_global) : 1.0f; diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/patches/0001-Increase-ozone-widget_size.patch b/projects/ArchR/packages/emulators/libretro/retroarch/patches/0001-Increase-ozone-widget_size.patch new file mode 100644 index 0000000000..3dd774b0ba --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/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/projects/ArchR/packages/emulators/libretro/retroarch/patches/0002-quit-not-restart.patch b/projects/ArchR/packages/emulators/libretro/retroarch/patches/0002-quit-not-restart.patch new file mode 100644 index 0000000000..76ea4041aa --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/patches/0002-quit-not-restart.patch @@ -0,0 +1,12 @@ +diff -rupN retroarch.orig/menu/menu_setting.c retroarch/menu/menu_setting.c +--- retroarch.orig/menu/menu_setting.c 2022-03-05 15:34:24.206615672 -0500 ++++ retroarch/menu/menu_setting.c 2022-03-05 20:09:51.435336191 -0500 +@@ -9321,7 +9321,7 @@ static bool setting_append_list( + CONFIG_ACTION( + list, list_info, + MENU_ENUM_LABEL_QUIT_RETROARCH, +- MENU_ENUM_LABEL_VALUE_RESTART_RETROARCH, ++ MENU_ENUM_LABEL_VALUE_QUIT_RETROARCH, + &group_info, + &subgroup_info, + parent_group); diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/patches/0003-fix-oga-no-preferred.patch b/projects/ArchR/packages/emulators/libretro/retroarch/patches/0003-fix-oga-no-preferred.patch new file mode 100644 index 0000000000..e5a77fe1d6 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/patches/0003-fix-oga-no-preferred.patch @@ -0,0 +1,54 @@ +diff --git a/deps/libgo2/src/display.c b/deps/libgo2/src/display.c +index b91cf0624b..e1d10593ba 100644 +--- a/deps/libgo2/src/display.c ++++ b/deps/libgo2/src/display.c +@@ -151,6 +151,7 @@ go2_display_t* go2_display_create() + + // Find prefered mode + drmModeModeInfo* mode; ++ mode = &connector->modes[0]; + for (i = 0; i < connector->count_modes; i++) + { + drmModeModeInfo *current_mode = &connector->modes[i]; +@@ -159,14 +160,6 @@ go2_display_t* go2_display_create() + mode = current_mode; + break; + } +- +- mode = NULL; +- } +- +- if (!mode) +- { +- printf("DRM_MODE_TYPE_PREFERRED not found.\n"); +- goto err_03; + } + + result->mode = *mode; +diff --git a/gfx/drivers/oga_gfx.c b/gfx/drivers/oga_gfx.c +index 69fa7a75bb..28c1b0f1fc 100644 +--- a/gfx/drivers/oga_gfx.c ++++ b/gfx/drivers/oga_gfx.c +@@ -142,6 +142,7 @@ static bool oga_create_display(oga_video_t* vid) + vid->connector_id = connector->connector_id; + + /* Find preferred mode */ ++ mode = &connector->modes[0]; + for (i = 0; i < connector->count_modes; i++) + { + drmModeModeInfo *current_mode = &connector->modes[i]; +@@ -150,14 +151,6 @@ static bool oga_create_display(oga_video_t* vid) + mode = current_mode; + break; + } +- +- mode = NULL; +- } +- +- if (!mode) +- { +- RARCH_ERR("DRM_MODE_TYPE_PREFERRED not found.\n"); +- goto err_03; + } + + vid->mode = *mode; diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/patches/0004-drm-resolution.patch b/projects/ArchR/packages/emulators/libretro/retroarch/patches/0004-drm-resolution.patch new file mode 100644 index 0000000000..369b26729e --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/patches/0004-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/projects/ArchR/packages/emulators/libretro/retroarch/patches/0006-no-screen-brightness.patch b/projects/ArchR/packages/emulators/libretro/retroarch/patches/0006-no-screen-brightness.patch new file mode 100644 index 0000000000..9f88f70e6f --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/patches/0006-no-screen-brightness.patch @@ -0,0 +1,29 @@ +diff -rupN retroarch.orig/frontend/drivers/platform_unix.c retroarch/frontend/drivers/platform_unix.c +--- retroarch.orig/frontend/drivers/platform_unix.c 2022-02-05 19:38:43.852018492 -0500 ++++ retroarch/frontend/drivers/platform_unix.c 2022-02-05 20:10:30.735583922 -0500 +@@ -2048,12 +2048,6 @@ static void frontend_unix_deinit(void *d + android_app_destroy(android_app); + #endif + +-#ifdef HAVE_LAKKA +- /* Reset brightness to maximum */ +- if (settings->uints.screen_brightness != DEFAULT_SCREEN_BRIGHTNESS) +- frontend_unix_set_screen_brightness(DEFAULT_SCREEN_BRIGHTNESS); +-#endif +- + frontend_unix_set_gamemode(false); + } + +@@ -2885,11 +2879,7 @@ frontend_ctx_driver_t frontend_ctx_unix + #else + NULL, /* get_lakka_version */ + #endif +-#if defined(HAVE_LAKKA_SWITCH) || (defined(HAVE_LAKKA) && defined(HAVE_ODROIDGO2)) +- frontend_unix_set_screen_brightness,/* set_screen_brightness */ +-#else +- NULL, /* set_screen_brightness */ +-#endif ++ NULL, /* set_screen_brightness? No. */ + frontend_unix_watch_path_for_changes, + frontend_unix_check_for_path_changes, + frontend_unix_set_sustained_performance_mode, diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/patches/0008-disable_search.patch b/projects/ArchR/packages/emulators/libretro/retroarch/patches/0008-disable_search.patch new file mode 100644 index 0000000000..c15a8979ab --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/patches/0008-disable_search.patch @@ -0,0 +1,13 @@ +diff --git a/menu/menu_driver.c b/menu/menu_driver.c +index cf2c30f7c7..e04ab9702b 100644 +--- a/menu/menu_driver.c ++++ b/menu/menu_driver.c +@@ -7617,7 +7617,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/projects/ArchR/packages/emulators/libretro/retroarch/patches/0009-hide-wayland-checkerboard.patch b/projects/ArchR/packages/emulators/libretro/retroarch/patches/0009-hide-wayland-checkerboard.patch new file mode 100644 index 0000000000..6c03def537 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/patches/0009-hide-wayland-checkerboard.patch @@ -0,0 +1,27 @@ +diff --git a/gfx/drivers/vulkan.c b/gfx/drivers/vulkan.c +index d04a24172c..806e336ba2 100644 +--- a/gfx/drivers/vulkan.c ++++ b/gfx/drivers/vulkan.c +@@ -3313,14 +3313,14 @@ static uintptr_t vulkan_load_texture(void *video_data, void *data, + { + /* Create a dummy texture instead. */ + static const uint32_t checkerboard[] = { +- VK_T0, VK_T1, VK_T0, VK_T1, VK_T0, VK_T1, VK_T0, VK_T1, +- VK_T1, VK_T0, VK_T1, VK_T0, VK_T1, VK_T0, VK_T1, VK_T0, +- VK_T0, VK_T1, VK_T0, VK_T1, VK_T0, VK_T1, VK_T0, VK_T1, +- VK_T1, VK_T0, VK_T1, VK_T0, VK_T1, VK_T0, VK_T1, VK_T0, +- VK_T0, VK_T1, VK_T0, VK_T1, VK_T0, VK_T1, VK_T0, VK_T1, +- VK_T1, VK_T0, VK_T1, VK_T0, VK_T1, VK_T0, VK_T1, VK_T0, +- VK_T0, VK_T1, VK_T0, VK_T1, VK_T0, VK_T1, VK_T0, VK_T1, +- VK_T1, VK_T0, VK_T1, VK_T0, VK_T1, VK_T0, VK_T1, VK_T0, ++ VK_T0, VK_T0, VK_T0, VK_T0, VK_T0, VK_T0, VK_T0, VK_T0, ++ VK_T0, VK_T0, VK_T0, VK_T0, VK_T0, VK_T0, VK_T0, VK_T0, ++ VK_T0, VK_T0, VK_T0, VK_T0, VK_T0, VK_T0, VK_T0, VK_T0, ++ VK_T0, VK_T0, VK_T0, VK_T0, VK_T0, VK_T0, VK_T0, VK_T0, ++ VK_T0, VK_T0, VK_T0, VK_T0, VK_T0, VK_T0, VK_T0, VK_T0, ++ VK_T0, VK_T0, VK_T0, VK_T0, VK_T0, VK_T0, VK_T0, VK_T0, ++ VK_T0, VK_T0, VK_T0, VK_T0, VK_T0, VK_T0, VK_T0, VK_T0, ++ VK_T0, VK_T0, VK_T0, VK_T0, VK_T0, VK_T0, VK_T0, VK_T0, + }; + *texture = vulkan_create_texture(vk, NULL, + 8, 8, VK_FORMAT_B8G8R8A8_UNORM, diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/patches/0010-paths.patch b/projects/ArchR/packages/emulators/libretro/retroarch/patches/0010-paths.patch new file mode 100644 index 0000000000..75595787dc --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/patches/0010-paths.patch @@ -0,0 +1,51 @@ +diff --git a/frontend/drivers/platform_unix.c b/frontend/drivers/platform_unix.c +index e1db1da096..7baf8a5f21 100644 +--- a/frontend/drivers/platform_unix.c ++++ b/frontend/drivers/platform_unix.c +@@ -1812,7 +1812,7 @@ static void frontend_unix_get_env(int *argc, + "/usr/share/games/retroarch", + "assets", sizeof(g_defaults.dirs[DEFAULT_DIR_ASSETS])); + else +- fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_ASSETS], base_path, ++ fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_ASSETS], "/tmp/", + "assets", sizeof(g_defaults.dirs[DEFAULT_DIR_ASSETS])); + + #if defined(DINGUX) +@@ -1885,7 +1885,7 @@ static void frontend_unix_get_env(int *argc, + fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_REMAP], + g_defaults.dirs[DEFAULT_DIR_MENU_CONFIG], + "remaps", sizeof(g_defaults.dirs[DEFAULT_DIR_REMAP])); +- fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_PLAYLIST], base_path, ++ fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_PLAYLIST], "/tmp/", + "playlists", sizeof(g_defaults.dirs[DEFAULT_DIR_PLAYLIST])); + fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_RECORD_CONFIG], base_path, + "records_config", sizeof(g_defaults.dirs[DEFAULT_DIR_RECORD_CONFIG])); +@@ -1896,14 +1896,14 @@ static void frontend_unix_get_env(int *argc, + libretro_database_directory, + sizeof(g_defaults.dirs[DEFAULT_DIR_DATABASE])); + else +- fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_DATABASE], base_path, ++ fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_DATABASE], "/tmp/", + "database/rdb", sizeof(g_defaults.dirs[DEFAULT_DIR_DATABASE])); + if (!string_is_empty(libretro_video_shader_directory)) + strlcpy(g_defaults.dirs[DEFAULT_DIR_SHADER], + libretro_video_shader_directory, + sizeof(g_defaults.dirs[DEFAULT_DIR_SHADER])); + else +- fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_SHADER], base_path, ++ fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_SHADER], "/tmp/", + "shaders", sizeof(g_defaults.dirs[DEFAULT_DIR_SHADER])); + if (!string_is_empty(libretro_cheats_directory)) + strlcpy(g_defaults.dirs[DEFAULT_DIR_CHEATS], +@@ -1912,9 +1912,9 @@ static void frontend_unix_get_env(int *argc, + else + fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_CHEATS], base_path, + "cheats", sizeof(g_defaults.dirs[DEFAULT_DIR_CHEATS])); +- fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_OVERLAY], base_path, ++ fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_OVERLAY], "/tmp/", + "overlays", sizeof(g_defaults.dirs[DEFAULT_DIR_OVERLAY])); +- fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_OSK_OVERLAY], base_path, ++ fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_OSK_OVERLAY], "/tmp/", + "overlays/keyboards", sizeof(g_defaults.dirs[DEFAULT_DIR_OSK_OVERLAY])); + fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_CORE_ASSETS], base_path, + "downloads", sizeof(g_defaults.dirs[DEFAULT_DIR_CORE_ASSETS])); diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/patches/0011-cheevos-sounds.patch b/projects/ArchR/packages/emulators/libretro/retroarch/patches/0011-cheevos-sounds.patch new file mode 100644 index 0000000000..b5e8662091 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/patches/0011-cheevos-sounds.patch @@ -0,0 +1,83 @@ +diff --git a/audio/audio_driver.c b/audio/audio_driver.c +index 01a727eb95..fc43700d22 100644 +--- a/audio/audio_driver.c ++++ b/audio/audio_driver.c +@@ -1339,8 +1339,8 @@ static void audio_driver_load_menu_bgm_callback(retro_task_t *task, + void audio_driver_load_system_sounds(void) + { + char basename_noext[NAME_MAX_LENGTH]; +- char sounds_path[PATH_MAX_LENGTH]; +- char sounds_fallback_path[PATH_MAX_LENGTH]; ++ char* sounds_path = "/usr/share/libretro/sounds"; ++ char* sounds_fallback_path = "/storage/roms/music/retroachievements"; + settings_t *settings = config_get_ptr(); + const char *dir_assets = settings->paths.directory_assets; + const bool audio_enable_menu = settings->bools.audio_enable_menu; +@@ -1365,19 +1365,6 @@ void audio_driver_load_system_sounds(void) + if (!audio_enable_menu && !audio_enable_cheevo_unlock) + goto end; + +- sounds_path[0] = basename_noext[0] ='\0'; +- +- fill_pathname_join_special( +- sounds_fallback_path, +- dir_assets, +- "sounds", +- sizeof(sounds_fallback_path)); +- +- fill_pathname_application_special( +- sounds_path, +- sizeof(sounds_path), +- APPLICATION_SPECIAL_DIRECTORY_ASSETS_SOUNDS); +- + list = dir_list_new(sounds_path, MENU_SOUND_FORMATS, false, false, false, false); + list_fallback = dir_list_new(sounds_fallback_path, MENU_SOUND_FORMATS, false, false, false, false); + +@@ -1423,8 +1410,13 @@ void audio_driver_load_system_sounds(void) + path_notice_back = path; + else if (string_is_equal_noncase(basename_noext, "bgm")) + path_bgm = path; +- else if (string_is_equal_noncase(basename_noext, "unlock")) +- path_cheevo_unlock = path; ++ else if(string_is_empty(settings->arrays.cheevos_unlock_sound) == false) { ++ if (string_is_equal_noncase(basename_noext, "unlock")) ++ path_cheevo_unlock = path; ++ else ++ if (string_is_equal_noncase(basename_noext, settings->arrays.cheevos_unlock_sound)) ++ path_cheevo_unlock = path; ++ } + else if (string_is_equal_noncase(basename_noext, "up")) + path_up = path; + else if (string_is_equal_noncase(basename_noext, "down")) +diff --git a/configuration.c b/configuration.c +index 6b202341b0..ef831dc1fb 100644 +--- a/configuration.c ++++ b/configuration.c +@@ -1568,6 +1568,7 @@ static struct config_array_setting *populate_settings_array( + SETTING_ARRAY("cheevos_username", settings->arrays.cheevos_username, false, NULL, true); + SETTING_ARRAY("cheevos_password", settings->arrays.cheevos_password, false, NULL, true); + SETTING_ARRAY("cheevos_token", settings->arrays.cheevos_token, false, NULL, true); ++ SETTING_ARRAY("cheevos_unlock_sound", settings->arrays.cheevos_unlock_sound, false, NULL, true); + SETTING_ARRAY("cheevos_leaderboards_enable", settings->arrays.cheevos_leaderboards_enable, true, "", true); /* deprecated */ + #endif + +@@ -2957,6 +2958,7 @@ void config_set_defaults(void *data) + #ifdef HAVE_CHEEVOS + *settings->arrays.cheevos_username = '\0'; + *settings->arrays.cheevos_password = '\0'; ++ *settings->arrays.cheevos_unlock_sound = '\0'; + *settings->arrays.cheevos_token = '\0'; + #endif + +diff --git a/configuration.h b/configuration.h +index 611678c510..e87f2f6318 100644 +--- a/configuration.h ++++ b/configuration.h +@@ -467,6 +467,7 @@ typedef struct settings + char cloud_sync_driver[32]; + char menu_driver[32]; + char cheevos_username[32]; ++ char cheevos_unlock_sound[128]; + char cheevos_token[32]; + char cheevos_leaderboards_enable[32]; + char video_context_driver[32]; diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/patches/0012-cheevos-cmd.patch b/projects/ArchR/packages/emulators/libretro/retroarch/patches/0012-cheevos-cmd.patch new file mode 100644 index 0000000000..1d94a25bab --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/patches/0012-cheevos-cmd.patch @@ -0,0 +1,42 @@ +diff --git a/cheevos/cheevos.c b/cheevos/cheevos.c +index d8fc40c..aed6de4 100644 +--- a/cheevos/cheevos.c ++++ b/cheevos/cheevos.c +@@ -470,6 +470,13 @@ static void rcheevos_award_achievement(const rc_client_achievement_t* cheevo) + } + } + ++ const char* cheevos_cmd = settings->arrays.cheevos_cmd; ++ if (cheevos_cmd[0]) { ++ char cmdargs[256]; ++ snprintf(cmdargs, sizeof(cmdargs), "%s %u \"%s\" \"%s\" > /dev/null 2>/dev/null", cheevos_cmd, cheevo->id, cheevo->title, cheevo->description); ++ system(cmdargs); ++ } ++ + #ifdef HAVE_AUDIOMIXER + /* Play the unlock sound */ + if (settings->bools.cheevos_unlock_sound_enable) +diff --git a/configuration.c b/configuration.c +index 0458404..3119b97 100644 +--- a/configuration.c ++++ b/configuration.c +@@ -1523,6 +1523,7 @@ static struct config_array_setting *populate_settings_array( + + #ifdef HAVE_CHEEVOS + SETTING_ARRAY("cheevos_custom_host", settings->arrays.cheevos_custom_host, false, NULL, true); ++ SETTING_ARRAY("cheevos_cmd", settings->arrays.cheevos_cmd, false, NULL, true); + SETTING_ARRAY("cheevos_username", settings->arrays.cheevos_username, false, NULL, true); + SETTING_ARRAY("cheevos_password", settings->arrays.cheevos_password, false, NULL, true); + SETTING_ARRAY("cheevos_token", settings->arrays.cheevos_token, false, NULL, true); +diff --git a/configuration.h b/configuration.h +index a7eae74..47a8376 100644 +--- a/configuration.h ++++ b/configuration.h +@@ -471,6 +471,7 @@ typedef struct settings + char cheevos_unlock_sound[128]; + char cheevos_token[32]; + char cheevos_leaderboards_enable[32]; ++ char cheevos_cmd[256]; + char video_context_driver[32]; + char audio_driver[32]; + char audio_resampler[32]; diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-assets/package.mk b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-assets/package.mk new file mode 100644 index 0000000000..99eb903150 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-assets/package.mk @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="retroarch-assets" +PKG_VERSION="76cc6cf03507429c5a136cb50d83a14e05430fcd" +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="make:host" +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" +} + +post_makeinstall_target() { + # Remove unnecesary Retroarch Assets and overlays + rm -rf ${INSTALL}/usr/share/retroarch-assets/{branding,nxrgui,pkg,scripts,switch,wallpapers} + rm -rf ${INSTALL}/usr/share/retroarch-assets/xmb/{automatic,dot-art,flatui,pixel,retrosystem,systematic} +} diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/ THEC64 Joystick THEC64 Joystick .cfg b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/ THEC64 Joystick THEC64 Joystick .cfg new file mode 100644 index 0000000000..0ec40c3ec9 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/ THEC64 Joystick THEC64 Joystick .cfg @@ -0,0 +1,16 @@ +input_driver = "udev" +input_device = " THEC64 Joystick THEC64 Joystick " +input_vendor_id = "7257" +input_product_id = "36" +input_b_btn = "1" +input_y_btn = "4" +input_select_btn = "2" +input_start_btn = "3" +input_up_axis = "-1" +input_down_axis = "+1" +input_left_axis = "-0" +input_right_axis = "+0" +input_a_btn = "0" +input_x_btn = "7" +input_l_btn = "5" +input_r_btn = "6" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/8Bitdo SF30 Pro 8Bitdo SN30 Pro.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/8Bitdo SF30 Pro 8Bitdo SN30 Pro.cfg new file mode 100644 index 0000000000..5d4714bb32 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/8Bitdo SF30 Pro 8Bitdo SN30 Pro.cfg @@ -0,0 +1,29 @@ +input_driver = "udev" +input_device = "8Bitdo SF30 Pro 8Bitdo SN30 Pro" +input_vendor_id = "11720" +input_product_id = "24577" +input_gun_trigger_mbtn = "1" +input_b_btn = "1" +input_y_btn = "4" +input_select_btn = "10" +input_start_btn = "11" +input_up_btn = "h0up" +input_down_btn = "h0down" +input_left_btn = "h0left" +input_right_btn = "h0right" +input_a_btn = "0" +input_x_btn = "3" +input_l_btn = "6" +input_r_btn = "7" +input_l2_btn = "8" +input_r2_btn = "9" +input_l3_btn = "13" +input_r3_btn = "14" +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" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/AYN Odin Gamepad.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/AYN Odin Gamepad.cfg new file mode 100644 index 0000000000..d8ed6f5fab --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/AYN Odin Gamepad.cfg @@ -0,0 +1,42 @@ +fast_forwardinput_driver = "udev" +input_device = "AYN Odin Gamepad" + +input_a_btn = "0" +input_b_btn = "1" +input_x_btn = "2" +input_y_btn = "3" +input_select_btn = "4" +input_start_btn = "6" +input_up_btn = "11" +input_down_btn = "12" +input_left_btn = "13" +input_right_btn = "14" +input_l_btn = "9" +input_r_btn = "10" +input_l2_axis = "+2" +input_r2_axis = "+5" +input_l3_btn = "7" +input_r3_btn = "8" +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 = "5" +input_exit_emulator_btn = "6" + +input_screenshot_btn = "0" +input_reset_btn = "1" +input_menu_toggle_btn = "2" +input_fps_toggle_btn = "3" + +input_load_state_btn = "9" +input_save_state_btn = "10" + +input_rewind_axis = "+2" +input_toggle_fast_forward_axis = "+5" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/AYN Odin2 Gamepad.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/AYN Odin2 Gamepad.cfg new file mode 100644 index 0000000000..4f6ca212a7 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/AYN Odin2 Gamepad.cfg @@ -0,0 +1,42 @@ +input_driver = "udev" +input_device = "AYN Odin2 Gamepad" + +input_b_btn = "1" +input_y_btn = "3" +input_select_btn = "4" +input_start_btn = "6" +input_up_btn = "11" +input_down_btn = "12" +input_left_btn = "13" +input_right_btn = "14" +input_a_btn = "0" +input_x_btn = "2" +input_l_btn = "9" +input_r_btn = "10" +input_l2_axis = "+4" +input_r2_axis = "+5" +input_l3_btn = "7" +input_r3_btn = "8" +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 = "5" +input_exit_emulator_btn = "6" + +input_menu_toggle_btn = "2" +input_fps_toggle_btn = "3" +input_screenshot_btn = "0" +input_reset_btn = "1" + +input_load_state_btn = "9" +input_save_state_btn = "10" + +input_rewind_axis = "+4" +input_toggle_fast_forward_axis = "+5" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/Atari Classic Controller.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/Atari Classic Controller.cfg new file mode 100644 index 0000000000..a4815613a0 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/Atari Classic Controller.cfg @@ -0,0 +1,14 @@ +input_driver = "udev" +input_device = "Atari Classic Controller" +input_vendor_id = "12880" +input_product_id = "4098" +input_b_btn = "2" +input_select_btn = "4" +input_start_btn = "3" +input_up_btn = "h0up" +input_down_btn = "h0down" +input_left_btn = "h0left" +input_right_btn = "h0right" +input_a_btn = "1" +input_x_btn = "5" +input_gun_trigger_mbtn = "1" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/Atari Game Controller.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/Atari Game Controller.cfg new file mode 100644 index 0000000000..5459ea22bc --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/Atari Game Controller.cfg @@ -0,0 +1,29 @@ +input_driver = "udev" +input_device = "Atari Game Controller" +input_vendor_id = "12880" +input_product_id = "4098" +input_b_btn = "1" +input_y_btn = "3" +input_select_btn = "10" +input_start_btn = "9" +input_up_btn = "h0up" +input_down_btn = "h0down" +input_left_btn = "h0left" +input_right_btn = "h0right" +input_a_btn = "2" +input_x_btn = "4" +input_l_btn = "5" +input_r_btn = "6" +input_l2_axis = "+5" +input_r2_axis = "+4" +input_l3_btn = "7" +input_r3_btn = "8" +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/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/Core (Plus) Wired Controller.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/Core (Plus) Wired Controller.cfg new file mode 100644 index 0000000000..345a0c5e62 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/Core (Plus) Wired Controller.cfg @@ -0,0 +1,29 @@ +input_driver = "udev" +input_device = "Core (Plus) Wired Controller" +input_vendor_id = "8406" +input_product_id = "42769" +input_b_btn = "1" +input_y_btn = "0" +input_select_btn = "8" +input_start_btn = "9" +input_up_btn = "h0up" +input_down_btn = "h0down" +input_left_btn = "h0left" +input_right_btn = "h0right" +input_a_btn = "2" +input_x_btn = "3" +input_l_btn = "4" +input_r_btn = "5" +input_l2_btn = "6" +input_r2_btn = "7" +input_l3_btn = "10" +input_r3_btn = "11" +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/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/GO-Super Gamepad.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/GO-Super Gamepad.cfg new file mode 100644 index 0000000000..d30e378aae --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/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" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/GO-Ultra Gamepad.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/GO-Ultra Gamepad.cfg new file mode 100644 index 0000000000..5bc2e5d0fe --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/GO-Ultra Gamepad.cfg @@ -0,0 +1,51 @@ +input_device = "GO-Ultra Gamepad" +input_driver = "udev" + +input_b_btn = "0" +input_a_btn = "1" +input_x_btn = "3" +input_y_btn = "4" +input_l_btn = "5" +input_r_btn = "6" +input_l2_btn = "7" +input_r2_btn = "8" + +input_up_btn = "14" +input_down_btn = "15" +input_left_btn = "16" +input_right_btn = "17" + +input_select_btn = "9" +input_start_btn = "10" + +input_l3_btn = "12" +input_r3_btn = "13" + +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 = "11" +input_exit_emulator_btn = "10" + +input_screenshot_btn = "0" +input_pause_toggle_btn = "1" +input_menu_toggle_btn = "3" +input_fps_toggle_btn = "4" + +input_state_slot_increase_btn = "14" +input_state_slot_decrease_btn = "15" + +input_load_state_btn = "5" +input_save_state_btn = "6" + +input_rewind_btn = "7" +input_toggle_fast_forward_btn = "8" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/Game Controller.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/Game Controller.cfg new file mode 100644 index 0000000000..835197fe99 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/Game Controller.cfg @@ -0,0 +1,29 @@ +input_driver = "udev" +input_device = "Game Controller" +input_vendor_id = "12880" +input_product_id = "4098" +input_b_btn = "1" +input_y_btn = "3" +input_select_btn = "10" +input_start_btn = "9" +input_up_btn = "h0up" +input_down_btn = "h0down" +input_left_btn = "h0left" +input_right_btn = "h0right" +input_a_btn = "2" +input_x_btn = "4" +input_l_btn = "5" +input_r_btn = "6" +input_l2_axis = "+5" +input_r2_axis = "+4" +input_l3_btn = "7" +input_r3_btn = "8" +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/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/GameForce ACE Gamepad.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/GameForce ACE Gamepad.cfg new file mode 100644 index 0000000000..69a36664ed --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/GameForce ACE Gamepad.cfg @@ -0,0 +1,27 @@ +input_driver = "udev" +input_device = "GameForce ACE Gamepad" +input_b_btn = "0" +input_y_btn = "4" +input_select_btn = "7" +input_start_btn = "8" +input_up_btn = "12" +input_down_btn = "13" +input_left_btn = "14" +input_right_btn = "15" +input_a_btn = "1" +input_x_btn = "3" +input_l_btn = "5" +input_r_btn = "6" +input_l2_axis = "-2" +input_r2_axis = "-5" +input_l3_btn = "10" +input_r3_btn = "11" +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 = "+3" +input_r_x_minus_axis = "-3" +input_r_y_plus_axis = "+4" +input_r_y_minus_axis = "-4" +input_enable_hotkey_btn = "9" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/H700 Gamepad.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/H700 Gamepad.cfg new file mode 100644 index 0000000000..f07001abd1 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/H700 Gamepad.cfg @@ -0,0 +1,52 @@ +input_driver = "udev" +input_device = "H700 Gamepad" +input_device_display_name = "Anbernic RG35XX Gamepad" +input_vendor_id = "18507" +input_product_id = "5343" + +input_b_btn = "0" +input_a_btn = "1" +input_y_btn = "2" +input_x_btn = "3" +input_l_btn = "4" +input_r_btn = "5" +input_l2_btn = "6" +input_r2_btn = "7" + +input_select_btn = "8" +input_start_btn = "9" + +input_l3_btn = "11" +input_r3_btn = "12" + +input_up_btn = "13" +input_down_btn = "14" +input_left_btn = "15" +input_right_btn = "16" + +input_enable_hotkey_btn = "10" +input_exit_emulator_btn = "9" + +input_pause_toggle_btn = "1" +input_menu_toggle_btn = "3" +input_fps_toggle_btn = "2" +input_screenshot_btn = "nul" +input_load_state_btn = "4" +input_save_state_btn = "5" +input_toggle_fast_forward_btn = "7" +input_rewind_btn = "6" + +input_analog_dpad_mode = "0" +input_gun_trigger_mbtn = "1" +input_joypad_index = "0" +input_l_x_minus_axis = "-0" +input_l_x_plus_axis = "+0" +input_l_y_minus_axis = "-1" +input_l_y_plus_axis = "+1" +input_mouse_index = "0" +input_r_x_minus_axis = "-2" +input_r_x_plus_axis = "+2" +input_r_y_minus_axis = "-3" +input_r_y_plus_axis = "+3" +input_state_slot_increase_btn = "nul" +input_state_slot_decrease_btn = "nul" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/Microsoft X-Box 360 pad.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/Microsoft X-Box 360 pad.cfg new file mode 100644 index 0000000000..07aed81e42 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/Microsoft X-Box 360 pad.cfg @@ -0,0 +1,28 @@ +input_driver = "udev" +input_device = "Microsoft X-Box 360 pad" +input_vendor_id = "1118" +input_product_id = "654" +input_b_btn = "0" +input_y_btn = "2" +input_select_btn = "6" +input_start_btn = "7" +input_up_btn = "h0up" +input_down_btn = "h0down" +input_left_btn = "h0left" +input_right_btn = "h0right" +input_a_btn = "1" +input_x_btn = "3" +input_l_btn = "4" +input_r_btn = "5" +input_l2_axis = "+2" +input_r2_axis = "+5" +input_l3_btn = "9" +input_r3_btn = "10" +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 = "+3" +input_r_x_minus_axis = "-3" +input_r_y_plus_axis = "+4" +input_r_y_minus_axis = "-4" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/Microsoft Xbox Series S_X Controller.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/Microsoft Xbox Series S_X Controller.cfg new file mode 100644 index 0000000000..4b96332b91 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/Microsoft Xbox Series S_X Controller.cfg @@ -0,0 +1,44 @@ +input_driver = "udev" +input_device = "Microsoft Xbox Series S|X Controller" +input_vendor_id = "1118" +input_product_id = "2834" + +input_b_btn = "0" +input_a_btn = "1" +input_y_btn = "2" +input_x_btn = "3" +input_l_btn = "4" +input_r_btn = "5" + +input_select_btn = "6" +input_start_btn = "7" + +input_up_btn = "h0up" +input_down_btn = "h0down" +input_left_btn = "h0left" +input_right_btn = "h0right" + +input_l2_axis = "+2" +input_r2_axis = "+5" +input_l3_btn = "9" +input_r3_btn = "10" + +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 = "+3" +input_r_x_minus_axis = "-3" +input_r_y_plus_axis = "+4" +input_r_y_minus_axis = "-4" + +input_enable_hotkey_btn = "8" +input_exit_emulator_btn = "7" +input_menu_toggle_btn = "3" +input_pause_toggle_btn = "1" +input_fps_toggle_btn = "0" +input_screenshot_btn = "2" +input_load_state_btn = "4" +input_save_state_btn = "5" +input_rewind_axis = "+2" +input_hold_fast_forward_axis = "+5" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/OpenSimHardware OSH PB Controller.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/OpenSimHardware OSH PB Controller.cfg new file mode 100755 index 0000000000..6edd2a183a --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/OpenSimHardware OSH PB Controller.cfg @@ -0,0 +1,44 @@ +input_device = "OpenSimHardware OSH PB Controller" +input_driver = "udev" +input_vendor_id = "4617" +input_product_id = "12544" + +input_b_btn = "1" +input_a_btn = "0" +input_x_btn = "2" +input_y_btn = "3" +input_l_btn = "4" +input_r_btn = "5" +input_l2_btn = "10" +input_r2_btn = "11" + +input_select_btn = "7" +input_start_btn = "6" + +input_l3_btn = "8" +input_r3_btn = "9" + +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 = "7" +input_exit_emulator_btn = "6" + +input_menu_toggle_btn = "2" +input_fps_toggle_btn = "3" + +input_load_state_btn = "4" +input_save_state_btn = "5" + diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/OpenSimHardware OSH PB Controller_SDL.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/OpenSimHardware OSH PB Controller_SDL.cfg new file mode 100644 index 0000000000..f9905f2781 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/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/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/RGB20S Gamepad.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/RGB20S Gamepad.cfg new file mode 100644 index 0000000000..3b09cd61f7 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/RGB20S Gamepad.cfg @@ -0,0 +1,44 @@ +input_driver = "udev" +input_device = "RGB20S Gamepad" +input_device_display_name = "RGB20S Gamepad" + +input_b_btn = "0" +input_y_btn = "3" +input_select_btn = "12" +input_start_btn = "13" +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 = "14" +input_r3_btn = "15" + +input_up_btn = "8" +input_down_btn = "9" +input_left_btn = "10" +input_right_btn = "11" + +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_menu_toggle_btn = "2" +input_fps_toggle_btn = "3" + +input_load_state_btn = "4" +input_save_state_btn = "5" + +input_rewind_btn = "6" +input_toggle_fast_forward_btn = "7" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/ROCKNIX Gamepad.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/ROCKNIX Gamepad.cfg new file mode 100644 index 0000000000..542b465936 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/ROCKNIX Gamepad.cfg @@ -0,0 +1,29 @@ +input_driver = "udev" +input_device = "ArchR Gamepad" +input_vendor_id = "4660" +input_product_id = "22136" +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 = "+3" +input_r_x_minus_axis = "-3" +input_r_y_plus_axis = "+4" +input_r_y_minus_axis = "-4" +input_gun_trigger_mbtn = "1" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/Retro Lite CM5 Gamepad.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/Retro Lite CM5 Gamepad.cfg new file mode 100644 index 0000000000..e85b5142bc --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/Retro Lite CM5 Gamepad.cfg @@ -0,0 +1,27 @@ +input_driver = "udev" +input_device = "Retro Lite CM5 Gamepad" +input_b_btn = "0" +input_y_btn = "2" +input_select_btn = "5" +input_start_btn = "4" +input_up_btn = "h0up" +input_down_btn = "h0down" +input_left_btn = "h0left" +input_right_btn = "h0right" +input_a_btn = "1" +input_x_btn = "3" +input_l_btn = "11" +input_r_btn = "10" +input_l2_btn = "6" +input_r2_btn = "7" +input_l3_btn = "12" +input_r3_btn = "13" +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 = "14" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/Retroid Pocket Gamepad.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/Retroid Pocket Gamepad.cfg new file mode 100644 index 0000000000..17fb8356af --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/Retroid Pocket Gamepad.cfg @@ -0,0 +1,42 @@ +input_driver = "udev" +input_device = "Retroid Pocket Gamepad" + +input_b_btn = "1" +input_y_btn = "3" +input_select_btn = "4" +input_start_btn = "6" +input_up_btn = "11" +input_down_btn = "12" +input_left_btn = "13" +input_right_btn = "14" +input_a_btn = "0" +input_x_btn = "2" +input_l_btn = "9" +input_r_btn = "10" +input_l2_axis = "+4" +input_r2_axis = "+5" +input_l3_btn = "7" +input_r3_btn = "8" +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 = "5" +input_exit_emulator_btn = "6" + +input_menu_toggle_btn = "2" +input_fps_toggle_btn = "3" +input_screenshot_btn = "0" +input_reset_btn = "1" + +input_load_state_btn = "9" +input_save_state_btn = "10" + +input_rewind_axis = "+4" +input_toggle_fast_forward_axis = "+5" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/Steam Controller.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/Steam Controller.cfg new file mode 100644 index 0000000000..8331e7cbac --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/Steam Controller.cfg @@ -0,0 +1,32 @@ +input_driver = "udev" +input_device = "Steam Controller" +input_vendor_id = "10462" +input_product_id = "4613" +input_b_btn = "5" +input_y_btn = "7" +input_select_btn = "13" +input_start_btn = "14" +input_up_btn = "20" +input_down_btn = "21" +input_left_btn = "22" +input_right_btn = "23" +input_a_btn = "6" +input_x_btn = "8" +input_l_btn = "9" +input_r_btn = "10" +input_l2_btn = "11" +input_r2_btn = "2" +input_l3_btn = "16" +input_r3_axis = "-1" +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 = "+3" +input_r_x_minus_axis = "-3" +input_r_y_plus_axis = "+4" +input_r_y_minus_axis = "-4" +input_l2_axis = "+4" +input_r2_axis = "+2" +input_r3_btn = "17" +input_gun_trigger_mbtn = "1" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/XU Mini M Gamepad.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/XU Mini M Gamepad.cfg new file mode 100644 index 0000000000..b32cd84915 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/XU Mini M Gamepad.cfg @@ -0,0 +1,35 @@ +input_driver = "udev" +input_device = "XU Mini M Gamepad" +input_device_display_name = "MagicX XU Mini M Gamepad" +input_b_btn = "0" +input_y_btn = "3" +input_select_btn = "8" +input_start_btn = "9" +input_up_btn = "12" +input_down_btn = "13" +input_left_btn = "14" +input_right_btn = "15" +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 = "10" +input_r3_btn = "11" +input_l_x_plus_axis = "+1" +input_l_x_minus_axis = "-1" +input_l_y_plus_axis = "-0" +input_l_y_minus_axis = "+0" +input_r_x_plus_axis = "+3" +input_r_x_minus_axis = "-3" +input_r_y_plus_axis = "-2" +input_r_y_minus_axis = "+2" +input_enable_hotkey_btn = "16" +input_exit_emulator_btn = "9" +input_menu_toggle_btn = "2" +input_fps_toggle_btn = "3" +input_load_state_btn = "4" +input_save_state_btn = "5" +input_rewind_btn = "6" +input_toggle_fast_forward_btn = "7" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/XU10 Gamepad.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/XU10 Gamepad.cfg new file mode 100644 index 0000000000..ba2d42a8d5 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/XU10 Gamepad.cfg @@ -0,0 +1,52 @@ +input_device = "XU10 Gamepad" +input_driver = "udev" +input_device_display_name = "MagicX XU10 Gamepad" + +input_b_btn = "1" +input_a_btn = "2" +input_x_btn = "3" +input_y_btn = "0" +input_l_btn = "4" +input_r_btn = "5" +input_l2_btn = "7" +input_r2_btn = "6" + +input_up_btn = "12" +input_down_btn = "13" +input_left_btn = "14" +input_right_btn = "15" + +input_select_btn = "8" +input_start_btn = "9" + +input_l3_btn = "10" +input_r3_btn = "11" + +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 = "16" +input_exit_emulator_btn = "9" + +input_screenshot_btn = "0" +input_pause_toggle_btn = "1" +input_menu_toggle_btn = "2" +input_fps_toggle_btn = "3" + +input_state_slot_increase_btn = "7" +input_state_slot_decrease_btn = "6" + +input_load_state_btn = "4" +input_save_state_btn = "5" + +input_rewind_btn = "10" +input_toggle_fast_forward_btn = "11" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/Xbox 360 Controller.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/Xbox 360 Controller.cfg new file mode 100644 index 0000000000..788729c2d4 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/Xbox 360 Controller.cfg @@ -0,0 +1,42 @@ +input_driver = "udev" +input_device = "Xbox 360 Controller" +input_vendor_id = "1118" +input_product_id = "654" + +input_b_btn = "1" +input_a_btn = "0" +input_y_btn = "3" +input_x_btn = "2" +input_l_btn = "9" +input_r_btn = "10" + +input_select_btn = "4" +input_start_btn = "6" +input_up_btn = "11" +input_down_btn = "12" +input_left_btn = "13" +input_right_btn = "14" +input_l2_axis = "+4" +input_r2_axis = "+5" +input_l3_btn = "7" +input_r3_btn = "8" +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 = "5" +input_exit_emulator_btn = "6" +input_menu_toggle_btn = "2" +input_pause_toggle_btn = "0" +input_fps_toggle_btn = "3" +input_screenshot_btn = "nul" +input_load_state_btn = "9" +input_save_state_btn = "10" +input_state_slot_increase_btn = "nul" +input_state_slot_decrease_btn = "nul" +input_menu_toggle_gamepad_combo = "nul" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/odroidgo2_joypad.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/odroidgo2_joypad.cfg new file mode 100644 index 0000000000..489d064618 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/odroidgo2_joypad.cfg @@ -0,0 +1,37 @@ +input_driver = "udev" +input_device = "odroidgo2_joypad" +input_device_display_name = "Odroid GO Advance Joypad" + +input_b_btn = "0" +input_y_btn = "3" +input_select_btn = "10" +input_start_btn = "13" +input_a_btn = "1" +input_x_btn = "2" +input_l_btn = "4" +input_r_btn = "5" +input_l2_btn = "11" +input_r2_btn = "12" + +input_up_btn = "6" +input_down_btn = "7" +input_left_btn = "8" +input_right_btn = "9" + +input_l_x_plus_axis = "+0" +input_l_x_minus_axis = "-0" +input_l_y_plus_axis = "+1" +input_l_y_minus_axis = "-1" + +# Hotkeys +input_enable_hotkey_btn = "10" +input_exit_emulator_btn = "13" + +input_menu_toggle_btn = "2" +input_fps_toggle_btn = "3" + +input_load_state_btn = "4" +input_save_state_btn = "5" + +input_rewind_btn = "11" +input_toggle_fast_forward_btn = "12" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/odroidgo2_v11_joypad.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/odroidgo2_v11_joypad.cfg new file mode 100644 index 0000000000..ec35a92031 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/odroidgo2_v11_joypad.cfg @@ -0,0 +1,39 @@ +input_driver = "udev" +input_device = "odroidgo2_v11_joypad" +input_device_display_name = "Odroid GO Advance Joypad v1.1" + +input_b_btn = "0" +input_y_btn = "3" +input_select_btn = "8" +input_start_btn = "9" +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 = "10" +input_r3_btn = "11" + +input_up_btn = "12" +input_down_btn = "13" +input_left_btn = "14" +input_right_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" + +# Hotkeys +input_enable_hotkey_btn = "8" +input_exit_emulator_btn = "9" + +input_menu_toggle_btn = "2" +input_fps_toggle_btn = "3" + +input_load_state_btn = "4" +input_save_state_btn = "5" + +input_rewind_btn = "6" +input_toggle_fast_forward_btn = "7" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/odroidgo3_joypad.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/odroidgo3_joypad.cfg new file mode 100644 index 0000000000..8904a82396 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/odroidgo3_joypad.cfg @@ -0,0 +1,44 @@ +input_driver = "udev" +input_device = "odroidgo3_joypad" +input_device_display_name = "Odroid GO Super" + +input_b_btn = "0" +input_y_btn = "3" +input_select_btn = "8" +input_start_btn = "9" +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 = "10" +input_r3_btn = "11" + +input_up_btn = "12" +input_down_btn = "13" +input_left_btn = "14" +input_right_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 = "8" +input_exit_emulator_btn = "9" + +input_menu_toggle_btn = "2" +input_fps_toggle_btn = "3" + +input_load_state_btn = "4" +input_save_state_btn = "5" + +input_rewind_btn = "6" +input_toggle_fast_forward_btn = "7" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/r33s_joypad.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/r33s_joypad.cfg new file mode 100644 index 0000000000..1067ae2c4a --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/r33s_joypad.cfg @@ -0,0 +1,32 @@ +input_driver = "udev" +input_device = "r33s_joypad" +input_device_display_name = "R33S Joypad" + +input_b_btn = "0" +input_y_btn = "3" +input_select_btn = "8" +input_start_btn = "9" +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_up_btn = "10" +input_down_btn = 11" +input_left_btn = "12" +input_right_btn = "13" + +# Hotkeys +input_enable_hotkey_btn = "8" +input_exit_emulator_btn = "9" + +input_menu_toggle_btn = "2" +input_fps_toggle_btn = "3" + +input_load_state_btn = "4" +input_save_state_btn = "5" + +input_rewind_btn = "6" +input_toggle_fast_forward_btn = "7" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/r36s_Gamepad.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/r36s_Gamepad.cfg new file mode 100644 index 0000000000..aab534b319 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/r36s_Gamepad.cfg @@ -0,0 +1,35 @@ +input_driver = "udev" +input_device = "r36s_Gamepad" +input_device_display_name = "R36S" +input_b_btn = "0" +input_y_btn = "3" +input_select_btn = "8" +input_start_btn = "9" +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_up_btn = "13" +input_down_btn = "14" +input_left_btn = "15" +input_right_btn = "16" +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 = "8" +input_exit_emulator_btn = "9" +input_menu_toggle_btn = "2" +input_fps_toggle_btn = "3" +input_load_state_btn = "4" +input_save_state_btn = "5" +input_rewind_btn = "6" +input_toggle_fast_forward_btn = "7" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/retrogame_joypad.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/retrogame_joypad.cfg new file mode 100644 index 0000000000..b6a11487b4 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/retrogame_joypad.cfg @@ -0,0 +1,56 @@ +input_driver = "udev" +input_device = "retrogame_joypad" +input_vendor_id = "18507" +input_product_id = "4353" +input_a = "x" +input_a_btn = "1" +input_analog_dpad_mode = "0" +input_b = "z" +input_b_btn = "0" +input_down = "down" +input_down_btn = "14" +input_gun_trigger_mbtn = "1" +input_joypad_index = "0" +input_l = "q" +input_l2_btn = "6" +input_l3_btn = "11" +input_l_btn = "4" +input_l_x_minus_axis = "-0" +input_l_x_plus_axis = "+0" +input_l_y_minus_axis = "-1" +input_l_y_plus_axis = "+1" +input_left = "left" +input_left_btn = "15" +input_mouse_index = "0" +input_r = "w" +input_r2_btn = "7" +input_r3_btn = "12" +input_r_btn = "5" +input_r_x_minus_axis = "-2" +input_r_x_plus_axis = "+2" +input_r_y_minus_axis = "-3" +input_r_y_plus_axis = "+3" +input_right = "right" +input_right_btn = "16" +input_select = "rshift" +input_select_btn = "8" +input_start = "enter" +input_start_btn = "9" +input_up = "up" +input_up_btn = "13" +input_x = "s" +input_x_btn = "2" +input_y = "a" +input_y_btn = "3" +input_enable_hotkey_btn = "8" +input_exit_emulator_btn = "9" +input_screenshot_btn = "nul" +input_pause_toggle_btn = "nul" +input_menu_toggle_btn = "2" +input_fps_toggle_btn = "3" +input_state_slot_increase_btn = "nul" +input_state_slot_decrease_btn = "nul" +input_load_state_btn = "4" +input_save_state_btn = "5" +input_rewind_btn = "6" +input_toggle_fast_forward_btn = "7" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/retrogame_joypad_s1_f2.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/retrogame_joypad_s1_f2.cfg new file mode 100644 index 0000000000..d1d51e107f --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/retrogame_joypad_s1_f2.cfg @@ -0,0 +1,31 @@ +input_driver = "udev" +input_device = "retrogame_joypad_s1_f2" +input_device_display_name = "Retro console gamepad" +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_enable_hotkey_btn = "10" +input_exit_emulator_btn = "9" +input_menu_toggle_btn = "2" +input_fps_toggle_btn = "3" +input_load_state_btn = "4" +input_save_state_btn = "5" +input_rewind_btn = "6" +input_toggle_fast_forward_btn = "7" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/rg552_joypad.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/rg552_joypad.cfg new file mode 100644 index 0000000000..5d15bc8847 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/rg552_joypad.cfg @@ -0,0 +1,47 @@ +input_driver = "udev" +input_device = "rg552_joypad" +input_device_display_name = "Anbernic RG552 Joypad" + +input_b_btn = "0" +input_a_btn = "1" +input_x_btn = "2" +input_y_btn = "3" + +input_select_btn = "8" +input_start_btn = "9" + + +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_up_btn = "13" +input_down_btn = "14" +input_left_btn = "15" +input_right_btn = "16" + +input_l_x_minus_axis = "-0" +input_l_x_plus_axis = "+0" +input_l_y_minus_axis = "-1" +input_l_y_plus_axis = "+1" + +input_r_x_minus_axis = "-2" +input_r_x_plus_axis = "+2" +input_r_y_minus_axis = "-3" +input_r_y_plus_axis = "+3" + +# Hotkeys +input_enable_hotkey_btn = "8" +input_exit_emulator_btn = "9" + +input_menu_toggle_btn = "2" +input_fps_toggle_btn = "3" + +input_load_state_btn = "4" +input_save_state_btn = "5" + +input_rewind_btn = "11" +input_toggle_fast_forward_btn = "12" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/rg_arc_joypad.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/rg_arc_joypad.cfg new file mode 100644 index 0000000000..8850d7c3fa --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/rg_arc_joypad.cfg @@ -0,0 +1,41 @@ +input_driver = "udev" +input_device = "rg_arc_joypad" +input_device_display_name = "Anbernic RG ARC" + + +input_b_btn = "1" +input_b_btn_label = "A" +input_y_btn = "3" +input_y_btn_label = "X" +input_select_btn = "10" +input_start_btn = "11" +input_a_btn = "0" +input_a_btn_label = "B" +input_x_btn = "4" +input_x_btn_label = "Y" +input_l_btn = "6" +input_r_btn = "7" +input_l2_btn = "8" +input_r2_btn = "9" + +input_up_btn = "12" +input_down_btn = 13" +input_left_btn = "14" +input_right_btn = "15" + +input_l3_btn = "5" +input_l3_btn_label = "Z" +input_r3_btn = "2" +input_r3_btn_label = "C" +# Hotkeys +input_enable_hotkey_btn = "10" +input_exit_emulator_btn = "11" + +input_menu_toggle_btn = "4" +input_fps_toggle_btn = "3" + +input_load_state_btn = "6" +input_save_state_btn = "7" + +input_rewind_btn = "8" +input_toggle_fast_forward_btn = "9" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/zed_joystick.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/zed_joystick.cfg new file mode 100644 index 0000000000..1a48b91395 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/gamepads/zed_joystick.cfg @@ -0,0 +1,39 @@ +input_driver = "udev" +input_device = "zed_joystick" +input_b_btn = "1" +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 = "0" +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" +input_enable_hotkey_btn = "8" +input_exit_emulator_btn = "9" +input_screenshot_btn = "nul" +input_pause_toggle_btn = "nul" +input_menu_toggle_btn = "2" +input_fps_toggle_btn = "3" +input_state_slot_increase_btn = "nul" +input_state_slot_decrease_btn = "nul" +input_load_state_btn = "4" +input_save_state_btn = "5" +input_rewind_btn = "6" +input_toggle_fast_forward_btn = "7" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/package.mk b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/package.mk new file mode 100644 index 0000000000..ccd66a1bda --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="retroarch-joypads" +PKG_VERSION="38cf938bba0adbde375972053068f10d955a9d14" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/libretro/retroarch-joypad-autoconfig" +PKG_URL="https://github.com/libretro/retroarch-joypad-autoconfig/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="RetroArch joypad autoconfigs." +PKG_TOOLCHAIN="manual" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/share/libretro/autoconfig + cp -an ${PKG_BUILD}/{linuxraw,sdl2,udev,x,xinput}/*.cfg ${INSTALL}/usr/share/libretro/autoconfig + cp -a ${PKG_DIR}/gamepads/* ${INSTALL}/usr/share/libretro/autoconfig +} + +post_install() { + enable_service tmp-joypads.mount +} diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/system.d/tmp-joypads.mount b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/system.d/tmp-joypads.mount new file mode 100644 index 0000000000..c038bee1bf --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-joypads/system.d/tmp-joypads.mount @@ -0,0 +1,14 @@ +[Unit] +Description=Joypad configs directory +After=systemd-tmpfiles-setup.service +RequiresMountsFor=/storage +DefaultDependencies=no + +[Mount] +What=none +Where=/tmp/joypads +Type=overlay +Options=lowerdir=/usr/share/libretro/autoconfig,upperdir=/storage/joypads,workdir=/storage/.tmp/joypads-workdir + +[Install] +WantedBy=archr.target diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-overlays/package.mk b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-overlays/package.mk new file mode 100644 index 0000000000..df0f501e4b --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/retroarch-overlays/package.mk @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="retroarch-overlays" +PKG_VERSION="ea3f2bf187ae814fdd90431cf796dfe1438cf98c" +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="" +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 -a ${PKG_BUILD}/{borders,ctr,effects,keyboards,misc} ${INSTALL}/usr/share/retroarch-overlays +} diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/scripts/call_achievements_hooks.sh b/projects/ArchR/packages/emulators/libretro/retroarch/scripts/call_achievements_hooks.sh new file mode 100755 index 0000000000..47fc59ffa8 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/scripts/call_achievements_hooks.sh @@ -0,0 +1,19 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile.d/001-functions + +# Get Cheevos LED state +CHEEVOS_LED=$(get_setting "global.retroachievements.leds") +if [ ! -n "${CHEEVOS_LED}" ]; then + set_setting "global.retroachievements.leds" "0" +fi + +if [ "${CHEEVOS_LED}" == "1" ]; then + if [ -f "/usr/lib/autostart/quirks/devices/${QUIRK_DEVICE}/bin/achievements" ]; then + "/usr/lib/autostart/quirks/devices/${QUIRK_DEVICE}/bin/achievements" $* & + elif [ -f "/usr/lib/autostart/quirks/platforms/${HW_DEVICE}/bin/achievements" ]; then + "/usr/lib/autostart/quirks/platforms/${HW_DEVICE}/bin/achievements" $* & + fi +fi diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sounds/ff-victory-orchestra.ogg b/projects/ArchR/packages/emulators/libretro/retroarch/sounds/ff-victory-orchestra.ogg new file mode 100644 index 0000000000..251334118c Binary files /dev/null and b/projects/ArchR/packages/emulators/libretro/retroarch/sounds/ff-victory-orchestra.ogg differ diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sounds/mario-1up.ogg b/projects/ArchR/packages/emulators/libretro/retroarch/sounds/mario-1up.ogg new file mode 100644 index 0000000000..0d5131e566 Binary files /dev/null and b/projects/ArchR/packages/emulators/libretro/retroarch/sounds/mario-1up.ogg differ diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sounds/mario-mushroom.ogg b/projects/ArchR/packages/emulators/libretro/retroarch/sounds/mario-mushroom.ogg new file mode 100644 index 0000000000..97d3bb1c2b Binary files /dev/null and b/projects/ArchR/packages/emulators/libretro/retroarch/sounds/mario-mushroom.ogg differ diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sounds/mgs-alert.ogg b/projects/ArchR/packages/emulators/libretro/retroarch/sounds/mgs-alert.ogg new file mode 100644 index 0000000000..c281e19b1f Binary files /dev/null and b/projects/ArchR/packages/emulators/libretro/retroarch/sounds/mgs-alert.ogg differ diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sounds/ps3-trophy.ogg b/projects/ArchR/packages/emulators/libretro/retroarch/sounds/ps3-trophy.ogg new file mode 100644 index 0000000000..c1e1a5c93c Binary files /dev/null and b/projects/ArchR/packages/emulators/libretro/retroarch/sounds/ps3-trophy.ogg differ diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sounds/sonic-ring.ogg b/projects/ArchR/packages/emulators/libretro/retroarch/sounds/sonic-ring.ogg new file mode 100644 index 0000000000..471434cf50 Binary files /dev/null and b/projects/ArchR/packages/emulators/libretro/retroarch/sounds/sonic-ring.ogg differ diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sounds/xbox360-achievement.ogg b/projects/ArchR/packages/emulators/libretro/retroarch/sounds/xbox360-achievement.ogg new file mode 100644 index 0000000000..35265e4d53 Binary files /dev/null and b/projects/ArchR/packages/emulators/libretro/retroarch/sounds/xbox360-achievement.ogg differ diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sounds/zelda-secret.ogg b/projects/ArchR/packages/emulators/libretro/retroarch/sounds/zelda-secret.ogg new file mode 100644 index 0000000000..afce6a046c Binary files /dev/null and b/projects/ArchR/packages/emulators/libretro/retroarch/sounds/zelda-secret.ogg differ diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/H700/TATE-MAME 2003-Plus.rmp b/projects/ArchR/packages/emulators/libretro/retroarch/sources/H700/TATE-MAME 2003-Plus.rmp new file mode 100755 index 0000000000..366e47afad --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/H700/TATE-MAME 2003-Plus.rmp @@ -0,0 +1,27 @@ +input_libretro_device_p1 = "1" +input_libretro_device_p2 = "1" +input_libretro_device_p3 = "1" +input_libretro_device_p4 = "1" +input_libretro_device_p5 = "1" +input_player1_analog_dpad_mode = "1" +input_player1_btn_down = "6" +input_player1_btn_left = "4" +input_player1_btn_right = "5" +input_player1_btn_up = "7" +input_player1_stk_l_x+ = "5" +input_player1_stk_l_x- = "4" +input_player1_stk_l_y+ = "6" +input_player1_stk_l_y- = "7" +input_player1_stk_r_x+ = "5" +input_player1_stk_r_x- = "4" +input_player1_stk_r_y+ = "6" +input_player1_stk_r_y- = "7" +input_player2_analog_dpad_mode = "0" +input_player3_analog_dpad_mode = "0" +input_player4_analog_dpad_mode = "0" +input_player5_analog_dpad_mode = "0" +input_remap_port_p1 = "0" +input_remap_port_p2 = "1" +input_remap_port_p3 = "2" +input_remap_port_p4 = "3" +input_remap_port_p5 = "4" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/H700/retroarch-core-options.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/H700/retroarch-core-options.cfg new file mode 100755 index 0000000000..8ccae69cf1 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/H700/retroarch-core-options.cfg @@ -0,0 +1,153 @@ +mupen64plus-alt-map = "False" +mupen64plus-aspect = "4:3" +mupen64plus-astick-deadzone = "15" +mupen64plus-astick-sensitivity = "100" +mupen64plus-BackgroundMode = "Stripped" +mupen64plus-BilinearMode = "standard" +mupen64plus-CorrectTexrectCoords = "Auto" +mupen64plus-CountPerOp = "0" +mupen64plus-CountPerOpDenomPot = "0" +mupen64plus-cpucore = "dynamic_recompiler" +mupen64plus-d-cbutton = "C3" +mupen64plus-DitheringPattern = "True" +mupen64plus-DitheringQuantization = "True" +mupen64plus-EnableCopyAuxToRDRAM = "True" +mupen64plus-EnableCopyColorToRDRAM = "Async" +mupen64plus-EnableCopyDepthToRDRAM = "Software" +mupen64plus-EnableEnhancedHighResStorage = "False" +mupen64plus-EnableEnhancedTextureStorage = "False" +mupen64plus-EnableFBEmulation = "True" +mupen64plus-EnableFragmentDepthWrite = "False" +mupen64plus-EnableHiResAltCRC = "False" +mupen64plus-EnableHWLighting = "True" +mupen64plus-EnableInaccurateTextureCoordinates = "False" +mupen64plus-EnableLegacyBlending = "False" +mupen64plus-EnableLODEmulation = "True" +mupen64plus-EnableNativeResFactor = "1" +mupen64plus-EnableNativeResTexrects = "Optimized" +mupen64plus-EnableOverscan = "Enabled" +mupen64plus-EnableTexCoordBounds = "False" +mupen64plus-EnableTextureCache = "True" +mupen64plus-ForceDisableExtraMem = "False" +mupen64plus-FrameDuping = "True" +mupen64plus-Framerate = "Original" +mupen64plus-FXAA = "0" +mupen64plus-GLideN64IniBehaviour = "late" +mupen64plus-HybridFilter = "True" +mupen64plus-IgnoreTLBExceptions = "False" +mupen64plus-l-cbutton = "C2" +mupen64plus-MaxHiResTxVramLimit = "0" +mupen64plus-MaxTxCacheSize = "8000" +mupen64plus-MultiSampling = "0" +mupen64plus-OverscanBottom = "0" +mupen64plus-OverscanLeft = "0" +mupen64plus-OverscanRight = "0" +mupen64plus-OverscanTop = "0" +mupen64plus-pak1 = "memory" +mupen64plus-pak2 = "none" +mupen64plus-pak3 = "none" +mupen64plus-pak4 = "none" +mupen64plus-r-cbutton = "C1" +mupen64plus-rdp-plugin = "gliden64" +mupen64plus-RDRAMImageDitheringMode = "BlueNoise" +mupen64plus-rsp-plugin = "hle" +mupen64plus-ThreadedRenderer = "True" +mupen64plus-txCacheCompression = "True" +mupen64plus-txEnhancementMode = "None" +mupen64plus-txFilterIgnoreBG = "True" +mupen64plus-txFilterMode = "None" +mupen64plus-txHiresEnable = "False" +mupen64plus-txHiresFullAlphaChannel = "False" +mupen64plus-u-cbutton = "C4" +mupen64plus-virefresh = "Auto" +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_type = "disabled" +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" +flycast_auto_skip_frame = "normal" +opera_swi_hle = "enabled" +opera_dsp_threaded = "enabled" +opera_madam_matrix_engine = "software" +puae_deadzone = "25" +melonds_screen_layout = "Left/Right" +melonds_swapscreen_mode = "Toggle" +melonds_threaded_renderer = "enabled" +melonds_touch_mode = "Joystick" +virtualjaguar_bios = "enabled" +virtualjaguar_usefastblitter = "enabled" +swanstation_GPU_Renderer = "Software" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/H700/retroarch.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/H700/retroarch.cfg new file mode 100755 index 0000000000..a893ac85ab --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/H700/retroarch.cfg @@ -0,0 +1,817 @@ +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_menu_bgm = "false" +audio_enable_menu_cancel = "false" +audio_enable_menu = "false" +audio_enable_menu_notice = "false" +audio_enable_menu_ok = "false" +audio_enable = "true" +audio_fastforward_mute = "false" +audio_filter_dir = "~/.config/retroarch/filters/audio" +audio_max_timing_skew = "0.049999" +audio_mixer_mute_enable = "false" +audio_mixer_volume = "0.000000" +audio_mute_enable = "false" +audio_out_rate = "44100" +audio_rate_control_delta = "0.004999" +audio_rate_control = "true" +audio_resampler_quality = "2" +audio_resampler = "sinc" +audio_sync = "true" +audio_volume = "0.000000" +auto_overrides_enable = "true" +auto_remaps_enable = "true" +autosave_interval = "10" +auto_screenshot_filename = "true" +auto_shaders_enable = "true" +block_sram_overwrite = "false" +bluetooth_driver = "null" +builtin_imageviewer_enable = "false" +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 = "false" +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_aggregate = "false" +content_runtime_log = "true" +content_show_add_entry = "2" +content_show_add = "true" +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_password = "" +content_show_settings = "true" +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 = "powersave" +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" +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" +framecount_show = "false" +frame_time_counter_reset_after_fastforwarding = "false" +frame_time_counter_reset_after_load_state = "false" +frame_time_counter_reset_after_save_state = "false" +frontend_log_level = "1" +game_specific_options = "true" +gamma_correction = "0" +global_core_options = "false" +history_list_enable = "true" +input_ai_service_axis = "nul" +input_ai_service_btn = "nul" +input_ai_service_mbtn = "nul" +input_ai_service = "nul" +input_analog_deadzone = "0.000000" +input_analog_sensitivity = "1.500000" +input_audio_mute_axis = "nul" +input_audio_mute_btn = "nul" +input_audio_mute = "f9" +input_audio_mute_mbtn = "nul" +input_autodetect_enable = "true" +input_auto_game_focus = "0" +input_auto_mouse_grab = "false" +input_axis_threshold = "0.500000" +input_bind_hold = "2" +input_bind_timeout = "5" +input_cheat_index_minus_axis = "nul" +input_cheat_index_minus_btn = "nul" +input_cheat_index_minus_mbtn = "nul" +input_cheat_index_minus = "t" +input_cheat_index_plus_axis = "nul" +input_cheat_index_plus_btn = "nul" +input_cheat_index_plus_mbtn = "nul" +input_cheat_index_plus = "y" +input_cheat_toggle_axis = "nul" +input_cheat_toggle_btn = "nul" +input_cheat_toggle_mbtn = "nul" +input_cheat_toggle = "u" +input_close_content_axis = "nul" +input_close_content_btn = "nul" +input_close_content_mbtn = "nul" +input_close_content = "nul" +input_descriptor_hide_unbound = "false" +input_descriptor_label_show = "true" +input_desktop_menu_toggle_axis = "nul" +input_desktop_menu_toggle_btn = "nul" +input_desktop_menu_toggle = "f5" +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_axis = "nul" +input_disk_eject_toggle_btn = "nul" +input_disk_eject_toggle_mbtn = "nul" +input_disk_eject_toggle = "nul" +input_disk_next_axis = "nul" +input_disk_next_btn = "nul" +input_disk_next_mbtn = "nul" +input_disk_next = "nul" +input_disk_prev_axis = "nul" +input_disk_prev_btn = "nul" +input_disk_prev_mbtn = "nul" +input_disk_prev = "nul" +input_driver = "udev" +input_duty_cycle = "3" +input_enable_hotkey_axis = "nul" +input_enable_hotkey_mbtn = "nul" +input_enable_hotkey = "nul" +input_exit_emulator_axis = "nul" +input_exit_emulator_btn = "9" +input_exit_emulator = "escape" +input_exit_emulator_mbtn = "nul" +input_fps_toggle_axis = "nul" +input_fps_toggle = "f3" +input_fps_toggle_mbtn = "nul" +input_frame_advance_axis = "nul" +input_frame_advance_btn = "nul" +input_frame_advance = "k" +input_frame_advance_mbtn = "nul" +input_game_focus_toggle_axis = "nul" +input_game_focus_toggle_btn = "nul" +input_game_focus_toggle_mbtn = "nul" +input_game_focus_toggle = "scroll_lock" +input_grab_mouse_toggle_axis = "nul" +input_grab_mouse_toggle_btn = "nul" +input_grab_mouse_toggle = "f11" +input_grab_mouse_toggle_mbtn = "nul" +input_hold_fast_forward_axis = "nul" +input_hold_fast_forward_btn = "nul" +input_hold_fast_forward = "l" +input_hold_fast_forward_mbtn = "nul" +input_hold_slowmotion_axis = "nul" +input_hold_slowmotion_btn = "nul" +input_hold_slowmotion = "e" +input_hold_slowmotion_mbtn = "nul" +input_hotkey_block_delay = "5" +input_joypad_driver = "udev" +input_keyboard_layout = "" +input_libretro_device_p10 = "1" +input_libretro_device_p1 = "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_axis = "nul" +input_load_state_btn = "4" +input_load_state = "f4" +input_load_state_mbtn = "nul" +input_max_users = "5" +input_menu_toggle_axis = "nul" +input_menu_toggle = "f1" +input_menu_toggle_gamepad_combo = "0" +input_menu_toggle_mbtn = "nul" +input_movie_record_toggle_axis = "nul" +input_movie_record_toggle_btn = "nul" +input_movie_record_toggle_mbtn = "nul" +input_movie_record_toggle = "o" +input_netplay_game_watch_axis = "nul" +input_netplay_game_watch_btn = "nul" +input_netplay_game_watch = "i" +input_netplay_game_watch_mbtn = "nul" +input_netplay_host_toggle_axis = "nul" +input_netplay_host_toggle_btn = "nul" +input_netplay_host_toggle_mbtn = "nul" +input_netplay_host_toggle = "nul" +input_nowinkey_enable = "false" +input_osk_toggle_axis = "nul" +input_osk_toggle_btn = "nul" +input_osk_toggle = "f12" +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_autopreferred = "true" +input_overlay_enable = "false" +input_overlay_hide_in_menu = "true" +input_overlay_hide_when_gamepad_connected = "false" +input_overlay_next_axis = "nul" +input_overlay_next_btn = "nul" +input_overlay_next_mbtn = "nul" +input_overlay_next = "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_axis = "nul" +input_pause_toggle_btn = "nul" +input_pause_toggle_mbtn = "nul" +input_pause_toggle = "p" +input_poll_type_behavior = "2" +input_quit_gamepad_combo = "0" +input_recording_toggle_axis = "nul" +input_recording_toggle_btn = "nul" +input_recording_toggle_mbtn = "nul" +input_recording_toggle = "nul" +input_remap_binds_enable = "true" +input_remapping_directory = "~/remappings" +input_reset_axis = "nul" +input_reset_btn = "nul" +input_reset = "h" +input_reset_mbtn = "nul" +input_rewind_axis = "nul" +input_rewind_btn = "6" +input_rewind_mbtn = "nul" +input_rewind = "r" +input_rumble_gain = "100" +input_runahead_toggle_axis = "nul" +input_runahead_toggle_btn = "nul" +input_runahead_toggle_mbtn = "nul" +input_runahead_toggle = "nul" +input_save_state_axis = "nul" +input_save_state_btn = "5" +input_save_state = "f2" +input_save_state_mbtn = "nul" +input_screenshot_axis = "nul" +input_screenshot_btn = "nul" +input_screenshot = "f8" +input_screenshot_mbtn = "nul" +input_send_debug_info_axis = "nul" +input_send_debug_info_btn = "nul" +input_send_debug_info = "f10" +input_send_debug_info_mbtn = "nul" +input_sensors_enable = "true" +input_shader_next_axis = "nul" +input_shader_next_btn = "nul" +input_shader_next = "m" +input_shader_next_mbtn = "nul" +input_shader_prev_axis = "nul" +input_shader_prev_btn = "nul" +input_shader_prev_mbtn = "nul" +input_shader_prev = "n" +input_state_slot_decrease_axis = "nul" +input_state_slot_decrease_btn = "nul" +input_state_slot_decrease = "f6" +input_state_slot_decrease_mbtn = "nul" +input_state_slot_increase_axis = "nul" +input_state_slot_increase_btn = "nul" +input_state_slot_increase = "f7" +input_state_slot_increase_mbtn = "nul" +input_streaming_toggle_axis = "nul" +input_streaming_toggle_btn = "nul" +input_streaming_toggle_mbtn = "nul" +input_streaming_toggle = "nul" +input_toggle_fast_forward_axis = "nul" +input_toggle_fast_forward_btn = "7" +input_toggle_fast_forward_mbtn = "nul" +input_toggle_fast_forward = "space" +input_toggle_fullscreen_axis = "nul" +input_toggle_fullscreen_btn = "nul" +input_toggle_fullscreen = "f" +input_toggle_fullscreen_mbtn = "nul" +input_toggle_slowmotion_axis = "nul" +input_toggle_slowmotion_btn = "nul" +input_toggle_slowmotion_mbtn = "nul" +input_toggle_slowmotion = "nul" +input_touch_scale = "1" +input_turbo_default_button = "0" +input_turbo_mode = "0" +input_turbo_period = "6" +input_volume_down_axis = "nul" +input_volume_down_btn = "nul" +input_volume_down_mbtn = "nul" +input_volume_down = "subtract" +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_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.300000" +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_animation = "false" +menu_show_load_content = "true" +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_thumbnails = "3" +menu_thumbnail_upscale_threshold = "0" +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 = "0.400000" +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_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_p1 = "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_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_p1 = "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_duration = "2" +notification_show_screenshot = "false" +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 = "" +playlist_directory = "~/playlists" +playlist_entry_remove_enable = "1" +playlist_entry_remove = "false" +playlist_entry_rename = "false" +playlist_fuzzy_archive_match = "false" +playlist_names = "" +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" +savestates_in_content_dir = "false" +savestate_thumbnail_enable = "true" +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_interface = "true" +settings_show_user = "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 = "glcore" +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 = "640" +video_fullscreen_y = "480" +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 = "480" +video_window_auto_width_max = "640" +video_window_custom_size_enable = "false" +video_windowed_fullscreen = "false" +video_windowed_position_height = "720" +video_windowed_position_width = "1280" +video_windowed_position_x = "0" +video_windowed_position_y = "0" +video_window_opacity = "100" +video_window_save_positions = "false" +video_window_show_decorations = "true" +vrr_runloop_enable = "false" +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/projects/ArchR/packages/emulators/libretro/retroarch/sources/H700/retroarch32bit-append.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/H700/retroarch32bit-append.cfg new file mode 100755 index 0000000000..343124c254 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/H700/retroarch32bit-append.cfg @@ -0,0 +1,3 @@ +audio_filter_dir = "/usr/share/retroarch/filters/32bit/audio" +video_filter_dir = "/usr/share/retroarch/filters/32bit/video" +libretro_directory = /usr/lib32/libretro diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/H700/retroarch64bit-append.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/H700/retroarch64bit-append.cfg new file mode 100755 index 0000000000..b6cbf68312 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/H700/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" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3326/TATE-MAME 2003-Plus.rmp b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3326/TATE-MAME 2003-Plus.rmp new file mode 100755 index 0000000000..366e47afad --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3326/TATE-MAME 2003-Plus.rmp @@ -0,0 +1,27 @@ +input_libretro_device_p1 = "1" +input_libretro_device_p2 = "1" +input_libretro_device_p3 = "1" +input_libretro_device_p4 = "1" +input_libretro_device_p5 = "1" +input_player1_analog_dpad_mode = "1" +input_player1_btn_down = "6" +input_player1_btn_left = "4" +input_player1_btn_right = "5" +input_player1_btn_up = "7" +input_player1_stk_l_x+ = "5" +input_player1_stk_l_x- = "4" +input_player1_stk_l_y+ = "6" +input_player1_stk_l_y- = "7" +input_player1_stk_r_x+ = "5" +input_player1_stk_r_x- = "4" +input_player1_stk_r_y+ = "6" +input_player1_stk_r_y- = "7" +input_player2_analog_dpad_mode = "0" +input_player3_analog_dpad_mode = "0" +input_player4_analog_dpad_mode = "0" +input_player5_analog_dpad_mode = "0" +input_remap_port_p1 = "0" +input_remap_port_p2 = "1" +input_remap_port_p3 = "2" +input_remap_port_p4 = "3" +input_remap_port_p5 = "4" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3326/retroarch-core-options.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3326/retroarch-core-options.cfg new file mode 100755 index 0000000000..0bcefde0af --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3326/retroarch-core-options.cfg @@ -0,0 +1,152 @@ +mupen64plus-alt-map = "False" +mupen64plus-aspect = "4:3" +mupen64plus-astick-deadzone = "15" +mupen64plus-astick-sensitivity = "100" +mupen64plus-BackgroundMode = "Stripped" +mupen64plus-BilinearMode = "standard" +mupen64plus-CorrectTexrectCoords = "Auto" +mupen64plus-CountPerOp = "0" +mupen64plus-CountPerOpDenomPot = "0" +mupen64plus-cpucore = "dynamic_recompiler" +mupen64plus-d-cbutton = "C3" +mupen64plus-DitheringPattern = "True" +mupen64plus-DitheringQuantization = "True" +mupen64plus-EnableCopyAuxToRDRAM = "True" +mupen64plus-EnableCopyColorToRDRAM = "Async" +mupen64plus-EnableCopyDepthToRDRAM = "Software" +mupen64plus-EnableEnhancedHighResStorage = "False" +mupen64plus-EnableEnhancedTextureStorage = "False" +mupen64plus-EnableFBEmulation = "True" +mupen64plus-EnableFragmentDepthWrite = "False" +mupen64plus-EnableHiResAltCRC = "False" +mupen64plus-EnableHWLighting = "True" +mupen64plus-EnableInaccurateTextureCoordinates = "False" +mupen64plus-EnableLegacyBlending = "False" +mupen64plus-EnableLODEmulation = "True" +mupen64plus-EnableNativeResFactor = "1" +mupen64plus-EnableNativeResTexrects = "Optimized" +mupen64plus-EnableOverscan = "Enabled" +mupen64plus-EnableTexCoordBounds = "False" +mupen64plus-EnableTextureCache = "True" +mupen64plus-ForceDisableExtraMem = "False" +mupen64plus-FrameDuping = "True" +mupen64plus-Framerate = "Original" +mupen64plus-FXAA = "0" +mupen64plus-GLideN64IniBehaviour = "late" +mupen64plus-HybridFilter = "True" +mupen64plus-IgnoreTLBExceptions = "False" +mupen64plus-l-cbutton = "C2" +mupen64plus-MaxHiResTxVramLimit = "0" +mupen64plus-MaxTxCacheSize = "8000" +mupen64plus-MultiSampling = "0" +mupen64plus-OverscanBottom = "0" +mupen64plus-OverscanLeft = "0" +mupen64plus-OverscanRight = "0" +mupen64plus-OverscanTop = "0" +mupen64plus-pak1 = "memory" +mupen64plus-pak2 = "none" +mupen64plus-pak3 = "none" +mupen64plus-pak4 = "none" +mupen64plus-r-cbutton = "C1" +mupen64plus-rdp-plugin = "gliden64" +mupen64plus-RDRAMImageDitheringMode = "BlueNoise" +mupen64plus-rsp-plugin = "hle" +mupen64plus-ThreadedRenderer = "True" +mupen64plus-txCacheCompression = "True" +mupen64plus-txEnhancementMode = "None" +mupen64plus-txFilterIgnoreBG = "True" +mupen64plus-txFilterMode = "None" +mupen64plus-txHiresEnable = "False" +mupen64plus-txHiresFullAlphaChannel = "False" +mupen64plus-u-cbutton = "C4" +mupen64plus-virefresh = "Auto" +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_type = "disabled" +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 = "enabled" +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" +flycast_auto_skip_frame = "normal" +opera_swi_hle = "enabled" +opera_dsp_threaded = "enabled" +opera_madam_matrix_engine = "software" +puae_deadzone = "25" +melonds_screen_layout = "Left/Right" +melonds_swapscreen_mode = "Toggle" +melonds_threaded_renderer = "enabled" +melonds_touch_mode = "Joystick" +virtualjaguar_bios = "enabled" +virtualjaguar_usefastblitter = "enabled" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3326/retroarch.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3326/retroarch.cfg new file mode 100755 index 0000000000..e2e893128c --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3326/retroarch.cfg @@ -0,0 +1,822 @@ +accessibility_enable = "false" +accessibility_narrator_speech_speed = "5" +ai_service_enable = "false" +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_menu_bgm = "false" +audio_enable_menu_cancel = "false" +audio_enable_menu = "false" +audio_enable_menu_notice = "false" +audio_enable_menu_ok = "false" +audio_enable = "true" +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_delta = "0.004999" +audio_rate_control = "true" +audio_resampler_quality = "2" +audio_resampler = "sinc" +audio_sync = "true" +audio_volume = "0.000000" +auto_overrides_enable = "true" +auto_remaps_enable = "true" +autosave_interval = "0" +auto_screenshot_filename = "true" +auto_shaders_enable = "true" +block_sram_overwrite = "false" +bluetooth_driver = "null" +builtin_imageviewer_enable = "false" +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 = "false" +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_aggregate = "false" +content_runtime_log = "false" +content_show_add_entry = "2" +content_show_add = "true" +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_password = "" +content_show_settings = "true" +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 = "interactive" +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" +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" +framecount_show = "false" +frame_time_counter_reset_after_fastforwarding = "false" +frame_time_counter_reset_after_load_state = "false" +frame_time_counter_reset_after_save_state = "false" +frontend_log_level = "1" +game_specific_options = "true" +gamma_correction = "0" +global_core_options = "false" +history_list_enable = "true" +input_ai_service_axis = "nul" +input_ai_service_btn = "nul" +input_ai_service_mbtn = "nul" +input_ai_service = "nul" +input_analog_deadzone = "0.000000" +input_analog_sensitivity = "1.500000" +input_audio_mute_axis = "nul" +input_audio_mute_btn = "nul" +input_audio_mute = "f9" +input_audio_mute_mbtn = "nul" +input_autodetect_enable = "true" +input_auto_game_focus = "0" +input_auto_mouse_grab = "false" +input_axis_threshold = "0.500000" +input_bind_hold = "2" +input_bind_timeout = "5" +input_cheat_index_minus_axis = "nul" +input_cheat_index_minus_btn = "nul" +input_cheat_index_minus_mbtn = "nul" +input_cheat_index_minus = "t" +input_cheat_index_plus_axis = "nul" +input_cheat_index_plus_btn = "nul" +input_cheat_index_plus_mbtn = "nul" +input_cheat_index_plus = "y" +input_cheat_toggle_axis = "nul" +input_cheat_toggle_btn = "nul" +input_cheat_toggle_mbtn = "nul" +input_cheat_toggle = "u" +input_close_content_axis = "nul" +input_close_content_btn = "nul" +input_close_content_mbtn = "nul" +input_close_content = "nul" +input_descriptor_hide_unbound = "false" +input_descriptor_label_show = "true" +input_desktop_menu_toggle_axis = "nul" +input_desktop_menu_toggle_btn = "nul" +input_desktop_menu_toggle = "f5" +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_axis = "nul" +input_disk_eject_toggle_btn = "nul" +input_disk_eject_toggle_mbtn = "nul" +input_disk_eject_toggle = "nul" +input_disk_next_axis = "nul" +input_disk_next_btn = "nul" +input_disk_next_mbtn = "nul" +input_disk_next = "nul" +input_disk_prev_axis = "nul" +input_disk_prev_btn = "nul" +input_disk_prev_mbtn = "nul" +input_disk_prev = "nul" +input_driver = "udev" +input_duty_cycle = "3" +input_enable_hotkey_axis = "nul" +input_enable_hotkey_btn = "8" +input_enable_hotkey_mbtn = "nul" +input_enable_hotkey = "nul" +input_exit_emulator_axis = "nul" +input_exit_emulator_btn = "9" +input_exit_emulator = "escape" +input_exit_emulator_mbtn = "nul" +input_fps_toggle_axis = "nul" +input_fps_toggle_btn = "3" +input_fps_toggle = "f3" +input_fps_toggle_mbtn = "nul" +input_frame_advance_axis = "nul" +input_frame_advance_btn = "nul" +input_frame_advance = "k" +input_frame_advance_mbtn = "nul" +input_game_focus_toggle_axis = "nul" +input_game_focus_toggle_btn = "nul" +input_game_focus_toggle_mbtn = "nul" +input_game_focus_toggle = "scroll_lock" +input_grab_mouse_toggle_axis = "nul" +input_grab_mouse_toggle_btn = "nul" +input_grab_mouse_toggle = "f11" +input_grab_mouse_toggle_mbtn = "nul" +input_hold_fast_forward_axis = "nul" +input_hold_fast_forward_btn = "nul" +input_hold_fast_forward = "l" +input_hold_fast_forward_mbtn = "nul" +input_hold_slowmotion_axis = "nul" +input_hold_slowmotion_btn = "nul" +input_hold_slowmotion = "e" +input_hold_slowmotion_mbtn = "nul" +input_hotkey_block_delay = "5" +input_joypad_driver = "udev" +input_keyboard_layout = "" +input_libretro_device_p10 = "1" +input_libretro_device_p1 = "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_axis = "nul" +input_load_state_btn = "4" +input_load_state = "f4" +input_load_state_mbtn = "nul" +input_max_users = "5" +input_menu_toggle_axis = "nul" +input_menu_toggle_btn = "2" +input_menu_toggle = "f1" +input_menu_toggle_gamepad_combo = "2" +input_menu_toggle_mbtn = "nul" +input_movie_record_toggle_axis = "nul" +input_movie_record_toggle_btn = "nul" +input_movie_record_toggle_mbtn = "nul" +input_movie_record_toggle = "o" +input_netplay_game_watch_axis = "nul" +input_netplay_game_watch_btn = "nul" +input_netplay_game_watch = "i" +input_netplay_game_watch_mbtn = "nul" +input_netplay_host_toggle_axis = "nul" +input_netplay_host_toggle_btn = "nul" +input_netplay_host_toggle_mbtn = "nul" +input_netplay_host_toggle = "nul" +input_nowinkey_enable = "false" +input_osk_toggle_axis = "nul" +input_osk_toggle_btn = "nul" +input_osk_toggle = "f12" +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_autopreferred = "true" +input_overlay_enable = "false" +input_overlay_hide_in_menu = "true" +input_overlay_hide_when_gamepad_connected = "false" +input_overlay_next_axis = "nul" +input_overlay_next_btn = "nul" +input_overlay_next_mbtn = "nul" +input_overlay_next = "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_axis = "nul" +input_pause_toggle_btn = "nul" +input_pause_toggle_mbtn = "nul" +input_pause_toggle = "p" +input_poll_type_behavior = "2" +input_quit_gamepad_combo = "0" +input_recording_toggle_axis = "nul" +input_recording_toggle_btn = "nul" +input_recording_toggle_mbtn = "nul" +input_recording_toggle = "nul" +input_remap_binds_enable = "true" +input_remapping_directory = "~/remappings" +input_reset_axis = "nul" +input_reset_btn = "nul" +input_reset = "h" +input_reset_mbtn = "nul" +input_rewind_axis = "nul" +input_rewind_btn = "6" +input_rewind_mbtn = "nul" +input_rewind = "r" +input_rumble_gain = "100" +input_runahead_toggle_axis = "nul" +input_runahead_toggle_btn = "nul" +input_runahead_toggle_mbtn = "nul" +input_runahead_toggle = "nul" +input_save_state_axis = "nul" +input_save_state_btn = "5" +input_save_state = "f2" +input_save_state_mbtn = "nul" +input_screenshot_axis = "nul" +input_screenshot_btn = "nul" +input_screenshot = "f8" +input_screenshot_mbtn = "nul" +input_send_debug_info_axis = "nul" +input_send_debug_info_btn = "nul" +input_send_debug_info = "f10" +input_send_debug_info_mbtn = "nul" +input_sensors_enable = "true" +input_shader_next_axis = "nul" +input_shader_next_btn = "nul" +input_shader_next = "m" +input_shader_next_mbtn = "nul" +input_shader_prev_axis = "nul" +input_shader_prev_btn = "nul" +input_shader_prev_mbtn = "nul" +input_shader_prev = "n" +input_state_slot_decrease_axis = "nul" +input_state_slot_decrease_btn = "nul" +input_state_slot_decrease = "f6" +input_state_slot_decrease_mbtn = "nul" +input_state_slot_increase_axis = "nul" +input_state_slot_increase_btn = "nul" +input_state_slot_increase = "f7" +input_state_slot_increase_mbtn = "nul" +input_streaming_toggle_axis = "nul" +input_streaming_toggle_btn = "nul" +input_streaming_toggle_mbtn = "nul" +input_streaming_toggle = "nul" +input_toggle_fast_forward_axis = "nul" +input_toggle_fast_forward_btn = "7" +input_toggle_fast_forward_mbtn = "nul" +input_toggle_fast_forward = "space" +input_toggle_fullscreen_axis = "nul" +input_toggle_fullscreen_btn = "nul" +input_toggle_fullscreen = "f" +input_toggle_fullscreen_mbtn = "nul" +input_toggle_slowmotion_axis = "nul" +input_toggle_slowmotion_btn = "nul" +input_toggle_slowmotion_mbtn = "nul" +input_toggle_slowmotion = "nul" +input_touch_scale = "1" +input_turbo_default_button = "0" +input_turbo_mode = "0" +input_turbo_period = "6" +input_volume_down_axis = "nul" +input_volume_down_btn = "nul" +input_volume_down_mbtn = "nul" +input_volume_down = "subtract" +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 = "false" +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 = "rgui" +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 = "1.000000" +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 = "1" +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_animation = "false" +menu_show_load_content = "true" +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_thumbnails = "3" +menu_thumbnail_upscale_threshold = "0" +menu_ticker_smooth = "true" +menu_ticker_speed = "2.000000" +menu_ticker_type = "0" +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 = "0.300000" +menu_widget_scale_auto = "false" +menu_widget_scale_factor = "0.350000" +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_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_p1 = "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_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_p1 = "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_duration = "2" +notification_show_screenshot = "false" +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 = "" +playlist_directory = "~/playlists" +playlist_entry_remove_enable = "1" +playlist_entry_remove = "false" +playlist_entry_rename = "false" +playlist_fuzzy_archive_match = "false" +playlist_names = "" +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" +savestates_in_content_dir = "false" +savestate_thumbnail_enable = "true" +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_interface = "true" +settings_show_user = "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 = "320" +video_window_auto_width_max = "480" +video_window_custom_size_enable = "false" +video_windowed_fullscreen = "false" +video_windowed_position_height = "720" +video_windowed_position_width = "1280" +video_windowed_position_x = "0" +video_windowed_position_y = "0" +video_window_opacity = "100" +video_window_save_positions = "false" +video_window_show_decorations = "true" +vrr_runloop_enable = "false" +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/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3326/retroarch32bit-append.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3326/retroarch32bit-append.cfg new file mode 100755 index 0000000000..343124c254 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3326/retroarch32bit-append.cfg @@ -0,0 +1,3 @@ +audio_filter_dir = "/usr/share/retroarch/filters/32bit/audio" +video_filter_dir = "/usr/share/retroarch/filters/32bit/video" +libretro_directory = /usr/lib32/libretro diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3326/retroarch64bit-append.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3326/retroarch64bit-append.cfg new file mode 100755 index 0000000000..b6cbf68312 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3326/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" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3399/TATE-MAME 2003-Plus.rmp b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3399/TATE-MAME 2003-Plus.rmp new file mode 100755 index 0000000000..366e47afad --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3399/TATE-MAME 2003-Plus.rmp @@ -0,0 +1,27 @@ +input_libretro_device_p1 = "1" +input_libretro_device_p2 = "1" +input_libretro_device_p3 = "1" +input_libretro_device_p4 = "1" +input_libretro_device_p5 = "1" +input_player1_analog_dpad_mode = "1" +input_player1_btn_down = "6" +input_player1_btn_left = "4" +input_player1_btn_right = "5" +input_player1_btn_up = "7" +input_player1_stk_l_x+ = "5" +input_player1_stk_l_x- = "4" +input_player1_stk_l_y+ = "6" +input_player1_stk_l_y- = "7" +input_player1_stk_r_x+ = "5" +input_player1_stk_r_x- = "4" +input_player1_stk_r_y+ = "6" +input_player1_stk_r_y- = "7" +input_player2_analog_dpad_mode = "0" +input_player3_analog_dpad_mode = "0" +input_player4_analog_dpad_mode = "0" +input_player5_analog_dpad_mode = "0" +input_remap_port_p1 = "0" +input_remap_port_p2 = "1" +input_remap_port_p3 = "2" +input_remap_port_p4 = "3" +input_remap_port_p5 = "4" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3399/retroarch-core-options.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3399/retroarch-core-options.cfg new file mode 100755 index 0000000000..0bcbaa2661 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3399/retroarch-core-options.cfg @@ -0,0 +1,152 @@ +mupen64plus-alt-map = "False" +mupen64plus-aspect = "4:3" +mupen64plus-astick-deadzone = "15" +mupen64plus-astick-sensitivity = "100" +mupen64plus-BackgroundMode = "Stripped" +mupen64plus-BilinearMode = "standard" +mupen64plus-CorrectTexrectCoords = "Auto" +mupen64plus-CountPerOp = "0" +mupen64plus-CountPerOpDenomPot = "0" +mupen64plus-cpucore = "dynamic_recompiler" +mupen64plus-d-cbutton = "C3" +mupen64plus-DitheringPattern = "True" +mupen64plus-DitheringQuantization = "True" +mupen64plus-EnableCopyAuxToRDRAM = "True" +mupen64plus-EnableCopyColorToRDRAM = "Async" +mupen64plus-EnableCopyDepthToRDRAM = "Software" +mupen64plus-EnableEnhancedHighResStorage = "False" +mupen64plus-EnableEnhancedTextureStorage = "False" +mupen64plus-EnableFBEmulation = "True" +mupen64plus-EnableFragmentDepthWrite = "False" +mupen64plus-EnableHiResAltCRC = "False" +mupen64plus-EnableHWLighting = "True" +mupen64plus-EnableInaccurateTextureCoordinates = "False" +mupen64plus-EnableLegacyBlending = "False" +mupen64plus-EnableLODEmulation = "True" +mupen64plus-EnableNativeResFactor = "1" +mupen64plus-EnableNativeResTexrects = "Optimized" +mupen64plus-EnableOverscan = "Enabled" +mupen64plus-EnableTexCoordBounds = "False" +mupen64plus-EnableTextureCache = "True" +mupen64plus-ForceDisableExtraMem = "False" +mupen64plus-FrameDuping = "True" +mupen64plus-Framerate = "Original" +mupen64plus-FXAA = "0" +mupen64plus-GLideN64IniBehaviour = "late" +mupen64plus-HybridFilter = "True" +mupen64plus-IgnoreTLBExceptions = "False" +mupen64plus-l-cbutton = "C2" +mupen64plus-MaxHiResTxVramLimit = "0" +mupen64plus-MaxTxCacheSize = "8000" +mupen64plus-MultiSampling = "0" +mupen64plus-OverscanBottom = "0" +mupen64plus-OverscanLeft = "0" +mupen64plus-OverscanRight = "0" +mupen64plus-OverscanTop = "0" +mupen64plus-pak1 = "memory" +mupen64plus-pak2 = "none" +mupen64plus-pak3 = "none" +mupen64plus-pak4 = "none" +mupen64plus-r-cbutton = "C1" +mupen64plus-rdp-plugin = "gliden64" +mupen64plus-RDRAMImageDitheringMode = "BlueNoise" +mupen64plus-rsp-plugin = "hle" +mupen64plus-ThreadedRenderer = "True" +mupen64plus-txCacheCompression = "True" +mupen64plus-txEnhancementMode = "None" +mupen64plus-txFilterIgnoreBG = "True" +mupen64plus-txFilterMode = "None" +mupen64plus-txHiresEnable = "False" +mupen64plus-txHiresFullAlphaChannel = "False" +mupen64plus-u-cbutton = "C4" +mupen64plus-virefresh = "Auto" +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_type = "disabled" +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" +flycast_auto_skip_frame = "normal" +opera_swi_hle = "enabled" +opera_dsp_threaded = "enabled" +opera_madam_matrix_engine = "software" +puae_deadzone = "25" +melonds_screen_layout = "Left/Right" +melonds_swapscreen_mode = "Toggle" +melonds_threaded_renderer = "enabled" +melonds_touch_mode = "Joystick" +virtualjaguar_bios = "enabled" +virtualjaguar_usefastblitter = "enabled" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3399/retroarch.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3399/retroarch.cfg new file mode 100644 index 0000000000..5ceb294e90 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3399/retroarch.cfg @@ -0,0 +1,826 @@ +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_menu_bgm = "false" +audio_enable_menu_cancel = "false" +audio_enable_menu = "false" +audio_enable_menu_notice = "false" +audio_enable_menu_ok = "false" +audio_enable = "true" +audio_fastforward_mute = "false" +audio_filter_dir = "~/.config/retroarch/filters/audio" +audio_latency = "32" +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_delta = "0.004999" +audio_rate_control = "true" +audio_resampler_quality = "2" +audio_resampler = "sinc" +audio_sync = "true" +audio_volume = "0.000000" +auto_overrides_enable = "true" +auto_remaps_enable = "true" +autosave_interval = "10" +auto_screenshot_filename = "true" +auto_shaders_enable = "true" +block_sram_overwrite = "false" +bluetooth_driver = "null" +builtin_imageviewer_enable = "false" +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 = "false" +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_aggregate = "false" +content_runtime_log = "true" +content_show_add_entry = "2" +content_show_add = "true" +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_password = "" +content_show_settings = "true" +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 = "interactive" +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 = "1920" +custom_viewport_x = "0" +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" +framecount_show = "false" +frame_time_counter_reset_after_fastforwarding = "false" +frame_time_counter_reset_after_load_state = "false" +frame_time_counter_reset_after_save_state = "false" +frontend_log_level = "1" +game_specific_options = "true" +gamma_correction = "0" +global_core_options = "false" +history_list_enable = "true" +input_ai_service_axis = "nul" +input_ai_service_btn = "nul" +input_ai_service_mbtn = "nul" +input_ai_service = "nul" +input_analog_deadzone = "0.000000" +input_analog_sensitivity = "1.500000" +input_audio_mute_axis = "nul" +input_audio_mute_btn = "nul" +input_audio_mute = "f9" +input_audio_mute_mbtn = "nul" +input_autodetect_enable = "true" +input_auto_game_focus = "0" +input_auto_mouse_grab = "false" +input_axis_threshold = "0.500000" +input_bind_hold = "2" +input_bind_timeout = "5" +input_cheat_index_minus_axis = "nul" +input_cheat_index_minus_btn = "nul" +input_cheat_index_minus_mbtn = "nul" +input_cheat_index_minus = "t" +input_cheat_index_plus_axis = "nul" +input_cheat_index_plus_btn = "nul" +input_cheat_index_plus_mbtn = "nul" +input_cheat_index_plus = "y" +input_cheat_toggle_axis = "nul" +input_cheat_toggle_btn = "nul" +input_cheat_toggle_mbtn = "nul" +input_cheat_toggle = "u" +input_close_content_axis = "nul" +input_close_content_btn = "nul" +input_close_content_mbtn = "nul" +input_close_content = "nul" +input_descriptor_hide_unbound = "false" +input_descriptor_label_show = "true" +input_desktop_menu_toggle_axis = "nul" +input_desktop_menu_toggle_btn = "nul" +input_desktop_menu_toggle = "f5" +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_axis = "nul" +input_disk_eject_toggle_btn = "nul" +input_disk_eject_toggle_mbtn = "nul" +input_disk_eject_toggle = "nul" +input_disk_next_axis = "nul" +input_disk_next_btn = "nul" +input_disk_next_mbtn = "nul" +input_disk_next = "nul" +input_disk_prev_axis = "nul" +input_disk_prev_btn = "nul" +input_disk_prev_mbtn = "nul" +input_disk_prev = "nul" +input_driver = "udev" +input_duty_cycle = "3" +input_enable_hotkey_axis = "nul" +input_enable_hotkey_btn = "8" +input_enable_hotkey_mbtn = "nul" +input_enable_hotkey = "nul" +input_exit_emulator_axis = "nul" +input_exit_emulator_btn = "9" +input_exit_emulator = "escape" +input_exit_emulator_mbtn = "nul" +input_fps_toggle_axis = "nul" +input_fps_toggle_btn = "3" +input_fps_toggle = "f3" +input_fps_toggle_mbtn = "nul" +input_frame_advance_axis = "nul" +input_frame_advance_btn = "nul" +input_frame_advance = "k" +input_frame_advance_mbtn = "nul" +input_game_focus_toggle_axis = "nul" +input_game_focus_toggle_btn = "nul" +input_game_focus_toggle_mbtn = "nul" +input_game_focus_toggle = "scroll_lock" +input_grab_mouse_toggle_axis = "nul" +input_grab_mouse_toggle_btn = "nul" +input_grab_mouse_toggle = "f11" +input_grab_mouse_toggle_mbtn = "nul" +input_hold_fast_forward_axis = "nul" +input_hold_fast_forward_btn = "nul" +input_hold_fast_forward = "l" +input_hold_fast_forward_mbtn = "nul" +input_hold_slowmotion_axis = "nul" +input_hold_slowmotion_btn = "nul" +input_hold_slowmotion = "e" +input_hold_slowmotion_mbtn = "nul" +input_hotkey_block_delay = "5" +input_joypad_driver = "udev" +input_keyboard_layout = "" +input_libretro_device_p10 = "1" +input_libretro_device_p1 = "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_axis = "nul" +input_load_state_btn = "4" +input_load_state = "f4" +input_load_state_mbtn = "nul" +input_max_users = "5" +input_menu_toggle_axis = "nul" +input_menu_toggle_btn = "2" +input_menu_toggle = "f1" +input_menu_toggle_gamepad_combo = "2" +input_menu_toggle_mbtn = "nul" +input_movie_record_toggle_axis = "nul" +input_movie_record_toggle_btn = "nul" +input_movie_record_toggle_mbtn = "nul" +input_movie_record_toggle = "o" +input_netplay_game_watch_axis = "nul" +input_netplay_game_watch_btn = "nul" +input_netplay_game_watch = "i" +input_netplay_game_watch_mbtn = "nul" +input_netplay_host_toggle_axis = "nul" +input_netplay_host_toggle_btn = "nul" +input_netplay_host_toggle_mbtn = "nul" +input_netplay_host_toggle = "nul" +input_nowinkey_enable = "false" +input_osk_toggle_axis = "nul" +input_osk_toggle_btn = "nul" +input_osk_toggle = "f12" +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_autopreferred = "true" +input_overlay_enable = "false" +input_overlay_hide_in_menu = "true" +input_overlay_hide_when_gamepad_connected = "false" +input_overlay_next_axis = "nul" +input_overlay_next_btn = "nul" +input_overlay_next_mbtn = "nul" +input_overlay_next = "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_axis = "nul" +input_pause_toggle_btn = "nul" +input_pause_toggle_mbtn = "nul" +input_pause_toggle = "p" +input_poll_type_behavior = "2" +input_quit_gamepad_combo = "0" +input_recording_toggle_axis = "nul" +input_recording_toggle_btn = "nul" +input_recording_toggle_mbtn = "nul" +input_recording_toggle = "nul" +input_remap_binds_enable = "true" +input_remapping_directory = "~/remappings" +input_reset_axis = "nul" +input_reset_btn = "nul" +input_reset = "h" +input_reset_mbtn = "nul" +input_rewind_axis = "nul" +input_rewind_btn = "6" +input_rewind_mbtn = "nul" +input_rewind = "r" +input_rumble_gain = "25" +input_runahead_toggle_axis = "nul" +input_runahead_toggle_btn = "nul" +input_runahead_toggle_mbtn = "nul" +input_runahead_toggle = "nul" +input_save_state_axis = "nul" +input_save_state_btn = "5" +input_save_state = "f2" +input_save_state_mbtn = "nul" +input_screenshot_axis = "nul" +input_screenshot_btn = "nul" +input_screenshot = "f8" +input_screenshot_mbtn = "nul" +input_send_debug_info_axis = "nul" +input_send_debug_info_btn = "nul" +input_send_debug_info = "f10" +input_send_debug_info_mbtn = "nul" +input_sensors_enable = "true" +input_shader_next_axis = "nul" +input_shader_next_btn = "nul" +input_shader_next = "m" +input_shader_next_mbtn = "nul" +input_shader_prev_axis = "nul" +input_shader_prev_btn = "nul" +input_shader_prev_mbtn = "nul" +input_shader_prev = "n" +input_state_slot_decrease_axis = "nul" +input_state_slot_decrease_btn = "nul" +input_state_slot_decrease = "f6" +input_state_slot_decrease_mbtn = "nul" +input_state_slot_increase_axis = "nul" +input_state_slot_increase_btn = "nul" +input_state_slot_increase = "f7" +input_state_slot_increase_mbtn = "nul" +input_streaming_toggle_axis = "nul" +input_streaming_toggle_btn = "nul" +input_streaming_toggle_mbtn = "nul" +input_streaming_toggle = "nul" +input_toggle_fast_forward_axis = "nul" +input_toggle_fast_forward_btn = "7" +input_toggle_fast_forward_mbtn = "nul" +input_toggle_fast_forward = "space" +input_toggle_fullscreen_axis = "nul" +input_toggle_fullscreen_btn = "nul" +input_toggle_fullscreen = "f" +input_toggle_fullscreen_mbtn = "nul" +input_toggle_slowmotion_axis = "nul" +input_toggle_slowmotion_btn = "nul" +input_toggle_slowmotion_mbtn = "nul" +input_toggle_slowmotion = "nul" +input_touch_scale = "1" +input_turbo_default_button = "0" +input_turbo_mode = "0" +input_turbo_period = "6" +input_volume_down_axis = "nul" +input_volume_down_btn = "nul" +input_volume_down_mbtn = "nul" +input_volume_down = "subtract" +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 = "true" +menu_rgui_full_width_layout = "true" +menu_rgui_shadows = "false" +menu_rgui_transparency = "true" +menu_savestate_resume = "true" +menu_scale_factor = "0.300000" +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_animation = "false" +menu_show_load_content = "true" +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_thumbnails = "3" +menu_thumbnail_upscale_threshold = "0" +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 = "0.350000" +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_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_p1 = "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_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_p1 = "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_duration = "2" +notification_show_screenshot = "false" +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 = "" +playlist_directory = "~/playlists" +playlist_entry_remove_enable = "1" +playlist_entry_remove = "false" +playlist_entry_rename = "false" +playlist_fuzzy_archive_match = "false" +playlist_names = "" +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" +savestates_in_content_dir = "false" +savestate_thumbnail_enable = "true" +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_interface = "true" +settings_show_user = "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 = "glcore" +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 = "1920" +video_fullscreen_y = "1152" +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 = "1152" +video_window_auto_width_max = "1920" +video_window_custom_size_enable = "false" +video_windowed_fullscreen = "false" +video_windowed_position_height = "720" +video_windowed_position_width = "1280" +video_windowed_position_x = "0" +video_windowed_position_y = "0" +video_window_opacity = "100" +video_window_save_positions = "false" +video_window_show_decorations = "true" +vrr_runloop_enable = "false" +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/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3399/retroarch32bit-append.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3399/retroarch32bit-append.cfg new file mode 100755 index 0000000000..343124c254 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3399/retroarch32bit-append.cfg @@ -0,0 +1,3 @@ +audio_filter_dir = "/usr/share/retroarch/filters/32bit/audio" +video_filter_dir = "/usr/share/retroarch/filters/32bit/video" +libretro_directory = /usr/lib32/libretro diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3399/retroarch64bit-append.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3399/retroarch64bit-append.cfg new file mode 100755 index 0000000000..b6cbf68312 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3399/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" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3566/TATE-MAME 2003-Plus.rmp b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3566/TATE-MAME 2003-Plus.rmp new file mode 100644 index 0000000000..366e47afad --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3566/TATE-MAME 2003-Plus.rmp @@ -0,0 +1,27 @@ +input_libretro_device_p1 = "1" +input_libretro_device_p2 = "1" +input_libretro_device_p3 = "1" +input_libretro_device_p4 = "1" +input_libretro_device_p5 = "1" +input_player1_analog_dpad_mode = "1" +input_player1_btn_down = "6" +input_player1_btn_left = "4" +input_player1_btn_right = "5" +input_player1_btn_up = "7" +input_player1_stk_l_x+ = "5" +input_player1_stk_l_x- = "4" +input_player1_stk_l_y+ = "6" +input_player1_stk_l_y- = "7" +input_player1_stk_r_x+ = "5" +input_player1_stk_r_x- = "4" +input_player1_stk_r_y+ = "6" +input_player1_stk_r_y- = "7" +input_player2_analog_dpad_mode = "0" +input_player3_analog_dpad_mode = "0" +input_player4_analog_dpad_mode = "0" +input_player5_analog_dpad_mode = "0" +input_remap_port_p1 = "0" +input_remap_port_p2 = "1" +input_remap_port_p3 = "2" +input_remap_port_p4 = "3" +input_remap_port_p5 = "4" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3566/retroarch-core-options.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3566/retroarch-core-options.cfg new file mode 100644 index 0000000000..59b65f5bfb --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3566/retroarch-core-options.cfg @@ -0,0 +1,152 @@ +mupen64plus-alt-map = "False" +mupen64plus-aspect = "4:3" +mupen64plus-astick-deadzone = "15" +mupen64plus-astick-sensitivity = "100" +mupen64plus-BackgroundMode = "Stripped" +mupen64plus-BilinearMode = "standard" +mupen64plus-CorrectTexrectCoords = "Auto" +mupen64plus-CountPerOp = "0" +mupen64plus-CountPerOpDenomPot = "0" +mupen64plus-cpucore = "dynamic_recompiler" +mupen64plus-d-cbutton = "C3" +mupen64plus-DitheringPattern = "True" +mupen64plus-DitheringQuantization = "True" +mupen64plus-EnableCopyAuxToRDRAM = "True" +mupen64plus-EnableCopyColorToRDRAM = "Async" +mupen64plus-EnableCopyDepthToRDRAM = "Software" +mupen64plus-EnableEnhancedHighResStorage = "False" +mupen64plus-EnableEnhancedTextureStorage = "False" +mupen64plus-EnableFBEmulation = "True" +mupen64plus-EnableFragmentDepthWrite = "True" +mupen64plus-EnableHiResAltCRC = "False" +mupen64plus-EnableHWLighting = "False" +mupen64plus-EnableInaccurateTextureCoordinates = "False" +mupen64plus-EnableLegacyBlending = "False" +mupen64plus-EnableLODEmulation = "True" +mupen64plus-EnableNativeResFactor = "1" +mupen64plus-EnableNativeResTexrects = "Optimized" +mupen64plus-EnableOverscan = "Enabled" +mupen64plus-EnableTexCoordBounds = "False" +mupen64plus-EnableTextureCache = "True" +mupen64plus-ForceDisableExtraMem = "False" +mupen64plus-FrameDuping = "True" +mupen64plus-Framerate = "Original" +mupen64plus-FXAA = "0" +mupen64plus-GLideN64IniBehaviour = "late" +mupen64plus-HybridFilter = "True" +mupen64plus-IgnoreTLBExceptions = "False" +mupen64plus-l-cbutton = "C2" +mupen64plus-MaxHiResTxVramLimit = "0" +mupen64plus-MaxTxCacheSize = "8000" +mupen64plus-MultiSampling = "0" +mupen64plus-OverscanBottom = "0" +mupen64plus-OverscanLeft = "0" +mupen64plus-OverscanRight = "0" +mupen64plus-OverscanTop = "0" +mupen64plus-pak1 = "memory" +mupen64plus-pak2 = "none" +mupen64plus-pak3 = "none" +mupen64plus-pak4 = "none" +mupen64plus-r-cbutton = "C1" +mupen64plus-rdp-plugin = "gliden64" +mupen64plus-RDRAMImageDitheringMode = "BlueNoise" +mupen64plus-rsp-plugin = "hle" +mupen64plus-ThreadedRenderer = "True" +mupen64plus-txCacheCompression = "True" +mupen64plus-txEnhancementMode = "None" +mupen64plus-txFilterIgnoreBG = "True" +mupen64plus-txFilterMode = "None" +mupen64plus-txHiresEnable = "False" +mupen64plus-txHiresFullAlphaChannel = "False" +mupen64plus-u-cbutton = "C4" +mupen64plus-virefresh = "Auto" +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_type = "disabled" +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" +flycast_auto_skip_frame = "normal" +opera_swi_hle = "enabled" +opera_dsp_threaded = "enabled" +opera_madam_matrix_engine = "software" +puae_deadzone = "25" +melonds_screen_layout = "Left/Right" +melonds_swapscreen_mode = "Toggle" +melonds_threaded_renderer = "enabled" +melonds_touch_mode = "Joystick" +virtualjaguar_bios = "enabled" +virtualjaguar_usefastblitter = "enabled" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3566/retroarch.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3566/retroarch.cfg new file mode 100644 index 0000000000..f95b391016 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3566/retroarch.cfg @@ -0,0 +1,822 @@ +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_menu_bgm = "false" +audio_enable_menu_cancel = "false" +audio_enable_menu = "false" +audio_enable_menu_notice = "false" +audio_enable_menu_ok = "false" +audio_enable = "true" +audio_fastforward_mute = "false" +audio_filter_dir = "~/.config/retroarch/filters/audio" +audio_latency = "32" +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_delta = "0.004999" +audio_rate_control = "true" +audio_resampler_quality = "2" +audio_resampler = "sinc" +audio_sync = "true" +audio_volume = "0.000000" +auto_overrides_enable = "true" +auto_remaps_enable = "true" +autosave_interval = "10" +auto_screenshot_filename = "true" +auto_shaders_enable = "true" +block_sram_overwrite = "false" +bluetooth_driver = "null" +builtin_imageviewer_enable = "false" +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 = "false" +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_aggregate = "false" +content_runtime_log = "true" +content_show_add_entry = "2" +content_show_add = "true" +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_password = "" +content_show_settings = "true" +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 = "interactive" +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" +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" +framecount_show = "false" +frame_time_counter_reset_after_fastforwarding = "false" +frame_time_counter_reset_after_load_state = "false" +frame_time_counter_reset_after_save_state = "false" +frontend_log_level = "1" +game_specific_options = "true" +gamma_correction = "0" +global_core_options = "false" +history_list_enable = "true" +input_ai_service_axis = "nul" +input_ai_service_btn = "nul" +input_ai_service_mbtn = "nul" +input_ai_service = "nul" +input_analog_deadzone = "0.000000" +input_analog_sensitivity = "1.500000" +input_audio_mute_axis = "nul" +input_audio_mute_btn = "nul" +input_audio_mute = "f9" +input_audio_mute_mbtn = "nul" +input_autodetect_enable = "true" +input_auto_game_focus = "0" +input_auto_mouse_grab = "false" +input_axis_threshold = "0.500000" +input_bind_hold = "2" +input_bind_timeout = "5" +input_cheat_index_minus_axis = "nul" +input_cheat_index_minus_btn = "nul" +input_cheat_index_minus_mbtn = "nul" +input_cheat_index_minus = "t" +input_cheat_index_plus_axis = "nul" +input_cheat_index_plus_btn = "nul" +input_cheat_index_plus_mbtn = "nul" +input_cheat_index_plus = "y" +input_cheat_toggle_axis = "nul" +input_cheat_toggle_btn = "nul" +input_cheat_toggle_mbtn = "nul" +input_cheat_toggle = "u" +input_close_content_axis = "nul" +input_close_content_btn = "nul" +input_close_content_mbtn = "nul" +input_close_content = "nul" +input_descriptor_hide_unbound = "false" +input_descriptor_label_show = "true" +input_desktop_menu_toggle_axis = "nul" +input_desktop_menu_toggle_btn = "nul" +input_desktop_menu_toggle = "f5" +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_axis = "nul" +input_disk_eject_toggle_btn = "nul" +input_disk_eject_toggle_mbtn = "nul" +input_disk_eject_toggle = "nul" +input_disk_next_axis = "nul" +input_disk_next_btn = "nul" +input_disk_next_mbtn = "nul" +input_disk_next = "nul" +input_disk_prev_axis = "nul" +input_disk_prev_btn = "nul" +input_disk_prev_mbtn = "nul" +input_disk_prev = "nul" +input_driver = "udev" +input_duty_cycle = "3" +input_enable_hotkey_axis = "nul" +input_enable_hotkey_btn = "8" +input_enable_hotkey_mbtn = "nul" +input_enable_hotkey = "nul" +input_exit_emulator_axis = "nul" +input_exit_emulator_btn = "9" +input_exit_emulator = "escape" +input_exit_emulator_mbtn = "nul" +input_fps_toggle_axis = "nul" +input_fps_toggle_btn = "3" +input_fps_toggle = "f3" +input_fps_toggle_mbtn = "nul" +input_frame_advance_axis = "nul" +input_frame_advance_btn = "nul" +input_frame_advance = "k" +input_frame_advance_mbtn = "nul" +input_game_focus_toggle_axis = "nul" +input_game_focus_toggle_btn = "nul" +input_game_focus_toggle_mbtn = "nul" +input_game_focus_toggle = "scroll_lock" +input_grab_mouse_toggle_axis = "nul" +input_grab_mouse_toggle_btn = "nul" +input_grab_mouse_toggle = "f11" +input_grab_mouse_toggle_mbtn = "nul" +input_hold_fast_forward_axis = "nul" +input_hold_fast_forward_btn = "nul" +input_hold_fast_forward = "l" +input_hold_fast_forward_mbtn = "nul" +input_hold_slowmotion_axis = "nul" +input_hold_slowmotion_btn = "nul" +input_hold_slowmotion = "e" +input_hold_slowmotion_mbtn = "nul" +input_hotkey_block_delay = "5" +input_joypad_driver = "udev" +input_keyboard_layout = "" +input_libretro_device_p10 = "1" +input_libretro_device_p1 = "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_axis = "nul" +input_load_state_btn = "4" +input_load_state = "f4" +input_load_state_mbtn = "nul" +input_max_users = "5" +input_menu_toggle_axis = "nul" +input_menu_toggle_btn = "2" +input_menu_toggle = "f1" +input_menu_toggle_gamepad_combo = "9" +input_menu_toggle_mbtn = "nul" +input_movie_record_toggle_axis = "nul" +input_movie_record_toggle_btn = "nul" +input_movie_record_toggle_mbtn = "nul" +input_movie_record_toggle = "o" +input_netplay_game_watch_axis = "nul" +input_netplay_game_watch_btn = "nul" +input_netplay_game_watch = "i" +input_netplay_game_watch_mbtn = "nul" +input_netplay_host_toggle_axis = "nul" +input_netplay_host_toggle_btn = "nul" +input_netplay_host_toggle_mbtn = "nul" +input_netplay_host_toggle = "nul" +input_nowinkey_enable = "false" +input_osk_toggle_axis = "nul" +input_osk_toggle_btn = "nul" +input_osk_toggle = "f12" +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_autopreferred = "true" +input_overlay_enable = "false" +input_overlay_hide_in_menu = "true" +input_overlay_hide_when_gamepad_connected = "false" +input_overlay_next_axis = "nul" +input_overlay_next_btn = "nul" +input_overlay_next_mbtn = "nul" +input_overlay_next = "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_axis = "nul" +input_pause_toggle_btn = "nul" +input_pause_toggle_mbtn = "nul" +input_pause_toggle = "p" +input_poll_type_behavior = "2" +input_quit_gamepad_combo = "0" +input_recording_toggle_axis = "nul" +input_recording_toggle_btn = "nul" +input_recording_toggle_mbtn = "nul" +input_recording_toggle = "nul" +input_remap_binds_enable = "true" +input_remapping_directory = "~/remappings" +input_reset_axis = "nul" +input_reset_btn = "nul" +input_reset = "h" +input_reset_mbtn = "nul" +input_rewind_axis = "nul" +input_rewind_btn = "6" +input_rewind_mbtn = "nul" +input_rewind = "r" +input_rumble_gain = "100" +input_runahead_toggle_axis = "nul" +input_runahead_toggle_btn = "nul" +input_runahead_toggle_mbtn = "nul" +input_runahead_toggle = "nul" +input_save_state_axis = "nul" +input_save_state_btn = "5" +input_save_state = "f2" +input_save_state_mbtn = "nul" +input_screenshot_axis = "nul" +input_screenshot_btn = "nul" +input_screenshot = "f8" +input_screenshot_mbtn = "nul" +input_send_debug_info_axis = "nul" +input_send_debug_info_btn = "nul" +input_send_debug_info = "f10" +input_send_debug_info_mbtn = "nul" +input_sensors_enable = "true" +input_shader_next_axis = "nul" +input_shader_next_btn = "nul" +input_shader_next = "m" +input_shader_next_mbtn = "nul" +input_shader_prev_axis = "nul" +input_shader_prev_btn = "nul" +input_shader_prev_mbtn = "nul" +input_shader_prev = "n" +input_state_slot_decrease_axis = "nul" +input_state_slot_decrease_btn = "nul" +input_state_slot_decrease = "f6" +input_state_slot_decrease_mbtn = "nul" +input_state_slot_increase_axis = "nul" +input_state_slot_increase_btn = "nul" +input_state_slot_increase = "f7" +input_state_slot_increase_mbtn = "nul" +input_streaming_toggle_axis = "nul" +input_streaming_toggle_btn = "nul" +input_streaming_toggle_mbtn = "nul" +input_streaming_toggle = "nul" +input_toggle_fast_forward_axis = "nul" +input_toggle_fast_forward_btn = "7" +input_toggle_fast_forward_mbtn = "nul" +input_toggle_fast_forward = "space" +input_toggle_fullscreen_axis = "nul" +input_toggle_fullscreen_btn = "nul" +input_toggle_fullscreen = "f" +input_toggle_fullscreen_mbtn = "nul" +input_toggle_slowmotion_axis = "nul" +input_toggle_slowmotion_btn = "nul" +input_toggle_slowmotion_mbtn = "nul" +input_toggle_slowmotion = "nul" +input_touch_scale = "1" +input_turbo_default_button = "0" +input_turbo_mode = "0" +input_turbo_period = "6" +input_volume_down_axis = "nul" +input_volume_down_btn = "nul" +input_volume_down_mbtn = "nul" +input_volume_down = "subtract" +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 = "true" +menu_rgui_full_width_layout = "true" +menu_rgui_shadows = "false" +menu_rgui_transparency = "true" +menu_savestate_resume = "true" +menu_scale_factor = "0.350000" +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_animation = "false" +menu_show_load_content = "true" +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_thumbnails = "3" +menu_thumbnail_upscale_threshold = "0" +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 = "0.350000" +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_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_p1 = "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_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_p1 = "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_duration = "2" +notification_show_screenshot = "false" +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 = "" +playlist_directory = "~/playlists" +playlist_entry_remove_enable = "1" +playlist_entry_remove = "false" +playlist_entry_rename = "false" +playlist_fuzzy_archive_match = "false" +playlist_names = "" +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" +savestates_in_content_dir = "false" +savestate_thumbnail_enable = "true" +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_interface = "true" +settings_show_user = "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_windowed_fullscreen = "false" +video_windowed_position_height = "720" +video_windowed_position_width = "1280" +video_windowed_position_x = "0" +video_windowed_position_y = "0" +video_window_opacity = "100" +video_window_save_positions = "false" +video_window_show_decorations = "true" +vrr_runloop_enable = "false" +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/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3566/retroarch32bit-append.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3566/retroarch32bit-append.cfg new file mode 100644 index 0000000000..343124c254 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3566/retroarch32bit-append.cfg @@ -0,0 +1,3 @@ +audio_filter_dir = "/usr/share/retroarch/filters/32bit/audio" +video_filter_dir = "/usr/share/retroarch/filters/32bit/video" +libretro_directory = /usr/lib32/libretro diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3566/retroarch64bit-append.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3566/retroarch64bit-append.cfg new file mode 100644 index 0000000000..b6cbf68312 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3566/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" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3588/TATE-MAME 2003-Plus.rmp b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3588/TATE-MAME 2003-Plus.rmp new file mode 100755 index 0000000000..366e47afad --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3588/TATE-MAME 2003-Plus.rmp @@ -0,0 +1,27 @@ +input_libretro_device_p1 = "1" +input_libretro_device_p2 = "1" +input_libretro_device_p3 = "1" +input_libretro_device_p4 = "1" +input_libretro_device_p5 = "1" +input_player1_analog_dpad_mode = "1" +input_player1_btn_down = "6" +input_player1_btn_left = "4" +input_player1_btn_right = "5" +input_player1_btn_up = "7" +input_player1_stk_l_x+ = "5" +input_player1_stk_l_x- = "4" +input_player1_stk_l_y+ = "6" +input_player1_stk_l_y- = "7" +input_player1_stk_r_x+ = "5" +input_player1_stk_r_x- = "4" +input_player1_stk_r_y+ = "6" +input_player1_stk_r_y- = "7" +input_player2_analog_dpad_mode = "0" +input_player3_analog_dpad_mode = "0" +input_player4_analog_dpad_mode = "0" +input_player5_analog_dpad_mode = "0" +input_remap_port_p1 = "0" +input_remap_port_p2 = "1" +input_remap_port_p3 = "2" +input_remap_port_p4 = "3" +input_remap_port_p5 = "4" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3588/retroarch-core-options.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3588/retroarch-core-options.cfg new file mode 100755 index 0000000000..0bcbaa2661 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3588/retroarch-core-options.cfg @@ -0,0 +1,152 @@ +mupen64plus-alt-map = "False" +mupen64plus-aspect = "4:3" +mupen64plus-astick-deadzone = "15" +mupen64plus-astick-sensitivity = "100" +mupen64plus-BackgroundMode = "Stripped" +mupen64plus-BilinearMode = "standard" +mupen64plus-CorrectTexrectCoords = "Auto" +mupen64plus-CountPerOp = "0" +mupen64plus-CountPerOpDenomPot = "0" +mupen64plus-cpucore = "dynamic_recompiler" +mupen64plus-d-cbutton = "C3" +mupen64plus-DitheringPattern = "True" +mupen64plus-DitheringQuantization = "True" +mupen64plus-EnableCopyAuxToRDRAM = "True" +mupen64plus-EnableCopyColorToRDRAM = "Async" +mupen64plus-EnableCopyDepthToRDRAM = "Software" +mupen64plus-EnableEnhancedHighResStorage = "False" +mupen64plus-EnableEnhancedTextureStorage = "False" +mupen64plus-EnableFBEmulation = "True" +mupen64plus-EnableFragmentDepthWrite = "False" +mupen64plus-EnableHiResAltCRC = "False" +mupen64plus-EnableHWLighting = "True" +mupen64plus-EnableInaccurateTextureCoordinates = "False" +mupen64plus-EnableLegacyBlending = "False" +mupen64plus-EnableLODEmulation = "True" +mupen64plus-EnableNativeResFactor = "1" +mupen64plus-EnableNativeResTexrects = "Optimized" +mupen64plus-EnableOverscan = "Enabled" +mupen64plus-EnableTexCoordBounds = "False" +mupen64plus-EnableTextureCache = "True" +mupen64plus-ForceDisableExtraMem = "False" +mupen64plus-FrameDuping = "True" +mupen64plus-Framerate = "Original" +mupen64plus-FXAA = "0" +mupen64plus-GLideN64IniBehaviour = "late" +mupen64plus-HybridFilter = "True" +mupen64plus-IgnoreTLBExceptions = "False" +mupen64plus-l-cbutton = "C2" +mupen64plus-MaxHiResTxVramLimit = "0" +mupen64plus-MaxTxCacheSize = "8000" +mupen64plus-MultiSampling = "0" +mupen64plus-OverscanBottom = "0" +mupen64plus-OverscanLeft = "0" +mupen64plus-OverscanRight = "0" +mupen64plus-OverscanTop = "0" +mupen64plus-pak1 = "memory" +mupen64plus-pak2 = "none" +mupen64plus-pak3 = "none" +mupen64plus-pak4 = "none" +mupen64plus-r-cbutton = "C1" +mupen64plus-rdp-plugin = "gliden64" +mupen64plus-RDRAMImageDitheringMode = "BlueNoise" +mupen64plus-rsp-plugin = "hle" +mupen64plus-ThreadedRenderer = "True" +mupen64plus-txCacheCompression = "True" +mupen64plus-txEnhancementMode = "None" +mupen64plus-txFilterIgnoreBG = "True" +mupen64plus-txFilterMode = "None" +mupen64plus-txHiresEnable = "False" +mupen64plus-txHiresFullAlphaChannel = "False" +mupen64plus-u-cbutton = "C4" +mupen64plus-virefresh = "Auto" +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_type = "disabled" +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" +flycast_auto_skip_frame = "normal" +opera_swi_hle = "enabled" +opera_dsp_threaded = "enabled" +opera_madam_matrix_engine = "software" +puae_deadzone = "25" +melonds_screen_layout = "Left/Right" +melonds_swapscreen_mode = "Toggle" +melonds_threaded_renderer = "enabled" +melonds_touch_mode = "Joystick" +virtualjaguar_bios = "enabled" +virtualjaguar_usefastblitter = "enabled" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3588/retroarch.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3588/retroarch.cfg new file mode 100755 index 0000000000..46991fdc90 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3588/retroarch.cfg @@ -0,0 +1,822 @@ +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_menu_bgm = "false" +audio_enable_menu_cancel = "false" +audio_enable_menu = "false" +audio_enable_menu_notice = "false" +audio_enable_menu_ok = "false" +audio_enable = "true" +audio_fastforward_mute = "false" +audio_filter_dir = "~/.config/retroarch/filters/audio" +audio_latency = "32" +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_delta = "0.004999" +audio_rate_control = "true" +audio_resampler_quality = "2" +audio_resampler = "sinc" +audio_sync = "true" +audio_volume = "0.000000" +auto_overrides_enable = "true" +auto_remaps_enable = "true" +autosave_interval = "10" +auto_screenshot_filename = "true" +auto_shaders_enable = "true" +block_sram_overwrite = "false" +bluetooth_driver = "null" +builtin_imageviewer_enable = "false" +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 = "false" +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_aggregate = "false" +content_runtime_log = "true" +content_show_add_entry = "2" +content_show_add = "true" +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_password = "" +content_show_settings = "true" +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 = "interactive" +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" +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" +framecount_show = "false" +frame_time_counter_reset_after_fastforwarding = "false" +frame_time_counter_reset_after_load_state = "false" +frame_time_counter_reset_after_save_state = "false" +frontend_log_level = "1" +game_specific_options = "true" +gamma_correction = "0" +global_core_options = "false" +history_list_enable = "true" +input_ai_service_axis = "nul" +input_ai_service_btn = "nul" +input_ai_service_mbtn = "nul" +input_ai_service = "nul" +input_analog_deadzone = "0.000000" +input_analog_sensitivity = "1.500000" +input_audio_mute_axis = "nul" +input_audio_mute_btn = "nul" +input_audio_mute = "f9" +input_audio_mute_mbtn = "nul" +input_autodetect_enable = "true" +input_auto_game_focus = "0" +input_auto_mouse_grab = "false" +input_axis_threshold = "0.500000" +input_bind_hold = "2" +input_bind_timeout = "5" +input_cheat_index_minus_axis = "nul" +input_cheat_index_minus_btn = "nul" +input_cheat_index_minus_mbtn = "nul" +input_cheat_index_minus = "t" +input_cheat_index_plus_axis = "nul" +input_cheat_index_plus_btn = "nul" +input_cheat_index_plus_mbtn = "nul" +input_cheat_index_plus = "y" +input_cheat_toggle_axis = "nul" +input_cheat_toggle_btn = "nul" +input_cheat_toggle_mbtn = "nul" +input_cheat_toggle = "u" +input_close_content_axis = "nul" +input_close_content_btn = "nul" +input_close_content_mbtn = "nul" +input_close_content = "nul" +input_descriptor_hide_unbound = "false" +input_descriptor_label_show = "true" +input_desktop_menu_toggle_axis = "nul" +input_desktop_menu_toggle_btn = "nul" +input_desktop_menu_toggle = "f5" +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_axis = "nul" +input_disk_eject_toggle_btn = "nul" +input_disk_eject_toggle_mbtn = "nul" +input_disk_eject_toggle = "nul" +input_disk_next_axis = "nul" +input_disk_next_btn = "nul" +input_disk_next_mbtn = "nul" +input_disk_next = "nul" +input_disk_prev_axis = "nul" +input_disk_prev_btn = "nul" +input_disk_prev_mbtn = "nul" +input_disk_prev = "nul" +input_driver = "udev" +input_duty_cycle = "3" +input_enable_hotkey_axis = "nul" +input_enable_hotkey_btn = "8" +input_enable_hotkey_mbtn = "nul" +input_enable_hotkey = "nul" +input_exit_emulator_axis = "nul" +input_exit_emulator_btn = "9" +input_exit_emulator = "escape" +input_exit_emulator_mbtn = "nul" +input_fps_toggle_axis = "nul" +input_fps_toggle_btn = "3" +input_fps_toggle = "f3" +input_fps_toggle_mbtn = "nul" +input_frame_advance_axis = "nul" +input_frame_advance_btn = "nul" +input_frame_advance = "k" +input_frame_advance_mbtn = "nul" +input_game_focus_toggle_axis = "nul" +input_game_focus_toggle_btn = "nul" +input_game_focus_toggle_mbtn = "nul" +input_game_focus_toggle = "scroll_lock" +input_grab_mouse_toggle_axis = "nul" +input_grab_mouse_toggle_btn = "nul" +input_grab_mouse_toggle = "f11" +input_grab_mouse_toggle_mbtn = "nul" +input_hold_fast_forward_axis = "nul" +input_hold_fast_forward_btn = "nul" +input_hold_fast_forward = "l" +input_hold_fast_forward_mbtn = "nul" +input_hold_slowmotion_axis = "nul" +input_hold_slowmotion_btn = "nul" +input_hold_slowmotion = "e" +input_hold_slowmotion_mbtn = "nul" +input_hotkey_block_delay = "5" +input_joypad_driver = "udev" +input_keyboard_layout = "" +input_libretro_device_p10 = "1" +input_libretro_device_p1 = "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_axis = "nul" +input_load_state_btn = "4" +input_load_state = "f4" +input_load_state_mbtn = "nul" +input_max_users = "5" +input_menu_toggle_axis = "nul" +input_menu_toggle_btn = "2" +input_menu_toggle = "f1" +input_menu_toggle_gamepad_combo = "2" +input_menu_toggle_mbtn = "nul" +input_movie_record_toggle_axis = "nul" +input_movie_record_toggle_btn = "nul" +input_movie_record_toggle_mbtn = "nul" +input_movie_record_toggle = "o" +input_netplay_game_watch_axis = "nul" +input_netplay_game_watch_btn = "nul" +input_netplay_game_watch = "i" +input_netplay_game_watch_mbtn = "nul" +input_netplay_host_toggle_axis = "nul" +input_netplay_host_toggle_btn = "nul" +input_netplay_host_toggle_mbtn = "nul" +input_netplay_host_toggle = "nul" +input_nowinkey_enable = "false" +input_osk_toggle_axis = "nul" +input_osk_toggle_btn = "nul" +input_osk_toggle = "f12" +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_autopreferred = "true" +input_overlay_enable = "false" +input_overlay_hide_in_menu = "true" +input_overlay_hide_when_gamepad_connected = "false" +input_overlay_next_axis = "nul" +input_overlay_next_btn = "nul" +input_overlay_next_mbtn = "nul" +input_overlay_next = "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_axis = "nul" +input_pause_toggle_btn = "nul" +input_pause_toggle_mbtn = "nul" +input_pause_toggle = "p" +input_poll_type_behavior = "2" +input_quit_gamepad_combo = "0" +input_recording_toggle_axis = "nul" +input_recording_toggle_btn = "nul" +input_recording_toggle_mbtn = "nul" +input_recording_toggle = "nul" +input_remap_binds_enable = "true" +input_remapping_directory = "~/remappings" +input_reset_axis = "nul" +input_reset_btn = "nul" +input_reset = "h" +input_reset_mbtn = "nul" +input_rewind_axis = "nul" +input_rewind_btn = "6" +input_rewind_mbtn = "nul" +input_rewind = "r" +input_rumble_gain = "100" +input_runahead_toggle_axis = "nul" +input_runahead_toggle_btn = "nul" +input_runahead_toggle_mbtn = "nul" +input_runahead_toggle = "nul" +input_save_state_axis = "nul" +input_save_state_btn = "5" +input_save_state = "f2" +input_save_state_mbtn = "nul" +input_screenshot_axis = "nul" +input_screenshot_btn = "nul" +input_screenshot = "f8" +input_screenshot_mbtn = "nul" +input_send_debug_info_axis = "nul" +input_send_debug_info_btn = "nul" +input_send_debug_info = "f10" +input_send_debug_info_mbtn = "nul" +input_sensors_enable = "true" +input_shader_next_axis = "nul" +input_shader_next_btn = "nul" +input_shader_next = "m" +input_shader_next_mbtn = "nul" +input_shader_prev_axis = "nul" +input_shader_prev_btn = "nul" +input_shader_prev_mbtn = "nul" +input_shader_prev = "n" +input_state_slot_decrease_axis = "nul" +input_state_slot_decrease_btn = "nul" +input_state_slot_decrease = "f6" +input_state_slot_decrease_mbtn = "nul" +input_state_slot_increase_axis = "nul" +input_state_slot_increase_btn = "nul" +input_state_slot_increase = "f7" +input_state_slot_increase_mbtn = "nul" +input_streaming_toggle_axis = "nul" +input_streaming_toggle_btn = "nul" +input_streaming_toggle_mbtn = "nul" +input_streaming_toggle = "nul" +input_toggle_fast_forward_axis = "nul" +input_toggle_fast_forward_btn = "7" +input_toggle_fast_forward_mbtn = "nul" +input_toggle_fast_forward = "space" +input_toggle_fullscreen_axis = "nul" +input_toggle_fullscreen_btn = "nul" +input_toggle_fullscreen = "f" +input_toggle_fullscreen_mbtn = "nul" +input_toggle_slowmotion_axis = "nul" +input_toggle_slowmotion_btn = "nul" +input_toggle_slowmotion_mbtn = "nul" +input_toggle_slowmotion = "nul" +input_touch_scale = "1" +input_turbo_default_button = "0" +input_turbo_mode = "0" +input_turbo_period = "6" +input_volume_down_axis = "nul" +input_volume_down_btn = "nul" +input_volume_down_mbtn = "nul" +input_volume_down = "subtract" +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.300000" +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_animation = "false" +menu_show_load_content = "true" +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_thumbnails = "3" +menu_thumbnail_upscale_threshold = "0" +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 = "0.350000" +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_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_p1 = "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_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_p1 = "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_duration = "2" +notification_show_screenshot = "false" +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 = "" +playlist_directory = "~/playlists" +playlist_entry_remove_enable = "1" +playlist_entry_remove = "false" +playlist_entry_rename = "false" +playlist_fuzzy_archive_match = "false" +playlist_names = "" +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" +savestates_in_content_dir = "false" +savestate_thumbnail_enable = "true" +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_interface = "true" +settings_show_user = "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 = "1920" +video_fullscreen_y = "1080" +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_windowed_fullscreen = "false" +video_windowed_position_height = "720" +video_windowed_position_width = "1280" +video_windowed_position_x = "0" +video_windowed_position_y = "0" +video_window_opacity = "100" +video_window_save_positions = "false" +video_window_show_decorations = "true" +vrr_runloop_enable = "false" +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/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3588/retroarch32bit-append.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3588/retroarch32bit-append.cfg new file mode 100755 index 0000000000..343124c254 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3588/retroarch32bit-append.cfg @@ -0,0 +1,3 @@ +audio_filter_dir = "/usr/share/retroarch/filters/32bit/audio" +video_filter_dir = "/usr/share/retroarch/filters/32bit/video" +libretro_directory = /usr/lib32/libretro diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3588/retroarch64bit-append.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3588/retroarch64bit-append.cfg new file mode 100755 index 0000000000..b6cbf68312 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/RK3588/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" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/S922X/TATE-MAME 2003-Plus.rmp b/projects/ArchR/packages/emulators/libretro/retroarch/sources/S922X/TATE-MAME 2003-Plus.rmp new file mode 100644 index 0000000000..366e47afad --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/S922X/TATE-MAME 2003-Plus.rmp @@ -0,0 +1,27 @@ +input_libretro_device_p1 = "1" +input_libretro_device_p2 = "1" +input_libretro_device_p3 = "1" +input_libretro_device_p4 = "1" +input_libretro_device_p5 = "1" +input_player1_analog_dpad_mode = "1" +input_player1_btn_down = "6" +input_player1_btn_left = "4" +input_player1_btn_right = "5" +input_player1_btn_up = "7" +input_player1_stk_l_x+ = "5" +input_player1_stk_l_x- = "4" +input_player1_stk_l_y+ = "6" +input_player1_stk_l_y- = "7" +input_player1_stk_r_x+ = "5" +input_player1_stk_r_x- = "4" +input_player1_stk_r_y+ = "6" +input_player1_stk_r_y- = "7" +input_player2_analog_dpad_mode = "0" +input_player3_analog_dpad_mode = "0" +input_player4_analog_dpad_mode = "0" +input_player5_analog_dpad_mode = "0" +input_remap_port_p1 = "0" +input_remap_port_p2 = "1" +input_remap_port_p3 = "2" +input_remap_port_p4 = "3" +input_remap_port_p5 = "4" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/S922X/retroarch-core-options.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/S922X/retroarch-core-options.cfg new file mode 100644 index 0000000000..3f1cc2ca9e --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/S922X/retroarch-core-options.cfg @@ -0,0 +1,153 @@ +mupen64plus-alt-map = "False" +mupen64plus-aspect = "4:3" +mupen64plus-astick-deadzone = "15" +mupen64plus-astick-sensitivity = "100" +mupen64plus-BackgroundMode = "Stripped" +mupen64plus-BilinearMode = "standard" +mupen64plus-CorrectTexrectCoords = "Auto" +mupen64plus-CountPerOp = "0" +mupen64plus-CountPerOpDenomPot = "0" +mupen64plus-cpucore = "dynamic_recompiler" +mupen64plus-d-cbutton = "C3" +mupen64plus-DitheringPattern = "True" +mupen64plus-DitheringQuantization = "True" +mupen64plus-EnableCopyAuxToRDRAM = "True" +mupen64plus-EnableCopyColorToRDRAM = "Async" +mupen64plus-EnableCopyDepthToRDRAM = "Software" +mupen64plus-EnableEnhancedHighResStorage = "False" +mupen64plus-EnableEnhancedTextureStorage = "False" +mupen64plus-EnableFBEmulation = "True" +mupen64plus-EnableFragmentDepthWrite = "True" +mupen64plus-EnableHiResAltCRC = "False" +mupen64plus-EnableHWLighting = "False" +mupen64plus-EnableInaccurateTextureCoordinates = "False" +mupen64plus-EnableLegacyBlending = "False" +mupen64plus-EnableLODEmulation = "True" +mupen64plus-EnableNativeResFactor = "1" +mupen64plus-EnableNativeResTexrects = "Optimized" +mupen64plus-EnableOverscan = "Enabled" +mupen64plus-EnableTexCoordBounds = "False" +mupen64plus-EnableTextureCache = "True" +mupen64plus-ForceDisableExtraMem = "False" +mupen64plus-FrameDuping = "True" +mupen64plus-Framerate = "Original" +mupen64plus-FXAA = "0" +mupen64plus-GLideN64IniBehaviour = "late" +mupen64plus-HybridFilter = "True" +mupen64plus-IgnoreTLBExceptions = "False" +mupen64plus-l-cbutton = "C2" +mupen64plus-MaxHiResTxVramLimit = "0" +mupen64plus-MaxTxCacheSize = "8000" +mupen64plus-MultiSampling = "0" +mupen64plus-OverscanBottom = "0" +mupen64plus-OverscanLeft = "0" +mupen64plus-OverscanRight = "0" +mupen64plus-OverscanTop = "0" +mupen64plus-pak1 = "memory" +mupen64plus-pak2 = "none" +mupen64plus-pak3 = "none" +mupen64plus-pak4 = "none" +mupen64plus-r-cbutton = "C1" +mupen64plus-rdp-plugin = "gliden64" +mupen64plus-RDRAMImageDitheringMode = "BlueNoise" +mupen64plus-rsp-plugin = "hle" +mupen64plus-ThreadedRenderer = "True" +mupen64plus-txCacheCompression = "True" +mupen64plus-txEnhancementMode = "None" +mupen64plus-txFilterIgnoreBG = "True" +mupen64plus-txFilterMode = "None" +mupen64plus-txHiresEnable = "False" +mupen64plus-txHiresFullAlphaChannel = "False" +mupen64plus-u-cbutton = "C4" +mupen64plus-virefresh = "Auto" +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_type = "disabled" +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" +flycast_auto_skip_frame = "normal" +opera_swi_hle = "enabled" +opera_dsp_threaded = "enabled" +opera_madam_matrix_engine = "software" +puae_deadzone = "25" +melonds_screen_layout = "Left/Right" +melonds_swapscreen_mode = "Toggle" +melonds_threaded_renderer = "enabled" +melonds_touch_mode = "Joystick" +virtualjaguar_bios = "enabled" +virtualjaguar_usefastblitter = "enabled" +desmume_screens_layout = "left/right" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/S922X/retroarch.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/S922X/retroarch.cfg new file mode 100644 index 0000000000..792bc4834a --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/S922X/retroarch.cfg @@ -0,0 +1,821 @@ +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_menu_bgm = "false" +audio_enable_menu_cancel = "false" +audio_enable_menu = "false" +audio_enable_menu_notice = "false" +audio_enable_menu_ok = "false" +audio_enable = "true" +audio_fastforward_mute = "false" +audio_filter_dir = "~/.config/retroarch/filters/audio" +audio_latency = "32" +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_delta = "0.004999" +audio_rate_control = "true" +audio_resampler_quality = "2" +audio_resampler = "sinc" +audio_sync = "true" +audio_volume = "0.000000" +auto_overrides_enable = "true" +auto_remaps_enable = "true" +autosave_interval = "10" +auto_screenshot_filename = "true" +auto_shaders_enable = "true" +block_sram_overwrite = "false" +bluetooth_driver = "null" +builtin_imageviewer_enable = "false" +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 = "false" +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_aggregate = "false" +content_runtime_log = "true" +content_show_add_entry = "2" +content_show_add = "true" +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_password = "" +content_show_settings = "true" +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 = "interactive" +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" +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" +framecount_show = "false" +frame_time_counter_reset_after_fastforwarding = "false" +frame_time_counter_reset_after_load_state = "false" +frame_time_counter_reset_after_save_state = "false" +frontend_log_level = "1" +game_specific_options = "true" +gamma_correction = "0" +global_core_options = "false" +history_list_enable = "true" +input_ai_service_axis = "nul" +input_ai_service_btn = "nul" +input_ai_service_mbtn = "nul" +input_ai_service = "nul" +input_analog_deadzone = "0.000000" +input_analog_sensitivity = "1.500000" +input_audio_mute_axis = "nul" +input_audio_mute_btn = "nul" +input_audio_mute = "f9" +input_audio_mute_mbtn = "nul" +input_autodetect_enable = "true" +input_auto_game_focus = "0" +input_auto_mouse_grab = "false" +input_axis_threshold = "0.500000" +input_bind_hold = "2" +input_bind_timeout = "5" +input_cheat_index_minus_axis = "nul" +input_cheat_index_minus_btn = "nul" +input_cheat_index_minus_mbtn = "nul" +input_cheat_index_minus = "t" +input_cheat_index_plus_axis = "nul" +input_cheat_index_plus_btn = "nul" +input_cheat_index_plus_mbtn = "nul" +input_cheat_index_plus = "y" +input_cheat_toggle_axis = "nul" +input_cheat_toggle_btn = "nul" +input_cheat_toggle_mbtn = "nul" +input_cheat_toggle = "u" +input_close_content_axis = "nul" +input_close_content_btn = "nul" +input_close_content_mbtn = "nul" +input_close_content = "nul" +input_descriptor_hide_unbound = "false" +input_descriptor_label_show = "true" +input_desktop_menu_toggle_axis = "nul" +input_desktop_menu_toggle_btn = "nul" +input_desktop_menu_toggle = "f5" +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_axis = "nul" +input_disk_eject_toggle_btn = "nul" +input_disk_eject_toggle_mbtn = "nul" +input_disk_eject_toggle = "nul" +input_disk_next_axis = "nul" +input_disk_next_btn = "nul" +input_disk_next_mbtn = "nul" +input_disk_next = "nul" +input_disk_prev_axis = "nul" +input_disk_prev_btn = "nul" +input_disk_prev_mbtn = "nul" +input_disk_prev = "nul" +input_driver = "udev" +input_duty_cycle = "3" +input_enable_hotkey_axis = "nul" +input_enable_hotkey_btn = "13" +input_enable_hotkey_mbtn = "nul" +input_enable_hotkey = "nul" +input_exit_emulator_axis = "nul" +input_exit_emulator_btn = "9" +input_exit_emulator = "escape" +input_exit_emulator_mbtn = "nul" +input_fps_toggle_axis = "nul" +input_fps_toggle_btn = "3" +input_fps_toggle = "f3" +input_fps_toggle_mbtn = "nul" +input_frame_advance_axis = "nul" +input_frame_advance_btn = "nul" +input_frame_advance = "k" +input_frame_advance_mbtn = "nul" +input_game_focus_toggle_axis = "nul" +input_game_focus_toggle_btn = "nul" +input_game_focus_toggle_mbtn = "nul" +input_game_focus_toggle = "scroll_lock" +input_grab_mouse_toggle_axis = "nul" +input_grab_mouse_toggle_btn = "nul" +input_grab_mouse_toggle = "f11" +input_grab_mouse_toggle_mbtn = "nul" +input_hold_fast_forward_axis = "nul" +input_hold_fast_forward_btn = "nul" +input_hold_fast_forward = "l" +input_hold_fast_forward_mbtn = "nul" +input_hold_slowmotion_axis = "nul" +input_hold_slowmotion_btn = "nul" +input_hold_slowmotion = "e" +input_hold_slowmotion_mbtn = "nul" +input_hotkey_block_delay = "5" +input_joypad_driver = "udev" +input_keyboard_layout = "" +input_libretro_device_p10 = "1" +input_libretro_device_p1 = "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_axis = "nul" +input_load_state_btn = "4" +input_load_state = "f4" +input_load_state_mbtn = "nul" +input_max_users = "5" +input_menu_toggle_axis = "nul" +input_menu_toggle_btn = "2" +input_menu_toggle = "f1" +input_menu_toggle_gamepad_combo = "2" +input_menu_toggle_mbtn = "nul" +input_movie_record_toggle_axis = "nul" +input_movie_record_toggle_btn = "nul" +input_movie_record_toggle_mbtn = "nul" +input_movie_record_toggle = "o" +input_netplay_game_watch_axis = "nul" +input_netplay_game_watch_btn = "nul" +input_netplay_game_watch = "i" +input_netplay_game_watch_mbtn = "nul" +input_netplay_host_toggle_axis = "nul" +input_netplay_host_toggle_btn = "nul" +input_netplay_host_toggle_mbtn = "nul" +input_netplay_host_toggle = "nul" +input_nowinkey_enable = "false" +input_osk_toggle_axis = "nul" +input_osk_toggle_btn = "nul" +input_osk_toggle = "f12" +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_autopreferred = "true" +input_overlay_enable = "false" +input_overlay_hide_in_menu = "true" +input_overlay_hide_when_gamepad_connected = "false" +input_overlay_next_axis = "nul" +input_overlay_next_btn = "nul" +input_overlay_next_mbtn = "nul" +input_overlay_next = "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_axis = "nul" +input_pause_toggle_btn = "nul" +input_pause_toggle_mbtn = "nul" +input_pause_toggle = "p" +input_poll_type_behavior = "2" +input_quit_gamepad_combo = "0" +input_recording_toggle_axis = "nul" +input_recording_toggle_btn = "nul" +input_recording_toggle_mbtn = "nul" +input_recording_toggle = "nul" +input_remap_binds_enable = "true" +input_remapping_directory = "~/remappings" +input_reset_axis = "nul" +input_reset_btn = "nul" +input_reset = "h" +input_reset_mbtn = "nul" +input_rewind_axis = "nul" +input_rewind_btn = "6" +input_rewind_mbtn = "nul" +input_rewind = "r" +input_rumble_gain = "100" +input_runahead_toggle_axis = "nul" +input_runahead_toggle_btn = "nul" +input_runahead_toggle_mbtn = "nul" +input_runahead_toggle = "nul" +input_save_state_axis = "nul" +input_save_state_btn = "5" +input_save_state = "f2" +input_save_state_mbtn = "nul" +input_screenshot_axis = "nul" +input_screenshot_btn = "nul" +input_screenshot = "f8" +input_screenshot_mbtn = "nul" +input_send_debug_info_axis = "nul" +input_send_debug_info_btn = "nul" +input_send_debug_info = "f10" +input_send_debug_info_mbtn = "nul" +input_sensors_enable = "true" +input_shader_next_axis = "nul" +input_shader_next_btn = "nul" +input_shader_next = "m" +input_shader_next_mbtn = "nul" +input_shader_prev_axis = "nul" +input_shader_prev_btn = "nul" +input_shader_prev_mbtn = "nul" +input_shader_prev = "n" +input_state_slot_decrease_axis = "nul" +input_state_slot_decrease_btn = "nul" +input_state_slot_decrease = "f6" +input_state_slot_decrease_mbtn = "nul" +input_state_slot_increase_axis = "nul" +input_state_slot_increase_btn = "nul" +input_state_slot_increase = "f7" +input_state_slot_increase_mbtn = "nul" +input_streaming_toggle_axis = "nul" +input_streaming_toggle_btn = "nul" +input_streaming_toggle_mbtn = "nul" +input_streaming_toggle = "nul" +input_toggle_fast_forward_axis = "nul" +input_toggle_fast_forward_btn = "7" +input_toggle_fast_forward_mbtn = "nul" +input_toggle_fast_forward = "space" +input_toggle_fullscreen_axis = "nul" +input_toggle_fullscreen_btn = "nul" +input_toggle_fullscreen = "f" +input_toggle_fullscreen_mbtn = "nul" +input_toggle_slowmotion_axis = "nul" +input_toggle_slowmotion_btn = "nul" +input_toggle_slowmotion_mbtn = "nul" +input_toggle_slowmotion = "nul" +input_touch_scale = "1" +input_turbo_default_button = "0" +input_turbo_mode = "0" +input_turbo_period = "6" +input_volume_down_axis = "nul" +input_volume_down_btn = "nul" +input_volume_down_mbtn = "nul" +input_volume_down = "subtract" +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_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_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.300000" +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_animation = "false" +menu_show_load_content = "true" +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_thumbnails = "3" +menu_thumbnail_upscale_threshold = "0" +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 = "0.350000" +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_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_p1 = "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_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_p1 = "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_duration = "2" +notification_show_screenshot = "false" +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 = "" +playlist_directory = "~/playlists" +playlist_entry_remove_enable = "1" +playlist_entry_remove = "false" +playlist_entry_rename = "false" +playlist_fuzzy_archive_match = "false" +playlist_names = "" +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" +savestates_in_content_dir = "false" +savestate_thumbnail_enable = "true" +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_interface = "true" +settings_show_user = "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 = "854" +video_fullscreen_y = "480" +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 = "480" +video_window_auto_width_max = "854" +video_window_custom_size_enable = "false" +video_windowed_fullscreen = "false" +video_windowed_position_height = "720" +video_windowed_position_width = "1280" +video_windowed_position_x = "0" +video_windowed_position_y = "0" +video_window_opacity = "100" +video_window_save_positions = "false" +video_window_show_decorations = "true" +vrr_runloop_enable = "false" +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 = "" +menu_driver = "ozone" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/S922X/retroarch32bit-append.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/S922X/retroarch32bit-append.cfg new file mode 100644 index 0000000000..343124c254 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/S922X/retroarch32bit-append.cfg @@ -0,0 +1,3 @@ +audio_filter_dir = "/usr/share/retroarch/filters/32bit/audio" +video_filter_dir = "/usr/share/retroarch/filters/32bit/video" +libretro_directory = /usr/lib32/libretro diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/S922X/retroarch64bit-append.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/S922X/retroarch64bit-append.cfg new file mode 100644 index 0000000000..b6cbf68312 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/S922X/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" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/SDM845/TATE-MAME 2003-Plus.rmp b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SDM845/TATE-MAME 2003-Plus.rmp new file mode 100755 index 0000000000..366e47afad --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SDM845/TATE-MAME 2003-Plus.rmp @@ -0,0 +1,27 @@ +input_libretro_device_p1 = "1" +input_libretro_device_p2 = "1" +input_libretro_device_p3 = "1" +input_libretro_device_p4 = "1" +input_libretro_device_p5 = "1" +input_player1_analog_dpad_mode = "1" +input_player1_btn_down = "6" +input_player1_btn_left = "4" +input_player1_btn_right = "5" +input_player1_btn_up = "7" +input_player1_stk_l_x+ = "5" +input_player1_stk_l_x- = "4" +input_player1_stk_l_y+ = "6" +input_player1_stk_l_y- = "7" +input_player1_stk_r_x+ = "5" +input_player1_stk_r_x- = "4" +input_player1_stk_r_y+ = "6" +input_player1_stk_r_y- = "7" +input_player2_analog_dpad_mode = "0" +input_player3_analog_dpad_mode = "0" +input_player4_analog_dpad_mode = "0" +input_player5_analog_dpad_mode = "0" +input_remap_port_p1 = "0" +input_remap_port_p2 = "1" +input_remap_port_p3 = "2" +input_remap_port_p4 = "3" +input_remap_port_p5 = "4" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/SDM845/retroarch-core-options.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SDM845/retroarch-core-options.cfg new file mode 100755 index 0000000000..0bcbaa2661 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SDM845/retroarch-core-options.cfg @@ -0,0 +1,152 @@ +mupen64plus-alt-map = "False" +mupen64plus-aspect = "4:3" +mupen64plus-astick-deadzone = "15" +mupen64plus-astick-sensitivity = "100" +mupen64plus-BackgroundMode = "Stripped" +mupen64plus-BilinearMode = "standard" +mupen64plus-CorrectTexrectCoords = "Auto" +mupen64plus-CountPerOp = "0" +mupen64plus-CountPerOpDenomPot = "0" +mupen64plus-cpucore = "dynamic_recompiler" +mupen64plus-d-cbutton = "C3" +mupen64plus-DitheringPattern = "True" +mupen64plus-DitheringQuantization = "True" +mupen64plus-EnableCopyAuxToRDRAM = "True" +mupen64plus-EnableCopyColorToRDRAM = "Async" +mupen64plus-EnableCopyDepthToRDRAM = "Software" +mupen64plus-EnableEnhancedHighResStorage = "False" +mupen64plus-EnableEnhancedTextureStorage = "False" +mupen64plus-EnableFBEmulation = "True" +mupen64plus-EnableFragmentDepthWrite = "False" +mupen64plus-EnableHiResAltCRC = "False" +mupen64plus-EnableHWLighting = "True" +mupen64plus-EnableInaccurateTextureCoordinates = "False" +mupen64plus-EnableLegacyBlending = "False" +mupen64plus-EnableLODEmulation = "True" +mupen64plus-EnableNativeResFactor = "1" +mupen64plus-EnableNativeResTexrects = "Optimized" +mupen64plus-EnableOverscan = "Enabled" +mupen64plus-EnableTexCoordBounds = "False" +mupen64plus-EnableTextureCache = "True" +mupen64plus-ForceDisableExtraMem = "False" +mupen64plus-FrameDuping = "True" +mupen64plus-Framerate = "Original" +mupen64plus-FXAA = "0" +mupen64plus-GLideN64IniBehaviour = "late" +mupen64plus-HybridFilter = "True" +mupen64plus-IgnoreTLBExceptions = "False" +mupen64plus-l-cbutton = "C2" +mupen64plus-MaxHiResTxVramLimit = "0" +mupen64plus-MaxTxCacheSize = "8000" +mupen64plus-MultiSampling = "0" +mupen64plus-OverscanBottom = "0" +mupen64plus-OverscanLeft = "0" +mupen64plus-OverscanRight = "0" +mupen64plus-OverscanTop = "0" +mupen64plus-pak1 = "memory" +mupen64plus-pak2 = "none" +mupen64plus-pak3 = "none" +mupen64plus-pak4 = "none" +mupen64plus-r-cbutton = "C1" +mupen64plus-rdp-plugin = "gliden64" +mupen64plus-RDRAMImageDitheringMode = "BlueNoise" +mupen64plus-rsp-plugin = "hle" +mupen64plus-ThreadedRenderer = "True" +mupen64plus-txCacheCompression = "True" +mupen64plus-txEnhancementMode = "None" +mupen64plus-txFilterIgnoreBG = "True" +mupen64plus-txFilterMode = "None" +mupen64plus-txHiresEnable = "False" +mupen64plus-txHiresFullAlphaChannel = "False" +mupen64plus-u-cbutton = "C4" +mupen64plus-virefresh = "Auto" +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_type = "disabled" +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" +flycast_auto_skip_frame = "normal" +opera_swi_hle = "enabled" +opera_dsp_threaded = "enabled" +opera_madam_matrix_engine = "software" +puae_deadzone = "25" +melonds_screen_layout = "Left/Right" +melonds_swapscreen_mode = "Toggle" +melonds_threaded_renderer = "enabled" +melonds_touch_mode = "Joystick" +virtualjaguar_bios = "enabled" +virtualjaguar_usefastblitter = "enabled" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/SDM845/retroarch.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SDM845/retroarch.cfg new file mode 100644 index 0000000000..d387d760d7 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SDM845/retroarch.cfg @@ -0,0 +1,894 @@ +accessibility_enable = "false" +accessibility_narrator_speech_speed = "5" +ai_service_mode = "1" +ai_service_pause = "false" +ai_service_source_lang = "0" +ai_service_target_lang = "0" +all_users_control_menu = "true" +app_icon = "default" +apply_cheats_after_load = "false" +apply_cheats_after_toggle = "false" +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_enable_menu_scroll = "false" +audio_fastforward_mute = "false" +audio_fastforward_speedup = "false" +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 = "false" +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 = "" +camera_allow = "false" +camera_device = "" +camera_driver = "null" +check_firmware_before_loading = "false" +cheevos_appearance_anchor = "0" +cheevos_appearance_padding_auto = "true" +cheevos_appearance_padding_h = "0.000000" +cheevos_appearance_padding_v = "0.000000" +cheevos_auto_screenshot = "false" +cheevos_badges_enable = "false" +cheevos_challenge_indicators = "true" +cheevos_custom_host = "" +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" +cheevos_visibility_account = "true" +cheevos_visibility_lboard_cancel = "true" +cheevos_visibility_lboard_start = "true" +cheevos_visibility_lboard_submit = "true" +cheevos_visibility_lboard_trackers = "true" +cheevos_visibility_mastery = "true" +cheevos_visibility_progress_tracker = "true" +cheevos_visibility_summary = "1" +cheevos_visibility_unlock = "true" +cloud_sync_destructive = "false" +cloud_sync_driver = "" +cloud_sync_enable = "false" +config_save_on_exit = "false" +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_contentless_cores = "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_info_savestate_bypass = "false" +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 = "interactive" +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 = "1080" +custom_viewport_width = "1920" +custom_viewport_x = "0" +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_frameskip = "true" +fastforward_ratio = "0.000000" +filter_by_current_core = "false" +flicker_filter_enable = "false" +flicker_filter_index = "0" +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" +gamemode_enable = "false" +gamma_correction = "0" +global_core_options = "false" +history_list_enable = "true" +initial_disk_change_enable = "true" +input_ai_service = "nul" +input_ai_service_axis = "nul" +input_ai_service_btn = "nul" +input_ai_service_mbtn = "nul" +input_allow_turbo_dpad = "false" +input_analog_deadzone = "0.100000" +input_analog_sensitivity = "1.500000" +input_audio_mute = "nul" +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 = "nul" +input_cheat_index_minus_axis = "nul" +input_cheat_index_minus_btn = "nul" +input_cheat_index_minus_mbtn = "nul" +input_cheat_index_plus = "nul" +input_cheat_index_plus_axis = "nul" +input_cheat_index_plus_btn = "nul" +input_cheat_index_plus_mbtn = "nul" +input_cheat_toggle = "nul" +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 = "nul" +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 = "nul" +input_exit_emulator_axis = "nul" +input_exit_emulator_btn = "nul" +input_exit_emulator_mbtn = "nul" +input_fps_toggle = "nul" +input_fps_toggle_axis = "nul" +input_fps_toggle_btn = "nul" +input_fps_toggle_mbtn = "nul" +input_frame_advance = "nul" +input_frame_advance_axis = "nul" +input_frame_advance_btn = "nul" +input_frame_advance_mbtn = "nul" +input_game_focus_toggle = "nul" +input_game_focus_toggle_axis = "nul" +input_game_focus_toggle_btn = "nul" +input_game_focus_toggle_mbtn = "nul" +input_grab_mouse_toggle = "nul" +input_grab_mouse_toggle_axis = "nul" +input_grab_mouse_toggle_btn = "nul" +input_grab_mouse_toggle_mbtn = "nul" +input_halt_replay = "nul" +input_halt_replay_axis = "nul" +input_halt_replay_btn = "nul" +input_halt_replay_mbtn = "nul" +input_hold_fast_forward = "nul" +input_hold_fast_forward_axis = "nul" +input_hold_fast_forward_btn = "nul" +input_hold_fast_forward_mbtn = "nul" +input_hold_slowmotion = "nul" +input_hold_slowmotion_axis = "nul" +input_hold_slowmotion_btn = "nul" +input_hold_slowmotion_mbtn = "nul" +input_hotkey_block_delay = "5" +input_hotkey_device_merge = "false" +input_joypad_driver = "sdl2" +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 = "nul" +input_load_state_axis = "nul" +input_load_state_btn = "nul" +input_load_state_mbtn = "nul" +input_max_users = "5" +input_menu_toggle = "nul" +input_menu_toggle_axis = "nul" +input_menu_toggle_btn = "nul" +input_menu_toggle_gamepad_combo = "nul" +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_fade_chat_toggle = "nul" +input_netplay_fade_chat_toggle_axis = "nul" +input_netplay_fade_chat_toggle_btn = "nul" +input_netplay_fade_chat_toggle_mbtn = "nul" +input_netplay_game_watch = "nul" +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_netplay_ping_toggle = "nul" +input_netplay_ping_toggle_axis = "nul" +input_netplay_ping_toggle_btn = "nul" +input_netplay_ping_toggle_mbtn = "nul" +input_netplay_player_chat = "nul" +input_netplay_player_chat_axis = "nul" +input_netplay_player_chat_btn = "nul" +input_netplay_player_chat_mbtn = "nul" +input_nowinkey_enable = "false" +input_osk_overlay = "" +input_osk_overlay_auto_scale = "false" +input_osk_overlay_opacity = "0.700000" +input_osk_toggle = "nul" +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_autopreferred = "true" +input_overlay_enable = "false" +input_overlay_hide_in_menu = "true" +input_overlay_hide_when_gamepad_connected = "false" +input_overlay_next_axis = "nul" +input_overlay_next_btn = "nul" +input_overlay_next_mbtn = "nul" +input_overlay_next = "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 = "nul" +input_pause_toggle_axis = "nul" +input_pause_toggle_btn = "nul" +input_pause_toggle_mbtn = "nul" +input_play_replay = "nul" +input_play_replay_axis = "nul" +input_play_replay_btn = "nul" +input_play_replay_mbtn = "nul" +input_poll_type_behavior = "2" +input_preempt_toggle = "nul" +input_preempt_toggle_axis = "nul" +input_preempt_toggle_btn = "nul" +input_preempt_toggle_mbtn = "nul" +input_quit_gamepad_combo = "0" +input_record_replay = "nul" +input_record_replay_axis = "nul" +input_record_replay_btn = "nul" +input_record_replay_mbtn = "nul" +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_replay_slot_decrease = "nul" +input_replay_slot_decrease_axis = "nul" +input_replay_slot_decrease_btn = "nul" +input_replay_slot_decrease_mbtn = "nul" +input_replay_slot_increase = "nul" +input_replay_slot_increase_axis = "nul" +input_replay_slot_increase_btn = "nul" +input_replay_slot_increase_mbtn = "nul" +input_reset = "nul" +input_reset_axis = "nul" +input_reset_btn = "nul" +input_reset_mbtn = "nul" +input_rewind = "nul" +input_rewind_axis = "nul" +input_rewind_btn = "nul" +input_rewind_mbtn = "nul" +input_rumble_gain = "25" +input_runahead_toggle = "nul" +input_runahead_toggle_axis = "nul" +input_runahead_toggle_btn = "nul" +input_runahead_toggle_mbtn = "nul" +input_save_state = "nul" +input_save_state_axis = "nul" +input_save_state_btn = "nul" +input_save_state_mbtn = "nul" +input_screenshot = "nul" +input_screenshot_axis = "nul" +input_screenshot_btn = "nul" +input_screenshot_mbtn = "nul" +input_send_debug_info = "nul" +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 = "nul" +input_shader_next_axis = "nul" +input_shader_next_btn = "nul" +input_shader_next_mbtn = "nul" +input_shader_prev = "nul" +input_shader_prev_axis = "nul" +input_shader_prev_btn = "nul" +input_shader_prev_mbtn = "nul" +input_shader_toggle = "nul" +input_shader_toggle_axis = "nul" +input_shader_toggle_btn = "nul" +input_shader_toggle_mbtn = "nul" +input_state_slot_decrease = "nul" +input_state_slot_decrease_axis = "nul" +input_state_slot_decrease_btn = "nul" +input_state_slot_decrease_mbtn = "nul" +input_state_slot_increase = "nul" +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 = "nul" +input_toggle_fast_forward_axis = "nul" +input_toggle_fast_forward_btn = "nul" +input_toggle_fast_forward_mbtn = "nul" +input_toggle_fullscreen = "nul" +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_toggle_statistics = "nul" +input_toggle_statistics_axis = "nul" +input_toggle_statistics_btn = "nul" +input_toggle_statistics_mbtn = "nul" +input_toggle_vrr_runloop = "nul" +input_toggle_vrr_runloop_axis = "nul" +input_toggle_vrr_runloop_btn = "nul" +input_toggle_vrr_runloop_mbtn = "nul" +input_touch_scale = "1" +input_touch_vmouse_gesture = "true" +input_touch_vmouse_mouse = "true" +input_touch_vmouse_pointer = "true" +input_touch_vmouse_touchpad = "true" +input_touch_vmouse_trackball = "false" +input_turbo_default_button = "0" +input_turbo_mode = "0" +input_turbo_period = "6" +input_volume_down = "nul" +input_volume_down_axis = "nul" +input_volume_down_btn = "nul" +input_volume_down_mbtn = "nul" +input_volume_up = "nul" +input_volume_up_axis = "nul" +input_volume_up_btn = "nul" +input_volume_up_mbtn = "nul" +keyboard_gamepad_enable = "true" +keyboard_gamepad_mapping_type = "1" +kiosk_mode_enable = "false" +kiosk_mode_password = "" +led_driver = "null" +libretro_log_level = "1" +load_dummy_on_core_shutdown = "true" +location_allow = "false" +location_driver = "null" +log_dir = "~/.config/retroarch/logs" +log_to_file = "true" +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_switch_icons = "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_disable_info_button = "false" +menu_disable_search_button = "false" +menu_driver = "ozone" +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 = "true" +menu_remember_selection = "1" +menu_rgui_full_width_layout = "true" +menu_rgui_shadows = "false" +menu_rgui_transparency = "true" +menu_savestate_resume = "true" +menu_scale_factor = "0.300000" +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_swap_scroll_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 = "0.350000" +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_show_title_header = "true" +menu_xmb_thumbnail_scale_factor = "100" +menu_xmb_title_margin = "5" +menu_xmb_title_margin_horizontal_offset = "0" +menu_xmb_vertical_fade_factor = "100" +microphone_block_frames = "0" +microphone_device = "" +microphone_driver = "alsathread" +microphone_enable = "true" +microphone_latency = "64" +microphone_rate = "48000" +microphone_resampler = "sinc" +microphone_resampler_quality = "3" +midi_driver = "alsa" +midi_input = "OFF" +midi_output = "OFF" +midi_volume = "100" +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_disk_control = "true" +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_save_state = "true" +notification_show_screenshot = "false" +notification_show_screenshot_duration = "2" +notification_show_screenshot_flash = "1" +notification_show_set_initial_disk = "true" +notification_show_when_menu_is_alive = "false" +osk_overlay_directory = "/tmp/overlays/keyboards" +ozone_collapse_sidebar = "false" +ozone_menu_color_theme = "1" +ozone_scroll_content_metadata = "false" +ozone_sort_after_truncate_playlist_name = "true" +ozone_thumbnail_scale_factor = "1.000000" +ozone_truncate_playlist_name = "true" +pause_nonactive = "true" +pause_on_disconnect = "false" +perfcnt_enable = "false" +playlist_compression = "false" +playlist_cores = "" +playlist_directory = "~/playlists" +playlist_entry_remove = "false" +playlist_entry_remove_enable = "1" +playlist_entry_rename = "false" +playlist_fuzzy_archive_match = "false" +playlist_names = "" +playlist_portable_paths = "false" +playlist_show_entry_idx = "true" +playlist_show_history_icons = "1" +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_filename = "false" +playlist_use_old_format = "false" +preemptive_frames_enable = "false" +preemptive_frames_hide_warnings = "false" +quick_menu_show_add_to_favorites = "true" +quick_menu_show_add_to_playlist = "false" +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_replay = "false" +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_savestate_submenu = "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" +remap_save_on_exit = "true" +replay_auto_index = "true" +replay_checkpoint_interval = "0" +replay_max_keep = "0" +replay_slot = "0" +resampler_directory = "" +rewind_buffer_size = "20971520" +rewind_buffer_size_step = "10" +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_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_file_compression = "true" +savestate_thumbnail_enable = "true" +savestates_in_content_dir = "false" +scan_serial_and_crc = "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" +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" +test_input_file_joypad = "" +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_autoswitch_pal_threshold = "54.500000" +video_autoswitch_refresh_rate = "0" +video_bfi_dark_frames = "1" +video_black_frame_insertion = "0" +video_context_driver = "" +video_crop_overscan = "true" +video_disable_composition = "false" +video_driver = "glcore" +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_frame_rest = "false" +video_fullscreen = "true" +video_fullscreen_x = "1920" +video_fullscreen_y = "1080" +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_frame_latency = "1" +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_scale = "3" +video_scan_subframes = "false" +video_shared_context = "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 = "false" +video_vsync = "true" +video_waitable_swapchains = "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 = "false" +vulkan_gpu_index = "0" +webdav_password = "" +webdav_url = "" +webdav_username = "" +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_switch_icons = "true" +xmb_theme = "0" +xmb_vertical_thumbnails = "false" +youtube_stream_key = "" +assets_directory = "/tmp/assets" +cache_directory = "/tmp/cache" +cheat_database_path = "/tmp/database/cht" +content_database_path = "/tmp/database/rdb" +joypad_autoconfig_dir = "/tmp/joypads" +libretro_directory = "/tmp/cores" +libretro_info_path = "/tmp/cores" +overlay_directory = "/tmp/overlays" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/SDM845/retroarch32bit-append.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SDM845/retroarch32bit-append.cfg new file mode 100755 index 0000000000..343124c254 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SDM845/retroarch32bit-append.cfg @@ -0,0 +1,3 @@ +audio_filter_dir = "/usr/share/retroarch/filters/32bit/audio" +video_filter_dir = "/usr/share/retroarch/filters/32bit/video" +libretro_directory = /usr/lib32/libretro diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/SDM845/retroarch64bit-append.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SDM845/retroarch64bit-append.cfg new file mode 100755 index 0000000000..b6cbf68312 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SDM845/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" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8250/TATE-MAME 2003-Plus.rmp b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8250/TATE-MAME 2003-Plus.rmp new file mode 100755 index 0000000000..366e47afad --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8250/TATE-MAME 2003-Plus.rmp @@ -0,0 +1,27 @@ +input_libretro_device_p1 = "1" +input_libretro_device_p2 = "1" +input_libretro_device_p3 = "1" +input_libretro_device_p4 = "1" +input_libretro_device_p5 = "1" +input_player1_analog_dpad_mode = "1" +input_player1_btn_down = "6" +input_player1_btn_left = "4" +input_player1_btn_right = "5" +input_player1_btn_up = "7" +input_player1_stk_l_x+ = "5" +input_player1_stk_l_x- = "4" +input_player1_stk_l_y+ = "6" +input_player1_stk_l_y- = "7" +input_player1_stk_r_x+ = "5" +input_player1_stk_r_x- = "4" +input_player1_stk_r_y+ = "6" +input_player1_stk_r_y- = "7" +input_player2_analog_dpad_mode = "0" +input_player3_analog_dpad_mode = "0" +input_player4_analog_dpad_mode = "0" +input_player5_analog_dpad_mode = "0" +input_remap_port_p1 = "0" +input_remap_port_p2 = "1" +input_remap_port_p3 = "2" +input_remap_port_p4 = "3" +input_remap_port_p5 = "4" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8250/retroarch-core-options.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8250/retroarch-core-options.cfg new file mode 100755 index 0000000000..0bcbaa2661 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8250/retroarch-core-options.cfg @@ -0,0 +1,152 @@ +mupen64plus-alt-map = "False" +mupen64plus-aspect = "4:3" +mupen64plus-astick-deadzone = "15" +mupen64plus-astick-sensitivity = "100" +mupen64plus-BackgroundMode = "Stripped" +mupen64plus-BilinearMode = "standard" +mupen64plus-CorrectTexrectCoords = "Auto" +mupen64plus-CountPerOp = "0" +mupen64plus-CountPerOpDenomPot = "0" +mupen64plus-cpucore = "dynamic_recompiler" +mupen64plus-d-cbutton = "C3" +mupen64plus-DitheringPattern = "True" +mupen64plus-DitheringQuantization = "True" +mupen64plus-EnableCopyAuxToRDRAM = "True" +mupen64plus-EnableCopyColorToRDRAM = "Async" +mupen64plus-EnableCopyDepthToRDRAM = "Software" +mupen64plus-EnableEnhancedHighResStorage = "False" +mupen64plus-EnableEnhancedTextureStorage = "False" +mupen64plus-EnableFBEmulation = "True" +mupen64plus-EnableFragmentDepthWrite = "False" +mupen64plus-EnableHiResAltCRC = "False" +mupen64plus-EnableHWLighting = "True" +mupen64plus-EnableInaccurateTextureCoordinates = "False" +mupen64plus-EnableLegacyBlending = "False" +mupen64plus-EnableLODEmulation = "True" +mupen64plus-EnableNativeResFactor = "1" +mupen64plus-EnableNativeResTexrects = "Optimized" +mupen64plus-EnableOverscan = "Enabled" +mupen64plus-EnableTexCoordBounds = "False" +mupen64plus-EnableTextureCache = "True" +mupen64plus-ForceDisableExtraMem = "False" +mupen64plus-FrameDuping = "True" +mupen64plus-Framerate = "Original" +mupen64plus-FXAA = "0" +mupen64plus-GLideN64IniBehaviour = "late" +mupen64plus-HybridFilter = "True" +mupen64plus-IgnoreTLBExceptions = "False" +mupen64plus-l-cbutton = "C2" +mupen64plus-MaxHiResTxVramLimit = "0" +mupen64plus-MaxTxCacheSize = "8000" +mupen64plus-MultiSampling = "0" +mupen64plus-OverscanBottom = "0" +mupen64plus-OverscanLeft = "0" +mupen64plus-OverscanRight = "0" +mupen64plus-OverscanTop = "0" +mupen64plus-pak1 = "memory" +mupen64plus-pak2 = "none" +mupen64plus-pak3 = "none" +mupen64plus-pak4 = "none" +mupen64plus-r-cbutton = "C1" +mupen64plus-rdp-plugin = "gliden64" +mupen64plus-RDRAMImageDitheringMode = "BlueNoise" +mupen64plus-rsp-plugin = "hle" +mupen64plus-ThreadedRenderer = "True" +mupen64plus-txCacheCompression = "True" +mupen64plus-txEnhancementMode = "None" +mupen64plus-txFilterIgnoreBG = "True" +mupen64plus-txFilterMode = "None" +mupen64plus-txHiresEnable = "False" +mupen64plus-txHiresFullAlphaChannel = "False" +mupen64plus-u-cbutton = "C4" +mupen64plus-virefresh = "Auto" +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_type = "disabled" +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" +flycast_auto_skip_frame = "normal" +opera_swi_hle = "enabled" +opera_dsp_threaded = "enabled" +opera_madam_matrix_engine = "software" +puae_deadzone = "25" +melonds_screen_layout = "Left/Right" +melonds_swapscreen_mode = "Toggle" +melonds_threaded_renderer = "enabled" +melonds_touch_mode = "Joystick" +virtualjaguar_bios = "enabled" +virtualjaguar_usefastblitter = "enabled" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8250/retroarch.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8250/retroarch.cfg new file mode 100644 index 0000000000..25942da255 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8250/retroarch.cfg @@ -0,0 +1,894 @@ +accessibility_enable = "false" +accessibility_narrator_speech_speed = "5" +ai_service_mode = "1" +ai_service_pause = "false" +ai_service_source_lang = "0" +ai_service_target_lang = "0" +all_users_control_menu = "true" +app_icon = "default" +apply_cheats_after_load = "false" +apply_cheats_after_toggle = "false" +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_enable_menu_scroll = "false" +audio_fastforward_mute = "false" +audio_fastforward_speedup = "false" +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 = "false" +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 = "" +camera_allow = "false" +camera_device = "" +camera_driver = "null" +check_firmware_before_loading = "false" +cheevos_appearance_anchor = "0" +cheevos_appearance_padding_auto = "true" +cheevos_appearance_padding_h = "0.000000" +cheevos_appearance_padding_v = "0.000000" +cheevos_auto_screenshot = "false" +cheevos_badges_enable = "false" +cheevos_challenge_indicators = "true" +cheevos_custom_host = "" +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" +cheevos_visibility_account = "true" +cheevos_visibility_lboard_cancel = "true" +cheevos_visibility_lboard_start = "true" +cheevos_visibility_lboard_submit = "true" +cheevos_visibility_lboard_trackers = "true" +cheevos_visibility_mastery = "true" +cheevos_visibility_progress_tracker = "true" +cheevos_visibility_summary = "1" +cheevos_visibility_unlock = "true" +cloud_sync_destructive = "false" +cloud_sync_driver = "" +cloud_sync_enable = "false" +config_save_on_exit = "false" +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_contentless_cores = "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_info_savestate_bypass = "false" +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 = "interactive" +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 = "1080" +custom_viewport_width = "1920" +custom_viewport_x = "0" +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_frameskip = "true" +fastforward_ratio = "0.000000" +filter_by_current_core = "false" +flicker_filter_enable = "false" +flicker_filter_index = "0" +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" +gamemode_enable = "false" +gamma_correction = "0" +global_core_options = "false" +history_list_enable = "true" +initial_disk_change_enable = "true" +input_ai_service = "nul" +input_ai_service_axis = "nul" +input_ai_service_btn = "nul" +input_ai_service_mbtn = "nul" +input_allow_turbo_dpad = "false" +input_analog_deadzone = "0.100000" +input_analog_sensitivity = "1.500000" +input_audio_mute = "nul" +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 = "nul" +input_cheat_index_minus_axis = "nul" +input_cheat_index_minus_btn = "nul" +input_cheat_index_minus_mbtn = "nul" +input_cheat_index_plus = "nul" +input_cheat_index_plus_axis = "nul" +input_cheat_index_plus_btn = "nul" +input_cheat_index_plus_mbtn = "nul" +input_cheat_toggle = "nul" +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 = "5" +input_enable_hotkey_mbtn = "nul" +input_exit_emulator = "nul" +input_exit_emulator_axis = "nul" +input_exit_emulator_btn = "6" +input_exit_emulator_mbtn = "nul" +input_fps_toggle = "nul" +input_fps_toggle_axis = "nul" +input_fps_toggle_btn = "3" +input_fps_toggle_mbtn = "nul" +input_frame_advance = "nul" +input_frame_advance_axis = "nul" +input_frame_advance_btn = "nul" +input_frame_advance_mbtn = "nul" +input_game_focus_toggle = "nul" +input_game_focus_toggle_axis = "nul" +input_game_focus_toggle_btn = "nul" +input_game_focus_toggle_mbtn = "nul" +input_grab_mouse_toggle = "nul" +input_grab_mouse_toggle_axis = "nul" +input_grab_mouse_toggle_btn = "nul" +input_grab_mouse_toggle_mbtn = "nul" +input_halt_replay = "nul" +input_halt_replay_axis = "nul" +input_halt_replay_btn = "nul" +input_halt_replay_mbtn = "nul" +input_hold_fast_forward = "nul" +input_hold_fast_forward_axis = "+5" +input_hold_fast_forward_btn = "nul" +input_hold_fast_forward_mbtn = "nul" +input_hold_slowmotion = "nul" +input_hold_slowmotion_axis = "nul" +input_hold_slowmotion_btn = "nul" +input_hold_slowmotion_mbtn = "nul" +input_hotkey_block_delay = "5" +input_hotkey_device_merge = "false" +input_joypad_driver = "sdl2" +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 = "nul" +input_load_state_axis = "nul" +input_load_state_btn = "9" +input_load_state_mbtn = "nul" +input_max_users = "5" +input_menu_toggle = "nul" +input_menu_toggle_axis = "nul" +input_menu_toggle_btn = "2" +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_fade_chat_toggle = "nul" +input_netplay_fade_chat_toggle_axis = "nul" +input_netplay_fade_chat_toggle_btn = "nul" +input_netplay_fade_chat_toggle_mbtn = "nul" +input_netplay_game_watch = "nul" +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_netplay_ping_toggle = "nul" +input_netplay_ping_toggle_axis = "nul" +input_netplay_ping_toggle_btn = "nul" +input_netplay_ping_toggle_mbtn = "nul" +input_netplay_player_chat = "nul" +input_netplay_player_chat_axis = "nul" +input_netplay_player_chat_btn = "nul" +input_netplay_player_chat_mbtn = "nul" +input_nowinkey_enable = "false" +input_osk_overlay = "" +input_osk_overlay_auto_scale = "false" +input_osk_overlay_opacity = "0.700000" +input_osk_toggle = "nul" +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_autopreferred = "true" +input_overlay_enable = "false" +input_overlay_hide_in_menu = "true" +input_overlay_hide_when_gamepad_connected = "false" +input_overlay_next_axis = "nul" +input_overlay_next_btn = "nul" +input_overlay_next_mbtn = "nul" +input_overlay_next = "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 = "nul" +input_pause_toggle_axis = "nul" +input_pause_toggle_btn = "nul" +input_pause_toggle_mbtn = "nul" +input_play_replay = "nul" +input_play_replay_axis = "nul" +input_play_replay_btn = "nul" +input_play_replay_mbtn = "nul" +input_poll_type_behavior = "2" +input_preempt_toggle = "nul" +input_preempt_toggle_axis = "nul" +input_preempt_toggle_btn = "nul" +input_preempt_toggle_mbtn = "nul" +input_quit_gamepad_combo = "0" +input_record_replay = "nul" +input_record_replay_axis = "nul" +input_record_replay_btn = "nul" +input_record_replay_mbtn = "nul" +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_replay_slot_decrease = "nul" +input_replay_slot_decrease_axis = "nul" +input_replay_slot_decrease_btn = "nul" +input_replay_slot_decrease_mbtn = "nul" +input_replay_slot_increase = "nul" +input_replay_slot_increase_axis = "nul" +input_replay_slot_increase_btn = "nul" +input_replay_slot_increase_mbtn = "nul" +input_reset = "nul" +input_reset_axis = "nul" +input_reset_btn = "nul" +input_reset_mbtn = "nul" +input_rewind = "nul" +input_rewind_axis = "+4" +input_rewind_btn = "nul" +input_rewind_mbtn = "nul" +input_rumble_gain = "25" +input_runahead_toggle = "nul" +input_runahead_toggle_axis = "nul" +input_runahead_toggle_btn = "nul" +input_runahead_toggle_mbtn = "nul" +input_save_state = "nul" +input_save_state_axis = "nul" +input_save_state_btn = "10" +input_save_state_mbtn = "nul" +input_screenshot = "nul" +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 = "nul" +input_shader_next_axis = "nul" +input_shader_next_btn = "nul" +input_shader_next_mbtn = "nul" +input_shader_prev = "nul" +input_shader_prev_axis = "nul" +input_shader_prev_btn = "nul" +input_shader_prev_mbtn = "nul" +input_shader_toggle = "nul" +input_shader_toggle_axis = "nul" +input_shader_toggle_btn = "nul" +input_shader_toggle_mbtn = "nul" +input_state_slot_decrease = "nul" +input_state_slot_decrease_axis = "nul" +input_state_slot_decrease_btn = "nul" +input_state_slot_decrease_mbtn = "nul" +input_state_slot_increase = "nul" +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 = "nul" +input_toggle_fast_forward_axis = "nul" +input_toggle_fast_forward_btn = "nul" +input_toggle_fast_forward_mbtn = "nul" +input_toggle_fullscreen = "nul" +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_toggle_statistics = "nul" +input_toggle_statistics_axis = "nul" +input_toggle_statistics_btn = "nul" +input_toggle_statistics_mbtn = "nul" +input_toggle_vrr_runloop = "nul" +input_toggle_vrr_runloop_axis = "nul" +input_toggle_vrr_runloop_btn = "nul" +input_toggle_vrr_runloop_mbtn = "nul" +input_touch_scale = "1" +input_touch_vmouse_gesture = "true" +input_touch_vmouse_mouse = "true" +input_touch_vmouse_pointer = "true" +input_touch_vmouse_touchpad = "true" +input_touch_vmouse_trackball = "false" +input_turbo_default_button = "0" +input_turbo_mode = "0" +input_turbo_period = "6" +input_volume_down = "nul" +input_volume_down_axis = "nul" +input_volume_down_btn = "nul" +input_volume_down_mbtn = "nul" +input_volume_up = "nul" +input_volume_up_axis = "nul" +input_volume_up_btn = "nul" +input_volume_up_mbtn = "nul" +keyboard_gamepad_enable = "true" +keyboard_gamepad_mapping_type = "1" +kiosk_mode_enable = "false" +kiosk_mode_password = "" +led_driver = "null" +libretro_log_level = "1" +load_dummy_on_core_shutdown = "true" +location_allow = "false" +location_driver = "null" +log_dir = "~/.config/retroarch/logs" +log_to_file = "true" +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_switch_icons = "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_disable_info_button = "false" +menu_disable_search_button = "false" +menu_driver = "ozone" +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 = "true" +menu_remember_selection = "1" +menu_rgui_full_width_layout = "true" +menu_rgui_shadows = "false" +menu_rgui_transparency = "true" +menu_savestate_resume = "true" +menu_scale_factor = "0.300000" +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_swap_scroll_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 = "0.350000" +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_show_title_header = "true" +menu_xmb_thumbnail_scale_factor = "100" +menu_xmb_title_margin = "5" +menu_xmb_title_margin_horizontal_offset = "0" +menu_xmb_vertical_fade_factor = "100" +microphone_block_frames = "0" +microphone_device = "" +microphone_driver = "alsathread" +microphone_enable = "true" +microphone_latency = "64" +microphone_rate = "48000" +microphone_resampler = "sinc" +microphone_resampler_quality = "3" +midi_driver = "alsa" +midi_input = "OFF" +midi_output = "OFF" +midi_volume = "100" +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_disk_control = "true" +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_save_state = "true" +notification_show_screenshot = "false" +notification_show_screenshot_duration = "2" +notification_show_screenshot_flash = "1" +notification_show_set_initial_disk = "true" +notification_show_when_menu_is_alive = "false" +osk_overlay_directory = "/tmp/overlays/keyboards" +ozone_collapse_sidebar = "false" +ozone_menu_color_theme = "1" +ozone_scroll_content_metadata = "false" +ozone_sort_after_truncate_playlist_name = "true" +ozone_thumbnail_scale_factor = "1.000000" +ozone_truncate_playlist_name = "true" +pause_nonactive = "true" +pause_on_disconnect = "false" +perfcnt_enable = "false" +playlist_compression = "false" +playlist_cores = "" +playlist_directory = "~/playlists" +playlist_entry_remove = "false" +playlist_entry_remove_enable = "1" +playlist_entry_rename = "false" +playlist_fuzzy_archive_match = "false" +playlist_names = "" +playlist_portable_paths = "false" +playlist_show_entry_idx = "true" +playlist_show_history_icons = "1" +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_filename = "false" +playlist_use_old_format = "false" +preemptive_frames_enable = "false" +preemptive_frames_hide_warnings = "false" +quick_menu_show_add_to_favorites = "true" +quick_menu_show_add_to_playlist = "false" +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_replay = "false" +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_savestate_submenu = "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" +remap_save_on_exit = "true" +replay_auto_index = "true" +replay_checkpoint_interval = "0" +replay_max_keep = "0" +replay_slot = "0" +resampler_directory = "" +rewind_buffer_size = "20971520" +rewind_buffer_size_step = "10" +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_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_file_compression = "true" +savestate_thumbnail_enable = "true" +savestates_in_content_dir = "false" +scan_serial_and_crc = "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" +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" +test_input_file_joypad = "" +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_autoswitch_pal_threshold = "54.500000" +video_autoswitch_refresh_rate = "0" +video_bfi_dark_frames = "1" +video_black_frame_insertion = "0" +video_context_driver = "" +video_crop_overscan = "true" +video_disable_composition = "false" +video_driver = "glcore" +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_frame_rest = "false" +video_fullscreen = "true" +video_fullscreen_x = "1920" +video_fullscreen_y = "1080" +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_frame_latency = "1" +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_scale = "3" +video_scan_subframes = "false" +video_shared_context = "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 = "false" +video_vsync = "true" +video_waitable_swapchains = "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 = "false" +vulkan_gpu_index = "0" +webdav_password = "" +webdav_url = "" +webdav_username = "" +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_switch_icons = "true" +xmb_theme = "0" +xmb_vertical_thumbnails = "false" +youtube_stream_key = "" +assets_directory = "/tmp/assets" +cache_directory = "/tmp/cache" +cheat_database_path = "/tmp/database/cht" +content_database_path = "/tmp/database/rdb" +joypad_autoconfig_dir = "/tmp/joypads" +libretro_directory = "/tmp/cores" +libretro_info_path = "/tmp/cores" +overlay_directory = "/tmp/overlays" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8250/retroarch32bit-append.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8250/retroarch32bit-append.cfg new file mode 100755 index 0000000000..343124c254 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8250/retroarch32bit-append.cfg @@ -0,0 +1,3 @@ +audio_filter_dir = "/usr/share/retroarch/filters/32bit/audio" +video_filter_dir = "/usr/share/retroarch/filters/32bit/video" +libretro_directory = /usr/lib32/libretro diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8250/retroarch64bit-append.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8250/retroarch64bit-append.cfg new file mode 100755 index 0000000000..b6cbf68312 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8250/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" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8550/TATE-MAME 2003-Plus.rmp b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8550/TATE-MAME 2003-Plus.rmp new file mode 100755 index 0000000000..366e47afad --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8550/TATE-MAME 2003-Plus.rmp @@ -0,0 +1,27 @@ +input_libretro_device_p1 = "1" +input_libretro_device_p2 = "1" +input_libretro_device_p3 = "1" +input_libretro_device_p4 = "1" +input_libretro_device_p5 = "1" +input_player1_analog_dpad_mode = "1" +input_player1_btn_down = "6" +input_player1_btn_left = "4" +input_player1_btn_right = "5" +input_player1_btn_up = "7" +input_player1_stk_l_x+ = "5" +input_player1_stk_l_x- = "4" +input_player1_stk_l_y+ = "6" +input_player1_stk_l_y- = "7" +input_player1_stk_r_x+ = "5" +input_player1_stk_r_x- = "4" +input_player1_stk_r_y+ = "6" +input_player1_stk_r_y- = "7" +input_player2_analog_dpad_mode = "0" +input_player3_analog_dpad_mode = "0" +input_player4_analog_dpad_mode = "0" +input_player5_analog_dpad_mode = "0" +input_remap_port_p1 = "0" +input_remap_port_p2 = "1" +input_remap_port_p3 = "2" +input_remap_port_p4 = "3" +input_remap_port_p5 = "4" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8550/retroarch-core-options.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8550/retroarch-core-options.cfg new file mode 100755 index 0000000000..0bcbaa2661 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8550/retroarch-core-options.cfg @@ -0,0 +1,152 @@ +mupen64plus-alt-map = "False" +mupen64plus-aspect = "4:3" +mupen64plus-astick-deadzone = "15" +mupen64plus-astick-sensitivity = "100" +mupen64plus-BackgroundMode = "Stripped" +mupen64plus-BilinearMode = "standard" +mupen64plus-CorrectTexrectCoords = "Auto" +mupen64plus-CountPerOp = "0" +mupen64plus-CountPerOpDenomPot = "0" +mupen64plus-cpucore = "dynamic_recompiler" +mupen64plus-d-cbutton = "C3" +mupen64plus-DitheringPattern = "True" +mupen64plus-DitheringQuantization = "True" +mupen64plus-EnableCopyAuxToRDRAM = "True" +mupen64plus-EnableCopyColorToRDRAM = "Async" +mupen64plus-EnableCopyDepthToRDRAM = "Software" +mupen64plus-EnableEnhancedHighResStorage = "False" +mupen64plus-EnableEnhancedTextureStorage = "False" +mupen64plus-EnableFBEmulation = "True" +mupen64plus-EnableFragmentDepthWrite = "False" +mupen64plus-EnableHiResAltCRC = "False" +mupen64plus-EnableHWLighting = "True" +mupen64plus-EnableInaccurateTextureCoordinates = "False" +mupen64plus-EnableLegacyBlending = "False" +mupen64plus-EnableLODEmulation = "True" +mupen64plus-EnableNativeResFactor = "1" +mupen64plus-EnableNativeResTexrects = "Optimized" +mupen64plus-EnableOverscan = "Enabled" +mupen64plus-EnableTexCoordBounds = "False" +mupen64plus-EnableTextureCache = "True" +mupen64plus-ForceDisableExtraMem = "False" +mupen64plus-FrameDuping = "True" +mupen64plus-Framerate = "Original" +mupen64plus-FXAA = "0" +mupen64plus-GLideN64IniBehaviour = "late" +mupen64plus-HybridFilter = "True" +mupen64plus-IgnoreTLBExceptions = "False" +mupen64plus-l-cbutton = "C2" +mupen64plus-MaxHiResTxVramLimit = "0" +mupen64plus-MaxTxCacheSize = "8000" +mupen64plus-MultiSampling = "0" +mupen64plus-OverscanBottom = "0" +mupen64plus-OverscanLeft = "0" +mupen64plus-OverscanRight = "0" +mupen64plus-OverscanTop = "0" +mupen64plus-pak1 = "memory" +mupen64plus-pak2 = "none" +mupen64plus-pak3 = "none" +mupen64plus-pak4 = "none" +mupen64plus-r-cbutton = "C1" +mupen64plus-rdp-plugin = "gliden64" +mupen64plus-RDRAMImageDitheringMode = "BlueNoise" +mupen64plus-rsp-plugin = "hle" +mupen64plus-ThreadedRenderer = "True" +mupen64plus-txCacheCompression = "True" +mupen64plus-txEnhancementMode = "None" +mupen64plus-txFilterIgnoreBG = "True" +mupen64plus-txFilterMode = "None" +mupen64plus-txHiresEnable = "False" +mupen64plus-txHiresFullAlphaChannel = "False" +mupen64plus-u-cbutton = "C4" +mupen64plus-virefresh = "Auto" +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_type = "disabled" +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" +flycast_auto_skip_frame = "normal" +opera_swi_hle = "enabled" +opera_dsp_threaded = "enabled" +opera_madam_matrix_engine = "software" +puae_deadzone = "25" +melonds_screen_layout = "Left/Right" +melonds_swapscreen_mode = "Toggle" +melonds_threaded_renderer = "enabled" +melonds_touch_mode = "Joystick" +virtualjaguar_bios = "enabled" +virtualjaguar_usefastblitter = "enabled" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8550/retroarch.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8550/retroarch.cfg new file mode 100644 index 0000000000..8eb383db75 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8550/retroarch.cfg @@ -0,0 +1,894 @@ +accessibility_enable = "false" +accessibility_narrator_speech_speed = "5" +ai_service_mode = "1" +ai_service_pause = "false" +ai_service_source_lang = "0" +ai_service_target_lang = "0" +all_users_control_menu = "true" +app_icon = "default" +apply_cheats_after_load = "false" +apply_cheats_after_toggle = "false" +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_enable_menu_scroll = "false" +audio_fastforward_mute = "false" +audio_fastforward_speedup = "false" +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 = "false" +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 = "" +camera_allow = "false" +camera_device = "" +camera_driver = "null" +check_firmware_before_loading = "false" +cheevos_appearance_anchor = "0" +cheevos_appearance_padding_auto = "true" +cheevos_appearance_padding_h = "0.000000" +cheevos_appearance_padding_v = "0.000000" +cheevos_auto_screenshot = "false" +cheevos_badges_enable = "false" +cheevos_challenge_indicators = "true" +cheevos_custom_host = "" +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" +cheevos_visibility_account = "true" +cheevos_visibility_lboard_cancel = "true" +cheevos_visibility_lboard_start = "true" +cheevos_visibility_lboard_submit = "true" +cheevos_visibility_lboard_trackers = "true" +cheevos_visibility_mastery = "true" +cheevos_visibility_progress_tracker = "true" +cheevos_visibility_summary = "1" +cheevos_visibility_unlock = "true" +cloud_sync_destructive = "false" +cloud_sync_driver = "" +cloud_sync_enable = "false" +config_save_on_exit = "false" +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_contentless_cores = "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_info_savestate_bypass = "false" +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 = "interactive" +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 = "1080" +custom_viewport_width = "1920" +custom_viewport_x = "0" +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_frameskip = "true" +fastforward_ratio = "0.000000" +filter_by_current_core = "false" +flicker_filter_enable = "false" +flicker_filter_index = "0" +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" +gamemode_enable = "false" +gamma_correction = "0" +global_core_options = "false" +history_list_enable = "true" +initial_disk_change_enable = "true" +input_ai_service = "nul" +input_ai_service_axis = "nul" +input_ai_service_btn = "nul" +input_ai_service_mbtn = "nul" +input_allow_turbo_dpad = "false" +input_analog_deadzone = "0.100000" +input_analog_sensitivity = "1.500000" +input_audio_mute = "nul" +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 = "nul" +input_cheat_index_minus_axis = "nul" +input_cheat_index_minus_btn = "nul" +input_cheat_index_minus_mbtn = "nul" +input_cheat_index_plus = "nul" +input_cheat_index_plus_axis = "nul" +input_cheat_index_plus_btn = "nul" +input_cheat_index_plus_mbtn = "nul" +input_cheat_toggle = "nul" +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 = "nul" +input_exit_emulator_axis = "nul" +input_exit_emulator_btn = "nul" +input_exit_emulator_mbtn = "nul" +input_fps_toggle = "nul" +input_fps_toggle_axis = "nul" +input_fps_toggle_btn = "nul" +input_fps_toggle_mbtn = "nul" +input_frame_advance = "nul" +input_frame_advance_axis = "nul" +input_frame_advance_btn = "nul" +input_frame_advance_mbtn = "nul" +input_game_focus_toggle = "nul" +input_game_focus_toggle_axis = "nul" +input_game_focus_toggle_btn = "nul" +input_game_focus_toggle_mbtn = "nul" +input_grab_mouse_toggle = "nul" +input_grab_mouse_toggle_axis = "nul" +input_grab_mouse_toggle_btn = "nul" +input_grab_mouse_toggle_mbtn = "nul" +input_halt_replay = "nul" +input_halt_replay_axis = "nul" +input_halt_replay_btn = "nul" +input_halt_replay_mbtn = "nul" +input_hold_fast_forward = "nul" +input_hold_fast_forward_axis = "nul" +input_hold_fast_forward_btn = "nul" +input_hold_fast_forward_mbtn = "nul" +input_hold_slowmotion = "nul" +input_hold_slowmotion_axis = "nul" +input_hold_slowmotion_btn = "nul" +input_hold_slowmotion_mbtn = "nul" +input_hotkey_block_delay = "5" +input_hotkey_device_merge = "false" +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 = "nul" +input_load_state_axis = "nul" +input_load_state_btn = "nul" +input_load_state_mbtn = "nul" +input_max_users = "5" +input_menu_toggle = "nul" +input_menu_toggle_axis = "nul" +input_menu_toggle_btn = "nul" +input_menu_toggle_gamepad_combo = "nul" +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_fade_chat_toggle = "nul" +input_netplay_fade_chat_toggle_axis = "nul" +input_netplay_fade_chat_toggle_btn = "nul" +input_netplay_fade_chat_toggle_mbtn = "nul" +input_netplay_game_watch = "nul" +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_netplay_ping_toggle = "nul" +input_netplay_ping_toggle_axis = "nul" +input_netplay_ping_toggle_btn = "nul" +input_netplay_ping_toggle_mbtn = "nul" +input_netplay_player_chat = "nul" +input_netplay_player_chat_axis = "nul" +input_netplay_player_chat_btn = "nul" +input_netplay_player_chat_mbtn = "nul" +input_nowinkey_enable = "false" +input_osk_overlay = "" +input_osk_overlay_auto_scale = "false" +input_osk_overlay_opacity = "0.700000" +input_osk_toggle = "nul" +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_autopreferred = "true" +input_overlay_enable = "false" +input_overlay_hide_in_menu = "true" +input_overlay_hide_when_gamepad_connected = "false" +input_overlay_next_axis = "nul" +input_overlay_next_btn = "nul" +input_overlay_next_mbtn = "nul" +input_overlay_next = "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 = "nul" +input_pause_toggle_axis = "nul" +input_pause_toggle_btn = "nul" +input_pause_toggle_mbtn = "nul" +input_play_replay = "nul" +input_play_replay_axis = "nul" +input_play_replay_btn = "nul" +input_play_replay_mbtn = "nul" +input_poll_type_behavior = "2" +input_preempt_toggle = "nul" +input_preempt_toggle_axis = "nul" +input_preempt_toggle_btn = "nul" +input_preempt_toggle_mbtn = "nul" +input_quit_gamepad_combo = "0" +input_record_replay = "nul" +input_record_replay_axis = "nul" +input_record_replay_btn = "nul" +input_record_replay_mbtn = "nul" +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_replay_slot_decrease = "nul" +input_replay_slot_decrease_axis = "nul" +input_replay_slot_decrease_btn = "nul" +input_replay_slot_decrease_mbtn = "nul" +input_replay_slot_increase = "nul" +input_replay_slot_increase_axis = "nul" +input_replay_slot_increase_btn = "nul" +input_replay_slot_increase_mbtn = "nul" +input_reset = "nul" +input_reset_axis = "nul" +input_reset_btn = "nul" +input_reset_mbtn = "nul" +input_rewind = "nul" +input_rewind_axis = "nul" +input_rewind_btn = "nul" +input_rewind_mbtn = "nul" +input_rumble_gain = "25" +input_runahead_toggle = "nul" +input_runahead_toggle_axis = "nul" +input_runahead_toggle_btn = "nul" +input_runahead_toggle_mbtn = "nul" +input_save_state = "nul" +input_save_state_axis = "nul" +input_save_state_btn = "nul" +input_save_state_mbtn = "nul" +input_screenshot = "nul" +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 = "nul" +input_shader_next_axis = "nul" +input_shader_next_btn = "nul" +input_shader_next_mbtn = "nul" +input_shader_prev = "nul" +input_shader_prev_axis = "nul" +input_shader_prev_btn = "nul" +input_shader_prev_mbtn = "nul" +input_shader_toggle = "nul" +input_shader_toggle_axis = "nul" +input_shader_toggle_btn = "nul" +input_shader_toggle_mbtn = "nul" +input_state_slot_decrease = "nul" +input_state_slot_decrease_axis = "nul" +input_state_slot_decrease_btn = "nul" +input_state_slot_decrease_mbtn = "nul" +input_state_slot_increase = "nul" +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 = "nul" +input_toggle_fast_forward_axis = "nul" +input_toggle_fast_forward_btn = "nul" +input_toggle_fast_forward_mbtn = "nul" +input_toggle_fullscreen = "nul" +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_toggle_statistics = "nul" +input_toggle_statistics_axis = "nul" +input_toggle_statistics_btn = "nul" +input_toggle_statistics_mbtn = "nul" +input_toggle_vrr_runloop = "nul" +input_toggle_vrr_runloop_axis = "nul" +input_toggle_vrr_runloop_btn = "nul" +input_toggle_vrr_runloop_mbtn = "nul" +input_touch_scale = "1" +input_touch_vmouse_gesture = "true" +input_touch_vmouse_mouse = "true" +input_touch_vmouse_pointer = "true" +input_touch_vmouse_touchpad = "true" +input_touch_vmouse_trackball = "false" +input_turbo_default_button = "0" +input_turbo_mode = "0" +input_turbo_period = "6" +input_volume_down = "nul" +input_volume_down_axis = "nul" +input_volume_down_btn = "nul" +input_volume_down_mbtn = "nul" +input_volume_up = "nul" +input_volume_up_axis = "nul" +input_volume_up_btn = "nul" +input_volume_up_mbtn = "nul" +keyboard_gamepad_enable = "true" +keyboard_gamepad_mapping_type = "1" +kiosk_mode_enable = "false" +kiosk_mode_password = "" +led_driver = "null" +libretro_log_level = "1" +load_dummy_on_core_shutdown = "true" +location_allow = "false" +location_driver = "null" +log_dir = "~/.config/retroarch/logs" +log_to_file = "true" +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_switch_icons = "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_disable_info_button = "false" +menu_disable_search_button = "false" +menu_driver = "ozone" +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 = "true" +menu_remember_selection = "1" +menu_rgui_full_width_layout = "true" +menu_rgui_shadows = "false" +menu_rgui_transparency = "true" +menu_savestate_resume = "true" +menu_scale_factor = "0.300000" +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_swap_scroll_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 = "0.350000" +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_show_title_header = "true" +menu_xmb_thumbnail_scale_factor = "100" +menu_xmb_title_margin = "5" +menu_xmb_title_margin_horizontal_offset = "0" +menu_xmb_vertical_fade_factor = "100" +microphone_block_frames = "0" +microphone_device = "" +microphone_driver = "alsathread" +microphone_enable = "true" +microphone_latency = "64" +microphone_rate = "48000" +microphone_resampler = "sinc" +microphone_resampler_quality = "3" +midi_driver = "alsa" +midi_input = "OFF" +midi_output = "OFF" +midi_volume = "100" +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_disk_control = "true" +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_save_state = "true" +notification_show_screenshot = "false" +notification_show_screenshot_duration = "2" +notification_show_screenshot_flash = "1" +notification_show_set_initial_disk = "true" +notification_show_when_menu_is_alive = "false" +osk_overlay_directory = "/tmp/overlays/keyboards" +ozone_collapse_sidebar = "false" +ozone_menu_color_theme = "1" +ozone_scroll_content_metadata = "false" +ozone_sort_after_truncate_playlist_name = "true" +ozone_thumbnail_scale_factor = "1.000000" +ozone_truncate_playlist_name = "true" +pause_nonactive = "true" +pause_on_disconnect = "false" +perfcnt_enable = "false" +playlist_compression = "false" +playlist_cores = "" +playlist_directory = "~/playlists" +playlist_entry_remove = "false" +playlist_entry_remove_enable = "1" +playlist_entry_rename = "false" +playlist_fuzzy_archive_match = "false" +playlist_names = "" +playlist_portable_paths = "false" +playlist_show_entry_idx = "true" +playlist_show_history_icons = "1" +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_filename = "false" +playlist_use_old_format = "false" +preemptive_frames_enable = "false" +preemptive_frames_hide_warnings = "false" +quick_menu_show_add_to_favorites = "true" +quick_menu_show_add_to_playlist = "false" +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_replay = "false" +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_savestate_submenu = "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" +remap_save_on_exit = "true" +replay_auto_index = "true" +replay_checkpoint_interval = "0" +replay_max_keep = "0" +replay_slot = "0" +resampler_directory = "" +rewind_buffer_size = "20971520" +rewind_buffer_size_step = "10" +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_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_file_compression = "true" +savestate_thumbnail_enable = "true" +savestates_in_content_dir = "false" +scan_serial_and_crc = "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" +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" +test_input_file_joypad = "" +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_autoswitch_pal_threshold = "54.500000" +video_autoswitch_refresh_rate = "0" +video_bfi_dark_frames = "1" +video_black_frame_insertion = "0" +video_context_driver = "" +video_crop_overscan = "true" +video_disable_composition = "false" +video_driver = "glcore" +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_frame_rest = "false" +video_fullscreen = "true" +video_fullscreen_x = "1920" +video_fullscreen_y = "1080" +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_frame_latency = "1" +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_scale = "3" +video_scan_subframes = "false" +video_shared_context = "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 = "false" +video_vsync = "true" +video_waitable_swapchains = "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 = "false" +vulkan_gpu_index = "0" +webdav_password = "" +webdav_url = "" +webdav_username = "" +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_switch_icons = "true" +xmb_theme = "0" +xmb_vertical_thumbnails = "false" +youtube_stream_key = "" +assets_directory = "/tmp/assets" +cache_directory = "/tmp/cache" +cheat_database_path = "/tmp/database/cht" +content_database_path = "/tmp/database/rdb" +joypad_autoconfig_dir = "/tmp/joypads" +libretro_directory = "/tmp/cores" +libretro_info_path = "/tmp/cores" +overlay_directory = "/tmp/overlays" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8550/retroarch32bit-append.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8550/retroarch32bit-append.cfg new file mode 100755 index 0000000000..343124c254 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8550/retroarch32bit-append.cfg @@ -0,0 +1,3 @@ +audio_filter_dir = "/usr/share/retroarch/filters/32bit/audio" +video_filter_dir = "/usr/share/retroarch/filters/32bit/video" +libretro_directory = /usr/lib32/libretro diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8550/retroarch64bit-append.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8550/retroarch64bit-append.cfg new file mode 100755 index 0000000000..b6cbf68312 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8550/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" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8650/TATE-MAME 2003-Plus.rmp b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8650/TATE-MAME 2003-Plus.rmp new file mode 100755 index 0000000000..366e47afad --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8650/TATE-MAME 2003-Plus.rmp @@ -0,0 +1,27 @@ +input_libretro_device_p1 = "1" +input_libretro_device_p2 = "1" +input_libretro_device_p3 = "1" +input_libretro_device_p4 = "1" +input_libretro_device_p5 = "1" +input_player1_analog_dpad_mode = "1" +input_player1_btn_down = "6" +input_player1_btn_left = "4" +input_player1_btn_right = "5" +input_player1_btn_up = "7" +input_player1_stk_l_x+ = "5" +input_player1_stk_l_x- = "4" +input_player1_stk_l_y+ = "6" +input_player1_stk_l_y- = "7" +input_player1_stk_r_x+ = "5" +input_player1_stk_r_x- = "4" +input_player1_stk_r_y+ = "6" +input_player1_stk_r_y- = "7" +input_player2_analog_dpad_mode = "0" +input_player3_analog_dpad_mode = "0" +input_player4_analog_dpad_mode = "0" +input_player5_analog_dpad_mode = "0" +input_remap_port_p1 = "0" +input_remap_port_p2 = "1" +input_remap_port_p3 = "2" +input_remap_port_p4 = "3" +input_remap_port_p5 = "4" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8650/retroarch-core-options.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8650/retroarch-core-options.cfg new file mode 100755 index 0000000000..f0f3122721 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8650/retroarch-core-options.cfg @@ -0,0 +1,153 @@ +mupen64plus-alt-map = "False" +mupen64plus-aspect = "4:3" +mupen64plus-astick-deadzone = "15" +mupen64plus-astick-sensitivity = "100" +mupen64plus-BackgroundMode = "Stripped" +mupen64plus-BilinearMode = "standard" +mupen64plus-CorrectTexrectCoords = "Auto" +mupen64plus-CountPerOp = "0" +mupen64plus-CountPerOpDenomPot = "0" +mupen64plus-cpucore = "dynamic_recompiler" +mupen64plus-d-cbutton = "C3" +mupen64plus-DitheringPattern = "True" +mupen64plus-DitheringQuantization = "True" +mupen64plus-EnableCopyAuxToRDRAM = "True" +mupen64plus-EnableCopyColorToRDRAM = "Async" +mupen64plus-EnableCopyDepthToRDRAM = "Software" +mupen64plus-EnableEnhancedHighResStorage = "False" +mupen64plus-EnableEnhancedTextureStorage = "False" +mupen64plus-EnableFBEmulation = "True" +mupen64plus-EnableFragmentDepthWrite = "False" +mupen64plus-EnableHiResAltCRC = "False" +mupen64plus-EnableHWLighting = "True" +mupen64plus-EnableInaccurateTextureCoordinates = "False" +mupen64plus-EnableLegacyBlending = "False" +mupen64plus-EnableLODEmulation = "True" +mupen64plus-EnableNativeResFactor = "1" +mupen64plus-EnableNativeResTexrects = "Optimized" +mupen64plus-EnableOverscan = "Enabled" +mupen64plus-EnableTexCoordBounds = "False" +mupen64plus-EnableTextureCache = "True" +mupen64plus-ForceDisableExtraMem = "False" +mupen64plus-FrameDuping = "True" +mupen64plus-Framerate = "Original" +mupen64plus-FXAA = "0" +mupen64plus-GLideN64IniBehaviour = "late" +mupen64plus-HybridFilter = "True" +mupen64plus-IgnoreTLBExceptions = "False" +mupen64plus-l-cbutton = "C2" +mupen64plus-MaxHiResTxVramLimit = "0" +mupen64plus-MaxTxCacheSize = "8000" +mupen64plus-MultiSampling = "0" +mupen64plus-OverscanBottom = "0" +mupen64plus-OverscanLeft = "0" +mupen64plus-OverscanRight = "0" +mupen64plus-OverscanTop = "0" +mupen64plus-pak1 = "memory" +mupen64plus-pak2 = "none" +mupen64plus-pak3 = "none" +mupen64plus-pak4 = "none" +mupen64plus-r-cbutton = "C1" +mupen64plus-rdp-plugin = "gliden64" +mupen64plus-RDRAMImageDitheringMode = "BlueNoise" +mupen64plus-rsp-plugin = "hle" +mupen64plus-ThreadedRenderer = "True" +mupen64plus-txCacheCompression = "True" +mupen64plus-txEnhancementMode = "None" +mupen64plus-txFilterIgnoreBG = "True" +mupen64plus-txFilterMode = "None" +mupen64plus-txHiresEnable = "False" +mupen64plus-txHiresFullAlphaChannel = "False" +mupen64plus-u-cbutton = "C4" +mupen64plus-virefresh = "Auto" +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_type = "disabled" +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" +flycast_auto_skip_frame = "normal" +opera_swi_hle = "enabled" +opera_dsp_threaded = "enabled" +opera_madam_matrix_engine = "software" +puae_deadzone = "25" +melonds_screen_layout = "Left/Right" +melonds_swapscreen_mode = "Toggle" +melonds_threaded_renderer = "enabled" +melonds_touch_mode = "Joystick" +duckstation_GPU.Renderer = "Software" +virtualjaguar_bios = "enabled" +virtualjaguar_usefastblitter = "enabled" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8650/retroarch.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8650/retroarch.cfg new file mode 100644 index 0000000000..8eb383db75 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8650/retroarch.cfg @@ -0,0 +1,894 @@ +accessibility_enable = "false" +accessibility_narrator_speech_speed = "5" +ai_service_mode = "1" +ai_service_pause = "false" +ai_service_source_lang = "0" +ai_service_target_lang = "0" +all_users_control_menu = "true" +app_icon = "default" +apply_cheats_after_load = "false" +apply_cheats_after_toggle = "false" +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_enable_menu_scroll = "false" +audio_fastforward_mute = "false" +audio_fastforward_speedup = "false" +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 = "false" +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 = "" +camera_allow = "false" +camera_device = "" +camera_driver = "null" +check_firmware_before_loading = "false" +cheevos_appearance_anchor = "0" +cheevos_appearance_padding_auto = "true" +cheevos_appearance_padding_h = "0.000000" +cheevos_appearance_padding_v = "0.000000" +cheevos_auto_screenshot = "false" +cheevos_badges_enable = "false" +cheevos_challenge_indicators = "true" +cheevos_custom_host = "" +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" +cheevos_visibility_account = "true" +cheevos_visibility_lboard_cancel = "true" +cheevos_visibility_lboard_start = "true" +cheevos_visibility_lboard_submit = "true" +cheevos_visibility_lboard_trackers = "true" +cheevos_visibility_mastery = "true" +cheevos_visibility_progress_tracker = "true" +cheevos_visibility_summary = "1" +cheevos_visibility_unlock = "true" +cloud_sync_destructive = "false" +cloud_sync_driver = "" +cloud_sync_enable = "false" +config_save_on_exit = "false" +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_contentless_cores = "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_info_savestate_bypass = "false" +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 = "interactive" +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 = "1080" +custom_viewport_width = "1920" +custom_viewport_x = "0" +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_frameskip = "true" +fastforward_ratio = "0.000000" +filter_by_current_core = "false" +flicker_filter_enable = "false" +flicker_filter_index = "0" +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" +gamemode_enable = "false" +gamma_correction = "0" +global_core_options = "false" +history_list_enable = "true" +initial_disk_change_enable = "true" +input_ai_service = "nul" +input_ai_service_axis = "nul" +input_ai_service_btn = "nul" +input_ai_service_mbtn = "nul" +input_allow_turbo_dpad = "false" +input_analog_deadzone = "0.100000" +input_analog_sensitivity = "1.500000" +input_audio_mute = "nul" +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 = "nul" +input_cheat_index_minus_axis = "nul" +input_cheat_index_minus_btn = "nul" +input_cheat_index_minus_mbtn = "nul" +input_cheat_index_plus = "nul" +input_cheat_index_plus_axis = "nul" +input_cheat_index_plus_btn = "nul" +input_cheat_index_plus_mbtn = "nul" +input_cheat_toggle = "nul" +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 = "nul" +input_exit_emulator_axis = "nul" +input_exit_emulator_btn = "nul" +input_exit_emulator_mbtn = "nul" +input_fps_toggle = "nul" +input_fps_toggle_axis = "nul" +input_fps_toggle_btn = "nul" +input_fps_toggle_mbtn = "nul" +input_frame_advance = "nul" +input_frame_advance_axis = "nul" +input_frame_advance_btn = "nul" +input_frame_advance_mbtn = "nul" +input_game_focus_toggle = "nul" +input_game_focus_toggle_axis = "nul" +input_game_focus_toggle_btn = "nul" +input_game_focus_toggle_mbtn = "nul" +input_grab_mouse_toggle = "nul" +input_grab_mouse_toggle_axis = "nul" +input_grab_mouse_toggle_btn = "nul" +input_grab_mouse_toggle_mbtn = "nul" +input_halt_replay = "nul" +input_halt_replay_axis = "nul" +input_halt_replay_btn = "nul" +input_halt_replay_mbtn = "nul" +input_hold_fast_forward = "nul" +input_hold_fast_forward_axis = "nul" +input_hold_fast_forward_btn = "nul" +input_hold_fast_forward_mbtn = "nul" +input_hold_slowmotion = "nul" +input_hold_slowmotion_axis = "nul" +input_hold_slowmotion_btn = "nul" +input_hold_slowmotion_mbtn = "nul" +input_hotkey_block_delay = "5" +input_hotkey_device_merge = "false" +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 = "nul" +input_load_state_axis = "nul" +input_load_state_btn = "nul" +input_load_state_mbtn = "nul" +input_max_users = "5" +input_menu_toggle = "nul" +input_menu_toggle_axis = "nul" +input_menu_toggle_btn = "nul" +input_menu_toggle_gamepad_combo = "nul" +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_fade_chat_toggle = "nul" +input_netplay_fade_chat_toggle_axis = "nul" +input_netplay_fade_chat_toggle_btn = "nul" +input_netplay_fade_chat_toggle_mbtn = "nul" +input_netplay_game_watch = "nul" +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_netplay_ping_toggle = "nul" +input_netplay_ping_toggle_axis = "nul" +input_netplay_ping_toggle_btn = "nul" +input_netplay_ping_toggle_mbtn = "nul" +input_netplay_player_chat = "nul" +input_netplay_player_chat_axis = "nul" +input_netplay_player_chat_btn = "nul" +input_netplay_player_chat_mbtn = "nul" +input_nowinkey_enable = "false" +input_osk_overlay = "" +input_osk_overlay_auto_scale = "false" +input_osk_overlay_opacity = "0.700000" +input_osk_toggle = "nul" +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_autopreferred = "true" +input_overlay_enable = "false" +input_overlay_hide_in_menu = "true" +input_overlay_hide_when_gamepad_connected = "false" +input_overlay_next_axis = "nul" +input_overlay_next_btn = "nul" +input_overlay_next_mbtn = "nul" +input_overlay_next = "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 = "nul" +input_pause_toggle_axis = "nul" +input_pause_toggle_btn = "nul" +input_pause_toggle_mbtn = "nul" +input_play_replay = "nul" +input_play_replay_axis = "nul" +input_play_replay_btn = "nul" +input_play_replay_mbtn = "nul" +input_poll_type_behavior = "2" +input_preempt_toggle = "nul" +input_preempt_toggle_axis = "nul" +input_preempt_toggle_btn = "nul" +input_preempt_toggle_mbtn = "nul" +input_quit_gamepad_combo = "0" +input_record_replay = "nul" +input_record_replay_axis = "nul" +input_record_replay_btn = "nul" +input_record_replay_mbtn = "nul" +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_replay_slot_decrease = "nul" +input_replay_slot_decrease_axis = "nul" +input_replay_slot_decrease_btn = "nul" +input_replay_slot_decrease_mbtn = "nul" +input_replay_slot_increase = "nul" +input_replay_slot_increase_axis = "nul" +input_replay_slot_increase_btn = "nul" +input_replay_slot_increase_mbtn = "nul" +input_reset = "nul" +input_reset_axis = "nul" +input_reset_btn = "nul" +input_reset_mbtn = "nul" +input_rewind = "nul" +input_rewind_axis = "nul" +input_rewind_btn = "nul" +input_rewind_mbtn = "nul" +input_rumble_gain = "25" +input_runahead_toggle = "nul" +input_runahead_toggle_axis = "nul" +input_runahead_toggle_btn = "nul" +input_runahead_toggle_mbtn = "nul" +input_save_state = "nul" +input_save_state_axis = "nul" +input_save_state_btn = "nul" +input_save_state_mbtn = "nul" +input_screenshot = "nul" +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 = "nul" +input_shader_next_axis = "nul" +input_shader_next_btn = "nul" +input_shader_next_mbtn = "nul" +input_shader_prev = "nul" +input_shader_prev_axis = "nul" +input_shader_prev_btn = "nul" +input_shader_prev_mbtn = "nul" +input_shader_toggle = "nul" +input_shader_toggle_axis = "nul" +input_shader_toggle_btn = "nul" +input_shader_toggle_mbtn = "nul" +input_state_slot_decrease = "nul" +input_state_slot_decrease_axis = "nul" +input_state_slot_decrease_btn = "nul" +input_state_slot_decrease_mbtn = "nul" +input_state_slot_increase = "nul" +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 = "nul" +input_toggle_fast_forward_axis = "nul" +input_toggle_fast_forward_btn = "nul" +input_toggle_fast_forward_mbtn = "nul" +input_toggle_fullscreen = "nul" +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_toggle_statistics = "nul" +input_toggle_statistics_axis = "nul" +input_toggle_statistics_btn = "nul" +input_toggle_statistics_mbtn = "nul" +input_toggle_vrr_runloop = "nul" +input_toggle_vrr_runloop_axis = "nul" +input_toggle_vrr_runloop_btn = "nul" +input_toggle_vrr_runloop_mbtn = "nul" +input_touch_scale = "1" +input_touch_vmouse_gesture = "true" +input_touch_vmouse_mouse = "true" +input_touch_vmouse_pointer = "true" +input_touch_vmouse_touchpad = "true" +input_touch_vmouse_trackball = "false" +input_turbo_default_button = "0" +input_turbo_mode = "0" +input_turbo_period = "6" +input_volume_down = "nul" +input_volume_down_axis = "nul" +input_volume_down_btn = "nul" +input_volume_down_mbtn = "nul" +input_volume_up = "nul" +input_volume_up_axis = "nul" +input_volume_up_btn = "nul" +input_volume_up_mbtn = "nul" +keyboard_gamepad_enable = "true" +keyboard_gamepad_mapping_type = "1" +kiosk_mode_enable = "false" +kiosk_mode_password = "" +led_driver = "null" +libretro_log_level = "1" +load_dummy_on_core_shutdown = "true" +location_allow = "false" +location_driver = "null" +log_dir = "~/.config/retroarch/logs" +log_to_file = "true" +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_switch_icons = "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_disable_info_button = "false" +menu_disable_search_button = "false" +menu_driver = "ozone" +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 = "true" +menu_remember_selection = "1" +menu_rgui_full_width_layout = "true" +menu_rgui_shadows = "false" +menu_rgui_transparency = "true" +menu_savestate_resume = "true" +menu_scale_factor = "0.300000" +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_swap_scroll_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 = "0.350000" +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_show_title_header = "true" +menu_xmb_thumbnail_scale_factor = "100" +menu_xmb_title_margin = "5" +menu_xmb_title_margin_horizontal_offset = "0" +menu_xmb_vertical_fade_factor = "100" +microphone_block_frames = "0" +microphone_device = "" +microphone_driver = "alsathread" +microphone_enable = "true" +microphone_latency = "64" +microphone_rate = "48000" +microphone_resampler = "sinc" +microphone_resampler_quality = "3" +midi_driver = "alsa" +midi_input = "OFF" +midi_output = "OFF" +midi_volume = "100" +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_disk_control = "true" +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_save_state = "true" +notification_show_screenshot = "false" +notification_show_screenshot_duration = "2" +notification_show_screenshot_flash = "1" +notification_show_set_initial_disk = "true" +notification_show_when_menu_is_alive = "false" +osk_overlay_directory = "/tmp/overlays/keyboards" +ozone_collapse_sidebar = "false" +ozone_menu_color_theme = "1" +ozone_scroll_content_metadata = "false" +ozone_sort_after_truncate_playlist_name = "true" +ozone_thumbnail_scale_factor = "1.000000" +ozone_truncate_playlist_name = "true" +pause_nonactive = "true" +pause_on_disconnect = "false" +perfcnt_enable = "false" +playlist_compression = "false" +playlist_cores = "" +playlist_directory = "~/playlists" +playlist_entry_remove = "false" +playlist_entry_remove_enable = "1" +playlist_entry_rename = "false" +playlist_fuzzy_archive_match = "false" +playlist_names = "" +playlist_portable_paths = "false" +playlist_show_entry_idx = "true" +playlist_show_history_icons = "1" +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_filename = "false" +playlist_use_old_format = "false" +preemptive_frames_enable = "false" +preemptive_frames_hide_warnings = "false" +quick_menu_show_add_to_favorites = "true" +quick_menu_show_add_to_playlist = "false" +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_replay = "false" +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_savestate_submenu = "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" +remap_save_on_exit = "true" +replay_auto_index = "true" +replay_checkpoint_interval = "0" +replay_max_keep = "0" +replay_slot = "0" +resampler_directory = "" +rewind_buffer_size = "20971520" +rewind_buffer_size_step = "10" +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_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_file_compression = "true" +savestate_thumbnail_enable = "true" +savestates_in_content_dir = "false" +scan_serial_and_crc = "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" +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" +test_input_file_joypad = "" +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_autoswitch_pal_threshold = "54.500000" +video_autoswitch_refresh_rate = "0" +video_bfi_dark_frames = "1" +video_black_frame_insertion = "0" +video_context_driver = "" +video_crop_overscan = "true" +video_disable_composition = "false" +video_driver = "glcore" +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_frame_rest = "false" +video_fullscreen = "true" +video_fullscreen_x = "1920" +video_fullscreen_y = "1080" +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_frame_latency = "1" +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_scale = "3" +video_scan_subframes = "false" +video_shared_context = "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 = "false" +video_vsync = "true" +video_waitable_swapchains = "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 = "false" +vulkan_gpu_index = "0" +webdav_password = "" +webdav_url = "" +webdav_username = "" +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_switch_icons = "true" +xmb_theme = "0" +xmb_vertical_thumbnails = "false" +youtube_stream_key = "" +assets_directory = "/tmp/assets" +cache_directory = "/tmp/cache" +cheat_database_path = "/tmp/database/cht" +content_database_path = "/tmp/database/rdb" +joypad_autoconfig_dir = "/tmp/joypads" +libretro_directory = "/tmp/cores" +libretro_info_path = "/tmp/cores" +overlay_directory = "/tmp/overlays" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8650/retroarch32bit-append.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8650/retroarch32bit-append.cfg new file mode 100755 index 0000000000..343124c254 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8650/retroarch32bit-append.cfg @@ -0,0 +1,3 @@ +audio_filter_dir = "/usr/share/retroarch/filters/32bit/audio" +video_filter_dir = "/usr/share/retroarch/filters/32bit/video" +libretro_directory = /usr/lib32/libretro diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8650/retroarch64bit-append.cfg b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8650/retroarch64bit-append.cfg new file mode 100755 index 0000000000..b6cbf68312 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/sources/SM8650/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" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/system.d/tmp-assets.mount b/projects/ArchR/packages/emulators/libretro/retroarch/system.d/tmp-assets.mount new file mode 100644 index 0000000000..25628de694 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/system.d/tmp-assets.mount @@ -0,0 +1,14 @@ +[Unit] +Description=Assets directory +After=systemd-tmpfiles-setup.service +RequiresMountsFor=/storage +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=archr.target diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/system.d/tmp-cores.mount b/projects/ArchR/packages/emulators/libretro/retroarch/system.d/tmp-cores.mount new file mode 100644 index 0000000000..f819867a3a --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/system.d/tmp-cores.mount @@ -0,0 +1,14 @@ +[Unit] +Description=Cores directory +After=systemd-tmpfiles-setup.service +RequiresMountsFor=/storage +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=archr.target diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/system.d/tmp-database.mount b/projects/ArchR/packages/emulators/libretro/retroarch/system.d/tmp-database.mount new file mode 100644 index 0000000000..3ca7aa6242 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/system.d/tmp-database.mount @@ -0,0 +1,14 @@ +[Unit] +Description=Database directory +After=systemd-tmpfiles-setup.service +RequiresMountsFor=/storage +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=archr.target diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/system.d/tmp-overlays.mount b/projects/ArchR/packages/emulators/libretro/retroarch/system.d/tmp-overlays.mount new file mode 100644 index 0000000000..11ed4f6e3b --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/system.d/tmp-overlays.mount @@ -0,0 +1,14 @@ +[Unit] +Description=Overlays directory +After=systemd-tmpfiles-setup.service +RequiresMountsFor=/storage +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=archr.target diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/system.d/tmp-shaders.mount b/projects/ArchR/packages/emulators/libretro/retroarch/system.d/tmp-shaders.mount new file mode 100644 index 0000000000..9a32142a60 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/system.d/tmp-shaders.mount @@ -0,0 +1,14 @@ +[Unit] +Description=Shaders directory RetroArch +After=systemd-tmpfiles-setup.service +RequiresMountsFor=/storage +DefaultDependencies=no + +[Mount] +What=none +Where=/tmp/shaders +Type=overlay +Options=lowerdir=/usr/share/common-shaders:/usr/share/glsl-shaders:/usr/share/slang-shaders,upperdir=/storage/shaders,workdir=/storage/.tmp/shaders-workdir + +[Install] +WantedBy=archr.target diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/tmpfiles.d/retroarch-userdirs.conf b/projects/ArchR/packages/emulators/libretro/retroarch/tmpfiles.d/retroarch-userdirs.conf new file mode 100644 index 0000000000..1a40a9ea2f --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/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/projects/ArchR/packages/emulators/libretro/retroarch/udev.d/99-8bitdo-bluetooth-controllers.rules b/projects/ArchR/packages/emulators/libretro/retroarch/udev.d/99-8bitdo-bluetooth-controllers.rules new file mode 100644 index 0000000000..b6abb22f60 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retroarch/udev.d/99-8bitdo-bluetooth-controllers.rules @@ -0,0 +1,49 @@ +# 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" + +# 8Bitdo 2.4ghz ultimate +ACTION=="add", ATTRS{idVendor}=="2dc8", ATTRS{idProduct}=="3106", RUN+="/usr/sbin/modprobe xpad", RUN+="/bin/sh -c 'echo 2dc8 3106 > /sys/bus/usb/drivers/xpad/new_id'" + +# 8Bitdo M30 +ACTION=="add", ATTRS{idVendor}=="2dc8", ATTRS{idProduct}=="6002", RUN+="/usr/sbin/modprobe xpad", RUN+="/bin/sh -c 'echo 2dc8 6002 > /sys/bus/usb/drivers/xpad/new_id'" diff --git a/projects/ArchR/packages/emulators/libretro/retroarch/udev.d/99-ION-iCade-bluetooth.rules b/projects/ArchR/packages/emulators/libretro/retroarch/udev.d/99-ION-iCade-bluetooth.rules new file mode 100644 index 0000000000..a25b646dc1 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/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/projects/ArchR/packages/emulators/libretro/retroarch/udev.d/99-gen-game-s3-controller.rules b/projects/ArchR/packages/emulators/libretro/retroarch/udev.d/99-gen-game-s3-controller.rules new file mode 100644 index 0000000000..66b6a0ac6c --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/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/projects/ArchR/packages/emulators/libretro/retroarch/udev.d/99-nintendo-wii-remote.rules b/projects/ArchR/packages/emulators/libretro/retroarch/udev.d/99-nintendo-wii-remote.rules new file mode 100644 index 0000000000..f07b272009 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/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/projects/ArchR/packages/emulators/libretro/retroarch/udev.d/99-ninteno-wii-remote.rules b/projects/ArchR/packages/emulators/libretro/retroarch/udev.d/99-ninteno-wii-remote.rules new file mode 100644 index 0000000000..f07b272009 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/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/projects/ArchR/packages/emulators/libretro/retroarch/udev.d/99-nv-shield-controller.rules b/projects/ArchR/packages/emulators/libretro/retroarch/udev.d/99-nv-shield-controller.rules new file mode 100644 index 0000000000..f5b679f7b0 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/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/projects/ArchR/packages/emulators/libretro/retroarch/udev.d/99-ouya-controller.rules b/projects/ArchR/packages/emulators/libretro/retroarch/udev.d/99-ouya-controller.rules new file mode 100644 index 0000000000..55a0949d9f --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/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/projects/ArchR/packages/emulators/libretro/retroarch/udev.d/99-terios-t3.rules b/projects/ArchR/packages/emulators/libretro/retroarch/udev.d/99-terios-t3.rules new file mode 100644 index 0000000000..32d1692892 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/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/projects/ArchR/packages/emulators/libretro/retropie-shaders/package.mk b/projects/ArchR/packages/emulators/libretro/retropie-shaders/package.mk new file mode 100644 index 0000000000..eeba4b444f --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/retropie-shaders/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) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) +# +# 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="retropie-shaders" +PKG_VERSION="43eaf9b91857eb8515310c74ae750895d77b20f8" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/RetroPie/common-shaders" +PKG_URL="${PKG_SITE}.git" +PKG_GIT_CLONE_BRANCH="rpi" +PKG_DEPENDS_TARGET="toolchain glsl-shaders" +PKG_LONGDESC="Libretro common shaders from retropie" +PKG_TOOLCHAIN="manual" + +make_target() { + : +} + +makeinstall_target() { + if [ ! -d "${INSTALL}/usr/share/common-shaders" ] + then + mkdir -p ${INSTALL}/usr/share/common-shaders + fi + rsync -a ${PKG_BUILD}/* ${INSTALL}/usr/share/common-shaders/ + rm -f ${INSTALL}/usr/share/common-shaders/{Makefile,configure} +} diff --git a/projects/ArchR/packages/emulators/libretro/same_cdi-lr/package.mk b/projects/ArchR/packages/emulators/libretro/same_cdi-lr/package.mk new file mode 100644 index 0000000000..b54aa2e16a --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/same_cdi-lr/package.mk @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present AmberELEC (https://github.com/AmberELEC) + +PKG_NAME="same_cdi-lr" +PKG_VERSION="7ee1d8e9cb4307b7cd44ee1dd757e9b3f48f41d5" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/libretro/same_cdi" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain expat zlib flac sqlite" +PKG_LONGDESC="SAME_CDI is a Single Arcade/Machine Emulator for libretro" +PKG_TOOLCHAIN="make" + +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 \ + 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 -f Makefile.libretro ${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 same_cdi_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/same_cdi-lr/patches/001-gcc13-fix.patch b/projects/ArchR/packages/emulators/libretro/same_cdi-lr/patches/001-gcc13-fix.patch new file mode 100644 index 0000000000..d2a6c8c43f --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/same_cdi-lr/patches/001-gcc13-fix.patch @@ -0,0 +1,12 @@ +diff --git a/src/osd/modules/lib/osdlib.h b/src/osd/modules/lib/osdlib.h +index 4a06b705..506ba834 100644 +--- a/src/osd/modules/lib/osdlib.h ++++ b/src/osd/modules/lib/osdlib.h +@@ -18,6 +18,7 @@ + + #include + #include ++#include + #include + #include + #include diff --git a/projects/ArchR/packages/emulators/libretro/same_cdi-lr/patches/002-fix-building-with-gcc15.patch b/projects/ArchR/packages/emulators/libretro/same_cdi-lr/patches/002-fix-building-with-gcc15.patch new file mode 100644 index 0000000000..3894a8a80e --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/same_cdi-lr/patches/002-fix-building-with-gcc15.patch @@ -0,0 +1,22 @@ +--- a/src/lib/util/corestr.h ++++ b/src/lib/util/corestr.h +@@ -17,6 +17,7 @@ + #include + + #include ++#include + + + /*************************************************************************** +--- a/3rdparty/sol2/sol/sol.hpp ++++ b/3rdparty/sol2/sol/sol.hpp +@@ -6056,7 +6056,8 @@ + static_assert(std::is_constructible::value, "T must be constructible with Args"); + + *this = nullopt; +- this->construct(std::forward(args)...); ++ m_value = std::addressof(std::forward(args)...); ++ return *m_value; + } + + /// Swaps this optional with the other. diff --git a/projects/ArchR/packages/emulators/libretro/same_cdi-lr/patches/mame-crosscompile.patch b/projects/ArchR/packages/emulators/libretro/same_cdi-lr/patches/mame-crosscompile.patch new file mode 100644 index 0000000000..49f1ff3763 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/same_cdi-lr/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/projects/ArchR/packages/emulators/libretro/sameboy-lr/package.mk b/projects/ArchR/packages/emulators/libretro/sameboy-lr/package.mk new file mode 100644 index 0000000000..c3244647e0 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/sameboy-lr/package.mk @@ -0,0 +1,39 @@ +################################################################################ +# 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-lr" +PKG_VERSION="2d29ece3b8e7ec44347c9daad0fabb84912ed44f" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/libretro/SameBoy" +PKG_URL="${PKG_SITE}/-/archive/${PKG_VERSION}/SameBoy-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain util-linux:host" +PKG_LONGDESC="Gameboy and Gameboy Color emulator written in C" + +PKG_TOOLCHAIN="make" + +make_target() { + make -C libretro BOOTROMS_DIR=${PKG_BUILD}/BootROMs/prebuilt +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp ${PKG_BUILD}/sameboy_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/sameduck-lr/package.mk b/projects/ArchR/packages/emulators/libretro/sameduck-lr/package.mk new file mode 100644 index 0000000000..6e07913912 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/sameduck-lr/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) +# 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-lr" +PKG_VERSION="5619abdb01cee6bedb47599cdb5532c318443b52" +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_LONGDESC="Mega Duck/Cougar Boy emulator written in C" + +PKG_TOOLCHAIN="make" + +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/projects/ArchR/packages/emulators/libretro/scummvm-lr/package.mk b/projects/ArchR/packages/emulators/libretro/scummvm-lr/package.mk new file mode 100644 index 0000000000..10aad938e2 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/scummvm-lr/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) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) +# +# 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-lr" +PKG_VERSION="9d31b31c179fd4a43f7cfc383a3435a9070c6aa8" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/scummvm" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="ScummVM with libretro backend." + +PKG_TOOLCHAIN="make" +PKG_BUILD_FLAGS="-lto" + +pre_make_target() { + CXXFLAGS+=" -DHAVE_POSIX_MEMALIGN=1" + cd ${PKG_BUILD}/backends/platform/libretro +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp scummvm_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/scummvm-lr/patches/001-fix-building-with-gcc15.patch b/projects/ArchR/packages/emulators/libretro/scummvm-lr/patches/001-fix-building-with-gcc15.patch new file mode 100644 index 0000000000..8447e5ef4d --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/scummvm-lr/patches/001-fix-building-with-gcc15.patch @@ -0,0 +1,14 @@ +--- a/backends/platform/libretro/scripts/configure_submodules.sh ++++ b/backends/platform/libretro/scripts/configure_submodules.sh +@@ -72,5 +72,11 @@ + cd $SUBMODULE_FOLDER + [ $reset -eq 1 ] && git reset --hard > /dev/null 2>&1 + ++# dirty hack to fix gcc15 build issue ++[ -f libfaad/libfaad/common.h ] && sed -i -e '/# define strchr index/d' \ ++ -e '/\# define strrchr rindex/d' \ ++ -e '/char \*strchr(), \*strrchr();/d' \ ++ libfaad/libfaad/common.h ++ + # Success + echo 0 diff --git a/projects/ArchR/packages/emulators/libretro/skyemu-lr/package.mk b/projects/ArchR/packages/emulators/libretro/skyemu-lr/package.mk new file mode 100644 index 0000000000..4eba8359fa --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/skyemu-lr/package.mk @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2026-present ROCKNIX (https://github.com/ROCKNIX) + +PKG_NAME="skyemu-lr" +PKG_VERSION="46efbcbdb3b902373a09f4724e6d3b1a5acc4af3" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/skylersaleh/SkyEmu" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_LONGDESC="SkyEmu is a low level GameBoy, GameBoy Color, Game Boy Advance, and DS emulator." +PKG_DEPENDS_TARGET="toolchain SDL2 openssl curl" +PKG_TOOLCHAIN="cmake" +PKG_PATCH_DIRS+="${DEVICE}" + +pre_configure_target() { + PKG_CMAKE_OPTS_TARGET+=" -DCMAKE_BUILD_TYPE=Release \ + -DENABLE_RETRO_ACHIEVEMENTS=ON \ + -DRETRO_CORE_ONLY=ON" +} + +make_target() { + cmake --build ${PKG_BUILD}/.${TARGET_NAME} --target skyemu_libretro --config Release} +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp -r ${PKG_BUILD}/.${TARGET_NAME}/skyemu_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/slang-shaders/package.mk b/projects/ArchR/packages/emulators/libretro/slang-shaders/package.mk new file mode 100644 index 0000000000..801da2ca21 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/slang-shaders/package.mk @@ -0,0 +1,39 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) +# +# 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="slang-shaders" +PKG_VERSION="a2ac00bcd5a44982ecaa6ba6e5b8cc9a9608b1d6" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/libretro/slang-shaders" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Common SLANG shaders for RetroArch" + +PKG_TOOLCHAIN="make" + +configure_target() { + cd ${PKG_BUILD} +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/share/slang-shaders + make install INSTALLDIR="${INSTALL}/usr/share/slang-shaders" +} diff --git a/projects/ArchR/packages/emulators/libretro/smsplus-gx-lr/package.mk b/projects/ArchR/packages/emulators/libretro/smsplus-gx-lr/package.mk new file mode 100644 index 0000000000..7f4af3451c --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/smsplus-gx-lr/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="smsplus-gx-lr" +PKG_VERSION="c642bbd0680b5959180a420036108893d0aec961" +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_LONGDESC="SMS Plus GX is an enhanced version" + +PKG_TOOLCHAIN="make" + +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/projects/ArchR/packages/emulators/libretro/snes9x-lr/package.mk b/projects/ArchR/packages/emulators/libretro/snes9x-lr/package.mk new file mode 100644 index 0000000000..2468246b8f --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/snes9x-lr/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) 2023 JELOS (https://github.com/JustEnoughLinuxOS) +# +# 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-lr" +PKG_VERSION="5a40cd5514e63e691e39141d64267798357a1424" +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_LONGDESC="Snes9x - Portable Super Nintendo Entertainment System (TM) emulator" + +PKG_TOOLCHAIN="make" + +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/projects/ArchR/packages/emulators/libretro/snes9x2002-lr/package.mk b/projects/ArchR/packages/emulators/libretro/snes9x2002-lr/package.mk new file mode 100644 index 0000000000..199b72fa73 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/snes9x2002-lr/package.mk @@ -0,0 +1,34 @@ +################################################################################ +# 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-lr" +PKG_VERSION="a0709ec7dcd6de2fbebb43106bd757b649e3b7cf" +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_LONGDESC="Snes9x 2002." + +PKG_TOOLCHAIN="make" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp snes9x2002_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/snes9x2005_plus-lr/package.mk b/projects/ArchR/packages/emulators/libretro/snes9x2005_plus-lr/package.mk new file mode 100644 index 0000000000..44febaaf54 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/snes9x2005_plus-lr/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="snes9x2005_plus-lr" +PKG_VERSION="74d871db9b4dba6dbe6c5ecebc88cbf255be5349" +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_LONGDESC="Snes9x 2005 Plus." +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/projects/ArchR/packages/emulators/libretro/snes9x2005_plus-lr/patches/01-snes9x2005_plux-01-fix-fpic.patch b/projects/ArchR/packages/emulators/libretro/snes9x2005_plus-lr/patches/01-snes9x2005_plux-01-fix-fpic.patch new file mode 100644 index 0000000000..3868c0280e --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/snes9x2005_plus-lr/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/projects/ArchR/packages/emulators/libretro/snes9x2010-lr/package.mk b/projects/ArchR/packages/emulators/libretro/snes9x2010-lr/package.mk new file mode 100644 index 0000000000..8ba4761916 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/snes9x2010-lr/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="snes9x2010-lr" +PKG_VERSION="f9ae8fd28b13070a945a829ccf41cbf90a21d0f7" +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_LONGDESC="Snes9x 2010." + +PKG_TOOLCHAIN="make" + +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/projects/ArchR/packages/emulators/libretro/snes9x2010-lr/patches/snes9x2010-add-oga.patch b/projects/ArchR/packages/emulators/libretro/snes9x2010-lr/patches/snes9x2010-add-oga.patch new file mode 100644 index 0000000000..dff83e8770 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/snes9x2010-lr/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 ++ 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/projects/ArchR/packages/emulators/libretro/stella-lr/package.mk b/projects/ArchR/packages/emulators/libretro/stella-lr/package.mk new file mode 100644 index 0000000000..1cc05badd6 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/stella-lr/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) 2023 JELOS (https://github.com/JustEnoughLinuxOS) +# +# 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-lr" +PKG_VERSION="5d737b2e54717753be235c4fd2cd172e307da623" +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_LONGDESC="Port of Stella to libretro." +PKG_TOOLCHAIN="make" + +pre_configure_target() { + case ${TARGET_ARCH} in + aarch64) + PKG_MAKE_OPTS_TARGET=" -C ${PKG_BUILD}/src/os/libretro -f Makefile platform=aarch64" + ;; + *) + PKG_MAKE_OPTS_TARGET=" -C ${PKG_BUILD}/src/os/libretro -f Makefile" + ;; + esac +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp ${PKG_BUILD}/src/os/libretro/stella_libretro.so ${INSTALL}/usr/lib/libretro/ +} + diff --git a/projects/ArchR/packages/emulators/libretro/stella-lr/patches/001-aarch64.patch b/projects/ArchR/packages/emulators/libretro/stella-lr/patches/001-aarch64.patch new file mode 100644 index 0000000000..f4cabd3119 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/stella-lr/patches/001-aarch64.patch @@ -0,0 +1,20 @@ +diff -rupN stella.orig/src/os/libretro/Makefile stella/src/os/libretro/Makefile +--- stella.orig/src/os/libretro/Makefile 2022-10-02 14:39:47.954719313 -0400 ++++ stella/src/os/libretro/Makefile 2022-10-03 19:19:12.544824555 -0400 +@@ -114,6 +114,16 @@ else ifeq ($(platform), osx) + CXXFLAGS += $(ARCHFLAGS) + LDFLAGS += $(ARCHFLAGS) + ++else ifeq ($(platform), aarch64) ++ 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) -stdlib=libc++ diff --git a/projects/ArchR/packages/emulators/libretro/swanstation-lr/package.mk b/projects/ArchR/packages/emulators/libretro/swanstation-lr/package.mk new file mode 100644 index 0000000000..a77a11a223 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/swanstation-lr/package.mk @@ -0,0 +1,30 @@ +# 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-lr" +PKG_VERSION="4d309c05fd7bdc503d91d267bd542edb8d192b09" +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" +PKG_LONGDESC="SwanStation - PlayStation 1, aka. PSX Emulator" +PKG_TOOLCHAIN="cmake" +PKG_BUILD_FLAGS="-lto" + +if [ ! "${OPENGL}" = "no" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL} glu libglvnd" +fi + +if [ "${OPENGLES_SUPPORT}" = yes ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" +fi + +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/projects/ArchR/packages/emulators/libretro/tgbdual-lr/package.mk b/projects/ArchR/packages/emulators/libretro/tgbdual-lr/package.mk new file mode 100644 index 0000000000..a9b11fc692 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/tgbdual-lr/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) +# 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-lr" +PKG_VERSION="933707c0ba8f12360f6d79712f735a917713709a" +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_LONGDESC="libretro port of TGB Dual" + +PKG_TOOLCHAIN="make" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp tgbdual_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/theodore-lr/package.mk b/projects/ArchR/packages/emulators/libretro/theodore-lr/package.mk new file mode 100644 index 0000000000..1a84175ae1 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/theodore-lr/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="theodore-lr" +PKG_VERSION="242e932d838284a61b81aa7641c60d813934025e" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/Zlika/theodore" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A port of the Theodore emulator for the Thomson MO/TO system--a family of French 8-bit home computers--to libretro. This core emulates all of the main models of the MO/TO family, including the TO7, TO7/70, TO8, TO8D, TO9, TO9+, MO5 and MO6 models, as well as the Olivetti Prodest PC128, which is a rebranded MO6 that was released in the Italian market. The core includes an onscreen keyboard, which can be toggled with retropad-select and navigated using the d-pad and retropad-B to press the selected key." +PKG_TOOLCHAIN="make" + +PKG_MAKE_OPTS_TARGET="-C . platform=unix" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp ${PKG_BUILD}/theodore_libretro.so ${INSTALL}/usr/lib/libretro +} diff --git a/projects/ArchR/packages/emulators/libretro/tic80-lr/package.mk b/projects/ArchR/packages/emulators/libretro/tic80-lr/package.mk new file mode 100644 index 0000000000..c053eff4e2 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/tic80-lr/package.mk @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="tic80-lr" +PKG_VERSION="7020500a6e88f6ee91301933bb77f082a10e10f5" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/nesbox/TIC-80" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="TIC-80 is a fantasy computer for making, playing and sharing tiny games." +GET_HANDLER_SUPPORT="git" + +PKG_CMAKE_OPTS_TARGET="-DBUILD_DEMO_CARTS=OFF \ + -DBUILD_EDITORS=OFF \ + -DBUILD_LIBRETRO=ON \ + -DBUILD_PLAYER=OFF \ + -DBUILD_PRO=OFF \ + -DBUILD_SDL=OFF \ + -DBUILD_SDLGPU=OFF \ + -DBUILD_SOKOL=OFF \ + -DBUILD_STATIC=ON \ + -DBUILD_TOOLS=OFF \ + -DBUILD_TOUCH_INPUT=ON \ + -DBUILD_WITH_ALL=OFF \ + -DBUILD_WITH_FENNEL=ON \ + -DBUILD_WITH_JANET=OFF \ + -DBUILD_WITH_LUA=ON \ + -DBUILD_WITH_MRUBY=OFF \ + -DBUILD_WITH_POCKETPY=OFF \ + -DBUILD_WITH_QUICKJS=OFF \ + -DBUILD_WITH_SCHEME=OFF \ + -DBUILD_WITH_SQUIRREL=OFF \ + -DBUILD_WITH_WASM=OFF \ + -DBUILD_WITH_WREN=ON \ + -DBUILD_WITH_ZLIB=ON \ + -DCMAKE_BUILD_TYPE=Release" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp ${PKG_BUILD}/.${TARGET_NAME}/bin/tic80_libretro.so ${INSTALL}/usr/lib/libretro/tic80_libretro.so +} diff --git a/projects/ArchR/packages/emulators/libretro/tyrquake-lr/package.mk b/projects/ArchR/packages/emulators/libretro/tyrquake-lr/package.mk new file mode 100644 index 0000000000..bae39ad327 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/tyrquake-lr/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="tyrquake-lr" +PKG_VERSION="77217664a09afe893a06be8e3e8f9611184636f8" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/tyrquake" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Libretro port of Tyrquake (Quake 1 engine)" +PKG_PATCH_DIRS+="${DEVICE}" + +PKG_TOOLCHAIN="make" + +pre_configure_target() { + if [ "${ARCH}" == "arm" ]; then + CFLAGS="${CFLAGS} -DARM -marm" + fi + CFLAGS="${CFLAGS} -std=gnu17" +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp tyrquake_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/uae4arm/package.mk b/projects/ArchR/packages/emulators/libretro/uae4arm/package.mk new file mode 100644 index 0000000000..1cd42273f4 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/uae4arm/package.mk @@ -0,0 +1,39 @@ +################################################################################ +# 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="177c2f0e892adf2603ada9b150e31beffe0f76c3" +PKG_ARCH="arm aarch64" +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_LONGDESC="Port of uae4arm for libretro (rpi/android)" + +PKG_TOOLCHAIN="make" + +make_target() { + make -f Makefile.libretro platform=unix_aarch64 "CPU_FLAGS=-mcpu=${TARGET_CPU}" +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp uae4arm_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/uzem-lr/package.mk b/projects/ArchR/packages/emulators/libretro/uzem-lr/package.mk new file mode 100644 index 0000000000..8726607911 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/uzem-lr/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="uzem-lr" +PKG_VERSION="cd6004ea143435cfdb6b12e7c6779dab499f7829" +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_LONGDESC="A retro-minimalist game console engine for the ATMega644" + +PKG_TOOLCHAIN="make" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp uzem_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/vba-next-lr/package.mk b/projects/ArchR/packages/emulators/libretro/vba-next-lr/package.mk new file mode 100644 index 0000000000..cda0c6330c --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/vba-next-lr/package.mk @@ -0,0 +1,39 @@ +################################################################################ +# 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-lr" +PKG_VERSION="d0ec7f3e209a91b903bb9d2c2397fef2bb3cca32" +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_LONGDESC="Optimized port of VBA-M to Libretro." + +PKG_TOOLCHAIN="make" + +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/projects/ArchR/packages/emulators/libretro/vbam-lr/package.mk b/projects/ArchR/packages/emulators/libretro/vbam-lr/package.mk new file mode 100644 index 0000000000..c5132744c0 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/vbam-lr/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) +# 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-lr" +PKG_VERSION="d0787aee43d260675da203c2f85ba9fa226c0c66" +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_LONGDESC="A fork of VBA-M with libretro integration" + +PKG_TOOLCHAIN="make" +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/projects/ArchR/packages/emulators/libretro/vecx-lr/package.mk b/projects/ArchR/packages/emulators/libretro/vecx-lr/package.mk new file mode 100644 index 0000000000..e9bc17d076 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/vecx-lr/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="vecx-lr" +PKG_VERSION="841229a6a81a0461d08af6488f252dcec5266c6a" +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_LONGDESC="libretro adaptation of vecx" + +PKG_TOOLCHAIN="make" + +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 +} diff --git a/projects/ArchR/packages/emulators/libretro/vice-lr/package.mk b/projects/ArchR/packages/emulators/libretro/vice-lr/package.mk new file mode 100644 index 0000000000..8f32781e9c --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/vice-lr/package.mk @@ -0,0 +1,52 @@ +################################################################################ +# 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) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) +# +# 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-lr" +PKG_VERSION="91d0d4d884acd44b5240dfcdbd8bdc2f0f757dfd" +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_LONGDESC="Versatile Commodore 8-bit Emulator version 3.0" +PKG_TOOLCHAIN="make" + +make_target() { + 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/ + cp built/vice_xpet_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/vice-lr/patches/001-revert-makefile.patch b/projects/ArchR/packages/emulators/libretro/vice-lr/patches/001-revert-makefile.patch new file mode 100644 index 0000000000..855ea82355 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/vice-lr/patches/001-revert-makefile.patch @@ -0,0 +1,31 @@ +diff -rupN vice.orig/Makefile vice/Makefile +--- vice.orig/Makefile 2023-09-10 22:23:12.000000000 +0000 ++++ vice/Makefile 2023-09-16 12:43:09.816419382 +0000 +@@ -416,7 +416,6 @@ COMMONFLAGS += -DCORE_NAME=\"$(EMUTYPE)\ + include Makefile.common + + OBJECTS += $(patsubst %.cpp,%.o,$(SOURCES_CXX:.cc=.o)) $(SOURCES_C:.c=.o) +-PLATFLAGS := $(CFLAGS) + CXXFLAGS += $(fpic) $(INCFLAGS) $(COMMONFLAGS) + CFLAGS += $(fpic) $(INCFLAGS) $(COMMONFLAGS) + LDFLAGS += -lm $(fpic) +@@ -437,12 +436,6 @@ ifeq ($(platform), theos_ios) + ${LIBRARY_NAME}_FILES = $(SOURCES_CXX) $(SOURCES_C) + include $(THEOS_MAKE_PATH)/library.mk + else +- +-default: +- $(info CFLAGS: $(PLATFLAGS) $(COMMONFLAGS)) +- $(info -------) +- $(MAKE) $(TARGET) +- + all: $(TARGET) + + -include $(OBJECTS:.o=.d)) +@@ -490,5 +483,5 @@ objectclean: + targetclean: + rm -f $(TARGET) + +-.PHONY: all clean objectclean targetclean ++.PHONY: clean + endif diff --git a/projects/ArchR/packages/emulators/libretro/vircon32-lr/package.mk b/projects/ArchR/packages/emulators/libretro/vircon32-lr/package.mk new file mode 100644 index 0000000000..a5dd329a4b --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/vircon32-lr/package.mk @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024-present AmberELEC (https://github.com/AmberELEC) + +PKG_NAME="vircon32-lr" +PKG_VERSION="d8a92430e887286b4e5351916ef0bd35d8cb40e8" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/vircon32/vircon32-libretro" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain ${OPENGLES}" +PKG_LONGDESC="Vircon32 32-bit Virtual Console" +PKG_TOOLCHAIN="cmake-make" + +pre_configure_target() { + PKG_CMAKE_OPTS_TARGET="-DPLATFORM=EMUELEC \ + -DOPENGL_INCLUDE_DIR=${SYSROOT_PREFIX}/usr/include \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_RULE_MESSAGES=OFF \ + -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON" + + if [ "${PREFER_GLES}" = "yes" ]; then + PKG_CMAKE_OPTS_TARGET+=" -DENABLE_OPENGLES2=1" + fi +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp -f vircon32_libretro.so ${INSTALL}/usr/lib/libretro +} diff --git a/projects/ArchR/packages/emulators/libretro/vircon32-lr/patches/0000-fix-opengl.patch b/projects/ArchR/packages/emulators/libretro/vircon32-lr/patches/0000-fix-opengl.patch new file mode 100644 index 0000000000..fd717489b6 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/vircon32-lr/patches/0000-fix-opengl.patch @@ -0,0 +1,22 @@ +diff --git a/VideoOutput.cpp b/VideoOutput.cpp +index 4109192..9dc1bca 100644 +--- a/VideoOutput.cpp ++++ b/VideoOutput.cpp +@@ -324,7 +324,7 @@ void VideoOutput::InitRendering() + + // on a core OpenGL profile, we need this since + // the default VAO is not valid! +- #if defined(EMUELEC) || defined(HAVE_OPENGLES2) ++ #if defined(HAVE_OPENGLES2) + glGenVertexArraysOES( 1, &VAO ); + glBindVertexArrayOES( VAO ); + #else +@@ -473,7 +473,7 @@ void VideoOutput::Destroy() + VBOVertexInfo = VBOIndices = 0; + + LOG( "Destroying OpenGL vertex arrays" ); +- #if defined(EMUELEC) || defined(HAVE_OPENGLES2) ++ #if defined(HAVE_OPENGLES2) + glDeleteVertexArraysOES( 1, &VAO ); + #else + glDeleteVertexArrays( 1, &VAO ); diff --git a/projects/ArchR/packages/emulators/libretro/virtualjaguar-lr/package.mk b/projects/ArchR/packages/emulators/libretro/virtualjaguar-lr/package.mk new file mode 100644 index 0000000000..a7649d3b98 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/virtualjaguar-lr/package.mk @@ -0,0 +1,34 @@ +################################################################################ +# 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-lr" +PKG_VERSION="48096c1f6f8b98cfff048a5cb4e6a86686631072" +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_LONGDESC="Port of Virtual Jaguar to Libretro" + +PKG_TOOLCHAIN="make" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp virtualjaguar_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/vitaquake2-lr/package.mk b/projects/ArchR/packages/emulators/libretro/vitaquake2-lr/package.mk new file mode 100644 index 0000000000..724f018102 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/vitaquake2-lr/package.mk @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="vitaquake2-lr" +PKG_VERSION="69e56a470638ca8ed15b53212923220360a69f97" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/vitaquake2" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain vitaquake2-rogue-lr vitaquake2-xatrix-lr vitaquake2-zaero-lr" +PKG_LONGDESC="Libretro port of VitaQuakeII (Quake 2 engine)" + +if [ "${OPENGL_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL}" +elif [ "${OPENGLES_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" +fi + +pre_make_target() { + export BUILD_SYSROOT=${SYSROOT_PREFIX} + + case ${TARGET_ARCH} in + aarch64) + PKG_MAKE_OPTS_TARGET+=" platform=${DEVICE}_archr" + ;; + esac +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp vitaquake2_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/vitaquake2-lr/patches/aarch64/001-set-platform.patch b/projects/ArchR/packages/emulators/libretro/vitaquake2-lr/patches/aarch64/001-set-platform.patch new file mode 100644 index 0000000000..800fed1e1e --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/vitaquake2-lr/patches/aarch64/001-set-platform.patch @@ -0,0 +1,19 @@ +diff -rupN vitaquake2.orig/Makefile vitaquake2/Makefile +--- vitaquake2.orig/Makefile 2023-09-15 16:57:45.991890996 +0000 ++++ vitaquake2/Makefile 2023-09-15 20:08:45.856895708 +0000 +@@ -76,6 +76,15 @@ else ifeq ($(platform), linux-portable) + SHARED := -shared -Wl,--version-script=$(CORE_DIR)/link.T + LIBM := + ++else ifeq ($(platform), @DEVICE@_archr) ++ TARGET := $(TARGET_NAME)_libretro.so ++ fpic := -fPIC ++ SHARED := -shared -Wl,--version-script=$(CORE_DIR)/link.T -Wl,--no-undefined ++ CFLAGS += -ffast-math -DARM ++ CFLAGS += -D_POSIX_C_SOURCE=200809L -D_DEFAULT_SOURCE ++ GLES := 1 ++ GLES31 := 1 ++ + else ifneq (,$(findstring rockchip,$(platform))) + EXT ?= so + TARGET := $(TARGET_NAME)_libretro.$(EXT) diff --git a/projects/ArchR/packages/emulators/libretro/vitaquake2-lr/patches/x86_64/001-set-platform.patch b/projects/ArchR/packages/emulators/libretro/vitaquake2-lr/patches/x86_64/001-set-platform.patch new file mode 100644 index 0000000000..fdb106c448 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/vitaquake2-lr/patches/x86_64/001-set-platform.patch @@ -0,0 +1,18 @@ +diff -rupN vitaquake2.orig/Makefile vitaquake2/Makefile +--- vitaquake2.orig/Makefile 2023-09-15 16:57:45.991890996 +0000 ++++ vitaquake2/Makefile 2023-09-15 20:08:45.856895708 +0000 +@@ -76,6 +76,14 @@ else ifeq ($(platform), linux-portable) + SHARED := -shared -Wl,--version-script=$(CORE_DIR)/link.T + LIBM := + ++else ifeq ($(platform), @DEVICE@) ++ TARGET := $(TARGET_NAME)_libretro.so ++ fpic := -fPIC ++ SHARED := -shared -Wl,--version-script=$(CORE_DIR)/link.T -Wl,--no-undefined ++ CFLAGS += -D_POSIX_C_SOURCE=199309L ++ GLES := 1 ++ GLES31 := 1 ++ + else ifneq (,$(findstring rockchip,$(platform))) + EXT ?= so + TARGET := $(TARGET_NAME)_libretro.$(EXT) diff --git a/projects/ArchR/packages/emulators/libretro/vitaquake2-lr/vitaquake2-rogue-lr/package.mk b/projects/ArchR/packages/emulators/libretro/vitaquake2-lr/vitaquake2-rogue-lr/package.mk new file mode 100644 index 0000000000..4adc23ff90 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/vitaquake2-lr/vitaquake2-rogue-lr/package.mk @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="vitaquake2-rogue-lr" +PKG_VERSION="$(get_pkg_version vitaquake2-lr)" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/vitaquake2" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Libretro port of VitaQuakeII (Quake 2 engine)" + +if [ "${OPENGL_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL}" +elif [ "${OPENGLES_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" +fi + +pre_make_target() { + export BUILD_SYSROOT=${SYSROOT_PREFIX} + + PKG_MAKE_OPTS_TARGET+=" basegame=rogue" + + case ${TARGET_ARCH} in + aarch64) + PKG_MAKE_OPTS_TARGET+=" platform=${DEVICE}_archr" + ;; + esac +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp vitaquake2-rogue_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/vitaquake2-lr/vitaquake2-rogue-lr/patches/aarch64/001-set-platform.patch b/projects/ArchR/packages/emulators/libretro/vitaquake2-lr/vitaquake2-rogue-lr/patches/aarch64/001-set-platform.patch new file mode 120000 index 0000000000..77bcdfd104 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/vitaquake2-lr/vitaquake2-rogue-lr/patches/aarch64/001-set-platform.patch @@ -0,0 +1 @@ +../../../patches/aarch64/001-set-platform.patch \ No newline at end of file diff --git a/projects/ArchR/packages/emulators/libretro/vitaquake2-lr/vitaquake2-rogue-lr/patches/x86_64/001-set-platform.patch b/projects/ArchR/packages/emulators/libretro/vitaquake2-lr/vitaquake2-rogue-lr/patches/x86_64/001-set-platform.patch new file mode 100644 index 0000000000..fdb106c448 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/vitaquake2-lr/vitaquake2-rogue-lr/patches/x86_64/001-set-platform.patch @@ -0,0 +1,18 @@ +diff -rupN vitaquake2.orig/Makefile vitaquake2/Makefile +--- vitaquake2.orig/Makefile 2023-09-15 16:57:45.991890996 +0000 ++++ vitaquake2/Makefile 2023-09-15 20:08:45.856895708 +0000 +@@ -76,6 +76,14 @@ else ifeq ($(platform), linux-portable) + SHARED := -shared -Wl,--version-script=$(CORE_DIR)/link.T + LIBM := + ++else ifeq ($(platform), @DEVICE@) ++ TARGET := $(TARGET_NAME)_libretro.so ++ fpic := -fPIC ++ SHARED := -shared -Wl,--version-script=$(CORE_DIR)/link.T -Wl,--no-undefined ++ CFLAGS += -D_POSIX_C_SOURCE=199309L ++ GLES := 1 ++ GLES31 := 1 ++ + else ifneq (,$(findstring rockchip,$(platform))) + EXT ?= so + TARGET := $(TARGET_NAME)_libretro.$(EXT) diff --git a/projects/ArchR/packages/emulators/libretro/vitaquake2-lr/vitaquake2-xatrix-lr/package.mk b/projects/ArchR/packages/emulators/libretro/vitaquake2-lr/vitaquake2-xatrix-lr/package.mk new file mode 100644 index 0000000000..e98f560878 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/vitaquake2-lr/vitaquake2-xatrix-lr/package.mk @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="vitaquake2-xatrix-lr" +PKG_VERSION="$(get_pkg_version vitaquake2-lr)" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/vitaquake2" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Libretro port of VitaQuakeII (Quake 2 engine)" + +if [ "${OPENGL_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL}" +elif [ "${OPENGLES_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" +fi + +pre_make_target() { + export BUILD_SYSROOT=${SYSROOT_PREFIX} + + PKG_MAKE_OPTS_TARGET+=" basegame=xatrix" + + case ${TARGET_ARCH} in + aarch64) + PKG_MAKE_OPTS_TARGET+=" platform=${DEVICE}_archr" + ;; + esac +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp vitaquake2-xatrix_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/vitaquake2-lr/vitaquake2-xatrix-lr/patches/aarch64/001-set-platform.patch b/projects/ArchR/packages/emulators/libretro/vitaquake2-lr/vitaquake2-xatrix-lr/patches/aarch64/001-set-platform.patch new file mode 120000 index 0000000000..77bcdfd104 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/vitaquake2-lr/vitaquake2-xatrix-lr/patches/aarch64/001-set-platform.patch @@ -0,0 +1 @@ +../../../patches/aarch64/001-set-platform.patch \ No newline at end of file diff --git a/projects/ArchR/packages/emulators/libretro/vitaquake2-lr/vitaquake2-xatrix-lr/patches/x86_64/001-set-platform.patch b/projects/ArchR/packages/emulators/libretro/vitaquake2-lr/vitaquake2-xatrix-lr/patches/x86_64/001-set-platform.patch new file mode 100644 index 0000000000..fdb106c448 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/vitaquake2-lr/vitaquake2-xatrix-lr/patches/x86_64/001-set-platform.patch @@ -0,0 +1,18 @@ +diff -rupN vitaquake2.orig/Makefile vitaquake2/Makefile +--- vitaquake2.orig/Makefile 2023-09-15 16:57:45.991890996 +0000 ++++ vitaquake2/Makefile 2023-09-15 20:08:45.856895708 +0000 +@@ -76,6 +76,14 @@ else ifeq ($(platform), linux-portable) + SHARED := -shared -Wl,--version-script=$(CORE_DIR)/link.T + LIBM := + ++else ifeq ($(platform), @DEVICE@) ++ TARGET := $(TARGET_NAME)_libretro.so ++ fpic := -fPIC ++ SHARED := -shared -Wl,--version-script=$(CORE_DIR)/link.T -Wl,--no-undefined ++ CFLAGS += -D_POSIX_C_SOURCE=199309L ++ GLES := 1 ++ GLES31 := 1 ++ + else ifneq (,$(findstring rockchip,$(platform))) + EXT ?= so + TARGET := $(TARGET_NAME)_libretro.$(EXT) diff --git a/projects/ArchR/packages/emulators/libretro/vitaquake2-lr/vitaquake2-zaero-lr/package.mk b/projects/ArchR/packages/emulators/libretro/vitaquake2-lr/vitaquake2-zaero-lr/package.mk new file mode 100644 index 0000000000..090bc1d08f --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/vitaquake2-lr/vitaquake2-zaero-lr/package.mk @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="vitaquake2-zaero-lr" +PKG_VERSION="$(get_pkg_version vitaquake2-lr)" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/vitaquake2" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Libretro port of VitaQuakeII (Quake 2 engine)" + +if [ "${OPENGL_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL}" +elif [ "${OPENGLES_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" +fi + +pre_make_target() { + export BUILD_SYSROOT=${SYSROOT_PREFIX} + + PKG_MAKE_OPTS_TARGET+=" basegame=zaero" + + case ${TARGET_ARCH} in + aarch64) + PKG_MAKE_OPTS_TARGET+=" platform=${DEVICE}_archr" + ;; + esac +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp vitaquake2-zaero_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/vitaquake2-lr/vitaquake2-zaero-lr/patches/aarch64/001-set-platform.patch b/projects/ArchR/packages/emulators/libretro/vitaquake2-lr/vitaquake2-zaero-lr/patches/aarch64/001-set-platform.patch new file mode 120000 index 0000000000..77bcdfd104 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/vitaquake2-lr/vitaquake2-zaero-lr/patches/aarch64/001-set-platform.patch @@ -0,0 +1 @@ +../../../patches/aarch64/001-set-platform.patch \ No newline at end of file diff --git a/projects/ArchR/packages/emulators/libretro/vitaquake2-lr/vitaquake2-zaero-lr/patches/x86_64/001-set-platform.patch b/projects/ArchR/packages/emulators/libretro/vitaquake2-lr/vitaquake2-zaero-lr/patches/x86_64/001-set-platform.patch new file mode 100644 index 0000000000..fdb106c448 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/vitaquake2-lr/vitaquake2-zaero-lr/patches/x86_64/001-set-platform.patch @@ -0,0 +1,18 @@ +diff -rupN vitaquake2.orig/Makefile vitaquake2/Makefile +--- vitaquake2.orig/Makefile 2023-09-15 16:57:45.991890996 +0000 ++++ vitaquake2/Makefile 2023-09-15 20:08:45.856895708 +0000 +@@ -76,6 +76,14 @@ else ifeq ($(platform), linux-portable) + SHARED := -shared -Wl,--version-script=$(CORE_DIR)/link.T + LIBM := + ++else ifeq ($(platform), @DEVICE@) ++ TARGET := $(TARGET_NAME)_libretro.so ++ fpic := -fPIC ++ SHARED := -shared -Wl,--version-script=$(CORE_DIR)/link.T -Wl,--no-undefined ++ CFLAGS += -D_POSIX_C_SOURCE=199309L ++ GLES := 1 ++ GLES31 := 1 ++ + else ifneq (,$(findstring rockchip,$(platform))) + EXT ?= so + TARGET := $(TARGET_NAME)_libretro.$(EXT) diff --git a/projects/ArchR/packages/emulators/libretro/vitaquake3-lr/package.mk b/projects/ArchR/packages/emulators/libretro/vitaquake3-lr/package.mk new file mode 100644 index 0000000000..829423e057 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/vitaquake3-lr/package.mk @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="vitaquake3-lr" +PKG_VERSION="7a633867cf0a35c71701aef6fc9dd9dfab9c33a9" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/vitaquake3" +PKG_URL="https://github.com/libretro/vitaquake3/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Quake III - ioquake3 port for libretro" +PKG_TOOLCHAIN="make" + +if [ "${OPENGL_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL}" +elif [ "${OPENGLES_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" +fi + +pre_configure_target() { + export CFLAGS="${CFLAGS} -Wno-implicit-function-declaration -Wno-incompatible-pointer-types -Wno-implicit-int" +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp vitaquake3_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/wasm4-lr/package.mk b/projects/ArchR/packages/emulators/libretro/wasm4-lr/package.mk new file mode 100644 index 0000000000..18ed257d1e --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/wasm4-lr/package.mk @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + + +PKG_NAME="wasm4-lr" +PKG_VERSION="68cbe429fcbab3e80537282d2c21566f5ea216ea" +PKG_LICENSE="ISC" +PKG_SITE="https://github.com/aduros/wasm4" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="WASM-4 is a low-level fantasy game console for building small games with WebAssembly. Game cartridges (ROMs) are small, self-contained .wasm files that can be built with any programming language that compiles to WebAssembly." +GET_HANDLER_SUPPORT="git" +PKG_TOOLCHAIN='manual' + +make_target() { + cd ${PKG_BUILD}/runtimes/native + cmake -B build \ + -DBUILD_TARGET=wasm4_libretro \ + -DCMAKE_BUILD_TYPE=Release + cmake --build build --target wasm4_libretro +} + + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp ${PKG_BUILD}/runtimes/native/build/wasm4_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/xmil-lr/package.mk b/projects/ArchR/packages/emulators/libretro/xmil-lr/package.mk new file mode 100644 index 0000000000..0ffcb46c66 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/xmil-lr/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present asakous (https://github.com/asakous) + +PKG_NAME="xmil-lr" +PKG_VERSION="6a52dc21a5ff106137670bb600ab2ce3fcebeb1b" +PKG_LICENSE="Unknown" +PKG_SITE="https://github.com/libretro/xmil-libretro" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain" +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/projects/ArchR/packages/emulators/libretro/yabasanshiro-lr/package.mk b/projects/ArchR/packages/emulators/libretro/yabasanshiro-lr/package.mk new file mode 100644 index 0000000000..16e9628e52 --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/yabasanshiro-lr/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) +# +# 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-lr" +PKG_VERSION="39535a6abcad5abf9f71c8b2a7975f005ee12ed6" +PKG_GIT_CLONE_BRANCH="yabasanshiro" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/yabause" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Port of YabaSanshiro to libretro." +PKG_TOOLCHAIN="make" +GET_HANDLER_SUPPORT="git" + +PKG_MAKE_OPTS_TARGET+=" -C yabause/src/libretro" +if [ "${OPENGL_SUPPORT}" = "yes" ] && [ ! "${PREFER_GLES}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL} glu libglvnd" + PKG_MAKE_OPTS_TARGET+=" FORCE_GLES=0" +elif [ "${OPENGLES_SUPPORT}" = yes ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" + PKG_MAKE_OPTS_TARGET+=" FORCE_GLES=1" +fi + +pre_configure_target() { + export CFLAGS="${CFLAGS} -Wno-implicit-function-declaration" + sed -i 's/\-O[23]/-Ofast -ffast-math/' ${PKG_BUILD}/yabause/src/libretro/Makefile + + case ${ARCH} in + aarch64) + PKG_MAKE_OPTS_TARGET+=" platform=rockpro64 HAVE_NEON=0" + # no-outline-atomics is only needed for armv8.2-a targets where we don't use this flag + # as it prohibits the use of LSE-instructions, this is a package bug most likely + export CFLAGS="${CFLAGS} -flto -fipa-pta -mno-outline-atomics" + export CXXFLAGS="${CXXFLAGS} -flto -fipa-pta -mno-outline-atomics" + export LDFLAGS="${CXXFLAGS} -flto -fipa-pta" + ;; + x86_64) + PKG_MAKE_OPTS_TARGET+=" USE_X86_DRC=1 FASTMATH=1" + ;; + esac +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/libretro + cp yabause/src/libretro/yabasanshiro_libretro.so ${INSTALL}/usr/lib/libretro/ +} diff --git a/projects/ArchR/packages/emulators/libretro/yabasanshiro-lr/patches/aarch64/01-optimization.patch b/projects/ArchR/packages/emulators/libretro/yabasanshiro-lr/patches/aarch64/01-optimization.patch new file mode 100644 index 0000000000..bae9d1126e --- /dev/null +++ b/projects/ArchR/packages/emulators/libretro/yabasanshiro-lr/patches/aarch64/01-optimization.patch @@ -0,0 +1,17 @@ +diff -rupN yabasanshiro.orig/yabause/src/libretro/Makefile yabasanshiro/yabause/src/libretro/Makefile +--- yabasanshiro.orig/yabause/src/libretro/Makefile 2022-02-27 14:51:53.958685169 -0500 ++++ yabasanshiro/yabause/src/libretro/Makefile 2022-02-27 14:57:08.993824415 -0500 +@@ -155,11 +155,11 @@ else ifneq (,$(findstring rockpro64,$(pl + SHARED := -shared -Wl,--no-undefined -Wl,--version-script=link.T + LDFLAGS += -lpthread + ARCH_IS_LINUX = 1 ++ FLAGS += -DAARCH64 + HAVE_SSE = 0 + FORCE_GLES = 1 +- USE_ARM_DRC = 1 ++ USE_AARCH64_DRC = 1 + DYNAREC_DEVMIYAX = 1 +- FLAGS += -march=armv8-a+crc -mcpu=cortex-a72 -mtune=cortex-a72.cortex-a53 -mfloat-abi=hard -mfpu=neon-vfpv4 -mvectorize-with-neon-quad + + # Rpi4 (64-bit) + else ifeq ($(platform), rpi4) diff --git a/projects/ArchR/packages/emulators/standalone/amiberry/config/conf/AmigaA1200-default.uae b/projects/ArchR/packages/emulators/standalone/amiberry/config/conf/AmigaA1200-default.uae new file mode 100644 index 0000000000..c81d2999d3 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/amiberry/config/conf/AmigaA1200-default.uae @@ -0,0 +1,197 @@ +config_description=UAE Amiga 1200 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/ +; +; +config_path=/storage/.config/amiberry/conf +controllers_path=/usr/config/SDL-GameControllerDB +retroarch_config=/storage/.config/retroarch/retroarch.cfg +; +; *** Controller/Input Configuration +; +joyport0=mouse +joyport0_autofire=none +joyport0_friendlyname=Mouse +joyport0_name=MOUSE0 +; +joyport1=joy0 +joyport1_autofire=normal +joyport1_friendlyname=Retrogame Joypad +joyport1_name=JOY0 +; +; +joyport1_amiberry_custom_none_a=Joy1 Fire/Mouse1 Left Button +joyport1_amiberry_custom_none_b=Swap joystick ports +joyport1_amiberry_custom_none_x=Joy1 2nd Button/Mouse1 Right Button +joyport1_amiberry_custom_none_y=Toggle Virtual Keyboard +joyport1_amiberry_custom_none_start=Pause emulation +joyport1_amiberry_custom_none_leftshoulder=Quick restore state +joyport1_amiberry_custom_none_rightshoulder=Quick save state +joyport1_amiberry_custom_none_dpup=Joy1 Up +joyport1_amiberry_custom_none_dpdown=Joy2 Down +joyport1_amiberry_custom_none_dpleft=Joy2 Left +joyport1_amiberry_custom_none_dpright=Joy2 Right +joyport1_amiberry_custom_axis_none_leftx=Joy1 Horizontal +joyport1_amiberry_custom_axis_none_lefty=Joy1 Vertical +joyport1_amiberry_custom_axis_none_rightx=Mouse1 Horizontal +joyport1_amiberry_custom_axis_none_righty=Mouse1 Vertical +; +; +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 +default_retroarch_vkbd=yes +default_vkbd_exit=yes +default_vkbd_hires=yes +default_vkbd_enabled=yes +vkbd_style=Original +vkbd_language=US +vkbd_transparency=0 +vkbd_exit=true +vkbd_hires=true +amiberry.use_retroarch_vkbd=true +amiberry.vkbd_enabled=true +amiberry.vkbd_hires=true +amiberry.vkbd_exit=true +; +; *** Common / Paths +; +use_gui=no +kickstart_rom_file=@BIOS_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=NULL +gfx_height=NULL +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 diff --git a/projects/ArchR/packages/emulators/standalone/amiberry/config/conf/AmigaA500-default.uae b/projects/ArchR/packages/emulators/standalone/amiberry/config/conf/AmigaA500-default.uae new file mode 100644 index 0000000000..19f33cefe7 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/amiberry/config/conf/AmigaA500-default.uae @@ -0,0 +1,197 @@ +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/ +; +; +config_path=/storage/.config/amiberry/conf +controllers_path=/usr/config/SDL-GameControllerDB +retroarch_config=/storage/.config/retroarch/retroarch.cfg +; +; *** Controller/Input Configuration +; +joyport0=mouse +joyport0_autofire=none +joyport0_friendlyname=Mouse +joyport0_name=MOUSE0 +; +joyport1=joy0 +joyport1_autofire=normal +joyport1_friendlyname=Retrogame Joypad +joyport1_name=JOY0 +; +; +joyport1_amiberry_custom_none_a=Joy1 Fire/Mouse1 Left Button +joyport1_amiberry_custom_none_b=Swap joystick ports +joyport1_amiberry_custom_none_x=Joy1 2nd Button/Mouse1 Right Button +joyport1_amiberry_custom_none_y=Toggle Virtual Keyboard +joyport1_amiberry_custom_none_start=Pause emulation +joyport1_amiberry_custom_none_leftshoulder=Quick restore state +joyport1_amiberry_custom_none_rightshoulder=Quick save state +joyport1_amiberry_custom_none_dpup=Joy1 Up +joyport1_amiberry_custom_none_dpdown=Joy2 Down +joyport1_amiberry_custom_none_dpleft=Joy2 Left +joyport1_amiberry_custom_none_dpright=Joy2 Right +joyport1_amiberry_custom_axis_none_leftx=Joy1 Horizontal +joyport1_amiberry_custom_axis_none_lefty=Joy1 Vertical +joyport1_amiberry_custom_axis_none_rightx=Mouse1 Horizontal +joyport1_amiberry_custom_axis_none_righty=Mouse1 Vertical +; +; +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 +default_retroarch_vkbd=yes +default_vkbd_exit=yes +default_vkbd_hires=yes +default_vkbd_enabled=yes +vkbd_style=Original +vkbd_language=US +vkbd_transparency=0 +vkbd_exit=true +vkbd_hires=true +amiberry.use_retroarch_vkbd=true +amiberry.vkbd_enabled=true +amiberry.vkbd_hires=true +amiberry.vkbd_exit=true +; +; *** Common / Paths +; +use_gui=no +kickstart_rom_file=@BIOS_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=NULL +gfx_height=NULL +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 diff --git a/projects/ArchR/packages/emulators/standalone/amiberry/config/conf/adfdir.conf b/projects/ArchR/packages/emulators/standalone/amiberry/config/conf/adfdir.conf new file mode 100644 index 0000000000..9ae98c169c --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/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/projects/ArchR/packages/emulators/standalone/amiberry/package.mk b/projects/ArchR/packages/emulators/standalone/amiberry/package.mk new file mode 100644 index 0000000000..45927036b4 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/amiberry/package.mk @@ -0,0 +1,54 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Frank Hartung (supervisedthinking (@) gmail.com) + +PKG_NAME="amiberry" +PKG_ARCH="aarch64" +PKG_VERSION="5c54536997c0039aaa72bb0552cefdc3c967ad8d" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/midwan/amiberry" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain linux glibc bzip2 zlib SDL2 SDL2_image SDL2_ttf capsimg freetype libxml2 flac libogg mpg123 libpng libmpeg2 libserialport" +PKG_LONGDESC="Amiberry is an optimized Amiga emulator for ARM-based boards." +GET_HANDLER_SUPPORT="git" +PKG_TOOLCHAIN="make" +PKG_GIT_CLONE_BRANCH="master" +PKG_PATCH_DIRS+=" ${DEVICE}" + +if [ ! "${OPENGL}" = "no" ]; then + PKG_PATCH_DIRS+=" opengl" +fi + +pre_configure_target() { + export LDFLAGS="${LDFLAGS} -logg" + + cd ${PKG_BUILD} + export SYSROOT_PREFIX=${SYSROOT_PREFIX} + AMIBERRY_PLATFORM="PLATFORM=${DEVICE}" + + sed -i "s|AS = as|AS \?= as|" Makefile + PKG_MAKE_OPTS_TARGET+="${AMIBERRY_PLATFORM} all 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/libretro/autoconfig" "${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 +} diff --git a/projects/ArchR/packages/emulators/standalone/amiberry/patches/01-platform.patch b/projects/ArchR/packages/emulators/standalone/amiberry/patches/01-platform.patch new file mode 100644 index 0000000000..a10f040c4a --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/amiberry/patches/01-platform.patch @@ -0,0 +1,52 @@ +diff -rupN amiberry.orig/Makefile amiberry/Makefile +--- amiberry/Makefile 2022-04-16 16:23:12.481980516 -0400 ++++ amiberry/Makefile 2022-04-16 23:36:53.638425501 -0400 +@@ -43,10 +43,10 @@ + export SDL_CFLAGS := $(shell $(SDL_CONFIG) --cflags) + export SDL_LDFLAGS := $(shell $(SDL_CONFIG) --libs) + +-CPPFLAGS = -MD -MT $@ -MF $(@:%.o=%.d) $(SDL_CFLAGS) -Iexternal/libguisan/include -Isrc -Isrc/osdep -Isrc/threaddep -Isrc/include -Isrc/archivers -Isrc/floppybridge -DAMIBERRY -D_FILE_OFFSET_BITS=64 ++CPPFLAGS = $(CXXFLAGS) -MD -MT $@ -MF $(@:%.o=%.d) $(SDL_CFLAGS) -Iexternal/libguisan/include -Isrc -Isrc/osdep -Isrc/threaddep -Isrc/include -Isrc/archivers -Isrc/floppybridge -DAMIBERRY -D_FILE_OFFSET_BITS=64 +-CFLAGS=-pipe -Wno-shift-overflow -Wno-narrowing ++CFLAGS += -pipe -Wno-shift-overflow -Wno-narrowing + USE_LD ?= gold +-LDFLAGS = $(SDL_LDFLAGS) -lSDL2_image -lSDL2_ttf -lserialport -lguisan -Lexternal/libguisan/lib ++LDFLAGS += $(SDL_LDFLAGS) -lSDL2_image -lSDL2_ttf -lserialport -lguisan -Lexternal/libguisan/lib + ifneq ($(strip $(USE_LD)),) + LDFLAGS += -fuse-ld=$(USE_LD) + endif +@@ -228,30 +228,12 @@ else ifeq ($(PLATFORM),a64) + else ifeq ($(PLATFORM),x86-64) + CPPFLAGS += -DUSE_RENDER_THREAD + +-# RK3288 e.g. Asus Tinker Board +-# RK3328 e.g. PINE64 Rock64 +-# RK3399 e.g. PINE64 RockPro64 +-# RK3326 e.g. Odroid Go Advance - 32-bit userspace +-else ifneq (,$(findstring RK,$(PLATFORM))) +- CPPFLAGS += $(CPPFLAGS32) $(NEON_FLAGS) ++# @DEVICE@ ++else ifeq ($(PLATFORM),@DEVICE@) ++ CPPFLAGS += $(CPPFLAGS64) -O3 -ffast-math -DUSE_RENDER_THREAD ++ AARCH64 = 1 + HAVE_NEON = 1 + +- ifneq (,$(findstring RK33,$(PLATFORM))) +- CPUFLAGS = -mfloat-abi=hard -mfpu=neon-fp-armv8 +- ifneq (,$(findstring RK3399,$(PLATFORM))) +- CPUFLAGS += -mcpu=cortex-a72 +- else ifneq (,$(findstring RK3328,$(PLATFORM))) +- CPUFLAGS += -mcpu=cortex-a53 +- CPPFLAGS += -DUSE_RENDER_THREAD +- else ifneq (,$(findstring RK3326,$(PLATFORM))) +- CPUFLAGS += -mcpu=cortex-a35 +- CPPFLAGS += -DUSE_RENDER_THREAD +- endif +- else ifneq (,$(findstring RK3288,$(PLATFORM))) +- CPUFLAGS = -mcpu=cortex-a17 -mfloat-abi=hard -mfpu=neon-vfpv4 +- CPPFLAGS += -DUSE_RENDER_THREAD +- endif +- + # sun8i Allwinner H2+ / H3 like Orange PI, Nano PI, Banana PI, Tritium, AlphaCore2, MPCORE-HUB + else ifeq ($(PLATFORM),sun8i) + CPUFLAGS = -mcpu=cortex-a7 -mfpu=neon-vfpv4 diff --git a/projects/ArchR/packages/emulators/standalone/amiberry/patches/02-fix-building-with-gcc15.patch b/projects/ArchR/packages/emulators/standalone/amiberry/patches/02-fix-building-with-gcc15.patch new file mode 100644 index 0000000000..4ccf4cc912 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/amiberry/patches/02-fix-building-with-gcc15.patch @@ -0,0 +1,11 @@ +--- a/src/archivers/chd/corestr.cpp ++++ b/src/archivers/chd/corestr.cpp +@@ -16,7 +16,7 @@ + + #include + #include +- ++#include + + /*------------------------------------------------- + core_stricmp - case-insensitive string compare diff --git a/projects/ArchR/packages/emulators/standalone/amiberry/patches/opengl/001-fix-sdl.patch b/projects/ArchR/packages/emulators/standalone/amiberry/patches/opengl/001-fix-sdl.patch new file mode 100644 index 0000000000..61b4f77186 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/amiberry/patches/opengl/001-fix-sdl.patch @@ -0,0 +1,20 @@ +diff --git a/src/osdep/amiberry.cpp b/src/osdep/amiberry.cpp +index 13237df9..95e6b04e 100644 +--- a/src/osdep/amiberry.cpp ++++ b/src/osdep/amiberry.cpp +@@ -3691,12 +3691,9 @@ int main(int argc, char* argv[]) + write_log("SDL could not initialize! SDL_Error: %s\n", SDL_GetError()); + abort(); + } +-#ifdef USE_OPENGL +- SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); +- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); +- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); +- //SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); +-#endif ++ ++ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); ++ + atexit(SDL_Quit); + write_log(_T("Sorting devices and modes...\n")); + sortdisplays(); diff --git a/projects/ArchR/packages/emulators/standalone/amiberry/scripts/start_amiberry.sh b/projects/ArchR/packages/emulators/standalone/amiberry/scripts/start_amiberry.sh new file mode 100755 index 0000000000..8fcf03e702 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/amiberry/scripts/start_amiberry.sh @@ -0,0 +1,159 @@ +#!/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) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile + +set_kill set "-9 amiberry" + +# 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="/var/log/amiberry.log" +BIOS_PATH="/storage/roms/bios" +MAX_DRIVES=4 +i=0 + +echo "Amiberry Log" > "${AMIBERRY_LOG}" + +if [ ! -d "${AMIBERRY_TMP_DIR}" ] +then + mkdir -p "${AMIBERRY_TMP_DIR}" +fi + +if [ ! -d "${AMIBERRY_DIR}" ] +then + cp -rf /usr/config/amiberry ${AMIBERRY_DIR} +fi + +### Refresh the configs so we can manage them. +cp -f /usr/config/amiberry/conf/* ${AMIBERRY_DIR}/conf + +find_gamepad() { + # Check for js0 first, else fall back to joypad + if grep -q "js0" /proc/bus/input/devices; then + GAMEPAD=$(grep -b4 js0 /proc/bus/input/devices | awk 'BEGIN {FS="\""}; /Name/ {printf $2}') + else + GAMEPAD=$(grep -b4 joypad /proc/bus/input/devices | awk 'BEGIN {FS="\""}; /Name/ {printf $2}') + fi + sed -i "s|joyport1_friendlyname=.*|joyport1_friendlyname=${GAMEPAD}|" "${AMIBERRY_TMP_CONFIG}" + echo "Gamepad used ${GAMEPAD}" >> "${AMIBERRY_LOG}" +} + +# 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 | grep -E 'AGA|CD32' | wc -l` -eq 1 -o `echo "${AMIBERRY_TMP_DIR}"/* | grep -e '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 + sed -i "s#@BIOS_PATH@#${BIOS_PATH}#g" ${AMIBERRY_TMP_CONFIG} + sed -i "s#gfx_width=.*\$#$(fbwidth)#g" ${AMIBERRY_TMP_CONFIG} + sed -i "s#gfx_height=.*\$#$(fbheight)#g" ${AMIBERRY_TMP_CONFIG} + 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/projects/ArchR/packages/emulators/standalone/daedalusx64-sa/config/Preferences.ini b/projects/ArchR/packages/emulators/standalone/daedalusx64-sa/config/Preferences.ini new file mode 100644 index 0000000000..f8b5ad6f89 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/daedalusx64-sa/config/Preferences.ini @@ -0,0 +1,13 @@ +DisplayFramerate=no +ForceLinearFilter=no +RumblePak=no +BatteryWarning=no +LargeROMBuffer=yes +GuiColor=0 +StickMinDeadzone=0.280000 +StickMaxDeadzone=1.000000 +Language=English +ViewportType=2 +TVEnable=no +TVLaced=no +TVType=0 diff --git a/projects/ArchR/packages/emulators/standalone/daedalusx64-sa/package.mk b/projects/ArchR/packages/emulators/standalone/daedalusx64-sa/package.mk new file mode 100644 index 0000000000..168d854e7e --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/daedalusx64-sa/package.mk @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2025-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="daedalusx64-sa" +PKG_VERSION="f17e9ed86f3806fadeb69abd29c9526ab2d4bd1b" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/DaedalusX64/daedalus" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain libfmt SDL2 SDL2_ttf glew mesa glm" +PKG_LONGDESC="DaedalusX64 is a Nintendo 64 emulator for PSP, 3DS, Vita, Linux, macOS and Windows" +PKG_PATCH_DIRS+="${DEVICE}" + +if [ "${ARCH}" = "aarch64" ]; then + PKG_TOOLCHAIN="manual" +else + PKG_TOOLCHAIN="cmake" +fi + +if [ "${OPENGL_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL}" +elif [ "${OPENGLES_SUPPORT}" = yes ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" +fi + +makeinstall_target() { + if [ "${ARCH}" = "aarch64" ] + then + mkdir -p ${INSTALL}/usr + cp -r ${ROOT}/build.${DISTRO}-${DEVICE}.arm/install_pkg/daedalusx64-sa-${PKG_VERSION}/usr/* ${INSTALL}/usr/ + chmod +x ${INSTALL}/usr/bin/* + else + mkdir -p ${INSTALL}/usr/bin + mkdir -p ${INSTALL}/usr/config/DaedalusX64 + cp ${PKG_BUILD}/.${TARGET_NAME}/Source/daedalus ${INSTALL}/usr/config/DaedalusX64/daedalus + cp ${PKG_DIR}/scripts/* ${INSTALL}/usr/bin + cp ${PKG_DIR}/config/* ${INSTALL}/usr/config/DaedalusX64 + cp -r ${PKG_BUILD}/Data/* ${INSTALL}/usr/config/DaedalusX64 + cp -r ${PKG_BUILD}/Source/SysGL/HLEGraphics/n64.psh ${INSTALL}/usr/config/DaedalusX64 + chmod +x ${INSTALL}/usr/bin/* + fi +} diff --git a/projects/ArchR/packages/emulators/standalone/daedalusx64-sa/patches/000-input.patch b/projects/ArchR/packages/emulators/standalone/daedalusx64-sa/patches/000-input.patch new file mode 100644 index 0000000000..e4d59f795e --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/daedalusx64-sa/patches/000-input.patch @@ -0,0 +1,151 @@ +diff --git a/Source/Input/SDL/InputManagerSDL.cpp b/Source/Input/SDL/InputManagerSDL.cpp +index 1ffd1741..358f2e49 100644 +--- a/Source/Input/SDL/InputManagerSDL.cpp ++++ b/Source/Input/SDL/InputManagerSDL.cpp +@@ -131,66 +131,96 @@ void IInputManager::GetJoyPad(OSContPad *pPad) + + //ToDo: Different gamepads will need different configuration, this is for PS3/PS2 controller + if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_START)) pPad->button |= START_BUTTON; +- if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_A)) pPad->button |= A_BUTTON; +- if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_B)) pPad->button |= B_BUTTON; +- if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_LEFTSHOULDER)) pPad->button |= Z_TRIG; +- if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER)) pPad->button |= Z_TRIG; +- if (SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_TRIGGERLEFT) > 16383) pPad->button |= L_TRIG; +- if (SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_TRIGGERRIGHT) > 16383) pPad->button |= R_TRIG; ++ if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_B)) pPad->button |= A_BUTTON; ++ if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_Y)) pPad->button |= B_BUTTON; ++ if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_LEFTSHOULDER)) pPad->button |= L_TRIG; ++ if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER)) pPad->button |= R_TRIG; ++ if (SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_TRIGGERLEFT) > 16383) pPad->button |= Z_TRIG; ++ if (SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_TRIGGERRIGHT) > 16383) pPad->button |= Z_TRIG; + + if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_DPAD_UP)) pPad->button |= U_JPAD; + if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_DPAD_DOWN)) pPad->button |= D_JPAD; + if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_DPAD_LEFT)) pPad->button |= L_JPAD; + if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_DPAD_RIGHT)) pPad->button |= R_JPAD; + +- // Hold O button and use hat buttons for N64 c buttons (same as the PSP) +- // We could use the second analog stick to map them, but will require to translate asix >=2 +- if(SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_X)) +- { +- if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_DPAD_UP)) pPad->button |= U_CBUTTONS; +- if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_DPAD_DOWN)) pPad->button |= D_CBUTTONS; +- if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_DPAD_LEFT)) pPad->button |= L_CBUTTONS; +- if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_DPAD_RIGHT)) pPad->button |= R_CBUTTONS; +- } +- +- // Used to see key presses, useful to add a different button configuration +- //for(int i = 0; i < num_buttons; i++) +- //{ +- // if(buttons[i]) +- // printf("%d\n",i); +- //} ++ if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_X)) pPad->button |= U_CBUTTONS; ++ if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_A)) pPad->button |= R_CBUTTONS; + ++ // Axis values for the first joystick (Left Stick - Joystick 1) + const s32 SDL_AXIS_MIN = -32768; + const s32 SDL_AXIS_MAX = 32767; + +- // Get the raw axis values +- s32 raw_x = SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_LEFTX); +- s32 raw_y = SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_LEFTY); ++ // Get the raw axis values for Left Stick (Joystick 1) ++ s32 raw_x_joystick1 = SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_LEFTX); ++ s32 raw_y_joystick1 = SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_LEFTY); + + // Normalize the axis values to the range [-1, 1] +- float normalized_x = raw_x / 32767.0f; +- float normalized_y = raw_y / 32767.0f; +- +- // Scale the normalized values to the N64 range +- s8 scaled_x = static_cast(normalized_x * N64_ANALOGUE_STICK_RANGE); +- s8 scaled_y = static_cast(normalized_y * N64_ANALOGUE_STICK_RANGE); +- +- // Manually clamp the values to ensure they are within the valid range +- if (scaled_x > N64_ANALOGUE_STICK_RANGE) { +- scaled_x = N64_ANALOGUE_STICK_RANGE; +- } else if (scaled_x < -N64_ANALOGUE_STICK_RANGE) { +- scaled_x = -N64_ANALOGUE_STICK_RANGE; ++ float normalized_x_joystick1 = raw_x_joystick1 / 32767.0f; ++ float normalized_y_joystick1 = raw_y_joystick1 / 32767.0f; ++ ++ // Scale the normalized values to the N64 range for Joystick 1 ++ s8 scaled_x_joystick1 = static_cast(normalized_x_joystick1 * N64_ANALOGUE_STICK_RANGE); ++ s8 scaled_y_joystick1 = static_cast(normalized_y_joystick1 * N64_ANALOGUE_STICK_RANGE); ++ ++ // Manually clamp the values to ensure they are within the valid range for N64 Joystick 1 ++ if (scaled_x_joystick1 > N64_ANALOGUE_STICK_RANGE) { ++ scaled_x_joystick1 = N64_ANALOGUE_STICK_RANGE; ++ } else if (scaled_x_joystick1 < -N64_ANALOGUE_STICK_RANGE) { ++ scaled_x_joystick1 = -N64_ANALOGUE_STICK_RANGE; + } + +- if (scaled_y > N64_ANALOGUE_STICK_RANGE) { +- scaled_y = N64_ANALOGUE_STICK_RANGE; +- } else if (scaled_y < -N64_ANALOGUE_STICK_RANGE) { +- scaled_y = -N64_ANALOGUE_STICK_RANGE; ++ if (scaled_y_joystick1 > N64_ANALOGUE_STICK_RANGE) { ++ scaled_y_joystick1 = N64_ANALOGUE_STICK_RANGE; ++ } else if (scaled_y_joystick1 < -N64_ANALOGUE_STICK_RANGE) { ++ scaled_y_joystick1 = -N64_ANALOGUE_STICK_RANGE; ++ } ++ ++ // Assign the left joystick values to N64 joystick analog stick ++ pPad->stick_x = scaled_x_joystick1; ++ pPad->stick_y = -1 * scaled_y_joystick1; ++ ++ // C buttons are controlled by the Right Stick (Joystick 2) ++ s32 raw_x_joystick2 = SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_RIGHTX); ++ s32 raw_y_joystick2 = SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_RIGHTY); ++ ++ // Normalize the axis values for Joystick 2 to the range [-1, 1] (Right Stick for C Buttons) ++ float normalized_x_joystick2 = raw_x_joystick2 / 32767.0f; ++ float normalized_y_joystick2 = raw_y_joystick2 / 32767.0f; ++ ++ // Scale the normalized values for C button range ++ s8 scaled_x_joystick2 = static_cast(normalized_x_joystick2 * N64_ANALOGUE_STICK_RANGE); ++ s8 scaled_y_joystick2 = static_cast(normalized_y_joystick2 * N64_ANALOGUE_STICK_RANGE); ++ ++ // Manually clamp the values for C buttons ++ if (scaled_x_joystick2 > N64_ANALOGUE_STICK_RANGE) { ++ scaled_x_joystick2 = N64_ANALOGUE_STICK_RANGE; ++ } else if (scaled_x_joystick2 < -N64_ANALOGUE_STICK_RANGE) { ++ scaled_x_joystick2 = -N64_ANALOGUE_STICK_RANGE; + } + +- pPad->stick_x = scaled_x; +- pPad->stick_y = -1 * scaled_y; ++ if (scaled_y_joystick2 > N64_ANALOGUE_STICK_RANGE) { ++ scaled_y_joystick2 = N64_ANALOGUE_STICK_RANGE; ++ } else if (scaled_y_joystick2 < -N64_ANALOGUE_STICK_RANGE) { ++ scaled_y_joystick2 = -N64_ANALOGUE_STICK_RANGE; ++ } + ++ // Use the values from the second joystick for C buttons ++ // Check for the dominant axis to avoid diagonal triggering both buttons ++ if (abs(scaled_x_joystick2) > abs(scaled_y_joystick2)) { ++ // Horizontal C buttons (left/right) ++ if (scaled_x_joystick2 > 20) { // Right movement ++ pPad->button |= R_CBUTTONS; ++ } else if (scaled_x_joystick2 < -20) { // Left movement ++ pPad->button |= L_CBUTTONS; ++ } ++ } else { ++ // Vertical C buttons (up/down) ++ if (scaled_y_joystick2 > 20) { // Up movement ++ pPad->button |= U_CBUTTONS; ++ } else if (scaled_y_joystick2 < -20) { // Down movement ++ pPad->button |= D_CBUTTONS; ++ } ++ } + } + + void IInputManager::GetState( OSContPad pPad[4] ) +@@ -449,4 +479,4 @@ glm::vec2 ApplyDeadzone( const glm::vec2 & in, f32 min_deadzone, f32 max_deadzon + scale = std::clamp( scale, 0.0f, 1.0f ); + + return ProjectToUnitSquare( in * (scale / length) ); +-} +\ No newline at end of file ++} diff --git a/projects/ArchR/packages/emulators/standalone/daedalusx64-sa/scripts/start_daedalusx64.sh b/projects/ArchR/packages/emulators/standalone/daedalusx64-sa/scripts/start_daedalusx64.sh new file mode 100644 index 0000000000..6c4a2b12b6 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/daedalusx64-sa/scripts/start_daedalusx64.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2025-present ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile +set_kill set "-9 daedalus" + +#Check if DaedalusX64 exists in .config +if [ ! -d "/storage/.config/DaedalusX64" ]; then + cp -r "/usr/config/DaedalusX64" "/storage/.config/" +fi + +#Check if n64 save state folders exist +if [ ! -d "/storage/roms/savestates/n64/daedalus" ]; then + mkdir -p "/storage/roms/savestates/n64/daedalus" +fi + +# Link Roms, Saves, and SaveStates to correct dir +rm "/storage/.config/DaedalusX64/Roms" +ln -sf "/storage/roms/n64" "/storage/.config/DaedalusX64/Roms" +rm "/storage/.config/DaedalusX64/SavesGames" +ln -sf "/storage/roms/n64" "/storage/.config/DaedalusX64/SavesGames" +rm "/storage/.config/DaedalusX64/SaveStates" +ln -sf "/storage/roms/savestates/n64/daedalus" "/storage/.config/DaedalusX64/SaveStates" + +#Emulation Station Features +GAME=$(echo "${1}"| sed "s#^/.*/##") +PLATFORM=$(echo "${2}"| sed "s#^/.*/##") + +#Set the cores to use +CORES=$(get_setting "cores" "${PLATFORM}" "${GAME}") +if [ "${CORES}" = "little" ] +then + EMUPERF="${SLOW_CORES}" +elif [ "${CORES}" = "big" ] +then + EMUPERF="${FAST_CORES}" +else + ### All.. + unset EMUPERF +fi + +#Always grab the latest daedalus bin +shasum1=$(sha1sum /usr/config/DaedalusX64/daedalus | awk '{print $1}') +shasum2=$(sha1sum /storage/.config/DaedalusX64/daedalus | awk '{print $1}') + +if [ "$shasum1" <> "$shasum2" ]; then + cp -r "/usr/config/DaedalusX64/daedalus" "/storage/.config/DaedalusX64/daedalus" +fi + +cd /storage/.config/DaedalusX64/ + +${EMUPERF} /storage/.config/DaedalusX64/daedalus "${1}" diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/InputPlumber/GamecubeControllerProfiles/GCPadNew.ini.east b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/InputPlumber/GamecubeControllerProfiles/GCPadNew.ini.east new file mode 100644 index 0000000000..ef28b82a1a --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/InputPlumber/GamecubeControllerProfiles/GCPadNew.ini.east @@ -0,0 +1,36 @@ +[GCPad1] +Device = evdev/0/Microsoft X-Box 360 pad +Buttons/A = Button 0 +Buttons/B = Button 1 +Buttons/Start = Button 7 +Buttons/X = Button 3 +Buttons/Y = Button 2 +Buttons/Z = Button 5 +Buttons/Hotkey = Button 6 +C-Stick/Dead Zone = 25.000000000000000 +C-Stick/Down = Axis 4+ +C-Stick/Left = Axis 3- +C-Stick/Modifier = Control_L +C-Stick/Modifier/Range = 50.000000000000000 +C-Stick/Right = Axis 3+ +C-Stick/Up = Axis 4- +D-Pad/Down = Axis 7+ +D-Pad/Left = Axis 6- +D-Pad/Right = Axis 6+ +D-Pad/Up = Axis 7- +Main Stick/Dead Zone = 25.000000000000000 +Main Stick/Down = Axis 1+ +Main Stick/Left = Axis 0- +Main Stick/Modifier = Shift_L +Main Stick/Modifier/Range = 50.000000000000000 +Main Stick/Right = Axis 0+ +Main Stick/Up = Axis 1- +Triggers/Dead Zone = 0. +Triggers/Threshold = 90. +Triggers/L = Axis 2+ +Triggers/R = Axis 5+ +Triggers/L-Analog = Axis 2+ +Triggers/R-Analog = Axis 5+ +Rumble/Motor = `evdev/0/AYN Odin2 Gamepad:Strong` +Triforce/Coin = Button 8 +Triforce/Service = Button 4 diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/InputPlumber/GamecubeControllerProfiles/GCPadNew.ini.south b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/InputPlumber/GamecubeControllerProfiles/GCPadNew.ini.south new file mode 100644 index 0000000000..253e7b2604 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/InputPlumber/GamecubeControllerProfiles/GCPadNew.ini.south @@ -0,0 +1,36 @@ +[GCPad1] +Device = evdev/0/Microsoft X-Box 360 pad +Buttons/A = Button 1 +Buttons/B = Button 2 +Buttons/Start = Button 7 +Buttons/X = Button 0 +Buttons/Y = Button 3 +Buttons/Z = Button 5 +Buttons/Hotkey = Button 6 +C-Stick/Dead Zone = 25.000000000000000 +C-Stick/Down = Axis 4+ +C-Stick/Left = Axis 3- +C-Stick/Modifier = Control_L +C-Stick/Modifier/Range = 50.000000000000000 +C-Stick/Right = Axis 3+ +C-Stick/Up = Axis 4- +D-Pad/Down = Axis 7+ +D-Pad/Left = Axis 6- +D-Pad/Right = Axis 6+ +D-Pad/Up = Axis 7- +Main Stick/Dead Zone = 25.000000000000000 +Main Stick/Down = Axis 1+ +Main Stick/Left = Axis 0- +Main Stick/Modifier = Shift_L +Main Stick/Modifier/Range = 50.000000000000000 +Main Stick/Right = Axis 0+ +Main Stick/Up = Axis 1- +Triggers/Dead Zone = 0. +Triggers/Threshold = 90. +Triggers/L = Axis 2+ +Triggers/R = Axis 5+ +Triggers/L-Analog = Axis 2+ +Triggers/R-Analog = Axis 5+ +Rumble/Motor = `evdev/0/AYN Odin2 Gamepad:Strong` +Triforce/Coin = Button 8 +Triforce/Service = Button 4 diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/InputPlumber/Hotkeys.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/InputPlumber/Hotkeys.ini new file mode 100644 index 0000000000..838c89f486 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/InputPlumber/Hotkeys.ini @@ -0,0 +1,10 @@ +[Hotkeys] +Device = evdev/0/Microsoft X-Box 360 pad +Graphics Toggles/Toggle Aspect Ratio = @(MODE+EAST) +General/Take Screenshot = @(MODE+SOUTH) +Save State/Save to Selected Slot = @(MODE+TR) +Load State/Load State Slot 1 = @(MODE+TL) +Other State Hotkeys/Increase Selected State Slot = @(MODE+`Axis 7-`) +Other State Hotkeys/Decrease Selected State Slot = @(MODE+`Axis 7+`) +Emulation Speed/Increase Emulation Speed = @(MODE+`Full Axis 5+`) +Emulation Speed/Decrease Emulation Speed = @(MODE+`Full Axis 2+`) diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/InputPlumber/WiiControllerProfiles/classic.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/InputPlumber/WiiControllerProfiles/classic.ini new file mode 100644 index 0000000000..77f260bf57 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/InputPlumber/WiiControllerProfiles/classic.ini @@ -0,0 +1,28 @@ +[Wiimote1] +Device = evdev/0/Microsoft X-Box 360 pad +Extension = Classic +Source = 1 +Classic/Buttons/A = Button 1 +Classic/Buttons/B = Button 0 +Classic/Buttons/X = Button 2 +Classic/Buttons/Y = Button 3 +Classic/Buttons/ZL = Axis 2+ +Classic/Buttons/ZR = Axis 5+ +Classic/Buttons/- = Button 6 +Classic/Buttons/+ = Button 7 +Classic/Buttons/Home = Button 8 +Classic/Left Stick/Up = Axis 1- +Classic/Left Stick/Down = Axis 1+ +Classic/Left Stick/Left = Axis 0- +Classic/Left Stick/Right = Axis 0+ +Classic/Right Stick/Up = Axis 4- +Classic/Right Stick/Down = Axis 4+ +Classic/Right Stick/Left = Axis 3- +Classic/Right Stick/Right = Axis 3+ +Classic/Triggers/L = Button 4 +Classic/Triggers/R = Button 5 +Classic/D-Pad/Up = Axis 7- +Classic/D-Pad/Down = Axis 7+ +Classic/D-Pad/Left = Axis 6- +Classic/D-Pad/Right = Axis 6+ +Rumble/Motor = `evdev/0/AYN Odin2 Gamepad:Strong` diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/InputPlumber/WiiControllerProfiles/hremote.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/InputPlumber/WiiControllerProfiles/hremote.ini new file mode 100644 index 0000000000..a424c70bed --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/InputPlumber/WiiControllerProfiles/hremote.ini @@ -0,0 +1,21 @@ +[Wiimote1] +Device = evdev/0/Microsoft X-Box 360 pad +Buttons/A = Button 3 +Buttons/B = Button 2 +Buttons/1 = Button 0 +Buttons/2 = Button 1 +Buttons/- = Button 6 +Buttons/+ = Button 7 +Buttons/Home = Button 8 +Shake/X = Button 4 +Shake/Y = Button 4 +Shake/Z = Button 4 +D-Pad/Up = `Axis 6-` | `Axis 0-` +D-Pad/Down = `Axis 6+` | `Axis 0+` +D-Pad/Left = `Axis 7+` | `Axis 1+` +D-Pad/Right = `Axis 7-` | `Axis 1-` +IR/Up = `Axis 4-` +IR/Down = `Axis 4+` +IR/Left = `Axis 3-` +IR/Right = `Axis 3+` +Rumble/Motor = `evdev/0/AYN Odin2 Gamepad:Strong` diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/InputPlumber/WiiControllerProfiles/nunchuck.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/InputPlumber/WiiControllerProfiles/nunchuck.ini new file mode 100644 index 0000000000..da607132d5 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/InputPlumber/WiiControllerProfiles/nunchuck.ini @@ -0,0 +1,31 @@ +[Wiimote1] +Device = evdev/0/Microsoft X-Box 360 pad +Extension = Nunchuk +Buttons/A = Button 1 +Buttons/B = Button 0 +Buttons/1 = Button 3 +Buttons/2 = Button 2 +Buttons/- = Button 6 +Buttons/+ = Button 7 +D-Pad/Up = Axis 7- +D-Pad/Down = Axis 7+ +D-Pad/Left = Axis 6- +D-Pad/Right = Axis 6+ +Buttons/Home = Button 8 +Shake/X = Button 4 +Shake/Y = Button 4 +Shake/Z = Button 4 +Nunchuk/Buttons/C = Button 5 +Nunchuk/Buttons/Z = Axis 5+ +Nunchuk/Stick/Up = Axis 1- +Nunchuk/Stick/Down = Axis 1+ +Nunchuk/Stick/Left = Axis 0- +Nunchuk/Stick/Right = Axis 0+ +Nunchuk/Shake/X = Axis 2+ +Nunchuk/Shake/Y = Axis 2+ +Nunchuk/Shake/Z = Axis 2+ +IR/Up = `Axis 4-` +IR/Down = `Axis 4+` +IR/Left = `Axis 3-` +IR/Right = `Axis 3+` +Rumble/Motor = `evdev/0/AYN Odin2 Gamepad:Strong` diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/InputPlumber/WiiControllerProfiles/vremote.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/InputPlumber/WiiControllerProfiles/vremote.ini new file mode 100644 index 0000000000..5e35a10901 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/InputPlumber/WiiControllerProfiles/vremote.ini @@ -0,0 +1,21 @@ +[Wiimote1] +Device = evdev/0/Microsoft X-Box 360 pad +Buttons/A = Button 1 +Buttons/B = Button 0 +Buttons/1 = Button 3 +Buttons/2 = Button 2 +Buttons/- = Button 6 +Buttons/+ = Button 7 +Buttons/Home = Button 8 +Shake/X = Button 4 +Shake/Y = Button 4 +Shake/Z = Button 4 +D-Pad/Up = `Axis 7-` | `Axis 1-` +D-Pad/Down = `Axis 7+` | `Axis 1+` +D-Pad/Left = `Axis 6-` | `Axis 0-` +D-Pad/Right = `Axis 6+` | `Axis 0+` +IR/Up = `Axis 4-` +IR/Down = `Axis 4+` +IR/Left = `Axis 3-` +IR/Right = `Axis 3+` +Rumble/Motor = `evdev/0/AYN Odin2 Gamepad:Strong` diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3399/Dolphin.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3399/Dolphin.ini new file mode 100755 index 0000000000..887e02bd7c --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3399/Dolphin.ini @@ -0,0 +1,153 @@ +[General] +LastFilename = +ShowLag = False +ShowFrameCount = False +ISOPath0 = /storage/roms/gamecube +ISOPath1 = /storage/roms/wii +ISOPaths = 2 +RecursiveISOPaths = False +NANDRootPath = +WirelessMac = +[Interface] +ConfirmStop = True +UsePanicHandlers = True +OnScreenDisplayMessages = True +HideCursor = False +AutoHideCursor = False +MainWindowPosX = 403 +MainWindowPosY = 148 +MainWindowWidth = 800 +MainWindowHeight = 600 +Language = 0 +ShowToolbar = True +ShowStatusbar = True +ShowLogWindow = False +ShowLogConfigWindow = False +ExtendedFPSInfo = False +ThemeName40 = Clean Blue +PauseOnFocusLost = False +[Display] +FullscreenResolution = Auto +Fullscreen = True +RenderToMain = False +RenderWindowXPos = -1 +RenderWindowYPos = -1 +RenderWindowWidth = 640 +RenderWindowHeight = 480 +RenderWindowAutoSize = False +KeepWindowOnTop = False +ProgressiveScan = False +PAL60 = True +DisableScreenSaver = True +ForceNTSCJ = False +[GameList] +ListDrives = False +ListWad = True +ListElfDol = True +ListWii = True +ListGC = True +ListJap = True +ListPal = True +ListUsa = True +ListAustralia = True +ListFrance = True +ListGermany = True +ListItaly = True +ListKorea = True +ListNetherlands = True +ListRussia = True +ListSpain = True +ListTaiwan = True +ListWorld = True +ListUnknown = True +ListSort = 3 +ListSortSecondary = 0 +ColorCompressed = True +ColumnPlatform = True +ColumnBanner = True +ColumnNotes = True +ColumnFileName = False +ColumnID = False +ColumnRegion = True +ColumnSize = True +ColumnState = True +[Core] +SkipIPL = True +HLE_BS2 = False +TimingVariance = 40 +CPUCore = 4 +Fastmem = True +CPUThread = True +DSPHLE = True +SkipIdle = True +SyncOnSkipIdle = True +SyncGPU = False +SyncGpuMaxDistance = 200000 +SyncGpuMinDistance = -200000 +SyncGpuOverclock = 1.00000000 +FPRF = False +AccurateNaNs = False +DefaultISO = +DVDRoot = +Apploader = +EnableCheats = True +SelectedLanguage = 0 +OverrideGCLang = False +DPL2Decoder = False +Latency = 2 +MemcardAPath = +MemcardBPath = +AgpCartAPath = +AgpCartBPath = +GCIFolderAPath = /storage/roms/bios/GC/USA +SlotA = 1 +SlotB = 255 +SerialPort1 = 255 +BBA_MAC = +SIDevice0 = 6 +AdapterRumble0 = True +SimulateKonga0 = False +SIDevice1 = 6 +AdapterRumble1 = True +SimulateKonga1 = False +SIDevice2 = 0 +AdapterRumble2 = True +SimulateKonga2 = False +SIDevice3 = 0 +AdapterRumble3 = True +SimulateKonga3 = False +WiiSDCard = False +WiiKeyboard = False +WiimoteContinuousScanning = False +WiimoteEnableSpeaker = False +RunCompareServer = False +RunCompareClient = False +EmulationSpeed = 1.00000000 +FrameSkip = 0x00000003 +Overclock = 4.00000000 +OverclockEnable = False +GFXBackend = +GPUDeterminismMode = auto +PerfMapDir = +AutoDiscChange = True +[Movie] +PauseMovie = False +Author = +DumpFrames = False +DumpFramesSilent = False +ShowInputDisplay = False +[DSP] +EnableJIT = True +DumpAudio = False +DumpUCode = False +Backend = Pulse +Volume = 100 +CaptureLog = False +[Input] +BackgroundInput = False +[FifoPlayer] +LoopReplay = True +[Analytics] +ID = 5082f0c30a7e422b1220107f69d6c108 +Enabled = False +PermissionAsked = True diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3399/GFX.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3399/GFX.ini new file mode 100755 index 0000000000..6cd269c601 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3399/GFX.ini @@ -0,0 +1,61 @@ +[Hardware] +VSync = False +Adapter = 0 +[Settings] +AspectRatio = 2 +InternalResolution = 1 +Crop = False +wideScreenHack = False +UseXFB = False +UseRealXFB = False +SafeTextureCacheColorSamples = 128 +ShowFPS = False +LogRenderTimeToFile = False +OverlayStats = False +OverlayProjStats = False +DumpTextures = False +HiresTextures = False +ConvertHiresTextures = False +CacheHiresTextures = False +DumpEFBTarget = False +FreeLook = False +UseFFV1 = False +EnablePixelLighting = False +FastDepthCalc = True +MSAA = 1 +SSAA = False +EFBScale = 2 +TexFmtOverlayEnable = False +TexFmtOverlayCenter = False +Wireframe = False +DisableFog = False +EnableShaderDebugging = False +BorderlessFullscreen = False +SWZComploc = True +SWZFreeze = True +SWDumpObjects = False +SWDumpTevStages = False +SWDumpTevTexFetches = False +SWDrawStart = 0 +SWDrawEnd = 100000 +ShaderCompilationMode = 0 +WaitForShadersBeforeStarting = True +BackendMultithreading = True +EnableGPUTextureDecoding = True +[Enhancements] +ForceFiltering = False +MaxAnisotropy = 0 +PostProcessingShader = +[Stereoscopy] +StereoMode = 0 +StereoDepth = 20 +StereoConvergencePercentage = 100 +StereoSwapEyes = False +[Hacks] +EFBAccessEnable = False +BBoxEnable = False +ForceProgressive = True +EFBToTextureEnable = True +EFBScaledCopy = False +EFBEmulateFormatChanges = False +SkipDuplicateXFBs = True diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3399/GamecubeControllerProfiles/GCPadNew.ini.east b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3399/GamecubeControllerProfiles/GCPadNew.ini.east new file mode 100755 index 0000000000..dbd6fae001 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3399/GamecubeControllerProfiles/GCPadNew.ini.east @@ -0,0 +1,31 @@ +[GCPad1] +Device = evdev/0/Microsoft X-Box 360 pad +Buttons/A = Button 1 +Buttons/B = Button 0 +Buttons/Start = Button 7 +Buttons/X = Button 2 +Buttons/Y = Button 3 +Buttons/Z = Button 5 +Buttons/Hotkey = Button 6 +C-Stick/Dead Zone = 25.000000000000000 +C-Stick/Down = Axis 4+ +C-Stick/Left = Axis 3- +C-Stick/Modifier = Control_L +C-Stick/Modifier/Range = 50.000000000000000 +C-Stick/Right = Axis 3+ +C-Stick/Up = Axis 4- +D-Pad/Down = Axis 7+ +D-Pad/Left = Axis 6- +D-Pad/Right = Axis 6+ +D-Pad/Up = Axis 7- +Main Stick/Dead Zone = 25.000000000000000 +Main Stick/Down = Axis 1+ +Main Stick/Left = Axis 0- +Main Stick/Modifier = Shift_L +Main Stick/Modifier/Range = 50.000000000000000 +Main Stick/Right = Axis 0+ +Main Stick/Up = Axis 1- +Triggers/L = Axis 2+ +Triggers/R = Axis 5+ +Triforce/Coin = Button 8 +Triforce/Service = Button 4 diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3399/GamecubeControllerProfiles/GCPadNew.ini.south b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3399/GamecubeControllerProfiles/GCPadNew.ini.south new file mode 100755 index 0000000000..8cd2c76826 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3399/GamecubeControllerProfiles/GCPadNew.ini.south @@ -0,0 +1,31 @@ +[GCPad1] +Device = evdev/0/Microsoft X-Box 360 pad +Buttons/A = Button 0 +Buttons/B = Button 3 +Buttons/Start = Button 7 +Buttons/X = Button 1 +Buttons/Y = Button 2 +Buttons/Z = Button 5 +Buttons/Hotkey = Button 6 +C-Stick/Dead Zone = 25.000000000000000 +C-Stick/Down = Axis 4+ +C-Stick/Left = Axis 3- +C-Stick/Modifier = Control_L +C-Stick/Modifier/Range = 50.000000000000000 +C-Stick/Right = Axis 3+ +C-Stick/Up = Axis 4- +D-Pad/Down = Axis 7+ +D-Pad/Left = Axis 6- +D-Pad/Right = Axis 6+ +D-Pad/Up = Axis 7- +Main Stick/Dead Zone = 25.000000000000000 +Main Stick/Down = Axis 1+ +Main Stick/Left = Axis 0- +Main Stick/Modifier = Shift_L +Main Stick/Modifier/Range = 50.000000000000000 +Main Stick/Right = Axis 0+ +Main Stick/Up = Axis 1- +Triggers/L = Axis 2+ +Triggers/R = Axis 5+ +Triforce/Coin = Button 8 +Triforce/Service = Button 4 diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3399/Hotkeys.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3399/Hotkeys.ini new file mode 100644 index 0000000000..8b2e2b8b4f --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3399/Hotkeys.ini @@ -0,0 +1,10 @@ +[Hotkeys] +Device = evdev/0/Microsoft X-Box 360 pad +Graphics Toggles/Toggle Aspect Ratio = @(SELECT+EAST) +General/Take Screenshot = @(SELECT+SOUTH) +Save State/Save to Selected Slot = @(SELECT+TR) +Load State/Load State Slot 1 = @(SELECT+TL) +Other State Hotkeys/Increase Selected State Slot = @(SELECT+`Axis 7-`) +Other State Hotkeys/Decrease Selected State Slot = @(SELECT+`Axis 7+`) +Emulation Speed/Increase Emulation Speed = @(SELECT+`Full Axis 5+`) +Emulation Speed/Decrease Emulation Speed = @(SELECT+`Full Axis 2+`) diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3399/WiiControllerProfiles/classic.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3399/WiiControllerProfiles/classic.ini new file mode 100755 index 0000000000..3c92a42bf0 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3399/WiiControllerProfiles/classic.ini @@ -0,0 +1,27 @@ +[Wiimote1] +Device = evdev/0/Microsoft X-Box 360 pad +Extension = Classic +Source = 1 +Classic/Buttons/A = Button 1 +Classic/Buttons/B = Button 0 +Classic/Buttons/X = Button 2 +Classic/Buttons/Y = Button 3 +Classic/Buttons/ZL = Axis 2+ +Classic/Buttons/ZR = Axis 5+ +Classic/Buttons/- = Button 6 +Classic/Buttons/+ = Button 7 +Classic/Buttons/Home = Button 8 +Classic/Left Stick/Up = Axis 1- +Classic/Left Stick/Down = Axis 1+ +Classic/Left Stick/Left = Axis 0- +Classic/Left Stick/Right = Axis 0+ +Classic/Right Stick/Up = Axis 4- +Classic/Right Stick/Down = Axis 4+ +Classic/Right Stick/Left = Axis 3- +Classic/Right Stick/Right = Axis 3+ +Classic/Triggers/L = Button 4 +Classic/Triggers/R = Button 5 +Classic/D-Pad/Up = Axis 7- +Classic/D-Pad/Down = Axis 7+ +Classic/D-Pad/Left = Axis 6- +Classic/D-Pad/Right = Axis 6+ diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3399/WiiControllerProfiles/hremote.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3399/WiiControllerProfiles/hremote.ini new file mode 100755 index 0000000000..5482c9e295 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3399/WiiControllerProfiles/hremote.ini @@ -0,0 +1,20 @@ +[Wiimote1] +Device = evdev/0/Microsoft X-Box 360 pad +Buttons/A = Button 3 +Buttons/B = Button 2 +Buttons/1 = Button 0 +Buttons/2 = Button 1 +Buttons/- = Button 6 +Buttons/+ = Button 7 +Buttons/Home = Button 8 +Shake/X = Button 4 +Shake/Y = Button 4 +Shake/Z = Button 4 +D-Pad/Up = Axis 6- +D-Pad/Down = Axis 6+ +D-Pad/Left = Axis 7+ +D-Pad/Right = Axis 7- +IR/Up = `Axis 4-` +IR/Down = `Axis 4+` +IR/Left = `Axis 3-` +IR/Right = `Axis 3+` diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3399/WiiControllerProfiles/nunchuck.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3399/WiiControllerProfiles/nunchuck.ini new file mode 100755 index 0000000000..8850d84ce8 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3399/WiiControllerProfiles/nunchuck.ini @@ -0,0 +1,30 @@ +[Wiimote1] +Device = evdev/0/Microsoft X-Box 360 pad +Extension = Nunchuk +Buttons/A = Button 1 +Buttons/B = Button 0 +Buttons/1 = Button 3 +Buttons/2 = Button 2 +Buttons/- = Button 6 +Buttons/+ = Button 7 +D-Pad/Up = Axis 7- +D-Pad/Down = Axis 7+ +D-Pad/Left = Axis 6- +D-Pad/Right = Axis 6+ +Buttons/Home = Button 8 +Shake/X = Button 4 +Shake/Y = Button 4 +Shake/Z = Button 4 +Nunchuk/Buttons/C = Button 5 +Nunchuk/Buttons/Z = Axis 5+ +Nunchuk/Stick/Up = Axis 1- +Nunchuk/Stick/Down = Axis 1+ +Nunchuk/Stick/Left = Axis 0- +Nunchuk/Stick/Right = Axis 0+ +Nunchuk/Shake/X = Axis 2+ +Nunchuk/Shake/Y = Axis 2+ +Nunchuk/Shake/Z = Axis 2+ +IR/Up = `Axis 4-` +IR/Down = `Axis 4+` +IR/Left = `Axis 3-` +IR/Right = `Axis 3+` diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3399/WiiControllerProfiles/vremote.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3399/WiiControllerProfiles/vremote.ini new file mode 100755 index 0000000000..8c0691d587 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3399/WiiControllerProfiles/vremote.ini @@ -0,0 +1,20 @@ +[Wiimote1] +Device = evdev/0/Microsoft X-Box 360 pad +Buttons/A = Button 1 +Buttons/B = Button 0 +Buttons/1 = Button 3 +Buttons/2 = Button 2 +Buttons/- = Button 6 +Buttons/+ = Button 7 +Buttons/Home = Button 8 +Shake/X = Button 4 +Shake/Y = Button 4 +Shake/Z = Button 4 +D-Pad/Up = Axis 7- +D-Pad/Down = Axis 7+ +D-Pad/Left = Axis 6- +D-Pad/Right = Axis 6+ +IR/Up = `Axis 4-` +IR/Down = `Axis 4+` +IR/Left = `Axis 3-` +IR/Right = `Axis 3+` diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3566/Dolphin.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3566/Dolphin.ini new file mode 100755 index 0000000000..887e02bd7c --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3566/Dolphin.ini @@ -0,0 +1,153 @@ +[General] +LastFilename = +ShowLag = False +ShowFrameCount = False +ISOPath0 = /storage/roms/gamecube +ISOPath1 = /storage/roms/wii +ISOPaths = 2 +RecursiveISOPaths = False +NANDRootPath = +WirelessMac = +[Interface] +ConfirmStop = True +UsePanicHandlers = True +OnScreenDisplayMessages = True +HideCursor = False +AutoHideCursor = False +MainWindowPosX = 403 +MainWindowPosY = 148 +MainWindowWidth = 800 +MainWindowHeight = 600 +Language = 0 +ShowToolbar = True +ShowStatusbar = True +ShowLogWindow = False +ShowLogConfigWindow = False +ExtendedFPSInfo = False +ThemeName40 = Clean Blue +PauseOnFocusLost = False +[Display] +FullscreenResolution = Auto +Fullscreen = True +RenderToMain = False +RenderWindowXPos = -1 +RenderWindowYPos = -1 +RenderWindowWidth = 640 +RenderWindowHeight = 480 +RenderWindowAutoSize = False +KeepWindowOnTop = False +ProgressiveScan = False +PAL60 = True +DisableScreenSaver = True +ForceNTSCJ = False +[GameList] +ListDrives = False +ListWad = True +ListElfDol = True +ListWii = True +ListGC = True +ListJap = True +ListPal = True +ListUsa = True +ListAustralia = True +ListFrance = True +ListGermany = True +ListItaly = True +ListKorea = True +ListNetherlands = True +ListRussia = True +ListSpain = True +ListTaiwan = True +ListWorld = True +ListUnknown = True +ListSort = 3 +ListSortSecondary = 0 +ColorCompressed = True +ColumnPlatform = True +ColumnBanner = True +ColumnNotes = True +ColumnFileName = False +ColumnID = False +ColumnRegion = True +ColumnSize = True +ColumnState = True +[Core] +SkipIPL = True +HLE_BS2 = False +TimingVariance = 40 +CPUCore = 4 +Fastmem = True +CPUThread = True +DSPHLE = True +SkipIdle = True +SyncOnSkipIdle = True +SyncGPU = False +SyncGpuMaxDistance = 200000 +SyncGpuMinDistance = -200000 +SyncGpuOverclock = 1.00000000 +FPRF = False +AccurateNaNs = False +DefaultISO = +DVDRoot = +Apploader = +EnableCheats = True +SelectedLanguage = 0 +OverrideGCLang = False +DPL2Decoder = False +Latency = 2 +MemcardAPath = +MemcardBPath = +AgpCartAPath = +AgpCartBPath = +GCIFolderAPath = /storage/roms/bios/GC/USA +SlotA = 1 +SlotB = 255 +SerialPort1 = 255 +BBA_MAC = +SIDevice0 = 6 +AdapterRumble0 = True +SimulateKonga0 = False +SIDevice1 = 6 +AdapterRumble1 = True +SimulateKonga1 = False +SIDevice2 = 0 +AdapterRumble2 = True +SimulateKonga2 = False +SIDevice3 = 0 +AdapterRumble3 = True +SimulateKonga3 = False +WiiSDCard = False +WiiKeyboard = False +WiimoteContinuousScanning = False +WiimoteEnableSpeaker = False +RunCompareServer = False +RunCompareClient = False +EmulationSpeed = 1.00000000 +FrameSkip = 0x00000003 +Overclock = 4.00000000 +OverclockEnable = False +GFXBackend = +GPUDeterminismMode = auto +PerfMapDir = +AutoDiscChange = True +[Movie] +PauseMovie = False +Author = +DumpFrames = False +DumpFramesSilent = False +ShowInputDisplay = False +[DSP] +EnableJIT = True +DumpAudio = False +DumpUCode = False +Backend = Pulse +Volume = 100 +CaptureLog = False +[Input] +BackgroundInput = False +[FifoPlayer] +LoopReplay = True +[Analytics] +ID = 5082f0c30a7e422b1220107f69d6c108 +Enabled = False +PermissionAsked = True diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3566/GFX.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3566/GFX.ini new file mode 100755 index 0000000000..6cd269c601 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3566/GFX.ini @@ -0,0 +1,61 @@ +[Hardware] +VSync = False +Adapter = 0 +[Settings] +AspectRatio = 2 +InternalResolution = 1 +Crop = False +wideScreenHack = False +UseXFB = False +UseRealXFB = False +SafeTextureCacheColorSamples = 128 +ShowFPS = False +LogRenderTimeToFile = False +OverlayStats = False +OverlayProjStats = False +DumpTextures = False +HiresTextures = False +ConvertHiresTextures = False +CacheHiresTextures = False +DumpEFBTarget = False +FreeLook = False +UseFFV1 = False +EnablePixelLighting = False +FastDepthCalc = True +MSAA = 1 +SSAA = False +EFBScale = 2 +TexFmtOverlayEnable = False +TexFmtOverlayCenter = False +Wireframe = False +DisableFog = False +EnableShaderDebugging = False +BorderlessFullscreen = False +SWZComploc = True +SWZFreeze = True +SWDumpObjects = False +SWDumpTevStages = False +SWDumpTevTexFetches = False +SWDrawStart = 0 +SWDrawEnd = 100000 +ShaderCompilationMode = 0 +WaitForShadersBeforeStarting = True +BackendMultithreading = True +EnableGPUTextureDecoding = True +[Enhancements] +ForceFiltering = False +MaxAnisotropy = 0 +PostProcessingShader = +[Stereoscopy] +StereoMode = 0 +StereoDepth = 20 +StereoConvergencePercentage = 100 +StereoSwapEyes = False +[Hacks] +EFBAccessEnable = False +BBoxEnable = False +ForceProgressive = True +EFBToTextureEnable = True +EFBScaledCopy = False +EFBEmulateFormatChanges = False +SkipDuplicateXFBs = True diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3566/GamecubeControllerProfiles/GCPadNew.ini.east b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3566/GamecubeControllerProfiles/GCPadNew.ini.east new file mode 100755 index 0000000000..d9d0185cb6 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3566/GamecubeControllerProfiles/GCPadNew.ini.east @@ -0,0 +1,29 @@ +[GCPad1] +Device = evdev/0/Microsoft X-Box 360 pad +Buttons/A = Button 1 +Buttons/B = Button 0 +Buttons/Start = Button 7 +Buttons/X = Button 2 +Buttons/Y = Button 3 +Buttons/Z = Button 5 +Buttons/Hotkey = Button 6 +C-Stick/Dead Zone = 25.000000000000000 +C-Stick/Down = Axis 4+ +C-Stick/Left = Axis 3- +C-Stick/Modifier = Control_L +C-Stick/Modifier/Range = 50.000000000000000 +C-Stick/Right = Axis 3+ +C-Stick/Up = Axis 4- +D-Pad/Down = Axis 7+ +D-Pad/Left = Axis 6- +D-Pad/Right = Axis 6+ +D-Pad/Up = Axis 7- +Main Stick/Dead Zone = 25.000000000000000 +Main Stick/Down = Axis 1+ +Main Stick/Left = Axis 0- +Main Stick/Modifier = Shift_L +Main Stick/Modifier/Range = 50.000000000000000 +Main Stick/Right = Axis 0+ +Main Stick/Up = Axis 1- +Triggers/L = Axis 2+ +Triggers/R = Axis 5+ diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3566/GamecubeControllerProfiles/GCPadNew.ini.south b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3566/GamecubeControllerProfiles/GCPadNew.ini.south new file mode 100755 index 0000000000..d34241032c --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3566/GamecubeControllerProfiles/GCPadNew.ini.south @@ -0,0 +1,29 @@ +[GCPad1] +Device = evdev/0/Microsoft X-Box 360 pad +Buttons/A = Button 0 +Buttons/B = Button 3 +Buttons/Start = Button 7 +Buttons/X = Button 1 +Buttons/Y = Button 2 +Buttons/Z = Button 5 +Buttons/Hotkey = Button 6 +C-Stick/Dead Zone = 25.000000000000000 +C-Stick/Down = Axis 4+ +C-Stick/Left = Axis 3- +C-Stick/Modifier = Control_L +C-Stick/Modifier/Range = 50.000000000000000 +C-Stick/Right = Axis 3+ +C-Stick/Up = Axis 4- +D-Pad/Down = Axis 7+ +D-Pad/Left = Axis 6- +D-Pad/Right = Axis 6+ +D-Pad/Up = Axis 7- +Main Stick/Dead Zone = 25.000000000000000 +Main Stick/Down = Axis 1+ +Main Stick/Left = Axis 0- +Main Stick/Modifier = Shift_L +Main Stick/Modifier/Range = 50.000000000000000 +Main Stick/Right = Axis 0+ +Main Stick/Up = Axis 1- +Triggers/L = Axis 2+ +Triggers/R = Axis 5+ diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3566/WiiControllerProfiles/classic.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3566/WiiControllerProfiles/classic.ini new file mode 100755 index 0000000000..3c92a42bf0 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3566/WiiControllerProfiles/classic.ini @@ -0,0 +1,27 @@ +[Wiimote1] +Device = evdev/0/Microsoft X-Box 360 pad +Extension = Classic +Source = 1 +Classic/Buttons/A = Button 1 +Classic/Buttons/B = Button 0 +Classic/Buttons/X = Button 2 +Classic/Buttons/Y = Button 3 +Classic/Buttons/ZL = Axis 2+ +Classic/Buttons/ZR = Axis 5+ +Classic/Buttons/- = Button 6 +Classic/Buttons/+ = Button 7 +Classic/Buttons/Home = Button 8 +Classic/Left Stick/Up = Axis 1- +Classic/Left Stick/Down = Axis 1+ +Classic/Left Stick/Left = Axis 0- +Classic/Left Stick/Right = Axis 0+ +Classic/Right Stick/Up = Axis 4- +Classic/Right Stick/Down = Axis 4+ +Classic/Right Stick/Left = Axis 3- +Classic/Right Stick/Right = Axis 3+ +Classic/Triggers/L = Button 4 +Classic/Triggers/R = Button 5 +Classic/D-Pad/Up = Axis 7- +Classic/D-Pad/Down = Axis 7+ +Classic/D-Pad/Left = Axis 6- +Classic/D-Pad/Right = Axis 6+ diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3566/WiiControllerProfiles/hremote.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3566/WiiControllerProfiles/hremote.ini new file mode 100755 index 0000000000..9c675c1d12 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3566/WiiControllerProfiles/hremote.ini @@ -0,0 +1,20 @@ +[Wiimote1] +Device = evdev/0/Microsoft X-Box 360 pad +Buttons/A = Button 3 +Buttons/B = Button 2 +Buttons/1 = Button 0 +Buttons/2 = Button 1 +Buttons/- = Button 6 +Buttons/+ = Button 7 +Buttons/Home = Button 8 +Shake/X = Button 4 +Shake/Y = Button 4 +Shake/Z = Button 4 +D-Pad/Up = `Axis 6-` | `Axis 0-` +D-Pad/Down = `Axis 6+` | `Axis 0+` +D-Pad/Left = `Axis 7+` | `Axis 1+` +D-Pad/Right = `Axis 7-` | `Axis 1-` +IR/Up = `Axis 4-` +IR/Down = `Axis 4+` +IR/Left = `Axis 3-` +IR/Right = `Axis 3+` diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3566/WiiControllerProfiles/nunchuck.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3566/WiiControllerProfiles/nunchuck.ini new file mode 100755 index 0000000000..8850d84ce8 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3566/WiiControllerProfiles/nunchuck.ini @@ -0,0 +1,30 @@ +[Wiimote1] +Device = evdev/0/Microsoft X-Box 360 pad +Extension = Nunchuk +Buttons/A = Button 1 +Buttons/B = Button 0 +Buttons/1 = Button 3 +Buttons/2 = Button 2 +Buttons/- = Button 6 +Buttons/+ = Button 7 +D-Pad/Up = Axis 7- +D-Pad/Down = Axis 7+ +D-Pad/Left = Axis 6- +D-Pad/Right = Axis 6+ +Buttons/Home = Button 8 +Shake/X = Button 4 +Shake/Y = Button 4 +Shake/Z = Button 4 +Nunchuk/Buttons/C = Button 5 +Nunchuk/Buttons/Z = Axis 5+ +Nunchuk/Stick/Up = Axis 1- +Nunchuk/Stick/Down = Axis 1+ +Nunchuk/Stick/Left = Axis 0- +Nunchuk/Stick/Right = Axis 0+ +Nunchuk/Shake/X = Axis 2+ +Nunchuk/Shake/Y = Axis 2+ +Nunchuk/Shake/Z = Axis 2+ +IR/Up = `Axis 4-` +IR/Down = `Axis 4+` +IR/Left = `Axis 3-` +IR/Right = `Axis 3+` diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3566/WiiControllerProfiles/vremote.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3566/WiiControllerProfiles/vremote.ini new file mode 100755 index 0000000000..90ef876567 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3566/WiiControllerProfiles/vremote.ini @@ -0,0 +1,20 @@ +[Wiimote1] +Device = evdev/0/Microsoft X-Box 360 pad +Buttons/A = Button 1 +Buttons/B = Button 0 +Buttons/1 = Button 3 +Buttons/2 = Button 2 +Buttons/- = Button 6 +Buttons/+ = Button 7 +Buttons/Home = Button 8 +Shake/X = Button 4 +Shake/Y = Button 4 +Shake/Z = Button 4 +D-Pad/Up = `Axis 7-` | `Axis 1-` +D-Pad/Down = `Axis 7+` | `Axis 1+` +D-Pad/Left = `Axis 6-` | `Axis 0-` +D-Pad/Right = `Axis 6+` | `Axis 0+` +IR/Up = `Axis 4-` +IR/Down = `Axis 4+` +IR/Left = `Axis 3-` +IR/Right = `Axis 3+` diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3588/Dolphin.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3588/Dolphin.ini new file mode 100644 index 0000000000..8c81872bc9 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3588/Dolphin.ini @@ -0,0 +1,154 @@ +[General] +LastFilename = +ShowLag = False +ShowFrameCount = False +ISOPath0 = /storage/roms/gamecube +ISOPath1 = /storage/roms/wii +ISOPaths = 2 +RecursiveISOPaths = False +NANDRootPath = +WirelessMac = +[Interface] +ConfirmStop = True +UsePanicHandlers = True +OnScreenDisplayMessages = True +HideCursor = False +AutoHideCursor = False +MainWindowPosX = 403 +MainWindowPosY = 148 +MainWindowWidth = 800 +MainWindowHeight = 600 +Language = 0 +ShowToolbar = True +ShowStatusbar = True +ShowLogWindow = False +ShowLogConfigWindow = False +ExtendedFPSInfo = False +ThemeName40 = Clean Blue +PauseOnFocusLost = False +[Display] +FullscreenResolution = Auto +Fullscreen = True +RenderToMain = False +RenderWindowXPos = -1 +RenderWindowYPos = -1 +RenderWindowWidth = 640 +RenderWindowHeight = 480 +RenderWindowAutoSize = False +KeepWindowOnTop = False +ProgressiveScan = False +PAL60 = True +DisableScreenSaver = True +ForceNTSCJ = False +[GameList] +ListDrives = False +ListWad = True +ListElfDol = True +ListWii = True +ListGC = True +ListJap = True +ListPal = True +ListUsa = True +ListAustralia = True +ListFrance = True +ListGermany = True +ListItaly = True +ListKorea = True +ListNetherlands = True +ListRussia = True +ListSpain = True +ListTaiwan = True +ListWorld = True +ListUnknown = True +ListSort = 3 +ListSortSecondary = 0 +ColorCompressed = True +ColumnPlatform = True +ColumnBanner = True +ColumnNotes = True +ColumnFileName = False +ColumnID = False +ColumnRegion = True +ColumnSize = True +ColumnState = True +[Core] +SkipIPL = True +HLE_BS2 = False +TimingVariance = 40 +CPUCore = 4 +Fastmem = True +CPUThread = True +DSPHLE = True +SkipIdle = True +SyncOnSkipIdle = False +SyncGPU = False +SyncGpuMaxDistance = 200000 +SyncGpuMinDistance = -200000 +SyncGpuOverclock = 1.00000000 +FPRF = False +AccurateNaNs = False +DefaultISO = +DVDRoot = +Apploader = +EnableCheats = True +SelectedLanguage = 0 +OverrideGCLang = False +DPL2Decoder = False +Latency = 2 +MemcardAPath = +MemcardBPath = +AgpCartAPath = +AgpCartBPath = +GCIFolderAPath = /storage/roms/bios/GC/USA +SlotA = 1 +SlotB = 255 +SerialPort1 = 255 +BBA_MAC = +SIDevice0 = 6 +AdapterRumble0 = True +SimulateKonga0 = False +SIDevice1 = 6 +AdapterRumble1 = True +SimulateKonga1 = False +SIDevice2 = 0 +AdapterRumble2 = True +SimulateKonga2 = False +SIDevice3 = 0 +AdapterRumble3 = True +SimulateKonga3 = False +WiiSDCard = False +WiiKeyboard = False +WiimoteContinuousScanning = False +WiimoteEnableSpeaker = False +RunCompareServer = False +RunCompareClient = False +EmulationSpeed = 1.00000000 +FrameSkip = 0x00000003 +Overclock = 1.0 +OverclockEnable = False +GFXBackend = OGL +GPUDeterminismMode = auto +PerfMapDir = +AutoDiscChange = True +[Movie] +PauseMovie = False +Author = +DumpFrames = False +DumpFramesSilent = False +ShowInputDisplay = False +[DSP] +EnableJIT = True +DumpAudio = False +DumpUCode = False +Backend = Pulse +Volume = 100 +CaptureLog = False +DSPThread = True +[Input] +BackgroundInput = False +[FifoPlayer] +LoopReplay = True +[Analytics] +ID = 5082f0c30a7e422b1220107f69d6c108 +Enabled = False +PermissionAsked = True diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3588/GFX.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3588/GFX.ini new file mode 100644 index 0000000000..6fcca41798 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3588/GFX.ini @@ -0,0 +1,62 @@ +[Hardware] +VSync = False +Adapter = 0 +[Settings] +PreferGLES = True +AspectRatio = 0 +InternalResolution = 2 +Crop = False +wideScreenHack = False +UseXFB = False +UseRealXFB = False +SafeTextureCacheColorSamples = 128 +ShowFPS = False +LogRenderTimeToFile = False +OverlayStats = False +OverlayProjStats = False +DumpTextures = False +HiresTextures = False +ConvertHiresTextures = False +CacheHiresTextures = False +DumpEFBTarget = False +FreeLook = False +UseFFV1 = False +EnablePixelLighting = False +FastDepthCalc = True +MSAA = 1 +SSAA = False +EFBScale = 2 +TexFmtOverlayEnable = False +TexFmtOverlayCenter = False +Wireframe = False +DisableFog = False +EnableShaderDebugging = False +BorderlessFullscreen = False +SWZComploc = True +SWZFreeze = True +SWDumpObjects = False +SWDumpTevStages = False +SWDumpTevTexFetches = False +SWDrawStart = 0 +SWDrawEnd = 100000 +ShaderCompilationMode = 0 +WaitForShadersBeforeStarting = True +BackendMultithreading = True +EnableGPUTextureDecoding = True +[Enhancements] +ForceTextureFiltering = False +MaxAnisotropy = 0 +PostProcessingShader = +[Stereoscopy] +StereoMode = 0 +StereoDepth = 20 +StereoConvergencePercentage = 100 +StereoSwapEyes = False +[Hacks] +EFBAccessEnable = False +BBoxEnable = False +ForceProgressive = True +EFBToTextureEnable = True +EFBScaledCopy = False +EFBEmulateFormatChanges = False +SkipDuplicateXFBs = True diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3588/GamecubeControllerProfiles/GCPadNew.ini.east b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3588/GamecubeControllerProfiles/GCPadNew.ini.east new file mode 100644 index 0000000000..7cbb844c54 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3588/GamecubeControllerProfiles/GCPadNew.ini.east @@ -0,0 +1,35 @@ +[GCPad1] +Device = evdev/0/Microsoft X-Box 360 pad +Buttons/A = Button 1 +Buttons/B = Button 0 +Buttons/Start = Button 7 +Buttons/X = Button 2 +Buttons/Y = Button 3 +Buttons/Z = Button 5 +Buttons/Hotkey = Button 6 +C-Stick/Dead Zone = 25.000000000000000 +C-Stick/Down = Axis 4+ +C-Stick/Left = Axis 3- +C-Stick/Modifier = Control_L +C-Stick/Modifier/Range = 50.000000000000000 +C-Stick/Right = Axis 3+ +C-Stick/Up = Axis 4- +D-Pad/Down = Axis 7+ +D-Pad/Left = Axis 6- +D-Pad/Right = Axis 6+ +D-Pad/Up = Axis 7- +Main Stick/Dead Zone = 25.000000000000000 +Main Stick/Down = Axis 1+ +Main Stick/Left = Axis 0- +Main Stick/Modifier = Shift_L +Main Stick/Modifier/Range = 50.000000000000000 +Main Stick/Right = Axis 0+ +Main Stick/Up = Axis 1- +Triggers/Dead Zone = 0. +Triggers/Threshold = 90. +Triggers/L = Axis 2+ +Triggers/R = Axis 5+ +Triggers/L-Analog = Axis 2+ +Triggers/R-Analog = Axis 5+ +Triforce/Coin = Button 8 +Triforce/Service = Button 4 diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3588/GamecubeControllerProfiles/GCPadNew.ini.south b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3588/GamecubeControllerProfiles/GCPadNew.ini.south new file mode 100644 index 0000000000..0547f74b72 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3588/GamecubeControllerProfiles/GCPadNew.ini.south @@ -0,0 +1,35 @@ +[GCPad1] +Device = evdev/0/Microsoft X-Box 360 pad +Buttons/A = Button 0 +Buttons/B = Button 3 +Buttons/Start = Button 7 +Buttons/X = Button 1 +Buttons/Y = Button 2 +Buttons/Z = Button 5 +Buttons/Hotkey = Button 6 +C-Stick/Dead Zone = 25.000000000000000 +C-Stick/Down = Axis 4+ +C-Stick/Left = Axis 3- +C-Stick/Modifier = Control_L +C-Stick/Modifier/Range = 50.000000000000000 +C-Stick/Right = Axis 3+ +C-Stick/Up = Axis 4- +D-Pad/Down = Axis 7+ +D-Pad/Left = Axis 6- +D-Pad/Right = Axis 6+ +D-Pad/Up = Axis 7- +Main Stick/Dead Zone = 25.000000000000000 +Main Stick/Down = Axis 1+ +Main Stick/Left = Axis 0- +Main Stick/Modifier = Shift_L +Main Stick/Modifier/Range = 50.000000000000000 +Main Stick/Right = Axis 0+ +Main Stick/Up = Axis 1- +Triggers/Dead Zone = 0. +Triggers/Threshold = 90. +Triggers/L = Axis 2+ +Triggers/R = Axis 5+ +Triggers/L-Analog = Axis 2+ +Triggers/R-Analog = Axis 5+ +Triforce/Coin = Button 8 +Triforce/Service = Button 4 diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3588/WiiControllerProfiles/classic.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3588/WiiControllerProfiles/classic.ini new file mode 100644 index 0000000000..3c92a42bf0 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3588/WiiControllerProfiles/classic.ini @@ -0,0 +1,27 @@ +[Wiimote1] +Device = evdev/0/Microsoft X-Box 360 pad +Extension = Classic +Source = 1 +Classic/Buttons/A = Button 1 +Classic/Buttons/B = Button 0 +Classic/Buttons/X = Button 2 +Classic/Buttons/Y = Button 3 +Classic/Buttons/ZL = Axis 2+ +Classic/Buttons/ZR = Axis 5+ +Classic/Buttons/- = Button 6 +Classic/Buttons/+ = Button 7 +Classic/Buttons/Home = Button 8 +Classic/Left Stick/Up = Axis 1- +Classic/Left Stick/Down = Axis 1+ +Classic/Left Stick/Left = Axis 0- +Classic/Left Stick/Right = Axis 0+ +Classic/Right Stick/Up = Axis 4- +Classic/Right Stick/Down = Axis 4+ +Classic/Right Stick/Left = Axis 3- +Classic/Right Stick/Right = Axis 3+ +Classic/Triggers/L = Button 4 +Classic/Triggers/R = Button 5 +Classic/D-Pad/Up = Axis 7- +Classic/D-Pad/Down = Axis 7+ +Classic/D-Pad/Left = Axis 6- +Classic/D-Pad/Right = Axis 6+ diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3588/WiiControllerProfiles/hremote.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3588/WiiControllerProfiles/hremote.ini new file mode 100644 index 0000000000..9c675c1d12 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3588/WiiControllerProfiles/hremote.ini @@ -0,0 +1,20 @@ +[Wiimote1] +Device = evdev/0/Microsoft X-Box 360 pad +Buttons/A = Button 3 +Buttons/B = Button 2 +Buttons/1 = Button 0 +Buttons/2 = Button 1 +Buttons/- = Button 6 +Buttons/+ = Button 7 +Buttons/Home = Button 8 +Shake/X = Button 4 +Shake/Y = Button 4 +Shake/Z = Button 4 +D-Pad/Up = `Axis 6-` | `Axis 0-` +D-Pad/Down = `Axis 6+` | `Axis 0+` +D-Pad/Left = `Axis 7+` | `Axis 1+` +D-Pad/Right = `Axis 7-` | `Axis 1-` +IR/Up = `Axis 4-` +IR/Down = `Axis 4+` +IR/Left = `Axis 3-` +IR/Right = `Axis 3+` diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3588/WiiControllerProfiles/nunchuck.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3588/WiiControllerProfiles/nunchuck.ini new file mode 100644 index 0000000000..8850d84ce8 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3588/WiiControllerProfiles/nunchuck.ini @@ -0,0 +1,30 @@ +[Wiimote1] +Device = evdev/0/Microsoft X-Box 360 pad +Extension = Nunchuk +Buttons/A = Button 1 +Buttons/B = Button 0 +Buttons/1 = Button 3 +Buttons/2 = Button 2 +Buttons/- = Button 6 +Buttons/+ = Button 7 +D-Pad/Up = Axis 7- +D-Pad/Down = Axis 7+ +D-Pad/Left = Axis 6- +D-Pad/Right = Axis 6+ +Buttons/Home = Button 8 +Shake/X = Button 4 +Shake/Y = Button 4 +Shake/Z = Button 4 +Nunchuk/Buttons/C = Button 5 +Nunchuk/Buttons/Z = Axis 5+ +Nunchuk/Stick/Up = Axis 1- +Nunchuk/Stick/Down = Axis 1+ +Nunchuk/Stick/Left = Axis 0- +Nunchuk/Stick/Right = Axis 0+ +Nunchuk/Shake/X = Axis 2+ +Nunchuk/Shake/Y = Axis 2+ +Nunchuk/Shake/Z = Axis 2+ +IR/Up = `Axis 4-` +IR/Down = `Axis 4+` +IR/Left = `Axis 3-` +IR/Right = `Axis 3+` diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3588/WiiControllerProfiles/vremote.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3588/WiiControllerProfiles/vremote.ini new file mode 100644 index 0000000000..90ef876567 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/RK3588/WiiControllerProfiles/vremote.ini @@ -0,0 +1,20 @@ +[Wiimote1] +Device = evdev/0/Microsoft X-Box 360 pad +Buttons/A = Button 1 +Buttons/B = Button 0 +Buttons/1 = Button 3 +Buttons/2 = Button 2 +Buttons/- = Button 6 +Buttons/+ = Button 7 +Buttons/Home = Button 8 +Shake/X = Button 4 +Shake/Y = Button 4 +Shake/Z = Button 4 +D-Pad/Up = `Axis 7-` | `Axis 1-` +D-Pad/Down = `Axis 7+` | `Axis 1+` +D-Pad/Left = `Axis 6-` | `Axis 0-` +D-Pad/Right = `Axis 6+` | `Axis 0+` +IR/Up = `Axis 4-` +IR/Down = `Axis 4+` +IR/Left = `Axis 3-` +IR/Right = `Axis 3+` diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/S922X/Dolphin.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/S922X/Dolphin.ini new file mode 100644 index 0000000000..f0d5885d3d --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/S922X/Dolphin.ini @@ -0,0 +1,152 @@ +[General] +LastFilename = +ShowLag = False +ShowFrameCount = False +ISOPaths = 1 +RecursiveISOPaths = False +NANDRootPath = +WirelessMac = +[Interface] +ConfirmStop = True +UsePanicHandlers = True +OnScreenDisplayMessages = True +HideCursor = False +AutoHideCursor = False +MainWindowPosX = 403 +MainWindowPosY = 148 +MainWindowWidth = 800 +MainWindowHeight = 600 +Language = 0 +ShowToolbar = True +ShowStatusbar = True +ShowLogWindow = False +ShowLogConfigWindow = False +ExtendedFPSInfo = False +ThemeName40 = Clean Blue +PauseOnFocusLost = False +[Display] +FullscreenResolution = Auto +Fullscreen = True +RenderToMain = False +RenderWindowXPos = -1 +RenderWindowYPos = -1 +RenderWindowWidth = 640 +RenderWindowHeight = 480 +RenderWindowAutoSize = False +KeepWindowOnTop = False +ProgressiveScan = False +PAL60 = True +DisableScreenSaver = True +ForceNTSCJ = False +[GameList] +ListDrives = False +ListWad = True +ListElfDol = True +ListWii = True +ListGC = True +ListJap = True +ListPal = True +ListUsa = True +ListAustralia = True +ListFrance = True +ListGermany = True +ListItaly = True +ListKorea = True +ListNetherlands = True +ListRussia = True +ListSpain = True +ListTaiwan = True +ListWorld = True +ListUnknown = True +ListSort = 3 +ListSortSecondary = 0 +ColorCompressed = True +ColumnPlatform = True +ColumnBanner = True +ColumnNotes = True +ColumnFileName = False +ColumnID = False +ColumnRegion = True +ColumnSize = True +ColumnState = True +[Core] +SkipIPL = True +HLE_BS2 = False +TimingVariance = 40 +CPUCore = 4 +Fastmem = True +CPUThread = True +DSPHLE = True +SkipIdle = True +SyncOnSkipIdle = False +SyncGPU = False +SyncGpuMaxDistance = 200000 +SyncGpuMinDistance = -200000 +SyncGpuOverclock = 1.00000000 +FPRF = False +AccurateNaNs = False +DefaultISO = +DVDRoot = +Apploader = +EnableCheats = True +SelectedLanguage = 0 +OverrideGCLang = False +DPL2Decoder = False +Latency = 2 +MemcardAPath = +MemcardBPath = +AgpCartAPath = +AgpCartBPath = +GCIFolderAPath = /storage/roms/bios/GC/USA +SlotA = 1 +SlotB = 255 +SerialPort1 = 255 +BBA_MAC = +SIDevice0 = 6 +AdapterRumble0 = True +SimulateKonga0 = False +SIDevice1 = 6 +AdapterRumble1 = True +SimulateKonga1 = False +SIDevice2 = 0 +AdapterRumble2 = True +SimulateKonga2 = False +SIDevice3 = 0 +AdapterRumble3 = True +SimulateKonga3 = False +WiiSDCard = False +WiiKeyboard = False +WiimoteContinuousScanning = False +WiimoteEnableSpeaker = False +RunCompareServer = False +RunCompareClient = False +EmulationSpeed = 1.00000000 +FrameSkip = 0x00000003 +Overclock = 1.0 +OverclockEnable = False +GFXBackend = Vulkan +GPUDeterminismMode = auto +PerfMapDir = +AutoDiscChange = True +[Movie] +PauseMovie = False +Author = +DumpFrames = False +DumpFramesSilent = False +ShowInputDisplay = False +[DSP] +EnableJIT = True +DumpAudio = False +DumpUCode = False +Backend = Pulse +Volume = 100 +CaptureLog = False +DSPThread = True +[Input] +BackgroundInput = False +[FifoPlayer] +LoopReplay = True +[Analytics] +ID = 5082f0c30a7e422b1220107f69d6c108 +Enabled = False +PermissionAsked = True diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/S922X/GFX.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/S922X/GFX.ini new file mode 100644 index 0000000000..4076f48287 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/S922X/GFX.ini @@ -0,0 +1,61 @@ +[Hardware] +VSync = False +Adapter = 0 +[Settings] +AspectRatio = 0 +InternalResolution = 2 +Crop = False +wideScreenHack = False +UseXFB = False +UseRealXFB = False +SafeTextureCacheColorSamples = 128 +ShowFPS = False +LogRenderTimeToFile = False +OverlayStats = False +OverlayProjStats = False +DumpTextures = False +HiresTextures = False +ConvertHiresTextures = False +CacheHiresTextures = False +DumpEFBTarget = False +FreeLook = False +UseFFV1 = False +EnablePixelLighting = False +FastDepthCalc = True +MSAA = 1 +SSAA = False +EFBScale = 2 +TexFmtOverlayEnable = False +TexFmtOverlayCenter = False +Wireframe = False +DisableFog = False +EnableShaderDebugging = False +BorderlessFullscreen = False +SWZComploc = True +SWZFreeze = True +SWDumpObjects = False +SWDumpTevStages = False +SWDumpTevTexFetches = False +SWDrawStart = 0 +SWDrawEnd = 100000 +ShaderCompilationMode = 0 +WaitForShadersBeforeStarting = True +BackendMultithreading = True +EnableGPUTextureDecoding = True +[Enhancements] +ForceTextureFiltering = False +MaxAnisotropy = 0 +PostProcessingShader = +[Stereoscopy] +StereoMode = 0 +StereoDepth = 20 +StereoConvergencePercentage = 100 +StereoSwapEyes = False +[Hacks] +EFBAccessEnable = False +BBoxEnable = False +ForceProgressive = True +EFBToTextureEnable = True +EFBScaledCopy = False +EFBEmulateFormatChanges = False +SkipDuplicateXFBs = True diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/S922X/GamecubeControllerProfiles/GCPadNew.ini.east b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/S922X/GamecubeControllerProfiles/GCPadNew.ini.east new file mode 100644 index 0000000000..7c37ae856e --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/S922X/GamecubeControllerProfiles/GCPadNew.ini.east @@ -0,0 +1,29 @@ +[GCPad1] +Device = evdev/0/Microsoft X-Box 360 pad +Buttons/A = Button 1 +Buttons/B = Button 0 +Buttons/Start = Button 7 +Buttons/X = Button 2 +Buttons/Y = Button 3 +Buttons/Z = Axis 5+ +Buttons/Hotkey = Button 6 +C-Stick/Dead Zone = 25.000000000000000 +C-Stick/Down = Axis 4+ +C-Stick/Left = Axis 3- +C-Stick/Modifier = Control_L +C-Stick/Modifier/Range = 50.000000000000000 +C-Stick/Right = Axis 3+ +C-Stick/Up = Axis 4- +D-Pad/Down = Axis 7+ +D-Pad/Left = Axis 6- +D-Pad/Right = Axis 6+ +D-Pad/Up = Axis 7- +Main Stick/Dead Zone = 25.000000000000000 +Main Stick/Down = Axis 1+ +Main Stick/Left = Axis 0- +Main Stick/Modifier = Shift_L +Main Stick/Modifier/Range = 50.000000000000000 +Main Stick/Right = Axis 0+ +Main Stick/Up = Axis 1- +Triggers/L = Button 4 +Triggers/R = Button 5 diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/S922X/GamecubeControllerProfiles/GCPadNew.ini.south b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/S922X/GamecubeControllerProfiles/GCPadNew.ini.south new file mode 100644 index 0000000000..6f3ae8606b --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/S922X/GamecubeControllerProfiles/GCPadNew.ini.south @@ -0,0 +1,29 @@ +[GCPad1] +Device = evdev/0/Microsoft X-Box 360 pad +Buttons/A = Button 0 +Buttons/B = Button 3 +Buttons/Start = Button 7 +Buttons/X = Button 1 +Buttons/Y = Button 2 +Buttons/Z = Axis 5+ +Buttons/Hotkey = Button 6 +C-Stick/Dead Zone = 25.000000000000000 +C-Stick/Down = Axis 4+ +C-Stick/Left = Axis 3- +C-Stick/Modifier = Control_L +C-Stick/Modifier/Range = 50.000000000000000 +C-Stick/Right = Axis 3+ +C-Stick/Up = Axis 4- +D-Pad/Down = Axis 7+ +D-Pad/Left = Axis 6- +D-Pad/Right = Axis 6+ +D-Pad/Up = Axis 7- +Main Stick/Dead Zone = 25.000000000000000 +Main Stick/Down = Axis 1+ +Main Stick/Left = Axis 0- +Main Stick/Modifier = Shift_L +Main Stick/Modifier/Range = 50.000000000000000 +Main Stick/Right = Axis 0+ +Main Stick/Up = Axis 1- +Triggers/L = Button 4 +Triggers/R = Button 5 diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/S922X/WiiControllerProfiles/classic.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/S922X/WiiControllerProfiles/classic.ini new file mode 100644 index 0000000000..3c92a42bf0 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/S922X/WiiControllerProfiles/classic.ini @@ -0,0 +1,27 @@ +[Wiimote1] +Device = evdev/0/Microsoft X-Box 360 pad +Extension = Classic +Source = 1 +Classic/Buttons/A = Button 1 +Classic/Buttons/B = Button 0 +Classic/Buttons/X = Button 2 +Classic/Buttons/Y = Button 3 +Classic/Buttons/ZL = Axis 2+ +Classic/Buttons/ZR = Axis 5+ +Classic/Buttons/- = Button 6 +Classic/Buttons/+ = Button 7 +Classic/Buttons/Home = Button 8 +Classic/Left Stick/Up = Axis 1- +Classic/Left Stick/Down = Axis 1+ +Classic/Left Stick/Left = Axis 0- +Classic/Left Stick/Right = Axis 0+ +Classic/Right Stick/Up = Axis 4- +Classic/Right Stick/Down = Axis 4+ +Classic/Right Stick/Left = Axis 3- +Classic/Right Stick/Right = Axis 3+ +Classic/Triggers/L = Button 4 +Classic/Triggers/R = Button 5 +Classic/D-Pad/Up = Axis 7- +Classic/D-Pad/Down = Axis 7+ +Classic/D-Pad/Left = Axis 6- +Classic/D-Pad/Right = Axis 6+ diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/S922X/WiiControllerProfiles/hremote.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/S922X/WiiControllerProfiles/hremote.ini new file mode 100644 index 0000000000..9c675c1d12 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/S922X/WiiControllerProfiles/hremote.ini @@ -0,0 +1,20 @@ +[Wiimote1] +Device = evdev/0/Microsoft X-Box 360 pad +Buttons/A = Button 3 +Buttons/B = Button 2 +Buttons/1 = Button 0 +Buttons/2 = Button 1 +Buttons/- = Button 6 +Buttons/+ = Button 7 +Buttons/Home = Button 8 +Shake/X = Button 4 +Shake/Y = Button 4 +Shake/Z = Button 4 +D-Pad/Up = `Axis 6-` | `Axis 0-` +D-Pad/Down = `Axis 6+` | `Axis 0+` +D-Pad/Left = `Axis 7+` | `Axis 1+` +D-Pad/Right = `Axis 7-` | `Axis 1-` +IR/Up = `Axis 4-` +IR/Down = `Axis 4+` +IR/Left = `Axis 3-` +IR/Right = `Axis 3+` diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/S922X/WiiControllerProfiles/nunchuck.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/S922X/WiiControllerProfiles/nunchuck.ini new file mode 100644 index 0000000000..8850d84ce8 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/S922X/WiiControllerProfiles/nunchuck.ini @@ -0,0 +1,30 @@ +[Wiimote1] +Device = evdev/0/Microsoft X-Box 360 pad +Extension = Nunchuk +Buttons/A = Button 1 +Buttons/B = Button 0 +Buttons/1 = Button 3 +Buttons/2 = Button 2 +Buttons/- = Button 6 +Buttons/+ = Button 7 +D-Pad/Up = Axis 7- +D-Pad/Down = Axis 7+ +D-Pad/Left = Axis 6- +D-Pad/Right = Axis 6+ +Buttons/Home = Button 8 +Shake/X = Button 4 +Shake/Y = Button 4 +Shake/Z = Button 4 +Nunchuk/Buttons/C = Button 5 +Nunchuk/Buttons/Z = Axis 5+ +Nunchuk/Stick/Up = Axis 1- +Nunchuk/Stick/Down = Axis 1+ +Nunchuk/Stick/Left = Axis 0- +Nunchuk/Stick/Right = Axis 0+ +Nunchuk/Shake/X = Axis 2+ +Nunchuk/Shake/Y = Axis 2+ +Nunchuk/Shake/Z = Axis 2+ +IR/Up = `Axis 4-` +IR/Down = `Axis 4+` +IR/Left = `Axis 3-` +IR/Right = `Axis 3+` diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/S922X/WiiControllerProfiles/vremote.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/S922X/WiiControllerProfiles/vremote.ini new file mode 100644 index 0000000000..90ef876567 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/S922X/WiiControllerProfiles/vremote.ini @@ -0,0 +1,20 @@ +[Wiimote1] +Device = evdev/0/Microsoft X-Box 360 pad +Buttons/A = Button 1 +Buttons/B = Button 0 +Buttons/1 = Button 3 +Buttons/2 = Button 2 +Buttons/- = Button 6 +Buttons/+ = Button 7 +Buttons/Home = Button 8 +Shake/X = Button 4 +Shake/Y = Button 4 +Shake/Z = Button 4 +D-Pad/Up = `Axis 7-` | `Axis 1-` +D-Pad/Down = `Axis 7+` | `Axis 1+` +D-Pad/Left = `Axis 6-` | `Axis 0-` +D-Pad/Right = `Axis 6+` | `Axis 0+` +IR/Up = `Axis 4-` +IR/Down = `Axis 4+` +IR/Left = `Axis 3-` +IR/Right = `Axis 3+` diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SDM845/Dolphin.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SDM845/Dolphin.ini new file mode 100644 index 0000000000..823db4700a --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SDM845/Dolphin.ini @@ -0,0 +1,154 @@ +[General] +LastFilename = +ShowLag = False +ShowFrameCount = False +ISOPath0 = /storage/roms/gamecube +ISOPath1 = /storage/roms/wii +ISOPaths = 2 +RecursiveISOPaths = False +NANDRootPath = +WirelessMac = +[Interface] +ConfirmStop = True +UsePanicHandlers = True +OnScreenDisplayMessages = True +HideCursor = False +AutoHideCursor = False +MainWindowPosX = 403 +MainWindowPosY = 148 +MainWindowWidth = 800 +MainWindowHeight = 600 +Language = 0 +ShowToolbar = True +ShowStatusbar = True +ShowLogWindow = False +ShowLogConfigWindow = False +ExtendedFPSInfo = False +ThemeName40 = Clean Blue +PauseOnFocusLost = False +[Display] +FullscreenResolution = Auto +Fullscreen = True +RenderToMain = False +RenderWindowXPos = -1 +RenderWindowYPos = -1 +RenderWindowWidth = 640 +RenderWindowHeight = 480 +RenderWindowAutoSize = False +KeepWindowOnTop = False +ProgressiveScan = False +PAL60 = True +DisableScreenSaver = True +ForceNTSCJ = False +[GameList] +ListDrives = False +ListWad = True +ListElfDol = True +ListWii = True +ListGC = True +ListJap = True +ListPal = True +ListUsa = True +ListAustralia = True +ListFrance = True +ListGermany = True +ListItaly = True +ListKorea = True +ListNetherlands = True +ListRussia = True +ListSpain = True +ListTaiwan = True +ListWorld = True +ListUnknown = True +ListSort = 3 +ListSortSecondary = 0 +ColorCompressed = True +ColumnPlatform = True +ColumnBanner = True +ColumnNotes = True +ColumnFileName = False +ColumnID = False +ColumnRegion = True +ColumnSize = True +ColumnState = True +[Core] +SkipIPL = True +HLE_BS2 = False +TimingVariance = 40 +CPUCore = 4 +Fastmem = True +CPUThread = True +DSPHLE = True +SkipIdle = True +SyncOnSkipIdle = False +SyncGPU = False +SyncGpuMaxDistance = 200000 +SyncGpuMinDistance = -200000 +SyncGpuOverclock = 1.00000000 +FPRF = False +AccurateNaNs = False +DefaultISO = +DVDRoot = +Apploader = +EnableCheats = True +SelectedLanguage = 0 +OverrideGCLang = False +DPL2Decoder = False +Latency = 2 +MemcardAPath = +MemcardBPath = +AgpCartAPath = +AgpCartBPath = +GCIFolderAPath = /storage/roms/bios/GC/USA +SlotA = 1 +SlotB = 255 +SerialPort1 = 255 +BBA_MAC = +SIDevice0 = 6 +AdapterRumble0 = True +SimulateKonga0 = False +SIDevice1 = 6 +AdapterRumble1 = True +SimulateKonga1 = False +SIDevice2 = 0 +AdapterRumble2 = True +SimulateKonga2 = False +SIDevice3 = 0 +AdapterRumble3 = True +SimulateKonga3 = False +WiiSDCard = False +WiiKeyboard = False +WiimoteContinuousScanning = False +WiimoteEnableSpeaker = False +RunCompareServer = False +RunCompareClient = False +EmulationSpeed = 1.00000000 +FrameSkip = 0x00000003 +Overclock = 1.0 +OverclockEnable = False +GFXBackend = Vulkan +GPUDeterminismMode = auto +PerfMapDir = +AutoDiscChange = True +[Movie] +PauseMovie = False +Author = +DumpFrames = False +DumpFramesSilent = False +ShowInputDisplay = False +[DSP] +EnableJIT = True +DumpAudio = False +DumpUCode = False +Backend = Pulse +Volume = 100 +CaptureLog = False +DSPThread = True +[Input] +BackgroundInput = False +[FifoPlayer] +LoopReplay = True +[Analytics] +ID = 5082f0c30a7e422b1220107f69d6c108 +Enabled = False +PermissionAsked = True diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SDM845/GFX.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SDM845/GFX.ini new file mode 100644 index 0000000000..ad0f286a21 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SDM845/GFX.ini @@ -0,0 +1,62 @@ +[Hardware] +VSync = False +Adapter = 0 +[Settings] +AspectRatio = 0 +InternalResolution = 2 +Crop = False +wideScreenHack = False +UseXFB = False +UseRealXFB = False +SafeTextureCacheColorSamples = 128 +ShowFPS = False +LogRenderTimeToFile = False +OverlayStats = False +OverlayProjStats = False +DumpTextures = False +HiresTextures = False +ConvertHiresTextures = False +CacheHiresTextures = False +DumpEFBTarget = False +FreeLook = False +UseFFV1 = False +EnablePixelLighting = False +FastDepthCalc = True +MSAA = 1 +SSAA = False +EFBScale = 2 +TexFmtOverlayEnable = False +TexFmtOverlayCenter = False +Wireframe = False +DisableFog = False +EnableShaderDebugging = False +BorderlessFullscreen = False +SWZComploc = True +SWZFreeze = True +SWDumpObjects = False +SWDumpTevStages = False +SWDumpTevTexFetches = False +SWDrawStart = 0 +SWDrawEnd = 100000 +ShaderCompilationMode = 0 +WaitForShadersBeforeStarting = True +BackendMultithreading = True +EnableGPUTextureDecoding = True +[Enhancements] +ForceTextureFiltering = False +MaxAnisotropy = 0 +PostProcessingShader = +[Stereoscopy] +StereoMode = 0 +StereoDepth = 20 +StereoConvergencePercentage = 100 +StereoSwapEyes = False +[Hacks] +EFBAccessEnable = False +BBoxEnable = False +ForceProgressive = True +EFBToTextureEnable = True +EFBScaledCopy = False +EFBEmulateFormatChanges = False +SkipDuplicateXFBs = True +XFBToTextureEnable = False diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SDM845/GamecubeControllerProfiles/GCPadNew.ini.east b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SDM845/GamecubeControllerProfiles/GCPadNew.ini.east new file mode 100644 index 0000000000..9389302558 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SDM845/GamecubeControllerProfiles/GCPadNew.ini.east @@ -0,0 +1,36 @@ +[GCPad1] +Device = evdev/0/Microsoft X-Box 360 pad +Buttons/A = Button 1 +Buttons/B = Button 0 +Buttons/Start = Button 7 +Buttons/X = Button 2 +Buttons/Y = Button 3 +Buttons/Z = Button 5 +Buttons/Hotkey = Button 6 +C-Stick/Dead Zone = 25.000000000000000 +C-Stick/Down = Axis 4+ +C-Stick/Left = Axis 3- +C-Stick/Modifier = Control_L +C-Stick/Modifier/Range = 50.000000000000000 +C-Stick/Right = Axis 3+ +C-Stick/Up = Axis 4- +D-Pad/Down = Axis 7+ +D-Pad/Left = Axis 6- +D-Pad/Right = Axis 6+ +D-Pad/Up = Axis 7- +Main Stick/Dead Zone = 25.000000000000000 +Main Stick/Down = Axis 1+ +Main Stick/Left = Axis 0- +Main Stick/Modifier = Shift_L +Main Stick/Modifier/Range = 50.000000000000000 +Main Stick/Right = Axis 0+ +Main Stick/Up = Axis 1- +Triggers/Dead Zone = 0. +Triggers/Threshold = 90. +Triggers/L = Axis 2+ +Triggers/R = Axis 5+ +Triggers/L-Analog = Axis 2+ +Triggers/R-Analog = Axis 5+ +Rumble/Motor = `evdev/0/Retroid Pocket Gamepad:Strong` +Triforce/Coin = Button 8 +Triforce/Service = Button 4 diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SDM845/GamecubeControllerProfiles/GCPadNew.ini.south b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SDM845/GamecubeControllerProfiles/GCPadNew.ini.south new file mode 100644 index 0000000000..20373880fd --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SDM845/GamecubeControllerProfiles/GCPadNew.ini.south @@ -0,0 +1,36 @@ +[GCPad1] +Device = evdev/0/Microsoft X-Box 360 pad +Buttons/A = Button 0 +Buttons/B = Button 3 +Buttons/Start = Button 7 +Buttons/X = Button 1 +Buttons/Y = Button 2 +Buttons/Z = Button 5 +Buttons/Hotkey = Button 6 +C-Stick/Dead Zone = 25.000000000000000 +C-Stick/Down = Axis 4+ +C-Stick/Left = Axis 3- +C-Stick/Modifier = Control_L +C-Stick/Modifier/Range = 50.000000000000000 +C-Stick/Right = Axis 3+ +C-Stick/Up = Axis 4- +D-Pad/Down = Axis 7+ +D-Pad/Left = Axis 6- +D-Pad/Right = Axis 6+ +D-Pad/Up = Axis 7- +Main Stick/Dead Zone = 25.000000000000000 +Main Stick/Down = Axis 1+ +Main Stick/Left = Axis 0- +Main Stick/Modifier = Shift_L +Main Stick/Modifier/Range = 50.000000000000000 +Main Stick/Right = Axis 0+ +Main Stick/Up = Axis 1- +Triggers/Dead Zone = 0. +Triggers/Threshold = 90. +Triggers/L = Axis 2+ +Triggers/R = Axis 5+ +Triggers/L-Analog = Axis 2+ +Triggers/R-Analog = Axis 5+ +Rumble/Motor = `evdev/0/Retroid Pocket Gamepad:Strong` +Triforce/Coin = Button 8 +Triforce/Service = Button 4 diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SDM845/Hotkeys.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SDM845/Hotkeys.ini new file mode 100644 index 0000000000..838c89f486 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SDM845/Hotkeys.ini @@ -0,0 +1,10 @@ +[Hotkeys] +Device = evdev/0/Microsoft X-Box 360 pad +Graphics Toggles/Toggle Aspect Ratio = @(MODE+EAST) +General/Take Screenshot = @(MODE+SOUTH) +Save State/Save to Selected Slot = @(MODE+TR) +Load State/Load State Slot 1 = @(MODE+TL) +Other State Hotkeys/Increase Selected State Slot = @(MODE+`Axis 7-`) +Other State Hotkeys/Decrease Selected State Slot = @(MODE+`Axis 7+`) +Emulation Speed/Increase Emulation Speed = @(MODE+`Full Axis 5+`) +Emulation Speed/Decrease Emulation Speed = @(MODE+`Full Axis 2+`) diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SDM845/WiiControllerProfiles/classic.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SDM845/WiiControllerProfiles/classic.ini new file mode 100644 index 0000000000..08839512ea --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SDM845/WiiControllerProfiles/classic.ini @@ -0,0 +1,28 @@ +[Wiimote1] +Device = evdev/0/Microsoft X-Box 360 pad +Extension = Classic +Source = 1 +Classic/Buttons/A = Button 1 +Classic/Buttons/B = Button 0 +Classic/Buttons/X = Button 2 +Classic/Buttons/Y = Button 3 +Classic/Buttons/ZL = Axis 2+ +Classic/Buttons/ZR = Axis 5+ +Classic/Buttons/- = Button 6 +Classic/Buttons/+ = Button 7 +Classic/Buttons/Home = Button 8 +Classic/Left Stick/Up = Axis 1- +Classic/Left Stick/Down = Axis 1+ +Classic/Left Stick/Left = Axis 0- +Classic/Left Stick/Right = Axis 0+ +Classic/Right Stick/Up = Axis 4- +Classic/Right Stick/Down = Axis 4+ +Classic/Right Stick/Left = Axis 3- +Classic/Right Stick/Right = Axis 3+ +Classic/Triggers/L = Button 4 +Classic/Triggers/R = Button 5 +Classic/D-Pad/Up = Axis 7- +Classic/D-Pad/Down = Axis 7+ +Classic/D-Pad/Left = Axis 6- +Classic/D-Pad/Right = Axis 6+ +Rumble/Motor = `evdev/0/Retroid Pocket Gamepad:Strong` diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SDM845/WiiControllerProfiles/hremote.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SDM845/WiiControllerProfiles/hremote.ini new file mode 100644 index 0000000000..7514cde014 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SDM845/WiiControllerProfiles/hremote.ini @@ -0,0 +1,21 @@ +[Wiimote1] +Device = evdev/0/Microsoft X-Box 360 pad +Buttons/A = Button 3 +Buttons/B = Button 2 +Buttons/1 = Button 0 +Buttons/2 = Button 1 +Buttons/- = Button 6 +Buttons/+ = Button 7 +Buttons/Home = Button 8 +Shake/X = Button 4 +Shake/Y = Button 4 +Shake/Z = Button 4 +D-Pad/Up = `Axis 6-` | `Axis 0-` +D-Pad/Down = `Axis 6+` | `Axis 0+` +D-Pad/Left = `Axis 7+` | `Axis 1+` +D-Pad/Right = `Axis 7-` | `Axis 1-` +IR/Up = `Axis 4-` +IR/Down = `Axis 4+` +IR/Left = `Axis 3-` +IR/Right = `Axis 3+` +Rumble/Motor = `evdev/0/Retroid Pocket Gamepad:Strong` diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SDM845/WiiControllerProfiles/nunchuck.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SDM845/WiiControllerProfiles/nunchuck.ini new file mode 100644 index 0000000000..83b23d7eb3 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SDM845/WiiControllerProfiles/nunchuck.ini @@ -0,0 +1,31 @@ +[Wiimote1] +Device = evdev/0/Microsoft X-Box 360 pad +Extension = Nunchuk +Buttons/A = Button 1 +Buttons/B = Button 0 +Buttons/1 = Button 3 +Buttons/2 = Button 2 +Buttons/- = Button 6 +Buttons/+ = Button 7 +D-Pad/Up = Axis 7- +D-Pad/Down = Axis 7+ +D-Pad/Left = Axis 6- +D-Pad/Right = Axis 6+ +Buttons/Home = Button 8 +Shake/X = Button 4 +Shake/Y = Button 4 +Shake/Z = Button 4 +Nunchuk/Buttons/C = Button 5 +Nunchuk/Buttons/Z = Axis 5+ +Nunchuk/Stick/Up = Axis 1- +Nunchuk/Stick/Down = Axis 1+ +Nunchuk/Stick/Left = Axis 0- +Nunchuk/Stick/Right = Axis 0+ +Nunchuk/Shake/X = Axis 2+ +Nunchuk/Shake/Y = Axis 2+ +Nunchuk/Shake/Z = Axis 2+ +IR/Up = `Axis 4-` +IR/Down = `Axis 4+` +IR/Left = `Axis 3-` +IR/Right = `Axis 3+` +Rumble/Motor = `evdev/0/Retroid Pocket Gamepad:Strong` diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SDM845/WiiControllerProfiles/vremote.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SDM845/WiiControllerProfiles/vremote.ini new file mode 100644 index 0000000000..cea8ee0448 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SDM845/WiiControllerProfiles/vremote.ini @@ -0,0 +1,21 @@ +[Wiimote1] +Device = evdev/0/Microsoft X-Box 360 pad +Buttons/A = Button 1 +Buttons/B = Button 0 +Buttons/1 = Button 3 +Buttons/2 = Button 2 +Buttons/- = Button 6 +Buttons/+ = Button 7 +Buttons/Home = Button 8 +Shake/X = Button 4 +Shake/Y = Button 4 +Shake/Z = Button 4 +D-Pad/Up = `Axis 7-` | `Axis 1-` +D-Pad/Down = `Axis 7+` | `Axis 1+` +D-Pad/Left = `Axis 6-` | `Axis 0-` +D-Pad/Right = `Axis 6+` | `Axis 0+` +IR/Up = `Axis 4-` +IR/Down = `Axis 4+` +IR/Left = `Axis 3-` +IR/Right = `Axis 3+` +Rumble/Motor = `evdev/0/Retroid Pocket Gamepad:Strong` diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8250/Dolphin.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8250/Dolphin.ini new file mode 100644 index 0000000000..823db4700a --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8250/Dolphin.ini @@ -0,0 +1,154 @@ +[General] +LastFilename = +ShowLag = False +ShowFrameCount = False +ISOPath0 = /storage/roms/gamecube +ISOPath1 = /storage/roms/wii +ISOPaths = 2 +RecursiveISOPaths = False +NANDRootPath = +WirelessMac = +[Interface] +ConfirmStop = True +UsePanicHandlers = True +OnScreenDisplayMessages = True +HideCursor = False +AutoHideCursor = False +MainWindowPosX = 403 +MainWindowPosY = 148 +MainWindowWidth = 800 +MainWindowHeight = 600 +Language = 0 +ShowToolbar = True +ShowStatusbar = True +ShowLogWindow = False +ShowLogConfigWindow = False +ExtendedFPSInfo = False +ThemeName40 = Clean Blue +PauseOnFocusLost = False +[Display] +FullscreenResolution = Auto +Fullscreen = True +RenderToMain = False +RenderWindowXPos = -1 +RenderWindowYPos = -1 +RenderWindowWidth = 640 +RenderWindowHeight = 480 +RenderWindowAutoSize = False +KeepWindowOnTop = False +ProgressiveScan = False +PAL60 = True +DisableScreenSaver = True +ForceNTSCJ = False +[GameList] +ListDrives = False +ListWad = True +ListElfDol = True +ListWii = True +ListGC = True +ListJap = True +ListPal = True +ListUsa = True +ListAustralia = True +ListFrance = True +ListGermany = True +ListItaly = True +ListKorea = True +ListNetherlands = True +ListRussia = True +ListSpain = True +ListTaiwan = True +ListWorld = True +ListUnknown = True +ListSort = 3 +ListSortSecondary = 0 +ColorCompressed = True +ColumnPlatform = True +ColumnBanner = True +ColumnNotes = True +ColumnFileName = False +ColumnID = False +ColumnRegion = True +ColumnSize = True +ColumnState = True +[Core] +SkipIPL = True +HLE_BS2 = False +TimingVariance = 40 +CPUCore = 4 +Fastmem = True +CPUThread = True +DSPHLE = True +SkipIdle = True +SyncOnSkipIdle = False +SyncGPU = False +SyncGpuMaxDistance = 200000 +SyncGpuMinDistance = -200000 +SyncGpuOverclock = 1.00000000 +FPRF = False +AccurateNaNs = False +DefaultISO = +DVDRoot = +Apploader = +EnableCheats = True +SelectedLanguage = 0 +OverrideGCLang = False +DPL2Decoder = False +Latency = 2 +MemcardAPath = +MemcardBPath = +AgpCartAPath = +AgpCartBPath = +GCIFolderAPath = /storage/roms/bios/GC/USA +SlotA = 1 +SlotB = 255 +SerialPort1 = 255 +BBA_MAC = +SIDevice0 = 6 +AdapterRumble0 = True +SimulateKonga0 = False +SIDevice1 = 6 +AdapterRumble1 = True +SimulateKonga1 = False +SIDevice2 = 0 +AdapterRumble2 = True +SimulateKonga2 = False +SIDevice3 = 0 +AdapterRumble3 = True +SimulateKonga3 = False +WiiSDCard = False +WiiKeyboard = False +WiimoteContinuousScanning = False +WiimoteEnableSpeaker = False +RunCompareServer = False +RunCompareClient = False +EmulationSpeed = 1.00000000 +FrameSkip = 0x00000003 +Overclock = 1.0 +OverclockEnable = False +GFXBackend = Vulkan +GPUDeterminismMode = auto +PerfMapDir = +AutoDiscChange = True +[Movie] +PauseMovie = False +Author = +DumpFrames = False +DumpFramesSilent = False +ShowInputDisplay = False +[DSP] +EnableJIT = True +DumpAudio = False +DumpUCode = False +Backend = Pulse +Volume = 100 +CaptureLog = False +DSPThread = True +[Input] +BackgroundInput = False +[FifoPlayer] +LoopReplay = True +[Analytics] +ID = 5082f0c30a7e422b1220107f69d6c108 +Enabled = False +PermissionAsked = True diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8250/GFX.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8250/GFX.ini new file mode 100644 index 0000000000..ad0f286a21 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8250/GFX.ini @@ -0,0 +1,62 @@ +[Hardware] +VSync = False +Adapter = 0 +[Settings] +AspectRatio = 0 +InternalResolution = 2 +Crop = False +wideScreenHack = False +UseXFB = False +UseRealXFB = False +SafeTextureCacheColorSamples = 128 +ShowFPS = False +LogRenderTimeToFile = False +OverlayStats = False +OverlayProjStats = False +DumpTextures = False +HiresTextures = False +ConvertHiresTextures = False +CacheHiresTextures = False +DumpEFBTarget = False +FreeLook = False +UseFFV1 = False +EnablePixelLighting = False +FastDepthCalc = True +MSAA = 1 +SSAA = False +EFBScale = 2 +TexFmtOverlayEnable = False +TexFmtOverlayCenter = False +Wireframe = False +DisableFog = False +EnableShaderDebugging = False +BorderlessFullscreen = False +SWZComploc = True +SWZFreeze = True +SWDumpObjects = False +SWDumpTevStages = False +SWDumpTevTexFetches = False +SWDrawStart = 0 +SWDrawEnd = 100000 +ShaderCompilationMode = 0 +WaitForShadersBeforeStarting = True +BackendMultithreading = True +EnableGPUTextureDecoding = True +[Enhancements] +ForceTextureFiltering = False +MaxAnisotropy = 0 +PostProcessingShader = +[Stereoscopy] +StereoMode = 0 +StereoDepth = 20 +StereoConvergencePercentage = 100 +StereoSwapEyes = False +[Hacks] +EFBAccessEnable = False +BBoxEnable = False +ForceProgressive = True +EFBToTextureEnable = True +EFBScaledCopy = False +EFBEmulateFormatChanges = False +SkipDuplicateXFBs = True +XFBToTextureEnable = False diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8250/GamecubeControllerProfiles/GCPadNew.ini.east b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8250/GamecubeControllerProfiles/GCPadNew.ini.east new file mode 100644 index 0000000000..9389302558 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8250/GamecubeControllerProfiles/GCPadNew.ini.east @@ -0,0 +1,36 @@ +[GCPad1] +Device = evdev/0/Microsoft X-Box 360 pad +Buttons/A = Button 1 +Buttons/B = Button 0 +Buttons/Start = Button 7 +Buttons/X = Button 2 +Buttons/Y = Button 3 +Buttons/Z = Button 5 +Buttons/Hotkey = Button 6 +C-Stick/Dead Zone = 25.000000000000000 +C-Stick/Down = Axis 4+ +C-Stick/Left = Axis 3- +C-Stick/Modifier = Control_L +C-Stick/Modifier/Range = 50.000000000000000 +C-Stick/Right = Axis 3+ +C-Stick/Up = Axis 4- +D-Pad/Down = Axis 7+ +D-Pad/Left = Axis 6- +D-Pad/Right = Axis 6+ +D-Pad/Up = Axis 7- +Main Stick/Dead Zone = 25.000000000000000 +Main Stick/Down = Axis 1+ +Main Stick/Left = Axis 0- +Main Stick/Modifier = Shift_L +Main Stick/Modifier/Range = 50.000000000000000 +Main Stick/Right = Axis 0+ +Main Stick/Up = Axis 1- +Triggers/Dead Zone = 0. +Triggers/Threshold = 90. +Triggers/L = Axis 2+ +Triggers/R = Axis 5+ +Triggers/L-Analog = Axis 2+ +Triggers/R-Analog = Axis 5+ +Rumble/Motor = `evdev/0/Retroid Pocket Gamepad:Strong` +Triforce/Coin = Button 8 +Triforce/Service = Button 4 diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8250/GamecubeControllerProfiles/GCPadNew.ini.south b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8250/GamecubeControllerProfiles/GCPadNew.ini.south new file mode 100644 index 0000000000..20373880fd --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8250/GamecubeControllerProfiles/GCPadNew.ini.south @@ -0,0 +1,36 @@ +[GCPad1] +Device = evdev/0/Microsoft X-Box 360 pad +Buttons/A = Button 0 +Buttons/B = Button 3 +Buttons/Start = Button 7 +Buttons/X = Button 1 +Buttons/Y = Button 2 +Buttons/Z = Button 5 +Buttons/Hotkey = Button 6 +C-Stick/Dead Zone = 25.000000000000000 +C-Stick/Down = Axis 4+ +C-Stick/Left = Axis 3- +C-Stick/Modifier = Control_L +C-Stick/Modifier/Range = 50.000000000000000 +C-Stick/Right = Axis 3+ +C-Stick/Up = Axis 4- +D-Pad/Down = Axis 7+ +D-Pad/Left = Axis 6- +D-Pad/Right = Axis 6+ +D-Pad/Up = Axis 7- +Main Stick/Dead Zone = 25.000000000000000 +Main Stick/Down = Axis 1+ +Main Stick/Left = Axis 0- +Main Stick/Modifier = Shift_L +Main Stick/Modifier/Range = 50.000000000000000 +Main Stick/Right = Axis 0+ +Main Stick/Up = Axis 1- +Triggers/Dead Zone = 0. +Triggers/Threshold = 90. +Triggers/L = Axis 2+ +Triggers/R = Axis 5+ +Triggers/L-Analog = Axis 2+ +Triggers/R-Analog = Axis 5+ +Rumble/Motor = `evdev/0/Retroid Pocket Gamepad:Strong` +Triforce/Coin = Button 8 +Triforce/Service = Button 4 diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8250/Hotkeys.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8250/Hotkeys.ini new file mode 100644 index 0000000000..838c89f486 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8250/Hotkeys.ini @@ -0,0 +1,10 @@ +[Hotkeys] +Device = evdev/0/Microsoft X-Box 360 pad +Graphics Toggles/Toggle Aspect Ratio = @(MODE+EAST) +General/Take Screenshot = @(MODE+SOUTH) +Save State/Save to Selected Slot = @(MODE+TR) +Load State/Load State Slot 1 = @(MODE+TL) +Other State Hotkeys/Increase Selected State Slot = @(MODE+`Axis 7-`) +Other State Hotkeys/Decrease Selected State Slot = @(MODE+`Axis 7+`) +Emulation Speed/Increase Emulation Speed = @(MODE+`Full Axis 5+`) +Emulation Speed/Decrease Emulation Speed = @(MODE+`Full Axis 2+`) diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8250/WiiControllerProfiles/classic.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8250/WiiControllerProfiles/classic.ini new file mode 100644 index 0000000000..08839512ea --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8250/WiiControllerProfiles/classic.ini @@ -0,0 +1,28 @@ +[Wiimote1] +Device = evdev/0/Microsoft X-Box 360 pad +Extension = Classic +Source = 1 +Classic/Buttons/A = Button 1 +Classic/Buttons/B = Button 0 +Classic/Buttons/X = Button 2 +Classic/Buttons/Y = Button 3 +Classic/Buttons/ZL = Axis 2+ +Classic/Buttons/ZR = Axis 5+ +Classic/Buttons/- = Button 6 +Classic/Buttons/+ = Button 7 +Classic/Buttons/Home = Button 8 +Classic/Left Stick/Up = Axis 1- +Classic/Left Stick/Down = Axis 1+ +Classic/Left Stick/Left = Axis 0- +Classic/Left Stick/Right = Axis 0+ +Classic/Right Stick/Up = Axis 4- +Classic/Right Stick/Down = Axis 4+ +Classic/Right Stick/Left = Axis 3- +Classic/Right Stick/Right = Axis 3+ +Classic/Triggers/L = Button 4 +Classic/Triggers/R = Button 5 +Classic/D-Pad/Up = Axis 7- +Classic/D-Pad/Down = Axis 7+ +Classic/D-Pad/Left = Axis 6- +Classic/D-Pad/Right = Axis 6+ +Rumble/Motor = `evdev/0/Retroid Pocket Gamepad:Strong` diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8250/WiiControllerProfiles/hremote.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8250/WiiControllerProfiles/hremote.ini new file mode 100644 index 0000000000..7514cde014 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8250/WiiControllerProfiles/hremote.ini @@ -0,0 +1,21 @@ +[Wiimote1] +Device = evdev/0/Microsoft X-Box 360 pad +Buttons/A = Button 3 +Buttons/B = Button 2 +Buttons/1 = Button 0 +Buttons/2 = Button 1 +Buttons/- = Button 6 +Buttons/+ = Button 7 +Buttons/Home = Button 8 +Shake/X = Button 4 +Shake/Y = Button 4 +Shake/Z = Button 4 +D-Pad/Up = `Axis 6-` | `Axis 0-` +D-Pad/Down = `Axis 6+` | `Axis 0+` +D-Pad/Left = `Axis 7+` | `Axis 1+` +D-Pad/Right = `Axis 7-` | `Axis 1-` +IR/Up = `Axis 4-` +IR/Down = `Axis 4+` +IR/Left = `Axis 3-` +IR/Right = `Axis 3+` +Rumble/Motor = `evdev/0/Retroid Pocket Gamepad:Strong` diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8250/WiiControllerProfiles/nunchuck.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8250/WiiControllerProfiles/nunchuck.ini new file mode 100644 index 0000000000..83b23d7eb3 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8250/WiiControllerProfiles/nunchuck.ini @@ -0,0 +1,31 @@ +[Wiimote1] +Device = evdev/0/Microsoft X-Box 360 pad +Extension = Nunchuk +Buttons/A = Button 1 +Buttons/B = Button 0 +Buttons/1 = Button 3 +Buttons/2 = Button 2 +Buttons/- = Button 6 +Buttons/+ = Button 7 +D-Pad/Up = Axis 7- +D-Pad/Down = Axis 7+ +D-Pad/Left = Axis 6- +D-Pad/Right = Axis 6+ +Buttons/Home = Button 8 +Shake/X = Button 4 +Shake/Y = Button 4 +Shake/Z = Button 4 +Nunchuk/Buttons/C = Button 5 +Nunchuk/Buttons/Z = Axis 5+ +Nunchuk/Stick/Up = Axis 1- +Nunchuk/Stick/Down = Axis 1+ +Nunchuk/Stick/Left = Axis 0- +Nunchuk/Stick/Right = Axis 0+ +Nunchuk/Shake/X = Axis 2+ +Nunchuk/Shake/Y = Axis 2+ +Nunchuk/Shake/Z = Axis 2+ +IR/Up = `Axis 4-` +IR/Down = `Axis 4+` +IR/Left = `Axis 3-` +IR/Right = `Axis 3+` +Rumble/Motor = `evdev/0/Retroid Pocket Gamepad:Strong` diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8250/WiiControllerProfiles/vremote.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8250/WiiControllerProfiles/vremote.ini new file mode 100644 index 0000000000..cea8ee0448 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8250/WiiControllerProfiles/vremote.ini @@ -0,0 +1,21 @@ +[Wiimote1] +Device = evdev/0/Microsoft X-Box 360 pad +Buttons/A = Button 1 +Buttons/B = Button 0 +Buttons/1 = Button 3 +Buttons/2 = Button 2 +Buttons/- = Button 6 +Buttons/+ = Button 7 +Buttons/Home = Button 8 +Shake/X = Button 4 +Shake/Y = Button 4 +Shake/Z = Button 4 +D-Pad/Up = `Axis 7-` | `Axis 1-` +D-Pad/Down = `Axis 7+` | `Axis 1+` +D-Pad/Left = `Axis 6-` | `Axis 0-` +D-Pad/Right = `Axis 6+` | `Axis 0+` +IR/Up = `Axis 4-` +IR/Down = `Axis 4+` +IR/Left = `Axis 3-` +IR/Right = `Axis 3+` +Rumble/Motor = `evdev/0/Retroid Pocket Gamepad:Strong` diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8550/Dolphin.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8550/Dolphin.ini new file mode 100644 index 0000000000..823db4700a --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8550/Dolphin.ini @@ -0,0 +1,154 @@ +[General] +LastFilename = +ShowLag = False +ShowFrameCount = False +ISOPath0 = /storage/roms/gamecube +ISOPath1 = /storage/roms/wii +ISOPaths = 2 +RecursiveISOPaths = False +NANDRootPath = +WirelessMac = +[Interface] +ConfirmStop = True +UsePanicHandlers = True +OnScreenDisplayMessages = True +HideCursor = False +AutoHideCursor = False +MainWindowPosX = 403 +MainWindowPosY = 148 +MainWindowWidth = 800 +MainWindowHeight = 600 +Language = 0 +ShowToolbar = True +ShowStatusbar = True +ShowLogWindow = False +ShowLogConfigWindow = False +ExtendedFPSInfo = False +ThemeName40 = Clean Blue +PauseOnFocusLost = False +[Display] +FullscreenResolution = Auto +Fullscreen = True +RenderToMain = False +RenderWindowXPos = -1 +RenderWindowYPos = -1 +RenderWindowWidth = 640 +RenderWindowHeight = 480 +RenderWindowAutoSize = False +KeepWindowOnTop = False +ProgressiveScan = False +PAL60 = True +DisableScreenSaver = True +ForceNTSCJ = False +[GameList] +ListDrives = False +ListWad = True +ListElfDol = True +ListWii = True +ListGC = True +ListJap = True +ListPal = True +ListUsa = True +ListAustralia = True +ListFrance = True +ListGermany = True +ListItaly = True +ListKorea = True +ListNetherlands = True +ListRussia = True +ListSpain = True +ListTaiwan = True +ListWorld = True +ListUnknown = True +ListSort = 3 +ListSortSecondary = 0 +ColorCompressed = True +ColumnPlatform = True +ColumnBanner = True +ColumnNotes = True +ColumnFileName = False +ColumnID = False +ColumnRegion = True +ColumnSize = True +ColumnState = True +[Core] +SkipIPL = True +HLE_BS2 = False +TimingVariance = 40 +CPUCore = 4 +Fastmem = True +CPUThread = True +DSPHLE = True +SkipIdle = True +SyncOnSkipIdle = False +SyncGPU = False +SyncGpuMaxDistance = 200000 +SyncGpuMinDistance = -200000 +SyncGpuOverclock = 1.00000000 +FPRF = False +AccurateNaNs = False +DefaultISO = +DVDRoot = +Apploader = +EnableCheats = True +SelectedLanguage = 0 +OverrideGCLang = False +DPL2Decoder = False +Latency = 2 +MemcardAPath = +MemcardBPath = +AgpCartAPath = +AgpCartBPath = +GCIFolderAPath = /storage/roms/bios/GC/USA +SlotA = 1 +SlotB = 255 +SerialPort1 = 255 +BBA_MAC = +SIDevice0 = 6 +AdapterRumble0 = True +SimulateKonga0 = False +SIDevice1 = 6 +AdapterRumble1 = True +SimulateKonga1 = False +SIDevice2 = 0 +AdapterRumble2 = True +SimulateKonga2 = False +SIDevice3 = 0 +AdapterRumble3 = True +SimulateKonga3 = False +WiiSDCard = False +WiiKeyboard = False +WiimoteContinuousScanning = False +WiimoteEnableSpeaker = False +RunCompareServer = False +RunCompareClient = False +EmulationSpeed = 1.00000000 +FrameSkip = 0x00000003 +Overclock = 1.0 +OverclockEnable = False +GFXBackend = Vulkan +GPUDeterminismMode = auto +PerfMapDir = +AutoDiscChange = True +[Movie] +PauseMovie = False +Author = +DumpFrames = False +DumpFramesSilent = False +ShowInputDisplay = False +[DSP] +EnableJIT = True +DumpAudio = False +DumpUCode = False +Backend = Pulse +Volume = 100 +CaptureLog = False +DSPThread = True +[Input] +BackgroundInput = False +[FifoPlayer] +LoopReplay = True +[Analytics] +ID = 5082f0c30a7e422b1220107f69d6c108 +Enabled = False +PermissionAsked = True diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8550/GFX.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8550/GFX.ini new file mode 100644 index 0000000000..ad0f286a21 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8550/GFX.ini @@ -0,0 +1,62 @@ +[Hardware] +VSync = False +Adapter = 0 +[Settings] +AspectRatio = 0 +InternalResolution = 2 +Crop = False +wideScreenHack = False +UseXFB = False +UseRealXFB = False +SafeTextureCacheColorSamples = 128 +ShowFPS = False +LogRenderTimeToFile = False +OverlayStats = False +OverlayProjStats = False +DumpTextures = False +HiresTextures = False +ConvertHiresTextures = False +CacheHiresTextures = False +DumpEFBTarget = False +FreeLook = False +UseFFV1 = False +EnablePixelLighting = False +FastDepthCalc = True +MSAA = 1 +SSAA = False +EFBScale = 2 +TexFmtOverlayEnable = False +TexFmtOverlayCenter = False +Wireframe = False +DisableFog = False +EnableShaderDebugging = False +BorderlessFullscreen = False +SWZComploc = True +SWZFreeze = True +SWDumpObjects = False +SWDumpTevStages = False +SWDumpTevTexFetches = False +SWDrawStart = 0 +SWDrawEnd = 100000 +ShaderCompilationMode = 0 +WaitForShadersBeforeStarting = True +BackendMultithreading = True +EnableGPUTextureDecoding = True +[Enhancements] +ForceTextureFiltering = False +MaxAnisotropy = 0 +PostProcessingShader = +[Stereoscopy] +StereoMode = 0 +StereoDepth = 20 +StereoConvergencePercentage = 100 +StereoSwapEyes = False +[Hacks] +EFBAccessEnable = False +BBoxEnable = False +ForceProgressive = True +EFBToTextureEnable = True +EFBScaledCopy = False +EFBEmulateFormatChanges = False +SkipDuplicateXFBs = True +XFBToTextureEnable = False diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8550/GamecubeControllerProfiles b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8550/GamecubeControllerProfiles new file mode 120000 index 0000000000..adef25610d --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8550/GamecubeControllerProfiles @@ -0,0 +1 @@ +../InputPlumber/GamecubeControllerProfiles \ No newline at end of file diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8550/Hotkeys.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8550/Hotkeys.ini new file mode 120000 index 0000000000..d65ca4e2bd --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8550/Hotkeys.ini @@ -0,0 +1 @@ +../InputPlumber/Hotkeys.ini \ No newline at end of file diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8550/WiiControllerProfiles b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8550/WiiControllerProfiles new file mode 120000 index 0000000000..d0c169d967 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8550/WiiControllerProfiles @@ -0,0 +1 @@ +../InputPlumber/WiiControllerProfiles \ No newline at end of file diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8650/Dolphin.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8650/Dolphin.ini new file mode 100644 index 0000000000..823db4700a --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8650/Dolphin.ini @@ -0,0 +1,154 @@ +[General] +LastFilename = +ShowLag = False +ShowFrameCount = False +ISOPath0 = /storage/roms/gamecube +ISOPath1 = /storage/roms/wii +ISOPaths = 2 +RecursiveISOPaths = False +NANDRootPath = +WirelessMac = +[Interface] +ConfirmStop = True +UsePanicHandlers = True +OnScreenDisplayMessages = True +HideCursor = False +AutoHideCursor = False +MainWindowPosX = 403 +MainWindowPosY = 148 +MainWindowWidth = 800 +MainWindowHeight = 600 +Language = 0 +ShowToolbar = True +ShowStatusbar = True +ShowLogWindow = False +ShowLogConfigWindow = False +ExtendedFPSInfo = False +ThemeName40 = Clean Blue +PauseOnFocusLost = False +[Display] +FullscreenResolution = Auto +Fullscreen = True +RenderToMain = False +RenderWindowXPos = -1 +RenderWindowYPos = -1 +RenderWindowWidth = 640 +RenderWindowHeight = 480 +RenderWindowAutoSize = False +KeepWindowOnTop = False +ProgressiveScan = False +PAL60 = True +DisableScreenSaver = True +ForceNTSCJ = False +[GameList] +ListDrives = False +ListWad = True +ListElfDol = True +ListWii = True +ListGC = True +ListJap = True +ListPal = True +ListUsa = True +ListAustralia = True +ListFrance = True +ListGermany = True +ListItaly = True +ListKorea = True +ListNetherlands = True +ListRussia = True +ListSpain = True +ListTaiwan = True +ListWorld = True +ListUnknown = True +ListSort = 3 +ListSortSecondary = 0 +ColorCompressed = True +ColumnPlatform = True +ColumnBanner = True +ColumnNotes = True +ColumnFileName = False +ColumnID = False +ColumnRegion = True +ColumnSize = True +ColumnState = True +[Core] +SkipIPL = True +HLE_BS2 = False +TimingVariance = 40 +CPUCore = 4 +Fastmem = True +CPUThread = True +DSPHLE = True +SkipIdle = True +SyncOnSkipIdle = False +SyncGPU = False +SyncGpuMaxDistance = 200000 +SyncGpuMinDistance = -200000 +SyncGpuOverclock = 1.00000000 +FPRF = False +AccurateNaNs = False +DefaultISO = +DVDRoot = +Apploader = +EnableCheats = True +SelectedLanguage = 0 +OverrideGCLang = False +DPL2Decoder = False +Latency = 2 +MemcardAPath = +MemcardBPath = +AgpCartAPath = +AgpCartBPath = +GCIFolderAPath = /storage/roms/bios/GC/USA +SlotA = 1 +SlotB = 255 +SerialPort1 = 255 +BBA_MAC = +SIDevice0 = 6 +AdapterRumble0 = True +SimulateKonga0 = False +SIDevice1 = 6 +AdapterRumble1 = True +SimulateKonga1 = False +SIDevice2 = 0 +AdapterRumble2 = True +SimulateKonga2 = False +SIDevice3 = 0 +AdapterRumble3 = True +SimulateKonga3 = False +WiiSDCard = False +WiiKeyboard = False +WiimoteContinuousScanning = False +WiimoteEnableSpeaker = False +RunCompareServer = False +RunCompareClient = False +EmulationSpeed = 1.00000000 +FrameSkip = 0x00000003 +Overclock = 1.0 +OverclockEnable = False +GFXBackend = Vulkan +GPUDeterminismMode = auto +PerfMapDir = +AutoDiscChange = True +[Movie] +PauseMovie = False +Author = +DumpFrames = False +DumpFramesSilent = False +ShowInputDisplay = False +[DSP] +EnableJIT = True +DumpAudio = False +DumpUCode = False +Backend = Pulse +Volume = 100 +CaptureLog = False +DSPThread = True +[Input] +BackgroundInput = False +[FifoPlayer] +LoopReplay = True +[Analytics] +ID = 5082f0c30a7e422b1220107f69d6c108 +Enabled = False +PermissionAsked = True diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8650/GFX.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8650/GFX.ini new file mode 100644 index 0000000000..ad0f286a21 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8650/GFX.ini @@ -0,0 +1,62 @@ +[Hardware] +VSync = False +Adapter = 0 +[Settings] +AspectRatio = 0 +InternalResolution = 2 +Crop = False +wideScreenHack = False +UseXFB = False +UseRealXFB = False +SafeTextureCacheColorSamples = 128 +ShowFPS = False +LogRenderTimeToFile = False +OverlayStats = False +OverlayProjStats = False +DumpTextures = False +HiresTextures = False +ConvertHiresTextures = False +CacheHiresTextures = False +DumpEFBTarget = False +FreeLook = False +UseFFV1 = False +EnablePixelLighting = False +FastDepthCalc = True +MSAA = 1 +SSAA = False +EFBScale = 2 +TexFmtOverlayEnable = False +TexFmtOverlayCenter = False +Wireframe = False +DisableFog = False +EnableShaderDebugging = False +BorderlessFullscreen = False +SWZComploc = True +SWZFreeze = True +SWDumpObjects = False +SWDumpTevStages = False +SWDumpTevTexFetches = False +SWDrawStart = 0 +SWDrawEnd = 100000 +ShaderCompilationMode = 0 +WaitForShadersBeforeStarting = True +BackendMultithreading = True +EnableGPUTextureDecoding = True +[Enhancements] +ForceTextureFiltering = False +MaxAnisotropy = 0 +PostProcessingShader = +[Stereoscopy] +StereoMode = 0 +StereoDepth = 20 +StereoConvergencePercentage = 100 +StereoSwapEyes = False +[Hacks] +EFBAccessEnable = False +BBoxEnable = False +ForceProgressive = True +EFBToTextureEnable = True +EFBScaledCopy = False +EFBEmulateFormatChanges = False +SkipDuplicateXFBs = True +XFBToTextureEnable = False diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8650/GamecubeControllerProfiles b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8650/GamecubeControllerProfiles new file mode 120000 index 0000000000..adef25610d --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8650/GamecubeControllerProfiles @@ -0,0 +1 @@ +../InputPlumber/GamecubeControllerProfiles \ No newline at end of file diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8650/Hotkeys.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8650/Hotkeys.ini new file mode 120000 index 0000000000..d65ca4e2bd --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8650/Hotkeys.ini @@ -0,0 +1 @@ +../InputPlumber/Hotkeys.ini \ No newline at end of file diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8650/WiiControllerProfiles b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8650/WiiControllerProfiles new file mode 120000 index 0000000000..d0c169d967 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/config/SM8650/WiiControllerProfiles @@ -0,0 +1 @@ +../InputPlumber/WiiControllerProfiles \ No newline at end of file diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/package.mk b/projects/ArchR/packages/emulators/standalone/dolphin-sa/package.mk new file mode 100644 index 0000000000..d60865be4c --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/package.mk @@ -0,0 +1,122 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="dolphin-sa" +PKG_LICENSE="GPLv2" +PKG_DEPENDS_TARGET="toolchain libevdev libdrm ffmpeg zlib libpng lzo libusb zstd ecm openal-soft pulseaudio alsa-lib libfmt hidapi curl" +PKG_LONGDESC="Dolphin is a GameCube / Wii / Triforce emulator, allowing you to play games for these two platforms on PC with improvements. " +PKG_TOOLCHAIN="cmake" + +case ${DEVICE} in + SM8250|SM8550|SDM845|RK3399|SM8650) + PKG_VERSION="9323074ada4b1d372809dc71ed092efe8d0e4c8e" + PKG_SITE="https://github.com/dolphin-emu/dolphin" + PKG_URL="${PKG_SITE}.git" + PKG_DEPENDS_TARGET+=" qt6" + PKG_PATCH_DIRS+=" qt6" + PKG_CMAKE_OPTS_TARGET+=" -DENABLE_QT=ON \ + -DUSE_RETRO_ACHIEVEMENTS=ON \ + -DENABLE_HEADLESS=OFF \ + -DCMAKE_EXE_LINKER_FLAGS=-flto=$(nproc)" + ;; + *) + PKG_VERSION="e6583f8bec814d8f3748f1d7738457600ce0de56" + PKG_SITE="https://github.com/dolphin-emu/dolphin" + PKG_URL="${PKG_SITE}.git" + PKG_PATCH_DIRS+=" wayland" + PKG_CMAKE_OPTS_TARGET+=" -DENABLE_QT=OFF \ + -DENABLE_WAYLAND=ON \ + -DUSE_RETRO_ACHIEVEMENTS=OFF \ + -DENABLE_HEADLESS=ON" + ;; +esac + +if [ "${OPENGL_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL} glu libglvnd" + PKG_CMAKE_OPTS_TARGET+=" -DENABLE_EGL=ON" +elif [ "${OPENGLES_SUPPORT}" = yes ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" + PKG_CMAKE_OPTS_TARGET+=" -DENABLE_EGL=ON" +fi + +if [ "${DISPLAYSERVER}" = "wl" ]; then + PKG_DEPENDS_TARGET+=" wayland ${WINDOWMANAGER} xwayland xrandr libXi" + PKG_CMAKE_OPTS_TARGET+=" -DENABLE_X11=ON" +else + PKG_CMAKE_OPTS_TARGET+=" -DENABLE_X11=OFF" +fi + +if [ "${VULKAN_SUPPORT}" = "yes" ] +then + PKG_DEPENDS_TARGET+=" ${VULKAN}" + PKG_CMAKE_OPTS_TARGET+=" -DENABLE_VULKAN=ON" + GRENDERER="Vulkan" +else + PKG_CMAKE_OPTS_TARGET+=" -DENABLE_VULKAN=OFF" + GRENDERER="OGL" +fi + +pre_configure_target() { + PKG_CMAKE_OPTS_TARGET+=" -DCMAKE_BUILD_TYPE=Release \ + -DDISTRIBUTOR="ArchR" \ + -DENABLE_NOGUI=ON \ + -DENABLE_EVDEV=ON \ + -DUSE_DISCORD_PRESENCE=OFF \ + -DBUILD_SHARED_LIBS=OFF \ + -DLINUX_LOCAL_DEV=OFF \ + -DENABLE_PULSEAUDIO=ON \ + -DENABLE_ALSA=ON \ + -DENABLE_TESTS=OFF \ + -DENABLE_LLVM=OFF \ + -DENABLE_ANALYTICS=OFF \ + -DENABLE_LTO=ON \ + -DENCODE_FRAMEDUMPS=OFF \ + -DENABLE_AUTOUPDATE=OFF \ + -DUSE_MGBA=OFF \ + -DENABLE_CLI_TOOL=OFF \ + -DCMAKE_POLICY_VERSION_MINIMUM=3.5" + + sed -i 's~#include ~#include \n#include ~g' ${PKG_BUILD}/Externals/VulkanMemoryAllocator/include/vk_mem_alloc.h + sed -i 's~#include ~#include \n#include ~g' ${PKG_BUILD}/Externals/VulkanMemoryAllocator/include/vk_mem_alloc.h +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp -rf ${PKG_BUILD}/.${TARGET_NAME}/Binaries/dolphin* ${INSTALL}/usr/bin + cp -rf ${PKG_DIR}/scripts/* ${INSTALL}/usr/bin + + chmod +x ${INSTALL}/usr/bin/* + + mkdir -p ${INSTALL}/usr/config/dolphin-emu + cp -rf ${PKG_BUILD}/Data/Sys/* ${INSTALL}/usr/config/dolphin-emu + cp -rfH ${PKG_DIR}/config/${DEVICE}/* ${INSTALL}/usr/config/dolphin-emu + cp -rf ${PKG_DIR}/triforce ${INSTALL}/usr/config/dolphin-emu/triforce_gecko_codes +} + +post_install() { + case ${DEVICE} in + RK3588) + DOLPHIN_BACKEND="\${DOLPHIN_BACKEND}" + EXPORTS="if [ ! -z 'lsmod | grep panthor' ]; then LD_LIBRARY_PATH='\/usr\/lib\/libmali-valhall-g610-g13p0-x11-gbm.so' DOLPHIN_BACKEND='wayland'; else DOLPHIN_BACKEND='x11'; fi" + ;; + SM8250|SM8550|RK3399|SM8650) + DOLPHIN_BACKEND="x11" + EXPORTS="export QT_QPA_PLATFORM=xcb" + ;; + *) + DOLPHIN_BACKEND="wayland" + EXPORTS="" + ;; + esac + sed -e "s/@DOLPHIN_BACKEND@/${DOLPHIN_BACKEND}/g" -i ${INSTALL}/usr/bin/start_dolphin_gc.sh + sed -e "s/@DOLPHIN_BACKEND@/${DOLPHIN_BACKEND}/g" -i ${INSTALL}/usr/bin/start_dolphin_wii.sh + + sed -e "s/@GRENDERER@/${GRENDERER}/g" -i ${INSTALL}/usr/bin/start_dolphin_gc.sh + sed -e "s/@GRENDERER@/${GRENDERER}/g" -i ${INSTALL}/usr/bin/start_dolphin_wii.sh + + sed -e "s/@EXPORTS@/${EXPORTS}/g" \ + -i ${INSTALL}/usr/bin/start_dolphin_gc.sh + sed -e "s/@EXPORTS@/${EXPORTS}/g" \ + -i ${INSTALL}/usr/bin/start_dolphin_wii.sh +} diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/qt6/000-hotkeys.patch b/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/qt6/000-hotkeys.patch new file mode 100644 index 0000000000..f4fb78a1bd --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/qt6/000-hotkeys.patch @@ -0,0 +1,179 @@ +diff -rupN dolphin.orig/Source/Core/Core/HW/GCPadEmu.cpp dolphin/Source/Core/Core/HW/GCPadEmu.cpp +--- dolphin.orig/Source/Core/Core/HW/GCPadEmu.cpp 2024-03-27 04:51:20.527212738 +0000 ++++ dolphin/Source/Core/Core/HW/GCPadEmu.cpp 2024-03-27 06:07:26.630071515 +0000 +@@ -26,6 +26,7 @@ static const u16 button_bitmasks[] = { + PAD_BUTTON_Y, + PAD_TRIGGER_Z, + PAD_BUTTON_START, ++ PAD_BUTTON_HOTKEY, + 0 // MIC HAX + }; + +@@ -50,6 +51,9 @@ GCPad::GCPad(const unsigned int index) : + // i18n: The START/PAUSE button on GameCube controllers + m_buttons->AddInput(Translatability::Translate, START_BUTTON, _trans("START")); + ++ // Hotkey Button ++ m_buttons->AddInput(Translatability::Translate, HOTKEY_BUTTON, _trans("HOTKEY")); ++ + // sticks + groups.emplace_back(m_main_stick = new ControllerEmu::OctagonAnalogStick( + MAIN_STICK_GROUP, _trans("Control Stick"), MAIN_STICK_GATE_RADIUS)); +diff -rupN dolphin.orig/Source/Core/Core/HW/GCPadEmu.h dolphin/Source/Core/Core/HW/GCPadEmu.h +--- dolphin.orig/Source/Core/Core/HW/GCPadEmu.h 2024-03-27 04:51:20.527212738 +0000 ++++ dolphin/Source/Core/Core/HW/GCPadEmu.h 2024-03-27 05:15:39.652307739 +0000 +@@ -68,6 +68,7 @@ public: + static constexpr const char* Y_BUTTON = "Y"; + static constexpr const char* Z_BUTTON = "Z"; + static constexpr const char* START_BUTTON = "Start"; ++ static constexpr const char* HOTKEY_BUTTON = "Hotkey"; + + // i18n: The left trigger button (labeled L on real controllers) + static constexpr const char* L_DIGITAL = _trans("L"); +diff -rupN dolphin.orig/Source/Core/DolphinNoGUI/PlatformX11.cpp dolphin/Source/Core/DolphinNoGUI/PlatformX11.cpp +--- dolphin.orig/Source/Core/DolphinNoGUI/PlatformX11.cpp 2024-03-27 04:51:20.535212986 +0000 ++++ dolphin/Source/Core/DolphinNoGUI/PlatformX11.cpp 2024-03-27 12:56:29.701030775 +0000 +@@ -15,7 +15,14 @@ static constexpr auto X_None = None; + #include "Core/Config/MainSettings.h" + #include "Core/Core.h" + #include "Core/State.h" ++ + #include "Core/System.h" ++#include "Core/HW/GCPad.h" ++#include "InputCommon/GCPadStatus.h" ++#include ++#include "Core/Config/GraphicsSettings.h" ++#include "VideoCommon/VideoConfig.h" ++#include "VideoCommon/OnScreenDisplay.h" + + #include + #include +@@ -151,11 +158,117 @@ void PlatformX11::MainLoop() + { + while (IsRunning()) + { ++ static int hotkey = 0; ++ static int slot = 0; ++ static int fps = 0; ++ static int aspect = 0; ++ static int fforward = 0; ++ static int ires = 0; ++ + UpdateRunningFlag(); + Core::HostDispatchJobs(Core::System::GetInstance()); + ProcessEvents(); + UpdateWindowPosition(); + ++ if(Pad::IsInitialized()) { ++ GCPadStatus x = Pad::GetStatus(0); ++ ++ if( (x.button & PAD_BUTTON_HOTKEY) == PAD_BUTTON_HOTKEY) { // hotkey pressed ++ if(hotkey == 1) { ++ hotkey = 2; ++ } ++ } else { ++ hotkey = 1; // assure hotkey is released between actions ++ } ++ ++ if(hotkey == 2) { // hotkey pressed ++ if( (x.button & PAD_BUTTON_START) == PAD_BUTTON_START) { ++ RequestShutdown(); ++ hotkey = 0; ++ } ++ ++ if( (x.button & PAD_TRIGGER_L) == PAD_TRIGGER_L) { ++ State::Load(Core::System::GetInstance(), slot); ++ hotkey = 0; ++ } ++ if( (x.button & PAD_TRIGGER_R) == PAD_TRIGGER_R) { ++ State::Save(Core::System::GetInstance(), slot); ++ hotkey = 0; ++ } ++ if( (x.button & PAD_BUTTON_DOWN) == PAD_BUTTON_DOWN) { ++ if(slot > 0) slot--; ++ Core::DisplayMessage(fmt::format("Slot {} selected", slot), 4000); ++ hotkey = 0; ++ } ++ if( (x.button & PAD_BUTTON_UP) == PAD_BUTTON_UP) { ++ if(slot < 10) slot++; ++ Core::DisplayMessage(fmt::format("Slot {} selected", slot), 4000); ++ hotkey = 0; ++ } ++ if( (x.button & PAD_BUTTON_A) == PAD_BUTTON_A) { ++ Core::SaveScreenShot(); ++ hotkey = 0; ++ } ++ if( (x.button & PAD_BUTTON_Y) == PAD_BUTTON_Y) { ++ if(fps == 0) { ++ Config::SetCurrent(Config::GFX_SHOW_FPS, True); ++ fps = 1; ++ } else { ++ Config::SetCurrent(Config::GFX_SHOW_FPS, False); ++ fps = 0; ++ } ++ hotkey = 0; ++ } ++ if( (x.button & PAD_BUTTON_X) == PAD_BUTTON_X) { ++ if(aspect == 0) { ++ Config::SetCurrent(Config::GFX_ASPECT_RATIO, AspectMode::Stretch); ++ aspect = 1; ++ } else { ++ Config::SetCurrent(Config::GFX_ASPECT_RATIO, AspectMode::Auto); ++ aspect = 0; ++ } ++ hotkey = 0; ++ } ++ if( (x.button & PAD_BUTTON_B) == PAD_BUTTON_B) { ++ if(ires == 0) { ++ Config::SetCurrent(Config::GFX_EFB_SCALE, 2); ++ OSD::AddMessage("Internal Resolution: 480P"); ++ ires = 2; ++ } ++ else if(ires == 2) { ++ Config::SetCurrent(Config::GFX_EFB_SCALE, 4); ++ OSD::AddMessage("Internal Resolution: 720P"); ++ ires = 4; ++ } ++ else if(ires == 4) { ++ Config::SetCurrent(Config::GFX_EFB_SCALE, 6); ++ OSD::AddMessage("Internal Resolution: 1080P"); ++ ires = 6; ++ } else { ++ Config::SetCurrent(Config::GFX_EFB_SCALE, 1); ++ OSD::AddMessage("Internal Resolution: 240P"); ++ ires = 0; ++ } ++ hotkey = 0; ++ } ++ if( (x.button & PAD_TRIGGER_Z) == PAD_TRIGGER_Z) { ++ if(fforward == 0) { ++ auto speed = Config::Get(Config::MAIN_EMULATION_SPEED) + 1.0; ++ speed = (speed >= 0.95 && speed <= 1.05) ? 1.0 : speed; ++ Config::SetCurrent(Config::MAIN_EMULATION_SPEED, speed); ++ OSD::AddMessage("Fast Forward: ON"); ++ fforward = 1; ++ } else { ++ auto speed = Config::Get(Config::MAIN_EMULATION_SPEED) - 1.0; ++ speed = (speed <= 0 || (speed >= 0.95 && speed <= 1.05)) ? 1.0 : speed; ++ Config::SetCurrent(Config::MAIN_EMULATION_SPEED, speed); ++ OSD::AddMessage("Fast Forward: OFF"); ++ fforward = 0; ++ } ++ hotkey = 0; ++ } ++ } ++ } + // TODO: Is this sleep appropriate? + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } +diff -rupN dolphin.orig/Source/Core/InputCommon/GCPadStatus.h dolphin/Source/Core/InputCommon/GCPadStatus.h +--- dolphin.orig/Source/Core/InputCommon/GCPadStatus.h 2024-03-27 04:51:20.543213235 +0000 ++++ dolphin/Source/Core/InputCommon/GCPadStatus.h 2024-03-27 06:05:14.489860245 +0000 +@@ -26,6 +26,7 @@ enum PadButton + PAD_BUTTON_X = 0x0400, + PAD_BUTTON_Y = 0x0800, + PAD_BUTTON_START = 0x1000, ++ PAD_BUTTON_HOTKEY = 0x2000, + }; + + struct GCPadStatus diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/qt6/001-padorder.patch b/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/qt6/001-padorder.patch new file mode 100644 index 0000000000..187a57efca --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/qt6/001-padorder.patch @@ -0,0 +1,111 @@ +diff --git a/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp b/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp +index 6df37b4..64ade4a 100644 +--- a/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp ++++ b/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp +@@ -392,6 +392,65 @@ void Init() + StartHotplugThread(); + } + ++struct joypad_udev_entry ++{ ++ const char *devnode; ++ struct udev_device *dev; ++}; ++ ++int isNumber(const char *s) { ++ int n; ++ ++ if(strlen(s) == 0) { ++ return 0; ++ } ++ ++ for(n=0; ndevnode, bb->devnode); ++} ++ + // Only call this when ControllerInterface::m_devices_population_mutex is locked + void PopulateDevices() + { +@@ -404,6 +463,10 @@ void PopulateDevices() + // We use udev to iterate over all /dev/input/event* devices. + // Note: the Linux kernel is currently limited to just 32 event devices. If + // this ever changes, hopefully udev will take care of this. ++ unsigned sorted_count = 0; ++ struct joypad_udev_entry sorted[64]; ++ const char* devnode; ++ int i; + + udev* const udev = udev_new(); + ASSERT_MSG(CONTROLLERINTERFACE, udev != nullptr, "Couldn't initialize libudev."); +@@ -422,11 +485,25 @@ void PopulateDevices() + + udev_device* dev = udev_device_new_from_syspath(udev, path); + +- if (const char* devnode = udev_device_get_devnode(dev)) +- AddDeviceNode(devnode); +- +- udev_device_unref(dev); ++ devnode = udev_device_get_devnode(dev); ++ if (devnode != NULL && sorted_count < 64) { ++ sorted[sorted_count].devnode = devnode; ++ sorted[sorted_count].dev = dev; ++ 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++) { ++ AddDeviceNode(sorted[i].devnode); ++ udev_device_unref(sorted[i].dev); ++ } ++ + udev_enumerate_unref(enumerate); + udev_unref(udev); + } diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/qt6/002-savestate-names.patch b/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/qt6/002-savestate-names.patch new file mode 100644 index 0000000000..e87521b4e3 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/qt6/002-savestate-names.patch @@ -0,0 +1,191 @@ +diff --git a/Source/Core/Core/BootManager.cpp b/Source/Core/Core/BootManager.cpp +index fc93d01a1e..915e77da77 100644 +--- a/Source/Core/Core/BootManager.cpp ++++ b/Source/Core/Core/BootManager.cpp +@@ -66,6 +66,11 @@ bool BootCore(Core::System& system, std::unique_ptr boot, + if (!StartUp.SetPathsAndGameMetadata(system, *boot)) + return false; + ++ if (std::holds_alternative(boot->parameters)) ++ { ++ StartUp.SetBaseSaveState(PathToFileName(std::get(boot->parameters).path)); ++ } ++ + // Movie settings + auto& movie = system.GetMovie(); + if (movie.IsPlayingInput() && movie.IsConfigSaved()) +diff --git a/Source/Core/Core/ConfigManager.cpp b/Source/Core/Core/ConfigManager.cpp +index 5a123c87cd..06890be2dd 100644 +--- a/Source/Core/Core/ConfigManager.cpp ++++ b/Source/Core/Core/ConfigManager.cpp +@@ -183,6 +183,10 @@ void SConfig::SetRunningGameMetadata(const std::string& game_id) + SetRunningGameMetadata(game_id, "", 0, 0, DiscIO::Region::Unknown); + } + ++void SConfig::SetBaseSaveState(const std::string& base_save_state) { ++ m_base_save_state = base_save_state; ++} ++ + void SConfig::SetRunningGameMetadata(const std::string& game_id, const std::string& gametdb_id, + u64 title_id, u16 revision, DiscIO::Region region) + { +diff --git a/Source/Core/Core/ConfigManager.h b/Source/Core/Core/ConfigManager.h +index d21b087a51..f0ce0b7e71 100644 +--- a/Source/Core/Core/ConfigManager.h ++++ b/Source/Core/Core/ConfigManager.h +@@ -63,6 +63,8 @@ struct SConfig + // TODO: remove this as soon as the ticket view hack in IOS/ES/Views is dropped. + bool m_disc_booted_from_game_list = false; + ++ const std::string& GetBaseSaveState() const { return m_base_save_state; } ++ void SetBaseSaveState(const std::string& base_save_state); + const std::string GetGameID() const; + const std::string GetGameTDBID() const; + const std::string GetTitleName() const; +@@ -118,6 +120,7 @@ private: + static SConfig* m_Instance; + mutable std::recursive_mutex m_metadata_lock; + ++ std::string m_base_save_state; + std::string m_game_id; + std::string m_gametdb_id; + std::string m_title_name; +diff --git a/Source/Core/Core/State.cpp b/Source/Core/Core/State.cpp +index a244fda1b6..13d5baa453 100644 +--- a/Source/Core/Core/State.cpp ++++ b/Source/Core/Core/State.cpp +@@ -248,11 +248,10 @@ static std::string SystemTimeAsDoubleToString(double time) + return fmt::format(std::locale{""}, "{:%x %X}", *local_time); + } + +-static std::string MakeStateFilename(int number) +-{ +- return fmt::format("{}{}.s{:02d}", File::GetUserPath(D_STATESAVES_IDX), +- SConfig::GetInstance().GetGameID(), number); +-} ++static std::string MakeStateFilename(bool useId, int number); ++static std::string MakeStateFilename_partdirectory(int number); ++static std::string MakeStateFilename_partfileName(int number); ++static std::string MakeStateFilename_partfileID(int number); + + static std::vector GetUsedSlotsWithTimestamp() + { +@@ -256,7 +259,7 @@ static std::vector GetUsedSlotsWithTimestamp() + StateHeader header; + for (int i = 1; i <= int(NUM_STATES); ++i) + { +- std::string filename = MakeStateFilename(i); ++ std::string filename = MakeStateFilename(true, i); + if (!File::Exists(filename) || !ReadHeader(filename, header)) + continue; + +@@ -525,7 +528,7 @@ std::string GetInfoStringOfSlot(int slot, bool translate) + { + std::lock_guard lk{s_state_saves_in_progress}; + +- std::string filename = MakeStateFilename(slot); ++ std::string filename = MakeStateFilename(true, slot); + if (!File::Exists(filename)) + return translate ? Common::GetStringT("Empty") : "Empty"; + +@@ -538,6 +541,6 @@ u64 GetUnixTimeOfSlot(int slot) + + State::StateHeader header; +- if (!ReadHeader(MakeStateFilename(slot), header)) ++ if (!ReadHeader(MakeStateFilename(true, slot), header)) + return 0; + + constexpr u64 MS_PER_SEC = 1000; +@@ -703,52 +706,88 @@ void Shutdown() + s_flush_unsaved_data_hook.reset(); + } + ++static std::string MakeStateFilename(bool useId, int number) ++{ ++ // Priority: file named by disc filename over file named by game ID. ++ // If the game was not loaded from a disc image, fall back to game ID. ++ std::string filePartName = MakeStateFilename_partfileName(number); ++ std::string fileWithName = ++ fmt::format("{}{}", MakeStateFilename_partdirectory(number), filePartName); ++ if (File::Exists(fileWithName) && filePartName != "") ++ return fileWithName; ++ std::string fileWithId = ++ fmt::format("{}{}", MakeStateFilename_partdirectory(number), MakeStateFilename_partfileID(number)); ++ if (File::Exists(fileWithId) && useId) ++ return fileWithId; ++ if (filePartName == "") ++ return fileWithId; ++ return fileWithName; ++} ++ ++static std::string MakeStateFilename_partdirectory(int number) ++{ ++ return File::GetUserPath(D_STATESAVES_IDX); ++} ++ ++static std::string MakeStateFilename_partfileID(int number) ++{ ++ return fmt::format("{}.s{:02d}", SConfig::GetInstance().GetGameID(), number); ++} ++ ++static std::string MakeStateFilename_partfileName(int number) ++{ ++ std::string basesavestate = SConfig::GetInstance().GetBaseSaveState(); ++ if (basesavestate == "") ++ return ""; ++ return fmt::format("{}.s{:02d}", basesavestate, number); ++} ++ + void Save(Core::System& system, int slot) + { +- SaveAs(system, MakeStateFilename(slot)); ++ SaveAs(system, MakeStateFilename(false, slot)); + } + + void Load(Core::System& system, int slot) + { +- LoadAs(system, MakeStateFilename(slot)); ++ LoadAs(system, MakeStateFilename(true, slot)); + } + + void LoadLastSaved(Core::System& system, int i) + { + if (!CheckIfStateLoadIsAllowed(system)) + return; + + Core::RunOnCPUThread(system, [&system, i] { + // Data must reach the filesystem for up to date "UsedSlots". + s_compress_and_dump_thread.WaitForCompletion(); + + std::vector used_slots = GetUsedSlotsWithTimestamp(); + if (std::size_t(i) > used_slots.size()) + { + Core::DisplayMessage("State doesn't exist", 2000); + return; + } + + std::ranges::stable_sort(used_slots, std::ranges::greater{}, &SlotWithTimestamp::timestamp); +- LoadAsFromCore(system, MakeStateFilename(used_slots[i].slot)); ++ LoadAsFromCore(system, MakeStateFilename(true, used_slots[i].slot)); + }); + } + + void SaveFirstSaved(Core::System& system) + { + Core::RunOnCPUThread(system, [&system, lock = GetStateSaveTaskLock()] { + // Data must reach the filesystem for up to date "UsedSlots". + s_compress_and_dump_thread.WaitForCompletion(); + + std::vector used_slots = GetUsedSlotsWithTimestamp(); + auto slot = GetEmptySlot(used_slots); + if (!slot.has_value()) + { + // overwrite the oldest state + std::ranges::stable_sort(used_slots, {}, &SlotWithTimestamp::timestamp); + slot = used_slots.front().slot; + } + +- SaveAsFromCore(system, MakeStateFilename(*slot)); ++ SaveAsFromCore(system, MakeStateFilename(false, *slot)); + }); + } diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/qt6/003-hide-osd-msg.patch b/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/qt6/003-hide-osd-msg.patch new file mode 100644 index 0000000000..8da14f3922 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/qt6/003-hide-osd-msg.patch @@ -0,0 +1,14 @@ +diff -rupN dolphin.orig/Source/Core/VideoBackends/OGL/OGLConfig.cpp dolphin/Source/Core/VideoBackends/OGL/OGLConfig.cpp +--- dolphin.orig/Source/Core/VideoBackends/OGL/OGLConfig.cpp 2024-06-17 15:48:10.116157156 +0000 ++++ dolphin/Source/Core/VideoBackends/OGL/OGLConfig.cpp 2024-06-17 16:21:36.934162183 +0000 +@@ -726,10 +726,6 @@ bool PopulateConfig(GLContext* m_main_gl + g_Config.VerifyValidity(); + UpdateActiveConfig(); + +- OSD::AddMessage(fmt::format("Video Info: {}, {}, {}", g_ogl_config.gl_vendor, +- g_ogl_config.gl_renderer, g_ogl_config.gl_version), +- 5000); +- + if (!g_ogl_config.bSupportsGLBufferStorage && !g_ogl_config.bSupportsGLPinnedMemory) + { + OSD::AddMessage(fmt::format("Your OpenGL driver does not support {}_buffer_storage.", diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/qt6/004-enable-240p-res.patch b/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/qt6/004-enable-240p-res.patch new file mode 100644 index 0000000000..518f51482e --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/qt6/004-enable-240p-res.patch @@ -0,0 +1,161 @@ +diff -rupN dolphin.orig/Source/Core/VideoCommon/FramebufferManager.cpp dolphin/Source/Core/VideoCommon/FramebufferManager.cpp +--- dolphin.orig/Source/Core/VideoCommon/FramebufferManager.cpp 2024-06-17 15:48:10.120157247 +0000 ++++ dolphin/Source/Core/VideoCommon/FramebufferManager.cpp 2024-06-17 17:17:45.953589800 +0000 +@@ -185,19 +185,24 @@ FramebufferManager::ConvertEFBRectangle( + return result; + } + +-unsigned int FramebufferManager::GetEFBScale() const ++bool FramebufferManager::IsUnscaled() const + { +- return m_efb_scale; ++ return m_efb_scale == 2; ++} ++ ++float FramebufferManager::GetEFBScalef() const ++{ ++ return m_efb_scale / 2.0f; + } + + int FramebufferManager::EFBToScaledX(int x) const + { +- return x * static_cast(m_efb_scale); ++ return x * static_cast(m_efb_scale) / 2; + } + + int FramebufferManager::EFBToScaledY(int y) const + { +- return y * static_cast(m_efb_scale); ++ return y * static_cast(m_efb_scale) / 2;; + } + + float FramebufferManager::EFBToScaledXf(float x) const +@@ -221,8 +226,8 @@ std::tuple FramebufferManager: + if (max_size < EFB_WIDTH * m_efb_scale) + m_efb_scale = max_size / EFB_WIDTH; + +- u32 new_efb_width = std::max(EFB_WIDTH * static_cast(m_efb_scale), 1u); +- u32 new_efb_height = std::max(EFB_HEIGHT * static_cast(m_efb_scale), 1u); ++ u32 new_efb_width = std::max(EFB_WIDTH * static_cast(m_efb_scale) / 2, 1u); ++ u32 new_efb_height = std::max(EFB_HEIGHT * static_cast(m_efb_scale) / 2, 1u); + + return std::make_tuple(new_efb_width, new_efb_height); + } +@@ -695,7 +700,8 @@ void FramebufferManager::DestroyReadback + + bool FramebufferManager::CreateReadbackFramebuffer() + { +- if (GetEFBScale() != 1) ++ //if (GetEFBScale() != 1) ++ if (IsUnscaled()) + { + const TextureConfig color_config(IsUsingTiledEFBCache() ? m_efb_cache_tile_size : EFB_WIDTH, + IsUsingTiledEFBCache() ? m_efb_cache_tile_size : EFB_HEIGHT, 1, +@@ -717,7 +723,8 @@ bool FramebufferManager::CreateReadbackF + (IsUsingTiledEFBCache() && !g_ActiveConfig.backend_info.bSupportsPartialDepthCopies) || + !AbstractTexture::IsCompatibleDepthAndColorFormats(m_efb_depth_texture->GetFormat(), + GetEFBDepthCopyFormat()) || +- GetEFBScale() != 1) ++ //GetEFBScale() != 1) ++ IsUnscaled()) + { + const TextureConfig depth_config(IsUsingTiledEFBCache() ? m_efb_cache_tile_size : EFB_WIDTH, + IsUsingTiledEFBCache() ? m_efb_cache_tile_size : EFB_HEIGHT, 1, +@@ -800,7 +807,8 @@ void FramebufferManager::PopulateEFBCach + const MathUtil::Rectangle native_rect = ConvertEFBRectangle(rect); + AbstractTexture* src_texture = + depth ? ResolveEFBDepthTexture(native_rect) : ResolveEFBColorTexture(native_rect); +- if (GetEFBScale() != 1 || force_intermediate_copy) ++ //if (GetEFBScale() != 1 || force_intermediate_copy) ++ if (IsUnscaled() || force_intermediate_copy) + { + // Downsample from internal resolution to 1x. + // TODO: This won't produce correct results at IRs above 2x. More samples are required. +@@ -989,7 +997,7 @@ void FramebufferManager::CreatePokeVerti + // GPU will expand the point to a quad. + const float cs_x = (static_cast(x) + 0.5f) * cs_pixel_width - 1.0f; + const float cs_y = 1.0f - (static_cast(y) + 0.5f) * cs_pixel_height; +- const float point_size = static_cast(GetEFBScale()); ++ const float point_size = GetEFBScalef(); + destination_list->push_back({{cs_x, cs_y, z, point_size}, color}); + return; + } +diff -rupN dolphin.orig/Source/Core/VideoCommon/FramebufferManager.h dolphin/Source/Core/VideoCommon/FramebufferManager.h +--- dolphin.orig/Source/Core/VideoCommon/FramebufferManager.h 2024-06-17 15:48:10.120157247 +0000 ++++ dolphin/Source/Core/VideoCommon/FramebufferManager.h 2024-06-17 17:14:56.241373087 +0000 +@@ -74,7 +74,8 @@ public: + // Use this to convert a whole native EFB rect to backbuffer coordinates + MathUtil::Rectangle ConvertEFBRectangle(const MathUtil::Rectangle& rc) const; + +- unsigned int GetEFBScale() const; ++ bool IsUnscaled() const; ++ float GetEFBScalef() const; + + // Use this to upscale native EFB coordinates to IDEAL internal resolution + int EFBToScaledX(int x) const; +@@ -194,7 +195,8 @@ protected: + void DoLoadState(PointerWrap& p); + void DoSaveState(PointerWrap& p); + +- float m_efb_scale = 1.0f; ++ //float m_efb_scale = 1.0f; ++ float m_efb_scale = 2.0f; + PixelFormat m_prev_efb_format; + + std::unique_ptr m_efb_color_texture; +diff -rupN dolphin.orig/Source/Core/VideoCommon/Present.cpp dolphin/Source/Core/VideoCommon/Present.cpp +--- dolphin.orig/Source/Core/VideoCommon/Present.cpp 2024-06-17 15:48:10.120157247 +0000 ++++ dolphin/Source/Core/VideoCommon/Present.cpp 2024-06-17 17:19:31.308204563 +0000 +@@ -78,7 +78,7 @@ static void TryToSnapToXFBSize(int& widt + // The reason why the threshold is 1 pixel (per internal resolution multiplier) is because of + // minor inaccuracies of the VI aspect ratio (and because some resolutions are rounded + // while other are floored). +- const unsigned int efb_scale = g_framebuffer_manager->GetEFBScale(); ++ const unsigned int efb_scale = g_framebuffer_manager->GetEFBScalef(); + const unsigned int pixel_difference_width = std::abs(width - xfb_width); + const unsigned int pixel_difference_height = std::abs(height - xfb_height); + // We ignore this if there's an offset on both hor and ver size, +diff -rupN dolphin.orig/Source/Core/VideoCommon/TextureCacheBase.cpp dolphin/Source/Core/VideoCommon/TextureCacheBase.cpp +--- dolphin.orig/Source/Core/VideoCommon/TextureCacheBase.cpp 2024-06-17 15:48:10.120157247 +0000 ++++ dolphin/Source/Core/VideoCommon/TextureCacheBase.cpp 2024-06-17 17:01:12.572725778 +0000 +@@ -1066,7 +1066,8 @@ SamplerState TextureCacheBase::GetSample + // that have arbitrary contents, eg. are used for fog effects where the + // distance they kick in at is important to preserve at any resolution. + // Correct this with the upscaling factor of custom textures. +- s32 lod_offset = std::log2(g_framebuffer_manager->GetEFBScale() / custom_tex_scale) * 256.f; ++ //s32 lod_offset = std::log2(g_framebuffer_manager->GetEFBScale() / custom_tex_scale) * 256.f; ++ s64 lod_offset = std::log2(g_framebuffer_manager->GetEFBScalef() / custom_tex_scale) * (s64) 256.f; + state.tm0.lod_bias = std::clamp(state.tm0.lod_bias + lod_offset, -32768, 32767); + + // Anisotropic also pushes mips farther away so it cannot be used either +@@ -2349,7 +2350,8 @@ void TextureCacheBase::CopyRenderTargetT + // complex down filtering to average all pixels and produce the correct result. + const bool linear_filter = + !is_depth_copy && +- (scaleByHalf || g_framebuffer_manager->GetEFBScale() != 1 || y_scale > 1.0f); ++ //(scaleByHalf || g_framebuffer_manager->GetEFBScale() != 1 || y_scale > 1.0f); ++ (scaleByHalf || g_framebuffer_manager->IsUnscaled() || y_scale > 1.0f); + + RcTcacheEntry entry; + if (copy_to_vram) +diff -rupN dolphin.orig/Source/Core/VideoCommon/VideoConfig.cpp dolphin/Source/Core/VideoCommon/VideoConfig.cpp +--- dolphin.orig/Source/Core/VideoCommon/VideoConfig.cpp 2024-06-17 15:48:10.120157247 +0000 ++++ dolphin/Source/Core/VideoCommon/VideoConfig.cpp 2024-06-17 17:20:19.009387860 +0000 +@@ -355,7 +355,7 @@ void CheckForConfigChanges() + if (changed_bits == 0) + return; + +- float old_scale = g_framebuffer_manager->GetEFBScale(); ++ float old_scale = g_framebuffer_manager->GetEFBScalef(); + + // Framebuffer changed? + if (changed_bits & (CONFIG_CHANGE_BIT_MULTISAMPLES | CONFIG_CHANGE_BIT_STEREO_MODE | +@@ -364,7 +364,7 @@ void CheckForConfigChanges() + g_framebuffer_manager->RecreateEFBFramebuffer(); + } + +- if (old_scale != g_framebuffer_manager->GetEFBScale()) ++ if (old_scale != g_framebuffer_manager->GetEFBScalef()) + { + auto& system = Core::System::GetInstance(); + auto& pixel_shader_manager = system.GetPixelShaderManager(); diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/qt6/005-set-defaults.patch b/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/qt6/005-set-defaults.patch new file mode 100644 index 0000000000..37106e7e1a --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/qt6/005-set-defaults.patch @@ -0,0 +1,15 @@ +diff --git a/Source/Core/Core/Config/MainSettings.cpp b/Source/Core/Core/Config/MainSettings.cpp +index 6d5f260f07..7358a9ea41 100644 +--- a/Source/Core/Core/Config/MainSettings.cpp ++++ b/Source/Core/Core/Config/MainSettings.cpp +@@ -431,8 +431,8 @@ const Info MAIN_USE_PANIC_HANDLERS{{System::Main, "Interface", "UsePanicHa + const Info MAIN_ABORT_ON_PANIC_ALERT{{System::Main, "Interface", "AbortOnPanicAlert"}, false}; + const Info MAIN_OSD_MESSAGES{{System::Main, "Interface", "OnScreenDisplayMessages"}, true}; + const Info MAIN_OSD_FONT_SIZE{{System::Main, "Settings", "OSDFontSize"}, 13}; +-const Info MAIN_SKIP_NKIT_WARNING{{System::Main, "Interface", "SkipNKitWarning"}, false}; +-const Info MAIN_CONFIRM_ON_STOP{{System::Main, "Interface", "ConfirmStop"}, true}; ++const Info MAIN_SKIP_NKIT_WARNING{{System::Main, "Interface", "SkipNKitWarning"}, true}; ++const Info MAIN_CONFIRM_ON_STOP{{System::Main, "Interface", "ConfirmStop"}, false}; + const Info MAIN_SHOW_CURSOR{{System::Main, "Interface", "CursorVisibility"}, + ShowCursor::OnMovement}; + const Info MAIN_LOCK_CURSOR{{System::Main, "Interface", "LockCursor"}, false}; diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/qt6/006-dolphin-version.patch b/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/qt6/006-dolphin-version.patch new file mode 100644 index 0000000000..a2d8f3c796 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/qt6/006-dolphin-version.patch @@ -0,0 +1,19 @@ +diff --git a/CMake/ScmRevGen.cmake b/CMake/ScmRevGen.cmake +index 12ee7727b2..889cc02b52 100644 +--- a/CMake/ScmRevGen.cmake ++++ b/CMake/ScmRevGen.cmake +@@ -37,12 +37,12 @@ set(DOLPHIN_VERSION_PATCH ${DOLPHIN_WC_REVISION}) + + # If Dolphin is not built from a Git repository, default the version info to + # reasonable values. +-if(NOT DOLPHIN_WC_REVISION) ++#if(NOT DOLPHIN_WC_REVISION) + set(DOLPHIN_WC_DESCRIBE "${DOLPHIN_VERSION_MAJOR}.${DOLPHIN_VERSION_MINOR}") + set(DOLPHIN_WC_REVISION "${DOLPHIN_WC_DESCRIBE} (no further info)") + set(DOLPHIN_WC_BRANCH "master") + set(DOLPHIN_WC_COMMITS_AHEAD_MASTER 0) +-endif() ++#endif() + + # If this is a tag (i.e. a release), then set the current patch version and + # the number of commits ahead to zero. diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/qt6/007-fix-qt.patch b/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/qt6/007-fix-qt.patch new file mode 100644 index 0000000000..6ec4c865ad --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/qt6/007-fix-qt.patch @@ -0,0 +1,13 @@ +diff --git a/Source/Core/DolphinQt/Resources.cpp b/Source/Core/DolphinQt/Resources.cpp +index 84fbcc8df8..21c82a1484 100644 +--- a/Source/Core/DolphinQt/Resources.cpp ++++ b/Source/Core/DolphinQt/Resources.cpp +@@ -50,7 +50,7 @@ QIcon Resources::LoadNamedIcon(std::string_view name, const QString& dir) + for (auto scale : {1, 2, 4}) + load_png(scale); + +- ASSERT(icon.availableSizes().size() > 0); ++ //ASSERT(icon.availableSizes().size() > 0); + + return icon; + } diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/qt6/008-bios-dir.patch b/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/qt6/008-bios-dir.patch new file mode 100644 index 0000000000..d9be1c4668 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/qt6/008-bios-dir.patch @@ -0,0 +1,35 @@ +diff --git a/Source/Core/Core/Boot/Boot.cpp b/Source/Core/Core/Boot/Boot.cpp +index b21d15478..5b62db919 100644 +--- a/Source/Core/Core/Boot/Boot.cpp ++++ b/Source/Core/Core/Boot/Boot.cpp +@@ -423,7 +423,7 @@ bool CBoot::Load_BS2(Core::System& system, const std::string& boot_rom_filename) + known_ipl = true; + break; + default: +- PanicAlertFmtT("The IPL file is not a known good dump. (CRC32: {0:x})", ipl_hash); ++ known_ipl = true; + break; + } + +@@ -598,7 +598,7 @@ bool CBoot::BootUp(Core::System& system, std::unique_ptr boot) + if (!File::Exists(ipl.path)) + { + if (ipl.disc) +- PanicAlertFmtT("Cannot start the game, because the GC IPL could not be found."); ++ PanicAlertFmtT("Gamecube bios not found, please add your IPL.bin to /storage/roms/bios/GC/(USA/JAP/EUR)/."); + else + PanicAlertFmtT("Cannot find the GC IPL."); + return false; +diff --git a/Source/Core/Core/Config/MainSettings.cpp b/Source/Core/Core/Config/MainSettings.cpp +index 0442347fdd..af148e79f9 100644 +--- a/Source/Core/Core/Config/MainSettings.cpp ++++ b/Source/Core/Core/Config/MainSettings.cpp +@@ -616,7 +616,7 @@ const char* GetDirectoryForRegion(DiscIO::Region region, RegionDirectoryStyle st + std::string GetBootROMPath(const std::string& region_directory) + { + const std::string path = +- File::GetUserPath(D_GCUSER_IDX) + DIR_SEP + region_directory + DIR_SEP GC_IPL; ++ std::string("/storage/roms/bios/GC/") + DIR_SEP + region_directory + DIR_SEP + GC_IPL; + if (!File::Exists(path)) + return File::GetSysDirectory() + GC_SYS_DIR + DIR_SEP + region_directory + DIR_SEP GC_IPL; + return path; diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/qt6/009-supress-warnings.patch b/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/qt6/009-supress-warnings.patch new file mode 100644 index 0000000000..d330842e2a --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/qt6/009-supress-warnings.patch @@ -0,0 +1,253 @@ +diff --git a/Source/Core/Core/HW/DVD/AMMediaboard.cpp b/Source/Core/Core/HW/DVD/AMMediaboard.cpp +index 5cd69f8a62..ebea8a3736 100644 +--- a/Source/Core/Core/HW/DVD/AMMediaboard.cpp ++++ b/Source/Core/Core/HW/DVD/AMMediaboard.cpp +@@ -472,19 +472,19 @@ void Init() + // This is the firmware for the Triforce + const std::string sega_boot_filename = base_path + "segaboot.gcm"; + +- if (!File::Exists(sega_boot_filename)) +- { +- PanicAlertFmt("Failed to open segaboot.gcm({}), which is required for test menus.", +- sega_boot_filename.c_str()); +- return; +- } ++ //if (!File::Exists(sega_boot_filename)) ++ //{ ++ // PanicAlertFmt("Failed to open segaboot.gcm({}), which is required for test menus.", ++ // sega_boot_filename.c_str()); ++ // return; ++ //} + + File::IOFile sega_boot(sega_boot_filename, "rb+"); +- if (!sega_boot.IsOpen()) +- { +- PanicAlertFmt("Failed to read: {}", sega_boot_filename); +- return; +- } ++ //if (!sega_boot.IsOpen()) ++ //{ ++ // PanicAlertFmt("Failed to read: {}", sega_boot_filename); ++ // return; ++ //} + + const u64 length = std::min(sega_boot.GetSize(), sizeof(s_firmware)); + sega_boot.ReadBytes(s_firmware.data(), length); +diff --git a/Source/Core/Core/HW/EXI/EXI_DeviceIPL.cpp b/Source/Core/Core/HW/EXI/EXI_DeviceIPL.cpp +index 82650ff1a0..587d1d577e 100644 +--- a/Source/Core/Core/HW/EXI/EXI_DeviceIPL.cpp ++++ b/Source/Core/Core/HW/EXI/EXI_DeviceIPL.cpp +@@ -328,16 +328,16 @@ void CEXIIPL::TransferByte(u8& data) + + if ((dev_addr >= 0x001AFF00) && (dev_addr <= 0x001FF474) && !m_fonts_loaded) + { +- if (dev_addr >= 0x001FCF00) +- { +- PanicAlertFmtT("Error: Trying to access Windows-1252 fonts but they are not loaded. " +- "Games may not show fonts correctly, or crash."); +- } +- else +- { +- PanicAlertFmtT("Error: Trying to access Shift JIS fonts but they are not loaded. " +- "Games may not show fonts correctly, or crash."); +- } ++ //if (dev_addr >= 0x001FCF00) ++ //{ ++ // PanicAlertFmtT("Error: Trying to access Windows-1252 fonts but they are not loaded. " ++ // "Games may not show fonts correctly, or crash."); ++ //} ++ //else ++ //{ ++ // PanicAlertFmtT("Error: Trying to access Shift JIS fonts but they are not loaded. " ++ // "Games may not show fonts correctly, or crash."); ++ //} + // Don't be a nag + m_fonts_loaded = true; + } +diff --git a/Source/Core/Core/HW/Memmap.cpp b/Source/Core/Core/HW/Memmap.cpp +index c7ec1debb0..17d740c158 100644 +--- a/Source/Core/Core/HW/Memmap.cpp ++++ b/Source/Core/Core/HW/Memmap.cpp +@@ -149,9 +149,9 @@ void MemoryManager::Init() + + if (!*region.out_pointer) + { +- PanicAlertFmt( +- "Memory::Init(): Failed to create view for physical region at 0x{:08X} (size 0x{:08X}).", +- region.physical_address, region.size); ++ //PanicAlertFmt( ++ // "Memory::Init(): Failed to create view for physical region at 0x{:08X} (size 0x{:08X}).", ++ // region.physical_address, region.size); + exit(0); + } + +@@ -216,7 +216,7 @@ bool MemoryManager::InitFastmemArena() + m_fastmem_arena = m_arena.ReserveMemoryRegion(memory_size); + if (!m_fastmem_arena) + { +- PanicAlertFmt("Memory::InitFastmemArena(): Failed finding a memory base."); ++ //PanicAlertFmt("Memory::InitFastmemArena(): Failed finding a memory base."); + return false; + } + +@@ -233,9 +233,9 @@ bool MemoryManager::InitFastmemArena() + + if (base != view) + { +- PanicAlertFmt("Memory::InitFastmemArena(): Failed to map memory region at 0x{:08X} " +- "(size 0x{:08X}) into physical fastmem region.", +- region.physical_address, region.size); ++ //PanicAlertFmt("Memory::InitFastmemArena(): Failed to map memory region at 0x{:08X} " ++ // "(size 0x{:08X}) into physical fastmem region.", ++ // region.physical_address, region.size); + return false; + } + } +@@ -302,9 +302,9 @@ void MemoryManager::UpdateDBATMappings(const PowerPC::BatTable& dbat_table) + void* mapped_pointer = m_arena.MapInMemoryRegion(position, mapped_size, base, true); + if (!mapped_pointer) + { +- PanicAlertFmt("Memory::UpdateDBATMappings(): Failed to map memory region at 0x{:08X} " +- "(size 0x{:08X}) into logical fastmem region at 0x{:08X}.", +- intersection_start, mapped_size, logical_address); ++ //PanicAlertFmt("Memory::UpdateDBATMappings(): Failed to map memory region at 0x{:08X} " ++ // "(size 0x{:08X}) into logical fastmem region at 0x{:08X}.", ++ // intersection_start, mapped_size, logical_address); + continue; + } + m_dbat_mapped_entries.emplace(logical_address, +@@ -629,7 +629,7 @@ u8* MemoryManager::GetPointerForRange(u32 address, size_t size) const + if (span.size() < size) + { + // The start address is in a valid region, but the end address is beyond the end of that region. +- PanicAlertFmt("Oversized range in GetPointerForRange. {:x} bytes at {:#010x}", size, address); ++ //PanicAlertFmt("Oversized range in GetPointerForRange. {:x} bytes at {:#010x}", size, address); + return nullptr; + } + +@@ -644,7 +644,7 @@ void MemoryManager::CopyFromEmu(void* data, u32 address, size_t size) const + void* pointer = GetPointerForRange(address, size); + if (!pointer) + { +- PanicAlertFmt("Invalid range in CopyFromEmu. {:x} bytes from {:#010x}", size, address); ++ //PanicAlertFmt("Invalid range in CopyFromEmu. {:x} bytes from {:#010x}", size, address); + return; + } + memcpy(data, pointer, size); +@@ -658,7 +658,7 @@ void MemoryManager::CopyToEmu(u32 address, const void* data, size_t size) + void* pointer = GetPointerForRange(address, size); + if (!pointer) + { +- PanicAlertFmt("Invalid range in CopyToEmu. {:x} bytes to {:#010x}", size, address); ++ //PanicAlertFmt("Invalid range in CopyToEmu. {:x} bytes to {:#010x}", size, address); + return; + } + memcpy(pointer, data, size); +@@ -672,7 +672,7 @@ void MemoryManager::Memset(u32 address, u8 value, size_t size) + void* pointer = GetPointerForRange(address, size); + if (!pointer) + { +- PanicAlertFmt("Invalid range in Memset. {:x} bytes at {:#010x}", size, address); ++ //PanicAlertFmt("Invalid range in Memset. {:x} bytes at {:#010x}", size, address); + return; + } + memset(pointer, value, size); +@@ -723,8 +723,8 @@ std::span MemoryManager::GetSpanForAddress(u32 address) const + } + + auto& ppc_state = m_system.GetPPCState(); +- PanicAlertFmt("Unknown Pointer {:#010x} PC {:#010x} LR {:#010x}", address, ppc_state.pc, +- LR(ppc_state)); ++ //PanicAlertFmt("Unknown Pointer {:#010x} PC {:#010x} LR {:#010x}", address, ppc_state.pc, ++ // LR(ppc_state)); + return {}; + } + +diff --git a/Source/Core/VideoBackends/OGL/OGLTexture.cpp b/Source/Core/VideoBackends/OGL/OGLTexture.cpp +index 003a7ec442..5924317c24 100644 +--- a/Source/Core/VideoBackends/OGL/OGLTexture.cpp ++++ b/Source/Core/VideoBackends/OGL/OGLTexture.cpp +@@ -279,19 +279,19 @@ void OGLTexture::ResolveFromTexture(const AbstractTexture* src, + void OGLTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer, + size_t buffer_size, u32 layer) + { +- if (level >= m_config.levels) +- PanicAlertFmt("Texture only has {} levels, can't update level {}", m_config.levels, level); ++ //if (level >= m_config.levels) ++ // PanicAlertFmt("Texture only has {} levels, can't update level {}", m_config.levels, level); + +- if (layer >= m_config.layers) +- PanicAlertFmt("Texture only has {} layer, can't update layer {}", m_config.layers, layer); ++ //if (layer >= m_config.layers) ++ // PanicAlertFmt("Texture only has {} layer, can't update layer {}", m_config.layers, layer); + + const auto expected_width = std::max(1U, m_config.width >> level); + const auto expected_height = std::max(1U, m_config.height >> level); +- if (width != expected_width || height != expected_height) +- { +- PanicAlertFmt("Size of level {} must be {}x{}, but {}x{} requested", level, expected_width, +- expected_height, width, height); +- } ++ //if (width != expected_width || height != expected_height) ++ //{ ++ // PanicAlertFmt("Size of level {} must be {}x{}, but {}x{} requested", level, expected_width, ++ // expected_height, width, height); ++ //} + + const GLenum target = GetGLTarget(); + glActiveTexture(GL_MUTABLE_TEXTURE_INDEX); +@@ -343,10 +343,10 @@ void OGLTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8 + static_cast(buffer_size), buffer); + } + } +- else +- { +- PanicAlertFmt("Failed to handle compressed texture load - unhandled type"); +- } ++ //else ++ //{ ++ // PanicAlertFmt("Failed to handle compressed texture load - unhandled type"); ++ //} + } + else + { +@@ -389,10 +389,10 @@ void OGLTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8 + buffer); + } + } +- else +- { +- PanicAlertFmt("Failed to handle texture load - unhandled type"); +- } ++ //else ++ //{ ++ // PanicAlertFmt("Failed to handle texture load - unhandled type"); ++ //} + } + + if (row_length != width) +diff --git a/Source/Core/VideoCommon/CommandProcessor.cpp b/Source/Core/VideoCommon/CommandProcessor.cpp +index 0d91284038..376e009dd4 100644 +--- a/Source/Core/VideoCommon/CommandProcessor.cpp ++++ b/Source/Core/VideoCommon/CommandProcessor.cpp +@@ -704,13 +704,13 @@ void CommandProcessorManager::HandleUnknownOpcode(u8 cmd_byte, const u8* buffer, + "game from working, please report it to the developers."); + } + +- PanicAlertFmtT("GFX FIFO: Unknown Opcode ({0:#04x} @ {1}, preprocess={2}).\n" +- "\n" +- "{3}\n" +- "\n" +- "Further errors will be sent to the Video Backend log and " +- "Dolphin will now likely crash or hang.", +- cmd_byte, fmt::ptr(buffer), preprocess, Common::GetStringT(advice)); ++ //PanicAlertFmtT("GFX FIFO: Unknown Opcode ({0:#04x} @ {1}, preprocess={2}).\n" ++ // "\n" ++ // "{3}\n" ++ // "\n" ++ // "Further errors will be sent to the Video Backend log and " ++ // "Dolphin will now likely crash or hang.", ++ // cmd_byte, fmt::ptr(buffer), preprocess, Common::GetStringT(advice)); + } + } + diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/qt6/010-codehandlers-bin-path.patch b/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/qt6/010-codehandlers-bin-path.patch new file mode 100644 index 0000000000..847cdc319c --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/qt6/010-codehandlers-bin-path.patch @@ -0,0 +1,14 @@ +diff --git a/Source/Core/Core/GeckoCode.cpp b/Source/Core/Core/GeckoCode.cpp +index 62d2dc5481..411b1c6204 100644 +--- a/Source/Core/Core/GeckoCode.cpp ++++ b/Source/Core/Core/GeckoCode.cpp +@@ -109,7 +109,8 @@ std::vector SetAndReturnActiveCodes(std::span gcodes + static Installation InstallCodeHandlerLocked(const Core::CPUThreadGuard& guard) + { + std::string data; +- if (!File::ReadFileToString(File::GetSysDirectory() + GECKO_CODE_HANDLER, data)) ++ const std::string custom_handler_path = "/storage/.config/dolphin-emu/" GECKO_CODE_HANDLER; ++ if (!File::ReadFileToString(custom_handler_path, data)) + { + ERROR_LOG_FMT(ACTIONREPLAY, + "Could not enable cheats because " GECKO_CODE_HANDLER " was missing."); diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/wayland/000-add-wayland.patch b/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/wayland/000-add-wayland.patch new file mode 100644 index 0000000000..ffbb76dd7f --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/wayland/000-add-wayland.patch @@ -0,0 +1,5370 @@ +diff -rupN dolphin.orig/CMake/FindWaylandProtocols.cmake dolphin/CMake/FindWaylandProtocols.cmake +--- dolphin.orig/CMake/FindWaylandProtocols.cmake 1970-01-01 00:00:00.000000000 +0000 ++++ dolphin/CMake/FindWaylandProtocols.cmake 2024-03-05 04:06:08.240295843 +0000 +@@ -0,0 +1,28 @@ ++# from https://github.com/glfw/glfw/blob/master/CMake/modules/FindWaylandProtocols.cmake ++ ++find_package(PkgConfig) ++ ++pkg_check_modules(WaylandProtocols QUIET wayland-protocols>=${WaylandProtocols_FIND_VERSION}) ++ ++execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=pkgdatadir wayland-protocols ++ OUTPUT_VARIABLE WaylandProtocols_PKGDATADIR ++ RESULT_VARIABLE _pkgconfig_failed) ++if (_pkgconfig_failed) ++ message(FATAL_ERROR "Missing wayland-protocols pkgdatadir") ++endif() ++ ++string(REGEX REPLACE "[\r\n]" "" WaylandProtocols_PKGDATADIR "${WaylandProtocols_PKGDATADIR}") ++ ++find_package_handle_standard_args(WaylandProtocols ++ FOUND_VAR ++ WaylandProtocols_FOUND ++ REQUIRED_VARS ++ WaylandProtocols_PKGDATADIR ++ VERSION_VAR ++ WaylandProtocols_VERSION ++ HANDLE_COMPONENTS ++) ++ ++set(WAYLAND_PROTOCOLS_FOUND ${WaylandProtocols_FOUND}) ++set(WAYLAND_PROTOCOLS_PKGDATADIR ${WaylandProtocols_PKGDATADIR}) ++set(WAYLAND_PROTOCOLS_VERSION ${WaylandProtocols_VERSION}) +diff -rupN dolphin.orig/CMake/FindXKBCommon.cmake dolphin/CMake/FindXKBCommon.cmake +--- dolphin.orig/CMake/FindXKBCommon.cmake 1970-01-01 00:00:00.000000000 +0000 ++++ dolphin/CMake/FindXKBCommon.cmake 2024-03-05 04:06:08.240295843 +0000 +@@ -0,0 +1,33 @@ ++# - Try to find XKBCommon ++# Once done, this will define ++# ++# XKBCOMMON_FOUND - System has XKBCommon ++# XKBCOMMON_INCLUDE_DIRS - The XKBCommon include directories ++# XKBCOMMON_LIBRARIES - The libraries needed to use XKBCommon ++# XKBCOMMON_DEFINITIONS - Compiler switches required for using XKBCommon ++ ++find_package(PkgConfig) ++pkg_check_modules(PC_XKBCOMMON QUIET xkbcommon) ++set(XKBCOMMON_DEFINITIONS ${PC_XKBCOMMON_CFLAGS_OTHER}) ++ ++find_path(XKBCOMMON_INCLUDE_DIR ++ NAMES xkbcommon/xkbcommon.h ++ HINTS ${PC_XKBCOMMON_INCLUDE_DIR} ${PC_XKBCOMMON_INCLUDE_DIRS} ++) ++ ++find_library(XKBCOMMON_LIBRARY ++ NAMES xkbcommon ++ HINTS ${PC_XKBCOMMON_LIBRARY} ${PC_XKBCOMMON_LIBRARY_DIRS} ++) ++ ++set(XKBCOMMON_LIBRARIES ${XKBCOMMON_LIBRARY}) ++set(XKBCOMMON_LIBRARY_DIRS ${XKBCOMMON_LIBRARY_DIRS}) ++set(XKBCOMMON_INCLUDE_DIRS ${XKBCOMMON_INCLUDE_DIR}) ++ ++include(FindPackageHandleStandardArgs) ++find_package_handle_standard_args(XKBCommon DEFAULT_MSG ++ XKBCOMMON_LIBRARY ++ XKBCOMMON_INCLUDE_DIR ++) ++ ++mark_as_advanced(XKBCOMMON_LIBRARY XKBCOMMON_INCLUDE_DIR) +diff -rupN dolphin.orig/CMakeLists.txt dolphin/CMakeLists.txt +--- dolphin.orig/CMakeLists.txt 2024-03-05 04:05:25.878960469 +0000 ++++ dolphin/CMakeLists.txt 2024-03-05 04:06:08.240295843 +0000 +@@ -47,6 +47,7 @@ set(DOLPHIN_DEFAULT_UPDATE_TRACK "" CACH + + if(UNIX AND NOT APPLE AND NOT ANDROID) + option(ENABLE_X11 "Enables X11 Support" ON) ++ option(ENABLE_WAYLAND "Enables Wayland Support" OFF) + endif() + if(NOT WIN32 AND NOT APPLE AND NOT HAIKU) + option(ENABLE_EGL "Enables EGL OpenGL Interface" ON) +@@ -543,6 +544,17 @@ if(ENABLE_X11) + endif() + endif() + ++if(ENABLE_WAYLAND) ++ find_package(ECM REQUIRED NO_MODULE) ++ list(APPEND CMAKE_MODULE_PATH "${ECM_MODULE_PATH}") ++ find_package(Wayland REQUIRED Client Egl) ++ find_package(WaylandScanner REQUIRED) ++ find_package(WaylandProtocols 1.15 REQUIRED) ++ find_package(XKBCommon REQUIRED) ++ add_definitions(-DHAVE_WAYLAND=1) ++ message(STATUS "Wayland support enabled") ++endif() ++ + if(ENABLE_EGL) + find_package(EGL) + if(EGL_FOUND) +diff -rupN dolphin.orig/Source/Core/Common/CMakeLists.txt dolphin/Source/Core/Common/CMakeLists.txt +--- dolphin.orig/Source/Core/Common/CMakeLists.txt 2024-03-05 04:05:26.574982411 +0000 ++++ dolphin/Source/Core/Common/CMakeLists.txt 2024-03-05 04:06:08.240295843 +0000 +@@ -253,11 +253,20 @@ if(ENABLE_EGL AND EGL_FOUND) + GL/GLInterface/EGLAndroid.cpp + GL/GLInterface/EGLAndroid.h + ) +- elseif(ENABLE_X11 AND X11_FOUND) +- target_sources(common PRIVATE +- GL/GLInterface/EGLX11.cpp +- GL/GLInterface/EGLX11.h +- ) ++ else() ++ if(ENABLE_X11 AND X11_FOUND) ++ target_sources(common PRIVATE ++ GL/GLInterface/EGLX11.cpp ++ GL/GLInterface/EGLX11.h ++ ) ++ endif() ++ if(ENABLE_WAYLAND AND WAYLAND_FOUND) ++ target_sources(common PRIVATE ++ GL/GLInterface/EGLWayland.cpp ++ GL/GLInterface/EGLWayland.h ++ ) ++ target_link_libraries(common PRIVATE Wayland::Egl) ++ endif() + endif() + target_include_directories(common PRIVATE ${EGL_INCLUDE_DIRS}) + target_link_libraries(common PUBLIC ${EGL_LIBRARIES}) +diff -rupN dolphin.orig/Source/Core/Common/GL/GLContext.cpp dolphin/Source/Core/Common/GL/GLContext.cpp +--- dolphin.orig/Source/Core/Common/GL/GLContext.cpp 2024-03-05 04:05:26.578982537 +0000 ++++ dolphin/Source/Core/Common/GL/GLContext.cpp 2024-03-05 04:06:08.240295843 +0000 +@@ -25,6 +25,9 @@ + #if defined(ANDROID) + #include "Common/GL/GLInterface/EGLAndroid.h" + #endif ++#if HAVE_WAYLAND ++#include "Common/GL/GLInterface/EGLWayland.h" ++#endif + #endif + + const std::array, 9> GLContext::s_desktop_opengl_versions = { +@@ -57,11 +60,11 @@ bool GLContext::ClearCurrent() + return false; + } + +-void GLContext::Update() ++void GLContext::UpdateDimensions(int window_width, int window_height) + { + } + +-void GLContext::UpdateSurface(void* window_handle) ++void GLContext::UpdateSurface(void* window_handle, int window_width, int window_height) + { + } + +@@ -113,6 +116,10 @@ std::unique_ptr GLContext::Cr + #endif + } + #endif ++#if HAVE_WAYLAND ++ if (wsi.type == WindowSystemType::Wayland) ++ context = std::make_unique(); ++#endif + #if HAVE_EGL + if (wsi.type == WindowSystemType::Headless || wsi.type == WindowSystemType::FBDev) + context = std::make_unique(); +diff -rupN dolphin.orig/Source/Core/Common/GL/GLContext.h dolphin/Source/Core/Common/GL/GLContext.h +--- dolphin.orig/Source/Core/Common/GL/GLContext.h 2024-03-05 04:05:26.578982537 +0000 ++++ dolphin/Source/Core/Common/GL/GLContext.h 2024-03-05 04:06:08.240295843 +0000 +@@ -36,8 +36,8 @@ public: + virtual bool MakeCurrent(); + virtual bool ClearCurrent(); + +- virtual void Update(); +- virtual void UpdateSurface(void* window_handle); ++ virtual void UpdateDimensions(int window_width, int window_height); ++ virtual void UpdateSurface(void* window_handle, int window_width, int window_height); + + virtual void Swap(); + virtual void SwapInterval(int interval); +diff -rupN dolphin.orig/Source/Core/Common/GL/GLInterface/AGL.h dolphin/Source/Core/Common/GL/GLInterface/AGL.h +--- dolphin.orig/Source/Core/Common/GL/GLInterface/AGL.h 2024-03-05 04:05:26.578982537 +0000 ++++ dolphin/Source/Core/Common/GL/GLInterface/AGL.h 2024-03-05 04:06:08.240295843 +0000 +@@ -27,6 +27,8 @@ public: + + bool MakeCurrent() override; + bool ClearCurrent() override; ++ ++ void UpdateDimensions(int window_width, int window_height) override; + + void Update() override; + +diff -rupN dolphin.orig/Source/Core/Common/GL/GLInterface/AGL.mm dolphin/Source/Core/Common/GL/GLInterface/AGL.mm +--- dolphin.orig/Source/Core/Common/GL/GLInterface/AGL.mm 2024-03-05 04:05:26.578982537 +0000 ++++ dolphin/Source/Core/Common/GL/GLInterface/AGL.mm 2024-03-05 04:06:08.240295843 +0000 +@@ -144,7 +144,7 @@ bool GLContextAGL::ClearCurrent() + return true; + } + +-void GLContextAGL::Update() ++void GLContextAGL::UpdateDimensions(int window_width, int window_height) + { + if (!m_view) + return; +diff -rupN dolphin.orig/Source/Core/Common/GL/GLInterface/EGL.cpp dolphin/Source/Core/Common/GL/GLInterface/EGL.cpp +--- dolphin.orig/Source/Core/Common/GL/GLInterface/EGL.cpp 2024-03-05 04:05:26.578982537 +0000 ++++ dolphin/Source/Core/Common/GL/GLInterface/EGL.cpp 2024-03-05 04:06:08.240295843 +0000 +@@ -292,8 +292,8 @@ bool GLContextEGL::CreateWindowSurface() + { + if (!IsHeadless()) + { +- EGLNativeWindowType native_window = GetEGLNativeWindow(m_config); +- m_egl_surface = eglCreateWindowSurface(m_egl_display, m_config, native_window, nullptr); ++ m_native_window = GetEGLNativeWindow(m_config); ++ m_egl_surface = eglCreateWindowSurface(m_egl_display, m_config, m_native_window, nullptr); + if (!m_egl_surface) + { + INFO_LOG_FMT(VIDEO, "Error: eglCreateWindowSurface failed"); +@@ -301,15 +301,7 @@ bool GLContextEGL::CreateWindowSurface() + } + + // Get dimensions from the surface. +- EGLint surface_width = 1, surface_height = 1; +- if (!eglQuerySurface(m_egl_display, m_egl_surface, EGL_WIDTH, &surface_width) || +- !eglQuerySurface(m_egl_display, m_egl_surface, EGL_HEIGHT, &surface_height)) +- { +- WARN_LOG_FMT(VIDEO, +- "Failed to get surface dimensions via eglQuerySurface. Size may be incorrect."); +- } +- m_backbuffer_width = static_cast(surface_width); +- m_backbuffer_height = static_cast(surface_height); ++ QueryDimensions(); + } + else if (!m_supports_surfaceless) + { +@@ -347,9 +339,16 @@ bool GLContextEGL::MakeCurrent() + return eglMakeCurrent(m_egl_display, m_egl_surface, m_egl_surface, m_egl_context); + } + +-void GLContextEGL::UpdateSurface(void* window_handle) ++void GLContextEGL::UpdateDimensions(int window_width, int window_height) ++{ ++ QueryDimensions(); ++} ++ ++void GLContextEGL::UpdateSurface(void* window_handle, int window_width, int window_height) + { + m_wsi.render_surface = window_handle; ++ m_wsi.render_surface_width = window_width; ++ m_wsi.render_surface_height = window_height; + ClearCurrent(); + DestroyWindowSurface(); + CreateWindowSurface(); +@@ -376,3 +375,15 @@ void GLContextEGL::DestroyContext() + m_egl_context = EGL_NO_CONTEXT; + m_egl_display = EGL_NO_DISPLAY; + } ++ ++void GLContextEGL::QueryDimensions() ++{ ++ EGLint surface_width = 1, surface_height = 1; ++ if (!eglQuerySurface(m_egl_display, m_egl_surface, EGL_WIDTH, &surface_width) || ++ !eglQuerySurface(m_egl_display, m_egl_surface, EGL_HEIGHT, &surface_height)) ++ { ++ INFO_LOG_FMT(VIDEO, "Failed to get surface dimensions via eglQuerySurface. Size may be incorrect."); ++ } ++ m_backbuffer_width = static_cast(surface_width); ++ m_backbuffer_height = static_cast(surface_height); ++} +diff -rupN dolphin.orig/Source/Core/Common/GL/GLInterface/EGL.h dolphin/Source/Core/Common/GL/GLInterface/EGL.h +--- dolphin.orig/Source/Core/Common/GL/GLInterface/EGL.h 2024-03-05 04:05:26.578982537 +0000 ++++ dolphin/Source/Core/Common/GL/GLInterface/EGL.h 2024-03-05 04:06:08.240295843 +0000 +@@ -22,7 +22,8 @@ public: + bool MakeCurrent() override; + bool ClearCurrent() override; + +- void UpdateSurface(void* window_handle) override; ++ void UpdateDimensions(int window_width, int window_height); ++ void UpdateSurface(void* window_handle, int window_width, int window_height) override; + + void Swap() override; + void SwapInterval(int interval) override; +@@ -39,9 +40,12 @@ protected: + void DestroyWindowSurface(); + void DetectMode(); + void DestroyContext(); ++ void QueryDimensions(); + + WindowSystemInfo m_wsi = {}; + ++ EGLNativeWindowType m_native_window = {}; ++ + EGLConfig m_config; + bool m_supports_surfaceless = false; + std::vector m_attribs; +diff -rupN dolphin.orig/Source/Core/Common/GL/GLInterface/EGLWayland.cpp dolphin/Source/Core/Common/GL/GLInterface/EGLWayland.cpp +--- dolphin.orig/Source/Core/Common/GL/GLInterface/EGLWayland.cpp 1970-01-01 00:00:00.000000000 +0000 ++++ dolphin/Source/Core/Common/GL/GLInterface/EGLWayland.cpp 2024-03-05 04:06:08.240295843 +0000 +@@ -0,0 +1,36 @@ ++// Copyright 2019 Dolphin Emulator Project ++// Licensed under GPLv2+ ++// Refer to the license.txt file included. ++ ++#include "Common/GL/GLInterface/EGLWayland.h" ++#include ++ ++GLContextEGLWayland::~GLContextEGLWayland() ++{ ++ if (m_native_window) ++ wl_egl_window_destroy(reinterpret_cast(m_native_window)); ++} ++ ++EGLDisplay GLContextEGLWayland::OpenEGLDisplay() ++{ ++ return eglGetDisplay(reinterpret_cast(m_wsi.display_connection)); ++} ++ ++void GLContextEGLWayland::UpdateDimensions(int window_width, int window_height) ++{ ++ wl_egl_window_resize(reinterpret_cast(m_native_window), window_width, ++ window_height, 0, 0); ++ m_backbuffer_width = window_width; ++ m_backbuffer_height = window_height; ++} ++ ++EGLNativeWindowType GLContextEGLWayland::GetEGLNativeWindow(EGLConfig config) ++{ ++ wl_egl_window* window = ++ wl_egl_window_create(static_cast(m_wsi.render_surface), ++ m_wsi.render_surface_width, m_wsi.render_surface_height); ++ if (!window) ++ return {}; ++ ++ return reinterpret_cast(window); ++} +diff -rupN dolphin.orig/Source/Core/Common/GL/GLInterface/EGLWayland.h dolphin/Source/Core/Common/GL/GLInterface/EGLWayland.h +--- dolphin.orig/Source/Core/Common/GL/GLInterface/EGLWayland.h 1970-01-01 00:00:00.000000000 +0000 ++++ dolphin/Source/Core/Common/GL/GLInterface/EGLWayland.h 2024-03-05 04:06:08.240295843 +0000 +@@ -0,0 +1,19 @@ ++// Copyright 2019 Dolphin Emulator Project ++// Licensed under GPLv2+ ++// Refer to the license.txt file included. ++ ++#pragma once ++ ++#include "Common/GL/GLInterface/EGL.h" ++ ++class GLContextEGLWayland : public GLContextEGL ++{ ++public: ++ ~GLContextEGLWayland(); ++ ++ void UpdateDimensions(int window_width, int window_height) override; ++ ++protected: ++ EGLDisplay OpenEGLDisplay() override; ++ EGLNativeWindowType GetEGLNativeWindow(EGLConfig config) override; ++}; +diff -rupN dolphin.orig/Source/Core/Common/GL/GLInterface/EGLX11.cpp dolphin/Source/Core/Common/GL/GLInterface/EGLX11.cpp +--- dolphin.orig/Source/Core/Common/GL/GLInterface/EGLX11.cpp 2024-03-05 04:05:26.578982537 +0000 ++++ dolphin/Source/Core/Common/GL/GLInterface/EGLX11.cpp 2024-03-05 04:06:08.240295843 +0000 +@@ -11,7 +11,7 @@ GLContextEGLX11::~GLContextEGLX11() + m_render_window.reset(); + } + +-void GLContextEGLX11::Update() ++void GLContextEGLX11::UpdateDimensions(int window_width, int window_height) + { + m_render_window->UpdateDimensions(); + m_backbuffer_width = m_render_window->GetWidth(); +diff -rupN dolphin.orig/Source/Core/Common/GL/GLInterface/EGLX11.h dolphin/Source/Core/Common/GL/GLInterface/EGLX11.h +--- dolphin.orig/Source/Core/Common/GL/GLInterface/EGLX11.h 2024-03-05 04:05:26.578982537 +0000 ++++ dolphin/Source/Core/Common/GL/GLInterface/EGLX11.h 2024-03-05 04:06:08.240295843 +0000 +@@ -13,7 +13,7 @@ class GLContextEGLX11 final : public GLC + public: + ~GLContextEGLX11() override; + +- void Update() override; ++void UpdateDimensions(int window_width, int window_height) override; + + protected: + EGLDisplay OpenEGLDisplay() override; +diff -rupN dolphin.orig/Source/Core/Common/GL/GLInterface/GLX.cpp dolphin/Source/Core/Common/GL/GLInterface/GLX.cpp +--- dolphin.orig/Source/Core/Common/GL/GLInterface/GLX.cpp 2024-03-05 04:05:26.578982537 +0000 ++++ dolphin/Source/Core/Common/GL/GLInterface/GLX.cpp 2024-03-05 04:06:08.240295843 +0000 +@@ -310,7 +310,7 @@ bool GLContextGLX::ClearCurrent() + return glXMakeCurrent(m_display, None, nullptr); + } + +-void GLContextGLX::Update() ++void GLContextGLX::UpdateDimensions(int window_width, int window_height) + { + m_render_window->UpdateDimensions(); + m_backbuffer_width = m_render_window->GetWidth(); +diff -rupN dolphin.orig/Source/Core/Common/GL/GLInterface/GLX.h dolphin/Source/Core/Common/GL/GLInterface/GLX.h +--- dolphin.orig/Source/Core/Common/GL/GLInterface/GLX.h 2024-03-05 04:05:26.578982537 +0000 ++++ dolphin/Source/Core/Common/GL/GLInterface/GLX.h 2024-03-05 04:06:08.240295843 +0000 +@@ -24,7 +24,7 @@ public: + bool MakeCurrent() override; + bool ClearCurrent() override; + +- void Update() override; ++ void UpdateDimensions(int window_width, int window_height) override; + + void SwapInterval(int Interval) override; + void Swap() override; +diff -rupN dolphin.orig/Source/Core/Common/GL/GLInterface/WGL.cpp dolphin/Source/Core/Common/GL/GLInterface/WGL.cpp +--- dolphin.orig/Source/Core/Common/GL/GLInterface/WGL.cpp 2024-03-05 04:05:26.578982537 +0000 ++++ dolphin/Source/Core/Common/GL/GLInterface/WGL.cpp 2024-03-05 04:06:08.240295843 +0000 +@@ -480,7 +480,7 @@ bool GLContextWGL::ClearCurrent() + } + + // Update window width, size and etc. Called from Render.cpp +-void GLContextWGL::Update() ++void GLContextWGL::UpdateDimensions(int window_width, int window_height) + { + RECT rcWindow; + GetClientRect(m_window_handle, &rcWindow); +diff -rupN dolphin.orig/Source/Core/Common/GL/GLInterface/WGL.h dolphin/Source/Core/Common/GL/GLInterface/WGL.h +--- dolphin.orig/Source/Core/Common/GL/GLInterface/WGL.h 2024-03-05 04:05:26.578982537 +0000 ++++ dolphin/Source/Core/Common/GL/GLInterface/WGL.h 2024-03-05 04:06:08.240295843 +0000 +@@ -19,7 +19,7 @@ public: + bool MakeCurrent() override; + bool ClearCurrent() override; + +- void Update() override; ++ void UpdateDimensions(int window_width, int window_height) override; + + void Swap() override; + void SwapInterval(int interval) override; +diff -rupN dolphin.orig/Source/Core/Common/WindowSystemInfo.h dolphin/Source/Core/Common/WindowSystemInfo.h +--- dolphin.orig/Source/Core/Common/WindowSystemInfo.h 2024-03-05 04:05:26.578982537 +0000 ++++ dolphin/Source/Core/Common/WindowSystemInfo.h 2024-03-05 04:06:08.240295843 +0000 +@@ -40,7 +40,11 @@ struct WindowSystemInfo + // This is kept seperate as input may require a different handle to rendering, and + // during video backend startup the surface pointer may change (MoltenVK). + void* render_surface = nullptr; +- ++ ++ // Dimensions of the render surface, if this is determined by the frontend. ++ int render_surface_width = 0; ++ int render_surface_height = 0; ++ + // Scale of the render surface. For hidpi systems, this will be >1. + float render_surface_scale = 1.0f; + }; +diff -rupN dolphin.orig/Source/Core/Core/BootManager.cpp dolphin/Source/Core/Core/BootManager.cpp +--- dolphin.orig/Source/Core/Core/BootManager.cpp 2024-03-05 04:05:26.578982537 +0000 ++++ dolphin/Source/Core/Core/BootManager.cpp 2024-03-05 04:06:08.240295843 +0000 +@@ -64,6 +64,11 @@ bool BootCore(std::unique_ptr(boot->parameters)) ++ { ++ StartUp.SetBaseSaveState(PathToFileName(std::get(boot->parameters).path)); ++ } ++ + // Movie settings + if (Movie::IsPlayingInput() && Movie::IsConfigSaved()) + { +diff -rupN dolphin.orig/Source/Core/Core/ConfigManager.cpp dolphin/Source/Core/Core/ConfigManager.cpp +--- dolphin.orig/Source/Core/Core/ConfigManager.cpp 2024-03-05 04:05:26.578982537 +0000 ++++ dolphin/Source/Core/Core/ConfigManager.cpp 2024-03-05 04:06:08.240295843 +0000 +@@ -139,6 +139,10 @@ void SConfig::SetRunningGameMetadata(con + SetRunningGameMetadata(game_id, "", 0, 0, DiscIO::Region::Unknown); + } + ++void SConfig::SetBaseSaveState(const std::string& base_save_state) { ++ m_base_save_state = base_save_state; ++} ++ + void SConfig::SetRunningGameMetadata(const std::string& game_id, const std::string& gametdb_id, + u64 title_id, u16 revision, DiscIO::Region region) + { +diff -rupN dolphin.orig/Source/Core/Core/ConfigManager.h dolphin/Source/Core/Core/ConfigManager.h +--- dolphin.orig/Source/Core/Core/ConfigManager.h 2024-03-05 04:05:26.578982537 +0000 ++++ dolphin/Source/Core/Core/ConfigManager.h 2024-03-05 04:06:08.240295843 +0000 +@@ -56,6 +56,8 @@ struct SConfig + // TODO: remove this as soon as the ticket view hack in IOS/ES/Views is dropped. + bool m_disc_booted_from_game_list = false; + ++ const std::string& GetBaseSaveState() const { return m_base_save_state; } ++ void SetBaseSaveState(const std::string& base_save_state); + const std::string& GetGameID() const { return m_game_id; } + const std::string& GetGameTDBID() const { return m_gametdb_id; } + const std::string& GetTitleName() const { return m_title_name; } +@@ -109,6 +111,7 @@ private: + + static SConfig* m_Instance; + ++ std::string m_base_save_state; + std::string m_game_id; + std::string m_gametdb_id; + std::string m_title_name; +diff -rupN dolphin.orig/Source/Core/Core/Core.cpp dolphin/Source/Core/Core/Core.cpp +--- dolphin.orig/Source/Core/Core/Core.cpp 2024-03-05 04:05:26.578982537 +0000 ++++ dolphin/Source/Core/Core/Core.cpp 2024-03-05 04:06:08.240295843 +0000 +@@ -474,6 +474,8 @@ static void EmuThread(std::unique_ptrAddInput(ControllerEmu::Translate, START_BUTTON, _trans("START")); + ++ // Hotkey Button ++ m_buttons->AddInput(ControllerEmu::Translate, HOTKEY_BUTTON, _trans("HOTKEY")); ++ + // sticks + groups.emplace_back(m_main_stick = new ControllerEmu::OctagonAnalogStick( + MAIN_STICK_GROUP, _trans("Control Stick"), MAIN_STICK_GATE_RADIUS)); +diff -rupN dolphin.orig/Source/Core/Core/HW/GCPadEmu.h dolphin/Source/Core/Core/HW/GCPadEmu.h +--- dolphin.orig/Source/Core/Core/HW/GCPadEmu.h 2024-03-05 04:05:26.582982663 +0000 ++++ dolphin/Source/Core/Core/HW/GCPadEmu.h 2024-03-05 14:38:20.524919664 +0000 +@@ -66,6 +66,8 @@ public: + static constexpr const char* Y_BUTTON = "Y"; + static constexpr const char* Z_BUTTON = "Z"; + static constexpr const char* START_BUTTON = "Start"; ++ static constexpr const char* HOTKEY_BUTTON = "Hotkey"; ++ + + // i18n: The left trigger button (labeled L on real controllers) + static constexpr const char* L_DIGITAL = _trans("L"); +diff -rupN dolphin.orig/Source/Core/Core/State.cpp dolphin/Source/Core/Core/State.cpp +--- dolphin.orig/Source/Core/Core/State.cpp 2024-03-05 04:05:26.586982789 +0000 ++++ dolphin/Source/Core/Core/State.cpp 2024-03-05 04:06:08.240295843 +0000 +@@ -327,7 +327,10 @@ static std::string SystemTimeAsDoubleToS + #endif + } + +-static std::string MakeStateFilename(int number); ++static std::string MakeStateFilename(bool useId, int number); ++static std::string MakeStateFilename_partdirectory(int number); ++static std::string MakeStateFilename_partfileName(int number); ++static std::string MakeStateFilename_partfileID(int number); + + // read state timestamps + static std::map GetSavedStates() +@@ -336,7 +339,7 @@ static std::map GetSavedSta + std::map m; + for (int i = 1; i <= (int)NUM_STATES; i++) + { +- std::string filename = MakeStateFilename(i); ++ std::string filename = MakeStateFilename(true, i); + if (File::Exists(filename)) + { + if (ReadHeader(filename, header)) +@@ -536,7 +539,7 @@ bool ReadHeader(const std::string& filen + + std::string GetInfoStringOfSlot(int slot, bool translate) + { +- std::string filename = MakeStateFilename(slot); ++ std::string filename = MakeStateFilename(true, slot); + if (!File::Exists(filename)) + return translate ? Common::GetStringT("Empty") : "Empty"; + +@@ -550,7 +553,7 @@ std::string GetInfoStringOfSlot(int slot + u64 GetUnixTimeOfSlot(int slot) + { + State::StateHeader header; +- if (!ReadHeader(MakeStateFilename(slot), header)) ++ if (!ReadHeader(MakeStateFilename(true, slot), header)) + return 0; + + constexpr u64 MS_PER_SEC = 1000; +@@ -751,20 +754,48 @@ void Shutdown() + } + } + +-static std::string MakeStateFilename(int number) ++static std::string MakeStateFilename(bool useId, int number) + { +- return fmt::format("{}{}.s{:02d}", File::GetUserPath(D_STATESAVES_IDX), +- SConfig::GetInstance().GetGameID(), number); ++ // if the useId flag is set : if the file with name exits, returns it, otherwise, if the file with id exists, returns it, otherwise, return the file with name ++ // => priority with the file with name. ++ // if the game is not loaded from a file (disk), use the gameId ++ std::string filePartName = MakeStateFilename_partfileName(number); ++ std::string fileWithName = fmt::format("{}{}", MakeStateFilename_partdirectory(number), filePartName); ++ if (File::Exists(fileWithName) && filePartName != "") ++ return fileWithName; ++ std::string fileWithId = fmt::format("{}{}", MakeStateFilename_partdirectory(number), MakeStateFilename_partfileID(number)); ++ if (File::Exists(fileWithId) && useId) ++ return fileWithId; ++ if(filePartName == "") return fileWithId; ++ return fileWithName; ++} ++ ++static std::string MakeStateFilename_partdirectory(int number) ++{ ++ return File::GetUserPath(D_STATESAVES_IDX); ++} ++ ++static std::string MakeStateFilename_partfileID(int number) ++{ ++ return fmt::format("{}.s{:02d}", SConfig::GetInstance().GetGameID(), number); ++} ++ ++static std::string MakeStateFilename_partfileName(int number) ++{ ++ std::string basesavestate = SConfig::GetInstance().GetBaseSaveState(); ++ if(basesavestate == "") return ""; ++ return fmt::format("{}.s{:02d}", basesavestate, number); + } + + void Save(int slot, bool wait) + { +- SaveAs(MakeStateFilename(slot), wait); ++ std::string savePath = MakeStateFilename(false, slot); ++ SaveAs(savePath, wait); + } + + void Load(int slot) + { +- LoadAs(MakeStateFilename(slot)); ++ LoadAs(MakeStateFilename(true, slot)); + } + + void LoadLastSaved(int i) +diff -rupN dolphin.orig/Source/Core/DolphinLib.props dolphin/Source/Core/DolphinLib.props +--- dolphin.orig/Source/Core/DolphinLib.props 2024-03-05 04:05:26.590982915 +0000 ++++ dolphin/Source/Core/DolphinLib.props 2024-03-05 04:06:08.240295843 +0000 +@@ -1207,6 +1207,7 @@ + + + ++ + + + +diff -rupN dolphin.orig/Source/Core/DolphinNoGUI/CMakeLists.txt dolphin/Source/Core/DolphinNoGUI/CMakeLists.txt +--- dolphin.orig/Source/Core/DolphinNoGUI/CMakeLists.txt 2024-03-05 04:05:26.590982915 +0000 ++++ dolphin/Source/Core/DolphinNoGUI/CMakeLists.txt 2024-03-05 04:06:08.240295843 +0000 +@@ -17,6 +17,22 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux" + target_sources(dolphin-nogui PRIVATE PlatformFBDev.cpp) + endif() + ++if(ENABLE_WAYLAND AND WAYLAND_FOUND) ++ set(WAYLAND_PLATFORM_SRCS PlatformWayland.cpp) ++ ++ # Generate the xdg-shell and xdg-decoration protocols at build-time. ++ ecm_add_wayland_client_protocol(WAYLAND_PLATFORM_SRCS ++ PROTOCOL "${WAYLAND_PROTOCOLS_PKGDATADIR}/stable/xdg-shell/xdg-shell.xml" ++ BASENAME xdg-shell) ++ ecm_add_wayland_client_protocol(WAYLAND_PLATFORM_SRCS ++ PROTOCOL "${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml" ++ BASENAME xdg-decoration) ++ ++ target_include_directories(dolphin-nogui PRIVATE "${CMAKE_CURRENT_BINARY_DIR}") ++ target_sources(dolphin-nogui PRIVATE "${WAYLAND_PLATFORM_SRCS}") ++ target_link_libraries(dolphin-nogui PRIVATE Wayland::Client) ++endif() ++ + set_target_properties(dolphin-nogui PROPERTIES OUTPUT_NAME dolphin-emu-nogui) + + target_link_libraries(dolphin-nogui +diff -rupN dolphin.orig/Source/Core/DolphinNoGUI/MainNoGUI.cpp dolphin/Source/Core/DolphinNoGUI/MainNoGUI.cpp +--- dolphin.orig/Source/Core/DolphinNoGUI/MainNoGUI.cpp 2024-03-05 04:05:26.590982915 +0000 ++++ dolphin/Source/Core/DolphinNoGUI/MainNoGUI.cpp 2024-03-05 04:06:08.240295843 +0000 +@@ -155,6 +155,11 @@ static std::unique_ptr GetPlat + { + std::string platform_name = static_cast(options.get("platform")); + ++#if HAVE_WAYLAND ++ if (platform_name == "wayland") ++ return Platform::CreateWaylandPlatform(); ++#endif ++ + #if HAVE_X11 + if (platform_name == "x11" || platform_name.empty()) + return Platform::CreateX11Platform(); +@@ -200,6 +205,10 @@ int main(int argc, char* argv[]) + , + "win32" + #endif ++#ifdef HAVE_WAYLAND ++ , ++ "wayland" ++#endif + }); + + optparse::Values& options = CommandLineParse::ParseArguments(parser.get(), argc, argv); +diff -rupN dolphin.orig/Source/Core/DolphinNoGUI/Platform.h dolphin/Source/Core/DolphinNoGUI/Platform.h +--- dolphin.orig/Source/Core/DolphinNoGUI/Platform.h 2024-03-05 04:05:26.590982915 +0000 ++++ dolphin/Source/Core/DolphinNoGUI/Platform.h 2024-03-05 04:06:08.240295843 +0000 +@@ -35,6 +35,10 @@ public: + static std::unique_ptr CreateX11Platform(); + #endif + ++#ifdef HAVE_WAYLAND ++ static std::unique_ptr CreateWaylandPlatform(); ++#endif ++ + #ifdef __linux__ + static std::unique_ptr CreateFBDevPlatform(); + #endif +diff -rupN dolphin.orig/Source/Core/DolphinNoGUI/PlatformWayland.cpp dolphin/Source/Core/DolphinNoGUI/PlatformWayland.cpp +--- dolphin.orig/Source/Core/DolphinNoGUI/PlatformWayland.cpp 1970-01-01 00:00:00.000000000 +0000 ++++ dolphin/Source/Core/DolphinNoGUI/PlatformWayland.cpp 2024-03-05 04:06:08.240295843 +0000 +@@ -0,0 +1,364 @@ ++// Copyright 2018 Dolphin Emulator Project ++// Licensed under GPLv2+ ++// Refer to the license.txt file included. ++ ++#include ++ ++#include "DolphinNoGUI/Platform.h" ++ ++#include "Common/MsgHandler.h" ++#include "Core/Config/MainSettings.h" ++#include "Core/Core.h" ++#include "Core/State.h" ++ ++#include "Core/HW/GCPad.h" ++#include "InputCommon/GCPadStatus.h" ++#include ++#include "Core/Config/GraphicsSettings.h" ++#include "VideoCommon/VideoConfig.h" ++#include "VideoCommon/OnScreenDisplay.h" ++ ++#include ++#include ++#include ++ ++#include ++#include "wayland-xdg-decoration-client-protocol.h" ++#include "wayland-xdg-shell-client-protocol.h" ++ ++#include "UICommon/X11Utils.h" ++#include "VideoCommon/RenderBase.h" ++ ++namespace ++{ ++class PlatformWayland : public Platform ++{ ++public: ++ ~PlatformWayland() override; ++ ++ bool Init() override; ++ void SetTitle(const std::string& string) override; ++ void MainLoop() override; ++ ++ WindowSystemInfo GetWindowSystemInfo() const; ++ ++private: ++ void ProcessEvents(); ++ ++ static void GlobalRegistryHandler(void* data, wl_registry* registry, uint32_t id, ++ const char* interface, uint32_t version); ++ static void GlobalRegistryRemover(void* data, wl_registry* registry, uint32_t id); ++ static void XDGWMBasePing(void* data, struct xdg_wm_base* xdg_wm_base, uint32_t serial); ++ static void XDGSurfaceConfigure(void* data, struct xdg_surface* xdg_surface, uint32_t serial); ++ static void TopLevelConfigure(void* data, struct xdg_toplevel* xdg_toplevel, int32_t width, ++ int32_t height, struct wl_array* states); ++ static void TopLevelClose(void* data, struct xdg_toplevel* xdg_toplevel); ++ ++ wl_display* m_display = nullptr; ++ wl_registry* m_registry = nullptr; ++ wl_compositor* m_compositor = nullptr; ++ xdg_wm_base* m_xdg_wm_base = nullptr; ++ wl_surface* m_surface = nullptr; ++ wl_region* m_region = nullptr; ++ xdg_surface* m_xdg_surface = nullptr; ++ xdg_toplevel* m_xdg_toplevel = nullptr; ++ zxdg_decoration_manager_v1* m_decoration_manager = nullptr; ++ zxdg_toplevel_decoration_v1* m_toplevel_decoration = nullptr; ++ ++ int m_surface_width = 0; ++ int m_surface_height = 0; ++}; ++ ++PlatformWayland::~PlatformWayland() ++{ ++ if (m_xdg_toplevel) ++ xdg_toplevel_destroy(m_xdg_toplevel); ++ if (m_xdg_surface) ++ xdg_surface_destroy(m_xdg_surface); ++ if (m_surface) ++ wl_surface_destroy(m_surface); ++ if (m_region) ++ wl_region_destroy(m_region); ++ if (m_xdg_wm_base) ++ xdg_wm_base_destroy(m_xdg_wm_base); ++ if (m_compositor) ++ wl_compositor_destroy(m_compositor); ++ if (m_registry) ++ wl_registry_destroy(m_registry); ++ if (m_display) ++ wl_display_disconnect(m_display); ++} ++ ++void PlatformWayland::GlobalRegistryHandler(void* data, wl_registry* registry, uint32_t id, ++ const char* interface, uint32_t version) ++{ ++ PlatformWayland* platform = static_cast(data); ++ if (std::strcmp(interface, wl_compositor_interface.name) == 0) ++ { ++ platform->m_compositor = static_cast( ++ wl_registry_bind(platform->m_registry, id, &wl_compositor_interface, 1)); ++ } ++ else if (std::strcmp(interface, xdg_wm_base_interface.name) == 0) ++ { ++ platform->m_xdg_wm_base = static_cast( ++ wl_registry_bind(platform->m_registry, id, &xdg_wm_base_interface, 1)); ++ } ++ else if (std::strcmp(interface, zxdg_decoration_manager_v1_interface.name) == 0) ++ { ++ platform->m_decoration_manager = static_cast( ++ wl_registry_bind(platform->m_registry, id, &zxdg_decoration_manager_v1_interface, 1)); ++ } ++} ++ ++void PlatformWayland::GlobalRegistryRemover(void* data, wl_registry* registry, uint32_t id) ++{ ++} ++ ++void PlatformWayland::XDGWMBasePing(void* data, struct xdg_wm_base* xdg_wm_base, uint32_t serial) ++{ ++ xdg_wm_base_pong(xdg_wm_base, serial); ++} ++ ++void PlatformWayland::XDGSurfaceConfigure(void* data, struct xdg_surface* xdg_surface, ++ uint32_t serial) ++{ ++ xdg_surface_ack_configure(xdg_surface, serial); ++} ++ ++void PlatformWayland::TopLevelConfigure(void* data, struct xdg_toplevel* xdg_toplevel, ++ int32_t width, int32_t height, struct wl_array* states) ++{ ++ // If this is zero, it's asking us to set the size. ++ if (width == 0 || height == 0) ++ return; ++ ++ PlatformWayland* platform = static_cast(data); ++ platform->m_surface_width = width; ++ platform->m_surface_height = height; ++ if (g_renderer) ++ g_renderer->ResizeSurface(width, height); ++ //if (g_controller_interface.IsInit()) ++ //g_controller_interface.OnWindowResized(width, height); ++} ++ ++void PlatformWayland::TopLevelClose(void* data, struct xdg_toplevel* xdg_toplevel) ++{ ++ PlatformWayland* platform = static_cast(data); ++ platform->Stop(); ++} ++ ++bool PlatformWayland::Init() ++{ ++ m_display = wl_display_connect(nullptr); ++ if (!m_display) ++ { ++ //PanicAlert("Failed to connect to Wayland display."); ++ return false; ++ } ++ ++ static const wl_registry_listener registry_listener = {GlobalRegistryHandler, ++ GlobalRegistryRemover}; ++ m_registry = wl_display_get_registry(m_display); ++ wl_registry_add_listener(m_registry, ®istry_listener, this); ++ ++ // Call back to registry listener to get compositor/shell. ++ wl_display_dispatch(m_display); ++ wl_display_roundtrip(m_display); ++ ++ // We need a shell/compositor, or at least one we understand. ++ if (!m_compositor || !m_display || !m_xdg_wm_base) ++ { ++ std::fprintf(stderr, "Missing Wayland shell/compositor\n"); ++ return false; ++ } ++ ++ // Create the compositor and shell surface. ++ if (!(m_surface = wl_compositor_create_surface(m_compositor)) || ++ !(m_xdg_surface = xdg_wm_base_get_xdg_surface(m_xdg_wm_base, m_surface)) || ++ !(m_xdg_toplevel = xdg_surface_get_toplevel(m_xdg_surface))) ++ { ++ std::fprintf(stderr, "Failed to create compositor/shell surfaces\n"); ++ return false; ++ } ++ ++ static const xdg_wm_base_listener xdg_wm_base_listener = {XDGWMBasePing}; ++ xdg_wm_base_add_listener(m_xdg_wm_base, &xdg_wm_base_listener, this); ++ ++ static const xdg_surface_listener shell_surface_listener = {XDGSurfaceConfigure}; ++ xdg_surface_add_listener(m_xdg_surface, &shell_surface_listener, this); ++ ++ static const xdg_toplevel_listener toplevel_listener = {TopLevelConfigure, TopLevelClose}; ++ xdg_toplevel_add_listener(m_xdg_toplevel, &toplevel_listener, this); ++ ++ // Create region in the surface to draw into. ++ m_surface_width = Config::Get(Config::MAIN_RENDER_WINDOW_WIDTH); ++ m_surface_height = Config::Get(Config::MAIN_RENDER_WINDOW_HEIGHT); ++ m_region = wl_compositor_create_region(m_compositor); ++ wl_region_add(m_region, 0, 0, m_surface_width, m_surface_height); ++ wl_surface_set_opaque_region(m_surface, m_region); ++ wl_surface_commit(m_surface); ++ ++ // This doesn't seem to have any effect on kwin... ++ xdg_surface_set_window_geometry(m_xdg_surface, Config::Get(Config::MAIN_RENDER_WINDOW_XPOS), ++ Config::Get(Config::MAIN_RENDER_WINDOW_YPOS), ++ Config::Get(Config::MAIN_RENDER_WINDOW_WIDTH), ++ Config::Get(Config::MAIN_RENDER_WINDOW_HEIGHT)); ++ ++ if (m_decoration_manager) ++ { ++ m_toplevel_decoration = ++ zxdg_decoration_manager_v1_get_toplevel_decoration(m_decoration_manager, m_xdg_toplevel); ++ if (m_toplevel_decoration) ++ zxdg_toplevel_decoration_v1_set_mode(m_toplevel_decoration, ++ ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); ++ } ++ ++ return true; ++} ++ ++void PlatformWayland::SetTitle(const std::string& string) ++{ ++ xdg_toplevel_set_title(m_xdg_toplevel, string.c_str()); ++} ++ ++void PlatformWayland::MainLoop() ++{ ++ while (IsRunning()) ++ { ++ static int hotkey = 0; ++ static int slot = 0; ++ static int fps = 0; ++ static int aspect = 0; ++ static int fforward = 0; ++ static int ires = 0; ++ ++ UpdateRunningFlag(); ++ Core::HostDispatchJobs(); ++ ProcessEvents(); ++ ++ if(Pad::IsInitialized()) { ++ GCPadStatus x = Pad::GetStatus(0); ++ ++ if( (x.button & PAD_BUTTON_HOTKEY) == PAD_BUTTON_HOTKEY) { // hotkey pressed ++ if(hotkey == 1) { ++ hotkey = 2; ++ } ++ } else { ++ hotkey = 1; // assure hotkey is released between actions ++ } ++ ++ if(hotkey == 2) { // hotkey pressed ++ if( (x.button & PAD_BUTTON_START) == PAD_BUTTON_START) { ++ RequestShutdown(); ++ hotkey = 0; ++ } ++ ++ if( (x.button & PAD_TRIGGER_L) == PAD_TRIGGER_L) { ++ State::Load(slot); ++ hotkey = 0; ++ } ++ if( (x.button & PAD_TRIGGER_R) == PAD_TRIGGER_R) { ++ State::Save(slot); ++ hotkey = 0; ++ } ++ if( (x.button & PAD_BUTTON_DOWN) == PAD_BUTTON_DOWN) { ++ if(slot > 0) slot--; ++ Core::DisplayMessage(fmt::format("Slot {} selected", slot), 4000); ++ hotkey = 0; ++ } ++ if( (x.button & PAD_BUTTON_UP) == PAD_BUTTON_UP) { ++ if(slot < 10) slot++; ++ Core::DisplayMessage(fmt::format("Slot {} selected", slot), 4000); ++ hotkey = 0; ++ } ++ if( (x.button & PAD_BUTTON_A) == PAD_BUTTON_A) { ++ Core::SaveScreenShot(); ++ hotkey = 0; ++ } ++ if( (x.button & PAD_BUTTON_Y) == PAD_BUTTON_Y) { ++ if(fps == 0) { ++ Config::SetCurrent(Config::GFX_SHOW_FPS, True); ++ fps = 1; ++ } else { ++ Config::SetCurrent(Config::GFX_SHOW_FPS, False); ++ fps = 0; ++ } ++ hotkey = 0; ++ } ++ if( (x.button & PAD_BUTTON_X) == PAD_BUTTON_X) { ++ if(aspect == 0) { ++ Config::SetCurrent(Config::GFX_ASPECT_RATIO, AspectMode::Stretch); ++ aspect = 1; ++ } else { ++ Config::SetCurrent(Config::GFX_ASPECT_RATIO, AspectMode::Auto); ++ aspect = 0; ++ } ++ hotkey = 0; ++ } ++ if( (x.button & PAD_BUTTON_B) == PAD_BUTTON_B) { ++ if(ires == 0) { ++ Config::SetCurrent(Config::GFX_EFB_SCALE, 2); ++ OSD::AddMessage("Internal Resolution: 480P"); ++ ires = 2; ++ } ++ else if(ires == 2) { ++ Config::SetCurrent(Config::GFX_EFB_SCALE, 4); ++ OSD::AddMessage("Internal Resolution: 720P"); ++ ires = 4; ++ } ++ else if(ires == 4) { ++ Config::SetCurrent(Config::GFX_EFB_SCALE, 6); ++ OSD::AddMessage("Internal Resolution: 1080P"); ++ ires = 6; ++ } else { ++ Config::SetCurrent(Config::GFX_EFB_SCALE, 1); ++ OSD::AddMessage("Internal Resolution: 240P"); ++ ires = 0; ++ } ++ hotkey = 0; ++ } ++ if( (x.button & PAD_TRIGGER_Z) == PAD_TRIGGER_Z) { ++ if(fforward == 0) { ++ auto speed = Config::Get(Config::MAIN_EMULATION_SPEED) + 1.0; ++ speed = (speed >= 0.95 && speed <= 1.05) ? 1.0 : speed; ++ Config::SetCurrent(Config::MAIN_EMULATION_SPEED, speed); ++ OSD::AddMessage("Fast Forward: ON"); ++ fforward = 1; ++ } else { ++ auto speed = Config::Get(Config::MAIN_EMULATION_SPEED) - 1.0; ++ speed = (speed <= 0 || (speed >= 0.95 && speed <= 1.05)) ? 1.0 : speed; ++ Config::SetCurrent(Config::MAIN_EMULATION_SPEED, speed); ++ OSD::AddMessage("Fast Forward: OFF"); ++ fforward = 0; ++ } ++ hotkey = 0; ++ } ++ } ++ } ++ ++ // TODO: Is this sleep appropriate? ++ std::this_thread::sleep_for(std::chrono::milliseconds(1)); ++ } ++} ++ ++WindowSystemInfo PlatformWayland::GetWindowSystemInfo() const ++{ ++ WindowSystemInfo wsi; ++ wsi.type = WindowSystemType::Wayland; ++ wsi.display_connection = static_cast(m_display); ++ wsi.render_surface = reinterpret_cast(m_surface); ++ wsi.render_surface_width = m_surface_width; ++ wsi.render_surface_height = m_surface_height; ++ return wsi; ++} ++ ++void PlatformWayland::ProcessEvents() ++{ ++ wl_display_dispatch_pending(m_display); ++} ++} // namespace ++ ++std::unique_ptr Platform::CreateWaylandPlatform() ++{ ++ return std::make_unique(); ++} +diff -rupN dolphin.orig/Source/Core/DolphinNoGUI/PlatformX11.cpp dolphin/Source/Core/DolphinNoGUI/PlatformX11.cpp +--- dolphin.orig/Source/Core/DolphinNoGUI/PlatformX11.cpp 2024-03-05 04:05:26.590982915 +0000 ++++ dolphin/Source/Core/DolphinNoGUI/PlatformX11.cpp 2024-03-05 04:21:20.855117890 +0000 +@@ -16,6 +16,13 @@ static constexpr auto X_None = None; + #include "Core/Core.h" + #include "Core/State.h" + ++#include "Core/HW/GCPad.h" ++#include "InputCommon/GCPadStatus.h" ++#include ++#include "Core/Config/GraphicsSettings.h" ++#include "VideoCommon/VideoConfig.h" ++#include "VideoCommon/OnScreenDisplay.h" ++ + #include + #include + #include +@@ -57,8 +64,8 @@ private: + #endif + int m_window_x = Config::Get(Config::MAIN_RENDER_WINDOW_XPOS); + int m_window_y = Config::Get(Config::MAIN_RENDER_WINDOW_YPOS); +- unsigned int m_window_width = Config::Get(Config::MAIN_RENDER_WINDOW_WIDTH); +- unsigned int m_window_height = Config::Get(Config::MAIN_RENDER_WINDOW_HEIGHT); ++ int m_window_width = Config::Get(Config::MAIN_RENDER_WINDOW_WIDTH); ++ int m_window_height = Config::Get(Config::MAIN_RENDER_WINDOW_HEIGHT); + }; + + PlatformX11::~PlatformX11() +@@ -149,11 +156,118 @@ void PlatformX11::MainLoop() + { + while (IsRunning()) + { ++ static int hotkey = 0; ++ static int slot = 0; ++ static int fps = 0; ++ static int aspect = 0; ++ static int fforward = 0; ++ static int ires = 0; ++ + UpdateRunningFlag(); + Core::HostDispatchJobs(); + ProcessEvents(); + UpdateWindowPosition(); + ++ if(Pad::IsInitialized()) { ++ GCPadStatus x = Pad::GetStatus(0); ++ ++ if( (x.button & PAD_BUTTON_HOTKEY) == PAD_BUTTON_HOTKEY) { // hotkey pressed ++ if(hotkey == 1) { ++ hotkey = 2; ++ } ++ } else { ++ hotkey = 1; // assure hotkey is released between actions ++ } ++ ++ if(hotkey == 2) { // hotkey pressed ++ if( (x.button & PAD_BUTTON_START) == PAD_BUTTON_START) { ++ RequestShutdown(); ++ hotkey = 0; ++ } ++ ++ if( (x.button & PAD_TRIGGER_L) == PAD_TRIGGER_L) { ++ State::Load(slot); ++ hotkey = 0; ++ } ++ if( (x.button & PAD_TRIGGER_R) == PAD_TRIGGER_R) { ++ State::Save(slot); ++ hotkey = 0; ++ } ++ if( (x.button & PAD_BUTTON_DOWN) == PAD_BUTTON_DOWN) { ++ if(slot > 0) slot--; ++ Core::DisplayMessage(fmt::format("Slot {} selected", slot), 4000); ++ hotkey = 0; ++ } ++ if( (x.button & PAD_BUTTON_UP) == PAD_BUTTON_UP) { ++ if(slot < 10) slot++; ++ Core::DisplayMessage(fmt::format("Slot {} selected", slot), 4000); ++ hotkey = 0; ++ } ++ if( (x.button & PAD_BUTTON_A) == PAD_BUTTON_A) { ++ Core::SaveScreenShot(); ++ hotkey = 0; ++ } ++ if( (x.button & PAD_BUTTON_Y) == PAD_BUTTON_Y) { ++ if(fps == 0) { ++ Config::SetCurrent(Config::GFX_SHOW_FPS, True); ++ fps = 1; ++ } else { ++ Config::SetCurrent(Config::GFX_SHOW_FPS, False); ++ fps = 0; ++ } ++ hotkey = 0; ++ } ++ if( (x.button & PAD_BUTTON_X) == PAD_BUTTON_X) { ++ if(aspect == 0) { ++ Config::SetCurrent(Config::GFX_ASPECT_RATIO, AspectMode::Stretch); ++ aspect = 1; ++ } else { ++ Config::SetCurrent(Config::GFX_ASPECT_RATIO, AspectMode::Auto); ++ aspect = 0; ++ } ++ hotkey = 0; ++ } ++ if( (x.button & PAD_BUTTON_B) == PAD_BUTTON_B) { ++ if(ires == 0) { ++ Config::SetCurrent(Config::GFX_EFB_SCALE, 2); ++ OSD::AddMessage("Internal Resolution: 480P"); ++ ires = 2; ++ } ++ else if(ires == 2) { ++ Config::SetCurrent(Config::GFX_EFB_SCALE, 4); ++ OSD::AddMessage("Internal Resolution: 720P"); ++ ires = 4; ++ } ++ else if(ires == 4) { ++ Config::SetCurrent(Config::GFX_EFB_SCALE, 6); ++ OSD::AddMessage("Internal Resolution: 1080P"); ++ ires = 6; ++ } else { ++ Config::SetCurrent(Config::GFX_EFB_SCALE, 1); ++ OSD::AddMessage("Internal Resolution: 240P"); ++ ires = 0; ++ } ++ hotkey = 0; ++ } ++ if( (x.button & PAD_TRIGGER_Z) == PAD_TRIGGER_Z) { ++ if(fforward == 0) { ++ auto speed = Config::Get(Config::MAIN_EMULATION_SPEED) + 1.0; ++ speed = (speed >= 0.95 && speed <= 1.05) ? 1.0 : speed; ++ Config::SetCurrent(Config::MAIN_EMULATION_SPEED, speed); ++ OSD::AddMessage("Fast Forward: ON"); ++ fforward = 1; ++ } else { ++ auto speed = Config::Get(Config::MAIN_EMULATION_SPEED) - 1.0; ++ speed = (speed <= 0 || (speed >= 0.95 && speed <= 1.05)) ? 1.0 : speed; ++ Config::SetCurrent(Config::MAIN_EMULATION_SPEED, speed); ++ OSD::AddMessage("Fast Forward: OFF"); ++ fforward = 0; ++ } ++ hotkey = 0; ++ } ++ } ++ } ++ + // TODO: Is this sleep appropriate? + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } +@@ -166,6 +280,8 @@ WindowSystemInfo PlatformX11::GetWindowS + wsi.display_connection = static_cast(m_display); + wsi.render_window = reinterpret_cast(m_window); + wsi.render_surface = reinterpret_cast(m_window); ++ wsi.render_surface_width = m_window_width; ++ wsi.render_surface_height = m_window_height; + return wsi; + } + +@@ -176,8 +292,9 @@ void PlatformX11::UpdateWindowPosition() + + Window winDummy; + unsigned int borderDummy, depthDummy; +- XGetGeometry(m_display, m_window, &winDummy, &m_window_x, &m_window_y, &m_window_width, +- &m_window_height, &borderDummy, &depthDummy); ++ XGetGeometry(m_display, m_window, &winDummy, &m_window_x, &m_window_y, ++ reinterpret_cast(&m_window_width), ++ reinterpret_cast(&m_window_height), &borderDummy, &depthDummy); + } + + void PlatformX11::ProcessEvents() +@@ -264,7 +381,10 @@ void PlatformX11::ProcessEvents() + case ConfigureNotify: + { + if (g_renderer) +- g_renderer->ResizeSurface(); ++ { ++ UpdateWindowPosition(); ++ g_renderer->ResizeSurface(m_window_width, m_window_height); ++ } + } + break; + } +diff -rupN dolphin.orig/Source/Core/InputCommon/GCPadStatus.h dolphin/Source/Core/InputCommon/GCPadStatus.h +--- dolphin.orig/Source/Core/InputCommon/GCPadStatus.h 2024-03-05 04:05:26.598983167 +0000 ++++ dolphin/Source/Core/InputCommon/GCPadStatus.h 2024-03-05 04:06:08.240295843 +0000 +@@ -26,6 +26,7 @@ enum PadButton + PAD_BUTTON_X = 0x0400, + PAD_BUTTON_Y = 0x0800, + PAD_BUTTON_START = 0x1000, ++ PAD_BUTTON_HOTKEY = 0x2000, + }; + + struct GCPadStatus +diff -rupN dolphin.orig/Source/Core/VideoBackends/OGL/OGLRender.cpp dolphin/Source/Core/VideoBackends/OGL/OGLRender.cpp +--- dolphin.orig/Source/Core/VideoBackends/OGL/OGLRender.cpp 2024-03-05 04:05:26.598983167 +0000 ++++ dolphin/Source/Core/VideoBackends/OGL/OGLRender.cpp 2024-03-05 04:06:08.240295843 +0000 +@@ -471,11 +471,7 @@ Renderer::Renderer(std::unique_ptrIsGLES()) + { +- g_ogl_config.SupportedESPointSize = GLExtensions::Supports("GL_OES_geometry_point_size") ? 1 : +- GLExtensions::Supports("GL_EXT_geometry_point_size") ? 2 : +- 0; ++ g_ogl_config.SupportedESPointSize = ++ GLExtensions::Supports("GL_OES_geometry_point_size") ? EsPointSizeType::PointSizeOes : ++ GLExtensions::Supports("GL_EXT_geometry_point_size") ? EsPointSizeType::PointSizeExt : ++ EsPointSizeType::PointSizeNone; + g_ogl_config.SupportedESTextureBuffer = + GLExtensions::Supports("VERSION_GLES_3_2") ? EsTexbufType::TexbufCore : + GLExtensions::Supports("GL_OES_texture_buffer") ? EsTexbufType::TexbufOes : +@@ -548,21 +545,16 @@ Renderer::Renderer(std::unique_ptr 0; ++ g_Config.backend_info.bSupportsGeometryShaders && ++ g_ogl_config.SupportedESPointSize != EsPointSizeType::PointSizeNone; + g_Config.backend_info.bSupportsSSAA = g_ogl_config.bSupportsAEP; + g_Config.backend_info.bSupportsFragmentStoresAndAtomics = true; + g_ogl_config.bSupportsMSAA = true; + g_ogl_config.bSupportsTextureStorage = true; +- g_ogl_config.bSupports2DTextureStorageMultisample = true; ++ if (GLExtensions::Supports("GL_OES_texture_storage_multisample_2d_array")) ++ g_ogl_config.SupportedMultisampleTexStorage = MultisampleTexStorageType::TexStorageOes; + g_Config.backend_info.bSupportsBitfield = true; + g_Config.backend_info.bSupportsDynamicSamplerIndexing = g_ogl_config.bSupportsAEP; +- if (g_ActiveConfig.stereo_mode != StereoMode::Off && g_ActiveConfig.iMultisamples > 1 && +- !g_ogl_config.bSupports3DTextureStorageMultisample) +- { +- // GLES 3.1 can't support stereo rendering and MSAA +- OSD::AddMessage("MSAA Stereo rendering isn't supported by your GPU.", 10000); +- Config::SetCurrent(Config::GFX_MSAA, UINT32_C(1)); +- } + } + else + { +@@ -572,7 +564,8 @@ Renderer::Renderer(std::unique_ptr 0; ++ g_Config.backend_info.bSupportsGSInstancing = ++ g_ogl_config.SupportedESPointSize != EsPointSizeType::PointSizeNone; + g_Config.backend_info.bSupportsPaletteConversion = true; + g_Config.backend_info.bSupportsSSAA = true; + g_Config.backend_info.bSupportsFragmentStoresAndAtomics = true; +@@ -581,8 +574,7 @@ Renderer::Renderer(std::unique_ptrUpdateSurface(m_new_surface_handle); ++ m_main_gl_context->UpdateSurface(m_new_surface_handle, m_new_surface_width, m_new_surface_height); + m_new_surface_handle = nullptr; + + // With a surface change, the window likely has new dimensions. +@@ -1093,7 +1088,7 @@ void Renderer::CheckForSurfaceResize() + if (!m_surface_resized.TestAndClear()) + return; + +- m_main_gl_context->Update(); ++ m_main_gl_context->UpdateDimensions(m_new_surface_width, m_new_surface_height); + m_backbuffer_width = m_main_gl_context->GetBackBufferWidth(); + m_backbuffer_height = m_main_gl_context->GetBackBufferHeight(); + m_system_framebuffer->UpdateDimensions(m_backbuffer_width, m_backbuffer_height); +diff -rupN dolphin.orig/Source/Core/VideoBackends/OGL/OGLRender.h dolphin/Source/Core/VideoBackends/OGL/OGLRender.h +--- dolphin.orig/Source/Core/VideoBackends/OGL/OGLRender.h 2024-03-05 04:05:26.598983167 +0000 ++++ dolphin/Source/Core/VideoBackends/OGL/OGLRender.h 2024-03-05 04:06:08.240295843 +0000 +@@ -31,6 +31,14 @@ enum GlslVersion + GlslEs310, // GLES 3.1 + GlslEs320, // GLES 3.2 + }; ++ ++enum class EsPointSizeType ++{ ++ PointSizeNone, ++ PointSizeOes, ++ PointSizeExt, ++}; ++ + enum class EsTexbufType + { + TexbufNone, +@@ -46,6 +54,13 @@ enum class EsFbFetchType + FbFetchArm, + }; + ++enum class MultisampleTexStorageType ++{ ++ TexStorageNone, ++ TexStorageCore, ++ TexStorageOes, ++}; ++ + // ogl-only config, so not in VideoConfig.h + struct VideoConfig + { +@@ -60,11 +75,10 @@ struct VideoConfig + bool bSupportsAEP; + bool bSupportsDebug; + bool bSupportsCopySubImage; +- u8 SupportedESPointSize; ++ EsPointSizeType SupportedESPointSize; + EsTexbufType SupportedESTextureBuffer; + bool bSupportsTextureStorage; +- bool bSupports2DTextureStorageMultisample; +- bool bSupports3DTextureStorageMultisample; ++ MultisampleTexStorageType SupportedMultisampleTexStorage; + bool bSupportsConservativeDepth; + bool bSupportsImageLoadStore; + bool bSupportsAniso; +diff -rupN dolphin.orig/Source/Core/VideoBackends/OGL/OGLTexture.cpp dolphin/Source/Core/VideoBackends/OGL/OGLTexture.cpp +--- dolphin.orig/Source/Core/VideoBackends/OGL/OGLTexture.cpp 2024-03-05 04:05:26.602983293 +0000 ++++ dolphin/Source/Core/VideoBackends/OGL/OGLTexture.cpp 2024-03-05 04:06:08.240295843 +0000 +@@ -128,12 +128,18 @@ OGLTexture::OGLTexture(const TextureConf + GLenum gl_internal_format = GetGLInternalFormatForTextureFormat(m_config.format, true); + if (tex_config.IsMultisampled()) + { +- if (g_ogl_config.bSupportsTextureStorage) ++ ASSERT(g_ogl_config.bSupportsMSAA); ++ if (g_ogl_config.SupportedMultisampleTexStorage != MultisampleTexStorageType::TexStorageNone) ++ { + glTexStorage3DMultisample(target, tex_config.samples, gl_internal_format, m_config.width, + m_config.height, m_config.layers, GL_FALSE); ++ } + else ++ { ++ ASSERT(!g_ogl_config.bIsES); + glTexImage3DMultisample(target, tex_config.samples, gl_internal_format, m_config.width, + m_config.height, m_config.layers, GL_FALSE); ++ } + } + else if (g_ogl_config.bSupportsTextureStorage) + { +diff -rupN dolphin.orig/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp dolphin/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp +--- dolphin.orig/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp 2024-03-05 04:05:26.602983293 +0000 ++++ dolphin/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp 2024-03-05 04:06:08.240295843 +0000 +@@ -661,12 +661,13 @@ void ProgramShaderCache::CreateHeader() + std::string SupportedESTextureBuffer; + switch (g_ogl_config.SupportedESPointSize) + { +- case 1: ++ case EsPointSizeType::PointSizeOes: + SupportedESPointSize = "#extension GL_OES_geometry_point_size : enable"; + break; +- case 2: ++ case EsPointSizeType::PointSizeExt: + SupportedESPointSize = "#extension GL_EXT_geometry_point_size : enable"; + break; ++ case EsPointSizeType::PointSizeNone: + default: + SupportedESPointSize = ""; + break; +@@ -718,6 +719,13 @@ void ProgramShaderCache::CreateHeader() + break; + } + ++ // The sampler2DMSArray keyword is reserved in GLSL ES 3.0 and 3.1, but is available in 3.2 and ++ // with GL_OES_texture_storage_multisample_2d_array for 3.1. ++ // See https://bugs.dolphin-emu.org/issues/13198. ++ const bool use_multisample_2d_array_precision = ++ v >= GlslEs320 || ++ g_ogl_config.SupportedMultisampleTexStorage != MultisampleTexStorageType::TexStorageNone; ++ + std::string shader_shuffle_string; + if (g_ogl_config.bSupportsShaderThreadShuffleNV) + { +@@ -762,6 +770,7 @@ void ProgramShaderCache::CreateHeader() + "{}\n" // shader thread shuffle + "{}\n" // derivative control + "{}\n" // query levels ++ "{}\n" // OES multisample texture storage + + // Precision defines for GLSL ES + "{}\n" +@@ -847,12 +856,18 @@ void ProgramShaderCache::CreateHeader() + g_ActiveConfig.backend_info.bSupportsTextureQueryLevels ? + "#extension GL_ARB_texture_query_levels : enable" : + "", ++ // Note: GL_ARB_texture_storage_multisample doesn't have an #extension, as it doesn't ++ // need to change GLSL, but on GLES 3.1 sampler2DMSArray is a reserved keyword unless ++ // the extension is enabled. Thus, we don't need to check TexStorageCore/have an ARB version. ++ g_ogl_config.SupportedMultisampleTexStorage == MultisampleTexStorageType::TexStorageOes ? ++ "#extension GL_OES_texture_storage_multisample_2d_array : enable" : ++ "", + is_glsles ? "precision highp float;" : "", is_glsles ? "precision highp int;" : "", + is_glsles ? "precision highp sampler2DArray;" : "", + (is_glsles && g_ActiveConfig.backend_info.bSupportsPaletteConversion) ? + "precision highp usamplerBuffer;" : + "", +- v > GlslEs300 ? "precision highp sampler2DMSArray;" : "", ++ use_multisample_2d_array_precision ? "precision highp sampler2DMSArray;" : "", + v >= GlslEs310 ? "precision highp image2DArray;" : ""); + } + +diff -rupN dolphin.orig/Source/Core/VideoBackends/Software/SWOGLWindow.cpp dolphin/Source/Core/VideoBackends/Software/SWOGLWindow.cpp +--- dolphin.orig/Source/Core/VideoBackends/Software/SWOGLWindow.cpp 2024-03-05 04:05:26.602983293 +0000 ++++ dolphin/Source/Core/VideoBackends/Software/SWOGLWindow.cpp 2024-03-05 04:06:08.240295843 +0000 +@@ -32,6 +32,16 @@ bool SWOGLWindow::IsHeadless() const + return m_gl_context->IsHeadless(); + } + ++u32 SWOGLWindow::GetWidth() const ++{ ++ return m_gl_context->GetBackBufferWidth(); ++} ++ ++u32 SWOGLWindow::GetHeight() const ++{ ++ return m_gl_context->GetBackBufferHeight(); ++} ++ + bool SWOGLWindow::Initialize(const WindowSystemInfo& wsi) + { + m_gl_context = GLContext::Create(wsi); +@@ -84,11 +94,17 @@ bool SWOGLWindow::Initialize(const Windo + return true; + } + ++ ++void SWOGLWindow::UpdateDimensions(int window_width, int window_height) ++{ ++ // just updates the render window position and the backbuffer size ++ m_gl_context->UpdateDimensions(window_width, window_height); ++} ++ + void SWOGLWindow::ShowImage(const AbstractTexture* image, + const MathUtil::Rectangle& xfb_region) + { + const SW::SWTexture* sw_image = static_cast(image); +- m_gl_context->Update(); // just updates the render window position and the backbuffer size + + GLsizei glWidth = (GLsizei)m_gl_context->GetBackBufferWidth(); + GLsizei glHeight = (GLsizei)m_gl_context->GetBackBufferHeight(); +diff -rupN dolphin.orig/Source/Core/VideoBackends/Software/SWOGLWindow.h dolphin/Source/Core/VideoBackends/Software/SWOGLWindow.h +--- dolphin.orig/Source/Core/VideoBackends/Software/SWOGLWindow.h 2024-03-05 04:05:26.602983293 +0000 ++++ dolphin/Source/Core/VideoBackends/Software/SWOGLWindow.h 2024-03-05 04:06:08.240295843 +0000 +@@ -20,6 +20,10 @@ public: + GLContext* GetContext() const { return m_gl_context.get(); } + bool IsHeadless() const; + ++ u32 GetWidth() const; ++ u32 GetHeight() const; ++ void UpdateDimensions(int window_width, int window_height); ++ + // Image to show, will be swapped immediately + void ShowImage(const AbstractTexture* image, const MathUtil::Rectangle& xfb_region); + +diff -rupN dolphin.orig/Source/Core/VideoBackends/Software/SWRenderer.cpp dolphin/Source/Core/VideoBackends/Software/SWRenderer.cpp +--- dolphin.orig/Source/Core/VideoBackends/Software/SWRenderer.cpp 2024-03-05 04:05:26.602983293 +0000 ++++ dolphin/Source/Core/VideoBackends/Software/SWRenderer.cpp 2024-03-05 04:06:08.240295843 +0000 +@@ -60,17 +60,17 @@ SWRenderer::CreateFramebuffer(AbstractTe + static_cast(depth_attachment)); + } + +-void SWRenderer::BindBackbuffer(const ClearColor& clear_color) +-{ ++//void SWRenderer::BindBackbuffer(const ClearColor& clear_color) ++//{ + // Look for framebuffer resizes +- if (!m_surface_resized.TestAndClear()) +- return; ++ //if (!m_surface_resized.TestAndClear()) ++ //return; + +- GLContext* context = m_window->GetContext(); +- context->Update(); +- m_backbuffer_width = context->GetBackBufferWidth(); +- m_backbuffer_height = context->GetBackBufferHeight(); +-} ++ //GLContext* context = m_window->GetContext(); ++ //context->UpdateDimensions(window_width, window_height); ++ //m_backbuffer_width = context->GetBackBufferWidth(); ++ //m_backbuffer_height = context->GetBackBufferHeight(); ++//} + + class SWShader final : public AbstractShader + { +@@ -108,7 +108,7 @@ std::unique_ptr SWRend + { + return std::make_unique(); + } +- ++ + // Called on the GPU thread + void SWRenderer::RenderXFBToScreen(const MathUtil::Rectangle& target_rc, + const AbstractTexture* source_texture, +@@ -118,6 +118,16 @@ void SWRenderer::RenderXFBToScreen(const + m_window->ShowImage(source_texture, source_rc); + } + ++void SWRenderer::CheckForSurfaceResize() ++{ ++ if (!m_surface_resized.TestAndClear()) ++ return; ++ ++ m_window->UpdateDimensions(m_new_surface_width, m_new_surface_height); ++ m_backbuffer_width = static_cast(m_window->GetWidth()); ++ m_backbuffer_height = static_cast(m_window->GetHeight()); ++} ++ + u32 SWRenderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 InputData) + { + u32 value = 0; +diff -rupN dolphin.orig/Source/Core/VideoBackends/Software/SWRenderer.h dolphin/Source/Core/VideoBackends/Software/SWRenderer.h +--- dolphin.orig/Source/Core/VideoBackends/Software/SWRenderer.h 2024-03-05 04:05:26.602983293 +0000 ++++ dolphin/Source/Core/VideoBackends/Software/SWRenderer.h 2024-03-05 04:06:08.240295843 +0000 +@@ -29,7 +29,7 @@ public: + std::unique_ptr + CreateFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment) override; + +- void BindBackbuffer(const ClearColor& clear_color = {}) override; ++ //void BindBackbuffer(const ClearColor& clear_color = {}) override; + + std::unique_ptr CreateShaderFromSource(ShaderStage stage, std::string_view source, + std::string_view name) override; +@@ -64,6 +64,8 @@ protected: + std::unique_ptr CreateBoundingBox() const override; + + private: ++void CheckForSurfaceResize(); ++ + std::unique_ptr m_window; + }; + } // namespace SW +diff -rupN dolphin.orig/Source/Core/VideoBackends/Vulkan/CMakeLists.txt dolphin/Source/Core/VideoBackends/Vulkan/CMakeLists.txt +--- dolphin.orig/Source/Core/VideoBackends/Vulkan/CMakeLists.txt 2024-03-05 04:05:26.602983293 +0000 ++++ dolphin/Source/Core/VideoBackends/Vulkan/CMakeLists.txt 2024-03-05 04:06:08.240295843 +0000 +@@ -35,6 +35,8 @@ add_library(videovulkan + VulkanContext.h + VulkanLoader.cpp + VulkanLoader.h ++ VKScheduler.h ++ VKScheduler.cpp + ) + + target_link_libraries(videovulkan +diff -rupN dolphin.orig/Source/Core/VideoBackends/Vulkan/CommandBufferManager.cpp dolphin/Source/Core/VideoBackends/Vulkan/CommandBufferManager.cpp +--- dolphin.orig/Source/Core/VideoBackends/Vulkan/CommandBufferManager.cpp 2024-03-05 04:05:26.602983293 +0000 ++++ dolphin/Source/Core/VideoBackends/Vulkan/CommandBufferManager.cpp 2024-03-05 04:06:08.240295843 +0000 +@@ -10,24 +10,24 @@ + #include "Common/MsgHandler.h" + #include "Common/Thread.h" + ++#include "VideoBackends/Vulkan/StateTracker.h" + #include "VideoBackends/Vulkan/VulkanContext.h" + + namespace Vulkan + { +-CommandBufferManager::CommandBufferManager(bool use_threaded_submission) +- : m_use_threaded_submission(use_threaded_submission) ++CommandBufferManager::CommandBufferManager() ++ : m_state_tracker(std::make_unique(this)), m_last_present_done(true) + { + } + + CommandBufferManager::~CommandBufferManager() + { + // If the worker thread is enabled, stop and block until it exits. +- if (m_use_threaded_submission) +- { +- WaitForWorkerThreadIdle(); +- m_submit_loop->Stop(); +- m_submit_thread.join(); +- } ++ WaitForSubmitWorkerThreadIdle(); ++ m_submit_loop->Stop(); ++ m_fence_loop->Stop(); ++ m_submit_thread.join(); ++ m_fence_thread.join(); + + DestroyCommandBuffers(); + } +@@ -37,10 +37,13 @@ bool CommandBufferManager::Initialize() + if (!CreateCommandBuffers()) + return false; + +- if (m_use_threaded_submission && !CreateSubmitThread()) ++ if (!CreateFenceThread()) + return false; + +- return true; ++ if (!CreateSubmitThread()) ++ return false; ++ ++ return m_state_tracker->Initialize(); + } + + bool CommandBufferManager::CreateCommandBuffers() +@@ -86,13 +89,6 @@ bool CommandBufferManager::CreateCommand + LOG_VULKAN_ERROR(res, "vkCreateFence failed: "); + return false; + } +- +- res = vkCreateSemaphore(device, &semaphore_create_info, nullptr, &resources.semaphore); +- if (res != VK_SUCCESS) +- { +- LOG_VULKAN_ERROR(res, "vkCreateSemaphore failed: "); +- return false; +- } + } + + res = vkCreateSemaphore(device, &semaphore_create_info, nullptr, &m_present_semaphore); +@@ -125,9 +121,6 @@ void CommandBufferManager::DestroyComman + for (auto& it : resources.cleanup_resources) + it(); + +- if (resources.semaphore != VK_NULL_HANDLE) +- vkDestroySemaphore(device, resources.semaphore, nullptr); +- + if (resources.fence != VK_NULL_HANDLE) + vkDestroyFence(device, resources.fence, nullptr); + } +@@ -215,11 +208,42 @@ VkDescriptorSet CommandBufferManager::Al + return descriptor_set; + } + ++bool CommandBufferManager::CreateFenceThread() ++{ ++ m_fence_loop = std::make_unique(); ++ m_fence_thread = std::thread([this]() { ++ Common::SetCurrentThreadName("Vulkan FenceThread"); ++ m_fence_loop->Run([this]() { ++ PendingFenceCounter fence; ++ { ++ std::lock_guard guard(m_pending_fences_lock); ++ if (m_pending_fences.empty()) ++ { ++ m_fence_condvar.notify_all(); ++ m_fence_loop->AllowSleep(); ++ return; ++ } ++ ++ fence = m_pending_fences.front(); ++ m_pending_fences.pop_front(); ++ } ++ ++ vkWaitForFences(g_vulkan_context->GetDevice(), 1, &fence.fence, true, ~0ul); ++ ++ std::lock_guard guard(m_pending_fences_lock); ++ m_completed_fence_counter.store(fence.counter, std::memory_order_release); ++ m_fence_condvar.notify_all(); ++ }); ++ }); ++ ++ return true; ++} ++ + bool CommandBufferManager::CreateSubmitThread() + { + m_submit_loop = std::make_unique(); + m_submit_thread = std::thread([this]() { +- Common::SetCurrentThreadName("Vulkan CommandBufferManager SubmitThread"); ++ Common::SetCurrentThreadName("Vulkan SubmitThread"); + + m_submit_loop->Run([this]() { + PendingCommandBufferSubmit submit; +@@ -227,9 +251,9 @@ bool CommandBufferManager::CreateSubmitT + std::lock_guard guard(m_pending_submit_lock); + if (m_pending_submits.empty()) + { +- m_submit_loop->AllowSleep(); + m_submit_worker_idle = true; + m_submit_worker_condvar.notify_all(); ++ m_submit_loop->AllowSleep(); + return; + } + +@@ -239,16 +263,12 @@ bool CommandBufferManager::CreateSubmitT + + SubmitCommandBuffer(submit.command_buffer_index, submit.present_swap_chain, + submit.present_image_index); +- CmdBufferResources& resources = m_command_buffers[submit.command_buffer_index]; +- resources.waiting_for_submit.store(false, std::memory_order_release); + ++ std::lock_guard guard(m_pending_submit_lock); ++ if (m_pending_submits.empty()) + { +- std::lock_guard guard(m_pending_submit_lock); +- if (m_pending_submits.empty()) +- { +- m_submit_worker_idle = true; +- m_submit_worker_condvar.notify_all(); +- } ++ m_submit_worker_idle = true; ++ m_submit_worker_condvar.notify_all(); + } + }); + }); +@@ -256,55 +276,28 @@ bool CommandBufferManager::CreateSubmitT + return true; + } + +-void CommandBufferManager::WaitForWorkerThreadIdle() ++void CommandBufferManager::WaitForSubmitWorkerThreadIdle() + { +- if (!m_use_threaded_submission) +- return; +- + std::unique_lock lock{m_pending_submit_lock}; + m_submit_worker_condvar.wait(lock, [&] { return m_submit_worker_idle; }); + } + + void CommandBufferManager::WaitForFenceCounter(u64 fence_counter) + { +- if (m_completed_fence_counter >= fence_counter) ++ if (m_completed_fence_counter.load(std::memory_order_relaxed) >= fence_counter) [[likely]] + return; + +- // Find the first command buffer which covers this counter value. +- u32 index = (m_current_cmd_buffer + 1) % NUM_COMMAND_BUFFERS; +- while (index != m_current_cmd_buffer) +- { +- if (m_command_buffers[index].fence_counter >= fence_counter) +- break; +- +- index = (index + 1) % NUM_COMMAND_BUFFERS; +- } +- +- ASSERT(index != m_current_cmd_buffer); +- WaitForCommandBufferCompletion(index); ++ std::unique_lock lock{m_pending_fences_lock}; ++ m_fence_condvar.wait(lock, [&] { ++ return m_completed_fence_counter.load(std::memory_order_relaxed) >= fence_counter; ++ }); + } + +-void CommandBufferManager::WaitForCommandBufferCompletion(u32 index) ++void CommandBufferManager::CleanupCompletedCommandBuffers() + { +- CmdBufferResources& resources = m_command_buffers[index]; +- +- // Ensure this command buffer has been submitted. +- if (resources.waiting_for_submit.load(std::memory_order_acquire)) +- { +- WaitForWorkerThreadIdle(); +- ASSERT_MSG(VIDEO, !resources.waiting_for_submit.load(std::memory_order_relaxed), +- "Submit thread is idle but command buffer is still waiting for submission!"); +- } +- +- // Wait for this command buffer to be completed. +- VkResult res = +- vkWaitForFences(g_vulkan_context->GetDevice(), 1, &resources.fence, VK_TRUE, UINT64_MAX); +- if (res != VK_SUCCESS) +- LOG_VULKAN_ERROR(res, "vkWaitForFences failed: "); +- + // Clean up any resources for command buffers between the last known completed buffer and this + // now-completed command buffer. If we use >2 buffers, this may be more than one buffer. +- const u64 now_completed_counter = resources.fence_counter; ++ const u64 now_completed_counter = m_completed_fence_counter.load(std::memory_order_acquire); + u32 cleanup_index = (m_current_cmd_buffer + 1) % NUM_COMMAND_BUFFERS; + while (cleanup_index != m_current_cmd_buffer) + { +@@ -312,26 +305,22 @@ void CommandBufferManager::WaitForComman + if (cleanup_resources.fence_counter > now_completed_counter) + break; + +- if (cleanup_resources.fence_counter > m_completed_fence_counter) +- { +- for (auto& it : cleanup_resources.cleanup_resources) +- it(); +- cleanup_resources.cleanup_resources.clear(); +- } ++ for (auto& it : cleanup_resources.cleanup_resources) ++ it(); ++ cleanup_resources.cleanup_resources.clear(); + + cleanup_index = (cleanup_index + 1) % NUM_COMMAND_BUFFERS; + } +- +- m_completed_fence_counter = now_completed_counter; + } + +-void CommandBufferManager::SubmitCommandBuffer(bool submit_on_worker_thread, ++void CommandBufferManager::SubmitCommandBuffer(u64 fence_counter, bool submit_on_worker_thread, + bool wait_for_completion, + VkSwapchainKHR present_swap_chain, + uint32_t present_image_index) + { + // End the current command buffer. + CmdBufferResources& resources = GetCurrentCmdBufferResources(); ++ resources.fence_counter = fence_counter; + for (VkCommandBuffer command_buffer : resources.command_buffers) + { + VkResult res = vkEndCommandBuffer(command_buffer); +@@ -344,32 +333,37 @@ void CommandBufferManager::SubmitCommand + } + + // Submitting off-thread? +- if (m_use_threaded_submission && submit_on_worker_thread && !wait_for_completion) ++ if (submit_on_worker_thread && !wait_for_completion) + { +- resources.waiting_for_submit.store(true, std::memory_order_relaxed); + // Push to the pending submit queue. + { + std::lock_guard guard(m_pending_submit_lock); + m_submit_worker_idle = false; + m_pending_submits.push_back({present_swap_chain, present_image_index, m_current_cmd_buffer}); +- } + +- // Wake up the worker thread for a single iteration. +- m_submit_loop->Wakeup(); ++ // Wake up the worker thread for a single iteration. ++ m_submit_loop->Wakeup(); ++ } + } + else + { +- WaitForWorkerThreadIdle(); ++ WaitForSubmitWorkerThreadIdle(); + + // Pass through to normal submission path. + SubmitCommandBuffer(m_current_cmd_buffer, present_swap_chain, present_image_index); + if (wait_for_completion) +- WaitForCommandBufferCompletion(m_current_cmd_buffer); ++ { ++ std::unique_lock lock{m_pending_fences_lock}; ++ m_fence_condvar.wait(lock, [&] { ++ return m_completed_fence_counter.load(std::memory_order_relaxed) >= resources.fence_counter; ++ }); ++ } + } + + if (present_swap_chain != VK_NULL_HANDLE) + { + m_current_frame = (m_current_frame + 1) % NUM_FRAMES_IN_FLIGHT; ++ const u64 now_completed_counter = m_completed_fence_counter.load(std::memory_order_acquire); + + // Wait for all command buffers that used the descriptor pool to finish + u32 cmd_buffer_index = (m_current_cmd_buffer + 1) % NUM_COMMAND_BUFFERS; +@@ -377,9 +371,9 @@ void CommandBufferManager::SubmitCommand + { + CmdBufferResources& cmd_buffer = m_command_buffers[cmd_buffer_index]; + if (cmd_buffer.frame_index == m_current_frame && cmd_buffer.fence_counter != 0 && +- cmd_buffer.fence_counter > m_completed_fence_counter) ++ cmd_buffer.fence_counter > now_completed_counter) + { +- WaitForCommandBufferCompletion(cmd_buffer_index); ++ WaitForFenceCounter(cmd_buffer.fence_counter); + } + cmd_buffer_index = (cmd_buffer_index + 1) % NUM_COMMAND_BUFFERS; + } +@@ -411,6 +405,7 @@ void CommandBufferManager::SubmitCommand + + // Switch to next cmdbuffer. + BeginCommandBuffer(); ++ m_state_tracker->InvalidateCachedState(); + } + + void CommandBufferManager::SubmitCommandBuffer(u32 command_buffer_index, +@@ -455,8 +450,15 @@ void CommandBufferManager::SubmitCommand + if (res != VK_SUCCESS) + { + LOG_VULKAN_ERROR(res, "vkQueueSubmit failed: "); +- PanicAlertFmt("Failed to submit command buffer: {} ({})", VkResultToString(res), +- static_cast(res)); ++ PanicAlertFmt("Failed to submit command buffer: {} ({}), semaphore used: {}, has present sc {}", ++ VkResultToString(res), static_cast(res), resources.semaphore_used, ++ present_swap_chain != VK_NULL_HANDLE); ++ } ++ ++ { ++ std::lock_guard guard(m_pending_fences_lock); ++ m_pending_fences.push_back({resources.fence, resources.fence_counter}); ++ m_fence_loop->Wakeup(); + } + + // Do we have a swap chain to present? +@@ -471,28 +473,27 @@ void CommandBufferManager::SubmitCommand + &present_swap_chain, + &present_image_index, + nullptr}; +- +- m_last_present_result = vkQueuePresentKHR(g_vulkan_context->GetPresentQueue(), &present_info); +- m_last_present_done.Set(); +- if (m_last_present_result != VK_SUCCESS) ++ res = vkQueuePresentKHR(g_vulkan_context->GetPresentQueue(), &present_info); ++ if (res != VK_SUCCESS) + { + // VK_ERROR_OUT_OF_DATE_KHR is not fatal, just means we need to recreate our swap chain. +- if (m_last_present_result != VK_ERROR_OUT_OF_DATE_KHR && +- m_last_present_result != VK_SUBOPTIMAL_KHR && +- m_last_present_result != VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT) ++ if (res != VK_ERROR_OUT_OF_DATE_KHR && res != VK_SUBOPTIMAL_KHR && ++ res != VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT) + { +- LOG_VULKAN_ERROR(m_last_present_result, "vkQueuePresentKHR failed: "); ++ LOG_VULKAN_ERROR(res, "vkQueuePresentKHR failed: "); + } + + // Don't treat VK_SUBOPTIMAL_KHR as fatal on Android. Android 10+ requires prerotation. + // See https://twitter.com/Themaister/status/1207062674011574273 + #ifdef VK_USE_PLATFORM_ANDROID_KHR +- if (m_last_present_result != VK_SUBOPTIMAL_KHR) ++ if (res != VK_SUBOPTIMAL_KHR) + m_last_present_failed.Set(); + #else + m_last_present_failed.Set(); + #endif + } ++ m_last_present_result.store(res); ++ m_last_present_done.Set(); + } + } + +@@ -503,8 +504,11 @@ void CommandBufferManager::BeginCommandB + CmdBufferResources& resources = m_command_buffers[next_buffer_index]; + + // Wait for the GPU to finish with all resources for this command buffer. +- if (resources.fence_counter > m_completed_fence_counter) +- WaitForCommandBufferCompletion(next_buffer_index); ++ if (resources.fence_counter > m_completed_fence_counter.load(std::memory_order_acquire) && ++ resources.fence_counter != 0) ++ WaitForFenceCounter(resources.fence_counter); ++ ++ CleanupCompletedCommandBuffers(); + + // Reset fence to unsignaled before starting. + VkResult res = vkResetFences(g_vulkan_context->GetDevice(), 1, &resources.fence); +@@ -526,10 +530,9 @@ void CommandBufferManager::BeginCommandB + LOG_VULKAN_ERROR(res, "vkBeginCommandBuffer failed: "); + } + +- // Reset upload command buffer state ++ // Reset command buffer state + resources.init_command_buffer_used = false; + resources.semaphore_used = false; +- resources.fence_counter = m_next_fence_counter++; + resources.frame_index = m_current_frame; + m_current_cmd_buffer = next_buffer_index; + } +@@ -569,6 +572,4 @@ void CommandBufferManager::DeferImageVie + cmd_buffer_resources.cleanup_resources.push_back( + [object]() { vkDestroyImageView(g_vulkan_context->GetDevice(), object, nullptr); }); + } +- +-std::unique_ptr g_command_buffer_mgr; + } // namespace Vulkan +diff -rupN dolphin.orig/Source/Core/VideoBackends/Vulkan/CommandBufferManager.h dolphin/Source/Core/VideoBackends/Vulkan/CommandBufferManager.h +--- dolphin.orig/Source/Core/VideoBackends/Vulkan/CommandBufferManager.h 2024-03-05 04:05:26.602983293 +0000 ++++ dolphin/Source/Core/VideoBackends/Vulkan/CommandBufferManager.h 2024-03-05 04:06:08.240295843 +0000 +@@ -22,10 +22,12 @@ + + namespace Vulkan + { ++class StateTracker; ++ + class CommandBufferManager + { + public: +- explicit CommandBufferManager(bool use_threaded_submission); ++ explicit CommandBufferManager(); + ~CommandBufferManager(); + + bool Initialize(); +@@ -50,39 +52,37 @@ public: + // If the last completed fence counter is greater or equal to N, it means that the work + // associated counter N has been completed by the GPU. The value of N to associate with + // commands can be retreived by calling GetCurrentFenceCounter(). +- u64 GetCompletedFenceCounter() const { return m_completed_fence_counter; } +- +- // Gets the fence that will be signaled when the currently executing command buffer is +- // queued and executed. Do not wait for this fence before the buffer is executed. +- u64 GetCurrentFenceCounter() const ++ // THREAD SAFE ++ u64 GetCompletedFenceCounter() const + { +- auto& resources = m_command_buffers[m_current_cmd_buffer]; +- return resources.fence_counter; ++ return m_completed_fence_counter.load(std::memory_order_acquire); + } + + // Returns the semaphore for the current command buffer, which can be used to ensure the + // swap chain image is ready before the command buffer executes. +- VkSemaphore GetCurrentCommandBufferSemaphore() ++ void SetWaitSemaphoreForCurrentCommandBuffer(VkSemaphore semaphore) + { + auto& resources = m_command_buffers[m_current_cmd_buffer]; + resources.semaphore_used = true; +- return resources.semaphore; ++ resources.semaphore = semaphore; + } + + // Ensure that the worker thread has submitted any previous command buffers and is idle. +- void WaitForWorkerThreadIdle(); ++ void WaitForSubmitWorkerThreadIdle(); + + // Wait for a fence to be completed. + // Also invokes callbacks for completion. ++ // THREAD SAFE + void WaitForFenceCounter(u64 fence_counter); + +- void SubmitCommandBuffer(bool submit_on_worker_thread, bool wait_for_completion, ++ void SubmitCommandBuffer(u64 fence_counter, bool submit_on_worker_thread, ++ bool wait_for_completion, + VkSwapchainKHR present_swap_chain = VK_NULL_HANDLE, + uint32_t present_image_index = 0xFFFFFFFF); + + // Was the last present submitted to the queue a failure? If so, we must recreate our swapchain. + bool CheckLastPresentFail() { return m_last_present_failed.TestAndClear(); } +- VkResult GetLastPresentResult() const { return m_last_present_result; } ++ VkResult GetLastPresentResult() const { return m_last_present_result.load(); } + bool CheckLastPresentDone() { return m_last_present_done.TestAndClear(); } + + // Schedule a vulkan resource for destruction later on. This will occur when the command buffer +@@ -93,17 +93,21 @@ public: + void DeferImageDestruction(VkImage object, VmaAllocation alloc); + void DeferImageViewDestruction(VkImageView object); + ++ StateTracker* GetStateTracker() { return m_state_tracker.get(); } ++ + private: + bool CreateCommandBuffers(); + void DestroyCommandBuffers(); + ++ bool CreateFenceThread(); + bool CreateSubmitThread(); + +- void WaitForCommandBufferCompletion(u32 command_buffer_index); + void SubmitCommandBuffer(u32 command_buffer_index, VkSwapchainKHR present_swap_chain, + u32 present_image_index); + void BeginCommandBuffer(); + ++ void CleanupCompletedCommandBuffers(); ++ + VkDescriptorPool CreateDescriptorPool(u32 descriptor_sizes); + + const u32 DESCRIPTOR_SETS_PER_POOL = 1024; +@@ -118,7 +122,6 @@ private: + u64 fence_counter = 0; + bool init_command_buffer_used = false; + bool semaphore_used = false; +- std::atomic waiting_for_submit{false}; + u32 frame_index = 0; + + std::vector> cleanup_resources; +@@ -137,14 +140,15 @@ private: + return m_command_buffers[m_current_cmd_buffer]; + } + +- u64 m_next_fence_counter = 1; +- u64 m_completed_fence_counter = 0; ++ std::atomic m_completed_fence_counter = 0; + + std::array m_frame_resources; + std::array m_command_buffers; + u32 m_current_frame = 0; + u32 m_current_cmd_buffer = 0; + ++ std::unique_ptr m_state_tracker; ++ + // Threaded command buffer execution + std::thread m_submit_thread; + std::unique_ptr m_submit_loop; +@@ -161,11 +165,20 @@ private: + bool m_submit_worker_idle = true; + Common::Flag m_last_present_failed; + Common::Flag m_last_present_done; +- VkResult m_last_present_result = VK_SUCCESS; +- bool m_use_threaded_submission = false; ++ std::atomic m_last_present_result = VK_SUCCESS; + u32 m_descriptor_set_count = DESCRIPTOR_SETS_PER_POOL; +-}; + +-extern std::unique_ptr g_command_buffer_mgr; ++ // Fence thread ++ std::thread m_fence_thread; ++ std::unique_ptr m_fence_loop; ++ struct PendingFenceCounter ++ { ++ VkFence fence; ++ u64 counter; ++ }; ++ std::deque m_pending_fences; ++ std::mutex m_pending_fences_lock; ++ std::condition_variable m_fence_condvar; ++}; + + } // namespace Vulkan +diff -rupN dolphin.orig/Source/Core/VideoBackends/Vulkan/Constants.h dolphin/Source/Core/VideoBackends/Vulkan/Constants.h +--- dolphin.orig/Source/Core/VideoBackends/Vulkan/Constants.h 2024-03-05 04:05:26.602983293 +0000 ++++ dolphin/Source/Core/VideoBackends/Vulkan/Constants.h 2024-03-05 04:06:08.240295843 +0000 +@@ -12,7 +12,7 @@ + namespace Vulkan + { + // Number of command buffers. +-constexpr size_t NUM_COMMAND_BUFFERS = 8; ++constexpr size_t NUM_COMMAND_BUFFERS = 16; + + // Number of frames in flight, will be used to decide how many descriptor pools are used + constexpr size_t NUM_FRAMES_IN_FLIGHT = 2; +diff -rupN dolphin.orig/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp dolphin/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp +--- dolphin.orig/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp 2024-03-05 04:05:26.602983293 +0000 ++++ dolphin/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp 2024-03-05 04:06:08.240295843 +0000 +@@ -389,6 +389,8 @@ VkSampler ObjectCache::GetSampler(const + VkRenderPass ObjectCache::GetRenderPass(VkFormat color_format, VkFormat depth_format, + u32 multisamples, VkAttachmentLoadOp load_op) + { ++ std::scoped_lock lock(m_render_pass_mutex); ++ + auto key = std::tie(color_format, depth_format, multisamples, load_op); + auto it = m_render_pass_cache.find(key); + if (it != m_render_pass_cache.end()) +@@ -467,6 +469,8 @@ VkRenderPass ObjectCache::GetRenderPass( + + void ObjectCache::DestroyRenderPassCache() + { ++ std::scoped_lock lock(m_render_pass_mutex); ++ + for (auto& it : m_render_pass_cache) + vkDestroyRenderPass(g_vulkan_context->GetDevice(), it.second, nullptr); + m_render_pass_cache.clear(); +diff -rupN dolphin.orig/Source/Core/VideoBackends/Vulkan/ObjectCache.h dolphin/Source/Core/VideoBackends/Vulkan/ObjectCache.h +--- dolphin.orig/Source/Core/VideoBackends/Vulkan/ObjectCache.h 2024-03-05 04:05:26.602983293 +0000 ++++ dolphin/Source/Core/VideoBackends/Vulkan/ObjectCache.h 2024-03-05 04:06:08.240295843 +0000 +@@ -7,6 +7,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -102,6 +103,7 @@ private: + std::unique_ptr m_dummy_texture; + + // Render pass cache ++ std::mutex m_render_pass_mutex; + using RenderPassCacheKey = std::tuple; + std::map m_render_pass_cache; + +diff -rupN dolphin.orig/Source/Core/VideoBackends/Vulkan/StagingBuffer.cpp dolphin/Source/Core/VideoBackends/Vulkan/StagingBuffer.cpp +--- dolphin.orig/Source/Core/VideoBackends/Vulkan/StagingBuffer.cpp 2024-03-05 04:05:26.602983293 +0000 ++++ dolphin/Source/Core/VideoBackends/Vulkan/StagingBuffer.cpp 2024-03-05 04:06:08.240295843 +0000 +@@ -8,6 +8,7 @@ + + #include "Common/Assert.h" + ++#include "VKScheduler.h" + #include "VideoBackends/Vulkan/CommandBufferManager.h" + #include "VideoBackends/Vulkan/VulkanContext.h" + #include "VideoCommon/DriverDetails.h" +@@ -26,7 +27,10 @@ StagingBuffer::~StagingBuffer() + if (m_map_pointer) + Unmap(); + +- g_command_buffer_mgr->DeferBufferDestruction(m_buffer, m_alloc); ++ g_scheduler->Record( ++ [c_alloc = m_alloc, c_buffer = m_buffer](CommandBufferManager* command_buffer_mgr) { ++ command_buffer_mgr->DeferBufferDestruction(c_buffer, c_alloc); ++ }); + } + + void StagingBuffer::BufferMemoryBarrier(VkCommandBuffer command_buffer, VkBuffer buffer, +diff -rupN dolphin.orig/Source/Core/VideoBackends/Vulkan/StateTracker.cpp dolphin/Source/Core/VideoBackends/Vulkan/StateTracker.cpp +--- dolphin.orig/Source/Core/VideoBackends/Vulkan/StateTracker.cpp 2024-03-05 04:05:26.602983293 +0000 ++++ dolphin/Source/Core/VideoBackends/Vulkan/StateTracker.cpp 2024-03-05 04:06:08.240295843 +0000 +@@ -16,59 +16,93 @@ + + namespace Vulkan + { +-static std::unique_ptr s_state_tracker; +- +-StateTracker::StateTracker() = default; +- +-StateTracker::~StateTracker() = default; ++StateTracker::StateTracker(CommandBufferManager* command_buffer_mgr) ++ : m_command_buffer_mgr(command_buffer_mgr) ++{ ++} + +-StateTracker* StateTracker::GetInstance() ++StateTracker::~StateTracker() + { +- return s_state_tracker.get(); ++ vkDestroyImageView(g_vulkan_context->GetDevice(), m_dummy_view, nullptr); ++ vmaDestroyImage(g_vulkan_context->GetMemoryAllocator(), m_dummy_image, m_dummy_alloc); + } + +-bool StateTracker::CreateInstance() ++bool StateTracker::Initialize() + { +- ASSERT(!s_state_tracker); +- s_state_tracker = std::make_unique(); +- if (!s_state_tracker->Initialize()) ++ // Create a dummy texture which can be used in place of a real binding. ++ VkImageCreateInfo dummy_info; ++ dummy_info.pNext = nullptr; ++ dummy_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; ++ dummy_info.extent = {1, 1, 1}; ++ dummy_info.arrayLayers = 1; ++ dummy_info.mipLevels = 1; ++ dummy_info.flags = 0; ++ dummy_info.imageType = VK_IMAGE_TYPE_2D; ++ dummy_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; ++ dummy_info.samples = VK_SAMPLE_COUNT_1_BIT; ++ dummy_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; ++ dummy_info.format = VK_FORMAT_R8G8B8A8_UNORM; ++ dummy_info.tiling = VK_IMAGE_TILING_OPTIMAL; ++ dummy_info.queueFamilyIndexCount = 0; ++ dummy_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT; ++ dummy_info.pQueueFamilyIndices = nullptr; ++ ++ VmaAllocationCreateInfo alloc_create_info = {}; ++ alloc_create_info.flags = VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT; ++ alloc_create_info.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE; ++ alloc_create_info.pool = VK_NULL_HANDLE; ++ alloc_create_info.pUserData = nullptr; ++ alloc_create_info.priority = 0.0; ++ alloc_create_info.requiredFlags = 0; ++ alloc_create_info.preferredFlags = 0; ++ ++ VkResult res = vmaCreateImage(g_vulkan_context->GetMemoryAllocator(), &dummy_info, ++ &alloc_create_info, &m_dummy_image, &m_dummy_alloc, nullptr); ++ if (res != VK_SUCCESS) + { +- s_state_tracker.reset(); ++ LOG_VULKAN_ERROR(res, "vmaCreateImage failed: "); + return false; + } +- return true; +-} + +-void StateTracker::DestroyInstance() +-{ +- if (!s_state_tracker) +- return; ++ VkImageViewCreateInfo dummy_view_info; ++ dummy_view_info.pNext = nullptr; ++ dummy_view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; ++ dummy_view_info.flags = 0; ++ dummy_view_info.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY; ++ dummy_view_info.format = VK_FORMAT_R8G8B8A8_UNORM; ++ dummy_view_info.components = {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, ++ VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY}; ++ dummy_view_info.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; ++ dummy_view_info.image = m_dummy_image; + +- // When the dummy texture is destroyed, it unbinds itself, then references itself. +- // Clear everything out so this doesn't happen. +- for (auto& it : s_state_tracker->m_bindings.samplers) +- it.imageView = VK_NULL_HANDLE; +- s_state_tracker->m_bindings.image_texture.imageView = VK_NULL_HANDLE; +- s_state_tracker->m_dummy_texture.reset(); +- +- s_state_tracker.reset(); +-} +- +-bool StateTracker::Initialize() +-{ +- // Create a dummy texture which can be used in place of a real binding. +- m_dummy_texture = +- VKTexture::Create(TextureConfig(1, 1, 1, 1, 1, AbstractTextureFormat::RGBA8, 0), ""); +- if (!m_dummy_texture) ++ res = vkCreateImageView(g_vulkan_context->GetDevice(), &dummy_view_info, nullptr, &m_dummy_view); ++ if (res != VK_SUCCESS) ++ { ++ LOG_VULKAN_ERROR(res, "vkCreateImageView failed: "); + return false; +- m_dummy_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentInitCommandBuffer(), +- VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); ++ } ++ ++ VkImageMemoryBarrier img_barrier; ++ img_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; ++ img_barrier.pNext = nullptr; ++ img_barrier.srcAccessMask = 0; ++ img_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; ++ img_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; ++ img_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; ++ img_barrier.image = m_dummy_image; ++ img_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; ++ img_barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; ++ img_barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; ++ ++ vkCmdPipelineBarrier(m_command_buffer_mgr->GetCurrentInitCommandBuffer(), ++ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, ++ nullptr, 0, nullptr, 1, &img_barrier); + + // Initialize all samplers to point by default + for (size_t i = 0; i < NUM_PIXEL_SHADER_SAMPLERS; i++) + { + m_bindings.samplers[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; +- m_bindings.samplers[i].imageView = m_dummy_texture->GetView(); ++ m_bindings.samplers[i].imageView = m_dummy_view; + m_bindings.samplers[i].sampler = g_object_cache->GetPointSampler(); + } + +@@ -107,11 +141,17 @@ void StateTracker::SetIndexBuffer(VkBuff + m_dirty_flags |= DIRTY_FLAG_INDEX_BUFFER; + } + +-void StateTracker::SetFramebuffer(VKFramebuffer* framebuffer) ++void StateTracker::SetFramebuffer(VkFramebuffer framebuffer, VkRect2D render_area, ++ VkRenderPass load_render_pass, VkRenderPass clear_render_pass, ++ VkRenderPass discard_render_pass) + { + // Should not be changed within a render pass. + ASSERT(!InRenderPass()); + m_framebuffer = framebuffer; ++ m_framebuffer_render_area = render_area; ++ m_framebuffer_load_render_pass = load_render_pass; ++ m_framebuffer_clear_render_pass = clear_render_pass; ++ m_framebuffer_discard_render_pass = discard_render_pass; + } + + void StateTracker::SetPipeline(const VKPipeline* pipeline) +@@ -232,14 +272,14 @@ void StateTracker::UnbindTexture(VkImage + { + if (it.imageView == view) + { +- it.imageView = m_dummy_texture->GetView(); ++ it.imageView = m_dummy_view; + it.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + } + } + + if (m_bindings.image_texture.imageView == view) + { +- m_bindings.image_texture.imageView = m_dummy_texture->GetView(); ++ m_bindings.image_texture.imageView = m_dummy_view; + m_bindings.image_texture.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + } + } +@@ -263,18 +303,18 @@ void StateTracker::BeginRenderPass() + if (InRenderPass()) + return; + +- m_current_render_pass = m_framebuffer->GetLoadRenderPass(); +- m_framebuffer_render_area = m_framebuffer->GetRect(); ++ m_current_render_pass = m_framebuffer_load_render_pass; ++ m_render_area = m_framebuffer_render_area; + + VkRenderPassBeginInfo begin_info = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, + nullptr, + m_current_render_pass, +- m_framebuffer->GetFB(), +- m_framebuffer_render_area, ++ m_framebuffer, ++ m_render_area, + 0, + nullptr}; + +- vkCmdBeginRenderPass(g_command_buffer_mgr->GetCurrentCommandBuffer(), &begin_info, ++ vkCmdBeginRenderPass(m_command_buffer_mgr->GetCurrentCommandBuffer(), &begin_info, + VK_SUBPASS_CONTENTS_INLINE); + } + +@@ -283,18 +323,18 @@ void StateTracker::BeginDiscardRenderPas + if (InRenderPass()) + return; + +- m_current_render_pass = m_framebuffer->GetDiscardRenderPass(); +- m_framebuffer_render_area = m_framebuffer->GetRect(); ++ m_current_render_pass = m_framebuffer_discard_render_pass; ++ m_render_area = m_framebuffer_render_area; + + VkRenderPassBeginInfo begin_info = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, + nullptr, + m_current_render_pass, +- m_framebuffer->GetFB(), +- m_framebuffer_render_area, ++ m_framebuffer, ++ m_render_area, + 0, + nullptr}; + +- vkCmdBeginRenderPass(g_command_buffer_mgr->GetCurrentCommandBuffer(), &begin_info, ++ vkCmdBeginRenderPass(m_command_buffer_mgr->GetCurrentCommandBuffer(), &begin_info, + VK_SUBPASS_CONTENTS_INLINE); + } + +@@ -303,7 +343,7 @@ void StateTracker::EndRenderPass() + if (!InRenderPass()) + return; + +- vkCmdEndRenderPass(g_command_buffer_mgr->GetCurrentCommandBuffer()); ++ vkCmdEndRenderPass(m_command_buffer_mgr->GetCurrentCommandBuffer()); + m_current_render_pass = VK_NULL_HANDLE; + } + +@@ -312,18 +352,18 @@ void StateTracker::BeginClearRenderPass( + { + ASSERT(!InRenderPass()); + +- m_current_render_pass = m_framebuffer->GetClearRenderPass(); +- m_framebuffer_render_area = area; ++ m_current_render_pass = m_framebuffer_clear_render_pass; ++ m_render_area = area; + + VkRenderPassBeginInfo begin_info = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, + nullptr, + m_current_render_pass, +- m_framebuffer->GetFB(), +- m_framebuffer_render_area, ++ m_framebuffer, ++ m_render_area, + num_clear_values, + clear_values}; + +- vkCmdBeginRenderPass(g_command_buffer_mgr->GetCurrentCommandBuffer(), &begin_info, ++ vkCmdBeginRenderPass(m_command_buffer_mgr->GetCurrentCommandBuffer(), &begin_info, + VK_SUBPASS_CONTENTS_INLINE); + } + +@@ -352,7 +392,7 @@ bool StateTracker::Bind() + return false; + + // Check the render area if we were in a clear pass. +- if (m_current_render_pass == m_framebuffer->GetClearRenderPass() && !IsViewportWithinRenderArea()) ++ if (m_current_render_pass == m_framebuffer_clear_render_pass && !IsViewportWithinRenderArea()) + EndRenderPass(); + + // Get a new descriptor set if any parts have changed +@@ -363,7 +403,7 @@ bool StateTracker::Bind() + BeginRenderPass(); + + // Re-bind parts of the pipeline +- const VkCommandBuffer command_buffer = g_command_buffer_mgr->GetCurrentCommandBuffer(); ++ const VkCommandBuffer command_buffer = m_command_buffer_mgr->GetCurrentCommandBuffer(); + const bool needs_vertex_buffer = !g_ActiveConfig.backend_info.bSupportsDynamicVertexLoader || + m_pipeline->GetUsage() != AbstractPipelineUsage::GXUber; + if (needs_vertex_buffer && (m_dirty_flags & DIRTY_FLAG_VERTEX_BUFFER)) +@@ -398,7 +438,7 @@ bool StateTracker::BindCompute() + if (InRenderPass()) + EndRenderPass(); + +- const VkCommandBuffer command_buffer = g_command_buffer_mgr->GetCurrentCommandBuffer(); ++ const VkCommandBuffer command_buffer = m_command_buffer_mgr->GetCurrentCommandBuffer(); + if (m_dirty_flags & DIRTY_FLAG_COMPUTE_SHADER) + { + vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, +@@ -414,10 +454,10 @@ bool StateTracker::IsWithinRenderArea(s3 + { + // Check that the viewport does not lie outside the render area. + // If it does, we need to switch to a normal load/store render pass. +- s32 left = m_framebuffer_render_area.offset.x; +- s32 top = m_framebuffer_render_area.offset.y; +- s32 right = left + static_cast(m_framebuffer_render_area.extent.width); +- s32 bottom = top + static_cast(m_framebuffer_render_area.extent.height); ++ s32 left = m_render_area.offset.x; ++ s32 top = m_render_area.offset.y; ++ s32 right = left + static_cast(m_render_area.extent.width); ++ s32 bottom = top + static_cast(m_render_area.extent.height); + s32 test_left = x; + s32 test_top = y; + s32 test_right = test_left + static_cast(width); +@@ -434,7 +474,7 @@ bool StateTracker::IsViewportWithinRende + + void StateTracker::EndClearRenderPass() + { +- if (m_current_render_pass != m_framebuffer->GetClearRenderPass()) ++ if (m_current_render_pass != m_framebuffer_clear_render_pass) + return; + + // End clear render pass. Bind() will call BeginRenderPass() which +@@ -463,7 +503,7 @@ void StateTracker::UpdateGXDescriptorSet + + if (m_dirty_flags & DIRTY_FLAG_GX_UBOS || m_gx_descriptor_sets[0] == VK_NULL_HANDLE) + { +- m_gx_descriptor_sets[0] = g_command_buffer_mgr->AllocateDescriptorSet( ++ m_gx_descriptor_sets[0] = m_command_buffer_mgr->AllocateDescriptorSet( + g_object_cache->GetDescriptorSetLayout(DESCRIPTOR_SET_LAYOUT_STANDARD_UNIFORM_BUFFERS)); + + for (size_t i = 0; i < NUM_UBO_DESCRIPTOR_SET_BINDINGS; i++) +@@ -490,7 +530,7 @@ void StateTracker::UpdateGXDescriptorSet + + if (m_dirty_flags & DIRTY_FLAG_GX_SAMPLERS || m_gx_descriptor_sets[1] == VK_NULL_HANDLE) + { +- m_gx_descriptor_sets[1] = g_command_buffer_mgr->AllocateDescriptorSet( ++ m_gx_descriptor_sets[1] = m_command_buffer_mgr->AllocateDescriptorSet( + g_object_cache->GetDescriptorSetLayout(DESCRIPTOR_SET_LAYOUT_STANDARD_SAMPLERS)); + + writes[num_writes++] = {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, +@@ -516,7 +556,7 @@ void StateTracker::UpdateGXDescriptorSet + (m_dirty_flags & DIRTY_FLAG_GX_SSBO || m_gx_descriptor_sets[2] == VK_NULL_HANDLE)) + { + m_gx_descriptor_sets[2] = +- g_command_buffer_mgr->AllocateDescriptorSet(g_object_cache->GetDescriptorSetLayout( ++ m_command_buffer_mgr->AllocateDescriptorSet(g_object_cache->GetDescriptorSetLayout( + DESCRIPTOR_SET_LAYOUT_STANDARD_SHADER_STORAGE_BUFFERS)); + + writes[num_writes++] = { +@@ -546,7 +586,7 @@ void StateTracker::UpdateGXDescriptorSet + + if (m_dirty_flags & DIRTY_FLAG_DESCRIPTOR_SETS) + { +- vkCmdBindDescriptorSets(g_command_buffer_mgr->GetCurrentCommandBuffer(), ++ vkCmdBindDescriptorSets(m_command_buffer_mgr->GetCurrentCommandBuffer(), + VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline->GetVkPipelineLayout(), 0, + needs_ssbo ? NUM_GX_DESCRIPTOR_SETS : (NUM_GX_DESCRIPTOR_SETS - 1), + m_gx_descriptor_sets.data(), +@@ -558,7 +598,7 @@ void StateTracker::UpdateGXDescriptorSet + else if (m_dirty_flags & DIRTY_FLAG_GX_UBO_OFFSETS) + { + vkCmdBindDescriptorSets( +- g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_PIPELINE_BIND_POINT_GRAPHICS, ++ m_command_buffer_mgr->GetCurrentCommandBuffer(), VK_PIPELINE_BIND_POINT_GRAPHICS, + m_pipeline->GetVkPipelineLayout(), 0, 1, m_gx_descriptor_sets.data(), + needs_gs_ubo ? NUM_UBO_DESCRIPTOR_SET_BINDINGS : (NUM_UBO_DESCRIPTOR_SET_BINDINGS - 1), + m_bindings.gx_ubo_offsets.data()); +@@ -575,7 +615,7 @@ void StateTracker::UpdateUtilityDescript + // Allocate descriptor sets. + if (m_dirty_flags & DIRTY_FLAG_UTILITY_UBO || m_utility_descriptor_sets[0] == VK_NULL_HANDLE) + { +- m_utility_descriptor_sets[0] = g_command_buffer_mgr->AllocateDescriptorSet( ++ m_utility_descriptor_sets[0] = m_command_buffer_mgr->AllocateDescriptorSet( + g_object_cache->GetDescriptorSetLayout(DESCRIPTOR_SET_LAYOUT_UTILITY_UNIFORM_BUFFER)); + + dswrites[writes++] = {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, +@@ -594,7 +634,7 @@ void StateTracker::UpdateUtilityDescript + + if (m_dirty_flags & DIRTY_FLAG_UTILITY_BINDINGS || m_utility_descriptor_sets[1] == VK_NULL_HANDLE) + { +- m_utility_descriptor_sets[1] = g_command_buffer_mgr->AllocateDescriptorSet( ++ m_utility_descriptor_sets[1] = m_command_buffer_mgr->AllocateDescriptorSet( + g_object_cache->GetDescriptorSetLayout(DESCRIPTOR_SET_LAYOUT_UTILITY_SAMPLERS)); + + dswrites[writes++] = {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, +@@ -626,7 +666,7 @@ void StateTracker::UpdateUtilityDescript + + if (m_dirty_flags & DIRTY_FLAG_DESCRIPTOR_SETS) + { +- vkCmdBindDescriptorSets(g_command_buffer_mgr->GetCurrentCommandBuffer(), ++ vkCmdBindDescriptorSets(m_command_buffer_mgr->GetCurrentCommandBuffer(), + VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline->GetVkPipelineLayout(), 0, + NUM_UTILITY_DESCRIPTOR_SETS, m_utility_descriptor_sets.data(), 1, + &m_bindings.utility_ubo_offset); +@@ -634,7 +674,7 @@ void StateTracker::UpdateUtilityDescript + } + else if (m_dirty_flags & DIRTY_FLAG_UTILITY_UBO_OFFSET) + { +- vkCmdBindDescriptorSets(g_command_buffer_mgr->GetCurrentCommandBuffer(), ++ vkCmdBindDescriptorSets(m_command_buffer_mgr->GetCurrentCommandBuffer(), + VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline->GetVkPipelineLayout(), 0, + 1, m_utility_descriptor_sets.data(), 1, &m_bindings.utility_ubo_offset); + m_dirty_flags &= ~(DIRTY_FLAG_DESCRIPTOR_SETS | DIRTY_FLAG_UTILITY_UBO_OFFSET); +@@ -649,7 +689,7 @@ void StateTracker::UpdateComputeDescript + // Allocate descriptor sets. + if (m_dirty_flags & DIRTY_FLAG_COMPUTE_BINDINGS) + { +- m_compute_descriptor_set = g_command_buffer_mgr->AllocateDescriptorSet( ++ m_compute_descriptor_set = m_command_buffer_mgr->AllocateDescriptorSet( + g_object_cache->GetDescriptorSetLayout(DESCRIPTOR_SET_LAYOUT_COMPUTE)); + dswrites[0] = {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + nullptr, +@@ -700,7 +740,7 @@ void StateTracker::UpdateComputeDescript + + if (m_dirty_flags & DIRTY_FLAG_COMPUTE_DESCRIPTOR_SET) + { +- vkCmdBindDescriptorSets(g_command_buffer_mgr->GetCurrentCommandBuffer(), ++ vkCmdBindDescriptorSets(m_command_buffer_mgr->GetCurrentCommandBuffer(), + VK_PIPELINE_BIND_POINT_COMPUTE, + g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_COMPUTE), 0, 1, + &m_compute_descriptor_set, 1, &m_bindings.utility_ubo_offset); +diff -rupN dolphin.orig/Source/Core/VideoBackends/Vulkan/StateTracker.h dolphin/Source/Core/VideoBackends/Vulkan/StateTracker.h +--- dolphin.orig/Source/Core/VideoBackends/Vulkan/StateTracker.h 2024-03-05 04:05:26.602983293 +0000 ++++ dolphin/Source/Core/VideoBackends/Vulkan/StateTracker.h 2024-03-05 04:06:08.240295843 +0000 +@@ -13,28 +13,24 @@ + + namespace Vulkan + { +-class VKFramebuffer; + class VKShader; + class VKPipeline; +-class VKTexture; +-class StreamBuffer; +-class VertexFormat; ++class CommandBufferManager; + + class StateTracker + { + public: +- StateTracker(); ++ StateTracker(CommandBufferManager* command_buffer_mgr); + ~StateTracker(); + +- static StateTracker* GetInstance(); +- static bool CreateInstance(); +- static void DestroyInstance(); ++ bool Initialize(); + +- VKFramebuffer* GetFramebuffer() const { return m_framebuffer; } + const VKPipeline* GetPipeline() const { return m_pipeline; } + void SetVertexBuffer(VkBuffer buffer, VkDeviceSize offset, u32 size); + void SetIndexBuffer(VkBuffer buffer, VkDeviceSize offset, VkIndexType type); +- void SetFramebuffer(VKFramebuffer* framebuffer); ++ void SetFramebuffer(VkFramebuffer framebuffer, VkRect2D render_area, ++ VkRenderPass load_render_pass, VkRenderPass clear_render_pass, ++ VkRenderPass discard_render_pass); + void SetPipeline(const VKPipeline* pipeline); + void SetComputeShader(const VKShader* shader); + void SetGXUniformBuffer(u32 index, VkBuffer buffer, u32 offset, u32 size); +@@ -110,8 +106,6 @@ private: + DIRTY_FLAG_UTILITY_BINDINGS | DIRTY_FLAG_COMPUTE_BINDINGS + }; + +- bool Initialize(); +- + // Check that the specified viewport is within the render area. + // If not, ends the render pass if it is a clear render pass. + bool IsViewportWithinRenderArea() const; +@@ -121,6 +115,8 @@ private: + void UpdateUtilityDescriptorSet(); + void UpdateComputeDescriptorSet(); + ++ CommandBufferManager* m_command_buffer_mgr; ++ + // Which bindings/state has to be updated before the next draw. + u32 m_dirty_flags = 0; + +@@ -157,10 +153,17 @@ private: + VkRect2D m_scissor = {{0, 0}, {1, 1}}; + + // uniform buffers +- std::unique_ptr m_dummy_texture; ++ VkImage m_dummy_image; ++ VkImageView m_dummy_view; ++ VmaAllocation m_dummy_alloc; + +- VKFramebuffer* m_framebuffer = nullptr; +- VkRenderPass m_current_render_pass = VK_NULL_HANDLE; ++ VkFramebuffer m_framebuffer = VK_NULL_HANDLE; + VkRect2D m_framebuffer_render_area = {}; ++ VkRenderPass m_framebuffer_load_render_pass = VK_NULL_HANDLE; ++ VkRenderPass m_framebuffer_discard_render_pass = VK_NULL_HANDLE; ++ VkRenderPass m_framebuffer_clear_render_pass = VK_NULL_HANDLE; ++ ++ VkRenderPass m_current_render_pass = VK_NULL_HANDLE; ++ VkRect2D m_render_area = {}; + }; + } // namespace Vulkan +diff -rupN dolphin.orig/Source/Core/VideoBackends/Vulkan/VKBoundingBox.cpp dolphin/Source/Core/VideoBackends/Vulkan/VKBoundingBox.cpp +--- dolphin.orig/Source/Core/VideoBackends/Vulkan/VKBoundingBox.cpp 2024-03-05 04:05:26.602983293 +0000 ++++ dolphin/Source/Core/VideoBackends/Vulkan/VKBoundingBox.cpp 2024-03-05 04:06:08.240295843 +0000 +@@ -12,6 +12,7 @@ + #include "VideoBackends/Vulkan/StagingBuffer.h" + #include "VideoBackends/Vulkan/StateTracker.h" + #include "VideoBackends/Vulkan/VKRenderer.h" ++#include "VideoBackends/Vulkan/VKScheduler.h" + #include "VideoBackends/Vulkan/VulkanContext.h" + + namespace Vulkan +@@ -33,36 +34,43 @@ bool VKBoundingBox::Initialize() + return false; + + // Bind bounding box to state tracker +- StateTracker::GetInstance()->SetSSBO(m_gpu_buffer, 0, BUFFER_SIZE); ++ g_scheduler->Record([c_gpu_buffer = m_gpu_buffer](CommandBufferManager* command_buffer_mgr) { ++ command_buffer_mgr->GetStateTracker()->SetSSBO(c_gpu_buffer, 0, BUFFER_SIZE); ++ }); + return true; + } + + std::vector VKBoundingBox::Read(u32 index, u32 length) + { +- // Can't be done within a render pass. +- StateTracker::GetInstance()->EndRenderPass(); +- +- // Ensure all writes are completed to the GPU buffer prior to the transfer. +- StagingBuffer::BufferMemoryBarrier( +- g_command_buffer_mgr->GetCurrentCommandBuffer(), m_gpu_buffer, +- VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, 0, +- BUFFER_SIZE, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); +- m_readback_buffer->PrepareForGPUWrite(g_command_buffer_mgr->GetCurrentCommandBuffer(), +- VK_ACCESS_TRANSFER_WRITE_BIT, +- VK_PIPELINE_STAGE_TRANSFER_BIT); +- +- // Copy from GPU -> readback buffer. +- VkBufferCopy region = {0, 0, BUFFER_SIZE}; +- vkCmdCopyBuffer(g_command_buffer_mgr->GetCurrentCommandBuffer(), m_gpu_buffer, +- m_readback_buffer->GetBuffer(), 1, ®ion); +- +- // Restore GPU buffer access. +- StagingBuffer::BufferMemoryBarrier( +- g_command_buffer_mgr->GetCurrentCommandBuffer(), m_gpu_buffer, VK_ACCESS_TRANSFER_READ_BIT, +- VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, 0, BUFFER_SIZE, +- VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); +- m_readback_buffer->FlushGPUCache(g_command_buffer_mgr->GetCurrentCommandBuffer(), +- VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); ++ std::vector values(length); ++ // We can just take a reference here, we'll sync immediately afterwards ++ g_scheduler->Record([&](CommandBufferManager* command_buffer_mgr) { ++ // Can't be done within a render pass. ++ command_buffer_mgr->GetStateTracker()->EndRenderPass(); ++ ++ // Ensure all writes are completed to the GPU buffer prior to the transfer. ++ StagingBuffer::BufferMemoryBarrier( ++ command_buffer_mgr->GetCurrentCommandBuffer(), m_gpu_buffer, ++ VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, 0, ++ BUFFER_SIZE, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); ++ ++ m_readback_buffer->PrepareForGPUWrite(command_buffer_mgr->GetCurrentCommandBuffer(), ++ VK_ACCESS_TRANSFER_WRITE_BIT, ++ VK_PIPELINE_STAGE_TRANSFER_BIT); ++ ++ // Copy from GPU -> readback buffer. ++ VkBufferCopy region = {0, 0, BUFFER_SIZE}; ++ vkCmdCopyBuffer(command_buffer_mgr->GetCurrentCommandBuffer(), m_gpu_buffer, ++ m_readback_buffer->GetBuffer(), 1, ®ion); ++ ++ // Restore GPU buffer access. ++ StagingBuffer::BufferMemoryBarrier( ++ command_buffer_mgr->GetCurrentCommandBuffer(), m_gpu_buffer, VK_ACCESS_TRANSFER_READ_BIT, ++ VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, 0, BUFFER_SIZE, ++ VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); ++ m_readback_buffer->FlushGPUCache(command_buffer_mgr->GetCurrentCommandBuffer(), ++ VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); ++ }); + + // Wait until these commands complete. + Renderer::GetInstance()->ExecuteCommandBuffer(false, true); +@@ -71,34 +79,37 @@ std::vector VKBoundingBox::Rea + m_readback_buffer->InvalidateCPUCache(); + + // Read out the values and return +- std::vector values(length); + m_readback_buffer->Read(index * sizeof(BBoxType), values.data(), length * sizeof(BBoxType), + false); ++ + return values; + } + + void VKBoundingBox::Write(u32 index, const std::vector& values) + { +- // We can't issue vkCmdUpdateBuffer within a render pass. +- // However, the writes must be serialized, so we can't put it in the init buffer. +- StateTracker::GetInstance()->EndRenderPass(); +- +- // Ensure GPU buffer is in a state where it can be transferred to. +- StagingBuffer::BufferMemoryBarrier( +- g_command_buffer_mgr->GetCurrentCommandBuffer(), m_gpu_buffer, +- VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, 0, +- BUFFER_SIZE, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); +- +- // Write the values to the GPU buffer +- vkCmdUpdateBuffer(g_command_buffer_mgr->GetCurrentCommandBuffer(), m_gpu_buffer, +- index * sizeof(BBoxType), values.size() * sizeof(BBoxType), +- reinterpret_cast(values.data())); +- +- // Restore fragment shader access to the buffer. +- StagingBuffer::BufferMemoryBarrier( +- g_command_buffer_mgr->GetCurrentCommandBuffer(), m_gpu_buffer, VK_ACCESS_TRANSFER_WRITE_BIT, +- VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, 0, BUFFER_SIZE, +- VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); ++ g_scheduler->Record([c_gpu_buffer = m_gpu_buffer, c_values = values, ++ c_index = index](CommandBufferManager* command_buffer_mgr) { ++ // We can't issue vkCmdUpdateBuffer within a render pass. ++ // However, the writes must be serialized, so we can't put it in the init buffer. ++ command_buffer_mgr->GetStateTracker()->EndRenderPass(); ++ ++ // Ensure GPU buffer is in a state where it can be transferred to. ++ StagingBuffer::BufferMemoryBarrier( ++ command_buffer_mgr->GetCurrentCommandBuffer(), c_gpu_buffer, ++ VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, 0, ++ BUFFER_SIZE, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); ++ ++ // Write the values to the GPU buffer ++ vkCmdUpdateBuffer(command_buffer_mgr->GetCurrentCommandBuffer(), c_gpu_buffer, ++ c_index * sizeof(BBoxType), c_values.size() * sizeof(BBoxType), ++ reinterpret_cast(c_values.data())); ++ ++ // Restore fragment shader access to the buffer. ++ StagingBuffer::BufferMemoryBarrier( ++ command_buffer_mgr->GetCurrentCommandBuffer(), c_gpu_buffer, VK_ACCESS_TRANSFER_WRITE_BIT, ++ VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, 0, BUFFER_SIZE, ++ VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); ++ }); + } + + bool VKBoundingBox::CreateGPUBuffer() +diff -rupN dolphin.orig/Source/Core/VideoBackends/Vulkan/VKMain.cpp dolphin/Source/Core/VideoBackends/Vulkan/VKMain.cpp +--- dolphin.orig/Source/Core/VideoBackends/Vulkan/VKMain.cpp 2024-03-05 04:05:26.602983293 +0000 ++++ dolphin/Source/Core/VideoBackends/Vulkan/VKMain.cpp 2024-03-05 04:06:08.240295843 +0000 +@@ -18,6 +18,7 @@ + #include "VideoBackends/Vulkan/VKVertexManager.h" + #include "VideoBackends/Vulkan/VulkanContext.h" + ++#include "VKScheduler.h" + #include "VideoCommon/FramebufferManager.h" + #include "VideoCommon/TextureCacheBase.h" + #include "VideoCommon/VideoBackendBase.h" +@@ -196,14 +197,7 @@ bool VideoBackend::Initialize(const Wind + // With the backend information populated, we can now initialize videocommon. + InitializeShared(); + +- // Create command buffers. We do this separately because the other classes depend on it. +- g_command_buffer_mgr = std::make_unique(g_Config.bBackendMultithreading); +- if (!g_command_buffer_mgr->Initialize()) +- { +- PanicAlertFmt("Failed to create Vulkan command buffers"); +- Shutdown(); +- return false; +- } ++ g_scheduler = std::make_unique(); + + // Remaining classes are also dependent on object cache. + g_object_cache = std::make_unique(); +@@ -214,6 +208,14 @@ bool VideoBackend::Initialize(const Wind + return false; + } + ++ // Has to be initialized after the object cache ++ if (!g_scheduler->Initialize()) ++ { ++ PanicAlertFmt("Failed to initialize Vulkan scheduler."); ++ Shutdown(); ++ return false; ++ } ++ + // Create swap chain. This has to be done early so that the target size is correct for auto-scale. + std::unique_ptr swap_chain; + if (surface != VK_NULL_HANDLE) +@@ -227,13 +229,6 @@ bool VideoBackend::Initialize(const Wind + } + } + +- if (!StateTracker::CreateInstance()) +- { +- PanicAlertFmt("Failed to create state tracker"); +- Shutdown(); +- return false; +- } +- + // Create main wrapper instances. + g_renderer = std::make_unique(std::move(swap_chain), wsi.render_surface_scale); + g_vertex_manager = std::make_unique(); +@@ -257,6 +252,9 @@ bool VideoBackend::Initialize(const Wind + + void VideoBackend::Shutdown() + { ++ if (g_scheduler) ++ g_scheduler->SyncWorker(); ++ + if (g_vulkan_context) + vkDeviceWaitIdle(g_vulkan_context->GetDevice()); + +@@ -269,6 +267,9 @@ void VideoBackend::Shutdown() + if (g_renderer) + g_renderer->Shutdown(); + ++ if (g_scheduler) ++ g_scheduler->Shutdown(); ++ + g_perf_query.reset(); + g_texture_cache.reset(); + g_framebuffer_manager.reset(); +@@ -276,8 +277,7 @@ void VideoBackend::Shutdown() + g_vertex_manager.reset(); + g_renderer.reset(); + g_object_cache.reset(); +- StateTracker::DestroyInstance(); +- g_command_buffer_mgr.reset(); ++ g_scheduler.reset(); + g_vulkan_context.reset(); + ShutdownShared(); + UnloadVulkanLibrary(); +diff -rupN dolphin.orig/Source/Core/VideoBackends/Vulkan/VKPerfQuery.cpp dolphin/Source/Core/VideoBackends/Vulkan/VKPerfQuery.cpp +--- dolphin.orig/Source/Core/VideoBackends/Vulkan/VKPerfQuery.cpp 2024-03-05 04:05:26.602983293 +0000 ++++ dolphin/Source/Core/VideoBackends/Vulkan/VKPerfQuery.cpp 2024-03-05 04:06:08.240295843 +0000 +@@ -11,6 +11,7 @@ + #include "Common/Logging/Log.h" + #include "Common/MsgHandler.h" + ++#include "VKScheduler.h" + #include "VideoBackends/Vulkan/CommandBufferManager.h" + #include "VideoBackends/Vulkan/StateTracker.h" + #include "VideoBackends/Vulkan/VKRenderer.h" +@@ -49,9 +50,11 @@ void PerfQuery::EnableQuery(PerfQueryGro + if (query_count > m_query_buffer.size() / 2) + PartialFlush(query_count == PERF_QUERY_BUFFER_SIZE); + +- // Ensure command buffer is ready to go before beginning the query, that way we don't submit +- // a buffer with open queries. +- StateTracker::GetInstance()->Bind(); ++ g_scheduler->Record([](CommandBufferManager* command_buffer_mgr) { ++ // Ensure command buffer is ready to go before beginning the query, that way we don't submit ++ // a buffer with open queries. ++ command_buffer_mgr->GetStateTracker()->Bind(); ++ }); + + if (group == PQG_ZCOMP_ZCOMPLOC || group == PQG_ZCOMP) + { +@@ -59,15 +62,16 @@ void PerfQuery::EnableQuery(PerfQueryGro + DEBUG_ASSERT(!entry.has_value); + entry.has_value = true; + entry.query_group = group; +- +- // Use precise queries if supported, otherwise boolean (which will be incorrect). +- VkQueryControlFlags flags = +- g_vulkan_context->SupportsPreciseOcclusionQueries() ? VK_QUERY_CONTROL_PRECISE_BIT : 0; +- +- // Ensure the query starts within a render pass. +- StateTracker::GetInstance()->BeginRenderPass(); +- vkCmdBeginQuery(g_command_buffer_mgr->GetCurrentCommandBuffer(), m_query_pool, m_query_next_pos, +- flags); ++ g_scheduler->Record([c_query_pool = m_query_pool, ++ c_pos = m_query_next_pos](CommandBufferManager* command_buffer_mgr) { ++ // Use precise queries if supported, otherwise boolean (which will be incorrect). ++ VkQueryControlFlags flags = ++ g_vulkan_context->SupportsPreciseOcclusionQueries() ? VK_QUERY_CONTROL_PRECISE_BIT : 0; ++ ++ // Ensure the query starts within a render pass. ++ command_buffer_mgr->GetStateTracker()->BeginRenderPass(); ++ vkCmdBeginQuery(command_buffer_mgr->GetCurrentCommandBuffer(), c_query_pool, c_pos, flags); ++ }); + } + } + +@@ -75,10 +79,13 @@ void PerfQuery::DisableQuery(PerfQueryGr + { + if (group == PQG_ZCOMP_ZCOMPLOC || group == PQG_ZCOMP) + { +- vkCmdEndQuery(g_command_buffer_mgr->GetCurrentCommandBuffer(), m_query_pool, m_query_next_pos); +- ActiveQuery& entry = m_query_buffer[m_query_next_pos]; +- entry.fence_counter = g_command_buffer_mgr->GetCurrentFenceCounter(); ++ g_scheduler->Record([c_query_pool = m_query_pool, c_pos = m_query_next_pos + ++ ](CommandBufferManager* command_buffer_mgr) { ++ vkCmdEndQuery(command_buffer_mgr->GetCurrentCommandBuffer(), c_query_pool, c_pos); ++ }); ++ ActiveQuery& entry = m_query_buffer[m_query_next_pos]; ++ entry.fence_counter = g_scheduler->GetCurrentFenceCounter(); + m_query_next_pos = (m_query_next_pos + 1) % PERF_QUERY_BUFFER_SIZE; + m_query_count.fetch_add(1, std::memory_order_relaxed); + } +@@ -93,10 +100,11 @@ void PerfQuery::ResetQuery() + m_results[i].store(0, std::memory_order_relaxed); + + // Reset entire query pool, ensuring all queries are ready to write to. +- StateTracker::GetInstance()->EndRenderPass(); +- vkCmdResetQueryPool(g_command_buffer_mgr->GetCurrentCommandBuffer(), m_query_pool, 0, +- PERF_QUERY_BUFFER_SIZE); +- ++ g_scheduler->Record([c_query_pool = m_query_pool](CommandBufferManager* command_buffer_mgr) { ++ command_buffer_mgr->GetStateTracker()->EndRenderPass(); ++ vkCmdResetQueryPool(command_buffer_mgr->GetCurrentCommandBuffer(), c_query_pool, 0, ++ PERF_QUERY_BUFFER_SIZE); ++ }); + std::memset(m_query_buffer.data(), 0, sizeof(ActiveQuery) * m_query_buffer.size()); + } + +@@ -160,7 +168,7 @@ bool PerfQuery::CreateQueryPool() + + void PerfQuery::ReadbackQueries() + { +- const u64 completed_fence_counter = g_command_buffer_mgr->GetCompletedFenceCounter(); ++ const u64 completed_fence_counter = g_scheduler->GetCompletedFenceCounter(); + + // Need to save these since ProcessResults will modify them. + const u32 outstanding_queries = m_query_count.load(std::memory_order_relaxed); +@@ -201,9 +209,12 @@ void PerfQuery::ReadbackQueries(u32 quer + if (res != VK_SUCCESS) + LOG_VULKAN_ERROR(res, "vkGetQueryPoolResults failed: "); + +- StateTracker::GetInstance()->EndRenderPass(); +- vkCmdResetQueryPool(g_command_buffer_mgr->GetCurrentCommandBuffer(), m_query_pool, +- m_query_readback_pos, query_count); ++ g_scheduler->Record([c_query_pool = m_query_pool, c_query_readback_pos = m_query_readback_pos, ++ query_count](CommandBufferManager* command_buffer_mgr) { ++ command_buffer_mgr->GetStateTracker()->EndRenderPass(); ++ vkCmdResetQueryPool(command_buffer_mgr->GetCurrentCommandBuffer(), c_query_pool, ++ c_query_readback_pos, query_count); ++ }); + + // Remove pending queries. + for (u32 i = 0; i < query_count; i++) +@@ -231,8 +242,8 @@ void PerfQuery::ReadbackQueries(u32 quer + void PerfQuery::PartialFlush(bool blocking) + { + // Submit a command buffer in the background if the front query is not bound to one. +- if (blocking || m_query_buffer[m_query_readback_pos].fence_counter == +- g_command_buffer_mgr->GetCurrentFenceCounter()) ++ if (blocking || ++ m_query_buffer[m_query_readback_pos].fence_counter == g_scheduler->GetCurrentFenceCounter()) + { + Renderer::GetInstance()->ExecuteCommandBuffer(true, blocking); + } +diff -rupN dolphin.orig/Source/Core/VideoBackends/Vulkan/VKRenderer.cpp dolphin/Source/Core/VideoBackends/Vulkan/VKRenderer.cpp +--- dolphin.orig/Source/Core/VideoBackends/Vulkan/VKRenderer.cpp 2024-03-05 04:05:26.602983293 +0000 ++++ dolphin/Source/Core/VideoBackends/Vulkan/VKRenderer.cpp 2024-03-05 04:06:08.240295843 +0000 +@@ -31,6 +31,7 @@ + #include "VideoBackends/Vulkan/VKVertexFormat.h" + #include "VideoBackends/Vulkan/VulkanContext.h" + ++#include "VKScheduler.h" + #include "VideoCommon/DriverDetails.h" + #include "VideoCommon/FramebufferManager.h" + #include "VideoCommon/RenderState.h" +@@ -124,7 +125,10 @@ std::unique_ptr Ren + + void Renderer::SetPipeline(const AbstractPipeline* pipeline) + { +- StateTracker::GetInstance()->SetPipeline(static_cast(pipeline)); ++ g_scheduler->Record([c_pipeline = static_cast(pipeline)]( ++ CommandBufferManager* command_buffer_mgr) { ++ command_buffer_mgr->GetStateTracker()->SetPipeline(c_pipeline); ++ }); + } + + std::unique_ptr Renderer::CreateBoundingBox() const +@@ -138,17 +142,6 @@ void Renderer::ClearScreen(const MathUti + g_framebuffer_manager->FlushEFBPokes(); + g_framebuffer_manager->FlagPeekCacheAsOutOfDate(); + +- // Native -> EFB coordinates +- MathUtil::Rectangle target_rc = Renderer::ConvertEFBRectangle(rc); +- +- // Size we pass this size to vkBeginRenderPass, it has to be clamped to the framebuffer +- // dimensions. The other backends just silently ignore this case. +- target_rc.ClampUL(0, 0, m_target_width, m_target_height); +- +- VkRect2D target_vk_rc = { +- {target_rc.left, target_rc.top}, +- {static_cast(target_rc.GetWidth()), static_cast(target_rc.GetHeight())}}; +- + // Determine whether the EFB has an alpha channel. If it doesn't, we can clear the alpha + // channel to 0xFF. This hopefully allows us to use the fast path in most cases. + if (bpmem.zcontrol.pixel_format == PixelFormat::RGB565_Z16 || +@@ -161,84 +154,98 @@ void Renderer::ClearScreen(const MathUti + color &= 0x00FFFFFF; + } + +- // Convert RGBA8 -> floating-point values. +- VkClearValue clear_color_value = {}; +- VkClearValue clear_depth_value = {}; +- clear_color_value.color.float32[0] = static_cast((color >> 16) & 0xFF) / 255.0f; +- clear_color_value.color.float32[1] = static_cast((color >> 8) & 0xFF) / 255.0f; +- clear_color_value.color.float32[2] = static_cast((color >> 0) & 0xFF) / 255.0f; +- clear_color_value.color.float32[3] = static_cast((color >> 24) & 0xFF) / 255.0f; +- clear_depth_value.depthStencil.depth = static_cast(z & 0xFFFFFF) / 16777216.0f; +- if (!g_ActiveConfig.backend_info.bSupportsReversedDepthRange) +- clear_depth_value.depthStencil.depth = 1.0f - clear_depth_value.depthStencil.depth; +- +- // If we're not in a render pass (start of the frame), we can use a clear render pass +- // to discard the data, rather than loading and then clearing. +- bool use_clear_attachments = (color_enable && alpha_enable) || z_enable; +- bool use_clear_render_pass = +- !StateTracker::GetInstance()->InRenderPass() && color_enable && alpha_enable && z_enable; +- +- // The NVIDIA Vulkan driver causes the GPU to lock up, or throw exceptions if MSAA is enabled, +- // a non-full clear rect is specified, and a clear loadop or vkCmdClearAttachments is used. +- if (g_ActiveConfig.iMultisamples > 1 && +- DriverDetails::HasBug(DriverDetails::BUG_BROKEN_MSAA_CLEAR)) +- { +- use_clear_render_pass = false; +- use_clear_attachments = false; +- } +- +- // This path cannot be used if the driver implementation doesn't guarantee pixels with no drawn +- // geometry in "this" renderpass won't be cleared +- if (DriverDetails::HasBug(DriverDetails::BUG_BROKEN_CLEAR_LOADOP_RENDERPASS)) +- use_clear_render_pass = false; +- +- // Fastest path: Use a render pass to clear the buffers. +- if (use_clear_render_pass) +- { +- const std::array clear_values = {{clear_color_value, clear_depth_value}}; +- StateTracker::GetInstance()->BeginClearRenderPass(target_vk_rc, clear_values.data(), +- static_cast(clear_values.size())); +- return; +- } ++ // Native -> EFB coordinates ++ MathUtil::Rectangle target_rc = Renderer::ConvertEFBRectangle(rc); ++ ++ // Size we pass this size to vkBeginRenderPass, it has to be clamped to the framebuffer ++ // dimensions. The other backends just silently ignore this case. ++ target_rc.ClampUL(0, 0, m_target_width, m_target_height); ++ ++ g_scheduler->Record([color, z, color_enable, alpha_enable, z_enable, ++ target_rc](CommandBufferManager* command_buffer_mgr) mutable { ++ VkRect2D target_vk_rc = {{target_rc.left, target_rc.top}, ++ {static_cast(target_rc.GetWidth()), ++ static_cast(target_rc.GetHeight())}}; ++ ++ // Convert RGBA8 -> floating-point values. ++ VkClearValue clear_color_value = {}; ++ VkClearValue clear_depth_value = {}; ++ clear_color_value.color.float32[0] = static_cast((color >> 16) & 0xFF) / 255.0f; ++ clear_color_value.color.float32[1] = static_cast((color >> 8) & 0xFF) / 255.0f; ++ clear_color_value.color.float32[2] = static_cast((color >> 0) & 0xFF) / 255.0f; ++ clear_color_value.color.float32[3] = static_cast((color >> 24) & 0xFF) / 255.0f; ++ clear_depth_value.depthStencil.depth = static_cast(z & 0xFFFFFF) / 16777216.0f; ++ if (!g_ActiveConfig.backend_info.bSupportsReversedDepthRange) ++ clear_depth_value.depthStencil.depth = 1.0f - clear_depth_value.depthStencil.depth; ++ ++ // If we're not in a render pass (start of the frame), we can use a clear render pass ++ // to discard the data, rather than loading and then clearing. ++ bool use_clear_attachments = (color_enable && alpha_enable) || z_enable; ++ bool use_clear_render_pass = !command_buffer_mgr->GetStateTracker()->InRenderPass() && ++ color_enable && alpha_enable && z_enable; ++ ++ // The NVIDIA Vulkan driver causes the GPU to lock up, or throw exceptions if MSAA is enabled, ++ // a non-full clear rect is specified, and a clear loadop or vkCmdClearAttachments is used. ++ if (g_ActiveConfig.iMultisamples > 1 && ++ DriverDetails::HasBug(DriverDetails::BUG_BROKEN_MSAA_CLEAR)) ++ { ++ use_clear_render_pass = false; ++ use_clear_attachments = false; ++ } ++ ++ // This path cannot be used if the driver implementation doesn't guarantee pixels with no drawn ++ // geometry in "this" renderpass won't be cleared ++ if (DriverDetails::HasBug(DriverDetails::BUG_BROKEN_CLEAR_LOADOP_RENDERPASS)) ++ use_clear_render_pass = false; + +- // Fast path: Use vkCmdClearAttachments to clear the buffers within a render path +- // We can't use this when preserving alpha but clearing color. +- if (use_clear_attachments) +- { +- VkClearAttachment clear_attachments[2]; +- uint32_t num_clear_attachments = 0; +- if (color_enable && alpha_enable) +- { +- clear_attachments[num_clear_attachments].aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; +- clear_attachments[num_clear_attachments].colorAttachment = 0; +- clear_attachments[num_clear_attachments].clearValue = clear_color_value; +- num_clear_attachments++; +- color_enable = false; +- alpha_enable = false; +- } +- if (z_enable) +- { +- clear_attachments[num_clear_attachments].aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; +- clear_attachments[num_clear_attachments].colorAttachment = 0; +- clear_attachments[num_clear_attachments].clearValue = clear_depth_value; +- num_clear_attachments++; +- z_enable = false; +- } +- if (num_clear_attachments > 0) +- { +- VkClearRect vk_rect = {target_vk_rc, 0, g_framebuffer_manager->GetEFBLayers()}; +- if (!StateTracker::GetInstance()->IsWithinRenderArea( +- target_vk_rc.offset.x, target_vk_rc.offset.y, target_vk_rc.extent.width, +- target_vk_rc.extent.height)) ++ // Fastest path: Use a render pass to clear the buffers. ++ if (use_clear_render_pass) ++ { ++ const std::array clear_values = {{clear_color_value, clear_depth_value}}; ++ command_buffer_mgr->GetStateTracker()->BeginClearRenderPass( ++ target_vk_rc, clear_values.data(), static_cast(clear_values.size())); ++ return; ++ } ++ ++ // Fast path: Use vkCmdClearAttachments to clear the buffers within a render path ++ // We can't use this when preserving alpha but clearing color. ++ if (use_clear_attachments) ++ { ++ VkClearAttachment clear_attachments[2]; ++ uint32_t num_clear_attachments = 0; ++ if (color_enable && alpha_enable) ++ { ++ clear_attachments[num_clear_attachments].aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; ++ clear_attachments[num_clear_attachments].colorAttachment = 0; ++ clear_attachments[num_clear_attachments].clearValue = clear_color_value; ++ num_clear_attachments++; ++ color_enable = false; ++ alpha_enable = false; ++ } ++ if (z_enable) + { +- StateTracker::GetInstance()->EndClearRenderPass(); ++ clear_attachments[num_clear_attachments].aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; ++ clear_attachments[num_clear_attachments].colorAttachment = 0; ++ clear_attachments[num_clear_attachments].clearValue = clear_depth_value; ++ num_clear_attachments++; ++ z_enable = false; + } +- StateTracker::GetInstance()->BeginRenderPass(); ++ if (num_clear_attachments > 0) ++ { ++ VkClearRect vk_rect = {target_vk_rc, 0, g_framebuffer_manager->GetEFBLayers()}; ++ if (!command_buffer_mgr->GetStateTracker()->IsWithinRenderArea( ++ target_vk_rc.offset.x, target_vk_rc.offset.y, target_vk_rc.extent.width, ++ target_vk_rc.extent.height)) ++ { ++ command_buffer_mgr->GetStateTracker()->EndClearRenderPass(); ++ } ++ command_buffer_mgr->GetStateTracker()->BeginRenderPass(); + +- vkCmdClearAttachments(g_command_buffer_mgr->GetCurrentCommandBuffer(), num_clear_attachments, +- clear_attachments, 1, &vk_rect); ++ vkCmdClearAttachments(command_buffer_mgr->GetCurrentCommandBuffer(), num_clear_attachments, ++ clear_attachments, 1, &vk_rect); ++ } + } +- } ++ }); + + // Anything left over for the slow path? + if (!color_enable && !alpha_enable && !z_enable) +@@ -259,10 +266,11 @@ void Renderer::WaitForGPUIdle() + + void Renderer::BindBackbuffer(const ClearColor& clear_color) + { +- StateTracker::GetInstance()->EndRenderPass(); +- +- if (!g_command_buffer_mgr->CheckLastPresentDone()) +- g_command_buffer_mgr->WaitForWorkerThreadIdle(); ++ g_scheduler->Record([](CommandBufferManager* command_buffer_mgr) { ++ command_buffer_mgr->GetStateTracker()->EndRenderPass(); ++ }); ++ if (!g_scheduler->CheckLastPresentDone()) ++ g_scheduler->SynchronizeSubmissionThread(); + + // Handle host window resizes. + CheckForSurfaceChange(); +@@ -276,9 +284,21 @@ void Renderer::BindBackbuffer(const Clea + m_swap_chain->SetNextFullscreenState(m_swap_chain->GetCurrentFullscreenState()); + } + +- const bool present_fail = g_command_buffer_mgr->CheckLastPresentFail(); +- VkResult res = present_fail ? g_command_buffer_mgr->GetLastPresentResult() : +- m_swap_chain->AcquireNextImage(); ++ VkSemaphore semaphore = VK_NULL_HANDLE; ++ VkResult res; ++ const bool present_fail = g_scheduler->CheckLastPresentFail(); ++ if (!present_fail) ++ { ++ semaphore = m_swap_chain->GetNextSemaphore(); ++ g_scheduler->Record([c_semaphore = semaphore](CommandBufferManager* command_buffer_mgr) { ++ command_buffer_mgr->SetWaitSemaphoreForCurrentCommandBuffer(c_semaphore); ++ }); ++ res = m_swap_chain->AcquireNextImage(semaphore); ++ } ++ else ++ { ++ res = g_scheduler->GetLastPresentResult(); ++ } + + if (res == VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT && + !m_swap_chain->GetCurrentFullscreenState()) +@@ -289,8 +309,13 @@ void Renderer::BindBackbuffer(const Clea + res = VK_SUCCESS; + if (present_fail) + { ++ if (semaphore == VK_NULL_HANDLE) ++ { ++ semaphore = m_swap_chain->GetNextSemaphore(); ++ } ++ + // We still need to acquire an image. +- res = m_swap_chain->AcquireNextImage(); ++ res = m_swap_chain->AcquireNextImage(semaphore); + } + } + +@@ -309,7 +334,7 @@ void Renderer::BindBackbuffer(const Clea + else if (res == VK_SUBOPTIMAL_KHR || res == VK_ERROR_OUT_OF_DATE_KHR) + { + INFO_LOG_FMT(VIDEO, "Resizing swap chain due to suboptimal/out-of-date"); +- m_swap_chain->ResizeSwapChain(); ++ m_swap_chain->ResizeSwapChain(m_backbuffer_width, m_backbuffer_height); + } + else + { +@@ -318,7 +343,12 @@ void Renderer::BindBackbuffer(const Clea + m_swap_chain->RecreateSwapChain(); + } + +- res = m_swap_chain->AcquireNextImage(); ++ semaphore = m_swap_chain->GetNextSemaphore(); ++ g_scheduler->Record([c_semaphore = semaphore](CommandBufferManager* command_buffer_mgr) { ++ command_buffer_mgr->SetWaitSemaphoreForCurrentCommandBuffer(c_semaphore); ++ }); ++ ++ res = m_swap_chain->AcquireNextImage(semaphore); + if (res != VK_SUCCESS) + PanicAlertFmt("Failed to grab image from swap chain: {:#010X} {}", static_cast(res), + VkResultToString(res)); +@@ -328,8 +358,7 @@ void Renderer::BindBackbuffer(const Clea + // color attachment ready for writing. These transitions must occur outside + // a render pass, unless the render pass declares a self-dependency. + m_swap_chain->GetCurrentTexture()->OverrideImageLayout(VK_IMAGE_LAYOUT_UNDEFINED); +- m_swap_chain->GetCurrentTexture()->TransitionToLayout( +- g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); ++ m_swap_chain->GetCurrentTexture()->TransitionToLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + SetAndClearFramebuffer(m_swap_chain->GetCurrentFramebuffer(), + ClearColor{{0.0f, 0.0f, 0.0f, 1.0f}}); + } +@@ -337,22 +366,20 @@ void Renderer::BindBackbuffer(const Clea + void Renderer::PresentBackbuffer() + { + // End drawing to backbuffer +- StateTracker::GetInstance()->EndRenderPass(); ++ g_scheduler->Record([](CommandBufferManager* command_buffer_mgr) { ++ command_buffer_mgr->GetStateTracker()->EndRenderPass(); ++ }); + + // Transition the backbuffer to PRESENT_SRC to ensure all commands drawing + // to it have finished before present. +- m_swap_chain->GetCurrentTexture()->TransitionToLayout( +- g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); ++ m_swap_chain->GetCurrentTexture()->TransitionToLayout(VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); + + // Submit the current command buffer, signaling rendering finished semaphore when it's done + // Because this final command buffer is rendering to the swap chain, we need to wait for + // the available semaphore to be signaled before executing the buffer. This final submission + // can happen off-thread in the background while we're preparing the next frame. +- g_command_buffer_mgr->SubmitCommandBuffer(true, false, m_swap_chain->GetSwapChain(), +- m_swap_chain->GetCurrentImageIndex()); +- +- // New cmdbuffer, so invalidate state. +- StateTracker::GetInstance()->InvalidateCachedState(); ++ g_scheduler->SubmitCommandBuffer(true, false, m_swap_chain->GetSwapChain(), ++ m_swap_chain->GetCurrentImageIndex()); + } + + void Renderer::SetFullscreen(bool enable_fullscreen) +@@ -370,11 +397,7 @@ bool Renderer::IsFullscreen() const + + void Renderer::ExecuteCommandBuffer(bool submit_off_thread, bool wait_for_completion) + { +- StateTracker::GetInstance()->EndRenderPass(); +- +- g_command_buffer_mgr->SubmitCommandBuffer(submit_off_thread, wait_for_completion); +- +- StateTracker::GetInstance()->InvalidateCachedState(); ++ g_scheduler->SubmitCommandBuffer(submit_off_thread, wait_for_completion); + } + + void Renderer::CheckForSurfaceChange() +@@ -382,15 +405,20 @@ void Renderer::CheckForSurfaceChange() + if (!m_surface_changed.TestAndClear() || !m_swap_chain) + return; + ++ g_scheduler->SyncWorker(); ++ + // Submit the current draws up until rendering the XFB. + ExecuteCommandBuffer(false, true); + + // Clear the present failed flag, since we don't want to resize after recreating. +- g_command_buffer_mgr->CheckLastPresentFail(); ++ g_scheduler->CheckLastPresentFail(); + + // Recreate the surface. If this fails we're in trouble. +- if (!m_swap_chain->RecreateSurface(m_new_surface_handle)) ++ if (!m_swap_chain->RecreateSurface(m_new_surface_handle, m_new_surface_width, ++ m_new_surface_height)) ++ { + PanicAlertFmt("Failed to recreate Vulkan surface. Cannot continue."); ++ } + m_new_surface_handle = nullptr; + + // Handle case where the dimensions are now different. +@@ -402,6 +430,8 @@ void Renderer::CheckForSurfaceResize() + if (!m_surface_resized.TestAndClear()) + return; + ++ g_scheduler->SyncWorker(); ++ + // If we don't have a surface, how can we resize the swap chain? + // CheckForSurfaceChange should handle this case. + if (!m_swap_chain) +@@ -414,17 +444,21 @@ void Renderer::CheckForSurfaceResize() + ExecuteCommandBuffer(false, true); + + // Clear the present failed flag, since we don't want to resize after recreating. +- g_command_buffer_mgr->CheckLastPresentFail(); ++ g_scheduler->CheckLastPresentFail(); + + // Resize the swap chain. +- m_swap_chain->RecreateSwapChain(); ++ m_swap_chain->ResizeSwapChain(m_new_surface_width, m_new_surface_height); + OnSwapChainResized(); + } + + void Renderer::OnConfigChanged(u32 bits) + { + if (bits & CONFIG_CHANGE_BIT_HOST_CONFIG) +- g_object_cache->ReloadPipelineCache(); ++ { ++ g_scheduler->Record([](CommandBufferManager* command_buffer_manager) { ++ g_object_cache->ReloadPipelineCache(); ++ }); ++ } + + // For vsync, we need to change the present mode, which means recreating the swap chain. + if (m_swap_chain && bits & CONFIG_CHANGE_BIT_VSYNC) +@@ -456,22 +490,32 @@ void Renderer::OnSwapChainResized() + + void Renderer::BindFramebuffer(VKFramebuffer* fb) + { +- StateTracker::GetInstance()->EndRenderPass(); ++ g_scheduler->Record([fb](CommandBufferManager* command_buffer_mgr) { ++ command_buffer_mgr->GetStateTracker()->EndRenderPass(); + +- // Shouldn't be bound as a texture. +- if (fb->GetColorAttachment()) +- { +- StateTracker::GetInstance()->UnbindTexture( +- static_cast(fb->GetColorAttachment())->GetView()); +- } +- if (fb->GetDepthAttachment()) +- { +- StateTracker::GetInstance()->UnbindTexture( +- static_cast(fb->GetDepthAttachment())->GetView()); +- } ++ // Shouldn't be bound as a texture. ++ if (fb->GetColorAttachment()) ++ { ++ command_buffer_mgr->GetStateTracker()->UnbindTexture( ++ static_cast(fb->GetColorAttachment())->GetView()); ++ } ++ if (fb->GetDepthAttachment()) ++ { ++ command_buffer_mgr->GetStateTracker()->UnbindTexture( ++ static_cast(fb->GetDepthAttachment())->GetView()); ++ } ++ }); + + fb->TransitionForRender(); +- StateTracker::GetInstance()->SetFramebuffer(fb); ++ ++ g_scheduler->Record([c_framebuffer = fb->GetFB(), c_rect = fb->GetRect(), ++ c_load_render_pass = fb->GetLoadRenderPass(), ++ c_clear_render_pass = fb->GetClearRenderPass(), ++ c_discard_render_pass = ++ fb->GetDiscardRenderPass()](CommandBufferManager* command_buffer_mgr) { ++ command_buffer_mgr->GetStateTracker()->SetFramebuffer( ++ c_framebuffer, c_rect, c_load_render_pass, c_clear_render_pass, c_discard_render_pass); ++ }); + m_current_framebuffer = fb; + } + +@@ -494,7 +538,9 @@ void Renderer::SetAndDiscardFramebuffer( + + // If we're discarding, begin the discard pass, then switch to a load pass. + // This way if the command buffer is flushed, we don't start another discard pass. +- StateTracker::GetInstance()->BeginDiscardRenderPass(); ++ g_scheduler->Record([](CommandBufferManager* command_buffer_mgr) { ++ command_buffer_mgr->GetStateTracker()->BeginDiscardRenderPass(); ++ }); + } + + void Renderer::SetAndClearFramebuffer(AbstractFramebuffer* framebuffer, +@@ -503,22 +549,25 @@ void Renderer::SetAndClearFramebuffer(Ab + VKFramebuffer* vkfb = static_cast(framebuffer); + BindFramebuffer(vkfb); + +- std::array clear_values; +- u32 num_clear_values = 0; +- if (vkfb->GetColorFormat() != AbstractTextureFormat::Undefined) +- { +- std::memcpy(clear_values[num_clear_values].color.float32, color_value.data(), +- sizeof(clear_values[num_clear_values].color.float32)); +- num_clear_values++; +- } +- if (vkfb->GetDepthFormat() != AbstractTextureFormat::Undefined) +- { +- clear_values[num_clear_values].depthStencil.depth = depth_value; +- clear_values[num_clear_values].depthStencil.stencil = 0; +- num_clear_values++; +- } +- StateTracker::GetInstance()->BeginClearRenderPass(vkfb->GetRect(), clear_values.data(), +- num_clear_values); ++ g_scheduler->Record( ++ [vkfb, c_color_value = color_value, depth_value](CommandBufferManager* command_buffer_mgr) { ++ std::array clear_values; ++ u32 num_clear_values = 0; ++ if (vkfb->GetColorFormat() != AbstractTextureFormat::Undefined) ++ { ++ std::memcpy(clear_values[num_clear_values].color.float32, c_color_value.data(), ++ sizeof(clear_values[num_clear_values].color.float32)); ++ num_clear_values++; ++ } ++ if (vkfb->GetDepthFormat() != AbstractTextureFormat::Undefined) ++ { ++ clear_values[num_clear_values].depthStencil.depth = depth_value; ++ clear_values[num_clear_values].depthStencil.stencil = 0; ++ num_clear_values++; ++ } ++ command_buffer_mgr->GetStateTracker()->BeginClearRenderPass( ++ vkfb->GetRect(), clear_values.data(), num_clear_values); ++ }); + } + + void Renderer::SetTexture(u32 index, const AbstractTexture* texture) +@@ -526,25 +575,31 @@ void Renderer::SetTexture(u32 index, con + // Texture should always be in SHADER_READ_ONLY layout prior to use. + // This is so we don't need to transition during render passes. + const VKTexture* tex = static_cast(texture); ++ + if (tex) + { + if (tex->GetLayout() != VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) + { +- if (StateTracker::GetInstance()->InRenderPass()) +- { +- WARN_LOG_FMT(VIDEO, "Transitioning image in render pass in Renderer::SetTexture()"); +- StateTracker::GetInstance()->EndRenderPass(); +- } ++ g_scheduler->Record([](CommandBufferManager* command_buffer_mgr) { ++ if (command_buffer_mgr->GetStateTracker()->InRenderPass()) ++ { ++ WARN_LOG_FMT(VIDEO, "Transitioning image in render pass in Renderer::SetTexture()"); ++ command_buffer_mgr->GetStateTracker()->EndRenderPass(); ++ } ++ }); + +- tex->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), +- VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); ++ tex->TransitionToLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + } + +- StateTracker::GetInstance()->SetTexture(index, tex->GetView()); ++ g_scheduler->Record([c_view = tex->GetView(), index](CommandBufferManager* command_buffer_mgr) { ++ command_buffer_mgr->GetStateTracker()->SetTexture(index, c_view); ++ }); + } + else + { +- StateTracker::GetInstance()->SetTexture(0, VK_NULL_HANDLE); ++ g_scheduler->Record([](CommandBufferManager* command_buffer_mgr) { ++ command_buffer_mgr->GetStateTracker()->SetTexture(0, VK_NULL_HANDLE); ++ }); + } + } + +@@ -554,15 +609,17 @@ void Renderer::SetSamplerState(u32 index + if (m_sampler_states[index] == state) + return; + +- // Look up new state and replace in state tracker. +- VkSampler sampler = g_object_cache->GetSampler(state); +- if (sampler == VK_NULL_HANDLE) +- { +- ERROR_LOG_FMT(VIDEO, "Failed to create sampler"); +- sampler = g_object_cache->GetPointSampler(); +- } ++ g_scheduler->Record([index, c_sampler_state = state](CommandBufferManager* command_buffer_mgr) { ++ // Look up new state and replace in state tracker. ++ VkSampler sampler = g_object_cache->GetSampler(c_sampler_state); ++ if (sampler == VK_NULL_HANDLE) ++ { ++ ERROR_LOG_FMT(VIDEO, "Failed to create sampler"); ++ sampler = g_object_cache->GetPointSampler(); ++ } + +- StateTracker::GetInstance()->SetSampler(index, sampler); ++ command_buffer_mgr->GetStateTracker()->SetSampler(index, sampler); ++ }); + m_sampler_states[index] = state; + } + +@@ -571,87 +628,116 @@ void Renderer::SetComputeImageTexture(Ab + VKTexture* vk_texture = static_cast(texture); + if (vk_texture) + { +- StateTracker::GetInstance()->EndRenderPass(); +- StateTracker::GetInstance()->SetImageTexture(vk_texture->GetView()); +- vk_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), +- read ? (write ? VKTexture::ComputeImageLayout::ReadWrite : ++ g_scheduler->Record([c_view = vk_texture->GetView()](CommandBufferManager* command_buffer_mgr) { ++ command_buffer_mgr->GetStateTracker()->EndRenderPass(); ++ command_buffer_mgr->GetStateTracker()->SetImageTexture(c_view); ++ }); ++ ++ vk_texture->TransitionToLayout(read ? (write ? VKTexture::ComputeImageLayout::ReadWrite : + VKTexture::ComputeImageLayout::ReadOnly) : + VKTexture::ComputeImageLayout::WriteOnly); + } + else + { +- StateTracker::GetInstance()->SetImageTexture(VK_NULL_HANDLE); ++ g_scheduler->Record([](CommandBufferManager* command_buffer_mgr) { ++ command_buffer_mgr->GetStateTracker()->SetImageTexture(VK_NULL_HANDLE); ++ }); + } + } + + void Renderer::UnbindTexture(const AbstractTexture* texture) + { +- StateTracker::GetInstance()->UnbindTexture(static_cast(texture)->GetView()); ++ g_scheduler->Record([c_view = static_cast(texture)->GetView()]( ++ CommandBufferManager* command_buffer_mgr) { ++ command_buffer_mgr->GetStateTracker()->UnbindTexture(c_view); ++ }); + } + + void Renderer::ResetSamplerStates() + { +- // Invalidate all sampler states, next draw will re-initialize them. + for (u32 i = 0; i < m_sampler_states.size(); i++) + { + m_sampler_states[i] = RenderState::GetPointSamplerState(); +- StateTracker::GetInstance()->SetSampler(i, g_object_cache->GetPointSampler()); + } + +- // Invalidate all sampler objects (some will be unused now). +- g_object_cache->ClearSamplerCache(); ++ g_scheduler->Record( ++ [c_sampler_count = m_sampler_states.size()](CommandBufferManager* command_buffer_mgr) { ++ // Invalidate all sampler states, next draw will re-initialize them. ++ for (u32 i = 0; i < c_sampler_count; i++) ++ { ++ command_buffer_mgr->GetStateTracker()->SetSampler(i, g_object_cache->GetPointSampler()); ++ } ++ ++ // Invalidate all sampler objects (some will be unused now). ++ g_object_cache->ClearSamplerCache(); ++ }); + } + + void Renderer::SetScissorRect(const MathUtil::Rectangle& rc) + { +- VkRect2D scissor = {{rc.left, rc.top}, +- {static_cast(rc.GetWidth()), static_cast(rc.GetHeight())}}; +- +- // See Vulkan spec for vkCmdSetScissor: +- // The x and y members of offset must be greater than or equal to 0. +- if (scissor.offset.x < 0) +- { +- scissor.extent.width -= -scissor.offset.x; +- scissor.offset.x = 0; +- } +- if (scissor.offset.y < 0) +- { +- scissor.extent.height -= -scissor.offset.y; +- scissor.offset.y = 0; +- } +- StateTracker::GetInstance()->SetScissor(scissor); ++ g_scheduler->Record([c_rc = rc](CommandBufferManager* command_buffer_mgr) { ++ VkRect2D scissor = {{c_rc.left, c_rc.top}, ++ {static_cast(c_rc.GetWidth()), static_cast(c_rc.GetHeight())}}; ++ ++ // See Vulkan spec for vkCmdSetScissor: ++ // The x and y members of offset must be greater than or equal to 0. ++ if (scissor.offset.x < 0) ++ { ++ scissor.extent.width -= -scissor.offset.x; ++ scissor.offset.x = 0; ++ } ++ if (scissor.offset.y < 0) ++ { ++ scissor.extent.height -= -scissor.offset.y; ++ scissor.offset.y = 0; ++ } ++ command_buffer_mgr->GetStateTracker()->SetScissor(scissor); ++ }); + } + + void Renderer::SetViewport(float x, float y, float width, float height, float near_depth, + float far_depth) + { + VkViewport viewport = {x, y, width, height, near_depth, far_depth}; +- StateTracker::GetInstance()->SetViewport(viewport); ++ g_scheduler->Record([viewport](CommandBufferManager* command_buffer_mgr) { ++ command_buffer_mgr->GetStateTracker()->SetViewport(viewport); ++ }); + } + + void Renderer::Draw(u32 base_vertex, u32 num_vertices) + { +- if (!StateTracker::GetInstance()->Bind()) +- return; ++ g_scheduler->Record([base_vertex, num_vertices](CommandBufferManager* command_buffer_mgr) { ++ if (!command_buffer_mgr->GetStateTracker()->Bind()) ++ return; + +- vkCmdDraw(g_command_buffer_mgr->GetCurrentCommandBuffer(), num_vertices, 1, base_vertex, 0); ++ vkCmdDraw(command_buffer_mgr->GetCurrentCommandBuffer(), num_vertices, 1, base_vertex, 0); ++ }); + } + + void Renderer::DrawIndexed(u32 base_index, u32 num_indices, u32 base_vertex) + { +- if (!StateTracker::GetInstance()->Bind()) +- return; +- +- vkCmdDrawIndexed(g_command_buffer_mgr->GetCurrentCommandBuffer(), num_indices, 1, base_index, +- base_vertex, 0); ++ g_scheduler->Record( ++ [base_vertex, num_indices, base_index](CommandBufferManager* command_buffer_mgr) { ++ if (!command_buffer_mgr->GetStateTracker()->Bind()) ++ return; ++ ++ vkCmdDrawIndexed(command_buffer_mgr->GetCurrentCommandBuffer(), num_indices, 1, base_index, ++ base_vertex, 0); ++ }); + } + + void Renderer::DispatchComputeShader(const AbstractShader* shader, u32 groupsize_x, u32 groupsize_y, + u32 groupsize_z, u32 groups_x, u32 groups_y, u32 groups_z) + { +- StateTracker::GetInstance()->SetComputeShader(static_cast(shader)); +- if (StateTracker::GetInstance()->BindCompute()) +- vkCmdDispatch(g_command_buffer_mgr->GetCurrentCommandBuffer(), groups_x, groups_y, groups_z); ++ g_scheduler->Record([groups_x, groups_y, groups_z, ++ shader](CommandBufferManager* command_buffer_mgr) { ++ if (!command_buffer_mgr->GetStateTracker()->Bind()) ++ return; ++ ++ command_buffer_mgr->GetStateTracker()->SetComputeShader(static_cast(shader)); ++ if (command_buffer_mgr->GetStateTracker()->BindCompute()) ++ vkCmdDispatch(command_buffer_mgr->GetCurrentCommandBuffer(), groups_x, groups_y, groups_z); ++ }); + } + + } // namespace Vulkan +diff -rupN dolphin.orig/Source/Core/VideoBackends/Vulkan/VKScheduler.cpp dolphin/Source/Core/VideoBackends/Vulkan/VKScheduler.cpp +--- dolphin.orig/Source/Core/VideoBackends/Vulkan/VKScheduler.cpp 1970-01-01 00:00:00.000000000 +0000 ++++ dolphin/Source/Core/VideoBackends/Vulkan/VKScheduler.cpp 2024-03-05 04:06:08.240295843 +0000 +@@ -0,0 +1,155 @@ ++// Copyright 2022 Dolphin Emulator Project ++// SPDX-License-Identifier: GPL-2.0-or-later ++ ++#include "VKScheduler.h" ++#include ++#include "Common/Thread.h" ++#include "StateTracker.h" ++ ++namespace Vulkan ++{ ++Scheduler::Scheduler() ++ : m_commandBufferManager(std::make_unique()), ++ m_submit_loop(std::make_unique()) ++{ ++ AcquireNewChunk(); ++ ++ m_worker = std::thread([this]() { ++ Common::SetCurrentThreadName("Vulkan CS Thread"); ++ WorkerThread(); ++ }); ++} ++ ++Scheduler::~Scheduler() ++{ ++ m_submit_loop->Stop(); ++ m_worker.join(); ++} ++ ++bool Scheduler::Initialize() ++{ ++ return m_commandBufferManager->Initialize(); ++} ++ ++void Scheduler::CommandChunk::ExecuteAll(CommandBufferManager* cmdbuf) ++{ ++ auto command = first; ++ while (command != nullptr) ++ { ++ auto next = command->GetNext(); ++ command->Execute(cmdbuf); ++ command->~Command(); ++ command = next; ++ } ++ command_offset = 0; ++ first = nullptr; ++ last = nullptr; ++} ++ ++void Scheduler::AcquireNewChunk() ++{ ++ std::scoped_lock lock{m_reserve_mutex}; ++ if (m_chunk_reserve.empty()) ++ { ++ m_chunk = std::make_unique(); ++ return; ++ } ++ m_chunk = std::move(m_chunk_reserve.back()); ++ m_chunk_reserve.pop_back(); ++} ++ ++void Scheduler::Flush() ++{ ++ if (m_chunk->Empty()) ++ return; ++ ++ { ++ std::scoped_lock lock{m_work_mutex}; ++ m_worker_idle = false; ++ m_work_queue.push(std::move(m_chunk)); ++ m_submit_loop->Wakeup(); ++ } ++ AcquireNewChunk(); ++} ++ ++void Scheduler::SyncWorker() ++{ ++ Flush(); ++ std::unique_lock lock{m_work_mutex}; ++ m_idle_condvar.wait(lock, [this] { return m_worker_idle; }); ++} ++ ++void Scheduler::WorkerThread() ++{ ++ m_submit_loop->Run([this]() { ++ std::unique_ptr work; ++ { ++ std::scoped_lock lock{m_work_mutex}; ++ if (m_work_queue.empty()) ++ { ++ m_worker_idle = true; ++ m_idle_condvar.notify_all(); ++ m_submit_loop->AllowSleep(); ++ return; ++ } ++ work = std::move(m_work_queue.front()); ++ m_work_queue.pop(); ++ } ++ ++ work->ExecuteAll(m_commandBufferManager.get()); ++ { ++ std::scoped_lock reserve_lock{m_reserve_mutex}; ++ m_chunk_reserve.push_back(std::move(work)); ++ } ++ { ++ std::scoped_lock lock{m_work_mutex}; ++ if (m_work_queue.empty()) ++ { ++ m_worker_idle = true; ++ m_idle_condvar.notify_all(); ++ } ++ } ++ }); ++} ++ ++void Scheduler::Shutdown() ++{ ++ SyncWorker(); ++ SynchronizeSubmissionThread(); ++} ++ ++void Scheduler::SynchronizeSubmissionThread() ++{ ++ SyncWorker(); ++ m_commandBufferManager->WaitForSubmitWorkerThreadIdle(); ++} ++ ++void Scheduler::WaitForFenceCounter(u64 counter) ++{ ++ if (m_commandBufferManager->GetCompletedFenceCounter() >= counter) ++ return; ++ ++ SyncWorker(); ++ m_commandBufferManager->WaitForFenceCounter(counter); ++} ++ ++void Scheduler::SubmitCommandBuffer(bool submit_on_worker_thread, bool wait_for_completion, ++ VkSwapchainKHR present_swap_chain, uint32_t present_image_index) ++{ ++ const u64 fence_counter = ++m_current_fence_counter; ++ Record([fence_counter, submit_on_worker_thread, wait_for_completion, present_swap_chain, ++ present_image_index](CommandBufferManager* command_buffer_mgr) { ++ command_buffer_mgr->GetStateTracker()->EndRenderPass(); ++ command_buffer_mgr->SubmitCommandBuffer(fence_counter, submit_on_worker_thread, ++ wait_for_completion, present_swap_chain, ++ present_image_index); ++ }); ++ ++ if (wait_for_completion) [[unlikely]] ++ g_scheduler->WaitForFenceCounter(fence_counter); ++ else ++ Flush(); ++} ++ ++std::unique_ptr g_scheduler; ++} // namespace Vulkan +diff -rupN dolphin.orig/Source/Core/VideoBackends/Vulkan/VKScheduler.h dolphin/Source/Core/VideoBackends/Vulkan/VKScheduler.h +--- dolphin.orig/Source/Core/VideoBackends/Vulkan/VKScheduler.h 1970-01-01 00:00:00.000000000 +0000 ++++ dolphin/Source/Core/VideoBackends/Vulkan/VKScheduler.h 2024-03-05 04:06:08.240295843 +0000 +@@ -0,0 +1,160 @@ ++// Copyright 2022 Dolphin Emulator Project ++// SPDX-License-Identifier: GPL-2.0-or-later ++ ++#pragma once ++ ++#include ++#include ++ ++#include "CommandBufferManager.h" ++#include "Common/Align.h" ++ ++namespace Vulkan ++{ ++class Scheduler ++{ ++ class Command ++ { ++ public: ++ virtual ~Command() = default; ++ ++ virtual void Execute(CommandBufferManager* cmdbuf) = 0; ++ ++ Command* GetNext() const { return next; } ++ ++ void SetNext(Command* next_) { next = next_; } ++ ++ private: ++ Command* next = nullptr; ++ }; ++ ++ template ++ class alignas(16) TypedCommand final : public Command ++ { ++ public: ++ explicit TypedCommand(T&& command_) : command{std::move(command_)} {} ++ ++ ~TypedCommand() override = default; ++ ++ TypedCommand(TypedCommand&&) = delete; ++ ++ TypedCommand& operator=(TypedCommand&&) = delete; ++ ++ void Execute(CommandBufferManager* cmdbuf) override { command(cmdbuf); } ++ ++ private: ++ T command; ++ }; ++ ++ class CommandChunk final ++ { ++ public: ++ void ExecuteAll(CommandBufferManager* cmdbuf); ++ ++ template ++ bool Record(T& command) ++ { ++ using FuncType = TypedCommand; ++ static_assert(sizeof(FuncType) < sizeof(data), "Lambda is too large"); ++ ++ command_offset = Common::AlignUp(command_offset, alignof(FuncType)); ++ if (command_offset > sizeof(data) - sizeof(FuncType)) [[unlikely]] ++ { ++ return false; ++ } ++ Command* const current_last = last; ++ last = new (data.data() + command_offset) FuncType(std::move(command)); ++ ++ if (current_last) [[likely]] ++ { ++ current_last->SetNext(last); ++ } ++ else ++ { ++ first = last; ++ } ++ command_offset += sizeof(FuncType); ++ return true; ++ } ++ ++ bool Empty() const { return command_offset == 0; } ++ ++ private: ++ Command* first = nullptr; ++ Command* last = nullptr; ++ ++ size_t command_offset = 0; ++ alignas(64) std::array data{}; ++ }; ++ ++public: ++ Scheduler(); ++ ~Scheduler(); ++ ++ bool Initialize(); ++ ++ void Flush(); ++ void SyncWorker(); ++ ++ void Shutdown(); ++ ++ template ++ void Record(T&& command) ++ { ++#ifdef VULKAN_DISABLE_THREADING ++ command(m_commandBufferManager.get()); ++ return; ++#endif ++ ++ if (m_chunk->Record(command)) [[likely]] ++ return; ++ ++ Flush(); ++ (void)m_chunk->Record(command); ++ } ++ ++ uint64_t GetCompletedFenceCounter() const ++ { ++ return m_commandBufferManager->GetCompletedFenceCounter(); ++ } ++ ++ uint64_t GetCurrentFenceCounter() const ++ { ++ return m_current_fence_counter.load(std::memory_order_acquire); ++ } ++ ++ void WaitForFenceCounter(u64 counter); ++ void SynchronizeSubmissionThread(); ++ ++ bool CheckLastPresentFail() { return m_commandBufferManager->CheckLastPresentFail(); } ++ VkResult GetLastPresentResult() const { return m_commandBufferManager->GetLastPresentResult(); } ++ bool CheckLastPresentDone() { return m_commandBufferManager->CheckLastPresentDone(); } ++ ++ void SubmitCommandBuffer(bool submit_on_worker_thread, bool wait_for_completion, ++ VkSwapchainKHR present_swap_chain = VK_NULL_HANDLE, ++ uint32_t present_image_index = 0xFFFFFFFF); ++ ++private: ++ void WorkerThread(); ++ void AcquireNewChunk(); ++ ++ std::unique_ptr m_commandBufferManager; ++ ++ std::unique_ptr m_chunk; ++ ++ std::thread m_worker; ++ std::unique_ptr m_submit_loop; ++ ++ std::atomic m_current_fence_counter = 1; ++ ++ std::queue> m_work_queue; ++ std::mutex m_work_mutex; ++ std::condition_variable m_idle_condvar; ++ bool m_worker_idle{true}; ++ ++ std::vector> m_chunk_reserve; ++ std::mutex m_reserve_mutex; ++}; ++ ++extern std::unique_ptr g_scheduler; ++} // namespace Vulkan +diff -rupN dolphin.orig/Source/Core/VideoBackends/Vulkan/VKStreamBuffer.cpp dolphin/Source/Core/VideoBackends/Vulkan/VKStreamBuffer.cpp +--- dolphin.orig/Source/Core/VideoBackends/Vulkan/VKStreamBuffer.cpp 2024-03-05 04:05:26.602983293 +0000 ++++ dolphin/Source/Core/VideoBackends/Vulkan/VKStreamBuffer.cpp 2024-03-05 04:06:08.240295843 +0000 +@@ -12,6 +12,7 @@ + #include "Common/MsgHandler.h" + + #include "VideoBackends/Vulkan/CommandBufferManager.h" ++#include "VideoBackends/Vulkan/VKScheduler.h" + #include "VideoBackends/Vulkan/VulkanContext.h" + + namespace Vulkan +@@ -24,7 +25,13 @@ StreamBuffer::~StreamBuffer() + { + // VMA_ALLOCATION_CREATE_MAPPED_BIT automatically handles unmapping for us + if (m_buffer != VK_NULL_HANDLE) +- g_command_buffer_mgr->DeferBufferDestruction(m_buffer, m_alloc); ++ { ++ g_scheduler->Record( ++ [c_buffer = m_buffer, c_alloc = m_alloc](CommandBufferManager* command_buffer_mgr) { ++ if (c_buffer != VK_NULL_HANDLE) ++ command_buffer_mgr->DeferBufferDestruction(c_buffer, c_alloc); ++ }); ++ } + } + + std::unique_ptr StreamBuffer::Create(VkBufferUsageFlags usage, u32 size) +@@ -75,8 +82,11 @@ bool StreamBuffer::AllocateBuffer() + + // Destroy the backings for the buffer after the command buffer executes + // VMA_ALLOCATION_CREATE_MAPPED_BIT automatically handles unmapping for us +- if (m_buffer != VK_NULL_HANDLE) +- g_command_buffer_mgr->DeferBufferDestruction(m_buffer, m_alloc); ++ g_scheduler->Record( ++ [c_buffer = m_buffer, c_alloc = m_alloc](CommandBufferManager* command_buffer_mgr) { ++ if (c_buffer != VK_NULL_HANDLE) ++ command_buffer_mgr->DeferBufferDestruction(c_buffer, c_alloc); ++ }); + + // Replace with the new buffer + m_buffer = buffer; +@@ -175,7 +185,7 @@ void StreamBuffer::UpdateCurrentFencePos + return; + + // Has the offset changed since the last fence? +- const u64 counter = g_command_buffer_mgr->GetCurrentFenceCounter(); ++ const u64 counter = g_scheduler->GetCurrentFenceCounter(); + if (!m_tracked_fences.empty() && m_tracked_fences.back().first == counter) + { + // Still haven't executed a command buffer, so just update the offset. +@@ -193,7 +203,7 @@ void StreamBuffer::UpdateGPUPosition() + auto start = m_tracked_fences.begin(); + auto end = start; + +- const u64 completed_counter = g_command_buffer_mgr->GetCompletedFenceCounter(); ++ const u64 completed_counter = g_scheduler->GetCompletedFenceCounter(); + while (end != m_tracked_fences.end() && completed_counter >= end->first) + { + m_current_gpu_position = end->second; +@@ -266,14 +276,13 @@ bool StreamBuffer::WaitForClearSpace(u32 + + // Did any fences satisfy this condition? + // Has the command buffer been executed yet? If not, the caller should execute it. +- if (iter == m_tracked_fences.end() || +- iter->first == g_command_buffer_mgr->GetCurrentFenceCounter()) ++ if (iter == m_tracked_fences.end() || iter->first == g_scheduler->GetCurrentFenceCounter()) + { + return false; + } + + // Wait until this fence is signaled. This will fire the callback, updating the GPU position. +- g_command_buffer_mgr->WaitForFenceCounter(iter->first); ++ g_scheduler->WaitForFenceCounter(iter->first); + m_tracked_fences.erase(m_tracked_fences.begin(), + m_current_offset == iter->second ? m_tracked_fences.end() : ++iter); + m_current_offset = new_offset; +diff -rupN dolphin.orig/Source/Core/VideoBackends/Vulkan/VKSwapChain.cpp dolphin/Source/Core/VideoBackends/Vulkan/VKSwapChain.cpp +--- dolphin.orig/Source/Core/VideoBackends/Vulkan/VKSwapChain.cpp 2024-03-05 04:05:26.602983293 +0000 ++++ dolphin/Source/Core/VideoBackends/Vulkan/VKSwapChain.cpp 2024-03-05 04:06:08.240295843 +0000 +@@ -13,9 +13,9 @@ + + #include "VideoBackends/Vulkan/CommandBufferManager.h" + #include "VideoBackends/Vulkan/ObjectCache.h" ++#include "VideoBackends/Vulkan/VKScheduler.h" + #include "VideoBackends/Vulkan/VKTexture.h" + #include "VideoBackends/Vulkan/VulkanContext.h" +-#include "VideoCommon/RenderBase.h" + + #if defined(VK_USE_PLATFORM_XLIB_KHR) + #include +@@ -25,15 +25,18 @@ namespace Vulkan + { + SwapChain::SwapChain(const WindowSystemInfo& wsi, VkSurfaceKHR surface, bool vsync) + : m_wsi(wsi), m_surface(surface), m_vsync_enabled(vsync), +- m_fullscreen_supported(g_vulkan_context->SupportsExclusiveFullscreen(wsi, surface)) ++ m_fullscreen_supported(g_vulkan_context->SupportsExclusiveFullscreen(wsi, surface)), ++ m_width(wsi.render_surface_width), m_height(wsi.render_surface_height) + { + } + + SwapChain::~SwapChain() + { ++ g_scheduler->SyncWorker(); + DestroySwapChainImages(); + DestroySwapChain(); + DestroySurface(); ++ DestroySemaphores(); + } + + VkSurfaceKHR SwapChain::CreateVulkanSurface(VkInstance instance, const WindowSystemInfo& wsi) +@@ -84,6 +87,29 @@ VkSurfaceKHR SwapChain::CreateVulkanSurf + } + #endif + ++#if defined(VK_USE_PLATFORM_WAYLAND_KHR) ++ if (wsi.type == WindowSystemType::Wayland) ++ { ++ VkWaylandSurfaceCreateInfoKHR surface_create_info = { ++ VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR, // VkStructureType sType ++ nullptr, // const void* pNext ++ 0, // VkWaylandSurfaceCreateFlagsKHR flags ++ static_cast(wsi.display_connection), // struct wl_display* display ++ static_cast(wsi.render_surface) // struct wl_surface* surface ++ }; ++ ++ VkSurfaceKHR surface; ++ VkResult res = vkCreateWaylandSurfaceKHR(instance, &surface_create_info, nullptr, &surface); ++ if (res != VK_SUCCESS) ++ { ++ LOG_VULKAN_ERROR(res, "vkCreateWaylandSurfaceKHR failed: "); ++ return VK_NULL_HANDLE; ++ } ++ ++ return surface; ++ } ++#endif ++ + #if defined(VK_USE_PLATFORM_ANDROID_KHR) + if (wsi.type == WindowSystemType::Android) + { +@@ -132,7 +158,8 @@ std::unique_ptr SwapChain::Cr + bool vsync) + { + std::unique_ptr swap_chain = std::make_unique(wsi, surface, vsync); +- if (!swap_chain->CreateSwapChain() || !swap_chain->SetupSwapChainImages()) ++ if (!swap_chain->CreateSwapChain() || !swap_chain->SetupSwapChainImages() || ++ !swap_chain->CreateSemaphores()) + return nullptr; + + return swap_chain; +@@ -237,6 +264,23 @@ bool SwapChain::SelectPresentMode() + return true; + } + ++bool SwapChain::CreateSemaphores() ++{ ++ static constexpr VkSemaphoreCreateInfo semaphore_create_info = { ++ VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, nullptr, 0}; ++ for (VkSemaphore& semaphore : m_semaphores) ++ { ++ VkResult res = vkCreateSemaphore(g_vulkan_context->GetDevice(), &semaphore_create_info, nullptr, ++ &semaphore); ++ if (res != VK_SUCCESS) ++ { ++ LOG_VULKAN_ERROR(res, "vkCreateSemaphore failed: "); ++ return false; ++ } ++ } ++ return true; ++} ++ + bool SwapChain::CreateSwapChain() + { + // Look up surface properties to determine image count and dimensions +@@ -265,8 +309,8 @@ bool SwapChain::CreateSwapChain() + VkExtent2D size = surface_capabilities.currentExtent; + if (size.width == UINT32_MAX) + { +- size.width = std::max(g_renderer->GetBackbufferWidth(), 1); +- size.height = std::max(g_renderer->GetBackbufferHeight(), 1); ++ size.width = static_cast(m_wsi.render_surface_width); ++ size.height = static_cast(m_wsi.render_surface_height); + } + size.width = std::clamp(size.width, surface_capabilities.minImageExtent.width, + surface_capabilities.maxImageExtent.width); +@@ -452,20 +496,33 @@ void SwapChain::DestroySwapChain() + m_swap_chain = VK_NULL_HANDLE; + } + +-VkResult SwapChain::AcquireNextImage() ++void SwapChain::DestroySemaphores() + { +- VkResult res = vkAcquireNextImageKHR(g_vulkan_context->GetDevice(), m_swap_chain, UINT64_MAX, +- g_command_buffer_mgr->GetCurrentCommandBufferSemaphore(), +- VK_NULL_HANDLE, &m_current_swap_chain_image_index); ++ for (VkSemaphore semaphore : m_semaphores) ++ { ++ if (semaphore != VK_NULL_HANDLE) ++ { ++ vkDestroySemaphore(g_vulkan_context->GetDevice(), semaphore, nullptr); ++ } ++ } ++} ++ ++VkResult SwapChain::AcquireNextImage(VkSemaphore semaphore) ++{ ++ VkResult res = ++ vkAcquireNextImageKHR(g_vulkan_context->GetDevice(), m_swap_chain, UINT64_MAX, semaphore, ++ VK_NULL_HANDLE, &m_current_swap_chain_image_index); + if (res != VK_SUCCESS && res != VK_ERROR_OUT_OF_DATE_KHR && res != VK_SUBOPTIMAL_KHR) + LOG_VULKAN_ERROR(res, "vkAcquireNextImageKHR failed: "); + + return res; + } + +-bool SwapChain::ResizeSwapChain() ++bool SwapChain::ResizeSwapChain(int window_width, int window_height) + { + DestroySwapChainImages(); ++ m_wsi.render_surface_width = window_width; ++ m_wsi.render_surface_height = window_height; + if (!CreateSwapChain() || !SetupSwapChainImages()) + { + PanicAlertFmt("Failed to re-configure swap chain images, this is fatal (for now)"); +@@ -531,7 +588,7 @@ bool SwapChain::SetFullscreenState(bool + #endif + } + +-bool SwapChain::RecreateSurface(void* native_handle) ++bool SwapChain::RecreateSurface(void* native_handle, int window_width, int window_height) + { + // Destroy the old swap chain, images, and surface. + DestroySwapChainImages(); +@@ -540,6 +597,8 @@ bool SwapChain::RecreateSurface(void* na + + // Re-create the surface with the new native handle + m_wsi.render_surface = native_handle; ++ m_wsi.render_surface_width = window_width; ++ m_wsi.render_surface_height = window_height; + m_surface = CreateVulkanSurface(g_vulkan_context->GetVulkanInstance(), m_wsi); + if (m_surface == VK_NULL_HANDLE) + return false; +diff -rupN dolphin.orig/Source/Core/VideoBackends/Vulkan/VKSwapChain.h dolphin/Source/Core/VideoBackends/Vulkan/VKSwapChain.h +--- dolphin.orig/Source/Core/VideoBackends/Vulkan/VKSwapChain.h 2024-03-05 04:05:26.602983293 +0000 ++++ dolphin/Source/Core/VideoBackends/Vulkan/VKSwapChain.h 2024-03-05 04:06:08.240295843 +0000 +@@ -3,6 +3,7 @@ + + #pragma once + ++#include + #include + #include + +@@ -50,10 +51,10 @@ public: + { + return m_swap_chain_images[m_current_swap_chain_image_index].framebuffer.get(); + } +- VkResult AcquireNextImage(); ++ VkResult AcquireNextImage(VkSemaphore semaphore); + +- bool RecreateSurface(void* native_handle); +- bool ResizeSwapChain(); ++ bool RecreateSurface(void* native_handle, int window_width, int window_height); ++ bool ResizeSwapChain(int window_width, int window_height); + bool RecreateSwapChain(); + + // Change vsync enabled state. This may fail as it causes a swapchain recreation. +@@ -70,10 +71,19 @@ public: + // Updates the fullscreen state. Must call on-thread. + bool SetFullscreenState(bool state); + ++ VkSemaphore GetNextSemaphore() ++ { ++ m_semaphore_index = (m_semaphore_index + 1) % NUM_COMMAND_BUFFERS; ++ return m_semaphores[m_semaphore_index]; ++ } ++ + private: + bool SelectSurfaceFormat(); + bool SelectPresentMode(); + ++ bool CreateSemaphores(); ++ void DestroySemaphores(); ++ + bool CreateSwapChain(); + void DestroySwapChain(); + +@@ -103,6 +113,9 @@ private: + std::vector m_swap_chain_images; + u32 m_current_swap_chain_image_index = 0; + ++ std::array m_semaphores = {}; ++ u32 m_semaphore_index = 0; ++ + u32 m_width = 0; + u32 m_height = 0; + u32 m_layers = 0; +diff -rupN dolphin.orig/Source/Core/VideoBackends/Vulkan/VKTexture.cpp dolphin/Source/Core/VideoBackends/Vulkan/VKTexture.cpp +--- dolphin.orig/Source/Core/VideoBackends/Vulkan/VKTexture.cpp 2024-03-05 04:05:26.602983293 +0000 ++++ dolphin/Source/Core/VideoBackends/Vulkan/VKTexture.cpp 2024-03-05 04:06:08.240295843 +0000 +@@ -21,6 +21,7 @@ + #include "VideoBackends/Vulkan/VKStreamBuffer.h" + #include "VideoBackends/Vulkan/VulkanContext.h" + ++#include "VKScheduler.h" + #include "VideoCommon/DriverDetails.h" + #include "VideoCommon/VideoConfig.h" + +@@ -45,14 +46,17 @@ VKTexture::VKTexture(const TextureConfig + + VKTexture::~VKTexture() + { +- StateTracker::GetInstance()->UnbindTexture(m_view); +- g_command_buffer_mgr->DeferImageViewDestruction(m_view); ++ g_scheduler->Record([c_view = m_view, c_image = m_image, ++ c_alloc = m_alloc](CommandBufferManager* command_buffer_mgr) { ++ command_buffer_mgr->GetStateTracker()->UnbindTexture(c_view); ++ command_buffer_mgr->DeferImageViewDestruction(c_view); + +- // If we don't have device memory allocated, the image is not owned by us (e.g. swapchain) +- if (m_alloc != VK_NULL_HANDLE) +- { +- g_command_buffer_mgr->DeferImageDestruction(m_image, m_alloc); +- } ++ // If we don't have device memory allocated, the image is not owned by us (e.g. swapchain) ++ if (c_alloc != VK_NULL_HANDLE) ++ { ++ command_buffer_mgr->DeferImageDestruction(c_image, c_alloc); ++ } ++ }); + } + + std::unique_ptr VKTexture::Create(const TextureConfig& tex_config, std::string_view name) +@@ -265,30 +269,35 @@ void VKTexture::CopyRectangleFromTexture + static_cast(dst_rect.GetHeight()) <= m_config.height, + "Dest rect is too large for CopyRectangleFromTexture"); + +- const u32 copy_layer_count = 1; +- +- VkImageCopy image_copy = { +- {VK_IMAGE_ASPECT_COLOR_BIT, src_level, src_layer, copy_layer_count}, +- {src_rect.left, src_rect.top, 0}, +- {VK_IMAGE_ASPECT_COLOR_BIT, dst_level, dst_layer, copy_layer_count}, +- {dst_rect.left, dst_rect.top, 0}, +- {static_cast(src_rect.GetWidth()), static_cast(src_rect.GetHeight()), 1}}; +- +- // Must be called outside of a render pass. +- StateTracker::GetInstance()->EndRenderPass(); ++ g_scheduler->Record([](CommandBufferManager* command_buffer_mgr) { ++ // Must be called outside of a render pass. ++ command_buffer_mgr->GetStateTracker()->EndRenderPass(); ++ }); + + const VkImageLayout old_src_layout = src_texture->GetLayout(); +- src_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), +- VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); +- TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), +- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); +- +- vkCmdCopyImage(g_command_buffer_mgr->GetCurrentCommandBuffer(), src_texture->m_image, +- VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_image, +- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy); ++ src_texture->TransitionToLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); ++ TransitionToLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); ++ ++ g_scheduler->Record([c_src_image = src_texture->GetImage(), c_image = m_image, ++ c_src_level = src_level, c_src_layer = src_layer, ++ c_src_layers = src_texture->GetLayers(), c_src_rect = src_rect, ++ c_dst_level = dst_level, c_dst_layer = dst_layer, ++ c_dst_layers = m_config.layers, ++ c_dst_rect = dst_rect](CommandBufferManager* command_buffer_mgr) { ++ VkImageCopy image_copy = {{VK_IMAGE_ASPECT_COLOR_BIT, c_src_level, c_src_layer, c_src_layers}, ++ {c_src_rect.left, c_src_rect.top, 0}, ++ {VK_IMAGE_ASPECT_COLOR_BIT, c_dst_level, c_dst_layer, c_dst_layers}, ++ {c_dst_rect.left, c_dst_rect.top, 0}, ++ {static_cast(c_src_rect.GetWidth()), ++ static_cast(c_src_rect.GetHeight()), 1}}; ++ ++ vkCmdCopyImage(command_buffer_mgr->GetCurrentCommandBuffer(), c_src_image, ++ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, c_image, ++ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy); ++ }); + + // Only restore the source layout. Destination is restored by FinishedRendering(). +- src_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), old_src_layout); ++ src_texture->TransitionToLayout(old_src_layout); + } + + void VKTexture::ResolveFromTexture(const AbstractTexture* src, const MathUtil::Rectangle& rect, +@@ -301,24 +310,28 @@ void VKTexture::ResolveFromTexture(const + rect.top + rect.GetHeight() <= static_cast(srcentry->m_config.height)); + + // Resolving is considered to be a transfer operation. +- StateTracker::GetInstance()->EndRenderPass(); ++ g_scheduler->Record([](CommandBufferManager* command_buffer_mgr) { ++ command_buffer_mgr->GetStateTracker()->EndRenderPass(); ++ }); + VkImageLayout old_src_layout = srcentry->m_layout; +- srcentry->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), +- VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); +- TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), +- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); +- +- VkImageResolve resolve = { +- {VK_IMAGE_ASPECT_COLOR_BIT, level, layer, 1}, // srcSubresource +- {rect.left, rect.top, 0}, // srcOffset +- {VK_IMAGE_ASPECT_COLOR_BIT, level, layer, 1}, // dstSubresource +- {rect.left, rect.top, 0}, // dstOffset +- {static_cast(rect.GetWidth()), static_cast(rect.GetHeight()), 1} // extent +- }; +- vkCmdResolveImage(g_command_buffer_mgr->GetCurrentCommandBuffer(), srcentry->m_image, +- srcentry->m_layout, m_image, m_layout, 1, &resolve); ++ srcentry->TransitionToLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); ++ TransitionToLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + +- srcentry->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), old_src_layout); ++ g_scheduler->Record([c_src_image = srcentry->GetImage(), c_image = m_image, ++ c_src_layout = srcentry->GetLayout(), c_dst_layout = m_layout, c_rect = rect, ++ c_layer = layer, c_level = level](CommandBufferManager* command_buffer_mgr) { ++ VkImageResolve resolve = { ++ {VK_IMAGE_ASPECT_COLOR_BIT, c_level, c_layer, 1}, // srcSubresource ++ {c_rect.left, c_rect.top, 0}, // srcOffset ++ {VK_IMAGE_ASPECT_COLOR_BIT, c_level, c_layer, 1}, // dstSubresource ++ {c_rect.left, c_rect.top, 0}, // dstOffset ++ {static_cast(c_rect.GetWidth()), static_cast(c_rect.GetHeight()), 1} // extent ++ }; ++ vkCmdResolveImage(command_buffer_mgr->GetCurrentCommandBuffer(), c_src_image, c_src_layout, ++ c_image, c_dst_layout, 1, &resolve); ++ }); ++ ++ srcentry->TransitionToLayout(old_src_layout); + } + + void VKTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer, +@@ -344,8 +357,7 @@ void VKTexture::Load(u32 level, u32 widt + // When the last mip level is uploaded, we transition to SHADER_READ_ONLY, ready for use. This is + // because we can't transition in a render pass, and we don't necessarily know when this texture + // is going to be used. +- TransitionToLayout(g_command_buffer_mgr->GetCurrentInitCommandBuffer(), +- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); ++ TransitionToLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true); + + // For unaligned textures, we can save some memory in the transfer buffer by skipping the rows + // that lie outside of the texture's dimensions. +@@ -396,26 +408,30 @@ void VKTexture::Load(u32 level, u32 widt + temp_buffer->Unmap(); + } + +- // Copy from the streaming buffer to the actual image. +- VkBufferImageCopy image_copy = { +- upload_buffer_offset, // VkDeviceSize bufferOffset +- row_length, // uint32_t bufferRowLength +- 0, // uint32_t bufferImageHeight +- {VK_IMAGE_ASPECT_COLOR_BIT, level, layer, 1}, // VkImageSubresourceLayers imageSubresource +- {0, 0, 0}, // VkOffset3D imageOffset +- {width, height, 1} // VkExtent3D imageExtent +- }; +- vkCmdCopyBufferToImage(g_command_buffer_mgr->GetCurrentInitCommandBuffer(), upload_buffer, +- m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy); ++ g_scheduler->Record([c_upload_buffer_offset = upload_buffer_offset, c_row_length = row_length, ++ c_level = level, c_width = width, c_height = height, ++ c_upload_buffer = upload_buffer, ++ c_image = m_image](CommandBufferManager* command_buffer_mgr) { ++ // Copy from the streaming buffer to the actual image. ++ VkBufferImageCopy image_copy = { ++ c_upload_buffer_offset, // VkDeviceSize bufferOffset ++ c_row_length, // uint32_t bufferRowLength ++ 0, // uint32_t bufferImageHeight ++ {VK_IMAGE_ASPECT_COLOR_BIT, c_level, 0, 1}, // VkImageSubresourceLayers imageSubresource ++ {0, 0, 0}, // VkOffset3D imageOffset ++ {c_width, c_height, 1} // VkExtent3D imageExtent ++ }; ++ vkCmdCopyBufferToImage(command_buffer_mgr->GetCurrentInitCommandBuffer(), c_upload_buffer, ++ c_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy); ++ }); + + // Preemptively transition to shader read only after uploading the last mip level, as we're + // likely finished with writes to this texture for now. We can't do this in common with a + // FinishedRendering() call because the upload happens in the init command buffer, and we + // don't want to interrupt the render pass with calls which were executed ages before. +- if (level == (m_config.levels - 1) && layer == (m_config.layers - 1)) ++ if (level == (m_config.levels - 1)) + { +- TransitionToLayout(g_command_buffer_mgr->GetCurrentInitCommandBuffer(), +- VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); ++ TransitionToLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, true); + } + } + +@@ -424,9 +440,10 @@ void VKTexture::FinishedRendering() + if (m_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) + return; + +- StateTracker::GetInstance()->EndRenderPass(); +- TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), +- VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); ++ g_scheduler->Record([](CommandBufferManager* command_buffer_mgr) { ++ command_buffer_mgr->GetStateTracker()->EndRenderPass(); ++ }); ++ TransitionToLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + } + + void VKTexture::OverrideImageLayout(VkImageLayout new_layout) +@@ -434,9 +451,9 @@ void VKTexture::OverrideImageLayout(VkIm + m_layout = new_layout; + } + +-void VKTexture::TransitionToLayout(VkCommandBuffer command_buffer, VkImageLayout new_layout) const ++void VKTexture::TransitionToLayout(VkImageLayout new_layout, bool init_command_buffer) const + { +- if (m_layout == new_layout) ++ if (m_layout == new_layout) [[likely]] + return; + + VkImageMemoryBarrier barrier = { +@@ -573,14 +590,19 @@ void VKTexture::TransitionToLayout(VkCom + } + m_compute_layout = ComputeImageLayout::Undefined; + +- vkCmdPipelineBarrier(command_buffer, srcStageMask, dstStageMask, 0, 0, nullptr, 0, nullptr, 1, +- &barrier); ++ g_scheduler->Record([c_src_stage_mask = srcStageMask, c_dst_stage_mask = dstStageMask, ++ c_barrier = barrier, ++ init_command_buffer](CommandBufferManager* command_buffer_mgr) { ++ vkCmdPipelineBarrier(init_command_buffer ? command_buffer_mgr->GetCurrentInitCommandBuffer() : ++ command_buffer_mgr->GetCurrentCommandBuffer(), ++ c_src_stage_mask, c_dst_stage_mask, 0, 0, nullptr, 0, nullptr, 1, ++ &c_barrier); ++ }); + + m_layout = new_layout; + } + +-void VKTexture::TransitionToLayout(VkCommandBuffer command_buffer, +- ComputeImageLayout new_layout) const ++void VKTexture::TransitionToLayout(ComputeImageLayout new_layout, bool init_command_buffer) const + { + ASSERT(new_layout != ComputeImageLayout::Undefined); + if (m_compute_layout == new_layout) +@@ -678,8 +700,14 @@ void VKTexture::TransitionToLayout(VkCom + m_layout = barrier.newLayout; + m_compute_layout = new_layout; + +- vkCmdPipelineBarrier(command_buffer, srcStageMask, dstStageMask, 0, 0, nullptr, 0, nullptr, 1, +- &barrier); ++ g_scheduler->Record([c_src_stage_mask = srcStageMask, c_dst_stage_mask = dstStageMask, ++ c_barrier = barrier, ++ init_command_buffer](CommandBufferManager* command_buffer_mgr) { ++ vkCmdPipelineBarrier(init_command_buffer ? command_buffer_mgr->GetCurrentInitCommandBuffer() : ++ command_buffer_mgr->GetCurrentCommandBuffer(), ++ c_src_stage_mask, c_dst_stage_mask, 0, 0, nullptr, 0, nullptr, 1, ++ &c_barrier); ++ }); + } + + VKStagingTexture::VKStagingTexture(PrivateTag, StagingTextureType type, const TextureConfig& config, +@@ -694,7 +722,11 @@ VKStagingTexture::~VKStagingTexture() + { + if (m_linear_image != VK_NULL_HANDLE) + { +- g_command_buffer_mgr->DeferImageDestruction(m_linear_image, m_linear_image_alloc); ++ g_scheduler->Record( ++ [c_linear_image = m_linear_image, ++ c_linear_image_alloc = m_linear_image_alloc](CommandBufferManager* command_buffer_mgr) { ++ command_buffer_mgr->DeferImageDestruction(c_linear_image, c_linear_image_alloc); ++ }); + } + } + +@@ -816,12 +848,12 @@ void VKStagingTexture::CopyFromTexture(c + src_rect.top >= 0 && static_cast(src_rect.bottom) <= src_tex->GetHeight()); + ASSERT(dst_rect.left >= 0 && static_cast(dst_rect.right) <= m_config.width && + dst_rect.top >= 0 && static_cast(dst_rect.bottom) <= m_config.height); +- +- StateTracker::GetInstance()->EndRenderPass(); ++ g_scheduler->Record([](CommandBufferManager* command_buffer_mgr) { ++ command_buffer_mgr->GetStateTracker()->EndRenderPass(); ++ }); + + VkImageLayout old_layout = src_tex->GetLayout(); +- src_tex->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), +- VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); ++ src_tex->TransitionToLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + + // Issue the image->buffer copy, but delay it for now. + VkBufferImageCopy image_copy = {}; +@@ -844,15 +876,17 @@ void VKStagingTexture::CopyFromTexture(c + image_copy.imageOffset = {0, 0, 0}; + } + +- vkCmdCopyImageToBuffer(g_command_buffer_mgr->GetCurrentCommandBuffer(), src_image, +- VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_staging_buffer->GetBuffer(), 1, +- &image_copy); ++ g_scheduler->Record([c_src_image = src_image, c_dst_buffer = m_staging_buffer->GetBuffer(), ++ c_image_copy = image_copy](CommandBufferManager* command_buffer_mgr) { ++ vkCmdCopyImageToBuffer(command_buffer_mgr->GetCurrentCommandBuffer(), c_src_image, ++ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, c_dst_buffer, 1, &c_image_copy); ++ }); + + // Restore old source texture layout. +- src_tex->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), old_layout); ++ src_tex->TransitionToLayout(old_layout); + + m_needs_flush = true; +- m_flush_fence_counter = g_command_buffer_mgr->GetCurrentFenceCounter(); ++ m_flush_fence_counter = g_scheduler->GetCurrentFenceCounter(); + } + + void VKStagingTexture::CopyFromTextureToLinearImage(const VKTexture* src_tex, +@@ -864,44 +898,49 @@ void VKStagingTexture::CopyFromTextureTo + // with optimal tiling (VK_IMAGE_TILING_OPTIMAL) to a buffer. + // That allocation is very slow, so we just do it ourself and reuse the intermediate image. + +- const VkImageAspectFlags aspect = VKTexture::GetImageViewAspectForFormat(src_tex->GetFormat()); +- +- VkImageMemoryBarrier linear_image_barrier = {}; +- linear_image_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; +- linear_image_barrier.pNext = nullptr; +- linear_image_barrier.srcAccessMask = 0; +- linear_image_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_TRANSFER_READ_BIT; +- linear_image_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; +- linear_image_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; +- linear_image_barrier.image = m_linear_image; +- linear_image_barrier.subresourceRange = {aspect, 0, 1, 0, 1}; +- vkCmdPipelineBarrier(g_command_buffer_mgr->GetCurrentCommandBuffer(), +- VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, +- nullptr, 0, nullptr, 1, &linear_image_barrier); +- +- VkImageBlit blit; +- blit.srcSubresource = {aspect, src_level, src_layer, 1}; +- blit.dstSubresource.layerCount = 1; +- blit.dstSubresource.baseArrayLayer = 0; +- blit.dstSubresource.mipLevel = 0; +- blit.dstSubresource.aspectMask = linear_image_barrier.subresourceRange.aspectMask; +- blit.srcOffsets[0] = {src_rect.left, src_rect.top, 0}; +- blit.srcOffsets[1] = {static_cast(blit.srcOffsets[0].x + src_rect.GetWidth()), +- static_cast(blit.srcOffsets[0].y + src_rect.GetHeight()), 1}; +- blit.dstOffsets[0] = {0, 0, 0}; +- blit.dstOffsets[1] = {dst_rect.GetWidth(), dst_rect.GetHeight(), 1u}; +- +- vkCmdBlitImage(g_command_buffer_mgr->GetCurrentCommandBuffer(), src_tex->GetImage(), +- VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_linear_image, +- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, VK_FILTER_NEAREST); +- +- linear_image_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; +- linear_image_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; +- linear_image_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; +- +- vkCmdPipelineBarrier(g_command_buffer_mgr->GetCurrentCommandBuffer(), +- VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, +- nullptr, 0, nullptr, 1, &linear_image_barrier); ++ g_scheduler->Record([c_linear_image = m_linear_image, c_src_image = src_tex->GetImage(), ++ c_src_format = src_tex->GetFormat(), c_src_rect = src_rect, ++ c_dst_rect = dst_rect, c_src_layer = src_layer, ++ c_src_level = src_level](CommandBufferManager* command_buffer_mgr) { ++ const VkImageAspectFlags aspect = VKTexture::GetImageViewAspectForFormat(c_src_format); ++ ++ VkImageMemoryBarrier linear_image_barrier = {}; ++ linear_image_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; ++ linear_image_barrier.pNext = nullptr; ++ linear_image_barrier.srcAccessMask = 0; ++ linear_image_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_TRANSFER_READ_BIT; ++ linear_image_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; ++ linear_image_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; ++ linear_image_barrier.image = c_linear_image; ++ linear_image_barrier.subresourceRange = {aspect, 0, 1, 0, 1}; ++ vkCmdPipelineBarrier(command_buffer_mgr->GetCurrentCommandBuffer(), ++ VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, ++ nullptr, 0, nullptr, 1, &linear_image_barrier); ++ ++ VkImageBlit blit; ++ blit.srcSubresource = {aspect, c_src_level, c_src_layer, 1}; ++ blit.dstSubresource.layerCount = 1; ++ blit.dstSubresource.baseArrayLayer = 0; ++ blit.dstSubresource.mipLevel = 0; ++ blit.dstSubresource.aspectMask = linear_image_barrier.subresourceRange.aspectMask; ++ blit.srcOffsets[0] = {c_src_rect.left, c_src_rect.top, 0}; ++ blit.srcOffsets[1] = {static_cast(blit.srcOffsets[0].x + c_src_rect.GetWidth()), ++ static_cast(blit.srcOffsets[0].y + c_src_rect.GetHeight()), 1}; ++ blit.dstOffsets[0] = {0, 0, 0}; ++ blit.dstOffsets[1] = {c_dst_rect.GetWidth(), c_dst_rect.GetHeight(), 1u}; ++ ++ vkCmdBlitImage(command_buffer_mgr->GetCurrentCommandBuffer(), c_src_image, ++ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, c_linear_image, ++ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, VK_FILTER_NEAREST); ++ ++ linear_image_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; ++ linear_image_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; ++ linear_image_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; ++ ++ vkCmdPipelineBarrier(command_buffer_mgr->GetCurrentCommandBuffer(), ++ VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, ++ nullptr, 0, nullptr, 1, &linear_image_barrier); ++ }); + } + + void VKStagingTexture::CopyToTexture(const MathUtil::Rectangle& src_rect, AbstractTexture* dst, +@@ -919,32 +958,40 @@ void VKStagingTexture::CopyToTexture(con + + // Flush caches before copying. + m_staging_buffer->FlushCPUCache(); +- StateTracker::GetInstance()->EndRenderPass(); ++ ++ g_scheduler->Record([](CommandBufferManager* command_buffer_manager) { ++ command_buffer_manager->GetStateTracker()->EndRenderPass(); ++ }); + + VkImageLayout old_layout = dst_tex->GetLayout(); +- dst_tex->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), +- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); ++ dst_tex->TransitionToLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + +- // Issue the image->buffer copy, but delay it for now. +- VkBufferImageCopy image_copy = {}; +- image_copy.bufferOffset = +- static_cast(static_cast(src_rect.top) * m_config.GetStride() + +- static_cast(src_rect.left) * m_texel_size); +- image_copy.bufferRowLength = static_cast(m_config.width); +- image_copy.bufferImageHeight = 0; +- image_copy.imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, dst_level, dst_layer, 1}; +- image_copy.imageOffset = {dst_rect.left, dst_rect.top, 0}; +- image_copy.imageExtent = {static_cast(dst_rect.GetWidth()), +- static_cast(dst_rect.GetHeight()), 1u}; +- vkCmdCopyBufferToImage(g_command_buffer_mgr->GetCurrentCommandBuffer(), +- m_staging_buffer->GetBuffer(), dst_tex->GetImage(), +- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy); ++ g_scheduler->Record( ++ [c_src_rect = src_rect, c_dst_rect = dst_rect, c_dst_layer = dst_layer, ++ c_dst_level = dst_level, c_width = m_config.width, c_height = m_config.height, ++ c_stride = m_config.GetStride(), c_texel_size = m_texel_size, ++ c_staging_buffer = m_staging_buffer->GetBuffer(), ++ c_dst_image = dst_tex->GetImage()](CommandBufferManager* command_buffer_mgr) { ++ // Issue the image->buffer copy, but delay it for now. ++ VkBufferImageCopy image_copy = {}; ++ image_copy.bufferOffset = ++ static_cast(static_cast(c_src_rect.top) * c_stride + ++ static_cast(c_src_rect.left) * c_texel_size); ++ image_copy.bufferRowLength = static_cast(c_width); ++ image_copy.bufferImageHeight = 0; ++ image_copy.imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, c_dst_level, c_dst_layer, 1}; ++ image_copy.imageOffset = {c_dst_rect.left, c_dst_rect.top, 0}; ++ image_copy.imageExtent = {static_cast(c_dst_rect.GetWidth()), ++ static_cast(c_dst_rect.GetHeight()), 1u}; ++ vkCmdCopyBufferToImage(command_buffer_mgr->GetCurrentCommandBuffer(), c_staging_buffer, ++ c_dst_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy); ++ }); + + // Restore old source texture layout. +- dst_tex->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), old_layout); ++ dst_tex->TransitionToLayout(old_layout); + + m_needs_flush = true; +- m_flush_fence_counter = g_command_buffer_mgr->GetCurrentFenceCounter(); ++ m_flush_fence_counter = g_scheduler->GetCurrentFenceCounter(); + } + + bool VKStagingTexture::Map() +@@ -964,7 +1011,7 @@ void VKStagingTexture::Flush() + return; + + // Is this copy in the current command buffer? +- if (g_command_buffer_mgr->GetCurrentFenceCounter() == m_flush_fence_counter) ++ if (g_scheduler->GetCurrentFenceCounter() == m_flush_fence_counter) + { + // Execute the command buffer and wait for it to finish. + Renderer::GetInstance()->ExecuteCommandBuffer(false, true); +@@ -972,7 +1019,7 @@ void VKStagingTexture::Flush() + else + { + // Wait for the GPU to finish with it. +- g_command_buffer_mgr->WaitForFenceCounter(m_flush_fence_counter); ++ g_scheduler->WaitForFenceCounter(m_flush_fence_counter); + } + + // For readback textures, invalidate the CPU cache as there is new data there. +@@ -998,7 +1045,11 @@ VKFramebuffer::VKFramebuffer(VKTexture* + + VKFramebuffer::~VKFramebuffer() + { +- g_command_buffer_mgr->DeferFramebufferDestruction(m_fb); ++ g_scheduler->SyncWorker(); // TODO ++ ++ g_scheduler->Record([c_fb = m_fb](CommandBufferManager* command_buffer_mgr) { ++ command_buffer_mgr->DeferFramebufferDestruction(c_fb); ++ }); + } + + std::unique_ptr VKFramebuffer::Create(VKTexture* color_attachment, +@@ -1067,15 +1118,13 @@ void VKFramebuffer::TransitionForRender( + if (m_color_attachment) + { + static_cast(m_color_attachment) +- ->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), +- VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); ++ ->TransitionToLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + } + + if (m_depth_attachment) + { + static_cast(m_depth_attachment) +- ->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), +- VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); ++ ->TransitionToLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + } + } + } // namespace Vulkan +diff -rupN dolphin.orig/Source/Core/VideoBackends/Vulkan/VKTexture.h dolphin/Source/Core/VideoBackends/Vulkan/VKTexture.h +--- dolphin.orig/Source/Core/VideoBackends/Vulkan/VKTexture.h 2024-03-05 04:05:26.602983293 +0000 ++++ dolphin/Source/Core/VideoBackends/Vulkan/VKTexture.h 2024-03-05 04:06:08.240295843 +0000 +@@ -67,8 +67,8 @@ public: + // irrelevant and will not be loaded. + void OverrideImageLayout(VkImageLayout new_layout); + +- void TransitionToLayout(VkCommandBuffer command_buffer, VkImageLayout new_layout) const; +- void TransitionToLayout(VkCommandBuffer command_buffer, ComputeImageLayout new_layout) const; ++ void TransitionToLayout(VkImageLayout new_layout, bool init_command_buffer = false) const; ++ void TransitionToLayout(ComputeImageLayout new_layout, bool init_command_buffer = false) const; + + private: + bool CreateView(VkImageViewType type); +diff -rupN dolphin.orig/Source/Core/VideoBackends/Vulkan/VKVertexManager.cpp dolphin/Source/Core/VideoBackends/Vulkan/VKVertexManager.cpp +--- dolphin.orig/Source/Core/VideoBackends/Vulkan/VKVertexManager.cpp 2024-03-05 04:05:26.602983293 +0000 ++++ dolphin/Source/Core/VideoBackends/Vulkan/VKVertexManager.cpp 2024-03-05 04:06:08.240295843 +0000 +@@ -15,6 +15,7 @@ + #include "VideoBackends/Vulkan/CommandBufferManager.h" + #include "VideoBackends/Vulkan/StateTracker.h" + #include "VideoBackends/Vulkan/VKRenderer.h" ++#include "VideoBackends/Vulkan/VKScheduler.h" + #include "VideoBackends/Vulkan/VKStreamBuffer.h" + #include "VideoBackends/Vulkan/VKVertexFormat.h" + #include "VideoBackends/Vulkan/VulkanContext.h" +@@ -67,11 +68,11 @@ bool VertexManager::Initialize() + + m_vertex_stream_buffer = + StreamBuffer::Create(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, +- VERTEX_STREAM_BUFFER_SIZE); ++ VERTEX_STREAM_BUFFER_SIZE * 2); + m_index_stream_buffer = +- StreamBuffer::Create(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, INDEX_STREAM_BUFFER_SIZE); ++ StreamBuffer::Create(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, INDEX_STREAM_BUFFER_SIZE * 2); + m_uniform_stream_buffer = +- StreamBuffer::Create(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, UNIFORM_STREAM_BUFFER_SIZE); ++ StreamBuffer::Create(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, UNIFORM_STREAM_BUFFER_SIZE * 2); + if (!m_vertex_stream_buffer || !m_index_stream_buffer || !m_uniform_stream_buffer) + { + PanicAlertFmt("Failed to allocate streaming buffers"); +@@ -121,13 +122,18 @@ bool VertexManager::Initialize() + + // Bind the buffers to all the known spots even if it's not used, to keep the driver happy. + UploadAllConstants(); +- StateTracker::GetInstance()->SetUtilityUniformBuffer(m_uniform_stream_buffer->GetBuffer(), 0, +- sizeof(VertexShaderConstants)); +- for (u32 i = 0; i < NUM_COMPUTE_TEXEL_BUFFERS; i++) +- { +- StateTracker::GetInstance()->SetTexelBuffer(i, +- m_texel_buffer_views[TEXEL_BUFFER_FORMAT_R8_UINT]); +- } ++ ++ g_scheduler->Record([c_buffer = m_uniform_stream_buffer->GetBuffer(), ++ c_texel_buffer_view = m_texel_buffer_views[TEXEL_BUFFER_FORMAT_R8_UINT]]( ++ CommandBufferManager* command_buffer_mgr) { ++ command_buffer_mgr->GetStateTracker()->SetUtilityUniformBuffer(c_buffer, 0, ++ sizeof(VertexShaderConstants)); ++ ++ for (u32 i = 0; i < NUM_COMPUTE_TEXEL_BUFFERS; i++) ++ { ++ command_buffer_mgr->GetStateTracker()->SetTexelBuffer(i, c_texel_buffer_view); ++ } ++ }); + + return true; + } +@@ -189,10 +195,13 @@ void VertexManager::CommitBuffer(u32 num + ADDSTAT(g_stats.this_frame.bytes_vertex_streamed, static_cast(vertex_data_size)); + ADDSTAT(g_stats.this_frame.bytes_index_streamed, static_cast(index_data_size)); + +- StateTracker::GetInstance()->SetVertexBuffer(m_vertex_stream_buffer->GetBuffer(), 0, +- VERTEX_STREAM_BUFFER_SIZE); +- StateTracker::GetInstance()->SetIndexBuffer(m_index_stream_buffer->GetBuffer(), 0, +- VK_INDEX_TYPE_UINT16); ++ g_scheduler->Record([c_vertex_buffer = m_vertex_stream_buffer->GetBuffer(), ++ c_index_buffer = m_index_stream_buffer->GetBuffer()]( ++ CommandBufferManager* command_buffer_mgr) { ++ command_buffer_mgr->GetStateTracker()->SetVertexBuffer(c_vertex_buffer, 0, ++ VERTEX_STREAM_BUFFER_SIZE); ++ command_buffer_mgr->GetStateTracker()->SetIndexBuffer(c_index_buffer, 0, VK_INDEX_TYPE_UINT16); ++ }); + } + + void VertexManager::UploadUniforms() +@@ -210,9 +219,12 @@ void VertexManager::UpdateVertexShaderCo + if (!vertex_shader_manager.dirty || !ReserveConstantStorage()) + return; + +- StateTracker::GetInstance()->SetGXUniformBuffer( +- UBO_DESCRIPTOR_SET_BINDING_VS, m_uniform_stream_buffer->GetBuffer(), +- m_uniform_stream_buffer->GetCurrentOffset(), sizeof(VertexShaderConstants)); ++ g_scheduler->Record([c_buffer = m_uniform_stream_buffer->GetBuffer(), ++ c_offset = m_uniform_stream_buffer->GetCurrentOffset()]( ++ CommandBufferManager* command_buffer_mgr) { ++ command_buffer_mgr->GetStateTracker()->SetGXUniformBuffer( ++ UBO_DESCRIPTOR_SET_BINDING_VS, c_buffer, c_offset, sizeof(VertexShaderConstants)); ++ }); + std::memcpy(m_uniform_stream_buffer->GetCurrentHostPointer(), &vertex_shader_manager.constants, + sizeof(VertexShaderConstants)); + m_uniform_stream_buffer->CommitMemory(sizeof(VertexShaderConstants)); +@@ -228,9 +240,13 @@ void VertexManager::UpdateGeometryShader + if (!geometry_shader_manager.dirty || !ReserveConstantStorage()) + return; + +- StateTracker::GetInstance()->SetGXUniformBuffer( +- UBO_DESCRIPTOR_SET_BINDING_GS, m_uniform_stream_buffer->GetBuffer(), +- m_uniform_stream_buffer->GetCurrentOffset(), sizeof(GeometryShaderConstants)); ++ g_scheduler->Record([c_buffer = m_uniform_stream_buffer->GetBuffer(), ++ c_offset = m_uniform_stream_buffer->GetCurrentOffset()]( ++ CommandBufferManager* command_buffer_mgr) { ++ command_buffer_mgr->GetStateTracker()->SetGXUniformBuffer( ++ UBO_DESCRIPTOR_SET_BINDING_GS, c_buffer, c_offset, sizeof(GeometryShaderConstants)); ++ }); ++ + std::memcpy(m_uniform_stream_buffer->GetCurrentHostPointer(), &geometry_shader_manager.constants, + sizeof(GeometryShaderConstants)); + m_uniform_stream_buffer->CommitMemory(sizeof(GeometryShaderConstants)); +@@ -246,9 +262,13 @@ void VertexManager::UpdatePixelShaderCon + if (!pixel_shader_manager.dirty || !ReserveConstantStorage()) + return; + +- StateTracker::GetInstance()->SetGXUniformBuffer( +- UBO_DESCRIPTOR_SET_BINDING_PS, m_uniform_stream_buffer->GetBuffer(), +- m_uniform_stream_buffer->GetCurrentOffset(), sizeof(PixelShaderConstants)); ++ g_scheduler->Record([c_buffer = m_uniform_stream_buffer->GetBuffer(), ++ c_offset = m_uniform_stream_buffer->GetCurrentOffset()]( ++ CommandBufferManager* command_buffer_mgr) { ++ command_buffer_mgr->GetStateTracker()->SetGXUniformBuffer( ++ UBO_DESCRIPTOR_SET_BINDING_PS, c_buffer, c_offset, sizeof(PixelShaderConstants)); ++ }); ++ + std::memcpy(m_uniform_stream_buffer->GetCurrentHostPointer(), &pixel_shader_manager.constants, + sizeof(PixelShaderConstants)); + m_uniform_stream_buffer->CommitMemory(sizeof(PixelShaderConstants)); +@@ -299,18 +319,21 @@ void VertexManager::UploadAllConstants() + auto& geometry_shader_manager = system.GetGeometryShaderManager(); + + // Update bindings +- StateTracker::GetInstance()->SetGXUniformBuffer( +- UBO_DESCRIPTOR_SET_BINDING_PS, m_uniform_stream_buffer->GetBuffer(), +- m_uniform_stream_buffer->GetCurrentOffset() + pixel_constants_offset, +- sizeof(PixelShaderConstants)); +- StateTracker::GetInstance()->SetGXUniformBuffer( +- UBO_DESCRIPTOR_SET_BINDING_VS, m_uniform_stream_buffer->GetBuffer(), +- m_uniform_stream_buffer->GetCurrentOffset() + vertex_constants_offset, +- sizeof(VertexShaderConstants)); +- StateTracker::GetInstance()->SetGXUniformBuffer( +- UBO_DESCRIPTOR_SET_BINDING_GS, m_uniform_stream_buffer->GetBuffer(), +- m_uniform_stream_buffer->GetCurrentOffset() + geometry_constants_offset, +- sizeof(GeometryShaderConstants)); ++ g_scheduler->Record( ++ [c_buffer = m_uniform_stream_buffer->GetBuffer(), ++ c_ps_offset = m_uniform_stream_buffer->GetCurrentOffset() + pixel_constants_offset, ++ c_vs_offset = m_uniform_stream_buffer->GetCurrentOffset() + vertex_constants_offset, ++ c_gs_offset = m_uniform_stream_buffer->GetCurrentOffset() + ++ geometry_constants_offset](CommandBufferManager* command_buffer_mgr) { ++ command_buffer_mgr->GetStateTracker()->SetGXUniformBuffer( ++ UBO_DESCRIPTOR_SET_BINDING_PS, c_buffer, c_ps_offset, sizeof(PixelShaderConstants)); ++ ++ command_buffer_mgr->GetStateTracker()->SetGXUniformBuffer( ++ UBO_DESCRIPTOR_SET_BINDING_VS, c_buffer, c_vs_offset, sizeof(VertexShaderConstants)); ++ ++ command_buffer_mgr->GetStateTracker()->SetGXUniformBuffer( ++ UBO_DESCRIPTOR_SET_BINDING_VS, c_buffer, c_gs_offset, sizeof(GeometryShaderConstants)); ++ }); + + // Copy the actual data in + std::memcpy(m_uniform_stream_buffer->GetCurrentHostPointer() + pixel_constants_offset, +@@ -340,8 +363,11 @@ void VertexManager::UploadUtilityUniform + Renderer::GetInstance()->ExecuteCommandBuffer(false); + } + +- StateTracker::GetInstance()->SetUtilityUniformBuffer( +- m_uniform_stream_buffer->GetBuffer(), m_uniform_stream_buffer->GetCurrentOffset(), data_size); ++ g_scheduler->Record([c_buffer = m_uniform_stream_buffer->GetBuffer(), ++ c_offset = m_uniform_stream_buffer->GetCurrentOffset(), ++ c_size = data_size](CommandBufferManager* command_buffer_mgr) { ++ command_buffer_mgr->GetStateTracker()->SetUtilityUniformBuffer(c_buffer, c_offset, c_size); ++ }); + std::memcpy(m_uniform_stream_buffer->GetCurrentHostPointer(), data, data_size); + m_uniform_stream_buffer->CommitMemory(data_size); + ADDSTAT(g_stats.this_frame.bytes_uniform_streamed, data_size); +@@ -370,7 +396,10 @@ bool VertexManager::UploadTexelBuffer(co + *out_offset = static_cast(m_texel_stream_buffer->GetCurrentOffset()) / elem_size; + m_texel_stream_buffer->CommitMemory(data_size); + ADDSTAT(g_stats.this_frame.bytes_uniform_streamed, data_size); +- StateTracker::GetInstance()->SetTexelBuffer(0, m_texel_buffer_views[format]); ++ g_scheduler->Record([c_texel_buffer_view = ++ m_texel_buffer_views[format]](CommandBufferManager* command_buffer_mgr) { ++ command_buffer_mgr->GetStateTracker()->SetTexelBuffer(0, c_texel_buffer_view); ++ }); + return true; + } + +@@ -407,8 +436,13 @@ bool VertexManager::UploadTexelBuffer(co + + m_texel_stream_buffer->CommitMemory(palette_byte_offset + palette_size); + ADDSTAT(g_stats.this_frame.bytes_uniform_streamed, palette_byte_offset + palette_size); +- StateTracker::GetInstance()->SetTexelBuffer(0, m_texel_buffer_views[format]); +- StateTracker::GetInstance()->SetTexelBuffer(1, m_texel_buffer_views[palette_format]); ++ ++ g_scheduler->Record([c_texel_buffer_view = m_texel_buffer_views[format], ++ c_palette_texel_buffer_view = m_texel_buffer_views[palette_format]]( ++ CommandBufferManager* command_buffer_mgr) { ++ command_buffer_mgr->GetStateTracker()->SetTexelBuffer(0, c_texel_buffer_view); ++ command_buffer_mgr->GetStateTracker()->SetTexelBuffer(1, c_palette_texel_buffer_view); ++ }); + return true; + } + } // namespace Vulkan +diff -rupN dolphin.orig/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp dolphin/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp +--- dolphin.orig/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp 2024-03-05 04:05:26.602983293 +0000 ++++ dolphin/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp 2024-03-05 04:06:08.240295843 +0000 +@@ -274,6 +274,13 @@ bool VulkanContext::SelectInstanceExtens + return false; + } + #endif ++#if defined(VK_USE_PLATFORM_WAYLAND_KHR) ++ if (wstype == WindowSystemType::Wayland && ++ !AddExtension(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME, true)) ++ { ++ return false; ++ } ++#endif + #if defined(VK_USE_PLATFORM_ANDROID_KHR) + if (wstype == WindowSystemType::Android && + !AddExtension(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME, true)) +diff -rupN dolphin.orig/Source/Core/VideoBackends/Vulkan/VulkanEntryPoints.inl dolphin/Source/Core/VideoBackends/Vulkan/VulkanEntryPoints.inl +--- dolphin.orig/Source/Core/VideoBackends/Vulkan/VulkanEntryPoints.inl 2024-03-05 04:05:26.602983293 +0000 ++++ dolphin/Source/Core/VideoBackends/Vulkan/VulkanEntryPoints.inl 2024-03-05 04:06:08.240295843 +0000 +@@ -49,6 +49,11 @@ VULKAN_INSTANCE_ENTRY_POINT(vkCreateXlib + VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceXlibPresentationSupportKHR, false) + #endif + ++#if defined(VK_USE_PLATFORM_WAYLAND_KHR) ++VULKAN_INSTANCE_ENTRY_POINT(vkCreateWaylandSurfaceKHR, false) ++VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceWaylandPresentationSupportKHR, false) ++#endif ++ + #if defined(VK_USE_PLATFORM_ANDROID_KHR) + VULKAN_INSTANCE_ENTRY_POINT(vkCreateAndroidSurfaceKHR, false) + #endif +diff -rupN dolphin.orig/Source/Core/VideoBackends/Vulkan/VulkanLoader.h dolphin/Source/Core/VideoBackends/Vulkan/VulkanLoader.h +--- dolphin.orig/Source/Core/VideoBackends/Vulkan/VulkanLoader.h 2024-03-05 04:05:26.602983293 +0000 ++++ dolphin/Source/Core/VideoBackends/Vulkan/VulkanLoader.h 2024-03-05 04:06:08.240295843 +0000 +@@ -13,6 +13,10 @@ + #define VK_USE_PLATFORM_XLIB_KHR + #endif + ++#if defined(HAVE_WAYLAND) ++#define VK_USE_PLATFORM_WAYLAND_KHR ++#endif ++ + #if defined(ANDROID) + #define VK_USE_PLATFORM_ANDROID_KHR + #endif +diff -rupN dolphin.orig/Source/Core/VideoCommon/FramebufferManager.cpp dolphin/Source/Core/VideoCommon/FramebufferManager.cpp +--- dolphin.orig/Source/Core/VideoCommon/FramebufferManager.cpp 2024-03-05 04:05:26.602983293 +0000 ++++ dolphin/Source/Core/VideoCommon/FramebufferManager.cpp 2024-03-05 04:06:08.240295843 +0000 +@@ -630,7 +630,7 @@ void FramebufferManager::DestroyReadback + + bool FramebufferManager::CreateReadbackFramebuffer() + { +- if (g_renderer->GetEFBScale() != 1) ++ if (g_renderer->IsUnscaled()) + { + const TextureConfig color_config(IsUsingTiledEFBCache() ? m_efb_cache_tile_size : EFB_WIDTH, + IsUsingTiledEFBCache() ? m_efb_cache_tile_size : EFB_HEIGHT, 1, +@@ -651,7 +651,7 @@ bool FramebufferManager::CreateReadbackF + (IsUsingTiledEFBCache() && !g_ActiveConfig.backend_info.bSupportsPartialDepthCopies) || + !AbstractTexture::IsCompatibleDepthAndColorFormats(m_efb_depth_texture->GetFormat(), + GetEFBDepthCopyFormat()) || +- g_renderer->GetEFBScale() != 1) ++ g_renderer->IsUnscaled()) + { + const TextureConfig depth_config(IsUsingTiledEFBCache() ? m_efb_cache_tile_size : EFB_WIDTH, + IsUsingTiledEFBCache() ? m_efb_cache_tile_size : EFB_HEIGHT, 1, +@@ -731,7 +731,7 @@ void FramebufferManager::PopulateEFBCach + const MathUtil::Rectangle native_rect = g_renderer->ConvertEFBRectangle(rect); + AbstractTexture* src_texture = + depth ? ResolveEFBDepthTexture(native_rect) : ResolveEFBColorTexture(native_rect); +- if (g_renderer->GetEFBScale() != 1 || force_intermediate_copy) ++ if (g_renderer->IsUnscaled() || force_intermediate_copy) + { + // Downsample from internal resolution to 1x. + // TODO: This won't produce correct results at IRs above 2x. More samples are required. +@@ -918,7 +918,7 @@ void FramebufferManager::CreatePokeVerti + // GPU will expand the point to a quad. + const float cs_x = (static_cast(x) + 0.5f) * cs_pixel_width - 1.0f; + const float cs_y = 1.0f - (static_cast(y) + 0.5f) * cs_pixel_height; +- const float point_size = static_cast(g_renderer->GetEFBScale()); ++ const float point_size = g_renderer->GetEFBScalef(); + destination_list->push_back({{cs_x, cs_y, z, point_size}, color}); + return; + } +diff -rupN dolphin.orig/Source/Core/VideoCommon/RenderBase.cpp dolphin/Source/Core/VideoCommon/RenderBase.cpp +--- dolphin.orig/Source/Core/VideoCommon/RenderBase.cpp 2024-03-05 04:05:26.602983293 +0000 ++++ dolphin/Source/Core/VideoCommon/RenderBase.cpp 2024-03-05 04:06:08.240295843 +0000 +@@ -364,19 +364,24 @@ void Renderer::RenderToXFB(u32 xfbAddr, + return; + } + +-unsigned int Renderer::GetEFBScale() const ++bool Renderer::IsUnscaled() const + { +- return m_efb_scale; ++ return m_efb_scale == 2; ++} ++ ++float Renderer::GetEFBScalef() const ++{ ++ return m_efb_scale / 2.0f; + } + + int Renderer::EFBToScaledX(int x) const + { +- return x * static_cast(m_efb_scale); ++ return x * static_cast(m_efb_scale) / 2; + } + + int Renderer::EFBToScaledY(int y) const + { +- return y * static_cast(m_efb_scale); ++ return y * static_cast(m_efb_scale) / 2; + } + + float Renderer::EFBToScaledXf(float x) const +@@ -391,7 +396,7 @@ float Renderer::EFBToScaledYf(float y) c + + std::tuple Renderer::CalculateTargetScale(int x, int y) const + { +- return std::make_tuple(x * static_cast(m_efb_scale), y * static_cast(m_efb_scale)); ++ return std::make_tuple(x * static_cast(m_efb_scale) / 2, y * static_cast(m_efb_scale) / 2); + } + + // return true if target size changed +@@ -711,16 +716,20 @@ bool Renderer::IsHeadless() const + return true; + } + +-void Renderer::ChangeSurface(void* new_surface_handle) ++void Renderer::ChangeSurface(void* new_surface_handle, int new_width, int new_height) + { + std::lock_guard lock(m_swap_mutex); + m_new_surface_handle = new_surface_handle; ++ m_new_surface_width = new_width; ++ m_new_surface_height = new_height; + m_surface_changed.Set(); + } + +-void Renderer::ResizeSurface() ++void Renderer::ResizeSurface(int new_width, int new_height) + { + std::lock_guard lock(m_swap_mutex); ++ m_new_surface_width = new_width; ++ m_new_surface_height = new_height; + m_surface_resized.Set(); + } + +diff -rupN dolphin.orig/Source/Core/VideoCommon/RenderBase.h dolphin/Source/Core/VideoCommon/RenderBase.h +--- dolphin.orig/Source/Core/VideoCommon/RenderBase.h 2024-03-05 04:05:26.602983293 +0000 ++++ dolphin/Source/Core/VideoCommon/RenderBase.h 2024-03-05 04:06:08.240295843 +0000 +@@ -193,7 +193,8 @@ public: + std::tuple, MathUtil::Rectangle> + ConvertStereoRectangle(const MathUtil::Rectangle& rc) const; + +- unsigned int GetEFBScale() const; ++ bool IsUnscaled() const; ++ float GetEFBScalef() const; + + // Use this to upscale native EFB coordinates to IDEAL internal resolution + int EFBToScaledX(int x) const; +@@ -246,8 +247,8 @@ public: + VideoCommon::PostProcessing* GetPostProcessor() const { return m_post_processor.get(); } + // Final surface changing + // This is called when the surface is resized (WX) or the window changes (Android). +- void ChangeSurface(void* new_surface_handle); +- void ResizeSurface(); ++ void ChangeSurface(void* new_surface_handle, int new_width, int new_height); ++ void ResizeSurface(int new_width, int new_height); + bool UseVertexDepthRange() const; + void DoState(PointerWrap& p); + +@@ -342,6 +343,8 @@ protected: + std::unique_ptr m_post_processor; + + void* m_new_surface_handle = nullptr; ++ int m_new_surface_width = 0; ++ int m_new_surface_height = 0; + Common::Flag m_surface_changed; + Common::Flag m_surface_resized; + std::mutex m_swap_mutex; +@@ -357,7 +360,8 @@ private: + std::tuple CalculateOutputDimensions(int width, int height) const; + + PixelFormat m_prev_efb_format = PixelFormat::INVALID_FMT; +- unsigned int m_efb_scale = 1; ++ // Scale in steps of 0.5x. Value of 2 is scale of 1 (unscaled). ++ unsigned int m_efb_scale = 2; + + // These will be set on the first call to SetWindowSize. + int m_last_window_request_width = 0; +diff -rupN dolphin.orig/Source/Core/VideoCommon/TextureCacheBase.cpp dolphin/Source/Core/VideoCommon/TextureCacheBase.cpp +--- dolphin.orig/Source/Core/VideoCommon/TextureCacheBase.cpp 2024-03-05 04:05:26.602983293 +0000 ++++ dolphin/Source/Core/VideoCommon/TextureCacheBase.cpp 2024-03-05 04:06:08.240295843 +0000 +@@ -1046,7 +1046,7 @@ static void SetSamplerState(u32 index, f + // that have arbitrary contents, eg. are used for fog effects where the + // distance they kick in at is important to preserve at any resolution. + // Correct this with the upscaling factor of custom textures. +- s32 lod_offset = std::log2(g_renderer->GetEFBScale() / custom_tex_scale) * 256.f; ++ s64 lod_offset = std::log2(g_renderer->GetEFBScalef() / custom_tex_scale) * (s64) 256.f; + state.tm0.lod_bias = std::clamp(state.tm0.lod_bias + lod_offset, -32768, 32767); + + // Anisotropic also pushes mips farther away so it cannot be used either +@@ -2221,7 +2221,7 @@ void TextureCacheBase::CopyRenderTargetT + // TODO: This only produces perfect downsampling for 2x IR, other resolutions will need more + // complex down filtering to average all pixels and produce the correct result. + const bool linear_filter = +- !is_depth_copy && (scaleByHalf || g_renderer->GetEFBScale() != 1 || y_scale > 1.0f); ++ !is_depth_copy && (scaleByHalf || g_renderer->IsUnscaled() || y_scale > 1.0f); + + TCacheEntry* entry = nullptr; + if (copy_to_vram) diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/wayland/001-padorder.patch b/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/wayland/001-padorder.patch new file mode 100644 index 0000000000..187a57efca --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/wayland/001-padorder.patch @@ -0,0 +1,111 @@ +diff --git a/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp b/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp +index 6df37b4..64ade4a 100644 +--- a/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp ++++ b/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp +@@ -392,6 +392,65 @@ void Init() + StartHotplugThread(); + } + ++struct joypad_udev_entry ++{ ++ const char *devnode; ++ struct udev_device *dev; ++}; ++ ++int isNumber(const char *s) { ++ int n; ++ ++ if(strlen(s) == 0) { ++ return 0; ++ } ++ ++ for(n=0; ndevnode, bb->devnode); ++} ++ + // Only call this when ControllerInterface::m_devices_population_mutex is locked + void PopulateDevices() + { +@@ -404,6 +463,10 @@ void PopulateDevices() + // We use udev to iterate over all /dev/input/event* devices. + // Note: the Linux kernel is currently limited to just 32 event devices. If + // this ever changes, hopefully udev will take care of this. ++ unsigned sorted_count = 0; ++ struct joypad_udev_entry sorted[64]; ++ const char* devnode; ++ int i; + + udev* const udev = udev_new(); + ASSERT_MSG(CONTROLLERINTERFACE, udev != nullptr, "Couldn't initialize libudev."); +@@ -422,11 +485,25 @@ void PopulateDevices() + + udev_device* dev = udev_device_new_from_syspath(udev, path); + +- if (const char* devnode = udev_device_get_devnode(dev)) +- AddDeviceNode(devnode); +- +- udev_device_unref(dev); ++ devnode = udev_device_get_devnode(dev); ++ if (devnode != NULL && sorted_count < 64) { ++ sorted[sorted_count].devnode = devnode; ++ sorted[sorted_count].dev = dev; ++ 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++) { ++ AddDeviceNode(sorted[i].devnode); ++ udev_device_unref(sorted[i].dev); ++ } ++ + udev_enumerate_unref(enumerate); + udev_unref(udev); + } diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/wayland/002-fix-bba.patch b/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/wayland/002-fix-bba.patch new file mode 100644 index 0000000000..b9fb92b1cb --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/wayland/002-fix-bba.patch @@ -0,0 +1,46 @@ +From beebe0a2000826de66c911344c7efca4872262ff Mon Sep 17 00:00:00 2001 +From: "Admiral H. Curtiss" +Date: Wed, 4 Oct 2023 16:13:16 +0200 +Subject: [PATCH] Core/BBA/BuiltIn: Replace IP_PROTOCOL with IPV4_ETHERTYPE to + avoid conflict with Linux headers. + +--- + Source/Core/Core/HW/EXI/BBA/BuiltIn.cpp | 3 ++- + Source/Core/Core/HW/EXI/BBA/BuiltIn.h | 3 --- + 2 files changed, 2 insertions(+), 4 deletions(-) + +diff --git a/Source/Core/Core/HW/EXI/BBA/BuiltIn.cpp b/Source/Core/Core/HW/EXI/BBA/BuiltIn.cpp +index 6e5c3eac9749..4782a0a8b0a7 100644 +--- a/Source/Core/Core/HW/EXI/BBA/BuiltIn.cpp ++++ b/Source/Core/Core/HW/EXI/BBA/BuiltIn.cpp +@@ -13,6 +13,7 @@ + #include "Common/BitUtils.h" + #include "Common/Logging/Log.h" + #include "Common/MsgHandler.h" ++#include "Common/Network.h" + #include "Common/ScopeGuard.h" + #include "Core/HW/EXI/EXI_Device.h" + #include "Core/HW/EXI/EXI_DeviceEthernet.h" +@@ -746,7 +747,7 @@ void CEXIETHERNET::BuiltInBBAInterface::ReadThreadHandler(CEXIETHERNET::BuiltInB + u8* buffer = reinterpret_cast(self->m_eth_ref->mRecvBuffer.get()); + Common::PacketView packet(buffer, datasize); + const auto packet_type = packet.GetEtherType(); +- if (packet_type.has_value() && packet_type == IP_PROTOCOL) ++ if (packet_type.has_value() && packet_type == Common::IPV4_ETHERTYPE) + { + SetIPIdentification(buffer, datasize, ++self->m_ip_frame_id); + } +diff --git a/Source/Core/Core/HW/EXI/BBA/BuiltIn.h b/Source/Core/Core/HW/EXI/BBA/BuiltIn.h +index 4478f4de48da..afcf39d2931b 100644 +--- a/Source/Core/Core/HW/EXI/BBA/BuiltIn.h ++++ b/Source/Core/Core/HW/EXI/BBA/BuiltIn.h +@@ -20,9 +20,6 @@ constexpr u16 TCP_FLAG_PSH = 0x8; + constexpr u16 TCP_FLAG_FIN = 0x1; + constexpr u16 TCP_FLAG_RST = 0x4; + +-constexpr u16 IP_PROTOCOL = 0x800; +-constexpr u16 ARP_PROTOCOL = 0x806; +- + constexpr u8 MAX_TCP_BUFFER = 4; + constexpr u16 MAX_UDP_LENGTH = 1500; + constexpr u16 MAX_TCP_LENGTH = 440; diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/wayland/004-git.patch b/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/wayland/004-git.patch new file mode 100644 index 0000000000..cbc4b582d1 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/wayland/004-git.patch @@ -0,0 +1,13 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index eb0f83f..9d41166 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -128,7 +128,7 @@ endif() + include(CCache) + + # for revision info +-find_package(Git) ++#find_package(Git) + if(GIT_FOUND) + # make sure version information gets re-run when the current Git HEAD changes + execute_process(WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} rev-parse --git-path HEAD diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/wayland/005-hide-osd-msg.patch b/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/wayland/005-hide-osd-msg.patch new file mode 100644 index 0000000000..5005309837 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/wayland/005-hide-osd-msg.patch @@ -0,0 +1,13 @@ +--- a/Source/Core/VideoBackends/OGL/OGLRender.cpp 2020-12-31 00:27:53.998709857 +0100 ++++ b/Source/Core/VideoBackends/OGL/OGLRender.cpp 2020-12-31 00:28:40.414557344 +0100 +@@ -736,10 +736,6 @@ + g_Config.VerifyValidity(); + UpdateActiveConfig(); + +- OSD::AddMessage(fmt::format("Video Info: {}, {}, {}", g_ogl_config.gl_vendor, +- g_ogl_config.gl_renderer, g_ogl_config.gl_version), +- 5000); +- + if (!g_ogl_config.bSupportsGLBufferStorage && !g_ogl_config.bSupportsGLPinnedMemory) + { + OSD::AddMessage(fmt::format("Your OpenGL driver does not support {}_buffer_storage.", diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/wayland/008-bios-dir.patch b/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/wayland/008-bios-dir.patch new file mode 100644 index 0000000000..d9be1c4668 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/patches/wayland/008-bios-dir.patch @@ -0,0 +1,35 @@ +diff --git a/Source/Core/Core/Boot/Boot.cpp b/Source/Core/Core/Boot/Boot.cpp +index b21d15478..5b62db919 100644 +--- a/Source/Core/Core/Boot/Boot.cpp ++++ b/Source/Core/Core/Boot/Boot.cpp +@@ -423,7 +423,7 @@ bool CBoot::Load_BS2(Core::System& system, const std::string& boot_rom_filename) + known_ipl = true; + break; + default: +- PanicAlertFmtT("The IPL file is not a known good dump. (CRC32: {0:x})", ipl_hash); ++ known_ipl = true; + break; + } + +@@ -598,7 +598,7 @@ bool CBoot::BootUp(Core::System& system, std::unique_ptr boot) + if (!File::Exists(ipl.path)) + { + if (ipl.disc) +- PanicAlertFmtT("Cannot start the game, because the GC IPL could not be found."); ++ PanicAlertFmtT("Gamecube bios not found, please add your IPL.bin to /storage/roms/bios/GC/(USA/JAP/EUR)/."); + else + PanicAlertFmtT("Cannot find the GC IPL."); + return false; +diff --git a/Source/Core/Core/Config/MainSettings.cpp b/Source/Core/Core/Config/MainSettings.cpp +index 0442347fdd..af148e79f9 100644 +--- a/Source/Core/Core/Config/MainSettings.cpp ++++ b/Source/Core/Core/Config/MainSettings.cpp +@@ -616,7 +616,7 @@ const char* GetDirectoryForRegion(DiscIO::Region region, RegionDirectoryStyle st + std::string GetBootROMPath(const std::string& region_directory) + { + const std::string path = +- File::GetUserPath(D_GCUSER_IDX) + DIR_SEP + region_directory + DIR_SEP GC_IPL; ++ std::string("/storage/roms/bios/GC/") + DIR_SEP + region_directory + DIR_SEP + GC_IPL; + if (!File::Exists(path)) + return File::GetSysDirectory() + GC_SYS_DIR + DIR_SEP + region_directory + DIR_SEP GC_IPL; + return path; diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/scripts/cheevos_dolphin.sh b/projects/ArchR/packages/emulators/standalone/dolphin-sa/scripts/cheevos_dolphin.sh new file mode 100644 index 0000000000..5a99e38251 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/scripts/cheevos_dolphin.sh @@ -0,0 +1,66 @@ +#! /bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile + +LOG_FILE="/var/log/cheevos.log" + +# Extract username, password, token, if enabled, and hardcore mode from system.cfg +username=$(get_setting "global.retroachievements.username") +password=$(get_setting "global.retroachievements.password") +token=$(get_setting "global.retroachievements.token") +enabled=$(get_setting "global.retroachievements") +hardcore=$(get_setting "global.retroachievements.hardcore") +encore=$(get_setting "global.retroachievements.encore") +unofficial=$(get_setting "global.retroachievements.testunofficial") + +# Check if RetroAchievements are enabled in Emulation Station +if [ "${enabled}" = 1 ]; then + enabled="True" +else + echo "RetroAchievements are not enabled, please turn them on in Emulation Station." > ${LOG_FILE} + enabled="False" + exit 1 +fi + +# Check if api token is present in system.cfg +if [ -z "${token}" ]; then + echo "RetroAchievements token is empty, please log in with your RetroAchievements credentials in Emulation Station." > ${LOG_FILE} + exit 1 +fi + +# Set hardcore mode +if [ "${hardcore}" = 1 ]; then + hardcore="True" +else + hardcore="False" +fi + +# Set encore mode +if [ "${encore}" = 1 ]; then + encore="True" +else + encore="False" +fi + +# Set unofficial mode +if [ "${unofficial}" = 1 ]; then + unofficial="True" +else + unofficial="False" +fi + +cat </storage/.config/dolphin-emu/RetroAchievements.ini +[Achievements] +DiscordPresenceEnabled = False +Enabled = ${enabled} +EncoreEnabled = ${encore} +HardcoreEnabled = ${hardcore} +ProgressEnabled = False +SpectatorEnabled = False +UnofficialEnabled = ${unofficial} +Username = ${username} +ApiToken = ${token} +EOF diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/scripts/start_dolphin_gc.sh b/projects/ArchR/packages/emulators/standalone/dolphin-sa/scripts/start_dolphin_gc.sh new file mode 100644 index 0000000000..3a44c6d0bd --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/scripts/start_dolphin_gc.sh @@ -0,0 +1,430 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile + +# Detect version of Dolphin +DOLPHIN_CORE=$(echo "${3}"| sed "s#^/.*/##") +if [ "${DOLPHIN_CORE}" = 'dolphin-qt-gc' ]; then + DOLPHIN_CORE="dolphin-emu" +else + DOLPHIN_CORE="dolphin-emu-nogui" +fi + +set_kill set "-9 ${DOLPHIN_CORE}" + +# Load gptokeyb support files +control-gen_init.sh +source /storage/.config/gptokeyb/control.ini +get_controls + +# Conf files vars +CONF_DIR="/storage/.config/dolphin-emu" +DOLPHIN_INI="Dolphin.ini" +GFX_INI="GFX.ini" +CONTROLLER_INI="GCPadNew.ini" + +# Check if dolphin-emu exists in .config +if [ ! -d "${CONF_DIR}" ]; then + cp -r "/usr/config/dolphin-emu" "/storage/.config/" +fi + +# Check if Hotkeys.ini exists +if [ "${DOLPHIN_CORE}" = 'dolphin-emu' ]; then + if [ ! -f "${CONF_DIR}/Hotkeys.ini" ]; then + cp -r "/usr/config/dolphin-emu/Hotkeys.ini" "${CONF_DIR}/" + fi +fi + +# Check if GC controller dir exists in .config/dolphin-emu/GamecubeControllerProfiles +if [ ! -d "${CONF_DIR}/GamecubeControllerProfiles" ]; then + cp -r "/usr/config/dolphin-emu/GamecubeControllerProfiles" "${CONF_DIR}/" +fi + +# Check if GC custom east profile exists in .config/dolphin-emu/GamecubeControllerProfiles +if [ ! -f "${CONF_DIR}/GamecubeControllerProfiles/GCPadNew.ini.east" ]; then + cp -r "/usr/config/dolphin-emu/GamecubeControllerProfiles/GCPadNew.ini.east" "${CONF_DIR}/GamecubeControllerProfiles/GCPadNew.ini.east" +fi + +# Check if GC custom controller profile exists in .config/dolphin-emu/GamecubeControllerProfiles +if [ ! -f "${CONF_DIR}/GamecubeControllerProfiles/GCPadNew.ini.custom" ]; then + cp -r "/usr/config/dolphin-emu/GamecubeControllerProfiles/GCPadNew.ini.south" "${CONF_DIR}/GamecubeControllerProfiles/GCPadNew.ini.custom" +fi + +# Link Save States to /roms/savestates/gamecube +if [ ! -d "/storage/roms/savestates/gamecube/" ]; then + mkdir -p "/storage/roms/savestates/gamecube/" +fi + +rm -rf ${CONF_DIR}/StateSaves +ln -sf /storage/roms/savestates/gamecube ${CONF_DIR}/StateSaves + +# Copy bios, memory cards and other system stuff to roms +if [ ! -d "/storage/roms/bios/GC/" ]; then + mkdir -p /storage/roms/bios/GC/{USA,JAP,EUR} + cp -r ${CONF_DIR}/GC /storage/roms/bios/ +fi + +# Create Triforce Bios folder if does not exist +if [ ! -d "/storage/roms/bios/GC/Triforce" ]; then + mkdir -p /storage/roms/bios/GC/Triforce + cp -r ${CONF_DIR}/GC/Triforce /storage/roms/bios/GC/ +fi + +# Make sure all Triforce Gecko codes are copied to GameSettings +for f in /usr/config/dolphin-emu/triforce_gecko_codes/*; do + [ -e "/storage/.config/dolphin-emu/GameSettings/$(basename "$f")" ] || cp -fH "$f" "/storage/.config/dolphin-emu/GameSettings/" +done +rm -rf "/storage/.config/dolphin-emu/triforce_gecko_codes" + +# Link bios and memory cards to roms +for REGION in EUR JAP USA +do + # Link bios + rm -rf "${CONF_DIR}/GC/${REGION}" + ln -sf "/storage/roms/bios/GC/${REGION}" "${CONF_DIR}/GC/${REGION}" + + # Link memory cards, copying to roms/bios first as needed + for SLOT in A B + do + MEM_CARD_FILE="MemoryCard${SLOT}.${REGION}.raw" + CONFIG_MEM_CARD="${CONF_DIR}/GC/${MEM_CARD_FILE}" + ROMS_BIOS_MEM_CARD="/storage/roms/bios/GC/${MEM_CARD_FILE}" + + if [ -f "${ROMS_BIOS_MEM_CARD}" ]; then + # Exists in roms/bios, remove from .config and link + rm -f "${CONFIG_MEM_CARD}" + ln -sf "${ROMS_BIOS_MEM_CARD}" "${CONFIG_MEM_CARD}" + elif [ -f "${CONFIG_MEM_CARD}" ]; then + # Only exists in .config, move to roms/bios and link + mv -f "${CONFIG_MEM_CARD}" "${ROMS_BIOS_MEM_CARD}" + ln -sf "${ROMS_BIOS_MEM_CARD}" "${CONFIG_MEM_CARD}" + fi + done +done + +# Emulation Station Features +GAME=$(echo "${1}"| sed "s#^/.*/##") +PLATFORM=$(echo "${2}"| sed "s#^/.*/##") +AA=$(get_setting anti_aliasing "${PLATFORM}" "${GAME}") +ASPECT=$(get_setting aspect_ratio "${PLATFORM}" "${GAME}") +AUDIOBE=$(get_setting audio_backend "${PLATFORM}" "${GAME}") +ASWAPDISCS=$(get_setting auto_swap_discs "${PLATFORM}" "${GAME}") +CLOCK=$(get_setting clock_speed "${PLATFORM}" "${GAME}") +ENBCHEATS=$(get_setting enable_cheats "${PLATFORM}" "${GAME}") +GRENDERER=$(get_setting graphics_backend "${PLATFORM}" "${GAME}") +IRES=$(get_setting internal_resolution "${PLATFORM}" "${GAME}") +FPS=$(get_setting show_fps "${PLATFORM}" "${GAME}") +CON=$(get_setting gamecube_controller_profile "${PLATFORM}" "${GAME}") +HKEY=$(get_setting hotkey_enable_button "${PLATFORM}" "${GAME}") +SAVETYPE=$(get_setting save_type "${PLATFORM}" "${GAME}") +SAVEREG=$(get_setting save_gci_region "${PLATFORM}" "${GAME}") +SHADERM=$(get_setting shader_mode "${PLATFORM}" "${GAME}") +SHADERP=$(get_setting shader_precompile "${PLATFORM}" "${GAME}") +VSYNC=$(get_setting vsync "${PLATFORM}" "${GAME}") +SKIPBIOS=$(get_setting use_bios "${PLATFORM}" "${GAME}") +EFBACCESS=$(get_setting skip_efb_cpu_access "${PLATFORM}" "${GAME}") +EFBTEXTURE=$(get_setting store_efb_to_texture_only "${PLATFORM}" "${GAME}") +XFBTEXTURE=$(get_setting store_xfb_to_texture_only "${PLATFORM}" "${GAME}") +TEXTURE_CACHE_ACCURACY=$(get_setting texture_cache_accuracy "${PLATFORM}" "${GAME}") +RUMBLE=$(get_setting rumble "${PLATFORM}" "${GAME}") +WHACK=$(get_setting widescreen_hack "${PLATFORM}" "${GAME}") +WPC=$(get_setting write_protect_configs "${PLATFORM}" "${GAME}") + +# Grab clean config files during boot, unless disabled in emulationstation +if [ "$WPC" != "false" ]; then + cp -r /usr/config/dolphin-emu/GFX.ini ${CONF_DIR}/${GFX_INI} + cp -r /usr/config/dolphin-emu/Dolphin.ini ${CONF_DIR}/${DOLPHIN_INI} +fi + +# Set the cores to use +CORES=$(get_setting "cores" "${PLATFORM}" "${GAME}") +if [ "${CORES}" = "little" ] +then + EMUPERF="${SLOW_CORES}" +elif [ "${CORES}" = "big" ] +then + EMUPERF="${FAST_CORES}" +else + ### All.. + unset EMUPERF +fi + +### Emulation Station features: + # Anti-Aliasing + if [ "$AA" = "2m" ]; then + sed -i '/MSAA/c\MSAA = 2' ${CONF_DIR}/${GFX_INI} + sed -i '/SSAA/c\SSAA = False' ${CONF_DIR}/${GFX_INI} + elif [ "$AA" = "2s" ]; then + sed -i '/MSAA/c\MSAA = 2' ${CONF_DIR}/${GFX_INI} + sed -i '/SSAA/c\SSAA = True' ${CONF_DIR}/${GFX_INI} + elif [ "$AA" = "4m" ]; then + sed -i '/MSAA/c\MSAA = 4' ${CONF_DIR}/${GFX_INI} + sed -i '/SSAA/c\SSAA = False' ${CONF_DIR}/${GFX_INI} + elif [ "$AA" = "4s" ]; then + sed -i '/MSAA/c\MSAA = 4' ${CONF_DIR}/${GFX_INI} + sed -i '/SSAA/c\SSAA = True' ${CONF_DIR}/${GFX_INI} + elif [ "$AA" = "8m" ]; then + sed -i '/MSAA/c\MSAA = 8' ${CONF_DIR}/${GFX_INI} + sed -i '/SSAA/c\SSAA = False' ${CONF_DIR}/${GFX_INI} + elif [ "$AA" = "8s" ]; then + sed -i '/MSAA/c\MSAA = 8' ${CONF_DIR}/${GFX_INI} + sed -i '/SSAA/c\SSAA = True' ${CONF_DIR}/${GFX_INI} + else + sed -i '/MSAA/c\MSAA = 0' ${CONF_DIR}/${GFX_INI} + sed -i '/SSAA/c\SSAA = False' ${CONF_DIR}/${GFX_INI} + fi + + # Aspect Ratio + if [ "$ASPECT" = "1" ]; then + sed -i '/AspectRatio/c\AspectRatio = 1' ${CONF_DIR}/${GFX_INI} + elif [ "$ASPECT" = "2" ]; then + sed -i '/AspectRatio/c\AspectRatio = 2' ${CONF_DIR}/${GFX_INI} + elif [ "$ASPECT" = "3" ]; then + sed -i '/AspectRatio/c\AspectRatio = 3' ${CONF_DIR}/${GFX_INI} + else + sed -i '/AspectRatio/c\AspectRatio = 0' ${CONF_DIR}/${GFX_INI} + fi + + # Audio Backend + if [ "$AUDIOBE" = "lle" ]; then + AUDIO_BACKEND="LLE" + else + AUDIO_BACKEND="HLE" + fi + + # Auto Swap Discs + if [ "$ASWAPDISCS" = "0" ]; then + sed -i '/AutoDiscChange/c\AutoDiscChange = False' ${CONF_DIR}/${DOLPHIN_INI} + else + sed -i '/AutoDiscChange/c\AutoDiscChange = True' ${CONF_DIR}/${DOLPHIN_INI} + fi + + # Clock Speed + if [ "$CLOCK" = "050" ]; then + sed -i '/^Overclock =/c\Overclock = 0.5' ${CONF_DIR}/${DOLPHIN_INI} + sed -i '/^OverclockEnable =/c\OverclockEnable = True' ${CONF_DIR}/${DOLPHIN_INI} + elif [ "$CLOCK" = "075" ]; then + sed -i '/^Overclock =/c\Overclock = 0.75' ${CONF_DIR}/${DOLPHIN_INI} + sed -i '/^OverclockEnable =/c\OverclockEnable = True' ${CONF_DIR}/${DOLPHIN_INI} + elif [ "$CLOCK" = "100" ]; then + sed -i '/^Overclock =/c\Overclock = 1.0' ${CONF_DIR}/${DOLPHIN_INI} + sed -i '/^OverclockEnable =/c\OverclockEnable = False' ${CONF_DIR}/${DOLPHIN_INI} + elif [ "$CLOCK" = "125" ]; then + sed -i '/^Overclock =/c\Overclock = 1.25' ${CONF_DIR}/${DOLPHIN_INI} + sed -i '/^OverclockEnable =/c\OverclockEnable = True' ${CONF_DIR}/${DOLPHIN_INI} + elif [ "$CLOCK" = "150" ]; then + sed -i '/^Overclock =/c\Overclock = 1.5' ${CONF_DIR}/${DOLPHIN_INI} + sed -i '/^OverclockEnable =/c\OverclockEnable = True' ${CONF_DIR}/${DOLPHIN_INI} + elif [ "$CLOCK" = "200" ]; then + sed -i '/^Overclock =/c\Overclock = 2.0' ${CONF_DIR}/${DOLPHIN_INI} + sed -i '/^OverclockEnable =/c\OverclockEnable = True' ${CONF_DIR}/${DOLPHIN_INI} + elif [ "$CLOCK" = "300" ]; then + sed -i '/^Overclock =/c\Overclock = 3.0' ${CONF_DIR}/${DOLPHIN_INI} + sed -i '/^OverclockEnable =/c\OverclockEnable = True' ${CONF_DIR}/${DOLPHIN_INI} + elif [ "$CLOCK" = "400" ]; then + sed -i '/^Overclock =/c\Overclock = 4.0' ${CONF_DIR}/${DOLPHIN_INI} + sed -i '/^OverclockEnable =/c\OverclockEnable = True' ${CONF_DIR}/${DOLPHIN_INI} + else + sed -i '/^OverclockEnable =/c\OverclockEnable = False' ${CONF_DIR}/${DOLPHIN_INI} + fi + + # Enable Cheats + if [ "$ENBCHEATS" = "1" ]; then + sed -i '/EnableCheats/c\EnableCheats = True' ${CONF_DIR}/${DOLPHIN_INI} + else + sed -i '/EnableCheats/c\EnableCheats = False' ${CONF_DIR}/${DOLPHIN_INI} + fi + + # Graphics Backend + if [ "$GRENDERER" = "vulkan" ]; then + sed -i '/GFXBackend/c\GFXBackend = Vulkan' ${CONF_DIR}/${DOLPHIN_INI} + elif [ "$GRENDERER" = "opengl" ]; then + sed -i '/GFXBackend/c\GFXBackend = OGL' ${CONF_DIR}/${DOLPHIN_INI} + else + sed -i '/GFXBackend/c\GFXBackend = @GRENDERER@' ${CONF_DIR}/${DOLPHIN_INI} + fi + + # Internal Resolution + if [ "$IRES" = "1" ]; then + sed -i '/InternalResolution/c\InternalResolution = 1' ${CONF_DIR}/${GFX_INI} + elif [ "$IRES" = "3" ]; then + sed -i '/InternalResolution/c\InternalResolution = 3' ${CONF_DIR}/${GFX_INI} + elif [ "$IRES" = "4" ]; then + sed -i '/InternalResolution/c\InternalResolution = 4' ${CONF_DIR}/${GFX_INI} + elif [ "$IRES" = "6" ]; then + sed -i '/InternalResolution/c\InternalResolution = 6' ${CONF_DIR}/${GFX_INI} + else + sed -i '/InternalResolution/c\InternalResolution = 2' ${CONF_DIR}/${GFX_INI} + fi + + # Save Type + if [ "$SAVETYPE" = "8" ]; then + sed -i '/SlotA/c\SlotA = 8' ${CONF_DIR}/${DOLPHIN_INI} + else + sed -i '/SlotA/c\SlotA = 1' ${CONF_DIR}/${DOLPHIN_INI} + fi + + # Save Reg + if [ "$SAVEREG" = "eur" ]; then + sed -i '/GCIFolderAPath/c\GCIFolderAPath = \/storage\/roms\/bios\/GC\/EUR' ${CONF_DIR}/${DOLPHIN_INI} + elif [ "$SAVEREG" = "jap" ]; then + sed -i '/GCIFolderAPath/c\GCIFolderAPath = \/storage\/roms\/bios\/GC\/JAP' ${CONF_DIR}/${DOLPHIN_INI} + else + sed -i '/GCIFolderAPath/c\GCIFolderAPath = \/storage\/roms\/bios\/GC\/USA' ${CONF_DIR}/${DOLPHIN_INI} + fi + + # Shader Mode + if [ "$SHADERM" = "0" ]; then + sed -i '/ShaderCompilationMode =/c\ShaderCompilationMode = 0' ${CONF_DIR}/${GFX_INI} + elif [ "$SHADERM" = "1" ]; then + sed -i '/ShaderCompilationMode =/c\ShaderCompilationMode = 1' ${CONF_DIR}/${GFX_INI} + elif [ "$SHADERM" = "2" ]; then + sed -i '/ShaderCompilationMode =/c\ShaderCompilationMode = 2' ${CONF_DIR}/${GFX_INI} + elif [ "$SHADERM" = "3" ]; then + sed -i '/ShaderCompilationMode =/c\ShaderCompilationMode = 3' ${CONF_DIR}/${GFX_INI} + fi + + #Shader Precompile + if [ "$SHADERP" = "false" ]; then + sed -i '/WaitForShadersBeforeStarting =/c\WaitForShadersBeforeStarting = False' ${CONF_DIR}/${GFX_INI} + elif [ "$SHADERP" = "true" ]; then + sed -i '/WaitForShadersBeforeStarting =/c\WaitForShadersBeforeStarting = True' ${CONF_DIR}/${GFX_INI} + fi + + # Show FPS + if [ "$FPS" = "true" ]; then + sed -i '/ShowFPS/c\ShowFPS = True' ${CONF_DIR}/${GFX_INI} + else + sed -i '/ShowFPS/c\ShowFPS = False' ${CONF_DIR}/${GFX_INI} + fi + + # Skip Bios + if [ "$SKIPBIOS" = "false" ]; then + sed -i '/SkipIPL/c\SkipIPL = False' ${CONF_DIR}/${DOLPHIN_INI} + else + sed -i '/SkipIPL/c\SkipIPL = True' ${CONF_DIR}/${DOLPHIN_INI} + fi + + # Skip EFB CPU Access + if [ "$EFBACCESS" = "false" ]; then + sed -i '/EFBAccessEnable =/c\EFBAccessEnable = False' ${CONF_DIR}/${GFX_INI} + else + sed -i '/EFBAccessEnable =/c\EFBAccessEnable = True' ${CONF_DIR}/${GFX_INI} + fi + + # Store EFB to texture only + if [ "$EFBTEXTURE" = "false" ]; then + sed -i '/EFBToTextureEnable =/c\EFBToTextureEnable = False' ${CONF_DIR}/${GFX_INI} + else + sed -i '/EFBToTextureEnable =/c\EFBToTextureEnable = True' ${CONF_DIR}/${GFX_INI} + fi + + # Store XFB to texture only + if [ "$XFBTEXTURE" = "false" ]; then + sed -i '/XFBToTextureEnable =/c\XFBToTextureEnable = False' ${CONF_DIR}/${GFX_INI} + else + sed -i '/XFBToTextureEnable =/c\XFBToTextureEnable = True' ${CONF_DIR}/${GFX_INI} + fi + + # Texture cache accuracy + if [ "$TEXTURE_CACHE_ACCURACY" = "0" ]; then + sed -i '/SafeTextureCacheColorSamples =/c\SafeTextureCacheColorSamples = 0' ${CONF_DIR}/${GFX_INI} + elif [ "$TEXTURE_CACHE_ACCURACY" = "512" ]; then + sed -i '/SafeTextureCacheColorSamples =/c\SafeTextureCacheColorSamples = 512' ${CONF_DIR}/${GFX_INI} + else + # Default to 128 = fast + sed -i '/SafeTextureCacheColorSamples =/c\SafeTextureCacheColorSamples = 128' ${CONF_DIR}/${GFX_INI} + fi + + # Widescreen Hack + if [ "$WHACK" = "true" ]; then + sed -i '/wideScreenHack =/c\wideScreenHack = True' ${CONF_DIR}/${GFX_INI} + else + sed -i '/wideScreenHack =/c\wideScreenHack = False' ${CONF_DIR}/${GFX_INI} + fi + + # GC Controller Profile + if [ "$CON" = "east" ]; then + cp -r ${CONF_DIR}/GamecubeControllerProfiles/GCPadNew.ini.east ${CONF_DIR}/${CONTROLLER_INI} + elif [ "$CON" = "custom" ]; then + cp -r ${CONF_DIR}/GamecubeControllerProfiles/GCPadNew.ini.custom ${CONF_DIR}/${CONTROLLER_INI} + else + cp -r ${CONF_DIR}/GamecubeControllerProfiles/GCPadNew.ini.south ${CONF_DIR}/${CONTROLLER_INI} + fi + + # GC Controller Rumble + if [ "$RUMBLE" = "false" ]; then + sed -i '/^Rumble/d' ${CONF_DIR}/${CONTROLLER_INI} + fi + + # GC Controller Hotkey Enable + if [ "$HKEY" = "mode" ]; then + sed -i '/^Buttons\/Hotkey =/c\Buttons\/Hotkey = Button 8' ${CONF_DIR}/${CONTROLLER_INI} + else + sed -i '/^Buttons\/Hotkey =/c\Buttons\/Hotkey = Button 6' ${CONF_DIR}/${CONTROLLER_INI} + fi + + # Vsync + if [ "$VSYNC" = "1" ]; then + sed -i '/VSync =/c\VSync = True' ${CONF_DIR}/${GFX_INI} + else + sed -i '/VSync =/c\VSync = False' ${CONF_DIR}/${GFX_INI} + fi + +# Link .config/dolphin-emu to .local +rm -rf /storage/.local/share/dolphin-emu +ln -sf /storage/.config/dolphin-emu /storage/.local/share/dolphin-emu + +@EXPORTS@ + +# Retroachievements + /usr/bin/cheevos_dolphin.sh + +# Set video and audio backend + CMD="${CMD} -v $GRENDERER" + +if [ ${DOLPHIN_CORE} = "dolphin-emu" ]; then + CMD="-b -a ${AUDIO_BACKEND}" +else + CMD="-p @DOLPHIN_BACKEND@ -a ${AUDIO_BACKEND}" +fi + +# Debugging info: + echo "GAME set to: ${GAME}" + echo "PLATFORM set to: ${PLATFORM}" + echo "CPU CORES set to: ${EMUPERF}" + echo "AA set to: ${AA}" + echo "ASPECT set to: ${ASPECT}" + echo "AUDIOBE set to: ${AUDIOBE}" + echo "ASWAPDISCS set to: ${ASWAPDISCS}" + echo "CLOCK set to: ${CLOCK}" + echo "DOLPHIN_BACKEND set to: ${DOLPHIN_BACKEND}" + echo "ENBCHEATS set to: ${ENBCHEATS}" + echo "GRENDERER set to: ${GRENDERER}" + echo "IRES set to: ${IRES}" + echo "FPS set to: ${FPS}" + echo "CON set to: ${CON}" + echo "HKEY set to: ${HKEY}" + echo "SAVETYPE set to: ${SAVETYPE}" + echo "SAVEREG set to: ${SAVEREG}" + echo "SHADERM set to: ${SHADERM}" + echo "SHADERP set to: ${SHADERP}" + echo "VSYNC set to: ${VSYNC}" + echo "SKIPBIOS set to: ${SKIPBIOS}" + echo "EFBACCESS set to: ${EFBACCESS}" + echo "EFBTEXTURE set to: ${EFBTEXTURE}" + echo "XFBTEXTURE set to: ${XFBTEXTURE}" + echo "TEXTURE_CACHE_ACCURACY set to: ${TEXTURE_CACHE_ACCURACY}" + echo "RUMBLE set to: ${RUMBLE}" + echo "WHACK set to: ${WHACK}" + echo "WPC set to: ${WPC}" + echo "Launching /usr/bin/${DOLPHIN_CORE} ${CMD} -e ${1}" + +# Run Dolphin emulator + ${GPTOKEYB} ${DOLPHIN_CORE} xbox360 & + ${EMUPERF} /usr/bin/${DOLPHIN_CORE} ${CMD} -e "${1}" + _gptokeyb_pid="$(pidof gptokeyb 2>/dev/null)" + [ -n "${_gptokeyb_pid}" ] && kill -9 ${_gptokeyb_pid} diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/scripts/start_dolphin_wii.sh b/projects/ArchR/packages/emulators/standalone/dolphin-sa/scripts/start_dolphin_wii.sh new file mode 100755 index 0000000000..4be8e71b91 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/scripts/start_dolphin_wii.sh @@ -0,0 +1,400 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile + +# Detect version of Dolphin +DOLPHIN_CORE=$(echo "${3}"| sed "s#^/.*/##") +if [ "${DOLPHIN_CORE}" = 'dolphin-qt-wii' ]; then + DOLPHIN_CORE="dolphin-emu" +else + DOLPHIN_CORE="dolphin-emu-nogui" +fi + +set_kill set "-9 ${DOLPHIN_CORE}" + +# Load gptokeyb support files +control-gen_init.sh +source /storage/.config/gptokeyb/control.ini +get_controls + +# Conf files vars +CONF_DIR="/storage/.config/dolphin-emu" +DOLPHIN_INI="Dolphin.ini" +GFX_INI="GFX.ini" +GC_CONTROLLER_INI="GCPadNew.ini" + +# Check if dolphin-emu exists in .config +if [ ! -d "${CONF_DIR}" ]; then + cp -r "/usr/config/dolphin-emu" "/storage/.config/" +fi + +# Check if Hotkeys.ini exists +if [ "${DOLPHIN_CORE}" = 'dolphin-emu' ]; then + if [ ! -f "${CONF_DIR}/Hotkeys.ini" ]; then + cp -r "/usr/config/dolphin-emu/Hotkeys.ini" "${CONF_DIR}/" + fi +fi + +# Check if GC controller dir exists in .config/dolphin-emu/GamecubeControllerProfiles +if [ ! -d "${CONF_DIR}/GamecubeControllerProfiles" ]; then + cp -r "/usr/config/dolphin-emu/GamecubeControllerProfiles" "${CONF_DIR}/" +fi + +# Check if Wii controller dir exists in .config/dolphin-emu/WiiControllerProfiles +if [ ! -d "${CONF_DIR}/WiiControllerProfiles" ]; then + cp -r "/usr/config/dolphin-emu/WiiControllerProfiles" "${CONF_DIR}/dolphin-emu/" +fi + +# Check if Wii custom controller profile exists in .config/dolphin-emu +if [ ! -f "${CONF_DIR}/WiiControllerProfiles/custom.ini" ]; then + cp -r "${CONF_DIR}/WiiControllerProfiles/vremote.ini" "${CONF_DIR}/WiiControllerProfiles/custom.ini" +fi + +# Gamecube controller profile needed for hotkeys to work on SA +if [ "${DOLPHIN_CORE}" = 'dolphin-emu-nogui' ]; then + cp -r "/storage/.config/dolphin-emu/GamecubeControllerProfiles/GCPadNew.ini.south" "/storage/.config/dolphin-emu/GCPadNew.ini" +else + rm -r "/storage/.config/dolphin-emu/GCPadNew.ini" +fi + +# Link Save States to /roms/savestates/wii +if [ ! -d "/storage/roms/savestates/wii/" ]; then + mkdir -p "/storage/roms/savestates/wii/" +fi + +rm -rf ${CONF_DIR}/StateSaves +ln -sf /storage/roms/savestates/wii ${CONF_DIR}/StateSaves + +# Copy bios, memory cards and other system stuff to roms +if [ ! -d "/storage/roms/bios/GC/" ]; then + mkdir -p /storage/roms/bios/GC/{USA,JAP,EUR} + cp -r ${CONF_DIR}/GC /storage/roms/bios/ +fi + +# Link bios and memory cards to roms +for REGION in EUR JAP USA +do + # Link bios + rm -rf "${CONF_DIR}/GC/${REGION}" + ln -sf "/storage/roms/bios/GC/${REGION}" "${CONF_DIR}/GC/${REGION}" + + # Link memory cards, copying to roms/bios first as needed + for SLOT in A B + do + MEM_CARD_FILE="MemoryCard${SLOT}.${REGION}.raw" + CONFIG_MEM_CARD="${CONF_DIR}/GC/${MEM_CARD_FILE}" + ROMS_BIOS_MEM_CARD="/storage/roms/bios/GC/${MEM_CARD_FILE}" + + if [ -f "${ROMS_BIOS_MEM_CARD}" ]; then + # Exists in roms/bios, remove from .config and link + rm -f "${CONFIG_MEM_CARD}" + ln -sf "${ROMS_BIOS_MEM_CARD}" "${CONFIG_MEM_CARD}" + elif [ -f "${CONFIG_MEM_CARD}" ]; then + # Only exists in .config, move to roms/bios and link + mv -f "${CONFIG_MEM_CARD}" "${ROMS_BIOS_MEM_CARD}" + ln -sf "${ROMS_BIOS_MEM_CARD}" "${CONFIG_MEM_CARD}" + fi + done +done + +# Emulation Station Features +GAME=$(echo "${1}"| sed "s#^/.*/##") +PLATFORM=$(echo "${2}"| sed "s#^/.*/##") +AA=$(get_setting anti_aliasing "${PLATFORM}" "${GAME}") +ASPECT=$(get_setting aspect_ratio "${PLATFORM}" "${GAME}") +AUDIOBE=$(get_setting audio_backend "${PLATFORM}" "${GAME}") +CLOCK=$(get_setting clock_speed "${PLATFORM}" "${GAME}") +ENBCHEATS=$(get_setting enable_cheats "${PLATFORM}" "${GAME}") +GRENDERER=$(get_setting graphics_backend "${PLATFORM}" "${GAME}") +IRES=$(get_setting internal_resolution "${PLATFORM}" "${GAME}") +FPS=$(get_setting show_fps "${PLATFORM}" "${GAME}") +CON=$(get_setting wii_controller_profile "${PLATFORM}" "${GAME}") +HKEY=$(get_setting hotkey_enable_button "${PLATFORM}" "${GAME}") +SHADERM=$(get_setting shader_mode "${PLATFORM}" "${GAME}") +SHADERP=$(get_setting shader_precompile "${PLATFORM}" "${GAME}") +VSYNC=$(get_setting vsync "${PLATFORM}" "${GAME}") +EFBACCESS=$(get_setting skip_efb_cpu_access "${PLATFORM}" "${GAME}") +EFBTEXTURE=$(get_setting store_efb_to_texture_only "${PLATFORM}" "${GAME}") +XFBTEXTURE=$(get_setting store_xfb_to_texture_only "${PLATFORM}" "${GAME}") +TEXTURE_CACHE_ACCURACY=$(get_setting texture_cache_accuracy "${PLATFORM}" "${GAME}") +RUMBLE=$(get_setting rumble "${PLATFORM}" "${GAME}") +WHACK=$(get_setting widescreen_hack "${PLATFORM}" "${GAME}") +WPC=$(get_setting write_protect_configs "${PLATFORM}" "${GAME}") + +# Grab clean config files during boot, unless disabled in emulationstation +if [ "$WPC" != "false" ]; then + cp -r /usr/config/dolphin-emu/GFX.ini ${CONF_DIR}/${GFX_INI} + cp -r /usr/config/dolphin-emu/Dolphin.ini ${CONF_DIR}/${DOLPHIN_INI} +fi + +# Set the cores to use +CORES=$(get_setting "cores" "${PLATFORM}" "${GAME}") +if [ "${CORES}" = "little" ] +then + EMUPERF="${SLOW_CORES}" +elif [ "${CORES}" = "big" ] +then + EMUPERF="${FAST_CORES}" +else + ### All.. + unset EMUPERF +fi + +### Emulation Station features: + # Anti-Aliasing + if [ "$AA" = "2m" ]; then + sed -i '/MSAA/c\MSAA = 2' ${CONF_DIR}/${GFX_INI} + sed -i '/SSAA/c\SSAA = False' ${CONF_DIR}/${GFX_INI} + elif [ "$AA" = "2s" ]; then + sed -i '/MSAA/c\MSAA = 2' ${CONF_DIR}/${GFX_INI} + sed -i '/SSAA/c\SSAA = True' ${CONF_DIR}/${GFX_INI} + elif [ "$AA" = "4m" ]; then + sed -i '/MSAA/c\MSAA = 4' ${CONF_DIR}/${GFX_INI} + sed -i '/SSAA/c\SSAA = False' ${CONF_DIR}/${GFX_INI} + elif [ "$AA" = "4s" ]; then + sed -i '/MSAA/c\MSAA = 4' ${CONF_DIR}/${GFX_INI} + sed -i '/SSAA/c\SSAA = True' ${CONF_DIR}/${GFX_INI} + elif [ "$AA" = "8m" ]; then + sed -i '/MSAA/c\MSAA = 8' ${CONF_DIR}/${GFX_INI} + sed -i '/SSAA/c\SSAA = False' ${CONF_DIR}/${GFX_INI} + elif [ "$AA" = "8s" ]; then + sed -i '/MSAA/c\MSAA = 8' ${CONF_DIR}/${GFX_INI} + sed -i '/SSAA/c\SSAA = True' ${CONF_DIR}/${GFX_INI} + else + sed -i '/MSAA/c\MSAA = 0' ${CONF_DIR}/${GFX_INI} + sed -i '/SSAA/c\SSAA = False' ${CONF_DIR}/${GFX_INI} + fi + + # Aspect Ratio + if [ "$ASPECT" = "1" ]; then + sed -i '/AspectRatio/c\AspectRatio = 1' ${CONF_DIR}/${GFX_INI} + elif [ "$ASPECT" = "2" ]; then + sed -i '/AspectRatio/c\AspectRatio = 2' ${CONF_DIR}/${GFX_INI} + elif [ "$ASPECT" = "3" ]; then + sed -i '/AspectRatio/c\AspectRatio = 3' ${CONF_DIR}/${GFX_INI} + else + sed -i '/AspectRatio/c\AspectRatio = 0' ${CONF_DIR}/${GFX_INI} + fi + + # Audio Backend + if [ "$AUDIOBE" = "lle" ]; then + AUDIO_BACKEND="LLE" + else + AUDIO_BACKEND="HLE" + fi + + # Clock Speed + if [ "$CLOCK" = "050" ]; then + sed -i '/^Overclock =/c\Overclock = 0.5' ${CONF_DIR}/${DOLPHIN_INI} + sed -i '/^OverclockEnable =/c\OverclockEnable = True' ${CONF_DIR}/${DOLPHIN_INI} + elif [ "$CLOCK" = "075" ]; then + sed -i '/^Overclock =/c\Overclock = 0.75' ${CONF_DIR}/${DOLPHIN_INI} + sed -i '/^OverclockEnable =/c\OverclockEnable = True' ${CONF_DIR}/${DOLPHIN_INI} + elif [ "$CLOCK" = "100" ]; then + sed -i '/^Overclock =/c\Overclock = 1.0' ${CONF_DIR}/${DOLPHIN_INI} + sed -i '/^OverclockEnable =/c\OverclockEnable = False' ${CONF_DIR}/${DOLPHIN_INI} + elif [ "$CLOCK" = "125" ]; then + sed -i '/^Overclock =/c\Overclock = 1.25' ${CONF_DIR}/${DOLPHIN_INI} + sed -i '/^OverclockEnable =/c\OverclockEnable = True' ${CONF_DIR}/${DOLPHIN_INI} + elif [ "$CLOCK" = "150" ]; then + sed -i '/^Overclock =/c\Overclock = 1.5' ${CONF_DIR}/${DOLPHIN_INI} + sed -i '/^OverclockEnable =/c\OverclockEnable = True' ${CONF_DIR}/${DOLPHIN_INI} + elif [ "$CLOCK" = "200" ]; then + sed -i '/^Overclock =/c\Overclock = 2.0' ${CONF_DIR}/${DOLPHIN_INI} + sed -i '/^OverclockEnable =/c\OverclockEnable = True' ${CONF_DIR}/${DOLPHIN_INI} + elif [ "$CLOCK" = "300" ]; then + sed -i '/^Overclock =/c\Overclock = 3.0' ${CONF_DIR}/${DOLPHIN_INI} + sed -i '/^OverclockEnable =/c\OverclockEnable = True' ${CONF_DIR}/${DOLPHIN_INI} + elif [ "$CLOCK" = "400" ]; then + sed -i '/^Overclock =/c\Overclock = 4.0' ${CONF_DIR}/${DOLPHIN_INI} + sed -i '/^OverclockEnable =/c\OverclockEnable = True' ${CONF_DIR}/${DOLPHIN_INI} + else + sed -i '/^OverclockEnable =/c\OverclockEnable = False' ${CONF_DIR}/${DOLPHIN_INI} + fi + + # Enable Cheats + if [ "$ENBCHEATS" = "1" ]; then + sed -i '/EnableCheats/c\EnableCheats = True' ${CONF_DIR}/${DOLPHIN_INI} + else + sed -i '/EnableCheats/c\EnableCheats = False' ${CONF_DIR}/${DOLPHIN_INI} + fi + + # Graphics Backend + if [ "$GRENDERER" = "vulkan" ]; then + sed -i '/GFXBackend/c\GFXBackend = Vulkan' ${CONF_DIR}/${DOLPHIN_INI} + elif [ "$GRENDERER" = "opengl" ]; then + sed -i '/GFXBackend/c\GFXBackend = OGL' ${CONF_DIR}/${DOLPHIN_INI} + else + sed -i '/GFXBackend/c\GFXBackend = @GRENDERER@' ${CONF_DIR}/${DOLPHIN_INI} + fi + + # Internal Resolution + if [ "$IRES" = "1" ]; then + sed -i '/InternalResolution/c\InternalResolution = 1' ${CONF_DIR}/${GFX_INI} + elif [ "$IRES" = "3" ]; then + sed -i '/InternalResolution/c\InternalResolution = 3' ${CONF_DIR}/${GFX_INI} + elif [ "$IRES" = "4" ]; then + sed -i '/InternalResolution/c\InternalResolution = 4' ${CONF_DIR}/${GFX_INI} + elif [ "$IRES" = "6" ]; then + sed -i '/InternalResolution/c\InternalResolution = 6' ${CONF_DIR}/${GFX_INI} + else + sed -i '/InternalResolution/c\InternalResolution = 2' ${CONF_DIR}/${GFX_INI} + fi + + # Shader Mode + if [ "$SHADERM" = "0" ]; then + sed -i '/ShaderCompilationMode =/c\ShaderCompilationMode = 0' ${CONF_DIR}/${GFX_INI} + elif [ "$SHADERM" = "1" ]; then + sed -i '/ShaderCompilationMode =/c\ShaderCompilationMode = 1' ${CONF_DIR}/${GFX_INI} + elif [ "$SHADERM" = "2" ]; then + sed -i '/ShaderCompilationMode =/c\ShaderCompilationMode = 2' ${CONF_DIR}/${GFX_INI} + elif [ "$SHADERM" = "3" ]; then + sed -i '/ShaderCompilationMode =/c\ShaderCompilationMode = 3' ${CONF_DIR}/${GFX_INI} + fi + + #Shader Precompile + if [ "$SHADERP" = "false" ]; then + sed -i '/WaitForShadersBeforeStarting =/c\WaitForShadersBeforeStarting = False' ${CONF_DIR}/${GFX_INI} + elif [ "$SHADERP" = "true" ]; then + sed -i '/WaitForShadersBeforeStarting =/c\WaitForShadersBeforeStarting = True' ${CONF_DIR}/${GFX_INI} + fi + + # Show FPS + if [ "$FPS" = "true" ]; then + sed -i '/ShowFPS/c\ShowFPS = True' ${CONF_DIR}/${GFX_INI} + else + sed -i '/ShowFPS/c\ShowFPS = False' ${CONF_DIR}/${GFX_INI} + fi + + # Wii Controller Profile + if [ "$CON" = "classic" ]; then + cp -r ${CONF_DIR}/WiiControllerProfiles/classic.ini ${CONF_DIR}/WiimoteNew.ini + elif [ "$CON" = "vremote" ]; then + cp -r ${CONF_DIR}/WiiControllerProfiles/vremote.ini ${CONF_DIR}/WiimoteNew.ini + elif [ "$CON" = "nunchuck" ]; then + cp -r ${CONF_DIR}/WiiControllerProfiles/nunchuck.ini ${CONF_DIR}/WiimoteNew.ini + elif [ "$CON" = "custom" ]; then + cp -r ${CONF_DIR}/WiiControllerProfiles/custom.ini ${CONF_DIR}/WiimoteNew.ini + else + cp -r ${CONF_DIR}/WiiControllerProfiles/hremote.ini ${CONF_DIR}/WiimoteNew.ini + fi + + # Wii Controller Rumble + if [ "$RUMBLE" = "false" ]; then + sed -i '/^Rumble/d' ${DOLPHIN_INI}/WiimoteNew.ini + fi + + # Wii Controller Hotkey Enable + if [ "$HKEY" = "mode" ]; then + sed -i '/^Buttons\/Hotkey =/c\Buttons\/Hotkey = Button 8' ${CONF_DIR}/GCPadNew.ini + else + sed -i '/^Buttons\/Hotkey =/c\Buttons\/Hotkey = Button 6' ${CONF_DIR}/GCPadNew.ini + fi + # Skip EFB CPU Access + if [ "$EFBACCESS" = "false" ]; then + sed -i '/EFBAccessEnable =/c\EFBAccessEnable = False' ${CONF_DIR}/${GFX_INI} + else + sed -i '/EFBAccessEnable =/c\EFBAccessEnable = True' ${CONF_DIR}/${GFX_INI} + fi + + # Store EFB to texture only + if [ "$EFBTEXTURE" = "false" ]; then + sed -i '/EFBToTextureEnable =/c\EFBToTextureEnable = False' ${CONF_DIR}/${GFX_INI} + else + sed -i '/EFBToTextureEnable =/c\EFBToTextureEnable = True' ${CONF_DIR}/${GFX_INI} + fi + + # Store XFB to texture only + if [ "$XFBTEXTURE" = "false" ]; then + sed -i '/XFBToTextureEnable =/c\XFBToTextureEnable = False' ${CONF_DIR}/${GFX_INI} + else + sed -i '/XFBToTextureEnable =/c\XFBToTextureEnable = True' ${CONF_DIR}/${GFX_INI} + fi + + # Texture cache accuracy + if [ "$TEXTURE_CACHE_ACCURACY" = "0" ]; then + sed -i '/SafeTextureCacheColorSamples =/c\SafeTextureCacheColorSamples = 0' ${CONF_DIR}/${GFX_INI} + elif [ "$TEXTURE_CACHE_ACCURACY" = "512" ]; then + sed -i '/SafeTextureCacheColorSamples =/c\SafeTextureCacheColorSamples = 512' ${CONF_DIR}/${GFX_INI} + else + # Default to 128 = fast + sed -i '/SafeTextureCacheColorSamples =/c\SafeTextureCacheColorSamples = 128' ${CONF_DIR}/${GFX_INI} + fi + + # Widescreen Hack + if [ "$WHACK" = "true" ]; then + sed -i '/wideScreenHack =/c\wideScreenHack = True' ${CONF_DIR}/${GFX_INI} + else + sed -i '/wideScreenHack =/c\wideScreenHack = False' ${CONF_DIR}/${GFX_INI} + fi + +# Skip bios always, it's untested for Wii +sed -i '/SkipIPL/c\SkipIPL = True' ${CONF_DIR}/${DOLPHIN_INI} + + # GC Controller Hotkey Enable + if [ "$HKEY" = "mode" ]; then + sed -i '/^Buttons\/Hotkey =/c\Buttons\/Hotkey = Button 8' ${CONF_DIR}/${GC_CONTROLLER_INI} + else + sed -i '/^Buttons\/Hotkey =/c\Buttons\/Hotkey = Button 6' ${CONF_DIR}/${GC_CONTROLLER_INI} + fi + + # Vsync + if [ "$VSYNC" = "1" ]; then + sed -i '/VSync =/c\VSync = True' ${CONF_DIR}/${GFX_INI} + else + sed -i '/VSync =/c\VSync = False' ${CONF_DIR}/${GFX_INI} + fi + +# Link .config/dolphin-emu to .local +rm -rf /storage/.local/share/dolphin-emu +ln -sf /storage/.config/dolphin-emu /storage/.local/share/dolphin-emu + +@EXPORTS@ + +# Retroachievements + /usr/bin/cheevos_dolphin.sh + +# Set video and audio backend + CMD="${CMD} -v $GRENDERER" + +if [ ${DOLPHIN_CORE} = "dolphin-emu" ]; then + CMD="-b -a ${AUDIO_BACKEND}" +else + CMD="-p @DOLPHIN_BACKEND@ -a ${AUDIO_BACKEND}" +fi + +# Debugging info: + echo "GAME set to: ${GAME}" + echo "PLATFORM set to: ${PLATFORM}" + echo "CPU CORES set to ${EMUPERF}" + echo "AA set to: ${AA}" + echo "ASPECT set to: ${ASPECT}" + echo "AUDIOBE set to: ${AUDIOBE}" + echo "CLOCK set to: ${CLOCK}" + echo "DOLPHIN_BACKEND set to: ${DOLPHIN_BACKEND}" + echo "ENBCHEATS set to: ${ENBCHEATS}" + echo "GRENDERER set to: ${GRENDERER}" + echo "IRES set to: ${IRES}" + echo "FPS set to: ${FPS}" + echo "CON set to: ${CON}" + echo "HKEY set to: ${HKEY}" + echo "SHADERM set to: ${SHADERM}" + echo "SHADERP set to: ${SHADERP}" + echo "VSYNC set to: ${VSYNC}" + echo "EFBACCESS set to: ${EFBACCESS}" + echo "EFBTEXTURE set to: ${EFBTEXTURE}" + echo "XFBTEXTURE set to: ${XFBTEXTURE}" + echo "TEXTURE_CACHE_ACCURACY set to: ${TEXTURE_CACHE_ACCURACY}" + echo "RUMBLE set to: ${RUMBLE}" + echo "WHACK set to: ${WHACK}" + echo "WPC set to: ${WPC}" + echo "Launching /usr/bin/${DOLPHIN_CORE} ${CMD} -e ${1}" + +# Run Dolphin emulator + ${GPTOKEYB} ${DOLPHIN_CORE} xbox360 & + ${EMUPERF} /usr/bin/${DOLPHIN_CORE} ${CMD} -e "${1}" + _gptokeyb_pid="$(pidof gptokeyb 2>/dev/null)" + [ -n "${_gptokeyb_pid}" ] && kill -9 ${_gptokeyb_pid} diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/triforce/GEYP6E.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/triforce/GEYP6E.ini new file mode 100644 index 0000000000..6361b66f96 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/triforce/GEYP6E.ini @@ -0,0 +1,10 @@ +# GEYP6E - Virtua Striker 2002 (Export, Type3) +[Core] +FPRF = True +[Gecko] +$Force Japan Version +04054234 60000000 +$ Unlock Special Teams +024E2F73 00004142 +004E2FA3 00000001 +004E2F9E 00000002 diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/triforce/GGGE6E.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/triforce/GGGE6E.ini new file mode 100644 index 0000000000..19ebe4c210 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/triforce/GGGE6E.ini @@ -0,0 +1,57 @@ +# GGGE6E - F-ZERO AX +[Core] +FPRF = True +CPUThread = True +[Gecko] +$Widescreen +044461B4 3FE40000 +$Infinite Time +0437C964 EA000000 +$Infinite Energy +04C43a04 42C80000 +[OnFrame] +$Disable Motor Setup (Rev. C) +0x8024DB74:dword:0x801809F8 +0x8024DB78:dword:0x8018085C +$Disable Motor Setup (Rev. D) +0x8024E034:dword:0x80180D5C +0x8024E038:dword:0x80180BC0 +$Disable Motor Setup (Rev. E) +0x8024E4B4:dword:0x801812E8 +0x8024E4B8:dword:0x8018114C +$Advertise Sound ON +0x803D0175:byte:0x00000001 +$Advertise Sound OFF +0x803D0175:byte:0x00000000 +$Game Difficulty (very easy) +0x803D0176:byte:0x00000000 +$Game Difficulty (easy) +0x803D0176:byte:0x00000001 +$Game Difficulty (normal) +0x803D0176:byte:0x00000002 +$Game Difficulty (hard) +0x803D0176:byte:0x00000003 +$Game Difficulty (hardest) +0x803D0176:byte:0x00000004 +$Race Mode Laps (normal) +0x803D0179:byte:0x00000000 +$Race Mode Laps (set 1) +0x803D0179:byte:0x00000001 +$Race Mode Laps (set 2) +0x803D0179:byte:0x00000002 +$Race Mode Laps (set 3) +0x803D0179:byte:0x00000003 +$Race Mode Laps (set 4) +0x803D0179:byte:0x00000004 +$Race Mode Laps (set 5) +0x803D0179:byte:0x00000005 +$Handicap On +0x803D132E:byte:0x00000001 +$Handicap Off +0x803D132E:byte:0x00000000 +[OnFrame_Enabled] +$Disable Motor Setup (Rev. C) +$Disable Motor Setup (Rev. D) +$Disable Motor Setup (Rev. E) +$Advertise Sound ON +$Game Difficulty (easy) diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/triforce/GHAE6E.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/triforce/GHAE6E.ini new file mode 100644 index 0000000000..af2f040bc3 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/triforce/GHAE6E.ini @@ -0,0 +1,18 @@ +# GHAE6E - F-ZERO AX (Monster) +[OnFrame] +$Disable Motor Setup +0x8023A0F4:dword:0x8016B4EC +0x8023A0F8:dword:0x8016B350 +[Core] +FPRF = True +CPUThread = True +[OnFrame_Enabled] +$Disable Motor Setup +[Gecko] +$Bypass Cycraft +0043137B 00000086 +$Slowdown Fix +0043137E 00000000 +[Gecko_Enabled] +$Bypass Cycraft +$Slowdown Fix diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/triforce/GKPJ6E.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/triforce/GKPJ6E.ini new file mode 100644 index 0000000000..45d5d81eb0 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/triforce/GKPJ6E.ini @@ -0,0 +1,53 @@ +# GKPJ6E - Mario Kart Arcade GP +[OnFrame] +$Disable NAMCAM +0x800790A0:dword:0x98650025 +$Loop Fix +0x8003226C:dword:0x60000000 +0x80032278:dword:0x41820158 +$Card Saving Fix +0x801be2dc:dword:0x4082009c +$Game Over Hang Fix +0x8003b020:dword:0x40820040 +$Loop fix2 +0x80031BF0:dword:0x60000000 +0x80031BFC:dword:0x60000000 +0x800BE10C:dword:0x4800002C +0x8009F1E0:dword:0x60000000 +[OnFrame_Enabled] +$Disable NAMCAM +$Card Saving Fix +$Game Over Hang Fix +$Loop Fix +$Loop fix2 +[Gecko] +$WIDESCREEN JPN +C228C800 00000009 +C03F0034 9421FFE0 +93C10004 93E10008 +DBE1000C 7FC802A6 +48000009 3FAAAAAB +7FE802A6 C3FF0000 +EC3F0072 7FC803A6 +83C10004 83E10008 +CBE1000C 38210020 +60000000 00000000 +$WIDESCREEN USA +C22C80D4 00000009 +C03F0034 9421FFE0 +93C10004 93E10008 +DBE1000C 7FC802A6 +48000009 3FAAAAAB +7FE802A6 C3FF0000 +EC3F0072 7FC803A6 +83C10004 83E10008 +CBE1000C 38210020 +60000000 00000000 +$Slowdowns Fix (Required) +041b2238 60000000 +$Link Check Skip +04032410 60000000 +$Skip Boot Checks +040320fc 60000000 +[Gecko_Enabled] +$Slowdowns Fix (Required) diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/triforce/GLLP6E.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/triforce/GLLP6E.ini new file mode 100644 index 0000000000..4f809a8c4d --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/triforce/GLLP6E.ini @@ -0,0 +1,8 @@ +# GLLP6E - VIRTUA STRIKER 4 Ver.2006 (Export) +[Core] +FPRF = True +[OnFrame_Enabled] +$bypass code +[OnFrame] +$bypass code +0x80414CE8:byte:0x00000005 diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/triforce/GNLJ82.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/triforce/GNLJ82.ini new file mode 100644 index 0000000000..161d238009 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/triforce/GNLJ82.ini @@ -0,0 +1,46 @@ +# GNLJ82 - Mario Kart Arcade GP 2 +[OnFrame] +$Disable NAMCAM +0x805986E5:byte:0x00000000 +0x80073BD8:dword:0x98650025 +[OnFrame_Enabled] +$Disable NAMCAM +[Gecko] +$WIDESCREEN +C22C80D4 00000009 +C03F0034 9421FFE0 +93C10004 93E10008 +DBE1000C 7FC802A6 +48000009 3FAAAAAB +7FE802A6 C3FF0000 +EC3F0072 7FC803A6 +83C10004 83E10008 +CBE1000C 38210020 +60000000 00000000 +$Slowdowns Fix (US - Required) +04086150 60000000 +$Link Check Skip (US - Optional) +0402eb6c 60000000 +$Skip boot checks (US - Optional) +0402e858 60000000 +$Card Save Hang Fix (US - Required) +04249958 38000000 +0424995c 980da504 +04249960 980da509 +04249964 480000ac +$Slowdowns Fix (JPN - Required) +04086768 60000000 +$Link Check Skip (JPN - Optional) +0402ebcc 60000000 +$Skip boot checks (JPN - Optional) +0402e8b8 60000000 +$Card Save Hang Fix (JPN - Required) +04249f60 38000000 +04249f64 980da504 +04249f68 980da509 +04249f6c 480000ac + +[Gecko_Enabled] +$WIDESCREEN +$Slowdowns Fix (US - Required) +$Link Check Skip (US - Optional) diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/triforce/SBJA.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/triforce/SBJA.ini new file mode 100644 index 0000000000..0b0bbfc456 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/triforce/SBJA.ini @@ -0,0 +1,8 @@ +# Virtua Striker 4 (Export) +[Core] +FPRF = True +[Gecko] +$bypass code +0405214c 60000000 +[Gecko_Enabled] +$bypass code diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/triforce/SBLK.ini b/projects/ArchR/packages/emulators/standalone/dolphin-sa/triforce/SBLK.ini new file mode 100644 index 0000000000..5fda0e0bbe --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/triforce/SBLK.ini @@ -0,0 +1,8 @@ +# Virtua Striker 4 Ver.2006 (Japan) +[Core] +FPRF = True +[Gecko] +$Bypass boot +040568D8 60000000 +[Gecko_Enabled] +$Bypass boot diff --git a/projects/ArchR/packages/emulators/standalone/drastic-sa/config/H700/drastic.cfg b/projects/ArchR/packages/emulators/standalone/drastic-sa/config/H700/drastic.cfg new file mode 100644 index 0000000000..9a29b95575 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/drastic-sa/config/H700/drastic.cfg @@ -0,0 +1,111 @@ +frameskip_type = 2 +frameskip_value = 3 +safe_frameskip = 0 +show_frame_counter = 0 +screen_orientation = 1 +screen_swap = 0 +savestate_number = 0 +fast_forward = 0 +enable_sound = 1 +clock_speed = 0 +threaded_3d = 1 +mirror_touch = 0 +compress_savestates = 1 +savestate_snapshot = 1 +unzip_roms = 0 +preload_roms = 0 +backup_in_savestates = 1 +ignore_gamecard_limit = 0 +frame_interval = 0 +trim_roms = 0 +fix_main_2d_screen = 0 +disable_edge_marking = 0 +interframe_blend = 0 +hires_3d = 1 +use_rtc_custom_time = 0 +rtc_custom_time = 0 +rtc_system_time = 0 +slot2_device_type = 0 +rumble_frames = 3 +firmware.username = Dr DraStic +firmware.language = 1 +firmware.favorite_color = 0 +firmware.birthday_month = 1 +firmware.birthday_day = 1 +enable_cheats = 1 +controls_a[CONTROL_INDEX_UP] = 1217 +controls_a[CONTROL_INDEX_DOWN] = 1153 +controls_a[CONTROL_INDEX_LEFT] = 1216 +controls_a[CONTROL_INDEX_RIGHT] = 1152 +controls_a[CONTROL_INDEX_A] = 65535 +controls_a[CONTROL_INDEX_B] = 65535 +controls_a[CONTROL_INDEX_X] = 65535 +controls_a[CONTROL_INDEX_Y] = 65535 +controls_a[CONTROL_INDEX_L] = 65535 +controls_a[CONTROL_INDEX_R] = 65535 +controls_a[CONTROL_INDEX_START] = 65535 +controls_a[CONTROL_INDEX_SELECT] = 65535 +controls_a[CONTROL_INDEX_HINGE] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_UP] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_DOWN] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_LEFT] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_RIGHT] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_PRESS] = 65535 +controls_a[CONTROL_INDEX_MENU] = 65535 +controls_a[CONTROL_INDEX_SAVE_STATE] = 65535 +controls_a[CONTROL_INDEX_LOAD_STATE] = 65535 +controls_a[CONTROL_INDEX_FAST_FORWARD] = 65535 +controls_a[CONTROL_INDEX_SWAP_SCREENS] = 65535 +controls_a[CONTROL_INDEX_SWAP_ORIENTATION_A] = 65535 +controls_a[CONTROL_INDEX_SWAP_ORIENTATION_B] = 65535 +controls_a[CONTROL_INDEX_LOAD_GAME] = 65535 +controls_a[CONTROL_INDEX_QUIT] = 65535 +controls_a[CONTROL_INDEX_FAKE_MICROPHONE] = 65535 +controls_a[CONTROL_INDEX_UI_UP] = 1217 +controls_a[CONTROL_INDEX_UI_DOWN] = 1153 +controls_a[CONTROL_INDEX_UI_LEFT] = 1216 +controls_a[CONTROL_INDEX_UI_RIGHT] = 1152 +controls_a[CONTROL_INDEX_UI_SELECT] = 65535 +controls_a[CONTROL_INDEX_UI_BACK] = 65535 +controls_a[CONTROL_INDEX_UI_EXIT] = 65535 +controls_a[CONTROL_INDEX_UI_PAGE_UP] = 65535 +controls_a[CONTROL_INDEX_UI_PAGE_DOWN] = 65535 +controls_a[CONTROL_INDEX_UI_SWITCH] = 65535 +controls_b[CONTROL_INDEX_UP] = 1037 +controls_b[CONTROL_INDEX_DOWN] = 1038 +controls_b[CONTROL_INDEX_LEFT] = 1039 +controls_b[CONTROL_INDEX_RIGHT] = 1040 +controls_b[CONTROL_INDEX_A] = 1025 +controls_b[CONTROL_INDEX_B] = 1024 +controls_b[CONTROL_INDEX_X] = 1026 +controls_b[CONTROL_INDEX_Y] = 1027 +controls_b[CONTROL_INDEX_L] = 1028 +controls_b[CONTROL_INDEX_R] = 1029 +controls_b[CONTROL_INDEX_START] = 1033 +controls_b[CONTROL_INDEX_SELECT] = 1032 +controls_b[CONTROL_INDEX_HINGE] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_UP] = 1219 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_DOWN] = 1155 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_LEFT] = 1218 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_RIGHT] = 1154 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_PRESS] = 1036 +controls_b[CONTROL_INDEX_MENU] = 1035 +controls_b[CONTROL_INDEX_SAVE_STATE] = 65535 +controls_b[CONTROL_INDEX_LOAD_STATE] = 65535 +controls_b[CONTROL_INDEX_FAST_FORWARD] = 65535 +controls_b[CONTROL_INDEX_SWAP_SCREENS] = 65535 +controls_b[CONTROL_INDEX_SWAP_ORIENTATION_A] = 1030 +controls_b[CONTROL_INDEX_SWAP_ORIENTATION_B] = 1031 +controls_b[CONTROL_INDEX_LOAD_GAME] = 65535 +controls_b[CONTROL_INDEX_QUIT] = 65535 +controls_b[CONTROL_INDEX_FAKE_MICROPHONE] = 65535 +controls_b[CONTROL_INDEX_UI_UP] = 1037 +controls_b[CONTROL_INDEX_UI_DOWN] = 1038 +controls_b[CONTROL_INDEX_UI_LEFT] = 1039 +controls_b[CONTROL_INDEX_UI_RIGHT] = 1040 +controls_b[CONTROL_INDEX_UI_SELECT] = 1025 +controls_b[CONTROL_INDEX_UI_BACK] = 65535 +controls_b[CONTROL_INDEX_UI_EXIT] = 1024 +controls_b[CONTROL_INDEX_UI_PAGE_UP] = 65535 +controls_b[CONTROL_INDEX_UI_PAGE_DOWN] = 65535 +controls_b[CONTROL_INDEX_UI_SWITCH] = 65535 diff --git a/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3326/drastic.cfg b/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3326/drastic.cfg new file mode 100644 index 0000000000..57c6076d48 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3326/drastic.cfg @@ -0,0 +1,111 @@ +frameskip_type = 2 +frameskip_value = 2 +safe_frameskip = 0 +show_frame_counter = 0 +screen_orientation = 2 +screen_swap = 0 +savestate_number = 0 +fast_forward = 0 +enable_sound = 1 +clock_speed = 0 +threaded_3d = 1 +mirror_touch = 0 +compress_savestates = 1 +savestate_snapshot = 1 +unzip_roms = 0 +preload_roms = 0 +backup_in_savestates = 1 +ignore_gamecard_limit = 0 +frame_interval = 0 +trim_roms = 0 +fix_main_2d_screen = 0 +disable_edge_marking = 0 +interframe_blend = 0 +hires_3d = 0 +use_rtc_custom_time = 0 +rtc_custom_time = 0 +rtc_system_time = 0 +slot2_device_type = 0 +rumble_frames = 3 +firmware.username = Dr DraStic +firmware.language = 1 +firmware.favorite_color = 0 +firmware.birthday_month = 1 +firmware.birthday_day = 1 +enable_cheats = 1 +controls_a[CONTROL_INDEX_UP] = 1089 +controls_a[CONTROL_INDEX_DOWN] = 1092 +controls_a[CONTROL_INDEX_LEFT] = 1096 +controls_a[CONTROL_INDEX_RIGHT] = 1090 +controls_a[CONTROL_INDEX_A] = 32 +controls_a[CONTROL_INDEX_B] = 480 +controls_a[CONTROL_INDEX_X] = 122 +controls_a[CONTROL_INDEX_Y] = 120 +controls_a[CONTROL_INDEX_L] = 481 +controls_a[CONTROL_INDEX_R] = 99 +controls_a[CONTROL_INDEX_START] = 13 +controls_a[CONTROL_INDEX_SELECT] = 485 +controls_a[CONTROL_INDEX_HINGE] = 104 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_UP] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_DOWN] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_LEFT] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_RIGHT] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_PRESS] = 1024 +controls_a[CONTROL_INDEX_MENU] = 1032 +controls_a[CONTROL_INDEX_SAVE_STATE] = 318 +controls_a[CONTROL_INDEX_LOAD_STATE] = 320 +controls_a[CONTROL_INDEX_FAST_FORWARD] = 8 +controls_a[CONTROL_INDEX_SWAP_SCREENS] = 1034 +controls_a[CONTROL_INDEX_SWAP_ORIENTATION_A] = 97 +controls_a[CONTROL_INDEX_SWAP_ORIENTATION_B] = 1035 +controls_a[CONTROL_INDEX_LOAD_GAME] = 65535 +controls_a[CONTROL_INDEX_QUIT] = 65535 +controls_a[CONTROL_INDEX_FAKE_MICROPHONE] = 65535 +controls_a[CONTROL_INDEX_UI_UP] = 338 +controls_a[CONTROL_INDEX_UI_DOWN] = 337 +controls_a[CONTROL_INDEX_UI_LEFT] = 336 +controls_a[CONTROL_INDEX_UI_RIGHT] = 335 +controls_a[CONTROL_INDEX_UI_SELECT] = 13 +controls_a[CONTROL_INDEX_UI_BACK] = 8 +controls_a[CONTROL_INDEX_UI_EXIT] = 27 +controls_a[CONTROL_INDEX_UI_PAGE_UP] = 331 +controls_a[CONTROL_INDEX_UI_PAGE_DOWN] = 334 +controls_a[CONTROL_INDEX_UI_SWITCH] = 481 +controls_b[CONTROL_INDEX_UP] = 1153 +controls_b[CONTROL_INDEX_DOWN] = 1217 +controls_b[CONTROL_INDEX_LEFT] = 1152 +controls_b[CONTROL_INDEX_RIGHT] = 1216 +controls_b[CONTROL_INDEX_A] = 1024 +controls_b[CONTROL_INDEX_B] = 1025 +controls_b[CONTROL_INDEX_X] = 1026 +controls_b[CONTROL_INDEX_Y] = 1027 +controls_b[CONTROL_INDEX_L] = 1028 +controls_b[CONTROL_INDEX_R] = 1029 +controls_b[CONTROL_INDEX_START] = 1030 +controls_b[CONTROL_INDEX_SELECT] = 1031 +controls_b[CONTROL_INDEX_HINGE] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_UP] = 1219 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_DOWN] = 1155 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_LEFT] = 1218 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_RIGHT] = 1154 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_PRESS] = 1033 +controls_b[CONTROL_INDEX_MENU] = 65535 +controls_b[CONTROL_INDEX_SAVE_STATE] = 65535 +controls_b[CONTROL_INDEX_LOAD_STATE] = 65535 +controls_b[CONTROL_INDEX_FAST_FORWARD] = 65535 +controls_b[CONTROL_INDEX_SWAP_SCREENS] = 65535 +controls_b[CONTROL_INDEX_SWAP_ORIENTATION_A] = 65535 +controls_b[CONTROL_INDEX_SWAP_ORIENTATION_B] = 65535 +controls_b[CONTROL_INDEX_LOAD_GAME] = 65535 +controls_b[CONTROL_INDEX_QUIT] = 65535 +controls_b[CONTROL_INDEX_FAKE_MICROPHONE] = 65535 +controls_b[CONTROL_INDEX_UI_UP] = 1089 +controls_b[CONTROL_INDEX_UI_DOWN] = 1092 +controls_b[CONTROL_INDEX_UI_LEFT] = 1096 +controls_b[CONTROL_INDEX_UI_RIGHT] = 1090 +controls_b[CONTROL_INDEX_UI_SELECT] = 1024 +controls_b[CONTROL_INDEX_UI_BACK] = 1034 +controls_b[CONTROL_INDEX_UI_EXIT] = 1025 +controls_b[CONTROL_INDEX_UI_PAGE_UP] = 1028 +controls_b[CONTROL_INDEX_UI_PAGE_DOWN] = 1029 +controls_b[CONTROL_INDEX_UI_SWITCH] = 1035 diff --git a/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3326/drastic.cfg.oga b/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3326/drastic.cfg.oga new file mode 100644 index 0000000000..f7283b94b1 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3326/drastic.cfg.oga @@ -0,0 +1,111 @@ +frameskip_type = 2 +frameskip_value = 2 +safe_frameskip = 0 +show_frame_counter = 0 +screen_orientation = 2 +screen_swap = 0 +savestate_number = 1 +fast_forward = 0 +enable_sound = 1 +clock_speed = 0 +threaded_3d = 1 +mirror_touch = 0 +compress_savestates = 1 +savestate_snapshot = 1 +unzip_roms = 0 +preload_roms = 0 +backup_in_savestates = 1 +ignore_gamecard_limit = 0 +frame_interval = 0 +trim_roms = 0 +fix_main_2d_screen = 0 +disable_edge_marking = 0 +interframe_blend = 0 +hires_3d = 0 +use_rtc_custom_time = 0 +rtc_custom_time = 0 +rtc_system_time = 0 +slot2_device_type = 0 +rumble_frames = 3 +firmware.username = Dr DraStic +firmware.language = 1 +firmware.favorite_color = 0 +firmware.birthday_month = 1 +firmware.birthday_day = 1 +enable_cheats = 1 +controls_a[CONTROL_INDEX_UP] = 1030 +controls_a[CONTROL_INDEX_DOWN] = 1031 +controls_a[CONTROL_INDEX_LEFT] = 1032 +controls_a[CONTROL_INDEX_RIGHT] = 1033 +controls_a[CONTROL_INDEX_A] = 1025 +controls_a[CONTROL_INDEX_B] = 1024 +controls_a[CONTROL_INDEX_X] = 1026 +controls_a[CONTROL_INDEX_Y] = 1027 +controls_a[CONTROL_INDEX_L] = 1028 +controls_a[CONTROL_INDEX_R] = 1029 +controls_a[CONTROL_INDEX_START] = 1037 +controls_a[CONTROL_INDEX_SELECT] = 1034 +controls_a[CONTROL_INDEX_HINGE] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_UP] = 1217 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_DOWN] = 1153 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_LEFT] = 1216 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_RIGHT] = 1152 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_PRESS] = 1036 +controls_a[CONTROL_INDEX_MENU] = 1035 +controls_a[CONTROL_INDEX_SAVE_STATE] = 65535 +controls_a[CONTROL_INDEX_LOAD_STATE] = 65535 +controls_a[CONTROL_INDEX_FAST_FORWARD] = 65535 +controls_a[CONTROL_INDEX_SWAP_SCREENS] = 65535 +controls_a[CONTROL_INDEX_SWAP_ORIENTATION_A] = 65535 +controls_a[CONTROL_INDEX_SWAP_ORIENTATION_B] = 65535 +controls_a[CONTROL_INDEX_LOAD_GAME] = 65535 +controls_a[CONTROL_INDEX_QUIT] = 65535 +controls_a[CONTROL_INDEX_FAKE_MICROPHONE] = 65535 +controls_a[CONTROL_INDEX_UI_UP] = 1030 +controls_a[CONTROL_INDEX_UI_DOWN] = 1031 +controls_a[CONTROL_INDEX_UI_LEFT] = 1032 +controls_a[CONTROL_INDEX_UI_RIGHT] = 1033 +controls_a[CONTROL_INDEX_UI_SELECT] = 1025 +controls_a[CONTROL_INDEX_UI_BACK] = 65535 +controls_a[CONTROL_INDEX_UI_EXIT] = 1024 +controls_a[CONTROL_INDEX_UI_PAGE_UP] = 65535 +controls_a[CONTROL_INDEX_UI_PAGE_DOWN] = 65535 +controls_a[CONTROL_INDEX_UI_SWITCH] = 65535 +controls_b[CONTROL_INDEX_UP] = 65535 +controls_b[CONTROL_INDEX_DOWN] = 65535 +controls_b[CONTROL_INDEX_LEFT] = 65535 +controls_b[CONTROL_INDEX_RIGHT] = 65535 +controls_b[CONTROL_INDEX_A] = 65535 +controls_b[CONTROL_INDEX_B] = 65535 +controls_b[CONTROL_INDEX_X] = 65535 +controls_b[CONTROL_INDEX_Y] = 65535 +controls_b[CONTROL_INDEX_L] = 65535 +controls_b[CONTROL_INDEX_R] = 65535 +controls_b[CONTROL_INDEX_START] = 65535 +controls_b[CONTROL_INDEX_SELECT] = 65535 +controls_b[CONTROL_INDEX_HINGE] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_UP] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_DOWN] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_LEFT] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_RIGHT] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_PRESS] = 65535 +controls_b[CONTROL_INDEX_MENU] = 65535 +controls_b[CONTROL_INDEX_SAVE_STATE] = 65535 +controls_b[CONTROL_INDEX_LOAD_STATE] = 65535 +controls_b[CONTROL_INDEX_FAST_FORWARD] = 65535 +controls_b[CONTROL_INDEX_SWAP_SCREENS] = 65535 +controls_b[CONTROL_INDEX_SWAP_ORIENTATION_A] = 65535 +controls_b[CONTROL_INDEX_SWAP_ORIENTATION_B] = 65535 +controls_b[CONTROL_INDEX_LOAD_GAME] = 65535 +controls_b[CONTROL_INDEX_QUIT] = 65535 +controls_b[CONTROL_INDEX_FAKE_MICROPHONE] = 65535 +controls_b[CONTROL_INDEX_UI_UP] = 1217 +controls_b[CONTROL_INDEX_UI_DOWN] = 1153 +controls_b[CONTROL_INDEX_UI_LEFT] = 1216 +controls_b[CONTROL_INDEX_UI_RIGHT] = 1152 +controls_b[CONTROL_INDEX_UI_SELECT] = 65535 +controls_b[CONTROL_INDEX_UI_BACK] = 65535 +controls_b[CONTROL_INDEX_UI_EXIT] = 65535 +controls_b[CONTROL_INDEX_UI_PAGE_UP] = 65535 +controls_b[CONTROL_INDEX_UI_PAGE_DOWN] = 65535 +controls_b[CONTROL_INDEX_UI_SWITCH] = 65535 diff --git a/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3326/drastic.cfg.ogabe b/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3326/drastic.cfg.ogabe new file mode 100644 index 0000000000..90418d0014 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3326/drastic.cfg.ogabe @@ -0,0 +1,111 @@ +frameskip_type = 2 +frameskip_value = 2 +safe_frameskip = 0 +show_frame_counter = 0 +screen_orientation = 2 +screen_swap = 0 +savestate_number = 0 +fast_forward = 0 +enable_sound = 1 +clock_speed = 0 +threaded_3d = 1 +mirror_touch = 0 +compress_savestates = 1 +savestate_snapshot = 1 +unzip_roms = 0 +preload_roms = 0 +backup_in_savestates = 1 +ignore_gamecard_limit = 0 +frame_interval = 0 +trim_roms = 0 +fix_main_2d_screen = 0 +disable_edge_marking = 0 +interframe_blend = 0 +hires_3d = 0 +use_rtc_custom_time = 0 +rtc_custom_time = 0 +rtc_system_time = 0 +slot2_device_type = 0 +rumble_frames = 3 +firmware.username = Dr DraStic +firmware.language = 1 +firmware.favorite_color = 0 +firmware.birthday_month = 1 +firmware.birthday_day = 1 +enable_cheats = 1 +controls_a[CONTROL_INDEX_UP] = 1036 +controls_a[CONTROL_INDEX_DOWN] = 1037 +controls_a[CONTROL_INDEX_LEFT] = 1038 +controls_a[CONTROL_INDEX_RIGHT] = 1039 +controls_a[CONTROL_INDEX_A] = 100 +controls_a[CONTROL_INDEX_B] = 99 +controls_a[CONTROL_INDEX_X] = 122 +controls_a[CONTROL_INDEX_Y] = 118 +controls_a[CONTROL_INDEX_L] = 113 +controls_a[CONTROL_INDEX_R] = 111 +controls_a[CONTROL_INDEX_START] = 1033 +controls_a[CONTROL_INDEX_SELECT] = 1032 +controls_a[CONTROL_INDEX_HINGE] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_UP] = 1217 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_DOWN] = 1153 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_LEFT] = 1216 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_RIGHT] = 1152 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_PRESS] = 1035 +controls_a[CONTROL_INDEX_MENU] = 1034 +controls_a[CONTROL_INDEX_SAVE_STATE] = 65535 +controls_a[CONTROL_INDEX_LOAD_STATE] = 65535 +controls_a[CONTROL_INDEX_FAST_FORWARD] = 65535 +controls_a[CONTROL_INDEX_SWAP_SCREENS] = 65535 +controls_a[CONTROL_INDEX_SWAP_ORIENTATION_A] = 1030 +controls_a[CONTROL_INDEX_SWAP_ORIENTATION_B] = 1031 +controls_a[CONTROL_INDEX_LOAD_GAME] = 65535 +controls_a[CONTROL_INDEX_QUIT] = 65535 +controls_a[CONTROL_INDEX_FAKE_MICROPHONE] = 65535 +controls_a[CONTROL_INDEX_UI_UP] = 1032 +controls_a[CONTROL_INDEX_UI_DOWN] = 1033 +controls_a[CONTROL_INDEX_UI_LEFT] = 1034 +controls_a[CONTROL_INDEX_UI_RIGHT] = 1035 +controls_a[CONTROL_INDEX_UI_SELECT] = 1025 +controls_a[CONTROL_INDEX_UI_BACK] = 65535 +controls_a[CONTROL_INDEX_UI_EXIT] = 1024 +controls_a[CONTROL_INDEX_UI_PAGE_UP] = 65535 +controls_a[CONTROL_INDEX_UI_PAGE_DOWN] = 65535 +controls_a[CONTROL_INDEX_UI_SWITCH] = 65535 +controls_b[CONTROL_INDEX_UP] = 65535 +controls_b[CONTROL_INDEX_DOWN] = 65535 +controls_b[CONTROL_INDEX_LEFT] = 65535 +controls_b[CONTROL_INDEX_RIGHT] = 65535 +controls_b[CONTROL_INDEX_A] = 65535 +controls_b[CONTROL_INDEX_B] = 65535 +controls_b[CONTROL_INDEX_X] = 65535 +controls_b[CONTROL_INDEX_Y] = 65535 +controls_b[CONTROL_INDEX_L] = 65535 +controls_b[CONTROL_INDEX_R] = 65535 +controls_b[CONTROL_INDEX_START] = 65535 +controls_b[CONTROL_INDEX_SELECT] = 65535 +controls_b[CONTROL_INDEX_HINGE] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_UP] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_DOWN] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_LEFT] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_RIGHT] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_PRESS] = 65535 +controls_b[CONTROL_INDEX_MENU] = 65535 +controls_b[CONTROL_INDEX_SAVE_STATE] = 65535 +controls_b[CONTROL_INDEX_LOAD_STATE] = 65535 +controls_b[CONTROL_INDEX_FAST_FORWARD] = 65535 +controls_b[CONTROL_INDEX_SWAP_SCREENS] = 65535 +controls_b[CONTROL_INDEX_SWAP_ORIENTATION_A] = 65535 +controls_b[CONTROL_INDEX_SWAP_ORIENTATION_B] = 65535 +controls_b[CONTROL_INDEX_LOAD_GAME] = 65535 +controls_b[CONTROL_INDEX_QUIT] = 65535 +controls_b[CONTROL_INDEX_FAKE_MICROPHONE] = 65535 +controls_b[CONTROL_INDEX_UI_UP] = 1217 +controls_b[CONTROL_INDEX_UI_DOWN] = 1153 +controls_b[CONTROL_INDEX_UI_LEFT] = 1216 +controls_b[CONTROL_INDEX_UI_RIGHT] = 1152 +controls_b[CONTROL_INDEX_UI_SELECT] = 65535 +controls_b[CONTROL_INDEX_UI_BACK] = 65535 +controls_b[CONTROL_INDEX_UI_EXIT] = 65535 +controls_b[CONTROL_INDEX_UI_PAGE_UP] = 65535 +controls_b[CONTROL_INDEX_UI_PAGE_DOWN] = 65535 +controls_b[CONTROL_INDEX_UI_SWITCH] = 65535 diff --git a/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3326/drastic.cfg.ogs b/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3326/drastic.cfg.ogs new file mode 100644 index 0000000000..7ee2ee6ca8 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3326/drastic.cfg.ogs @@ -0,0 +1,111 @@ +frameskip_type = 2 +frameskip_value = 4 +safe_frameskip = 0 +show_frame_counter = 0 +screen_orientation = 0 +screen_swap = 0 +savestate_number = 0 +fast_forward = 0 +enable_sound = 1 +clock_speed = 0 +threaded_3d = 0 +mirror_touch = 0 +compress_savestates = 1 +savestate_snapshot = 1 +unzip_roms = 0 +preload_roms = 0 +backup_in_savestates = 1 +ignore_gamecard_limit = 0 +frame_interval = 0 +trim_roms = 0 +fix_main_2d_screen = 0 +disable_edge_marking = 0 +interframe_blend = 0 +hires_3d = 0 +use_rtc_custom_time = 0 +rtc_custom_time = 0 +rtc_system_time = 0 +slot2_device_type = 0 +rumble_frames = 3 +firmware.username = Dr DraStic +firmware.language = 1 +firmware.favorite_color = 0 +firmware.birthday_month = 1 +firmware.birthday_day = 1 +enable_cheats = 1 +controls_a[CONTROL_INDEX_UP] = 1036 +controls_a[CONTROL_INDEX_DOWN] = 1037 +controls_a[CONTROL_INDEX_LEFT] = 1038 +controls_a[CONTROL_INDEX_RIGHT] = 1039 +controls_a[CONTROL_INDEX_A] = 1025 +controls_a[CONTROL_INDEX_B] = 1024 +controls_a[CONTROL_INDEX_X] = 1026 +controls_a[CONTROL_INDEX_Y] = 1027 +controls_a[CONTROL_INDEX_L] = 1028 +controls_a[CONTROL_INDEX_R] = 1029 +controls_a[CONTROL_INDEX_START] = 1033 +controls_a[CONTROL_INDEX_SELECT] = 1032 +controls_a[CONTROL_INDEX_HINGE] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_UP] = 1219 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_DOWN] = 1155 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_LEFT] = 1218 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_RIGHT] = 1154 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_PRESS] = 1035 +controls_a[CONTROL_INDEX_MENU] = 1040 +controls_a[CONTROL_INDEX_SAVE_STATE] = 1031 +controls_a[CONTROL_INDEX_LOAD_STATE] = 1030 +controls_a[CONTROL_INDEX_FAST_FORWARD] = 65535 +controls_a[CONTROL_INDEX_SWAP_SCREENS] = 65535 +controls_a[CONTROL_INDEX_SWAP_ORIENTATION_A] = 1034 +controls_a[CONTROL_INDEX_SWAP_ORIENTATION_B] = 1041 +controls_a[CONTROL_INDEX_LOAD_GAME] = 65535 +controls_a[CONTROL_INDEX_QUIT] = 65535 +controls_a[CONTROL_INDEX_FAKE_MICROPHONE] = 65535 +controls_a[CONTROL_INDEX_UI_UP] = 1036 +controls_a[CONTROL_INDEX_UI_DOWN] = 1037 +controls_a[CONTROL_INDEX_UI_LEFT] = 1038 +controls_a[CONTROL_INDEX_UI_RIGHT] = 1039 +controls_a[CONTROL_INDEX_UI_SELECT] = 1025 +controls_a[CONTROL_INDEX_UI_BACK] = 1026 +controls_a[CONTROL_INDEX_UI_EXIT] = 1024 +controls_a[CONTROL_INDEX_UI_PAGE_UP] = 65535 +controls_a[CONTROL_INDEX_UI_PAGE_DOWN] = 65535 +controls_a[CONTROL_INDEX_UI_SWITCH] = 65535 +controls_b[CONTROL_INDEX_UP] = 1217 +controls_b[CONTROL_INDEX_DOWN] = 1153 +controls_b[CONTROL_INDEX_LEFT] = 1216 +controls_b[CONTROL_INDEX_RIGHT] = 1152 +controls_b[CONTROL_INDEX_A] = 65535 +controls_b[CONTROL_INDEX_B] = 65535 +controls_b[CONTROL_INDEX_X] = 65535 +controls_b[CONTROL_INDEX_Y] = 65535 +controls_b[CONTROL_INDEX_L] = 65535 +controls_b[CONTROL_INDEX_R] = 65535 +controls_b[CONTROL_INDEX_START] = 65535 +controls_b[CONTROL_INDEX_SELECT] = 65535 +controls_b[CONTROL_INDEX_HINGE] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_UP] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_DOWN] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_LEFT] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_RIGHT] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_PRESS] = 65535 +controls_b[CONTROL_INDEX_MENU] = 65535 +controls_b[CONTROL_INDEX_SAVE_STATE] = 65535 +controls_b[CONTROL_INDEX_LOAD_STATE] = 65535 +controls_b[CONTROL_INDEX_FAST_FORWARD] = 65535 +controls_b[CONTROL_INDEX_SWAP_SCREENS] = 65535 +controls_b[CONTROL_INDEX_SWAP_ORIENTATION_A] = 65535 +controls_b[CONTROL_INDEX_SWAP_ORIENTATION_B] = 65535 +controls_b[CONTROL_INDEX_LOAD_GAME] = 65535 +controls_b[CONTROL_INDEX_QUIT] = 65535 +controls_b[CONTROL_INDEX_FAKE_MICROPHONE] = 65535 +controls_b[CONTROL_INDEX_UI_UP] = 1217 +controls_b[CONTROL_INDEX_UI_DOWN] = 1153 +controls_b[CONTROL_INDEX_UI_LEFT] = 1216 +controls_b[CONTROL_INDEX_UI_RIGHT] = 1152 +controls_b[CONTROL_INDEX_UI_SELECT] = 1033 +controls_b[CONTROL_INDEX_UI_BACK] = 65535 +controls_b[CONTROL_INDEX_UI_EXIT] = 1032 +controls_b[CONTROL_INDEX_UI_PAGE_UP] = 65535 +controls_b[CONTROL_INDEX_UI_PAGE_DOWN] = 65535 +controls_b[CONTROL_INDEX_UI_SWITCH] = 65535 diff --git a/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3326/drastic.cfg.r33s b/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3326/drastic.cfg.r33s new file mode 100644 index 0000000000..3fb8155c6a --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3326/drastic.cfg.r33s @@ -0,0 +1,111 @@ +frameskip_type = 2 +frameskip_value = 2 +safe_frameskip = 0 +show_frame_counter = 0 +screen_orientation = 0 +screen_swap = 0 +savestate_number = 0 +fast_forward = 0 +enable_sound = 1 +clock_speed = 0 +threaded_3d = 0 +mirror_touch = 0 +compress_savestates = 1 +savestate_snapshot = 1 +unzip_roms = 0 +preload_roms = 0 +backup_in_savestates = 1 +ignore_gamecard_limit = 0 +frame_interval = 0 +trim_roms = 0 +fix_main_2d_screen = 0 +disable_edge_marking = 0 +interframe_blend = 0 +hires_3d = 0 +use_rtc_custom_time = 0 +rtc_custom_time = 0 +rtc_system_time = 0 +slot2_device_type = 0 +rumble_frames = 3 +firmware.username = Dr DraStic +firmware.language = 1 +firmware.favorite_color = 0 +firmware.birthday_month = 1 +firmware.birthday_day = 1 +enable_cheats = 1 +controls_a[CONTROL_INDEX_UP] = 1034 +controls_a[CONTROL_INDEX_DOWN] = 1035 +controls_a[CONTROL_INDEX_LEFT] = 1036 +controls_a[CONTROL_INDEX_RIGHT] = 1037 +controls_a[CONTROL_INDEX_A] = 100 +controls_a[CONTROL_INDEX_B] = 99 +controls_a[CONTROL_INDEX_X] = 122 +controls_a[CONTROL_INDEX_Y] = 118 +controls_a[CONTROL_INDEX_L] = 113 +controls_a[CONTROL_INDEX_R] = 111 +controls_a[CONTROL_INDEX_START] = 1033 +controls_a[CONTROL_INDEX_SELECT] = 101 +controls_a[CONTROL_INDEX_HINGE] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_UP] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_DOWN] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_LEFT] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_RIGHT] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_PRESS] = 65535 +controls_a[CONTROL_INDEX_MENU] = 120 +controls_a[CONTROL_INDEX_SAVE_STATE] = 115 +controls_a[CONTROL_INDEX_LOAD_STATE] = 108 +controls_a[CONTROL_INDEX_FAST_FORWARD] = 116 +controls_a[CONTROL_INDEX_SWAP_SCREENS] = 65535 +controls_a[CONTROL_INDEX_SWAP_ORIENTATION_A] = 112 +controls_a[CONTROL_INDEX_SWAP_ORIENTATION_B] = 110 +controls_a[CONTROL_INDEX_LOAD_GAME] = 65535 +controls_a[CONTROL_INDEX_QUIT] = 65535 +controls_a[CONTROL_INDEX_FAKE_MICROPHONE] = 65535 +controls_a[CONTROL_INDEX_UI_UP] = 338 +controls_a[CONTROL_INDEX_UI_DOWN] = 337 +controls_a[CONTROL_INDEX_UI_LEFT] = 336 +controls_a[CONTROL_INDEX_UI_RIGHT] = 335 +controls_a[CONTROL_INDEX_UI_SELECT] = 13 +controls_a[CONTROL_INDEX_UI_BACK] = 8 +controls_a[CONTROL_INDEX_UI_EXIT] = 27 +controls_a[CONTROL_INDEX_UI_PAGE_UP] = 331 +controls_a[CONTROL_INDEX_UI_PAGE_DOWN] = 334 +controls_a[CONTROL_INDEX_UI_SWITCH] = 481 +controls_b[CONTROL_INDEX_UP] = 65535 +controls_b[CONTROL_INDEX_DOWN] = 65535 +controls_b[CONTROL_INDEX_LEFT] = 65535 +controls_b[CONTROL_INDEX_RIGHT] = 65535 +controls_b[CONTROL_INDEX_A] = 65535 +controls_b[CONTROL_INDEX_B] = 65535 +controls_b[CONTROL_INDEX_X] = 65535 +controls_b[CONTROL_INDEX_Y] = 65535 +controls_b[CONTROL_INDEX_L] = 65535 +controls_b[CONTROL_INDEX_R] = 65535 +controls_b[CONTROL_INDEX_START] = 65535 +controls_b[CONTROL_INDEX_SELECT] = 65535 +controls_b[CONTROL_INDEX_HINGE] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_UP] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_DOWN] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_LEFT] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_RIGHT] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_PRESS] = 65535 +controls_b[CONTROL_INDEX_MENU] = 32 +controls_b[CONTROL_INDEX_SAVE_STATE] = 65535 +controls_b[CONTROL_INDEX_LOAD_STATE] = 65535 +controls_b[CONTROL_INDEX_FAST_FORWARD] = 65535 +controls_b[CONTROL_INDEX_SWAP_SCREENS] = 65535 +controls_b[CONTROL_INDEX_SWAP_ORIENTATION_A] = 65535 +controls_b[CONTROL_INDEX_SWAP_ORIENTATION_B] = 65535 +controls_b[CONTROL_INDEX_LOAD_GAME] = 65535 +controls_b[CONTROL_INDEX_QUIT] = 65535 +controls_b[CONTROL_INDEX_FAKE_MICROPHONE] = 65535 +controls_b[CONTROL_INDEX_UI_UP] = 1034 +controls_b[CONTROL_INDEX_UI_DOWN] = 1035 +controls_b[CONTROL_INDEX_UI_LEFT] = 1036 +controls_b[CONTROL_INDEX_UI_RIGHT] = 1037 +controls_b[CONTROL_INDEX_UI_SELECT] = 1033 +controls_b[CONTROL_INDEX_UI_BACK] = 65535 +controls_b[CONTROL_INDEX_UI_EXIT] = 101 +controls_b[CONTROL_INDEX_UI_PAGE_UP] = 65535 +controls_b[CONTROL_INDEX_UI_PAGE_DOWN] = 65535 +controls_b[CONTROL_INDEX_UI_SWITCH] = 118 diff --git a/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3326/drastic.cfg.r36s b/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3326/drastic.cfg.r36s new file mode 100644 index 0000000000..86d5325010 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3326/drastic.cfg.r36s @@ -0,0 +1,100 @@ +frameskip_type = 2 +frameskip_value = 2 +safe_frameskip = 0 +show_frame_counter = 0 +screen_orientation = 2 +screen_swap = 0 +savestate_number = 1 +fast_forward = 0 +enable_sound = 1 +clock_speed = 0 +threaded_3d = 1 +mirror_touch = 0 +compress_savestates = 1 +savestate_snapshot = 1 +unzip_roms = 0 +preload_roms = 0 +backup_in_savestates = 1 +ignore_gamecard_limit = 0 +frame_interval = 0 +trim_roms = 0 +fix_main_2d_screen = 0 +disable_edge_marking = 0 +interframe_blend = 0 +hires_3d = 0 +use_rtc_custom_time = 0 +rtc_custom_time = 0 +rtc_system_time = 0 +slot2_device_type = 0 +rumble_frames = 3 +firmware.username = Dr DraStic +firmware.language = 1 +firmware.favorite_color = 0 +firmware.birthday_month = 1 +firmware.birthday_day = 1 +enable_cheats = 1 +controls_a[CONTROL_INDEX_UP] = 1037 +controls_a[CONTROL_INDEX_DOWN] = 1038 +controls_a[CONTROL_INDEX_LEFT] = 1039 +controls_a[CONTROL_INDEX_RIGHT] = 1040 +controls_a[CONTROL_INDEX_A] = 1025 +controls_a[CONTROL_INDEX_B] = 1024 +controls_a[CONTROL_INDEX_X] = 1026 +controls_a[CONTROL_INDEX_Y] = 1027 +controls_a[CONTROL_INDEX_L] = 1028 +controls_a[CONTROL_INDEX_R] = 1029 +controls_a[CONTROL_INDEX_START] = 1033 +controls_a[CONTROL_INDEX_SELECT] = 1032 +controls_a[CONTROL_INDEX_HINGE] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_UP] = 1219 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_DOWN] = 1155 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_LEFT] = 1218 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_RIGHT] = 1154 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_PRESS] = 1036 +controls_a[CONTROL_INDEX_MENU] = 1034 +controls_a[CONTROL_INDEX_SAVE_STATE] = 65535 +controls_a[CONTROL_INDEX_LOAD_STATE] = 65535 +controls_a[CONTROL_INDEX_FAST_FORWARD] = 65535 +controls_a[CONTROL_INDEX_SWAP_SCREENS] = 65535 +controls_a[CONTROL_INDEX_SWAP_ORIENTATION_A] = 1030 +controls_a[CONTROL_INDEX_SWAP_ORIENTATION_B] = 1031 +controls_a[CONTROL_INDEX_LOAD_GAME] = 65535 +controls_a[CONTROL_INDEX_QUIT] = 65535 +controls_a[CONTROL_INDEX_FAKE_MICROPHONE] = 65535 +controls_a[CONTROL_INDEX_UI_UP] = 1037 +controls_a[CONTROL_INDEX_UI_DOWN] = 1038 +controls_a[CONTROL_INDEX_UI_LEFT] = 1039 +controls_a[CONTROL_INDEX_UI_RIGHT] = 1040 +controls_a[CONTROL_INDEX_UI_SELECT] = 1025 +controls_a[CONTROL_INDEX_UI_BACK] = 1026 +controls_a[CONTROL_INDEX_UI_EXIT] = 1024 +controls_a[CONTROL_INDEX_UI_PAGE_UP] = 65535 +controls_a[CONTROL_INDEX_UI_PAGE_DOWN] = 65535 +controls_a[CONTROL_INDEX_UI_SWITCH] = 65535 +controls_b[CONTROL_INDEX_UP] = 1217 +controls_b[CONTROL_INDEX_DOWN] = 1153 +controls_b[CONTROL_INDEX_LEFT] = 1216 +controls_b[CONTROL_INDEX_RIGHT] = 1152 +controls_b[CONTROL_INDEX_A] = 65535 +controls_b[CONTROL_INDEX_B] = 65535 +controls_b[CONTROL_INDEX_X] = 65535 +controls_b[CONTROL_INDEX_Y] = 65535 +controls_b[CONTROL_INDEX_L] = 65535 +controls_b[CONTROL_INDEX_R] = 65535 +controls_b[CONTROL_INDEX_START] = 65535 +controls_b[CONTROL_INDEX_SELECT] = 65535 +controls_b[CONTROL_INDEX_HINGE] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_UP] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_DOWN] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_LEFT] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_RIGHT] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_PRESS] = 65535 +controls_b[CONTROL_INDEX_MENU] = 65535 +controls_b[CONTROL_INDEX_SAVE_STATE] = 65535 +controls_b[CONTROL_INDEX_LOAD_STATE] = 65535 +controls_b[CONTROL_INDEX_FAST_FORWARD] = 65535 +controls_b[CONTROL_INDEX_SWAP_SCREENS] = 65535 +controls_b[CONTROL_INDEX_SWAP_ORIENTATION_A] = 65535 +controls_b[CONTROL_INDEX_SWAP_ORIENTATION_B] = 65535 +controls_b[CONTROL_INDEX_LOAD_GAME] = 65535 +controls_b[CONTROL_INDEX_QUIT] = 65535 diff --git a/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3326/drastic.cfg.rgb20s b/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3326/drastic.cfg.rgb20s new file mode 100644 index 0000000000..948b690ea0 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3326/drastic.cfg.rgb20s @@ -0,0 +1,111 @@ +frameskip_type = 2 +frameskip_value = 4 +safe_frameskip = 0 +show_frame_counter = 0 +screen_orientation = 0 +screen_swap = 0 +savestate_number = 0 +fast_forward = 0 +enable_sound = 1 +clock_speed = 0 +threaded_3d = 0 +mirror_touch = 0 +compress_savestates = 1 +savestate_snapshot = 1 +unzip_roms = 0 +preload_roms = 0 +backup_in_savestates = 1 +ignore_gamecard_limit = 0 +frame_interval = 0 +trim_roms = 0 +fix_main_2d_screen = 0 +disable_edge_marking = 0 +interframe_blend = 0 +hires_3d = 0 +use_rtc_custom_time = 0 +rtc_custom_time = 0 +rtc_system_time = 0 +slot2_device_type = 0 +rumble_frames = 3 +firmware.username = Dr DraStic +firmware.language = 1 +firmware.favorite_color = 0 +firmware.birthday_month = 1 +firmware.birthday_day = 1 +enable_cheats = 1 +controls_a[CONTROL_INDEX_UP] = 1032 +controls_a[CONTROL_INDEX_DOWN] = 1033 +controls_a[CONTROL_INDEX_LEFT] = 1034 +controls_a[CONTROL_INDEX_RIGHT] = 1035 +controls_a[CONTROL_INDEX_A] = 1025 +controls_a[CONTROL_INDEX_B] = 1024 +controls_a[CONTROL_INDEX_X] = 1026 +controls_a[CONTROL_INDEX_Y] = 1027 +controls_a[CONTROL_INDEX_L] = 1028 +controls_a[CONTROL_INDEX_R] = 1029 +controls_a[CONTROL_INDEX_START] = 1037 +controls_a[CONTROL_INDEX_SELECT] = 1036 +controls_a[CONTROL_INDEX_HINGE] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_UP] = 1219 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_DOWN] = 1155 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_LEFT] = 1218 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_RIGHT] = 1154 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_PRESS] = 1039 +controls_a[CONTROL_INDEX_MENU] = 1038 +controls_a[CONTROL_INDEX_SAVE_STATE] = 1031 +controls_a[CONTROL_INDEX_LOAD_STATE] = 1030 +controls_a[CONTROL_INDEX_FAST_FORWARD] = 65535 +controls_a[CONTROL_INDEX_SWAP_SCREENS] = 65535 +controls_a[CONTROL_INDEX_SWAP_ORIENTATION_A] = 110 +controls_a[CONTROL_INDEX_SWAP_ORIENTATION_B] = 112 +controls_a[CONTROL_INDEX_LOAD_GAME] = 65535 +controls_a[CONTROL_INDEX_QUIT] = 65535 +controls_a[CONTROL_INDEX_FAKE_MICROPHONE] = 65535 +controls_a[CONTROL_INDEX_UI_UP] = 1032 +controls_a[CONTROL_INDEX_UI_DOWN] = 1033 +controls_a[CONTROL_INDEX_UI_LEFT] = 1034 +controls_a[CONTROL_INDEX_UI_RIGHT] = 1035 +controls_a[CONTROL_INDEX_UI_SELECT] = 1025 +controls_a[CONTROL_INDEX_UI_BACK] = 1026 +controls_a[CONTROL_INDEX_UI_EXIT] = 1024 +controls_a[CONTROL_INDEX_UI_PAGE_UP] = 65535 +controls_a[CONTROL_INDEX_UI_PAGE_DOWN] = 65535 +controls_a[CONTROL_INDEX_UI_SWITCH] = 65535 +controls_b[CONTROL_INDEX_UP] = 1217 +controls_b[CONTROL_INDEX_DOWN] = 1153 +controls_b[CONTROL_INDEX_LEFT] = 1216 +controls_b[CONTROL_INDEX_RIGHT] = 1152 +controls_b[CONTROL_INDEX_A] = 65535 +controls_b[CONTROL_INDEX_B] = 65535 +controls_b[CONTROL_INDEX_X] = 65535 +controls_b[CONTROL_INDEX_Y] = 65535 +controls_b[CONTROL_INDEX_L] = 65535 +controls_b[CONTROL_INDEX_R] = 65535 +controls_b[CONTROL_INDEX_START] = 65535 +controls_b[CONTROL_INDEX_SELECT] = 65535 +controls_b[CONTROL_INDEX_HINGE] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_UP] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_DOWN] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_LEFT] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_RIGHT] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_PRESS] = 65535 +controls_b[CONTROL_INDEX_MENU] = 65535 +controls_b[CONTROL_INDEX_SAVE_STATE] = 65535 +controls_b[CONTROL_INDEX_LOAD_STATE] = 65535 +controls_b[CONTROL_INDEX_FAST_FORWARD] = 65535 +controls_b[CONTROL_INDEX_SWAP_SCREENS] = 65535 +controls_b[CONTROL_INDEX_SWAP_ORIENTATION_A] = 65535 +controls_b[CONTROL_INDEX_SWAP_ORIENTATION_B] = 65535 +controls_b[CONTROL_INDEX_LOAD_GAME] = 65535 +controls_b[CONTROL_INDEX_QUIT] = 65535 +controls_b[CONTROL_INDEX_FAKE_MICROPHONE] = 65535 +controls_b[CONTROL_INDEX_UI_UP] = 1217 +controls_b[CONTROL_INDEX_UI_DOWN] = 1153 +controls_b[CONTROL_INDEX_UI_LEFT] = 1216 +controls_b[CONTROL_INDEX_UI_RIGHT] = 1152 +controls_b[CONTROL_INDEX_UI_SELECT] = 1037 +controls_b[CONTROL_INDEX_UI_BACK] = 65535 +controls_b[CONTROL_INDEX_UI_EXIT] = 1036 +controls_b[CONTROL_INDEX_UI_PAGE_UP] = 65535 +controls_b[CONTROL_INDEX_UI_PAGE_DOWN] = 65535 +controls_b[CONTROL_INDEX_UI_SWITCH] = 65535 diff --git a/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3326/drastic.cfg.s1_f2 b/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3326/drastic.cfg.s1_f2 new file mode 100644 index 0000000000..0a78f97e62 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3326/drastic.cfg.s1_f2 @@ -0,0 +1,111 @@ +frameskip_type = 2 +frameskip_value = 2 +safe_frameskip = 0 +show_frame_counter = 0 +screen_orientation = 2 +screen_swap = 0 +savestate_number = 0 +fast_forward = 0 +enable_sound = 1 +clock_speed = 0 +threaded_3d = 1 +mirror_touch = 0 +compress_savestates = 1 +savestate_snapshot = 1 +unzip_roms = 0 +preload_roms = 0 +backup_in_savestates = 1 +ignore_gamecard_limit = 0 +frame_interval = 0 +trim_roms = 0 +fix_main_2d_screen = 0 +disable_edge_marking = 0 +interframe_blend = 0 +hires_3d = 0 +use_rtc_custom_time = 0 +rtc_custom_time = 0 +rtc_system_time = 0 +slot2_device_type = 0 +rumble_frames = 3 +firmware.username = Dr DraStic +firmware.language = 1 +firmware.favorite_color = 0 +firmware.birthday_month = 1 +firmware.birthday_day = 1 +enable_cheats = 1 +controls_a[CONTROL_INDEX_UP] = 1037 +controls_a[CONTROL_INDEX_DOWN] = 1038 +controls_a[CONTROL_INDEX_LEFT] = 1039 +controls_a[CONTROL_INDEX_RIGHT] = 1040 +controls_a[CONTROL_INDEX_A] = 99 +controls_a[CONTROL_INDEX_B] = 100 +controls_a[CONTROL_INDEX_X] = 122 +controls_a[CONTROL_INDEX_Y] = 118 +controls_a[CONTROL_INDEX_L] = 113 +controls_a[CONTROL_INDEX_R] = 111 +controls_a[CONTROL_INDEX_START] = 1033 +controls_a[CONTROL_INDEX_SELECT] = 1032 +controls_a[CONTROL_INDEX_HINGE] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_UP] = 1217 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_DOWN] = 1153 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_LEFT] = 1216 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_RIGHT] = 1152 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_PRESS] = 1035 +controls_a[CONTROL_INDEX_MENU] = 1034 +controls_a[CONTROL_INDEX_SAVE_STATE] = 65535 +controls_a[CONTROL_INDEX_LOAD_STATE] = 65535 +controls_a[CONTROL_INDEX_FAST_FORWARD] = 1036 +controls_a[CONTROL_INDEX_SWAP_SCREENS] = 65535 +controls_a[CONTROL_INDEX_SWAP_ORIENTATION_A] = 1030 +controls_a[CONTROL_INDEX_SWAP_ORIENTATION_B] = 1031 +controls_a[CONTROL_INDEX_LOAD_GAME] = 65535 +controls_a[CONTROL_INDEX_QUIT] = 65535 +controls_a[CONTROL_INDEX_FAKE_MICROPHONE] = 65535 +controls_a[CONTROL_INDEX_UI_UP] = 1032 +controls_a[CONTROL_INDEX_UI_DOWN] = 1033 +controls_a[CONTROL_INDEX_UI_LEFT] = 1034 +controls_a[CONTROL_INDEX_UI_RIGHT] = 1035 +controls_a[CONTROL_INDEX_UI_SELECT] = 1025 +controls_a[CONTROL_INDEX_UI_BACK] = 65535 +controls_a[CONTROL_INDEX_UI_EXIT] = 1024 +controls_a[CONTROL_INDEX_UI_PAGE_UP] = 65535 +controls_a[CONTROL_INDEX_UI_PAGE_DOWN] = 65535 +controls_a[CONTROL_INDEX_UI_SWITCH] = 65535 +controls_b[CONTROL_INDEX_UP] = 65535 +controls_b[CONTROL_INDEX_DOWN] = 65535 +controls_b[CONTROL_INDEX_LEFT] = 65535 +controls_b[CONTROL_INDEX_RIGHT] = 65535 +controls_b[CONTROL_INDEX_A] = 65535 +controls_b[CONTROL_INDEX_B] = 65535 +controls_b[CONTROL_INDEX_X] = 65535 +controls_b[CONTROL_INDEX_Y] = 65535 +controls_b[CONTROL_INDEX_L] = 65535 +controls_b[CONTROL_INDEX_R] = 65535 +controls_b[CONTROL_INDEX_START] = 65535 +controls_b[CONTROL_INDEX_SELECT] = 65535 +controls_b[CONTROL_INDEX_HINGE] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_UP] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_DOWN] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_LEFT] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_RIGHT] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_PRESS] = 65535 +controls_b[CONTROL_INDEX_MENU] = 65535 +controls_b[CONTROL_INDEX_SAVE_STATE] = 65535 +controls_b[CONTROL_INDEX_LOAD_STATE] = 65535 +controls_b[CONTROL_INDEX_FAST_FORWARD] = 65535 +controls_b[CONTROL_INDEX_SWAP_SCREENS] = 65535 +controls_b[CONTROL_INDEX_SWAP_ORIENTATION_A] = 65535 +controls_b[CONTROL_INDEX_SWAP_ORIENTATION_B] = 65535 +controls_b[CONTROL_INDEX_LOAD_GAME] = 65535 +controls_b[CONTROL_INDEX_QUIT] = 65535 +controls_b[CONTROL_INDEX_FAKE_MICROPHONE] = 65535 +controls_b[CONTROL_INDEX_UI_UP] = 1217 +controls_b[CONTROL_INDEX_UI_DOWN] = 1153 +controls_b[CONTROL_INDEX_UI_LEFT] = 1216 +controls_b[CONTROL_INDEX_UI_RIGHT] = 1152 +controls_b[CONTROL_INDEX_UI_SELECT] = 65535 +controls_b[CONTROL_INDEX_UI_BACK] = 65535 +controls_b[CONTROL_INDEX_UI_EXIT] = 65535 +controls_b[CONTROL_INDEX_UI_PAGE_UP] = 65535 +controls_b[CONTROL_INDEX_UI_PAGE_DOWN] = 65535 +controls_b[CONTROL_INDEX_UI_SWITCH] = 65535 diff --git a/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3326/drastic.cfg.xut b/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3326/drastic.cfg.xut new file mode 100644 index 0000000000..f9561a081a --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3326/drastic.cfg.xut @@ -0,0 +1,111 @@ +frameskip_type = 2 +frameskip_value = 2 +safe_frameskip = 0 +show_frame_counter = 0 +screen_orientation = 2 +screen_swap = 0 +savestate_number = 0 +fast_forward = 0 +enable_sound = 1 +clock_speed = 0 +threaded_3d = 0 +mirror_touch = 0 +compress_savestates = 1 +savestate_snapshot = 1 +unzip_roms = 0 +preload_roms = 0 +backup_in_savestates = 1 +ignore_gamecard_limit = 0 +frame_interval = 0 +trim_roms = 0 +fix_main_2d_screen = 0 +disable_edge_marking = 0 +interframe_blend = 0 +hires_3d = 0 +use_rtc_custom_time = 0 +rtc_custom_time = 0 +rtc_system_time = 0 +slot2_device_type = 0 +rumble_frames = 3 +firmware.username = Dr DraStic +firmware.language = 1 +firmware.favorite_color = 0 +firmware.birthday_month = 1 +firmware.birthday_day = 1 +enable_cheats = 1 +controls_a[CONTROL_INDEX_UP] = 338 +controls_a[CONTROL_INDEX_DOWN] = 337 +controls_a[CONTROL_INDEX_LEFT] = 336 +controls_a[CONTROL_INDEX_RIGHT] = 335 +controls_a[CONTROL_INDEX_A] = 32 +controls_a[CONTROL_INDEX_B] = 480 +controls_a[CONTROL_INDEX_X] = 122 +controls_a[CONTROL_INDEX_Y] = 120 +controls_a[CONTROL_INDEX_L] = 481 +controls_a[CONTROL_INDEX_R] = 99 +controls_a[CONTROL_INDEX_START] = 13 +controls_a[CONTROL_INDEX_SELECT] = 485 +controls_a[CONTROL_INDEX_HINGE] = 104 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_UP] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_DOWN] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_LEFT] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_RIGHT] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_PRESS] = 65535 +controls_a[CONTROL_INDEX_MENU] = 65535 +controls_a[CONTROL_INDEX_SAVE_STATE] = 65535 +controls_a[CONTROL_INDEX_LOAD_STATE] = 65535 +controls_a[CONTROL_INDEX_FAST_FORWARD] = 65535 +controls_a[CONTROL_INDEX_SWAP_SCREENS] = 65535 +controls_a[CONTROL_INDEX_SWAP_ORIENTATION_A] = 65535 +controls_a[CONTROL_INDEX_SWAP_ORIENTATION_B] = 65535 +controls_a[CONTROL_INDEX_LOAD_GAME] = 65535 +controls_a[CONTROL_INDEX_QUIT] = 65535 +controls_a[CONTROL_INDEX_FAKE_MICROPHONE] = 65535 +controls_a[CONTROL_INDEX_UI_UP] = 338 +controls_a[CONTROL_INDEX_UI_DOWN] = 337 +controls_a[CONTROL_INDEX_UI_LEFT] = 336 +controls_a[CONTROL_INDEX_UI_RIGHT] = 335 +controls_a[CONTROL_INDEX_UI_SELECT] = 13 +controls_a[CONTROL_INDEX_UI_BACK] = 8 +controls_a[CONTROL_INDEX_UI_EXIT] = 27 +controls_a[CONTROL_INDEX_UI_PAGE_UP] = 331 +controls_a[CONTROL_INDEX_UI_PAGE_DOWN] = 334 +controls_a[CONTROL_INDEX_UI_SWITCH] = 481 +controls_b[CONTROL_INDEX_UP] = 1036 +controls_b[CONTROL_INDEX_DOWN] = 1037 +controls_b[CONTROL_INDEX_LEFT] = 1038 +controls_b[CONTROL_INDEX_RIGHT] = 1039 +controls_b[CONTROL_INDEX_A] = 1026 +controls_b[CONTROL_INDEX_B] = 1025 +controls_b[CONTROL_INDEX_X] = 1027 +controls_b[CONTROL_INDEX_Y] = 1024 +controls_b[CONTROL_INDEX_L] = 1028 +controls_b[CONTROL_INDEX_R] = 1029 +controls_b[CONTROL_INDEX_START] = 1033 +controls_b[CONTROL_INDEX_SELECT] = 1032 +controls_b[CONTROL_INDEX_HINGE] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_UP] = 1219 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_DOWN] = 1155 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_LEFT] = 1218 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_RIGHT] = 1154 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_PRESS] = 1035 +controls_b[CONTROL_INDEX_MENU] = 1040 +controls_b[CONTROL_INDEX_SAVE_STATE] = 65535 +controls_b[CONTROL_INDEX_LOAD_STATE] = 65535 +controls_b[CONTROL_INDEX_FAST_FORWARD] = 65535 +controls_b[CONTROL_INDEX_SWAP_SCREENS] = 65535 +controls_b[CONTROL_INDEX_SWAP_ORIENTATION_A] = 1031 +controls_b[CONTROL_INDEX_SWAP_ORIENTATION_B] = 1030 +controls_b[CONTROL_INDEX_LOAD_GAME] = 65535 +controls_b[CONTROL_INDEX_QUIT] = 65535 +controls_b[CONTROL_INDEX_FAKE_MICROPHONE] = 65535 +controls_b[CONTROL_INDEX_UI_UP] = 1036 +controls_b[CONTROL_INDEX_UI_DOWN] = 1037 +controls_b[CONTROL_INDEX_UI_LEFT] = 1038 +controls_b[CONTROL_INDEX_UI_RIGHT] = 1039 +controls_b[CONTROL_INDEX_UI_SELECT] = 1026 +controls_b[CONTROL_INDEX_UI_BACK] = 1025 +controls_b[CONTROL_INDEX_UI_EXIT] = 1024 +controls_b[CONTROL_INDEX_UI_PAGE_UP] = 1029 +controls_b[CONTROL_INDEX_UI_PAGE_DOWN] = 1028 +controls_b[CONTROL_INDEX_UI_SWITCH] = 1027 diff --git a/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3399/drastic.cfg b/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3399/drastic.cfg new file mode 100644 index 0000000000..bf348a0155 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3399/drastic.cfg @@ -0,0 +1,111 @@ +frameskip_type = 0 +frameskip_value = 4 +safe_frameskip = 0 +show_frame_counter = 0 +screen_orientation = 0 +screen_swap = 0 +savestate_number = 0 +fast_forward = 0 +enable_sound = 1 +clock_speed = 0 +threaded_3d = 0 +mirror_touch = 0 +compress_savestates = 1 +savestate_snapshot = 1 +unzip_roms = 0 +preload_roms = 0 +backup_in_savestates = 1 +ignore_gamecard_limit = 0 +frame_interval = 0 +trim_roms = 0 +fix_main_2d_screen = 0 +disable_edge_marking = 0 +interframe_blend = 0 +hires_3d = 1 +use_rtc_custom_time = 0 +rtc_custom_time = 0 +rtc_system_time = 0 +slot2_device_type = 0 +rumble_frames = 3 +firmware.username = Dr DraStic +firmware.language = 1 +firmware.favorite_color = 0 +firmware.birthday_month = 1 +firmware.birthday_day = 1 +enable_cheats = 1 +controls_a[CONTROL_INDEX_UP] = 1217 +controls_a[CONTROL_INDEX_DOWN] = 1153 +controls_a[CONTROL_INDEX_LEFT] = 1216 +controls_a[CONTROL_INDEX_RIGHT] = 1152 +controls_a[CONTROL_INDEX_A] = 65535 +controls_a[CONTROL_INDEX_B] = 65535 +controls_a[CONTROL_INDEX_X] = 65535 +controls_a[CONTROL_INDEX_Y] = 65535 +controls_a[CONTROL_INDEX_L] = 65535 +controls_a[CONTROL_INDEX_R] = 65535 +controls_a[CONTROL_INDEX_START] = 65535 +controls_a[CONTROL_INDEX_SELECT] = 65535 +controls_a[CONTROL_INDEX_HINGE] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_UP] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_DOWN] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_LEFT] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_RIGHT] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_PRESS] = 65535 +controls_a[CONTROL_INDEX_MENU] = 120 +controls_a[CONTROL_INDEX_SAVE_STATE] = 115 +controls_a[CONTROL_INDEX_LOAD_STATE] = 108 +controls_a[CONTROL_INDEX_FAST_FORWARD] = 116 +controls_a[CONTROL_INDEX_SWAP_SCREENS] = 109 +controls_a[CONTROL_INDEX_SWAP_ORIENTATION_A] = 65535 +controls_a[CONTROL_INDEX_SWAP_ORIENTATION_B] = 65535 +controls_a[CONTROL_INDEX_LOAD_GAME] = 65535 +controls_a[CONTROL_INDEX_QUIT] = 65535 +controls_a[CONTROL_INDEX_FAKE_MICROPHONE] = 65535 +controls_a[CONTROL_INDEX_UI_UP] = 1217 +controls_a[CONTROL_INDEX_UI_DOWN] = 1153 +controls_a[CONTROL_INDEX_UI_LEFT] = 1216 +controls_a[CONTROL_INDEX_UI_RIGHT] = 1152 +controls_a[CONTROL_INDEX_UI_SELECT] = 65535 +controls_a[CONTROL_INDEX_UI_BACK] = 65535 +controls_a[CONTROL_INDEX_UI_EXIT] = 65535 +controls_a[CONTROL_INDEX_UI_PAGE_UP] = 65535 +controls_a[CONTROL_INDEX_UI_PAGE_DOWN] = 65535 +controls_a[CONTROL_INDEX_UI_SWITCH] = 65535 +controls_b[CONTROL_INDEX_UP] = 1037 +controls_b[CONTROL_INDEX_DOWN] = 1038 +controls_b[CONTROL_INDEX_LEFT] = 1039 +controls_b[CONTROL_INDEX_RIGHT] = 1040 +controls_b[CONTROL_INDEX_A] = 1025 +controls_b[CONTROL_INDEX_B] = 1024 +controls_b[CONTROL_INDEX_X] = 1026 +controls_b[CONTROL_INDEX_Y] = 1027 +controls_b[CONTROL_INDEX_L] = 1028 +controls_b[CONTROL_INDEX_R] = 1029 +controls_b[CONTROL_INDEX_START] = 1033 +controls_b[CONTROL_INDEX_SELECT] = 1032 +controls_b[CONTROL_INDEX_HINGE] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_UP] = 1219 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_DOWN] = 1155 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_LEFT] = 1218 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_RIGHT] = 1154 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_PRESS] = 1036 +controls_b[CONTROL_INDEX_MENU] = 1035 +controls_b[CONTROL_INDEX_SAVE_STATE] = 65535 +controls_b[CONTROL_INDEX_LOAD_STATE] = 65535 +controls_b[CONTROL_INDEX_FAST_FORWARD] = 65535 +controls_b[CONTROL_INDEX_SWAP_SCREENS] = 65535 +controls_b[CONTROL_INDEX_SWAP_ORIENTATION_A] = 1030 +controls_b[CONTROL_INDEX_SWAP_ORIENTATION_B] = 1031 +controls_b[CONTROL_INDEX_LOAD_GAME] = 65535 +controls_b[CONTROL_INDEX_QUIT] = 65535 +controls_b[CONTROL_INDEX_FAKE_MICROPHONE] = 65535 +controls_b[CONTROL_INDEX_UI_UP] = 1037 +controls_b[CONTROL_INDEX_UI_DOWN] = 1038 +controls_b[CONTROL_INDEX_UI_LEFT] = 1039 +controls_b[CONTROL_INDEX_UI_RIGHT] = 1040 +controls_b[CONTROL_INDEX_UI_SELECT] = 1025 +controls_b[CONTROL_INDEX_UI_BACK] = 65535 +controls_b[CONTROL_INDEX_UI_EXIT] = 1024 +controls_b[CONTROL_INDEX_UI_PAGE_UP] = 65535 +controls_b[CONTROL_INDEX_UI_PAGE_DOWN] = 65535 +controls_b[CONTROL_INDEX_UI_SWITCH] = 65535 diff --git a/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3566/drastic.cfg b/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3566/drastic.cfg new file mode 100644 index 0000000000..83c8ed1cf8 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3566/drastic.cfg @@ -0,0 +1,111 @@ +frameskip_type = 0 +frameskip_value = 1 +safe_frameskip = 1 +show_frame_counter = 0 +screen_orientation = 0 +screen_swap = 0 +savestate_number = 0 +fast_forward = 0 +enable_sound = 1 +clock_speed = 0 +threaded_3d = 1 +mirror_touch = 0 +compress_savestates = 1 +savestate_snapshot = 1 +unzip_roms = 0 +preload_roms = 0 +backup_in_savestates = 1 +ignore_gamecard_limit = 0 +frame_interval = 0 +trim_roms = 0 +fix_main_2d_screen = 0 +disable_edge_marking = 0 +interframe_blend = 0 +hires_3d = 1 +use_rtc_custom_time = 0 +rtc_custom_time = 0 +rtc_system_time = 0 +slot2_device_type = 0 +rumble_frames = 3 +firmware.username = Dr DraStic +firmware.language = 1 +firmware.favorite_color = 0 +firmware.birthday_month = 1 +firmware.birthday_day = 1 +enable_cheats = 1 +controls_a[CONTROL_INDEX_UP] = 1217 +controls_a[CONTROL_INDEX_DOWN] = 1153 +controls_a[CONTROL_INDEX_LEFT] = 1216 +controls_a[CONTROL_INDEX_RIGHT] = 1152 +controls_a[CONTROL_INDEX_A] = 65535 +controls_a[CONTROL_INDEX_B] = 65535 +controls_a[CONTROL_INDEX_X] = 65535 +controls_a[CONTROL_INDEX_Y] = 65535 +controls_a[CONTROL_INDEX_L] = 65535 +controls_a[CONTROL_INDEX_R] = 65535 +controls_a[CONTROL_INDEX_START] = 65535 +controls_a[CONTROL_INDEX_SELECT] = 65535 +controls_a[CONTROL_INDEX_HINGE] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_UP] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_DOWN] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_LEFT] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_RIGHT] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_PRESS] = 65535 +controls_a[CONTROL_INDEX_MENU] = 65535 +controls_a[CONTROL_INDEX_SAVE_STATE] = 65535 +controls_a[CONTROL_INDEX_LOAD_STATE] = 65535 +controls_a[CONTROL_INDEX_FAST_FORWARD] = 65535 +controls_a[CONTROL_INDEX_SWAP_SCREENS] = 65535 +controls_a[CONTROL_INDEX_SWAP_ORIENTATION_A] = 65535 +controls_a[CONTROL_INDEX_SWAP_ORIENTATION_B] = 65535 +controls_a[CONTROL_INDEX_LOAD_GAME] = 65535 +controls_a[CONTROL_INDEX_QUIT] = 65535 +controls_a[CONTROL_INDEX_FAKE_MICROPHONE] = 65535 +controls_a[CONTROL_INDEX_UI_UP] = 1217 +controls_a[CONTROL_INDEX_UI_DOWN] = 1153 +controls_a[CONTROL_INDEX_UI_LEFT] = 1216 +controls_a[CONTROL_INDEX_UI_RIGHT] = 1152 +controls_a[CONTROL_INDEX_UI_SELECT] = 65535 +controls_a[CONTROL_INDEX_UI_BACK] = 65535 +controls_a[CONTROL_INDEX_UI_EXIT] = 65535 +controls_a[CONTROL_INDEX_UI_PAGE_UP] = 65535 +controls_a[CONTROL_INDEX_UI_PAGE_DOWN] = 65535 +controls_a[CONTROL_INDEX_UI_SWITCH] = 65535 +controls_b[CONTROL_INDEX_UP] = 1037 +controls_b[CONTROL_INDEX_DOWN] = 1038 +controls_b[CONTROL_INDEX_LEFT] = 1039 +controls_b[CONTROL_INDEX_RIGHT] = 1040 +controls_b[CONTROL_INDEX_A] = 1025 +controls_b[CONTROL_INDEX_B] = 1024 +controls_b[CONTROL_INDEX_X] = 1026 +controls_b[CONTROL_INDEX_Y] = 1027 +controls_b[CONTROL_INDEX_L] = 1028 +controls_b[CONTROL_INDEX_R] = 1029 +controls_b[CONTROL_INDEX_START] = 1033 +controls_b[CONTROL_INDEX_SELECT] = 1032 +controls_b[CONTROL_INDEX_HINGE] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_UP] = 1219 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_DOWN] = 1155 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_LEFT] = 1218 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_RIGHT] = 1154 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_PRESS] = 1036 +controls_b[CONTROL_INDEX_MENU] = 1035 +controls_b[CONTROL_INDEX_SAVE_STATE] = 65535 +controls_b[CONTROL_INDEX_LOAD_STATE] = 65535 +controls_b[CONTROL_INDEX_FAST_FORWARD] = 65535 +controls_b[CONTROL_INDEX_SWAP_SCREENS] = 65535 +controls_b[CONTROL_INDEX_SWAP_ORIENTATION_A] = 1030 +controls_b[CONTROL_INDEX_SWAP_ORIENTATION_B] = 1031 +controls_b[CONTROL_INDEX_LOAD_GAME] = 65535 +controls_b[CONTROL_INDEX_QUIT] = 65535 +controls_b[CONTROL_INDEX_FAKE_MICROPHONE] = 65535 +controls_b[CONTROL_INDEX_UI_UP] = 1037 +controls_b[CONTROL_INDEX_UI_DOWN] = 1038 +controls_b[CONTROL_INDEX_UI_LEFT] = 1039 +controls_b[CONTROL_INDEX_UI_RIGHT] = 1040 +controls_b[CONTROL_INDEX_UI_SELECT] = 1025 +controls_b[CONTROL_INDEX_UI_BACK] = 65535 +controls_b[CONTROL_INDEX_UI_EXIT] = 1024 +controls_b[CONTROL_INDEX_UI_PAGE_UP] = 65535 +controls_b[CONTROL_INDEX_UI_PAGE_DOWN] = 65535 +controls_b[CONTROL_INDEX_UI_SWITCH] = 65535 diff --git a/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3566/drastic.cfg.arc b/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3566/drastic.cfg.arc new file mode 100644 index 0000000000..3c98537dcd --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3566/drastic.cfg.arc @@ -0,0 +1,111 @@ +frameskip_type = 0 +frameskip_value = 1 +safe_frameskip = 1 +show_frame_counter = 0 +screen_orientation = 3 +screen_swap = 0 +savestate_number = 0 +fast_forward = 0 +enable_sound = 1 +clock_speed = 0 +threaded_3d = 1 +mirror_touch = 0 +compress_savestates = 1 +savestate_snapshot = 1 +unzip_roms = 0 +preload_roms = 0 +backup_in_savestates = 1 +ignore_gamecard_limit = 0 +frame_interval = 0 +trim_roms = 0 +fix_main_2d_screen = 0 +disable_edge_marking = 0 +interframe_blend = 0 +hires_3d = 1 +use_rtc_custom_time = 0 +rtc_custom_time = 0 +rtc_system_time = 0 +slot2_device_type = 0 +rumble_frames = 3 +firmware.username = Dr DraStic +firmware.language = 1 +firmware.favorite_color = 0 +firmware.birthday_month = 1 +firmware.birthday_day = 1 +enable_cheats = 1 +controls_a[CONTROL_INDEX_UP] = 1036 +controls_a[CONTROL_INDEX_DOWN] = 1037 +controls_a[CONTROL_INDEX_LEFT] = 1038 +controls_a[CONTROL_INDEX_RIGHT] = 1039 +controls_a[CONTROL_INDEX_A] = 100 +controls_a[CONTROL_INDEX_B] = 99 +controls_a[CONTROL_INDEX_X] = 122 +controls_a[CONTROL_INDEX_Y] = 118 +controls_a[CONTROL_INDEX_L] = 113 +controls_a[CONTROL_INDEX_R] = 111 +controls_a[CONTROL_INDEX_START] = 1035 +controls_a[CONTROL_INDEX_SELECT] = 1034 +controls_a[CONTROL_INDEX_HINGE] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_UP] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_DOWN] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_LEFT] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_RIGHT] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_PRESS] = 65535 +controls_a[CONTROL_INDEX_MENU] = 1029 +controls_a[CONTROL_INDEX_SAVE_STATE] = 65535 +controls_a[CONTROL_INDEX_LOAD_STATE] = 65535 +controls_a[CONTROL_INDEX_FAST_FORWARD] = 65535 +controls_a[CONTROL_INDEX_SWAP_SCREENS] = 65535 +controls_a[CONTROL_INDEX_SWAP_ORIENTATION_A] = 110 +controls_a[CONTROL_INDEX_SWAP_ORIENTATION_B] = 112 +controls_a[CONTROL_INDEX_LOAD_GAME] = 65535 +controls_a[CONTROL_INDEX_QUIT] = 65535 +controls_a[CONTROL_INDEX_FAKE_MICROPHONE] = 65535 +controls_a[CONTROL_INDEX_UI_UP] = 1036 +controls_a[CONTROL_INDEX_UI_DOWN] = 1037 +controls_a[CONTROL_INDEX_UI_LEFT] = 1038 +controls_a[CONTROL_INDEX_UI_RIGHT] = 1039 +controls_a[CONTROL_INDEX_UI_SELECT] = 1024 +controls_a[CONTROL_INDEX_UI_BACK] = 65535 +controls_a[CONTROL_INDEX_UI_EXIT] = 65535 +controls_a[CONTROL_INDEX_UI_PAGE_UP] = 65535 +controls_a[CONTROL_INDEX_UI_PAGE_DOWN] = 65535 +controls_a[CONTROL_INDEX_UI_SWITCH] = 65535 +controls_b[CONTROL_INDEX_UP] = 1036 +controls_b[CONTROL_INDEX_DOWN] = 1037 +controls_b[CONTROL_INDEX_LEFT] = 1038 +controls_b[CONTROL_INDEX_RIGHT] = 1039 +controls_b[CONTROL_INDEX_A] = 100 +controls_b[CONTROL_INDEX_B] = 99 +controls_b[CONTROL_INDEX_X] = 122 +controls_b[CONTROL_INDEX_Y] = 118 +controls_b[CONTROL_INDEX_L] = 113 +controls_b[CONTROL_INDEX_R] = 111 +controls_b[CONTROL_INDEX_START] = 1035 +controls_b[CONTROL_INDEX_SELECT] = 1034 +controls_b[CONTROL_INDEX_HINGE] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_UP] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_DOWN] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_LEFT] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_RIGHT] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_PRESS] = 65535 +controls_b[CONTROL_INDEX_MENU] = 1029 +controls_b[CONTROL_INDEX_SAVE_STATE] = 65535 +controls_b[CONTROL_INDEX_LOAD_STATE] = 65535 +controls_b[CONTROL_INDEX_FAST_FORWARD] = 65535 +controls_b[CONTROL_INDEX_SWAP_SCREENS] = 65535 +controls_b[CONTROL_INDEX_SWAP_ORIENTATION_A] = 110 +controls_b[CONTROL_INDEX_SWAP_ORIENTATION_B] = 112 +controls_b[CONTROL_INDEX_LOAD_GAME] = 65535 +controls_b[CONTROL_INDEX_QUIT] = 65535 +controls_b[CONTROL_INDEX_FAKE_MICROPHONE] = 65535 +controls_b[CONTROL_INDEX_UI_UP] = 1036 +controls_b[CONTROL_INDEX_UI_DOWN] = 1037 +controls_b[CONTROL_INDEX_UI_LEFT] = 1038 +controls_b[CONTROL_INDEX_UI_RIGHT] = 1039 +controls_b[CONTROL_INDEX_UI_SELECT] = 65535 +controls_b[CONTROL_INDEX_UI_BACK] = 65535 +controls_b[CONTROL_INDEX_UI_EXIT] = 65535 +controls_b[CONTROL_INDEX_UI_PAGE_UP] = 65535 +controls_b[CONTROL_INDEX_UI_PAGE_DOWN] = 65535 +controls_b[CONTROL_INDEX_UI_SWITCH] = 65535 diff --git a/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3566/drastic.cfg.rgds b/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3566/drastic.cfg.rgds new file mode 100644 index 0000000000..dc74b4d149 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3566/drastic.cfg.rgds @@ -0,0 +1,111 @@ +frameskip_type = 0 +frameskip_value = 1 +safe_frameskip = 1 +show_frame_counter = 0 +screen_orientation = 1 +screen_swap = 0 +savestate_number = 0 +fast_forward = 0 +enable_sound = 1 +clock_speed = 0 +threaded_3d = 0 +mirror_touch = 0 +compress_savestates = 1 +savestate_snapshot = 1 +unzip_roms = 0 +preload_roms = 0 +backup_in_savestates = 1 +ignore_gamecard_limit = 0 +frame_interval = 0 +trim_roms = 0 +fix_main_2d_screen = 0 +disable_edge_marking = 0 +interframe_blend = 0 +hires_3d = 0 +use_rtc_custom_time = 0 +rtc_custom_time = 0 +rtc_system_time = 0 +slot2_device_type = 0 +rumble_frames = 3 +firmware.username = Dr DraStic +firmware.language = 1 +firmware.favorite_color = 0 +firmware.birthday_month = 1 +firmware.birthday_day = 1 +enable_cheats = 1 +controls_a[CONTROL_INDEX_UP] = 1217 +controls_a[CONTROL_INDEX_DOWN] = 1153 +controls_a[CONTROL_INDEX_LEFT] = 1216 +controls_a[CONTROL_INDEX_RIGHT] = 1152 +controls_a[CONTROL_INDEX_A] = 65535 +controls_a[CONTROL_INDEX_B] = 65535 +controls_a[CONTROL_INDEX_X] = 65535 +controls_a[CONTROL_INDEX_Y] = 65535 +controls_a[CONTROL_INDEX_L] = 65535 +controls_a[CONTROL_INDEX_R] = 65535 +controls_a[CONTROL_INDEX_START] = 65535 +controls_a[CONTROL_INDEX_SELECT] = 65535 +controls_a[CONTROL_INDEX_HINGE] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_UP] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_DOWN] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_LEFT] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_RIGHT] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_PRESS] = 65535 +controls_a[CONTROL_INDEX_MENU] = 1035 +controls_a[CONTROL_INDEX_SAVE_STATE] = 1031 +controls_a[CONTROL_INDEX_LOAD_STATE] = 1030 +controls_a[CONTROL_INDEX_FAST_FORWARD] = 1036 +controls_a[CONTROL_INDEX_SWAP_SCREENS] = 65535 +controls_a[CONTROL_INDEX_SWAP_ORIENTATION_A] = 65535 +controls_a[CONTROL_INDEX_SWAP_ORIENTATION_B] = 65535 +controls_a[CONTROL_INDEX_LOAD_GAME] = 65535 +controls_a[CONTROL_INDEX_QUIT] = 65535 +controls_a[CONTROL_INDEX_FAKE_MICROPHONE] = 327 +controls_a[CONTROL_INDEX_UI_UP] = 1217 +controls_a[CONTROL_INDEX_UI_DOWN] = 1153 +controls_a[CONTROL_INDEX_UI_LEFT] = 1216 +controls_a[CONTROL_INDEX_UI_RIGHT] = 1152 +controls_a[CONTROL_INDEX_UI_SELECT] = 65535 +controls_a[CONTROL_INDEX_UI_BACK] = 65535 +controls_a[CONTROL_INDEX_UI_EXIT] = 65535 +controls_a[CONTROL_INDEX_UI_PAGE_UP] = 65535 +controls_a[CONTROL_INDEX_UI_PAGE_DOWN] = 65535 +controls_a[CONTROL_INDEX_UI_SWITCH] = 65535 +controls_b[CONTROL_INDEX_UP] = 1037 +controls_b[CONTROL_INDEX_DOWN] = 1038 +controls_b[CONTROL_INDEX_LEFT] = 1039 +controls_b[CONTROL_INDEX_RIGHT] = 1040 +controls_b[CONTROL_INDEX_A] = 1025 +controls_b[CONTROL_INDEX_B] = 1024 +controls_b[CONTROL_INDEX_X] = 1026 +controls_b[CONTROL_INDEX_Y] = 1027 +controls_b[CONTROL_INDEX_L] = 1028 +controls_b[CONTROL_INDEX_R] = 1029 +controls_b[CONTROL_INDEX_START] = 1033 +controls_b[CONTROL_INDEX_SELECT] = 1032 +controls_b[CONTROL_INDEX_HINGE] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_UP] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_DOWN] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_LEFT] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_RIGHT] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_PRESS] = 65535 +controls_b[CONTROL_INDEX_MENU] = 1035 +controls_b[CONTROL_INDEX_SAVE_STATE] = 1031 +controls_b[CONTROL_INDEX_LOAD_STATE] = 1030 +controls_b[CONTROL_INDEX_FAST_FORWARD] = 1036 +controls_b[CONTROL_INDEX_SWAP_SCREENS] = 65535 +controls_b[CONTROL_INDEX_SWAP_ORIENTATION_A] = 65535 +controls_b[CONTROL_INDEX_SWAP_ORIENTATION_B] = 65535 +controls_b[CONTROL_INDEX_LOAD_GAME] = 65535 +controls_b[CONTROL_INDEX_QUIT] = 65535 +controls_b[CONTROL_INDEX_FAKE_MICROPHONE] = 327 +controls_b[CONTROL_INDEX_UI_UP] = 1037 +controls_b[CONTROL_INDEX_UI_DOWN] = 1038 +controls_b[CONTROL_INDEX_UI_LEFT] = 1039 +controls_b[CONTROL_INDEX_UI_RIGHT] = 1040 +controls_b[CONTROL_INDEX_UI_SELECT] = 1025 +controls_b[CONTROL_INDEX_UI_BACK] = 65535 +controls_b[CONTROL_INDEX_UI_EXIT] = 1024 +controls_b[CONTROL_INDEX_UI_PAGE_UP] = 65535 +controls_b[CONTROL_INDEX_UI_PAGE_DOWN] = 65535 +controls_b[CONTROL_INDEX_UI_SWITCH] = 65535 diff --git a/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3588/drastic.cfg b/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3588/drastic.cfg new file mode 100644 index 0000000000..2faa194290 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/drastic-sa/config/RK3588/drastic.cfg @@ -0,0 +1,111 @@ +frameskip_type = 0 +frameskip_value = 4 +safe_frameskip = 0 +show_frame_counter = 0 +screen_orientation = 1 +screen_swap = 0 +savestate_number = 0 +fast_forward = 0 +enable_sound = 1 +clock_speed = 0 +threaded_3d = 0 +mirror_touch = 0 +compress_savestates = 1 +savestate_snapshot = 1 +unzip_roms = 0 +preload_roms = 0 +backup_in_savestates = 1 +ignore_gamecard_limit = 0 +frame_interval = 0 +trim_roms = 0 +fix_main_2d_screen = 0 +disable_edge_marking = 0 +interframe_blend = 0 +hires_3d = 1 +use_rtc_custom_time = 0 +rtc_custom_time = 0 +rtc_system_time = 0 +slot2_device_type = 0 +rumble_frames = 3 +firmware.username = Dr DraStic +firmware.language = 1 +firmware.favorite_color = 0 +firmware.birthday_month = 1 +firmware.birthday_day = 1 +enable_cheats = 1 +controls_a[CONTROL_INDEX_UP] = 338 +controls_a[CONTROL_INDEX_DOWN] = 337 +controls_a[CONTROL_INDEX_LEFT] = 336 +controls_a[CONTROL_INDEX_RIGHT] = 335 +controls_a[CONTROL_INDEX_A] = 32 +controls_a[CONTROL_INDEX_B] = 480 +controls_a[CONTROL_INDEX_X] = 122 +controls_a[CONTROL_INDEX_Y] = 120 +controls_a[CONTROL_INDEX_L] = 113 +controls_a[CONTROL_INDEX_R] = 111 +controls_a[CONTROL_INDEX_START] = 13 +controls_a[CONTROL_INDEX_SELECT] = 485 +controls_a[CONTROL_INDEX_HINGE] = 104 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_UP] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_DOWN] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_LEFT] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_RIGHT] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_PRESS] = 65535 +controls_a[CONTROL_INDEX_MENU] = 27 +controls_a[CONTROL_INDEX_SAVE_STATE] = 115 +controls_a[CONTROL_INDEX_LOAD_STATE] = 108 +controls_a[CONTROL_INDEX_FAST_FORWARD] = 116 +controls_a[CONTROL_INDEX_SWAP_SCREENS] = 109 +controls_a[CONTROL_INDEX_SWAP_ORIENTATION_A] = 1026 +controls_a[CONTROL_INDEX_SWAP_ORIENTATION_B] = 65535 +controls_a[CONTROL_INDEX_LOAD_GAME] = 65535 +controls_a[CONTROL_INDEX_QUIT] = 65535 +controls_a[CONTROL_INDEX_FAKE_MICROPHONE] = 65535 +controls_a[CONTROL_INDEX_UI_UP] = 338 +controls_a[CONTROL_INDEX_UI_DOWN] = 337 +controls_a[CONTROL_INDEX_UI_LEFT] = 336 +controls_a[CONTROL_INDEX_UI_RIGHT] = 335 +controls_a[CONTROL_INDEX_UI_SELECT] = 13 +controls_a[CONTROL_INDEX_UI_BACK] = 8 +controls_a[CONTROL_INDEX_UI_EXIT] = 27 +controls_a[CONTROL_INDEX_UI_PAGE_UP] = 331 +controls_a[CONTROL_INDEX_UI_PAGE_DOWN] = 334 +controls_a[CONTROL_INDEX_UI_SWITCH] = 481 +controls_b[CONTROL_INDEX_UP] = 1036 +controls_b[CONTROL_INDEX_DOWN] = 1037 +controls_b[CONTROL_INDEX_LEFT] = 1038 +controls_b[CONTROL_INDEX_RIGHT] = 1039 +controls_b[CONTROL_INDEX_A] = 1025 +controls_b[CONTROL_INDEX_B] = 1024 +controls_b[CONTROL_INDEX_X] = 1027 +controls_b[CONTROL_INDEX_Y] = 1028 +controls_b[CONTROL_INDEX_L] = 1218 +controls_b[CONTROL_INDEX_R] = 1221 +controls_b[CONTROL_INDEX_START] = 1032 +controls_b[CONTROL_INDEX_SELECT] = 1031 +controls_b[CONTROL_INDEX_HINGE] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_UP] = 1220 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_DOWN] = 1156 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_LEFT] = 1219 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_RIGHT] = 1155 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_PRESS] = 1035 +controls_b[CONTROL_INDEX_MENU] = 120 +controls_b[CONTROL_INDEX_SAVE_STATE] = 65535 +controls_b[CONTROL_INDEX_LOAD_STATE] = 65535 +controls_b[CONTROL_INDEX_FAST_FORWARD] = 65535 +controls_b[CONTROL_INDEX_SWAP_SCREENS] = 65535 +controls_b[CONTROL_INDEX_SWAP_ORIENTATION_A] = 65535 +controls_b[CONTROL_INDEX_SWAP_ORIENTATION_B] = 65535 +controls_b[CONTROL_INDEX_LOAD_GAME] = 65535 +controls_b[CONTROL_INDEX_QUIT] = 65535 +controls_b[CONTROL_INDEX_FAKE_MICROPHONE] = 65535 +controls_b[CONTROL_INDEX_UI_UP] = 1036 +controls_b[CONTROL_INDEX_UI_DOWN] = 1037 +controls_b[CONTROL_INDEX_UI_LEFT] = 1038 +controls_b[CONTROL_INDEX_UI_RIGHT] = 1039 +controls_b[CONTROL_INDEX_UI_SELECT] = 1025 +controls_b[CONTROL_INDEX_UI_BACK] = 1027 +controls_b[CONTROL_INDEX_UI_EXIT] = 1024 +controls_b[CONTROL_INDEX_UI_PAGE_UP] = 1152 +controls_b[CONTROL_INDEX_UI_PAGE_DOWN] = 1216 +controls_b[CONTROL_INDEX_UI_SWITCH] = 1026 diff --git a/projects/ArchR/packages/emulators/standalone/drastic-sa/config/S922X/drastic.cfg b/projects/ArchR/packages/emulators/standalone/drastic-sa/config/S922X/drastic.cfg new file mode 100644 index 0000000000..791068a137 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/drastic-sa/config/S922X/drastic.cfg @@ -0,0 +1,111 @@ +frameskip_type = 0 +frameskip_value = 1 +safe_frameskip = 1 +show_frame_counter = 0 +screen_orientation = 1 +screen_swap = 0 +savestate_number = 0 +fast_forward = 0 +enable_sound = 1 +clock_speed = 0 +threaded_3d = 1 +mirror_touch = 0 +compress_savestates = 1 +savestate_snapshot = 1 +unzip_roms = 0 +preload_roms = 0 +backup_in_savestates = 1 +ignore_gamecard_limit = 0 +frame_interval = 0 +trim_roms = 0 +fix_main_2d_screen = 0 +disable_edge_marking = 0 +interframe_blend = 0 +hires_3d = 1 +use_rtc_custom_time = 0 +rtc_custom_time = 0 +rtc_system_time = 0 +slot2_device_type = 0 +rumble_frames = 3 +firmware.username = Dr DraStic +firmware.language = 1 +firmware.favorite_color = 0 +firmware.birthday_month = 1 +firmware.birthday_day = 1 +enable_cheats = 1 +controls_a[CONTROL_INDEX_UP] = 1217 +controls_a[CONTROL_INDEX_DOWN] = 1153 +controls_a[CONTROL_INDEX_LEFT] = 1216 +controls_a[CONTROL_INDEX_RIGHT] = 1152 +controls_a[CONTROL_INDEX_A] = 65535 +controls_a[CONTROL_INDEX_B] = 65535 +controls_a[CONTROL_INDEX_X] = 65535 +controls_a[CONTROL_INDEX_Y] = 65535 +controls_a[CONTROL_INDEX_L] = 65535 +controls_a[CONTROL_INDEX_R] = 65535 +controls_a[CONTROL_INDEX_START] = 65535 +controls_a[CONTROL_INDEX_SELECT] = 65535 +controls_a[CONTROL_INDEX_HINGE] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_UP] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_DOWN] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_LEFT] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_RIGHT] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_PRESS] = 65535 +controls_a[CONTROL_INDEX_MENU] = 1026 +controls_a[CONTROL_INDEX_SAVE_STATE] = 65535 +controls_a[CONTROL_INDEX_LOAD_STATE] = 65535 +controls_a[CONTROL_INDEX_FAST_FORWARD] = 65535 +controls_a[CONTROL_INDEX_SWAP_SCREENS] = 65535 +controls_a[CONTROL_INDEX_SWAP_ORIENTATION_A] = 65535 +controls_a[CONTROL_INDEX_SWAP_ORIENTATION_B] = 65535 +controls_a[CONTROL_INDEX_LOAD_GAME] = 65535 +controls_a[CONTROL_INDEX_QUIT] = 65535 +controls_a[CONTROL_INDEX_FAKE_MICROPHONE] = 65535 +controls_a[CONTROL_INDEX_UI_UP] = 1038 +controls_a[CONTROL_INDEX_UI_DOWN] = 1039 +controls_a[CONTROL_INDEX_UI_LEFT] = 1040 +controls_a[CONTROL_INDEX_UI_RIGHT] = 1041 +controls_a[CONTROL_INDEX_UI_SELECT] = 65535 +controls_a[CONTROL_INDEX_UI_BACK] = 65535 +controls_a[CONTROL_INDEX_UI_EXIT] = 65535 +controls_a[CONTROL_INDEX_UI_PAGE_UP] = 65535 +controls_a[CONTROL_INDEX_UI_PAGE_DOWN] = 65535 +controls_a[CONTROL_INDEX_UI_SWITCH] = 65535 +controls_b[CONTROL_INDEX_UP] = 1038 +controls_b[CONTROL_INDEX_DOWN] = 1039 +controls_b[CONTROL_INDEX_LEFT] = 1040 +controls_b[CONTROL_INDEX_RIGHT] = 1041 +controls_b[CONTROL_INDEX_A] = 1025 +controls_b[CONTROL_INDEX_B] = 1024 +controls_b[CONTROL_INDEX_X] = 1027 +controls_b[CONTROL_INDEX_Y] = 1028 +controls_b[CONTROL_INDEX_L] = 1029 +controls_b[CONTROL_INDEX_R] = 1030 +controls_b[CONTROL_INDEX_START] = 1034 +controls_b[CONTROL_INDEX_SELECT] = 1033 +controls_b[CONTROL_INDEX_HINGE] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_UP] = 1219 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_DOWN] = 1155 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_LEFT] = 1218 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_RIGHT] = 1154 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_PRESS] = 1037 +controls_b[CONTROL_INDEX_MENU] = 1026 +controls_b[CONTROL_INDEX_SAVE_STATE] = 115 +controls_b[CONTROL_INDEX_LOAD_STATE] = 108 +controls_b[CONTROL_INDEX_FAST_FORWARD] = 116 +controls_b[CONTROL_INDEX_SWAP_SCREENS] = 109 +controls_b[CONTROL_INDEX_SWAP_ORIENTATION_A] = 1031 +controls_b[CONTROL_INDEX_SWAP_ORIENTATION_B] = 1032 +controls_b[CONTROL_INDEX_LOAD_GAME] = 65535 +controls_b[CONTROL_INDEX_QUIT] = 65535 +controls_b[CONTROL_INDEX_FAKE_MICROPHONE] = 65535 +controls_b[CONTROL_INDEX_UI_UP] = 1217 +controls_b[CONTROL_INDEX_UI_DOWN] = 1153 +controls_b[CONTROL_INDEX_UI_LEFT] = 1216 +controls_b[CONTROL_INDEX_UI_RIGHT] = 1152 +controls_b[CONTROL_INDEX_UI_SELECT] = 1025 +controls_b[CONTROL_INDEX_UI_BACK] = 65535 +controls_b[CONTROL_INDEX_UI_EXIT] = 1024 +controls_b[CONTROL_INDEX_UI_PAGE_UP] = 65535 +controls_b[CONTROL_INDEX_UI_PAGE_DOWN] = 65535 +controls_b[CONTROL_INDEX_UI_SWITCH] = 65535 diff --git a/projects/ArchR/packages/emulators/standalone/drastic-sa/config/SM8250/drastic.cfg b/projects/ArchR/packages/emulators/standalone/drastic-sa/config/SM8250/drastic.cfg new file mode 100644 index 0000000000..af4dd6cc80 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/drastic-sa/config/SM8250/drastic.cfg @@ -0,0 +1,111 @@ +frameskip_type = 0 +frameskip_value = 4 +safe_frameskip = 0 +show_frame_counter = 0 +screen_orientation = 0 +screen_swap = 0 +savestate_number = 0 +fast_forward = 0 +enable_sound = 1 +clock_speed = 0 +threaded_3d = 0 +mirror_touch = 0 +compress_savestates = 1 +savestate_snapshot = 1 +unzip_roms = 0 +preload_roms = 0 +backup_in_savestates = 1 +ignore_gamecard_limit = 0 +frame_interval = 0 +trim_roms = 0 +fix_main_2d_screen = 0 +disable_edge_marking = 0 +interframe_blend = 0 +hires_3d = 1 +use_rtc_custom_time = 0 +rtc_custom_time = 0 +rtc_system_time = 0 +slot2_device_type = 0 +rumble_frames = 3 +firmware.username = Dr DraStic +firmware.language = 1 +firmware.favorite_color = 0 +firmware.birthday_month = 1 +firmware.birthday_day = 1 +enable_cheats = 1 +controls_a[CONTROL_INDEX_UP] = 1035 +controls_a[CONTROL_INDEX_DOWN] = 1036 +controls_a[CONTROL_INDEX_LEFT] = 1037 +controls_a[CONTROL_INDEX_RIGHT] = 1038 +controls_a[CONTROL_INDEX_A] = 65535 +controls_a[CONTROL_INDEX_B] = 65535 +controls_a[CONTROL_INDEX_X] = 65535 +controls_a[CONTROL_INDEX_Y] = 65535 +controls_a[CONTROL_INDEX_L] = 65535 +controls_a[CONTROL_INDEX_R] = 65535 +controls_a[CONTROL_INDEX_START] = 65535 +controls_a[CONTROL_INDEX_SELECT] = 65535 +controls_a[CONTROL_INDEX_HINGE] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_UP] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_DOWN] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_LEFT] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_RIGHT] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_PRESS] = 65535 +controls_a[CONTROL_INDEX_MENU] = 1032 +controls_a[CONTROL_INDEX_SAVE_STATE] = 115 +controls_a[CONTROL_INDEX_LOAD_STATE] = 108 +controls_a[CONTROL_INDEX_FAST_FORWARD] = 116 +controls_a[CONTROL_INDEX_SWAP_SCREENS] = 1039 +controls_a[CONTROL_INDEX_SWAP_ORIENTATION_A] = 110 +controls_a[CONTROL_INDEX_SWAP_ORIENTATION_B] = 112 +controls_a[CONTROL_INDEX_LOAD_GAME] = 65535 +controls_a[CONTROL_INDEX_QUIT] = 65535 +controls_a[CONTROL_INDEX_FAKE_MICROPHONE] = 65535 +controls_a[CONTROL_INDEX_UI_UP] = 1035 +controls_a[CONTROL_INDEX_UI_DOWN] = 1036 +controls_a[CONTROL_INDEX_UI_LEFT] = 1037 +controls_a[CONTROL_INDEX_UI_RIGHT] = 1038 +controls_a[CONTROL_INDEX_UI_SELECT] = 65535 +controls_a[CONTROL_INDEX_UI_BACK] = 65535 +controls_a[CONTROL_INDEX_UI_EXIT] = 65535 +controls_a[CONTROL_INDEX_UI_PAGE_UP] = 65535 +controls_a[CONTROL_INDEX_UI_PAGE_DOWN] = 65535 +controls_a[CONTROL_INDEX_UI_SWITCH] = 65535 +controls_b[CONTROL_INDEX_UP] = 1217 +controls_b[CONTROL_INDEX_DOWN] = 1153 +controls_b[CONTROL_INDEX_LEFT] = 1216 +controls_b[CONTROL_INDEX_RIGHT] = 1152 +controls_b[CONTROL_INDEX_A] = 1025 +controls_b[CONTROL_INDEX_B] = 1024 +controls_b[CONTROL_INDEX_X] = 1026 +controls_b[CONTROL_INDEX_Y] = 1027 +controls_b[CONTROL_INDEX_L] = 1028 +controls_b[CONTROL_INDEX_R] = 1029 +controls_b[CONTROL_INDEX_START] = 1031 +controls_b[CONTROL_INDEX_SELECT] = 1030 +controls_b[CONTROL_INDEX_HINGE] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_UP] = 1220 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_DOWN] = 1156 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_LEFT] = 1219 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_RIGHT] = 1155 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_PRESS] = 1034 +controls_b[CONTROL_INDEX_MENU] = 120 +controls_b[CONTROL_INDEX_SAVE_STATE] = 65535 +controls_b[CONTROL_INDEX_LOAD_STATE] = 65535 +controls_b[CONTROL_INDEX_FAST_FORWARD] = 65535 +controls_b[CONTROL_INDEX_SWAP_SCREENS] = 65535 +controls_b[CONTROL_INDEX_SWAP_ORIENTATION_A] = 65535 +controls_b[CONTROL_INDEX_SWAP_ORIENTATION_B] = 65535 +controls_b[CONTROL_INDEX_LOAD_GAME] = 65535 +controls_b[CONTROL_INDEX_QUIT] = 65535 +controls_b[CONTROL_INDEX_FAKE_MICROPHONE] = 65535 +controls_b[CONTROL_INDEX_UI_UP] = 1217 +controls_b[CONTROL_INDEX_UI_DOWN] = 1153 +controls_b[CONTROL_INDEX_UI_LEFT] = 1216 +controls_b[CONTROL_INDEX_UI_RIGHT] = 1152 +controls_b[CONTROL_INDEX_UI_SELECT] = 1025 +controls_b[CONTROL_INDEX_UI_BACK] = 65535 +controls_b[CONTROL_INDEX_UI_EXIT] = 1024 +controls_b[CONTROL_INDEX_UI_PAGE_UP] = 65535 +controls_b[CONTROL_INDEX_UI_PAGE_DOWN] = 65535 +controls_b[CONTROL_INDEX_UI_SWITCH] = 65535 diff --git a/projects/ArchR/packages/emulators/standalone/drastic-sa/config/SM8550/drastic.cfg b/projects/ArchR/packages/emulators/standalone/drastic-sa/config/SM8550/drastic.cfg new file mode 100644 index 0000000000..af4dd6cc80 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/drastic-sa/config/SM8550/drastic.cfg @@ -0,0 +1,111 @@ +frameskip_type = 0 +frameskip_value = 4 +safe_frameskip = 0 +show_frame_counter = 0 +screen_orientation = 0 +screen_swap = 0 +savestate_number = 0 +fast_forward = 0 +enable_sound = 1 +clock_speed = 0 +threaded_3d = 0 +mirror_touch = 0 +compress_savestates = 1 +savestate_snapshot = 1 +unzip_roms = 0 +preload_roms = 0 +backup_in_savestates = 1 +ignore_gamecard_limit = 0 +frame_interval = 0 +trim_roms = 0 +fix_main_2d_screen = 0 +disable_edge_marking = 0 +interframe_blend = 0 +hires_3d = 1 +use_rtc_custom_time = 0 +rtc_custom_time = 0 +rtc_system_time = 0 +slot2_device_type = 0 +rumble_frames = 3 +firmware.username = Dr DraStic +firmware.language = 1 +firmware.favorite_color = 0 +firmware.birthday_month = 1 +firmware.birthday_day = 1 +enable_cheats = 1 +controls_a[CONTROL_INDEX_UP] = 1035 +controls_a[CONTROL_INDEX_DOWN] = 1036 +controls_a[CONTROL_INDEX_LEFT] = 1037 +controls_a[CONTROL_INDEX_RIGHT] = 1038 +controls_a[CONTROL_INDEX_A] = 65535 +controls_a[CONTROL_INDEX_B] = 65535 +controls_a[CONTROL_INDEX_X] = 65535 +controls_a[CONTROL_INDEX_Y] = 65535 +controls_a[CONTROL_INDEX_L] = 65535 +controls_a[CONTROL_INDEX_R] = 65535 +controls_a[CONTROL_INDEX_START] = 65535 +controls_a[CONTROL_INDEX_SELECT] = 65535 +controls_a[CONTROL_INDEX_HINGE] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_UP] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_DOWN] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_LEFT] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_RIGHT] = 65535 +controls_a[CONTROL_INDEX_TOUCH_CURSOR_PRESS] = 65535 +controls_a[CONTROL_INDEX_MENU] = 1032 +controls_a[CONTROL_INDEX_SAVE_STATE] = 115 +controls_a[CONTROL_INDEX_LOAD_STATE] = 108 +controls_a[CONTROL_INDEX_FAST_FORWARD] = 116 +controls_a[CONTROL_INDEX_SWAP_SCREENS] = 1039 +controls_a[CONTROL_INDEX_SWAP_ORIENTATION_A] = 110 +controls_a[CONTROL_INDEX_SWAP_ORIENTATION_B] = 112 +controls_a[CONTROL_INDEX_LOAD_GAME] = 65535 +controls_a[CONTROL_INDEX_QUIT] = 65535 +controls_a[CONTROL_INDEX_FAKE_MICROPHONE] = 65535 +controls_a[CONTROL_INDEX_UI_UP] = 1035 +controls_a[CONTROL_INDEX_UI_DOWN] = 1036 +controls_a[CONTROL_INDEX_UI_LEFT] = 1037 +controls_a[CONTROL_INDEX_UI_RIGHT] = 1038 +controls_a[CONTROL_INDEX_UI_SELECT] = 65535 +controls_a[CONTROL_INDEX_UI_BACK] = 65535 +controls_a[CONTROL_INDEX_UI_EXIT] = 65535 +controls_a[CONTROL_INDEX_UI_PAGE_UP] = 65535 +controls_a[CONTROL_INDEX_UI_PAGE_DOWN] = 65535 +controls_a[CONTROL_INDEX_UI_SWITCH] = 65535 +controls_b[CONTROL_INDEX_UP] = 1217 +controls_b[CONTROL_INDEX_DOWN] = 1153 +controls_b[CONTROL_INDEX_LEFT] = 1216 +controls_b[CONTROL_INDEX_RIGHT] = 1152 +controls_b[CONTROL_INDEX_A] = 1025 +controls_b[CONTROL_INDEX_B] = 1024 +controls_b[CONTROL_INDEX_X] = 1026 +controls_b[CONTROL_INDEX_Y] = 1027 +controls_b[CONTROL_INDEX_L] = 1028 +controls_b[CONTROL_INDEX_R] = 1029 +controls_b[CONTROL_INDEX_START] = 1031 +controls_b[CONTROL_INDEX_SELECT] = 1030 +controls_b[CONTROL_INDEX_HINGE] = 65535 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_UP] = 1220 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_DOWN] = 1156 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_LEFT] = 1219 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_RIGHT] = 1155 +controls_b[CONTROL_INDEX_TOUCH_CURSOR_PRESS] = 1034 +controls_b[CONTROL_INDEX_MENU] = 120 +controls_b[CONTROL_INDEX_SAVE_STATE] = 65535 +controls_b[CONTROL_INDEX_LOAD_STATE] = 65535 +controls_b[CONTROL_INDEX_FAST_FORWARD] = 65535 +controls_b[CONTROL_INDEX_SWAP_SCREENS] = 65535 +controls_b[CONTROL_INDEX_SWAP_ORIENTATION_A] = 65535 +controls_b[CONTROL_INDEX_SWAP_ORIENTATION_B] = 65535 +controls_b[CONTROL_INDEX_LOAD_GAME] = 65535 +controls_b[CONTROL_INDEX_QUIT] = 65535 +controls_b[CONTROL_INDEX_FAKE_MICROPHONE] = 65535 +controls_b[CONTROL_INDEX_UI_UP] = 1217 +controls_b[CONTROL_INDEX_UI_DOWN] = 1153 +controls_b[CONTROL_INDEX_UI_LEFT] = 1216 +controls_b[CONTROL_INDEX_UI_RIGHT] = 1152 +controls_b[CONTROL_INDEX_UI_SELECT] = 1025 +controls_b[CONTROL_INDEX_UI_BACK] = 65535 +controls_b[CONTROL_INDEX_UI_EXIT] = 1024 +controls_b[CONTROL_INDEX_UI_PAGE_UP] = 65535 +controls_b[CONTROL_INDEX_UI_PAGE_DOWN] = 65535 +controls_b[CONTROL_INDEX_UI_SWITCH] = 65535 diff --git a/projects/ArchR/packages/emulators/standalone/drastic-sa/config/drastic.gptk b/projects/ArchR/packages/emulators/standalone/drastic-sa/config/drastic.gptk new file mode 100644 index 0000000000..13dcd76844 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/drastic-sa/config/drastic.gptk @@ -0,0 +1,32 @@ +back = e +start = \\ +a = d +a_hk = a +b = c +b_hk = b +x = z +x_hk = x +y = v +y_hk = y +l1 = q +l1_hk = l +l2 = n +l2_hk = m +l3 = \\ +r1 = o +r1_hk = s +r2 = p +r2_hk = t +r3 = \\ +up = \\ +down = \\ +left = \\ +right = \\ +left_analog_up = \\ +left_analog_down = \\ +left_analog_left = \\ +left_analog_right = \\ +right_analog_up = \\ +right_analog_down = \\ +right_analog_left = \\ +right_analog_right = \\ diff --git a/projects/ArchR/packages/emulators/standalone/drastic-sa/package.mk b/projects/ArchR/packages/emulators/standalone/drastic-sa/package.mk new file mode 100644 index 0000000000..bcfd5bddcf --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/drastic-sa/package.mk @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="drastic-sa" +PKG_VERSION="1.0" +PKG_LICENSE="Proprietary:DRASTIC.pdf" +PKG_ARCH="aarch64" +PKG_URL="https://github.com/archr-linux/packages/raw/main/drastic.tar.gz" +PKG_DEPENDS_TARGET="toolchain archr-hotkey" +PKG_LONGDESC="Install Drastic Launcher script, will download bin on first run" +PKG_TOOLCHAIN="make" + +if [ "${DEVICE}" = "S922X" ]; then + PKG_DEPENDS_TARGET+=" libegl" +fi + +make_target() { + ${CC} ${CFLAGS} -shared -fPIC -o libdrastouch.so \ + ${PKG_DIR}/sources/libdrastouch.c -ldl +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp -rf ${PKG_DIR}/scripts/* ${INSTALL}/usr/bin + chmod +x ${INSTALL}/usr/bin/start_drastic.sh + + mkdir -p ${INSTALL}/usr/lib + cp -f ${PKG_BUILD}/libdrastouch.so ${INSTALL}/usr/lib/ + + mkdir -p ${INSTALL}/usr/config/drastic/config + cp -rf ${PKG_BUILD}/drastic_aarch64/* ${INSTALL}/usr/config/drastic/ + cp -rf ${PKG_DIR}/config/${DEVICE}/* ${INSTALL}/usr/config/drastic/config/ + cp -rf ${PKG_DIR}/config/drastic.gptk ${INSTALL}/usr/config/drastic/ + + mkdir -p ${INSTALL}/usr/config/drastic/microphone + cp -f ${PKG_DIR}/sources/microphone.wav ${INSTALL}/usr/config/drastic/microphone/ +} + +post_install() { + case ${DEVICE} in + RK3588) + HOTKEY="export HOTKEY="guide"" + ;; + *) + HOTKEY="" + ;; + esac + sed -e "s/@HOTKEY@/${HOTKEY}/g" \ + -i ${INSTALL}/usr/bin/start_drastic.sh +} diff --git a/projects/ArchR/packages/emulators/standalone/drastic-sa/scripts/start_drastic.sh b/projects/ArchR/packages/emulators/standalone/drastic-sa/scripts/start_drastic.sh new file mode 100644 index 0000000000..6d2bd390f1 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/drastic-sa/scripts/start_drastic.sh @@ -0,0 +1,102 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile +. /etc/os-release + +set_kill set "-9 drastic" + +#Get game/platform info +GAME=$(echo "${1}"| sed "s#^/.*/##") +PLATFORM="nds" + +#Get ES feature settings +HIRES3D=$(get_setting hires_3d "${PLATFORM}" "${GAME}") +THREADED3D=$(get_setting threaded_3d "${PLATFORM}" "${GAME}") +FOLLOW3D=$(get_setting follow_3d_renderer "${PLATFORM}" "${GAME}") +MICTHRESH=$(get_setting microphone_sensitivity "${PLATFORM}" "${GAME}") + +#load gptokeyb support files +control-gen_init.sh +source /storage/.config/gptokeyb/control.ini +get_controls + +#Copy drastic files to .config +if [ ! -d "/storage/.config/drastic" ]; then + mkdir -p /storage/.config/drastic/ + cp -r /usr/config/drastic/* /storage/.config/drastic/ +fi + +if [ ! -d "/storage/.config/drastic/system" ]; then + mkdir -p /storage/.config/drastic/system +fi + +for bios in nds_bios_arm9.bin nds_bios_arm7.bin +do + if [ ! -e "/storage/.config/drastic/system/${bios}" ]; then + if [ -e "/storage/roms/bios/${bios}" ]; then + ln -sf /storage/roms/bios/${bios} /storage/.config/drastic/system + fi + fi +done + +#Copy drastic files to .config +if [ ! -f "/storage/.config/drastic/drastic.gptk" ]; then + cp -r /usr/config/drastic/drastic.gptk /storage/.config/drastic/ +fi + +#Make drastic savestate folder +if [ ! -d "/storage/roms/savestates/nds" ]; then + mkdir -p /storage/roms/savestates/nds +fi + +#Link savestates to roms/savestates/nds +rm -rf /storage/.config/drastic/savestates +ln -sf /storage/roms/savestates/nds /storage/.config/drastic/savestates + +#Link saves to roms/nds/saves +rm -rf /storage/.config/drastic/backup +ln -sf /storage/roms/nds /storage/.config/drastic/backup + +#Apply ES features to config +if [ "${HIRES3D}" = "1" ]; then + sed -i 's/^hires_3d = .*/hires_3d = 1/' /storage/.config/drastic/config/drastic.cfg +else + sed -i 's/^hires_3d = .*/hires_3d = 0/' /storage/.config/drastic/config/drastic.cfg +fi + +if [ "${THREADED3D}" = "1" ]; then + sed -i 's/^threaded_3d = .*/threaded_3d = 1/' /storage/.config/drastic/config/drastic.cfg +else + sed -i 's/^threaded_3d = .*/threaded_3d = 0/' /storage/.config/drastic/config/drastic.cfg +fi + +if [ "${FOLLOW3D}" = "1" ]; then + sed -i 's/^fix_main_2d_screen = .*/fix_main_2d_screen = 1/' /storage/.config/drastic/config/drastic.cfg +else + sed -i 's/^fix_main_2d_screen = .*/fix_main_2d_screen = 0/' /storage/.config/drastic/config/drastic.cfg +fi + +cd /storage/.config/drastic/ +@HOTKEY@ + +# Fix for libmali gpu driver on S922X platform +if [ "${HW_DEVICE}" = "S922X" ]; then + GPUDRIVER=$(/usr/bin/gpudriver) + + if [ "${GPUDRIVER}" = "libmali" ]; then + export SDL_VIDEO_GL_DRIVER=\/usr\/lib\/egl\/libGL.so.1 + export SDL_VIDEO_EGL_DRIVER=\/usr\/lib\/egl\/libEGL.so.1 + fi +fi + +$GPTOKEYB "drastic" -c "drastic.gptk" & +# Fix actual touch inputs by replacing touch->mouse translation and add hw mic support +export LD_PRELOAD="/usr/lib/libdrastouch.so" +export SDL_TOUCH_MOUSE_EVENTS="0" +export DSHOOK_MIC_THRESH="${MICTHRESH}" +./drastic "$1" +_gptokeyb_pid="$(pidof gptokeyb 2>/dev/null)" +[ -n "${_gptokeyb_pid}" ] && kill -9 ${_gptokeyb_pid} diff --git a/projects/ArchR/packages/emulators/standalone/drastic-sa/sources/libdrastouch.c b/projects/ArchR/packages/emulators/standalone/drastic-sa/sources/libdrastouch.c new file mode 100644 index 0000000000..790923bca9 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/drastic-sa/sources/libdrastouch.c @@ -0,0 +1,378 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include + +static int ds_screen_width = 256; +static int ds_screen_height = 192; +static int last_x = -1; +static int last_y = -1; +static int xy_idx = 0; +static int phys_width = -1; +static int phys_height = -1; +static int logical_width = -1; +static int logical_height = -1; +static int actual_touch = 0; + +// Microphone monitoring +static SDL_AudioDeviceID mic_device = 0; +static int mic_key_held = 0; +static float mic_threshold = 0.0f; +static int mic_enabled = 0; +static float mic_baseline = 0.0f; +static int mic_baseline_samples = 0; + +static SDL_Texture* screens[4]; +static SDL_Texture* stylus_tex[2]; +static SDL_Rect touch_rect_storage = {0}; +static SDL_Rect* touch_rect = NULL; +static SDL_Renderer* renderer = NULL; +static SDL_Window* (*real_SDL_CreateWindow)(const char*, int, int, int, int, Uint32) = NULL; +static void (*real_SDL_SetWindowSize)(SDL_Window* window, int w, int h) = NULL; +static SDL_Renderer* (*real_SDL_CreateRenderer)(SDL_Window*, int, Uint32) = NULL; +static int (*real_SDL_RenderSetLogicalSize)(SDL_Renderer*, int, int) = NULL; +static SDL_Texture* (*real_SDL_CreateTexture)(SDL_Renderer*, Uint32, int, int, int) = NULL; +static int (*real_SDL_RenderCopy)(SDL_Renderer*, SDL_Texture*, const SDL_Rect*, const SDL_Rect*) = NULL; +static int (*real_SDL_PollEvent)(SDL_Event*) = NULL; +static int (*real_SDL_PushEvent)(SDL_Event*) = NULL; +static Uint32 (*real_SDL_WasInit)(Uint32) = NULL; +static int (*real_SDL_InitSubSystem)(Uint32) = NULL; +static SDL_AudioDeviceID (*real_SDL_OpenAudioDevice)(const char*, int, const SDL_AudioSpec*, SDL_AudioSpec*, int) = NULL; +static void (*real_SDL_PauseAudioDevice)(SDL_AudioDeviceID, int) = NULL; +static void (*real_SDL_CloseAudioDevice)(SDL_AudioDeviceID) = NULL; +static int (*real_SDL_GetNumAudioDevices)(int) = NULL; +static const char* (*real_SDL_GetAudioDeviceName)(int, int) = NULL; + +SDL_Window* SDL_CreateWindow(const char* title, int x, int y, int w, int h, Uint32 flags) { + int num_displays = SDL_GetNumVideoDisplays(); + int total_width = 0; + int total_height = 0; + int last_width = 0; + int last_height = 0; + + // Change window to total screen size + // Prevents empty spacing on dual displays + for (int i = 0; i < num_displays; ++i) { + SDL_Rect bounds; + if (SDL_GetDisplayBounds(i, &bounds) == 0) { + last_width = bounds.w; + last_height = bounds.h; + if (bounds.w + bounds.x > total_width) + total_width += bounds.w; + if (bounds.h + bounds.y > total_height) + total_height += bounds.h; + } + } + + // Record screen size for rect tracking/conversion + phys_width = total_width; + phys_height = total_height; + + // DraStic starts in the center of the native virtual screen + last_x = 128; + last_y = 96; + + // Check which screen side is longer for dual screens + if (num_displays > 1) + xy_idx = (last_width > last_height) ? 1 : 2; + + // Set window size to single screen to fix offsets when resizing + return real_SDL_CreateWindow(title, 0, 0, last_width, last_height, flags); +} + +void SDL_SetWindowSize(SDL_Window* window, int w, int h) { + static int init_resize = 2; + + if (init_resize > 0) { + real_SDL_SetWindowSize(window, w, h); + init_resize -= 1; + } + + // Force window size to fill AFTER DraStic does its weird init thing + // Also check if this is a resize after init, if so, toggle a scale down to allow DraStic menu visibility + if (init_resize == 0) { + real_SDL_SetWindowSize(window, phys_width, phys_height); + init_resize = -1; + } else if (init_resize == -1) { + if (xy_idx == 1) + w = phys_width / 2; + if (xy_idx == 2) + h = phys_height / 2; + + real_SDL_SetWindowSize(window, w, h); + init_resize = 0; + } + +} + +SDL_Renderer* SDL_CreateRenderer(SDL_Window* window, int index, Uint32 flags) { + renderer = real_SDL_CreateRenderer(window, index, flags); + // Just in case it's already set + SDL_RenderGetLogicalSize(renderer, &logical_width, &logical_height); + return renderer; +} + +int SDL_RenderSetLogicalSize(SDL_Renderer* renderer, int w, int h) { + int result = real_SDL_RenderSetLogicalSize(renderer, w, h); + // Otherwise store it here + logical_width = w; + logical_height = h; + return result; +} + +SDL_Texture* SDL_CreateTexture(SDL_Renderer *renderer, Uint32 format, int type, int w, int h) { + SDL_Texture* texture = real_SDL_CreateTexture(renderer, format, type, w, h); + // Identify DS screen and stylus textures + if (type == SDL_TEXTUREACCESS_STREAMING) { + if (w == 512 && h == 384) { + ds_screen_width = 512; + ds_screen_height = 384; + if (!screens[0]) screens[0] = texture; + else if (!screens[1]) screens[1] = texture; + } else if (w == 256 && h == 192 && !screens[0]) { + if (!screens[2]) screens[2] = texture; + else if (!screens[3]) screens[3] = texture; + } + } + if (w == 32 && h == 32) { + if (!stylus_tex[0]) stylus_tex[0] = texture; + else if (!stylus_tex[1]) stylus_tex[1] = texture; + } + return texture; +} + +int SDL_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect, const SDL_Rect *dstrect) { + if ((screens[0] && texture == screens[0] && ds_screen_width == 512) || + (screens[3] && texture == screens[3] && ds_screen_width == 256)) { + // Convert renderer coordinates to physical screen coordinates + if (logical_width > 0 && logical_height > 0) { + int output_w, output_h; + SDL_GetRendererOutputSize(renderer, &output_w, &output_h); + float scale_x = (float)output_w / logical_width; + float scale_y = (float)output_h / logical_height; + + touch_rect_storage.x = (int)(dstrect->x * scale_x); + touch_rect_storage.y = (int)(dstrect->y * scale_y); + touch_rect_storage.w = (int)(dstrect->w * scale_x); + touch_rect_storage.h = (int)(dstrect->h * scale_y); + } else { + // Fallback and hope they're right + touch_rect_storage.x = dstrect->x; + touch_rect_storage.y = dstrect->y; + touch_rect_storage.w = dstrect->w; + touch_rect_storage.h = dstrect->h; + } + touch_rect = &touch_rect_storage; + } + + // Make stylus fully transparent for actual touchscreens + if (actual_touch && (texture == stylus_tex[0] || texture == stylus_tex[1])) + SDL_SetTextureAlphaMod(texture, 0); + + return real_SDL_RenderCopy(renderer, texture, srcrect, dstrect); +} + +void mic_audio_callback(void* userdata, Uint8* stream, int len) { + if (!mic_enabled) return; + + Sint16* samples = (Sint16*)stream; + int sample_count = len / 2; + + // Calculate RMS amplitude + float sum = 0.0f; + for (int i = 0; i < sample_count; i++) { + float sample = samples[i] / 32768.0f; // Normalize to [-1.0..1.0] + sum += sample * sample; + } + float rms = sqrtf(sum / sample_count); + + // Build ambient baseline over first ~3 seconds + if (mic_baseline_samples < 60) { + mic_baseline = (mic_baseline * mic_baseline_samples + rms) / (mic_baseline_samples + 1); + mic_baseline_samples++; + return; // Don't trigger during calibration + } + + mic_baseline = mic_baseline * 0.999f + rms * 0.001f; + + // Trigger only if significantly above baseline + float trigger_level = mic_baseline + mic_threshold; + int should_hold = (rms > trigger_level); + if (should_hold && !mic_key_held) { + // Noise detected, press Scroll Lock + SDL_Event key_event = {0}; + key_event.type = SDL_KEYDOWN; + key_event.key.state = SDL_PRESSED; + key_event.key.keysym.scancode = SDL_SCANCODE_SCROLLLOCK; + key_event.key.keysym.sym = SDLK_SCROLLLOCK; + real_SDL_PushEvent(&key_event); + mic_key_held = 1; + } else if (!should_hold && mic_key_held) { + // Noise dropped below threshold, release Scroll Lock + SDL_Event key_event = {0}; + key_event.type = SDL_KEYUP; + key_event.key.state = SDL_RELEASED; + key_event.key.keysym.scancode = SDL_SCANCODE_SCROLLLOCK; + key_event.key.keysym.sym = SDLK_SCROLLLOCK; + real_SDL_PushEvent(&key_event); + mic_key_held = 0; + } +} + +int SDL_PollEvent(SDL_Event* event) { + // Loop required to filter events we don't want to pass along + while (1) { + int result = real_SDL_PollEvent(event); + if (!result) return 0; + + switch (event->type) { + case SDL_FINGERDOWN: { + if (!actual_touch) + actual_touch = 1; + + int x = (int)(event->tfinger.x * phys_width); + int y = (int)(event->tfinger.y * phys_height); + if (xy_idx == 1) + x *= 2; + if (xy_idx == 2) + y *= 2; + + if (x < touch_rect->x || x > touch_rect->x + touch_rect->w || + y < touch_rect->y || y > touch_rect->y + touch_rect->h) + return 0; // Outside valid coords, don't convert + + // Scale to native virtual touchscreen + x = ((x - touch_rect->x) * 256) / touch_rect->w; + y = ((y - touch_rect->y) * 192) / touch_rect->h; + + // Queue click for after jump + event->type = SDL_MOUSEBUTTONDOWN; + event->button.button = SDL_BUTTON_LEFT; + event->button.state = SDL_PRESSED; + event->button.x = x; + event->button.y = y; + real_SDL_PushEvent(event); + + // Jump to new position + event->type = SDL_MOUSEMOTION; + event->motion.x = x; + event->motion.y = y; + event->motion.xrel = x - last_x; + event->motion.yrel = y - last_y; + + // Update to keep position accurate + last_x = x; + last_y = y; + break; + } + case SDL_FINGERMOTION: { + int x = (int)(event->tfinger.x * phys_width); + int y = (int)(event->tfinger.y * phys_height); + if (xy_idx == 1) + x *= 2; + if (xy_idx == 2) + y *= 2; + + if (x < touch_rect->x || x > touch_rect->x + touch_rect->w || + y < touch_rect->y || y > touch_rect->y + touch_rect->h) + return 0; + + x = ((x - touch_rect->x) * 256) / touch_rect->w; + y = ((y - touch_rect->y) * 192) / touch_rect->h; + int xrel = x - last_x; + int yrel = y - last_y; + + // Motion is also used when already clicked but not moving + // Always update it + event->type = SDL_MOUSEMOTION; + event->motion.x = x; + event->motion.y = y; + event->motion.xrel = xrel; + event->motion.yrel = yrel; + + last_x = x; + last_y = y; + break; + } + case SDL_FINGERUP: { + event->type = SDL_MOUSEBUTTONUP; + event->button.button = SDL_BUTTON_LEFT; + event->button.state = SDL_RELEASED; + event->button.x = last_x; + event->button.y = last_y; + break; + } + } + return result; + } +} + +__attribute__((constructor)) +static void init(void) { + real_SDL_CreateWindow = dlsym(RTLD_NEXT, "SDL_CreateWindow"); + real_SDL_SetWindowSize = dlsym(RTLD_NEXT, "SDL_SetWindowSize"); + real_SDL_CreateRenderer = dlsym(RTLD_NEXT, "SDL_CreateRenderer"); + real_SDL_RenderSetLogicalSize = dlsym(RTLD_NEXT, "SDL_RenderSetLogicalSize"); + real_SDL_CreateTexture = dlsym(RTLD_NEXT, "SDL_CreateTexture"); + real_SDL_RenderCopy = dlsym(RTLD_NEXT, "SDL_RenderCopy"); + real_SDL_PollEvent = dlsym(RTLD_NEXT, "SDL_PollEvent"); + real_SDL_PushEvent = dlsym(RTLD_NEXT, "SDL_PushEvent"); + real_SDL_WasInit = dlsym(RTLD_NEXT, "SDL_WasInit"); + real_SDL_InitSubSystem = dlsym(RTLD_NEXT, "SDL_InitSubSystem"); + real_SDL_OpenAudioDevice = dlsym(RTLD_NEXT, "SDL_OpenAudioDevice"); + real_SDL_PauseAudioDevice = dlsym(RTLD_NEXT, "SDL_PauseAudioDevice"); + real_SDL_CloseAudioDevice = dlsym(RTLD_NEXT, "SDL_CloseAudioDevice"); + real_SDL_GetNumAudioDevices = dlsym(RTLD_NEXT, "SDL_GetNumAudioDevices"); + real_SDL_GetAudioDeviceName = dlsym(RTLD_NEXT, "SDL_GetAudioDeviceName"); + + const char* threshold_str = getenv("DSHOOK_MIC_THRESH"); + if (threshold_str) { + mic_threshold = atof(threshold_str); + if (mic_threshold > 0.0f) { + mic_enabled = 1; + + // Make sure SDL audio is ready, just in case + if (real_SDL_WasInit(SDL_INIT_AUDIO) == 0) + real_SDL_InitSubSystem(SDL_INIT_AUDIO); + + int num_devices = real_SDL_GetNumAudioDevices(1); + const char* device_name = NULL; + for (int i = 0; i < num_devices; i++) { + const char* name = real_SDL_GetAudioDeviceName(i, 1); + // Use first available device (or look for Built-in) + if (name && (i == 0 || strstr(name, "Built-in"))) { + device_name = name; + break; + } + } + + // Configure audio capture + SDL_AudioSpec desired_spec = {0}; + desired_spec.freq = 44100; + desired_spec.format = AUDIO_S16SYS; + desired_spec.channels = 1; + desired_spec.samples = 2048; + desired_spec.callback = mic_audio_callback; + + SDL_AudioSpec obtained_spec; + mic_device = real_SDL_OpenAudioDevice(device_name, 1, &desired_spec, &obtained_spec, 0); + + if (mic_device > 0) // Opened, start capture + real_SDL_PauseAudioDevice(mic_device, 0); + else // Couldn't open, fallback to disable + mic_enabled = 0; + } + } +} + +__attribute__((destructor)) +static void cleanup(void) { + if (mic_device > 0 && real_SDL_CloseAudioDevice) { + real_SDL_CloseAudioDevice(mic_device); + } +} + +// Major thanks/credit to Shaun Inman for providing the basis of this hook library! \ No newline at end of file diff --git a/projects/ArchR/packages/emulators/standalone/drastic-sa/sources/microphone.wav b/projects/ArchR/packages/emulators/standalone/drastic-sa/sources/microphone.wav new file mode 100644 index 0000000000..7d58159181 Binary files /dev/null and b/projects/ArchR/packages/emulators/standalone/drastic-sa/sources/microphone.wav differ diff --git a/projects/ArchR/packages/emulators/standalone/duckstation-sa/config/H700/settings.ini b/projects/ArchR/packages/emulators/standalone/duckstation-sa/config/H700/settings.ini new file mode 100644 index 0000000000..3d91aa7780 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/duckstation-sa/config/H700/settings.ini @@ -0,0 +1,265 @@ +[Main] +SettingsVersion = 3 +StartFullscreen = true +EmulationSpeed = 1.000000 +FastForwardSpeed = 0.000000 +TurboSpeed = 0.000000 +SyncToHostRefreshRate = false +IncreaseTimerResolution = true +InhibitScreensaver = true +StartPaused = false +PauseOnFocusLoss = false +PauseOnMenu = true +SaveStateOnExit = true +ConfirmPowerOff = false +LoadDevicesFromSaveStates = false +ApplyGameSettings = true +AutoLoadCheats = true +DisableAllEnhancements = false +RewindEnable = false +RewindFrequency = 10.000000 +RewindSaveSlots = 10 +RunaheadFrameCount = 0 +NoDesktopFile = true + + +[BIOS] +SearchDirectory = /storage/roms/bios +PathNTSCU = +PathNTSCJ = +PathPAL = +PatchTTYEnable = false +PatchFastBoot = true + + +[GPU] +Renderer = Software +Adapter = +ResolutionScale = 1 +Multisamples = 1 +UseDebugDevice = false +PerSampleShading = false +UseThread = true +ThreadedPresentation = true +UseSoftwareRendererForReadbacks = false +TrueColor = false +ScaledDithering = false +TextureFilter = Nearest +DownsampleMode = Disabled +DisableInterlacing = false +ForceNTSCTimings = false +WidescreenHack = false +ChromaSmoothing24Bit = false +PGXPEnable = false +PGXPCulling = true +PGXPTextureCorrection = true +PGXPVertexCache = false +PGXPCPU = false +PGXPPreserveProjFP = false +PGXPTolerance = -1.000000 +PGXPDepthBuffer = false +PGXPDepthClearThreshold = 300.000000 + + +[Display] +CropMode = Overscan +ActiveStartOffset = 0 +ActiveEndOffset = 0 +LineStartOffset = 0 +LineEndOffset = 0 +Force4_3For24Bit = false +AspectRatio = 4:3 +CustomAspectRatioNumerator = 4 +LinearFiltering = true +IntegerScaling = false +Stretch = false +PostProcessing = false +ShowOSDMessages = true +ShowFPS = false +ShowVPS = false +ShowSpeed = false +ShowResolution = false +ShowStatusIndicators = true +ShowEnhancements = false +DisplayAllFrames = true +VSync = false +MaxFPS = 0.000000 + + +[Hotkeys] +OpenPauseMenu = SDL-0/Guide & SDL-0/X +FastForward = SDL-0/Guide & SDL-0/+RightTrigger +Screenshot = SDL-0/Guide & SDL-0/A +LoadSelectedSaveState = SDL-0/Guide & SDL-0/LeftShoulder +SaveSelectedSaveState = SDL-0/Guide & SDL-0/RightShoulder +PowerOff = SDL-0/Guide & SDL-0/Start + + +[Logging] +LogLevel = Error +LogFilter = +LogToConsole = false +LogToDebug = false +LogToWindow = false +LogToFile = false + + +[Controller1] +Type = AnalogController +ButtonUp = Controller0/Button11 +ButtonDown = Controller0/Button12 +ButtonLeft = Controller0/Button13 +ButtonRight = Controller0/Button14 +ButtonSelect = Controller0/Button4 +ButtonStart = Controller0/Button6 +ButtonTriangle = Controller0/Button2 +ButtonCross = Controller0/Button1 +ButtonSquare = Controller0/Button3 +ButtonCircle = Controller0/Button0 +ButtonL1 = Controller0/Button9 +ButtonL2 = Controller0/+Axis4 +ButtonR1 = Controller0/Button10 +ButtonR2 = Controller0/+Axis5 +AxisLeftX = Controller0/Axis0 +AxisLeftY = Controller0/Axis1 +ButtonL3 = Controller0/Button7 +ButtonR3 = Controller0/Button8 +AxisRightX = Controller0/Axis2 +AxisRightY = Controller0/Axis3 +AnalogDPadInDigitalMode = false + + +[GameList] +RecursivePaths = /storage/roms/psx + + +[MemoryCards] +UsePlaylistTitle = true +Directory = /storage/roms/psx +Card1Type = PerGameTitle +Card2Type = None + + +[Console] +Region = Auto +Enable8MBRAM = false + + +[CPU] +ExecutionMode = Recompiler +OverclockEnable = false +OverclockNumerator = 1 +OverclockDenominator = 1 +RecompilerMemoryExceptions = false +RecompilerBlockLinking = true +RecompilerICache = false +FastmemMode = MMap + + +[CDROM] +ReadaheadSectors = 8 +RegionCheck = false +LoadImageToRAM = false +MuteCDAudio = false +ReadSpeedup = 1 +SeekSpeedup = 1 + + +[Audio] +Backend = SDL +OutputVolume = 100 +FastForwardVolume = 100 +BufferSize = 2048 +Resampling = true +OutputMuted = false +Sync = true +DumpOnBoot = false + + +[Hacks] +DMAMaxSliceTicks = 1000 +DMAHaltTicks = 100 +GPUFIFOSize = 16 +GPUMaxRunAhead = 128 + + +[Controller2] +Type = None + + +[Controller3] +Type = None + + +[Controller4] +Type = None + + +[Controller5] +Type = None + + +[Controller6] +Type = None + + +[Controller7] +Type = None + + +[Controller8] +Type = None + + +[ControllerPorts] +MultitapMode = Disabled + + +[Debug] +ShowVRAM = false +DumpCPUToVRAMCopies = false +DumpVRAMToCPUCopies = false +ShowGPUState = false +ShowCDROMState = false +ShowSPUState = false +ShowTimersState = false +ShowMDECState = false +ShowDMAState = false + + +[TextureReplacements] +EnableVRAMWriteReplacements = false +PreloadTextures = false +DumpVRAMWrites = false +DumpVRAMWriteForceAlphaChannel = true +DumpVRAMWriteWidthThreshold = 128 +DumpVRAMWriteHeightThreshold = 128 + + +[Pad1] +Up = SDL-0/DPadUp +Right = SDL-0/DPadRight +Down = SDL-0/DPadDown +Left = SDL-0/DPadLeft +Triangle = SDL-0/X +Circle = SDL-0/A +Cross = SDL-0/B +Square = SDL-0/Y +Select = SDL-0/Back +Start = SDL-0/Start +L1 = SDL-0/LeftShoulder +R1 = SDL-0/RightShoulder +L2 = SDL-0/+LeftTrigger +R2 = SDL-0/+RightTrigger +L3 = SDL-0/LeftStick +R3 = SDL-0/RightStick +LLeft = SDL-0/-LeftX +LRight = SDL-0/+LeftX +LDown = SDL-0/+LeftY +LUp = SDL-0/-LeftY +RLeft = SDL-0/+RightX +RRight = SDL-0/-RightX +RDown = SDL-0/+RightY +RUp = SDL-0/-RightY +LargeMotor = SDL-0/LargeMotor +SmallMotor = SDL-0/SmallMotor diff --git a/projects/ArchR/packages/emulators/standalone/duckstation-sa/config/InputPlumber/settings.ini b/projects/ArchR/packages/emulators/standalone/duckstation-sa/config/InputPlumber/settings.ini new file mode 100644 index 0000000000..2e9be3c1a1 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/duckstation-sa/config/InputPlumber/settings.ini @@ -0,0 +1,266 @@ +[Main] +SettingsVersion = 3 +StartFullscreen = true +EmulationSpeed = 1.000000 +FastForwardSpeed = 0.000000 +TurboSpeed = 0.000000 +SyncToHostRefreshRate = false +IncreaseTimerResolution = true +InhibitScreensaver = true +StartPaused = false +PauseOnFocusLoss = false +PauseOnMenu = true +SaveStateOnExit = true +ConfirmPowerOff = false +LoadDevicesFromSaveStates = false +ApplyGameSettings = true +AutoLoadCheats = true +DisableAllEnhancements = false +RewindEnable = false +RewindFrequency = 10.000000 +RewindSaveSlots = 10 +RunaheadFrameCount = 0 +NoDesktopFile = true + + +[BIOS] +SearchDirectory = /storage/roms/bios +PathNTSCU = +PathNTSCJ = +PathPAL = +PatchTTYEnable = false +PatchFastBoot = true + + +[GPU] +Renderer = Software +Adapter = +ResolutionScale = 1 +Multisamples = 1 +UseDebugDevice = false +PerSampleShading = false +UseThread = true +ThreadedPresentation = true +UseSoftwareRendererForReadbacks = false +TrueColor = false +ScaledDithering = false +TextureFilter = Nearest +DownsampleMode = Disabled +DisableInterlacing = false +ForceNTSCTimings = false +WidescreenHack = false +ChromaSmoothing24Bit = false +PGXPEnable = false +PGXPCulling = true +PGXPTextureCorrection = true +PGXPVertexCache = false +PGXPCPU = false +PGXPPreserveProjFP = false +PGXPTolerance = -1.000000 +PGXPDepthBuffer = false +PGXPDepthClearThreshold = 300.000000 + + +[Display] +CropMode = Overscan +ActiveStartOffset = 0 +ActiveEndOffset = 0 +LineStartOffset = 0 +LineEndOffset = 0 +Force4_3For24Bit = false +AspectRatio = 4:3 +CustomAspectRatioNumerator = 4 +LinearFiltering = true +IntegerScaling = false +Stretch = false +PostProcessing = false +ShowOSDMessages = true +ShowFPS = false +ShowVPS = false +ShowSpeed = false +ShowResolution = false +ShowStatusIndicators = true +ShowEnhancements = false +DisplayAllFrames = true +VSync = true +MaxFPS = 0.000000 + + +[Hotkeys] +OpenPauseMenu = SDL-0/Guide & SDL-0/Y +FastForward = SDL-0/Guide & SDL-0/+RightTrigger +Screenshot = SDL-0/Guide & SDL-0/B +LoadSelectedSaveState = SDL-0/Guide & SDL-0/LeftShoulder +SaveSelectedSaveState = SDL-0/Guide & SDL-0/RightShoulder +PowerOff = SDL-0/Guide & SDL-0/Start + + +[Logging] +LogLevel = Error +LogFilter = +LogToConsole = false +LogToDebug = false +LogToWindow = false +LogToFile = false + + +[Controller1] +Type = AnalogController +ButtonUp = Controller0/Button11 +ButtonDown = Controller0/Button12 +ButtonLeft = Controller0/Button13 +ButtonRight = Controller0/Button14 +ButtonSelect = Controller0/Button4 +ButtonStart = Controller0/Button6 +ButtonTriangle = Controller0/Button2 +ButtonCross = Controller0/Button1 +ButtonSquare = Controller0/Button3 +ButtonCircle = Controller0/Button0 +ButtonL1 = Controller0/Button9 +ButtonL2 = Controller0/+Axis4 +ButtonR1 = Controller0/Button10 +ButtonR2 = Controller0/+Axis5 +AxisLeftX = Controller0/Axis0 +AxisLeftY = Controller0/Axis1 +ButtonL3 = Controller0/Button7 +ButtonR3 = Controller0/Button8 +AxisRightX = Controller0/Axis2 +AxisRightY = Controller0/Axis3 +AnalogDPadInDigitalMode = false + + +[GameList] +RecursivePaths = /storage/roms/psx + + +[MemoryCards] +UsePlaylistTitle = true +Directory = /storage/roms/psx +Card1Type = PerGameTitle +Card2Type = None + + +[Console] +Region = Auto +Enable8MBRAM = false + + +[CPU] +ExecutionMode = Recompiler +OverclockEnable = false +OverclockNumerator = 1 +OverclockDenominator = 1 +RecompilerMemoryExceptions = false +RecompilerBlockLinking = true +RecompilerICache = false +FastmemMode = MMap + + +[CDROM] +ReadaheadSectors = 8 +RegionCheck = false +LoadImageToRAM = false +MuteCDAudio = false +ReadSpeedup = 1 +SeekSpeedup = 1 + + +[Audio] +Backend = SDL +OutputVolume = 100 +FastForwardVolume = 100 +BufferSize = 2048 +Resampling = true +OutputMuted = false +Sync = true +DumpOnBoot = false +BufferMS = 100 + + +[Hacks] +DMAMaxSliceTicks = 1000 +DMAHaltTicks = 100 +GPUFIFOSize = 16 +GPUMaxRunAhead = 128 + + +[Controller2] +Type = None + + +[Controller3] +Type = None + + +[Controller4] +Type = None + + +[Controller5] +Type = None + + +[Controller6] +Type = None + + +[Controller7] +Type = None + + +[Controller8] +Type = None + + +[ControllerPorts] +MultitapMode = Disabled + + +[Debug] +ShowVRAM = false +DumpCPUToVRAMCopies = false +DumpVRAMToCPUCopies = false +ShowGPUState = false +ShowCDROMState = false +ShowSPUState = false +ShowTimersState = false +ShowMDECState = false +ShowDMAState = false + + +[TextureReplacements] +EnableVRAMWriteReplacements = false +PreloadTextures = false +DumpVRAMWrites = false +DumpVRAMWriteForceAlphaChannel = true +DumpVRAMWriteWidthThreshold = 128 +DumpVRAMWriteHeightThreshold = 128 + + +[Pad1] +Up = SDL-0/DPadUp +Right = SDL-0/DPadRight +Down = SDL-0/DPadDown +Left = SDL-0/DPadLeft +Triangle = SDL-0/Y +Circle = SDL-0/B +Cross = SDL-0/A +Square = SDL-0/X +Select = SDL-0/Back +Start = SDL-0/Start +L1 = SDL-0/LeftShoulder +R1 = SDL-0/RightShoulder +L2 = SDL-0/+LeftTrigger +R2 = SDL-0/+RightTrigger +L3 = SDL-0/LeftStick +R3 = SDL-0/RightStick +LLeft = SDL-0/-LeftX +LRight = SDL-0/+LeftX +LDown = SDL-0/+LeftY +LUp = SDL-0/-LeftY +RLeft = SDL-0/+RightX +RRight = SDL-0/-RightX +RDown = SDL-0/+RightY +RUp = SDL-0/-RightY +LargeMotor = SDL-0/LargeMotor +SmallMotor = SDL-0/SmallMotor diff --git a/projects/ArchR/packages/emulators/standalone/duckstation-sa/config/RK3326/settings.ini b/projects/ArchR/packages/emulators/standalone/duckstation-sa/config/RK3326/settings.ini new file mode 100644 index 0000000000..792c4a149f --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/duckstation-sa/config/RK3326/settings.ini @@ -0,0 +1,263 @@ +[Main] +SettingsVersion = 3 +StartFullscreen = true +EmulationSpeed = 1.000000 +FastForwardSpeed = 0.000000 +TurboSpeed = 0.000000 +SyncToHostRefreshRate = false +IncreaseTimerResolution = true +InhibitScreensaver = true +StartPaused = false +PauseOnFocusLoss = false +PauseOnMenu = true +SaveStateOnExit = true +ConfirmPowerOff = false +LoadDevicesFromSaveStates = false +ApplyGameSettings = true +AutoLoadCheats = true +DisableAllEnhancements = false +RewindEnable = false +RewindFrequency = 10.000000 +RewindSaveSlots = 10 +RunaheadFrameCount = 0 +NoDesktopFile = true + + +[BIOS] +SearchDirectory = /storage/roms/bios +PathNTSCU = +PathNTSCJ = +PathPAL = +PatchTTYEnable = false +PatchFastBoot = true + + +[GPU] +Renderer = Software +Adapter = +ResolutionScale = 1 +Multisamples = 1 +UseDebugDevice = false +PerSampleShading = false +UseThread = true +ThreadedPresentation = true +UseSoftwareRendererForReadbacks = false +TrueColor = false +ScaledDithering = false +TextureFilter = Nearest +DownsampleMode = Disabled +DisableInterlacing = false +ForceNTSCTimings = false +WidescreenHack = false +ChromaSmoothing24Bit = false +PGXPEnable = false +PGXPCulling = true +PGXPTextureCorrection = true +PGXPVertexCache = false +PGXPCPU = false +PGXPPreserveProjFP = false +PGXPTolerance = -1.000000 +PGXPDepthBuffer = false +PGXPDepthClearThreshold = 300.000000 + + +[Display] +CropMode = Overscan +ActiveStartOffset = 0 +ActiveEndOffset = 0 +LineStartOffset = 0 +LineEndOffset = 0 +Force4_3For24Bit = false +AspectRatio = 4:3 +CustomAspectRatioNumerator = 4 +LinearFiltering = true +IntegerScaling = false +Stretch = false +PostProcessing = false +ShowOSDMessages = true +ShowFPS = false +ShowVPS = false +ShowSpeed = false +ShowResolution = false +ShowStatusIndicators = true +ShowEnhancements = false +DisplayAllFrames = false +VSync = false +MaxFPS = 0.000000 + + +[Hotkeys] +OpenPauseMenu = SDL-0/Back & SDL-0/X +FastForward = SDL-0/Back & SDL-0/+RightTrigger +Screenshot = SDL-0/Back & SDL-0/A +LoadSelectedSaveState = SDL-0/Back & SDL-0/LeftShoulder +SaveSelectedSaveState = SDL-0/Back & SDL-0/RightShoulder +PowerOff = SDL-0/Back & SDL-0/Start + + +[Logging] +LogLevel = Error +LogFilter = +LogToConsole = false +LogToDebug = false +LogToWindow = false +LogToFile = false + + +[Controller1] +Type = AnalogController +ButtonUp = Controller0/Button11 +ButtonDown = Controller0/Button12 +ButtonLeft = Controller0/Button13 +ButtonRight = Controller0/Button14 +ButtonSelect = Controller0/Button4 +ButtonStart = Controller0/Button6 +ButtonTriangle = Controller0/Button2 +ButtonCross = Controller0/Button1 +ButtonSquare = Controller0/Button3 +ButtonCircle = Controller0/Button0 +ButtonL1 = Controller0/Button9 +ButtonL2 = Controller0/+Axis4 +ButtonR1 = Controller0/Button10 +ButtonR2 = Controller0/+Axis5 +AxisLeftX = Controller0/Axis0 +AxisLeftY = Controller0/Axis1 +ButtonL3 = Controller0/Button7 +ButtonR3 = Controller0/Button8 +AxisRightX = Controller0/Axis2 +AxisRightY = Controller0/Axis3 +AnalogDPadInDigitalMode = false + + +[GameList] +RecursivePaths = /storage/roms/psx + + +[MemoryCards] +UsePlaylistTitle = true +Directory = /storage/roms/psx +Card1Type = PerGameTitle +Card2Type = None + + +[Console] +Region = Auto +Enable8MBRAM = false + + +[CPU] +ExecutionMode = Recompiler +OverclockEnable = false +OverclockNumerator = 1 +OverclockDenominator = 1 +RecompilerMemoryExceptions = false +RecompilerBlockLinking = true +RecompilerICache = false +FastmemMode = MMap + + +[CDROM] +ReadaheadSectors = 16 +RegionCheck = false +LoadImageToRAM = false +MuteCDAudio = false +ReadSpeedup = 2 +SeekSpeedup = 2 + + +[Audio] +Backend = SDL +OutputVolume = 100 +FastForwardVolume = 100 +BufferSize = 2048 +Resampling = true +OutputMuted = false +Sync = true +DumpOnBoot = false + + +[Hacks] +DMAMaxSliceTicks = 1000 +DMAHaltTicks = 100 +GPUFIFOSize = 16 +GPUMaxRunAhead = 128 + + +[Controller2] +Type = None + + +[Controller3] +Type = None + + +[Controller4] +Type = None + + +[Controller5] +Type = None + + +[Controller6] +Type = None + + +[Controller7] +Type = None + + +[Controller8] +Type = None + + +[ControllerPorts] +MultitapMode = Disabled + + +[Debug] +ShowVRAM = false +DumpCPUToVRAMCopies = false +DumpVRAMToCPUCopies = false +ShowGPUState = false +ShowCDROMState = false +ShowSPUState = false +ShowTimersState = false +ShowMDECState = false +ShowDMAState = false + + +[TextureReplacements] +EnableVRAMWriteReplacements = false +PreloadTextures = false +DumpVRAMWrites = false +DumpVRAMWriteForceAlphaChannel = true +DumpVRAMWriteWidthThreshold = 128 +DumpVRAMWriteHeightThreshold = 128 + + +[Pad1] +Up = SDL-0/DPadUp +Right = SDL-0/DPadRight +Down = SDL-0/DPadDown +Left = SDL-0/DPadLeft +Triangle = SDL-0/X +Circle = SDL-0/A +Cross = SDL-0/B +Square = SDL-0/Y +Select = SDL-0/Back +Start = SDL-0/Start +L1 = SDL-0/LeftShoulder +R1 = SDL-0/RightShoulder +L2 = SDL-0/+LeftTrigger +R2 = SDL-0/+RightTrigger +L3 = SDL-0/LeftStick +R3 = SDL-0/RightStick +LLeft = SDL-0/-LeftX +LRight = SDL-0/+LeftX +LDown = SDL-0/+LeftY +LUp = SDL-0/-LeftY +RLeft = SDL-0/+RightX +RRight = SDL-0/-RightX +RDown = SDL-0/+RightY +RUp = SDL-0/-RightY diff --git a/projects/ArchR/packages/emulators/standalone/duckstation-sa/config/RK3399/settings.ini b/projects/ArchR/packages/emulators/standalone/duckstation-sa/config/RK3399/settings.ini new file mode 100644 index 0000000000..4894932bf6 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/duckstation-sa/config/RK3399/settings.ini @@ -0,0 +1,242 @@ +[Main] +SettingsVersion = 3 +StartFullscreen = true +EmulationSpeed = 1.000000 +FastForwardSpeed = 0.000000 +TurboSpeed = 0.000000 +SyncToHostRefreshRate = false +IncreaseTimerResolution = true +InhibitScreensaver = true +StartPaused = false +PauseOnFocusLoss = false +PauseOnMenu = true +SaveStateOnExit = true +ConfirmPowerOff = false +LoadDevicesFromSaveStates = false +ApplyGameSettings = true +AutoLoadCheats = true +DisableAllEnhancements = false +RewindEnable = false +RewindFrequency = 10.000000 +RewindSaveSlots = 10 +RunaheadFrameCount = 0 +NoDesktopFile = true + + +[BIOS] +SearchDirectory = /storage/roms/bios +PathNTSCU = +PathNTSCJ = +PathPAL = +PatchTTYEnable = false +PatchFastBoot = true + + +[GPU] +Renderer = Software +Adapter = +ResolutionScale = 1 +Multisamples = 1 +UseDebugDevice = false +PerSampleShading = false +UseThread = true +ThreadedPresentation = true +UseSoftwareRendererForReadbacks = false +TrueColor = false +ScaledDithering = false +TextureFilter = Nearest +DownsampleMode = Disabled +DisableInterlacing = false +ForceNTSCTimings = false +WidescreenHack = false +ChromaSmoothing24Bit = false +PGXPEnable = false +PGXPCulling = true +PGXPTextureCorrection = true +PGXPVertexCache = false +PGXPCPU = false +PGXPPreserveProjFP = false +PGXPTolerance = -1.000000 +PGXPDepthBuffer = false +PGXPDepthClearThreshold = 300.000000 + + +[Display] +CropMode = Overscan +ActiveStartOffset = 0 +ActiveEndOffset = 0 +LineStartOffset = 0 +LineEndOffset = 0 +Force4_3For24Bit = false +AspectRatio = 4:3 +CustomAspectRatioNumerator = 4 +LinearFiltering = true +IntegerScaling = false +Stretch = false +PostProcessing = false +ShowOSDMessages = true +ShowFPS = false +ShowVPS = false +ShowSpeed = false +ShowResolution = false +ShowStatusIndicators = true +ShowEnhancements = false +DisplayAllFrames = true +VSync = false +MaxFPS = 0.000000 + + +[Hotkeys] +OpenPauseMenu = SDL-0/Back & SDL-0/X +FastForward = SDL-0/Back & SDL-0/+RightTrigger +Screenshot = SDL-0/Back & SDL-0/A +LoadSelectedSaveState = SDL-0/Back & SDL-0/LeftShoulder +SaveSelectedSaveState = SDL-0/Back & SDL-0/RightShoulder +PowerOff = SDL-0/Back & SDL-0/Start + + +[Logging] +LogLevel = Error +LogFilter = +LogToConsole = false +LogToDebug = false +LogToWindow = false +LogToFile = false + + +[GameList] +RecursivePaths = /storage/roms/psx + + +[MemoryCards] +UsePlaylistTitle = true +Directory = /storage/roms/psx +Card1Type = PerGameTitle +Card2Type = None + + +[Console] +Region = Auto +Enable8MBRAM = false + + +[CPU] +ExecutionMode = Recompiler +OverclockEnable = false +OverclockNumerator = 1 +OverclockDenominator = 1 +RecompilerMemoryExceptions = false +RecompilerBlockLinking = true +RecompilerICache = false +FastmemMode = MMap + + +[CDROM] +ReadaheadSectors = 8 +RegionCheck = false +LoadImageToRAM = false +MuteCDAudio = false +ReadSpeedup = 1 +SeekSpeedup = 1 + + +[Audio] +Backend = SDL +OutputVolume = 100 +FastForwardVolume = 100 +BufferSize = 2048 +Resampling = true +OutputMuted = false +Sync = true +DumpOnBoot = false + + +[Hacks] +DMAMaxSliceTicks = 1000 +DMAHaltTicks = 100 +GPUFIFOSize = 16 +GPUMaxRunAhead = 128 + + +[Controller1] +Type = AnalogController + + +[Controller2] +Type = None + + +[Controller3] +Type = None + + +[Controller4] +Type = None + + +[Controller5] +Type = None + + +[Controller6] +Type = None + + +[Controller7] +Type = None + + +[Controller8] +Type = None + + +[ControllerPorts] +MultitapMode = Disabled + + +[Debug] +ShowVRAM = false +DumpCPUToVRAMCopies = false +DumpVRAMToCPUCopies = false +ShowGPUState = false +ShowCDROMState = false +ShowSPUState = false +ShowTimersState = false +ShowMDECState = false +ShowDMAState = false + + +[TextureReplacements] +EnableVRAMWriteReplacements = false +PreloadTextures = false +DumpVRAMWrites = false +DumpVRAMWriteForceAlphaChannel = true +DumpVRAMWriteWidthThreshold = 128 +DumpVRAMWriteHeightThreshold = 128 + + +[Pad1] +Up = SDL-0/DPadUp +Right = SDL-0/DPadRight +Down = SDL-0/DPadDown +Left = SDL-0/DPadLeft +Triangle = SDL-0/X +Circle = SDL-0/A +Cross = SDL-0/B +Square = SDL-0/Y +Select = SDL-0/Back +Start = SDL-0/Start +L1 = SDL-0/LeftShoulder +R1 = SDL-0/RightShoulder +L2 = SDL-0/+LeftTrigger +R2 = SDL-0/+RightTrigger +L3 = SDL-0/LeftStick +R3 = SDL-0/RightStick +LLeft = SDL-0/-LeftX +LRight = SDL-0/+LeftX +LDown = SDL-0/+LeftY +LUp = SDL-0/-LeftY +RLeft = SDL-0/+RightX +RRight = SDL-0/-RightX +RDown = SDL-0/+RightY +RUp = SDL-0/-RightY diff --git a/projects/ArchR/packages/emulators/standalone/duckstation-sa/config/RK3566/settings.ini b/projects/ArchR/packages/emulators/standalone/duckstation-sa/config/RK3566/settings.ini new file mode 100644 index 0000000000..9750aebd96 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/duckstation-sa/config/RK3566/settings.ini @@ -0,0 +1,240 @@ +[Main] +SettingsVersion = 3 +StartFullscreen = true +EmulationSpeed = 1.000000 +FastForwardSpeed = 0.000000 +TurboSpeed = 0.000000 +SyncToHostRefreshRate = false +IncreaseTimerResolution = true +InhibitScreensaver = true +StartPaused = false +PauseOnFocusLoss = false +PauseOnMenu = true +SaveStateOnExit = true +ConfirmPowerOff = false +LoadDevicesFromSaveStates = false +ApplyGameSettings = true +AutoLoadCheats = true +DisableAllEnhancements = false +RewindEnable = false +RewindFrequency = 10.000000 +RewindSaveSlots = 10 +RunaheadFrameCount = 0 +NoDesktopFile = true + + +[BIOS] +SearchDirectory = /storage/roms/bios +PathNTSCU = +PathNTSCJ = +PathPAL = +PatchTTYEnable = false +PatchFastBoot = true + + +[GPU] +Renderer = Software +Adapter = +ResolutionScale = 1 +Multisamples = 1 +UseDebugDevice = false +PerSampleShading = false +UseThread = true +ThreadedPresentation = true +UseSoftwareRendererForReadbacks = false +TrueColor = false +ScaledDithering = false +TextureFilter = Nearest +DownsampleMode = Disabled +DisableInterlacing = false +ForceNTSCTimings = false +WidescreenHack = false +ChromaSmoothing24Bit = false +PGXPEnable = false +PGXPCulling = true +PGXPTextureCorrection = true +PGXPVertexCache = false +PGXPCPU = false +PGXPPreserveProjFP = false +PGXPTolerance = -1.000000 +PGXPDepthBuffer = false +PGXPDepthClearThreshold = 300.000000 + + +[Display] +CropMode = Overscan +ActiveStartOffset = 0 +ActiveEndOffset = 0 +LineStartOffset = 0 +LineEndOffset = 0 +Force4_3For24Bit = false +AspectRatio = 4:3 +CustomAspectRatioNumerator = 4 +LinearFiltering = true +IntegerScaling = false +Stretch = false +PostProcessing = false +ShowOSDMessages = true +ShowFPS = false +ShowVPS = false +ShowSpeed = false +ShowResolution = false +ShowStatusIndicators = true +ShowEnhancements = false +DisplayAllFrames = true +VSync = false +MaxFPS = 0.000000 +Rotation = 0 + + +[Hotkeys] +OpenPauseMenu = SDL-0/Back & SDL-0/X +FastForward = SDL-0/Back & SDL-0/+RightTrigger +Screenshot = SDL-0/Back & SDL-0/A +LoadSelectedSaveState = SDL-0/Back & SDL-0/LeftShoulder +SaveSelectedSaveState = SDL-0/Back & SDL-0/RightShoulder +PowerOff = SDL-0/Back & SDL-0/Start + +[Logging] +LogLevel = Error +LogFilter = +LogToConsole = false +LogToDebug = false +LogToWindow = false +LogToFile = false + + +[GameList] +RecursivePaths = /storage/roms/psx + + +[MemoryCards] +UsePlaylistTitle = true +Directory = /storage/roms/psx +Card1Type = PerGameTitle +Card2Type = None + + +[Console] +Region = Auto +Enable8MBRAM = false + + +[CPU] +ExecutionMode = Recompiler +OverclockEnable = false +OverclockNumerator = 1 +OverclockDenominator = 1 +RecompilerMemoryExceptions = false +RecompilerBlockLinking = true +RecompilerICache = false +FastmemMode = MMap + + +[CDROM] +ReadaheadSectors = 8 +RegionCheck = false +LoadImageToRAM = false +MuteCDAudio = false +ReadSpeedup = 1 +SeekSpeedup = 1 + + +[Audio] +Backend = SDL +OutputVolume = 100 +FastForwardVolume = 100 +BufferSize = 2048 +Resampling = true +OutputMuted = false +Sync = true +DumpOnBoot = false + + +[Hacks] +DMAMaxSliceTicks = 1000 +DMAHaltTicks = 100 +GPUFIFOSize = 16 +GPUMaxRunAhead = 128 + +[Controller1] +Type = AnalogController + + +[Controller2] +Type = None + + +[Controller3] +Type = None + + +[Controller4] +Type = None + + +[Controller5] +Type = None + + +[Controller6] +Type = None + + +[Controller7] +Type = None + + +[Controller8] +Type = None + + +[ControllerPorts] +MultitapMode = Disabled + + +[Debug] +ShowVRAM = false +DumpCPUToVRAMCopies = false +DumpVRAMToCPUCopies = false +ShowGPUState = false +ShowCDROMState = false +ShowSPUState = false +ShowTimersState = false +ShowMDECState = false +ShowDMAState = false + + +[TextureReplacements] +EnableVRAMWriteReplacements = false +PreloadTextures = false +DumpVRAMWrites = false +DumpVRAMWriteForceAlphaChannel = true +DumpVRAMWriteWidthThreshold = 128 +DumpVRAMWriteHeightThreshold = 128 + +[Pad1] +Up = SDL-0/DPadUp +Right = SDL-0/DPadRight +Down = SDL-0/DPadDown +Left = SDL-0/DPadLeft +Triangle = SDL-0/X +Circle = SDL-0/A +Cross = SDL-0/B +Square = SDL-0/Y +Select = SDL-0/Back +Start = SDL-0/Start +L1 = SDL-0/LeftShoulder +R1 = SDL-0/RightShoulder +L2 = SDL-0/+LeftTrigger +R2 = SDL-0/+RightTrigger +L3 = SDL-0/LeftStick +R3 = SDL-0/RightStick +LLeft = SDL-0/-LeftX +LRight = SDL-0/+LeftX +LDown = SDL-0/+LeftY +LUp = SDL-0/-LeftY +RLeft = SDL-0/+RightX +RRight = SDL-0/-RightX +RDown = SDL-0/+RightY +RUp = SDL-0/-RightY diff --git a/projects/ArchR/packages/emulators/standalone/duckstation-sa/config/RK3588/settings.ini b/projects/ArchR/packages/emulators/standalone/duckstation-sa/config/RK3588/settings.ini new file mode 100644 index 0000000000..07a70fac16 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/duckstation-sa/config/RK3588/settings.ini @@ -0,0 +1,242 @@ +[Main] +SettingsVersion = 3 +StartFullscreen = true +EmulationSpeed = 1.000000 +FastForwardSpeed = 0.000000 +TurboSpeed = 0.000000 +SyncToHostRefreshRate = false +IncreaseTimerResolution = true +InhibitScreensaver = true +StartPaused = false +PauseOnFocusLoss = false +PauseOnMenu = true +SaveStateOnExit = true +ConfirmPowerOff = false +LoadDevicesFromSaveStates = false +ApplyGameSettings = true +AutoLoadCheats = true +DisableAllEnhancements = false +RewindEnable = false +RewindFrequency = 10.000000 +RewindSaveSlots = 10 +RunaheadFrameCount = 0 +NoDesktopFile = true + + +[BIOS] +SearchDirectory = /storage/roms/bios +PathNTSCU = +PathNTSCJ = +PathPAL = +PatchTTYEnable = false +PatchFastBoot = true + + +[GPU] +Renderer = Software +Adapter = +ResolutionScale = 1 +Multisamples = 1 +UseDebugDevice = false +PerSampleShading = false +UseThread = true +ThreadedPresentation = true +UseSoftwareRendererForReadbacks = false +TrueColor = false +ScaledDithering = false +TextureFilter = Nearest +DownsampleMode = Disabled +DisableInterlacing = false +ForceNTSCTimings = false +WidescreenHack = false +ChromaSmoothing24Bit = false +PGXPEnable = false +PGXPCulling = true +PGXPTextureCorrection = true +PGXPVertexCache = false +PGXPCPU = false +PGXPPreserveProjFP = false +PGXPTolerance = -1.000000 +PGXPDepthBuffer = false +PGXPDepthClearThreshold = 300.000000 + + +[Display] +CropMode = Overscan +ActiveStartOffset = 0 +ActiveEndOffset = 0 +LineStartOffset = 0 +LineEndOffset = 0 +Force4_3For24Bit = false +AspectRatio = 4:3 +CustomAspectRatioNumerator = 4 +LinearFiltering = true +IntegerScaling = false +Stretch = false +PostProcessing = false +ShowOSDMessages = true +ShowFPS = false +ShowVPS = false +ShowSpeed = false +ShowResolution = false +ShowStatusIndicators = true +ShowEnhancements = false +DisplayAllFrames = true +VSync = false +MaxFPS = 0.000000 + + +[Hotkeys] +OpenPauseMenu = SDL-0/Guide & SDL-0/X +FastForward = SDL-0/Guide & SDL-0/+RightTrigger +Screenshot = SDL-0/Guide & SDL-0/A +LoadSelectedSaveState = SDL-0/Guide & SDL-0/LeftShoulder +SaveSelectedSaveState = SDL-0/Guide & SDL-0/RightShoulder +PowerOff = SDL-0/Guide & SDL-0/Start + + +[Logging] +LogLevel = Error +LogFilter = +LogToConsole = false +LogToDebug = false +LogToWindow = false +LogToFile = false + + +[GameList] +RecursivePaths = /storage/roms/psx + + +[MemoryCards] +UsePlaylistTitle = true +Directory = /storage/roms/psx +Card1Type = PerGameTitle +Card2Type = None + + +[Console] +Region = Auto +Enable8MBRAM = false + + +[CPU] +ExecutionMode = Recompiler +OverclockEnable = false +OverclockNumerator = 1 +OverclockDenominator = 1 +RecompilerMemoryExceptions = false +RecompilerBlockLinking = true +RecompilerICache = false +FastmemMode = MMap + + +[CDROM] +ReadaheadSectors = 8 +RegionCheck = false +LoadImageToRAM = false +MuteCDAudio = false +ReadSpeedup = 1 +SeekSpeedup = 1 + + +[Audio] +Backend = SDL +OutputVolume = 100 +FastForwardVolume = 100 +BufferSize = 2048 +Resampling = true +OutputMuted = false +Sync = true +DumpOnBoot = false + + +[Hacks] +DMAMaxSliceTicks = 1000 +DMAHaltTicks = 100 +GPUFIFOSize = 16 +GPUMaxRunAhead = 128 + + +[Controller1] +Type = AnalogController + + +[Controller2] +Type = None + + +[Controller3] +Type = None + + +[Controller4] +Type = None + + +[Controller5] +Type = None + + +[Controller6] +Type = None + + +[Controller7] +Type = None + + +[Controller8] +Type = None + + +[ControllerPorts] +MultitapMode = Disabled + + +[Debug] +ShowVRAM = false +DumpCPUToVRAMCopies = false +DumpVRAMToCPUCopies = false +ShowGPUState = false +ShowCDROMState = false +ShowSPUState = false +ShowTimersState = false +ShowMDECState = false +ShowDMAState = false + + +[TextureReplacements] +EnableVRAMWriteReplacements = false +PreloadTextures = false +DumpVRAMWrites = false +DumpVRAMWriteForceAlphaChannel = true +DumpVRAMWriteWidthThreshold = 128 +DumpVRAMWriteHeightThreshold = 128 + + +[Pad1] +Up = SDL-0/DPadUp +Right = SDL-0/DPadRight +Down = SDL-0/DPadDown +Left = SDL-0/DPadLeft +Triangle = SDL-0/X +Circle = SDL-0/A +Cross = SDL-0/B +Square = SDL-0/Y +Select = SDL-0/Back +Start = SDL-0/Start +L1 = SDL-0/LeftShoulder +R1 = SDL-0/RightShoulder +L2 = SDL-0/+LeftTrigger +R2 = SDL-0/+RightTrigger +L3 = SDL-0/LeftStick +R3 = SDL-0/RightStick +LLeft = SDL-0/-LeftX +LRight = SDL-0/+LeftX +LDown = SDL-0/+LeftY +LUp = SDL-0/-LeftY +RLeft = SDL-0/-RightX +RRight = SDL-0/+RightX +RDown = SDL-0/+RightY +RUp = SDL-0/-RightY diff --git a/projects/ArchR/packages/emulators/standalone/duckstation-sa/config/S922X/settings.ini b/projects/ArchR/packages/emulators/standalone/duckstation-sa/config/S922X/settings.ini new file mode 100644 index 0000000000..8cab1f305f --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/duckstation-sa/config/S922X/settings.ini @@ -0,0 +1,321 @@ +[Main] +SettingsVersion = 3 +EmulationSpeed = 1.000000 +FastForwardSpeed = 0.000000 +TurboSpeed = 0.000000 +SyncToHostRefreshRate = false +IncreaseTimerResolution = true +InhibitScreensaver = true +StartPaused = false +StartFullscreen = true +PauseOnFocusLoss = false +PauseOnMenu = true +SaveStateOnExit = true +CreateSaveStateBackups = true +CompressSaveStates = true +ConfirmPowerOff = false +LoadDevicesFromSaveStates = false +ApplyCompatibilitySettings = true +ApplyGameSettings = true +AutoLoadCheats = true +DisableAllEnhancements = false +RewindEnable = false +RewindFrequency = 10.000000 +RewindSaveSlots = 10 +RunaheadFrameCount = 0 +NoDesktopFile = true + + +[Console] +Region = Auto +Enable8MBRAM = false + + +[CPU] +ExecutionMode = Recompiler +OverclockEnable = false +OverclockNumerator = 1 +OverclockDenominator = 1 +RecompilerMemoryExceptions = false +RecompilerBlockLinking = true +RecompilerICache = false +FastmemMode = MMap + + +[GPU] +Renderer = Software +Adapter = +ResolutionScale = 1 +Multisamples = 1 +UseDebugDevice = false +PerSampleShading = false +UseThread = true +ThreadedPresentation = true +UseSoftwareRendererForReadbacks = false +TrueColor = true +ScaledDithering = true +TextureFilter = Nearest +DownsampleMode = Disabled +DisableInterlacing = true +ForceNTSCTimings = false +WidescreenHack = false +ChromaSmoothing24Bit = false +PGXPEnable = false +PGXPCulling = true +PGXPTextureCorrection = true +PGXPVertexCache = false +PGXPCPU = false +PGXPPreserveProjFP = false +PGXPTolerance = -1.000000 +PGXPDepthBuffer = false +PGXPDepthClearThreshold = 1228800.000000 +FullscreenMode = + + +[Display] +CropMode = Overscan +ActiveStartOffset = 0 +ActiveEndOffset = 0 +LineStartOffset = 0 +LineEndOffset = 0 +Force4_3For24Bit = false +AspectRatio = Auto (Game Native) +CustomAspectRatioNumerator = 0 +LinearFiltering = true +IntegerScaling = false +Stretch = false +PostProcessing = false +ShowOSDMessages = true +ShowFPS = false +ShowSpeed = false +ShowResolution = false +ShowCPU = false +ShowGPU = false +ShowStatusIndicators = true +ShowInputs = false +ShowEnhancements = false +DisplayAllFrames = false +InternalResolutionScreenshots = false +VSync = false +MaxFPS = 0.000000 +OSDScale = 100.000000 + + +[CDROM] +ReadaheadSectors = 8 +RegionCheck = false +LoadImageToRAM = false +LoadImagePatches = false +MuteCDAudio = false +ReadSpeedup = 1 +SeekSpeedup = 1 + + +[Audio] +Backend = Cubeb +Driver = +StretchMode = TimeStretch +BufferMS = 50 +OutputLatencyMS = 20 +OutputVolume = 100 +FastForwardVolume = 100 +OutputMuted = false +DumpOnBoot = false + + +[Hacks] +DMAMaxSliceTicks = 1000 +DMAHaltTicks = 100 +GPUFIFOSize = 16 +GPUMaxRunAhead = 128 + + +[BIOS] +SearchDirectory = /storage/roms/bios +PathNTSCU = +PathNTSCJ = +PathPAL = +PatchTTYEnable = false +PatchFastBoot = true + + +[Controller1] +Type = AnalogController + + +[Controller2] +Type = None + + +[Controller3] +Type = None + + +[Controller4] +Type = None + + +[Controller5] +Type = None + + +[Controller6] +Type = None + + +[Controller7] +Type = None + + +[Controller8] +Type = None + + +[MemoryCards] +Card1Type = PerGameTitle +Card2Type = None +UsePlaylistTitle = true +Directory = memcards + + +[ControllerPorts] +MultitapMode = Disabled +PointerXScale = 8.000000 +PointerYScale = 8.000000 +PointerXInvert = false +PointerYInvert = false + + +[Cheevos] +Enabled = false +TestMode = false +UnofficialTestMode = false +UseFirstDiscFromPlaylist = true +RichPresence = false +ChallengeMode = false + + +[Logging] +LogLevel = Error +LogFilter = +LogToConsole = false +LogToDebug = false +LogToWindow = false +LogToFile = false + + +[Debug] +ShowVRAM = false +DumpCPUToVRAMCopies = false +DumpVRAMToCPUCopies = false +ShowGPUState = false +ShowCDROMState = false +ShowSPUState = false +ShowTimersState = false +ShowMDECState = false +ShowDMAState = false + + +[TextureReplacements] +EnableVRAMWriteReplacements = false +PreloadTextures = false +DumpVRAMWrites = false +DumpVRAMWriteForceAlphaChannel = true +DumpVRAMWriteWidthThreshold = 128 +DumpVRAMWriteHeightThreshold = 128 + + +[Folders] +Cache = cache +Cheats = cheats +Covers = covers +Dumps = dump +GameSettings = gamesettings +InputProfiles = inputprofiles +SaveStates = savestates +Screenshots = screenshots +Shaders = shaders +Textures = textures + + +[InputSources] +SDL = true +SDLControllerEnhancedMode = false +Evdev = false +XInput = false +RawInput = false + + +[Pad1] +Up = SDL-0/DPadUp +Right = SDL-0/DPadRight +Down = SDL-0/DPadDown +Left = SDL-0/DPadLeft +Triangle = SDL-0/X +Circle = SDL-0/A +Cross = SDL-0/B +Square = SDL-0/Y +Select = SDL-0/Back +Start = SDL-0/Start +L1 = SDL-0/LeftShoulder +R1 = SDL-0/RightShoulder +L2 = SDL-0/+LeftTrigger +R2 = SDL-0/+RightTrigger +L3 = SDL-0/LeftStick +R3 = SDL-0/RightStick +LLeft = SDL-0/-LeftX +LRight = SDL-0/+LeftX +LDown = SDL-0/+LeftY +LUp = SDL-0/-LeftY +RLeft = SDL-0/-RightX +RRight = SDL-0/+RightX +RDown = SDL-0/+RightY +RUp = SDL-0/-RightY + + +[Pad2] +Type = None + + +[Pad3] +Type = None + + +[Pad4] +Type = None + + +[Pad5] +Type = None + + +[Pad6] +Type = None + + +[Pad7] +Type = None + + +[Pad8] +Type = None + + +[Hotkeys] +OpenPauseMenu = SDL-0/Guide & SDL-0/X +FastForward = SDL-0/Guide & SDL-0/+RightTrigger +Screenshot = SDL-0/Guide & SDL-0/A +LoadSelectedSaveState = SDL-0/Guide & SDL-0/LeftShoulder +SaveSelectedSaveState = SDL-0/Guide & SDL-0/RightShoulder +PowerOff = SDL-0/Guide & SDL-0/Start + + +[NoGUI] +WindowX = 0 +WindowY = 0 +WindowWidth = 854 +WindowHeight = 480 + + +[GameList] +RecursivePaths = /storage/roms/psx diff --git a/projects/ArchR/packages/emulators/standalone/duckstation-sa/config/SDM845/settings.ini b/projects/ArchR/packages/emulators/standalone/duckstation-sa/config/SDM845/settings.ini new file mode 100644 index 0000000000..362f424d47 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/duckstation-sa/config/SDM845/settings.ini @@ -0,0 +1,264 @@ +[Main] +SettingsVersion = 3 +StartFullscreen = true +EmulationSpeed = 1.000000 +FastForwardSpeed = 0.000000 +TurboSpeed = 0.000000 +SyncToHostRefreshRate = false +IncreaseTimerResolution = true +InhibitScreensaver = true +StartPaused = false +PauseOnFocusLoss = false +PauseOnMenu = true +SaveStateOnExit = true +ConfirmPowerOff = false +LoadDevicesFromSaveStates = false +ApplyGameSettings = true +AutoLoadCheats = true +DisableAllEnhancements = false +RewindEnable = false +RewindFrequency = 10.000000 +RewindSaveSlots = 10 +RunaheadFrameCount = 0 +NoDesktopFile = true + + +[BIOS] +SearchDirectory = /storage/roms/bios +PathNTSCU = +PathNTSCJ = +PathPAL = +PatchTTYEnable = false +PatchFastBoot = true + + +[GPU] +Renderer = Software +Adapter = +ResolutionScale = 1 +Multisamples = 1 +UseDebugDevice = false +PerSampleShading = false +UseThread = true +ThreadedPresentation = true +UseSoftwareRendererForReadbacks = false +TrueColor = false +ScaledDithering = false +TextureFilter = Nearest +DownsampleMode = Disabled +DisableInterlacing = false +ForceNTSCTimings = false +WidescreenHack = false +ChromaSmoothing24Bit = false +PGXPEnable = false +PGXPCulling = true +PGXPTextureCorrection = true +PGXPVertexCache = false +PGXPCPU = false +PGXPPreserveProjFP = false +PGXPTolerance = -1.000000 +PGXPDepthBuffer = false +PGXPDepthClearThreshold = 300.000000 + + +[Display] +CropMode = Overscan +ActiveStartOffset = 0 +ActiveEndOffset = 0 +LineStartOffset = 0 +LineEndOffset = 0 +Force4_3For24Bit = false +AspectRatio = 4:3 +CustomAspectRatioNumerator = 4 +LinearFiltering = true +IntegerScaling = false +Stretch = false +PostProcessing = false +ShowOSDMessages = true +ShowFPS = false +ShowVPS = false +ShowSpeed = false +ShowResolution = false +ShowStatusIndicators = true +ShowEnhancements = false +DisplayAllFrames = true +VSync = true +MaxFPS = 0.000000 + + +[Hotkeys] +OpenPauseMenu = SDL-0/Guide & SDL-0/X +FastForward = SDL-0/Guide & SDL-0/+RightTrigger +Screenshot = SDL-0/Back & SDL-0/A +LoadSelectedSaveState = SDL-0/Guide & SDL-0/LeftShoulder +SaveSelectedSaveState = SDL-0/Guide & SDL-0/RightShoulder +PowerOff = SDL-0/Guide & SDL-0/Start + + +[Logging] +LogLevel = Error +LogFilter = +LogToConsole = false +LogToDebug = false +LogToWindow = false +LogToFile = false + + +[Controller1] +Type = AnalogController +ButtonUp = Controller0/Button11 +ButtonDown = Controller0/Button12 +ButtonLeft = Controller0/Button13 +ButtonRight = Controller0/Button14 +ButtonSelect = Controller0/Button4 +ButtonStart = Controller0/Button6 +ButtonTriangle = Controller0/Button2 +ButtonCross = Controller0/Button1 +ButtonSquare = Controller0/Button3 +ButtonCircle = Controller0/Button0 +ButtonL1 = Controller0/Button9 +ButtonL2 = Controller0/+Axis4 +ButtonR1 = Controller0/Button10 +ButtonR2 = Controller0/+Axis5 +AxisLeftX = Controller0/Axis0 +AxisLeftY = Controller0/Axis1 +ButtonL3 = Controller0/Button7 +ButtonR3 = Controller0/Button8 +AxisRightX = Controller0/Axis2 +AxisRightY = Controller0/Axis3 +AnalogDPadInDigitalMode = false + + +[GameList] +RecursivePaths = /storage/roms/psx + + +[MemoryCards] +UsePlaylistTitle = true +Directory = /storage/roms/psx +Card1Type = PerGameTitle +Card2Type = None + + +[Console] +Region = Auto +Enable8MBRAM = false + + +[CPU] +ExecutionMode = Recompiler +OverclockEnable = false +OverclockNumerator = 1 +OverclockDenominator = 1 +RecompilerMemoryExceptions = false +RecompilerBlockLinking = true +RecompilerICache = false +FastmemMode = MMap + + +[CDROM] +ReadaheadSectors = 8 +RegionCheck = false +LoadImageToRAM = false +MuteCDAudio = false +ReadSpeedup = 1 +SeekSpeedup = 1 + + +[Audio] +Backend = SDL +OutputVolume = 100 +FastForwardVolume = 100 +BufferSize = 2048 +Resampling = true +OutputMuted = false +Sync = true +DumpOnBoot = false +BufferMS = 100 + + +[Hacks] +DMAMaxSliceTicks = 1000 +DMAHaltTicks = 100 +GPUFIFOSize = 16 +GPUMaxRunAhead = 128 + + +[Controller2] +Type = None + + +[Controller3] +Type = None + + +[Controller4] +Type = None + + +[Controller5] +Type = None + + +[Controller6] +Type = None + + +[Controller7] +Type = None + + +[Controller8] +Type = None + + +[ControllerPorts] +MultitapMode = Disabled + + +[Debug] +ShowVRAM = false +DumpCPUToVRAMCopies = false +DumpVRAMToCPUCopies = false +ShowGPUState = false +ShowCDROMState = false +ShowSPUState = false +ShowTimersState = false +ShowMDECState = false +ShowDMAState = false + + +[TextureReplacements] +EnableVRAMWriteReplacements = false +PreloadTextures = false +DumpVRAMWrites = false +DumpVRAMWriteForceAlphaChannel = true +DumpVRAMWriteWidthThreshold = 128 +DumpVRAMWriteHeightThreshold = 128 + + +[Pad1] +Up = SDL-0/DPadUp +Right = SDL-0/DPadRight +Down = SDL-0/DPadDown +Left = SDL-0/DPadLeft +Triangle = SDL-0/X +Circle = SDL-0/A +Cross = SDL-0/B +Square = SDL-0/Y +Select = SDL-0/Back +Start = SDL-0/Start +L1 = SDL-0/LeftShoulder +R1 = SDL-0/RightShoulder +L2 = SDL-0/+LeftTrigger +R2 = SDL-0/+RightTrigger +L3 = SDL-0/LeftStick +R3 = SDL-0/RightStick +LLeft = SDL-0/-LeftX +LRight = SDL-0/+LeftX +LDown = SDL-0/+LeftY +LUp = SDL-0/-LeftY +RLeft = SDL-0/+RightX +RRight = SDL-0/-RightX +RDown = SDL-0/+RightY +RUp = SDL-0/-RightY diff --git a/projects/ArchR/packages/emulators/standalone/duckstation-sa/config/SM8250/settings.ini b/projects/ArchR/packages/emulators/standalone/duckstation-sa/config/SM8250/settings.ini new file mode 100644 index 0000000000..362f424d47 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/duckstation-sa/config/SM8250/settings.ini @@ -0,0 +1,264 @@ +[Main] +SettingsVersion = 3 +StartFullscreen = true +EmulationSpeed = 1.000000 +FastForwardSpeed = 0.000000 +TurboSpeed = 0.000000 +SyncToHostRefreshRate = false +IncreaseTimerResolution = true +InhibitScreensaver = true +StartPaused = false +PauseOnFocusLoss = false +PauseOnMenu = true +SaveStateOnExit = true +ConfirmPowerOff = false +LoadDevicesFromSaveStates = false +ApplyGameSettings = true +AutoLoadCheats = true +DisableAllEnhancements = false +RewindEnable = false +RewindFrequency = 10.000000 +RewindSaveSlots = 10 +RunaheadFrameCount = 0 +NoDesktopFile = true + + +[BIOS] +SearchDirectory = /storage/roms/bios +PathNTSCU = +PathNTSCJ = +PathPAL = +PatchTTYEnable = false +PatchFastBoot = true + + +[GPU] +Renderer = Software +Adapter = +ResolutionScale = 1 +Multisamples = 1 +UseDebugDevice = false +PerSampleShading = false +UseThread = true +ThreadedPresentation = true +UseSoftwareRendererForReadbacks = false +TrueColor = false +ScaledDithering = false +TextureFilter = Nearest +DownsampleMode = Disabled +DisableInterlacing = false +ForceNTSCTimings = false +WidescreenHack = false +ChromaSmoothing24Bit = false +PGXPEnable = false +PGXPCulling = true +PGXPTextureCorrection = true +PGXPVertexCache = false +PGXPCPU = false +PGXPPreserveProjFP = false +PGXPTolerance = -1.000000 +PGXPDepthBuffer = false +PGXPDepthClearThreshold = 300.000000 + + +[Display] +CropMode = Overscan +ActiveStartOffset = 0 +ActiveEndOffset = 0 +LineStartOffset = 0 +LineEndOffset = 0 +Force4_3For24Bit = false +AspectRatio = 4:3 +CustomAspectRatioNumerator = 4 +LinearFiltering = true +IntegerScaling = false +Stretch = false +PostProcessing = false +ShowOSDMessages = true +ShowFPS = false +ShowVPS = false +ShowSpeed = false +ShowResolution = false +ShowStatusIndicators = true +ShowEnhancements = false +DisplayAllFrames = true +VSync = true +MaxFPS = 0.000000 + + +[Hotkeys] +OpenPauseMenu = SDL-0/Guide & SDL-0/X +FastForward = SDL-0/Guide & SDL-0/+RightTrigger +Screenshot = SDL-0/Back & SDL-0/A +LoadSelectedSaveState = SDL-0/Guide & SDL-0/LeftShoulder +SaveSelectedSaveState = SDL-0/Guide & SDL-0/RightShoulder +PowerOff = SDL-0/Guide & SDL-0/Start + + +[Logging] +LogLevel = Error +LogFilter = +LogToConsole = false +LogToDebug = false +LogToWindow = false +LogToFile = false + + +[Controller1] +Type = AnalogController +ButtonUp = Controller0/Button11 +ButtonDown = Controller0/Button12 +ButtonLeft = Controller0/Button13 +ButtonRight = Controller0/Button14 +ButtonSelect = Controller0/Button4 +ButtonStart = Controller0/Button6 +ButtonTriangle = Controller0/Button2 +ButtonCross = Controller0/Button1 +ButtonSquare = Controller0/Button3 +ButtonCircle = Controller0/Button0 +ButtonL1 = Controller0/Button9 +ButtonL2 = Controller0/+Axis4 +ButtonR1 = Controller0/Button10 +ButtonR2 = Controller0/+Axis5 +AxisLeftX = Controller0/Axis0 +AxisLeftY = Controller0/Axis1 +ButtonL3 = Controller0/Button7 +ButtonR3 = Controller0/Button8 +AxisRightX = Controller0/Axis2 +AxisRightY = Controller0/Axis3 +AnalogDPadInDigitalMode = false + + +[GameList] +RecursivePaths = /storage/roms/psx + + +[MemoryCards] +UsePlaylistTitle = true +Directory = /storage/roms/psx +Card1Type = PerGameTitle +Card2Type = None + + +[Console] +Region = Auto +Enable8MBRAM = false + + +[CPU] +ExecutionMode = Recompiler +OverclockEnable = false +OverclockNumerator = 1 +OverclockDenominator = 1 +RecompilerMemoryExceptions = false +RecompilerBlockLinking = true +RecompilerICache = false +FastmemMode = MMap + + +[CDROM] +ReadaheadSectors = 8 +RegionCheck = false +LoadImageToRAM = false +MuteCDAudio = false +ReadSpeedup = 1 +SeekSpeedup = 1 + + +[Audio] +Backend = SDL +OutputVolume = 100 +FastForwardVolume = 100 +BufferSize = 2048 +Resampling = true +OutputMuted = false +Sync = true +DumpOnBoot = false +BufferMS = 100 + + +[Hacks] +DMAMaxSliceTicks = 1000 +DMAHaltTicks = 100 +GPUFIFOSize = 16 +GPUMaxRunAhead = 128 + + +[Controller2] +Type = None + + +[Controller3] +Type = None + + +[Controller4] +Type = None + + +[Controller5] +Type = None + + +[Controller6] +Type = None + + +[Controller7] +Type = None + + +[Controller8] +Type = None + + +[ControllerPorts] +MultitapMode = Disabled + + +[Debug] +ShowVRAM = false +DumpCPUToVRAMCopies = false +DumpVRAMToCPUCopies = false +ShowGPUState = false +ShowCDROMState = false +ShowSPUState = false +ShowTimersState = false +ShowMDECState = false +ShowDMAState = false + + +[TextureReplacements] +EnableVRAMWriteReplacements = false +PreloadTextures = false +DumpVRAMWrites = false +DumpVRAMWriteForceAlphaChannel = true +DumpVRAMWriteWidthThreshold = 128 +DumpVRAMWriteHeightThreshold = 128 + + +[Pad1] +Up = SDL-0/DPadUp +Right = SDL-0/DPadRight +Down = SDL-0/DPadDown +Left = SDL-0/DPadLeft +Triangle = SDL-0/X +Circle = SDL-0/A +Cross = SDL-0/B +Square = SDL-0/Y +Select = SDL-0/Back +Start = SDL-0/Start +L1 = SDL-0/LeftShoulder +R1 = SDL-0/RightShoulder +L2 = SDL-0/+LeftTrigger +R2 = SDL-0/+RightTrigger +L3 = SDL-0/LeftStick +R3 = SDL-0/RightStick +LLeft = SDL-0/-LeftX +LRight = SDL-0/+LeftX +LDown = SDL-0/+LeftY +LUp = SDL-0/-LeftY +RLeft = SDL-0/+RightX +RRight = SDL-0/-RightX +RDown = SDL-0/+RightY +RUp = SDL-0/-RightY diff --git a/projects/ArchR/packages/emulators/standalone/duckstation-sa/config/SM8550 b/projects/ArchR/packages/emulators/standalone/duckstation-sa/config/SM8550 new file mode 120000 index 0000000000..72081d3859 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/duckstation-sa/config/SM8550 @@ -0,0 +1 @@ +InputPlumber \ No newline at end of file diff --git a/projects/ArchR/packages/emulators/standalone/duckstation-sa/config/SM8650 b/projects/ArchR/packages/emulators/standalone/duckstation-sa/config/SM8650 new file mode 120000 index 0000000000..72081d3859 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/duckstation-sa/config/SM8650 @@ -0,0 +1 @@ +InputPlumber \ No newline at end of file diff --git a/projects/ArchR/packages/emulators/standalone/duckstation-sa/package.mk b/projects/ArchR/packages/emulators/standalone/duckstation-sa/package.mk new file mode 100644 index 0000000000..7d432a9ffa --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/duckstation-sa/package.mk @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="duckstation-sa" +PKG_LICENSE="GPLv3" +PKG_DEPENDS_TARGET="toolchain" +PKG_SITE="https://github.com/stenzek/duckstation" +PKG_VERSION="0.1-10998" +PKG_LONGDESC="Fast PlayStation 1 emulator for x86-64/AArch32/AArch64 " +PKG_TOOLCHAIN="manual" + +case ${TARGET_ARCH} in + x86_64) + PKG_URL="${PKG_SITE}/releases/download/v${PKG_VERSION}/DuckStation-x64.AppImage" + ;; + aarch64) + PKG_URL="${PKG_SITE}/releases/download/v${PKG_VERSION}/DuckStation-arm64.AppImage" + ;; +esac + +install_script() { + if [ ! -d "${INSTALL}/usr/config/modules" ] + then + mkdir -p ${INSTALL}/usr/config/modules + fi + cp -rf ${PKG_DIR}/sources/"${1}" ${INSTALL}/usr/config/modules + chmod 0755 ${INSTALL}/usr/config/modules/"${1}" +} + +makeinstall_target() { + # Redefine strip or the AppImage will be stripped rendering it unusable. + export STRIP=true + mkdir -p ${INSTALL}/usr/bin + cp ${PKG_BUILD}/${PKG_NAME}-${PKG_VERSION}.AppImage ${INSTALL}/usr/bin/${PKG_NAME} + cp -rf ${PKG_DIR}/scripts/*.sh ${INSTALL}/usr/bin + chmod 755 ${INSTALL}/usr/bin/* + + mkdir -p ${INSTALL}/usr/config/duckstation + cp -rf ${PKG_DIR}/config/${DEVICE}/* ${INSTALL}/usr/config/duckstation + + install_script "Start Duckstation.sh" +} diff --git a/projects/ArchR/packages/emulators/standalone/duckstation-sa/scripts/cheevos_duckstation.sh b/projects/ArchR/packages/emulators/standalone/duckstation-sa/scripts/cheevos_duckstation.sh new file mode 100644 index 0000000000..f6fd1e4cb6 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/duckstation-sa/scripts/cheevos_duckstation.sh @@ -0,0 +1,66 @@ +#! /bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-present Hector Calvarro (https://github.com/kelvfimer) +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile + +DUCK_CFG="/storage/.config/duckstation/settings.ini" +LOG_FILE="/var/log/cheevos.log" + +# Extract username, password, token, if enabled, and hardcore mode from system.cfg +username=$(get_setting "global.retroachievements.username") +password=$(get_setting "global.retroachievements.password") +token=$(get_setting "global.retroachievements.token") +enabled=$(get_setting "global.retroachievements") +hardcore=$(get_setting "global.retroachievements.hardcore") + +# Check if RetroAchievements are enabled in Emulation Station +if [ ! ${enabled} = 1 ]; then + echo "RetroAchievements are not enabled, please turn them on in Emulation Station." > ${LOG_FILE} + sed -i '/\[Cheevos\]/,/^\s*$/s/Enabled =.*/Enabled = false/' ${DUCK_CFG} + exit 1 +fi + +# Check if api token is present in system.cfg +if [ -z "${token}" ]; then + echo "RetroAchievements token is empty, please log in with your RetroAchievements credentials in Emulation Station." > ${LOG_FILE} + exit 1 +fi + +# Set hardcore mode +if [ "${hardcore}" = 1 ]; then + hardcore="true" +else + hardcore="false" +fi + +# Update emulator config with RetroAchievements settings +zcheevos=$(grep -Fx "[Cheevos]" ${DUCK_CFG}) +datets=$(date +%s%N | cut -b1-13) + +if [ -z "${zcheevos}" ]; then + sed -i "\$a [Cheevos]\nEnabled = true\nUsername = ${username}\nToken = ${token}\nLoginTimestamp = ${datets}\nChallengeMode = ${hardcore}" ${DUCK_CFG} +else + sed -i '/\[Cheevos\]/,/^\s*$/s/Enabled =.*/Enabled = true/' ${DUCK_CFG} + if ! grep -q "^Username = " ${DUCK_CFG}; then + sed -i "/^\[Cheevos\]/a Username = ${username}" ${DUCK_CFG} + else + sed -i "/^\[Cheevos\]/,/^\[/{s/^Username = .*/Username = ${username}/;}" ${DUCK_CFG} + fi + + if ! grep -q "^Token = " ${DUCK_CFG}; then + sed -i "/^\[Cheevos\]/a Token = ${token}" ${DUCK_CFG} + else + sed -i "/^\[Cheevos\]/,/^\[/{s/^Token = .*/Token = ${token}/;}" ${DUCK_CFG} + fi + + if ! grep -q "^ChallengeMode = " ${DUCK_CFG}; then + sed -i "/^\[Cheevos\]/a ChallengeMode = ${hardcore}" ${DUCK_CFG} + else + sed -i "/^\[Cheevos\]/,/^\[/{s/^ChallengeMode = .*/ChallengeMode = ${hardcore}/;}" ${DUCK_CFG} + fi + + sed -i "/^\[Cheevos\]/,/^\[/{s/^LoginTimestamp = .*/LoginTimestamp = ${datets}/;}" ${DUCK_CFG} +fi diff --git a/projects/ArchR/packages/emulators/standalone/duckstation-sa/scripts/start_duckstation.sh b/projects/ArchR/packages/emulators/standalone/duckstation-sa/scripts/start_duckstation.sh new file mode 100644 index 0000000000..6696718449 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/duckstation-sa/scripts/start_duckstation.sh @@ -0,0 +1,133 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile +set_kill set "-9 AppRun.wrapped" + +# Filesystem vars +IMMUTABLE_CONF_DIR="/usr/config/duckstation" +IMMUTABLE_CONF_FILE="${IMMUTABLE_CONF_DIR}/settings.ini" +APPIMAGE_CONF_DIR="/storage/.local/share/duckstation" +CONF_DIR="/storage/.config/duckstation" +CONF_FILE="${CONF_DIR}/settings.ini" +SAVESTATES_DIR="/storage/roms/savestates/psx" +MEMCARDS_DIR="/storage/roms/psx/duckstation/memcards" + +#Init config dir if required +[ ! -d "${CONF_DIR}" ] && cp -r "${IMMUTABLE_CONF_DIR}" /storage/.config + +#Init config file if required +[ ! -f "${CONF_FILE}" ] && cp ${IMMUTABLE_CONF_FILE} ${CONF_FILE} + +#Link config dir to where appimage can find it +mkdir -p /storage/.local/share +rm -rf "${APPIMAGE_CONF_DIR}" +ln -sfv "${CONF_DIR}" "${APPIMAGE_CONF_DIR}" + +#Link savestates to roms/savestates +[ ! -d "${SAVESTATES_DIR}" ] && mkdir -p "${SAVESTATES_DIR}" +[ -d "${CONF_DIR}/savestates" ] && rm -rf "${CONF_DIR}/savestates" +ln -sfv "${SAVESTATES_DIR}" "${CONF_DIR}/savestates" + +# Link memcards to roms +if [ ! -d "${MEMCARDS_DIR}" ]; then + mkdir -p ${MEMCARDS_DIR} + + # Migrate any existing memcards + if [ -d "${CONF_DIR}/memcards" ]; then + cp -rf ${CONF_DIR}/memcards/* ${MEMCARDS_DIR} + fi +fi + +[ -d "${CONF_DIR}/memcards" ] && rm -rf ${CONF_DIR}/memcards +ln -sfv ${MEMCARDS_DIR} ${CONF_DIR}/memcards + +#Link gamecontrollerdb.txt +ln -sf /usr/config/SDL-GameControllerDB/gamecontrollerdb.txt "${CONF_DIR}/gamecontrollerdb.txt" + +#Emulation Station Features +GAME=$(echo "${1}"| sed "s#^/.*/##") +PLATFORM=$(echo "${2}"| sed "s#^/.*/##") +ASPECT=$(get_setting aspect_ratio "${PLATFORM}" "${GAME}") +FPS=$(get_setting show_fps "${PLATFORM}" "${GAME}") +IRES=$(get_setting internal_resolution "${PLATFORM}" "${GAME}") +RENDERER=$(get_setting graphics_backend "${PLATFORM}" "${GAME}") +VSYNC=$(get_setting vsync "${PLATFORM}" "${GAME}") + +#Set the cores to use +CORES=$(get_setting "cores" "${PLATFORM}" "${GAME}") +if [ "${CORES}" = "little" ] +then + EMUPERF="${SLOW_CORES}" +elif [ "${CORES}" = "big" ] +then + EMUPERF="${FAST_CORES}" +else + ### All.. + unset EMUPERF +fi + + #Aspect Ratio + if [ "$ASPECT" = "1" ]; then + sed -i '/^AspectRatio/c\AspectRatio = 16:9' ${CONF_FILE} + elif [ "$ASPECT" = "2" ]; then + sed -i '/^AspectRatio/c\AspectRatio = Stretch To Fill' ${CONF_FILE} + else + #Default to 4:3 aspect ratio + sed -i '/^AspectRatio/c\AspectRatio = 4:3' ${CONF_FILE} + fi + + #Show FPS + if [ "$FPS" = "true" ]; then + sed -i '/^ShowFPS/c\ShowFPS = true' ${CONF_FILE} + else + #Default to not show FPS + sed -i '/^ShowFPS/c\ShowFPS = false' ${CONF_FILE} + fi + + #Internal Resolution + if [ "$IRES" = "2" ]; then + sed -i '/^ResolutionScale =/c\ResolutionScale = 2' ${CONF_FILE} + elif [ "$IRES" = "3" ]; then + sed -i '/^ResolutionScale =/c\ResolutionScale = 3' ${CONF_FILE} + elif [ "$IRES" = "4" ]; then + sed -i '/^ResolutionScale =/c\ResolutionScale = 4' ${CONF_FILE} + elif [ "$IRES" = "5" ]; then + sed -i '/^ResolutionScale =/c\ResolutionScale = 5' ${CONF_FILE} + else + #Default to native resolution + sed -i '/^ResolutionScale =/c\ResolutionScale = 1' ${CONF_FILE} + fi + + #Video Backend + if [ "$RENDERER" = "opengl" ]; then + sed -i '/^Renderer =/c\Renderer = OpenGL' ${CONF_FILE} + elif [ "$RENDERER" = "vulkan" ]; then + sed -i '/^Renderer =/c\Renderer = Vulkan' ${CONF_FILE} + else + #Default to software renderer + sed -i '/^Renderer =/c\Renderer = Software' ${CONF_FILE} + fi + + #VSYNC + if [ "$VSYNC" = "off" ]; then + sed -i '/^VSync =/c\VSync = false' ${CONF_FILE} + else + #Default to vsync on + sed -i '/^VSync =/c\VSync = true' ${CONF_FILE} + fi + +#Retroachievements +# Disabled, not working. Seems like Duckstation changed the token encruption... +# /usr/bin/cheevos_duckstation.sh +sed -i '/\[Cheevos\]/,/^\s*$/s/Enabled =.*/Enabled = false/' ${CONF_FILE} + + +# Panfrost optimization for Mali-G31 +export PAN_MESA_DEBUG=forcepack +export MESA_NO_ERROR=1 + +#Run Duckstation +${EMUPERF} duckstation-sa -fullscreen -bigpicture -nogui -- "${1}" > /dev/null 2>&1 diff --git a/projects/ArchR/packages/emulators/standalone/duckstation-sa/sources/Start Duckstation.sh b/projects/ArchR/packages/emulators/standalone/duckstation-sa/sources/Start Duckstation.sh new file mode 100644 index 0000000000..896059d6cc --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/duckstation-sa/sources/Start Duckstation.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile +set_kill set "-9 AppRun.wrapped" + +# Filesystem vars +IMMUTABLE_CONF_DIR="/usr/config/duckstation" +IMMUTABLE_CONF_FILE="${IMMUTABLE_CONF_DIR}/settings.ini" +APPIMAGE_CONF_DIR="/storage/.local/share/duckstation" +CONF_DIR="/storage/.config/duckstation" +CONF_FILE="${CONF_DIR}/settings.ini" + +#Init config dir if required +[ ! -d "${CONF_DIR}" ] && cp -r "${IMMUTABLE_CONF_DIR}" /storage/.config + +#Link config dir to where appimage can find it +mkdir -p /storage/.local/share +rm -rf "${APPIMAGE_CONF_DIR}" +ln -sfv "${CONF_DIR}" "${APPIMAGE_CONF_DIR}" + +#Init config file if required +[ ! -f "${CONF_FILE}" ] && cp ${IMMUTABLE_CONF_FILE} ${CONF_FILE} + +#Link gamecontrollerdb.txt +ln -sf /usr/config/SDL-GameControllerDB/gamecontrollerdb.txt "${CONF_DIR}/gamecontrollerdb.txt" + +/usr/bin/duckstation-sa -fullscreen -bigpicture diff --git a/projects/ArchR/packages/emulators/standalone/flycast-sa/config/H700/emu.cfg b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/H700/emu.cfg new file mode 100644 index 0000000000..ce42e97956 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/H700/emu.cfg @@ -0,0 +1,13 @@ +[audio] +backend = pulse + +[input] +maple_sdl_joystick_0 = 0 +maple_sdl_joystick_1 = 1 + +device1 = 0 +device1.1 = 1 +device1.2 = 1 +device2 = 0 +device2.1 = 1 +device2.2 = 1 diff --git a/projects/ArchR/packages/emulators/standalone/flycast-sa/config/H700/mappings/SDL_H700 Gamepad.cfg b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/H700/mappings/SDL_H700 Gamepad.cfg new file mode 100644 index 0000000000..33743839c1 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/H700/mappings/SDL_H700 Gamepad.cfg @@ -0,0 +1,32 @@ +[analog] +bind0 = 0-:btn_analog_left +bind1 = 0+:btn_analog_right +bind2 = 1-:btn_analog_up +bind3 = 1+:btn_analog_down +bind4 = 2-:axis2_left +bind5 = 2+:axis2_right +bind6 = 3-:axis2_up +bind7 = 3+:axis2_down + +[digital] +bind0 = 0:btn_a +bind1 = 1:btn_b +bind10 = 13:btn_dpad1_up +bind11 = 14:btn_dpad1_down +bind12 = 15:btn_dpad1_left +bind13 = 16:btn_dpad1_right +bind2 = 2:btn_x +bind3 = 3:btn_y +bind4 = 4:btn_trigger_left +bind5 = 5:btn_trigger_right +bind6 = 6:btn_trigger2_left +bind7 = 7:btn_trigger2_right +bind8 = 8:btn_menu +bind9 = 9:btn_start + +[emulator] +dead_zone = 10 +mapping_name = H700 Gamepad +rumble_power = 100 +saturation = 100 +version = 3 diff --git a/projects/ArchR/packages/emulators/standalone/flycast-sa/config/InputPlumber/SDL_Xbox Series X Controller.cfg b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/InputPlumber/SDL_Xbox Series X Controller.cfg new file mode 100644 index 0000000000..685c10973e --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/InputPlumber/SDL_Xbox Series X Controller.cfg @@ -0,0 +1,40 @@ +[analog] +bind0 = 0-:btn_analog_left +bind1 = 0+:btn_analog_right +bind2 = 1-:btn_analog_up +bind3 = 1+:btn_analog_down +bind4 = 2+:btn_trigger_left +bind5 = 3-:axis2_left +bind6 = 3+:axis2_right +bind7 = 4-:axis2_up +bind8 = 4+:axis2_down +bind9 = 5+:btn_trigger_right + +[combo] +bind0 = 8,4:btn_jump_state:0 +bind1 = 8,5:btn_quick_save:0 +bind2 = 8,7:btn_escape:0 + +[digital] +bind0 = 0:btn_a +bind1 = 1:btn_b +bind10 = 257:btn_dpad1_down +bind11 = 258:btn_dpad1_left +bind12 = 259:btn_dpad1_right +bind2 = 2:btn_x +bind3 = 3:btn_y +bind4 = 4:btn_z +bind5 = 5:btn_c +bind6 = 6:btn_menu +bind7 = 7:btn_start +bind8 = 8:btn_dpad2_up +bind9 = 256:btn_dpad1_up + +[emulator] +dead_zone = 10 +mapping_name = Microsoft Xbox Series Controller +rumble_power = 100 +saturation = 100 +triggers = 2,5 +version = 4 + diff --git a/projects/ArchR/packages/emulators/standalone/flycast-sa/config/RK3326/emu.cfg b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/RK3326/emu.cfg new file mode 100644 index 0000000000..72b7876b44 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/RK3326/emu.cfg @@ -0,0 +1,33 @@ +[audio] +backend = auto + +[config] +rend.Resolution = 240 +pvr.rend = 0 +pvr.AutoSkipFrame = 2 +pvr.RenderToTextureBuffer = 0 +rend.RenderToTextureBuffer = 0 +rend.TextureUpscale = 1 +rend.Fog = 1 +rend.FloatVMUs = 0 +rend.ShowFPS = no +rend.WideScreen = no +rend.SuperWideScreen = no +rend.vsync = yes +ta_skip = 0 +rend.ThreadedRendering = 1 +aica.DSPEnabled = 0 +aica.NoBatch = 0 +Dynarec.Enabled = 1 +Dynarec.idleskip = 1 + +[input] +maple_sdl_joystick_0 = 0 +maple_sdl_joystick_1 = 1 + +device1 = 0 +device1.1 = 1 +device1.2 = 1 +device2 = 0 +device2.1 = 1 +device2.2 = 1 diff --git a/projects/ArchR/packages/emulators/standalone/flycast-sa/config/RK3326/mappings/SDL_odroidgo2__joypad.cfg b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/RK3326/mappings/SDL_odroidgo2__joypad.cfg new file mode 100644 index 0000000000..e0f04b97ef --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/RK3326/mappings/SDL_odroidgo2__joypad.cfg @@ -0,0 +1,32 @@ +[analog] +bind0 = 0-:btn_analog_left +bind1 = 0+:btn_analog_right +bind2 = 1-:btn_analog_up +bind3 = 1+:btn_analog_down +bind4 = 2-:axis2_left +bind5 = 2+:axis2_right +bind6 = 3-:axis2_up +bind7 = 3+:axis2_down + +[digital] +bind0 = 0:btn_a +bind1 = 1:btn_b +bind10 = 12:btn_escape +bind11 = 13:btn_menu +bind12 = 14:btn_fforward +bind13 = 15:btn_start +bind2 = 2:btn_x +bind3 = 3:btn_y +bind4 = 4:btn_trigger_left +bind5 = 5:btn_trigger_right +bind6 = 8:btn_dpad1_up +bind7 = 9:btn_dpad1_down +bind8 = 10:btn_dpad1_left +bind9 = 11:btn_dpad1_right + +[emulator] +dead_zone = 10 +mapping_name = ODROID Go 2 +rumble_power = 100 +version = 3 + diff --git a/projects/ArchR/packages/emulators/standalone/flycast-sa/config/RK3326/mappings/SDL_odroidgo2_v11_joypad.cfg b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/RK3326/mappings/SDL_odroidgo2_v11_joypad.cfg new file mode 100644 index 0000000000..e0f04b97ef --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/RK3326/mappings/SDL_odroidgo2_v11_joypad.cfg @@ -0,0 +1,32 @@ +[analog] +bind0 = 0-:btn_analog_left +bind1 = 0+:btn_analog_right +bind2 = 1-:btn_analog_up +bind3 = 1+:btn_analog_down +bind4 = 2-:axis2_left +bind5 = 2+:axis2_right +bind6 = 3-:axis2_up +bind7 = 3+:axis2_down + +[digital] +bind0 = 0:btn_a +bind1 = 1:btn_b +bind10 = 12:btn_escape +bind11 = 13:btn_menu +bind12 = 14:btn_fforward +bind13 = 15:btn_start +bind2 = 2:btn_x +bind3 = 3:btn_y +bind4 = 4:btn_trigger_left +bind5 = 5:btn_trigger_right +bind6 = 8:btn_dpad1_up +bind7 = 9:btn_dpad1_down +bind8 = 10:btn_dpad1_left +bind9 = 11:btn_dpad1_right + +[emulator] +dead_zone = 10 +mapping_name = ODROID Go 2 +rumble_power = 100 +version = 3 + diff --git a/projects/ArchR/packages/emulators/standalone/flycast-sa/config/RK3326/mappings/SDL_r33s_joypad.cfg b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/RK3326/mappings/SDL_r33s_joypad.cfg new file mode 100644 index 0000000000..abd5b1c153 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/RK3326/mappings/SDL_r33s_joypad.cfg @@ -0,0 +1,21 @@ +[digital] +bind0 = 0:btn_a +bind1 = 1:btn_b +bind10 = 10:btn_analog_up +bind11 = 11:btn_analog_down +bind12 = 12:btn_analog_left +bind13 = 13:btn_analog_right +bind2 = 2:btn_y +bind3 = 3:btn_x +bind4 = 4:btn_trigger_left +bind5 = 5:btn_trigger_right +bind6 = 6:btn_jump_state +bind7 = 7:btn_quick_save +bind8 = 8:btn_menu +bind9 = 9:btn_start + +[emulator] +dead_zone = 10 +mapping_name = r33s_joypad +rumble_power = 100 +version = 3 diff --git a/projects/ArchR/packages/emulators/standalone/flycast-sa/config/RK3399/emu.cfg b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/RK3399/emu.cfg new file mode 100644 index 0000000000..9b66c3d516 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/RK3399/emu.cfg @@ -0,0 +1,22 @@ +[audio] +backend = pulse + +[config] +pvr.AutoSkipFrame = 2 +rend.Resolution = 480 + +[input] +maple_sdl_joystick_0 = 0 +maple_sdl_joystick_1 = 1 + +device1 = 0 +device1.1 = 1 +device1.2 = 1 +device2 = 0 +device2.1 = 1 +device2.2 = 1 + +[window] +fullscreen = yes +height = 1152 +width = 1920 diff --git a/projects/ArchR/packages/emulators/standalone/flycast-sa/config/RK3399/mappings/SDL_retrogame_joypad.cfg b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/RK3399/mappings/SDL_retrogame_joypad.cfg new file mode 100644 index 0000000000..1471462970 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/RK3399/mappings/SDL_retrogame_joypad.cfg @@ -0,0 +1,32 @@ +[analog] +bind0 = 0-:btn_analog_left +bind1 = 0+:btn_analog_right +bind2 = 1-:btn_analog_up +bind3 = 1+:btn_analog_down +bind4 = 2-:axis2_left +bind5 = 2+:axis2_right +bind6 = 3-:axis2_up +bind7 = 3+:axis2_down + +[digital] +bind0 = 0:btn_a +bind1 = 1:btn_b +bind10 = 13:btn_dpad1_up +bind11 = 14:btn_dpad1_down +bind12 = 15:btn_dpad1_left +bind13 = 16:btn_dpad1_right +bind2 = 2:btn_y +bind3 = 3:btn_x +bind4 = 4:btn_trigger_left +bind5 = 5:btn_trigger_right +bind6 = 6:btn_jump_state +bind7 = 7:btn_quick_save +bind8 = 8:btn_menu +bind9 = 9:btn_start + +[emulator] +dead_zone = 10 +mapping_name = rg552_joypad +rumble_power = 100 +version = 3 + diff --git a/projects/ArchR/packages/emulators/standalone/flycast-sa/config/RK3566/emu.cfg b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/RK3566/emu.cfg new file mode 100644 index 0000000000..1718e69fd5 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/RK3566/emu.cfg @@ -0,0 +1,21 @@ +[audio] +backend = pulse + +[input] +device1 = 0 +device1.1 = 1 +device1.2 = 1 +device2 = 0 +device2.1 = 1 +device2.2 = 1 +maple_sdl_joystick_0 = 0 +maple_sdl_joystick_1 = 1 + +[config] +pvr.AutoSkipFrame = 1 +pvr.rend = 0 +rend.Resolution = 240 +rend.vsync = no +ta.skip = 1 + + diff --git a/projects/ArchR/packages/emulators/standalone/flycast-sa/config/RK3566/mappings/SDL_retrogame_joypad.cfg b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/RK3566/mappings/SDL_retrogame_joypad.cfg new file mode 100644 index 0000000000..3e61e80e12 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/RK3566/mappings/SDL_retrogame_joypad.cfg @@ -0,0 +1,34 @@ +[analog] +bind0 = 0-:btn_analog_left +bind1 = 0+:btn_analog_right +bind2 = 1-:btn_analog_up +bind3 = 1+:btn_analog_down +bind4 = 2-:axis2_left +bind5 = 2+:axis2_right +bind6 = 3-:axis2_up +bind7 = 3+:axis2_down + +[digital] +bind0 = 0:btn_a +bind1 = 1:btn_b +bind10 = 13:btn_dpad1_up +bind11 = 14:btn_dpad1_down +bind12 = 15:btn_dpad1_left +bind13 = 16:btn_dpad1_right +bind2 = 2:btn_y +bind3 = 3:btn_x +bind4 = 4:btn_trigger_left +bind5 = 5:btn_trigger_right +bind6 = 6:btn_trigger2_left +bind7 = 7:btn_trigger2_right +bind8 = 8:btn_menu +bind9 = 9:btn_start + +[emulator] +dead_zone = 10 +mapping_name = RetroGame Joypad +rumble_power = 100 +saturation = 100 +version = 3 + + diff --git a/projects/ArchR/packages/emulators/standalone/flycast-sa/config/RK3588/emu.cfg b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/RK3588/emu.cfg new file mode 100644 index 0000000000..9282480349 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/RK3588/emu.cfg @@ -0,0 +1,21 @@ +[audio] +backend = pulse + +[config] +rend.Resolution = 480 + +[input] +maple_sdl_joystick_0 = 0 +maple_sdl_joystick_1 = 1 + +device1 = 0 +device1.1 = 1 +device1.2 = 1 +device2 = 0 +device2.1 = 1 +device2.2 = 1 + +[window] +fullscreen = yes +height = 1080 +width = 1920 diff --git a/projects/ArchR/packages/emulators/standalone/flycast-sa/config/RK3588/mappings/SDL_GameForce ACE Gamepad.cfg b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/RK3588/mappings/SDL_GameForce ACE Gamepad.cfg new file mode 100644 index 0000000000..6a6ecb4b44 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/RK3588/mappings/SDL_GameForce ACE Gamepad.cfg @@ -0,0 +1,32 @@ +[analog] +bind0 = 1+:btn_analog_down +bind1 = 1-:btn_analog_up +bind2 = 0-:btn_analog_left +bind3 = 0+:btn_analog_right +bind4 = 2+:btn_trigger_left +bind5 = 3-:axis2_left +bind6 = 3+:axis2_right +bind7 = 4-:axis2_up +bind8 = 4+:axis2_down +bind9 = 5+:btn_trigger_right + +[digital] +bind0 = 0:btn_a +bind1 = 1:btn_b +bind10 = 14:btn_dpad1_left +bind11 = 15:btn_dpad1_right +bind2 = 3:btn_y +bind3 = 4:btn_x +bind4 = 5:btn_z +bind5 = 6:btn_c +bind6 = 9:btn_menu +bind7 = 8:btn_start +bind8 = 12:btn_dpad1_up +bind9 = 13:btn_dpad1_down + +[emulator] +dead_zone = 10 +mapping_name = GameForce ACE Gamepad +rumble_power = 100 +saturation = 100 +version = 3 diff --git a/projects/ArchR/packages/emulators/standalone/flycast-sa/config/S922X/emu.cfg b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/S922X/emu.cfg new file mode 100644 index 0000000000..7c02ea27d7 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/S922X/emu.cfg @@ -0,0 +1,21 @@ +[audio] +backend = pulse + +[config] +rend.Resolution = 480 + +[input] +maple_sdl_joystick_0 = 0 +maple_sdl_joystick_1 = 1 + +device1 = 0 +device1.1 = 1 +device1.2 = 1 +device2 = 0 +device2.1 = 1 +device2.2 = 1 + +[window] +fullscreen = yes +height = 854 +width = 480 diff --git a/projects/ArchR/packages/emulators/standalone/flycast-sa/config/S922X/mappings/SDL_GO-Ultra Gamepad.cfg b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/S922X/mappings/SDL_GO-Ultra Gamepad.cfg new file mode 100644 index 0000000000..9e9113bfc8 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/S922X/mappings/SDL_GO-Ultra Gamepad.cfg @@ -0,0 +1,33 @@ +[analog] +bind0 = 0-:btn_analog_left +bind1 = 0+:btn_analog_right +bind2 = 1-:btn_analog_up +bind3 = 1+:btn_analog_down +bind4 = 2-:axis2_left +bind5 = 2+:axis2_right +bind6 = 3-:axis2_up +bind7 = 3+:axis2_down + +[digital] +bind0 = 0:btn_a +bind1 = 1:btn_b +bind10 = 13:btn_dpad2_up +bind11 = 14:btn_dpad1_up +bind12 = 15:btn_dpad1_down +bind13 = 16:btn_dpad1_left +bind14 = 17:btn_dpad1_right +bind2 = 3:btn_y +bind3 = 4:btn_x +bind4 = 5:btn_trigger_left +bind5 = 6:btn_trigger_right +bind6 = 7:btn_jump_state +bind7 = 8:btn_quick_save +bind8 = 10:btn_start +bind9 = 11:btn_menu + +[emulator] +dead_zone = 10 +mapping_name = GO-Ultra Gamepad +rumble_power = 100 +saturation = 100 +version = 3 diff --git a/projects/ArchR/packages/emulators/standalone/flycast-sa/config/SDL_Keyboard.cfg b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/SDL_Keyboard.cfg new file mode 100644 index 0000000000..114b67a6f7 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/SDL_Keyboard.cfg @@ -0,0 +1,11 @@ +digital] +bind0 = 9:btn_fforward +bind1 = 15:btn_jump_state +bind2 = 22:btn_quick_save + +[emulator] +dead_zone = 10 +mapping_name = Keyboard +rumble_power = 100 +saturation = 100 +version = 3 diff --git a/projects/ArchR/packages/emulators/standalone/flycast-sa/config/SDM845/emu.cfg b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/SDM845/emu.cfg new file mode 100644 index 0000000000..eb221fc9ef --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/SDM845/emu.cfg @@ -0,0 +1,23 @@ +[audio] +backend = pulse + +[config] +pvr.AutoSkipFrame = 2 +pvr.rend = 0 +rend.Resolution = 480 + +[input] +maple_sdl_joystick_0 = 0 +maple_sdl_joystick_1 = 1 + +device1 = 0 +device1.1 = 1 +device1.2 = 1 +device2 = 0 +device2.1 = 1 +device2.2 = 1 + +[window] +fullscreen = yes +height = 1080 +width = 1920 diff --git a/projects/ArchR/packages/emulators/standalone/flycast-sa/config/SDM845/mappings/SDL_AYN Odin Gamepad.cfg b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/SDM845/mappings/SDL_AYN Odin Gamepad.cfg new file mode 100644 index 0000000000..d3b399a6bd --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/SDM845/mappings/SDL_AYN Odin Gamepad.cfg @@ -0,0 +1,32 @@ +[analog] +bind0 = 0-:btn_analog_left +bind1 = 0+:btn_analog_right +bind2 = 1-:btn_analog_up +bind3 = 1+:btn_analog_down +bind4 = 2-:axis2_left +bind5 = 2+:axis2_right +bind6 = 3-:axis2_up +bind7 = 3+:axis2_down +bind8 = 4+:btn_trigger_right +bind9 = 5+:btn_trigger_left + +[digital] +bind0 = 0:btn_a +bind1 = 1:btn_b +bind10 = 15:btn_dpad1_left +bind11 = 16:btn_dpad1_right +bind2 = 2:btn_y +bind3 = 3:btn_x +bind4 = 4:btn_jump_state +bind5 = 5:btn_quick_save +bind6 = 9:btn_start +bind7 = 10:btn_menu +bind8 = 13:btn_dpad1_up +bind9 = 14:btn_dpad1_down + +[emulator] +dead_zone = 10 +mapping_name = AYN Odin Gamepad +rumble_power = 100 +saturation = 100 +version = 3 diff --git a/projects/ArchR/packages/emulators/standalone/flycast-sa/config/SM8250/emu.cfg b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/SM8250/emu.cfg new file mode 100644 index 0000000000..eb221fc9ef --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/SM8250/emu.cfg @@ -0,0 +1,23 @@ +[audio] +backend = pulse + +[config] +pvr.AutoSkipFrame = 2 +pvr.rend = 0 +rend.Resolution = 480 + +[input] +maple_sdl_joystick_0 = 0 +maple_sdl_joystick_1 = 1 + +device1 = 0 +device1.1 = 1 +device1.2 = 1 +device2 = 0 +device2.1 = 1 +device2.2 = 1 + +[window] +fullscreen = yes +height = 1080 +width = 1920 diff --git a/projects/ArchR/packages/emulators/standalone/flycast-sa/config/SM8250/mappings/SDL_Retroid Pocket Gamepad.cfg b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/SM8250/mappings/SDL_Retroid Pocket Gamepad.cfg new file mode 100644 index 0000000000..f6ce3818ef --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/SM8250/mappings/SDL_Retroid Pocket Gamepad.cfg @@ -0,0 +1,33 @@ +[analog] +bind0 = 0-:btn_analog_left +bind1 = 0+:btn_analog_right +bind2 = 1-:btn_analog_up +bind3 = 1+:btn_analog_down +bind4 = 3-:axis2_left +bind5 = 3+:axis2_right +bind6 = 4-:axis2_up +bind7 = 4+:axis2_down +bind8 = 6+:btn_trigger2_left +bind9 = 7+:btn_trigger2_right + +[digital] +bind0 = 0:btn_a +bind1 = 1:btn_b +bind10 = 13:btn_dpad1_left +bind11 = 14:btn_dpad1_right +bind12 = 15:btn_menu +bind2 = 2:btn_y +bind3 = 3:btn_x +bind4 = 4:btn_trigger_left +bind5 = 5:btn_trigger_right +bind6 = 6:reload +bind7 = 7:btn_start +bind8 = 11:btn_dpad1_up +bind9 = 12:btn_dpad1_down + +[emulator] +dead_zone = 10 +mapping_name = Retroid Pocket Gamepad +rumble_power = 100 +saturation = 100 +version = 3 diff --git a/projects/ArchR/packages/emulators/standalone/flycast-sa/config/SM8550/emu.cfg b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/SM8550/emu.cfg new file mode 100644 index 0000000000..eb221fc9ef --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/SM8550/emu.cfg @@ -0,0 +1,23 @@ +[audio] +backend = pulse + +[config] +pvr.AutoSkipFrame = 2 +pvr.rend = 0 +rend.Resolution = 480 + +[input] +maple_sdl_joystick_0 = 0 +maple_sdl_joystick_1 = 1 + +device1 = 0 +device1.1 = 1 +device1.2 = 1 +device2 = 0 +device2.1 = 1 +device2.2 = 1 + +[window] +fullscreen = yes +height = 1080 +width = 1920 diff --git a/projects/ArchR/packages/emulators/standalone/flycast-sa/config/SM8550/mappings b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/SM8550/mappings new file mode 120000 index 0000000000..67e264f17b --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/SM8550/mappings @@ -0,0 +1 @@ +../InputPlumber \ No newline at end of file diff --git a/projects/ArchR/packages/emulators/standalone/flycast-sa/config/SM8650/emu.cfg b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/SM8650/emu.cfg new file mode 100644 index 0000000000..eb221fc9ef --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/SM8650/emu.cfg @@ -0,0 +1,23 @@ +[audio] +backend = pulse + +[config] +pvr.AutoSkipFrame = 2 +pvr.rend = 0 +rend.Resolution = 480 + +[input] +maple_sdl_joystick_0 = 0 +maple_sdl_joystick_1 = 1 + +device1 = 0 +device1.1 = 1 +device1.2 = 1 +device2 = 0 +device2.1 = 1 +device2.2 = 1 + +[window] +fullscreen = yes +height = 1080 +width = 1920 diff --git a/projects/ArchR/packages/emulators/standalone/flycast-sa/config/SM8650/mappings b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/SM8650/mappings new file mode 120000 index 0000000000..67e264f17b --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/SM8650/mappings @@ -0,0 +1 @@ +../InputPlumber \ No newline at end of file diff --git a/projects/ArchR/packages/emulators/standalone/flycast-sa/config/flycast.gptk b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/flycast.gptk new file mode 100644 index 0000000000..cc9dafc882 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/flycast-sa/config/flycast.gptk @@ -0,0 +1,31 @@ +back = \\ +start = \\ +a = \\ +b = \\ +x = \\ +y = \\ +l1 = \\ +l1_hk = l +l2 = \\ +l2_hk = \\ +l3 = \\ +r1 = \\ +r1_hk = s +r2 = \\ +r2_hk = f +r3 = \\ +up = \\ +down = \\ +left = \\ +right = \\ +left_analog_up = \\ +left_analog_down = \\ +left_analog_left = \\ +left_analog_right = \\ +right_analog_up = \\ +right_analog_down = \\ +right_analog_left = \\ +right_analog_right = \\ +deadzone_triggers = \\ +mouse_scale = \\ +mouse_delay = \\ diff --git a/projects/ArchR/packages/emulators/standalone/flycast-sa/package.mk b/projects/ArchR/packages/emulators/standalone/flycast-sa/package.mk new file mode 100644 index 0000000000..6d45f8d0b6 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/flycast-sa/package.mk @@ -0,0 +1,56 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="flycast-sa" +PKG_VERSION="392a429e8b040b3e5bf6696cb4f984274fc44123" #v2.6 +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/flyinghead/flycast" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain alsa SDL2 libzip zip curl miniupnpc lua54 libao" +PKG_LONGDESC="Flycast is a multiplatform Sega Dreamcast, Naomi and Atomiswave emulator" +PKG_TOOLCHAIN="cmake" +PKG_PATCH_DIRS+="${DEVICE}" + +if [ "${OPENGL_SUPPORT}" = "yes" ] && [ ! "${PREFER_GLES}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL} glu libglvnd" + PKG_CMAKE_OPTS_TARGET+=" -DUSE_OPENGL=ON -DUSE_GLES=OFF" + +elif [ "${OPENGLES_SUPPORT}" = yes ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" + PKG_CMAKE_OPTS_TARGET+=" -DUSE_GLES=ON" +fi + +if [ "${VULKAN_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${VULKAN}" + PKG_CMAKE_OPTS_TARGET+=" -DUSE_VULKAN=ON" + GRENDERER="4" +else + PKG_CMAKE_OPTS_TARGET+=" -DUSE_VULKAN=OFF" + GRENDERER="0" +fi + +pre_configure_target() { + export CXXFLAGS="${CXXFLAGS} -Wno-error=array-bounds" + PKG_CMAKE_OPTS_TARGET+=" -DUSE_OPENMP=ON" + # -Ofast is intentional for Flycast: SH4 FPU emulation doesn't require + # strict IEEE 754, and Dreamcast hardware itself flushes denormals. + # Validated by JELOS/AmberELEC/ROCKNIX upstream for years. + sed -i 's/\-O[23]/-Ofast/' ${PKG_BUILD}/CMakeLists.txt +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + mkdir -p ${INSTALL}/usr/config/flycast + cp ${PKG_BUILD}/.${TARGET_NAME}/flycast ${INSTALL}/usr/bin/flycast + cp ${PKG_DIR}/scripts/* ${INSTALL}/usr/bin + cp -rH ${PKG_DIR}/config/${DEVICE}/* ${INSTALL}/usr/config/flycast + cp -rf ${PKG_DIR}/config/flycast.gptk ${INSTALL}/usr/config/flycast + cp -rf ${PKG_DIR}/config/SDL_Keyboard.cfg ${INSTALL}/usr/config/flycast/mappings + + chmod +x ${INSTALL}/usr/bin/* +} + +post_install() { + sed -e "s/@GRENDERER@/${GRENDERER}/g" -i ${INSTALL}/usr/bin/start_flycast.sh +} diff --git a/projects/ArchR/packages/emulators/standalone/flycast-sa/patches/000-conf-dir.patch b/projects/ArchR/packages/emulators/standalone/flycast-sa/patches/000-conf-dir.patch new file mode 100644 index 0000000000..171694b7b5 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/flycast-sa/patches/000-conf-dir.patch @@ -0,0 +1,83 @@ +diff --git a/core/linux-dist/main.cpp b/core/linux-dist/main.cpp +index 83a18bc7..1c3ac548 100644 +--- a/core/linux-dist/main.cpp ++++ b/core/linux-dist/main.cpp +@@ -42,6 +42,10 @@ void common_linux_setup(); + // $HOME/.config/flycast on linux + static std::string find_user_config_dir() + { ++#ifdef __unix__ ++ flycast::mkdir("/storage/.config/flycast", 0755); ++ return "/storage/.config/flycast/"; ++#else + std::string xdg_home; + if (nowide::getenv("XDG_CONFIG_HOME") != nullptr) + // If XDG_CONFIG_HOME is set explicitly, we'll use that instead of $HOME/.config +@@ -65,12 +69,17 @@ static std::string find_user_config_dir() + } + // Unable to detect config dir, use the current folder + return "."; ++#endif + } + + // Find the user data directory. + // $HOME/.local/share/flycast on linux + static std::string find_user_data_dir() + { ++#ifdef __unix__ ++ flycast::mkdir("/storage/roms/dreamcast/data", 0755); ++ return "/storage/roms/dreamcast/data/"; ++#else + std::string xdg_home; + if (nowide::getenv("XDG_DATA_HOME") != nullptr) + // If XDG_DATA_HOME is set explicitly, we'll use that instead of $HOME/.local/share +@@ -94,6 +103,7 @@ static std::string find_user_data_dir() + } + // Unable to detect data dir, use the current folder + return "."; ++#endif + } + + static void addDirectoriesFromPath(std::vector& dirs, const std::string& path, const std::string& suffix) +@@ -123,8 +133,10 @@ static void addDirectoriesFromPath(std::vector& dirs, const std::st + // . + static std::vector find_system_config_dirs() + { +- std::vector dirs; +- ++ std::vector dirs; ++#ifdef __unix__ ++ dirs.push_back("/storage/.config/flycast/"); ++#else + std::string xdg_home; + if (nowide::getenv("XDG_CONFIG_HOME") != nullptr) + // If XDG_CONFIG_HOME is set explicitly, we'll use that instead of $HOME/.config +@@ -150,7 +162,7 @@ static std::vector find_system_config_dirs() + dirs.push_back("/etc/xdg/flycast/"); + } + dirs.push_back("./"); +- ++#endif + return dirs; + } + +@@ -168,7 +180,9 @@ static std::vector find_system_config_dirs() + static std::vector find_system_data_dirs() + { + std::vector dirs; +- ++#ifdef __unix__ ++ dirs.push_back("/storage/roms/dreamcast/data/"); ++#else + std::string xdg_home; + if (nowide::getenv("XDG_DATA_HOME") != nullptr) + // If XDG_DATA_HOME is set explicitly, we'll use that instead of $HOME/.local/share +@@ -200,7 +214,7 @@ static std::vector find_system_data_dirs() + } + dirs.push_back("./"); + dirs.push_back("data/"); +- ++#endif + return dirs; + } + diff --git a/projects/ArchR/packages/emulators/standalone/flycast-sa/patches/001-fix-building-with-gcc15.patch b/projects/ArchR/packages/emulators/standalone/flycast-sa/patches/001-fix-building-with-gcc15.patch new file mode 100644 index 0000000000..84157201e5 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/flycast-sa/patches/001-fix-building-with-gcc15.patch @@ -0,0 +1,10 @@ +--- a/core/deps/glslang/SPIRV/SpvBuilder.h ++++ b/core/deps/glslang/SPIRV/SpvBuilder.h +@@ -63,6 +63,7 @@ + #include + #include + #include ++#include + + namespace spv { + diff --git a/projects/ArchR/packages/emulators/standalone/flycast-sa/patches/003-fix-sdl-controller.patch b/projects/ArchR/packages/emulators/standalone/flycast-sa/patches/003-fix-sdl-controller.patch new file mode 100644 index 0000000000..acdf902ef0 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/flycast-sa/patches/003-fix-sdl-controller.patch @@ -0,0 +1,16 @@ +diff --git a/core/sdl/sdl.cpp b/core/sdl/sdl.cpp +index 62467d08..cb167b4f 100644 +--- a/core/sdl/sdl.cpp ++++ b/core/sdl/sdl.cpp +@@ -160,6 +160,11 @@ void input_sdl_init() + #endif + std::string db = get_readonly_data_path("gamecontrollerdb.txt"); + int rv = SDL_GameControllerAddMappingsFromFile(db.c_str()); ++ if (rv < 0 && (nowide::getenv("SDL_GAMECONTROLLERCONFIG_FILE") != NULL)) ++ { ++ db = (std::string) nowide::getenv("SDL_GAMECONTROLLERCONFIG_FILE"); ++ rv = SDL_GameControllerAddMappingsFromFile(db.c_str()); ++ } + if (rv < 0) + { + db = get_readonly_config_path("gamecontrollerdb.txt"); diff --git a/projects/ArchR/packages/emulators/standalone/flycast-sa/scripts/cheevos_flycast.sh b/projects/ArchR/packages/emulators/standalone/flycast-sa/scripts/cheevos_flycast.sh new file mode 100644 index 0000000000..469072e5f8 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/flycast-sa/scripts/cheevos_flycast.sh @@ -0,0 +1,63 @@ +#! /bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-present Hector Calvarro (https://github.com/kelvfimer) +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile + +FLYCAST_CFG="/storage/.config/flycast/emu.cfg" +LOG_FILE="/var/log/cheevos.log" + +# Extract username, password, token, if enabled, and hardcore mode from system.cfg +username=$(get_setting "global.retroachievements.username") +password=$(get_setting "global.retroachievements.password") +token=$(get_setting "global.retroachievements.token") +enabled=$(get_setting "global.retroachievements") +hardcore=$(get_setting "global.retroachievements.hardcore") + +# Check if RetroAchievements are enabled in Emulation Station +if [ ! ${enabled} = 1 ]; then + echo "RetroAchievements are not enabled, please turn them on in Emulation Station." > ${LOG_FILE} + sed -i '/\[achievements\]/,/^\s*$/s/Enabled =.*/Enabled = no/' ${FLYCAST_CFG} + exit 1 +fi + +# Check if api token is present in system.cfg +if [ -z "${token}" ]; then + echo "RetroAchievements token is empty, please log in with your RetroAchievements credentials in Emulation Station." > ${LOG_FILE} + exit 1 +fi + +# Set hardcore mode +if [ "${hardcore}" = 1 ]; then + hardcore="true" +else + hardcore="false" +fi + +# Update emulator config with RetroAchievements settings +zcheevos=$(grep -Fx "[achievements]" ${FLYCAST_CFG}) + +if [ -z "${zcheevos}" ]; then + sed -i "\$a [achievements]\nEnabled = yes\nHardcoreMode = ${hardcore}\nUserName = ${username}\nToken = ${token}" ${FLYCAST_CFG} +else + sed -i '/\[achievements\]/,/^\s*$/s/Enabled =.*/Enabled = yes/' ${FLYCAST_CFG} + if ! grep -q "^HardcoreMode = " ${FLYCAST_CFG}; then + sed -i "/^\[achievements\]/a HardcoreMode = ${hardcore}" ${FLYCAST_CFG} + else + sed -i "/^\[achievements\]/,/^\[/{s/^HardcoreMode = .*/HardcoreMode = ${hardcore}/;}" ${FLYCAST_CFG} + fi + + if ! grep -q "^UserName = " ${FLYCAST_CFG}; then + sed -i "/^\[achievements\]/a UserName = ${username}" ${FLYCAST_CFG} + else + sed -i "/^\[achievements\]/,/^\[/{s/^UserName = .*/UserName = ${username}/;}" ${FLYCAST_CFG} + fi + + if ! grep -q "^Token = " ${FLYCAST_CFG}; then + sed -i "/^\[achievements\]/a Token = ${token}" ${FLYCAST_CFG} + else + sed -i "/^\[achievements\]/,/^\[/{s/^Token = .*/Token = ${token}/;}" ${FLYCAST_CFG} + fi +fi diff --git a/projects/ArchR/packages/emulators/standalone/flycast-sa/scripts/start_flycast.sh b/projects/ArchR/packages/emulators/standalone/flycast-sa/scripts/start_flycast.sh new file mode 100644 index 0000000000..2c26ece69c --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/flycast-sa/scripts/start_flycast.sh @@ -0,0 +1,159 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile +set_kill set "-9 flycast" + +#load gptokeyb support files +control-gen_init.sh +source /storage/.config/gptokeyb/control.ini +get_controls + +# Conf files vars +SOURCE_DIR="/usr/config/flycast" +CONF_DIR="/storage/.config/flycast" +FLYCAST_INI="emu.cfg" + +#Check if flycast exists in .config +if [ ! -d "/storage/.config/flycast" ]; then + cp -r "${SOURCE_DIR}" "${CONF_DIR}" +fi + +#Move save file storage/roms +if [ -d "${CONF_DIR}/data" ]; then + mv "${CONF_DIR}/data" "/storage/roms/dreamcast/" +fi + +#Make flycast bios folder +if [ ! -d "/storage/roms/bios/dc" ]; then + mkdir -p "/storage/roms/bios/dc" +fi + +#Link .config/flycast to .local +ln -sf "/storage/roms/bios/dc" "/storage/roms/dreamcast/data" + + +#Make sure flycast gptk config exists +if [ ! -f "${CONF_DIR}/flycast.gptk" ]; then + cp -r "/usr/config/flycast/flycast.gptk" "${CONF_DIR}/flycast.gptk" +fi + +#Make sure flycast gptk SDL_Keyboard.cfg exists +if [ ! -f "${CONF_DIR}/mappings/SDL_Keyboard.cfg" ]; then + cp -r "/usr/config/flycast/mappings/SDL_Keyboard.cfg" "${CONF_DIR}/mappings/SDL_Keyboard.cfg" +fi + +#Emulation Station Features +GAME=$(echo "${1}"| sed "s#^/.*/##") +PLATFORM=$(echo "${2}"| sed "s#^/.*/##") +ASPECT=$(get_setting aspect_ratio "${PLATFORM}" "${GAME}") +ASKIP=$(get_setting auto_frame_skip "${PLATFORM}" "${GAME}") +FPS=$(get_setting show_fps "${PLATFORM}" "${GAME}") +IRES=$(get_setting internal_resolution "${PLATFORM}" "${GAME}") +GRENDERER=$(get_setting graphics_backend "${PLATFORM}" "${GAME}") +VSYNC=$(get_setting vsync "${PLATFORM}" "${GAME}") + +#Set the cores to use +CORES=$(get_setting "cores" "${PLATFORM}" "${GAME}") +if [ "${CORES}" = "little" ] +then + EMUPERF="${SLOW_CORES}" +elif [ "${CORES}" = "big" ] +then + EMUPERF="${FAST_CORES}" +else + ### All.. + unset EMUPERF +fi + + #AspectRatio + if [ "$ASPECT" = "w" ]; then + sed -i '/^rend.WideScreen =/c\rend.WideScreen = yes' "${CONF_DIR}/${FLYCAST_INI}" + sed -i '/^rend.SuperWideScreen =/c\rend.SuperWideScreen = no' "${CONF_DIR}/${FLYCAST_INI}" + elif [ "$ASPECT" = "sw" ]; then + sed -i '/^rend.WideScreen =/c\rend.WideScreen = yes' "${CONF_DIR}/${FLYCAST_INI}" + sed -i '/^rend.SuperWideScreen =/c\rend.SuperWideScreen = yes' "${CONF_DIR}/${FLYCAST_INI}" + else + sed -i '/^rend.WideScreen =/c\rend.WideScreen = no' "${CONF_DIR}/${FLYCAST_INI}" + sed -i '/^rend.SuperWideScreen =/c\rend.SuperWideScreen = no' "${CONF_DIR}/${FLYCAST_INI}" + fi + + #AutoFrameSkip + if [ "$ASKIP" = "normal" ]; then + sed -i '/^pvr.AutoSkipFrame =/c\pvr.AutoSkipFrame = 1' "${CONF_DIR}/${FLYCAST_INI}" + elif [ "$ASKIP" = "max" ]; then + sed -i '/^pvr.AutoSkipFrame =/c\pvr.AutoSkipFrame = 2' "${CONF_DIR}/${FLYCAST_INI}" + else + sed -i '/^pvr.AutoSkipFrame =/c\pvr.AutoSkipFrame = 0' "${CONF_DIR}/${FLYCAST_INI}" + fi + + #Internal Resolution + if [ "$IRES" = "0" ]; then + sed -i '/rend.Resolution =/c\rend.Resolution = 240' "${CONF_DIR}/${FLYCAST_INI}" + elif [ "$IRES" = "2" ]; then + sed -i '/rend.Resolution =/c\rend.Resolution = 720' "${CONF_DIR}/${FLYCAST_INI}" + elif [ "$IRES" = "3" ]; then + sed -i '/rend.Resolution =/c\rend.Resolution = 960' "${CONF_DIR}/${FLYCAST_INI}" + elif [ "$IRES" = "4" ]; then + sed -i '/rend.Resolution =/c\rend.Resolution = 1200' "${CONF_DIR}/${FLYCAST_INI}" + elif [ "$IRES" = "5" ]; then + sed -i '/rend.Resolution =/c\rend.Resolution = 1440' "${CONF_DIR}/${FLYCAST_INI}" + else + sed -i '/rend.Resolution =/c\rend.Resolution = 480' "${CONF_DIR}/${FLYCAST_INI}" + fi + + #Graphics Renderer + if [ "$GRENDERER" = "opengl" ]; then + sed -i '/^pvr.rend =/c\pvr.rend = 0' "${CONF_DIR}/${FLYCAST_INI}" + elif [ "$GRENDERER" = "vulkan" ]; then + sed -i '/^pvr.rend =/c\pvr.rend = 4' "${CONF_DIR}/${FLYCAST_INI}" + else + sed -i '/^pvr.rend =/c\pvr.rend = @GRENDERER@' "${CONF_DIR}/${FLYCAST_INI}" + fi + + #ShowFPS + if [ "$FPS" = "1" ]; then + sed -i '/^rend.ShowFPS =/c\rend.ShowFPS = yes' "${CONF_DIR}/${FLYCAST_INI}" + else + sed -i '/^rend.ShowFPS =/c\rend.ShowFPS = no' "${CONF_DIR}/${FLYCAST_INI}" + fi + + #Vsync + if [ "$VSYNC" = "1" ];then + sed -i '/^rend.vsync =/c\rend.vsync = yes' "${CONF_DIR}/${FLYCAST_INI}" + else + sed -i '/^rend.vsync =/c\rend.vsync = no' "${CONF_DIR}/${FLYCAST_INI}" + fi + +#Retroachievements +/usr/bin/cheevos_flycast.sh + +# Debugging info: + echo "GAME set to: ${GAME}" + echo "PLATFORM set to: ${PLATFORM}" + echo "CONF DIR: ${CONF_DIR}/${FLYCAST_INI}" + echo "CPU CORES set to: ${EMUPERF}" + echo "ASPECT RATIO set to: ${ASPECT}" + echo "AUTO FRAME SKIP set to: ${ASKIP}" + echo "INTERNAL RESOLUTION set to: ${IRES}" + echo "GRAPHICS RENDERER set to: ${GRENDERER}" + echo "FPS set to: ${FPS}" + echo "VSYNC set to: ${VSYNC}" + echo "Launching /usr/bin/flycast ${1}" + +# Panfrost optimization for Mali-G31 +export PAN_MESA_DEBUG=forcepack +export MESA_NO_ERROR=1 +# Mesa GL command thread: Flycast already runs GL in a worker thread +# (rend.ThreadedRendering=1) and is GPU-bound on RK3326. Marshalling GL +# calls into Mesa's own thread amortises the per-call dispatch cost on a +# single-issue Cortex-A35. See docs/mesa-glthread-matrix.md. +export MESA_GLTHREAD=true + +#Run flycast emulator +$GPTOKEYB "flycast" -c "${CONF_DIR}/flycast.gptk" & +${EMUPERF} /usr/bin/flycast "${1}" +_gptokeyb_pid="$(pidof gptokeyb 2>/dev/null)" +[ -n "${_gptokeyb_pid}" ] && kill -9 ${_gptokeyb_pid} diff --git a/projects/ArchR/packages/emulators/standalone/gzdoom-sa/config/gzdoom.ini b/projects/ArchR/packages/emulators/standalone/gzdoom-sa/config/gzdoom.ini new file mode 100644 index 0000000000..31f69a36ac --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/gzdoom-sa/config/gzdoom.ini @@ -0,0 +1,749 @@ +# 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/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/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/gzdoom/soundfonts +Path=/storage/.config/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/gzdoom/autoexec.cfg + +[Heretic.AutoExec] +Path=/storage/.config/gzdoom/autoexec.cfg + +[Hexen.AutoExec] +Path=/storage/.config/gzdoom/autoexec.cfg + +[Strife.AutoExec] +Path=/storage/.config/gzdoom/autoexec.cfg + +[Chex.AutoExec] +Path=/storage/.config/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=1920 +vid_defwidth=1080 +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 +Joy9= +Joy10= +Joy11=weapprev +Joy12=weapnext +Joy13=togglemap +Joy14=menu_main +Joy16=centerview +Joy18= +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/projects/ArchR/packages/emulators/standalone/gzdoom-sa/package.mk b/projects/ArchR/packages/emulators/standalone/gzdoom-sa/package.mk new file mode 100644 index 0000000000..4d2d37bfa6 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/gzdoom-sa/package.mk @@ -0,0 +1,62 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present 351ELEC (https://github.com/351ELEC) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="gzdoom-sa" +PKG_VERSION="g4.14.2" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/ZDoom/gzdoom" +PKG_URL="https://github.com/ZDoom/gzdoom/archive/refs/tags/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="toolchain SDL2:host zmusic:host libvpx:host libwebp:host" +PKG_DEPENDS_TARGET="toolchain SDL2 gzdoom-sa:host zmusic libvpx libwebp" +PKG_LONGDESC="GZDoom is a modder-friendly OpenGL and Vulkan source port based on the DOOM engine" +PKG_TOOLCHAIN="cmake-make" + +pre_configure_host() { + unset HOST_CMAKE_OPTS + PKG_CMAKE_OPTS_HOST+=" -DZMUSIC_LIBRARIES=${TOOLCHAIN}/usr/lib/libzmusic.so \ + -DZMUSIC_INCLUDE_DIR=${TOOLCHAIN}/usr/include \ + -DNO_GTK=ON \ + -DHAVE_VULKAN=OFF \ + -DHAVE_GLES2=OFF" +} + +makeinstall_host() { + : +} + +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 \ + -DZMUSIC_LIBRARIES=${SYSROOT_PREFIX}/usr/lib/libzmusic.so -DZMUSIC_INCLUDE_DIR=${SYSROOT_PREFIX}/usr/include" + ### Enable GLES on devices that don't support OpenGL. + if [ ! "${OPENGL_SUPPORT}" = "yes" ] || [ ${PREFER_GLES} = "yes" ] + then + PKG_CMAKE_OPTS_TARGET+=" -DHAVE_GLES2=ON" + fi + + ### Enable vulkan support on devices that have it available. + if [ "${VULKAN_SUPPORT}" = "yes" ] + then + PKG_CMAKE_OPTS_TARGET+=" -DHAVE_VULKAN=ON" + else + PKG_CMAKE_OPTS_TARGET+=" -DHAVE_VULKAN=OFF" + fi +} + +makeinstall_target() { + + mkdir -p ${INSTALL}/usr/bin + cp ${PKG_BUILD}/.${TARGET_NAME}/gzdoom ${INSTALL}/usr/bin + cp ${PKG_DIR}/scripts/start_gzdoom.sh ${INSTALL}/usr/bin/ + chmod +x ${INSTALL}/usr/bin/* + + mkdir -p ${INSTALL}/usr/config/gzdoom + cp ${PKG_DIR}/config/* ${INSTALL}/usr/config/gzdoom + cp ${PKG_BUILD}/.${TARGET_NAME}/*.pk3 ${INSTALL}/usr/config/gzdoom + cp -r ${PKG_BUILD}/.${TARGET_NAME}/soundfonts ${INSTALL}/usr/config/gzdoom + cp -r ${PKG_BUILD}/.${TARGET_NAME}/fm_banks ${INSTALL}/usr/config/gzdoom +} diff --git a/projects/ArchR/packages/emulators/standalone/gzdoom-sa/patches/000-fix-build.patch b/projects/ArchR/packages/emulators/standalone/gzdoom-sa/patches/000-fix-build.patch new file mode 100644 index 0000000000..4d6d089da2 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/gzdoom-sa/patches/000-fix-build.patch @@ -0,0 +1,140 @@ +diff --git a/specs/udmf_zdoom.txt b/specs/udmf_zdoom.txt +index ebc831d57..f2d7974a8 100644 +--- a/specs/udmf_zdoom.txt ++++ b/specs/udmf_zdoom.txt +@@ -218,6 +218,9 @@ Note: All fields default to false unless mentioned otherwise. + useowncolors_bottom = ; // Set to 1 to use the colors set in the sidedef. Default is using the colors from the owning sector. + uppercolor_bottom = ; // Material color of the top of the lower tier. + lowercolor_bottom = ; // Material color of the bottom of the lower tier. (Hardware rendering only.) ++ colorscalefactor_top = // scales the material color by the given factor. Default is 1. ++ colorscalefactor_mid = // scales the material color by the given factor. Default is 1. ++ colorscalefactor_bottom = // scales the material color by the given factor. Default is 1. + + useowncoloradd_top = ; // Controls where the advanced colorization properties are taken from. + useowncoloradd_mid = ; // 0: From the containing sector, 1: from the given part of the linedef itself +diff --git a/src/common/console/keydef.h b/src/common/console/keydef.h +index 108806774..971ab398f 100644 +--- a/src/common/console/keydef.h ++++ b/src/common/console/keydef.h +@@ -75,8 +75,13 @@ enum EKeyCodes + KEY_JOY6, + KEY_JOY7, + KEY_JOY8, +- KEY_JOY14 = KEY_FIRSTJOYBUTTON+13, +- KEY_JOY15 = KEY_FIRSTJOYBUTTON+14, ++ KEY_JOY9, ++ KEY_JOY10, ++ KEY_JOY11, ++ KEY_JOY12, ++ KEY_JOY13, ++ KEY_JOY14, ++ KEY_JOY15, + KEY_LASTJOYBUTTON = 0x187, + KEY_JOYPOV1_UP = 0x188, + KEY_JOYPOV1_RIGHT = 0x189, +diff --git a/src/common/menu/menu.cpp b/src/common/menu/menu.cpp +index 448b196a1..62f4819aa 100644 +--- a/src/common/menu/menu.cpp ++++ b/src/common/menu/menu.cpp +@@ -687,15 +687,12 @@ bool M_Responder (event_t *ev) + ch = ev->data1; + switch (ch) + { +- case KEY_JOY1: +- case KEY_JOY3: +- case KEY_JOY15: ++ case KEY_JOY2: + case KEY_PAD_A: + mkey = MKEY_Enter; + break; + +- case KEY_JOY2: +- case KEY_JOY14: ++ case KEY_JOY1: + case KEY_PAD_B: + mkey = MKEY_Back; + break; +@@ -719,6 +716,7 @@ bool M_Responder (event_t *ev) + case KEY_PAD_LTHUMB_UP: + case KEY_JOYAXIS2MINUS: + case KEY_JOYPOV1_UP: ++ case KEY_JOY9: + mkey = MKEY_Up; + break; + +@@ -726,6 +724,7 @@ bool M_Responder (event_t *ev) + case KEY_PAD_LTHUMB_DOWN: + case KEY_JOYAXIS2PLUS: + case KEY_JOYPOV1_DOWN: ++ case KEY_JOY10: + mkey = MKEY_Down; + break; + +@@ -733,6 +732,7 @@ bool M_Responder (event_t *ev) + case KEY_PAD_LTHUMB_LEFT: + case KEY_JOYAXIS1MINUS: + case KEY_JOYPOV1_LEFT: ++ case KEY_JOY11: + mkey = MKEY_Left; + break; + +@@ -740,6 +740,7 @@ bool M_Responder (event_t *ev) + case KEY_PAD_LTHUMB_RIGHT: + case KEY_JOYAXIS1PLUS: + case KEY_JOYPOV1_RIGHT: ++ case KEY_JOY12: + mkey = MKEY_Right; + break; + } +diff --git a/src/common/platform/posix/sdl/i_gui.cpp b/src/common/platform/posix/sdl/i_gui.cpp +index 9290f063f..62df74a35 100644 +--- a/src/common/platform/posix/sdl/i_gui.cpp ++++ b/src/common/platform/posix/sdl/i_gui.cpp +@@ -68,7 +68,7 @@ bool I_SetCursor(FGameTexture *cursorpic) + SDL_FreeCursor (cursor); + cursor = SDL_CreateColorCursor (cursorSurface, 0, 0); + SDL_SetCursor (cursor); +- SDL_ShowCursor(SDL_ENABLE); ++ SDL_ShowCursor(SDL_DISABLE); + } + else + { +diff --git a/src/gamedata/doomfont.h b/src/gamedata/doomfont.h +index fedeb513c..23b2c0759 100644 +--- a/src/gamedata/doomfont.h ++++ b/src/gamedata/doomfont.h +@@ -57,6 +57,6 @@ void InitDoomFonts() + } + else if (fileSystem.CheckNumForName("STCFN033", FileSys::ns_graphics) >= 0) + { +- OriginalSmallFont = new FFont("OriginalSmallFont", "STCFN%.3d", "defsmallfont", HU_FONTSTART, HU_FONTSIZE, HU_FONTSTART, -1, -1, false, true, true); ++ OriginalSmallFont = new FFont("OriginalSmallFont", "STCFN%.3d", "defsmallfont", HU_FONTSTART, HU_FONTSIZE, HU_FONTSTART, -1, -1, false, true); + } + +diff --git a/wadsrc/static/language.def b/wadsrc/static/language.def +index da8ddfb4a..a0e3cc60d 100644 +--- a/wadsrc/static/language.def ++++ b/wadsrc/static/language.def +@@ -99,6 +99,9 @@ STARTUP3 = ""; + STARTUP4 = ""; + STARTUP5 = ""; + ++// Engine strings ++CNTRLMNU_OPEN_MAIN = "Open Main Menu"; ++ + // Placeholder definitions for strings that are in the game content table where the labels are needed even when that file is not loaded. + + // Level names + +diff --git a/src/common/rendering/gles/gles_system.cpp b/src/common/rendering/gles/gles_system.cpp +index d9bedafdd..2b02dfcd8 100644 +--- a/src/common/rendering/gles/gles_system.cpp ++++ b/src/common/rendering/gles/gles_system.cpp +@@ -208,6 +208,7 @@ namespace OpenGLESRenderer + gles.npotAvailable = CheckExtension("GL_OES_texture_npot"); + gles.depthClampAvailable = CheckExtension("GL_EXT_depth_clamp"); + gles.anistropicFilterAvailable = CheckExtension("GL_EXT_texture_filter_anisotropic"); ++ gles.useMappedBuffers = true; + } + else if (gles.glesMode == GLES_MODE_OGL2) + { diff --git a/projects/ArchR/packages/emulators/standalone/gzdoom-sa/scripts/start_gzdoom.sh b/projects/ArchR/packages/emulators/standalone/gzdoom-sa/scripts/start_gzdoom.sh new file mode 100644 index 0000000000..944a29bf34 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/gzdoom-sa/scripts/start_gzdoom.sh @@ -0,0 +1,88 @@ +#!/usr/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present 351ELEC (https://github.com/351ELEC) + +. /etc/profile +set_kill set "-9 gzdoom" + +RUN_DIR="/storage/roms/doom" +CONFIG="/storage/.config/gzdoom/gzdoom.ini" +SAVE_DIR="/storage/roms/gzdoom" + +#Emulation Station Features +GAME=$(echo "${1}"| sed "s#^/.*/##") +PLATFORM=$(echo "${2}"| sed "s#^/.*/##") +VSYNC=$(get_setting vsync "${PLATFORM}" "${GAME}") + + +if [ ! -d "/storage/.config/gzdoom/" ]; then + cp -rf /usr/config/gzdoom /storage/.config/ +fi + +if [ ! -f "/storage/.config/gzdoom/gzdoom.ini" ]; then + cp -rf /usr/config/gzdoom/gzdoom.ini /storage/.config/gzdoom/ +fi + +# Check for newer pk3 files +SHASUMSRC=$(sha256sum "/usr/config/gzdoom/gzdoom.pk3" | awk '{print $1}') +SHASUMDST=$(sha256sum "/storage/.config/gzdoom/gzdoom.pk3" | awk '{print $1}') + +if [ $SHASUMSRC != $SHASUMDST ]; then + cp /usr/config/gzdoom/*.pk3 /storage/.config/gzdoom/ +fi + +# set resolution +sed -i '/vid_defheight=/c\vid_defheight='$(fbheight) /storage/.config/gzdoom/gzdoom.ini +sed -i '/vid_defwidth=/c\vid_defwidth='$(fbwidth) /storage/.config/gzdoom/gzdoom.ini + +if [ ! -d "/storage/roms/doom/iwads" ]; then + mkdir /storage/roms/doom/iwads +fi + +if [ ! -d "/storage/roms/doom/mods" ]; then + mkdir /storage/roms/doom/mods +fi + +mkdir -p ${SAVE_DIR} + +params=" -config ${CONFIG} -savedir ${SAVE_DIR}" +params+=" +gl_es 1 +vid_preferbackend 3 +cl_capfps 0 +vid_fps 0" + +if [ "$VSYNC" = "false" ]; then + params+=" +vid_vsync 0" +else + params+=" +vid_vsync 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 + +#Set the cores to use +CORES=$(get_setting "cores" "${PLATFORM}" "${GAME}") +if [ "${CORES}" = "little" ]; then + EMUPERF="${SLOW_CORES}" +elif [ "${CORES}" = "big" ]; then + EMUPERF="${FAST_CORES}" +else + ### All.. + unset EMUPERF +fi + +cd "${RUN_DIR}" +echo ${params} | ${EMUPERF} xargs /usr/bin/gzdoom +gl_es 1 +vid_preferbackend 3 +cl_capfps 0 >/var/log/gzdoom.log 2>&1 diff --git a/projects/ArchR/packages/emulators/standalone/gzdoom-sa/zmusic/package.mk b/projects/ArchR/packages/emulators/standalone/gzdoom-sa/zmusic/package.mk new file mode 100644 index 0000000000..21a563bd5b --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/gzdoom-sa/zmusic/package.mk @@ -0,0 +1,45 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present 351ELEC (https://github.com/351ELEC) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="zmusic" +PKG_VERSION="1.1.14" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/ZDoom/ZMusic" +PKG_URL="https://github.com/ZDoom/ZMusic/archive/refs/tags/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="toolchain" +PKG_DEPENDS_TARGET="toolchain zmusic:host glib" +PKG_LONGDESC="GZDoom's music system as a standalone library" +PKG_TOOLCHAIN="cmake-make" + +make_host() { + [ -d "${PKG_BUILD}/build" ] && rm -rf ${PKG_BUILD}/build + mkdir ${PKG_BUILD}/build + cd ${PKG_BUILD}/build + unset HOST_CMAKE_OPTS + cmake -DCMAKE_BUILD_TYPE=Release .. + cmake --build . +} + +make_target() { + [ -d "${PKG_BUILD}/build" ] && rm -rf ${PKG_BUILD}/build + mkdir ${PKG_BUILD}/build + cd ${PKG_BUILD}/build + cmake -DCMAKE_BUILD_TYPE=Release .. + cmake --build . +} + +makeinstall_host() { + mkdir -p ${TOOLCHAIN}/usr/{lib,include} + cp -f ${PKG_BUILD}/build/source/libzmusic* ${TOOLCHAIN}/usr/lib/ + cp -f ${PKG_BUILD}/include/zmusic.h ${TOOLCHAIN}/usr/include +} + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/{lib,include} + cp -f ${PKG_BUILD}/build/source/libzmusic* ${SYSROOT_PREFIX}/usr/lib/ + cp -f ${PKG_BUILD}/include/zmusic.h ${SYSROOT_PREFIX}/usr/include + + mkdir -p ${INSTALL}/usr/lib + cp -f ${PKG_BUILD}/build/source/libzmusic* ${INSTALL}/usr/lib +} diff --git a/projects/ArchR/packages/emulators/standalone/hatarisa/config/conf/Atari-ST-default.cfg b/projects/ArchR/packages/emulators/standalone/hatarisa/config/conf/Atari-ST-default.cfg new file mode 100644 index 0000000000..f242a8e4aa --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/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/projects/ArchR/packages/emulators/standalone/hatarisa/package.mk b/projects/ArchR/packages/emulators/standalone/hatarisa/package.mk new file mode 100644 index 0000000000..54b5377fd1 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/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="6da06056d89bb39777063388d82d065d9e2e31fd" +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_install_dir capsimg)/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/hatarisa + cp -R ${PKG_DIR}/scripts/start_hatari.sh ${INSTALL}/usr/bin/ + chmod 0755 ${INSTALL}/usr/bin/start_hatari.sh +} diff --git a/projects/ArchR/packages/emulators/standalone/hatarisa/portaudio/package.mk b/projects/ArchR/packages/emulators/standalone/hatarisa/portaudio/package.mk new file mode 100644 index 0000000000..21281b7716 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/hatarisa/portaudio/package.mk @@ -0,0 +1,13 @@ +# 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." + +PKG_CMAKE_OPTS_TARGET="-DCMAKE_POLICY_VERSION_MINIMUM=3.5" diff --git a/projects/ArchR/packages/emulators/standalone/hatarisa/scripts/start_hatari.sh b/projects/ArchR/packages/emulators/standalone/hatarisa/scripts/start_hatari.sh new file mode 100755 index 0000000000..5f55c2886b --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/hatarisa/scripts/start_hatari.sh @@ -0,0 +1,74 @@ +#!/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="/var/log/hatari.log" +MAX_DRIVES=2 +i=0 + +# 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 hatarisa --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 hatarisa --configfile "$1" >> $HATARI_LOG 2>&1 +# All other files +else + nice -n -19 hatarisa --configfile "$HATARI_TMP_CONFIG" --disk-a "$1" >> $HATARI_LOG 2>&1 +fi +# Remove temporary dir +rm -rf "$HATARI_TMP_DIR" diff --git a/projects/ArchR/packages/emulators/standalone/hypseus-singe/package.mk b/projects/ArchR/packages/emulators/standalone/hypseus-singe/package.mk new file mode 100644 index 0000000000..f3f4284f9c --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/hypseus-singe/package.mk @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="hypseus-singe" +PKG_VERSION="b353e1728bf56d8b6c6fb606df78b7296a203702" +PKG_LICENSE="GPL3" +PKG_SITE="https://github.com/DirtBagXon/hypseus-singe" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain SDL2 SDL2_ttf SDL2_image libmpeg2 libogg libvorbis libzip" +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/game/configs/hypseus + ln -fs /storage/roms/daphne/roms ${INSTALL}/usr/config/game/configs/hypseus/roms + ln -fs /usr/share/daphne/sound ${INSTALL}/usr/config/game/configs/hypseus/sound + ln -fs /usr/share/daphne/fonts ${INSTALL}/usr/config/game/configs/hypseus/fonts + ln -fs /usr/share/daphne/pics ${INSTALL}/usr/config/game/configs/hypseus/pics +} + +post_makeinstall_target() { + cp -rf ${PKG_BUILD}/doc/hypinput.ini ${INSTALL}/usr/config/game/configs/hypseus/ + ln -fs /storage/.config/game/configs/hypseus/hypinput.ini ${INSTALL}/usr/share/daphne/hypinput.ini + cp ${PKG_BUILD}/start_hypseus.sh ${INSTALL}/usr/bin +} diff --git a/projects/ArchR/packages/emulators/standalone/hypseus-singe/patches/hypseus-singe-001-buildfix.patch b/projects/ArchR/packages/emulators/standalone/hypseus-singe/patches/hypseus-singe-001-buildfix.patch new file mode 100644 index 0000000000..3e8887f125 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/hypseus-singe/patches/hypseus-singe-001-buildfix.patch @@ -0,0 +1,89 @@ +--- a/src/CMakeLists.txt 2021-06-07 19:12:18.646828485 +0200 ++++ b/src/CMakeLists.txt 2021-06-07 19:13:56.113491528 +0200 +@@ -45,14 +45,12 @@ + include(GNUInstallDirs) + include(InstallRequiredSystemLibraries) + include(FindPkgConfig) +-include(ExternalProject) +-include(BuildLibMPEG2) + + use_cxx11( ) + + PKG_SEARCH_MODULE(SDL2 REQUIRED sdl2) + PKG_SEARCH_MODULE(SDL2_TTF REQUIRED SDL2_ttf) +-build_libmpeg2( ) ++PKG_SEARCH_MODULE(MPEG2 REQUIRED libmpeg2) + + message(STATUS "Target: ${CMAKE_SYSTEM_NAME} ${CMAKE_TARGET_ARCHITECTURES}") + +@@ -91,7 +89,6 @@ + add_subdirectory(video) + add_subdirectory(vldp) + +-add_dependencies( vldp libmpeg2 ) + add_dependencies( ldp-out vldp ) + add_dependencies( game vldp ) + add_dependencies( sound vldp ) +@@ -129,3 +129,5 @@ set(CPACK_PACKAGE_VERSION_MINOR "${VER_MINOR}") + set(CPACK_PACKAGE_VERSION_PATCH "${VER_PATCH}") + + include(CPack) ++install(TARGETS hypseus DESTINATION bin) ++install(DIRECTORY ../pics ../fonts ../sound DESTINATION /usr/share/daphne) +diff --git a/src/vldp/vldp.h b/src/vldp/vldp.h +index a59c723..3c986dc 100644 +--- a/src/vldp/vldp.h ++++ b/src/vldp/vldp.h +@@ -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 --git a/src/vldp/vldp_internal.h b/src/vldp/vldp_internal.h +index cd046fe..67cea2d 100644 +--- a/src/vldp/vldp_internal.h ++++ b/src/vldp/vldp_internal.h +@@ -27,7 +27,6 @@ + + #include "vldp.h" // for the VLDP_BOOL definition and SDL.h + +-#include + + // this is which version of the .dat file format we are using + #define DAT_VERSION 2 + +--- a/src/manymouse/manymouse.c ++++ b/src/manymouse/manymouse.c +@@ -17,7 +17,6 @@ + extern const ManyMouseDriver *ManyMouseDriver_evdev; + extern const ManyMouseDriver *ManyMouseDriver_hidmanager; + extern const ManyMouseDriver *ManyMouseDriver_hidutilities; +-extern const ManyMouseDriver *ManyMouseDriver_xinput2; + + /* + * These have to be in the favored order...obviously it doesn't matter if the +@@ -31,7 +30,6 @@ + */ + static const ManyMouseDriver **mice_drivers[] = + { +- &ManyMouseDriver_xinput2, + &ManyMouseDriver_evdev, + &ManyMouseDriver_windows, + &ManyMouseDriver_hidmanager, + +--- a/src/manymouse/CMakeLists.txt ++++ b/src/manymouse/CMakeLists.txt +@@ -1,7 +1,8 @@ ++ ++ + set( LIB_SOURCES + manymouse.c linux_evdev.c macosx_hidmanager.c + macosx_hidutilities.c windows_wminput.c +- x11_xinput2.c + ) + + set( LIB_HEADERS diff --git a/projects/ArchR/packages/emulators/standalone/hypseus-singe/patches/hypseus-singe-002-headersfix.patch b/projects/ArchR/packages/emulators/standalone/hypseus-singe/patches/hypseus-singe-002-headersfix.patch new file mode 100644 index 0000000000..55a74a2f88 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/hypseus-singe/patches/hypseus-singe-002-headersfix.patch @@ -0,0 +1,13 @@ +diff --git a/src/game/singe.cpp b/src/game/singe.cpp +index b6506b8..fb2af4e 100644 +--- a/src/game/singe.cpp ++++ b/src/game/singe.cpp +@@ -28,6 +28,8 @@ + + #include "singe.h" + #include "singe/singe_interface.h" ++#include ++#include + + // Win32 doesn't use strcasecmp, it uses stricmp (lame) + #ifdef WIN32 diff --git a/projects/ArchR/packages/emulators/standalone/hypseus-singe/sources/start_hypseus.sh b/projects/ArchR/packages/emulators/standalone/hypseus-singe/sources/start_hypseus.sh new file mode 100755 index 0000000000..df3fb8e1f9 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/hypseus-singe/sources/start_hypseus.sh @@ -0,0 +1,87 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +dir="${1}" +name=${dir##*/} +name=${name%.*} +config="/storage/.config/game/configs/hypseus" +configfile="${config}/hypinput.ini" + +# Attempt to auto configure gamepad +# +GAMEPADINFO="$(sdljoytest -skip_loop)" +#JOYGUID=$(echo "${GAMEPADINFO}" | grep "Joystick 0 Guid " | sed "s|Joystick 0 Guid ||") +JOYNAME=$(echo "${GAMEPADINFO}" | grep "Joystick 0 name " | sed "s|Joystick 0 name ||" | sed "s|'||g") +# + +for file in /usr/share/libretro/autoconfig/*.cfg; do + GAMEPAD=$(cat "$file" | grep input_device | cut -d'"' -f 2) + if [ "${JOYNAME}" == "${GAMEPAD}" ]; then + GPFILE="${file}" + # Other keys to consider KEY_SCREENSHOT KEY_QUIT KEY_PAUSE + for key in KEY_UP KEY_DOWN KEY_LEFT KEY_RIGHT KEY_BUTTON1 KEY_BUTTON2 KEY_BUTTON3 KEY_START1 KEY_COIN1; do + case ${key} in + "KEY_UP") + button=$(cat "${GPFILE}" | grep -E 'input_up_btn' | cut -d '"' -f2) + keyboard="1073741906 0" + ;; + "KEY_DOWN") + button=$(cat "${GPFILE}" | grep -E 'input_down_btn' | cut -d '"' -f2) + keyboard="1073741905 0" + ;; + "KEY_LEFT") + button=$(cat "${GPFILE}" | grep -E 'input_left_btn' | cut -d '"' -f2) + keyboard="1073741904 0" + ;; + "KEY_RIGHT") + button=$(cat "${GPFILE}" | grep -E 'input_right_btn' | cut -d '"' -f2) + keyboard="1073741903 0" + ;; + "KEY_BUTTON1") + button=$(cat "${GPFILE}" | grep -E 'input_a_btn' | cut -d '"' -f2) + keyboard="1073742048 0" + ;; + "KEY_BUTTON2") + button=$(cat "${GPFILE}" | grep -E 'input_b_btn' | cut -d '"' -f2) + keyboard="1073742050 0" + ;; + "KEY_BUTTON3") + button=$(cat "${GPFILE}" | grep -E 'input_x_btn' | cut -d '"' -f2) + keyboard="32 0" + ;; + "KEY_START1") + button=$(cat "${GPFILE}" | grep -E 'input_start_btn' | cut -d '"' -f2) + keyboard="49 0" + ;; + "KEY_COIN1") + button=$(cat "${GPFILE}" | grep -E 'input_select_btn' | cut -d '"' -f2) + keyboard="53 54" + ;; + esac + + # if the button is in fact a hat extract the number, else use the button number+1 + if [[ "${button}" == "h"* ]]; then + button="0 ${button:1:1}" + else + button="$((${button} + 1))" + fi + + sed -i "s|${key}.*|${key} = ${keyboard} ${button} |" ${configfile} + done + fi +done # finish auto gamepad + +if [[ -f "${dir}/${name}.commands" ]]; then + params=$(<"${dir}/${name}.commands") +fi + +cd "${config}" + +if [[ -f "${dir}/${name}.singe" ]]; then + hypseus singe vldp -framefile "${dir}/${name}.txt" -script "${dir}/${name}.singe" -fullscreen -useoverlaysb 2 $params +else + hypseus "${name}" vldp -framefile "${dir}/${name}.txt" -fullscreen -useoverlaysb 2 $params +fi diff --git a/projects/ArchR/packages/emulators/standalone/mednafen/config/common/mednafen.template b/projects/ArchR/packages/emulators/standalone/mednafen/config/common/mednafen.template new file mode 100644 index 0000000000..1acdc0776d --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mednafen/config/common/mednafen.template @@ -0,0 +1,17652 @@ +;VERSION 1.31.0-UNSTABLE +;Edit this file at your own risk! +;DO NOT EDIT THIS FILE WHILE AN INSTANCE OF MEDNAFEN THAT USES IT IS RUNNING. +;File format: +; +;Dummy guard line to prevent settings file corruption by accidentally running ancient versions of Mednafen. Dummy guard line to prevent settings file corruption by accidentally running ancient versions of Mednafen. Dummy guard line to prevent settings file corruption by accidentally running ancient versions of Mednafen. Dummy guard line to prevent settings file corruption by accidentally running ancient versions of Mednafen. Dummy guard line to prevent settings file corruption by accidentally running ancient versions of Mednafen. Dummy guard line to prevent settings file corruption by accidentally running ancient versions of Mednafen. Dummy guard line to prevent settings file corruption by accidentally running ancient versions of Mednafen. Dummy guard line to prevent settings file corruption by accidentally running ancient versions of Mednafen. Dummy guard line to prevent settings file corruption by accidentally running ancient versions of Mednafen.;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;fs ~ + +;CD read threads CPU affinity mask. +affinity.cd 0 + +;Main emulation thread CPU affinity mask. +affinity.emu 0x3 + +;Video blitting thread CPU affinity mask. +affinity.video 0 + +;Automatically load/save state on game load/close. +autosave 0 + +;Cache entire CD images in memory. +cd.image_memcache 0 + +;M3U total number of disc images limit. +cd.m3u.disc_limit 50 + +;M3U recursion limit. +cd.m3u.recursion_limit 9 + +;Enable (automatic) usage of this module. +cdplay.enable 1 + +;Force monophonic sound output. +cdplay.forcemono 0 + +;cdplay, Built-In, Controller: Next Track +cdplay.input.builtin.controller.next_track keyboard 0x0 79 + +;cdplay, Built-In, Controller: Next Track 10 +cdplay.input.builtin.controller.next_track_10 keyboard 0x0 82 + +;cdplay, Built-In, Controller: Play/Pause +cdplay.input.builtin.controller.play_pause keyboard 0x0 44 + +;cdplay, Built-In, Controller: Previous Track +cdplay.input.builtin.controller.previous_track keyboard 0x0 80 + +;cdplay, Built-In, Controller: Previous Track 10 +cdplay.input.builtin.controller.previous_track_10 keyboard 0x0 81 + +;cdplay, Built-In, Controller: Scan Forward +cdplay.input.builtin.controller.scan_forward keyboard 0x0 75 + +;cdplay, Built-In, Controller: Scan Reverse +cdplay.input.builtin.controller.scan_reverse keyboard 0x0 78 + +;cdplay, Built-In, Controller: Stop +cdplay.input.builtin.controller.stop keyboard 0x0 40 + +;Enable scanlines with specified opacity. +cdplay.scanlines 0 + +;Enable specified OpenGL shader. +cdplay.shader none + +;Force interlaced video to be treated as progressive. +cdplay.shader.goat.fprog 0 + +;Constant RGB horizontal divergence. +cdplay.shader.goat.hdiv 0.50 + +;Mask pattern. +cdplay.shader.goat.pat goatron + +;Enable scanlines effect. +cdplay.shader.goat.slen 1 + +;Transparency of otherwise-opaque mask areas. +cdplay.shader.goat.tp 0.50 + +;Constant RGB vertical divergence. +cdplay.shader.goat.vdiv 0.50 + +;Enable specified special video scaler. +cdplay.special none + +;Stretch to fill screen. +cdplay.stretch aspect + +;Enable video temporal blur(50/50 previous/current frame by default). +cdplay.tblur 0 + +;Accumulate color data rather than discarding it. +cdplay.tblur.accum 0 + +;Blur amount in accumulation mode, specified in percentage of accumulation buffer to mix with the current frame. +cdplay.tblur.accum.amount 50 + +;Enable (bi)linear interpolation. +cdplay.videoip 0 + +;Enable simple waveform visualization. +cdplay.visualization 1 + +;Full-screen horizontal resolution. +cdplay.xres 0 + +;Scaling factor for the X axis in windowed mode. +cdplay.xscale 5.000000 + +;Scaling factor for the X axis in fullscreen mode. +cdplay.xscalefs 1.000000 + +;Full-screen vertical resolution. +cdplay.yres 0 + +;Scaling factor for the Y axis in windowed mode. +cdplay.yscale 5.000000 + +;Scaling factor for the Y axis in fullscreen mode. +cdplay.yscalefs 1.000000 + +;Enable cheats. +cheats 1 + +;Save state 0 select +command.0 keyboard 0x0 39 + +;Save state 1 select +command.1 keyboard 0x0 30 + +;Save state 2 select +command.2 keyboard 0x0 31 + +;Save state 3 select +command.3 keyboard 0x0 32 + +;Save state 4 select +command.4 keyboard 0x0 33 + +;Save state 5 select +command.5 keyboard 0x0 34 + +;Save state 6 select +command.6 keyboard 0x0 35 + +;Save state 7 select +command.7 keyboard 0x0 36 + +;Save state 8 select +command.8 keyboard 0x0 37 + +;Save state 9 select +command.9 keyboard 0x0 38 + +;Activate barcode(for Famicom) +command.activate_barcode keyboard 0x0 65 + +;Advance frame +command.advance_frame keyboard 0x0 4+alt + +;Select virtual device on virtual input port 1 +command.device_select1 keyboard 0x0 30+ctrl+shift + +;Select virtual device on virtual input port 10 +command.device_select10 keyboard 0x0 39+ctrl+shift + +;Select virtual device on virtual input port 11 +command.device_select11 keyboard 0x0 89+ctrl+shift + +;Select virtual device on virtual input port 12 +command.device_select12 keyboard 0x0 90+ctrl+shift + +;Select virtual device on virtual input port 13 +command.device_select13 keyboard 0x0 91+ctrl+shift + +;Select virtual device on virtual input port 2 +command.device_select2 keyboard 0x0 31+ctrl+shift + +;Select virtual device on virtual input port 3 +command.device_select3 keyboard 0x0 32+ctrl+shift + +;Select virtual device on virtual input port 4 +command.device_select4 keyboard 0x0 33+ctrl+shift + +;Select virtual device on virtual input port 5 +command.device_select5 keyboard 0x0 34+ctrl+shift + +;Select virtual device on virtual input port 6 +command.device_select6 keyboard 0x0 35+ctrl+shift + +;Select virtual device on virtual input port 7 +command.device_select7 keyboard 0x0 36+ctrl+shift + +;Select virtual device on virtual input port 8 +command.device_select8 keyboard 0x0 37+ctrl+shift + +;Select virtual device on virtual input port 9 +command.device_select9 keyboard 0x0 38+ctrl+shift + +;Exit +command.exit joystick @GUID1@ @DEVICE_FUNC_KEYA_MODIFIER@ && joystick @GUID1@ @DEVICE_BTN_START@ + +;Fast-forward +command.fast_forward joystick @GUID1@ @DEVICE_FUNC_KEYA_MODIFIER@ && joystick @GUID1@ @DEVICE_BTN_TR2@ + +;Configure buttons on virtual port 1 +command.input_config1 keyboard 0x0 30+alt+shift || joystick @GUID1@ @DEVICE_FUNC_KEYB_MODIFIER@ && joystick @GUID1@ @DEVICE_BTN_TL2@ + +;Configure buttons on virtual port 10 +command.input_config10 keyboard 0x0 39+alt+shift + +;Configure buttons on virtual port 11 +command.input_config11 keyboard 0x0 89+alt+shift + +;Configure buttons on virtual port 12 +command.input_config12 keyboard 0x0 90+alt+shift + +;Configure buttons on virtual port 13 +command.input_config13 keyboard 0x0 91+alt+shift + +;Configure buttons on virtual port 2 +command.input_config2 keyboard 0x0 31+alt+shift + +;Configure buttons on virtual port 3 +command.input_config3 keyboard 0x0 32+alt+shift + +;Configure buttons on virtual port 4 +command.input_config4 keyboard 0x0 33+alt+shift + +;Configure buttons on virtual port 5 +command.input_config5 keyboard 0x0 34+alt+shift + +;Configure buttons on virtual port 6 +command.input_config6 keyboard 0x0 35+alt+shift + +;Configure buttons on virtual port 7 +command.input_config7 keyboard 0x0 36+alt+shift + +;Configure buttons on virtual port 8 +command.input_config8 keyboard 0x0 37+alt+shift + +;Configure buttons on virtual port 9 +command.input_config9 keyboard 0x0 38+alt+shift + +;Detect analog buttons on physical joysticks/gamepads(for use with the input configuration process). +command.input_config_abd keyboard 0x0 60 + +;Configure command key +command.input_configc keyboard 0x0 59 + +;Configure command key, for all-pressed-to-trigger mode +command.input_configc_am keyboard 0x0 59+shift + +;Insert coin +command.insert_coin keyboard 0x0 65 || joystick @GUID1@ @DEVICE_FUNC_KEYB_MODIFIER@ && joystick @GUID1@ @DEVICE_BTN_TR2@ + +;Insert/Eject disk/disc +command.insert_eject_disk joystick @GUID1@ @DEVICE_FUNC_KEYB_MODIFIER@ && joystick @GUID1@ @DEVICE_BTN_TR@ + +;Load movie +command.load_movie keyboard 0x0 64+shift + +;Load state +command.load_state joystick @GUID1@ @DEVICE_FUNC_KEYA_MODIFIER@ && joystick @GUID1@ @DEVICE_BTN_TL@ + +;Movie 0 select +command.m0 keyboard 0x0 39+shift + +;Movie 1 select +command.m1 keyboard 0x0 30+shift + +;Movie 2 select +command.m2 keyboard 0x0 31+shift + +;Movie 3 select +command.m3 keyboard 0x0 32+shift + +;Movie 4 select +command.m4 keyboard 0x0 33+shift + +;Movie 5 select +command.m5 keyboard 0x0 34+shift + +;Movie 6 select +command.m6 keyboard 0x0 35+shift + +;Movie 7 select +command.m7 keyboard 0x0 36+shift + +;Movie 8 select +command.m8 keyboard 0x0 37+shift + +;Movie 9 select +command.m9 keyboard 0x0 38+shift + +;Pause/Unpause +command.pause keyboard 0x0 72 + +;Power toggle +command.power keyboard 0x0 68 + +;Reinitialize physical joysticks/gamepads. +command.reinit_joysticks keyboard 0x0 60+shift + +;Reset +command.reset keyboard 0x0 67 + +;Rotate screen +command.rotate_screen keyboard 0x0 18+alt + +;Return to normal mode after advancing frames +command.run_normal keyboard 0x0 21+alt + +;Save movie +command.save_movie keyboard 0x0 62+shift + +;Save state +command.save_state joystick @GUID1@ @DEVICE_FUNC_KEYA_MODIFIER@ && joystick @GUID1@ @DEVICE_BTN_TR@ + +;Select disk/disc +command.select_disk joystick @GUID1@ @DEVICE_FUNC_KEYB_MODIFIER@ && joystick @GUID1@ @DEVICE_BTN_TL@ + +;Select drive +command.select_drive keyboard 0x0 63+shift + +;Slow-forward +command.slow_forward keyboard 0x0 49 + +;Rewind +command.state_rewind joystick @GUID1@ @DEVICE_FUNC_KEYA_MODIFIER@ && joystick @GUID1@ @DEVICE_BTN_TL2@ + +;Decrease selected save state slot by 1 +command.state_slot_dec joystick @GUID1@ @DEVICE_FUNC_KEYB_MODIFIER@ && joystick @GUID1@ @DEVICE_BTN_DPAD_LEFT@ + +;Increase selected save state slot by 1 +command.state_slot_inc joystick @GUID1@ @DEVICE_FUNC_KEYB_MODIFIER@ && joystick @GUID1@ @DEVICE_BTN_DPAD_RIGHT@ + +;Take scaled(and filtered) screen snapshot +command.take_scaled_snapshot keyboard 0x0 66+shift + +;Take screen snapshot +command.take_snapshot joystick @GUID1@ @DEVICE_FUNC_KEYA_MODIFIER@ && joystick @GUID1@ @DEVICE_BTN_EAST@ + +;Toggle graphics layer 1 +command.tl1 keyboard 0x0 30+ctrl + +;Toggle graphics layer 2 +command.tl2 keyboard 0x0 31+ctrl + +;Toggle graphics layer 3 +command.tl3 keyboard 0x0 32+ctrl + +;Toggle graphics layer 4 +command.tl4 keyboard 0x0 33+ctrl + +;Toggle graphics layer 5 +command.tl5 keyboard 0x0 34+ctrl + +;Toggle graphics layer 6 +command.tl6 keyboard 0x0 35+ctrl + +;Toggle graphics layer 7 +command.tl7 keyboard 0x0 36+ctrl + +;Toggle graphics layer 8 +command.tl8 keyboard 0x0 37+ctrl + +;Toggle graphics layer 9 +command.tl9 keyboard 0x0 38+ctrl + +;Toggle debugger +command.toggle_debugger keyboard 0x0 7+alt + +;Toggle DIP switch view +command.toggle_dipview keyboard 0x0 63 + +;Toggle frames-per-second display +command.toggle_fps_view joystick @GUID1@ @DEVICE_FUNC_KEYA_MODIFIER@ && joystick @GUID1@ @DEVICE_BTN_WEST@ + +;Toggle fullscreen mode +command.toggle_fs keyboard 0x0 40+alt + +;Grab input +command.toggle_grab keyboard 0x0 101+ctrl+shift + +;Toggle help screen +command.toggle_help keyboard 0x0 58 + +;Toggle state rewind functionality +command.toggle_state_rewind keyboard 0x0 35+alt + +;Enable/Disable cheats +command.togglecheatactive keyboard 0x0 23+alt + +;Toggle cheat console +command.togglecheatview keyboard 0x0 6+alt + +;Toggle netplay console +command.togglenetview keyboard 0x0 23 + +;Automatically go into the debugger's step mode after a game is loaded. +debugger.autostepmode 0 + +;Enable (automatic) usage of this module. +demo.enable 1 + +;Force monophonic sound output. +demo.forcemono 0 + +;demo, Port 1, Controller: Rumble Control Strong +demo.input.port1.controller.rcstrong + +;demo, Port 1, Controller: Rumble Control Weak +demo.input.port1.controller.rcweak + +;demo, Port 1, Controller: Stick DOWN +demo.input.port1.controller.stick_down + +;demo, Port 1, Controller: Stick LEFT +demo.input.port1.controller.stick_left + +;demo, Port 1, Controller: Stick RIGHT +demo.input.port1.controller.stick_right + +;demo, Port 1, Controller: Stick UP +demo.input.port1.controller.stick_up + +;demo, Port 1, Controller: Select Test Mode +demo.input.port1.controller.stm + +;demo, Port 1, Controller: Switch Meow +demo.input.port1.controller.swt + +;Default position for switch "Switch Meow". +demo.input.port1.controller.swt.defpos waffles + +;demo, Port 1, Controller: Toggle Interlace Mode +demo.input.port1.controller.toggle_ilace + +;demo, Port 2, Controller: Rumble Control Strong +demo.input.port2.controller.rcstrong + +;demo, Port 2, Controller: Rumble Control Weak +demo.input.port2.controller.rcweak + +;demo, Port 2, Controller: Stick DOWN +demo.input.port2.controller.stick_down + +;demo, Port 2, Controller: Stick LEFT +demo.input.port2.controller.stick_left + +;demo, Port 2, Controller: Stick RIGHT +demo.input.port2.controller.stick_right + +;demo, Port 2, Controller: Stick UP +demo.input.port2.controller.stick_up + +;demo, Port 2, Controller: Select Test Mode +demo.input.port2.controller.stm + +;demo, Port 2, Controller: Switch Meow +demo.input.port2.controller.swt + +;Default position for switch "Switch Meow". +demo.input.port2.controller.swt.defpos waffles + +;demo, Port 2, Controller: Toggle Interlace Mode +demo.input.port2.controller.toggle_ilace + +;Multi-enum test. +demo.multi_enum + +;Sound quality. +demo.resamp_quality 3 + +;Sound output rate tolerance. +demo.resamp_rate_error 0.0000009 + +;Enable scanlines with specified opacity. +demo.scanlines 0 + +;Enable specified OpenGL shader. +demo.shader none + +;Force interlaced video to be treated as progressive. +demo.shader.goat.fprog 0 + +;Constant RGB horizontal divergence. +demo.shader.goat.hdiv 0.50 + +;Mask pattern. +demo.shader.goat.pat goatron + +;Enable scanlines effect. +demo.shader.goat.slen 1 + +;Transparency of otherwise-opaque mask areas. +demo.shader.goat.tp 0.50 + +;Constant RGB vertical divergence. +demo.shader.goat.vdiv 0.50 + +;Enable specified special video scaler. +demo.special none + +;Stretch to fill screen. +demo.stretch aspect + +;Enable video temporal blur(50/50 previous/current frame by default). +demo.tblur 0 + +;Accumulate color data rather than discarding it. +demo.tblur.accum 0 + +;Blur amount in accumulation mode, specified in percentage of accumulation buffer to mix with the current frame. +demo.tblur.accum.amount 50 + +;Enable (bi)linear interpolation. +demo.videoip 1 + +;Full-screen horizontal resolution. +demo.xres 0 + +;Scaling factor for the X axis in windowed mode. +demo.xscale 2.000000 + +;Scaling factor for the X axis in fullscreen mode. +demo.xscalefs 1.000000 + +;Full-screen vertical resolution. +demo.yres 0 + +;Scaling factor for the Y axis in windowed mode. +demo.yscale 2.000000 + +;Scaling factor for the Y axis in fullscreen mode. +demo.yscalefs 1.000000 + +;Silence sound output when fast-forwarding. +ffnosound 0 + +;Fast-forwarding speed multiplier. +ffspeed 15 + +;Treat the fast-forward button as a toggle. +fftoggle 1 + +;Format string for movie filename. +filesys.fname_movie %f.%M%p.mednafen.%x + +;Format string for save games filename. +filesys.fname_sav %f.mednafen.%M%x + +;Format string for save game backups filename. +filesys.fname_savbackup %f.%m%z%p.mednafen.%x + +;Format string for screen snapshot filenames. +filesys.fname_snap %f-%p.mednafen.%x + +;Format string for state filename. +filesys.fname_state %f.mednafen.%M%X + +;Enable old handling of .gz file extensions with respect to data file path construction. +filesys.old_gz_naming 0 + +;Path to directory for cheats. +filesys.path_cheat cheats + +;Path to directory for firmware. +filesys.path_firmware /storage/roms/bios/ + +;Path to directory for movies. +filesys.path_movie mcm + +;Path to directory for custom palettes. +filesys.path_palette palettes + +;Path to directory for per-game configuration override files. +filesys.path_pgconfig pgconfig + +;Path to directory for save games and nonvolatile memory. +filesys.path_sav /storage/roms/@PLATFORM@/ + +;Path to directory for backups of save games and nonvolatile memory. +filesys.path_savbackup /storage/roms/@PLATFORM@/ + +;Path to directory for screen snapshots. +filesys.path_snap /storage/roms/screenshots/ + +;Path to directory for save states. +filesys.path_state /storage/roms/savestates/@PLATFORM@/ + +;Save state file compression level. +filesys.state_comp_level 6 + +;Enable untrusted file-inclusion path security check. +filesys.untrusted_fip_check 1 + +;Automatically enable FPS display on startup. +fps.autoenable 0 + +;FPS display background color. +fps.bgcolor 0x80000000 + +;FPS display font. +fps.font 5x7 + +;FPS display position. +fps.position upper_left + +;FPS display scale factor. +fps.scale 0 + +;FPS display text color. +fps.textcolor 0xFFFFFFFF + +;Enable (automatic) usage of this module. +gb.enable 1 + +;Force monophonic sound output. +gb.forcemono 0 + +;gb, Built-In, Gamepad: A +gb.input.builtin.gamepad.a joystick @GUID1@ @DEVICE_BTN_EAST@ + +;gb, Built-In, Gamepad: B +gb.input.builtin.gamepad.b joystick @GUID1@ @DEVICE_BTN_SOUTH@ + +;gb, Built-In, Gamepad: DOWN ↓ +gb.input.builtin.gamepad.down joystick @GUID1@ @DEVICE_BTN_DPAD_DOWN@ + +;gb, Built-In, Gamepad: LEFT ← +gb.input.builtin.gamepad.left joystick @GUID1@ @DEVICE_BTN_DPAD_LEFT@ + +;gb, Built-In, Gamepad: Rapid A +gb.input.builtin.gamepad.rapid_a joystick @GUID1@ @DEVICE_BTN_NORTH@ + +;gb, Built-In, Gamepad: Rapid B +gb.input.builtin.gamepad.rapid_b joystick @GUID1@ @DEVICE_BTN_WEST@ + +;gb, Built-In, Gamepad: RIGHT → +gb.input.builtin.gamepad.right joystick @GUID1@ @DEVICE_BTN_DPAD_RIGHT@ + +;gb, Built-In, Gamepad: SELECT +gb.input.builtin.gamepad.select joystick @GUID1@ @DEVICE_BTN_SELECT@ + +;gb, Built-In, Gamepad: START +gb.input.builtin.gamepad.start joystick @GUID1@ @DEVICE_BTN_START@ + +;gb, Built-In, Gamepad: UP ↑ +gb.input.builtin.gamepad.up joystick @GUID1@ @DEVICE_BTN_DPAD_UP@ + +;gb, Tilt, Tilt: DOWN ↓ +gb.input.tilt.tilt.down + +;gb, Tilt, Tilt: LEFT ← +gb.input.tilt.tilt.left + +;gb, Tilt, Tilt: RIGHT → +gb.input.tilt.tilt.right + +;gb, Tilt, Tilt: UP ↑ +gb.input.tilt.tilt.up + +;Enable scanlines with specified opacity. +gb.scanlines 0 + +;Enable specified OpenGL shader. +gb.shader ipsharper + +;Force interlaced video to be treated as progressive. +gb.shader.goat.fprog 0 + +;Constant RGB horizontal divergence. +gb.shader.goat.hdiv 0.50 + +;Mask pattern. +gb.shader.goat.pat goatron + +;Enable scanlines effect. +gb.shader.goat.slen 1 + +;Transparency of otherwise-opaque mask areas. +gb.shader.goat.tp 0.50 + +;Constant RGB vertical divergence. +gb.shader.goat.vdiv 0.50 + +;Enable specified special video scaler. +gb.special none + +;Stretch to fill screen. +gb.stretch aspect + +;Emulated GB type. +gb.system_type dmg + +;Enable video temporal blur(50/50 previous/current frame by default). +gb.tblur 0 + +;Accumulate color data rather than discarding it. +gb.tblur.accum 0 + +;Blur amount in accumulation mode, specified in percentage of accumulation buffer to mix with the current frame. +gb.tblur.accum.amount 50 + +;Enable (bi)linear interpolation. +gb.videoip 0 + +;Full-screen horizontal resolution. +gb.xres 0 + +;Scaling factor for the X axis in windowed mode. +gb.xscale 6.000000 + +;Scaling factor for the X axis in fullscreen mode. +gb.xscalefs 1.000000 + +;Full-screen vertical resolution. +gb.yres 0 + +;Scaling factor for the Y axis in windowed mode. +gb.yscale 6.000000 + +;Scaling factor for the Y axis in fullscreen mode. +gb.yscalefs 1.000000 + +;Path to optional GBA BIOS ROM image. +gba.bios gba_bios.bin + +;Enable (automatic) usage of this module. +gba.enable 1 + +;Force monophonic sound output. +gba.forcemono 0 + +;gba, Built-In, Gamepad: A +gba.input.builtin.gamepad.a joystick @GUID1@ @DEVICE_BTN_EAST@ + +;gba, Built-In, Gamepad: B +gba.input.builtin.gamepad.b joystick @GUID1@ @DEVICE_BTN_SOUTH@ + +;gba, Built-In, Gamepad: DOWN ↓ +gba.input.builtin.gamepad.down joystick @GUID1@ @DEVICE_BTN_DPAD_DOWN@ + +;gba, Built-In, Gamepad: LEFT ← +gba.input.builtin.gamepad.left joystick @GUID1@ @DEVICE_BTN_DPAD_LEFT@ + +;gba, Built-In, Gamepad: Rapid A +gba.input.builtin.gamepad.rapid_a joystick @GUID1@ @DEVICE_BTN_NORTH@ + +;gba, Built-In, Gamepad: Rapid B +gba.input.builtin.gamepad.rapid_b joystick @GUID1@ @DEVICE_BTN_WEST@ + +;gba, Built-In, Gamepad: RIGHT → +gba.input.builtin.gamepad.right joystick @GUID1@ @DEVICE_BTN_DPAD_RIGHT@ + +;gba, Built-In, Gamepad: SELECT +gba.input.builtin.gamepad.select joystick @GUID1@ @DEVICE_BTN_SELECT@ + +;gba, Built-In, Gamepad: SHOULDER L +gba.input.builtin.gamepad.shoulder_l joystick @GUID1@ @DEVICE_BTN_TL@ + +;gba, Built-In, Gamepad: SHOULDER R +gba.input.builtin.gamepad.shoulder_r joystick @GUID1@ @DEVICE_BTN_TR@ + +;gba, Built-In, Gamepad: START +gba.input.builtin.gamepad.start joystick @GUID1@ @DEVICE_BTN_START@ + +;gba, Built-In, Gamepad: UP ↑ +gba.input.builtin.gamepad.up joystick @GUID1@ @DEVICE_BTN_DPAD_UP@ + +;Enable scanlines with specified opacity. +gba.scanlines 0 + +;Enable specified OpenGL shader. +gba.shader none + +;Force interlaced video to be treated as progressive. +gba.shader.goat.fprog 0 + +;Constant RGB horizontal divergence. +gba.shader.goat.hdiv 0.50 + +;Mask pattern. +gba.shader.goat.pat goatron + +;Enable scanlines effect. +gba.shader.goat.slen 1 + +;Transparency of otherwise-opaque mask areas. +gba.shader.goat.tp 0.50 + +;Constant RGB vertical divergence. +gba.shader.goat.vdiv 0.50 + +;Enable specified special video scaler. +gba.special none + +;Stretch to fill screen. +gba.stretch aspect_int + +;Enable video temporal blur(50/50 previous/current frame by default). +gba.tblur 1 + +;Accumulate color data rather than discarding it. +gba.tblur.accum 0 + +;Blur amount in accumulation mode, specified in percentage of accumulation buffer to mix with the current frame. +gba.tblur.accum.amount 50 + +;Enable (bi)linear interpolation. +gba.videoip 0 + +;Full-screen horizontal resolution. +gba.xres 0 + +;Scaling factor for the X axis in windowed mode. +gba.xscale 4.000000 + +;Scaling factor for the X axis in fullscreen mode. +gba.xscalefs 1.000000 + +;Full-screen vertical resolution. +gba.yres 0 + +;Scaling factor for the Y axis in windowed mode. +gba.yscale 4.000000 + +;Scaling factor for the Y axis in fullscreen mode. +gba.yscalefs 1.000000 + +;Enable (automatic) usage of this module. +gg.enable 1 + +;Force monophonic sound output. +gg.forcemono 0 + +;gg, Built-In, Gamepad: Button 1 +gg.input.builtin.gamepad.button1 joystick @GUID1@ @DEVICE_BTN_SOUTH@ + +;gg, Built-In, Gamepad: Button 2 +gg.input.builtin.gamepad.button2 joystick @GUID1@ @DEVICE_BTN_EAST@ + +;gg, Built-In, Gamepad: DOWN ↓ +gg.input.builtin.gamepad.down joystick @GUID1@ @DEVICE_BTN_DPAD_DOWN@ + +;gg, Built-In, Gamepad: LEFT ← +gg.input.builtin.gamepad.left joystick @GUID1@ @DEVICE_BTN_DPAD_LEFT@ + +;gg, Built-In, Gamepad: Rapid Button 1 +gg.input.builtin.gamepad.rapid_button1 joystick @GUID1@ @DEVICE_BTN_WEST@ + +;gg, Built-In, Gamepad: Rapid Button 2 +gg.input.builtin.gamepad.rapid_button2 joystick @GUID1@ @DEVICE_BTN_NORTH@ + +;gg, Built-In, Gamepad: RIGHT → +gg.input.builtin.gamepad.right joystick @GUID1@ @DEVICE_BTN_DPAD_RIGHT@ + +;gg, Built-In, Gamepad: Start +gg.input.builtin.gamepad.start joystick @GUID1@ @DEVICE_BTN_START@ + +;gg, Built-In, Gamepad: UP ↑ +gg.input.builtin.gamepad.up joystick @GUID1@ @DEVICE_BTN_DPAD_UP@ + +;Enable scanlines with specified opacity. +gg.scanlines 0 + +;Enable specified OpenGL shader. +gg.shader ipsharper + +;Force interlaced video to be treated as progressive. +gg.shader.goat.fprog 0 + +;Constant RGB horizontal divergence. +gg.shader.goat.hdiv 0.50 + +;Mask pattern. +gg.shader.goat.pat goatron + +;Enable scanlines effect. +gg.shader.goat.slen 1 + +;Transparency of otherwise-opaque mask areas. +gg.shader.goat.tp 0.50 + +;Constant RGB vertical divergence. +gg.shader.goat.vdiv 0.50 + +;Enable specified special video scaler. +gg.special none + +;Stretch to fill screen. +gg.stretch full + +;Enable video temporal blur(50/50 previous/current frame by default). +gg.tblur 0 + +;Accumulate color data rather than discarding it. +gg.tblur.accum 0 + +;Blur amount in accumulation mode, specified in percentage of accumulation buffer to mix with the current frame. +gg.tblur.accum.amount 50 + +;Enable (bi)linear interpolation. +gg.videoip 0 + +;Full-screen horizontal resolution. +gg.xres 0 + +;Scaling factor for the X axis in windowed mode. +gg.xscale 6.000000 + +;Scaling factor for the X axis in fullscreen mode. +gg.xscalefs 1.000000 + +;Full-screen vertical resolution. +gg.yres 0 + +;Scaling factor for the Y axis in windowed mode. +gg.yscale 6.000000 + +;Scaling factor for the Y axis in fullscreen mode. +gg.yscalefs 1.000000 + +;Auto-fire frequency. +input.autofirefreq 3 + +;Dangerous key action delay. +input.ckdelay 1500 + +;Analog axis binary press detection threshold. +input.joystick.axis_threshold 75 + +;Update physical joystick(s) internal state in Mednafen even when Mednafen lacks OS focus. +input.joystick.global_focus 1 + +;Enable (automatic) usage of this module. +lynx.enable 1 + +;Force monophonic sound output. +lynx.forcemono 0 + +;lynx, Built-In, Gamepad: A (outer) +lynx.input.builtin.gamepad.a joystick @GUID1@ @DEVICE_BTN_EAST@ + +;lynx, Built-In, Gamepad: B (inner) +lynx.input.builtin.gamepad.b joystick @GUID1@ @DEVICE_BTN_SOUTH@ + +;lynx, Built-In, Gamepad: DOWN ↓ +lynx.input.builtin.gamepad.down joystick @GUID1@ @DEVICE_BTN_DPAD_DOWN@ + +;lynx, Built-In, Gamepad: LEFT ← +lynx.input.builtin.gamepad.left joystick @GUID1@ @DEVICE_BTN_DPAD_LEFT@ + +;lynx, Built-In, Gamepad: Option 1 (upper) +lynx.input.builtin.gamepad.option_1 joystick @GUID1@ @DEVICE_BTN_TL@ + +;lynx, Built-In, Gamepad: Option 2 (lower) +lynx.input.builtin.gamepad.option_2 joystick @GUID1@ @DEVICE_BTN_TR@ + +;lynx, Built-In, Gamepad: PAUSE +lynx.input.builtin.gamepad.pause joystick @GUID1@ @DEVICE_BTN_START@ + +;lynx, Built-In, Gamepad: Rapid A (outer) +lynx.input.builtin.gamepad.rapid_a joystick @GUID1@ @DEVICE_BTN_NORTH@ + +;lynx, Built-In, Gamepad: Rapid B (inner) +lynx.input.builtin.gamepad.rapid_b joystick @GUID1@ @DEVICE_BTN_WEST@ + +;lynx, Built-In, Gamepad: Rapid Option 1 (upper) +lynx.input.builtin.gamepad.rapid_option_1 joystick @GUID1@ @DEVICE_BTN_TL2@ + +;lynx, Built-In, Gamepad: Rapid Option 2 (lower) +lynx.input.builtin.gamepad.rapid_option_2 joystick @GUID1@ @DEVICE_BTN_TR2@ + +;lynx, Built-In, Gamepad: RIGHT → +lynx.input.builtin.gamepad.right joystick @GUID1@ @DEVICE_BTN_DPAD_RIGHT@ + +;lynx, Built-In, Gamepad: UP ↑ +lynx.input.builtin.gamepad.up joystick @GUID1@ @DEVICE_BTN_DPAD_UP@ + +;Enable sound output lowpass filter. +lynx.lowpass 1 + +;Virtually rotate the D-pad when the screen is rotated. +lynx.rotateinput 1 + +;Enable scanlines with specified opacity. +lynx.scanlines 0 + +;Enable specified OpenGL shader. +lynx.shader ipsharper + +;Force interlaced video to be treated as progressive. +lynx.shader.goat.fprog 0 + +;Constant RGB horizontal divergence. +lynx.shader.goat.hdiv 0.50 + +;Mask pattern. +lynx.shader.goat.pat goatron + +;Enable scanlines effect. +lynx.shader.goat.slen 1 + +;Transparency of otherwise-opaque mask areas. +lynx.shader.goat.tp 0.50 + +;Constant RGB vertical divergence. +lynx.shader.goat.vdiv 0.50 + +;Enable specified special video scaler. +lynx.special none + +;Stretch to fill screen. +lynx.stretch aspect_int + +;Enable video temporal blur(50/50 previous/current frame by default). +lynx.tblur 0 + +;Accumulate color data rather than discarding it. +lynx.tblur.accum 0 + +;Blur amount in accumulation mode, specified in percentage of accumulation buffer to mix with the current frame. +lynx.tblur.accum.amount 50 + +;Enable (bi)linear interpolation. +lynx.videoip 0 + +;Full-screen horizontal resolution. +lynx.xres 0 + +;Scaling factor for the X axis in windowed mode. +lynx.xscale 6.000000 + +;Scaling factor for the X axis in fullscreen mode. +lynx.xscalefs 1.000000 + +;Full-screen vertical resolution. +lynx.yres 0 + +;Scaling factor for the Y axis in windowed mode. +lynx.yscale 6.000000 + +;Scaling factor for the Y axis in fullscreen mode. +lynx.yscalefs 1.000000 + +;Path to the CD BIOS +md.cdbios us_scd1_9210.bin + +;Correct the aspect ratio. +md.correct_aspect 1 + +;Disassembly font size. +md.debugger.disfontsize 5x7 + +;Character encoding for the debugger's memory editor. +md.debugger.memcharenc shift_jis + +;Enable (automatic) usage of this module. +md.enable 1 + +;Force monophonic sound output. +md.forcemono 0 + +;Automatically select appropriate input devices. +md.input.auto 1 + +;Emulated mouse sensitivity. +md.input.mouse_sensitivity 1.00 + +;Enable multitap(s). +md.input.multitap none + +;Input device for Virtual Port 1 +md.input.port1 gamepad + +;md, Virtual Port 1, 3-Button Gamepad: A +md.input.port1.gamepad.a joystick @GUID1@ @DEVICE_BTN_WEST@ + +;md, Virtual Port 1, 3-Button Gamepad: B +md.input.port1.gamepad.b joystick @GUID1@ @DEVICE_BTN_SOUTH@ + +;md, Virtual Port 1, 3-Button Gamepad: C +md.input.port1.gamepad.c joystick @GUID1@ @DEVICE_BTN_EAST@ + +;md, Virtual Port 1, 3-Button Gamepad: DOWN ↓ +md.input.port1.gamepad.down joystick @GUID1@ @DEVICE_BTN_DPAD_DOWN@ + +;md, Virtual Port 1, 3-Button Gamepad: LEFT ← +md.input.port1.gamepad.left joystick @GUID1@ @DEVICE_BTN_DPAD_LEFT@ + +;md, Virtual Port 1, 3-Button Gamepad: Rapid A +md.input.port1.gamepad.rapid_a joystick @GUID1@ @DEVICE_BTN_TL@ + +;md, Virtual Port 1, 3-Button Gamepad: Rapid B +md.input.port1.gamepad.rapid_b joystick @GUID1@ @DEVICE_BTN_NORTH@ + +;md, Virtual Port 1, 3-Button Gamepad: Rapid C +md.input.port1.gamepad.rapid_c joystick @GUID1@ @DEVICE_BTN_TR@ + +;md, Virtual Port 1, 3-Button Gamepad: RIGHT → +md.input.port1.gamepad.right joystick @GUID1@ @DEVICE_BTN_DPAD_RIGHT@ + +;md, Virtual Port 1, 3-Button Gamepad: Start +md.input.port1.gamepad.start joystick @GUID1@ @DEVICE_BTN_START@ + +;md, Virtual Port 1, 3-Button Gamepad: UP ↑ +md.input.port1.gamepad.up joystick @GUID1@ @DEVICE_BTN_DPAD_UP@ + +;md, Virtual Port 1, 2-Button Gamepad: A +md.input.port1.gamepad2.a + +;md, Virtual Port 1, 2-Button Gamepad: B +md.input.port1.gamepad2.b + +;md, Virtual Port 1, 2-Button Gamepad: DOWN ↓ +md.input.port1.gamepad2.down + +;md, Virtual Port 1, 2-Button Gamepad: LEFT ← +md.input.port1.gamepad2.left + +;md, Virtual Port 1, 2-Button Gamepad: Rapid A +md.input.port1.gamepad2.rapid_a + +;md, Virtual Port 1, 2-Button Gamepad: Rapid B +md.input.port1.gamepad2.rapid_b + +;md, Virtual Port 1, 2-Button Gamepad: RIGHT → +md.input.port1.gamepad2.right + +;md, Virtual Port 1, 2-Button Gamepad: Start +md.input.port1.gamepad2.start + +;md, Virtual Port 1, 2-Button Gamepad: UP ↑ +md.input.port1.gamepad2.up + +;md, Virtual Port 1, 6-Button Gamepad: A +md.input.port1.gamepad6.a joystick @GUID1@ @DEVICE_BTN_WEST@ + +;md, Virtual Port 1, 6-Button Gamepad: B +md.input.port1.gamepad6.b joystick @GUID1@ @DEVICE_BTN_SOUTH@ + +;md, Virtual Port 1, 6-Button Gamepad: C +md.input.port1.gamepad6.c joystick @GUID1@ @DEVICE_BTN_EAST@ + +;md, Virtual Port 1, 6-Button Gamepad: DOWN ↓ +md.input.port1.gamepad6.down joystick @GUID1@ @DEVICE_BTN_DPAD_DOWN@ + +;md, Virtual Port 1, 6-Button Gamepad: LEFT ← +md.input.port1.gamepad6.left joystick @GUID1@ @DEVICE_BTN_DPAD_LEFT@ + +;md, Virtual Port 1, 6-Button Gamepad: Mode +md.input.port1.gamepad6.mode joystick @GUID1@ @DEVICE_BTN_SELECT@ + +;md, Virtual Port 1, 6-Button Gamepad: Rapid A +md.input.port1.gamepad6.rapid_a + +;md, Virtual Port 1, 6-Button Gamepad: Rapid B +md.input.port1.gamepad6.rapid_b + +;md, Virtual Port 1, 6-Button Gamepad: Rapid C +md.input.port1.gamepad6.rapid_c + +;md, Virtual Port 1, 6-Button Gamepad: Rapid X +md.input.port1.gamepad6.rapid_x + +;md, Virtual Port 1, 6-Button Gamepad: Rapid Y +md.input.port1.gamepad6.rapid_y + +;md, Virtual Port 1, 6-Button Gamepad: Rapid Z +md.input.port1.gamepad6.rapid_z + +;md, Virtual Port 1, 6-Button Gamepad: RIGHT → +md.input.port1.gamepad6.right joystick @GUID1@ @DEVICE_BTN_DPAD_RIGHT@ + +;md, Virtual Port 1, 6-Button Gamepad: Start +md.input.port1.gamepad6.start joystick @GUID1@ @DEVICE_BTN_START@ + +;md, Virtual Port 1, 6-Button Gamepad: UP ↑ +md.input.port1.gamepad6.up joystick @GUID1@ @DEVICE_BTN_DPAD_UP@ + +;md, Virtual Port 1, 6-Button Gamepad: X +md.input.port1.gamepad6.x joystick @GUID1@ @DEVICE_BTN_TL@ + +;md, Virtual Port 1, 6-Button Gamepad: Y +md.input.port1.gamepad6.y joystick @GUID1@ @DEVICE_BTN_NORTH@ + +;md, Virtual Port 1, 6-Button Gamepad: Z +md.input.port1.gamepad6.z joystick @GUID1@ @DEVICE_BTN_TR@ + +;md, Virtual Port 1, Sega Mega Mouse: Left Button +md.input.port1.megamouse.left mouse 0x0 button_left + +;md, Virtual Port 1, Sega Mega Mouse: Middle Button +md.input.port1.megamouse.middle mouse 0x0 button_middle + +;md, Virtual Port 1, Sega Mega Mouse: Motion Down +md.input.port1.megamouse.motion_down mouse 0x0 rel_y+ + +;md, Virtual Port 1, Sega Mega Mouse: Motion Left +md.input.port1.megamouse.motion_left mouse 0x0 rel_x- + +;md, Virtual Port 1, Sega Mega Mouse: Motion Right +md.input.port1.megamouse.motion_right mouse 0x0 rel_x+ + +;md, Virtual Port 1, Sega Mega Mouse: Motion Up +md.input.port1.megamouse.motion_up mouse 0x0 rel_y- + +;md, Virtual Port 1, Sega Mega Mouse: Right Button +md.input.port1.megamouse.right mouse 0x0 button_right + +;md, Virtual Port 1, Sega Mega Mouse: Start Button +md.input.port1.megamouse.start keyboard 0x0 40 + +;Input device for Virtual Port 2 +md.input.port2 gamepad + +;md, Virtual Port 2, 3-Button Gamepad: A +md.input.port2.gamepad.a + +;md, Virtual Port 2, 3-Button Gamepad: B +md.input.port2.gamepad.b + +;md, Virtual Port 2, 3-Button Gamepad: C +md.input.port2.gamepad.c + +;md, Virtual Port 2, 3-Button Gamepad: DOWN ↓ +md.input.port2.gamepad.down + +;md, Virtual Port 2, 3-Button Gamepad: LEFT ← +md.input.port2.gamepad.left + +;md, Virtual Port 2, 3-Button Gamepad: Rapid A +md.input.port2.gamepad.rapid_a + +;md, Virtual Port 2, 3-Button Gamepad: Rapid B +md.input.port2.gamepad.rapid_b + +;md, Virtual Port 2, 3-Button Gamepad: Rapid C +md.input.port2.gamepad.rapid_c + +;md, Virtual Port 2, 3-Button Gamepad: RIGHT → +md.input.port2.gamepad.right + +;md, Virtual Port 2, 3-Button Gamepad: Start +md.input.port2.gamepad.start + +;md, Virtual Port 2, 3-Button Gamepad: UP ↑ +md.input.port2.gamepad.up + +;md, Virtual Port 2, 2-Button Gamepad: A +md.input.port2.gamepad2.a + +;md, Virtual Port 2, 2-Button Gamepad: B +md.input.port2.gamepad2.b + +;md, Virtual Port 2, 2-Button Gamepad: DOWN ↓ +md.input.port2.gamepad2.down + +;md, Virtual Port 2, 2-Button Gamepad: LEFT ← +md.input.port2.gamepad2.left + +;md, Virtual Port 2, 2-Button Gamepad: Rapid A +md.input.port2.gamepad2.rapid_a + +;md, Virtual Port 2, 2-Button Gamepad: Rapid B +md.input.port2.gamepad2.rapid_b + +;md, Virtual Port 2, 2-Button Gamepad: RIGHT → +md.input.port2.gamepad2.right + +;md, Virtual Port 2, 2-Button Gamepad: Start +md.input.port2.gamepad2.start + +;md, Virtual Port 2, 2-Button Gamepad: UP ↑ +md.input.port2.gamepad2.up + +;md, Virtual Port 2, 6-Button Gamepad: A +md.input.port2.gamepad6.a + +;md, Virtual Port 2, 6-Button Gamepad: B +md.input.port2.gamepad6.b + +;md, Virtual Port 2, 6-Button Gamepad: C +md.input.port2.gamepad6.c + +;md, Virtual Port 2, 6-Button Gamepad: DOWN ↓ +md.input.port2.gamepad6.down + +;md, Virtual Port 2, 6-Button Gamepad: LEFT ← +md.input.port2.gamepad6.left + +;md, Virtual Port 2, 6-Button Gamepad: Mode +md.input.port2.gamepad6.mode + +;md, Virtual Port 2, 6-Button Gamepad: Rapid A +md.input.port2.gamepad6.rapid_a + +;md, Virtual Port 2, 6-Button Gamepad: Rapid B +md.input.port2.gamepad6.rapid_b + +;md, Virtual Port 2, 6-Button Gamepad: Rapid C +md.input.port2.gamepad6.rapid_c + +;md, Virtual Port 2, 6-Button Gamepad: Rapid X +md.input.port2.gamepad6.rapid_x + +;md, Virtual Port 2, 6-Button Gamepad: Rapid Y +md.input.port2.gamepad6.rapid_y + +;md, Virtual Port 2, 6-Button Gamepad: Rapid Z +md.input.port2.gamepad6.rapid_z + +;md, Virtual Port 2, 6-Button Gamepad: RIGHT → +md.input.port2.gamepad6.right + +;md, Virtual Port 2, 6-Button Gamepad: Start +md.input.port2.gamepad6.start + +;md, Virtual Port 2, 6-Button Gamepad: UP ↑ +md.input.port2.gamepad6.up + +;md, Virtual Port 2, 6-Button Gamepad: X +md.input.port2.gamepad6.x + +;md, Virtual Port 2, 6-Button Gamepad: Y +md.input.port2.gamepad6.y + +;md, Virtual Port 2, 6-Button Gamepad: Z +md.input.port2.gamepad6.z + +;md, Virtual Port 2, Sega Mega Mouse: Left Button +md.input.port2.megamouse.left mouse 0x0 button_left + +;md, Virtual Port 2, Sega Mega Mouse: Middle Button +md.input.port2.megamouse.middle mouse 0x0 button_middle + +;md, Virtual Port 2, Sega Mega Mouse: Motion Down +md.input.port2.megamouse.motion_down mouse 0x0 rel_y+ + +;md, Virtual Port 2, Sega Mega Mouse: Motion Left +md.input.port2.megamouse.motion_left mouse 0x0 rel_x- + +;md, Virtual Port 2, Sega Mega Mouse: Motion Right +md.input.port2.megamouse.motion_right mouse 0x0 rel_x+ + +;md, Virtual Port 2, Sega Mega Mouse: Motion Up +md.input.port2.megamouse.motion_up mouse 0x0 rel_y- + +;md, Virtual Port 2, Sega Mega Mouse: Right Button +md.input.port2.megamouse.right mouse 0x0 button_right + +;md, Virtual Port 2, Sega Mega Mouse: Start Button +md.input.port2.megamouse.start keyboard 0x0 40 + +;Input device for Virtual Port 3 +md.input.port3 gamepad + +;md, Virtual Port 3, 3-Button Gamepad: A +md.input.port3.gamepad.a + +;md, Virtual Port 3, 3-Button Gamepad: B +md.input.port3.gamepad.b + +;md, Virtual Port 3, 3-Button Gamepad: C +md.input.port3.gamepad.c + +;md, Virtual Port 3, 3-Button Gamepad: DOWN ↓ +md.input.port3.gamepad.down + +;md, Virtual Port 3, 3-Button Gamepad: LEFT ← +md.input.port3.gamepad.left + +;md, Virtual Port 3, 3-Button Gamepad: Rapid A +md.input.port3.gamepad.rapid_a + +;md, Virtual Port 3, 3-Button Gamepad: Rapid B +md.input.port3.gamepad.rapid_b + +;md, Virtual Port 3, 3-Button Gamepad: Rapid C +md.input.port3.gamepad.rapid_c + +;md, Virtual Port 3, 3-Button Gamepad: RIGHT → +md.input.port3.gamepad.right + +;md, Virtual Port 3, 3-Button Gamepad: Start +md.input.port3.gamepad.start + +;md, Virtual Port 3, 3-Button Gamepad: UP ↑ +md.input.port3.gamepad.up + +;md, Virtual Port 3, 2-Button Gamepad: A +md.input.port3.gamepad2.a + +;md, Virtual Port 3, 2-Button Gamepad: B +md.input.port3.gamepad2.b + +;md, Virtual Port 3, 2-Button Gamepad: DOWN ↓ +md.input.port3.gamepad2.down + +;md, Virtual Port 3, 2-Button Gamepad: LEFT ← +md.input.port3.gamepad2.left + +;md, Virtual Port 3, 2-Button Gamepad: Rapid A +md.input.port3.gamepad2.rapid_a + +;md, Virtual Port 3, 2-Button Gamepad: Rapid B +md.input.port3.gamepad2.rapid_b + +;md, Virtual Port 3, 2-Button Gamepad: RIGHT → +md.input.port3.gamepad2.right + +;md, Virtual Port 3, 2-Button Gamepad: Start +md.input.port3.gamepad2.start + +;md, Virtual Port 3, 2-Button Gamepad: UP ↑ +md.input.port3.gamepad2.up + +;md, Virtual Port 3, 6-Button Gamepad: A +md.input.port3.gamepad6.a + +;md, Virtual Port 3, 6-Button Gamepad: B +md.input.port3.gamepad6.b + +;md, Virtual Port 3, 6-Button Gamepad: C +md.input.port3.gamepad6.c + +;md, Virtual Port 3, 6-Button Gamepad: DOWN ↓ +md.input.port3.gamepad6.down + +;md, Virtual Port 3, 6-Button Gamepad: LEFT ← +md.input.port3.gamepad6.left + +;md, Virtual Port 3, 6-Button Gamepad: Mode +md.input.port3.gamepad6.mode + +;md, Virtual Port 3, 6-Button Gamepad: Rapid A +md.input.port3.gamepad6.rapid_a + +;md, Virtual Port 3, 6-Button Gamepad: Rapid B +md.input.port3.gamepad6.rapid_b + +;md, Virtual Port 3, 6-Button Gamepad: Rapid C +md.input.port3.gamepad6.rapid_c + +;md, Virtual Port 3, 6-Button Gamepad: Rapid X +md.input.port3.gamepad6.rapid_x + +;md, Virtual Port 3, 6-Button Gamepad: Rapid Y +md.input.port3.gamepad6.rapid_y + +;md, Virtual Port 3, 6-Button Gamepad: Rapid Z +md.input.port3.gamepad6.rapid_z + +;md, Virtual Port 3, 6-Button Gamepad: RIGHT → +md.input.port3.gamepad6.right + +;md, Virtual Port 3, 6-Button Gamepad: Start +md.input.port3.gamepad6.start + +;md, Virtual Port 3, 6-Button Gamepad: UP ↑ +md.input.port3.gamepad6.up + +;md, Virtual Port 3, 6-Button Gamepad: X +md.input.port3.gamepad6.x + +;md, Virtual Port 3, 6-Button Gamepad: Y +md.input.port3.gamepad6.y + +;md, Virtual Port 3, 6-Button Gamepad: Z +md.input.port3.gamepad6.z + +;md, Virtual Port 3, Sega Mega Mouse: Left Button +md.input.port3.megamouse.left mouse 0x0 button_left + +;md, Virtual Port 3, Sega Mega Mouse: Middle Button +md.input.port3.megamouse.middle mouse 0x0 button_middle + +;md, Virtual Port 3, Sega Mega Mouse: Motion Down +md.input.port3.megamouse.motion_down mouse 0x0 rel_y+ + +;md, Virtual Port 3, Sega Mega Mouse: Motion Left +md.input.port3.megamouse.motion_left mouse 0x0 rel_x- + +;md, Virtual Port 3, Sega Mega Mouse: Motion Right +md.input.port3.megamouse.motion_right mouse 0x0 rel_x+ + +;md, Virtual Port 3, Sega Mega Mouse: Motion Up +md.input.port3.megamouse.motion_up mouse 0x0 rel_y- + +;md, Virtual Port 3, Sega Mega Mouse: Right Button +md.input.port3.megamouse.right mouse 0x0 button_right + +;md, Virtual Port 3, Sega Mega Mouse: Start Button +md.input.port3.megamouse.start keyboard 0x0 40 + +;Input device for Virtual Port 4 +md.input.port4 gamepad + +;md, Virtual Port 4, 3-Button Gamepad: A +md.input.port4.gamepad.a + +;md, Virtual Port 4, 3-Button Gamepad: B +md.input.port4.gamepad.b + +;md, Virtual Port 4, 3-Button Gamepad: C +md.input.port4.gamepad.c + +;md, Virtual Port 4, 3-Button Gamepad: DOWN ↓ +md.input.port4.gamepad.down + +;md, Virtual Port 4, 3-Button Gamepad: LEFT ← +md.input.port4.gamepad.left + +;md, Virtual Port 4, 3-Button Gamepad: Rapid A +md.input.port4.gamepad.rapid_a + +;md, Virtual Port 4, 3-Button Gamepad: Rapid B +md.input.port4.gamepad.rapid_b + +;md, Virtual Port 4, 3-Button Gamepad: Rapid C +md.input.port4.gamepad.rapid_c + +;md, Virtual Port 4, 3-Button Gamepad: RIGHT → +md.input.port4.gamepad.right + +;md, Virtual Port 4, 3-Button Gamepad: Start +md.input.port4.gamepad.start + +;md, Virtual Port 4, 3-Button Gamepad: UP ↑ +md.input.port4.gamepad.up + +;md, Virtual Port 4, 2-Button Gamepad: A +md.input.port4.gamepad2.a + +;md, Virtual Port 4, 2-Button Gamepad: B +md.input.port4.gamepad2.b + +;md, Virtual Port 4, 2-Button Gamepad: DOWN ↓ +md.input.port4.gamepad2.down + +;md, Virtual Port 4, 2-Button Gamepad: LEFT ← +md.input.port4.gamepad2.left + +;md, Virtual Port 4, 2-Button Gamepad: Rapid A +md.input.port4.gamepad2.rapid_a + +;md, Virtual Port 4, 2-Button Gamepad: Rapid B +md.input.port4.gamepad2.rapid_b + +;md, Virtual Port 4, 2-Button Gamepad: RIGHT → +md.input.port4.gamepad2.right + +;md, Virtual Port 4, 2-Button Gamepad: Start +md.input.port4.gamepad2.start + +;md, Virtual Port 4, 2-Button Gamepad: UP ↑ +md.input.port4.gamepad2.up + +;md, Virtual Port 4, 6-Button Gamepad: A +md.input.port4.gamepad6.a + +;md, Virtual Port 4, 6-Button Gamepad: B +md.input.port4.gamepad6.b + +;md, Virtual Port 4, 6-Button Gamepad: C +md.input.port4.gamepad6.c + +;md, Virtual Port 4, 6-Button Gamepad: DOWN ↓ +md.input.port4.gamepad6.down + +;md, Virtual Port 4, 6-Button Gamepad: LEFT ← +md.input.port4.gamepad6.left + +;md, Virtual Port 4, 6-Button Gamepad: Mode +md.input.port4.gamepad6.mode + +;md, Virtual Port 4, 6-Button Gamepad: Rapid A +md.input.port4.gamepad6.rapid_a + +;md, Virtual Port 4, 6-Button Gamepad: Rapid B +md.input.port4.gamepad6.rapid_b + +;md, Virtual Port 4, 6-Button Gamepad: Rapid C +md.input.port4.gamepad6.rapid_c + +;md, Virtual Port 4, 6-Button Gamepad: Rapid X +md.input.port4.gamepad6.rapid_x + +;md, Virtual Port 4, 6-Button Gamepad: Rapid Y +md.input.port4.gamepad6.rapid_y + +;md, Virtual Port 4, 6-Button Gamepad: Rapid Z +md.input.port4.gamepad6.rapid_z + +;md, Virtual Port 4, 6-Button Gamepad: RIGHT → +md.input.port4.gamepad6.right + +;md, Virtual Port 4, 6-Button Gamepad: Start +md.input.port4.gamepad6.start + +;md, Virtual Port 4, 6-Button Gamepad: UP ↑ +md.input.port4.gamepad6.up + +;md, Virtual Port 4, 6-Button Gamepad: X +md.input.port4.gamepad6.x + +;md, Virtual Port 4, 6-Button Gamepad: Y +md.input.port4.gamepad6.y + +;md, Virtual Port 4, 6-Button Gamepad: Z +md.input.port4.gamepad6.z + +;md, Virtual Port 4, Sega Mega Mouse: Left Button +md.input.port4.megamouse.left mouse 0x0 button_left + +;md, Virtual Port 4, Sega Mega Mouse: Middle Button +md.input.port4.megamouse.middle mouse 0x0 button_middle + +;md, Virtual Port 4, Sega Mega Mouse: Motion Down +md.input.port4.megamouse.motion_down mouse 0x0 rel_y+ + +;md, Virtual Port 4, Sega Mega Mouse: Motion Left +md.input.port4.megamouse.motion_left mouse 0x0 rel_x- + +;md, Virtual Port 4, Sega Mega Mouse: Motion Right +md.input.port4.megamouse.motion_right mouse 0x0 rel_x+ + +;md, Virtual Port 4, Sega Mega Mouse: Motion Up +md.input.port4.megamouse.motion_up mouse 0x0 rel_y- + +;md, Virtual Port 4, Sega Mega Mouse: Right Button +md.input.port4.megamouse.right mouse 0x0 button_right + +;md, Virtual Port 4, Sega Mega Mouse: Start Button +md.input.port4.megamouse.start keyboard 0x0 40 + +;Input device for Virtual Port 5 +md.input.port5 gamepad + +;md, Virtual Port 5, 3-Button Gamepad: A +md.input.port5.gamepad.a + +;md, Virtual Port 5, 3-Button Gamepad: B +md.input.port5.gamepad.b + +;md, Virtual Port 5, 3-Button Gamepad: C +md.input.port5.gamepad.c + +;md, Virtual Port 5, 3-Button Gamepad: DOWN ↓ +md.input.port5.gamepad.down + +;md, Virtual Port 5, 3-Button Gamepad: LEFT ← +md.input.port5.gamepad.left + +;md, Virtual Port 5, 3-Button Gamepad: Rapid A +md.input.port5.gamepad.rapid_a + +;md, Virtual Port 5, 3-Button Gamepad: Rapid B +md.input.port5.gamepad.rapid_b + +;md, Virtual Port 5, 3-Button Gamepad: Rapid C +md.input.port5.gamepad.rapid_c + +;md, Virtual Port 5, 3-Button Gamepad: RIGHT → +md.input.port5.gamepad.right + +;md, Virtual Port 5, 3-Button Gamepad: Start +md.input.port5.gamepad.start + +;md, Virtual Port 5, 3-Button Gamepad: UP ↑ +md.input.port5.gamepad.up + +;md, Virtual Port 5, 2-Button Gamepad: A +md.input.port5.gamepad2.a + +;md, Virtual Port 5, 2-Button Gamepad: B +md.input.port5.gamepad2.b + +;md, Virtual Port 5, 2-Button Gamepad: DOWN ↓ +md.input.port5.gamepad2.down + +;md, Virtual Port 5, 2-Button Gamepad: LEFT ← +md.input.port5.gamepad2.left + +;md, Virtual Port 5, 2-Button Gamepad: Rapid A +md.input.port5.gamepad2.rapid_a + +;md, Virtual Port 5, 2-Button Gamepad: Rapid B +md.input.port5.gamepad2.rapid_b + +;md, Virtual Port 5, 2-Button Gamepad: RIGHT → +md.input.port5.gamepad2.right + +;md, Virtual Port 5, 2-Button Gamepad: Start +md.input.port5.gamepad2.start + +;md, Virtual Port 5, 2-Button Gamepad: UP ↑ +md.input.port5.gamepad2.up + +;md, Virtual Port 5, 6-Button Gamepad: A +md.input.port5.gamepad6.a + +;md, Virtual Port 5, 6-Button Gamepad: B +md.input.port5.gamepad6.b + +;md, Virtual Port 5, 6-Button Gamepad: C +md.input.port5.gamepad6.c + +;md, Virtual Port 5, 6-Button Gamepad: DOWN ↓ +md.input.port5.gamepad6.down + +;md, Virtual Port 5, 6-Button Gamepad: LEFT ← +md.input.port5.gamepad6.left + +;md, Virtual Port 5, 6-Button Gamepad: Mode +md.input.port5.gamepad6.mode + +;md, Virtual Port 5, 6-Button Gamepad: Rapid A +md.input.port5.gamepad6.rapid_a + +;md, Virtual Port 5, 6-Button Gamepad: Rapid B +md.input.port5.gamepad6.rapid_b + +;md, Virtual Port 5, 6-Button Gamepad: Rapid C +md.input.port5.gamepad6.rapid_c + +;md, Virtual Port 5, 6-Button Gamepad: Rapid X +md.input.port5.gamepad6.rapid_x + +;md, Virtual Port 5, 6-Button Gamepad: Rapid Y +md.input.port5.gamepad6.rapid_y + +;md, Virtual Port 5, 6-Button Gamepad: Rapid Z +md.input.port5.gamepad6.rapid_z + +;md, Virtual Port 5, 6-Button Gamepad: RIGHT → +md.input.port5.gamepad6.right + +;md, Virtual Port 5, 6-Button Gamepad: Start +md.input.port5.gamepad6.start + +;md, Virtual Port 5, 6-Button Gamepad: UP ↑ +md.input.port5.gamepad6.up + +;md, Virtual Port 5, 6-Button Gamepad: X +md.input.port5.gamepad6.x + +;md, Virtual Port 5, 6-Button Gamepad: Y +md.input.port5.gamepad6.y + +;md, Virtual Port 5, 6-Button Gamepad: Z +md.input.port5.gamepad6.z + +;md, Virtual Port 5, Sega Mega Mouse: Left Button +md.input.port5.megamouse.left mouse 0x0 button_left + +;md, Virtual Port 5, Sega Mega Mouse: Middle Button +md.input.port5.megamouse.middle mouse 0x0 button_middle + +;md, Virtual Port 5, Sega Mega Mouse: Motion Down +md.input.port5.megamouse.motion_down mouse 0x0 rel_y+ + +;md, Virtual Port 5, Sega Mega Mouse: Motion Left +md.input.port5.megamouse.motion_left mouse 0x0 rel_x- + +;md, Virtual Port 5, Sega Mega Mouse: Motion Right +md.input.port5.megamouse.motion_right mouse 0x0 rel_x+ + +;md, Virtual Port 5, Sega Mega Mouse: Motion Up +md.input.port5.megamouse.motion_up mouse 0x0 rel_y- + +;md, Virtual Port 5, Sega Mega Mouse: Right Button +md.input.port5.megamouse.right mouse 0x0 button_right + +;md, Virtual Port 5, Sega Mega Mouse: Start Button +md.input.port5.megamouse.start keyboard 0x0 40 + +;Input device for Virtual Port 6 +md.input.port6 gamepad + +;md, Virtual Port 6, 3-Button Gamepad: A +md.input.port6.gamepad.a + +;md, Virtual Port 6, 3-Button Gamepad: B +md.input.port6.gamepad.b + +;md, Virtual Port 6, 3-Button Gamepad: C +md.input.port6.gamepad.c + +;md, Virtual Port 6, 3-Button Gamepad: DOWN ↓ +md.input.port6.gamepad.down + +;md, Virtual Port 6, 3-Button Gamepad: LEFT ← +md.input.port6.gamepad.left + +;md, Virtual Port 6, 3-Button Gamepad: Rapid A +md.input.port6.gamepad.rapid_a + +;md, Virtual Port 6, 3-Button Gamepad: Rapid B +md.input.port6.gamepad.rapid_b + +;md, Virtual Port 6, 3-Button Gamepad: Rapid C +md.input.port6.gamepad.rapid_c + +;md, Virtual Port 6, 3-Button Gamepad: RIGHT → +md.input.port6.gamepad.right + +;md, Virtual Port 6, 3-Button Gamepad: Start +md.input.port6.gamepad.start + +;md, Virtual Port 6, 3-Button Gamepad: UP ↑ +md.input.port6.gamepad.up + +;md, Virtual Port 6, 2-Button Gamepad: A +md.input.port6.gamepad2.a + +;md, Virtual Port 6, 2-Button Gamepad: B +md.input.port6.gamepad2.b + +;md, Virtual Port 6, 2-Button Gamepad: DOWN ↓ +md.input.port6.gamepad2.down + +;md, Virtual Port 6, 2-Button Gamepad: LEFT ← +md.input.port6.gamepad2.left + +;md, Virtual Port 6, 2-Button Gamepad: Rapid A +md.input.port6.gamepad2.rapid_a + +;md, Virtual Port 6, 2-Button Gamepad: Rapid B +md.input.port6.gamepad2.rapid_b + +;md, Virtual Port 6, 2-Button Gamepad: RIGHT → +md.input.port6.gamepad2.right + +;md, Virtual Port 6, 2-Button Gamepad: Start +md.input.port6.gamepad2.start + +;md, Virtual Port 6, 2-Button Gamepad: UP ↑ +md.input.port6.gamepad2.up + +;md, Virtual Port 6, 6-Button Gamepad: A +md.input.port6.gamepad6.a + +;md, Virtual Port 6, 6-Button Gamepad: B +md.input.port6.gamepad6.b + +;md, Virtual Port 6, 6-Button Gamepad: C +md.input.port6.gamepad6.c + +;md, Virtual Port 6, 6-Button Gamepad: DOWN ↓ +md.input.port6.gamepad6.down + +;md, Virtual Port 6, 6-Button Gamepad: LEFT ← +md.input.port6.gamepad6.left + +;md, Virtual Port 6, 6-Button Gamepad: Mode +md.input.port6.gamepad6.mode + +;md, Virtual Port 6, 6-Button Gamepad: Rapid A +md.input.port6.gamepad6.rapid_a + +;md, Virtual Port 6, 6-Button Gamepad: Rapid B +md.input.port6.gamepad6.rapid_b + +;md, Virtual Port 6, 6-Button Gamepad: Rapid C +md.input.port6.gamepad6.rapid_c + +;md, Virtual Port 6, 6-Button Gamepad: Rapid X +md.input.port6.gamepad6.rapid_x + +;md, Virtual Port 6, 6-Button Gamepad: Rapid Y +md.input.port6.gamepad6.rapid_y + +;md, Virtual Port 6, 6-Button Gamepad: Rapid Z +md.input.port6.gamepad6.rapid_z + +;md, Virtual Port 6, 6-Button Gamepad: RIGHT → +md.input.port6.gamepad6.right + +;md, Virtual Port 6, 6-Button Gamepad: Start +md.input.port6.gamepad6.start + +;md, Virtual Port 6, 6-Button Gamepad: UP ↑ +md.input.port6.gamepad6.up + +;md, Virtual Port 6, 6-Button Gamepad: X +md.input.port6.gamepad6.x + +;md, Virtual Port 6, 6-Button Gamepad: Y +md.input.port6.gamepad6.y + +;md, Virtual Port 6, 6-Button Gamepad: Z +md.input.port6.gamepad6.z + +;md, Virtual Port 6, Sega Mega Mouse: Left Button +md.input.port6.megamouse.left mouse 0x0 button_left + +;md, Virtual Port 6, Sega Mega Mouse: Middle Button +md.input.port6.megamouse.middle mouse 0x0 button_middle + +;md, Virtual Port 6, Sega Mega Mouse: Motion Down +md.input.port6.megamouse.motion_down mouse 0x0 rel_y+ + +;md, Virtual Port 6, Sega Mega Mouse: Motion Left +md.input.port6.megamouse.motion_left mouse 0x0 rel_x- + +;md, Virtual Port 6, Sega Mega Mouse: Motion Right +md.input.port6.megamouse.motion_right mouse 0x0 rel_x+ + +;md, Virtual Port 6, Sega Mega Mouse: Motion Up +md.input.port6.megamouse.motion_up mouse 0x0 rel_y- + +;md, Virtual Port 6, Sega Mega Mouse: Right Button +md.input.port6.megamouse.right mouse 0x0 button_right + +;md, Virtual Port 6, Sega Mega Mouse: Start Button +md.input.port6.megamouse.start keyboard 0x0 40 + +;Input device for Virtual Port 7 +md.input.port7 gamepad + +;md, Virtual Port 7, 3-Button Gamepad: A +md.input.port7.gamepad.a + +;md, Virtual Port 7, 3-Button Gamepad: B +md.input.port7.gamepad.b + +;md, Virtual Port 7, 3-Button Gamepad: C +md.input.port7.gamepad.c + +;md, Virtual Port 7, 3-Button Gamepad: DOWN ↓ +md.input.port7.gamepad.down + +;md, Virtual Port 7, 3-Button Gamepad: LEFT ← +md.input.port7.gamepad.left + +;md, Virtual Port 7, 3-Button Gamepad: Rapid A +md.input.port7.gamepad.rapid_a + +;md, Virtual Port 7, 3-Button Gamepad: Rapid B +md.input.port7.gamepad.rapid_b + +;md, Virtual Port 7, 3-Button Gamepad: Rapid C +md.input.port7.gamepad.rapid_c + +;md, Virtual Port 7, 3-Button Gamepad: RIGHT → +md.input.port7.gamepad.right + +;md, Virtual Port 7, 3-Button Gamepad: Start +md.input.port7.gamepad.start + +;md, Virtual Port 7, 3-Button Gamepad: UP ↑ +md.input.port7.gamepad.up + +;md, Virtual Port 7, 2-Button Gamepad: A +md.input.port7.gamepad2.a + +;md, Virtual Port 7, 2-Button Gamepad: B +md.input.port7.gamepad2.b + +;md, Virtual Port 7, 2-Button Gamepad: DOWN ↓ +md.input.port7.gamepad2.down + +;md, Virtual Port 7, 2-Button Gamepad: LEFT ← +md.input.port7.gamepad2.left + +;md, Virtual Port 7, 2-Button Gamepad: Rapid A +md.input.port7.gamepad2.rapid_a + +;md, Virtual Port 7, 2-Button Gamepad: Rapid B +md.input.port7.gamepad2.rapid_b + +;md, Virtual Port 7, 2-Button Gamepad: RIGHT → +md.input.port7.gamepad2.right + +;md, Virtual Port 7, 2-Button Gamepad: Start +md.input.port7.gamepad2.start + +;md, Virtual Port 7, 2-Button Gamepad: UP ↑ +md.input.port7.gamepad2.up + +;md, Virtual Port 7, 6-Button Gamepad: A +md.input.port7.gamepad6.a + +;md, Virtual Port 7, 6-Button Gamepad: B +md.input.port7.gamepad6.b + +;md, Virtual Port 7, 6-Button Gamepad: C +md.input.port7.gamepad6.c + +;md, Virtual Port 7, 6-Button Gamepad: DOWN ↓ +md.input.port7.gamepad6.down + +;md, Virtual Port 7, 6-Button Gamepad: LEFT ← +md.input.port7.gamepad6.left + +;md, Virtual Port 7, 6-Button Gamepad: Mode +md.input.port7.gamepad6.mode + +;md, Virtual Port 7, 6-Button Gamepad: Rapid A +md.input.port7.gamepad6.rapid_a + +;md, Virtual Port 7, 6-Button Gamepad: Rapid B +md.input.port7.gamepad6.rapid_b + +;md, Virtual Port 7, 6-Button Gamepad: Rapid C +md.input.port7.gamepad6.rapid_c + +;md, Virtual Port 7, 6-Button Gamepad: Rapid X +md.input.port7.gamepad6.rapid_x + +;md, Virtual Port 7, 6-Button Gamepad: Rapid Y +md.input.port7.gamepad6.rapid_y + +;md, Virtual Port 7, 6-Button Gamepad: Rapid Z +md.input.port7.gamepad6.rapid_z + +;md, Virtual Port 7, 6-Button Gamepad: RIGHT → +md.input.port7.gamepad6.right + +;md, Virtual Port 7, 6-Button Gamepad: Start +md.input.port7.gamepad6.start + +;md, Virtual Port 7, 6-Button Gamepad: UP ↑ +md.input.port7.gamepad6.up + +;md, Virtual Port 7, 6-Button Gamepad: X +md.input.port7.gamepad6.x + +;md, Virtual Port 7, 6-Button Gamepad: Y +md.input.port7.gamepad6.y + +;md, Virtual Port 7, 6-Button Gamepad: Z +md.input.port7.gamepad6.z + +;md, Virtual Port 7, Sega Mega Mouse: Left Button +md.input.port7.megamouse.left mouse 0x0 button_left + +;md, Virtual Port 7, Sega Mega Mouse: Middle Button +md.input.port7.megamouse.middle mouse 0x0 button_middle + +;md, Virtual Port 7, Sega Mega Mouse: Motion Down +md.input.port7.megamouse.motion_down mouse 0x0 rel_y+ + +;md, Virtual Port 7, Sega Mega Mouse: Motion Left +md.input.port7.megamouse.motion_left mouse 0x0 rel_x- + +;md, Virtual Port 7, Sega Mega Mouse: Motion Right +md.input.port7.megamouse.motion_right mouse 0x0 rel_x+ + +;md, Virtual Port 7, Sega Mega Mouse: Motion Up +md.input.port7.megamouse.motion_up mouse 0x0 rel_y- + +;md, Virtual Port 7, Sega Mega Mouse: Right Button +md.input.port7.megamouse.right mouse 0x0 button_right + +;md, Virtual Port 7, Sega Mega Mouse: Start Button +md.input.port7.megamouse.start keyboard 0x0 40 + +;Input device for Virtual Port 8 +md.input.port8 gamepad + +;md, Virtual Port 8, 3-Button Gamepad: A +md.input.port8.gamepad.a + +;md, Virtual Port 8, 3-Button Gamepad: B +md.input.port8.gamepad.b + +;md, Virtual Port 8, 3-Button Gamepad: C +md.input.port8.gamepad.c + +;md, Virtual Port 8, 3-Button Gamepad: DOWN ↓ +md.input.port8.gamepad.down + +;md, Virtual Port 8, 3-Button Gamepad: LEFT ← +md.input.port8.gamepad.left + +;md, Virtual Port 8, 3-Button Gamepad: Rapid A +md.input.port8.gamepad.rapid_a + +;md, Virtual Port 8, 3-Button Gamepad: Rapid B +md.input.port8.gamepad.rapid_b + +;md, Virtual Port 8, 3-Button Gamepad: Rapid C +md.input.port8.gamepad.rapid_c + +;md, Virtual Port 8, 3-Button Gamepad: RIGHT → +md.input.port8.gamepad.right + +;md, Virtual Port 8, 3-Button Gamepad: Start +md.input.port8.gamepad.start + +;md, Virtual Port 8, 3-Button Gamepad: UP ↑ +md.input.port8.gamepad.up + +;md, Virtual Port 8, 2-Button Gamepad: A +md.input.port8.gamepad2.a + +;md, Virtual Port 8, 2-Button Gamepad: B +md.input.port8.gamepad2.b + +;md, Virtual Port 8, 2-Button Gamepad: DOWN ↓ +md.input.port8.gamepad2.down + +;md, Virtual Port 8, 2-Button Gamepad: LEFT ← +md.input.port8.gamepad2.left + +;md, Virtual Port 8, 2-Button Gamepad: Rapid A +md.input.port8.gamepad2.rapid_a + +;md, Virtual Port 8, 2-Button Gamepad: Rapid B +md.input.port8.gamepad2.rapid_b + +;md, Virtual Port 8, 2-Button Gamepad: RIGHT → +md.input.port8.gamepad2.right + +;md, Virtual Port 8, 2-Button Gamepad: Start +md.input.port8.gamepad2.start + +;md, Virtual Port 8, 2-Button Gamepad: UP ↑ +md.input.port8.gamepad2.up + +;md, Virtual Port 8, 6-Button Gamepad: A +md.input.port8.gamepad6.a + +;md, Virtual Port 8, 6-Button Gamepad: B +md.input.port8.gamepad6.b + +;md, Virtual Port 8, 6-Button Gamepad: C +md.input.port8.gamepad6.c + +;md, Virtual Port 8, 6-Button Gamepad: DOWN ↓ +md.input.port8.gamepad6.down + +;md, Virtual Port 8, 6-Button Gamepad: LEFT ← +md.input.port8.gamepad6.left + +;md, Virtual Port 8, 6-Button Gamepad: Mode +md.input.port8.gamepad6.mode + +;md, Virtual Port 8, 6-Button Gamepad: Rapid A +md.input.port8.gamepad6.rapid_a + +;md, Virtual Port 8, 6-Button Gamepad: Rapid B +md.input.port8.gamepad6.rapid_b + +;md, Virtual Port 8, 6-Button Gamepad: Rapid C +md.input.port8.gamepad6.rapid_c + +;md, Virtual Port 8, 6-Button Gamepad: Rapid X +md.input.port8.gamepad6.rapid_x + +;md, Virtual Port 8, 6-Button Gamepad: Rapid Y +md.input.port8.gamepad6.rapid_y + +;md, Virtual Port 8, 6-Button Gamepad: Rapid Z +md.input.port8.gamepad6.rapid_z + +;md, Virtual Port 8, 6-Button Gamepad: RIGHT → +md.input.port8.gamepad6.right + +;md, Virtual Port 8, 6-Button Gamepad: Start +md.input.port8.gamepad6.start + +;md, Virtual Port 8, 6-Button Gamepad: UP ↑ +md.input.port8.gamepad6.up + +;md, Virtual Port 8, 6-Button Gamepad: X +md.input.port8.gamepad6.x + +;md, Virtual Port 8, 6-Button Gamepad: Y +md.input.port8.gamepad6.y + +;md, Virtual Port 8, 6-Button Gamepad: Z +md.input.port8.gamepad6.z + +;md, Virtual Port 8, Sega Mega Mouse: Left Button +md.input.port8.megamouse.left mouse 0x0 button_left + +;md, Virtual Port 8, Sega Mega Mouse: Middle Button +md.input.port8.megamouse.middle mouse 0x0 button_middle + +;md, Virtual Port 8, Sega Mega Mouse: Motion Down +md.input.port8.megamouse.motion_down mouse 0x0 rel_y+ + +;md, Virtual Port 8, Sega Mega Mouse: Motion Left +md.input.port8.megamouse.motion_left mouse 0x0 rel_x- + +;md, Virtual Port 8, Sega Mega Mouse: Motion Right +md.input.port8.megamouse.motion_right mouse 0x0 rel_x+ + +;md, Virtual Port 8, Sega Mega Mouse: Motion Up +md.input.port8.megamouse.motion_up mouse 0x0 rel_y- + +;md, Virtual Port 8, Sega Mega Mouse: Right Button +md.input.port8.megamouse.right mouse 0x0 button_right + +;md, Virtual Port 8, Sega Mega Mouse: Start Button +md.input.port8.megamouse.start keyboard 0x0 40 + +;Emulate the specified region's Genesis/MegaDrive +md.region game + +;Region reported to the game. +md.reported_region same + +;Enable scanlines with specified opacity. +md.scanlines 0 + +;Enable specified OpenGL shader. +md.shader none + +;Force interlaced video to be treated as progressive. +md.shader.goat.fprog 0 + +;Constant RGB horizontal divergence. +md.shader.goat.hdiv 0.50 + +;Mask pattern. +md.shader.goat.pat goatron + +;Enable scanlines effect. +md.shader.goat.slen 1 + +;Transparency of otherwise-opaque mask areas. +md.shader.goat.tp 0.50 + +;Constant RGB vertical divergence. +md.shader.goat.vdiv 0.50 + +;Enable specified special video scaler. +md.special none + +;Stretch to fill screen. +md.stretch aspect + +;Enable video temporal blur(50/50 previous/current frame by default). +md.tblur 0 + +;Accumulate color data rather than discarding it. +md.tblur.accum 0 + +;Blur amount in accumulation mode, specified in percentage of accumulation buffer to mix with the current frame. +md.tblur.accum.amount 50 + +;Enable (bi)linear interpolation. +md.videoip 0 + +;Full-screen horizontal resolution. +md.xres 0 + +;Scaling factor for the X axis in windowed mode. +md.xscale 3.000000 + +;Scaling factor for the X axis in fullscreen mode. +md.xscalefs 1.000000 + +;Full-screen vertical resolution. +md.yres 0 + +;Scaling factor for the Y axis in windowed mode. +md.yscale 3.000000 + +;Scaling factor for the Y axis in fullscreen mode. +md.yscalefs 1.000000 + +;Clip left+right 8 pixel columns. +nes.clipsides 0 + +;Correct the aspect ratio. +nes.correct_aspect 1 + +;Disassembly font size. +nes.debugger.disfontsize 5x7 + +;Character encoding for the debugger's memory editor. +nes.debugger.memcharenc cp437 + +;Enable (automatic) usage of this module. +nes.enable 1 + +;Scan filename for (U),(J),(E),etc. strings to en/dis-able PAL emulation. +nes.fnscan 1 + +;Enable Game Genie emulation. +nes.gg 0 + +;Path to Game Genie ROM image. +nes.ggrom gg.rom + +;Input device for Famicom Expansion Port +nes.input.fcexp none + +;nes, Famicom Expansion Port, Arkanoid Paddle: Button +nes.input.fcexp.arkanoid.button mouse 0x0 button_left + +;nes, Famicom Expansion Port, Arkanoid Paddle: X Axis +nes.input.fcexp.arkanoid.x_axis mouse 0x0 cursor_x-+ + +;nes, Famicom Expansion Port, Family Keyboard: 0 +nes.input.fcexp.fkb.0 keyboard 0x0 39 + +;nes, Famicom Expansion Port, Family Keyboard: 1 +nes.input.fcexp.fkb.1 keyboard 0x0 30 + +;nes, Famicom Expansion Port, Family Keyboard: 2 +nes.input.fcexp.fkb.2 keyboard 0x0 31 + +;nes, Famicom Expansion Port, Family Keyboard: 3 +nes.input.fcexp.fkb.3 keyboard 0x0 32 + +;nes, Famicom Expansion Port, Family Keyboard: 4 +nes.input.fcexp.fkb.4 keyboard 0x0 33 + +;nes, Famicom Expansion Port, Family Keyboard: 5 +nes.input.fcexp.fkb.5 keyboard 0x0 34 + +;nes, Famicom Expansion Port, Family Keyboard: 6 +nes.input.fcexp.fkb.6 keyboard 0x0 35 + +;nes, Famicom Expansion Port, Family Keyboard: 7 +nes.input.fcexp.fkb.7 keyboard 0x0 36 + +;nes, Famicom Expansion Port, Family Keyboard: 8 +nes.input.fcexp.fkb.8 keyboard 0x0 37 + +;nes, Famicom Expansion Port, Family Keyboard: 9 +nes.input.fcexp.fkb.9 keyboard 0x0 38 + +;nes, Famicom Expansion Port, Family Keyboard: A +nes.input.fcexp.fkb.a keyboard 0x0 4 + +;nes, Famicom Expansion Port, Family Keyboard: @ +nes.input.fcexp.fkb.at keyboard 0x0 53 + +;nes, Famicom Expansion Port, Family Keyboard: B +nes.input.fcexp.fkb.b keyboard 0x0 5 + +;nes, Famicom Expansion Port, Family Keyboard: \ +nes.input.fcexp.fkb.backslash keyboard 0x0 49 + +;nes, Famicom Expansion Port, Family Keyboard: C +nes.input.fcexp.fkb.c keyboard 0x0 6 + +;nes, Famicom Expansion Port, Family Keyboard: ^ +nes.input.fcexp.fkb.caret keyboard 0x0 46 + +;nes, Famicom Expansion Port, Family Keyboard: CLR +nes.input.fcexp.fkb.clear keyboard 0x0 76 + +;nes, Famicom Expansion Port, Family Keyboard: : +nes.input.fcexp.fkb.colon keyboard 0x0 52 + +;nes, Famicom Expansion Port, Family Keyboard: , +nes.input.fcexp.fkb.comma keyboard 0x0 54 + +;nes, Famicom Expansion Port, Family Keyboard: CTR +nes.input.fcexp.fkb.ctrl keyboard 0x0 224 + +;nes, Famicom Expansion Port, Family Keyboard: D +nes.input.fcexp.fkb.d keyboard 0x0 7 + +;nes, Famicom Expansion Port, Family Keyboard: DEL +nes.input.fcexp.fkb.delete keyboard 0x0 78 + +;nes, Famicom Expansion Port, Family Keyboard: DOWN +nes.input.fcexp.fkb.down keyboard 0x0 81 + +;nes, Famicom Expansion Port, Family Keyboard: E +nes.input.fcexp.fkb.e keyboard 0x0 8 + +;nes, Famicom Expansion Port, Family Keyboard: Empty +nes.input.fcexp.fkb.empty keyboard 0x0 230 + +;nes, Famicom Expansion Port, Family Keyboard: ESC +nes.input.fcexp.fkb.escape keyboard 0x0 41 + +;nes, Famicom Expansion Port, Family Keyboard: F +nes.input.fcexp.fkb.f keyboard 0x0 9 + +;nes, Famicom Expansion Port, Family Keyboard: F1 +nes.input.fcexp.fkb.f1 keyboard 0x0 58 + +;nes, Famicom Expansion Port, Family Keyboard: F2 +nes.input.fcexp.fkb.f2 keyboard 0x0 59 + +;nes, Famicom Expansion Port, Family Keyboard: F3 +nes.input.fcexp.fkb.f3 keyboard 0x0 60 + +;nes, Famicom Expansion Port, Family Keyboard: F4 +nes.input.fcexp.fkb.f4 keyboard 0x0 61 + +;nes, Famicom Expansion Port, Family Keyboard: F5 +nes.input.fcexp.fkb.f5 keyboard 0x0 62 + +;nes, Famicom Expansion Port, Family Keyboard: F6 +nes.input.fcexp.fkb.f6 keyboard 0x0 63 + +;nes, Famicom Expansion Port, Family Keyboard: F7 +nes.input.fcexp.fkb.f7 keyboard 0x0 64 + +;nes, Famicom Expansion Port, Family Keyboard: F8 +nes.input.fcexp.fkb.f8 keyboard 0x0 65 + +;nes, Famicom Expansion Port, Family Keyboard: G +nes.input.fcexp.fkb.g keyboard 0x0 10 + +;nes, Famicom Expansion Port, Family Keyboard: GRPH +nes.input.fcexp.fkb.graph keyboard 0x0 226 + +;nes, Famicom Expansion Port, Family Keyboard: H +nes.input.fcexp.fkb.h keyboard 0x0 11 + +;nes, Famicom Expansion Port, Family Keyboard: I +nes.input.fcexp.fkb.i keyboard 0x0 12 + +;nes, Famicom Expansion Port, Family Keyboard: INS +nes.input.fcexp.fkb.insert keyboard 0x0 77 + +;nes, Famicom Expansion Port, Family Keyboard: J +nes.input.fcexp.fkb.j keyboard 0x0 13 + +;nes, Famicom Expansion Port, Family Keyboard: K +nes.input.fcexp.fkb.k keyboard 0x0 14 + +;nes, Famicom Expansion Port, Family Keyboard: カナ +nes.input.fcexp.fkb.kana keyboard 0x0 73 + +;nes, Famicom Expansion Port, Family Keyboard: L +nes.input.fcexp.fkb.l keyboard 0x0 15 + +;nes, Famicom Expansion Port, Family Keyboard: LEFT +nes.input.fcexp.fkb.left keyboard 0x0 80 + +;nes, Famicom Expansion Port, Family Keyboard: [ +nes.input.fcexp.fkb.left_bracket keyboard 0x0 47 + +;nes, Famicom Expansion Port, Family Keyboard: Left SHIFT +nes.input.fcexp.fkb.left_shift keyboard 0x0 225 + +;nes, Famicom Expansion Port, Family Keyboard: M +nes.input.fcexp.fkb.m keyboard 0x0 16 + +;nes, Famicom Expansion Port, Family Keyboard: - +nes.input.fcexp.fkb.minus keyboard 0x0 45 + +;nes, Famicom Expansion Port, Family Keyboard: N +nes.input.fcexp.fkb.n keyboard 0x0 17 + +;nes, Famicom Expansion Port, Family Keyboard: O +nes.input.fcexp.fkb.o keyboard 0x0 18 + +;nes, Famicom Expansion Port, Family Keyboard: P +nes.input.fcexp.fkb.p keyboard 0x0 19 + +;nes, Famicom Expansion Port, Family Keyboard: . +nes.input.fcexp.fkb.period keyboard 0x0 55 + +;nes, Famicom Expansion Port, Family Keyboard: Q +nes.input.fcexp.fkb.q keyboard 0x0 20 + +;nes, Famicom Expansion Port, Family Keyboard: R +nes.input.fcexp.fkb.r keyboard 0x0 21 + +;nes, Famicom Expansion Port, Family Keyboard: RETURN +nes.input.fcexp.fkb.return keyboard 0x0 40 + +;nes, Famicom Expansion Port, Family Keyboard: RIGHT +nes.input.fcexp.fkb.right keyboard 0x0 79 + +;nes, Famicom Expansion Port, Family Keyboard: ] +nes.input.fcexp.fkb.right_bracket keyboard 0x0 48 + +;nes, Famicom Expansion Port, Family Keyboard: Right SHIFT +nes.input.fcexp.fkb.right_shift keyboard 0x0 229 + +;nes, Famicom Expansion Port, Family Keyboard: S +nes.input.fcexp.fkb.s keyboard 0x0 22 + +;nes, Famicom Expansion Port, Family Keyboard: ; +nes.input.fcexp.fkb.semicolon keyboard 0x0 51 + +;nes, Famicom Expansion Port, Family Keyboard: / +nes.input.fcexp.fkb.slash keyboard 0x0 56 + +;nes, Famicom Expansion Port, Family Keyboard: SPACE +nes.input.fcexp.fkb.space keyboard 0x0 44 + +;nes, Famicom Expansion Port, Family Keyboard: STOP +nes.input.fcexp.fkb.stop keyboard 0x0 42 + +;nes, Famicom Expansion Port, Family Keyboard: T +nes.input.fcexp.fkb.t keyboard 0x0 23 + +;nes, Famicom Expansion Port, Family Keyboard: U +nes.input.fcexp.fkb.u keyboard 0x0 24 + +;nes, Famicom Expansion Port, Family Keyboard: UP +nes.input.fcexp.fkb.up keyboard 0x0 82 + +;nes, Famicom Expansion Port, Family Keyboard: V +nes.input.fcexp.fkb.v keyboard 0x0 25 + +;nes, Famicom Expansion Port, Family Keyboard: W +nes.input.fcexp.fkb.w keyboard 0x0 26 + +;nes, Famicom Expansion Port, Family Keyboard: X +nes.input.fcexp.fkb.x keyboard 0x0 27 + +;nes, Famicom Expansion Port, Family Keyboard: Y +nes.input.fcexp.fkb.y keyboard 0x0 28 + +;nes, Famicom Expansion Port, Family Keyboard: Z +nes.input.fcexp.fkb.z keyboard 0x0 29 + +;nes, Famicom Expansion Port, Family Trainer Side A: 1 +nes.input.fcexp.ftrainera.1 keyboard 0x0 18 + +;nes, Famicom Expansion Port, Family Trainer Side A: 10 +nes.input.fcexp.ftrainera.10 keyboard 0x0 54 + +;nes, Famicom Expansion Port, Family Trainer Side A: 11 +nes.input.fcexp.ftrainera.11 keyboard 0x0 55 + +;nes, Famicom Expansion Port, Family Trainer Side A: 12 +nes.input.fcexp.ftrainera.12 keyboard 0x0 56 + +;nes, Famicom Expansion Port, Family Trainer Side A: 2 +nes.input.fcexp.ftrainera.2 keyboard 0x0 19 + +;nes, Famicom Expansion Port, Family Trainer Side A: 3 +nes.input.fcexp.ftrainera.3 keyboard 0x0 47 + +;nes, Famicom Expansion Port, Family Trainer Side A: 4 +nes.input.fcexp.ftrainera.4 keyboard 0x0 48 + +;nes, Famicom Expansion Port, Family Trainer Side A: 5 +nes.input.fcexp.ftrainera.5 keyboard 0x0 14 + +;nes, Famicom Expansion Port, Family Trainer Side A: 6 +nes.input.fcexp.ftrainera.6 keyboard 0x0 15 + +;nes, Famicom Expansion Port, Family Trainer Side A: 7 +nes.input.fcexp.ftrainera.7 keyboard 0x0 51 + +;nes, Famicom Expansion Port, Family Trainer Side A: 8 +nes.input.fcexp.ftrainera.8 keyboard 0x0 52 + +;nes, Famicom Expansion Port, Family Trainer Side A: 9 +nes.input.fcexp.ftrainera.9 keyboard 0x0 16 + +;nes, Famicom Expansion Port, Family Trainer Side B: 1 +nes.input.fcexp.ftrainerb.1 keyboard 0x0 18 + +;nes, Famicom Expansion Port, Family Trainer Side B: 10 +nes.input.fcexp.ftrainerb.10 keyboard 0x0 54 + +;nes, Famicom Expansion Port, Family Trainer Side B: 11 +nes.input.fcexp.ftrainerb.11 keyboard 0x0 55 + +;nes, Famicom Expansion Port, Family Trainer Side B: 12 +nes.input.fcexp.ftrainerb.12 keyboard 0x0 56 + +;nes, Famicom Expansion Port, Family Trainer Side B: 2 +nes.input.fcexp.ftrainerb.2 keyboard 0x0 19 + +;nes, Famicom Expansion Port, Family Trainer Side B: 3 +nes.input.fcexp.ftrainerb.3 keyboard 0x0 47 + +;nes, Famicom Expansion Port, Family Trainer Side B: 4 +nes.input.fcexp.ftrainerb.4 keyboard 0x0 48 + +;nes, Famicom Expansion Port, Family Trainer Side B: 5 +nes.input.fcexp.ftrainerb.5 keyboard 0x0 14 + +;nes, Famicom Expansion Port, Family Trainer Side B: 6 +nes.input.fcexp.ftrainerb.6 keyboard 0x0 15 + +;nes, Famicom Expansion Port, Family Trainer Side B: 7 +nes.input.fcexp.ftrainerb.7 keyboard 0x0 51 + +;nes, Famicom Expansion Port, Family Trainer Side B: 8 +nes.input.fcexp.ftrainerb.8 keyboard 0x0 52 + +;nes, Famicom Expansion Port, Family Trainer Side B: 9 +nes.input.fcexp.ftrainerb.9 keyboard 0x0 16 + +;nes, Famicom Expansion Port, Hypershot Paddles: I, JUMP +nes.input.fcexp.hypershot.i_jump keyboard 0x0 26 + +;nes, Famicom Expansion Port, Hypershot Paddles: I, RUN +nes.input.fcexp.hypershot.i_run keyboard 0x0 20 + +;nes, Famicom Expansion Port, Hypershot Paddles: II, JUMP +nes.input.fcexp.hypershot.ii_jump keyboard 0x0 21 + +;nes, Famicom Expansion Port, Hypershot Paddles: II, RUN +nes.input.fcexp.hypershot.ii_run keyboard 0x0 8 + +;nes, Famicom Expansion Port, Hypershot Paddles: Rapid I, JUMP +nes.input.fcexp.hypershot.rapid_i_jump + +;nes, Famicom Expansion Port, Hypershot Paddles: Rapid I, RUN +nes.input.fcexp.hypershot.rapid_i_run + +;nes, Famicom Expansion Port, Hypershot Paddles: Rapid II, JUMP +nes.input.fcexp.hypershot.rapid_ii_jump + +;nes, Famicom Expansion Port, Hypershot Paddles: Rapid II, RUN +nes.input.fcexp.hypershot.rapid_ii_run + +;nes, Famicom Expansion Port, Mahjong Controller: 1 +nes.input.fcexp.mahjong.1 keyboard 0x0 20 + +;nes, Famicom Expansion Port, Mahjong Controller: 10 +nes.input.fcexp.mahjong.10 keyboard 0x0 10 + +;nes, Famicom Expansion Port, Mahjong Controller: 11 +nes.input.fcexp.mahjong.11 keyboard 0x0 11 + +;nes, Famicom Expansion Port, Mahjong Controller: 12 +nes.input.fcexp.mahjong.12 keyboard 0x0 13 + +;nes, Famicom Expansion Port, Mahjong Controller: 13 +nes.input.fcexp.mahjong.13 keyboard 0x0 14 + +;nes, Famicom Expansion Port, Mahjong Controller: 14 +nes.input.fcexp.mahjong.14 keyboard 0x0 15 + +;nes, Famicom Expansion Port, Mahjong Controller: 15 +nes.input.fcexp.mahjong.15 keyboard 0x0 29 + +;nes, Famicom Expansion Port, Mahjong Controller: 16 +nes.input.fcexp.mahjong.16 keyboard 0x0 27 + +;nes, Famicom Expansion Port, Mahjong Controller: 17 +nes.input.fcexp.mahjong.17 keyboard 0x0 6 + +;nes, Famicom Expansion Port, Mahjong Controller: 18 +nes.input.fcexp.mahjong.18 keyboard 0x0 25 + +;nes, Famicom Expansion Port, Mahjong Controller: 19 +nes.input.fcexp.mahjong.19 keyboard 0x0 5 + +;nes, Famicom Expansion Port, Mahjong Controller: 2 +nes.input.fcexp.mahjong.2 keyboard 0x0 26 + +;nes, Famicom Expansion Port, Mahjong Controller: 20 +nes.input.fcexp.mahjong.20 keyboard 0x0 17 + +;nes, Famicom Expansion Port, Mahjong Controller: 21 +nes.input.fcexp.mahjong.21 keyboard 0x0 16 + +;nes, Famicom Expansion Port, Mahjong Controller: 3 +nes.input.fcexp.mahjong.3 keyboard 0x0 8 + +;nes, Famicom Expansion Port, Mahjong Controller: 4 +nes.input.fcexp.mahjong.4 keyboard 0x0 21 + +;nes, Famicom Expansion Port, Mahjong Controller: 5 +nes.input.fcexp.mahjong.5 keyboard 0x0 23 + +;nes, Famicom Expansion Port, Mahjong Controller: 6 +nes.input.fcexp.mahjong.6 keyboard 0x0 4 + +;nes, Famicom Expansion Port, Mahjong Controller: 7 +nes.input.fcexp.mahjong.7 keyboard 0x0 22 + +;nes, Famicom Expansion Port, Mahjong Controller: 8 +nes.input.fcexp.mahjong.8 keyboard 0x0 7 + +;nes, Famicom Expansion Port, Mahjong Controller: 9 +nes.input.fcexp.mahjong.9 keyboard 0x0 9 + +;nes, Famicom Expansion Port, Oeka Kids Tablet: Button +nes.input.fcexp.oekakids.button mouse 0x0 button_left + +;nes, Famicom Expansion Port, Oeka Kids Tablet: X Axis +nes.input.fcexp.oekakids.x_axis mouse 0x0 cursor_x-+ + +;nes, Famicom Expansion Port, Oeka Kids Tablet: Y Axis +nes.input.fcexp.oekakids.y_axis mouse 0x0 cursor_y-+ + +;nes, Famicom Expansion Port, Party Tap: Buzzer 1 +nes.input.fcexp.partytap.buzzer_1 keyboard 0x0 20 + +;nes, Famicom Expansion Port, Party Tap: Buzzer 2 +nes.input.fcexp.partytap.buzzer_2 keyboard 0x0 26 + +;nes, Famicom Expansion Port, Party Tap: Buzzer 3 +nes.input.fcexp.partytap.buzzer_3 keyboard 0x0 8 + +;nes, Famicom Expansion Port, Party Tap: Buzzer 4 +nes.input.fcexp.partytap.buzzer_4 keyboard 0x0 21 + +;nes, Famicom Expansion Port, Party Tap: Buzzer 5 +nes.input.fcexp.partytap.buzzer_5 keyboard 0x0 23 + +;nes, Famicom Expansion Port, Party Tap: Buzzer 6 +nes.input.fcexp.partytap.buzzer_6 keyboard 0x0 28 + +;nes, Famicom Expansion Port, Space Shadow Gun: Away Trigger +nes.input.fcexp.shadow.away_trigger mouse 0x0 button_right + +;nes, Famicom Expansion Port, Space Shadow Gun: Trigger +nes.input.fcexp.shadow.trigger mouse 0x0 button_left + +;nes, Famicom Expansion Port, Space Shadow Gun: X Axis +nes.input.fcexp.shadow.x_axis mouse 0x0 cursor_x-+ + +;nes, Famicom Expansion Port, Space Shadow Gun: Y Axis +nes.input.fcexp.shadow.y_axis mouse 0x0 cursor_y-+ + +;Input device for Port 1 +nes.input.port1 gamepad + +;nes, Port 1, Arkanoid Paddle: Button +nes.input.port1.arkanoid.button mouse 0x0 button_left + +;nes, Port 1, Arkanoid Paddle: X Axis +nes.input.port1.arkanoid.x_axis mouse 0x0 cursor_x-+ + +;nes, Port 1, Gamepad: A +nes.input.port1.gamepad.a joystick @GUID1@ @DEVICE_BTN_EAST@ + +;nes, Port 1, Gamepad: B +nes.input.port1.gamepad.b joystick @GUID1@ @DEVICE_BTN_SOUTH@ + +;nes, Port 1, Gamepad: DOWN ↓ +nes.input.port1.gamepad.down joystick @GUID1@ @DEVICE_BTN_DPAD_DOWN@ + +;nes, Port 1, Gamepad: LEFT ← +nes.input.port1.gamepad.left joystick @GUID1@ @DEVICE_BTN_DPAD_LEFT@ + +;nes, Port 1, Gamepad: Rapid A +nes.input.port1.gamepad.rapid_a joystick @GUID1@ @DEVICE_BTN_NORTH@ + +;nes, Port 1, Gamepad: Rapid B +nes.input.port1.gamepad.rapid_b joystick @GUID1@ @DEVICE_BTN_WEST@ + +;nes, Port 1, Gamepad: RIGHT → +nes.input.port1.gamepad.right joystick @GUID1@ @DEVICE_BTN_DPAD_RIGHT@ + +;nes, Port 1, Gamepad: SELECT +nes.input.port1.gamepad.select joystick @GUID1@ @DEVICE_BTN_SELECT@ + +;nes, Port 1, Gamepad: START +nes.input.port1.gamepad.start joystick @GUID1@ @DEVICE_BTN_START@ + +;nes, Port 1, Gamepad: UP ↑ +nes.input.port1.gamepad.up joystick @GUID1@ @DEVICE_BTN_DPAD_UP@ + +;nes, Port 1, Power Pad Side A: 1 +nes.input.port1.powerpada.1 keyboard 0x0 18 + +;nes, Port 1, Power Pad Side A: 10 +nes.input.port1.powerpada.10 keyboard 0x0 54 + +;nes, Port 1, Power Pad Side A: 11 +nes.input.port1.powerpada.11 keyboard 0x0 55 + +;nes, Port 1, Power Pad Side A: 12 +nes.input.port1.powerpada.12 keyboard 0x0 56 + +;nes, Port 1, Power Pad Side A: 2 +nes.input.port1.powerpada.2 keyboard 0x0 19 + +;nes, Port 1, Power Pad Side A: 3 +nes.input.port1.powerpada.3 keyboard 0x0 47 + +;nes, Port 1, Power Pad Side A: 4 +nes.input.port1.powerpada.4 keyboard 0x0 48 + +;nes, Port 1, Power Pad Side A: 5 +nes.input.port1.powerpada.5 keyboard 0x0 14 + +;nes, Port 1, Power Pad Side A: 6 +nes.input.port1.powerpada.6 keyboard 0x0 15 + +;nes, Port 1, Power Pad Side A: 7 +nes.input.port1.powerpada.7 keyboard 0x0 51 + +;nes, Port 1, Power Pad Side A: 8 +nes.input.port1.powerpada.8 keyboard 0x0 52 + +;nes, Port 1, Power Pad Side A: 9 +nes.input.port1.powerpada.9 keyboard 0x0 16 + +;nes, Port 1, Power Pad Side B: 1 +nes.input.port1.powerpadb.1 keyboard 0x0 18 + +;nes, Port 1, Power Pad Side B: 10 +nes.input.port1.powerpadb.10 keyboard 0x0 54 + +;nes, Port 1, Power Pad Side B: 11 +nes.input.port1.powerpadb.11 keyboard 0x0 55 + +;nes, Port 1, Power Pad Side B: 12 +nes.input.port1.powerpadb.12 keyboard 0x0 56 + +;nes, Port 1, Power Pad Side B: 2 +nes.input.port1.powerpadb.2 keyboard 0x0 19 + +;nes, Port 1, Power Pad Side B: 3 +nes.input.port1.powerpadb.3 keyboard 0x0 47 + +;nes, Port 1, Power Pad Side B: 4 +nes.input.port1.powerpadb.4 keyboard 0x0 48 + +;nes, Port 1, Power Pad Side B: 5 +nes.input.port1.powerpadb.5 keyboard 0x0 14 + +;nes, Port 1, Power Pad Side B: 6 +nes.input.port1.powerpadb.6 keyboard 0x0 15 + +;nes, Port 1, Power Pad Side B: 7 +nes.input.port1.powerpadb.7 keyboard 0x0 51 + +;nes, Port 1, Power Pad Side B: 8 +nes.input.port1.powerpadb.8 keyboard 0x0 52 + +;nes, Port 1, Power Pad Side B: 9 +nes.input.port1.powerpadb.9 keyboard 0x0 16 + +;nes, Port 1, Zapper: Away Trigger +nes.input.port1.zapper.away_trigger mouse 0x0 button_right + +;nes, Port 1, Zapper: Trigger +nes.input.port1.zapper.trigger mouse 0x0 button_left + +;nes, Port 1, Zapper: X Axis +nes.input.port1.zapper.x_axis mouse 0x0 cursor_x-+ + +;nes, Port 1, Zapper: Y Axis +nes.input.port1.zapper.y_axis mouse 0x0 cursor_y-+ + +;Input device for Port 2 +nes.input.port2 gamepad + +;nes, Port 2, Arkanoid Paddle: Button +nes.input.port2.arkanoid.button mouse 0x0 button_left + +;nes, Port 2, Arkanoid Paddle: X Axis +nes.input.port2.arkanoid.x_axis mouse 0x0 cursor_x-+ + +;nes, Port 2, Gamepad: A +nes.input.port2.gamepad.a + +;nes, Port 2, Gamepad: B +nes.input.port2.gamepad.b + +;nes, Port 2, Gamepad: DOWN ↓ +nes.input.port2.gamepad.down + +;nes, Port 2, Gamepad: LEFT ← +nes.input.port2.gamepad.left + +;nes, Port 2, Gamepad: Rapid A +nes.input.port2.gamepad.rapid_a + +;nes, Port 2, Gamepad: Rapid B +nes.input.port2.gamepad.rapid_b + +;nes, Port 2, Gamepad: RIGHT → +nes.input.port2.gamepad.right + +;nes, Port 2, Gamepad: SELECT +nes.input.port2.gamepad.select + +;nes, Port 2, Gamepad: START +nes.input.port2.gamepad.start + +;nes, Port 2, Gamepad: UP ↑ +nes.input.port2.gamepad.up + +;nes, Port 2, Power Pad Side A: 1 +nes.input.port2.powerpada.1 keyboard 0x0 18 + +;nes, Port 2, Power Pad Side A: 10 +nes.input.port2.powerpada.10 keyboard 0x0 54 + +;nes, Port 2, Power Pad Side A: 11 +nes.input.port2.powerpada.11 keyboard 0x0 55 + +;nes, Port 2, Power Pad Side A: 12 +nes.input.port2.powerpada.12 keyboard 0x0 56 + +;nes, Port 2, Power Pad Side A: 2 +nes.input.port2.powerpada.2 keyboard 0x0 19 + +;nes, Port 2, Power Pad Side A: 3 +nes.input.port2.powerpada.3 keyboard 0x0 47 + +;nes, Port 2, Power Pad Side A: 4 +nes.input.port2.powerpada.4 keyboard 0x0 48 + +;nes, Port 2, Power Pad Side A: 5 +nes.input.port2.powerpada.5 keyboard 0x0 14 + +;nes, Port 2, Power Pad Side A: 6 +nes.input.port2.powerpada.6 keyboard 0x0 15 + +;nes, Port 2, Power Pad Side A: 7 +nes.input.port2.powerpada.7 keyboard 0x0 51 + +;nes, Port 2, Power Pad Side A: 8 +nes.input.port2.powerpada.8 keyboard 0x0 52 + +;nes, Port 2, Power Pad Side A: 9 +nes.input.port2.powerpada.9 keyboard 0x0 16 + +;nes, Port 2, Power Pad Side B: 1 +nes.input.port2.powerpadb.1 keyboard 0x0 18 + +;nes, Port 2, Power Pad Side B: 10 +nes.input.port2.powerpadb.10 keyboard 0x0 54 + +;nes, Port 2, Power Pad Side B: 11 +nes.input.port2.powerpadb.11 keyboard 0x0 55 + +;nes, Port 2, Power Pad Side B: 12 +nes.input.port2.powerpadb.12 keyboard 0x0 56 + +;nes, Port 2, Power Pad Side B: 2 +nes.input.port2.powerpadb.2 keyboard 0x0 19 + +;nes, Port 2, Power Pad Side B: 3 +nes.input.port2.powerpadb.3 keyboard 0x0 47 + +;nes, Port 2, Power Pad Side B: 4 +nes.input.port2.powerpadb.4 keyboard 0x0 48 + +;nes, Port 2, Power Pad Side B: 5 +nes.input.port2.powerpadb.5 keyboard 0x0 14 + +;nes, Port 2, Power Pad Side B: 6 +nes.input.port2.powerpadb.6 keyboard 0x0 15 + +;nes, Port 2, Power Pad Side B: 7 +nes.input.port2.powerpadb.7 keyboard 0x0 51 + +;nes, Port 2, Power Pad Side B: 8 +nes.input.port2.powerpadb.8 keyboard 0x0 52 + +;nes, Port 2, Power Pad Side B: 9 +nes.input.port2.powerpadb.9 keyboard 0x0 16 + +;nes, Port 2, Zapper: Away Trigger +nes.input.port2.zapper.away_trigger mouse 0x0 button_right + +;nes, Port 2, Zapper: Trigger +nes.input.port2.zapper.trigger mouse 0x0 button_left + +;nes, Port 2, Zapper: X Axis +nes.input.port2.zapper.x_axis mouse 0x0 cursor_x-+ + +;nes, Port 2, Zapper: Y Axis +nes.input.port2.zapper.y_axis mouse 0x0 cursor_y-+ + +;Input device for Port 3 +nes.input.port3 gamepad + +;nes, Port 3, Gamepad: A +nes.input.port3.gamepad.a + +;nes, Port 3, Gamepad: B +nes.input.port3.gamepad.b + +;nes, Port 3, Gamepad: DOWN ↓ +nes.input.port3.gamepad.down + +;nes, Port 3, Gamepad: LEFT ← +nes.input.port3.gamepad.left + +;nes, Port 3, Gamepad: Rapid A +nes.input.port3.gamepad.rapid_a + +;nes, Port 3, Gamepad: Rapid B +nes.input.port3.gamepad.rapid_b + +;nes, Port 3, Gamepad: RIGHT → +nes.input.port3.gamepad.right + +;nes, Port 3, Gamepad: SELECT +nes.input.port3.gamepad.select + +;nes, Port 3, Gamepad: START +nes.input.port3.gamepad.start + +;nes, Port 3, Gamepad: UP ↑ +nes.input.port3.gamepad.up + +;Input device for Port 4 +nes.input.port4 gamepad + +;nes, Port 4, Gamepad: A +nes.input.port4.gamepad.a + +;nes, Port 4, Gamepad: B +nes.input.port4.gamepad.b + +;nes, Port 4, Gamepad: DOWN ↓ +nes.input.port4.gamepad.down + +;nes, Port 4, Gamepad: LEFT ← +nes.input.port4.gamepad.left + +;nes, Port 4, Gamepad: Rapid A +nes.input.port4.gamepad.rapid_a + +;nes, Port 4, Gamepad: Rapid B +nes.input.port4.gamepad.rapid_b + +;nes, Port 4, Gamepad: RIGHT → +nes.input.port4.gamepad.right + +;nes, Port 4, Gamepad: SELECT +nes.input.port4.gamepad.select + +;nes, Port 4, Gamepad: START +nes.input.port4.gamepad.start + +;nes, Port 4, Gamepad: UP ↑ +nes.input.port4.gamepad.up + +;Enable less-accurate, but better sounding, Namco 106(mapper 19) sound emulation. +nes.n106bs 0 + +;Remove 8-sprites-per-scanline hardware limit. +nes.no8lim 0 + +;Disable four-score emulation. +nes.nofs 0 + +;NTSC composite blitter brightness. +nes.ntsc.brightness 0 + +;NTSC composite blitter contrast. +nes.ntsc.contrast 0 + +;NTSC composite blitter hue. +nes.ntsc.hue 0 + +;Enable NTSC custom decoder matrix. +nes.ntsc.matrix 0 + +;NTSC custom decoder matrix element 0(red, value * V). +nes.ntsc.matrix.0 1.539 + +;NTSC custom decoder matrix element 1(red, value * U). +nes.ntsc.matrix.1 -0.622 + +;NTSC custom decoder matrix element 2(green, value * V). +nes.ntsc.matrix.2 -0.571 + +;NTSC custom decoder matrix element 3(green, value * U). +nes.ntsc.matrix.3 -0.185 + +;NTSC custom decoder matrix element 4(blue, value * V). +nes.ntsc.matrix.4 0.000 + +;NTSC custom decoder matrix element 5(blue, value * U. +nes.ntsc.matrix.5 2.000 + +;Merge fields to partially work around !=60.1Hz refresh rates. +nes.ntsc.mergefields 0 + +;Video quality/type preset. +nes.ntsc.preset none + +;NTSC composite blitter saturation. +nes.ntsc.saturation 0 + +;NTSC composite blitter sharpness. +nes.ntsc.sharpness 0 + +;Enable NTSC color generation and blitter. +nes.ntscblitter 0 + +;Enable PAL(50Hz) NES emulation. +nes.pal 0 + +;Enable scanlines with specified opacity. +nes.scanlines 0 + +;Enable specified OpenGL shader. +nes.shader ipsharper + +;Force interlaced video to be treated as progressive. +nes.shader.goat.fprog 0 + +;Constant RGB horizontal divergence. +nes.shader.goat.hdiv 0.50 + +;Mask pattern. +nes.shader.goat.pat goatron + +;Enable scanlines effect. +nes.shader.goat.slen 1 + +;Transparency of otherwise-opaque mask areas. +nes.shader.goat.tp 0.50 + +;Constant RGB vertical divergence. +nes.shader.goat.vdiv 0.50 + +;Last displayed scanline in NTSC mode. +nes.slend 231 + +;Last displayed scanline in PAL mode. +nes.slendp 239 + +;First displayed scanline in NTSC mode. +nes.slstart 8 + +;First displayed scanline in PAL mode. +nes.slstartp 0 + +;Output rate tolerance. +nes.sound_rate_error 0.00004 + +;Sound quality. +nes.soundq 0 + +;Enable specified special video scaler. +nes.special none + +;Stretch to fill screen. +nes.stretch full + +;Enable video temporal blur(50/50 previous/current frame by default). +nes.tblur 0 + +;Accumulate color data rather than discarding it. +nes.tblur.accum 0 + +;Blur amount in accumulation mode, specified in percentage of accumulation buffer to mix with the current frame. +nes.tblur.accum.amount 50 + +;Enable (bi)linear interpolation. +nes.videoip 0 + +;Full-screen horizontal resolution. +nes.xres 0 + +;Scaling factor for the X axis in windowed mode. +nes.xscale 4.000000 + +;Scaling factor for the X axis in fullscreen mode. +nes.xscalefs 1.000000 + +;Full-screen vertical resolution. +nes.yres 0 + +;Scaling factor for the Y axis in windowed mode. +nes.yscale 4.000000 + +;Scaling factor for the Y axis in fullscreen mode. +nes.yscalefs 1.000000 + +;Font for netplay chat console. +netplay.console.font 9x18 + +;Height of chat console, in lines. +netplay.console.lines 5 + +;Netplay chat console text scale factor. +netplay.console.scale 1 + +;Key to hash with the MD5 hash of the game. +netplay.gamekey + +;Server hostname. +netplay.host netplay.fobby.net + +;Local player count. +netplay.localplayers 1 + +;Nickname. +netplay.nick + +;Server password. +netplay.password + +;Server port. +netplay.port 4046 + +;Enable (automatic) usage of this module. +ngp.enable 1 + +;Force monophonic sound output. +ngp.forcemono 0 + +;ngp, Built-In, Gamepad: A +ngp.input.builtin.gamepad.a joystick @GUID1@ @DEVICE_BTN_SOUTH@ + +;ngp, Built-In, Gamepad: B +ngp.input.builtin.gamepad.b joystick @GUID1@ @DEVICE_BTN_EAST@ + +;ngp, Built-In, Gamepad: DOWN ↓ +ngp.input.builtin.gamepad.down joystick @GUID1@ @DEVICE_BTN_DPAD_DOWN@ + +;ngp, Built-In, Gamepad: LEFT ← +ngp.input.builtin.gamepad.left joystick @GUID1@ @DEVICE_BTN_DPAD_LEFT@ + +;ngp, Built-In, Gamepad: OPTION +ngp.input.builtin.gamepad.option joystick @GUID1@ @DEVICE_BTN_START@ + +;ngp, Built-In, Gamepad: Rapid A +ngp.input.builtin.gamepad.rapid_a joystick @GUID1@ @DEVICE_BTN_WEST@ + +;ngp, Built-In, Gamepad: Rapid B +ngp.input.builtin.gamepad.rapid_b joystick @GUID1@ @DEVICE_BTN_NORTH@ + +;ngp, Built-In, Gamepad: RIGHT → +ngp.input.builtin.gamepad.right joystick @GUID1@ @DEVICE_BTN_DPAD_RIGHT@ + +;ngp, Built-In, Gamepad: UP ↑ +ngp.input.builtin.gamepad.up joystick @GUID1@ @DEVICE_BTN_DPAD_UP@ + +;Language games should display text in. +ngp.language english + +;Enable scanlines with specified opacity. +ngp.scanlines 0 + +;Enable specified OpenGL shader. +ngp.shader ipsharper + +;Force interlaced video to be treated as progressive. +ngp.shader.goat.fprog 0 + +;Constant RGB horizontal divergence. +ngp.shader.goat.hdiv 0.50 + +;Mask pattern. +ngp.shader.goat.pat goatron + +;Enable scanlines effect. +ngp.shader.goat.slen 1 + +;Transparency of otherwise-opaque mask areas. +ngp.shader.goat.tp 0.50 + +;Constant RGB vertical divergence. +ngp.shader.goat.vdiv 0.50 + +;Enable specified special video scaler. +ngp.special none + +;Stretch to fill screen. +ngp.stretch aspect + +;Enable video temporal blur(50/50 previous/current frame by default). +ngp.tblur 0 + +;Accumulate color data rather than discarding it. +ngp.tblur.accum 0 + +;Blur amount in accumulation mode, specified in percentage of accumulation buffer to mix with the current frame. +ngp.tblur.accum.amount 50 + +;Enable (bi)linear interpolation. +ngp.videoip 0 + +;Full-screen horizontal resolution. +ngp.xres 0 + +;Scaling factor for the X axis in windowed mode. +ngp.xscale 6.000000 + +;Scaling factor for the X axis in fullscreen mode. +ngp.xscalefs 1.000000 + +;Full-screen vertical resolution. +ngp.yres 0 + +;Scaling factor for the Y axis in windowed mode. +ngp.yscale 6.000000 + +;Scaling factor for the Y axis in fullscreen mode. +ngp.yscalefs 1.000000 + +;Disable speed throttling when sound is disabled. +nothrottle 0 + +;Enable alpha blending for OSD elements. +osd.alpha_blend 1 + +;Length of time, in milliseconds, to display internal status and error messages +osd.message_display_time 2500 + +;Length of time, in milliseconds, to display the save state or the movie selector after selecting a state or movie. +osd.state_display_time 2000 + +;Output the full 12-bit ADPCM predictor. +pce.adpcmextraprec 0 + +;ADPCM volume. +pce.adpcmvolume 100 + +;Enable Arcade Card emulation. +pce.arcadecard 1 + +;Path to the CD BIOS +pce.cdbios syscard3.pce + +;CD-DA volume. +pce.cddavolume 100 + +;PSG volume when playing a CD game. +pce.cdpsgvolume 100 + +;Disassembly font size. +pce.debugger.disfontsize 5x7 + +;Character encoding for the debugger's memory editor. +pce.debugger.memcharenc shift_jis + +;Disable BRAM(saved game memory) for CD games. +pce.disable_bram_cd 0 + +;Disable BRAM(saved game memory) for HuCard games. +pce.disable_bram_hucard 0 + +;If set, when RUN+SEL are pressed simultaneously, disable both buttons temporarily. +pce.disable_softreset 0 + +;Enable (automatic) usage of this module. +pce.enable 1 + +;Force monophonic sound output. +pce.forcemono 0 + +;Force SuperGrafx emulation. +pce.forcesgx 0 + +;Path to the GE CD BIOS +pce.gecdbios gecard.pce + +;Show horizontal overscan area. +pce.h_overscan 0 + +;Enable multitap(TurboTap) emulation. +pce.input.multitap 1 + +;Input device for Port 1 +pce.input.port1 gamepad + +;pce, Port 1, Gamepad: DOWN ↓ +pce.input.port1.gamepad.down joystick @GUID1@ @DEVICE_BTN_DPAD_DOWN@ + +;pce, Port 1, Gamepad: I +pce.input.port1.gamepad.i joystick @GUID1@ @DEVICE_BTN_EAST@ + +;pce, Port 1, Gamepad: II +pce.input.port1.gamepad.ii joystick @GUID1@ @DEVICE_BTN_SOUTH@ + +;pce, Port 1, Gamepad: III +pce.input.port1.gamepad.iii joystick @GUID1@ @DEVICE_BTN_WEST@ + +;pce, Port 1, Gamepad: IV +pce.input.port1.gamepad.iv joystick @GUID1@ @DEVICE_BTN_NORTH@ + +;pce, Port 1, Gamepad: LEFT ← +pce.input.port1.gamepad.left joystick @GUID1@ @DEVICE_BTN_DPAD_LEFT@ + +;pce, Port 1, Gamepad: Mode +pce.input.port1.gamepad.mode_select keyboard 0x0 20 + +;Default position for switch "Mode". +pce.input.port1.gamepad.mode_select.defpos 2 + +;pce, Port 1, Gamepad: Rapid I +pce.input.port1.gamepad.rapid_i keyboard 0x0 17 + +;pce, Port 1, Gamepad: Rapid II +pce.input.port1.gamepad.rapid_ii keyboard 0x0 17 + +;pce, Port 1, Gamepad: RIGHT → +pce.input.port1.gamepad.right joystick @GUID1@ @DEVICE_BTN_DPAD_RIGHT@ + +;pce, Port 1, Gamepad: RUN +pce.input.port1.gamepad.run joystick @GUID1@ @DEVICE_BTN_START@ + +;pce, Port 1, Gamepad: SELECT +pce.input.port1.gamepad.select joystick @GUID1@ @DEVICE_BTN_SELECT@ + +;pce, Port 1, Gamepad: UP ↑ +pce.input.port1.gamepad.up joystick @GUID1@ @DEVICE_BTN_DPAD_UP@ + +;pce, Port 1, Gamepad: V +pce.input.port1.gamepad.v joystick @GUID1@ @DEVICE_BTN_TL@ + +;pce, Port 1, Gamepad: VI +pce.input.port1.gamepad.vi joystick @GUID1@ @DEVICE_BTN_TR@ + +;pce, Port 1, Mouse: Left Button +pce.input.port1.mouse.left mouse 0x0 button_left + +;pce, Port 1, Mouse: Motion Down +pce.input.port1.mouse.motion_down mouse 0x0 rel_y+ + +;pce, Port 1, Mouse: Motion Left +pce.input.port1.mouse.motion_left mouse 0x0 rel_x- + +;pce, Port 1, Mouse: Motion Right +pce.input.port1.mouse.motion_right mouse 0x0 rel_x+ + +;pce, Port 1, Mouse: Motion Up +pce.input.port1.mouse.motion_up mouse 0x0 rel_y- + +;pce, Port 1, Mouse: Right Button +pce.input.port1.mouse.right mouse 0x0 button_right + +;pce, Port 1, Mouse: RUN +pce.input.port1.mouse.run keyboard 0x0 40 + +;pce, Port 1, Mouse: SELECT +pce.input.port1.mouse.select keyboard 0x0 43 + +;pce, Port 1, Tsushin Keyboard: 0 +pce.input.port1.tsushinkb.0 keyboard 0x0 39 + +;pce, Port 1, Tsushin Keyboard: 1 +pce.input.port1.tsushinkb.1 keyboard 0x0 30 + +;pce, Port 1, Tsushin Keyboard: 2 +pce.input.port1.tsushinkb.2 keyboard 0x0 31 + +;pce, Port 1, Tsushin Keyboard: 3 +pce.input.port1.tsushinkb.3 keyboard 0x0 32 + +;pce, Port 1, Tsushin Keyboard: 4 +pce.input.port1.tsushinkb.4 keyboard 0x0 33 + +;pce, Port 1, Tsushin Keyboard: 5 +pce.input.port1.tsushinkb.5 keyboard 0x0 34 + +;pce, Port 1, Tsushin Keyboard: 6 +pce.input.port1.tsushinkb.6 keyboard 0x0 35 + +;pce, Port 1, Tsushin Keyboard: 7 +pce.input.port1.tsushinkb.7 keyboard 0x0 36 + +;pce, Port 1, Tsushin Keyboard: 8 +pce.input.port1.tsushinkb.8 keyboard 0x0 37 + +;pce, Port 1, Tsushin Keyboard: 9 +pce.input.port1.tsushinkb.9 keyboard 0x0 38 + +;pce, Port 1, Tsushin Keyboard: a +pce.input.port1.tsushinkb.a keyboard 0x0 4 + +;pce, Port 1, Tsushin Keyboard: @ +pce.input.port1.tsushinkb.at keyboard 0x0 53 + +;pce, Port 1, Tsushin Keyboard: b +pce.input.port1.tsushinkb.b keyboard 0x0 5 + +;pce, Port 1, Tsushin Keyboard: backspace +pce.input.port1.tsushinkb.backspace keyboard 0x0 42 + +;pce, Port 1, Tsushin Keyboard: c +pce.input.port1.tsushinkb.c keyboard 0x0 6 + +;pce, Port 1, Tsushin Keyboard: Caps Lock +pce.input.port1.tsushinkb.caps_lock keyboard 0x0 57 + +;pce, Port 1, Tsushin Keyboard: ^ +pce.input.port1.tsushinkb.caret keyboard 0x0 46 + +;pce, Port 1, Tsushin Keyboard: clear +pce.input.port1.tsushinkb.clear keyboard 0x0 74 + +;pce, Port 1, Tsushin Keyboard: : +pce.input.port1.tsushinkb.colon keyboard 0x0 52 + +;pce, Port 1, Tsushin Keyboard: , +pce.input.port1.tsushinkb.comma keyboard 0x0 54 + +;pce, Port 1, Tsushin Keyboard: 変換 +pce.input.port1.tsushinkb.convert keyboard 0x0 230 + +;pce, Port 1, Tsushin Keyboard: Copy +pce.input.port1.tsushinkb.copy keyboard 0x0 70 + +;pce, Port 1, Tsushin Keyboard: CTRL/Control +pce.input.port1.tsushinkb.ctrl keyboard 0x0 224 + +;pce, Port 1, Tsushin Keyboard: d +pce.input.port1.tsushinkb.d keyboard 0x0 7 + +;pce, Port 1, Tsushin Keyboard: Delete +pce.input.port1.tsushinkb.delete keyboard 0x0 76 + +;pce, Port 1, Tsushin Keyboard: down +pce.input.port1.tsushinkb.down keyboard 0x0 81 + +;pce, Port 1, Tsushin Keyboard: e +pce.input.port1.tsushinkb.e keyboard 0x0 8 + +;pce, Port 1, Tsushin Keyboard: Escape +pce.input.port1.tsushinkb.escape keyboard 0x0 41 + +;pce, Port 1, Tsushin Keyboard: f +pce.input.port1.tsushinkb.f keyboard 0x0 9 + +;pce, Port 1, Tsushin Keyboard: F1 +pce.input.port1.tsushinkb.f1 keyboard 0x0 58 + +;pce, Port 1, Tsushin Keyboard: F10 +pce.input.port1.tsushinkb.f10 keyboard 0x0 67 + +;pce, Port 1, Tsushin Keyboard: F2 +pce.input.port1.tsushinkb.f2 keyboard 0x0 59 + +;pce, Port 1, Tsushin Keyboard: F3 +pce.input.port1.tsushinkb.f3 keyboard 0x0 60 + +;pce, Port 1, Tsushin Keyboard: F4 +pce.input.port1.tsushinkb.f4 keyboard 0x0 61 + +;pce, Port 1, Tsushin Keyboard: F5 +pce.input.port1.tsushinkb.f5 keyboard 0x0 62 + +;pce, Port 1, Tsushin Keyboard: f6 +pce.input.port1.tsushinkb.f6 keyboard 0x0 63 + +;pce, Port 1, Tsushin Keyboard: f7 +pce.input.port1.tsushinkb.f7 keyboard 0x0 64 + +;pce, Port 1, Tsushin Keyboard: f8 +pce.input.port1.tsushinkb.f8 keyboard 0x0 65 + +;pce, Port 1, Tsushin Keyboard: f9 +pce.input.port1.tsushinkb.f9 keyboard 0x0 66 + +;pce, Port 1, Tsushin Keyboard: g +pce.input.port1.tsushinkb.g keyboard 0x0 10 + +;pce, Port 1, Tsushin Keyboard: GRPH +pce.input.port1.tsushinkb.grph keyboard 0x0 0 + +;pce, Port 1, Tsushin Keyboard: h +pce.input.port1.tsushinkb.h keyboard 0x0 11 + +;pce, Port 1, Tsushin Keyboard: Help +pce.input.port1.tsushinkb.help keyboard 0x0 77 + +;pce, Port 1, Tsushin Keyboard: i +pce.input.port1.tsushinkb.i keyboard 0x0 12 + +;pce, Port 1, Tsushin Keyboard: insert +pce.input.port1.tsushinkb.insert keyboard 0x0 73 + +;pce, Port 1, Tsushin Keyboard: j +pce.input.port1.tsushinkb.j keyboard 0x0 13 + +;pce, Port 1, Tsushin Keyboard: k +pce.input.port1.tsushinkb.k keyboard 0x0 14 + +;pce, Port 1, Tsushin Keyboard: カナ +pce.input.port1.tsushinkb.kana keyboard 0x0 227 + +;pce, Port 1, Tsushin Keyboard: Keypad 0 +pce.input.port1.tsushinkb.kp_0 keyboard 0x0 98 + +;pce, Port 1, Tsushin Keyboard: Keypad 1 +pce.input.port1.tsushinkb.kp_1 keyboard 0x0 89 + +;pce, Port 1, Tsushin Keyboard: Keypad 2 +pce.input.port1.tsushinkb.kp_2 keyboard 0x0 90 + +;pce, Port 1, Tsushin Keyboard: Keypad 3 +pce.input.port1.tsushinkb.kp_3 keyboard 0x0 91 + +;pce, Port 1, Tsushin Keyboard: Keypad 4 +pce.input.port1.tsushinkb.kp_4 keyboard 0x0 92 + +;pce, Port 1, Tsushin Keyboard: Keypad 5 +pce.input.port1.tsushinkb.kp_5 keyboard 0x0 93 + +;pce, Port 1, Tsushin Keyboard: Keypad 6 +pce.input.port1.tsushinkb.kp_6 keyboard 0x0 94 + +;pce, Port 1, Tsushin Keyboard: Keypad 7 +pce.input.port1.tsushinkb.kp_7 keyboard 0x0 95 + +;pce, Port 1, Tsushin Keyboard: Keypad 8 +pce.input.port1.tsushinkb.kp_8 keyboard 0x0 96 + +;pce, Port 1, Tsushin Keyboard: Keypad 9 +pce.input.port1.tsushinkb.kp_9 keyboard 0x0 97 + +;pce, Port 1, Tsushin Keyboard: Keypad , +pce.input.port1.tsushinkb.kp_comma keyboard 0x0 0 + +;pce, Port 1, Tsushin Keyboard: Keypad Divide +pce.input.port1.tsushinkb.kp_divide keyboard 0x0 84 + +;pce, Port 1, Tsushin Keyboard: Keypad Enter +pce.input.port1.tsushinkb.kp_enter keyboard 0x0 88 + +;pce, Port 1, Tsushin Keyboard: Keypad = +pce.input.port1.tsushinkb.kp_equals keyboard 0x0 103 + +;pce, Port 1, Tsushin Keyboard: Keypad Minus +pce.input.port1.tsushinkb.kp_minus keyboard 0x0 86 + +;pce, Port 1, Tsushin Keyboard: Keypad * +pce.input.port1.tsushinkb.kp_multiply keyboard 0x0 85 + +;pce, Port 1, Tsushin Keyboard: Keypad . +pce.input.port1.tsushinkb.kp_period keyboard 0x0 99 + +;pce, Port 1, Tsushin Keyboard: Keypad + +pce.input.port1.tsushinkb.kp_plus keyboard 0x0 87 + +;pce, Port 1, Tsushin Keyboard: l +pce.input.port1.tsushinkb.l keyboard 0x0 15 + +;pce, Port 1, Tsushin Keyboard: left +pce.input.port1.tsushinkb.left keyboard 0x0 80 + +;pce, Port 1, Tsushin Keyboard: [ +pce.input.port1.tsushinkb.left_bracket keyboard 0x0 47 + +;pce, Port 1, Tsushin Keyboard: Left Shift +pce.input.port1.tsushinkb.left_shift keyboard 0x0 225 + +;pce, Port 1, Tsushin Keyboard: m +pce.input.port1.tsushinkb.m keyboard 0x0 16 + +;pce, Port 1, Tsushin Keyboard: Minus +pce.input.port1.tsushinkb.minus keyboard 0x0 45 + +;pce, Port 1, Tsushin Keyboard: n +pce.input.port1.tsushinkb.n keyboard 0x0 17 + +;pce, Port 1, Tsushin Keyboard: 決定 +pce.input.port1.tsushinkb.nonconvert keyboard 0x0 226 + +;pce, Port 1, Tsushin Keyboard: o +pce.input.port1.tsushinkb.o keyboard 0x0 18 + +;pce, Port 1, Tsushin Keyboard: p +pce.input.port1.tsushinkb.p keyboard 0x0 19 + +;pce, Port 1, Tsushin Keyboard: PC +pce.input.port1.tsushinkb.pc keyboard 0x0 231 + +;pce, Port 1, Tsushin Keyboard: . +pce.input.port1.tsushinkb.period keyboard 0x0 55 + +;pce, Port 1, Tsushin Keyboard: q +pce.input.port1.tsushinkb.q keyboard 0x0 20 + +;pce, Port 1, Tsushin Keyboard: r +pce.input.port1.tsushinkb.r keyboard 0x0 21 + +;pce, Port 1, Tsushin Keyboard: return +pce.input.port1.tsushinkb.return keyboard 0x0 40 + +;pce, Port 1, Tsushin Keyboard: right +pce.input.port1.tsushinkb.right keyboard 0x0 79 + +;pce, Port 1, Tsushin Keyboard: ] +pce.input.port1.tsushinkb.right_bracket keyboard 0x0 48 + +;pce, Port 1, Tsushin Keyboard: Right Shift +pce.input.port1.tsushinkb.right_shift keyboard 0x0 229 + +;pce, Port 1, Tsushin Keyboard: ROLL DOWN +pce.input.port1.tsushinkb.roll_down keyboard 0x0 78 + +;pce, Port 1, Tsushin Keyboard: ROLL UP +pce.input.port1.tsushinkb.roll_up keyboard 0x0 75 + +;pce, Port 1, Tsushin Keyboard: s +pce.input.port1.tsushinkb.s keyboard 0x0 22 + +;pce, Port 1, Tsushin Keyboard: ; +pce.input.port1.tsushinkb.semicolon keyboard 0x0 51 + +;pce, Port 1, Tsushin Keyboard: / +pce.input.port1.tsushinkb.slash keyboard 0x0 56 + +;pce, Port 1, Tsushin Keyboard: space +pce.input.port1.tsushinkb.space keyboard 0x0 44 + +;pce, Port 1, Tsushin Keyboard: STOP +pce.input.port1.tsushinkb.stop keyboard 0x0 72 + +;pce, Port 1, Tsushin Keyboard: t +pce.input.port1.tsushinkb.t keyboard 0x0 23 + +;pce, Port 1, Tsushin Keyboard: Tab +pce.input.port1.tsushinkb.tab keyboard 0x0 43 + +;pce, Port 1, Tsushin Keyboard: u +pce.input.port1.tsushinkb.u keyboard 0x0 24 + +;pce, Port 1, Tsushin Keyboard: Underscore +pce.input.port1.tsushinkb.underscore keyboard 0x0 0 + +;pce, Port 1, Tsushin Keyboard: up +pce.input.port1.tsushinkb.up keyboard 0x0 82 + +;pce, Port 1, Tsushin Keyboard: v +pce.input.port1.tsushinkb.v keyboard 0x0 25 + +;pce, Port 1, Tsushin Keyboard: w +pce.input.port1.tsushinkb.w keyboard 0x0 26 + +;pce, Port 1, Tsushin Keyboard: 変換 +pce.input.port1.tsushinkb.width keyboard 0x0 228 + +;pce, Port 1, Tsushin Keyboard: x +pce.input.port1.tsushinkb.x keyboard 0x0 27 + +;pce, Port 1, Tsushin Keyboard: y +pce.input.port1.tsushinkb.y keyboard 0x0 28 + +;pce, Port 1, Tsushin Keyboard: Yen +pce.input.port1.tsushinkb.yen keyboard 0x0 46 + +;pce, Port 1, Tsushin Keyboard: z +pce.input.port1.tsushinkb.z keyboard 0x0 29 + +;Input device for Port 2 +pce.input.port2 gamepad + +;pce, Port 2, Gamepad: DOWN ↓ +pce.input.port2.gamepad.down + +;pce, Port 2, Gamepad: I +pce.input.port2.gamepad.i + +;pce, Port 2, Gamepad: II +pce.input.port2.gamepad.ii + +;pce, Port 2, Gamepad: III +pce.input.port2.gamepad.iii + +;pce, Port 2, Gamepad: IV +pce.input.port2.gamepad.iv + +;pce, Port 2, Gamepad: LEFT ← +pce.input.port2.gamepad.left + +;pce, Port 2, Gamepad: Mode +pce.input.port2.gamepad.mode_select + +;Default position for switch "Mode". +pce.input.port2.gamepad.mode_select.defpos 2 + +;pce, Port 2, Gamepad: Rapid I +pce.input.port2.gamepad.rapid_i + +;pce, Port 2, Gamepad: Rapid II +pce.input.port2.gamepad.rapid_ii + +;pce, Port 2, Gamepad: RIGHT → +pce.input.port2.gamepad.right + +;pce, Port 2, Gamepad: RUN +pce.input.port2.gamepad.run + +;pce, Port 2, Gamepad: SELECT +pce.input.port2.gamepad.select + +;pce, Port 2, Gamepad: UP ↑ +pce.input.port2.gamepad.up + +;pce, Port 2, Gamepad: V +pce.input.port2.gamepad.v + +;pce, Port 2, Gamepad: VI +pce.input.port2.gamepad.vi + +;pce, Port 2, Mouse: Left Button +pce.input.port2.mouse.left mouse 0x0 button_left + +;pce, Port 2, Mouse: Motion Down +pce.input.port2.mouse.motion_down mouse 0x0 rel_y+ + +;pce, Port 2, Mouse: Motion Left +pce.input.port2.mouse.motion_left mouse 0x0 rel_x- + +;pce, Port 2, Mouse: Motion Right +pce.input.port2.mouse.motion_right mouse 0x0 rel_x+ + +;pce, Port 2, Mouse: Motion Up +pce.input.port2.mouse.motion_up mouse 0x0 rel_y- + +;pce, Port 2, Mouse: Right Button +pce.input.port2.mouse.right mouse 0x0 button_right + +;pce, Port 2, Mouse: RUN +pce.input.port2.mouse.run keyboard 0x0 40 + +;pce, Port 2, Mouse: SELECT +pce.input.port2.mouse.select keyboard 0x0 43 + +;Input device for Port 3 +pce.input.port3 gamepad + +;pce, Port 3, Gamepad: DOWN ↓ +pce.input.port3.gamepad.down + +;pce, Port 3, Gamepad: I +pce.input.port3.gamepad.i + +;pce, Port 3, Gamepad: II +pce.input.port3.gamepad.ii + +;pce, Port 3, Gamepad: III +pce.input.port3.gamepad.iii + +;pce, Port 3, Gamepad: IV +pce.input.port3.gamepad.iv + +;pce, Port 3, Gamepad: LEFT ← +pce.input.port3.gamepad.left + +;pce, Port 3, Gamepad: Mode +pce.input.port3.gamepad.mode_select + +;Default position for switch "Mode". +pce.input.port3.gamepad.mode_select.defpos 2 + +;pce, Port 3, Gamepad: Rapid I +pce.input.port3.gamepad.rapid_i + +;pce, Port 3, Gamepad: Rapid II +pce.input.port3.gamepad.rapid_ii + +;pce, Port 3, Gamepad: RIGHT → +pce.input.port3.gamepad.right + +;pce, Port 3, Gamepad: RUN +pce.input.port3.gamepad.run + +;pce, Port 3, Gamepad: SELECT +pce.input.port3.gamepad.select + +;pce, Port 3, Gamepad: UP ↑ +pce.input.port3.gamepad.up + +;pce, Port 3, Gamepad: V +pce.input.port3.gamepad.v + +;pce, Port 3, Gamepad: VI +pce.input.port3.gamepad.vi + +;pce, Port 3, Mouse: Left Button +pce.input.port3.mouse.left mouse 0x0 button_left + +;pce, Port 3, Mouse: Motion Down +pce.input.port3.mouse.motion_down mouse 0x0 rel_y+ + +;pce, Port 3, Mouse: Motion Left +pce.input.port3.mouse.motion_left mouse 0x0 rel_x- + +;pce, Port 3, Mouse: Motion Right +pce.input.port3.mouse.motion_right mouse 0x0 rel_x+ + +;pce, Port 3, Mouse: Motion Up +pce.input.port3.mouse.motion_up mouse 0x0 rel_y- + +;pce, Port 3, Mouse: Right Button +pce.input.port3.mouse.right mouse 0x0 button_right + +;pce, Port 3, Mouse: RUN +pce.input.port3.mouse.run keyboard 0x0 40 + +;pce, Port 3, Mouse: SELECT +pce.input.port3.mouse.select keyboard 0x0 43 + +;Input device for Port 4 +pce.input.port4 gamepad + +;pce, Port 4, Gamepad: DOWN ↓ +pce.input.port4.gamepad.down + +;pce, Port 4, Gamepad: I +pce.input.port4.gamepad.i + +;pce, Port 4, Gamepad: II +pce.input.port4.gamepad.ii + +;pce, Port 4, Gamepad: III +pce.input.port4.gamepad.iii + +;pce, Port 4, Gamepad: IV +pce.input.port4.gamepad.iv + +;pce, Port 4, Gamepad: LEFT ← +pce.input.port4.gamepad.left + +;pce, Port 4, Gamepad: Mode +pce.input.port4.gamepad.mode_select + +;Default position for switch "Mode". +pce.input.port4.gamepad.mode_select.defpos 2 + +;pce, Port 4, Gamepad: Rapid I +pce.input.port4.gamepad.rapid_i + +;pce, Port 4, Gamepad: Rapid II +pce.input.port4.gamepad.rapid_ii + +;pce, Port 4, Gamepad: RIGHT → +pce.input.port4.gamepad.right + +;pce, Port 4, Gamepad: RUN +pce.input.port4.gamepad.run + +;pce, Port 4, Gamepad: SELECT +pce.input.port4.gamepad.select + +;pce, Port 4, Gamepad: UP ↑ +pce.input.port4.gamepad.up + +;pce, Port 4, Gamepad: V +pce.input.port4.gamepad.v + +;pce, Port 4, Gamepad: VI +pce.input.port4.gamepad.vi + +;pce, Port 4, Mouse: Left Button +pce.input.port4.mouse.left mouse 0x0 button_left + +;pce, Port 4, Mouse: Motion Down +pce.input.port4.mouse.motion_down mouse 0x0 rel_y+ + +;pce, Port 4, Mouse: Motion Left +pce.input.port4.mouse.motion_left mouse 0x0 rel_x- + +;pce, Port 4, Mouse: Motion Right +pce.input.port4.mouse.motion_right mouse 0x0 rel_x+ + +;pce, Port 4, Mouse: Motion Up +pce.input.port4.mouse.motion_up mouse 0x0 rel_y- + +;pce, Port 4, Mouse: Right Button +pce.input.port4.mouse.right mouse 0x0 button_right + +;pce, Port 4, Mouse: RUN +pce.input.port4.mouse.run keyboard 0x0 40 + +;pce, Port 4, Mouse: SELECT +pce.input.port4.mouse.select keyboard 0x0 43 + +;Input device for Port 5 +pce.input.port5 gamepad + +;pce, Port 5, Gamepad: DOWN ↓ +pce.input.port5.gamepad.down + +;pce, Port 5, Gamepad: I +pce.input.port5.gamepad.i + +;pce, Port 5, Gamepad: II +pce.input.port5.gamepad.ii + +;pce, Port 5, Gamepad: III +pce.input.port5.gamepad.iii + +;pce, Port 5, Gamepad: IV +pce.input.port5.gamepad.iv + +;pce, Port 5, Gamepad: LEFT ← +pce.input.port5.gamepad.left + +;pce, Port 5, Gamepad: Mode +pce.input.port5.gamepad.mode_select + +;Default position for switch "Mode". +pce.input.port5.gamepad.mode_select.defpos 2 + +;pce, Port 5, Gamepad: Rapid I +pce.input.port5.gamepad.rapid_i + +;pce, Port 5, Gamepad: Rapid II +pce.input.port5.gamepad.rapid_ii + +;pce, Port 5, Gamepad: RIGHT → +pce.input.port5.gamepad.right + +;pce, Port 5, Gamepad: RUN +pce.input.port5.gamepad.run + +;pce, Port 5, Gamepad: SELECT +pce.input.port5.gamepad.select + +;pce, Port 5, Gamepad: UP ↑ +pce.input.port5.gamepad.up + +;pce, Port 5, Gamepad: V +pce.input.port5.gamepad.v + +;pce, Port 5, Gamepad: VI +pce.input.port5.gamepad.vi + +;pce, Port 5, Mouse: Left Button +pce.input.port5.mouse.left mouse 0x0 button_left + +;pce, Port 5, Mouse: Motion Down +pce.input.port5.mouse.motion_down mouse 0x0 rel_y+ + +;pce, Port 5, Mouse: Motion Left +pce.input.port5.mouse.motion_left mouse 0x0 rel_x- + +;pce, Port 5, Mouse: Motion Right +pce.input.port5.mouse.motion_right mouse 0x0 rel_x+ + +;pce, Port 5, Mouse: Motion Up +pce.input.port5.mouse.motion_up mouse 0x0 rel_y- + +;pce, Port 5, Mouse: Right Button +pce.input.port5.mouse.right mouse 0x0 button_right + +;pce, Port 5, Mouse: RUN +pce.input.port5.mouse.run keyboard 0x0 40 + +;pce, Port 5, Mouse: SELECT +pce.input.port5.mouse.select keyboard 0x0 43 + +;Emulated mouse sensitivity. +pce.mouse_sensitivity 0.50 + +;Remove 16-sprites-per-scanline hardware limit. +pce.nospritelimit 0 + +;Select PSG revision. +pce.psgrevision match + +;Sound quality. +pce.resamp_quality 3 + +;Sound output rate tolerance. +pce.resamp_rate_error 0.0000009 + +;Enable scanlines with specified opacity. +pce.scanlines 0 + +;Enable specified OpenGL shader. +pce.shader ipsharper + +;Force interlaced video to be treated as progressive. +pce.shader.goat.fprog 0 + +;Constant RGB horizontal divergence. +pce.shader.goat.hdiv 0.50 + +;Mask pattern. +pce.shader.goat.pat goatron + +;Enable scanlines effect. +pce.shader.goat.slen 1 + +;Transparency of otherwise-opaque mask areas. +pce.shader.goat.tp 0.50 + +;Constant RGB vertical divergence. +pce.shader.goat.vdiv 0.50 + +;Last rendered scanline. +pce.slend 235 + +;First rendered scanline. +pce.slstart 4 + +;Enable specified special video scaler. +pce.special none + +;Stretch to fill screen. +pce.stretch full + +;Enable video temporal blur(50/50 previous/current frame by default). +pce.tblur 0 + +;Accumulate color data rather than discarding it. +pce.tblur.accum 0 + +;Blur amount in accumulation mode, specified in percentage of accumulation buffer to mix with the current frame. +pce.tblur.accum.amount 50 + +;Enable (bi)linear interpolation. +pce.videoip 0 + +;Size of emulated VRAM per VDC in 16-bit words. DO NOT CHANGE THIS UNLESS YOU KNOW WTF YOU ARE DOING. +pce.vramsize 32768 + +;Full-screen horizontal resolution. +pce.xres 0 + +;Scaling factor for the X axis in windowed mode. +pce.xscale 3.000000 + +;Scaling factor for the X axis in fullscreen mode. +pce.xscalefs 1.000000 + +;Full-screen vertical resolution. +pce.yres 0 + +;Scaling factor for the Y axis in windowed mode. +pce.yscale 3.000000 + +;Scaling factor for the Y axis in fullscreen mode. +pce.yscalefs 1.000000 + +;Enable dynamic ADPCM lowpass filter. +pce_fast.adpcmlp 0 + +;ADPCM volume. +pce_fast.adpcmvolume 100 + +;Enable Arcade Card emulation. +pce_fast.arcadecard 1 + +;Path to the CD BIOS +pce_fast.cdbios syscard3.pce + +;CD-DA volume. +pce_fast.cddavolume 100 + +;PSG volume when playing a CD game. +pce_fast.cdpsgvolume 100 + +;CD-ROM data transfer speed multiplier. +pce_fast.cdspeed 1 + +;Correct the aspect ratio. +pce_fast.correct_aspect 1 + +;If set, when RUN+SEL are pressed simultaneously, disable both buttons temporarily. +pce_fast.disable_softreset 0 + +;Enable (automatic) usage of this module. +pce_fast.enable 1 + +;Force monophonic sound output. +pce_fast.forcemono 0 + +;Force SuperGrafx emulation. +pce_fast.forcesgx 0 + +;Input device for Port 1 +pce_fast.input.port1 gamepad + +;pce_fast, Port 1, Gamepad: DOWN ↓ +pce_fast.input.port1.gamepad.down joystick @GUID1@ @DEVICE_BTN_DPAD_DOWN@ + +;pce_fast, Port 1, Gamepad: I +pce_fast.input.port1.gamepad.i joystick @GUID1@ @DEVICE_BTN_EAST@ + +;pce_fast, Port 1, Gamepad: II +pce_fast.input.port1.gamepad.ii joystick @GUID1@ @DEVICE_BTN_SOUTH@ + +;pce_fast, Port 1, Gamepad: III +pce_fast.input.port1.gamepad.iii joystick @GUID1@ @DEVICE_BTN_WEST@ + +;pce_fast, Port 1, Gamepad: IV +pce_fast.input.port1.gamepad.iv joystick @GUID1@ @DEVICE_BTN_NORTH@ + +;pce_fast, Port 1, Gamepad: LEFT ← +pce_fast.input.port1.gamepad.left joystick @GUID1@ @DEVICE_BTN_DPAD_LEFT@ + +;pce_fast, Port 1, Gamepad: Mode +pce_fast.input.port1.gamepad.mode_select keyboard 0x0 20 + +;Default position for switch "Mode". +pce_fast.input.port1.gamepad.mode_select.defpos 2 + +;pce_fast, Port 1, Gamepad: Rapid I +pce_fast.input.port1.gamepad.rapid_i keyboard 0x0 17 + +;pce_fast, Port 1, Gamepad: Rapid II +pce_fast.input.port1.gamepad.rapid_ii keyboard 0x0 17 + +;pce_fast, Port 1, Gamepad: RIGHT → +pce_fast.input.port1.gamepad.right joystick @GUID1@ @DEVICE_BTN_DPAD_RIGHT@ + +;pce_fast, Port 1, Gamepad: RUN +pce_fast.input.port1.gamepad.run joystick @GUID1@ @DEVICE_BTN_START@ + +;pce_fast, Port 1, Gamepad: SELECT +pce_fast.input.port1.gamepad.select joystick @GUID1@ @DEVICE_BTN_SELECT@ + +;pce_fast, Port 1, Gamepad: UP ↑ +pce_fast.input.port1.gamepad.up joystick @GUID1@ @DEVICE_BTN_DPAD_UP@ + +;pce_fast, Port 1, Gamepad: V +pce_fast.input.port1.gamepad.v joystick @GUID1@ @DEVICE_BTN_TL@ + +;pce_fast, Port 1, Gamepad: VI +pce_fast.input.port1.gamepad.vi joystick @GUID1@ @DEVICE_BTN_TR@ + +;pce_fast, Port 1, Mouse: Left Button +pce_fast.input.port1.mouse.left mouse 0x0 button_left + +;pce_fast, Port 1, Mouse: Motion Down +pce_fast.input.port1.mouse.motion_down mouse 0x0 rel_y+ + +;pce_fast, Port 1, Mouse: Motion Left +pce_fast.input.port1.mouse.motion_left mouse 0x0 rel_x- + +;pce_fast, Port 1, Mouse: Motion Right +pce_fast.input.port1.mouse.motion_right mouse 0x0 rel_x+ + +;pce_fast, Port 1, Mouse: Motion Up +pce_fast.input.port1.mouse.motion_up mouse 0x0 rel_y- + +;pce_fast, Port 1, Mouse: Right Button +pce_fast.input.port1.mouse.right mouse 0x0 button_right + +;pce_fast, Port 1, Mouse: RUN +pce_fast.input.port1.mouse.run keyboard 0x0 40 + +;pce_fast, Port 1, Mouse: SELECT +pce_fast.input.port1.mouse.select keyboard 0x0 43 + +;Input device for Port 2 +pce_fast.input.port2 gamepad + +;pce_fast, Port 2, Gamepad: DOWN ↓ +pce_fast.input.port2.gamepad.down + +;pce_fast, Port 2, Gamepad: I +pce_fast.input.port2.gamepad.i + +;pce_fast, Port 2, Gamepad: II +pce_fast.input.port2.gamepad.ii + +;pce_fast, Port 2, Gamepad: III +pce_fast.input.port2.gamepad.iii + +;pce_fast, Port 2, Gamepad: IV +pce_fast.input.port2.gamepad.iv + +;pce_fast, Port 2, Gamepad: LEFT ← +pce_fast.input.port2.gamepad.left + +;pce_fast, Port 2, Gamepad: Mode +pce_fast.input.port2.gamepad.mode_select + +;Default position for switch "Mode". +pce_fast.input.port2.gamepad.mode_select.defpos 2 + +;pce_fast, Port 2, Gamepad: Rapid I +pce_fast.input.port2.gamepad.rapid_i + +;pce_fast, Port 2, Gamepad: Rapid II +pce_fast.input.port2.gamepad.rapid_ii + +;pce_fast, Port 2, Gamepad: RIGHT → +pce_fast.input.port2.gamepad.right + +;pce_fast, Port 2, Gamepad: RUN +pce_fast.input.port2.gamepad.run + +;pce_fast, Port 2, Gamepad: SELECT +pce_fast.input.port2.gamepad.select + +;pce_fast, Port 2, Gamepad: UP ↑ +pce_fast.input.port2.gamepad.up + +;pce_fast, Port 2, Gamepad: V +pce_fast.input.port2.gamepad.v + +;pce_fast, Port 2, Gamepad: VI +pce_fast.input.port2.gamepad.vi + +;pce_fast, Port 2, Mouse: Left Button +pce_fast.input.port2.mouse.left mouse 0x0 button_left + +;pce_fast, Port 2, Mouse: Motion Down +pce_fast.input.port2.mouse.motion_down mouse 0x0 rel_y+ + +;pce_fast, Port 2, Mouse: Motion Left +pce_fast.input.port2.mouse.motion_left mouse 0x0 rel_x- + +;pce_fast, Port 2, Mouse: Motion Right +pce_fast.input.port2.mouse.motion_right mouse 0x0 rel_x+ + +;pce_fast, Port 2, Mouse: Motion Up +pce_fast.input.port2.mouse.motion_up mouse 0x0 rel_y- + +;pce_fast, Port 2, Mouse: Right Button +pce_fast.input.port2.mouse.right mouse 0x0 button_right + +;pce_fast, Port 2, Mouse: RUN +pce_fast.input.port2.mouse.run keyboard 0x0 40 + +;pce_fast, Port 2, Mouse: SELECT +pce_fast.input.port2.mouse.select keyboard 0x0 43 + +;Input device for Port 3 +pce_fast.input.port3 gamepad + +;pce_fast, Port 3, Gamepad: DOWN ↓ +pce_fast.input.port3.gamepad.down + +;pce_fast, Port 3, Gamepad: I +pce_fast.input.port3.gamepad.i + +;pce_fast, Port 3, Gamepad: II +pce_fast.input.port3.gamepad.ii + +;pce_fast, Port 3, Gamepad: III +pce_fast.input.port3.gamepad.iii + +;pce_fast, Port 3, Gamepad: IV +pce_fast.input.port3.gamepad.iv + +;pce_fast, Port 3, Gamepad: LEFT ← +pce_fast.input.port3.gamepad.left + +;pce_fast, Port 3, Gamepad: Mode +pce_fast.input.port3.gamepad.mode_select + +;Default position for switch "Mode". +pce_fast.input.port3.gamepad.mode_select.defpos 2 + +;pce_fast, Port 3, Gamepad: Rapid I +pce_fast.input.port3.gamepad.rapid_i + +;pce_fast, Port 3, Gamepad: Rapid II +pce_fast.input.port3.gamepad.rapid_ii + +;pce_fast, Port 3, Gamepad: RIGHT → +pce_fast.input.port3.gamepad.right + +;pce_fast, Port 3, Gamepad: RUN +pce_fast.input.port3.gamepad.run + +;pce_fast, Port 3, Gamepad: SELECT +pce_fast.input.port3.gamepad.select + +;pce_fast, Port 3, Gamepad: UP ↑ +pce_fast.input.port3.gamepad.up + +;pce_fast, Port 3, Gamepad: V +pce_fast.input.port3.gamepad.v + +;pce_fast, Port 3, Gamepad: VI +pce_fast.input.port3.gamepad.vi + +;pce_fast, Port 3, Mouse: Left Button +pce_fast.input.port3.mouse.left mouse 0x0 button_left + +;pce_fast, Port 3, Mouse: Motion Down +pce_fast.input.port3.mouse.motion_down mouse 0x0 rel_y+ + +;pce_fast, Port 3, Mouse: Motion Left +pce_fast.input.port3.mouse.motion_left mouse 0x0 rel_x- + +;pce_fast, Port 3, Mouse: Motion Right +pce_fast.input.port3.mouse.motion_right mouse 0x0 rel_x+ + +;pce_fast, Port 3, Mouse: Motion Up +pce_fast.input.port3.mouse.motion_up mouse 0x0 rel_y- + +;pce_fast, Port 3, Mouse: Right Button +pce_fast.input.port3.mouse.right mouse 0x0 button_right + +;pce_fast, Port 3, Mouse: RUN +pce_fast.input.port3.mouse.run keyboard 0x0 40 + +;pce_fast, Port 3, Mouse: SELECT +pce_fast.input.port3.mouse.select keyboard 0x0 43 + +;Input device for Port 4 +pce_fast.input.port4 gamepad + +;pce_fast, Port 4, Gamepad: DOWN ↓ +pce_fast.input.port4.gamepad.down + +;pce_fast, Port 4, Gamepad: I +pce_fast.input.port4.gamepad.i + +;pce_fast, Port 4, Gamepad: II +pce_fast.input.port4.gamepad.ii + +;pce_fast, Port 4, Gamepad: III +pce_fast.input.port4.gamepad.iii + +;pce_fast, Port 4, Gamepad: IV +pce_fast.input.port4.gamepad.iv + +;pce_fast, Port 4, Gamepad: LEFT ← +pce_fast.input.port4.gamepad.left + +;pce_fast, Port 4, Gamepad: Mode +pce_fast.input.port4.gamepad.mode_select + +;Default position for switch "Mode". +pce_fast.input.port4.gamepad.mode_select.defpos 2 + +;pce_fast, Port 4, Gamepad: Rapid I +pce_fast.input.port4.gamepad.rapid_i + +;pce_fast, Port 4, Gamepad: Rapid II +pce_fast.input.port4.gamepad.rapid_ii + +;pce_fast, Port 4, Gamepad: RIGHT → +pce_fast.input.port4.gamepad.right + +;pce_fast, Port 4, Gamepad: RUN +pce_fast.input.port4.gamepad.run + +;pce_fast, Port 4, Gamepad: SELECT +pce_fast.input.port4.gamepad.select + +;pce_fast, Port 4, Gamepad: UP ↑ +pce_fast.input.port4.gamepad.up + +;pce_fast, Port 4, Gamepad: V +pce_fast.input.port4.gamepad.v + +;pce_fast, Port 4, Gamepad: VI +pce_fast.input.port4.gamepad.vi + +;pce_fast, Port 4, Mouse: Left Button +pce_fast.input.port4.mouse.left mouse 0x0 button_left + +;pce_fast, Port 4, Mouse: Motion Down +pce_fast.input.port4.mouse.motion_down mouse 0x0 rel_y+ + +;pce_fast, Port 4, Mouse: Motion Left +pce_fast.input.port4.mouse.motion_left mouse 0x0 rel_x- + +;pce_fast, Port 4, Mouse: Motion Right +pce_fast.input.port4.mouse.motion_right mouse 0x0 rel_x+ + +;pce_fast, Port 4, Mouse: Motion Up +pce_fast.input.port4.mouse.motion_up mouse 0x0 rel_y- + +;pce_fast, Port 4, Mouse: Right Button +pce_fast.input.port4.mouse.right mouse 0x0 button_right + +;pce_fast, Port 4, Mouse: RUN +pce_fast.input.port4.mouse.run keyboard 0x0 40 + +;pce_fast, Port 4, Mouse: SELECT +pce_fast.input.port4.mouse.select keyboard 0x0 43 + +;Input device for Port 5 +pce_fast.input.port5 gamepad + +;pce_fast, Port 5, Gamepad: DOWN ↓ +pce_fast.input.port5.gamepad.down + +;pce_fast, Port 5, Gamepad: I +pce_fast.input.port5.gamepad.i + +;pce_fast, Port 5, Gamepad: II +pce_fast.input.port5.gamepad.ii + +;pce_fast, Port 5, Gamepad: III +pce_fast.input.port5.gamepad.iii + +;pce_fast, Port 5, Gamepad: IV +pce_fast.input.port5.gamepad.iv + +;pce_fast, Port 5, Gamepad: LEFT ← +pce_fast.input.port5.gamepad.left + +;pce_fast, Port 5, Gamepad: Mode +pce_fast.input.port5.gamepad.mode_select + +;Default position for switch "Mode". +pce_fast.input.port5.gamepad.mode_select.defpos 2 + +;pce_fast, Port 5, Gamepad: Rapid I +pce_fast.input.port5.gamepad.rapid_i + +;pce_fast, Port 5, Gamepad: Rapid II +pce_fast.input.port5.gamepad.rapid_ii + +;pce_fast, Port 5, Gamepad: RIGHT → +pce_fast.input.port5.gamepad.right + +;pce_fast, Port 5, Gamepad: RUN +pce_fast.input.port5.gamepad.run + +;pce_fast, Port 5, Gamepad: SELECT +pce_fast.input.port5.gamepad.select + +;pce_fast, Port 5, Gamepad: UP ↑ +pce_fast.input.port5.gamepad.up + +;pce_fast, Port 5, Gamepad: V +pce_fast.input.port5.gamepad.v + +;pce_fast, Port 5, Gamepad: VI +pce_fast.input.port5.gamepad.vi + +;pce_fast, Port 5, Mouse: Left Button +pce_fast.input.port5.mouse.left mouse 0x0 button_left + +;pce_fast, Port 5, Mouse: Motion Down +pce_fast.input.port5.mouse.motion_down mouse 0x0 rel_y+ + +;pce_fast, Port 5, Mouse: Motion Left +pce_fast.input.port5.mouse.motion_left mouse 0x0 rel_x- + +;pce_fast, Port 5, Mouse: Motion Right +pce_fast.input.port5.mouse.motion_right mouse 0x0 rel_x+ + +;pce_fast, Port 5, Mouse: Motion Up +pce_fast.input.port5.mouse.motion_up mouse 0x0 rel_y- + +;pce_fast, Port 5, Mouse: Right Button +pce_fast.input.port5.mouse.right mouse 0x0 button_right + +;pce_fast, Port 5, Mouse: RUN +pce_fast.input.port5.mouse.run keyboard 0x0 40 + +;pce_fast, Port 5, Mouse: SELECT +pce_fast.input.port5.mouse.select keyboard 0x0 43 + +;Mouse sensitivity. +pce_fast.mouse_sensitivity 0.50 + +;Remove 16-sprites-per-scanline hardware limit. +pce_fast.nospritelimit 1 + +;CPU overclock multiplier. +pce_fast.ocmultiplier 2 + +;Enable scanlines with specified opacity. +pce_fast.scanlines 0 + +;Enable specified OpenGL shader. +pce_fast.shader none + +;Force interlaced video to be treated as progressive. +pce_fast.shader.goat.fprog 0 + +;Constant RGB horizontal divergence. +pce_fast.shader.goat.hdiv 0.50 + +;Mask pattern. +pce_fast.shader.goat.pat goatron + +;Enable scanlines effect. +pce_fast.shader.goat.slen 1 + +;Transparency of otherwise-opaque mask areas. +pce_fast.shader.goat.tp 0.50 + +;Constant RGB vertical divergence. +pce_fast.shader.goat.vdiv 0.50 + +;Last rendered scanline. +pce_fast.slend 235 + +;First rendered scanline. +pce_fast.slstart 4 + +;Enable specified special video scaler. +pce_fast.special none + +;Stretch to fill screen. +pce_fast.stretch full + +;Enable video temporal blur(50/50 previous/current frame by default). +pce_fast.tblur 0 + +;Accumulate color data rather than discarding it. +pce_fast.tblur.accum 0 + +;Blur amount in accumulation mode, specified in percentage of accumulation buffer to mix with the current frame. +pce_fast.tblur.accum.amount 50 + +;Enable (bi)linear interpolation. +pce_fast.videoip 0 + +;Full-screen horizontal resolution. +pce_fast.xres 0 + +;Scaling factor for the X axis in windowed mode. +pce_fast.xscale 3.000000 + +;Scaling factor for the X axis in fullscreen mode. +pce_fast.xscalefs 1.000000 + +;Full-screen vertical resolution. +pce_fast.yres 0 + +;Scaling factor for the Y axis in windowed mode. +pce_fast.yscale 3.000000 + +;Scaling factor for the Y axis in fullscreen mode. +pce_fast.yscalefs 1.000000 + +;Hack that emulates the codec a buggy ADPCM encoder used for some games' ADPCM. +pcfx.adpcm.emulate_buggy_codec 0 + +;Hack to suppress clicks caused by forced channel resets. +pcfx.adpcm.suppress_channel_reset_clicks 1 + +;Path to the ROM BIOS +pcfx.bios pcfx.rom + +;Emulated CD-ROM speed. +pcfx.cdspeed 2 + +;CPU emulation mode. +pcfx.cpu_emulation auto + +;Disassembly font size. +pcfx.debugger.disfontsize 5x7 + +;Character encoding for the debugger's memory editor. +pcfx.debugger.memcharenc shift_jis + +;Disable internal and external BRAM. +pcfx.disable_bram 0 + +;When RUN+SEL are pressed simultaneously, disable both buttons temporarily. +pcfx.disable_softreset 0 + +;Enable (automatic) usage of this module. +pcfx.enable 1 + +;Force monophonic sound output. +pcfx.forcemono 0 + +;Path to the FX-SCSI ROM +pcfx.fxscsi 0 + +;Emulated width for 7.16MHz dot-clock mode. +pcfx.high_dotclock_width 1024 + +;Input device for Port 1 +pcfx.input.port1 gamepad + +;pcfx, Port 1, Gamepad: DOWN ↓ +pcfx.input.port1.gamepad.down joystick @GUID1@ @DEVICE_BTN_DPAD_DOWN@ + +;pcfx, Port 1, Gamepad: I +pcfx.input.port1.gamepad.i joystick @GUID1@ @DEVICE_BTN_EAST@ + +;pcfx, Port 1, Gamepad: II +pcfx.input.port1.gamepad.ii joystick @GUID1@ @DEVICE_BTN_SOUTH@ + +;pcfx, Port 1, Gamepad: III +pcfx.input.port1.gamepad.iii joystick @GUID1@ @DEVICE_BTN_NORTH@ + +;pcfx, Port 1, Gamepad: IV +pcfx.input.port1.gamepad.iv joystick @GUID1@ @DEVICE_BTN_WEST@ + +;pcfx, Port 1, Gamepad: LEFT ← +pcfx.input.port1.gamepad.left joystick @GUID1@ @DEVICE_BTN_DPAD_LEFT@ + +;pcfx, Port 1, Gamepad: MODE 1 +pcfx.input.port1.gamepad.mode1 joystick @GUID1@ @DEVICE_BTN_TL2@ + +;Default position for switch "MODE 1". +pcfx.input.port1.gamepad.mode1.defpos a + +;pcfx, Port 1, Gamepad: MODE 2 +pcfx.input.port1.gamepad.mode2 joystick @GUID1@ @DEVICE_BTN_TR2@ + +;Default position for switch "MODE 2". +pcfx.input.port1.gamepad.mode2.defpos a + +;pcfx, Port 1, Gamepad: RIGHT → +pcfx.input.port1.gamepad.right joystick @GUID1@ @DEVICE_BTN_DPAD_RIGHT@ + +;pcfx, Port 1, Gamepad: RUN +pcfx.input.port1.gamepad.run joystick @GUID1@ @DEVICE_BTN_START@ + +;pcfx, Port 1, Gamepad: SELECT +pcfx.input.port1.gamepad.select joystick @GUID1@ @DEVICE_BTN_SELECT@ + +;pcfx, Port 1, Gamepad: UP ↑ +pcfx.input.port1.gamepad.up joystick @GUID1@ @DEVICE_BTN_DPAD_UP@ + +;pcfx, Port 1, Gamepad: V +pcfx.input.port1.gamepad.v joystick @GUID1@ @DEVICE_BTN_TL@ + +;pcfx, Port 1, Gamepad: VI +pcfx.input.port1.gamepad.vi joystick @GUID1@ @DEVICE_BTN_TR@ + +;pcfx, Port 1, Mouse: Left Button +pcfx.input.port1.mouse.left mouse 0x0 button_left + +;pcfx, Port 1, Mouse: Motion Down +pcfx.input.port1.mouse.motion_down mouse 0x0 rel_y+ + +;pcfx, Port 1, Mouse: Motion Left +pcfx.input.port1.mouse.motion_left mouse 0x0 rel_x- + +;pcfx, Port 1, Mouse: Motion Right +pcfx.input.port1.mouse.motion_right mouse 0x0 rel_x+ + +;pcfx, Port 1, Mouse: Motion Up +pcfx.input.port1.mouse.motion_up mouse 0x0 rel_y- + +;pcfx, Port 1, Mouse: Right Button +pcfx.input.port1.mouse.right mouse 0x0 button_right + +;Enable multitap on PC-FX port 1. +pcfx.input.port1.multitap 0 + +;Input device for Port 2 +pcfx.input.port2 gamepad + +;pcfx, Port 2, Gamepad: DOWN ↓ +pcfx.input.port2.gamepad.down + +;pcfx, Port 2, Gamepad: I +pcfx.input.port2.gamepad.i + +;pcfx, Port 2, Gamepad: II +pcfx.input.port2.gamepad.ii + +;pcfx, Port 2, Gamepad: III +pcfx.input.port2.gamepad.iii + +;pcfx, Port 2, Gamepad: IV +pcfx.input.port2.gamepad.iv + +;pcfx, Port 2, Gamepad: LEFT ← +pcfx.input.port2.gamepad.left + +;pcfx, Port 2, Gamepad: MODE 1 +pcfx.input.port2.gamepad.mode1 + +;Default position for switch "MODE 1". +pcfx.input.port2.gamepad.mode1.defpos a + +;pcfx, Port 2, Gamepad: MODE 2 +pcfx.input.port2.gamepad.mode2 + +;Default position for switch "MODE 2". +pcfx.input.port2.gamepad.mode2.defpos a + +;pcfx, Port 2, Gamepad: RIGHT → +pcfx.input.port2.gamepad.right + +;pcfx, Port 2, Gamepad: RUN +pcfx.input.port2.gamepad.run + +;pcfx, Port 2, Gamepad: SELECT +pcfx.input.port2.gamepad.select + +;pcfx, Port 2, Gamepad: UP ↑ +pcfx.input.port2.gamepad.up + +;pcfx, Port 2, Gamepad: V +pcfx.input.port2.gamepad.v + +;pcfx, Port 2, Gamepad: VI +pcfx.input.port2.gamepad.vi + +;pcfx, Port 2, Mouse: Left Button +pcfx.input.port2.mouse.left mouse 0x0 button_left + +;pcfx, Port 2, Mouse: Motion Down +pcfx.input.port2.mouse.motion_down mouse 0x0 rel_y+ + +;pcfx, Port 2, Mouse: Motion Left +pcfx.input.port2.mouse.motion_left mouse 0x0 rel_x- + +;pcfx, Port 2, Mouse: Motion Right +pcfx.input.port2.mouse.motion_right mouse 0x0 rel_x+ + +;pcfx, Port 2, Mouse: Motion Up +pcfx.input.port2.mouse.motion_up mouse 0x0 rel_y- + +;pcfx, Port 2, Mouse: Right Button +pcfx.input.port2.mouse.right mouse 0x0 button_right + +;Enable multitap on PC-FX port 2. +pcfx.input.port2.multitap 0 + +;Input device for Port 3 +pcfx.input.port3 gamepad + +;pcfx, Port 3, Gamepad: DOWN ↓ +pcfx.input.port3.gamepad.down + +;pcfx, Port 3, Gamepad: I +pcfx.input.port3.gamepad.i + +;pcfx, Port 3, Gamepad: II +pcfx.input.port3.gamepad.ii + +;pcfx, Port 3, Gamepad: III +pcfx.input.port3.gamepad.iii + +;pcfx, Port 3, Gamepad: IV +pcfx.input.port3.gamepad.iv + +;pcfx, Port 3, Gamepad: LEFT ← +pcfx.input.port3.gamepad.left + +;pcfx, Port 3, Gamepad: MODE 1 +pcfx.input.port3.gamepad.mode1 + +;Default position for switch "MODE 1". +pcfx.input.port3.gamepad.mode1.defpos a + +;pcfx, Port 3, Gamepad: MODE 2 +pcfx.input.port3.gamepad.mode2 + +;Default position for switch "MODE 2". +pcfx.input.port3.gamepad.mode2.defpos a + +;pcfx, Port 3, Gamepad: RIGHT → +pcfx.input.port3.gamepad.right + +;pcfx, Port 3, Gamepad: RUN +pcfx.input.port3.gamepad.run + +;pcfx, Port 3, Gamepad: SELECT +pcfx.input.port3.gamepad.select + +;pcfx, Port 3, Gamepad: UP ↑ +pcfx.input.port3.gamepad.up + +;pcfx, Port 3, Gamepad: V +pcfx.input.port3.gamepad.v + +;pcfx, Port 3, Gamepad: VI +pcfx.input.port3.gamepad.vi + +;pcfx, Port 3, Mouse: Left Button +pcfx.input.port3.mouse.left mouse 0x0 button_left + +;pcfx, Port 3, Mouse: Motion Down +pcfx.input.port3.mouse.motion_down mouse 0x0 rel_y+ + +;pcfx, Port 3, Mouse: Motion Left +pcfx.input.port3.mouse.motion_left mouse 0x0 rel_x- + +;pcfx, Port 3, Mouse: Motion Right +pcfx.input.port3.mouse.motion_right mouse 0x0 rel_x+ + +;pcfx, Port 3, Mouse: Motion Up +pcfx.input.port3.mouse.motion_up mouse 0x0 rel_y- + +;pcfx, Port 3, Mouse: Right Button +pcfx.input.port3.mouse.right mouse 0x0 button_right + +;Input device for Port 4 +pcfx.input.port4 gamepad + +;pcfx, Port 4, Gamepad: DOWN ↓ +pcfx.input.port4.gamepad.down + +;pcfx, Port 4, Gamepad: I +pcfx.input.port4.gamepad.i + +;pcfx, Port 4, Gamepad: II +pcfx.input.port4.gamepad.ii + +;pcfx, Port 4, Gamepad: III +pcfx.input.port4.gamepad.iii + +;pcfx, Port 4, Gamepad: IV +pcfx.input.port4.gamepad.iv + +;pcfx, Port 4, Gamepad: LEFT ← +pcfx.input.port4.gamepad.left + +;pcfx, Port 4, Gamepad: MODE 1 +pcfx.input.port4.gamepad.mode1 + +;Default position for switch "MODE 1". +pcfx.input.port4.gamepad.mode1.defpos a + +;pcfx, Port 4, Gamepad: MODE 2 +pcfx.input.port4.gamepad.mode2 + +;Default position for switch "MODE 2". +pcfx.input.port4.gamepad.mode2.defpos a + +;pcfx, Port 4, Gamepad: RIGHT → +pcfx.input.port4.gamepad.right + +;pcfx, Port 4, Gamepad: RUN +pcfx.input.port4.gamepad.run + +;pcfx, Port 4, Gamepad: SELECT +pcfx.input.port4.gamepad.select + +;pcfx, Port 4, Gamepad: UP ↑ +pcfx.input.port4.gamepad.up + +;pcfx, Port 4, Gamepad: V +pcfx.input.port4.gamepad.v + +;pcfx, Port 4, Gamepad: VI +pcfx.input.port4.gamepad.vi + +;pcfx, Port 4, Mouse: Left Button +pcfx.input.port4.mouse.left mouse 0x0 button_left + +;pcfx, Port 4, Mouse: Motion Down +pcfx.input.port4.mouse.motion_down mouse 0x0 rel_y+ + +;pcfx, Port 4, Mouse: Motion Left +pcfx.input.port4.mouse.motion_left mouse 0x0 rel_x- + +;pcfx, Port 4, Mouse: Motion Right +pcfx.input.port4.mouse.motion_right mouse 0x0 rel_x+ + +;pcfx, Port 4, Mouse: Motion Up +pcfx.input.port4.mouse.motion_up mouse 0x0 rel_y- + +;pcfx, Port 4, Mouse: Right Button +pcfx.input.port4.mouse.right mouse 0x0 button_right + +;Input device for Port 5 +pcfx.input.port5 gamepad + +;pcfx, Port 5, Gamepad: DOWN ↓ +pcfx.input.port5.gamepad.down + +;pcfx, Port 5, Gamepad: I +pcfx.input.port5.gamepad.i + +;pcfx, Port 5, Gamepad: II +pcfx.input.port5.gamepad.ii + +;pcfx, Port 5, Gamepad: III +pcfx.input.port5.gamepad.iii + +;pcfx, Port 5, Gamepad: IV +pcfx.input.port5.gamepad.iv + +;pcfx, Port 5, Gamepad: LEFT ← +pcfx.input.port5.gamepad.left + +;pcfx, Port 5, Gamepad: MODE 1 +pcfx.input.port5.gamepad.mode1 + +;Default position for switch "MODE 1". +pcfx.input.port5.gamepad.mode1.defpos a + +;pcfx, Port 5, Gamepad: MODE 2 +pcfx.input.port5.gamepad.mode2 + +;Default position for switch "MODE 2". +pcfx.input.port5.gamepad.mode2.defpos a + +;pcfx, Port 5, Gamepad: RIGHT → +pcfx.input.port5.gamepad.right + +;pcfx, Port 5, Gamepad: RUN +pcfx.input.port5.gamepad.run + +;pcfx, Port 5, Gamepad: SELECT +pcfx.input.port5.gamepad.select + +;pcfx, Port 5, Gamepad: UP ↑ +pcfx.input.port5.gamepad.up + +;pcfx, Port 5, Gamepad: V +pcfx.input.port5.gamepad.v + +;pcfx, Port 5, Gamepad: VI +pcfx.input.port5.gamepad.vi + +;pcfx, Port 5, Mouse: Left Button +pcfx.input.port5.mouse.left mouse 0x0 button_left + +;pcfx, Port 5, Mouse: Motion Down +pcfx.input.port5.mouse.motion_down mouse 0x0 rel_y+ + +;pcfx, Port 5, Mouse: Motion Left +pcfx.input.port5.mouse.motion_left mouse 0x0 rel_x- + +;pcfx, Port 5, Mouse: Motion Right +pcfx.input.port5.mouse.motion_right mouse 0x0 rel_x+ + +;pcfx, Port 5, Mouse: Motion Up +pcfx.input.port5.mouse.motion_up mouse 0x0 rel_y- + +;pcfx, Port 5, Mouse: Right Button +pcfx.input.port5.mouse.right mouse 0x0 button_right + +;Input device for Port 6 +pcfx.input.port6 gamepad + +;pcfx, Port 6, Gamepad: DOWN ↓ +pcfx.input.port6.gamepad.down + +;pcfx, Port 6, Gamepad: I +pcfx.input.port6.gamepad.i + +;pcfx, Port 6, Gamepad: II +pcfx.input.port6.gamepad.ii + +;pcfx, Port 6, Gamepad: III +pcfx.input.port6.gamepad.iii + +;pcfx, Port 6, Gamepad: IV +pcfx.input.port6.gamepad.iv + +;pcfx, Port 6, Gamepad: LEFT ← +pcfx.input.port6.gamepad.left + +;pcfx, Port 6, Gamepad: MODE 1 +pcfx.input.port6.gamepad.mode1 + +;Default position for switch "MODE 1". +pcfx.input.port6.gamepad.mode1.defpos a + +;pcfx, Port 6, Gamepad: MODE 2 +pcfx.input.port6.gamepad.mode2 + +;Default position for switch "MODE 2". +pcfx.input.port6.gamepad.mode2.defpos a + +;pcfx, Port 6, Gamepad: RIGHT → +pcfx.input.port6.gamepad.right + +;pcfx, Port 6, Gamepad: RUN +pcfx.input.port6.gamepad.run + +;pcfx, Port 6, Gamepad: SELECT +pcfx.input.port6.gamepad.select + +;pcfx, Port 6, Gamepad: UP ↑ +pcfx.input.port6.gamepad.up + +;pcfx, Port 6, Gamepad: V +pcfx.input.port6.gamepad.v + +;pcfx, Port 6, Gamepad: VI +pcfx.input.port6.gamepad.vi + +;pcfx, Port 6, Mouse: Left Button +pcfx.input.port6.mouse.left mouse 0x0 button_left + +;pcfx, Port 6, Mouse: Motion Down +pcfx.input.port6.mouse.motion_down mouse 0x0 rel_y+ + +;pcfx, Port 6, Mouse: Motion Left +pcfx.input.port6.mouse.motion_left mouse 0x0 rel_x- + +;pcfx, Port 6, Mouse: Motion Right +pcfx.input.port6.mouse.motion_right mouse 0x0 rel_x+ + +;pcfx, Port 6, Mouse: Motion Up +pcfx.input.port6.mouse.motion_up mouse 0x0 rel_y- + +;pcfx, Port 6, Mouse: Right Button +pcfx.input.port6.mouse.right mouse 0x0 button_right + +;Input device for Port 7 +pcfx.input.port7 gamepad + +;pcfx, Port 7, Gamepad: DOWN ↓ +pcfx.input.port7.gamepad.down + +;pcfx, Port 7, Gamepad: I +pcfx.input.port7.gamepad.i + +;pcfx, Port 7, Gamepad: II +pcfx.input.port7.gamepad.ii + +;pcfx, Port 7, Gamepad: III +pcfx.input.port7.gamepad.iii + +;pcfx, Port 7, Gamepad: IV +pcfx.input.port7.gamepad.iv + +;pcfx, Port 7, Gamepad: LEFT ← +pcfx.input.port7.gamepad.left + +;pcfx, Port 7, Gamepad: MODE 1 +pcfx.input.port7.gamepad.mode1 + +;Default position for switch "MODE 1". +pcfx.input.port7.gamepad.mode1.defpos a + +;pcfx, Port 7, Gamepad: MODE 2 +pcfx.input.port7.gamepad.mode2 + +;Default position for switch "MODE 2". +pcfx.input.port7.gamepad.mode2.defpos a + +;pcfx, Port 7, Gamepad: RIGHT → +pcfx.input.port7.gamepad.right + +;pcfx, Port 7, Gamepad: RUN +pcfx.input.port7.gamepad.run + +;pcfx, Port 7, Gamepad: SELECT +pcfx.input.port7.gamepad.select + +;pcfx, Port 7, Gamepad: UP ↑ +pcfx.input.port7.gamepad.up + +;pcfx, Port 7, Gamepad: V +pcfx.input.port7.gamepad.v + +;pcfx, Port 7, Gamepad: VI +pcfx.input.port7.gamepad.vi + +;pcfx, Port 7, Mouse: Left Button +pcfx.input.port7.mouse.left mouse 0x0 button_left + +;pcfx, Port 7, Mouse: Motion Down +pcfx.input.port7.mouse.motion_down mouse 0x0 rel_y+ + +;pcfx, Port 7, Mouse: Motion Left +pcfx.input.port7.mouse.motion_left mouse 0x0 rel_x- + +;pcfx, Port 7, Mouse: Motion Right +pcfx.input.port7.mouse.motion_right mouse 0x0 rel_x+ + +;pcfx, Port 7, Mouse: Motion Up +pcfx.input.port7.mouse.motion_up mouse 0x0 rel_y- + +;pcfx, Port 7, Mouse: Right Button +pcfx.input.port7.mouse.right mouse 0x0 button_right + +;Input device for Port 8 +pcfx.input.port8 gamepad + +;pcfx, Port 8, Gamepad: DOWN ↓ +pcfx.input.port8.gamepad.down + +;pcfx, Port 8, Gamepad: I +pcfx.input.port8.gamepad.i + +;pcfx, Port 8, Gamepad: II +pcfx.input.port8.gamepad.ii + +;pcfx, Port 8, Gamepad: III +pcfx.input.port8.gamepad.iii + +;pcfx, Port 8, Gamepad: IV +pcfx.input.port8.gamepad.iv + +;pcfx, Port 8, Gamepad: LEFT ← +pcfx.input.port8.gamepad.left + +;pcfx, Port 8, Gamepad: MODE 1 +pcfx.input.port8.gamepad.mode1 + +;Default position for switch "MODE 1". +pcfx.input.port8.gamepad.mode1.defpos a + +;pcfx, Port 8, Gamepad: MODE 2 +pcfx.input.port8.gamepad.mode2 + +;Default position for switch "MODE 2". +pcfx.input.port8.gamepad.mode2.defpos a + +;pcfx, Port 8, Gamepad: RIGHT → +pcfx.input.port8.gamepad.right + +;pcfx, Port 8, Gamepad: RUN +pcfx.input.port8.gamepad.run + +;pcfx, Port 8, Gamepad: SELECT +pcfx.input.port8.gamepad.select + +;pcfx, Port 8, Gamepad: UP ↑ +pcfx.input.port8.gamepad.up + +;pcfx, Port 8, Gamepad: V +pcfx.input.port8.gamepad.v + +;pcfx, Port 8, Gamepad: VI +pcfx.input.port8.gamepad.vi + +;pcfx, Port 8, Mouse: Left Button +pcfx.input.port8.mouse.left mouse 0x0 button_left + +;pcfx, Port 8, Mouse: Motion Down +pcfx.input.port8.mouse.motion_down mouse 0x0 rel_y+ + +;pcfx, Port 8, Mouse: Motion Left +pcfx.input.port8.mouse.motion_left mouse 0x0 rel_x- + +;pcfx, Port 8, Mouse: Motion Right +pcfx.input.port8.mouse.motion_right mouse 0x0 rel_x+ + +;pcfx, Port 8, Mouse: Motion Up +pcfx.input.port8.mouse.motion_up mouse 0x0 rel_y- + +;pcfx, Port 8, Mouse: Right Button +pcfx.input.port8.mouse.right mouse 0x0 button_right + +;Mouse sensitivity. +pcfx.mouse_sensitivity 1.25 + +;Remove 16-sprites-per-scanline hardware limit. +pcfx.nospritelimit 0 + +;Enable bilinear interpolation on the chroma channel of RAINBOW YUV output. +pcfx.rainbow.chromaip 0 + +;Sound quality. +pcfx.resamp_quality 3 + +;Output rate tolerance. +pcfx.resamp_rate_error 0.0000009 + +;Enable scanlines with specified opacity. +pcfx.scanlines 0 + +;Enable specified OpenGL shader. +pcfx.shader ipsharper + +;Force interlaced video to be treated as progressive. +pcfx.shader.goat.fprog 0 + +;Constant RGB horizontal divergence. +pcfx.shader.goat.hdiv 0.50 + +;Mask pattern. +pcfx.shader.goat.pat goatron + +;Enable scanlines effect. +pcfx.shader.goat.slen 1 + +;Transparency of otherwise-opaque mask areas. +pcfx.shader.goat.tp 0.50 + +;Constant RGB vertical divergence. +pcfx.shader.goat.vdiv 0.50 + +;Last rendered scanline. +pcfx.slend 235 + +;First rendered scanline. +pcfx.slstart 4 + +;Enable specified special video scaler. +pcfx.special none + +;Stretch to fill screen. +pcfx.stretch full + +;Enable video temporal blur(50/50 previous/current frame by default). +pcfx.tblur 0 + +;Accumulate color data rather than discarding it. +pcfx.tblur.accum 0 + +;Blur amount in accumulation mode, specified in percentage of accumulation buffer to mix with the current frame. +pcfx.tblur.accum.amount 50 + +;Enable (bi)linear interpolation. +pcfx.videoip 0 + +;Full-screen horizontal resolution. +pcfx.xres 0 + +;Scaling factor for the X axis in windowed mode. +pcfx.xscale 3.000000 + +;Scaling factor for the X axis in fullscreen mode. +pcfx.xscalefs 1.000000 + +;Full-screen vertical resolution. +pcfx.yres 0 + +;Scaling factor for the Y axis in windowed mode. +pcfx.yscale 3.000000 + +;Scaling factor for the Y axis in fullscreen mode. +pcfx.yscalefs 1.000000 + +;Enable scanlines with specified opacity. +player.scanlines 0 + +;Enable specified OpenGL shader. +player.shader none + +;Force interlaced video to be treated as progressive. +player.shader.goat.fprog 0 + +;Constant RGB horizontal divergence. +player.shader.goat.hdiv 0.50 + +;Mask pattern. +player.shader.goat.pat goatron + +;Enable scanlines effect. +player.shader.goat.slen 1 + +;Transparency of otherwise-opaque mask areas. +player.shader.goat.tp 0.50 + +;Constant RGB vertical divergence. +player.shader.goat.vdiv 0.50 + +;Enable specified special video scaler. +player.special none + +;Stretch to fill screen. +player.stretch aspect + +;Enable (bi)linear interpolation. +player.videoip 0 + +;Full-screen horizontal resolution. +player.xres 0 + +;Scaling factor for the X axis in windowed mode. +player.xscale 2.000000 + +;Scaling factor for the X axis in fullscreen mode. +player.xscalefs 1.000000 + +;Full-screen vertical resolution. +player.yres 0 + +;Scaling factor for the Y axis in windowed mode. +player.yscale 2.000000 + +;Scaling factor for the Y axis in fullscreen mode. +player.yscalefs 1.000000 + +;Double the raw image's height if it's below this threshold. +qtrecord.h_double_threshold 256 + +;Video codec to use. +qtrecord.vcodec cscd + +;Double the raw image's width if it's below this threshold. +qtrecord.w_double_threshold 384 + +;SLOW-forwarding speed multiplier. +sfspeed 0.75 + +;Treat the SLOW-forward button as a toggle. +sftoggle 0 + +;Enable (automatic) usage of this module. +sms.enable 1 + +;Enable FM sound emulation when playing domestic/Japan-region games. +sms.fm 1 + +;Force monophonic sound output. +sms.forcemono 0 + +;sms, Port 1, Gamepad: DOWN ↓ +sms.input.port1.gamepad.down joystick @GUID1@ @DEVICE_BTN_DPAD_DOWN@ + +;sms, Port 1, Gamepad: Fire 1/Start +sms.input.port1.gamepad.fire1 joystick @GUID1@ @DEVICE_BTN_SOUTH@ + +;sms, Port 1, Gamepad: Fire 2 +sms.input.port1.gamepad.fire2 joystick @GUID1@ @DEVICE_BTN_EAST@ + +;sms, Port 1, Gamepad: LEFT ← +sms.input.port1.gamepad.left joystick @GUID1@ @DEVICE_BTN_DPAD_LEFT@ + +;sms, Port 1, Gamepad: Pause +sms.input.port1.gamepad.pause joystick @GUID1@ @DEVICE_BTN_START@ + +;sms, Port 1, Gamepad: Rapid Fire 1/Start +sms.input.port1.gamepad.rapid_fire1 joystick @GUID1@ @DEVICE_BTN_WEST@ + +;sms, Port 1, Gamepad: Rapid Fire 2 +sms.input.port1.gamepad.rapid_fire2 joystick @GUID1@ @DEVICE_BTN_NORTH@ + +;sms, Port 1, Gamepad: RIGHT → +sms.input.port1.gamepad.right joystick @GUID1@ @DEVICE_BTN_DPAD_RIGHT@ + +;sms, Port 1, Gamepad: UP ↑ +sms.input.port1.gamepad.up joystick @GUID1@ @DEVICE_BTN_DPAD_UP@ + +;sms, Port 2, Gamepad: DOWN ↓ +sms.input.port2.gamepad.down + +;sms, Port 2, Gamepad: Fire 1/Start +sms.input.port2.gamepad.fire1 + +;sms, Port 2, Gamepad: Fire 2 +sms.input.port2.gamepad.fire2 + +;sms, Port 2, Gamepad: LEFT ← +sms.input.port2.gamepad.left + +;sms, Port 2, Gamepad: Pause +sms.input.port2.gamepad.pause + +;sms, Port 2, Gamepad: Rapid Fire 1/Start +sms.input.port2.gamepad.rapid_fire1 + +;sms, Port 2, Gamepad: Rapid Fire 2 +sms.input.port2.gamepad.rapid_fire2 + +;sms, Port 2, Gamepad: RIGHT → +sms.input.port2.gamepad.right + +;sms, Port 2, Gamepad: UP ↑ +sms.input.port2.gamepad.up + +;Enable scanlines with specified opacity. +sms.scanlines 0 + +;Enable specified OpenGL shader. +sms.shader ipsharper + +;Force interlaced video to be treated as progressive. +sms.shader.goat.fprog 0 + +;Constant RGB horizontal divergence. +sms.shader.goat.hdiv 0.50 + +;Mask pattern. +sms.shader.goat.pat goatron + +;Enable scanlines effect. +sms.shader.goat.slen 1 + +;Transparency of otherwise-opaque mask areas. +sms.shader.goat.tp 0.50 + +;Constant RGB vertical divergence. +sms.shader.goat.vdiv 0.50 + +;Last displayed scanline in NTSC mode. +sms.slend 215 + +;Last displayed scanline in PAL mode. +sms.slendp 231 + +;First displayed scanline in NTSC mode. +sms.slstart 24 + +;First displayed scanline in PAL mode. +sms.slstartp 8 + +;Enable specified special video scaler. +sms.special none + +;Stretch to fill screen. +sms.stretch aspect + +;Enable video temporal blur(50/50 previous/current frame by default). +sms.tblur 0 + +;Accumulate color data rather than discarding it. +sms.tblur.accum 0 + +;Blur amount in accumulation mode, specified in percentage of accumulation buffer to mix with the current frame. +sms.tblur.accum.amount 50 + +;System territory/region. +sms.territory export + +;Enable (bi)linear interpolation. +sms.videoip 0 + +;Full-screen horizontal resolution. +sms.xres 0 + +;Scaling factor for the X axis in windowed mode. +sms.xscale 4.000000 + +;Scaling factor for the X axis in fullscreen mode. +sms.xscalefs 1.000000 + +;Full-screen vertical resolution. +sms.yres 0 + +;Scaling factor for the Y axis in windowed mode. +sms.yscale 4.000000 + +;Scaling factor for the Y axis in fullscreen mode. +sms.yscalefs 1.000000 + +;APU output resampler quality. +snes.apu.resamp_quality 5 + +;Correct the aspect ratio. +snes.correct_aspect 0 + +;Enable (automatic) usage of this module. +snes.enable 1 + +;Force monophonic sound output. +snes.forcemono 0 + +;Enable horizontal blend(blur) filter. +snes.h_blend 0 + +;Input device for Port 1/1A +snes.input.port1 gamepad + +;snes, Virtual Port 1/1A, Gamepad: A (right) +snes.input.port1.gamepad.a joystick @GUID1@ @DEVICE_BTN_EAST@ + +;snes, Virtual Port 1/1A, Gamepad: B (center, lower) +snes.input.port1.gamepad.b joystick @GUID1@ @DEVICE_BTN_SOUTH@ + +;snes, Virtual Port 1/1A, Gamepad: DOWN (down) +snes.input.port1.gamepad.down joystick @GUID1@ @DEVICE_BTN_DPAD_DOWN@ + +;snes, Virtual Port 1/1A, Gamepad: Left Shoulder +snes.input.port1.gamepad.l joystick @GUID1@ @DEVICE_BTN_TL@ + +;snes, Virtual Port 1/1A, Gamepad: LEFT (left) +snes.input.port1.gamepad.left joystick @GUID1@ @DEVICE_BTN_DPAD_LEFT@ + +;snes, Virtual Port 1/1A, Gamepad: Right Shoulder +snes.input.port1.gamepad.r joystick @GUID1@ @DEVICE_BTN_TR@ + +;snes, Virtual Port 1/1A, Gamepad: Rapid A (right) +snes.input.port1.gamepad.rapid_a keyboard 0x0 17 + +;snes, Virtual Port 1/1A, Gamepad: Rapid B (center, lower) +snes.input.port1.gamepad.rapid_b keyboard 0x0 17 + +;snes, Virtual Port 1/1A, Gamepad: Rapid X (center, upper) +snes.input.port1.gamepad.rapid_x keyboard 0x0 17 + +;snes, Virtual Port 1/1A, Gamepad: Rapid Y (left) +snes.input.port1.gamepad.rapid_y keyboard 0x0 17 + +;snes, Virtual Port 1/1A, Gamepad: RIGHT (right) +snes.input.port1.gamepad.right joystick @GUID1@ @DEVICE_BTN_DPAD_RIGHT@ + +;snes, Virtual Port 1/1A, Gamepad: SELECT +snes.input.port1.gamepad.select joystick @GUID1@ @DEVICE_BTN_SELECT@ + +;snes, Virtual Port 1/1A, Gamepad: START +snes.input.port1.gamepad.start joystick @GUID1@ @DEVICE_BTN_START@ + +;snes, Virtual Port 1/1A, Gamepad: UP +snes.input.port1.gamepad.up joystick @GUID1@ @DEVICE_BTN_DPAD_UP@ + +;snes, Virtual Port 1/1A, Gamepad: X (center, upper) +snes.input.port1.gamepad.x joystick @GUID1@ @DEVICE_BTN_NORTH@ + +;snes, Virtual Port 1/1A, Gamepad: Y (left) +snes.input.port1.gamepad.y joystick @GUID1@ @DEVICE_BTN_WEST@ + +;snes, Port 1/1A, Mouse: Left Button +snes.input.port1.mouse.left mouse 0x0 button_left + +;snes, Port 1/1A, Mouse: Motion Down +snes.input.port1.mouse.motion_down mouse 0x0 rel_y+ + +;snes, Port 1/1A, Mouse: Motion Left +snes.input.port1.mouse.motion_left mouse 0x0 rel_x- + +;snes, Port 1/1A, Mouse: Motion Right +snes.input.port1.mouse.motion_right mouse 0x0 rel_x+ + +;snes, Port 1/1A, Mouse: Motion Up +snes.input.port1.mouse.motion_up mouse 0x0 rel_y- + +;snes, Port 1/1A, Mouse: Right Button +snes.input.port1.mouse.right mouse 0x0 button_right + +;Enable multitap on SNES port 1. +snes.input.port1.multitap 0 + +;Input device for Port 2/2A +snes.input.port2 gamepad + +;snes, Port 2/2A, Gamepad: A (right) +snes.input.port2.gamepad.a + +;snes, Port 2/2A, Gamepad: B (center, lower) +snes.input.port2.gamepad.b + +;snes, Port 2/2A, Gamepad: DOWN ↓ +snes.input.port2.gamepad.down + +;snes, Port 2/2A, Gamepad: Left Shoulder +snes.input.port2.gamepad.l + +;snes, Port 2/2A, Gamepad: LEFT ← +snes.input.port2.gamepad.left + +;snes, Port 2/2A, Gamepad: Right Shoulder +snes.input.port2.gamepad.r + +;snes, Port 2/2A, Gamepad: Rapid A (right) +snes.input.port2.gamepad.rapid_a + +;snes, Port 2/2A, Gamepad: Rapid B (center, lower) +snes.input.port2.gamepad.rapid_b + +;snes, Port 2/2A, Gamepad: Rapid X (center, upper) +snes.input.port2.gamepad.rapid_x + +;snes, Port 2/2A, Gamepad: Rapid Y (left) +snes.input.port2.gamepad.rapid_y + +;snes, Port 2/2A, Gamepad: RIGHT → +snes.input.port2.gamepad.right + +;snes, Port 2/2A, Gamepad: SELECT +snes.input.port2.gamepad.select + +;snes, Port 2/2A, Gamepad: START +snes.input.port2.gamepad.start + +;snes, Port 2/2A, Gamepad: UP ↑ +snes.input.port2.gamepad.up + +;snes, Port 2/2A, Gamepad: X (center, upper) +snes.input.port2.gamepad.x + +;snes, Port 2/2A, Gamepad: Y (left) +snes.input.port2.gamepad.y + +;snes, Port 2/2A, Mouse: Left Button +snes.input.port2.mouse.left mouse 0x0 button_left + +;snes, Port 2/2A, Mouse: Motion Down +snes.input.port2.mouse.motion_down mouse 0x0 rel_y+ + +;snes, Port 2/2A, Mouse: Motion Left +snes.input.port2.mouse.motion_left mouse 0x0 rel_x- + +;snes, Port 2/2A, Mouse: Motion Right +snes.input.port2.mouse.motion_right mouse 0x0 rel_x+ + +;snes, Port 2/2A, Mouse: Motion Up +snes.input.port2.mouse.motion_up mouse 0x0 rel_y- + +;snes, Port 2/2A, Mouse: Right Button +snes.input.port2.mouse.right mouse 0x0 button_right + +;Enable multitap on SNES port 2. +snes.input.port2.multitap 0 + +;snes, Port 2/2A, Super Scope: Cursor +snes.input.port2.superscope.cursor mouse 0x0 button_right + +;snes, Port 2/2A, Super Scope: Offscreen Shot(Simulated) +snes.input.port2.superscope.offscreen_shot keyboard 0x0 44 + +;snes, Port 2/2A, Super Scope: Pause +snes.input.port2.superscope.pause mouse 0x0 button_middle + +;snes, Port 2/2A, Super Scope: Trigger +snes.input.port2.superscope.trigger mouse 0x0 button_left + +;snes, Port 2/2A, Super Scope: Turbo +snes.input.port2.superscope.turbo keyboard 0x0 77 + +;snes, Port 2/2A, Super Scope: X Axis +snes.input.port2.superscope.x_axis mouse 0x0 cursor_x-+ + +;snes, Port 2/2A, Super Scope: Y Axis +snes.input.port2.superscope.y_axis mouse 0x0 cursor_y-+ + +;snes, Port 2B, Gamepad: A (right) +snes.input.port3.gamepad.a + +;snes, Port 2B, Gamepad: B (center, lower) +snes.input.port3.gamepad.b + +;snes, Port 2B, Gamepad: DOWN ↓ +snes.input.port3.gamepad.down + +;snes, Port 2B, Gamepad: Left Shoulder +snes.input.port3.gamepad.l + +;snes, Port 2B, Gamepad: LEFT ← +snes.input.port3.gamepad.left + +;snes, Port 2B, Gamepad: Right Shoulder +snes.input.port3.gamepad.r + +;snes, Port 2B, Gamepad: Rapid A (right) +snes.input.port3.gamepad.rapid_a + +;snes, Port 2B, Gamepad: Rapid B (center, lower) +snes.input.port3.gamepad.rapid_b + +;snes, Port 2B, Gamepad: Rapid X (center, upper) +snes.input.port3.gamepad.rapid_x + +;snes, Port 2B, Gamepad: Rapid Y (left) +snes.input.port3.gamepad.rapid_y + +;snes, Port 2B, Gamepad: RIGHT → +snes.input.port3.gamepad.right + +;snes, Port 2B, Gamepad: SELECT +snes.input.port3.gamepad.select + +;snes, Port 2B, Gamepad: START +snes.input.port3.gamepad.start + +;snes, Port 2B, Gamepad: UP ↑ +snes.input.port3.gamepad.up + +;snes, Port 2B, Gamepad: X (center, upper) +snes.input.port3.gamepad.x + +;snes, Port 2B, Gamepad: Y (left) +snes.input.port3.gamepad.y + +;snes, Port 2C, Gamepad: A (right) +snes.input.port4.gamepad.a + +;snes, Port 2C, Gamepad: B (center, lower) +snes.input.port4.gamepad.b + +;snes, Port 2C, Gamepad: DOWN ↓ +snes.input.port4.gamepad.down + +;snes, Port 2C, Gamepad: Left Shoulder +snes.input.port4.gamepad.l + +;snes, Port 2C, Gamepad: LEFT ← +snes.input.port4.gamepad.left + +;snes, Port 2C, Gamepad: Right Shoulder +snes.input.port4.gamepad.r + +;snes, Port 2C, Gamepad: Rapid A (right) +snes.input.port4.gamepad.rapid_a + +;snes, Port 2C, Gamepad: Rapid B (center, lower) +snes.input.port4.gamepad.rapid_b + +;snes, Port 2C, Gamepad: Rapid X (center, upper) +snes.input.port4.gamepad.rapid_x + +;snes, Port 2C, Gamepad: Rapid Y (left) +snes.input.port4.gamepad.rapid_y + +;snes, Port 2C, Gamepad: RIGHT → +snes.input.port4.gamepad.right + +;snes, Port 2C, Gamepad: SELECT +snes.input.port4.gamepad.select + +;snes, Port 2C, Gamepad: START +snes.input.port4.gamepad.start + +;snes, Port 2C, Gamepad: UP ↑ +snes.input.port4.gamepad.up + +;snes, Port 2C, Gamepad: X (center, upper) +snes.input.port4.gamepad.x + +;snes, Port 2C, Gamepad: Y (left) +snes.input.port4.gamepad.y + +;snes, Port 2D, Gamepad: A (right) +snes.input.port5.gamepad.a + +;snes, Port 2D, Gamepad: B (center, lower) +snes.input.port5.gamepad.b + +;snes, Port 2D, Gamepad: DOWN ↓ +snes.input.port5.gamepad.down + +;snes, Port 2D, Gamepad: Left Shoulder +snes.input.port5.gamepad.l + +;snes, Port 2D, Gamepad: LEFT ← +snes.input.port5.gamepad.left + +;snes, Port 2D, Gamepad: Right Shoulder +snes.input.port5.gamepad.r + +;snes, Port 2D, Gamepad: Rapid A (right) +snes.input.port5.gamepad.rapid_a + +;snes, Port 2D, Gamepad: Rapid B (center, lower) +snes.input.port5.gamepad.rapid_b + +;snes, Port 2D, Gamepad: Rapid X (center, upper) +snes.input.port5.gamepad.rapid_x + +;snes, Port 2D, Gamepad: Rapid Y (left) +snes.input.port5.gamepad.rapid_y + +;snes, Port 2D, Gamepad: RIGHT → +snes.input.port5.gamepad.right + +;snes, Port 2D, Gamepad: SELECT +snes.input.port5.gamepad.select + +;snes, Port 2D, Gamepad: START +snes.input.port5.gamepad.start + +;snes, Port 2D, Gamepad: UP ↑ +snes.input.port5.gamepad.up + +;snes, Port 2D, Gamepad: X (center, upper) +snes.input.port5.gamepad.x + +;snes, Port 2D, Gamepad: Y (left) +snes.input.port5.gamepad.y + +;snes, Port 1B, Gamepad: A (right) +snes.input.port6.gamepad.a + +;snes, Port 1B, Gamepad: B (center, lower) +snes.input.port6.gamepad.b + +;snes, Port 1B, Gamepad: DOWN ↓ +snes.input.port6.gamepad.down + +;snes, Port 1B, Gamepad: Left Shoulder +snes.input.port6.gamepad.l + +;snes, Port 1B, Gamepad: LEFT ← +snes.input.port6.gamepad.left + +;snes, Port 1B, Gamepad: Right Shoulder +snes.input.port6.gamepad.r + +;snes, Port 1B, Gamepad: Rapid A (right) +snes.input.port6.gamepad.rapid_a + +;snes, Port 1B, Gamepad: Rapid B (center, lower) +snes.input.port6.gamepad.rapid_b + +;snes, Port 1B, Gamepad: Rapid X (center, upper) +snes.input.port6.gamepad.rapid_x + +;snes, Port 1B, Gamepad: Rapid Y (left) +snes.input.port6.gamepad.rapid_y + +;snes, Port 1B, Gamepad: RIGHT → +snes.input.port6.gamepad.right + +;snes, Port 1B, Gamepad: SELECT +snes.input.port6.gamepad.select + +;snes, Port 1B, Gamepad: START +snes.input.port6.gamepad.start + +;snes, Port 1B, Gamepad: UP ↑ +snes.input.port6.gamepad.up + +;snes, Port 1B, Gamepad: X (center, upper) +snes.input.port6.gamepad.x + +;snes, Port 1B, Gamepad: Y (left) +snes.input.port6.gamepad.y + +;snes, Port 1C, Gamepad: A (right) +snes.input.port7.gamepad.a + +;snes, Port 1C, Gamepad: B (center, lower) +snes.input.port7.gamepad.b + +;snes, Port 1C, Gamepad: DOWN ↓ +snes.input.port7.gamepad.down + +;snes, Port 1C, Gamepad: Left Shoulder +snes.input.port7.gamepad.l + +;snes, Port 1C, Gamepad: LEFT ← +snes.input.port7.gamepad.left + +;snes, Port 1C, Gamepad: Right Shoulder +snes.input.port7.gamepad.r + +;snes, Port 1C, Gamepad: Rapid A (right) +snes.input.port7.gamepad.rapid_a + +;snes, Port 1C, Gamepad: Rapid B (center, lower) +snes.input.port7.gamepad.rapid_b + +;snes, Port 1C, Gamepad: Rapid X (center, upper) +snes.input.port7.gamepad.rapid_x + +;snes, Port 1C, Gamepad: Rapid Y (left) +snes.input.port7.gamepad.rapid_y + +;snes, Port 1C, Gamepad: RIGHT → +snes.input.port7.gamepad.right + +;snes, Port 1C, Gamepad: SELECT +snes.input.port7.gamepad.select + +;snes, Port 1C, Gamepad: START +snes.input.port7.gamepad.start + +;snes, Port 1C, Gamepad: UP ↑ +snes.input.port7.gamepad.up + +;snes, Port 1C, Gamepad: X (center, upper) +snes.input.port7.gamepad.x + +;snes, Port 1C, Gamepad: Y (left) +snes.input.port7.gamepad.y + +;snes, Port 1D, Gamepad: A (right) +snes.input.port8.gamepad.a + +;snes, Port 1D, Gamepad: B (center, lower) +snes.input.port8.gamepad.b + +;snes, Port 1D, Gamepad: DOWN ↓ +snes.input.port8.gamepad.down + +;snes, Port 1D, Gamepad: Left Shoulder +snes.input.port8.gamepad.l + +;snes, Port 1D, Gamepad: LEFT ← +snes.input.port8.gamepad.left + +;snes, Port 1D, Gamepad: Right Shoulder +snes.input.port8.gamepad.r + +;snes, Port 1D, Gamepad: Rapid A (right) +snes.input.port8.gamepad.rapid_a + +;snes, Port 1D, Gamepad: Rapid B (center, lower) +snes.input.port8.gamepad.rapid_b + +;snes, Port 1D, Gamepad: Rapid X (center, upper) +snes.input.port8.gamepad.rapid_x + +;snes, Port 1D, Gamepad: Rapid Y (left) +snes.input.port8.gamepad.rapid_y + +;snes, Port 1D, Gamepad: RIGHT → +snes.input.port8.gamepad.right + +;snes, Port 1D, Gamepad: SELECT +snes.input.port8.gamepad.select + +;snes, Port 1D, Gamepad: START +snes.input.port8.gamepad.start + +;snes, Port 1D, Gamepad: UP ↑ +snes.input.port8.gamepad.up + +;snes, Port 1D, Gamepad: X (center, upper) +snes.input.port8.gamepad.x + +;snes, Port 1D, Gamepad: Y (left) +snes.input.port8.gamepad.y + +;Emulated mouse sensitivity. +snes.mouse_sensitivity 0.50 + +;Enable scanlines with specified opacity. +snes.scanlines 0 + +;Enable specified OpenGL shader. +snes.shader none + +;Force interlaced video to be treated as progressive. +snes.shader.goat.fprog 0 + +;Constant RGB horizontal divergence. +snes.shader.goat.hdiv 0.50 + +;Mask pattern. +snes.shader.goat.pat goatron + +;Enable scanlines effect. +snes.shader.goat.slen 1 + +;Transparency of otherwise-opaque mask areas. +snes.shader.goat.tp 0.50 + +;Constant RGB vertical divergence. +snes.shader.goat.vdiv 0.50 + +;Enable specified special video scaler. +snes.special none + +;Stretch to fill screen. +snes.stretch aspect + +;Enable video temporal blur(50/50 previous/current frame by default). +snes.tblur 0 + +;Accumulate color data rather than discarding it. +snes.tblur.accum 0 + +;Blur amount in accumulation mode, specified in percentage of accumulation buffer to mix with the current frame. +snes.tblur.accum.amount 50 + +;Enable (bi)linear interpolation. +snes.videoip 0 + +;Full-screen horizontal resolution. +snes.xres 0 + +;Scaling factor for the X axis in windowed mode. +snes.xscale 4.000000 + +;Scaling factor for the X axis in fullscreen mode. +snes.xscalefs 1.000000 + +;Full-screen vertical resolution. +snes.yres 0 + +;Scaling factor for the Y axis in windowed mode. +snes.yscale 4.000000 + +;Scaling factor for the Y axis in fullscreen mode. +snes.yscalefs 1.000000 + +;MSU1 audio read thread CPU affinity mask. +snes_faust.affinity.msu1.audio 0 + +;MSU1 data read thread CPU affinity mask. +snes_faust.affinity.msu1.data 0 + +;PPU rendering thread CPU affinity mask. +snes_faust.affinity.ppu 0xc + +;Correct aspect ratio. +snes_faust.correct_aspect 1 + +;CX4 clock rate, specified in percentage of normal. +snes_faust.cx4.clock_rate 100 + +;Enable (automatic) usage of this module. +snes_faust.enable 1 + +;Force monophonic sound output. +snes_faust.forcemono 0 + +;Horizontal blending/doubling filter. +snes_faust.h_filter none + +;Emulated mouse sensitivity. +snes_faust.input.mouse_sensitivity 0.50 + +;Input device for Virtual Port 1 +snes_faust.input.port1 gamepad + +;snes_faust, Virtual Port 1, Gamepad: A (right) +snes_faust.input.port1.gamepad.a joystick @GUID1@ @DEVICE_BTN_EAST@ + +;snes_faust, Virtual Port 1, Gamepad: B (center, lower) +snes_faust.input.port1.gamepad.b joystick @GUID1@ @DEVICE_BTN_SOUTH@ + +;snes_faust, Virtual Port 1, Gamepad: DOWN ↓ +snes_faust.input.port1.gamepad.down joystick @GUID1@ @DEVICE_BTN_DPAD_DOWN@ + +;snes_faust, Virtual Port 1, Gamepad: Left Shoulder +snes_faust.input.port1.gamepad.l joystick @GUID1@ @DEVICE_BTN_TL@ + +;snes_faust, Virtual Port 1, Gamepad: LEFT ← +snes_faust.input.port1.gamepad.left joystick @GUID1@ @DEVICE_BTN_DPAD_LEFT@ + +;snes_faust, Virtual Port 1, Gamepad: Right Shoulder +snes_faust.input.port1.gamepad.r joystick @GUID1@ @DEVICE_BTN_TR@ + +;snes_faust, Virtual Port 1, Gamepad: Rapid A (right) +snes_faust.input.port1.gamepad.rapid_a keyboard 0x0 17 + +;snes_faust, Virtual Port 1, Gamepad: Rapid B (center, lower) +snes_faust.input.port1.gamepad.rapid_b keyboard 0x0 17 + +;snes_faust, Virtual Port 1, Gamepad: Rapid X (center, upper) +snes_faust.input.port1.gamepad.rapid_x keyboard 0x0 17 + +;snes_faust, Virtual Port 1, Gamepad: Rapid Y (left) +snes_faust.input.port1.gamepad.rapid_y keyboard 0x0 17 + +;snes_faust, Virtual Port 1, Gamepad: RIGHT → +snes_faust.input.port1.gamepad.right joystick @GUID1@ @DEVICE_BTN_DPAD_RIGHT@ + +;snes_faust, Virtual Port 1, Gamepad: SELECT +snes_faust.input.port1.gamepad.select joystick @GUID1@ @DEVICE_BTN_SELECT@ + +;snes_faust, Virtual Port 1, Gamepad: START +snes_faust.input.port1.gamepad.start joystick @GUID1@ @DEVICE_BTN_START@ + +;snes_faust, Virtual Port 1, Gamepad: UP ↑ +snes_faust.input.port1.gamepad.up joystick @GUID1@ @DEVICE_BTN_DPAD_UP@ + +;snes_faust, Virtual Port 1, Gamepad: X (center, upper) +snes_faust.input.port1.gamepad.x joystick @GUID1@ @DEVICE_BTN_NORTH@ + +;snes_faust, Virtual Port 1, Gamepad: Y (left) +snes_faust.input.port1.gamepad.y joystick @GUID1@ @DEVICE_BTN_WEST@ + +;snes_faust, Virtual Port 1, Mouse: Left Button +snes_faust.input.port1.mouse.left mouse 0x0 button_left + +;snes_faust, Virtual Port 1, Mouse: Motion Down +snes_faust.input.port1.mouse.motion_down mouse 0x0 rel_y+ + +;snes_faust, Virtual Port 1, Mouse: Motion Left +snes_faust.input.port1.mouse.motion_left mouse 0x0 rel_x- + +;snes_faust, Virtual Port 1, Mouse: Motion Right +snes_faust.input.port1.mouse.motion_right mouse 0x0 rel_x+ + +;snes_faust, Virtual Port 1, Mouse: Motion Up +snes_faust.input.port1.mouse.motion_up mouse 0x0 rel_y- + +;snes_faust, Virtual Port 1, Mouse: Right Button +snes_faust.input.port1.mouse.right mouse 0x0 button_right + +;Input device for Virtual Port 2 +snes_faust.input.port2 gamepad + +;snes_faust, Virtual Port 2, Gamepad: A (right) +snes_faust.input.port2.gamepad.a + +;snes_faust, Virtual Port 2, Gamepad: B (center, lower) +snes_faust.input.port2.gamepad.b + +;snes_faust, Virtual Port 2, Gamepad: DOWN ↓ +snes_faust.input.port2.gamepad.down + +;snes_faust, Virtual Port 2, Gamepad: Left Shoulder +snes_faust.input.port2.gamepad.l + +;snes_faust, Virtual Port 2, Gamepad: LEFT ← +snes_faust.input.port2.gamepad.left + +;snes_faust, Virtual Port 2, Gamepad: Right Shoulder +snes_faust.input.port2.gamepad.r + +;snes_faust, Virtual Port 2, Gamepad: Rapid A (right) +snes_faust.input.port2.gamepad.rapid_a + +;snes_faust, Virtual Port 2, Gamepad: Rapid B (center, lower) +snes_faust.input.port2.gamepad.rapid_b + +;snes_faust, Virtual Port 2, Gamepad: Rapid X (center, upper) +snes_faust.input.port2.gamepad.rapid_x + +;snes_faust, Virtual Port 2, Gamepad: Rapid Y (left) +snes_faust.input.port2.gamepad.rapid_y + +;snes_faust, Virtual Port 2, Gamepad: RIGHT → +snes_faust.input.port2.gamepad.right + +;snes_faust, Virtual Port 2, Gamepad: SELECT +snes_faust.input.port2.gamepad.select + +;snes_faust, Virtual Port 2, Gamepad: START +snes_faust.input.port2.gamepad.start + +;snes_faust, Virtual Port 2, Gamepad: UP ↑ +snes_faust.input.port2.gamepad.up + +;snes_faust, Virtual Port 2, Gamepad: X (center, upper) +snes_faust.input.port2.gamepad.x + +;snes_faust, Virtual Port 2, Gamepad: Y (left) +snes_faust.input.port2.gamepad.y + +;snes_faust, Virtual Port 2, Mouse: Left Button +snes_faust.input.port2.mouse.left mouse 0x0 button_left + +;snes_faust, Virtual Port 2, Mouse: Motion Down +snes_faust.input.port2.mouse.motion_down mouse 0x0 rel_y+ + +;snes_faust, Virtual Port 2, Mouse: Motion Left +snes_faust.input.port2.mouse.motion_left mouse 0x0 rel_x- + +;snes_faust, Virtual Port 2, Mouse: Motion Right +snes_faust.input.port2.mouse.motion_right mouse 0x0 rel_x+ + +;snes_faust, Virtual Port 2, Mouse: Motion Up +snes_faust.input.port2.mouse.motion_up mouse 0x0 rel_y- + +;snes_faust, Virtual Port 2, Mouse: Right Button +snes_faust.input.port2.mouse.right mouse 0x0 button_right + +;Input device for Virtual Port 3 +snes_faust.input.port3 gamepad + +;snes_faust, Virtual Port 3, Gamepad: A (right) +snes_faust.input.port3.gamepad.a + +;snes_faust, Virtual Port 3, Gamepad: B (center, lower) +snes_faust.input.port3.gamepad.b + +;snes_faust, Virtual Port 3, Gamepad: DOWN ↓ +snes_faust.input.port3.gamepad.down + +;snes_faust, Virtual Port 3, Gamepad: Left Shoulder +snes_faust.input.port3.gamepad.l + +;snes_faust, Virtual Port 3, Gamepad: LEFT ← +snes_faust.input.port3.gamepad.left + +;snes_faust, Virtual Port 3, Gamepad: Right Shoulder +snes_faust.input.port3.gamepad.r + +;snes_faust, Virtual Port 3, Gamepad: Rapid A (right) +snes_faust.input.port3.gamepad.rapid_a + +;snes_faust, Virtual Port 3, Gamepad: Rapid B (center, lower) +snes_faust.input.port3.gamepad.rapid_b + +;snes_faust, Virtual Port 3, Gamepad: Rapid X (center, upper) +snes_faust.input.port3.gamepad.rapid_x + +;snes_faust, Virtual Port 3, Gamepad: Rapid Y (left) +snes_faust.input.port3.gamepad.rapid_y + +;snes_faust, Virtual Port 3, Gamepad: RIGHT → +snes_faust.input.port3.gamepad.right + +;snes_faust, Virtual Port 3, Gamepad: SELECT +snes_faust.input.port3.gamepad.select + +;snes_faust, Virtual Port 3, Gamepad: START +snes_faust.input.port3.gamepad.start + +;snes_faust, Virtual Port 3, Gamepad: UP ↑ +snes_faust.input.port3.gamepad.up + +;snes_faust, Virtual Port 3, Gamepad: X (center, upper) +snes_faust.input.port3.gamepad.x + +;snes_faust, Virtual Port 3, Gamepad: Y (left) +snes_faust.input.port3.gamepad.y + +;snes_faust, Virtual Port 3, Mouse: Left Button +snes_faust.input.port3.mouse.left mouse 0x0 button_left + +;snes_faust, Virtual Port 3, Mouse: Motion Down +snes_faust.input.port3.mouse.motion_down mouse 0x0 rel_y+ + +;snes_faust, Virtual Port 3, Mouse: Motion Left +snes_faust.input.port3.mouse.motion_left mouse 0x0 rel_x- + +;snes_faust, Virtual Port 3, Mouse: Motion Right +snes_faust.input.port3.mouse.motion_right mouse 0x0 rel_x+ + +;snes_faust, Virtual Port 3, Mouse: Motion Up +snes_faust.input.port3.mouse.motion_up mouse 0x0 rel_y- + +;snes_faust, Virtual Port 3, Mouse: Right Button +snes_faust.input.port3.mouse.right mouse 0x0 button_right + +;Input device for Virtual Port 4 +snes_faust.input.port4 gamepad + +;snes_faust, Virtual Port 4, Gamepad: A (right) +snes_faust.input.port4.gamepad.a + +;snes_faust, Virtual Port 4, Gamepad: B (center, lower) +snes_faust.input.port4.gamepad.b + +;snes_faust, Virtual Port 4, Gamepad: DOWN ↓ +snes_faust.input.port4.gamepad.down + +;snes_faust, Virtual Port 4, Gamepad: Left Shoulder +snes_faust.input.port4.gamepad.l + +;snes_faust, Virtual Port 4, Gamepad: LEFT ← +snes_faust.input.port4.gamepad.left + +;snes_faust, Virtual Port 4, Gamepad: Right Shoulder +snes_faust.input.port4.gamepad.r + +;snes_faust, Virtual Port 4, Gamepad: Rapid A (right) +snes_faust.input.port4.gamepad.rapid_a + +;snes_faust, Virtual Port 4, Gamepad: Rapid B (center, lower) +snes_faust.input.port4.gamepad.rapid_b + +;snes_faust, Virtual Port 4, Gamepad: Rapid X (center, upper) +snes_faust.input.port4.gamepad.rapid_x + +;snes_faust, Virtual Port 4, Gamepad: Rapid Y (left) +snes_faust.input.port4.gamepad.rapid_y + +;snes_faust, Virtual Port 4, Gamepad: RIGHT → +snes_faust.input.port4.gamepad.right + +;snes_faust, Virtual Port 4, Gamepad: SELECT +snes_faust.input.port4.gamepad.select + +;snes_faust, Virtual Port 4, Gamepad: START +snes_faust.input.port4.gamepad.start + +;snes_faust, Virtual Port 4, Gamepad: UP ↑ +snes_faust.input.port4.gamepad.up + +;snes_faust, Virtual Port 4, Gamepad: X (center, upper) +snes_faust.input.port4.gamepad.x + +;snes_faust, Virtual Port 4, Gamepad: Y (left) +snes_faust.input.port4.gamepad.y + +;snes_faust, Virtual Port 4, Mouse: Left Button +snes_faust.input.port4.mouse.left mouse 0x0 button_left + +;snes_faust, Virtual Port 4, Mouse: Motion Down +snes_faust.input.port4.mouse.motion_down mouse 0x0 rel_y+ + +;snes_faust, Virtual Port 4, Mouse: Motion Left +snes_faust.input.port4.mouse.motion_left mouse 0x0 rel_x- + +;snes_faust, Virtual Port 4, Mouse: Motion Right +snes_faust.input.port4.mouse.motion_right mouse 0x0 rel_x+ + +;snes_faust, Virtual Port 4, Mouse: Motion Up +snes_faust.input.port4.mouse.motion_up mouse 0x0 rel_y- + +;snes_faust, Virtual Port 4, Mouse: Right Button +snes_faust.input.port4.mouse.right mouse 0x0 button_right + +;Input device for Virtual Port 5 +snes_faust.input.port5 gamepad + +;snes_faust, Virtual Port 5, Gamepad: A (right) +snes_faust.input.port5.gamepad.a + +;snes_faust, Virtual Port 5, Gamepad: B (center, lower) +snes_faust.input.port5.gamepad.b + +;snes_faust, Virtual Port 5, Gamepad: DOWN ↓ +snes_faust.input.port5.gamepad.down + +;snes_faust, Virtual Port 5, Gamepad: Left Shoulder +snes_faust.input.port5.gamepad.l + +;snes_faust, Virtual Port 5, Gamepad: LEFT ← +snes_faust.input.port5.gamepad.left + +;snes_faust, Virtual Port 5, Gamepad: Right Shoulder +snes_faust.input.port5.gamepad.r + +;snes_faust, Virtual Port 5, Gamepad: Rapid A (right) +snes_faust.input.port5.gamepad.rapid_a + +;snes_faust, Virtual Port 5, Gamepad: Rapid B (center, lower) +snes_faust.input.port5.gamepad.rapid_b + +;snes_faust, Virtual Port 5, Gamepad: Rapid X (center, upper) +snes_faust.input.port5.gamepad.rapid_x + +;snes_faust, Virtual Port 5, Gamepad: Rapid Y (left) +snes_faust.input.port5.gamepad.rapid_y + +;snes_faust, Virtual Port 5, Gamepad: RIGHT → +snes_faust.input.port5.gamepad.right + +;snes_faust, Virtual Port 5, Gamepad: SELECT +snes_faust.input.port5.gamepad.select + +;snes_faust, Virtual Port 5, Gamepad: START +snes_faust.input.port5.gamepad.start + +;snes_faust, Virtual Port 5, Gamepad: UP ↑ +snes_faust.input.port5.gamepad.up + +;snes_faust, Virtual Port 5, Gamepad: X (center, upper) +snes_faust.input.port5.gamepad.x + +;snes_faust, Virtual Port 5, Gamepad: Y (left) +snes_faust.input.port5.gamepad.y + +;snes_faust, Virtual Port 5, Mouse: Left Button +snes_faust.input.port5.mouse.left mouse 0x0 button_left + +;snes_faust, Virtual Port 5, Mouse: Motion Down +snes_faust.input.port5.mouse.motion_down mouse 0x0 rel_y+ + +;snes_faust, Virtual Port 5, Mouse: Motion Left +snes_faust.input.port5.mouse.motion_left mouse 0x0 rel_x- + +;snes_faust, Virtual Port 5, Mouse: Motion Right +snes_faust.input.port5.mouse.motion_right mouse 0x0 rel_x+ + +;snes_faust, Virtual Port 5, Mouse: Motion Up +snes_faust.input.port5.mouse.motion_up mouse 0x0 rel_y- + +;snes_faust, Virtual Port 5, Mouse: Right Button +snes_faust.input.port5.mouse.right mouse 0x0 button_right + +;Input device for Virtual Port 6 +snes_faust.input.port6 gamepad + +;snes_faust, Virtual Port 6, Gamepad: A (right) +snes_faust.input.port6.gamepad.a + +;snes_faust, Virtual Port 6, Gamepad: B (center, lower) +snes_faust.input.port6.gamepad.b + +;snes_faust, Virtual Port 6, Gamepad: DOWN ↓ +snes_faust.input.port6.gamepad.down + +;snes_faust, Virtual Port 6, Gamepad: Left Shoulder +snes_faust.input.port6.gamepad.l + +;snes_faust, Virtual Port 6, Gamepad: LEFT ← +snes_faust.input.port6.gamepad.left + +;snes_faust, Virtual Port 6, Gamepad: Right Shoulder +snes_faust.input.port6.gamepad.r + +;snes_faust, Virtual Port 6, Gamepad: Rapid A (right) +snes_faust.input.port6.gamepad.rapid_a + +;snes_faust, Virtual Port 6, Gamepad: Rapid B (center, lower) +snes_faust.input.port6.gamepad.rapid_b + +;snes_faust, Virtual Port 6, Gamepad: Rapid X (center, upper) +snes_faust.input.port6.gamepad.rapid_x + +;snes_faust, Virtual Port 6, Gamepad: Rapid Y (left) +snes_faust.input.port6.gamepad.rapid_y + +;snes_faust, Virtual Port 6, Gamepad: RIGHT → +snes_faust.input.port6.gamepad.right + +;snes_faust, Virtual Port 6, Gamepad: SELECT +snes_faust.input.port6.gamepad.select + +;snes_faust, Virtual Port 6, Gamepad: START +snes_faust.input.port6.gamepad.start + +;snes_faust, Virtual Port 6, Gamepad: UP ↑ +snes_faust.input.port6.gamepad.up + +;snes_faust, Virtual Port 6, Gamepad: X (center, upper) +snes_faust.input.port6.gamepad.x + +;snes_faust, Virtual Port 6, Gamepad: Y (left) +snes_faust.input.port6.gamepad.y + +;snes_faust, Virtual Port 6, Mouse: Left Button +snes_faust.input.port6.mouse.left mouse 0x0 button_left + +;snes_faust, Virtual Port 6, Mouse: Motion Down +snes_faust.input.port6.mouse.motion_down mouse 0x0 rel_y+ + +;snes_faust, Virtual Port 6, Mouse: Motion Left +snes_faust.input.port6.mouse.motion_left mouse 0x0 rel_x- + +;snes_faust, Virtual Port 6, Mouse: Motion Right +snes_faust.input.port6.mouse.motion_right mouse 0x0 rel_x+ + +;snes_faust, Virtual Port 6, Mouse: Motion Up +snes_faust.input.port6.mouse.motion_up mouse 0x0 rel_y- + +;snes_faust, Virtual Port 6, Mouse: Right Button +snes_faust.input.port6.mouse.right mouse 0x0 button_right + +;Input device for Virtual Port 7 +snes_faust.input.port7 gamepad + +;snes_faust, Virtual Port 7, Gamepad: A (right) +snes_faust.input.port7.gamepad.a + +;snes_faust, Virtual Port 7, Gamepad: B (center, lower) +snes_faust.input.port7.gamepad.b + +;snes_faust, Virtual Port 7, Gamepad: DOWN ↓ +snes_faust.input.port7.gamepad.down + +;snes_faust, Virtual Port 7, Gamepad: Left Shoulder +snes_faust.input.port7.gamepad.l + +;snes_faust, Virtual Port 7, Gamepad: LEFT ← +snes_faust.input.port7.gamepad.left + +;snes_faust, Virtual Port 7, Gamepad: Right Shoulder +snes_faust.input.port7.gamepad.r + +;snes_faust, Virtual Port 7, Gamepad: Rapid A (right) +snes_faust.input.port7.gamepad.rapid_a + +;snes_faust, Virtual Port 7, Gamepad: Rapid B (center, lower) +snes_faust.input.port7.gamepad.rapid_b + +;snes_faust, Virtual Port 7, Gamepad: Rapid X (center, upper) +snes_faust.input.port7.gamepad.rapid_x + +;snes_faust, Virtual Port 7, Gamepad: Rapid Y (left) +snes_faust.input.port7.gamepad.rapid_y + +;snes_faust, Virtual Port 7, Gamepad: RIGHT → +snes_faust.input.port7.gamepad.right + +;snes_faust, Virtual Port 7, Gamepad: SELECT +snes_faust.input.port7.gamepad.select + +;snes_faust, Virtual Port 7, Gamepad: START +snes_faust.input.port7.gamepad.start + +;snes_faust, Virtual Port 7, Gamepad: UP ↑ +snes_faust.input.port7.gamepad.up + +;snes_faust, Virtual Port 7, Gamepad: X (center, upper) +snes_faust.input.port7.gamepad.x + +;snes_faust, Virtual Port 7, Gamepad: Y (left) +snes_faust.input.port7.gamepad.y + +;snes_faust, Virtual Port 7, Mouse: Left Button +snes_faust.input.port7.mouse.left mouse 0x0 button_left + +;snes_faust, Virtual Port 7, Mouse: Motion Down +snes_faust.input.port7.mouse.motion_down mouse 0x0 rel_y+ + +;snes_faust, Virtual Port 7, Mouse: Motion Left +snes_faust.input.port7.mouse.motion_left mouse 0x0 rel_x- + +;snes_faust, Virtual Port 7, Mouse: Motion Right +snes_faust.input.port7.mouse.motion_right mouse 0x0 rel_x+ + +;snes_faust, Virtual Port 7, Mouse: Motion Up +snes_faust.input.port7.mouse.motion_up mouse 0x0 rel_y- + +;snes_faust, Virtual Port 7, Mouse: Right Button +snes_faust.input.port7.mouse.right mouse 0x0 button_right + +;Input device for Virtual Port 8 +snes_faust.input.port8 gamepad + +;snes_faust, Virtual Port 8, Gamepad: A (right) +snes_faust.input.port8.gamepad.a + +;snes_faust, Virtual Port 8, Gamepad: B (center, lower) +snes_faust.input.port8.gamepad.b + +;snes_faust, Virtual Port 8, Gamepad: DOWN ↓ +snes_faust.input.port8.gamepad.down + +;snes_faust, Virtual Port 8, Gamepad: Left Shoulder +snes_faust.input.port8.gamepad.l + +;snes_faust, Virtual Port 8, Gamepad: LEFT ← +snes_faust.input.port8.gamepad.left + +;snes_faust, Virtual Port 8, Gamepad: Right Shoulder +snes_faust.input.port8.gamepad.r + +;snes_faust, Virtual Port 8, Gamepad: Rapid A (right) +snes_faust.input.port8.gamepad.rapid_a + +;snes_faust, Virtual Port 8, Gamepad: Rapid B (center, lower) +snes_faust.input.port8.gamepad.rapid_b + +;snes_faust, Virtual Port 8, Gamepad: Rapid X (center, upper) +snes_faust.input.port8.gamepad.rapid_x + +;snes_faust, Virtual Port 8, Gamepad: Rapid Y (left) +snes_faust.input.port8.gamepad.rapid_y + +;snes_faust, Virtual Port 8, Gamepad: RIGHT → +snes_faust.input.port8.gamepad.right + +;snes_faust, Virtual Port 8, Gamepad: SELECT +snes_faust.input.port8.gamepad.select + +;snes_faust, Virtual Port 8, Gamepad: START +snes_faust.input.port8.gamepad.start + +;snes_faust, Virtual Port 8, Gamepad: UP ↑ +snes_faust.input.port8.gamepad.up + +;snes_faust, Virtual Port 8, Gamepad: X (center, upper) +snes_faust.input.port8.gamepad.x + +;snes_faust, Virtual Port 8, Gamepad: Y (left) +snes_faust.input.port8.gamepad.y + +;snes_faust, Virtual Port 8, Mouse: Left Button +snes_faust.input.port8.mouse.left mouse 0x0 button_left + +;snes_faust, Virtual Port 8, Mouse: Motion Down +snes_faust.input.port8.mouse.motion_down mouse 0x0 rel_y+ + +;snes_faust, Virtual Port 8, Mouse: Motion Left +snes_faust.input.port8.mouse.motion_left mouse 0x0 rel_x- + +;snes_faust, Virtual Port 8, Mouse: Motion Right +snes_faust.input.port8.mouse.motion_right mouse 0x0 rel_x+ + +;snes_faust, Virtual Port 8, Mouse: Motion Up +snes_faust.input.port8.mouse.motion_up mouse 0x0 rel_y- + +;snes_faust, Virtual Port 8, Mouse: Right Button +snes_faust.input.port8.mouse.right mouse 0x0 button_right + +;Enable multitap on SNES port 1. +snes_faust.input.sport1.multitap 0 + +;Enable multitap on SNES port 2. +snes_faust.input.sport2.multitap 0 + +;MSU1 sound quality. +snes_faust.msu1.resamp_quality 4 + +;Region of SNES to emulate. +snes_faust.region auto + +;PPU renderer. +snes_faust.renderer mt + +;Sound quality. +snes_faust.resamp_quality 3 + +;Sound output rate tolerance. +snes_faust.resamp_rate_error 0.000035 + +;Enable scanlines with specified opacity. +snes_faust.scanlines 0 + +;Enable specified OpenGL shader. +snes_faust.shader autoip + +;Force interlaced video to be treated as progressive. +snes_faust.shader.goat.fprog 0 + +;Constant RGB horizontal divergence. +snes_faust.shader.goat.hdiv 0.50 + +;Mask pattern. +snes_faust.shader.goat.pat goatron + +;Enable scanlines effect. +snes_faust.shader.goat.slen 1 + +;Transparency of otherwise-opaque mask areas. +snes_faust.shader.goat.tp 0.50 + +;Constant RGB vertical divergence. +snes_faust.shader.goat.vdiv 0.50 + +;Last displayed scanline in NTSC mode. +snes_faust.slend 223 + +;Last displayed scanline in PAL mode. +snes_faust.slendp 238 + +;First displayed scanline in NTSC mode. +snes_faust.slstart 0 + +;First displayed scanline in PAL mode. +snes_faust.slstartp 0 + +;Enable specified special video scaler. +snes_faust.special none + +;Enable 1-frame speculative execution for video output. +snes_faust.spex 0 + +;Enable speculative execution for sound output too. +snes_faust.spex.sound 1 + +;Stretch to fill screen. +snes_faust.stretch full + +;Super FX clock rate, specified in percentage of normal. +snes_faust.superfx.clock_rate 100 + +;Enable SuperFX instruction cache emulation. +snes_faust.superfx.icache 0 + +;Enable video temporal blur(50/50 previous/current frame by default). +snes_faust.tblur 0 + +;Accumulate color data rather than discarding it. +snes_faust.tblur.accum 0 + +;Blur amount in accumulation mode, specified in percentage of accumulation buffer to mix with the current frame. +snes_faust.tblur.accum.amount 50 + +;Enable (bi)linear interpolation. +snes_faust.videoip 0 + +;Full-screen horizontal resolution. +snes_faust.xres 0 + +;Scaling factor for the X axis in windowed mode. +snes_faust.xscale 3.000000 + +;Scaling factor for the X axis in fullscreen mode. +snes_faust.xscalefs 1.000000 + +;Full-screen vertical resolution. +snes_faust.yres 0 + +;Scaling factor for the Y axis in windowed mode. +snes_faust.yscale 3.000000 + +;Scaling factor for the Y axis in fullscreen mode. +snes_faust.yscalefs 1.000000 + +;Enable sound output. +sound 1 + +;Desired buffer size in milliseconds(ms). +sound.buffer_time 0 + +;Select sound output device. +sound.device sexyal-literal-default + +;Select sound driver. +sound.driver default + +;Desired period size in microseconds(μs). +sound.period_time 0 + +;Specifies the sound playback rate, in sound frames per second("Hz"). +sound.rate 48000 + +;Sound volume level, in percent. +sound.volume 100 + +;DO NOT USE UNLESS YOU'RE A SPACE GOAT +srwautoenable 0 + +;Number of frames to keep states for when state rewinding is enabled. +srwframes 600 + +;3D mode. +vb.3dmode anaglyph + +;Reverse left/right 3D views. +vb.3dreverse 0 + +;Allow draw skipping. +vb.allow_draw_skip 0 + +;Anaglyph maximum-brightness color for left view. +vb.anaglyph.lcolor 0xff0000 + +;Anaglyph preset colors. +vb.anaglyph.preset disabled + +;Anaglyph maximum-brightness color for right view. +vb.anaglyph.rcolor 0x000000 + +;CPU emulation mode. +vb.cpu_emulation accurate + +;Disassembly font size. +vb.debugger.disfontsize 5x7 + +;Character encoding for the debugger's memory editor. +vb.debugger.memcharenc shift_jis + +;Default maximum-brightness color to use in non-anaglyph 3D modes. +vb.default_color 0xF0F0F0 + +;Disable parallax for BG and OBJ rendering. +vb.disable_parallax 0 + +;Enable (automatic) usage of this module. +vb.enable 1 + +;Force monophonic sound output. +vb.forcemono 0 + +;vb, Built-In, Gamepad: A +vb.input.builtin.gamepad.a joystick @GUID1@ @DEVICE_BTN_EAST@ + +;vb, Built-In, Gamepad: B +vb.input.builtin.gamepad.b joystick @GUID1@ @DEVICE_BTN_SOUTH@ + +;vb, Built-In, Gamepad: DOWN ↓ (Left D-Pad) +vb.input.builtin.gamepad.down-l joystick @GUID1@ @DEVICE_BTN_DPAD_DOWN@ + +;vb, Built-In, Gamepad: DOWN ↓ (Right D-Pad) +vb.input.builtin.gamepad.down-r joystick @GUID1@ abs_1+ + +;vb, Built-In, Gamepad: LEFT ← (Left D-Pad) +vb.input.builtin.gamepad.left-l joystick @GUID1@ @DEVICE_BTN_DPAD_LEFT@ + +;vb, Built-In, Gamepad: LEFT ← (Right D-Pad) +vb.input.builtin.gamepad.left-r joystick @GUID1@ abs_0- + +;vb, Built-In, Gamepad: Left-Back +vb.input.builtin.gamepad.lt joystick @GUID1@ @DEVICE_BTN_TL@ + +;vb, Built-In, Gamepad: Rapid A +vb.input.builtin.gamepad.rapid_a joystick @GUID1@ @DEVICE_BTN_NORTH@ + +;vb, Built-In, Gamepad: Rapid B +vb.input.builtin.gamepad.rapid_b joystick @GUID1@ @DEVICE_BTN_WEST@ + +;vb, Built-In, Gamepad: RIGHT → (Left D-Pad) +vb.input.builtin.gamepad.right-l joystick @GUID1@ @DEVICE_BTN_DPAD_RIGHT@ + +;vb, Built-In, Gamepad: RIGHT → (Right D-Pad) +vb.input.builtin.gamepad.right-r joystick @GUID1@ abs_0+ + +;vb, Built-In, Gamepad: Right-Back +vb.input.builtin.gamepad.rt joystick @GUID1@ @DEVICE_BTN_TR@ + +;vb, Built-In, Gamepad: Select +vb.input.builtin.gamepad.select joystick @GUID1@ @DEVICE_BTN_SELECT@ + +;vb, Built-In, Gamepad: Start +vb.input.builtin.gamepad.start joystick @GUID1@ @DEVICE_BTN_START@ + +;vb, Built-In, Gamepad: UP ↑ (Left D-Pad) +vb.input.builtin.gamepad.up-l joystick @GUID1@ @DEVICE_BTN_DPAD_UP@ + +;vb, Built-In, Gamepad: UP ↑ (Right D-Pad) +vb.input.builtin.gamepad.up-r joystick @GUID1@ abs_1- + +;Input latency reduction hack. +vb.input.instant_read_hack 1 + +;vb, System, Misc: Battery Voltage +vb.input.system.misc.battery + +;Default position for switch "Battery Voltage". +vb.input.system.misc.battery.defpos normal + +;Display latency reduction hack. +vb.instant_display_hack 0 + +;LED on duration to linear RGB conversion coefficient. +vb.ledonscale 1.75 + +;Line Interlaced prescale. +vb.liprescale 2 + +;Enable scanlines with specified opacity. +vb.scanlines 0 + +;Enable specified OpenGL shader. +vb.shader ipxnoty + +;Force interlaced video to be treated as progressive. +vb.shader.goat.fprog 0 + +;Constant RGB horizontal divergence. +vb.shader.goat.hdiv 0.50 + +;Mask pattern. +vb.shader.goat.pat goatron + +;Enable scanlines effect. +vb.shader.goat.slen 1 + +;Transparency of otherwise-opaque mask areas. +vb.shader.goat.tp 0.50 + +;Constant RGB vertical divergence. +vb.shader.goat.vdiv 0.50 + +;Number of pixels to separate L/R views by. +vb.sidebyside.separation 0 + +;Enable specified special video scaler. +vb.special none + +;Stretch to fill screen. +vb.stretch full + +;Enable video temporal blur(50/50 previous/current frame by default). +vb.tblur 0 + +;Accumulate color data rather than discarding it. +vb.tblur.accum 0 + +;Blur amount in accumulation mode, specified in percentage of accumulation buffer to mix with the current frame. +vb.tblur.accum.amount 50 + +;Enable (bi)linear interpolation. +vb.videoip 0 + +;Full-screen horizontal resolution. +vb.xres 0 + +;Scaling factor for the X axis in windowed mode. +vb.xscale 2.000000 + +;Scaling factor for the X axis in fullscreen mode. +vb.xscalefs 1.000000 + +;Full-screen vertical resolution. +vb.yres 0 + +;Scaling factor for the Y axis in windowed mode. +vb.yscale 2.000000 + +;Scaling factor for the Y axis in fullscreen mode. +vb.yscalefs 1.000000 + +;Enable time synchronization(waiting) for frame blitting. +video.blit_timesync 1 + +;Preferred window manager cursor visibility. +video.cursorvis hidden + +;Deinterlacer to use for interlaced video. +video.deinterlacer weave + +;Attempt to disable desktop composition. +video.disable_composition 1 + +;Video output driver. +video.driver opengl + +;Force backbuffer clear before drawing. +video.force_bbclear 0 + +;Enable frameskip during emulation rendering. +video.frameskip 1 + +;Enable fullscreen mode. +video.fs 1 + +;Display to use with fullscreen mode. +video.fs.display -1 + +;Preferred source data pixel format for emulated video. +video.glformat auto + +;Attempt to synchronize OpenGL page flips to vertical retrace period. +video.glvsync 1 + +;Birth Day +wswan.bday 23 + +;Blood Type +wswan.blood O + +;Birth Month +wswan.bmonth 6 + +;Birth Year +wswan.byear 1989 + +;Disassembly font size. +wswan.debugger.disfontsize 5x7 + +;Character encoding for the debugger's memory editor. +wswan.debugger.memcharenc shift_jis + +;Enable (automatic) usage of this module. +wswan.enable 1 + +;Enable comms to external program. +wswan.excomm 0 + +;Comms external program path. +wswan.excomm.path wonderfence + +;Force monophonic sound output. +wswan.forcemono 0 + +;Input device for Built-In +wswan.input.builtin gamepad + +;wswan, Built-In, Gamepad: A +wswan.input.builtin.gamepad.a joystick @GUID1@ @DEVICE_BTN_EAST@ + +;wswan, Built-In, Gamepad: B +wswan.input.builtin.gamepad.b joystick @GUID1@ @DEVICE_BTN_SOUTH@ + +;wswan, Built-In, Gamepad: X3(X DOWN ↓) +wswan.input.builtin.gamepad.down-x joystick @GUID1@ @DEVICE_BTN_DPAD_DOWN@ + +;wswan, Built-In, Gamepad: Y3(Y DOWN ↓) +wswan.input.builtin.gamepad.down-y joystick @GUID1@ @DEVICE_BTN_TL2@ + +;wswan, Built-In, Gamepad: X4(X LEFT ←) +wswan.input.builtin.gamepad.left-x joystick @GUID1@ @DEVICE_BTN_DPAD_LEFT@ + +;wswan, Built-In, Gamepad: Y4(Y LEFT ←) +wswan.input.builtin.gamepad.left-y joystick @GUID1@ @DEVICE_BTN_TL@ + +;wswan, Built-In, Gamepad: Rapid A +wswan.input.builtin.gamepad.rapid_a joystick @GUID1@ @DEVICE_BTN_NORTH@ + +;wswan, Built-In, Gamepad: Rapid B +wswan.input.builtin.gamepad.rapid_b joystick @GUID1@ @DEVICE_BTN_WEST@ + +;wswan, Built-In, Gamepad: X2(X RIGHT →) +wswan.input.builtin.gamepad.right-x joystick @GUID1@ @DEVICE_BTN_DPAD_RIGHT@ + +;wswan, Built-In, Gamepad: Y2(Y RIGHT →) +wswan.input.builtin.gamepad.right-y joystick @GUID1@ @DEVICE_BTN_TR@ + +;wswan, Built-In, Gamepad: Start +wswan.input.builtin.gamepad.start joystick @GUID1@ @DEVICE_BTN_START@ + +;wswan, Built-In, Gamepad: X1(X UP ↑) +wswan.input.builtin.gamepad.up-x joystick @GUID1@ @DEVICE_BTN_DPAD_UP@ + +;wswan, Built-In, Gamepad: Y1(Y UP ↑) +wswan.input.builtin.gamepad.up-y joystick @GUID1@ @DEVICE_BTN_TR2@ + +;wswan, Built-In, Gamepad(Rotation Auto-Adjust): A (right) +wswan.input.builtin.gamepadraa.a keyboard 0x0 91 + +;wswan, Built-In, Gamepad(Rotation Auto-Adjust): A'(center, upper) +wswan.input.builtin.gamepadraa.ap keyboard 0x0 94 + +;wswan, Built-In, Gamepad(Rotation Auto-Adjust): B (center, lower) +wswan.input.builtin.gamepadraa.b keyboard 0x0 90 + +;wswan, Built-In, Gamepad(Rotation Auto-Adjust): B'(left) +wswan.input.builtin.gamepadraa.bp keyboard 0x0 93 + +;wswan, Built-In, Gamepad(Rotation Auto-Adjust): X3(X DOWN ↓) +wswan.input.builtin.gamepadraa.down-x keyboard 0x0 22 + +;wswan, Built-In, Gamepad(Rotation Auto-Adjust): Y3(Y DOWN ↓) +wswan.input.builtin.gamepadraa.down-y keyboard 0x0 81 + +;wswan, Built-In, Gamepad(Rotation Auto-Adjust): X4(X LEFT ←) +wswan.input.builtin.gamepadraa.left-x keyboard 0x0 4 + +;wswan, Built-In, Gamepad(Rotation Auto-Adjust): Y4(Y LEFT ←) +wswan.input.builtin.gamepadraa.left-y keyboard 0x0 80 + +;wswan, Built-In, Gamepad(Rotation Auto-Adjust): X2(X RIGHT →) +wswan.input.builtin.gamepadraa.right-x keyboard 0x0 7 + +;wswan, Built-In, Gamepad(Rotation Auto-Adjust): Y2(Y RIGHT →) +wswan.input.builtin.gamepadraa.right-y keyboard 0x0 79 + +;wswan, Built-In, Gamepad(Rotation Auto-Adjust): Start +wswan.input.builtin.gamepadraa.start keyboard 0x0 40 + +;wswan, Built-In, Gamepad(Rotation Auto-Adjust): X1(X UP ↑) +wswan.input.builtin.gamepadraa.up-x keyboard 0x0 26 + +;wswan, Built-In, Gamepad(Rotation Auto-Adjust): Y1(Y UP ↑) +wswan.input.builtin.gamepadraa.up-y keyboard 0x0 82 + +;Language games should display text in. +wswan.language english + +;Name +wswan.name Mednafen + +;Enable scanlines with specified opacity. +wswan.scanlines 0 + +;Sex +wswan.sex F + +;Enable specified OpenGL shader. +wswan.shader ipsharper + +;Force interlaced video to be treated as progressive. +wswan.shader.goat.fprog 0 + +;Constant RGB horizontal divergence. +wswan.shader.goat.hdiv 0.50 + +;Mask pattern. +wswan.shader.goat.pat goatron + +;Enable scanlines effect. +wswan.shader.goat.slen 1 + +;Transparency of otherwise-opaque mask areas. +wswan.shader.goat.tp 0.50 + +;Constant RGB vertical divergence. +wswan.shader.goat.vdiv 0.50 + +;Enable specified special video scaler. +wswan.special none + +;Stretch to fill screen. +wswan.stretch full + +;Enable video temporal blur(50/50 previous/current frame by default). +wswan.tblur 0 + +;Accumulate color data rather than discarding it. +wswan.tblur.accum 0 + +;Blur amount in accumulation mode, specified in percentage of accumulation buffer to mix with the current frame. +wswan.tblur.accum.amount 50 + +;Enable (bi)linear interpolation. +wswan.videoip 0 + +;Full-screen horizontal resolution. +wswan.xres 0 + +;Scaling factor for the X axis in windowed mode. +wswan.xscale 4.000000 + +;Scaling factor for the X axis in fullscreen mode. +wswan.xscalefs 1.000000 + +;Full-screen vertical resolution. +wswan.yres 0 + +;Scaling factor for the Y axis in windowed mode. +wswan.yscale 4.000000 + +;Scaling factor for the Y axis in fullscreen mode. +wswan.yscalefs 1.000000 + + +; +;Unrecognized settings follow: +; + +command.insert_eject_joystick @GUID1@ @DEVICE_BTN_TL@ + +apple2.enable 1 + +apple2.input.keyboard.twopiece.0 keyboard 0x0 39 + +apple2.input.keyboard.twopiece.1 keyboard 0x0 30 + +apple2.input.keyboard.twopiece.2 keyboard 0x0 31 + +apple2.input.keyboard.twopiece.3 keyboard 0x0 32 + +apple2.input.keyboard.twopiece.4 keyboard 0x0 33 + +apple2.input.keyboard.twopiece.5 keyboard 0x0 34 + +apple2.input.keyboard.twopiece.6 keyboard 0x0 35 + +apple2.input.keyboard.twopiece.7 keyboard 0x0 36 + +apple2.input.keyboard.twopiece.8 keyboard 0x0 37 + +apple2.input.keyboard.twopiece.9 keyboard 0x0 38 + +apple2.input.keyboard.twopiece.a keyboard 0x0 4 || keyboard 0x0 82 || keyboard 0x0 96 + +apple2.input.keyboard.twopiece.b keyboard 0x0 5 + +apple2.input.keyboard.twopiece.bs keyboard 0x0 80 || keyboard 0x0 42 || keyboard 0x0 93 || keyboard 0x0 76 + +apple2.input.keyboard.twopiece.c keyboard 0x0 6 + +apple2.input.keyboard.twopiece.colon keyboard 0x0 45 + +apple2.input.keyboard.twopiece.comma keyboard 0x0 54 + +apple2.input.keyboard.twopiece.cr keyboard 0x0 40 || keyboard 0x0 49 || keyboard 0x0 74 + +apple2.input.keyboard.twopiece.ctrl keyboard 0x0 57 || keyboard 0x0 224 || keyboard 0x0 228 + +apple2.input.keyboard.twopiece.d keyboard 0x0 7 + +apple2.input.keyboard.twopiece.e keyboard 0x0 8 + +apple2.input.keyboard.twopiece.esc keyboard 0x0 41 || keyboard 0x0 43 + +apple2.input.keyboard.twopiece.f keyboard 0x0 9 + +apple2.input.keyboard.twopiece.g keyboard 0x0 10 + +apple2.input.keyboard.twopiece.h keyboard 0x0 11 + +apple2.input.keyboard.twopiece.i keyboard 0x0 12 + +apple2.input.keyboard.twopiece.j keyboard 0x0 13 + +apple2.input.keyboard.twopiece.k keyboard 0x0 14 + +apple2.input.keyboard.twopiece.l keyboard 0x0 15 + +apple2.input.keyboard.twopiece.lshift keyboard 0x0 225 + +apple2.input.keyboard.twopiece.m keyboard 0x0 16 + +apple2.input.keyboard.twopiece.minus keyboard 0x0 46 + +apple2.input.keyboard.twopiece.n keyboard 0x0 17 + +apple2.input.keyboard.twopiece.nak keyboard 0x0 79 || keyboard 0x0 94 || keyboard 0x0 78 + +apple2.input.keyboard.twopiece.o keyboard 0x0 18 + +apple2.input.keyboard.twopiece.p keyboard 0x0 19 + +apple2.input.keyboard.twopiece.period keyboard 0x0 55 + +apple2.input.keyboard.twopiece.q keyboard 0x0 20 + +apple2.input.keyboard.twopiece.r keyboard 0x0 21 + +apple2.input.keyboard.twopiece.rept keyboard 0x0 47 || keyboard 0x0 226 || keyboard 0x0 230 + +apple2.input.keyboard.twopiece.reset keyboard 0x0 73 + +apple2.input.keyboard.twopiece.rshift keyboard 0x0 229 + +apple2.input.keyboard.twopiece.s keyboard 0x0 22 + +apple2.input.keyboard.twopiece.semicolon keyboard 0x0 51 || keyboard 0x0 92 + +apple2.input.keyboard.twopiece.slash keyboard 0x0 56 || keyboard 0x0 77 + +apple2.input.keyboard.twopiece.sp keyboard 0x0 44 + +apple2.input.keyboard.twopiece.t keyboard 0x0 23 + +apple2.input.keyboard.twopiece.u keyboard 0x0 24 + +apple2.input.keyboard.twopiece.v keyboard 0x0 25 + +apple2.input.keyboard.twopiece.w keyboard 0x0 26 + +apple2.input.keyboard.twopiece.x keyboard 0x0 27 + +apple2.input.keyboard.twopiece.y keyboard 0x0 28 + +apple2.input.keyboard.twopiece.z keyboard 0x0 29 || keyboard 0x0 81 || keyboard 0x0 90 + +apple2.input.port1 joystick + +apple2.input.port1.atari.button + +apple2.input.port1.atari.down + +apple2.input.port1.atari.left + +apple2.input.port1.atari.right + +apple2.input.port1.atari.up + +apple2.input.port1.gamepad.button1 + +apple2.input.port1.gamepad.button2 + +apple2.input.port1.gamepad.down + +apple2.input.port1.gamepad.left + +apple2.input.port1.gamepad.resistance_select + +apple2.input.port1.gamepad.resistance_select.defpos 2 + +apple2.input.port1.gamepad.right + +apple2.input.port1.gamepad.up + +apple2.input.port1.joystick.axis_scale 1.00 + +apple2.input.port1.joystick.button1 + +apple2.input.port1.joystick.button2 + +apple2.input.port1.joystick.resistance_select + +apple2.input.port1.joystick.resistance_select.defpos 2 + +apple2.input.port1.joystick.stick_down + +apple2.input.port1.joystick.stick_left + +apple2.input.port1.joystick.stick_right + +apple2.input.port1.joystick.stick_up + +apple2.input.port1.paddle.button + +apple2.input.port1.paddle.dial_left + +apple2.input.port1.paddle.dial_right + +apple2.input.port2 paddle + +apple2.input.port2.atari.button + +apple2.input.port2.atari.down + +apple2.input.port2.atari.left + +apple2.input.port2.atari.right + +apple2.input.port2.atari.up + +apple2.input.port2.paddle.button + +apple2.input.port2.paddle.dial_left + +apple2.input.port2.paddle.dial_right + +apple2.scanlines 0 + +apple2.shader none + +apple2.shader.goat.fprog 0 + +apple2.shader.goat.hdiv 0.50 + +apple2.shader.goat.pat goatron + +apple2.shader.goat.slen 1 + +apple2.shader.goat.tp 0.50 + +apple2.shader.goat.vdiv 0.50 + +apple2.special none + +apple2.stretch aspect + +apple2.tblur 0 + +apple2.tblur.accum 0 + +apple2.tblur.accum.amount 50 + +apple2.video.brightness 0.0 + +apple2.video.color_lumafilter -3 + +apple2.video.color_smooth 0 + +apple2.video.contrast 0.0 + +apple2.video.force_mono 0x000000 + +apple2.video.hue 0.0 + +apple2.video.matrix mednafen + +apple2.video.matrix.blue.i -1.11 + +apple2.video.matrix.blue.q 1.70 + +apple2.video.matrix.green.i -0.28 + +apple2.video.matrix.green.q -0.64 + +apple2.video.matrix.red.i 0.96 + +apple2.video.matrix.red.q 0.62 + +apple2.video.mixed_text_mono 0 + +apple2.video.mode composite + +apple2.video.mono_lumafilter 5 + +apple2.video.saturation 0.0 + +apple2.videoip x + +apple2.xres 0 + +apple2.xscale 4.000000 + +apple2.xscalefs 1.000000 + +apple2.yres 0 + +apple2.yscale 4.000000 + +apple2.yscalefs 1.000000 + +psx.bios_eu scph5502.bin + +psx.bios_jp scph5500.bin + +psx.bios_na scph5501.bin + +psx.bios_sanity 1 + +psx.cd_sanity 1 + +psx.correct_aspect 1 + +psx.dbg_exe_cdpath + +psx.dbg_level 0 + +psx.debugger.disfontsize 5x7 + +psx.debugger.memcharenc shift_jis + +psx.enable 1 + +psx.forcemono 0 + +psx.h_overscan 1 + +psx.input.analog_mode_ct 0 + +psx.input.analog_mode_ct.compare 0x0F09 + +psx.input.mouse_sensitivity 1.00 + +psx.input.port1 gamepad + +psx.input.port1.analogjoy.axis_scale 1.00 + +psx.input.port1.analogjoy.circle joystick @GUID1@ @DEVICE_BTN_EAST@ + +psx.input.port1.analogjoy.cross joystick @GUID1@ @DEVICE_BTN_SOUTH@ + +psx.input.port1.analogjoy.down joystick @GUID1@ @DEVICE_BTN_DPAD_DOWN@ + +psx.input.port1.analogjoy.l1 joystick @GUID1@ @DEVICE_BTN_TL@ + +psx.input.port1.analogjoy.l2 joystick @GUID1@ @DEVICE_BTN_TL2@ + +psx.input.port1.analogjoy.left joystick @GUID1@ @DEVICE_BTN_DPAD_LEFT@ + +psx.input.port1.analogjoy.lstick_down joystick @GUID1@ @DEVICE_BTN_AL_DOWN@ + +psx.input.port1.analogjoy.lstick_left joystick @GUID1@ @DEVICE_BTN_AL_LEFT@ + +psx.input.port1.analogjoy.lstick_right joystick @GUID1@ @DEVICE_BTN_AL_RIGHT@ + +psx.input.port1.analogjoy.lstick_up joystick @GUID1@ @DEVICE_BTN_AL_UP@ + +psx.input.port1.analogjoy.r1 joystick @GUID1@ @DEVICE_BTN_TR@ + +psx.input.port1.analogjoy.r2 joystick @GUID1@ @DEVICE_BTN_TR2@ + +psx.input.port1.analogjoy.right joystick @GUID1@ @DEVICE_BTN_DPAD_RIGHT@ + +psx.input.port1.analogjoy.rstick_down joystick @GUID1@ @DEVICE_BTN_AR_DOWN@ + +psx.input.port1.analogjoy.rstick_left joystick @GUID1@ @DEVICE_BTN_AR_LEFT@ + +psx.input.port1.analogjoy.rstick_right joystick @GUID1@ @DEVICE_BTN_AR_RIGHT@ + +psx.input.port1.analogjoy.rstick_up joystick @GUID1@ @DEVICE_BTN_AR_UP@ + +psx.input.port1.analogjoy.select joystick @GUID1@ @DEVICE_BTN_SELECT@ + +psx.input.port1.analogjoy.square joystick @GUID1@ @DEVICE_BTN_WEST@ + +psx.input.port1.analogjoy.start joystick @GUID1@ @DEVICE_BTN_START@ + +psx.input.port1.analogjoy.triangle joystick @GUID1@ @DEVICE_BTN_NORTH@ + +psx.input.port1.analogjoy.up joystick @GUID1@ @DEVICE_BTN_DPAD_UP@ + +psx.input.port1.dancepad.circle keyboard 0x0 97 + +psx.input.port1.dancepad.cross keyboard 0x0 95 + +psx.input.port1.dancepad.down keyboard 0x0 90 + +psx.input.port1.dancepad.left keyboard 0x0 92 + +psx.input.port1.dancepad.right keyboard 0x0 94 + +psx.input.port1.dancepad.select keyboard 0x0 84 + +psx.input.port1.dancepad.square keyboard 0x0 91 + +psx.input.port1.dancepad.start keyboard 0x0 85 + +psx.input.port1.dancepad.triangle keyboard 0x0 89 + +psx.input.port1.dancepad.up keyboard 0x0 96 + +psx.input.port1.dualanalog.axis_scale 1.00 + +psx.input.port1.dualanalog.circle + +psx.input.port1.dualanalog.cross + +psx.input.port1.dualanalog.down + +psx.input.port1.dualanalog.l1 + +psx.input.port1.dualanalog.l2 + +psx.input.port1.dualanalog.l3 + +psx.input.port1.dualanalog.left + +psx.input.port1.dualanalog.lstick_down + +psx.input.port1.dualanalog.lstick_left + +psx.input.port1.dualanalog.lstick_right + +psx.input.port1.dualanalog.lstick_up + +psx.input.port1.dualanalog.r1 + +psx.input.port1.dualanalog.r2 + +psx.input.port1.dualanalog.r3 + +psx.input.port1.dualanalog.rapid_circle + +psx.input.port1.dualanalog.rapid_cross + +psx.input.port1.dualanalog.rapid_square + +psx.input.port1.dualanalog.rapid_triangle + +psx.input.port1.dualanalog.right + +psx.input.port1.dualanalog.rstick_down + +psx.input.port1.dualanalog.rstick_left + +psx.input.port1.dualanalog.rstick_right + +psx.input.port1.dualanalog.rstick_up + +psx.input.port1.dualanalog.select + +psx.input.port1.dualanalog.square + +psx.input.port1.dualanalog.start + +psx.input.port1.dualanalog.triangle + +psx.input.port1.dualanalog.up + +psx.input.port1.dualshock.analog + +psx.input.port1.dualshock.axis_scale 1.00 + +psx.input.port1.dualshock.circle joystick @GUID1@ @DEVICE_BTN_EAST@ + +psx.input.port1.dualshock.cross joystick @GUID1@ @DEVICE_BTN_SOUTH@ + +psx.input.port1.dualshock.down joystick @GUID1@ @DEVICE_BTN_DPAD_DOWN@ + +psx.input.port1.dualshock.l1 joystick @GUID1@ @DEVICE_BTN_TL@ + +psx.input.port1.dualshock.l2 joystick @GUID1@ @DEVICE_BTN_TL2@ + +psx.input.port1.dualshock.l3 joystick @GUID1@ @DEVICE_BTN_THUMBL@ + +psx.input.port1.dualshock.left joystick @GUID1@ @DEVICE_BTN_DPAD_LEFT@ + +psx.input.port1.dualshock.lstick_down joystick @GUID1@ @DEVICE_BTN_AL_DOWN@ + +psx.input.port1.dualshock.lstick_left joystick @GUID1@ @DEVICE_BTN_AL_LEFT@ + +psx.input.port1.dualshock.lstick_right joystick @GUID1@ @DEVICE_BTN_AL_RIGHT@ + +psx.input.port1.dualshock.lstick_up joystick @GUID1@ @DEVICE_BTN_AL_UP@ + +psx.input.port1.dualshock.r1 joystick @GUID1@ @DEVICE_BTN_TR@ + +psx.input.port1.dualshock.r2 joystick @GUID1@ @DEVICE_BTN_TR2@ + +psx.input.port1.dualshock.r3 joystick @GUID1@ @DEVICE_BTN_THUMBR@ + +psx.input.port1.dualshock.rapid_circle + +psx.input.port1.dualshock.rapid_cross + +psx.input.port1.dualshock.rapid_square + +psx.input.port1.dualshock.rapid_triangle + +psx.input.port1.dualshock.right joystick @GUID1@ @DEVICE_BTN_DPAD_RIGHT@ + +psx.input.port1.dualshock.rstick_down joystick @GUID1@ @DEVICE_BTN_AR_DOWN@ + +psx.input.port1.dualshock.rstick_left joystick @GUID1@ @DEVICE_BTN_AR_LEFT@ + +psx.input.port1.dualshock.rstick_right joystick @GUID1@ @DEVICE_BTN_AR_RIGHT@ + +psx.input.port1.dualshock.rstick_up joystick @GUID1@ @DEVICE_BTN_AR_UP@ + +psx.input.port1.dualshock.select joystick @GUID1@ @DEVICE_BTN_SELECT@ + +psx.input.port1.dualshock.square joystick @GUID1@ @DEVICE_BTN_WEST@ + +psx.input.port1.dualshock.start joystick @GUID1@ @DEVICE_BTN_START@ + +psx.input.port1.dualshock.triangle joystick @GUID1@ @DEVICE_BTN_NORTH@ + +psx.input.port1.dualshock.up joystick @GUID1@ @DEVICE_BTN_DPAD_UP@ + +psx.input.port1.gamepad.circle joystick @GUID1@ @DEVICE_BTN_EAST@ + +psx.input.port1.gamepad.cross joystick @GUID1@ @DEVICE_BTN_SOUTH@ + +psx.input.port1.gamepad.down joystick @GUID1@ @DEVICE_BTN_DPAD_DOWN@ + +psx.input.port1.gamepad.l1 joystick @GUID1@ @DEVICE_BTN_TL@ + +psx.input.port1.gamepad.l2 joystick @GUID1@ @DEVICE_BTN_TL2@ + +psx.input.port1.gamepad.left joystick @GUID1@ @DEVICE_BTN_DPAD_LEFT@ + +psx.input.port1.gamepad.r1 joystick @GUID1@ @DEVICE_BTN_TR@ + +psx.input.port1.gamepad.r2 joystick @GUID1@ @DEVICE_BTN_TR2@ + +psx.input.port1.gamepad.rapid_circle + +psx.input.port1.gamepad.rapid_cross + +psx.input.port1.gamepad.rapid_square + +psx.input.port1.gamepad.rapid_triangle + +psx.input.port1.gamepad.right joystick @GUID1@ @DEVICE_BTN_DPAD_RIGHT@ + +psx.input.port1.gamepad.select joystick @GUID1@ @DEVICE_BTN_SELECT@ + +psx.input.port1.gamepad.square joystick @GUID1@ @DEVICE_BTN_WEST@ + +psx.input.port1.gamepad.start joystick @GUID1@ @DEVICE_BTN_START@ + +psx.input.port1.gamepad.triangle joystick @GUID1@ @DEVICE_BTN_NORTH@ + +psx.input.port1.gamepad.up joystick @GUID1@ @DEVICE_BTN_DPAD_UP@ + +psx.input.port1.gun_chairs 0xFF0000 + +psx.input.port1.guncon.a mouse 0x0 button_right + +psx.input.port1.guncon.b mouse 0x0 button_middle + +psx.input.port1.guncon.offscreen_shot keyboard 0x0 44 + +psx.input.port1.guncon.trigger mouse 0x0 button_left + +psx.input.port1.guncon.x_axis mouse 0x0 cursor_x-+ + +psx.input.port1.guncon.y_axis mouse 0x0 cursor_y-+ + +psx.input.port1.justifier.o mouse 0x0 button_right + +psx.input.port1.justifier.offscreen_shot keyboard 0x0 44 + +psx.input.port1.justifier.start mouse 0x0 button_middle + +psx.input.port1.justifier.trigger mouse 0x0 button_left + +psx.input.port1.justifier.x_axis mouse 0x0 cursor_x-+ + +psx.input.port1.justifier.y_axis mouse 0x0 cursor_y-+ + +psx.input.port1.memcard 1 + +psx.input.port1.mouse.left mouse 0x0 button_left + +psx.input.port1.mouse.motion_down mouse 0x0 rel_y+ + +psx.input.port1.mouse.motion_left mouse 0x0 rel_x- + +psx.input.port1.mouse.motion_right mouse 0x0 rel_x+ + +psx.input.port1.mouse.motion_up mouse 0x0 rel_y- + +psx.input.port1.mouse.right mouse 0x0 button_right + +psx.input.port1.negcon.a + +psx.input.port1.negcon.b + +psx.input.port1.negcon.down + +psx.input.port1.negcon.i + +psx.input.port1.negcon.ii + +psx.input.port1.negcon.l + +psx.input.port1.negcon.left + +psx.input.port1.negcon.r + +psx.input.port1.negcon.right + +psx.input.port1.negcon.start + +psx.input.port1.negcon.twist_ccwise + +psx.input.port1.negcon.twist_cwise + +psx.input.port1.negcon.up + +psx.input.port2 gamepad + +psx.input.port2.analogjoy.axis_scale 1.00 + +psx.input.port2.analogjoy.circle + +psx.input.port2.analogjoy.cross + +psx.input.port2.analogjoy.down + +psx.input.port2.analogjoy.l1 + +psx.input.port2.analogjoy.l2 + +psx.input.port2.analogjoy.left + +psx.input.port2.analogjoy.lstick_down + +psx.input.port2.analogjoy.lstick_left + +psx.input.port2.analogjoy.lstick_right + +psx.input.port2.analogjoy.lstick_up + +psx.input.port2.analogjoy.r1 + +psx.input.port2.analogjoy.r2 + +psx.input.port2.analogjoy.right + +psx.input.port2.analogjoy.rstick_down + +psx.input.port2.analogjoy.rstick_left + +psx.input.port2.analogjoy.rstick_right + +psx.input.port2.analogjoy.rstick_up + +psx.input.port2.analogjoy.select + +psx.input.port2.analogjoy.square + +psx.input.port2.analogjoy.start + +psx.input.port2.analogjoy.triangle + +psx.input.port2.analogjoy.up + +psx.input.port2.dancepad.circle + +psx.input.port2.dancepad.cross + +psx.input.port2.dancepad.down + +psx.input.port2.dancepad.left + +psx.input.port2.dancepad.right + +psx.input.port2.dancepad.select + +psx.input.port2.dancepad.square + +psx.input.port2.dancepad.start + +psx.input.port2.dancepad.triangle + +psx.input.port2.dancepad.up + +psx.input.port2.dualanalog.axis_scale 1.00 + +psx.input.port2.dualanalog.circle + +psx.input.port2.dualanalog.cross + +psx.input.port2.dualanalog.down + +psx.input.port2.dualanalog.l1 + +psx.input.port2.dualanalog.l2 + +psx.input.port2.dualanalog.l3 + +psx.input.port2.dualanalog.left + +psx.input.port2.dualanalog.lstick_down + +psx.input.port2.dualanalog.lstick_left + +psx.input.port2.dualanalog.lstick_right + +psx.input.port2.dualanalog.lstick_up + +psx.input.port2.dualanalog.r1 + +psx.input.port2.dualanalog.r2 + +psx.input.port2.dualanalog.r3 + +psx.input.port2.dualanalog.rapid_circle + +psx.input.port2.dualanalog.rapid_cross + +psx.input.port2.dualanalog.rapid_square + +psx.input.port2.dualanalog.rapid_triangle + +psx.input.port2.dualanalog.right + +psx.input.port2.dualanalog.rstick_down + +psx.input.port2.dualanalog.rstick_left + +psx.input.port2.dualanalog.rstick_right + +psx.input.port2.dualanalog.rstick_up + +psx.input.port2.dualanalog.select + +psx.input.port2.dualanalog.square + +psx.input.port2.dualanalog.start + +psx.input.port2.dualanalog.triangle + +psx.input.port2.dualanalog.up + +psx.input.port2.dualshock.analog + +psx.input.port2.dualshock.axis_scale 1.00 + +psx.input.port2.dualshock.circle + +psx.input.port2.dualshock.cross + +psx.input.port2.dualshock.down + +psx.input.port2.dualshock.l1 + +psx.input.port2.dualshock.l2 + +psx.input.port2.dualshock.l3 + +psx.input.port2.dualshock.left + +psx.input.port2.dualshock.lstick_down + +psx.input.port2.dualshock.lstick_left + +psx.input.port2.dualshock.lstick_right + +psx.input.port2.dualshock.lstick_up + +psx.input.port2.dualshock.r1 + +psx.input.port2.dualshock.r2 + +psx.input.port2.dualshock.r3 + +psx.input.port2.dualshock.rapid_circle + +psx.input.port2.dualshock.rapid_cross + +psx.input.port2.dualshock.rapid_square + +psx.input.port2.dualshock.rapid_triangle + +psx.input.port2.dualshock.right + +psx.input.port2.dualshock.rstick_down + +psx.input.port2.dualshock.rstick_left + +psx.input.port2.dualshock.rstick_right + +psx.input.port2.dualshock.rstick_up + +psx.input.port2.dualshock.select + +psx.input.port2.dualshock.square + +psx.input.port2.dualshock.start + +psx.input.port2.dualshock.triangle + +psx.input.port2.dualshock.up + +psx.input.port2.gamepad.circle + +psx.input.port2.gamepad.cross + +psx.input.port2.gamepad.down + +psx.input.port2.gamepad.l1 + +psx.input.port2.gamepad.l2 + +psx.input.port2.gamepad.left + +psx.input.port2.gamepad.r1 + +psx.input.port2.gamepad.r2 + +psx.input.port2.gamepad.rapid_circle + +psx.input.port2.gamepad.rapid_cross + +psx.input.port2.gamepad.rapid_square + +psx.input.port2.gamepad.rapid_triangle + +psx.input.port2.gamepad.right + +psx.input.port2.gamepad.select + +psx.input.port2.gamepad.square + +psx.input.port2.gamepad.start + +psx.input.port2.gamepad.triangle + +psx.input.port2.gamepad.up + +psx.input.port2.gun_chairs 0x00FF00 + +psx.input.port2.guncon.a mouse 0x0 button_right + +psx.input.port2.guncon.b mouse 0x0 button_middle + +psx.input.port2.guncon.offscreen_shot keyboard 0x0 44 + +psx.input.port2.guncon.trigger mouse 0x0 button_left + +psx.input.port2.guncon.x_axis mouse 0x0 cursor_x-+ + +psx.input.port2.guncon.y_axis mouse 0x0 cursor_y-+ + +psx.input.port2.justifier.o mouse 0x0 button_right + +psx.input.port2.justifier.offscreen_shot keyboard 0x0 44 + +psx.input.port2.justifier.start mouse 0x0 button_middle + +psx.input.port2.justifier.trigger mouse 0x0 button_left + +psx.input.port2.justifier.x_axis mouse 0x0 cursor_x-+ + +psx.input.port2.justifier.y_axis mouse 0x0 cursor_y-+ + +psx.input.port2.memcard 1 + +psx.input.port2.mouse.left mouse 0x0 button_left + +psx.input.port2.mouse.motion_down mouse 0x0 rel_y+ + +psx.input.port2.mouse.motion_left mouse 0x0 rel_x- + +psx.input.port2.mouse.motion_right mouse 0x0 rel_x+ + +psx.input.port2.mouse.motion_up mouse 0x0 rel_y- + +psx.input.port2.mouse.right mouse 0x0 button_right + +psx.input.port2.negcon.a + +psx.input.port2.negcon.b + +psx.input.port2.negcon.down + +psx.input.port2.negcon.i + +psx.input.port2.negcon.ii + +psx.input.port2.negcon.l + +psx.input.port2.negcon.left + +psx.input.port2.negcon.r + +psx.input.port2.negcon.right + +psx.input.port2.negcon.start + +psx.input.port2.negcon.twist_ccwise + +psx.input.port2.negcon.twist_cwise + +psx.input.port2.negcon.up + +psx.input.port3 gamepad + +psx.input.port3.analogjoy.axis_scale 1.00 + +psx.input.port3.analogjoy.circle + +psx.input.port3.analogjoy.cross + +psx.input.port3.analogjoy.down + +psx.input.port3.analogjoy.l1 + +psx.input.port3.analogjoy.l2 + +psx.input.port3.analogjoy.left + +psx.input.port3.analogjoy.lstick_down + +psx.input.port3.analogjoy.lstick_left + +psx.input.port3.analogjoy.lstick_right + +psx.input.port3.analogjoy.lstick_up + +psx.input.port3.analogjoy.r1 + +psx.input.port3.analogjoy.r2 + +psx.input.port3.analogjoy.right + +psx.input.port3.analogjoy.rstick_down + +psx.input.port3.analogjoy.rstick_left + +psx.input.port3.analogjoy.rstick_right + +psx.input.port3.analogjoy.rstick_up + +psx.input.port3.analogjoy.select + +psx.input.port3.analogjoy.square + +psx.input.port3.analogjoy.start + +psx.input.port3.analogjoy.triangle + +psx.input.port3.analogjoy.up + +psx.input.port3.dancepad.circle + +psx.input.port3.dancepad.cross + +psx.input.port3.dancepad.down + +psx.input.port3.dancepad.left + +psx.input.port3.dancepad.right + +psx.input.port3.dancepad.select + +psx.input.port3.dancepad.square + +psx.input.port3.dancepad.start + +psx.input.port3.dancepad.triangle + +psx.input.port3.dancepad.up + +psx.input.port3.dualanalog.axis_scale 1.00 + +psx.input.port3.dualanalog.circle + +psx.input.port3.dualanalog.cross + +psx.input.port3.dualanalog.down + +psx.input.port3.dualanalog.l1 + +psx.input.port3.dualanalog.l2 + +psx.input.port3.dualanalog.l3 + +psx.input.port3.dualanalog.left + +psx.input.port3.dualanalog.lstick_down + +psx.input.port3.dualanalog.lstick_left + +psx.input.port3.dualanalog.lstick_right + +psx.input.port3.dualanalog.lstick_up + +psx.input.port3.dualanalog.r1 + +psx.input.port3.dualanalog.r2 + +psx.input.port3.dualanalog.r3 + +psx.input.port3.dualanalog.rapid_circle + +psx.input.port3.dualanalog.rapid_cross + +psx.input.port3.dualanalog.rapid_square + +psx.input.port3.dualanalog.rapid_triangle + +psx.input.port3.dualanalog.right + +psx.input.port3.dualanalog.rstick_down + +psx.input.port3.dualanalog.rstick_left + +psx.input.port3.dualanalog.rstick_right + +psx.input.port3.dualanalog.rstick_up + +psx.input.port3.dualanalog.select + +psx.input.port3.dualanalog.square + +psx.input.port3.dualanalog.start + +psx.input.port3.dualanalog.triangle + +psx.input.port3.dualanalog.up + +psx.input.port3.dualshock.analog + +psx.input.port3.dualshock.axis_scale 1.00 + +psx.input.port3.dualshock.circle + +psx.input.port3.dualshock.cross + +psx.input.port3.dualshock.down + +psx.input.port3.dualshock.l1 + +psx.input.port3.dualshock.l2 + +psx.input.port3.dualshock.l3 + +psx.input.port3.dualshock.left + +psx.input.port3.dualshock.lstick_down + +psx.input.port3.dualshock.lstick_left + +psx.input.port3.dualshock.lstick_right + +psx.input.port3.dualshock.lstick_up + +psx.input.port3.dualshock.r1 + +psx.input.port3.dualshock.r2 + +psx.input.port3.dualshock.r3 + +psx.input.port3.dualshock.rapid_circle + +psx.input.port3.dualshock.rapid_cross + +psx.input.port3.dualshock.rapid_square + +psx.input.port3.dualshock.rapid_triangle + +psx.input.port3.dualshock.right + +psx.input.port3.dualshock.rstick_down + +psx.input.port3.dualshock.rstick_left + +psx.input.port3.dualshock.rstick_right + +psx.input.port3.dualshock.rstick_up + +psx.input.port3.dualshock.select + +psx.input.port3.dualshock.square + +psx.input.port3.dualshock.start + +psx.input.port3.dualshock.triangle + +psx.input.port3.dualshock.up + +psx.input.port3.gamepad.circle + +psx.input.port3.gamepad.cross + +psx.input.port3.gamepad.down + +psx.input.port3.gamepad.l1 + +psx.input.port3.gamepad.l2 + +psx.input.port3.gamepad.left + +psx.input.port3.gamepad.r1 + +psx.input.port3.gamepad.r2 + +psx.input.port3.gamepad.rapid_circle + +psx.input.port3.gamepad.rapid_cross + +psx.input.port3.gamepad.rapid_square + +psx.input.port3.gamepad.rapid_triangle + +psx.input.port3.gamepad.right + +psx.input.port3.gamepad.select + +psx.input.port3.gamepad.square + +psx.input.port3.gamepad.start + +psx.input.port3.gamepad.triangle + +psx.input.port3.gamepad.up + +psx.input.port3.gun_chairs 0xFF00FF + +psx.input.port3.guncon.a mouse 0x0 button_right + +psx.input.port3.guncon.b mouse 0x0 button_middle + +psx.input.port3.guncon.offscreen_shot keyboard 0x0 44 + +psx.input.port3.guncon.trigger mouse 0x0 button_left + +psx.input.port3.guncon.x_axis mouse 0x0 cursor_x-+ + +psx.input.port3.guncon.y_axis mouse 0x0 cursor_y-+ + +psx.input.port3.justifier.o + +psx.input.port3.justifier.offscreen_shot + +psx.input.port3.justifier.start + +psx.input.port3.justifier.trigger + +psx.input.port3.justifier.x_axis + +psx.input.port3.justifier.y_axis + +psx.input.port3.memcard 1 + +psx.input.port3.mouse.left mouse 0x0 button_left + +psx.input.port3.mouse.motion_down mouse 0x0 rel_y+ + +psx.input.port3.mouse.motion_left mouse 0x0 rel_x- + +psx.input.port3.mouse.motion_right mouse 0x0 rel_x+ + +psx.input.port3.mouse.motion_up mouse 0x0 rel_y- + +psx.input.port3.mouse.right mouse 0x0 button_right + +psx.input.port3.negcon.a + +psx.input.port3.negcon.b + +psx.input.port3.negcon.down + +psx.input.port3.negcon.i + +psx.input.port3.negcon.ii + +psx.input.port3.negcon.l + +psx.input.port3.negcon.left + +psx.input.port3.negcon.r + +psx.input.port3.negcon.right + +psx.input.port3.negcon.start + +psx.input.port3.negcon.twist_ccwise + +psx.input.port3.negcon.twist_cwise + +psx.input.port3.negcon.up + +psx.input.port4 gamepad + +psx.input.port4.analogjoy.axis_scale 1.00 + +psx.input.port4.analogjoy.circle + +psx.input.port4.analogjoy.cross + +psx.input.port4.analogjoy.down + +psx.input.port4.analogjoy.l1 + +psx.input.port4.analogjoy.l2 + +psx.input.port4.analogjoy.left + +psx.input.port4.analogjoy.lstick_down + +psx.input.port4.analogjoy.lstick_left + +psx.input.port4.analogjoy.lstick_right + +psx.input.port4.analogjoy.lstick_up + +psx.input.port4.analogjoy.r1 + +psx.input.port4.analogjoy.r2 + +psx.input.port4.analogjoy.right + +psx.input.port4.analogjoy.rstick_down + +psx.input.port4.analogjoy.rstick_left + +psx.input.port4.analogjoy.rstick_right + +psx.input.port4.analogjoy.rstick_up + +psx.input.port4.analogjoy.select + +psx.input.port4.analogjoy.square + +psx.input.port4.analogjoy.start + +psx.input.port4.analogjoy.triangle + +psx.input.port4.analogjoy.up + +psx.input.port4.dancepad.circle + +psx.input.port4.dancepad.cross + +psx.input.port4.dancepad.down + +psx.input.port4.dancepad.left + +psx.input.port4.dancepad.right + +psx.input.port4.dancepad.select + +psx.input.port4.dancepad.square + +psx.input.port4.dancepad.start + +psx.input.port4.dancepad.triangle + +psx.input.port4.dancepad.up + +psx.input.port4.dualanalog.axis_scale 1.00 + +psx.input.port4.dualanalog.circle + +psx.input.port4.dualanalog.cross + +psx.input.port4.dualanalog.down + +psx.input.port4.dualanalog.l1 + +psx.input.port4.dualanalog.l2 + +psx.input.port4.dualanalog.l3 + +psx.input.port4.dualanalog.left + +psx.input.port4.dualanalog.lstick_down + +psx.input.port4.dualanalog.lstick_left + +psx.input.port4.dualanalog.lstick_right + +psx.input.port4.dualanalog.lstick_up + +psx.input.port4.dualanalog.r1 + +psx.input.port4.dualanalog.r2 + +psx.input.port4.dualanalog.r3 + +psx.input.port4.dualanalog.rapid_circle + +psx.input.port4.dualanalog.rapid_cross + +psx.input.port4.dualanalog.rapid_square + +psx.input.port4.dualanalog.rapid_triangle + +psx.input.port4.dualanalog.right + +psx.input.port4.dualanalog.rstick_down + +psx.input.port4.dualanalog.rstick_left + +psx.input.port4.dualanalog.rstick_right + +psx.input.port4.dualanalog.rstick_up + +psx.input.port4.dualanalog.select + +psx.input.port4.dualanalog.square + +psx.input.port4.dualanalog.start + +psx.input.port4.dualanalog.triangle + +psx.input.port4.dualanalog.up + +psx.input.port4.dualshock.analog + +psx.input.port4.dualshock.axis_scale 1.00 + +psx.input.port4.dualshock.circle + +psx.input.port4.dualshock.cross + +psx.input.port4.dualshock.down + +psx.input.port4.dualshock.l1 + +psx.input.port4.dualshock.l2 + +psx.input.port4.dualshock.l3 + +psx.input.port4.dualshock.left + +psx.input.port4.dualshock.lstick_down + +psx.input.port4.dualshock.lstick_left + +psx.input.port4.dualshock.lstick_right + +psx.input.port4.dualshock.lstick_up + +psx.input.port4.dualshock.r1 + +psx.input.port4.dualshock.r2 + +psx.input.port4.dualshock.r3 + +psx.input.port4.dualshock.rapid_circle + +psx.input.port4.dualshock.rapid_cross + +psx.input.port4.dualshock.rapid_square + +psx.input.port4.dualshock.rapid_triangle + +psx.input.port4.dualshock.right + +psx.input.port4.dualshock.rstick_down + +psx.input.port4.dualshock.rstick_left + +psx.input.port4.dualshock.rstick_right + +psx.input.port4.dualshock.rstick_up + +psx.input.port4.dualshock.select + +psx.input.port4.dualshock.square + +psx.input.port4.dualshock.start + +psx.input.port4.dualshock.triangle + +psx.input.port4.dualshock.up + +psx.input.port4.gamepad.circle + +psx.input.port4.gamepad.cross + +psx.input.port4.gamepad.down + +psx.input.port4.gamepad.l1 + +psx.input.port4.gamepad.l2 + +psx.input.port4.gamepad.left + +psx.input.port4.gamepad.r1 + +psx.input.port4.gamepad.r2 + +psx.input.port4.gamepad.rapid_circle + +psx.input.port4.gamepad.rapid_cross + +psx.input.port4.gamepad.rapid_square + +psx.input.port4.gamepad.rapid_triangle + +psx.input.port4.gamepad.right + +psx.input.port4.gamepad.select + +psx.input.port4.gamepad.square + +psx.input.port4.gamepad.start + +psx.input.port4.gamepad.triangle + +psx.input.port4.gamepad.up + +psx.input.port4.gun_chairs 0xFF8000 + +psx.input.port4.guncon.a mouse 0x0 button_right + +psx.input.port4.guncon.b mouse 0x0 button_middle + +psx.input.port4.guncon.offscreen_shot keyboard 0x0 44 + +psx.input.port4.guncon.trigger mouse 0x0 button_left + +psx.input.port4.guncon.x_axis mouse 0x0 cursor_x-+ + +psx.input.port4.guncon.y_axis mouse 0x0 cursor_y-+ + +psx.input.port4.justifier.o + +psx.input.port4.justifier.offscreen_shot + +psx.input.port4.justifier.start + +psx.input.port4.justifier.trigger + +psx.input.port4.justifier.x_axis + +psx.input.port4.justifier.y_axis + +psx.input.port4.memcard 1 + +psx.input.port4.mouse.left mouse 0x0 button_left + +psx.input.port4.mouse.motion_down mouse 0x0 rel_y+ + +psx.input.port4.mouse.motion_left mouse 0x0 rel_x- + +psx.input.port4.mouse.motion_right mouse 0x0 rel_x+ + +psx.input.port4.mouse.motion_up mouse 0x0 rel_y- + +psx.input.port4.mouse.right mouse 0x0 button_right + +psx.input.port4.negcon.a + +psx.input.port4.negcon.b + +psx.input.port4.negcon.down + +psx.input.port4.negcon.i + +psx.input.port4.negcon.ii + +psx.input.port4.negcon.l + +psx.input.port4.negcon.left + +psx.input.port4.negcon.r + +psx.input.port4.negcon.right + +psx.input.port4.negcon.start + +psx.input.port4.negcon.twist_ccwise + +psx.input.port4.negcon.twist_cwise + +psx.input.port4.negcon.up + +psx.input.port5 gamepad + +psx.input.port5.analogjoy.axis_scale 1.00 + +psx.input.port5.analogjoy.circle + +psx.input.port5.analogjoy.cross + +psx.input.port5.analogjoy.down + +psx.input.port5.analogjoy.l1 + +psx.input.port5.analogjoy.l2 + +psx.input.port5.analogjoy.left + +psx.input.port5.analogjoy.lstick_down + +psx.input.port5.analogjoy.lstick_left + +psx.input.port5.analogjoy.lstick_right + +psx.input.port5.analogjoy.lstick_up + +psx.input.port5.analogjoy.r1 + +psx.input.port5.analogjoy.r2 + +psx.input.port5.analogjoy.right + +psx.input.port5.analogjoy.rstick_down + +psx.input.port5.analogjoy.rstick_left + +psx.input.port5.analogjoy.rstick_right + +psx.input.port5.analogjoy.rstick_up + +psx.input.port5.analogjoy.select + +psx.input.port5.analogjoy.square + +psx.input.port5.analogjoy.start + +psx.input.port5.analogjoy.triangle + +psx.input.port5.analogjoy.up + +psx.input.port5.dancepad.circle + +psx.input.port5.dancepad.cross + +psx.input.port5.dancepad.down + +psx.input.port5.dancepad.left + +psx.input.port5.dancepad.right + +psx.input.port5.dancepad.select + +psx.input.port5.dancepad.square + +psx.input.port5.dancepad.start + +psx.input.port5.dancepad.triangle + +psx.input.port5.dancepad.up + +psx.input.port5.dualanalog.axis_scale 1.00 + +psx.input.port5.dualanalog.circle + +psx.input.port5.dualanalog.cross + +psx.input.port5.dualanalog.down + +psx.input.port5.dualanalog.l1 + +psx.input.port5.dualanalog.l2 + +psx.input.port5.dualanalog.l3 + +psx.input.port5.dualanalog.left + +psx.input.port5.dualanalog.lstick_down + +psx.input.port5.dualanalog.lstick_left + +psx.input.port5.dualanalog.lstick_right + +psx.input.port5.dualanalog.lstick_up + +psx.input.port5.dualanalog.r1 + +psx.input.port5.dualanalog.r2 + +psx.input.port5.dualanalog.r3 + +psx.input.port5.dualanalog.rapid_circle + +psx.input.port5.dualanalog.rapid_cross + +psx.input.port5.dualanalog.rapid_square + +psx.input.port5.dualanalog.rapid_triangle + +psx.input.port5.dualanalog.right + +psx.input.port5.dualanalog.rstick_down + +psx.input.port5.dualanalog.rstick_left + +psx.input.port5.dualanalog.rstick_right + +psx.input.port5.dualanalog.rstick_up + +psx.input.port5.dualanalog.select + +psx.input.port5.dualanalog.square + +psx.input.port5.dualanalog.start + +psx.input.port5.dualanalog.triangle + +psx.input.port5.dualanalog.up + +psx.input.port5.dualshock.analog + +psx.input.port5.dualshock.axis_scale 1.00 + +psx.input.port5.dualshock.circle + +psx.input.port5.dualshock.cross + +psx.input.port5.dualshock.down + +psx.input.port5.dualshock.l1 + +psx.input.port5.dualshock.l2 + +psx.input.port5.dualshock.l3 + +psx.input.port5.dualshock.left + +psx.input.port5.dualshock.lstick_down + +psx.input.port5.dualshock.lstick_left + +psx.input.port5.dualshock.lstick_right + +psx.input.port5.dualshock.lstick_up + +psx.input.port5.dualshock.r1 + +psx.input.port5.dualshock.r2 + +psx.input.port5.dualshock.r3 + +psx.input.port5.dualshock.rapid_circle + +psx.input.port5.dualshock.rapid_cross + +psx.input.port5.dualshock.rapid_square + +psx.input.port5.dualshock.rapid_triangle + +psx.input.port5.dualshock.right + +psx.input.port5.dualshock.rstick_down + +psx.input.port5.dualshock.rstick_left + +psx.input.port5.dualshock.rstick_right + +psx.input.port5.dualshock.rstick_up + +psx.input.port5.dualshock.select + +psx.input.port5.dualshock.square + +psx.input.port5.dualshock.start + +psx.input.port5.dualshock.triangle + +psx.input.port5.dualshock.up + +psx.input.port5.gamepad.circle + +psx.input.port5.gamepad.cross + +psx.input.port5.gamepad.down + +psx.input.port5.gamepad.l1 + +psx.input.port5.gamepad.l2 + +psx.input.port5.gamepad.left + +psx.input.port5.gamepad.r1 + +psx.input.port5.gamepad.r2 + +psx.input.port5.gamepad.rapid_circle + +psx.input.port5.gamepad.rapid_cross + +psx.input.port5.gamepad.rapid_square + +psx.input.port5.gamepad.rapid_triangle + +psx.input.port5.gamepad.right + +psx.input.port5.gamepad.select + +psx.input.port5.gamepad.square + +psx.input.port5.gamepad.start + +psx.input.port5.gamepad.triangle + +psx.input.port5.gamepad.up + +psx.input.port5.gun_chairs 0xFFFF00 + +psx.input.port5.guncon.a mouse 0x0 button_right + +psx.input.port5.guncon.b mouse 0x0 button_middle + +psx.input.port5.guncon.offscreen_shot keyboard 0x0 44 + +psx.input.port5.guncon.trigger mouse 0x0 button_left + +psx.input.port5.guncon.x_axis mouse 0x0 cursor_x-+ + +psx.input.port5.guncon.y_axis mouse 0x0 cursor_y-+ + +psx.input.port5.justifier.o + +psx.input.port5.justifier.offscreen_shot + +psx.input.port5.justifier.start + +psx.input.port5.justifier.trigger + +psx.input.port5.justifier.x_axis + +psx.input.port5.justifier.y_axis + +psx.input.port5.memcard 1 + +psx.input.port5.mouse.left mouse 0x0 button_left + +psx.input.port5.mouse.motion_down mouse 0x0 rel_y+ + +psx.input.port5.mouse.motion_left mouse 0x0 rel_x- + +psx.input.port5.mouse.motion_right mouse 0x0 rel_x+ + +psx.input.port5.mouse.motion_up mouse 0x0 rel_y- + +psx.input.port5.mouse.right mouse 0x0 button_right + +psx.input.port5.negcon.a + +psx.input.port5.negcon.b + +psx.input.port5.negcon.down + +psx.input.port5.negcon.i + +psx.input.port5.negcon.ii + +psx.input.port5.negcon.l + +psx.input.port5.negcon.left + +psx.input.port5.negcon.r + +psx.input.port5.negcon.right + +psx.input.port5.negcon.start + +psx.input.port5.negcon.twist_ccwise + +psx.input.port5.negcon.twist_cwise + +psx.input.port5.negcon.up + +psx.input.port6 gamepad + +psx.input.port6.analogjoy.axis_scale 1.00 + +psx.input.port6.analogjoy.circle + +psx.input.port6.analogjoy.cross + +psx.input.port6.analogjoy.down + +psx.input.port6.analogjoy.l1 + +psx.input.port6.analogjoy.l2 + +psx.input.port6.analogjoy.left + +psx.input.port6.analogjoy.lstick_down + +psx.input.port6.analogjoy.lstick_left + +psx.input.port6.analogjoy.lstick_right + +psx.input.port6.analogjoy.lstick_up + +psx.input.port6.analogjoy.r1 + +psx.input.port6.analogjoy.r2 + +psx.input.port6.analogjoy.right + +psx.input.port6.analogjoy.rstick_down + +psx.input.port6.analogjoy.rstick_left + +psx.input.port6.analogjoy.rstick_right + +psx.input.port6.analogjoy.rstick_up + +psx.input.port6.analogjoy.select + +psx.input.port6.analogjoy.square + +psx.input.port6.analogjoy.start + +psx.input.port6.analogjoy.triangle + +psx.input.port6.analogjoy.up + +psx.input.port6.dancepad.circle + +psx.input.port6.dancepad.cross + +psx.input.port6.dancepad.down + +psx.input.port6.dancepad.left + +psx.input.port6.dancepad.right + +psx.input.port6.dancepad.select + +psx.input.port6.dancepad.square + +psx.input.port6.dancepad.start + +psx.input.port6.dancepad.triangle + +psx.input.port6.dancepad.up + +psx.input.port6.dualanalog.axis_scale 1.00 + +psx.input.port6.dualanalog.circle + +psx.input.port6.dualanalog.cross + +psx.input.port6.dualanalog.down + +psx.input.port6.dualanalog.l1 + +psx.input.port6.dualanalog.l2 + +psx.input.port6.dualanalog.l3 + +psx.input.port6.dualanalog.left + +psx.input.port6.dualanalog.lstick_down + +psx.input.port6.dualanalog.lstick_left + +psx.input.port6.dualanalog.lstick_right + +psx.input.port6.dualanalog.lstick_up + +psx.input.port6.dualanalog.r1 + +psx.input.port6.dualanalog.r2 + +psx.input.port6.dualanalog.r3 + +psx.input.port6.dualanalog.rapid_circle + +psx.input.port6.dualanalog.rapid_cross + +psx.input.port6.dualanalog.rapid_square + +psx.input.port6.dualanalog.rapid_triangle + +psx.input.port6.dualanalog.right + +psx.input.port6.dualanalog.rstick_down + +psx.input.port6.dualanalog.rstick_left + +psx.input.port6.dualanalog.rstick_right + +psx.input.port6.dualanalog.rstick_up + +psx.input.port6.dualanalog.select + +psx.input.port6.dualanalog.square + +psx.input.port6.dualanalog.start + +psx.input.port6.dualanalog.triangle + +psx.input.port6.dualanalog.up + +psx.input.port6.dualshock.analog + +psx.input.port6.dualshock.axis_scale 1.00 + +psx.input.port6.dualshock.circle + +psx.input.port6.dualshock.cross + +psx.input.port6.dualshock.down + +psx.input.port6.dualshock.l1 + +psx.input.port6.dualshock.l2 + +psx.input.port6.dualshock.l3 + +psx.input.port6.dualshock.left + +psx.input.port6.dualshock.lstick_down + +psx.input.port6.dualshock.lstick_left + +psx.input.port6.dualshock.lstick_right + +psx.input.port6.dualshock.lstick_up + +psx.input.port6.dualshock.r1 + +psx.input.port6.dualshock.r2 + +psx.input.port6.dualshock.r3 + +psx.input.port6.dualshock.rapid_circle + +psx.input.port6.dualshock.rapid_cross + +psx.input.port6.dualshock.rapid_square + +psx.input.port6.dualshock.rapid_triangle + +psx.input.port6.dualshock.right + +psx.input.port6.dualshock.rstick_down + +psx.input.port6.dualshock.rstick_left + +psx.input.port6.dualshock.rstick_right + +psx.input.port6.dualshock.rstick_up + +psx.input.port6.dualshock.select + +psx.input.port6.dualshock.square + +psx.input.port6.dualshock.start + +psx.input.port6.dualshock.triangle + +psx.input.port6.dualshock.up + +psx.input.port6.gamepad.circle + +psx.input.port6.gamepad.cross + +psx.input.port6.gamepad.down + +psx.input.port6.gamepad.l1 + +psx.input.port6.gamepad.l2 + +psx.input.port6.gamepad.left + +psx.input.port6.gamepad.r1 + +psx.input.port6.gamepad.r2 + +psx.input.port6.gamepad.rapid_circle + +psx.input.port6.gamepad.rapid_cross + +psx.input.port6.gamepad.rapid_square + +psx.input.port6.gamepad.rapid_triangle + +psx.input.port6.gamepad.right + +psx.input.port6.gamepad.select + +psx.input.port6.gamepad.square + +psx.input.port6.gamepad.start + +psx.input.port6.gamepad.triangle + +psx.input.port6.gamepad.up + +psx.input.port6.gun_chairs 0x00FFFF + +psx.input.port6.guncon.a mouse 0x0 button_right + +psx.input.port6.guncon.b mouse 0x0 button_middle + +psx.input.port6.guncon.offscreen_shot keyboard 0x0 44 + +psx.input.port6.guncon.trigger mouse 0x0 button_left + +psx.input.port6.guncon.x_axis mouse 0x0 cursor_x-+ + +psx.input.port6.guncon.y_axis mouse 0x0 cursor_y-+ + +psx.input.port6.justifier.o + +psx.input.port6.justifier.offscreen_shot + +psx.input.port6.justifier.start + +psx.input.port6.justifier.trigger + +psx.input.port6.justifier.x_axis + +psx.input.port6.justifier.y_axis + +psx.input.port6.memcard 1 + +psx.input.port6.mouse.left mouse 0x0 button_left + +psx.input.port6.mouse.motion_down mouse 0x0 rel_y+ + +psx.input.port6.mouse.motion_left mouse 0x0 rel_x- + +psx.input.port6.mouse.motion_right mouse 0x0 rel_x+ + +psx.input.port6.mouse.motion_up mouse 0x0 rel_y- + +psx.input.port6.mouse.right mouse 0x0 button_right + +psx.input.port6.negcon.a + +psx.input.port6.negcon.b + +psx.input.port6.negcon.down + +psx.input.port6.negcon.i + +psx.input.port6.negcon.ii + +psx.input.port6.negcon.l + +psx.input.port6.negcon.left + +psx.input.port6.negcon.r + +psx.input.port6.negcon.right + +psx.input.port6.negcon.start + +psx.input.port6.negcon.twist_ccwise + +psx.input.port6.negcon.twist_cwise + +psx.input.port6.negcon.up + +psx.input.port7 gamepad + +psx.input.port7.analogjoy.axis_scale 1.00 + +psx.input.port7.analogjoy.circle + +psx.input.port7.analogjoy.cross + +psx.input.port7.analogjoy.down + +psx.input.port7.analogjoy.l1 + +psx.input.port7.analogjoy.l2 + +psx.input.port7.analogjoy.left + +psx.input.port7.analogjoy.lstick_down + +psx.input.port7.analogjoy.lstick_left + +psx.input.port7.analogjoy.lstick_right + +psx.input.port7.analogjoy.lstick_up + +psx.input.port7.analogjoy.r1 + +psx.input.port7.analogjoy.r2 + +psx.input.port7.analogjoy.right + +psx.input.port7.analogjoy.rstick_down + +psx.input.port7.analogjoy.rstick_left + +psx.input.port7.analogjoy.rstick_right + +psx.input.port7.analogjoy.rstick_up + +psx.input.port7.analogjoy.select + +psx.input.port7.analogjoy.square + +psx.input.port7.analogjoy.start + +psx.input.port7.analogjoy.triangle + +psx.input.port7.analogjoy.up + +psx.input.port7.dancepad.circle + +psx.input.port7.dancepad.cross + +psx.input.port7.dancepad.down + +psx.input.port7.dancepad.left + +psx.input.port7.dancepad.right + +psx.input.port7.dancepad.select + +psx.input.port7.dancepad.square + +psx.input.port7.dancepad.start + +psx.input.port7.dancepad.triangle + +psx.input.port7.dancepad.up + +psx.input.port7.dualanalog.axis_scale 1.00 + +psx.input.port7.dualanalog.circle + +psx.input.port7.dualanalog.cross + +psx.input.port7.dualanalog.down + +psx.input.port7.dualanalog.l1 + +psx.input.port7.dualanalog.l2 + +psx.input.port7.dualanalog.l3 + +psx.input.port7.dualanalog.left + +psx.input.port7.dualanalog.lstick_down + +psx.input.port7.dualanalog.lstick_left + +psx.input.port7.dualanalog.lstick_right + +psx.input.port7.dualanalog.lstick_up + +psx.input.port7.dualanalog.r1 + +psx.input.port7.dualanalog.r2 + +psx.input.port7.dualanalog.r3 + +psx.input.port7.dualanalog.rapid_circle + +psx.input.port7.dualanalog.rapid_cross + +psx.input.port7.dualanalog.rapid_square + +psx.input.port7.dualanalog.rapid_triangle + +psx.input.port7.dualanalog.right + +psx.input.port7.dualanalog.rstick_down + +psx.input.port7.dualanalog.rstick_left + +psx.input.port7.dualanalog.rstick_right + +psx.input.port7.dualanalog.rstick_up + +psx.input.port7.dualanalog.select + +psx.input.port7.dualanalog.square + +psx.input.port7.dualanalog.start + +psx.input.port7.dualanalog.triangle + +psx.input.port7.dualanalog.up + +psx.input.port7.dualshock.analog + +psx.input.port7.dualshock.axis_scale 1.00 + +psx.input.port7.dualshock.circle + +psx.input.port7.dualshock.cross + +psx.input.port7.dualshock.down + +psx.input.port7.dualshock.l1 + +psx.input.port7.dualshock.l2 + +psx.input.port7.dualshock.l3 + +psx.input.port7.dualshock.left + +psx.input.port7.dualshock.lstick_down + +psx.input.port7.dualshock.lstick_left + +psx.input.port7.dualshock.lstick_right + +psx.input.port7.dualshock.lstick_up + +psx.input.port7.dualshock.r1 + +psx.input.port7.dualshock.r2 + +psx.input.port7.dualshock.r3 + +psx.input.port7.dualshock.rapid_circle + +psx.input.port7.dualshock.rapid_cross + +psx.input.port7.dualshock.rapid_square + +psx.input.port7.dualshock.rapid_triangle + +psx.input.port7.dualshock.right + +psx.input.port7.dualshock.rstick_down + +psx.input.port7.dualshock.rstick_left + +psx.input.port7.dualshock.rstick_right + +psx.input.port7.dualshock.rstick_up + +psx.input.port7.dualshock.select + +psx.input.port7.dualshock.square + +psx.input.port7.dualshock.start + +psx.input.port7.dualshock.triangle + +psx.input.port7.dualshock.up + +psx.input.port7.gamepad.circle + +psx.input.port7.gamepad.cross + +psx.input.port7.gamepad.down + +psx.input.port7.gamepad.l1 + +psx.input.port7.gamepad.l2 + +psx.input.port7.gamepad.left + +psx.input.port7.gamepad.r1 + +psx.input.port7.gamepad.r2 + +psx.input.port7.gamepad.rapid_circle + +psx.input.port7.gamepad.rapid_cross + +psx.input.port7.gamepad.rapid_square + +psx.input.port7.gamepad.rapid_triangle + +psx.input.port7.gamepad.right + +psx.input.port7.gamepad.select + +psx.input.port7.gamepad.square + +psx.input.port7.gamepad.start + +psx.input.port7.gamepad.triangle + +psx.input.port7.gamepad.up + +psx.input.port7.gun_chairs 0x0080FF + +psx.input.port7.guncon.a mouse 0x0 button_right + +psx.input.port7.guncon.b mouse 0x0 button_middle + +psx.input.port7.guncon.offscreen_shot keyboard 0x0 44 + +psx.input.port7.guncon.trigger mouse 0x0 button_left + +psx.input.port7.guncon.x_axis mouse 0x0 cursor_x-+ + +psx.input.port7.guncon.y_axis mouse 0x0 cursor_y-+ + +psx.input.port7.justifier.o + +psx.input.port7.justifier.offscreen_shot + +psx.input.port7.justifier.start + +psx.input.port7.justifier.trigger + +psx.input.port7.justifier.x_axis + +psx.input.port7.justifier.y_axis + +psx.input.port7.memcard 1 + +psx.input.port7.mouse.left mouse 0x0 button_left + +psx.input.port7.mouse.motion_down mouse 0x0 rel_y+ + +psx.input.port7.mouse.motion_left mouse 0x0 rel_x- + +psx.input.port7.mouse.motion_right mouse 0x0 rel_x+ + +psx.input.port7.mouse.motion_up mouse 0x0 rel_y- + +psx.input.port7.mouse.right mouse 0x0 button_right + +psx.input.port7.negcon.a + +psx.input.port7.negcon.b + +psx.input.port7.negcon.down + +psx.input.port7.negcon.i + +psx.input.port7.negcon.ii + +psx.input.port7.negcon.l + +psx.input.port7.negcon.left + +psx.input.port7.negcon.r + +psx.input.port7.negcon.right + +psx.input.port7.negcon.start + +psx.input.port7.negcon.twist_ccwise + +psx.input.port7.negcon.twist_cwise + +psx.input.port7.negcon.up + +psx.input.port8 gamepad + +psx.input.port8.analogjoy.axis_scale 1.00 + +psx.input.port8.analogjoy.circle + +psx.input.port8.analogjoy.cross + +psx.input.port8.analogjoy.down + +psx.input.port8.analogjoy.l1 + +psx.input.port8.analogjoy.l2 + +psx.input.port8.analogjoy.left + +psx.input.port8.analogjoy.lstick_down + +psx.input.port8.analogjoy.lstick_left + +psx.input.port8.analogjoy.lstick_right + +psx.input.port8.analogjoy.lstick_up + +psx.input.port8.analogjoy.r1 + +psx.input.port8.analogjoy.r2 + +psx.input.port8.analogjoy.right + +psx.input.port8.analogjoy.rstick_down + +psx.input.port8.analogjoy.rstick_left + +psx.input.port8.analogjoy.rstick_right + +psx.input.port8.analogjoy.rstick_up + +psx.input.port8.analogjoy.select + +psx.input.port8.analogjoy.square + +psx.input.port8.analogjoy.start + +psx.input.port8.analogjoy.triangle + +psx.input.port8.analogjoy.up + +psx.input.port8.dancepad.circle + +psx.input.port8.dancepad.cross + +psx.input.port8.dancepad.down + +psx.input.port8.dancepad.left + +psx.input.port8.dancepad.right + +psx.input.port8.dancepad.select + +psx.input.port8.dancepad.square + +psx.input.port8.dancepad.start + +psx.input.port8.dancepad.triangle + +psx.input.port8.dancepad.up + +psx.input.port8.dualanalog.axis_scale 1.00 + +psx.input.port8.dualanalog.circle + +psx.input.port8.dualanalog.cross + +psx.input.port8.dualanalog.down + +psx.input.port8.dualanalog.l1 + +psx.input.port8.dualanalog.l2 + +psx.input.port8.dualanalog.l3 + +psx.input.port8.dualanalog.left + +psx.input.port8.dualanalog.lstick_down + +psx.input.port8.dualanalog.lstick_left + +psx.input.port8.dualanalog.lstick_right + +psx.input.port8.dualanalog.lstick_up + +psx.input.port8.dualanalog.r1 + +psx.input.port8.dualanalog.r2 + +psx.input.port8.dualanalog.r3 + +psx.input.port8.dualanalog.rapid_circle + +psx.input.port8.dualanalog.rapid_cross + +psx.input.port8.dualanalog.rapid_square + +psx.input.port8.dualanalog.rapid_triangle + +psx.input.port8.dualanalog.right + +psx.input.port8.dualanalog.rstick_down + +psx.input.port8.dualanalog.rstick_left + +psx.input.port8.dualanalog.rstick_right + +psx.input.port8.dualanalog.rstick_up + +psx.input.port8.dualanalog.select + +psx.input.port8.dualanalog.square + +psx.input.port8.dualanalog.start + +psx.input.port8.dualanalog.triangle + +psx.input.port8.dualanalog.up + +psx.input.port8.dualshock.analog + +psx.input.port8.dualshock.axis_scale 1.00 + +psx.input.port8.dualshock.circle + +psx.input.port8.dualshock.cross + +psx.input.port8.dualshock.down + +psx.input.port8.dualshock.l1 + +psx.input.port8.dualshock.l2 + +psx.input.port8.dualshock.l3 + +psx.input.port8.dualshock.left + +psx.input.port8.dualshock.lstick_down + +psx.input.port8.dualshock.lstick_left + +psx.input.port8.dualshock.lstick_right + +psx.input.port8.dualshock.lstick_up + +psx.input.port8.dualshock.r1 + +psx.input.port8.dualshock.r2 + +psx.input.port8.dualshock.r3 + +psx.input.port8.dualshock.rapid_circle + +psx.input.port8.dualshock.rapid_cross + +psx.input.port8.dualshock.rapid_square + +psx.input.port8.dualshock.rapid_triangle + +psx.input.port8.dualshock.right + +psx.input.port8.dualshock.rstick_down + +psx.input.port8.dualshock.rstick_left + +psx.input.port8.dualshock.rstick_right + +psx.input.port8.dualshock.rstick_up + +psx.input.port8.dualshock.select + +psx.input.port8.dualshock.square + +psx.input.port8.dualshock.start + +psx.input.port8.dualshock.triangle + +psx.input.port8.dualshock.up + +psx.input.port8.gamepad.circle + +psx.input.port8.gamepad.cross + +psx.input.port8.gamepad.down + +psx.input.port8.gamepad.l1 + +psx.input.port8.gamepad.l2 + +psx.input.port8.gamepad.left + +psx.input.port8.gamepad.r1 + +psx.input.port8.gamepad.r2 + +psx.input.port8.gamepad.rapid_circle + +psx.input.port8.gamepad.rapid_cross + +psx.input.port8.gamepad.rapid_square + +psx.input.port8.gamepad.rapid_triangle + +psx.input.port8.gamepad.right + +psx.input.port8.gamepad.select + +psx.input.port8.gamepad.square + +psx.input.port8.gamepad.start + +psx.input.port8.gamepad.triangle + +psx.input.port8.gamepad.up + +psx.input.port8.gun_chairs 0x8000FF + +psx.input.port8.guncon.a mouse 0x0 button_right + +psx.input.port8.guncon.b mouse 0x0 button_middle + +psx.input.port8.guncon.offscreen_shot keyboard 0x0 44 + +psx.input.port8.guncon.trigger mouse 0x0 button_left + +psx.input.port8.guncon.x_axis mouse 0x0 cursor_x-+ + +psx.input.port8.guncon.y_axis mouse 0x0 cursor_y-+ + +psx.input.port8.justifier.o + +psx.input.port8.justifier.offscreen_shot + +psx.input.port8.justifier.start + +psx.input.port8.justifier.trigger + +psx.input.port8.justifier.x_axis + +psx.input.port8.justifier.y_axis + +psx.input.port8.memcard 1 + +psx.input.port8.mouse.left mouse 0x0 button_left + +psx.input.port8.mouse.motion_down mouse 0x0 rel_y+ + +psx.input.port8.mouse.motion_left mouse 0x0 rel_x- + +psx.input.port8.mouse.motion_right mouse 0x0 rel_x+ + +psx.input.port8.mouse.motion_up mouse 0x0 rel_y- + +psx.input.port8.mouse.right mouse 0x0 button_right + +psx.input.port8.negcon.a + +psx.input.port8.negcon.b + +psx.input.port8.negcon.down + +psx.input.port8.negcon.i + +psx.input.port8.negcon.ii + +psx.input.port8.negcon.l + +psx.input.port8.negcon.left + +psx.input.port8.negcon.r + +psx.input.port8.negcon.right + +psx.input.port8.negcon.start + +psx.input.port8.negcon.twist_ccwise + +psx.input.port8.negcon.twist_cwise + +psx.input.port8.negcon.up + +psx.input.pport1.multitap 0 + +psx.input.pport2.multitap 0 + +psx.region_autodetect 1 + +psx.region_default jp + +psx.scanlines 0 + +psx.shader none + +psx.shader.goat.fprog 0 + +psx.shader.goat.hdiv 0.50 + +psx.shader.goat.pat goatron + +psx.shader.goat.slen 1 + +psx.shader.goat.tp 0.50 + +psx.shader.goat.vdiv 0.50 + +psx.slend 239 + +psx.slendp 287 + +psx.slstart 0 + +psx.slstartp 0 + +psx.special none + +psx.spu.resamp_quality 5 + +psx.stretch aspect + +psx.tblur 0 + +psx.tblur.accum 0 + +psx.tblur.accum.amount 50 + +psx.videoip 1 + +psx.xres 0 + +psx.xscale 3.000000 + +psx.xscalefs 1.000000 + +psx.yres 0 + +psx.yscale 3.000000 + +psx.yscalefs 1.000000 + +sasplay.enable 1 + +sasplay.forcemono 0 + +sasplay.input.builtin.controller.next_song keyboard 0x0 7 || keyboard 0x0 79 + +sasplay.input.builtin.controller.next_song_10 keyboard 0x0 26 || keyboard 0x0 82 + +sasplay.input.builtin.controller.previous_song keyboard 0x0 4 || keyboard 0x0 80 + +sasplay.input.builtin.controller.previous_song_10 keyboard 0x0 22 || keyboard 0x0 81 + +sasplay.input.builtin.controller.restart keyboard 0x0 40 + +sasplay.resamp_quality 5 + +sasplay.scanlines 0 + +sasplay.shader none + +sasplay.shader.goat.fprog 0 + +sasplay.shader.goat.hdiv 0.50 + +sasplay.shader.goat.pat goatron + +sasplay.shader.goat.slen 1 + +sasplay.shader.goat.tp 0.50 + +sasplay.shader.goat.vdiv 0.50 + +sasplay.special none + +sasplay.stretch aspect + +sasplay.tblur 0 + +sasplay.tblur.accum 0 + +sasplay.tblur.accum.amount 50 + +sasplay.videoip 0 + +sasplay.xres 0 + +sasplay.xscale 2.000000 + +sasplay.xscalefs 1.000000 + +sasplay.yres 0 + +sasplay.yscale 2.000000 + +sasplay.yscalefs 1.000000 + +ss.affinity.vdp2 0 + +ss.bios_jp sega_101.bin + +ss.bios_na_eu mpr-17933.bin + +ss.bios_sanity 1 + +ss.bios_stv_eu epr-17954a.ic8 + +ss.bios_stv_jp epr-20091.ic8 + +ss.bios_stv_na epr-17952a.ic8 + +ss.cart auto + +ss.cart.auto_default backup + +ss.cart.kof95_path mpr-18811-mx.ic1 + +ss.cart.ultraman_path mpr-19367-mx.ic1 + +ss.cd_sanity 1 + +ss.correct_aspect 1 + +ss.dbg_exe_cdpath + +ss.debugger.disfontsize 5x7 + +ss.debugger.memcharenc SJIS + +ss.enable 1 + +ss.forcemono 0 + +ss.h_blend 0 + +ss.h_overscan 1 + +ss.input.builtin.builtin.smpc_reset + +ss.input.builtin.builtin.stv_pause keyboard 0x0 86 && keyboard 0x0 88 + +ss.input.builtin.builtin.stv_service keyboard 0x0 86 && keyboard 0x0 87 + +ss.input.builtin.builtin.stv_test keyboard 0x0 86 && keyboard 0x0 84 + +ss.input.mouse_sensitivity 0.50 + +ss.input.port1 gamepad + +ss.input.port1.3dpad.a joystick @GUID1@ @DEVICE_BTN_WEST@ + +ss.input.port1.3dpad.analog_down joystick @GUID1@ @DEVICE_BTN_AL_DOWN@ + +ss.input.port1.3dpad.analog_left joystick @GUID1@ @DEVICE_BTN_AL_LEFT@ + +ss.input.port1.3dpad.analog_right joystick @GUID1@ @DEVICE_BTN_AL_RIGHT@ + +ss.input.port1.3dpad.analog_up joystick @GUID1@ @DEVICE_BTN_AL_UP@ + +ss.input.port1.3dpad.b joystick @GUID1@ @DEVICE_BTN_SOUTH@ + +ss.input.port1.3dpad.c joystick @GUID1@ @DEVICE_BTN_TR@ + +ss.input.port1.3dpad.down joystick @GUID1@ @DEVICE_BTN_DPAD_DOWN@ + +ss.input.port1.3dpad.left joystick @GUID1@ @DEVICE_BTN_DPAD_LEFT@ + +ss.input.port1.3dpad.ls joystick @GUID1@ @DEVICE_BTN_TL2@ || joystick @GUID1@ @DEVICE_BTN_TL2_MINUS@ + +ss.input.port1.3dpad.mode joystick + +ss.input.port1.3dpad.mode.defpos analog + +ss.input.port1.3dpad.right joystick @GUID1@ @DEVICE_BTN_DPAD_RIGHT@ + +ss.input.port1.3dpad.rs joystick @GUID1@ @DEVICE_BTN_TR2@ || joystick @GUID1@ @DEVICE_BTN_TR2_MINUS@ + +ss.input.port1.3dpad.start joystick @GUID1@ @DEVICE_BTN_START@ + +ss.input.port1.3dpad.up joystick @GUID1@ @DEVICE_BTN_DPAD_UP@ + +ss.input.port1.3dpad.x joystick @GUID1@ @DEVICE_BTN_EAST@ + +ss.input.port1.3dpad.y joystick @GUID1@ @DEVICE_BTN_NORTH@ + +ss.input.port1.3dpad.z joystick @GUID1@ @DEVICE_BTN_TL@ + +ss.input.port1.dmission.a + +ss.input.port1.dmission.afa + +ss.input.port1.dmission.afa.defpos off + +ss.input.port1.dmission.afb + +ss.input.port1.dmission.afb.defpos off + +ss.input.port1.dmission.afc + +ss.input.port1.dmission.afc.defpos off + +ss.input.port1.dmission.afl + +ss.input.port1.dmission.afl.defpos off + +ss.input.port1.dmission.afr + +ss.input.port1.dmission.afr.defpos off + +ss.input.port1.dmission.afspeed + +ss.input.port1.dmission.afspeed.defpos 1 + +ss.input.port1.dmission.afx + +ss.input.port1.dmission.afx.defpos off + +ss.input.port1.dmission.afy + +ss.input.port1.dmission.afy.defpos off + +ss.input.port1.dmission.afz + +ss.input.port1.dmission.afz.defpos off + +ss.input.port1.dmission.b + +ss.input.port1.dmission.c + +ss.input.port1.dmission.l + +ss.input.port1.dmission.lstick_back + +ss.input.port1.dmission.lstick_fore + +ss.input.port1.dmission.lstick_left + +ss.input.port1.dmission.lstick_right + +ss.input.port1.dmission.lthrottle_down + +ss.input.port1.dmission.lthrottle_up + +ss.input.port1.dmission.r + +ss.input.port1.dmission.rstick_back + +ss.input.port1.dmission.rstick_fore + +ss.input.port1.dmission.rstick_left + +ss.input.port1.dmission.rstick_right + +ss.input.port1.dmission.rthrottle_down + +ss.input.port1.dmission.rthrottle_up + +ss.input.port1.dmission.start + +ss.input.port1.dmission.x + +ss.input.port1.dmission.y + +ss.input.port1.dmission.z + +ss.input.port1.gamepad.a joystick @GUID1@ @DEVICE_BTN_WEST@ + +ss.input.port1.gamepad.b joystick @GUID1@ @DEVICE_BTN_SOUTH@ + +ss.input.port1.gamepad.c joystick @GUID1@ @DEVICE_BTN_TR@ + +ss.input.port1.gamepad.down joystick @GUID1@ @DEVICE_BTN_DPAD_DOWN@ + +ss.input.port1.gamepad.left joystick @GUID1@ @DEVICE_BTN_DPAD_LEFT@ + +ss.input.port1.gamepad.ls joystick @GUID1@ @DEVICE_BTN_TL2@ + +ss.input.port1.gamepad.right joystick @GUID1@ @DEVICE_BTN_DPAD_RIGHT@ + +ss.input.port1.gamepad.rs joystick @GUID1@ @DEVICE_BTN_TR2@ + +ss.input.port1.gamepad.start joystick @GUID1@ @DEVICE_BTN_START@ + +ss.input.port1.gamepad.up joystick @GUID1@ @DEVICE_BTN_DPAD_UP@ + +ss.input.port1.gamepad.x joystick @GUID1@ @DEVICE_BTN_EAST@ + +ss.input.port1.gamepad.y joystick @GUID1@ @DEVICE_BTN_NORTH@ + +ss.input.port1.gamepad.z joystick @GUID1@ @DEVICE_BTN_TL@ + +ss.input.port1.gun.offscreen_shot joystick @GUID1@ @DEVICE_BTN_SOUTH@ + +ss.input.port1.gun.start joystick @GUID1@ @DEVICE_BTN_EAST@ + +ss.input.port1.gun.trigger mouse 0x0 button_left + +ss.input.port1.gun.x_axis mouse 0x0 cursor_x-+ + +ss.input.port1.gun.y_axis mouse 0x0 cursor_y-+ + +ss.input.port1.gun_chairs 0xFF0000 + +ss.input.port1.jpkeyboard.0 keyboard 0x0 39 + +ss.input.port1.jpkeyboard.1 keyboard 0x0 30 + +ss.input.port1.jpkeyboard.2 keyboard 0x0 31 + +ss.input.port1.jpkeyboard.3 keyboard 0x0 32 + +ss.input.port1.jpkeyboard.4 keyboard 0x0 33 + +ss.input.port1.jpkeyboard.5 keyboard 0x0 34 + +ss.input.port1.jpkeyboard.6 keyboard 0x0 35 + +ss.input.port1.jpkeyboard.7 keyboard 0x0 36 + +ss.input.port1.jpkeyboard.8 keyboard 0x0 37 + +ss.input.port1.jpkeyboard.9 keyboard 0x0 38 + +ss.input.port1.jpkeyboard.a keyboard 0x0 4 + +ss.input.port1.jpkeyboard.at keyboard 0x0 47 + +ss.input.port1.jpkeyboard.b keyboard 0x0 5 + +ss.input.port1.jpkeyboard.backslash keyboard 0x0 135 + +ss.input.port1.jpkeyboard.backspace keyboard 0x0 42 + +ss.input.port1.jpkeyboard.c keyboard 0x0 6 + +ss.input.port1.jpkeyboard.capslock keyboard 0x0 57 + +ss.input.port1.jpkeyboard.circumflex keyboard 0x0 46 + +ss.input.port1.jpkeyboard.colon keyboard 0x0 52 + +ss.input.port1.jpkeyboard.comma keyboard 0x0 54 + +ss.input.port1.jpkeyboard.conv keyboard 0x0 138 + +ss.input.port1.jpkeyboard.d keyboard 0x0 7 + +ss.input.port1.jpkeyboard.delete keyboard 0x0 76 + +ss.input.port1.jpkeyboard.down keyboard 0x0 81 + +ss.input.port1.jpkeyboard.e keyboard 0x0 8 + +ss.input.port1.jpkeyboard.end keyboard 0x0 77 + +ss.input.port1.jpkeyboard.enter keyboard 0x0 40 + +ss.input.port1.jpkeyboard.esc keyboard 0x0 41 + +ss.input.port1.jpkeyboard.f keyboard 0x0 9 + +ss.input.port1.jpkeyboard.f1 keyboard 0x0 58 + +ss.input.port1.jpkeyboard.f10 keyboard 0x0 67 + +ss.input.port1.jpkeyboard.f11 keyboard 0x0 68 + +ss.input.port1.jpkeyboard.f12 keyboard 0x0 69 + +ss.input.port1.jpkeyboard.f2 keyboard 0x0 59 + +ss.input.port1.jpkeyboard.f3 keyboard 0x0 60 + +ss.input.port1.jpkeyboard.f4 keyboard 0x0 61 + +ss.input.port1.jpkeyboard.f5 keyboard 0x0 62 + +ss.input.port1.jpkeyboard.f6 keyboard 0x0 63 + +ss.input.port1.jpkeyboard.f7 keyboard 0x0 64 + +ss.input.port1.jpkeyboard.f8 keyboard 0x0 65 + +ss.input.port1.jpkeyboard.f9 keyboard 0x0 66 + +ss.input.port1.jpkeyboard.g keyboard 0x0 10 + +ss.input.port1.jpkeyboard.h keyboard 0x0 11 + +ss.input.port1.jpkeyboard.hkr keyboard 0x0 136 + +ss.input.port1.jpkeyboard.home keyboard 0x0 74 + +ss.input.port1.jpkeyboard.hwfw keyboard 0x0 53 + +ss.input.port1.jpkeyboard.i keyboard 0x0 12 + +ss.input.port1.jpkeyboard.insert keyboard 0x0 73 + +ss.input.port1.jpkeyboard.j keyboard 0x0 13 + +ss.input.port1.jpkeyboard.k keyboard 0x0 14 + +ss.input.port1.jpkeyboard.l keyboard 0x0 15 + +ss.input.port1.jpkeyboard.lalt keyboard 0x0 226 + +ss.input.port1.jpkeyboard.lctrl keyboard 0x0 224 + +ss.input.port1.jpkeyboard.left keyboard 0x0 80 + +ss.input.port1.jpkeyboard.leftbracket keyboard 0x0 48 + +ss.input.port1.jpkeyboard.lshift keyboard 0x0 225 + +ss.input.port1.jpkeyboard.m keyboard 0x0 16 + +ss.input.port1.jpkeyboard.minus keyboard 0x0 45 + +ss.input.port1.jpkeyboard.n keyboard 0x0 17 + +ss.input.port1.jpkeyboard.nonconv keyboard 0x0 139 + +ss.input.port1.jpkeyboard.o keyboard 0x0 18 + +ss.input.port1.jpkeyboard.p keyboard 0x0 19 + +ss.input.port1.jpkeyboard.pagedown keyboard 0x0 78 + +ss.input.port1.jpkeyboard.pageup keyboard 0x0 75 + +ss.input.port1.jpkeyboard.pause keyboard 0x0 72 || keyboard 0x0 83 + +ss.input.port1.jpkeyboard.period keyboard 0x0 55 + +ss.input.port1.jpkeyboard.printscreen keyboard 0x0 70 + +ss.input.port1.jpkeyboard.q keyboard 0x0 20 + +ss.input.port1.jpkeyboard.r keyboard 0x0 21 + +ss.input.port1.jpkeyboard.ralt keyboard 0x0 230 + +ss.input.port1.jpkeyboard.rctrl keyboard 0x0 228 + +ss.input.port1.jpkeyboard.right keyboard 0x0 79 + +ss.input.port1.jpkeyboard.rightbracket keyboard 0x0 49 + +ss.input.port1.jpkeyboard.rshift keyboard 0x0 229 + +ss.input.port1.jpkeyboard.s keyboard 0x0 22 + +ss.input.port1.jpkeyboard.scrolllock keyboard 0x0 71 + +ss.input.port1.jpkeyboard.semicolon keyboard 0x0 51 + +ss.input.port1.jpkeyboard.slash keyboard 0x0 56 + +ss.input.port1.jpkeyboard.space keyboard 0x0 44 + +ss.input.port1.jpkeyboard.t keyboard 0x0 23 + +ss.input.port1.jpkeyboard.tab keyboard 0x0 43 + +ss.input.port1.jpkeyboard.u keyboard 0x0 24 + +ss.input.port1.jpkeyboard.up keyboard 0x0 82 + +ss.input.port1.jpkeyboard.v keyboard 0x0 25 + +ss.input.port1.jpkeyboard.w keyboard 0x0 26 + +ss.input.port1.jpkeyboard.x keyboard 0x0 27 + +ss.input.port1.jpkeyboard.y keyboard 0x0 28 + +ss.input.port1.jpkeyboard.yen keyboard 0x0 137 + +ss.input.port1.jpkeyboard.z keyboard 0x0 29 + +ss.input.port1.keyboard.0 keyboard 0x0 39 + +ss.input.port1.keyboard.1 keyboard 0x0 30 + +ss.input.port1.keyboard.2 keyboard 0x0 31 + +ss.input.port1.keyboard.3 keyboard 0x0 32 + +ss.input.port1.keyboard.4 keyboard 0x0 33 + +ss.input.port1.keyboard.5 keyboard 0x0 34 + +ss.input.port1.keyboard.6 keyboard 0x0 35 + +ss.input.port1.keyboard.7 keyboard 0x0 36 + +ss.input.port1.keyboard.8 keyboard 0x0 37 + +ss.input.port1.keyboard.9 keyboard 0x0 38 + +ss.input.port1.keyboard.a keyboard 0x0 4 + +ss.input.port1.keyboard.b keyboard 0x0 5 + +ss.input.port1.keyboard.backslash keyboard 0x0 49 || keyboard 0x0 135 + +ss.input.port1.keyboard.backspace keyboard 0x0 42 + +ss.input.port1.keyboard.c keyboard 0x0 6 + +ss.input.port1.keyboard.capslock keyboard 0x0 57 + +ss.input.port1.keyboard.comma keyboard 0x0 54 + +ss.input.port1.keyboard.d keyboard 0x0 7 + +ss.input.port1.keyboard.delete keyboard 0x0 76 + +ss.input.port1.keyboard.down keyboard 0x0 81 + +ss.input.port1.keyboard.e keyboard 0x0 8 + +ss.input.port1.keyboard.end keyboard 0x0 77 + +ss.input.port1.keyboard.enter keyboard 0x0 40 + +ss.input.port1.keyboard.equals keyboard 0x0 46 + +ss.input.port1.keyboard.esc keyboard 0x0 41 + +ss.input.port1.keyboard.f keyboard 0x0 9 + +ss.input.port1.keyboard.f1 keyboard 0x0 58 + +ss.input.port1.keyboard.f10 keyboard 0x0 67 + +ss.input.port1.keyboard.f11 keyboard 0x0 68 + +ss.input.port1.keyboard.f12 keyboard 0x0 69 + +ss.input.port1.keyboard.f2 keyboard 0x0 59 + +ss.input.port1.keyboard.f3 keyboard 0x0 60 + +ss.input.port1.keyboard.f4 keyboard 0x0 61 + +ss.input.port1.keyboard.f5 keyboard 0x0 62 + +ss.input.port1.keyboard.f6 keyboard 0x0 63 + +ss.input.port1.keyboard.f7 keyboard 0x0 64 + +ss.input.port1.keyboard.f8 keyboard 0x0 65 + +ss.input.port1.keyboard.f9 keyboard 0x0 66 + +ss.input.port1.keyboard.g keyboard 0x0 10 + +ss.input.port1.keyboard.grave keyboard 0x0 53 + +ss.input.port1.keyboard.h keyboard 0x0 11 + +ss.input.port1.keyboard.home keyboard 0x0 74 + +ss.input.port1.keyboard.i keyboard 0x0 12 + +ss.input.port1.keyboard.insert keyboard 0x0 73 + +ss.input.port1.keyboard.j keyboard 0x0 13 + +ss.input.port1.keyboard.k keyboard 0x0 14 + +ss.input.port1.keyboard.kp_asterisk keyboard 0x0 85 + +ss.input.port1.keyboard.kp_center keyboard 0x0 93 + +ss.input.port1.keyboard.kp_delete keyboard 0x0 99 + +ss.input.port1.keyboard.kp_down keyboard 0x0 90 + +ss.input.port1.keyboard.kp_end keyboard 0x0 89 + +ss.input.port1.keyboard.kp_enter keyboard 0x0 88 + +ss.input.port1.keyboard.kp_home keyboard 0x0 95 + +ss.input.port1.keyboard.kp_insert keyboard 0x0 98 + +ss.input.port1.keyboard.kp_left keyboard 0x0 92 + +ss.input.port1.keyboard.kp_minus keyboard 0x0 86 + +ss.input.port1.keyboard.kp_pagedown keyboard 0x0 91 + +ss.input.port1.keyboard.kp_pageup keyboard 0x0 97 + +ss.input.port1.keyboard.kp_plus keyboard 0x0 87 + +ss.input.port1.keyboard.kp_right keyboard 0x0 94 + +ss.input.port1.keyboard.kp_slash keyboard 0x0 84 + +ss.input.port1.keyboard.kp_up keyboard 0x0 96 + +ss.input.port1.keyboard.l keyboard 0x0 15 + +ss.input.port1.keyboard.lalt keyboard 0x0 226 + +ss.input.port1.keyboard.lctrl keyboard 0x0 224 + +ss.input.port1.keyboard.left keyboard 0x0 80 + +ss.input.port1.keyboard.leftbracket keyboard 0x0 47 + +ss.input.port1.keyboard.lshift keyboard 0x0 225 + +ss.input.port1.keyboard.m keyboard 0x0 16 + +ss.input.port1.keyboard.minus keyboard 0x0 45 + +ss.input.port1.keyboard.n keyboard 0x0 17 + +ss.input.port1.keyboard.numlock keyboard 0x0 83 + +ss.input.port1.keyboard.o keyboard 0x0 18 + +ss.input.port1.keyboard.p keyboard 0x0 19 + +ss.input.port1.keyboard.pagedown keyboard 0x0 78 + +ss.input.port1.keyboard.pageup keyboard 0x0 75 + +ss.input.port1.keyboard.pause keyboard 0x0 72 + +ss.input.port1.keyboard.period keyboard 0x0 55 + +ss.input.port1.keyboard.printscreen keyboard 0x0 70 + +ss.input.port1.keyboard.q keyboard 0x0 20 + +ss.input.port1.keyboard.quote keyboard 0x0 52 + +ss.input.port1.keyboard.r keyboard 0x0 21 + +ss.input.port1.keyboard.ralt keyboard 0x0 230 + +ss.input.port1.keyboard.rctrl keyboard 0x0 228 + +ss.input.port1.keyboard.right keyboard 0x0 79 + +ss.input.port1.keyboard.rightbracket keyboard 0x0 48 + +ss.input.port1.keyboard.rshift keyboard 0x0 229 + +ss.input.port1.keyboard.s keyboard 0x0 22 + +ss.input.port1.keyboard.scrolllock keyboard 0x0 71 + +ss.input.port1.keyboard.semicolon keyboard 0x0 51 + +ss.input.port1.keyboard.slash keyboard 0x0 56 + +ss.input.port1.keyboard.space keyboard 0x0 44 + +ss.input.port1.keyboard.t keyboard 0x0 23 + +ss.input.port1.keyboard.tab keyboard 0x0 43 + +ss.input.port1.keyboard.u keyboard 0x0 24 + +ss.input.port1.keyboard.up keyboard 0x0 82 + +ss.input.port1.keyboard.v keyboard 0x0 25 + +ss.input.port1.keyboard.w keyboard 0x0 26 + +ss.input.port1.keyboard.x keyboard 0x0 27 + +ss.input.port1.keyboard.y keyboard 0x0 28 + +ss.input.port1.keyboard.z keyboard 0x0 29 + +ss.input.port1.mission.a + +ss.input.port1.mission.afa + +ss.input.port1.mission.afa.defpos off + +ss.input.port1.mission.afb + +ss.input.port1.mission.afb.defpos off + +ss.input.port1.mission.afc + +ss.input.port1.mission.afc.defpos off + +ss.input.port1.mission.afl + +ss.input.port1.mission.afl.defpos off + +ss.input.port1.mission.afr + +ss.input.port1.mission.afr.defpos off + +ss.input.port1.mission.afspeed + +ss.input.port1.mission.afspeed.defpos 1 + +ss.input.port1.mission.afx + +ss.input.port1.mission.afx.defpos off + +ss.input.port1.mission.afy + +ss.input.port1.mission.afy.defpos off + +ss.input.port1.mission.afz + +ss.input.port1.mission.afz.defpos off + +ss.input.port1.mission.b + +ss.input.port1.mission.c + +ss.input.port1.mission.l + +ss.input.port1.mission.r + +ss.input.port1.mission.start + +ss.input.port1.mission.stick_back + +ss.input.port1.mission.stick_fore + +ss.input.port1.mission.stick_left + +ss.input.port1.mission.stick_right + +ss.input.port1.mission.throttle_down + +ss.input.port1.mission.throttle_up + +ss.input.port1.mission.x + +ss.input.port1.mission.y + +ss.input.port1.mission.z + +ss.input.port1.mouse.left mouse 0x0 button_left + +ss.input.port1.mouse.middle mouse 0x0 button_middle + +ss.input.port1.mouse.motion_down mouse 0x0 rel_y+ + +ss.input.port1.mouse.motion_left mouse 0x0 rel_x- + +ss.input.port1.mouse.motion_right mouse 0x0 rel_x+ + +ss.input.port1.mouse.motion_up mouse 0x0 rel_y- + +ss.input.port1.mouse.right mouse 0x0 button_right + +ss.input.port1.mouse.start keyboard 0x0 40 + +ss.input.port1.wheel.a + +ss.input.port1.wheel.analog_left + +ss.input.port1.wheel.analog_right + +ss.input.port1.wheel.b + +ss.input.port1.wheel.c + +ss.input.port1.wheel.down + +ss.input.port1.wheel.start + +ss.input.port1.wheel.up + +ss.input.port1.wheel.x + +ss.input.port1.wheel.y + +ss.input.port1.wheel.z + +ss.input.port10 gamepad + +ss.input.port10.3dpad.a + +ss.input.port10.3dpad.analog_down + +ss.input.port10.3dpad.analog_left + +ss.input.port10.3dpad.analog_right + +ss.input.port10.3dpad.analog_up + +ss.input.port10.3dpad.b + +ss.input.port10.3dpad.c + +ss.input.port10.3dpad.down + +ss.input.port10.3dpad.left + +ss.input.port10.3dpad.ls + +ss.input.port10.3dpad.mode + +ss.input.port10.3dpad.mode.defpos digital + +ss.input.port10.3dpad.right + +ss.input.port10.3dpad.rs + +ss.input.port10.3dpad.start + +ss.input.port10.3dpad.up + +ss.input.port10.3dpad.x + +ss.input.port10.3dpad.y + +ss.input.port10.3dpad.z + +ss.input.port10.dmission.a + +ss.input.port10.dmission.afa + +ss.input.port10.dmission.afa.defpos off + +ss.input.port10.dmission.afb + +ss.input.port10.dmission.afb.defpos off + +ss.input.port10.dmission.afc + +ss.input.port10.dmission.afc.defpos off + +ss.input.port10.dmission.afl + +ss.input.port10.dmission.afl.defpos off + +ss.input.port10.dmission.afr + +ss.input.port10.dmission.afr.defpos off + +ss.input.port10.dmission.afspeed + +ss.input.port10.dmission.afspeed.defpos 1 + +ss.input.port10.dmission.afx + +ss.input.port10.dmission.afx.defpos off + +ss.input.port10.dmission.afy + +ss.input.port10.dmission.afy.defpos off + +ss.input.port10.dmission.afz + +ss.input.port10.dmission.afz.defpos off + +ss.input.port10.dmission.b + +ss.input.port10.dmission.c + +ss.input.port10.dmission.l + +ss.input.port10.dmission.lstick_back + +ss.input.port10.dmission.lstick_fore + +ss.input.port10.dmission.lstick_left + +ss.input.port10.dmission.lstick_right + +ss.input.port10.dmission.lthrottle_down + +ss.input.port10.dmission.lthrottle_up + +ss.input.port10.dmission.r + +ss.input.port10.dmission.rstick_back + +ss.input.port10.dmission.rstick_fore + +ss.input.port10.dmission.rstick_left + +ss.input.port10.dmission.rstick_right + +ss.input.port10.dmission.rthrottle_down + +ss.input.port10.dmission.rthrottle_up + +ss.input.port10.dmission.start + +ss.input.port10.dmission.x + +ss.input.port10.dmission.y + +ss.input.port10.dmission.z + +ss.input.port10.gamepad.a + +ss.input.port10.gamepad.b + +ss.input.port10.gamepad.c + +ss.input.port10.gamepad.down + +ss.input.port10.gamepad.left + +ss.input.port10.gamepad.ls + +ss.input.port10.gamepad.right + +ss.input.port10.gamepad.rs + +ss.input.port10.gamepad.start + +ss.input.port10.gamepad.up + +ss.input.port10.gamepad.x + +ss.input.port10.gamepad.y + +ss.input.port10.gamepad.z + +ss.input.port10.gun.offscreen_shot mouse 0x0 button_right + +ss.input.port10.gun.start mouse 0x0 button_middle + +ss.input.port10.gun.trigger mouse 0x0 button_left + +ss.input.port10.gun.x_axis mouse 0x0 cursor_x-+ + +ss.input.port10.gun.y_axis mouse 0x0 cursor_y-+ + +ss.input.port10.gun_chairs 0x00FF80 + +ss.input.port10.jpkeyboard.0 keyboard 0x0 39 + +ss.input.port10.jpkeyboard.1 keyboard 0x0 30 + +ss.input.port10.jpkeyboard.2 keyboard 0x0 31 + +ss.input.port10.jpkeyboard.3 keyboard 0x0 32 + +ss.input.port10.jpkeyboard.4 keyboard 0x0 33 + +ss.input.port10.jpkeyboard.5 keyboard 0x0 34 + +ss.input.port10.jpkeyboard.6 keyboard 0x0 35 + +ss.input.port10.jpkeyboard.7 keyboard 0x0 36 + +ss.input.port10.jpkeyboard.8 keyboard 0x0 37 + +ss.input.port10.jpkeyboard.9 keyboard 0x0 38 + +ss.input.port10.jpkeyboard.a keyboard 0x0 4 + +ss.input.port10.jpkeyboard.at keyboard 0x0 47 + +ss.input.port10.jpkeyboard.b keyboard 0x0 5 + +ss.input.port10.jpkeyboard.backslash keyboard 0x0 135 + +ss.input.port10.jpkeyboard.backspace keyboard 0x0 42 + +ss.input.port10.jpkeyboard.c keyboard 0x0 6 + +ss.input.port10.jpkeyboard.capslock keyboard 0x0 57 + +ss.input.port10.jpkeyboard.circumflex keyboard 0x0 46 + +ss.input.port10.jpkeyboard.colon keyboard 0x0 52 + +ss.input.port10.jpkeyboard.comma keyboard 0x0 54 + +ss.input.port10.jpkeyboard.conv keyboard 0x0 138 + +ss.input.port10.jpkeyboard.d keyboard 0x0 7 + +ss.input.port10.jpkeyboard.delete keyboard 0x0 76 + +ss.input.port10.jpkeyboard.down keyboard 0x0 81 + +ss.input.port10.jpkeyboard.e keyboard 0x0 8 + +ss.input.port10.jpkeyboard.end keyboard 0x0 77 + +ss.input.port10.jpkeyboard.enter keyboard 0x0 40 + +ss.input.port10.jpkeyboard.esc keyboard 0x0 41 + +ss.input.port10.jpkeyboard.f keyboard 0x0 9 + +ss.input.port10.jpkeyboard.f1 keyboard 0x0 58 + +ss.input.port10.jpkeyboard.f10 keyboard 0x0 67 + +ss.input.port10.jpkeyboard.f11 keyboard 0x0 68 + +ss.input.port10.jpkeyboard.f12 keyboard 0x0 69 + +ss.input.port10.jpkeyboard.f2 keyboard 0x0 59 + +ss.input.port10.jpkeyboard.f3 keyboard 0x0 60 + +ss.input.port10.jpkeyboard.f4 keyboard 0x0 61 + +ss.input.port10.jpkeyboard.f5 keyboard 0x0 62 + +ss.input.port10.jpkeyboard.f6 keyboard 0x0 63 + +ss.input.port10.jpkeyboard.f7 keyboard 0x0 64 + +ss.input.port10.jpkeyboard.f8 keyboard 0x0 65 + +ss.input.port10.jpkeyboard.f9 keyboard 0x0 66 + +ss.input.port10.jpkeyboard.g keyboard 0x0 10 + +ss.input.port10.jpkeyboard.h keyboard 0x0 11 + +ss.input.port10.jpkeyboard.hkr keyboard 0x0 136 + +ss.input.port10.jpkeyboard.home keyboard 0x0 74 + +ss.input.port10.jpkeyboard.hwfw keyboard 0x0 53 + +ss.input.port10.jpkeyboard.i keyboard 0x0 12 + +ss.input.port10.jpkeyboard.insert keyboard 0x0 73 + +ss.input.port10.jpkeyboard.j keyboard 0x0 13 + +ss.input.port10.jpkeyboard.k keyboard 0x0 14 + +ss.input.port10.jpkeyboard.l keyboard 0x0 15 + +ss.input.port10.jpkeyboard.lalt keyboard 0x0 226 + +ss.input.port10.jpkeyboard.lctrl keyboard 0x0 224 + +ss.input.port10.jpkeyboard.left keyboard 0x0 80 + +ss.input.port10.jpkeyboard.leftbracket keyboard 0x0 48 + +ss.input.port10.jpkeyboard.lshift keyboard 0x0 225 + +ss.input.port10.jpkeyboard.m keyboard 0x0 16 + +ss.input.port10.jpkeyboard.minus keyboard 0x0 45 + +ss.input.port10.jpkeyboard.n keyboard 0x0 17 + +ss.input.port10.jpkeyboard.nonconv keyboard 0x0 139 + +ss.input.port10.jpkeyboard.o keyboard 0x0 18 + +ss.input.port10.jpkeyboard.p keyboard 0x0 19 + +ss.input.port10.jpkeyboard.pagedown keyboard 0x0 78 + +ss.input.port10.jpkeyboard.pageup keyboard 0x0 75 + +ss.input.port10.jpkeyboard.pause keyboard 0x0 72 || keyboard 0x0 83 + +ss.input.port10.jpkeyboard.period keyboard 0x0 55 + +ss.input.port10.jpkeyboard.printscreen keyboard 0x0 70 + +ss.input.port10.jpkeyboard.q keyboard 0x0 20 + +ss.input.port10.jpkeyboard.r keyboard 0x0 21 + +ss.input.port10.jpkeyboard.ralt keyboard 0x0 230 + +ss.input.port10.jpkeyboard.rctrl keyboard 0x0 228 + +ss.input.port10.jpkeyboard.right keyboard 0x0 79 + +ss.input.port10.jpkeyboard.rightbracket keyboard 0x0 49 + +ss.input.port10.jpkeyboard.rshift keyboard 0x0 229 + +ss.input.port10.jpkeyboard.s keyboard 0x0 22 + +ss.input.port10.jpkeyboard.scrolllock keyboard 0x0 71 + +ss.input.port10.jpkeyboard.semicolon keyboard 0x0 51 + +ss.input.port10.jpkeyboard.slash keyboard 0x0 56 + +ss.input.port10.jpkeyboard.space keyboard 0x0 44 + +ss.input.port10.jpkeyboard.t keyboard 0x0 23 + +ss.input.port10.jpkeyboard.tab keyboard 0x0 43 + +ss.input.port10.jpkeyboard.u keyboard 0x0 24 + +ss.input.port10.jpkeyboard.up keyboard 0x0 82 + +ss.input.port10.jpkeyboard.v keyboard 0x0 25 + +ss.input.port10.jpkeyboard.w keyboard 0x0 26 + +ss.input.port10.jpkeyboard.x keyboard 0x0 27 + +ss.input.port10.jpkeyboard.y keyboard 0x0 28 + +ss.input.port10.jpkeyboard.yen keyboard 0x0 137 + +ss.input.port10.jpkeyboard.z keyboard 0x0 29 + +ss.input.port10.keyboard.0 keyboard 0x0 39 + +ss.input.port10.keyboard.1 keyboard 0x0 30 + +ss.input.port10.keyboard.2 keyboard 0x0 31 + +ss.input.port10.keyboard.3 keyboard 0x0 32 + +ss.input.port10.keyboard.4 keyboard 0x0 33 + +ss.input.port10.keyboard.5 keyboard 0x0 34 + +ss.input.port10.keyboard.6 keyboard 0x0 35 + +ss.input.port10.keyboard.7 keyboard 0x0 36 + +ss.input.port10.keyboard.8 keyboard 0x0 37 + +ss.input.port10.keyboard.9 keyboard 0x0 38 + +ss.input.port10.keyboard.a keyboard 0x0 4 + +ss.input.port10.keyboard.b keyboard 0x0 5 + +ss.input.port10.keyboard.backslash keyboard 0x0 49 || keyboard 0x0 135 + +ss.input.port10.keyboard.backspace keyboard 0x0 42 + +ss.input.port10.keyboard.c keyboard 0x0 6 + +ss.input.port10.keyboard.capslock keyboard 0x0 57 + +ss.input.port10.keyboard.comma keyboard 0x0 54 + +ss.input.port10.keyboard.d keyboard 0x0 7 + +ss.input.port10.keyboard.delete keyboard 0x0 76 + +ss.input.port10.keyboard.down keyboard 0x0 81 + +ss.input.port10.keyboard.e keyboard 0x0 8 + +ss.input.port10.keyboard.end keyboard 0x0 77 + +ss.input.port10.keyboard.enter keyboard 0x0 40 + +ss.input.port10.keyboard.equals keyboard 0x0 46 + +ss.input.port10.keyboard.esc keyboard 0x0 41 + +ss.input.port10.keyboard.f keyboard 0x0 9 + +ss.input.port10.keyboard.f1 keyboard 0x0 58 + +ss.input.port10.keyboard.f10 keyboard 0x0 67 + +ss.input.port10.keyboard.f11 keyboard 0x0 68 + +ss.input.port10.keyboard.f12 keyboard 0x0 69 + +ss.input.port10.keyboard.f2 keyboard 0x0 59 + +ss.input.port10.keyboard.f3 keyboard 0x0 60 + +ss.input.port10.keyboard.f4 keyboard 0x0 61 + +ss.input.port10.keyboard.f5 keyboard 0x0 62 + +ss.input.port10.keyboard.f6 keyboard 0x0 63 + +ss.input.port10.keyboard.f7 keyboard 0x0 64 + +ss.input.port10.keyboard.f8 keyboard 0x0 65 + +ss.input.port10.keyboard.f9 keyboard 0x0 66 + +ss.input.port10.keyboard.g keyboard 0x0 10 + +ss.input.port10.keyboard.grave keyboard 0x0 53 + +ss.input.port10.keyboard.h keyboard 0x0 11 + +ss.input.port10.keyboard.home keyboard 0x0 74 + +ss.input.port10.keyboard.i keyboard 0x0 12 + +ss.input.port10.keyboard.insert keyboard 0x0 73 + +ss.input.port10.keyboard.j keyboard 0x0 13 + +ss.input.port10.keyboard.k keyboard 0x0 14 + +ss.input.port10.keyboard.kp_asterisk keyboard 0x0 85 + +ss.input.port10.keyboard.kp_center keyboard 0x0 93 + +ss.input.port10.keyboard.kp_delete keyboard 0x0 99 + +ss.input.port10.keyboard.kp_down keyboard 0x0 90 + +ss.input.port10.keyboard.kp_end keyboard 0x0 89 + +ss.input.port10.keyboard.kp_enter keyboard 0x0 88 + +ss.input.port10.keyboard.kp_home keyboard 0x0 95 + +ss.input.port10.keyboard.kp_insert keyboard 0x0 98 + +ss.input.port10.keyboard.kp_left keyboard 0x0 92 + +ss.input.port10.keyboard.kp_minus keyboard 0x0 86 + +ss.input.port10.keyboard.kp_pagedown keyboard 0x0 91 + +ss.input.port10.keyboard.kp_pageup keyboard 0x0 97 + +ss.input.port10.keyboard.kp_plus keyboard 0x0 87 + +ss.input.port10.keyboard.kp_right keyboard 0x0 94 + +ss.input.port10.keyboard.kp_slash keyboard 0x0 84 + +ss.input.port10.keyboard.kp_up keyboard 0x0 96 + +ss.input.port10.keyboard.l keyboard 0x0 15 + +ss.input.port10.keyboard.lalt keyboard 0x0 226 + +ss.input.port10.keyboard.lctrl keyboard 0x0 224 + +ss.input.port10.keyboard.left keyboard 0x0 80 + +ss.input.port10.keyboard.leftbracket keyboard 0x0 47 + +ss.input.port10.keyboard.lshift keyboard 0x0 225 + +ss.input.port10.keyboard.m keyboard 0x0 16 + +ss.input.port10.keyboard.minus keyboard 0x0 45 + +ss.input.port10.keyboard.n keyboard 0x0 17 + +ss.input.port10.keyboard.numlock keyboard 0x0 83 + +ss.input.port10.keyboard.o keyboard 0x0 18 + +ss.input.port10.keyboard.p keyboard 0x0 19 + +ss.input.port10.keyboard.pagedown keyboard 0x0 78 + +ss.input.port10.keyboard.pageup keyboard 0x0 75 + +ss.input.port10.keyboard.pause keyboard 0x0 72 + +ss.input.port10.keyboard.period keyboard 0x0 55 + +ss.input.port10.keyboard.printscreen keyboard 0x0 70 + +ss.input.port10.keyboard.q keyboard 0x0 20 + +ss.input.port10.keyboard.quote keyboard 0x0 52 + +ss.input.port10.keyboard.r keyboard 0x0 21 + +ss.input.port10.keyboard.ralt keyboard 0x0 230 + +ss.input.port10.keyboard.rctrl keyboard 0x0 228 + +ss.input.port10.keyboard.right keyboard 0x0 79 + +ss.input.port10.keyboard.rightbracket keyboard 0x0 48 + +ss.input.port10.keyboard.rshift keyboard 0x0 229 + +ss.input.port10.keyboard.s keyboard 0x0 22 + +ss.input.port10.keyboard.scrolllock keyboard 0x0 71 + +ss.input.port10.keyboard.semicolon keyboard 0x0 51 + +ss.input.port10.keyboard.slash keyboard 0x0 56 + +ss.input.port10.keyboard.space keyboard 0x0 44 + +ss.input.port10.keyboard.t keyboard 0x0 23 + +ss.input.port10.keyboard.tab keyboard 0x0 43 + +ss.input.port10.keyboard.u keyboard 0x0 24 + +ss.input.port10.keyboard.up keyboard 0x0 82 + +ss.input.port10.keyboard.v keyboard 0x0 25 + +ss.input.port10.keyboard.w keyboard 0x0 26 + +ss.input.port10.keyboard.x keyboard 0x0 27 + +ss.input.port10.keyboard.y keyboard 0x0 28 + +ss.input.port10.keyboard.z keyboard 0x0 29 + +ss.input.port10.mission.a + +ss.input.port10.mission.afa + +ss.input.port10.mission.afa.defpos off + +ss.input.port10.mission.afb + +ss.input.port10.mission.afb.defpos off + +ss.input.port10.mission.afc + +ss.input.port10.mission.afc.defpos off + +ss.input.port10.mission.afl + +ss.input.port10.mission.afl.defpos off + +ss.input.port10.mission.afr + +ss.input.port10.mission.afr.defpos off + +ss.input.port10.mission.afspeed + +ss.input.port10.mission.afspeed.defpos 1 + +ss.input.port10.mission.afx + +ss.input.port10.mission.afx.defpos off + +ss.input.port10.mission.afy + +ss.input.port10.mission.afy.defpos off + +ss.input.port10.mission.afz + +ss.input.port10.mission.afz.defpos off + +ss.input.port10.mission.b + +ss.input.port10.mission.c + +ss.input.port10.mission.l + +ss.input.port10.mission.r + +ss.input.port10.mission.start + +ss.input.port10.mission.stick_back + +ss.input.port10.mission.stick_fore + +ss.input.port10.mission.stick_left + +ss.input.port10.mission.stick_right + +ss.input.port10.mission.throttle_down + +ss.input.port10.mission.throttle_up + +ss.input.port10.mission.x + +ss.input.port10.mission.y + +ss.input.port10.mission.z + +ss.input.port10.mouse.left mouse 0x0 button_left + +ss.input.port10.mouse.middle mouse 0x0 button_middle + +ss.input.port10.mouse.motion_down mouse 0x0 rel_y+ + +ss.input.port10.mouse.motion_left mouse 0x0 rel_x- + +ss.input.port10.mouse.motion_right mouse 0x0 rel_x+ + +ss.input.port10.mouse.motion_up mouse 0x0 rel_y- + +ss.input.port10.mouse.right mouse 0x0 button_right + +ss.input.port10.mouse.start keyboard 0x0 40 + +ss.input.port10.wheel.a + +ss.input.port10.wheel.analog_left + +ss.input.port10.wheel.analog_right + +ss.input.port10.wheel.b + +ss.input.port10.wheel.c + +ss.input.port10.wheel.down + +ss.input.port10.wheel.start + +ss.input.port10.wheel.up + +ss.input.port10.wheel.x + +ss.input.port10.wheel.y + +ss.input.port10.wheel.z + +ss.input.port11 gamepad + +ss.input.port11.3dpad.a + +ss.input.port11.3dpad.analog_down + +ss.input.port11.3dpad.analog_left + +ss.input.port11.3dpad.analog_right + +ss.input.port11.3dpad.analog_up + +ss.input.port11.3dpad.b + +ss.input.port11.3dpad.c + +ss.input.port11.3dpad.down + +ss.input.port11.3dpad.left + +ss.input.port11.3dpad.ls + +ss.input.port11.3dpad.mode + +ss.input.port11.3dpad.mode.defpos digital + +ss.input.port11.3dpad.right + +ss.input.port11.3dpad.rs + +ss.input.port11.3dpad.start + +ss.input.port11.3dpad.up + +ss.input.port11.3dpad.x + +ss.input.port11.3dpad.y + +ss.input.port11.3dpad.z + +ss.input.port11.dmission.a + +ss.input.port11.dmission.afa + +ss.input.port11.dmission.afa.defpos off + +ss.input.port11.dmission.afb + +ss.input.port11.dmission.afb.defpos off + +ss.input.port11.dmission.afc + +ss.input.port11.dmission.afc.defpos off + +ss.input.port11.dmission.afl + +ss.input.port11.dmission.afl.defpos off + +ss.input.port11.dmission.afr + +ss.input.port11.dmission.afr.defpos off + +ss.input.port11.dmission.afspeed + +ss.input.port11.dmission.afspeed.defpos 1 + +ss.input.port11.dmission.afx + +ss.input.port11.dmission.afx.defpos off + +ss.input.port11.dmission.afy + +ss.input.port11.dmission.afy.defpos off + +ss.input.port11.dmission.afz + +ss.input.port11.dmission.afz.defpos off + +ss.input.port11.dmission.b + +ss.input.port11.dmission.c + +ss.input.port11.dmission.l + +ss.input.port11.dmission.lstick_back + +ss.input.port11.dmission.lstick_fore + +ss.input.port11.dmission.lstick_left + +ss.input.port11.dmission.lstick_right + +ss.input.port11.dmission.lthrottle_down + +ss.input.port11.dmission.lthrottle_up + +ss.input.port11.dmission.r + +ss.input.port11.dmission.rstick_back + +ss.input.port11.dmission.rstick_fore + +ss.input.port11.dmission.rstick_left + +ss.input.port11.dmission.rstick_right + +ss.input.port11.dmission.rthrottle_down + +ss.input.port11.dmission.rthrottle_up + +ss.input.port11.dmission.start + +ss.input.port11.dmission.x + +ss.input.port11.dmission.y + +ss.input.port11.dmission.z + +ss.input.port11.gamepad.a + +ss.input.port11.gamepad.b + +ss.input.port11.gamepad.c + +ss.input.port11.gamepad.down + +ss.input.port11.gamepad.left + +ss.input.port11.gamepad.ls + +ss.input.port11.gamepad.right + +ss.input.port11.gamepad.rs + +ss.input.port11.gamepad.start + +ss.input.port11.gamepad.up + +ss.input.port11.gamepad.x + +ss.input.port11.gamepad.y + +ss.input.port11.gamepad.z + +ss.input.port11.gun.offscreen_shot mouse 0x0 button_right + +ss.input.port11.gun.start mouse 0x0 button_middle + +ss.input.port11.gun.trigger mouse 0x0 button_left + +ss.input.port11.gun.x_axis mouse 0x0 cursor_x-+ + +ss.input.port11.gun.y_axis mouse 0x0 cursor_y-+ + +ss.input.port11.gun_chairs 0x8080FF + +ss.input.port11.jpkeyboard.0 keyboard 0x0 39 + +ss.input.port11.jpkeyboard.1 keyboard 0x0 30 + +ss.input.port11.jpkeyboard.2 keyboard 0x0 31 + +ss.input.port11.jpkeyboard.3 keyboard 0x0 32 + +ss.input.port11.jpkeyboard.4 keyboard 0x0 33 + +ss.input.port11.jpkeyboard.5 keyboard 0x0 34 + +ss.input.port11.jpkeyboard.6 keyboard 0x0 35 + +ss.input.port11.jpkeyboard.7 keyboard 0x0 36 + +ss.input.port11.jpkeyboard.8 keyboard 0x0 37 + +ss.input.port11.jpkeyboard.9 keyboard 0x0 38 + +ss.input.port11.jpkeyboard.a keyboard 0x0 4 + +ss.input.port11.jpkeyboard.at keyboard 0x0 47 + +ss.input.port11.jpkeyboard.b keyboard 0x0 5 + +ss.input.port11.jpkeyboard.backslash keyboard 0x0 135 + +ss.input.port11.jpkeyboard.backspace keyboard 0x0 42 + +ss.input.port11.jpkeyboard.c keyboard 0x0 6 + +ss.input.port11.jpkeyboard.capslock keyboard 0x0 57 + +ss.input.port11.jpkeyboard.circumflex keyboard 0x0 46 + +ss.input.port11.jpkeyboard.colon keyboard 0x0 52 + +ss.input.port11.jpkeyboard.comma keyboard 0x0 54 + +ss.input.port11.jpkeyboard.conv keyboard 0x0 138 + +ss.input.port11.jpkeyboard.d keyboard 0x0 7 + +ss.input.port11.jpkeyboard.delete keyboard 0x0 76 + +ss.input.port11.jpkeyboard.down keyboard 0x0 81 + +ss.input.port11.jpkeyboard.e keyboard 0x0 8 + +ss.input.port11.jpkeyboard.end keyboard 0x0 77 + +ss.input.port11.jpkeyboard.enter keyboard 0x0 40 + +ss.input.port11.jpkeyboard.esc keyboard 0x0 41 + +ss.input.port11.jpkeyboard.f keyboard 0x0 9 + +ss.input.port11.jpkeyboard.f1 keyboard 0x0 58 + +ss.input.port11.jpkeyboard.f10 keyboard 0x0 67 + +ss.input.port11.jpkeyboard.f11 keyboard 0x0 68 + +ss.input.port11.jpkeyboard.f12 keyboard 0x0 69 + +ss.input.port11.jpkeyboard.f2 keyboard 0x0 59 + +ss.input.port11.jpkeyboard.f3 keyboard 0x0 60 + +ss.input.port11.jpkeyboard.f4 keyboard 0x0 61 + +ss.input.port11.jpkeyboard.f5 keyboard 0x0 62 + +ss.input.port11.jpkeyboard.f6 keyboard 0x0 63 + +ss.input.port11.jpkeyboard.f7 keyboard 0x0 64 + +ss.input.port11.jpkeyboard.f8 keyboard 0x0 65 + +ss.input.port11.jpkeyboard.f9 keyboard 0x0 66 + +ss.input.port11.jpkeyboard.g keyboard 0x0 10 + +ss.input.port11.jpkeyboard.h keyboard 0x0 11 + +ss.input.port11.jpkeyboard.hkr keyboard 0x0 136 + +ss.input.port11.jpkeyboard.home keyboard 0x0 74 + +ss.input.port11.jpkeyboard.hwfw keyboard 0x0 53 + +ss.input.port11.jpkeyboard.i keyboard 0x0 12 + +ss.input.port11.jpkeyboard.insert keyboard 0x0 73 + +ss.input.port11.jpkeyboard.j keyboard 0x0 13 + +ss.input.port11.jpkeyboard.k keyboard 0x0 14 + +ss.input.port11.jpkeyboard.l keyboard 0x0 15 + +ss.input.port11.jpkeyboard.lalt keyboard 0x0 226 + +ss.input.port11.jpkeyboard.lctrl keyboard 0x0 224 + +ss.input.port11.jpkeyboard.left keyboard 0x0 80 + +ss.input.port11.jpkeyboard.leftbracket keyboard 0x0 48 + +ss.input.port11.jpkeyboard.lshift keyboard 0x0 225 + +ss.input.port11.jpkeyboard.m keyboard 0x0 16 + +ss.input.port11.jpkeyboard.minus keyboard 0x0 45 + +ss.input.port11.jpkeyboard.n keyboard 0x0 17 + +ss.input.port11.jpkeyboard.nonconv keyboard 0x0 139 + +ss.input.port11.jpkeyboard.o keyboard 0x0 18 + +ss.input.port11.jpkeyboard.p keyboard 0x0 19 + +ss.input.port11.jpkeyboard.pagedown keyboard 0x0 78 + +ss.input.port11.jpkeyboard.pageup keyboard 0x0 75 + +ss.input.port11.jpkeyboard.pause keyboard 0x0 72 || keyboard 0x0 83 + +ss.input.port11.jpkeyboard.period keyboard 0x0 55 + +ss.input.port11.jpkeyboard.printscreen keyboard 0x0 70 + +ss.input.port11.jpkeyboard.q keyboard 0x0 20 + +ss.input.port11.jpkeyboard.r keyboard 0x0 21 + +ss.input.port11.jpkeyboard.ralt keyboard 0x0 230 + +ss.input.port11.jpkeyboard.rctrl keyboard 0x0 228 + +ss.input.port11.jpkeyboard.right keyboard 0x0 79 + +ss.input.port11.jpkeyboard.rightbracket keyboard 0x0 49 + +ss.input.port11.jpkeyboard.rshift keyboard 0x0 229 + +ss.input.port11.jpkeyboard.s keyboard 0x0 22 + +ss.input.port11.jpkeyboard.scrolllock keyboard 0x0 71 + +ss.input.port11.jpkeyboard.semicolon keyboard 0x0 51 + +ss.input.port11.jpkeyboard.slash keyboard 0x0 56 + +ss.input.port11.jpkeyboard.space keyboard 0x0 44 + +ss.input.port11.jpkeyboard.t keyboard 0x0 23 + +ss.input.port11.jpkeyboard.tab keyboard 0x0 43 + +ss.input.port11.jpkeyboard.u keyboard 0x0 24 + +ss.input.port11.jpkeyboard.up keyboard 0x0 82 + +ss.input.port11.jpkeyboard.v keyboard 0x0 25 + +ss.input.port11.jpkeyboard.w keyboard 0x0 26 + +ss.input.port11.jpkeyboard.x keyboard 0x0 27 + +ss.input.port11.jpkeyboard.y keyboard 0x0 28 + +ss.input.port11.jpkeyboard.yen keyboard 0x0 137 + +ss.input.port11.jpkeyboard.z keyboard 0x0 29 + +ss.input.port11.keyboard.0 keyboard 0x0 39 + +ss.input.port11.keyboard.1 keyboard 0x0 30 + +ss.input.port11.keyboard.2 keyboard 0x0 31 + +ss.input.port11.keyboard.3 keyboard 0x0 32 + +ss.input.port11.keyboard.4 keyboard 0x0 33 + +ss.input.port11.keyboard.5 keyboard 0x0 34 + +ss.input.port11.keyboard.6 keyboard 0x0 35 + +ss.input.port11.keyboard.7 keyboard 0x0 36 + +ss.input.port11.keyboard.8 keyboard 0x0 37 + +ss.input.port11.keyboard.9 keyboard 0x0 38 + +ss.input.port11.keyboard.a keyboard 0x0 4 + +ss.input.port11.keyboard.b keyboard 0x0 5 + +ss.input.port11.keyboard.backslash keyboard 0x0 49 || keyboard 0x0 135 + +ss.input.port11.keyboard.backspace keyboard 0x0 42 + +ss.input.port11.keyboard.c keyboard 0x0 6 + +ss.input.port11.keyboard.capslock keyboard 0x0 57 + +ss.input.port11.keyboard.comma keyboard 0x0 54 + +ss.input.port11.keyboard.d keyboard 0x0 7 + +ss.input.port11.keyboard.delete keyboard 0x0 76 + +ss.input.port11.keyboard.down keyboard 0x0 81 + +ss.input.port11.keyboard.e keyboard 0x0 8 + +ss.input.port11.keyboard.end keyboard 0x0 77 + +ss.input.port11.keyboard.enter keyboard 0x0 40 + +ss.input.port11.keyboard.equals keyboard 0x0 46 + +ss.input.port11.keyboard.esc keyboard 0x0 41 + +ss.input.port11.keyboard.f keyboard 0x0 9 + +ss.input.port11.keyboard.f1 keyboard 0x0 58 + +ss.input.port11.keyboard.f10 keyboard 0x0 67 + +ss.input.port11.keyboard.f11 keyboard 0x0 68 + +ss.input.port11.keyboard.f12 keyboard 0x0 69 + +ss.input.port11.keyboard.f2 keyboard 0x0 59 + +ss.input.port11.keyboard.f3 keyboard 0x0 60 + +ss.input.port11.keyboard.f4 keyboard 0x0 61 + +ss.input.port11.keyboard.f5 keyboard 0x0 62 + +ss.input.port11.keyboard.f6 keyboard 0x0 63 + +ss.input.port11.keyboard.f7 keyboard 0x0 64 + +ss.input.port11.keyboard.f8 keyboard 0x0 65 + +ss.input.port11.keyboard.f9 keyboard 0x0 66 + +ss.input.port11.keyboard.g keyboard 0x0 10 + +ss.input.port11.keyboard.grave keyboard 0x0 53 + +ss.input.port11.keyboard.h keyboard 0x0 11 + +ss.input.port11.keyboard.home keyboard 0x0 74 + +ss.input.port11.keyboard.i keyboard 0x0 12 + +ss.input.port11.keyboard.insert keyboard 0x0 73 + +ss.input.port11.keyboard.j keyboard 0x0 13 + +ss.input.port11.keyboard.k keyboard 0x0 14 + +ss.input.port11.keyboard.kp_asterisk keyboard 0x0 85 + +ss.input.port11.keyboard.kp_center keyboard 0x0 93 + +ss.input.port11.keyboard.kp_delete keyboard 0x0 99 + +ss.input.port11.keyboard.kp_down keyboard 0x0 90 + +ss.input.port11.keyboard.kp_end keyboard 0x0 89 + +ss.input.port11.keyboard.kp_enter keyboard 0x0 88 + +ss.input.port11.keyboard.kp_home keyboard 0x0 95 + +ss.input.port11.keyboard.kp_insert keyboard 0x0 98 + +ss.input.port11.keyboard.kp_left keyboard 0x0 92 + +ss.input.port11.keyboard.kp_minus keyboard 0x0 86 + +ss.input.port11.keyboard.kp_pagedown keyboard 0x0 91 + +ss.input.port11.keyboard.kp_pageup keyboard 0x0 97 + +ss.input.port11.keyboard.kp_plus keyboard 0x0 87 + +ss.input.port11.keyboard.kp_right keyboard 0x0 94 + +ss.input.port11.keyboard.kp_slash keyboard 0x0 84 + +ss.input.port11.keyboard.kp_up keyboard 0x0 96 + +ss.input.port11.keyboard.l keyboard 0x0 15 + +ss.input.port11.keyboard.lalt keyboard 0x0 226 + +ss.input.port11.keyboard.lctrl keyboard 0x0 224 + +ss.input.port11.keyboard.left keyboard 0x0 80 + +ss.input.port11.keyboard.leftbracket keyboard 0x0 47 + +ss.input.port11.keyboard.lshift keyboard 0x0 225 + +ss.input.port11.keyboard.m keyboard 0x0 16 + +ss.input.port11.keyboard.minus keyboard 0x0 45 + +ss.input.port11.keyboard.n keyboard 0x0 17 + +ss.input.port11.keyboard.numlock keyboard 0x0 83 + +ss.input.port11.keyboard.o keyboard 0x0 18 + +ss.input.port11.keyboard.p keyboard 0x0 19 + +ss.input.port11.keyboard.pagedown keyboard 0x0 78 + +ss.input.port11.keyboard.pageup keyboard 0x0 75 + +ss.input.port11.keyboard.pause keyboard 0x0 72 + +ss.input.port11.keyboard.period keyboard 0x0 55 + +ss.input.port11.keyboard.printscreen keyboard 0x0 70 + +ss.input.port11.keyboard.q keyboard 0x0 20 + +ss.input.port11.keyboard.quote keyboard 0x0 52 + +ss.input.port11.keyboard.r keyboard 0x0 21 + +ss.input.port11.keyboard.ralt keyboard 0x0 230 + +ss.input.port11.keyboard.rctrl keyboard 0x0 228 + +ss.input.port11.keyboard.right keyboard 0x0 79 + +ss.input.port11.keyboard.rightbracket keyboard 0x0 48 + +ss.input.port11.keyboard.rshift keyboard 0x0 229 + +ss.input.port11.keyboard.s keyboard 0x0 22 + +ss.input.port11.keyboard.scrolllock keyboard 0x0 71 + +ss.input.port11.keyboard.semicolon keyboard 0x0 51 + +ss.input.port11.keyboard.slash keyboard 0x0 56 + +ss.input.port11.keyboard.space keyboard 0x0 44 + +ss.input.port11.keyboard.t keyboard 0x0 23 + +ss.input.port11.keyboard.tab keyboard 0x0 43 + +ss.input.port11.keyboard.u keyboard 0x0 24 + +ss.input.port11.keyboard.up keyboard 0x0 82 + +ss.input.port11.keyboard.v keyboard 0x0 25 + +ss.input.port11.keyboard.w keyboard 0x0 26 + +ss.input.port11.keyboard.x keyboard 0x0 27 + +ss.input.port11.keyboard.y keyboard 0x0 28 + +ss.input.port11.keyboard.z keyboard 0x0 29 + +ss.input.port11.mission.a + +ss.input.port11.mission.afa + +ss.input.port11.mission.afa.defpos off + +ss.input.port11.mission.afb + +ss.input.port11.mission.afb.defpos off + +ss.input.port11.mission.afc + +ss.input.port11.mission.afc.defpos off + +ss.input.port11.mission.afl + +ss.input.port11.mission.afl.defpos off + +ss.input.port11.mission.afr + +ss.input.port11.mission.afr.defpos off + +ss.input.port11.mission.afspeed + +ss.input.port11.mission.afspeed.defpos 1 + +ss.input.port11.mission.afx + +ss.input.port11.mission.afx.defpos off + +ss.input.port11.mission.afy + +ss.input.port11.mission.afy.defpos off + +ss.input.port11.mission.afz + +ss.input.port11.mission.afz.defpos off + +ss.input.port11.mission.b + +ss.input.port11.mission.c + +ss.input.port11.mission.l + +ss.input.port11.mission.r + +ss.input.port11.mission.start + +ss.input.port11.mission.stick_back + +ss.input.port11.mission.stick_fore + +ss.input.port11.mission.stick_left + +ss.input.port11.mission.stick_right + +ss.input.port11.mission.throttle_down + +ss.input.port11.mission.throttle_up + +ss.input.port11.mission.x + +ss.input.port11.mission.y + +ss.input.port11.mission.z + +ss.input.port11.mouse.left mouse 0x0 button_left + +ss.input.port11.mouse.middle mouse 0x0 button_middle + +ss.input.port11.mouse.motion_down mouse 0x0 rel_y+ + +ss.input.port11.mouse.motion_left mouse 0x0 rel_x- + +ss.input.port11.mouse.motion_right mouse 0x0 rel_x+ + +ss.input.port11.mouse.motion_up mouse 0x0 rel_y- + +ss.input.port11.mouse.right mouse 0x0 button_right + +ss.input.port11.mouse.start keyboard 0x0 40 + +ss.input.port11.wheel.a + +ss.input.port11.wheel.analog_left + +ss.input.port11.wheel.analog_right + +ss.input.port11.wheel.b + +ss.input.port11.wheel.c + +ss.input.port11.wheel.down + +ss.input.port11.wheel.start + +ss.input.port11.wheel.up + +ss.input.port11.wheel.x + +ss.input.port11.wheel.y + +ss.input.port11.wheel.z + +ss.input.port12 gamepad + +ss.input.port12.3dpad.a + +ss.input.port12.3dpad.analog_down + +ss.input.port12.3dpad.analog_left + +ss.input.port12.3dpad.analog_right + +ss.input.port12.3dpad.analog_up + +ss.input.port12.3dpad.b + +ss.input.port12.3dpad.c + +ss.input.port12.3dpad.down + +ss.input.port12.3dpad.left + +ss.input.port12.3dpad.ls + +ss.input.port12.3dpad.mode + +ss.input.port12.3dpad.mode.defpos digital + +ss.input.port12.3dpad.right + +ss.input.port12.3dpad.rs + +ss.input.port12.3dpad.start + +ss.input.port12.3dpad.up + +ss.input.port12.3dpad.x + +ss.input.port12.3dpad.y + +ss.input.port12.3dpad.z + +ss.input.port12.dmission.a + +ss.input.port12.dmission.afa + +ss.input.port12.dmission.afa.defpos off + +ss.input.port12.dmission.afb + +ss.input.port12.dmission.afb.defpos off + +ss.input.port12.dmission.afc + +ss.input.port12.dmission.afc.defpos off + +ss.input.port12.dmission.afl + +ss.input.port12.dmission.afl.defpos off + +ss.input.port12.dmission.afr + +ss.input.port12.dmission.afr.defpos off + +ss.input.port12.dmission.afspeed + +ss.input.port12.dmission.afspeed.defpos 1 + +ss.input.port12.dmission.afx + +ss.input.port12.dmission.afx.defpos off + +ss.input.port12.dmission.afy + +ss.input.port12.dmission.afy.defpos off + +ss.input.port12.dmission.afz + +ss.input.port12.dmission.afz.defpos off + +ss.input.port12.dmission.b + +ss.input.port12.dmission.c + +ss.input.port12.dmission.l + +ss.input.port12.dmission.lstick_back + +ss.input.port12.dmission.lstick_fore + +ss.input.port12.dmission.lstick_left + +ss.input.port12.dmission.lstick_right + +ss.input.port12.dmission.lthrottle_down + +ss.input.port12.dmission.lthrottle_up + +ss.input.port12.dmission.r + +ss.input.port12.dmission.rstick_back + +ss.input.port12.dmission.rstick_fore + +ss.input.port12.dmission.rstick_left + +ss.input.port12.dmission.rstick_right + +ss.input.port12.dmission.rthrottle_down + +ss.input.port12.dmission.rthrottle_up + +ss.input.port12.dmission.start + +ss.input.port12.dmission.x + +ss.input.port12.dmission.y + +ss.input.port12.dmission.z + +ss.input.port12.gamepad.a + +ss.input.port12.gamepad.b + +ss.input.port12.gamepad.c + +ss.input.port12.gamepad.down + +ss.input.port12.gamepad.left + +ss.input.port12.gamepad.ls + +ss.input.port12.gamepad.right + +ss.input.port12.gamepad.rs + +ss.input.port12.gamepad.start + +ss.input.port12.gamepad.up + +ss.input.port12.gamepad.x + +ss.input.port12.gamepad.y + +ss.input.port12.gamepad.z + +ss.input.port12.gun.offscreen_shot mouse 0x0 button_right + +ss.input.port12.gun.start mouse 0x0 button_middle + +ss.input.port12.gun.trigger mouse 0x0 button_left + +ss.input.port12.gun.x_axis mouse 0x0 cursor_x-+ + +ss.input.port12.gun.y_axis mouse 0x0 cursor_y-+ + +ss.input.port12.gun_chairs 0xFF8080 + +ss.input.port12.jpkeyboard.0 keyboard 0x0 39 + +ss.input.port12.jpkeyboard.1 keyboard 0x0 30 + +ss.input.port12.jpkeyboard.2 keyboard 0x0 31 + +ss.input.port12.jpkeyboard.3 keyboard 0x0 32 + +ss.input.port12.jpkeyboard.4 keyboard 0x0 33 + +ss.input.port12.jpkeyboard.5 keyboard 0x0 34 + +ss.input.port12.jpkeyboard.6 keyboard 0x0 35 + +ss.input.port12.jpkeyboard.7 keyboard 0x0 36 + +ss.input.port12.jpkeyboard.8 keyboard 0x0 37 + +ss.input.port12.jpkeyboard.9 keyboard 0x0 38 + +ss.input.port12.jpkeyboard.a keyboard 0x0 4 + +ss.input.port12.jpkeyboard.at keyboard 0x0 47 + +ss.input.port12.jpkeyboard.b keyboard 0x0 5 + +ss.input.port12.jpkeyboard.backslash keyboard 0x0 135 + +ss.input.port12.jpkeyboard.backspace keyboard 0x0 42 + +ss.input.port12.jpkeyboard.c keyboard 0x0 6 + +ss.input.port12.jpkeyboard.capslock keyboard 0x0 57 + +ss.input.port12.jpkeyboard.circumflex keyboard 0x0 46 + +ss.input.port12.jpkeyboard.colon keyboard 0x0 52 + +ss.input.port12.jpkeyboard.comma keyboard 0x0 54 + +ss.input.port12.jpkeyboard.conv keyboard 0x0 138 + +ss.input.port12.jpkeyboard.d keyboard 0x0 7 + +ss.input.port12.jpkeyboard.delete keyboard 0x0 76 + +ss.input.port12.jpkeyboard.down keyboard 0x0 81 + +ss.input.port12.jpkeyboard.e keyboard 0x0 8 + +ss.input.port12.jpkeyboard.end keyboard 0x0 77 + +ss.input.port12.jpkeyboard.enter keyboard 0x0 40 + +ss.input.port12.jpkeyboard.esc keyboard 0x0 41 + +ss.input.port12.jpkeyboard.f keyboard 0x0 9 + +ss.input.port12.jpkeyboard.f1 keyboard 0x0 58 + +ss.input.port12.jpkeyboard.f10 keyboard 0x0 67 + +ss.input.port12.jpkeyboard.f11 keyboard 0x0 68 + +ss.input.port12.jpkeyboard.f12 keyboard 0x0 69 + +ss.input.port12.jpkeyboard.f2 keyboard 0x0 59 + +ss.input.port12.jpkeyboard.f3 keyboard 0x0 60 + +ss.input.port12.jpkeyboard.f4 keyboard 0x0 61 + +ss.input.port12.jpkeyboard.f5 keyboard 0x0 62 + +ss.input.port12.jpkeyboard.f6 keyboard 0x0 63 + +ss.input.port12.jpkeyboard.f7 keyboard 0x0 64 + +ss.input.port12.jpkeyboard.f8 keyboard 0x0 65 + +ss.input.port12.jpkeyboard.f9 keyboard 0x0 66 + +ss.input.port12.jpkeyboard.g keyboard 0x0 10 + +ss.input.port12.jpkeyboard.h keyboard 0x0 11 + +ss.input.port12.jpkeyboard.hkr keyboard 0x0 136 + +ss.input.port12.jpkeyboard.home keyboard 0x0 74 + +ss.input.port12.jpkeyboard.hwfw keyboard 0x0 53 + +ss.input.port12.jpkeyboard.i keyboard 0x0 12 + +ss.input.port12.jpkeyboard.insert keyboard 0x0 73 + +ss.input.port12.jpkeyboard.j keyboard 0x0 13 + +ss.input.port12.jpkeyboard.k keyboard 0x0 14 + +ss.input.port12.jpkeyboard.l keyboard 0x0 15 + +ss.input.port12.jpkeyboard.lalt keyboard 0x0 226 + +ss.input.port12.jpkeyboard.lctrl keyboard 0x0 224 + +ss.input.port12.jpkeyboard.left keyboard 0x0 80 + +ss.input.port12.jpkeyboard.leftbracket keyboard 0x0 48 + +ss.input.port12.jpkeyboard.lshift keyboard 0x0 225 + +ss.input.port12.jpkeyboard.m keyboard 0x0 16 + +ss.input.port12.jpkeyboard.minus keyboard 0x0 45 + +ss.input.port12.jpkeyboard.n keyboard 0x0 17 + +ss.input.port12.jpkeyboard.nonconv keyboard 0x0 139 + +ss.input.port12.jpkeyboard.o keyboard 0x0 18 + +ss.input.port12.jpkeyboard.p keyboard 0x0 19 + +ss.input.port12.jpkeyboard.pagedown keyboard 0x0 78 + +ss.input.port12.jpkeyboard.pageup keyboard 0x0 75 + +ss.input.port12.jpkeyboard.pause keyboard 0x0 72 || keyboard 0x0 83 + +ss.input.port12.jpkeyboard.period keyboard 0x0 55 + +ss.input.port12.jpkeyboard.printscreen keyboard 0x0 70 + +ss.input.port12.jpkeyboard.q keyboard 0x0 20 + +ss.input.port12.jpkeyboard.r keyboard 0x0 21 + +ss.input.port12.jpkeyboard.ralt keyboard 0x0 230 + +ss.input.port12.jpkeyboard.rctrl keyboard 0x0 228 + +ss.input.port12.jpkeyboard.right keyboard 0x0 79 + +ss.input.port12.jpkeyboard.rightbracket keyboard 0x0 49 + +ss.input.port12.jpkeyboard.rshift keyboard 0x0 229 + +ss.input.port12.jpkeyboard.s keyboard 0x0 22 + +ss.input.port12.jpkeyboard.scrolllock keyboard 0x0 71 + +ss.input.port12.jpkeyboard.semicolon keyboard 0x0 51 + +ss.input.port12.jpkeyboard.slash keyboard 0x0 56 + +ss.input.port12.jpkeyboard.space keyboard 0x0 44 + +ss.input.port12.jpkeyboard.t keyboard 0x0 23 + +ss.input.port12.jpkeyboard.tab keyboard 0x0 43 + +ss.input.port12.jpkeyboard.u keyboard 0x0 24 + +ss.input.port12.jpkeyboard.up keyboard 0x0 82 + +ss.input.port12.jpkeyboard.v keyboard 0x0 25 + +ss.input.port12.jpkeyboard.w keyboard 0x0 26 + +ss.input.port12.jpkeyboard.x keyboard 0x0 27 + +ss.input.port12.jpkeyboard.y keyboard 0x0 28 + +ss.input.port12.jpkeyboard.yen keyboard 0x0 137 + +ss.input.port12.jpkeyboard.z keyboard 0x0 29 + +ss.input.port12.keyboard.0 keyboard 0x0 39 + +ss.input.port12.keyboard.1 keyboard 0x0 30 + +ss.input.port12.keyboard.2 keyboard 0x0 31 + +ss.input.port12.keyboard.3 keyboard 0x0 32 + +ss.input.port12.keyboard.4 keyboard 0x0 33 + +ss.input.port12.keyboard.5 keyboard 0x0 34 + +ss.input.port12.keyboard.6 keyboard 0x0 35 + +ss.input.port12.keyboard.7 keyboard 0x0 36 + +ss.input.port12.keyboard.8 keyboard 0x0 37 + +ss.input.port12.keyboard.9 keyboard 0x0 38 + +ss.input.port12.keyboard.a keyboard 0x0 4 + +ss.input.port12.keyboard.b keyboard 0x0 5 + +ss.input.port12.keyboard.backslash keyboard 0x0 49 || keyboard 0x0 135 + +ss.input.port12.keyboard.backspace keyboard 0x0 42 + +ss.input.port12.keyboard.c keyboard 0x0 6 + +ss.input.port12.keyboard.capslock keyboard 0x0 57 + +ss.input.port12.keyboard.comma keyboard 0x0 54 + +ss.input.port12.keyboard.d keyboard 0x0 7 + +ss.input.port12.keyboard.delete keyboard 0x0 76 + +ss.input.port12.keyboard.down keyboard 0x0 81 + +ss.input.port12.keyboard.e keyboard 0x0 8 + +ss.input.port12.keyboard.end keyboard 0x0 77 + +ss.input.port12.keyboard.enter keyboard 0x0 40 + +ss.input.port12.keyboard.equals keyboard 0x0 46 + +ss.input.port12.keyboard.esc keyboard 0x0 41 + +ss.input.port12.keyboard.f keyboard 0x0 9 + +ss.input.port12.keyboard.f1 keyboard 0x0 58 + +ss.input.port12.keyboard.f10 keyboard 0x0 67 + +ss.input.port12.keyboard.f11 keyboard 0x0 68 + +ss.input.port12.keyboard.f12 keyboard 0x0 69 + +ss.input.port12.keyboard.f2 keyboard 0x0 59 + +ss.input.port12.keyboard.f3 keyboard 0x0 60 + +ss.input.port12.keyboard.f4 keyboard 0x0 61 + +ss.input.port12.keyboard.f5 keyboard 0x0 62 + +ss.input.port12.keyboard.f6 keyboard 0x0 63 + +ss.input.port12.keyboard.f7 keyboard 0x0 64 + +ss.input.port12.keyboard.f8 keyboard 0x0 65 + +ss.input.port12.keyboard.f9 keyboard 0x0 66 + +ss.input.port12.keyboard.g keyboard 0x0 10 + +ss.input.port12.keyboard.grave keyboard 0x0 53 + +ss.input.port12.keyboard.h keyboard 0x0 11 + +ss.input.port12.keyboard.home keyboard 0x0 74 + +ss.input.port12.keyboard.i keyboard 0x0 12 + +ss.input.port12.keyboard.insert keyboard 0x0 73 + +ss.input.port12.keyboard.j keyboard 0x0 13 + +ss.input.port12.keyboard.k keyboard 0x0 14 + +ss.input.port12.keyboard.kp_asterisk keyboard 0x0 85 + +ss.input.port12.keyboard.kp_center keyboard 0x0 93 + +ss.input.port12.keyboard.kp_delete keyboard 0x0 99 + +ss.input.port12.keyboard.kp_down keyboard 0x0 90 + +ss.input.port12.keyboard.kp_end keyboard 0x0 89 + +ss.input.port12.keyboard.kp_enter keyboard 0x0 88 + +ss.input.port12.keyboard.kp_home keyboard 0x0 95 + +ss.input.port12.keyboard.kp_insert keyboard 0x0 98 + +ss.input.port12.keyboard.kp_left keyboard 0x0 92 + +ss.input.port12.keyboard.kp_minus keyboard 0x0 86 + +ss.input.port12.keyboard.kp_pagedown keyboard 0x0 91 + +ss.input.port12.keyboard.kp_pageup keyboard 0x0 97 + +ss.input.port12.keyboard.kp_plus keyboard 0x0 87 + +ss.input.port12.keyboard.kp_right keyboard 0x0 94 + +ss.input.port12.keyboard.kp_slash keyboard 0x0 84 + +ss.input.port12.keyboard.kp_up keyboard 0x0 96 + +ss.input.port12.keyboard.l keyboard 0x0 15 + +ss.input.port12.keyboard.lalt keyboard 0x0 226 + +ss.input.port12.keyboard.lctrl keyboard 0x0 224 + +ss.input.port12.keyboard.left keyboard 0x0 80 + +ss.input.port12.keyboard.leftbracket keyboard 0x0 47 + +ss.input.port12.keyboard.lshift keyboard 0x0 225 + +ss.input.port12.keyboard.m keyboard 0x0 16 + +ss.input.port12.keyboard.minus keyboard 0x0 45 + +ss.input.port12.keyboard.n keyboard 0x0 17 + +ss.input.port12.keyboard.numlock keyboard 0x0 83 + +ss.input.port12.keyboard.o keyboard 0x0 18 + +ss.input.port12.keyboard.p keyboard 0x0 19 + +ss.input.port12.keyboard.pagedown keyboard 0x0 78 + +ss.input.port12.keyboard.pageup keyboard 0x0 75 + +ss.input.port12.keyboard.pause keyboard 0x0 72 + +ss.input.port12.keyboard.period keyboard 0x0 55 + +ss.input.port12.keyboard.printscreen keyboard 0x0 70 + +ss.input.port12.keyboard.q keyboard 0x0 20 + +ss.input.port12.keyboard.quote keyboard 0x0 52 + +ss.input.port12.keyboard.r keyboard 0x0 21 + +ss.input.port12.keyboard.ralt keyboard 0x0 230 + +ss.input.port12.keyboard.rctrl keyboard 0x0 228 + +ss.input.port12.keyboard.right keyboard 0x0 79 + +ss.input.port12.keyboard.rightbracket keyboard 0x0 48 + +ss.input.port12.keyboard.rshift keyboard 0x0 229 + +ss.input.port12.keyboard.s keyboard 0x0 22 + +ss.input.port12.keyboard.scrolllock keyboard 0x0 71 + +ss.input.port12.keyboard.semicolon keyboard 0x0 51 + +ss.input.port12.keyboard.slash keyboard 0x0 56 + +ss.input.port12.keyboard.space keyboard 0x0 44 + +ss.input.port12.keyboard.t keyboard 0x0 23 + +ss.input.port12.keyboard.tab keyboard 0x0 43 + +ss.input.port12.keyboard.u keyboard 0x0 24 + +ss.input.port12.keyboard.up keyboard 0x0 82 + +ss.input.port12.keyboard.v keyboard 0x0 25 + +ss.input.port12.keyboard.w keyboard 0x0 26 + +ss.input.port12.keyboard.x keyboard 0x0 27 + +ss.input.port12.keyboard.y keyboard 0x0 28 + +ss.input.port12.keyboard.z keyboard 0x0 29 + +ss.input.port12.mission.a + +ss.input.port12.mission.afa + +ss.input.port12.mission.afa.defpos off + +ss.input.port12.mission.afb + +ss.input.port12.mission.afb.defpos off + +ss.input.port12.mission.afc + +ss.input.port12.mission.afc.defpos off + +ss.input.port12.mission.afl + +ss.input.port12.mission.afl.defpos off + +ss.input.port12.mission.afr + +ss.input.port12.mission.afr.defpos off + +ss.input.port12.mission.afspeed + +ss.input.port12.mission.afspeed.defpos 1 + +ss.input.port12.mission.afx + +ss.input.port12.mission.afx.defpos off + +ss.input.port12.mission.afy + +ss.input.port12.mission.afy.defpos off + +ss.input.port12.mission.afz + +ss.input.port12.mission.afz.defpos off + +ss.input.port12.mission.b + +ss.input.port12.mission.c + +ss.input.port12.mission.l + +ss.input.port12.mission.r + +ss.input.port12.mission.start + +ss.input.port12.mission.stick_back + +ss.input.port12.mission.stick_fore + +ss.input.port12.mission.stick_left + +ss.input.port12.mission.stick_right + +ss.input.port12.mission.throttle_down + +ss.input.port12.mission.throttle_up + +ss.input.port12.mission.x + +ss.input.port12.mission.y + +ss.input.port12.mission.z + +ss.input.port12.mouse.left mouse 0x0 button_left + +ss.input.port12.mouse.middle mouse 0x0 button_middle + +ss.input.port12.mouse.motion_down mouse 0x0 rel_y+ + +ss.input.port12.mouse.motion_left mouse 0x0 rel_x- + +ss.input.port12.mouse.motion_right mouse 0x0 rel_x+ + +ss.input.port12.mouse.motion_up mouse 0x0 rel_y- + +ss.input.port12.mouse.right mouse 0x0 button_right + +ss.input.port12.mouse.start keyboard 0x0 40 + +ss.input.port12.wheel.a + +ss.input.port12.wheel.analog_left + +ss.input.port12.wheel.analog_right + +ss.input.port12.wheel.b + +ss.input.port12.wheel.c + +ss.input.port12.wheel.down + +ss.input.port12.wheel.start + +ss.input.port12.wheel.up + +ss.input.port12.wheel.x + +ss.input.port12.wheel.y + +ss.input.port12.wheel.z + +ss.input.port2 gamepad + +ss.input.port2.3dpad.a + +ss.input.port2.3dpad.analog_down + +ss.input.port2.3dpad.analog_left + +ss.input.port2.3dpad.analog_right + +ss.input.port2.3dpad.analog_up + +ss.input.port2.3dpad.b + +ss.input.port2.3dpad.c + +ss.input.port2.3dpad.down + +ss.input.port2.3dpad.left + +ss.input.port2.3dpad.ls + +ss.input.port2.3dpad.mode + +ss.input.port2.3dpad.mode.defpos digital + +ss.input.port2.3dpad.right + +ss.input.port2.3dpad.rs + +ss.input.port2.3dpad.start + +ss.input.port2.3dpad.up + +ss.input.port2.3dpad.x + +ss.input.port2.3dpad.y + +ss.input.port2.3dpad.z + +ss.input.port2.dmission.a + +ss.input.port2.dmission.afa + +ss.input.port2.dmission.afa.defpos off + +ss.input.port2.dmission.afb + +ss.input.port2.dmission.afb.defpos off + +ss.input.port2.dmission.afc + +ss.input.port2.dmission.afc.defpos off + +ss.input.port2.dmission.afl + +ss.input.port2.dmission.afl.defpos off + +ss.input.port2.dmission.afr + +ss.input.port2.dmission.afr.defpos off + +ss.input.port2.dmission.afspeed + +ss.input.port2.dmission.afspeed.defpos 1 + +ss.input.port2.dmission.afx + +ss.input.port2.dmission.afx.defpos off + +ss.input.port2.dmission.afy + +ss.input.port2.dmission.afy.defpos off + +ss.input.port2.dmission.afz + +ss.input.port2.dmission.afz.defpos off + +ss.input.port2.dmission.b + +ss.input.port2.dmission.c + +ss.input.port2.dmission.l + +ss.input.port2.dmission.lstick_back + +ss.input.port2.dmission.lstick_fore + +ss.input.port2.dmission.lstick_left + +ss.input.port2.dmission.lstick_right + +ss.input.port2.dmission.lthrottle_down + +ss.input.port2.dmission.lthrottle_up + +ss.input.port2.dmission.r + +ss.input.port2.dmission.rstick_back + +ss.input.port2.dmission.rstick_fore + +ss.input.port2.dmission.rstick_left + +ss.input.port2.dmission.rstick_right + +ss.input.port2.dmission.rthrottle_down + +ss.input.port2.dmission.rthrottle_up + +ss.input.port2.dmission.start + +ss.input.port2.dmission.x + +ss.input.port2.dmission.y + +ss.input.port2.dmission.z + +ss.input.port2.gamepad.a + +ss.input.port2.gamepad.b + +ss.input.port2.gamepad.c + +ss.input.port2.gamepad.down + +ss.input.port2.gamepad.left + +ss.input.port2.gamepad.ls + +ss.input.port2.gamepad.right + +ss.input.port2.gamepad.rs + +ss.input.port2.gamepad.start + +ss.input.port2.gamepad.up + +ss.input.port2.gamepad.x + +ss.input.port2.gamepad.y + +ss.input.port2.gamepad.z + +ss.input.port2.gun.offscreen_shot mouse 0x0 button_right + +ss.input.port2.gun.start mouse 0x0 button_middle + +ss.input.port2.gun.trigger mouse 0x0 button_left + +ss.input.port2.gun.x_axis mouse 0x0 cursor_x-+ + +ss.input.port2.gun.y_axis mouse 0x0 cursor_y-+ + +ss.input.port2.gun_chairs 0x00FF00 + +ss.input.port2.jpkeyboard.0 keyboard 0x0 39 + +ss.input.port2.jpkeyboard.1 keyboard 0x0 30 + +ss.input.port2.jpkeyboard.2 keyboard 0x0 31 + +ss.input.port2.jpkeyboard.3 keyboard 0x0 32 + +ss.input.port2.jpkeyboard.4 keyboard 0x0 33 + +ss.input.port2.jpkeyboard.5 keyboard 0x0 34 + +ss.input.port2.jpkeyboard.6 keyboard 0x0 35 + +ss.input.port2.jpkeyboard.7 keyboard 0x0 36 + +ss.input.port2.jpkeyboard.8 keyboard 0x0 37 + +ss.input.port2.jpkeyboard.9 keyboard 0x0 38 + +ss.input.port2.jpkeyboard.a keyboard 0x0 4 + +ss.input.port2.jpkeyboard.at keyboard 0x0 47 + +ss.input.port2.jpkeyboard.b keyboard 0x0 5 + +ss.input.port2.jpkeyboard.backslash keyboard 0x0 135 + +ss.input.port2.jpkeyboard.backspace keyboard 0x0 42 + +ss.input.port2.jpkeyboard.c keyboard 0x0 6 + +ss.input.port2.jpkeyboard.capslock keyboard 0x0 57 + +ss.input.port2.jpkeyboard.circumflex keyboard 0x0 46 + +ss.input.port2.jpkeyboard.colon keyboard 0x0 52 + +ss.input.port2.jpkeyboard.comma keyboard 0x0 54 + +ss.input.port2.jpkeyboard.conv keyboard 0x0 138 + +ss.input.port2.jpkeyboard.d keyboard 0x0 7 + +ss.input.port2.jpkeyboard.delete keyboard 0x0 76 + +ss.input.port2.jpkeyboard.down keyboard 0x0 81 + +ss.input.port2.jpkeyboard.e keyboard 0x0 8 + +ss.input.port2.jpkeyboard.end keyboard 0x0 77 + +ss.input.port2.jpkeyboard.enter keyboard 0x0 40 + +ss.input.port2.jpkeyboard.esc keyboard 0x0 41 + +ss.input.port2.jpkeyboard.f keyboard 0x0 9 + +ss.input.port2.jpkeyboard.f1 keyboard 0x0 58 + +ss.input.port2.jpkeyboard.f10 keyboard 0x0 67 + +ss.input.port2.jpkeyboard.f11 keyboard 0x0 68 + +ss.input.port2.jpkeyboard.f12 keyboard 0x0 69 + +ss.input.port2.jpkeyboard.f2 keyboard 0x0 59 + +ss.input.port2.jpkeyboard.f3 keyboard 0x0 60 + +ss.input.port2.jpkeyboard.f4 keyboard 0x0 61 + +ss.input.port2.jpkeyboard.f5 keyboard 0x0 62 + +ss.input.port2.jpkeyboard.f6 keyboard 0x0 63 + +ss.input.port2.jpkeyboard.f7 keyboard 0x0 64 + +ss.input.port2.jpkeyboard.f8 keyboard 0x0 65 + +ss.input.port2.jpkeyboard.f9 keyboard 0x0 66 + +ss.input.port2.jpkeyboard.g keyboard 0x0 10 + +ss.input.port2.jpkeyboard.h keyboard 0x0 11 + +ss.input.port2.jpkeyboard.hkr keyboard 0x0 136 + +ss.input.port2.jpkeyboard.home keyboard 0x0 74 + +ss.input.port2.jpkeyboard.hwfw keyboard 0x0 53 + +ss.input.port2.jpkeyboard.i keyboard 0x0 12 + +ss.input.port2.jpkeyboard.insert keyboard 0x0 73 + +ss.input.port2.jpkeyboard.j keyboard 0x0 13 + +ss.input.port2.jpkeyboard.k keyboard 0x0 14 + +ss.input.port2.jpkeyboard.l keyboard 0x0 15 + +ss.input.port2.jpkeyboard.lalt keyboard 0x0 226 + +ss.input.port2.jpkeyboard.lctrl keyboard 0x0 224 + +ss.input.port2.jpkeyboard.left keyboard 0x0 80 + +ss.input.port2.jpkeyboard.leftbracket keyboard 0x0 48 + +ss.input.port2.jpkeyboard.lshift keyboard 0x0 225 + +ss.input.port2.jpkeyboard.m keyboard 0x0 16 + +ss.input.port2.jpkeyboard.minus keyboard 0x0 45 + +ss.input.port2.jpkeyboard.n keyboard 0x0 17 + +ss.input.port2.jpkeyboard.nonconv keyboard 0x0 139 + +ss.input.port2.jpkeyboard.o keyboard 0x0 18 + +ss.input.port2.jpkeyboard.p keyboard 0x0 19 + +ss.input.port2.jpkeyboard.pagedown keyboard 0x0 78 + +ss.input.port2.jpkeyboard.pageup keyboard 0x0 75 + +ss.input.port2.jpkeyboard.pause keyboard 0x0 72 || keyboard 0x0 83 + +ss.input.port2.jpkeyboard.period keyboard 0x0 55 + +ss.input.port2.jpkeyboard.printscreen keyboard 0x0 70 + +ss.input.port2.jpkeyboard.q keyboard 0x0 20 + +ss.input.port2.jpkeyboard.r keyboard 0x0 21 + +ss.input.port2.jpkeyboard.ralt keyboard 0x0 230 + +ss.input.port2.jpkeyboard.rctrl keyboard 0x0 228 + +ss.input.port2.jpkeyboard.right keyboard 0x0 79 + +ss.input.port2.jpkeyboard.rightbracket keyboard 0x0 49 + +ss.input.port2.jpkeyboard.rshift keyboard 0x0 229 + +ss.input.port2.jpkeyboard.s keyboard 0x0 22 + +ss.input.port2.jpkeyboard.scrolllock keyboard 0x0 71 + +ss.input.port2.jpkeyboard.semicolon keyboard 0x0 51 + +ss.input.port2.jpkeyboard.slash keyboard 0x0 56 + +ss.input.port2.jpkeyboard.space keyboard 0x0 44 + +ss.input.port2.jpkeyboard.t keyboard 0x0 23 + +ss.input.port2.jpkeyboard.tab keyboard 0x0 43 + +ss.input.port2.jpkeyboard.u keyboard 0x0 24 + +ss.input.port2.jpkeyboard.up keyboard 0x0 82 + +ss.input.port2.jpkeyboard.v keyboard 0x0 25 + +ss.input.port2.jpkeyboard.w keyboard 0x0 26 + +ss.input.port2.jpkeyboard.x keyboard 0x0 27 + +ss.input.port2.jpkeyboard.y keyboard 0x0 28 + +ss.input.port2.jpkeyboard.yen keyboard 0x0 137 + +ss.input.port2.jpkeyboard.z keyboard 0x0 29 + +ss.input.port2.keyboard.0 keyboard 0x0 39 + +ss.input.port2.keyboard.1 keyboard 0x0 30 + +ss.input.port2.keyboard.2 keyboard 0x0 31 + +ss.input.port2.keyboard.3 keyboard 0x0 32 + +ss.input.port2.keyboard.4 keyboard 0x0 33 + +ss.input.port2.keyboard.5 keyboard 0x0 34 + +ss.input.port2.keyboard.6 keyboard 0x0 35 + +ss.input.port2.keyboard.7 keyboard 0x0 36 + +ss.input.port2.keyboard.8 keyboard 0x0 37 + +ss.input.port2.keyboard.9 keyboard 0x0 38 + +ss.input.port2.keyboard.a keyboard 0x0 4 + +ss.input.port2.keyboard.b keyboard 0x0 5 + +ss.input.port2.keyboard.backslash keyboard 0x0 49 || keyboard 0x0 135 + +ss.input.port2.keyboard.backspace keyboard 0x0 42 + +ss.input.port2.keyboard.c keyboard 0x0 6 + +ss.input.port2.keyboard.capslock keyboard 0x0 57 + +ss.input.port2.keyboard.comma keyboard 0x0 54 + +ss.input.port2.keyboard.d keyboard 0x0 7 + +ss.input.port2.keyboard.delete keyboard 0x0 76 + +ss.input.port2.keyboard.down keyboard 0x0 81 + +ss.input.port2.keyboard.e keyboard 0x0 8 + +ss.input.port2.keyboard.end keyboard 0x0 77 + +ss.input.port2.keyboard.enter keyboard 0x0 40 + +ss.input.port2.keyboard.equals keyboard 0x0 46 + +ss.input.port2.keyboard.esc keyboard 0x0 41 + +ss.input.port2.keyboard.f keyboard 0x0 9 + +ss.input.port2.keyboard.f1 keyboard 0x0 58 + +ss.input.port2.keyboard.f10 keyboard 0x0 67 + +ss.input.port2.keyboard.f11 keyboard 0x0 68 + +ss.input.port2.keyboard.f12 keyboard 0x0 69 + +ss.input.port2.keyboard.f2 keyboard 0x0 59 + +ss.input.port2.keyboard.f3 keyboard 0x0 60 + +ss.input.port2.keyboard.f4 keyboard 0x0 61 + +ss.input.port2.keyboard.f5 keyboard 0x0 62 + +ss.input.port2.keyboard.f6 keyboard 0x0 63 + +ss.input.port2.keyboard.f7 keyboard 0x0 64 + +ss.input.port2.keyboard.f8 keyboard 0x0 65 + +ss.input.port2.keyboard.f9 keyboard 0x0 66 + +ss.input.port2.keyboard.g keyboard 0x0 10 + +ss.input.port2.keyboard.grave keyboard 0x0 53 + +ss.input.port2.keyboard.h keyboard 0x0 11 + +ss.input.port2.keyboard.home keyboard 0x0 74 + +ss.input.port2.keyboard.i keyboard 0x0 12 + +ss.input.port2.keyboard.insert keyboard 0x0 73 + +ss.input.port2.keyboard.j keyboard 0x0 13 + +ss.input.port2.keyboard.k keyboard 0x0 14 + +ss.input.port2.keyboard.kp_asterisk keyboard 0x0 85 + +ss.input.port2.keyboard.kp_center keyboard 0x0 93 + +ss.input.port2.keyboard.kp_delete keyboard 0x0 99 + +ss.input.port2.keyboard.kp_down keyboard 0x0 90 + +ss.input.port2.keyboard.kp_end keyboard 0x0 89 + +ss.input.port2.keyboard.kp_enter keyboard 0x0 88 + +ss.input.port2.keyboard.kp_home keyboard 0x0 95 + +ss.input.port2.keyboard.kp_insert keyboard 0x0 98 + +ss.input.port2.keyboard.kp_left keyboard 0x0 92 + +ss.input.port2.keyboard.kp_minus keyboard 0x0 86 + +ss.input.port2.keyboard.kp_pagedown keyboard 0x0 91 + +ss.input.port2.keyboard.kp_pageup keyboard 0x0 97 + +ss.input.port2.keyboard.kp_plus keyboard 0x0 87 + +ss.input.port2.keyboard.kp_right keyboard 0x0 94 + +ss.input.port2.keyboard.kp_slash keyboard 0x0 84 + +ss.input.port2.keyboard.kp_up keyboard 0x0 96 + +ss.input.port2.keyboard.l keyboard 0x0 15 + +ss.input.port2.keyboard.lalt keyboard 0x0 226 + +ss.input.port2.keyboard.lctrl keyboard 0x0 224 + +ss.input.port2.keyboard.left keyboard 0x0 80 + +ss.input.port2.keyboard.leftbracket keyboard 0x0 47 + +ss.input.port2.keyboard.lshift keyboard 0x0 225 + +ss.input.port2.keyboard.m keyboard 0x0 16 + +ss.input.port2.keyboard.minus keyboard 0x0 45 + +ss.input.port2.keyboard.n keyboard 0x0 17 + +ss.input.port2.keyboard.numlock keyboard 0x0 83 + +ss.input.port2.keyboard.o keyboard 0x0 18 + +ss.input.port2.keyboard.p keyboard 0x0 19 + +ss.input.port2.keyboard.pagedown keyboard 0x0 78 + +ss.input.port2.keyboard.pageup keyboard 0x0 75 + +ss.input.port2.keyboard.pause keyboard 0x0 72 + +ss.input.port2.keyboard.period keyboard 0x0 55 + +ss.input.port2.keyboard.printscreen keyboard 0x0 70 + +ss.input.port2.keyboard.q keyboard 0x0 20 + +ss.input.port2.keyboard.quote keyboard 0x0 52 + +ss.input.port2.keyboard.r keyboard 0x0 21 + +ss.input.port2.keyboard.ralt keyboard 0x0 230 + +ss.input.port2.keyboard.rctrl keyboard 0x0 228 + +ss.input.port2.keyboard.right keyboard 0x0 79 + +ss.input.port2.keyboard.rightbracket keyboard 0x0 48 + +ss.input.port2.keyboard.rshift keyboard 0x0 229 + +ss.input.port2.keyboard.s keyboard 0x0 22 + +ss.input.port2.keyboard.scrolllock keyboard 0x0 71 + +ss.input.port2.keyboard.semicolon keyboard 0x0 51 + +ss.input.port2.keyboard.slash keyboard 0x0 56 + +ss.input.port2.keyboard.space keyboard 0x0 44 + +ss.input.port2.keyboard.t keyboard 0x0 23 + +ss.input.port2.keyboard.tab keyboard 0x0 43 + +ss.input.port2.keyboard.u keyboard 0x0 24 + +ss.input.port2.keyboard.up keyboard 0x0 82 + +ss.input.port2.keyboard.v keyboard 0x0 25 + +ss.input.port2.keyboard.w keyboard 0x0 26 + +ss.input.port2.keyboard.x keyboard 0x0 27 + +ss.input.port2.keyboard.y keyboard 0x0 28 + +ss.input.port2.keyboard.z keyboard 0x0 29 + +ss.input.port2.mission.a + +ss.input.port2.mission.afa + +ss.input.port2.mission.afa.defpos off + +ss.input.port2.mission.afb + +ss.input.port2.mission.afb.defpos off + +ss.input.port2.mission.afc + +ss.input.port2.mission.afc.defpos off + +ss.input.port2.mission.afl + +ss.input.port2.mission.afl.defpos off + +ss.input.port2.mission.afr + +ss.input.port2.mission.afr.defpos off + +ss.input.port2.mission.afspeed + +ss.input.port2.mission.afspeed.defpos 1 + +ss.input.port2.mission.afx + +ss.input.port2.mission.afx.defpos off + +ss.input.port2.mission.afy + +ss.input.port2.mission.afy.defpos off + +ss.input.port2.mission.afz + +ss.input.port2.mission.afz.defpos off + +ss.input.port2.mission.b + +ss.input.port2.mission.c + +ss.input.port2.mission.l + +ss.input.port2.mission.r + +ss.input.port2.mission.start + +ss.input.port2.mission.stick_back + +ss.input.port2.mission.stick_fore + +ss.input.port2.mission.stick_left + +ss.input.port2.mission.stick_right + +ss.input.port2.mission.throttle_down + +ss.input.port2.mission.throttle_up + +ss.input.port2.mission.x + +ss.input.port2.mission.y + +ss.input.port2.mission.z + +ss.input.port2.mouse.left mouse 0x0 button_left + +ss.input.port2.mouse.middle mouse 0x0 button_middle + +ss.input.port2.mouse.motion_down mouse 0x0 rel_y+ + +ss.input.port2.mouse.motion_left mouse 0x0 rel_x- + +ss.input.port2.mouse.motion_right mouse 0x0 rel_x+ + +ss.input.port2.mouse.motion_up mouse 0x0 rel_y- + +ss.input.port2.mouse.right mouse 0x0 button_right + +ss.input.port2.mouse.start keyboard 0x0 40 + +ss.input.port2.wheel.a + +ss.input.port2.wheel.analog_left + +ss.input.port2.wheel.analog_right + +ss.input.port2.wheel.b + +ss.input.port2.wheel.c + +ss.input.port2.wheel.down + +ss.input.port2.wheel.start + +ss.input.port2.wheel.up + +ss.input.port2.wheel.x + +ss.input.port2.wheel.y + +ss.input.port2.wheel.z + +ss.input.port3 gamepad + +ss.input.port3.3dpad.a + +ss.input.port3.3dpad.analog_down + +ss.input.port3.3dpad.analog_left + +ss.input.port3.3dpad.analog_right + +ss.input.port3.3dpad.analog_up + +ss.input.port3.3dpad.b + +ss.input.port3.3dpad.c + +ss.input.port3.3dpad.down + +ss.input.port3.3dpad.left + +ss.input.port3.3dpad.ls + +ss.input.port3.3dpad.mode + +ss.input.port3.3dpad.mode.defpos digital + +ss.input.port3.3dpad.right + +ss.input.port3.3dpad.rs + +ss.input.port3.3dpad.start + +ss.input.port3.3dpad.up + +ss.input.port3.3dpad.x + +ss.input.port3.3dpad.y + +ss.input.port3.3dpad.z + +ss.input.port3.dmission.a + +ss.input.port3.dmission.afa + +ss.input.port3.dmission.afa.defpos off + +ss.input.port3.dmission.afb + +ss.input.port3.dmission.afb.defpos off + +ss.input.port3.dmission.afc + +ss.input.port3.dmission.afc.defpos off + +ss.input.port3.dmission.afl + +ss.input.port3.dmission.afl.defpos off + +ss.input.port3.dmission.afr + +ss.input.port3.dmission.afr.defpos off + +ss.input.port3.dmission.afspeed + +ss.input.port3.dmission.afspeed.defpos 1 + +ss.input.port3.dmission.afx + +ss.input.port3.dmission.afx.defpos off + +ss.input.port3.dmission.afy + +ss.input.port3.dmission.afy.defpos off + +ss.input.port3.dmission.afz + +ss.input.port3.dmission.afz.defpos off + +ss.input.port3.dmission.b + +ss.input.port3.dmission.c + +ss.input.port3.dmission.l + +ss.input.port3.dmission.lstick_back + +ss.input.port3.dmission.lstick_fore + +ss.input.port3.dmission.lstick_left + +ss.input.port3.dmission.lstick_right + +ss.input.port3.dmission.lthrottle_down + +ss.input.port3.dmission.lthrottle_up + +ss.input.port3.dmission.r + +ss.input.port3.dmission.rstick_back + +ss.input.port3.dmission.rstick_fore + +ss.input.port3.dmission.rstick_left + +ss.input.port3.dmission.rstick_right + +ss.input.port3.dmission.rthrottle_down + +ss.input.port3.dmission.rthrottle_up + +ss.input.port3.dmission.start + +ss.input.port3.dmission.x + +ss.input.port3.dmission.y + +ss.input.port3.dmission.z + +ss.input.port3.gamepad.a + +ss.input.port3.gamepad.b + +ss.input.port3.gamepad.c + +ss.input.port3.gamepad.down + +ss.input.port3.gamepad.left + +ss.input.port3.gamepad.ls + +ss.input.port3.gamepad.right + +ss.input.port3.gamepad.rs + +ss.input.port3.gamepad.start + +ss.input.port3.gamepad.up + +ss.input.port3.gamepad.x + +ss.input.port3.gamepad.y + +ss.input.port3.gamepad.z + +ss.input.port3.gun.offscreen_shot mouse 0x0 button_right + +ss.input.port3.gun.start mouse 0x0 button_middle + +ss.input.port3.gun.trigger mouse 0x0 button_left + +ss.input.port3.gun.x_axis mouse 0x0 cursor_x-+ + +ss.input.port3.gun.y_axis mouse 0x0 cursor_y-+ + +ss.input.port3.gun_chairs 0xFF00FF + +ss.input.port3.jpkeyboard.0 keyboard 0x0 39 + +ss.input.port3.jpkeyboard.1 keyboard 0x0 30 + +ss.input.port3.jpkeyboard.2 keyboard 0x0 31 + +ss.input.port3.jpkeyboard.3 keyboard 0x0 32 + +ss.input.port3.jpkeyboard.4 keyboard 0x0 33 + +ss.input.port3.jpkeyboard.5 keyboard 0x0 34 + +ss.input.port3.jpkeyboard.6 keyboard 0x0 35 + +ss.input.port3.jpkeyboard.7 keyboard 0x0 36 + +ss.input.port3.jpkeyboard.8 keyboard 0x0 37 + +ss.input.port3.jpkeyboard.9 keyboard 0x0 38 + +ss.input.port3.jpkeyboard.a keyboard 0x0 4 + +ss.input.port3.jpkeyboard.at keyboard 0x0 47 + +ss.input.port3.jpkeyboard.b keyboard 0x0 5 + +ss.input.port3.jpkeyboard.backslash keyboard 0x0 135 + +ss.input.port3.jpkeyboard.backspace keyboard 0x0 42 + +ss.input.port3.jpkeyboard.c keyboard 0x0 6 + +ss.input.port3.jpkeyboard.capslock keyboard 0x0 57 + +ss.input.port3.jpkeyboard.circumflex keyboard 0x0 46 + +ss.input.port3.jpkeyboard.colon keyboard 0x0 52 + +ss.input.port3.jpkeyboard.comma keyboard 0x0 54 + +ss.input.port3.jpkeyboard.conv keyboard 0x0 138 + +ss.input.port3.jpkeyboard.d keyboard 0x0 7 + +ss.input.port3.jpkeyboard.delete keyboard 0x0 76 + +ss.input.port3.jpkeyboard.down keyboard 0x0 81 + +ss.input.port3.jpkeyboard.e keyboard 0x0 8 + +ss.input.port3.jpkeyboard.end keyboard 0x0 77 + +ss.input.port3.jpkeyboard.enter keyboard 0x0 40 + +ss.input.port3.jpkeyboard.esc keyboard 0x0 41 + +ss.input.port3.jpkeyboard.f keyboard 0x0 9 + +ss.input.port3.jpkeyboard.f1 keyboard 0x0 58 + +ss.input.port3.jpkeyboard.f10 keyboard 0x0 67 + +ss.input.port3.jpkeyboard.f11 keyboard 0x0 68 + +ss.input.port3.jpkeyboard.f12 keyboard 0x0 69 + +ss.input.port3.jpkeyboard.f2 keyboard 0x0 59 + +ss.input.port3.jpkeyboard.f3 keyboard 0x0 60 + +ss.input.port3.jpkeyboard.f4 keyboard 0x0 61 + +ss.input.port3.jpkeyboard.f5 keyboard 0x0 62 + +ss.input.port3.jpkeyboard.f6 keyboard 0x0 63 + +ss.input.port3.jpkeyboard.f7 keyboard 0x0 64 + +ss.input.port3.jpkeyboard.f8 keyboard 0x0 65 + +ss.input.port3.jpkeyboard.f9 keyboard 0x0 66 + +ss.input.port3.jpkeyboard.g keyboard 0x0 10 + +ss.input.port3.jpkeyboard.h keyboard 0x0 11 + +ss.input.port3.jpkeyboard.hkr keyboard 0x0 136 + +ss.input.port3.jpkeyboard.home keyboard 0x0 74 + +ss.input.port3.jpkeyboard.hwfw keyboard 0x0 53 + +ss.input.port3.jpkeyboard.i keyboard 0x0 12 + +ss.input.port3.jpkeyboard.insert keyboard 0x0 73 + +ss.input.port3.jpkeyboard.j keyboard 0x0 13 + +ss.input.port3.jpkeyboard.k keyboard 0x0 14 + +ss.input.port3.jpkeyboard.l keyboard 0x0 15 + +ss.input.port3.jpkeyboard.lalt keyboard 0x0 226 + +ss.input.port3.jpkeyboard.lctrl keyboard 0x0 224 + +ss.input.port3.jpkeyboard.left keyboard 0x0 80 + +ss.input.port3.jpkeyboard.leftbracket keyboard 0x0 48 + +ss.input.port3.jpkeyboard.lshift keyboard 0x0 225 + +ss.input.port3.jpkeyboard.m keyboard 0x0 16 + +ss.input.port3.jpkeyboard.minus keyboard 0x0 45 + +ss.input.port3.jpkeyboard.n keyboard 0x0 17 + +ss.input.port3.jpkeyboard.nonconv keyboard 0x0 139 + +ss.input.port3.jpkeyboard.o keyboard 0x0 18 + +ss.input.port3.jpkeyboard.p keyboard 0x0 19 + +ss.input.port3.jpkeyboard.pagedown keyboard 0x0 78 + +ss.input.port3.jpkeyboard.pageup keyboard 0x0 75 + +ss.input.port3.jpkeyboard.pause keyboard 0x0 72 || keyboard 0x0 83 + +ss.input.port3.jpkeyboard.period keyboard 0x0 55 + +ss.input.port3.jpkeyboard.printscreen keyboard 0x0 70 + +ss.input.port3.jpkeyboard.q keyboard 0x0 20 + +ss.input.port3.jpkeyboard.r keyboard 0x0 21 + +ss.input.port3.jpkeyboard.ralt keyboard 0x0 230 + +ss.input.port3.jpkeyboard.rctrl keyboard 0x0 228 + +ss.input.port3.jpkeyboard.right keyboard 0x0 79 + +ss.input.port3.jpkeyboard.rightbracket keyboard 0x0 49 + +ss.input.port3.jpkeyboard.rshift keyboard 0x0 229 + +ss.input.port3.jpkeyboard.s keyboard 0x0 22 + +ss.input.port3.jpkeyboard.scrolllock keyboard 0x0 71 + +ss.input.port3.jpkeyboard.semicolon keyboard 0x0 51 + +ss.input.port3.jpkeyboard.slash keyboard 0x0 56 + +ss.input.port3.jpkeyboard.space keyboard 0x0 44 + +ss.input.port3.jpkeyboard.t keyboard 0x0 23 + +ss.input.port3.jpkeyboard.tab keyboard 0x0 43 + +ss.input.port3.jpkeyboard.u keyboard 0x0 24 + +ss.input.port3.jpkeyboard.up keyboard 0x0 82 + +ss.input.port3.jpkeyboard.v keyboard 0x0 25 + +ss.input.port3.jpkeyboard.w keyboard 0x0 26 + +ss.input.port3.jpkeyboard.x keyboard 0x0 27 + +ss.input.port3.jpkeyboard.y keyboard 0x0 28 + +ss.input.port3.jpkeyboard.yen keyboard 0x0 137 + +ss.input.port3.jpkeyboard.z keyboard 0x0 29 + +ss.input.port3.keyboard.0 keyboard 0x0 39 + +ss.input.port3.keyboard.1 keyboard 0x0 30 + +ss.input.port3.keyboard.2 keyboard 0x0 31 + +ss.input.port3.keyboard.3 keyboard 0x0 32 + +ss.input.port3.keyboard.4 keyboard 0x0 33 + +ss.input.port3.keyboard.5 keyboard 0x0 34 + +ss.input.port3.keyboard.6 keyboard 0x0 35 + +ss.input.port3.keyboard.7 keyboard 0x0 36 + +ss.input.port3.keyboard.8 keyboard 0x0 37 + +ss.input.port3.keyboard.9 keyboard 0x0 38 + +ss.input.port3.keyboard.a keyboard 0x0 4 + +ss.input.port3.keyboard.b keyboard 0x0 5 + +ss.input.port3.keyboard.backslash keyboard 0x0 49 || keyboard 0x0 135 + +ss.input.port3.keyboard.backspace keyboard 0x0 42 + +ss.input.port3.keyboard.c keyboard 0x0 6 + +ss.input.port3.keyboard.capslock keyboard 0x0 57 + +ss.input.port3.keyboard.comma keyboard 0x0 54 + +ss.input.port3.keyboard.d keyboard 0x0 7 + +ss.input.port3.keyboard.delete keyboard 0x0 76 + +ss.input.port3.keyboard.down keyboard 0x0 81 + +ss.input.port3.keyboard.e keyboard 0x0 8 + +ss.input.port3.keyboard.end keyboard 0x0 77 + +ss.input.port3.keyboard.enter keyboard 0x0 40 + +ss.input.port3.keyboard.equals keyboard 0x0 46 + +ss.input.port3.keyboard.esc keyboard 0x0 41 + +ss.input.port3.keyboard.f keyboard 0x0 9 + +ss.input.port3.keyboard.f1 keyboard 0x0 58 + +ss.input.port3.keyboard.f10 keyboard 0x0 67 + +ss.input.port3.keyboard.f11 keyboard 0x0 68 + +ss.input.port3.keyboard.f12 keyboard 0x0 69 + +ss.input.port3.keyboard.f2 keyboard 0x0 59 + +ss.input.port3.keyboard.f3 keyboard 0x0 60 + +ss.input.port3.keyboard.f4 keyboard 0x0 61 + +ss.input.port3.keyboard.f5 keyboard 0x0 62 + +ss.input.port3.keyboard.f6 keyboard 0x0 63 + +ss.input.port3.keyboard.f7 keyboard 0x0 64 + +ss.input.port3.keyboard.f8 keyboard 0x0 65 + +ss.input.port3.keyboard.f9 keyboard 0x0 66 + +ss.input.port3.keyboard.g keyboard 0x0 10 + +ss.input.port3.keyboard.grave keyboard 0x0 53 + +ss.input.port3.keyboard.h keyboard 0x0 11 + +ss.input.port3.keyboard.home keyboard 0x0 74 + +ss.input.port3.keyboard.i keyboard 0x0 12 + +ss.input.port3.keyboard.insert keyboard 0x0 73 + +ss.input.port3.keyboard.j keyboard 0x0 13 + +ss.input.port3.keyboard.k keyboard 0x0 14 + +ss.input.port3.keyboard.kp_asterisk keyboard 0x0 85 + +ss.input.port3.keyboard.kp_center keyboard 0x0 93 + +ss.input.port3.keyboard.kp_delete keyboard 0x0 99 + +ss.input.port3.keyboard.kp_down keyboard 0x0 90 + +ss.input.port3.keyboard.kp_end keyboard 0x0 89 + +ss.input.port3.keyboard.kp_enter keyboard 0x0 88 + +ss.input.port3.keyboard.kp_home keyboard 0x0 95 + +ss.input.port3.keyboard.kp_insert keyboard 0x0 98 + +ss.input.port3.keyboard.kp_left keyboard 0x0 92 + +ss.input.port3.keyboard.kp_minus keyboard 0x0 86 + +ss.input.port3.keyboard.kp_pagedown keyboard 0x0 91 + +ss.input.port3.keyboard.kp_pageup keyboard 0x0 97 + +ss.input.port3.keyboard.kp_plus keyboard 0x0 87 + +ss.input.port3.keyboard.kp_right keyboard 0x0 94 + +ss.input.port3.keyboard.kp_slash keyboard 0x0 84 + +ss.input.port3.keyboard.kp_up keyboard 0x0 96 + +ss.input.port3.keyboard.l keyboard 0x0 15 + +ss.input.port3.keyboard.lalt keyboard 0x0 226 + +ss.input.port3.keyboard.lctrl keyboard 0x0 224 + +ss.input.port3.keyboard.left keyboard 0x0 80 + +ss.input.port3.keyboard.leftbracket keyboard 0x0 47 + +ss.input.port3.keyboard.lshift keyboard 0x0 225 + +ss.input.port3.keyboard.m keyboard 0x0 16 + +ss.input.port3.keyboard.minus keyboard 0x0 45 + +ss.input.port3.keyboard.n keyboard 0x0 17 + +ss.input.port3.keyboard.numlock keyboard 0x0 83 + +ss.input.port3.keyboard.o keyboard 0x0 18 + +ss.input.port3.keyboard.p keyboard 0x0 19 + +ss.input.port3.keyboard.pagedown keyboard 0x0 78 + +ss.input.port3.keyboard.pageup keyboard 0x0 75 + +ss.input.port3.keyboard.pause keyboard 0x0 72 + +ss.input.port3.keyboard.period keyboard 0x0 55 + +ss.input.port3.keyboard.printscreen keyboard 0x0 70 + +ss.input.port3.keyboard.q keyboard 0x0 20 + +ss.input.port3.keyboard.quote keyboard 0x0 52 + +ss.input.port3.keyboard.r keyboard 0x0 21 + +ss.input.port3.keyboard.ralt keyboard 0x0 230 + +ss.input.port3.keyboard.rctrl keyboard 0x0 228 + +ss.input.port3.keyboard.right keyboard 0x0 79 + +ss.input.port3.keyboard.rightbracket keyboard 0x0 48 + +ss.input.port3.keyboard.rshift keyboard 0x0 229 + +ss.input.port3.keyboard.s keyboard 0x0 22 + +ss.input.port3.keyboard.scrolllock keyboard 0x0 71 + +ss.input.port3.keyboard.semicolon keyboard 0x0 51 + +ss.input.port3.keyboard.slash keyboard 0x0 56 + +ss.input.port3.keyboard.space keyboard 0x0 44 + +ss.input.port3.keyboard.t keyboard 0x0 23 + +ss.input.port3.keyboard.tab keyboard 0x0 43 + +ss.input.port3.keyboard.u keyboard 0x0 24 + +ss.input.port3.keyboard.up keyboard 0x0 82 + +ss.input.port3.keyboard.v keyboard 0x0 25 + +ss.input.port3.keyboard.w keyboard 0x0 26 + +ss.input.port3.keyboard.x keyboard 0x0 27 + +ss.input.port3.keyboard.y keyboard 0x0 28 + +ss.input.port3.keyboard.z keyboard 0x0 29 + +ss.input.port3.mission.a + +ss.input.port3.mission.afa + +ss.input.port3.mission.afa.defpos off + +ss.input.port3.mission.afb + +ss.input.port3.mission.afb.defpos off + +ss.input.port3.mission.afc + +ss.input.port3.mission.afc.defpos off + +ss.input.port3.mission.afl + +ss.input.port3.mission.afl.defpos off + +ss.input.port3.mission.afr + +ss.input.port3.mission.afr.defpos off + +ss.input.port3.mission.afspeed + +ss.input.port3.mission.afspeed.defpos 1 + +ss.input.port3.mission.afx + +ss.input.port3.mission.afx.defpos off + +ss.input.port3.mission.afy + +ss.input.port3.mission.afy.defpos off + +ss.input.port3.mission.afz + +ss.input.port3.mission.afz.defpos off + +ss.input.port3.mission.b + +ss.input.port3.mission.c + +ss.input.port3.mission.l + +ss.input.port3.mission.r + +ss.input.port3.mission.start + +ss.input.port3.mission.stick_back + +ss.input.port3.mission.stick_fore + +ss.input.port3.mission.stick_left + +ss.input.port3.mission.stick_right + +ss.input.port3.mission.throttle_down + +ss.input.port3.mission.throttle_up + +ss.input.port3.mission.x + +ss.input.port3.mission.y + +ss.input.port3.mission.z + +ss.input.port3.mouse.left mouse 0x0 button_left + +ss.input.port3.mouse.middle mouse 0x0 button_middle + +ss.input.port3.mouse.motion_down mouse 0x0 rel_y+ + +ss.input.port3.mouse.motion_left mouse 0x0 rel_x- + +ss.input.port3.mouse.motion_right mouse 0x0 rel_x+ + +ss.input.port3.mouse.motion_up mouse 0x0 rel_y- + +ss.input.port3.mouse.right mouse 0x0 button_right + +ss.input.port3.mouse.start keyboard 0x0 40 + +ss.input.port3.wheel.a + +ss.input.port3.wheel.analog_left + +ss.input.port3.wheel.analog_right + +ss.input.port3.wheel.b + +ss.input.port3.wheel.c + +ss.input.port3.wheel.down + +ss.input.port3.wheel.start + +ss.input.port3.wheel.up + +ss.input.port3.wheel.x + +ss.input.port3.wheel.y + +ss.input.port3.wheel.z + +ss.input.port4 gamepad + +ss.input.port4.3dpad.a + +ss.input.port4.3dpad.analog_down + +ss.input.port4.3dpad.analog_left + +ss.input.port4.3dpad.analog_right + +ss.input.port4.3dpad.analog_up + +ss.input.port4.3dpad.b + +ss.input.port4.3dpad.c + +ss.input.port4.3dpad.down + +ss.input.port4.3dpad.left + +ss.input.port4.3dpad.ls + +ss.input.port4.3dpad.mode + +ss.input.port4.3dpad.mode.defpos digital + +ss.input.port4.3dpad.right + +ss.input.port4.3dpad.rs + +ss.input.port4.3dpad.start + +ss.input.port4.3dpad.up + +ss.input.port4.3dpad.x + +ss.input.port4.3dpad.y + +ss.input.port4.3dpad.z + +ss.input.port4.dmission.a + +ss.input.port4.dmission.afa + +ss.input.port4.dmission.afa.defpos off + +ss.input.port4.dmission.afb + +ss.input.port4.dmission.afb.defpos off + +ss.input.port4.dmission.afc + +ss.input.port4.dmission.afc.defpos off + +ss.input.port4.dmission.afl + +ss.input.port4.dmission.afl.defpos off + +ss.input.port4.dmission.afr + +ss.input.port4.dmission.afr.defpos off + +ss.input.port4.dmission.afspeed + +ss.input.port4.dmission.afspeed.defpos 1 + +ss.input.port4.dmission.afx + +ss.input.port4.dmission.afx.defpos off + +ss.input.port4.dmission.afy + +ss.input.port4.dmission.afy.defpos off + +ss.input.port4.dmission.afz + +ss.input.port4.dmission.afz.defpos off + +ss.input.port4.dmission.b + +ss.input.port4.dmission.c + +ss.input.port4.dmission.l + +ss.input.port4.dmission.lstick_back + +ss.input.port4.dmission.lstick_fore + +ss.input.port4.dmission.lstick_left + +ss.input.port4.dmission.lstick_right + +ss.input.port4.dmission.lthrottle_down + +ss.input.port4.dmission.lthrottle_up + +ss.input.port4.dmission.r + +ss.input.port4.dmission.rstick_back + +ss.input.port4.dmission.rstick_fore + +ss.input.port4.dmission.rstick_left + +ss.input.port4.dmission.rstick_right + +ss.input.port4.dmission.rthrottle_down + +ss.input.port4.dmission.rthrottle_up + +ss.input.port4.dmission.start + +ss.input.port4.dmission.x + +ss.input.port4.dmission.y + +ss.input.port4.dmission.z + +ss.input.port4.gamepad.a + +ss.input.port4.gamepad.b + +ss.input.port4.gamepad.c + +ss.input.port4.gamepad.down + +ss.input.port4.gamepad.left + +ss.input.port4.gamepad.ls + +ss.input.port4.gamepad.right + +ss.input.port4.gamepad.rs + +ss.input.port4.gamepad.start + +ss.input.port4.gamepad.up + +ss.input.port4.gamepad.x + +ss.input.port4.gamepad.y + +ss.input.port4.gamepad.z + +ss.input.port4.gun.offscreen_shot mouse 0x0 button_right + +ss.input.port4.gun.start mouse 0x0 button_middle + +ss.input.port4.gun.trigger mouse 0x0 button_left + +ss.input.port4.gun.x_axis mouse 0x0 cursor_x-+ + +ss.input.port4.gun.y_axis mouse 0x0 cursor_y-+ + +ss.input.port4.gun_chairs 0xFF8000 + +ss.input.port4.jpkeyboard.0 keyboard 0x0 39 + +ss.input.port4.jpkeyboard.1 keyboard 0x0 30 + +ss.input.port4.jpkeyboard.2 keyboard 0x0 31 + +ss.input.port4.jpkeyboard.3 keyboard 0x0 32 + +ss.input.port4.jpkeyboard.4 keyboard 0x0 33 + +ss.input.port4.jpkeyboard.5 keyboard 0x0 34 + +ss.input.port4.jpkeyboard.6 keyboard 0x0 35 + +ss.input.port4.jpkeyboard.7 keyboard 0x0 36 + +ss.input.port4.jpkeyboard.8 keyboard 0x0 37 + +ss.input.port4.jpkeyboard.9 keyboard 0x0 38 + +ss.input.port4.jpkeyboard.a keyboard 0x0 4 + +ss.input.port4.jpkeyboard.at keyboard 0x0 47 + +ss.input.port4.jpkeyboard.b keyboard 0x0 5 + +ss.input.port4.jpkeyboard.backslash keyboard 0x0 135 + +ss.input.port4.jpkeyboard.backspace keyboard 0x0 42 + +ss.input.port4.jpkeyboard.c keyboard 0x0 6 + +ss.input.port4.jpkeyboard.capslock keyboard 0x0 57 + +ss.input.port4.jpkeyboard.circumflex keyboard 0x0 46 + +ss.input.port4.jpkeyboard.colon keyboard 0x0 52 + +ss.input.port4.jpkeyboard.comma keyboard 0x0 54 + +ss.input.port4.jpkeyboard.conv keyboard 0x0 138 + +ss.input.port4.jpkeyboard.d keyboard 0x0 7 + +ss.input.port4.jpkeyboard.delete keyboard 0x0 76 + +ss.input.port4.jpkeyboard.down keyboard 0x0 81 + +ss.input.port4.jpkeyboard.e keyboard 0x0 8 + +ss.input.port4.jpkeyboard.end keyboard 0x0 77 + +ss.input.port4.jpkeyboard.enter keyboard 0x0 40 + +ss.input.port4.jpkeyboard.esc keyboard 0x0 41 + +ss.input.port4.jpkeyboard.f keyboard 0x0 9 + +ss.input.port4.jpkeyboard.f1 keyboard 0x0 58 + +ss.input.port4.jpkeyboard.f10 keyboard 0x0 67 + +ss.input.port4.jpkeyboard.f11 keyboard 0x0 68 + +ss.input.port4.jpkeyboard.f12 keyboard 0x0 69 + +ss.input.port4.jpkeyboard.f2 keyboard 0x0 59 + +ss.input.port4.jpkeyboard.f3 keyboard 0x0 60 + +ss.input.port4.jpkeyboard.f4 keyboard 0x0 61 + +ss.input.port4.jpkeyboard.f5 keyboard 0x0 62 + +ss.input.port4.jpkeyboard.f6 keyboard 0x0 63 + +ss.input.port4.jpkeyboard.f7 keyboard 0x0 64 + +ss.input.port4.jpkeyboard.f8 keyboard 0x0 65 + +ss.input.port4.jpkeyboard.f9 keyboard 0x0 66 + +ss.input.port4.jpkeyboard.g keyboard 0x0 10 + +ss.input.port4.jpkeyboard.h keyboard 0x0 11 + +ss.input.port4.jpkeyboard.hkr keyboard 0x0 136 + +ss.input.port4.jpkeyboard.home keyboard 0x0 74 + +ss.input.port4.jpkeyboard.hwfw keyboard 0x0 53 + +ss.input.port4.jpkeyboard.i keyboard 0x0 12 + +ss.input.port4.jpkeyboard.insert keyboard 0x0 73 + +ss.input.port4.jpkeyboard.j keyboard 0x0 13 + +ss.input.port4.jpkeyboard.k keyboard 0x0 14 + +ss.input.port4.jpkeyboard.l keyboard 0x0 15 + +ss.input.port4.jpkeyboard.lalt keyboard 0x0 226 + +ss.input.port4.jpkeyboard.lctrl keyboard 0x0 224 + +ss.input.port4.jpkeyboard.left keyboard 0x0 80 + +ss.input.port4.jpkeyboard.leftbracket keyboard 0x0 48 + +ss.input.port4.jpkeyboard.lshift keyboard 0x0 225 + +ss.input.port4.jpkeyboard.m keyboard 0x0 16 + +ss.input.port4.jpkeyboard.minus keyboard 0x0 45 + +ss.input.port4.jpkeyboard.n keyboard 0x0 17 + +ss.input.port4.jpkeyboard.nonconv keyboard 0x0 139 + +ss.input.port4.jpkeyboard.o keyboard 0x0 18 + +ss.input.port4.jpkeyboard.p keyboard 0x0 19 + +ss.input.port4.jpkeyboard.pagedown keyboard 0x0 78 + +ss.input.port4.jpkeyboard.pageup keyboard 0x0 75 + +ss.input.port4.jpkeyboard.pause keyboard 0x0 72 || keyboard 0x0 83 + +ss.input.port4.jpkeyboard.period keyboard 0x0 55 + +ss.input.port4.jpkeyboard.printscreen keyboard 0x0 70 + +ss.input.port4.jpkeyboard.q keyboard 0x0 20 + +ss.input.port4.jpkeyboard.r keyboard 0x0 21 + +ss.input.port4.jpkeyboard.ralt keyboard 0x0 230 + +ss.input.port4.jpkeyboard.rctrl keyboard 0x0 228 + +ss.input.port4.jpkeyboard.right keyboard 0x0 79 + +ss.input.port4.jpkeyboard.rightbracket keyboard 0x0 49 + +ss.input.port4.jpkeyboard.rshift keyboard 0x0 229 + +ss.input.port4.jpkeyboard.s keyboard 0x0 22 + +ss.input.port4.jpkeyboard.scrolllock keyboard 0x0 71 + +ss.input.port4.jpkeyboard.semicolon keyboard 0x0 51 + +ss.input.port4.jpkeyboard.slash keyboard 0x0 56 + +ss.input.port4.jpkeyboard.space keyboard 0x0 44 + +ss.input.port4.jpkeyboard.t keyboard 0x0 23 + +ss.input.port4.jpkeyboard.tab keyboard 0x0 43 + +ss.input.port4.jpkeyboard.u keyboard 0x0 24 + +ss.input.port4.jpkeyboard.up keyboard 0x0 82 + +ss.input.port4.jpkeyboard.v keyboard 0x0 25 + +ss.input.port4.jpkeyboard.w keyboard 0x0 26 + +ss.input.port4.jpkeyboard.x keyboard 0x0 27 + +ss.input.port4.jpkeyboard.y keyboard 0x0 28 + +ss.input.port4.jpkeyboard.yen keyboard 0x0 137 + +ss.input.port4.jpkeyboard.z keyboard 0x0 29 + +ss.input.port4.keyboard.0 keyboard 0x0 39 + +ss.input.port4.keyboard.1 keyboard 0x0 30 + +ss.input.port4.keyboard.2 keyboard 0x0 31 + +ss.input.port4.keyboard.3 keyboard 0x0 32 + +ss.input.port4.keyboard.4 keyboard 0x0 33 + +ss.input.port4.keyboard.5 keyboard 0x0 34 + +ss.input.port4.keyboard.6 keyboard 0x0 35 + +ss.input.port4.keyboard.7 keyboard 0x0 36 + +ss.input.port4.keyboard.8 keyboard 0x0 37 + +ss.input.port4.keyboard.9 keyboard 0x0 38 + +ss.input.port4.keyboard.a keyboard 0x0 4 + +ss.input.port4.keyboard.b keyboard 0x0 5 + +ss.input.port4.keyboard.backslash keyboard 0x0 49 || keyboard 0x0 135 + +ss.input.port4.keyboard.backspace keyboard 0x0 42 + +ss.input.port4.keyboard.c keyboard 0x0 6 + +ss.input.port4.keyboard.capslock keyboard 0x0 57 + +ss.input.port4.keyboard.comma keyboard 0x0 54 + +ss.input.port4.keyboard.d keyboard 0x0 7 + +ss.input.port4.keyboard.delete keyboard 0x0 76 + +ss.input.port4.keyboard.down keyboard 0x0 81 + +ss.input.port4.keyboard.e keyboard 0x0 8 + +ss.input.port4.keyboard.end keyboard 0x0 77 + +ss.input.port4.keyboard.enter keyboard 0x0 40 + +ss.input.port4.keyboard.equals keyboard 0x0 46 + +ss.input.port4.keyboard.esc keyboard 0x0 41 + +ss.input.port4.keyboard.f keyboard 0x0 9 + +ss.input.port4.keyboard.f1 keyboard 0x0 58 + +ss.input.port4.keyboard.f10 keyboard 0x0 67 + +ss.input.port4.keyboard.f11 keyboard 0x0 68 + +ss.input.port4.keyboard.f12 keyboard 0x0 69 + +ss.input.port4.keyboard.f2 keyboard 0x0 59 + +ss.input.port4.keyboard.f3 keyboard 0x0 60 + +ss.input.port4.keyboard.f4 keyboard 0x0 61 + +ss.input.port4.keyboard.f5 keyboard 0x0 62 + +ss.input.port4.keyboard.f6 keyboard 0x0 63 + +ss.input.port4.keyboard.f7 keyboard 0x0 64 + +ss.input.port4.keyboard.f8 keyboard 0x0 65 + +ss.input.port4.keyboard.f9 keyboard 0x0 66 + +ss.input.port4.keyboard.g keyboard 0x0 10 + +ss.input.port4.keyboard.grave keyboard 0x0 53 + +ss.input.port4.keyboard.h keyboard 0x0 11 + +ss.input.port4.keyboard.home keyboard 0x0 74 + +ss.input.port4.keyboard.i keyboard 0x0 12 + +ss.input.port4.keyboard.insert keyboard 0x0 73 + +ss.input.port4.keyboard.j keyboard 0x0 13 + +ss.input.port4.keyboard.k keyboard 0x0 14 + +ss.input.port4.keyboard.kp_asterisk keyboard 0x0 85 + +ss.input.port4.keyboard.kp_center keyboard 0x0 93 + +ss.input.port4.keyboard.kp_delete keyboard 0x0 99 + +ss.input.port4.keyboard.kp_down keyboard 0x0 90 + +ss.input.port4.keyboard.kp_end keyboard 0x0 89 + +ss.input.port4.keyboard.kp_enter keyboard 0x0 88 + +ss.input.port4.keyboard.kp_home keyboard 0x0 95 + +ss.input.port4.keyboard.kp_insert keyboard 0x0 98 + +ss.input.port4.keyboard.kp_left keyboard 0x0 92 + +ss.input.port4.keyboard.kp_minus keyboard 0x0 86 + +ss.input.port4.keyboard.kp_pagedown keyboard 0x0 91 + +ss.input.port4.keyboard.kp_pageup keyboard 0x0 97 + +ss.input.port4.keyboard.kp_plus keyboard 0x0 87 + +ss.input.port4.keyboard.kp_right keyboard 0x0 94 + +ss.input.port4.keyboard.kp_slash keyboard 0x0 84 + +ss.input.port4.keyboard.kp_up keyboard 0x0 96 + +ss.input.port4.keyboard.l keyboard 0x0 15 + +ss.input.port4.keyboard.lalt keyboard 0x0 226 + +ss.input.port4.keyboard.lctrl keyboard 0x0 224 + +ss.input.port4.keyboard.left keyboard 0x0 80 + +ss.input.port4.keyboard.leftbracket keyboard 0x0 47 + +ss.input.port4.keyboard.lshift keyboard 0x0 225 + +ss.input.port4.keyboard.m keyboard 0x0 16 + +ss.input.port4.keyboard.minus keyboard 0x0 45 + +ss.input.port4.keyboard.n keyboard 0x0 17 + +ss.input.port4.keyboard.numlock keyboard 0x0 83 + +ss.input.port4.keyboard.o keyboard 0x0 18 + +ss.input.port4.keyboard.p keyboard 0x0 19 + +ss.input.port4.keyboard.pagedown keyboard 0x0 78 + +ss.input.port4.keyboard.pageup keyboard 0x0 75 + +ss.input.port4.keyboard.pause keyboard 0x0 72 + +ss.input.port4.keyboard.period keyboard 0x0 55 + +ss.input.port4.keyboard.printscreen keyboard 0x0 70 + +ss.input.port4.keyboard.q keyboard 0x0 20 + +ss.input.port4.keyboard.quote keyboard 0x0 52 + +ss.input.port4.keyboard.r keyboard 0x0 21 + +ss.input.port4.keyboard.ralt keyboard 0x0 230 + +ss.input.port4.keyboard.rctrl keyboard 0x0 228 + +ss.input.port4.keyboard.right keyboard 0x0 79 + +ss.input.port4.keyboard.rightbracket keyboard 0x0 48 + +ss.input.port4.keyboard.rshift keyboard 0x0 229 + +ss.input.port4.keyboard.s keyboard 0x0 22 + +ss.input.port4.keyboard.scrolllock keyboard 0x0 71 + +ss.input.port4.keyboard.semicolon keyboard 0x0 51 + +ss.input.port4.keyboard.slash keyboard 0x0 56 + +ss.input.port4.keyboard.space keyboard 0x0 44 + +ss.input.port4.keyboard.t keyboard 0x0 23 + +ss.input.port4.keyboard.tab keyboard 0x0 43 + +ss.input.port4.keyboard.u keyboard 0x0 24 + +ss.input.port4.keyboard.up keyboard 0x0 82 + +ss.input.port4.keyboard.v keyboard 0x0 25 + +ss.input.port4.keyboard.w keyboard 0x0 26 + +ss.input.port4.keyboard.x keyboard 0x0 27 + +ss.input.port4.keyboard.y keyboard 0x0 28 + +ss.input.port4.keyboard.z keyboard 0x0 29 + +ss.input.port4.mission.a + +ss.input.port4.mission.afa + +ss.input.port4.mission.afa.defpos off + +ss.input.port4.mission.afb + +ss.input.port4.mission.afb.defpos off + +ss.input.port4.mission.afc + +ss.input.port4.mission.afc.defpos off + +ss.input.port4.mission.afl + +ss.input.port4.mission.afl.defpos off + +ss.input.port4.mission.afr + +ss.input.port4.mission.afr.defpos off + +ss.input.port4.mission.afspeed + +ss.input.port4.mission.afspeed.defpos 1 + +ss.input.port4.mission.afx + +ss.input.port4.mission.afx.defpos off + +ss.input.port4.mission.afy + +ss.input.port4.mission.afy.defpos off + +ss.input.port4.mission.afz + +ss.input.port4.mission.afz.defpos off + +ss.input.port4.mission.b + +ss.input.port4.mission.c + +ss.input.port4.mission.l + +ss.input.port4.mission.r + +ss.input.port4.mission.start + +ss.input.port4.mission.stick_back + +ss.input.port4.mission.stick_fore + +ss.input.port4.mission.stick_left + +ss.input.port4.mission.stick_right + +ss.input.port4.mission.throttle_down + +ss.input.port4.mission.throttle_up + +ss.input.port4.mission.x + +ss.input.port4.mission.y + +ss.input.port4.mission.z + +ss.input.port4.mouse.left mouse 0x0 button_left + +ss.input.port4.mouse.middle mouse 0x0 button_middle + +ss.input.port4.mouse.motion_down mouse 0x0 rel_y+ + +ss.input.port4.mouse.motion_left mouse 0x0 rel_x- + +ss.input.port4.mouse.motion_right mouse 0x0 rel_x+ + +ss.input.port4.mouse.motion_up mouse 0x0 rel_y- + +ss.input.port4.mouse.right mouse 0x0 button_right + +ss.input.port4.mouse.start keyboard 0x0 40 + +ss.input.port4.wheel.a + +ss.input.port4.wheel.analog_left + +ss.input.port4.wheel.analog_right + +ss.input.port4.wheel.b + +ss.input.port4.wheel.c + +ss.input.port4.wheel.down + +ss.input.port4.wheel.start + +ss.input.port4.wheel.up + +ss.input.port4.wheel.x + +ss.input.port4.wheel.y + +ss.input.port4.wheel.z + +ss.input.port5 gamepad + +ss.input.port5.3dpad.a + +ss.input.port5.3dpad.analog_down + +ss.input.port5.3dpad.analog_left + +ss.input.port5.3dpad.analog_right + +ss.input.port5.3dpad.analog_up + +ss.input.port5.3dpad.b + +ss.input.port5.3dpad.c + +ss.input.port5.3dpad.down + +ss.input.port5.3dpad.left + +ss.input.port5.3dpad.ls + +ss.input.port5.3dpad.mode + +ss.input.port5.3dpad.mode.defpos digital + +ss.input.port5.3dpad.right + +ss.input.port5.3dpad.rs + +ss.input.port5.3dpad.start + +ss.input.port5.3dpad.up + +ss.input.port5.3dpad.x + +ss.input.port5.3dpad.y + +ss.input.port5.3dpad.z + +ss.input.port5.dmission.a + +ss.input.port5.dmission.afa + +ss.input.port5.dmission.afa.defpos off + +ss.input.port5.dmission.afb + +ss.input.port5.dmission.afb.defpos off + +ss.input.port5.dmission.afc + +ss.input.port5.dmission.afc.defpos off + +ss.input.port5.dmission.afl + +ss.input.port5.dmission.afl.defpos off + +ss.input.port5.dmission.afr + +ss.input.port5.dmission.afr.defpos off + +ss.input.port5.dmission.afspeed + +ss.input.port5.dmission.afspeed.defpos 1 + +ss.input.port5.dmission.afx + +ss.input.port5.dmission.afx.defpos off + +ss.input.port5.dmission.afy + +ss.input.port5.dmission.afy.defpos off + +ss.input.port5.dmission.afz + +ss.input.port5.dmission.afz.defpos off + +ss.input.port5.dmission.b + +ss.input.port5.dmission.c + +ss.input.port5.dmission.l + +ss.input.port5.dmission.lstick_back + +ss.input.port5.dmission.lstick_fore + +ss.input.port5.dmission.lstick_left + +ss.input.port5.dmission.lstick_right + +ss.input.port5.dmission.lthrottle_down + +ss.input.port5.dmission.lthrottle_up + +ss.input.port5.dmission.r + +ss.input.port5.dmission.rstick_back + +ss.input.port5.dmission.rstick_fore + +ss.input.port5.dmission.rstick_left + +ss.input.port5.dmission.rstick_right + +ss.input.port5.dmission.rthrottle_down + +ss.input.port5.dmission.rthrottle_up + +ss.input.port5.dmission.start + +ss.input.port5.dmission.x + +ss.input.port5.dmission.y + +ss.input.port5.dmission.z + +ss.input.port5.gamepad.a + +ss.input.port5.gamepad.b + +ss.input.port5.gamepad.c + +ss.input.port5.gamepad.down + +ss.input.port5.gamepad.left + +ss.input.port5.gamepad.ls + +ss.input.port5.gamepad.right + +ss.input.port5.gamepad.rs + +ss.input.port5.gamepad.start + +ss.input.port5.gamepad.up + +ss.input.port5.gamepad.x + +ss.input.port5.gamepad.y + +ss.input.port5.gamepad.z + +ss.input.port5.gun.offscreen_shot mouse 0x0 button_right + +ss.input.port5.gun.start mouse 0x0 button_middle + +ss.input.port5.gun.trigger mouse 0x0 button_left + +ss.input.port5.gun.x_axis mouse 0x0 cursor_x-+ + +ss.input.port5.gun.y_axis mouse 0x0 cursor_y-+ + +ss.input.port5.gun_chairs 0xFFFF00 + +ss.input.port5.jpkeyboard.0 keyboard 0x0 39 + +ss.input.port5.jpkeyboard.1 keyboard 0x0 30 + +ss.input.port5.jpkeyboard.2 keyboard 0x0 31 + +ss.input.port5.jpkeyboard.3 keyboard 0x0 32 + +ss.input.port5.jpkeyboard.4 keyboard 0x0 33 + +ss.input.port5.jpkeyboard.5 keyboard 0x0 34 + +ss.input.port5.jpkeyboard.6 keyboard 0x0 35 + +ss.input.port5.jpkeyboard.7 keyboard 0x0 36 + +ss.input.port5.jpkeyboard.8 keyboard 0x0 37 + +ss.input.port5.jpkeyboard.9 keyboard 0x0 38 + +ss.input.port5.jpkeyboard.a keyboard 0x0 4 + +ss.input.port5.jpkeyboard.at keyboard 0x0 47 + +ss.input.port5.jpkeyboard.b keyboard 0x0 5 + +ss.input.port5.jpkeyboard.backslash keyboard 0x0 135 + +ss.input.port5.jpkeyboard.backspace keyboard 0x0 42 + +ss.input.port5.jpkeyboard.c keyboard 0x0 6 + +ss.input.port5.jpkeyboard.capslock keyboard 0x0 57 + +ss.input.port5.jpkeyboard.circumflex keyboard 0x0 46 + +ss.input.port5.jpkeyboard.colon keyboard 0x0 52 + +ss.input.port5.jpkeyboard.comma keyboard 0x0 54 + +ss.input.port5.jpkeyboard.conv keyboard 0x0 138 + +ss.input.port5.jpkeyboard.d keyboard 0x0 7 + +ss.input.port5.jpkeyboard.delete keyboard 0x0 76 + +ss.input.port5.jpkeyboard.down keyboard 0x0 81 + +ss.input.port5.jpkeyboard.e keyboard 0x0 8 + +ss.input.port5.jpkeyboard.end keyboard 0x0 77 + +ss.input.port5.jpkeyboard.enter keyboard 0x0 40 + +ss.input.port5.jpkeyboard.esc keyboard 0x0 41 + +ss.input.port5.jpkeyboard.f keyboard 0x0 9 + +ss.input.port5.jpkeyboard.f1 keyboard 0x0 58 + +ss.input.port5.jpkeyboard.f10 keyboard 0x0 67 + +ss.input.port5.jpkeyboard.f11 keyboard 0x0 68 + +ss.input.port5.jpkeyboard.f12 keyboard 0x0 69 + +ss.input.port5.jpkeyboard.f2 keyboard 0x0 59 + +ss.input.port5.jpkeyboard.f3 keyboard 0x0 60 + +ss.input.port5.jpkeyboard.f4 keyboard 0x0 61 + +ss.input.port5.jpkeyboard.f5 keyboard 0x0 62 + +ss.input.port5.jpkeyboard.f6 keyboard 0x0 63 + +ss.input.port5.jpkeyboard.f7 keyboard 0x0 64 + +ss.input.port5.jpkeyboard.f8 keyboard 0x0 65 + +ss.input.port5.jpkeyboard.f9 keyboard 0x0 66 + +ss.input.port5.jpkeyboard.g keyboard 0x0 10 + +ss.input.port5.jpkeyboard.h keyboard 0x0 11 + +ss.input.port5.jpkeyboard.hkr keyboard 0x0 136 + +ss.input.port5.jpkeyboard.home keyboard 0x0 74 + +ss.input.port5.jpkeyboard.hwfw keyboard 0x0 53 + +ss.input.port5.jpkeyboard.i keyboard 0x0 12 + +ss.input.port5.jpkeyboard.insert keyboard 0x0 73 + +ss.input.port5.jpkeyboard.j keyboard 0x0 13 + +ss.input.port5.jpkeyboard.k keyboard 0x0 14 + +ss.input.port5.jpkeyboard.l keyboard 0x0 15 + +ss.input.port5.jpkeyboard.lalt keyboard 0x0 226 + +ss.input.port5.jpkeyboard.lctrl keyboard 0x0 224 + +ss.input.port5.jpkeyboard.left keyboard 0x0 80 + +ss.input.port5.jpkeyboard.leftbracket keyboard 0x0 48 + +ss.input.port5.jpkeyboard.lshift keyboard 0x0 225 + +ss.input.port5.jpkeyboard.m keyboard 0x0 16 + +ss.input.port5.jpkeyboard.minus keyboard 0x0 45 + +ss.input.port5.jpkeyboard.n keyboard 0x0 17 + +ss.input.port5.jpkeyboard.nonconv keyboard 0x0 139 + +ss.input.port5.jpkeyboard.o keyboard 0x0 18 + +ss.input.port5.jpkeyboard.p keyboard 0x0 19 + +ss.input.port5.jpkeyboard.pagedown keyboard 0x0 78 + +ss.input.port5.jpkeyboard.pageup keyboard 0x0 75 + +ss.input.port5.jpkeyboard.pause keyboard 0x0 72 || keyboard 0x0 83 + +ss.input.port5.jpkeyboard.period keyboard 0x0 55 + +ss.input.port5.jpkeyboard.printscreen keyboard 0x0 70 + +ss.input.port5.jpkeyboard.q keyboard 0x0 20 + +ss.input.port5.jpkeyboard.r keyboard 0x0 21 + +ss.input.port5.jpkeyboard.ralt keyboard 0x0 230 + +ss.input.port5.jpkeyboard.rctrl keyboard 0x0 228 + +ss.input.port5.jpkeyboard.right keyboard 0x0 79 + +ss.input.port5.jpkeyboard.rightbracket keyboard 0x0 49 + +ss.input.port5.jpkeyboard.rshift keyboard 0x0 229 + +ss.input.port5.jpkeyboard.s keyboard 0x0 22 + +ss.input.port5.jpkeyboard.scrolllock keyboard 0x0 71 + +ss.input.port5.jpkeyboard.semicolon keyboard 0x0 51 + +ss.input.port5.jpkeyboard.slash keyboard 0x0 56 + +ss.input.port5.jpkeyboard.space keyboard 0x0 44 + +ss.input.port5.jpkeyboard.t keyboard 0x0 23 + +ss.input.port5.jpkeyboard.tab keyboard 0x0 43 + +ss.input.port5.jpkeyboard.u keyboard 0x0 24 + +ss.input.port5.jpkeyboard.up keyboard 0x0 82 + +ss.input.port5.jpkeyboard.v keyboard 0x0 25 + +ss.input.port5.jpkeyboard.w keyboard 0x0 26 + +ss.input.port5.jpkeyboard.x keyboard 0x0 27 + +ss.input.port5.jpkeyboard.y keyboard 0x0 28 + +ss.input.port5.jpkeyboard.yen keyboard 0x0 137 + +ss.input.port5.jpkeyboard.z keyboard 0x0 29 + +ss.input.port5.keyboard.0 keyboard 0x0 39 + +ss.input.port5.keyboard.1 keyboard 0x0 30 + +ss.input.port5.keyboard.2 keyboard 0x0 31 + +ss.input.port5.keyboard.3 keyboard 0x0 32 + +ss.input.port5.keyboard.4 keyboard 0x0 33 + +ss.input.port5.keyboard.5 keyboard 0x0 34 + +ss.input.port5.keyboard.6 keyboard 0x0 35 + +ss.input.port5.keyboard.7 keyboard 0x0 36 + +ss.input.port5.keyboard.8 keyboard 0x0 37 + +ss.input.port5.keyboard.9 keyboard 0x0 38 + +ss.input.port5.keyboard.a keyboard 0x0 4 + +ss.input.port5.keyboard.b keyboard 0x0 5 + +ss.input.port5.keyboard.backslash keyboard 0x0 49 || keyboard 0x0 135 + +ss.input.port5.keyboard.backspace keyboard 0x0 42 + +ss.input.port5.keyboard.c keyboard 0x0 6 + +ss.input.port5.keyboard.capslock keyboard 0x0 57 + +ss.input.port5.keyboard.comma keyboard 0x0 54 + +ss.input.port5.keyboard.d keyboard 0x0 7 + +ss.input.port5.keyboard.delete keyboard 0x0 76 + +ss.input.port5.keyboard.down keyboard 0x0 81 + +ss.input.port5.keyboard.e keyboard 0x0 8 + +ss.input.port5.keyboard.end keyboard 0x0 77 + +ss.input.port5.keyboard.enter keyboard 0x0 40 + +ss.input.port5.keyboard.equals keyboard 0x0 46 + +ss.input.port5.keyboard.esc keyboard 0x0 41 + +ss.input.port5.keyboard.f keyboard 0x0 9 + +ss.input.port5.keyboard.f1 keyboard 0x0 58 + +ss.input.port5.keyboard.f10 keyboard 0x0 67 + +ss.input.port5.keyboard.f11 keyboard 0x0 68 + +ss.input.port5.keyboard.f12 keyboard 0x0 69 + +ss.input.port5.keyboard.f2 keyboard 0x0 59 + +ss.input.port5.keyboard.f3 keyboard 0x0 60 + +ss.input.port5.keyboard.f4 keyboard 0x0 61 + +ss.input.port5.keyboard.f5 keyboard 0x0 62 + +ss.input.port5.keyboard.f6 keyboard 0x0 63 + +ss.input.port5.keyboard.f7 keyboard 0x0 64 + +ss.input.port5.keyboard.f8 keyboard 0x0 65 + +ss.input.port5.keyboard.f9 keyboard 0x0 66 + +ss.input.port5.keyboard.g keyboard 0x0 10 + +ss.input.port5.keyboard.grave keyboard 0x0 53 + +ss.input.port5.keyboard.h keyboard 0x0 11 + +ss.input.port5.keyboard.home keyboard 0x0 74 + +ss.input.port5.keyboard.i keyboard 0x0 12 + +ss.input.port5.keyboard.insert keyboard 0x0 73 + +ss.input.port5.keyboard.j keyboard 0x0 13 + +ss.input.port5.keyboard.k keyboard 0x0 14 + +ss.input.port5.keyboard.kp_asterisk keyboard 0x0 85 + +ss.input.port5.keyboard.kp_center keyboard 0x0 93 + +ss.input.port5.keyboard.kp_delete keyboard 0x0 99 + +ss.input.port5.keyboard.kp_down keyboard 0x0 90 + +ss.input.port5.keyboard.kp_end keyboard 0x0 89 + +ss.input.port5.keyboard.kp_enter keyboard 0x0 88 + +ss.input.port5.keyboard.kp_home keyboard 0x0 95 + +ss.input.port5.keyboard.kp_insert keyboard 0x0 98 + +ss.input.port5.keyboard.kp_left keyboard 0x0 92 + +ss.input.port5.keyboard.kp_minus keyboard 0x0 86 + +ss.input.port5.keyboard.kp_pagedown keyboard 0x0 91 + +ss.input.port5.keyboard.kp_pageup keyboard 0x0 97 + +ss.input.port5.keyboard.kp_plus keyboard 0x0 87 + +ss.input.port5.keyboard.kp_right keyboard 0x0 94 + +ss.input.port5.keyboard.kp_slash keyboard 0x0 84 + +ss.input.port5.keyboard.kp_up keyboard 0x0 96 + +ss.input.port5.keyboard.l keyboard 0x0 15 + +ss.input.port5.keyboard.lalt keyboard 0x0 226 + +ss.input.port5.keyboard.lctrl keyboard 0x0 224 + +ss.input.port5.keyboard.left keyboard 0x0 80 + +ss.input.port5.keyboard.leftbracket keyboard 0x0 47 + +ss.input.port5.keyboard.lshift keyboard 0x0 225 + +ss.input.port5.keyboard.m keyboard 0x0 16 + +ss.input.port5.keyboard.minus keyboard 0x0 45 + +ss.input.port5.keyboard.n keyboard 0x0 17 + +ss.input.port5.keyboard.numlock keyboard 0x0 83 + +ss.input.port5.keyboard.o keyboard 0x0 18 + +ss.input.port5.keyboard.p keyboard 0x0 19 + +ss.input.port5.keyboard.pagedown keyboard 0x0 78 + +ss.input.port5.keyboard.pageup keyboard 0x0 75 + +ss.input.port5.keyboard.pause keyboard 0x0 72 + +ss.input.port5.keyboard.period keyboard 0x0 55 + +ss.input.port5.keyboard.printscreen keyboard 0x0 70 + +ss.input.port5.keyboard.q keyboard 0x0 20 + +ss.input.port5.keyboard.quote keyboard 0x0 52 + +ss.input.port5.keyboard.r keyboard 0x0 21 + +ss.input.port5.keyboard.ralt keyboard 0x0 230 + +ss.input.port5.keyboard.rctrl keyboard 0x0 228 + +ss.input.port5.keyboard.right keyboard 0x0 79 + +ss.input.port5.keyboard.rightbracket keyboard 0x0 48 + +ss.input.port5.keyboard.rshift keyboard 0x0 229 + +ss.input.port5.keyboard.s keyboard 0x0 22 + +ss.input.port5.keyboard.scrolllock keyboard 0x0 71 + +ss.input.port5.keyboard.semicolon keyboard 0x0 51 + +ss.input.port5.keyboard.slash keyboard 0x0 56 + +ss.input.port5.keyboard.space keyboard 0x0 44 + +ss.input.port5.keyboard.t keyboard 0x0 23 + +ss.input.port5.keyboard.tab keyboard 0x0 43 + +ss.input.port5.keyboard.u keyboard 0x0 24 + +ss.input.port5.keyboard.up keyboard 0x0 82 + +ss.input.port5.keyboard.v keyboard 0x0 25 + +ss.input.port5.keyboard.w keyboard 0x0 26 + +ss.input.port5.keyboard.x keyboard 0x0 27 + +ss.input.port5.keyboard.y keyboard 0x0 28 + +ss.input.port5.keyboard.z keyboard 0x0 29 + +ss.input.port5.mission.a + +ss.input.port5.mission.afa + +ss.input.port5.mission.afa.defpos off + +ss.input.port5.mission.afb + +ss.input.port5.mission.afb.defpos off + +ss.input.port5.mission.afc + +ss.input.port5.mission.afc.defpos off + +ss.input.port5.mission.afl + +ss.input.port5.mission.afl.defpos off + +ss.input.port5.mission.afr + +ss.input.port5.mission.afr.defpos off + +ss.input.port5.mission.afspeed + +ss.input.port5.mission.afspeed.defpos 1 + +ss.input.port5.mission.afx + +ss.input.port5.mission.afx.defpos off + +ss.input.port5.mission.afy + +ss.input.port5.mission.afy.defpos off + +ss.input.port5.mission.afz + +ss.input.port5.mission.afz.defpos off + +ss.input.port5.mission.b + +ss.input.port5.mission.c + +ss.input.port5.mission.l + +ss.input.port5.mission.r + +ss.input.port5.mission.start + +ss.input.port5.mission.stick_back + +ss.input.port5.mission.stick_fore + +ss.input.port5.mission.stick_left + +ss.input.port5.mission.stick_right + +ss.input.port5.mission.throttle_down + +ss.input.port5.mission.throttle_up + +ss.input.port5.mission.x + +ss.input.port5.mission.y + +ss.input.port5.mission.z + +ss.input.port5.mouse.left mouse 0x0 button_left + +ss.input.port5.mouse.middle mouse 0x0 button_middle + +ss.input.port5.mouse.motion_down mouse 0x0 rel_y+ + +ss.input.port5.mouse.motion_left mouse 0x0 rel_x- + +ss.input.port5.mouse.motion_right mouse 0x0 rel_x+ + +ss.input.port5.mouse.motion_up mouse 0x0 rel_y- + +ss.input.port5.mouse.right mouse 0x0 button_right + +ss.input.port5.mouse.start keyboard 0x0 40 + +ss.input.port5.wheel.a + +ss.input.port5.wheel.analog_left + +ss.input.port5.wheel.analog_right + +ss.input.port5.wheel.b + +ss.input.port5.wheel.c + +ss.input.port5.wheel.down + +ss.input.port5.wheel.start + +ss.input.port5.wheel.up + +ss.input.port5.wheel.x + +ss.input.port5.wheel.y + +ss.input.port5.wheel.z + +ss.input.port6 gamepad + +ss.input.port6.3dpad.a + +ss.input.port6.3dpad.analog_down + +ss.input.port6.3dpad.analog_left + +ss.input.port6.3dpad.analog_right + +ss.input.port6.3dpad.analog_up + +ss.input.port6.3dpad.b + +ss.input.port6.3dpad.c + +ss.input.port6.3dpad.down + +ss.input.port6.3dpad.left + +ss.input.port6.3dpad.ls + +ss.input.port6.3dpad.mode + +ss.input.port6.3dpad.mode.defpos digital + +ss.input.port6.3dpad.right + +ss.input.port6.3dpad.rs + +ss.input.port6.3dpad.start + +ss.input.port6.3dpad.up + +ss.input.port6.3dpad.x + +ss.input.port6.3dpad.y + +ss.input.port6.3dpad.z + +ss.input.port6.dmission.a + +ss.input.port6.dmission.afa + +ss.input.port6.dmission.afa.defpos off + +ss.input.port6.dmission.afb + +ss.input.port6.dmission.afb.defpos off + +ss.input.port6.dmission.afc + +ss.input.port6.dmission.afc.defpos off + +ss.input.port6.dmission.afl + +ss.input.port6.dmission.afl.defpos off + +ss.input.port6.dmission.afr + +ss.input.port6.dmission.afr.defpos off + +ss.input.port6.dmission.afspeed + +ss.input.port6.dmission.afspeed.defpos 1 + +ss.input.port6.dmission.afx + +ss.input.port6.dmission.afx.defpos off + +ss.input.port6.dmission.afy + +ss.input.port6.dmission.afy.defpos off + +ss.input.port6.dmission.afz + +ss.input.port6.dmission.afz.defpos off + +ss.input.port6.dmission.b + +ss.input.port6.dmission.c + +ss.input.port6.dmission.l + +ss.input.port6.dmission.lstick_back + +ss.input.port6.dmission.lstick_fore + +ss.input.port6.dmission.lstick_left + +ss.input.port6.dmission.lstick_right + +ss.input.port6.dmission.lthrottle_down + +ss.input.port6.dmission.lthrottle_up + +ss.input.port6.dmission.r + +ss.input.port6.dmission.rstick_back + +ss.input.port6.dmission.rstick_fore + +ss.input.port6.dmission.rstick_left + +ss.input.port6.dmission.rstick_right + +ss.input.port6.dmission.rthrottle_down + +ss.input.port6.dmission.rthrottle_up + +ss.input.port6.dmission.start + +ss.input.port6.dmission.x + +ss.input.port6.dmission.y + +ss.input.port6.dmission.z + +ss.input.port6.gamepad.a + +ss.input.port6.gamepad.b + +ss.input.port6.gamepad.c + +ss.input.port6.gamepad.down + +ss.input.port6.gamepad.left + +ss.input.port6.gamepad.ls + +ss.input.port6.gamepad.right + +ss.input.port6.gamepad.rs + +ss.input.port6.gamepad.start + +ss.input.port6.gamepad.up + +ss.input.port6.gamepad.x + +ss.input.port6.gamepad.y + +ss.input.port6.gamepad.z + +ss.input.port6.gun.offscreen_shot mouse 0x0 button_right + +ss.input.port6.gun.start mouse 0x0 button_middle + +ss.input.port6.gun.trigger mouse 0x0 button_left + +ss.input.port6.gun.x_axis mouse 0x0 cursor_x-+ + +ss.input.port6.gun.y_axis mouse 0x0 cursor_y-+ + +ss.input.port6.gun_chairs 0x00FFFF + +ss.input.port6.jpkeyboard.0 keyboard 0x0 39 + +ss.input.port6.jpkeyboard.1 keyboard 0x0 30 + +ss.input.port6.jpkeyboard.2 keyboard 0x0 31 + +ss.input.port6.jpkeyboard.3 keyboard 0x0 32 + +ss.input.port6.jpkeyboard.4 keyboard 0x0 33 + +ss.input.port6.jpkeyboard.5 keyboard 0x0 34 + +ss.input.port6.jpkeyboard.6 keyboard 0x0 35 + +ss.input.port6.jpkeyboard.7 keyboard 0x0 36 + +ss.input.port6.jpkeyboard.8 keyboard 0x0 37 + +ss.input.port6.jpkeyboard.9 keyboard 0x0 38 + +ss.input.port6.jpkeyboard.a keyboard 0x0 4 + +ss.input.port6.jpkeyboard.at keyboard 0x0 47 + +ss.input.port6.jpkeyboard.b keyboard 0x0 5 + +ss.input.port6.jpkeyboard.backslash keyboard 0x0 135 + +ss.input.port6.jpkeyboard.backspace keyboard 0x0 42 + +ss.input.port6.jpkeyboard.c keyboard 0x0 6 + +ss.input.port6.jpkeyboard.capslock keyboard 0x0 57 + +ss.input.port6.jpkeyboard.circumflex keyboard 0x0 46 + +ss.input.port6.jpkeyboard.colon keyboard 0x0 52 + +ss.input.port6.jpkeyboard.comma keyboard 0x0 54 + +ss.input.port6.jpkeyboard.conv keyboard 0x0 138 + +ss.input.port6.jpkeyboard.d keyboard 0x0 7 + +ss.input.port6.jpkeyboard.delete keyboard 0x0 76 + +ss.input.port6.jpkeyboard.down keyboard 0x0 81 + +ss.input.port6.jpkeyboard.e keyboard 0x0 8 + +ss.input.port6.jpkeyboard.end keyboard 0x0 77 + +ss.input.port6.jpkeyboard.enter keyboard 0x0 40 + +ss.input.port6.jpkeyboard.esc keyboard 0x0 41 + +ss.input.port6.jpkeyboard.f keyboard 0x0 9 + +ss.input.port6.jpkeyboard.f1 keyboard 0x0 58 + +ss.input.port6.jpkeyboard.f10 keyboard 0x0 67 + +ss.input.port6.jpkeyboard.f11 keyboard 0x0 68 + +ss.input.port6.jpkeyboard.f12 keyboard 0x0 69 + +ss.input.port6.jpkeyboard.f2 keyboard 0x0 59 + +ss.input.port6.jpkeyboard.f3 keyboard 0x0 60 + +ss.input.port6.jpkeyboard.f4 keyboard 0x0 61 + +ss.input.port6.jpkeyboard.f5 keyboard 0x0 62 + +ss.input.port6.jpkeyboard.f6 keyboard 0x0 63 + +ss.input.port6.jpkeyboard.f7 keyboard 0x0 64 + +ss.input.port6.jpkeyboard.f8 keyboard 0x0 65 + +ss.input.port6.jpkeyboard.f9 keyboard 0x0 66 + +ss.input.port6.jpkeyboard.g keyboard 0x0 10 + +ss.input.port6.jpkeyboard.h keyboard 0x0 11 + +ss.input.port6.jpkeyboard.hkr keyboard 0x0 136 + +ss.input.port6.jpkeyboard.home keyboard 0x0 74 + +ss.input.port6.jpkeyboard.hwfw keyboard 0x0 53 + +ss.input.port6.jpkeyboard.i keyboard 0x0 12 + +ss.input.port6.jpkeyboard.insert keyboard 0x0 73 + +ss.input.port6.jpkeyboard.j keyboard 0x0 13 + +ss.input.port6.jpkeyboard.k keyboard 0x0 14 + +ss.input.port6.jpkeyboard.l keyboard 0x0 15 + +ss.input.port6.jpkeyboard.lalt keyboard 0x0 226 + +ss.input.port6.jpkeyboard.lctrl keyboard 0x0 224 + +ss.input.port6.jpkeyboard.left keyboard 0x0 80 + +ss.input.port6.jpkeyboard.leftbracket keyboard 0x0 48 + +ss.input.port6.jpkeyboard.lshift keyboard 0x0 225 + +ss.input.port6.jpkeyboard.m keyboard 0x0 16 + +ss.input.port6.jpkeyboard.minus keyboard 0x0 45 + +ss.input.port6.jpkeyboard.n keyboard 0x0 17 + +ss.input.port6.jpkeyboard.nonconv keyboard 0x0 139 + +ss.input.port6.jpkeyboard.o keyboard 0x0 18 + +ss.input.port6.jpkeyboard.p keyboard 0x0 19 + +ss.input.port6.jpkeyboard.pagedown keyboard 0x0 78 + +ss.input.port6.jpkeyboard.pageup keyboard 0x0 75 + +ss.input.port6.jpkeyboard.pause keyboard 0x0 72 || keyboard 0x0 83 + +ss.input.port6.jpkeyboard.period keyboard 0x0 55 + +ss.input.port6.jpkeyboard.printscreen keyboard 0x0 70 + +ss.input.port6.jpkeyboard.q keyboard 0x0 20 + +ss.input.port6.jpkeyboard.r keyboard 0x0 21 + +ss.input.port6.jpkeyboard.ralt keyboard 0x0 230 + +ss.input.port6.jpkeyboard.rctrl keyboard 0x0 228 + +ss.input.port6.jpkeyboard.right keyboard 0x0 79 + +ss.input.port6.jpkeyboard.rightbracket keyboard 0x0 49 + +ss.input.port6.jpkeyboard.rshift keyboard 0x0 229 + +ss.input.port6.jpkeyboard.s keyboard 0x0 22 + +ss.input.port6.jpkeyboard.scrolllock keyboard 0x0 71 + +ss.input.port6.jpkeyboard.semicolon keyboard 0x0 51 + +ss.input.port6.jpkeyboard.slash keyboard 0x0 56 + +ss.input.port6.jpkeyboard.space keyboard 0x0 44 + +ss.input.port6.jpkeyboard.t keyboard 0x0 23 + +ss.input.port6.jpkeyboard.tab keyboard 0x0 43 + +ss.input.port6.jpkeyboard.u keyboard 0x0 24 + +ss.input.port6.jpkeyboard.up keyboard 0x0 82 + +ss.input.port6.jpkeyboard.v keyboard 0x0 25 + +ss.input.port6.jpkeyboard.w keyboard 0x0 26 + +ss.input.port6.jpkeyboard.x keyboard 0x0 27 + +ss.input.port6.jpkeyboard.y keyboard 0x0 28 + +ss.input.port6.jpkeyboard.yen keyboard 0x0 137 + +ss.input.port6.jpkeyboard.z keyboard 0x0 29 + +ss.input.port6.keyboard.0 keyboard 0x0 39 + +ss.input.port6.keyboard.1 keyboard 0x0 30 + +ss.input.port6.keyboard.2 keyboard 0x0 31 + +ss.input.port6.keyboard.3 keyboard 0x0 32 + +ss.input.port6.keyboard.4 keyboard 0x0 33 + +ss.input.port6.keyboard.5 keyboard 0x0 34 + +ss.input.port6.keyboard.6 keyboard 0x0 35 + +ss.input.port6.keyboard.7 keyboard 0x0 36 + +ss.input.port6.keyboard.8 keyboard 0x0 37 + +ss.input.port6.keyboard.9 keyboard 0x0 38 + +ss.input.port6.keyboard.a keyboard 0x0 4 + +ss.input.port6.keyboard.b keyboard 0x0 5 + +ss.input.port6.keyboard.backslash keyboard 0x0 49 || keyboard 0x0 135 + +ss.input.port6.keyboard.backspace keyboard 0x0 42 + +ss.input.port6.keyboard.c keyboard 0x0 6 + +ss.input.port6.keyboard.capslock keyboard 0x0 57 + +ss.input.port6.keyboard.comma keyboard 0x0 54 + +ss.input.port6.keyboard.d keyboard 0x0 7 + +ss.input.port6.keyboard.delete keyboard 0x0 76 + +ss.input.port6.keyboard.down keyboard 0x0 81 + +ss.input.port6.keyboard.e keyboard 0x0 8 + +ss.input.port6.keyboard.end keyboard 0x0 77 + +ss.input.port6.keyboard.enter keyboard 0x0 40 + +ss.input.port6.keyboard.equals keyboard 0x0 46 + +ss.input.port6.keyboard.esc keyboard 0x0 41 + +ss.input.port6.keyboard.f keyboard 0x0 9 + +ss.input.port6.keyboard.f1 keyboard 0x0 58 + +ss.input.port6.keyboard.f10 keyboard 0x0 67 + +ss.input.port6.keyboard.f11 keyboard 0x0 68 + +ss.input.port6.keyboard.f12 keyboard 0x0 69 + +ss.input.port6.keyboard.f2 keyboard 0x0 59 + +ss.input.port6.keyboard.f3 keyboard 0x0 60 + +ss.input.port6.keyboard.f4 keyboard 0x0 61 + +ss.input.port6.keyboard.f5 keyboard 0x0 62 + +ss.input.port6.keyboard.f6 keyboard 0x0 63 + +ss.input.port6.keyboard.f7 keyboard 0x0 64 + +ss.input.port6.keyboard.f8 keyboard 0x0 65 + +ss.input.port6.keyboard.f9 keyboard 0x0 66 + +ss.input.port6.keyboard.g keyboard 0x0 10 + +ss.input.port6.keyboard.grave keyboard 0x0 53 + +ss.input.port6.keyboard.h keyboard 0x0 11 + +ss.input.port6.keyboard.home keyboard 0x0 74 + +ss.input.port6.keyboard.i keyboard 0x0 12 + +ss.input.port6.keyboard.insert keyboard 0x0 73 + +ss.input.port6.keyboard.j keyboard 0x0 13 + +ss.input.port6.keyboard.k keyboard 0x0 14 + +ss.input.port6.keyboard.kp_asterisk keyboard 0x0 85 + +ss.input.port6.keyboard.kp_center keyboard 0x0 93 + +ss.input.port6.keyboard.kp_delete keyboard 0x0 99 + +ss.input.port6.keyboard.kp_down keyboard 0x0 90 + +ss.input.port6.keyboard.kp_end keyboard 0x0 89 + +ss.input.port6.keyboard.kp_enter keyboard 0x0 88 + +ss.input.port6.keyboard.kp_home keyboard 0x0 95 + +ss.input.port6.keyboard.kp_insert keyboard 0x0 98 + +ss.input.port6.keyboard.kp_left keyboard 0x0 92 + +ss.input.port6.keyboard.kp_minus keyboard 0x0 86 + +ss.input.port6.keyboard.kp_pagedown keyboard 0x0 91 + +ss.input.port6.keyboard.kp_pageup keyboard 0x0 97 + +ss.input.port6.keyboard.kp_plus keyboard 0x0 87 + +ss.input.port6.keyboard.kp_right keyboard 0x0 94 + +ss.input.port6.keyboard.kp_slash keyboard 0x0 84 + +ss.input.port6.keyboard.kp_up keyboard 0x0 96 + +ss.input.port6.keyboard.l keyboard 0x0 15 + +ss.input.port6.keyboard.lalt keyboard 0x0 226 + +ss.input.port6.keyboard.lctrl keyboard 0x0 224 + +ss.input.port6.keyboard.left keyboard 0x0 80 + +ss.input.port6.keyboard.leftbracket keyboard 0x0 47 + +ss.input.port6.keyboard.lshift keyboard 0x0 225 + +ss.input.port6.keyboard.m keyboard 0x0 16 + +ss.input.port6.keyboard.minus keyboard 0x0 45 + +ss.input.port6.keyboard.n keyboard 0x0 17 + +ss.input.port6.keyboard.numlock keyboard 0x0 83 + +ss.input.port6.keyboard.o keyboard 0x0 18 + +ss.input.port6.keyboard.p keyboard 0x0 19 + +ss.input.port6.keyboard.pagedown keyboard 0x0 78 + +ss.input.port6.keyboard.pageup keyboard 0x0 75 + +ss.input.port6.keyboard.pause keyboard 0x0 72 + +ss.input.port6.keyboard.period keyboard 0x0 55 + +ss.input.port6.keyboard.printscreen keyboard 0x0 70 + +ss.input.port6.keyboard.q keyboard 0x0 20 + +ss.input.port6.keyboard.quote keyboard 0x0 52 + +ss.input.port6.keyboard.r keyboard 0x0 21 + +ss.input.port6.keyboard.ralt keyboard 0x0 230 + +ss.input.port6.keyboard.rctrl keyboard 0x0 228 + +ss.input.port6.keyboard.right keyboard 0x0 79 + +ss.input.port6.keyboard.rightbracket keyboard 0x0 48 + +ss.input.port6.keyboard.rshift keyboard 0x0 229 + +ss.input.port6.keyboard.s keyboard 0x0 22 + +ss.input.port6.keyboard.scrolllock keyboard 0x0 71 + +ss.input.port6.keyboard.semicolon keyboard 0x0 51 + +ss.input.port6.keyboard.slash keyboard 0x0 56 + +ss.input.port6.keyboard.space keyboard 0x0 44 + +ss.input.port6.keyboard.t keyboard 0x0 23 + +ss.input.port6.keyboard.tab keyboard 0x0 43 + +ss.input.port6.keyboard.u keyboard 0x0 24 + +ss.input.port6.keyboard.up keyboard 0x0 82 + +ss.input.port6.keyboard.v keyboard 0x0 25 + +ss.input.port6.keyboard.w keyboard 0x0 26 + +ss.input.port6.keyboard.x keyboard 0x0 27 + +ss.input.port6.keyboard.y keyboard 0x0 28 + +ss.input.port6.keyboard.z keyboard 0x0 29 + +ss.input.port6.mission.a + +ss.input.port6.mission.afa + +ss.input.port6.mission.afa.defpos off + +ss.input.port6.mission.afb + +ss.input.port6.mission.afb.defpos off + +ss.input.port6.mission.afc + +ss.input.port6.mission.afc.defpos off + +ss.input.port6.mission.afl + +ss.input.port6.mission.afl.defpos off + +ss.input.port6.mission.afr + +ss.input.port6.mission.afr.defpos off + +ss.input.port6.mission.afspeed + +ss.input.port6.mission.afspeed.defpos 1 + +ss.input.port6.mission.afx + +ss.input.port6.mission.afx.defpos off + +ss.input.port6.mission.afy + +ss.input.port6.mission.afy.defpos off + +ss.input.port6.mission.afz + +ss.input.port6.mission.afz.defpos off + +ss.input.port6.mission.b + +ss.input.port6.mission.c + +ss.input.port6.mission.l + +ss.input.port6.mission.r + +ss.input.port6.mission.start + +ss.input.port6.mission.stick_back + +ss.input.port6.mission.stick_fore + +ss.input.port6.mission.stick_left + +ss.input.port6.mission.stick_right + +ss.input.port6.mission.throttle_down + +ss.input.port6.mission.throttle_up + +ss.input.port6.mission.x + +ss.input.port6.mission.y + +ss.input.port6.mission.z + +ss.input.port6.mouse.left mouse 0x0 button_left + +ss.input.port6.mouse.middle mouse 0x0 button_middle + +ss.input.port6.mouse.motion_down mouse 0x0 rel_y+ + +ss.input.port6.mouse.motion_left mouse 0x0 rel_x- + +ss.input.port6.mouse.motion_right mouse 0x0 rel_x+ + +ss.input.port6.mouse.motion_up mouse 0x0 rel_y- + +ss.input.port6.mouse.right mouse 0x0 button_right + +ss.input.port6.mouse.start keyboard 0x0 40 + +ss.input.port6.wheel.a + +ss.input.port6.wheel.analog_left + +ss.input.port6.wheel.analog_right + +ss.input.port6.wheel.b + +ss.input.port6.wheel.c + +ss.input.port6.wheel.down + +ss.input.port6.wheel.start + +ss.input.port6.wheel.up + +ss.input.port6.wheel.x + +ss.input.port6.wheel.y + +ss.input.port6.wheel.z + +ss.input.port7 gamepad + +ss.input.port7.3dpad.a + +ss.input.port7.3dpad.analog_down + +ss.input.port7.3dpad.analog_left + +ss.input.port7.3dpad.analog_right + +ss.input.port7.3dpad.analog_up + +ss.input.port7.3dpad.b + +ss.input.port7.3dpad.c + +ss.input.port7.3dpad.down + +ss.input.port7.3dpad.left + +ss.input.port7.3dpad.ls + +ss.input.port7.3dpad.mode + +ss.input.port7.3dpad.mode.defpos digital + +ss.input.port7.3dpad.right + +ss.input.port7.3dpad.rs + +ss.input.port7.3dpad.start + +ss.input.port7.3dpad.up + +ss.input.port7.3dpad.x + +ss.input.port7.3dpad.y + +ss.input.port7.3dpad.z + +ss.input.port7.dmission.a + +ss.input.port7.dmission.afa + +ss.input.port7.dmission.afa.defpos off + +ss.input.port7.dmission.afb + +ss.input.port7.dmission.afb.defpos off + +ss.input.port7.dmission.afc + +ss.input.port7.dmission.afc.defpos off + +ss.input.port7.dmission.afl + +ss.input.port7.dmission.afl.defpos off + +ss.input.port7.dmission.afr + +ss.input.port7.dmission.afr.defpos off + +ss.input.port7.dmission.afspeed + +ss.input.port7.dmission.afspeed.defpos 1 + +ss.input.port7.dmission.afx + +ss.input.port7.dmission.afx.defpos off + +ss.input.port7.dmission.afy + +ss.input.port7.dmission.afy.defpos off + +ss.input.port7.dmission.afz + +ss.input.port7.dmission.afz.defpos off + +ss.input.port7.dmission.b + +ss.input.port7.dmission.c + +ss.input.port7.dmission.l + +ss.input.port7.dmission.lstick_back + +ss.input.port7.dmission.lstick_fore + +ss.input.port7.dmission.lstick_left + +ss.input.port7.dmission.lstick_right + +ss.input.port7.dmission.lthrottle_down + +ss.input.port7.dmission.lthrottle_up + +ss.input.port7.dmission.r + +ss.input.port7.dmission.rstick_back + +ss.input.port7.dmission.rstick_fore + +ss.input.port7.dmission.rstick_left + +ss.input.port7.dmission.rstick_right + +ss.input.port7.dmission.rthrottle_down + +ss.input.port7.dmission.rthrottle_up + +ss.input.port7.dmission.start + +ss.input.port7.dmission.x + +ss.input.port7.dmission.y + +ss.input.port7.dmission.z + +ss.input.port7.gamepad.a + +ss.input.port7.gamepad.b + +ss.input.port7.gamepad.c + +ss.input.port7.gamepad.down + +ss.input.port7.gamepad.left + +ss.input.port7.gamepad.ls + +ss.input.port7.gamepad.right + +ss.input.port7.gamepad.rs + +ss.input.port7.gamepad.start + +ss.input.port7.gamepad.up + +ss.input.port7.gamepad.x + +ss.input.port7.gamepad.y + +ss.input.port7.gamepad.z + +ss.input.port7.gun.offscreen_shot mouse 0x0 button_right + +ss.input.port7.gun.start mouse 0x0 button_middle + +ss.input.port7.gun.trigger mouse 0x0 button_left + +ss.input.port7.gun.x_axis mouse 0x0 cursor_x-+ + +ss.input.port7.gun.y_axis mouse 0x0 cursor_y-+ + +ss.input.port7.gun_chairs 0x0080FF + +ss.input.port7.jpkeyboard.0 keyboard 0x0 39 + +ss.input.port7.jpkeyboard.1 keyboard 0x0 30 + +ss.input.port7.jpkeyboard.2 keyboard 0x0 31 + +ss.input.port7.jpkeyboard.3 keyboard 0x0 32 + +ss.input.port7.jpkeyboard.4 keyboard 0x0 33 + +ss.input.port7.jpkeyboard.5 keyboard 0x0 34 + +ss.input.port7.jpkeyboard.6 keyboard 0x0 35 + +ss.input.port7.jpkeyboard.7 keyboard 0x0 36 + +ss.input.port7.jpkeyboard.8 keyboard 0x0 37 + +ss.input.port7.jpkeyboard.9 keyboard 0x0 38 + +ss.input.port7.jpkeyboard.a keyboard 0x0 4 + +ss.input.port7.jpkeyboard.at keyboard 0x0 47 + +ss.input.port7.jpkeyboard.b keyboard 0x0 5 + +ss.input.port7.jpkeyboard.backslash keyboard 0x0 135 + +ss.input.port7.jpkeyboard.backspace keyboard 0x0 42 + +ss.input.port7.jpkeyboard.c keyboard 0x0 6 + +ss.input.port7.jpkeyboard.capslock keyboard 0x0 57 + +ss.input.port7.jpkeyboard.circumflex keyboard 0x0 46 + +ss.input.port7.jpkeyboard.colon keyboard 0x0 52 + +ss.input.port7.jpkeyboard.comma keyboard 0x0 54 + +ss.input.port7.jpkeyboard.conv keyboard 0x0 138 + +ss.input.port7.jpkeyboard.d keyboard 0x0 7 + +ss.input.port7.jpkeyboard.delete keyboard 0x0 76 + +ss.input.port7.jpkeyboard.down keyboard 0x0 81 + +ss.input.port7.jpkeyboard.e keyboard 0x0 8 + +ss.input.port7.jpkeyboard.end keyboard 0x0 77 + +ss.input.port7.jpkeyboard.enter keyboard 0x0 40 + +ss.input.port7.jpkeyboard.esc keyboard 0x0 41 + +ss.input.port7.jpkeyboard.f keyboard 0x0 9 + +ss.input.port7.jpkeyboard.f1 keyboard 0x0 58 + +ss.input.port7.jpkeyboard.f10 keyboard 0x0 67 + +ss.input.port7.jpkeyboard.f11 keyboard 0x0 68 + +ss.input.port7.jpkeyboard.f12 keyboard 0x0 69 + +ss.input.port7.jpkeyboard.f2 keyboard 0x0 59 + +ss.input.port7.jpkeyboard.f3 keyboard 0x0 60 + +ss.input.port7.jpkeyboard.f4 keyboard 0x0 61 + +ss.input.port7.jpkeyboard.f5 keyboard 0x0 62 + +ss.input.port7.jpkeyboard.f6 keyboard 0x0 63 + +ss.input.port7.jpkeyboard.f7 keyboard 0x0 64 + +ss.input.port7.jpkeyboard.f8 keyboard 0x0 65 + +ss.input.port7.jpkeyboard.f9 keyboard 0x0 66 + +ss.input.port7.jpkeyboard.g keyboard 0x0 10 + +ss.input.port7.jpkeyboard.h keyboard 0x0 11 + +ss.input.port7.jpkeyboard.hkr keyboard 0x0 136 + +ss.input.port7.jpkeyboard.home keyboard 0x0 74 + +ss.input.port7.jpkeyboard.hwfw keyboard 0x0 53 + +ss.input.port7.jpkeyboard.i keyboard 0x0 12 + +ss.input.port7.jpkeyboard.insert keyboard 0x0 73 + +ss.input.port7.jpkeyboard.j keyboard 0x0 13 + +ss.input.port7.jpkeyboard.k keyboard 0x0 14 + +ss.input.port7.jpkeyboard.l keyboard 0x0 15 + +ss.input.port7.jpkeyboard.lalt keyboard 0x0 226 + +ss.input.port7.jpkeyboard.lctrl keyboard 0x0 224 + +ss.input.port7.jpkeyboard.left keyboard 0x0 80 + +ss.input.port7.jpkeyboard.leftbracket keyboard 0x0 48 + +ss.input.port7.jpkeyboard.lshift keyboard 0x0 225 + +ss.input.port7.jpkeyboard.m keyboard 0x0 16 + +ss.input.port7.jpkeyboard.minus keyboard 0x0 45 + +ss.input.port7.jpkeyboard.n keyboard 0x0 17 + +ss.input.port7.jpkeyboard.nonconv keyboard 0x0 139 + +ss.input.port7.jpkeyboard.o keyboard 0x0 18 + +ss.input.port7.jpkeyboard.p keyboard 0x0 19 + +ss.input.port7.jpkeyboard.pagedown keyboard 0x0 78 + +ss.input.port7.jpkeyboard.pageup keyboard 0x0 75 + +ss.input.port7.jpkeyboard.pause keyboard 0x0 72 || keyboard 0x0 83 + +ss.input.port7.jpkeyboard.period keyboard 0x0 55 + +ss.input.port7.jpkeyboard.printscreen keyboard 0x0 70 + +ss.input.port7.jpkeyboard.q keyboard 0x0 20 + +ss.input.port7.jpkeyboard.r keyboard 0x0 21 + +ss.input.port7.jpkeyboard.ralt keyboard 0x0 230 + +ss.input.port7.jpkeyboard.rctrl keyboard 0x0 228 + +ss.input.port7.jpkeyboard.right keyboard 0x0 79 + +ss.input.port7.jpkeyboard.rightbracket keyboard 0x0 49 + +ss.input.port7.jpkeyboard.rshift keyboard 0x0 229 + +ss.input.port7.jpkeyboard.s keyboard 0x0 22 + +ss.input.port7.jpkeyboard.scrolllock keyboard 0x0 71 + +ss.input.port7.jpkeyboard.semicolon keyboard 0x0 51 + +ss.input.port7.jpkeyboard.slash keyboard 0x0 56 + +ss.input.port7.jpkeyboard.space keyboard 0x0 44 + +ss.input.port7.jpkeyboard.t keyboard 0x0 23 + +ss.input.port7.jpkeyboard.tab keyboard 0x0 43 + +ss.input.port7.jpkeyboard.u keyboard 0x0 24 + +ss.input.port7.jpkeyboard.up keyboard 0x0 82 + +ss.input.port7.jpkeyboard.v keyboard 0x0 25 + +ss.input.port7.jpkeyboard.w keyboard 0x0 26 + +ss.input.port7.jpkeyboard.x keyboard 0x0 27 + +ss.input.port7.jpkeyboard.y keyboard 0x0 28 + +ss.input.port7.jpkeyboard.yen keyboard 0x0 137 + +ss.input.port7.jpkeyboard.z keyboard 0x0 29 + +ss.input.port7.keyboard.0 keyboard 0x0 39 + +ss.input.port7.keyboard.1 keyboard 0x0 30 + +ss.input.port7.keyboard.2 keyboard 0x0 31 + +ss.input.port7.keyboard.3 keyboard 0x0 32 + +ss.input.port7.keyboard.4 keyboard 0x0 33 + +ss.input.port7.keyboard.5 keyboard 0x0 34 + +ss.input.port7.keyboard.6 keyboard 0x0 35 + +ss.input.port7.keyboard.7 keyboard 0x0 36 + +ss.input.port7.keyboard.8 keyboard 0x0 37 + +ss.input.port7.keyboard.9 keyboard 0x0 38 + +ss.input.port7.keyboard.a keyboard 0x0 4 + +ss.input.port7.keyboard.b keyboard 0x0 5 + +ss.input.port7.keyboard.backslash keyboard 0x0 49 || keyboard 0x0 135 + +ss.input.port7.keyboard.backspace keyboard 0x0 42 + +ss.input.port7.keyboard.c keyboard 0x0 6 + +ss.input.port7.keyboard.capslock keyboard 0x0 57 + +ss.input.port7.keyboard.comma keyboard 0x0 54 + +ss.input.port7.keyboard.d keyboard 0x0 7 + +ss.input.port7.keyboard.delete keyboard 0x0 76 + +ss.input.port7.keyboard.down keyboard 0x0 81 + +ss.input.port7.keyboard.e keyboard 0x0 8 + +ss.input.port7.keyboard.end keyboard 0x0 77 + +ss.input.port7.keyboard.enter keyboard 0x0 40 + +ss.input.port7.keyboard.equals keyboard 0x0 46 + +ss.input.port7.keyboard.esc keyboard 0x0 41 + +ss.input.port7.keyboard.f keyboard 0x0 9 + +ss.input.port7.keyboard.f1 keyboard 0x0 58 + +ss.input.port7.keyboard.f10 keyboard 0x0 67 + +ss.input.port7.keyboard.f11 keyboard 0x0 68 + +ss.input.port7.keyboard.f12 keyboard 0x0 69 + +ss.input.port7.keyboard.f2 keyboard 0x0 59 + +ss.input.port7.keyboard.f3 keyboard 0x0 60 + +ss.input.port7.keyboard.f4 keyboard 0x0 61 + +ss.input.port7.keyboard.f5 keyboard 0x0 62 + +ss.input.port7.keyboard.f6 keyboard 0x0 63 + +ss.input.port7.keyboard.f7 keyboard 0x0 64 + +ss.input.port7.keyboard.f8 keyboard 0x0 65 + +ss.input.port7.keyboard.f9 keyboard 0x0 66 + +ss.input.port7.keyboard.g keyboard 0x0 10 + +ss.input.port7.keyboard.grave keyboard 0x0 53 + +ss.input.port7.keyboard.h keyboard 0x0 11 + +ss.input.port7.keyboard.home keyboard 0x0 74 + +ss.input.port7.keyboard.i keyboard 0x0 12 + +ss.input.port7.keyboard.insert keyboard 0x0 73 + +ss.input.port7.keyboard.j keyboard 0x0 13 + +ss.input.port7.keyboard.k keyboard 0x0 14 + +ss.input.port7.keyboard.kp_asterisk keyboard 0x0 85 + +ss.input.port7.keyboard.kp_center keyboard 0x0 93 + +ss.input.port7.keyboard.kp_delete keyboard 0x0 99 + +ss.input.port7.keyboard.kp_down keyboard 0x0 90 + +ss.input.port7.keyboard.kp_end keyboard 0x0 89 + +ss.input.port7.keyboard.kp_enter keyboard 0x0 88 + +ss.input.port7.keyboard.kp_home keyboard 0x0 95 + +ss.input.port7.keyboard.kp_insert keyboard 0x0 98 + +ss.input.port7.keyboard.kp_left keyboard 0x0 92 + +ss.input.port7.keyboard.kp_minus keyboard 0x0 86 + +ss.input.port7.keyboard.kp_pagedown keyboard 0x0 91 + +ss.input.port7.keyboard.kp_pageup keyboard 0x0 97 + +ss.input.port7.keyboard.kp_plus keyboard 0x0 87 + +ss.input.port7.keyboard.kp_right keyboard 0x0 94 + +ss.input.port7.keyboard.kp_slash keyboard 0x0 84 + +ss.input.port7.keyboard.kp_up keyboard 0x0 96 + +ss.input.port7.keyboard.l keyboard 0x0 15 + +ss.input.port7.keyboard.lalt keyboard 0x0 226 + +ss.input.port7.keyboard.lctrl keyboard 0x0 224 + +ss.input.port7.keyboard.left keyboard 0x0 80 + +ss.input.port7.keyboard.leftbracket keyboard 0x0 47 + +ss.input.port7.keyboard.lshift keyboard 0x0 225 + +ss.input.port7.keyboard.m keyboard 0x0 16 + +ss.input.port7.keyboard.minus keyboard 0x0 45 + +ss.input.port7.keyboard.n keyboard 0x0 17 + +ss.input.port7.keyboard.numlock keyboard 0x0 83 + +ss.input.port7.keyboard.o keyboard 0x0 18 + +ss.input.port7.keyboard.p keyboard 0x0 19 + +ss.input.port7.keyboard.pagedown keyboard 0x0 78 + +ss.input.port7.keyboard.pageup keyboard 0x0 75 + +ss.input.port7.keyboard.pause keyboard 0x0 72 + +ss.input.port7.keyboard.period keyboard 0x0 55 + +ss.input.port7.keyboard.printscreen keyboard 0x0 70 + +ss.input.port7.keyboard.q keyboard 0x0 20 + +ss.input.port7.keyboard.quote keyboard 0x0 52 + +ss.input.port7.keyboard.r keyboard 0x0 21 + +ss.input.port7.keyboard.ralt keyboard 0x0 230 + +ss.input.port7.keyboard.rctrl keyboard 0x0 228 + +ss.input.port7.keyboard.right keyboard 0x0 79 + +ss.input.port7.keyboard.rightbracket keyboard 0x0 48 + +ss.input.port7.keyboard.rshift keyboard 0x0 229 + +ss.input.port7.keyboard.s keyboard 0x0 22 + +ss.input.port7.keyboard.scrolllock keyboard 0x0 71 + +ss.input.port7.keyboard.semicolon keyboard 0x0 51 + +ss.input.port7.keyboard.slash keyboard 0x0 56 + +ss.input.port7.keyboard.space keyboard 0x0 44 + +ss.input.port7.keyboard.t keyboard 0x0 23 + +ss.input.port7.keyboard.tab keyboard 0x0 43 + +ss.input.port7.keyboard.u keyboard 0x0 24 + +ss.input.port7.keyboard.up keyboard 0x0 82 + +ss.input.port7.keyboard.v keyboard 0x0 25 + +ss.input.port7.keyboard.w keyboard 0x0 26 + +ss.input.port7.keyboard.x keyboard 0x0 27 + +ss.input.port7.keyboard.y keyboard 0x0 28 + +ss.input.port7.keyboard.z keyboard 0x0 29 + +ss.input.port7.mission.a + +ss.input.port7.mission.afa + +ss.input.port7.mission.afa.defpos off + +ss.input.port7.mission.afb + +ss.input.port7.mission.afb.defpos off + +ss.input.port7.mission.afc + +ss.input.port7.mission.afc.defpos off + +ss.input.port7.mission.afl + +ss.input.port7.mission.afl.defpos off + +ss.input.port7.mission.afr + +ss.input.port7.mission.afr.defpos off + +ss.input.port7.mission.afspeed + +ss.input.port7.mission.afspeed.defpos 1 + +ss.input.port7.mission.afx + +ss.input.port7.mission.afx.defpos off + +ss.input.port7.mission.afy + +ss.input.port7.mission.afy.defpos off + +ss.input.port7.mission.afz + +ss.input.port7.mission.afz.defpos off + +ss.input.port7.mission.b + +ss.input.port7.mission.c + +ss.input.port7.mission.l + +ss.input.port7.mission.r + +ss.input.port7.mission.start + +ss.input.port7.mission.stick_back + +ss.input.port7.mission.stick_fore + +ss.input.port7.mission.stick_left + +ss.input.port7.mission.stick_right + +ss.input.port7.mission.throttle_down + +ss.input.port7.mission.throttle_up + +ss.input.port7.mission.x + +ss.input.port7.mission.y + +ss.input.port7.mission.z + +ss.input.port7.mouse.left mouse 0x0 button_left + +ss.input.port7.mouse.middle mouse 0x0 button_middle + +ss.input.port7.mouse.motion_down mouse 0x0 rel_y+ + +ss.input.port7.mouse.motion_left mouse 0x0 rel_x- + +ss.input.port7.mouse.motion_right mouse 0x0 rel_x+ + +ss.input.port7.mouse.motion_up mouse 0x0 rel_y- + +ss.input.port7.mouse.right mouse 0x0 button_right + +ss.input.port7.mouse.start keyboard 0x0 40 + +ss.input.port7.wheel.a + +ss.input.port7.wheel.analog_left + +ss.input.port7.wheel.analog_right + +ss.input.port7.wheel.b + +ss.input.port7.wheel.c + +ss.input.port7.wheel.down + +ss.input.port7.wheel.start + +ss.input.port7.wheel.up + +ss.input.port7.wheel.x + +ss.input.port7.wheel.y + +ss.input.port7.wheel.z + +ss.input.port8 gamepad + +ss.input.port8.3dpad.a + +ss.input.port8.3dpad.analog_down + +ss.input.port8.3dpad.analog_left + +ss.input.port8.3dpad.analog_right + +ss.input.port8.3dpad.analog_up + +ss.input.port8.3dpad.b + +ss.input.port8.3dpad.c + +ss.input.port8.3dpad.down + +ss.input.port8.3dpad.left + +ss.input.port8.3dpad.ls + +ss.input.port8.3dpad.mode + +ss.input.port8.3dpad.mode.defpos digital + +ss.input.port8.3dpad.right + +ss.input.port8.3dpad.rs + +ss.input.port8.3dpad.start + +ss.input.port8.3dpad.up + +ss.input.port8.3dpad.x + +ss.input.port8.3dpad.y + +ss.input.port8.3dpad.z + +ss.input.port8.dmission.a + +ss.input.port8.dmission.afa + +ss.input.port8.dmission.afa.defpos off + +ss.input.port8.dmission.afb + +ss.input.port8.dmission.afb.defpos off + +ss.input.port8.dmission.afc + +ss.input.port8.dmission.afc.defpos off + +ss.input.port8.dmission.afl + +ss.input.port8.dmission.afl.defpos off + +ss.input.port8.dmission.afr + +ss.input.port8.dmission.afr.defpos off + +ss.input.port8.dmission.afspeed + +ss.input.port8.dmission.afspeed.defpos 1 + +ss.input.port8.dmission.afx + +ss.input.port8.dmission.afx.defpos off + +ss.input.port8.dmission.afy + +ss.input.port8.dmission.afy.defpos off + +ss.input.port8.dmission.afz + +ss.input.port8.dmission.afz.defpos off + +ss.input.port8.dmission.b + +ss.input.port8.dmission.c + +ss.input.port8.dmission.l + +ss.input.port8.dmission.lstick_back + +ss.input.port8.dmission.lstick_fore + +ss.input.port8.dmission.lstick_left + +ss.input.port8.dmission.lstick_right + +ss.input.port8.dmission.lthrottle_down + +ss.input.port8.dmission.lthrottle_up + +ss.input.port8.dmission.r + +ss.input.port8.dmission.rstick_back + +ss.input.port8.dmission.rstick_fore + +ss.input.port8.dmission.rstick_left + +ss.input.port8.dmission.rstick_right + +ss.input.port8.dmission.rthrottle_down + +ss.input.port8.dmission.rthrottle_up + +ss.input.port8.dmission.start + +ss.input.port8.dmission.x + +ss.input.port8.dmission.y + +ss.input.port8.dmission.z + +ss.input.port8.gamepad.a + +ss.input.port8.gamepad.b + +ss.input.port8.gamepad.c + +ss.input.port8.gamepad.down + +ss.input.port8.gamepad.left + +ss.input.port8.gamepad.ls + +ss.input.port8.gamepad.right + +ss.input.port8.gamepad.rs + +ss.input.port8.gamepad.start + +ss.input.port8.gamepad.up + +ss.input.port8.gamepad.x + +ss.input.port8.gamepad.y + +ss.input.port8.gamepad.z + +ss.input.port8.gun.offscreen_shot mouse 0x0 button_right + +ss.input.port8.gun.start mouse 0x0 button_middle + +ss.input.port8.gun.trigger mouse 0x0 button_left + +ss.input.port8.gun.x_axis mouse 0x0 cursor_x-+ + +ss.input.port8.gun.y_axis mouse 0x0 cursor_y-+ + +ss.input.port8.gun_chairs 0x8000FF + +ss.input.port8.jpkeyboard.0 keyboard 0x0 39 + +ss.input.port8.jpkeyboard.1 keyboard 0x0 30 + +ss.input.port8.jpkeyboard.2 keyboard 0x0 31 + +ss.input.port8.jpkeyboard.3 keyboard 0x0 32 + +ss.input.port8.jpkeyboard.4 keyboard 0x0 33 + +ss.input.port8.jpkeyboard.5 keyboard 0x0 34 + +ss.input.port8.jpkeyboard.6 keyboard 0x0 35 + +ss.input.port8.jpkeyboard.7 keyboard 0x0 36 + +ss.input.port8.jpkeyboard.8 keyboard 0x0 37 + +ss.input.port8.jpkeyboard.9 keyboard 0x0 38 + +ss.input.port8.jpkeyboard.a keyboard 0x0 4 + +ss.input.port8.jpkeyboard.at keyboard 0x0 47 + +ss.input.port8.jpkeyboard.b keyboard 0x0 5 + +ss.input.port8.jpkeyboard.backslash keyboard 0x0 135 + +ss.input.port8.jpkeyboard.backspace keyboard 0x0 42 + +ss.input.port8.jpkeyboard.c keyboard 0x0 6 + +ss.input.port8.jpkeyboard.capslock keyboard 0x0 57 + +ss.input.port8.jpkeyboard.circumflex keyboard 0x0 46 + +ss.input.port8.jpkeyboard.colon keyboard 0x0 52 + +ss.input.port8.jpkeyboard.comma keyboard 0x0 54 + +ss.input.port8.jpkeyboard.conv keyboard 0x0 138 + +ss.input.port8.jpkeyboard.d keyboard 0x0 7 + +ss.input.port8.jpkeyboard.delete keyboard 0x0 76 + +ss.input.port8.jpkeyboard.down keyboard 0x0 81 + +ss.input.port8.jpkeyboard.e keyboard 0x0 8 + +ss.input.port8.jpkeyboard.end keyboard 0x0 77 + +ss.input.port8.jpkeyboard.enter keyboard 0x0 40 + +ss.input.port8.jpkeyboard.esc keyboard 0x0 41 + +ss.input.port8.jpkeyboard.f keyboard 0x0 9 + +ss.input.port8.jpkeyboard.f1 keyboard 0x0 58 + +ss.input.port8.jpkeyboard.f10 keyboard 0x0 67 + +ss.input.port8.jpkeyboard.f11 keyboard 0x0 68 + +ss.input.port8.jpkeyboard.f12 keyboard 0x0 69 + +ss.input.port8.jpkeyboard.f2 keyboard 0x0 59 + +ss.input.port8.jpkeyboard.f3 keyboard 0x0 60 + +ss.input.port8.jpkeyboard.f4 keyboard 0x0 61 + +ss.input.port8.jpkeyboard.f5 keyboard 0x0 62 + +ss.input.port8.jpkeyboard.f6 keyboard 0x0 63 + +ss.input.port8.jpkeyboard.f7 keyboard 0x0 64 + +ss.input.port8.jpkeyboard.f8 keyboard 0x0 65 + +ss.input.port8.jpkeyboard.f9 keyboard 0x0 66 + +ss.input.port8.jpkeyboard.g keyboard 0x0 10 + +ss.input.port8.jpkeyboard.h keyboard 0x0 11 + +ss.input.port8.jpkeyboard.hkr keyboard 0x0 136 + +ss.input.port8.jpkeyboard.home keyboard 0x0 74 + +ss.input.port8.jpkeyboard.hwfw keyboard 0x0 53 + +ss.input.port8.jpkeyboard.i keyboard 0x0 12 + +ss.input.port8.jpkeyboard.insert keyboard 0x0 73 + +ss.input.port8.jpkeyboard.j keyboard 0x0 13 + +ss.input.port8.jpkeyboard.k keyboard 0x0 14 + +ss.input.port8.jpkeyboard.l keyboard 0x0 15 + +ss.input.port8.jpkeyboard.lalt keyboard 0x0 226 + +ss.input.port8.jpkeyboard.lctrl keyboard 0x0 224 + +ss.input.port8.jpkeyboard.left keyboard 0x0 80 + +ss.input.port8.jpkeyboard.leftbracket keyboard 0x0 48 + +ss.input.port8.jpkeyboard.lshift keyboard 0x0 225 + +ss.input.port8.jpkeyboard.m keyboard 0x0 16 + +ss.input.port8.jpkeyboard.minus keyboard 0x0 45 + +ss.input.port8.jpkeyboard.n keyboard 0x0 17 + +ss.input.port8.jpkeyboard.nonconv keyboard 0x0 139 + +ss.input.port8.jpkeyboard.o keyboard 0x0 18 + +ss.input.port8.jpkeyboard.p keyboard 0x0 19 + +ss.input.port8.jpkeyboard.pagedown keyboard 0x0 78 + +ss.input.port8.jpkeyboard.pageup keyboard 0x0 75 + +ss.input.port8.jpkeyboard.pause keyboard 0x0 72 || keyboard 0x0 83 + +ss.input.port8.jpkeyboard.period keyboard 0x0 55 + +ss.input.port8.jpkeyboard.printscreen keyboard 0x0 70 + +ss.input.port8.jpkeyboard.q keyboard 0x0 20 + +ss.input.port8.jpkeyboard.r keyboard 0x0 21 + +ss.input.port8.jpkeyboard.ralt keyboard 0x0 230 + +ss.input.port8.jpkeyboard.rctrl keyboard 0x0 228 + +ss.input.port8.jpkeyboard.right keyboard 0x0 79 + +ss.input.port8.jpkeyboard.rightbracket keyboard 0x0 49 + +ss.input.port8.jpkeyboard.rshift keyboard 0x0 229 + +ss.input.port8.jpkeyboard.s keyboard 0x0 22 + +ss.input.port8.jpkeyboard.scrolllock keyboard 0x0 71 + +ss.input.port8.jpkeyboard.semicolon keyboard 0x0 51 + +ss.input.port8.jpkeyboard.slash keyboard 0x0 56 + +ss.input.port8.jpkeyboard.space keyboard 0x0 44 + +ss.input.port8.jpkeyboard.t keyboard 0x0 23 + +ss.input.port8.jpkeyboard.tab keyboard 0x0 43 + +ss.input.port8.jpkeyboard.u keyboard 0x0 24 + +ss.input.port8.jpkeyboard.up keyboard 0x0 82 + +ss.input.port8.jpkeyboard.v keyboard 0x0 25 + +ss.input.port8.jpkeyboard.w keyboard 0x0 26 + +ss.input.port8.jpkeyboard.x keyboard 0x0 27 + +ss.input.port8.jpkeyboard.y keyboard 0x0 28 + +ss.input.port8.jpkeyboard.yen keyboard 0x0 137 + +ss.input.port8.jpkeyboard.z keyboard 0x0 29 + +ss.input.port8.keyboard.0 keyboard 0x0 39 + +ss.input.port8.keyboard.1 keyboard 0x0 30 + +ss.input.port8.keyboard.2 keyboard 0x0 31 + +ss.input.port8.keyboard.3 keyboard 0x0 32 + +ss.input.port8.keyboard.4 keyboard 0x0 33 + +ss.input.port8.keyboard.5 keyboard 0x0 34 + +ss.input.port8.keyboard.6 keyboard 0x0 35 + +ss.input.port8.keyboard.7 keyboard 0x0 36 + +ss.input.port8.keyboard.8 keyboard 0x0 37 + +ss.input.port8.keyboard.9 keyboard 0x0 38 + +ss.input.port8.keyboard.a keyboard 0x0 4 + +ss.input.port8.keyboard.b keyboard 0x0 5 + +ss.input.port8.keyboard.backslash keyboard 0x0 49 || keyboard 0x0 135 + +ss.input.port8.keyboard.backspace keyboard 0x0 42 + +ss.input.port8.keyboard.c keyboard 0x0 6 + +ss.input.port8.keyboard.capslock keyboard 0x0 57 + +ss.input.port8.keyboard.comma keyboard 0x0 54 + +ss.input.port8.keyboard.d keyboard 0x0 7 + +ss.input.port8.keyboard.delete keyboard 0x0 76 + +ss.input.port8.keyboard.down keyboard 0x0 81 + +ss.input.port8.keyboard.e keyboard 0x0 8 + +ss.input.port8.keyboard.end keyboard 0x0 77 + +ss.input.port8.keyboard.enter keyboard 0x0 40 + +ss.input.port8.keyboard.equals keyboard 0x0 46 + +ss.input.port8.keyboard.esc keyboard 0x0 41 + +ss.input.port8.keyboard.f keyboard 0x0 9 + +ss.input.port8.keyboard.f1 keyboard 0x0 58 + +ss.input.port8.keyboard.f10 keyboard 0x0 67 + +ss.input.port8.keyboard.f11 keyboard 0x0 68 + +ss.input.port8.keyboard.f12 keyboard 0x0 69 + +ss.input.port8.keyboard.f2 keyboard 0x0 59 + +ss.input.port8.keyboard.f3 keyboard 0x0 60 + +ss.input.port8.keyboard.f4 keyboard 0x0 61 + +ss.input.port8.keyboard.f5 keyboard 0x0 62 + +ss.input.port8.keyboard.f6 keyboard 0x0 63 + +ss.input.port8.keyboard.f7 keyboard 0x0 64 + +ss.input.port8.keyboard.f8 keyboard 0x0 65 + +ss.input.port8.keyboard.f9 keyboard 0x0 66 + +ss.input.port8.keyboard.g keyboard 0x0 10 + +ss.input.port8.keyboard.grave keyboard 0x0 53 + +ss.input.port8.keyboard.h keyboard 0x0 11 + +ss.input.port8.keyboard.home keyboard 0x0 74 + +ss.input.port8.keyboard.i keyboard 0x0 12 + +ss.input.port8.keyboard.insert keyboard 0x0 73 + +ss.input.port8.keyboard.j keyboard 0x0 13 + +ss.input.port8.keyboard.k keyboard 0x0 14 + +ss.input.port8.keyboard.kp_asterisk keyboard 0x0 85 + +ss.input.port8.keyboard.kp_center keyboard 0x0 93 + +ss.input.port8.keyboard.kp_delete keyboard 0x0 99 + +ss.input.port8.keyboard.kp_down keyboard 0x0 90 + +ss.input.port8.keyboard.kp_end keyboard 0x0 89 + +ss.input.port8.keyboard.kp_enter keyboard 0x0 88 + +ss.input.port8.keyboard.kp_home keyboard 0x0 95 + +ss.input.port8.keyboard.kp_insert keyboard 0x0 98 + +ss.input.port8.keyboard.kp_left keyboard 0x0 92 + +ss.input.port8.keyboard.kp_minus keyboard 0x0 86 + +ss.input.port8.keyboard.kp_pagedown keyboard 0x0 91 + +ss.input.port8.keyboard.kp_pageup keyboard 0x0 97 + +ss.input.port8.keyboard.kp_plus keyboard 0x0 87 + +ss.input.port8.keyboard.kp_right keyboard 0x0 94 + +ss.input.port8.keyboard.kp_slash keyboard 0x0 84 + +ss.input.port8.keyboard.kp_up keyboard 0x0 96 + +ss.input.port8.keyboard.l keyboard 0x0 15 + +ss.input.port8.keyboard.lalt keyboard 0x0 226 + +ss.input.port8.keyboard.lctrl keyboard 0x0 224 + +ss.input.port8.keyboard.left keyboard 0x0 80 + +ss.input.port8.keyboard.leftbracket keyboard 0x0 47 + +ss.input.port8.keyboard.lshift keyboard 0x0 225 + +ss.input.port8.keyboard.m keyboard 0x0 16 + +ss.input.port8.keyboard.minus keyboard 0x0 45 + +ss.input.port8.keyboard.n keyboard 0x0 17 + +ss.input.port8.keyboard.numlock keyboard 0x0 83 + +ss.input.port8.keyboard.o keyboard 0x0 18 + +ss.input.port8.keyboard.p keyboard 0x0 19 + +ss.input.port8.keyboard.pagedown keyboard 0x0 78 + +ss.input.port8.keyboard.pageup keyboard 0x0 75 + +ss.input.port8.keyboard.pause keyboard 0x0 72 + +ss.input.port8.keyboard.period keyboard 0x0 55 + +ss.input.port8.keyboard.printscreen keyboard 0x0 70 + +ss.input.port8.keyboard.q keyboard 0x0 20 + +ss.input.port8.keyboard.quote keyboard 0x0 52 + +ss.input.port8.keyboard.r keyboard 0x0 21 + +ss.input.port8.keyboard.ralt keyboard 0x0 230 + +ss.input.port8.keyboard.rctrl keyboard 0x0 228 + +ss.input.port8.keyboard.right keyboard 0x0 79 + +ss.input.port8.keyboard.rightbracket keyboard 0x0 48 + +ss.input.port8.keyboard.rshift keyboard 0x0 229 + +ss.input.port8.keyboard.s keyboard 0x0 22 + +ss.input.port8.keyboard.scrolllock keyboard 0x0 71 + +ss.input.port8.keyboard.semicolon keyboard 0x0 51 + +ss.input.port8.keyboard.slash keyboard 0x0 56 + +ss.input.port8.keyboard.space keyboard 0x0 44 + +ss.input.port8.keyboard.t keyboard 0x0 23 + +ss.input.port8.keyboard.tab keyboard 0x0 43 + +ss.input.port8.keyboard.u keyboard 0x0 24 + +ss.input.port8.keyboard.up keyboard 0x0 82 + +ss.input.port8.keyboard.v keyboard 0x0 25 + +ss.input.port8.keyboard.w keyboard 0x0 26 + +ss.input.port8.keyboard.x keyboard 0x0 27 + +ss.input.port8.keyboard.y keyboard 0x0 28 + +ss.input.port8.keyboard.z keyboard 0x0 29 + +ss.input.port8.mission.a + +ss.input.port8.mission.afa + +ss.input.port8.mission.afa.defpos off + +ss.input.port8.mission.afb + +ss.input.port8.mission.afb.defpos off + +ss.input.port8.mission.afc + +ss.input.port8.mission.afc.defpos off + +ss.input.port8.mission.afl + +ss.input.port8.mission.afl.defpos off + +ss.input.port8.mission.afr + +ss.input.port8.mission.afr.defpos off + +ss.input.port8.mission.afspeed + +ss.input.port8.mission.afspeed.defpos 1 + +ss.input.port8.mission.afx + +ss.input.port8.mission.afx.defpos off + +ss.input.port8.mission.afy + +ss.input.port8.mission.afy.defpos off + +ss.input.port8.mission.afz + +ss.input.port8.mission.afz.defpos off + +ss.input.port8.mission.b + +ss.input.port8.mission.c + +ss.input.port8.mission.l + +ss.input.port8.mission.r + +ss.input.port8.mission.start + +ss.input.port8.mission.stick_back + +ss.input.port8.mission.stick_fore + +ss.input.port8.mission.stick_left + +ss.input.port8.mission.stick_right + +ss.input.port8.mission.throttle_down + +ss.input.port8.mission.throttle_up + +ss.input.port8.mission.x + +ss.input.port8.mission.y + +ss.input.port8.mission.z + +ss.input.port8.mouse.left mouse 0x0 button_left + +ss.input.port8.mouse.middle mouse 0x0 button_middle + +ss.input.port8.mouse.motion_down mouse 0x0 rel_y+ + +ss.input.port8.mouse.motion_left mouse 0x0 rel_x- + +ss.input.port8.mouse.motion_right mouse 0x0 rel_x+ + +ss.input.port8.mouse.motion_up mouse 0x0 rel_y- + +ss.input.port8.mouse.right mouse 0x0 button_right + +ss.input.port8.mouse.start keyboard 0x0 40 + +ss.input.port8.wheel.a + +ss.input.port8.wheel.analog_left + +ss.input.port8.wheel.analog_right + +ss.input.port8.wheel.b + +ss.input.port8.wheel.c + +ss.input.port8.wheel.down + +ss.input.port8.wheel.start + +ss.input.port8.wheel.up + +ss.input.port8.wheel.x + +ss.input.port8.wheel.y + +ss.input.port8.wheel.z + +ss.input.port9 gamepad + +ss.input.port9.3dpad.a + +ss.input.port9.3dpad.analog_down + +ss.input.port9.3dpad.analog_left + +ss.input.port9.3dpad.analog_right + +ss.input.port9.3dpad.analog_up + +ss.input.port9.3dpad.b + +ss.input.port9.3dpad.c + +ss.input.port9.3dpad.down + +ss.input.port9.3dpad.left + +ss.input.port9.3dpad.ls + +ss.input.port9.3dpad.mode + +ss.input.port9.3dpad.mode.defpos digital + +ss.input.port9.3dpad.right + +ss.input.port9.3dpad.rs + +ss.input.port9.3dpad.start + +ss.input.port9.3dpad.up + +ss.input.port9.3dpad.x + +ss.input.port9.3dpad.y + +ss.input.port9.3dpad.z + +ss.input.port9.dmission.a + +ss.input.port9.dmission.afa + +ss.input.port9.dmission.afa.defpos off + +ss.input.port9.dmission.afb + +ss.input.port9.dmission.afb.defpos off + +ss.input.port9.dmission.afc + +ss.input.port9.dmission.afc.defpos off + +ss.input.port9.dmission.afl + +ss.input.port9.dmission.afl.defpos off + +ss.input.port9.dmission.afr + +ss.input.port9.dmission.afr.defpos off + +ss.input.port9.dmission.afspeed + +ss.input.port9.dmission.afspeed.defpos 1 + +ss.input.port9.dmission.afx + +ss.input.port9.dmission.afx.defpos off + +ss.input.port9.dmission.afy + +ss.input.port9.dmission.afy.defpos off + +ss.input.port9.dmission.afz + +ss.input.port9.dmission.afz.defpos off + +ss.input.port9.dmission.b + +ss.input.port9.dmission.c + +ss.input.port9.dmission.l + +ss.input.port9.dmission.lstick_back + +ss.input.port9.dmission.lstick_fore + +ss.input.port9.dmission.lstick_left + +ss.input.port9.dmission.lstick_right + +ss.input.port9.dmission.lthrottle_down + +ss.input.port9.dmission.lthrottle_up + +ss.input.port9.dmission.r + +ss.input.port9.dmission.rstick_back + +ss.input.port9.dmission.rstick_fore + +ss.input.port9.dmission.rstick_left + +ss.input.port9.dmission.rstick_right + +ss.input.port9.dmission.rthrottle_down + +ss.input.port9.dmission.rthrottle_up + +ss.input.port9.dmission.start + +ss.input.port9.dmission.x + +ss.input.port9.dmission.y + +ss.input.port9.dmission.z + +ss.input.port9.gamepad.a + +ss.input.port9.gamepad.b + +ss.input.port9.gamepad.c + +ss.input.port9.gamepad.down + +ss.input.port9.gamepad.left + +ss.input.port9.gamepad.ls + +ss.input.port9.gamepad.right + +ss.input.port9.gamepad.rs + +ss.input.port9.gamepad.start + +ss.input.port9.gamepad.up + +ss.input.port9.gamepad.x + +ss.input.port9.gamepad.y + +ss.input.port9.gamepad.z + +ss.input.port9.gun.offscreen_shot mouse 0x0 button_right + +ss.input.port9.gun.start mouse 0x0 button_middle + +ss.input.port9.gun.trigger mouse 0x0 button_left + +ss.input.port9.gun.x_axis mouse 0x0 cursor_x-+ + +ss.input.port9.gun.y_axis mouse 0x0 cursor_y-+ + +ss.input.port9.gun_chairs 0xFF80FF + +ss.input.port9.jpkeyboard.0 keyboard 0x0 39 + +ss.input.port9.jpkeyboard.1 keyboard 0x0 30 + +ss.input.port9.jpkeyboard.2 keyboard 0x0 31 + +ss.input.port9.jpkeyboard.3 keyboard 0x0 32 + +ss.input.port9.jpkeyboard.4 keyboard 0x0 33 + +ss.input.port9.jpkeyboard.5 keyboard 0x0 34 + +ss.input.port9.jpkeyboard.6 keyboard 0x0 35 + +ss.input.port9.jpkeyboard.7 keyboard 0x0 36 + +ss.input.port9.jpkeyboard.8 keyboard 0x0 37 + +ss.input.port9.jpkeyboard.9 keyboard 0x0 38 + +ss.input.port9.jpkeyboard.a keyboard 0x0 4 + +ss.input.port9.jpkeyboard.at keyboard 0x0 47 + +ss.input.port9.jpkeyboard.b keyboard 0x0 5 + +ss.input.port9.jpkeyboard.backslash keyboard 0x0 135 + +ss.input.port9.jpkeyboard.backspace keyboard 0x0 42 + +ss.input.port9.jpkeyboard.c keyboard 0x0 6 + +ss.input.port9.jpkeyboard.capslock keyboard 0x0 57 + +ss.input.port9.jpkeyboard.circumflex keyboard 0x0 46 + +ss.input.port9.jpkeyboard.colon keyboard 0x0 52 + +ss.input.port9.jpkeyboard.comma keyboard 0x0 54 + +ss.input.port9.jpkeyboard.conv keyboard 0x0 138 + +ss.input.port9.jpkeyboard.d keyboard 0x0 7 + +ss.input.port9.jpkeyboard.delete keyboard 0x0 76 + +ss.input.port9.jpkeyboard.down keyboard 0x0 81 + +ss.input.port9.jpkeyboard.e keyboard 0x0 8 + +ss.input.port9.jpkeyboard.end keyboard 0x0 77 + +ss.input.port9.jpkeyboard.enter keyboard 0x0 40 + +ss.input.port9.jpkeyboard.esc keyboard 0x0 41 + +ss.input.port9.jpkeyboard.f keyboard 0x0 9 + +ss.input.port9.jpkeyboard.f1 keyboard 0x0 58 + +ss.input.port9.jpkeyboard.f10 keyboard 0x0 67 + +ss.input.port9.jpkeyboard.f11 keyboard 0x0 68 + +ss.input.port9.jpkeyboard.f12 keyboard 0x0 69 + +ss.input.port9.jpkeyboard.f2 keyboard 0x0 59 + +ss.input.port9.jpkeyboard.f3 keyboard 0x0 60 + +ss.input.port9.jpkeyboard.f4 keyboard 0x0 61 + +ss.input.port9.jpkeyboard.f5 keyboard 0x0 62 + +ss.input.port9.jpkeyboard.f6 keyboard 0x0 63 + +ss.input.port9.jpkeyboard.f7 keyboard 0x0 64 + +ss.input.port9.jpkeyboard.f8 keyboard 0x0 65 + +ss.input.port9.jpkeyboard.f9 keyboard 0x0 66 + +ss.input.port9.jpkeyboard.g keyboard 0x0 10 + +ss.input.port9.jpkeyboard.h keyboard 0x0 11 + +ss.input.port9.jpkeyboard.hkr keyboard 0x0 136 + +ss.input.port9.jpkeyboard.home keyboard 0x0 74 + +ss.input.port9.jpkeyboard.hwfw keyboard 0x0 53 + +ss.input.port9.jpkeyboard.i keyboard 0x0 12 + +ss.input.port9.jpkeyboard.insert keyboard 0x0 73 + +ss.input.port9.jpkeyboard.j keyboard 0x0 13 + +ss.input.port9.jpkeyboard.k keyboard 0x0 14 + +ss.input.port9.jpkeyboard.l keyboard 0x0 15 + +ss.input.port9.jpkeyboard.lalt keyboard 0x0 226 + +ss.input.port9.jpkeyboard.lctrl keyboard 0x0 224 + +ss.input.port9.jpkeyboard.left keyboard 0x0 80 + +ss.input.port9.jpkeyboard.leftbracket keyboard 0x0 48 + +ss.input.port9.jpkeyboard.lshift keyboard 0x0 225 + +ss.input.port9.jpkeyboard.m keyboard 0x0 16 + +ss.input.port9.jpkeyboard.minus keyboard 0x0 45 + +ss.input.port9.jpkeyboard.n keyboard 0x0 17 + +ss.input.port9.jpkeyboard.nonconv keyboard 0x0 139 + +ss.input.port9.jpkeyboard.o keyboard 0x0 18 + +ss.input.port9.jpkeyboard.p keyboard 0x0 19 + +ss.input.port9.jpkeyboard.pagedown keyboard 0x0 78 + +ss.input.port9.jpkeyboard.pageup keyboard 0x0 75 + +ss.input.port9.jpkeyboard.pause keyboard 0x0 72 || keyboard 0x0 83 + +ss.input.port9.jpkeyboard.period keyboard 0x0 55 + +ss.input.port9.jpkeyboard.printscreen keyboard 0x0 70 + +ss.input.port9.jpkeyboard.q keyboard 0x0 20 + +ss.input.port9.jpkeyboard.r keyboard 0x0 21 + +ss.input.port9.jpkeyboard.ralt keyboard 0x0 230 + +ss.input.port9.jpkeyboard.rctrl keyboard 0x0 228 + +ss.input.port9.jpkeyboard.right keyboard 0x0 79 + +ss.input.port9.jpkeyboard.rightbracket keyboard 0x0 49 + +ss.input.port9.jpkeyboard.rshift keyboard 0x0 229 + +ss.input.port9.jpkeyboard.s keyboard 0x0 22 + +ss.input.port9.jpkeyboard.scrolllock keyboard 0x0 71 + +ss.input.port9.jpkeyboard.semicolon keyboard 0x0 51 + +ss.input.port9.jpkeyboard.slash keyboard 0x0 56 + +ss.input.port9.jpkeyboard.space keyboard 0x0 44 + +ss.input.port9.jpkeyboard.t keyboard 0x0 23 + +ss.input.port9.jpkeyboard.tab keyboard 0x0 43 + +ss.input.port9.jpkeyboard.u keyboard 0x0 24 + +ss.input.port9.jpkeyboard.up keyboard 0x0 82 + +ss.input.port9.jpkeyboard.v keyboard 0x0 25 + +ss.input.port9.jpkeyboard.w keyboard 0x0 26 + +ss.input.port9.jpkeyboard.x keyboard 0x0 27 + +ss.input.port9.jpkeyboard.y keyboard 0x0 28 + +ss.input.port9.jpkeyboard.yen keyboard 0x0 137 + +ss.input.port9.jpkeyboard.z keyboard 0x0 29 + +ss.input.port9.keyboard.0 keyboard 0x0 39 + +ss.input.port9.keyboard.1 keyboard 0x0 30 + +ss.input.port9.keyboard.2 keyboard 0x0 31 + +ss.input.port9.keyboard.3 keyboard 0x0 32 + +ss.input.port9.keyboard.4 keyboard 0x0 33 + +ss.input.port9.keyboard.5 keyboard 0x0 34 + +ss.input.port9.keyboard.6 keyboard 0x0 35 + +ss.input.port9.keyboard.7 keyboard 0x0 36 + +ss.input.port9.keyboard.8 keyboard 0x0 37 + +ss.input.port9.keyboard.9 keyboard 0x0 38 + +ss.input.port9.keyboard.a keyboard 0x0 4 + +ss.input.port9.keyboard.b keyboard 0x0 5 + +ss.input.port9.keyboard.backslash keyboard 0x0 49 || keyboard 0x0 135 + +ss.input.port9.keyboard.backspace keyboard 0x0 42 + +ss.input.port9.keyboard.c keyboard 0x0 6 + +ss.input.port9.keyboard.capslock keyboard 0x0 57 + +ss.input.port9.keyboard.comma keyboard 0x0 54 + +ss.input.port9.keyboard.d keyboard 0x0 7 + +ss.input.port9.keyboard.delete keyboard 0x0 76 + +ss.input.port9.keyboard.down keyboard 0x0 81 + +ss.input.port9.keyboard.e keyboard 0x0 8 + +ss.input.port9.keyboard.end keyboard 0x0 77 + +ss.input.port9.keyboard.enter keyboard 0x0 40 + +ss.input.port9.keyboard.equals keyboard 0x0 46 + +ss.input.port9.keyboard.esc keyboard 0x0 41 + +ss.input.port9.keyboard.f keyboard 0x0 9 + +ss.input.port9.keyboard.f1 keyboard 0x0 58 + +ss.input.port9.keyboard.f10 keyboard 0x0 67 + +ss.input.port9.keyboard.f11 keyboard 0x0 68 + +ss.input.port9.keyboard.f12 keyboard 0x0 69 + +ss.input.port9.keyboard.f2 keyboard 0x0 59 + +ss.input.port9.keyboard.f3 keyboard 0x0 60 + +ss.input.port9.keyboard.f4 keyboard 0x0 61 + +ss.input.port9.keyboard.f5 keyboard 0x0 62 + +ss.input.port9.keyboard.f6 keyboard 0x0 63 + +ss.input.port9.keyboard.f7 keyboard 0x0 64 + +ss.input.port9.keyboard.f8 keyboard 0x0 65 + +ss.input.port9.keyboard.f9 keyboard 0x0 66 + +ss.input.port9.keyboard.g keyboard 0x0 10 + +ss.input.port9.keyboard.grave keyboard 0x0 53 + +ss.input.port9.keyboard.h keyboard 0x0 11 + +ss.input.port9.keyboard.home keyboard 0x0 74 + +ss.input.port9.keyboard.i keyboard 0x0 12 + +ss.input.port9.keyboard.insert keyboard 0x0 73 + +ss.input.port9.keyboard.j keyboard 0x0 13 + +ss.input.port9.keyboard.k keyboard 0x0 14 + +ss.input.port9.keyboard.kp_asterisk keyboard 0x0 85 + +ss.input.port9.keyboard.kp_center keyboard 0x0 93 + +ss.input.port9.keyboard.kp_delete keyboard 0x0 99 + +ss.input.port9.keyboard.kp_down keyboard 0x0 90 + +ss.input.port9.keyboard.kp_end keyboard 0x0 89 + +ss.input.port9.keyboard.kp_enter keyboard 0x0 88 + +ss.input.port9.keyboard.kp_home keyboard 0x0 95 + +ss.input.port9.keyboard.kp_insert keyboard 0x0 98 + +ss.input.port9.keyboard.kp_left keyboard 0x0 92 + +ss.input.port9.keyboard.kp_minus keyboard 0x0 86 + +ss.input.port9.keyboard.kp_pagedown keyboard 0x0 91 + +ss.input.port9.keyboard.kp_pageup keyboard 0x0 97 + +ss.input.port9.keyboard.kp_plus keyboard 0x0 87 + +ss.input.port9.keyboard.kp_right keyboard 0x0 94 + +ss.input.port9.keyboard.kp_slash keyboard 0x0 84 + +ss.input.port9.keyboard.kp_up keyboard 0x0 96 + +ss.input.port9.keyboard.l keyboard 0x0 15 + +ss.input.port9.keyboard.lalt keyboard 0x0 226 + +ss.input.port9.keyboard.lctrl keyboard 0x0 224 + +ss.input.port9.keyboard.left keyboard 0x0 80 + +ss.input.port9.keyboard.leftbracket keyboard 0x0 47 + +ss.input.port9.keyboard.lshift keyboard 0x0 225 + +ss.input.port9.keyboard.m keyboard 0x0 16 + +ss.input.port9.keyboard.minus keyboard 0x0 45 + +ss.input.port9.keyboard.n keyboard 0x0 17 + +ss.input.port9.keyboard.numlock keyboard 0x0 83 + +ss.input.port9.keyboard.o keyboard 0x0 18 + +ss.input.port9.keyboard.p keyboard 0x0 19 + +ss.input.port9.keyboard.pagedown keyboard 0x0 78 + +ss.input.port9.keyboard.pageup keyboard 0x0 75 + +ss.input.port9.keyboard.pause keyboard 0x0 72 + +ss.input.port9.keyboard.period keyboard 0x0 55 + +ss.input.port9.keyboard.printscreen keyboard 0x0 70 + +ss.input.port9.keyboard.q keyboard 0x0 20 + +ss.input.port9.keyboard.quote keyboard 0x0 52 + +ss.input.port9.keyboard.r keyboard 0x0 21 + +ss.input.port9.keyboard.ralt keyboard 0x0 230 + +ss.input.port9.keyboard.rctrl keyboard 0x0 228 + +ss.input.port9.keyboard.right keyboard 0x0 79 + +ss.input.port9.keyboard.rightbracket keyboard 0x0 48 + +ss.input.port9.keyboard.rshift keyboard 0x0 229 + +ss.input.port9.keyboard.s keyboard 0x0 22 + +ss.input.port9.keyboard.scrolllock keyboard 0x0 71 + +ss.input.port9.keyboard.semicolon keyboard 0x0 51 + +ss.input.port9.keyboard.slash keyboard 0x0 56 + +ss.input.port9.keyboard.space keyboard 0x0 44 + +ss.input.port9.keyboard.t keyboard 0x0 23 + +ss.input.port9.keyboard.tab keyboard 0x0 43 + +ss.input.port9.keyboard.u keyboard 0x0 24 + +ss.input.port9.keyboard.up keyboard 0x0 82 + +ss.input.port9.keyboard.v keyboard 0x0 25 + +ss.input.port9.keyboard.w keyboard 0x0 26 + +ss.input.port9.keyboard.x keyboard 0x0 27 + +ss.input.port9.keyboard.y keyboard 0x0 28 + +ss.input.port9.keyboard.z keyboard 0x0 29 + +ss.input.port9.mission.a + +ss.input.port9.mission.afa + +ss.input.port9.mission.afa.defpos off + +ss.input.port9.mission.afb + +ss.input.port9.mission.afb.defpos off + +ss.input.port9.mission.afc + +ss.input.port9.mission.afc.defpos off + +ss.input.port9.mission.afl + +ss.input.port9.mission.afl.defpos off + +ss.input.port9.mission.afr + +ss.input.port9.mission.afr.defpos off + +ss.input.port9.mission.afspeed + +ss.input.port9.mission.afspeed.defpos 1 + +ss.input.port9.mission.afx + +ss.input.port9.mission.afx.defpos off + +ss.input.port9.mission.afy + +ss.input.port9.mission.afy.defpos off + +ss.input.port9.mission.afz + +ss.input.port9.mission.afz.defpos off + +ss.input.port9.mission.b + +ss.input.port9.mission.c + +ss.input.port9.mission.l + +ss.input.port9.mission.r + +ss.input.port9.mission.start + +ss.input.port9.mission.stick_back + +ss.input.port9.mission.stick_fore + +ss.input.port9.mission.stick_left + +ss.input.port9.mission.stick_right + +ss.input.port9.mission.throttle_down + +ss.input.port9.mission.throttle_up + +ss.input.port9.mission.x + +ss.input.port9.mission.y + +ss.input.port9.mission.z + +ss.input.port9.mouse.left mouse 0x0 button_left + +ss.input.port9.mouse.middle mouse 0x0 button_middle + +ss.input.port9.mouse.motion_down mouse 0x0 rel_y+ + +ss.input.port9.mouse.motion_left mouse 0x0 rel_x- + +ss.input.port9.mouse.motion_right mouse 0x0 rel_x+ + +ss.input.port9.mouse.motion_up mouse 0x0 rel_y- + +ss.input.port9.mouse.right mouse 0x0 button_right + +ss.input.port9.mouse.start keyboard 0x0 40 + +ss.input.port9.wheel.a + +ss.input.port9.wheel.analog_left + +ss.input.port9.wheel.analog_right + +ss.input.port9.wheel.b + +ss.input.port9.wheel.c + +ss.input.port9.wheel.down + +ss.input.port9.wheel.start + +ss.input.port9.wheel.up + +ss.input.port9.wheel.x + +ss.input.port9.wheel.y + +ss.input.port9.wheel.z + +ss.input.sport1.multitap 0 + +ss.input.sport2.multitap 0 + +ss.region_autodetect 1 + +ss.region_default jp + +ss.scanlines 0 + +ss.scsp.resamp_quality 4 + +ss.shader none + +ss.shader.goat.fprog 0 + +ss.shader.goat.hdiv 0.50 + +ss.shader.goat.pat goatron + +ss.shader.goat.slen 1 + +ss.shader.goat.tp 0.50 + +ss.shader.goat.vdiv 0.50 + +ss.slend 239 + +ss.slendp 255 + +ss.slstart 0 + +ss.slstartp 0 + +ss.smpc.autortc 1 + +ss.smpc.autortc.lang english + +ss.special none + +ss.stretch aspect + +ss.tblur 0 + +ss.tblur.accum 0 + +ss.tblur.accum.amount 50 + +ss.videoip 1 + +ss.xres 0 + +ss.xscale 3.000000 + +ss.xscalefs 1.000000 + +ss.yres 0 + +ss.yscale 3.000000 + +ss.yscalefs 1.000000 + +ssfplay.enable 1 + +ssfplay.forcemono 0 + +ssfplay.resamp_quality 4 + +ssfplay.scanlines 0 + +ssfplay.shader none + +ssfplay.shader.goat.fprog 0 + +ssfplay.shader.goat.hdiv 0.50 + +ssfplay.shader.goat.pat goatron + +ssfplay.shader.goat.slen 1 + +ssfplay.shader.goat.tp 0.50 + +ssfplay.shader.goat.vdiv 0.50 + +ssfplay.special none + +ssfplay.stretch aspect + +ssfplay.tblur 0 + +ssfplay.tblur.accum 0 + +ssfplay.tblur.accum.amount 50 + +ssfplay.videoip 0 + +ssfplay.xres 0 + +ssfplay.xscale 2.000000 + +ssfplay.xscalefs 1.000000 + +ssfplay.yres 0 + +ssfplay.yscale 2.000000 + +ssfplay.yscalefs 1.000000 diff --git a/projects/ArchR/packages/emulators/standalone/mednafen/package.mk b/projects/ArchR/packages/emulators/standalone/mednafen/package.mk new file mode 100644 index 0000000000..e255cd7b21 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mednafen/package.mk @@ -0,0 +1,65 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="mednafen" +PKG_VERSION="1.32.1" +PKG_LICENSE="mixed" +PKG_SITE="https://mednafen.github.io/" +# Upstream pull url +#PKG_URL="${PKG_SITE}/releases/files/${PKG_NAME}-${PKG_VERSION}.tar.xz" +# Fork with CHD additions +PKG_URL="https://github.com/sydarn/mednafen/archive/refs/tags/1.32.1-chd.tar.gz" +PKG_DEPENDS_TARGET="toolchain SDL2 flac zstd zlib" +PKG_TOOLCHAIN="configure" + +case ${DEVICE} in + H700|SM8*) + PKG_PATCH_DIRS+=" sdl-input" + ;; +esac + +pre_configure_target() { + +export CFLAGS="${CFLAGS} -flto -fipa-pta" +export CXXFLAGS="${CXXFLAGS} -flto -fipa-pta" +export LDFLAGS="${LDFLAGS} -flto -fipa-pta" + +# unsupported modules +DISABLED_MODULES+=" --disable-apple2 \ + --disable-sasplay \ + --disable-ssfplay" + +case ${DEVICE} in + RK3326|RK3566*|H700) + DISABLED_MODULES+=" --disable-snes \ + --disable-ss \ + --disable-psx" + ;; + RK3399) + DISABLED_MODULES+=" --disable-snes \ + --disable-ss" + ;; + RK3588*) + DISABLED_MODULES+=" --disable-snes" + ;; +esac + +PKG_CONFIGURE_OPTS_TARGET="${DISABLED_MODULES}" +# Need to update automake files + ( + cd .. + sh autogen.sh + ) +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp -rf ${PKG_BUILD}/.${TARGET_NAME}/src/mednafen ${INSTALL}/usr/bin + cp -rf ${PKG_DIR}/scripts/* ${INSTALL}/usr/bin + + chmod +x ${INSTALL}/usr/bin/start_mednafen.sh + chmod +x ${INSTALL}/usr/bin/mednafen_gen_config.sh + + mkdir -p ${INSTALL}/usr/config/${PKG_NAME} + cp ${PKG_DIR}/config/common/* ${INSTALL}/usr/config/${PKG_NAME} +} diff --git a/projects/ArchR/packages/emulators/standalone/mednafen/patches/0001-list-joysticks.patch b/projects/ArchR/packages/emulators/standalone/mednafen/patches/0001-list-joysticks.patch new file mode 100644 index 0000000000..56c281a4a1 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mednafen/patches/0001-list-joysticks.patch @@ -0,0 +1,20 @@ +diff --git a/src/drivers/main.cpp b/src/drivers/main.cpp +index a6f7db2..e69e4c4 100644 +--- a/src/drivers/main.cpp ++++ b/src/drivers/main.cpp +@@ -1980,6 +1980,13 @@ __attribute__((force_align_arg_pointer)) // Not sure what's going on to cause th + #endif + int main(int argc, char *argv[]) + { ++ if(argc == 2) { ++ const char* ljoy = "--list-joysticks"; ++ size_t size = ljoy < argv[1] ? strlen(ljoy) : strlen(argv[1]); ++ if(!strncmp(ljoy, argv[1], size)) ++ JoystickManager::Init(); ++ return 0; ++ } + // SuppressErrorPopups must be set very early. + { + char* mnp = getenv("MEDNAFEN_NOPOPUPS"); +-- +2.39.2 diff --git a/projects/ArchR/packages/emulators/standalone/mednafen/patches/sdl-input/001-force-sdl-joystick.patch b/projects/ArchR/packages/emulators/standalone/mednafen/patches/sdl-input/001-force-sdl-joystick.patch new file mode 100644 index 0000000000..3c872a7d7e --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mednafen/patches/sdl-input/001-force-sdl-joystick.patch @@ -0,0 +1,21 @@ +diff --git a/src/drivers/Joystick.cpp b/src/drivers/Joystick.cpp +index 4944723..978d1bc 100644 +--- a/src/drivers/Joystick.cpp ++++ b/src/drivers/Joystick.cpp +@@ -175,16 +175,7 @@ void Init(void) + + try + { +- #ifdef HAVE_LINUX_JOYSTICK +- main_driver = JoystickDriver_Linux_New(); +- #elif defined(WIN32) +- { +- hicp_driver = JoystickDriver_XInput_New(); +- main_driver = JoystickDriver_DX5_New(hicp_driver != NULL && hicp_driver->NumJoysticks() > 0); +- } +- #elif defined(HAVE_SDL) + main_driver = JoystickDriver_SDL_New(); +- #endif + + if(hicp_driver != NULL) + { diff --git a/projects/ArchR/packages/emulators/standalone/mednafen/scripts/mednafen_gen_config.sh b/projects/ArchR/packages/emulators/standalone/mednafen/scripts/mednafen_gen_config.sh new file mode 100644 index 0000000000..9165eba895 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mednafen/scripts/mednafen_gen_config.sh @@ -0,0 +1,77 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile + +# Generate controller config +# Set controller guid, just take the first one mednafen lists +GUID1="$(mednafen --list-joysticks | grep ID | awk 'NR==1 {print $2}')" +sed -e "s/@GUID1@/${GUID1}/g" ${MEDNAFEN_CONFIG} >> $MEDNAFEN_HOME/mednafen.cfg + +NAME="$(mednafen --list-joysticks | grep ID | awk 'NR==1 {print $5$6}')" +if [[ "$(mednafen --list-joysticks | grep ID | awk 'NR==1 {print $4}')" = "8BitDo" ]] +then +NAME="X-Box360" +fi + +if [[ "${NAME}" = "X-Box360" ]] +then +export DEVICE_FUNC_KEYA_MODIFIER="BTN_THUMBL" +export DEVICE_FUNC_KEYB_MODIFIER="BTN_THUMBR" +fi + +# explcitly override d-pad that are hats, they are somehow randomly mapped as analog in mednafen +if [[ "${NAME}" = "X-Box360" ]] +then +DEVICE_BTN_DPAD_UP="7-" +DEVICE_BTN_DPAD_DOWN="7+" +DEVICE_BTN_DPAD_LEFT="6-" +DEVICE_BTN_DPAD_RIGHT="6+" +elif [[ "${NAME}" = "OSHPB" ]] +then +DEVICE_BTN_DPAD_UP="6-" +DEVICE_BTN_DPAD_DOWN="6+" +DEVICE_BTN_DPAD_LEFT="5-" +DEVICE_BTN_DPAD_RIGHT="5+" +fi + +# Replace modifiers with actual buttons +for MOD in DEVICE_FUNC_KEYA_MODIFIER DEVICE_FUNC_KEYB_MODIFIER +do + sed -i -e "s/${MOD}/DEVICE_${!MOD}/g" $MEDNAFEN_HOME/mednafen.cfg +done + +# If not trigger minus axes, default to same as trigger button +if [[ -z "${DEVICE_BTN_TL2_MINUS}" ]]; then +DEVICE_BTN_TL2_MINUS=${DEVICE_BTN_TL2} +fi +if [[ -z "${DEVICE_BTN_TR2_MINUS}" ]]; then +DEVICE_BTN_TR2_MINUS=${DEVICE_BTN_TR2} +fi +# General case our 098-controller is right, we just need prefixes. First axes that are prefixed with abs_ +for CONTROL in DEVICE_BTN_AL_DOWN DEVICE_BTN_AL_UP DEVICE_BTN_AL_LEFT \ + DEVICE_BTN_AL_RIGHT DEVICE_BTN_AR_DOWN DEVICE_BTN_AR_UP \ + DEVICE_BTN_AR_LEFT DEVICE_BTN_AR_RIGHT \ + DEVICE_BTN_SOUTH DEVICE_BTN_EAST DEVICE_BTN_NORTH \ + DEVICE_BTN_WEST DEVICE_BTN_TL DEVICE_BTN_TR \ + DEVICE_BTN_TL2 DEVICE_BTN_TR2 DEVICE_BTN_SELECT \ + DEVICE_BTN_START DEVICE_BTN_MODE DEVICE_BTN_THUMBL \ + DEVICE_BTN_THUMBR DEVICE_BTN_DPAD_UP DEVICE_BTN_DPAD_DOWN \ + DEVICE_BTN_DPAD_LEFT DEVICE_BTN_DPAD_RIGHT \ + DEVICE_BTN_TL2_MINUS DEVICE_BTN_TR2_MINUS + +do + # Detect axes, and treat appropriately. Default is button + if [[ ${!CONTROL} =~ [+|-]$ ]]; then + sed -i -e "s/@${CONTROL}@/abs_${!CONTROL}/g" $MEDNAFEN_HOME/mednafen.cfg + elif [[ ${!CONTROL} =~ ^[0-9]+$ ]]; then + # if it's just a number its a button + sed -i -e "s/@${CONTROL}@/button_${!CONTROL}/g" $MEDNAFEN_HOME/mednafen.cfg + else + # unidentifiable buttons or non-existent on this pad + # Set a non-consequential value so that we don't get a syntax error in mednafen config + # I randomly picked button_99 here. + sed -i -e "s/@${CONTROL}@/button_99/g" $MEDNAFEN_HOME/mednafen.cfg + fi +done diff --git a/projects/ArchR/packages/emulators/standalone/mednafen/scripts/start_mednafen.sh b/projects/ArchR/packages/emulators/standalone/mednafen/scripts/start_mednafen.sh new file mode 100644 index 0000000000..176885bdc2 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mednafen/scripts/start_mednafen.sh @@ -0,0 +1,240 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile +. /etc/os-release + +set -x +set_kill set "-9 mednafen" + +export MEDNAFEN_HOME=/storage/.config/mednafen +export MEDNAFEN_CONFIG=/usr/config/mednafen/mednafen.template + +if [ ! -d "$MEDNAFEN_HOME" ] +then + mkdir /storage/.config/mednafen +fi + +if [ ! -f "$MEDNAFEN_HOME/mednafen.cfg" ] +then + /usr/bin/bash /usr/bin/mednafen_gen_config.sh +fi + +#Emulation Station Features +GAME=$(echo "${1}"| sed "s#^/.*/##") +CORE=$(echo "${2}"| sed "s#^/.*/##") +PLATFORM=$(echo "${3}"| sed "s#^/.*/##") +STRETCH=$(get_setting stretch "${PLATFORM}" "${GAME}") +SHADER=$(get_setting shader "${PLATFORM}" "${GAME}") + +#Set the cores to use +CORES=$(get_setting "cores" "${PLATFORM}" "${GAME}") +FEATURES_CMDLINE="" +if [ "${CORES}" = "little" ] +then + EMUPERF="${SLOW_CORES}" +elif [ "${CORES}" = "big" ] +then + EMUPERF="${FAST_CORES}" + if [ "${HW_DEVICE}" = "RK3588" ]; then + FEATURES_CMDLINE+=" -affinity.emu 0x30 " + FEATURES_CMDLINE+=" -ss.affinity.vdp2 0xc0 " + elif [ "${HW_DEVICE}" = "RK3399" ]; then + FEATURES_CMDLINE+=" -affinity.emu 0x10 " + FEATURES_CMDLINE+=" -ss.affinity.vdp2 0x20 " + fi +else + ### All.. + unset EMUPERF +fi + +#Set Save paths +sed -i "s/filesys.path_sav .*/filesys.path_sav \/storage\/roms\/${PLATFORM}/g" $MEDNAFEN_HOME/mednafen.cfg +sed -i "s/filesys.path_savbackup.*/filesys.path_savbackup \/storage\/roms\/${PLATFORM}/g" $MEDNAFEN_HOME/mednafen.cfg +sed -i "s/filesys.path_state.*/filesys.path_state \/storage\/roms\/savestates\/${PLATFORM}/g" $MEDNAFEN_HOME/mednafen.cfg + +# Get command line switches +CORRECT_ASPECT=$(get_setting correct_aspect ${PLATFORM} "${GAME}") +CR="" +if [ ! -z "${CORRECT_ASPECT}" ] +then + CR=" -${CORE}.correct_aspect ${CORRECT_ASPECT}" +fi +if [[ "${CORE}" =~ pce[_fast] ]] +then + if [ "$(get_setting nospritelimit ${PLATFORM} "${GAME}")" = "1" ] + then + FEATURES_CMDLINE+=" -${CORE}.nospritelimit 1" + else + FEATURES_CMDLINE+=" -${CORE}.nospritelimit 0" + fi + if [ "$(get_setting forcesgx ${PLATFORM} "${GAME}")" = "1" ] + then + FEATURES_CMDLINE+=" -${CORE}.forcesgx 1" + else + FEATURES_CMDLINE+=" -${CORE}.forcesgx 0" + fi + if [ "${CORE}" = pce_fast ] + then + FEATURES_CMDLINE+=$CR + OCM=$(get_setting ocmultiplier ${PLATFORM} "${GAME}") + if [ ${OCM} > 1 ] + then + FEATURES_CMDLINE+=" -${CORE}.ocmultiplier ${OCM}" + else + FEATURES_CMDLINE+=" -${CORE}.ocmultiplier 1" + fi + CDS=$(get_setting cdspeed ${PLATFORM} "${GAME}") + if [ ${CDS} > 1 ] + then + FEATURES_CMDLINE+=" -${CORE}.cdspeed ${CDS}" + else + FEATURES_CMDLINE+=" -${CORE}.cdspeed 1" + fi + fi +elif [ "${CORE}" = "gb" ] +then + ST=$(get_setting system_type "${PLATFORM}" "${GAME}") + if [[ "${ST}" =~ auto|dmg|cgb|agb ]] + then + FEATURES_CMDLINE+=" -${CORE}.system_type ${ST}" + else + FEATURES_CMDLINE+=" -${CORE}.system_type auto" + fi +elif [ "${CORE}" = "gba" ] +then + if [ $(get_setting tblur "${PLATFORM}" "${GAME}") = "1" ] + then + FEATURES_CMDLINE+=" -${CORE}.tblur 1" + else + FEATURES_CMDLINE+=" -${CORE}.tblur 0" + fi +elif [ "${CORE}" = "nes" ] +then + FEATURES_CMDLINE+=$CR + if [ $(get_setting clipsides "${PLATFORM}" "${GAME}") = "1" ] + then + FEATURES_CMDLINE+=" -${CORE}.clipsides 1" + else + FEATURES_CMDLINE+=" -${CORE}.clipsides 0" + fi + if [ $(get_setting no8lim "${PLATFORM}" "${GAME}") = "1" ] + then + FEATURES_CMDLINE+=" -${CORE}.no8lim 1" + else + FEATURES_CMDLINE+=" -${CORE}.no8lim 0" + fi +elif [ "${CORE}" = "snes_faust" ] +then + FEATURES_CMDLINE+=$CR + if [ $(get_setting spex "${PLATFORM}" "${GAME}") = "1" ] + then + FEATURES_CMDLINE+=" -${CORE}.spex 1" + else + FEATURES_CMDLINE+=" -${CORE}.spex 0" + fi + if [ $(get_setting spex.sound "${PLATFORM}" "${GAME}") = "1" ] + then + FEATURES_CMDLINE+=" -${CORE}.spex.sound 1" + else + FEATURES_CMDLINE+=" -${CORE}.spex.sound 0" + fi + SFXCR=$(get_setting superfx.clock_rate ${PLATFORM} "${GAME}") + if [ ${SFXCR} > 1 ] + then + FEATURES_CMDLINE+=" -${CORE}.superfx.clock_rate ${SFXCR}" + else + FEATURES_CMDLINE+=" -${CORE}.superfx.clock_rate 100" + fi + if [[ "$(get_setting superfx.icache ${PLATFORM} "${GAME}")" == "1" ]] + then + FEATURES_CMDLINE+=" -${CORE}.superfx.icache 1" + else + FEATURES_CMDLINE+=" -${CORE}.superfx.icache 0" + fi + CX4CR=$(get_setting cx4.clock_rate ${PLATFORM} "${GAME}") + if [ ${CX4CR} > 1 ] + then + FEATURES_CMDLINE+=" -${CORE}.cx4.clock_rate ${CX4CR}" + else + FEATURES_CMDLINE+=" -${CORE}.cx4.clock_rate 100" + fi +elif [ "${CORE}" = "vb" ] +then + CE=$(get_setting cpu_emulation "${PLATFORM}" "${GAME}") + if [[ "${CE}" =~ fast|accurate ]] + then + FEATURES_CMDLINE+=" -${CORE}.cpu_emulation ${CE}" + else + FEATURES_CMDLINE+=" -${CORE}.cpu_emulation fast" + fi + DM=$(get_setting 3dmode "${PLATFORM}" "${GAME}") + if [[ "${DM}" =~ anaglyph|cscope|sidebyside|vli|hli|left|right] ]] + then + FEATURES_CMDLINE+=" -${CORE}.3dmode ${CE}" + fi +elif [ "${CORE}" = "pcfx" ] +then + CE=$(get_setting cpu_emulation "${PLATFORM}" "${GAME}") + if [[ "${CE}" =~ auto|fast|accurate ]] + then + FEATURES_CMDLINE+=" -${CORE}.cpu_emulation ${CE}" + else + FEATURES_CMDLINE+=" -${CORE}.cpu_emulation auto" + fi + CS=$(get_setting cdspeed "${PLATFORM}" "${GAME}") + if [ CS > 2] + then + FEATURES_CMDLINE+=" -${CORE}.cdspeed ${CS}" + else + FEATURES_CMDLINE+=" -${CORE}.cdspeed 2" + fi +elif [ "${CORE}" = "ss" ] +then + FEATURES_CMDLINE+=$CR + IP1=$(get_setting input.port1 "${PLATFORM}" "${GAME}") + if [[ "${IP1}" =~ gamepad|3dpad|gun ]] + then + FEATURES_CMDLINE+=" -${CORE}.input.port1 ${IP1}" + else + FEATURES_CMDLINE+=" -${CORE}.input.port1 gamepad" + fi + IP13DMODE=$(get_setting input.port1.3dpad.mode.defpos "${PLATFORM}" "${GAME}") + if [[ "${IP13DMODE}" =~ digital|analog ]] + then + FEATURES_CMDLINE+=" -${CORE}.input.port1.3dpad.mode.defpos ${IP13DMODE}" + else + FEATURES_CMDLINE+=" -${CORE}.input.port1.3dpad.mode.defpos analog" + fi + CART=$(get_setting cart "${PLATFORM}" "${GAME}") + if [[ "${CART}" =~ auto|none|backup|extram1|extram4|cs1ram16 ]] + then + FEATURES_CMDLINE+=" -${CORE}.cart ${CART}" + else + FEATURES_CMDLINE+=" -${CORE}.cart auto" + fi + CARTAD=$(get_setting cart.auto_default "${PLATFORM}" "${GAME}") + if [[ "${CARTAD}" =~ none|backup|extram1|extram4|cs1ram16 ]] + then + FEATURES_CMDLINE+=" -${CORE}.cart.auto_default ${CARTAD}" + else + FEATURES_CMDLINE+=" -${CORE}.cart.auto_default none" + fi +elif [ "${CORE}" = "md" ] +then + FEATURES_CMDLINE+=$CR +elif [ "${CORE}" = "psx" ] +then + FEATURES_CMDLINE+=$CR + IP1=$(get_setting input.port1 "${PLATFORM}" "${GAME}") + if [[ "${IP1}" =~ gamepad|dualshock ]] + then + FEATURES_CMDLINE+=" -${CORE}.input.port1 ${IP1}" + else + FEATURES_CMDLINE+=" -${CORE}.input.port1 gamepad" + fi +fi + +#Run mednafen +${EMUPERF} /usr/bin/mednafen -force_module ${CORE} -${CORE}.stretch ${STRETCH:="aspect"} -${CORE}.shader ${SHADER:="ipsharper"} ${FEATURES_CMDLINE} "${1}" diff --git a/projects/ArchR/packages/emulators/standalone/melonds-sa/config/InputPlumber/melonDS.ini b/projects/ArchR/packages/emulators/standalone/melonds-sa/config/InputPlumber/melonDS.ini new file mode 100644 index 0000000000..36fb65fba3 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/melonds-sa/config/InputPlumber/melonDS.ini @@ -0,0 +1,157 @@ +Key_A=-1 +Key_B=-1 +Key_Select=-1 +Key_Start=-1 +Key_Right=-1 +Key_Left=-1 +Key_Up=-1 +Key_Down=-1 +Key_R=-1 +Key_L=-1 +Key_X=-1 +Key_Y=-1 +Joy_A=1 +Joy_B=0 +Joy_Select=6 +Joy_Start=7 +Joy_Right=65550 +Joy_Left=1114125 +Joy_Up=17891339 +Joy_Down=16842764 +Joy_R=5 +Joy_L=4 +Joy_X=2 +Joy_Y=3 +HKKey_Lid=-1 +HKKey_Mic=-1 +HKKey_Pause=-1 +HKKey_Reset=-1 +HKKey_FastForward=-1 +HKKey_FastForwardToggle=70 +HKKey_FullscreenToggle=-1 +HKKey_SwapScreens=-1 +HKKey_SwapScreenEmphasis=-1 +HKKey_SolarSensorDecrease=-1 +HKKey_SolarSensorIncrease=-1 +HKKey_FrameStep=-1 +HKKey_PowerButton=-1 +HKKey_VolumeUp=-1 +HKKey_VolumeDown=-1 +HKKey_SaveState=83 +HKKey_LoadState=76 +HKJoy_Lid=-1 +HKJoy_Mic=-1 +HKJoy_Pause=-1 +HKJoy_Reset=-1 +HKJoy_FastForward=-1 +HKJoy_FastForwardToggle=-1 +HKJoy_FullscreenToggle=-1 +HKJoy_SwapScreens=15 +HKJoy_SwapScreenEmphasis=-1 +HKJoy_SolarSensorDecrease=-1 +HKJoy_SolarSensorIncrease=-1 +HKJoy_FrameStep=-1 +HKJoy_PowerButton=-1 +HKJoy_VolumeUp=-1 +HKJoy_VolumeDown=-1 +HKJoy_SaveState=-1 +HKJoy_LoadState=-1 +JoystickID=0 +WindowWidth=1920 +WindowHeight=1080 +WindowMax=0 +ScreenRotation=0 +ScreenGap=0 +ScreenLayout=2 +ScreenSwap=1 +ScreenSizing=0 +IntegerScaling=0 +ScreenAspectTop=0 +ScreenAspectBot=0 +ScreenFilter=1 +ScreenUseGL=1 +ScreenVSync=0 +ScreenVSyncInterval=1 +3DRenderer=0 +Threaded3D=1 +GL_ScaleFactor=1 +GL_BetterPolygons=0 +LimitFPS=1 +AudioSync=0 +ShowOSD=1 +ConsoleType=0 +DirectBoot=1 +JIT_Enable=0 +JIT_MaxBlockSize=32 +JIT_BranchOptimisations=1 +JIT_LiteralOptimisations=1 +JIT_FastMemory=1 +ExternalBIOSEnable=0 +BIOS9Path=/storage/roms/bios/bios9.bin +BIOS7Path=/storage/roms/bios/bios7.bin +FirmwarePath=/storage/roms/bios/firmware.bin +DSiBIOS9Path=/storage/roms/bios/dsi_bios9.bin +DSiBIOS7Path=/storage/roms/bios/dsi_bios7.bin +DSiFirmwarePath=/storage/roms/bios/dsi_firmware.bin +DSiNANDPath=/storage/roms/bios/dsi_nand.bin +DLDIEnable=0 +DLDISDPath=dldi.bin +DLDISize=0 +DLDIReadOnly=0 +DLDIFolderSync=0 +DLDIFolderPath= +DSiSDEnable=0 +DSiSDPath=dsisd.bin +DSiSDSize=0 +DSiSDReadOnly=0 +DSiSDFolderSync=0 +DSiSDFolderPath= +FirmwareOverrideSettings=0 +FirmwareUsername=melonDS +FirmwareLanguage=1 +FirmwareBirthdayMonth=1 +FirmwareBirthdayDay=1 +FirmwareFavouriteColour=0 +FirmwareMessage= +FirmwareMAC= +MPAudioMode=1 +MPRecvTimeout=25 +LANDevice= +DirectLAN=0 +SavStaRelocSRAM=0 +AudioInterp=0 +AudioBitrate=0 +AudioVolume=256 +DSiVolumeSync=0 +MicInputType=0 +MicWavPath= +LastROMFolder= +LastBIOSFolder= +RecentROM_0= +RecentROM_1= +RecentROM_2= +RecentROM_3= +RecentROM_4= +RecentROM_5= +RecentROM_6= +RecentROM_7= +RecentROM_8= +RecentROM_9= +SaveFilePath=/storage/roms/nds +SavestatePath=/storage/roms/savestates/nds +CheatFilePath= +EnableCheats=0 +MouseHide=0 +MouseHideSeconds=5 +PauseLostFocus=0 +DSBatteryLevelOkay=1 +DSiBatteryLevel=15 +DSiBatteryCharging=1 +Camera0_InputType=0 +Camera0_ImagePath= +Camera0_CamDeviceName= +Camera0_XFlip=0 +Camera1_InputType=0 +Camera1_ImagePath= +Camera1_CamDeviceName= +Camera1_XFlip=0 diff --git a/projects/ArchR/packages/emulators/standalone/melonds-sa/config/RK3326/melonDS.ini b/projects/ArchR/packages/emulators/standalone/melonds-sa/config/RK3326/melonDS.ini new file mode 100644 index 0000000000..94aef69e8a --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/melonds-sa/config/RK3326/melonDS.ini @@ -0,0 +1,160 @@ +Key_A=-1 +Key_B=-1 +Key_Select=-1 +Key_Start=-1 +Key_Right=-1 +Key_Left=-1 +Key_Up=-1 +Key_Down=-1 +Key_R=-1 +Key_L=-1 +Key_X=-1 +Key_Y=-1 +Joy_A=1 +Joy_B=0 +Joy_Select=8 +Joy_Start=9 +Joy_Right=65552 +Joy_Left=1114127 +Joy_Up=17891341 +Joy_Down=16842766 +Joy_R=5 +Joy_L=4 +Joy_X=2 +Joy_Y=3 +HKKey_Lid=-1 +HKKey_Mic=-1 +HKKey_Pause=-1 +HKKey_Reset=-1 +HKKey_FastForward=-1 +HKKey_FastForwardToggle=70 +HKKey_FullscreenToggle=-1 +HKKey_SwapScreens=-1 +HKKey_SwapScreenEmphasis=-1 +HKKey_SolarSensorDecrease=-1 +HKKey_SolarSensorIncrease=-1 +HKKey_FrameStep=-1 +HKKey_PowerButton=-1 +HKKey_VolumeUp=-1 +HKKey_VolumeDown=-1 +HKKey_SaveState=83 +HKKey_LoadState=76 +HKJoy_Lid=-1 +HKJoy_Mic=-1 +HKJoy_Pause=-1 +HKJoy_Reset=-1 +HKJoy_FastForward=-1 +HKJoy_FastForwardToggle=-1 +HKJoy_FullscreenToggle=-1 +HKJoy_SwapScreens=11 +HKJoy_SwapScreenEmphasis=-1 +HKJoy_SolarSensorDecrease=-1 +HKJoy_SolarSensorIncrease=-1 +HKJoy_FrameStep=-1 +HKJoy_PowerButton=-1 +HKJoy_VolumeUp=-1 +HKJoy_VolumeDown=-1 +HKJoy_SaveState=-1 +HKJoy_LoadState=-1 +JoystickID=0 +WindowWidth=640 +WindowHeight=480 +WindowMax=0 +ScreenRotation=0 +ScreenGap=0 +ScreenLayout=2 +ScreenSwap=1 +ScreenSizing=0 +Screen1Layout=2 +Screen1Enabled=false +Screen1Sizing=5 +IntegerScaling=0 +ScreenAspectTop=0 +ScreenAspectBot=0 +ScreenFilter=0 +ScreenUseGL=0 +ScreenVSync=0 +ScreenVSyncInterval=1 +3DRenderer=0 +Threaded3D=1 +GL_ScaleFactor=1 +GL_BetterPolygons=0 +LimitFPS=1 +AudioSync=0 +ShowOSD=0 +ConsoleType=0 +DirectBoot=1 +JIT_Enable=1 +JIT_MaxBlockSize=32 +JIT_BranchOptimisations=1 +JIT_LiteralOptimisations=1 +JIT_FastMemory=1 +ExternalBIOSEnable=0 +BIOS9Path=/storage/roms/bios/bios9.bin +BIOS7Path=/storage/roms/bios/bios7.bin +FirmwarePath=/storage/roms/bios/firmware.bin +DSiBIOS9Path=/storage/roms/bios/dsi_bios9.bin +DSiBIOS7Path=/storage/roms/bios/dsi_bios7.bin +DSiFirmwarePath=/storage/roms/bios/dsi_firmware.bin +DSiNANDPath=/storage/roms/bios/dsi_nand.bin +DLDIEnable=0 +DLDISDPath=dldi.bin +DLDISize=0 +DLDIReadOnly=0 +DLDIFolderSync=0 +DLDIFolderPath= +DSiSDEnable=0 +DSiSDPath=dsisd.bin +DSiSDSize=0 +DSiSDReadOnly=0 +DSiSDFolderSync=0 +DSiSDFolderPath= +FirmwareOverrideSettings=0 +FirmwareUsername=melonDS +FirmwareLanguage=1 +FirmwareBirthdayMonth=1 +FirmwareBirthdayDay=1 +FirmwareFavouriteColour=0 +FirmwareMessage= +FirmwareMAC= +MPAudioMode=1 +MPRecvTimeout=25 +LANDevice= +DirectLAN=0 +SavStaRelocSRAM=0 +AudioInterp=0 +AudioBitrate=0 +AudioVolume=256 +DSiVolumeSync=0 +MicInputType=0 +MicWavPath= +LastROMFolder= +LastBIOSFolder= +RecentROM_0= +RecentROM_1= +RecentROM_2= +RecentROM_3= +RecentROM_4= +RecentROM_5= +RecentROM_6= +RecentROM_7= +RecentROM_8= +RecentROM_9= +SaveFilePath=/storage/roms/nds +SavestatePath=/storage/roms/savestates/nds +CheatFilePath= +EnableCheats=0 +MouseHide=1 +MouseHideSeconds=1 +PauseLostFocus=0 +DSBatteryLevelOkay=1 +DSiBatteryLevel=15 +DSiBatteryCharging=1 +Camera0_InputType=0 +Camera0_ImagePath= +Camera0_CamDeviceName= +Camera0_XFlip=0 +Camera1_InputType=0 +Camera1_ImagePath= +Camera1_CamDeviceName= +Camera1_XFlip=0 diff --git a/projects/ArchR/packages/emulators/standalone/melonds-sa/config/RK3399/melonDS.ini b/projects/ArchR/packages/emulators/standalone/melonds-sa/config/RK3399/melonDS.ini new file mode 100644 index 0000000000..0bdc8ac05e --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/melonds-sa/config/RK3399/melonDS.ini @@ -0,0 +1,160 @@ +Key_A=-1 +Key_B=-1 +Key_Select=-1 +Key_Start=-1 +Key_Right=-1 +Key_Left=-1 +Key_Up=-1 +Key_Down=-1 +Key_R=-1 +Key_L=-1 +Key_X=-1 +Key_Y=-1 +Joy_A=1 +Joy_B=0 +Joy_Select=8 +Joy_Start=9 +Joy_Right=65552 +Joy_Left=1114127 +Joy_Up=17891341 +Joy_Down=16842766 +Joy_R=5 +Joy_L=4 +Joy_X=2 +Joy_Y=3 +HKKey_Lid=-1 +HKKey_Mic=-1 +HKKey_Pause=-1 +HKKey_Reset=-1 +HKKey_FastForward=-1 +HKKey_FastForwardToggle=70 +HKKey_FullscreenToggle=-1 +HKKey_SwapScreens=-1 +HKKey_SwapScreenEmphasis=-1 +HKKey_SolarSensorDecrease=-1 +HKKey_SolarSensorIncrease=-1 +HKKey_FrameStep=-1 +HKKey_PowerButton=-1 +HKKey_VolumeUp=-1 +HKKey_VolumeDown=-1 +HKKey_SaveState=83 +HKKey_LoadState=76 +HKJoy_Lid=-1 +HKJoy_Mic=-1 +HKJoy_Pause=-1 +HKJoy_Reset=-1 +HKJoy_FastForward=-1 +HKJoy_FastForwardToggle=-1 +HKJoy_FullscreenToggle=-1 +HKJoy_SwapScreens=11 +HKJoy_SwapScreenEmphasis=-1 +HKJoy_SolarSensorDecrease=-1 +HKJoy_SolarSensorIncrease=-1 +HKJoy_FrameStep=-1 +HKJoy_PowerButton=-1 +HKJoy_VolumeUp=-1 +HKJoy_VolumeDown=-1 +HKJoy_SaveState=-1 +HKJoy_LoadState=-1 +JoystickID=0 +WindowWidth=1920 +WindowHeight=1152 +WindowMax=0 +ScreenRotation=0 +ScreenGap=0 +ScreenLayout=2 +ScreenSwap=1 +ScreenSizing=0 +Screen1Layout=2 +Screen1Enabled=false +Screen1Sizing=5 +IntegerScaling=0 +ScreenAspectTop=0 +ScreenAspectBot=0 +ScreenFilter=1 +ScreenUseGL=1 +ScreenVSync=0 +ScreenVSyncInterval=1 +3DRenderer=0 +Threaded3D=1 +GL_ScaleFactor=1 +GL_BetterPolygons=0 +LimitFPS=1 +AudioSync=0 +ShowOSD=1 +ConsoleType=0 +DirectBoot=1 +JIT_Enable=0 +JIT_MaxBlockSize=32 +JIT_BranchOptimisations=1 +JIT_LiteralOptimisations=1 +JIT_FastMemory=1 +ExternalBIOSEnable=0 +BIOS9Path=/storage/roms/bios/bios9.bin +BIOS7Path=/storage/roms/bios/bios7.bin +FirmwarePath=/storage/roms/bios/firmware.bin +DSiBIOS9Path=/storage/roms/bios/dsi_bios9.bin +DSiBIOS7Path=/storage/roms/bios/dsi_bios7.bin +DSiFirmwarePath=/storage/roms/bios/dsi_firmware.bin +DSiNANDPath=/storage/roms/bios/dsi_nand.bin +DLDIEnable=0 +DLDISDPath=dldi.bin +DLDISize=0 +DLDIReadOnly=0 +DLDIFolderSync=0 +DLDIFolderPath= +DSiSDEnable=0 +DSiSDPath=dsisd.bin +DSiSDSize=0 +DSiSDReadOnly=0 +DSiSDFolderSync=0 +DSiSDFolderPath= +FirmwareOverrideSettings=0 +FirmwareUsername=melonDS +FirmwareLanguage=1 +FirmwareBirthdayMonth=1 +FirmwareBirthdayDay=1 +FirmwareFavouriteColour=0 +FirmwareMessage= +FirmwareMAC= +MPAudioMode=1 +MPRecvTimeout=25 +LANDevice= +DirectLAN=0 +SavStaRelocSRAM=0 +AudioInterp=0 +AudioBitrate=0 +AudioVolume=256 +DSiVolumeSync=0 +MicInputType=0 +MicWavPath= +LastROMFolder= +LastBIOSFolder= +RecentROM_0= +RecentROM_1= +RecentROM_2= +RecentROM_3= +RecentROM_4= +RecentROM_5= +RecentROM_6= +RecentROM_7= +RecentROM_8= +RecentROM_9= +SaveFilePath=/storage/roms/nds +SavestatePath=/storage/roms/savestates/nds +CheatFilePath= +EnableCheats=0 +MouseHide=0 +MouseHideSeconds=5 +PauseLostFocus=0 +DSBatteryLevelOkay=1 +DSiBatteryLevel=15 +DSiBatteryCharging=1 +Camera0_InputType=0 +Camera0_ImagePath= +Camera0_CamDeviceName= +Camera0_XFlip=0 +Camera1_InputType=0 +Camera1_ImagePath= +Camera1_CamDeviceName= +Camera1_XFlip=0 diff --git a/projects/ArchR/packages/emulators/standalone/melonds-sa/config/RK3566/melonDS.ini b/projects/ArchR/packages/emulators/standalone/melonds-sa/config/RK3566/melonDS.ini new file mode 100644 index 0000000000..3e1ecce8e4 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/melonds-sa/config/RK3566/melonDS.ini @@ -0,0 +1,160 @@ +Key_A=-1 +Key_B=-1 +Key_Select=-1 +Key_Start=-1 +Key_Right=-1 +Key_Left=-1 +Key_Up=-1 +Key_Down=-1 +Key_R=-1 +Key_L=-1 +Key_X=-1 +Key_Y=-1 +Joy_A=1 +Joy_B=0 +Joy_Select=8 +Joy_Start=9 +Joy_Right=65552 +Joy_Left=1114127 +Joy_Up=17891341 +Joy_Down=16842766 +Joy_R=5 +Joy_L=4 +Joy_X=2 +Joy_Y=3 +HKKey_Lid=-1 +HKKey_Mic=-1 +HKKey_Pause=-1 +HKKey_Reset=-1 +HKKey_FastForward=-1 +HKKey_FastForwardToggle=-1 +HKKey_FullscreenToggle=-1 +HKKey_SwapScreens=-1 +HKKey_SwapScreenEmphasis=-1 +HKKey_SolarSensorDecrease=-1 +HKKey_SolarSensorIncrease=-1 +HKKey_FrameStep=-1 +HKKey_PowerButton=-1 +HKKey_VolumeUp=-1 +HKKey_VolumeDown=-1 +HKKey_SaveState=-1 +HKKey_LoadState=-1 +HKJoy_Lid=-1 +HKJoy_Mic=-1 +HKJoy_Pause=-1 +HKJoy_Reset=-1 +HKJoy_FastForward=-1 +HKJoy_FastForwardToggle=-1 +HKJoy_FullscreenToggle=-1 +HKJoy_SwapScreens=11 +HKJoy_SwapScreenEmphasis=-1 +HKJoy_SolarSensorDecrease=-1 +HKJoy_SolarSensorIncrease=-1 +HKJoy_FrameStep=-1 +HKJoy_PowerButton=-1 +HKJoy_VolumeUp=-1 +HKJoy_VolumeDown=-1 +HKJoy_SaveState=7 +HKJoy_LoadState=6 +JoystickID=0 +WindowWidth=1920 +WindowHeight=1152 +WindowMax=0 +ScreenRotation=0 +ScreenGap=0 +ScreenLayout=2 +ScreenSwap=1 +ScreenSizing=0 +Screen1Layout=2 +Screen1Enabled=false +Screen1Sizing=5 +IntegerScaling=0 +ScreenAspectTop=0 +ScreenAspectBot=0 +ScreenFilter=1 +ScreenUseGL=1 +ScreenVSync=0 +ScreenVSyncInterval=1 +3DRenderer=0 +Threaded3D=1 +GL_ScaleFactor=1 +GL_BetterPolygons=0 +LimitFPS=1 +AudioSync=0 +ShowOSD=1 +ConsoleType=0 +DirectBoot=1 +JIT_Enable=1 +JIT_MaxBlockSize=32 +JIT_BranchOptimisations=1 +JIT_LiteralOptimisations=1 +JIT_FastMemory=1 +ExternalBIOSEnable=0 +BIOS9Path=/storage/roms/bios/bios9.bin +BIOS7Path=/storage/roms/bios/bios7.bin +FirmwarePath=/storage/roms/bios/firmware.bin +DSiBIOS9Path=/storage/roms/bios/dsi_bios9.bin +DSiBIOS7Path=/storage/roms/bios/dsi_bios7.bin +DSiFirmwarePath=/storage/roms/bios/dsi_firmware.bin +DSiNANDPath=/storage/roms/bios/dsi_nand.bin +DLDIEnable=0 +DLDISDPath=dldi.bin +DLDISize=0 +DLDIReadOnly=0 +DLDIFolderSync=0 +DLDIFolderPath= +DSiSDEnable=0 +DSiSDPath=dsisd.bin +DSiSDSize=0 +DSiSDReadOnly=0 +DSiSDFolderSync=0 +DSiSDFolderPath= +FirmwareOverrideSettings=0 +FirmwareUsername=melonDS +FirmwareLanguage=1 +FirmwareBirthdayMonth=1 +FirmwareBirthdayDay=1 +FirmwareFavouriteColour=0 +FirmwareMessage= +FirmwareMAC= +MPAudioMode=1 +MPRecvTimeout=25 +LANDevice= +DirectLAN=0 +SavStaRelocSRAM=0 +AudioInterp=0 +AudioBitrate=0 +AudioVolume=256 +DSiVolumeSync=0 +MicInputType=0 +MicWavPath= +LastROMFolder= +LastBIOSFolder= +RecentROM_0= +RecentROM_1= +RecentROM_2= +RecentROM_3= +RecentROM_4= +RecentROM_5= +RecentROM_6= +RecentROM_7= +RecentROM_8= +RecentROM_9= +SaveFilePath=/storage/roms/nds +SavestatePath=/storage/roms/savestates/nds +CheatFilePath= +EnableCheats=0 +MouseHide=0 +MouseHideSeconds=5 +PauseLostFocus=0 +DSBatteryLevelOkay=1 +DSiBatteryLevel=15 +DSiBatteryCharging=1 +Camera0_InputType=0 +Camera0_ImagePath= +Camera0_CamDeviceName= +Camera0_XFlip=0 +Camera1_InputType=0 +Camera1_ImagePath= +Camera1_CamDeviceName= +Camera1_XFlip=0 diff --git a/projects/ArchR/packages/emulators/standalone/melonds-sa/config/RK3588/melonDS.ini b/projects/ArchR/packages/emulators/standalone/melonds-sa/config/RK3588/melonDS.ini new file mode 100644 index 0000000000..6fd5e441c3 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/melonds-sa/config/RK3588/melonDS.ini @@ -0,0 +1,160 @@ +Key_A=-1 +Key_B=-1 +Key_Select=-1 +Key_Start=-1 +Key_Right=-1 +Key_Left=-1 +Key_Up=-1 +Key_Down=-1 +Key_R=-1 +Key_L=-1 +Key_X=-1 +Key_Y=-1 +Joy_A=1 +Joy_B=0 +Joy_Select=7 +Joy_Start=8 +Joy_Right=16842767 +Joy_Left=17891342 +Joy_Up=65548 +Joy_Down=1114125 +Joy_R=85065727 +Joy_L=34734079 +Joy_X=3 +Joy_Y=4 +HKKey_Lid=-1 +HKKey_Mic=77 +HKKey_Pause=-1 +HKKey_Reset=-1 +HKKey_FastForward=70 +HKKey_FastForwardToggle=-1 +HKKey_FullscreenToggle=-1 +HKKey_SwapScreens=-1 +HKKey_SwapScreenEmphasis=-1 +HKKey_SolarSensorDecrease=-1 +HKKey_SolarSensorIncrease=-1 +HKKey_FrameStep=-1 +HKKey_PowerButton=-1 +HKKey_VolumeUp=-1 +HKKey_VolumeDown=-1 +HKKey_SaveState=83 +HKKey_LoadState=76 +HKJoy_Lid=-1 +HKJoy_Mic=-1 +HKJoy_Pause=-1 +HKJoy_Reset=-1 +HKJoy_FastForward=-1 +HKJoy_FastForwardToggle=-1 +HKJoy_FullscreenToggle=-1 +HKJoy_SwapScreens=2 +HKJoy_SwapScreenEmphasis=-1 +HKJoy_SolarSensorDecrease=-1 +HKJoy_SolarSensorIncrease=-1 +HKJoy_FrameStep=-1 +HKJoy_PowerButton=-1 +HKJoy_VolumeUp=-1 +HKJoy_VolumeDown=-1 +HKJoy_SaveState=-1 +HKJoy_LoadState=-1 +JoystickID=0 +WindowWidth=1920 +WindowHeight=1080 +WindowMax=0 +ScreenRotation=0 +ScreenGap=0 +ScreenLayout=2 +ScreenSwap=0 +ScreenSizing=3 +Screen1Layout=2 +Screen1Enabled=false +Screen1Sizing=5 +IntegerScaling=0 +ScreenAspectTop=0 +ScreenAspectBot=0 +ScreenFilter=1 +ScreenUseGL=0 +ScreenVSync=0 +ScreenVSyncInterval=1 +3DRenderer=0 +Threaded3D=1 +GL_ScaleFactor=1 +GL_BetterPolygons=0 +LimitFPS=1 +AudioSync=0 +ShowOSD=1 +ConsoleType=0 +DirectBoot=1 +JIT_Enable=0 +JIT_MaxBlockSize=32 +JIT_BranchOptimisations=1 +JIT_LiteralOptimisations=1 +JIT_FastMemory=1 +ExternalBIOSEnable=0 +BIOS9Path=/storage/roms/bios/bios9.bin +BIOS7Path=/storage/roms/bios/bios7.bin +FirmwarePath=/storage/roms/bios/firmware.bin +DSiBIOS9Path=/storage/roms/bios/dsi_bios9.bin +DSiBIOS7Path=/storage/roms/bios/dsi_bios7.bin +DSiFirmwarePath=/storage/roms/bios/dsi_firmware.bin +DSiNANDPath=/storage/roms/bios/dsi_nand.bin +DLDIEnable=0 +DLDISDPath=dldi.bin +DLDISize=0 +DLDIReadOnly=0 +DLDIFolderSync=0 +DLDIFolderPath= +DSiSDEnable=0 +DSiSDPath=dsisd.bin +DSiSDSize=0 +DSiSDReadOnly=0 +DSiSDFolderSync=0 +DSiSDFolderPath= +FirmwareOverrideSettings=0 +FirmwareUsername=melonDS +FirmwareLanguage=1 +FirmwareBirthdayMonth=1 +FirmwareBirthdayDay=1 +FirmwareFavouriteColour=0 +FirmwareMessage= +FirmwareMAC= +MPAudioMode=1 +MPRecvTimeout=25 +LANDevice= +DirectLAN=0 +SavStaRelocSRAM=0 +AudioInterp=0 +AudioBitrate=0 +AudioVolume=256 +DSiVolumeSync=0 +MicInputType=0 +MicWavPath= +LastROMFolder= +LastBIOSFolder= +RecentROM_0= +RecentROM_1= +RecentROM_2= +RecentROM_3= +RecentROM_4= +RecentROM_5= +RecentROM_6= +RecentROM_7= +RecentROM_8= +RecentROM_9= +SaveFilePath=/storage/roms/nds +SavestatePath=/storage/roms/savestates/nds +CheatFilePath= +EnableCheats=0 +MouseHide=0 +MouseHideSeconds=5 +PauseLostFocus=0 +DSBatteryLevelOkay=1 +DSiBatteryLevel=15 +DSiBatteryCharging=1 +Camera0_InputType=0 +Camera0_ImagePath= +Camera0_CamDeviceName= +Camera0_XFlip=0 +Camera1_InputType=0 +Camera1_ImagePath= +Camera1_CamDeviceName= +Camera1_XFlip=0 diff --git a/projects/ArchR/packages/emulators/standalone/melonds-sa/config/S922X/melonDS.ini b/projects/ArchR/packages/emulators/standalone/melonds-sa/config/S922X/melonDS.ini new file mode 100644 index 0000000000..c424999feb --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/melonds-sa/config/S922X/melonDS.ini @@ -0,0 +1,170 @@ +Key_A=-1 +Key_B=-1 +Key_Select=-1 +Key_Start=-1 +Key_Right=-1 +Key_Left=-1 +Key_Up=-1 +Key_Down=-1 +Key_R=-1 +Key_L=-1 +Key_X=-1 +Key_Y=-1 +Joy_A=1 +Joy_B=0 +Joy_Select=9 +Joy_Start=10 +Joy_Right=17 +Joy_Left=16 +Joy_Up=14 +Joy_Down=15 +Joy_R=6 +Joy_L=5 +Joy_X=3 +Joy_Y=4 +HKKey_Lid=-1 +HKKey_Mic=-1 +HKKey_Pause=-1 +HKKey_Reset=-1 +HKKey_FastForward=-1 +HKKey_FastForwardToggle=-1 +HKKey_FullscreenToggle=-1 +HKKey_SwapScreens=-1 +HKKey_SwapScreenEmphasis=-1 +HKKey_SolarSensorDecrease=-1 +HKKey_SolarSensorIncrease=-1 +HKKey_FrameStep=-1 +HKKey_PowerButton=-1 +HKKey_VolumeUp=-1 +HKKey_VolumeDown=-1 +HKKey_SaveState=83 +HKKey_LoadState=76 +HKJoy_Lid=-1 +HKJoy_Mic=-1 +HKJoy_Pause=-1 +HKJoy_Reset=-1 +HKJoy_FastForward=-1 +HKJoy_FastForwardToggle=-1 +HKJoy_FullscreenToggle=-1 +HKJoy_SwapScreens=7 +HKJoy_SwapScreenEmphasis=-1 +HKJoy_SolarSensorDecrease=-1 +HKJoy_SolarSensorIncrease=-1 +HKJoy_FrameStep=-1 +HKJoy_PowerButton=-1 +HKJoy_VolumeUp=-1 +HKJoy_VolumeDown=-1 +HKJoy_SaveState=-1 +HKJoy_LoadState=-1 +JoystickID=0 +WindowWidth=854 +WindowHeight=480 +WindowMax=0 +ScreenRotation=0 +ScreenGap=0 +ScreenLayout=2 +ScreenSwap=0 +ScreenSizing=1 +Screen1Layout=2 +Screen1Enabled=false +Screen1Sizing=5 +IntegerScaling=0 +ScreenAspectTop=0 +ScreenAspectBot=0 +ScreenFilter=1 +ScreenUseGL=1 +ScreenVSync=0 +ScreenVSyncInterval=1 +3DRenderer=0 +Threaded3D=1 +GL_ScaleFactor=1 +GL_BetterPolygons=0 +GL_HiresCoordinates=1 +LimitFPS=1 +MaxFPS=1000 +AudioSync=0 +ShowOSD=1 +ConsoleType=0 +DirectBoot=1 +JIT_Enable=0 +JIT_MaxBlockSize=32 +JIT_BranchOptimisations=1 +JIT_LiteralOptimisations=1 +JIT_FastMemory=1 +ExternalBIOSEnable=0 +BIOS9Path=/storage/roms/bios/bios9.bin +BIOS7Path=/storage/roms/bios/bios7.bin +FirmwarePath=/storage/roms/bios/firmware.bin +DSiBIOS9Path=/storage/roms/bios/dsi_bios9.bin +DSiBIOS7Path=/storage/roms/bios/dsi_bios7.bin +DSiFirmwarePath=/storage/roms/bios/dsi_firmware.bin +DSiNANDPath=/storage/roms/bios/dsi_nand.bin +DLDIEnable=0 +DLDISDPath=dldi.bin +DLDISize=0 +DLDIReadOnly=0 +DLDIFolderSync=0 +DLDIFolderPath= +DSiSDEnable=0 +DSiSDPath=dsisd.bin +DSiSDSize=0 +DSiSDReadOnly=0 +DSiSDFolderSync=0 +DSiSDFolderPath= +FirmwareOverrideSettings=0 +FirmwareUsername=melonDS +FirmwareLanguage=1 +FirmwareBirthdayMonth=1 +FirmwareBirthdayDay=1 +FirmwareFavouriteColour=0 +FirmwareMessage= +FirmwareMAC= +MPAudioMode=1 +MPRecvTimeout=25 +LANDevice= +DirectLAN=0 +SavStaRelocSRAM=0 +AudioInterp=0 +AudioBitDepth=0 +AudioVolume=256 +DSiVolumeSync=0 +MicInputType=0 +MicWavPath= +LastROMFolder= +LastBIOSFolder= +RecentROM_0= +RecentROM_1= +RecentROM_2= +RecentROM_3= +RecentROM_4= +RecentROM_5= +RecentROM_6= +RecentROM_7= +RecentROM_8= +RecentROM_9= +SaveFilePath=/storage/roms/nds +SavestatePath=/storage/roms/savestates/nds +CheatFilePath= +EnableCheats=0 +MouseHide=0 +MouseHideSeconds=5 +PauseLostFocus=0 +UITheme= +RTCOffset=0 +DSBatteryLevelOkay=1 +DSiBatteryLevel=15 +DSiBatteryCharging=1 +DSiFullBIOSBoot=0 +GdbEnabled=0 +GdbPortARM7=3334 +GdbPortARM9=3333 +GdbARM7BreakOnStartup=0 +GdbARM9BreakOnStartup=0 +Camera0_InputType=0 +Camera0_ImagePath= +Camera0_CamDeviceName= +Camera0_XFlip=0 +Camera1_InputType=0 +Camera1_ImagePath= +Camera1_CamDeviceName= +Camera1_XFlip=0 diff --git a/projects/ArchR/packages/emulators/standalone/melonds-sa/config/SDM845/melonDS.ini b/projects/ArchR/packages/emulators/standalone/melonds-sa/config/SDM845/melonDS.ini new file mode 100644 index 0000000000..4425f4752e --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/melonds-sa/config/SDM845/melonDS.ini @@ -0,0 +1,171 @@ +Key_A=-1 +Key_B=-1 +Key_Select=-1 +Key_Start=-1 +Key_Right=-1 +Key_Left=-1 +Key_Up=-1 +Key_Down=-1 +Key_R=-1 +Key_L=-1 +Key_X=-1 +Key_Y=-1 +Joy_A=1 +Joy_B=0 +Joy_Select=8 +Joy_Start=9 +Joy_Right=65552 +Joy_Left=1114127 +Joy_Up=17891341 +Joy_Down=16842766 +Joy_R=5 +Joy_L=4 +Joy_X=2 +Joy_Y=3 +HKKey_Lid=-1 +HKKey_Mic=-1 +HKKey_Pause=-1 +HKKey_Reset=-1 +HKKey_FastForward=-1 +HKKey_FastForwardToggle=-1 +HKKey_FullscreenToggle=-1 +HKKey_SwapScreens=70 +HKKey_SwapScreenEmphasis=77 +HKKey_SolarSensorDecrease=-1 +HKKey_SolarSensorIncrease=-1 +HKKey_FrameStep=-1 +HKKey_PowerButton=-1 +HKKey_VolumeUp=-1 +HKKey_VolumeDown=-1 +HKKey_SaveState=83 +HKKey_LoadState=76 +HKJoy_Lid=-1 +HKJoy_Mic=-1 +HKJoy_Pause=-1 +HKJoy_Reset=-1 +HKJoy_FastForward=-1 +HKJoy_FastForwardToggle=-1 +HKJoy_FullscreenToggle=-1 +HKJoy_SwapScreens=-1 +HKJoy_SwapScreenEmphasis=-1 +HKJoy_SolarSensorDecrease=-1 +HKJoy_SolarSensorIncrease=-1 +HKJoy_FrameStep=-1 +HKJoy_PowerButton=-1 +HKJoy_VolumeUp=-1 +HKJoy_VolumeDown=-1 +HKJoy_SaveState=-1 +HKJoy_LoadState=-1 +JoystickID=0 +WindowWidth=960 +WindowHeight=1080 +WindowMax=0 +ScreenRotation=0 +ScreenGap=0 +ScreenLayout=2 +ScreenSwap=0 +ScreenSizing=0 +Screen1Layout=2 +Screen1Enabled=false +Screen1Sizing=5 +IntegerScaling=0 +ScreenAspectTop=0 +ScreenAspectBot=0 +ScreenFilter=1 +ScreenUseGL=1 +ScreenVSync=0 +ScreenVSyncInterval=1 +3DRenderer=0 +Threaded3D=1 +GL_ScaleFactor=1 +GL_BetterPolygons=0 +GL_HiresCoordinates=1 +LimitFPS=1 +MaxFPS=1000 +AudioSync=0 +ShowOSD=1 +ConsoleType=0 +DirectBoot=1 +JIT_Enable=0 +JIT_MaxBlockSize=32 +JIT_BranchOptimisations=1 +JIT_LiteralOptimisations=1 +JIT_FastMemory=1 +ExternalBIOSEnable=0 +BIOS9Path=/storage/roms/bios/bios9.bin +BIOS7Path=/storage/roms/bios/bios7.bin +FirmwarePath=/storage/roms/bios/firmware.bin +DSiBIOS9Path=/storage/roms/bios/dsi_bios9.bin +DSiBIOS7Path=/storage/roms/bios/dsi_bios7.bin +DSiFirmwarePath=/storage/roms/bios/dsi_firmware.bin +DSiNANDPath=/storage/roms/bios/dsi_nand.bin +DLDIEnable=0 +DLDISDPath=dldi.bin +DLDISize=0 +DLDIReadOnly=0 +DLDIFolderSync=0 +DLDIFolderPath= +DSiSDEnable=0 +DSiSDPath=dsisd.bin +DSiSDSize=0 +DSiSDReadOnly=0 +DSiSDFolderSync=0 +DSiSDFolderPath= +FirmwareOverrideSettings=0 +FirmwareUsername=melonDS +FirmwareLanguage=1 +FirmwareBirthdayMonth=1 +FirmwareBirthdayDay=1 +FirmwareFavouriteColour=0 +FirmwareMessage= +FirmwareMAC= +MPAudioMode=1 +MPRecvTimeout=25 +LANDevice= +DirectLAN=0 +SavStaRelocSRAM=0 +AudioInterp=0 +AudioBitDepth=0 +AudioVolume=256 +DSiVolumeSync=0 +MicInputType=0 +MicDevice= +MicWavPath= +LastROMFolder= +LastBIOSFolder= +RecentROM_0=/storage/roms/nds/DiagnoSe.nds +RecentROM_1=/storage/roms/nds/Chrono Trigger.nds +RecentROM_2= +RecentROM_3= +RecentROM_4= +RecentROM_5= +RecentROM_6= +RecentROM_7= +RecentROM_8= +RecentROM_9= +SaveFilePath=/storage/roms/nds +SavestatePath=/storage/roms/savestates/nds +CheatFilePath= +EnableCheats=0 +MouseHide=0 +MouseHideSeconds=5 +PauseLostFocus=0 +UITheme= +RTCOffset=0 +DSBatteryLevelOkay=1 +DSiBatteryLevel=15 +DSiBatteryCharging=1 +DSiFullBIOSBoot=0 +GdbEnabled=0 +GdbPortARM7=3334 +GdbPortARM9=3333 +GdbARM7BreakOnStartup=0 +GdbARM9BreakOnStartup=0 +Camera0_InputType=0 +Camera0_ImagePath= +Camera0_CamDeviceName= +Camera0_XFlip=0 +Camera1_InputType=0 +Camera1_ImagePath= +Camera1_CamDeviceName= +Camera1_XFlip=0 diff --git a/projects/ArchR/packages/emulators/standalone/melonds-sa/config/SM8250/melonDS.ini b/projects/ArchR/packages/emulators/standalone/melonds-sa/config/SM8250/melonDS.ini new file mode 100644 index 0000000000..b1bbebfaa7 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/melonds-sa/config/SM8250/melonDS.ini @@ -0,0 +1,160 @@ +Key_A=-1 +Key_B=-1 +Key_Select=-1 +Key_Start=-1 +Key_Right=-1 +Key_Left=-1 +Key_Up=-1 +Key_Down=-1 +Key_R=-1 +Key_L=-1 +Key_X=-1 +Key_Y=-1 +Joy_A=1 +Joy_B=0 +Joy_Select=6 +Joy_Start=7 +Joy_Right=65550 +Joy_Left=1114125 +Joy_Up=17891339 +Joy_Down=16842764 +Joy_R=5 +Joy_L=4 +Joy_X=2 +Joy_Y=3 +HKKey_Lid=-1 +HKKey_Mic=-1 +HKKey_Pause=-1 +HKKey_Reset=-1 +HKKey_FastForward=-1 +HKKey_FastForwardToggle=70 +HKKey_FullscreenToggle=-1 +HKKey_SwapScreens=-1 +HKKey_SwapScreenEmphasis=-1 +HKKey_SolarSensorDecrease=-1 +HKKey_SolarSensorIncrease=-1 +HKKey_FrameStep=-1 +HKKey_PowerButton=-1 +HKKey_VolumeUp=-1 +HKKey_VolumeDown=-1 +HKKey_SaveState=83 +HKKey_LoadState=76 +HKJoy_Lid=-1 +HKJoy_Mic=-1 +HKJoy_Pause=-1 +HKJoy_Reset=-1 +HKJoy_FastForward=-1 +HKJoy_FastForwardToggle=-1 +HKJoy_FullscreenToggle=-1 +HKJoy_SwapScreens=15 +HKJoy_SwapScreenEmphasis=-1 +HKJoy_SolarSensorDecrease=-1 +HKJoy_SolarSensorIncrease=-1 +HKJoy_FrameStep=-1 +HKJoy_PowerButton=-1 +HKJoy_VolumeUp=-1 +HKJoy_VolumeDown=-1 +HKJoy_SaveState=-1 +HKJoy_LoadState=-1 +JoystickID=0 +WindowWidth=1920 +WindowHeight=1080 +WindowMax=0 +ScreenRotation=0 +ScreenGap=0 +ScreenLayout=2 +ScreenSwap=1 +ScreenSizing=4 +Screen1Layout=2 +Screen1Enabled=false +Screen1Sizing=5 +IntegerScaling=0 +ScreenAspectTop=0 +ScreenAspectBot=0 +ScreenFilter=1 +ScreenUseGL=1 +ScreenVSync=0 +ScreenVSyncInterval=1 +3DRenderer=0 +Threaded3D=1 +GL_ScaleFactor=1 +GL_BetterPolygons=0 +LimitFPS=1 +AudioSync=0 +ShowOSD=1 +ConsoleType=0 +DirectBoot=1 +JIT_Enable=0 +JIT_MaxBlockSize=32 +JIT_BranchOptimisations=1 +JIT_LiteralOptimisations=1 +JIT_FastMemory=1 +ExternalBIOSEnable=0 +BIOS9Path=/storage/roms/bios/bios9.bin +BIOS7Path=/storage/roms/bios/bios7.bin +FirmwarePath=/storage/roms/bios/firmware.bin +DSiBIOS9Path=/storage/roms/bios/dsi_bios9.bin +DSiBIOS7Path=/storage/roms/bios/dsi_bios7.bin +DSiFirmwarePath=/storage/roms/bios/dsi_firmware.bin +DSiNANDPath=/storage/roms/bios/dsi_nand.bin +DLDIEnable=0 +DLDISDPath=dldi.bin +DLDISize=0 +DLDIReadOnly=0 +DLDIFolderSync=0 +DLDIFolderPath= +DSiSDEnable=0 +DSiSDPath=dsisd.bin +DSiSDSize=0 +DSiSDReadOnly=0 +DSiSDFolderSync=0 +DSiSDFolderPath= +FirmwareOverrideSettings=0 +FirmwareUsername=melonDS +FirmwareLanguage=1 +FirmwareBirthdayMonth=1 +FirmwareBirthdayDay=1 +FirmwareFavouriteColour=0 +FirmwareMessage= +FirmwareMAC= +MPAudioMode=1 +MPRecvTimeout=25 +LANDevice= +DirectLAN=0 +SavStaRelocSRAM=0 +AudioInterp=0 +AudioBitrate=0 +AudioVolume=256 +DSiVolumeSync=0 +MicInputType=0 +MicWavPath= +LastROMFolder= +LastBIOSFolder= +RecentROM_0= +RecentROM_1= +RecentROM_2= +RecentROM_3= +RecentROM_4= +RecentROM_5= +RecentROM_6= +RecentROM_7= +RecentROM_8= +RecentROM_9= +SaveFilePath=/storage/roms/nds +SavestatePath=/storage/roms/savestates/nds +CheatFilePath= +EnableCheats=0 +MouseHide=0 +MouseHideSeconds=5 +PauseLostFocus=0 +DSBatteryLevelOkay=1 +DSiBatteryLevel=15 +DSiBatteryCharging=1 +Camera0_InputType=0 +Camera0_ImagePath= +Camera0_CamDeviceName= +Camera0_XFlip=0 +Camera1_InputType=0 +Camera1_ImagePath= +Camera1_CamDeviceName= +Camera1_XFlip=0 diff --git a/projects/ArchR/packages/emulators/standalone/melonds-sa/config/SM8550 b/projects/ArchR/packages/emulators/standalone/melonds-sa/config/SM8550 new file mode 120000 index 0000000000..72081d3859 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/melonds-sa/config/SM8550 @@ -0,0 +1 @@ +InputPlumber \ No newline at end of file diff --git a/projects/ArchR/packages/emulators/standalone/melonds-sa/config/SM8650 b/projects/ArchR/packages/emulators/standalone/melonds-sa/config/SM8650 new file mode 120000 index 0000000000..72081d3859 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/melonds-sa/config/SM8650 @@ -0,0 +1 @@ +InputPlumber \ No newline at end of file diff --git a/projects/ArchR/packages/emulators/standalone/melonds-sa/config/melonDS.gptk b/projects/ArchR/packages/emulators/standalone/melonds-sa/config/melonDS.gptk new file mode 100644 index 0000000000..a9253ebf6a --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/melonds-sa/config/melonDS.gptk @@ -0,0 +1,31 @@ +back = \\ +start = \\ +a = \\ +b = \\ +x = \\ +y = \\ +l1 = \\ +l1_hk = l +l2 = \\ +l2_hk = m +l3 = \\ +r1 = \\ +r1_hk = s +r2 = \\ +r2_hk = f +r3 = mouse_left +up = \\ +down = \\ +left = \\ +right = \\ +left_analog_up = \\ +left_analog_down = \\ +left_analog_left = \\ +left_analog_right = \\ +right_analog_up = mouse_movement_up +right_analog_down = mouse_movement_down +right_analog_left = mouse_movement_left +right_analog_right = mouse_movement_right +deadzone_triggers = 3000 +mouse_scale = 6128 +mouse_delay = 16 diff --git a/projects/ArchR/packages/emulators/standalone/melonds-sa/package.mk b/projects/ArchR/packages/emulators/standalone/melonds-sa/package.mk new file mode 100644 index 0000000000..76c4073e69 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/melonds-sa/package.mk @@ -0,0 +1,101 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="melonds-sa" +PKG_VERSION="bdd85c9ccb40c0a3fcaa6103baf79c2d2d52d6ad" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/melonDS-emu/melonDS" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="SDL2 qt6 libslirp libepoxy libarchive ecm libpcap control-gen faad2" +PKG_LONGDESC="DS emulator, sorta. The goal is to do things right and fast" +PKG_TOOLCHAIN="cmake" + +if [ "${OPENGL_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL} glu libglvnd" +fi + +if [ "${OPENGLES_SUPPORT}" = yes ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" +fi + +if [ "${DISPLAYSERVER}" = "wl" ]; then + PKG_DEPENDS_TARGET+=" wayland ${WINDOWMANAGER} xwayland xrandr libXi" +fi + +if [ "${VULKAN_SUPPORT}" = "yes" ] +then + PKG_DEPENDS_TARGET+=" ${VULKAN}" +fi + +get_graphicdrivers +if listcontains "${GRAPHIC_DRIVERS}" "(panfrost)"; then + GRAPHICS_DRIVER="panfrost" +fi + +pre_configure_target() { +export CFLAGS+=" -Wno-sign-compare" +export CXXFLAGS="${CXXFLAGS} -Wno-sign-compare" + +PKG_CMAKE_OPTS_TARGET+=" -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX="/usr" \ + -DUSE_QT6=ON \ + -DENABLE_RETROACHIEVEMENTS=ON \ + -DBUILD_SHARED_LIBS=OFF" + +mkdir -p ${PKG_BUILD}/src/frontend/qt_sdl/retroachievements/resources/sounds +mkdir -p ${PKG_BUILD}/src/frontend/qt_sdl/retroachievements/resources/icons +touch ${PKG_BUILD}/src/frontend/qt_sdl/retroachievements/resources/sounds/unlock.wav +cp -rf ${PKG_DIR}/resources/ra-icon.png ${PKG_BUILD}/src/frontend/qt_sdl/retroachievements/resources/icons/ra-icon.png +touch ${PKG_BUILD}/src/frontend/qt_sdl/retroachievements/resources/icons/placeholder.png +} + + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp -rf ${PKG_BUILD}/.${TARGET_NAME}/melonDS ${INSTALL}/usr/bin + + mkdir -p ${INSTALL}/usr/config/melonDS + cp -rf ${PKG_DIR}/config/${DEVICE}/* ${INSTALL}/usr/config/melonDS + cp -rf ${PKG_DIR}/config/melonDS.gptk ${INSTALL}/usr/config/melonDS + + cp -rf ${PKG_DIR}/scripts/* ${INSTALL}/usr/bin + chmod +x ${INSTALL}/usr/bin/* +} + +post_install() { + case ${GRAPHICS_DRIVER} in + panfrost) + PANFROST="export MESA_GL_VERSION_OVERRIDE=3.3" + ;; + *) + PANFROST="" + ;; + esac + sed -e "s/@PANFROST@/${PANFROST}/g" \ + -i ${INSTALL}/usr/bin/start_melonds.sh + + # Platform hotkeys + case ${DEVICE} in + RK3588|S922X|SM8*) + HOTKEY="export HOTKEY="guide"" + ;; + *) + HOTKEY="" + ;; + esac + + # Libmali check - force software renderer + case ${DEVICE} in + RK3588|S922X|RK3566) + LIBMALI="if [[ -x \"\/usr\/bin\/gpudriver\" ]] \&\& [[ \"\$\(\/usr\/bin\/gpudriver\)\" = \"libmali\" ]]; then sed -i '\/ScreenUseGL=\/c\\\ScreenUseGL=0' \/storage\/.config\/melonDS\/melonDS.ini; fi" + ;; + *) + LIBMALI="" + ;; + esac + + sed -e "s/@HOTKEY@/${HOTKEY}/g" \ + -i ${INSTALL}/usr/bin/start_melonds.sh + sed -e "s/@LIBMALI@/${LIBMALI}/g" \ + -i ${INSTALL}/usr/bin/start_melonds.sh +} diff --git a/projects/ArchR/packages/emulators/standalone/melonds-sa/patches/000-retro-achievements.patch b/projects/ArchR/packages/emulators/standalone/melonds-sa/patches/000-retro-achievements.patch new file mode 100644 index 0000000000..2856680c8f --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/melonds-sa/patches/000-retro-achievements.patch @@ -0,0 +1,42806 @@ +diff -rupbN melonDS.orig/src/CMakeLists.txt melonDS.ra/src/CMakeLists.txt +--- melonDS.orig/src/CMakeLists.txt 2026-03-06 21:36:14.522056951 +0000 ++++ melonDS.ra/src/CMakeLists.txt 2026-03-06 21:37:07.046799886 +0000 +@@ -226,6 +226,65 @@ if (ENABLE_JIT_PROFILING) + target_link_libraries(core PRIVATE "${VTUNE_LIBRARY}") + endif() + ++# --- RetroAchievements --- ++option(ENABLE_RETROACHIEVEMENTS "Enable RetroAchievements support" OFF) ++ ++if (ENABLE_RETROACHIEVEMENTS) ++ message(STATUS "RetroAchievements: ENABLED") ++ ++ if (WIN32) ++ target_compile_definitions(core PUBLIC RETROACHIEVEMENTS_ENABLED HAVE_CURL CURL_STATICLIB) ++ ++ set(CURL_DEPENDENCY_NAMES ++ curl nghttp2 nghttp3 ngtcp2 ssh2 psl ssl crypto brotlidec ++ brotlicommon brotlienc zstd idn2 unistring iconv z ++ ) ++ ++ set(CURL_FOUND_LIBS "") ++ foreach(LIB_NAME ${CURL_DEPENDENCY_NAMES}) ++ find_library(LIB_PATH_${LIB_NAME} NAMES ${LIB_NAME} REQUIRED) ++ if(LIB_PATH_${LIB_NAME}) ++ list(APPEND CURL_FOUND_LIBS ${LIB_PATH_${LIB_NAME}}) ++ endif() ++ endforeach() ++ ++ find_library(LIB_NGTCP2_CRYPTO NAMES ngtcp2_crypto_ossl ngtcp2_crypto_openssl) ++ if(LIB_NGTCP2_CRYPTO) ++ list(INSERT CURL_FOUND_LIBS 4 ${LIB_NGTCP2_CRYPTO}) ++ endif() ++ ++ target_link_libraries(core PRIVATE ++ ${CURL_FOUND_LIBS} ++ ws2_32 wldap32 crypt32 normaliz advapi32 secur32 bcrypt ++ ) ++ else() ++ find_package(CURL REQUIRED) ++ target_compile_definitions(core PUBLIC RETROACHIEVEMENTS_ENABLED HAVE_CURL) ++ target_link_libraries(core PRIVATE ${CURL_LIBRARIES}) ++ target_include_directories(core PRIVATE ${CURL_INCLUDE_DIRS}) ++ endif() ++ ++ target_include_directories(core PRIVATE ++ "${CMAKE_CURRENT_SOURCE_DIR}/RetroAchievements" ++ "${CMAKE_CURRENT_SOURCE_DIR}" ++ ) ++ ++ target_sources(core PRIVATE ++ RetroAchievements/RAClient.cpp ++ RetroAchievements/RAClient.h ++ ) ++ ++ file(GLOB_RECURSE RCH_ALL "${CMAKE_CURRENT_SOURCE_DIR}/rcheevos/src/*.c") ++ list(FILTER RCH_ALL EXCLUDE REGEX "rc_libretro.c|rc_client_external.c|rhash/aes.c") ++ target_sources(core PRIVATE ${RCH_ALL}) ++ target_include_directories(core PRIVATE ++ "${CMAKE_CURRENT_SOURCE_DIR}/rcheevos/include" ++ "${CMAKE_CURRENT_SOURCE_DIR}/rcheevos/src" ++ ) ++else() ++ message(STATUS "RetroAchievements: DISABLED (default)") ++endif() ++ + #if(CMAKE_BUILD_TYPE MATCHES "Debug") + # set( + # CMAKE_C_FLAGS +diff -rupbN melonDS.orig/src/NDS.cpp melonDS.ra/src/NDS.cpp +--- melonDS.orig/src/NDS.cpp 2026-03-06 21:36:14.530057064 +0000 ++++ melonDS.ra/src/NDS.cpp 2026-03-06 21:37:07.046799886 +0000 +@@ -44,6 +44,11 @@ + #include "DSi_DSP.h" + #include "ARMJIT.h" + #include "ARMJIT_Memory.h" ++#include ++ ++#ifdef RETROACHIEVEMENTS_ENABLED ++#include "RetroAchievements/RAClient.h" ++#endif + + namespace melonDS + { +@@ -539,6 +544,9 @@ void NDS::Reset() + SPI.Reset(); + RTC.Reset(); + Wifi.Reset(); ++ memset(MainRAM, 0, MainRAMMask + 1); ++ memset(SharedWRAM, 0, 0x8000); ++ memset(ARM7WRAM, 0, 0x10000); + } + + void NDS::Start() +@@ -761,6 +769,16 @@ bool NDS::DoSavestate(Savestate* file) + #endif + } + ++#ifdef RETROACHIEVEMENTS_ENABLED ++ if (ra) ++ { ++ if (file->Saving) ++ ra->SaveSavestate(file); ++ else ++ ra->LoadSavestate(file); ++ } ++#endif ++ + file->Finish(); + + return true; +@@ -772,6 +790,16 @@ void NDS::SetNDSCart(std::unique_ptrGetRAHash(); ++ if (h && h[0]) ++ ra->SetPendingGameHash(h); ++ } ++ } ++ #endif + } + + void NDS::SetNDSSave(const u8* savedata, u32 savelen) +@@ -918,6 +946,11 @@ void NDS::RunSystemSleep(u64 timestamp) + template + u32 NDS::RunFrame() + { ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ if (ra) { ++ ra->DoFrame(); ++ } ++ #endif + Current = this; + + FrameStartTimestamp = SysTimestamp; +@@ -1593,6 +1626,11 @@ void NDS::MonitorARM9Jump(u32 addr) + { + Log(LogLevel::Info, "Game is now booting\n"); + RunningGame = true; ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ if (ra) { ++ ra->AttachNDS(this); ++ } ++ #endif + } + } + } +diff -rupbN melonDS.orig/src/NDS.h melonDS.ra/src/NDS.h +--- melonDS.orig/src/NDS.h 2026-03-06 21:36:14.530057064 +0000 ++++ melonDS.ra/src/NDS.h 2026-03-06 21:37:07.046799886 +0000 +@@ -44,6 +44,9 @@ + #include "DMA.h" + #include "FreeBIOS.h" + ++#ifdef RETROACHIEVEMENTS_ENABLED ++#include "RetroAchievements/RAClient.h" ++#endif + // when touching the main loop/timing code, pls test a lot of shit + // with this enabled, to make sure it doesn't desync + //#define DEBUG_CHECK_DESYNC +@@ -248,6 +251,11 @@ private: + #endif + + public: // TODO: Encapsulate the rest of these members ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ RAContext* ra = nullptr; ++ void SetRAContext(RAContext* ctx) noexcept { ra = ctx; } ++ bool IsGameRunning() const { return RunningGame; } ++ #endif + void* UserData; + + int ConsoleType; +diff -rupbN melonDS.orig/src/NDSCart.cpp melonDS.ra/src/NDSCart.cpp +--- melonDS.orig/src/NDSCart.cpp 2026-03-06 21:36:14.530057064 +0000 ++++ melonDS.ra/src/NDSCart.cpp 2026-03-06 21:37:07.046799886 +0000 +@@ -27,6 +27,11 @@ + #include "FATStorage.h" + #include "Utils.h" + ++#ifdef RETROACHIEVEMENTS_ENABLED ++#include "RetroAchievements/RAClient.h" ++#include ++#endif ++ + namespace melonDS + { + using Platform::Log; +@@ -202,6 +207,25 @@ CartCommon::CartCommon(std::unique_ptr 0) ++ { ++ const bool ok = rc_hash_generate_from_buffer( ++ this->ra_hash, ++ RC_CONSOLE_NINTENDO_DS, ++ ROM.get(), ++ ROMLength ++ ); ++ ++ if (ok) ++ { ++ if (ra) ++ { ++ ra->SetPendingGameHash(this->ra_hash); ++ } ++ } ++ } ++ #endif + memcpy(&Header, ROM.get(), sizeof(Header)); + IsDSi = Header.IsDSi() && !badDSiDump; + DSiBase = Header.DSiRegionStart << 19; +diff -rupbN melonDS.orig/src/NDSCart.h melonDS.ra/src/NDSCart.h +--- melonDS.orig/src/NDSCart.h 2026-03-06 21:36:14.530057064 +0000 ++++ melonDS.ra/src/NDSCart.h 2026-03-06 21:37:07.046799886 +0000 +@@ -30,6 +30,10 @@ + #include "FATStorage.h" + #include "ROMList.h" + ++#ifdef RETROACHIEVEMENTS_ENABLED ++#include "RetroAchievements/RAClient.h" ++#endif ++ + namespace melonDS + { + class NDS; +@@ -76,6 +80,11 @@ struct NDSCartArgs + class CartCommon + { + public: ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ RAContext* ra = nullptr; ++ const char* GetRAHash() const { return ra_hash; } ++ char ra_hash[33] = {0}; ++ #endif + CartCommon(const u8* rom, u32 len, u32 chipid, bool badDSiDump, ROMListEntry romparams, CartType type, void* userdata); + CartCommon(std::unique_ptr&& rom, u32 len, u32 chipid, bool badDSiDump, ROMListEntry romparams, CartType type, void* userdata); + virtual ~CartCommon(); +diff -rupbN melonDS.orig/src/RetroAchievements/RAClient.cpp melonDS.ra/src/RetroAchievements/RAClient.cpp +--- melonDS.orig/src/RetroAchievements/RAClient.cpp 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/RetroAchievements/RAClient.cpp 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,1119 @@ ++#include "RAClient.h" ++#include "../NDS.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "RetroAchievements/cacert.c" ++#include "version.h" ++#include "Savestate.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct RAHttpJob { ++ std::string url; ++ std::string post_data; ++ rc_client_server_callback_t callback; ++ void* userdata; ++}; ++ ++struct RAPendingCallback { ++ rc_client_server_callback_t callback; ++ rc_api_server_response_t resp; ++ std::string body; ++ void* userdata; ++}; ++ ++static void PerformServerCall(const RAHttpJob& job); ++static void EnsureHTTPThread(); ++ ++static std::mutex s_httpMutex; ++static std::condition_variable s_httpCV; ++static std::queue s_httpJobs; ++ ++static std::mutex s_cbMutex; ++static std::queue s_pendingCallbacks; ++ ++static std::thread s_httpThread; ++static std::atomic s_httpRunning{false}; ++ ++static std::once_flag s_curlInitOnce; ++static thread_local CURL* s_curl = nullptr; ++static void EnsureCurlInit() ++{ ++ std::call_once(s_curlInitOnce, [] { ++ curl_global_init(CURL_GLOBAL_DEFAULT); ++ }); ++} ++static bool s_raOffline = false; ++static int s_pendingCount = 0; ++extern const unsigned char _accacert[]; ++extern const size_t _accacert_len; ++void RAContext::SetDisplayName(const char* name) ++{ ++ m_displayName = name ? name : ""; ++} ++ ++const std::string& RAContext::GetDisplayName() const ++{ ++ return m_displayName; ++} ++static uint64_t g_ra_mem_reads = 0; ++static uint64_t g_ra_mem_logged = 0; ++static size_t CurlWrite(void* ptr, size_t size, size_t nmemb, void* userdata) ++{ ++ std::string* s = static_cast(userdata); ++ s->append(static_cast(ptr), size * nmemb); ++ return size * nmemb; ++} ++bool RAContext::CanPause(uint32_t* frames_remaining) { ++ if (!client) return true; ++ return rc_client_can_pause(client, frames_remaining) != 0; ++} ++ ++void RAContext::SetPaused(bool paused) { ++ m_IsPaused = paused; ++} ++ ++RAContext::RAContext() : nds(nullptr), client(nullptr) ++{ ++} ++ ++RAContext::~RAContext() ++{ ++ Shutdown(); ++} ++ ++void RAContext::Init(melonDS::NDS* nds_) ++{ ++ EnsureCurlInit(); ++ nds = nds_; ++ client = rc_client_create( ++ &RAContext::ReadMemory, ++ &RAContext::ServerCall ++ ); ++ rc_client_set_userdata(client, this); ++ rc_client_set_allow_background_memory_reads(client, 1); ++ rc_runtime_init(&m_runtime); ++ rc_client_set_event_handler(client, ++ [](const rc_client_event_t* event, rc_client_t* client) ++ { ++ auto* ctx = static_cast(rc_client_get_userdata(client)); ++ if (!ctx) return; ++ switch (event->type) ++ { ++ case RC_CLIENT_EVENT_ACHIEVEMENT_TRIGGERED: ++ { ++ const rc_client_achievement_t* ach = (const rc_client_achievement_t*)event->achievement; ++ ++ for (auto& a : ctx->allAchievements) ++ { ++ if (a.id == ach->id) ++ { ++ a.unlocked = true; ++ a.measured = false; ++ a.state = ach->state; ++ break; ++ } ++ } ++ ++ if (ctx->m_onAchievementUnlocked) ++ ctx->m_onAchievementUnlocked( ++ ach->title, ++ ach->description, ++ ach->badge_url ++ ); ++ ctx->m_progressThrottle.erase(ach->id); ++ break; ++ } ++ case RC_CLIENT_EVENT_LEADERBOARD_STARTED: ++ { ++ printf("[RA][LB] START id=%u title=%s\n", ++ event->leaderboard->id, ++ event->leaderboard->title); ++ auto* ctx = static_cast(rc_client_get_userdata(client)); ++ if (ctx && ctx->onLeaderboardStarted) ++ ctx->onLeaderboardStarted(event->leaderboard); ++ break; ++ } ++ ++ case RC_CLIENT_EVENT_LEADERBOARD_FAILED: ++ { ++ printf("[RA][LB] FAILED id=%u\n", ++ event->leaderboard->id); ++ auto* ctx = static_cast(rc_client_get_userdata(client)); ++ if (ctx && ctx->onLeaderboardFailed) ++ ctx->onLeaderboardFailed(event->leaderboard); ++ break; ++ } ++ ++ case RC_CLIENT_EVENT_LEADERBOARD_SCOREBOARD: ++ { ++ auto* ctx = static_cast(rc_client_get_userdata(client)); ++ if (ctx && ctx->m_onLeaderboardSubmitted && event->leaderboard_scoreboard) { ++ bool isNewRecord = (strcmp(event->leaderboard_scoreboard->submitted_score, ++ event->leaderboard_scoreboard->best_score) == 0); ++ ++ const char* title = isNewRecord ? "New Personal Best!" : "Score Submitted"; ++ ++ ctx->m_onLeaderboardSubmitted( ++ title, ++ event->leaderboard_scoreboard->submitted_score, ++ event->leaderboard_scoreboard->new_rank ++ ); ++ } ++ break; ++ } ++ ++ case RC_CLIENT_EVENT_LEADERBOARD_SUBMITTED: ++ break; ++ case RC_CLIENT_EVENT_LEADERBOARD_TRACKER_SHOW: ++ { ++ if (event->leaderboard_tracker) { ++ ctx->activeTrackers[event->leaderboard_tracker->id] = { ++ event->leaderboard_tracker->id, ++ event->leaderboard_tracker->display ++ }; ++ } ++ break; ++ } ++ case RC_CLIENT_EVENT_LEADERBOARD_TRACKER_UPDATE: ++ { ++ if (event->leaderboard_tracker) { ++ auto it = ctx->activeTrackers.find(event->leaderboard_tracker->id); ++ if (it != ctx->activeTrackers.end()) { ++ it->second.display = event->leaderboard_tracker->display; ++ } ++ } ++ break; ++ } ++ case RC_CLIENT_EVENT_LEADERBOARD_TRACKER_HIDE: ++ { ++ if (event->leaderboard_tracker) { ++ ctx->activeTrackers.erase(event->leaderboard_tracker->id); ++ } ++ break; ++ } ++ case RC_CLIENT_EVENT_ACHIEVEMENT_CHALLENGE_INDICATOR_SHOW: ++ { ++ const rc_client_achievement_t* ach = (const rc_client_achievement_t*)event->achievement; ++ if (ach && ctx->m_onChallenge) { ++ ctx->m_onChallenge(ach->badge_name); ++ } ++ break; ++ } ++ case RC_CLIENT_EVENT_ACHIEVEMENT_CHALLENGE_INDICATOR_HIDE: ++ { ++ if (ctx->m_onChallengeHide) ++ ctx->m_onChallengeHide(); ++ break; ++ } ++ case RC_CLIENT_EVENT_GAME_COMPLETED: ++ { ++ RAContext* ctx = static_cast(rc_client_get_userdata(client)); ++ if (ctx && ctx->m_onGameMastered) ++ { ++ const rc_client_game_t* game = rc_client_get_game_info(client); ++ std::string gameTitle = (game && game->title) ? game->title : "Unknown Game"; ++ ++ char rp_buffer[256]; ++ rc_client_get_rich_presence_message(client, rp_buffer, sizeof(rp_buffer)); ++ ++ ctx->m_onGameMastered( ++ gameTitle, ++ rp_buffer ++ ); ++ } ++ break; ++ } ++ ++ case RC_CLIENT_EVENT_ACHIEVEMENT_PROGRESS_INDICATOR_SHOW: ++ { ++ if (ctx->m_suppressProgressFrames > 0) break; ++ ++ const rc_client_achievement_t* ach = (const rc_client_achievement_t*)event->achievement; ++ ++ if (ctx->m_onAchievementProgress && ctx->ShouldShowProgress(ach->id, (unsigned)ach->measured_percent, 100)) { ++ ctx->m_onAchievementProgress( ++ ach->title, ++ ach->measured_progress, ++ ach->badge_locked_url ? ach->badge_locked_url : ach->badge_url ++ ); ++ } ++ break; ++ } ++ ++ case RC_CLIENT_EVENT_ACHIEVEMENT_PROGRESS_INDICATOR_UPDATE: ++ { ++ if (ctx->m_suppressProgressFrames > 0) break; ++ ++ const rc_client_achievement_t* ach = (const rc_client_achievement_t*)event->achievement; ++ ++ if (ctx->m_onAchievementProgress && ctx->ShouldShowProgress(ach->id, (unsigned)ach->measured_percent, 100)) { ++ ctx->m_onAchievementProgress( ++ ach->title, ++ ach->measured_progress, ++ ach->badge_locked_url ? ach->badge_locked_url : ach->badge_url ++ ); ++ } ++ break; ++ } ++ ++ case RC_CLIENT_EVENT_ACHIEVEMENT_PROGRESS_INDICATOR_HIDE: ++ { ++ if (ctx->m_onChallengeHide) { ++ } ++ break; ++ } ++ default: ++ break; ++ } ++ }); ++} ++ ++void RAContext::Shutdown() ++{ ++ s_httpRunning = false; ++ s_httpCV.notify_all(); ++ if (s_httpThread.joinable()) ++ s_httpThread.join(); ++ m_onRADisconnected = nullptr; ++ m_onRAReconnected = nullptr; ++ m_onRAPendingSent = nullptr; ++ m_onLeaderboardSubmitted = nullptr; ++ m_onLeaderboardTrackerUpdate = nullptr; ++ m_onAchievementUnlocked = nullptr; ++ m_onAchievementProgress = nullptr; ++ m_onMeasuredProgress = nullptr; ++ m_onChallenge = nullptr; ++ m_onChallengeHide = nullptr; ++ m_onGameMastered = nullptr; ++ m_onLogin = nullptr; ++ onGameLoaded = nullptr; ++ SavePlaytime(); ++ if (client) { ++ rc_client_destroy(client); ++ client = nullptr; ++ } ++ rc_runtime_destroy(&m_runtime); ++ ResetGameState(); ++} ++ ++uint32_t RC_CCONV RuntimePeek(uint32_t address, uint32_t num_bytes, void* ud) ++{ ++ RAContext* ctx = static_cast(ud); ++ if (!ctx || !ctx->client) ++ return 0; ++ ++ uint8_t buffer[4] = {0}; ++ ++ ctx->ReadMemory(address, buffer, num_bytes, ctx->client); ++ ++ uint32_t value = 0; ++ memcpy(&value, buffer, num_bytes); ++ return value; ++} ++ ++void RAContext::DoFrame() ++{ ++ { ++ std::queue local; ++ ++ { ++ std::lock_guard lock(s_cbMutex); ++ std::swap(local, s_pendingCallbacks); ++ } ++ ++ while (!local.empty()) { ++ auto& cb = local.front(); ++ if (cb.callback) { ++ if (!cb.body.empty()) { ++ cb.resp.body = cb.body.c_str(); ++ cb.resp.body_length = (uint32_t)cb.body.size(); ++ } ++ cb.callback( ++ cb.resp.body ? &cb.resp : nullptr, ++ cb.userdata ++ ); ++ } ++ local.pop(); ++ } ++ } ++ if (!nds || !client || m_IsPaused) ++ return; ++ ++ std::string currentHash = pendingGameHash.value_or(""); ++ if (currentHash != m_lastHash) { ++ gameLoaded = false; ++ m_lastHash = currentHash; ++ pendingLoadFailed = false; ++ isLoading = false; ++ } ++ ++ if (pendingLoadFailed || isLoading) return; ++ ++ if (!gameLoaded && ++ pendingGameHash.has_value() && ++ nds->IsGameRunning()) ++ { ++ isLoading = true; ++ LoadGame(pendingGameHash->c_str()); ++ return; ++ } ++ ++ if (!gameLoaded) return; ++ ++ if (rc_client_is_processing_required(client) == 0) { ++ return; ++ } ++ ++ if (m_suppressProgressFrames > 0) ++ m_suppressProgressFrames--; ++ ++ rc_runtime_do_frame( ++ &m_runtime, ++ nullptr, ++ &RuntimePeek, ++ this, ++ nullptr ++ ); ++ ++ auto f0 = std::chrono::steady_clock::now(); ++ ++ rc_client_do_frame(client); ++ ++ auto f1 = std::chrono::steady_clock::now(); ++ auto fms = std::chrono::duration_cast(f1 - f0).count(); ++ ++ if (fms > 20) { ++ printf("[RA][FRAME] rc_client_do_frame blocked %lld ms\n", fms); ++ } ++ ++ if (m_onLeaderboardTrackerUpdate) { ++ if (activeTrackers.empty()) { ++ m_onLeaderboardTrackerUpdate(""); ++ } else { ++ std::string combinedDisplay = ""; ++ for (auto const& [id, tracker] : activeTrackers) { ++ if (!combinedDisplay.empty()) combinedDisplay += "\n"; ++ combinedDisplay += tracker.display; ++ } ++ m_onLeaderboardTrackerUpdate(combinedDisplay.c_str()); ++ } ++ } ++ ++ static int playtimeSaveCounter = 0; ++ if (gameLoaded && ++playtimeSaveCounter >= 3600) { ++ SavePlaytime(); ++ playtimeSaveCounter = 0; ++ } ++} ++ ++void RAContext::UpdateMeasuredAchievements() ++{ ++ if (!client || trackedAchievements.empty()) ++ return; ++ ++ char formatted[128]; ++ ++ for (auto& ach : trackedAchievements) ++ { ++ unsigned value = 0; ++ unsigned target = 0; ++ ++ bool isMeasured = rc_runtime_get_achievement_measured(&m_runtime, ach.id, &value, &target) != 0; ++ ++ if (!isMeasured) ++ continue; ++ ++ rc_runtime_format_achievement_measured(&m_runtime, ach.id, formatted, sizeof(formatted)); ++ ++ bool valueChanged = (value != ach.prev_value); ++ ++ if (valueChanged) { ++ ach.prev_value = value; ++ if (m_onMeasuredProgress && ShouldShowProgress(ach.id, value, target)) { ++ m_onMeasuredProgress(ach.id, value, target, formatted); ++ } ++ } ++ for (auto& full : allAchievements) ++ { ++ if (full.id == ach.id) ++ { ++ if (!full.measured || full.value != value || full.target != target) ++ { ++ full.measured = true; ++ full.value = value; ++ full.target = target; ++ full.progressText = formatted; ++ full.measured_percent = (target > 0) ++ ? (static_cast(value) / static_cast(target) * 100.0f) ++ : 0.0f; ++ } ++ break; ++ } ++ } ++ } ++} ++ ++void RAContext::SetLoggedIn(bool v) ++{ ++ if (m_logged_in == v) ++ return; ++ m_logged_in = v; ++ ++ if (m_onLogin) ++ m_onLogin(); ++} ++ ++void RAContext::SetEncoreMode(bool enabled) ++{ ++ if (client) { ++ rc_client_set_encore_mode_enabled(client, enabled ? 1 : 0); ++ } ++} ++ ++void RAContext::SetUnofficialEnabled(bool enabled) ++{ ++ if (client) { ++ rc_client_set_unofficial_enabled(client, enabled ? 1 : 0); ++ } ++} ++ ++static void LoginPasswordCallback(int result, const char* err, rc_client_t* client, void* userdata) ++{ ++ RAContext* ctx = static_cast(userdata); ++ if (result == RC_OK) ++ { ++ const rc_client_user_t* user_info = rc_client_get_user_info(client); ++ ctx->SetToken(user_info->token ? user_info->token : ""); ++ ctx->SetLoggedIn(true); ++ if (ctx->onLoginResponse) { ++ ctx->onLoginResponse(true, "Logged in Successfully!"); ++ } ++ } ++ else ++ { ++ ctx->loginSuccess = false; ++ ctx->loginErrorMessage = err ? err : "Unknown error"; ++ ctx->SetLoggedIn(false); ++ if (ctx->onLoginResponse) { ++ ctx->onLoginResponse(false, ctx->loginErrorMessage); ++ } ++ } ++} ++ ++void RAContext::LoadGame(const char* hash) ++{ ++ if (!client) return; ++ rc_client_begin_load_game( ++ client, ++ hash, ++ [](int result, const char* err, rc_client_t*, void* userdata) ++ { ++ auto* context = static_cast(userdata); ++ ++ if (result != RC_OK) ++ { ++ context->gameLoaded = false; ++ context->pendingLoadError = err ? err : "Unknown error"; ++ context->pendingLoadFailed = true; ++ context->isLoading = false; ++ ++ if (context->onGameLoaded) ++ context->onGameLoaded(); ++ ++ return; ++ } ++ ++ rc_runtime_reset(&context->m_runtime); ++ context->ResetGameState(); ++ context->trackedAchievements.clear(); ++ context->allAchievements.clear(); ++ context->pendingLoadFailed = false; ++ context->isLoading = false; ++ context->gameLoaded = true; ++ context->currentGameInfo = rc_client_get_game_info(context->client); ++ ++ if (context->currentGameInfo) { ++ context->m_currentGameId = context->currentGameInfo->id; ++ context->m_sessionStart = time(nullptr); ++ context->m_accumulatedTime = 0; ++ ++ if (context->m_playtimeLoader) { ++ context->m_accumulatedTime = context->m_playtimeLoader(context->m_currentGameId); ++ } ++ } ++ ++ rc_client_achievement_list_t* list = rc_client_create_achievement_list( ++ context->client, ++ RC_CLIENT_ACHIEVEMENT_CATEGORY_CORE_AND_UNOFFICIAL, ++ RC_CLIENT_ACHIEVEMENT_LIST_GROUPING_PROGRESS ++ ); ++ ++ for (uint32_t i = 0; i < list->num_buckets; ++i) { ++ const rc_client_achievement_bucket_t& bucket = list->buckets[i]; ++ ++ for (uint32_t j = 0; j < bucket.num_achievements; ++j) { ++ const rc_client_achievement_t* ach = bucket.achievements[j]; ++ ++ FullAchievement fa; ++ fa.id = ach->id; ++ fa.title = ach->title ? ach->title : ""; ++ fa.description = ach->description ? ach->description : ""; ++ fa.points = ach->points; ++ fa.unlocked = (ach->state == RC_CLIENT_ACHIEVEMENT_STATE_UNLOCKED); ++ ++ fa.measured = false; ++ fa.progressText.clear(); ++ fa.measured_percent = 0.0f; ++ fa.value = 0; ++ fa.target = 0; ++ ++ if (ach->type == RC_CLIENT_ACHIEVEMENT_TYPE_PROGRESSION || ++ ach->type == RC_CLIENT_ACHIEVEMENT_TYPE_STANDARD) ++ { ++ context->trackedAchievements.push_back({ ach->id, 0 }); ++ } ++ ++ fa.value = 0; ++ fa.target = 0; ++ ++ std::strncpy(fa.badge_name, ach->badge_name, sizeof(fa.badge_name)); ++ fa.unlock_time = ach->unlock_time; ++ fa.state = ach->state; ++ fa.category = ach->category; ++ fa.bucket = ach->bucket; ++ fa.rarity = ach->rarity; ++ fa.rarity_hardcore = ach->rarity_hardcore; ++ fa.type = ach->type; ++ fa.badge_url = ach->badge_url; ++ fa.badge_locked_url = ach->badge_locked_url; ++ ++ fa.bucket_type = bucket.bucket_type; ++ fa.label = bucket.label ? bucket.label : ""; ++ fa.num_achievements = bucket.num_achievements; ++ fa.achievements = bucket.achievements; ++ ++ context->allAchievements.push_back(fa); ++ } ++ } ++ ++ rc_client_destroy_achievement_list(list); ++ ++ context->m_suppressProgressFrames = 50; ++ ++ if (context->onGameLoaded) ++ context->onGameLoaded(); ++ }, ++ this ++ ); ++} ++ ++uint32_t RAContext::ReadMemory(uint32_t address, uint8_t* buffer, uint32_t size, rc_client_t* client) ++{ ++ g_ra_mem_reads++; ++ RAContext* ctx = static_cast(rc_client_get_userdata(client)); ++ ++ if (!ctx || !ctx->nds || !buffer || size == 0) ++ return 0; ++ ++ memset(buffer, 0, size); ++ ++ if (address < 0x00400000) ++ { ++ uint32_t count = std::min(size, 0x00400000 - address); ++ memcpy(buffer, ctx->nds->MainRAM + address, count); ++ return count; ++ } ++ ++ if (address >= 0x00400000 && address < 0x00408000) ++ { ++ uint32_t offset = address - 0x00400000; ++ uint32_t count = std::min(size, 0x00408000 - address); ++ memcpy(buffer, ctx->nds->SharedWRAM + offset, count); ++ return count; ++ } ++ ++ if (address >= 0x00408000 && address < 0x00418000) ++ { ++ uint32_t offset = address - 0x00408000; ++ uint32_t count = std::min(size, 0x00418000 - address); ++ memcpy(buffer, ctx->nds->ARM7WRAM + offset, count); ++ return count; ++ } ++ ++ if (address >= 0x00480000 && address < 0x00580000) ++ { ++ uint32_t offset = address - 0x00480000; ++ uint32_t remaining = std::min(size, 0x00580000 - address); ++ uint32_t copied = 0; ++ ++ struct { uint8_t* data; uint32_t size; } banks[] = { ++ {ctx->nds->GPU.VRAM_A, 128*1024}, ++ {ctx->nds->GPU.VRAM_B, 128*1024}, ++ {ctx->nds->GPU.VRAM_C, 128*1024}, ++ {ctx->nds->GPU.VRAM_D, 128*1024}, ++ {ctx->nds->GPU.VRAM_E, 64*1024}, ++ {ctx->nds->GPU.VRAM_F, 16*1024}, ++ {ctx->nds->GPU.VRAM_G, 16*1024}, ++ {ctx->nds->GPU.VRAM_H, 32*1024}, ++ {ctx->nds->GPU.VRAM_I, 16*1024} ++ }; ++ uint32_t bank_offset = 0; ++ ++ for (int i = 0; i < 9; ++i) { ++ if (offset >= bank_offset + banks[i].size) { ++ bank_offset += banks[i].size; ++ continue; ++ } ++ ++ uint32_t local_offset = offset - bank_offset; ++ uint32_t to_copy = std::min(remaining - copied, banks[i].size - local_offset); ++ memcpy(buffer + copied, banks[i].data + local_offset, to_copy); ++ copied += to_copy; ++ ++ if (copied >= remaining) break; ++ ++ bank_offset += banks[i].size; ++ } ++ ++ return copied; ++ } ++ ++ if (address >= 0x00600000 && address < 0x00602000) ++ { ++ uint32_t offset = address - 0x00600000; ++ uint32_t count = std::min(size, 0x00602000 - address); ++ uint32_t io_base = 0x04000000 + offset; ++ ++ for (uint32_t i = 0; i < count; ++i) { ++ buffer[i] = ctx->nds->ARM9Read8(io_base + i); ++ } ++ return count; ++ } ++ return 0; ++} ++ ++static curl_blob s_cacertBlob = { ++ (void*)_accacert, ++ _accacert_len, ++ CURL_BLOB_COPY ++}; ++ ++static std::set s_pendingAchiIDs; ++ ++void RAContext::ServerCall(const rc_api_request_t* request, ++ rc_client_server_callback_t callback, ++ void* userdata, ++ rc_client_t*) ++{ ++ EnsureHTTPThread(); ++ ++ RAHttpJob job; ++ job.url = request->url; ++ job.post_data = request->post_data ? request->post_data : ""; ++ job.callback = callback; ++ job.userdata = userdata; ++ ++ { ++ std::lock_guard lock(s_httpMutex); ++ s_httpJobs.push(std::move(job)); ++ } ++ ++ s_httpCV.notify_one(); ++} ++void RAContext::Reset() { ++ if (client) ++ rc_client_reset(client); ++ ResetGameState(); ++} ++ ++void RAContext::LoginWithPassword(const char* username, const char* password, bool hardcore) ++{ ++ if (!client) return; ++ ++ rc_client_set_hardcore_enabled(client, hardcore ? 1 : 0); ++ ++ rc_client_begin_login_with_password( ++ client, ++ username, ++ password, ++ &LoginPasswordCallback, ++ this ++ ); ++} ++void RAContext::SetCredentials(const char* user, const char* password, bool hardcore) { ++ m_user = user; ++ m_password = password; ++ m_hardcore = hardcore; ++} ++ ++void RAContext::SetPendingGameHash(const char* hash) ++{ ++ if (!hash || !*hash) ++ return; ++ ++ pendingGameHash = std::string(hash); ++ gameLoaded = false; ++} ++void RAContext::AttachNDS(melonDS::NDS* nds_) ++{ ++ if (nds == nds_) ++ return; ++ ++ nds = nds_; ++} ++ ++void RAContext::Enable() ++{ ++ if (m_enabled) ++ return; ++ ++ m_enabled = true; ++ ++ Init(nds); ++ ++ if (!IsLoggedIn()) ++ { ++ LoginNow(); ++ } ++} ++ ++void RAContext::Disable() ++{ ++ if (!m_enabled) ++ return; ++ ++ m_enabled = false; ++ ++ Shutdown(); ++ m_logged_in = false; ++ gameLoaded = false; ++ pendingGameHash.reset(); ++ ResetGameState(); ++} ++ ++void RAContext::LoginNow() ++{ ++ if (m_logged_in) ++ return; ++ ++ if (!m_user.empty() && !m_password.empty()) ++ { ++ LoginWithPassword(m_user.c_str(), m_password.c_str(), m_hardcore); ++ } ++} ++ ++void RAContext::SetOnAchievementUnlocked(AchievementUnlockedCallback cb) ++{ ++ m_onAchievementUnlocked = std::move(cb); ++} ++void RAContext::SetOnAchievementProgress(AchievementProgressCallback cb) ++{ ++ m_onAchievementProgress = std::move(cb); ++} ++ ++void RAContext::SetOnGameLoadedCallback(std::function cb) ++{ ++ onGameLoaded = std::move(cb); ++} ++void RAContext::SetOnMeasuredProgress(MeasuredProgressCallback cb) ++{ ++ m_onMeasuredProgress = std::move(cb); ++} ++void RAContext::ResetGameState() ++{ ++ trackedAchievements.clear(); ++ allAchievements.clear(); ++ activeTrackers.clear(); ++ m_sessionStart = 0; ++ m_accumulatedTime = 0; ++ m_currentGameId = 0; ++} ++void RAContext::showProgressIndicator(const rc_client_achievement_t* ach) ++{ ++ if (ach) { ++ printf("[RA] PROGRESS SHOW: %s (%s)\n", ach->title, ach->measured_progress); ++ } ++} ++ ++void RAContext::updateProgressIndicator(const rc_client_achievement_t* ach) ++{ ++ if (ach) { ++ printf("[RA] PROGRESS UPDATE: %s (%s)\n", ach->title, ach->measured_progress); ++ } ++} ++ ++void RAContext::hideProgressIndicator() ++{ ++ printf("[RA] PROGRESS HIDE\n"); ++} ++ ++void RAContext::SaveSavestate(melonDS::Savestate* file) ++{ ++ printf("wywołanie savesavestate"); ++ if (!client) ++ return; ++ ++ uint32_t size = rc_client_progress_size(client); ++ std::vector buffer(size); ++ ++ if (rc_client_serialize_progress(client, buffer.data()) != RC_OK) ++ return; ++ ++ file->Section("RACH"); ++ file->Var32(&size); ++ file->VarArray(buffer.data(), size); ++} ++ ++void RAContext::LoadSavestate(melonDS::Savestate* file) ++{ ++ printf("wywołanie loadsavestate"); ++ if (!client) ++ return; ++ ++ file->Section("RACH"); ++ ++ if (file->Error) ++ { ++ rc_client_deserialize_progress(client, nullptr); ++ return; ++ } ++ ++ uint32_t size = 0; ++ file->Var32(&size); ++ ++ std::vector buffer(size); ++ file->VarArray(buffer.data(), size); ++ ++ rc_client_deserialize_progress(client, buffer.data()); ++} ++void RAContext::SetOnChallenge(ChallengeShowCallback cb) ++{ ++ m_onChallenge = cb; ++} ++ ++void RAContext::SetOnChallengeHide(ChallengeHideCallback cb) ++{ ++ m_onChallengeHide = cb; ++} ++ ++void RAContext::SetOnGameMastered(GameMasteredCallback cb) ++{ ++ m_onGameMastered = cb; ++} ++const std::vector& RAContext::GetAllAchievements() ++{ ++ if (!client) return allAchievements; ++ ++ for (auto& ach : allAchievements) ++ { ++ const rc_client_achievement_t* rc_ach = rc_client_get_achievement_info(client, ach.id); ++ ++ if (rc_ach) ++ { ++ ach.unlocked = (rc_ach->unlocked != RC_CLIENT_ACHIEVEMENT_UNLOCKED_NONE); ++ ++ if (rc_ach->measured_progress[0] != '\0') ++ { ++ ach.measured = true; ++ ach.progressText = std::string(rc_ach->measured_progress); ++ ach.measured_percent = rc_ach->measured_percent; ++ } ++ else ++ { ++ ach.measured = false; ++ ach.measured_percent = 0.0f; ++ ach.progressText = ""; ++ } ++ } ++ } ++ ++ return allAchievements; ++} ++void RAContext::SavePlaytime() { ++ if (m_currentGameId == 0 || !gameLoaded) return; ++ ++ uint32_t totalMinutes = GetGamePlaytime(); ++ ++ if (m_playtimeSaver) { ++ m_playtimeSaver(m_currentGameId, totalMinutes); ++ } ++} ++bool RAContext::ShouldShowProgress(uint32_t id, unsigned value, unsigned target) { ++ if (target == 0) return false; ++ ++ auto nowObj = std::chrono::steady_clock::now(); ++ uint64_t now = std::chrono::duration_cast(nowObj.time_since_epoch()).count(); ++ ++ auto& s = m_progressThrottle[id]; ++ float percent = (static_cast(value) / static_cast(target)); ++ ++ if (now - s.rapidWindowStart > 3000) { ++ s.rapidWindowStart = now; ++ s.rapidChanges = 0; ++ } ++ if (value != s.lastValue) s.rapidChanges++; ++ ++ if (s.rapidChanges > 5) { ++ s.lastValue = value; ++ return false; ++ } ++ ++ float milestone = 0.0f; ++ if (percent >= 0.95f) milestone = 0.95f; ++ else if (percent >= 0.90f) milestone = 0.90f; ++ else if (percent >= 0.75f) milestone = 0.75f; ++ else if (percent >= 0.50f) milestone = 0.50f; ++ else if (percent >= 0.25f) milestone = 0.25f; ++ ++ if (milestone > s.lastPercent) { ++ s.lastPercent = milestone; ++ s.lastValue = value; ++ s.lastShownMs = now; ++ return true; ++ } ++ ++ return false; ++} ++std::vector RAContext::GetActiveTrackerTexts() { ++ std::vector texts; ++ for (auto const& [id, tracker] : activeTrackers) { ++ texts.push_back(tracker.display); ++ } ++ return texts; ++} ++void RAContext::SetOnLeaderboardTrackerUpdate(LeaderboardTrackerUpdateCallback cb) { ++ m_onLeaderboardTrackerUpdate = std::move(cb); ++} ++ ++void RAContext::SetOnLeaderboardSubmitted(LeaderboardSubmittedCallback cb) { ++ m_onLeaderboardSubmitted = std::move(cb); ++} ++void RAContext::SetOnRADisconnected(std::function cb) ++{ ++ m_onRADisconnected = std::move(cb); ++} ++ ++void RAContext::SetOnRAReconnected(std::function cb) ++{ ++ m_onRAReconnected = std::move(cb); ++} ++ ++void RAContext::SetOnRAPendingSent(RAPendingSentCallback cb) ++{ ++ m_onRAPendingSent = std::move(cb); ++} ++ ++static void PerformServerCall(const RAHttpJob& job) ++{ ++ EnsureCurlInit(); ++ ++ CURL* curl = curl_easy_init(); ++ if (!curl) { ++ return; ++ } ++ ++ curl_easy_setopt(curl, CURLOPT_CAINFO_BLOB, &s_cacertBlob); ++ curl_easy_setopt(curl, CURLOPT_URL, job.url.c_str()); ++ ++ if (!job.post_data.empty()) { ++ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, job.post_data.c_str()); ++ } ++ ++ std::string response_body; ++ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWrite); ++ curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_body); ++ ++ curl_easy_setopt(curl, CURLOPT_TIMEOUT, 15L); ++ curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 5L); ++ ++ CURLcode res = curl_easy_perform(curl); ++ ++ if (res == CURLE_OK) { ++ long http_code = 0; ++ curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code); ++ ++ RAPendingCallback cb; ++ cb.callback = job.callback; ++ cb.userdata = job.userdata; ++ cb.body = std::move(response_body); ++ cb.resp.http_status_code = (int)http_code; ++ // NOTE: resp.body and resp.body_length are set in DoFrame/ProcessAsyncCallbacks ++ // after dequeue, to avoid a dangling pointer after std::move(cb). ++ ++ { ++ std::lock_guard lock(s_cbMutex); ++ s_pendingCallbacks.push(std::move(cb)); ++ } ++ } ++ else { ++ RAPendingCallback cb; ++ cb.callback = job.callback; ++ cb.userdata = job.userdata; ++ cb.resp = {}; ++ { ++ std::lock_guard lock(s_cbMutex); ++ s_pendingCallbacks.push(std::move(cb)); ++ } ++ } ++ ++ curl_easy_cleanup(curl); ++} ++ ++static void EnsureHTTPThread() ++{ ++ if (s_httpRunning) ++ return; ++ ++ s_httpRunning = true; ++ s_httpThread = std::thread([] { ++ while (s_httpRunning) { ++ RAHttpJob job; ++ ++ { ++ std::unique_lock lock(s_httpMutex); ++ s_httpCV.wait(lock, [] { ++ return !s_httpJobs.empty() || !s_httpRunning; ++ }); ++ ++ if (!s_httpRunning) ++ return; ++ ++ job = std::move(s_httpJobs.front()); ++ s_httpJobs.pop(); ++ } ++ ++ PerformServerCall(job); ++ } ++ }); ++} ++ ++void RAContext::ProcessAsyncCallbacks() ++{ ++ std::lock_guard lock(s_cbMutex); ++ while (!s_pendingCallbacks.empty()) ++ { ++ RAPendingCallback cb = std::move(s_pendingCallbacks.front()); ++ s_pendingCallbacks.pop(); ++ ++ cb.resp.body = cb.body.empty() ? nullptr : cb.body.c_str(); ++ cb.resp.body_length = (uint32_t)cb.body.size(); ++ ++ if (cb.callback) { ++ cb.callback(&cb.resp, cb.userdata); ++ } ++ } ++} +diff -rupbN melonDS.orig/src/RetroAchievements/RAClient.h melonDS.ra/src/RetroAchievements/RAClient.h +--- melonDS.orig/src/RetroAchievements/RAClient.h 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/RetroAchievements/RAClient.h 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,250 @@ ++#pragma once ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++using AchievementUnlockedCallback = ++ std::function; ++using MeasuredProgressCallback = ++ std::function; ++using AchievementProgressCallback = ++ std::function; ++using ChallengeShowCallback = ++ std::function; ++using ChallengeHideCallback = ++ std::function; ++using LeaderboardTrackerUpdateCallback = ++ std::function; ++using LeaderboardSubmittedCallback = ++ std::function; ++using GameMasteredCallback = ++ std::function; ++using RADisconnectedCallback = std::function; ++using RAReconnectedCallback = std::function; ++using RAPendingSentCallback = std::function; ++using LoginCallback = std::function; ++using LeaderboardCallback = std::function; ++ ++struct TrackedAchievement ++{ ++ uint32_t id = 0; ++ unsigned prev_value = 0; ++}; ++namespace melonDS { ++ class NDS; ++ class Savestate; ++} ++class RAContext { ++public: ++ void ProcessAsyncCallbacks(); ++ using PlaytimeLoadHandler = std::function; ++ using PlaytimeSaveHandler = std::function; ++ ++ void SetPlaytimeHandlers(PlaytimeLoadHandler loader, PlaytimeSaveHandler saver) { ++ m_playtimeLoader = std::move(loader); ++ m_playtimeSaver = std::move(saver); ++ } ++ int m_suppressProgressFrames = 0; ++ void SaveSavestate(melonDS::Savestate* file); ++ void LoadSavestate(melonDS::Savestate* file); ++ ++ void showProgressIndicator(const rc_client_achievement_t* ach); ++ void updateProgressIndicator(const rc_client_achievement_t* ach); ++ void hideProgressIndicator(); ++ struct LeaderboardTracker { ++ uint32_t id; ++ std::string display; ++ }; ++ std::unordered_map activeTrackers; ++ friend uint32_t RC_CCONV RuntimePeek(uint32_t, uint32_t, void*); ++ struct FullAchievement ++ { ++ uint32_t id = 0; ++ std::string title; ++ std::string description; ++ uint32_t points = 0; ++ bool unlocked = false; ++ ++ bool measured = false; ++ int value = 0; ++ int target = 0; ++ std::string progressText; ++ ++ char badge_name[8] = {}; ++ float measured_percent = 0.0f; ++ time_t unlock_time = 0; ++ uint8_t state = 0; ++ uint8_t category = 0; ++ uint8_t bucket = 0; ++ float rarity = 0.0f; ++ float rarity_hardcore = 0.0f; ++ uint8_t type = 0; ++ const char* badge_url = nullptr; ++ const char* badge_locked_url = nullptr; ++ const rc_client_achievement_t** achievements = nullptr; ++ uint32_t num_achievements; ++ ++ const char* label; ++ uint32_t subset_id; ++ uint8_t bucket_type; ++ }; ++ ++ ++ const std::vector& GetAllAchievements(); ++ void ResetGameState(); ++ RAContext(); ++ ~RAContext(); ++ bool m_shuttingDown = false; ++ bool m_IsPaused = false; ++ bool CanPause(uint32_t* frames_remaining); ++ void SetPaused(bool paused); ++ std::function onLoginResponse; ++ bool pendingLoginResult = false; ++ bool loginSuccess = false; ++ std::string loginErrorMessage; ++ bool isLoading = false; ++ std::string m_lastHash; ++ std::string pendingLoadError; ++ bool pendingLoadFailed = false; ++ void SetOnGameLoadedCallback(std::function cb); ++ std::function onGameLoaded; ++ const rc_client_game_t* GetCurrentGameInfo() const { return currentGameInfo; } ++ bool IsGameLoaded() const { return gameLoaded; } ++ void SetOnAchievementUnlocked(AchievementUnlockedCallback cb); ++ void SetOnAchievementProgress(AchievementProgressCallback cb); ++ void SetOnChallenge(ChallengeShowCallback cb); ++ void SetOnChallengeHide(ChallengeHideCallback cb); ++ void SetOnLeaderboardTrackerUpdate(LeaderboardTrackerUpdateCallback cb); ++ void SetOnLeaderboardSubmitted(LeaderboardSubmittedCallback cb); ++ void SetOnRADisconnected(RADisconnectedCallback cb); ++ void SetOnRAReconnected(RAReconnectedCallback cb); ++ void SetOnRAPendingSent(RAPendingSentCallback cb); ++ void SetOnGameMastered(GameMasteredCallback cb); ++ void SetOnMeasuredProgress(MeasuredProgressCallback cb); ++ void SetOnLogin(LoginCallback cb); ++ void UpdateMeasuredAchievements(); ++ void LoginNow(); ++ void Enable(); ++ void Disable(); ++ bool IsEnabled() const { return m_enabled; } ++ bool IsHardcoreEnabled() const { return m_hardcore; } ++ void SetEncoreMode(bool enabled); ++ void SetUnofficialEnabled(bool enabled); ++ void AttachNDS(melonDS::NDS* nds_); ++ void SetPendingGameHash(const char* hash); ++ void SetToken(const std::string& token) { m_token = token; } ++ void SetLoggedIn(bool v); ++ void Init(melonDS::NDS* nds); ++ void Shutdown(); ++ void DoFrame(); ++ void LoginWithPassword(const char* username, const char* password, bool hardcore); ++ void SetCredentials(const char* user, const char* password, bool hardcore); ++ void LoadGame(const char* hash); ++ void Reset(); ++ bool IsLoggedIn() const { return m_logged_in; } ++ const std::string& GetUser() const { return m_user; } ++ const std::string& GetToken() const { return m_token; } ++ const std::string& GetDisplayName() const; ++ melonDS::NDS* nds = nullptr; ++ rc_client_t* client = nullptr; ++ bool m_logged_in = false; ++ const char* GetUserPicURL() const { ++ const rc_client_user_t* user = rc_client_get_user_info(client); ++ return (user) ? user->avatar_url : nullptr; ++ } ++ ++ const char* GetGameTitle() const { ++ const rc_client_game_t* game = rc_client_get_game_info(client); ++ return (game) ? game->title : "Unknown Game"; ++ } ++ ++ const char* GetGameIconURL() const { ++ const rc_client_game_t* game = rc_client_get_game_info(client); ++ return (game) ? game->badge_url : nullptr; ++ } ++ ++ uint32_t GetGameID() const { ++ const rc_client_game_t* game = rc_client_get_game_info(client); ++ return (game) ? game->id : 0; ++ } ++ uint32_t GetGamePlaytime() const { ++ if (!gameLoaded || m_sessionStart == 0) return m_accumulatedTime; ++ uint32_t sessionMinutes = (uint32_t)((time(nullptr) - m_sessionStart) / 60); ++ return m_accumulatedTime + sessionMinutes; ++ } ++ std::vector GetActiveTrackerTexts(); ++private: ++ void InitHTTPThread(); ++ struct ProgressThrottleState { ++ unsigned lastValue = 0; ++ float lastPercent = 0.0f; ++ uint64_t lastShownMs = 0; ++ int rapidChanges = 0; ++ uint64_t rapidWindowStart = 0; ++ }; ++ ++ std::unordered_map m_progressThrottle; ++ bool ShouldShowProgress(uint32_t id, unsigned value, unsigned target); ++ PlaytimeLoadHandler m_playtimeLoader; ++ PlaytimeSaveHandler m_playtimeSaver; ++ void SavePlaytime(); ++ time_t m_sessionStart = 0; ++ uint32_t m_accumulatedTime = 0; ++ uint32_t m_currentGameId = 0; ++ rc_runtime_t m_runtime; ++ std::vector trackedAchievements; ++ std::vector allAchievements; ++ void SetDisplayName(const char* name); ++ LeaderboardCallback onLeaderboardStarted; ++ LeaderboardCallback onLeaderboardFailed; ++ LeaderboardCallback onLeaderboardSubmitted; ++ AchievementUnlockedCallback m_onAchievementUnlocked; ++ MeasuredProgressCallback m_onMeasuredProgress; ++ AchievementProgressCallback m_onAchievementProgress; ++ ChallengeShowCallback m_onChallenge; ++ ChallengeHideCallback m_onChallengeHide; ++ LeaderboardTrackerUpdateCallback m_onLeaderboardTrackerUpdate; ++ LeaderboardSubmittedCallback m_onLeaderboardSubmitted; ++ GameMasteredCallback m_onGameMastered; ++ RADisconnectedCallback m_onRADisconnected; ++ RAReconnectedCallback m_onRAReconnected; ++ RAPendingSentCallback m_onRAPendingSent; ++ LoginCallback m_onLogin; ++ std::string m_displayName; ++ const rc_client_game_t* currentGameInfo = nullptr; ++ bool m_enabled = false; ++ std::optional pendingGameHash; ++ bool gameLoaded = false; ++ std::string m_user; ++ std::string m_token; ++ std::string m_password; ++ bool m_hardcore = false; ++ static uint32_t ReadMemory( ++ uint32_t address, ++ uint8_t* buffer, ++ uint32_t size, ++ rc_client_t* client ++ ); ++ static void ServerCall( ++ const rc_api_request_t* request, ++ rc_client_server_callback_t callback, ++ void* userdata, ++ rc_client_t* client ++ ); ++}; +\ No newline at end of file +diff -rupbN melonDS.orig/src/RetroAchievements/cacert.c melonDS.ra/src/RetroAchievements/cacert.c +--- melonDS.orig/src/RetroAchievements/cacert.c 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/RetroAchievements/cacert.c 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,5642 @@ ++/* ++ C-file generated by Bin2C ++ Compiled: Nov 20 2025 at 10:44:24 ++ ++ Copyright (C) 2018 ++ Segger Microcontroller GmbH ++ www.segger.com ++ ++ The Embedded Experts ++*/ ++ ++const unsigned char _accacert[225076UL + 1] = { ++ 0x23, 0x23, 0x0A, 0x23, 0x23, 0x20, 0x42, 0x75, 0x6E, 0x64, 0x6C, 0x65, 0x20, 0x6F, 0x66, 0x20, 0x43, 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x0A, 0x23, 0x23, 0x0A, ++ 0x23, 0x23, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x4D, 0x6F, 0x7A, 0x69, 0x6C, 0x6C, 0x61, 0x20, 0x61, 0x73, 0x20, 0x6F, 0x66, 0x3A, 0x20, ++ 0x54, 0x75, 0x65, 0x20, 0x44, 0x65, 0x63, 0x20, 0x20, 0x32, 0x20, 0x30, 0x34, 0x3A, 0x31, 0x32, 0x3A, 0x30, 0x32, 0x20, 0x32, 0x30, 0x32, 0x35, 0x20, 0x47, 0x4D, 0x54, 0x0A, 0x23, 0x23, 0x0A, 0x23, 0x23, 0x20, 0x46, 0x69, 0x6E, 0x64, 0x20, ++ 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x68, 0x65, 0x72, 0x65, 0x3A, 0x20, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3A, 0x2F, 0x2F, 0x63, 0x75, 0x72, 0x6C, 0x2E, 0x73, 0x65, 0x2F, 0x64, ++ 0x6F, 0x63, 0x73, 0x2F, 0x63, 0x61, 0x65, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, 0x2E, 0x68, 0x74, 0x6D, 0x6C, 0x0A, 0x23, 0x23, 0x0A, 0x23, 0x23, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x62, 0x75, 0x6E, 0x64, 0x6C, ++ 0x65, 0x20, 0x6F, 0x66, 0x20, 0x58, 0x2E, 0x35, 0x30, 0x39, 0x20, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x20, 0x6F, 0x66, 0x20, 0x70, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, ++ 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x69, 0x65, 0x73, 0x0A, 0x23, 0x23, 0x20, 0x28, 0x43, 0x41, 0x29, 0x2E, 0x20, 0x54, 0x68, 0x65, 0x73, 0x65, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x61, 0x75, ++ 0x74, 0x6F, 0x6D, 0x61, 0x74, 0x69, 0x63, 0x61, 0x6C, 0x6C, 0x79, 0x20, 0x65, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x4D, 0x6F, 0x7A, 0x69, 0x6C, 0x6C, 0x61, 0x27, 0x73, 0x20, 0x72, 0x6F, 0x6F, ++ 0x74, 0x20, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x0A, 0x23, 0x23, 0x20, 0x66, 0x69, 0x6C, 0x65, 0x20, 0x28, 0x63, 0x65, 0x72, 0x74, 0x64, 0x61, 0x74, 0x61, 0x2E, 0x74, 0x78, 0x74, 0x29, 0x2E, 0x20, 0x20, ++ 0x54, 0x68, 0x69, 0x73, 0x20, 0x66, 0x69, 0x6C, 0x65, 0x20, 0x63, 0x61, 0x6E, 0x20, 0x62, 0x65, 0x20, 0x66, 0x6F, 0x75, 0x6E, 0x64, 0x20, 0x69, 0x6E, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6D, 0x6F, 0x7A, 0x69, 0x6C, 0x6C, 0x61, 0x20, 0x73, 0x6F, ++ 0x75, 0x72, 0x63, 0x65, 0x20, 0x74, 0x72, 0x65, 0x65, 0x3A, 0x0A, 0x23, 0x23, 0x20, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3A, 0x2F, 0x2F, 0x72, 0x61, 0x77, 0x2E, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x75, 0x73, 0x65, 0x72, 0x63, 0x6F, 0x6E, 0x74, ++ 0x65, 0x6E, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x6D, 0x6F, 0x7A, 0x69, 0x6C, 0x6C, 0x61, 0x2D, 0x66, 0x69, 0x72, 0x65, 0x66, 0x6F, 0x78, 0x2F, 0x66, 0x69, 0x72, 0x65, 0x66, 0x6F, 0x78, 0x2F, 0x72, 0x65, 0x66, 0x73, 0x2F, 0x68, 0x65, 0x61, ++ 0x64, 0x73, 0x2F, 0x72, 0x65, 0x6C, 0x65, 0x61, 0x73, 0x65, 0x2F, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x2F, 0x6E, 0x73, 0x73, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x63, 0x6B, 0x66, 0x77, 0x2F, 0x62, 0x75, 0x69, 0x6C, 0x74, 0x69, 0x6E, ++ 0x73, 0x2F, 0x63, 0x65, 0x72, 0x74, 0x64, 0x61, 0x74, 0x61, 0x2E, 0x74, 0x78, 0x74, 0x0A, 0x23, 0x23, 0x0A, 0x23, 0x23, 0x20, 0x49, 0x74, 0x20, 0x63, 0x6F, 0x6E, 0x74, 0x61, 0x69, 0x6E, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x65, 0x72, ++ 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x20, 0x69, 0x6E, 0x20, 0x50, 0x45, 0x4D, 0x20, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x66, 0x6F, 0x72, 0x65, 0x0A, 0x23, 0x23, ++ 0x20, 0x63, 0x61, 0x6E, 0x20, 0x62, 0x65, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6C, 0x79, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x63, 0x75, 0x72, 0x6C, 0x20, 0x2F, 0x20, 0x6C, 0x69, 0x62, 0x63, 0x75, 0x72, ++ 0x6C, 0x20, 0x2F, 0x20, 0x70, 0x68, 0x70, 0x5F, 0x63, 0x75, 0x72, 0x6C, 0x2C, 0x20, 0x6F, 0x72, 0x20, 0x77, 0x69, 0x74, 0x68, 0x0A, 0x23, 0x23, 0x20, 0x61, 0x6E, 0x20, 0x41, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2B, 0x6D, 0x6F, 0x64, 0x5F, 0x73, ++ 0x73, 0x6C, 0x20, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x53, 0x53, 0x4C, 0x20, 0x63, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x20, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, ++ 0x6F, 0x6E, 0x2E, 0x0A, 0x23, 0x23, 0x20, 0x4A, 0x75, 0x73, 0x74, 0x20, 0x63, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x66, 0x69, 0x6C, 0x65, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x53, ++ 0x53, 0x4C, 0x43, 0x41, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6C, 0x65, 0x2E, 0x0A, 0x23, 0x23, 0x0A, 0x23, 0x23, 0x20, 0x43, 0x6F, 0x6E, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x20, 0x64, 0x6F, ++ 0x6E, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6D, 0x6B, 0x2D, 0x63, 0x61, 0x2D, 0x62, 0x75, 0x6E, 0x64, 0x6C, 0x65, 0x2E, 0x70, 0x6C, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x20, 0x31, 0x2E, 0x33, 0x30, 0x2E, 0x0A, 0x23, 0x23, ++ 0x20, 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, 0x3A, 0x20, 0x61, 0x39, 0x30, 0x33, 0x62, 0x33, 0x63, 0x64, 0x30, 0x35, 0x32, 0x33, 0x31, 0x65, 0x33, 0x39, 0x33, 0x33, 0x32, 0x35, 0x31, 0x35, 0x65, 0x66, 0x37, 0x65, 0x62, 0x65, 0x33, 0x37, 0x65, ++ 0x36, 0x39, 0x37, 0x32, 0x36, 0x32, 0x66, 0x33, 0x39, 0x35, 0x31, 0x35, 0x61, 0x35, 0x32, 0x30, 0x31, 0x35, 0x63, 0x32, 0x33, 0x63, 0x36, 0x32, 0x38, 0x30, 0x35, 0x62, 0x37, 0x33, 0x63, 0x64, 0x30, 0x0A, 0x23, 0x23, 0x0A, 0x0A, 0x0A, 0x45, ++ 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, ++ 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x45, 0x6B, 0x54, 0x43, 0x43, 0x41, 0x33, 0x6D, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, ++ 0x45, 0x52, 0x57, 0x74, 0x51, 0x56, 0x44, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x55, 0x46, 0x41, 0x44, 0x43, 0x42, 0x73, 0x44, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, ++ 0x45, 0x42, 0x68, 0x4D, 0x43, 0x56, 0x56, 0x4D, 0x78, 0x46, 0x6A, 0x41, 0x55, 0x42, 0x67, 0x4E, 0x56, 0x0A, 0x42, 0x41, 0x6F, 0x54, 0x44, 0x55, 0x56, 0x75, 0x64, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x51, 0x73, 0x49, 0x45, 0x6C, 0x75, 0x59, 0x79, ++ 0x34, 0x78, 0x4F, 0x54, 0x41, 0x33, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x73, 0x54, 0x4D, 0x48, 0x64, 0x33, 0x64, 0x79, 0x35, 0x6C, 0x62, 0x6E, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x4C, 0x6D, 0x35, 0x6C, 0x64, 0x43, 0x39, 0x44, 0x55, 0x46, ++ 0x4D, 0x67, 0x61, 0x58, 0x4D, 0x67, 0x61, 0x57, 0x35, 0x6A, 0x62, 0x33, 0x4A, 0x77, 0x0A, 0x62, 0x33, 0x4A, 0x68, 0x64, 0x47, 0x56, 0x6B, 0x49, 0x47, 0x4A, 0x35, 0x49, 0x48, 0x4A, 0x6C, 0x5A, 0x6D, 0x56, 0x79, 0x5A, 0x57, 0x35, 0x6A, 0x5A, ++ 0x54, 0x45, 0x66, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x78, 0x4D, 0x57, 0x4B, 0x47, 0x4D, 0x70, 0x49, 0x44, 0x49, 0x77, 0x4D, 0x44, 0x59, 0x67, 0x52, 0x57, 0x35, 0x30, 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x43, 0x77, 0x67, 0x53, ++ 0x57, 0x35, 0x6A, 0x4C, 0x6A, 0x45, 0x74, 0x4D, 0x43, 0x73, 0x47, 0x0A, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x6B, 0x52, 0x57, 0x35, 0x30, 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x43, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x6C, ++ 0x63, 0x6E, 0x52, 0x70, 0x5A, 0x6D, 0x6C, 0x6A, 0x59, 0x58, 0x52, 0x70, 0x62, 0x32, 0x34, 0x67, 0x51, 0x58, 0x56, 0x30, 0x61, 0x47, 0x39, 0x79, 0x61, 0x58, 0x52, 0x35, 0x4D, 0x42, 0x34, 0x58, 0x44, 0x54, 0x41, 0x32, 0x4D, 0x54, 0x45, 0x79, ++ 0x4E, 0x7A, 0x49, 0x77, 0x4D, 0x6A, 0x4D, 0x30, 0x0A, 0x4D, 0x6C, 0x6F, 0x58, 0x44, 0x54, 0x49, 0x32, 0x4D, 0x54, 0x45, 0x79, 0x4E, 0x7A, 0x49, 0x77, 0x4E, 0x54, 0x4D, 0x30, 0x4D, 0x6C, 0x6F, 0x77, 0x67, 0x62, 0x41, 0x78, 0x43, 0x7A, 0x41, ++ 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6C, 0x56, 0x54, 0x4D, 0x52, 0x59, 0x77, 0x46, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x45, 0x77, 0x31, 0x46, 0x62, 0x6E, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x4C, 0x43, 0x42, ++ 0x4A, 0x62, 0x6D, 0x4D, 0x75, 0x0A, 0x4D, 0x54, 0x6B, 0x77, 0x4E, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4C, 0x45, 0x7A, 0x42, 0x33, 0x64, 0x33, 0x63, 0x75, 0x5A, 0x57, 0x35, 0x30, 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x43, 0x35, 0x75, 0x5A, 0x58, ++ 0x51, 0x76, 0x51, 0x31, 0x42, 0x54, 0x49, 0x47, 0x6C, 0x7A, 0x49, 0x47, 0x6C, 0x75, 0x59, 0x32, 0x39, 0x79, 0x63, 0x47, 0x39, 0x79, 0x59, 0x58, 0x52, 0x6C, 0x5A, 0x43, 0x42, 0x69, 0x65, 0x53, 0x42, 0x79, 0x5A, 0x57, 0x5A, 0x6C, 0x63, 0x6D, ++ 0x56, 0x75, 0x0A, 0x59, 0x32, 0x55, 0x78, 0x48, 0x7A, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x73, 0x54, 0x46, 0x69, 0x68, 0x6A, 0x4B, 0x53, 0x41, 0x79, 0x4D, 0x44, 0x41, 0x32, 0x49, 0x45, 0x56, 0x75, 0x64, 0x48, 0x4A, 0x31, 0x63, ++ 0x33, 0x51, 0x73, 0x49, 0x45, 0x6C, 0x75, 0x59, 0x79, 0x34, 0x78, 0x4C, 0x54, 0x41, 0x72, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x4A, 0x45, 0x56, 0x75, 0x64, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x51, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x0A, ++ 0x64, 0x43, 0x42, 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x61, 0x57, 0x5A, 0x70, 0x59, 0x32, 0x46, 0x30, 0x61, 0x57, 0x39, 0x75, 0x49, 0x45, 0x46, 0x31, 0x64, 0x47, 0x68, 0x76, 0x63, 0x6D, 0x6C, 0x30, 0x65, 0x54, 0x43, 0x43, 0x41, 0x53, 0x49, 0x77, ++ 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x45, 0x50, 0x41, 0x44, 0x43, 0x43, 0x41, 0x51, 0x6F, 0x43, 0x67, 0x67, 0x45, 0x42, 0x0A, 0x41, 0x4C, 0x61, ++ 0x56, 0x74, 0x6B, 0x4E, 0x43, 0x2B, 0x73, 0x5A, 0x74, 0x4B, 0x6D, 0x39, 0x49, 0x33, 0x35, 0x52, 0x4D, 0x4F, 0x56, 0x63, 0x46, 0x37, 0x73, 0x4E, 0x35, 0x45, 0x55, 0x46, 0x6F, 0x4E, 0x75, 0x33, 0x73, 0x2F, 0x70, 0x6F, 0x42, 0x6A, 0x36, 0x45, ++ 0x34, 0x4B, 0x50, 0x7A, 0x33, 0x45, 0x45, 0x5A, 0x6D, 0x4C, 0x6B, 0x30, 0x65, 0x47, 0x72, 0x45, 0x61, 0x54, 0x73, 0x62, 0x52, 0x77, 0x4A, 0x57, 0x49, 0x73, 0x4D, 0x6E, 0x2F, 0x4D, 0x59, 0x73, 0x7A, 0x0A, 0x41, 0x39, 0x75, 0x33, 0x67, 0x33, ++ 0x73, 0x2B, 0x49, 0x49, 0x52, 0x65, 0x37, 0x62, 0x4A, 0x57, 0x4B, 0x4B, 0x66, 0x34, 0x34, 0x4C, 0x6C, 0x41, 0x63, 0x54, 0x66, 0x46, 0x79, 0x30, 0x63, 0x4F, 0x6C, 0x79, 0x70, 0x6F, 0x77, 0x43, 0x4B, 0x56, 0x59, 0x68, 0x58, 0x62, 0x52, 0x39, ++ 0x6E, 0x31, 0x30, 0x43, 0x76, 0x2F, 0x67, 0x6B, 0x76, 0x4A, 0x72, 0x54, 0x37, 0x65, 0x54, 0x4E, 0x75, 0x51, 0x67, 0x46, 0x41, 0x2F, 0x43, 0x59, 0x71, 0x45, 0x41, 0x4F, 0x77, 0x77, 0x0A, 0x43, 0x6A, 0x30, 0x59, 0x7A, 0x66, 0x76, 0x39, 0x4B, ++ 0x6C, 0x6D, 0x61, 0x49, 0x35, 0x55, 0x58, 0x4C, 0x45, 0x57, 0x65, 0x48, 0x32, 0x35, 0x44, 0x65, 0x57, 0x30, 0x4D, 0x58, 0x4A, 0x6A, 0x2B, 0x53, 0x4B, 0x66, 0x46, 0x49, 0x30, 0x64, 0x63, 0x58, 0x76, 0x31, 0x75, 0x35, 0x78, 0x36, 0x30, 0x39, ++ 0x6D, 0x68, 0x46, 0x30, 0x59, 0x61, 0x44, 0x57, 0x36, 0x4B, 0x4B, 0x6A, 0x62, 0x48, 0x6A, 0x4B, 0x59, 0x44, 0x2B, 0x4A, 0x58, 0x47, 0x49, 0x72, 0x62, 0x36, 0x38, 0x0A, 0x6A, 0x36, 0x78, 0x53, 0x6C, 0x6B, 0x75, 0x71, 0x55, 0x59, 0x33, 0x6B, ++ 0x45, 0x7A, 0x45, 0x5A, 0x36, 0x45, 0x35, 0x4E, 0x6E, 0x39, 0x75, 0x73, 0x73, 0x32, 0x72, 0x56, 0x76, 0x44, 0x6C, 0x55, 0x63, 0x63, 0x70, 0x36, 0x65, 0x6E, 0x2B, 0x51, 0x33, 0x58, 0x30, 0x64, 0x67, 0x4E, 0x6D, 0x42, 0x75, 0x31, 0x6B, 0x6D, ++ 0x77, 0x68, 0x48, 0x2B, 0x35, 0x70, 0x50, 0x69, 0x39, 0x34, 0x44, 0x6B, 0x5A, 0x66, 0x73, 0x30, 0x4E, 0x77, 0x34, 0x70, 0x67, 0x48, 0x42, 0x4E, 0x0A, 0x72, 0x7A, 0x69, 0x47, 0x4C, 0x70, 0x35, 0x2F, 0x56, 0x36, 0x2B, 0x65, 0x46, 0x36, 0x37, ++ 0x72, 0x48, 0x4D, 0x73, 0x6F, 0x49, 0x56, 0x2B, 0x32, 0x48, 0x4E, 0x6A, 0x6E, 0x6F, 0x67, 0x51, 0x69, 0x2B, 0x64, 0x50, 0x61, 0x32, 0x4D, 0x73, 0x43, 0x41, 0x77, 0x45, 0x41, 0x41, 0x61, 0x4F, 0x42, 0x73, 0x44, 0x43, 0x42, 0x72, 0x54, 0x41, ++ 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x51, 0x59, 0x77, 0x0A, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, ++ 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x72, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x52, 0x41, 0x45, 0x4A, 0x44, 0x41, 0x69, 0x67, 0x41, 0x38, 0x79, 0x4D, 0x44, 0x41, 0x32, 0x4D, 0x54, 0x45, 0x79, 0x4E, 0x7A, 0x49, 0x77, 0x4D, 0x6A, 0x4D, 0x30, 0x4D, 0x6C, ++ 0x71, 0x42, 0x44, 0x7A, 0x49, 0x77, 0x4D, 0x6A, 0x59, 0x78, 0x4D, 0x54, 0x49, 0x33, 0x4D, 0x6A, 0x41, 0x31, 0x0A, 0x4D, 0x7A, 0x51, 0x79, 0x57, 0x6A, 0x41, 0x66, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x53, 0x4D, 0x45, 0x47, 0x44, 0x41, 0x57, 0x67, ++ 0x42, 0x52, 0x6F, 0x6B, 0x4F, 0x52, 0x6E, 0x70, 0x4B, 0x5A, 0x54, 0x67, 0x4D, 0x65, 0x47, 0x5A, 0x71, 0x54, 0x78, 0x39, 0x30, 0x74, 0x44, 0x2B, 0x34, 0x53, 0x39, 0x62, 0x54, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, ++ 0x67, 0x51, 0x55, 0x61, 0x4A, 0x44, 0x6B, 0x5A, 0x36, 0x53, 0x6D, 0x55, 0x34, 0x44, 0x48, 0x0A, 0x68, 0x6D, 0x61, 0x6B, 0x38, 0x66, 0x64, 0x4C, 0x51, 0x2F, 0x75, 0x45, 0x76, 0x57, 0x30, 0x77, 0x48, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, ++ 0x68, 0x76, 0x5A, 0x39, 0x42, 0x30, 0x45, 0x41, 0x42, 0x42, 0x41, 0x77, 0x44, 0x68, 0x73, 0x49, 0x56, 0x6A, 0x63, 0x75, 0x4D, 0x54, 0x6F, 0x30, 0x4C, 0x6A, 0x41, 0x44, 0x41, 0x67, 0x53, 0x51, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, ++ 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x42, 0x51, 0x55, 0x41, 0x0A, 0x41, 0x34, 0x49, 0x42, 0x41, 0x51, 0x43, 0x54, 0x31, 0x44, 0x43, 0x77, 0x31, 0x77, 0x4D, 0x67, 0x4B, 0x74, 0x44, 0x35, 0x59, 0x2B, 0x69, 0x52, 0x44, 0x41, 0x55, ++ 0x67, 0x71, 0x56, 0x38, 0x5A, 0x79, 0x6E, 0x74, 0x79, 0x54, 0x74, 0x53, 0x78, 0x32, 0x39, 0x43, 0x57, 0x2B, 0x31, 0x52, 0x61, 0x47, 0x53, 0x77, 0x4D, 0x43, 0x50, 0x65, 0x79, 0x76, 0x49, 0x57, 0x6F, 0x6E, 0x58, 0x39, 0x74, 0x4F, 0x31, 0x4B, ++ 0x7A, 0x4B, 0x74, 0x76, 0x6E, 0x31, 0x49, 0x53, 0x4D, 0x0A, 0x59, 0x2F, 0x59, 0x50, 0x79, 0x79, 0x59, 0x42, 0x6B, 0x56, 0x42, 0x73, 0x39, 0x46, 0x38, 0x55, 0x34, 0x70, 0x4E, 0x30, 0x77, 0x42, 0x4F, 0x65, 0x4D, 0x44, 0x70, 0x51, 0x34, 0x37, ++ 0x52, 0x67, 0x78, 0x52, 0x7A, 0x77, 0x49, 0x6B, 0x53, 0x4E, 0x63, 0x55, 0x65, 0x73, 0x79, 0x42, 0x72, 0x4A, 0x36, 0x5A, 0x75, 0x61, 0x41, 0x47, 0x41, 0x54, 0x2F, 0x33, 0x42, 0x2B, 0x58, 0x78, 0x46, 0x4E, 0x53, 0x52, 0x75, 0x7A, 0x46, 0x56, ++ 0x4A, 0x37, 0x79, 0x56, 0x54, 0x61, 0x0A, 0x76, 0x35, 0x32, 0x56, 0x72, 0x32, 0x75, 0x61, 0x32, 0x4A, 0x37, 0x70, 0x38, 0x65, 0x52, 0x44, 0x6A, 0x65, 0x49, 0x52, 0x52, 0x44, 0x71, 0x2F, 0x72, 0x37, 0x32, 0x44, 0x51, 0x6E, 0x4E, 0x53, 0x69, ++ 0x36, 0x71, 0x37, 0x70, 0x79, 0x6E, 0x50, 0x39, 0x57, 0x51, 0x63, 0x43, 0x6B, 0x33, 0x52, 0x76, 0x4B, 0x71, 0x73, 0x6E, 0x79, 0x72, 0x51, 0x2F, 0x33, 0x39, 0x2F, 0x32, 0x6E, 0x33, 0x71, 0x73, 0x65, 0x30, 0x77, 0x4A, 0x63, 0x47, 0x45, 0x32, ++ 0x6A, 0x54, 0x53, 0x0A, 0x57, 0x33, 0x69, 0x44, 0x56, 0x75, 0x79, 0x63, 0x4E, 0x73, 0x4D, 0x6D, 0x34, 0x68, 0x48, 0x32, 0x5A, 0x30, 0x6B, 0x64, 0x6B, 0x71, 0x75, 0x4D, 0x2B, 0x2B, 0x76, 0x2F, 0x65, 0x75, 0x36, 0x46, 0x53, 0x71, 0x64, 0x51, ++ 0x67, 0x50, 0x43, 0x6E, 0x58, 0x45, 0x71, 0x55, 0x4C, 0x6C, 0x38, 0x46, 0x6D, 0x54, 0x78, 0x53, 0x51, 0x65, 0x44, 0x4E, 0x74, 0x47, 0x50, 0x50, 0x41, 0x55, 0x4F, 0x36, 0x6E, 0x49, 0x50, 0x63, 0x6A, 0x32, 0x41, 0x37, 0x38, 0x31, 0x71, 0x30, ++ 0x0A, 0x74, 0x48, 0x75, 0x75, 0x32, 0x67, 0x75, 0x51, 0x4F, 0x48, 0x58, 0x76, 0x67, 0x52, 0x31, 0x6D, 0x30, 0x76, 0x64, 0x58, 0x63, 0x44, 0x61, 0x7A, 0x76, 0x2F, 0x77, 0x6F, 0x72, 0x33, 0x45, 0x6C, 0x68, 0x56, 0x73, 0x54, 0x2F, 0x68, 0x35, ++ 0x2F, 0x57, 0x72, 0x51, 0x38, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, ++ 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, ++ 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x74, 0x7A, 0x43, 0x43, 0x41, 0x35, 0x2B, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x43, 0x42, ++ 0x51, 0x6B, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x46, 0x42, 0x51, 0x41, 0x77, 0x52, 0x54, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x51, ++ 0x6B, 0x30, 0x78, 0x47, 0x54, 0x41, 0x58, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x0A, 0x45, 0x46, 0x46, 0x31, 0x62, 0x31, 0x5A, 0x68, 0x5A, 0x47, 0x6C, 0x7A, 0x49, 0x45, 0x78, 0x70, 0x62, 0x57, 0x6C, 0x30, 0x5A, 0x57, 0x51, 0x78, ++ 0x47, 0x7A, 0x41, 0x5A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x45, 0x6C, 0x46, 0x31, 0x62, 0x31, 0x5A, 0x68, 0x5A, 0x47, 0x6C, 0x7A, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x67, 0x4D, 0x6A, 0x41, 0x65, ++ 0x46, 0x77, 0x30, 0x77, 0x4E, 0x6A, 0x45, 0x78, 0x4D, 0x6A, 0x51, 0x78, 0x0A, 0x4F, 0x44, 0x49, 0x33, 0x4D, 0x44, 0x42, 0x61, 0x46, 0x77, 0x30, 0x7A, 0x4D, 0x54, 0x45, 0x78, 0x4D, 0x6A, 0x51, 0x78, 0x4F, 0x44, 0x49, 0x7A, 0x4D, 0x7A, 0x4E, ++ 0x61, 0x4D, 0x45, 0x55, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6B, 0x4A, 0x4E, 0x4D, 0x52, 0x6B, 0x77, 0x46, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x45, 0x78, 0x42, 0x52, 0x64, 0x57, 0x39, ++ 0x57, 0x59, 0x57, 0x52, 0x70, 0x63, 0x79, 0x42, 0x4D, 0x0A, 0x61, 0x57, 0x31, 0x70, 0x64, 0x47, 0x56, 0x6B, 0x4D, 0x52, 0x73, 0x77, 0x47, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x4A, 0x52, 0x64, 0x57, 0x39, 0x57, 0x59, 0x57, ++ 0x52, 0x70, 0x63, 0x79, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x42, 0x49, 0x44, 0x49, 0x77, 0x67, 0x67, 0x49, 0x69, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, ++ 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x0A, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x49, 0x4B, 0x41, 0x6F, 0x49, 0x43, 0x41, 0x51, 0x43, 0x61, 0x47, 0x4D, 0x70, 0x4C, 0x6C, 0x41, 0x30, 0x41, 0x4C, 0x61, 0x38, 0x44, 0x4B, 0x59, 0x72, 0x77, 0x44, ++ 0x34, 0x48, 0x49, 0x72, 0x6B, 0x77, 0x5A, 0x68, 0x52, 0x30, 0x49, 0x6E, 0x36, 0x73, 0x70, 0x52, 0x49, 0x58, 0x7A, 0x4C, 0x34, 0x47, 0x74, 0x4D, 0x68, 0x36, 0x51, 0x52, 0x72, 0x2B, 0x6A, 0x68, 0x69, 0x59, 0x61, 0x48, 0x76, 0x35, 0x2B, 0x48, ++ 0x42, 0x67, 0x36, 0x0A, 0x58, 0x4A, 0x78, 0x67, 0x46, 0x79, 0x6F, 0x36, 0x64, 0x49, 0x4D, 0x7A, 0x4D, 0x48, 0x31, 0x68, 0x56, 0x42, 0x48, 0x4C, 0x37, 0x61, 0x76, 0x67, 0x35, 0x74, 0x4B, 0x69, 0x66, 0x76, 0x56, 0x72, 0x62, 0x78, 0x69, 0x33, ++ 0x43, 0x67, 0x73, 0x74, 0x2F, 0x65, 0x6B, 0x2B, 0x37, 0x77, 0x72, 0x47, 0x73, 0x78, 0x44, 0x70, 0x33, 0x4D, 0x4A, 0x47, 0x46, 0x2F, 0x68, 0x64, 0x2F, 0x61, 0x54, 0x61, 0x2F, 0x35, 0x35, 0x4A, 0x57, 0x70, 0x7A, 0x6D, 0x4D, 0x2B, 0x59, 0x6B, ++ 0x0A, 0x6C, 0x76, 0x63, 0x2F, 0x75, 0x6C, 0x73, 0x72, 0x48, 0x48, 0x6F, 0x31, 0x77, 0x74, 0x5A, 0x6E, 0x2F, 0x71, 0x74, 0x6D, 0x55, 0x49, 0x74, 0x74, 0x4B, 0x47, 0x41, 0x72, 0x37, 0x39, 0x64, 0x67, 0x77, 0x38, 0x65, 0x54, 0x76, 0x49, 0x30, ++ 0x32, 0x6B, 0x66, 0x4E, 0x2F, 0x2B, 0x4E, 0x73, 0x52, 0x45, 0x38, 0x53, 0x63, 0x64, 0x33, 0x62, 0x42, 0x72, 0x72, 0x63, 0x43, 0x61, 0x6F, 0x46, 0x36, 0x71, 0x55, 0x57, 0x44, 0x34, 0x67, 0x58, 0x6D, 0x75, 0x56, 0x62, 0x42, 0x0A, 0x6C, 0x44, ++ 0x65, 0x50, 0x53, 0x48, 0x46, 0x6A, 0x49, 0x75, 0x77, 0x58, 0x5A, 0x51, 0x65, 0x56, 0x69, 0x6B, 0x76, 0x66, 0x6A, 0x38, 0x5A, 0x61, 0x43, 0x75, 0x57, 0x77, 0x34, 0x31, 0x39, 0x65, 0x61, 0x78, 0x47, 0x72, 0x44, 0x50, 0x6D, 0x46, 0x36, 0x30, ++ 0x54, 0x70, 0x2B, 0x41, 0x52, 0x7A, 0x38, 0x75, 0x6E, 0x2B, 0x58, 0x4A, 0x69, 0x4D, 0x39, 0x58, 0x4F, 0x76, 0x61, 0x37, 0x52, 0x2B, 0x7A, 0x64, 0x52, 0x63, 0x41, 0x69, 0x74, 0x4D, 0x4F, 0x65, 0x47, 0x79, 0x0A, 0x6C, 0x5A, 0x55, 0x74, 0x51, ++ 0x6F, 0x66, 0x58, 0x31, 0x62, 0x4F, 0x51, 0x51, 0x37, 0x64, 0x73, 0x45, 0x2F, 0x48, 0x65, 0x33, 0x66, 0x62, 0x45, 0x2B, 0x49, 0x6B, 0x2F, 0x30, 0x58, 0x58, 0x31, 0x6B, 0x73, 0x4F, 0x52, 0x31, 0x59, 0x71, 0x49, 0x30, 0x4A, 0x44, 0x73, 0x33, ++ 0x47, 0x33, 0x65, 0x69, 0x63, 0x4A, 0x6C, 0x63, 0x5A, 0x61, 0x4C, 0x44, 0x51, 0x50, 0x39, 0x6E, 0x4C, 0x39, 0x62, 0x46, 0x71, 0x79, 0x53, 0x32, 0x2B, 0x72, 0x2B, 0x65, 0x58, 0x79, 0x74, 0x0A, 0x36, 0x36, 0x2F, 0x33, 0x46, 0x73, 0x76, 0x62, ++ 0x7A, 0x53, 0x55, 0x72, 0x35, 0x52, 0x2F, 0x37, 0x6D, 0x70, 0x2F, 0x69, 0x55, 0x63, 0x77, 0x36, 0x55, 0x77, 0x78, 0x49, 0x35, 0x67, 0x36, 0x39, 0x79, 0x62, 0x52, 0x32, 0x42, 0x6C, 0x4C, 0x6D, 0x45, 0x52, 0x4F, 0x46, 0x63, 0x6D, 0x4D, 0x44, ++ 0x42, 0x4F, 0x41, 0x45, 0x4E, 0x69, 0x73, 0x67, 0x47, 0x51, 0x4C, 0x6F, 0x64, 0x4B, 0x63, 0x66, 0x74, 0x73, 0x6C, 0x57, 0x5A, 0x76, 0x42, 0x31, 0x4A, 0x64, 0x78, 0x6E, 0x0A, 0x77, 0x51, 0x35, 0x68, 0x59, 0x49, 0x69, 0x7A, 0x50, 0x74, 0x47, ++ 0x6F, 0x2F, 0x4B, 0x50, 0x61, 0x48, 0x62, 0x44, 0x52, 0x73, 0x53, 0x4E, 0x55, 0x33, 0x30, 0x52, 0x32, 0x62, 0x65, 0x31, 0x42, 0x32, 0x4D, 0x47, 0x79, 0x49, 0x72, 0x5A, 0x54, 0x48, 0x4E, 0x38, 0x31, 0x48, 0x64, 0x79, 0x68, 0x64, 0x79, 0x6F, ++ 0x78, 0x35, 0x43, 0x33, 0x31, 0x35, 0x65, 0x58, 0x62, 0x79, 0x4F, 0x44, 0x2F, 0x35, 0x59, 0x44, 0x58, 0x43, 0x32, 0x4F, 0x67, 0x2F, 0x7A, 0x4F, 0x68, 0x0A, 0x44, 0x37, 0x6F, 0x73, 0x46, 0x52, 0x58, 0x71, 0x6C, 0x37, 0x50, 0x53, 0x6F, 0x72, ++ 0x57, 0x2B, 0x38, 0x6F, 0x79, 0x57, 0x48, 0x68, 0x71, 0x50, 0x48, 0x57, 0x79, 0x6B, 0x59, 0x54, 0x65, 0x35, 0x68, 0x6E, 0x4D, 0x7A, 0x31, 0x35, 0x65, 0x57, 0x6E, 0x69, 0x4E, 0x39, 0x67, 0x71, 0x52, 0x4D, 0x67, 0x65, 0x4B, 0x68, 0x30, 0x62, ++ 0x70, 0x6E, 0x58, 0x35, 0x55, 0x48, 0x6F, 0x79, 0x63, 0x52, 0x37, 0x68, 0x59, 0x51, 0x65, 0x37, 0x78, 0x46, 0x53, 0x6B, 0x79, 0x79, 0x0A, 0x42, 0x4E, 0x4B, 0x72, 0x37, 0x39, 0x58, 0x39, 0x44, 0x46, 0x48, 0x4F, 0x55, 0x47, 0x6F, 0x49, 0x4D, ++ 0x66, 0x6D, 0x52, 0x32, 0x67, 0x79, 0x50, 0x5A, 0x46, 0x77, 0x44, 0x77, 0x7A, 0x71, 0x4C, 0x49, 0x44, 0x39, 0x75, 0x6A, 0x57, 0x63, 0x39, 0x4F, 0x74, 0x62, 0x2B, 0x66, 0x56, 0x75, 0x49, 0x79, 0x56, 0x37, 0x37, 0x7A, 0x47, 0x48, 0x63, 0x69, ++ 0x7A, 0x4E, 0x33, 0x30, 0x30, 0x51, 0x79, 0x4E, 0x51, 0x6C, 0x69, 0x42, 0x4A, 0x49, 0x57, 0x45, 0x4E, 0x69, 0x65, 0x0A, 0x4A, 0x30, 0x66, 0x37, 0x4F, 0x79, 0x48, 0x6A, 0x2B, 0x4F, 0x73, 0x64, 0x57, 0x77, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, ++ 0x6F, 0x34, 0x47, 0x77, 0x4D, 0x49, 0x47, 0x74, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x43, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, ++ 0x42, 0x41, 0x51, 0x44, 0x41, 0x67, 0x45, 0x47, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x0A, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x51, 0x61, 0x68, 0x47, 0x4B, 0x38, 0x53, 0x45, 0x77, 0x7A, 0x4A, 0x51, 0x54, 0x55, 0x37, 0x74, 0x44, ++ 0x32, 0x41, 0x38, 0x51, 0x5A, 0x52, 0x74, 0x47, 0x55, 0x61, 0x7A, 0x42, 0x75, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x53, 0x4D, 0x45, 0x5A, 0x7A, 0x42, 0x6C, 0x67, 0x42, 0x51, 0x61, 0x68, 0x47, 0x4B, 0x38, 0x53, 0x45, 0x77, 0x7A, 0x4A, 0x51, 0x54, ++ 0x55, 0x37, 0x74, 0x44, 0x32, 0x41, 0x38, 0x51, 0x5A, 0x52, 0x74, 0x47, 0x55, 0x0A, 0x61, 0x36, 0x46, 0x4A, 0x70, 0x45, 0x63, 0x77, 0x52, 0x54, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x51, 0x6B, ++ 0x30, 0x78, 0x47, 0x54, 0x41, 0x58, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x45, 0x46, 0x46, 0x31, 0x62, 0x31, 0x5A, 0x68, 0x5A, 0x47, 0x6C, 0x7A, 0x49, 0x45, 0x78, 0x70, 0x62, 0x57, 0x6C, 0x30, 0x5A, 0x57, 0x51, 0x78, 0x47, 0x7A, ++ 0x41, 0x5A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x0A, 0x45, 0x6C, 0x46, 0x31, 0x62, 0x31, 0x5A, 0x68, 0x5A, 0x47, 0x6C, 0x7A, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x67, 0x4D, 0x6F, 0x49, 0x43, 0x42, ++ 0x51, 0x6B, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x46, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x42, 0x41, 0x44, 0x34, 0x4B, 0x46, 0x6B, 0x32, 0x66, 0x42, 0x6C, 0x75, 0x6F, 0x72, ++ 0x6E, 0x46, 0x64, 0x4C, 0x77, 0x55, 0x76, 0x0A, 0x5A, 0x2B, 0x59, 0x54, 0x52, 0x59, 0x50, 0x45, 0x4E, 0x76, 0x62, 0x7A, 0x77, 0x43, 0x59, 0x4D, 0x44, 0x62, 0x56, 0x48, 0x5A, 0x46, 0x33, 0x34, 0x74, 0x48, 0x4C, 0x4A, 0x52, 0x71, 0x55, 0x44, ++ 0x47, 0x43, 0x64, 0x56, 0x69, 0x58, 0x68, 0x39, 0x64, 0x75, 0x71, 0x57, 0x4E, 0x49, 0x41, 0x58, 0x49, 0x4E, 0x7A, 0x6E, 0x67, 0x2F, 0x69, 0x4E, 0x2F, 0x41, 0x65, 0x34, 0x32, 0x6C, 0x39, 0x4E, 0x4C, 0x6D, 0x65, 0x79, 0x68, 0x50, 0x33, 0x5A, ++ 0x52, 0x50, 0x78, 0x33, 0x0A, 0x55, 0x49, 0x48, 0x6D, 0x66, 0x4C, 0x54, 0x4A, 0x44, 0x51, 0x74, 0x79, 0x55, 0x2F, 0x68, 0x32, 0x42, 0x77, 0x64, 0x42, 0x52, 0x35, 0x59, 0x4D, 0x2B, 0x2B, 0x43, 0x43, 0x4A, 0x70, 0x4E, 0x56, 0x6A, 0x50, 0x34, ++ 0x69, 0x48, 0x32, 0x42, 0x6C, 0x66, 0x46, 0x2F, 0x6E, 0x4A, 0x72, 0x50, 0x33, 0x4D, 0x70, 0x43, 0x59, 0x55, 0x4E, 0x51, 0x33, 0x63, 0x56, 0x58, 0x32, 0x6B, 0x69, 0x46, 0x34, 0x39, 0x35, 0x56, 0x35, 0x2B, 0x76, 0x67, 0x74, 0x4A, 0x6F, 0x64, ++ 0x6D, 0x0A, 0x56, 0x6A, 0x42, 0x33, 0x70, 0x6A, 0x64, 0x34, 0x4D, 0x31, 0x49, 0x51, 0x57, 0x4B, 0x34, 0x2F, 0x59, 0x59, 0x37, 0x79, 0x61, 0x72, 0x48, 0x76, 0x47, 0x48, 0x35, 0x4B, 0x57, 0x57, 0x50, 0x4B, 0x6A, 0x61, 0x4A, 0x57, 0x31, 0x61, ++ 0x63, 0x76, 0x76, 0x46, 0x59, 0x66, 0x7A, 0x7A, 0x6E, 0x42, 0x34, 0x76, 0x73, 0x4B, 0x71, 0x42, 0x55, 0x73, 0x66, 0x55, 0x31, 0x36, 0x59, 0x38, 0x5A, 0x73, 0x6C, 0x30, 0x51, 0x38, 0x30, 0x6D, 0x2F, 0x44, 0x53, 0x68, 0x63, 0x4B, 0x0A, 0x2B, ++ 0x4A, 0x44, 0x53, 0x56, 0x36, 0x49, 0x5A, 0x55, 0x61, 0x55, 0x74, 0x6C, 0x30, 0x48, 0x61, 0x42, 0x30, 0x2B, 0x70, 0x55, 0x4E, 0x71, 0x51, 0x6A, 0x5A, 0x52, 0x47, 0x34, 0x54, 0x37, 0x77, 0x6C, 0x50, 0x30, 0x51, 0x41, 0x44, 0x6A, 0x31, 0x4F, ++ 0x2B, 0x68, 0x41, 0x34, 0x62, 0x52, 0x75, 0x56, 0x68, 0x6F, 0x67, 0x7A, 0x47, 0x39, 0x59, 0x6A, 0x65, 0x30, 0x75, 0x52, 0x59, 0x2F, 0x57, 0x36, 0x5A, 0x4D, 0x2F, 0x35, 0x37, 0x45, 0x73, 0x33, 0x7A, 0x72, 0x57, 0x0A, 0x49, 0x6F, 0x7A, 0x63, ++ 0x68, 0x4C, 0x73, 0x69, 0x62, 0x39, 0x44, 0x34, 0x35, 0x4D, 0x59, 0x35, 0x36, 0x51, 0x53, 0x49, 0x50, 0x4D, 0x4F, 0x36, 0x36, 0x31, 0x56, 0x36, 0x62, 0x59, 0x43, 0x5A, 0x4A, 0x50, 0x56, 0x73, 0x41, 0x66, 0x76, 0x34, 0x6C, 0x37, 0x43, 0x55, ++ 0x57, 0x2B, 0x76, 0x39, 0x30, 0x6D, 0x2F, 0x78, 0x64, 0x32, 0x67, 0x4E, 0x4E, 0x57, 0x51, 0x6A, 0x72, 0x4C, 0x68, 0x56, 0x6F, 0x51, 0x50, 0x52, 0x54, 0x55, 0x49, 0x5A, 0x33, 0x50, 0x68, 0x31, 0x0A, 0x57, 0x56, 0x61, 0x6A, 0x2B, 0x61, 0x68, ++ 0x4A, 0x65, 0x66, 0x69, 0x76, 0x44, 0x72, 0x6B, 0x52, 0x6F, 0x48, 0x79, 0x33, 0x61, 0x75, 0x30, 0x30, 0x30, 0x4C, 0x59, 0x6D, 0x59, 0x6A, 0x67, 0x61, 0x68, 0x77, 0x7A, 0x34, 0x36, 0x50, 0x30, 0x75, 0x30, 0x35, 0x42, 0x2F, 0x42, 0x35, 0x45, ++ 0x71, 0x48, 0x64, 0x5A, 0x2B, 0x58, 0x49, 0x57, 0x44, 0x6D, 0x62, 0x41, 0x34, 0x43, 0x44, 0x2F, 0x70, 0x58, 0x76, 0x6B, 0x31, 0x42, 0x2B, 0x54, 0x4A, 0x59, 0x6D, 0x35, 0x58, 0x0A, 0x66, 0x36, 0x64, 0x51, 0x6C, 0x66, 0x65, 0x36, 0x79, 0x4A, ++ 0x76, 0x6D, 0x6A, 0x71, 0x49, 0x42, 0x78, 0x64, 0x5A, 0x6D, 0x76, 0x33, 0x6C, 0x68, 0x38, 0x7A, 0x77, 0x63, 0x34, 0x62, 0x6D, 0x43, 0x58, 0x46, 0x32, 0x67, 0x77, 0x2B, 0x6E, 0x59, 0x53, 0x4C, 0x30, 0x5A, 0x6F, 0x68, 0x45, 0x55, 0x47, 0x57, ++ 0x36, 0x79, 0x68, 0x68, 0x74, 0x6F, 0x50, 0x6B, 0x67, 0x33, 0x47, 0x6F, 0x69, 0x33, 0x58, 0x5A, 0x5A, 0x65, 0x6E, 0x4D, 0x66, 0x76, 0x4A, 0x32, 0x49, 0x49, 0x0A, 0x34, 0x70, 0x45, 0x5A, 0x58, 0x4E, 0x4C, 0x78, 0x49, 0x64, 0x32, 0x36, 0x46, ++ 0x30, 0x4B, 0x43, 0x6C, 0x33, 0x47, 0x42, 0x55, 0x7A, 0x47, 0x70, 0x6E, 0x2F, 0x5A, 0x39, 0x59, 0x72, 0x39, 0x79, 0x34, 0x61, 0x4F, 0x54, 0x48, 0x63, 0x79, 0x4B, 0x4A, 0x6C, 0x6F, 0x4A, 0x4F, 0x4E, 0x44, 0x4F, 0x31, 0x77, 0x32, 0x41, 0x46, ++ 0x72, 0x52, 0x34, 0x70, 0x54, 0x71, 0x48, 0x54, 0x49, 0x32, 0x4B, 0x70, 0x64, 0x56, 0x47, 0x6C, 0x2F, 0x49, 0x73, 0x45, 0x4C, 0x6D, 0x38, 0x0A, 0x56, 0x43, 0x4C, 0x41, 0x41, 0x56, 0x42, 0x70, 0x51, 0x35, 0x37, 0x30, 0x73, 0x75, 0x39, 0x74, ++ 0x2B, 0x4F, 0x7A, 0x61, 0x38, 0x65, 0x4F, 0x78, 0x37, 0x39, 0x2B, 0x52, 0x6A, 0x31, 0x51, 0x71, 0x43, 0x79, 0x58, 0x42, 0x4A, 0x68, 0x6E, 0x45, 0x55, 0x68, 0x41, 0x46, 0x5A, 0x64, 0x57, 0x43, 0x45, 0x4F, 0x72, 0x43, 0x4D, 0x63, 0x30, 0x75, ++ 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x52, 0x6F, 0x6F, ++ 0x74, 0x20, 0x43, 0x41, 0x20, 0x33, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, ++ 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x47, 0x6E, 0x54, 0x43, 0x43, 0x42, 0x49, 0x57, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x43, 0x42, 0x63, 0x59, 0x77, 0x44, 0x51, ++ 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x46, 0x42, 0x51, 0x41, 0x77, 0x52, 0x54, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x51, 0x6B, 0x30, 0x78, 0x47, 0x54, ++ 0x41, 0x58, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x0A, 0x45, 0x46, 0x46, 0x31, 0x62, 0x31, 0x5A, 0x68, 0x5A, 0x47, 0x6C, 0x7A, 0x49, 0x45, 0x78, 0x70, 0x62, 0x57, 0x6C, 0x30, 0x5A, 0x57, 0x51, 0x78, 0x47, 0x7A, 0x41, 0x5A, 0x42, ++ 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x45, 0x6C, 0x46, 0x31, 0x62, 0x31, 0x5A, 0x68, 0x5A, 0x47, 0x6C, 0x7A, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x67, 0x4D, 0x7A, 0x41, 0x65, 0x46, 0x77, 0x30, 0x77, 0x4E, ++ 0x6A, 0x45, 0x78, 0x4D, 0x6A, 0x51, 0x78, 0x0A, 0x4F, 0x54, 0x45, 0x78, 0x4D, 0x6A, 0x4E, 0x61, 0x46, 0x77, 0x30, 0x7A, 0x4D, 0x54, 0x45, 0x78, 0x4D, 0x6A, 0x51, 0x78, 0x4F, 0x54, 0x41, 0x32, 0x4E, 0x44, 0x52, 0x61, 0x4D, 0x45, 0x55, 0x78, ++ 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6B, 0x4A, 0x4E, 0x4D, 0x52, 0x6B, 0x77, 0x46, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x45, 0x78, 0x42, 0x52, 0x64, 0x57, 0x39, 0x57, 0x59, 0x57, 0x52, 0x70, ++ 0x63, 0x79, 0x42, 0x4D, 0x0A, 0x61, 0x57, 0x31, 0x70, 0x64, 0x47, 0x56, 0x6B, 0x4D, 0x52, 0x73, 0x77, 0x47, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x4A, 0x52, 0x64, 0x57, 0x39, 0x57, 0x59, 0x57, 0x52, 0x70, 0x63, 0x79, 0x42, ++ 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x42, 0x49, 0x44, 0x4D, 0x77, 0x67, 0x67, 0x49, 0x69, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, ++ 0x43, 0x0A, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x49, 0x4B, 0x41, 0x6F, 0x49, 0x43, 0x41, 0x51, 0x44, 0x4D, 0x56, 0x30, 0x49, 0x57, 0x56, 0x4A, 0x7A, 0x6D, 0x6D, 0x4E, 0x50, 0x54, 0x54, 0x65, 0x37, 0x2B, 0x37, 0x63, 0x65, 0x66, 0x51, 0x7A, ++ 0x6C, 0x4B, 0x5A, 0x62, 0x50, 0x6F, 0x46, 0x6F, 0x67, 0x30, 0x32, 0x77, 0x31, 0x5A, 0x6B, 0x58, 0x54, 0x50, 0x6B, 0x72, 0x67, 0x45, 0x51, 0x4B, 0x30, 0x43, 0x53, 0x7A, 0x47, 0x72, 0x76, 0x49, 0x32, 0x52, 0x61, 0x4E, 0x67, 0x67, 0x0A, 0x44, ++ 0x68, 0x6F, 0x42, 0x34, 0x68, 0x70, 0x37, 0x54, 0x68, 0x64, 0x64, 0x34, 0x6F, 0x71, 0x33, 0x50, 0x35, 0x6B, 0x61, 0x7A, 0x65, 0x74, 0x68, 0x71, 0x38, 0x4A, 0x6C, 0x70, 0x68, 0x2B, 0x33, 0x74, 0x37, 0x32, 0x33, 0x6A, 0x2F, 0x7A, 0x39, 0x63, ++ 0x49, 0x38, 0x4C, 0x6F, 0x47, 0x65, 0x2B, 0x41, 0x61, 0x4A, 0x5A, 0x7A, 0x33, 0x48, 0x6D, 0x44, 0x79, 0x6C, 0x32, 0x2F, 0x37, 0x46, 0x57, 0x65, 0x55, 0x55, 0x72, 0x48, 0x35, 0x35, 0x36, 0x56, 0x4F, 0x69, 0x6A, 0x0A, 0x4B, 0x54, 0x56, 0x6F, ++ 0x70, 0x41, 0x46, 0x50, 0x44, 0x36, 0x51, 0x75, 0x4E, 0x2B, 0x38, 0x62, 0x76, 0x2B, 0x4F, 0x50, 0x45, 0x4B, 0x68, 0x79, 0x71, 0x31, 0x68, 0x58, 0x35, 0x31, 0x53, 0x47, 0x79, 0x4D, 0x6E, 0x7A, 0x57, 0x39, 0x6F, 0x73, 0x32, 0x6C, 0x32, 0x4F, ++ 0x62, 0x6A, 0x79, 0x6A, 0x50, 0x74, 0x72, 0x37, 0x67, 0x75, 0x58, 0x64, 0x38, 0x6C, 0x79, 0x79, 0x42, 0x54, 0x4E, 0x76, 0x69, 0x6A, 0x62, 0x4F, 0x30, 0x42, 0x4E, 0x4F, 0x2F, 0x37, 0x39, 0x4B, 0x0A, 0x44, 0x44, 0x52, 0x4D, 0x70, 0x73, 0x4D, ++ 0x68, 0x76, 0x56, 0x41, 0x45, 0x56, 0x65, 0x75, 0x78, 0x75, 0x35, 0x33, 0x37, 0x52, 0x52, 0x35, 0x6B, 0x46, 0x64, 0x35, 0x56, 0x41, 0x59, 0x77, 0x43, 0x64, 0x72, 0x58, 0x4C, 0x6F, 0x54, 0x39, 0x43, 0x61, 0x62, 0x77, 0x76, 0x76, 0x57, 0x68, ++ 0x44, 0x46, 0x6C, 0x61, 0x4A, 0x4B, 0x6A, 0x64, 0x68, 0x6B, 0x66, 0x32, 0x6D, 0x72, 0x6B, 0x37, 0x41, 0x79, 0x78, 0x52, 0x6C, 0x6C, 0x44, 0x64, 0x4C, 0x6B, 0x67, 0x62, 0x76, 0x0A, 0x42, 0x4E, 0x44, 0x49, 0x6E, 0x49, 0x6A, 0x62, 0x43, 0x33, ++ 0x75, 0x42, 0x72, 0x37, 0x45, 0x39, 0x4B, 0x73, 0x52, 0x6C, 0x4F, 0x6E, 0x69, 0x32, 0x37, 0x74, 0x79, 0x41, 0x73, 0x64, 0x4C, 0x54, 0x6D, 0x5A, 0x77, 0x36, 0x37, 0x6D, 0x74, 0x61, 0x61, 0x37, 0x4F, 0x4E, 0x74, 0x39, 0x58, 0x4F, 0x6E, 0x4D, ++ 0x4B, 0x2B, 0x70, 0x55, 0x73, 0x76, 0x46, 0x72, 0x47, 0x65, 0x61, 0x44, 0x73, 0x47, 0x62, 0x36, 0x35, 0x39, 0x6E, 0x2F, 0x6A, 0x65, 0x37, 0x4D, 0x77, 0x70, 0x0A, 0x70, 0x35, 0x69, 0x6A, 0x4A, 0x55, 0x4D, 0x76, 0x37, 0x2F, 0x46, 0x66, 0x4A, ++ 0x75, 0x47, 0x49, 0x54, 0x66, 0x68, 0x65, 0x62, 0x74, 0x66, 0x5A, 0x46, 0x47, 0x34, 0x5A, 0x4D, 0x32, 0x6D, 0x6E, 0x4F, 0x34, 0x53, 0x4A, 0x6B, 0x38, 0x52, 0x54, 0x56, 0x52, 0x4F, 0x68, 0x55, 0x58, 0x68, 0x41, 0x2B, 0x4C, 0x6A, 0x4A, 0x6F, ++ 0x75, 0x35, 0x37, 0x75, 0x6C, 0x4A, 0x43, 0x67, 0x35, 0x34, 0x55, 0x37, 0x51, 0x56, 0x53, 0x57, 0x6C, 0x6C, 0x57, 0x70, 0x35, 0x66, 0x38, 0x0A, 0x6E, 0x54, 0x38, 0x4B, 0x4B, 0x64, 0x6A, 0x63, 0x54, 0x35, 0x45, 0x4F, 0x45, 0x37, 0x7A, 0x65, ++ 0x6C, 0x61, 0x54, 0x66, 0x69, 0x35, 0x6D, 0x2B, 0x72, 0x4A, 0x73, 0x7A, 0x69, 0x4F, 0x2B, 0x31, 0x67, 0x61, 0x38, 0x62, 0x78, 0x69, 0x4A, 0x54, 0x79, 0x50, 0x62, 0x48, 0x37, 0x70, 0x63, 0x55, 0x73, 0x4D, 0x56, 0x38, 0x65, 0x46, 0x4C, 0x49, ++ 0x38, 0x4D, 0x35, 0x75, 0x64, 0x32, 0x43, 0x45, 0x70, 0x75, 0x6B, 0x71, 0x64, 0x69, 0x44, 0x74, 0x57, 0x41, 0x45, 0x58, 0x0A, 0x4D, 0x4A, 0x50, 0x70, 0x47, 0x6F, 0x76, 0x67, 0x63, 0x32, 0x50, 0x5A, 0x61, 0x70, 0x4B, 0x55, 0x53, 0x55, 0x36, ++ 0x30, 0x72, 0x55, 0x71, 0x46, 0x78, 0x4B, 0x4D, 0x69, 0x4D, 0x50, 0x77, 0x4A, 0x37, 0x57, 0x67, 0x69, 0x63, 0x36, 0x61, 0x49, 0x44, 0x46, 0x55, 0x68, 0x57, 0x4D, 0x58, 0x68, 0x4F, 0x70, 0x38, 0x71, 0x33, 0x63, 0x72, 0x68, 0x6B, 0x4F, 0x44, ++ 0x5A, 0x63, 0x36, 0x74, 0x73, 0x67, 0x4C, 0x6A, 0x6F, 0x43, 0x32, 0x53, 0x54, 0x6F, 0x4A, 0x79, 0x4D, 0x0A, 0x47, 0x66, 0x2B, 0x7A, 0x30, 0x67, 0x7A, 0x73, 0x6B, 0x53, 0x61, 0x48, 0x69, 0x72, 0x4F, 0x69, 0x34, 0x58, 0x43, 0x50, 0x4C, 0x41, ++ 0x72, 0x6C, 0x7A, 0x57, 0x31, 0x6F, 0x55, 0x65, 0x76, 0x61, 0x50, 0x77, 0x56, 0x2F, 0x69, 0x7A, 0x4C, 0x6D, 0x45, 0x31, 0x78, 0x72, 0x2F, 0x6C, 0x39, 0x41, 0x34, 0x69, 0x4C, 0x49, 0x74, 0x4C, 0x52, 0x6B, 0x54, 0x39, 0x61, 0x36, 0x66, 0x55, ++ 0x67, 0x2B, 0x71, 0x47, 0x6B, 0x4D, 0x31, 0x37, 0x75, 0x47, 0x63, 0x63, 0x6C, 0x7A, 0x0A, 0x75, 0x44, 0x38, 0x37, 0x6E, 0x53, 0x56, 0x4C, 0x32, 0x76, 0x39, 0x41, 0x36, 0x77, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x6F, 0x34, 0x49, 0x42, 0x6C, ++ 0x54, 0x43, 0x43, 0x41, 0x5A, 0x45, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x43, 0x42, 0x34, 0x51, 0x59, 0x44, 0x56, 0x52, 0x30, 0x67, 0x42, ++ 0x49, 0x48, 0x5A, 0x4D, 0x49, 0x48, 0x57, 0x4D, 0x49, 0x48, 0x54, 0x0A, 0x42, 0x67, 0x6B, 0x72, 0x42, 0x67, 0x45, 0x45, 0x41, 0x62, 0x35, 0x59, 0x41, 0x41, 0x4D, 0x77, 0x67, 0x63, 0x55, 0x77, 0x67, 0x5A, 0x4D, 0x47, 0x43, 0x43, 0x73, 0x47, ++ 0x41, 0x51, 0x55, 0x46, 0x42, 0x77, 0x49, 0x43, 0x4D, 0x49, 0x47, 0x47, 0x47, 0x6F, 0x47, 0x44, 0x51, 0x57, 0x35, 0x35, 0x49, 0x48, 0x56, 0x7A, 0x5A, 0x53, 0x42, 0x76, 0x5A, 0x69, 0x42, 0x30, 0x61, 0x47, 0x6C, 0x7A, 0x49, 0x45, 0x4E, 0x6C, ++ 0x63, 0x6E, 0x52, 0x70, 0x5A, 0x6D, 0x6C, 0x6A, 0x0A, 0x59, 0x58, 0x52, 0x6C, 0x49, 0x47, 0x4E, 0x76, 0x62, 0x6E, 0x4E, 0x30, 0x61, 0x58, 0x52, 0x31, 0x64, 0x47, 0x56, 0x7A, 0x49, 0x47, 0x46, 0x6A, 0x59, 0x32, 0x56, 0x77, 0x64, 0x47, 0x46, ++ 0x75, 0x59, 0x32, 0x55, 0x67, 0x62, 0x32, 0x59, 0x67, 0x64, 0x47, 0x68, 0x6C, 0x49, 0x46, 0x46, 0x31, 0x62, 0x31, 0x5A, 0x68, 0x5A, 0x47, 0x6C, 0x7A, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x67, 0x4D, 0x79, 0x42, ++ 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x0A, 0x61, 0x57, 0x5A, 0x70, 0x59, 0x32, 0x46, 0x30, 0x5A, 0x53, 0x42, 0x51, 0x62, 0x32, 0x78, 0x70, 0x59, 0x33, 0x6B, 0x67, 0x4C, 0x79, 0x42, 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x61, 0x57, 0x5A, 0x70, 0x59, 0x32, ++ 0x46, 0x30, 0x61, 0x57, 0x39, 0x75, 0x49, 0x46, 0x42, 0x79, 0x59, 0x57, 0x4E, 0x30, 0x61, 0x57, 0x4E, 0x6C, 0x49, 0x46, 0x4E, 0x30, 0x59, 0x58, 0x52, 0x6C, 0x62, 0x57, 0x56, 0x75, 0x64, 0x43, 0x34, 0x77, 0x4C, 0x51, 0x59, 0x49, 0x4B, 0x77, ++ 0x59, 0x42, 0x0A, 0x42, 0x51, 0x55, 0x48, 0x41, 0x67, 0x45, 0x57, 0x49, 0x57, 0x68, 0x30, 0x64, 0x48, 0x41, 0x36, 0x4C, 0x79, 0x39, 0x33, 0x64, 0x33, 0x63, 0x75, 0x63, 0x58, 0x56, 0x76, 0x64, 0x6D, 0x46, 0x6B, 0x61, 0x58, 0x4E, 0x6E, 0x62, ++ 0x47, 0x39, 0x69, 0x59, 0x57, 0x77, 0x75, 0x59, 0x32, 0x39, 0x74, 0x4C, 0x32, 0x4E, 0x77, 0x63, 0x7A, 0x41, 0x4C, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x45, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x51, 0x59, 0x77, 0x48, 0x51, 0x59, 0x44, 0x0A, ++ 0x56, 0x52, 0x30, 0x4F, 0x42, 0x42, 0x59, 0x45, 0x46, 0x50, 0x4C, 0x41, 0x45, 0x2B, 0x43, 0x43, 0x51, 0x7A, 0x37, 0x37, 0x37, 0x69, 0x39, 0x6E, 0x4D, 0x70, 0x59, 0x31, 0x58, 0x4E, 0x75, 0x34, 0x79, 0x77, 0x4C, 0x51, 0x4D, 0x47, 0x34, 0x47, ++ 0x41, 0x31, 0x55, 0x64, 0x49, 0x77, 0x52, 0x6E, 0x4D, 0x47, 0x57, 0x41, 0x46, 0x50, 0x4C, 0x41, 0x45, 0x2B, 0x43, 0x43, 0x51, 0x7A, 0x37, 0x37, 0x37, 0x69, 0x39, 0x6E, 0x4D, 0x70, 0x59, 0x31, 0x58, 0x4E, 0x75, 0x34, 0x0A, 0x79, 0x77, 0x4C, ++ 0x51, 0x6F, 0x55, 0x6D, 0x6B, 0x52, 0x7A, 0x42, 0x46, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x43, 0x54, 0x54, 0x45, 0x5A, 0x4D, 0x42, 0x63, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, ++ 0x51, 0x55, 0x58, 0x56, 0x76, 0x56, 0x6D, 0x46, 0x6B, 0x61, 0x58, 0x4D, 0x67, 0x54, 0x47, 0x6C, 0x74, 0x61, 0x58, 0x52, 0x6C, 0x5A, 0x44, 0x45, 0x62, 0x4D, 0x42, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x0A, 0x41, 0x78, 0x4D, 0x53, 0x55, 0x58, ++ 0x56, 0x76, 0x56, 0x6D, 0x46, 0x6B, 0x61, 0x58, 0x4D, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x51, 0x53, 0x41, 0x7A, 0x67, 0x67, 0x49, 0x46, 0x78, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, ++ 0x30, 0x42, 0x41, 0x51, 0x55, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x67, 0x45, 0x41, 0x54, 0x36, 0x32, 0x67, 0x4C, 0x45, 0x7A, 0x36, 0x77, 0x50, 0x4A, 0x76, 0x39, 0x32, 0x5A, 0x56, 0x0A, 0x71, 0x79, 0x4D, 0x30, 0x37, 0x75, 0x63, 0x70, 0x32, ++ 0x73, 0x4E, 0x62, 0x74, 0x72, 0x43, 0x44, 0x32, 0x64, 0x44, 0x51, 0x34, 0x69, 0x48, 0x37, 0x38, 0x32, 0x43, 0x6E, 0x4F, 0x31, 0x31, 0x67, 0x55, 0x79, 0x65, 0x69, 0x6D, 0x2F, 0x59, 0x49, 0x49, 0x69, 0x72, 0x6E, 0x76, 0x36, 0x42, 0x79, 0x35, ++ 0x5A, 0x77, 0x6B, 0x61, 0x6A, 0x47, 0x78, 0x6B, 0x48, 0x6F, 0x6E, 0x32, 0x34, 0x51, 0x52, 0x69, 0x53, 0x65, 0x6D, 0x64, 0x31, 0x6F, 0x34, 0x31, 0x37, 0x2B, 0x73, 0x0A, 0x68, 0x76, 0x7A, 0x75, 0x58, 0x59, 0x4F, 0x38, 0x42, 0x73, 0x62, 0x52, ++ 0x64, 0x32, 0x73, 0x50, 0x62, 0x53, 0x51, 0x76, 0x53, 0x33, 0x70, 0x73, 0x70, 0x77, 0x65, 0x57, 0x79, 0x75, 0x4F, 0x45, 0x6E, 0x36, 0x32, 0x49, 0x69, 0x78, 0x32, 0x72, 0x46, 0x6F, 0x31, 0x62, 0x5A, 0x68, 0x66, 0x5A, 0x46, 0x76, 0x53, 0x4C, ++ 0x67, 0x4E, 0x4C, 0x64, 0x2B, 0x4C, 0x4A, 0x32, 0x77, 0x2F, 0x77, 0x34, 0x45, 0x36, 0x6F, 0x4D, 0x33, 0x6B, 0x4A, 0x70, 0x4B, 0x32, 0x37, 0x7A, 0x0A, 0x50, 0x4F, 0x75, 0x41, 0x4A, 0x39, 0x76, 0x31, 0x70, 0x6B, 0x51, 0x4E, 0x6E, 0x31, 0x70, ++ 0x56, 0x57, 0x51, 0x76, 0x56, 0x44, 0x56, 0x4A, 0x49, 0x78, 0x61, 0x36, 0x66, 0x38, 0x69, 0x2B, 0x41, 0x78, 0x65, 0x6F, 0x79, 0x55, 0x44, 0x55, 0x53, 0x6C, 0x79, 0x37, 0x42, 0x34, 0x66, 0x2F, 0x78, 0x49, 0x34, 0x68, 0x52, 0x4F, 0x4A, 0x2F, ++ 0x79, 0x5A, 0x6C, 0x5A, 0x32, 0x35, 0x77, 0x39, 0x52, 0x6C, 0x36, 0x56, 0x53, 0x44, 0x45, 0x31, 0x4A, 0x55, 0x5A, 0x55, 0x32, 0x0A, 0x50, 0x62, 0x2B, 0x69, 0x53, 0x77, 0x77, 0x51, 0x48, 0x59, 0x61, 0x5A, 0x54, 0x4B, 0x72, 0x7A, 0x63, 0x68, ++ 0x47, 0x54, 0x35, 0x4F, 0x72, 0x32, 0x6D, 0x39, 0x71, 0x6F, 0x58, 0x61, 0x64, 0x4E, 0x74, 0x35, 0x34, 0x43, 0x72, 0x6E, 0x4D, 0x41, 0x79, 0x4E, 0x6F, 0x6A, 0x41, 0x2B, 0x6A, 0x35, 0x36, 0x68, 0x6C, 0x30, 0x59, 0x67, 0x43, 0x55, 0x79, 0x79, ++ 0x49, 0x67, 0x76, 0x70, 0x53, 0x6E, 0x57, 0x62, 0x57, 0x43, 0x61, 0x72, 0x36, 0x5A, 0x65, 0x58, 0x71, 0x70, 0x0A, 0x38, 0x6B, 0x6F, 0x6B, 0x55, 0x76, 0x64, 0x30, 0x2F, 0x62, 0x70, 0x4F, 0x35, 0x71, 0x67, 0x64, 0x41, 0x6D, 0x36, 0x78, 0x44, ++ 0x59, 0x42, 0x45, 0x77, 0x61, 0x37, 0x54, 0x49, 0x7A, 0x64, 0x66, 0x75, 0x34, 0x56, 0x38, 0x4B, 0x35, 0x49, 0x75, 0x36, 0x48, 0x36, 0x6C, 0x69, 0x39, 0x32, 0x5A, 0x34, 0x62, 0x38, 0x6E, 0x62, 0x79, 0x31, 0x64, 0x71, 0x6E, 0x75, 0x48, 0x2F, ++ 0x67, 0x72, 0x64, 0x53, 0x2F, 0x79, 0x4F, 0x39, 0x53, 0x62, 0x6B, 0x62, 0x6E, 0x42, 0x43, 0x0A, 0x62, 0x6A, 0x50, 0x73, 0x4D, 0x5A, 0x35, 0x37, 0x6B, 0x38, 0x48, 0x6B, 0x79, 0x57, 0x6B, 0x61, 0x50, 0x63, 0x42, 0x72, 0x54, 0x69, 0x4A, 0x74, ++ 0x37, 0x71, 0x74, 0x59, 0x54, 0x63, 0x62, 0x51, 0x51, 0x63, 0x45, 0x72, 0x36, 0x6B, 0x38, 0x53, 0x68, 0x31, 0x37, 0x72, 0x52, 0x64, 0x68, 0x73, 0x39, 0x5A, 0x67, 0x43, 0x30, 0x36, 0x44, 0x59, 0x56, 0x59, 0x6F, 0x47, 0x6D, 0x52, 0x6D, 0x69, ++ 0x6F, 0x48, 0x66, 0x52, 0x4D, 0x4A, 0x36, 0x73, 0x7A, 0x48, 0x58, 0x75, 0x0A, 0x67, 0x2F, 0x57, 0x77, 0x59, 0x6A, 0x6E, 0x50, 0x62, 0x46, 0x66, 0x69, 0x54, 0x4E, 0x4B, 0x52, 0x43, 0x77, 0x35, 0x31, 0x4B, 0x42, 0x75, 0x61, 0x76, 0x2F, 0x30, ++ 0x61, 0x51, 0x2F, 0x48, 0x4B, 0x64, 0x2F, 0x73, 0x37, 0x6A, 0x32, 0x47, 0x34, 0x61, 0x53, 0x67, 0x57, 0x51, 0x67, 0x52, 0x65, 0x63, 0x43, 0x6F, 0x63, 0x49, 0x64, 0x69, 0x50, 0x34, 0x62, 0x30, 0x6A, 0x57, 0x79, 0x31, 0x30, 0x51, 0x4A, 0x4C, ++ 0x5A, 0x59, 0x78, 0x6B, 0x4E, 0x63, 0x39, 0x31, 0x70, 0x0A, 0x76, 0x47, 0x4A, 0x48, 0x76, 0x4F, 0x42, 0x30, 0x4B, 0x37, 0x4C, 0x72, 0x66, 0x62, 0x35, 0x42, 0x47, 0x37, 0x58, 0x41, 0x52, 0x73, 0x57, 0x68, 0x49, 0x73, 0x74, 0x66, 0x54, 0x73, ++ 0x45, 0x6F, 0x6B, 0x74, 0x34, 0x59, 0x75, 0x74, 0x55, 0x71, 0x4B, 0x4C, 0x73, 0x52, 0x69, 0x78, 0x65, 0x54, 0x6D, 0x4A, 0x6C, 0x67, 0x6C, 0x46, 0x77, 0x6A, 0x7A, 0x31, 0x6F, 0x6E, 0x6C, 0x31, 0x34, 0x4C, 0x42, 0x51, 0x61, 0x54, 0x4E, 0x78, ++ 0x34, 0x37, 0x61, 0x54, 0x62, 0x72, 0x0A, 0x71, 0x5A, 0x35, 0x68, 0x48, 0x59, 0x38, 0x79, 0x32, 0x6F, 0x34, 0x4D, 0x31, 0x6E, 0x51, 0x2B, 0x65, 0x77, 0x6B, 0x6B, 0x32, 0x67, 0x46, 0x33, 0x52, 0x38, 0x51, 0x37, 0x7A, 0x54, 0x53, 0x4D, 0x6D, ++ 0x66, 0x58, 0x4B, 0x34, 0x53, 0x56, 0x68, 0x4D, 0x37, 0x4A, 0x5A, 0x47, 0x2B, 0x4A, 0x75, 0x31, 0x7A, 0x64, 0x58, 0x74, 0x67, 0x32, 0x70, 0x45, 0x74, 0x6F, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, ++ 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, ++ 0x43, 0x41, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, ++ 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x44, 0x74, 0x7A, 0x43, 0x43, 0x41, 0x70, 0x2B, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x44, ++ 0x4F, 0x66, 0x67, 0x35, 0x52, 0x66, 0x59, 0x52, 0x76, 0x36, 0x50, 0x35, 0x57, 0x44, 0x38, 0x47, 0x2F, 0x41, 0x77, 0x4F, 0x54, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x55, 0x46, 0x41, ++ 0x44, 0x42, 0x6C, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x0A, 0x45, 0x77, 0x4A, 0x56, 0x55, 0x7A, 0x45, 0x56, 0x4D, 0x42, 0x4D, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x4D, 0x52, 0x47, 0x6C, 0x6E, ++ 0x61, 0x55, 0x4E, 0x6C, 0x63, 0x6E, 0x51, 0x67, 0x53, 0x57, 0x35, 0x6A, 0x4D, 0x52, 0x6B, 0x77, 0x46, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4C, 0x45, 0x78, 0x42, 0x33, 0x64, 0x33, 0x63, 0x75, 0x5A, 0x47, 0x6C, 0x6E, 0x61, 0x57, 0x4E, 0x6C, ++ 0x63, 0x6E, 0x51, 0x75, 0x59, 0x32, 0x39, 0x74, 0x4D, 0x53, 0x51, 0x77, 0x0A, 0x49, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x74, 0x45, 0x61, 0x57, 0x64, 0x70, 0x51, 0x32, 0x56, 0x79, 0x64, 0x43, 0x42, 0x42, 0x63, 0x33, 0x4E, ++ 0x31, 0x63, 0x6D, 0x56, 0x6B, 0x49, 0x45, 0x6C, 0x45, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x44, 0x59, 0x78, 0x4D, 0x54, 0x45, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x44, 0x41, ++ 0x77, 0x57, 0x68, 0x63, 0x4E, 0x4D, 0x7A, 0x45, 0x78, 0x0A, 0x4D, 0x54, 0x45, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x57, 0x6A, 0x42, 0x6C, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, ++ 0x4A, 0x56, 0x55, 0x7A, 0x45, 0x56, 0x4D, 0x42, 0x4D, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x4D, 0x52, 0x47, 0x6C, 0x6E, 0x61, 0x55, 0x4E, 0x6C, 0x63, 0x6E, 0x51, 0x67, 0x53, 0x57, 0x35, 0x6A, 0x4D, 0x52, 0x6B, 0x77, 0x46, 0x77, ++ 0x59, 0x44, 0x56, 0x51, 0x51, 0x4C, 0x0A, 0x45, 0x78, 0x42, 0x33, 0x64, 0x33, 0x63, 0x75, 0x5A, 0x47, 0x6C, 0x6E, 0x61, 0x57, 0x4E, 0x6C, 0x63, 0x6E, 0x51, 0x75, 0x59, 0x32, 0x39, 0x74, 0x4D, 0x53, 0x51, 0x77, 0x49, 0x67, 0x59, 0x44, 0x56, ++ 0x51, 0x51, 0x44, 0x45, 0x78, 0x74, 0x45, 0x61, 0x57, 0x64, 0x70, 0x51, 0x32, 0x56, 0x79, 0x64, 0x43, 0x42, 0x42, 0x63, 0x33, 0x4E, 0x31, 0x63, 0x6D, 0x56, 0x6B, 0x49, 0x45, 0x6C, 0x45, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, ++ 0x30, 0x45, 0x77, 0x0A, 0x67, 0x67, 0x45, 0x69, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x42, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x45, 0x4B, ++ 0x41, 0x6F, 0x49, 0x42, 0x41, 0x51, 0x43, 0x74, 0x44, 0x68, 0x58, 0x4F, 0x35, 0x45, 0x4F, 0x41, 0x58, 0x4C, 0x47, 0x48, 0x38, 0x37, 0x64, 0x67, 0x2B, 0x58, 0x45, 0x53, 0x70, 0x61, 0x37, 0x63, 0x4A, 0x70, 0x53, 0x49, 0x71, 0x76, 0x54, 0x4F, ++ 0x0A, 0x39, 0x53, 0x41, 0x35, 0x4B, 0x46, 0x68, 0x67, 0x44, 0x50, 0x69, 0x41, 0x32, 0x71, 0x6B, 0x56, 0x6C, 0x54, 0x4A, 0x68, 0x50, 0x4C, 0x57, 0x78, 0x4B, 0x49, 0x53, 0x4B, 0x69, 0x74, 0x79, 0x66, 0x43, 0x67, 0x79, 0x44, 0x46, 0x33, 0x71, ++ 0x50, 0x6B, 0x4B, 0x79, 0x4B, 0x35, 0x33, 0x6C, 0x54, 0x58, 0x44, 0x47, 0x45, 0x4B, 0x76, 0x59, 0x50, 0x6D, 0x44, 0x49, 0x32, 0x64, 0x73, 0x7A, 0x65, 0x33, 0x54, 0x79, 0x6F, 0x6F, 0x75, 0x39, 0x71, 0x2B, 0x79, 0x48, 0x79, 0x0A, 0x55, 0x6D, ++ 0x48, 0x66, 0x6E, 0x79, 0x44, 0x58, 0x48, 0x2B, 0x4B, 0x78, 0x32, 0x66, 0x34, 0x59, 0x5A, 0x4E, 0x49, 0x53, 0x57, 0x31, 0x2F, 0x35, 0x57, 0x42, 0x67, 0x31, 0x76, 0x45, 0x66, 0x4E, 0x6F, 0x54, 0x62, 0x35, 0x61, 0x33, 0x2F, 0x55, 0x73, 0x44, ++ 0x67, 0x2B, 0x77, 0x52, 0x76, 0x44, 0x6A, 0x44, 0x50, 0x5A, 0x32, 0x43, 0x38, 0x59, 0x2F, 0x69, 0x67, 0x50, 0x73, 0x36, 0x65, 0x44, 0x31, 0x73, 0x4E, 0x75, 0x52, 0x4D, 0x42, 0x68, 0x4E, 0x5A, 0x59, 0x57, 0x0A, 0x2F, 0x6C, 0x6D, 0x63, 0x69, ++ 0x33, 0x5A, 0x74, 0x31, 0x2F, 0x47, 0x69, 0x53, 0x77, 0x30, 0x72, 0x2F, 0x77, 0x74, 0x79, 0x32, 0x70, 0x35, 0x67, 0x30, 0x49, 0x36, 0x51, 0x4E, 0x63, 0x5A, 0x34, 0x56, 0x59, 0x63, 0x67, 0x6F, 0x63, 0x2F, 0x6C, 0x62, 0x51, 0x72, 0x49, 0x53, ++ 0x58, 0x77, 0x78, 0x6D, 0x44, 0x4E, 0x73, 0x49, 0x75, 0x6D, 0x48, 0x30, 0x44, 0x4A, 0x61, 0x6F, 0x72, 0x6F, 0x54, 0x67, 0x68, 0x48, 0x74, 0x4F, 0x52, 0x65, 0x64, 0x6D, 0x54, 0x70, 0x79, 0x0A, 0x6F, 0x65, 0x62, 0x36, 0x70, 0x4E, 0x6E, 0x56, ++ 0x46, 0x7A, 0x46, 0x31, 0x72, 0x6F, 0x56, 0x39, 0x49, 0x71, 0x34, 0x2F, 0x41, 0x55, 0x61, 0x47, 0x39, 0x69, 0x68, 0x35, 0x79, 0x4C, 0x48, 0x61, 0x35, 0x46, 0x63, 0x58, 0x78, 0x48, 0x34, 0x63, 0x44, 0x72, 0x43, 0x30, 0x6B, 0x71, 0x5A, 0x57, ++ 0x73, 0x37, 0x32, 0x79, 0x6C, 0x2B, 0x32, 0x71, 0x70, 0x2F, 0x43, 0x33, 0x78, 0x61, 0x67, 0x2F, 0x6C, 0x52, 0x62, 0x51, 0x2F, 0x36, 0x47, 0x57, 0x36, 0x77, 0x68, 0x66, 0x0A, 0x47, 0x48, 0x64, 0x50, 0x41, 0x67, 0x4D, 0x42, 0x41, 0x41, 0x47, ++ 0x6A, 0x59, 0x7A, 0x42, 0x68, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x42, 0x68, 0x6A, 0x41, 0x50, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x52, 0x4D, 0x42, 0x41, 0x66, 0x38, ++ 0x45, 0x42, 0x54, 0x41, 0x44, 0x41, 0x51, 0x48, 0x2F, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x52, 0x46, 0x0A, 0x36, 0x36, 0x4B, 0x76, 0x39, 0x4A, 0x4C, 0x4C, 0x67, 0x6A, 0x45, 0x74, 0x55, 0x59, ++ 0x75, 0x6E, 0x70, 0x79, 0x47, 0x64, 0x38, 0x32, 0x33, 0x49, 0x44, 0x7A, 0x41, 0x66, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x53, 0x4D, 0x45, 0x47, 0x44, 0x41, 0x57, 0x67, 0x42, 0x52, 0x46, 0x36, 0x36, 0x4B, 0x76, 0x39, 0x4A, 0x4C, 0x4C, 0x67, 0x6A, ++ 0x45, 0x74, 0x55, 0x59, 0x75, 0x6E, 0x70, 0x79, 0x47, 0x64, 0x38, 0x32, 0x33, 0x49, 0x44, 0x7A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x0A, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x55, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, ++ 0x51, 0x45, 0x41, 0x6F, 0x67, 0x36, 0x38, 0x33, 0x2B, 0x4C, 0x74, 0x38, 0x4F, 0x4E, 0x79, 0x63, 0x33, 0x70, 0x6B, 0x6C, 0x4C, 0x2F, 0x33, 0x63, 0x6D, 0x62, 0x59, 0x4D, 0x75, 0x52, 0x43, 0x64, 0x57, 0x4B, 0x75, 0x68, 0x2B, 0x76, 0x79, 0x31, ++ 0x64, 0x6E, 0x65, 0x56, 0x72, 0x4F, 0x66, 0x7A, 0x4D, 0x34, 0x55, 0x4B, 0x4C, 0x6B, 0x4E, 0x6C, 0x32, 0x42, 0x63, 0x0A, 0x45, 0x6B, 0x78, 0x59, 0x35, 0x4E, 0x4D, 0x39, 0x67, 0x30, 0x6C, 0x46, 0x57, 0x4A, 0x63, 0x31, 0x61, 0x52, 0x71, 0x6F, ++ 0x52, 0x2B, 0x70, 0x57, 0x78, 0x6E, 0x6D, 0x72, 0x45, 0x74, 0x68, 0x6E, 0x67, 0x59, 0x54, 0x66, 0x66, 0x77, 0x6B, 0x38, 0x6C, 0x4F, 0x61, 0x34, 0x4A, 0x69, 0x77, 0x67, 0x76, 0x54, 0x32, 0x7A, 0x4B, 0x49, 0x6E, 0x33, 0x58, 0x2F, 0x38, 0x69, ++ 0x34, 0x70, 0x65, 0x45, 0x48, 0x2B, 0x6C, 0x6C, 0x37, 0x34, 0x66, 0x67, 0x33, 0x38, 0x46, 0x6E, 0x0A, 0x53, 0x62, 0x4E, 0x64, 0x36, 0x37, 0x49, 0x4A, 0x4B, 0x75, 0x73, 0x6D, 0x37, 0x58, 0x69, 0x2B, 0x66, 0x54, 0x38, 0x72, 0x38, 0x37, 0x63, ++ 0x6D, 0x4E, 0x57, 0x31, 0x66, 0x69, 0x51, 0x47, 0x32, 0x53, 0x56, 0x75, 0x66, 0x41, 0x51, 0x57, 0x62, 0x71, 0x7A, 0x30, 0x6C, 0x77, 0x63, 0x79, 0x32, 0x66, 0x38, 0x4C, 0x78, 0x62, 0x34, 0x62, 0x47, 0x2B, 0x6D, 0x52, 0x6F, 0x36, 0x34, 0x45, ++ 0x74, 0x6C, 0x4F, 0x74, 0x43, 0x74, 0x2F, 0x71, 0x4D, 0x48, 0x74, 0x31, 0x69, 0x0A, 0x38, 0x62, 0x35, 0x51, 0x5A, 0x37, 0x64, 0x73, 0x76, 0x66, 0x50, 0x78, 0x48, 0x32, 0x73, 0x4D, 0x4E, 0x67, 0x63, 0x57, 0x66, 0x7A, 0x64, 0x38, 0x71, 0x56, ++ 0x74, 0x74, 0x65, 0x76, 0x45, 0x53, 0x52, 0x6D, 0x43, 0x44, 0x31, 0x79, 0x63, 0x45, 0x76, 0x6B, 0x76, 0x4F, 0x6C, 0x37, 0x37, 0x44, 0x5A, 0x79, 0x70, 0x6F, 0x45, 0x64, 0x2B, 0x41, 0x35, 0x77, 0x77, 0x7A, 0x5A, 0x72, 0x38, 0x54, 0x44, 0x52, ++ 0x52, 0x75, 0x38, 0x33, 0x38, 0x66, 0x59, 0x78, 0x41, 0x65, 0x0A, 0x2B, 0x6F, 0x30, 0x62, 0x4A, 0x57, 0x31, 0x73, 0x6A, 0x36, 0x57, 0x33, 0x59, 0x51, 0x47, 0x78, 0x30, 0x71, 0x4D, 0x6D, 0x6F, 0x52, 0x42, 0x78, 0x6E, 0x61, 0x33, 0x69, 0x77, ++ 0x2F, 0x6E, 0x44, 0x6D, 0x56, 0x47, 0x33, 0x4B, 0x77, 0x63, 0x49, 0x7A, 0x69, 0x37, 0x6D, 0x55, 0x4C, 0x4B, 0x6E, 0x2B, 0x67, 0x70, 0x46, 0x4C, 0x36, 0x4C, 0x77, 0x38, 0x67, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, ++ 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, ++ 0x43, 0x41, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, ++ 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x44, 0x72, 0x7A, 0x43, 0x43, 0x41, 0x70, 0x65, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x43, 0x44, 0x76, 0x67, 0x56, ++ 0x70, 0x42, 0x43, 0x52, 0x72, 0x47, 0x68, 0x64, 0x57, 0x72, 0x4A, 0x57, 0x5A, 0x48, 0x48, 0x53, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x55, 0x46, 0x41, 0x44, 0x42, 0x68, 0x4D, ++ 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x0A, 0x45, 0x77, 0x4A, 0x56, 0x55, 0x7A, 0x45, 0x56, 0x4D, 0x42, 0x4D, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x4D, 0x52, 0x47, 0x6C, 0x6E, 0x61, 0x55, 0x4E, 0x6C, ++ 0x63, 0x6E, 0x51, 0x67, 0x53, 0x57, 0x35, 0x6A, 0x4D, 0x52, 0x6B, 0x77, 0x46, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4C, 0x45, 0x78, 0x42, 0x33, 0x64, 0x33, 0x63, 0x75, 0x5A, 0x47, 0x6C, 0x6E, 0x61, 0x57, 0x4E, 0x6C, 0x63, 0x6E, 0x51, 0x75, ++ 0x59, 0x32, 0x39, 0x74, 0x4D, 0x53, 0x41, 0x77, 0x0A, 0x48, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x64, 0x45, 0x61, 0x57, 0x64, 0x70, 0x51, 0x32, 0x56, 0x79, 0x64, 0x43, 0x42, 0x48, 0x62, 0x47, 0x39, 0x69, 0x59, 0x57, 0x77, ++ 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x51, 0x54, 0x41, 0x65, 0x46, 0x77, 0x30, 0x77, 0x4E, 0x6A, 0x45, 0x78, 0x4D, 0x54, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x44, 0x42, 0x61, 0x46, 0x77, 0x30, 0x7A, 0x4D, 0x54, 0x45, ++ 0x78, 0x4D, 0x54, 0x41, 0x77, 0x0A, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x44, 0x42, 0x61, 0x4D, 0x47, 0x45, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6C, 0x56, 0x54, 0x4D, 0x52, 0x55, 0x77, 0x45, 0x77, ++ 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x45, 0x77, 0x78, 0x45, 0x61, 0x57, 0x64, 0x70, 0x51, 0x32, 0x56, 0x79, 0x64, 0x43, 0x42, 0x4A, 0x62, 0x6D, 0x4D, 0x78, 0x47, 0x54, 0x41, 0x58, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x73, 0x54, 0x45, 0x48, ++ 0x64, 0x33, 0x0A, 0x64, 0x79, 0x35, 0x6B, 0x61, 0x57, 0x64, 0x70, 0x59, 0x32, 0x56, 0x79, 0x64, 0x43, 0x35, 0x6A, 0x62, 0x32, 0x30, 0x78, 0x49, 0x44, 0x41, 0x65, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x46, 0x30, 0x52, 0x70, 0x5A, ++ 0x32, 0x6C, 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x49, 0x45, 0x64, 0x73, 0x62, 0x32, 0x4A, 0x68, 0x62, 0x43, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x42, 0x4D, 0x49, 0x49, 0x42, 0x49, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x0A, ++ 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x45, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x51, 0x38, 0x41, 0x4D, 0x49, 0x49, 0x42, 0x43, 0x67, 0x4B, 0x43, 0x41, 0x51, 0x45, 0x41, 0x34, 0x6A, 0x76, 0x68, 0x45, 0x58, 0x4C, 0x65, ++ 0x71, 0x4B, 0x54, 0x54, 0x6F, 0x31, 0x65, 0x71, 0x55, 0x4B, 0x4B, 0x50, 0x43, 0x33, 0x65, 0x51, 0x79, 0x61, 0x4B, 0x6C, 0x37, 0x68, 0x4C, 0x4F, 0x6C, 0x6C, 0x73, 0x42, 0x43, 0x53, 0x44, 0x4D, 0x41, 0x5A, 0x4F, 0x6E, 0x0A, 0x54, 0x6A, 0x43, ++ 0x33, 0x55, 0x2F, 0x64, 0x44, 0x78, 0x47, 0x6B, 0x41, 0x56, 0x35, 0x33, 0x69, 0x6A, 0x53, 0x4C, 0x64, 0x68, 0x77, 0x5A, 0x41, 0x41, 0x49, 0x45, 0x4A, 0x7A, 0x73, 0x34, 0x62, 0x67, 0x37, 0x2F, 0x66, 0x7A, 0x54, 0x74, 0x78, 0x52, 0x75, 0x4C, ++ 0x57, 0x5A, 0x73, 0x63, 0x46, 0x73, 0x33, 0x59, 0x6E, 0x46, 0x6F, 0x39, 0x37, 0x6E, 0x68, 0x36, 0x56, 0x66, 0x65, 0x36, 0x33, 0x53, 0x4B, 0x4D, 0x49, 0x32, 0x74, 0x61, 0x76, 0x65, 0x67, 0x77, 0x35, 0x0A, 0x42, 0x6D, 0x56, 0x2F, 0x53, 0x6C, ++ 0x30, 0x66, 0x76, 0x42, 0x66, 0x34, 0x71, 0x37, 0x37, 0x75, 0x4B, 0x4E, 0x64, 0x30, 0x66, 0x33, 0x70, 0x34, 0x6D, 0x56, 0x6D, 0x46, 0x61, 0x47, 0x35, 0x63, 0x49, 0x7A, 0x4A, 0x4C, 0x76, 0x30, 0x37, 0x41, 0x36, 0x46, 0x70, 0x74, 0x34, 0x33, ++ 0x43, 0x2F, 0x64, 0x78, 0x43, 0x2F, 0x2F, 0x41, 0x48, 0x32, 0x68, 0x64, 0x6D, 0x6F, 0x52, 0x42, 0x42, 0x59, 0x4D, 0x71, 0x6C, 0x31, 0x47, 0x4E, 0x58, 0x52, 0x6F, 0x72, 0x35, 0x48, 0x0A, 0x34, 0x69, 0x64, 0x71, 0x39, 0x4A, 0x6F, 0x7A, 0x2B, ++ 0x45, 0x6B, 0x49, 0x59, 0x49, 0x76, 0x55, 0x58, 0x37, 0x51, 0x36, 0x68, 0x4C, 0x2B, 0x68, 0x71, 0x6B, 0x70, 0x4D, 0x66, 0x54, 0x37, 0x50, 0x54, 0x31, 0x39, 0x73, 0x64, 0x6C, 0x36, 0x67, 0x53, 0x7A, 0x65, 0x52, 0x6E, 0x74, 0x77, 0x69, 0x35, ++ 0x6D, 0x33, 0x4F, 0x46, 0x42, 0x71, 0x4F, 0x61, 0x73, 0x76, 0x2B, 0x7A, 0x62, 0x4D, 0x55, 0x5A, 0x42, 0x66, 0x48, 0x57, 0x79, 0x6D, 0x65, 0x4D, 0x72, 0x2F, 0x79, 0x0A, 0x37, 0x76, 0x72, 0x54, 0x43, 0x30, 0x4C, 0x55, 0x71, 0x37, 0x64, 0x42, ++ 0x4D, 0x74, 0x6F, 0x4D, 0x31, 0x4F, 0x2F, 0x34, 0x67, 0x64, 0x57, 0x37, 0x6A, 0x56, 0x67, 0x2F, 0x74, 0x52, 0x76, 0x6F, 0x53, 0x53, 0x69, 0x69, 0x63, 0x4E, 0x6F, 0x78, 0x42, 0x4E, 0x33, 0x33, 0x73, 0x68, 0x62, 0x79, 0x54, 0x41, 0x70, 0x4F, ++ 0x42, 0x36, 0x6A, 0x74, 0x53, 0x6A, 0x31, 0x65, 0x74, 0x58, 0x2B, 0x6A, 0x6B, 0x4D, 0x4F, 0x76, 0x4A, 0x77, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x0A, 0x6F, 0x32, 0x4D, 0x77, 0x59, 0x54, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, ++ 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x59, 0x59, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x64, 0x42, 0x67, 0x4E, ++ 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x41, 0x39, 0x35, 0x51, 0x4E, 0x56, 0x62, 0x52, 0x54, 0x4C, 0x74, 0x6D, 0x0A, 0x38, 0x4B, 0x50, 0x69, 0x47, 0x78, 0x76, 0x44, 0x6C, 0x37, 0x49, 0x39, 0x30, 0x56, 0x55, 0x77, 0x48, 0x77, ++ 0x59, 0x44, 0x56, 0x52, 0x30, 0x6A, 0x42, 0x42, 0x67, 0x77, 0x46, 0x6F, 0x41, 0x55, 0x41, 0x39, 0x35, 0x51, 0x4E, 0x56, 0x62, 0x52, 0x54, 0x4C, 0x74, 0x6D, 0x38, 0x4B, 0x50, 0x69, 0x47, 0x78, 0x76, 0x44, 0x6C, 0x37, 0x49, 0x39, 0x30, 0x56, ++ 0x55, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x46, 0x0A, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x45, 0x42, 0x41, 0x4D, 0x75, 0x63, 0x4E, 0x36, 0x70, 0x49, 0x45, 0x78, 0x49, 0x4B, 0x2B, ++ 0x74, 0x31, 0x45, 0x6E, 0x45, 0x39, 0x53, 0x73, 0x50, 0x54, 0x66, 0x72, 0x67, 0x54, 0x31, 0x65, 0x58, 0x6B, 0x49, 0x6F, 0x79, 0x51, 0x59, 0x2F, 0x45, 0x73, 0x72, 0x68, 0x4D, 0x41, 0x74, 0x75, 0x64, 0x58, 0x48, 0x2F, 0x76, 0x54, 0x42, 0x48, ++ 0x31, 0x6A, 0x4C, 0x75, 0x47, 0x32, 0x63, 0x65, 0x6E, 0x54, 0x6E, 0x6D, 0x43, 0x6D, 0x72, 0x0A, 0x45, 0x62, 0x58, 0x6A, 0x63, 0x4B, 0x43, 0x68, 0x7A, 0x55, 0x79, 0x49, 0x6D, 0x5A, 0x4F, 0x4D, 0x6B, 0x58, 0x44, 0x69, 0x71, 0x77, 0x38, 0x63, ++ 0x76, 0x70, 0x4F, 0x70, 0x2F, 0x32, 0x50, 0x56, 0x35, 0x41, 0x64, 0x67, 0x30, 0x36, 0x4F, 0x2F, 0x6E, 0x56, 0x73, 0x4A, 0x38, 0x64, 0x57, 0x4F, 0x34, 0x31, 0x50, 0x30, 0x6A, 0x6D, 0x50, 0x36, 0x50, 0x36, 0x66, 0x62, 0x74, 0x47, 0x62, 0x66, ++ 0x59, 0x6D, 0x62, 0x57, 0x30, 0x57, 0x35, 0x42, 0x6A, 0x66, 0x49, 0x74, 0x0A, 0x74, 0x65, 0x70, 0x33, 0x53, 0x70, 0x2B, 0x64, 0x57, 0x4F, 0x49, 0x72, 0x57, 0x63, 0x42, 0x41, 0x49, 0x2B, 0x30, 0x74, 0x4B, 0x49, 0x4A, 0x46, 0x50, 0x6E, 0x6C, ++ 0x55, 0x6B, 0x69, 0x61, 0x59, 0x34, 0x49, 0x42, 0x49, 0x71, 0x44, 0x66, 0x76, 0x38, 0x4E, 0x5A, 0x35, 0x59, 0x42, 0x62, 0x65, 0x72, 0x4F, 0x67, 0x4F, 0x7A, 0x57, 0x36, 0x73, 0x52, 0x42, 0x63, 0x34, 0x4C, 0x30, 0x6E, 0x61, 0x34, 0x55, 0x55, ++ 0x2B, 0x4B, 0x72, 0x6B, 0x32, 0x55, 0x38, 0x38, 0x36, 0x0A, 0x55, 0x41, 0x62, 0x33, 0x4C, 0x75, 0x6A, 0x45, 0x56, 0x30, 0x6C, 0x73, 0x59, 0x53, 0x45, 0x59, 0x31, 0x51, 0x53, 0x74, 0x65, 0x44, 0x77, 0x73, 0x4F, 0x6F, 0x42, 0x72, 0x70, 0x2B, ++ 0x75, 0x76, 0x46, 0x52, 0x54, 0x70, 0x32, 0x49, 0x6E, 0x42, 0x75, 0x54, 0x68, 0x73, 0x34, 0x70, 0x46, 0x73, 0x69, 0x76, 0x39, 0x6B, 0x75, 0x58, 0x63, 0x6C, 0x56, 0x7A, 0x44, 0x41, 0x47, 0x79, 0x53, 0x6A, 0x34, 0x64, 0x7A, 0x70, 0x33, 0x30, ++ 0x64, 0x38, 0x74, 0x62, 0x51, 0x6B, 0x0A, 0x43, 0x41, 0x55, 0x77, 0x37, 0x43, 0x32, 0x39, 0x43, 0x37, 0x39, 0x46, 0x76, 0x31, 0x43, 0x35, 0x71, 0x66, 0x50, 0x72, 0x6D, 0x41, 0x45, 0x53, 0x72, 0x63, 0x69, 0x49, 0x78, 0x70, 0x67, 0x30, 0x58, ++ 0x34, 0x30, 0x4B, 0x50, 0x4D, 0x62, 0x70, 0x31, 0x5A, 0x57, 0x56, 0x62, 0x64, 0x34, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, ++ 0x2D, 0x0A, 0x0A, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x48, 0x69, 0x67, 0x68, 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x61, 0x6E, 0x63, 0x65, 0x20, 0x45, 0x56, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x0A, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, ++ 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x44, 0x78, 0x54, 0x43, 0x43, 0x41, 0x71, 0x32, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, ++ 0x51, 0x41, 0x71, 0x78, 0x63, 0x4A, 0x6D, 0x6F, 0x4C, 0x51, 0x4A, 0x75, 0x50, 0x43, 0x33, 0x6E, 0x79, 0x72, 0x6B, 0x59, 0x6C, 0x64, 0x7A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x55, ++ 0x46, 0x41, 0x44, 0x42, 0x73, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x0A, 0x45, 0x77, 0x4A, 0x56, 0x55, 0x7A, 0x45, 0x56, 0x4D, 0x42, 0x4D, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x4D, 0x52, 0x47, ++ 0x6C, 0x6E, 0x61, 0x55, 0x4E, 0x6C, 0x63, 0x6E, 0x51, 0x67, 0x53, 0x57, 0x35, 0x6A, 0x4D, 0x52, 0x6B, 0x77, 0x46, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4C, 0x45, 0x78, 0x42, 0x33, 0x64, 0x33, 0x63, 0x75, 0x5A, 0x47, 0x6C, 0x6E, 0x61, 0x57, ++ 0x4E, 0x6C, 0x63, 0x6E, 0x51, 0x75, 0x59, 0x32, 0x39, 0x74, 0x4D, 0x53, 0x73, 0x77, 0x0A, 0x4B, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x79, 0x4A, 0x45, 0x61, 0x57, 0x64, 0x70, 0x51, 0x32, 0x56, 0x79, 0x64, 0x43, 0x42, 0x49, 0x61, ++ 0x57, 0x64, 0x6F, 0x49, 0x45, 0x46, 0x7A, 0x63, 0x33, 0x56, 0x79, 0x59, 0x57, 0x35, 0x6A, 0x5A, 0x53, 0x42, 0x46, 0x56, 0x69, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x42, 0x4D, 0x42, 0x34, 0x58, 0x44, 0x54, 0x41, 0x32, 0x4D, ++ 0x54, 0x45, 0x78, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x0A, 0x4D, 0x46, 0x6F, 0x58, 0x44, 0x54, 0x4D, 0x78, 0x4D, 0x54, 0x45, 0x78, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x46, 0x6F, 0x77, 0x62, 0x44, 0x45, 0x4C, ++ 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x56, 0x56, 0x4D, 0x78, 0x46, 0x54, 0x41, 0x54, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x44, 0x45, 0x52, 0x70, 0x5A, 0x32, 0x6C, 0x44, 0x5A, 0x58, 0x4A, 0x30, ++ 0x49, 0x45, 0x6C, 0x75, 0x59, 0x7A, 0x45, 0x5A, 0x0A, 0x4D, 0x42, 0x63, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x78, 0x4D, 0x51, 0x64, 0x33, 0x64, 0x33, 0x4C, 0x6D, 0x52, 0x70, 0x5A, 0x32, 0x6C, 0x6A, 0x5A, 0x58, 0x4A, 0x30, 0x4C, 0x6D, 0x4E, ++ 0x76, 0x62, 0x54, 0x45, 0x72, 0x4D, 0x43, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x69, 0x52, 0x47, 0x6C, 0x6E, 0x61, 0x55, 0x4E, 0x6C, 0x63, 0x6E, 0x51, 0x67, 0x53, 0x47, 0x6C, 0x6E, 0x61, 0x43, 0x42, 0x42, 0x63, 0x33, 0x4E, ++ 0x31, 0x63, 0x6D, 0x46, 0x75, 0x0A, 0x59, 0x32, 0x55, 0x67, 0x52, 0x56, 0x59, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x51, 0x54, 0x43, 0x43, 0x41, 0x53, 0x49, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, ++ 0x63, 0x4E, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x45, 0x50, 0x41, 0x44, 0x43, 0x43, 0x41, 0x51, 0x6F, 0x43, 0x67, 0x67, 0x45, 0x42, 0x41, 0x4D, 0x62, 0x4D, 0x35, 0x58, 0x50, 0x6D, 0x2B, 0x39, 0x53, 0x37, 0x35, 0x53, ++ 0x30, 0x74, 0x0A, 0x4D, 0x71, 0x62, 0x66, 0x35, 0x59, 0x45, 0x2F, 0x79, 0x63, 0x30, 0x6C, 0x53, 0x62, 0x5A, 0x78, 0x4B, 0x73, 0x50, 0x56, 0x6C, 0x44, 0x52, 0x6E, 0x6F, 0x67, 0x6F, 0x63, 0x73, 0x46, 0x39, 0x70, 0x70, 0x6B, 0x43, 0x78, 0x78, ++ 0x4C, 0x65, 0x79, 0x6A, 0x39, 0x43, 0x59, 0x70, 0x4B, 0x6C, 0x42, 0x57, 0x54, 0x72, 0x54, 0x33, 0x4A, 0x54, 0x57, 0x50, 0x4E, 0x74, 0x30, 0x4F, 0x4B, 0x52, 0x4B, 0x7A, 0x45, 0x30, 0x6C, 0x67, 0x76, 0x64, 0x4B, 0x70, 0x56, 0x4D, 0x53, 0x0A, ++ 0x4F, 0x4F, 0x37, 0x7A, 0x53, 0x57, 0x31, 0x78, 0x6B, 0x58, 0x35, 0x6A, 0x74, 0x71, 0x75, 0x6D, 0x58, 0x38, 0x4F, 0x6B, 0x68, 0x50, 0x68, 0x50, 0x59, 0x6C, 0x47, 0x2B, 0x2B, 0x4D, 0x58, 0x73, 0x32, 0x7A, 0x69, 0x53, 0x34, 0x77, 0x62, 0x6C, ++ 0x43, 0x4A, 0x45, 0x4D, 0x78, 0x43, 0x68, 0x42, 0x56, 0x66, 0x76, 0x4C, 0x57, 0x6F, 0x6B, 0x56, 0x66, 0x6E, 0x48, 0x6F, 0x4E, 0x62, 0x39, 0x4E, 0x63, 0x67, 0x6B, 0x39, 0x76, 0x6A, 0x6F, 0x34, 0x55, 0x46, 0x74, 0x33, 0x0A, 0x4D, 0x52, 0x75, ++ 0x4E, 0x73, 0x38, 0x63, 0x6B, 0x52, 0x5A, 0x71, 0x6E, 0x72, 0x47, 0x30, 0x41, 0x46, 0x46, 0x6F, 0x45, 0x74, 0x37, 0x6F, 0x54, 0x36, 0x31, 0x45, 0x4B, 0x6D, 0x45, 0x46, 0x42, 0x49, 0x6B, 0x35, 0x6C, 0x59, 0x59, 0x65, 0x42, 0x51, 0x56, 0x43, ++ 0x6D, 0x65, 0x56, 0x79, 0x4A, 0x33, 0x68, 0x6C, 0x4B, 0x56, 0x39, 0x55, 0x75, 0x35, 0x6C, 0x30, 0x63, 0x55, 0x79, 0x78, 0x2B, 0x6D, 0x4D, 0x30, 0x61, 0x42, 0x68, 0x61, 0x6B, 0x61, 0x48, 0x50, 0x51, 0x0A, 0x4E, 0x41, 0x51, 0x54, 0x58, 0x4B, ++ 0x46, 0x78, 0x30, 0x31, 0x70, 0x38, 0x56, 0x64, 0x74, 0x65, 0x5A, 0x4F, 0x45, 0x33, 0x68, 0x7A, 0x42, 0x57, 0x42, 0x4F, 0x55, 0x52, 0x74, 0x43, 0x6D, 0x41, 0x45, 0x76, 0x46, 0x35, 0x4F, 0x59, 0x69, 0x69, 0x41, 0x68, 0x46, 0x38, 0x4A, 0x32, ++ 0x61, 0x33, 0x69, 0x4C, 0x64, 0x34, 0x38, 0x73, 0x6F, 0x4B, 0x71, 0x44, 0x69, 0x72, 0x43, 0x6D, 0x54, 0x43, 0x76, 0x32, 0x5A, 0x64, 0x6C, 0x59, 0x54, 0x42, 0x6F, 0x53, 0x55, 0x65, 0x0A, 0x68, 0x31, 0x30, 0x61, 0x55, 0x41, 0x73, 0x67, 0x45, ++ 0x73, 0x78, 0x42, 0x75, 0x32, 0x34, 0x4C, 0x55, 0x54, 0x69, 0x34, 0x53, 0x38, 0x73, 0x43, 0x41, 0x77, 0x45, 0x41, 0x41, 0x61, 0x4E, 0x6A, 0x4D, 0x47, 0x45, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x41, 0x51, 0x48, 0x2F, 0x42, ++ 0x41, 0x51, 0x44, 0x41, 0x67, 0x47, 0x47, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x0A, 0x41, 0x66, 0x38, 0x77, 0x48, 0x51, 0x59, 0x44, 0x56, 0x52, 0x30, 0x4F, ++ 0x42, 0x42, 0x59, 0x45, 0x46, 0x4C, 0x45, 0x2B, 0x77, 0x32, 0x6B, 0x44, 0x2B, 0x4C, 0x39, 0x48, 0x41, 0x64, 0x53, 0x59, 0x4A, 0x68, 0x6F, 0x49, 0x41, 0x75, 0x39, 0x6A, 0x5A, 0x43, 0x76, 0x44, 0x4D, 0x42, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, ++ 0x49, 0x77, 0x51, 0x59, 0x4D, 0x42, 0x61, 0x41, 0x46, 0x4C, 0x45, 0x2B, 0x77, 0x32, 0x6B, 0x44, 0x2B, 0x4C, 0x39, 0x48, 0x41, 0x64, 0x53, 0x59, 0x0A, 0x4A, 0x68, 0x6F, 0x49, 0x41, 0x75, 0x39, 0x6A, 0x5A, 0x43, 0x76, 0x44, 0x4D, 0x41, 0x30, ++ 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x42, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x42, 0x41, 0x51, 0x41, 0x63, 0x47, 0x67, 0x61, 0x58, 0x33, 0x4E, 0x65, 0x63, 0x6E, 0x7A, 0x79, 0x49, 0x5A, 0x67, 0x59, ++ 0x49, 0x56, 0x79, 0x48, 0x62, 0x49, 0x55, 0x66, 0x34, 0x4B, 0x6D, 0x65, 0x71, 0x76, 0x78, 0x67, 0x79, 0x64, 0x6B, 0x41, 0x51, 0x0A, 0x56, 0x38, 0x47, 0x4B, 0x38, 0x33, 0x72, 0x5A, 0x45, 0x57, 0x57, 0x4F, 0x4E, 0x66, 0x71, 0x65, 0x2F, 0x45, ++ 0x57, 0x31, 0x6E, 0x74, 0x6C, 0x4D, 0x4D, 0x55, 0x75, 0x34, 0x6B, 0x65, 0x68, 0x44, 0x4C, 0x49, 0x36, 0x7A, 0x65, 0x4D, 0x37, 0x62, 0x34, 0x31, 0x4E, 0x35, 0x63, 0x64, 0x62, 0x6C, 0x49, 0x5A, 0x51, 0x42, 0x32, 0x6C, 0x57, 0x48, 0x6D, 0x69, ++ 0x52, 0x6B, 0x39, 0x6F, 0x70, 0x6D, 0x7A, 0x4E, 0x36, 0x63, 0x4E, 0x38, 0x32, 0x6F, 0x4E, 0x4C, 0x46, 0x70, 0x0A, 0x6D, 0x79, 0x50, 0x49, 0x6E, 0x6E, 0x67, 0x69, 0x4B, 0x33, 0x42, 0x44, 0x34, 0x31, 0x56, 0x48, 0x4D, 0x57, 0x45, 0x5A, 0x37, ++ 0x31, 0x6A, 0x46, 0x68, 0x53, 0x39, 0x4F, 0x4D, 0x50, 0x61, 0x67, 0x4D, 0x52, 0x59, 0x6A, 0x79, 0x4F, 0x66, 0x69, 0x5A, 0x52, 0x59, 0x7A, 0x79, 0x37, 0x38, 0x61, 0x47, 0x36, 0x41, 0x39, 0x2B, 0x4D, 0x70, 0x65, 0x69, 0x7A, 0x47, 0x4C, 0x59, ++ 0x41, 0x69, 0x4A, 0x4C, 0x51, 0x77, 0x47, 0x58, 0x46, 0x4B, 0x33, 0x78, 0x50, 0x6B, 0x4B, 0x0A, 0x6D, 0x4E, 0x45, 0x56, 0x58, 0x35, 0x38, 0x53, 0x76, 0x6E, 0x77, 0x32, 0x59, 0x7A, 0x69, 0x39, 0x52, 0x4B, 0x52, 0x2F, 0x35, 0x43, 0x59, 0x72, ++ 0x43, 0x73, 0x53, 0x58, 0x61, 0x51, 0x33, 0x70, 0x6A, 0x4F, 0x4C, 0x41, 0x45, 0x46, 0x65, 0x34, 0x79, 0x48, 0x59, 0x53, 0x6B, 0x56, 0x58, 0x79, 0x53, 0x47, 0x6E, 0x59, 0x76, 0x43, 0x6F, 0x43, 0x57, 0x77, 0x39, 0x45, 0x31, 0x43, 0x41, 0x78, ++ 0x32, 0x2F, 0x53, 0x36, 0x63, 0x43, 0x5A, 0x64, 0x6B, 0x47, 0x43, 0x65, 0x0A, 0x76, 0x45, 0x73, 0x58, 0x43, 0x53, 0x2B, 0x30, 0x79, 0x78, 0x35, 0x44, 0x61, 0x4D, 0x6B, 0x48, 0x4A, 0x38, 0x48, 0x53, 0x58, 0x50, 0x66, 0x71, 0x49, 0x62, 0x6C, ++ 0x6F, 0x45, 0x70, 0x77, 0x38, 0x6E, 0x4C, 0x2B, 0x65, 0x2F, 0x49, 0x42, 0x63, 0x6D, 0x32, 0x50, 0x4E, 0x37, 0x45, 0x65, 0x71, 0x4A, 0x53, 0x64, 0x6E, 0x6F, 0x44, 0x66, 0x7A, 0x41, 0x49, 0x4A, 0x39, 0x56, 0x4E, 0x65, 0x70, 0x2B, 0x4F, 0x6B, ++ 0x75, 0x45, 0x36, 0x4E, 0x33, 0x36, 0x42, 0x39, 0x4B, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x53, 0x77, 0x69, ++ 0x73, 0x73, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x47, 0x6F, 0x6C, 0x64, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x32, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x75, 0x6A, 0x43, 0x43, 0x41, ++ 0x36, 0x4B, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x4A, 0x41, 0x4C, 0x74, 0x41, 0x48, 0x45, 0x50, 0x31, 0x58, 0x6B, 0x2B, 0x77, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x42, ++ 0x51, 0x55, 0x41, 0x4D, 0x45, 0x55, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6B, 0x4E, 0x49, 0x4D, 0x52, 0x55, 0x77, 0x0A, 0x45, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x45, 0x77, 0x78, 0x54, ++ 0x64, 0x32, 0x6C, 0x7A, 0x63, 0x31, 0x4E, 0x70, 0x5A, 0x32, 0x34, 0x67, 0x51, 0x55, 0x63, 0x78, 0x48, 0x7A, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x46, 0x6C, 0x4E, 0x33, 0x61, 0x58, 0x4E, 0x7A, 0x55, 0x32, 0x6C, 0x6E, ++ 0x62, 0x69, 0x42, 0x48, 0x62, 0x32, 0x78, 0x6B, 0x49, 0x45, 0x4E, 0x42, 0x49, 0x43, 0x30, 0x67, 0x52, 0x7A, 0x49, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x0A, 0x4D, 0x44, 0x59, 0x78, 0x4D, 0x44, 0x49, 0x31, 0x4D, 0x44, 0x67, 0x7A, 0x4D, 0x44, 0x4D, ++ 0x31, 0x57, 0x68, 0x63, 0x4E, 0x4D, 0x7A, 0x59, 0x78, 0x4D, 0x44, 0x49, 0x31, 0x4D, 0x44, 0x67, 0x7A, 0x4D, 0x44, 0x4D, 0x31, 0x57, 0x6A, 0x42, 0x46, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, ++ 0x44, 0x53, 0x44, 0x45, 0x56, 0x4D, 0x42, 0x4D, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x4D, 0x55, 0x33, 0x64, 0x70, 0x0A, 0x63, 0x33, 0x4E, 0x54, 0x61, 0x57, 0x64, 0x75, 0x49, 0x45, 0x46, 0x48, 0x4D, 0x52, 0x38, 0x77, 0x48, 0x51, ++ 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x5A, 0x54, 0x64, 0x32, 0x6C, 0x7A, 0x63, 0x31, 0x4E, 0x70, 0x5A, 0x32, 0x34, 0x67, 0x52, 0x32, 0x39, 0x73, 0x5A, 0x43, 0x42, 0x44, 0x51, 0x53, 0x41, 0x74, 0x49, 0x45, 0x63, 0x79, 0x4D, 0x49, ++ 0x49, 0x43, 0x49, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x0A, 0x41, 0x51, 0x45, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x67, 0x38, 0x41, 0x4D, 0x49, 0x49, 0x43, 0x43, 0x67, 0x4B, 0x43, 0x41, ++ 0x67, 0x45, 0x41, 0x72, 0x2B, 0x54, 0x75, 0x66, 0x6F, 0x73, 0x6B, 0x44, 0x68, 0x4A, 0x75, 0x71, 0x56, 0x41, 0x74, 0x46, 0x6B, 0x51, 0x37, 0x6B, 0x70, 0x4A, 0x63, 0x79, 0x72, 0x68, 0x64, 0x68, 0x4A, 0x4A, 0x43, 0x45, 0x79, 0x71, 0x38, 0x5A, ++ 0x56, 0x65, 0x43, 0x51, 0x44, 0x35, 0x58, 0x4A, 0x4D, 0x31, 0x51, 0x69, 0x79, 0x55, 0x71, 0x0A, 0x74, 0x32, 0x2F, 0x38, 0x37, 0x36, 0x4C, 0x51, 0x77, 0x42, 0x38, 0x43, 0x4A, 0x45, 0x6F, 0x54, 0x6C, 0x6F, 0x38, 0x6A, 0x45, 0x2B, 0x59, 0x6F, ++ 0x57, 0x41, 0x43, 0x6A, 0x52, 0x38, 0x63, 0x47, 0x70, 0x34, 0x51, 0x6A, 0x4B, 0x37, 0x75, 0x39, 0x6C, 0x69, 0x74, 0x2F, 0x56, 0x63, 0x79, 0x4C, 0x77, 0x56, 0x63, 0x66, 0x44, 0x6D, 0x4A, 0x6C, 0x44, 0x39, 0x30, 0x39, 0x56, 0x6F, 0x70, 0x7A, ++ 0x32, 0x71, 0x35, 0x2B, 0x62, 0x62, 0x71, 0x42, 0x48, 0x48, 0x35, 0x43, 0x0A, 0x6A, 0x43, 0x41, 0x31, 0x32, 0x55, 0x4E, 0x4E, 0x68, 0x50, 0x71, 0x45, 0x32, 0x31, 0x49, 0x73, 0x38, 0x77, 0x34, 0x6E, 0x64, 0x77, 0x74, 0x72, 0x76, 0x78, 0x45, ++ 0x76, 0x63, 0x6E, 0x69, 0x66, 0x4C, 0x74, 0x67, 0x2B, 0x35, 0x68, 0x67, 0x33, 0x57, 0x69, 0x70, 0x79, 0x2B, 0x64, 0x70, 0x69, 0x6B, 0x4A, 0x4B, 0x56, 0x79, 0x68, 0x2B, 0x63, 0x36, 0x62, 0x4D, 0x38, 0x4B, 0x38, 0x76, 0x7A, 0x41, 0x52, 0x4F, ++ 0x2F, 0x57, 0x73, 0x2F, 0x42, 0x74, 0x51, 0x70, 0x67, 0x0A, 0x76, 0x64, 0x32, 0x31, 0x6D, 0x57, 0x52, 0x54, 0x75, 0x4B, 0x43, 0x57, 0x73, 0x32, 0x2F, 0x69, 0x4A, 0x6E, 0x65, 0x52, 0x6A, 0x4F, 0x42, 0x69, 0x45, 0x41, 0x4B, 0x66, 0x4E, 0x41, ++ 0x2B, 0x6B, 0x31, 0x5A, 0x49, 0x7A, 0x55, 0x64, 0x36, 0x2B, 0x6A, 0x62, 0x71, 0x45, 0x65, 0x6D, 0x41, 0x38, 0x61, 0x74, 0x75, 0x66, 0x4B, 0x2B, 0x7A, 0x65, 0x33, 0x67, 0x45, 0x2F, 0x62, 0x6B, 0x33, 0x6C, 0x55, 0x49, 0x62, 0x4C, 0x74, 0x4B, ++ 0x2F, 0x74, 0x52, 0x45, 0x44, 0x46, 0x0A, 0x79, 0x6C, 0x71, 0x4D, 0x32, 0x74, 0x49, 0x72, 0x66, 0x4B, 0x6A, 0x75, 0x76, 0x71, 0x62, 0x6C, 0x43, 0x71, 0x6F, 0x4F, 0x70, 0x64, 0x38, 0x46, 0x55, 0x72, 0x64, 0x56, 0x78, 0x79, 0x4A, 0x64, 0x4D, ++ 0x6D, 0x71, 0x58, 0x6C, 0x32, 0x4D, 0x54, 0x32, 0x38, 0x6E, 0x62, 0x65, 0x54, 0x5A, 0x37, 0x68, 0x54, 0x70, 0x4B, 0x78, 0x56, 0x4B, 0x4A, 0x2B, 0x53, 0x54, 0x6E, 0x6E, 0x58, 0x65, 0x70, 0x67, 0x76, 0x39, 0x56, 0x48, 0x4B, 0x56, 0x78, 0x61, ++ 0x53, 0x76, 0x52, 0x0A, 0x41, 0x69, 0x54, 0x79, 0x73, 0x79, 0x62, 0x55, 0x61, 0x39, 0x6F, 0x45, 0x56, 0x65, 0x58, 0x42, 0x43, 0x73, 0x64, 0x74, 0x4D, 0x44, 0x65, 0x51, 0x4B, 0x75, 0x53, 0x65, 0x46, 0x44, 0x4E, 0x65, 0x46, 0x68, 0x64, 0x56, ++ 0x78, 0x56, 0x75, 0x31, 0x79, 0x7A, 0x53, 0x4A, 0x6B, 0x76, 0x47, 0x64, 0x4A, 0x6F, 0x2B, 0x68, 0x42, 0x39, 0x54, 0x47, 0x73, 0x6E, 0x68, 0x51, 0x32, 0x77, 0x77, 0x4D, 0x43, 0x33, 0x77, 0x4C, 0x6A, 0x45, 0x48, 0x58, 0x75, 0x65, 0x6E, 0x64, ++ 0x0A, 0x6A, 0x49, 0x6A, 0x33, 0x6F, 0x30, 0x32, 0x79, 0x4D, 0x73, 0x7A, 0x59, 0x46, 0x39, 0x72, 0x4E, 0x74, 0x38, 0x35, 0x6D, 0x6E, 0x64, 0x54, 0x39, 0x58, 0x76, 0x2B, 0x39, 0x6C, 0x7A, 0x34, 0x70, 0x64, 0x65, 0x64, 0x2B, 0x70, 0x32, 0x4A, ++ 0x59, 0x72, 0x79, 0x55, 0x30, 0x70, 0x55, 0x48, 0x48, 0x50, 0x62, 0x77, 0x4E, 0x55, 0x4D, 0x6F, 0x44, 0x41, 0x77, 0x38, 0x49, 0x57, 0x68, 0x2B, 0x56, 0x63, 0x33, 0x68, 0x69, 0x76, 0x36, 0x39, 0x79, 0x46, 0x47, 0x6B, 0x4F, 0x0A, 0x70, 0x65, ++ 0x55, 0x44, 0x44, 0x6E, 0x69, 0x4F, 0x4A, 0x69, 0x68, 0x43, 0x38, 0x41, 0x63, 0x4C, 0x59, 0x69, 0x41, 0x51, 0x5A, 0x7A, 0x6C, 0x47, 0x2B, 0x71, 0x6B, 0x44, 0x7A, 0x41, 0x51, 0x34, 0x65, 0x6D, 0x62, 0x76, 0x49, 0x49, 0x4F, 0x31, 0x6A, 0x45, ++ 0x70, 0x57, 0x6A, 0x70, 0x45, 0x41, 0x2F, 0x49, 0x35, 0x63, 0x67, 0x74, 0x36, 0x49, 0x6F, 0x4D, 0x50, 0x69, 0x61, 0x47, 0x35, 0x39, 0x6A, 0x65, 0x38, 0x38, 0x33, 0x57, 0x58, 0x30, 0x58, 0x61, 0x78, 0x52, 0x0A, 0x37, 0x79, 0x53, 0x41, 0x72, ++ 0x71, 0x70, 0x57, 0x6C, 0x32, 0x2F, 0x35, 0x72, 0x58, 0x33, 0x61, 0x59, 0x54, 0x2B, 0x59, 0x64, 0x7A, 0x79, 0x6C, 0x6B, 0x62, 0x59, 0x63, 0x6A, 0x43, 0x62, 0x61, 0x5A, 0x61, 0x49, 0x4A, 0x62, 0x63, 0x48, 0x69, 0x56, 0x4F, 0x4F, 0x35, 0x79, ++ 0x6B, 0x78, 0x4D, 0x67, 0x49, 0x39, 0x33, 0x65, 0x32, 0x43, 0x61, 0x48, 0x74, 0x2B, 0x32, 0x38, 0x6B, 0x67, 0x65, 0x44, 0x72, 0x70, 0x4F, 0x56, 0x47, 0x32, 0x59, 0x34, 0x4F, 0x47, 0x69, 0x0A, 0x47, 0x71, 0x4A, 0x33, 0x55, 0x4D, 0x2F, 0x45, ++ 0x59, 0x35, 0x4C, 0x73, 0x52, 0x78, 0x6D, 0x64, 0x36, 0x2B, 0x5A, 0x72, 0x7A, 0x73, 0x45, 0x43, 0x41, 0x77, 0x45, 0x41, 0x41, 0x61, 0x4F, 0x42, 0x72, 0x44, 0x43, 0x42, 0x71, 0x54, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x42, ++ 0x41, 0x66, 0x38, 0x45, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x51, 0x59, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x0A, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x64, 0x42, 0x67, 0x4E, ++ 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x57, 0x79, 0x56, 0x37, 0x6C, 0x71, 0x52, 0x6C, 0x55, 0x58, 0x36, 0x34, 0x4F, 0x66, 0x50, 0x41, 0x65, 0x47, 0x5A, 0x65, 0x36, 0x44, 0x72, 0x6E, 0x38, 0x4F, 0x34, 0x77, 0x48, 0x77, 0x59, ++ 0x44, 0x56, 0x52, 0x30, 0x6A, 0x42, 0x42, 0x67, 0x77, 0x46, 0x6F, 0x41, 0x55, 0x57, 0x79, 0x56, 0x37, 0x6C, 0x71, 0x52, 0x6C, 0x55, 0x58, 0x36, 0x34, 0x0A, 0x4F, 0x66, 0x50, 0x41, 0x65, 0x47, 0x5A, 0x65, 0x36, 0x44, 0x72, 0x6E, 0x38, 0x4F, ++ 0x34, 0x77, 0x52, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x67, 0x42, 0x44, 0x38, 0x77, 0x50, 0x54, 0x41, 0x37, 0x42, 0x67, 0x6C, 0x67, 0x68, 0x58, 0x51, 0x42, 0x57, 0x51, 0x45, 0x43, 0x41, 0x51, 0x45, 0x77, 0x4C, 0x6A, 0x41, 0x73, 0x42, 0x67, ++ 0x67, 0x72, 0x42, 0x67, 0x45, 0x46, 0x42, 0x51, 0x63, 0x43, 0x41, 0x52, 0x59, 0x67, 0x61, 0x48, 0x52, 0x30, 0x63, 0x44, 0x6F, 0x76, 0x0A, 0x4C, 0x33, 0x4A, 0x6C, 0x63, 0x47, 0x39, 0x7A, 0x61, 0x58, 0x52, 0x76, 0x63, 0x6E, 0x6B, 0x75, 0x63, ++ 0x33, 0x64, 0x70, 0x63, 0x33, 0x4E, 0x7A, 0x61, 0x57, 0x64, 0x75, 0x4C, 0x6D, 0x4E, 0x76, 0x62, 0x53, 0x38, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x46, 0x42, 0x51, 0x41, 0x44, 0x67, ++ 0x67, 0x49, 0x42, 0x41, 0x43, 0x65, 0x36, 0x34, 0x35, 0x52, 0x38, 0x38, 0x61, 0x37, 0x41, 0x33, 0x68, 0x66, 0x6D, 0x0A, 0x35, 0x64, 0x6A, 0x56, 0x39, 0x56, 0x53, 0x77, 0x67, 0x2F, 0x53, 0x37, 0x7A, 0x56, 0x34, 0x46, 0x65, 0x30, 0x2B, 0x66, ++ 0x64, 0x57, 0x61, 0x76, 0x50, 0x4F, 0x68, 0x57, 0x66, 0x76, 0x78, 0x79, 0x65, 0x44, 0x67, 0x44, 0x32, 0x53, 0x74, 0x69, 0x47, 0x77, 0x43, 0x35, 0x2B, 0x4F, 0x6C, 0x67, 0x7A, 0x63, 0x7A, 0x4F, 0x55, 0x59, 0x72, 0x48, 0x55, 0x44, 0x46, 0x75, ++ 0x34, 0x55, 0x70, 0x2B, 0x47, 0x43, 0x39, 0x70, 0x57, 0x62, 0x59, 0x39, 0x5A, 0x49, 0x45, 0x72, 0x0A, 0x34, 0x34, 0x4F, 0x45, 0x35, 0x69, 0x4B, 0x48, 0x6A, 0x6E, 0x33, 0x67, 0x37, 0x67, 0x4B, 0x5A, 0x59, 0x62, 0x67, 0x65, 0x39, 0x4C, 0x67, ++ 0x72, 0x69, 0x42, 0x49, 0x57, 0x68, 0x4D, 0x49, 0x78, 0x6B, 0x7A, 0x69, 0x57, 0x4D, 0x61, 0x61, 0x35, 0x4F, 0x31, 0x4D, 0x2F, 0x77, 0x79, 0x53, 0x54, 0x56, 0x6C, 0x74, 0x70, 0x6B, 0x75, 0x7A, 0x46, 0x77, 0x62, 0x73, 0x34, 0x41, 0x4F, 0x50, ++ 0x73, 0x46, 0x36, 0x6D, 0x34, 0x33, 0x4D, 0x64, 0x38, 0x41, 0x59, 0x4F, 0x66, 0x0A, 0x4D, 0x6B, 0x65, 0x36, 0x55, 0x69, 0x49, 0x30, 0x48, 0x54, 0x4A, 0x36, 0x43, 0x56, 0x61, 0x6E, 0x66, 0x43, 0x55, 0x32, 0x71, 0x54, 0x31, 0x4C, 0x32, 0x73, ++ 0x43, 0x43, 0x62, 0x77, 0x71, 0x37, 0x45, 0x73, 0x69, 0x48, 0x53, 0x79, 0x63, 0x52, 0x2B, 0x52, 0x34, 0x74, 0x78, 0x35, 0x4D, 0x2F, 0x6E, 0x74, 0x74, 0x66, 0x4A, 0x6D, 0x74, 0x53, 0x32, 0x53, 0x36, 0x4B, 0x38, 0x52, 0x54, 0x47, 0x52, 0x49, ++ 0x30, 0x56, 0x71, 0x62, 0x65, 0x2F, 0x76, 0x64, 0x36, 0x6D, 0x0A, 0x47, 0x75, 0x36, 0x75, 0x4C, 0x66, 0x74, 0x49, 0x64, 0x78, 0x66, 0x2B, 0x75, 0x2B, 0x79, 0x76, 0x47, 0x50, 0x55, 0x71, 0x55, 0x66, 0x41, 0x35, 0x68, 0x4A, 0x65, 0x56, 0x62, ++ 0x47, 0x34, 0x62, 0x77, 0x79, 0x76, 0x45, 0x64, 0x47, 0x42, 0x35, 0x4A, 0x62, 0x41, 0x4B, 0x4A, 0x39, 0x2F, 0x66, 0x58, 0x74, 0x49, 0x35, 0x7A, 0x30, 0x56, 0x39, 0x51, 0x6B, 0x76, 0x66, 0x73, 0x79, 0x77, 0x65, 0x78, 0x63, 0x5A, 0x64, 0x79, ++ 0x6C, 0x55, 0x36, 0x6F, 0x4A, 0x78, 0x70, 0x0A, 0x6D, 0x6F, 0x2F, 0x61, 0x37, 0x37, 0x4B, 0x77, 0x50, 0x4A, 0x2B, 0x48, 0x62, 0x42, 0x49, 0x72, 0x5A, 0x58, 0x41, 0x56, 0x55, 0x6A, 0x45, 0x61, 0x4A, 0x4D, 0x39, 0x76, 0x4D, 0x53, 0x4E, 0x51, ++ 0x48, 0x34, 0x78, 0x50, 0x6A, 0x79, 0x50, 0x44, 0x64, 0x45, 0x46, 0x6A, 0x48, 0x46, 0x57, 0x6F, 0x46, 0x4E, 0x30, 0x2B, 0x34, 0x46, 0x46, 0x51, 0x7A, 0x2F, 0x45, 0x62, 0x4D, 0x46, 0x59, 0x4F, 0x6B, 0x72, 0x43, 0x43, 0x68, 0x64, 0x69, 0x44, ++ 0x79, 0x79, 0x4A, 0x6B, 0x0A, 0x76, 0x43, 0x32, 0x34, 0x4A, 0x64, 0x56, 0x55, 0x6F, 0x72, 0x67, 0x47, 0x36, 0x71, 0x32, 0x53, 0x70, 0x43, 0x53, 0x67, 0x77, 0x59, 0x61, 0x31, 0x53, 0x68, 0x4E, 0x71, 0x52, 0x38, 0x38, 0x75, 0x43, 0x31, 0x61, ++ 0x56, 0x56, 0x4D, 0x76, 0x4F, 0x6D, 0x74, 0x74, 0x71, 0x74, 0x4B, 0x61, 0x79, 0x32, 0x30, 0x45, 0x49, 0x68, 0x69, 0x64, 0x33, 0x39, 0x32, 0x71, 0x67, 0x51, 0x6D, 0x77, 0x4C, 0x4F, 0x4D, 0x37, 0x58, 0x64, 0x56, 0x41, 0x79, 0x6B, 0x73, 0x4C, ++ 0x66, 0x0A, 0x4B, 0x7A, 0x41, 0x69, 0x53, 0x4E, 0x44, 0x56, 0x51, 0x54, 0x67, 0x6C, 0x58, 0x61, 0x54, 0x70, 0x58, 0x5A, 0x2F, 0x47, 0x6C, 0x48, 0x58, 0x51, 0x52, 0x66, 0x30, 0x77, 0x6C, 0x30, 0x4F, 0x50, 0x6B, 0x4B, 0x73, 0x4B, 0x78, 0x34, ++ 0x5A, 0x7A, 0x59, 0x45, 0x70, 0x70, 0x4C, 0x64, 0x36, 0x6C, 0x65, 0x4E, 0x63, 0x47, 0x32, 0x6D, 0x71, 0x65, 0x53, 0x7A, 0x35, 0x33, 0x4F, 0x69, 0x41, 0x54, 0x49, 0x67, 0x48, 0x51, 0x76, 0x32, 0x69, 0x65, 0x59, 0x32, 0x42, 0x72, 0x0A, 0x4E, ++ 0x55, 0x30, 0x4C, 0x62, 0x62, 0x71, 0x68, 0x50, 0x63, 0x43, 0x54, 0x34, 0x48, 0x38, 0x6A, 0x73, 0x31, 0x57, 0x74, 0x63, 0x69, 0x56, 0x4F, 0x52, 0x76, 0x6E, 0x53, 0x46, 0x75, 0x2B, 0x77, 0x5A, 0x4D, 0x45, 0x42, 0x6E, 0x75, 0x6E, 0x4B, 0x6F, ++ 0x47, 0x71, 0x59, 0x44, 0x73, 0x2F, 0x59, 0x59, 0x50, 0x49, 0x76, 0x53, 0x62, 0x6A, 0x6B, 0x51, 0x75, 0x45, 0x34, 0x4E, 0x52, 0x62, 0x30, 0x79, 0x47, 0x35, 0x50, 0x39, 0x34, 0x46, 0x57, 0x36, 0x4C, 0x71, 0x6A, 0x0A, 0x76, 0x69, 0x4F, 0x76, ++ 0x72, 0x76, 0x31, 0x76, 0x41, 0x2B, 0x41, 0x43, 0x4F, 0x7A, 0x42, 0x32, 0x2B, 0x68, 0x74, 0x74, 0x51, 0x63, 0x38, 0x42, 0x73, 0x65, 0x6D, 0x34, 0x79, 0x57, 0x62, 0x30, 0x32, 0x79, 0x62, 0x7A, 0x4F, 0x71, 0x52, 0x30, 0x38, 0x6B, 0x6B, 0x6B, ++ 0x57, 0x38, 0x6D, 0x77, 0x30, 0x46, 0x66, 0x42, 0x2B, 0x6A, 0x35, 0x36, 0x34, 0x5A, 0x66, 0x4A, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, ++ 0x2D, 0x2D, 0x0A, 0x0A, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x43, 0x41, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, ++ 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x44, 0x75, 0x44, 0x43, 0x43, 0x41, 0x71, 0x43, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, ++ 0x49, 0x51, 0x44, 0x50, 0x43, 0x4F, 0x58, 0x41, 0x67, 0x57, 0x70, 0x61, 0x31, 0x43, 0x66, 0x2F, 0x44, 0x72, 0x4A, 0x78, 0x68, 0x5A, 0x30, 0x44, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, ++ 0x55, 0x46, 0x41, 0x44, 0x42, 0x49, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x0A, 0x45, 0x77, 0x4A, 0x56, 0x55, 0x7A, 0x45, 0x67, 0x4D, 0x42, 0x34, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x58, 0x55, ++ 0x32, 0x56, 0x6A, 0x64, 0x58, 0x4A, 0x6C, 0x56, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x51, 0x67, 0x51, 0x32, 0x39, 0x79, 0x63, 0x47, 0x39, 0x79, 0x59, 0x58, 0x52, 0x70, 0x62, 0x32, 0x34, 0x78, 0x46, 0x7A, 0x41, 0x56, 0x42, 0x67, 0x4E, 0x56, 0x42, ++ 0x41, 0x4D, 0x54, 0x44, 0x6C, 0x4E, 0x6C, 0x59, 0x33, 0x56, 0x79, 0x5A, 0x56, 0x52, 0x79, 0x0A, 0x64, 0x58, 0x4E, 0x30, 0x49, 0x45, 0x4E, 0x42, 0x4D, 0x42, 0x34, 0x58, 0x44, 0x54, 0x41, 0x32, 0x4D, 0x54, 0x45, 0x77, 0x4E, 0x7A, 0x45, 0x35, ++ 0x4D, 0x7A, 0x45, 0x78, 0x4F, 0x46, 0x6F, 0x58, 0x44, 0x54, 0x49, 0x35, 0x4D, 0x54, 0x49, 0x7A, 0x4D, 0x54, 0x45, 0x35, 0x4E, 0x44, 0x41, 0x31, 0x4E, 0x56, 0x6F, 0x77, 0x53, 0x44, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, ++ 0x42, 0x68, 0x4D, 0x43, 0x56, 0x56, 0x4D, 0x78, 0x49, 0x44, 0x41, 0x65, 0x0A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x46, 0x31, 0x4E, 0x6C, 0x59, 0x33, 0x56, 0x79, 0x5A, 0x56, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x49, 0x45, 0x4E, ++ 0x76, 0x63, 0x6E, 0x42, 0x76, 0x63, 0x6D, 0x46, 0x30, 0x61, 0x57, 0x39, 0x75, 0x4D, 0x52, 0x63, 0x77, 0x46, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x77, 0x35, 0x54, 0x5A, 0x57, 0x4E, 0x31, 0x63, 0x6D, 0x56, 0x55, 0x63, 0x6E, 0x56, ++ 0x7A, 0x64, 0x43, 0x42, 0x44, 0x51, 0x54, 0x43, 0x43, 0x0A, 0x41, 0x53, 0x49, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x45, 0x50, 0x41, 0x44, ++ 0x43, 0x43, 0x41, 0x51, 0x6F, 0x43, 0x67, 0x67, 0x45, 0x42, 0x41, 0x4B, 0x75, 0x6B, 0x67, 0x65, 0x57, 0x56, 0x7A, 0x66, 0x58, 0x32, 0x46, 0x49, 0x37, 0x43, 0x54, 0x38, 0x72, 0x55, 0x34, 0x6E, 0x69, 0x56, 0x57, 0x4A, 0x78, 0x42, 0x34, 0x51, ++ 0x32, 0x5A, 0x51, 0x43, 0x51, 0x58, 0x0A, 0x4F, 0x5A, 0x45, 0x7A, 0x5A, 0x75, 0x6D, 0x2B, 0x34, 0x59, 0x4F, 0x76, 0x59, 0x6C, 0x79, 0x4A, 0x30, 0x66, 0x77, 0x6B, 0x57, 0x32, 0x47, 0x7A, 0x34, 0x42, 0x45, 0x52, 0x51, 0x52, 0x77, 0x64, 0x62, ++ 0x76, 0x43, 0x34, 0x75, 0x2F, 0x6A, 0x65, 0x70, 0x34, 0x47, 0x36, 0x70, 0x6B, 0x6A, 0x47, 0x6E, 0x78, 0x32, 0x39, 0x76, 0x6F, 0x36, 0x70, 0x51, 0x54, 0x36, 0x34, 0x6C, 0x4F, 0x30, 0x70, 0x47, 0x74, 0x53, 0x4F, 0x30, 0x67, 0x4D, 0x64, 0x41, ++ 0x2B, 0x39, 0x74, 0x0A, 0x44, 0x57, 0x63, 0x63, 0x56, 0x39, 0x63, 0x47, 0x72, 0x63, 0x72, 0x49, 0x39, 0x66, 0x34, 0x4F, 0x72, 0x32, 0x59, 0x6C, 0x53, 0x41, 0x53, 0x57, 0x43, 0x31, 0x32, 0x6A, 0x75, 0x68, 0x62, 0x44, 0x43, 0x45, 0x2F, 0x52, ++ 0x52, 0x76, 0x67, 0x55, 0x58, 0x50, 0x4C, 0x49, 0x58, 0x67, 0x47, 0x5A, 0x62, 0x66, 0x32, 0x49, 0x7A, 0x49, 0x61, 0x6F, 0x77, 0x57, 0x38, 0x78, 0x51, 0x6D, 0x78, 0x53, 0x50, 0x6D, 0x6A, 0x4C, 0x38, 0x78, 0x6B, 0x30, 0x33, 0x37, 0x75, 0x48, ++ 0x0A, 0x47, 0x46, 0x61, 0x41, 0x4A, 0x73, 0x54, 0x51, 0x33, 0x4D, 0x42, 0x76, 0x33, 0x39, 0x36, 0x67, 0x77, 0x70, 0x45, 0x57, 0x6F, 0x47, 0x51, 0x52, 0x53, 0x30, 0x53, 0x38, 0x48, 0x76, 0x62, 0x6E, 0x2B, 0x6D, 0x50, 0x65, 0x5A, 0x71, 0x78, ++ 0x32, 0x70, 0x48, 0x47, 0x6A, 0x37, 0x44, 0x61, 0x55, 0x61, 0x48, 0x70, 0x33, 0x70, 0x4C, 0x48, 0x6E, 0x44, 0x69, 0x2B, 0x42, 0x65, 0x75, 0x4B, 0x31, 0x63, 0x6F, 0x62, 0x76, 0x6F, 0x6D, 0x75, 0x4C, 0x38, 0x41, 0x2F, 0x62, 0x0A, 0x30, 0x31, ++ 0x6B, 0x2F, 0x75, 0x6E, 0x4B, 0x38, 0x52, 0x43, 0x53, 0x63, 0x34, 0x33, 0x4F, 0x7A, 0x39, 0x36, 0x39, 0x58, 0x4C, 0x30, 0x49, 0x6D, 0x6E, 0x61, 0x6C, 0x30, 0x75, 0x67, 0x42, 0x53, 0x38, 0x6B, 0x76, 0x4E, 0x55, 0x33, 0x78, 0x48, 0x43, 0x7A, ++ 0x61, 0x46, 0x44, 0x6D, 0x61, 0x70, 0x43, 0x4A, 0x63, 0x57, 0x4E, 0x46, 0x66, 0x42, 0x5A, 0x76, 0x65, 0x41, 0x34, 0x2B, 0x31, 0x77, 0x56, 0x4D, 0x65, 0x54, 0x34, 0x43, 0x34, 0x6F, 0x46, 0x56, 0x6D, 0x48, 0x0A, 0x75, 0x72, 0x73, 0x43, 0x41, ++ 0x77, 0x45, 0x41, 0x41, 0x61, 0x4F, 0x42, 0x6E, 0x54, 0x43, 0x42, 0x6D, 0x6A, 0x41, 0x54, 0x42, 0x67, 0x6B, 0x72, 0x42, 0x67, 0x45, 0x45, 0x41, 0x59, 0x49, 0x33, 0x46, 0x41, 0x49, 0x45, 0x42, 0x68, 0x34, 0x45, 0x41, 0x45, 0x4D, 0x41, 0x51, ++ 0x54, 0x41, 0x4C, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x45, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x59, 0x59, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x0A, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, ++ 0x2F, 0x7A, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x51, 0x6A, 0x4B, 0x32, 0x46, 0x76, 0x6F, 0x45, 0x2F, 0x66, 0x35, 0x64, 0x53, 0x33, 0x72, 0x44, 0x2F, 0x66, 0x64, 0x4D, 0x51, 0x42, 0x31, 0x61, ++ 0x51, 0x36, 0x38, 0x77, 0x4E, 0x41, 0x59, 0x44, 0x56, 0x52, 0x30, 0x66, 0x42, 0x43, 0x30, 0x77, 0x4B, 0x7A, 0x41, 0x70, 0x6F, 0x43, 0x65, 0x67, 0x4A, 0x59, 0x59, 0x6A, 0x0A, 0x61, 0x48, 0x52, 0x30, 0x63, 0x44, 0x6F, 0x76, 0x4C, 0x32, 0x4E, ++ 0x79, 0x62, 0x43, 0x35, 0x7A, 0x5A, 0x57, 0x4E, 0x31, 0x63, 0x6D, 0x56, 0x30, 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x43, 0x35, 0x6A, 0x62, 0x32, 0x30, 0x76, 0x55, 0x31, 0x52, 0x44, 0x51, 0x53, 0x35, 0x6A, 0x63, 0x6D, 0x77, 0x77, 0x45, 0x41, 0x59, ++ 0x4A, 0x4B, 0x77, 0x59, 0x42, 0x42, 0x41, 0x47, 0x43, 0x4E, 0x78, 0x55, 0x42, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x51, 0x41, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x0A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x46, 0x42, 0x51, ++ 0x41, 0x44, 0x67, 0x67, 0x45, 0x42, 0x41, 0x44, 0x44, 0x74, 0x54, 0x30, 0x72, 0x68, 0x57, 0x44, 0x70, 0x53, 0x63, 0x6C, 0x75, 0x31, 0x70, 0x71, 0x4E, 0x6C, 0x47, 0x4B, 0x61, 0x37, 0x55, 0x54, 0x74, 0x33, 0x36, 0x5A, 0x33, 0x71, 0x30, 0x35, ++ 0x39, 0x63, 0x34, 0x45, 0x56, 0x6C, 0x65, 0x77, 0x33, 0x4B, 0x57, 0x2B, 0x4A, 0x77, 0x55, 0x4C, 0x4B, 0x55, 0x42, 0x52, 0x53, 0x75, 0x0A, 0x53, 0x63, 0x65, 0x4E, 0x51, 0x51, 0x63, 0x53, 0x63, 0x35, 0x52, 0x2B, 0x44, 0x43, 0x4D, 0x68, 0x2F, ++ 0x62, 0x77, 0x51, 0x66, 0x32, 0x41, 0x51, 0x57, 0x6E, 0x4C, 0x31, 0x6D, 0x41, 0x36, 0x73, 0x37, 0x4C, 0x6C, 0x2F, 0x33, 0x58, 0x70, 0x76, 0x58, 0x64, 0x4D, 0x63, 0x39, 0x50, 0x2B, 0x49, 0x42, 0x57, 0x6C, 0x43, 0x71, 0x51, 0x56, 0x78, 0x79, ++ 0x4C, 0x65, 0x73, 0x4A, 0x75, 0x67, 0x75, 0x74, 0x49, 0x78, 0x71, 0x2F, 0x33, 0x48, 0x63, 0x75, 0x4C, 0x48, 0x66, 0x0A, 0x6D, 0x62, 0x78, 0x38, 0x49, 0x56, 0x51, 0x72, 0x35, 0x46, 0x69, 0x69, 0x75, 0x31, 0x63, 0x70, 0x72, 0x70, 0x36, 0x70, ++ 0x6F, 0x78, 0x6B, 0x6D, 0x44, 0x35, 0x6B, 0x75, 0x43, 0x4C, 0x44, 0x76, 0x2F, 0x57, 0x6E, 0x50, 0x6D, 0x52, 0x6F, 0x4A, 0x6A, 0x65, 0x4F, 0x6E, 0x6E, 0x79, 0x76, 0x4A, 0x4E, 0x6A, 0x52, 0x37, 0x4A, 0x4C, 0x4E, 0x34, 0x54, 0x4A, 0x55, 0x58, ++ 0x70, 0x41, 0x59, 0x6D, 0x48, 0x72, 0x5A, 0x6B, 0x55, 0x6A, 0x5A, 0x66, 0x59, 0x47, 0x66, 0x5A, 0x0A, 0x6E, 0x4D, 0x55, 0x46, 0x64, 0x41, 0x76, 0x6E, 0x5A, 0x79, 0x50, 0x53, 0x43, 0x50, 0x79, 0x49, 0x36, 0x61, 0x36, 0x4C, 0x66, 0x2B, 0x45, ++ 0x77, 0x39, 0x44, 0x64, 0x2B, 0x2F, 0x63, 0x59, 0x79, 0x32, 0x69, 0x32, 0x65, 0x52, 0x44, 0x41, 0x77, 0x62, 0x4F, 0x34, 0x48, 0x33, 0x74, 0x49, 0x30, 0x2F, 0x4E, 0x4C, 0x2F, 0x51, 0x50, 0x5A, 0x4C, 0x39, 0x47, 0x5A, 0x47, 0x42, 0x6C, 0x53, ++ 0x6D, 0x38, 0x6A, 0x49, 0x4B, 0x59, 0x79, 0x59, 0x77, 0x61, 0x35, 0x76, 0x52, 0x0A, 0x33, 0x49, 0x74, 0x48, 0x75, 0x75, 0x47, 0x35, 0x31, 0x57, 0x4C, 0x51, 0x6F, 0x71, 0x44, 0x30, 0x5A, 0x77, 0x56, 0x34, 0x4B, 0x57, 0x4D, 0x61, 0x62, 0x77, ++ 0x54, 0x57, 0x2B, 0x4D, 0x5A, 0x4D, 0x6F, 0x35, 0x71, 0x78, 0x4E, 0x37, 0x53, 0x4E, 0x35, 0x53, 0x68, 0x4C, 0x48, 0x5A, 0x34, 0x73, 0x77, 0x72, 0x68, 0x6F, 0x76, 0x4F, 0x30, 0x43, 0x37, 0x6A, 0x45, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, ++ 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x43, 0x41, 0x0A, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, ++ 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x44, 0x76, 0x44, 0x43, 0x43, 0x41, 0x71, 0x53, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x42, 0x31, 0x59, 0x69, 0x70, 0x4F, 0x6A, 0x55, 0x69, 0x6F, 0x6C, 0x4E, 0x39, 0x42, 0x50, 0x49, ++ 0x38, 0x50, 0x6A, 0x71, 0x70, 0x54, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x55, 0x46, 0x41, 0x44, 0x42, 0x4B, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, ++ 0x0A, 0x45, 0x77, 0x4A, 0x56, 0x55, 0x7A, 0x45, 0x67, 0x4D, 0x42, 0x34, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x58, 0x55, 0x32, 0x56, 0x6A, 0x64, 0x58, 0x4A, 0x6C, 0x56, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x51, 0x67, 0x51, 0x32, 0x39, ++ 0x79, 0x63, 0x47, 0x39, 0x79, 0x59, 0x58, 0x52, 0x70, 0x62, 0x32, 0x34, 0x78, 0x47, 0x54, 0x41, 0x58, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x45, 0x46, 0x4E, 0x6C, 0x59, 0x33, 0x56, 0x79, 0x5A, 0x53, 0x42, 0x48, 0x0A, 0x62, 0x47, ++ 0x39, 0x69, 0x59, 0x57, 0x77, 0x67, 0x51, 0x30, 0x45, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x44, 0x59, 0x78, 0x4D, 0x54, 0x41, 0x33, 0x4D, 0x54, 0x6B, 0x30, 0x4D, 0x6A, 0x49, 0x34, 0x57, 0x68, 0x63, 0x4E, 0x4D, 0x6A, 0x6B, 0x78, 0x4D, 0x6A, ++ 0x4D, 0x78, 0x4D, 0x54, 0x6B, 0x31, 0x4D, 0x6A, 0x41, 0x32, 0x57, 0x6A, 0x42, 0x4B, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x56, 0x55, 0x7A, 0x45, 0x67, 0x0A, 0x4D, 0x42, 0x34, 0x47, 0x41, ++ 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x58, 0x55, 0x32, 0x56, 0x6A, 0x64, 0x58, 0x4A, 0x6C, 0x56, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x51, 0x67, 0x51, 0x32, 0x39, 0x79, 0x63, 0x47, 0x39, 0x79, 0x59, 0x58, 0x52, 0x70, 0x62, 0x32, 0x34, 0x78, 0x47, ++ 0x54, 0x41, 0x58, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x45, 0x46, 0x4E, 0x6C, 0x59, 0x33, 0x56, 0x79, 0x5A, 0x53, 0x42, 0x48, 0x62, 0x47, 0x39, 0x69, 0x59, 0x57, 0x77, 0x67, 0x0A, 0x51, 0x30, 0x45, 0x77, 0x67, 0x67, 0x45, 0x69, ++ 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x42, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x45, 0x4B, 0x41, 0x6F, 0x49, 0x42, 0x41, 0x51, 0x43, 0x76, ++ 0x4E, 0x53, 0x37, 0x59, 0x72, 0x47, 0x78, 0x56, 0x61, 0x51, 0x5A, 0x78, 0x35, 0x52, 0x4E, 0x6F, 0x4A, 0x4C, 0x4E, 0x50, 0x32, 0x4D, 0x77, 0x68, 0x52, 0x2F, 0x6A, 0x78, 0x0A, 0x59, 0x44, 0x69, 0x4A, 0x69, 0x51, 0x50, 0x70, 0x76, 0x65, 0x70, ++ 0x65, 0x52, 0x6C, 0x4D, 0x4A, 0x33, 0x46, 0x7A, 0x31, 0x57, 0x75, 0x6A, 0x33, 0x52, 0x53, 0x6F, 0x43, 0x36, 0x7A, 0x46, 0x68, 0x31, 0x79, 0x6B, 0x7A, 0x54, 0x4D, 0x37, 0x48, 0x66, 0x41, 0x6F, 0x33, 0x66, 0x67, 0x2B, 0x36, 0x4D, 0x70, 0x6A, ++ 0x68, 0x48, 0x5A, 0x65, 0x76, 0x6A, 0x38, 0x66, 0x63, 0x79, 0x54, 0x69, 0x57, 0x38, 0x39, 0x73, 0x61, 0x2F, 0x46, 0x48, 0x74, 0x61, 0x4D, 0x62, 0x51, 0x0A, 0x62, 0x71, 0x52, 0x38, 0x4A, 0x4E, 0x47, 0x75, 0x51, 0x73, 0x69, 0x57, 0x55, 0x47, ++ 0x4D, 0x75, 0x34, 0x50, 0x35, 0x31, 0x2F, 0x70, 0x69, 0x6E, 0x58, 0x30, 0x6B, 0x75, 0x6C, 0x65, 0x4D, 0x35, 0x4D, 0x32, 0x53, 0x4F, 0x48, 0x71, 0x52, 0x66, 0x6B, 0x4E, 0x4A, 0x6E, 0x50, 0x4C, 0x4C, 0x5A, 0x2F, 0x6B, 0x47, 0x35, 0x56, 0x61, ++ 0x63, 0x4A, 0x6A, 0x6E, 0x49, 0x46, 0x48, 0x6F, 0x76, 0x64, 0x52, 0x49, 0x57, 0x43, 0x51, 0x74, 0x42, 0x4A, 0x77, 0x42, 0x31, 0x67, 0x0A, 0x38, 0x4E, 0x45, 0x58, 0x4C, 0x4A, 0x58, 0x72, 0x39, 0x71, 0x58, 0x42, 0x6B, 0x71, 0x50, 0x46, 0x77, ++ 0x71, 0x63, 0x49, 0x59, 0x41, 0x31, 0x67, 0x42, 0x42, 0x43, 0x57, 0x65, 0x5A, 0x34, 0x57, 0x4E, 0x4F, 0x61, 0x70, 0x74, 0x76, 0x6F, 0x6C, 0x52, 0x54, 0x6E, 0x49, 0x48, 0x6D, 0x58, 0x35, 0x6B, 0x2F, 0x57, 0x71, 0x38, 0x56, 0x4C, 0x63, 0x6D, ++ 0x5A, 0x67, 0x39, 0x70, 0x59, 0x59, 0x61, 0x44, 0x44, 0x55, 0x7A, 0x2B, 0x6B, 0x75, 0x6C, 0x42, 0x41, 0x59, 0x56, 0x0A, 0x48, 0x44, 0x47, 0x41, 0x37, 0x36, 0x6F, 0x59, 0x61, 0x38, 0x4A, 0x37, 0x31, 0x39, 0x72, 0x4F, 0x2B, 0x54, 0x4D, 0x67, ++ 0x31, 0x66, 0x57, 0x39, 0x61, 0x6A, 0x4D, 0x74, 0x67, 0x51, 0x54, 0x37, 0x73, 0x46, 0x7A, 0x55, 0x6E, 0x4B, 0x50, 0x69, 0x58, 0x42, 0x33, 0x6A, 0x71, 0x55, 0x4A, 0x31, 0x58, 0x6E, 0x76, 0x55, 0x64, 0x2B, 0x38, 0x35, 0x56, 0x4C, 0x72, 0x4A, ++ 0x43, 0x68, 0x67, 0x62, 0x45, 0x70, 0x6C, 0x4A, 0x4C, 0x34, 0x68, 0x4C, 0x2F, 0x56, 0x42, 0x69, 0x0A, 0x30, 0x58, 0x50, 0x6E, 0x6A, 0x33, 0x70, 0x44, 0x41, 0x67, 0x4D, 0x42, 0x41, 0x41, 0x47, 0x6A, 0x67, 0x5A, 0x30, 0x77, 0x67, 0x5A, 0x6F, ++ 0x77, 0x45, 0x77, 0x59, 0x4A, 0x4B, 0x77, 0x59, 0x42, 0x42, 0x41, 0x47, 0x43, 0x4E, 0x78, 0x51, 0x43, 0x42, 0x41, 0x59, 0x65, 0x42, 0x41, 0x42, 0x44, 0x41, 0x45, 0x45, 0x77, 0x43, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x42, 0x41, 0x51, ++ 0x44, 0x41, 0x67, 0x47, 0x47, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x0A, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x48, 0x51, 0x59, 0x44, 0x56, 0x52, 0x30, 0x4F, 0x42, 0x42, ++ 0x59, 0x45, 0x46, 0x4B, 0x39, 0x45, 0x42, 0x4D, 0x4A, 0x42, 0x66, 0x6B, 0x69, 0x44, 0x32, 0x30, 0x34, 0x35, 0x41, 0x75, 0x7A, 0x73, 0x68, 0x48, 0x72, 0x6D, 0x7A, 0x73, 0x6D, 0x6B, 0x4D, 0x44, 0x51, 0x47, 0x41, 0x31, 0x55, 0x64, 0x48, 0x77, ++ 0x51, 0x74, 0x4D, 0x43, 0x73, 0x77, 0x4B, 0x61, 0x41, 0x6E, 0x0A, 0x6F, 0x43, 0x57, 0x47, 0x49, 0x32, 0x68, 0x30, 0x64, 0x48, 0x41, 0x36, 0x4C, 0x79, 0x39, 0x6A, 0x63, 0x6D, 0x77, 0x75, 0x63, 0x32, 0x56, 0x6A, 0x64, 0x58, 0x4A, 0x6C, 0x64, ++ 0x48, 0x4A, 0x31, 0x63, 0x33, 0x51, 0x75, 0x59, 0x32, 0x39, 0x74, 0x4C, 0x31, 0x4E, 0x48, 0x51, 0x30, 0x45, 0x75, 0x59, 0x33, 0x4A, 0x73, 0x4D, 0x42, 0x41, 0x47, 0x43, 0x53, 0x73, 0x47, 0x41, 0x51, 0x51, 0x42, 0x67, 0x6A, 0x63, 0x56, 0x41, ++ 0x51, 0x51, 0x44, 0x41, 0x67, 0x45, 0x41, 0x0A, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x42, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x42, 0x41, 0x51, 0x42, 0x6A, 0x47, 0x67, 0x68, 0x41, ++ 0x66, 0x61, 0x52, 0x65, 0x55, 0x77, 0x31, 0x33, 0x32, 0x48, 0x71, 0x75, 0x48, 0x77, 0x30, 0x4C, 0x55, 0x52, 0x59, 0x44, 0x37, 0x78, 0x68, 0x38, 0x79, 0x4F, 0x4F, 0x76, 0x61, 0x6C, 0x69, 0x54, 0x46, 0x47, 0x43, 0x52, 0x73, 0x6F, 0x54, 0x63, ++ 0x69, 0x45, 0x36, 0x2B, 0x0A, 0x4F, 0x59, 0x6F, 0x36, 0x38, 0x2B, 0x61, 0x43, 0x69, 0x56, 0x30, 0x42, 0x4E, 0x37, 0x4F, 0x72, 0x4A, 0x4B, 0x51, 0x56, 0x44, 0x70, 0x49, 0x31, 0x57, 0x6B, 0x70, 0x45, 0x58, 0x6B, 0x35, 0x58, 0x2B, 0x6E, 0x58, ++ 0x4F, 0x48, 0x30, 0x6A, 0x4F, 0x5A, 0x76, 0x51, 0x38, 0x51, 0x43, 0x61, 0x53, 0x6D, 0x47, 0x77, 0x62, 0x37, 0x69, 0x52, 0x47, 0x44, 0x42, 0x65, 0x7A, 0x55, 0x71, 0x58, 0x62, 0x70, 0x5A, 0x47, 0x52, 0x7A, 0x7A, 0x66, 0x54, 0x62, 0x2B, 0x63, ++ 0x6E, 0x0A, 0x43, 0x44, 0x70, 0x4F, 0x47, 0x52, 0x38, 0x36, 0x70, 0x31, 0x68, 0x63, 0x46, 0x38, 0x39, 0x35, 0x50, 0x34, 0x76, 0x6B, 0x70, 0x39, 0x4D, 0x6D, 0x49, 0x35, 0x30, 0x6D, 0x44, 0x31, 0x68, 0x70, 0x2F, 0x45, 0x64, 0x2B, 0x73, 0x74, ++ 0x43, 0x4E, 0x69, 0x35, 0x4F, 0x2F, 0x4B, 0x55, 0x39, 0x44, 0x61, 0x58, 0x52, 0x32, 0x5A, 0x30, 0x76, 0x50, 0x42, 0x34, 0x7A, 0x6D, 0x41, 0x76, 0x65, 0x31, 0x34, 0x62, 0x52, 0x44, 0x74, 0x55, 0x73, 0x74, 0x46, 0x4A, 0x2F, 0x35, 0x0A, 0x33, ++ 0x43, 0x59, 0x4E, 0x76, 0x36, 0x5A, 0x48, 0x64, 0x41, 0x62, 0x59, 0x69, 0x4E, 0x45, 0x36, 0x4B, 0x54, 0x43, 0x45, 0x7A, 0x74, 0x49, 0x35, 0x67, 0x47, 0x49, 0x62, 0x71, 0x4D, 0x64, 0x58, 0x53, 0x62, 0x78, 0x71, 0x56, 0x56, 0x46, 0x6E, 0x46, ++ 0x55, 0x71, 0x2B, 0x4E, 0x51, 0x66, 0x6B, 0x31, 0x58, 0x57, 0x59, 0x4E, 0x33, 0x6B, 0x77, 0x46, 0x4E, 0x73, 0x70, 0x6E, 0x57, 0x7A, 0x46, 0x61, 0x63, 0x78, 0x48, 0x56, 0x61, 0x49, 0x77, 0x39, 0x38, 0x78, 0x63, 0x0A, 0x66, 0x38, 0x4C, 0x44, ++ 0x6D, 0x42, 0x78, 0x72, 0x54, 0x68, 0x61, 0x41, 0x36, 0x33, 0x70, 0x34, 0x5A, 0x55, 0x57, 0x69, 0x41, 0x42, 0x71, 0x76, 0x44, 0x41, 0x31, 0x56, 0x5A, 0x44, 0x52, 0x49, 0x75, 0x4A, 0x4B, 0x35, 0x38, 0x62, 0x52, 0x51, 0x4B, 0x66, 0x4A, 0x50, ++ 0x49, 0x78, 0x2F, 0x61, 0x62, 0x4B, 0x77, 0x66, 0x52, 0x4F, 0x48, 0x64, 0x49, 0x33, 0x68, 0x52, 0x57, 0x38, 0x63, 0x57, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, ++ 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x0A, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, ++ 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x45, 0x48, 0x54, 0x43, 0x43, 0x41, 0x77, 0x57, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x54, 0x6F, ++ 0x45, 0x74, 0x69, 0x6F, 0x4A, 0x6C, 0x34, 0x41, 0x73, 0x43, 0x37, 0x6A, 0x34, 0x31, 0x41, 0x6B, 0x62, 0x6C, 0x50, 0x54, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x55, 0x46, 0x41, 0x44, ++ 0x43, 0x42, 0x67, 0x54, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x0A, 0x42, 0x68, 0x4D, 0x43, 0x52, 0x30, 0x49, 0x78, 0x47, 0x7A, 0x41, 0x5A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x67, 0x54, 0x45, 0x6B, 0x64, 0x79, 0x5A, ++ 0x57, 0x46, 0x30, 0x5A, 0x58, 0x49, 0x67, 0x54, 0x57, 0x46, 0x75, 0x59, 0x32, 0x68, 0x6C, 0x63, 0x33, 0x52, 0x6C, 0x63, 0x6A, 0x45, 0x51, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x78, 0x4D, 0x48, 0x55, 0x32, 0x46, 0x73, 0x5A, ++ 0x6D, 0x39, 0x79, 0x5A, 0x44, 0x45, 0x61, 0x4D, 0x42, 0x67, 0x47, 0x0A, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x52, 0x51, 0x30, 0x39, 0x4E, 0x54, 0x30, 0x52, 0x50, 0x49, 0x45, 0x4E, 0x42, 0x49, 0x45, 0x78, 0x70, 0x62, 0x57, 0x6C, 0x30, ++ 0x5A, 0x57, 0x51, 0x78, 0x4A, 0x7A, 0x41, 0x6C, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x48, 0x6B, 0x4E, 0x50, 0x54, 0x55, 0x39, 0x45, 0x54, 0x79, 0x42, 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x61, 0x57, 0x5A, 0x70, 0x59, 0x32, 0x46, 0x30, ++ 0x61, 0x57, 0x39, 0x75, 0x49, 0x45, 0x46, 0x31, 0x0A, 0x64, 0x47, 0x68, 0x76, 0x63, 0x6D, 0x6C, 0x30, 0x65, 0x54, 0x41, 0x65, 0x46, 0x77, 0x30, 0x77, 0x4E, 0x6A, 0x45, 0x79, 0x4D, 0x44, 0x45, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x44, 0x42, ++ 0x61, 0x46, 0x77, 0x30, 0x79, 0x4F, 0x54, 0x45, 0x79, 0x4D, 0x7A, 0x45, 0x79, 0x4D, 0x7A, 0x55, 0x35, 0x4E, 0x54, 0x6C, 0x61, 0x4D, 0x49, 0x47, 0x42, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, ++ 0x48, 0x51, 0x6A, 0x45, 0x62, 0x0A, 0x4D, 0x42, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x42, 0x4D, 0x53, 0x52, 0x33, 0x4A, 0x6C, 0x59, 0x58, 0x52, 0x6C, 0x63, 0x69, 0x42, 0x4E, 0x59, 0x57, 0x35, 0x6A, 0x61, 0x47, 0x56, 0x7A, 0x64, 0x47, ++ 0x56, 0x79, 0x4D, 0x52, 0x41, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x48, 0x45, 0x77, 0x64, 0x54, 0x59, 0x57, 0x78, 0x6D, 0x62, 0x33, 0x4A, 0x6B, 0x4D, 0x52, 0x6F, 0x77, 0x47, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x45, 0x78, ++ 0x46, 0x44, 0x0A, 0x54, 0x30, 0x31, 0x50, 0x52, 0x45, 0x38, 0x67, 0x51, 0x30, 0x45, 0x67, 0x54, 0x47, 0x6C, 0x74, 0x61, 0x58, 0x52, 0x6C, 0x5A, 0x44, 0x45, 0x6E, 0x4D, 0x43, 0x55, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x65, 0x51, ++ 0x30, 0x39, 0x4E, 0x54, 0x30, 0x52, 0x50, 0x49, 0x45, 0x4E, 0x6C, 0x63, 0x6E, 0x52, 0x70, 0x5A, 0x6D, 0x6C, 0x6A, 0x59, 0x58, 0x52, 0x70, 0x62, 0x32, 0x34, 0x67, 0x51, 0x58, 0x56, 0x30, 0x61, 0x47, 0x39, 0x79, 0x61, 0x58, 0x52, 0x35, 0x0A, ++ 0x4D, 0x49, 0x49, 0x42, 0x49, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x45, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x51, 0x38, 0x41, 0x4D, 0x49, 0x49, 0x42, 0x43, 0x67, 0x4B, 0x43, ++ 0x41, 0x51, 0x45, 0x41, 0x30, 0x45, 0x43, 0x4C, 0x69, 0x33, 0x4C, 0x6A, 0x6B, 0x52, 0x76, 0x33, 0x55, 0x63, 0x45, 0x62, 0x56, 0x41, 0x53, 0x59, 0x30, 0x36, 0x6D, 0x2F, 0x77, 0x65, 0x61, 0x4B, 0x58, 0x54, 0x75, 0x48, 0x0A, 0x2B, 0x37, 0x75, ++ 0x49, 0x7A, 0x67, 0x33, 0x6A, 0x4C, 0x7A, 0x38, 0x47, 0x6C, 0x76, 0x43, 0x69, 0x4B, 0x56, 0x43, 0x5A, 0x72, 0x74, 0x73, 0x37, 0x6F, 0x56, 0x65, 0x77, 0x64, 0x46, 0x46, 0x78, 0x7A, 0x65, 0x31, 0x43, 0x6B, 0x55, 0x31, 0x42, 0x2F, 0x71, 0x6E, ++ 0x49, 0x32, 0x47, 0x71, 0x47, 0x64, 0x30, 0x53, 0x37, 0x57, 0x57, 0x61, 0x58, 0x55, 0x46, 0x36, 0x30, 0x31, 0x43, 0x78, 0x77, 0x52, 0x4D, 0x2F, 0x61, 0x4E, 0x35, 0x56, 0x43, 0x61, 0x54, 0x77, 0x77, 0x0A, 0x78, 0x48, 0x47, 0x7A, 0x55, 0x76, ++ 0x41, 0x68, 0x54, 0x61, 0x48, 0x59, 0x75, 0x6A, 0x6C, 0x38, 0x48, 0x4A, 0x36, 0x6A, 0x4A, 0x4A, 0x33, 0x79, 0x67, 0x78, 0x61, 0x59, 0x71, 0x68, 0x5A, 0x38, 0x51, 0x35, 0x73, 0x56, 0x57, 0x37, 0x65, 0x75, 0x4E, 0x4A, 0x48, 0x2B, 0x31, 0x47, ++ 0x49, 0x6D, 0x47, 0x45, 0x61, 0x61, 0x50, 0x2B, 0x76, 0x42, 0x2B, 0x66, 0x47, 0x51, 0x56, 0x2B, 0x75, 0x73, 0x65, 0x67, 0x32, 0x4C, 0x32, 0x33, 0x49, 0x77, 0x61, 0x6D, 0x62, 0x56, 0x0A, 0x34, 0x45, 0x61, 0x6A, 0x63, 0x4E, 0x78, 0x6F, 0x32, ++ 0x66, 0x38, 0x45, 0x53, 0x49, 0x6C, 0x33, 0x33, 0x72, 0x58, 0x70, 0x2B, 0x32, 0x64, 0x74, 0x51, 0x65, 0x6D, 0x38, 0x4F, 0x62, 0x30, 0x79, 0x32, 0x57, 0x49, 0x43, 0x38, 0x62, 0x47, 0x6F, 0x50, 0x57, 0x34, 0x33, 0x6E, 0x4F, 0x49, 0x76, 0x34, ++ 0x74, 0x4F, 0x69, 0x4A, 0x6F, 0x76, 0x47, 0x75, 0x46, 0x56, 0x44, 0x69, 0x4F, 0x45, 0x6A, 0x50, 0x71, 0x58, 0x53, 0x4A, 0x44, 0x6C, 0x71, 0x52, 0x36, 0x73, 0x41, 0x0A, 0x31, 0x4B, 0x47, 0x7A, 0x71, 0x53, 0x58, 0x2B, 0x44, 0x54, 0x2B, 0x6E, ++ 0x48, 0x62, 0x72, 0x54, 0x55, 0x63, 0x45, 0x4C, 0x70, 0x4E, 0x71, 0x73, 0x4F, 0x4F, 0x39, 0x56, 0x55, 0x43, 0x51, 0x46, 0x5A, 0x55, 0x61, 0x54, 0x4E, 0x45, 0x38, 0x74, 0x6A, 0x61, 0x33, 0x47, 0x31, 0x43, 0x45, 0x5A, 0x30, 0x6F, 0x37, 0x4B, ++ 0x42, 0x57, 0x46, 0x78, 0x42, 0x33, 0x4E, 0x48, 0x35, 0x59, 0x6F, 0x5A, 0x45, 0x72, 0x30, 0x45, 0x54, 0x63, 0x35, 0x4F, 0x6E, 0x4B, 0x56, 0x49, 0x0A, 0x72, 0x4C, 0x73, 0x6D, 0x39, 0x77, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x6F, 0x34, 0x47, ++ 0x4F, 0x4D, 0x49, 0x47, 0x4C, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x51, 0x4C, 0x57, 0x4F, 0x57, 0x4C, 0x78, 0x6B, 0x77, 0x56, 0x4E, 0x36, 0x52, 0x41, 0x71, 0x54, 0x43, 0x70, 0x49, 0x62, 0x35, ++ 0x48, 0x4E, 0x6C, 0x70, 0x57, 0x2F, 0x7A, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x42, 0x41, 0x66, 0x38, 0x45, 0x0A, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x51, 0x59, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, ++ 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x42, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x52, 0x38, 0x45, 0x51, 0x6A, 0x42, 0x41, 0x4D, 0x44, 0x36, 0x67, 0x50, 0x4B, 0x41, 0x36, 0x68, 0x6A, 0x68, 0x6F, 0x64, 0x48, ++ 0x52, 0x77, 0x4F, 0x69, 0x38, 0x76, 0x59, 0x33, 0x4A, 0x73, 0x4C, 0x6D, 0x4E, 0x76, 0x62, 0x57, 0x39, 0x6B, 0x0A, 0x62, 0x32, 0x4E, 0x68, 0x4C, 0x6D, 0x4E, 0x76, 0x62, 0x53, 0x39, 0x44, 0x54, 0x30, 0x31, 0x50, 0x52, 0x45, 0x39, 0x44, 0x5A, ++ 0x58, 0x4A, 0x30, 0x61, 0x57, 0x5A, 0x70, 0x59, 0x32, 0x46, 0x30, 0x61, 0x57, 0x39, 0x75, 0x51, 0x58, 0x56, 0x30, 0x61, 0x47, 0x39, 0x79, 0x61, 0x58, 0x52, 0x35, 0x4C, 0x6D, 0x4E, 0x79, 0x62, 0x44, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, ++ 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x55, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x0A, 0x41, 0x51, 0x45, 0x41, 0x50, 0x70, 0x69, 0x65, 0x6D, 0x2F, 0x59, 0x62, 0x36, 0x64, 0x63, 0x35, 0x74, 0x33, 0x69, 0x75, 0x48, 0x58, 0x49, 0x59, ++ 0x53, 0x64, 0x4F, 0x48, 0x35, 0x45, 0x4F, 0x43, 0x36, 0x7A, 0x2F, 0x4A, 0x71, 0x76, 0x57, 0x6F, 0x74, 0x65, 0x39, 0x56, 0x66, 0x43, 0x46, 0x53, 0x5A, 0x66, 0x6E, 0x56, 0x44, 0x65, 0x46, 0x73, 0x39, 0x44, 0x36, 0x4D, 0x6B, 0x33, 0x4F, 0x52, ++ 0x4C, 0x67, 0x4C, 0x45, 0x54, 0x67, 0x64, 0x78, 0x62, 0x38, 0x43, 0x50, 0x0A, 0x4F, 0x47, 0x45, 0x49, 0x71, 0x42, 0x36, 0x42, 0x43, 0x73, 0x41, 0x76, 0x49, 0x43, 0x39, 0x42, 0x69, 0x35, 0x48, 0x63, 0x53, 0x45, 0x57, 0x38, 0x38, 0x63, 0x62, ++ 0x65, 0x75, 0x6E, 0x5A, 0x72, 0x4D, 0x38, 0x67, 0x41, 0x4C, 0x54, 0x46, 0x47, 0x54, 0x4F, 0x33, 0x6E, 0x6E, 0x63, 0x2B, 0x49, 0x6C, 0x50, 0x38, 0x7A, 0x77, 0x46, 0x62, 0x6F, 0x4A, 0x49, 0x59, 0x6D, 0x75, 0x4E, 0x67, 0x34, 0x4F, 0x4E, 0x38, ++ 0x71, 0x61, 0x39, 0x30, 0x53, 0x7A, 0x4D, 0x63, 0x2F, 0x0A, 0x52, 0x78, 0x64, 0x4D, 0x6F, 0x73, 0x49, 0x47, 0x6C, 0x67, 0x6E, 0x57, 0x32, 0x2F, 0x34, 0x2F, 0x50, 0x45, 0x5A, 0x42, 0x33, 0x31, 0x6A, 0x69, 0x56, 0x67, 0x38, 0x38, 0x4F, 0x38, ++ 0x45, 0x63, 0x6B, 0x7A, 0x58, 0x5A, 0x4F, 0x46, 0x4B, 0x73, 0x37, 0x73, 0x6A, 0x73, 0x4C, 0x6A, 0x42, 0x4F, 0x6C, 0x44, 0x57, 0x30, 0x4A, 0x42, 0x39, 0x4C, 0x65, 0x47, 0x6E, 0x61, 0x38, 0x67, 0x49, 0x34, 0x7A, 0x4A, 0x56, 0x53, 0x6B, 0x2F, ++ 0x42, 0x77, 0x4A, 0x56, 0x6D, 0x63, 0x0A, 0x49, 0x47, 0x66, 0x45, 0x37, 0x76, 0x6D, 0x4C, 0x56, 0x32, 0x48, 0x30, 0x6B, 0x6E, 0x5A, 0x39, 0x50, 0x34, 0x53, 0x4E, 0x56, 0x62, 0x66, 0x6F, 0x35, 0x61, 0x7A, 0x56, 0x38, 0x66, 0x55, 0x5A, 0x56, ++ 0x71, 0x5A, 0x61, 0x2B, 0x35, 0x41, 0x63, 0x72, 0x35, 0x50, 0x72, 0x35, 0x52, 0x7A, 0x55, 0x5A, 0x35, 0x64, 0x64, 0x42, 0x41, 0x36, 0x2B, 0x43, 0x34, 0x4F, 0x6D, 0x46, 0x34, 0x4F, 0x35, 0x4D, 0x42, 0x4B, 0x67, 0x78, 0x54, 0x4D, 0x56, 0x42, ++ 0x62, 0x6B, 0x4E, 0x0A, 0x2B, 0x38, 0x63, 0x46, 0x64, 0x75, 0x50, 0x59, 0x53, 0x6F, 0x33, 0x38, 0x4E, 0x42, 0x65, 0x6A, 0x78, 0x69, 0x45, 0x6F, 0x76, 0x6A, 0x42, 0x46, 0x4D, 0x52, 0x37, 0x48, 0x65, 0x4C, 0x35, 0x59, 0x59, 0x54, 0x69, 0x73, ++ 0x4F, 0x2B, 0x49, 0x42, 0x5A, 0x51, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x43, 0x4F, 0x4D, 0x4F, ++ 0x44, 0x4F, 0x20, 0x45, 0x43, 0x43, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, ++ 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x43, 0x69, 0x54, 0x43, 0x43, 0x41, 0x67, 0x2B, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x48, 0x30, 0x65, 0x76, 0x71, 0x6D, ++ 0x49, 0x41, 0x63, 0x46, 0x42, 0x55, 0x54, 0x41, 0x47, 0x65, 0x6D, 0x32, 0x4F, 0x5A, 0x4B, 0x6A, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x7A, 0x43, 0x42, 0x68, 0x54, 0x45, 0x4C, 0x4D, 0x41, ++ 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x0A, 0x52, 0x30, 0x49, 0x78, 0x47, 0x7A, 0x41, 0x5A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x67, 0x54, 0x45, 0x6B, 0x64, 0x79, 0x5A, 0x57, 0x46, 0x30, 0x5A, 0x58, 0x49, 0x67, 0x54, ++ 0x57, 0x46, 0x75, 0x59, 0x32, 0x68, 0x6C, 0x63, 0x33, 0x52, 0x6C, 0x63, 0x6A, 0x45, 0x51, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x78, 0x4D, 0x48, 0x55, 0x32, 0x46, 0x73, 0x5A, 0x6D, 0x39, 0x79, 0x5A, 0x44, 0x45, 0x61, 0x4D, ++ 0x42, 0x67, 0x47, 0x41, 0x31, 0x55, 0x45, 0x0A, 0x43, 0x68, 0x4D, 0x52, 0x51, 0x30, 0x39, 0x4E, 0x54, 0x30, 0x52, 0x50, 0x49, 0x45, 0x4E, 0x42, 0x49, 0x45, 0x78, 0x70, 0x62, 0x57, 0x6C, 0x30, 0x5A, 0x57, 0x51, 0x78, 0x4B, 0x7A, 0x41, 0x70, ++ 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x49, 0x6B, 0x4E, 0x50, 0x54, 0x55, 0x39, 0x45, 0x54, 0x79, 0x42, 0x46, 0x51, 0x30, 0x4D, 0x67, 0x51, 0x32, 0x56, 0x79, 0x64, 0x47, 0x6C, 0x6D, 0x61, 0x57, 0x4E, 0x68, 0x64, 0x47, 0x6C, 0x76, ++ 0x62, 0x69, 0x42, 0x42, 0x0A, 0x64, 0x58, 0x52, 0x6F, 0x62, 0x33, 0x4A, 0x70, 0x64, 0x48, 0x6B, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x44, 0x67, 0x77, 0x4D, 0x7A, 0x41, 0x32, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x57, 0x68, 0x63, ++ 0x4E, 0x4D, 0x7A, 0x67, 0x77, 0x4D, 0x54, 0x45, 0x34, 0x4D, 0x6A, 0x4D, 0x31, 0x4F, 0x54, 0x55, 0x35, 0x57, 0x6A, 0x43, 0x42, 0x68, 0x54, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x52, 0x30, 0x49, ++ 0x78, 0x0A, 0x47, 0x7A, 0x41, 0x5A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x67, 0x54, 0x45, 0x6B, 0x64, 0x79, 0x5A, 0x57, 0x46, 0x30, 0x5A, 0x58, 0x49, 0x67, 0x54, 0x57, 0x46, 0x75, 0x59, 0x32, 0x68, 0x6C, 0x63, 0x33, 0x52, 0x6C, 0x63, 0x6A, ++ 0x45, 0x51, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x78, 0x4D, 0x48, 0x55, 0x32, 0x46, 0x73, 0x5A, 0x6D, 0x39, 0x79, 0x5A, 0x44, 0x45, 0x61, 0x4D, 0x42, 0x67, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x52, 0x0A, 0x51, ++ 0x30, 0x39, 0x4E, 0x54, 0x30, 0x52, 0x50, 0x49, 0x45, 0x4E, 0x42, 0x49, 0x45, 0x78, 0x70, 0x62, 0x57, 0x6C, 0x30, 0x5A, 0x57, 0x51, 0x78, 0x4B, 0x7A, 0x41, 0x70, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x49, 0x6B, 0x4E, 0x50, 0x54, ++ 0x55, 0x39, 0x45, 0x54, 0x79, 0x42, 0x46, 0x51, 0x30, 0x4D, 0x67, 0x51, 0x32, 0x56, 0x79, 0x64, 0x47, 0x6C, 0x6D, 0x61, 0x57, 0x4E, 0x68, 0x64, 0x47, 0x6C, 0x76, 0x62, 0x69, 0x42, 0x42, 0x64, 0x58, 0x52, 0x6F, 0x0A, 0x62, 0x33, 0x4A, 0x70, ++ 0x64, 0x48, 0x6B, 0x77, 0x64, 0x6A, 0x41, 0x51, 0x42, 0x67, 0x63, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x49, 0x42, 0x42, 0x67, 0x55, 0x72, 0x67, 0x51, 0x51, 0x41, 0x49, 0x67, 0x4E, 0x69, 0x41, 0x41, 0x51, 0x44, 0x52, 0x33, 0x73, 0x76, ++ 0x64, 0x63, 0x6D, 0x43, 0x46, 0x59, 0x58, 0x37, 0x64, 0x65, 0x53, 0x52, 0x46, 0x74, 0x53, 0x72, 0x59, 0x70, 0x6E, 0x31, 0x50, 0x6C, 0x49, 0x4C, 0x42, 0x73, 0x35, 0x42, 0x41, 0x48, 0x2B, 0x58, 0x0A, 0x34, 0x51, 0x6F, 0x6B, 0x50, 0x42, 0x30, ++ 0x42, 0x42, 0x4F, 0x34, 0x39, 0x30, 0x6F, 0x30, 0x4A, 0x6C, 0x77, 0x7A, 0x67, 0x64, 0x65, 0x54, 0x36, 0x2B, 0x33, 0x65, 0x4B, 0x4B, 0x76, 0x55, 0x44, 0x59, 0x45, 0x73, 0x32, 0x69, 0x78, 0x59, 0x6A, 0x46, 0x71, 0x30, 0x4A, 0x63, 0x66, 0x52, ++ 0x4B, 0x39, 0x43, 0x68, 0x51, 0x74, 0x50, 0x36, 0x49, 0x48, 0x47, 0x34, 0x2F, 0x62, 0x43, 0x38, 0x76, 0x43, 0x56, 0x6C, 0x62, 0x70, 0x56, 0x73, 0x4C, 0x4D, 0x35, 0x6E, 0x69, 0x0A, 0x77, 0x7A, 0x32, 0x4A, 0x2B, 0x57, 0x6F, 0x73, 0x37, 0x37, ++ 0x4C, 0x54, 0x42, 0x75, 0x6D, 0x6A, 0x51, 0x6A, 0x42, 0x41, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x52, 0x31, 0x63, 0x61, 0x63, 0x5A, 0x53, 0x42, 0x6D, 0x38, 0x6E, 0x5A, 0x33, 0x71, 0x51, 0x55, ++ 0x66, 0x66, 0x6C, 0x4D, 0x52, 0x49, 0x64, 0x35, 0x6E, 0x54, 0x65, 0x54, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x42, 0x41, 0x66, 0x38, 0x45, 0x0A, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x51, 0x59, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, ++ 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x77, 0x4E, 0x6F, 0x41, 0x44, 0x42, 0x6C, 0x41, ++ 0x6A, 0x45, 0x41, 0x37, 0x77, 0x4E, 0x62, 0x65, 0x71, 0x79, 0x33, 0x65, 0x41, 0x70, 0x79, 0x74, 0x34, 0x6A, 0x66, 0x2F, 0x37, 0x56, 0x47, 0x0A, 0x46, 0x41, 0x6B, 0x4B, 0x2B, 0x71, 0x44, 0x6D, 0x66, 0x51, 0x6A, 0x47, 0x47, 0x6F, 0x65, 0x39, ++ 0x47, 0x4B, 0x68, 0x7A, 0x76, 0x53, 0x62, 0x4B, 0x59, 0x41, 0x79, 0x64, 0x7A, 0x70, 0x6D, 0x66, 0x7A, 0x31, 0x77, 0x50, 0x4D, 0x4F, 0x47, 0x2B, 0x46, 0x44, 0x48, 0x71, 0x41, 0x6A, 0x41, 0x55, 0x39, 0x4A, 0x4D, 0x38, 0x53, 0x61, 0x63, 0x7A, ++ 0x65, 0x70, 0x42, 0x47, 0x52, 0x37, 0x4E, 0x6A, 0x66, 0x52, 0x4F, 0x62, 0x54, 0x72, 0x64, 0x76, 0x47, 0x44, 0x65, 0x41, 0x0A, 0x55, 0x2F, 0x37, 0x64, 0x49, 0x4F, 0x41, 0x31, 0x6D, 0x6A, 0x62, 0x52, 0x78, 0x77, 0x47, 0x35, 0x35, 0x74, 0x7A, ++ 0x64, 0x38, 0x2F, 0x38, 0x64, 0x4C, 0x44, 0x6F, 0x57, 0x56, 0x39, 0x6D, 0x53, 0x4F, 0x64, 0x59, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, ++ 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x43, 0x65, 0x72, 0x74, 0x69, 0x67, 0x6E, 0x61, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, ++ 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x44, 0x71, 0x44, 0x43, 0x43, 0x41, 0x70, 0x43, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x4A, 0x41, 0x50, 0x37, 0x63, 0x34, 0x77, 0x45, 0x50, 0x79, ++ 0x55, 0x6A, 0x2F, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x42, 0x51, 0x55, 0x41, 0x4D, 0x44, 0x51, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, ++ 0x6B, 0x5A, 0x53, 0x4D, 0x52, 0x49, 0x77, 0x0A, 0x45, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x44, 0x41, 0x6C, 0x45, 0x61, 0x47, 0x6C, 0x74, 0x65, 0x57, 0x39, 0x30, 0x61, 0x58, 0x4D, 0x78, 0x45, 0x54, 0x41, 0x50, 0x42, 0x67, 0x4E, 0x56, ++ 0x42, 0x41, 0x4D, 0x4D, 0x43, 0x45, 0x4E, 0x6C, 0x63, 0x6E, 0x52, 0x70, 0x5A, 0x32, 0x35, 0x68, 0x4D, 0x42, 0x34, 0x58, 0x44, 0x54, 0x41, 0x33, 0x4D, 0x44, 0x59, 0x79, 0x4F, 0x54, 0x45, 0x31, 0x4D, 0x54, 0x4D, 0x77, 0x4E, 0x56, 0x6F, 0x58, ++ 0x44, 0x54, 0x49, 0x33, 0x0A, 0x4D, 0x44, 0x59, 0x79, 0x4F, 0x54, 0x45, 0x31, 0x4D, 0x54, 0x4D, 0x77, 0x4E, 0x56, 0x6F, 0x77, 0x4E, 0x44, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x52, 0x6C, 0x49, ++ 0x78, 0x45, 0x6A, 0x41, 0x51, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x4D, 0x43, 0x55, 0x52, 0x6F, 0x61, 0x57, 0x31, 0x35, 0x62, 0x33, 0x52, 0x70, 0x63, 0x7A, 0x45, 0x52, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x77, 0x77, ++ 0x49, 0x0A, 0x51, 0x32, 0x56, 0x79, 0x64, 0x47, 0x6C, 0x6E, 0x62, 0x6D, 0x45, 0x77, 0x67, 0x67, 0x45, 0x69, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, ++ 0x49, 0x42, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x45, 0x4B, 0x41, 0x6F, 0x49, 0x42, 0x41, 0x51, 0x44, 0x49, 0x61, 0x50, 0x48, 0x4A, 0x31, 0x74, 0x61, 0x7A, 0x4E, 0x48, 0x55, 0x6D, 0x67, 0x68, 0x37, 0x73, 0x74, 0x4C, 0x37, 0x71, 0x0A, 0x58, ++ 0x4F, 0x45, 0x6D, 0x37, 0x52, 0x46, 0x48, 0x59, 0x65, 0x47, 0x69, 0x66, 0x42, 0x5A, 0x34, 0x51, 0x43, 0x48, 0x6B, 0x59, 0x4A, 0x35, 0x61, 0x79, 0x47, 0x50, 0x68, 0x78, 0x4C, 0x47, 0x57, 0x6B, 0x76, 0x38, 0x59, 0x62, 0x57, 0x6B, 0x6A, 0x34, ++ 0x53, 0x74, 0x69, 0x39, 0x39, 0x33, 0x69, 0x4E, 0x69, 0x2B, 0x52, 0x42, 0x37, 0x6C, 0x49, 0x7A, 0x77, 0x37, 0x73, 0x65, 0x62, 0x59, 0x73, 0x35, 0x7A, 0x52, 0x4C, 0x63, 0x41, 0x67, 0x6C, 0x6F, 0x7A, 0x79, 0x48, 0x0A, 0x47, 0x78, 0x6E, 0x79, ++ 0x67, 0x51, 0x63, 0x50, 0x4F, 0x4A, 0x41, 0x5A, 0x30, 0x78, 0x48, 0x2B, 0x68, 0x72, 0x54, 0x79, 0x30, 0x56, 0x34, 0x65, 0x48, 0x70, 0x62, 0x4E, 0x67, 0x47, 0x7A, 0x4F, 0x4F, 0x7A, 0x47, 0x54, 0x74, 0x76, 0x4B, 0x67, 0x30, 0x4B, 0x6D, 0x56, ++ 0x45, 0x6E, 0x32, 0x6C, 0x6D, 0x73, 0x78, 0x72, 0x79, 0x49, 0x52, 0x57, 0x69, 0x6A, 0x4F, 0x70, 0x35, 0x79, 0x49, 0x56, 0x55, 0x78, 0x62, 0x77, 0x7A, 0x42, 0x66, 0x73, 0x56, 0x31, 0x2F, 0x70, 0x0A, 0x6F, 0x67, 0x71, 0x59, 0x43, 0x64, 0x37, ++ 0x6A, 0x58, 0x35, 0x78, 0x76, 0x33, 0x45, 0x6A, 0x6A, 0x68, 0x51, 0x73, 0x56, 0x57, 0x71, 0x61, 0x36, 0x6E, 0x36, 0x78, 0x49, 0x34, 0x77, 0x6D, 0x79, 0x39, 0x2F, 0x51, 0x79, 0x33, 0x6C, 0x34, 0x30, 0x76, 0x68, 0x78, 0x34, 0x58, 0x55, 0x4A, ++ 0x62, 0x7A, 0x67, 0x34, 0x69, 0x6A, 0x30, 0x32, 0x51, 0x31, 0x33, 0x30, 0x79, 0x47, 0x4C, 0x4D, 0x4C, 0x4C, 0x47, 0x71, 0x2F, 0x6A, 0x6A, 0x38, 0x55, 0x45, 0x59, 0x6B, 0x67, 0x0A, 0x44, 0x6E, 0x63, 0x55, 0x74, 0x54, 0x32, 0x55, 0x43, 0x49, ++ 0x66, 0x33, 0x4A, 0x52, 0x37, 0x56, 0x73, 0x6D, 0x41, 0x41, 0x37, 0x47, 0x38, 0x71, 0x4B, 0x43, 0x56, 0x75, 0x4B, 0x6A, 0x34, 0x59, 0x59, 0x78, 0x63, 0x6C, 0x50, 0x7A, 0x35, 0x45, 0x49, 0x42, 0x62, 0x32, 0x4A, 0x73, 0x67, 0x6C, 0x72, 0x67, ++ 0x56, 0x4B, 0x74, 0x4F, 0x64, 0x6A, 0x4C, 0x50, 0x4F, 0x4D, 0x46, 0x6C, 0x4E, 0x2B, 0x58, 0x50, 0x73, 0x52, 0x47, 0x67, 0x6A, 0x42, 0x52, 0x6D, 0x4B, 0x66, 0x0A, 0x49, 0x72, 0x6A, 0x78, 0x77, 0x6F, 0x31, 0x70, 0x33, 0x50, 0x6F, 0x36, 0x57, ++ 0x41, 0x62, 0x66, 0x41, 0x67, 0x4D, 0x42, 0x41, 0x41, 0x47, 0x6A, 0x67, 0x62, 0x77, 0x77, 0x67, 0x62, 0x6B, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, ++ 0x7A, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x47, 0x75, 0x33, 0x2B, 0x51, 0x54, 0x6D, 0x51, 0x0A, 0x74, 0x43, 0x52, 0x5A, 0x76, 0x67, 0x48, 0x79, 0x55, 0x74, 0x56, 0x46, 0x39, 0x6C, 0x6F, 0x35, ++ 0x33, 0x42, 0x45, 0x77, 0x5A, 0x41, 0x59, 0x44, 0x56, 0x52, 0x30, 0x6A, 0x42, 0x46, 0x30, 0x77, 0x57, 0x34, 0x41, 0x55, 0x47, 0x75, 0x33, 0x2B, 0x51, 0x54, 0x6D, 0x51, 0x74, 0x43, 0x52, 0x5A, 0x76, 0x67, 0x48, 0x79, 0x55, 0x74, 0x56, 0x46, ++ 0x39, 0x6C, 0x6F, 0x35, 0x33, 0x42, 0x47, 0x68, 0x4F, 0x4B, 0x51, 0x32, 0x4D, 0x44, 0x51, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x0A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6B, 0x5A, 0x53, 0x4D, 0x52, 0x49, 0x77, 0x45, 0x41, 0x59, ++ 0x44, 0x56, 0x51, 0x51, 0x4B, 0x44, 0x41, 0x6C, 0x45, 0x61, 0x47, 0x6C, 0x74, 0x65, 0x57, 0x39, 0x30, 0x61, 0x58, 0x4D, 0x78, 0x45, 0x54, 0x41, 0x50, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x4D, 0x43, 0x45, 0x4E, 0x6C, 0x63, 0x6E, 0x52, ++ 0x70, 0x5A, 0x32, 0x35, 0x68, 0x67, 0x67, 0x6B, 0x41, 0x2F, 0x74, 0x7A, 0x6A, 0x41, 0x51, 0x2F, 0x4A, 0x0A, 0x53, 0x50, 0x38, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x51, 0x44, 0x41, 0x67, ++ 0x45, 0x47, 0x4D, 0x42, 0x45, 0x47, 0x43, 0x57, 0x43, 0x47, 0x53, 0x41, 0x47, 0x47, 0x2B, 0x45, 0x49, 0x42, 0x41, 0x51, 0x51, 0x45, 0x41, 0x77, 0x49, 0x41, 0x42, 0x7A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, ++ 0x30, 0x42, 0x41, 0x51, 0x55, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x51, 0x45, 0x41, 0x0A, 0x68, 0x51, 0x4D, 0x65, 0x6B, 0x6E, 0x48, 0x32, 0x51, 0x71, 0x2F, 0x68, 0x6F, 0x32, 0x47, 0x65, 0x36, 0x2F, 0x50, 0x41, 0x44, 0x2F, 0x4B, 0x6C, 0x31, ++ 0x4E, 0x71, 0x56, 0x35, 0x74, 0x61, 0x2B, 0x61, 0x44, 0x59, 0x39, 0x66, 0x6D, 0x34, 0x66, 0x54, 0x49, 0x72, 0x76, 0x30, 0x51, 0x38, 0x68, 0x62, 0x56, 0x36, 0x6C, 0x55, 0x6D, 0x50, 0x4F, 0x45, 0x76, 0x6A, 0x76, 0x4B, 0x74, 0x70, 0x76, 0x36, ++ 0x7A, 0x66, 0x2B, 0x45, 0x77, 0x4C, 0x48, 0x79, 0x7A, 0x73, 0x2B, 0x0A, 0x49, 0x6D, 0x76, 0x61, 0x59, 0x53, 0x35, 0x2F, 0x31, 0x48, 0x49, 0x39, 0x33, 0x54, 0x44, 0x68, 0x48, 0x6B, 0x78, 0x41, 0x47, 0x59, 0x77, 0x50, 0x31, 0x35, 0x7A, 0x52, ++ 0x67, 0x7A, 0x42, 0x37, 0x6D, 0x46, 0x6E, 0x63, 0x66, 0x63, 0x61, 0x35, 0x44, 0x43, 0x6C, 0x4D, 0x6F, 0x54, 0x4F, 0x69, 0x36, 0x32, 0x63, 0x36, 0x5A, 0x59, 0x54, 0x54, 0x6C, 0x75, 0x4C, 0x74, 0x64, 0x6B, 0x56, 0x77, 0x6A, 0x37, 0x55, 0x72, ++ 0x33, 0x76, 0x6B, 0x6A, 0x31, 0x6B, 0x6C, 0x75, 0x0A, 0x50, 0x42, 0x53, 0x31, 0x78, 0x70, 0x38, 0x31, 0x48, 0x6C, 0x44, 0x51, 0x77, 0x59, 0x39, 0x71, 0x63, 0x45, 0x51, 0x43, 0x59, 0x73, 0x75, 0x75, 0x48, 0x57, 0x68, 0x42, 0x70, 0x36, 0x70, ++ 0x58, 0x36, 0x46, 0x4F, 0x71, 0x42, 0x39, 0x49, 0x47, 0x39, 0x74, 0x55, 0x55, 0x42, 0x67, 0x75, 0x52, 0x41, 0x33, 0x55, 0x73, 0x62, 0x48, 0x4B, 0x31, 0x59, 0x5A, 0x57, 0x61, 0x44, 0x59, 0x75, 0x35, 0x44, 0x65, 0x66, 0x31, 0x33, 0x31, 0x54, ++ 0x4E, 0x33, 0x75, 0x62, 0x59, 0x0A, 0x31, 0x67, 0x6B, 0x49, 0x6C, 0x32, 0x50, 0x6C, 0x77, 0x53, 0x36, 0x77, 0x74, 0x30, 0x51, 0x6D, 0x77, 0x43, 0x62, 0x41, 0x72, 0x31, 0x55, 0x77, 0x6E, 0x6A, 0x76, 0x56, 0x4E, 0x69, 0x6F, 0x5A, 0x42, 0x50, ++ 0x52, 0x63, 0x48, 0x76, 0x2F, 0x50, 0x4C, 0x4C, 0x66, 0x2F, 0x30, 0x50, 0x32, 0x48, 0x51, 0x42, 0x48, 0x56, 0x45, 0x53, 0x4F, 0x37, 0x53, 0x4D, 0x41, 0x68, 0x71, 0x61, 0x51, 0x6F, 0x4C, 0x66, 0x30, 0x56, 0x2B, 0x4C, 0x42, 0x4F, 0x4B, 0x2F, ++ 0x51, 0x77, 0x0A, 0x57, 0x79, 0x48, 0x38, 0x45, 0x5A, 0x45, 0x30, 0x76, 0x6B, 0x48, 0x76, 0x65, 0x35, 0x32, 0x58, 0x64, 0x66, 0x2B, 0x58, 0x6C, 0x63, 0x43, 0x57, 0x57, 0x43, 0x2F, 0x71, 0x75, 0x30, 0x62, 0x58, 0x75, 0x2B, 0x54, 0x5A, 0x4C, ++ 0x67, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x65, 0x50, 0x4B, 0x49, 0x20, 0x52, 0x6F, 0x6F, 0x74, ++ 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, ++ 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x73, 0x44, 0x43, 0x43, 0x41, 0x35, 0x69, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x46, 0x63, 0x69, 0x39, 0x5A, 0x55, 0x64, 0x63, 0x72, 0x37, 0x69, 0x58, 0x41, ++ 0x46, 0x37, 0x6B, 0x42, 0x74, 0x4B, 0x38, 0x6E, 0x54, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x55, 0x46, 0x41, 0x44, 0x42, 0x65, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, ++ 0x51, 0x51, 0x47, 0x0A, 0x45, 0x77, 0x4A, 0x55, 0x56, 0x7A, 0x45, 0x6A, 0x4D, 0x43, 0x45, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, 0x61, 0x51, 0x32, 0x68, 0x31, 0x62, 0x6D, 0x64, 0x6F, 0x64, 0x32, 0x45, 0x67, 0x56, 0x47, 0x56, 0x73, ++ 0x5A, 0x57, 0x4E, 0x76, 0x62, 0x53, 0x42, 0x44, 0x62, 0x79, 0x34, 0x73, 0x49, 0x45, 0x78, 0x30, 0x5A, 0x43, 0x34, 0x78, 0x4B, 0x6A, 0x41, 0x6F, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x73, 0x4D, 0x49, 0x57, 0x56, 0x51, 0x53, 0x30, 0x6B, 0x67, ++ 0x0A, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x61, 0x57, 0x5A, 0x70, 0x59, 0x32, 0x46, 0x30, 0x61, 0x57, 0x39, 0x75, 0x49, 0x45, 0x46, 0x31, 0x64, 0x47, 0x68, 0x76, 0x63, 0x6D, 0x6C, 0x30, 0x65, 0x54, 0x41, ++ 0x65, 0x46, 0x77, 0x30, 0x77, 0x4E, 0x44, 0x45, 0x79, 0x4D, 0x6A, 0x41, 0x77, 0x4D, 0x6A, 0x4D, 0x78, 0x4D, 0x6A, 0x64, 0x61, 0x46, 0x77, 0x30, 0x7A, 0x4E, 0x44, 0x45, 0x79, 0x4D, 0x6A, 0x41, 0x77, 0x4D, 0x6A, 0x4D, 0x78, 0x0A, 0x4D, 0x6A, ++ 0x64, 0x61, 0x4D, 0x46, 0x34, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6C, 0x52, 0x58, 0x4D, 0x53, 0x4D, 0x77, 0x49, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x44, 0x42, 0x70, 0x44, 0x61, 0x48, ++ 0x56, 0x75, 0x5A, 0x32, 0x68, 0x33, 0x59, 0x53, 0x42, 0x55, 0x5A, 0x57, 0x78, 0x6C, 0x59, 0x32, 0x39, 0x74, 0x49, 0x45, 0x4E, 0x76, 0x4C, 0x69, 0x77, 0x67, 0x54, 0x48, 0x52, 0x6B, 0x4C, 0x6A, 0x45, 0x71, 0x0A, 0x4D, 0x43, 0x67, 0x47, 0x41, ++ 0x31, 0x55, 0x45, 0x43, 0x77, 0x77, 0x68, 0x5A, 0x56, 0x42, 0x4C, 0x53, 0x53, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x6C, 0x63, 0x6E, 0x52, 0x70, 0x5A, 0x6D, 0x6C, 0x6A, 0x59, 0x58, 0x52, 0x70, 0x62, 0x32, 0x34, 0x67, 0x51, ++ 0x58, 0x56, 0x30, 0x61, 0x47, 0x39, 0x79, 0x61, 0x58, 0x52, 0x35, 0x4D, 0x49, 0x49, 0x43, 0x49, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x0A, 0x41, 0x51, 0x45, 0x46, 0x41, 0x41, 0x4F, 0x43, ++ 0x41, 0x67, 0x38, 0x41, 0x4D, 0x49, 0x49, 0x43, 0x43, 0x67, 0x4B, 0x43, 0x41, 0x67, 0x45, 0x41, 0x34, 0x53, 0x55, 0x50, 0x37, 0x6F, 0x33, 0x62, 0x69, 0x44, 0x4E, 0x31, 0x5A, 0x38, 0x32, 0x74, 0x48, 0x33, 0x30, 0x36, 0x54, 0x6D, 0x32, 0x64, ++ 0x30, 0x79, 0x38, 0x55, 0x38, 0x32, 0x4E, 0x30, 0x79, 0x77, 0x45, 0x68, 0x61, 0x6A, 0x66, 0x71, 0x68, 0x46, 0x41, 0x48, 0x53, 0x79, 0x5A, 0x62, 0x43, 0x55, 0x4E, 0x73, 0x0A, 0x49, 0x5A, 0x35, 0x71, 0x79, 0x4E, 0x55, 0x44, 0x39, 0x57, 0x42, ++ 0x70, 0x6A, 0x38, 0x7A, 0x77, 0x49, 0x75, 0x51, 0x66, 0x35, 0x2F, 0x64, 0x71, 0x49, 0x6A, 0x47, 0x33, 0x4C, 0x42, 0x58, 0x79, 0x34, 0x50, 0x34, 0x41, 0x61, 0x6B, 0x50, 0x2F, 0x68, 0x32, 0x58, 0x47, 0x74, 0x52, 0x72, 0x42, 0x70, 0x30, 0x78, ++ 0x74, 0x49, 0x6E, 0x41, 0x68, 0x69, 0x6A, 0x48, 0x79, 0x6C, 0x33, 0x53, 0x4A, 0x43, 0x52, 0x49, 0x6D, 0x48, 0x4A, 0x37, 0x4B, 0x32, 0x52, 0x4B, 0x69, 0x0A, 0x6C, 0x54, 0x7A, 0x61, 0x36, 0x57, 0x65, 0x2F, 0x43, 0x4B, 0x42, 0x6B, 0x34, 0x39, ++ 0x5A, 0x43, 0x74, 0x30, 0x58, 0x76, 0x6C, 0x2F, 0x54, 0x32, 0x39, 0x64, 0x65, 0x31, 0x53, 0x68, 0x55, 0x43, 0x57, 0x48, 0x32, 0x59, 0x57, 0x45, 0x74, 0x67, 0x76, 0x4D, 0x33, 0x58, 0x44, 0x5A, 0x6F, 0x54, 0x4D, 0x31, 0x50, 0x52, 0x59, 0x66, ++ 0x6C, 0x36, 0x31, 0x64, 0x64, 0x34, 0x73, 0x35, 0x6F, 0x7A, 0x39, 0x77, 0x43, 0x47, 0x7A, 0x68, 0x31, 0x4E, 0x6C, 0x44, 0x69, 0x76, 0x0A, 0x71, 0x4F, 0x78, 0x34, 0x55, 0x58, 0x43, 0x4B, 0x58, 0x42, 0x43, 0x44, 0x55, 0x53, 0x48, 0x33, 0x45, ++ 0x54, 0x30, 0x30, 0x68, 0x6C, 0x37, 0x6C, 0x53, 0x4D, 0x32, 0x58, 0x67, 0x59, 0x49, 0x31, 0x54, 0x42, 0x6E, 0x73, 0x5A, 0x66, 0x5A, 0x72, 0x78, 0x51, 0x57, 0x68, 0x37, 0x6B, 0x63, 0x54, 0x31, 0x72, 0x4D, 0x68, 0x4A, 0x35, 0x51, 0x51, 0x43, ++ 0x74, 0x6B, 0x6B, 0x4F, 0x37, 0x71, 0x2B, 0x52, 0x42, 0x4E, 0x47, 0x4D, 0x44, 0x2B, 0x58, 0x50, 0x4E, 0x6A, 0x58, 0x0A, 0x31, 0x32, 0x72, 0x75, 0x4F, 0x7A, 0x6A, 0x6A, 0x4B, 0x39, 0x53, 0x58, 0x44, 0x72, 0x6B, 0x62, 0x35, 0x77, 0x64, 0x4A, ++ 0x66, 0x7A, 0x63, 0x71, 0x2B, 0x58, 0x64, 0x34, 0x7A, 0x31, 0x54, 0x74, 0x57, 0x30, 0x61, 0x64, 0x6F, 0x34, 0x41, 0x4F, 0x6B, 0x55, 0x50, 0x42, 0x31, 0x6C, 0x74, 0x66, 0x46, 0x4C, 0x71, 0x66, 0x70, 0x6F, 0x30, 0x6B, 0x52, 0x30, 0x42, 0x5A, ++ 0x76, 0x33, 0x49, 0x34, 0x73, 0x6A, 0x5A, 0x73, 0x4E, 0x2F, 0x2B, 0x5A, 0x30, 0x56, 0x30, 0x4F, 0x0A, 0x57, 0x51, 0x71, 0x72, 0x61, 0x66, 0x66, 0x41, 0x73, 0x67, 0x52, 0x46, 0x65, 0x6C, 0x51, 0x41, 0x72, 0x72, 0x35, 0x54, 0x39, 0x72, 0x58, ++ 0x6E, 0x34, 0x66, 0x67, 0x38, 0x6F, 0x7A, 0x48, 0x53, 0x71, 0x66, 0x34, 0x68, 0x55, 0x6D, 0x54, 0x46, 0x70, 0x6D, 0x66, 0x77, 0x64, 0x51, 0x63, 0x47, 0x6C, 0x42, 0x53, 0x42, 0x56, 0x63, 0x59, 0x6E, 0x35, 0x41, 0x47, 0x50, 0x46, 0x38, 0x46, ++ 0x71, 0x63, 0x64, 0x65, 0x2B, 0x53, 0x2F, 0x75, 0x55, 0x57, 0x48, 0x31, 0x2B, 0x0A, 0x45, 0x54, 0x4F, 0x78, 0x51, 0x76, 0x64, 0x69, 0x62, 0x42, 0x6A, 0x57, 0x7A, 0x77, 0x6C, 0x6F, 0x50, 0x6E, 0x39, 0x73, 0x39, 0x68, 0x36, 0x50, 0x59, 0x71, ++ 0x32, 0x6C, 0x59, 0x39, 0x73, 0x4A, 0x70, 0x78, 0x38, 0x69, 0x51, 0x6B, 0x45, 0x65, 0x62, 0x35, 0x6D, 0x4B, 0x50, 0x74, 0x66, 0x35, 0x50, 0x30, 0x42, 0x36, 0x65, 0x62, 0x43, 0x6C, 0x41, 0x5A, 0x4C, 0x53, 0x6E, 0x54, 0x30, 0x49, 0x46, 0x61, ++ 0x55, 0x51, 0x41, 0x53, 0x32, 0x7A, 0x4D, 0x6E, 0x61, 0x6F, 0x0A, 0x6C, 0x51, 0x32, 0x7A, 0x65, 0x70, 0x72, 0x37, 0x42, 0x78, 0x42, 0x34, 0x45, 0x57, 0x2F, 0x68, 0x6A, 0x38, 0x65, 0x36, 0x44, 0x79, 0x55, 0x61, 0x64, 0x43, 0x72, 0x6C, 0x48, ++ 0x4A, 0x68, 0x42, 0x6D, 0x64, 0x38, 0x68, 0x68, 0x2B, 0x69, 0x56, 0x42, 0x6D, 0x6F, 0x4B, 0x73, 0x32, 0x70, 0x48, 0x64, 0x6D, 0x58, 0x32, 0x4F, 0x73, 0x2B, 0x50, 0x59, 0x68, 0x63, 0x5A, 0x65, 0x77, 0x6F, 0x6F, 0x7A, 0x52, 0x72, 0x53, 0x67, ++ 0x78, 0x34, 0x68, 0x78, 0x79, 0x79, 0x2F, 0x0A, 0x76, 0x76, 0x39, 0x68, 0x61, 0x4C, 0x64, 0x6E, 0x47, 0x37, 0x74, 0x34, 0x54, 0x59, 0x33, 0x4F, 0x5A, 0x2B, 0x58, 0x6B, 0x77, 0x59, 0x36, 0x33, 0x49, 0x32, 0x62, 0x69, 0x6E, 0x5A, 0x42, 0x31, ++ 0x4E, 0x4A, 0x69, 0x70, 0x4E, 0x69, 0x75, 0x4B, 0x6D, 0x70, 0x53, 0x35, 0x6E, 0x65, 0x7A, 0x4D, 0x69, 0x72, 0x48, 0x34, 0x4A, 0x59, 0x6C, 0x63, 0x57, 0x72, 0x59, 0x76, 0x6A, 0x42, 0x39, 0x74, 0x65, 0x53, 0x53, 0x6E, 0x55, 0x6D, 0x6A, 0x44, ++ 0x68, 0x44, 0x58, 0x69, 0x0A, 0x5A, 0x6F, 0x31, 0x6A, 0x44, 0x69, 0x56, 0x4E, 0x31, 0x52, 0x6D, 0x79, 0x35, 0x6E, 0x6B, 0x33, 0x70, 0x79, 0x4B, 0x64, 0x56, 0x44, 0x45, 0x43, 0x41, 0x77, 0x45, 0x41, 0x41, 0x61, 0x4E, 0x71, 0x4D, 0x47, 0x67, ++ 0x77, 0x48, 0x51, 0x59, 0x44, 0x56, 0x52, 0x30, 0x4F, 0x42, 0x42, 0x59, 0x45, 0x46, 0x42, 0x34, 0x4D, 0x39, 0x37, 0x5A, 0x6E, 0x38, 0x75, 0x47, 0x53, 0x4A, 0x67, 0x6C, 0x46, 0x77, 0x46, 0x55, 0x35, 0x4C, 0x6E, 0x63, 0x2F, 0x51, 0x6B, 0x71, ++ 0x69, 0x0A, 0x4D, 0x41, 0x77, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x4F, 0x51, 0x59, 0x45, 0x5A, 0x79, 0x6F, 0x48, 0x41, 0x41, 0x51, 0x78, 0x4D, 0x43, 0x38, 0x77, 0x4C, 0x51, ++ 0x49, 0x42, 0x41, 0x44, 0x41, 0x4A, 0x42, 0x67, 0x55, 0x72, 0x44, 0x67, 0x4D, 0x43, 0x47, 0x67, 0x55, 0x41, 0x4D, 0x41, 0x63, 0x47, 0x42, 0x57, 0x63, 0x71, 0x41, 0x77, 0x41, 0x41, 0x42, 0x42, 0x52, 0x46, 0x73, 0x4D, 0x4C, 0x48, 0x0A, 0x43, ++ 0x6C, 0x5A, 0x38, 0x37, 0x6C, 0x74, 0x34, 0x44, 0x4A, 0x58, 0x35, 0x47, 0x46, 0x50, 0x42, 0x70, 0x68, 0x7A, 0x59, 0x45, 0x44, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x55, 0x46, 0x41, ++ 0x41, 0x4F, 0x43, 0x41, 0x67, 0x45, 0x41, 0x43, 0x62, 0x4F, 0x44, 0x55, 0x31, 0x6B, 0x42, 0x50, 0x70, 0x56, 0x4A, 0x75, 0x66, 0x47, 0x42, 0x75, 0x76, 0x6C, 0x32, 0x49, 0x43, 0x4F, 0x31, 0x4A, 0x32, 0x42, 0x30, 0x0A, 0x31, 0x47, 0x71, 0x5A, ++ 0x4E, 0x46, 0x35, 0x73, 0x41, 0x46, 0x50, 0x5A, 0x6E, 0x2F, 0x4B, 0x6D, 0x73, 0x53, 0x51, 0x48, 0x52, 0x47, 0x6F, 0x71, 0x78, 0x71, 0x57, 0x4F, 0x65, 0x42, 0x4C, 0x6F, 0x52, 0x39, 0x6C, 0x59, 0x47, 0x78, 0x4D, 0x71, 0x58, 0x6E, 0x6D, 0x62, ++ 0x6E, 0x77, 0x6F, 0x71, 0x5A, 0x36, 0x59, 0x6C, 0x50, 0x77, 0x5A, 0x70, 0x56, 0x6E, 0x50, 0x44, 0x69, 0x6D, 0x5A, 0x49, 0x2B, 0x79, 0x6D, 0x42, 0x56, 0x33, 0x51, 0x47, 0x79, 0x70, 0x7A, 0x71, 0x0A, 0x4B, 0x4F, 0x67, 0x34, 0x5A, 0x79, 0x59, ++ 0x72, 0x38, 0x64, 0x57, 0x31, 0x50, 0x32, 0x57, 0x54, 0x2B, 0x44, 0x5A, 0x64, 0x6A, 0x6F, 0x32, 0x4E, 0x51, 0x43, 0x43, 0x48, 0x47, 0x65, 0x72, 0x76, 0x4A, 0x38, 0x41, 0x39, 0x74, 0x44, 0x6B, 0x50, 0x4A, 0x58, 0x74, 0x6F, 0x55, 0x48, 0x52, ++ 0x56, 0x6E, 0x41, 0x78, 0x5A, 0x66, 0x56, 0x6F, 0x39, 0x51, 0x5A, 0x51, 0x6C, 0x55, 0x67, 0x6A, 0x67, 0x52, 0x79, 0x77, 0x56, 0x4D, 0x52, 0x6E, 0x56, 0x76, 0x77, 0x64, 0x56, 0x0A, 0x78, 0x72, 0x73, 0x53, 0x74, 0x5A, 0x66, 0x30, 0x58, 0x34, ++ 0x4F, 0x46, 0x75, 0x6E, 0x48, 0x42, 0x32, 0x57, 0x79, 0x42, 0x45, 0x58, 0x59, 0x4B, 0x43, 0x72, 0x43, 0x2F, 0x67, 0x70, 0x66, 0x33, 0x36, 0x6A, 0x33, 0x36, 0x2B, 0x75, 0x77, 0x74, 0x71, 0x53, 0x69, 0x55, 0x4F, 0x31, 0x62, 0x64, 0x30, 0x6C, ++ 0x45, 0x75, 0x72, 0x73, 0x43, 0x39, 0x43, 0x42, 0x57, 0x4D, 0x64, 0x31, 0x49, 0x30, 0x6C, 0x74, 0x61, 0x62, 0x72, 0x4E, 0x4D, 0x64, 0x6A, 0x6D, 0x45, 0x50, 0x0A, 0x4E, 0x58, 0x75, 0x62, 0x72, 0x6A, 0x6C, 0x70, 0x43, 0x32, 0x4A, 0x67, 0x51, ++ 0x43, 0x41, 0x32, 0x6A, 0x36, 0x2F, 0x37, 0x4E, 0x75, 0x34, 0x74, 0x43, 0x45, 0x6F, 0x64, 0x75, 0x4C, 0x2B, 0x62, 0x58, 0x50, 0x6A, 0x71, 0x70, 0x52, 0x75, 0x67, 0x63, 0x36, 0x62, 0x59, 0x2B, 0x47, 0x37, 0x67, 0x4D, 0x77, 0x52, 0x66, 0x61, ++ 0x4B, 0x6F, 0x6E, 0x68, 0x2B, 0x33, 0x5A, 0x77, 0x5A, 0x43, 0x63, 0x37, 0x62, 0x33, 0x6A, 0x61, 0x6A, 0x57, 0x76, 0x59, 0x39, 0x2B, 0x72, 0x0A, 0x47, 0x4E, 0x6D, 0x36, 0x35, 0x75, 0x6C, 0x4B, 0x36, 0x6C, 0x43, 0x4B, 0x44, 0x32, 0x47, 0x54, ++ 0x48, 0x75, 0x49, 0x74, 0x47, 0x65, 0x49, 0x77, 0x6C, 0x44, 0x57, 0x53, 0x58, 0x51, 0x36, 0x32, 0x42, 0x36, 0x38, 0x5A, 0x67, 0x49, 0x39, 0x48, 0x6B, 0x46, 0x46, 0x4C, 0x4C, 0x6B, 0x33, 0x64, 0x68, 0x65, 0x4C, 0x53, 0x43, 0x6C, 0x49, 0x4B, ++ 0x46, 0x35, 0x72, 0x38, 0x47, 0x72, 0x42, 0x51, 0x41, 0x75, 0x55, 0x42, 0x6F, 0x32, 0x4D, 0x33, 0x49, 0x55, 0x78, 0x45, 0x0A, 0x78, 0x4A, 0x74, 0x52, 0x6D, 0x52, 0x45, 0x4F, 0x63, 0x35, 0x77, 0x47, 0x6A, 0x31, 0x51, 0x75, 0x70, 0x79, 0x68, ++ 0x65, 0x52, 0x44, 0x6D, 0x48, 0x56, 0x69, 0x30, 0x33, 0x76, 0x59, 0x56, 0x45, 0x6C, 0x4F, 0x45, 0x4D, 0x53, 0x79, 0x79, 0x63, 0x77, 0x35, 0x4B, 0x46, 0x4E, 0x47, 0x48, 0x4C, 0x44, 0x37, 0x69, 0x62, 0x53, 0x6B, 0x4E, 0x53, 0x2F, 0x6A, 0x51, ++ 0x36, 0x66, 0x62, 0x6A, 0x70, 0x4B, 0x64, 0x78, 0x32, 0x71, 0x63, 0x67, 0x77, 0x2B, 0x42, 0x52, 0x78, 0x0A, 0x67, 0x4D, 0x59, 0x65, 0x4E, 0x6B, 0x68, 0x30, 0x49, 0x6B, 0x46, 0x63, 0x68, 0x34, 0x4C, 0x6F, 0x47, 0x48, 0x47, 0x4C, 0x51, 0x59, ++ 0x6C, 0x45, 0x35, 0x33, 0x35, 0x59, 0x57, 0x36, 0x69, 0x34, 0x6A, 0x52, 0x50, 0x70, 0x70, 0x32, 0x7A, 0x44, 0x52, 0x2B, 0x32, 0x7A, 0x47, 0x70, 0x31, 0x69, 0x72, 0x6F, 0x32, 0x43, 0x36, 0x70, 0x53, 0x65, 0x33, 0x56, 0x6B, 0x51, 0x77, 0x36, ++ 0x33, 0x64, 0x34, 0x6B, 0x33, 0x6A, 0x4D, 0x64, 0x58, 0x48, 0x37, 0x4F, 0x6A, 0x79, 0x0A, 0x73, 0x50, 0x36, 0x53, 0x48, 0x68, 0x59, 0x4B, 0x47, 0x76, 0x7A, 0x5A, 0x38, 0x2F, 0x67, 0x6E, 0x74, 0x73, 0x6D, 0x2B, 0x48, 0x62, 0x52, 0x73, 0x5A, ++ 0x4A, 0x42, 0x2F, 0x39, 0x4F, 0x54, 0x45, 0x57, 0x39, 0x63, 0x33, 0x72, 0x6B, 0x49, 0x4F, 0x33, 0x61, 0x51, 0x61, 0x62, 0x33, 0x79, 0x49, 0x56, 0x4D, 0x55, 0x57, 0x62, 0x75, 0x46, 0x36, 0x61, 0x43, 0x37, 0x34, 0x4F, 0x72, 0x38, 0x4E, 0x70, ++ 0x44, 0x79, 0x4A, 0x4F, 0x33, 0x69, 0x6E, 0x54, 0x6D, 0x4F, 0x44, 0x0A, 0x42, 0x43, 0x45, 0x49, 0x5A, 0x34, 0x33, 0x79, 0x67, 0x6B, 0x6E, 0x51, 0x57, 0x2F, 0x32, 0x78, 0x7A, 0x51, 0x2B, 0x44, 0x68, 0x4E, 0x51, 0x2B, 0x49, 0x49, 0x58, 0x33, ++ 0x53, 0x6A, 0x30, 0x72, 0x6E, 0x50, 0x30, 0x71, 0x43, 0x67, 0x6C, 0x4E, 0x36, 0x6F, 0x48, 0x34, 0x45, 0x5A, 0x77, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, ++ 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x63, 0x65, 0x72, 0x74, 0x53, 0x49, 0x47, 0x4E, 0x20, 0x52, 0x4F, 0x4F, 0x54, 0x20, 0x43, 0x41, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x44, 0x4F, 0x44, 0x43, 0x43, 0x41, 0x69, ++ 0x43, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x47, 0x49, 0x41, 0x59, 0x46, 0x46, 0x6E, 0x41, 0x43, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x42, 0x51, 0x55, 0x41, 0x4D, 0x44, ++ 0x73, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6C, 0x4A, 0x50, 0x4D, 0x52, 0x45, 0x77, 0x44, 0x77, 0x59, 0x44, 0x0A, 0x56, 0x51, 0x51, 0x4B, 0x45, 0x77, 0x68, 0x6A, 0x5A, 0x58, 0x4A, 0x30, 0x55, ++ 0x30, 0x6C, 0x48, 0x54, 0x6A, 0x45, 0x5A, 0x4D, 0x42, 0x63, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x78, 0x4D, 0x51, 0x59, 0x32, 0x56, 0x79, 0x64, 0x46, 0x4E, 0x4A, 0x52, 0x30, 0x34, 0x67, 0x55, 0x6B, 0x39, 0x50, 0x56, 0x43, 0x42, 0x44, 0x51, ++ 0x54, 0x41, 0x65, 0x46, 0x77, 0x30, 0x77, 0x4E, 0x6A, 0x41, 0x33, 0x4D, 0x44, 0x51, 0x78, 0x4E, 0x7A, 0x49, 0x77, 0x4D, 0x44, 0x52, 0x61, 0x0A, 0x46, 0x77, 0x30, 0x7A, 0x4D, 0x54, 0x41, 0x33, 0x4D, 0x44, 0x51, 0x78, 0x4E, 0x7A, 0x49, 0x77, ++ 0x4D, 0x44, 0x52, 0x61, 0x4D, 0x44, 0x73, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6C, 0x4A, 0x50, 0x4D, 0x52, 0x45, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x45, 0x77, 0x68, 0x6A, ++ 0x5A, 0x58, 0x4A, 0x30, 0x55, 0x30, 0x6C, 0x48, 0x54, 0x6A, 0x45, 0x5A, 0x4D, 0x42, 0x63, 0x47, 0x41, 0x31, 0x55, 0x45, 0x0A, 0x43, 0x78, 0x4D, 0x51, 0x59, 0x32, 0x56, 0x79, 0x64, 0x46, 0x4E, 0x4A, 0x52, 0x30, 0x34, 0x67, 0x55, 0x6B, 0x39, ++ 0x50, 0x56, 0x43, 0x42, 0x44, 0x51, 0x54, 0x43, 0x43, 0x41, 0x53, 0x49, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x45, 0x50, 0x41, 0x44, 0x43, ++ 0x43, 0x41, 0x51, 0x6F, 0x43, 0x67, 0x67, 0x45, 0x42, 0x41, 0x4C, 0x63, 0x7A, 0x75, 0x58, 0x37, 0x49, 0x0A, 0x4A, 0x55, 0x71, 0x4F, 0x74, 0x64, 0x75, 0x30, 0x4B, 0x42, 0x75, 0x71, 0x56, 0x35, 0x44, 0x6F, 0x30, 0x53, 0x4C, 0x54, 0x5A, 0x4C, ++ 0x72, 0x54, 0x6B, 0x2B, 0x6A, 0x55, 0x72, 0x49, 0x5A, 0x68, 0x51, 0x47, 0x70, 0x67, 0x56, 0x32, 0x68, 0x55, 0x68, 0x45, 0x32, 0x38, 0x61, 0x6C, 0x51, 0x43, 0x42, 0x66, 0x2F, 0x66, 0x6D, 0x35, 0x6F, 0x71, 0x72, 0x6C, 0x30, 0x48, 0x6A, 0x30, ++ 0x72, 0x44, 0x4B, 0x48, 0x2F, 0x76, 0x2B, 0x79, 0x76, 0x36, 0x65, 0x66, 0x48, 0x48, 0x0A, 0x72, 0x66, 0x41, 0x51, 0x55, 0x79, 0x53, 0x51, 0x69, 0x32, 0x62, 0x4A, 0x71, 0x49, 0x69, 0x72, 0x72, 0x31, 0x71, 0x6A, 0x41, 0x4F, 0x6D, 0x2B, 0x75, ++ 0x6B, 0x62, 0x75, 0x57, 0x33, 0x4E, 0x37, 0x4C, 0x42, 0x65, 0x43, 0x67, 0x56, 0x35, 0x69, 0x4C, 0x4B, 0x45, 0x43, 0x5A, 0x62, 0x4F, 0x39, 0x78, 0x53, 0x73, 0x41, 0x66, 0x73, 0x54, 0x38, 0x41, 0x7A, 0x4E, 0x58, 0x44, 0x65, 0x33, 0x69, 0x2B, ++ 0x73, 0x35, 0x64, 0x52, 0x64, 0x59, 0x34, 0x7A, 0x54, 0x57, 0x32, 0x0A, 0x73, 0x73, 0x48, 0x51, 0x6E, 0x49, 0x46, 0x4B, 0x71, 0x75, 0x53, 0x79, 0x41, 0x56, 0x77, 0x64, 0x6A, 0x31, 0x2B, 0x5A, 0x78, 0x4C, 0x47, 0x74, 0x32, 0x34, 0x67, 0x68, ++ 0x36, 0x35, 0x41, 0x49, 0x67, 0x6F, 0x44, 0x7A, 0x4D, 0x4B, 0x4E, 0x44, 0x35, 0x70, 0x43, 0x43, 0x72, 0x6C, 0x55, 0x6F, 0x53, 0x65, 0x31, 0x62, 0x31, 0x36, 0x6B, 0x51, 0x4F, 0x41, 0x37, 0x2B, 0x6A, 0x30, 0x78, 0x62, 0x6D, 0x30, 0x62, 0x71, ++ 0x51, 0x66, 0x57, 0x77, 0x43, 0x48, 0x54, 0x44, 0x0A, 0x30, 0x49, 0x67, 0x7A, 0x74, 0x6E, 0x7A, 0x58, 0x64, 0x4E, 0x2F, 0x63, 0x68, 0x4E, 0x46, 0x44, 0x44, 0x6E, 0x55, 0x35, 0x6F, 0x53, 0x56, 0x41, 0x4B, 0x4F, 0x70, 0x34, 0x79, 0x77, 0x34, ++ 0x73, 0x4C, 0x6A, 0x6D, 0x64, 0x6A, 0x49, 0x74, 0x75, 0x46, 0x68, 0x77, 0x76, 0x4A, 0x6F, 0x49, 0x51, 0x34, 0x75, 0x4E, 0x6C, 0x6C, 0x41, 0x6F, 0x45, 0x77, 0x46, 0x37, 0x33, 0x58, 0x56, 0x76, 0x34, 0x45, 0x4F, 0x4C, 0x51, 0x75, 0x6E, 0x70, ++ 0x4C, 0x2B, 0x39, 0x34, 0x33, 0x0A, 0x41, 0x41, 0x41, 0x61, 0x57, 0x79, 0x6A, 0x6A, 0x30, 0x70, 0x78, 0x7A, 0x50, 0x6A, 0x4B, 0x48, 0x6D, 0x4B, 0x48, 0x4A, 0x55, 0x53, 0x2F, 0x58, 0x33, 0x71, 0x77, 0x7A, 0x73, 0x30, 0x38, 0x43, 0x41, 0x77, ++ 0x45, 0x41, 0x41, 0x61, 0x4E, 0x43, 0x4D, 0x45, 0x41, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, ++ 0x38, 0x42, 0x0A, 0x41, 0x66, 0x38, 0x45, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x63, 0x59, 0x77, 0x48, 0x51, 0x59, 0x44, 0x56, 0x52, 0x30, 0x4F, 0x42, 0x42, 0x59, 0x45, 0x46, 0x4F, 0x43, 0x4D, 0x6D, 0x39, 0x73, 0x6C, 0x53, 0x62, 0x50, 0x78, 0x66, ++ 0x49, 0x62, 0x57, 0x73, 0x6B, 0x4B, 0x48, 0x43, 0x39, 0x42, 0x72, 0x6F, 0x4E, 0x6E, 0x6B, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x42, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x42, 0x0A, ++ 0x41, 0x51, 0x41, 0x2B, 0x30, 0x68, 0x79, 0x4A, 0x4C, 0x6A, 0x58, 0x38, 0x2B, 0x48, 0x58, 0x64, 0x35, 0x6E, 0x39, 0x6C, 0x69, 0x50, 0x52, 0x79, 0x54, 0x4D, 0x6B, 0x73, 0x31, 0x7A, 0x4A, 0x4F, 0x38, 0x39, 0x30, 0x5A, 0x65, 0x55, 0x65, 0x39, ++ 0x6A, 0x6A, 0x74, 0x62, 0x6B, 0x77, 0x39, 0x51, 0x53, 0x53, 0x51, 0x54, 0x61, 0x78, 0x51, 0x47, 0x63, 0x75, 0x38, 0x4A, 0x30, 0x36, 0x47, 0x68, 0x34, 0x30, 0x43, 0x45, 0x79, 0x65, 0x63, 0x59, 0x4D, 0x6E, 0x51, 0x38, 0x0A, 0x53, 0x47, 0x34, ++ 0x50, 0x6E, 0x30, 0x76, 0x55, 0x39, 0x78, 0x37, 0x54, 0x6B, 0x34, 0x5A, 0x6B, 0x56, 0x4A, 0x64, 0x6A, 0x63, 0x6C, 0x44, 0x56, 0x56, 0x63, 0x2F, 0x36, 0x49, 0x4A, 0x4D, 0x43, 0x6F, 0x70, 0x76, 0x44, 0x49, 0x35, 0x4E, 0x4F, 0x46, 0x6C, 0x56, ++ 0x32, 0x6F, 0x48, 0x42, 0x35, 0x62, 0x63, 0x30, 0x68, 0x48, 0x38, 0x38, 0x76, 0x4C, 0x62, 0x77, 0x5A, 0x34, 0x34, 0x67, 0x78, 0x2B, 0x46, 0x6B, 0x61, 0x67, 0x51, 0x6E, 0x49, 0x6C, 0x36, 0x5A, 0x30, 0x0A, 0x78, 0x32, 0x44, 0x45, 0x57, 0x38, ++ 0x78, 0x58, 0x6A, 0x72, 0x4A, 0x31, 0x2F, 0x52, 0x73, 0x43, 0x43, 0x64, 0x74, 0x5A, 0x62, 0x33, 0x4B, 0x54, 0x61, 0x66, 0x63, 0x78, 0x51, 0x64, 0x61, 0x49, 0x4F, 0x4C, 0x2B, 0x48, 0x73, 0x72, 0x30, 0x57, 0x65, 0x66, 0x6D, 0x71, 0x35, 0x4C, ++ 0x36, 0x49, 0x4A, 0x64, 0x31, 0x68, 0x4A, 0x79, 0x4D, 0x63, 0x74, 0x54, 0x45, 0x48, 0x42, 0x44, 0x61, 0x30, 0x47, 0x70, 0x43, 0x39, 0x6F, 0x48, 0x52, 0x78, 0x55, 0x49, 0x6C, 0x74, 0x0A, 0x76, 0x42, 0x54, 0x6A, 0x44, 0x34, 0x61, 0x75, 0x38, ++ 0x61, 0x73, 0x2B, 0x78, 0x36, 0x41, 0x4A, 0x7A, 0x4B, 0x4E, 0x49, 0x30, 0x65, 0x44, 0x62, 0x5A, 0x4F, 0x65, 0x53, 0x74, 0x63, 0x2B, 0x76, 0x63, 0x6B, 0x4E, 0x77, 0x69, 0x2F, 0x6E, 0x44, 0x68, 0x44, 0x77, 0x54, 0x71, 0x6E, 0x36, 0x53, 0x6D, ++ 0x31, 0x64, 0x54, 0x6B, 0x2F, 0x70, 0x77, 0x77, 0x70, 0x45, 0x4F, 0x4D, 0x66, 0x6D, 0x62, 0x5A, 0x31, 0x33, 0x70, 0x6C, 0x6A, 0x68, 0x65, 0x58, 0x37, 0x4E, 0x7A, 0x0A, 0x54, 0x6F, 0x67, 0x56, 0x5A, 0x39, 0x36, 0x65, 0x64, 0x68, 0x42, 0x69, ++ 0x49, 0x4C, 0x35, 0x56, 0x61, 0x5A, 0x56, 0x44, 0x41, 0x44, 0x6C, 0x4E, 0x39, 0x75, 0x36, 0x77, 0x57, 0x6B, 0x35, 0x4A, 0x52, 0x46, 0x52, 0x59, 0x58, 0x30, 0x4B, 0x44, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, ++ 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x4E, 0x65, 0x74, 0x4C, 0x6F, 0x63, 0x6B, 0x20, 0x41, 0x72, 0x61, 0x6E, 0x79, 0x20, 0x28, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x47, 0x6F, 0x6C, ++ 0x64, 0x29, 0x20, 0x46, 0xC5, 0x91, 0x74, 0x61, 0x6E, 0xC3, 0xBA, 0x73, 0xC3, 0xAD, 0x74, 0x76, 0xC3, 0xA1, 0x6E, 0x79, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, ++ 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x45, 0x46, 0x54, 0x43, 0x43, 0x41, 0x76, 0x32, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x47, 0x53, 0x55, 0x45, 0x73, 0x35, 0x41, 0x41, 0x51, 0x4D, 0x41, ++ 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x43, 0x77, 0x55, 0x41, 0x4D, 0x49, 0x47, 0x6E, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x49, 0x56, 0x54, ++ 0x45, 0x52, 0x4D, 0x41, 0x38, 0x47, 0x0A, 0x41, 0x31, 0x55, 0x45, 0x42, 0x77, 0x77, 0x49, 0x51, 0x6E, 0x56, 0x6B, 0x59, 0x58, 0x42, 0x6C, 0x63, 0x33, 0x51, 0x78, 0x46, 0x54, 0x41, 0x54, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x4D, 0x44, ++ 0x45, 0x35, 0x6C, 0x64, 0x45, 0x78, 0x76, 0x59, 0x32, 0x73, 0x67, 0x53, 0x32, 0x5A, 0x30, 0x4C, 0x6A, 0x45, 0x33, 0x4D, 0x44, 0x55, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x77, 0x77, 0x75, 0x56, 0x47, 0x46, 0x75, 0x77, 0x37, 0x70, 0x7A, 0x77, ++ 0x36, 0x31, 0x30, 0x0A, 0x64, 0x73, 0x4F, 0x68, 0x62, 0x6E, 0x6C, 0x72, 0x61, 0x57, 0x46, 0x6B, 0x77, 0x37, 0x4E, 0x72, 0x49, 0x43, 0x68, 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x61, 0x57, 0x5A, 0x70, 0x59, 0x32, 0x46, 0x30, 0x61, 0x57, 0x39, 0x75, ++ 0x49, 0x46, 0x4E, 0x6C, 0x63, 0x6E, 0x5A, 0x70, 0x59, 0x32, 0x56, 0x7A, 0x4B, 0x54, 0x45, 0x31, 0x4D, 0x44, 0x4D, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x77, 0x77, 0x73, 0x54, 0x6D, 0x56, 0x30, 0x54, 0x47, 0x39, 0x6A, 0x61, 0x79, 0x42, 0x42, ++ 0x0A, 0x63, 0x6D, 0x46, 0x75, 0x65, 0x53, 0x41, 0x6F, 0x51, 0x32, 0x78, 0x68, 0x63, 0x33, 0x4D, 0x67, 0x52, 0x32, 0x39, 0x73, 0x5A, 0x43, 0x6B, 0x67, 0x52, 0x73, 0x57, 0x52, 0x64, 0x47, 0x46, 0x75, 0x77, 0x37, 0x70, 0x7A, 0x77, 0x36, 0x31, ++ 0x30, 0x64, 0x73, 0x4F, 0x68, 0x62, 0x6E, 0x6B, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x44, 0x67, 0x78, 0x4D, 0x6A, 0x45, 0x78, 0x4D, 0x54, 0x55, 0x77, 0x4F, 0x44, 0x49, 0x78, 0x57, 0x68, 0x63, 0x4E, 0x4D, 0x6A, 0x67, 0x78, 0x0A, 0x4D, 0x6A, ++ 0x41, 0x32, 0x4D, 0x54, 0x55, 0x77, 0x4F, 0x44, 0x49, 0x78, 0x57, 0x6A, 0x43, 0x42, 0x70, 0x7A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x53, 0x46, 0x55, 0x78, 0x45, 0x54, 0x41, 0x50, 0x42, 0x67, ++ 0x4E, 0x56, 0x42, 0x41, 0x63, 0x4D, 0x43, 0x45, 0x4A, 0x31, 0x5A, 0x47, 0x46, 0x77, 0x5A, 0x58, 0x4E, 0x30, 0x4D, 0x52, 0x55, 0x77, 0x45, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x44, 0x41, 0x78, 0x4F, 0x0A, 0x5A, 0x58, 0x52, 0x4D, 0x62, ++ 0x32, 0x4E, 0x72, 0x49, 0x45, 0x74, 0x6D, 0x64, 0x43, 0x34, 0x78, 0x4E, 0x7A, 0x41, 0x31, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x73, 0x4D, 0x4C, 0x6C, 0x52, 0x68, 0x62, 0x73, 0x4F, 0x36, 0x63, 0x38, 0x4F, 0x74, 0x64, 0x48, 0x62, 0x44, 0x6F, ++ 0x57, 0x35, 0x35, 0x61, 0x32, 0x6C, 0x68, 0x5A, 0x4D, 0x4F, 0x7A, 0x61, 0x79, 0x41, 0x6F, 0x51, 0x32, 0x56, 0x79, 0x64, 0x47, 0x6C, 0x6D, 0x61, 0x57, 0x4E, 0x68, 0x64, 0x47, 0x6C, 0x76, 0x0A, 0x62, 0x69, 0x42, 0x54, 0x5A, 0x58, 0x4A, 0x32, ++ 0x61, 0x57, 0x4E, 0x6C, 0x63, 0x79, 0x6B, 0x78, 0x4E, 0x54, 0x41, 0x7A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x4D, 0x4C, 0x45, 0x35, 0x6C, 0x64, 0x45, 0x78, 0x76, 0x59, 0x32, 0x73, 0x67, 0x51, 0x58, 0x4A, 0x68, 0x62, 0x6E, 0x6B, 0x67, ++ 0x4B, 0x45, 0x4E, 0x73, 0x59, 0x58, 0x4E, 0x7A, 0x49, 0x45, 0x64, 0x76, 0x62, 0x47, 0x51, 0x70, 0x49, 0x45, 0x62, 0x46, 0x6B, 0x58, 0x52, 0x68, 0x62, 0x73, 0x4F, 0x36, 0x0A, 0x63, 0x38, 0x4F, 0x74, 0x64, 0x48, 0x62, 0x44, 0x6F, 0x57, 0x35, ++ 0x35, 0x4D, 0x49, 0x49, 0x42, 0x49, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x45, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x51, 0x38, 0x41, 0x4D, 0x49, 0x49, 0x42, 0x43, 0x67, 0x4B, ++ 0x43, 0x41, 0x51, 0x45, 0x41, 0x78, 0x43, 0x52, 0x65, 0x63, 0x37, 0x35, 0x4C, 0x62, 0x52, 0x54, 0x44, 0x6F, 0x66, 0x54, 0x6A, 0x6C, 0x35, 0x42, 0x75, 0x0A, 0x30, 0x6A, 0x42, 0x46, 0x48, 0x6A, 0x7A, 0x75, 0x5A, 0x39, 0x6C, 0x6B, 0x34, 0x42, ++ 0x71, 0x4B, 0x66, 0x38, 0x6F, 0x77, 0x79, 0x6F, 0x50, 0x6A, 0x49, 0x4D, 0x48, 0x6A, 0x39, 0x44, 0x72, 0x54, 0x6C, 0x46, 0x38, 0x61, 0x66, 0x46, 0x74, 0x74, 0x76, 0x7A, 0x42, 0x50, 0x68, 0x43, 0x66, 0x32, 0x6E, 0x78, 0x39, 0x4A, 0x76, 0x4D, ++ 0x61, 0x5A, 0x43, 0x70, 0x44, 0x79, 0x44, 0x2F, 0x56, 0x2F, 0x51, 0x34, 0x51, 0x33, 0x59, 0x31, 0x47, 0x4C, 0x65, 0x71, 0x56, 0x77, 0x0A, 0x2F, 0x48, 0x70, 0x59, 0x7A, 0x59, 0x36, 0x62, 0x37, 0x63, 0x4E, 0x47, 0x62, 0x49, 0x52, 0x77, 0x58, ++ 0x64, 0x72, 0x7A, 0x41, 0x5A, 0x41, 0x6A, 0x2F, 0x45, 0x34, 0x77, 0x71, 0x58, 0x37, 0x68, 0x4A, 0x32, 0x50, 0x6E, 0x37, 0x57, 0x51, 0x38, 0x6F, 0x4C, 0x6A, 0x4A, 0x4D, 0x32, 0x50, 0x2B, 0x46, 0x70, 0x44, 0x2F, 0x73, 0x4C, 0x6A, 0x39, 0x31, ++ 0x36, 0x6A, 0x41, 0x77, 0x4A, 0x52, 0x44, 0x43, 0x37, 0x62, 0x56, 0x57, 0x61, 0x61, 0x65, 0x56, 0x74, 0x41, 0x6B, 0x0A, 0x48, 0x33, 0x42, 0x35, 0x72, 0x39, 0x73, 0x35, 0x56, 0x41, 0x31, 0x6C, 0x64, 0x64, 0x6B, 0x56, 0x51, 0x5A, 0x51, 0x42, ++ 0x72, 0x31, 0x37, 0x73, 0x39, 0x6F, 0x33, 0x78, 0x2F, 0x36, 0x31, 0x6B, 0x2F, 0x69, 0x43, 0x61, 0x31, 0x31, 0x7A, 0x72, 0x2F, 0x71, 0x59, 0x66, 0x43, 0x47, 0x53, 0x6A, 0x69, 0x33, 0x5A, 0x56, 0x72, 0x52, 0x34, 0x37, 0x4B, 0x47, 0x41, 0x75, ++ 0x68, 0x79, 0x58, 0x6F, 0x71, 0x71, 0x38, 0x66, 0x78, 0x6D, 0x52, 0x47, 0x49, 0x4C, 0x64, 0x77, 0x0A, 0x66, 0x7A, 0x7A, 0x65, 0x53, 0x4E, 0x75, 0x57, 0x55, 0x37, 0x63, 0x35, 0x64, 0x2B, 0x51, 0x61, 0x34, 0x73, 0x63, 0x57, 0x68, 0x48, 0x61, ++ 0x58, 0x57, 0x79, 0x2B, 0x37, 0x47, 0x52, 0x57, 0x46, 0x2B, 0x47, 0x6D, 0x46, 0x39, 0x5A, 0x6D, 0x6E, 0x71, 0x66, 0x49, 0x30, 0x70, 0x36, 0x6D, 0x32, 0x70, 0x67, 0x50, 0x38, 0x62, 0x34, 0x59, 0x39, 0x56, 0x48, 0x78, 0x32, 0x42, 0x4A, 0x74, ++ 0x72, 0x2B, 0x55, 0x42, 0x64, 0x41, 0x44, 0x54, 0x48, 0x4C, 0x70, 0x6C, 0x31, 0x0A, 0x6E, 0x65, 0x57, 0x49, 0x41, 0x36, 0x70, 0x4E, 0x2B, 0x41, 0x50, 0x53, 0x51, 0x6E, 0x62, 0x41, 0x47, 0x77, 0x49, 0x44, 0x41, 0x4B, 0x69, 0x4C, 0x6F, 0x30, ++ 0x55, 0x77, 0x51, 0x7A, 0x41, 0x53, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x52, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x45, 0x43, 0x44, 0x41, 0x47, 0x41, 0x51, 0x48, 0x2F, 0x41, 0x67, 0x45, 0x45, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, ++ 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x42, 0x0A, 0x42, 0x6A, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x7A, 0x50, 0x70, 0x6E, 0x6B, 0x2F, 0x43, 0x32, 0x75, 0x4E, 0x43, 0x6C, 0x77, ++ 0x42, 0x37, 0x7A, 0x55, 0x2F, 0x32, 0x4D, 0x55, 0x39, 0x2B, 0x44, 0x31, 0x35, 0x59, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x45, 0x42, 0x41, ++ 0x4B, 0x74, 0x2F, 0x37, 0x68, 0x77, 0x57, 0x0A, 0x71, 0x5A, 0x77, 0x38, 0x55, 0x51, 0x43, 0x67, 0x77, 0x42, 0x45, 0x49, 0x42, 0x61, 0x65, 0x5A, 0x35, 0x6D, 0x38, 0x42, 0x69, 0x46, 0x52, 0x68, 0x62, 0x76, 0x47, 0x35, 0x47, 0x4B, 0x31, 0x4B, ++ 0x72, 0x66, 0x36, 0x42, 0x51, 0x43, 0x4F, 0x55, 0x4C, 0x2F, 0x74, 0x31, 0x66, 0x43, 0x38, 0x6F, 0x53, 0x32, 0x49, 0x6B, 0x67, 0x59, 0x49, 0x4C, 0x39, 0x57, 0x48, 0x78, 0x48, 0x47, 0x36, 0x34, 0x59, 0x54, 0x6A, 0x72, 0x67, 0x66, 0x70, 0x69, ++ 0x6F, 0x54, 0x74, 0x61, 0x0A, 0x59, 0x74, 0x4F, 0x55, 0x5A, 0x63, 0x54, 0x68, 0x35, 0x6D, 0x32, 0x43, 0x2B, 0x43, 0x38, 0x6C, 0x63, 0x4C, 0x49, 0x68, 0x4A, 0x73, 0x46, 0x79, 0x55, 0x52, 0x2B, 0x4D, 0x4C, 0x4D, 0x4F, 0x45, 0x6B, 0x4D, 0x4E, ++ 0x61, 0x6A, 0x37, 0x72, 0x50, 0x39, 0x4B, 0x64, 0x6C, 0x70, 0x65, 0x75, 0x59, 0x30, 0x66, 0x73, 0x46, 0x73, 0x6B, 0x5A, 0x31, 0x46, 0x53, 0x4E, 0x71, 0x62, 0x34, 0x56, 0x6A, 0x4D, 0x49, 0x44, 0x77, 0x31, 0x5A, 0x34, 0x66, 0x4B, 0x52, 0x7A, ++ 0x43, 0x0A, 0x62, 0x4C, 0x42, 0x51, 0x57, 0x56, 0x32, 0x51, 0x57, 0x7A, 0x75, 0x6F, 0x44, 0x54, 0x44, 0x50, 0x76, 0x33, 0x31, 0x2F, 0x7A, 0x76, 0x47, 0x64, 0x67, 0x37, 0x33, 0x4A, 0x52, 0x6D, 0x34, 0x67, 0x70, 0x76, 0x6C, 0x68, 0x55, 0x62, ++ 0x6F, 0x68, 0x4C, 0x33, 0x75, 0x2B, 0x70, 0x52, 0x56, 0x6A, 0x6F, 0x64, 0x53, 0x56, 0x68, 0x2F, 0x47, 0x65, 0x75, 0x66, 0x4F, 0x4A, 0x38, 0x7A, 0x32, 0x46, 0x75, 0x4C, 0x6A, 0x62, 0x76, 0x72, 0x57, 0x35, 0x4B, 0x66, 0x6E, 0x61, 0x0A, 0x4E, ++ 0x77, 0x55, 0x41, 0x53, 0x5A, 0x51, 0x44, 0x68, 0x45, 0x54, 0x6E, 0x76, 0x30, 0x4D, 0x78, 0x7A, 0x33, 0x57, 0x4C, 0x4A, 0x64, 0x48, 0x30, 0x70, 0x6D, 0x54, 0x31, 0x6B, 0x76, 0x61, 0x72, 0x42, 0x65, 0x73, 0x39, 0x36, 0x61, 0x55, 0x4C, 0x4E, ++ 0x6D, 0x4C, 0x61, 0x7A, 0x41, 0x5A, 0x66, 0x4E, 0x6F, 0x75, 0x32, 0x58, 0x6A, 0x47, 0x34, 0x4B, 0x76, 0x74, 0x65, 0x39, 0x6E, 0x48, 0x66, 0x52, 0x43, 0x61, 0x65, 0x78, 0x4F, 0x59, 0x4E, 0x6B, 0x62, 0x51, 0x75, 0x0A, 0x64, 0x5A, 0x57, 0x41, ++ 0x55, 0x57, 0x70, 0x4C, 0x4D, 0x4B, 0x61, 0x77, 0x59, 0x71, 0x47, 0x54, 0x38, 0x5A, 0x76, 0x59, 0x7A, 0x73, 0x52, 0x6A, 0x64, 0x54, 0x39, 0x5A, 0x52, 0x37, 0x45, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, ++ 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x65, 0x63, 0x20, 0x65, 0x2D, 0x53, 0x7A, 0x69, 0x67, 0x6E, 0x6F, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, ++ 0x41, 0x20, 0x32, 0x30, 0x30, 0x39, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, ++ 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x45, 0x43, 0x6A, 0x43, 0x43, 0x41, 0x76, 0x4B, 0x67, 0x41, 0x77, ++ 0x49, 0x42, 0x41, 0x67, 0x49, 0x4A, 0x41, 0x4D, 0x4A, 0x2B, 0x51, 0x77, 0x52, 0x4F, 0x52, 0x7A, 0x38, 0x5A, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x43, 0x77, 0x55, 0x41, 0x4D, 0x49, ++ 0x47, 0x43, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x49, 0x56, 0x54, 0x45, 0x52, 0x0A, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x77, 0x77, 0x49, 0x51, 0x6E, 0x56, 0x6B, 0x59, ++ 0x58, 0x42, 0x6C, 0x63, 0x33, 0x51, 0x78, 0x46, 0x6A, 0x41, 0x55, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x4D, 0x44, 0x55, 0x31, 0x70, 0x59, 0x33, 0x4A, 0x76, 0x63, 0x32, 0x56, 0x6A, 0x49, 0x45, 0x78, 0x30, 0x5A, 0x43, 0x34, 0x78, 0x4A, ++ 0x7A, 0x41, 0x6C, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x4D, 0x48, 0x6B, 0x31, 0x70, 0x59, 0x33, 0x4A, 0x76, 0x0A, 0x63, 0x32, 0x56, 0x6A, 0x49, 0x47, 0x55, 0x74, 0x55, 0x33, 0x70, 0x70, 0x5A, 0x32, 0x35, 0x76, 0x49, 0x46, 0x4A, 0x76, ++ 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x67, 0x4D, 0x6A, 0x41, 0x77, 0x4F, 0x54, 0x45, 0x66, 0x4D, 0x42, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x4A, 0x41, 0x52, 0x59, 0x51, 0x61, 0x57, 0x35, 0x6D, ++ 0x62, 0x30, 0x42, 0x6C, 0x4C, 0x58, 0x4E, 0x36, 0x61, 0x57, 0x64, 0x75, 0x62, 0x79, 0x35, 0x6F, 0x0A, 0x64, 0x54, 0x41, 0x65, 0x46, 0x77, 0x30, 0x77, 0x4F, 0x54, 0x41, 0x32, 0x4D, 0x54, 0x59, 0x78, 0x4D, 0x54, 0x4D, 0x77, 0x4D, 0x54, 0x68, ++ 0x61, 0x46, 0x77, 0x30, 0x79, 0x4F, 0x54, 0x45, 0x79, 0x4D, 0x7A, 0x41, 0x78, 0x4D, 0x54, 0x4D, 0x77, 0x4D, 0x54, 0x68, 0x61, 0x4D, 0x49, 0x47, 0x43, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, ++ 0x49, 0x56, 0x54, 0x45, 0x52, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x45, 0x0A, 0x42, 0x77, 0x77, 0x49, 0x51, 0x6E, 0x56, 0x6B, 0x59, 0x58, 0x42, 0x6C, 0x63, 0x33, 0x51, 0x78, 0x46, 0x6A, 0x41, 0x55, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, ++ 0x6F, 0x4D, 0x44, 0x55, 0x31, 0x70, 0x59, 0x33, 0x4A, 0x76, 0x63, 0x32, 0x56, 0x6A, 0x49, 0x45, 0x78, 0x30, 0x5A, 0x43, 0x34, 0x78, 0x4A, 0x7A, 0x41, 0x6C, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x4D, 0x48, 0x6B, 0x31, 0x70, 0x59, 0x33, ++ 0x4A, 0x76, 0x63, 0x32, 0x56, 0x6A, 0x49, 0x47, 0x55, 0x74, 0x0A, 0x55, 0x33, 0x70, 0x70, 0x5A, 0x32, 0x35, 0x76, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x67, 0x4D, 0x6A, 0x41, 0x77, 0x4F, 0x54, 0x45, 0x66, 0x4D, ++ 0x42, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x4A, 0x41, 0x52, 0x59, 0x51, 0x61, 0x57, 0x35, 0x6D, 0x62, 0x30, 0x42, 0x6C, 0x4C, 0x58, 0x4E, 0x36, 0x61, 0x57, 0x64, 0x75, 0x62, 0x79, 0x35, 0x6F, 0x64, ++ 0x54, 0x43, 0x43, 0x41, 0x53, 0x49, 0x77, 0x0A, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x45, 0x50, 0x41, 0x44, 0x43, 0x43, 0x41, 0x51, 0x6F, 0x43, ++ 0x67, 0x67, 0x45, 0x42, 0x41, 0x4F, 0x6E, 0x34, 0x6A, 0x2F, 0x4E, 0x6A, 0x72, 0x64, 0x71, 0x47, 0x32, 0x4B, 0x66, 0x67, 0x51, 0x76, 0x76, 0x50, 0x6B, 0x64, 0x36, 0x6D, 0x4A, 0x76, 0x69, 0x5A, 0x70, 0x57, 0x4E, 0x77, 0x72, 0x5A, 0x75, 0x75, ++ 0x79, 0x6A, 0x4E, 0x41, 0x0A, 0x66, 0x57, 0x32, 0x57, 0x62, 0x71, 0x45, 0x4F, 0x52, 0x4F, 0x37, 0x68, 0x45, 0x35, 0x32, 0x55, 0x51, 0x6C, 0x4B, 0x61, 0x76, 0x58, 0x57, 0x46, 0x64, 0x43, 0x79, 0x6F, 0x44, 0x68, 0x32, 0x54, 0x74, 0x68, 0x69, ++ 0x33, 0x6A, 0x43, 0x79, 0x6F, 0x7A, 0x2F, 0x74, 0x63, 0x63, 0x62, 0x6E, 0x61, 0x37, 0x50, 0x37, 0x6F, 0x66, 0x6F, 0x2F, 0x6B, 0x4C, 0x78, 0x32, 0x79, 0x71, 0x48, 0x57, 0x48, 0x32, 0x4C, 0x65, 0x68, 0x35, 0x54, 0x76, 0x50, 0x6D, 0x55, 0x70, ++ 0x47, 0x0A, 0x30, 0x49, 0x4D, 0x5A, 0x66, 0x63, 0x43, 0x68, 0x45, 0x68, 0x79, 0x56, 0x62, 0x55, 0x72, 0x30, 0x32, 0x4D, 0x65, 0x6C, 0x54, 0x54, 0x4D, 0x75, 0x68, 0x54, 0x6C, 0x41, 0x64, 0x58, 0x34, 0x55, 0x66, 0x49, 0x41, 0x53, 0x6D, 0x46, ++ 0x44, 0x48, 0x51, 0x57, 0x65, 0x34, 0x6F, 0x49, 0x42, 0x68, 0x56, 0x4B, 0x5A, 0x73, 0x54, 0x68, 0x2F, 0x67, 0x6E, 0x51, 0x34, 0x48, 0x36, 0x63, 0x6D, 0x36, 0x4D, 0x2B, 0x66, 0x2B, 0x77, 0x46, 0x55, 0x6F, 0x4C, 0x41, 0x4B, 0x41, 0x0A, 0x70, ++ 0x78, 0x6E, 0x31, 0x6E, 0x74, 0x78, 0x56, 0x55, 0x77, 0x4F, 0x58, 0x65, 0x77, 0x64, 0x49, 0x2F, 0x35, 0x6E, 0x37, 0x4E, 0x34, 0x6F, 0x6B, 0x78, 0x46, 0x6E, 0x4D, 0x55, 0x42, 0x42, 0x6A, 0x6A, 0x71, 0x71, 0x70, 0x47, 0x72, 0x43, 0x45, 0x47, ++ 0x6F, 0x62, 0x35, 0x58, 0x37, 0x75, 0x78, 0x55, 0x47, 0x36, 0x6B, 0x30, 0x51, 0x72, 0x4D, 0x31, 0x58, 0x46, 0x2B, 0x48, 0x36, 0x63, 0x62, 0x66, 0x50, 0x56, 0x54, 0x62, 0x69, 0x4A, 0x66, 0x79, 0x79, 0x76, 0x6D, 0x0A, 0x31, 0x48, 0x78, 0x64, ++ 0x72, 0x74, 0x62, 0x43, 0x78, 0x6B, 0x7A, 0x6C, 0x42, 0x51, 0x48, 0x5A, 0x37, 0x56, 0x66, 0x38, 0x77, 0x53, 0x4E, 0x35, 0x2F, 0x50, 0x72, 0x49, 0x4A, 0x49, 0x4F, 0x56, 0x38, 0x37, 0x56, 0x71, 0x55, 0x51, 0x48, 0x51, 0x64, 0x39, 0x62, 0x70, ++ 0x45, 0x71, 0x48, 0x35, 0x47, 0x6F, 0x50, 0x37, 0x67, 0x68, 0x75, 0x35, 0x73, 0x4A, 0x66, 0x30, 0x64, 0x67, 0x59, 0x7A, 0x51, 0x30, 0x6D, 0x67, 0x2F, 0x77, 0x75, 0x31, 0x2B, 0x72, 0x55, 0x43, 0x0A, 0x41, 0x77, 0x45, 0x41, 0x41, 0x61, 0x4F, ++ 0x42, 0x67, 0x44, 0x42, 0x2B, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x41, 0x51, 0x48, ++ 0x2F, 0x42, 0x41, 0x51, 0x44, 0x41, 0x67, 0x45, 0x47, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x54, 0x4C, 0x44, 0x38, 0x62, 0x66, 0x0A, 0x51, 0x6B, 0x50, 0x4D, 0x50, 0x63, 0x75, 0x31, 0x53, 0x43, ++ 0x4F, 0x68, 0x47, 0x6E, 0x71, 0x6D, 0x4B, 0x72, 0x73, 0x30, 0x61, 0x44, 0x41, 0x66, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x53, 0x4D, 0x45, 0x47, 0x44, 0x41, 0x57, 0x67, 0x42, 0x54, 0x4C, 0x44, 0x38, 0x62, 0x66, 0x51, 0x6B, 0x50, 0x4D, 0x50, 0x63, ++ 0x75, 0x31, 0x53, 0x43, 0x4F, 0x68, 0x47, 0x6E, 0x71, 0x6D, 0x4B, 0x72, 0x73, 0x30, 0x61, 0x44, 0x41, 0x62, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x52, 0x45, 0x45, 0x0A, 0x46, 0x44, 0x41, 0x53, 0x67, 0x52, 0x42, 0x70, 0x62, 0x6D, 0x5A, 0x76, 0x51, ++ 0x47, 0x55, 0x74, 0x63, 0x33, 0x70, 0x70, 0x5A, 0x32, 0x35, 0x76, 0x4C, 0x6D, 0x68, 0x31, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x43, 0x77, 0x55, 0x41, 0x41, 0x34, 0x49, 0x42, 0x41, ++ 0x51, 0x44, 0x4A, 0x30, 0x51, 0x35, 0x65, 0x4C, 0x74, 0x58, 0x4D, 0x73, 0x33, 0x77, 0x2B, 0x79, 0x2F, 0x77, 0x39, 0x2F, 0x77, 0x30, 0x6F, 0x0A, 0x6C, 0x5A, 0x4D, 0x45, 0x79, 0x4C, 0x2F, 0x61, 0x7A, 0x58, 0x6D, 0x34, 0x51, 0x35, 0x44, 0x77, ++ 0x70, 0x4C, 0x37, 0x76, 0x38, 0x75, 0x38, 0x68, 0x6D, 0x4C, 0x7A, 0x55, 0x31, 0x46, 0x30, 0x47, 0x39, 0x75, 0x35, 0x43, 0x37, 0x44, 0x42, 0x73, 0x6F, 0x4B, 0x71, 0x70, 0x79, 0x76, 0x47, 0x76, 0x69, 0x76, 0x6F, 0x2F, 0x43, 0x33, 0x4E, 0x71, ++ 0x50, 0x75, 0x6F, 0x75, 0x51, 0x48, 0x34, 0x66, 0x72, 0x6C, 0x52, 0x68, 0x65, 0x65, 0x73, 0x75, 0x43, 0x44, 0x66, 0x58, 0x0A, 0x49, 0x2F, 0x4F, 0x4D, 0x6E, 0x37, 0x34, 0x64, 0x73, 0x65, 0x47, 0x6B, 0x64, 0x64, 0x75, 0x67, 0x34, 0x6C, 0x51, ++ 0x55, 0x73, 0x62, 0x6F, 0x63, 0x4B, 0x61, 0x51, 0x59, 0x39, 0x68, 0x4B, 0x36, 0x6F, 0x68, 0x51, 0x55, 0x34, 0x7A, 0x45, 0x31, 0x79, 0x45, 0x44, 0x2F, 0x74, 0x2B, 0x41, 0x46, 0x64, 0x6C, 0x66, 0x42, 0x48, 0x46, 0x6E, 0x79, 0x2B, 0x4C, 0x2F, ++ 0x6B, 0x37, 0x53, 0x56, 0x69, 0x58, 0x49, 0x54, 0x77, 0x66, 0x6E, 0x34, 0x66, 0x73, 0x37, 0x37, 0x35, 0x0A, 0x74, 0x79, 0x45, 0x52, 0x7A, 0x41, 0x4D, 0x42, 0x56, 0x6E, 0x43, 0x6E, 0x45, 0x4A, 0x49, 0x65, 0x47, 0x7A, 0x53, 0x42, 0x48, 0x71, ++ 0x32, 0x63, 0x47, 0x73, 0x4D, 0x45, 0x50, 0x4F, 0x30, 0x43, 0x59, 0x64, 0x59, 0x65, 0x42, 0x76, 0x4E, 0x66, 0x4F, 0x6F, 0x66, 0x79, 0x4B, 0x2F, 0x46, 0x46, 0x68, 0x2B, 0x55, 0x39, 0x72, 0x4E, 0x48, 0x48, 0x56, 0x34, 0x53, 0x39, 0x61, 0x36, ++ 0x37, 0x63, 0x32, 0x50, 0x6D, 0x32, 0x47, 0x32, 0x4A, 0x77, 0x43, 0x7A, 0x30, 0x32, 0x0A, 0x79, 0x55, 0x4C, 0x79, 0x4D, 0x74, 0x64, 0x36, 0x59, 0x65, 0x62, 0x53, 0x32, 0x7A, 0x33, 0x50, 0x79, 0x4B, 0x6E, 0x4A, 0x6D, 0x39, 0x7A, 0x62, 0x57, ++ 0x45, 0x54, 0x58, 0x62, 0x7A, 0x69, 0x76, 0x66, 0x33, 0x6A, 0x54, 0x6F, 0x36, 0x30, 0x61, 0x64, 0x62, 0x6F, 0x63, 0x77, 0x54, 0x5A, 0x38, 0x6A, 0x78, 0x35, 0x74, 0x48, 0x4D, 0x4E, 0x31, 0x52, 0x71, 0x34, 0x31, 0x42, 0x61, 0x62, 0x32, 0x58, ++ 0x44, 0x30, 0x68, 0x37, 0x6C, 0x62, 0x77, 0x79, 0x59, 0x49, 0x69, 0x0A, 0x4C, 0x58, 0x70, 0x55, 0x71, 0x33, 0x44, 0x44, 0x66, 0x53, 0x4A, 0x6C, 0x67, 0x6E, 0x43, 0x57, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, ++ 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x52, 0x33, 0x0A, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, ++ 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x44, 0x58, 0x7A, 0x43, 0x43, 0x41, 0x6B, 0x65, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x4C, 0x42, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x42, ++ 0x49, 0x56, 0x68, 0x54, 0x43, 0x4B, 0x49, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x42, 0x51, 0x41, 0x77, 0x54, 0x44, 0x45, 0x67, 0x4D, 0x42, 0x34, 0x47, 0x41, 0x31, 0x55, 0x45, ++ 0x43, 0x78, 0x4D, 0x58, 0x52, 0x32, 0x78, 0x76, 0x0A, 0x59, 0x6D, 0x46, 0x73, 0x55, 0x32, 0x6C, 0x6E, 0x62, 0x69, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x42, 0x49, 0x43, 0x30, 0x67, 0x55, 0x6A, 0x4D, 0x78, 0x45, 0x7A, 0x41, ++ 0x52, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x43, 0x6B, 0x64, 0x73, 0x62, 0x32, 0x4A, 0x68, 0x62, 0x46, 0x4E, 0x70, 0x5A, 0x32, 0x34, 0x78, 0x45, 0x7A, 0x41, 0x52, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x43, 0x6B, 0x64, ++ 0x73, 0x62, 0x32, 0x4A, 0x68, 0x0A, 0x62, 0x46, 0x4E, 0x70, 0x5A, 0x32, 0x34, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x44, 0x6B, 0x77, 0x4D, 0x7A, 0x45, 0x34, 0x4D, 0x54, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x57, 0x68, 0x63, 0x4E, 0x4D, 0x6A, ++ 0x6B, 0x77, 0x4D, 0x7A, 0x45, 0x34, 0x4D, 0x54, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x57, 0x6A, 0x42, 0x4D, 0x4D, 0x53, 0x41, 0x77, 0x48, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4C, 0x45, 0x78, 0x64, 0x48, 0x62, 0x47, 0x39, 0x69, 0x59, 0x57, ++ 0x78, 0x54, 0x0A, 0x61, 0x57, 0x64, 0x75, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x67, 0x4C, 0x53, 0x42, 0x53, 0x4D, 0x7A, 0x45, 0x54, 0x4D, 0x42, 0x45, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x4B, 0x52, ++ 0x32, 0x78, 0x76, 0x59, 0x6D, 0x46, 0x73, 0x55, 0x32, 0x6C, 0x6E, 0x62, 0x6A, 0x45, 0x54, 0x4D, 0x42, 0x45, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x4B, 0x52, 0x32, 0x78, 0x76, 0x59, 0x6D, 0x46, 0x73, 0x55, 0x32, 0x6C, 0x6E, 0x0A, ++ 0x62, 0x6A, 0x43, 0x43, 0x41, 0x53, 0x49, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x45, 0x50, 0x41, 0x44, 0x43, 0x43, 0x41, 0x51, 0x6F, 0x43, ++ 0x67, 0x67, 0x45, 0x42, 0x41, 0x4D, 0x77, 0x6C, 0x64, 0x70, 0x42, 0x35, 0x42, 0x6E, 0x67, 0x69, 0x46, 0x76, 0x58, 0x41, 0x67, 0x37, 0x61, 0x45, 0x79, 0x69, 0x69, 0x65, 0x2F, 0x51, 0x56, 0x32, 0x45, 0x63, 0x57, 0x74, 0x0A, 0x69, 0x48, 0x4C, ++ 0x38, 0x52, 0x67, 0x4A, 0x44, 0x78, 0x37, 0x4B, 0x4B, 0x6E, 0x51, 0x52, 0x66, 0x4A, 0x4D, 0x73, 0x75, 0x53, 0x2B, 0x46, 0x67, 0x67, 0x6B, 0x62, 0x68, 0x55, 0x71, 0x73, 0x4D, 0x67, 0x55, 0x64, 0x77, 0x62, 0x4E, 0x31, 0x6B, 0x30, 0x65, 0x76, ++ 0x31, 0x4C, 0x4B, 0x4D, 0x50, 0x67, 0x6A, 0x30, 0x4D, 0x4B, 0x36, 0x36, 0x58, 0x31, 0x37, 0x59, 0x55, 0x68, 0x68, 0x42, 0x35, 0x75, 0x7A, 0x73, 0x54, 0x67, 0x48, 0x65, 0x4D, 0x43, 0x4F, 0x46, 0x4A, 0x0A, 0x30, 0x6D, 0x70, 0x69, 0x4C, 0x78, ++ 0x39, 0x65, 0x2B, 0x70, 0x5A, 0x6F, 0x33, 0x34, 0x6B, 0x6E, 0x6C, 0x54, 0x69, 0x66, 0x42, 0x74, 0x63, 0x2B, 0x79, 0x63, 0x73, 0x6D, 0x57, 0x51, 0x31, 0x7A, 0x33, 0x72, 0x44, 0x49, 0x36, 0x53, 0x59, 0x4F, 0x67, 0x78, 0x58, 0x47, 0x37, 0x31, ++ 0x75, 0x4C, 0x30, 0x67, 0x52, 0x67, 0x79, 0x6B, 0x6D, 0x6D, 0x4B, 0x50, 0x5A, 0x70, 0x4F, 0x2F, 0x62, 0x4C, 0x79, 0x43, 0x69, 0x52, 0x35, 0x5A, 0x32, 0x4B, 0x59, 0x56, 0x63, 0x33, 0x0A, 0x72, 0x48, 0x51, 0x55, 0x33, 0x48, 0x54, 0x67, 0x4F, ++ 0x75, 0x35, 0x79, 0x4C, 0x79, 0x36, 0x63, 0x2B, 0x39, 0x43, 0x37, 0x76, 0x2F, 0x55, 0x39, 0x41, 0x4F, 0x45, 0x47, 0x4D, 0x2B, 0x69, 0x43, 0x4B, 0x36, 0x35, 0x54, 0x70, 0x6A, 0x6F, 0x57, 0x63, 0x34, 0x7A, 0x64, 0x51, 0x51, 0x34, 0x67, 0x4F, ++ 0x73, 0x43, 0x30, 0x70, 0x36, 0x48, 0x70, 0x73, 0x6B, 0x2B, 0x51, 0x4C, 0x6A, 0x4A, 0x67, 0x36, 0x56, 0x66, 0x4C, 0x75, 0x51, 0x53, 0x53, 0x61, 0x47, 0x6A, 0x6C, 0x0A, 0x4F, 0x43, 0x5A, 0x67, 0x64, 0x62, 0x4B, 0x66, 0x64, 0x2F, 0x2B, 0x52, ++ 0x46, 0x4F, 0x2B, 0x75, 0x49, 0x45, 0x6E, 0x38, 0x72, 0x55, 0x41, 0x56, 0x53, 0x4E, 0x45, 0x43, 0x4D, 0x57, 0x45, 0x5A, 0x58, 0x72, 0x69, 0x58, 0x37, 0x36, 0x31, 0x33, 0x74, 0x32, 0x53, 0x61, 0x65, 0x72, 0x39, 0x66, 0x77, 0x52, 0x50, 0x76, ++ 0x6D, 0x32, 0x4C, 0x37, 0x44, 0x57, 0x7A, 0x67, 0x56, 0x47, 0x6B, 0x57, 0x71, 0x51, 0x50, 0x61, 0x62, 0x75, 0x6D, 0x44, 0x6B, 0x33, 0x46, 0x32, 0x0A, 0x78, 0x6D, 0x6D, 0x46, 0x67, 0x68, 0x63, 0x43, 0x41, 0x77, 0x45, 0x41, 0x41, 0x61, 0x4E, ++ 0x43, 0x4D, 0x45, 0x41, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x51, 0x44, 0x41, 0x67, 0x45, 0x47, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, ++ 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x48, 0x51, 0x59, 0x44, 0x56, 0x52, 0x30, 0x4F, 0x42, 0x42, 0x59, 0x45, 0x0A, 0x46, 0x49, 0x2F, 0x77, 0x53, 0x33, 0x2B, 0x6F, 0x4C, 0x6B, 0x55, 0x6B, 0x72, 0x6B, 0x31, 0x51, 0x2B, 0x6D, ++ 0x4F, 0x61, 0x69, 0x39, 0x37, 0x69, 0x33, 0x52, 0x75, 0x38, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x43, 0x77, 0x55, 0x41, 0x41, 0x34, 0x49, 0x42, 0x41, 0x51, 0x42, 0x4C, 0x51, 0x4E, ++ 0x76, 0x41, 0x55, 0x4B, 0x72, 0x2B, 0x79, 0x41, 0x7A, 0x76, 0x39, 0x35, 0x5A, 0x55, 0x52, 0x55, 0x6D, 0x37, 0x0A, 0x6C, 0x67, 0x41, 0x4A, 0x51, 0x61, 0x79, 0x7A, 0x45, 0x34, 0x61, 0x47, 0x4B, 0x41, 0x63, 0x7A, 0x79, 0x6D, 0x76, 0x6D, 0x64, ++ 0x4C, 0x6D, 0x36, 0x41, 0x43, 0x32, 0x75, 0x70, 0x41, 0x72, 0x54, 0x39, 0x66, 0x48, 0x78, 0x44, 0x34, 0x71, 0x2F, 0x63, 0x32, 0x64, 0x4B, 0x67, 0x38, 0x64, 0x45, 0x65, 0x33, 0x6A, 0x67, 0x72, 0x32, 0x35, 0x73, 0x62, 0x77, 0x4D, 0x70, 0x6A, ++ 0x6A, 0x4D, 0x35, 0x52, 0x63, 0x4F, 0x4F, 0x35, 0x4C, 0x6C, 0x58, 0x62, 0x4B, 0x72, 0x38, 0x0A, 0x45, 0x70, 0x62, 0x73, 0x55, 0x38, 0x59, 0x74, 0x35, 0x43, 0x52, 0x73, 0x75, 0x5A, 0x52, 0x6A, 0x2B, 0x39, 0x78, 0x54, 0x61, 0x47, 0x64, 0x57, ++ 0x50, 0x6F, 0x4F, 0x34, 0x7A, 0x7A, 0x55, 0x68, 0x77, 0x38, 0x6C, 0x6F, 0x2F, 0x73, 0x37, 0x61, 0x77, 0x6C, 0x4F, 0x71, 0x7A, 0x4A, 0x43, 0x4B, 0x36, 0x66, 0x42, 0x64, 0x52, 0x6F, 0x79, 0x56, 0x33, 0x58, 0x70, 0x59, 0x4B, 0x42, 0x6F, 0x76, ++ 0x48, 0x64, 0x37, 0x4E, 0x41, 0x44, 0x64, 0x42, 0x6A, 0x2B, 0x31, 0x45, 0x0A, 0x62, 0x64, 0x64, 0x54, 0x4B, 0x4A, 0x64, 0x2B, 0x38, 0x32, 0x63, 0x45, 0x48, 0x68, 0x58, 0x58, 0x69, 0x70, 0x61, 0x30, 0x30, 0x39, 0x35, 0x4D, 0x4A, 0x36, 0x52, ++ 0x4D, 0x47, 0x33, 0x4E, 0x7A, 0x64, 0x76, 0x51, 0x58, 0x6D, 0x63, 0x49, 0x66, 0x65, 0x67, 0x37, 0x6A, 0x4C, 0x51, 0x69, 0x74, 0x43, 0x68, 0x77, 0x73, 0x2F, 0x7A, 0x79, 0x72, 0x56, 0x51, 0x34, 0x50, 0x6B, 0x58, 0x34, 0x32, 0x36, 0x38, 0x4E, ++ 0x58, 0x53, 0x62, 0x37, 0x68, 0x4C, 0x69, 0x31, 0x38, 0x0A, 0x59, 0x49, 0x76, 0x44, 0x51, 0x56, 0x45, 0x54, 0x49, 0x35, 0x33, 0x4F, 0x39, 0x7A, 0x4A, 0x72, 0x6C, 0x41, 0x47, 0x6F, 0x6D, 0x65, 0x63, 0x73, 0x4D, 0x78, 0x38, 0x36, 0x4F, 0x79, ++ 0x58, 0x53, 0x68, 0x6B, 0x44, 0x4F, 0x4F, 0x79, 0x79, 0x47, 0x65, 0x4D, 0x6C, 0x68, 0x4C, 0x78, 0x53, 0x36, 0x37, 0x74, 0x74, 0x56, 0x62, 0x39, 0x2B, 0x45, 0x37, 0x67, 0x55, 0x4A, 0x54, 0x62, 0x30, 0x6F, 0x32, 0x48, 0x4C, 0x4F, 0x30, 0x32, ++ 0x4A, 0x51, 0x5A, 0x52, 0x37, 0x72, 0x0A, 0x6B, 0x70, 0x65, 0x44, 0x4D, 0x64, 0x6D, 0x7A, 0x74, 0x63, 0x70, 0x48, 0x57, 0x44, 0x39, 0x66, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, ++ 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x49, 0x7A, 0x65, 0x6E, 0x70, 0x65, 0x2E, 0x63, 0x6F, 0x6D, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, ++ 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x38, 0x54, 0x43, 0x43, 0x41, 0x39, 0x6D, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, ++ 0x51, 0x41, 0x4C, 0x43, 0x33, 0x57, 0x68, 0x5A, 0x49, 0x58, 0x37, 0x2F, 0x68, 0x79, 0x2F, 0x57, 0x4C, 0x31, 0x78, 0x6E, 0x6D, 0x66, 0x54, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, ++ 0x46, 0x41, 0x44, 0x41, 0x34, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x0A, 0x45, 0x77, 0x4A, 0x46, 0x55, 0x7A, 0x45, 0x55, 0x4D, 0x42, 0x49, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, 0x4C, 0x53, 0x56, ++ 0x70, 0x46, 0x54, 0x6C, 0x42, 0x46, 0x49, 0x46, 0x4D, 0x75, 0x51, 0x53, 0x34, 0x78, 0x45, 0x7A, 0x41, 0x52, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x4D, 0x43, 0x6B, 0x6C, 0x36, 0x5A, 0x57, 0x35, 0x77, 0x5A, 0x53, 0x35, 0x6A, 0x62, 0x32, ++ 0x30, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x44, 0x63, 0x78, 0x4D, 0x6A, 0x45, 0x7A, 0x0A, 0x4D, 0x54, 0x4D, 0x77, 0x4F, 0x44, 0x49, 0x34, 0x57, 0x68, 0x63, 0x4E, 0x4D, 0x7A, 0x63, 0x78, 0x4D, 0x6A, 0x45, 0x7A, 0x4D, 0x44, 0x67, 0x79, 0x4E, ++ 0x7A, 0x49, 0x31, 0x57, 0x6A, 0x41, 0x34, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x46, 0x55, 0x7A, 0x45, 0x55, 0x4D, 0x42, 0x49, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, 0x4C, 0x53, ++ 0x56, 0x70, 0x46, 0x54, 0x6C, 0x42, 0x46, 0x49, 0x46, 0x4D, 0x75, 0x0A, 0x51, 0x53, 0x34, 0x78, 0x45, 0x7A, 0x41, 0x52, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x4D, 0x43, 0x6B, 0x6C, 0x36, 0x5A, 0x57, 0x35, 0x77, 0x5A, 0x53, 0x35, 0x6A, ++ 0x62, 0x32, 0x30, 0x77, 0x67, 0x67, 0x49, 0x69, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x49, 0x4B, ++ 0x41, 0x6F, 0x49, 0x43, 0x41, 0x51, 0x44, 0x4A, 0x0A, 0x30, 0x33, 0x72, 0x4B, 0x44, 0x78, 0x36, 0x73, 0x70, 0x34, 0x62, 0x6F, 0x46, 0x6D, 0x56, 0x71, 0x73, 0x63, 0x49, 0x62, 0x52, 0x54, 0x4A, 0x78, 0x6C, 0x64, 0x6E, 0x2B, 0x45, 0x46, 0x76, ++ 0x4D, 0x72, 0x2B, 0x65, 0x6C, 0x65, 0x51, 0x47, 0x50, 0x69, 0x63, 0x50, 0x4B, 0x38, 0x6C, 0x56, 0x78, 0x39, 0x33, 0x65, 0x2B, 0x64, 0x35, 0x54, 0x7A, 0x63, 0x71, 0x51, 0x73, 0x52, 0x4E, 0x69, 0x65, 0x6B, 0x70, 0x73, 0x55, 0x4F, 0x71, 0x48, ++ 0x6E, 0x4A, 0x4A, 0x41, 0x4B, 0x0A, 0x43, 0x6C, 0x61, 0x4F, 0x78, 0x64, 0x67, 0x6D, 0x6C, 0x4F, 0x48, 0x5A, 0x53, 0x4F, 0x45, 0x74, 0x50, 0x74, 0x6F, 0x4B, 0x63, 0x74, 0x32, 0x6A, 0x6D, 0x52, 0x58, 0x61, 0x67, 0x61, 0x4B, 0x48, 0x39, 0x48, ++ 0x74, 0x75, 0x4A, 0x6E, 0x65, 0x4A, 0x57, 0x4B, 0x33, 0x57, 0x36, 0x77, 0x79, 0x79, 0x51, 0x58, 0x70, 0x7A, 0x62, 0x6D, 0x33, 0x62, 0x65, 0x6E, 0x68, 0x42, 0x36, 0x51, 0x69, 0x49, 0x45, 0x6E, 0x36, 0x48, 0x4C, 0x6D, 0x59, 0x52, 0x59, 0x32, ++ 0x78, 0x55, 0x0A, 0x2B, 0x7A, 0x79, 0x64, 0x63, 0x73, 0x43, 0x38, 0x4C, 0x76, 0x2F, 0x43, 0x74, 0x39, 0x30, 0x4E, 0x64, 0x75, 0x4D, 0x36, 0x31, 0x2F, 0x65, 0x30, 0x61, 0x4C, 0x36, 0x69, 0x39, 0x65, 0x4F, 0x42, 0x62, 0x73, 0x46, 0x47, 0x62, ++ 0x31, 0x32, 0x4E, 0x34, 0x45, 0x33, 0x47, 0x56, 0x46, 0x57, 0x4A, 0x47, 0x6A, 0x4D, 0x78, 0x43, 0x72, 0x46, 0x58, 0x75, 0x61, 0x4F, 0x4B, 0x6D, 0x4D, 0x50, 0x73, 0x4F, 0x7A, 0x54, 0x46, 0x6C, 0x55, 0x46, 0x70, 0x66, 0x6E, 0x58, 0x43, 0x0A, ++ 0x50, 0x43, 0x44, 0x46, 0x59, 0x62, 0x70, 0x52, 0x52, 0x36, 0x41, 0x67, 0x6B, 0x4A, 0x4F, 0x68, 0x6B, 0x45, 0x76, 0x7A, 0x54, 0x6E, 0x79, 0x46, 0x52, 0x56, 0x53, 0x61, 0x30, 0x51, 0x55, 0x6D, 0x51, 0x62, 0x43, 0x31, 0x54, 0x52, 0x30, 0x7A, ++ 0x76, 0x73, 0x51, 0x44, 0x79, 0x43, 0x56, 0x38, 0x77, 0x58, 0x44, 0x62, 0x4F, 0x2F, 0x51, 0x4A, 0x4C, 0x56, 0x51, 0x6E, 0x53, 0x4B, 0x77, 0x76, 0x34, 0x63, 0x53, 0x73, 0x50, 0x73, 0x6A, 0x4C, 0x6B, 0x6B, 0x78, 0x54, 0x0A, 0x4F, 0x54, 0x63, ++ 0x6A, 0x37, 0x4E, 0x4D, 0x42, 0x2B, 0x65, 0x41, 0x4A, 0x52, 0x45, 0x31, 0x4E, 0x5A, 0x4D, 0x44, 0x68, 0x44, 0x56, 0x71, 0x48, 0x49, 0x72, 0x79, 0x74, 0x47, 0x36, 0x50, 0x2B, 0x4A, 0x72, 0x55, 0x56, 0x38, 0x36, 0x66, 0x38, 0x68, 0x42, 0x6E, ++ 0x70, 0x37, 0x4B, 0x47, 0x49, 0x74, 0x45, 0x52, 0x70, 0x68, 0x49, 0x50, 0x7A, 0x69, 0x64, 0x46, 0x30, 0x42, 0x71, 0x6E, 0x4D, 0x43, 0x39, 0x62, 0x43, 0x33, 0x69, 0x65, 0x46, 0x55, 0x43, 0x62, 0x4B, 0x0A, 0x46, 0x37, 0x6A, 0x4A, 0x65, 0x6F, ++ 0x64, 0x57, 0x4C, 0x42, 0x6F, 0x42, 0x48, 0x6D, 0x79, 0x2B, 0x45, 0x36, 0x30, 0x51, 0x72, 0x4C, 0x55, 0x6B, 0x39, 0x54, 0x69, 0x52, 0x6F, 0x64, 0x5A, 0x4C, 0x32, 0x76, 0x47, 0x37, 0x30, 0x74, 0x35, 0x48, 0x74, 0x66, 0x47, 0x38, 0x67, 0x66, ++ 0x5A, 0x5A, 0x61, 0x38, 0x38, 0x5A, 0x55, 0x2B, 0x6D, 0x4E, 0x46, 0x63, 0x74, 0x4B, 0x79, 0x36, 0x6C, 0x76, 0x52, 0x4F, 0x55, 0x62, 0x51, 0x63, 0x2F, 0x68, 0x68, 0x71, 0x66, 0x4B, 0x0A, 0x30, 0x47, 0x71, 0x66, 0x76, 0x45, 0x79, 0x4E, 0x42, ++ 0x6A, 0x4E, 0x61, 0x6F, 0x6F, 0x58, 0x6C, 0x6B, 0x44, 0x57, 0x67, 0x59, 0x6C, 0x77, 0x57, 0x54, 0x76, 0x44, 0x6A, 0x6F, 0x76, 0x6F, 0x44, 0x47, 0x72, 0x51, 0x73, 0x63, 0x62, 0x4E, 0x59, 0x4C, 0x4E, 0x35, 0x37, 0x43, 0x39, 0x73, 0x61, 0x44, ++ 0x2B, 0x76, 0x65, 0x49, 0x52, 0x38, 0x47, 0x64, 0x77, 0x59, 0x44, 0x73, 0x4D, 0x6E, 0x76, 0x6D, 0x66, 0x7A, 0x41, 0x75, 0x55, 0x38, 0x4C, 0x68, 0x69, 0x6A, 0x2B, 0x0A, 0x30, 0x72, 0x6E, 0x71, 0x34, 0x39, 0x71, 0x6C, 0x77, 0x30, 0x64, 0x70, ++ 0x45, 0x75, 0x44, 0x62, 0x38, 0x50, 0x59, 0x5A, 0x69, 0x2B, 0x31, 0x37, 0x63, 0x4E, 0x63, 0x43, 0x31, 0x75, 0x32, 0x48, 0x47, 0x43, 0x67, 0x73, 0x42, 0x43, 0x52, 0x4D, 0x64, 0x2B, 0x52, 0x49, 0x69, 0x68, 0x72, 0x47, 0x4F, 0x35, 0x72, 0x55, ++ 0x44, 0x38, 0x72, 0x36, 0x64, 0x64, 0x49, 0x42, 0x51, 0x46, 0x71, 0x4E, 0x65, 0x62, 0x2B, 0x4C, 0x7A, 0x30, 0x76, 0x50, 0x71, 0x68, 0x62, 0x42, 0x0A, 0x6C, 0x65, 0x53, 0x74, 0x54, 0x49, 0x6F, 0x2B, 0x46, 0x35, 0x48, 0x55, 0x73, 0x57, 0x4C, ++ 0x6C, 0x67, 0x75, 0x57, 0x41, 0x42, 0x4B, 0x51, 0x44, 0x66, 0x6F, 0x32, 0x2F, 0x32, 0x6E, 0x2B, 0x69, 0x44, 0x35, 0x64, 0x50, 0x44, 0x4E, 0x4D, 0x4E, 0x2B, 0x39, 0x66, 0x52, 0x35, 0x58, 0x4A, 0x2B, 0x48, 0x4D, 0x68, 0x33, 0x2F, 0x31, 0x75, ++ 0x61, 0x44, 0x37, 0x65, 0x75, 0x42, 0x55, 0x62, 0x6C, 0x38, 0x61, 0x67, 0x57, 0x37, 0x45, 0x65, 0x6B, 0x46, 0x77, 0x49, 0x44, 0x0A, 0x41, 0x51, 0x41, 0x42, 0x6F, 0x34, 0x48, 0x32, 0x4D, 0x49, 0x48, 0x7A, 0x4D, 0x49, 0x47, 0x77, 0x42, 0x67, ++ 0x4E, 0x56, 0x48, 0x52, 0x45, 0x45, 0x67, 0x61, 0x67, 0x77, 0x67, 0x61, 0x57, 0x42, 0x44, 0x32, 0x6C, 0x75, 0x5A, 0x6D, 0x39, 0x41, 0x61, 0x58, 0x70, 0x6C, 0x62, 0x6E, 0x42, 0x6C, 0x4C, 0x6D, 0x4E, 0x76, 0x62, 0x61, 0x53, 0x42, 0x6B, 0x54, ++ 0x43, 0x42, 0x6A, 0x6A, 0x46, 0x48, 0x4D, 0x45, 0x55, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, 0x2B, 0x0A, 0x53, 0x56, 0x70, 0x46, 0x54, 0x6C, 0x42, 0x46, 0x49, 0x46, 0x4D, 0x75, 0x51, 0x53, 0x34, 0x67, 0x4C, 0x53, 0x42, 0x44, 0x53, ++ 0x55, 0x59, 0x67, 0x51, 0x54, 0x41, 0x78, 0x4D, 0x7A, 0x4D, 0x33, 0x4D, 0x6A, 0x59, 0x77, 0x4C, 0x56, 0x4A, 0x4E, 0x5A, 0x58, 0x4A, 0x6A, 0x4C, 0x6C, 0x5A, 0x70, 0x64, 0x47, 0x39, 0x79, 0x61, 0x57, 0x45, 0x74, 0x52, 0x32, 0x46, 0x7A, 0x64, ++ 0x47, 0x56, 0x70, 0x65, 0x69, 0x42, 0x55, 0x4D, 0x54, 0x41, 0x31, 0x4E, 0x53, 0x42, 0x47, 0x0A, 0x4E, 0x6A, 0x49, 0x67, 0x55, 0x7A, 0x67, 0x78, 0x51, 0x7A, 0x42, 0x42, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6B, 0x4D, 0x4F, 0x6B, 0x46, 0x32, ++ 0x5A, 0x47, 0x45, 0x67, 0x5A, 0x47, 0x56, 0x73, 0x49, 0x45, 0x31, 0x6C, 0x5A, 0x47, 0x6C, 0x30, 0x5A, 0x58, 0x4A, 0x79, 0x59, 0x57, 0x35, 0x6C, 0x62, 0x79, 0x42, 0x46, 0x64, 0x47, 0x39, 0x79, 0x59, 0x6D, 0x6C, 0x6B, 0x5A, 0x57, 0x45, 0x67, ++ 0x4D, 0x54, 0x51, 0x67, 0x4C, 0x53, 0x41, 0x77, 0x4D, 0x54, 0x41, 0x78, 0x0A, 0x4D, 0x43, 0x42, 0x57, 0x61, 0x58, 0x52, 0x76, 0x63, 0x6D, 0x6C, 0x68, 0x4C, 0x55, 0x64, 0x68, 0x63, 0x33, 0x52, 0x6C, 0x61, 0x58, 0x6F, 0x77, 0x44, 0x77, 0x59, ++ 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x51, 0x59, ++ 0x77, 0x48, 0x51, 0x59, 0x44, 0x56, 0x52, 0x30, 0x4F, 0x0A, 0x42, 0x42, 0x59, 0x45, 0x46, 0x42, 0x30, 0x63, 0x5A, 0x51, 0x36, 0x6F, 0x38, 0x69, 0x56, 0x37, 0x74, 0x4A, 0x48, 0x50, 0x35, 0x4C, 0x47, 0x78, 0x35, 0x72, 0x31, 0x56, 0x64, 0x47, ++ 0x77, 0x46, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x43, 0x77, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x41, 0x51, 0x42, 0x34, 0x70, 0x67, 0x77, 0x57, 0x53, 0x70, 0x39, 0x4D, 0x69, 0x44, ++ 0x72, 0x41, 0x79, 0x77, 0x36, 0x6C, 0x0A, 0x46, 0x6E, 0x32, 0x66, 0x75, 0x55, 0x68, 0x66, 0x47, 0x49, 0x38, 0x4E, 0x59, 0x6A, 0x62, 0x32, 0x7A, 0x52, 0x6C, 0x72, 0x72, 0x4B, 0x76, 0x56, 0x39, 0x70, 0x46, 0x39, 0x72, 0x6E, 0x48, 0x7A, 0x50, ++ 0x37, 0x4D, 0x4F, 0x65, 0x49, 0x57, 0x62, 0x6C, 0x61, 0x51, 0x6E, 0x49, 0x55, 0x64, 0x43, 0x53, 0x6E, 0x78, 0x49, 0x4F, 0x76, 0x56, 0x46, 0x66, 0x4C, 0x4D, 0x4D, 0x6A, 0x6C, 0x46, 0x34, 0x72, 0x4A, 0x55, 0x54, 0x33, 0x73, 0x62, 0x39, 0x66, ++ 0x62, 0x67, 0x61, 0x0A, 0x6B, 0x45, 0x79, 0x72, 0x6B, 0x67, 0x50, 0x48, 0x37, 0x55, 0x49, 0x42, 0x7A, 0x67, 0x2F, 0x59, 0x73, 0x66, 0x71, 0x69, 0x6B, 0x75, 0x46, 0x67, 0x62, 0x61, 0x35, 0x36, 0x61, 0x77, 0x6D, 0x71, 0x78, 0x69, 0x6E, 0x75, ++ 0x61, 0x45, 0x6C, 0x6E, 0x4D, 0x49, 0x41, 0x6B, 0x65, 0x6A, 0x45, 0x57, 0x4F, 0x56, 0x74, 0x2B, 0x38, 0x52, 0x77, 0x75, 0x33, 0x57, 0x77, 0x4A, 0x72, 0x66, 0x49, 0x78, 0x77, 0x59, 0x4A, 0x4F, 0x75, 0x62, 0x76, 0x35, 0x76, 0x72, 0x38, 0x71, ++ 0x0A, 0x68, 0x54, 0x2F, 0x41, 0x51, 0x4B, 0x4D, 0x36, 0x57, 0x66, 0x78, 0x5A, 0x53, 0x7A, 0x77, 0x6F, 0x4A, 0x4E, 0x75, 0x30, 0x46, 0x58, 0x57, 0x75, 0x44, 0x59, 0x69, 0x36, 0x4C, 0x6E, 0x50, 0x41, 0x76, 0x56, 0x69, 0x48, 0x35, 0x55, 0x4C, ++ 0x79, 0x36, 0x31, 0x37, 0x75, 0x48, 0x6A, 0x41, 0x69, 0x6D, 0x63, 0x73, 0x33, 0x30, 0x63, 0x51, 0x68, 0x62, 0x49, 0x48, 0x73, 0x76, 0x6D, 0x30, 0x6D, 0x35, 0x68, 0x7A, 0x6B, 0x51, 0x69, 0x43, 0x65, 0x52, 0x37, 0x43, 0x73, 0x0A, 0x67, 0x31, ++ 0x6C, 0x77, 0x4C, 0x44, 0x58, 0x57, 0x72, 0x7A, 0x59, 0x30, 0x74, 0x4D, 0x30, 0x37, 0x2B, 0x44, 0x4B, 0x6F, 0x37, 0x2B, 0x4E, 0x34, 0x69, 0x66, 0x75, 0x4E, 0x52, 0x53, 0x7A, 0x61, 0x6E, 0x4C, 0x68, 0x2B, 0x51, 0x42, 0x78, 0x68, 0x35, 0x7A, ++ 0x36, 0x69, 0x6B, 0x69, 0x78, 0x4C, 0x38, 0x73, 0x33, 0x36, 0x6D, 0x4C, 0x59, 0x70, 0x2F, 0x2F, 0x50, 0x79, 0x65, 0x36, 0x6B, 0x66, 0x4C, 0x71, 0x43, 0x54, 0x56, 0x79, 0x76, 0x65, 0x68, 0x51, 0x50, 0x35, 0x0A, 0x61, 0x54, 0x66, 0x4C, 0x6E, ++ 0x6E, 0x68, 0x71, 0x42, 0x62, 0x54, 0x46, 0x4D, 0x58, 0x69, 0x4A, 0x37, 0x48, 0x71, 0x6E, 0x68, 0x65, 0x47, 0x35, 0x65, 0x7A, 0x7A, 0x65, 0x76, 0x68, 0x35, 0x35, 0x68, 0x4D, 0x36, 0x66, 0x63, 0x41, 0x35, 0x5A, 0x77, 0x6A, 0x55, 0x75, 0x6B, ++ 0x43, 0x6F, 0x78, 0x32, 0x65, 0x52, 0x46, 0x65, 0x6B, 0x47, 0x6B, 0x4C, 0x68, 0x4F, 0x62, 0x4E, 0x41, 0x35, 0x6D, 0x65, 0x30, 0x6D, 0x72, 0x5A, 0x4A, 0x66, 0x51, 0x52, 0x73, 0x4E, 0x35, 0x0A, 0x6E, 0x58, 0x4A, 0x51, 0x59, 0x36, 0x61, 0x59, ++ 0x57, 0x77, 0x61, 0x39, 0x53, 0x47, 0x33, 0x59, 0x4F, 0x59, 0x4E, 0x77, 0x36, 0x44, 0x58, 0x77, 0x42, 0x64, 0x47, 0x71, 0x76, 0x4F, 0x50, 0x62, 0x79, 0x41, 0x4C, 0x71, 0x66, 0x50, 0x32, 0x43, 0x32, 0x73, 0x4A, 0x62, 0x55, 0x6A, 0x57, 0x75, ++ 0x6D, 0x44, 0x71, 0x74, 0x75, 0x6A, 0x57, 0x54, 0x49, 0x36, 0x63, 0x66, 0x53, 0x4E, 0x30, 0x31, 0x52, 0x70, 0x69, 0x79, 0x45, 0x47, 0x6A, 0x6B, 0x70, 0x54, 0x48, 0x43, 0x0A, 0x43, 0x6C, 0x67, 0x75, 0x47, 0x59, 0x45, 0x51, 0x79, 0x56, 0x42, ++ 0x31, 0x2F, 0x4F, 0x70, 0x61, 0x46, 0x73, 0x34, 0x52, 0x31, 0x2B, 0x37, 0x76, 0x55, 0x49, 0x67, 0x74, 0x59, 0x66, 0x38, 0x2F, 0x51, 0x6E, 0x4D, 0x46, 0x6C, 0x45, 0x50, 0x56, 0x6A, 0x6A, 0x78, 0x4F, 0x41, 0x54, 0x6F, 0x5A, 0x70, 0x52, 0x39, ++ 0x47, 0x54, 0x6E, 0x66, 0x51, 0x58, 0x65, 0x57, 0x42, 0x49, 0x69, 0x47, 0x48, 0x2F, 0x70, 0x52, 0x39, 0x68, 0x4E, 0x69, 0x54, 0x72, 0x64, 0x5A, 0x6F, 0x0A, 0x51, 0x30, 0x69, 0x79, 0x32, 0x2B, 0x74, 0x7A, 0x4A, 0x4F, 0x65, 0x52, 0x66, 0x31, ++ 0x53, 0x6B, 0x74, 0x6F, 0x41, 0x2B, 0x6E, 0x61, 0x4D, 0x38, 0x54, 0x48, 0x4C, 0x43, 0x56, 0x38, 0x53, 0x67, 0x31, 0x4D, 0x77, 0x34, 0x4A, 0x38, 0x37, 0x56, 0x42, 0x70, 0x36, 0x69, 0x53, 0x4E, 0x6E, 0x70, 0x6E, 0x38, 0x36, 0x43, 0x63, 0x44, ++ 0x61, 0x54, 0x6D, 0x6A, 0x76, 0x66, 0x6C, 0x69, 0x48, 0x6A, 0x57, 0x62, 0x63, 0x4D, 0x32, 0x70, 0x45, 0x33, 0x38, 0x50, 0x31, 0x5A, 0x0A, 0x57, 0x72, 0x4F, 0x5A, 0x79, 0x47, 0x6C, 0x73, 0x51, 0x79, 0x59, 0x42, 0x4E, 0x57, 0x4E, 0x67, 0x56, ++ 0x59, 0x6B, 0x44, 0x4F, 0x6E, 0x58, 0x59, 0x75, 0x6B, 0x72, 0x5A, 0x56, 0x50, 0x2F, 0x75, 0x33, 0x6F, 0x44, 0x59, 0x4C, 0x64, 0x45, 0x34, 0x31, 0x56, 0x34, 0x74, 0x43, 0x35, 0x68, 0x39, 0x50, 0x6D, 0x7A, 0x62, 0x2F, 0x43, 0x61, 0x49, 0x78, ++ 0x77, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x47, 0x6F, 0x20, 0x44, 0x61, 0x64, 0x64, 0x79, 0x20, ++ 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x47, 0x32, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, ++ 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x44, 0x78, 0x54, 0x43, 0x43, 0x41, 0x71, 0x32, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, ++ 0x42, 0x41, 0x44, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x44, 0x43, 0x42, 0x67, 0x7A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, ++ 0x43, 0x56, 0x56, 0x4D, 0x78, 0x45, 0x44, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x67, 0x54, 0x0A, 0x42, 0x30, 0x46, 0x79, 0x61, 0x58, 0x70, 0x76, 0x62, 0x6D, 0x45, 0x78, 0x45, 0x7A, 0x41, 0x52, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, ++ 0x63, 0x54, 0x43, 0x6C, 0x4E, 0x6A, 0x62, 0x33, 0x52, 0x30, 0x63, 0x32, 0x52, 0x68, 0x62, 0x47, 0x55, 0x78, 0x47, 0x6A, 0x41, 0x59, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x45, 0x55, 0x64, 0x76, 0x52, 0x47, 0x46, 0x6B, 0x5A, 0x48, ++ 0x6B, 0x75, 0x59, 0x32, 0x39, 0x74, 0x4C, 0x43, 0x42, 0x4A, 0x62, 0x6D, 0x4D, 0x75, 0x0A, 0x4D, 0x54, 0x45, 0x77, 0x4C, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x79, 0x68, 0x48, 0x62, 0x79, 0x42, 0x45, 0x59, 0x57, 0x52, 0x6B, 0x65, ++ 0x53, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x6C, 0x63, 0x6E, 0x52, 0x70, 0x5A, 0x6D, 0x6C, 0x6A, 0x59, 0x58, 0x52, 0x6C, 0x49, 0x45, 0x46, 0x31, 0x64, 0x47, 0x68, 0x76, 0x63, 0x6D, 0x6C, 0x30, 0x65, 0x53, 0x41, 0x74, 0x49, ++ 0x45, 0x63, 0x79, 0x4D, 0x42, 0x34, 0x58, 0x44, 0x54, 0x41, 0x35, 0x0A, 0x4D, 0x44, 0x6B, 0x77, 0x4D, 0x54, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x46, 0x6F, 0x58, 0x44, 0x54, 0x4D, 0x33, 0x4D, 0x54, 0x49, 0x7A, 0x4D, 0x54, 0x49, 0x7A, ++ 0x4E, 0x54, 0x6B, 0x31, 0x4F, 0x56, 0x6F, 0x77, 0x67, 0x59, 0x4D, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6C, 0x56, 0x54, 0x4D, 0x52, 0x41, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x49, ++ 0x45, 0x77, 0x64, 0x42, 0x63, 0x6D, 0x6C, 0x36, 0x0A, 0x62, 0x32, 0x35, 0x68, 0x4D, 0x52, 0x4D, 0x77, 0x45, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x48, 0x45, 0x77, 0x70, 0x54, 0x59, 0x32, 0x39, 0x30, 0x64, 0x48, 0x4E, 0x6B, 0x59, 0x57, 0x78, ++ 0x6C, 0x4D, 0x52, 0x6F, 0x77, 0x47, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x45, 0x78, 0x46, 0x48, 0x62, 0x30, 0x52, 0x68, 0x5A, 0x47, 0x52, 0x35, 0x4C, 0x6D, 0x4E, 0x76, 0x62, 0x53, 0x77, 0x67, 0x53, 0x57, 0x35, 0x6A, 0x4C, 0x6A, 0x45, ++ 0x78, 0x4D, 0x43, 0x38, 0x47, 0x0A, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x6F, 0x52, 0x32, 0x38, 0x67, 0x52, 0x47, 0x46, 0x6B, 0x5A, 0x48, 0x6B, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x61, 0x57, ++ 0x5A, 0x70, 0x59, 0x32, 0x46, 0x30, 0x5A, 0x53, 0x42, 0x42, 0x64, 0x58, 0x52, 0x6F, 0x62, 0x33, 0x4A, 0x70, 0x64, 0x48, 0x6B, 0x67, 0x4C, 0x53, 0x42, 0x48, 0x4D, 0x6A, 0x43, 0x43, 0x41, 0x53, 0x49, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, ++ 0x5A, 0x49, 0x0A, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x45, 0x50, 0x41, 0x44, 0x43, 0x43, 0x41, 0x51, 0x6F, 0x43, 0x67, 0x67, 0x45, 0x42, 0x41, 0x4C, 0x39, 0x78, 0x59, 0x67, 0x6A, 0x78, 0x2B, ++ 0x6C, 0x6B, 0x30, 0x39, 0x78, 0x76, 0x4A, 0x47, 0x4B, 0x50, 0x33, 0x67, 0x45, 0x6C, 0x59, 0x36, 0x53, 0x4B, 0x44, 0x45, 0x36, 0x62, 0x46, 0x49, 0x45, 0x4D, 0x42, 0x4F, 0x34, 0x54, 0x78, 0x35, 0x6F, 0x56, 0x4A, 0x6E, 0x79, 0x66, 0x71, 0x0A, ++ 0x39, 0x6F, 0x51, 0x62, 0x54, 0x71, 0x43, 0x30, 0x32, 0x33, 0x43, 0x59, 0x78, 0x7A, 0x49, 0x42, 0x73, 0x51, 0x55, 0x2B, 0x42, 0x30, 0x37, 0x75, 0x39, 0x50, 0x70, 0x50, 0x4C, 0x31, 0x6B, 0x77, 0x49, 0x75, 0x65, 0x72, 0x47, 0x56, 0x5A, 0x72, ++ 0x34, 0x6F, 0x41, 0x48, 0x2F, 0x50, 0x4D, 0x57, 0x64, 0x59, 0x41, 0x35, 0x55, 0x58, 0x76, 0x6C, 0x2B, 0x54, 0x57, 0x32, 0x64, 0x45, 0x36, 0x70, 0x6A, 0x59, 0x49, 0x54, 0x35, 0x4C, 0x59, 0x2F, 0x71, 0x51, 0x4F, 0x44, 0x0A, 0x2B, 0x71, 0x4B, ++ 0x2B, 0x69, 0x68, 0x56, 0x71, 0x66, 0x39, 0x34, 0x4C, 0x77, 0x37, 0x59, 0x5A, 0x46, 0x41, 0x58, 0x4B, 0x36, 0x73, 0x4F, 0x6F, 0x42, 0x4A, 0x51, 0x37, 0x52, 0x6E, 0x77, 0x79, 0x44, 0x66, 0x4D, 0x41, 0x5A, 0x69, 0x4C, 0x49, 0x6A, 0x57, 0x6C, ++ 0x74, 0x4E, 0x6F, 0x77, 0x52, 0x47, 0x4C, 0x66, 0x54, 0x73, 0x68, 0x78, 0x67, 0x74, 0x44, 0x6A, 0x36, 0x41, 0x6F, 0x7A, 0x4F, 0x30, 0x39, 0x31, 0x47, 0x42, 0x39, 0x34, 0x4B, 0x50, 0x75, 0x74, 0x64, 0x0A, 0x66, 0x4D, 0x68, 0x38, 0x2B, 0x37, ++ 0x41, 0x72, 0x55, 0x36, 0x53, 0x53, 0x59, 0x6D, 0x6C, 0x52, 0x4A, 0x51, 0x56, 0x68, 0x47, 0x6B, 0x53, 0x42, 0x6A, 0x43, 0x79, 0x70, 0x51, 0x35, 0x59, 0x6A, 0x33, 0x36, 0x77, 0x36, 0x67, 0x5A, 0x6F, 0x4F, 0x4B, 0x63, 0x55, 0x63, 0x71, 0x65, ++ 0x6C, 0x64, 0x48, 0x72, 0x61, 0x65, 0x6E, 0x6A, 0x41, 0x4B, 0x4F, 0x63, 0x37, 0x78, 0x69, 0x49, 0x44, 0x37, 0x53, 0x31, 0x33, 0x4D, 0x4D, 0x75, 0x79, 0x46, 0x59, 0x6B, 0x4D, 0x6C, 0x0A, 0x4E, 0x41, 0x4A, 0x57, 0x4A, 0x77, 0x47, 0x52, 0x74, ++ 0x44, 0x74, 0x77, 0x4B, 0x6A, 0x39, 0x75, 0x73, 0x65, 0x69, 0x63, 0x69, 0x41, 0x46, 0x39, 0x6E, 0x39, 0x54, 0x35, 0x32, 0x31, 0x4E, 0x74, 0x59, 0x4A, 0x32, 0x2F, 0x4C, 0x4F, 0x64, 0x59, 0x71, 0x37, 0x68, 0x66, 0x52, 0x76, 0x7A, 0x4F, 0x78, ++ 0x42, 0x73, 0x44, 0x50, 0x41, 0x6E, 0x72, 0x53, 0x54, 0x46, 0x63, 0x61, 0x55, 0x61, 0x7A, 0x34, 0x45, 0x63, 0x43, 0x41, 0x77, 0x45, 0x41, 0x41, 0x61, 0x4E, 0x43, 0x0A, 0x4D, 0x45, 0x41, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, ++ 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x51, 0x59, 0x77, 0x48, 0x51, 0x59, 0x44, ++ 0x56, 0x52, 0x30, 0x4F, 0x42, 0x42, 0x59, 0x45, 0x46, 0x44, 0x71, 0x61, 0x68, 0x51, 0x63, 0x51, 0x5A, 0x79, 0x69, 0x32, 0x37, 0x2F, 0x61, 0x39, 0x0A, 0x42, 0x55, 0x46, 0x75, 0x49, 0x4D, 0x47, 0x55, 0x32, 0x67, 0x2F, 0x65, 0x4D, 0x41, 0x30, ++ 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x43, 0x77, 0x55, 0x41, 0x41, 0x34, 0x49, 0x42, 0x41, 0x51, 0x43, 0x5A, 0x32, 0x31, 0x31, 0x35, 0x31, 0x66, 0x6D, 0x58, 0x57, 0x57, 0x63, 0x44, 0x59, 0x66, 0x46, ++ 0x2B, 0x4F, 0x77, 0x59, 0x78, 0x64, 0x53, 0x32, 0x68, 0x49, 0x49, 0x35, 0x50, 0x5A, 0x59, 0x65, 0x30, 0x39, 0x36, 0x61, 0x63, 0x0A, 0x76, 0x4E, 0x6A, 0x70, 0x4C, 0x39, 0x44, 0x62, 0x57, 0x75, 0x37, 0x50, 0x64, 0x49, 0x78, 0x7A, 0x74, 0x44, ++ 0x68, 0x43, 0x32, 0x67, 0x56, 0x37, 0x2B, 0x41, 0x4A, 0x31, 0x75, 0x50, 0x32, 0x6C, 0x73, 0x64, 0x65, 0x75, 0x39, 0x74, 0x66, 0x65, 0x45, 0x38, 0x74, 0x54, 0x45, 0x48, 0x36, 0x4B, 0x52, 0x74, 0x47, 0x58, 0x2B, 0x72, 0x63, 0x75, 0x4B, 0x78, ++ 0x47, 0x72, 0x6B, 0x4C, 0x41, 0x6E, 0x67, 0x50, 0x6E, 0x6F, 0x6E, 0x31, 0x72, 0x70, 0x4E, 0x35, 0x2B, 0x72, 0x0A, 0x35, 0x4E, 0x39, 0x73, 0x73, 0x34, 0x55, 0x58, 0x6E, 0x54, 0x33, 0x5A, 0x4A, 0x45, 0x39, 0x35, 0x6B, 0x54, 0x58, 0x57, 0x58, ++ 0x77, 0x54, 0x72, 0x67, 0x49, 0x4F, 0x72, 0x6D, 0x67, 0x49, 0x74, 0x74, 0x52, 0x44, 0x30, 0x32, 0x4A, 0x44, 0x48, 0x42, 0x48, 0x4E, 0x41, 0x37, 0x58, 0x49, 0x6C, 0x6F, 0x4B, 0x6D, 0x66, 0x37, 0x4A, 0x36, 0x72, 0x61, 0x42, 0x4B, 0x5A, 0x56, ++ 0x38, 0x61, 0x50, 0x45, 0x6A, 0x6F, 0x4A, 0x70, 0x4C, 0x31, 0x45, 0x2F, 0x51, 0x59, 0x56, 0x0A, 0x4E, 0x38, 0x47, 0x62, 0x35, 0x44, 0x4B, 0x6A, 0x37, 0x54, 0x6A, 0x6F, 0x32, 0x47, 0x54, 0x7A, 0x4C, 0x48, 0x34, 0x55, 0x2F, 0x41, 0x4C, 0x71, ++ 0x6E, 0x38, 0x33, 0x2F, 0x42, 0x32, 0x67, 0x58, 0x32, 0x79, 0x4B, 0x51, 0x4F, 0x43, 0x31, 0x36, 0x6A, 0x64, 0x46, 0x55, 0x38, 0x57, 0x6E, 0x6A, 0x58, 0x7A, 0x50, 0x4B, 0x65, 0x6A, 0x31, 0x37, 0x43, 0x75, 0x50, 0x4B, 0x66, 0x31, 0x38, 0x35, ++ 0x35, 0x65, 0x4A, 0x31, 0x75, 0x73, 0x56, 0x32, 0x47, 0x44, 0x50, 0x4F, 0x0A, 0x4C, 0x50, 0x41, 0x76, 0x54, 0x4B, 0x33, 0x33, 0x73, 0x65, 0x66, 0x4F, 0x54, 0x36, 0x6A, 0x45, 0x6D, 0x30, 0x70, 0x55, 0x42, 0x73, 0x56, 0x2F, 0x66, 0x64, 0x55, ++ 0x49, 0x44, 0x2B, 0x49, 0x63, 0x2F, 0x6E, 0x34, 0x58, 0x75, 0x4B, 0x78, 0x65, 0x39, 0x74, 0x51, 0x57, 0x73, 0x6B, 0x4D, 0x4A, 0x44, 0x45, 0x33, 0x32, 0x70, 0x32, 0x75, 0x30, 0x6D, 0x59, 0x52, 0x6C, 0x79, 0x6E, 0x71, 0x49, 0x34, 0x75, 0x4A, ++ 0x45, 0x76, 0x6C, 0x7A, 0x33, 0x36, 0x68, 0x7A, 0x31, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x53, 0x74, 0x61, ++ 0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x47, 0x32, 0x0A, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x44, 0x33, 0x54, 0x43, 0x43, 0x41, 0x73, 0x57, ++ 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x42, 0x41, 0x44, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x44, 0x43, 0x42, 0x6A, 0x7A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, ++ 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x56, 0x56, 0x4D, 0x78, 0x45, 0x44, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x67, 0x54, 0x0A, 0x42, 0x30, 0x46, 0x79, 0x61, 0x58, 0x70, 0x76, 0x62, 0x6D, 0x45, 0x78, 0x45, 0x7A, ++ 0x41, 0x52, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x63, 0x54, 0x43, 0x6C, 0x4E, 0x6A, 0x62, 0x33, 0x52, 0x30, 0x63, 0x32, 0x52, 0x68, 0x62, 0x47, 0x55, 0x78, 0x4A, 0x54, 0x41, 0x6A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x48, 0x46, ++ 0x4E, 0x30, 0x59, 0x58, 0x4A, 0x6D, 0x61, 0x57, 0x56, 0x73, 0x5A, 0x43, 0x42, 0x55, 0x5A, 0x57, 0x4E, 0x6F, 0x62, 0x6D, 0x39, 0x73, 0x0A, 0x62, 0x32, 0x64, 0x70, 0x5A, 0x58, 0x4D, 0x73, 0x49, 0x45, 0x6C, 0x75, 0x59, 0x79, 0x34, 0x78, 0x4D, ++ 0x6A, 0x41, 0x77, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x4B, 0x56, 0x4E, 0x30, 0x59, 0x58, 0x4A, 0x6D, 0x61, 0x57, 0x56, 0x73, 0x5A, 0x43, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x6C, 0x63, 0x6E, 0x52, 0x70, 0x5A, ++ 0x6D, 0x6C, 0x6A, 0x59, 0x58, 0x52, 0x6C, 0x49, 0x45, 0x46, 0x31, 0x64, 0x47, 0x68, 0x76, 0x63, 0x6D, 0x6C, 0x30, 0x0A, 0x65, 0x53, 0x41, 0x74, 0x49, 0x45, 0x63, 0x79, 0x4D, 0x42, 0x34, 0x58, 0x44, 0x54, 0x41, 0x35, 0x4D, 0x44, 0x6B, 0x77, ++ 0x4D, 0x54, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x46, 0x6F, 0x58, 0x44, 0x54, 0x4D, 0x33, 0x4D, 0x54, 0x49, 0x7A, 0x4D, 0x54, 0x49, 0x7A, 0x4E, 0x54, 0x6B, 0x31, 0x4F, 0x56, 0x6F, 0x77, 0x67, 0x59, 0x38, 0x78, 0x43, 0x7A, 0x41, 0x4A, ++ 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6C, 0x56, 0x54, 0x4D, 0x52, 0x41, 0x77, 0x0A, 0x44, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x49, 0x45, 0x77, 0x64, 0x42, 0x63, 0x6D, 0x6C, 0x36, 0x62, 0x32, 0x35, 0x68, 0x4D, 0x52, 0x4D, ++ 0x77, 0x45, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x48, 0x45, 0x77, 0x70, 0x54, 0x59, 0x32, 0x39, 0x30, 0x64, 0x48, 0x4E, 0x6B, 0x59, 0x57, 0x78, 0x6C, 0x4D, 0x53, 0x55, 0x77, 0x49, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x45, 0x78, 0x78, ++ 0x54, 0x64, 0x47, 0x46, 0x79, 0x5A, 0x6D, 0x6C, 0x6C, 0x62, 0x47, 0x51, 0x67, 0x0A, 0x56, 0x47, 0x56, 0x6A, 0x61, 0x47, 0x35, 0x76, 0x62, 0x47, 0x39, 0x6E, 0x61, 0x57, 0x56, 0x7A, 0x4C, 0x43, 0x42, 0x4A, 0x62, 0x6D, 0x4D, 0x75, 0x4D, 0x54, ++ 0x49, 0x77, 0x4D, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x79, 0x6C, 0x54, 0x64, 0x47, 0x46, 0x79, 0x5A, 0x6D, 0x6C, 0x6C, 0x62, 0x47, 0x51, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x61, 0x57, ++ 0x5A, 0x70, 0x59, 0x32, 0x46, 0x30, 0x5A, 0x53, 0x42, 0x42, 0x0A, 0x64, 0x58, 0x52, 0x6F, 0x62, 0x33, 0x4A, 0x70, 0x64, 0x48, 0x6B, 0x67, 0x4C, 0x53, 0x42, 0x48, 0x4D, 0x6A, 0x43, 0x43, 0x41, 0x53, 0x49, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, ++ 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x45, 0x50, 0x41, 0x44, 0x43, 0x43, 0x41, 0x51, 0x6F, 0x43, 0x67, 0x67, 0x45, 0x42, 0x41, 0x4C, 0x33, 0x74, 0x77, 0x51, 0x50, 0x38, 0x39, ++ 0x6F, 0x2F, 0x38, 0x41, 0x72, 0x46, 0x76, 0x0A, 0x57, 0x35, 0x39, 0x49, 0x32, 0x5A, 0x31, 0x35, 0x34, 0x71, 0x4B, 0x33, 0x41, 0x32, 0x46, 0x57, 0x47, 0x4D, 0x4E, 0x48, 0x74, 0x74, 0x66, 0x4B, 0x50, 0x54, 0x55, 0x75, 0x69, 0x55, 0x50, 0x33, ++ 0x6F, 0x57, 0x6D, 0x62, 0x33, 0x6F, 0x6F, 0x61, 0x2F, 0x52, 0x4D, 0x67, 0x6E, 0x4C, 0x52, 0x4A, 0x64, 0x7A, 0x49, 0x70, 0x56, 0x76, 0x32, 0x35, 0x37, 0x49, 0x7A, 0x64, 0x49, 0x76, 0x70, 0x79, 0x33, 0x43, 0x64, 0x68, 0x6C, 0x2B, 0x37, 0x32, ++ 0x57, 0x6F, 0x54, 0x73, 0x0A, 0x62, 0x68, 0x6D, 0x35, 0x69, 0x53, 0x7A, 0x63, 0x68, 0x46, 0x76, 0x56, 0x64, 0x50, 0x74, 0x72, 0x58, 0x38, 0x57, 0x4A, 0x70, 0x52, 0x42, 0x53, 0x69, 0x55, 0x5A, 0x56, 0x39, 0x4C, 0x68, 0x31, 0x48, 0x4F, 0x5A, ++ 0x2F, 0x35, 0x46, 0x53, 0x75, 0x53, 0x2F, 0x68, 0x56, 0x63, 0x6C, 0x63, 0x43, 0x47, 0x66, 0x67, 0x58, 0x63, 0x56, 0x6E, 0x72, 0x48, 0x69, 0x67, 0x48, 0x64, 0x4D, 0x57, 0x64, 0x53, 0x4C, 0x35, 0x73, 0x74, 0x50, 0x53, 0x6B, 0x73, 0x50, 0x4E, ++ 0x6B, 0x0A, 0x4E, 0x33, 0x6D, 0x53, 0x77, 0x4F, 0x78, 0x47, 0x58, 0x6E, 0x2F, 0x68, 0x62, 0x56, 0x4E, 0x4D, 0x59, 0x71, 0x2F, 0x4E, 0x48, 0x77, 0x74, 0x6A, 0x75, 0x7A, 0x71, 0x64, 0x2B, 0x2F, 0x78, 0x35, 0x41, 0x4A, 0x68, 0x68, 0x64, 0x4D, ++ 0x38, 0x6D, 0x67, 0x6B, 0x42, 0x6A, 0x38, 0x37, 0x4A, 0x79, 0x61, 0x68, 0x6B, 0x4E, 0x6D, 0x63, 0x72, 0x55, 0x44, 0x6E, 0x58, 0x4D, 0x4E, 0x2F, 0x75, 0x4C, 0x69, 0x63, 0x46, 0x5A, 0x38, 0x57, 0x4A, 0x2F, 0x58, 0x37, 0x4E, 0x66, 0x0A, 0x5A, ++ 0x54, 0x44, 0x34, 0x70, 0x37, 0x64, 0x4E, 0x64, 0x6C, 0x6F, 0x65, 0x64, 0x6C, 0x34, 0x30, 0x77, 0x4F, 0x69, 0x57, 0x56, 0x70, 0x6D, 0x4B, 0x73, 0x2F, 0x42, 0x2F, 0x70, 0x4D, 0x32, 0x39, 0x33, 0x44, 0x49, 0x78, 0x66, 0x4A, 0x48, 0x50, 0x34, ++ 0x46, 0x38, 0x52, 0x2B, 0x47, 0x75, 0x71, 0x53, 0x56, 0x7A, 0x52, 0x6D, 0x5A, 0x54, 0x52, 0x6F, 0x75, 0x4E, 0x6A, 0x57, 0x77, 0x6C, 0x32, 0x74, 0x56, 0x5A, 0x69, 0x34, 0x55, 0x74, 0x30, 0x48, 0x5A, 0x62, 0x55, 0x0A, 0x4A, 0x74, 0x51, 0x49, ++ 0x42, 0x46, 0x6E, 0x51, 0x6D, 0x41, 0x34, 0x4F, 0x35, 0x74, 0x37, 0x38, 0x77, 0x2B, 0x77, 0x66, 0x6B, 0x50, 0x45, 0x43, 0x41, 0x77, 0x45, 0x41, 0x41, 0x61, 0x4E, 0x43, 0x4D, 0x45, 0x41, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, ++ 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x41, 0x4D, 0x43, 0x0A, 0x41, 0x51, 0x59, 0x77, 0x48, 0x51, 0x59, ++ 0x44, 0x56, 0x52, 0x30, 0x4F, 0x42, 0x42, 0x59, 0x45, 0x46, 0x48, 0x77, 0x4D, 0x4D, 0x68, 0x2B, 0x6E, 0x32, 0x54, 0x42, 0x2F, 0x78, 0x48, 0x31, 0x6F, 0x6F, 0x32, 0x4B, 0x6F, 0x6F, 0x63, 0x36, 0x72, 0x42, 0x31, 0x73, 0x6E, 0x4D, 0x41, 0x30, ++ 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x43, 0x77, 0x55, 0x41, 0x41, 0x34, 0x49, 0x42, 0x41, 0x51, 0x41, 0x52, 0x57, 0x66, 0x6F, 0x6C, 0x0A, 0x54, 0x77, 0x4E, 0x76, 0x6C, 0x4A, 0x6B, 0x37, 0x6D, 0x68, ++ 0x2B, 0x43, 0x68, 0x54, 0x6E, 0x55, 0x64, 0x67, 0x57, 0x55, 0x58, 0x75, 0x45, 0x6F, 0x6B, 0x32, 0x31, 0x69, 0x58, 0x51, 0x6E, 0x43, 0x6F, 0x4B, 0x6A, 0x55, 0x73, 0x48, 0x55, 0x34, 0x38, 0x54, 0x52, 0x71, 0x6E, 0x65, 0x53, 0x66, 0x69, 0x6F, ++ 0x59, 0x6D, 0x55, 0x65, 0x59, 0x73, 0x30, 0x63, 0x59, 0x74, 0x62, 0x70, 0x55, 0x67, 0x53, 0x70, 0x49, 0x42, 0x37, 0x4C, 0x69, 0x4B, 0x5A, 0x33, 0x73, 0x78, 0x0A, 0x34, 0x6D, 0x63, 0x75, 0x6A, 0x4A, 0x55, 0x44, 0x4A, 0x69, 0x35, 0x44, 0x6E, ++ 0x55, 0x6F, 0x78, 0x39, 0x67, 0x36, 0x31, 0x44, 0x4C, 0x75, 0x33, 0x34, 0x6A, 0x64, 0x2F, 0x49, 0x72, 0x6F, 0x41, 0x6F, 0x77, 0x35, 0x37, 0x55, 0x76, 0x74, 0x72, 0x75, 0x7A, 0x76, 0x45, 0x30, 0x33, 0x6C, 0x52, 0x54, 0x73, 0x32, 0x51, 0x39, ++ 0x47, 0x63, 0x48, 0x47, 0x63, 0x67, 0x38, 0x52, 0x6E, 0x6F, 0x4E, 0x41, 0x58, 0x33, 0x46, 0x57, 0x4F, 0x64, 0x74, 0x35, 0x6F, 0x55, 0x77, 0x0A, 0x46, 0x35, 0x6F, 0x6B, 0x78, 0x42, 0x44, 0x67, 0x42, 0x50, 0x66, 0x67, 0x38, 0x6E, 0x2F, 0x55, ++ 0x71, 0x67, 0x72, 0x2F, 0x51, 0x68, 0x30, 0x33, 0x37, 0x5A, 0x54, 0x6C, 0x5A, 0x46, 0x6B, 0x53, 0x49, 0x48, 0x63, 0x34, 0x30, 0x7A, 0x49, 0x2B, 0x4F, 0x49, 0x46, 0x31, 0x6C, 0x6E, 0x50, 0x36, 0x61, 0x49, 0x2B, 0x78, 0x79, 0x38, 0x34, 0x66, ++ 0x78, 0x65, 0x7A, 0x36, 0x6E, 0x48, 0x37, 0x50, 0x66, 0x72, 0x48, 0x78, 0x42, 0x79, 0x32, 0x32, 0x2F, 0x4C, 0x2F, 0x4B, 0x0A, 0x70, 0x4C, 0x2F, 0x51, 0x6C, 0x77, 0x56, 0x4B, 0x76, 0x4F, 0x6F, 0x59, 0x4B, 0x41, 0x4B, 0x51, 0x76, 0x56, 0x52, ++ 0x34, 0x43, 0x53, 0x46, 0x78, 0x30, 0x39, 0x46, 0x39, 0x48, 0x64, 0x6B, 0x57, 0x73, 0x4B, 0x6C, 0x68, 0x50, 0x64, 0x41, 0x4B, 0x41, 0x43, 0x4C, 0x38, 0x78, 0x33, 0x76, 0x4C, 0x43, 0x57, 0x52, 0x46, 0x43, 0x7A, 0x74, 0x41, 0x67, 0x66, 0x64, ++ 0x39, 0x66, 0x44, 0x4C, 0x31, 0x6D, 0x4D, 0x70, 0x59, 0x6A, 0x6E, 0x30, 0x71, 0x37, 0x70, 0x42, 0x5A, 0x0A, 0x63, 0x32, 0x54, 0x35, 0x4E, 0x6E, 0x52, 0x65, 0x4A, 0x61, 0x48, 0x31, 0x5A, 0x67, 0x55, 0x75, 0x66, 0x7A, 0x6B, 0x56, 0x71, 0x53, ++ 0x72, 0x37, 0x55, 0x49, 0x75, 0x4F, 0x68, 0x57, 0x6E, 0x30, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x53, 0x74, ++ 0x61, 0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, ++ 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x47, 0x32, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, ++ 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x44, 0x37, 0x7A, 0x43, 0x43, 0x41, 0x74, 0x65, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x42, 0x41, 0x44, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, ++ 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x44, 0x43, 0x42, 0x6D, 0x44, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x56, 0x56, 0x4D, 0x78, 0x45, 0x44, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, ++ 0x42, 0x41, 0x67, 0x54, 0x0A, 0x42, 0x30, 0x46, 0x79, 0x61, 0x58, 0x70, 0x76, 0x62, 0x6D, 0x45, 0x78, 0x45, 0x7A, 0x41, 0x52, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x63, 0x54, 0x43, 0x6C, 0x4E, 0x6A, 0x62, 0x33, 0x52, 0x30, 0x63, 0x32, 0x52, ++ 0x68, 0x62, 0x47, 0x55, 0x78, 0x4A, 0x54, 0x41, 0x6A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x48, 0x46, 0x4E, 0x30, 0x59, 0x58, 0x4A, 0x6D, 0x61, 0x57, 0x56, 0x73, 0x5A, 0x43, 0x42, 0x55, 0x5A, 0x57, 0x4E, 0x6F, 0x62, 0x6D, 0x39, ++ 0x73, 0x0A, 0x62, 0x32, 0x64, 0x70, 0x5A, 0x58, 0x4D, 0x73, 0x49, 0x45, 0x6C, 0x75, 0x59, 0x79, 0x34, 0x78, 0x4F, 0x7A, 0x41, 0x35, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x4D, 0x6C, 0x4E, 0x30, 0x59, 0x58, 0x4A, 0x6D, 0x61, 0x57, ++ 0x56, 0x73, 0x5A, 0x43, 0x42, 0x54, 0x5A, 0x58, 0x4A, 0x32, 0x61, 0x57, 0x4E, 0x6C, 0x63, 0x79, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x6C, 0x63, 0x6E, 0x52, 0x70, 0x5A, 0x6D, 0x6C, 0x6A, 0x59, 0x58, 0x52, 0x6C, 0x0A, 0x49, ++ 0x45, 0x46, 0x31, 0x64, 0x47, 0x68, 0x76, 0x63, 0x6D, 0x6C, 0x30, 0x65, 0x53, 0x41, 0x74, 0x49, 0x45, 0x63, 0x79, 0x4D, 0x42, 0x34, 0x58, 0x44, 0x54, 0x41, 0x35, 0x4D, 0x44, 0x6B, 0x77, 0x4D, 0x54, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x4D, ++ 0x46, 0x6F, 0x58, 0x44, 0x54, 0x4D, 0x33, 0x4D, 0x54, 0x49, 0x7A, 0x4D, 0x54, 0x49, 0x7A, 0x4E, 0x54, 0x6B, 0x31, 0x4F, 0x56, 0x6F, 0x77, 0x67, 0x5A, 0x67, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x0A, 0x42, 0x41, 0x59, 0x54, ++ 0x41, 0x6C, 0x56, 0x54, 0x4D, 0x52, 0x41, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x49, 0x45, 0x77, 0x64, 0x42, 0x63, 0x6D, 0x6C, 0x36, 0x62, 0x32, 0x35, 0x68, 0x4D, 0x52, 0x4D, 0x77, 0x45, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x48, ++ 0x45, 0x77, 0x70, 0x54, 0x59, 0x32, 0x39, 0x30, 0x64, 0x48, 0x4E, 0x6B, 0x59, 0x57, 0x78, 0x6C, 0x4D, 0x53, 0x55, 0x77, 0x49, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x45, 0x78, 0x78, 0x54, 0x0A, 0x64, 0x47, 0x46, 0x79, 0x5A, 0x6D, 0x6C, ++ 0x6C, 0x62, 0x47, 0x51, 0x67, 0x56, 0x47, 0x56, 0x6A, 0x61, 0x47, 0x35, 0x76, 0x62, 0x47, 0x39, 0x6E, 0x61, 0x57, 0x56, 0x7A, 0x4C, 0x43, 0x42, 0x4A, 0x62, 0x6D, 0x4D, 0x75, 0x4D, 0x54, 0x73, 0x77, 0x4F, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, ++ 0x44, 0x45, 0x7A, 0x4A, 0x54, 0x64, 0x47, 0x46, 0x79, 0x5A, 0x6D, 0x6C, 0x6C, 0x62, 0x47, 0x51, 0x67, 0x55, 0x32, 0x56, 0x79, 0x64, 0x6D, 0x6C, 0x6A, 0x5A, 0x58, 0x4D, 0x67, 0x0A, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x5A, 0x58, ++ 0x4A, 0x30, 0x61, 0x57, 0x5A, 0x70, 0x59, 0x32, 0x46, 0x30, 0x5A, 0x53, 0x42, 0x42, 0x64, 0x58, 0x52, 0x6F, 0x62, 0x33, 0x4A, 0x70, 0x64, 0x48, 0x6B, 0x67, 0x4C, 0x53, 0x42, 0x48, 0x4D, 0x6A, 0x43, 0x43, 0x41, 0x53, 0x49, 0x77, 0x44, 0x51, ++ 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x45, 0x50, 0x41, 0x44, 0x43, 0x43, 0x0A, 0x41, 0x51, 0x6F, 0x43, 0x67, 0x67, 0x45, 0x42, 0x41, 0x4E, 0x55, 0x4D, 0x4F, ++ 0x73, 0x51, 0x71, 0x2B, 0x55, 0x37, 0x69, 0x39, 0x62, 0x34, 0x5A, 0x6C, 0x31, 0x2B, 0x4F, 0x69, 0x46, 0x4F, 0x78, 0x48, 0x7A, 0x2F, 0x4C, 0x7A, 0x35, 0x38, 0x67, 0x45, 0x32, 0x30, 0x70, 0x4F, 0x73, 0x67, 0x50, 0x66, 0x54, 0x7A, 0x33, 0x61, ++ 0x33, 0x59, 0x34, 0x59, 0x39, 0x6B, 0x32, 0x59, 0x4B, 0x69, 0x62, 0x58, 0x6C, 0x77, 0x41, 0x67, 0x4C, 0x49, 0x76, 0x57, 0x58, 0x2F, 0x32, 0x0A, 0x68, 0x2F, 0x6B, 0x6C, 0x51, 0x34, 0x62, 0x6E, 0x61, 0x52, 0x74, 0x53, 0x6D, 0x70, 0x44, 0x68, ++ 0x63, 0x65, 0x50, 0x59, 0x4C, 0x51, 0x31, 0x4F, 0x62, 0x2F, 0x62, 0x49, 0x53, 0x64, 0x6D, 0x32, 0x38, 0x78, 0x70, 0x57, 0x72, 0x69, 0x75, 0x32, 0x64, 0x42, 0x54, 0x72, 0x7A, 0x2F, 0x73, 0x6D, 0x34, 0x78, 0x71, 0x36, 0x48, 0x5A, 0x59, 0x75, ++ 0x61, 0x6A, 0x74, 0x59, 0x6C, 0x49, 0x6C, 0x48, 0x56, 0x76, 0x38, 0x6C, 0x6F, 0x4A, 0x4E, 0x77, 0x55, 0x34, 0x50, 0x61, 0x0A, 0x68, 0x48, 0x51, 0x55, 0x77, 0x32, 0x65, 0x65, 0x42, 0x47, 0x67, 0x36, 0x33, 0x34, 0x35, 0x41, 0x57, 0x68, 0x31, ++ 0x4B, 0x54, 0x73, 0x39, 0x44, 0x6B, 0x54, 0x76, 0x6E, 0x56, 0x74, 0x59, 0x41, 0x63, 0x4D, 0x74, 0x53, 0x37, 0x6E, 0x74, 0x39, 0x72, 0x6A, 0x72, 0x6E, 0x76, 0x44, 0x48, 0x35, 0x52, 0x66, 0x62, 0x43, 0x59, 0x4D, 0x38, 0x54, 0x57, 0x51, 0x49, ++ 0x72, 0x67, 0x4D, 0x77, 0x30, 0x52, 0x39, 0x2B, 0x35, 0x33, 0x70, 0x42, 0x6C, 0x62, 0x51, 0x4C, 0x50, 0x0A, 0x4C, 0x4A, 0x47, 0x6D, 0x70, 0x75, 0x66, 0x65, 0x68, 0x52, 0x68, 0x4A, 0x66, 0x47, 0x5A, 0x4F, 0x6F, 0x7A, 0x70, 0x74, 0x71, 0x62, ++ 0x58, 0x75, 0x4E, 0x43, 0x36, 0x36, 0x44, 0x51, 0x4F, 0x34, 0x4D, 0x39, 0x39, 0x48, 0x36, 0x37, 0x46, 0x72, 0x6A, 0x53, 0x58, 0x5A, 0x6D, 0x38, 0x36, 0x42, 0x30, 0x55, 0x56, 0x47, 0x4D, 0x70, 0x5A, 0x77, 0x68, 0x39, 0x34, 0x43, 0x44, 0x6B, ++ 0x6C, 0x44, 0x68, 0x62, 0x5A, 0x73, 0x63, 0x37, 0x74, 0x6B, 0x36, 0x6D, 0x46, 0x42, 0x0A, 0x72, 0x4D, 0x6E, 0x55, 0x56, 0x4E, 0x2B, 0x48, 0x4C, 0x38, 0x63, 0x69, 0x73, 0x69, 0x62, 0x4D, 0x6E, 0x31, 0x6C, 0x55, 0x61, 0x4A, 0x2F, 0x38, 0x76, ++ 0x69, 0x6F, 0x76, 0x78, 0x46, 0x55, 0x63, 0x64, 0x55, 0x42, 0x67, 0x46, 0x34, 0x55, 0x43, 0x56, 0x54, 0x6D, 0x4C, 0x66, 0x77, 0x55, 0x43, 0x41, 0x77, 0x45, 0x41, 0x41, 0x61, 0x4E, 0x43, 0x4D, 0x45, 0x41, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, ++ 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x0A, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x51, 0x59, 0x77, ++ 0x48, 0x51, 0x59, 0x44, 0x56, 0x52, 0x30, 0x4F, 0x42, 0x42, 0x59, 0x45, 0x46, 0x4A, 0x78, 0x66, 0x41, 0x4E, 0x2B, 0x71, 0x41, 0x64, 0x63, 0x77, 0x4B, 0x7A, 0x69, 0x49, 0x6F, 0x72, 0x68, 0x74, 0x53, 0x70, 0x7A, 0x79, 0x45, 0x5A, 0x47, 0x44, ++ 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x0A, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x43, 0x77, 0x55, 0x41, 0x41, 0x34, 0x49, 0x42, 0x41, 0x51, 0x42, 0x4C, 0x4E, 0x71, 0x61, 0x45, 0x64, 0x32, 0x6E, 0x64, 0x4F, 0x78, 0x6D, ++ 0x66, 0x5A, 0x79, 0x4D, 0x49, 0x62, 0x77, 0x35, 0x68, 0x79, 0x66, 0x32, 0x45, 0x33, 0x46, 0x2F, 0x59, 0x4E, 0x6F, 0x48, 0x4E, 0x32, 0x42, 0x74, 0x42, 0x4C, 0x5A, 0x39, 0x67, 0x33, 0x63, 0x63, 0x61, 0x61, 0x4E, 0x6E, 0x52, 0x62, 0x6F, 0x62, ++ 0x68, 0x69, 0x43, 0x50, 0x50, 0x0A, 0x45, 0x39, 0x35, 0x44, 0x7A, 0x2B, 0x49, 0x30, 0x73, 0x77, 0x53, 0x64, 0x48, 0x79, 0x6E, 0x56, 0x76, 0x2F, 0x68, 0x65, 0x79, 0x4E, 0x58, 0x42, 0x76, 0x65, 0x36, 0x53, 0x62, 0x7A, 0x4A, 0x30, 0x38, 0x70, ++ 0x47, 0x43, 0x4C, 0x37, 0x32, 0x43, 0x51, 0x6E, 0x71, 0x74, 0x4B, 0x72, 0x63, 0x67, 0x66, 0x55, 0x32, 0x38, 0x65, 0x6C, 0x55, 0x53, 0x77, 0x68, 0x58, 0x71, 0x76, 0x66, 0x64, 0x71, 0x6C, 0x53, 0x35, 0x73, 0x64, 0x4A, 0x2F, 0x50, 0x48, 0x4C, ++ 0x54, 0x79, 0x0A, 0x78, 0x51, 0x47, 0x6A, 0x68, 0x64, 0x42, 0x79, 0x50, 0x71, 0x31, 0x7A, 0x71, 0x77, 0x75, 0x62, 0x64, 0x51, 0x78, 0x74, 0x52, 0x62, 0x65, 0x4F, 0x6C, 0x4B, 0x79, 0x57, 0x4E, 0x37, 0x57, 0x67, 0x30, 0x49, 0x38, 0x56, 0x52, ++ 0x77, 0x37, 0x6A, 0x36, 0x49, 0x50, 0x64, 0x6A, 0x2F, 0x33, 0x76, 0x51, 0x51, 0x46, 0x33, 0x7A, 0x43, 0x65, 0x70, 0x59, 0x6F, 0x55, 0x7A, 0x38, 0x6A, 0x63, 0x49, 0x37, 0x33, 0x48, 0x50, 0x64, 0x77, 0x62, 0x65, 0x79, 0x42, 0x6B, 0x64, 0x0A, ++ 0x69, 0x45, 0x44, 0x50, 0x66, 0x55, 0x59, 0x64, 0x2F, 0x78, 0x37, 0x48, 0x34, 0x63, 0x37, 0x2F, 0x49, 0x39, 0x76, 0x47, 0x2B, 0x6F, 0x31, 0x56, 0x54, 0x71, 0x6B, 0x43, 0x35, 0x30, 0x63, 0x52, 0x52, 0x6A, 0x37, 0x30, 0x2F, 0x62, 0x31, 0x37, ++ 0x4B, 0x53, 0x61, 0x37, 0x71, 0x57, 0x46, 0x69, 0x4E, 0x79, 0x69, 0x32, 0x4C, 0x53, 0x72, 0x32, 0x45, 0x49, 0x5A, 0x6B, 0x79, 0x58, 0x43, 0x6E, 0x30, 0x71, 0x32, 0x33, 0x4B, 0x58, 0x42, 0x35, 0x36, 0x6A, 0x7A, 0x61, 0x0A, 0x59, 0x79, 0x57, ++ 0x66, 0x2F, 0x57, 0x69, 0x33, 0x4D, 0x4F, 0x78, 0x77, 0x2B, 0x33, 0x57, 0x4B, 0x74, 0x32, 0x31, 0x67, 0x5A, 0x37, 0x49, 0x65, 0x79, 0x4C, 0x6E, 0x70, 0x32, 0x4B, 0x68, 0x76, 0x41, 0x6F, 0x74, 0x6E, 0x44, 0x55, 0x30, 0x6D, 0x56, 0x33, 0x48, ++ 0x61, 0x49, 0x50, 0x7A, 0x42, 0x53, 0x6C, 0x43, 0x4E, 0x73, 0x53, 0x69, 0x36, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, ++ 0x0A, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x43, 0x6F, 0x6D, 0x6D, 0x65, 0x72, 0x63, 0x69, 0x61, 0x6C, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x44, 0x54, ++ 0x44, 0x43, 0x43, 0x41, 0x6A, 0x53, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x49, 0x64, 0x33, 0x63, 0x47, 0x4A, 0x79, 0x61, 0x70, 0x73, 0x58, 0x77, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, ++ 0x51, 0x45, 0x4C, 0x42, 0x51, 0x41, 0x77, 0x52, 0x44, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x56, 0x56, 0x4D, 0x78, 0x46, 0x44, 0x41, 0x53, 0x0A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x4D, ++ 0x43, 0x30, 0x46, 0x6D, 0x5A, 0x6D, 0x6C, 0x79, 0x62, 0x56, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x4D, 0x52, 0x38, 0x77, 0x48, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x44, 0x42, 0x5A, 0x42, 0x5A, 0x6D, 0x5A, 0x70, 0x63, 0x6D, 0x31, 0x55, ++ 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x43, 0x42, 0x44, 0x62, 0x32, 0x31, 0x74, 0x5A, 0x58, 0x4A, 0x6A, 0x61, 0x57, 0x46, 0x73, 0x4D, 0x42, 0x34, 0x58, 0x44, 0x54, 0x45, 0x77, 0x0A, 0x4D, 0x44, 0x45, 0x79, 0x4F, 0x54, 0x45, 0x30, 0x4D, 0x44, 0x59, ++ 0x77, 0x4E, 0x6C, 0x6F, 0x58, 0x44, 0x54, 0x4D, 0x77, 0x4D, 0x54, 0x49, 0x7A, 0x4D, 0x54, 0x45, 0x30, 0x4D, 0x44, 0x59, 0x77, 0x4E, 0x6C, 0x6F, 0x77, 0x52, 0x44, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, ++ 0x43, 0x56, 0x56, 0x4D, 0x78, 0x46, 0x44, 0x41, 0x53, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x4D, 0x43, 0x30, 0x46, 0x6D, 0x5A, 0x6D, 0x6C, 0x79, 0x0A, 0x62, 0x56, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x4D, 0x52, 0x38, 0x77, 0x48, 0x51, ++ 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x44, 0x42, 0x5A, 0x42, 0x5A, 0x6D, 0x5A, 0x70, 0x63, 0x6D, 0x31, 0x55, 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x43, 0x42, 0x44, 0x62, 0x32, 0x31, 0x74, 0x5A, 0x58, 0x4A, 0x6A, 0x61, 0x57, 0x46, 0x73, 0x4D, 0x49, ++ 0x49, 0x42, 0x49, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x45, 0x46, 0x0A, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x51, 0x38, 0x41, 0x4D, 0x49, 0x49, 0x42, 0x43, 0x67, 0x4B, 0x43, 0x41, ++ 0x51, 0x45, 0x41, 0x39, 0x68, 0x74, 0x50, 0x5A, 0x77, 0x63, 0x72, 0x6F, 0x52, 0x58, 0x31, 0x42, 0x69, 0x4C, 0x4C, 0x48, 0x77, 0x47, 0x79, 0x34, 0x33, 0x4E, 0x46, 0x42, 0x6B, 0x52, 0x4A, 0x4C, 0x4C, 0x74, 0x4A, 0x4A, 0x52, 0x54, 0x57, 0x7A, ++ 0x73, 0x4F, 0x33, 0x71, 0x79, 0x78, 0x50, 0x78, 0x6B, 0x45, 0x79, 0x6C, 0x46, 0x66, 0x36, 0x45, 0x71, 0x64, 0x62, 0x0A, 0x44, 0x75, 0x4B, 0x50, 0x48, 0x78, 0x36, 0x47, 0x47, 0x61, 0x65, 0x71, 0x74, 0x53, 0x32, 0x35, 0x58, 0x77, 0x32, 0x4B, ++ 0x77, 0x71, 0x2B, 0x46, 0x4E, 0x58, 0x6B, 0x79, 0x4C, 0x62, 0x73, 0x63, 0x59, 0x6A, 0x66, 0x79, 0x73, 0x56, 0x74, 0x4B, 0x50, 0x63, 0x72, 0x4E, 0x63, 0x56, 0x2F, 0x70, 0x51, 0x72, 0x36, 0x55, 0x36, 0x4D, 0x6A, 0x65, 0x2B, 0x53, 0x4A, 0x49, ++ 0x5A, 0x4D, 0x62, 0x6C, 0x71, 0x38, 0x59, 0x72, 0x62, 0x61, 0x30, 0x46, 0x38, 0x50, 0x72, 0x56, 0x0A, 0x43, 0x38, 0x2B, 0x61, 0x35, 0x66, 0x42, 0x51, 0x70, 0x49, 0x73, 0x37, 0x52, 0x36, 0x55, 0x6A, 0x57, 0x33, 0x70, 0x36, 0x2B, 0x44, 0x4D, ++ 0x2F, 0x75, 0x4F, 0x2B, 0x5A, 0x6C, 0x2B, 0x4D, 0x67, 0x77, 0x64, 0x59, 0x6F, 0x69, 0x63, 0x2B, 0x55, 0x2B, 0x37, 0x6C, 0x46, 0x37, 0x65, 0x4E, 0x41, 0x46, 0x78, 0x48, 0x55, 0x64, 0x50, 0x41, 0x4C, 0x4D, 0x65, 0x49, 0x72, 0x4A, 0x6D, 0x71, ++ 0x62, 0x54, 0x46, 0x65, 0x75, 0x72, 0x43, 0x41, 0x2B, 0x75, 0x6B, 0x56, 0x36, 0x0A, 0x42, 0x66, 0x4F, 0x39, 0x6D, 0x32, 0x6B, 0x56, 0x72, 0x6E, 0x31, 0x4F, 0x49, 0x47, 0x50, 0x45, 0x4E, 0x58, 0x59, 0x36, 0x42, 0x77, 0x4C, 0x4A, 0x4E, 0x2F, ++ 0x33, 0x48, 0x52, 0x2B, 0x37, 0x6F, 0x38, 0x58, 0x59, 0x64, 0x63, 0x78, 0x58, 0x79, 0x6C, 0x36, 0x53, 0x31, 0x79, 0x48, 0x70, 0x35, 0x32, 0x55, 0x4B, 0x71, 0x4B, 0x33, 0x39, 0x63, 0x2F, 0x73, 0x34, 0x6D, 0x54, 0x36, 0x4E, 0x6D, 0x67, 0x54, ++ 0x57, 0x76, 0x52, 0x4C, 0x70, 0x55, 0x48, 0x68, 0x77, 0x77, 0x0A, 0x4D, 0x6D, 0x57, 0x64, 0x35, 0x6A, 0x79, 0x54, 0x58, 0x6C, 0x42, 0x4F, 0x65, 0x75, 0x4D, 0x36, 0x31, 0x47, 0x37, 0x4D, 0x47, 0x76, 0x76, 0x35, 0x30, 0x6A, 0x65, 0x75, 0x4A, ++ 0x43, 0x71, 0x72, 0x56, 0x77, 0x4D, 0x69, 0x4B, 0x41, 0x31, 0x4A, 0x64, 0x58, 0x2B, 0x33, 0x4B, 0x4E, 0x70, 0x31, 0x76, 0x34, 0x37, 0x6A, 0x33, 0x41, 0x35, 0x35, 0x4D, 0x51, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x6F, 0x30, 0x49, 0x77, 0x51, ++ 0x44, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x0A, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x6E, 0x5A, 0x50, 0x47, 0x55, 0x34, 0x74, 0x65, 0x79, 0x71, 0x38, 0x2F, 0x6E, 0x78, 0x34, 0x50, 0x35, 0x5A, 0x6D, 0x56, 0x76, 0x43, 0x54, 0x32, ++ 0x6C, 0x49, 0x38, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x42, 0x41, 0x66, 0x38, 0x45, ++ 0x42, 0x41, 0x4D, 0x43, 0x0A, 0x41, 0x51, 0x59, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x45, 0x42, 0x41, 0x46, 0x69, 0x73, 0x39, 0x41, 0x51, ++ 0x4F, 0x7A, 0x63, 0x41, 0x4E, 0x2F, 0x77, 0x72, 0x39, 0x31, 0x4C, 0x6F, 0x57, 0x58, 0x79, 0x6D, 0x39, 0x65, 0x32, 0x69, 0x5A, 0x57, 0x45, 0x6E, 0x53, 0x74, 0x42, 0x30, 0x33, 0x54, 0x58, 0x38, 0x6E, 0x66, 0x55, 0x59, 0x47, 0x58, 0x55, 0x50, ++ 0x47, 0x0A, 0x68, 0x69, 0x34, 0x2B, 0x63, 0x37, 0x49, 0x6D, 0x66, 0x55, 0x2B, 0x54, 0x71, 0x62, 0x62, 0x45, 0x4B, 0x70, 0x71, 0x72, 0x49, 0x5A, 0x63, 0x55, 0x73, 0x64, 0x36, 0x4D, 0x30, 0x36, 0x75, 0x4A, 0x46, 0x64, 0x68, 0x72, 0x4A, 0x4E, ++ 0x54, 0x78, 0x46, 0x71, 0x37, 0x59, 0x70, 0x46, 0x7A, 0x55, 0x66, 0x31, 0x47, 0x4F, 0x37, 0x52, 0x67, 0x42, 0x73, 0x5A, 0x4E, 0x6A, 0x76, 0x62, 0x7A, 0x34, 0x59, 0x59, 0x43, 0x61, 0x6E, 0x72, 0x48, 0x4F, 0x51, 0x6E, 0x44, 0x69, 0x0A, 0x71, ++ 0x58, 0x30, 0x47, 0x4A, 0x58, 0x30, 0x6E, 0x6F, 0x66, 0x35, 0x76, 0x37, 0x4C, 0x4D, 0x65, 0x4A, 0x4E, 0x72, 0x6A, 0x53, 0x31, 0x55, 0x61, 0x41, 0x44, 0x73, 0x31, 0x74, 0x44, 0x76, 0x5A, 0x31, 0x31, 0x30, 0x77, 0x2F, 0x59, 0x45, 0x54, 0x69, ++ 0x66, 0x4C, 0x43, 0x42, 0x69, 0x76, 0x74, 0x5A, 0x38, 0x53, 0x4F, 0x79, 0x55, 0x4F, 0x79, 0x58, 0x47, 0x73, 0x56, 0x69, 0x51, 0x4B, 0x38, 0x59, 0x76, 0x78, 0x4F, 0x38, 0x72, 0x55, 0x7A, 0x71, 0x72, 0x4A, 0x76, 0x0A, 0x30, 0x77, 0x71, 0x69, ++ 0x55, 0x4F, 0x50, 0x32, 0x4F, 0x2B, 0x67, 0x75, 0x52, 0x4D, 0x4C, 0x62, 0x5A, 0x6A, 0x69, 0x70, 0x4D, 0x31, 0x5A, 0x49, 0x38, 0x57, 0x30, 0x62, 0x4D, 0x34, 0x30, 0x4E, 0x6A, 0x44, 0x39, 0x67, 0x4E, 0x35, 0x33, 0x54, 0x79, 0x6D, 0x31, 0x2B, ++ 0x4E, 0x48, 0x34, 0x4E, 0x6E, 0x33, 0x4A, 0x32, 0x69, 0x78, 0x75, 0x66, 0x63, 0x76, 0x31, 0x53, 0x4E, 0x55, 0x46, 0x46, 0x41, 0x70, 0x59, 0x76, 0x48, 0x4C, 0x4B, 0x61, 0x63, 0x30, 0x6B, 0x68, 0x0A, 0x73, 0x55, 0x6C, 0x48, 0x52, 0x55, 0x65, ++ 0x30, 0x37, 0x32, 0x6F, 0x30, 0x45, 0x63, 0x6C, 0x4E, 0x6D, 0x73, 0x78, 0x5A, 0x74, 0x39, 0x59, 0x43, 0x6E, 0x6C, 0x70, 0x4F, 0x5A, 0x62, 0x57, 0x55, 0x72, 0x68, 0x76, 0x66, 0x4B, 0x62, 0x41, 0x57, 0x38, 0x62, 0x38, 0x41, 0x6E, 0x67, 0x63, ++ 0x36, 0x46, 0x32, 0x53, 0x31, 0x42, 0x4C, 0x55, 0x6A, 0x49, 0x5A, 0x6B, 0x4B, 0x6C, 0x54, 0x75, 0x58, 0x66, 0x4F, 0x38, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, ++ 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x69, 0x6E, 0x67, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, ++ 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x44, 0x54, 0x44, 0x43, 0x43, 0x41, 0x6A, 0x53, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x49, 0x66, 0x45, 0x38, 0x45, 0x4F, 0x52, 0x7A, 0x55, 0x6D, 0x53, 0x30, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, ++ 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x46, 0x42, 0x51, 0x41, 0x77, 0x52, 0x44, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x56, 0x56, 0x4D, 0x78, 0x46, 0x44, 0x41, 0x53, 0x0A, ++ 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x4D, 0x43, 0x30, 0x46, 0x6D, 0x5A, 0x6D, 0x6C, 0x79, 0x62, 0x56, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x4D, 0x52, 0x38, 0x77, 0x48, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x44, 0x42, 0x5A, 0x42, ++ 0x5A, 0x6D, 0x5A, 0x70, 0x63, 0x6D, 0x31, 0x55, 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x43, 0x42, 0x4F, 0x5A, 0x58, 0x52, 0x33, 0x62, 0x33, 0x4A, 0x72, 0x61, 0x57, 0x35, 0x6E, 0x4D, 0x42, 0x34, 0x58, 0x44, 0x54, 0x45, 0x77, 0x0A, 0x4D, 0x44, 0x45, ++ 0x79, 0x4F, 0x54, 0x45, 0x30, 0x4D, 0x44, 0x67, 0x79, 0x4E, 0x46, 0x6F, 0x58, 0x44, 0x54, 0x4D, 0x77, 0x4D, 0x54, 0x49, 0x7A, 0x4D, 0x54, 0x45, 0x30, 0x4D, 0x44, 0x67, 0x79, 0x4E, 0x46, 0x6F, 0x77, 0x52, 0x44, 0x45, 0x4C, 0x4D, 0x41, 0x6B, ++ 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x56, 0x56, 0x4D, 0x78, 0x46, 0x44, 0x41, 0x53, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x4D, 0x43, 0x30, 0x46, 0x6D, 0x5A, 0x6D, 0x6C, 0x79, 0x0A, 0x62, 0x56, 0x52, 0x79, 0x64, 0x58, ++ 0x4E, 0x30, 0x4D, 0x52, 0x38, 0x77, 0x48, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x44, 0x42, 0x5A, 0x42, 0x5A, 0x6D, 0x5A, 0x70, 0x63, 0x6D, 0x31, 0x55, 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x43, 0x42, 0x4F, 0x5A, 0x58, 0x52, 0x33, 0x62, 0x33, ++ 0x4A, 0x72, 0x61, 0x57, 0x35, 0x6E, 0x4D, 0x49, 0x49, 0x42, 0x49, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x45, 0x46, 0x0A, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x51, 0x38, 0x41, 0x4D, ++ 0x49, 0x49, 0x42, 0x43, 0x67, 0x4B, 0x43, 0x41, 0x51, 0x45, 0x41, 0x74, 0x49, 0x54, 0x4D, 0x4D, 0x78, 0x63, 0x75, 0x61, 0x35, 0x52, 0x73, 0x61, 0x32, 0x46, 0x53, 0x6F, 0x4F, 0x75, 0x6A, 0x7A, 0x33, 0x6D, 0x55, 0x54, 0x4F, 0x57, 0x55, 0x67, ++ 0x4A, 0x6E, 0x4C, 0x56, 0x57, 0x52, 0x45, 0x5A, 0x59, 0x39, 0x6E, 0x5A, 0x4F, 0x49, 0x47, 0x34, 0x31, 0x77, 0x33, 0x53, 0x66, 0x59, 0x76, 0x6D, 0x34, 0x53, 0x45, 0x0A, 0x48, 0x69, 0x33, 0x79, 0x59, 0x4A, 0x30, 0x77, 0x54, 0x73, 0x79, 0x45, ++ 0x68, 0x65, 0x49, 0x73, 0x7A, 0x78, 0x36, 0x65, 0x2F, 0x6A, 0x61, 0x72, 0x4D, 0x33, 0x63, 0x31, 0x52, 0x4E, 0x67, 0x31, 0x6C, 0x68, 0x6F, 0x39, 0x4E, 0x75, 0x68, 0x36, 0x44, 0x74, 0x6A, 0x56, 0x52, 0x36, 0x46, 0x71, 0x61, 0x59, 0x76, 0x5A, ++ 0x2F, 0x4C, 0x73, 0x36, 0x72, 0x6E, 0x6C, 0x61, 0x31, 0x66, 0x54, 0x57, 0x63, 0x62, 0x75, 0x61, 0x6B, 0x43, 0x4E, 0x72, 0x6D, 0x72, 0x65, 0x49, 0x0A, 0x64, 0x49, 0x63, 0x4D, 0x48, 0x6C, 0x2B, 0x35, 0x6E, 0x69, 0x33, 0x36, 0x71, 0x31, 0x4D, ++ 0x72, 0x33, 0x4C, 0x74, 0x32, 0x50, 0x70, 0x4E, 0x4D, 0x43, 0x41, 0x69, 0x4D, 0x48, 0x71, 0x49, 0x6A, 0x48, 0x4E, 0x52, 0x71, 0x72, 0x53, 0x4B, 0x36, 0x6D, 0x51, 0x45, 0x75, 0x62, 0x57, 0x58, 0x4C, 0x76, 0x69, 0x52, 0x6D, 0x56, 0x53, 0x52, ++ 0x4C, 0x51, 0x45, 0x53, 0x78, 0x47, 0x39, 0x66, 0x68, 0x77, 0x6F, 0x58, 0x41, 0x33, 0x68, 0x41, 0x2F, 0x50, 0x65, 0x32, 0x34, 0x0A, 0x2F, 0x50, 0x48, 0x78, 0x49, 0x31, 0x50, 0x63, 0x76, 0x32, 0x57, 0x58, 0x62, 0x39, 0x6E, 0x35, 0x51, 0x48, ++ 0x47, 0x4E, 0x66, 0x62, 0x32, 0x56, 0x31, 0x4D, 0x36, 0x2B, 0x6F, 0x46, 0x34, 0x6E, 0x49, 0x39, 0x37, 0x39, 0x70, 0x74, 0x41, 0x6D, 0x44, 0x67, 0x41, 0x70, 0x36, 0x7A, 0x78, 0x47, 0x38, 0x44, 0x31, 0x67, 0x76, 0x7A, 0x39, 0x51, 0x30, 0x74, ++ 0x77, 0x6D, 0x51, 0x56, 0x47, 0x65, 0x46, 0x44, 0x64, 0x43, 0x42, 0x4B, 0x4E, 0x77, 0x56, 0x36, 0x67, 0x62, 0x0A, 0x68, 0x2B, 0x30, 0x74, 0x2B, 0x6E, 0x76, 0x75, 0x6A, 0x41, 0x72, 0x6A, 0x71, 0x57, 0x61, 0x4A, 0x47, 0x63, 0x74, 0x42, 0x2B, ++ 0x64, 0x31, 0x45, 0x4E, 0x6D, 0x48, 0x50, 0x34, 0x6E, 0x64, 0x47, 0x79, 0x48, 0x33, 0x32, 0x39, 0x4A, 0x4B, 0x42, 0x4E, 0x76, 0x33, 0x62, 0x4E, 0x50, 0x46, 0x79, 0x66, 0x76, 0x4D, 0x4D, 0x46, 0x72, 0x32, 0x30, 0x46, 0x51, 0x49, 0x44, 0x41, ++ 0x51, 0x41, 0x42, 0x6F, 0x30, 0x49, 0x77, 0x51, 0x44, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x0A, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x42, 0x78, 0x2F, 0x53, 0x35, 0x35, 0x7A, 0x61, 0x77, 0x6D, 0x36, 0x69, 0x51, 0x4C, 0x53, 0x77, ++ 0x65, 0x6C, 0x41, 0x51, 0x55, 0x48, 0x54, 0x45, 0x79, 0x4C, 0x30, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, ++ 0x48, 0x51, 0x38, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x41, 0x4D, 0x43, 0x0A, 0x41, 0x51, 0x59, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x46, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x45, ++ 0x42, 0x41, 0x49, 0x6C, 0x58, 0x73, 0x68, 0x5A, 0x36, 0x71, 0x4D, 0x4C, 0x39, 0x31, 0x74, 0x6D, 0x62, 0x6D, 0x7A, 0x54, 0x43, 0x6E, 0x4C, 0x51, 0x79, 0x46, 0x45, 0x32, 0x6E, 0x70, 0x4E, 0x2F, 0x73, 0x76, 0x71, 0x65, 0x2B, 0x2B, 0x45, 0x50, ++ 0x62, 0x6B, 0x54, 0x66, 0x4F, 0x74, 0x44, 0x49, 0x75, 0x0A, 0x55, 0x46, 0x55, 0x61, 0x4E, 0x55, 0x35, 0x32, 0x51, 0x33, 0x45, 0x67, 0x37, 0x35, 0x4E, 0x33, 0x54, 0x68, 0x56, 0x77, 0x4C, 0x6F, 0x66, 0x44, 0x77, 0x52, 0x31, 0x74, 0x33, 0x4D, ++ 0x75, 0x31, 0x4A, 0x39, 0x51, 0x73, 0x56, 0x74, 0x46, 0x53, 0x55, 0x7A, 0x70, 0x45, 0x30, 0x6E, 0x50, 0x49, 0x78, 0x42, 0x73, 0x46, 0x5A, 0x56, 0x70, 0x69, 0x6B, 0x70, 0x7A, 0x75, 0x51, 0x59, 0x30, 0x78, 0x32, 0x2B, 0x63, 0x30, 0x36, 0x6C, ++ 0x6B, 0x68, 0x31, 0x51, 0x46, 0x36, 0x0A, 0x31, 0x32, 0x53, 0x34, 0x5A, 0x44, 0x6E, 0x4E, 0x79, 0x65, 0x32, 0x76, 0x37, 0x55, 0x73, 0x44, 0x53, 0x4B, 0x65, 0x67, 0x6D, 0x51, 0x47, 0x41, 0x33, 0x47, 0x57, 0x6A, 0x4E, 0x71, 0x35, 0x6C, 0x57, ++ 0x55, 0x68, 0x50, 0x67, 0x6B, 0x76, 0x49, 0x5A, 0x66, 0x46, 0x58, 0x48, 0x65, 0x56, 0x5A, 0x4C, 0x67, 0x6F, 0x2F, 0x62, 0x4E, 0x6A, 0x52, 0x39, 0x65, 0x55, 0x4A, 0x74, 0x47, 0x78, 0x55, 0x41, 0x41, 0x72, 0x67, 0x46, 0x55, 0x32, 0x48, 0x64, ++ 0x57, 0x32, 0x33, 0x0A, 0x57, 0x4A, 0x5A, 0x61, 0x33, 0x57, 0x33, 0x53, 0x41, 0x4B, 0x44, 0x30, 0x6D, 0x30, 0x69, 0x2B, 0x77, 0x7A, 0x65, 0x6B, 0x75, 0x6A, 0x62, 0x67, 0x66, 0x49, 0x65, 0x46, 0x6C, 0x78, 0x6F, 0x56, 0x6F, 0x74, 0x34, 0x75, ++ 0x6F, 0x6C, 0x75, 0x39, 0x72, 0x78, 0x6A, 0x35, 0x6B, 0x46, 0x44, 0x4E, 0x63, 0x46, 0x6E, 0x34, 0x4A, 0x32, 0x64, 0x48, 0x79, 0x38, 0x65, 0x67, 0x42, 0x7A, 0x70, 0x39, 0x30, 0x53, 0x78, 0x64, 0x62, 0x42, 0x6B, 0x36, 0x5A, 0x72, 0x56, 0x39, ++ 0x0A, 0x2F, 0x5A, 0x46, 0x76, 0x67, 0x72, 0x47, 0x2B, 0x43, 0x4A, 0x50, 0x62, 0x46, 0x45, 0x66, 0x78, 0x6F, 0x6A, 0x66, 0x48, 0x52, 0x5A, 0x34, 0x38, 0x78, 0x33, 0x65, 0x76, 0x5A, 0x4B, 0x69, 0x54, 0x33, 0x2F, 0x5A, 0x70, 0x67, 0x34, 0x4A, ++ 0x67, 0x38, 0x6B, 0x6C, 0x43, 0x4E, 0x4F, 0x31, 0x61, 0x41, 0x46, 0x53, 0x46, 0x48, 0x42, 0x59, 0x32, 0x6B, 0x67, 0x78, 0x63, 0x2B, 0x71, 0x61, 0x74, 0x76, 0x39, 0x73, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, ++ 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x50, 0x72, 0x65, 0x6D, 0x69, 0x75, 0x6D, 0x0A, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, ++ 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x52, 0x6A, 0x43, 0x43, 0x41, 0x79, 0x36, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x49, 0x62, 0x59, 0x77, 0x55, 0x52, 0x72, 0x47, 0x6D, 0x43, 0x75, 0x34, 0x77, 0x44, 0x51, 0x59, ++ 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4D, 0x42, 0x51, 0x41, 0x77, 0x51, 0x54, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x56, 0x56, 0x4D, 0x78, 0x46, 0x44, 0x41, ++ 0x53, 0x0A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x4D, 0x43, 0x30, 0x46, 0x6D, 0x5A, 0x6D, 0x6C, 0x79, 0x62, 0x56, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x4D, 0x52, 0x77, 0x77, 0x47, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x44, 0x42, ++ 0x4E, 0x42, 0x5A, 0x6D, 0x5A, 0x70, 0x63, 0x6D, 0x31, 0x55, 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x43, 0x42, 0x51, 0x63, 0x6D, 0x56, 0x74, 0x61, 0x58, 0x56, 0x74, 0x4D, 0x42, 0x34, 0x58, 0x44, 0x54, 0x45, 0x77, 0x4D, 0x44, 0x45, 0x79, 0x0A, 0x4F, ++ 0x54, 0x45, 0x30, 0x4D, 0x54, 0x41, 0x7A, 0x4E, 0x6C, 0x6F, 0x58, 0x44, 0x54, 0x51, 0x77, 0x4D, 0x54, 0x49, 0x7A, 0x4D, 0x54, 0x45, 0x30, 0x4D, 0x54, 0x41, 0x7A, 0x4E, 0x6C, 0x6F, 0x77, 0x51, 0x54, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, ++ 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x56, 0x56, 0x4D, 0x78, 0x46, 0x44, 0x41, 0x53, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x4D, 0x43, 0x30, 0x46, 0x6D, 0x5A, 0x6D, 0x6C, 0x79, 0x62, 0x56, 0x52, 0x79, 0x0A, 0x64, 0x58, 0x4E, 0x30, ++ 0x4D, 0x52, 0x77, 0x77, 0x47, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x44, 0x42, 0x4E, 0x42, 0x5A, 0x6D, 0x5A, 0x70, 0x63, 0x6D, 0x31, 0x55, 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x43, 0x42, 0x51, 0x63, 0x6D, 0x56, 0x74, 0x61, 0x58, 0x56, 0x74, ++ 0x4D, 0x49, 0x49, 0x43, 0x49, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x45, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x67, 0x38, 0x41, 0x0A, 0x4D, 0x49, 0x49, 0x43, 0x43, 0x67, 0x4B, ++ 0x43, 0x41, 0x67, 0x45, 0x41, 0x78, 0x42, 0x4C, 0x66, 0x71, 0x56, 0x2F, 0x2B, 0x51, 0x64, 0x33, 0x64, 0x39, 0x5A, 0x2B, 0x4B, 0x34, 0x2F, 0x61, 0x73, 0x34, 0x54, 0x78, 0x34, 0x6D, 0x72, 0x7A, 0x59, 0x38, 0x48, 0x39, 0x36, 0x6F, 0x44, 0x4D, ++ 0x71, 0x33, 0x49, 0x30, 0x67, 0x57, 0x36, 0x34, 0x74, 0x62, 0x2B, 0x65, 0x54, 0x32, 0x54, 0x5A, 0x77, 0x61, 0x6D, 0x6A, 0x50, 0x6A, 0x6C, 0x47, 0x6A, 0x68, 0x56, 0x74, 0x6E, 0x0A, 0x42, 0x4B, 0x41, 0x51, 0x4A, 0x47, 0x39, 0x64, 0x4B, 0x49, ++ 0x4C, 0x42, 0x6C, 0x31, 0x66, 0x59, 0x53, 0x43, 0x6B, 0x54, 0x74, 0x75, 0x47, 0x2B, 0x6B, 0x55, 0x33, 0x66, 0x68, 0x51, 0x78, 0x54, 0x47, 0x4A, 0x6F, 0x65, 0x4A, 0x4B, 0x4A, 0x50, 0x6A, 0x2F, 0x43, 0x69, 0x68, 0x51, 0x76, 0x4C, 0x39, 0x43, ++ 0x6C, 0x2F, 0x30, 0x71, 0x52, 0x59, 0x37, 0x69, 0x5A, 0x4E, 0x79, 0x61, 0x71, 0x6F, 0x65, 0x35, 0x72, 0x5A, 0x2B, 0x6A, 0x6A, 0x65, 0x52, 0x46, 0x63, 0x56, 0x0A, 0x35, 0x66, 0x69, 0x4D, 0x79, 0x4E, 0x6C, 0x49, 0x34, 0x67, 0x30, 0x57, 0x4A, ++ 0x78, 0x30, 0x65, 0x79, 0x49, 0x4F, 0x46, 0x4A, 0x62, 0x65, 0x36, 0x71, 0x6C, 0x56, 0x42, 0x7A, 0x41, 0x4D, 0x69, 0x53, 0x79, 0x32, 0x52, 0x6A, 0x59, 0x76, 0x6D, 0x69, 0x61, 0x39, 0x6D, 0x78, 0x2B, 0x6E, 0x2F, 0x4B, 0x2B, 0x6B, 0x38, 0x72, ++ 0x4E, 0x72, 0x53, 0x73, 0x38, 0x50, 0x68, 0x61, 0x4A, 0x79, 0x4A, 0x2B, 0x48, 0x6F, 0x41, 0x56, 0x74, 0x37, 0x30, 0x56, 0x5A, 0x56, 0x73, 0x0A, 0x2B, 0x37, 0x70, 0x6B, 0x33, 0x57, 0x4B, 0x4C, 0x33, 0x77, 0x74, 0x33, 0x4D, 0x75, 0x74, 0x69, ++ 0x7A, 0x43, 0x61, 0x61, 0x6D, 0x37, 0x75, 0x71, 0x59, 0x6F, 0x4E, 0x4D, 0x74, 0x41, 0x5A, 0x36, 0x4D, 0x4D, 0x67, 0x70, 0x76, 0x2B, 0x30, 0x47, 0x54, 0x5A, 0x65, 0x35, 0x48, 0x4D, 0x51, 0x78, 0x4B, 0x39, 0x56, 0x66, 0x76, 0x46, 0x4D, 0x53, ++ 0x46, 0x35, 0x79, 0x5A, 0x56, 0x79, 0x6C, 0x6D, 0x64, 0x32, 0x45, 0x68, 0x4D, 0x51, 0x63, 0x75, 0x4A, 0x55, 0x6D, 0x64, 0x0A, 0x47, 0x50, 0x4C, 0x75, 0x38, 0x79, 0x74, 0x78, 0x6A, 0x4C, 0x57, 0x36, 0x4F, 0x51, 0x64, 0x4A, 0x64, 0x2F, 0x7A, ++ 0x76, 0x4C, 0x70, 0x4B, 0x51, 0x42, 0x59, 0x30, 0x74, 0x4C, 0x33, 0x64, 0x37, 0x37, 0x30, 0x4F, 0x2F, 0x4E, 0x62, 0x75, 0x61, 0x32, 0x50, 0x6C, 0x7A, 0x70, 0x79, 0x7A, 0x79, 0x30, 0x46, 0x66, 0x75, 0x4B, 0x45, 0x34, 0x6D, 0x58, 0x34, 0x2B, ++ 0x51, 0x61, 0x41, 0x6B, 0x76, 0x75, 0x50, 0x6A, 0x63, 0x42, 0x75, 0x6B, 0x75, 0x6D, 0x6A, 0x35, 0x52, 0x0A, 0x70, 0x39, 0x45, 0x69, 0x78, 0x41, 0x71, 0x6E, 0x4F, 0x45, 0x68, 0x73, 0x73, 0x2F, 0x6E, 0x2F, 0x66, 0x61, 0x75, 0x47, 0x56, 0x2B, ++ 0x4F, 0x36, 0x31, 0x6F, 0x56, 0x34, 0x64, 0x37, 0x70, 0x44, 0x36, 0x6B, 0x68, 0x2F, 0x39, 0x74, 0x69, 0x2B, 0x49, 0x32, 0x30, 0x65, 0x76, 0x39, 0x45, 0x32, 0x62, 0x46, 0x68, 0x63, 0x38, 0x65, 0x36, 0x6B, 0x47, 0x56, 0x51, 0x61, 0x39, 0x51, ++ 0x50, 0x53, 0x64, 0x75, 0x62, 0x68, 0x6A, 0x4C, 0x30, 0x38, 0x73, 0x39, 0x4E, 0x49, 0x0A, 0x53, 0x2B, 0x4C, 0x49, 0x2B, 0x48, 0x2B, 0x53, 0x71, 0x48, 0x5A, 0x47, 0x6E, 0x45, 0x4A, 0x6C, 0x50, 0x71, 0x51, 0x65, 0x77, 0x51, 0x63, 0x44, 0x57, ++ 0x6B, 0x59, 0x74, 0x75, 0x4A, 0x66, 0x7A, 0x74, 0x39, 0x57, 0x79, 0x56, 0x53, 0x48, 0x76, 0x75, 0x74, 0x78, 0x4D, 0x41, 0x4A, 0x66, 0x37, 0x46, 0x4A, 0x55, 0x6E, 0x4D, 0x37, 0x2F, 0x6F, 0x51, 0x30, 0x64, 0x47, 0x30, 0x67, 0x69, 0x5A, 0x46, ++ 0x6D, 0x41, 0x37, 0x6D, 0x6E, 0x37, 0x53, 0x35, 0x75, 0x30, 0x34, 0x0A, 0x36, 0x75, 0x77, 0x42, 0x48, 0x6A, 0x78, 0x49, 0x56, 0x6B, 0x6B, 0x4A, 0x78, 0x30, 0x77, 0x33, 0x41, 0x4A, 0x36, 0x49, 0x44, 0x73, 0x42, 0x7A, 0x34, 0x57, 0x39, 0x6D, ++ 0x36, 0x58, 0x4A, 0x48, 0x4D, 0x44, 0x34, 0x51, 0x35, 0x51, 0x73, 0x44, 0x79, 0x5A, 0x70, 0x43, 0x41, 0x47, 0x7A, 0x46, 0x6C, 0x48, 0x35, 0x68, 0x78, 0x49, 0x72, 0x66, 0x66, 0x34, 0x49, 0x61, 0x43, 0x31, 0x6E, 0x45, 0x57, 0x54, 0x4A, 0x33, ++ 0x73, 0x37, 0x78, 0x67, 0x61, 0x56, 0x59, 0x35, 0x0A, 0x2F, 0x62, 0x51, 0x47, 0x65, 0x79, 0x7A, 0x57, 0x5A, 0x44, 0x62, 0x5A, 0x76, 0x55, 0x6A, 0x74, 0x68, 0x42, 0x39, 0x2B, 0x70, 0x53, 0x4B, 0x50, 0x4B, 0x72, 0x68, 0x43, 0x39, 0x49, 0x4B, ++ 0x33, 0x31, 0x46, 0x4F, 0x51, 0x65, 0x45, 0x34, 0x74, 0x47, 0x76, 0x32, 0x42, 0x62, 0x30, 0x54, 0x58, 0x4F, 0x77, 0x46, 0x30, 0x6C, 0x6B, 0x4C, 0x67, 0x41, 0x4F, 0x49, 0x75, 0x61, 0x2B, 0x72, 0x46, 0x37, 0x6E, 0x4B, 0x73, 0x75, 0x37, 0x2F, ++ 0x2B, 0x36, 0x71, 0x71, 0x6F, 0x0A, 0x2B, 0x4E, 0x7A, 0x32, 0x73, 0x6E, 0x6D, 0x4B, 0x74, 0x6D, 0x63, 0x43, 0x41, 0x77, 0x45, 0x41, 0x41, 0x61, 0x4E, 0x43, 0x4D, 0x45, 0x41, 0x77, 0x48, 0x51, 0x59, 0x44, 0x56, 0x52, 0x30, 0x4F, 0x42, 0x42, ++ 0x59, 0x45, 0x46, 0x4A, 0x33, 0x41, 0x5A, 0x36, 0x59, 0x4D, 0x49, 0x74, 0x6B, 0x6D, 0x39, 0x55, 0x57, 0x72, 0x70, 0x6D, 0x56, 0x53, 0x45, 0x53, 0x66, 0x59, 0x52, 0x61, 0x78, 0x6A, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, ++ 0x45, 0x42, 0x0A, 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x51, 0x44, 0x41, 0x67, 0x45, 0x47, 0x4D, 0x41, 0x30, 0x47, 0x43, ++ 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x44, 0x41, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x41, 0x51, 0x43, 0x7A, 0x56, 0x30, 0x30, 0x51, 0x59, 0x6B, 0x34, 0x36, 0x35, 0x4B, 0x7A, 0x71, 0x75, 0x42, 0x79, 0x76, 0x0A, ++ 0x4D, 0x69, 0x50, 0x49, 0x73, 0x30, 0x6C, 0x61, 0x55, 0x5A, 0x78, 0x32, 0x4B, 0x49, 0x31, 0x35, 0x71, 0x6C, 0x64, 0x47, 0x46, 0x39, 0x58, 0x31, 0x55, 0x76, 0x61, 0x33, 0x52, 0x4F, 0x67, 0x49, 0x52, 0x4C, 0x38, 0x59, 0x68, 0x4E, 0x49, 0x4C, ++ 0x67, 0x4D, 0x33, 0x46, 0x45, 0x76, 0x30, 0x41, 0x56, 0x51, 0x56, 0x68, 0x68, 0x30, 0x48, 0x63, 0x74, 0x53, 0x53, 0x65, 0x50, 0x4D, 0x54, 0x59, 0x79, 0x50, 0x74, 0x77, 0x6E, 0x69, 0x39, 0x34, 0x6C, 0x6F, 0x4D, 0x67, 0x0A, 0x4E, 0x74, 0x35, ++ 0x38, 0x44, 0x32, 0x6B, 0x54, 0x69, 0x4B, 0x56, 0x31, 0x4E, 0x70, 0x67, 0x49, 0x70, 0x73, 0x62, 0x66, 0x72, 0x4D, 0x37, 0x6A, 0x57, 0x4E, 0x61, 0x33, 0x50, 0x74, 0x36, 0x36, 0x38, 0x2B, 0x73, 0x30, 0x51, 0x4E, 0x69, 0x69, 0x67, 0x66, 0x56, ++ 0x34, 0x50, 0x79, 0x2F, 0x56, 0x70, 0x66, 0x7A, 0x5A, 0x6F, 0x74, 0x52, 0x65, 0x42, 0x41, 0x34, 0x58, 0x72, 0x66, 0x35, 0x42, 0x38, 0x4F, 0x57, 0x79, 0x63, 0x76, 0x70, 0x45, 0x67, 0x6A, 0x4E, 0x43, 0x0A, 0x36, 0x43, 0x31, 0x59, 0x39, 0x31, ++ 0x61, 0x4D, 0x59, 0x6A, 0x2B, 0x36, 0x51, 0x72, 0x43, 0x63, 0x44, 0x46, 0x78, 0x2B, 0x4C, 0x6D, 0x55, 0x6D, 0x58, 0x46, 0x4E, 0x50, 0x41, 0x4C, 0x4A, 0x34, 0x66, 0x71, 0x45, 0x4E, 0x6D, 0x53, 0x32, 0x4E, 0x75, 0x42, 0x32, 0x4F, 0x6F, 0x73, ++ 0x53, 0x77, 0x2F, 0x57, 0x44, 0x51, 0x4D, 0x4B, 0x53, 0x4F, 0x79, 0x41, 0x52, 0x69, 0x71, 0x63, 0x54, 0x74, 0x4E, 0x64, 0x35, 0x36, 0x6C, 0x2B, 0x30, 0x4F, 0x4F, 0x46, 0x36, 0x53, 0x0A, 0x4C, 0x35, 0x4E, 0x77, 0x70, 0x61, 0x6D, 0x63, 0x62, ++ 0x36, 0x64, 0x39, 0x45, 0x78, 0x31, 0x2B, 0x78, 0x67, 0x68, 0x49, 0x73, 0x56, 0x35, 0x6E, 0x36, 0x31, 0x45, 0x49, 0x4A, 0x65, 0x6E, 0x6D, 0x4A, 0x57, 0x74, 0x53, 0x4B, 0x5A, 0x47, 0x63, 0x30, 0x6A, 0x6C, 0x7A, 0x43, 0x46, 0x66, 0x65, 0x6D, ++ 0x51, 0x61, 0x30, 0x57, 0x35, 0x30, 0x51, 0x42, 0x75, 0x48, 0x43, 0x41, 0x4B, 0x69, 0x34, 0x48, 0x45, 0x6F, 0x43, 0x43, 0x68, 0x54, 0x51, 0x77, 0x55, 0x48, 0x4B, 0x0A, 0x2B, 0x34, 0x77, 0x31, 0x49, 0x58, 0x32, 0x43, 0x4F, 0x50, 0x4B, 0x70, ++ 0x56, 0x4A, 0x45, 0x5A, 0x4E, 0x5A, 0x4F, 0x55, 0x62, 0x57, 0x6F, 0x36, 0x78, 0x62, 0x4C, 0x51, 0x75, 0x34, 0x6D, 0x47, 0x6B, 0x2B, 0x69, 0x62, 0x79, 0x51, 0x38, 0x36, 0x70, 0x33, 0x71, 0x34, 0x6F, 0x66, 0x42, 0x34, 0x52, 0x76, 0x72, 0x38, ++ 0x4E, 0x79, 0x2F, 0x6C, 0x69, 0x6F, 0x54, 0x7A, 0x33, 0x2F, 0x34, 0x45, 0x32, 0x61, 0x46, 0x6F, 0x6F, 0x43, 0x38, 0x6B, 0x34, 0x67, 0x6D, 0x56, 0x0A, 0x42, 0x74, 0x57, 0x56, 0x79, 0x75, 0x45, 0x6B, 0x6C, 0x75, 0x74, 0x38, 0x39, 0x70, 0x4D, ++ 0x46, 0x75, 0x2B, 0x31, 0x7A, 0x36, 0x53, 0x33, 0x52, 0x64, 0x54, 0x6E, 0x58, 0x35, 0x79, 0x54, 0x62, 0x32, 0x45, 0x35, 0x66, 0x51, 0x34, 0x2B, 0x65, 0x30, 0x42, 0x51, 0x35, 0x76, 0x31, 0x56, 0x77, 0x53, 0x4A, 0x6C, 0x58, 0x4D, 0x62, 0x53, ++ 0x63, 0x37, 0x6B, 0x71, 0x59, 0x41, 0x35, 0x59, 0x77, 0x48, 0x32, 0x41, 0x47, 0x37, 0x68, 0x73, 0x6A, 0x2F, 0x6F, 0x46, 0x67, 0x0A, 0x49, 0x78, 0x70, 0x48, 0x59, 0x6F, 0x57, 0x6C, 0x7A, 0x42, 0x6B, 0x30, 0x67, 0x47, 0x2B, 0x7A, 0x72, 0x42, ++ 0x72, 0x6A, 0x6E, 0x2F, 0x42, 0x37, 0x53, 0x4B, 0x33, 0x56, 0x41, 0x64, 0x6C, 0x6E, 0x74, 0x71, 0x6C, 0x79, 0x6B, 0x2B, 0x6F, 0x74, 0x5A, 0x72, 0x57, 0x79, 0x75, 0x4F, 0x51, 0x39, 0x50, 0x4C, 0x4C, 0x76, 0x54, 0x49, 0x7A, 0x71, 0x36, 0x77, ++ 0x65, 0x2F, 0x71, 0x7A, 0x57, 0x61, 0x56, 0x59, 0x61, 0x38, 0x47, 0x4B, 0x61, 0x31, 0x71, 0x46, 0x36, 0x30, 0x0A, 0x67, 0x32, 0x78, 0x72, 0x61, 0x55, 0x44, 0x54, 0x6E, 0x39, 0x7A, 0x78, 0x77, 0x32, 0x6C, 0x72, 0x75, 0x65, 0x46, 0x74, 0x43, ++ 0x66, 0x54, 0x78, 0x71, 0x6C, 0x42, 0x32, 0x43, 0x6E, 0x70, 0x39, 0x65, 0x68, 0x65, 0x68, 0x56, 0x5A, 0x5A, 0x43, 0x6D, 0x54, 0x45, 0x4A, 0x33, 0x57, 0x41, 0x52, 0x6A, 0x51, 0x55, 0x77, 0x66, 0x75, 0x61, 0x4F, 0x52, 0x74, 0x47, 0x64, 0x46, ++ 0x4E, 0x72, 0x48, 0x46, 0x2B, 0x51, 0x46, 0x6C, 0x6F, 0x7A, 0x45, 0x4A, 0x4C, 0x55, 0x62, 0x0A, 0x7A, 0x78, 0x51, 0x48, 0x73, 0x6B, 0x44, 0x34, 0x6F, 0x35, 0x35, 0x42, 0x68, 0x72, 0x77, 0x45, 0x30, 0x47, 0x75, 0x57, 0x79, 0x43, 0x71, 0x41, ++ 0x4E, 0x50, 0x32, 0x2F, 0x37, 0x77, 0x61, 0x6A, 0x33, 0x56, 0x6A, 0x46, 0x68, 0x54, 0x30, 0x2B, 0x6A, 0x2F, 0x36, 0x65, 0x4B, 0x65, 0x43, 0x32, 0x75, 0x41, 0x6C, 0x6F, 0x47, 0x52, 0x77, 0x59, 0x51, 0x77, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, ++ 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x50, 0x72, 0x65, 0x6D, ++ 0x69, 0x75, 0x6D, 0x20, 0x45, 0x43, 0x43, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, ++ 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x42, 0x2F, 0x6A, 0x43, 0x43, 0x41, 0x59, 0x57, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x49, ++ 0x64, 0x4A, 0x63, 0x6C, 0x69, 0x73, 0x63, 0x2F, 0x65, 0x6C, 0x51, 0x77, 0x43, 0x67, 0x59, 0x49, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x45, 0x41, 0x77, 0x4D, 0x77, 0x52, 0x54, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, ++ 0x42, 0x68, 0x4D, 0x43, 0x56, 0x56, 0x4D, 0x78, 0x46, 0x44, 0x41, 0x53, 0x42, 0x67, 0x4E, 0x56, 0x0A, 0x42, 0x41, 0x6F, 0x4D, 0x43, 0x30, 0x46, 0x6D, 0x5A, 0x6D, 0x6C, 0x79, 0x62, 0x56, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x4D, 0x53, 0x41, ++ 0x77, 0x48, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x44, 0x42, 0x64, 0x42, 0x5A, 0x6D, 0x5A, 0x70, 0x63, 0x6D, 0x31, 0x55, 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x43, 0x42, 0x51, 0x63, 0x6D, 0x56, 0x74, 0x61, 0x58, 0x56, 0x74, 0x49, 0x45, 0x56, ++ 0x44, 0x51, 0x7A, 0x41, 0x65, 0x46, 0x77, 0x30, 0x78, 0x4D, 0x44, 0x41, 0x78, 0x0A, 0x4D, 0x6A, 0x6B, 0x78, 0x4E, 0x44, 0x49, 0x77, 0x4D, 0x6A, 0x52, 0x61, 0x46, 0x77, 0x30, 0x30, 0x4D, 0x44, 0x45, 0x79, 0x4D, 0x7A, 0x45, 0x78, 0x4E, 0x44, ++ 0x49, 0x77, 0x4D, 0x6A, 0x52, 0x61, 0x4D, 0x45, 0x55, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6C, 0x56, 0x54, 0x4D, 0x52, 0x51, 0x77, 0x45, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x44, 0x41, ++ 0x74, 0x42, 0x5A, 0x6D, 0x5A, 0x70, 0x63, 0x6D, 0x31, 0x55, 0x0A, 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x44, 0x45, 0x67, 0x4D, 0x42, 0x34, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x77, 0x77, 0x58, 0x51, 0x57, 0x5A, 0x6D, 0x61, 0x58, 0x4A, 0x74, 0x56, ++ 0x48, 0x4A, 0x31, 0x63, 0x33, 0x51, 0x67, 0x55, 0x48, 0x4A, 0x6C, 0x62, 0x57, 0x6C, 0x31, 0x62, 0x53, 0x42, 0x46, 0x51, 0x30, 0x4D, 0x77, 0x64, 0x6A, 0x41, 0x51, 0x42, 0x67, 0x63, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x49, 0x42, 0x42, ++ 0x67, 0x55, 0x72, 0x67, 0x51, 0x51, 0x41, 0x0A, 0x49, 0x67, 0x4E, 0x69, 0x41, 0x41, 0x51, 0x4E, 0x4D, 0x46, 0x34, 0x62, 0x46, 0x5A, 0x30, 0x44, 0x30, 0x4B, 0x46, 0x35, 0x4E, 0x62, 0x63, 0x36, 0x50, 0x4A, 0x4A, 0x36, 0x79, 0x68, 0x55, 0x63, ++ 0x7A, 0x57, 0x4C, 0x7A, 0x6E, 0x43, 0x5A, 0x63, 0x42, 0x7A, 0x33, 0x6C, 0x56, 0x50, 0x71, 0x6A, 0x31, 0x73, 0x77, 0x53, 0x36, 0x76, 0x51, 0x55, 0x58, 0x2B, 0x69, 0x4F, 0x47, 0x61, 0x73, 0x76, 0x4C, 0x6B, 0x6A, 0x6D, 0x72, 0x42, 0x68, 0x44, ++ 0x65, 0x4B, 0x7A, 0x51, 0x0A, 0x4E, 0x38, 0x4F, 0x39, 0x73, 0x73, 0x30, 0x73, 0x35, 0x6B, 0x66, 0x69, 0x47, 0x75, 0x5A, 0x6A, 0x75, 0x44, 0x30, 0x75, 0x4C, 0x33, 0x6A, 0x45, 0x54, 0x39, 0x76, 0x30, 0x44, 0x36, 0x52, 0x6F, 0x54, 0x46, 0x56, ++ 0x79, 0x61, 0x35, 0x55, 0x64, 0x54, 0x68, 0x68, 0x43, 0x6C, 0x58, 0x6A, 0x4D, 0x4E, 0x7A, 0x79, 0x52, 0x34, 0x70, 0x74, 0x6C, 0x4B, 0x79, 0x6D, 0x6A, 0x51, 0x6A, 0x42, 0x41, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, ++ 0x57, 0x0A, 0x42, 0x42, 0x53, 0x61, 0x72, 0x79, 0x6C, 0x36, 0x77, 0x42, 0x45, 0x31, 0x4E, 0x53, 0x5A, 0x52, 0x4D, 0x41, 0x44, 0x44, 0x61, 0x76, 0x35, 0x41, 0x31, 0x61, 0x37, 0x57, 0x50, 0x44, 0x41, 0x50, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x52, ++ 0x4D, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x54, 0x41, 0x44, 0x41, 0x51, 0x48, 0x2F, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x42, 0x42, 0x6A, 0x41, 0x4B, 0x0A, 0x42, ++ 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x77, 0x4E, 0x6E, 0x41, 0x44, 0x42, 0x6B, 0x41, 0x6A, 0x41, 0x58, 0x43, 0x66, 0x4F, 0x48, 0x69, 0x46, 0x42, 0x61, 0x72, 0x38, 0x6A, 0x41, 0x51, 0x72, 0x39, 0x48, 0x58, ++ 0x2F, 0x56, 0x73, 0x61, 0x6F, 0x62, 0x67, 0x78, 0x43, 0x64, 0x30, 0x35, 0x44, 0x68, 0x54, 0x31, 0x77, 0x56, 0x2F, 0x47, 0x7A, 0x54, 0x6A, 0x78, 0x69, 0x2B, 0x7A, 0x79, 0x67, 0x6B, 0x38, 0x4E, 0x35, 0x33, 0x58, 0x0A, 0x35, 0x37, 0x68, 0x47, ++ 0x38, 0x66, 0x32, 0x68, 0x34, 0x6E, 0x45, 0x43, 0x4D, 0x45, 0x4A, 0x5A, 0x68, 0x30, 0x50, 0x55, 0x55, 0x64, 0x2B, 0x36, 0x30, 0x77, 0x6B, 0x79, 0x57, 0x73, 0x36, 0x49, 0x66, 0x6C, 0x63, 0x39, 0x6E, 0x46, 0x39, 0x43, 0x61, 0x2F, 0x55, 0x48, ++ 0x4C, 0x62, 0x58, 0x77, 0x67, 0x70, 0x50, 0x35, 0x57, 0x57, 0x2B, 0x75, 0x5A, 0x50, 0x70, 0x59, 0x35, 0x59, 0x73, 0x65, 0x34, 0x32, 0x4F, 0x2B, 0x74, 0x59, 0x48, 0x4E, 0x62, 0x77, 0x4B, 0x4D, 0x0A, 0x65, 0x51, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, ++ 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, ++ 0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x20, 0x43, 0x41, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, ++ 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x44, 0x75, 0x7A, 0x43, 0x43, 0x41, 0x71, 0x4F, 0x67, 0x41, 0x77, 0x49, ++ 0x42, 0x41, 0x67, 0x49, 0x44, 0x42, 0x45, 0x54, 0x41, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x42, 0x51, 0x55, 0x41, 0x4D, 0x48, 0x34, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, ++ 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6C, 0x42, 0x4D, 0x4D, 0x53, 0x49, 0x77, 0x49, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x0A, 0x45, 0x78, 0x6C, 0x56, 0x62, 0x6D, 0x6C, 0x36, 0x5A, 0x58, 0x52, 0x76, 0x49, 0x46, 0x52, 0x6C, 0x59, 0x32, ++ 0x68, 0x75, 0x62, 0x32, 0x78, 0x76, 0x5A, 0x32, 0x6C, 0x6C, 0x63, 0x79, 0x42, 0x54, 0x4C, 0x6B, 0x45, 0x75, 0x4D, 0x53, 0x63, 0x77, 0x4A, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4C, 0x45, 0x78, 0x35, 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x64, 0x57, ++ 0x30, 0x67, 0x51, 0x32, 0x56, 0x79, 0x64, 0x47, 0x6C, 0x6D, 0x61, 0x57, 0x4E, 0x68, 0x64, 0x47, 0x6C, 0x76, 0x0A, 0x62, 0x69, 0x42, 0x42, 0x64, 0x58, 0x52, 0x6F, 0x62, 0x33, 0x4A, 0x70, 0x64, 0x48, 0x6B, 0x78, 0x49, 0x6A, 0x41, 0x67, 0x42, ++ 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x47, 0x55, 0x4E, 0x6C, 0x63, 0x6E, 0x52, 0x31, 0x62, 0x53, 0x42, 0x55, 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x47, 0x56, 0x6B, 0x49, 0x45, 0x35, 0x6C, 0x64, 0x48, 0x64, 0x76, 0x63, 0x6D, 0x73, 0x67, 0x51, ++ 0x30, 0x45, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x44, 0x67, 0x78, 0x4D, 0x44, 0x49, 0x79, 0x0A, 0x4D, 0x54, 0x49, 0x77, 0x4E, 0x7A, 0x4D, 0x33, 0x57, 0x68, 0x63, 0x4E, 0x4D, 0x6A, 0x6B, 0x78, 0x4D, 0x6A, 0x4D, 0x78, 0x4D, 0x54, 0x49, 0x77, ++ 0x4E, 0x7A, 0x4D, 0x33, 0x57, 0x6A, 0x42, 0x2B, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x51, 0x54, 0x44, 0x45, 0x69, 0x4D, 0x43, 0x41, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x5A, ++ 0x56, 0x57, 0x35, 0x70, 0x65, 0x6D, 0x56, 0x30, 0x62, 0x79, 0x42, 0x55, 0x0A, 0x5A, 0x57, 0x4E, 0x6F, 0x62, 0x6D, 0x39, 0x73, 0x62, 0x32, 0x64, 0x70, 0x5A, 0x58, 0x4D, 0x67, 0x55, 0x79, 0x35, 0x42, 0x4C, 0x6A, 0x45, 0x6E, 0x4D, 0x43, 0x55, ++ 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x78, 0x4D, 0x65, 0x51, 0x32, 0x56, 0x79, 0x64, 0x48, 0x56, 0x74, 0x49, 0x45, 0x4E, 0x6C, 0x63, 0x6E, 0x52, 0x70, 0x5A, 0x6D, 0x6C, 0x6A, 0x59, 0x58, 0x52, 0x70, 0x62, 0x32, 0x34, 0x67, 0x51, 0x58, 0x56, ++ 0x30, 0x61, 0x47, 0x39, 0x79, 0x61, 0x58, 0x52, 0x35, 0x0A, 0x4D, 0x53, 0x49, 0x77, 0x49, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x6C, 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x64, 0x57, 0x30, 0x67, 0x56, 0x48, 0x4A, 0x31, 0x63, 0x33, ++ 0x52, 0x6C, 0x5A, 0x43, 0x42, 0x4F, 0x5A, 0x58, 0x52, 0x33, 0x62, 0x33, 0x4A, 0x72, 0x49, 0x45, 0x4E, 0x42, 0x4D, 0x49, 0x49, 0x42, 0x49, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, ++ 0x45, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x0A, 0x41, 0x51, 0x38, 0x41, 0x4D, 0x49, 0x49, 0x42, 0x43, 0x67, 0x4B, 0x43, 0x41, 0x51, 0x45, 0x41, 0x34, 0x2F, 0x74, 0x39, 0x6F, 0x33, 0x4B, 0x36, 0x77, 0x76, 0x44, 0x4A, 0x46, 0x49, 0x66, 0x31, 0x61, ++ 0x77, 0x46, 0x4F, 0x34, 0x57, 0x35, 0x41, 0x42, 0x37, 0x70, 0x74, 0x4A, 0x31, 0x31, 0x2F, 0x39, 0x31, 0x73, 0x74, 0x73, 0x31, 0x72, 0x48, 0x55, 0x56, 0x2B, 0x72, 0x70, 0x44, 0x4B, 0x6D, 0x59, 0x59, 0x65, 0x32, 0x62, 0x67, 0x2B, 0x47, 0x30, ++ 0x6A, 0x41, 0x43, 0x0A, 0x6C, 0x2F, 0x6A, 0x58, 0x61, 0x56, 0x65, 0x68, 0x47, 0x44, 0x6C, 0x64, 0x61, 0x6D, 0x52, 0x35, 0x78, 0x67, 0x46, 0x5A, 0x72, 0x44, 0x77, 0x78, 0x53, 0x6A, 0x68, 0x38, 0x30, 0x67, 0x54, 0x53, 0x53, 0x79, 0x6A, 0x6F, ++ 0x49, 0x46, 0x38, 0x37, 0x42, 0x36, 0x4C, 0x4D, 0x54, 0x58, 0x50, 0x62, 0x38, 0x36, 0x35, 0x50, 0x78, 0x31, 0x62, 0x56, 0x57, 0x71, 0x65, 0x57, 0x69, 0x66, 0x72, 0x7A, 0x71, 0x32, 0x6A, 0x55, 0x49, 0x34, 0x5A, 0x5A, 0x4A, 0x38, 0x38, 0x4A, ++ 0x0A, 0x4A, 0x37, 0x79, 0x73, 0x62, 0x6E, 0x4B, 0x44, 0x48, 0x44, 0x42, 0x79, 0x33, 0x2B, 0x43, 0x69, 0x36, 0x64, 0x4C, 0x68, 0x64, 0x48, 0x55, 0x5A, 0x76, 0x53, 0x71, 0x65, 0x65, 0x78, 0x56, 0x55, 0x42, 0x42, 0x76, 0x58, 0x51, 0x7A, 0x6D, ++ 0x74, 0x56, 0x53, 0x6A, 0x46, 0x34, 0x68, 0x71, 0x37, 0x39, 0x4D, 0x44, 0x6B, 0x72, 0x6A, 0x68, 0x4A, 0x4D, 0x38, 0x78, 0x32, 0x68, 0x5A, 0x38, 0x35, 0x52, 0x64, 0x4B, 0x6B, 0x6E, 0x76, 0x49, 0x53, 0x6A, 0x46, 0x48, 0x34, 0x0A, 0x66, 0x4F, ++ 0x51, 0x74, 0x66, 0x2F, 0x57, 0x73, 0x58, 0x2B, 0x73, 0x57, 0x6E, 0x37, 0x45, 0x74, 0x30, 0x62, 0x72, 0x4D, 0x6B, 0x55, 0x4A, 0x33, 0x54, 0x43, 0x58, 0x4A, 0x6B, 0x44, 0x68, 0x76, 0x32, 0x2F, 0x44, 0x4D, 0x2B, 0x34, 0x34, 0x65, 0x6C, 0x31, ++ 0x6B, 0x2B, 0x31, 0x57, 0x42, 0x4F, 0x35, 0x67, 0x55, 0x6F, 0x37, 0x55, 0x6C, 0x35, 0x45, 0x30, 0x75, 0x36, 0x53, 0x4E, 0x73, 0x76, 0x2B, 0x58, 0x4C, 0x54, 0x4F, 0x63, 0x72, 0x2B, 0x48, 0x39, 0x67, 0x30, 0x0A, 0x63, 0x76, 0x57, 0x30, 0x51, ++ 0x4D, 0x38, 0x78, 0x41, 0x63, 0x50, 0x73, 0x33, 0x68, 0x45, 0x74, 0x46, 0x31, 0x30, 0x66, 0x75, 0x46, 0x44, 0x52, 0x58, 0x68, 0x6D, 0x6E, 0x61, 0x64, 0x34, 0x48, 0x4D, 0x79, 0x6A, 0x4B, 0x55, 0x4A, 0x58, 0x35, 0x70, 0x31, 0x54, 0x4C, 0x56, ++ 0x49, 0x5A, 0x51, 0x52, 0x61, 0x6E, 0x35, 0x53, 0x51, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x6F, 0x30, 0x49, 0x77, 0x51, 0x44, 0x41, 0x50, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x52, 0x4D, 0x42, 0x0A, 0x41, 0x66, 0x38, 0x45, 0x42, 0x54, 0x41, 0x44, ++ 0x41, 0x51, 0x48, 0x2F, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x51, 0x49, 0x64, 0x73, 0x33, 0x4C, 0x42, 0x2F, 0x38, 0x6B, 0x39, 0x73, 0x58, 0x4E, 0x37, 0x62, 0x75, 0x51, 0x76, 0x4F, 0x4B, 0x45, ++ 0x4E, 0x30, 0x5A, 0x31, 0x39, 0x7A, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x51, 0x59, 0x77, 0x0A, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, ++ 0x4E, 0x41, 0x51, 0x45, 0x46, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x45, 0x42, 0x41, 0x4B, 0x61, 0x6F, 0x72, 0x53, 0x4C, 0x4F, 0x41, 0x54, 0x32, 0x6D, 0x6F, 0x2F, 0x39, 0x69, 0x30, 0x45, 0x69, 0x64, 0x69, 0x31, 0x35, 0x79, 0x73, 0x48, 0x68, ++ 0x45, 0x34, 0x39, 0x77, 0x63, 0x72, 0x77, 0x6E, 0x39, 0x49, 0x30, 0x6A, 0x36, 0x76, 0x53, 0x72, 0x45, 0x75, 0x56, 0x55, 0x45, 0x74, 0x52, 0x43, 0x6A, 0x0A, 0x6A, 0x53, 0x66, 0x65, 0x43, 0x34, 0x4A, 0x6A, 0x30, 0x4F, 0x37, 0x65, 0x44, 0x44, ++ 0x64, 0x35, 0x51, 0x56, 0x73, 0x69, 0x73, 0x72, 0x43, 0x61, 0x51, 0x56, 0x79, 0x6D, 0x63, 0x4F, 0x44, 0x55, 0x30, 0x48, 0x66, 0x4C, 0x49, 0x39, 0x4D, 0x41, 0x34, 0x47, 0x78, 0x57, 0x4C, 0x2B, 0x46, 0x70, 0x44, 0x51, 0x33, 0x5A, 0x71, 0x72, ++ 0x38, 0x68, 0x67, 0x56, 0x44, 0x5A, 0x42, 0x71, 0x57, 0x6F, 0x2F, 0x35, 0x55, 0x33, 0x30, 0x4B, 0x72, 0x2B, 0x34, 0x72, 0x50, 0x31, 0x0A, 0x6D, 0x53, 0x31, 0x46, 0x68, 0x49, 0x72, 0x6C, 0x51, 0x67, 0x6E, 0x58, 0x64, 0x41, 0x49, 0x76, 0x39, ++ 0x34, 0x6E, 0x59, 0x6D, 0x65, 0x6D, 0x38, 0x4A, 0x39, 0x52, 0x48, 0x6A, 0x62, 0x6F, 0x4E, 0x52, 0x68, 0x78, 0x33, 0x7A, 0x78, 0x53, 0x6B, 0x48, 0x4C, 0x6D, 0x6B, 0x4D, 0x63, 0x53, 0x63, 0x4B, 0x48, 0x51, 0x44, 0x4E, 0x50, 0x38, 0x7A, 0x47, ++ 0x53, 0x61, 0x6C, 0x36, 0x51, 0x31, 0x30, 0x74, 0x7A, 0x36, 0x58, 0x78, 0x6E, 0x62, 0x6F, 0x4A, 0x35, 0x61, 0x6A, 0x0A, 0x5A, 0x74, 0x33, 0x68, 0x72, 0x76, 0x4A, 0x42, 0x57, 0x38, 0x71, 0x59, 0x56, 0x6F, 0x4E, 0x7A, 0x63, 0x4F, 0x53, 0x47, ++ 0x47, 0x74, 0x49, 0x78, 0x51, 0x62, 0x6F, 0x76, 0x76, 0x69, 0x30, 0x54, 0x57, 0x6E, 0x5A, 0x76, 0x54, 0x75, 0x68, 0x4F, 0x67, 0x51, 0x34, 0x2F, 0x57, 0x77, 0x4D, 0x69, 0x6F, 0x42, 0x4B, 0x2B, 0x5A, 0x6C, 0x67, 0x52, 0x53, 0x73, 0x73, 0x44, ++ 0x78, 0x4C, 0x51, 0x71, 0x4B, 0x69, 0x32, 0x57, 0x46, 0x2B, 0x41, 0x35, 0x56, 0x4C, 0x78, 0x49, 0x0A, 0x30, 0x33, 0x59, 0x6E, 0x6E, 0x5A, 0x6F, 0x74, 0x42, 0x71, 0x62, 0x4A, 0x37, 0x44, 0x6E, 0x53, 0x71, 0x39, 0x75, 0x66, 0x6D, 0x67, 0x73, ++ 0x6E, 0x41, 0x6A, 0x55, 0x70, 0x73, 0x55, 0x43, 0x56, 0x35, 0x2F, 0x6E, 0x6F, 0x6E, 0x46, 0x57, 0x49, 0x47, 0x55, 0x62, 0x57, 0x74, 0x7A, 0x54, 0x31, 0x66, 0x73, 0x34, 0x35, 0x6D, 0x74, 0x6B, 0x34, 0x38, 0x56, 0x48, 0x33, 0x54, 0x79, 0x77, ++ 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x54, 0x57, 0x43, 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, ++ 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, ++ 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x44, 0x65, 0x7A, 0x43, 0x43, 0x41, 0x6D, 0x4F, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x42, 0x41, 0x54, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, ++ 0x42, 0x41, 0x51, 0x55, 0x46, 0x41, 0x44, 0x42, 0x66, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x55, 0x56, 0x7A, 0x45, 0x53, 0x4D, 0x42, 0x41, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, ++ 0x4A, 0x0A, 0x56, 0x45, 0x46, 0x4A, 0x56, 0x30, 0x46, 0x4F, 0x4C, 0x55, 0x4E, 0x42, 0x4D, 0x52, 0x41, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4C, 0x44, 0x41, 0x64, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x42, 0x4D, 0x53, ++ 0x6F, 0x77, 0x4B, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x44, 0x43, 0x46, 0x55, 0x56, 0x30, 0x4E, 0x42, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x32, 0x56, 0x79, 0x64, 0x47, 0x6C, 0x6D, 0x61, 0x57, 0x4E, 0x68, 0x0A, 0x64, ++ 0x47, 0x6C, 0x76, 0x62, 0x69, 0x42, 0x42, 0x64, 0x58, 0x52, 0x6F, 0x62, 0x33, 0x4A, 0x70, 0x64, 0x48, 0x6B, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x44, 0x67, 0x77, 0x4F, 0x44, 0x49, 0x34, 0x4D, 0x44, 0x63, 0x79, 0x4E, 0x44, 0x4D, 0x7A, 0x57, ++ 0x68, 0x63, 0x4E, 0x4D, 0x7A, 0x41, 0x78, 0x4D, 0x6A, 0x4D, 0x78, 0x4D, 0x54, 0x55, 0x31, 0x4F, 0x54, 0x55, 0x35, 0x57, 0x6A, 0x42, 0x66, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x0A, 0x45, 0x77, 0x4A, 0x55, ++ 0x56, 0x7A, 0x45, 0x53, 0x4D, 0x42, 0x41, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, 0x4A, 0x56, 0x45, 0x46, 0x4A, 0x56, 0x30, 0x46, 0x4F, 0x4C, 0x55, 0x4E, 0x42, 0x4D, 0x52, 0x41, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4C, ++ 0x44, 0x41, 0x64, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x42, 0x4D, 0x53, 0x6F, 0x77, 0x4B, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x44, 0x43, 0x46, 0x55, 0x56, 0x30, 0x4E, 0x42, 0x0A, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, ++ 0x67, 0x51, 0x32, 0x56, 0x79, 0x64, 0x47, 0x6C, 0x6D, 0x61, 0x57, 0x4E, 0x68, 0x64, 0x47, 0x6C, 0x76, 0x62, 0x69, 0x42, 0x42, 0x64, 0x58, 0x52, 0x6F, 0x62, 0x33, 0x4A, 0x70, 0x64, 0x48, 0x6B, 0x77, 0x67, 0x67, 0x45, 0x69, 0x4D, 0x41, 0x30, ++ 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x42, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x45, 0x4B, 0x0A, 0x41, 0x6F, 0x49, 0x42, 0x41, 0x51, 0x43, 0x77, 0x66, 0x6E, ++ 0x4B, 0x34, 0x70, 0x41, 0x4F, 0x55, 0x35, 0x71, 0x66, 0x65, 0x43, 0x54, 0x69, 0x52, 0x53, 0x68, 0x46, 0x41, 0x68, 0x36, 0x64, 0x38, 0x57, 0x57, 0x51, 0x55, 0x65, 0x37, 0x55, 0x52, 0x45, 0x4E, 0x33, 0x2B, 0x76, 0x39, 0x58, 0x41, 0x75, 0x31, ++ 0x62, 0x69, 0x68, 0x53, 0x58, 0x30, 0x4E, 0x58, 0x49, 0x50, 0x2B, 0x46, 0x50, 0x51, 0x51, 0x65, 0x46, 0x45, 0x41, 0x63, 0x4B, 0x30, 0x48, 0x4D, 0x4D, 0x78, 0x0A, 0x51, 0x68, 0x5A, 0x48, 0x68, 0x54, 0x4D, 0x69, 0x64, 0x72, 0x49, 0x4B, 0x62, ++ 0x77, 0x2F, 0x6C, 0x4A, 0x56, 0x42, 0x50, 0x68, 0x59, 0x61, 0x2B, 0x76, 0x35, 0x67, 0x75, 0x45, 0x47, 0x63, 0x65, 0x76, 0x68, 0x45, 0x46, 0x68, 0x67, 0x57, 0x51, 0x78, 0x46, 0x6E, 0x51, 0x66, 0x48, 0x67, 0x51, 0x73, 0x49, 0x42, 0x63, 0x74, ++ 0x2B, 0x48, 0x48, 0x4B, 0x33, 0x58, 0x4C, 0x66, 0x4A, 0x2B, 0x75, 0x74, 0x64, 0x47, 0x64, 0x49, 0x7A, 0x64, 0x6A, 0x70, 0x39, 0x78, 0x43, 0x0A, 0x6F, 0x69, 0x32, 0x53, 0x42, 0x42, 0x74, 0x51, 0x77, 0x58, 0x75, 0x34, 0x50, 0x68, 0x76, 0x4A, ++ 0x56, 0x67, 0x53, 0x4C, 0x4C, 0x31, 0x4B, 0x62, 0x72, 0x61, 0x6C, 0x57, 0x36, 0x63, 0x48, 0x2F, 0x72, 0x61, 0x6C, 0x59, 0x68, 0x7A, 0x43, 0x32, 0x67, 0x66, 0x65, 0x58, 0x52, 0x66, 0x77, 0x5A, 0x56, 0x7A, 0x73, 0x72, 0x62, 0x2B, 0x52, 0x48, ++ 0x39, 0x4A, 0x6C, 0x46, 0x2F, 0x68, 0x33, 0x78, 0x2B, 0x4A, 0x65, 0x6A, 0x69, 0x42, 0x30, 0x33, 0x48, 0x46, 0x79, 0x50, 0x0A, 0x34, 0x48, 0x59, 0x6C, 0x6D, 0x6C, 0x44, 0x34, 0x6F, 0x46, 0x54, 0x2F, 0x52, 0x4A, 0x42, 0x32, 0x49, 0x39, 0x49, ++ 0x79, 0x78, 0x73, 0x4F, 0x72, 0x42, 0x72, 0x2F, 0x38, 0x2B, 0x37, 0x2F, 0x7A, 0x72, 0x58, 0x32, 0x53, 0x59, 0x67, 0x4A, 0x62, 0x4B, 0x64, 0x4D, 0x31, 0x6F, 0x35, 0x4F, 0x61, 0x51, 0x32, 0x52, 0x67, 0x58, 0x62, 0x4C, 0x36, 0x4D, 0x76, 0x38, ++ 0x37, 0x42, 0x4B, 0x39, 0x4E, 0x51, 0x47, 0x72, 0x35, 0x78, 0x2B, 0x50, 0x76, 0x49, 0x2F, 0x31, 0x72, 0x0A, 0x79, 0x2B, 0x55, 0x50, 0x69, 0x7A, 0x67, 0x4E, 0x37, 0x67, 0x72, 0x38, 0x2F, 0x67, 0x2B, 0x59, 0x6E, 0x7A, 0x41, 0x78, 0x33, 0x57, ++ 0x78, 0x53, 0x5A, 0x66, 0x6D, 0x4C, 0x67, 0x62, 0x34, 0x69, 0x34, 0x52, 0x78, 0x59, 0x41, 0x37, 0x71, 0x52, 0x47, 0x34, 0x6B, 0x48, 0x41, 0x67, 0x4D, 0x42, 0x41, 0x41, 0x47, 0x6A, 0x51, 0x6A, 0x42, 0x41, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, ++ 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x42, 0x0A, 0x42, 0x6A, 0x41, 0x50, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x52, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x54, 0x41, 0x44, 0x41, 0x51, 0x48, 0x2F, 0x4D, ++ 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x52, 0x71, 0x4F, 0x46, 0x73, 0x6D, 0x6A, 0x64, 0x36, 0x4C, 0x57, 0x76, 0x4A, 0x50, 0x65, 0x6C, 0x53, 0x44, 0x47, 0x52, 0x6A, 0x6A, 0x43, 0x44, 0x57, 0x6D, 0x75, ++ 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x0A, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x55, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x51, 0x45, 0x41, 0x50, 0x4E, 0x56, 0x33, 0x50, 0x64, 0x72, 0x66, 0x69, 0x62, 0x71, 0x48, ++ 0x44, 0x41, 0x68, 0x55, 0x61, 0x69, 0x42, 0x51, 0x6B, 0x72, 0x36, 0x77, 0x51, 0x54, 0x32, 0x35, 0x4A, 0x6D, 0x53, 0x44, 0x43, 0x69, 0x2F, 0x6F, 0x51, 0x4D, 0x43, 0x58, 0x4B, 0x43, 0x65, 0x43, 0x4D, 0x45, 0x72, 0x4A, 0x6B, 0x2F, 0x39, 0x71, ++ 0x35, 0x36, 0x59, 0x41, 0x66, 0x34, 0x6C, 0x43, 0x0A, 0x6D, 0x74, 0x59, 0x52, 0x35, 0x56, 0x50, 0x4F, 0x4C, 0x38, 0x7A, 0x79, 0x32, 0x67, 0x58, 0x45, 0x2F, 0x75, 0x4A, 0x51, 0x78, 0x44, 0x71, 0x47, 0x66, 0x63, 0x7A, 0x61, 0x66, 0x68, 0x41, ++ 0x4A, 0x4F, 0x35, 0x49, 0x31, 0x4B, 0x6C, 0x4F, 0x79, 0x2F, 0x75, 0x73, 0x72, 0x42, 0x64, 0x6C, 0x73, 0x58, 0x65, 0x62, 0x51, 0x37, 0x39, 0x4E, 0x71, 0x5A, 0x70, 0x34, 0x56, 0x4B, 0x49, 0x56, 0x36, 0x36, 0x49, 0x49, 0x41, 0x72, 0x42, 0x36, ++ 0x6E, 0x43, 0x57, 0x6C, 0x57, 0x0A, 0x51, 0x74, 0x4E, 0x6F, 0x55, 0x52, 0x69, 0x2B, 0x56, 0x4A, 0x71, 0x2F, 0x52, 0x45, 0x47, 0x36, 0x53, 0x62, 0x34, 0x67, 0x75, 0x6D, 0x6C, 0x63, 0x37, 0x72, 0x68, 0x33, 0x7A, 0x63, 0x35, 0x73, 0x48, 0x36, ++ 0x32, 0x44, 0x6C, 0x68, 0x68, 0x39, 0x44, 0x72, 0x55, 0x55, 0x4F, 0x59, 0x54, 0x78, 0x4B, 0x4F, 0x6B, 0x74, 0x6F, 0x35, 0x35, 0x37, 0x48, 0x6E, 0x70, 0x79, 0x57, 0x6F, 0x4F, 0x7A, 0x65, 0x57, 0x2F, 0x76, 0x74, 0x50, 0x7A, 0x51, 0x43, 0x71, ++ 0x56, 0x59, 0x0A, 0x54, 0x30, 0x62, 0x66, 0x2B, 0x32, 0x31, 0x35, 0x57, 0x66, 0x4B, 0x45, 0x49, 0x6C, 0x4B, 0x75, 0x44, 0x38, 0x7A, 0x37, 0x66, 0x44, 0x76, 0x6E, 0x61, 0x73, 0x70, 0x48, 0x59, 0x63, 0x4E, 0x36, 0x2B, 0x4E, 0x4F, 0x53, 0x42, ++ 0x42, 0x2B, 0x34, 0x49, 0x49, 0x54, 0x68, 0x4E, 0x6C, 0x51, 0x57, 0x78, 0x30, 0x44, 0x65, 0x4F, 0x34, 0x70, 0x7A, 0x33, 0x4E, 0x2F, 0x47, 0x43, 0x55, 0x7A, 0x66, 0x37, 0x4E, 0x72, 0x2F, 0x31, 0x46, 0x4E, 0x43, 0x6F, 0x63, 0x6E, 0x79, 0x0A, ++ 0x59, 0x68, 0x30, 0x69, 0x67, 0x7A, 0x79, 0x58, 0x78, 0x66, 0x6B, 0x5A, 0x59, 0x69, 0x65, 0x73, 0x5A, 0x53, 0x4C, 0x58, 0x30, 0x7A, 0x7A, 0x47, 0x35, 0x59, 0x36, 0x79, 0x55, 0x38, 0x78, 0x4A, 0x7A, 0x72, 0x77, 0x77, 0x2F, 0x6E, 0x73, 0x4F, ++ 0x4D, 0x35, 0x44, 0x37, 0x37, 0x64, 0x49, 0x55, 0x6B, 0x52, 0x38, 0x48, 0x72, 0x77, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, ++ 0x2D, 0x2D, 0x0A, 0x0A, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x43, 0x6F, 0x6D, 0x6D, 0x75, 0x6E, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x43, 0x41, 0x32, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, ++ 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x44, 0x64, 0x7A, 0x43, 0x43, 0x41, 0x6C, 0x2B, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x42, 0x41, 0x44, 0x41, 0x4E, 0x42, 0x67, ++ 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x44, 0x42, 0x64, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x4B, 0x55, 0x44, 0x45, 0x6C, 0x4D, 0x43, ++ 0x4D, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x63, 0x0A, 0x55, 0x30, 0x56, 0x44, 0x54, 0x30, 0x30, 0x67, 0x56, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x51, 0x67, 0x55, 0x33, 0x6C, 0x7A, 0x64, 0x47, 0x56, 0x74, 0x63, 0x79, 0x42, 0x44, 0x54, ++ 0x79, 0x34, 0x73, 0x54, 0x46, 0x52, 0x45, 0x4C, 0x6A, 0x45, 0x6E, 0x4D, 0x43, 0x55, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x78, 0x4D, 0x65, 0x55, 0x32, 0x56, 0x6A, 0x64, 0x58, 0x4A, 0x70, 0x64, 0x48, 0x6B, 0x67, 0x51, 0x32, 0x39, 0x74, 0x62, ++ 0x58, 0x56, 0x75, 0x61, 0x57, 0x4E, 0x68, 0x0A, 0x64, 0x47, 0x6C, 0x76, 0x62, 0x69, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x51, 0x30, 0x45, 0x79, 0x4D, 0x42, 0x34, 0x58, 0x44, 0x54, 0x41, 0x35, 0x4D, 0x44, 0x55, 0x79, 0x4F, 0x54, 0x41, 0x31, ++ 0x4D, 0x44, 0x41, 0x7A, 0x4F, 0x56, 0x6F, 0x58, 0x44, 0x54, 0x49, 0x35, 0x4D, 0x44, 0x55, 0x79, 0x4F, 0x54, 0x41, 0x31, 0x4D, 0x44, 0x41, 0x7A, 0x4F, 0x56, 0x6F, 0x77, 0x58, 0x54, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, ++ 0x42, 0x68, 0x4D, 0x43, 0x0A, 0x53, 0x6C, 0x41, 0x78, 0x4A, 0x54, 0x41, 0x6A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x48, 0x46, 0x4E, 0x46, 0x51, 0x30, 0x39, 0x4E, 0x49, 0x46, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x49, 0x46, 0x4E, ++ 0x35, 0x63, 0x33, 0x52, 0x6C, 0x62, 0x58, 0x4D, 0x67, 0x51, 0x30, 0x38, 0x75, 0x4C, 0x45, 0x78, 0x55, 0x52, 0x43, 0x34, 0x78, 0x4A, 0x7A, 0x41, 0x6C, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x73, 0x54, 0x48, 0x6C, 0x4E, 0x6C, 0x59, 0x33, 0x56, ++ 0x79, 0x0A, 0x61, 0x58, 0x52, 0x35, 0x49, 0x45, 0x4E, 0x76, 0x62, 0x57, 0x31, 0x31, 0x62, 0x6D, 0x6C, 0x6A, 0x59, 0x58, 0x52, 0x70, 0x62, 0x32, 0x34, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x45, 0x4E, 0x42, 0x4D, 0x6A, 0x43, 0x43, 0x41, 0x53, ++ 0x49, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x45, 0x50, 0x41, 0x44, 0x43, 0x43, 0x41, 0x51, 0x6F, 0x43, 0x67, 0x67, 0x45, 0x42, 0x0A, 0x41, ++ 0x4E, 0x41, 0x56, 0x4F, 0x56, 0x4B, 0x78, 0x55, 0x72, 0x4F, 0x36, 0x78, 0x56, 0x6D, 0x43, 0x78, 0x46, 0x31, 0x53, 0x72, 0x6A, 0x70, 0x44, 0x5A, 0x59, 0x42, 0x4C, 0x78, 0x2F, 0x4B, 0x57, 0x76, 0x4E, 0x73, 0x32, 0x6C, 0x39, 0x61, 0x6D, 0x5A, ++ 0x49, 0x79, 0x6F, 0x58, 0x76, 0x44, 0x6A, 0x43, 0x68, 0x7A, 0x33, 0x33, 0x35, 0x63, 0x39, 0x53, 0x36, 0x37, 0x32, 0x58, 0x65, 0x77, 0x68, 0x74, 0x55, 0x47, 0x72, 0x7A, 0x62, 0x6C, 0x2B, 0x64, 0x70, 0x2B, 0x2B, 0x0A, 0x2B, 0x54, 0x34, 0x32, ++ 0x4E, 0x4B, 0x41, 0x37, 0x77, 0x66, 0x59, 0x78, 0x45, 0x55, 0x56, 0x30, 0x6B, 0x7A, 0x31, 0x58, 0x67, 0x4D, 0x58, 0x35, 0x69, 0x5A, 0x6E, 0x4B, 0x35, 0x61, 0x74, 0x71, 0x31, 0x4C, 0x58, 0x61, 0x51, 0x5A, 0x41, 0x51, 0x77, 0x64, 0x62, 0x57, ++ 0x51, 0x6F, 0x6E, 0x43, 0x76, 0x2F, 0x51, 0x34, 0x45, 0x70, 0x56, 0x4D, 0x56, 0x41, 0x58, 0x33, 0x4E, 0x75, 0x52, 0x46, 0x67, 0x33, 0x73, 0x55, 0x5A, 0x64, 0x62, 0x63, 0x44, 0x45, 0x33, 0x52, 0x0A, 0x33, 0x6E, 0x34, 0x4D, 0x71, 0x7A, 0x76, ++ 0x45, 0x46, 0x62, 0x34, 0x36, 0x56, 0x71, 0x5A, 0x61, 0x62, 0x33, 0x5A, 0x70, 0x55, 0x71, 0x6C, 0x36, 0x75, 0x63, 0x6A, 0x72, 0x61, 0x70, 0x70, 0x64, 0x55, 0x74, 0x41, 0x74, 0x43, 0x6D, 0x73, 0x31, 0x46, 0x67, 0x6B, 0x51, 0x68, 0x4E, 0x42, ++ 0x71, 0x79, 0x6A, 0x6F, 0x47, 0x41, 0x44, 0x64, 0x48, 0x35, 0x48, 0x35, 0x58, 0x54, 0x7A, 0x2B, 0x4C, 0x36, 0x32, 0x65, 0x34, 0x69, 0x4B, 0x72, 0x46, 0x76, 0x6C, 0x4E, 0x56, 0x0A, 0x73, 0x70, 0x48, 0x45, 0x66, 0x62, 0x6D, 0x77, 0x68, 0x52, ++ 0x6B, 0x47, 0x65, 0x43, 0x37, 0x62, 0x59, 0x52, 0x72, 0x36, 0x68, 0x66, 0x56, 0x4B, 0x6B, 0x61, 0x48, 0x6E, 0x46, 0x74, 0x57, 0x4F, 0x6F, 0x6A, 0x6E, 0x66, 0x6C, 0x4C, 0x68, 0x77, 0x48, 0x79, 0x67, 0x2F, 0x69, 0x2F, 0x78, 0x41, 0x58, 0x6D, ++ 0x4F, 0x44, 0x50, 0x49, 0x4D, 0x71, 0x47, 0x70, 0x6C, 0x72, 0x7A, 0x39, 0x35, 0x5A, 0x61, 0x6A, 0x76, 0x38, 0x62, 0x78, 0x62, 0x58, 0x48, 0x2F, 0x31, 0x4B, 0x0A, 0x45, 0x4F, 0x74, 0x4F, 0x67, 0x68, 0x59, 0x36, 0x72, 0x43, 0x63, 0x4D, 0x55, ++ 0x2F, 0x47, 0x74, 0x31, 0x53, 0x53, 0x77, 0x61, 0x77, 0x4E, 0x51, 0x77, 0x53, 0x30, 0x38, 0x46, 0x74, 0x31, 0x45, 0x4E, 0x43, 0x63, 0x61, 0x64, 0x66, 0x73, 0x43, 0x41, 0x77, 0x45, 0x41, 0x41, 0x61, 0x4E, 0x43, 0x4D, 0x45, 0x41, 0x77, 0x48, ++ 0x51, 0x59, 0x44, 0x56, 0x52, 0x30, 0x4F, 0x42, 0x42, 0x59, 0x45, 0x46, 0x41, 0x71, 0x46, 0x71, 0x58, 0x64, 0x6C, 0x42, 0x5A, 0x68, 0x38, 0x0A, 0x51, 0x49, 0x48, 0x34, 0x44, 0x35, 0x63, 0x73, 0x4F, 0x50, 0x45, 0x4B, 0x37, 0x44, 0x7A, 0x50, ++ 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x42, 0x42, 0x6A, 0x41, 0x50, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x52, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x54, 0x41, 0x44, ++ 0x41, 0x51, 0x48, 0x2F, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x0A, 0x43, 0x77, 0x55, 0x41, 0x41, 0x34, 0x49, 0x42, 0x41, 0x51, 0x42, 0x4D, 0x4F, 0x71, 0x4E, 0x45, 0x72, 0x4C, 0x6C, ++ 0x46, 0x73, 0x63, 0x65, 0x54, 0x66, 0x73, 0x67, 0x4C, 0x43, 0x6B, 0x4C, 0x66, 0x5A, 0x4F, 0x6F, 0x63, 0x37, 0x6C, 0x6C, 0x73, 0x43, 0x4C, 0x71, 0x4A, 0x58, 0x32, 0x72, 0x4B, 0x53, 0x70, 0x57, 0x65, 0x65, 0x6F, 0x38, 0x48, 0x78, 0x64, 0x70, ++ 0x46, 0x63, 0x6F, 0x4A, 0x78, 0x44, 0x6A, 0x72, 0x53, 0x7A, 0x47, 0x2B, 0x6E, 0x74, 0x4B, 0x45, 0x6A, 0x0A, 0x75, 0x2F, 0x59, 0x6B, 0x6E, 0x38, 0x73, 0x58, 0x2F, 0x6F, 0x79, 0x6D, 0x7A, 0x73, 0x4C, 0x53, 0x32, 0x38, 0x79, 0x4E, 0x2F, 0x48, ++ 0x48, 0x38, 0x41, 0x79, 0x6E, 0x42, 0x62, 0x46, 0x30, 0x7A, 0x58, 0x32, 0x53, 0x32, 0x5A, 0x54, 0x75, 0x4A, 0x62, 0x78, 0x68, 0x32, 0x65, 0x50, 0x58, 0x63, 0x6F, 0x6B, 0x67, 0x66, 0x47, 0x54, 0x2B, 0x4F, 0x6B, 0x2B, 0x76, 0x78, 0x2B, 0x68, ++ 0x66, 0x75, 0x7A, 0x55, 0x37, 0x6A, 0x42, 0x42, 0x4A, 0x56, 0x31, 0x75, 0x58, 0x6B, 0x0A, 0x33, 0x66, 0x73, 0x2B, 0x42, 0x58, 0x7A, 0x69, 0x48, 0x56, 0x37, 0x47, 0x70, 0x37, 0x79, 0x58, 0x54, 0x32, 0x67, 0x36, 0x39, 0x65, 0x6B, 0x75, 0x43, ++ 0x6B, 0x4F, 0x32, 0x72, 0x31, 0x64, 0x63, 0x59, 0x6D, 0x68, 0x38, 0x74, 0x2F, 0x32, 0x6A, 0x69, 0x6F, 0x53, 0x67, 0x72, 0x47, 0x4B, 0x2B, 0x4B, 0x77, 0x6D, 0x48, 0x4E, 0x50, 0x42, 0x71, 0x41, 0x62, 0x75, 0x62, 0x4B, 0x56, 0x59, 0x38, 0x2F, ++ 0x67, 0x41, 0x33, 0x7A, 0x79, 0x4E, 0x73, 0x38, 0x55, 0x36, 0x71, 0x0A, 0x74, 0x6E, 0x52, 0x47, 0x45, 0x6D, 0x79, 0x52, 0x37, 0x6A, 0x54, 0x56, 0x37, 0x4A, 0x71, 0x52, 0x35, 0x30, 0x53, 0x2B, 0x6B, 0x44, 0x46, 0x79, 0x31, 0x55, 0x6B, 0x43, ++ 0x39, 0x67, 0x4C, 0x6C, 0x39, 0x42, 0x2F, 0x72, 0x66, 0x4E, 0x6D, 0x57, 0x56, 0x61, 0x6E, 0x2F, 0x37, 0x49, 0x72, 0x35, 0x6D, 0x55, 0x66, 0x2F, 0x4E, 0x56, 0x6F, 0x43, 0x71, 0x67, 0x54, 0x4C, 0x69, 0x6C, 0x75, 0x48, 0x63, 0x53, 0x6D, 0x52, ++ 0x76, 0x61, 0x53, 0x30, 0x65, 0x67, 0x32, 0x39, 0x0A, 0x6D, 0x76, 0x56, 0x58, 0x49, 0x77, 0x41, 0x48, 0x49, 0x52, 0x63, 0x2F, 0x53, 0x6A, 0x6E, 0x52, 0x42, 0x55, 0x6B, 0x4C, 0x70, 0x37, 0x59, 0x33, 0x67, 0x61, 0x56, 0x64, 0x6A, 0x4B, 0x6F, ++ 0x7A, 0x58, 0x6F, 0x45, 0x6F, 0x66, 0x4B, 0x64, 0x39, 0x4A, 0x2B, 0x73, 0x41, 0x72, 0x6F, 0x30, 0x33, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, ++ 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x41, 0x63, 0x74, 0x61, 0x6C, 0x69, 0x73, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, ++ 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x75, 0x7A, 0x43, 0x43, 0x41, 0x36, 0x4F, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x49, 0x56, 0x77, 0x6F, 0x52, 0x6C, ++ 0x30, 0x4C, 0x45, 0x34, 0x38, 0x77, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x42, 0x51, 0x41, 0x77, 0x61, 0x7A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, ++ 0x68, 0x4D, 0x43, 0x53, 0x56, 0x51, 0x78, 0x44, 0x6A, 0x41, 0x4D, 0x0A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x63, 0x4D, 0x42, 0x55, 0x31, 0x70, 0x62, 0x47, 0x46, 0x75, 0x4D, 0x53, 0x4D, 0x77, 0x49, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, ++ 0x44, 0x42, 0x70, 0x42, 0x59, 0x33, 0x52, 0x68, 0x62, 0x47, 0x6C, 0x7A, 0x49, 0x46, 0x4D, 0x75, 0x63, 0x43, 0x35, 0x42, 0x4C, 0x69, 0x38, 0x77, 0x4D, 0x7A, 0x4D, 0x31, 0x4F, 0x44, 0x55, 0x79, 0x4D, 0x44, 0x6B, 0x32, 0x4E, 0x7A, 0x45, 0x6E, ++ 0x4D, 0x43, 0x55, 0x47, 0x41, 0x31, 0x55, 0x45, 0x0A, 0x41, 0x77, 0x77, 0x65, 0x51, 0x57, 0x4E, 0x30, 0x59, 0x57, 0x78, 0x70, 0x63, 0x79, 0x42, 0x42, 0x64, 0x58, 0x52, 0x6F, 0x5A, 0x57, 0x35, 0x30, 0x61, 0x57, 0x4E, 0x68, 0x64, 0x47, 0x6C, ++ 0x76, 0x62, 0x69, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x42, 0x4D, 0x42, 0x34, 0x58, 0x44, 0x54, 0x45, 0x78, 0x4D, 0x44, 0x6B, 0x79, 0x4D, 0x6A, 0x45, 0x78, 0x4D, 0x6A, 0x49, 0x77, 0x4D, 0x6C, 0x6F, 0x58, 0x44, 0x54, 0x4D, ++ 0x77, 0x4D, 0x44, 0x6B, 0x79, 0x0A, 0x4D, 0x6A, 0x45, 0x78, 0x4D, 0x6A, 0x49, 0x77, 0x4D, 0x6C, 0x6F, 0x77, 0x61, 0x7A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x53, 0x56, 0x51, 0x78, 0x44, 0x6A, ++ 0x41, 0x4D, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x63, 0x4D, 0x42, 0x55, 0x31, 0x70, 0x62, 0x47, 0x46, 0x75, 0x4D, 0x53, 0x4D, 0x77, 0x49, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x44, 0x42, 0x70, 0x42, 0x59, 0x33, 0x52, 0x68, 0x62, 0x47, ++ 0x6C, 0x7A, 0x0A, 0x49, 0x46, 0x4D, 0x75, 0x63, 0x43, 0x35, 0x42, 0x4C, 0x69, 0x38, 0x77, 0x4D, 0x7A, 0x4D, 0x31, 0x4F, 0x44, 0x55, 0x79, 0x4D, 0x44, 0x6B, 0x32, 0x4E, 0x7A, 0x45, 0x6E, 0x4D, 0x43, 0x55, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, ++ 0x77, 0x77, 0x65, 0x51, 0x57, 0x4E, 0x30, 0x59, 0x57, 0x78, 0x70, 0x63, 0x79, 0x42, 0x42, 0x64, 0x58, 0x52, 0x6F, 0x5A, 0x57, 0x35, 0x30, 0x61, 0x57, 0x4E, 0x68, 0x64, 0x47, 0x6C, 0x76, 0x62, 0x69, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x0A, ++ 0x49, 0x45, 0x4E, 0x42, 0x4D, 0x49, 0x49, 0x43, 0x49, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x45, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x67, 0x38, 0x41, 0x4D, 0x49, 0x49, 0x43, ++ 0x43, 0x67, 0x4B, 0x43, 0x41, 0x67, 0x45, 0x41, 0x70, 0x38, 0x62, 0x45, 0x70, 0x53, 0x6D, 0x6B, 0x4C, 0x4F, 0x2F, 0x6C, 0x47, 0x4D, 0x57, 0x77, 0x55, 0x4B, 0x4E, 0x76, 0x55, 0x54, 0x75, 0x66, 0x43, 0x6C, 0x72, 0x4A, 0x0A, 0x77, 0x6B, 0x67, ++ 0x34, 0x43, 0x73, 0x49, 0x63, 0x6F, 0x42, 0x68, 0x2F, 0x6B, 0x62, 0x57, 0x48, 0x75, 0x55, 0x41, 0x2F, 0x33, 0x52, 0x31, 0x6F, 0x48, 0x77, 0x69, 0x44, 0x31, 0x53, 0x30, 0x65, 0x69, 0x4B, 0x44, 0x34, 0x6A, 0x31, 0x61, 0x50, 0x62, 0x5A, 0x6B, ++ 0x43, 0x6B, 0x70, 0x41, 0x57, 0x31, 0x56, 0x38, 0x49, 0x62, 0x49, 0x6E, 0x58, 0x34, 0x61, 0x79, 0x38, 0x49, 0x4D, 0x4B, 0x78, 0x34, 0x49, 0x4E, 0x52, 0x69, 0x6D, 0x6C, 0x4E, 0x41, 0x4A, 0x5A, 0x61, 0x0A, 0x62, 0x79, 0x2F, 0x41, 0x52, 0x48, ++ 0x36, 0x6A, 0x44, 0x75, 0x53, 0x52, 0x7A, 0x56, 0x6A, 0x75, 0x33, 0x50, 0x76, 0x48, 0x48, 0x6B, 0x56, 0x48, 0x33, 0x53, 0x65, 0x35, 0x43, 0x41, 0x47, 0x66, 0x70, 0x69, 0x45, 0x64, 0x39, 0x55, 0x45, 0x74, 0x4C, 0x30, 0x7A, 0x39, 0x4B, 0x4B, ++ 0x33, 0x67, 0x69, 0x71, 0x30, 0x69, 0x74, 0x46, 0x5A, 0x6C, 0x6A, 0x6F, 0x5A, 0x55, 0x6A, 0x35, 0x4E, 0x44, 0x4B, 0x64, 0x34, 0x35, 0x52, 0x6E, 0x69, 0x6A, 0x4D, 0x43, 0x4F, 0x36, 0x0A, 0x7A, 0x66, 0x42, 0x39, 0x45, 0x31, 0x66, 0x41, 0x58, ++ 0x64, 0x4B, 0x44, 0x61, 0x30, 0x68, 0x4D, 0x78, 0x4B, 0x75, 0x66, 0x67, 0x46, 0x70, 0x62, 0x4F, 0x72, 0x33, 0x4A, 0x70, 0x79, 0x49, 0x2F, 0x67, 0x43, 0x63, 0x7A, 0x57, 0x77, 0x36, 0x33, 0x69, 0x67, 0x78, 0x64, 0x42, 0x7A, 0x63, 0x49, 0x79, ++ 0x32, 0x7A, 0x53, 0x65, 0x6B, 0x63, 0x69, 0x52, 0x44, 0x58, 0x46, 0x7A, 0x4D, 0x77, 0x75, 0x6A, 0x74, 0x30, 0x71, 0x37, 0x62, 0x64, 0x39, 0x5A, 0x67, 0x31, 0x66, 0x0A, 0x59, 0x56, 0x45, 0x69, 0x56, 0x52, 0x76, 0x6A, 0x52, 0x75, 0x50, 0x6A, ++ 0x50, 0x64, 0x41, 0x31, 0x59, 0x70, 0x72, 0x62, 0x72, 0x78, 0x54, 0x49, 0x57, 0x36, 0x48, 0x4D, 0x69, 0x52, 0x76, 0x68, 0x4D, 0x43, 0x62, 0x38, 0x6F, 0x4A, 0x73, 0x66, 0x67, 0x61, 0x64, 0x48, 0x48, 0x77, 0x54, 0x72, 0x6F, 0x7A, 0x6D, 0x53, ++ 0x42, 0x70, 0x2B, 0x5A, 0x30, 0x37, 0x2F, 0x54, 0x36, 0x6B, 0x39, 0x51, 0x6E, 0x42, 0x6E, 0x2B, 0x6C, 0x6F, 0x63, 0x65, 0x50, 0x47, 0x58, 0x32, 0x0A, 0x6F, 0x78, 0x67, 0x6B, 0x67, 0x34, 0x59, 0x51, 0x35, 0x31, 0x51, 0x2B, 0x71, 0x44, 0x70, ++ 0x32, 0x4A, 0x45, 0x2B, 0x42, 0x49, 0x63, 0x58, 0x6A, 0x44, 0x77, 0x4C, 0x34, 0x6B, 0x35, 0x52, 0x48, 0x49, 0x4C, 0x76, 0x2B, 0x31, 0x41, 0x37, 0x54, 0x61, 0x4C, 0x6E, 0x64, 0x78, 0x48, 0x71, 0x45, 0x67, 0x75, 0x4E, 0x54, 0x56, 0x48, 0x6E, ++ 0x64, 0x32, 0x35, 0x7A, 0x53, 0x38, 0x67, 0x65, 0x62, 0x4C, 0x72, 0x61, 0x38, 0x50, 0x75, 0x32, 0x46, 0x62, 0x65, 0x38, 0x6C, 0x0A, 0x45, 0x66, 0x4B, 0x58, 0x47, 0x6B, 0x4A, 0x68, 0x39, 0x30, 0x71, 0x58, 0x36, 0x49, 0x75, 0x78, 0x45, 0x41, ++ 0x66, 0x36, 0x5A, 0x59, 0x47, 0x79, 0x6F, 0x6A, 0x6E, 0x50, 0x39, 0x7A, 0x7A, 0x2F, 0x47, 0x50, 0x76, 0x47, 0x38, 0x56, 0x71, 0x4C, 0x57, 0x65, 0x49, 0x43, 0x72, 0x48, 0x75, 0x53, 0x30, 0x45, 0x34, 0x55, 0x54, 0x31, 0x6C, 0x46, 0x39, 0x67, ++ 0x78, 0x65, 0x4B, 0x46, 0x2B, 0x77, 0x36, 0x44, 0x39, 0x46, 0x7A, 0x38, 0x2B, 0x76, 0x6D, 0x32, 0x2F, 0x37, 0x0A, 0x68, 0x4E, 0x4E, 0x33, 0x57, 0x70, 0x56, 0x76, 0x72, 0x4A, 0x53, 0x45, 0x6E, 0x75, 0x36, 0x38, 0x77, 0x45, 0x71, 0x50, 0x53, ++ 0x70, 0x50, 0x34, 0x52, 0x43, 0x48, 0x69, 0x4D, 0x55, 0x56, 0x68, 0x55, 0x45, 0x34, 0x51, 0x32, 0x4F, 0x4D, 0x31, 0x66, 0x45, 0x77, 0x5A, 0x74, 0x4E, 0x34, 0x46, 0x76, 0x36, 0x4D, 0x47, 0x6E, 0x38, 0x69, 0x31, 0x7A, 0x65, 0x51, 0x66, 0x31, ++ 0x78, 0x63, 0x47, 0x44, 0x58, 0x71, 0x56, 0x64, 0x46, 0x55, 0x4E, 0x61, 0x42, 0x72, 0x38, 0x0A, 0x45, 0x42, 0x74, 0x69, 0x5A, 0x4A, 0x31, 0x74, 0x34, 0x4A, 0x57, 0x67, 0x77, 0x35, 0x51, 0x48, 0x56, 0x77, 0x30, 0x55, 0x35, 0x72, 0x30, 0x46, ++ 0x2B, 0x37, 0x69, 0x66, 0x35, 0x74, 0x2B, 0x4C, 0x34, 0x73, 0x62, 0x6E, 0x66, 0x70, 0x62, 0x32, 0x55, 0x38, 0x57, 0x41, 0x4E, 0x46, 0x41, 0x6F, 0x57, 0x50, 0x41, 0x53, 0x55, 0x48, 0x45, 0x58, 0x4D, 0x4C, 0x72, 0x6D, 0x65, 0x47, 0x4F, 0x38, ++ 0x39, 0x4C, 0x4B, 0x74, 0x6D, 0x79, 0x75, 0x79, 0x2F, 0x75, 0x45, 0x35, 0x0A, 0x6A, 0x46, 0x36, 0x36, 0x43, 0x79, 0x43, 0x55, 0x33, 0x6E, 0x75, 0x44, 0x75, 0x50, 0x2F, 0x6A, 0x56, 0x6F, 0x32, 0x33, 0x45, 0x65, 0x6B, 0x37, 0x6A, 0x50, 0x4B, ++ 0x78, 0x77, 0x56, 0x32, 0x64, 0x70, 0x41, 0x74, 0x4D, 0x4B, 0x39, 0x6D, 0x79, 0x47, 0x50, 0x57, 0x31, 0x6E, 0x30, 0x73, 0x43, 0x41, 0x77, 0x45, 0x41, 0x41, 0x61, 0x4E, 0x6A, 0x4D, 0x47, 0x45, 0x77, 0x48, 0x51, 0x59, 0x44, 0x56, 0x52, 0x30, ++ 0x4F, 0x42, 0x42, 0x59, 0x45, 0x46, 0x46, 0x4C, 0x59, 0x0A, 0x69, 0x44, 0x72, 0x49, 0x6E, 0x33, 0x68, 0x6D, 0x37, 0x59, 0x6E, 0x7A, 0x65, 0x7A, 0x68, 0x77, 0x6C, 0x4D, 0x6B, 0x43, 0x41, 0x6A, 0x62, 0x51, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, ++ 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x48, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x6A, 0x42, 0x42, 0x67, 0x77, 0x46, 0x6F, 0x41, 0x55, 0x55, 0x74, 0x69, 0x49, 0x4F, 0x73, ++ 0x69, 0x66, 0x65, 0x47, 0x62, 0x74, 0x0A, 0x69, 0x66, 0x4E, 0x37, 0x4F, 0x48, 0x43, 0x55, 0x79, 0x51, 0x49, 0x43, 0x4E, 0x74, 0x41, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x51, 0x44, 0x41, ++ 0x67, 0x45, 0x47, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x43, 0x77, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x41, 0x51, 0x41, 0x4C, 0x65, 0x33, 0x4B, 0x48, 0x77, 0x47, 0x43, 0x6D, 0x53, ++ 0x55, 0x79, 0x49, 0x0A, 0x57, 0x4F, 0x59, 0x64, 0x69, 0x50, 0x63, 0x55, 0x5A, 0x45, 0x69, 0x6D, 0x32, 0x46, 0x67, 0x4B, 0x44, 0x6B, 0x38, 0x54, 0x4E, 0x64, 0x38, 0x31, 0x48, 0x64, 0x54, 0x74, 0x42, 0x6A, 0x48, 0x49, 0x67, 0x54, 0x35, 0x71, ++ 0x31, 0x64, 0x30, 0x37, 0x47, 0x6A, 0x4C, 0x75, 0x6B, 0x44, 0x30, 0x52, 0x30, 0x69, 0x37, 0x30, 0x6A, 0x73, 0x4E, 0x6A, 0x4C, 0x69, 0x4E, 0x6D, 0x73, 0x47, 0x65, 0x2B, 0x62, 0x37, 0x62, 0x41, 0x45, 0x7A, 0x6C, 0x67, 0x71, 0x71, 0x49, 0x30, ++ 0x0A, 0x4A, 0x5A, 0x4E, 0x31, 0x55, 0x74, 0x36, 0x6E, 0x6E, 0x61, 0x30, 0x4F, 0x68, 0x34, 0x6C, 0x53, 0x63, 0x57, 0x6F, 0x57, 0x50, 0x42, 0x6B, 0x64, 0x67, 0x2F, 0x69, 0x61, 0x4B, 0x57, 0x57, 0x2B, 0x39, 0x44, 0x2B, 0x61, 0x32, 0x66, 0x44, ++ 0x7A, 0x57, 0x6F, 0x63, 0x68, 0x63, 0x59, 0x42, 0x4E, 0x79, 0x2B, 0x41, 0x34, 0x6D, 0x7A, 0x2B, 0x37, 0x2B, 0x75, 0x41, 0x77, 0x54, 0x63, 0x2B, 0x47, 0x30, 0x32, 0x55, 0x51, 0x47, 0x52, 0x6A, 0x52, 0x6C, 0x77, 0x4B, 0x78, 0x0A, 0x4B, 0x33, ++ 0x4A, 0x43, 0x61, 0x4B, 0x79, 0x67, 0x76, 0x55, 0x35, 0x61, 0x32, 0x68, 0x69, 0x2F, 0x61, 0x35, 0x69, 0x42, 0x30, 0x50, 0x32, 0x61, 0x76, 0x6C, 0x34, 0x56, 0x53, 0x4D, 0x30, 0x52, 0x46, 0x62, 0x6E, 0x41, 0x4B, 0x56, 0x79, 0x30, 0x36, 0x49, ++ 0x6A, 0x33, 0x50, 0x6A, 0x61, 0x75, 0x74, 0x32, 0x4C, 0x39, 0x48, 0x6D, 0x4C, 0x65, 0x63, 0x48, 0x67, 0x51, 0x48, 0x45, 0x68, 0x62, 0x32, 0x72, 0x79, 0x6B, 0x4F, 0x4C, 0x70, 0x6E, 0x37, 0x56, 0x55, 0x2B, 0x0A, 0x58, 0x6C, 0x66, 0x66, 0x31, ++ 0x41, 0x4E, 0x41, 0x54, 0x49, 0x47, 0x6B, 0x30, 0x6B, 0x39, 0x6A, 0x70, 0x77, 0x6C, 0x43, 0x43, 0x52, 0x54, 0x38, 0x41, 0x4B, 0x6E, 0x43, 0x67, 0x48, 0x4E, 0x50, 0x4C, 0x73, 0x42, 0x41, 0x32, 0x52, 0x46, 0x37, 0x53, 0x4F, 0x70, 0x36, 0x41, ++ 0x73, 0x44, 0x54, 0x36, 0x79, 0x67, 0x42, 0x4A, 0x6C, 0x68, 0x30, 0x77, 0x63, 0x42, 0x7A, 0x49, 0x6D, 0x32, 0x54, 0x6C, 0x66, 0x30, 0x35, 0x66, 0x62, 0x73, 0x71, 0x34, 0x2F, 0x61, 0x43, 0x0A, 0x34, 0x79, 0x79, 0x58, 0x58, 0x30, 0x34, 0x66, ++ 0x6B, 0x5A, 0x54, 0x36, 0x2F, 0x69, 0x79, 0x6A, 0x32, 0x48, 0x59, 0x61, 0x75, 0x45, 0x32, 0x79, 0x4F, 0x45, 0x2B, 0x62, 0x2B, 0x68, 0x31, 0x49, 0x59, 0x48, 0x6B, 0x6D, 0x34, 0x76, 0x50, 0x39, 0x71, 0x64, 0x43, 0x61, 0x36, 0x48, 0x43, 0x50, ++ 0x53, 0x58, 0x72, 0x57, 0x35, 0x62, 0x30, 0x4B, 0x44, 0x74, 0x73, 0x74, 0x38, 0x34, 0x32, 0x2F, 0x36, 0x2B, 0x4F, 0x6B, 0x66, 0x63, 0x76, 0x48, 0x6C, 0x58, 0x48, 0x6F, 0x0A, 0x32, 0x71, 0x4E, 0x38, 0x78, 0x63, 0x4C, 0x34, 0x64, 0x4A, 0x49, ++ 0x45, 0x47, 0x34, 0x61, 0x73, 0x70, 0x43, 0x4A, 0x54, 0x51, 0x4C, 0x61, 0x73, 0x2F, 0x6B, 0x78, 0x32, 0x7A, 0x2F, 0x75, 0x55, 0x4D, 0x73, 0x41, 0x31, 0x6E, 0x33, 0x59, 0x2F, 0x62, 0x75, 0x57, 0x51, 0x62, 0x71, 0x43, 0x6D, 0x4A, 0x71, 0x4B, ++ 0x34, 0x4C, 0x4C, 0x37, 0x52, 0x4B, 0x34, 0x58, 0x39, 0x70, 0x32, 0x6A, 0x49, 0x75, 0x67, 0x45, 0x72, 0x73, 0x57, 0x78, 0x30, 0x48, 0x62, 0x68, 0x7A, 0x0A, 0x6C, 0x65, 0x66, 0x75, 0x74, 0x38, 0x63, 0x6C, 0x38, 0x41, 0x42, 0x4D, 0x41, 0x4C, ++ 0x4A, 0x2B, 0x74, 0x67, 0x75, 0x4C, 0x48, 0x50, 0x50, 0x41, 0x55, 0x4A, 0x34, 0x6C, 0x75, 0x65, 0x41, 0x49, 0x33, 0x6A, 0x5A, 0x6D, 0x2F, 0x7A, 0x65, 0x6C, 0x30, 0x62, 0x74, 0x55, 0x5A, 0x43, 0x7A, 0x4A, 0x4A, 0x37, 0x56, 0x4C, 0x6B, 0x6E, ++ 0x35, 0x6C, 0x2F, 0x39, 0x4D, 0x74, 0x34, 0x62, 0x6C, 0x4F, 0x76, 0x48, 0x2B, 0x6B, 0x51, 0x53, 0x47, 0x51, 0x51, 0x58, 0x65, 0x6D, 0x0A, 0x4F, 0x52, 0x2F, 0x71, 0x6E, 0x75, 0x4F, 0x66, 0x30, 0x47, 0x5A, 0x76, 0x42, 0x65, 0x79, 0x71, 0x64, ++ 0x6E, 0x36, 0x2F, 0x61, 0x78, 0x61, 0x67, 0x36, 0x37, 0x58, 0x48, 0x2F, 0x4A, 0x4A, 0x55, 0x4C, 0x79, 0x73, 0x52, 0x4A, 0x79, 0x55, 0x33, 0x65, 0x45, 0x78, 0x52, 0x61, 0x72, 0x44, 0x7A, 0x7A, 0x46, 0x68, 0x64, 0x46, 0x50, 0x46, 0x71, 0x53, ++ 0x42, 0x58, 0x2F, 0x77, 0x67, 0x65, 0x32, 0x73, 0x59, 0x30, 0x50, 0x6A, 0x6C, 0x78, 0x51, 0x52, 0x72, 0x4D, 0x39, 0x0A, 0x76, 0x77, 0x47, 0x59, 0x54, 0x37, 0x4A, 0x5A, 0x56, 0x45, 0x63, 0x2B, 0x4E, 0x48, 0x74, 0x34, 0x62, 0x56, 0x61, 0x54, ++ 0x4C, 0x6E, 0x50, 0x71, 0x5A, 0x69, 0x68, 0x34, 0x7A, 0x52, 0x30, 0x55, 0x76, 0x36, 0x43, 0x50, 0x4C, 0x79, 0x36, 0x34, 0x4C, 0x6F, 0x37, 0x79, 0x46, 0x49, 0x72, 0x4D, 0x36, 0x62, 0x56, 0x38, 0x2B, 0x32, 0x79, 0x64, 0x44, 0x4B, 0x58, 0x68, ++ 0x6C, 0x67, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x42, 0x75, 0x79, 0x70, 0x61, 0x73, 0x73, 0x20, ++ 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x32, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, ++ 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x57, 0x54, 0x43, 0x43, 0x41, 0x30, 0x47, 0x67, ++ 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x42, 0x41, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x44, 0x42, 0x4F, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, ++ 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x4F, 0x54, 0x7A, 0x45, 0x64, 0x4D, 0x42, 0x73, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, 0x55, 0x0A, 0x51, 0x6E, 0x56, 0x35, 0x63, 0x47, 0x46, 0x7A, 0x63, 0x79, 0x42, 0x42, 0x55, 0x79, 0x30, ++ 0x35, 0x4F, 0x44, 0x4D, 0x78, 0x4E, 0x6A, 0x4D, 0x7A, 0x4D, 0x6A, 0x63, 0x78, 0x49, 0x44, 0x41, 0x65, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x4D, 0x46, 0x30, 0x4A, 0x31, 0x65, 0x58, 0x42, 0x68, 0x63, 0x33, 0x4D, 0x67, 0x51, 0x32, 0x78, ++ 0x68, 0x63, 0x33, 0x4D, 0x67, 0x4D, 0x69, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x42, 0x4D, 0x42, 0x34, 0x58, 0x0A, 0x44, 0x54, 0x45, 0x77, 0x4D, 0x54, 0x41, 0x79, 0x4E, 0x6A, 0x41, 0x34, 0x4D, 0x7A, 0x67, 0x77, 0x4D, 0x31, ++ 0x6F, 0x58, 0x44, 0x54, 0x51, 0x77, 0x4D, 0x54, 0x41, 0x79, 0x4E, 0x6A, 0x41, 0x34, 0x4D, 0x7A, 0x67, 0x77, 0x4D, 0x31, 0x6F, 0x77, 0x54, 0x6A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x54, 0x6B, ++ 0x38, 0x78, 0x48, 0x54, 0x41, 0x62, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x4D, 0x46, 0x45, 0x4A, 0x31, 0x0A, 0x65, 0x58, 0x42, 0x68, 0x63, 0x33, 0x4D, 0x67, 0x51, 0x56, 0x4D, 0x74, 0x4F, 0x54, 0x67, 0x7A, 0x4D, 0x54, 0x59, 0x7A, 0x4D, ++ 0x7A, 0x49, 0x33, 0x4D, 0x53, 0x41, 0x77, 0x48, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x44, 0x42, 0x64, 0x43, 0x64, 0x58, 0x6C, 0x77, 0x59, 0x58, 0x4E, 0x7A, 0x49, 0x45, 0x4E, 0x73, 0x59, 0x58, 0x4E, 0x7A, 0x49, 0x44, 0x49, 0x67, 0x55, ++ 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x51, 0x54, 0x43, 0x43, 0x41, 0x69, 0x49, 0x77, 0x0A, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x50, ++ 0x41, 0x44, 0x43, 0x43, 0x41, 0x67, 0x6F, 0x43, 0x67, 0x67, 0x49, 0x42, 0x41, 0x4E, 0x66, 0x48, 0x58, 0x76, 0x66, 0x42, 0x42, 0x39, 0x52, 0x33, 0x2B, 0x30, 0x4D, 0x68, 0x39, 0x50, 0x54, 0x31, 0x61, 0x65, 0x54, 0x75, 0x4D, 0x67, 0x48, 0x62, ++ 0x6F, 0x34, 0x59, 0x66, 0x35, 0x46, 0x6B, 0x4E, 0x75, 0x75, 0x64, 0x31, 0x0A, 0x67, 0x31, 0x4C, 0x72, 0x36, 0x68, 0x78, 0x68, 0x46, 0x55, 0x69, 0x37, 0x48, 0x51, 0x66, 0x4B, 0x6A, 0x4B, 0x36, 0x77, 0x33, 0x4A, 0x61, 0x64, 0x36, 0x73, 0x4E, ++ 0x67, 0x6B, 0x6F, 0x61, 0x43, 0x4B, 0x48, 0x4F, 0x63, 0x56, 0x67, 0x62, 0x2F, 0x53, 0x32, 0x54, 0x77, 0x44, 0x43, 0x6F, 0x33, 0x53, 0x62, 0x58, 0x6C, 0x7A, 0x77, 0x78, 0x38, 0x37, 0x76, 0x46, 0x4B, 0x75, 0x33, 0x4D, 0x77, 0x5A, 0x66, 0x50, ++ 0x56, 0x4C, 0x34, 0x4F, 0x32, 0x66, 0x75, 0x50, 0x6E, 0x0A, 0x39, 0x5A, 0x36, 0x72, 0x59, 0x50, 0x6E, 0x54, 0x38, 0x5A, 0x32, 0x53, 0x64, 0x49, 0x72, 0x6B, 0x48, 0x4A, 0x61, 0x73, 0x57, 0x34, 0x44, 0x70, 0x74, 0x66, 0x51, 0x78, 0x68, 0x36, ++ 0x4E, 0x52, 0x2F, 0x4D, 0x64, 0x2B, 0x6F, 0x57, 0x2B, 0x4F, 0x55, 0x33, 0x66, 0x55, 0x6C, 0x38, 0x46, 0x56, 0x4D, 0x35, 0x49, 0x2B, 0x47, 0x43, 0x39, 0x31, 0x31, 0x4B, 0x32, 0x47, 0x53, 0x63, 0x75, 0x56, 0x72, 0x31, 0x51, 0x47, 0x62, 0x4E, ++ 0x67, 0x47, 0x45, 0x34, 0x31, 0x62, 0x0A, 0x2F, 0x2B, 0x45, 0x6D, 0x47, 0x56, 0x6E, 0x41, 0x4A, 0x4C, 0x71, 0x42, 0x63, 0x58, 0x6D, 0x51, 0x52, 0x46, 0x42, 0x6F, 0x4A, 0x4A, 0x52, 0x66, 0x75, 0x4C, 0x4D, 0x52, 0x38, 0x53, 0x6C, 0x42, 0x59, ++ 0x61, 0x4E, 0x42, 0x79, 0x79, 0x4D, 0x32, 0x31, 0x63, 0x48, 0x78, 0x4D, 0x6C, 0x41, 0x51, 0x54, 0x6E, 0x2F, 0x30, 0x68, 0x70, 0x50, 0x73, 0x68, 0x4E, 0x4F, 0x4F, 0x76, 0x45, 0x75, 0x2F, 0x58, 0x41, 0x46, 0x4F, 0x42, 0x7A, 0x33, 0x63, 0x46, ++ 0x49, 0x71, 0x55, 0x0A, 0x43, 0x71, 0x54, 0x71, 0x63, 0x2F, 0x73, 0x4C, 0x55, 0x65, 0x67, 0x54, 0x42, 0x78, 0x6A, 0x36, 0x44, 0x76, 0x45, 0x72, 0x30, 0x56, 0x51, 0x56, 0x66, 0x54, 0x7A, 0x68, 0x39, 0x37, 0x51, 0x5A, 0x51, 0x6D, 0x64, 0x69, ++ 0x58, 0x6E, 0x66, 0x67, 0x6F, 0x6C, 0x58, 0x73, 0x74, 0x74, 0x6C, 0x70, 0x46, 0x39, 0x55, 0x36, 0x72, 0x30, 0x54, 0x74, 0x53, 0x73, 0x57, 0x65, 0x35, 0x48, 0x6F, 0x6E, 0x66, 0x4F, 0x56, 0x31, 0x31, 0x36, 0x72, 0x4C, 0x4A, 0x65, 0x66, 0x66, ++ 0x0A, 0x61, 0x77, 0x72, 0x62, 0x44, 0x30, 0x32, 0x54, 0x54, 0x71, 0x69, 0x67, 0x7A, 0x58, 0x73, 0x75, 0x38, 0x6C, 0x6B, 0x42, 0x61, 0x72, 0x63, 0x4E, 0x75, 0x41, 0x65, 0x42, 0x66, 0x6F, 0x73, 0x34, 0x47, 0x7A, 0x6A, 0x6D, 0x43, 0x6C, 0x65, ++ 0x5A, 0x50, 0x65, 0x34, 0x68, 0x36, 0x4B, 0x50, 0x31, 0x44, 0x42, 0x62, 0x64, 0x69, 0x2B, 0x77, 0x30, 0x6A, 0x70, 0x77, 0x71, 0x48, 0x41, 0x41, 0x56, 0x46, 0x34, 0x31, 0x6F, 0x67, 0x39, 0x4A, 0x77, 0x6E, 0x78, 0x67, 0x49, 0x0A, 0x7A, 0x52, ++ 0x46, 0x6F, 0x31, 0x63, 0x6C, 0x72, 0x55, 0x73, 0x33, 0x45, 0x52, 0x6F, 0x2F, 0x63, 0x74, 0x66, 0x50, 0x59, 0x56, 0x33, 0x4D, 0x65, 0x36, 0x5A, 0x51, 0x35, 0x42, 0x4C, 0x2F, 0x54, 0x33, 0x6A, 0x6A, 0x65, 0x74, 0x46, 0x50, 0x73, 0x61, 0x52, ++ 0x79, 0x69, 0x66, 0x73, 0x53, 0x50, 0x35, 0x42, 0x74, 0x77, 0x72, 0x66, 0x4B, 0x69, 0x2B, 0x66, 0x76, 0x33, 0x46, 0x6D, 0x52, 0x6D, 0x61, 0x5A, 0x39, 0x4A, 0x55, 0x61, 0x4C, 0x69, 0x46, 0x52, 0x68, 0x6E, 0x0A, 0x42, 0x6B, 0x70, 0x2F, 0x31, ++ 0x57, 0x79, 0x31, 0x54, 0x62, 0x4D, 0x7A, 0x34, 0x47, 0x48, 0x72, 0x58, 0x62, 0x37, 0x70, 0x6D, 0x41, 0x38, 0x79, 0x31, 0x78, 0x31, 0x4C, 0x50, 0x43, 0x35, 0x61, 0x41, 0x56, 0x4B, 0x52, 0x43, 0x66, 0x4C, 0x66, 0x36, 0x6F, 0x33, 0x59, 0x42, ++ 0x6B, 0x42, 0x6A, 0x71, 0x68, 0x48, 0x6B, 0x2F, 0x73, 0x4D, 0x33, 0x6E, 0x68, 0x52, 0x53, 0x50, 0x2F, 0x54, 0x69, 0x7A, 0x50, 0x4A, 0x68, 0x6B, 0x39, 0x48, 0x39, 0x5A, 0x32, 0x76, 0x58, 0x0A, 0x55, 0x71, 0x36, 0x2F, 0x61, 0x4B, 0x74, 0x41, ++ 0x51, 0x36, 0x42, 0x58, 0x4E, 0x56, 0x4E, 0x34, 0x38, 0x46, 0x50, 0x34, 0x59, 0x55, 0x49, 0x48, 0x5A, 0x4D, 0x62, 0x58, 0x62, 0x35, 0x74, 0x4D, 0x4F, 0x41, 0x31, 0x6A, 0x72, 0x47, 0x4B, 0x76, 0x4E, 0x6F, 0x75, 0x69, 0x63, 0x77, 0x6F, 0x4E, ++ 0x39, 0x53, 0x47, 0x39, 0x64, 0x4B, 0x70, 0x4E, 0x36, 0x6E, 0x49, 0x44, 0x53, 0x64, 0x76, 0x48, 0x58, 0x78, 0x31, 0x69, 0x59, 0x38, 0x66, 0x39, 0x33, 0x5A, 0x48, 0x73, 0x0A, 0x4D, 0x2B, 0x37, 0x31, 0x62, 0x62, 0x52, 0x75, 0x4D, 0x47, 0x6A, ++ 0x65, 0x79, 0x4E, 0x59, 0x6D, 0x73, 0x48, 0x56, 0x65, 0x65, 0x37, 0x51, 0x48, 0x49, 0x4A, 0x69, 0x68, 0x64, 0x6A, 0x4B, 0x34, 0x54, 0x57, 0x78, 0x50, 0x41, 0x67, 0x4D, 0x42, 0x41, 0x41, 0x47, 0x6A, 0x51, 0x6A, 0x42, 0x41, 0x4D, 0x41, 0x38, ++ 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x48, 0x51, 0x59, 0x44, 0x0A, 0x56, 0x52, 0x30, 0x4F, 0x42, 0x42, 0x59, 0x45, 0x46, 0x4D, 0x6D, 0x41, 0x64, 0x2B, ++ 0x42, 0x69, 0x6B, 0x6F, 0x4C, 0x31, 0x52, 0x70, 0x7A, 0x7A, 0x75, 0x76, 0x64, 0x4D, 0x77, 0x39, 0x36, 0x34, 0x6F, 0x36, 0x30, 0x35, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, ++ 0x49, 0x42, 0x42, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x0A, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x67, 0x45, 0x41, 0x55, 0x31, 0x38, 0x68, 0x39, 0x62, 0x71, 0x77, 0x4F, ++ 0x6C, 0x49, 0x35, 0x4C, 0x4A, 0x4B, 0x77, 0x62, 0x41, 0x44, 0x4A, 0x37, 0x38, 0x34, 0x67, 0x37, 0x77, 0x62, 0x79, 0x6C, 0x70, 0x37, 0x70, 0x70, 0x48, 0x52, 0x2F, 0x65, 0x68, 0x62, 0x38, 0x74, 0x2F, 0x57, 0x32, 0x2B, 0x78, 0x55, 0x62, 0x50, ++ 0x36, 0x75, 0x6D, 0x77, 0x48, 0x4A, 0x64, 0x45, 0x4C, 0x46, 0x78, 0x37, 0x72, 0x78, 0x50, 0x34, 0x36, 0x32, 0x73, 0x0A, 0x41, 0x32, 0x30, 0x75, 0x63, 0x53, 0x36, 0x76, 0x78, 0x4F, 0x4F, 0x74, 0x6F, 0x37, 0x30, 0x4D, 0x45, 0x61, 0x65, 0x30, ++ 0x2F, 0x30, 0x71, 0x79, 0x65, 0x78, 0x41, 0x51, 0x48, 0x36, 0x64, 0x58, 0x51, 0x62, 0x4C, 0x41, 0x72, 0x76, 0x51, 0x73, 0x57, 0x64, 0x5A, 0x48, 0x45, 0x49, 0x6A, 0x7A, 0x49, 0x56, 0x45, 0x70, 0x4D, 0x4D, 0x70, 0x67, 0x68, 0x71, 0x39, 0x47, ++ 0x71, 0x78, 0x33, 0x74, 0x4F, 0x6C, 0x75, 0x77, 0x6C, 0x4E, 0x35, 0x45, 0x34, 0x30, 0x45, 0x49, 0x0A, 0x6F, 0x73, 0x48, 0x73, 0x48, 0x64, 0x62, 0x39, 0x54, 0x37, 0x62, 0x57, 0x52, 0x39, 0x41, 0x55, 0x43, 0x38, 0x72, 0x6D, 0x79, 0x72, 0x56, ++ 0x37, 0x64, 0x33, 0x35, 0x42, 0x48, 0x31, 0x36, 0x44, 0x78, 0x37, 0x61, 0x4D, 0x4F, 0x5A, 0x61, 0x77, 0x50, 0x35, 0x61, 0x42, 0x51, 0x57, 0x39, 0x67, 0x6B, 0x4F, 0x4C, 0x6F, 0x2B, 0x66, 0x73, 0x69, 0x63, 0x64, 0x6C, 0x39, 0x73, 0x7A, 0x31, ++ 0x47, 0x76, 0x37, 0x53, 0x45, 0x72, 0x35, 0x41, 0x63, 0x44, 0x34, 0x38, 0x53, 0x0A, 0x61, 0x71, 0x2F, 0x76, 0x37, 0x68, 0x35, 0x36, 0x72, 0x67, 0x4A, 0x4B, 0x69, 0x68, 0x63, 0x72, 0x64, 0x76, 0x36, 0x73, 0x56, 0x49, 0x6B, 0x6B, 0x4C, 0x45, ++ 0x38, 0x2F, 0x74, 0x72, 0x4B, 0x6E, 0x54, 0x6F, 0x79, 0x6F, 0x6B, 0x5A, 0x66, 0x37, 0x4B, 0x63, 0x5A, 0x37, 0x58, 0x43, 0x32, 0x35, 0x79, 0x32, 0x61, 0x32, 0x74, 0x36, 0x68, 0x62, 0x45, 0x6C, 0x47, 0x46, 0x74, 0x51, 0x6C, 0x2B, 0x59, 0x6E, ++ 0x68, 0x77, 0x2F, 0x71, 0x6C, 0x71, 0x59, 0x4C, 0x59, 0x64, 0x0A, 0x44, 0x6E, 0x6B, 0x4D, 0x2F, 0x63, 0x72, 0x71, 0x4A, 0x49, 0x42, 0x79, 0x77, 0x35, 0x63, 0x2F, 0x38, 0x6E, 0x65, 0x72, 0x51, 0x79, 0x49, 0x4B, 0x78, 0x2B, 0x75, 0x32, 0x44, ++ 0x49, 0x53, 0x43, 0x4C, 0x49, 0x42, 0x72, 0x51, 0x59, 0x6F, 0x49, 0x77, 0x4F, 0x75, 0x6C, 0x61, 0x39, 0x2B, 0x5A, 0x45, 0x73, 0x75, 0x4B, 0x31, 0x56, 0x36, 0x41, 0x44, 0x4A, 0x48, 0x67, 0x4A, 0x67, 0x67, 0x32, 0x53, 0x4D, 0x58, 0x36, 0x4F, ++ 0x42, 0x45, 0x31, 0x2F, 0x79, 0x57, 0x44, 0x0A, 0x4C, 0x66, 0x4A, 0x36, 0x76, 0x39, 0x72, 0x39, 0x6A, 0x76, 0x36, 0x6C, 0x79, 0x30, 0x55, 0x73, 0x48, 0x38, 0x53, 0x49, 0x55, 0x36, 0x35, 0x33, 0x44, 0x74, 0x6D, 0x61, 0x64, 0x73, 0x57, 0x4F, ++ 0x4C, 0x42, 0x32, 0x6A, 0x75, 0x74, 0x58, 0x73, 0x4D, 0x71, 0x37, 0x41, 0x71, 0x71, 0x7A, 0x33, 0x30, 0x58, 0x70, 0x4E, 0x36, 0x39, 0x51, 0x48, 0x34, 0x6B, 0x6A, 0x33, 0x49, 0x6F, 0x36, 0x77, 0x70, 0x4A, 0x39, 0x71, 0x7A, 0x6F, 0x36, 0x79, ++ 0x73, 0x6D, 0x44, 0x30, 0x0A, 0x6F, 0x79, 0x4C, 0x51, 0x49, 0x2B, 0x75, 0x55, 0x57, 0x6E, 0x70, 0x70, 0x33, 0x51, 0x2B, 0x2F, 0x51, 0x46, 0x65, 0x73, 0x61, 0x31, 0x6C, 0x51, 0x32, 0x61, 0x4F, 0x5A, 0x34, 0x57, 0x37, 0x2B, 0x6A, 0x51, 0x46, ++ 0x35, 0x4A, 0x79, 0x4D, 0x56, 0x33, 0x70, 0x4B, 0x64, 0x65, 0x77, 0x6C, 0x4E, 0x57, 0x75, 0x64, 0x4C, 0x53, 0x44, 0x42, 0x61, 0x47, 0x4F, 0x59, 0x4B, 0x62, 0x65, 0x61, 0x50, 0x34, 0x4E, 0x4B, 0x37, 0x35, 0x74, 0x39, 0x38, 0x62, 0x69, 0x47, ++ 0x43, 0x0A, 0x77, 0x57, 0x67, 0x35, 0x54, 0x62, 0x53, 0x59, 0x57, 0x47, 0x5A, 0x69, 0x7A, 0x45, 0x71, 0x51, 0x58, 0x73, 0x50, 0x36, 0x4A, 0x77, 0x53, 0x78, 0x65, 0x52, 0x56, 0x30, 0x6D, 0x63, 0x79, 0x2B, 0x72, 0x53, 0x44, 0x65, 0x4A, 0x6D, ++ 0x41, 0x63, 0x36, 0x31, 0x5A, 0x52, 0x70, 0x71, 0x50, 0x71, 0x35, 0x4B, 0x4D, 0x2F, 0x70, 0x2F, 0x39, 0x68, 0x33, 0x50, 0x46, 0x61, 0x54, 0x57, 0x77, 0x79, 0x49, 0x30, 0x50, 0x75, 0x72, 0x4B, 0x6A, 0x75, 0x37, 0x6B, 0x6F, 0x53, 0x0A, 0x43, ++ 0x54, 0x78, 0x64, 0x63, 0x63, 0x4B, 0x2B, 0x65, 0x66, 0x72, 0x43, 0x68, 0x32, 0x67, 0x64, 0x43, 0x2F, 0x31, 0x63, 0x61, 0x63, 0x77, 0x47, 0x30, 0x4A, 0x70, 0x39, 0x56, 0x4A, 0x6B, 0x71, 0x79, 0x54, 0x6B, 0x61, 0x47, 0x61, 0x39, 0x4C, 0x4B, ++ 0x6B, 0x50, 0x7A, 0x59, 0x31, 0x31, 0x61, 0x57, 0x4F, 0x49, 0x76, 0x34, 0x78, 0x33, 0x6B, 0x71, 0x64, 0x62, 0x51, 0x43, 0x74, 0x43, 0x65, 0x76, 0x39, 0x65, 0x42, 0x43, 0x66, 0x48, 0x4A, 0x78, 0x79, 0x59, 0x4E, 0x0A, 0x72, 0x4A, 0x67, 0x57, ++ 0x56, 0x71, 0x41, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x42, 0x75, 0x79, 0x70, 0x61, 0x73, 0x73, 0x20, ++ 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, ++ 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x57, 0x54, 0x43, 0x43, 0x41, 0x30, 0x47, 0x67, ++ 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x42, 0x41, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x44, 0x42, 0x4F, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, ++ 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x4F, 0x54, 0x7A, 0x45, 0x64, 0x4D, 0x42, 0x73, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, 0x55, 0x0A, 0x51, 0x6E, 0x56, 0x35, 0x63, 0x47, 0x46, 0x7A, 0x63, 0x79, 0x42, 0x42, 0x55, 0x79, 0x30, ++ 0x35, 0x4F, 0x44, 0x4D, 0x78, 0x4E, 0x6A, 0x4D, 0x7A, 0x4D, 0x6A, 0x63, 0x78, 0x49, 0x44, 0x41, 0x65, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x4D, 0x46, 0x30, 0x4A, 0x31, 0x65, 0x58, 0x42, 0x68, 0x63, 0x33, 0x4D, 0x67, 0x51, 0x32, 0x78, ++ 0x68, 0x63, 0x33, 0x4D, 0x67, 0x4D, 0x79, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x42, 0x4D, 0x42, 0x34, 0x58, 0x0A, 0x44, 0x54, 0x45, 0x77, 0x4D, 0x54, 0x41, 0x79, 0x4E, 0x6A, 0x41, 0x34, 0x4D, 0x6A, 0x67, 0x31, 0x4F, 0x46, ++ 0x6F, 0x58, 0x44, 0x54, 0x51, 0x77, 0x4D, 0x54, 0x41, 0x79, 0x4E, 0x6A, 0x41, 0x34, 0x4D, 0x6A, 0x67, 0x31, 0x4F, 0x46, 0x6F, 0x77, 0x54, 0x6A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x54, 0x6B, ++ 0x38, 0x78, 0x48, 0x54, 0x41, 0x62, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x4D, 0x46, 0x45, 0x4A, 0x31, 0x0A, 0x65, 0x58, 0x42, 0x68, 0x63, 0x33, 0x4D, 0x67, 0x51, 0x56, 0x4D, 0x74, 0x4F, 0x54, 0x67, 0x7A, 0x4D, 0x54, 0x59, 0x7A, 0x4D, ++ 0x7A, 0x49, 0x33, 0x4D, 0x53, 0x41, 0x77, 0x48, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x44, 0x42, 0x64, 0x43, 0x64, 0x58, 0x6C, 0x77, 0x59, 0x58, 0x4E, 0x7A, 0x49, 0x45, 0x4E, 0x73, 0x59, 0x58, 0x4E, 0x7A, 0x49, 0x44, 0x4D, 0x67, 0x55, ++ 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x51, 0x54, 0x43, 0x43, 0x41, 0x69, 0x49, 0x77, 0x0A, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x50, ++ 0x41, 0x44, 0x43, 0x43, 0x41, 0x67, 0x6F, 0x43, 0x67, 0x67, 0x49, 0x42, 0x41, 0x4B, 0x58, 0x61, 0x43, 0x70, 0x55, 0x57, 0x55, 0x4F, 0x4F, 0x56, 0x38, 0x6C, 0x36, 0x64, 0x64, 0x6A, 0x45, 0x47, 0x4D, 0x6E, 0x71, 0x62, 0x38, 0x52, 0x42, 0x32, ++ 0x75, 0x41, 0x43, 0x61, 0x74, 0x56, 0x49, 0x32, 0x7A, 0x53, 0x52, 0x48, 0x0A, 0x73, 0x4A, 0x38, 0x59, 0x5A, 0x4C, 0x79, 0x61, 0x39, 0x76, 0x72, 0x56, 0x65, 0x64, 0x69, 0x51, 0x59, 0x6B, 0x77, 0x69, 0x4C, 0x39, 0x34, 0x34, 0x50, 0x64, 0x62, ++ 0x67, 0x71, 0x4F, 0x6B, 0x63, 0x4C, 0x4E, 0x74, 0x34, 0x45, 0x65, 0x6D, 0x4F, 0x61, 0x46, 0x45, 0x56, 0x63, 0x73, 0x66, 0x7A, 0x4D, 0x34, 0x66, 0x6B, 0x6F, 0x46, 0x30, 0x4C, 0x58, 0x4F, 0x42, 0x58, 0x42, 0x79, 0x6F, 0x77, 0x39, 0x63, 0x33, ++ 0x45, 0x4E, 0x33, 0x63, 0x6F, 0x54, 0x52, 0x69, 0x52, 0x0A, 0x35, 0x72, 0x2F, 0x56, 0x55, 0x76, 0x31, 0x78, 0x4C, 0x58, 0x41, 0x2B, 0x35, 0x38, 0x62, 0x45, 0x69, 0x75, 0x50, 0x77, 0x4B, 0x41, 0x76, 0x30, 0x64, 0x70, 0x69, 0x68, 0x69, 0x34, ++ 0x64, 0x56, 0x73, 0x6A, 0x6F, 0x54, 0x2F, 0x4C, 0x63, 0x2B, 0x4A, 0x7A, 0x65, 0x4F, 0x49, 0x75, 0x4F, 0x6F, 0x54, 0x79, 0x72, 0x76, 0x59, 0x4C, 0x73, 0x39, 0x74, 0x7A, 0x6E, 0x44, 0x44, 0x67, 0x46, 0x48, 0x6D, 0x56, 0x30, 0x53, 0x54, 0x39, ++ 0x74, 0x44, 0x2B, 0x6C, 0x65, 0x68, 0x0A, 0x37, 0x66, 0x6D, 0x64, 0x76, 0x68, 0x46, 0x48, 0x4A, 0x6C, 0x73, 0x54, 0x6D, 0x4B, 0x74, 0x64, 0x46, 0x6F, 0x71, 0x77, 0x4E, 0x78, 0x78, 0x58, 0x6E, 0x55, 0x58, 0x2F, 0x69, 0x4A, 0x59, 0x32, 0x76, ++ 0x37, 0x76, 0x4B, 0x42, 0x33, 0x74, 0x76, 0x68, 0x32, 0x50, 0x58, 0x30, 0x44, 0x4A, 0x71, 0x31, 0x6C, 0x31, 0x73, 0x44, 0x50, 0x47, 0x7A, 0x62, 0x6A, 0x6E, 0x69, 0x61, 0x7A, 0x45, 0x75, 0x4F, 0x51, 0x41, 0x6E, 0x46, 0x4E, 0x34, 0x34, 0x77, ++ 0x4F, 0x77, 0x5A, 0x0A, 0x5A, 0x6F, 0x59, 0x53, 0x36, 0x4A, 0x31, 0x79, 0x46, 0x68, 0x4E, 0x6B, 0x55, 0x73, 0x65, 0x70, 0x4E, 0x78, 0x7A, 0x39, 0x67, 0x6A, 0x44, 0x74, 0x68, 0x42, 0x67, 0x64, 0x39, 0x4B, 0x35, 0x63, 0x2F, 0x33, 0x41, 0x54, ++ 0x41, 0x4F, 0x75, 0x78, 0x39, 0x54, 0x4E, 0x36, 0x53, 0x39, 0x5A, 0x56, 0x2B, 0x41, 0x57, 0x4E, 0x53, 0x32, 0x6D, 0x77, 0x39, 0x62, 0x4D, 0x6F, 0x4E, 0x6C, 0x77, 0x55, 0x78, 0x46, 0x46, 0x7A, 0x54, 0x57, 0x73, 0x4C, 0x38, 0x54, 0x51, 0x48, ++ 0x0A, 0x32, 0x78, 0x63, 0x35, 0x31, 0x39, 0x77, 0x6F, 0x65, 0x32, 0x76, 0x31, 0x6E, 0x2F, 0x4D, 0x75, 0x77, 0x55, 0x38, 0x58, 0x4B, 0x68, 0x44, 0x7A, 0x7A, 0x4D, 0x72, 0x6F, 0x36, 0x2F, 0x31, 0x72, 0x71, 0x79, 0x36, 0x61, 0x6E, 0x79, 0x32, ++ 0x43, 0x62, 0x67, 0x54, 0x55, 0x55, 0x67, 0x47, 0x54, 0x4C, 0x54, 0x32, 0x47, 0x2F, 0x48, 0x37, 0x38, 0x33, 0x2B, 0x39, 0x43, 0x48, 0x61, 0x5A, 0x72, 0x37, 0x37, 0x6B, 0x67, 0x78, 0x76, 0x65, 0x39, 0x6F, 0x4B, 0x65, 0x56, 0x0A, 0x2F, 0x61, ++ 0x66, 0x6D, 0x69, 0x53, 0x54, 0x59, 0x7A, 0x49, 0x77, 0x30, 0x62, 0x4F, 0x49, 0x6A, 0x4C, 0x39, 0x6B, 0x53, 0x47, 0x69, 0x47, 0x35, 0x56, 0x5A, 0x46, 0x76, 0x43, 0x35, 0x46, 0x35, 0x47, 0x51, 0x79, 0x74, 0x51, 0x49, 0x67, 0x4C, 0x63, 0x4F, ++ 0x4A, 0x36, 0x30, 0x67, 0x37, 0x59, 0x61, 0x45, 0x69, 0x37, 0x67, 0x68, 0x4D, 0x35, 0x45, 0x46, 0x6A, 0x70, 0x32, 0x43, 0x6F, 0x48, 0x78, 0x68, 0x4C, 0x62, 0x57, 0x4E, 0x76, 0x53, 0x4F, 0x31, 0x55, 0x51, 0x0A, 0x52, 0x77, 0x55, 0x56, 0x5A, ++ 0x32, 0x4A, 0x2B, 0x47, 0x47, 0x4F, 0x6D, 0x52, 0x6A, 0x38, 0x4A, 0x44, 0x6C, 0x51, 0x79, 0x58, 0x72, 0x38, 0x4E, 0x59, 0x6E, 0x6F, 0x6E, 0x37, 0x34, 0x44, 0x6F, 0x32, 0x39, 0x6C, 0x4C, 0x42, 0x6C, 0x6F, 0x33, 0x57, 0x69, 0x58, 0x51, 0x43, ++ 0x42, 0x4A, 0x33, 0x31, 0x47, 0x38, 0x4A, 0x55, 0x4A, 0x63, 0x39, 0x79, 0x42, 0x33, 0x44, 0x33, 0x34, 0x78, 0x46, 0x4D, 0x46, 0x62, 0x47, 0x30, 0x32, 0x53, 0x72, 0x5A, 0x76, 0x50, 0x41, 0x0A, 0x58, 0x70, 0x61, 0x63, 0x77, 0x38, 0x54, 0x76, ++ 0x77, 0x33, 0x78, 0x72, 0x69, 0x7A, 0x70, 0x35, 0x66, 0x37, 0x4E, 0x4A, 0x7A, 0x7A, 0x33, 0x69, 0x69, 0x5A, 0x2B, 0x67, 0x4D, 0x45, 0x75, 0x46, 0x75, 0x5A, 0x79, 0x55, 0x4A, 0x48, 0x6D, 0x50, 0x66, 0x57, 0x75, 0x70, 0x52, 0x57, 0x67, 0x50, ++ 0x4B, 0x39, 0x44, 0x78, 0x32, 0x68, 0x7A, 0x4C, 0x61, 0x62, 0x6A, 0x4B, 0x53, 0x57, 0x4A, 0x74, 0x79, 0x4E, 0x42, 0x6A, 0x59, 0x74, 0x31, 0x67, 0x44, 0x31, 0x69, 0x71, 0x0A, 0x6A, 0x36, 0x47, 0x38, 0x42, 0x61, 0x56, 0x6D, 0x6F, 0x73, 0x38, ++ 0x62, 0x64, 0x72, 0x4B, 0x45, 0x5A, 0x4C, 0x46, 0x4D, 0x4F, 0x56, 0x4C, 0x41, 0x4D, 0x4C, 0x72, 0x77, 0x6A, 0x45, 0x73, 0x43, 0x73, 0x4C, 0x61, 0x33, 0x41, 0x67, 0x4D, 0x42, 0x41, 0x41, 0x47, 0x6A, 0x51, 0x6A, 0x42, 0x41, 0x4D, 0x41, 0x38, ++ 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x48, 0x51, 0x59, 0x44, 0x0A, 0x56, 0x52, 0x30, 0x4F, 0x42, 0x42, 0x59, 0x45, 0x46, 0x45, 0x65, 0x34, 0x7A, 0x66, ++ 0x2F, 0x6C, 0x62, 0x2B, 0x37, 0x34, 0x73, 0x75, 0x77, 0x76, 0x54, 0x67, 0x37, 0x35, 0x4A, 0x62, 0x43, 0x4F, 0x50, 0x47, 0x76, 0x44, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, ++ 0x49, 0x42, 0x42, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x0A, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x67, 0x45, 0x41, 0x41, 0x43, 0x41, 0x6A, 0x51, 0x54, 0x55, 0x45, 0x6B, ++ 0x4D, 0x4A, 0x41, 0x59, 0x6D, 0x44, 0x76, 0x34, 0x6A, 0x56, 0x4D, 0x31, 0x7A, 0x2B, 0x73, 0x34, 0x6A, 0x53, 0x51, 0x75, 0x4B, 0x46, 0x76, 0x64, 0x76, 0x6F, 0x57, 0x46, 0x71, 0x52, 0x49, 0x4E, 0x79, 0x7A, 0x70, 0x6B, 0x4D, 0x4C, 0x79, 0x50, ++ 0x50, 0x67, 0x4B, 0x6E, 0x39, 0x69, 0x42, 0x35, 0x62, 0x74, 0x62, 0x32, 0x69, 0x55, 0x73, 0x70, 0x4B, 0x64, 0x56, 0x0A, 0x63, 0x53, 0x51, 0x79, 0x39, 0x73, 0x67, 0x4C, 0x38, 0x72, 0x78, 0x71, 0x2B, 0x4A, 0x4F, 0x73, 0x73, 0x67, 0x66, 0x43, ++ 0x58, 0x35, 0x2F, 0x62, 0x7A, 0x4D, 0x69, 0x4B, 0x71, 0x72, 0x35, 0x71, 0x62, 0x2B, 0x46, 0x4A, 0x45, 0x4D, 0x77, 0x78, 0x31, 0x34, 0x43, 0x37, 0x75, 0x38, 0x6A, 0x59, 0x6F, 0x67, 0x35, 0x6B, 0x56, 0x2B, 0x71, 0x69, 0x39, 0x63, 0x4B, 0x70, ++ 0x4D, 0x52, 0x58, 0x53, 0x49, 0x47, 0x72, 0x73, 0x2F, 0x43, 0x49, 0x42, 0x4B, 0x4D, 0x2B, 0x47, 0x0A, 0x75, 0x49, 0x41, 0x65, 0x71, 0x63, 0x77, 0x52, 0x70, 0x54, 0x7A, 0x79, 0x46, 0x72, 0x4E, 0x48, 0x6E, 0x66, 0x7A, 0x53, 0x67, 0x43, 0x48, ++ 0x45, 0x79, 0x39, 0x42, 0x48, 0x63, 0x45, 0x47, 0x68, 0x79, 0x6F, 0x4D, 0x5A, 0x43, 0x43, 0x78, 0x74, 0x38, 0x6C, 0x31, 0x33, 0x6E, 0x49, 0x6F, 0x55, 0x45, 0x39, 0x51, 0x32, 0x48, 0x4A, 0x4C, 0x77, 0x35, 0x51, 0x59, 0x33, 0x33, 0x4B, 0x62, ++ 0x6D, 0x6B, 0x4A, 0x73, 0x34, 0x6A, 0x31, 0x78, 0x72, 0x47, 0x30, 0x61, 0x47, 0x0A, 0x51, 0x30, 0x4A, 0x66, 0x50, 0x67, 0x45, 0x48, 0x55, 0x31, 0x52, 0x64, 0x5A, 0x58, 0x33, 0x33, 0x69, 0x6E, 0x4F, 0x68, 0x6D, 0x6C, 0x52, 0x61, 0x48, 0x79, ++ 0x6C, 0x44, 0x46, 0x43, 0x66, 0x43, 0x68, 0x51, 0x2B, 0x31, 0x69, 0x48, 0x73, 0x61, 0x4F, 0x35, 0x53, 0x33, 0x48, 0x57, 0x43, 0x6E, 0x74, 0x5A, 0x7A, 0x6E, 0x4B, 0x57, 0x6C, 0x58, 0x57, 0x70, 0x75, 0x54, 0x65, 0x6B, 0x4D, 0x77, 0x47, 0x77, ++ 0x50, 0x58, 0x59, 0x73, 0x68, 0x41, 0x70, 0x71, 0x72, 0x38, 0x0A, 0x5A, 0x4F, 0x52, 0x4B, 0x31, 0x35, 0x46, 0x54, 0x41, 0x61, 0x67, 0x67, 0x69, 0x47, 0x36, 0x63, 0x58, 0x30, 0x53, 0x35, 0x79, 0x32, 0x43, 0x42, 0x4E, 0x4F, 0x78, 0x76, 0x30, ++ 0x33, 0x33, 0x61, 0x53, 0x46, 0x2F, 0x72, 0x74, 0x4A, 0x43, 0x38, 0x4C, 0x61, 0x6B, 0x63, 0x43, 0x36, 0x77, 0x63, 0x31, 0x61, 0x4A, 0x6F, 0x49, 0x49, 0x41, 0x45, 0x31, 0x76, 0x79, 0x78, 0x6A, 0x79, 0x2B, 0x37, 0x53, 0x6A, 0x45, 0x4E, 0x53, ++ 0x6F, 0x59, 0x63, 0x36, 0x2B, 0x49, 0x32, 0x0A, 0x4B, 0x53, 0x62, 0x31, 0x32, 0x74, 0x6A, 0x45, 0x38, 0x6E, 0x56, 0x68, 0x7A, 0x33, 0x36, 0x75, 0x64, 0x6D, 0x4E, 0x4B, 0x65, 0x6B, 0x42, 0x6C, 0x6B, 0x34, 0x66, 0x34, 0x48, 0x6F, 0x43, 0x4D, ++ 0x68, 0x75, 0x57, 0x47, 0x31, 0x6F, 0x38, 0x4F, 0x2F, 0x46, 0x4D, 0x73, 0x59, 0x4F, 0x67, 0x57, 0x59, 0x52, 0x71, 0x69, 0x50, 0x6B, 0x4E, 0x37, 0x7A, 0x54, 0x6C, 0x67, 0x56, 0x47, 0x72, 0x31, 0x38, 0x6F, 0x6B, 0x6D, 0x41, 0x57, 0x69, 0x44, ++ 0x53, 0x4B, 0x49, 0x7A, 0x0A, 0x36, 0x4D, 0x6B, 0x45, 0x6B, 0x62, 0x49, 0x52, 0x4E, 0x42, 0x45, 0x2B, 0x36, 0x74, 0x42, 0x44, 0x47, 0x52, 0x38, 0x44, 0x6B, 0x35, 0x41, 0x4D, 0x2F, 0x31, 0x45, 0x39, 0x56, 0x2F, 0x52, 0x42, 0x62, 0x75, 0x48, ++ 0x4C, 0x6F, 0x4C, 0x37, 0x72, 0x79, 0x57, 0x50, 0x4E, 0x62, 0x63, 0x7A, 0x6B, 0x2B, 0x44, 0x61, 0x71, 0x61, 0x4A, 0x33, 0x74, 0x76, 0x56, 0x32, 0x58, 0x63, 0x45, 0x51, 0x4E, 0x74, 0x67, 0x34, 0x31, 0x33, 0x4F, 0x45, 0x4D, 0x58, 0x62, 0x75, ++ 0x67, 0x0A, 0x55, 0x5A, 0x54, 0x4C, 0x66, 0x68, 0x62, 0x72, 0x45, 0x53, 0x2B, 0x6A, 0x6B, 0x6B, 0x58, 0x49, 0x54, 0x48, 0x48, 0x5A, 0x76, 0x4D, 0x6D, 0x5A, 0x55, 0x6C, 0x64, 0x47, 0x4C, 0x31, 0x44, 0x50, 0x76, 0x54, 0x56, 0x70, 0x39, 0x44, ++ 0x30, 0x56, 0x7A, 0x67, 0x61, 0x6C, 0x4C, 0x41, 0x38, 0x2B, 0x39, 0x6F, 0x47, 0x36, 0x6C, 0x4C, 0x76, 0x44, 0x75, 0x37, 0x39, 0x6C, 0x65, 0x4E, 0x4B, 0x47, 0x65, 0x66, 0x39, 0x4A, 0x4F, 0x78, 0x71, 0x44, 0x44, 0x50, 0x44, 0x65, 0x0A, 0x65, ++ 0x4F, 0x7A, 0x49, 0x38, 0x6B, 0x31, 0x4D, 0x47, 0x74, 0x36, 0x43, 0x4B, 0x66, 0x6A, 0x42, 0x57, 0x74, 0x72, 0x74, 0x37, 0x75, 0x59, 0x6E, 0x58, 0x75, 0x68, 0x46, 0x30, 0x4A, 0x30, 0x63, 0x55, 0x61, 0x68, 0x6F, 0x71, 0x30, 0x54, 0x6A, 0x30, ++ 0x49, 0x74, 0x71, 0x34, 0x2F, 0x67, 0x37, 0x75, 0x39, 0x78, 0x4E, 0x31, 0x32, 0x54, 0x79, 0x55, 0x62, 0x37, 0x6D, 0x71, 0x71, 0x74, 0x61, 0x36, 0x54, 0x48, 0x75, 0x42, 0x72, 0x78, 0x7A, 0x76, 0x78, 0x4E, 0x69, 0x0A, 0x43, 0x70, 0x2F, 0x48, ++ 0x75, 0x5A, 0x63, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x54, 0x2D, 0x54, 0x65, 0x6C, 0x65, 0x53, 0x65, ++ 0x63, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, ++ 0x49, 0x44, 0x77, 0x7A, 0x43, 0x43, 0x41, 0x71, 0x75, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x42, 0x41, 0x54, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x44, ++ 0x43, 0x42, 0x67, 0x6A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x52, 0x45, 0x55, 0x78, 0x4B, 0x7A, 0x41, 0x70, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x4D, 0x0A, 0x49, 0x6C, 0x51, 0x74, 0x55, ++ 0x33, 0x6C, 0x7A, 0x64, 0x47, 0x56, 0x74, 0x63, 0x79, 0x42, 0x46, 0x62, 0x6E, 0x52, 0x6C, 0x63, 0x6E, 0x42, 0x79, 0x61, 0x58, 0x4E, 0x6C, 0x49, 0x46, 0x4E, 0x6C, 0x63, 0x6E, 0x5A, 0x70, 0x59, 0x32, 0x56, 0x7A, 0x49, 0x45, 0x64, 0x74, 0x59, ++ 0x6B, 0x67, 0x78, 0x48, 0x7A, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x73, 0x4D, 0x46, 0x6C, 0x51, 0x74, 0x55, 0x33, 0x6C, 0x7A, 0x64, 0x47, 0x56, 0x74, 0x63, 0x79, 0x42, 0x55, 0x0A, 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x43, 0x42, 0x44, ++ 0x5A, 0x57, 0x35, 0x30, 0x5A, 0x58, 0x49, 0x78, 0x4A, 0x54, 0x41, 0x6A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x4D, 0x48, 0x46, 0x51, 0x74, 0x56, 0x47, 0x56, 0x73, 0x5A, 0x56, 0x4E, 0x6C, 0x59, 0x79, 0x42, 0x48, 0x62, 0x47, 0x39, 0x69, ++ 0x59, 0x57, 0x78, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x73, 0x59, 0x58, 0x4E, 0x7A, 0x49, 0x44, 0x4D, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x44, 0x67, 0x78, 0x0A, 0x4D, 0x44, 0x41, 0x78, 0x4D, 0x54, 0x41, 0x79, 0x4F, 0x54, 0x55, ++ 0x32, 0x57, 0x68, 0x63, 0x4E, 0x4D, 0x7A, 0x4D, 0x78, 0x4D, 0x44, 0x41, 0x78, 0x4D, 0x6A, 0x4D, 0x31, 0x4F, 0x54, 0x55, 0x35, 0x57, 0x6A, 0x43, 0x42, 0x67, 0x6A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, ++ 0x43, 0x52, 0x45, 0x55, 0x78, 0x4B, 0x7A, 0x41, 0x70, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x4D, 0x49, 0x6C, 0x51, 0x74, 0x55, 0x33, 0x6C, 0x7A, 0x0A, 0x64, 0x47, 0x56, 0x74, 0x63, 0x79, 0x42, 0x46, 0x62, 0x6E, 0x52, 0x6C, 0x63, 0x6E, ++ 0x42, 0x79, 0x61, 0x58, 0x4E, 0x6C, 0x49, 0x46, 0x4E, 0x6C, 0x63, 0x6E, 0x5A, 0x70, 0x59, 0x32, 0x56, 0x7A, 0x49, 0x45, 0x64, 0x74, 0x59, 0x6B, 0x67, 0x78, 0x48, 0x7A, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x73, 0x4D, 0x46, 0x6C, ++ 0x51, 0x74, 0x55, 0x33, 0x6C, 0x7A, 0x64, 0x47, 0x56, 0x74, 0x63, 0x79, 0x42, 0x55, 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x43, 0x42, 0x44, 0x0A, 0x5A, 0x57, 0x35, 0x30, 0x5A, 0x58, 0x49, 0x78, 0x4A, 0x54, 0x41, 0x6A, 0x42, 0x67, 0x4E, 0x56, 0x42, ++ 0x41, 0x4D, 0x4D, 0x48, 0x46, 0x51, 0x74, 0x56, 0x47, 0x56, 0x73, 0x5A, 0x56, 0x4E, 0x6C, 0x59, 0x79, 0x42, 0x48, 0x62, 0x47, 0x39, 0x69, 0x59, 0x57, 0x78, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x73, 0x59, 0x58, 0x4E, 0x7A, 0x49, ++ 0x44, 0x4D, 0x77, 0x67, 0x67, 0x45, 0x69, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x0A, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x42, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x45, 0x4B, ++ 0x41, 0x6F, 0x49, 0x42, 0x41, 0x51, 0x43, 0x39, 0x64, 0x5A, 0x50, 0x77, 0x59, 0x69, 0x4A, 0x76, 0x4A, 0x4B, 0x37, 0x67, 0x65, 0x6E, 0x61, 0x73, 0x66, 0x62, 0x33, 0x5A, 0x4A, 0x4E, 0x57, 0x34, 0x74, 0x2F, 0x7A, 0x4E, 0x38, 0x45, 0x4C, 0x67, ++ 0x36, 0x33, 0x69, 0x49, 0x56, 0x6C, 0x36, 0x62, 0x6D, 0x6C, 0x51, 0x64, 0x54, 0x51, 0x79, 0x4B, 0x0A, 0x39, 0x74, 0x50, 0x50, 0x63, 0x50, 0x52, 0x53, 0x74, 0x64, 0x69, 0x54, 0x42, 0x4F, 0x4E, 0x47, 0x68, 0x6E, 0x46, 0x42, 0x53, 0x69, 0x76, ++ 0x77, 0x4B, 0x69, 0x78, 0x56, 0x41, 0x39, 0x5A, 0x49, 0x77, 0x2B, 0x41, 0x35, 0x4F, 0x4F, 0x33, 0x79, 0x58, 0x44, 0x77, 0x2F, 0x52, 0x4C, 0x79, 0x54, 0x50, 0x57, 0x47, 0x72, 0x54, 0x73, 0x30, 0x4E, 0x76, 0x76, 0x41, 0x67, 0x4A, 0x31, 0x67, ++ 0x4F, 0x52, 0x48, 0x38, 0x45, 0x47, 0x6F, 0x65, 0x6C, 0x31, 0x35, 0x59, 0x55, 0x0A, 0x4E, 0x70, 0x44, 0x51, 0x53, 0x58, 0x75, 0x68, 0x64, 0x66, 0x73, 0x61, 0x61, 0x33, 0x4F, 0x78, 0x2B, 0x4D, 0x36, 0x70, 0x43, 0x53, 0x7A, 0x79, 0x55, 0x39, ++ 0x58, 0x44, 0x46, 0x45, 0x53, 0x34, 0x68, 0x71, 0x58, 0x32, 0x69, 0x79, 0x73, 0x35, 0x32, 0x71, 0x4D, 0x7A, 0x56, 0x4E, 0x6E, 0x36, 0x63, 0x68, 0x72, 0x33, 0x49, 0x68, 0x55, 0x63, 0x69, 0x4A, 0x46, 0x72, 0x66, 0x32, 0x62, 0x6C, 0x77, 0x32, ++ 0x71, 0x41, 0x73, 0x43, 0x54, 0x7A, 0x33, 0x34, 0x5A, 0x46, 0x0A, 0x69, 0x50, 0x30, 0x5A, 0x66, 0x33, 0x57, 0x48, 0x48, 0x78, 0x2B, 0x78, 0x47, 0x77, 0x70, 0x7A, 0x4A, 0x46, 0x75, 0x35, 0x5A, 0x65, 0x41, 0x73, 0x56, 0x4D, 0x68, 0x67, 0x30, ++ 0x32, 0x59, 0x58, 0x50, 0x2B, 0x48, 0x4D, 0x56, 0x44, 0x4E, 0x7A, 0x6B, 0x51, 0x49, 0x36, 0x70, 0x6E, 0x39, 0x37, 0x64, 0x6A, 0x6D, 0x69, 0x48, 0x35, 0x61, 0x32, 0x4F, 0x4B, 0x36, 0x31, 0x79, 0x4A, 0x4E, 0x30, 0x48, 0x5A, 0x36, 0x35, 0x74, ++ 0x4F, 0x56, 0x67, 0x6E, 0x53, 0x39, 0x57, 0x0A, 0x30, 0x65, 0x44, 0x72, 0x58, 0x6C, 0x74, 0x4D, 0x45, 0x6E, 0x41, 0x4D, 0x62, 0x45, 0x51, 0x67, 0x71, 0x78, 0x48, 0x59, 0x39, 0x42, 0x6E, 0x32, 0x30, 0x70, 0x78, 0x53, 0x4E, 0x2B, 0x66, 0x36, ++ 0x74, 0x73, 0x49, 0x78, 0x4F, 0x30, 0x72, 0x55, 0x46, 0x4A, 0x6D, 0x74, 0x78, 0x78, 0x72, 0x31, 0x58, 0x56, 0x2F, 0x36, 0x42, 0x37, 0x68, 0x38, 0x44, 0x52, 0x2F, 0x57, 0x67, 0x78, 0x36, 0x7A, 0x41, 0x67, 0x4D, 0x42, 0x41, 0x41, 0x47, 0x6A, ++ 0x51, 0x6A, 0x42, 0x41, 0x0A, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x41, 0x51, 0x48, ++ 0x2F, 0x42, 0x41, 0x51, 0x44, 0x41, 0x67, 0x45, 0x47, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x53, 0x31, 0x41, 0x2F, 0x64, 0x32, 0x4F, 0x32, 0x47, 0x43, 0x61, 0x68, 0x4B, 0x71, 0x47, 0x46, 0x50, ++ 0x72, 0x0A, 0x41, 0x79, 0x47, 0x55, 0x76, 0x2F, 0x37, 0x4F, 0x79, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x51, 0x45, 0x41, 0x56, 0x6A, ++ 0x33, 0x76, 0x6C, 0x4E, 0x57, 0x39, 0x32, 0x6E, 0x4F, 0x79, 0x57, 0x4C, 0x36, 0x75, 0x6B, 0x4B, 0x32, 0x59, 0x4A, 0x35, 0x66, 0x2B, 0x41, 0x62, 0x47, 0x77, 0x55, 0x67, 0x43, 0x34, 0x54, 0x65, 0x51, 0x62, 0x49, 0x58, 0x51, 0x62, 0x0A, 0x66, ++ 0x73, 0x44, 0x75, 0x58, 0x6D, 0x6B, 0x71, 0x4A, 0x61, 0x39, 0x63, 0x31, 0x68, 0x33, 0x61, 0x30, 0x6E, 0x6E, 0x4A, 0x38, 0x35, 0x63, 0x70, 0x34, 0x49, 0x61, 0x48, 0x33, 0x67, 0x52, 0x5A, 0x44, 0x2F, 0x46, 0x5A, 0x31, 0x47, 0x53, 0x46, 0x53, ++ 0x35, 0x6D, 0x76, 0x4A, 0x51, 0x51, 0x65, 0x79, 0x55, 0x61, 0x70, 0x6C, 0x39, 0x36, 0x43, 0x73, 0x68, 0x74, 0x77, 0x6E, 0x35, 0x7A, 0x32, 0x72, 0x33, 0x45, 0x78, 0x33, 0x58, 0x73, 0x46, 0x70, 0x53, 0x7A, 0x54, 0x0A, 0x75, 0x63, 0x70, 0x48, ++ 0x39, 0x73, 0x72, 0x79, 0x39, 0x75, 0x65, 0x74, 0x75, 0x55, 0x67, 0x2F, 0x76, 0x42, 0x61, 0x33, 0x77, 0x57, 0x33, 0x30, 0x36, 0x67, 0x6D, 0x76, 0x37, 0x50, 0x4F, 0x31, 0x35, 0x77, 0x57, 0x65, 0x70, 0x68, 0x36, 0x4B, 0x55, 0x31, 0x48, 0x57, ++ 0x6B, 0x34, 0x48, 0x4D, 0x64, 0x4A, 0x50, 0x32, 0x75, 0x64, 0x71, 0x6D, 0x4A, 0x51, 0x56, 0x30, 0x65, 0x56, 0x70, 0x2B, 0x51, 0x44, 0x36, 0x43, 0x53, 0x79, 0x59, 0x52, 0x4D, 0x47, 0x37, 0x68, 0x0A, 0x50, 0x30, 0x48, 0x48, 0x52, 0x77, 0x41, ++ 0x31, 0x31, 0x66, 0x58, 0x54, 0x39, 0x31, 0x51, 0x2B, 0x67, 0x54, 0x33, 0x61, 0x53, 0x57, 0x71, 0x61, 0x73, 0x2B, 0x38, 0x51, 0x50, 0x65, 0x62, 0x72, 0x62, 0x39, 0x48, 0x49, 0x49, 0x6B, 0x66, 0x4C, 0x7A, 0x4D, 0x38, 0x42, 0x4D, 0x5A, 0x4C, ++ 0x5A, 0x47, 0x4F, 0x4D, 0x69, 0x76, 0x67, 0x6B, 0x65, 0x47, 0x6A, 0x35, 0x61, 0x73, 0x75, 0x52, 0x72, 0x44, 0x46, 0x52, 0x36, 0x66, 0x55, 0x4E, 0x4F, 0x75, 0x49, 0x6D, 0x6C, 0x0A, 0x65, 0x39, 0x65, 0x69, 0x50, 0x5A, 0x61, 0x47, 0x7A, 0x50, ++ 0x49, 0x6D, 0x4E, 0x43, 0x31, 0x71, 0x6B, 0x70, 0x32, 0x61, 0x47, 0x74, 0x41, 0x77, 0x34, 0x6C, 0x31, 0x4F, 0x42, 0x4C, 0x42, 0x66, 0x69, 0x79, 0x42, 0x2B, 0x64, 0x38, 0x45, 0x39, 0x6C, 0x59, 0x4C, 0x52, 0x52, 0x70, 0x6F, 0x37, 0x50, 0x48, ++ 0x69, 0x34, 0x62, 0x36, 0x48, 0x51, 0x44, 0x57, 0x53, 0x69, 0x65, 0x42, 0x34, 0x70, 0x54, 0x70, 0x50, 0x44, 0x70, 0x46, 0x51, 0x55, 0x57, 0x77, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, ++ 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, ++ 0x32, 0x30, 0x30, 0x39, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, ++ 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x45, 0x4D, 0x7A, 0x43, 0x43, 0x41, 0x78, 0x75, 0x67, 0x41, 0x77, 0x49, 0x42, ++ 0x41, 0x67, 0x49, 0x44, 0x43, 0x59, 0x50, 0x7A, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x43, 0x77, 0x55, 0x41, 0x4D, 0x45, 0x30, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, ++ 0x42, 0x41, 0x59, 0x54, 0x41, 0x6B, 0x52, 0x46, 0x4D, 0x52, 0x55, 0x77, 0x45, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x0A, 0x44, 0x41, 0x78, 0x45, 0x4C, 0x56, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x49, 0x45, 0x64, 0x74, 0x59, 0x6B, 0x67, ++ 0x78, 0x4A, 0x7A, 0x41, 0x6C, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x4D, 0x48, 0x6B, 0x51, 0x74, 0x56, 0x46, 0x4A, 0x56, 0x55, 0x31, 0x51, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x62, 0x47, 0x46, 0x7A, 0x63, 0x79, 0x41, ++ 0x7A, 0x49, 0x45, 0x4E, 0x42, 0x49, 0x44, 0x49, 0x67, 0x4D, 0x6A, 0x41, 0x77, 0x4F, 0x54, 0x41, 0x65, 0x0A, 0x46, 0x77, 0x30, 0x77, 0x4F, 0x54, 0x45, 0x78, 0x4D, 0x44, 0x55, 0x77, 0x4F, 0x44, 0x4D, 0x31, 0x4E, 0x54, 0x68, 0x61, 0x46, 0x77, ++ 0x30, 0x79, 0x4F, 0x54, 0x45, 0x78, 0x4D, 0x44, 0x55, 0x77, 0x4F, 0x44, 0x4D, 0x31, 0x4E, 0x54, 0x68, 0x61, 0x4D, 0x45, 0x30, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6B, 0x52, 0x46, 0x4D, 0x52, ++ 0x55, 0x77, 0x45, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x44, 0x41, 0x78, 0x45, 0x0A, 0x4C, 0x56, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x49, 0x45, 0x64, 0x74, 0x59, 0x6B, 0x67, 0x78, 0x4A, 0x7A, 0x41, 0x6C, 0x42, 0x67, 0x4E, 0x56, 0x42, ++ 0x41, 0x4D, 0x4D, 0x48, 0x6B, 0x51, 0x74, 0x56, 0x46, 0x4A, 0x56, 0x55, 0x31, 0x51, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x62, 0x47, 0x46, 0x7A, 0x63, 0x79, 0x41, 0x7A, 0x49, 0x45, 0x4E, 0x42, 0x49, 0x44, 0x49, 0x67, 0x4D, ++ 0x6A, 0x41, 0x77, 0x4F, 0x54, 0x43, 0x43, 0x41, 0x53, 0x49, 0x77, 0x0A, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x45, 0x50, 0x41, 0x44, 0x43, 0x43, ++ 0x41, 0x51, 0x6F, 0x43, 0x67, 0x67, 0x45, 0x42, 0x41, 0x4E, 0x4F, 0x79, 0x53, 0x73, 0x39, 0x36, 0x52, 0x2B, 0x39, 0x31, 0x6D, 0x79, 0x50, 0x36, 0x4F, 0x69, 0x2F, 0x57, 0x55, 0x45, 0x57, 0x4A, 0x4E, 0x54, 0x72, 0x47, 0x61, 0x39, 0x76, 0x2B, ++ 0x32, 0x77, 0x42, 0x6F, 0x71, 0x4F, 0x41, 0x44, 0x0A, 0x45, 0x52, 0x30, 0x33, 0x55, 0x41, 0x69, 0x66, 0x54, 0x55, 0x70, 0x6F, 0x6C, 0x44, 0x57, 0x7A, 0x55, 0x39, 0x47, 0x55, 0x59, 0x36, 0x63, 0x67, 0x56, 0x71, 0x2F, 0x65, 0x55, 0x58, 0x6A, ++ 0x73, 0x4B, 0x6A, 0x33, 0x7A, 0x53, 0x45, 0x68, 0x51, 0x50, 0x67, 0x72, 0x66, 0x52, 0x6C, 0x57, 0x4C, 0x4A, 0x32, 0x33, 0x44, 0x45, 0x45, 0x30, 0x4E, 0x6B, 0x56, 0x4A, 0x44, 0x32, 0x49, 0x66, 0x67, 0x58, 0x55, 0x34, 0x32, 0x74, 0x53, 0x48, ++ 0x4B, 0x58, 0x7A, 0x6C, 0x41, 0x0A, 0x42, 0x46, 0x39, 0x62, 0x66, 0x73, 0x79, 0x6A, 0x78, 0x69, 0x75, 0x70, 0x51, 0x42, 0x37, 0x5A, 0x4E, 0x6F, 0x54, 0x57, 0x53, 0x50, 0x4F, 0x53, 0x48, 0x6A, 0x52, 0x47, 0x49, 0x43, 0x54, 0x42, 0x70, 0x46, ++ 0x47, 0x4F, 0x53, 0x68, 0x72, 0x76, 0x55, 0x44, 0x39, 0x70, 0x58, 0x52, 0x6C, 0x2F, 0x52, 0x63, 0x50, 0x48, 0x41, 0x59, 0x39, 0x52, 0x79, 0x53, 0x50, 0x6F, 0x63, 0x71, 0x36, 0x30, 0x76, 0x46, 0x59, 0x4A, 0x66, 0x78, 0x4C, 0x4C, 0x48, 0x4C, ++ 0x47, 0x76, 0x0A, 0x4B, 0x5A, 0x41, 0x4B, 0x79, 0x56, 0x58, 0x4D, 0x44, 0x39, 0x4F, 0x30, 0x47, 0x75, 0x31, 0x48, 0x4E, 0x56, 0x70, 0x4B, 0x37, 0x5A, 0x78, 0x7A, 0x42, 0x43, 0x48, 0x51, 0x71, 0x72, 0x30, 0x4D, 0x45, 0x37, 0x55, 0x41, 0x79, ++ 0x69, 0x5A, 0x73, 0x78, 0x47, 0x73, 0x4D, 0x6C, 0x46, 0x71, 0x56, 0x6C, 0x4E, 0x70, 0x51, 0x6D, 0x76, 0x48, 0x2F, 0x70, 0x53, 0x74, 0x6D, 0x4D, 0x61, 0x54, 0x4A, 0x4F, 0x4B, 0x44, 0x66, 0x48, 0x52, 0x2B, 0x34, 0x43, 0x53, 0x37, 0x7A, 0x0A, ++ 0x70, 0x2B, 0x68, 0x6E, 0x55, 0x71, 0x75, 0x56, 0x48, 0x2B, 0x42, 0x47, 0x50, 0x74, 0x69, 0x6B, 0x77, 0x38, 0x70, 0x61, 0x78, 0x54, 0x47, 0x41, 0x36, 0x45, 0x69, 0x61, 0x6E, 0x35, 0x52, 0x70, 0x2F, 0x68, 0x6E, 0x64, 0x32, 0x48, 0x4E, 0x38, ++ 0x67, 0x63, 0x71, 0x57, 0x33, 0x6F, 0x37, 0x74, 0x73, 0x7A, 0x49, 0x46, 0x5A, 0x59, 0x51, 0x30, 0x35, 0x75, 0x62, 0x39, 0x56, 0x78, 0x43, 0x31, 0x58, 0x33, 0x61, 0x2F, 0x4C, 0x37, 0x41, 0x51, 0x44, 0x63, 0x55, 0x43, 0x0A, 0x41, 0x77, 0x45, ++ 0x41, 0x41, 0x61, 0x4F, 0x43, 0x41, 0x52, 0x6F, 0x77, 0x67, 0x67, 0x45, 0x57, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x48, 0x51, 0x59, ++ 0x44, 0x56, 0x52, 0x30, 0x4F, 0x42, 0x42, 0x59, 0x45, 0x46, 0x50, 0x33, 0x61, 0x46, 0x4D, 0x53, 0x66, 0x4D, 0x4E, 0x34, 0x68, 0x76, 0x52, 0x35, 0x43, 0x4F, 0x66, 0x79, 0x72, 0x59, 0x79, 0x4E, 0x4A, 0x0A, 0x34, 0x50, 0x47, 0x45, 0x4D, 0x41, ++ 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x42, 0x42, 0x6A, 0x43, 0x42, 0x30, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x66, 0x42, 0x49, 0x48, 0x4C, 0x4D, 0x49, 0x48, 0x49, 0x4D, 0x49, ++ 0x47, 0x41, 0x6F, 0x48, 0x36, 0x67, 0x66, 0x49, 0x5A, 0x36, 0x62, 0x47, 0x52, 0x68, 0x63, 0x44, 0x6F, 0x76, 0x4C, 0x32, 0x52, 0x70, 0x63, 0x6D, 0x56, 0x6A, 0x64, 0x47, 0x39, 0x79, 0x0A, 0x65, 0x53, 0x35, 0x6B, 0x4C, 0x58, 0x52, 0x79, 0x64, ++ 0x58, 0x4E, 0x30, 0x4C, 0x6D, 0x35, 0x6C, 0x64, 0x43, 0x39, 0x44, 0x54, 0x6A, 0x31, 0x45, 0x4C, 0x56, 0x52, 0x53, 0x56, 0x56, 0x4E, 0x55, 0x4A, 0x54, 0x49, 0x77, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x55, 0x79, 0x4D, 0x45, 0x4E, 0x73, 0x59, ++ 0x58, 0x4E, 0x7A, 0x4A, 0x54, 0x49, 0x77, 0x4D, 0x79, 0x55, 0x79, 0x4D, 0x45, 0x4E, 0x42, 0x4A, 0x54, 0x49, 0x77, 0x4D, 0x69, 0x55, 0x79, 0x4D, 0x44, 0x49, 0x77, 0x0A, 0x4D, 0x44, 0x6B, 0x73, 0x54, 0x7A, 0x31, 0x45, 0x4C, 0x56, 0x52, 0x79, ++ 0x64, 0x58, 0x4E, 0x30, 0x4A, 0x54, 0x49, 0x77, 0x52, 0x32, 0x31, 0x69, 0x53, 0x43, 0x78, 0x44, 0x50, 0x55, 0x52, 0x46, 0x50, 0x32, 0x4E, 0x6C, 0x63, 0x6E, 0x52, 0x70, 0x5A, 0x6D, 0x6C, 0x6A, 0x59, 0x58, 0x52, 0x6C, 0x63, 0x6D, 0x56, 0x32, ++ 0x62, 0x32, 0x4E, 0x68, 0x64, 0x47, 0x6C, 0x76, 0x62, 0x6D, 0x78, 0x70, 0x63, 0x33, 0x51, 0x77, 0x51, 0x36, 0x42, 0x42, 0x6F, 0x44, 0x2B, 0x47, 0x0A, 0x50, 0x57, 0x68, 0x30, 0x64, 0x48, 0x41, 0x36, 0x4C, 0x79, 0x39, 0x33, 0x64, 0x33, 0x63, ++ 0x75, 0x5A, 0x43, 0x31, 0x30, 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x43, 0x35, 0x75, 0x5A, 0x58, 0x51, 0x76, 0x59, 0x33, 0x4A, 0x73, 0x4C, 0x32, 0x51, 0x74, 0x64, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x52, 0x66, 0x63, 0x6D, 0x39, 0x76, 0x64, 0x46, 0x39, ++ 0x6A, 0x62, 0x47, 0x46, 0x7A, 0x63, 0x31, 0x38, 0x7A, 0x58, 0x32, 0x4E, 0x68, 0x58, 0x7A, 0x4A, 0x66, 0x4D, 0x6A, 0x41, 0x77, 0x0A, 0x4F, 0x53, 0x35, 0x6A, 0x63, 0x6D, 0x77, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, ++ 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x45, 0x42, 0x41, 0x48, 0x2B, 0x58, 0x32, 0x7A, 0x44, 0x49, 0x33, 0x36, 0x53, 0x63, 0x66, 0x53, 0x46, 0x36, 0x67, 0x48, 0x44, 0x4F, 0x46, 0x42, 0x4A, 0x70, 0x69, 0x42, ++ 0x53, 0x56, 0x59, 0x45, 0x51, 0x42, 0x72, 0x4C, 0x4C, 0x70, 0x4D, 0x45, 0x2B, 0x62, 0x55, 0x4D, 0x4A, 0x6D, 0x0A, 0x32, 0x48, 0x36, 0x4E, 0x4D, 0x4C, 0x56, 0x77, 0x4D, 0x65, 0x6E, 0x69, 0x61, 0x63, 0x66, 0x7A, 0x63, 0x4E, 0x73, 0x67, 0x46, ++ 0x59, 0x62, 0x51, 0x44, 0x66, 0x43, 0x2B, 0x72, 0x41, 0x46, 0x31, 0x68, 0x4D, 0x35, 0x2B, 0x6E, 0x30, 0x32, 0x2F, 0x74, 0x32, 0x41, 0x37, 0x6E, 0x50, 0x50, 0x4B, 0x48, 0x65, 0x4A, 0x65, 0x61, 0x4E, 0x69, 0x6A, 0x6E, 0x5A, 0x66, 0x6C, 0x51, ++ 0x47, 0x44, 0x53, 0x4E, 0x69, 0x48, 0x2B, 0x30, 0x4C, 0x53, 0x34, 0x46, 0x39, 0x70, 0x30, 0x0A, 0x6F, 0x33, 0x2F, 0x55, 0x33, 0x37, 0x43, 0x59, 0x41, 0x71, 0x78, 0x76, 0x61, 0x32, 0x73, 0x73, 0x4A, 0x53, 0x52, 0x79, 0x6F, 0x57, 0x58, 0x75, ++ 0x4A, 0x56, 0x72, 0x6C, 0x35, 0x6A, 0x4C, 0x6E, 0x38, 0x74, 0x2B, 0x72, 0x53, 0x66, 0x72, 0x7A, 0x6B, 0x47, 0x6B, 0x6A, 0x32, 0x77, 0x54, 0x5A, 0x35, 0x31, 0x78, 0x59, 0x2F, 0x47, 0x58, 0x55, 0x6C, 0x37, 0x37, 0x4D, 0x2F, 0x43, 0x34, 0x4B, ++ 0x7A, 0x43, 0x55, 0x71, 0x4E, 0x51, 0x54, 0x34, 0x59, 0x4A, 0x45, 0x56, 0x0A, 0x64, 0x54, 0x31, 0x42, 0x2F, 0x79, 0x4D, 0x66, 0x47, 0x63, 0x68, 0x73, 0x36, 0x34, 0x4A, 0x54, 0x42, 0x4B, 0x62, 0x6B, 0x54, 0x43, 0x4A, 0x4E, 0x6A, 0x59, 0x79, ++ 0x36, 0x7A, 0x6C, 0x74, 0x7A, 0x37, 0x47, 0x52, 0x55, 0x55, 0x47, 0x33, 0x52, 0x6E, 0x46, 0x58, 0x37, 0x61, 0x63, 0x4D, 0x32, 0x77, 0x34, 0x79, 0x38, 0x50, 0x49, 0x57, 0x6D, 0x61, 0x77, 0x6F, 0x6D, 0x44, 0x65, 0x43, 0x54, 0x6D, 0x47, 0x43, ++ 0x75, 0x66, 0x73, 0x59, 0x6B, 0x6C, 0x34, 0x70, 0x68, 0x0A, 0x58, 0x35, 0x47, 0x4F, 0x5A, 0x70, 0x49, 0x4A, 0x68, 0x7A, 0x62, 0x4E, 0x69, 0x35, 0x73, 0x74, 0x50, 0x76, 0x5A, 0x52, 0x31, 0x46, 0x44, 0x55, 0x57, 0x53, 0x69, 0x39, 0x67, 0x2F, ++ 0x4C, 0x4D, 0x4B, 0x48, 0x74, 0x54, 0x68, 0x6D, 0x33, 0x59, 0x4A, 0x6F, 0x68, 0x77, 0x31, 0x2B, 0x71, 0x52, 0x7A, 0x54, 0x36, 0x35, 0x79, 0x73, 0x43, 0x51, 0x62, 0x6C, 0x72, 0x47, 0x58, 0x6E, 0x52, 0x6C, 0x31, 0x31, 0x7A, 0x2B, 0x6F, 0x2B, ++ 0x49, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x52, 0x6F, ++ 0x6F, 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, 0x45, 0x56, 0x20, 0x32, 0x30, 0x30, 0x39, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, ++ 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x45, 0x51, 0x7A, 0x43, 0x43, 0x41, 0x79, 0x75, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x44, 0x43, 0x59, 0x50, 0x30, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, ++ 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x43, 0x77, 0x55, 0x41, 0x4D, 0x46, 0x41, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6B, 0x52, 0x46, 0x4D, 0x52, 0x55, 0x77, 0x45, 0x77, 0x59, 0x44, 0x56, 0x51, ++ 0x51, 0x4B, 0x0A, 0x44, 0x41, 0x78, 0x45, 0x4C, 0x56, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x49, 0x45, 0x64, 0x74, 0x59, 0x6B, 0x67, 0x78, 0x4B, 0x6A, 0x41, 0x6F, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x4D, 0x49, 0x55, 0x51, 0x74, 0x56, ++ 0x46, 0x4A, 0x56, 0x55, 0x31, 0x51, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x62, 0x47, 0x46, 0x7A, 0x63, 0x79, 0x41, 0x7A, 0x49, 0x45, 0x4E, 0x42, 0x49, 0x44, 0x49, 0x67, 0x52, 0x56, 0x59, 0x67, 0x4D, 0x6A, 0x41, 0x77, 0x0A, ++ 0x4F, 0x54, 0x41, 0x65, 0x46, 0x77, 0x30, 0x77, 0x4F, 0x54, 0x45, 0x78, 0x4D, 0x44, 0x55, 0x77, 0x4F, 0x44, 0x55, 0x77, 0x4E, 0x44, 0x5A, 0x61, 0x46, 0x77, 0x30, 0x79, 0x4F, 0x54, 0x45, 0x78, 0x4D, 0x44, 0x55, 0x77, 0x4F, 0x44, 0x55, 0x77, ++ 0x4E, 0x44, 0x5A, 0x61, 0x4D, 0x46, 0x41, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6B, 0x52, 0x46, 0x4D, 0x52, 0x55, 0x77, 0x45, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x0A, 0x44, 0x41, 0x78, ++ 0x45, 0x4C, 0x56, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x49, 0x45, 0x64, 0x74, 0x59, 0x6B, 0x67, 0x78, 0x4B, 0x6A, 0x41, 0x6F, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x4D, 0x49, 0x55, 0x51, 0x74, 0x56, 0x46, 0x4A, 0x56, 0x55, 0x31, 0x51, ++ 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x62, 0x47, 0x46, 0x7A, 0x63, 0x79, 0x41, 0x7A, 0x49, 0x45, 0x4E, 0x42, 0x49, 0x44, 0x49, 0x67, 0x52, 0x56, 0x59, 0x67, 0x4D, 0x6A, 0x41, 0x77, 0x0A, 0x4F, 0x54, 0x43, 0x43, 0x41, 0x53, ++ 0x49, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x45, 0x50, 0x41, 0x44, 0x43, 0x43, 0x41, 0x51, 0x6F, 0x43, 0x67, 0x67, 0x45, 0x42, 0x41, 0x4A, ++ 0x6E, 0x78, 0x68, 0x44, 0x52, 0x77, 0x75, 0x69, 0x2B, 0x33, 0x4D, 0x4B, 0x43, 0x4F, 0x76, 0x58, 0x77, 0x45, 0x7A, 0x37, 0x35, 0x69, 0x76, 0x4A, 0x6E, 0x39, 0x67, 0x70, 0x66, 0x53, 0x0A, 0x65, 0x67, 0x70, 0x6E, 0x6C, 0x6A, 0x67, 0x4A, 0x39, ++ 0x68, 0x42, 0x4F, 0x6C, 0x53, 0x4A, 0x7A, 0x6D, 0x59, 0x33, 0x61, 0x46, 0x53, 0x33, 0x6E, 0x42, 0x66, 0x77, 0x5A, 0x63, 0x79, 0x4B, 0x33, 0x6A, 0x70, 0x67, 0x41, 0x76, 0x44, 0x77, 0x39, 0x72, 0x4B, 0x46, 0x73, 0x2B, 0x39, 0x5A, 0x35, 0x4A, ++ 0x55, 0x75, 0x74, 0x38, 0x4D, 0x78, 0x6B, 0x32, 0x6F, 0x67, 0x2B, 0x4B, 0x62, 0x67, 0x50, 0x43, 0x64, 0x4D, 0x30, 0x33, 0x54, 0x50, 0x31, 0x59, 0x74, 0x48, 0x68, 0x0A, 0x7A, 0x52, 0x6E, 0x70, 0x37, 0x68, 0x68, 0x50, 0x54, 0x46, 0x69, 0x75, ++ 0x34, 0x68, 0x37, 0x57, 0x44, 0x46, 0x73, 0x56, 0x57, 0x74, 0x67, 0x36, 0x75, 0x4D, 0x51, 0x59, 0x5A, 0x42, 0x37, 0x6A, 0x4D, 0x37, 0x4B, 0x31, 0x69, 0x58, 0x64, 0x4F, 0x44, 0x4C, 0x2F, 0x5A, 0x6C, 0x47, 0x73, 0x54, 0x6C, 0x32, 0x38, 0x53, ++ 0x6F, 0x2F, 0x36, 0x5A, 0x71, 0x51, 0x54, 0x4D, 0x46, 0x65, 0x78, 0x67, 0x61, 0x44, 0x62, 0x74, 0x43, 0x48, 0x75, 0x33, 0x39, 0x62, 0x2B, 0x54, 0x0A, 0x37, 0x57, 0x59, 0x78, 0x67, 0x34, 0x7A, 0x47, 0x63, 0x54, 0x53, 0x48, 0x54, 0x68, 0x66, ++ 0x71, 0x72, 0x34, 0x75, 0x52, 0x6A, 0x52, 0x78, 0x57, 0x51, 0x61, 0x34, 0x69, 0x4E, 0x31, 0x34, 0x33, 0x38, 0x68, 0x33, 0x5A, 0x30, 0x53, 0x30, 0x4E, 0x4C, 0x32, 0x6C, 0x52, 0x70, 0x37, 0x35, 0x6D, 0x70, 0x6F, 0x6F, 0x36, 0x4B, 0x72, 0x33, ++ 0x48, 0x47, 0x72, 0x48, 0x68, 0x46, 0x50, 0x43, 0x2B, 0x4F, 0x68, 0x32, 0x35, 0x7A, 0x31, 0x75, 0x78, 0x61, 0x76, 0x36, 0x30, 0x0A, 0x73, 0x55, 0x59, 0x67, 0x6F, 0x76, 0x73, 0x65, 0x4F, 0x33, 0x44, 0x76, 0x6B, 0x35, 0x68, 0x39, 0x6A, 0x48, ++ 0x4F, 0x57, 0x38, 0x73, 0x58, 0x76, 0x68, 0x58, 0x43, 0x74, 0x4B, 0x53, 0x62, 0x38, 0x48, 0x67, 0x51, 0x2B, 0x48, 0x4B, 0x44, 0x59, 0x44, 0x38, 0x74, 0x53, 0x67, 0x32, 0x4A, 0x38, 0x37, 0x6F, 0x74, 0x54, 0x6C, 0x5A, 0x43, 0x70, 0x56, 0x36, ++ 0x4C, 0x71, 0x59, 0x51, 0x58, 0x59, 0x2B, 0x55, 0x33, 0x45, 0x4A, 0x2F, 0x70, 0x75, 0x72, 0x65, 0x33, 0x35, 0x0A, 0x31, 0x31, 0x48, 0x33, 0x61, 0x36, 0x55, 0x43, 0x41, 0x77, 0x45, 0x41, 0x41, 0x61, 0x4F, 0x43, 0x41, 0x53, 0x51, 0x77, 0x67, ++ 0x67, 0x45, 0x67, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x48, 0x51, 0x59, 0x44, 0x56, 0x52, 0x30, 0x4F, 0x42, 0x42, 0x59, 0x45, 0x46, ++ 0x4E, 0x4F, 0x55, 0x69, 0x6B, 0x78, 0x69, 0x45, 0x79, 0x6F, 0x5A, 0x4C, 0x73, 0x79, 0x76, 0x0A, 0x63, 0x6F, 0x70, 0x39, 0x4E, 0x74, 0x65, 0x61, 0x48, 0x4E, 0x78, 0x6E, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, ++ 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x42, 0x42, 0x6A, 0x43, 0x42, 0x33, 0x51, 0x59, 0x44, 0x56, 0x52, 0x30, 0x66, 0x42, 0x49, 0x48, 0x56, 0x4D, 0x49, 0x48, 0x53, 0x4D, 0x49, 0x47, 0x48, 0x6F, 0x49, 0x47, 0x45, 0x6F, 0x49, 0x47, 0x42, ++ 0x68, 0x6E, 0x39, 0x73, 0x5A, 0x47, 0x46, 0x77, 0x4F, 0x69, 0x38, 0x76, 0x0A, 0x5A, 0x47, 0x6C, 0x79, 0x5A, 0x57, 0x4E, 0x30, 0x62, 0x33, 0x4A, 0x35, 0x4C, 0x6D, 0x51, 0x74, 0x64, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x51, 0x75, 0x62, 0x6D, 0x56, ++ 0x30, 0x4C, 0x30, 0x4E, 0x4F, 0x50, 0x55, 0x51, 0x74, 0x56, 0x46, 0x4A, 0x56, 0x55, 0x31, 0x51, 0x6C, 0x4D, 0x6A, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x4A, 0x54, 0x49, 0x77, 0x51, 0x32, 0x78, 0x68, 0x63, 0x33, 0x4D, 0x6C, 0x4D, 0x6A, 0x41, ++ 0x7A, 0x4A, 0x54, 0x49, 0x77, 0x51, 0x30, 0x45, 0x6C, 0x0A, 0x4D, 0x6A, 0x41, 0x79, 0x4A, 0x54, 0x49, 0x77, 0x52, 0x56, 0x59, 0x6C, 0x4D, 0x6A, 0x41, 0x79, 0x4D, 0x44, 0x41, 0x35, 0x4C, 0x45, 0x38, 0x39, 0x52, 0x43, 0x31, 0x55, 0x63, 0x6E, ++ 0x56, 0x7A, 0x64, 0x43, 0x55, 0x79, 0x4D, 0x45, 0x64, 0x74, 0x59, 0x6B, 0x67, 0x73, 0x51, 0x7A, 0x31, 0x45, 0x52, 0x54, 0x39, 0x6A, 0x5A, 0x58, 0x4A, 0x30, 0x61, 0x57, 0x5A, 0x70, 0x59, 0x32, 0x46, 0x30, 0x5A, 0x58, 0x4A, 0x6C, 0x64, 0x6D, ++ 0x39, 0x6A, 0x59, 0x58, 0x52, 0x70, 0x0A, 0x62, 0x32, 0x35, 0x73, 0x61, 0x58, 0x4E, 0x30, 0x4D, 0x45, 0x61, 0x67, 0x52, 0x4B, 0x42, 0x43, 0x68, 0x6B, 0x42, 0x6F, 0x64, 0x48, 0x52, 0x77, 0x4F, 0x69, 0x38, 0x76, 0x64, 0x33, 0x64, 0x33, 0x4C, ++ 0x6D, 0x51, 0x74, 0x64, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x51, 0x75, 0x62, 0x6D, 0x56, 0x30, 0x4C, 0x32, 0x4E, 0x79, 0x62, 0x43, 0x39, 0x6B, 0x4C, 0x58, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x58, 0x33, 0x4A, 0x76, 0x62, 0x33, 0x52, 0x66, 0x59, ++ 0x32, 0x78, 0x68, 0x0A, 0x63, 0x33, 0x4E, 0x66, 0x4D, 0x31, 0x39, 0x6A, 0x59, 0x56, 0x38, 0x79, 0x58, 0x32, 0x56, 0x32, 0x58, 0x7A, 0x49, 0x77, 0x4D, 0x44, 0x6B, 0x75, 0x59, 0x33, 0x4A, 0x73, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, ++ 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x43, 0x77, 0x55, 0x41, 0x41, 0x34, 0x49, 0x42, 0x41, 0x51, 0x41, 0x30, 0x37, 0x58, 0x74, 0x61, 0x50, 0x4B, 0x53, 0x55, 0x69, 0x4F, 0x38, 0x61, 0x45, 0x58, 0x55, 0x48, 0x4C, 0x37, 0x50, 0x2B, ++ 0x0A, 0x50, 0x50, 0x6F, 0x65, 0x55, 0x53, 0x62, 0x72, 0x68, 0x2F, 0x59, 0x70, 0x33, 0x75, 0x44, 0x78, 0x31, 0x4D, 0x59, 0x6B, 0x43, 0x65, 0x6E, 0x42, 0x7A, 0x31, 0x55, 0x62, 0x74, 0x44, 0x44, 0x5A, 0x7A, 0x68, 0x72, 0x2B, 0x42, 0x6C, 0x47, ++ 0x6D, 0x46, 0x61, 0x51, 0x74, 0x37, 0x37, 0x4A, 0x4C, 0x76, 0x79, 0x41, 0x6F, 0x4A, 0x55, 0x6E, 0x52, 0x70, 0x6A, 0x5A, 0x33, 0x4E, 0x4F, 0x68, 0x6B, 0x33, 0x31, 0x4B, 0x78, 0x45, 0x63, 0x64, 0x7A, 0x65, 0x73, 0x30, 0x35, 0x0A, 0x6E, 0x73, ++ 0x4B, 0x74, 0x6A, 0x48, 0x45, 0x68, 0x38, 0x6C, 0x70, 0x72, 0x72, 0x39, 0x38, 0x38, 0x54, 0x6C, 0x57, 0x76, 0x73, 0x6F, 0x52, 0x6C, 0x46, 0x49, 0x6D, 0x35, 0x64, 0x38, 0x73, 0x71, 0x4D, 0x62, 0x37, 0x50, 0x6F, 0x32, 0x33, 0x50, 0x62, 0x30, ++ 0x69, 0x55, 0x4D, 0x6B, 0x5A, 0x76, 0x35, 0x33, 0x47, 0x4D, 0x6F, 0x4B, 0x61, 0x45, 0x47, 0x54, 0x63, 0x48, 0x38, 0x67, 0x4E, 0x46, 0x43, 0x53, 0x75, 0x47, 0x64, 0x58, 0x7A, 0x66, 0x58, 0x32, 0x6C, 0x58, 0x0A, 0x41, 0x4E, 0x74, 0x75, 0x32, ++ 0x4B, 0x5A, 0x79, 0x49, 0x6B, 0x74, 0x51, 0x31, 0x48, 0x57, 0x59, 0x56, 0x74, 0x2B, 0x33, 0x47, 0x50, 0x39, 0x44, 0x51, 0x31, 0x43, 0x75, 0x65, 0x6B, 0x52, 0x37, 0x38, 0x48, 0x6C, 0x52, 0x31, 0x30, 0x4D, 0x39, 0x70, 0x39, 0x4F, 0x42, 0x30, ++ 0x2F, 0x44, 0x4A, 0x54, 0x37, 0x6E, 0x61, 0x78, 0x70, 0x65, 0x47, 0x30, 0x49, 0x4C, 0x44, 0x35, 0x45, 0x4A, 0x74, 0x2F, 0x72, 0x44, 0x69, 0x5A, 0x45, 0x34, 0x4F, 0x4A, 0x75, 0x64, 0x41, 0x0A, 0x4E, 0x43, 0x61, 0x31, 0x43, 0x49, 0x6E, 0x58, ++ 0x43, 0x47, 0x4E, 0x6A, 0x4F, 0x43, 0x64, 0x31, 0x48, 0x6A, 0x50, 0x71, 0x62, 0x71, 0x6A, 0x64, 0x6E, 0x35, 0x6C, 0x50, 0x64, 0x45, 0x32, 0x42, 0x69, 0x59, 0x42, 0x4C, 0x33, 0x5A, 0x71, 0x58, 0x4B, 0x56, 0x77, 0x76, 0x76, 0x6F, 0x46, 0x42, ++ 0x75, 0x59, 0x7A, 0x2F, 0x36, 0x6E, 0x31, 0x67, 0x42, 0x70, 0x37, 0x4E, 0x31, 0x7A, 0x33, 0x54, 0x4C, 0x71, 0x4D, 0x56, 0x76, 0x4B, 0x6A, 0x6D, 0x4A, 0x75, 0x56, 0x76, 0x0A, 0x77, 0x39, 0x79, 0x34, 0x41, 0x79, 0x48, 0x71, 0x6E, 0x78, 0x62, ++ 0x78, 0x4C, 0x46, 0x53, 0x31, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x43, 0x41, 0x20, 0x44, 0x69, 0x73, 0x69, ++ 0x67, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x32, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, ++ 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x61, 0x54, 0x43, 0x43, 0x41, 0x31, 0x47, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x4A, 0x41, 0x4A, 0x4B, 0x34, 0x69, ++ 0x4E, 0x75, 0x77, 0x69, 0x73, 0x46, 0x6A, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x43, 0x77, 0x55, 0x41, 0x4D, 0x46, 0x49, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, ++ 0x41, 0x59, 0x54, 0x41, 0x6C, 0x4E, 0x4C, 0x4D, 0x52, 0x4D, 0x77, 0x0A, 0x45, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x48, 0x45, 0x77, 0x70, 0x43, 0x63, 0x6D, 0x46, 0x30, 0x61, 0x58, 0x4E, 0x73, 0x59, 0x58, 0x5A, 0x68, 0x4D, 0x52, 0x4D, 0x77, ++ 0x45, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x45, 0x77, 0x70, 0x45, 0x61, 0x58, 0x4E, 0x70, 0x5A, 0x79, 0x42, 0x68, 0x4C, 0x6E, 0x4D, 0x75, 0x4D, 0x52, 0x6B, 0x77, 0x46, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x42, 0x44, ++ 0x51, 0x53, 0x42, 0x45, 0x61, 0x58, 0x4E, 0x70, 0x0A, 0x5A, 0x79, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x46, 0x49, 0x79, 0x4D, 0x42, 0x34, 0x58, 0x44, 0x54, 0x45, 0x79, 0x4D, 0x44, 0x63, 0x78, 0x4F, 0x54, 0x41, 0x35, 0x4D, 0x54, 0x55, ++ 0x7A, 0x4D, 0x46, 0x6F, 0x58, 0x44, 0x54, 0x51, 0x79, 0x4D, 0x44, 0x63, 0x78, 0x4F, 0x54, 0x41, 0x35, 0x4D, 0x54, 0x55, 0x7A, 0x4D, 0x46, 0x6F, 0x77, 0x55, 0x6A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, ++ 0x43, 0x55, 0x30, 0x73, 0x78, 0x0A, 0x45, 0x7A, 0x41, 0x52, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x63, 0x54, 0x43, 0x6B, 0x4A, 0x79, 0x59, 0x58, 0x52, 0x70, 0x63, 0x32, 0x78, 0x68, 0x64, 0x6D, 0x45, 0x78, 0x45, 0x7A, 0x41, 0x52, 0x42, 0x67, ++ 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x43, 0x6B, 0x52, 0x70, 0x63, 0x32, 0x6C, 0x6E, 0x49, 0x47, 0x45, 0x75, 0x63, 0x79, 0x34, 0x78, 0x47, 0x54, 0x41, 0x58, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x45, 0x45, 0x4E, 0x42, 0x49, 0x45, ++ 0x52, 0x70, 0x0A, 0x63, 0x32, 0x6C, 0x6E, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x55, 0x6A, 0x49, 0x77, 0x67, 0x67, 0x49, 0x69, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, ++ 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x49, 0x4B, 0x41, 0x6F, 0x49, 0x43, 0x41, 0x51, 0x43, 0x69, 0x6F, 0x38, 0x51, 0x41, 0x43, 0x64, 0x61, 0x46, 0x58, 0x53, 0x31, 0x74, 0x46, 0x50, 0x62, 0x43, 0x0A, ++ 0x77, 0x33, 0x4F, 0x65, 0x4E, 0x63, 0x4A, 0x78, 0x56, 0x58, 0x36, 0x42, 0x2B, 0x36, 0x74, 0x47, 0x55, 0x4F, 0x44, 0x42, 0x66, 0x45, 0x6C, 0x34, 0x35, 0x71, 0x74, 0x35, 0x57, 0x44, 0x7A, 0x61, 0x2F, 0x33, 0x77, 0x63, 0x6E, 0x39, 0x69, 0x58, ++ 0x41, 0x6E, 0x67, 0x2B, 0x61, 0x30, 0x45, 0x45, 0x36, 0x55, 0x47, 0x39, 0x76, 0x67, 0x4D, 0x73, 0x52, 0x66, 0x59, 0x76, 0x5A, 0x4E, 0x53, 0x72, 0x58, 0x61, 0x4E, 0x48, 0x50, 0x57, 0x53, 0x62, 0x36, 0x57, 0x69, 0x61, 0x0A, 0x78, 0x73, 0x77, ++ 0x62, 0x50, 0x37, 0x71, 0x2B, 0x73, 0x6F, 0x73, 0x30, 0x41, 0x69, 0x36, 0x59, 0x56, 0x52, 0x6E, 0x38, 0x6A, 0x47, 0x2B, 0x71, 0x58, 0x39, 0x70, 0x4D, 0x7A, 0x6B, 0x30, 0x44, 0x49, 0x61, 0x50, 0x59, 0x30, 0x6A, 0x53, 0x54, 0x56, 0x70, 0x62, ++ 0x4C, 0x54, 0x41, 0x77, 0x41, 0x46, 0x6A, 0x78, 0x66, 0x47, 0x73, 0x33, 0x49, 0x78, 0x32, 0x79, 0x6D, 0x72, 0x64, 0x4D, 0x78, 0x70, 0x37, 0x7A, 0x6F, 0x35, 0x65, 0x46, 0x6D, 0x31, 0x74, 0x4C, 0x37, 0x0A, 0x41, 0x37, 0x52, 0x42, 0x5A, 0x63, ++ 0x6B, 0x51, 0x72, 0x67, 0x34, 0x46, 0x59, 0x38, 0x61, 0x41, 0x61, 0x6D, 0x6B, 0x77, 0x2F, 0x64, 0x4C, 0x75, 0x6B, 0x4F, 0x38, 0x4E, 0x4A, 0x39, 0x2B, 0x66, 0x6C, 0x58, 0x50, 0x30, 0x34, 0x53, 0x58, 0x61, 0x62, 0x42, 0x62, 0x65, 0x51, 0x54, ++ 0x67, 0x30, 0x36, 0x6F, 0x76, 0x38, 0x30, 0x65, 0x67, 0x45, 0x46, 0x47, 0x45, 0x74, 0x51, 0x58, 0x36, 0x73, 0x78, 0x33, 0x64, 0x4F, 0x79, 0x31, 0x46, 0x55, 0x2B, 0x31, 0x36, 0x53, 0x0A, 0x47, 0x42, 0x73, 0x45, 0x57, 0x6D, 0x6A, 0x47, 0x79, ++ 0x63, 0x54, 0x36, 0x74, 0x78, 0x4F, 0x67, 0x6D, 0x4C, 0x63, 0x52, 0x4B, 0x37, 0x66, 0x57, 0x56, 0x38, 0x78, 0x38, 0x6E, 0x68, 0x66, 0x52, 0x79, 0x79, 0x58, 0x2B, 0x68, 0x6B, 0x34, 0x6B, 0x4C, 0x6C, 0x59, 0x4D, 0x65, 0x45, 0x32, 0x65, 0x41, ++ 0x52, 0x4B, 0x6D, 0x4B, 0x36, 0x63, 0x42, 0x5A, 0x57, 0x35, 0x38, 0x59, 0x68, 0x32, 0x45, 0x68, 0x4E, 0x2F, 0x71, 0x77, 0x47, 0x75, 0x31, 0x70, 0x53, 0x71, 0x56, 0x0A, 0x67, 0x38, 0x4E, 0x54, 0x45, 0x51, 0x78, 0x7A, 0x48, 0x51, 0x75, 0x79, ++ 0x52, 0x70, 0x44, 0x52, 0x51, 0x6A, 0x72, 0x4F, 0x51, 0x47, 0x36, 0x56, 0x72, 0x66, 0x2F, 0x47, 0x6C, 0x4B, 0x31, 0x75, 0x6C, 0x34, 0x53, 0x4F, 0x66, 0x57, 0x2B, 0x65, 0x69, 0x6F, 0x41, 0x4E, 0x53, 0x57, 0x31, 0x7A, 0x34, 0x6E, 0x75, 0x53, ++ 0x48, 0x73, 0x50, 0x7A, 0x77, 0x66, 0x50, 0x72, 0x4C, 0x67, 0x56, 0x76, 0x32, 0x52, 0x76, 0x50, 0x4E, 0x33, 0x59, 0x45, 0x79, 0x4C, 0x52, 0x61, 0x0A, 0x35, 0x42, 0x65, 0x6E, 0x79, 0x39, 0x31, 0x32, 0x48, 0x39, 0x41, 0x5A, 0x64, 0x75, 0x67, ++ 0x73, 0x42, 0x62, 0x50, 0x57, 0x6E, 0x44, 0x54, 0x59, 0x6C, 0x74, 0x78, 0x68, 0x68, 0x35, 0x45, 0x46, 0x35, 0x45, 0x51, 0x49, 0x4D, 0x38, 0x48, 0x61, 0x75, 0x51, 0x68, 0x6C, 0x31, 0x4B, 0x36, 0x79, 0x4E, 0x67, 0x33, 0x72, 0x75, 0x6A, 0x69, ++ 0x36, 0x44, 0x4F, 0x57, 0x62, 0x6E, 0x75, 0x75, 0x4E, 0x5A, 0x74, 0x32, 0x5A, 0x7A, 0x39, 0x61, 0x4A, 0x51, 0x66, 0x59, 0x45, 0x0A, 0x6B, 0x6F, 0x6F, 0x70, 0x4B, 0x57, 0x31, 0x72, 0x4F, 0x68, 0x7A, 0x6E, 0x64, 0x58, 0x30, 0x43, 0x63, 0x51, ++ 0x37, 0x7A, 0x77, 0x4F, 0x65, 0x39, 0x79, 0x78, 0x6E, 0x64, 0x6E, 0x57, 0x43, 0x79, 0x77, 0x6D, 0x5A, 0x67, 0x74, 0x72, 0x45, 0x45, 0x37, 0x73, 0x6E, 0x6D, 0x68, 0x72, 0x6D, 0x61, 0x5A, 0x6B, 0x43, 0x6F, 0x35, 0x78, 0x48, 0x74, 0x67, 0x55, ++ 0x55, 0x44, 0x69, 0x2F, 0x5A, 0x6E, 0x57, 0x65, 0x6A, 0x42, 0x42, 0x68, 0x47, 0x39, 0x33, 0x63, 0x2B, 0x41, 0x0A, 0x41, 0x6B, 0x39, 0x6C, 0x51, 0x48, 0x68, 0x63, 0x52, 0x31, 0x44, 0x49, 0x6D, 0x2B, 0x59, 0x66, 0x67, 0x58, 0x76, 0x6B, 0x52, ++ 0x4B, 0x68, 0x62, 0x68, 0x5A, 0x72, 0x69, 0x33, 0x6C, 0x72, 0x56, 0x78, 0x2F, 0x6B, 0x36, 0x52, 0x47, 0x5A, 0x4C, 0x35, 0x44, 0x4A, 0x55, 0x66, 0x4F, 0x52, 0x73, 0x6E, 0x4C, 0x4D, 0x4F, 0x50, 0x52, 0x65, 0x69, 0x73, 0x6A, 0x51, 0x53, 0x31, ++ 0x6E, 0x36, 0x79, 0x71, 0x45, 0x6D, 0x37, 0x30, 0x58, 0x6F, 0x6F, 0x51, 0x4C, 0x36, 0x69, 0x0A, 0x46, 0x68, 0x2F, 0x66, 0x35, 0x44, 0x63, 0x66, 0x45, 0x58, 0x50, 0x37, 0x6B, 0x41, 0x70, 0x6C, 0x51, 0x36, 0x49, 0x4E, 0x66, 0x50, 0x67, 0x47, ++ 0x41, 0x56, 0x55, 0x7A, 0x66, 0x62, 0x41, 0x4E, 0x75, 0x50, 0x54, 0x31, 0x72, 0x71, 0x56, 0x43, 0x56, 0x33, 0x77, 0x32, 0x45, 0x59, 0x78, 0x37, 0x58, 0x73, 0x51, 0x44, 0x6E, 0x59, 0x78, 0x35, 0x6E, 0x51, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, ++ 0x6F, 0x30, 0x49, 0x77, 0x51, 0x44, 0x41, 0x50, 0x42, 0x67, 0x4E, 0x56, 0x0A, 0x48, 0x52, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x54, 0x41, 0x44, 0x41, 0x51, 0x48, 0x2F, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, ++ 0x42, 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x42, 0x42, 0x6A, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x74, 0x5A, 0x6E, 0x34, 0x72, 0x37, 0x43, 0x55, 0x39, 0x65, 0x4D, 0x67, 0x31, 0x67, 0x71, ++ 0x74, 0x7A, 0x6B, 0x35, 0x57, 0x70, 0x43, 0x35, 0x75, 0x0A, 0x51, 0x75, 0x30, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x42, 0x41, 0x43, ++ 0x59, 0x47, 0x58, 0x6E, 0x44, 0x6E, 0x5A, 0x54, 0x50, 0x49, 0x67, 0x6D, 0x37, 0x5A, 0x6E, 0x42, 0x63, 0x36, 0x47, 0x33, 0x70, 0x6D, 0x73, 0x67, 0x48, 0x32, 0x65, 0x44, 0x74, 0x70, 0x58, 0x69, 0x2F, 0x71, 0x2F, 0x30, 0x37, 0x35, 0x4B, 0x4D, ++ 0x4F, 0x59, 0x4B, 0x6D, 0x46, 0x4D, 0x0A, 0x74, 0x43, 0x51, 0x53, 0x69, 0x6E, 0x31, 0x74, 0x45, 0x52, 0x54, 0x33, 0x6E, 0x4C, 0x58, 0x4B, 0x35, 0x72, 0x79, 0x65, 0x4A, 0x34, 0x35, 0x4D, 0x47, 0x63, 0x69, 0x70, 0x76, 0x58, 0x72, 0x41, 0x31, ++ 0x7A, 0x59, 0x4F, 0x62, 0x59, 0x56, 0x79, 0x62, 0x71, 0x6A, 0x47, 0x6F, 0x6D, 0x33, 0x32, 0x2B, 0x6E, 0x4E, 0x6A, 0x66, 0x37, 0x78, 0x75, 0x65, 0x51, 0x67, 0x63, 0x6E, 0x59, 0x71, 0x66, 0x47, 0x6F, 0x70, 0x54, 0x70, 0x74, 0x69, 0x37, 0x32, ++ 0x54, 0x56, 0x56, 0x0A, 0x73, 0x52, 0x48, 0x46, 0x71, 0x51, 0x4F, 0x7A, 0x56, 0x6A, 0x75, 0x35, 0x68, 0x4A, 0x4D, 0x69, 0x58, 0x6E, 0x37, 0x42, 0x39, 0x68, 0x4A, 0x53, 0x69, 0x2B, 0x6F, 0x73, 0x5A, 0x37, 0x7A, 0x2B, 0x4E, 0x6B, 0x7A, 0x31, ++ 0x75, 0x4D, 0x2F, 0x52, 0x73, 0x30, 0x6D, 0x53, 0x4F, 0x39, 0x4D, 0x70, 0x44, 0x70, 0x6B, 0x62, 0x6C, 0x76, 0x64, 0x68, 0x75, 0x44, 0x76, 0x45, 0x4B, 0x37, 0x5A, 0x34, 0x62, 0x4C, 0x51, 0x6A, 0x62, 0x2F, 0x44, 0x39, 0x30, 0x37, 0x4A, 0x65, ++ 0x0A, 0x64, 0x52, 0x2B, 0x5A, 0x6C, 0x61, 0x69, 0x73, 0x39, 0x74, 0x72, 0x68, 0x78, 0x54, 0x46, 0x37, 0x2B, 0x39, 0x46, 0x47, 0x73, 0x39, 0x4B, 0x38, 0x5A, 0x37, 0x52, 0x69, 0x56, 0x4C, 0x6F, 0x4A, 0x39, 0x32, 0x4F, 0x77, 0x6B, 0x36, 0x4B, ++ 0x61, 0x2B, 0x65, 0x6C, 0x53, 0x4C, 0x6F, 0x74, 0x67, 0x45, 0x71, 0x76, 0x38, 0x39, 0x57, 0x42, 0x57, 0x37, 0x78, 0x42, 0x63, 0x69, 0x38, 0x51, 0x61, 0x51, 0x74, 0x79, 0x44, 0x57, 0x32, 0x51, 0x4F, 0x79, 0x37, 0x57, 0x38, 0x0A, 0x31, 0x6B, ++ 0x2F, 0x42, 0x66, 0x44, 0x78, 0x75, 0x6A, 0x52, 0x4E, 0x74, 0x2B, 0x33, 0x76, 0x72, 0x4D, 0x4E, 0x44, 0x63, 0x54, 0x61, 0x2F, 0x46, 0x31, 0x62, 0x61, 0x6C, 0x54, 0x46, 0x74, 0x78, 0x79, 0x65, 0x67, 0x78, 0x76, 0x75, 0x67, 0x34, 0x42, 0x6B, ++ 0x69, 0x68, 0x47, 0x75, 0x4C, 0x71, 0x30, 0x74, 0x34, 0x53, 0x4F, 0x56, 0x67, 0x61, 0x2F, 0x34, 0x41, 0x4F, 0x67, 0x6E, 0x58, 0x6D, 0x74, 0x38, 0x6B, 0x48, 0x62, 0x41, 0x37, 0x76, 0x2F, 0x7A, 0x6A, 0x78, 0x0A, 0x6D, 0x48, 0x48, 0x45, 0x74, ++ 0x33, 0x38, 0x4F, 0x46, 0x64, 0x41, 0x6C, 0x61, 0x62, 0x30, 0x69, 0x6E, 0x53, 0x76, 0x74, 0x42, 0x66, 0x5A, 0x47, 0x52, 0x36, 0x7A, 0x74, 0x77, 0x50, 0x44, 0x55, 0x4F, 0x2B, 0x4C, 0x73, 0x37, 0x70, 0x5A, 0x62, 0x6B, 0x42, 0x4E, 0x4F, 0x48, ++ 0x6C, 0x59, 0x36, 0x36, 0x37, 0x44, 0x76, 0x6C, 0x72, 0x75, 0x57, 0x49, 0x78, 0x47, 0x36, 0x38, 0x6B, 0x4F, 0x47, 0x64, 0x47, 0x53, 0x56, 0x79, 0x43, 0x68, 0x31, 0x33, 0x78, 0x30, 0x31, 0x0A, 0x75, 0x74, 0x49, 0x33, 0x67, 0x7A, 0x68, 0x54, ++ 0x4F, 0x44, 0x59, 0x37, 0x7A, 0x32, 0x7A, 0x70, 0x2B, 0x57, 0x73, 0x4F, 0x30, 0x50, 0x73, 0x45, 0x36, 0x45, 0x39, 0x33, 0x31, 0x32, 0x55, 0x42, 0x65, 0x49, 0x59, 0x4D, 0x65, 0x6A, 0x34, 0x68, 0x59, 0x76, 0x46, 0x2F, 0x59, 0x33, 0x45, 0x4D, ++ 0x79, 0x5A, 0x39, 0x45, 0x32, 0x36, 0x67, 0x6E, 0x6F, 0x6E, 0x57, 0x2B, 0x62, 0x6F, 0x45, 0x2B, 0x31, 0x38, 0x44, 0x72, 0x47, 0x35, 0x67, 0x50, 0x63, 0x46, 0x77, 0x30, 0x0A, 0x73, 0x6F, 0x72, 0x4D, 0x77, 0x49, 0x55, 0x59, 0x36, 0x32, 0x35, ++ 0x36, 0x73, 0x2F, 0x64, 0x61, 0x6F, 0x51, 0x65, 0x2F, 0x71, 0x55, 0x4B, 0x53, 0x38, 0x32, 0x41, 0x69, 0x6C, 0x2B, 0x51, 0x55, 0x6F, 0x51, 0x65, 0x62, 0x54, 0x6E, 0x62, 0x41, 0x6A, 0x6E, 0x33, 0x39, 0x70, 0x43, 0x58, 0x48, 0x52, 0x2B, 0x33, ++ 0x2F, 0x48, 0x33, 0x4F, 0x73, 0x7A, 0x4D, 0x4F, 0x6C, 0x36, 0x57, 0x38, 0x4B, 0x6A, 0x70, 0x74, 0x6C, 0x77, 0x6C, 0x43, 0x46, 0x74, 0x61, 0x4F, 0x67, 0x0A, 0x55, 0x78, 0x4C, 0x4D, 0x56, 0x59, 0x64, 0x68, 0x38, 0x34, 0x47, 0x75, 0x45, 0x45, ++ 0x5A, 0x68, 0x76, 0x55, 0x51, 0x68, 0x75, 0x4D, 0x49, 0x39, 0x64, 0x4D, 0x39, 0x2B, 0x4A, 0x44, 0x58, 0x36, 0x48, 0x41, 0x63, 0x4F, 0x6D, 0x7A, 0x30, 0x69, 0x79, 0x75, 0x38, 0x78, 0x4C, 0x34, 0x79, 0x73, 0x45, 0x72, 0x33, 0x76, 0x51, 0x43, ++ 0x6A, 0x38, 0x4B, 0x57, 0x65, 0x66, 0x73, 0x68, 0x4E, 0x50, 0x5A, 0x69, 0x54, 0x45, 0x55, 0x78, 0x6E, 0x70, 0x48, 0x69, 0x6B, 0x56, 0x0A, 0x37, 0x2B, 0x5A, 0x74, 0x73, 0x48, 0x38, 0x74, 0x5A, 0x2F, 0x33, 0x7A, 0x62, 0x42, 0x74, 0x31, 0x52, ++ 0x71, 0x50, 0x6C, 0x53, 0x68, 0x66, 0x70, 0x70, 0x4E, 0x63, 0x4C, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x41, ++ 0x43, 0x43, 0x56, 0x52, 0x41, 0x49, 0x5A, 0x31, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, ++ 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x48, 0x30, 0x7A, 0x43, 0x43, 0x42, 0x62, 0x75, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x49, 0x58, 0x73, 0x4F, 0x33, 0x70, 0x6B, 0x4E, 0x2F, 0x70, 0x4F, 0x41, 0x77, 0x44, ++ 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x46, 0x42, 0x51, 0x41, 0x77, 0x51, 0x6A, 0x45, 0x53, 0x4D, 0x42, 0x41, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x77, 0x77, 0x4A, 0x51, 0x55, 0x4E, 0x44, 0x56, ++ 0x6C, 0x4A, 0x42, 0x0A, 0x53, 0x56, 0x6F, 0x78, 0x4D, 0x52, 0x41, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4C, 0x44, 0x41, 0x64, 0x51, 0x53, 0x30, 0x6C, 0x42, 0x51, 0x30, 0x4E, 0x57, 0x4D, 0x51, 0x30, 0x77, 0x43, 0x77, 0x59, 0x44, ++ 0x56, 0x51, 0x51, 0x4B, 0x44, 0x41, 0x52, 0x42, 0x51, 0x30, 0x4E, 0x57, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x46, 0x55, 0x7A, 0x41, 0x65, 0x46, 0x77, 0x30, 0x78, 0x4D, 0x54, 0x41, 0x31, ++ 0x0A, 0x4D, 0x44, 0x55, 0x77, 0x4F, 0x54, 0x4D, 0x33, 0x4D, 0x7A, 0x64, 0x61, 0x46, 0x77, 0x30, 0x7A, 0x4D, 0x44, 0x45, 0x79, 0x4D, 0x7A, 0x45, 0x77, 0x4F, 0x54, 0x4D, 0x33, 0x4D, 0x7A, 0x64, 0x61, 0x4D, 0x45, 0x49, 0x78, 0x45, 0x6A, 0x41, ++ 0x51, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x4D, 0x43, 0x55, 0x46, 0x44, 0x51, 0x31, 0x5A, 0x53, 0x51, 0x55, 0x6C, 0x61, 0x4D, 0x54, 0x45, 0x51, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x77, 0x77, 0x48, 0x0A, 0x55, 0x45, ++ 0x74, 0x4A, 0x51, 0x55, 0x4E, 0x44, 0x56, 0x6A, 0x45, 0x4E, 0x4D, 0x41, 0x73, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, 0x45, 0x51, 0x55, 0x4E, 0x44, 0x56, 0x6A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, ++ 0x4D, 0x43, 0x52, 0x56, 0x4D, 0x77, 0x67, 0x67, 0x49, 0x69, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x0A, 0x44, 0x77, 0x41, 0x77, 0x67, ++ 0x67, 0x49, 0x4B, 0x41, 0x6F, 0x49, 0x43, 0x41, 0x51, 0x43, 0x62, 0x71, 0x61, 0x75, 0x2F, 0x59, 0x55, 0x71, 0x58, 0x72, 0x79, 0x2B, 0x58, 0x5A, 0x70, 0x70, 0x30, 0x58, 0x39, 0x44, 0x5A, 0x6C, 0x76, 0x33, 0x50, 0x34, 0x75, 0x52, 0x6D, 0x37, ++ 0x78, 0x38, 0x66, 0x52, 0x7A, 0x50, 0x43, 0x52, 0x4B, 0x50, 0x66, 0x6D, 0x74, 0x34, 0x66, 0x74, 0x56, 0x54, 0x64, 0x46, 0x58, 0x78, 0x70, 0x4E, 0x52, 0x46, 0x76, 0x75, 0x38, 0x67, 0x4D, 0x0A, 0x6A, 0x6D, 0x6F, 0x59, 0x48, 0x74, 0x69, 0x50, ++ 0x32, 0x52, 0x61, 0x38, 0x45, 0x45, 0x67, 0x32, 0x58, 0x50, 0x42, 0x6A, 0x73, 0x35, 0x42, 0x61, 0x58, 0x43, 0x51, 0x33, 0x31, 0x36, 0x50, 0x57, 0x79, 0x77, 0x6C, 0x78, 0x75, 0x66, 0x45, 0x42, 0x63, 0x6F, 0x53, 0x77, 0x66, 0x64, 0x74, 0x4E, ++ 0x67, 0x4D, 0x33, 0x38, 0x30, 0x32, 0x2F, 0x4A, 0x2B, 0x4E, 0x71, 0x32, 0x44, 0x6F, 0x4C, 0x53, 0x52, 0x59, 0x57, 0x6F, 0x47, 0x32, 0x69, 0x6F, 0x50, 0x65, 0x6A, 0x30, 0x0A, 0x52, 0x47, 0x79, 0x39, 0x6F, 0x63, 0x4C, 0x4C, 0x41, 0x37, 0x36, ++ 0x4D, 0x50, 0x68, 0x4D, 0x41, 0x68, 0x4E, 0x39, 0x4B, 0x53, 0x4D, 0x44, 0x6A, 0x49, 0x67, 0x72, 0x6F, 0x36, 0x54, 0x65, 0x6E, 0x47, 0x45, 0x79, 0x78, 0x43, 0x51, 0x30, 0x6A, 0x56, 0x6E, 0x38, 0x45, 0x54, 0x64, 0x6B, 0x58, 0x68, 0x42, 0x69, ++ 0x6C, 0x79, 0x4E, 0x70, 0x41, 0x6C, 0x48, 0x50, 0x72, 0x7A, 0x67, 0x35, 0x58, 0x50, 0x41, 0x4F, 0x42, 0x4F, 0x70, 0x30, 0x4B, 0x6F, 0x56, 0x64, 0x44, 0x0A, 0x61, 0x61, 0x78, 0x58, 0x62, 0x58, 0x6D, 0x51, 0x65, 0x4F, 0x57, 0x31, 0x74, 0x44, ++ 0x76, 0x59, 0x76, 0x45, 0x79, 0x4E, 0x4B, 0x4B, 0x47, 0x6E, 0x6F, 0x36, 0x65, 0x36, 0x41, 0x6B, 0x34, 0x6C, 0x30, 0x53, 0x71, 0x75, 0x37, 0x61, 0x34, 0x44, 0x49, 0x72, 0x68, 0x72, 0x49, 0x41, 0x38, 0x77, 0x4B, 0x46, 0x53, 0x56, 0x66, 0x2B, ++ 0x44, 0x75, 0x7A, 0x67, 0x70, 0x6D, 0x6E, 0x64, 0x46, 0x41, 0x4C, 0x57, 0x34, 0x69, 0x72, 0x35, 0x30, 0x61, 0x77, 0x51, 0x55, 0x5A, 0x0A, 0x30, 0x6D, 0x2F, 0x41, 0x38, 0x70, 0x2F, 0x34, 0x65, 0x37, 0x4D, 0x43, 0x51, 0x76, 0x74, 0x51, 0x71, ++ 0x52, 0x30, 0x74, 0x6B, 0x77, 0x38, 0x6A, 0x71, 0x38, 0x62, 0x42, 0x44, 0x35, 0x4C, 0x2F, 0x30, 0x4B, 0x49, 0x56, 0x39, 0x56, 0x4D, 0x4A, 0x63, 0x52, 0x7A, 0x2F, 0x52, 0x52, 0x4F, 0x45, 0x35, 0x69, 0x5A, 0x65, 0x2B, 0x4F, 0x43, 0x49, 0x48, ++ 0x41, 0x72, 0x38, 0x46, 0x72, 0x61, 0x6F, 0x63, 0x77, 0x61, 0x34, 0x38, 0x47, 0x4F, 0x45, 0x41, 0x71, 0x44, 0x47, 0x0A, 0x57, 0x75, 0x7A, 0x6E, 0x64, 0x4E, 0x39, 0x77, 0x72, 0x71, 0x4F, 0x44, 0x4A, 0x65, 0x72, 0x57, 0x78, 0x35, 0x65, 0x48, ++ 0x6B, 0x36, 0x66, 0x47, 0x69, 0x6F, 0x6F, 0x7A, 0x6C, 0x32, 0x41, 0x33, 0x45, 0x44, 0x36, 0x58, 0x50, 0x6D, 0x34, 0x70, 0x46, 0x64, 0x61, 0x68, 0x44, 0x39, 0x47, 0x49, 0x4C, 0x42, 0x4B, 0x66, 0x62, 0x36, 0x71, 0x6B, 0x78, 0x6B, 0x4C, 0x72, ++ 0x51, 0x61, 0x4C, 0x6A, 0x6C, 0x55, 0x50, 0x54, 0x41, 0x59, 0x56, 0x74, 0x6A, 0x72, 0x73, 0x37, 0x0A, 0x38, 0x79, 0x4D, 0x32, 0x78, 0x2F, 0x34, 0x37, 0x34, 0x4B, 0x45, 0x6C, 0x42, 0x30, 0x69, 0x72, 0x79, 0x59, 0x6C, 0x30, 0x2F, 0x77, 0x69, ++ 0x50, 0x67, 0x4C, 0x2F, 0x41, 0x6C, 0x6D, 0x58, 0x7A, 0x37, 0x75, 0x78, 0x4C, 0x61, 0x4C, 0x32, 0x64, 0x69, 0x4D, 0x4D, 0x78, 0x73, 0x30, 0x44, 0x78, 0x36, 0x4D, 0x2F, 0x32, 0x4F, 0x4C, 0x75, 0x63, 0x35, 0x4E, 0x46, 0x2F, 0x31, 0x4F, 0x56, ++ 0x59, 0x6D, 0x33, 0x7A, 0x36, 0x31, 0x50, 0x4D, 0x4F, 0x6D, 0x33, 0x57, 0x52, 0x0A, 0x35, 0x4C, 0x70, 0x53, 0x4C, 0x68, 0x6C, 0x2B, 0x30, 0x66, 0x58, 0x4E, 0x57, 0x68, 0x6E, 0x38, 0x75, 0x67, 0x62, 0x32, 0x2B, 0x31, 0x4B, 0x6F, 0x53, 0x35, ++ 0x6B, 0x45, 0x33, 0x66, 0x6A, 0x35, 0x74, 0x49, 0x74, 0x51, 0x6F, 0x30, 0x35, 0x69, 0x69, 0x66, 0x43, 0x48, 0x4A, 0x50, 0x71, 0x44, 0x51, 0x73, 0x47, 0x48, 0x2B, 0x74, 0x55, 0x74, 0x4B, 0x53, 0x70, 0x61, 0x63, 0x58, 0x70, 0x6B, 0x61, 0x74, ++ 0x63, 0x6E, 0x59, 0x47, 0x4D, 0x4E, 0x32, 0x38, 0x35, 0x4A, 0x0A, 0x39, 0x59, 0x30, 0x66, 0x6B, 0x49, 0x6B, 0x79, 0x46, 0x2F, 0x68, 0x7A, 0x51, 0x37, 0x6A, 0x53, 0x57, 0x70, 0x4F, 0x47, 0x59, 0x64, 0x62, 0x68, 0x64, 0x51, 0x72, 0x71, 0x65, ++ 0x57, 0x5A, 0x32, 0x69, 0x45, 0x39, 0x78, 0x36, 0x77, 0x51, 0x6C, 0x31, 0x67, 0x70, 0x61, 0x65, 0x70, 0x50, 0x6C, 0x75, 0x55, 0x73, 0x58, 0x51, 0x41, 0x2B, 0x78, 0x74, 0x72, 0x6E, 0x31, 0x33, 0x6B, 0x2F, 0x63, 0x34, 0x4C, 0x4F, 0x73, 0x4F, ++ 0x78, 0x46, 0x77, 0x59, 0x49, 0x52, 0x4B, 0x0A, 0x51, 0x32, 0x36, 0x5A, 0x49, 0x4D, 0x41, 0x70, 0x63, 0x51, 0x72, 0x41, 0x5A, 0x51, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x6F, 0x34, 0x49, 0x43, 0x79, 0x7A, 0x43, 0x43, 0x41, 0x73, 0x63, 0x77, ++ 0x66, 0x51, 0x59, 0x49, 0x4B, 0x77, 0x59, 0x42, 0x42, 0x51, 0x55, 0x48, 0x41, 0x51, 0x45, 0x45, 0x63, 0x54, 0x42, 0x76, 0x4D, 0x45, 0x77, 0x47, 0x43, 0x43, 0x73, 0x47, 0x41, 0x51, 0x55, 0x46, 0x42, 0x7A, 0x41, 0x43, 0x68, 0x6B, 0x42, 0x6F, ++ 0x64, 0x48, 0x52, 0x77, 0x0A, 0x4F, 0x69, 0x38, 0x76, 0x64, 0x33, 0x64, 0x33, 0x4C, 0x6D, 0x46, 0x6A, 0x59, 0x33, 0x59, 0x75, 0x5A, 0x58, 0x4D, 0x76, 0x5A, 0x6D, 0x6C, 0x73, 0x5A, 0x57, 0x46, 0x6B, 0x62, 0x57, 0x6C, 0x75, 0x4C, 0x30, 0x46, ++ 0x79, 0x59, 0x32, 0x68, 0x70, 0x64, 0x6D, 0x39, 0x7A, 0x4C, 0x32, 0x4E, 0x6C, 0x63, 0x6E, 0x52, 0x70, 0x5A, 0x6D, 0x6C, 0x6A, 0x59, 0x57, 0x52, 0x76, 0x63, 0x79, 0x39, 0x79, 0x59, 0x57, 0x6C, 0x36, 0x59, 0x57, 0x4E, 0x6A, 0x64, 0x6A, 0x45, ++ 0x75, 0x0A, 0x59, 0x33, 0x4A, 0x30, 0x4D, 0x42, 0x38, 0x47, 0x43, 0x43, 0x73, 0x47, 0x41, 0x51, 0x55, 0x46, 0x42, 0x7A, 0x41, 0x42, 0x68, 0x68, 0x4E, 0x6F, 0x64, 0x48, 0x52, 0x77, 0x4F, 0x69, 0x38, 0x76, 0x62, 0x32, 0x4E, 0x7A, 0x63, 0x43, ++ 0x35, 0x68, 0x59, 0x32, 0x4E, 0x32, 0x4C, 0x6D, 0x56, 0x7A, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x54, 0x53, 0x68, 0x37, 0x54, 0x6A, 0x33, 0x7A, 0x63, 0x6E, 0x6B, 0x31, 0x58, 0x32, 0x0A, 0x56, ++ 0x75, 0x71, 0x42, 0x35, 0x54, 0x62, 0x4D, 0x6A, 0x42, 0x34, 0x2F, 0x76, 0x54, 0x41, 0x50, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x52, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x54, 0x41, 0x44, 0x41, 0x51, 0x48, 0x2F, 0x4D, 0x42, 0x38, 0x47, 0x41, ++ 0x31, 0x55, 0x64, 0x49, 0x77, 0x51, 0x59, 0x4D, 0x42, 0x61, 0x41, 0x46, 0x4E, 0x4B, 0x48, 0x74, 0x4F, 0x50, 0x66, 0x4E, 0x79, 0x65, 0x54, 0x56, 0x66, 0x5A, 0x57, 0x36, 0x6F, 0x48, 0x6C, 0x4E, 0x73, 0x79, 0x4D, 0x0A, 0x48, 0x6A, 0x2B, 0x39, ++ 0x4D, 0x49, 0x49, 0x42, 0x63, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x67, 0x42, 0x49, 0x49, 0x42, 0x61, 0x6A, 0x43, 0x43, 0x41, 0x57, 0x59, 0x77, 0x67, 0x67, 0x46, 0x69, 0x42, 0x67, 0x52, 0x56, 0x48, 0x53, 0x41, 0x41, 0x4D, 0x49, 0x49, 0x42, ++ 0x57, 0x44, 0x43, 0x43, 0x41, 0x53, 0x49, 0x47, 0x43, 0x43, 0x73, 0x47, 0x41, 0x51, 0x55, 0x46, 0x42, 0x77, 0x49, 0x43, 0x4D, 0x49, 0x49, 0x42, 0x46, 0x42, 0x36, 0x43, 0x41, 0x52, 0x41, 0x41, 0x0A, 0x51, 0x51, 0x42, 0x31, 0x41, 0x48, 0x51, ++ 0x41, 0x62, 0x77, 0x42, 0x79, 0x41, 0x47, 0x6B, 0x41, 0x5A, 0x41, 0x42, 0x68, 0x41, 0x47, 0x51, 0x41, 0x49, 0x41, 0x42, 0x6B, 0x41, 0x47, 0x55, 0x41, 0x49, 0x41, 0x42, 0x44, 0x41, 0x47, 0x55, 0x41, 0x63, 0x67, 0x42, 0x30, 0x41, 0x47, 0x6B, ++ 0x41, 0x5A, 0x67, 0x42, 0x70, 0x41, 0x47, 0x4D, 0x41, 0x59, 0x51, 0x42, 0x6A, 0x41, 0x47, 0x6B, 0x41, 0x38, 0x77, 0x42, 0x75, 0x41, 0x43, 0x41, 0x41, 0x55, 0x67, 0x42, 0x68, 0x0A, 0x41, 0x4F, 0x30, 0x41, 0x65, 0x67, 0x41, 0x67, 0x41, 0x47, ++ 0x51, 0x41, 0x5A, 0x51, 0x41, 0x67, 0x41, 0x47, 0x77, 0x41, 0x59, 0x51, 0x41, 0x67, 0x41, 0x45, 0x45, 0x41, 0x51, 0x77, 0x42, 0x44, 0x41, 0x46, 0x59, 0x41, 0x49, 0x41, 0x41, 0x6F, 0x41, 0x45, 0x45, 0x41, 0x5A, 0x77, 0x42, 0x6C, 0x41, 0x47, ++ 0x34, 0x41, 0x59, 0x77, 0x42, 0x70, 0x41, 0x47, 0x45, 0x41, 0x49, 0x41, 0x42, 0x6B, 0x41, 0x47, 0x55, 0x41, 0x49, 0x41, 0x42, 0x55, 0x41, 0x47, 0x55, 0x41, 0x0A, 0x59, 0x77, 0x42, 0x75, 0x41, 0x47, 0x38, 0x41, 0x62, 0x41, 0x42, 0x76, 0x41, ++ 0x47, 0x63, 0x41, 0x37, 0x51, 0x42, 0x68, 0x41, 0x43, 0x41, 0x41, 0x65, 0x51, 0x41, 0x67, 0x41, 0x45, 0x4D, 0x41, 0x5A, 0x51, 0x42, 0x79, 0x41, 0x48, 0x51, 0x41, 0x61, 0x51, 0x42, 0x6D, 0x41, 0x47, 0x6B, 0x41, 0x59, 0x77, 0x42, 0x68, 0x41, ++ 0x47, 0x4D, 0x41, 0x61, 0x51, 0x44, 0x7A, 0x41, 0x47, 0x34, 0x41, 0x49, 0x41, 0x42, 0x46, 0x41, 0x47, 0x77, 0x41, 0x5A, 0x51, 0x42, 0x6A, 0x0A, 0x41, 0x48, 0x51, 0x41, 0x63, 0x67, 0x44, 0x7A, 0x41, 0x47, 0x34, 0x41, 0x61, 0x51, 0x42, 0x6A, ++ 0x41, 0x47, 0x45, 0x41, 0x4C, 0x41, 0x41, 0x67, 0x41, 0x45, 0x4D, 0x41, 0x53, 0x51, 0x42, 0x47, 0x41, 0x43, 0x41, 0x41, 0x55, 0x51, 0x41, 0x30, 0x41, 0x44, 0x59, 0x41, 0x4D, 0x41, 0x41, 0x78, 0x41, 0x44, 0x45, 0x41, 0x4E, 0x51, 0x41, 0x32, ++ 0x41, 0x45, 0x55, 0x41, 0x4B, 0x51, 0x41, 0x75, 0x41, 0x43, 0x41, 0x41, 0x51, 0x77, 0x42, 0x51, 0x41, 0x46, 0x4D, 0x41, 0x0A, 0x49, 0x41, 0x42, 0x6C, 0x41, 0x47, 0x34, 0x41, 0x49, 0x41, 0x42, 0x6F, 0x41, 0x48, 0x51, 0x41, 0x64, 0x41, 0x42, ++ 0x77, 0x41, 0x44, 0x6F, 0x41, 0x4C, 0x77, 0x41, 0x76, 0x41, 0x48, 0x63, 0x41, 0x64, 0x77, 0x42, 0x33, 0x41, 0x43, 0x34, 0x41, 0x59, 0x51, 0x42, 0x6A, 0x41, 0x47, 0x4D, 0x41, 0x64, 0x67, 0x41, 0x75, 0x41, 0x47, 0x55, 0x41, 0x63, 0x7A, 0x41, ++ 0x77, 0x42, 0x67, 0x67, 0x72, 0x42, 0x67, 0x45, 0x46, 0x42, 0x51, 0x63, 0x43, 0x41, 0x52, 0x59, 0x6B, 0x0A, 0x61, 0x48, 0x52, 0x30, 0x63, 0x44, 0x6F, 0x76, 0x4C, 0x33, 0x64, 0x33, 0x64, 0x79, 0x35, 0x68, 0x59, 0x32, 0x4E, 0x32, 0x4C, 0x6D, ++ 0x56, 0x7A, 0x4C, 0x32, 0x78, 0x6C, 0x5A, 0x32, 0x6C, 0x7A, 0x62, 0x47, 0x46, 0x6A, 0x61, 0x57, 0x39, 0x75, 0x58, 0x32, 0x4D, 0x75, 0x61, 0x48, 0x52, 0x74, 0x4D, 0x46, 0x55, 0x47, 0x41, 0x31, 0x55, 0x64, 0x48, 0x77, 0x52, 0x4F, 0x4D, 0x45, ++ 0x77, 0x77, 0x53, 0x71, 0x42, 0x49, 0x6F, 0x45, 0x61, 0x47, 0x52, 0x47, 0x68, 0x30, 0x0A, 0x64, 0x48, 0x41, 0x36, 0x4C, 0x79, 0x39, 0x33, 0x64, 0x33, 0x63, 0x75, 0x59, 0x57, 0x4E, 0x6A, 0x64, 0x69, 0x35, 0x6C, 0x63, 0x79, 0x39, 0x6D, 0x61, ++ 0x57, 0x78, 0x6C, 0x59, 0x57, 0x52, 0x74, 0x61, 0x57, 0x34, 0x76, 0x51, 0x58, 0x4A, 0x6A, 0x61, 0x47, 0x6C, 0x32, 0x62, 0x33, 0x4D, 0x76, 0x59, 0x32, 0x56, 0x79, 0x64, 0x47, 0x6C, 0x6D, 0x61, 0x57, 0x4E, 0x68, 0x5A, 0x47, 0x39, 0x7A, 0x4C, ++ 0x33, 0x4A, 0x68, 0x61, 0x58, 0x70, 0x68, 0x59, 0x32, 0x4E, 0x32, 0x0A, 0x4D, 0x56, 0x39, 0x6B, 0x5A, 0x58, 0x49, 0x75, 0x59, 0x33, 0x4A, 0x73, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, ++ 0x41, 0x77, 0x49, 0x42, 0x42, 0x6A, 0x41, 0x58, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x52, 0x45, 0x45, 0x45, 0x44, 0x41, 0x4F, 0x67, 0x51, 0x78, 0x68, 0x59, 0x32, 0x4E, 0x32, 0x51, 0x47, 0x46, 0x6A, 0x59, 0x33, 0x59, 0x75, 0x5A, 0x58, 0x4D, 0x77, ++ 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x0A, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x46, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x42, 0x41, 0x4A, 0x63, 0x78, 0x41, 0x70, 0x2F, 0x6E, 0x2F, 0x55, 0x4E, 0x6E, 0x53, 0x45, 0x51, ++ 0x55, 0x35, 0x43, 0x6D, 0x48, 0x37, 0x55, 0x77, 0x6F, 0x5A, 0x74, 0x43, 0x50, 0x4E, 0x64, 0x70, 0x4E, 0x59, 0x62, 0x64, 0x4B, 0x6C, 0x30, 0x32, 0x31, 0x32, 0x35, 0x44, 0x67, 0x42, 0x53, 0x34, 0x4F, 0x78, 0x6E, 0x6E, 0x51, 0x38, 0x70, 0x64, ++ 0x70, 0x44, 0x37, 0x30, 0x45, 0x0A, 0x52, 0x39, 0x6D, 0x2B, 0x32, 0x37, 0x55, 0x70, 0x32, 0x70, 0x76, 0x5A, 0x72, 0x71, 0x6D, 0x5A, 0x31, 0x64, 0x4D, 0x38, 0x4D, 0x4A, 0x50, 0x31, 0x6A, 0x61, 0x47, 0x6F, 0x2F, 0x41, 0x61, 0x4E, 0x52, 0x50, ++ 0x54, 0x4B, 0x46, 0x70, 0x56, 0x38, 0x4D, 0x39, 0x78, 0x69, 0x69, 0x36, 0x67, 0x33, 0x2B, 0x43, 0x66, 0x59, 0x43, 0x53, 0x30, 0x62, 0x37, 0x38, 0x67, 0x55, 0x4A, 0x79, 0x43, 0x70, 0x5A, 0x45, 0x54, 0x2F, 0x4C, 0x74, 0x5A, 0x31, 0x71, 0x6D, ++ 0x78, 0x4E, 0x0A, 0x59, 0x45, 0x41, 0x5A, 0x53, 0x55, 0x4E, 0x55, 0x59, 0x39, 0x72, 0x69, 0x7A, 0x4C, 0x70, 0x6D, 0x35, 0x55, 0x39, 0x45, 0x65, 0x6C, 0x76, 0x5A, 0x61, 0x6F, 0x45, 0x72, 0x51, 0x4E, 0x56, 0x2F, 0x2B, 0x51, 0x45, 0x6E, 0x57, ++ 0x43, 0x7A, 0x49, 0x37, 0x55, 0x69, 0x52, 0x66, 0x44, 0x2B, 0x6D, 0x41, 0x4D, 0x2F, 0x45, 0x4B, 0x58, 0x4D, 0x52, 0x4E, 0x74, 0x36, 0x47, 0x47, 0x54, 0x36, 0x64, 0x37, 0x68, 0x6D, 0x4B, 0x47, 0x39, 0x57, 0x77, 0x37, 0x59, 0x34, 0x39, 0x0A, ++ 0x6E, 0x43, 0x72, 0x41, 0x44, 0x64, 0x67, 0x39, 0x5A, 0x75, 0x4D, 0x38, 0x44, 0x62, 0x33, 0x56, 0x6C, 0x46, 0x7A, 0x69, 0x34, 0x71, 0x63, 0x31, 0x47, 0x77, 0x51, 0x41, 0x39, 0x6A, 0x39, 0x61, 0x6A, 0x65, 0x70, 0x44, 0x76, 0x56, 0x2B, 0x4A, ++ 0x48, 0x61, 0x6E, 0x42, 0x73, 0x4D, 0x79, 0x5A, 0x34, 0x6B, 0x30, 0x41, 0x43, 0x74, 0x72, 0x4A, 0x4A, 0x31, 0x76, 0x6E, 0x45, 0x35, 0x42, 0x63, 0x35, 0x50, 0x55, 0x7A, 0x6F, 0x6C, 0x56, 0x74, 0x33, 0x4F, 0x41, 0x4A, 0x0A, 0x54, 0x53, 0x2B, ++ 0x78, 0x4A, 0x6C, 0x73, 0x6E, 0x64, 0x51, 0x41, 0x4A, 0x78, 0x47, 0x4A, 0x33, 0x4B, 0x51, 0x68, 0x66, 0x6E, 0x6C, 0x6D, 0x73, 0x74, 0x6E, 0x36, 0x74, 0x6E, 0x31, 0x51, 0x77, 0x49, 0x67, 0x50, 0x42, 0x48, 0x6E, 0x46, 0x6B, 0x2F, 0x76, 0x6B, ++ 0x34, 0x43, 0x70, 0x59, 0x59, 0x33, 0x51, 0x49, 0x55, 0x72, 0x43, 0x50, 0x4C, 0x42, 0x68, 0x77, 0x65, 0x70, 0x48, 0x32, 0x4E, 0x44, 0x64, 0x34, 0x6E, 0x51, 0x65, 0x69, 0x74, 0x32, 0x68, 0x57, 0x33, 0x0A, 0x73, 0x43, 0x50, 0x64, 0x4B, 0x36, ++ 0x6A, 0x54, 0x32, 0x69, 0x57, 0x48, 0x37, 0x65, 0x68, 0x56, 0x52, 0x45, 0x32, 0x49, 0x39, 0x44, 0x5A, 0x2B, 0x68, 0x4A, 0x70, 0x34, 0x72, 0x50, 0x63, 0x4F, 0x56, 0x6B, 0x6B, 0x4F, 0x31, 0x6A, 0x4D, 0x6C, 0x31, 0x6F, 0x52, 0x51, 0x51, 0x6D, ++ 0x77, 0x67, 0x45, 0x68, 0x30, 0x71, 0x31, 0x62, 0x36, 0x38, 0x38, 0x6E, 0x43, 0x42, 0x70, 0x48, 0x42, 0x67, 0x76, 0x67, 0x57, 0x31, 0x6D, 0x35, 0x34, 0x45, 0x52, 0x4C, 0x35, 0x68, 0x0A, 0x49, 0x36, 0x7A, 0x70, 0x70, 0x53, 0x53, 0x4D, 0x45, ++ 0x59, 0x43, 0x55, 0x57, 0x71, 0x4B, 0x69, 0x75, 0x55, 0x6E, 0x53, 0x77, 0x64, 0x7A, 0x52, 0x70, 0x2B, 0x30, 0x78, 0x45, 0x53, 0x79, 0x65, 0x47, 0x61, 0x62, 0x75, 0x34, 0x56, 0x58, 0x68, 0x77, 0x4F, 0x72, 0x50, 0x44, 0x59, 0x54, 0x6B, 0x46, ++ 0x37, 0x65, 0x69, 0x66, 0x4B, 0x58, 0x65, 0x56, 0x53, 0x55, 0x47, 0x37, 0x73, 0x7A, 0x41, 0x68, 0x31, 0x78, 0x41, 0x32, 0x73, 0x79, 0x56, 0x50, 0x31, 0x58, 0x67, 0x0A, 0x4E, 0x63, 0x65, 0x34, 0x68, 0x4C, 0x36, 0x30, 0x58, 0x63, 0x31, 0x36, ++ 0x67, 0x77, 0x46, 0x79, 0x37, 0x6F, 0x66, 0x6D, 0x58, 0x78, 0x32, 0x75, 0x74, 0x59, 0x58, 0x47, 0x4A, 0x74, 0x2F, 0x6D, 0x77, 0x5A, 0x72, 0x70, 0x48, 0x67, 0x4A, 0x48, 0x6E, 0x79, 0x71, 0x6F, 0x62, 0x61, 0x6C, 0x62, 0x7A, 0x2B, 0x78, 0x46, ++ 0x64, 0x33, 0x2B, 0x59, 0x4A, 0x35, 0x6F, 0x79, 0x58, 0x53, 0x72, 0x6A, 0x68, 0x4F, 0x37, 0x46, 0x6D, 0x47, 0x59, 0x76, 0x6C, 0x69, 0x41, 0x64, 0x0A, 0x33, 0x64, 0x6A, 0x44, 0x4A, 0x39, 0x65, 0x77, 0x2B, 0x66, 0x37, 0x5A, 0x66, 0x63, 0x33, ++ 0x51, 0x6E, 0x34, 0x38, 0x4C, 0x46, 0x46, 0x68, 0x52, 0x6E, 0x79, 0x2B, 0x4C, 0x77, 0x7A, 0x67, 0x74, 0x33, 0x75, 0x69, 0x50, 0x31, 0x6F, 0x32, 0x48, 0x70, 0x50, 0x56, 0x57, 0x51, 0x78, 0x61, 0x5A, 0x4C, 0x50, 0x53, 0x6B, 0x56, 0x72, 0x51, ++ 0x30, 0x75, 0x47, 0x45, 0x33, 0x79, 0x63, 0x4A, 0x59, 0x67, 0x42, 0x75, 0x67, 0x6C, 0x36, 0x48, 0x38, 0x57, 0x59, 0x33, 0x70, 0x0A, 0x45, 0x66, 0x62, 0x52, 0x44, 0x30, 0x74, 0x56, 0x4E, 0x45, 0x59, 0x71, 0x69, 0x34, 0x59, 0x37, 0x0A, 0x2D, ++ 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x54, 0x57, 0x43, 0x41, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, ++ 0x6F, 0x74, 0x20, 0x43, 0x41, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, ++ 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x51, 0x54, 0x43, 0x43, 0x41, 0x79, 0x6D, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x43, 0x44, 0x4C, 0x34, 0x77, 0x44, 0x51, ++ 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x42, 0x51, 0x41, 0x77, 0x55, 0x54, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x56, 0x46, 0x63, 0x78, 0x45, 0x6A, ++ 0x41, 0x51, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x0A, 0x43, 0x56, 0x52, 0x42, 0x53, 0x56, 0x64, 0x42, 0x54, 0x69, 0x31, 0x44, 0x51, 0x54, 0x45, 0x51, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x78, 0x4D, 0x48, 0x55, ++ 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x51, 0x54, 0x45, 0x63, 0x4D, 0x42, 0x6F, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x54, 0x56, 0x46, 0x64, 0x44, 0x51, 0x53, 0x42, 0x48, 0x62, 0x47, 0x39, 0x69, 0x59, 0x57, 0x77, 0x67, 0x55, ++ 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x0A, 0x51, 0x54, 0x41, 0x65, 0x46, 0x77, 0x30, 0x78, 0x4D, 0x6A, 0x41, 0x32, 0x4D, 0x6A, 0x63, 0x77, 0x4E, 0x6A, 0x49, 0x34, 0x4D, 0x7A, 0x4E, 0x61, 0x46, 0x77, 0x30, 0x7A, 0x4D, 0x44, 0x45, 0x79, ++ 0x4D, 0x7A, 0x45, 0x78, 0x4E, 0x54, 0x55, 0x35, 0x4E, 0x54, 0x6C, 0x61, 0x4D, 0x46, 0x45, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6C, 0x52, 0x58, 0x4D, 0x52, 0x49, 0x77, 0x45, 0x41, 0x59, 0x44, ++ 0x56, 0x51, 0x51, 0x4B, 0x0A, 0x45, 0x77, 0x6C, 0x55, 0x51, 0x55, 0x6C, 0x58, 0x51, 0x55, 0x34, 0x74, 0x51, 0x30, 0x45, 0x78, 0x45, 0x44, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x73, 0x54, 0x42, 0x31, 0x4A, 0x76, 0x62, 0x33, 0x51, ++ 0x67, 0x51, 0x30, 0x45, 0x78, 0x48, 0x44, 0x41, 0x61, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x45, 0x31, 0x52, 0x58, 0x51, 0x30, 0x45, 0x67, 0x52, 0x32, 0x78, 0x76, 0x59, 0x6D, 0x46, 0x73, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, ++ 0x67, 0x0A, 0x51, 0x30, 0x45, 0x77, 0x67, 0x67, 0x49, 0x69, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, ++ 0x49, 0x4B, 0x41, 0x6F, 0x49, 0x43, 0x41, 0x51, 0x43, 0x77, 0x42, 0x64, 0x76, 0x49, 0x36, 0x34, 0x7A, 0x45, 0x62, 0x6F, 0x6F, 0x68, 0x37, 0x34, 0x35, 0x4E, 0x6E, 0x48, 0x45, 0x4B, 0x48, 0x31, 0x4A, 0x77, 0x37, 0x57, 0x32, 0x43, 0x0A, 0x6E, ++ 0x4A, 0x66, 0x46, 0x31, 0x30, 0x78, 0x4F, 0x52, 0x55, 0x6E, 0x4C, 0x51, 0x45, 0x4B, 0x31, 0x45, 0x6A, 0x52, 0x73, 0x47, 0x63, 0x4A, 0x30, 0x70, 0x44, 0x46, 0x66, 0x68, 0x51, 0x4B, 0x58, 0x37, 0x45, 0x4D, 0x7A, 0x43, 0x6C, 0x50, 0x53, 0x6E, ++ 0x49, 0x79, 0x4F, 0x74, 0x37, 0x68, 0x35, 0x32, 0x79, 0x76, 0x56, 0x61, 0x76, 0x4B, 0x4F, 0x5A, 0x73, 0x54, 0x75, 0x4B, 0x77, 0x45, 0x48, 0x6B, 0x74, 0x53, 0x7A, 0x30, 0x41, 0x4C, 0x66, 0x55, 0x50, 0x5A, 0x56, 0x0A, 0x72, 0x32, 0x59, 0x4F, ++ 0x79, 0x2B, 0x42, 0x48, 0x59, 0x43, 0x38, 0x72, 0x4D, 0x6A, 0x6B, 0x31, 0x55, 0x6A, 0x6F, 0x6F, 0x67, 0x2F, 0x68, 0x37, 0x46, 0x73, 0x59, 0x59, 0x75, 0x47, 0x4C, 0x57, 0x52, 0x79, 0x57, 0x52, 0x7A, 0x76, 0x41, 0x5A, 0x45, 0x6B, 0x32, 0x74, ++ 0x59, 0x2F, 0x58, 0x54, 0x50, 0x33, 0x56, 0x66, 0x4B, 0x66, 0x43, 0x68, 0x4D, 0x42, 0x77, 0x71, 0x6F, 0x4A, 0x69, 0x6D, 0x46, 0x62, 0x33, 0x75, 0x2F, 0x52, 0x6B, 0x32, 0x38, 0x4F, 0x4B, 0x52, 0x0A, 0x51, 0x34, 0x2F, 0x36, 0x79, 0x74, 0x59, ++ 0x51, 0x4A, 0x30, 0x6C, 0x4D, 0x37, 0x39, 0x33, 0x42, 0x38, 0x59, 0x56, 0x77, 0x6D, 0x38, 0x72, 0x71, 0x71, 0x46, 0x70, 0x44, 0x2F, 0x47, 0x32, 0x47, 0x62, 0x33, 0x50, 0x70, 0x4E, 0x30, 0x57, 0x70, 0x38, 0x44, 0x62, 0x48, 0x7A, 0x49, 0x68, ++ 0x31, 0x48, 0x72, 0x74, 0x73, 0x42, 0x76, 0x2B, 0x62, 0x61, 0x7A, 0x34, 0x58, 0x37, 0x47, 0x47, 0x71, 0x63, 0x58, 0x7A, 0x47, 0x48, 0x61, 0x4C, 0x33, 0x53, 0x65, 0x6B, 0x56, 0x0A, 0x74, 0x54, 0x7A, 0x57, 0x6F, 0x57, 0x48, 0x31, 0x45, 0x66, ++ 0x63, 0x46, 0x62, 0x78, 0x33, 0x39, 0x45, 0x62, 0x37, 0x51, 0x4D, 0x41, 0x66, 0x43, 0x4B, 0x62, 0x41, 0x4A, 0x54, 0x69, 0x62, 0x63, 0x34, 0x36, 0x4B, 0x6F, 0x6B, 0x57, 0x6F, 0x66, 0x77, 0x70, 0x46, 0x46, 0x69, 0x46, 0x7A, 0x6C, 0x6D, 0x4C, ++ 0x68, 0x78, 0x70, 0x52, 0x55, 0x5A, 0x79, 0x58, 0x78, 0x31, 0x45, 0x63, 0x78, 0x77, 0x64, 0x45, 0x38, 0x74, 0x6D, 0x78, 0x32, 0x52, 0x52, 0x50, 0x31, 0x57, 0x0A, 0x4B, 0x4B, 0x44, 0x2B, 0x75, 0x34, 0x5A, 0x71, 0x79, 0x50, 0x70, 0x63, 0x43, ++ 0x31, 0x6A, 0x63, 0x78, 0x6B, 0x74, 0x32, 0x79, 0x4B, 0x73, 0x69, 0x32, 0x58, 0x4D, 0x50, 0x70, 0x66, 0x52, 0x61, 0x41, 0x6F, 0x6B, 0x2F, 0x54, 0x35, 0x34, 0x69, 0x67, 0x75, 0x36, 0x69, 0x64, 0x46, 0x4D, 0x71, 0x50, 0x56, 0x4D, 0x6E, 0x61, ++ 0x52, 0x31, 0x73, 0x6A, 0x6A, 0x49, 0x73, 0x5A, 0x41, 0x41, 0x6D, 0x59, 0x32, 0x45, 0x32, 0x54, 0x71, 0x4E, 0x47, 0x74, 0x7A, 0x39, 0x39, 0x0A, 0x73, 0x79, 0x32, 0x73, 0x62, 0x5A, 0x43, 0x69, 0x6C, 0x61, 0x4C, 0x4F, 0x7A, 0x39, 0x71, 0x43, ++ 0x35, 0x77, 0x63, 0x30, 0x47, 0x5A, 0x62, 0x70, 0x75, 0x43, 0x47, 0x71, 0x4B, 0x58, 0x36, 0x6D, 0x4F, 0x4C, 0x36, 0x4F, 0x4B, 0x55, 0x6F, 0x68, 0x5A, 0x6E, 0x6B, 0x66, 0x73, 0x38, 0x4F, 0x31, 0x43, 0x57, 0x66, 0x65, 0x31, 0x74, 0x51, 0x48, ++ 0x52, 0x76, 0x4D, 0x71, 0x32, 0x75, 0x59, 0x69, 0x4E, 0x32, 0x44, 0x4C, 0x67, 0x62, 0x59, 0x50, 0x6F, 0x41, 0x2F, 0x70, 0x0A, 0x79, 0x4A, 0x56, 0x2F, 0x76, 0x31, 0x57, 0x52, 0x42, 0x58, 0x72, 0x50, 0x50, 0x52, 0x58, 0x41, 0x62, 0x39, 0x34, ++ 0x4A, 0x6C, 0x41, 0x47, 0x44, 0x31, 0x7A, 0x51, 0x62, 0x7A, 0x45, 0x43, 0x6C, 0x38, 0x4C, 0x69, 0x62, 0x5A, 0x39, 0x57, 0x59, 0x6B, 0x54, 0x75, 0x6E, 0x68, 0x48, 0x69, 0x56, 0x4A, 0x71, 0x52, 0x61, 0x43, 0x50, 0x67, 0x72, 0x64, 0x4C, 0x51, ++ 0x41, 0x42, 0x44, 0x7A, 0x66, 0x75, 0x42, 0x53, 0x4F, 0x36, 0x4E, 0x2B, 0x70, 0x6A, 0x57, 0x78, 0x6E, 0x0A, 0x6B, 0x6A, 0x4D, 0x64, 0x77, 0x4C, 0x66, 0x53, 0x37, 0x4A, 0x4C, 0x49, 0x76, 0x67, 0x6D, 0x2F, 0x4C, 0x43, 0x6B, 0x46, 0x62, 0x77, ++ 0x4A, 0x72, 0x6E, 0x75, 0x2B, 0x38, 0x76, 0x79, 0x71, 0x38, 0x57, 0x38, 0x42, 0x51, 0x6A, 0x30, 0x46, 0x77, 0x63, 0x59, 0x65, 0x79, 0x54, 0x62, 0x63, 0x45, 0x71, 0x59, 0x53, 0x6A, 0x4D, 0x71, 0x2B, 0x75, 0x37, 0x6D, 0x73, 0x58, 0x69, 0x37, ++ 0x4B, 0x78, 0x2F, 0x6D, 0x7A, 0x68, 0x6B, 0x49, 0x79, 0x49, 0x71, 0x4A, 0x64, 0x49, 0x0A, 0x7A, 0x73, 0x68, 0x4E, 0x79, 0x2F, 0x4D, 0x47, 0x7A, 0x31, 0x39, 0x71, 0x43, 0x6B, 0x4B, 0x78, 0x48, 0x68, 0x35, 0x33, 0x4C, 0x34, 0x36, 0x67, 0x35, ++ 0x70, 0x49, 0x4F, 0x42, 0x76, 0x77, 0x46, 0x49, 0x74, 0x49, 0x6D, 0x34, 0x54, 0x46, 0x52, 0x66, 0x54, 0x4C, 0x63, 0x44, 0x77, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x6F, 0x79, 0x4D, 0x77, 0x49, 0x54, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, ++ 0x51, 0x38, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x41, 0x4D, 0x43, 0x0A, 0x41, 0x51, 0x59, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x4E, ++ 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x67, 0x45, 0x41, 0x58, 0x7A, 0x53, 0x42, 0x64, 0x75, 0x2B, 0x57, 0x48, 0x64, 0x58, 0x6C, 0x74, 0x64, 0x6B, 0x43, ++ 0x59, 0x34, 0x51, 0x57, 0x77, 0x61, 0x36, 0x67, 0x0A, 0x63, 0x46, 0x47, 0x6E, 0x39, 0x30, 0x78, 0x48, 0x4E, 0x63, 0x67, 0x4C, 0x31, 0x79, 0x67, 0x39, 0x69, 0x58, 0x48, 0x5A, 0x71, 0x6A, 0x4E, 0x42, 0x36, 0x68, 0x51, 0x62, 0x62, 0x43, 0x45, ++ 0x41, 0x77, 0x47, 0x78, 0x43, 0x47, 0x58, 0x36, 0x66, 0x61, 0x56, 0x73, 0x67, 0x51, 0x74, 0x2B, 0x69, 0x30, 0x74, 0x72, 0x45, 0x66, 0x4A, 0x64, 0x4C, 0x6A, 0x62, 0x44, 0x6F, 0x72, 0x4D, 0x6A, 0x75, 0x70, 0x57, 0x6B, 0x45, 0x6D, 0x51, 0x71, ++ 0x53, 0x70, 0x71, 0x73, 0x6E, 0x0A, 0x4C, 0x68, 0x70, 0x4E, 0x67, 0x62, 0x2B, 0x45, 0x31, 0x48, 0x41, 0x65, 0x72, 0x55, 0x66, 0x2B, 0x2F, 0x55, 0x71, 0x64, 0x4D, 0x2B, 0x44, 0x79, 0x75, 0x63, 0x52, 0x46, 0x43, 0x43, 0x45, 0x4B, 0x32, 0x6D, ++ 0x6C, 0x70, 0x63, 0x33, 0x49, 0x4E, 0x76, 0x6A, 0x54, 0x2B, 0x6C, 0x49, 0x75, 0x74, 0x77, 0x78, 0x34, 0x31, 0x31, 0x36, 0x4B, 0x44, 0x37, 0x2B, 0x55, 0x34, 0x78, 0x36, 0x57, 0x46, 0x48, 0x36, 0x76, 0x50, 0x4E, 0x4F, 0x77, 0x2F, 0x4B, 0x50, ++ 0x34, 0x4D, 0x0A, 0x38, 0x56, 0x65, 0x47, 0x54, 0x73, 0x6C, 0x56, 0x39, 0x78, 0x7A, 0x55, 0x32, 0x4B, 0x56, 0x39, 0x42, 0x6E, 0x70, 0x76, 0x31, 0x64, 0x38, 0x51, 0x33, 0x34, 0x46, 0x4F, 0x49, 0x57, 0x57, 0x78, 0x74, 0x75, 0x45, 0x58, 0x65, ++ 0x5A, 0x56, 0x46, 0x42, 0x73, 0x35, 0x66, 0x7A, 0x4E, 0x78, 0x47, 0x69, 0x57, 0x4E, 0x6F, 0x52, 0x49, 0x32, 0x54, 0x39, 0x47, 0x52, 0x77, 0x6F, 0x44, 0x32, 0x64, 0x4B, 0x41, 0x58, 0x44, 0x4F, 0x58, 0x43, 0x34, 0x59, 0x6E, 0x73, 0x67, 0x0A, ++ 0x2F, 0x65, 0x54, 0x62, 0x36, 0x51, 0x69, 0x68, 0x75, 0x4A, 0x34, 0x39, 0x43, 0x63, 0x64, 0x50, 0x2B, 0x79, 0x7A, 0x34, 0x6B, 0x33, 0x5A, 0x42, 0x33, 0x6C, 0x4C, 0x67, 0x34, 0x56, 0x66, 0x53, 0x6E, 0x51, 0x4F, 0x38, 0x64, 0x35, 0x37, 0x2B, ++ 0x6E, 0x69, 0x6C, 0x65, 0x39, 0x38, 0x46, 0x52, 0x59, 0x42, 0x2F, 0x65, 0x32, 0x67, 0x75, 0x79, 0x4C, 0x58, 0x57, 0x33, 0x51, 0x30, 0x69, 0x54, 0x35, 0x2F, 0x5A, 0x35, 0x78, 0x6F, 0x52, 0x64, 0x67, 0x46, 0x6C, 0x67, 0x0A, 0x6C, 0x50, 0x78, ++ 0x34, 0x6D, 0x49, 0x38, 0x38, 0x6B, 0x31, 0x48, 0x74, 0x51, 0x4A, 0x41, 0x48, 0x33, 0x32, 0x52, 0x6A, 0x4A, 0x4D, 0x74, 0x4F, 0x63, 0x51, 0x57, 0x68, 0x31, 0x35, 0x51, 0x61, 0x69, 0x44, 0x4C, 0x78, 0x49, 0x6E, 0x51, 0x69, 0x72, 0x71, 0x57, ++ 0x6D, 0x32, 0x42, 0x4A, 0x70, 0x54, 0x47, 0x43, 0x6A, 0x41, 0x75, 0x34, 0x72, 0x37, 0x4E, 0x52, 0x6A, 0x6B, 0x67, 0x74, 0x65, 0x76, 0x69, 0x39, 0x32, 0x61, 0x36, 0x4F, 0x32, 0x4A, 0x72, 0x79, 0x50, 0x0A, 0x41, 0x39, 0x67, 0x4B, 0x38, 0x6B, ++ 0x78, 0x6B, 0x52, 0x72, 0x30, 0x35, 0x59, 0x75, 0x57, 0x57, 0x36, 0x7A, 0x52, 0x6A, 0x45, 0x53, 0x6A, 0x4D, 0x6C, 0x66, 0x47, 0x74, 0x37, 0x2B, 0x2F, 0x63, 0x67, 0x46, 0x68, 0x49, 0x36, 0x55, 0x75, 0x34, 0x36, 0x6D, 0x57, 0x73, 0x36, 0x66, ++ 0x79, 0x41, 0x74, 0x62, 0x58, 0x49, 0x52, 0x66, 0x6D, 0x73, 0x77, 0x5A, 0x2F, 0x5A, 0x75, 0x65, 0x70, 0x69, 0x69, 0x49, 0x37, 0x45, 0x38, 0x55, 0x75, 0x44, 0x45, 0x71, 0x33, 0x6D, 0x0A, 0x69, 0x34, 0x54, 0x57, 0x6E, 0x73, 0x4C, 0x72, 0x67, ++ 0x78, 0x69, 0x66, 0x61, 0x72, 0x73, 0x62, 0x4A, 0x47, 0x41, 0x7A, 0x63, 0x4D, 0x7A, 0x73, 0x39, 0x7A, 0x4C, 0x7A, 0x58, 0x4E, 0x6C, 0x35, 0x66, 0x65, 0x2B, 0x65, 0x70, 0x50, 0x37, 0x4A, 0x49, 0x38, 0x4D, 0x6B, 0x37, 0x68, 0x57, 0x53, 0x73, ++ 0x54, 0x32, 0x52, 0x54, 0x79, 0x61, 0x47, 0x76, 0x57, 0x5A, 0x7A, 0x4A, 0x42, 0x50, 0x71, 0x70, 0x4B, 0x35, 0x6A, 0x77, 0x61, 0x31, 0x39, 0x68, 0x41, 0x4D, 0x38, 0x0A, 0x45, 0x48, 0x69, 0x47, 0x47, 0x33, 0x6E, 0x6A, 0x78, 0x50, 0x50, 0x79, ++ 0x42, 0x4A, 0x55, 0x67, 0x72, 0x69, 0x4F, 0x43, 0x78, 0x4C, 0x4D, 0x36, 0x41, 0x47, 0x4B, 0x2F, 0x35, 0x6A, 0x59, 0x6B, 0x34, 0x56, 0x65, 0x36, 0x78, 0x78, 0x36, 0x51, 0x64, 0x64, 0x56, 0x66, 0x50, 0x35, 0x56, 0x68, 0x4B, 0x38, 0x45, 0x37, ++ 0x7A, 0x65, 0x57, 0x7A, 0x61, 0x47, 0x48, 0x51, 0x52, 0x69, 0x61, 0x70, 0x49, 0x56, 0x4A, 0x70, 0x4C, 0x65, 0x73, 0x75, 0x78, 0x2B, 0x74, 0x33, 0x0A, 0x7A, 0x71, 0x59, 0x36, 0x74, 0x51, 0x4D, 0x7A, 0x54, 0x33, 0x62, 0x52, 0x35, 0x31, 0x78, ++ 0x55, 0x41, 0x56, 0x33, 0x4C, 0x65, 0x50, 0x54, 0x4A, 0x44, 0x4C, 0x2F, 0x50, 0x45, 0x6F, 0x34, 0x58, 0x4C, 0x53, 0x4E, 0x6F, 0x6C, 0x4F, 0x65, 0x72, 0x2F, 0x71, 0x6D, 0x79, 0x4B, 0x77, 0x62, 0x51, 0x42, 0x4D, 0x30, 0x3D, 0x0A, 0x2D, 0x2D, ++ 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x54, 0x65, 0x6C, 0x69, 0x61, 0x53, 0x6F, 0x6E, 0x65, 0x72, 0x61, 0x20, 0x52, 0x6F, 0x6F, ++ 0x74, 0x20, 0x43, 0x41, 0x20, 0x76, 0x31, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, ++ 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x4F, 0x44, 0x43, 0x43, 0x41, 0x79, 0x43, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x52, 0x41, ++ 0x4A, 0x57, 0x2B, 0x46, 0x71, 0x44, 0x33, 0x4C, 0x6B, 0x62, 0x78, 0x65, 0x7A, 0x6D, 0x43, 0x63, 0x76, 0x71, 0x4C, 0x7A, 0x5A, 0x59, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x46, 0x42, ++ 0x51, 0x41, 0x77, 0x4E, 0x7A, 0x45, 0x55, 0x4D, 0x42, 0x49, 0x47, 0x41, 0x31, 0x55, 0x45, 0x0A, 0x43, 0x67, 0x77, 0x4C, 0x56, 0x47, 0x56, 0x73, 0x61, 0x57, 0x46, 0x54, 0x62, 0x32, 0x35, 0x6C, 0x63, 0x6D, 0x45, 0x78, 0x48, 0x7A, 0x41, 0x64, ++ 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x4D, 0x46, 0x6C, 0x52, 0x6C, 0x62, 0x47, 0x6C, 0x68, 0x55, 0x32, 0x39, 0x75, 0x5A, 0x58, 0x4A, 0x68, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x67, 0x64, 0x6A, 0x45, 0x77, ++ 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x44, 0x63, 0x78, 0x4D, 0x44, 0x45, 0x34, 0x0A, 0x4D, 0x54, 0x49, 0x77, 0x4D, 0x44, 0x55, 0x77, 0x57, 0x68, 0x63, 0x4E, 0x4D, 0x7A, 0x49, 0x78, 0x4D, 0x44, 0x45, 0x34, 0x4D, 0x54, 0x49, 0x77, 0x4D, 0x44, 0x55, ++ 0x77, 0x57, 0x6A, 0x41, 0x33, 0x4D, 0x52, 0x51, 0x77, 0x45, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x44, 0x41, 0x74, 0x55, 0x5A, 0x57, 0x78, 0x70, 0x59, 0x56, 0x4E, 0x76, 0x62, 0x6D, 0x56, 0x79, 0x59, 0x54, 0x45, 0x66, 0x4D, 0x42, 0x30, ++ 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x77, 0x77, 0x57, 0x0A, 0x56, 0x47, 0x56, 0x73, 0x61, 0x57, 0x46, 0x54, 0x62, 0x32, 0x35, 0x6C, 0x63, 0x6D, 0x45, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x51, 0x53, 0x42, 0x32, 0x4D, 0x54, ++ 0x43, 0x43, 0x41, 0x69, 0x49, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x50, 0x41, 0x44, 0x43, 0x43, 0x41, 0x67, 0x6F, 0x43, 0x67, 0x67, ++ 0x49, 0x42, 0x41, 0x4D, 0x4B, 0x2B, 0x0A, 0x36, 0x79, 0x66, 0x77, 0x49, 0x61, 0x50, 0x7A, 0x61, 0x53, 0x5A, 0x56, 0x66, 0x70, 0x33, 0x46, 0x56, 0x52, 0x61, 0x52, 0x58, 0x50, 0x33, 0x76, 0x49, 0x62, 0x39, 0x54, 0x67, 0x48, 0x6F, 0x74, 0x30, ++ 0x70, 0x47, 0x4D, 0x59, 0x7A, 0x48, 0x77, 0x37, 0x43, 0x54, 0x77, 0x77, 0x36, 0x58, 0x53, 0x63, 0x6E, 0x77, 0x51, 0x62, 0x66, 0x51, 0x33, 0x74, 0x2B, 0x58, 0x6D, 0x66, 0x48, 0x6E, 0x71, 0x6A, 0x4C, 0x57, 0x43, 0x69, 0x36, 0x35, 0x49, 0x74, ++ 0x71, 0x77, 0x41, 0x0A, 0x33, 0x47, 0x56, 0x31, 0x37, 0x43, 0x70, 0x4E, 0x58, 0x38, 0x47, 0x48, 0x39, 0x53, 0x42, 0x6C, 0x4B, 0x34, 0x47, 0x6F, 0x52, 0x7A, 0x36, 0x4A, 0x49, 0x35, 0x55, 0x77, 0x46, 0x70, 0x42, 0x2F, 0x36, 0x46, 0x63, 0x48, ++ 0x53, 0x4F, 0x63, 0x5A, 0x72, 0x72, 0x39, 0x46, 0x5A, 0x37, 0x45, 0x33, 0x47, 0x77, 0x59, 0x71, 0x2F, 0x74, 0x37, 0x35, 0x72, 0x48, 0x32, 0x44, 0x2B, 0x31, 0x36, 0x36, 0x35, 0x49, 0x2B, 0x58, 0x5A, 0x37, 0x35, 0x4C, 0x6A, 0x6F, 0x31, 0x6B, ++ 0x0A, 0x42, 0x31, 0x63, 0x34, 0x56, 0x57, 0x6B, 0x30, 0x4E, 0x6A, 0x30, 0x54, 0x53, 0x4F, 0x39, 0x50, 0x34, 0x74, 0x4E, 0x6D, 0x48, 0x71, 0x54, 0x50, 0x47, 0x72, 0x64, 0x65, 0x4E, 0x6A, 0x50, 0x55, 0x74, 0x41, 0x61, 0x39, 0x47, 0x41, 0x48, ++ 0x39, 0x64, 0x34, 0x52, 0x51, 0x41, 0x45, 0x58, 0x31, 0x6A, 0x46, 0x33, 0x6F, 0x49, 0x37, 0x78, 0x2B, 0x2F, 0x6A, 0x58, 0x68, 0x37, 0x56, 0x42, 0x37, 0x71, 0x54, 0x43, 0x4E, 0x47, 0x64, 0x4D, 0x4A, 0x6A, 0x6D, 0x68, 0x6E, 0x0A, 0x58, 0x62, ++ 0x38, 0x38, 0x6C, 0x78, 0x68, 0x54, 0x75, 0x79, 0x6C, 0x69, 0x78, 0x63, 0x70, 0x65, 0x63, 0x73, 0x48, 0x48, 0x6C, 0x74, 0x54, 0x62, 0x4C, 0x61, 0x43, 0x30, 0x48, 0x32, 0x6B, 0x44, 0x37, 0x4F, 0x72, 0x69, 0x55, 0x50, 0x45, 0x4D, 0x50, 0x50, ++ 0x43, 0x73, 0x38, 0x31, 0x4D, 0x74, 0x38, 0x42, 0x7A, 0x31, 0x37, 0x57, 0x77, 0x35, 0x4F, 0x58, 0x4F, 0x41, 0x46, 0x73, 0x68, 0x53, 0x73, 0x43, 0x50, 0x4E, 0x34, 0x44, 0x37, 0x63, 0x33, 0x54, 0x78, 0x48, 0x0A, 0x6F, 0x4C, 0x73, 0x31, 0x69, ++ 0x75, 0x4B, 0x59, 0x61, 0x49, 0x75, 0x2B, 0x35, 0x62, 0x39, 0x79, 0x37, 0x74, 0x4C, 0x36, 0x70, 0x65, 0x30, 0x53, 0x37, 0x66, 0x79, 0x59, 0x47, 0x4B, 0x6B, 0x6D, 0x64, 0x74, 0x77, 0x6F, 0x53, 0x78, 0x41, 0x67, 0x48, 0x4E, 0x4E, 0x2F, 0x46, ++ 0x6E, 0x63, 0x74, 0x37, 0x57, 0x2B, 0x41, 0x39, 0x30, 0x6D, 0x37, 0x55, 0x77, 0x57, 0x37, 0x58, 0x57, 0x6A, 0x48, 0x31, 0x4D, 0x68, 0x31, 0x46, 0x6A, 0x2B, 0x4A, 0x57, 0x6F, 0x76, 0x33, 0x0A, 0x46, 0x30, 0x66, 0x55, 0x54, 0x50, 0x48, 0x53, ++ 0x69, 0x58, 0x6B, 0x2B, 0x54, 0x54, 0x32, 0x59, 0x71, 0x47, 0x48, 0x65, 0x4F, 0x68, 0x37, 0x53, 0x2B, 0x46, 0x34, 0x44, 0x34, 0x4D, 0x48, 0x4A, 0x48, 0x49, 0x7A, 0x54, 0x6A, 0x55, 0x33, 0x54, 0x6C, 0x54, 0x61, 0x7A, 0x4E, 0x31, 0x39, 0x6A, ++ 0x59, 0x35, 0x73, 0x7A, 0x46, 0x50, 0x41, 0x74, 0x4A, 0x6D, 0x74, 0x54, 0x66, 0x49, 0x6D, 0x4D, 0x4D, 0x73, 0x4A, 0x75, 0x37, 0x44, 0x30, 0x68, 0x41, 0x44, 0x6E, 0x4A, 0x0A, 0x6F, 0x57, 0x6A, 0x69, 0x55, 0x49, 0x4D, 0x75, 0x73, 0x44, 0x6F, ++ 0x72, 0x38, 0x7A, 0x61, 0x67, 0x72, 0x43, 0x2F, 0x6B, 0x62, 0x32, 0x48, 0x43, 0x55, 0x51, 0x6B, 0x35, 0x50, 0x6F, 0x74, 0x54, 0x75, 0x62, 0x74, 0x6E, 0x32, 0x74, 0x78, 0x54, 0x75, 0x58, 0x5A, 0x5A, 0x4E, 0x70, 0x31, 0x44, 0x35, 0x53, 0x44, ++ 0x67, 0x50, 0x54, 0x4A, 0x67, 0x68, 0x53, 0x4A, 0x52, 0x74, 0x38, 0x63, 0x7A, 0x75, 0x39, 0x30, 0x56, 0x4C, 0x36, 0x52, 0x34, 0x70, 0x67, 0x64, 0x37, 0x0A, 0x67, 0x55, 0x59, 0x32, 0x42, 0x49, 0x62, 0x64, 0x65, 0x54, 0x58, 0x48, 0x6C, 0x53, ++ 0x77, 0x37, 0x73, 0x4B, 0x4D, 0x58, 0x4E, 0x65, 0x56, 0x7A, 0x48, 0x37, 0x52, 0x63, 0x57, 0x65, 0x2F, 0x61, 0x36, 0x68, 0x42, 0x6C, 0x65, 0x33, 0x72, 0x51, 0x66, 0x35, 0x2B, 0x7A, 0x74, 0x43, 0x6F, 0x33, 0x4F, 0x33, 0x43, 0x4C, 0x6D, 0x31, ++ 0x75, 0x35, 0x4B, 0x37, 0x66, 0x73, 0x73, 0x6C, 0x45, 0x53, 0x6C, 0x31, 0x4D, 0x70, 0x57, 0x74, 0x54, 0x77, 0x45, 0x68, 0x44, 0x63, 0x0A, 0x54, 0x77, 0x4B, 0x37, 0x45, 0x70, 0x49, 0x76, 0x59, 0x74, 0x51, 0x2F, 0x61, 0x55, 0x4E, 0x38, 0x44, ++ 0x64, 0x62, 0x38, 0x57, 0x48, 0x55, 0x42, 0x69, 0x4A, 0x31, 0x59, 0x46, 0x6B, 0x76, 0x65, 0x75, 0x70, 0x44, 0x2F, 0x52, 0x77, 0x47, 0x4A, 0x42, 0x6D, 0x72, 0x32, 0x58, 0x37, 0x4B, 0x51, 0x61, 0x72, 0x4D, 0x43, 0x70, 0x67, 0x4B, 0x49, 0x76, ++ 0x37, 0x4E, 0x48, 0x66, 0x69, 0x72, 0x5A, 0x31, 0x66, 0x70, 0x6F, 0x65, 0x44, 0x56, 0x4E, 0x41, 0x67, 0x4D, 0x42, 0x0A, 0x41, 0x41, 0x47, 0x6A, 0x50, 0x7A, 0x41, 0x39, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, ++ 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x43, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x42, 0x41, 0x51, 0x44, 0x41, 0x67, 0x45, 0x47, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, ++ 0x42, 0x42, 0x54, 0x77, 0x6A, 0x31, 0x6B, 0x34, 0x41, 0x4C, 0x50, 0x31, 0x6A, 0x35, 0x71, 0x57, 0x0A, 0x44, 0x4E, 0x58, 0x72, 0x2B, 0x6E, 0x75, 0x71, 0x46, 0x2B, 0x67, 0x54, 0x45, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, ++ 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x55, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x67, 0x45, 0x41, 0x76, 0x75, 0x52, 0x63, 0x59, 0x6B, 0x34, 0x6B, 0x39, 0x41, 0x77, 0x49, 0x2F, 0x2F, 0x44, 0x54, 0x44, 0x47, 0x6A, 0x6B, 0x6B, 0x30, 0x6B, ++ 0x69, 0x50, 0x30, 0x51, 0x6E, 0x62, 0x37, 0x74, 0x74, 0x33, 0x6F, 0x4E, 0x6D, 0x0A, 0x7A, 0x71, 0x6A, 0x4D, 0x44, 0x66, 0x7A, 0x31, 0x6D, 0x67, 0x62, 0x6C, 0x64, 0x78, 0x53, 0x52, 0x36, 0x35, 0x31, 0x42, 0x65, 0x35, 0x6B, 0x71, 0x68, 0x4F, ++ 0x58, 0x2F, 0x2F, 0x43, 0x48, 0x42, 0x58, 0x66, 0x44, 0x6B, 0x48, 0x31, 0x65, 0x33, 0x64, 0x61, 0x6D, 0x68, 0x58, 0x77, 0x49, 0x6D, 0x2F, 0x39, 0x66, 0x48, 0x39, 0x30, 0x37, 0x65, 0x54, 0x2F, 0x6A, 0x33, 0x48, 0x45, 0x62, 0x41, 0x65, 0x6B, ++ 0x39, 0x41, 0x4C, 0x43, 0x49, 0x31, 0x38, 0x42, 0x6D, 0x78, 0x0A, 0x30, 0x47, 0x74, 0x6E, 0x4C, 0x4C, 0x43, 0x6F, 0x34, 0x4D, 0x42, 0x41, 0x4E, 0x7A, 0x58, 0x32, 0x68, 0x46, 0x78, 0x63, 0x34, 0x36, 0x39, 0x43, 0x65, 0x50, 0x36, 0x6E, 0x79, ++ 0x51, 0x31, 0x51, 0x36, 0x67, 0x32, 0x45, 0x64, 0x76, 0x5A, 0x52, 0x37, 0x34, 0x4E, 0x54, 0x78, 0x6E, 0x72, 0x2F, 0x44, 0x6C, 0x5A, 0x4A, 0x4C, 0x6F, 0x39, 0x36, 0x31, 0x67, 0x7A, 0x6D, 0x4A, 0x31, 0x54, 0x6A, 0x54, 0x51, 0x70, 0x67, 0x63, ++ 0x6D, 0x4C, 0x4E, 0x6B, 0x51, 0x66, 0x57, 0x0A, 0x70, 0x62, 0x2F, 0x49, 0x6D, 0x57, 0x76, 0x74, 0x78, 0x42, 0x6E, 0x6D, 0x71, 0x30, 0x77, 0x52, 0x4F, 0x4D, 0x56, 0x76, 0x4D, 0x65, 0x4A, 0x75, 0x53, 0x63, 0x67, 0x2F, 0x64, 0x6F, 0x41, 0x6D, ++ 0x41, 0x79, 0x59, 0x70, 0x34, 0x44, 0x62, 0x32, 0x39, 0x69, 0x42, 0x54, 0x34, 0x78, 0x64, 0x77, 0x4E, 0x42, 0x65, 0x64, 0x59, 0x32, 0x67, 0x65, 0x61, 0x2B, 0x7A, 0x44, 0x54, 0x59, 0x61, 0x34, 0x45, 0x7A, 0x41, 0x76, 0x58, 0x55, 0x59, 0x4E, ++ 0x52, 0x30, 0x50, 0x56, 0x0A, 0x47, 0x36, 0x70, 0x5A, 0x44, 0x72, 0x6C, 0x63, 0x6A, 0x51, 0x5A, 0x49, 0x72, 0x58, 0x53, 0x48, 0x58, 0x38, 0x66, 0x38, 0x4D, 0x56, 0x52, 0x42, 0x45, 0x2B, 0x4C, 0x48, 0x49, 0x51, 0x36, 0x65, 0x34, 0x42, 0x34, ++ 0x4E, 0x34, 0x63, 0x42, 0x37, 0x51, 0x34, 0x57, 0x51, 0x78, 0x59, 0x70, 0x59, 0x78, 0x6D, 0x55, 0x4B, 0x65, 0x46, 0x66, 0x79, 0x78, 0x69, 0x4D, 0x50, 0x41, 0x64, 0x6B, 0x67, 0x53, 0x39, 0x34, 0x50, 0x2B, 0x35, 0x4B, 0x46, 0x64, 0x53, 0x70, ++ 0x63, 0x0A, 0x63, 0x34, 0x31, 0x74, 0x65, 0x79, 0x57, 0x52, 0x79, 0x75, 0x35, 0x46, 0x72, 0x67, 0x5A, 0x4C, 0x41, 0x4D, 0x7A, 0x54, 0x73, 0x56, 0x6C, 0x51, 0x32, 0x6A, 0x71, 0x49, 0x4F, 0x79, 0x6C, 0x44, 0x52, 0x6C, 0x36, 0x58, 0x4B, 0x31, ++ 0x54, 0x4F, 0x55, 0x32, 0x2B, 0x4E, 0x53, 0x75, 0x65, 0x57, 0x2B, 0x72, 0x39, 0x78, 0x44, 0x6B, 0x4B, 0x4C, 0x66, 0x50, 0x30, 0x6F, 0x6F, 0x4E, 0x42, 0x49, 0x79, 0x74, 0x72, 0x45, 0x67, 0x55, 0x79, 0x37, 0x6F, 0x6E, 0x4F, 0x54, 0x0A, 0x4A, ++ 0x73, 0x6A, 0x72, 0x44, 0x4E, 0x59, 0x6D, 0x69, 0x4C, 0x62, 0x41, 0x4A, 0x4D, 0x2B, 0x37, 0x76, 0x56, 0x76, 0x72, 0x64, 0x58, 0x33, 0x70, 0x43, 0x49, 0x36, 0x47, 0x4D, 0x79, 0x78, 0x35, 0x64, 0x77, 0x6C, 0x70, 0x70, 0x59, 0x6E, 0x38, 0x73, ++ 0x33, 0x43, 0x51, 0x68, 0x33, 0x61, 0x50, 0x30, 0x79, 0x4B, 0x37, 0x51, 0x73, 0x36, 0x39, 0x63, 0x77, 0x73, 0x67, 0x4A, 0x69, 0x72, 0x51, 0x6D, 0x7A, 0x31, 0x77, 0x48, 0x69, 0x52, 0x73, 0x7A, 0x59, 0x64, 0x32, 0x0A, 0x71, 0x52, 0x65, 0x57, ++ 0x74, 0x38, 0x38, 0x4E, 0x6B, 0x76, 0x75, 0x4F, 0x47, 0x4B, 0x6D, 0x59, 0x53, 0x64, 0x47, 0x65, 0x2F, 0x6D, 0x42, 0x45, 0x63, 0x69, 0x47, 0x35, 0x47, 0x65, 0x33, 0x43, 0x39, 0x54, 0x48, 0x78, 0x4F, 0x55, 0x69, 0x49, 0x6B, 0x43, 0x52, 0x31, ++ 0x56, 0x42, 0x61, 0x74, 0x7A, 0x76, 0x54, 0x34, 0x61, 0x52, 0x52, 0x6B, 0x4F, 0x66, 0x75, 0x6A, 0x75, 0x4C, 0x70, 0x77, 0x51, 0x4D, 0x63, 0x6E, 0x48, 0x4C, 0x2F, 0x45, 0x56, 0x6C, 0x50, 0x36, 0x0A, 0x59, 0x32, 0x58, 0x51, 0x38, 0x78, 0x77, ++ 0x4F, 0x46, 0x76, 0x56, 0x72, 0x68, 0x6C, 0x68, 0x4E, 0x47, 0x4E, 0x54, 0x6B, 0x44, 0x59, 0x36, 0x6C, 0x6E, 0x56, 0x75, 0x52, 0x33, 0x48, 0x59, 0x6B, 0x55, 0x44, 0x2F, 0x47, 0x4B, 0x76, 0x76, 0x5A, 0x74, 0x35, 0x79, 0x31, 0x31, 0x75, 0x62, ++ 0x51, 0x32, 0x65, 0x67, 0x5A, 0x69, 0x78, 0x56, 0x78, 0x53, 0x4B, 0x32, 0x33, 0x36, 0x74, 0x68, 0x5A, 0x69, 0x4E, 0x53, 0x51, 0x76, 0x78, 0x61, 0x7A, 0x32, 0x65, 0x6D, 0x73, 0x0A, 0x57, 0x57, 0x46, 0x55, 0x79, 0x42, 0x79, 0x36, 0x79, 0x73, ++ 0x48, 0x4B, 0x34, 0x62, 0x6B, 0x67, 0x54, 0x49, 0x38, 0x36, 0x6B, 0x34, 0x6D, 0x6C, 0x6F, 0x4D, 0x79, 0x2F, 0x30, 0x2F, 0x5A, 0x31, 0x70, 0x48, 0x57, 0x57, 0x62, 0x56, 0x59, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, ++ 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x54, 0x2D, 0x54, 0x65, 0x6C, 0x65, 0x53, 0x65, 0x63, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, ++ 0x6C, 0x61, 0x73, 0x73, 0x20, 0x32, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, ++ 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x44, 0x77, 0x7A, 0x43, 0x43, 0x41, 0x71, 0x75, 0x67, 0x41, 0x77, 0x49, 0x42, ++ 0x41, 0x67, 0x49, 0x42, 0x41, 0x54, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x44, 0x43, 0x42, 0x67, 0x6A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, ++ 0x42, 0x68, 0x4D, 0x43, 0x52, 0x45, 0x55, 0x78, 0x4B, 0x7A, 0x41, 0x70, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x4D, 0x0A, 0x49, 0x6C, 0x51, 0x74, 0x55, 0x33, 0x6C, 0x7A, 0x64, 0x47, 0x56, 0x74, 0x63, 0x79, 0x42, 0x46, 0x62, 0x6E, 0x52, ++ 0x6C, 0x63, 0x6E, 0x42, 0x79, 0x61, 0x58, 0x4E, 0x6C, 0x49, 0x46, 0x4E, 0x6C, 0x63, 0x6E, 0x5A, 0x70, 0x59, 0x32, 0x56, 0x7A, 0x49, 0x45, 0x64, 0x74, 0x59, 0x6B, 0x67, 0x78, 0x48, 0x7A, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x73, ++ 0x4D, 0x46, 0x6C, 0x51, 0x74, 0x55, 0x33, 0x6C, 0x7A, 0x64, 0x47, 0x56, 0x74, 0x63, 0x79, 0x42, 0x55, 0x0A, 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x43, 0x42, 0x44, 0x5A, 0x57, 0x35, 0x30, 0x5A, 0x58, 0x49, 0x78, 0x4A, 0x54, 0x41, 0x6A, 0x42, 0x67, ++ 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x4D, 0x48, 0x46, 0x51, 0x74, 0x56, 0x47, 0x56, 0x73, 0x5A, 0x56, 0x4E, 0x6C, 0x59, 0x79, 0x42, 0x48, 0x62, 0x47, 0x39, 0x69, 0x59, 0x57, 0x78, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x73, 0x59, 0x58, ++ 0x4E, 0x7A, 0x49, 0x44, 0x49, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x44, 0x67, 0x78, 0x0A, 0x4D, 0x44, 0x41, 0x78, 0x4D, 0x54, 0x41, 0x30, 0x4D, 0x44, 0x45, 0x30, 0x57, 0x68, 0x63, 0x4E, 0x4D, 0x7A, 0x4D, 0x78, 0x4D, 0x44, 0x41, 0x78, 0x4D, ++ 0x6A, 0x4D, 0x31, 0x4F, 0x54, 0x55, 0x35, 0x57, 0x6A, 0x43, 0x42, 0x67, 0x6A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x52, 0x45, 0x55, 0x78, 0x4B, 0x7A, 0x41, 0x70, 0x42, 0x67, 0x4E, 0x56, 0x42, ++ 0x41, 0x6F, 0x4D, 0x49, 0x6C, 0x51, 0x74, 0x55, 0x33, 0x6C, 0x7A, 0x0A, 0x64, 0x47, 0x56, 0x74, 0x63, 0x79, 0x42, 0x46, 0x62, 0x6E, 0x52, 0x6C, 0x63, 0x6E, 0x42, 0x79, 0x61, 0x58, 0x4E, 0x6C, 0x49, 0x46, 0x4E, 0x6C, 0x63, 0x6E, 0x5A, 0x70, ++ 0x59, 0x32, 0x56, 0x7A, 0x49, 0x45, 0x64, 0x74, 0x59, 0x6B, 0x67, 0x78, 0x48, 0x7A, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x73, 0x4D, 0x46, 0x6C, 0x51, 0x74, 0x55, 0x33, 0x6C, 0x7A, 0x64, 0x47, 0x56, 0x74, 0x63, 0x79, 0x42, 0x55, ++ 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x43, 0x42, 0x44, 0x0A, 0x5A, 0x57, 0x35, 0x30, 0x5A, 0x58, 0x49, 0x78, 0x4A, 0x54, 0x41, 0x6A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x4D, 0x48, 0x46, 0x51, 0x74, 0x56, 0x47, 0x56, 0x73, 0x5A, 0x56, 0x4E, ++ 0x6C, 0x59, 0x79, 0x42, 0x48, 0x62, 0x47, 0x39, 0x69, 0x59, 0x57, 0x78, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x73, 0x59, 0x58, 0x4E, 0x7A, 0x49, 0x44, 0x49, 0x77, 0x67, 0x67, 0x45, 0x69, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, ++ 0x47, 0x53, 0x49, 0x62, 0x33, 0x0A, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x42, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x45, 0x4B, 0x41, 0x6F, 0x49, 0x42, 0x41, 0x51, 0x43, 0x71, 0x58, 0x39, 0x6F, 0x62, 0x58, 0x2B, ++ 0x68, 0x7A, 0x6B, 0x65, 0x58, 0x61, 0x58, 0x50, 0x53, 0x69, 0x35, 0x6B, 0x66, 0x6C, 0x38, 0x32, 0x68, 0x56, 0x59, 0x41, 0x55, 0x64, 0x41, 0x71, 0x53, 0x7A, 0x6D, 0x31, 0x6E, 0x7A, 0x48, 0x6F, 0x71, 0x76, 0x4E, 0x4B, 0x33, 0x38, 0x44, 0x63, ++ 0x4C, 0x5A, 0x0A, 0x53, 0x42, 0x6E, 0x75, 0x61, 0x59, 0x2F, 0x4A, 0x49, 0x50, 0x77, 0x68, 0x71, 0x67, 0x63, 0x5A, 0x37, 0x62, 0x42, 0x63, 0x72, 0x47, 0x58, 0x48, 0x58, 0x2B, 0x30, 0x43, 0x66, 0x48, 0x74, 0x38, 0x4C, 0x52, 0x76, 0x57, 0x75, ++ 0x72, 0x6D, 0x41, 0x77, 0x68, 0x69, 0x43, 0x46, 0x6F, 0x54, 0x36, 0x5A, 0x72, 0x41, 0x49, 0x78, 0x6C, 0x51, 0x6A, 0x67, 0x65, 0x54, 0x4E, 0x75, 0x55, 0x6B, 0x2F, 0x39, 0x6B, 0x39, 0x75, 0x4E, 0x30, 0x67, 0x6F, 0x4F, 0x41, 0x2F, 0x46, 0x0A, ++ 0x76, 0x75, 0x64, 0x6F, 0x63, 0x50, 0x30, 0x35, 0x6C, 0x30, 0x33, 0x53, 0x78, 0x35, 0x69, 0x52, 0x55, 0x4B, 0x72, 0x45, 0x52, 0x4C, 0x4D, 0x6A, 0x66, 0x54, 0x6C, 0x48, 0x36, 0x56, 0x4A, 0x69, 0x31, 0x68, 0x4B, 0x54, 0x58, 0x72, 0x63, 0x78, ++ 0x6C, 0x6B, 0x49, 0x46, 0x2B, 0x33, 0x61, 0x6E, 0x48, 0x71, 0x50, 0x31, 0x77, 0x76, 0x7A, 0x70, 0x65, 0x73, 0x56, 0x73, 0x71, 0x58, 0x46, 0x50, 0x36, 0x73, 0x74, 0x34, 0x76, 0x47, 0x43, 0x76, 0x78, 0x39, 0x37, 0x30, 0x0A, 0x32, 0x63, 0x75, ++ 0x2B, 0x66, 0x6A, 0x4F, 0x6C, 0x62, 0x70, 0x53, 0x44, 0x38, 0x44, 0x54, 0x36, 0x49, 0x61, 0x76, 0x71, 0x6A, 0x6E, 0x4B, 0x67, 0x50, 0x36, 0x54, 0x65, 0x4D, 0x46, 0x76, 0x76, 0x68, 0x6B, 0x31, 0x71, 0x6C, 0x56, 0x74, 0x44, 0x52, 0x4B, 0x67, ++ 0x51, 0x46, 0x52, 0x7A, 0x6C, 0x41, 0x56, 0x66, 0x46, 0x6D, 0x50, 0x48, 0x6D, 0x42, 0x69, 0x69, 0x52, 0x71, 0x69, 0x44, 0x46, 0x74, 0x31, 0x4D, 0x6D, 0x55, 0x55, 0x4F, 0x79, 0x43, 0x78, 0x47, 0x56, 0x0A, 0x57, 0x4F, 0x48, 0x41, 0x44, 0x33, ++ 0x62, 0x5A, 0x77, 0x49, 0x31, 0x38, 0x67, 0x66, 0x4E, 0x79, 0x63, 0x4A, 0x35, 0x76, 0x2F, 0x68, 0x71, 0x4F, 0x32, 0x56, 0x38, 0x31, 0x78, 0x72, 0x4A, 0x76, 0x4E, 0x48, 0x79, 0x2B, 0x53, 0x45, 0x2F, 0x69, 0x57, 0x6A, 0x6E, 0x58, 0x32, 0x4A, ++ 0x31, 0x34, 0x6E, 0x70, 0x2B, 0x47, 0x50, 0x67, 0x4E, 0x65, 0x47, 0x59, 0x74, 0x45, 0x6F, 0x74, 0x58, 0x48, 0x41, 0x67, 0x4D, 0x42, 0x41, 0x41, 0x47, 0x6A, 0x51, 0x6A, 0x42, 0x41, 0x0A, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, ++ 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x51, 0x44, 0x41, 0x67, 0x45, 0x47, 0x4D, 0x42, 0x30, 0x47, 0x41, ++ 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x53, 0x2F, 0x57, 0x53, 0x41, 0x32, 0x41, 0x48, 0x6D, 0x67, 0x6F, 0x43, 0x4A, 0x72, 0x6A, 0x4E, 0x58, 0x79, 0x0A, 0x59, 0x64, 0x4B, 0x34, 0x4C, 0x4D, 0x75, 0x43, 0x53, 0x6A, 0x41, 0x4E, ++ 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x51, 0x45, 0x41, 0x4D, 0x51, 0x4F, 0x69, 0x59, 0x51, 0x73, 0x66, 0x64, 0x4F, 0x68, 0x79, 0x4E, 0x73, 0x5A, 0x74, ++ 0x2B, 0x55, 0x32, 0x65, 0x2B, 0x69, 0x4B, 0x6F, 0x34, 0x59, 0x46, 0x57, 0x7A, 0x38, 0x32, 0x37, 0x6E, 0x2B, 0x71, 0x72, 0x6B, 0x52, 0x6B, 0x34, 0x0A, 0x72, 0x36, 0x70, 0x38, 0x46, 0x55, 0x33, 0x7A, 0x74, 0x71, 0x4F, 0x4E, 0x70, 0x66, 0x53, ++ 0x4F, 0x39, 0x6B, 0x53, 0x70, 0x70, 0x2B, 0x67, 0x68, 0x6C, 0x61, 0x30, 0x2B, 0x41, 0x47, 0x49, 0x57, 0x69, 0x50, 0x41, 0x43, 0x75, 0x76, 0x78, 0x68, 0x49, 0x2B, 0x59, 0x7A, 0x6D, 0x7A, 0x42, 0x36, 0x61, 0x7A, 0x5A, 0x69, 0x65, 0x36, 0x30, ++ 0x45, 0x49, 0x34, 0x52, 0x59, 0x5A, 0x65, 0x4C, 0x62, 0x4B, 0x34, 0x72, 0x6E, 0x4A, 0x56, 0x4D, 0x33, 0x59, 0x6C, 0x4E, 0x66, 0x0A, 0x76, 0x4E, 0x6F, 0x42, 0x59, 0x69, 0x6D, 0x69, 0x70, 0x69, 0x64, 0x78, 0x35, 0x6A, 0x6F, 0x69, 0x66, 0x73, ++ 0x46, 0x76, 0x48, 0x5A, 0x56, 0x77, 0x49, 0x45, 0x6F, 0x48, 0x4E, 0x4E, 0x2F, 0x71, 0x2F, 0x78, 0x57, 0x41, 0x35, 0x62, 0x72, 0x58, 0x65, 0x74, 0x68, 0x62, 0x64, 0x58, 0x77, 0x46, 0x65, 0x69, 0x6C, 0x48, 0x66, 0x6B, 0x43, 0x6F, 0x4D, 0x52, ++ 0x4E, 0x33, 0x7A, 0x55, 0x41, 0x37, 0x74, 0x46, 0x46, 0x48, 0x65, 0x69, 0x34, 0x52, 0x34, 0x30, 0x63, 0x52, 0x0A, 0x33, 0x70, 0x31, 0x6D, 0x30, 0x49, 0x76, 0x56, 0x56, 0x47, 0x62, 0x36, 0x67, 0x31, 0x58, 0x71, 0x66, 0x4D, 0x49, 0x70, 0x69, ++ 0x52, 0x76, 0x70, 0x62, 0x37, 0x50, 0x4F, 0x34, 0x67, 0x57, 0x45, 0x79, 0x53, 0x38, 0x2B, 0x65, 0x49, 0x56, 0x69, 0x62, 0x73, 0x6C, 0x66, 0x77, 0x58, 0x68, 0x6A, 0x64, 0x46, 0x6A, 0x41, 0x53, 0x42, 0x67, 0x4D, 0x6D, 0x54, 0x6E, 0x72, 0x70, ++ 0x4D, 0x77, 0x61, 0x74, 0x58, 0x6C, 0x61, 0x6A, 0x52, 0x57, 0x63, 0x32, 0x42, 0x51, 0x4E, 0x0A, 0x39, 0x6E, 0x6F, 0x48, 0x56, 0x38, 0x63, 0x69, 0x67, 0x77, 0x55, 0x74, 0x50, 0x4A, 0x73, 0x6C, 0x4A, 0x6A, 0x30, 0x59, 0x73, 0x36, 0x6C, 0x44, ++ 0x66, 0x4D, 0x6A, 0x49, 0x71, 0x32, 0x53, 0x50, 0x44, 0x71, 0x4F, 0x2F, 0x6E, 0x42, 0x75, 0x64, 0x4D, 0x4E, 0x76, 0x61, 0x30, 0x42, 0x6B, 0x75, 0x71, 0x6A, 0x7A, 0x78, 0x2B, 0x7A, 0x4F, 0x41, 0x64, 0x75, 0x54, 0x4E, 0x72, 0x52, 0x6C, 0x50, ++ 0x42, 0x53, 0x65, 0x4F, 0x45, 0x36, 0x46, 0x75, 0x77, 0x67, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, ++ 0x41, 0x74, 0x6F, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x32, 0x30, 0x31, 0x31, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x44, 0x64, 0x7A, 0x43, 0x43, ++ 0x41, 0x6C, 0x2B, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x49, 0x58, 0x44, 0x50, 0x4C, 0x59, 0x69, 0x78, 0x66, 0x73, 0x7A, 0x49, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4C, ++ 0x42, 0x51, 0x41, 0x77, 0x50, 0x44, 0x45, 0x65, 0x4D, 0x42, 0x77, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x77, 0x77, 0x56, 0x51, 0x58, 0x52, 0x76, 0x63, 0x79, 0x42, 0x55, 0x0A, 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x47, 0x56, 0x6B, 0x55, 0x6D, 0x39, ++ 0x76, 0x64, 0x43, 0x41, 0x79, 0x4D, 0x44, 0x45, 0x78, 0x4D, 0x51, 0x30, 0x77, 0x43, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x44, 0x41, 0x52, 0x42, 0x64, 0x47, 0x39, 0x7A, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, ++ 0x47, 0x45, 0x77, 0x4A, 0x45, 0x52, 0x54, 0x41, 0x65, 0x46, 0x77, 0x30, 0x78, 0x4D, 0x54, 0x41, 0x33, 0x4D, 0x44, 0x63, 0x78, 0x4E, 0x44, 0x55, 0x34, 0x0A, 0x4D, 0x7A, 0x42, 0x61, 0x46, 0x77, 0x30, 0x7A, 0x4D, 0x44, 0x45, 0x79, 0x4D, 0x7A, ++ 0x45, 0x79, 0x4D, 0x7A, 0x55, 0x35, 0x4E, 0x54, 0x6C, 0x61, 0x4D, 0x44, 0x77, 0x78, 0x48, 0x6A, 0x41, 0x63, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x4D, 0x46, 0x55, 0x46, 0x30, 0x62, 0x33, 0x4D, 0x67, 0x56, 0x48, 0x4A, 0x31, 0x63, 0x33, ++ 0x52, 0x6C, 0x5A, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x4D, 0x6A, 0x41, 0x78, 0x4D, 0x54, 0x45, 0x4E, 0x4D, 0x41, 0x73, 0x47, 0x0A, 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, 0x45, 0x51, 0x58, 0x52, 0x76, 0x63, 0x7A, 0x45, 0x4C, 0x4D, ++ 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x52, 0x45, 0x55, 0x77, 0x67, 0x67, 0x45, 0x69, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, ++ 0x34, 0x49, 0x42, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x45, 0x4B, 0x41, 0x6F, 0x49, 0x42, 0x41, 0x51, 0x43, 0x56, 0x0A, 0x68, 0x54, 0x75, 0x58, 0x62, 0x79, 0x6F, 0x37, 0x4C, 0x6A, 0x76, 0x50, 0x70, 0x76, 0x4D, 0x70, 0x4E, 0x62, 0x37, 0x50, ++ 0x47, 0x4B, 0x77, 0x2B, 0x71, 0x74, 0x6E, 0x34, 0x54, 0x61, 0x41, 0x2B, 0x47, 0x6B, 0x65, 0x35, 0x76, 0x4A, 0x72, 0x66, 0x38, 0x76, 0x37, 0x4D, 0x50, 0x6B, 0x66, 0x6F, 0x65, 0x70, 0x62, 0x43, 0x4A, 0x49, 0x34, 0x31, 0x39, 0x4B, 0x6B, 0x4D, ++ 0x2F, 0x49, 0x4C, 0x39, 0x62, 0x63, 0x46, 0x79, 0x59, 0x69, 0x65, 0x39, 0x36, 0x6D, 0x76, 0x72, 0x0A, 0x35, 0x34, 0x72, 0x4D, 0x56, 0x44, 0x36, 0x51, 0x55, 0x4D, 0x2B, 0x41, 0x31, 0x4A, 0x58, 0x37, 0x36, 0x4C, 0x57, 0x43, 0x31, 0x42, 0x54, ++ 0x46, 0x74, 0x71, 0x6C, 0x56, 0x4A, 0x56, 0x66, 0x62, 0x73, 0x56, 0x44, 0x32, 0x73, 0x47, 0x42, 0x6B, 0x57, 0x58, 0x70, 0x70, 0x7A, 0x77, 0x4F, 0x33, 0x62, 0x77, 0x32, 0x2B, 0x79, 0x6A, 0x35, 0x76, 0x64, 0x48, 0x4C, 0x71, 0x71, 0x6A, 0x41, ++ 0x71, 0x63, 0x32, 0x4B, 0x2B, 0x53, 0x5A, 0x46, 0x68, 0x79, 0x42, 0x48, 0x2B, 0x0A, 0x44, 0x67, 0x4D, 0x71, 0x39, 0x32, 0x6F, 0x67, 0x33, 0x41, 0x49, 0x56, 0x44, 0x56, 0x34, 0x56, 0x61, 0x76, 0x7A, 0x6A, 0x67, 0x73, 0x47, 0x31, 0x78, 0x5A, ++ 0x31, 0x6B, 0x43, 0x57, 0x79, 0x6A, 0x57, 0x5A, 0x67, 0x48, 0x4A, 0x38, 0x63, 0x62, 0x6C, 0x69, 0x74, 0x68, 0x64, 0x48, 0x46, 0x73, 0x51, 0x2F, 0x48, 0x33, 0x4E, 0x59, 0x6B, 0x51, 0x34, 0x4A, 0x37, 0x73, 0x56, 0x61, 0x45, 0x33, 0x49, 0x71, ++ 0x4B, 0x48, 0x42, 0x41, 0x55, 0x73, 0x52, 0x33, 0x32, 0x30, 0x0A, 0x48, 0x4C, 0x6C, 0x69, 0x4B, 0x57, 0x59, 0x6F, 0x79, 0x72, 0x66, 0x68, 0x6B, 0x2F, 0x57, 0x6B, 0x6C, 0x41, 0x4F, 0x5A, 0x75, 0x58, 0x43, 0x46, 0x74, 0x65, 0x5A, 0x49, 0x36, ++ 0x6F, 0x31, 0x51, 0x2F, 0x4E, 0x6E, 0x65, 0x7A, 0x47, 0x38, 0x48, 0x44, 0x74, 0x30, 0x4C, 0x63, 0x70, 0x32, 0x41, 0x4D, 0x42, 0x59, 0x48, 0x6C, 0x54, 0x38, 0x6F, 0x44, 0x76, 0x33, 0x46, 0x64, 0x55, 0x39, 0x54, 0x31, 0x6E, 0x53, 0x61, 0x74, ++ 0x43, 0x51, 0x75, 0x6A, 0x67, 0x4B, 0x52, 0x0A, 0x7A, 0x33, 0x62, 0x46, 0x6D, 0x78, 0x35, 0x56, 0x64, 0x4A, 0x78, 0x34, 0x49, 0x62, 0x48, 0x77, 0x4C, 0x66, 0x45, 0x4C, 0x6E, 0x38, 0x4C, 0x56, 0x6C, 0x68, 0x67, 0x66, 0x38, 0x46, 0x51, 0x69, ++ 0x65, 0x6F, 0x77, 0x48, 0x41, 0x67, 0x4D, 0x42, 0x41, 0x41, 0x47, 0x6A, 0x66, 0x54, 0x42, 0x37, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x53, 0x6E, 0x70, 0x51, 0x61, 0x78, 0x4C, 0x4B, 0x59, 0x4A, ++ 0x59, 0x4F, 0x37, 0x52, 0x0A, 0x6C, 0x2B, 0x6C, 0x77, 0x72, 0x72, 0x77, 0x37, 0x47, 0x57, 0x7A, 0x62, 0x49, 0x54, 0x41, 0x50, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x52, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x54, 0x41, 0x44, 0x41, 0x51, 0x48, ++ 0x2F, 0x4D, 0x42, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x49, 0x77, 0x51, 0x59, 0x4D, 0x42, 0x61, 0x41, 0x46, 0x4B, 0x65, 0x6C, 0x42, 0x72, 0x45, 0x73, 0x70, 0x67, 0x6C, 0x67, 0x37, 0x74, 0x47, 0x58, 0x36, 0x58, 0x43, 0x75, 0x76, 0x44, 0x73, ++ 0x5A, 0x0A, 0x62, 0x4E, 0x73, 0x68, 0x4D, 0x42, 0x67, 0x47, 0x41, 0x31, 0x55, 0x64, 0x49, 0x41, 0x51, 0x52, 0x4D, 0x41, 0x38, 0x77, 0x44, 0x51, 0x59, 0x4C, 0x4B, 0x77, 0x59, 0x42, 0x42, 0x41, 0x47, 0x77, 0x4C, 0x51, 0x4D, 0x45, 0x41, 0x51, ++ 0x45, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x51, 0x44, 0x41, 0x67, 0x47, 0x47, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x0A, 0x43, ++ 0x77, 0x55, 0x41, 0x41, 0x34, 0x49, 0x42, 0x41, 0x51, 0x41, 0x6D, 0x64, 0x7A, 0x54, 0x62, 0x6C, 0x45, 0x69, 0x47, 0x4B, 0x6B, 0x47, 0x64, 0x4C, 0x44, 0x34, 0x47, 0x6B, 0x47, 0x44, 0x45, 0x6A, 0x4B, 0x77, 0x4C, 0x56, 0x4C, 0x67, 0x66, 0x75, ++ 0x58, 0x76, 0x54, 0x42, 0x7A, 0x6E, 0x6B, 0x2B, 0x6A, 0x35, 0x37, 0x73, 0x6A, 0x31, 0x4F, 0x37, 0x5A, 0x38, 0x6A, 0x76, 0x5A, 0x66, 0x7A, 0x61, 0x31, 0x7A, 0x76, 0x37, 0x76, 0x31, 0x41, 0x70, 0x74, 0x2B, 0x68, 0x0A, 0x6B, 0x36, 0x45, 0x4B, ++ 0x68, 0x71, 0x7A, 0x76, 0x49, 0x4E, 0x42, 0x35, 0x41, 0x62, 0x31, 0x34, 0x39, 0x78, 0x6E, 0x59, 0x4A, 0x44, 0x45, 0x30, 0x42, 0x41, 0x47, 0x6D, 0x75, 0x68, 0x57, 0x61, 0x77, 0x79, 0x66, 0x63, 0x32, 0x45, 0x38, 0x50, 0x7A, 0x42, 0x68, 0x6A, ++ 0x2F, 0x35, 0x6B, 0x50, 0x44, 0x70, 0x46, 0x72, 0x64, 0x52, 0x62, 0x68, 0x49, 0x66, 0x7A, 0x59, 0x4A, 0x73, 0x64, 0x48, 0x74, 0x36, 0x62, 0x50, 0x57, 0x48, 0x4A, 0x78, 0x66, 0x72, 0x72, 0x68, 0x0A, 0x54, 0x5A, 0x56, 0x48, 0x4F, 0x38, 0x6D, ++ 0x76, 0x62, 0x61, 0x47, 0x30, 0x77, 0x65, 0x79, 0x4A, 0x39, 0x72, 0x51, 0x50, 0x4F, 0x4C, 0x58, 0x69, 0x5A, 0x4E, 0x77, 0x6C, 0x7A, 0x36, 0x62, 0x62, 0x36, 0x35, 0x70, 0x63, 0x6D, 0x61, 0x48, 0x46, 0x43, 0x4E, 0x37, 0x39, 0x35, 0x74, 0x72, ++ 0x56, 0x31, 0x6C, 0x70, 0x46, 0x44, 0x4D, 0x53, 0x33, 0x77, 0x72, 0x55, 0x55, 0x37, 0x37, 0x51, 0x52, 0x2F, 0x77, 0x34, 0x56, 0x74, 0x66, 0x58, 0x31, 0x32, 0x38, 0x61, 0x39, 0x0A, 0x36, 0x31, 0x71, 0x6E, 0x38, 0x46, 0x59, 0x69, 0x71, 0x54, ++ 0x78, 0x6C, 0x56, 0x4D, 0x59, 0x56, 0x71, 0x4C, 0x32, 0x47, 0x6E, 0x73, 0x32, 0x44, 0x6C, 0x6D, 0x68, 0x36, 0x63, 0x59, 0x47, 0x4A, 0x34, 0x51, 0x76, 0x68, 0x36, 0x68, 0x45, 0x62, 0x61, 0x41, 0x6A, 0x4D, 0x61, 0x5A, 0x37, 0x73, 0x6E, 0x6B, ++ 0x47, 0x65, 0x52, 0x44, 0x49, 0x6D, 0x65, 0x75, 0x4B, 0x48, 0x43, 0x6E, 0x45, 0x39, 0x36, 0x2B, 0x52, 0x61, 0x70, 0x4E, 0x4C, 0x62, 0x78, 0x63, 0x33, 0x47, 0x0A, 0x33, 0x6D, 0x42, 0x2F, 0x75, 0x66, 0x4E, 0x50, 0x52, 0x4A, 0x4C, 0x76, 0x4B, ++ 0x72, 0x63, 0x59, 0x50, 0x71, 0x63, 0x5A, 0x32, 0x51, 0x74, 0x39, 0x73, 0x54, 0x64, 0x42, 0x51, 0x72, 0x43, 0x36, 0x59, 0x42, 0x33, 0x79, 0x2F, 0x67, 0x6B, 0x52, 0x73, 0x50, 0x43, 0x48, 0x65, 0x36, 0x65, 0x64, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, ++ 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, ++ 0x31, 0x20, 0x47, 0x33, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, ++ 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x59, 0x44, 0x43, 0x43, 0x41, 0x30, 0x69, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x55, 0x65, 0x46, 0x68, 0x66, 0x4C, ++ 0x71, 0x30, 0x73, 0x47, 0x55, 0x76, 0x6A, 0x4E, 0x77, 0x63, 0x31, 0x4E, 0x42, 0x4D, 0x6F, 0x74, 0x5A, 0x62, 0x55, 0x5A, 0x5A, 0x4D, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x42, ++ 0x51, 0x41, 0x77, 0x53, 0x44, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x0A, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x51, 0x6B, 0x30, 0x78, 0x47, 0x54, 0x41, 0x58, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x45, 0x46, 0x46, 0x31, ++ 0x62, 0x31, 0x5A, 0x68, 0x5A, 0x47, 0x6C, 0x7A, 0x49, 0x45, 0x78, 0x70, 0x62, 0x57, 0x6C, 0x30, 0x5A, 0x57, 0x51, 0x78, 0x48, 0x6A, 0x41, 0x63, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x46, 0x56, 0x46, 0x31, 0x62, 0x31, 0x5A, 0x68, ++ 0x5A, 0x47, 0x6C, 0x7A, 0x49, 0x46, 0x4A, 0x76, 0x0A, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x67, 0x4D, 0x53, 0x42, 0x48, 0x4D, 0x7A, 0x41, 0x65, 0x46, 0x77, 0x30, 0x78, 0x4D, 0x6A, 0x41, 0x78, 0x4D, 0x54, 0x49, 0x78, 0x4E, 0x7A, 0x49, ++ 0x33, 0x4E, 0x44, 0x52, 0x61, 0x46, 0x77, 0x30, 0x30, 0x4D, 0x6A, 0x41, 0x78, 0x4D, 0x54, 0x49, 0x78, 0x4E, 0x7A, 0x49, 0x33, 0x4E, 0x44, 0x52, 0x61, 0x4D, 0x45, 0x67, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, ++ 0x54, 0x41, 0x6B, 0x4A, 0x4E, 0x0A, 0x4D, 0x52, 0x6B, 0x77, 0x46, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x45, 0x78, 0x42, 0x52, 0x64, 0x57, 0x39, 0x57, 0x59, 0x57, 0x52, 0x70, 0x63, 0x79, 0x42, 0x4D, 0x61, 0x57, 0x31, 0x70, 0x64, 0x47, ++ 0x56, 0x6B, 0x4D, 0x52, 0x34, 0x77, 0x48, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x56, 0x52, 0x64, 0x57, 0x39, 0x57, 0x59, 0x57, 0x52, 0x70, 0x63, 0x79, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x42, 0x49, 0x44, ++ 0x45, 0x67, 0x0A, 0x52, 0x7A, 0x4D, 0x77, 0x67, 0x67, 0x49, 0x69, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x44, 0x77, 0x41, 0x77, 0x67, ++ 0x67, 0x49, 0x4B, 0x41, 0x6F, 0x49, 0x43, 0x41, 0x51, 0x43, 0x67, 0x76, 0x6C, 0x41, 0x51, 0x6A, 0x75, 0x6E, 0x79, 0x62, 0x45, 0x43, 0x30, 0x42, 0x4A, 0x79, 0x46, 0x75, 0x54, 0x48, 0x4B, 0x33, 0x43, 0x33, 0x6B, 0x45, 0x61, 0x6B, 0x45, 0x0A, ++ 0x50, 0x42, 0x74, 0x56, 0x77, 0x65, 0x64, 0x59, 0x4D, 0x42, 0x30, 0x6B, 0x74, 0x4D, 0x50, 0x76, 0x68, 0x64, 0x36, 0x4D, 0x4C, 0x4F, 0x48, 0x42, 0x50, 0x64, 0x2B, 0x43, 0x35, 0x6B, 0x2B, 0x74, 0x52, 0x34, 0x64, 0x73, 0x37, 0x46, 0x74, 0x4A, ++ 0x77, 0x55, 0x72, 0x56, 0x75, 0x34, 0x2F, 0x73, 0x68, 0x36, 0x78, 0x2F, 0x67, 0x70, 0x71, 0x47, 0x37, 0x44, 0x30, 0x44, 0x6D, 0x56, 0x49, 0x42, 0x30, 0x6A, 0x57, 0x65, 0x72, 0x4E, 0x72, 0x77, 0x55, 0x38, 0x6C, 0x6D, 0x0A, 0x50, 0x4E, 0x53, ++ 0x73, 0x41, 0x67, 0x48, 0x61, 0x4A, 0x4E, 0x4D, 0x37, 0x71, 0x41, 0x4A, 0x47, 0x72, 0x36, 0x51, 0x63, 0x34, 0x2F, 0x68, 0x7A, 0x57, 0x48, 0x61, 0x33, 0x39, 0x67, 0x36, 0x51, 0x44, 0x62, 0x58, 0x77, 0x7A, 0x38, 0x7A, 0x36, 0x2B, 0x63, 0x5A, ++ 0x4D, 0x35, 0x63, 0x4F, 0x47, 0x4D, 0x41, 0x71, 0x4E, 0x46, 0x33, 0x34, 0x31, 0x36, 0x38, 0x58, 0x66, 0x75, 0x77, 0x36, 0x63, 0x77, 0x49, 0x32, 0x48, 0x34, 0x34, 0x67, 0x34, 0x68, 0x57, 0x66, 0x36, 0x0A, 0x50, 0x73, 0x65, 0x72, 0x34, 0x42, ++ 0x4F, 0x63, 0x42, 0x52, 0x69, 0x59, 0x7A, 0x35, 0x50, 0x31, 0x73, 0x5A, 0x4B, 0x30, 0x2F, 0x43, 0x50, 0x54, 0x7A, 0x39, 0x58, 0x45, 0x4A, 0x30, 0x6E, 0x67, 0x6E, 0x6A, 0x79, 0x62, 0x43, 0x4B, 0x4F, 0x4C, 0x58, 0x53, 0x6F, 0x68, 0x34, 0x50, ++ 0x77, 0x35, 0x71, 0x6C, 0x50, 0x61, 0x66, 0x58, 0x37, 0x50, 0x47, 0x67, 0x6C, 0x54, 0x76, 0x46, 0x30, 0x46, 0x42, 0x4D, 0x2B, 0x68, 0x53, 0x6F, 0x2B, 0x4C, 0x64, 0x6F, 0x49, 0x4E, 0x0A, 0x6F, 0x66, 0x6A, 0x53, 0x78, 0x78, 0x52, 0x33, 0x57, ++ 0x35, 0x41, 0x32, 0x42, 0x34, 0x47, 0x62, 0x50, 0x67, 0x62, 0x36, 0x55, 0x6C, 0x35, 0x6A, 0x78, 0x61, 0x59, 0x41, 0x2F, 0x71, 0x58, 0x70, 0x55, 0x68, 0x74, 0x53, 0x74, 0x5A, 0x49, 0x35, 0x63, 0x67, 0x4D, 0x4A, 0x59, 0x72, 0x32, 0x77, 0x59, ++ 0x42, 0x5A, 0x75, 0x70, 0x74, 0x30, 0x6C, 0x77, 0x67, 0x4E, 0x6D, 0x33, 0x66, 0x4D, 0x45, 0x30, 0x55, 0x44, 0x69, 0x54, 0x6F, 0x75, 0x47, 0x39, 0x47, 0x2F, 0x6C, 0x0A, 0x67, 0x36, 0x41, 0x6E, 0x68, 0x46, 0x34, 0x45, 0x77, 0x66, 0x57, 0x51, ++ 0x76, 0x54, 0x41, 0x39, 0x78, 0x4F, 0x2B, 0x6F, 0x61, 0x62, 0x77, 0x34, 0x6D, 0x36, 0x53, 0x6B, 0x6C, 0x74, 0x46, 0x69, 0x32, 0x6D, 0x6E, 0x41, 0x41, 0x5A, 0x61, 0x75, 0x79, 0x38, 0x52, 0x52, 0x4E, 0x4F, 0x6F, 0x4D, 0x71, 0x76, 0x38, 0x68, ++ 0x6A, 0x6C, 0x6D, 0x50, 0x53, 0x6C, 0x7A, 0x6B, 0x59, 0x5A, 0x71, 0x6E, 0x30, 0x75, 0x6B, 0x71, 0x65, 0x49, 0x31, 0x52, 0x50, 0x54, 0x6F, 0x56, 0x0A, 0x37, 0x71, 0x4A, 0x5A, 0x6A, 0x71, 0x6C, 0x63, 0x33, 0x73, 0x58, 0x35, 0x6B, 0x43, 0x4C, ++ 0x6C, 0x69, 0x45, 0x56, 0x78, 0x33, 0x5A, 0x47, 0x5A, 0x62, 0x48, 0x71, 0x66, 0x50, 0x54, 0x32, 0x59, 0x66, 0x46, 0x37, 0x32, 0x76, 0x68, 0x5A, 0x6F, 0x6F, 0x46, 0x36, 0x75, 0x43, 0x79, 0x50, 0x38, 0x57, 0x67, 0x2B, 0x71, 0x49, 0x6E, 0x59, ++ 0x74, 0x79, 0x61, 0x45, 0x51, 0x48, 0x65, 0x54, 0x54, 0x52, 0x43, 0x4F, 0x51, 0x69, 0x4A, 0x2F, 0x47, 0x4B, 0x75, 0x62, 0x58, 0x0A, 0x39, 0x5A, 0x71, 0x7A, 0x57, 0x42, 0x34, 0x76, 0x4D, 0x49, 0x6B, 0x49, 0x47, 0x31, 0x53, 0x69, 0x74, 0x5A, ++ 0x67, 0x6A, 0x37, 0x41, 0x68, 0x33, 0x48, 0x4A, 0x56, 0x64, 0x59, 0x64, 0x48, 0x4C, 0x69, 0x5A, 0x78, 0x66, 0x6F, 0x6B, 0x71, 0x52, 0x6D, 0x75, 0x38, 0x68, 0x71, 0x6B, 0x6B, 0x57, 0x43, 0x4B, 0x69, 0x39, 0x59, 0x53, 0x67, 0x78, 0x79, 0x58, ++ 0x53, 0x74, 0x68, 0x66, 0x62, 0x5A, 0x78, 0x62, 0x47, 0x4C, 0x30, 0x65, 0x55, 0x51, 0x4D, 0x6B, 0x31, 0x66, 0x0A, 0x69, 0x79, 0x41, 0x36, 0x50, 0x45, 0x6B, 0x66, 0x4D, 0x34, 0x56, 0x5A, 0x44, 0x64, 0x76, 0x4C, 0x43, 0x58, 0x56, 0x44, 0x61, ++ 0x58, 0x50, 0x37, 0x61, 0x33, 0x46, 0x39, 0x38, 0x4E, 0x2F, 0x45, 0x54, 0x48, 0x33, 0x47, 0x6F, 0x79, 0x37, 0x49, 0x6C, 0x58, 0x6E, 0x4C, 0x63, 0x36, 0x4B, 0x4F, 0x54, 0x6B, 0x30, 0x6B, 0x2B, 0x31, 0x37, 0x6B, 0x42, 0x4C, 0x35, 0x79, 0x47, ++ 0x36, 0x59, 0x6E, 0x4C, 0x55, 0x6C, 0x61, 0x6D, 0x58, 0x72, 0x58, 0x58, 0x41, 0x6B, 0x67, 0x0A, 0x74, 0x33, 0x2B, 0x55, 0x75, 0x55, 0x2F, 0x78, 0x44, 0x52, 0x78, 0x65, 0x69, 0x45, 0x49, 0x62, 0x45, 0x62, 0x66, 0x6E, 0x6B, 0x64, 0x75, 0x65, ++ 0x62, 0x50, 0x52, 0x71, 0x33, 0x34, 0x77, 0x47, 0x6D, 0x41, 0x4F, 0x74, 0x7A, 0x43, 0x6A, 0x76, 0x70, 0x55, 0x66, 0x7A, 0x55, 0x77, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x6F, 0x30, 0x49, 0x77, 0x51, 0x44, 0x41, 0x50, 0x42, 0x67, 0x4E, 0x56, ++ 0x48, 0x52, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x54, 0x41, 0x44, 0x0A, 0x41, 0x51, 0x48, 0x2F, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x42, 0x42, 0x6A, 0x41, ++ 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x6F, 0x35, 0x66, 0x57, 0x38, 0x31, 0x36, 0x69, 0x45, 0x4F, 0x47, 0x72, 0x52, 0x5A, 0x38, 0x38, 0x46, 0x32, 0x51, 0x38, 0x37, 0x67, 0x46, 0x77, 0x6E, 0x4D, 0x77, ++ 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x0A, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x42, 0x41, 0x42, 0x6A, 0x36, 0x57, 0x33, 0x58, 0x38, 0x50, 0x6E, 0x72, 0x48, 0x58, 0x33, ++ 0x66, 0x48, 0x79, 0x74, 0x2F, 0x50, 0x58, 0x38, 0x4D, 0x53, 0x78, 0x45, 0x42, 0x64, 0x31, 0x44, 0x4B, 0x71, 0x75, 0x47, 0x72, 0x58, 0x31, 0x52, 0x55, 0x56, 0x52, 0x70, 0x67, 0x6A, 0x70, 0x65, 0x61, 0x51, 0x57, 0x78, 0x69, 0x5A, 0x54, 0x4F, ++ 0x4F, 0x74, 0x51, 0x71, 0x4F, 0x43, 0x0A, 0x4D, 0x54, 0x61, 0x49, 0x7A, 0x65, 0x6E, 0x37, 0x78, 0x41, 0x53, 0x57, 0x53, 0x49, 0x73, 0x42, 0x78, 0x34, 0x30, 0x42, 0x7A, 0x31, 0x73, 0x7A, 0x42, 0x70, 0x5A, 0x47, 0x5A, 0x6E, 0x51, 0x64, 0x54, ++ 0x2B, 0x33, 0x42, 0x74, 0x72, 0x6D, 0x30, 0x44, 0x57, 0x48, 0x4D, 0x59, 0x33, 0x37, 0x58, 0x4C, 0x6E, 0x65, 0x4D, 0x6C, 0x68, 0x77, 0x71, 0x49, 0x32, 0x68, 0x72, 0x68, 0x56, 0x64, 0x32, 0x63, 0x44, 0x4D, 0x54, 0x2F, 0x75, 0x46, 0x50, 0x70, ++ 0x69, 0x4E, 0x33, 0x0A, 0x47, 0x50, 0x6F, 0x61, 0x6A, 0x4F, 0x69, 0x39, 0x5A, 0x63, 0x6E, 0x50, 0x50, 0x2F, 0x54, 0x4A, 0x46, 0x39, 0x7A, 0x72, 0x78, 0x37, 0x7A, 0x41, 0x42, 0x43, 0x34, 0x74, 0x52, 0x69, 0x39, 0x70, 0x5A, 0x73, 0x4D, 0x62, ++ 0x6A, 0x2F, 0x37, 0x73, 0x50, 0x74, 0x50, 0x4B, 0x6C, 0x4C, 0x39, 0x32, 0x43, 0x69, 0x55, 0x4E, 0x71, 0x58, 0x73, 0x43, 0x48, 0x4B, 0x6E, 0x51, 0x4F, 0x31, 0x38, 0x4C, 0x77, 0x49, 0x45, 0x36, 0x50, 0x57, 0x54, 0x68, 0x76, 0x36, 0x63, 0x74, ++ 0x0A, 0x54, 0x72, 0x31, 0x4E, 0x78, 0x4E, 0x67, 0x70, 0x78, 0x69, 0x49, 0x59, 0x30, 0x4D, 0x57, 0x73, 0x63, 0x67, 0x4B, 0x43, 0x50, 0x36, 0x6F, 0x36, 0x6F, 0x6A, 0x6F, 0x69, 0x6C, 0x7A, 0x48, 0x64, 0x43, 0x47, 0x50, 0x44, 0x64, 0x52, 0x53, ++ 0x35, 0x59, 0x43, 0x67, 0x74, 0x57, 0x32, 0x6A, 0x67, 0x46, 0x71, 0x6C, 0x6D, 0x67, 0x69, 0x4E, 0x52, 0x39, 0x65, 0x74, 0x54, 0x32, 0x44, 0x47, 0x62, 0x65, 0x2B, 0x6D, 0x33, 0x6E, 0x55, 0x76, 0x72, 0x69, 0x42, 0x62, 0x50, 0x0A, 0x2B, 0x56, ++ 0x30, 0x34, 0x69, 0x6B, 0x6B, 0x77, 0x6A, 0x2B, 0x33, 0x78, 0x36, 0x78, 0x6E, 0x30, 0x64, 0x78, 0x6F, 0x78, 0x47, 0x45, 0x31, 0x6E, 0x56, 0x47, 0x77, 0x76, 0x62, 0x32, 0x58, 0x35, 0x32, 0x7A, 0x33, 0x73, 0x49, 0x65, 0x78, 0x65, 0x39, 0x50, ++ 0x53, 0x4C, 0x79, 0x6D, 0x42, 0x6C, 0x56, 0x4E, 0x46, 0x78, 0x5A, 0x50, 0x54, 0x35, 0x70, 0x71, 0x4F, 0x42, 0x4D, 0x7A, 0x59, 0x7A, 0x63, 0x66, 0x43, 0x6B, 0x65, 0x46, 0x39, 0x4F, 0x72, 0x59, 0x4D, 0x68, 0x0A, 0x33, 0x6A, 0x52, 0x4A, 0x6A, ++ 0x65, 0x68, 0x5A, 0x72, 0x4A, 0x33, 0x79, 0x64, 0x6C, 0x6F, 0x32, 0x38, 0x68, 0x50, 0x30, 0x72, 0x2B, 0x41, 0x4A, 0x78, 0x32, 0x45, 0x71, 0x62, 0x50, 0x66, 0x67, 0x6E, 0x61, 0x36, 0x37, 0x68, 0x6B, 0x6F, 0x6F, 0x62, 0x79, 0x37, 0x75, 0x74, ++ 0x48, 0x6E, 0x4E, 0x6B, 0x44, 0x50, 0x44, 0x73, 0x33, 0x62, 0x36, 0x39, 0x66, 0x42, 0x73, 0x6E, 0x51, 0x47, 0x51, 0x2B, 0x70, 0x36, 0x51, 0x39, 0x70, 0x78, 0x79, 0x7A, 0x30, 0x66, 0x61, 0x0A, 0x77, 0x78, 0x2F, 0x6B, 0x4E, 0x53, 0x42, 0x54, ++ 0x38, 0x6C, 0x54, 0x52, 0x33, 0x32, 0x47, 0x44, 0x70, 0x67, 0x4C, 0x69, 0x4A, 0x54, 0x6A, 0x65, 0x68, 0x54, 0x49, 0x74, 0x58, 0x6E, 0x4F, 0x51, 0x55, 0x6C, 0x31, 0x43, 0x78, 0x4D, 0x34, 0x39, 0x53, 0x2B, 0x48, 0x35, 0x47, 0x59, 0x51, 0x64, ++ 0x31, 0x61, 0x4A, 0x51, 0x7A, 0x45, 0x48, 0x37, 0x51, 0x52, 0x54, 0x44, 0x76, 0x64, 0x62, 0x4A, 0x57, 0x71, 0x4E, 0x6A, 0x5A, 0x67, 0x4B, 0x41, 0x76, 0x51, 0x55, 0x36, 0x0A, 0x4F, 0x30, 0x65, 0x63, 0x37, 0x41, 0x41, 0x6D, 0x54, 0x50, 0x57, ++ 0x49, 0x55, 0x62, 0x2B, 0x6F, 0x49, 0x33, 0x38, 0x59, 0x42, 0x37, 0x41, 0x4C, 0x37, 0x59, 0x73, 0x6D, 0x6F, 0x57, 0x54, 0x54, 0x59, 0x55, 0x72, 0x72, 0x58, 0x4A, 0x2F, 0x65, 0x73, 0x36, 0x39, 0x6E, 0x41, 0x37, 0x4D, 0x66, 0x33, 0x57, 0x31, ++ 0x64, 0x61, 0x57, 0x68, 0x70, 0x71, 0x31, 0x34, 0x36, 0x37, 0x48, 0x78, 0x70, 0x76, 0x4D, 0x63, 0x37, 0x68, 0x55, 0x36, 0x65, 0x46, 0x62, 0x6D, 0x30, 0x0A, 0x46, 0x55, 0x2F, 0x44, 0x6C, 0x58, 0x70, 0x59, 0x31, 0x38, 0x6C, 0x73, 0x36, 0x57, ++ 0x79, 0x35, 0x38, 0x79, 0x6C, 0x6A, 0x58, 0x72, 0x51, 0x73, 0x38, 0x43, 0x30, 0x39, 0x37, 0x56, 0x70, 0x6C, 0x34, 0x4B, 0x6C, 0x62, 0x51, 0x4D, 0x4A, 0x49, 0x6D, 0x59, 0x46, 0x74, 0x6E, 0x68, 0x38, 0x47, 0x4B, 0x6A, 0x77, 0x53, 0x74, 0x49, ++ 0x73, 0x50, 0x6D, 0x36, 0x49, 0x6B, 0x38, 0x4B, 0x61, 0x4E, 0x31, 0x6E, 0x72, 0x67, 0x53, 0x37, 0x5A, 0x6B, 0x6C, 0x6D, 0x4F, 0x56, 0x0A, 0x68, 0x4D, 0x4A, 0x4B, 0x7A, 0x52, 0x77, 0x75, 0x4A, 0x49, 0x63, 0x7A, 0x59, 0x4F, 0x58, 0x44, 0x0A, ++ 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, ++ 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, 0x47, 0x33, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, ++ 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x59, 0x44, 0x43, 0x43, 0x41, 0x30, 0x69, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x55, 0x52, ++ 0x46, 0x63, 0x30, 0x4A, 0x46, 0x75, 0x42, 0x69, 0x5A, 0x73, 0x31, 0x38, 0x73, 0x36, 0x34, 0x4B, 0x7A, 0x74, 0x62, 0x70, 0x79, 0x62, 0x77, 0x64, 0x53, 0x67, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, ++ 0x51, 0x45, 0x4C, 0x42, 0x51, 0x41, 0x77, 0x53, 0x44, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x0A, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x51, 0x6B, 0x30, 0x78, 0x47, 0x54, 0x41, 0x58, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, ++ 0x45, 0x46, 0x46, 0x31, 0x62, 0x31, 0x5A, 0x68, 0x5A, 0x47, 0x6C, 0x7A, 0x49, 0x45, 0x78, 0x70, 0x62, 0x57, 0x6C, 0x30, 0x5A, 0x57, 0x51, 0x78, 0x48, 0x6A, 0x41, 0x63, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x46, 0x56, 0x46, 0x31, ++ 0x62, 0x31, 0x5A, 0x68, 0x5A, 0x47, 0x6C, 0x7A, 0x49, 0x46, 0x4A, 0x76, 0x0A, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x67, 0x4D, 0x69, 0x42, 0x48, 0x4D, 0x7A, 0x41, 0x65, 0x46, 0x77, 0x30, 0x78, 0x4D, 0x6A, 0x41, 0x78, 0x4D, 0x54, 0x49, ++ 0x78, 0x4F, 0x44, 0x55, 0x35, 0x4D, 0x7A, 0x4A, 0x61, 0x46, 0x77, 0x30, 0x30, 0x4D, 0x6A, 0x41, 0x78, 0x4D, 0x54, 0x49, 0x78, 0x4F, 0x44, 0x55, 0x35, 0x4D, 0x7A, 0x4A, 0x61, 0x4D, 0x45, 0x67, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, ++ 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6B, 0x4A, 0x4E, 0x0A, 0x4D, 0x52, 0x6B, 0x77, 0x46, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x45, 0x78, 0x42, 0x52, 0x64, 0x57, 0x39, 0x57, 0x59, 0x57, 0x52, 0x70, 0x63, 0x79, 0x42, 0x4D, 0x61, 0x57, ++ 0x31, 0x70, 0x64, 0x47, 0x56, 0x6B, 0x4D, 0x52, 0x34, 0x77, 0x48, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x56, 0x52, 0x64, 0x57, 0x39, 0x57, 0x59, 0x57, 0x52, 0x70, 0x63, 0x79, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, ++ 0x4E, 0x42, 0x49, 0x44, 0x49, 0x67, 0x0A, 0x52, 0x7A, 0x4D, 0x77, 0x67, 0x67, 0x49, 0x69, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x44, ++ 0x77, 0x41, 0x77, 0x67, 0x67, 0x49, 0x4B, 0x41, 0x6F, 0x49, 0x43, 0x41, 0x51, 0x43, 0x68, 0x72, 0x69, 0x57, 0x79, 0x41, 0x52, 0x6A, 0x63, 0x56, 0x34, 0x67, 0x2F, 0x52, 0x75, 0x76, 0x35, 0x72, 0x2B, 0x4C, 0x72, 0x49, 0x33, 0x48, 0x69, 0x6D, ++ 0x74, 0x46, 0x68, 0x0A, 0x5A, 0x69, 0x46, 0x66, 0x71, 0x71, 0x38, 0x6E, 0x55, 0x65, 0x56, 0x75, 0x47, 0x78, 0x62, 0x55, 0x4C, 0x58, 0x31, 0x51, 0x73, 0x46, 0x4E, 0x33, 0x76, 0x58, 0x67, 0x36, 0x59, 0x4F, 0x4A, 0x6B, 0x41, 0x70, 0x74, 0x38, ++ 0x68, 0x70, 0x76, 0x57, 0x47, 0x6F, 0x36, 0x74, 0x2F, 0x78, 0x38, 0x56, 0x66, 0x39, 0x57, 0x56, 0x48, 0x68, 0x4C, 0x4C, 0x35, 0x68, 0x53, 0x45, 0x42, 0x4D, 0x48, 0x66, 0x4E, 0x72, 0x4D, 0x57, 0x6E, 0x34, 0x72, 0x6A, 0x79, 0x64, 0x75, 0x59, ++ 0x0A, 0x4E, 0x4D, 0x37, 0x59, 0x4D, 0x78, 0x63, 0x6F, 0x52, 0x76, 0x79, 0x6E, 0x79, 0x66, 0x44, 0x53, 0x74, 0x4E, 0x56, 0x4E, 0x43, 0x58, 0x4A, 0x4A, 0x2B, 0x66, 0x4B, 0x48, 0x34, 0x36, 0x6E, 0x61, 0x66, 0x61, 0x46, 0x39, 0x61, 0x37, 0x49, ++ 0x36, 0x4A, 0x61, 0x6C, 0x74, 0x55, 0x6B, 0x53, 0x73, 0x2B, 0x4C, 0x35, 0x75, 0x2B, 0x39, 0x79, 0x6D, 0x63, 0x35, 0x47, 0x51, 0x59, 0x61, 0x59, 0x44, 0x46, 0x43, 0x44, 0x79, 0x35, 0x34, 0x65, 0x6A, 0x69, 0x4B, 0x32, 0x74, 0x0A, 0x6F, 0x49, ++ 0x7A, 0x2F, 0x70, 0x67, 0x73, 0x6C, 0x55, 0x69, 0x58, 0x6E, 0x46, 0x67, 0x48, 0x56, 0x79, 0x37, 0x67, 0x31, 0x67, 0x51, 0x79, 0x6A, 0x4F, 0x2F, 0x44, 0x68, 0x34, 0x66, 0x78, 0x61, 0x58, 0x63, 0x36, 0x41, 0x63, 0x57, 0x33, 0x34, 0x53, 0x61, ++ 0x73, 0x2B, 0x4F, 0x37, 0x71, 0x34, 0x31, 0x34, 0x41, 0x42, 0x2B, 0x36, 0x58, 0x72, 0x57, 0x37, 0x50, 0x46, 0x58, 0x6D, 0x41, 0x71, 0x4D, 0x61, 0x43, 0x76, 0x4E, 0x2B, 0x67, 0x67, 0x4F, 0x70, 0x2B, 0x6F, 0x0A, 0x4D, 0x69, 0x77, 0x4D, 0x7A, ++ 0x41, 0x6B, 0x64, 0x30, 0x35, 0x36, 0x4F, 0x58, 0x62, 0x78, 0x4D, 0x6D, 0x4F, 0x37, 0x46, 0x47, 0x6D, 0x68, 0x37, 0x37, 0x46, 0x4F, 0x6D, 0x36, 0x52, 0x51, 0x31, 0x6F, 0x39, 0x2F, 0x4E, 0x67, 0x4A, 0x38, 0x4D, 0x53, 0x50, 0x73, 0x63, 0x39, ++ 0x50, 0x47, 0x2F, 0x53, 0x72, 0x6A, 0x36, 0x31, 0x59, 0x78, 0x78, 0x53, 0x73, 0x63, 0x66, 0x72, 0x66, 0x35, 0x42, 0x6D, 0x72, 0x4F, 0x44, 0x58, 0x66, 0x4B, 0x45, 0x56, 0x75, 0x2B, 0x6C, 0x0A, 0x56, 0x30, 0x50, 0x4F, 0x4B, 0x61, 0x32, 0x4D, ++ 0x71, 0x31, 0x57, 0x2F, 0x78, 0x50, 0x74, 0x62, 0x41, 0x64, 0x30, 0x6A, 0x49, 0x61, 0x46, 0x59, 0x41, 0x49, 0x37, 0x44, 0x30, 0x47, 0x6F, 0x54, 0x37, 0x52, 0x50, 0x6A, 0x45, 0x69, 0x75, 0x41, 0x33, 0x47, 0x66, 0x6D, 0x6C, 0x62, 0x4C, 0x4E, ++ 0x48, 0x69, 0x4A, 0x75, 0x4B, 0x76, 0x68, 0x42, 0x31, 0x50, 0x4C, 0x4B, 0x46, 0x41, 0x65, 0x4E, 0x69, 0x6C, 0x55, 0x53, 0x78, 0x6D, 0x6E, 0x31, 0x75, 0x49, 0x5A, 0x6F, 0x0A, 0x4C, 0x31, 0x4E, 0x65, 0x73, 0x4E, 0x4B, 0x71, 0x49, 0x63, 0x47, ++ 0x59, 0x35, 0x6A, 0x44, 0x6A, 0x5A, 0x31, 0x58, 0x48, 0x6D, 0x32, 0x36, 0x73, 0x47, 0x61, 0x68, 0x56, 0x70, 0x6B, 0x55, 0x47, 0x30, 0x43, 0x4D, 0x36, 0x32, 0x2B, 0x74, 0x6C, 0x58, 0x53, 0x6F, 0x52, 0x45, 0x66, 0x41, 0x37, 0x54, 0x38, 0x70, ++ 0x74, 0x39, 0x44, 0x54, 0x45, 0x63, 0x65, 0x54, 0x2F, 0x41, 0x46, 0x72, 0x32, 0x58, 0x4B, 0x34, 0x6A, 0x59, 0x49, 0x56, 0x7A, 0x38, 0x65, 0x51, 0x51, 0x0A, 0x73, 0x53, 0x57, 0x75, 0x31, 0x5A, 0x4B, 0x37, 0x45, 0x38, 0x45, 0x4D, 0x34, 0x44, ++ 0x6E, 0x61, 0x74, 0x44, 0x6C, 0x58, 0x74, 0x61, 0x73, 0x31, 0x71, 0x6E, 0x49, 0x68, 0x4F, 0x34, 0x4D, 0x31, 0x35, 0x7A, 0x48, 0x66, 0x65, 0x69, 0x46, 0x75, 0x75, 0x44, 0x49, 0x49, 0x66, 0x52, 0x30, 0x79, 0x6B, 0x52, 0x56, 0x4B, 0x59, 0x6E, ++ 0x4C, 0x50, 0x34, 0x33, 0x65, 0x68, 0x76, 0x4E, 0x55, 0x52, 0x47, 0x33, 0x59, 0x42, 0x5A, 0x77, 0x6A, 0x67, 0x51, 0x51, 0x76, 0x44, 0x0A, 0x36, 0x78, 0x56, 0x75, 0x2B, 0x4B, 0x51, 0x5A, 0x32, 0x61, 0x4B, 0x72, 0x72, 0x2B, 0x49, 0x6E, 0x55, ++ 0x6C, 0x59, 0x72, 0x41, 0x6F, 0x6F, 0x73, 0x46, 0x43, 0x54, 0x35, 0x76, 0x30, 0x49, 0x43, 0x76, 0x79, 0x62, 0x49, 0x78, 0x6F, 0x2F, 0x67, 0x62, 0x6A, 0x68, 0x39, 0x55, 0x79, 0x33, 0x6C, 0x37, 0x5A, 0x69, 0x7A, 0x6C, 0x57, 0x4E, 0x6F, 0x66, ++ 0x2F, 0x6B, 0x31, 0x39, 0x4E, 0x2B, 0x49, 0x78, 0x57, 0x41, 0x31, 0x6B, 0x73, 0x42, 0x38, 0x61, 0x52, 0x78, 0x68, 0x0A, 0x6C, 0x52, 0x62, 0x51, 0x36, 0x39, 0x34, 0x4C, 0x72, 0x7A, 0x34, 0x45, 0x45, 0x45, 0x56, 0x6C, 0x57, 0x46, 0x41, 0x34, ++ 0x72, 0x30, 0x6A, 0x79, 0x57, 0x62, 0x59, 0x57, 0x38, 0x6A, 0x77, 0x4E, 0x6B, 0x41, 0x4C, 0x47, 0x63, 0x43, 0x34, 0x42, 0x72, 0x54, 0x77, 0x56, 0x31, 0x77, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x6F, 0x30, 0x49, 0x77, 0x51, 0x44, 0x41, 0x50, ++ 0x42, 0x67, 0x4E, 0x56, 0x48, 0x52, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x54, 0x41, 0x44, 0x0A, 0x41, 0x51, 0x48, 0x2F, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, ++ 0x42, 0x42, 0x6A, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x37, 0x65, 0x64, 0x76, 0x64, 0x6C, 0x71, 0x2F, 0x59, 0x4F, 0x78, 0x4A, 0x57, 0x38, 0x61, 0x6C, 0x64, 0x37, 0x74, 0x79, 0x46, 0x6E, 0x47, ++ 0x62, 0x78, 0x44, 0x30, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x0A, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x42, 0x41, 0x4A, 0x48, 0x66, 0x67, 0x44, 0x39, 0x44, 0x43, 0x58, ++ 0x35, 0x78, 0x77, 0x76, 0x66, 0x72, 0x73, 0x34, 0x69, 0x50, 0x34, 0x56, 0x47, 0x79, 0x76, 0x44, 0x31, 0x31, 0x2B, 0x53, 0x68, 0x64, 0x79, 0x4C, 0x79, 0x5A, 0x6D, 0x33, 0x74, 0x64, 0x71, 0x75, 0x58, 0x4B, 0x34, 0x51, 0x72, 0x33, 0x36, 0x4C, ++ 0x4C, 0x54, 0x6E, 0x39, 0x31, 0x6E, 0x4D, 0x58, 0x36, 0x36, 0x0A, 0x41, 0x61, 0x72, 0x48, 0x61, 0x6B, 0x45, 0x37, 0x6B, 0x4E, 0x51, 0x49, 0x58, 0x4C, 0x4A, 0x67, 0x61, 0x70, 0x44, 0x77, 0x79, 0x4D, 0x34, 0x44, 0x59, 0x76, 0x6D, 0x4C, 0x37, ++ 0x66, 0x74, 0x75, 0x4B, 0x74, 0x77, 0x47, 0x54, 0x54, 0x77, 0x70, 0x44, 0x34, 0x6B, 0x57, 0x69, 0x6C, 0x68, 0x4D, 0x53, 0x41, 0x2F, 0x6F, 0x68, 0x47, 0x48, 0x71, 0x50, 0x48, 0x4B, 0x6D, 0x64, 0x2B, 0x52, 0x43, 0x72, 0x6F, 0x69, 0x6A, 0x51, ++ 0x31, 0x68, 0x35, 0x66, 0x71, 0x37, 0x4B, 0x0A, 0x70, 0x56, 0x4D, 0x4E, 0x71, 0x54, 0x31, 0x77, 0x76, 0x53, 0x41, 0x5A, 0x59, 0x61, 0x52, 0x73, 0x4F, 0x50, 0x78, 0x44, 0x4D, 0x75, 0x48, 0x42, 0x52, 0x2F, 0x2F, 0x34, 0x37, 0x50, 0x45, 0x52, ++ 0x49, 0x6A, 0x4B, 0x57, 0x6E, 0x4D, 0x4C, 0x32, 0x57, 0x32, 0x6D, 0x57, 0x65, 0x79, 0x41, 0x4D, 0x51, 0x30, 0x47, 0x61, 0x57, 0x2F, 0x5A, 0x5A, 0x47, 0x59, 0x6A, 0x65, 0x56, 0x59, 0x67, 0x33, 0x55, 0x51, 0x74, 0x34, 0x58, 0x41, 0x6F, 0x65, ++ 0x6F, 0x30, 0x4C, 0x39, 0x0A, 0x78, 0x35, 0x32, 0x49, 0x44, 0x38, 0x44, 0x79, 0x65, 0x41, 0x49, 0x6B, 0x56, 0x4A, 0x4F, 0x76, 0x69, 0x59, 0x65, 0x49, 0x79, 0x55, 0x71, 0x41, 0x48, 0x65, 0x72, 0x51, 0x62, 0x6A, 0x35, 0x68, 0x4C, 0x6A, 0x61, ++ 0x37, 0x4E, 0x51, 0x34, 0x6E, 0x6C, 0x76, 0x31, 0x6D, 0x4E, 0x44, 0x74, 0x68, 0x63, 0x6E, 0x50, 0x78, 0x46, 0x6C, 0x78, 0x48, 0x42, 0x6C, 0x52, 0x4A, 0x41, 0x48, 0x70, 0x59, 0x45, 0x72, 0x41, 0x4B, 0x37, 0x34, 0x58, 0x39, 0x73, 0x62, 0x67, ++ 0x7A, 0x0A, 0x64, 0x57, 0x71, 0x54, 0x48, 0x42, 0x4C, 0x6D, 0x59, 0x46, 0x35, 0x76, 0x48, 0x58, 0x2F, 0x4A, 0x48, 0x79, 0x50, 0x4C, 0x68, 0x47, 0x47, 0x66, 0x48, 0x6F, 0x4A, 0x45, 0x2B, 0x56, 0x2B, 0x74, 0x59, 0x6C, 0x55, 0x6B, 0x6D, 0x6C, ++ 0x4B, 0x59, 0x37, 0x56, 0x48, 0x6E, 0x6F, 0x58, 0x36, 0x58, 0x4F, 0x75, 0x59, 0x76, 0x48, 0x78, 0x48, 0x61, 0x55, 0x34, 0x41, 0x73, 0x68, 0x5A, 0x36, 0x72, 0x4E, 0x52, 0x44, 0x62, 0x49, 0x6C, 0x39, 0x71, 0x78, 0x56, 0x36, 0x58, 0x0A, 0x55, ++ 0x2F, 0x49, 0x79, 0x41, 0x67, 0x6B, 0x77, 0x6F, 0x31, 0x6A, 0x77, 0x44, 0x51, 0x48, 0x56, 0x63, 0x73, 0x61, 0x78, 0x66, 0x47, 0x6C, 0x37, 0x77, 0x2F, 0x55, 0x32, 0x52, 0x63, 0x78, 0x68, 0x62, 0x6C, 0x35, 0x4D, 0x6C, 0x4D, 0x56, 0x65, 0x72, ++ 0x75, 0x67, 0x4F, 0x58, 0x6F, 0x75, 0x2F, 0x39, 0x38, 0x33, 0x67, 0x37, 0x61, 0x45, 0x4F, 0x47, 0x7A, 0x50, 0x75, 0x56, 0x42, 0x6A, 0x2B, 0x44, 0x37, 0x37, 0x76, 0x66, 0x6F, 0x52, 0x72, 0x51, 0x2B, 0x4E, 0x77, 0x0A, 0x6D, 0x4E, 0x74, 0x64, ++ 0x64, 0x62, 0x49, 0x4E, 0x57, 0x51, 0x65, 0x46, 0x46, 0x53, 0x4D, 0x35, 0x31, 0x76, 0x48, 0x66, 0x71, 0x53, 0x59, 0x50, 0x31, 0x6B, 0x6A, 0x48, 0x73, 0x36, 0x59, 0x69, 0x39, 0x54, 0x4D, 0x33, 0x57, 0x70, 0x56, 0x48, 0x6E, 0x33, 0x75, 0x36, ++ 0x47, 0x42, 0x56, 0x76, 0x2F, 0x39, 0x59, 0x55, 0x5A, 0x49, 0x4E, 0x4A, 0x30, 0x67, 0x70, 0x6E, 0x49, 0x64, 0x73, 0x50, 0x4E, 0x57, 0x4E, 0x67, 0x4B, 0x43, 0x4C, 0x6A, 0x73, 0x5A, 0x57, 0x44, 0x0A, 0x7A, 0x59, 0x57, 0x6D, 0x33, 0x53, 0x38, ++ 0x50, 0x35, 0x32, 0x64, 0x53, 0x62, 0x72, 0x73, 0x76, 0x68, 0x58, 0x7A, 0x31, 0x53, 0x6E, 0x50, 0x6E, 0x78, 0x54, 0x37, 0x41, 0x76, 0x53, 0x45, 0x53, 0x42, 0x54, 0x2F, 0x38, 0x74, 0x77, 0x4E, 0x4A, 0x41, 0x6C, 0x76, 0x49, 0x4A, 0x65, 0x62, ++ 0x69, 0x56, 0x44, 0x6A, 0x31, 0x65, 0x59, 0x65, 0x4D, 0x48, 0x56, 0x4F, 0x79, 0x54, 0x6F, 0x56, 0x37, 0x42, 0x6A, 0x6A, 0x48, 0x4C, 0x50, 0x6A, 0x34, 0x73, 0x48, 0x4B, 0x4E, 0x0A, 0x4A, 0x65, 0x56, 0x33, 0x55, 0x76, 0x51, 0x44, 0x48, 0x45, ++ 0x69, 0x6D, 0x55, 0x46, 0x2B, 0x49, 0x49, 0x44, 0x42, 0x75, 0x38, 0x6F, 0x4A, 0x44, 0x71, 0x7A, 0x32, 0x58, 0x68, 0x4F, 0x64, 0x54, 0x2B, 0x79, 0x48, 0x42, 0x54, 0x77, 0x38, 0x69, 0x6D, 0x6F, 0x61, 0x34, 0x57, 0x53, 0x72, 0x32, 0x52, 0x7A, ++ 0x30, 0x5A, 0x69, 0x43, 0x33, 0x6F, 0x68, 0x65, 0x47, 0x65, 0x37, 0x49, 0x55, 0x49, 0x61, 0x72, 0x46, 0x73, 0x4E, 0x4D, 0x6B, 0x64, 0x37, 0x45, 0x67, 0x72, 0x0A, 0x4F, 0x33, 0x6A, 0x74, 0x5A, 0x73, 0x53, 0x4F, 0x65, 0x57, 0x6D, 0x44, 0x33, ++ 0x6E, 0x2B, 0x4D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, ++ 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33, 0x20, 0x47, 0x33, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, ++ 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x59, 0x44, 0x43, 0x43, 0x41, 0x30, 0x69, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, ++ 0x67, 0x49, 0x55, 0x4C, 0x76, 0x57, 0x62, 0x41, 0x69, 0x69, 0x6E, 0x32, 0x33, 0x72, 0x2F, 0x31, 0x61, 0x4F, 0x70, 0x37, 0x72, 0x30, 0x44, 0x6F, 0x4D, 0x38, 0x53, 0x61, 0x68, 0x30, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, ++ 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x42, 0x51, 0x41, 0x77, 0x53, 0x44, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x0A, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x51, 0x6B, 0x30, 0x78, 0x47, 0x54, 0x41, 0x58, 0x42, 0x67, 0x4E, 0x56, ++ 0x42, 0x41, 0x6F, 0x54, 0x45, 0x46, 0x46, 0x31, 0x62, 0x31, 0x5A, 0x68, 0x5A, 0x47, 0x6C, 0x7A, 0x49, 0x45, 0x78, 0x70, 0x62, 0x57, 0x6C, 0x30, 0x5A, 0x57, 0x51, 0x78, 0x48, 0x6A, 0x41, 0x63, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, ++ 0x46, 0x56, 0x46, 0x31, 0x62, 0x31, 0x5A, 0x68, 0x5A, 0x47, 0x6C, 0x7A, 0x49, 0x46, 0x4A, 0x76, 0x0A, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x67, 0x4D, 0x79, 0x42, 0x48, 0x4D, 0x7A, 0x41, 0x65, 0x46, 0x77, 0x30, 0x78, 0x4D, 0x6A, 0x41, ++ 0x78, 0x4D, 0x54, 0x49, 0x79, 0x4D, 0x44, 0x49, 0x32, 0x4D, 0x7A, 0x4A, 0x61, 0x46, 0x77, 0x30, 0x30, 0x4D, 0x6A, 0x41, 0x78, 0x4D, 0x54, 0x49, 0x79, 0x4D, 0x44, 0x49, 0x32, 0x4D, 0x7A, 0x4A, 0x61, 0x4D, 0x45, 0x67, 0x78, 0x43, 0x7A, 0x41, ++ 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6B, 0x4A, 0x4E, 0x0A, 0x4D, 0x52, 0x6B, 0x77, 0x46, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x45, 0x78, 0x42, 0x52, 0x64, 0x57, 0x39, 0x57, 0x59, 0x57, 0x52, 0x70, 0x63, 0x79, ++ 0x42, 0x4D, 0x61, 0x57, 0x31, 0x70, 0x64, 0x47, 0x56, 0x6B, 0x4D, 0x52, 0x34, 0x77, 0x48, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x56, 0x52, 0x64, 0x57, 0x39, 0x57, 0x59, 0x57, 0x52, 0x70, 0x63, 0x79, 0x42, 0x53, 0x62, 0x32, ++ 0x39, 0x30, 0x49, 0x45, 0x4E, 0x42, 0x49, 0x44, 0x4D, 0x67, 0x0A, 0x52, 0x7A, 0x4D, 0x77, 0x67, 0x67, 0x49, 0x69, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, ++ 0x34, 0x49, 0x43, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x49, 0x4B, 0x41, 0x6F, 0x49, 0x43, 0x41, 0x51, 0x43, 0x7A, 0x79, 0x77, 0x34, 0x51, 0x5A, 0x34, 0x37, 0x71, 0x46, 0x4A, 0x65, 0x6E, 0x4D, 0x69, 0x6F, 0x4B, 0x56, 0x6A, 0x5A, 0x2F, 0x61, ++ 0x45, 0x7A, 0x48, 0x73, 0x32, 0x38, 0x36, 0x0A, 0x49, 0x78, 0x53, 0x52, 0x2F, 0x78, 0x6C, 0x2F, 0x70, 0x63, 0x71, 0x73, 0x37, 0x72, 0x4E, 0x32, 0x6E, 0x58, 0x72, 0x70, 0x69, 0x78, 0x75, 0x72, 0x61, 0x7A, 0x48, 0x62, 0x2B, 0x67, 0x74, 0x54, ++ 0x54, 0x4B, 0x2F, 0x46, 0x70, 0x52, 0x70, 0x35, 0x50, 0x49, 0x70, 0x4D, 0x2F, 0x36, 0x7A, 0x66, 0x4A, 0x64, 0x35, 0x4F, 0x32, 0x59, 0x49, 0x79, 0x43, 0x30, 0x54, 0x65, 0x79, 0x74, 0x75, 0x4D, 0x72, 0x4B, 0x4E, 0x75, 0x46, 0x6F, 0x4D, 0x37, ++ 0x70, 0x6D, 0x52, 0x4C, 0x0A, 0x4D, 0x6F, 0x6E, 0x37, 0x46, 0x68, 0x59, 0x34, 0x66, 0x75, 0x74, 0x44, 0x34, 0x74, 0x4E, 0x30, 0x53, 0x73, 0x4A, 0x69, 0x43, 0x6E, 0x4D, 0x4B, 0x33, 0x55, 0x6D, 0x7A, 0x56, 0x39, 0x4B, 0x77, 0x43, 0x6F, 0x57, ++ 0x64, 0x63, 0x54, 0x7A, 0x65, 0x6F, 0x38, 0x76, 0x41, 0x4D, 0x76, 0x4D, 0x42, 0x4F, 0x53, 0x42, 0x44, 0x47, 0x7A, 0x58, 0x52, 0x55, 0x37, 0x4F, 0x78, 0x37, 0x73, 0x57, 0x54, 0x61, 0x59, 0x49, 0x2B, 0x46, 0x72, 0x55, 0x6F, 0x52, 0x71, 0x48, ++ 0x65, 0x0A, 0x36, 0x6F, 0x6B, 0x4A, 0x37, 0x55, 0x4F, 0x34, 0x42, 0x55, 0x61, 0x4B, 0x68, 0x76, 0x56, 0x5A, 0x52, 0x37, 0x34, 0x62, 0x62, 0x77, 0x45, 0x68, 0x45, 0x4C, 0x6E, 0x39, 0x71, 0x64, 0x49, 0x6F, 0x79, 0x68, 0x41, 0x35, 0x43, 0x63, ++ 0x6F, 0x54, 0x4E, 0x73, 0x2B, 0x63, 0x72, 0x61, 0x31, 0x41, 0x64, 0x48, 0x6B, 0x72, 0x41, 0x6A, 0x38, 0x30, 0x2F, 0x2F, 0x6F, 0x67, 0x61, 0x58, 0x33, 0x54, 0x37, 0x6D, 0x48, 0x31, 0x75, 0x72, 0x50, 0x6E, 0x4D, 0x4E, 0x41, 0x33, 0x0A, 0x49, ++ 0x34, 0x5A, 0x79, 0x59, 0x55, 0x55, 0x70, 0x53, 0x46, 0x6C, 0x6F, 0x62, 0x33, 0x65, 0x6D, 0x4C, 0x6F, 0x47, 0x2B, 0x42, 0x30, 0x31, 0x76, 0x72, 0x38, 0x37, 0x45, 0x52, 0x52, 0x4F, 0x52, 0x46, 0x48, 0x41, 0x47, 0x6A, 0x78, 0x2B, 0x66, 0x2B, ++ 0x49, 0x64, 0x70, 0x73, 0x51, 0x37, 0x76, 0x77, 0x34, 0x6B, 0x5A, 0x36, 0x2B, 0x6F, 0x63, 0x59, 0x66, 0x78, 0x36, 0x62, 0x49, 0x72, 0x63, 0x31, 0x67, 0x4D, 0x4C, 0x6E, 0x69, 0x61, 0x36, 0x45, 0x74, 0x33, 0x55, 0x0A, 0x56, 0x44, 0x6D, 0x72, ++ 0x4A, 0x71, 0x4D, 0x7A, 0x36, 0x6E, 0x57, 0x42, 0x32, 0x69, 0x33, 0x4E, 0x44, 0x30, 0x2F, 0x6B, 0x41, 0x39, 0x48, 0x76, 0x46, 0x5A, 0x63, 0x62, 0x61, 0x35, 0x44, 0x46, 0x41, 0x70, 0x43, 0x54, 0x5A, 0x67, 0x49, 0x68, 0x73, 0x55, 0x66, 0x65, ++ 0x69, 0x35, 0x70, 0x4B, 0x67, 0x4C, 0x6C, 0x56, 0x6A, 0x37, 0x57, 0x69, 0x4C, 0x38, 0x44, 0x57, 0x4D, 0x32, 0x66, 0x61, 0x66, 0x73, 0x53, 0x6E, 0x74, 0x41, 0x52, 0x45, 0x36, 0x30, 0x66, 0x37, 0x0A, 0x35, 0x6C, 0x69, 0x35, 0x39, 0x77, 0x7A, ++ 0x77, 0x65, 0x79, 0x75, 0x78, 0x77, 0x48, 0x41, 0x70, 0x77, 0x30, 0x42, 0x69, 0x4C, 0x54, 0x74, 0x49, 0x61, 0x64, 0x77, 0x6A, 0x50, 0x45, 0x6A, 0x72, 0x65, 0x77, 0x6C, 0x35, 0x71, 0x57, 0x33, 0x61, 0x71, 0x44, 0x43, 0x59, 0x7A, 0x34, 0x42, ++ 0x79, 0x41, 0x34, 0x69, 0x6D, 0x57, 0x30, 0x61, 0x75, 0x63, 0x6E, 0x6C, 0x38, 0x43, 0x41, 0x4D, 0x68, 0x5A, 0x61, 0x36, 0x33, 0x34, 0x52, 0x79, 0x6C, 0x73, 0x53, 0x71, 0x69, 0x0A, 0x4D, 0x64, 0x35, 0x6D, 0x42, 0x50, 0x66, 0x41, 0x64, 0x4F, ++ 0x68, 0x78, 0x33, 0x76, 0x38, 0x39, 0x57, 0x63, 0x79, 0x57, 0x4A, 0x68, 0x4B, 0x4C, 0x68, 0x5A, 0x56, 0x58, 0x47, 0x71, 0x74, 0x72, 0x64, 0x51, 0x74, 0x45, 0x50, 0x52, 0x45, 0x6F, 0x50, 0x48, 0x74, 0x68, 0x74, 0x2B, 0x4B, 0x50, 0x5A, 0x30, ++ 0x2F, 0x6C, 0x37, 0x44, 0x78, 0x4D, 0x59, 0x49, 0x42, 0x70, 0x56, 0x7A, 0x67, 0x65, 0x41, 0x56, 0x75, 0x4E, 0x56, 0x65, 0x6A, 0x48, 0x33, 0x38, 0x44, 0x4D, 0x0A, 0x64, 0x79, 0x4D, 0x30, 0x53, 0x58, 0x56, 0x38, 0x39, 0x70, 0x67, 0x52, 0x36, ++ 0x79, 0x33, 0x65, 0x37, 0x55, 0x45, 0x75, 0x46, 0x41, 0x55, 0x43, 0x66, 0x2B, 0x44, 0x2B, 0x49, 0x4F, 0x73, 0x31, 0x35, 0x78, 0x47, 0x73, 0x49, 0x73, 0x35, 0x58, 0x50, 0x64, 0x37, 0x4A, 0x4D, 0x47, 0x30, 0x51, 0x41, 0x34, 0x58, 0x4E, 0x38, ++ 0x66, 0x2B, 0x4D, 0x46, 0x72, 0x58, 0x42, 0x73, 0x6A, 0x36, 0x49, 0x62, 0x47, 0x42, 0x2F, 0x6B, 0x45, 0x2B, 0x56, 0x39, 0x2F, 0x59, 0x74, 0x0A, 0x72, 0x51, 0x45, 0x35, 0x42, 0x77, 0x54, 0x36, 0x64, 0x59, 0x42, 0x39, 0x76, 0x30, 0x6C, 0x51, ++ 0x37, 0x65, 0x2F, 0x4A, 0x78, 0x48, 0x77, 0x63, 0x36, 0x34, 0x42, 0x2B, 0x32, 0x37, 0x62, 0x51, 0x33, 0x52, 0x50, 0x2B, 0x79, 0x64, 0x4F, 0x63, 0x31, 0x37, 0x4B, 0x58, 0x71, 0x51, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x6F, 0x30, 0x49, 0x77, ++ 0x51, 0x44, 0x41, 0x50, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x52, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x54, 0x41, 0x44, 0x0A, 0x41, 0x51, 0x48, 0x2F, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, ++ 0x45, 0x41, 0x77, 0x49, 0x42, 0x42, 0x6A, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x78, 0x68, 0x66, 0x51, 0x76, 0x4B, 0x6A, 0x71, 0x41, 0x6B, 0x50, 0x79, 0x47, 0x77, 0x61, 0x5A, 0x58, 0x53, 0x75, ++ 0x51, 0x49, 0x4C, 0x6E, 0x58, 0x6E, 0x4F, 0x51, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x0A, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x42, 0x41, 0x44, 0x52, 0x68, 0x32, 0x56, ++ 0x61, 0x31, 0x45, 0x6F, 0x64, 0x56, 0x54, 0x64, 0x32, 0x6A, 0x4E, 0x54, 0x46, 0x47, 0x75, 0x36, 0x51, 0x48, 0x63, 0x72, 0x78, 0x66, 0x59, 0x57, 0x4C, 0x6F, 0x70, 0x66, 0x73, 0x4C, 0x4E, 0x37, 0x45, 0x38, 0x74, 0x72, 0x50, 0x36, 0x4B, 0x5A, ++ 0x31, 0x2F, 0x41, 0x76, 0x57, 0x6B, 0x79, 0x61, 0x69, 0x54, 0x74, 0x33, 0x70, 0x78, 0x0A, 0x4B, 0x47, 0x6D, 0x50, 0x63, 0x2B, 0x46, 0x53, 0x6B, 0x4E, 0x72, 0x56, 0x76, 0x6A, 0x72, 0x6C, 0x74, 0x33, 0x5A, 0x71, 0x56, 0x6F, 0x41, 0x68, 0x33, ++ 0x31, 0x33, 0x6D, 0x36, 0x54, 0x71, 0x65, 0x35, 0x54, 0x37, 0x32, 0x6F, 0x6D, 0x6E, 0x48, 0x4B, 0x67, 0x71, 0x77, 0x47, 0x45, 0x66, 0x63, 0x49, 0x48, 0x42, 0x39, 0x55, 0x71, 0x4D, 0x2B, 0x57, 0x58, 0x7A, 0x42, 0x75, 0x73, 0x6E, 0x49, 0x46, ++ 0x55, 0x42, 0x68, 0x79, 0x6E, 0x4C, 0x57, 0x63, 0x4B, 0x7A, 0x53, 0x0A, 0x74, 0x2F, 0x41, 0x63, 0x35, 0x49, 0x59, 0x70, 0x38, 0x4D, 0x37, 0x76, 0x61, 0x47, 0x50, 0x51, 0x74, 0x53, 0x43, 0x4B, 0x46, 0x57, 0x47, 0x61, 0x66, 0x6F, 0x61, 0x59, ++ 0x74, 0x4D, 0x6E, 0x43, 0x64, 0x76, 0x76, 0x4D, 0x75, 0x6A, 0x41, 0x57, 0x7A, 0x4B, 0x4E, 0x68, 0x78, 0x6E, 0x51, 0x54, 0x35, 0x57, 0x76, 0x76, 0x6F, 0x78, 0x58, 0x71, 0x41, 0x2F, 0x34, 0x54, 0x69, 0x32, 0x54, 0x6B, 0x30, 0x38, 0x48, 0x53, ++ 0x36, 0x49, 0x54, 0x37, 0x53, 0x64, 0x45, 0x51, 0x0A, 0x54, 0x58, 0x6C, 0x6D, 0x36, 0x36, 0x72, 0x39, 0x39, 0x49, 0x30, 0x78, 0x48, 0x6E, 0x41, 0x55, 0x72, 0x64, 0x7A, 0x65, 0x5A, 0x78, 0x4E, 0x4D, 0x67, 0x52, 0x56, 0x68, 0x76, 0x4C, 0x66, ++ 0x5A, 0x6B, 0x58, 0x64, 0x78, 0x47, 0x59, 0x46, 0x67, 0x75, 0x2F, 0x42, 0x59, 0x70, 0x62, 0x57, 0x63, 0x43, 0x2F, 0x65, 0x50, 0x49, 0x6C, 0x55, 0x6E, 0x77, 0x45, 0x73, 0x42, 0x62, 0x54, 0x75, 0x5A, 0x44, 0x64, 0x51, 0x64, 0x6D, 0x32, 0x4E, ++ 0x6E, 0x4C, 0x39, 0x44, 0x75, 0x0A, 0x44, 0x63, 0x70, 0x6D, 0x76, 0x4A, 0x52, 0x50, 0x70, 0x71, 0x33, 0x74, 0x2F, 0x4F, 0x35, 0x6A, 0x72, 0x46, 0x63, 0x2F, 0x5A, 0x53, 0x58, 0x50, 0x73, 0x6F, 0x61, 0x50, 0x30, 0x41, 0x6A, 0x2F, 0x75, 0x48, ++ 0x59, 0x55, 0x62, 0x74, 0x37, 0x6C, 0x4A, 0x2B, 0x79, 0x72, 0x65, 0x4C, 0x56, 0x54, 0x75, 0x62, 0x59, 0x2F, 0x36, 0x43, 0x44, 0x35, 0x30, 0x71, 0x69, 0x2B, 0x59, 0x55, 0x62, 0x4B, 0x68, 0x34, 0x79, 0x45, 0x38, 0x2F, 0x6E, 0x78, 0x6F, 0x47, ++ 0x69, 0x62, 0x0A, 0x49, 0x68, 0x36, 0x42, 0x4A, 0x70, 0x73, 0x51, 0x42, 0x4A, 0x46, 0x78, 0x77, 0x41, 0x59, 0x66, 0x33, 0x4B, 0x44, 0x54, 0x75, 0x56, 0x61, 0x6E, 0x34, 0x35, 0x67, 0x74, 0x66, 0x34, 0x4F, 0x64, 0x33, 0x34, 0x77, 0x72, 0x6E, ++ 0x44, 0x4B, 0x4F, 0x4D, 0x70, 0x54, 0x77, 0x41, 0x54, 0x77, 0x69, 0x4B, 0x70, 0x39, 0x44, 0x77, 0x69, 0x37, 0x44, 0x6D, 0x44, 0x6B, 0x48, 0x4F, 0x48, 0x76, 0x38, 0x58, 0x67, 0x42, 0x43, 0x48, 0x2F, 0x4D, 0x79, 0x4A, 0x6E, 0x6D, 0x44, 0x0A, ++ 0x68, 0x50, 0x62, 0x6C, 0x38, 0x4D, 0x46, 0x52, 0x45, 0x73, 0x41, 0x4C, 0x48, 0x67, 0x51, 0x6A, 0x44, 0x46, 0x53, 0x6C, 0x54, 0x43, 0x39, 0x4A, 0x78, 0x55, 0x72, 0x52, 0x74, 0x6D, 0x35, 0x67, 0x44, 0x57, 0x76, 0x38, 0x61, 0x34, 0x75, 0x46, ++ 0x4A, 0x47, 0x53, 0x33, 0x69, 0x51, 0x36, 0x72, 0x4A, 0x55, 0x64, 0x62, 0x50, 0x4D, 0x39, 0x2B, 0x53, 0x62, 0x33, 0x48, 0x36, 0x51, 0x72, 0x47, 0x32, 0x76, 0x64, 0x2B, 0x44, 0x68, 0x63, 0x49, 0x30, 0x30, 0x69, 0x58, 0x0A, 0x30, 0x48, 0x47, ++ 0x53, 0x38, 0x41, 0x38, 0x35, 0x50, 0x6A, 0x52, 0x71, 0x48, 0x48, 0x33, 0x59, 0x38, 0x69, 0x4B, 0x75, 0x75, 0x32, 0x6E, 0x30, 0x4D, 0x37, 0x53, 0x6D, 0x53, 0x46, 0x58, 0x52, 0x44, 0x77, 0x34, 0x6D, 0x36, 0x4F, 0x79, 0x32, 0x43, 0x79, 0x32, ++ 0x6E, 0x68, 0x54, 0x58, 0x4E, 0x2F, 0x56, 0x6E, 0x49, 0x6E, 0x39, 0x48, 0x4E, 0x50, 0x6C, 0x6F, 0x70, 0x4E, 0x4C, 0x6B, 0x39, 0x68, 0x4D, 0x36, 0x78, 0x5A, 0x64, 0x52, 0x5A, 0x6B, 0x5A, 0x46, 0x57, 0x0A, 0x64, 0x53, 0x48, 0x42, 0x64, 0x35, ++ 0x37, 0x35, 0x65, 0x75, 0x46, 0x67, 0x6E, 0x64, 0x4F, 0x74, 0x42, 0x42, 0x6A, 0x30, 0x66, 0x4F, 0x74, 0x65, 0x6B, 0x34, 0x39, 0x54, 0x53, 0x69, 0x49, 0x70, 0x2B, 0x45, 0x67, 0x72, 0x50, 0x6B, 0x32, 0x47, 0x72, 0x46, 0x74, 0x2F, 0x79, 0x77, ++ 0x61, 0x5A, 0x57, 0x57, 0x44, 0x59, 0x57, 0x47, 0x57, 0x56, 0x6A, 0x55, 0x54, 0x52, 0x39, 0x33, 0x39, 0x2B, 0x4A, 0x33, 0x39, 0x39, 0x72, 0x6F, 0x44, 0x31, 0x42, 0x30, 0x79, 0x32, 0x0A, 0x50, 0x70, 0x78, 0x78, 0x56, 0x4A, 0x6B, 0x45, 0x53, ++ 0x2F, 0x31, 0x59, 0x2B, 0x5A, 0x6A, 0x30, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x44, 0x69, 0x67, 0x69, 0x43, ++ 0x65, 0x72, 0x74, 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x32, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, ++ 0x49, 0x49, 0x44, 0x6C, 0x6A, 0x43, 0x43, 0x41, 0x6E, 0x36, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x43, 0x35, 0x4D, 0x63, 0x4F, 0x74, 0x59, 0x35, 0x5A, 0x2B, 0x70, 0x6E, 0x49, 0x37, 0x2F, 0x44, 0x72, 0x35, 0x72, 0x30, 0x53, ++ 0x7A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x44, 0x42, 0x6C, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x0A, 0x45, 0x77, 0x4A, 0x56, ++ 0x55, 0x7A, 0x45, 0x56, 0x4D, 0x42, 0x4D, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x4D, 0x52, 0x47, 0x6C, 0x6E, 0x61, 0x55, 0x4E, 0x6C, 0x63, 0x6E, 0x51, 0x67, 0x53, 0x57, 0x35, 0x6A, 0x4D, 0x52, 0x6B, 0x77, 0x46, 0x77, 0x59, 0x44, ++ 0x56, 0x51, 0x51, 0x4C, 0x45, 0x78, 0x42, 0x33, 0x64, 0x33, 0x63, 0x75, 0x5A, 0x47, 0x6C, 0x6E, 0x61, 0x57, 0x4E, 0x6C, 0x63, 0x6E, 0x51, 0x75, 0x59, 0x32, 0x39, 0x74, 0x4D, 0x53, 0x51, 0x77, 0x0A, 0x49, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, ++ 0x44, 0x45, 0x78, 0x74, 0x45, 0x61, 0x57, 0x64, 0x70, 0x51, 0x32, 0x56, 0x79, 0x64, 0x43, 0x42, 0x42, 0x63, 0x33, 0x4E, 0x31, 0x63, 0x6D, 0x56, 0x6B, 0x49, 0x45, 0x6C, 0x45, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x52, 0x7A, 0x49, ++ 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x54, 0x4D, 0x77, 0x4F, 0x44, 0x41, 0x78, 0x4D, 0x54, 0x49, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x57, 0x68, 0x63, 0x4E, 0x4D, 0x7A, 0x67, 0x77, 0x0A, 0x4D, 0x54, 0x45, 0x31, 0x4D, 0x54, 0x49, 0x77, 0x4D, 0x44, ++ 0x41, 0x77, 0x57, 0x6A, 0x42, 0x6C, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x56, 0x55, 0x7A, 0x45, 0x56, 0x4D, 0x42, 0x4D, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x4D, 0x52, 0x47, ++ 0x6C, 0x6E, 0x61, 0x55, 0x4E, 0x6C, 0x63, 0x6E, 0x51, 0x67, 0x53, 0x57, 0x35, 0x6A, 0x4D, 0x52, 0x6B, 0x77, 0x46, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4C, 0x0A, 0x45, 0x78, 0x42, 0x33, 0x64, 0x33, 0x63, 0x75, 0x5A, 0x47, 0x6C, 0x6E, 0x61, ++ 0x57, 0x4E, 0x6C, 0x63, 0x6E, 0x51, 0x75, 0x59, 0x32, 0x39, 0x74, 0x4D, 0x53, 0x51, 0x77, 0x49, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x74, 0x45, 0x61, 0x57, 0x64, 0x70, 0x51, 0x32, 0x56, 0x79, 0x64, 0x43, 0x42, 0x42, 0x63, ++ 0x33, 0x4E, 0x31, 0x63, 0x6D, 0x56, 0x6B, 0x49, 0x45, 0x6C, 0x45, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x52, 0x7A, 0x49, 0x77, 0x0A, 0x67, 0x67, 0x45, 0x69, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, ++ 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x42, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x45, 0x4B, 0x41, 0x6F, 0x49, 0x42, 0x41, 0x51, 0x44, 0x5A, 0x35, 0x79, 0x67, 0x76, 0x55, 0x6A, 0x38, 0x32, 0x63, 0x6B, 0x6D, 0x49, ++ 0x6B, 0x7A, 0x54, 0x7A, 0x2B, 0x47, 0x6F, 0x65, 0x4D, 0x56, 0x53, 0x41, 0x6E, 0x36, 0x31, 0x55, 0x51, 0x62, 0x56, 0x48, 0x0A, 0x33, 0x35, 0x61, 0x6F, 0x31, 0x4B, 0x2B, 0x41, 0x4C, 0x62, 0x6B, 0x4B, 0x7A, 0x33, 0x58, 0x39, 0x69, 0x61, 0x56, ++ 0x39, 0x4A, 0x50, 0x72, 0x6A, 0x49, 0x67, 0x77, 0x72, 0x76, 0x4A, 0x55, 0x58, 0x43, 0x7A, 0x4F, 0x2F, 0x47, 0x55, 0x31, 0x42, 0x42, 0x70, 0x41, 0x41, 0x76, 0x51, 0x78, 0x4E, 0x45, 0x50, 0x34, 0x48, 0x74, 0x65, 0x63, 0x63, 0x62, 0x69, 0x4A, ++ 0x56, 0x4D, 0x57, 0x57, 0x58, 0x76, 0x64, 0x4D, 0x58, 0x30, 0x68, 0x35, 0x69, 0x38, 0x39, 0x76, 0x71, 0x0A, 0x62, 0x46, 0x43, 0x4D, 0x50, 0x34, 0x51, 0x4D, 0x6C, 0x73, 0x2B, 0x33, 0x79, 0x77, 0x50, 0x67, 0x79, 0x6D, 0x32, 0x68, 0x46, 0x45, ++ 0x77, 0x62, 0x69, 0x64, 0x33, 0x74, 0x41, 0x4C, 0x42, 0x53, 0x66, 0x4B, 0x2B, 0x52, 0x62, 0x4C, 0x45, 0x34, 0x45, 0x39, 0x48, 0x70, 0x45, 0x67, 0x6A, 0x41, 0x41, 0x4C, 0x41, 0x63, 0x4B, 0x78, 0x48, 0x61, 0x64, 0x33, 0x41, 0x32, 0x6D, 0x36, ++ 0x37, 0x4F, 0x65, 0x59, 0x66, 0x63, 0x67, 0x6E, 0x44, 0x6D, 0x43, 0x58, 0x52, 0x77, 0x0A, 0x56, 0x57, 0x6D, 0x76, 0x6F, 0x32, 0x69, 0x66, 0x76, 0x39, 0x32, 0x32, 0x65, 0x62, 0x50, 0x79, 0x6E, 0x58, 0x41, 0x70, 0x56, 0x66, 0x53, 0x72, 0x2F, ++ 0x35, 0x56, 0x68, 0x38, 0x38, 0x6C, 0x41, 0x62, 0x78, 0x33, 0x52, 0x76, 0x70, 0x4F, 0x37, 0x30, 0x34, 0x67, 0x71, 0x75, 0x35, 0x32, 0x2F, 0x63, 0x6C, 0x70, 0x57, 0x63, 0x54, 0x73, 0x2F, 0x31, 0x50, 0x50, 0x52, 0x43, 0x76, 0x34, 0x6F, 0x37, ++ 0x36, 0x50, 0x75, 0x32, 0x5A, 0x6D, 0x76, 0x41, 0x39, 0x4F, 0x50, 0x0A, 0x59, 0x4C, 0x66, 0x79, 0x6B, 0x71, 0x47, 0x78, 0x76, 0x59, 0x6D, 0x4A, 0x48, 0x7A, 0x44, 0x4E, 0x77, 0x36, 0x59, 0x75, 0x59, 0x6A, 0x4F, 0x75, 0x46, 0x67, 0x4A, 0x33, ++ 0x52, 0x46, 0x72, 0x6E, 0x67, 0x51, 0x6F, 0x38, 0x70, 0x30, 0x51, 0x75, 0x65, 0x62, 0x67, 0x2F, 0x42, 0x4C, 0x78, 0x63, 0x6F, 0x49, 0x66, 0x68, 0x47, 0x36, 0x39, 0x52, 0x6A, 0x73, 0x33, 0x73, 0x4C, 0x50, 0x72, 0x34, 0x2F, 0x6D, 0x33, 0x77, ++ 0x4F, 0x6E, 0x79, 0x71, 0x69, 0x2B, 0x52, 0x6E, 0x0A, 0x6C, 0x54, 0x47, 0x4E, 0x41, 0x67, 0x4D, 0x42, 0x41, 0x41, 0x47, 0x6A, 0x51, 0x6A, 0x42, 0x41, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, ++ 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x51, 0x44, 0x41, 0x67, 0x47, 0x47, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, ++ 0x57, 0x42, 0x42, 0x54, 0x4F, 0x0A, 0x77, 0x30, 0x71, 0x35, 0x6D, 0x56, 0x58, 0x79, 0x75, 0x4E, 0x74, 0x67, 0x76, 0x36, 0x6C, 0x2B, 0x76, 0x56, 0x61, 0x31, 0x6C, 0x7A, 0x61, 0x6E, 0x31, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, ++ 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x51, 0x45, 0x41, 0x79, 0x71, 0x56, 0x56, 0x6A, 0x4F, 0x50, 0x49, 0x51, 0x57, 0x35, 0x70, 0x4A, 0x36, 0x64, 0x31, 0x45, 0x65, 0x38, 0x38, 0x68, 0x6A, ++ 0x5A, 0x76, 0x0A, 0x30, 0x70, 0x33, 0x47, 0x65, 0x44, 0x67, 0x64, 0x61, 0x5A, 0x61, 0x69, 0x6B, 0x6D, 0x6B, 0x75, 0x4F, 0x47, 0x79, 0x62, 0x66, 0x51, 0x54, 0x55, 0x69, 0x61, 0x57, 0x78, 0x4D, 0x54, 0x65, 0x4B, 0x79, 0x53, 0x48, 0x4D, 0x71, ++ 0x32, 0x7A, 0x4E, 0x69, 0x78, 0x79, 0x61, 0x31, 0x72, 0x39, 0x49, 0x30, 0x6A, 0x4A, 0x6D, 0x77, 0x59, 0x72, 0x41, 0x38, 0x79, 0x38, 0x36, 0x37, 0x38, 0x44, 0x6A, 0x31, 0x4A, 0x47, 0x47, 0x30, 0x56, 0x44, 0x6A, 0x41, 0x39, 0x74, 0x7A, 0x0A, ++ 0x64, 0x32, 0x39, 0x4B, 0x4F, 0x56, 0x50, 0x74, 0x33, 0x69, 0x62, 0x48, 0x74, 0x58, 0x32, 0x76, 0x4B, 0x30, 0x4C, 0x52, 0x64, 0x57, 0x4C, 0x6A, 0x53, 0x69, 0x73, 0x43, 0x78, 0x31, 0x42, 0x4C, 0x34, 0x47, 0x6E, 0x69, 0x6C, 0x6D, 0x77, 0x4F, ++ 0x52, 0x47, 0x59, 0x51, 0x52, 0x49, 0x2B, 0x74, 0x42, 0x65, 0x76, 0x34, 0x65, 0x61, 0x79, 0x6D, 0x47, 0x2B, 0x67, 0x33, 0x4E, 0x4A, 0x31, 0x54, 0x79, 0x57, 0x47, 0x71, 0x6F, 0x6C, 0x4B, 0x76, 0x53, 0x6E, 0x41, 0x57, 0x0A, 0x68, 0x73, 0x49, ++ 0x36, 0x79, 0x4C, 0x45, 0x54, 0x63, 0x44, 0x62, 0x59, 0x7A, 0x2B, 0x37, 0x30, 0x43, 0x6A, 0x54, 0x56, 0x57, 0x30, 0x7A, 0x39, 0x42, 0x35, 0x79, 0x69, 0x75, 0x74, 0x6B, 0x42, 0x63, 0x6C, 0x7A, 0x7A, 0x54, 0x63, 0x48, 0x64, 0x44, 0x72, 0x45, ++ 0x63, 0x44, 0x63, 0x52, 0x6A, 0x76, 0x71, 0x33, 0x30, 0x46, 0x50, 0x75, 0x4A, 0x37, 0x4B, 0x4A, 0x42, 0x44, 0x6B, 0x7A, 0x4D, 0x79, 0x46, 0x64, 0x41, 0x30, 0x47, 0x34, 0x44, 0x71, 0x73, 0x30, 0x4D, 0x0A, 0x6A, 0x6F, 0x6D, 0x5A, 0x6D, 0x57, ++ 0x7A, 0x77, 0x50, 0x44, 0x43, 0x76, 0x4F, 0x4E, 0x39, 0x76, 0x76, 0x4B, 0x4F, 0x2B, 0x4B, 0x53, 0x41, 0x6E, 0x71, 0x33, 0x54, 0x2F, 0x45, 0x79, 0x4A, 0x34, 0x33, 0x70, 0x64, 0x53, 0x56, 0x52, 0x36, 0x44, 0x74, 0x56, 0x51, 0x67, 0x41, 0x2B, ++ 0x36, 0x75, 0x77, 0x45, 0x39, 0x57, 0x33, 0x6A, 0x66, 0x4D, 0x77, 0x33, 0x2B, 0x71, 0x42, 0x43, 0x65, 0x37, 0x30, 0x33, 0x65, 0x34, 0x59, 0x74, 0x73, 0x58, 0x66, 0x4A, 0x77, 0x6F, 0x0A, 0x49, 0x68, 0x4E, 0x7A, 0x62, 0x4D, 0x38, 0x6D, 0x39, ++ 0x59, 0x6F, 0x70, 0x35, 0x77, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x44, 0x69, 0x67, 0x69, 0x43, ++ 0x65, 0x72, 0x74, 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x33, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, ++ 0x49, 0x49, 0x43, 0x52, 0x6A, 0x43, 0x43, 0x41, 0x63, 0x32, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x43, 0x36, 0x46, 0x61, 0x2B, 0x68, 0x33, 0x66, 0x6F, 0x4C, 0x56, 0x4A, 0x52, 0x4B, 0x2F, 0x4E, 0x4A, 0x4B, 0x42, 0x73, 0x37, ++ 0x44, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x7A, 0x42, 0x6C, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x56, 0x0A, 0x55, 0x7A, 0x45, 0x56, ++ 0x4D, 0x42, 0x4D, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x4D, 0x52, 0x47, 0x6C, 0x6E, 0x61, 0x55, 0x4E, 0x6C, 0x63, 0x6E, 0x51, 0x67, 0x53, 0x57, 0x35, 0x6A, 0x4D, 0x52, 0x6B, 0x77, 0x46, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4C, ++ 0x45, 0x78, 0x42, 0x33, 0x64, 0x33, 0x63, 0x75, 0x5A, 0x47, 0x6C, 0x6E, 0x61, 0x57, 0x4E, 0x6C, 0x63, 0x6E, 0x51, 0x75, 0x59, 0x32, 0x39, 0x74, 0x4D, 0x53, 0x51, 0x77, 0x49, 0x67, 0x59, 0x44, 0x0A, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x74, ++ 0x45, 0x61, 0x57, 0x64, 0x70, 0x51, 0x32, 0x56, 0x79, 0x64, 0x43, 0x42, 0x42, 0x63, 0x33, 0x4E, 0x31, 0x63, 0x6D, 0x56, 0x6B, 0x49, 0x45, 0x6C, 0x45, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x52, 0x7A, 0x4D, 0x77, 0x48, 0x68, 0x63, ++ 0x4E, 0x4D, 0x54, 0x4D, 0x77, 0x4F, 0x44, 0x41, 0x78, 0x4D, 0x54, 0x49, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x57, 0x68, 0x63, 0x4E, 0x4D, 0x7A, 0x67, 0x77, 0x4D, 0x54, 0x45, 0x31, 0x0A, 0x4D, 0x54, 0x49, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x57, 0x6A, ++ 0x42, 0x6C, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x56, 0x55, 0x7A, 0x45, 0x56, 0x4D, 0x42, 0x4D, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x4D, 0x52, 0x47, 0x6C, 0x6E, 0x61, 0x55, ++ 0x4E, 0x6C, 0x63, 0x6E, 0x51, 0x67, 0x53, 0x57, 0x35, 0x6A, 0x4D, 0x52, 0x6B, 0x77, 0x46, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4C, 0x45, 0x78, 0x42, 0x33, 0x0A, 0x64, 0x33, 0x63, 0x75, 0x5A, 0x47, 0x6C, 0x6E, 0x61, 0x57, 0x4E, 0x6C, 0x63, ++ 0x6E, 0x51, 0x75, 0x59, 0x32, 0x39, 0x74, 0x4D, 0x53, 0x51, 0x77, 0x49, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x74, 0x45, 0x61, 0x57, 0x64, 0x70, 0x51, 0x32, 0x56, 0x79, 0x64, 0x43, 0x42, 0x42, 0x63, 0x33, 0x4E, 0x31, 0x63, ++ 0x6D, 0x56, 0x6B, 0x49, 0x45, 0x6C, 0x45, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x52, 0x7A, 0x4D, 0x77, 0x64, 0x6A, 0x41, 0x51, 0x0A, 0x42, 0x67, 0x63, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x49, 0x42, 0x42, 0x67, 0x55, 0x72, ++ 0x67, 0x51, 0x51, 0x41, 0x49, 0x67, 0x4E, 0x69, 0x41, 0x41, 0x51, 0x5A, 0x35, 0x37, 0x79, 0x73, 0x52, 0x47, 0x58, 0x74, 0x7A, 0x62, 0x67, 0x2F, 0x57, 0x50, 0x75, 0x4E, 0x73, 0x56, 0x65, 0x70, 0x52, 0x43, 0x30, 0x46, 0x46, 0x66, 0x4C, 0x76, ++ 0x43, 0x2F, 0x38, 0x51, 0x64, 0x4A, 0x2B, 0x31, 0x59, 0x6C, 0x4A, 0x66, 0x5A, 0x6E, 0x34, 0x66, 0x35, 0x64, 0x77, 0x62, 0x0A, 0x52, 0x58, 0x6B, 0x4C, 0x7A, 0x4D, 0x5A, 0x54, 0x43, 0x70, 0x32, 0x4E, 0x58, 0x51, 0x4C, 0x5A, 0x71, 0x56, 0x6E, ++ 0x65, 0x41, 0x6C, 0x72, 0x32, 0x6C, 0x53, 0x6F, 0x4F, 0x6A, 0x54, 0x68, 0x4B, 0x69, 0x6B, 0x6E, 0x47, 0x76, 0x4D, 0x59, 0x44, 0x4F, 0x41, 0x64, 0x66, 0x56, 0x64, 0x70, 0x2B, 0x43, 0x57, 0x37, 0x69, 0x66, 0x31, 0x37, 0x51, 0x52, 0x53, 0x41, ++ 0x50, 0x57, 0x58, 0x59, 0x51, 0x31, 0x71, 0x41, 0x6B, 0x38, 0x43, 0x33, 0x65, 0x4E, 0x76, 0x4A, 0x73, 0x0A, 0x4B, 0x54, 0x6D, 0x6A, 0x51, 0x6A, 0x42, 0x41, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, ++ 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x51, 0x44, 0x41, 0x67, 0x47, 0x47, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, ++ 0x51, 0x57, 0x42, 0x42, 0x54, 0x4C, 0x30, 0x4C, 0x32, 0x70, 0x34, 0x5A, 0x67, 0x46, 0x0A, 0x55, 0x61, 0x46, 0x4E, 0x4E, 0x36, 0x4B, 0x44, 0x65, 0x63, 0x36, 0x4E, 0x48, 0x53, 0x72, 0x6B, 0x68, 0x44, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, ++ 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x77, 0x4E, 0x6E, 0x41, 0x44, 0x42, 0x6B, 0x41, 0x6A, 0x41, 0x6C, 0x70, 0x49, 0x46, 0x46, 0x41, 0x6D, 0x73, 0x53, 0x53, 0x33, 0x56, 0x30, 0x54, 0x38, 0x67, 0x6A, 0x34, 0x33, 0x44, 0x79, 0x64, ++ 0x58, 0x4C, 0x65, 0x66, 0x49, 0x6E, 0x77, 0x7A, 0x35, 0x46, 0x79, 0x0A, 0x59, 0x5A, 0x35, 0x65, 0x45, 0x4A, 0x4A, 0x5A, 0x56, 0x72, 0x6D, 0x44, 0x78, 0x78, 0x44, 0x6E, 0x4F, 0x4F, 0x6C, 0x59, 0x4A, 0x6A, 0x5A, 0x39, 0x31, 0x65, 0x51, 0x30, ++ 0x68, 0x6A, 0x6B, 0x43, 0x4D, 0x48, 0x77, 0x32, 0x55, 0x2F, 0x41, 0x77, 0x35, 0x57, 0x4A, 0x6A, 0x4F, 0x70, 0x6E, 0x69, 0x74, 0x71, 0x4D, 0x37, 0x6D, 0x7A, 0x54, 0x36, 0x48, 0x74, 0x6F, 0x51, 0x6B, 0x6E, 0x46, 0x65, 0x6B, 0x52, 0x4F, 0x6E, ++ 0x33, 0x61, 0x52, 0x75, 0x6B, 0x73, 0x77, 0x79, 0x0A, 0x31, 0x76, 0x55, 0x68, 0x5A, 0x73, 0x63, 0x76, 0x36, 0x70, 0x5A, 0x6A, 0x61, 0x6D, 0x56, 0x46, 0x6B, 0x70, 0x55, 0x42, 0x74, 0x41, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, ++ 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, ++ 0x74, 0x20, 0x47, 0x32, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, ++ 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x44, 0x6A, 0x6A, 0x43, 0x43, 0x41, 0x6E, 0x61, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x41, 0x7A, 0x72, ++ 0x78, 0x35, 0x71, 0x63, 0x52, 0x71, 0x61, 0x43, 0x37, 0x4B, 0x47, 0x53, 0x78, 0x48, 0x51, 0x6E, 0x36, 0x35, 0x54, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x44, 0x42, ++ 0x68, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x0A, 0x45, 0x77, 0x4A, 0x56, 0x55, 0x7A, 0x45, 0x56, 0x4D, 0x42, 0x4D, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x4D, 0x52, 0x47, 0x6C, 0x6E, 0x61, 0x55, ++ 0x4E, 0x6C, 0x63, 0x6E, 0x51, 0x67, 0x53, 0x57, 0x35, 0x6A, 0x4D, 0x52, 0x6B, 0x77, 0x46, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4C, 0x45, 0x78, 0x42, 0x33, 0x64, 0x33, 0x63, 0x75, 0x5A, 0x47, 0x6C, 0x6E, 0x61, 0x57, 0x4E, 0x6C, 0x63, 0x6E, ++ 0x51, 0x75, 0x59, 0x32, 0x39, 0x74, 0x4D, 0x53, 0x41, 0x77, 0x0A, 0x48, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x64, 0x45, 0x61, 0x57, 0x64, 0x70, 0x51, 0x32, 0x56, 0x79, 0x64, 0x43, 0x42, 0x48, 0x62, 0x47, 0x39, 0x69, 0x59, ++ 0x57, 0x77, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x48, 0x4D, 0x6A, 0x41, 0x65, 0x46, 0x77, 0x30, 0x78, 0x4D, 0x7A, 0x41, 0x34, 0x4D, 0x44, 0x45, 0x78, 0x4D, 0x6A, 0x41, 0x77, 0x4D, 0x44, 0x42, 0x61, 0x46, 0x77, 0x30, 0x7A, 0x4F, ++ 0x44, 0x41, 0x78, 0x4D, 0x54, 0x55, 0x78, 0x0A, 0x4D, 0x6A, 0x41, 0x77, 0x4D, 0x44, 0x42, 0x61, 0x4D, 0x47, 0x45, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6C, 0x56, 0x54, 0x4D, 0x52, 0x55, 0x77, ++ 0x45, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x45, 0x77, 0x78, 0x45, 0x61, 0x57, 0x64, 0x70, 0x51, 0x32, 0x56, 0x79, 0x64, 0x43, 0x42, 0x4A, 0x62, 0x6D, 0x4D, 0x78, 0x47, 0x54, 0x41, 0x58, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x73, 0x54, ++ 0x45, 0x48, 0x64, 0x33, 0x0A, 0x64, 0x79, 0x35, 0x6B, 0x61, 0x57, 0x64, 0x70, 0x59, 0x32, 0x56, 0x79, 0x64, 0x43, 0x35, 0x6A, 0x62, 0x32, 0x30, 0x78, 0x49, 0x44, 0x41, 0x65, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x46, 0x30, 0x52, ++ 0x70, 0x5A, 0x32, 0x6C, 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x49, 0x45, 0x64, 0x73, 0x62, 0x32, 0x4A, 0x68, 0x62, 0x43, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x63, 0x79, 0x4D, 0x49, 0x49, 0x42, 0x49, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, ++ 0x71, 0x0A, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x45, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x51, 0x38, 0x41, 0x4D, 0x49, 0x49, 0x42, 0x43, 0x67, 0x4B, 0x43, 0x41, 0x51, 0x45, 0x41, 0x75, 0x7A, 0x66, 0x4E, 0x4E, 0x4E, ++ 0x78, 0x37, 0x61, 0x38, 0x6D, 0x79, 0x61, 0x4A, 0x43, 0x74, 0x53, 0x6E, 0x58, 0x2F, 0x52, 0x72, 0x6F, 0x68, 0x43, 0x67, 0x69, 0x4E, 0x39, 0x52, 0x6C, 0x55, 0x79, 0x66, 0x75, 0x49, 0x32, 0x2F, 0x4F, 0x75, 0x38, 0x6A, 0x71, 0x4A, 0x0A, 0x6B, ++ 0x54, 0x78, 0x36, 0x35, 0x71, 0x73, 0x47, 0x47, 0x6D, 0x76, 0x50, 0x72, 0x43, 0x33, 0x6F, 0x58, 0x67, 0x6B, 0x6B, 0x52, 0x4C, 0x70, 0x69, 0x6D, 0x6E, 0x37, 0x57, 0x6F, 0x36, 0x68, 0x2B, 0x34, 0x46, 0x52, 0x31, 0x49, 0x41, 0x57, 0x73, 0x55, ++ 0x4C, 0x65, 0x63, 0x59, 0x78, 0x70, 0x73, 0x4D, 0x4E, 0x7A, 0x61, 0x48, 0x78, 0x6D, 0x78, 0x31, 0x78, 0x37, 0x65, 0x2F, 0x64, 0x66, 0x67, 0x79, 0x35, 0x53, 0x44, 0x4E, 0x36, 0x37, 0x73, 0x48, 0x30, 0x4E, 0x4F, 0x0A, 0x33, 0x58, 0x73, 0x73, ++ 0x30, 0x72, 0x30, 0x75, 0x70, 0x53, 0x2F, 0x6B, 0x71, 0x62, 0x69, 0x74, 0x4F, 0x74, 0x53, 0x5A, 0x70, 0x4C, 0x59, 0x6C, 0x36, 0x5A, 0x74, 0x72, 0x41, 0x47, 0x43, 0x53, 0x59, 0x50, 0x39, 0x50, 0x49, 0x55, 0x6B, 0x59, 0x39, 0x32, 0x65, 0x51, ++ 0x71, 0x32, 0x45, 0x47, 0x6E, 0x49, 0x2F, 0x79, 0x75, 0x75, 0x6D, 0x30, 0x36, 0x5A, 0x49, 0x79, 0x61, 0x37, 0x58, 0x7A, 0x56, 0x2B, 0x68, 0x64, 0x47, 0x38, 0x32, 0x4D, 0x48, 0x61, 0x75, 0x56, 0x0A, 0x42, 0x4A, 0x56, 0x4A, 0x38, 0x7A, 0x55, ++ 0x74, 0x6C, 0x75, 0x4E, 0x4A, 0x62, 0x64, 0x31, 0x33, 0x34, 0x2F, 0x74, 0x4A, 0x53, 0x37, 0x53, 0x73, 0x56, 0x51, 0x65, 0x70, 0x6A, 0x35, 0x57, 0x7A, 0x74, 0x43, 0x4F, 0x37, 0x54, 0x47, 0x31, 0x46, 0x38, 0x50, 0x61, 0x70, 0x73, 0x70, 0x55, ++ 0x77, 0x74, 0x50, 0x31, 0x4D, 0x56, 0x59, 0x77, 0x6E, 0x53, 0x6C, 0x63, 0x55, 0x66, 0x49, 0x4B, 0x64, 0x7A, 0x58, 0x4F, 0x53, 0x30, 0x78, 0x5A, 0x4B, 0x42, 0x67, 0x79, 0x4D, 0x0A, 0x55, 0x4E, 0x47, 0x50, 0x48, 0x67, 0x6D, 0x2B, 0x46, 0x36, ++ 0x48, 0x6D, 0x49, 0x63, 0x72, 0x39, 0x67, 0x2B, 0x55, 0x51, 0x76, 0x49, 0x4F, 0x6C, 0x43, 0x73, 0x52, 0x6E, 0x4B, 0x50, 0x5A, 0x7A, 0x46, 0x42, 0x51, 0x39, 0x52, 0x6E, 0x62, 0x44, 0x68, 0x78, 0x53, 0x4A, 0x49, 0x54, 0x52, 0x4E, 0x72, 0x77, ++ 0x39, 0x46, 0x44, 0x4B, 0x5A, 0x4A, 0x6F, 0x62, 0x71, 0x37, 0x6E, 0x4D, 0x57, 0x78, 0x4D, 0x34, 0x4D, 0x70, 0x68, 0x51, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x0A, 0x6F, 0x30, 0x49, 0x77, 0x51, 0x44, 0x41, 0x50, 0x42, 0x67, 0x4E, 0x56, 0x48, ++ 0x52, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x54, 0x41, 0x44, 0x41, 0x51, 0x48, 0x2F, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x42, 0x68, 0x6A, 0x41, 0x64, 0x42, ++ 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x54, 0x69, 0x4A, 0x55, 0x49, 0x42, 0x69, 0x56, 0x35, 0x75, 0x4E, 0x75, 0x0A, 0x35, 0x67, 0x2F, 0x36, 0x2B, 0x72, 0x6B, 0x53, 0x37, 0x51, 0x59, 0x58, 0x6A, 0x7A, 0x6B, 0x77, ++ 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x45, 0x42, 0x41, 0x47, 0x42, 0x6E, 0x4B, 0x4A, 0x52, 0x76, 0x44, 0x6B, 0x68, 0x6A, 0x36, 0x7A, 0x48, 0x64, ++ 0x36, 0x6D, 0x63, 0x59, 0x31, 0x59, 0x6C, 0x39, 0x50, 0x4D, 0x57, 0x4C, 0x53, 0x6E, 0x2F, 0x70, 0x76, 0x74, 0x73, 0x72, 0x0A, 0x46, 0x39, 0x2B, 0x77, 0x58, 0x33, 0x4E, 0x33, 0x4B, 0x6A, 0x49, 0x54, 0x4F, 0x59, 0x46, 0x6E, 0x51, 0x6F, 0x51, ++ 0x6A, 0x38, 0x6B, 0x56, 0x6E, 0x4E, 0x65, 0x79, 0x49, 0x76, 0x2F, 0x69, 0x50, 0x73, 0x47, 0x45, 0x4D, 0x4E, 0x4B, 0x53, 0x75, 0x49, 0x45, 0x79, 0x45, 0x78, 0x74, 0x76, 0x34, 0x4E, 0x65, 0x46, 0x32, 0x32, 0x64, 0x2B, 0x6D, 0x51, 0x72, 0x76, ++ 0x48, 0x52, 0x41, 0x69, 0x47, 0x66, 0x7A, 0x5A, 0x30, 0x4A, 0x46, 0x72, 0x61, 0x62, 0x41, 0x30, 0x55, 0x0A, 0x57, 0x54, 0x57, 0x39, 0x38, 0x6B, 0x6E, 0x64, 0x74, 0x68, 0x2F, 0x4A, 0x73, 0x77, 0x31, 0x48, 0x4B, 0x6A, 0x32, 0x5A, 0x4C, 0x37, ++ 0x74, 0x63, 0x75, 0x37, 0x58, 0x55, 0x49, 0x4F, 0x47, 0x5A, 0x58, 0x31, 0x4E, 0x47, 0x46, 0x64, 0x74, 0x6F, 0x6D, 0x2F, 0x44, 0x7A, 0x4D, 0x4E, 0x55, 0x2B, 0x4D, 0x65, 0x4B, 0x4E, 0x68, 0x4A, 0x37, 0x6A, 0x69, 0x74, 0x72, 0x61, 0x6C, 0x6A, ++ 0x34, 0x31, 0x45, 0x36, 0x56, 0x66, 0x38, 0x50, 0x6C, 0x77, 0x55, 0x48, 0x42, 0x48, 0x0A, 0x51, 0x52, 0x46, 0x58, 0x47, 0x55, 0x37, 0x41, 0x6A, 0x36, 0x34, 0x47, 0x78, 0x4A, 0x55, 0x54, 0x46, 0x79, 0x38, 0x62, 0x4A, 0x5A, 0x39, 0x31, 0x38, ++ 0x72, 0x47, 0x4F, 0x6D, 0x61, 0x46, 0x76, 0x45, 0x37, 0x46, 0x42, 0x63, 0x66, 0x36, 0x49, 0x4B, 0x73, 0x68, 0x50, 0x45, 0x43, 0x42, 0x56, 0x31, 0x2F, 0x4D, 0x55, 0x52, 0x65, 0x58, 0x67, 0x52, 0x50, 0x54, 0x71, 0x68, 0x35, 0x55, 0x79, 0x6B, ++ 0x77, 0x37, 0x2B, 0x55, 0x30, 0x62, 0x36, 0x4C, 0x4A, 0x33, 0x2F, 0x0A, 0x69, 0x79, 0x4B, 0x35, 0x53, 0x39, 0x6B, 0x4A, 0x52, 0x61, 0x54, 0x65, 0x70, 0x4C, 0x69, 0x61, 0x57, 0x4E, 0x30, 0x62, 0x66, 0x56, 0x4B, 0x66, 0x6A, 0x6C, 0x6C, 0x44, ++ 0x69, 0x49, 0x47, 0x6B, 0x6E, 0x69, 0x62, 0x56, 0x62, 0x36, 0x33, 0x64, 0x44, 0x63, 0x59, 0x33, 0x66, 0x65, 0x30, 0x44, 0x6B, 0x68, 0x76, 0x6C, 0x64, 0x31, 0x39, 0x32, 0x37, 0x6A, 0x79, 0x4E, 0x78, 0x46, 0x31, 0x57, 0x57, 0x36, 0x4C, 0x5A, ++ 0x5A, 0x6D, 0x36, 0x7A, 0x4E, 0x54, 0x66, 0x6C, 0x0A, 0x4D, 0x72, 0x59, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, ++ 0x0A, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x33, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, ++ 0x43, 0x50, 0x7A, 0x43, 0x43, 0x41, 0x63, 0x57, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x42, 0x56, 0x56, 0x57, 0x76, 0x50, 0x4A, 0x65, 0x70, 0x44, 0x55, 0x31, 0x77, 0x36, 0x51, 0x50, 0x31, 0x61, 0x74, 0x46, 0x63, 0x6A, 0x41, ++ 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x7A, 0x42, 0x68, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x56, 0x0A, 0x55, 0x7A, 0x45, 0x56, 0x4D, 0x42, ++ 0x4D, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x4D, 0x52, 0x47, 0x6C, 0x6E, 0x61, 0x55, 0x4E, 0x6C, 0x63, 0x6E, 0x51, 0x67, 0x53, 0x57, 0x35, 0x6A, 0x4D, 0x52, 0x6B, 0x77, 0x46, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4C, 0x45, 0x78, ++ 0x42, 0x33, 0x64, 0x33, 0x63, 0x75, 0x5A, 0x47, 0x6C, 0x6E, 0x61, 0x57, 0x4E, 0x6C, 0x63, 0x6E, 0x51, 0x75, 0x59, 0x32, 0x39, 0x74, 0x4D, 0x53, 0x41, 0x77, 0x48, 0x67, 0x59, 0x44, 0x0A, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x64, 0x45, 0x61, ++ 0x57, 0x64, 0x70, 0x51, 0x32, 0x56, 0x79, 0x64, 0x43, 0x42, 0x48, 0x62, 0x47, 0x39, 0x69, 0x59, 0x57, 0x77, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x48, 0x4D, 0x7A, 0x41, 0x65, 0x46, 0x77, 0x30, 0x78, 0x4D, 0x7A, 0x41, 0x34, 0x4D, ++ 0x44, 0x45, 0x78, 0x4D, 0x6A, 0x41, 0x77, 0x4D, 0x44, 0x42, 0x61, 0x46, 0x77, 0x30, 0x7A, 0x4F, 0x44, 0x41, 0x78, 0x4D, 0x54, 0x55, 0x78, 0x4D, 0x6A, 0x41, 0x77, 0x0A, 0x4D, 0x44, 0x42, 0x61, 0x4D, 0x47, 0x45, 0x78, 0x43, 0x7A, 0x41, 0x4A, ++ 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6C, 0x56, 0x54, 0x4D, 0x52, 0x55, 0x77, 0x45, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x45, 0x77, 0x78, 0x45, 0x61, 0x57, 0x64, 0x70, 0x51, 0x32, 0x56, 0x79, 0x64, 0x43, 0x42, 0x4A, ++ 0x62, 0x6D, 0x4D, 0x78, 0x47, 0x54, 0x41, 0x58, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x73, 0x54, 0x45, 0x48, 0x64, 0x33, 0x64, 0x79, 0x35, 0x6B, 0x0A, 0x61, 0x57, 0x64, 0x70, 0x59, 0x32, 0x56, 0x79, 0x64, 0x43, 0x35, 0x6A, 0x62, 0x32, 0x30, ++ 0x78, 0x49, 0x44, 0x41, 0x65, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x46, 0x30, 0x52, 0x70, 0x5A, 0x32, 0x6C, 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x49, 0x45, 0x64, 0x73, 0x62, 0x32, 0x4A, 0x68, 0x62, 0x43, 0x42, 0x53, 0x62, 0x32, 0x39, ++ 0x30, 0x49, 0x45, 0x63, 0x7A, 0x4D, 0x48, 0x59, 0x77, 0x45, 0x41, 0x59, 0x48, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x43, 0x0A, 0x41, 0x51, 0x59, 0x46, 0x4B, 0x34, 0x45, 0x45, 0x41, 0x43, 0x49, 0x44, 0x59, 0x67, 0x41, 0x45, 0x33, 0x61, ++ 0x66, 0x5A, 0x75, 0x34, 0x71, 0x34, 0x43, 0x2F, 0x73, 0x4C, 0x66, 0x79, 0x48, 0x53, 0x38, 0x4C, 0x36, 0x2B, 0x63, 0x2F, 0x4D, 0x7A, 0x58, 0x52, 0x71, 0x38, 0x4E, 0x4F, 0x72, 0x65, 0x78, 0x70, 0x75, 0x38, 0x30, 0x4A, 0x58, 0x32, 0x38, 0x4D, ++ 0x7A, 0x51, 0x43, 0x37, 0x70, 0x68, 0x57, 0x31, 0x46, 0x47, 0x66, 0x70, 0x34, 0x74, 0x6E, 0x2B, 0x36, 0x4F, 0x0A, 0x59, 0x77, 0x77, 0x58, 0x37, 0x41, 0x64, 0x77, 0x39, 0x63, 0x2B, 0x45, 0x4C, 0x6B, 0x43, 0x44, 0x6E, 0x4F, 0x67, 0x2F, 0x51, ++ 0x57, 0x30, 0x37, 0x72, 0x64, 0x4F, 0x6B, 0x46, 0x46, 0x6B, 0x32, 0x65, 0x4A, 0x30, 0x44, 0x51, 0x2B, 0x34, 0x51, 0x45, 0x32, 0x78, 0x79, 0x33, 0x71, 0x36, 0x49, 0x70, 0x36, 0x46, 0x72, 0x74, 0x55, 0x50, 0x4F, 0x5A, 0x39, 0x77, 0x6A, 0x2F, ++ 0x77, 0x4D, 0x63, 0x6F, 0x2B, 0x49, 0x2B, 0x6F, 0x30, 0x49, 0x77, 0x51, 0x44, 0x41, 0x50, 0x0A, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x52, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x54, 0x41, 0x44, 0x41, 0x51, 0x48, 0x2F, 0x4D, 0x41, 0x34, 0x47, ++ 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x42, 0x68, 0x6A, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x73, 0x39, 0x74, 0x49, 0x70, 0x50, 0x6D, 0x68, ++ 0x78, 0x64, 0x69, 0x75, 0x4E, 0x6B, 0x48, 0x4D, 0x45, 0x57, 0x4E, 0x70, 0x0A, 0x59, 0x69, 0x6D, 0x38, 0x53, 0x38, 0x59, 0x77, 0x43, 0x67, 0x59, 0x49, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x45, 0x41, 0x77, 0x4D, 0x44, 0x61, 0x41, 0x41, ++ 0x77, 0x5A, 0x51, 0x49, 0x78, 0x41, 0x4B, 0x32, 0x38, 0x38, 0x6D, 0x77, 0x2F, 0x45, 0x6B, 0x72, 0x52, 0x4C, 0x54, 0x6E, 0x44, 0x43, 0x67, 0x6D, 0x58, 0x63, 0x2F, 0x53, 0x49, 0x4E, 0x6F, 0x79, 0x49, 0x4A, 0x37, 0x76, 0x6D, 0x69, 0x49, 0x31, ++ 0x51, 0x68, 0x61, 0x64, 0x6A, 0x2B, 0x5A, 0x34, 0x79, 0x0A, 0x33, 0x6D, 0x61, 0x54, 0x44, 0x2F, 0x48, 0x4D, 0x73, 0x51, 0x6D, 0x50, 0x33, 0x57, 0x79, 0x72, 0x2B, 0x6D, 0x74, 0x2F, 0x6F, 0x41, 0x49, 0x77, 0x4F, 0x57, 0x5A, 0x62, 0x77, 0x6D, ++ 0x53, 0x4E, 0x75, 0x4A, 0x35, 0x51, 0x33, 0x4B, 0x6A, 0x56, 0x53, 0x61, 0x4C, 0x74, 0x78, 0x39, 0x7A, 0x52, 0x53, 0x58, 0x38, 0x58, 0x41, 0x62, 0x6A, 0x49, 0x68, 0x6F, 0x39, 0x4F, 0x6A, 0x49, 0x67, 0x72, 0x71, 0x4A, 0x71, 0x70, 0x69, 0x73, ++ 0x58, 0x52, 0x41, 0x4C, 0x33, 0x34, 0x0A, 0x56, 0x4F, 0x4B, 0x61, 0x35, 0x56, 0x74, 0x38, 0x73, 0x79, 0x63, 0x58, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, ++ 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x34, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, ++ 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x6B, 0x44, 0x43, 0x43, 0x41, 0x33, 0x69, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x42, 0x5A, 0x73, 0x62, 0x56, 0x35, 0x36, 0x4F, 0x49, 0x54, 0x4C, 0x69, 0x4F, 0x51, 0x65, ++ 0x39, 0x70, 0x33, 0x64, 0x31, 0x58, 0x44, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x77, 0x46, 0x41, 0x44, 0x42, 0x69, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, ++ 0x47, 0x0A, 0x45, 0x77, 0x4A, 0x56, 0x55, 0x7A, 0x45, 0x56, 0x4D, 0x42, 0x4D, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x4D, 0x52, 0x47, 0x6C, 0x6E, 0x61, 0x55, 0x4E, 0x6C, 0x63, 0x6E, 0x51, 0x67, 0x53, 0x57, 0x35, 0x6A, 0x4D, 0x52, ++ 0x6B, 0x77, 0x46, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4C, 0x45, 0x78, 0x42, 0x33, 0x64, 0x33, 0x63, 0x75, 0x5A, 0x47, 0x6C, 0x6E, 0x61, 0x57, 0x4E, 0x6C, 0x63, 0x6E, 0x51, 0x75, 0x59, 0x32, 0x39, 0x74, 0x4D, 0x53, 0x45, 0x77, 0x0A, 0x48, ++ 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x68, 0x45, 0x61, 0x57, 0x64, 0x70, 0x51, 0x32, 0x56, 0x79, 0x64, 0x43, 0x42, 0x55, 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x47, 0x56, 0x6B, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x52, ++ 0x7A, 0x51, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x54, 0x4D, 0x77, 0x4F, 0x44, 0x41, 0x78, 0x4D, 0x54, 0x49, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x57, 0x68, 0x63, 0x4E, 0x4D, 0x7A, 0x67, 0x77, 0x4D, 0x54, 0x45, 0x31, 0x0A, 0x4D, 0x54, 0x49, 0x77, ++ 0x4D, 0x44, 0x41, 0x77, 0x57, 0x6A, 0x42, 0x69, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x56, 0x55, 0x7A, 0x45, 0x56, 0x4D, 0x42, 0x4D, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x4D, ++ 0x52, 0x47, 0x6C, 0x6E, 0x61, 0x55, 0x4E, 0x6C, 0x63, 0x6E, 0x51, 0x67, 0x53, 0x57, 0x35, 0x6A, 0x4D, 0x52, 0x6B, 0x77, 0x46, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4C, 0x45, 0x78, 0x42, 0x33, 0x0A, 0x64, 0x33, 0x63, 0x75, 0x5A, 0x47, 0x6C, ++ 0x6E, 0x61, 0x57, 0x4E, 0x6C, 0x63, 0x6E, 0x51, 0x75, 0x59, 0x32, 0x39, 0x74, 0x4D, 0x53, 0x45, 0x77, 0x48, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x68, 0x45, 0x61, 0x57, 0x64, 0x70, 0x51, 0x32, 0x56, 0x79, 0x64, 0x43, 0x42, ++ 0x55, 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x47, 0x56, 0x6B, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x52, 0x7A, 0x51, 0x77, 0x67, 0x67, 0x49, 0x69, 0x4D, 0x41, 0x30, 0x47, 0x0A, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, ++ 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x49, 0x4B, 0x41, 0x6F, 0x49, 0x43, 0x41, 0x51, 0x43, 0x2F, 0x35, 0x70, 0x42, 0x7A, 0x61, 0x4E, 0x36, 0x37, 0x35, 0x46, 0x31, 0x4B, 0x50, 0x44, ++ 0x41, 0x69, 0x4D, 0x47, 0x6B, 0x7A, 0x37, 0x4D, 0x4B, 0x6E, 0x4A, 0x53, 0x37, 0x4A, 0x49, 0x54, 0x33, 0x79, 0x69, 0x74, 0x68, 0x5A, 0x77, 0x75, 0x45, 0x70, 0x0A, 0x70, 0x7A, 0x31, 0x59, 0x71, 0x33, 0x61, 0x61, 0x7A, 0x61, 0x35, 0x37, 0x47, ++ 0x34, 0x51, 0x4E, 0x78, 0x44, 0x41, 0x66, 0x38, 0x78, 0x75, 0x6B, 0x4F, 0x42, 0x62, 0x72, 0x56, 0x73, 0x61, 0x58, 0x62, 0x52, 0x32, 0x72, 0x73, 0x6E, 0x6E, 0x79, 0x79, 0x68, 0x48, 0x53, 0x35, 0x46, 0x2F, 0x57, 0x42, 0x54, 0x78, 0x53, 0x44, ++ 0x31, 0x49, 0x66, 0x78, 0x70, 0x34, 0x56, 0x70, 0x58, 0x36, 0x2B, 0x6E, 0x36, 0x6C, 0x58, 0x46, 0x6C, 0x6C, 0x56, 0x63, 0x71, 0x39, 0x6F, 0x0A, 0x6B, 0x33, 0x44, 0x43, 0x73, 0x72, 0x70, 0x31, 0x6D, 0x57, 0x70, 0x7A, 0x4D, 0x70, 0x54, 0x52, ++ 0x45, 0x45, 0x51, 0x51, 0x4C, 0x74, 0x2B, 0x43, 0x38, 0x77, 0x65, 0x45, 0x35, 0x6E, 0x51, 0x37, 0x62, 0x58, 0x48, 0x69, 0x4C, 0x51, 0x77, 0x62, 0x37, 0x69, 0x44, 0x56, 0x79, 0x53, 0x41, 0x64, 0x59, 0x79, 0x6B, 0x74, 0x7A, 0x75, 0x78, 0x65, ++ 0x54, 0x73, 0x69, 0x54, 0x2B, 0x43, 0x46, 0x68, 0x6D, 0x7A, 0x54, 0x72, 0x42, 0x63, 0x5A, 0x65, 0x37, 0x46, 0x73, 0x61, 0x0A, 0x76, 0x4F, 0x76, 0x4A, 0x7A, 0x38, 0x32, 0x73, 0x4E, 0x45, 0x42, 0x66, 0x73, 0x58, 0x70, 0x6D, 0x37, 0x6E, 0x66, ++ 0x49, 0x53, 0x4B, 0x68, 0x6D, 0x56, 0x31, 0x65, 0x66, 0x56, 0x46, 0x69, 0x4F, 0x44, 0x43, 0x75, 0x33, 0x54, 0x36, 0x63, 0x77, 0x32, 0x56, 0x62, 0x75, 0x79, 0x6E, 0x74, 0x64, 0x34, 0x36, 0x33, 0x4A, 0x54, 0x31, 0x37, 0x6C, 0x4E, 0x65, 0x63, ++ 0x78, 0x79, 0x39, 0x71, 0x54, 0x58, 0x74, 0x79, 0x4F, 0x6A, 0x34, 0x44, 0x61, 0x74, 0x70, 0x47, 0x59, 0x0A, 0x51, 0x4A, 0x42, 0x35, 0x77, 0x33, 0x6A, 0x48, 0x74, 0x72, 0x48, 0x45, 0x74, 0x57, 0x6F, 0x59, 0x4F, 0x41, 0x4D, 0x51, 0x6A, 0x64, ++ 0x6A, 0x55, 0x4E, 0x36, 0x51, 0x75, 0x42, 0x58, 0x32, 0x49, 0x39, 0x59, 0x49, 0x2B, 0x45, 0x4A, 0x46, 0x77, 0x71, 0x31, 0x57, 0x43, 0x51, 0x54, 0x4C, 0x58, 0x32, 0x77, 0x52, 0x7A, 0x4B, 0x6D, 0x36, 0x52, 0x41, 0x58, 0x77, 0x68, 0x54, 0x4E, ++ 0x53, 0x38, 0x72, 0x68, 0x73, 0x44, 0x64, 0x56, 0x31, 0x34, 0x5A, 0x74, 0x6B, 0x36, 0x0A, 0x4D, 0x55, 0x53, 0x61, 0x4D, 0x30, 0x43, 0x2F, 0x43, 0x4E, 0x64, 0x61, 0x53, 0x61, 0x54, 0x43, 0x35, 0x71, 0x6D, 0x67, 0x5A, 0x39, 0x32, 0x6B, 0x4A, ++ 0x37, 0x79, 0x68, 0x54, 0x7A, 0x6D, 0x31, 0x45, 0x56, 0x67, 0x58, 0x39, 0x79, 0x52, 0x63, 0x52, 0x6F, 0x39, 0x6B, 0x39, 0x38, 0x46, 0x70, 0x69, 0x48, 0x61, 0x59, 0x64, 0x6A, 0x31, 0x5A, 0x58, 0x55, 0x4A, 0x32, 0x68, 0x34, 0x6D, 0x58, 0x61, ++ 0x58, 0x70, 0x49, 0x38, 0x4F, 0x43, 0x69, 0x45, 0x68, 0x74, 0x6D, 0x0A, 0x6D, 0x6E, 0x54, 0x4B, 0x33, 0x6B, 0x73, 0x65, 0x35, 0x77, 0x35, 0x6A, 0x72, 0x75, 0x62, 0x55, 0x37, 0x35, 0x4B, 0x53, 0x4F, 0x70, 0x34, 0x39, 0x33, 0x41, 0x44, 0x6B, ++ 0x52, 0x53, 0x57, 0x4A, 0x74, 0x70, 0x70, 0x45, 0x47, 0x53, 0x74, 0x2B, 0x77, 0x4A, 0x53, 0x30, 0x30, 0x6D, 0x46, 0x74, 0x36, 0x7A, 0x50, 0x5A, 0x78, 0x64, 0x39, 0x4C, 0x42, 0x41, 0x44, 0x4D, 0x66, 0x52, 0x79, 0x56, 0x77, 0x34, 0x2F, 0x33, ++ 0x49, 0x62, 0x4B, 0x79, 0x45, 0x62, 0x65, 0x37, 0x0A, 0x66, 0x2F, 0x4C, 0x56, 0x6A, 0x48, 0x41, 0x73, 0x51, 0x57, 0x43, 0x71, 0x73, 0x57, 0x4D, 0x59, 0x52, 0x4A, 0x55, 0x61, 0x64, 0x6D, 0x4A, 0x2B, 0x39, 0x6F, 0x43, 0x77, 0x2B, 0x2B, 0x68, ++ 0x6B, 0x70, 0x6A, 0x50, 0x52, 0x69, 0x51, 0x66, 0x68, 0x76, 0x62, 0x66, 0x6D, 0x51, 0x36, 0x51, 0x59, 0x75, 0x4B, 0x5A, 0x33, 0x41, 0x65, 0x45, 0x50, 0x6C, 0x41, 0x77, 0x68, 0x48, 0x62, 0x4A, 0x55, 0x4B, 0x53, 0x57, 0x4A, 0x62, 0x4F, 0x55, ++ 0x4F, 0x55, 0x6C, 0x46, 0x48, 0x0A, 0x64, 0x4C, 0x34, 0x6D, 0x72, 0x4C, 0x5A, 0x42, 0x64, 0x64, 0x35, 0x36, 0x72, 0x46, 0x2B, 0x4E, 0x50, 0x38, 0x6D, 0x38, 0x30, 0x30, 0x45, 0x52, 0x45, 0x6C, 0x76, 0x6C, 0x45, 0x46, 0x44, 0x72, 0x4D, 0x63, ++ 0x58, 0x4B, 0x63, 0x68, 0x59, 0x69, 0x43, 0x64, 0x39, 0x38, 0x54, 0x48, 0x55, 0x2F, 0x59, 0x2B, 0x77, 0x68, 0x58, 0x38, 0x51, 0x67, 0x55, 0x57, 0x74, 0x76, 0x73, 0x61, 0x75, 0x47, 0x69, 0x30, 0x2F, 0x43, 0x31, 0x6B, 0x56, 0x66, 0x6E, 0x53, ++ 0x44, 0x38, 0x0A, 0x6F, 0x52, 0x37, 0x46, 0x77, 0x49, 0x2B, 0x69, 0x73, 0x58, 0x34, 0x4B, 0x4A, 0x70, 0x6E, 0x31, 0x35, 0x47, 0x6B, 0x76, 0x6D, 0x42, 0x30, 0x74, 0x39, 0x64, 0x6D, 0x70, 0x73, 0x68, 0x33, 0x6C, 0x47, 0x77, 0x49, 0x44, 0x41, ++ 0x51, 0x41, 0x42, 0x6F, 0x30, 0x49, 0x77, 0x51, 0x44, 0x41, 0x50, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x52, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x54, 0x41, 0x44, 0x41, 0x51, 0x48, 0x2F, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x0A, ++ 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x42, 0x68, 0x6A, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x37, 0x4E, 0x66, 0x6A, 0x67, 0x74, 0x4A, 0x78, 0x58, 0x57, 0x52, 0x4D, ++ 0x33, 0x79, 0x35, 0x6E, 0x50, 0x2B, 0x65, 0x36, 0x6D, 0x4B, 0x34, 0x63, 0x44, 0x30, 0x38, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4D, 0x42, 0x51, 0x41, 0x44, 0x0A, 0x67, 0x67, 0x49, ++ 0x42, 0x41, 0x4C, 0x74, 0x68, 0x32, 0x58, 0x32, 0x70, 0x62, 0x4C, 0x34, 0x58, 0x78, 0x4A, 0x45, 0x62, 0x77, 0x36, 0x47, 0x69, 0x41, 0x49, 0x33, 0x6A, 0x5A, 0x47, 0x67, 0x50, 0x56, 0x73, 0x39, 0x33, 0x72, 0x6E, 0x44, 0x35, 0x2F, 0x5A, 0x70, ++ 0x4B, 0x6D, 0x62, 0x6E, 0x4A, 0x65, 0x46, 0x77, 0x4D, 0x44, 0x46, 0x2F, 0x6B, 0x35, 0x68, 0x51, 0x70, 0x56, 0x67, 0x73, 0x32, 0x53, 0x56, 0x31, 0x45, 0x59, 0x2B, 0x43, 0x74, 0x6E, 0x4A, 0x59, 0x59, 0x0A, 0x5A, 0x68, 0x73, 0x6A, 0x44, 0x54, ++ 0x31, 0x35, 0x36, 0x57, 0x31, 0x72, 0x31, 0x6C, 0x54, 0x34, 0x30, 0x6A, 0x7A, 0x42, 0x51, 0x30, 0x43, 0x75, 0x48, 0x56, 0x44, 0x31, 0x55, 0x76, 0x79, 0x51, 0x4F, 0x37, 0x75, 0x59, 0x6D, 0x57, 0x6C, 0x72, 0x78, 0x38, 0x47, 0x6E, 0x71, 0x47, ++ 0x69, 0x6B, 0x4A, 0x39, 0x79, 0x64, 0x2B, 0x53, 0x65, 0x75, 0x4D, 0x49, 0x57, 0x35, 0x39, 0x6D, 0x64, 0x4E, 0x4F, 0x6A, 0x36, 0x50, 0x57, 0x54, 0x6B, 0x69, 0x55, 0x30, 0x54, 0x72, 0x0A, 0x79, 0x46, 0x30, 0x44, 0x79, 0x75, 0x31, 0x51, 0x65, ++ 0x6E, 0x31, 0x69, 0x49, 0x51, 0x71, 0x41, 0x79, 0x48, 0x4E, 0x6D, 0x30, 0x61, 0x41, 0x46, 0x59, 0x46, 0x2F, 0x6F, 0x70, 0x62, 0x53, 0x6E, 0x72, 0x36, 0x6A, 0x33, 0x62, 0x54, 0x57, 0x63, 0x66, 0x46, 0x71, 0x4B, 0x31, 0x71, 0x49, 0x34, 0x6D, ++ 0x66, 0x4E, 0x34, 0x69, 0x2F, 0x52, 0x4E, 0x30, 0x69, 0x41, 0x4C, 0x33, 0x67, 0x54, 0x75, 0x6A, 0x4A, 0x74, 0x48, 0x67, 0x58, 0x49, 0x4E, 0x77, 0x42, 0x51, 0x79, 0x0A, 0x37, 0x7A, 0x42, 0x5A, 0x4C, 0x71, 0x37, 0x67, 0x63, 0x66, 0x4A, 0x57, ++ 0x35, 0x47, 0x71, 0x58, 0x62, 0x35, 0x4A, 0x51, 0x62, 0x5A, 0x61, 0x4E, 0x61, 0x48, 0x71, 0x61, 0x73, 0x6A, 0x59, 0x55, 0x65, 0x67, 0x62, 0x79, 0x4A, 0x4C, 0x6B, 0x4A, 0x45, 0x56, 0x44, 0x58, 0x43, 0x4C, 0x47, 0x34, 0x69, 0x58, 0x71, 0x45, ++ 0x49, 0x32, 0x46, 0x43, 0x4B, 0x65, 0x57, 0x6A, 0x7A, 0x61, 0x49, 0x67, 0x51, 0x64, 0x66, 0x52, 0x6E, 0x47, 0x54, 0x5A, 0x36, 0x69, 0x61, 0x68, 0x0A, 0x69, 0x78, 0x54, 0x58, 0x54, 0x42, 0x6D, 0x79, 0x55, 0x45, 0x46, 0x78, 0x50, 0x54, 0x39, ++ 0x4E, 0x63, 0x43, 0x4F, 0x47, 0x44, 0x45, 0x72, 0x63, 0x67, 0x64, 0x4C, 0x4D, 0x4D, 0x70, 0x53, 0x45, 0x44, 0x51, 0x67, 0x4A, 0x6C, 0x78, 0x78, 0x50, 0x77, 0x4F, 0x35, 0x72, 0x49, 0x48, 0x51, 0x77, 0x30, 0x75, 0x41, 0x35, 0x4E, 0x42, 0x43, ++ 0x46, 0x49, 0x52, 0x55, 0x42, 0x43, 0x4F, 0x68, 0x56, 0x4D, 0x74, 0x35, 0x78, 0x53, 0x64, 0x6B, 0x6F, 0x46, 0x31, 0x42, 0x4E, 0x0A, 0x35, 0x72, 0x35, 0x4E, 0x30, 0x58, 0x57, 0x73, 0x30, 0x4D, 0x72, 0x37, 0x51, 0x62, 0x68, 0x44, 0x70, 0x61, ++ 0x72, 0x54, 0x77, 0x77, 0x56, 0x45, 0x54, 0x79, 0x77, 0x32, 0x6D, 0x2B, 0x4C, 0x36, 0x34, 0x6B, 0x57, 0x34, 0x49, 0x31, 0x4E, 0x73, 0x42, 0x6D, 0x39, 0x6E, 0x56, 0x58, 0x39, 0x47, 0x74, 0x55, 0x77, 0x2F, 0x62, 0x69, 0x68, 0x61, 0x65, 0x53, ++ 0x62, 0x53, 0x70, 0x4B, 0x68, 0x69, 0x6C, 0x39, 0x49, 0x65, 0x34, 0x75, 0x31, 0x4B, 0x69, 0x37, 0x77, 0x62, 0x0A, 0x2F, 0x55, 0x64, 0x4B, 0x44, 0x64, 0x39, 0x6E, 0x5A, 0x6E, 0x36, 0x79, 0x57, 0x30, 0x48, 0x51, 0x4F, 0x2B, 0x54, 0x30, 0x4F, ++ 0x2F, 0x51, 0x45, 0x59, 0x2B, 0x6E, 0x76, 0x77, 0x6C, 0x51, 0x41, 0x55, 0x61, 0x43, 0x4B, 0x4B, 0x73, 0x6E, 0x4F, 0x65, 0x4D, 0x7A, 0x56, 0x36, 0x6F, 0x63, 0x45, 0x47, 0x4C, 0x50, 0x4F, 0x72, 0x30, 0x6D, 0x49, 0x72, 0x2F, 0x4F, 0x53, 0x6D, ++ 0x62, 0x61, 0x7A, 0x35, 0x6D, 0x45, 0x50, 0x30, 0x6F, 0x55, 0x41, 0x35, 0x31, 0x41, 0x61, 0x0A, 0x35, 0x42, 0x75, 0x56, 0x6E, 0x52, 0x6D, 0x68, 0x75, 0x5A, 0x79, 0x78, 0x6D, 0x37, 0x45, 0x41, 0x48, 0x75, 0x2F, 0x51, 0x44, 0x30, 0x39, 0x43, ++ 0x62, 0x4D, 0x6B, 0x4B, 0x76, 0x4F, 0x35, 0x44, 0x2B, 0x6A, 0x70, 0x78, 0x70, 0x63, 0x68, 0x4E, 0x4A, 0x71, 0x55, 0x31, 0x2F, 0x59, 0x6C, 0x64, 0x76, 0x49, 0x56, 0x69, 0x48, 0x54, 0x4C, 0x53, 0x6F, 0x43, 0x74, 0x55, 0x37, 0x5A, 0x70, 0x58, ++ 0x77, 0x64, 0x76, 0x36, 0x45, 0x4D, 0x38, 0x5A, 0x74, 0x34, 0x74, 0x4B, 0x0A, 0x47, 0x34, 0x38, 0x42, 0x74, 0x69, 0x65, 0x56, 0x55, 0x2B, 0x69, 0x32, 0x69, 0x57, 0x31, 0x62, 0x76, 0x47, 0x6A, 0x55, 0x49, 0x2B, 0x69, 0x4C, 0x55, 0x61, 0x4A, ++ 0x57, 0x2B, 0x66, 0x43, 0x6D, 0x67, 0x4B, 0x44, 0x57, 0x48, 0x72, 0x4F, 0x38, 0x44, 0x77, 0x39, 0x54, 0x64, 0x53, 0x6D, 0x71, 0x36, 0x68, 0x4E, 0x33, 0x35, 0x4E, 0x36, 0x4D, 0x67, 0x53, 0x47, 0x74, 0x42, 0x78, 0x42, 0x48, 0x45, 0x61, 0x32, ++ 0x48, 0x50, 0x51, 0x66, 0x52, 0x64, 0x62, 0x7A, 0x50, 0x0A, 0x38, 0x32, 0x5A, 0x2B, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, ++ 0x0A, 0x0A, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, 0x20, 0x52, 0x53, 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x0A, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, ++ 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x32, 0x44, 0x43, 0x43, 0x41, 0x38, 0x43, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, ++ 0x54, 0x4B, 0x72, 0x35, 0x79, 0x74, 0x74, 0x6A, 0x62, 0x2B, 0x41, 0x66, 0x39, 0x30, 0x37, 0x59, 0x57, 0x77, 0x4F, 0x47, 0x6E, 0x54, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x77, 0x46, ++ 0x41, 0x44, 0x43, 0x42, 0x68, 0x54, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x0A, 0x42, 0x68, 0x4D, 0x43, 0x52, 0x30, 0x49, 0x78, 0x47, 0x7A, 0x41, 0x5A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x67, 0x54, 0x45, 0x6B, 0x64, ++ 0x79, 0x5A, 0x57, 0x46, 0x30, 0x5A, 0x58, 0x49, 0x67, 0x54, 0x57, 0x46, 0x75, 0x59, 0x32, 0x68, 0x6C, 0x63, 0x33, 0x52, 0x6C, 0x63, 0x6A, 0x45, 0x51, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x78, 0x4D, 0x48, 0x55, 0x32, 0x46, ++ 0x73, 0x5A, 0x6D, 0x39, 0x79, 0x5A, 0x44, 0x45, 0x61, 0x4D, 0x42, 0x67, 0x47, 0x0A, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x52, 0x51, 0x30, 0x39, 0x4E, 0x54, 0x30, 0x52, 0x50, 0x49, 0x45, 0x4E, 0x42, 0x49, 0x45, 0x78, 0x70, 0x62, 0x57, ++ 0x6C, 0x30, 0x5A, 0x57, 0x51, 0x78, 0x4B, 0x7A, 0x41, 0x70, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x49, 0x6B, 0x4E, 0x50, 0x54, 0x55, 0x39, 0x45, 0x54, 0x79, 0x42, 0x53, 0x55, 0x30, 0x45, 0x67, 0x51, 0x32, 0x56, 0x79, 0x64, 0x47, ++ 0x6C, 0x6D, 0x61, 0x57, 0x4E, 0x68, 0x64, 0x47, 0x6C, 0x76, 0x0A, 0x62, 0x69, 0x42, 0x42, 0x64, 0x58, 0x52, 0x6F, 0x62, 0x33, 0x4A, 0x70, 0x64, 0x48, 0x6B, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x54, 0x41, 0x77, 0x4D, 0x54, 0x45, 0x35, 0x4D, ++ 0x44, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x57, 0x68, 0x63, 0x4E, 0x4D, 0x7A, 0x67, 0x77, 0x4D, 0x54, 0x45, 0x34, 0x4D, 0x6A, 0x4D, 0x31, 0x4F, 0x54, 0x55, 0x35, 0x57, 0x6A, 0x43, 0x42, 0x68, 0x54, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, ++ 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x0A, 0x52, 0x30, 0x49, 0x78, 0x47, 0x7A, 0x41, 0x5A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x67, 0x54, 0x45, 0x6B, 0x64, 0x79, 0x5A, 0x57, 0x46, 0x30, 0x5A, 0x58, 0x49, 0x67, 0x54, 0x57, 0x46, 0x75, ++ 0x59, 0x32, 0x68, 0x6C, 0x63, 0x33, 0x52, 0x6C, 0x63, 0x6A, 0x45, 0x51, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x78, 0x4D, 0x48, 0x55, 0x32, 0x46, 0x73, 0x5A, 0x6D, 0x39, 0x79, 0x5A, 0x44, 0x45, 0x61, 0x4D, 0x42, 0x67, 0x47, ++ 0x41, 0x31, 0x55, 0x45, 0x0A, 0x43, 0x68, 0x4D, 0x52, 0x51, 0x30, 0x39, 0x4E, 0x54, 0x30, 0x52, 0x50, 0x49, 0x45, 0x4E, 0x42, 0x49, 0x45, 0x78, 0x70, 0x62, 0x57, 0x6C, 0x30, 0x5A, 0x57, 0x51, 0x78, 0x4B, 0x7A, 0x41, 0x70, 0x42, 0x67, 0x4E, ++ 0x56, 0x42, 0x41, 0x4D, 0x54, 0x49, 0x6B, 0x4E, 0x50, 0x54, 0x55, 0x39, 0x45, 0x54, 0x79, 0x42, 0x53, 0x55, 0x30, 0x45, 0x67, 0x51, 0x32, 0x56, 0x79, 0x64, 0x47, 0x6C, 0x6D, 0x61, 0x57, 0x4E, 0x68, 0x64, 0x47, 0x6C, 0x76, 0x62, 0x69, 0x42, ++ 0x42, 0x0A, 0x64, 0x58, 0x52, 0x6F, 0x62, 0x33, 0x4A, 0x70, 0x64, 0x48, 0x6B, 0x77, 0x67, 0x67, 0x49, 0x69, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, ++ 0x49, 0x43, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x49, 0x4B, 0x41, 0x6F, 0x49, 0x43, 0x41, 0x51, 0x43, 0x52, 0x36, 0x46, 0x53, 0x53, 0x30, 0x67, 0x70, 0x57, 0x73, 0x61, 0x77, 0x4E, 0x4A, 0x4E, 0x33, 0x46, 0x7A, 0x30, 0x52, 0x6E, 0x0A, 0x64, ++ 0x4A, 0x6B, 0x72, 0x4E, 0x36, 0x4E, 0x39, 0x49, 0x33, 0x41, 0x41, 0x63, 0x62, 0x78, 0x54, 0x33, 0x38, 0x54, 0x36, 0x4B, 0x68, 0x4B, 0x50, 0x53, 0x33, 0x38, 0x51, 0x56, 0x72, 0x32, 0x66, 0x63, 0x48, 0x4B, 0x33, 0x59, 0x58, 0x2F, 0x4A, 0x53, ++ 0x77, 0x38, 0x58, 0x70, 0x7A, 0x33, 0x6A, 0x73, 0x41, 0x52, 0x68, 0x37, 0x76, 0x38, 0x52, 0x6C, 0x38, 0x66, 0x30, 0x68, 0x6A, 0x34, 0x4B, 0x2B, 0x6A, 0x35, 0x63, 0x2B, 0x5A, 0x50, 0x6D, 0x4E, 0x48, 0x72, 0x5A, 0x0A, 0x46, 0x47, 0x76, 0x6E, ++ 0x6E, 0x4C, 0x4F, 0x46, 0x6F, 0x49, 0x4A, 0x36, 0x64, 0x71, 0x39, 0x78, 0x6B, 0x4E, 0x66, 0x73, 0x2F, 0x51, 0x33, 0x36, 0x6E, 0x47, 0x7A, 0x36, 0x33, 0x37, 0x43, 0x43, 0x39, 0x42, 0x52, 0x2B, 0x2B, 0x62, 0x37, 0x45, 0x70, 0x69, 0x39, 0x50, ++ 0x66, 0x35, 0x6C, 0x2F, 0x74, 0x66, 0x78, 0x6E, 0x51, 0x33, 0x4B, 0x39, 0x44, 0x41, 0x44, 0x57, 0x69, 0x65, 0x74, 0x72, 0x4C, 0x4E, 0x50, 0x74, 0x6A, 0x35, 0x67, 0x63, 0x46, 0x4B, 0x74, 0x2B, 0x0A, 0x35, 0x65, 0x4E, 0x75, 0x2F, 0x4E, 0x69, ++ 0x6F, 0x35, 0x4A, 0x49, 0x6B, 0x32, 0x6B, 0x4E, 0x72, 0x59, 0x72, 0x68, 0x56, 0x2F, 0x65, 0x72, 0x42, 0x76, 0x47, 0x79, 0x32, 0x69, 0x2F, 0x4D, 0x4F, 0x6A, 0x5A, 0x72, 0x6B, 0x6D, 0x32, 0x78, 0x70, 0x6D, 0x66, 0x68, 0x34, 0x53, 0x44, 0x42, ++ 0x46, 0x31, 0x61, 0x33, 0x68, 0x44, 0x54, 0x78, 0x46, 0x59, 0x50, 0x77, 0x79, 0x6C, 0x6C, 0x45, 0x6E, 0x76, 0x47, 0x66, 0x44, 0x79, 0x69, 0x36, 0x32, 0x61, 0x2B, 0x70, 0x47, 0x0A, 0x78, 0x38, 0x63, 0x67, 0x6F, 0x4C, 0x45, 0x66, 0x5A, 0x64, ++ 0x35, 0x49, 0x43, 0x4C, 0x71, 0x6B, 0x54, 0x71, 0x6E, 0x79, 0x67, 0x30, 0x59, 0x33, 0x68, 0x4F, 0x76, 0x6F, 0x7A, 0x49, 0x46, 0x49, 0x51, 0x32, 0x64, 0x4F, 0x63, 0x69, 0x71, 0x62, 0x58, 0x4C, 0x31, 0x4D, 0x47, 0x79, 0x69, 0x4B, 0x58, 0x43, ++ 0x4A, 0x37, 0x74, 0x4B, 0x75, 0x59, 0x32, 0x65, 0x37, 0x67, 0x55, 0x59, 0x50, 0x44, 0x43, 0x55, 0x5A, 0x4F, 0x62, 0x54, 0x36, 0x5A, 0x2B, 0x70, 0x55, 0x58, 0x0A, 0x32, 0x6E, 0x77, 0x7A, 0x56, 0x30, 0x45, 0x38, 0x6A, 0x56, 0x48, 0x74, 0x43, ++ 0x37, 0x5A, 0x63, 0x72, 0x79, 0x78, 0x6A, 0x47, 0x74, 0x39, 0x58, 0x79, 0x44, 0x2B, 0x38, 0x36, 0x56, 0x33, 0x45, 0x6D, 0x36, 0x39, 0x46, 0x6D, 0x65, 0x4B, 0x6A, 0x57, 0x69, 0x53, 0x30, 0x75, 0x71, 0x6C, 0x57, 0x50, 0x63, 0x39, 0x76, 0x71, ++ 0x76, 0x39, 0x4A, 0x57, 0x4C, 0x37, 0x77, 0x71, 0x50, 0x2F, 0x30, 0x75, 0x4B, 0x33, 0x70, 0x4E, 0x2F, 0x75, 0x36, 0x75, 0x50, 0x51, 0x4C, 0x0A, 0x4F, 0x76, 0x6E, 0x6F, 0x51, 0x30, 0x49, 0x65, 0x69, 0x64, 0x69, 0x45, 0x79, 0x78, 0x50, 0x78, ++ 0x32, 0x62, 0x76, 0x68, 0x69, 0x57, 0x43, 0x34, 0x6A, 0x43, 0x68, 0x57, 0x72, 0x42, 0x51, 0x64, 0x6E, 0x41, 0x72, 0x6E, 0x63, 0x65, 0x76, 0x50, 0x44, 0x74, 0x30, 0x39, 0x71, 0x5A, 0x61, 0x68, 0x53, 0x4C, 0x30, 0x38, 0x39, 0x36, 0x2B, 0x31, ++ 0x44, 0x53, 0x4A, 0x4D, 0x77, 0x42, 0x47, 0x42, 0x37, 0x46, 0x59, 0x37, 0x39, 0x74, 0x4F, 0x69, 0x34, 0x6C, 0x75, 0x33, 0x0A, 0x73, 0x67, 0x51, 0x69, 0x55, 0x70, 0x57, 0x41, 0x6B, 0x32, 0x6E, 0x6F, 0x6A, 0x6B, 0x78, 0x6C, 0x38, 0x5A, 0x45, ++ 0x44, 0x4C, 0x58, 0x42, 0x30, 0x41, 0x75, 0x71, 0x4C, 0x5A, 0x78, 0x55, 0x70, 0x61, 0x56, 0x49, 0x43, 0x75, 0x39, 0x66, 0x66, 0x55, 0x47, 0x70, 0x56, 0x52, 0x72, 0x2B, 0x67, 0x6F, 0x79, 0x68, 0x68, 0x66, 0x33, 0x44, 0x51, 0x77, 0x36, 0x4B, ++ 0x71, 0x4C, 0x43, 0x47, 0x71, 0x52, 0x38, 0x34, 0x6F, 0x6E, 0x41, 0x5A, 0x46, 0x64, 0x72, 0x2B, 0x43, 0x0A, 0x47, 0x43, 0x65, 0x30, 0x31, 0x61, 0x36, 0x30, 0x79, 0x31, 0x44, 0x6D, 0x61, 0x2F, 0x52, 0x4D, 0x68, 0x6E, 0x45, 0x77, 0x36, 0x61, ++ 0x62, 0x66, 0x46, 0x6F, 0x62, 0x67, 0x32, 0x50, 0x39, 0x41, 0x33, 0x66, 0x76, 0x51, 0x51, 0x6F, 0x68, 0x2F, 0x6F, 0x7A, 0x4D, 0x36, 0x4C, 0x6C, 0x77, 0x65, 0x51, 0x52, 0x47, 0x42, 0x59, 0x38, 0x34, 0x59, 0x63, 0x57, 0x73, 0x72, 0x37, 0x4B, ++ 0x61, 0x4B, 0x74, 0x7A, 0x46, 0x63, 0x4F, 0x6D, 0x70, 0x48, 0x34, 0x4D, 0x4E, 0x35, 0x0A, 0x57, 0x64, 0x59, 0x67, 0x47, 0x71, 0x2F, 0x79, 0x61, 0x70, 0x69, 0x71, 0x63, 0x72, 0x78, 0x58, 0x53, 0x74, 0x4A, 0x4C, 0x6E, 0x62, 0x73, 0x51, 0x2F, ++ 0x4C, 0x42, 0x4D, 0x51, 0x65, 0x58, 0x74, 0x48, 0x54, 0x31, 0x65, 0x4B, 0x4A, 0x32, 0x63, 0x7A, 0x4C, 0x2B, 0x7A, 0x55, 0x64, 0x71, 0x6E, 0x52, 0x2B, 0x57, 0x45, 0x55, 0x77, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x6F, 0x30, 0x49, 0x77, 0x51, ++ 0x44, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x0A, 0x46, 0x67, 0x51, 0x55, 0x75, 0x36, 0x39, 0x2B, 0x41, 0x6A, 0x33, 0x36, 0x70, 0x76, 0x45, 0x38, 0x68, 0x49, 0x36, 0x74, 0x37, 0x6A, 0x69, 0x59, 0x37, 0x4E, 0x6B, 0x79, ++ 0x4D, 0x74, 0x51, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x51, 0x44, 0x41, 0x67, 0x45, 0x47, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, ++ 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x0A, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4D, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x42, 0x41, 0x41, 0x72, 0x78, 0x31, 0x55, 0x61, ++ 0x45, 0x74, 0x36, 0x35, 0x52, 0x75, 0x32, 0x79, 0x79, 0x54, 0x55, 0x45, 0x55, 0x41, 0x4A, 0x4E, 0x4D, 0x6E, 0x4D, 0x76, 0x6C, 0x77, 0x46, 0x54, 0x50, 0x6F, 0x43, 0x57, 0x4F, 0x41, 0x76, 0x6E, 0x39, 0x73, 0x4B, 0x49, 0x4E, 0x39, 0x53, 0x43, ++ 0x59, 0x50, 0x42, 0x4D, 0x74, 0x0A, 0x72, 0x46, 0x61, 0x69, 0x73, 0x4E, 0x5A, 0x2B, 0x45, 0x5A, 0x4C, 0x70, 0x4C, 0x72, 0x71, 0x65, 0x4C, 0x70, 0x70, 0x79, 0x73, 0x62, 0x30, 0x5A, 0x52, 0x47, 0x78, 0x68, 0x4E, 0x61, 0x4B, 0x61, 0x74, 0x42, ++ 0x59, 0x53, 0x61, 0x56, 0x71, 0x4D, 0x34, 0x64, 0x63, 0x2B, 0x70, 0x42, 0x72, 0x6F, 0x4C, 0x77, 0x50, 0x30, 0x72, 0x6D, 0x45, 0x64, 0x45, 0x42, 0x73, 0x71, 0x70, 0x49, 0x74, 0x36, 0x78, 0x66, 0x34, 0x46, 0x70, 0x75, 0x48, 0x41, 0x31, 0x73, ++ 0x6A, 0x2B, 0x0A, 0x6E, 0x71, 0x36, 0x50, 0x4B, 0x37, 0x6F, 0x39, 0x6D, 0x66, 0x6A, 0x59, 0x63, 0x77, 0x6C, 0x59, 0x52, 0x6D, 0x36, 0x6D, 0x6E, 0x50, 0x54, 0x58, 0x4A, 0x39, 0x4F, 0x56, 0x32, 0x6A, 0x65, 0x44, 0x63, 0x68, 0x7A, 0x54, 0x63, ++ 0x2B, 0x43, 0x69, 0x52, 0x35, 0x6B, 0x44, 0x4F, 0x46, 0x33, 0x56, 0x53, 0x58, 0x6B, 0x41, 0x4B, 0x52, 0x7A, 0x48, 0x37, 0x4A, 0x73, 0x67, 0x48, 0x41, 0x63, 0x6B, 0x61, 0x56, 0x64, 0x34, 0x73, 0x6A, 0x6E, 0x38, 0x4F, 0x6F, 0x53, 0x67, 0x0A, ++ 0x74, 0x5A, 0x78, 0x38, 0x6A, 0x62, 0x38, 0x75, 0x6B, 0x32, 0x49, 0x6E, 0x74, 0x7A, 0x6E, 0x61, 0x46, 0x78, 0x69, 0x75, 0x76, 0x54, 0x77, 0x4A, 0x61, 0x50, 0x2B, 0x45, 0x6D, 0x7A, 0x7A, 0x56, 0x31, 0x67, 0x73, 0x44, 0x34, 0x31, 0x65, 0x65, ++ 0x46, 0x50, 0x66, 0x52, 0x36, 0x30, 0x2F, 0x49, 0x76, 0x59, 0x63, 0x6A, 0x74, 0x37, 0x5A, 0x4A, 0x51, 0x33, 0x6D, 0x46, 0x58, 0x4C, 0x72, 0x72, 0x6B, 0x67, 0x75, 0x68, 0x78, 0x75, 0x68, 0x6F, 0x71, 0x45, 0x77, 0x57, 0x0A, 0x73, 0x52, 0x71, ++ 0x5A, 0x43, 0x75, 0x68, 0x54, 0x4C, 0x4A, 0x4B, 0x37, 0x6F, 0x51, 0x6B, 0x59, 0x64, 0x51, 0x78, 0x6C, 0x71, 0x48, 0x76, 0x4C, 0x49, 0x37, 0x63, 0x61, 0x77, 0x69, 0x69, 0x46, 0x77, 0x78, 0x76, 0x2F, 0x30, 0x43, 0x74, 0x69, 0x37, 0x36, 0x52, ++ 0x37, 0x43, 0x5A, 0x47, 0x59, 0x5A, 0x34, 0x77, 0x55, 0x41, 0x63, 0x31, 0x6F, 0x42, 0x6D, 0x70, 0x6A, 0x49, 0x58, 0x55, 0x44, 0x67, 0x49, 0x69, 0x4B, 0x62, 0x6F, 0x48, 0x47, 0x68, 0x66, 0x4B, 0x70, 0x0A, 0x70, 0x43, 0x33, 0x6E, 0x39, 0x4B, ++ 0x55, 0x6B, 0x45, 0x45, 0x65, 0x44, 0x79, 0x73, 0x33, 0x30, 0x6A, 0x58, 0x6C, 0x59, 0x73, 0x51, 0x61, 0x62, 0x35, 0x78, 0x6F, 0x71, 0x32, 0x5A, 0x30, 0x42, 0x31, 0x35, 0x52, 0x39, 0x37, 0x51, 0x4E, 0x4B, 0x79, 0x76, 0x44, 0x62, 0x36, 0x4B, ++ 0x6B, 0x42, 0x50, 0x76, 0x56, 0x57, 0x6D, 0x63, 0x6B, 0x65, 0x6A, 0x6B, 0x6B, 0x39, 0x75, 0x2B, 0x55, 0x4A, 0x75, 0x65, 0x42, 0x50, 0x53, 0x5A, 0x49, 0x39, 0x46, 0x6F, 0x4A, 0x41, 0x0A, 0x7A, 0x4D, 0x78, 0x5A, 0x78, 0x75, 0x59, 0x36, 0x37, ++ 0x52, 0x49, 0x75, 0x61, 0x54, 0x78, 0x73, 0x6C, 0x62, 0x48, 0x39, 0x71, 0x68, 0x31, 0x37, 0x66, 0x34, 0x61, 0x2B, 0x48, 0x67, 0x34, 0x79, 0x52, 0x76, 0x76, 0x37, 0x45, 0x34, 0x39, 0x31, 0x66, 0x30, 0x79, 0x4C, 0x53, 0x30, 0x5A, 0x6A, 0x2F, ++ 0x67, 0x41, 0x30, 0x51, 0x48, 0x44, 0x42, 0x77, 0x37, 0x6D, 0x68, 0x33, 0x61, 0x5A, 0x77, 0x34, 0x67, 0x53, 0x7A, 0x51, 0x62, 0x7A, 0x70, 0x67, 0x4A, 0x48, 0x71, 0x0A, 0x5A, 0x4A, 0x78, 0x36, 0x34, 0x53, 0x49, 0x44, 0x71, 0x5A, 0x78, 0x75, ++ 0x62, 0x77, 0x35, 0x6C, 0x54, 0x32, 0x79, 0x48, 0x68, 0x31, 0x37, 0x7A, 0x62, 0x71, 0x44, 0x35, 0x64, 0x61, 0x57, 0x62, 0x51, 0x4F, 0x68, 0x54, 0x73, 0x69, 0x65, 0x64, 0x53, 0x72, 0x6E, 0x41, 0x64, 0x79, 0x47, 0x4E, 0x2F, 0x34, 0x66, 0x79, ++ 0x33, 0x72, 0x79, 0x4D, 0x37, 0x78, 0x66, 0x66, 0x74, 0x30, 0x6B, 0x4C, 0x30, 0x66, 0x4A, 0x75, 0x4D, 0x41, 0x73, 0x61, 0x44, 0x6B, 0x35, 0x32, 0x0A, 0x37, 0x52, 0x48, 0x38, 0x39, 0x65, 0x6C, 0x57, 0x73, 0x6E, 0x32, 0x2F, 0x78, 0x32, 0x30, ++ 0x4B, 0x6B, 0x34, 0x79, 0x6C, 0x30, 0x4D, 0x43, 0x32, 0x48, 0x62, 0x34, 0x36, 0x54, 0x70, 0x53, 0x69, 0x31, 0x32, 0x35, 0x73, 0x43, 0x38, 0x4B, 0x4B, 0x66, 0x50, 0x6F, 0x67, 0x38, 0x38, 0x54, 0x6B, 0x35, 0x63, 0x30, 0x4E, 0x71, 0x4D, 0x75, ++ 0x52, 0x6B, 0x72, 0x46, 0x38, 0x68, 0x65, 0x79, 0x31, 0x46, 0x47, 0x6C, 0x6D, 0x44, 0x6F, 0x4C, 0x6E, 0x7A, 0x63, 0x37, 0x49, 0x0A, 0x4C, 0x61, 0x5A, 0x52, 0x66, 0x79, 0x48, 0x42, 0x4E, 0x56, 0x4F, 0x46, 0x42, 0x6B, 0x70, 0x64, 0x6E, 0x36, ++ 0x32, 0x37, 0x47, 0x31, 0x39, 0x30, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x55, 0x53, 0x45, 0x52, 0x54, 0x72, ++ 0x75, 0x73, 0x74, 0x20, 0x52, 0x53, 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, ++ 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x33, 0x6A, 0x43, 0x43, 0x41, 0x38, 0x61, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x41, 0x66, ++ 0x31, 0x74, 0x4D, 0x50, 0x79, 0x6A, 0x79, 0x6C, 0x47, 0x6F, 0x47, 0x37, 0x78, 0x6B, 0x44, 0x6A, 0x55, 0x44, 0x4C, 0x54, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x77, 0x46, 0x41, 0x44, ++ 0x43, 0x42, 0x69, 0x44, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x0A, 0x42, 0x68, 0x4D, 0x43, 0x56, 0x56, 0x4D, 0x78, 0x45, 0x7A, 0x41, 0x52, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x67, 0x54, 0x43, 0x6B, 0x35, 0x6C, 0x64, ++ 0x79, 0x42, 0x4B, 0x5A, 0x58, 0x4A, 0x7A, 0x5A, 0x58, 0x6B, 0x78, 0x46, 0x44, 0x41, 0x53, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x63, 0x54, 0x43, 0x30, 0x70, 0x6C, 0x63, 0x6E, 0x4E, 0x6C, 0x65, 0x53, 0x42, 0x44, 0x61, 0x58, 0x52, 0x35, 0x4D, ++ 0x52, 0x34, 0x77, 0x48, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x0A, 0x45, 0x78, 0x56, 0x55, 0x61, 0x47, 0x55, 0x67, 0x56, 0x56, 0x4E, 0x46, 0x55, 0x6C, 0x52, 0x53, 0x56, 0x56, 0x4E, 0x55, 0x49, 0x45, 0x35, 0x6C, 0x64, 0x48, 0x64, 0x76, ++ 0x63, 0x6D, 0x73, 0x78, 0x4C, 0x6A, 0x41, 0x73, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x4A, 0x56, 0x56, 0x54, 0x52, 0x56, 0x4A, 0x55, 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x43, 0x42, 0x53, 0x55, 0x30, 0x45, 0x67, 0x51, 0x32, 0x56, 0x79, ++ 0x64, 0x47, 0x6C, 0x6D, 0x61, 0x57, 0x4E, 0x68, 0x0A, 0x64, 0x47, 0x6C, 0x76, 0x62, 0x69, 0x42, 0x42, 0x64, 0x58, 0x52, 0x6F, 0x62, 0x33, 0x4A, 0x70, 0x64, 0x48, 0x6B, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x54, 0x41, 0x77, 0x4D, 0x6A, 0x41, ++ 0x78, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x57, 0x68, 0x63, 0x4E, 0x4D, 0x7A, 0x67, 0x77, 0x4D, 0x54, 0x45, 0x34, 0x4D, 0x6A, 0x4D, 0x31, 0x4F, 0x54, 0x55, 0x35, 0x57, 0x6A, 0x43, 0x42, 0x69, 0x44, 0x45, 0x4C, 0x4D, 0x41, 0x6B, ++ 0x47, 0x41, 0x31, 0x55, 0x45, 0x0A, 0x42, 0x68, 0x4D, 0x43, 0x56, 0x56, 0x4D, 0x78, 0x45, 0x7A, 0x41, 0x52, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x67, 0x54, 0x43, 0x6B, 0x35, 0x6C, 0x64, 0x79, 0x42, 0x4B, 0x5A, 0x58, 0x4A, 0x7A, 0x5A, 0x58, ++ 0x6B, 0x78, 0x46, 0x44, 0x41, 0x53, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x63, 0x54, 0x43, 0x30, 0x70, 0x6C, 0x63, 0x6E, 0x4E, 0x6C, 0x65, 0x53, 0x42, 0x44, 0x61, 0x58, 0x52, 0x35, 0x4D, 0x52, 0x34, 0x77, 0x48, 0x41, 0x59, 0x44, 0x56, 0x51, ++ 0x51, 0x4B, 0x0A, 0x45, 0x78, 0x56, 0x55, 0x61, 0x47, 0x55, 0x67, 0x56, 0x56, 0x4E, 0x46, 0x55, 0x6C, 0x52, 0x53, 0x56, 0x56, 0x4E, 0x55, 0x49, 0x45, 0x35, 0x6C, 0x64, 0x48, 0x64, 0x76, 0x63, 0x6D, 0x73, 0x78, 0x4C, 0x6A, 0x41, 0x73, 0x42, ++ 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x4A, 0x56, 0x56, 0x54, 0x52, 0x56, 0x4A, 0x55, 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x43, 0x42, 0x53, 0x55, 0x30, 0x45, 0x67, 0x51, 0x32, 0x56, 0x79, 0x64, 0x47, 0x6C, 0x6D, 0x61, 0x57, 0x4E, 0x68, 0x0A, ++ 0x64, 0x47, 0x6C, 0x76, 0x62, 0x69, 0x42, 0x42, 0x64, 0x58, 0x52, 0x6F, 0x62, 0x33, 0x4A, 0x70, 0x64, 0x48, 0x6B, 0x77, 0x67, 0x67, 0x49, 0x69, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, ++ 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x49, 0x4B, 0x41, 0x6F, 0x49, 0x43, 0x41, 0x51, 0x43, 0x41, 0x45, 0x6D, 0x55, 0x58, 0x4E, 0x67, 0x37, 0x44, 0x32, 0x77, 0x69, 0x7A, 0x0A, 0x30, 0x4B, 0x78, ++ 0x58, 0x44, 0x58, 0x62, 0x74, 0x7A, 0x53, 0x66, 0x54, 0x54, 0x4B, 0x31, 0x51, 0x67, 0x32, 0x48, 0x69, 0x71, 0x69, 0x42, 0x4E, 0x43, 0x53, 0x31, 0x6B, 0x43, 0x64, 0x7A, 0x4F, 0x69, 0x5A, 0x2F, 0x4D, 0x50, 0x61, 0x6E, 0x73, 0x39, 0x73, 0x2F, ++ 0x42, 0x33, 0x50, 0x48, 0x54, 0x73, 0x64, 0x5A, 0x37, 0x4E, 0x79, 0x67, 0x52, 0x4B, 0x30, 0x66, 0x61, 0x4F, 0x63, 0x61, 0x38, 0x4F, 0x68, 0x6D, 0x30, 0x58, 0x36, 0x61, 0x39, 0x66, 0x5A, 0x32, 0x6A, 0x0A, 0x59, 0x30, 0x4B, 0x32, 0x64, 0x76, ++ 0x4B, 0x70, 0x4F, 0x79, 0x75, 0x52, 0x2B, 0x4F, 0x4A, 0x76, 0x30, 0x4F, 0x77, 0x57, 0x49, 0x4A, 0x41, 0x4A, 0x50, 0x75, 0x4C, 0x6F, 0x64, 0x4D, 0x6B, 0x59, 0x74, 0x4A, 0x48, 0x55, 0x59, 0x6D, 0x54, 0x62, 0x66, 0x36, 0x4D, 0x47, 0x38, 0x59, ++ 0x67, 0x59, 0x61, 0x70, 0x41, 0x69, 0x50, 0x4C, 0x7A, 0x2B, 0x45, 0x2F, 0x43, 0x48, 0x46, 0x48, 0x76, 0x32, 0x35, 0x42, 0x2B, 0x4F, 0x31, 0x4F, 0x52, 0x52, 0x78, 0x68, 0x46, 0x6E, 0x0A, 0x52, 0x67, 0x68, 0x52, 0x79, 0x34, 0x59, 0x55, 0x56, ++ 0x44, 0x2B, 0x38, 0x4D, 0x2F, 0x35, 0x2B, 0x62, 0x4A, 0x7A, 0x2F, 0x46, 0x70, 0x30, 0x59, 0x76, 0x56, 0x47, 0x4F, 0x4E, 0x61, 0x61, 0x6E, 0x5A, 0x73, 0x68, 0x79, 0x5A, 0x39, 0x73, 0x68, 0x5A, 0x72, 0x48, 0x55, 0x6D, 0x33, 0x67, 0x44, 0x77, ++ 0x46, 0x41, 0x36, 0x36, 0x4D, 0x7A, 0x77, 0x33, 0x4C, 0x79, 0x65, 0x54, 0x50, 0x36, 0x76, 0x42, 0x5A, 0x59, 0x31, 0x48, 0x31, 0x64, 0x61, 0x74, 0x2F, 0x2F, 0x4F, 0x0A, 0x2B, 0x54, 0x32, 0x33, 0x4C, 0x4C, 0x62, 0x32, 0x56, 0x4E, 0x33, 0x49, ++ 0x35, 0x78, 0x49, 0x36, 0x54, 0x61, 0x35, 0x4D, 0x69, 0x72, 0x64, 0x63, 0x6D, 0x72, 0x53, 0x33, 0x49, 0x44, 0x33, 0x4B, 0x66, 0x79, 0x49, 0x30, 0x72, 0x6E, 0x34, 0x37, 0x61, 0x47, 0x59, 0x42, 0x52, 0x4F, 0x63, 0x42, 0x54, 0x6B, 0x5A, 0x54, ++ 0x6D, 0x7A, 0x4E, 0x67, 0x39, 0x35, 0x53, 0x2B, 0x55, 0x7A, 0x65, 0x51, 0x63, 0x30, 0x50, 0x7A, 0x4D, 0x73, 0x4E, 0x54, 0x37, 0x39, 0x75, 0x71, 0x0A, 0x2F, 0x6E, 0x52, 0x4F, 0x61, 0x63, 0x64, 0x72, 0x6A, 0x47, 0x43, 0x54, 0x33, 0x73, 0x54, ++ 0x48, 0x44, 0x4E, 0x2F, 0x68, 0x4D, 0x71, 0x37, 0x4D, 0x6B, 0x7A, 0x74, 0x52, 0x65, 0x4A, 0x56, 0x6E, 0x69, 0x2B, 0x34, 0x39, 0x56, 0x76, 0x34, 0x4D, 0x30, 0x47, 0x6B, 0x50, 0x47, 0x77, 0x2F, 0x7A, 0x4A, 0x53, 0x5A, 0x72, 0x4D, 0x32, 0x33, ++ 0x33, 0x62, 0x6B, 0x66, 0x36, 0x63, 0x30, 0x50, 0x6C, 0x66, 0x67, 0x36, 0x6C, 0x5A, 0x72, 0x45, 0x70, 0x66, 0x44, 0x4B, 0x45, 0x0A, 0x59, 0x31, 0x57, 0x4A, 0x78, 0x41, 0x33, 0x42, 0x6B, 0x31, 0x51, 0x77, 0x47, 0x52, 0x4F, 0x73, 0x30, 0x33, ++ 0x30, 0x33, 0x70, 0x2B, 0x74, 0x64, 0x4F, 0x6D, 0x77, 0x31, 0x58, 0x4E, 0x74, 0x42, 0x31, 0x78, 0x4C, 0x61, 0x71, 0x55, 0x6B, 0x4C, 0x33, 0x39, 0x69, 0x41, 0x69, 0x67, 0x6D, 0x54, 0x59, 0x6F, 0x36, 0x31, 0x5A, 0x73, 0x38, 0x6C, 0x69, 0x4D, ++ 0x32, 0x45, 0x75, 0x4C, 0x45, 0x2F, 0x70, 0x44, 0x6B, 0x50, 0x32, 0x51, 0x4B, 0x65, 0x36, 0x78, 0x4A, 0x4D, 0x0A, 0x6C, 0x58, 0x7A, 0x7A, 0x61, 0x77, 0x57, 0x70, 0x58, 0x68, 0x61, 0x44, 0x7A, 0x4C, 0x68, 0x6E, 0x34, 0x75, 0x67, 0x54, 0x6E, ++ 0x63, 0x78, 0x62, 0x67, 0x74, 0x4E, 0x4D, 0x73, 0x2B, 0x31, 0x62, 0x2F, 0x39, 0x37, 0x6C, 0x63, 0x36, 0x77, 0x6A, 0x4F, 0x79, 0x30, 0x41, 0x76, 0x7A, 0x56, 0x56, 0x64, 0x41, 0x6C, 0x4A, 0x32, 0x45, 0x6C, 0x59, 0x47, 0x6E, 0x2B, 0x53, 0x4E, ++ 0x75, 0x5A, 0x52, 0x6B, 0x67, 0x37, 0x7A, 0x4A, 0x6E, 0x30, 0x63, 0x54, 0x52, 0x65, 0x38, 0x0A, 0x79, 0x65, 0x78, 0x44, 0x4A, 0x74, 0x43, 0x2F, 0x51, 0x56, 0x39, 0x41, 0x71, 0x55, 0x52, 0x45, 0x39, 0x4A, 0x6E, 0x6E, 0x56, 0x34, 0x65, 0x65, ++ 0x55, 0x42, 0x39, 0x58, 0x56, 0x4B, 0x67, 0x2B, 0x2F, 0x58, 0x52, 0x6A, 0x4C, 0x37, 0x46, 0x51, 0x5A, 0x51, 0x6E, 0x6D, 0x57, 0x45, 0x49, 0x75, 0x51, 0x78, 0x70, 0x4D, 0x74, 0x50, 0x41, 0x6C, 0x52, 0x31, 0x6E, 0x36, 0x42, 0x42, 0x36, 0x54, ++ 0x31, 0x43, 0x5A, 0x47, 0x53, 0x6C, 0x43, 0x42, 0x73, 0x74, 0x36, 0x2B, 0x0A, 0x65, 0x4C, 0x66, 0x38, 0x5A, 0x78, 0x58, 0x68, 0x79, 0x56, 0x65, 0x45, 0x48, 0x67, 0x39, 0x6A, 0x31, 0x75, 0x6C, 0x69, 0x75, 0x74, 0x5A, 0x66, 0x56, 0x53, 0x37, ++ 0x71, 0x58, 0x4D, 0x59, 0x6F, 0x43, 0x41, 0x51, 0x6C, 0x4F, 0x62, 0x67, 0x4F, 0x4B, 0x36, 0x6E, 0x79, 0x54, 0x4A, 0x63, 0x63, 0x42, 0x7A, 0x38, 0x4E, 0x55, 0x76, 0x58, 0x74, 0x37, 0x79, 0x2B, 0x43, 0x44, 0x77, 0x49, 0x44, 0x41, 0x51, 0x41, ++ 0x42, 0x6F, 0x30, 0x49, 0x77, 0x51, 0x44, 0x41, 0x64, 0x0A, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x55, 0x33, 0x6D, 0x2F, 0x57, 0x71, 0x6F, 0x72, 0x53, 0x73, 0x39, 0x55, 0x67, 0x4F, 0x48, 0x59, 0x6D, 0x38, ++ 0x43, 0x64, 0x38, 0x72, 0x49, 0x44, 0x5A, 0x73, 0x73, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x51, 0x44, 0x41, 0x67, 0x45, 0x47, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, ++ 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, 0x0A, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4D, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x42, 0x41, ++ 0x46, 0x7A, 0x55, 0x66, 0x41, 0x33, 0x50, 0x39, 0x77, 0x46, 0x39, 0x51, 0x5A, 0x6C, 0x6C, 0x44, 0x48, 0x50, 0x46, 0x55, 0x70, 0x2F, 0x4C, 0x2B, 0x4D, 0x2B, 0x5A, 0x42, 0x6E, 0x38, 0x62, 0x32, 0x6B, 0x4D, 0x56, 0x6E, 0x35, 0x34, 0x43, 0x56, ++ 0x56, 0x65, 0x57, 0x0A, 0x46, 0x50, 0x46, 0x53, 0x50, 0x43, 0x65, 0x48, 0x6C, 0x43, 0x6A, 0x74, 0x48, 0x7A, 0x6F, 0x42, 0x4E, 0x36, 0x4A, 0x32, 0x2F, 0x46, 0x4E, 0x51, 0x77, 0x49, 0x53, 0x62, 0x78, 0x6D, 0x74, 0x4F, 0x75, 0x6F, 0x77, 0x68, ++ 0x54, 0x36, 0x4B, 0x4F, 0x56, 0x57, 0x4B, 0x52, 0x38, 0x32, 0x6B, 0x56, 0x32, 0x4C, 0x79, 0x49, 0x34, 0x38, 0x53, 0x71, 0x43, 0x2F, 0x33, 0x76, 0x71, 0x4F, 0x6C, 0x4C, 0x56, 0x53, 0x6F, 0x47, 0x49, 0x47, 0x31, 0x56, 0x65, 0x43, 0x6B, 0x5A, ++ 0x0A, 0x37, 0x6C, 0x38, 0x77, 0x58, 0x45, 0x73, 0x6B, 0x45, 0x56, 0x58, 0x2F, 0x4A, 0x4A, 0x70, 0x75, 0x58, 0x69, 0x6F, 0x72, 0x37, 0x67, 0x74, 0x4E, 0x6E, 0x33, 0x2F, 0x33, 0x41, 0x54, 0x69, 0x55, 0x46, 0x4A, 0x56, 0x44, 0x42, 0x77, 0x6E, ++ 0x37, 0x59, 0x4B, 0x6E, 0x75, 0x48, 0x4B, 0x73, 0x53, 0x6A, 0x4B, 0x43, 0x61, 0x58, 0x71, 0x65, 0x59, 0x61, 0x6C, 0x6C, 0x74, 0x69, 0x7A, 0x38, 0x49, 0x2B, 0x38, 0x6A, 0x52, 0x52, 0x61, 0x38, 0x59, 0x46, 0x57, 0x53, 0x51, 0x0A, 0x45, 0x67, ++ 0x39, 0x7A, 0x4B, 0x43, 0x37, 0x46, 0x34, 0x69, 0x52, 0x4F, 0x2F, 0x46, 0x6A, 0x73, 0x38, 0x50, 0x52, 0x46, 0x2F, 0x69, 0x4B, 0x7A, 0x36, 0x79, 0x2B, 0x4F, 0x30, 0x74, 0x6C, 0x46, 0x59, 0x51, 0x58, 0x42, 0x6C, 0x32, 0x2B, 0x6F, 0x64, 0x6E, ++ 0x4B, 0x50, 0x69, 0x34, 0x77, 0x32, 0x72, 0x37, 0x38, 0x4E, 0x42, 0x63, 0x35, 0x78, 0x6A, 0x65, 0x61, 0x6D, 0x62, 0x78, 0x39, 0x73, 0x70, 0x6E, 0x46, 0x69, 0x78, 0x64, 0x6A, 0x51, 0x67, 0x33, 0x49, 0x4D, 0x0A, 0x38, 0x57, 0x63, 0x52, 0x69, ++ 0x51, 0x79, 0x63, 0x45, 0x30, 0x78, 0x79, 0x4E, 0x4E, 0x2B, 0x38, 0x31, 0x58, 0x48, 0x66, 0x71, 0x6E, 0x48, 0x64, 0x34, 0x62, 0x6C, 0x73, 0x6A, 0x44, 0x77, 0x53, 0x58, 0x57, 0x58, 0x61, 0x76, 0x56, 0x63, 0x53, 0x74, 0x6B, 0x4E, 0x72, 0x2F, ++ 0x2B, 0x58, 0x65, 0x54, 0x57, 0x59, 0x52, 0x55, 0x63, 0x2B, 0x5A, 0x72, 0x75, 0x77, 0x58, 0x74, 0x75, 0x68, 0x78, 0x6B, 0x59, 0x7A, 0x65, 0x53, 0x66, 0x37, 0x64, 0x4E, 0x58, 0x47, 0x69, 0x0A, 0x46, 0x53, 0x65, 0x55, 0x48, 0x4D, 0x39, 0x68, ++ 0x34, 0x79, 0x61, 0x37, 0x62, 0x36, 0x4E, 0x6E, 0x4A, 0x53, 0x46, 0x64, 0x35, 0x74, 0x30, 0x64, 0x43, 0x79, 0x35, 0x6F, 0x47, 0x7A, 0x75, 0x43, 0x72, 0x2B, 0x79, 0x44, 0x5A, 0x34, 0x58, 0x55, 0x6D, 0x46, 0x46, 0x30, 0x73, 0x62, 0x6D, 0x5A, ++ 0x67, 0x49, 0x6E, 0x2F, 0x66, 0x33, 0x67, 0x5A, 0x58, 0x48, 0x6C, 0x4B, 0x59, 0x43, 0x36, 0x53, 0x51, 0x4B, 0x35, 0x4D, 0x4E, 0x79, 0x6F, 0x73, 0x79, 0x63, 0x64, 0x69, 0x0A, 0x79, 0x41, 0x35, 0x64, 0x39, 0x7A, 0x5A, 0x62, 0x79, 0x75, 0x41, ++ 0x6C, 0x4A, 0x51, 0x47, 0x30, 0x33, 0x52, 0x6F, 0x48, 0x6E, 0x48, 0x63, 0x41, 0x50, 0x39, 0x44, 0x63, 0x31, 0x65, 0x77, 0x39, 0x31, 0x50, 0x71, 0x37, 0x50, 0x38, 0x79, 0x46, 0x31, 0x6D, 0x39, 0x2F, 0x71, 0x53, 0x33, 0x66, 0x75, 0x51, 0x4C, ++ 0x33, 0x39, 0x5A, 0x65, 0x61, 0x74, 0x54, 0x58, 0x61, 0x77, 0x32, 0x65, 0x77, 0x68, 0x30, 0x71, 0x70, 0x4B, 0x4A, 0x34, 0x6A, 0x6A, 0x76, 0x39, 0x63, 0x0A, 0x4A, 0x32, 0x76, 0x68, 0x73, 0x45, 0x2F, 0x7A, 0x42, 0x2B, 0x34, 0x41, 0x4C, 0x74, ++ 0x52, 0x5A, 0x68, 0x38, 0x74, 0x53, 0x51, 0x5A, 0x58, 0x71, 0x39, 0x45, 0x66, 0x58, 0x37, 0x6D, 0x52, 0x42, 0x56, 0x58, 0x79, 0x4E, 0x57, 0x51, 0x4B, 0x56, 0x33, 0x57, 0x4B, 0x64, 0x77, 0x72, 0x6E, 0x75, 0x57, 0x69, 0x68, 0x30, 0x68, 0x4B, ++ 0x57, 0x62, 0x74, 0x35, 0x44, 0x48, 0x44, 0x41, 0x66, 0x66, 0x39, 0x59, 0x6B, 0x32, 0x64, 0x44, 0x4C, 0x57, 0x4B, 0x4D, 0x47, 0x77, 0x0A, 0x73, 0x41, 0x76, 0x67, 0x6E, 0x45, 0x7A, 0x44, 0x48, 0x4E, 0x62, 0x38, 0x34, 0x32, 0x6D, 0x31, 0x52, ++ 0x30, 0x61, 0x42, 0x4C, 0x36, 0x4B, 0x43, 0x71, 0x39, 0x4E, 0x6A, 0x52, 0x48, 0x44, 0x45, 0x6A, 0x66, 0x38, 0x74, 0x4D, 0x37, 0x71, 0x74, 0x6A, 0x33, 0x75, 0x31, 0x63, 0x49, 0x69, 0x75, 0x50, 0x68, 0x6E, 0x50, 0x51, 0x43, 0x6A, 0x59, 0x2F, ++ 0x4D, 0x69, 0x51, 0x75, 0x31, 0x32, 0x5A, 0x49, 0x76, 0x56, 0x53, 0x35, 0x6C, 0x6A, 0x46, 0x48, 0x34, 0x67, 0x78, 0x0A, 0x51, 0x2B, 0x36, 0x49, 0x48, 0x64, 0x66, 0x47, 0x6A, 0x6A, 0x78, 0x44, 0x61, 0x68, 0x32, 0x6E, 0x47, 0x4E, 0x35, 0x39, ++ 0x50, 0x52, 0x62, 0x78, 0x59, 0x76, 0x6E, 0x4B, 0x6B, 0x4B, 0x6A, 0x39, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, ++ 0x55, 0x53, 0x45, 0x52, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x45, 0x43, 0x43, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x0A, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, ++ 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x43, 0x6A, 0x7A, 0x43, 0x43, 0x41, 0x68, 0x57, 0x67, 0x41, 0x77, 0x49, 0x42, ++ 0x41, 0x67, 0x49, 0x51, 0x58, 0x49, 0x75, 0x5A, 0x78, 0x56, 0x71, 0x55, 0x78, 0x64, 0x4A, 0x78, 0x56, 0x74, 0x37, 0x4E, 0x69, 0x59, 0x44, 0x4D, 0x4A, 0x6A, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, ++ 0x41, 0x7A, 0x43, 0x42, 0x69, 0x44, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x0A, 0x56, 0x56, 0x4D, 0x78, 0x45, 0x7A, 0x41, 0x52, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x67, 0x54, 0x43, 0x6B, 0x35, ++ 0x6C, 0x64, 0x79, 0x42, 0x4B, 0x5A, 0x58, 0x4A, 0x7A, 0x5A, 0x58, 0x6B, 0x78, 0x46, 0x44, 0x41, 0x53, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x63, 0x54, 0x43, 0x30, 0x70, 0x6C, 0x63, 0x6E, 0x4E, 0x6C, 0x65, 0x53, 0x42, 0x44, 0x61, 0x58, 0x52, ++ 0x35, 0x4D, 0x52, 0x34, 0x77, 0x48, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x45, 0x78, 0x56, 0x55, 0x0A, 0x61, 0x47, 0x55, 0x67, 0x56, 0x56, 0x4E, 0x46, 0x55, 0x6C, 0x52, 0x53, 0x56, 0x56, 0x4E, 0x55, 0x49, 0x45, 0x35, 0x6C, 0x64, 0x48, ++ 0x64, 0x76, 0x63, 0x6D, 0x73, 0x78, 0x4C, 0x6A, 0x41, 0x73, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x4A, 0x56, 0x56, 0x54, 0x52, 0x56, 0x4A, 0x55, 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x43, 0x42, 0x46, 0x51, 0x30, 0x4D, 0x67, 0x51, 0x32, ++ 0x56, 0x79, 0x64, 0x47, 0x6C, 0x6D, 0x61, 0x57, 0x4E, 0x68, 0x64, 0x47, 0x6C, 0x76, 0x0A, 0x62, 0x69, 0x42, 0x42, 0x64, 0x58, 0x52, 0x6F, 0x62, 0x33, 0x4A, 0x70, 0x64, 0x48, 0x6B, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x54, 0x41, 0x77, 0x4D, ++ 0x6A, 0x41, 0x78, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x57, 0x68, 0x63, 0x4E, 0x4D, 0x7A, 0x67, 0x77, 0x4D, 0x54, 0x45, 0x34, 0x4D, 0x6A, 0x4D, 0x31, 0x4F, 0x54, 0x55, 0x35, 0x57, 0x6A, 0x43, 0x42, 0x69, 0x44, 0x45, 0x4C, 0x4D, ++ 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x0A, 0x56, 0x56, 0x4D, 0x78, 0x45, 0x7A, 0x41, 0x52, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x67, 0x54, 0x43, 0x6B, 0x35, 0x6C, 0x64, 0x79, 0x42, 0x4B, 0x5A, 0x58, 0x4A, 0x7A, ++ 0x5A, 0x58, 0x6B, 0x78, 0x46, 0x44, 0x41, 0x53, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x63, 0x54, 0x43, 0x30, 0x70, 0x6C, 0x63, 0x6E, 0x4E, 0x6C, 0x65, 0x53, 0x42, 0x44, 0x61, 0x58, 0x52, 0x35, 0x4D, 0x52, 0x34, 0x77, 0x48, 0x41, 0x59, 0x44, ++ 0x56, 0x51, 0x51, 0x4B, 0x45, 0x78, 0x56, 0x55, 0x0A, 0x61, 0x47, 0x55, 0x67, 0x56, 0x56, 0x4E, 0x46, 0x55, 0x6C, 0x52, 0x53, 0x56, 0x56, 0x4E, 0x55, 0x49, 0x45, 0x35, 0x6C, 0x64, 0x48, 0x64, 0x76, 0x63, 0x6D, 0x73, 0x78, 0x4C, 0x6A, 0x41, ++ 0x73, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x4A, 0x56, 0x56, 0x54, 0x52, 0x56, 0x4A, 0x55, 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x43, 0x42, 0x46, 0x51, 0x30, 0x4D, 0x67, 0x51, 0x32, 0x56, 0x79, 0x64, 0x47, 0x6C, 0x6D, 0x61, 0x57, 0x4E, ++ 0x68, 0x64, 0x47, 0x6C, 0x76, 0x0A, 0x62, 0x69, 0x42, 0x42, 0x64, 0x58, 0x52, 0x6F, 0x62, 0x33, 0x4A, 0x70, 0x64, 0x48, 0x6B, 0x77, 0x64, 0x6A, 0x41, 0x51, 0x42, 0x67, 0x63, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x49, 0x42, 0x42, 0x67, ++ 0x55, 0x72, 0x67, 0x51, 0x51, 0x41, 0x49, 0x67, 0x4E, 0x69, 0x41, 0x41, 0x51, 0x61, 0x72, 0x46, 0x52, 0x61, 0x71, 0x66, 0x6C, 0x6F, 0x49, 0x2B, 0x64, 0x36, 0x31, 0x53, 0x52, 0x76, 0x55, 0x38, 0x5A, 0x61, 0x32, 0x45, 0x75, 0x72, 0x78, 0x74, ++ 0x57, 0x32, 0x0A, 0x30, 0x65, 0x5A, 0x7A, 0x63, 0x61, 0x37, 0x64, 0x6E, 0x4E, 0x59, 0x4D, 0x59, 0x66, 0x33, 0x62, 0x6F, 0x49, 0x6B, 0x44, 0x75, 0x41, 0x55, 0x55, 0x37, 0x46, 0x66, 0x4F, 0x37, 0x6C, 0x30, 0x2F, 0x34, 0x69, 0x47, 0x7A, 0x7A, ++ 0x76, 0x66, 0x55, 0x69, 0x6E, 0x6E, 0x67, 0x6F, 0x34, 0x4E, 0x2B, 0x4C, 0x5A, 0x66, 0x51, 0x59, 0x63, 0x54, 0x78, 0x6D, 0x64, 0x77, 0x6C, 0x6B, 0x57, 0x4F, 0x72, 0x66, 0x7A, 0x43, 0x6A, 0x74, 0x48, 0x44, 0x69, 0x78, 0x36, 0x45, 0x7A, 0x0A, ++ 0x6E, 0x50, 0x4F, 0x2F, 0x4C, 0x6C, 0x78, 0x54, 0x73, 0x56, 0x2B, 0x7A, 0x66, 0x54, 0x4A, 0x2F, 0x69, 0x6A, 0x54, 0x6A, 0x65, 0x58, 0x6D, 0x6A, 0x51, 0x6A, 0x42, 0x41, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, ++ 0x42, 0x42, 0x51, 0x36, 0x34, 0x51, 0x6D, 0x47, 0x31, 0x4D, 0x38, 0x5A, 0x77, 0x70, 0x5A, 0x32, 0x64, 0x45, 0x6C, 0x32, 0x33, 0x4F, 0x41, 0x31, 0x78, 0x6D, 0x4E, 0x6A, 0x6D, 0x6A, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x0A, 0x48, 0x51, 0x38, ++ 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x51, 0x59, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x4B, 0x42, 0x67, 0x67, ++ 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x77, 0x4E, 0x6F, 0x41, 0x44, 0x42, 0x6C, 0x41, 0x6A, 0x41, 0x32, 0x5A, 0x36, 0x45, 0x57, 0x43, 0x4E, 0x7A, 0x6B, 0x6C, 0x77, 0x42, 0x42, 0x0A, 0x48, 0x55, 0x36, 0x2B, 0x34, 0x57, ++ 0x4D, 0x42, 0x7A, 0x7A, 0x75, 0x71, 0x51, 0x68, 0x46, 0x6B, 0x6F, 0x4A, 0x32, 0x55, 0x4F, 0x51, 0x49, 0x52, 0x65, 0x56, 0x78, 0x37, 0x48, 0x66, 0x70, 0x6B, 0x75, 0x65, 0x34, 0x57, 0x51, 0x72, 0x4F, 0x2F, 0x69, 0x73, 0x49, 0x4A, 0x78, 0x4F, ++ 0x7A, 0x6B, 0x73, 0x55, 0x30, 0x43, 0x4D, 0x51, 0x44, 0x70, 0x4B, 0x6D, 0x46, 0x48, 0x6A, 0x46, 0x4A, 0x4B, 0x53, 0x30, 0x34, 0x59, 0x63, 0x50, 0x62, 0x57, 0x52, 0x4E, 0x5A, 0x75, 0x0A, 0x39, 0x59, 0x4F, 0x36, 0x62, 0x56, 0x69, 0x39, 0x4A, ++ 0x4E, 0x6C, 0x57, 0x53, 0x4F, 0x72, 0x76, 0x78, 0x4B, 0x4A, 0x47, 0x67, 0x59, 0x68, 0x71, 0x4F, 0x6B, 0x62, 0x52, 0x71, 0x5A, 0x74, 0x4E, 0x79, 0x57, 0x48, 0x61, 0x30, 0x56, 0x31, 0x58, 0x61, 0x68, 0x67, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, ++ 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, ++ 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x52, 0x35, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, ++ 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x43, 0x48, 0x6A, 0x43, 0x43, 0x41, 0x61, 0x53, 0x67, 0x41, ++ 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x52, 0x59, 0x46, 0x6C, 0x4A, 0x34, 0x43, 0x59, 0x75, 0x75, 0x31, 0x58, 0x35, 0x43, 0x6E, 0x65, 0x4B, 0x63, 0x66, 0x6C, 0x4B, 0x32, 0x47, 0x77, 0x77, 0x43, 0x67, 0x59, 0x49, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, ++ 0x6A, 0x30, 0x45, 0x41, 0x77, 0x4D, 0x77, 0x55, 0x44, 0x45, 0x6B, 0x4D, 0x43, 0x49, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x78, 0x4D, 0x62, 0x0A, 0x52, 0x32, 0x78, 0x76, 0x59, 0x6D, 0x46, 0x73, 0x55, 0x32, 0x6C, 0x6E, 0x62, 0x69, 0x42, 0x46, ++ 0x51, 0x30, 0x4D, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x51, 0x53, 0x41, 0x74, 0x49, 0x46, 0x49, 0x31, 0x4D, 0x52, 0x4D, 0x77, 0x45, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x45, 0x77, 0x70, 0x48, 0x62, 0x47, 0x39, 0x69, ++ 0x59, 0x57, 0x78, 0x54, 0x61, 0x57, 0x64, 0x75, 0x4D, 0x52, 0x4D, 0x77, 0x45, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x0A, 0x45, 0x77, 0x70, 0x48, 0x62, 0x47, 0x39, 0x69, 0x59, 0x57, 0x78, 0x54, 0x61, 0x57, 0x64, 0x75, 0x4D, 0x42, 0x34, ++ 0x58, 0x44, 0x54, 0x45, 0x79, 0x4D, 0x54, 0x45, 0x78, 0x4D, 0x7A, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x46, 0x6F, 0x58, 0x44, 0x54, 0x4D, 0x34, 0x4D, 0x44, 0x45, 0x78, 0x4F, 0x54, 0x41, 0x7A, 0x4D, 0x54, 0x51, 0x77, 0x4E, 0x31, 0x6F, ++ 0x77, 0x55, 0x44, 0x45, 0x6B, 0x4D, 0x43, 0x49, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x78, 0x4D, 0x62, 0x0A, 0x52, 0x32, 0x78, 0x76, 0x59, 0x6D, 0x46, 0x73, 0x55, 0x32, 0x6C, 0x6E, 0x62, 0x69, 0x42, 0x46, 0x51, 0x30, 0x4D, 0x67, 0x55, 0x6D, ++ 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x51, 0x53, 0x41, 0x74, 0x49, 0x46, 0x49, 0x31, 0x4D, 0x52, 0x4D, 0x77, 0x45, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x45, 0x77, 0x70, 0x48, 0x62, 0x47, 0x39, 0x69, 0x59, 0x57, 0x78, 0x54, 0x61, 0x57, ++ 0x64, 0x75, 0x4D, 0x52, 0x4D, 0x77, 0x45, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x0A, 0x45, 0x77, 0x70, 0x48, 0x62, 0x47, 0x39, 0x69, 0x59, 0x57, 0x78, 0x54, 0x61, 0x57, 0x64, 0x75, 0x4D, 0x48, 0x59, 0x77, 0x45, 0x41, 0x59, 0x48, 0x4B, ++ 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x43, 0x41, 0x51, 0x59, 0x46, 0x4B, 0x34, 0x45, 0x45, 0x41, 0x43, 0x49, 0x44, 0x59, 0x67, 0x41, 0x45, 0x52, 0x30, 0x55, 0x4F, 0x6C, 0x76, 0x74, 0x39, 0x58, 0x62, 0x2F, 0x70, 0x4F, 0x64, 0x45, 0x68, 0x2B, ++ 0x4A, 0x38, 0x4C, 0x74, 0x74, 0x56, 0x37, 0x48, 0x70, 0x49, 0x36, 0x0A, 0x53, 0x46, 0x6B, 0x63, 0x38, 0x47, 0x49, 0x78, 0x4C, 0x63, 0x42, 0x36, 0x4B, 0x50, 0x34, 0x61, 0x70, 0x31, 0x79, 0x7A, 0x74, 0x73, 0x79, 0x58, 0x35, 0x30, 0x58, 0x55, ++ 0x57, 0x50, 0x72, 0x52, 0x64, 0x32, 0x31, 0x44, 0x6F, 0x73, 0x43, 0x48, 0x5A, 0x54, 0x51, 0x4B, 0x48, 0x33, 0x72, 0x64, 0x36, 0x7A, 0x77, 0x7A, 0x6F, 0x63, 0x57, 0x64, 0x54, 0x61, 0x52, 0x76, 0x51, 0x5A, 0x55, 0x34, 0x66, 0x38, 0x6B, 0x65, ++ 0x68, 0x4F, 0x76, 0x52, 0x6E, 0x6B, 0x6D, 0x53, 0x0A, 0x68, 0x35, 0x53, 0x48, 0x44, 0x44, 0x71, 0x46, 0x53, 0x6D, 0x61, 0x66, 0x6E, 0x56, 0x6D, 0x54, 0x54, 0x5A, 0x64, 0x68, 0x42, 0x6F, 0x5A, 0x4B, 0x6F, 0x30, 0x49, 0x77, 0x51, 0x44, 0x41, ++ 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x51, 0x59, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, ++ 0x42, 0x2F, 0x7A, 0x41, 0x64, 0x0A, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x50, 0x65, 0x59, 0x70, 0x53, 0x4A, 0x76, 0x71, 0x42, 0x38, 0x6F, 0x68, 0x52, 0x45, 0x6F, 0x6D, 0x33, 0x6D, 0x37, 0x65, 0x30, 0x6F, ++ 0x50, 0x51, 0x6E, 0x31, 0x6B, 0x77, 0x43, 0x67, 0x59, 0x49, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x45, 0x41, 0x77, 0x4D, 0x44, 0x61, 0x41, 0x41, 0x77, 0x5A, 0x51, 0x49, 0x78, 0x41, 0x4F, 0x56, 0x70, 0x45, 0x73, 0x6C, 0x75, 0x32, 0x38, ++ 0x59, 0x78, 0x0A, 0x75, 0x67, 0x6C, 0x42, 0x34, 0x5A, 0x66, 0x34, 0x2B, 0x2F, 0x32, 0x61, 0x34, 0x6E, 0x30, 0x53, 0x79, 0x65, 0x31, 0x38, 0x5A, 0x4E, 0x50, 0x4C, 0x42, 0x53, 0x57, 0x4C, 0x56, 0x74, 0x6D, 0x67, 0x35, 0x31, 0x35, 0x64, 0x54, ++ 0x67, 0x75, 0x44, 0x6E, 0x46, 0x74, 0x32, 0x4B, 0x61, 0x41, 0x4A, 0x4A, 0x69, 0x46, 0x71, 0x59, 0x67, 0x49, 0x77, 0x63, 0x64, 0x4B, 0x31, 0x6A, 0x31, 0x7A, 0x71, 0x4F, 0x2B, 0x46, 0x34, 0x43, 0x59, 0x57, 0x6F, 0x64, 0x5A, 0x49, 0x37, 0x0A, ++ 0x79, 0x46, 0x7A, 0x39, 0x53, 0x4F, 0x38, 0x4E, 0x64, 0x43, 0x4B, 0x6F, 0x43, 0x4F, 0x4A, 0x75, 0x78, 0x55, 0x6E, 0x4F, 0x78, 0x77, 0x79, 0x38, 0x70, 0x32, 0x46, 0x70, 0x38, 0x66, 0x63, 0x37, 0x34, 0x53, 0x72, 0x4C, 0x2B, 0x53, 0x76, 0x7A, ++ 0x5A, 0x70, 0x41, 0x33, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x49, 0x64, 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, ++ 0x74, 0x20, 0x43, 0x6F, 0x6D, 0x6D, 0x65, 0x72, 0x63, 0x69, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, ++ 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x59, 0x44, 0x43, 0x43, 0x41, 0x30, 0x69, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x43, 0x67, 0x46, 0x43, 0x67, 0x41, 0x41, 0x41, 0x41, 0x55, 0x55, 0x6A, 0x79, 0x45, 0x53, 0x31, 0x41, 0x41, ++ 0x41, 0x41, 0x41, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x44, 0x42, 0x4B, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x0A, 0x45, ++ 0x77, 0x4A, 0x56, 0x55, 0x7A, 0x45, 0x53, 0x4D, 0x42, 0x41, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x4A, 0x53, 0x57, 0x52, 0x6C, 0x62, 0x6C, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x4D, 0x53, 0x63, 0x77, 0x4A, 0x51, 0x59, 0x44, 0x56, ++ 0x51, 0x51, 0x44, 0x45, 0x78, 0x35, 0x4A, 0x5A, 0x47, 0x56, 0x75, 0x56, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x51, 0x67, 0x51, 0x32, 0x39, 0x74, 0x62, 0x57, 0x56, 0x79, 0x59, 0x32, 0x6C, 0x68, 0x62, 0x43, 0x42, 0x53, 0x0A, 0x62, 0x32, 0x39, 0x30, ++ 0x49, 0x45, 0x4E, 0x42, 0x49, 0x44, 0x45, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x54, 0x51, 0x77, 0x4D, 0x54, 0x45, 0x32, 0x4D, 0x54, 0x67, 0x78, 0x4D, 0x6A, 0x49, 0x7A, 0x57, 0x68, 0x63, 0x4E, 0x4D, 0x7A, 0x51, 0x77, 0x4D, 0x54, 0x45, 0x32, ++ 0x4D, 0x54, 0x67, 0x78, 0x4D, 0x6A, 0x49, 0x7A, 0x57, 0x6A, 0x42, 0x4B, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x56, 0x55, 0x7A, 0x45, 0x53, 0x0A, 0x4D, 0x42, 0x41, 0x47, 0x41, 0x31, 0x55, ++ 0x45, 0x43, 0x68, 0x4D, 0x4A, 0x53, 0x57, 0x52, 0x6C, 0x62, 0x6C, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x4D, 0x53, 0x63, 0x77, 0x4A, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x35, 0x4A, 0x5A, 0x47, 0x56, 0x75, 0x56, 0x48, 0x4A, ++ 0x31, 0x63, 0x33, 0x51, 0x67, 0x51, 0x32, 0x39, 0x74, 0x62, 0x57, 0x56, 0x79, 0x59, 0x32, 0x6C, 0x68, 0x62, 0x43, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x42, 0x0A, 0x49, 0x44, 0x45, 0x77, 0x67, 0x67, 0x49, 0x69, 0x4D, 0x41, ++ 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x49, 0x4B, 0x41, 0x6F, 0x49, 0x43, 0x41, 0x51, 0x43, 0x6E, 0x55, 0x42, ++ 0x6E, 0x65, 0x50, 0x35, 0x6B, 0x39, 0x31, 0x44, 0x4E, 0x47, 0x38, 0x57, 0x39, 0x52, 0x59, 0x59, 0x4B, 0x79, 0x71, 0x55, 0x2B, 0x50, 0x5A, 0x34, 0x6C, 0x64, 0x0A, 0x68, 0x4E, 0x6C, 0x54, 0x33, 0x51, 0x77, 0x6F, 0x32, 0x64, 0x66, 0x77, 0x2F, ++ 0x36, 0x36, 0x56, 0x51, 0x33, 0x4B, 0x5A, 0x2B, 0x62, 0x56, 0x64, 0x66, 0x49, 0x72, 0x42, 0x51, 0x75, 0x45, 0x78, 0x55, 0x48, 0x54, 0x52, 0x67, 0x51, 0x31, 0x38, 0x7A, 0x5A, 0x73, 0x68, 0x71, 0x30, 0x50, 0x69, 0x72, 0x4B, 0x31, 0x65, 0x68, ++ 0x6D, 0x37, 0x7A, 0x43, 0x59, 0x6F, 0x66, 0x57, 0x6A, 0x4B, 0x39, 0x6F, 0x75, 0x75, 0x55, 0x2B, 0x65, 0x68, 0x63, 0x43, 0x75, 0x7A, 0x2F, 0x0A, 0x6D, 0x4E, 0x4B, 0x76, 0x63, 0x62, 0x4F, 0x30, 0x55, 0x35, 0x39, 0x4F, 0x68, 0x2B, 0x2B, 0x53, ++ 0x76, 0x4C, 0x33, 0x73, 0x54, 0x7A, 0x49, 0x77, 0x69, 0x45, 0x73, 0x58, 0x58, 0x6C, 0x66, 0x45, 0x55, 0x38, 0x4C, 0x32, 0x41, 0x70, 0x65, 0x4E, 0x32, 0x57, 0x49, 0x72, 0x76, 0x79, 0x51, 0x66, 0x59, 0x6F, 0x33, 0x66, 0x77, 0x37, 0x67, 0x70, ++ 0x53, 0x30, 0x6C, 0x34, 0x50, 0x4A, 0x4E, 0x67, 0x69, 0x43, 0x4C, 0x38, 0x6D, 0x64, 0x6F, 0x32, 0x79, 0x4D, 0x4B, 0x69, 0x0A, 0x31, 0x43, 0x78, 0x55, 0x41, 0x47, 0x63, 0x31, 0x62, 0x6E, 0x4F, 0x2F, 0x41, 0x6C, 0x6A, 0x77, 0x70, 0x4E, 0x33, ++ 0x6C, 0x73, 0x4B, 0x49, 0x6D, 0x65, 0x73, 0x72, 0x67, 0x4E, 0x71, 0x55, 0x5A, 0x46, 0x76, 0x58, 0x39, 0x74, 0x2B, 0x2B, 0x75, 0x50, 0x30, 0x44, 0x31, 0x62, 0x56, 0x6F, 0x45, 0x2F, 0x63, 0x34, 0x30, 0x79, 0x69, 0x54, 0x63, 0x64, 0x43, 0x4D, ++ 0x62, 0x58, 0x54, 0x4D, 0x54, 0x45, 0x6C, 0x33, 0x45, 0x41, 0x53, 0x58, 0x32, 0x4D, 0x4E, 0x30, 0x43, 0x0A, 0x58, 0x5A, 0x2F, 0x67, 0x31, 0x55, 0x65, 0x39, 0x74, 0x4F, 0x73, 0x62, 0x6F, 0x62, 0x74, 0x4A, 0x53, 0x64, 0x69, 0x66, 0x57, 0x77, ++ 0x4C, 0x7A, 0x69, 0x75, 0x51, 0x6B, 0x6B, 0x4F, 0x52, 0x69, 0x54, 0x30, 0x2F, 0x42, 0x72, 0x34, 0x73, 0x4F, 0x64, 0x42, 0x65, 0x6F, 0x30, 0x58, 0x4B, 0x49, 0x61, 0x6E, 0x6F, 0x42, 0x53, 0x63, 0x79, 0x30, 0x52, 0x6E, 0x6E, 0x47, 0x46, 0x37, ++ 0x48, 0x61, 0x6D, 0x42, 0x34, 0x48, 0x57, 0x66, 0x70, 0x31, 0x49, 0x59, 0x56, 0x6C, 0x0A, 0x33, 0x5A, 0x42, 0x57, 0x7A, 0x76, 0x75, 0x72, 0x70, 0x57, 0x43, 0x64, 0x78, 0x4A, 0x33, 0x35, 0x55, 0x72, 0x43, 0x4C, 0x76, 0x59, 0x66, 0x35, 0x6A, ++ 0x79, 0x73, 0x6A, 0x43, 0x69, 0x4E, 0x32, 0x4F, 0x2F, 0x63, 0x7A, 0x34, 0x63, 0x6B, 0x41, 0x38, 0x32, 0x6E, 0x35, 0x53, 0x36, 0x4C, 0x67, 0x54, 0x72, 0x78, 0x2B, 0x6B, 0x7A, 0x6D, 0x45, 0x42, 0x2F, 0x64, 0x45, 0x63, 0x48, 0x37, 0x2B, 0x42, ++ 0x31, 0x72, 0x6C, 0x73, 0x61, 0x7A, 0x52, 0x47, 0x4D, 0x7A, 0x79, 0x0A, 0x4E, 0x65, 0x56, 0x4A, 0x53, 0x51, 0x6A, 0x4B, 0x56, 0x73, 0x6B, 0x39, 0x2B, 0x77, 0x38, 0x59, 0x66, 0x59, 0x73, 0x37, 0x77, 0x52, 0x50, 0x43, 0x54, 0x59, 0x2F, 0x4A, ++ 0x54, 0x77, 0x34, 0x33, 0x36, 0x52, 0x2B, 0x68, 0x44, 0x6D, 0x72, 0x66, 0x59, 0x69, 0x37, 0x4C, 0x4E, 0x51, 0x5A, 0x52, 0x65, 0x53, 0x7A, 0x49, 0x4A, 0x54, 0x6A, 0x30, 0x2B, 0x6B, 0x75, 0x6E, 0x69, 0x56, 0x79, 0x63, 0x30, 0x75, 0x4D, 0x4E, ++ 0x4F, 0x59, 0x5A, 0x4B, 0x64, 0x48, 0x7A, 0x56, 0x0A, 0x57, 0x59, 0x66, 0x43, 0x50, 0x30, 0x34, 0x4D, 0x58, 0x46, 0x4C, 0x30, 0x50, 0x66, 0x64, 0x53, 0x67, 0x76, 0x48, 0x71, 0x6F, 0x36, 0x7A, 0x39, 0x53, 0x54, 0x51, 0x61, 0x4B, 0x50, 0x4E, ++ 0x42, 0x69, 0x44, 0x6F, 0x54, 0x37, 0x75, 0x6A, 0x65, 0x2F, 0x35, 0x6B, 0x64, 0x58, 0x37, 0x72, 0x4C, 0x36, 0x42, 0x37, 0x79, 0x75, 0x56, 0x42, 0x67, 0x77, 0x44, 0x48, 0x54, 0x63, 0x2B, 0x58, 0x76, 0x76, 0x71, 0x44, 0x74, 0x4D, 0x77, 0x74, ++ 0x30, 0x76, 0x69, 0x41, 0x67, 0x0A, 0x78, 0x47, 0x64, 0x73, 0x38, 0x41, 0x67, 0x44, 0x65, 0x6C, 0x57, 0x41, 0x66, 0x30, 0x5A, 0x4F, 0x6C, 0x71, 0x66, 0x30, 0x48, 0x6A, 0x37, 0x68, 0x39, 0x74, 0x67, 0x4A, 0x34, 0x54, 0x4E, 0x6B, 0x4B, 0x32, ++ 0x50, 0x58, 0x4D, 0x6C, 0x36, 0x66, 0x2B, 0x63, 0x42, 0x37, 0x44, 0x33, 0x68, 0x76, 0x6C, 0x37, 0x79, 0x54, 0x6D, 0x76, 0x6D, 0x63, 0x45, 0x70, 0x42, 0x34, 0x65, 0x6F, 0x43, 0x48, 0x46, 0x64, 0x64, 0x79, 0x64, 0x4A, 0x78, 0x56, 0x64, 0x48, ++ 0x69, 0x78, 0x0A, 0x75, 0x75, 0x46, 0x75, 0x63, 0x41, 0x53, 0x36, 0x54, 0x36, 0x43, 0x36, 0x61, 0x4D, 0x4E, 0x37, 0x2F, 0x7A, 0x48, 0x77, 0x63, 0x7A, 0x30, 0x39, 0x6C, 0x43, 0x71, 0x78, 0x43, 0x30, 0x45, 0x4F, 0x6F, 0x50, 0x35, 0x4E, 0x69, ++ 0x47, 0x56, 0x72, 0x65, 0x54, 0x4F, 0x30, 0x31, 0x77, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x6F, 0x30, 0x49, 0x77, 0x51, 0x44, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x41, 0x4D, 0x43, 0x0A, ++ 0x41, 0x51, 0x59, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, ++ 0x37, 0x55, 0x51, 0x5A, 0x77, 0x4E, 0x50, 0x77, 0x42, 0x6F, 0x76, 0x75, 0x70, 0x48, 0x75, 0x2B, 0x51, 0x75, 0x63, 0x6D, 0x56, 0x4D, 0x69, 0x4F, 0x4E, 0x6E, 0x59, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x0A, 0x68, 0x76, 0x63, ++ 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x42, 0x41, 0x41, 0x32, 0x75, 0x6B, 0x44, 0x4C, 0x32, 0x70, 0x6B, 0x74, 0x38, 0x52, 0x48, 0x59, 0x5A, 0x59, 0x52, 0x34, 0x6E, 0x4B, 0x4D, 0x31, 0x65, 0x56, 0x4F, 0x38, ++ 0x6C, 0x76, 0x4F, 0x4D, 0x49, 0x6B, 0x50, 0x6B, 0x70, 0x31, 0x36, 0x35, 0x6F, 0x43, 0x4F, 0x47, 0x55, 0x41, 0x46, 0x6A, 0x76, 0x4C, 0x69, 0x35, 0x2B, 0x55, 0x31, 0x4B, 0x4D, 0x74, 0x6C, 0x77, 0x48, 0x0A, 0x36, 0x6F, 0x69, 0x36, 0x6D, 0x59, ++ 0x74, 0x51, 0x6C, 0x4E, 0x65, 0x43, 0x67, 0x4E, 0x39, 0x68, 0x43, 0x51, 0x43, 0x54, 0x72, 0x51, 0x30, 0x55, 0x35, 0x73, 0x37, 0x42, 0x38, 0x6A, 0x65, 0x55, 0x65, 0x4C, 0x42, 0x66, 0x6E, 0x4C, 0x4F, 0x69, 0x63, 0x37, 0x69, 0x50, 0x42, 0x5A, ++ 0x4D, 0x34, 0x7A, 0x59, 0x30, 0x2B, 0x73, 0x4C, 0x6A, 0x37, 0x77, 0x4D, 0x2B, 0x78, 0x38, 0x75, 0x77, 0x74, 0x4C, 0x52, 0x76, 0x4D, 0x37, 0x4B, 0x71, 0x61, 0x73, 0x36, 0x70, 0x67, 0x0A, 0x67, 0x68, 0x73, 0x74, 0x4F, 0x38, 0x4F, 0x45, 0x50, ++ 0x56, 0x65, 0x4B, 0x6C, 0x68, 0x36, 0x63, 0x64, 0x62, 0x6A, 0x54, 0x4D, 0x4D, 0x31, 0x67, 0x43, 0x49, 0x4F, 0x51, 0x30, 0x34, 0x35, 0x55, 0x38, 0x55, 0x31, 0x6D, 0x77, 0x46, 0x31, 0x30, 0x41, 0x30, 0x43, 0x6A, 0x37, 0x6F, 0x56, 0x2B, 0x77, ++ 0x68, 0x39, 0x33, 0x6E, 0x41, 0x62, 0x6F, 0x77, 0x61, 0x63, 0x59, 0x58, 0x56, 0x4B, 0x56, 0x37, 0x63, 0x6E, 0x64, 0x4A, 0x5A, 0x35, 0x74, 0x2B, 0x71, 0x6E, 0x74, 0x0A, 0x6F, 0x7A, 0x6F, 0x30, 0x30, 0x46, 0x6C, 0x37, 0x32, 0x75, 0x31, 0x51, ++ 0x38, 0x7A, 0x57, 0x2F, 0x37, 0x65, 0x73, 0x55, 0x54, 0x54, 0x48, 0x48, 0x59, 0x50, 0x54, 0x61, 0x38, 0x59, 0x65, 0x63, 0x34, 0x6B, 0x6A, 0x69, 0x78, 0x73, 0x55, 0x33, 0x2B, 0x77, 0x59, 0x51, 0x2B, 0x6E, 0x56, 0x5A, 0x5A, 0x6A, 0x46, 0x48, ++ 0x4B, 0x64, 0x70, 0x32, 0x6D, 0x68, 0x7A, 0x70, 0x67, 0x71, 0x37, 0x76, 0x6D, 0x72, 0x6C, 0x52, 0x39, 0x34, 0x67, 0x6A, 0x6D, 0x6D, 0x6D, 0x56, 0x0A, 0x59, 0x6A, 0x7A, 0x6C, 0x56, 0x59, 0x41, 0x32, 0x31, 0x31, 0x51, 0x43, 0x2F, 0x2F, 0x47, ++ 0x35, 0x58, 0x63, 0x37, 0x55, 0x49, 0x32, 0x2F, 0x59, 0x52, 0x59, 0x52, 0x4B, 0x57, 0x32, 0x58, 0x76, 0x69, 0x51, 0x7A, 0x64, 0x46, 0x4B, 0x63, 0x67, 0x79, 0x78, 0x69, 0x6C, 0x4A, 0x62, 0x51, 0x4E, 0x2B, 0x51, 0x48, 0x77, 0x6F, 0x74, 0x4C, ++ 0x30, 0x41, 0x4D, 0x68, 0x30, 0x6A, 0x71, 0x45, 0x71, 0x53, 0x49, 0x35, 0x6C, 0x32, 0x78, 0x50, 0x45, 0x34, 0x69, 0x55, 0x58, 0x0A, 0x66, 0x65, 0x75, 0x2B, 0x68, 0x31, 0x73, 0x58, 0x49, 0x46, 0x52, 0x52, 0x6B, 0x30, 0x70, 0x54, 0x41, 0x77, ++ 0x76, 0x73, 0x58, 0x63, 0x6F, 0x7A, 0x37, 0x57, 0x4C, 0x39, 0x52, 0x63, 0x63, 0x76, 0x57, 0x39, 0x78, 0x59, 0x6F, 0x49, 0x41, 0x35, 0x35, 0x76, 0x72, 0x58, 0x2F, 0x68, 0x4D, 0x55, 0x70, 0x75, 0x30, 0x39, 0x6C, 0x45, 0x70, 0x43, 0x64, 0x4E, ++ 0x54, 0x44, 0x64, 0x31, 0x6C, 0x7A, 0x7A, 0x59, 0x39, 0x47, 0x76, 0x6C, 0x55, 0x34, 0x37, 0x2F, 0x72, 0x6F, 0x0A, 0x6B, 0x54, 0x4C, 0x71, 0x6C, 0x31, 0x67, 0x45, 0x49, 0x74, 0x34, 0x34, 0x77, 0x38, 0x79, 0x38, 0x62, 0x63, 0x6B, 0x7A, 0x4F, ++ 0x6D, 0x6F, 0x4B, 0x61, 0x54, 0x2B, 0x67, 0x79, 0x4F, 0x70, 0x79, 0x6A, 0x34, 0x78, 0x6A, 0x68, 0x69, 0x4F, 0x39, 0x62, 0x54, 0x79, 0x57, 0x6E, 0x70, 0x58, 0x67, 0x53, 0x55, 0x79, 0x71, 0x6F, 0x72, 0x6B, 0x71, 0x47, 0x35, 0x77, 0x32, 0x67, ++ 0x58, 0x6A, 0x74, 0x77, 0x2B, 0x68, 0x47, 0x34, 0x69, 0x5A, 0x5A, 0x52, 0x48, 0x55, 0x65, 0x0A, 0x32, 0x58, 0x57, 0x4A, 0x55, 0x63, 0x30, 0x51, 0x68, 0x4A, 0x31, 0x68, 0x59, 0x4D, 0x74, 0x64, 0x2B, 0x5A, 0x63, 0x69, 0x54, 0x59, 0x36, 0x59, ++ 0x35, 0x75, 0x4E, 0x2F, 0x39, 0x6C, 0x75, 0x37, 0x72, 0x73, 0x33, 0x4B, 0x53, 0x6F, 0x46, 0x72, 0x58, 0x67, 0x76, 0x7A, 0x55, 0x65, 0x46, 0x30, 0x4B, 0x2B, 0x6C, 0x2B, 0x4A, 0x36, 0x66, 0x5A, 0x6D, 0x55, 0x6C, 0x4F, 0x2B, 0x4B, 0x57, 0x41, ++ 0x32, 0x79, 0x55, 0x50, 0x48, 0x47, 0x4E, 0x69, 0x69, 0x73, 0x6B, 0x7A, 0x0A, 0x5A, 0x32, 0x73, 0x38, 0x45, 0x49, 0x50, 0x47, 0x72, 0x64, 0x36, 0x6F, 0x7A, 0x52, 0x61, 0x4F, 0x6A, 0x66, 0x41, 0x48, 0x4E, 0x33, 0x47, 0x66, 0x38, 0x71, 0x76, ++ 0x38, 0x51, 0x66, 0x58, 0x42, 0x69, 0x2B, 0x77, 0x41, 0x4E, 0x31, 0x30, 0x4A, 0x35, 0x55, 0x36, 0x41, 0x37, 0x2F, 0x71, 0x78, 0x58, 0x44, 0x67, 0x47, 0x70, 0x52, 0x74, 0x4B, 0x34, 0x64, 0x77, 0x34, 0x4C, 0x54, 0x7A, 0x63, 0x71, 0x78, 0x2B, ++ 0x51, 0x47, 0x74, 0x56, 0x4B, 0x6E, 0x4F, 0x37, 0x52, 0x0A, 0x63, 0x47, 0x7A, 0x4D, 0x37, 0x76, 0x52, 0x58, 0x2B, 0x42, 0x69, 0x36, 0x68, 0x47, 0x36, 0x48, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, ++ 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x49, 0x64, 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x20, 0x53, 0x65, 0x63, 0x74, 0x6F, 0x72, 0x20, 0x52, 0x6F, ++ 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x5A, 0x6A, 0x43, 0x43, 0x41, 0x30, ++ 0x36, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x43, 0x67, 0x46, 0x43, 0x67, 0x41, 0x41, 0x41, 0x41, 0x55, 0x55, 0x6A, 0x7A, 0x30, 0x5A, 0x38, 0x41, 0x41, 0x41, 0x41, 0x41, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, ++ 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x44, 0x42, 0x4E, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x0A, 0x45, 0x77, 0x4A, 0x56, 0x55, 0x7A, 0x45, 0x53, 0x4D, 0x42, 0x41, 0x47, 0x41, ++ 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x4A, 0x53, 0x57, 0x52, 0x6C, 0x62, 0x6C, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x4D, 0x53, 0x6F, 0x77, 0x4B, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x79, 0x46, 0x4A, 0x5A, 0x47, 0x56, 0x75, 0x56, ++ 0x48, 0x4A, 0x31, 0x63, 0x33, 0x51, 0x67, 0x55, 0x48, 0x56, 0x69, 0x62, 0x47, 0x6C, 0x6A, 0x49, 0x46, 0x4E, 0x6C, 0x59, 0x33, 0x52, 0x76, 0x0A, 0x63, 0x69, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x42, 0x49, 0x44, 0x45, 0x77, ++ 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x54, 0x51, 0x77, 0x4D, 0x54, 0x45, 0x32, 0x4D, 0x54, 0x63, 0x31, 0x4D, 0x7A, 0x4D, 0x79, 0x57, 0x68, 0x63, 0x4E, 0x4D, 0x7A, 0x51, 0x77, 0x4D, 0x54, 0x45, 0x32, 0x4D, 0x54, 0x63, 0x31, 0x4D, 0x7A, 0x4D, 0x79, ++ 0x57, 0x6A, 0x42, 0x4E, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x56, 0x0A, 0x55, 0x7A, 0x45, 0x53, 0x4D, 0x42, 0x41, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x4A, 0x53, 0x57, 0x52, ++ 0x6C, 0x62, 0x6C, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x4D, 0x53, 0x6F, 0x77, 0x4B, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x79, 0x46, 0x4A, 0x5A, 0x47, 0x56, 0x75, 0x56, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x51, 0x67, 0x55, 0x48, 0x56, ++ 0x69, 0x62, 0x47, 0x6C, 0x6A, 0x49, 0x46, 0x4E, 0x6C, 0x59, 0x33, 0x52, 0x76, 0x63, 0x69, 0x42, 0x53, 0x0A, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x42, 0x49, 0x44, 0x45, 0x77, 0x67, 0x67, 0x49, 0x69, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, ++ 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x49, 0x4B, 0x41, 0x6F, 0x49, 0x43, 0x41, 0x51, 0x43, 0x32, 0x49, 0x70, 0x54, 0x38, 0x70, 0x45, ++ 0x69, 0x76, 0x36, 0x45, 0x64, 0x72, 0x43, 0x76, 0x73, 0x6E, 0x64, 0x75, 0x54, 0x79, 0x0A, 0x50, 0x34, 0x6F, 0x37, 0x65, 0x6B, 0x6F, 0x73, 0x4D, 0x53, 0x71, 0x4D, 0x6A, 0x62, 0x43, 0x70, 0x77, 0x7A, 0x46, 0x72, 0x71, 0x48, 0x64, 0x32, 0x68, ++ 0x43, 0x61, 0x32, 0x72, 0x49, 0x46, 0x43, 0x44, 0x51, 0x6A, 0x72, 0x56, 0x56, 0x69, 0x37, 0x65, 0x76, 0x69, 0x38, 0x5A, 0x58, 0x33, 0x79, 0x6F, 0x47, 0x32, 0x4C, 0x71, 0x45, 0x66, 0x70, 0x59, 0x6E, 0x59, 0x65, 0x45, 0x65, 0x34, 0x49, 0x46, ++ 0x4E, 0x47, 0x79, 0x52, 0x42, 0x62, 0x30, 0x36, 0x74, 0x44, 0x36, 0x0A, 0x48, 0x69, 0x39, 0x65, 0x32, 0x38, 0x74, 0x7A, 0x51, 0x61, 0x36, 0x38, 0x41, 0x4C, 0x42, 0x4B, 0x4B, 0x30, 0x43, 0x79, 0x72, 0x4F, 0x45, 0x37, 0x53, 0x38, 0x49, 0x74, ++ 0x6E, 0x65, 0x53, 0x68, 0x6D, 0x2B, 0x77, 0x61, 0x4F, 0x68, 0x37, 0x77, 0x43, 0x4C, 0x50, 0x51, 0x35, 0x43, 0x51, 0x31, 0x42, 0x35, 0x2B, 0x63, 0x74, 0x4D, 0x6C, 0x53, 0x62, 0x64, 0x73, 0x48, 0x79, 0x6F, 0x2B, 0x31, 0x57, 0x2F, 0x43, 0x44, ++ 0x38, 0x30, 0x2F, 0x48, 0x4C, 0x61, 0x58, 0x49, 0x0A, 0x72, 0x63, 0x75, 0x56, 0x49, 0x4B, 0x51, 0x78, 0x4B, 0x46, 0x64, 0x59, 0x57, 0x75, 0x53, 0x4E, 0x47, 0x35, 0x71, 0x72, 0x6E, 0x67, 0x30, 0x4D, 0x38, 0x67, 0x6F, 0x7A, 0x4F, 0x53, 0x49, ++ 0x35, 0x43, 0x70, 0x63, 0x75, 0x38, 0x31, 0x4E, 0x33, 0x75, 0x55, 0x52, 0x46, 0x2F, 0x59, 0x54, 0x4C, 0x4E, 0x69, 0x43, 0x42, 0x57, 0x53, 0x32, 0x61, 0x62, 0x32, 0x31, 0x49, 0x53, 0x47, 0x48, 0x4B, 0x54, 0x4E, 0x39, 0x54, 0x30, 0x61, 0x39, ++ 0x53, 0x76, 0x45, 0x53, 0x66, 0x0A, 0x71, 0x79, 0x39, 0x72, 0x67, 0x33, 0x4C, 0x76, 0x64, 0x59, 0x44, 0x61, 0x42, 0x6A, 0x4D, 0x62, 0x58, 0x63, 0x6A, 0x61, 0x59, 0x38, 0x5A, 0x4E, 0x7A, 0x61, 0x78, 0x6D, 0x4D, 0x63, 0x33, 0x52, 0x33, 0x6A, ++ 0x36, 0x48, 0x45, 0x44, 0x62, 0x68, 0x75, 0x61, 0x52, 0x36, 0x37, 0x32, 0x42, 0x51, 0x73, 0x73, 0x76, 0x4B, 0x70, 0x6C, 0x62, 0x67, 0x4E, 0x36, 0x2B, 0x72, 0x4E, 0x42, 0x4D, 0x35, 0x4A, 0x65, 0x67, 0x35, 0x5A, 0x75, 0x53, 0x59, 0x65, 0x71, ++ 0x6F, 0x53, 0x0A, 0x6D, 0x4A, 0x78, 0x5A, 0x5A, 0x6F, 0x59, 0x2B, 0x72, 0x66, 0x47, 0x77, 0x79, 0x6A, 0x34, 0x47, 0x44, 0x33, 0x76, 0x77, 0x45, 0x55, 0x73, 0x33, 0x6F, 0x45, 0x52, 0x74, 0x65, 0x38, 0x75, 0x6F, 0x6A, 0x48, 0x48, 0x30, 0x31, ++ 0x62, 0x57, 0x52, 0x4E, 0x73, 0x7A, 0x77, 0x46, 0x63, 0x59, 0x72, 0x33, 0x6C, 0x45, 0x58, 0x73, 0x5A, 0x64, 0x4D, 0x55, 0x44, 0x32, 0x78, 0x6C, 0x56, 0x6C, 0x38, 0x42, 0x58, 0x30, 0x74, 0x49, 0x64, 0x55, 0x41, 0x76, 0x77, 0x46, 0x6E, 0x0A, ++ 0x6F, 0x6C, 0x35, 0x37, 0x70, 0x6C, 0x7A, 0x79, 0x39, 0x79, 0x4C, 0x78, 0x6B, 0x41, 0x32, 0x54, 0x32, 0x36, 0x70, 0x45, 0x55, 0x57, 0x62, 0x4D, 0x66, 0x58, 0x59, 0x44, 0x36, 0x32, 0x71, 0x6F, 0x4B, 0x6A, 0x67, 0x5A, 0x6C, 0x33, 0x59, 0x4E, ++ 0x61, 0x34, 0x70, 0x68, 0x2B, 0x62, 0x7A, 0x32, 0x37, 0x6E, 0x62, 0x39, 0x63, 0x43, 0x76, 0x64, 0x4B, 0x54, 0x7A, 0x34, 0x43, 0x68, 0x35, 0x62, 0x51, 0x68, 0x79, 0x4C, 0x56, 0x69, 0x39, 0x56, 0x47, 0x78, 0x79, 0x68, 0x0A, 0x4C, 0x72, 0x58, ++ 0x48, 0x46, 0x75, 0x62, 0x34, 0x71, 0x6A, 0x79, 0x53, 0x6A, 0x6D, 0x6D, 0x32, 0x41, 0x63, 0x47, 0x31, 0x68, 0x70, 0x32, 0x4A, 0x44, 0x77, 0x73, 0x34, 0x6C, 0x46, 0x54, 0x6F, 0x36, 0x74, 0x79, 0x65, 0x50, 0x53, 0x57, 0x38, 0x55, 0x79, 0x62, ++ 0x74, 0x31, 0x61, 0x73, 0x35, 0x71, 0x73, 0x56, 0x41, 0x54, 0x46, 0x53, 0x72, 0x73, 0x72, 0x54, 0x5A, 0x32, 0x66, 0x6A, 0x58, 0x63, 0x74, 0x73, 0x63, 0x76, 0x47, 0x32, 0x39, 0x5A, 0x56, 0x2F, 0x76, 0x0A, 0x69, 0x44, 0x55, 0x71, 0x5A, 0x69, ++ 0x2F, 0x75, 0x39, 0x72, 0x4E, 0x6C, 0x38, 0x44, 0x4F, 0x4E, 0x66, 0x4A, 0x68, 0x42, 0x61, 0x55, 0x59, 0x50, 0x51, 0x78, 0x78, 0x70, 0x2B, 0x70, 0x75, 0x31, 0x30, 0x47, 0x46, 0x71, 0x7A, 0x63, 0x70, 0x4C, 0x32, 0x55, 0x79, 0x51, 0x52, 0x71, ++ 0x73, 0x56, 0x57, 0x61, 0x46, 0x48, 0x56, 0x43, 0x6B, 0x75, 0x67, 0x79, 0x68, 0x66, 0x48, 0x4D, 0x4B, 0x69, 0x71, 0x33, 0x49, 0x58, 0x41, 0x41, 0x61, 0x4F, 0x52, 0x65, 0x79, 0x4C, 0x0A, 0x34, 0x6A, 0x4D, 0x39, 0x66, 0x39, 0x6F, 0x5A, 0x52, ++ 0x4F, 0x52, 0x69, 0x63, 0x73, 0x50, 0x66, 0x49, 0x73, 0x62, 0x79, 0x56, 0x74, 0x54, 0x64, 0x58, 0x35, 0x56, 0x79, 0x37, 0x57, 0x31, 0x66, 0x39, 0x30, 0x67, 0x44, 0x57, 0x2F, 0x33, 0x46, 0x4B, 0x71, 0x44, 0x32, 0x63, 0x79, 0x4F, 0x45, 0x45, ++ 0x42, 0x73, 0x42, 0x35, 0x77, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x6F, 0x30, 0x49, 0x77, 0x51, 0x44, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x42, 0x0A, 0x41, 0x66, 0x38, 0x45, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x51, 0x59, 0x77, ++ 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x34, 0x33, 0x48, 0x67, ++ 0x6E, 0x74, 0x69, 0x6E, 0x51, 0x74, 0x6E, 0x62, 0x63, 0x5A, 0x46, 0x72, 0x6C, 0x4A, 0x50, 0x72, 0x77, 0x36, 0x50, 0x52, 0x46, 0x4B, 0x4D, 0x77, 0x0A, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, ++ 0x4C, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x42, 0x41, 0x45, 0x66, 0x36, 0x33, 0x51, 0x71, 0x77, 0x45, 0x5A, 0x45, 0x34, 0x72, 0x55, 0x31, 0x64, 0x39, 0x2B, 0x55, 0x4F, 0x6C, 0x31, 0x51, 0x5A, 0x67, 0x6B, 0x69, 0x48, 0x56, 0x49, 0x79, ++ 0x71, 0x5A, 0x4A, 0x6E, 0x59, 0x57, 0x76, 0x36, 0x49, 0x41, 0x63, 0x56, 0x59, 0x70, 0x5A, 0x6D, 0x78, 0x49, 0x31, 0x51, 0x6A, 0x0A, 0x74, 0x32, 0x6F, 0x64, 0x49, 0x46, 0x66, 0x6C, 0x41, 0x57, 0x4A, 0x42, 0x46, 0x39, 0x4D, 0x4A, 0x32, 0x33, ++ 0x58, 0x4C, 0x62, 0x6C, 0x53, 0x51, 0x64, 0x66, 0x34, 0x61, 0x6E, 0x34, 0x45, 0x4B, 0x77, 0x74, 0x33, 0x58, 0x39, 0x77, 0x6E, 0x51, 0x57, 0x33, 0x49, 0x56, 0x35, 0x42, 0x34, 0x4A, 0x61, 0x6A, 0x30, 0x7A, 0x38, 0x79, 0x47, 0x61, 0x35, 0x68, ++ 0x56, 0x2B, 0x72, 0x56, 0x48, 0x56, 0x44, 0x52, 0x44, 0x74, 0x66, 0x55, 0x4C, 0x41, 0x6A, 0x2B, 0x37, 0x41, 0x0A, 0x6D, 0x67, 0x6A, 0x56, 0x51, 0x64, 0x5A, 0x63, 0x44, 0x69, 0x46, 0x70, 0x62, 0x6F, 0x42, 0x68, 0x44, 0x68, 0x58, 0x41, 0x75, ++ 0x4D, 0x2F, 0x46, 0x53, 0x52, 0x4A, 0x53, 0x7A, 0x4C, 0x34, 0x36, 0x7A, 0x4E, 0x51, 0x75, 0x4F, 0x41, 0x58, 0x65, 0x4E, 0x66, 0x30, 0x66, 0x62, 0x37, 0x69, 0x41, 0x61, 0x4A, 0x67, 0x39, 0x54, 0x61, 0x44, 0x4B, 0x51, 0x47, 0x58, 0x53, 0x63, ++ 0x33, 0x7A, 0x31, 0x69, 0x39, 0x6B, 0x4B, 0x6C, 0x54, 0x2F, 0x59, 0x50, 0x79, 0x4E, 0x74, 0x0A, 0x47, 0x74, 0x45, 0x71, 0x4A, 0x42, 0x6E, 0x5A, 0x68, 0x62, 0x4D, 0x58, 0x37, 0x33, 0x68, 0x75, 0x71, 0x56, 0x6A, 0x52, 0x49, 0x39, 0x50, 0x48, ++ 0x45, 0x2B, 0x31, 0x79, 0x4A, 0x58, 0x39, 0x64, 0x73, 0x58, 0x4E, 0x77, 0x30, 0x48, 0x38, 0x47, 0x6C, 0x77, 0x6D, 0x45, 0x4B, 0x59, 0x42, 0x68, 0x48, 0x66, 0x70, 0x65, 0x2F, 0x33, 0x4F, 0x73, 0x6F, 0x4F, 0x4F, 0x4A, 0x75, 0x42, 0x78, 0x78, ++ 0x46, 0x63, 0x62, 0x65, 0x4D, 0x58, 0x38, 0x53, 0x33, 0x4F, 0x46, 0x74, 0x0A, 0x6D, 0x36, 0x2F, 0x6E, 0x36, 0x4A, 0x39, 0x31, 0x65, 0x45, 0x79, 0x72, 0x52, 0x6A, 0x75, 0x61, 0x7A, 0x72, 0x38, 0x46, 0x47, 0x46, 0x31, 0x4E, 0x46, 0x54, 0x77, ++ 0x57, 0x6D, 0x68, 0x6C, 0x51, 0x42, 0x4A, 0x71, 0x79, 0x6D, 0x6D, 0x39, 0x6C, 0x69, 0x31, 0x4A, 0x66, 0x50, 0x46, 0x67, 0x45, 0x4B, 0x43, 0x58, 0x41, 0x5A, 0x6D, 0x45, 0x78, 0x66, 0x72, 0x6E, 0x67, 0x64, 0x62, 0x6B, 0x61, 0x71, 0x49, 0x48, ++ 0x57, 0x63, 0x68, 0x65, 0x7A, 0x78, 0x51, 0x4D, 0x78, 0x0A, 0x4E, 0x52, 0x46, 0x34, 0x65, 0x4B, 0x4C, 0x67, 0x36, 0x54, 0x43, 0x4D, 0x66, 0x34, 0x44, 0x66, 0x57, 0x4E, 0x38, 0x38, 0x75, 0x69, 0x65, 0x57, 0x34, 0x6F, 0x41, 0x30, 0x62, 0x65, ++ 0x4F, 0x59, 0x30, 0x32, 0x51, 0x6E, 0x72, 0x45, 0x68, 0x2B, 0x4B, 0x48, 0x64, 0x63, 0x78, 0x69, 0x56, 0x68, 0x4A, 0x66, 0x69, 0x46, 0x44, 0x47, 0x58, 0x36, 0x78, 0x44, 0x49, 0x76, 0x70, 0x5A, 0x67, 0x46, 0x35, 0x50, 0x67, 0x4C, 0x5A, 0x78, ++ 0x59, 0x57, 0x78, 0x6F, 0x4B, 0x34, 0x0A, 0x4D, 0x68, 0x6E, 0x35, 0x2B, 0x62, 0x6C, 0x35, 0x33, 0x42, 0x2F, 0x4E, 0x36, 0x36, 0x2B, 0x72, 0x44, 0x74, 0x30, 0x62, 0x32, 0x30, 0x58, 0x6B, 0x65, 0x75, 0x63, 0x43, 0x34, 0x70, 0x56, 0x64, 0x2F, ++ 0x47, 0x6E, 0x77, 0x55, 0x32, 0x6C, 0x68, 0x6C, 0x58, 0x56, 0x35, 0x43, 0x31, 0x35, 0x56, 0x35, 0x6A, 0x67, 0x63, 0x6C, 0x4B, 0x6C, 0x5A, 0x4D, 0x35, 0x37, 0x49, 0x63, 0x58, 0x52, 0x35, 0x66, 0x31, 0x47, 0x4A, 0x74, 0x73, 0x68, 0x71, 0x75, ++ 0x44, 0x44, 0x49, 0x0A, 0x61, 0x6A, 0x6A, 0x44, 0x62, 0x70, 0x37, 0x68, 0x4E, 0x78, 0x62, 0x71, 0x42, 0x57, 0x4A, 0x4D, 0x57, 0x78, 0x4A, 0x48, 0x37, 0x61, 0x65, 0x30, 0x73, 0x31, 0x68, 0x57, 0x78, 0x30, 0x6E, 0x7A, 0x66, 0x78, 0x4A, 0x6F, ++ 0x43, 0x54, 0x46, 0x78, 0x38, 0x47, 0x33, 0x34, 0x54, 0x6B, 0x66, 0x37, 0x31, 0x6F, 0x58, 0x75, 0x78, 0x56, 0x68, 0x41, 0x47, 0x61, 0x51, 0x64, 0x70, 0x2F, 0x6C, 0x4C, 0x51, 0x7A, 0x66, 0x63, 0x61, 0x46, 0x70, 0x50, 0x7A, 0x2B, 0x76, 0x43, ++ 0x0A, 0x5A, 0x48, 0x54, 0x65, 0x74, 0x42, 0x58, 0x5A, 0x39, 0x46, 0x52, 0x55, 0x47, 0x69, 0x38, 0x63, 0x31, 0x35, 0x64, 0x78, 0x56, 0x4A, 0x43, 0x4F, 0x32, 0x53, 0x43, 0x64, 0x55, 0x79, 0x74, 0x2F, 0x71, 0x34, 0x2F, 0x69, 0x36, 0x6A, 0x43, ++ 0x38, 0x55, 0x44, 0x66, 0x76, 0x38, 0x55, 0x65, 0x31, 0x66, 0x58, 0x77, 0x73, 0x42, 0x4F, 0x78, 0x6F, 0x6E, 0x62, 0x52, 0x4A, 0x52, 0x42, 0x44, 0x30, 0x63, 0x6B, 0x73, 0x63, 0x5A, 0x4F, 0x66, 0x38, 0x35, 0x6D, 0x75, 0x51, 0x0A, 0x33, 0x57, ++ 0x6C, 0x39, 0x61, 0x66, 0x30, 0x41, 0x56, 0x71, 0x57, 0x33, 0x72, 0x4C, 0x61, 0x74, 0x74, 0x38, 0x6F, 0x2B, 0x41, 0x65, 0x2B, 0x63, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, ++ 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, ++ 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x47, 0x32, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, ++ 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x45, 0x50, 0x6A, 0x43, 0x43, 0x41, 0x79, 0x61, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x45, 0x53, 0x6C, 0x4F, 0x4D, 0x4B, 0x44, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, ++ 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x44, 0x43, 0x42, 0x76, 0x6A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x56, 0x56, 0x4D, 0x78, 0x46, 0x6A, 0x41, 0x55, 0x42, 0x67, 0x4E, 0x56, 0x0A, 0x42, ++ 0x41, 0x6F, 0x54, 0x44, 0x55, 0x56, 0x75, 0x64, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x51, 0x73, 0x49, 0x45, 0x6C, 0x75, 0x59, 0x79, 0x34, 0x78, 0x4B, 0x44, 0x41, 0x6D, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x73, 0x54, 0x48, 0x31, 0x4E, 0x6C, 0x5A, ++ 0x53, 0x42, 0x33, 0x64, 0x33, 0x63, 0x75, 0x5A, 0x57, 0x35, 0x30, 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x43, 0x35, 0x75, 0x5A, 0x58, 0x51, 0x76, 0x62, 0x47, 0x56, 0x6E, 0x59, 0x57, 0x77, 0x74, 0x64, 0x47, 0x56, 0x79, 0x0A, 0x62, 0x58, 0x4D, 0x78, ++ 0x4F, 0x54, 0x41, 0x33, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x73, 0x54, 0x4D, 0x43, 0x68, 0x6A, 0x4B, 0x53, 0x41, 0x79, 0x4D, 0x44, 0x41, 0x35, 0x49, 0x45, 0x56, 0x75, 0x64, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x51, 0x73, 0x49, 0x45, 0x6C, 0x75, ++ 0x59, 0x79, 0x34, 0x67, 0x4C, 0x53, 0x42, 0x6D, 0x62, 0x33, 0x49, 0x67, 0x59, 0x58, 0x56, 0x30, 0x61, 0x47, 0x39, 0x79, 0x61, 0x58, 0x70, 0x6C, 0x5A, 0x43, 0x42, 0x31, 0x63, 0x32, 0x55, 0x67, 0x0A, 0x62, 0x32, 0x35, 0x73, 0x65, 0x54, 0x45, ++ 0x79, 0x4D, 0x44, 0x41, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x70, 0x52, 0x57, 0x35, 0x30, 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x43, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x6C, 0x63, 0x6E, 0x52, 0x70, 0x5A, 0x6D, 0x6C, ++ 0x6A, 0x59, 0x58, 0x52, 0x70, 0x62, 0x32, 0x34, 0x67, 0x51, 0x58, 0x56, 0x30, 0x61, 0x47, 0x39, 0x79, 0x61, 0x58, 0x52, 0x35, 0x49, 0x43, 0x30, 0x67, 0x52, 0x7A, 0x49, 0x77, 0x0A, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x44, 0x6B, 0x77, 0x4E, 0x7A, ++ 0x41, 0x33, 0x4D, 0x54, 0x63, 0x79, 0x4E, 0x54, 0x55, 0x30, 0x57, 0x68, 0x63, 0x4E, 0x4D, 0x7A, 0x41, 0x78, 0x4D, 0x6A, 0x41, 0x33, 0x4D, 0x54, 0x63, 0x31, 0x4E, 0x54, 0x55, 0x30, 0x57, 0x6A, 0x43, 0x42, 0x76, 0x6A, 0x45, 0x4C, 0x4D, 0x41, ++ 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x56, 0x56, 0x4D, 0x78, 0x46, 0x6A, 0x41, 0x55, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x0A, 0x44, 0x55, 0x56, 0x75, 0x64, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x51, 0x73, 0x49, ++ 0x45, 0x6C, 0x75, 0x59, 0x79, 0x34, 0x78, 0x4B, 0x44, 0x41, 0x6D, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x73, 0x54, 0x48, 0x31, 0x4E, 0x6C, 0x5A, 0x53, 0x42, 0x33, 0x64, 0x33, 0x63, 0x75, 0x5A, 0x57, 0x35, 0x30, 0x63, 0x6E, 0x56, 0x7A, 0x64, ++ 0x43, 0x35, 0x75, 0x5A, 0x58, 0x51, 0x76, 0x62, 0x47, 0x56, 0x6E, 0x59, 0x57, 0x77, 0x74, 0x64, 0x47, 0x56, 0x79, 0x62, 0x58, 0x4D, 0x78, 0x0A, 0x4F, 0x54, 0x41, 0x33, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x73, 0x54, 0x4D, 0x43, 0x68, 0x6A, ++ 0x4B, 0x53, 0x41, 0x79, 0x4D, 0x44, 0x41, 0x35, 0x49, 0x45, 0x56, 0x75, 0x64, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x51, 0x73, 0x49, 0x45, 0x6C, 0x75, 0x59, 0x79, 0x34, 0x67, 0x4C, 0x53, 0x42, 0x6D, 0x62, 0x33, 0x49, 0x67, 0x59, 0x58, 0x56, 0x30, ++ 0x61, 0x47, 0x39, 0x79, 0x61, 0x58, 0x70, 0x6C, 0x5A, 0x43, 0x42, 0x31, 0x63, 0x32, 0x55, 0x67, 0x62, 0x32, 0x35, 0x73, 0x0A, 0x65, 0x54, 0x45, 0x79, 0x4D, 0x44, 0x41, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x70, 0x52, 0x57, 0x35, ++ 0x30, 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x43, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x6C, 0x63, 0x6E, 0x52, 0x70, 0x5A, 0x6D, 0x6C, 0x6A, 0x59, 0x58, 0x52, 0x70, 0x62, 0x32, 0x34, 0x67, 0x51, 0x58, 0x56, 0x30, 0x61, 0x47, 0x39, ++ 0x79, 0x61, 0x58, 0x52, 0x35, 0x49, 0x43, 0x30, 0x67, 0x52, 0x7A, 0x49, 0x77, 0x67, 0x67, 0x45, 0x69, 0x0A, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, ++ 0x49, 0x42, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x45, 0x4B, 0x41, 0x6F, 0x49, 0x42, 0x41, 0x51, 0x43, 0x36, 0x68, 0x4C, 0x5A, 0x79, 0x32, 0x35, 0x34, 0x4D, 0x61, 0x2B, 0x4B, 0x5A, 0x36, 0x54, 0x41, 0x42, 0x70, 0x33, 0x62, 0x71, 0x4D, 0x72, ++ 0x69, 0x56, 0x51, 0x52, 0x72, 0x4A, 0x32, 0x6D, 0x46, 0x4F, 0x57, 0x48, 0x4C, 0x50, 0x0A, 0x2F, 0x76, 0x61, 0x43, 0x65, 0x62, 0x39, 0x7A, 0x59, 0x51, 0x59, 0x4B, 0x70, 0x53, 0x66, 0x59, 0x73, 0x31, 0x2F, 0x54, 0x52, 0x55, 0x34, 0x63, 0x63, ++ 0x74, 0x5A, 0x4F, 0x4D, 0x76, 0x4A, 0x79, 0x69, 0x67, 0x2F, 0x33, 0x67, 0x78, 0x6E, 0x51, 0x61, 0x6F, 0x43, 0x41, 0x41, 0x45, 0x55, 0x65, 0x73, 0x4D, 0x66, 0x6E, 0x6D, 0x72, 0x38, 0x53, 0x56, 0x79, 0x63, 0x63, 0x6F, 0x32, 0x67, 0x76, 0x43, ++ 0x6F, 0x65, 0x39, 0x61, 0x6D, 0x73, 0x4F, 0x58, 0x6D, 0x58, 0x7A, 0x0A, 0x48, 0x48, 0x66, 0x56, 0x31, 0x49, 0x57, 0x4E, 0x63, 0x43, 0x47, 0x30, 0x73, 0x7A, 0x4C, 0x6E, 0x69, 0x36, 0x4C, 0x56, 0x68, 0x6A, 0x6B, 0x43, 0x73, 0x62, 0x6A, 0x53, ++ 0x52, 0x38, 0x37, 0x6B, 0x79, 0x55, 0x6E, 0x45, 0x4F, 0x36, 0x66, 0x65, 0x2B, 0x31, 0x52, 0x39, 0x56, 0x37, 0x37, 0x77, 0x36, 0x47, 0x37, 0x43, 0x65, 0x62, 0x49, 0x36, 0x43, 0x31, 0x58, 0x69, 0x55, 0x4A, 0x67, 0x57, 0x4D, 0x68, 0x4E, 0x63, ++ 0x4C, 0x33, 0x68, 0x57, 0x77, 0x63, 0x4B, 0x55, 0x0A, 0x73, 0x2F, 0x4A, 0x61, 0x35, 0x43, 0x65, 0x61, 0x6E, 0x79, 0x54, 0x58, 0x78, 0x75, 0x7A, 0x51, 0x6D, 0x79, 0x57, 0x43, 0x34, 0x38, 0x7A, 0x43, 0x78, 0x45, 0x58, 0x46, 0x6A, 0x4A, 0x64, ++ 0x36, 0x42, 0x6D, 0x73, 0x71, 0x45, 0x5A, 0x2B, 0x70, 0x43, 0x6D, 0x35, 0x49, 0x4F, 0x32, 0x2F, 0x62, 0x31, 0x42, 0x45, 0x5A, 0x51, 0x76, 0x65, 0x50, 0x42, 0x37, 0x2F, 0x31, 0x55, 0x31, 0x2B, 0x63, 0x50, 0x76, 0x51, 0x58, 0x4C, 0x4F, 0x5A, ++ 0x70, 0x72, 0x45, 0x34, 0x79, 0x0A, 0x54, 0x47, 0x4A, 0x33, 0x36, 0x72, 0x66, 0x6F, 0x35, 0x62, 0x73, 0x30, 0x76, 0x42, 0x6D, 0x4C, 0x72, 0x70, 0x78, 0x52, 0x35, 0x37, 0x64, 0x2B, 0x74, 0x56, 0x4F, 0x78, 0x4D, 0x79, 0x4C, 0x6C, 0x62, 0x63, ++ 0x39, 0x77, 0x50, 0x42, 0x72, 0x36, 0x34, 0x70, 0x74, 0x6E, 0x74, 0x6F, 0x50, 0x30, 0x6A, 0x61, 0x57, 0x76, 0x59, 0x6B, 0x78, 0x4E, 0x34, 0x46, 0x69, 0x73, 0x5A, 0x44, 0x51, 0x53, 0x41, 0x2F, 0x69, 0x32, 0x6A, 0x5A, 0x52, 0x6A, 0x4A, 0x4B, ++ 0x52, 0x78, 0x0A, 0x41, 0x67, 0x4D, 0x42, 0x41, 0x41, 0x47, 0x6A, 0x51, 0x6A, 0x42, 0x41, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x42, 0x42, 0x6A, 0x41, 0x50, 0x42, ++ 0x67, 0x4E, 0x56, 0x48, 0x52, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x54, 0x41, 0x44, 0x41, 0x51, 0x48, 0x2F, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x52, 0x71, 0x63, 0x69, 0x5A, 0x36, 0x0A, ++ 0x30, 0x42, 0x37, 0x76, 0x66, 0x65, 0x63, 0x37, 0x61, 0x56, 0x48, 0x55, 0x62, 0x49, 0x32, 0x66, 0x6B, 0x42, 0x4A, 0x6D, 0x71, 0x7A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, ++ 0x41, 0x41, 0x4F, 0x43, 0x41, 0x51, 0x45, 0x41, 0x65, 0x5A, 0x38, 0x64, 0x6C, 0x73, 0x61, 0x32, 0x65, 0x54, 0x38, 0x69, 0x6A, 0x59, 0x66, 0x54, 0x68, 0x77, 0x4D, 0x45, 0x59, 0x47, 0x70, 0x72, 0x6D, 0x69, 0x35, 0x5A, 0x0A, 0x69, 0x58, 0x4D, ++ 0x52, 0x72, 0x45, 0x50, 0x52, 0x39, 0x52, 0x50, 0x2F, 0x6A, 0x54, 0x6B, 0x72, 0x77, 0x50, 0x4B, 0x39, 0x54, 0x33, 0x43, 0x4D, 0x71, 0x53, 0x2F, 0x71, 0x46, 0x38, 0x51, 0x4C, 0x56, 0x4A, 0x37, 0x55, 0x47, 0x35, 0x61, 0x59, 0x4D, 0x7A, 0x79, ++ 0x6F, 0x72, 0x57, 0x4B, 0x69, 0x41, 0x48, 0x61, 0x72, 0x57, 0x57, 0x6C, 0x75, 0x42, 0x68, 0x31, 0x2B, 0x78, 0x4C, 0x6C, 0x45, 0x6A, 0x5A, 0x69, 0x76, 0x45, 0x74, 0x52, 0x68, 0x32, 0x77, 0x6F, 0x5A, 0x0A, 0x52, 0x6B, 0x66, 0x7A, 0x36, 0x2F, ++ 0x64, 0x6A, 0x77, 0x55, 0x41, 0x46, 0x51, 0x4B, 0x58, 0x53, 0x74, 0x2F, 0x53, 0x31, 0x6D, 0x6A, 0x61, 0x2F, 0x71, 0x59, 0x68, 0x32, 0x69, 0x41, 0x52, 0x56, 0x42, 0x43, 0x75, 0x63, 0x68, 0x33, 0x38, 0x61, 0x4E, 0x7A, 0x78, 0x2B, 0x4C, 0x61, ++ 0x55, 0x61, 0x32, 0x4E, 0x53, 0x4A, 0x58, 0x73, 0x71, 0x39, 0x72, 0x44, 0x31, 0x73, 0x32, 0x47, 0x32, 0x76, 0x31, 0x66, 0x4E, 0x32, 0x44, 0x38, 0x30, 0x37, 0x69, 0x44, 0x67, 0x69, 0x0A, 0x6E, 0x57, 0x79, 0x54, 0x6D, 0x73, 0x51, 0x39, 0x76, ++ 0x34, 0x49, 0x62, 0x5A, 0x54, 0x2B, 0x6D, 0x44, 0x31, 0x32, 0x71, 0x2F, 0x4F, 0x57, 0x79, 0x46, 0x63, 0x71, 0x31, 0x72, 0x63, 0x61, 0x38, 0x50, 0x64, 0x43, 0x45, 0x36, 0x4F, 0x6F, 0x47, 0x63, 0x72, 0x42, 0x4E, 0x4F, 0x54, 0x4A, 0x34, 0x76, ++ 0x7A, 0x34, 0x52, 0x6E, 0x41, 0x75, 0x6B, 0x6E, 0x5A, 0x6F, 0x68, 0x38, 0x2F, 0x43, 0x62, 0x43, 0x7A, 0x42, 0x34, 0x32, 0x38, 0x48, 0x63, 0x68, 0x30, 0x50, 0x2B, 0x0A, 0x76, 0x47, 0x4F, 0x61, 0x79, 0x73, 0x58, 0x43, 0x48, 0x4D, 0x6E, 0x48, ++ 0x6A, 0x66, 0x38, 0x37, 0x45, 0x6C, 0x67, 0x49, 0x35, 0x72, 0x59, 0x39, 0x37, 0x48, 0x6F, 0x73, 0x54, 0x76, 0x75, 0x44, 0x6C, 0x73, 0x34, 0x4D, 0x50, 0x47, 0x6D, 0x48, 0x56, 0x48, 0x4F, 0x6B, 0x63, 0x38, 0x4B, 0x54, 0x2F, 0x31, 0x45, 0x51, ++ 0x72, 0x42, 0x56, 0x55, 0x41, 0x64, 0x6A, 0x38, 0x42, 0x62, 0x47, 0x4A, 0x6F, 0x58, 0x39, 0x30, 0x67, 0x35, 0x70, 0x4A, 0x31, 0x39, 0x78, 0x4F, 0x0A, 0x65, 0x34, 0x70, 0x49, 0x62, 0x34, 0x74, 0x46, 0x39, 0x67, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, ++ 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, ++ 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x45, 0x43, 0x31, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, ++ 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x43, 0x2B, 0x54, 0x43, 0x43, 0x41, 0x6F, 0x43, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x4E, 0x41, ++ 0x4B, 0x61, 0x4C, 0x65, 0x53, 0x6B, 0x41, 0x41, 0x41, 0x41, 0x41, 0x55, 0x4E, 0x43, 0x52, 0x2B, 0x54, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x7A, 0x43, 0x42, 0x76, 0x7A, 0x45, 0x4C, 0x4D, ++ 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x56, 0x56, 0x4D, 0x78, 0x0A, 0x46, 0x6A, 0x41, 0x55, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x44, 0x55, 0x56, 0x75, 0x64, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x51, 0x73, ++ 0x49, 0x45, 0x6C, 0x75, 0x59, 0x79, 0x34, 0x78, 0x4B, 0x44, 0x41, 0x6D, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x73, 0x54, 0x48, 0x31, 0x4E, 0x6C, 0x5A, 0x53, 0x42, 0x33, 0x64, 0x33, 0x63, 0x75, 0x5A, 0x57, 0x35, 0x30, 0x63, 0x6E, 0x56, 0x7A, ++ 0x64, 0x43, 0x35, 0x75, 0x5A, 0x58, 0x51, 0x76, 0x62, 0x47, 0x56, 0x6E, 0x0A, 0x59, 0x57, 0x77, 0x74, 0x64, 0x47, 0x56, 0x79, 0x62, 0x58, 0x4D, 0x78, 0x4F, 0x54, 0x41, 0x33, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x73, 0x54, 0x4D, 0x43, 0x68, ++ 0x6A, 0x4B, 0x53, 0x41, 0x79, 0x4D, 0x44, 0x45, 0x79, 0x49, 0x45, 0x56, 0x75, 0x64, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x51, 0x73, 0x49, 0x45, 0x6C, 0x75, 0x59, 0x79, 0x34, 0x67, 0x4C, 0x53, 0x42, 0x6D, 0x62, 0x33, 0x49, 0x67, 0x59, 0x58, 0x56, ++ 0x30, 0x61, 0x47, 0x39, 0x79, 0x61, 0x58, 0x70, 0x6C, 0x0A, 0x5A, 0x43, 0x42, 0x31, 0x63, 0x32, 0x55, 0x67, 0x62, 0x32, 0x35, 0x73, 0x65, 0x54, 0x45, 0x7A, 0x4D, 0x44, 0x45, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x71, 0x52, 0x57, ++ 0x35, 0x30, 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x43, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x6C, 0x63, 0x6E, 0x52, 0x70, 0x5A, 0x6D, 0x6C, 0x6A, 0x59, 0x58, 0x52, 0x70, 0x62, 0x32, 0x34, 0x67, 0x51, 0x58, 0x56, 0x30, 0x61, 0x47, ++ 0x39, 0x79, 0x61, 0x58, 0x52, 0x35, 0x0A, 0x49, 0x43, 0x30, 0x67, 0x52, 0x55, 0x4D, 0x78, 0x4D, 0x42, 0x34, 0x58, 0x44, 0x54, 0x45, 0x79, 0x4D, 0x54, 0x49, 0x78, 0x4F, 0x44, 0x45, 0x31, 0x4D, 0x6A, 0x55, 0x7A, 0x4E, 0x6C, 0x6F, 0x58, 0x44, ++ 0x54, 0x4D, 0x33, 0x4D, 0x54, 0x49, 0x78, 0x4F, 0x44, 0x45, 0x31, 0x4E, 0x54, 0x55, 0x7A, 0x4E, 0x6C, 0x6F, 0x77, 0x67, 0x62, 0x38, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6C, 0x56, 0x54, 0x4D, ++ 0x52, 0x59, 0x77, 0x0A, 0x46, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x45, 0x77, 0x31, 0x46, 0x62, 0x6E, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x4C, 0x43, 0x42, 0x4A, 0x62, 0x6D, 0x4D, 0x75, 0x4D, 0x53, 0x67, 0x77, 0x4A, 0x67, 0x59, 0x44, ++ 0x56, 0x51, 0x51, 0x4C, 0x45, 0x78, 0x39, 0x54, 0x5A, 0x57, 0x55, 0x67, 0x64, 0x33, 0x64, 0x33, 0x4C, 0x6D, 0x56, 0x75, 0x64, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x51, 0x75, 0x62, 0x6D, 0x56, 0x30, 0x4C, 0x32, 0x78, 0x6C, 0x5A, 0x32, 0x46, 0x73, ++ 0x0A, 0x4C, 0x58, 0x52, 0x6C, 0x63, 0x6D, 0x31, 0x7A, 0x4D, 0x54, 0x6B, 0x77, 0x4E, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4C, 0x45, 0x7A, 0x41, 0x6F, 0x59, 0x79, 0x6B, 0x67, 0x4D, 0x6A, 0x41, 0x78, 0x4D, 0x69, 0x42, 0x46, 0x62, 0x6E, 0x52, ++ 0x79, 0x64, 0x58, 0x4E, 0x30, 0x4C, 0x43, 0x42, 0x4A, 0x62, 0x6D, 0x4D, 0x75, 0x49, 0x43, 0x30, 0x67, 0x5A, 0x6D, 0x39, 0x79, 0x49, 0x47, 0x46, 0x31, 0x64, 0x47, 0x68, 0x76, 0x63, 0x6D, 0x6C, 0x36, 0x5A, 0x57, 0x51, 0x67, 0x0A, 0x64, 0x58, ++ 0x4E, 0x6C, 0x49, 0x47, 0x39, 0x75, 0x62, 0x48, 0x6B, 0x78, 0x4D, 0x7A, 0x41, 0x78, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x4B, 0x6B, 0x56, 0x75, 0x64, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x51, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, ++ 0x42, 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x61, 0x57, 0x5A, 0x70, 0x59, 0x32, 0x46, 0x30, 0x61, 0x57, 0x39, 0x75, 0x49, 0x45, 0x46, 0x31, 0x64, 0x47, 0x68, 0x76, 0x63, 0x6D, 0x6C, 0x30, 0x65, 0x53, 0x41, 0x74, 0x0A, 0x49, 0x45, 0x56, 0x44, 0x4D, ++ 0x54, 0x42, 0x32, 0x4D, 0x42, 0x41, 0x47, 0x42, 0x79, 0x71, 0x47, 0x53, 0x4D, 0x34, 0x39, 0x41, 0x67, 0x45, 0x47, 0x42, 0x53, 0x75, 0x42, 0x42, 0x41, 0x41, 0x69, 0x41, 0x32, 0x49, 0x41, 0x42, 0x49, 0x51, 0x54, 0x79, 0x64, 0x43, 0x36, 0x62, ++ 0x55, 0x46, 0x37, 0x34, 0x6D, 0x7A, 0x51, 0x36, 0x31, 0x56, 0x66, 0x5A, 0x67, 0x49, 0x61, 0x4A, 0x50, 0x52, 0x62, 0x69, 0x57, 0x6C, 0x48, 0x34, 0x37, 0x6A, 0x43, 0x66, 0x66, 0x48, 0x79, 0x0A, 0x41, 0x73, 0x57, 0x66, 0x6F, 0x50, 0x5A, 0x62, ++ 0x31, 0x59, 0x73, 0x47, 0x47, 0x59, 0x5A, 0x50, 0x55, 0x78, 0x42, 0x74, 0x42, 0x79, 0x51, 0x6E, 0x6F, 0x61, 0x44, 0x34, 0x31, 0x55, 0x63, 0x5A, 0x59, 0x55, 0x78, 0x39, 0x79, 0x70, 0x4D, 0x6E, 0x36, 0x6E, 0x51, 0x4D, 0x37, 0x32, 0x2B, 0x57, ++ 0x43, 0x66, 0x35, 0x6A, 0x37, 0x48, 0x42, 0x64, 0x4E, 0x71, 0x31, 0x6E, 0x64, 0x36, 0x37, 0x4A, 0x6E, 0x58, 0x78, 0x56, 0x52, 0x44, 0x71, 0x69, 0x59, 0x31, 0x45, 0x66, 0x0A, 0x39, 0x65, 0x4E, 0x69, 0x31, 0x4B, 0x6C, 0x48, 0x42, 0x7A, 0x37, ++ 0x4D, 0x49, 0x4B, 0x4E, 0x43, 0x4D, 0x45, 0x41, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x51, 0x44, 0x41, 0x67, 0x45, 0x47, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, ++ 0x42, 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x48, 0x51, 0x59, 0x44, 0x56, 0x52, 0x30, 0x4F, 0x42, 0x42, 0x59, 0x45, 0x0A, 0x46, 0x4C, 0x64, 0x6A, 0x35, 0x78, 0x72, 0x64, 0x6A, 0x65, 0x6B, 0x49, 0x70, 0x6C, ++ 0x57, 0x44, 0x70, 0x4F, 0x42, 0x71, 0x55, 0x45, 0x46, 0x6C, 0x45, 0x55, 0x4A, 0x4A, 0x4D, 0x41, 0x6F, 0x47, 0x43, 0x43, 0x71, 0x47, 0x53, 0x4D, 0x34, 0x39, 0x42, 0x41, 0x4D, 0x44, 0x41, 0x32, 0x63, 0x41, 0x4D, 0x47, 0x51, 0x43, 0x4D, 0x47, ++ 0x46, 0x35, 0x32, 0x4F, 0x56, 0x43, 0x52, 0x39, 0x38, 0x63, 0x72, 0x6C, 0x4F, 0x5A, 0x46, 0x37, 0x5A, 0x76, 0x48, 0x48, 0x33, 0x68, 0x0A, 0x76, 0x78, 0x47, 0x55, 0x30, 0x51, 0x4F, 0x49, 0x64, 0x65, 0x53, 0x4E, 0x69, 0x61, 0x53, 0x4B, 0x64, ++ 0x30, 0x62, 0x65, 0x62, 0x57, 0x48, 0x76, 0x41, 0x76, 0x58, 0x37, 0x74, 0x64, 0x2F, 0x4D, 0x2F, 0x6B, 0x37, 0x2F, 0x2F, 0x71, 0x6E, 0x6D, 0x70, 0x77, 0x49, 0x77, 0x57, 0x35, 0x6E, 0x58, 0x68, 0x54, 0x63, 0x47, 0x74, 0x58, 0x73, 0x49, 0x2F, ++ 0x65, 0x73, 0x6E, 0x69, 0x30, 0x71, 0x55, 0x2B, 0x65, 0x48, 0x36, 0x70, 0x34, 0x34, 0x6D, 0x43, 0x4F, 0x68, 0x38, 0x0A, 0x6B, 0x6D, 0x68, 0x74, 0x63, 0x39, 0x68, 0x76, 0x4A, 0x71, 0x77, 0x68, 0x41, 0x72, 0x69, 0x5A, 0x74, 0x79, 0x5A, 0x42, ++ 0x57, 0x79, 0x56, 0x67, 0x72, 0x74, 0x42, 0x49, 0x47, 0x75, 0x34, 0x47, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, ++ 0x43, 0x46, 0x43, 0x41, 0x20, 0x45, 0x56, 0x20, 0x52, 0x4F, 0x4F, 0x54, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, ++ 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x6A, 0x54, 0x43, 0x43, 0x41, 0x33, 0x57, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x45, 0x47, 0x45, 0x72, 0x4D, 0x31, 0x6A, ++ 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x44, 0x42, 0x57, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x44, 0x54, 0x6A, ++ 0x45, 0x77, 0x4D, 0x43, 0x34, 0x47, 0x41, 0x31, 0x55, 0x45, 0x0A, 0x43, 0x67, 0x77, 0x6E, 0x51, 0x32, 0x68, 0x70, 0x62, 0x6D, 0x45, 0x67, 0x52, 0x6D, 0x6C, 0x75, 0x59, 0x57, 0x35, 0x6A, 0x61, 0x57, 0x46, 0x73, 0x49, 0x45, 0x4E, 0x6C, 0x63, ++ 0x6E, 0x52, 0x70, 0x5A, 0x6D, 0x6C, 0x6A, 0x59, 0x58, 0x52, 0x70, 0x62, 0x32, 0x34, 0x67, 0x51, 0x58, 0x56, 0x30, 0x61, 0x47, 0x39, 0x79, 0x61, 0x58, 0x52, 0x35, 0x4D, 0x52, 0x55, 0x77, 0x45, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x44, ++ 0x41, 0x78, 0x44, 0x52, 0x6B, 0x4E, 0x42, 0x0A, 0x49, 0x45, 0x56, 0x57, 0x49, 0x46, 0x4A, 0x50, 0x54, 0x31, 0x51, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x54, 0x49, 0x77, 0x4F, 0x44, 0x41, 0x34, 0x4D, 0x44, 0x4D, 0x77, 0x4E, 0x7A, 0x41, 0x78, ++ 0x57, 0x68, 0x63, 0x4E, 0x4D, 0x6A, 0x6B, 0x78, 0x4D, 0x6A, 0x4D, 0x78, 0x4D, 0x44, 0x4D, 0x77, 0x4E, 0x7A, 0x41, 0x78, 0x57, 0x6A, 0x42, 0x57, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x44, ++ 0x54, 0x6A, 0x45, 0x77, 0x0A, 0x4D, 0x43, 0x34, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, 0x6E, 0x51, 0x32, 0x68, 0x70, 0x62, 0x6D, 0x45, 0x67, 0x52, 0x6D, 0x6C, 0x75, 0x59, 0x57, 0x35, 0x6A, 0x61, 0x57, 0x46, 0x73, 0x49, 0x45, 0x4E, ++ 0x6C, 0x63, 0x6E, 0x52, 0x70, 0x5A, 0x6D, 0x6C, 0x6A, 0x59, 0x58, 0x52, 0x70, 0x62, 0x32, 0x34, 0x67, 0x51, 0x58, 0x56, 0x30, 0x61, 0x47, 0x39, 0x79, 0x61, 0x58, 0x52, 0x35, 0x4D, 0x52, 0x55, 0x77, 0x45, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, ++ 0x44, 0x0A, 0x44, 0x41, 0x78, 0x44, 0x52, 0x6B, 0x4E, 0x42, 0x49, 0x45, 0x56, 0x57, 0x49, 0x46, 0x4A, 0x50, 0x54, 0x31, 0x51, 0x77, 0x67, 0x67, 0x49, 0x69, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, ++ 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x49, 0x4B, 0x41, 0x6F, 0x49, 0x43, 0x41, 0x51, 0x44, 0x58, 0x58, 0x57, 0x76, 0x4E, 0x45, 0x44, 0x38, 0x66, 0x42, 0x56, 0x6E, 0x56, 0x0A, 0x42, ++ 0x55, 0x30, 0x33, 0x73, 0x51, 0x37, 0x73, 0x6D, 0x43, 0x75, 0x4F, 0x46, 0x52, 0x33, 0x36, 0x6B, 0x30, 0x73, 0x58, 0x67, 0x69, 0x46, 0x78, 0x45, 0x46, 0x4C, 0x58, 0x55, 0x57, 0x52, 0x77, 0x46, 0x73, 0x4A, 0x56, 0x61, 0x55, 0x32, 0x4F, 0x46, ++ 0x57, 0x32, 0x66, 0x76, 0x77, 0x77, 0x62, 0x77, 0x75, 0x43, 0x6A, 0x5A, 0x39, 0x59, 0x4D, 0x72, 0x4D, 0x38, 0x69, 0x72, 0x71, 0x39, 0x33, 0x56, 0x43, 0x70, 0x4C, 0x54, 0x49, 0x70, 0x54, 0x55, 0x6E, 0x72, 0x44, 0x0A, 0x37, 0x69, 0x37, 0x65, ++ 0x73, 0x33, 0x45, 0x6C, 0x77, 0x65, 0x6C, 0x64, 0x50, 0x65, 0x36, 0x68, 0x4C, 0x36, 0x50, 0x33, 0x4B, 0x6A, 0x7A, 0x4A, 0x49, 0x78, 0x31, 0x71, 0x71, 0x78, 0x32, 0x68, 0x70, 0x2F, 0x48, 0x7A, 0x37, 0x4B, 0x44, 0x56, 0x52, 0x4D, 0x38, 0x56, ++ 0x7A, 0x33, 0x49, 0x76, 0x48, 0x57, 0x4F, 0x58, 0x36, 0x4A, 0x6E, 0x35, 0x2F, 0x5A, 0x4F, 0x6B, 0x56, 0x49, 0x42, 0x4D, 0x55, 0x74, 0x52, 0x53, 0x71, 0x79, 0x35, 0x4A, 0x33, 0x35, 0x44, 0x4E, 0x0A, 0x75, 0x46, 0x2B, 0x2B, 0x50, 0x39, 0x36, ++ 0x68, 0x79, 0x6B, 0x30, 0x67, 0x31, 0x43, 0x58, 0x6F, 0x68, 0x43, 0x6C, 0x54, 0x74, 0x37, 0x47, 0x49, 0x48, 0x2F, 0x2F, 0x36, 0x32, 0x70, 0x43, 0x66, 0x43, 0x71, 0x6B, 0x74, 0x51, 0x54, 0x2B, 0x78, 0x38, 0x52, 0x67, 0x70, 0x37, 0x68, 0x5A, ++ 0x5A, 0x4C, 0x44, 0x52, 0x4A, 0x47, 0x71, 0x67, 0x47, 0x31, 0x36, 0x69, 0x49, 0x30, 0x67, 0x4E, 0x79, 0x65, 0x6A, 0x4C, 0x69, 0x36, 0x6D, 0x68, 0x4E, 0x62, 0x69, 0x79, 0x57, 0x0A, 0x5A, 0x58, 0x76, 0x4B, 0x57, 0x66, 0x72, 0x79, 0x34, 0x74, ++ 0x33, 0x75, 0x4D, 0x43, 0x7A, 0x37, 0x7A, 0x45, 0x61, 0x73, 0x78, 0x47, 0x50, 0x72, 0x62, 0x33, 0x38, 0x32, 0x4B, 0x7A, 0x52, 0x7A, 0x45, 0x70, 0x52, 0x2F, 0x33, 0x38, 0x77, 0x6D, 0x6E, 0x76, 0x46, 0x79, 0x58, 0x56, 0x42, 0x6C, 0x57, 0x59, ++ 0x39, 0x70, 0x73, 0x34, 0x64, 0x65, 0x4D, 0x6D, 0x2F, 0x44, 0x47, 0x49, 0x71, 0x31, 0x6C, 0x59, 0x2B, 0x77, 0x65, 0x6A, 0x66, 0x65, 0x57, 0x6B, 0x55, 0x37, 0x0A, 0x78, 0x7A, 0x62, 0x68, 0x37, 0x32, 0x66, 0x52, 0x4F, 0x64, 0x4F, 0x58, 0x57, ++ 0x33, 0x4E, 0x69, 0x47, 0x55, 0x67, 0x74, 0x68, 0x78, 0x77, 0x47, 0x2B, 0x33, 0x53, 0x59, 0x49, 0x45, 0x6C, 0x7A, 0x38, 0x41, 0x58, 0x53, 0x47, 0x37, 0x47, 0x67, 0x6F, 0x37, 0x63, 0x62, 0x63, 0x4E, 0x4F, 0x49, 0x61, 0x62, 0x6C, 0x61, 0x31, ++ 0x6A, 0x6A, 0x30, 0x59, 0x74, 0x77, 0x6C, 0x69, 0x33, 0x69, 0x2F, 0x2B, 0x4F, 0x68, 0x2B, 0x75, 0x46, 0x7A, 0x4A, 0x6C, 0x55, 0x39, 0x66, 0x0A, 0x70, 0x79, 0x32, 0x35, 0x49, 0x47, 0x76, 0x50, 0x61, 0x39, 0x33, 0x31, 0x44, 0x66, 0x53, 0x43, ++ 0x74, 0x2F, 0x53, 0x79, 0x5A, 0x69, 0x34, 0x51, 0x4B, 0x50, 0x61, 0x58, 0x57, 0x6E, 0x75, 0x57, 0x46, 0x6F, 0x38, 0x42, 0x47, 0x53, 0x31, 0x73, 0x62, 0x6E, 0x38, 0x35, 0x57, 0x41, 0x5A, 0x6B, 0x67, 0x77, 0x47, 0x44, 0x67, 0x38, 0x4E, 0x4E, ++ 0x6B, 0x74, 0x30, 0x79, 0x78, 0x6F, 0x65, 0x6B, 0x4E, 0x2B, 0x6B, 0x57, 0x7A, 0x71, 0x6F, 0x74, 0x61, 0x4B, 0x38, 0x4B, 0x0A, 0x67, 0x57, 0x55, 0x36, 0x63, 0x4D, 0x47, 0x62, 0x72, 0x55, 0x31, 0x74, 0x56, 0x4D, 0x6F, 0x71, 0x4C, 0x55, 0x75, ++ 0x46, 0x47, 0x37, 0x4F, 0x41, 0x35, 0x6E, 0x42, 0x46, 0x44, 0x57, 0x74, 0x65, 0x4E, 0x66, 0x42, 0x2F, 0x4F, 0x37, 0x69, 0x63, 0x35, 0x41, 0x52, 0x77, 0x69, 0x52, 0x49, 0x6C, 0x6B, 0x39, 0x6F, 0x4B, 0x6D, 0x53, 0x4A, 0x67, 0x61, 0x6D, 0x4E, ++ 0x67, 0x54, 0x6E, 0x59, 0x47, 0x6D, 0x45, 0x36, 0x39, 0x67, 0x36, 0x30, 0x64, 0x57, 0x49, 0x6F, 0x6C, 0x0A, 0x68, 0x64, 0x4C, 0x48, 0x5A, 0x52, 0x34, 0x74, 0x6A, 0x73, 0x62, 0x66, 0x74, 0x73, 0x62, 0x68, 0x66, 0x34, 0x6F, 0x45, 0x49, 0x52, ++ 0x55, 0x70, 0x64, 0x50, 0x41, 0x2B, 0x6E, 0x4A, 0x43, 0x64, 0x44, 0x43, 0x37, 0x78, 0x69, 0x6A, 0x35, 0x61, 0x71, 0x67, 0x77, 0x4A, 0x48, 0x73, 0x66, 0x56, 0x50, 0x4B, 0x50, 0x74, 0x6C, 0x38, 0x4D, 0x65, 0x4E, 0x50, 0x6F, 0x34, 0x2B, 0x51, ++ 0x67, 0x4F, 0x34, 0x38, 0x42, 0x64, 0x4B, 0x34, 0x50, 0x52, 0x56, 0x6D, 0x72, 0x4A, 0x0A, 0x74, 0x71, 0x68, 0x55, 0x55, 0x79, 0x35, 0x34, 0x4D, 0x6D, 0x63, 0x39, 0x67, 0x6E, 0x39, 0x30, 0x30, 0x50, 0x76, 0x68, 0x74, 0x67, 0x56, 0x67, 0x75, ++ 0x58, 0x44, 0x62, 0x6A, 0x67, 0x76, 0x35, 0x45, 0x31, 0x68, 0x76, 0x63, 0x57, 0x41, 0x51, 0x55, 0x68, 0x43, 0x35, 0x77, 0x55, 0x45, 0x4A, 0x37, 0x33, 0x49, 0x66, 0x5A, 0x7A, 0x46, 0x34, 0x2F, 0x35, 0x59, 0x46, 0x6A, 0x51, 0x49, 0x44, 0x41, ++ 0x51, 0x41, 0x42, 0x6F, 0x32, 0x4D, 0x77, 0x59, 0x54, 0x41, 0x66, 0x0A, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x53, 0x4D, 0x45, 0x47, 0x44, 0x41, 0x57, 0x67, 0x42, 0x54, 0x6A, 0x2F, 0x69, 0x33, 0x39, 0x4B, 0x4E, 0x41, 0x4C, 0x74, 0x62, 0x71, 0x32, ++ 0x6F, 0x73, 0x53, 0x2F, 0x42, 0x71, 0x6F, 0x46, 0x6A, 0x4A, 0x50, 0x37, 0x4C, 0x7A, 0x41, 0x50, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x52, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x54, 0x41, 0x44, 0x41, 0x51, 0x48, 0x2F, 0x4D, 0x41, 0x34, 0x47, ++ 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x0A, 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x42, 0x42, 0x6A, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x34, 0x2F, 0x34, 0x74, 0x2F, 0x53, 0x6A, ++ 0x51, 0x43, 0x37, 0x57, 0x36, 0x74, 0x71, 0x4C, 0x45, 0x76, 0x77, 0x61, 0x71, 0x42, 0x59, 0x79, 0x54, 0x2B, 0x79, 0x38, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x42, 0x51, 0x41, ++ 0x44, 0x67, 0x67, 0x49, 0x42, 0x0A, 0x41, 0x43, 0x58, 0x47, 0x75, 0x6D, 0x76, 0x72, 0x68, 0x38, 0x76, 0x65, 0x67, 0x6A, 0x6D, 0x57, 0x50, 0x66, 0x42, 0x45, 0x70, 0x32, 0x75, 0x45, 0x63, 0x77, 0x50, 0x65, 0x6E, 0x53, 0x74, 0x50, 0x75, 0x69, ++ 0x42, 0x2F, 0x76, 0x48, 0x69, 0x79, 0x7A, 0x35, 0x65, 0x77, 0x47, 0x35, 0x7A, 0x7A, 0x31, 0x33, 0x6B, 0x75, 0x39, 0x55, 0x69, 0x32, 0x30, 0x76, 0x73, 0x58, 0x69, 0x4F, 0x62, 0x54, 0x65, 0x6A, 0x2F, 0x74, 0x55, 0x78, 0x50, 0x51, 0x34, 0x69, ++ 0x39, 0x71, 0x0A, 0x65, 0x63, 0x73, 0x41, 0x49, 0x79, 0x6A, 0x6D, 0x48, 0x6A, 0x64, 0x58, 0x4E, 0x59, 0x6D, 0x45, 0x77, 0x6E, 0x5A, 0x50, 0x4E, 0x44, 0x61, 0x74, 0x5A, 0x38, 0x50, 0x4F, 0x51, 0x51, 0x61, 0x49, 0x78, 0x66, 0x66, 0x75, 0x32, ++ 0x42, 0x71, 0x34, 0x31, 0x67, 0x74, 0x2F, 0x55, 0x50, 0x2B, 0x54, 0x71, 0x68, 0x64, 0x4C, 0x6A, 0x4F, 0x7A, 0x74, 0x55, 0x6D, 0x43, 0x79, 0x70, 0x41, 0x62, 0x71, 0x54, 0x75, 0x76, 0x30, 0x61, 0x78, 0x6E, 0x39, 0x36, 0x2F, 0x55, 0x61, 0x0A, ++ 0x34, 0x43, 0x55, 0x71, 0x6D, 0x74, 0x7A, 0x48, 0x51, 0x54, 0x62, 0x33, 0x79, 0x48, 0x51, 0x46, 0x68, 0x44, 0x6D, 0x56, 0x4F, 0x64, 0x59, 0x4C, 0x4F, 0x36, 0x51, 0x6E, 0x2B, 0x67, 0x6A, 0x59, 0x58, 0x42, 0x37, 0x34, 0x42, 0x47, 0x42, 0x53, ++ 0x45, 0x53, 0x67, 0x6F, 0x41, 0x2F, 0x2F, 0x76, 0x55, 0x32, 0x59, 0x41, 0x70, 0x55, 0x6F, 0x30, 0x46, 0x6D, 0x5A, 0x38, 0x2F, 0x51, 0x6D, 0x6B, 0x72, 0x70, 0x35, 0x6E, 0x47, 0x6D, 0x39, 0x42, 0x43, 0x32, 0x73, 0x47, 0x0A, 0x45, 0x35, 0x75, ++ 0x50, 0x68, 0x6E, 0x45, 0x46, 0x74, 0x43, 0x2B, 0x4E, 0x69, 0x57, 0x59, 0x7A, 0x4B, 0x58, 0x5A, 0x55, 0x6D, 0x68, 0x48, 0x34, 0x4A, 0x2F, 0x71, 0x79, 0x50, 0x35, 0x48, 0x67, 0x7A, 0x67, 0x30, 0x62, 0x38, 0x7A, 0x41, 0x61, 0x72, 0x62, 0x38, ++ 0x69, 0x58, 0x52, 0x76, 0x54, 0x76, 0x79, 0x55, 0x46, 0x54, 0x65, 0x47, 0x53, 0x47, 0x6E, 0x2B, 0x5A, 0x6E, 0x7A, 0x78, 0x45, 0x6B, 0x38, 0x72, 0x55, 0x51, 0x45, 0x6C, 0x73, 0x67, 0x49, 0x66, 0x58, 0x0A, 0x42, 0x44, 0x72, 0x44, 0x4D, 0x6C, ++ 0x49, 0x31, 0x44, 0x6C, 0x62, 0x34, 0x70, 0x64, 0x31, 0x39, 0x78, 0x49, 0x73, 0x4E, 0x45, 0x52, 0x39, 0x54, 0x79, 0x78, 0x36, 0x79, 0x46, 0x37, 0x5A, 0x6F, 0x64, 0x31, 0x72, 0x67, 0x31, 0x4D, 0x76, 0x49, 0x42, 0x36, 0x37, 0x31, 0x4F, 0x69, ++ 0x36, 0x4F, 0x4E, 0x37, 0x66, 0x51, 0x41, 0x55, 0x74, 0x44, 0x4B, 0x58, 0x65, 0x4D, 0x4F, 0x5A, 0x65, 0x50, 0x67, 0x6C, 0x72, 0x34, 0x55, 0x65, 0x57, 0x4A, 0x6F, 0x42, 0x6A, 0x6E, 0x0A, 0x61, 0x48, 0x39, 0x64, 0x43, 0x69, 0x37, 0x37, 0x6F, ++ 0x30, 0x63, 0x4F, 0x50, 0x61, 0x59, 0x6A, 0x65, 0x73, 0x59, 0x42, 0x78, 0x34, 0x2F, 0x49, 0x58, 0x72, 0x39, 0x74, 0x67, 0x46, 0x61, 0x2B, 0x69, 0x69, 0x53, 0x36, 0x4D, 0x2B, 0x71, 0x66, 0x34, 0x54, 0x49, 0x52, 0x6E, 0x76, 0x48, 0x53, 0x54, ++ 0x34, 0x44, 0x32, 0x47, 0x30, 0x43, 0x76, 0x4F, 0x4A, 0x34, 0x52, 0x55, 0x48, 0x6C, 0x7A, 0x45, 0x68, 0x4C, 0x4E, 0x35, 0x6D, 0x79, 0x64, 0x4C, 0x49, 0x68, 0x79, 0x0A, 0x50, 0x44, 0x43, 0x42, 0x42, 0x70, 0x45, 0x69, 0x36, 0x6C, 0x6D, 0x74, ++ 0x32, 0x68, 0x6B, 0x75, 0x49, 0x73, 0x4B, 0x4E, 0x75, 0x59, 0x79, 0x48, 0x34, 0x47, 0x61, 0x38, 0x63, 0x79, 0x4E, 0x66, 0x49, 0x57, 0x52, 0x6A, 0x67, 0x45, 0x6A, 0x31, 0x6F, 0x44, 0x77, 0x59, 0x50, 0x5A, 0x54, 0x49, 0x53, 0x45, 0x45, 0x64, ++ 0x51, 0x4C, 0x70, 0x65, 0x2F, 0x76, 0x35, 0x57, 0x4F, 0x61, 0x48, 0x49, 0x7A, 0x31, 0x36, 0x65, 0x47, 0x57, 0x52, 0x47, 0x45, 0x4E, 0x6F, 0x58, 0x0A, 0x6B, 0x62, 0x63, 0x46, 0x67, 0x4B, 0x79, 0x4C, 0x6D, 0x5A, 0x4A, 0x39, 0x35, 0x36, 0x4C, ++ 0x59, 0x42, 0x77, 0x73, 0x32, 0x4A, 0x2B, 0x64, 0x49, 0x65, 0x57, 0x43, 0x4B, 0x77, 0x39, 0x63, 0x54, 0x58, 0x50, 0x68, 0x79, 0x51, 0x4E, 0x39, 0x4B, 0x79, 0x38, 0x2B, 0x5A, 0x41, 0x41, 0x6F, 0x41, 0x43, 0x78, 0x47, 0x56, 0x32, 0x6C, 0x5A, ++ 0x46, 0x41, 0x34, 0x67, 0x4B, 0x6E, 0x32, 0x66, 0x51, 0x31, 0x58, 0x6D, 0x78, 0x71, 0x49, 0x31, 0x41, 0x62, 0x51, 0x33, 0x43, 0x0A, 0x65, 0x6B, 0x44, 0x36, 0x38, 0x31, 0x39, 0x6B, 0x52, 0x35, 0x4C, 0x4C, 0x55, 0x37, 0x6D, 0x37, 0x57, 0x63, ++ 0x35, 0x50, 0x2F, 0x64, 0x41, 0x56, 0x55, 0x77, 0x48, 0x59, 0x33, 0x2B, 0x76, 0x5A, 0x35, 0x6E, 0x62, 0x76, 0x30, 0x43, 0x4F, 0x37, 0x4F, 0x36, 0x6C, 0x35, 0x73, 0x39, 0x55, 0x43, 0x4B, 0x63, 0x32, 0x4A, 0x6F, 0x35, 0x59, 0x50, 0x53, 0x6A, ++ 0x58, 0x6E, 0x54, 0x6B, 0x4C, 0x41, 0x64, 0x63, 0x30, 0x48, 0x7A, 0x2B, 0x59, 0x73, 0x36, 0x33, 0x73, 0x75, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, ++ 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x4F, 0x49, 0x53, 0x54, 0x45, 0x20, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x42, 0x20, 0x43, 0x41, 0x0A, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, ++ 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x44, 0x74, 0x54, 0x43, 0x43, 0x41, 0x70, 0x32, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x64, 0x72, ++ 0x45, 0x67, 0x55, 0x6E, 0x54, 0x77, 0x68, 0x59, 0x64, 0x47, 0x73, 0x2F, 0x67, 0x6A, 0x47, 0x76, 0x62, 0x43, 0x77, 0x44, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x44, ++ 0x42, 0x74, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x0A, 0x45, 0x77, 0x4A, 0x44, 0x53, 0x44, 0x45, 0x51, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x48, 0x56, 0x30, 0x6C, 0x54, 0x5A, ++ 0x55, 0x74, 0x6C, 0x65, 0x54, 0x45, 0x69, 0x4D, 0x43, 0x41, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x78, 0x4D, 0x5A, 0x54, 0x30, 0x6C, 0x54, 0x56, 0x45, 0x55, 0x67, 0x52, 0x6D, 0x39, 0x31, 0x62, 0x6D, 0x52, 0x68, 0x64, 0x47, 0x6C, 0x76, 0x62, ++ 0x69, 0x42, 0x46, 0x62, 0x6D, 0x52, 0x76, 0x63, 0x6E, 0x4E, 0x6C, 0x0A, 0x5A, 0x44, 0x45, 0x6F, 0x4D, 0x43, 0x59, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x66, 0x54, 0x30, 0x6C, 0x54, 0x56, 0x45, 0x55, 0x67, 0x56, 0x30, 0x6C, 0x54, ++ 0x5A, 0x55, 0x74, 0x6C, 0x65, 0x53, 0x42, 0x48, 0x62, 0x47, 0x39, 0x69, 0x59, 0x57, 0x77, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x48, 0x51, 0x69, 0x42, 0x44, 0x51, 0x54, 0x41, 0x65, 0x46, 0x77, 0x30, 0x78, 0x4E, 0x44, 0x45, 0x79, ++ 0x4D, 0x44, 0x45, 0x78, 0x4E, 0x54, 0x41, 0x77, 0x0A, 0x4D, 0x7A, 0x4A, 0x61, 0x46, 0x77, 0x30, 0x7A, 0x4F, 0x54, 0x45, 0x79, 0x4D, 0x44, 0x45, 0x78, 0x4E, 0x54, 0x45, 0x77, 0x4D, 0x7A, 0x46, 0x61, 0x4D, 0x47, 0x30, 0x78, 0x43, 0x7A, 0x41, ++ 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6B, 0x4E, 0x49, 0x4D, 0x52, 0x41, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x45, 0x77, 0x64, 0x58, 0x53, 0x56, 0x4E, 0x6C, 0x53, 0x32, 0x56, 0x35, 0x4D, 0x53, 0x49, ++ 0x77, 0x49, 0x41, 0x59, 0x44, 0x0A, 0x56, 0x51, 0x51, 0x4C, 0x45, 0x78, 0x6C, 0x50, 0x53, 0x56, 0x4E, 0x55, 0x52, 0x53, 0x42, 0x47, 0x62, 0x33, 0x56, 0x75, 0x5A, 0x47, 0x46, 0x30, 0x61, 0x57, 0x39, 0x75, 0x49, 0x45, 0x56, 0x75, 0x5A, 0x47, ++ 0x39, 0x79, 0x63, 0x32, 0x56, 0x6B, 0x4D, 0x53, 0x67, 0x77, 0x4A, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x39, 0x50, 0x53, 0x56, 0x4E, 0x55, 0x52, 0x53, 0x42, 0x58, 0x53, 0x56, 0x4E, 0x6C, 0x53, 0x32, 0x56, 0x35, 0x49, 0x45, ++ 0x64, 0x73, 0x0A, 0x62, 0x32, 0x4A, 0x68, 0x62, 0x43, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x64, 0x43, 0x49, 0x45, 0x4E, 0x42, 0x4D, 0x49, 0x49, 0x42, 0x49, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, ++ 0x77, 0x30, 0x42, 0x41, 0x51, 0x45, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x51, 0x38, 0x41, 0x4D, 0x49, 0x49, 0x42, 0x43, 0x67, 0x4B, 0x43, 0x41, 0x51, 0x45, 0x41, 0x32, 0x42, 0x65, 0x33, 0x48, 0x45, 0x6F, 0x6B, 0x4B, 0x74, 0x61, 0x58, 0x0A, ++ 0x73, 0x63, 0x72, 0x69, 0x48, 0x76, 0x74, 0x39, 0x4F, 0x4F, 0x2B, 0x59, 0x39, 0x62, 0x49, 0x35, 0x6D, 0x45, 0x34, 0x6E, 0x75, 0x42, 0x46, 0x64, 0x65, 0x39, 0x49, 0x6C, 0x6C, 0x49, 0x69, 0x43, 0x46, 0x53, 0x5A, 0x71, 0x47, 0x7A, 0x47, 0x37, ++ 0x71, 0x46, 0x73, 0x68, 0x49, 0x53, 0x76, 0x59, 0x44, 0x30, 0x36, 0x66, 0x57, 0x76, 0x47, 0x78, 0x57, 0x75, 0x52, 0x35, 0x31, 0x6A, 0x49, 0x6A, 0x4B, 0x2B, 0x46, 0x54, 0x7A, 0x4A, 0x6C, 0x46, 0x58, 0x48, 0x74, 0x50, 0x0A, 0x72, 0x62, 0x79, ++ 0x2F, 0x68, 0x30, 0x6F, 0x4C, 0x53, 0x35, 0x64, 0x61, 0x71, 0x50, 0x5A, 0x49, 0x37, 0x48, 0x31, 0x37, 0x44, 0x63, 0x30, 0x68, 0x42, 0x74, 0x2B, 0x65, 0x46, 0x66, 0x31, 0x42, 0x69, 0x6B, 0x69, 0x33, 0x49, 0x50, 0x53, 0x68, 0x65, 0x68, 0x74, ++ 0x58, 0x31, 0x46, 0x31, 0x51, 0x2F, 0x37, 0x70, 0x6E, 0x32, 0x43, 0x4F, 0x5A, 0x48, 0x38, 0x67, 0x2F, 0x34, 0x39, 0x37, 0x2F, 0x62, 0x31, 0x74, 0x33, 0x73, 0x57, 0x74, 0x75, 0x75, 0x4D, 0x6C, 0x6B, 0x0A, 0x39, 0x2B, 0x48, 0x4B, 0x51, 0x55, ++ 0x59, 0x4F, 0x4B, 0x58, 0x48, 0x51, 0x75, 0x53, 0x50, 0x38, 0x79, 0x59, 0x46, 0x66, 0x54, 0x76, 0x64, 0x76, 0x33, 0x37, 0x2B, 0x45, 0x72, 0x58, 0x4E, 0x6B, 0x75, 0x37, 0x64, 0x43, 0x6A, 0x6D, 0x6E, 0x32, 0x31, 0x48, 0x59, 0x64, 0x66, 0x70, ++ 0x32, 0x6E, 0x75, 0x46, 0x65, 0x4B, 0x55, 0x57, 0x64, 0x79, 0x31, 0x39, 0x53, 0x6F, 0x75, 0x4A, 0x56, 0x55, 0x51, 0x48, 0x4D, 0x44, 0x39, 0x75, 0x72, 0x30, 0x36, 0x2F, 0x34, 0x6F, 0x0A, 0x51, 0x6E, 0x63, 0x2F, 0x6E, 0x53, 0x4D, 0x62, 0x73, ++ 0x72, 0x59, 0x39, 0x67, 0x42, 0x51, 0x48, 0x54, 0x43, 0x35, 0x50, 0x39, 0x39, 0x55, 0x4B, 0x46, 0x67, 0x32, 0x39, 0x5A, 0x6B, 0x4D, 0x33, 0x66, 0x69, 0x4E, 0x44, 0x65, 0x63, 0x4E, 0x41, 0x68, 0x76, 0x56, 0x4D, 0x4B, 0x64, 0x71, 0x4F, 0x6D, ++ 0x71, 0x30, 0x4E, 0x70, 0x51, 0x53, 0x48, 0x69, 0x42, 0x36, 0x46, 0x34, 0x2B, 0x6C, 0x54, 0x31, 0x5A, 0x76, 0x49, 0x69, 0x77, 0x4E, 0x6A, 0x65, 0x4F, 0x76, 0x67, 0x0A, 0x47, 0x55, 0x70, 0x75, 0x75, 0x79, 0x39, 0x72, 0x4D, 0x32, 0x52, 0x59, ++ 0x6B, 0x36, 0x31, 0x70, 0x76, 0x34, 0x38, 0x62, 0x37, 0x34, 0x4A, 0x49, 0x78, 0x77, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x6F, 0x31, 0x45, 0x77, 0x54, 0x7A, 0x41, 0x4C, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x45, 0x42, 0x41, 0x4D, 0x43, ++ 0x41, 0x59, 0x59, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x0A, 0x2F, 0x7A, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, ++ 0x55, 0x4E, 0x51, 0x2F, 0x49, 0x4E, 0x6D, 0x4E, 0x65, 0x34, 0x71, 0x50, 0x73, 0x2B, 0x54, 0x74, 0x6D, 0x46, 0x63, 0x35, 0x52, 0x55, 0x75, 0x4F, 0x52, 0x6D, 0x6A, 0x30, 0x77, 0x45, 0x41, 0x59, 0x4A, 0x4B, 0x77, 0x59, 0x42, 0x42, 0x41, 0x47, ++ 0x43, 0x4E, 0x78, 0x55, 0x42, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x51, 0x41, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x0A, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x45, 0x42, 0x41, 0x45, ++ 0x42, 0x4D, 0x2B, 0x34, 0x65, 0x79, 0x6D, 0x59, 0x47, 0x51, 0x66, 0x70, 0x33, 0x46, 0x73, 0x4C, 0x41, 0x6D, 0x7A, 0x59, 0x68, 0x37, 0x4B, 0x7A, 0x4B, 0x4E, 0x62, 0x72, 0x67, 0x68, 0x63, 0x56, 0x69, 0x58, 0x66, 0x61, 0x34, 0x33, 0x46, 0x4B, ++ 0x38, 0x2B, 0x35, 0x2F, 0x65, 0x61, 0x34, 0x6E, 0x33, 0x32, 0x63, 0x5A, 0x69, 0x5A, 0x42, 0x4B, 0x70, 0x44, 0x0A, 0x64, 0x48, 0x69, 0x6A, 0x34, 0x30, 0x6C, 0x68, 0x50, 0x6E, 0x4F, 0x4D, 0x54, 0x5A, 0x54, 0x67, 0x2B, 0x58, 0x48, 0x45, 0x74, ++ 0x68, 0x59, 0x4F, 0x55, 0x33, 0x67, 0x66, 0x31, 0x71, 0x4B, 0x48, 0x4C, 0x77, 0x49, 0x35, 0x67, 0x53, 0x6B, 0x38, 0x72, 0x78, 0x57, 0x59, 0x49, 0x54, 0x44, 0x2B, 0x4B, 0x4A, 0x41, 0x41, 0x6A, 0x4E, 0x48, 0x68, 0x79, 0x2F, 0x70, 0x65, 0x79, ++ 0x50, 0x33, 0x34, 0x45, 0x45, 0x59, 0x37, 0x6F, 0x6E, 0x68, 0x43, 0x6B, 0x52, 0x64, 0x30, 0x0A, 0x56, 0x51, 0x72, 0x65, 0x55, 0x47, 0x64, 0x4E, 0x5A, 0x74, 0x47, 0x6E, 0x2F, 0x2F, 0x33, 0x5A, 0x77, 0x4C, 0x57, 0x6F, 0x6F, 0x34, 0x72, 0x4F, ++ 0x5A, 0x76, 0x55, 0x50, 0x51, 0x38, 0x32, 0x6E, 0x4B, 0x31, 0x64, 0x37, 0x59, 0x30, 0x5A, 0x71, 0x71, 0x69, 0x35, 0x53, 0x32, 0x50, 0x54, 0x74, 0x34, 0x57, 0x32, 0x74, 0x4B, 0x5A, 0x42, 0x34, 0x53, 0x4C, 0x72, 0x68, 0x49, 0x36, 0x71, 0x6A, ++ 0x69, 0x65, 0x79, 0x31, 0x71, 0x35, 0x62, 0x41, 0x74, 0x45, 0x75, 0x69, 0x0A, 0x48, 0x5A, 0x65, 0x65, 0x65, 0x76, 0x4A, 0x75, 0x51, 0x48, 0x48, 0x66, 0x61, 0x50, 0x46, 0x6C, 0x54, 0x63, 0x35, 0x38, 0x42, 0x64, 0x39, 0x54, 0x5A, 0x61, 0x6D, ++ 0x6C, 0x38, 0x4C, 0x47, 0x58, 0x42, 0x48, 0x41, 0x56, 0x52, 0x67, 0x4F, 0x59, 0x31, 0x4E, 0x4B, 0x2F, 0x56, 0x4C, 0x53, 0x67, 0x57, 0x48, 0x31, 0x53, 0x62, 0x39, 0x70, 0x57, 0x4A, 0x6D, 0x4C, 0x55, 0x32, 0x4E, 0x75, 0x4A, 0x4D, 0x57, 0x38, ++ 0x63, 0x38, 0x43, 0x4C, 0x43, 0x30, 0x32, 0x49, 0x63, 0x0A, 0x4E, 0x63, 0x31, 0x4D, 0x61, 0x52, 0x56, 0x55, 0x47, 0x70, 0x43, 0x59, 0x33, 0x75, 0x73, 0x65, 0x58, 0x38, 0x70, 0x33, 0x78, 0x38, 0x75, 0x4F, 0x50, 0x55, 0x4E, 0x70, 0x6E, 0x4A, ++ 0x70, 0x59, 0x30, 0x43, 0x51, 0x37, 0x33, 0x78, 0x74, 0x41, 0x6C, 0x6E, 0x34, 0x31, 0x72, 0x59, 0x48, 0x48, 0x54, 0x6E, 0x47, 0x36, 0x69, 0x42, 0x4D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, ++ 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x53, 0x5A, 0x41, 0x46, 0x49, 0x52, 0x20, 0x52, 0x4F, 0x4F, 0x54, 0x20, 0x43, 0x41, 0x32, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x44, 0x63, 0x6A, ++ 0x43, 0x43, 0x41, 0x6C, 0x71, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x55, 0x50, 0x6F, 0x70, 0x64, 0x42, 0x2B, 0x78, 0x56, 0x30, 0x6A, 0x4C, 0x56, 0x74, 0x2B, 0x4F, 0x32, 0x58, 0x77, 0x48, 0x72, 0x4C, 0x64, 0x7A, 0x6B, 0x31, 0x75, ++ 0x51, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x42, 0x51, 0x41, 0x77, 0x55, 0x54, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x0A, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x55, ++ 0x45, 0x77, 0x78, 0x4B, 0x44, 0x41, 0x6D, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x4D, 0x48, 0x30, 0x74, 0x79, 0x59, 0x57, 0x70, 0x76, 0x64, 0x32, 0x45, 0x67, 0x53, 0x58, 0x70, 0x69, 0x59, 0x53, 0x42, 0x53, 0x62, 0x33, 0x70, 0x73, 0x61, ++ 0x57, 0x4E, 0x36, 0x5A, 0x57, 0x35, 0x70, 0x62, 0x33, 0x64, 0x68, 0x49, 0x46, 0x4D, 0x75, 0x51, 0x53, 0x34, 0x78, 0x47, 0x44, 0x41, 0x57, 0x42, 0x67, 0x4E, 0x56, 0x0A, 0x42, 0x41, 0x4D, 0x4D, 0x44, 0x31, 0x4E, 0x61, 0x51, 0x55, 0x5A, 0x4A, ++ 0x55, 0x69, 0x42, 0x53, 0x54, 0x30, 0x39, 0x55, 0x49, 0x45, 0x4E, 0x42, 0x4D, 0x6A, 0x41, 0x65, 0x46, 0x77, 0x30, 0x78, 0x4E, 0x54, 0x45, 0x77, 0x4D, 0x54, 0x6B, 0x77, 0x4E, 0x7A, 0x51, 0x7A, 0x4D, 0x7A, 0x42, 0x61, 0x46, 0x77, 0x30, 0x7A, ++ 0x4E, 0x54, 0x45, 0x77, 0x4D, 0x54, 0x6B, 0x77, 0x4E, 0x7A, 0x51, 0x7A, 0x4D, 0x7A, 0x42, 0x61, 0x4D, 0x46, 0x45, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x0A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6C, 0x42, 0x4D, 0x4D, 0x53, 0x67, ++ 0x77, 0x4A, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x44, 0x42, 0x39, 0x4C, 0x63, 0x6D, 0x46, 0x71, 0x62, 0x33, 0x64, 0x68, 0x49, 0x45, 0x6C, 0x36, 0x59, 0x6D, 0x45, 0x67, 0x55, 0x6D, 0x39, 0x36, 0x62, 0x47, 0x6C, 0x6A, 0x65, 0x6D, 0x56, ++ 0x75, 0x61, 0x57, 0x39, 0x33, 0x59, 0x53, 0x42, 0x54, 0x4C, 0x6B, 0x45, 0x75, 0x4D, 0x52, 0x67, 0x77, 0x46, 0x67, 0x59, 0x44, 0x0A, 0x56, 0x51, 0x51, 0x44, 0x44, 0x41, 0x39, 0x54, 0x57, 0x6B, 0x46, 0x47, 0x53, 0x56, 0x49, 0x67, 0x55, 0x6B, ++ 0x39, 0x50, 0x56, 0x43, 0x42, 0x44, 0x51, 0x54, 0x49, 0x77, 0x67, 0x67, 0x45, 0x69, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x42, 0x44, 0x77, ++ 0x41, 0x77, 0x67, 0x67, 0x45, 0x4B, 0x41, 0x6F, 0x49, 0x42, 0x41, 0x51, 0x43, 0x33, 0x76, 0x44, 0x35, 0x51, 0x0A, 0x71, 0x45, 0x76, 0x4E, 0x51, 0x4C, 0x58, 0x4F, 0x59, 0x65, 0x65, 0x57, 0x79, 0x72, 0x53, 0x68, 0x32, 0x67, 0x77, 0x69, 0x73, ++ 0x50, 0x71, 0x31, 0x65, 0x33, 0x59, 0x41, 0x64, 0x34, 0x77, 0x4C, 0x7A, 0x33, 0x32, 0x6F, 0x68, 0x73, 0x77, 0x6D, 0x55, 0x65, 0x51, 0x67, 0x50, 0x59, 0x55, 0x4D, 0x31, 0x6C, 0x6A, 0x6A, 0x35, 0x2F, 0x51, 0x71, 0x47, 0x4A, 0x33, 0x61, 0x30, ++ 0x61, 0x34, 0x6D, 0x37, 0x75, 0x74, 0x54, 0x33, 0x50, 0x53, 0x51, 0x31, 0x68, 0x4E, 0x4B, 0x0A, 0x44, 0x4A, 0x41, 0x38, 0x77, 0x2F, 0x54, 0x61, 0x30, 0x6F, 0x34, 0x4E, 0x6B, 0x6A, 0x72, 0x63, 0x73, 0x62, 0x48, 0x2F, 0x4F, 0x4E, 0x37, 0x44, ++ 0x75, 0x69, 0x31, 0x66, 0x67, 0x4C, 0x6B, 0x43, 0x76, 0x55, 0x71, 0x64, 0x47, 0x77, 0x2B, 0x30, 0x77, 0x38, 0x4C, 0x42, 0x5A, 0x77, 0x50, 0x64, 0x33, 0x42, 0x75, 0x63, 0x50, 0x62, 0x4F, 0x77, 0x33, 0x67, 0x41, 0x65, 0x71, 0x44, 0x52, 0x48, ++ 0x75, 0x35, 0x72, 0x72, 0x2F, 0x67, 0x73, 0x55, 0x76, 0x54, 0x61, 0x45, 0x0A, 0x32, 0x67, 0x30, 0x67, 0x76, 0x2F, 0x70, 0x62, 0x79, 0x36, 0x6B, 0x57, 0x49, 0x4B, 0x30, 0x35, 0x59, 0x4F, 0x34, 0x76, 0x64, 0x62, 0x62, 0x6E, 0x6C, 0x35, 0x7A, ++ 0x35, 0x50, 0x76, 0x31, 0x2B, 0x54, 0x57, 0x39, 0x4E, 0x4C, 0x2B, 0x2B, 0x49, 0x44, 0x57, 0x72, 0x36, 0x33, 0x66, 0x45, 0x39, 0x62, 0x69, 0x43, 0x6C, 0x6F, 0x42, 0x4B, 0x30, 0x54, 0x58, 0x43, 0x35, 0x7A, 0x74, 0x64, 0x79, 0x4F, 0x34, 0x6D, ++ 0x54, 0x70, 0x34, 0x43, 0x45, 0x48, 0x43, 0x64, 0x4A, 0x0A, 0x63, 0x6B, 0x6D, 0x31, 0x2F, 0x7A, 0x75, 0x56, 0x6E, 0x73, 0x48, 0x4D, 0x79, 0x41, 0x48, 0x73, 0x36, 0x41, 0x36, 0x4B, 0x43, 0x70, 0x62, 0x6E, 0x73, 0x36, 0x61, 0x48, 0x35, 0x64, ++ 0x62, 0x35, 0x42, 0x53, 0x73, 0x4E, 0x6C, 0x30, 0x42, 0x77, 0x50, 0x4C, 0x71, 0x73, 0x64, 0x56, 0x71, 0x63, 0x31, 0x55, 0x32, 0x64, 0x41, 0x67, 0x72, 0x53, 0x53, 0x35, 0x74, 0x6D, 0x53, 0x30, 0x59, 0x48, 0x46, 0x32, 0x57, 0x74, 0x6E, 0x32, ++ 0x79, 0x49, 0x41, 0x4E, 0x77, 0x69, 0x0A, 0x69, 0x65, 0x44, 0x68, 0x5A, 0x4E, 0x52, 0x6E, 0x76, 0x44, 0x46, 0x35, 0x59, 0x54, 0x79, 0x37, 0x79, 0x6B, 0x48, 0x4E, 0x58, 0x47, 0x6F, 0x41, 0x79, 0x44, 0x77, 0x34, 0x6A, 0x6C, 0x69, 0x76, 0x41, ++ 0x67, 0x4D, 0x42, 0x41, 0x41, 0x47, 0x6A, 0x51, 0x6A, 0x42, 0x41, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, ++ 0x52, 0x30, 0x50, 0x0A, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x51, 0x44, 0x41, 0x67, 0x45, 0x47, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x51, 0x75, 0x46, 0x71, 0x6C, 0x4B, 0x47, 0x4C, 0x58, 0x4C, ++ 0x7A, 0x50, 0x56, 0x76, 0x55, 0x50, 0x4D, 0x6A, 0x58, 0x2F, 0x68, 0x64, 0x35, 0x36, 0x7A, 0x77, 0x79, 0x44, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x41, 0x4F, 0x43, ++ 0x0A, 0x41, 0x51, 0x45, 0x41, 0x74, 0x58, 0x50, 0x34, 0x41, 0x39, 0x78, 0x5A, 0x57, 0x78, 0x31, 0x32, 0x36, 0x61, 0x4D, 0x71, 0x65, 0x35, 0x41, 0x6F, 0x73, 0x6B, 0x33, 0x41, 0x4D, 0x30, 0x2B, 0x71, 0x6D, 0x72, 0x48, 0x55, 0x75, 0x4F, 0x51, ++ 0x6E, 0x2F, 0x36, 0x6D, 0x57, 0x6D, 0x63, 0x35, 0x47, 0x34, 0x47, 0x31, 0x38, 0x54, 0x4B, 0x49, 0x34, 0x70, 0x41, 0x5A, 0x77, 0x38, 0x50, 0x52, 0x42, 0x45, 0x65, 0x77, 0x2F, 0x52, 0x34, 0x30, 0x2F, 0x63, 0x6F, 0x66, 0x35, 0x0A, 0x4F, 0x2F, ++ 0x32, 0x6B, 0x62, 0x79, 0x74, 0x54, 0x41, 0x4F, 0x44, 0x2F, 0x4F, 0x62, 0x6C, 0x71, 0x42, 0x77, 0x37, 0x72, 0x48, 0x52, 0x7A, 0x32, 0x6F, 0x6E, 0x4B, 0x51, 0x79, 0x34, 0x49, 0x39, 0x45, 0x59, 0x4B, 0x4C, 0x30, 0x72, 0x75, 0x66, 0x4B, 0x71, ++ 0x38, 0x68, 0x35, 0x6D, 0x4F, 0x47, 0x6E, 0x58, 0x6B, 0x5A, 0x37, 0x2F, 0x65, 0x37, 0x44, 0x44, 0x57, 0x51, 0x77, 0x34, 0x72, 0x74, 0x54, 0x77, 0x2F, 0x31, 0x7A, 0x42, 0x4C, 0x5A, 0x70, 0x44, 0x36, 0x37, 0x0A, 0x6F, 0x50, 0x77, 0x67, 0x6C, ++ 0x56, 0x39, 0x50, 0x4A, 0x69, 0x38, 0x52, 0x49, 0x34, 0x4E, 0x4F, 0x64, 0x51, 0x63, 0x50, 0x76, 0x35, 0x76, 0x52, 0x74, 0x42, 0x33, 0x70, 0x45, 0x41, 0x54, 0x2B, 0x79, 0x6D, 0x43, 0x50, 0x6F, 0x6B, 0x79, 0x34, 0x72, 0x63, 0x2F, 0x68, 0x6B, ++ 0x41, 0x2F, 0x4E, 0x72, 0x67, 0x72, 0x48, 0x58, 0x58, 0x75, 0x33, 0x55, 0x4E, 0x4C, 0x55, 0x59, 0x66, 0x72, 0x56, 0x46, 0x64, 0x76, 0x58, 0x6E, 0x34, 0x64, 0x52, 0x56, 0x4F, 0x75, 0x6C, 0x0A, 0x34, 0x2B, 0x76, 0x4A, 0x68, 0x61, 0x41, 0x6C, ++ 0x49, 0x44, 0x66, 0x37, 0x6A, 0x73, 0x34, 0x4D, 0x4E, 0x49, 0x54, 0x68, 0x50, 0x49, 0x47, 0x79, 0x64, 0x30, 0x35, 0x44, 0x70, 0x59, 0x68, 0x66, 0x68, 0x6D, 0x65, 0x68, 0x50, 0x65, 0x61, 0x30, 0x58, 0x47, 0x47, 0x32, 0x50, 0x74, 0x76, 0x2B, ++ 0x74, 0x79, 0x6A, 0x46, 0x6F, 0x67, 0x65, 0x75, 0x74, 0x63, 0x72, 0x4B, 0x6A, 0x53, 0x6F, 0x53, 0x37, 0x35, 0x66, 0x74, 0x77, 0x6A, 0x43, 0x6B, 0x79, 0x53, 0x70, 0x36, 0x0A, 0x2B, 0x2F, 0x4E, 0x4E, 0x49, 0x78, 0x75, 0x5A, 0x4D, 0x7A, 0x53, ++ 0x67, 0x4C, 0x76, 0x57, 0x70, 0x43, 0x7A, 0x2F, 0x55, 0x58, 0x65, 0x48, 0x50, 0x68, 0x4A, 0x2F, 0x69, 0x47, 0x63, 0x4A, 0x66, 0x69, 0x74, 0x59, 0x67, 0x48, 0x75, 0x4E, 0x7A, 0x74, 0x77, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, ++ 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x4E, 0x65, 0x74, 0x77, ++ 0x6F, 0x72, 0x6B, 0x20, 0x43, 0x41, 0x20, 0x32, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, ++ 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x30, 0x6A, 0x43, 0x43, 0x41, 0x37, 0x71, 0x67, 0x41, 0x77, 0x49, ++ 0x42, 0x41, 0x67, 0x49, 0x51, 0x49, 0x64, 0x62, 0x51, 0x53, 0x6B, 0x38, 0x6C, 0x44, 0x38, 0x6B, 0x79, 0x4E, 0x2F, 0x79, 0x71, 0x58, 0x68, 0x4B, 0x4E, 0x36, 0x54, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, ++ 0x42, 0x41, 0x51, 0x30, 0x46, 0x41, 0x44, 0x43, 0x42, 0x67, 0x44, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x0A, 0x42, 0x68, 0x4D, 0x43, 0x55, 0x45, 0x77, 0x78, 0x49, 0x6A, 0x41, 0x67, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, ++ 0x6F, 0x54, 0x47, 0x56, 0x56, 0x75, 0x61, 0x58, 0x70, 0x6C, 0x64, 0x47, 0x38, 0x67, 0x56, 0x47, 0x56, 0x6A, 0x61, 0x47, 0x35, 0x76, 0x62, 0x47, 0x39, 0x6E, 0x61, 0x57, 0x56, 0x7A, 0x49, 0x46, 0x4D, 0x75, 0x51, 0x53, 0x34, 0x78, 0x4A, 0x7A, ++ 0x41, 0x6C, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x73, 0x54, 0x48, 0x6B, 0x4E, 0x6C, 0x63, 0x6E, 0x52, 0x31, 0x0A, 0x62, 0x53, 0x42, 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x61, 0x57, 0x5A, 0x70, 0x59, 0x32, 0x46, 0x30, 0x61, 0x57, 0x39, 0x75, 0x49, ++ 0x45, 0x46, 0x31, 0x64, 0x47, 0x68, 0x76, 0x63, 0x6D, 0x6C, 0x30, 0x65, 0x54, 0x45, 0x6B, 0x4D, 0x43, 0x49, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x62, 0x51, 0x32, 0x56, 0x79, 0x64, 0x48, 0x56, 0x74, 0x49, 0x46, 0x52, 0x79, 0x64, ++ 0x58, 0x4E, 0x30, 0x5A, 0x57, 0x51, 0x67, 0x54, 0x6D, 0x56, 0x30, 0x64, 0x32, 0x39, 0x79, 0x0A, 0x61, 0x79, 0x42, 0x44, 0x51, 0x53, 0x41, 0x79, 0x4D, 0x43, 0x49, 0x59, 0x44, 0x7A, 0x49, 0x77, 0x4D, 0x54, 0x45, 0x78, 0x4D, 0x44, 0x41, 0x32, ++ 0x4D, 0x44, 0x67, 0x7A, 0x4F, 0x54, 0x55, 0x32, 0x57, 0x68, 0x67, 0x50, 0x4D, 0x6A, 0x41, 0x30, 0x4E, 0x6A, 0x45, 0x77, 0x4D, 0x44, 0x59, 0x77, 0x4F, 0x44, 0x4D, 0x35, 0x4E, 0x54, 0x5A, 0x61, 0x4D, 0x49, 0x47, 0x41, 0x4D, 0x51, 0x73, 0x77, ++ 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x51, 0x0A, 0x54, 0x44, 0x45, 0x69, 0x4D, 0x43, 0x41, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x5A, 0x56, 0x57, 0x35, 0x70, 0x65, 0x6D, 0x56, 0x30, 0x62, 0x79, 0x42, ++ 0x55, 0x5A, 0x57, 0x4E, 0x6F, 0x62, 0x6D, 0x39, 0x73, 0x62, 0x32, 0x64, 0x70, 0x5A, 0x58, 0x4D, 0x67, 0x55, 0x79, 0x35, 0x42, 0x4C, 0x6A, 0x45, 0x6E, 0x4D, 0x43, 0x55, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x78, 0x4D, 0x65, 0x51, 0x32, 0x56, ++ 0x79, 0x64, 0x48, 0x56, 0x74, 0x49, 0x45, 0x4E, 0x6C, 0x0A, 0x63, 0x6E, 0x52, 0x70, 0x5A, 0x6D, 0x6C, 0x6A, 0x59, 0x58, 0x52, 0x70, 0x62, 0x32, 0x34, 0x67, 0x51, 0x58, 0x56, 0x30, 0x61, 0x47, 0x39, 0x79, 0x61, 0x58, 0x52, 0x35, 0x4D, 0x53, ++ 0x51, 0x77, 0x49, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x74, 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x64, 0x57, 0x30, 0x67, 0x56, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x52, 0x6C, 0x5A, 0x43, 0x42, 0x4F, 0x5A, 0x58, 0x52, 0x33, 0x62, 0x33, ++ 0x4A, 0x72, 0x49, 0x45, 0x4E, 0x42, 0x0A, 0x49, 0x44, 0x49, 0x77, 0x67, 0x67, 0x49, 0x69, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x44, ++ 0x77, 0x41, 0x77, 0x67, 0x67, 0x49, 0x4B, 0x41, 0x6F, 0x49, 0x43, 0x41, 0x51, 0x43, 0x39, 0x2B, 0x58, 0x6A, 0x34, 0x35, 0x74, 0x57, 0x41, 0x44, 0x47, 0x53, 0x64, 0x68, 0x68, 0x75, 0x57, 0x5A, 0x47, 0x63, 0x2F, 0x49, 0x6A, 0x6F, 0x65, 0x64, ++ 0x51, 0x46, 0x39, 0x0A, 0x37, 0x2F, 0x74, 0x63, 0x5A, 0x34, 0x7A, 0x4A, 0x7A, 0x46, 0x78, 0x72, 0x71, 0x5A, 0x48, 0x6D, 0x75, 0x55, 0x4C, 0x6C, 0x49, 0x45, 0x75, 0x62, 0x32, 0x70, 0x74, 0x37, 0x75, 0x5A, 0x6C, 0x64, 0x32, 0x5A, 0x75, 0x41, ++ 0x53, 0x39, 0x65, 0x45, 0x51, 0x43, 0x73, 0x6E, 0x30, 0x2B, 0x69, 0x36, 0x4D, 0x4C, 0x73, 0x2B, 0x43, 0x52, 0x71, 0x6E, 0x53, 0x5A, 0x58, 0x76, 0x4B, 0x30, 0x41, 0x6B, 0x77, 0x70, 0x66, 0x48, 0x70, 0x2B, 0x36, 0x62, 0x4A, 0x65, 0x2B, 0x6F, ++ 0x0A, 0x43, 0x67, 0x43, 0x58, 0x68, 0x56, 0x71, 0x71, 0x6E, 0x64, 0x77, 0x70, 0x79, 0x65, 0x49, 0x31, 0x42, 0x2B, 0x74, 0x77, 0x54, 0x55, 0x72, 0x57, 0x77, 0x62, 0x4E, 0x57, 0x75, 0x4B, 0x46, 0x42, 0x4F, 0x4A, 0x76, 0x52, 0x2B, 0x7A, 0x46, ++ 0x2F, 0x6A, 0x2B, 0x42, 0x66, 0x34, 0x62, 0x45, 0x2F, 0x44, 0x34, 0x34, 0x57, 0x53, 0x57, 0x44, 0x58, 0x42, 0x6F, 0x30, 0x59, 0x2B, 0x61, 0x6F, 0x6D, 0x45, 0x4B, 0x73, 0x71, 0x30, 0x39, 0x44, 0x52, 0x5A, 0x34, 0x30, 0x62, 0x0A, 0x52, 0x72, ++ 0x35, 0x48, 0x4D, 0x4E, 0x55, 0x75, 0x63, 0x74, 0x48, 0x46, 0x59, 0x39, 0x72, 0x6E, 0x59, 0x33, 0x6C, 0x45, 0x66, 0x6B, 0x74, 0x6A, 0x4A, 0x49, 0x6D, 0x47, 0x4C, 0x6A, 0x51, 0x2F, 0x4B, 0x55, 0x78, 0x53, 0x69, 0x79, 0x71, 0x6E, 0x77, 0x4F, ++ 0x4B, 0x52, 0x4B, 0x49, 0x6D, 0x35, 0x77, 0x46, 0x76, 0x35, 0x48, 0x64, 0x6E, 0x6E, 0x4A, 0x36, 0x33, 0x2F, 0x6D, 0x67, 0x4B, 0x58, 0x77, 0x63, 0x5A, 0x51, 0x6B, 0x70, 0x73, 0x43, 0x4C, 0x4C, 0x32, 0x70, 0x0A, 0x75, 0x54, 0x52, 0x5A, 0x43, ++ 0x72, 0x2B, 0x45, 0x53, 0x76, 0x2F, 0x66, 0x2F, 0x72, 0x4F, 0x66, 0x36, 0x39, 0x6D, 0x65, 0x34, 0x4A, 0x67, 0x6A, 0x37, 0x4B, 0x5A, 0x72, 0x64, 0x78, 0x59, 0x71, 0x32, 0x38, 0x79, 0x74, 0x4F, 0x78, 0x79, 0x6B, 0x68, 0x39, 0x78, 0x47, 0x63, ++ 0x31, 0x34, 0x5A, 0x59, 0x6D, 0x68, 0x46, 0x56, 0x2B, 0x53, 0x51, 0x67, 0x6B, 0x4B, 0x37, 0x51, 0x74, 0x62, 0x77, 0x59, 0x65, 0x44, 0x42, 0x6F, 0x7A, 0x31, 0x6D, 0x6F, 0x31, 0x33, 0x30, 0x0A, 0x47, 0x4F, 0x36, 0x49, 0x79, 0x59, 0x30, 0x58, ++ 0x52, 0x53, 0x6D, 0x5A, 0x4D, 0x6E, 0x55, 0x43, 0x4D, 0x65, 0x34, 0x70, 0x4A, 0x73, 0x68, 0x72, 0x41, 0x75, 0x61, 0x31, 0x59, 0x6B, 0x56, 0x2F, 0x4E, 0x78, 0x56, 0x61, 0x49, 0x32, 0x69, 0x4A, 0x31, 0x44, 0x37, 0x65, 0x54, 0x69, 0x65, 0x77, ++ 0x38, 0x45, 0x41, 0x4D, 0x76, 0x45, 0x30, 0x58, 0x79, 0x30, 0x32, 0x69, 0x73, 0x78, 0x37, 0x51, 0x42, 0x6C, 0x72, 0x64, 0x39, 0x70, 0x50, 0x50, 0x56, 0x33, 0x57, 0x5A, 0x0A, 0x39, 0x66, 0x71, 0x47, 0x47, 0x6D, 0x64, 0x34, 0x73, 0x37, 0x2B, ++ 0x57, 0x2F, 0x6A, 0x54, 0x63, 0x76, 0x65, 0x64, 0x53, 0x56, 0x75, 0x57, 0x7A, 0x35, 0x58, 0x56, 0x37, 0x31, 0x30, 0x47, 0x52, 0x42, 0x64, 0x78, 0x64, 0x61, 0x65, 0x4F, 0x56, 0x44, 0x55, 0x4F, 0x35, 0x2F, 0x49, 0x4F, 0x57, 0x4F, 0x5A, 0x56, ++ 0x37, 0x62, 0x49, 0x42, 0x61, 0x54, 0x78, 0x4E, 0x79, 0x78, 0x74, 0x64, 0x39, 0x4B, 0x58, 0x70, 0x45, 0x75, 0x6C, 0x4B, 0x6B, 0x4B, 0x74, 0x56, 0x42, 0x0A, 0x52, 0x67, 0x6B, 0x67, 0x2F, 0x69, 0x4B, 0x67, 0x74, 0x6C, 0x73, 0x77, 0x6A, 0x62, ++ 0x79, 0x4A, 0x44, 0x4E, 0x58, 0x58, 0x63, 0x50, 0x69, 0x48, 0x55, 0x76, 0x33, 0x61, 0x37, 0x36, 0x78, 0x52, 0x4C, 0x67, 0x65, 0x7A, 0x54, 0x76, 0x37, 0x51, 0x43, 0x64, 0x70, 0x77, 0x37, 0x35, 0x6A, 0x36, 0x56, 0x75, 0x5A, 0x74, 0x32, 0x37, ++ 0x56, 0x58, 0x53, 0x39, 0x7A, 0x6C, 0x4C, 0x43, 0x55, 0x56, 0x79, 0x4A, 0x34, 0x75, 0x65, 0x45, 0x37, 0x34, 0x32, 0x70, 0x79, 0x65, 0x0A, 0x68, 0x69, 0x7A, 0x4B, 0x56, 0x2F, 0x4D, 0x61, 0x35, 0x63, 0x69, 0x53, 0x69, 0x78, 0x71, 0x43, 0x6C, ++ 0x6E, 0x72, 0x44, 0x76, 0x46, 0x41, 0x53, 0x61, 0x64, 0x67, 0x4F, 0x57, 0x6B, 0x61, 0x4C, 0x4F, 0x75, 0x73, 0x6D, 0x2B, 0x69, 0x50, 0x4A, 0x74, 0x72, 0x43, 0x42, 0x76, 0x6B, 0x49, 0x41, 0x70, 0x50, 0x6A, 0x57, 0x2F, 0x6A, 0x41, 0x75, 0x78, ++ 0x39, 0x4A, 0x47, 0x39, 0x75, 0x57, 0x4F, 0x64, 0x66, 0x33, 0x79, 0x7A, 0x4C, 0x6E, 0x51, 0x68, 0x31, 0x76, 0x4D, 0x0A, 0x42, 0x68, 0x42, 0x67, 0x75, 0x34, 0x4D, 0x31, 0x74, 0x31, 0x35, 0x6E, 0x33, 0x6B, 0x66, 0x73, 0x6D, 0x55, 0x6A, 0x78, ++ 0x70, 0x4B, 0x45, 0x56, 0x2F, 0x71, 0x32, 0x4D, 0x59, 0x6F, 0x34, 0x35, 0x56, 0x55, 0x38, 0x35, 0x46, 0x72, 0x6D, 0x78, 0x59, 0x35, 0x33, 0x2F, 0x74, 0x77, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x6F, 0x30, 0x49, 0x77, 0x51, 0x44, 0x41, 0x50, ++ 0x42, 0x67, 0x4E, 0x56, 0x48, 0x52, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x54, 0x41, 0x44, 0x0A, 0x41, 0x51, 0x48, 0x2F, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x53, 0x32, 0x6F, 0x56, 0x51, ++ 0x35, 0x41, 0x73, 0x4F, 0x67, 0x50, 0x34, 0x36, 0x4B, 0x76, 0x50, 0x72, 0x55, 0x2B, 0x42, 0x79, 0x6D, 0x30, 0x54, 0x6F, 0x4F, 0x2F, 0x54, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x41, 0x4D, ++ 0x43, 0x41, 0x51, 0x59, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x0A, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4E, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x42, 0x41, 0x48, 0x47, 0x6C, 0x44, 0x73, 0x37, 0x6B, 0x36, 0x62, ++ 0x38, 0x2F, 0x4F, 0x4E, 0x57, 0x4A, 0x57, 0x73, 0x51, 0x43, 0x59, 0x66, 0x74, 0x4D, 0x78, 0x52, 0x51, 0x58, 0x4C, 0x59, 0x74, 0x50, 0x55, 0x32, 0x73, 0x51, 0x46, 0x2F, 0x78, 0x6C, 0x68, 0x4D, 0x63, 0x51, 0x53, 0x5A, 0x44, 0x65, 0x32, 0x38, ++ 0x63, 0x6D, 0x6B, 0x34, 0x67, 0x6D, 0x62, 0x33, 0x44, 0x57, 0x0A, 0x41, 0x6C, 0x34, 0x35, 0x6F, 0x50, 0x65, 0x50, 0x71, 0x35, 0x61, 0x31, 0x70, 0x52, 0x4E, 0x63, 0x67, 0x52, 0x52, 0x74, 0x44, 0x6F, 0x47, 0x43, 0x45, 0x52, 0x75, 0x4B, 0x54, ++ 0x73, 0x5A, 0x50, 0x70, 0x64, 0x31, 0x69, 0x48, 0x6B, 0x54, 0x66, 0x43, 0x56, 0x6E, 0x30, 0x57, 0x33, 0x63, 0x4C, 0x4E, 0x2B, 0x6D, 0x4C, 0x49, 0x4D, 0x62, 0x34, 0x43, 0x6B, 0x34, 0x75, 0x57, 0x42, 0x7A, 0x72, 0x4D, 0x39, 0x44, 0x50, 0x68, ++ 0x6D, 0x44, 0x4A, 0x32, 0x76, 0x75, 0x41, 0x0A, 0x4C, 0x35, 0x35, 0x4D, 0x59, 0x49, 0x52, 0x34, 0x50, 0x53, 0x46, 0x6B, 0x31, 0x76, 0x74, 0x42, 0x48, 0x78, 0x67, 0x50, 0x35, 0x38, 0x6C, 0x31, 0x63, 0x62, 0x32, 0x39, 0x58, 0x4E, 0x34, 0x30, ++ 0x68, 0x7A, 0x35, 0x42, 0x73, 0x41, 0x37, 0x32, 0x75, 0x64, 0x59, 0x2F, 0x43, 0x52, 0x4F, 0x57, 0x46, 0x43, 0x2F, 0x65, 0x6D, 0x68, 0x31, 0x61, 0x75, 0x56, 0x62, 0x4F, 0x4E, 0x54, 0x71, 0x77, 0x58, 0x33, 0x42, 0x4E, 0x58, 0x75, 0x4D, 0x70, ++ 0x38, 0x53, 0x4D, 0x6F, 0x0A, 0x63, 0x6C, 0x6D, 0x32, 0x71, 0x38, 0x4B, 0x4D, 0x5A, 0x69, 0x59, 0x63, 0x64, 0x79, 0x77, 0x6D, 0x64, 0x6A, 0x57, 0x4C, 0x4B, 0x4B, 0x64, 0x70, 0x6F, 0x50, 0x6B, 0x37, 0x39, 0x53, 0x50, 0x64, 0x68, 0x52, 0x42, ++ 0x30, 0x79, 0x5A, 0x41, 0x44, 0x56, 0x70, 0x48, 0x6E, 0x72, 0x37, 0x70, 0x48, 0x31, 0x42, 0x4B, 0x58, 0x45, 0x53, 0x4C, 0x6A, 0x6F, 0x6B, 0x6D, 0x55, 0x62, 0x4F, 0x65, 0x33, 0x6C, 0x45, 0x75, 0x36, 0x4C, 0x61, 0x54, 0x61, 0x4D, 0x34, 0x74, ++ 0x4D, 0x0A, 0x70, 0x6B, 0x54, 0x2F, 0x57, 0x6A, 0x7A, 0x47, 0x48, 0x57, 0x54, 0x59, 0x74, 0x54, 0x48, 0x6B, 0x70, 0x6A, 0x78, 0x36, 0x71, 0x46, 0x63, 0x4C, 0x32, 0x2B, 0x31, 0x68, 0x47, 0x73, 0x76, 0x78, 0x7A, 0x6E, 0x4E, 0x33, 0x59, 0x36, ++ 0x53, 0x48, 0x62, 0x30, 0x78, 0x52, 0x4F, 0x4E, 0x62, 0x6B, 0x58, 0x38, 0x65, 0x66, 0x74, 0x6F, 0x45, 0x71, 0x35, 0x49, 0x56, 0x49, 0x65, 0x56, 0x68, 0x65, 0x4F, 0x2F, 0x6A, 0x62, 0x41, 0x6F, 0x4A, 0x6E, 0x77, 0x54, 0x6E, 0x62, 0x0A, 0x77, ++ 0x33, 0x52, 0x4C, 0x50, 0x54, 0x59, 0x65, 0x2B, 0x53, 0x6D, 0x54, 0x69, 0x47, 0x68, 0x62, 0x71, 0x45, 0x51, 0x5A, 0x49, 0x66, 0x43, 0x6E, 0x36, 0x49, 0x45, 0x4E, 0x4C, 0x4F, 0x69, 0x54, 0x4E, 0x72, 0x51, 0x33, 0x73, 0x73, 0x71, 0x77, 0x47, ++ 0x79, 0x5A, 0x36, 0x6D, 0x69, 0x55, 0x66, 0x6D, 0x70, 0x71, 0x41, 0x6E, 0x6B, 0x73, 0x71, 0x50, 0x2F, 0x75, 0x6A, 0x6D, 0x76, 0x35, 0x7A, 0x4D, 0x6E, 0x48, 0x43, 0x6E, 0x73, 0x5A, 0x79, 0x34, 0x59, 0x70, 0x6F, 0x0A, 0x4A, 0x2F, 0x48, 0x6B, ++ 0x44, 0x37, 0x54, 0x45, 0x54, 0x4B, 0x56, 0x68, 0x6B, 0x2F, 0x69, 0x58, 0x45, 0x41, 0x63, 0x71, 0x4D, 0x43, 0x57, 0x70, 0x75, 0x63, 0x68, 0x78, 0x75, 0x4F, 0x39, 0x6F, 0x7A, 0x43, 0x31, 0x2B, 0x39, 0x65, 0x42, 0x2B, 0x44, 0x34, 0x4B, 0x6F, ++ 0x62, 0x37, 0x61, 0x36, 0x62, 0x49, 0x4E, 0x44, 0x64, 0x38, 0x32, 0x4B, 0x6B, 0x68, 0x65, 0x68, 0x6E, 0x6C, 0x74, 0x34, 0x46, 0x6A, 0x31, 0x46, 0x34, 0x6A, 0x4E, 0x79, 0x33, 0x65, 0x46, 0x6D, 0x0A, 0x79, 0x70, 0x6E, 0x54, 0x79, 0x63, 0x55, ++ 0x6D, 0x2F, 0x51, 0x31, 0x6F, 0x42, 0x45, 0x61, 0x75, 0x74, 0x74, 0x6D, 0x62, 0x6A, 0x4C, 0x34, 0x5A, 0x76, 0x72, 0x48, 0x47, 0x38, 0x68, 0x6E, 0x6A, 0x58, 0x41, 0x4C, 0x4B, 0x4C, 0x4E, 0x68, 0x76, 0x53, 0x67, 0x66, 0x5A, 0x79, 0x54, 0x58, ++ 0x61, 0x51, 0x48, 0x58, 0x79, 0x78, 0x4B, 0x63, 0x5A, 0x62, 0x35, 0x35, 0x43, 0x45, 0x4A, 0x68, 0x31, 0x35, 0x70, 0x57, 0x4C, 0x59, 0x4C, 0x7A, 0x74, 0x78, 0x52, 0x4C, 0x58, 0x0A, 0x69, 0x73, 0x37, 0x56, 0x6D, 0x46, 0x78, 0x57, 0x6C, 0x67, ++ 0x50, 0x46, 0x37, 0x6E, 0x63, 0x47, 0x4E, 0x66, 0x2F, 0x50, 0x35, 0x4F, 0x34, 0x2F, 0x45, 0x32, 0x48, 0x75, 0x32, 0x39, 0x6F, 0x74, 0x68, 0x66, 0x44, 0x4E, 0x72, 0x70, 0x32, 0x79, 0x47, 0x41, 0x6C, 0x46, 0x77, 0x35, 0x4B, 0x68, 0x63, 0x68, ++ 0x66, 0x38, 0x52, 0x37, 0x61, 0x67, 0x43, 0x79, 0x7A, 0x78, 0x78, 0x4E, 0x35, 0x44, 0x61, 0x41, 0x68, 0x71, 0x58, 0x7A, 0x76, 0x77, 0x64, 0x6D, 0x50, 0x37, 0x0A, 0x7A, 0x41, 0x59, 0x73, 0x70, 0x73, 0x62, 0x69, 0x44, 0x72, 0x57, 0x35, 0x76, ++ 0x69, 0x53, 0x50, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, 0x69, 0x63, 0x20, ++ 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x43, ++ 0x41, 0x20, 0x32, 0x30, 0x31, 0x35, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, ++ 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x47, 0x43, 0x7A, 0x43, 0x43, 0x41, 0x2F, 0x4F, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x42, 0x41, 0x44, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, ++ 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x44, 0x43, 0x42, 0x70, 0x6A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x52, 0x31, 0x49, 0x78, 0x44, 0x7A, 0x41, 0x4E, 0x42, ++ 0x67, 0x4E, 0x56, 0x42, 0x41, 0x63, 0x54, 0x0A, 0x42, 0x6B, 0x46, 0x30, 0x61, 0x47, 0x56, 0x75, 0x63, 0x7A, 0x46, 0x45, 0x4D, 0x45, 0x49, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x37, 0x53, 0x47, 0x56, 0x73, 0x62, 0x47, 0x56, 0x75, ++ 0x61, 0x57, 0x4D, 0x67, 0x51, 0x57, 0x4E, 0x68, 0x5A, 0x47, 0x56, 0x74, 0x61, 0x57, 0x4D, 0x67, 0x59, 0x57, 0x35, 0x6B, 0x49, 0x46, 0x4A, 0x6C, 0x63, 0x32, 0x56, 0x68, 0x63, 0x6D, 0x4E, 0x6F, 0x49, 0x45, 0x6C, 0x75, 0x63, 0x33, 0x52, 0x70, ++ 0x64, 0x48, 0x56, 0x30, 0x0A, 0x61, 0x57, 0x39, 0x75, 0x63, 0x79, 0x42, 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x4C, 0x69, 0x42, 0x42, 0x64, 0x58, 0x52, 0x6F, 0x62, 0x33, 0x4A, 0x70, 0x64, 0x48, 0x6B, 0x78, 0x51, 0x44, 0x41, 0x2B, 0x42, 0x67, 0x4E, ++ 0x56, 0x42, 0x41, 0x4D, 0x54, 0x4E, 0x30, 0x68, 0x6C, 0x62, 0x47, 0x78, 0x6C, 0x62, 0x6D, 0x6C, 0x6A, 0x49, 0x45, 0x46, 0x6A, 0x59, 0x57, 0x52, 0x6C, 0x62, 0x57, 0x6C, 0x6A, 0x49, 0x47, 0x46, 0x75, 0x5A, 0x43, 0x42, 0x53, 0x5A, 0x58, 0x4E, ++ 0x6C, 0x0A, 0x59, 0x58, 0x4A, 0x6A, 0x61, 0x43, 0x42, 0x4A, 0x62, 0x6E, 0x4E, 0x30, 0x61, 0x58, 0x52, 0x31, 0x64, 0x47, 0x6C, 0x76, 0x62, 0x6E, 0x4D, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x45, 0x4E, 0x42, 0x49, 0x44, 0x49, 0x77, 0x4D, 0x54, ++ 0x55, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x54, 0x55, 0x77, 0x4E, 0x7A, 0x41, 0x33, 0x4D, 0x54, 0x41, 0x78, 0x4D, 0x54, 0x49, 0x78, 0x57, 0x68, 0x63, 0x4E, 0x4E, 0x44, 0x41, 0x77, 0x4E, 0x6A, 0x4D, 0x77, 0x4D, 0x54, 0x41, 0x78, 0x0A, 0x4D, ++ 0x54, 0x49, 0x78, 0x57, 0x6A, 0x43, 0x42, 0x70, 0x6A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x52, 0x31, 0x49, 0x78, 0x44, 0x7A, 0x41, 0x4E, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x63, 0x54, 0x42, ++ 0x6B, 0x46, 0x30, 0x61, 0x47, 0x56, 0x75, 0x63, 0x7A, 0x46, 0x45, 0x4D, 0x45, 0x49, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x37, 0x53, 0x47, 0x56, 0x73, 0x62, 0x47, 0x56, 0x75, 0x61, 0x57, 0x4D, 0x67, 0x0A, 0x51, 0x57, 0x4E, 0x68, ++ 0x5A, 0x47, 0x56, 0x74, 0x61, 0x57, 0x4D, 0x67, 0x59, 0x57, 0x35, 0x6B, 0x49, 0x46, 0x4A, 0x6C, 0x63, 0x32, 0x56, 0x68, 0x63, 0x6D, 0x4E, 0x6F, 0x49, 0x45, 0x6C, 0x75, 0x63, 0x33, 0x52, 0x70, 0x64, 0x48, 0x56, 0x30, 0x61, 0x57, 0x39, 0x75, ++ 0x63, 0x79, 0x42, 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x4C, 0x69, 0x42, 0x42, 0x64, 0x58, 0x52, 0x6F, 0x62, 0x33, 0x4A, 0x70, 0x64, 0x48, 0x6B, 0x78, 0x51, 0x44, 0x41, 0x2B, 0x42, 0x67, 0x4E, 0x56, 0x0A, 0x42, 0x41, 0x4D, 0x54, 0x4E, 0x30, 0x68, ++ 0x6C, 0x62, 0x47, 0x78, 0x6C, 0x62, 0x6D, 0x6C, 0x6A, 0x49, 0x45, 0x46, 0x6A, 0x59, 0x57, 0x52, 0x6C, 0x62, 0x57, 0x6C, 0x6A, 0x49, 0x47, 0x46, 0x75, 0x5A, 0x43, 0x42, 0x53, 0x5A, 0x58, 0x4E, 0x6C, 0x59, 0x58, 0x4A, 0x6A, 0x61, 0x43, 0x42, ++ 0x4A, 0x62, 0x6E, 0x4E, 0x30, 0x61, 0x58, 0x52, 0x31, 0x64, 0x47, 0x6C, 0x76, 0x62, 0x6E, 0x4D, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x45, 0x4E, 0x42, 0x49, 0x44, 0x49, 0x77, 0x0A, 0x4D, 0x54, 0x55, 0x77, 0x67, 0x67, 0x49, 0x69, 0x4D, 0x41, ++ 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x49, 0x4B, 0x41, 0x6F, 0x49, 0x43, 0x41, 0x51, 0x44, 0x43, 0x2B, 0x4B, ++ 0x6B, 0x2F, 0x47, 0x34, 0x6E, 0x38, 0x50, 0x44, 0x77, 0x45, 0x58, 0x54, 0x32, 0x51, 0x4E, 0x72, 0x43, 0x52, 0x4F, 0x6E, 0x6B, 0x38, 0x5A, 0x6C, 0x72, 0x76, 0x0A, 0x62, 0x54, 0x6B, 0x42, 0x53, 0x52, 0x71, 0x30, 0x74, 0x38, 0x39, 0x2F, 0x54, ++ 0x53, 0x4E, 0x54, 0x74, 0x35, 0x41, 0x41, 0x34, 0x78, 0x4D, 0x71, 0x4B, 0x4B, 0x59, 0x78, 0x38, 0x5A, 0x45, 0x41, 0x34, 0x79, 0x6A, 0x73, 0x72, 0x69, 0x46, 0x42, 0x7A, 0x68, 0x2F, 0x61, 0x2F, 0x58, 0x30, 0x53, 0x57, 0x77, 0x47, 0x44, 0x44, ++ 0x37, 0x6D, 0x77, 0x58, 0x35, 0x6E, 0x68, 0x38, 0x68, 0x4B, 0x44, 0x67, 0x45, 0x30, 0x47, 0x50, 0x74, 0x2B, 0x73, 0x72, 0x2B, 0x65, 0x68, 0x0A, 0x69, 0x47, 0x73, 0x78, 0x72, 0x2F, 0x43, 0x4C, 0x30, 0x42, 0x67, 0x7A, 0x75, 0x4E, 0x74, 0x46, ++ 0x61, 0x6A, 0x54, 0x30, 0x41, 0x6F, 0x41, 0x6B, 0x4B, 0x41, 0x6F, 0x43, 0x46, 0x5A, 0x56, 0x65, 0x64, 0x69, 0x6F, 0x4E, 0x6D, 0x54, 0x6F, 0x55, 0x57, 0x2F, 0x62, 0x4C, 0x79, 0x31, 0x4F, 0x38, 0x45, 0x30, 0x30, 0x42, 0x69, 0x44, 0x65, 0x55, ++ 0x4A, 0x52, 0x74, 0x43, 0x76, 0x43, 0x4C, 0x59, 0x6A, 0x71, 0x4F, 0x57, 0x58, 0x6A, 0x72, 0x5A, 0x4D, 0x74, 0x73, 0x2B, 0x0A, 0x36, 0x50, 0x41, 0x51, 0x5A, 0x65, 0x31, 0x30, 0x34, 0x53, 0x2B, 0x6E, 0x66, 0x4B, 0x38, 0x6E, 0x4E, 0x4C, 0x73, ++ 0x70, 0x66, 0x5A, 0x75, 0x32, 0x7A, 0x77, 0x6E, 0x49, 0x35, 0x64, 0x4D, 0x4B, 0x2F, 0x49, 0x68, 0x6C, 0x5A, 0x58, 0x51, 0x4B, 0x33, 0x48, 0x4D, 0x63, 0x58, 0x4D, 0x31, 0x41, 0x73, 0x52, 0x7A, 0x55, 0x74, 0x6F, 0x53, 0x4D, 0x54, 0x46, 0x44, ++ 0x50, 0x61, 0x49, 0x36, 0x6F, 0x57, 0x61, 0x37, 0x43, 0x4A, 0x30, 0x36, 0x43, 0x6F, 0x6A, 0x58, 0x64, 0x0A, 0x46, 0x50, 0x51, 0x66, 0x2F, 0x37, 0x4A, 0x33, 0x31, 0x59, 0x63, 0x76, 0x71, 0x6D, 0x35, 0x39, 0x4A, 0x43, 0x66, 0x6E, 0x78, 0x73, ++ 0x73, 0x6D, 0x35, 0x75, 0x58, 0x2B, 0x5A, 0x77, 0x64, 0x6A, 0x32, 0x45, 0x55, 0x4E, 0x33, 0x54, 0x70, 0x5A, 0x5A, 0x54, 0x6C, 0x59, 0x65, 0x70, 0x4B, 0x5A, 0x63, 0x6A, 0x32, 0x63, 0x68, 0x46, 0x36, 0x49, 0x49, 0x62, 0x6A, 0x56, 0x39, 0x43, ++ 0x7A, 0x38, 0x32, 0x58, 0x42, 0x53, 0x54, 0x33, 0x69, 0x34, 0x76, 0x54, 0x77, 0x72, 0x0A, 0x69, 0x35, 0x57, 0x59, 0x39, 0x62, 0x50, 0x52, 0x61, 0x4D, 0x38, 0x67, 0x46, 0x48, 0x35, 0x4D, 0x58, 0x46, 0x2F, 0x6E, 0x69, 0x2B, 0x58, 0x31, 0x4E, ++ 0x59, 0x45, 0x5A, 0x4E, 0x39, 0x63, 0x52, 0x43, 0x4C, 0x64, 0x6D, 0x76, 0x74, 0x4E, 0x4B, 0x7A, 0x6F, 0x4E, 0x58, 0x41, 0x44, 0x72, 0x44, 0x67, 0x66, 0x67, 0x58, 0x79, 0x35, 0x49, 0x32, 0x58, 0x64, 0x47, 0x6A, 0x32, 0x48, 0x55, 0x62, 0x34, ++ 0x59, 0x73, 0x6E, 0x36, 0x6E, 0x70, 0x49, 0x51, 0x66, 0x31, 0x46, 0x0A, 0x47, 0x51, 0x61, 0x74, 0x4A, 0x35, 0x6C, 0x4F, 0x77, 0x58, 0x42, 0x48, 0x33, 0x62, 0x57, 0x66, 0x67, 0x56, 0x4D, 0x53, 0x35, 0x62, 0x47, 0x4D, 0x53, 0x46, 0x30, 0x78, ++ 0x51, 0x78, 0x66, 0x6A, 0x6A, 0x4D, 0x5A, 0x36, 0x59, 0x35, 0x5A, 0x4C, 0x4B, 0x54, 0x42, 0x4F, 0x68, 0x45, 0x35, 0x69, 0x47, 0x56, 0x34, 0x38, 0x7A, 0x70, 0x65, 0x51, 0x70, 0x58, 0x38, 0x42, 0x36, 0x35, 0x33, 0x67, 0x2B, 0x49, 0x75, 0x4A, ++ 0x33, 0x53, 0x57, 0x59, 0x50, 0x5A, 0x4B, 0x32, 0x0A, 0x66, 0x75, 0x2F, 0x5A, 0x38, 0x56, 0x46, 0x52, 0x66, 0x53, 0x30, 0x6D, 0x79, 0x47, 0x6C, 0x5A, 0x59, 0x65, 0x43, 0x73, 0x61, 0x72, 0x67, 0x71, 0x4E, 0x68, 0x45, 0x45, 0x65, 0x6C, 0x43, ++ 0x39, 0x4D, 0x6F, 0x53, 0x2B, 0x4C, 0x39, 0x78, 0x79, 0x31, 0x64, 0x63, 0x64, 0x46, 0x6B, 0x66, 0x6B, 0x52, 0x32, 0x59, 0x67, 0x50, 0x2F, 0x53, 0x57, 0x78, 0x61, 0x2B, 0x4F, 0x41, 0x58, 0x71, 0x6C, 0x44, 0x33, 0x70, 0x6B, 0x39, 0x51, 0x30, ++ 0x59, 0x68, 0x39, 0x6D, 0x75, 0x0A, 0x69, 0x4E, 0x58, 0x36, 0x68, 0x4D, 0x45, 0x36, 0x77, 0x47, 0x6B, 0x6F, 0x4C, 0x66, 0x49, 0x4E, 0x61, 0x46, 0x47, 0x71, 0x34, 0x36, 0x56, 0x33, 0x78, 0x71, 0x53, 0x51, 0x44, 0x71, 0x45, 0x33, 0x69, 0x7A, ++ 0x45, 0x6A, 0x52, 0x38, 0x45, 0x4A, 0x43, 0x4F, 0x74, 0x75, 0x39, 0x33, 0x69, 0x62, 0x31, 0x34, 0x4C, 0x38, 0x68, 0x43, 0x43, 0x5A, 0x53, 0x52, 0x6D, 0x32, 0x45, 0x6B, 0x61, 0x78, 0x2B, 0x30, 0x56, 0x56, 0x46, 0x71, 0x6D, 0x6A, 0x5A, 0x61, ++ 0x79, 0x63, 0x0A, 0x42, 0x77, 0x2F, 0x71, 0x61, 0x39, 0x77, 0x66, 0x4C, 0x67, 0x5A, 0x79, 0x37, 0x49, 0x61, 0x49, 0x45, 0x75, 0x51, 0x74, 0x32, 0x31, 0x38, 0x46, 0x4C, 0x2B, 0x54, 0x77, 0x41, 0x39, 0x4D, 0x6D, 0x4D, 0x2B, 0x65, 0x41, 0x77, ++ 0x73, 0x31, 0x43, 0x6F, 0x52, 0x63, 0x30, 0x43, 0x77, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x6F, 0x30, 0x49, 0x77, 0x51, 0x44, 0x41, 0x50, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x52, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x54, 0x41, 0x44, 0x0A, ++ 0x41, 0x51, 0x48, 0x2F, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x42, 0x42, 0x6A, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, ++ 0x63, 0x52, 0x56, 0x6E, 0x79, 0x4D, 0x6A, 0x4A, 0x76, 0x58, 0x56, 0x64, 0x63, 0x74, 0x41, 0x34, 0x47, 0x47, 0x71, 0x64, 0x38, 0x33, 0x45, 0x6B, 0x56, 0x41, 0x73, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x0A, 0x68, 0x76, 0x63, ++ 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x42, 0x41, 0x48, 0x57, 0x37, 0x62, 0x56, 0x52, 0x4C, 0x71, 0x68, 0x42, 0x59, 0x52, 0x6A, 0x54, 0x79, 0x59, 0x74, 0x63, 0x57, 0x4E, 0x6C, 0x30, 0x49, 0x58, 0x74, 0x56, ++ 0x73, 0x79, 0x49, 0x65, 0x39, 0x74, 0x43, 0x35, 0x47, 0x38, 0x6A, 0x48, 0x34, 0x66, 0x4F, 0x70, 0x43, 0x74, 0x5A, 0x4D, 0x57, 0x56, 0x64, 0x79, 0x68, 0x44, 0x42, 0x4B, 0x67, 0x32, 0x6D, 0x46, 0x2B, 0x0A, 0x44, 0x31, 0x68, 0x59, 0x63, 0x32, ++ 0x52, 0x79, 0x78, 0x2B, 0x68, 0x46, 0x6A, 0x74, 0x79, 0x70, 0x38, 0x69, 0x59, 0x2F, 0x78, 0x6E, 0x6D, 0x4D, 0x73, 0x56, 0x4D, 0x49, 0x4D, 0x34, 0x47, 0x77, 0x56, 0x68, 0x4F, 0x2B, 0x35, 0x6C, 0x46, 0x63, 0x32, 0x4A, 0x73, 0x4B, 0x54, 0x30, ++ 0x75, 0x63, 0x56, 0x6C, 0x4D, 0x43, 0x36, 0x55, 0x2F, 0x32, 0x44, 0x57, 0x44, 0x71, 0x54, 0x55, 0x4A, 0x56, 0x36, 0x48, 0x77, 0x62, 0x49, 0x53, 0x48, 0x54, 0x47, 0x7A, 0x72, 0x4D, 0x0A, 0x64, 0x2F, 0x4B, 0x34, 0x6B, 0x50, 0x46, 0x6F, 0x78, ++ 0x2F, 0x6C, 0x61, 0x2F, 0x76, 0x6F, 0x74, 0x39, 0x4C, 0x2F, 0x4A, 0x39, 0x55, 0x55, 0x62, 0x7A, 0x6A, 0x67, 0x51, 0x4B, 0x6A, 0x65, 0x4B, 0x65, 0x61, 0x4F, 0x30, 0x34, 0x77, 0x6C, 0x73, 0x68, 0x59, 0x61, 0x54, 0x2F, 0x34, 0x6D, 0x57, 0x4A, ++ 0x33, 0x69, 0x42, 0x6A, 0x32, 0x66, 0x6A, 0x52, 0x6E, 0x52, 0x55, 0x6A, 0x74, 0x6B, 0x4E, 0x61, 0x65, 0x4A, 0x4B, 0x39, 0x45, 0x31, 0x30, 0x41, 0x2F, 0x2B, 0x79, 0x0A, 0x64, 0x2B, 0x32, 0x56, 0x5A, 0x35, 0x66, 0x6B, 0x73, 0x63, 0x57, 0x72, ++ 0x76, 0x32, 0x6F, 0x6A, 0x36, 0x4E, 0x53, 0x55, 0x34, 0x6B, 0x51, 0x6F, 0x59, 0x73, 0x52, 0x4C, 0x34, 0x76, 0x44, 0x59, 0x34, 0x69, 0x6C, 0x72, 0x47, 0x6E, 0x42, 0x2B, 0x4A, 0x47, 0x47, 0x54, 0x65, 0x30, 0x38, 0x44, 0x4D, 0x69, 0x55, 0x4E, ++ 0x52, 0x53, 0x51, 0x72, 0x6C, 0x72, 0x52, 0x47, 0x61, 0x72, 0x39, 0x4B, 0x43, 0x2F, 0x65, 0x61, 0x6A, 0x38, 0x47, 0x73, 0x47, 0x73, 0x56, 0x6E, 0x0A, 0x38, 0x32, 0x38, 0x30, 0x30, 0x76, 0x70, 0x7A, 0x59, 0x34, 0x7A, 0x76, 0x46, 0x72, 0x43, ++ 0x6F, 0x70, 0x45, 0x59, 0x71, 0x2B, 0x4F, 0x73, 0x53, 0x37, 0x48, 0x4B, 0x30, 0x37, 0x2F, 0x67, 0x72, 0x66, 0x6F, 0x78, 0x53, 0x77, 0x49, 0x75, 0x45, 0x56, 0x50, 0x6B, 0x76, 0x50, 0x75, 0x4E, 0x56, 0x71, 0x4E, 0x78, 0x6D, 0x73, 0x64, 0x6E, ++ 0x68, 0x58, 0x39, 0x69, 0x7A, 0x6A, 0x46, 0x6B, 0x30, 0x57, 0x61, 0x53, 0x72, 0x54, 0x32, 0x79, 0x37, 0x48, 0x78, 0x6A, 0x62, 0x0A, 0x64, 0x61, 0x76, 0x59, 0x79, 0x35, 0x4C, 0x4E, 0x6C, 0x44, 0x68, 0x68, 0x44, 0x67, 0x63, 0x47, 0x48, 0x30, ++ 0x74, 0x47, 0x45, 0x50, 0x45, 0x56, 0x76, 0x6F, 0x32, 0x46, 0x58, 0x44, 0x74, 0x4B, 0x4B, 0x34, 0x46, 0x35, 0x44, 0x37, 0x52, 0x70, 0x6E, 0x30, 0x6C, 0x51, 0x6C, 0x30, 0x33, 0x33, 0x44, 0x6C, 0x5A, 0x64, 0x77, 0x4A, 0x56, 0x71, 0x77, 0x6A, ++ 0x62, 0x44, 0x47, 0x32, 0x6A, 0x4A, 0x39, 0x53, 0x72, 0x63, 0x52, 0x35, 0x71, 0x2B, 0x73, 0x73, 0x37, 0x46, 0x0A, 0x4A, 0x65, 0x6A, 0x36, 0x41, 0x37, 0x6E, 0x61, 0x2B, 0x52, 0x5A, 0x75, 0x6B, 0x59, 0x54, 0x31, 0x48, 0x43, 0x6A, 0x49, 0x2F, ++ 0x43, 0x62, 0x4D, 0x31, 0x78, 0x79, 0x51, 0x56, 0x71, 0x64, 0x66, 0x62, 0x7A, 0x6F, 0x45, 0x76, 0x4D, 0x31, 0x34, 0x69, 0x51, 0x75, 0x4F, 0x44, 0x79, 0x2B, 0x6A, 0x71, 0x6B, 0x2B, 0x69, 0x47, 0x78, 0x49, 0x39, 0x46, 0x67, 0x68, 0x41, 0x44, ++ 0x2F, 0x46, 0x47, 0x54, 0x4E, 0x65, 0x71, 0x65, 0x77, 0x6A, 0x42, 0x43, 0x76, 0x56, 0x74, 0x0A, 0x4A, 0x39, 0x34, 0x43, 0x6A, 0x38, 0x72, 0x44, 0x74, 0x53, 0x76, 0x4B, 0x36, 0x65, 0x76, 0x49, 0x49, 0x56, 0x4D, 0x34, 0x70, 0x63, 0x77, 0x37, ++ 0x32, 0x48, 0x63, 0x33, 0x4D, 0x4B, 0x4A, 0x50, 0x32, 0x57, 0x2F, 0x52, 0x38, 0x6B, 0x43, 0x74, 0x51, 0x58, 0x6F, 0x58, 0x78, 0x64, 0x5A, 0x4B, 0x4E, 0x59, 0x6D, 0x33, 0x51, 0x64, 0x56, 0x38, 0x68, 0x6E, 0x39, 0x56, 0x54, 0x59, 0x4E, 0x4B, ++ 0x70, 0x58, 0x4D, 0x67, 0x77, 0x44, 0x71, 0x76, 0x6B, 0x50, 0x47, 0x61, 0x0A, 0x4A, 0x49, 0x37, 0x5A, 0x6A, 0x6E, 0x48, 0x4B, 0x65, 0x37, 0x69, 0x47, 0x32, 0x72, 0x4B, 0x50, 0x6D, 0x54, 0x34, 0x64, 0x45, 0x77, 0x30, 0x53, 0x45, 0x65, 0x37, ++ 0x55, 0x71, 0x2F, 0x44, 0x70, 0x46, 0x58, 0x59, 0x43, 0x35, 0x4F, 0x44, 0x66, 0x71, 0x69, 0x41, 0x65, 0x57, 0x32, 0x47, 0x46, 0x5A, 0x45, 0x43, 0x70, 0x6B, 0x4A, 0x63, 0x4E, 0x72, 0x56, 0x50, 0x53, 0x57, 0x68, 0x32, 0x48, 0x61, 0x67, 0x43, ++ 0x58, 0x5A, 0x57, 0x4B, 0x30, 0x76, 0x6D, 0x39, 0x71, 0x0A, 0x70, 0x2F, 0x55, 0x73, 0x51, 0x75, 0x30, 0x79, 0x72, 0x62, 0x59, 0x68, 0x6E, 0x72, 0x36, 0x38, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, ++ 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, ++ 0x61, 0x72, 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, 0x35, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, ++ 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x43, 0x77, 0x7A, 0x43, 0x43, 0x41, 0x6B, 0x71, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x42, 0x41, 0x44, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x6A, ++ 0x43, 0x42, 0x71, 0x6A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x52, 0x31, 0x49, 0x78, 0x44, 0x7A, 0x41, 0x4E, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x63, 0x54, 0x42, 0x6B, 0x46, 0x30, 0x0A, 0x61, ++ 0x47, 0x56, 0x75, 0x63, 0x7A, 0x46, 0x45, 0x4D, 0x45, 0x49, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x37, 0x53, 0x47, 0x56, 0x73, 0x62, 0x47, 0x56, 0x75, 0x61, 0x57, 0x4D, 0x67, 0x51, 0x57, 0x4E, 0x68, 0x5A, 0x47, 0x56, 0x74, 0x61, ++ 0x57, 0x4D, 0x67, 0x59, 0x57, 0x35, 0x6B, 0x49, 0x46, 0x4A, 0x6C, 0x63, 0x32, 0x56, 0x68, 0x63, 0x6D, 0x4E, 0x6F, 0x49, 0x45, 0x6C, 0x75, 0x63, 0x33, 0x52, 0x70, 0x64, 0x48, 0x56, 0x30, 0x61, 0x57, 0x39, 0x75, 0x0A, 0x63, 0x79, 0x42, 0x44, ++ 0x5A, 0x58, 0x4A, 0x30, 0x4C, 0x69, 0x42, 0x42, 0x64, 0x58, 0x52, 0x6F, 0x62, 0x33, 0x4A, 0x70, 0x64, 0x48, 0x6B, 0x78, 0x52, 0x44, 0x42, 0x43, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x4F, 0x30, 0x68, 0x6C, 0x62, 0x47, 0x78, 0x6C, ++ 0x62, 0x6D, 0x6C, 0x6A, 0x49, 0x45, 0x46, 0x6A, 0x59, 0x57, 0x52, 0x6C, 0x62, 0x57, 0x6C, 0x6A, 0x49, 0x47, 0x46, 0x75, 0x5A, 0x43, 0x42, 0x53, 0x5A, 0x58, 0x4E, 0x6C, 0x59, 0x58, 0x4A, 0x6A, 0x0A, 0x61, 0x43, 0x42, 0x4A, 0x62, 0x6E, 0x4E, ++ 0x30, 0x61, 0x58, 0x52, 0x31, 0x64, 0x47, 0x6C, 0x76, 0x62, 0x6E, 0x4D, 0x67, 0x52, 0x55, 0x4E, 0x44, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x52, 0x44, 0x51, 0x53, 0x41, 0x79, 0x4D, 0x44, 0x45, 0x31, 0x4D, 0x42, 0x34, 0x58, 0x44, 0x54, 0x45, ++ 0x31, 0x4D, 0x44, 0x63, 0x77, 0x4E, 0x7A, 0x45, 0x77, 0x4D, 0x7A, 0x63, 0x78, 0x4D, 0x6C, 0x6F, 0x58, 0x44, 0x54, 0x51, 0x77, 0x4D, 0x44, 0x59, 0x7A, 0x4D, 0x44, 0x45, 0x77, 0x0A, 0x4D, 0x7A, 0x63, 0x78, 0x4D, 0x6C, 0x6F, 0x77, 0x67, 0x61, ++ 0x6F, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6B, 0x64, 0x53, 0x4D, 0x51, 0x38, 0x77, 0x44, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x48, 0x45, 0x77, 0x5A, 0x42, 0x64, 0x47, 0x68, 0x6C, 0x62, 0x6E, ++ 0x4D, 0x78, 0x52, 0x44, 0x42, 0x43, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x4F, 0x30, 0x68, 0x6C, 0x62, 0x47, 0x78, 0x6C, 0x62, 0x6D, 0x6C, 0x6A, 0x0A, 0x49, 0x45, 0x46, 0x6A, 0x59, 0x57, 0x52, 0x6C, 0x62, 0x57, 0x6C, 0x6A, 0x49, ++ 0x47, 0x46, 0x75, 0x5A, 0x43, 0x42, 0x53, 0x5A, 0x58, 0x4E, 0x6C, 0x59, 0x58, 0x4A, 0x6A, 0x61, 0x43, 0x42, 0x4A, 0x62, 0x6E, 0x4E, 0x30, 0x61, 0x58, 0x52, 0x31, 0x64, 0x47, 0x6C, 0x76, 0x62, 0x6E, 0x4D, 0x67, 0x51, 0x32, 0x56, 0x79, 0x64, ++ 0x43, 0x34, 0x67, 0x51, 0x58, 0x56, 0x30, 0x61, 0x47, 0x39, 0x79, 0x61, 0x58, 0x52, 0x35, 0x4D, 0x55, 0x51, 0x77, 0x51, 0x67, 0x59, 0x44, 0x0A, 0x56, 0x51, 0x51, 0x44, 0x45, 0x7A, 0x74, 0x49, 0x5A, 0x57, 0x78, 0x73, 0x5A, 0x57, 0x35, 0x70, ++ 0x59, 0x79, 0x42, 0x42, 0x59, 0x32, 0x46, 0x6B, 0x5A, 0x57, 0x31, 0x70, 0x59, 0x79, 0x42, 0x68, 0x62, 0x6D, 0x51, 0x67, 0x55, 0x6D, 0x56, 0x7A, 0x5A, 0x57, 0x46, 0x79, 0x59, 0x32, 0x67, 0x67, 0x53, 0x57, 0x35, 0x7A, 0x64, 0x47, 0x6C, 0x30, ++ 0x64, 0x58, 0x52, 0x70, 0x62, 0x32, 0x35, 0x7A, 0x49, 0x45, 0x56, 0x44, 0x51, 0x79, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x0A, 0x51, 0x30, 0x45, 0x67, 0x4D, 0x6A, 0x41, 0x78, 0x4E, 0x54, 0x42, 0x32, 0x4D, 0x42, 0x41, 0x47, 0x42, 0x79, 0x71, ++ 0x47, 0x53, 0x4D, 0x34, 0x39, 0x41, 0x67, 0x45, 0x47, 0x42, 0x53, 0x75, 0x42, 0x42, 0x41, 0x41, 0x69, 0x41, 0x32, 0x49, 0x41, 0x42, 0x4A, 0x4B, 0x67, 0x51, 0x65, 0x68, 0x4C, 0x67, 0x6F, 0x52, 0x63, 0x34, 0x76, 0x67, 0x78, 0x45, 0x5A, 0x6D, ++ 0x47, 0x5A, 0x45, 0x34, 0x4A, 0x4A, 0x53, 0x2B, 0x64, 0x51, 0x53, 0x38, 0x4B, 0x72, 0x6A, 0x56, 0x50, 0x0A, 0x64, 0x4A, 0x57, 0x79, 0x55, 0x57, 0x52, 0x72, 0x6A, 0x57, 0x76, 0x6D, 0x50, 0x33, 0x43, 0x56, 0x38, 0x41, 0x56, 0x45, 0x52, 0x36, ++ 0x5A, 0x79, 0x4F, 0x46, 0x42, 0x32, 0x6C, 0x51, 0x4A, 0x61, 0x6A, 0x71, 0x34, 0x6F, 0x6E, 0x76, 0x6B, 0x74, 0x54, 0x70, 0x6E, 0x76, 0x4C, 0x45, 0x68, 0x76, 0x54, 0x43, 0x55, 0x70, 0x36, 0x4E, 0x46, 0x78, 0x57, 0x39, 0x38, 0x64, 0x77, 0x58, ++ 0x55, 0x33, 0x74, 0x4E, 0x66, 0x36, 0x65, 0x33, 0x70, 0x43, 0x6E, 0x47, 0x6F, 0x4B, 0x0A, 0x56, 0x6C, 0x70, 0x38, 0x61, 0x51, 0x75, 0x71, 0x67, 0x41, 0x6B, 0x6B, 0x62, 0x48, 0x37, 0x42, 0x52, 0x71, 0x4E, 0x43, 0x4D, 0x45, 0x41, 0x77, 0x44, ++ 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x41, 0x4D, 0x43, 0x41, ++ 0x51, 0x59, 0x77, 0x48, 0x51, 0x59, 0x44, 0x56, 0x52, 0x30, 0x4F, 0x0A, 0x42, 0x42, 0x59, 0x45, 0x46, 0x4C, 0x51, 0x69, 0x43, 0x34, 0x4B, 0x5A, 0x4A, 0x41, 0x45, 0x4F, 0x6E, 0x4C, 0x76, 0x6B, 0x44, 0x76, 0x32, 0x2F, 0x2B, 0x35, 0x63, 0x67, ++ 0x6B, 0x35, 0x6B, 0x71, 0x4D, 0x41, 0x6F, 0x47, 0x43, 0x43, 0x71, 0x47, 0x53, 0x4D, 0x34, 0x39, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x32, 0x63, 0x41, 0x4D, 0x47, 0x51, 0x43, 0x4D, 0x47, 0x66, 0x4F, 0x46, 0x6D, 0x49, 0x34, 0x6F, 0x71, 0x78, 0x69, ++ 0x52, 0x61, 0x65, 0x70, 0x6C, 0x53, 0x54, 0x41, 0x0A, 0x47, 0x69, 0x65, 0x63, 0x4D, 0x6A, 0x76, 0x41, 0x77, 0x4E, 0x57, 0x36, 0x71, 0x65, 0x66, 0x34, 0x42, 0x45, 0x4E, 0x54, 0x68, 0x65, 0x35, 0x53, 0x49, 0x64, 0x36, 0x64, 0x39, 0x53, 0x57, ++ 0x44, 0x50, 0x70, 0x35, 0x59, 0x53, 0x79, 0x2F, 0x58, 0x5A, 0x78, 0x4D, 0x4F, 0x49, 0x51, 0x49, 0x77, 0x42, 0x65, 0x46, 0x31, 0x41, 0x64, 0x35, 0x6F, 0x37, 0x53, 0x6F, 0x66, 0x54, 0x55, 0x77, 0x4A, 0x43, 0x41, 0x33, 0x73, 0x53, 0x36, 0x31, ++ 0x6B, 0x46, 0x79, 0x6A, 0x6E, 0x0A, 0x64, 0x63, 0x35, 0x46, 0x5A, 0x58, 0x49, 0x68, 0x46, 0x38, 0x73, 0x69, 0x51, 0x51, 0x36, 0x4D, 0x45, 0x35, 0x67, 0x34, 0x6D, 0x6C, 0x52, 0x74, 0x6D, 0x38, 0x72, 0x69, 0x66, 0x4F, 0x6F, 0x43, 0x57, 0x43, ++ 0x4B, 0x52, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x49, 0x53, 0x52, 0x47, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, ++ 0x58, 0x31, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, ++ 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x61, 0x7A, 0x43, 0x43, 0x41, 0x31, 0x4F, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x52, 0x41, 0x49, 0x49, 0x51, 0x7A, 0x37, 0x44, 0x53, 0x51, 0x4F, 0x4E, 0x5A, 0x52, 0x47, 0x50, 0x67, ++ 0x75, 0x32, 0x4F, 0x43, 0x69, 0x77, 0x41, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x42, 0x51, 0x41, 0x77, 0x54, 0x7A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, ++ 0x0A, 0x42, 0x68, 0x4D, 0x43, 0x56, 0x56, 0x4D, 0x78, 0x4B, 0x54, 0x41, 0x6E, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x49, 0x45, 0x6C, 0x75, 0x64, 0x47, 0x56, 0x79, 0x62, 0x6D, 0x56, 0x30, 0x49, 0x46, 0x4E, 0x6C, 0x59, 0x33, 0x56, ++ 0x79, 0x61, 0x58, 0x52, 0x35, 0x49, 0x46, 0x4A, 0x6C, 0x63, 0x32, 0x56, 0x68, 0x63, 0x6D, 0x4E, 0x6F, 0x49, 0x45, 0x64, 0x79, 0x62, 0x33, 0x56, 0x77, 0x4D, 0x52, 0x55, 0x77, 0x45, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x0A, 0x45, 0x77, ++ 0x78, 0x4A, 0x55, 0x31, 0x4A, 0x48, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x57, 0x44, 0x45, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x54, 0x55, 0x77, 0x4E, 0x6A, 0x41, 0x30, 0x4D, 0x54, 0x45, 0x77, 0x4E, 0x44, 0x4D, 0x34, 0x57, 0x68, ++ 0x63, 0x4E, 0x4D, 0x7A, 0x55, 0x77, 0x4E, 0x6A, 0x41, 0x30, 0x4D, 0x54, 0x45, 0x77, 0x4E, 0x44, 0x4D, 0x34, 0x57, 0x6A, 0x42, 0x50, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x0A, 0x45, 0x77, 0x4A, 0x56, 0x55, ++ 0x7A, 0x45, 0x70, 0x4D, 0x43, 0x63, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x67, 0x53, 0x57, 0x35, 0x30, 0x5A, 0x58, 0x4A, 0x75, 0x5A, 0x58, 0x51, 0x67, 0x55, 0x32, 0x56, 0x6A, 0x64, 0x58, 0x4A, 0x70, 0x64, 0x48, 0x6B, 0x67, 0x55, ++ 0x6D, 0x56, 0x7A, 0x5A, 0x57, 0x46, 0x79, 0x59, 0x32, 0x67, 0x67, 0x52, 0x33, 0x4A, 0x76, 0x64, 0x58, 0x41, 0x78, 0x46, 0x54, 0x41, 0x54, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x0A, 0x44, 0x45, 0x6C, 0x54, 0x55, 0x6B, 0x63, 0x67, ++ 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x59, 0x4D, 0x54, 0x43, 0x43, 0x41, 0x69, 0x49, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x50, ++ 0x41, 0x44, 0x43, 0x43, 0x41, 0x67, 0x6F, 0x43, 0x67, 0x67, 0x49, 0x42, 0x41, 0x4B, 0x33, 0x6F, 0x4A, 0x48, 0x50, 0x30, 0x46, 0x44, 0x66, 0x7A, 0x6D, 0x35, 0x34, 0x72, 0x0A, 0x56, 0x79, 0x67, 0x63, 0x68, 0x37, 0x37, 0x63, 0x74, 0x39, 0x38, ++ 0x34, 0x6B, 0x49, 0x78, 0x75, 0x50, 0x4F, 0x5A, 0x58, 0x6F, 0x48, 0x6A, 0x33, 0x64, 0x63, 0x4B, 0x69, 0x2F, 0x76, 0x56, 0x71, 0x62, 0x76, 0x59, 0x41, 0x54, 0x79, 0x6A, 0x62, 0x33, 0x6D, 0x69, 0x47, 0x62, 0x45, 0x53, 0x54, 0x74, 0x72, 0x46, ++ 0x6A, 0x2F, 0x52, 0x51, 0x53, 0x61, 0x37, 0x38, 0x66, 0x30, 0x75, 0x6F, 0x78, 0x6D, 0x79, 0x46, 0x2B, 0x30, 0x54, 0x4D, 0x38, 0x75, 0x6B, 0x6A, 0x31, 0x0A, 0x33, 0x58, 0x6E, 0x66, 0x73, 0x37, 0x6A, 0x2F, 0x45, 0x76, 0x45, 0x68, 0x6D, 0x6B, ++ 0x76, 0x42, 0x69, 0x6F, 0x5A, 0x78, 0x61, 0x55, 0x70, 0x6D, 0x5A, 0x6D, 0x79, 0x50, 0x66, 0x6A, 0x78, 0x77, 0x76, 0x36, 0x30, 0x70, 0x49, 0x67, 0x62, 0x7A, 0x35, 0x4D, 0x44, 0x6D, 0x67, 0x4B, 0x37, 0x69, 0x53, 0x34, 0x2B, 0x33, 0x6D, 0x58, ++ 0x36, 0x55, 0x41, 0x35, 0x2F, 0x54, 0x52, 0x35, 0x64, 0x38, 0x6D, 0x55, 0x67, 0x6A, 0x55, 0x2B, 0x67, 0x34, 0x72, 0x6B, 0x38, 0x4B, 0x0A, 0x62, 0x34, 0x4D, 0x75, 0x30, 0x55, 0x6C, 0x58, 0x6A, 0x49, 0x42, 0x30, 0x74, 0x74, 0x6F, 0x76, 0x30, ++ 0x44, 0x69, 0x4E, 0x65, 0x77, 0x4E, 0x77, 0x49, 0x52, 0x74, 0x31, 0x38, 0x6A, 0x41, 0x38, 0x2B, 0x6F, 0x2B, 0x75, 0x33, 0x64, 0x70, 0x6A, 0x71, 0x2B, 0x73, 0x57, 0x54, 0x38, 0x4B, 0x4F, 0x45, 0x55, 0x74, 0x2B, 0x7A, 0x77, 0x76, 0x6F, 0x2F, ++ 0x37, 0x56, 0x33, 0x4C, 0x76, 0x53, 0x79, 0x65, 0x30, 0x72, 0x67, 0x54, 0x42, 0x49, 0x6C, 0x44, 0x48, 0x43, 0x4E, 0x0A, 0x41, 0x79, 0x6D, 0x67, 0x34, 0x56, 0x4D, 0x6B, 0x37, 0x42, 0x50, 0x5A, 0x37, 0x68, 0x6D, 0x2F, 0x45, 0x4C, 0x4E, 0x4B, ++ 0x6A, 0x44, 0x2B, 0x4A, 0x6F, 0x32, 0x46, 0x52, 0x33, 0x71, 0x79, 0x48, 0x42, 0x35, 0x54, 0x30, 0x59, 0x33, 0x48, 0x73, 0x4C, 0x75, 0x4A, 0x76, 0x57, 0x35, 0x69, 0x42, 0x34, 0x59, 0x6C, 0x63, 0x4E, 0x48, 0x6C, 0x73, 0x64, 0x75, 0x38, 0x37, ++ 0x6B, 0x47, 0x4A, 0x35, 0x35, 0x74, 0x75, 0x6B, 0x6D, 0x69, 0x38, 0x6D, 0x78, 0x64, 0x41, 0x51, 0x0A, 0x34, 0x51, 0x37, 0x65, 0x32, 0x52, 0x43, 0x4F, 0x46, 0x76, 0x75, 0x33, 0x39, 0x36, 0x6A, 0x33, 0x78, 0x2B, 0x55, 0x43, 0x42, 0x35, 0x69, ++ 0x50, 0x4E, 0x67, 0x69, 0x56, 0x35, 0x2B, 0x49, 0x33, 0x6C, 0x67, 0x30, 0x32, 0x64, 0x5A, 0x37, 0x37, 0x44, 0x6E, 0x4B, 0x78, 0x48, 0x5A, 0x75, 0x38, 0x41, 0x2F, 0x6C, 0x4A, 0x42, 0x64, 0x69, 0x42, 0x33, 0x51, 0x57, 0x30, 0x4B, 0x74, 0x5A, ++ 0x42, 0x36, 0x61, 0x77, 0x42, 0x64, 0x70, 0x55, 0x4B, 0x44, 0x39, 0x6A, 0x66, 0x0A, 0x31, 0x62, 0x30, 0x53, 0x48, 0x7A, 0x55, 0x76, 0x4B, 0x42, 0x64, 0x73, 0x30, 0x70, 0x6A, 0x42, 0x71, 0x41, 0x6C, 0x6B, 0x64, 0x32, 0x35, 0x48, 0x4E, 0x37, ++ 0x72, 0x4F, 0x72, 0x46, 0x6C, 0x65, 0x61, 0x4A, 0x31, 0x2F, 0x63, 0x74, 0x61, 0x4A, 0x78, 0x51, 0x5A, 0x42, 0x4B, 0x54, 0x35, 0x5A, 0x50, 0x74, 0x30, 0x6D, 0x39, 0x53, 0x54, 0x4A, 0x45, 0x61, 0x64, 0x61, 0x6F, 0x30, 0x78, 0x41, 0x48, 0x30, ++ 0x61, 0x68, 0x6D, 0x62, 0x57, 0x6E, 0x4F, 0x6C, 0x46, 0x75, 0x0A, 0x68, 0x6A, 0x75, 0x65, 0x66, 0x58, 0x4B, 0x6E, 0x45, 0x67, 0x56, 0x34, 0x57, 0x65, 0x30, 0x2B, 0x55, 0x58, 0x67, 0x56, 0x43, 0x77, 0x4F, 0x50, 0x6A, 0x64, 0x41, 0x76, 0x42, ++ 0x62, 0x49, 0x2B, 0x65, 0x30, 0x6F, 0x63, 0x53, 0x33, 0x4D, 0x46, 0x45, 0x76, 0x7A, 0x47, 0x36, 0x75, 0x42, 0x51, 0x45, 0x33, 0x78, 0x44, 0x6B, 0x33, 0x53, 0x7A, 0x79, 0x6E, 0x54, 0x6E, 0x6A, 0x68, 0x38, 0x42, 0x43, 0x4E, 0x41, 0x77, 0x31, ++ 0x46, 0x74, 0x78, 0x4E, 0x72, 0x51, 0x48, 0x0A, 0x75, 0x73, 0x45, 0x77, 0x4D, 0x46, 0x78, 0x49, 0x74, 0x34, 0x49, 0x37, 0x6D, 0x4B, 0x5A, 0x39, 0x59, 0x49, 0x71, 0x69, 0x6F, 0x79, 0x6D, 0x43, 0x7A, 0x4C, 0x71, 0x39, 0x67, 0x77, 0x51, 0x62, ++ 0x6F, 0x6F, 0x4D, 0x44, 0x51, 0x61, 0x48, 0x57, 0x42, 0x66, 0x45, 0x62, 0x77, 0x72, 0x62, 0x77, 0x71, 0x48, 0x79, 0x47, 0x4F, 0x30, 0x61, 0x6F, 0x53, 0x43, 0x71, 0x49, 0x33, 0x48, 0x61, 0x61, 0x64, 0x72, 0x38, 0x66, 0x61, 0x71, 0x55, 0x39, ++ 0x47, 0x59, 0x2F, 0x72, 0x0A, 0x4F, 0x50, 0x4E, 0x6B, 0x33, 0x73, 0x67, 0x72, 0x44, 0x51, 0x6F, 0x6F, 0x2F, 0x2F, 0x66, 0x62, 0x34, 0x68, 0x56, 0x43, 0x31, 0x43, 0x4C, 0x51, 0x4A, 0x31, 0x33, 0x68, 0x65, 0x66, 0x34, 0x59, 0x35, 0x33, 0x43, ++ 0x49, 0x72, 0x55, 0x37, 0x6D, 0x32, 0x59, 0x73, 0x36, 0x78, 0x74, 0x30, 0x6E, 0x55, 0x57, 0x37, 0x2F, 0x76, 0x47, 0x54, 0x31, 0x4D, 0x30, 0x4E, 0x50, 0x41, 0x67, 0x4D, 0x42, 0x41, 0x41, 0x47, 0x6A, 0x51, 0x6A, 0x42, 0x41, 0x4D, 0x41, 0x34, ++ 0x47, 0x0A, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x42, 0x42, 0x6A, 0x41, 0x50, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x52, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x54, 0x41, 0x44, 0x41, 0x51, ++ 0x48, 0x2F, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x52, 0x35, 0x74, 0x46, 0x6E, 0x6D, 0x65, 0x37, 0x62, 0x6C, 0x35, 0x41, 0x46, 0x7A, 0x67, 0x41, 0x69, 0x49, 0x79, 0x42, 0x70, 0x59, 0x0A, 0x39, ++ 0x75, 0x6D, 0x62, 0x62, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x67, 0x45, 0x41, 0x56, 0x52, 0x39, 0x59, 0x71, 0x62, 0x79, 0x79, 0x71, ++ 0x46, 0x44, 0x51, 0x44, 0x4C, 0x48, 0x59, 0x47, 0x6D, 0x6B, 0x67, 0x4A, 0x79, 0x6B, 0x49, 0x72, 0x47, 0x46, 0x31, 0x58, 0x49, 0x70, 0x75, 0x2B, 0x49, 0x4C, 0x6C, 0x61, 0x53, 0x2F, 0x56, 0x39, 0x6C, 0x5A, 0x4C, 0x0A, 0x75, 0x62, 0x68, 0x7A, ++ 0x45, 0x46, 0x6E, 0x54, 0x49, 0x5A, 0x64, 0x2B, 0x35, 0x30, 0x78, 0x78, 0x2B, 0x37, 0x4C, 0x53, 0x59, 0x4B, 0x30, 0x35, 0x71, 0x41, 0x76, 0x71, 0x46, 0x79, 0x46, 0x57, 0x68, 0x66, 0x46, 0x51, 0x44, 0x6C, 0x6E, 0x72, 0x7A, 0x75, 0x42, 0x5A, ++ 0x36, 0x62, 0x72, 0x4A, 0x46, 0x65, 0x2B, 0x47, 0x6E, 0x59, 0x2B, 0x45, 0x67, 0x50, 0x62, 0x6B, 0x36, 0x5A, 0x47, 0x51, 0x33, 0x42, 0x65, 0x62, 0x59, 0x68, 0x74, 0x46, 0x38, 0x47, 0x61, 0x56, 0x0A, 0x30, 0x6E, 0x78, 0x76, 0x77, 0x75, 0x6F, ++ 0x37, 0x37, 0x78, 0x2F, 0x50, 0x79, 0x39, 0x61, 0x75, 0x4A, 0x2F, 0x47, 0x70, 0x73, 0x4D, 0x69, 0x75, 0x2F, 0x58, 0x31, 0x2B, 0x6D, 0x76, 0x6F, 0x69, 0x42, 0x4F, 0x76, 0x2F, 0x32, 0x58, 0x2F, 0x71, 0x6B, 0x53, 0x73, 0x69, 0x73, 0x52, 0x63, ++ 0x4F, 0x6A, 0x2F, 0x4B, 0x4B, 0x4E, 0x46, 0x74, 0x59, 0x32, 0x50, 0x77, 0x42, 0x79, 0x56, 0x53, 0x35, 0x75, 0x43, 0x62, 0x4D, 0x69, 0x6F, 0x67, 0x7A, 0x69, 0x55, 0x77, 0x74, 0x0A, 0x68, 0x44, 0x79, 0x43, 0x33, 0x2B, 0x36, 0x57, 0x56, 0x77, ++ 0x57, 0x36, 0x4C, 0x4C, 0x76, 0x33, 0x78, 0x4C, 0x66, 0x48, 0x54, 0x6A, 0x75, 0x43, 0x76, 0x6A, 0x48, 0x49, 0x49, 0x6E, 0x4E, 0x7A, 0x6B, 0x74, 0x48, 0x43, 0x67, 0x4B, 0x51, 0x35, 0x4F, 0x52, 0x41, 0x7A, 0x49, 0x34, 0x4A, 0x4D, 0x50, 0x4A, ++ 0x2B, 0x47, 0x73, 0x6C, 0x57, 0x59, 0x48, 0x62, 0x34, 0x70, 0x68, 0x6F, 0x77, 0x69, 0x6D, 0x35, 0x37, 0x69, 0x61, 0x7A, 0x74, 0x58, 0x4F, 0x6F, 0x4A, 0x77, 0x0A, 0x54, 0x64, 0x77, 0x4A, 0x78, 0x34, 0x6E, 0x4C, 0x43, 0x67, 0x64, 0x4E, 0x62, ++ 0x4F, 0x68, 0x64, 0x6A, 0x73, 0x6E, 0x76, 0x7A, 0x71, 0x76, 0x48, 0x75, 0x37, 0x55, 0x72, 0x54, 0x6B, 0x58, 0x57, 0x53, 0x74, 0x41, 0x6D, 0x7A, 0x4F, 0x56, 0x79, 0x79, 0x67, 0x68, 0x71, 0x70, 0x5A, 0x58, 0x6A, 0x46, 0x61, 0x48, 0x33, 0x70, ++ 0x4F, 0x33, 0x4A, 0x4C, 0x46, 0x2B, 0x6C, 0x2B, 0x2F, 0x2B, 0x73, 0x4B, 0x41, 0x49, 0x75, 0x76, 0x74, 0x64, 0x37, 0x75, 0x2B, 0x4E, 0x78, 0x0A, 0x65, 0x35, 0x41, 0x57, 0x30, 0x77, 0x64, 0x65, 0x52, 0x6C, 0x4E, 0x38, 0x4E, 0x77, 0x64, 0x43, ++ 0x6A, 0x4E, 0x50, 0x45, 0x6C, 0x70, 0x7A, 0x56, 0x6D, 0x62, 0x55, 0x71, 0x34, 0x4A, 0x55, 0x61, 0x67, 0x45, 0x69, 0x75, 0x54, 0x44, 0x6B, 0x48, 0x7A, 0x73, 0x78, 0x48, 0x70, 0x46, 0x4B, 0x56, 0x4B, 0x37, 0x71, 0x34, 0x2B, 0x36, 0x33, 0x53, ++ 0x4D, 0x31, 0x4E, 0x39, 0x35, 0x52, 0x31, 0x4E, 0x62, 0x64, 0x57, 0x68, 0x73, 0x63, 0x64, 0x43, 0x62, 0x2B, 0x5A, 0x41, 0x0A, 0x4A, 0x7A, 0x56, 0x63, 0x6F, 0x79, 0x69, 0x33, 0x42, 0x34, 0x33, 0x6E, 0x6A, 0x54, 0x4F, 0x51, 0x35, 0x79, 0x4F, ++ 0x66, 0x2B, 0x31, 0x43, 0x63, 0x65, 0x57, 0x78, 0x47, 0x31, 0x62, 0x51, 0x56, 0x73, 0x35, 0x5A, 0x75, 0x66, 0x70, 0x73, 0x4D, 0x6C, 0x6A, 0x71, 0x34, 0x55, 0x69, 0x30, 0x2F, 0x31, 0x6C, 0x76, 0x68, 0x2B, 0x77, 0x6A, 0x43, 0x68, 0x50, 0x34, ++ 0x6B, 0x71, 0x4B, 0x4F, 0x4A, 0x32, 0x71, 0x78, 0x71, 0x34, 0x52, 0x67, 0x71, 0x73, 0x61, 0x68, 0x44, 0x0A, 0x59, 0x56, 0x76, 0x54, 0x48, 0x39, 0x77, 0x37, 0x6A, 0x58, 0x62, 0x79, 0x4C, 0x65, 0x69, 0x4E, 0x64, 0x64, 0x38, 0x58, 0x4D, 0x32, ++ 0x77, 0x39, 0x55, 0x2F, 0x74, 0x37, 0x79, 0x30, 0x46, 0x66, 0x2F, 0x39, 0x79, 0x69, 0x30, 0x47, 0x45, 0x34, 0x34, 0x5A, 0x61, 0x34, 0x72, 0x46, 0x32, 0x4C, 0x4E, 0x39, 0x64, 0x31, 0x31, 0x54, 0x50, 0x41, 0x6D, 0x52, 0x47, 0x75, 0x6E, 0x55, ++ 0x48, 0x42, 0x63, 0x6E, 0x57, 0x45, 0x76, 0x67, 0x4A, 0x42, 0x51, 0x6C, 0x39, 0x6E, 0x0A, 0x4A, 0x45, 0x69, 0x55, 0x30, 0x5A, 0x73, 0x6E, 0x76, 0x67, 0x63, 0x2F, 0x75, 0x62, 0x68, 0x50, 0x67, 0x58, 0x52, 0x52, 0x34, 0x58, 0x71, 0x33, 0x37, ++ 0x5A, 0x30, 0x6A, 0x34, 0x72, 0x37, 0x67, 0x31, 0x53, 0x67, 0x45, 0x45, 0x7A, 0x77, 0x78, 0x41, 0x35, 0x37, 0x64, 0x65, 0x6D, 0x79, 0x50, 0x78, 0x67, 0x63, 0x59, 0x78, 0x6E, 0x2F, 0x65, 0x52, 0x34, 0x34, 0x2F, 0x4B, 0x4A, 0x34, 0x45, 0x42, ++ 0x73, 0x2B, 0x6C, 0x56, 0x44, 0x52, 0x33, 0x76, 0x65, 0x79, 0x4A, 0x0A, 0x6D, 0x2B, 0x6B, 0x58, 0x51, 0x39, 0x39, 0x62, 0x32, 0x31, 0x2F, 0x2B, 0x6A, 0x68, 0x35, 0x58, 0x6F, 0x73, 0x31, 0x41, 0x6E, 0x58, 0x35, 0x69, 0x49, 0x74, 0x72, 0x65, ++ 0x47, 0x43, 0x63, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x41, 0x43, 0x20, 0x52, 0x41, 0x49, 0x5A, 0x20, ++ 0x46, 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, 0x4D, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, ++ 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x67, 0x7A, 0x43, 0x43, 0x41, 0x32, 0x75, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x50, 0x58, 0x5A, 0x4F, 0x4E, 0x4D, 0x47, ++ 0x63, 0x32, 0x79, 0x41, 0x59, 0x64, 0x47, 0x73, 0x64, 0x55, 0x68, 0x47, 0x6B, 0x48, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x43, 0x77, 0x55, 0x41, 0x4D, 0x44, 0x73, 0x78, 0x43, 0x7A, ++ 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x0A, 0x41, 0x6B, 0x56, 0x54, 0x4D, 0x52, 0x45, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x44, 0x41, 0x68, 0x47, 0x54, 0x6B, 0x31, 0x55, 0x4C, 0x56, 0x4A, 0x44, 0x54, ++ 0x54, 0x45, 0x5A, 0x4D, 0x42, 0x63, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x77, 0x77, 0x51, 0x51, 0x55, 0x4D, 0x67, 0x55, 0x6B, 0x46, 0x4A, 0x57, 0x69, 0x42, 0x47, 0x54, 0x6B, 0x31, 0x55, 0x4C, 0x56, 0x4A, 0x44, 0x54, 0x54, 0x41, 0x65, 0x46, ++ 0x77, 0x30, 0x77, 0x4F, 0x44, 0x45, 0x77, 0x0A, 0x4D, 0x6A, 0x6B, 0x78, 0x4E, 0x54, 0x55, 0x35, 0x4E, 0x54, 0x5A, 0x61, 0x46, 0x77, 0x30, 0x7A, 0x4D, 0x44, 0x41, 0x78, 0x4D, 0x44, 0x45, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x44, 0x42, 0x61, ++ 0x4D, 0x44, 0x73, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6B, 0x56, 0x54, 0x4D, 0x52, 0x45, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x44, 0x41, 0x68, 0x47, 0x54, 0x6B, 0x31, 0x55, ++ 0x4C, 0x56, 0x4A, 0x44, 0x0A, 0x54, 0x54, 0x45, 0x5A, 0x4D, 0x42, 0x63, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x77, 0x77, 0x51, 0x51, 0x55, 0x4D, 0x67, 0x55, 0x6B, 0x46, 0x4A, 0x57, 0x69, 0x42, 0x47, 0x54, 0x6B, 0x31, 0x55, 0x4C, 0x56, 0x4A, ++ 0x44, 0x54, 0x54, 0x43, 0x43, 0x41, 0x69, 0x49, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x50, 0x41, 0x44, 0x43, 0x43, 0x41, 0x67, 0x6F, ++ 0x43, 0x0A, 0x67, 0x67, 0x49, 0x42, 0x41, 0x4C, 0x70, 0x78, 0x67, 0x48, 0x70, 0x4D, 0x68, 0x6D, 0x35, 0x2F, 0x79, 0x42, 0x4E, 0x74, 0x77, 0x4D, 0x5A, 0x39, 0x48, 0x41, 0x43, 0x58, 0x6A, 0x79, 0x77, 0x4D, 0x49, 0x37, 0x73, 0x51, 0x6D, 0x6B, ++ 0x43, 0x70, 0x47, 0x72, 0x65, 0x48, 0x69, 0x50, 0x69, 0x62, 0x56, 0x6D, 0x72, 0x37, 0x35, 0x6E, 0x75, 0x4F, 0x69, 0x35, 0x4B, 0x4F, 0x70, 0x79, 0x56, 0x64, 0x57, 0x52, 0x48, 0x62, 0x4E, 0x69, 0x36, 0x33, 0x55, 0x52, 0x63, 0x66, 0x0A, 0x71, ++ 0x51, 0x67, 0x66, 0x42, 0x42, 0x63, 0x6B, 0x57, 0x4B, 0x6F, 0x33, 0x53, 0x68, 0x6A, 0x66, 0x35, 0x54, 0x6E, 0x55, 0x56, 0x2F, 0x33, 0x58, 0x77, 0x53, 0x79, 0x52, 0x41, 0x5A, 0x48, 0x69, 0x49, 0x74, 0x51, 0x44, 0x77, 0x46, 0x6A, 0x38, 0x64, ++ 0x30, 0x66, 0x73, 0x6A, 0x7A, 0x35, 0x30, 0x51, 0x37, 0x71, 0x73, 0x4E, 0x49, 0x31, 0x4E, 0x4F, 0x48, 0x5A, 0x6E, 0x6A, 0x72, 0x44, 0x49, 0x62, 0x7A, 0x41, 0x7A, 0x57, 0x48, 0x46, 0x63, 0x74, 0x50, 0x56, 0x72, 0x0A, 0x62, 0x74, 0x51, 0x42, ++ 0x55, 0x4C, 0x67, 0x54, 0x66, 0x6D, 0x78, 0x4B, 0x6F, 0x30, 0x6E, 0x52, 0x49, 0x42, 0x6E, 0x75, 0x76, 0x4D, 0x41, 0x70, 0x47, 0x47, 0x57, 0x6E, 0x33, 0x76, 0x37, 0x76, 0x33, 0x51, 0x71, 0x51, 0x49, 0x65, 0x63, 0x61, 0x5A, 0x35, 0x4A, 0x43, ++ 0x45, 0x4A, 0x68, 0x66, 0x54, 0x7A, 0x43, 0x38, 0x50, 0x68, 0x78, 0x46, 0x74, 0x42, 0x44, 0x58, 0x61, 0x45, 0x41, 0x55, 0x77, 0x45, 0x44, 0x36, 0x35, 0x33, 0x63, 0x58, 0x65, 0x75, 0x59, 0x4C, 0x0A, 0x6A, 0x32, 0x56, 0x62, 0x50, 0x4E, 0x6D, ++ 0x61, 0x55, 0x74, 0x75, 0x31, 0x76, 0x5A, 0x35, 0x47, 0x7A, 0x7A, 0x33, 0x72, 0x6B, 0x51, 0x55, 0x43, 0x77, 0x4A, 0x61, 0x79, 0x64, 0x6B, 0x78, 0x4E, 0x45, 0x4A, 0x59, 0x37, 0x6B, 0x76, 0x71, 0x63, 0x66, 0x77, 0x2B, 0x5A, 0x33, 0x37, 0x34, ++ 0x6A, 0x4E, 0x55, 0x55, 0x65, 0x41, 0x6C, 0x7A, 0x2B, 0x74, 0x61, 0x69, 0x62, 0x6D, 0x53, 0x58, 0x61, 0x58, 0x76, 0x4D, 0x69, 0x77, 0x7A, 0x6E, 0x31, 0x35, 0x43, 0x6F, 0x75, 0x0A, 0x30, 0x38, 0x59, 0x66, 0x78, 0x47, 0x79, 0x71, 0x78, 0x52, ++ 0x78, 0x71, 0x41, 0x51, 0x56, 0x4B, 0x4C, 0x39, 0x4C, 0x46, 0x77, 0x61, 0x67, 0x30, 0x4A, 0x6C, 0x31, 0x6D, 0x70, 0x64, 0x49, 0x43, 0x49, 0x66, 0x6B, 0x59, 0x74, 0x77, 0x62, 0x31, 0x54, 0x70, 0x6C, 0x76, 0x71, 0x4B, 0x74, 0x4D, 0x55, 0x65, ++ 0x6A, 0x50, 0x55, 0x42, 0x6A, 0x46, 0x64, 0x38, 0x67, 0x35, 0x43, 0x53, 0x78, 0x4A, 0x6B, 0x6A, 0x4B, 0x5A, 0x71, 0x4C, 0x73, 0x58, 0x46, 0x33, 0x6D, 0x77, 0x0A, 0x57, 0x73, 0x58, 0x6D, 0x6F, 0x38, 0x52, 0x5A, 0x5A, 0x55, 0x63, 0x31, 0x67, ++ 0x31, 0x36, 0x70, 0x36, 0x44, 0x55, 0x4C, 0x6D, 0x62, 0x76, 0x6B, 0x7A, 0x53, 0x44, 0x47, 0x6D, 0x30, 0x6F, 0x47, 0x4F, 0x62, 0x56, 0x6F, 0x2F, 0x43, 0x4B, 0x36, 0x37, 0x6C, 0x57, 0x4D, 0x4B, 0x30, 0x37, 0x71, 0x38, 0x37, 0x48, 0x6A, 0x2F, ++ 0x4C, 0x61, 0x5A, 0x6D, 0x74, 0x56, 0x43, 0x2B, 0x6E, 0x46, 0x4E, 0x43, 0x4D, 0x2B, 0x48, 0x48, 0x6D, 0x70, 0x78, 0x66, 0x66, 0x6E, 0x54, 0x0A, 0x74, 0x4F, 0x6D, 0x6C, 0x63, 0x59, 0x46, 0x37, 0x77, 0x6B, 0x35, 0x48, 0x6C, 0x71, 0x58, 0x32, ++ 0x64, 0x6F, 0x57, 0x6A, 0x4B, 0x49, 0x2F, 0x70, 0x67, 0x47, 0x36, 0x42, 0x55, 0x36, 0x56, 0x74, 0x58, 0x37, 0x68, 0x49, 0x2B, 0x63, 0x4C, 0x35, 0x4E, 0x71, 0x59, 0x75, 0x53, 0x66, 0x2B, 0x34, 0x6C, 0x73, 0x4B, 0x4D, 0x42, 0x37, 0x4F, 0x62, ++ 0x69, 0x46, 0x6A, 0x38, 0x36, 0x78, 0x73, 0x63, 0x33, 0x69, 0x31, 0x77, 0x34, 0x70, 0x65, 0x53, 0x4D, 0x4B, 0x47, 0x4A, 0x0A, 0x34, 0x37, 0x78, 0x56, 0x71, 0x43, 0x66, 0x57, 0x53, 0x2B, 0x32, 0x51, 0x72, 0x59, 0x76, 0x36, 0x59, 0x79, 0x56, ++ 0x5A, 0x4C, 0x61, 0x67, 0x31, 0x33, 0x63, 0x71, 0x58, 0x4D, 0x37, 0x7A, 0x6C, 0x7A, 0x63, 0x65, 0x64, 0x30, 0x65, 0x7A, 0x76, 0x58, 0x67, 0x35, 0x4B, 0x6B, 0x41, 0x59, 0x6D, 0x59, 0x36, 0x32, 0x35, 0x32, 0x54, 0x55, 0x74, 0x42, 0x37, 0x70, ++ 0x32, 0x5A, 0x53, 0x79, 0x73, 0x56, 0x34, 0x39, 0x39, 0x39, 0x41, 0x65, 0x55, 0x31, 0x34, 0x45, 0x43, 0x0A, 0x6C, 0x6C, 0x32, 0x6A, 0x42, 0x30, 0x6E, 0x56, 0x65, 0x74, 0x42, 0x58, 0x2B, 0x52, 0x76, 0x6E, 0x55, 0x30, 0x5A, 0x31, 0x71, 0x72, ++ 0x42, 0x35, 0x51, 0x73, 0x74, 0x6F, 0x63, 0x51, 0x6A, 0x70, 0x59, 0x4C, 0x30, 0x35, 0x61, 0x63, 0x37, 0x30, 0x72, 0x38, 0x4E, 0x57, 0x51, 0x4D, 0x65, 0x74, 0x55, 0x71, 0x49, 0x4A, 0x35, 0x47, 0x2B, 0x47, 0x52, 0x34, 0x6F, 0x66, 0x36, 0x79, ++ 0x67, 0x6E, 0x58, 0x59, 0x4D, 0x67, 0x72, 0x77, 0x54, 0x4A, 0x62, 0x46, 0x61, 0x61, 0x0A, 0x69, 0x30, 0x62, 0x31, 0x41, 0x67, 0x4D, 0x42, 0x41, 0x41, 0x47, 0x6A, 0x67, 0x59, 0x4D, 0x77, 0x67, 0x59, 0x41, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, ++ 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x51, 0x59, 0x77, 0x48, ++ 0x51, 0x59, 0x44, 0x56, 0x52, 0x30, 0x4F, 0x42, 0x42, 0x59, 0x45, 0x0A, 0x46, 0x50, 0x64, 0x39, 0x78, 0x66, 0x33, 0x45, 0x36, 0x4A, 0x6F, 0x62, 0x64, 0x32, 0x53, 0x6E, 0x39, 0x52, 0x32, 0x67, 0x7A, 0x4C, 0x2B, 0x48, 0x59, 0x4A, 0x70, 0x74, ++ 0x4D, 0x44, 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x49, 0x41, 0x51, 0x33, 0x4D, 0x44, 0x55, 0x77, 0x4D, 0x77, 0x59, 0x45, 0x56, 0x52, 0x30, 0x67, 0x41, 0x44, 0x41, 0x72, 0x4D, 0x43, 0x6B, 0x47, 0x43, 0x43, 0x73, 0x47, 0x41, 0x51, 0x55, 0x46, ++ 0x42, 0x77, 0x49, 0x42, 0x46, 0x68, 0x31, 0x6F, 0x0A, 0x64, 0x48, 0x52, 0x77, 0x4F, 0x69, 0x38, 0x76, 0x64, 0x33, 0x64, 0x33, 0x4C, 0x6D, 0x4E, 0x6C, 0x63, 0x6E, 0x51, 0x75, 0x5A, 0x6D, 0x35, 0x74, 0x64, 0x43, 0x35, 0x6C, 0x63, 0x79, 0x39, ++ 0x6B, 0x63, 0x47, 0x4E, 0x7A, 0x4C, 0x7A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x67, 0x45, 0x41, 0x42, 0x35, 0x42, 0x4B, 0x33, 0x2F, 0x4D, ++ 0x6A, 0x54, 0x76, 0x44, 0x44, 0x0A, 0x6E, 0x46, 0x46, 0x6C, 0x6D, 0x35, 0x77, 0x69, 0x6F, 0x6F, 0x6F, 0x4D, 0x68, 0x66, 0x4E, 0x7A, 0x4B, 0x57, 0x74, 0x4E, 0x2F, 0x67, 0x48, 0x69, 0x71, 0x51, 0x78, 0x6A, 0x41, 0x62, 0x38, 0x45, 0x5A, 0x36, ++ 0x57, 0x64, 0x6D, 0x46, 0x2F, 0x39, 0x41, 0x52, 0x50, 0x36, 0x37, 0x4A, 0x70, 0x69, 0x36, 0x59, 0x62, 0x2B, 0x74, 0x6D, 0x4C, 0x53, 0x62, 0x6B, 0x79, 0x55, 0x2B, 0x38, 0x42, 0x31, 0x52, 0x58, 0x78, 0x6C, 0x44, 0x50, 0x69, 0x79, 0x4E, 0x38, ++ 0x2B, 0x73, 0x0A, 0x44, 0x38, 0x2B, 0x4E, 0x62, 0x2F, 0x6B, 0x5A, 0x39, 0x34, 0x2F, 0x73, 0x48, 0x76, 0x4A, 0x77, 0x6E, 0x76, 0x44, 0x4B, 0x75, 0x4F, 0x2B, 0x33, 0x2F, 0x33, 0x59, 0x33, 0x64, 0x6C, 0x76, 0x32, 0x62, 0x6F, 0x6A, 0x7A, 0x72, ++ 0x32, 0x49, 0x79, 0x49, 0x70, 0x4D, 0x4E, 0x4F, 0x6D, 0x71, 0x4F, 0x46, 0x47, 0x59, 0x4D, 0x4C, 0x56, 0x4E, 0x30, 0x56, 0x32, 0x55, 0x65, 0x31, 0x62, 0x4C, 0x64, 0x49, 0x34, 0x45, 0x37, 0x70, 0x57, 0x59, 0x6A, 0x4A, 0x32, 0x63, 0x4A, 0x0A, ++ 0x6A, 0x2B, 0x46, 0x33, 0x71, 0x6B, 0x50, 0x4E, 0x5A, 0x56, 0x45, 0x49, 0x37, 0x56, 0x46, 0x59, 0x2F, 0x75, 0x59, 0x35, 0x2B, 0x63, 0x74, 0x48, 0x68, 0x4B, 0x51, 0x56, 0x38, 0x58, 0x61, 0x37, 0x70, 0x4F, 0x36, 0x6B, 0x4F, 0x38, 0x52, 0x66, ++ 0x37, 0x37, 0x49, 0x7A, 0x6C, 0x68, 0x45, 0x59, 0x74, 0x38, 0x6C, 0x6C, 0x76, 0x68, 0x6A, 0x68, 0x6F, 0x36, 0x54, 0x63, 0x2B, 0x68, 0x6A, 0x35, 0x30, 0x37, 0x77, 0x54, 0x6D, 0x7A, 0x6C, 0x36, 0x4E, 0x4C, 0x72, 0x54, 0x0A, 0x51, 0x66, 0x76, ++ 0x36, 0x4D, 0x6F, 0x6F, 0x71, 0x74, 0x79, 0x75, 0x47, 0x43, 0x32, 0x6D, 0x44, 0x4F, 0x4C, 0x37, 0x4E, 0x69, 0x69, 0x34, 0x4C, 0x63, 0x4B, 0x32, 0x4E, 0x4A, 0x70, 0x4C, 0x75, 0x48, 0x76, 0x55, 0x42, 0x4B, 0x77, 0x72, 0x5A, 0x31, 0x70, 0x65, ++ 0x62, 0x62, 0x75, 0x43, 0x6F, 0x47, 0x52, 0x77, 0x36, 0x49, 0x59, 0x73, 0x4D, 0x48, 0x6B, 0x43, 0x74, 0x41, 0x2B, 0x66, 0x64, 0x5A, 0x6E, 0x37, 0x31, 0x75, 0x53, 0x41, 0x4E, 0x41, 0x2B, 0x69, 0x57, 0x0A, 0x2B, 0x59, 0x4A, 0x46, 0x31, 0x44, ++ 0x6E, 0x67, 0x6F, 0x41, 0x42, 0x64, 0x31, 0x35, 0x6A, 0x6D, 0x66, 0x5A, 0x35, 0x6E, 0x63, 0x38, 0x4F, 0x61, 0x4B, 0x76, 0x65, 0x72, 0x69, 0x36, 0x45, 0x36, 0x46, 0x4F, 0x38, 0x30, 0x76, 0x46, 0x49, 0x4F, 0x69, 0x5A, 0x69, 0x61, 0x42, 0x45, ++ 0x43, 0x45, 0x48, 0x58, 0x35, 0x46, 0x61, 0x5A, 0x4E, 0x58, 0x7A, 0x75, 0x76, 0x4F, 0x2B, 0x46, 0x42, 0x38, 0x54, 0x78, 0x78, 0x75, 0x42, 0x45, 0x4F, 0x62, 0x2B, 0x64, 0x59, 0x37, 0x0A, 0x49, 0x78, 0x6A, 0x70, 0x36, 0x6F, 0x37, 0x52, 0x54, ++ 0x55, 0x61, 0x4E, 0x38, 0x54, 0x76, 0x6B, 0x61, 0x73, 0x71, 0x36, 0x2B, 0x79, 0x4F, 0x33, 0x6D, 0x2F, 0x71, 0x5A, 0x41, 0x53, 0x6C, 0x61, 0x57, 0x46, 0x6F, 0x74, 0x34, 0x2F, 0x6E, 0x55, 0x62, 0x51, 0x34, 0x6D, 0x72, 0x63, 0x46, 0x75, 0x4E, ++ 0x4C, 0x77, 0x79, 0x2B, 0x41, 0x77, 0x46, 0x2B, 0x6D, 0x57, 0x6A, 0x32, 0x7A, 0x73, 0x33, 0x67, 0x79, 0x4C, 0x70, 0x31, 0x74, 0x78, 0x79, 0x4D, 0x2F, 0x31, 0x64, 0x0A, 0x38, 0x69, 0x43, 0x39, 0x64, 0x6A, 0x77, 0x6A, 0x32, 0x69, 0x6A, 0x33, ++ 0x2B, 0x52, 0x76, 0x72, 0x57, 0x57, 0x54, 0x56, 0x33, 0x46, 0x39, 0x79, 0x66, 0x69, 0x44, 0x38, 0x7A, 0x59, 0x6D, 0x31, 0x6B, 0x47, 0x64, 0x4E, 0x59, 0x6E, 0x6F, 0x2F, 0x54, 0x71, 0x30, 0x64, 0x77, 0x7A, 0x6E, 0x2B, 0x65, 0x76, 0x51, 0x6F, ++ 0x46, 0x74, 0x39, 0x42, 0x39, 0x6B, 0x69, 0x41, 0x42, 0x64, 0x63, 0x50, 0x55, 0x58, 0x6D, 0x73, 0x45, 0x4B, 0x76, 0x55, 0x37, 0x41, 0x4E, 0x6D, 0x0A, 0x35, 0x6D, 0x71, 0x77, 0x75, 0x6A, 0x47, 0x53, 0x51, 0x6B, 0x42, 0x71, 0x76, 0x6A, 0x72, ++ 0x54, 0x63, 0x75, 0x46, 0x71, 0x4E, 0x31, 0x57, 0x38, 0x72, 0x42, 0x32, 0x56, 0x74, 0x32, 0x6C, 0x68, 0x38, 0x6B, 0x4F, 0x52, 0x64, 0x4F, 0x61, 0x67, 0x30, 0x77, 0x6F, 0x6B, 0x52, 0x71, 0x45, 0x49, 0x72, 0x39, 0x62, 0x61, 0x52, 0x52, 0x6D, ++ 0x57, 0x31, 0x46, 0x4D, 0x64, 0x57, 0x34, 0x52, 0x35, 0x38, 0x4D, 0x44, 0x33, 0x52, 0x2B, 0x2B, 0x4C, 0x6A, 0x38, 0x55, 0x47, 0x0A, 0x72, 0x70, 0x31, 0x4D, 0x59, 0x70, 0x33, 0x2F, 0x52, 0x67, 0x54, 0x34, 0x30, 0x38, 0x6D, 0x32, 0x45, 0x43, ++ 0x56, 0x41, 0x64, 0x66, 0x34, 0x57, 0x71, 0x73, 0x6C, 0x4B, 0x59, 0x49, 0x59, 0x76, 0x75, 0x75, 0x38, 0x77, 0x64, 0x2B, 0x52, 0x55, 0x34, 0x72, 0x69, 0x45, 0x6D, 0x56, 0x69, 0x41, 0x71, 0x68, 0x4F, 0x4C, 0x55, 0x54, 0x70, 0x50, 0x53, 0x50, ++ 0x61, 0x4C, 0x74, 0x72, 0x4D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, ++ 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, ++ 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x44, 0x51, 0x54, 0x43, 0x43, 0x41, 0x69, 0x6D, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x54, 0x42, 0x6D, 0x79, 0x66, ++ 0x7A, 0x35, 0x6D, 0x2F, 0x6A, 0x41, 0x6F, 0x35, 0x34, 0x76, 0x42, 0x34, 0x69, 0x6B, 0x50, 0x6D, 0x6C, 0x6A, 0x5A, 0x62, 0x79, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, ++ 0x41, 0x44, 0x41, 0x35, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x0A, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x56, 0x55, 0x7A, 0x45, 0x50, 0x4D, 0x41, 0x30, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x47, 0x51, 0x57, 0x31, ++ 0x68, 0x65, 0x6D, 0x39, 0x75, 0x4D, 0x52, 0x6B, 0x77, 0x46, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x42, 0x42, 0x62, 0x57, 0x46, 0x36, 0x62, 0x32, 0x34, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x51, 0x53, 0x41, ++ 0x78, 0x4D, 0x42, 0x34, 0x58, 0x44, 0x54, 0x45, 0x31, 0x0A, 0x4D, 0x44, 0x55, 0x79, 0x4E, 0x6A, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x46, 0x6F, 0x58, 0x44, 0x54, 0x4D, 0x34, 0x4D, 0x44, 0x45, 0x78, 0x4E, 0x7A, 0x41, 0x77, 0x4D, 0x44, ++ 0x41, 0x77, 0x4D, 0x46, 0x6F, 0x77, 0x4F, 0x54, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x56, 0x56, 0x4D, 0x78, 0x44, 0x7A, 0x41, 0x4E, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x42, 0x6B, ++ 0x46, 0x74, 0x59, 0x58, 0x70, 0x76, 0x0A, 0x62, 0x6A, 0x45, 0x5A, 0x4D, 0x42, 0x63, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x51, 0x51, 0x57, 0x31, 0x68, 0x65, 0x6D, 0x39, 0x75, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, ++ 0x30, 0x45, 0x67, 0x4D, 0x54, 0x43, 0x43, 0x41, 0x53, 0x49, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x45, 0x50, 0x41, 0x44, 0x43, 0x43, 0x41, ++ 0x51, 0x6F, 0x43, 0x0A, 0x67, 0x67, 0x45, 0x42, 0x41, 0x4C, 0x4A, 0x34, 0x67, 0x48, 0x48, 0x4B, 0x65, 0x4E, 0x58, 0x6A, 0x63, 0x61, 0x39, 0x48, 0x67, 0x46, 0x42, 0x30, 0x66, 0x57, 0x37, 0x59, 0x31, 0x34, 0x68, 0x32, 0x39, 0x4A, 0x6C, 0x6F, ++ 0x39, 0x31, 0x67, 0x68, 0x59, 0x50, 0x6C, 0x30, 0x68, 0x41, 0x45, 0x76, 0x72, 0x41, 0x49, 0x74, 0x68, 0x74, 0x4F, 0x67, 0x51, 0x33, 0x70, 0x4F, 0x73, 0x71, 0x54, 0x51, 0x4E, 0x72, 0x6F, 0x42, 0x76, 0x6F, 0x33, 0x62, 0x53, 0x4D, 0x67, 0x48, ++ 0x0A, 0x46, 0x7A, 0x5A, 0x4D, 0x39, 0x4F, 0x36, 0x49, 0x49, 0x38, 0x63, 0x2B, 0x36, 0x7A, 0x66, 0x31, 0x74, 0x52, 0x6E, 0x34, 0x53, 0x57, 0x69, 0x77, 0x33, 0x74, 0x65, 0x35, 0x64, 0x6A, 0x67, 0x64, 0x59, 0x5A, 0x36, 0x6B, 0x2F, 0x6F, 0x49, ++ 0x32, 0x70, 0x65, 0x56, 0x4B, 0x56, 0x75, 0x52, 0x46, 0x34, 0x66, 0x6E, 0x39, 0x74, 0x42, 0x62, 0x36, 0x64, 0x4E, 0x71, 0x63, 0x6D, 0x7A, 0x55, 0x35, 0x4C, 0x2F, 0x71, 0x77, 0x49, 0x46, 0x41, 0x47, 0x62, 0x48, 0x72, 0x51, 0x0A, 0x67, 0x4C, ++ 0x4B, 0x6D, 0x2B, 0x61, 0x2F, 0x73, 0x52, 0x78, 0x6D, 0x50, 0x55, 0x44, 0x67, 0x48, 0x33, 0x4B, 0x4B, 0x48, 0x4F, 0x56, 0x6A, 0x34, 0x75, 0x74, 0x57, 0x70, 0x2B, 0x55, 0x68, 0x6E, 0x4D, 0x4A, 0x62, 0x75, 0x6C, 0x48, 0x68, 0x65, 0x62, 0x34, ++ 0x6D, 0x6A, 0x55, 0x63, 0x41, 0x77, 0x68, 0x6D, 0x61, 0x68, 0x52, 0x57, 0x61, 0x36, 0x56, 0x4F, 0x75, 0x6A, 0x77, 0x35, 0x48, 0x35, 0x53, 0x4E, 0x7A, 0x2F, 0x30, 0x65, 0x67, 0x77, 0x4C, 0x58, 0x30, 0x74, 0x0A, 0x64, 0x48, 0x41, 0x31, 0x31, ++ 0x34, 0x67, 0x6B, 0x39, 0x35, 0x37, 0x45, 0x57, 0x57, 0x36, 0x37, 0x63, 0x34, 0x63, 0x58, 0x38, 0x6A, 0x4A, 0x47, 0x4B, 0x4C, 0x68, 0x44, 0x2B, 0x72, 0x63, 0x64, 0x71, 0x73, 0x71, 0x30, 0x38, 0x70, 0x38, 0x6B, 0x44, 0x69, 0x31, 0x4C, 0x39, ++ 0x33, 0x46, 0x63, 0x58, 0x6D, 0x6E, 0x2F, 0x36, 0x70, 0x55, 0x43, 0x79, 0x7A, 0x69, 0x4B, 0x72, 0x6C, 0x41, 0x34, 0x62, 0x39, 0x76, 0x37, 0x4C, 0x57, 0x49, 0x62, 0x78, 0x63, 0x63, 0x65, 0x0A, 0x56, 0x4F, 0x46, 0x33, 0x34, 0x47, 0x66, 0x49, ++ 0x44, 0x35, 0x79, 0x48, 0x49, 0x39, 0x59, 0x2F, 0x51, 0x43, 0x42, 0x2F, 0x49, 0x49, 0x44, 0x45, 0x67, 0x45, 0x77, 0x2B, 0x4F, 0x79, 0x51, 0x6D, 0x6A, 0x67, 0x53, 0x75, 0x62, 0x4A, 0x72, 0x49, 0x71, 0x67, 0x30, 0x43, 0x41, 0x77, 0x45, 0x41, ++ 0x41, 0x61, 0x4E, 0x43, 0x4D, 0x45, 0x41, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x0A, 0x2F, 0x7A, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, ++ 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x59, 0x59, 0x77, 0x48, 0x51, 0x59, 0x44, 0x56, 0x52, 0x30, 0x4F, 0x42, 0x42, 0x59, 0x45, 0x46, 0x49, 0x51, 0x59, 0x7A, 0x49, 0x55, 0x30, 0x37, 0x4C, 0x77, 0x4D, 0x6C, 0x4A, 0x51, ++ 0x75, 0x43, 0x46, 0x6D, 0x63, 0x78, 0x37, 0x49, 0x51, 0x54, 0x67, 0x6F, 0x49, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x0A, 0x44, 0x51, 0x45, 0x42, 0x43, 0x77, 0x55, 0x41, 0x41, 0x34, 0x49, 0x42, 0x41, 0x51, ++ 0x43, 0x59, 0x38, 0x6A, 0x64, 0x61, 0x51, 0x5A, 0x43, 0x68, 0x47, 0x73, 0x56, 0x32, 0x55, 0x53, 0x67, 0x67, 0x4E, 0x69, 0x4D, 0x4F, 0x72, 0x75, 0x59, 0x6F, 0x75, 0x36, 0x72, 0x34, 0x6C, 0x4B, 0x35, 0x49, 0x70, 0x44, 0x42, 0x2F, 0x47, 0x2F, ++ 0x77, 0x6B, 0x6A, 0x55, 0x75, 0x30, 0x79, 0x4B, 0x47, 0x58, 0x39, 0x72, 0x62, 0x78, 0x65, 0x6E, 0x44, 0x49, 0x55, 0x35, 0x50, 0x4D, 0x0A, 0x43, 0x43, 0x6A, 0x6A, 0x6D, 0x43, 0x58, 0x50, 0x49, 0x36, 0x54, 0x35, 0x33, 0x69, 0x48, 0x54, 0x66, ++ 0x49, 0x55, 0x4A, 0x72, 0x55, 0x36, 0x61, 0x64, 0x54, 0x72, 0x43, 0x43, 0x32, 0x71, 0x4A, 0x65, 0x48, 0x5A, 0x45, 0x52, 0x78, 0x68, 0x6C, 0x62, 0x49, 0x31, 0x42, 0x6A, 0x6A, 0x74, 0x2F, 0x6D, 0x73, 0x76, 0x30, 0x74, 0x61, 0x64, 0x51, 0x31, ++ 0x77, 0x55, 0x73, 0x4E, 0x2B, 0x67, 0x44, 0x53, 0x36, 0x33, 0x70, 0x59, 0x61, 0x41, 0x43, 0x62, 0x76, 0x58, 0x79, 0x0A, 0x38, 0x4D, 0x57, 0x79, 0x37, 0x56, 0x75, 0x33, 0x33, 0x50, 0x71, 0x55, 0x58, 0x48, 0x65, 0x65, 0x45, 0x36, 0x56, 0x2F, ++ 0x55, 0x71, 0x32, 0x56, 0x38, 0x76, 0x69, 0x54, 0x4F, 0x39, 0x36, 0x4C, 0x58, 0x46, 0x76, 0x4B, 0x57, 0x6C, 0x4A, 0x62, 0x59, 0x4B, 0x38, 0x55, 0x39, 0x30, 0x76, 0x76, 0x6F, 0x2F, 0x75, 0x66, 0x51, 0x4A, 0x56, 0x74, 0x4D, 0x56, 0x54, 0x38, ++ 0x51, 0x74, 0x50, 0x48, 0x52, 0x68, 0x38, 0x6A, 0x72, 0x64, 0x6B, 0x50, 0x53, 0x48, 0x43, 0x61, 0x0A, 0x32, 0x58, 0x56, 0x34, 0x63, 0x64, 0x46, 0x79, 0x51, 0x7A, 0x52, 0x31, 0x62, 0x6C, 0x64, 0x5A, 0x77, 0x67, 0x4A, 0x63, 0x4A, 0x6D, 0x41, ++ 0x70, 0x7A, 0x79, 0x4D, 0x5A, 0x46, 0x6F, 0x36, 0x49, 0x51, 0x36, 0x58, 0x55, 0x35, 0x4D, 0x73, 0x49, 0x2B, 0x79, 0x4D, 0x52, 0x51, 0x2B, 0x68, 0x44, 0x4B, 0x58, 0x4A, 0x69, 0x6F, 0x61, 0x6C, 0x64, 0x58, 0x67, 0x6A, 0x55, 0x6B, 0x4B, 0x36, ++ 0x34, 0x32, 0x4D, 0x34, 0x55, 0x77, 0x74, 0x42, 0x56, 0x38, 0x6F, 0x62, 0x32, 0x0A, 0x78, 0x4A, 0x4E, 0x44, 0x64, 0x32, 0x5A, 0x68, 0x77, 0x4C, 0x6E, 0x6F, 0x51, 0x64, 0x65, 0x58, 0x65, 0x47, 0x41, 0x44, 0x62, 0x6B, 0x70, 0x79, 0x72, 0x71, ++ 0x58, 0x52, 0x66, 0x62, 0x6F, 0x51, 0x6E, 0x6F, 0x5A, 0x73, 0x47, 0x34, 0x71, 0x35, 0x57, 0x54, 0x50, 0x34, 0x36, 0x38, 0x53, 0x51, 0x76, 0x76, 0x47, 0x35, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, ++ 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, ++ 0x51, 0x54, 0x43, 0x43, 0x41, 0x79, 0x6D, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x54, 0x42, 0x6D, 0x79, 0x66, 0x30, 0x70, 0x59, 0x31, 0x68, 0x70, 0x38, 0x4B, 0x44, 0x2B, 0x57, 0x47, 0x65, 0x50, 0x68, 0x62, 0x4A, 0x72, 0x75, 0x4B, ++ 0x4E, 0x7A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x77, 0x46, 0x41, 0x44, 0x41, 0x35, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x0A, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, ++ 0x56, 0x55, 0x7A, 0x45, 0x50, 0x4D, 0x41, 0x30, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x47, 0x51, 0x57, 0x31, 0x68, 0x65, 0x6D, 0x39, 0x75, 0x4D, 0x52, 0x6B, 0x77, 0x46, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x42, ++ 0x42, 0x62, 0x57, 0x46, 0x36, 0x62, 0x32, 0x34, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x51, 0x53, 0x41, 0x79, 0x4D, 0x42, 0x34, 0x58, 0x44, 0x54, 0x45, 0x31, 0x0A, 0x4D, 0x44, 0x55, 0x79, 0x4E, 0x6A, 0x41, 0x77, 0x4D, 0x44, ++ 0x41, 0x77, 0x4D, 0x46, 0x6F, 0x58, 0x44, 0x54, 0x51, 0x77, 0x4D, 0x44, 0x55, 0x79, 0x4E, 0x6A, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x46, 0x6F, 0x77, 0x4F, 0x54, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, ++ 0x4D, 0x43, 0x56, 0x56, 0x4D, 0x78, 0x44, 0x7A, 0x41, 0x4E, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x42, 0x6B, 0x46, 0x74, 0x59, 0x58, 0x70, 0x76, 0x0A, 0x62, 0x6A, 0x45, 0x5A, 0x4D, 0x42, 0x63, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, ++ 0x78, 0x4D, 0x51, 0x51, 0x57, 0x31, 0x68, 0x65, 0x6D, 0x39, 0x75, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x67, 0x4D, 0x6A, 0x43, 0x43, 0x41, 0x69, 0x49, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, ++ 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x50, 0x41, 0x44, 0x43, 0x43, 0x41, 0x67, 0x6F, 0x43, 0x0A, 0x67, 0x67, 0x49, 0x42, 0x41, 0x4B, 0x32, 0x57, 0x6E, 0x79, 0x32, 0x63, 0x53, 0x6B, 0x78, 0x4B, ++ 0x67, 0x58, 0x6C, 0x52, 0x6D, 0x65, 0x79, 0x4B, 0x79, 0x32, 0x74, 0x67, 0x55, 0x52, 0x4F, 0x38, 0x54, 0x57, 0x30, 0x47, 0x2F, 0x4C, 0x41, 0x49, 0x6A, 0x64, 0x30, 0x5A, 0x45, 0x47, 0x72, 0x48, 0x4A, 0x67, 0x77, 0x31, 0x32, 0x4D, 0x42, 0x76, ++ 0x49, 0x49, 0x54, 0x70, 0x6C, 0x4C, 0x47, 0x62, 0x68, 0x51, 0x50, 0x44, 0x57, 0x39, 0x74, 0x4B, 0x36, 0x4D, 0x6A, 0x34, 0x0A, 0x6B, 0x48, 0x62, 0x5A, 0x57, 0x30, 0x2F, 0x6A, 0x54, 0x4F, 0x67, 0x47, 0x4E, 0x6B, 0x33, 0x4D, 0x6D, 0x71, 0x77, ++ 0x39, 0x44, 0x4A, 0x41, 0x72, 0x6B, 0x74, 0x51, 0x47, 0x47, 0x57, 0x43, 0x73, 0x4E, 0x30, 0x52, 0x35, 0x68, 0x59, 0x47, 0x43, 0x72, 0x56, 0x6F, 0x33, 0x34, 0x41, 0x33, 0x4D, 0x6E, 0x61, 0x5A, 0x4D, 0x55, 0x6E, 0x62, 0x71, 0x51, 0x35, 0x32, ++ 0x33, 0x42, 0x4E, 0x46, 0x51, 0x39, 0x6C, 0x58, 0x67, 0x31, 0x64, 0x4B, 0x6D, 0x53, 0x59, 0x58, 0x70, 0x0A, 0x4E, 0x2B, 0x6E, 0x4B, 0x66, 0x71, 0x35, 0x63, 0x6C, 0x55, 0x31, 0x49, 0x6D, 0x6A, 0x2B, 0x75, 0x49, 0x46, 0x70, 0x74, 0x69, 0x4A, ++ 0x58, 0x5A, 0x4E, 0x4C, 0x68, 0x53, 0x47, 0x6B, 0x4F, 0x51, 0x73, 0x4C, 0x39, 0x73, 0x42, 0x62, 0x6D, 0x32, 0x65, 0x4C, 0x66, 0x71, 0x30, 0x4F, 0x51, 0x36, 0x50, 0x42, 0x4A, 0x54, 0x59, 0x76, 0x39, 0x4B, 0x38, 0x6E, 0x75, 0x2B, 0x4E, 0x51, ++ 0x57, 0x70, 0x45, 0x6A, 0x54, 0x6A, 0x38, 0x32, 0x52, 0x30, 0x59, 0x69, 0x77, 0x39, 0x0A, 0x41, 0x45, 0x6C, 0x61, 0x4B, 0x50, 0x34, 0x79, 0x52, 0x4C, 0x75, 0x48, 0x33, 0x57, 0x55, 0x6E, 0x41, 0x6E, 0x45, 0x37, 0x32, 0x6B, 0x72, 0x33, 0x48, ++ 0x39, 0x72, 0x4E, 0x39, 0x79, 0x46, 0x56, 0x6B, 0x45, 0x38, 0x50, 0x37, 0x4B, 0x36, 0x43, 0x34, 0x5A, 0x39, 0x72, 0x32, 0x55, 0x58, 0x54, 0x75, 0x2F, 0x42, 0x66, 0x68, 0x2B, 0x30, 0x38, 0x4C, 0x44, 0x6D, 0x47, 0x32, 0x6A, 0x2F, 0x65, 0x37, ++ 0x48, 0x4A, 0x56, 0x36, 0x33, 0x6D, 0x6A, 0x72, 0x64, 0x76, 0x64, 0x0A, 0x66, 0x4C, 0x43, 0x36, 0x48, 0x4D, 0x37, 0x38, 0x33, 0x6B, 0x38, 0x31, 0x64, 0x73, 0x38, 0x50, 0x2B, 0x48, 0x67, 0x66, 0x61, 0x6A, 0x5A, 0x52, 0x52, 0x69, 0x64, 0x68, ++ 0x57, 0x2B, 0x6D, 0x65, 0x7A, 0x2F, 0x43, 0x69, 0x56, 0x58, 0x31, 0x38, 0x4A, 0x59, 0x70, 0x76, 0x4C, 0x37, 0x54, 0x46, 0x7A, 0x34, 0x51, 0x75, 0x4B, 0x2F, 0x30, 0x4E, 0x55, 0x52, 0x42, 0x73, 0x2B, 0x31, 0x38, 0x62, 0x76, 0x42, 0x74, 0x2B, ++ 0x78, 0x61, 0x34, 0x37, 0x6D, 0x41, 0x45, 0x78, 0x0A, 0x6B, 0x76, 0x38, 0x4C, 0x56, 0x2F, 0x53, 0x61, 0x73, 0x72, 0x6C, 0x58, 0x36, 0x61, 0x76, 0x76, 0x44, 0x58, 0x62, 0x52, 0x38, 0x4F, 0x37, 0x30, 0x7A, 0x6F, 0x61, 0x6E, 0x34, 0x47, 0x37, ++ 0x70, 0x74, 0x47, 0x6D, 0x68, 0x33, 0x32, 0x6E, 0x32, 0x4D, 0x38, 0x5A, 0x70, 0x4C, 0x70, 0x63, 0x54, 0x6E, 0x71, 0x57, 0x48, 0x73, 0x46, 0x63, 0x51, 0x67, 0x54, 0x66, 0x4A, 0x55, 0x37, 0x4F, 0x37, 0x66, 0x2F, 0x61, 0x53, 0x30, 0x5A, 0x7A, ++ 0x51, 0x47, 0x50, 0x53, 0x53, 0x0A, 0x62, 0x74, 0x71, 0x44, 0x54, 0x36, 0x5A, 0x6A, 0x6D, 0x55, 0x79, 0x6C, 0x2B, 0x31, 0x37, 0x76, 0x49, 0x57, 0x52, 0x36, 0x49, 0x46, 0x39, 0x73, 0x5A, 0x49, 0x55, 0x56, 0x79, 0x7A, 0x66, 0x70, 0x59, 0x67, ++ 0x77, 0x4C, 0x4B, 0x68, 0x62, 0x63, 0x41, 0x53, 0x34, 0x79, 0x32, 0x6A, 0x35, 0x4C, 0x39, 0x5A, 0x34, 0x36, 0x39, 0x68, 0x64, 0x41, 0x6C, 0x4F, 0x2B, 0x65, 0x6B, 0x51, 0x69, 0x47, 0x2B, 0x72, 0x35, 0x6A, 0x71, 0x46, 0x6F, 0x7A, 0x37, 0x4D, ++ 0x74, 0x30, 0x0A, 0x51, 0x35, 0x58, 0x35, 0x62, 0x47, 0x6C, 0x53, 0x4E, 0x73, 0x63, 0x70, 0x62, 0x2F, 0x78, 0x56, 0x41, 0x31, 0x77, 0x66, 0x2B, 0x35, 0x2B, 0x39, 0x52, 0x2B, 0x76, 0x6E, 0x53, 0x55, 0x65, 0x56, 0x43, 0x30, 0x36, 0x4A, 0x49, ++ 0x67, 0x6C, 0x4A, 0x34, 0x50, 0x56, 0x68, 0x48, 0x76, 0x47, 0x2F, 0x4C, 0x6F, 0x70, 0x79, 0x62, 0x6F, 0x42, 0x5A, 0x2F, 0x31, 0x63, 0x36, 0x2B, 0x58, 0x55, 0x79, 0x6F, 0x30, 0x35, 0x66, 0x37, 0x4F, 0x30, 0x6F, 0x59, 0x74, 0x6C, 0x4E, 0x0A, ++ 0x63, 0x2F, 0x4C, 0x4D, 0x67, 0x52, 0x64, 0x67, 0x37, 0x63, 0x33, 0x72, 0x33, 0x4E, 0x75, 0x6E, 0x79, 0x73, 0x56, 0x2B, 0x41, 0x72, 0x33, 0x79, 0x56, 0x41, 0x68, 0x55, 0x2F, 0x62, 0x51, 0x74, 0x43, 0x53, 0x77, 0x58, 0x56, 0x45, 0x71, 0x59, ++ 0x30, 0x56, 0x54, 0x68, 0x55, 0x57, 0x63, 0x49, 0x30, 0x75, 0x31, 0x75, 0x66, 0x6D, 0x38, 0x2F, 0x30, 0x69, 0x32, 0x42, 0x57, 0x53, 0x6C, 0x6D, 0x79, 0x35, 0x41, 0x35, 0x6C, 0x52, 0x45, 0x65, 0x64, 0x43, 0x66, 0x2B, 0x0A, 0x33, 0x65, 0x75, ++ 0x76, 0x41, 0x67, 0x4D, 0x42, 0x41, 0x41, 0x47, 0x6A, 0x51, 0x6A, 0x42, 0x41, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x44, 0x67, 0x59, ++ 0x44, 0x56, 0x52, 0x30, 0x50, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x51, 0x44, 0x41, 0x67, 0x47, 0x47, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x53, 0x77, 0x0A, 0x44, 0x50, 0x42, 0x4D, 0x4D, 0x50, ++ 0x51, 0x46, 0x57, 0x41, 0x4A, 0x49, 0x2F, 0x54, 0x50, 0x6C, 0x55, 0x71, 0x39, 0x4C, 0x68, 0x4F, 0x4E, 0x6D, 0x55, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x77, 0x46, 0x41, 0x41, ++ 0x4F, 0x43, 0x41, 0x67, 0x45, 0x41, 0x71, 0x71, 0x69, 0x41, 0x6A, 0x77, 0x35, 0x34, 0x6F, 0x2B, 0x43, 0x69, 0x31, 0x4D, 0x33, 0x6D, 0x39, 0x5A, 0x68, 0x36, 0x4F, 0x2B, 0x6F, 0x41, 0x0A, 0x41, 0x37, 0x43, 0x58, 0x44, 0x70, 0x4F, 0x38, 0x57, ++ 0x71, 0x6A, 0x32, 0x4C, 0x49, 0x78, 0x79, 0x68, 0x36, 0x6D, 0x78, 0x2F, 0x48, 0x39, 0x7A, 0x2F, 0x57, 0x4E, 0x78, 0x65, 0x4B, 0x57, 0x48, 0x57, 0x63, 0x38, 0x77, 0x34, 0x51, 0x30, 0x51, 0x73, 0x68, 0x4E, 0x61, 0x62, 0x59, 0x4C, 0x31, 0x61, ++ 0x75, 0x61, 0x41, 0x6E, 0x36, 0x41, 0x46, 0x43, 0x32, 0x6A, 0x6B, 0x52, 0x32, 0x76, 0x48, 0x61, 0x74, 0x2B, 0x32, 0x2F, 0x58, 0x63, 0x79, 0x63, 0x75, 0x55, 0x59, 0x0A, 0x2B, 0x67, 0x6E, 0x30, 0x6F, 0x4A, 0x4D, 0x73, 0x58, 0x64, 0x4B, 0x4D, ++ 0x64, 0x59, 0x56, 0x32, 0x5A, 0x5A, 0x41, 0x4D, 0x41, 0x33, 0x6D, 0x33, 0x4D, 0x53, 0x4E, 0x6A, 0x72, 0x58, 0x69, 0x44, 0x43, 0x59, 0x5A, 0x6F, 0x68, 0x4D, 0x72, 0x2F, 0x2B, 0x63, 0x38, 0x6D, 0x6D, 0x70, 0x4A, 0x35, 0x35, 0x38, 0x31, 0x4C, ++ 0x78, 0x65, 0x64, 0x68, 0x70, 0x78, 0x66, 0x4C, 0x38, 0x36, 0x6B, 0x53, 0x6B, 0x35, 0x4E, 0x72, 0x70, 0x2B, 0x67, 0x76, 0x55, 0x35, 0x4C, 0x45, 0x0A, 0x59, 0x46, 0x69, 0x77, 0x7A, 0x41, 0x4A, 0x52, 0x47, 0x46, 0x75, 0x46, 0x6A, 0x57, 0x4A, ++ 0x5A, 0x59, 0x37, 0x61, 0x74, 0x74, 0x4E, 0x36, 0x61, 0x2B, 0x79, 0x62, 0x33, 0x41, 0x43, 0x66, 0x41, 0x58, 0x56, 0x55, 0x33, 0x64, 0x4A, 0x6E, 0x4A, 0x55, 0x48, 0x2F, 0x6A, 0x57, 0x53, 0x35, 0x45, 0x34, 0x79, 0x77, 0x6C, 0x37, 0x75, 0x78, ++ 0x4D, 0x4D, 0x6E, 0x65, 0x30, 0x6E, 0x78, 0x72, 0x70, 0x53, 0x31, 0x30, 0x67, 0x78, 0x64, 0x72, 0x39, 0x48, 0x49, 0x63, 0x57, 0x0A, 0x78, 0x6B, 0x50, 0x6F, 0x31, 0x4C, 0x73, 0x6D, 0x6D, 0x6B, 0x56, 0x77, 0x58, 0x71, 0x6B, 0x4C, 0x4E, 0x31, ++ 0x50, 0x69, 0x52, 0x6E, 0x73, 0x6E, 0x2F, 0x65, 0x42, 0x47, 0x38, 0x6F, 0x6D, 0x33, 0x7A, 0x45, 0x4B, 0x32, 0x79, 0x79, 0x67, 0x6D, 0x62, 0x74, 0x6D, 0x6C, 0x79, 0x54, 0x72, 0x49, 0x51, 0x52, 0x4E, 0x67, 0x39, 0x31, 0x43, 0x4D, 0x46, 0x61, ++ 0x36, 0x79, 0x62, 0x52, 0x6F, 0x56, 0x47, 0x6C, 0x64, 0x34, 0x35, 0x70, 0x49, 0x71, 0x32, 0x57, 0x57, 0x51, 0x0A, 0x67, 0x6A, 0x39, 0x73, 0x41, 0x71, 0x2B, 0x75, 0x45, 0x6A, 0x6F, 0x6E, 0x6C, 0x6A, 0x59, 0x45, 0x31, 0x78, 0x32, 0x69, 0x67, ++ 0x47, 0x4F, 0x70, 0x6D, 0x2F, 0x48, 0x6C, 0x75, 0x72, 0x52, 0x38, 0x46, 0x4C, 0x42, 0x4F, 0x79, 0x62, 0x45, 0x66, 0x64, 0x46, 0x38, 0x34, 0x39, 0x6C, 0x48, 0x71, 0x6D, 0x2F, 0x6F, 0x73, 0x6F, 0x68, 0x48, 0x55, 0x71, 0x53, 0x30, 0x6E, 0x47, ++ 0x6B, 0x57, 0x78, 0x72, 0x37, 0x4A, 0x4F, 0x63, 0x51, 0x33, 0x41, 0x57, 0x45, 0x62, 0x57, 0x0A, 0x61, 0x51, 0x62, 0x4C, 0x55, 0x38, 0x75, 0x7A, 0x2F, 0x6D, 0x74, 0x42, 0x7A, 0x55, 0x46, 0x2B, 0x66, 0x55, 0x77, 0x50, 0x66, 0x48, 0x4A, 0x35, ++ 0x65, 0x6C, 0x6E, 0x4E, 0x58, 0x6B, 0x6F, 0x4F, 0x72, 0x4A, 0x75, 0x70, 0x6D, 0x48, 0x4E, 0x35, 0x66, 0x4C, 0x54, 0x30, 0x7A, 0x4C, 0x6D, 0x34, 0x42, 0x77, 0x79, 0x79, 0x64, 0x46, 0x79, 0x34, 0x78, 0x32, 0x2B, 0x49, 0x6F, 0x5A, 0x43, 0x6E, ++ 0x39, 0x4B, 0x72, 0x35, 0x76, 0x32, 0x63, 0x36, 0x39, 0x42, 0x6F, 0x56, 0x0A, 0x59, 0x68, 0x36, 0x33, 0x6E, 0x37, 0x34, 0x39, 0x73, 0x53, 0x6D, 0x76, 0x5A, 0x36, 0x45, 0x53, 0x38, 0x6C, 0x67, 0x51, 0x47, 0x56, 0x4D, 0x44, 0x4D, 0x42, 0x75, ++ 0x34, 0x47, 0x6F, 0x6E, 0x32, 0x6E, 0x4C, 0x32, 0x58, 0x41, 0x34, 0x36, 0x6A, 0x43, 0x66, 0x4D, 0x64, 0x69, 0x79, 0x48, 0x78, 0x74, 0x4E, 0x2F, 0x6B, 0x48, 0x4E, 0x47, 0x66, 0x5A, 0x51, 0x49, 0x47, 0x36, 0x6C, 0x7A, 0x57, 0x45, 0x37, 0x4F, ++ 0x45, 0x37, 0x36, 0x4B, 0x6C, 0x58, 0x49, 0x78, 0x33, 0x0A, 0x4B, 0x61, 0x64, 0x6F, 0x77, 0x47, 0x75, 0x75, 0x51, 0x4E, 0x4B, 0x6F, 0x74, 0x4F, 0x72, 0x4E, 0x38, 0x49, 0x31, 0x4C, 0x4F, 0x4A, 0x77, 0x5A, 0x6D, 0x68, 0x73, 0x6F, 0x56, 0x4C, ++ 0x69, 0x4A, 0x6B, 0x4F, 0x2F, 0x4B, 0x64, 0x59, 0x45, 0x2B, 0x48, 0x76, 0x4A, 0x6B, 0x4A, 0x4D, 0x63, 0x59, 0x72, 0x30, 0x37, 0x2F, 0x52, 0x35, 0x34, 0x48, 0x39, 0x6A, 0x56, 0x6C, 0x70, 0x4E, 0x4D, 0x4B, 0x56, 0x76, 0x2F, 0x31, 0x46, 0x32, ++ 0x52, 0x73, 0x37, 0x36, 0x67, 0x69, 0x0A, 0x4A, 0x55, 0x6D, 0x54, 0x74, 0x74, 0x38, 0x41, 0x46, 0x39, 0x70, 0x59, 0x66, 0x6C, 0x33, 0x75, 0x78, 0x52, 0x75, 0x77, 0x30, 0x64, 0x46, 0x66, 0x49, 0x52, 0x44, 0x48, 0x2B, 0x66, 0x4F, 0x36, 0x41, ++ 0x67, 0x6F, 0x6E, 0x42, 0x38, 0x58, 0x78, 0x31, 0x73, 0x66, 0x54, 0x34, 0x50, 0x73, 0x4A, 0x59, 0x47, 0x77, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, ++ 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x42, 0x74, 0x6A, 0x43, 0x43, 0x41, 0x56, 0x75, ++ 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x54, 0x42, 0x6D, 0x79, 0x66, 0x31, 0x58, 0x53, 0x58, 0x4E, 0x6D, 0x59, 0x2F, 0x4F, 0x77, 0x75, 0x61, 0x32, 0x65, 0x69, 0x65, 0x64, 0x67, 0x50, 0x79, 0x53, 0x6A, 0x41, 0x4B, 0x42, 0x67, 0x67, ++ 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x6A, 0x41, 0x35, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x0A, 0x45, 0x77, 0x4A, 0x56, 0x55, 0x7A, 0x45, 0x50, 0x4D, 0x41, 0x30, 0x47, 0x41, 0x31, ++ 0x55, 0x45, 0x43, 0x68, 0x4D, 0x47, 0x51, 0x57, 0x31, 0x68, 0x65, 0x6D, 0x39, 0x75, 0x4D, 0x52, 0x6B, 0x77, 0x46, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x42, 0x42, 0x62, 0x57, 0x46, 0x36, 0x62, 0x32, 0x34, 0x67, 0x55, 0x6D, ++ 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x51, 0x53, 0x41, 0x7A, 0x4D, 0x42, 0x34, 0x58, 0x44, 0x54, 0x45, 0x31, 0x4D, 0x44, 0x55, 0x79, 0x0A, 0x4E, 0x6A, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x46, 0x6F, 0x58, 0x44, 0x54, 0x51, 0x77, 0x4D, ++ 0x44, 0x55, 0x79, 0x4E, 0x6A, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x46, 0x6F, 0x77, 0x4F, 0x54, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x56, 0x56, 0x4D, 0x78, 0x44, 0x7A, 0x41, 0x4E, 0x42, ++ 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x42, 0x6B, 0x46, 0x74, 0x59, 0x58, 0x70, 0x76, 0x62, 0x6A, 0x45, 0x5A, 0x0A, 0x4D, 0x42, 0x63, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x51, 0x51, 0x57, 0x31, 0x68, 0x65, 0x6D, 0x39, 0x75, ++ 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x67, 0x4D, 0x7A, 0x42, 0x5A, 0x4D, 0x42, 0x4D, 0x47, 0x42, 0x79, 0x71, 0x47, 0x53, 0x4D, 0x34, 0x39, 0x41, 0x67, 0x45, 0x47, 0x43, 0x43, 0x71, 0x47, 0x53, 0x4D, 0x34, 0x39, ++ 0x41, 0x77, 0x45, 0x48, 0x41, 0x30, 0x49, 0x41, 0x42, 0x43, 0x6D, 0x58, 0x70, 0x38, 0x5A, 0x42, 0x0A, 0x66, 0x38, 0x41, 0x4E, 0x6D, 0x2B, 0x67, 0x42, 0x47, 0x31, 0x62, 0x47, 0x38, 0x6C, 0x4B, 0x6C, 0x75, 0x69, 0x32, 0x79, 0x45, 0x75, 0x6A, ++ 0x53, 0x4C, 0x74, 0x66, 0x36, 0x79, 0x63, 0x58, 0x59, 0x71, 0x6D, 0x30, 0x66, 0x63, 0x34, 0x45, 0x37, 0x4F, 0x35, 0x68, 0x72, 0x4F, 0x58, 0x77, 0x7A, 0x70, 0x63, 0x56, 0x4F, 0x68, 0x6F, 0x36, 0x41, 0x46, 0x32, 0x68, 0x69, 0x52, 0x56, 0x64, ++ 0x39, 0x52, 0x46, 0x67, 0x64, 0x73, 0x7A, 0x66, 0x6C, 0x5A, 0x77, 0x6A, 0x72, 0x0A, 0x5A, 0x74, 0x36, 0x6A, 0x51, 0x6A, 0x42, 0x41, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, ++ 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x51, 0x44, 0x41, 0x67, 0x47, 0x47, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, ++ 0x53, 0x72, 0x74, 0x74, 0x76, 0x58, 0x42, 0x70, 0x34, 0x33, 0x0A, 0x72, 0x44, 0x43, 0x47, 0x42, 0x35, 0x46, 0x77, 0x78, 0x35, 0x7A, 0x45, 0x47, 0x62, 0x46, 0x34, 0x77, 0x44, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, ++ 0x51, 0x51, 0x44, 0x41, 0x67, 0x4E, 0x4A, 0x41, 0x44, 0x42, 0x47, 0x41, 0x69, 0x45, 0x41, 0x34, 0x49, 0x57, 0x53, 0x6F, 0x78, 0x65, 0x33, 0x6A, 0x66, 0x6B, 0x72, 0x42, 0x71, 0x57, 0x54, 0x72, 0x42, 0x71, 0x59, 0x61, 0x47, 0x46, 0x79, 0x2B, ++ 0x75, 0x47, 0x68, 0x30, 0x50, 0x73, 0x63, 0x0A, 0x65, 0x47, 0x43, 0x6D, 0x51, 0x35, 0x6E, 0x46, 0x75, 0x4D, 0x51, 0x43, 0x49, 0x51, 0x43, 0x63, 0x41, 0x75, 0x2F, 0x78, 0x6C, 0x4A, 0x79, 0x7A, 0x6C, 0x76, 0x6E, 0x72, 0x78, 0x69, 0x72, 0x34, ++ 0x74, 0x69, 0x7A, 0x2B, 0x4F, 0x70, 0x41, 0x55, 0x46, 0x74, 0x65, 0x4D, 0x59, 0x79, 0x52, 0x49, 0x48, 0x4E, 0x38, 0x77, 0x66, 0x64, 0x56, 0x6F, 0x4F, 0x77, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, ++ 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x34, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, ++ 0x49, 0x42, 0x38, 0x6A, 0x43, 0x43, 0x41, 0x58, 0x69, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x54, 0x42, 0x6D, 0x79, 0x66, 0x31, 0x38, 0x47, 0x37, 0x45, 0x45, 0x77, 0x70, 0x51, 0x2B, 0x56, 0x78, 0x65, 0x33, 0x73, 0x73, 0x79, 0x42, ++ 0x72, 0x42, 0x44, 0x6A, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x7A, 0x41, 0x35, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x0A, 0x45, 0x77, 0x4A, 0x56, 0x55, ++ 0x7A, 0x45, 0x50, 0x4D, 0x41, 0x30, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x47, 0x51, 0x57, 0x31, 0x68, 0x65, 0x6D, 0x39, 0x75, 0x4D, 0x52, 0x6B, 0x77, 0x46, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x42, 0x42, 0x62, ++ 0x57, 0x46, 0x36, 0x62, 0x32, 0x34, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x51, 0x53, 0x41, 0x30, 0x4D, 0x42, 0x34, 0x58, 0x44, 0x54, 0x45, 0x31, 0x4D, 0x44, 0x55, 0x79, 0x0A, 0x4E, 0x6A, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, ++ 0x4D, 0x46, 0x6F, 0x58, 0x44, 0x54, 0x51, 0x77, 0x4D, 0x44, 0x55, 0x79, 0x4E, 0x6A, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x46, 0x6F, 0x77, 0x4F, 0x54, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, ++ 0x56, 0x56, 0x4D, 0x78, 0x44, 0x7A, 0x41, 0x4E, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x42, 0x6B, 0x46, 0x74, 0x59, 0x58, 0x70, 0x76, 0x62, 0x6A, 0x45, 0x5A, 0x0A, 0x4D, 0x42, 0x63, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, ++ 0x51, 0x51, 0x57, 0x31, 0x68, 0x65, 0x6D, 0x39, 0x75, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x67, 0x4E, 0x44, 0x42, 0x32, 0x4D, 0x42, 0x41, 0x47, 0x42, 0x79, 0x71, 0x47, 0x53, 0x4D, 0x34, 0x39, 0x41, 0x67, 0x45, ++ 0x47, 0x42, 0x53, 0x75, 0x42, 0x42, 0x41, 0x41, 0x69, 0x41, 0x32, 0x49, 0x41, 0x42, 0x4E, 0x4B, 0x72, 0x69, 0x6A, 0x64, 0x50, 0x6F, 0x31, 0x4D, 0x4E, 0x0A, 0x2F, 0x73, 0x47, 0x4B, 0x65, 0x30, 0x75, 0x6F, 0x65, 0x30, 0x5A, 0x4C, 0x59, 0x37, ++ 0x42, 0x69, 0x39, 0x69, 0x30, 0x62, 0x32, 0x77, 0x68, 0x78, 0x49, 0x64, 0x49, 0x41, 0x36, 0x47, 0x4F, 0x39, 0x6D, 0x69, 0x66, 0x37, 0x38, 0x44, 0x6C, 0x75, 0x58, 0x65, 0x6F, 0x39, 0x70, 0x63, 0x6D, 0x42, 0x71, 0x71, 0x4E, 0x62, 0x49, 0x4A, ++ 0x68, 0x46, 0x58, 0x52, 0x62, 0x62, 0x2F, 0x65, 0x67, 0x51, 0x62, 0x65, 0x4F, 0x63, 0x34, 0x4F, 0x4F, 0x39, 0x58, 0x34, 0x52, 0x69, 0x0A, 0x38, 0x33, 0x42, 0x6B, 0x4D, 0x36, 0x44, 0x4C, 0x4A, 0x43, 0x39, 0x77, 0x75, 0x6F, 0x69, 0x68, 0x4B, ++ 0x71, 0x42, 0x31, 0x2B, 0x49, 0x47, 0x75, 0x59, 0x67, 0x62, 0x45, 0x67, 0x64, 0x73, 0x35, 0x62, 0x69, 0x6D, 0x77, 0x48, 0x76, 0x6F, 0x75, 0x58, 0x4B, 0x4E, 0x43, 0x4D, 0x45, 0x41, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, ++ 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x0A, 0x48, 0x51, 0x38, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x59, 0x59, 0x77, 0x48, 0x51, 0x59, 0x44, ++ 0x56, 0x52, 0x30, 0x4F, 0x42, 0x42, 0x59, 0x45, 0x46, 0x4E, 0x50, 0x73, 0x78, 0x7A, 0x70, 0x6C, 0x62, 0x73, 0x7A, 0x68, 0x32, 0x6E, 0x61, 0x61, 0x56, 0x76, 0x75, 0x63, 0x38, 0x34, 0x5A, 0x74, 0x56, 0x2B, 0x57, 0x42, 0x4D, 0x41, 0x6F, 0x47, ++ 0x43, 0x43, 0x71, 0x47, 0x53, 0x4D, 0x34, 0x39, 0x42, 0x41, 0x4D, 0x44, 0x41, 0x32, 0x67, 0x41, 0x0A, 0x4D, 0x47, 0x55, 0x43, 0x4D, 0x44, 0x71, 0x4C, 0x49, 0x66, 0x47, 0x39, 0x66, 0x68, 0x47, 0x74, 0x30, 0x4F, 0x39, 0x59, 0x6C, 0x69, 0x2F, ++ 0x57, 0x36, 0x35, 0x31, 0x2B, 0x6B, 0x49, 0x30, 0x72, 0x7A, 0x32, 0x5A, 0x56, 0x77, 0x79, 0x7A, 0x6A, 0x4B, 0x4B, 0x6C, 0x77, 0x43, 0x6B, 0x63, 0x4F, 0x38, 0x44, 0x64, 0x5A, 0x45, 0x76, 0x38, 0x74, 0x6D, 0x5A, 0x51, 0x6F, 0x54, 0x69, 0x70, ++ 0x50, 0x4E, 0x55, 0x30, 0x7A, 0x57, 0x67, 0x49, 0x78, 0x41, 0x4F, 0x70, 0x31, 0x0A, 0x41, 0x45, 0x34, 0x37, 0x78, 0x44, 0x71, 0x55, 0x45, 0x70, 0x48, 0x4A, 0x57, 0x45, 0x61, 0x64, 0x49, 0x52, 0x4E, 0x79, 0x70, 0x34, 0x69, 0x63, 0x69, 0x75, ++ 0x52, 0x4D, 0x53, 0x74, 0x75, 0x57, 0x31, 0x4B, 0x79, 0x4C, 0x61, 0x32, 0x74, 0x4A, 0x45, 0x6C, 0x4D, 0x7A, 0x72, 0x64, 0x66, 0x6B, 0x76, 0x69, 0x54, 0x38, 0x74, 0x51, 0x70, 0x32, 0x31, 0x4B, 0x57, 0x38, 0x45, 0x41, 0x3D, 0x3D, 0x0A, 0x2D, ++ 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x54, 0x55, 0x42, 0x49, 0x54, 0x41, 0x4B, 0x20, 0x4B, 0x61, 0x6D, 0x75, 0x20, 0x53, ++ 0x4D, 0x20, 0x53, 0x53, 0x4C, 0x20, 0x4B, 0x6F, 0x6B, 0x20, 0x53, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x6B, 0x61, 0x73, 0x69, 0x20, 0x2D, 0x20, 0x53, 0x75, 0x72, 0x75, 0x6D, 0x20, 0x31, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, ++ 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x45, 0x59, 0x7A, 0x43, 0x43, 0x41, 0x30, 0x75, 0x67, 0x41, 0x77, ++ 0x49, 0x42, 0x41, 0x67, 0x49, 0x42, 0x41, 0x54, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x44, 0x43, 0x42, 0x30, 0x6A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, ++ 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x56, 0x46, 0x49, 0x78, 0x47, 0x44, 0x41, 0x57, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x63, 0x54, 0x0A, 0x44, 0x30, 0x64, 0x6C, 0x59, 0x6E, 0x70, 0x6C, 0x49, 0x43, 0x30, 0x67, 0x53, 0x32, 0x39, 0x6A, 0x59, ++ 0x57, 0x56, 0x73, 0x61, 0x54, 0x46, 0x43, 0x4D, 0x45, 0x41, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x35, 0x56, 0x48, 0x56, 0x79, 0x61, 0x32, 0x6C, 0x35, 0x5A, 0x53, 0x42, 0x43, 0x61, 0x57, 0x78, 0x70, 0x62, 0x58, 0x4E, 0x6C, 0x62, ++ 0x43, 0x42, 0x32, 0x5A, 0x53, 0x42, 0x55, 0x5A, 0x57, 0x74, 0x75, 0x62, 0x32, 0x78, 0x76, 0x61, 0x6D, 0x6C, 0x72, 0x0A, 0x49, 0x45, 0x46, 0x79, 0x59, 0x58, 0x4E, 0x30, 0x61, 0x58, 0x4A, 0x74, 0x59, 0x53, 0x42, 0x4C, 0x64, 0x58, 0x4A, 0x31, ++ 0x62, 0x58, 0x55, 0x67, 0x4C, 0x53, 0x42, 0x55, 0x56, 0x55, 0x4A, 0x4A, 0x56, 0x45, 0x46, 0x4C, 0x4D, 0x53, 0x30, 0x77, 0x4B, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4C, 0x45, 0x79, 0x52, 0x4C, 0x59, 0x57, 0x31, 0x31, 0x49, 0x46, 0x4E, 0x6C, ++ 0x63, 0x6E, 0x52, 0x70, 0x5A, 0x6D, 0x6C, 0x72, 0x59, 0x58, 0x4E, 0x35, 0x62, 0x32, 0x34, 0x67, 0x0A, 0x54, 0x57, 0x56, 0x79, 0x61, 0x32, 0x56, 0x36, 0x61, 0x53, 0x41, 0x74, 0x49, 0x45, 0x74, 0x68, 0x62, 0x58, 0x55, 0x67, 0x55, 0x30, 0x30, ++ 0x78, 0x4E, 0x6A, 0x41, 0x30, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x4C, 0x56, 0x52, 0x56, 0x51, 0x6B, 0x6C, 0x55, 0x51, 0x55, 0x73, 0x67, 0x53, 0x32, 0x46, 0x74, 0x64, 0x53, 0x42, 0x54, 0x54, 0x53, 0x42, 0x54, 0x55, 0x30, 0x77, ++ 0x67, 0x53, 0x32, 0x39, 0x72, 0x49, 0x46, 0x4E, 0x6C, 0x63, 0x6E, 0x52, 0x70, 0x0A, 0x5A, 0x6D, 0x6C, 0x72, 0x59, 0x58, 0x4E, 0x70, 0x49, 0x43, 0x30, 0x67, 0x55, 0x33, 0x56, 0x79, 0x64, 0x57, 0x30, 0x67, 0x4D, 0x54, 0x41, 0x65, 0x46, 0x77, ++ 0x30, 0x78, 0x4D, 0x7A, 0x45, 0x78, 0x4D, 0x6A, 0x55, 0x77, 0x4F, 0x44, 0x49, 0x31, 0x4E, 0x54, 0x56, 0x61, 0x46, 0x77, 0x30, 0x30, 0x4D, 0x7A, 0x45, 0x77, 0x4D, 0x6A, 0x55, 0x77, 0x4F, 0x44, 0x49, 0x31, 0x4E, 0x54, 0x56, 0x61, 0x4D, 0x49, ++ 0x48, 0x53, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x0A, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x55, 0x55, 0x6A, 0x45, 0x59, 0x4D, 0x42, 0x59, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x78, 0x4D, 0x50, 0x52, 0x32, 0x56, 0x69, 0x65, ++ 0x6D, 0x55, 0x67, 0x4C, 0x53, 0x42, 0x4C, 0x62, 0x32, 0x4E, 0x68, 0x5A, 0x57, 0x78, 0x70, 0x4D, 0x55, 0x49, 0x77, 0x51, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x45, 0x7A, 0x6C, 0x55, 0x64, 0x58, 0x4A, 0x72, 0x61, 0x58, 0x6C, 0x6C, 0x49, ++ 0x45, 0x4A, 0x70, 0x62, 0x47, 0x6C, 0x74, 0x0A, 0x63, 0x32, 0x56, 0x73, 0x49, 0x48, 0x5A, 0x6C, 0x49, 0x46, 0x52, 0x6C, 0x61, 0x32, 0x35, 0x76, 0x62, 0x47, 0x39, 0x71, 0x61, 0x57, 0x73, 0x67, 0x51, 0x58, 0x4A, 0x68, 0x63, 0x33, 0x52, 0x70, ++ 0x63, 0x6D, 0x31, 0x68, 0x49, 0x45, 0x74, 0x31, 0x63, 0x6E, 0x56, 0x74, 0x64, 0x53, 0x41, 0x74, 0x49, 0x46, 0x52, 0x56, 0x51, 0x6B, 0x6C, 0x55, 0x51, 0x55, 0x73, 0x78, 0x4C, 0x54, 0x41, 0x72, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x73, 0x54, ++ 0x4A, 0x45, 0x74, 0x68, 0x0A, 0x62, 0x58, 0x55, 0x67, 0x55, 0x32, 0x56, 0x79, 0x64, 0x47, 0x6C, 0x6D, 0x61, 0x57, 0x74, 0x68, 0x63, 0x33, 0x6C, 0x76, 0x62, 0x69, 0x42, 0x4E, 0x5A, 0x58, 0x4A, 0x72, 0x5A, 0x58, 0x70, 0x70, 0x49, 0x43, 0x30, ++ 0x67, 0x53, 0x32, 0x46, 0x74, 0x64, 0x53, 0x42, 0x54, 0x54, 0x54, 0x45, 0x32, 0x4D, 0x44, 0x51, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x74, 0x56, 0x46, 0x56, 0x43, 0x53, 0x56, 0x52, 0x42, 0x53, 0x79, 0x42, 0x4C, 0x59, 0x57, 0x31, ++ 0x31, 0x0A, 0x49, 0x46, 0x4E, 0x4E, 0x49, 0x46, 0x4E, 0x54, 0x54, 0x43, 0x42, 0x4C, 0x62, 0x32, 0x73, 0x67, 0x55, 0x32, 0x56, 0x79, 0x64, 0x47, 0x6C, 0x6D, 0x61, 0x57, 0x74, 0x68, 0x63, 0x32, 0x6B, 0x67, 0x4C, 0x53, 0x42, 0x54, 0x64, 0x58, ++ 0x4A, 0x31, 0x62, 0x53, 0x41, 0x78, 0x4D, 0x49, 0x49, 0x42, 0x49, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x45, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x51, 0x38, 0x41, 0x0A, 0x4D, ++ 0x49, 0x49, 0x42, 0x43, 0x67, 0x4B, 0x43, 0x41, 0x51, 0x45, 0x41, 0x72, 0x33, 0x55, 0x77, 0x4D, 0x36, 0x71, 0x37, 0x61, 0x39, 0x4F, 0x5A, 0x4C, 0x42, 0x49, 0x33, 0x68, 0x4E, 0x6D, 0x4E, 0x65, 0x35, 0x65, 0x41, 0x30, 0x32, 0x37, 0x6E, 0x2F, ++ 0x35, 0x74, 0x51, 0x6C, 0x54, 0x36, 0x51, 0x6C, 0x56, 0x5A, 0x43, 0x31, 0x78, 0x6C, 0x38, 0x4A, 0x6F, 0x53, 0x4E, 0x6B, 0x76, 0x6F, 0x42, 0x48, 0x54, 0x6F, 0x50, 0x34, 0x6D, 0x51, 0x34, 0x74, 0x34, 0x79, 0x38, 0x0A, 0x36, 0x49, 0x6A, 0x35, ++ 0x69, 0x79, 0x53, 0x72, 0x4C, 0x71, 0x50, 0x31, 0x4E, 0x2B, 0x52, 0x41, 0x6A, 0x68, 0x67, 0x6C, 0x65, 0x59, 0x4E, 0x31, 0x48, 0x7A, 0x76, 0x2F, 0x62, 0x4B, 0x6A, 0x46, 0x78, 0x6C, 0x62, 0x34, 0x74, 0x4F, 0x32, 0x4B, 0x52, 0x4B, 0x4F, 0x72, ++ 0x62, 0x45, 0x7A, 0x38, 0x48, 0x64, 0x44, 0x63, 0x37, 0x32, 0x69, 0x39, 0x7A, 0x2B, 0x53, 0x71, 0x7A, 0x76, 0x42, 0x56, 0x39, 0x36, 0x49, 0x30, 0x31, 0x49, 0x4E, 0x72, 0x4E, 0x33, 0x77, 0x63, 0x0A, 0x77, 0x76, 0x36, 0x31, 0x41, 0x2B, 0x78, ++ 0x58, 0x7A, 0x72, 0x79, 0x30, 0x74, 0x63, 0x58, 0x74, 0x41, 0x41, 0x39, 0x54, 0x4E, 0x79, 0x70, 0x4E, 0x39, 0x45, 0x38, 0x4D, 0x67, 0x2F, 0x75, 0x47, 0x7A, 0x38, 0x76, 0x2B, 0x6A, 0x45, 0x36, 0x39, 0x68, 0x2F, 0x6D, 0x6E, 0x69, 0x79, 0x46, ++ 0x58, 0x6E, 0x48, 0x72, 0x66, 0x41, 0x32, 0x65, 0x4A, 0x4C, 0x4A, 0x32, 0x58, 0x59, 0x61, 0x63, 0x51, 0x75, 0x46, 0x57, 0x51, 0x66, 0x77, 0x34, 0x74, 0x4A, 0x7A, 0x68, 0x30, 0x0A, 0x33, 0x2B, 0x66, 0x39, 0x32, 0x6B, 0x34, 0x53, 0x34, 0x30, ++ 0x30, 0x56, 0x49, 0x67, 0x4C, 0x49, 0x34, 0x4F, 0x44, 0x38, 0x44, 0x36, 0x32, 0x4B, 0x31, 0x38, 0x6C, 0x55, 0x55, 0x4D, 0x77, 0x37, 0x44, 0x38, 0x6F, 0x57, 0x67, 0x49, 0x54, 0x51, 0x55, 0x56, 0x62, 0x44, 0x6A, 0x6C, 0x5A, 0x2F, 0x69, 0x53, ++ 0x49, 0x7A, 0x4C, 0x2B, 0x61, 0x46, 0x43, 0x72, 0x32, 0x6C, 0x71, 0x42, 0x73, 0x32, 0x33, 0x74, 0x50, 0x63, 0x4C, 0x47, 0x30, 0x37, 0x78, 0x78, 0x4F, 0x39, 0x0A, 0x57, 0x53, 0x4D, 0x73, 0x35, 0x75, 0x57, 0x6B, 0x39, 0x39, 0x67, 0x4C, 0x37, ++ 0x65, 0x71, 0x51, 0x51, 0x45, 0x53, 0x6F, 0x6C, 0x62, 0x75, 0x54, 0x31, 0x64, 0x43, 0x41, 0x4E, 0x4C, 0x5A, 0x47, 0x65, 0x41, 0x34, 0x66, 0x41, 0x4A, 0x4E, 0x47, 0x34, 0x65, 0x37, 0x70, 0x2B, 0x65, 0x78, 0x50, 0x46, 0x77, 0x49, 0x44, 0x41, ++ 0x51, 0x41, 0x42, 0x6F, 0x30, 0x49, 0x77, 0x51, 0x44, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x0A, 0x5A, 0x54, 0x2F, 0x48, 0x69, 0x6F, 0x62, 0x47, 0x50, 0x4E, 0x30, 0x38, 0x56, 0x46, 0x77, 0x31, ++ 0x2B, 0x44, 0x72, 0x74, 0x55, 0x67, 0x78, 0x48, 0x56, 0x38, 0x67, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x51, 0x44, 0x41, 0x67, 0x45, 0x47, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, ++ 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x0A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x45, ++ 0x42, 0x41, 0x43, 0x6F, 0x2F, 0x34, 0x66, 0x45, 0x79, 0x6A, 0x71, 0x37, 0x68, 0x6D, 0x46, 0x78, 0x4C, 0x58, 0x73, 0x39, 0x72, 0x48, 0x6D, 0x6F, 0x4A, 0x30, 0x69, 0x4B, 0x70, 0x45, 0x73, 0x64, 0x65, 0x56, 0x33, 0x31, 0x7A, 0x56, 0x6D, 0x53, ++ 0x41, 0x68, 0x48, 0x71, 0x54, 0x35, 0x41, 0x6D, 0x35, 0x45, 0x4D, 0x32, 0x66, 0x4B, 0x69, 0x66, 0x68, 0x0A, 0x41, 0x48, 0x65, 0x2B, 0x53, 0x4D, 0x67, 0x31, 0x71, 0x49, 0x47, 0x66, 0x35, 0x4C, 0x67, 0x73, 0x79, 0x58, 0x38, 0x4F, 0x73, 0x4E, ++ 0x4A, 0x4C, 0x4E, 0x31, 0x33, 0x71, 0x75, 0x64, 0x55, 0x4C, 0x58, 0x6A, 0x53, 0x39, 0x39, 0x48, 0x4D, 0x70, 0x77, 0x2B, 0x30, 0x6D, 0x46, 0x5A, 0x78, 0x2B, 0x43, 0x46, 0x4F, 0x4B, 0x57, 0x49, 0x33, 0x51, 0x53, 0x79, 0x6A, 0x66, 0x77, 0x62, ++ 0x50, 0x66, 0x49, 0x50, 0x50, 0x35, 0x34, 0x2B, 0x4D, 0x36, 0x33, 0x38, 0x79, 0x63, 0x0A, 0x6C, 0x4E, 0x68, 0x4F, 0x54, 0x38, 0x4E, 0x72, 0x46, 0x37, 0x66, 0x33, 0x63, 0x75, 0x69, 0x74, 0x5A, 0x6A, 0x4F, 0x31, 0x4A, 0x56, 0x4F, 0x72, 0x34, ++ 0x50, 0x68, 0x4D, 0x71, 0x5A, 0x33, 0x39, 0x38, 0x67, 0x32, 0x36, 0x72, 0x72, 0x6E, 0x5A, 0x71, 0x73, 0x5A, 0x72, 0x2B, 0x5A, 0x4F, 0x37, 0x72, 0x71, 0x75, 0x34, 0x6C, 0x7A, 0x77, 0x44, 0x47, 0x72, 0x70, 0x44, 0x78, 0x70, 0x61, 0x35, 0x52, ++ 0x58, 0x49, 0x34, 0x73, 0x36, 0x65, 0x68, 0x6C, 0x6A, 0x32, 0x52, 0x0A, 0x65, 0x33, 0x37, 0x41, 0x49, 0x56, 0x4E, 0x4D, 0x68, 0x2B, 0x33, 0x79, 0x43, 0x31, 0x53, 0x56, 0x55, 0x5A, 0x50, 0x56, 0x49, 0x71, 0x55, 0x4E, 0x69, 0x76, 0x47, 0x54, ++ 0x44, 0x6A, 0x35, 0x55, 0x44, 0x72, 0x44, 0x59, 0x79, 0x55, 0x37, 0x63, 0x38, 0x6A, 0x45, 0x79, 0x56, 0x75, 0x70, 0x6B, 0x2B, 0x65, 0x71, 0x31, 0x6E, 0x52, 0x5A, 0x6D, 0x51, 0x6E, 0x4C, 0x7A, 0x66, 0x39, 0x4F, 0x78, 0x4D, 0x55, 0x50, 0x38, ++ 0x70, 0x49, 0x34, 0x58, 0x38, 0x57, 0x30, 0x6A, 0x0A, 0x71, 0x35, 0x52, 0x6D, 0x2B, 0x4B, 0x33, 0x37, 0x44, 0x77, 0x68, 0x75, 0x4A, 0x69, 0x31, 0x2F, 0x46, 0x77, 0x63, 0x4A, 0x73, 0x6F, 0x7A, 0x37, 0x55, 0x4D, 0x43, 0x66, 0x6C, 0x6F, 0x33, ++ 0x50, 0x74, 0x76, 0x30, 0x41, 0x6E, 0x56, 0x6F, 0x55, 0x6D, 0x72, 0x38, 0x43, 0x52, 0x50, 0x58, 0x42, 0x77, 0x70, 0x38, 0x69, 0x58, 0x71, 0x49, 0x50, 0x6F, 0x65, 0x4D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, ++ 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x47, 0x44, 0x43, 0x41, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x55, 0x54, 0x48, 0x20, 0x52, 0x35, 0x20, 0x52, 0x4F, 0x4F, 0x54, 0x0A, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, ++ 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x69, 0x44, 0x43, 0x43, 0x41, 0x33, 0x43, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x49, 0x66, 0x51, 0x6D, 0x58, 0x2F, 0x76, 0x42, 0x48, 0x36, ++ 0x6E, 0x6F, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x42, 0x51, 0x41, 0x77, 0x59, 0x6A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x51, ++ 0x30, 0x34, 0x78, 0x4D, 0x6A, 0x41, 0x77, 0x0A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x4D, 0x4B, 0x55, 0x64, 0x56, 0x51, 0x55, 0x35, 0x48, 0x49, 0x45, 0x52, 0x50, 0x54, 0x6B, 0x63, 0x67, 0x51, 0x30, 0x56, 0x53, 0x56, 0x45, 0x6C, 0x47, ++ 0x53, 0x55, 0x4E, 0x42, 0x56, 0x45, 0x55, 0x67, 0x51, 0x56, 0x56, 0x55, 0x53, 0x45, 0x39, 0x53, 0x53, 0x56, 0x52, 0x5A, 0x49, 0x45, 0x4E, 0x50, 0x4C, 0x69, 0x78, 0x4D, 0x56, 0x45, 0x51, 0x75, 0x4D, 0x52, 0x38, 0x77, 0x48, 0x51, 0x59, 0x44, ++ 0x56, 0x51, 0x51, 0x44, 0x0A, 0x44, 0x42, 0x5A, 0x48, 0x52, 0x45, 0x4E, 0x42, 0x49, 0x46, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x51, 0x56, 0x56, 0x55, 0x53, 0x43, 0x42, 0x53, 0x4E, 0x53, 0x42, 0x53, 0x54, 0x30, 0x39, 0x55, 0x4D, 0x42, 0x34, ++ 0x58, 0x44, 0x54, 0x45, 0x30, 0x4D, 0x54, 0x45, 0x79, 0x4E, 0x6A, 0x41, 0x31, 0x4D, 0x54, 0x4D, 0x78, 0x4E, 0x56, 0x6F, 0x58, 0x44, 0x54, 0x51, 0x77, 0x4D, 0x54, 0x49, 0x7A, 0x4D, 0x54, 0x45, 0x31, 0x4E, 0x54, 0x6B, 0x31, 0x4F, 0x56, 0x6F, ++ 0x77, 0x0A, 0x59, 0x6A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x51, 0x30, 0x34, 0x78, 0x4D, 0x6A, 0x41, 0x77, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x4D, 0x4B, 0x55, 0x64, 0x56, 0x51, 0x55, ++ 0x35, 0x48, 0x49, 0x45, 0x52, 0x50, 0x54, 0x6B, 0x63, 0x67, 0x51, 0x30, 0x56, 0x53, 0x56, 0x45, 0x6C, 0x47, 0x53, 0x55, 0x4E, 0x42, 0x56, 0x45, 0x55, 0x67, 0x51, 0x56, 0x56, 0x55, 0x53, 0x45, 0x39, 0x53, 0x53, 0x56, 0x52, 0x5A, 0x0A, 0x49, ++ 0x45, 0x4E, 0x50, 0x4C, 0x69, 0x78, 0x4D, 0x56, 0x45, 0x51, 0x75, 0x4D, 0x52, 0x38, 0x77, 0x48, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x44, 0x42, 0x5A, 0x48, 0x52, 0x45, 0x4E, 0x42, 0x49, 0x46, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x51, ++ 0x56, 0x56, 0x55, 0x53, 0x43, 0x42, 0x53, 0x4E, 0x53, 0x42, 0x53, 0x54, 0x30, 0x39, 0x55, 0x4D, 0x49, 0x49, 0x43, 0x49, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x0A, 0x41, 0x51, 0x45, 0x46, ++ 0x41, 0x41, 0x4F, 0x43, 0x41, 0x67, 0x38, 0x41, 0x4D, 0x49, 0x49, 0x43, 0x43, 0x67, 0x4B, 0x43, 0x41, 0x67, 0x45, 0x41, 0x32, 0x61, 0x4D, 0x57, 0x38, 0x4D, 0x68, 0x30, 0x64, 0x48, 0x65, 0x62, 0x37, 0x7A, 0x4D, 0x4E, 0x4F, 0x77, 0x5A, 0x2B, ++ 0x56, 0x66, 0x79, 0x31, 0x59, 0x49, 0x39, 0x32, 0x68, 0x68, 0x4A, 0x43, 0x66, 0x56, 0x5A, 0x6D, 0x50, 0x6F, 0x69, 0x43, 0x37, 0x58, 0x4A, 0x6A, 0x44, 0x70, 0x36, 0x4C, 0x33, 0x54, 0x51, 0x73, 0x0A, 0x41, 0x6C, 0x46, 0x52, 0x77, 0x78, 0x6E, ++ 0x39, 0x57, 0x56, 0x53, 0x45, 0x79, 0x66, 0x46, 0x72, 0x73, 0x30, 0x79, 0x77, 0x36, 0x65, 0x68, 0x47, 0x58, 0x54, 0x6A, 0x47, 0x6F, 0x71, 0x63, 0x75, 0x45, 0x56, 0x65, 0x36, 0x67, 0x68, 0x57, 0x69, 0x6E, 0x49, 0x39, 0x74, 0x73, 0x4A, 0x6C, ++ 0x4B, 0x43, 0x76, 0x4C, 0x72, 0x69, 0x58, 0x42, 0x6A, 0x54, 0x6E, 0x6E, 0x45, 0x74, 0x31, 0x75, 0x39, 0x6F, 0x6C, 0x32, 0x78, 0x38, 0x6B, 0x45, 0x43, 0x4B, 0x36, 0x32, 0x70, 0x0A, 0x4F, 0x71, 0x50, 0x73, 0x65, 0x51, 0x72, 0x73, 0x58, 0x7A, ++ 0x72, 0x6A, 0x2F, 0x65, 0x2B, 0x41, 0x50, 0x4B, 0x30, 0x30, 0x6D, 0x78, 0x71, 0x72, 0x69, 0x43, 0x5A, 0x37, 0x56, 0x71, 0x4B, 0x43, 0x68, 0x68, 0x2F, 0x72, 0x4E, 0x59, 0x6D, 0x44, 0x66, 0x31, 0x2B, 0x75, 0x4B, 0x55, 0x34, 0x39, 0x74, 0x6D, ++ 0x37, 0x73, 0x72, 0x73, 0x48, 0x77, 0x4A, 0x35, 0x75, 0x75, 0x34, 0x2F, 0x54, 0x73, 0x37, 0x36, 0x35, 0x2F, 0x39, 0x34, 0x59, 0x39, 0x63, 0x6E, 0x72, 0x72, 0x0A, 0x70, 0x66, 0x74, 0x5A, 0x54, 0x71, 0x66, 0x72, 0x6C, 0x59, 0x77, 0x69, 0x4F, ++ 0x58, 0x6E, 0x68, 0x4C, 0x51, 0x69, 0x50, 0x7A, 0x4C, 0x79, 0x52, 0x75, 0x45, 0x48, 0x33, 0x46, 0x4D, 0x45, 0x6A, 0x71, 0x63, 0x4F, 0x74, 0x6D, 0x6B, 0x56, 0x45, 0x73, 0x37, 0x4C, 0x58, 0x4C, 0x4D, 0x33, 0x47, 0x4B, 0x65, 0x4A, 0x51, 0x45, ++ 0x4B, 0x35, 0x63, 0x79, 0x34, 0x4B, 0x4F, 0x46, 0x78, 0x67, 0x32, 0x66, 0x5A, 0x66, 0x6D, 0x69, 0x4A, 0x71, 0x77, 0x54, 0x54, 0x51, 0x4A, 0x0A, 0x39, 0x43, 0x79, 0x35, 0x57, 0x6D, 0x59, 0x71, 0x73, 0x42, 0x65, 0x62, 0x6E, 0x68, 0x35, 0x32, ++ 0x6E, 0x55, 0x70, 0x6D, 0x4D, 0x55, 0x48, 0x66, 0x50, 0x2F, 0x76, 0x46, 0x42, 0x75, 0x38, 0x62, 0x74, 0x6E, 0x34, 0x61, 0x52, 0x6A, 0x62, 0x33, 0x5A, 0x47, 0x4D, 0x37, 0x34, 0x7A, 0x6B, 0x59, 0x49, 0x2B, 0x64, 0x6E, 0x64, 0x52, 0x54, 0x56, ++ 0x64, 0x56, 0x65, 0x53, 0x4E, 0x37, 0x32, 0x2B, 0x61, 0x68, 0x73, 0x6D, 0x55, 0x50, 0x49, 0x32, 0x4A, 0x67, 0x61, 0x51, 0x0A, 0x78, 0x58, 0x41, 0x42, 0x5A, 0x47, 0x31, 0x32, 0x5A, 0x75, 0x47, 0x52, 0x32, 0x32, 0x34, 0x48, 0x77, 0x47, 0x47, ++ 0x41, 0x4C, 0x72, 0x49, 0x75, 0x4C, 0x34, 0x78, 0x77, 0x70, 0x39, 0x45, 0x37, 0x50, 0x4C, 0x4F, 0x52, 0x35, 0x47, 0x36, 0x32, 0x78, 0x44, 0x74, 0x77, 0x38, 0x6D, 0x79, 0x53, 0x6C, 0x77, 0x6E, 0x4E, 0x52, 0x33, 0x30, 0x59, 0x77, 0x50, 0x4F, ++ 0x37, 0x6E, 0x67, 0x2F, 0x57, 0x69, 0x36, 0x34, 0x48, 0x74, 0x6C, 0x6F, 0x50, 0x7A, 0x67, 0x73, 0x4D, 0x0A, 0x52, 0x36, 0x66, 0x6C, 0x50, 0x72, 0x69, 0x39, 0x66, 0x63, 0x65, 0x62, 0x4E, 0x61, 0x42, 0x68, 0x6C, 0x7A, 0x70, 0x42, 0x64, 0x52, ++ 0x66, 0x4D, 0x4B, 0x35, 0x5A, 0x33, 0x4B, 0x70, 0x49, 0x68, 0x48, 0x74, 0x6D, 0x56, 0x64, 0x69, 0x42, 0x6E, 0x61, 0x4D, 0x38, 0x4E, 0x76, 0x64, 0x2F, 0x57, 0x48, 0x77, 0x6C, 0x71, 0x6D, 0x75, 0x4C, 0x4D, 0x63, 0x33, 0x47, 0x6B, 0x4C, 0x33, ++ 0x30, 0x53, 0x67, 0x4C, 0x64, 0x54, 0x4D, 0x45, 0x5A, 0x65, 0x53, 0x31, 0x53, 0x5A, 0x0A, 0x44, 0x32, 0x66, 0x4A, 0x70, 0x63, 0x6A, 0x79, 0x49, 0x4D, 0x47, 0x43, 0x37, 0x4A, 0x30, 0x52, 0x33, 0x38, 0x49, 0x43, 0x2B, 0x78, 0x6F, 0x37, 0x30, ++ 0x65, 0x30, 0x67, 0x6D, 0x75, 0x39, 0x6C, 0x5A, 0x4A, 0x49, 0x51, 0x44, 0x53, 0x72, 0x69, 0x33, 0x6E, 0x44, 0x78, 0x47, 0x47, 0x65, 0x43, 0x6A, 0x47, 0x48, 0x65, 0x75, 0x4C, 0x7A, 0x52, 0x4C, 0x35, 0x7A, 0x37, 0x44, 0x39, 0x41, 0x72, 0x37, ++ 0x52, 0x74, 0x32, 0x75, 0x65, 0x51, 0x35, 0x56, 0x66, 0x6A, 0x34, 0x0A, 0x6F, 0x52, 0x32, 0x34, 0x71, 0x6F, 0x41, 0x41, 0x54, 0x49, 0x4C, 0x6E, 0x73, 0x6E, 0x38, 0x4A, 0x75, 0x4C, 0x77, 0x77, 0x6F, 0x43, 0x38, 0x4E, 0x39, 0x56, 0x4B, 0x65, ++ 0x6A, 0x76, 0x65, 0x53, 0x73, 0x77, 0x6F, 0x41, 0x48, 0x51, 0x42, 0x55, 0x6C, 0x77, 0x62, 0x67, 0x73, 0x51, 0x66, 0x5A, 0x78, 0x77, 0x39, 0x63, 0x5A, 0x58, 0x30, 0x38, 0x62, 0x56, 0x6C, 0x58, 0x35, 0x4F, 0x32, 0x6C, 0x6A, 0x65, 0x6C, 0x41, ++ 0x55, 0x35, 0x38, 0x56, 0x53, 0x36, 0x42, 0x78, 0x0A, 0x39, 0x68, 0x6F, 0x68, 0x34, 0x39, 0x70, 0x77, 0x42, 0x69, 0x46, 0x59, 0x46, 0x49, 0x65, 0x46, 0x64, 0x33, 0x6D, 0x71, 0x67, 0x6E, 0x6B, 0x43, 0x41, 0x77, 0x45, 0x41, 0x41, 0x61, 0x4E, ++ 0x43, 0x4D, 0x45, 0x41, 0x77, 0x48, 0x51, 0x59, 0x44, 0x56, 0x52, 0x30, 0x4F, 0x42, 0x42, 0x59, 0x45, 0x46, 0x4F, 0x4C, 0x4A, 0x51, 0x4A, 0x39, 0x4E, 0x7A, 0x75, 0x69, 0x61, 0x6F, 0x58, 0x7A, 0x50, 0x44, 0x6A, 0x39, 0x6C, 0x78, 0x53, 0x6D, ++ 0x49, 0x61, 0x68, 0x6C, 0x52, 0x0A, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x41, 0x51, ++ 0x48, 0x2F, 0x42, 0x41, 0x51, 0x44, 0x41, 0x67, 0x47, 0x47, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x43, 0x77, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x41, 0x51, 0x44, 0x52, 0x53, 0x56, ++ 0x66, 0x67, 0x0A, 0x70, 0x38, 0x78, 0x6F, 0x57, 0x4C, 0x6F, 0x42, 0x44, 0x79, 0x73, 0x5A, 0x7A, 0x59, 0x32, 0x77, 0x59, 0x55, 0x57, 0x73, 0x45, 0x65, 0x31, 0x6A, 0x55, 0x47, 0x6E, 0x34, 0x48, 0x33, 0x2B, 0x2B, 0x46, 0x6F, 0x2F, 0x39, 0x6E, ++ 0x65, 0x73, 0x4C, 0x71, 0x6A, 0x4A, 0x48, 0x64, 0x74, 0x4A, 0x6E, 0x4A, 0x4F, 0x32, 0x39, 0x66, 0x44, 0x4D, 0x79, 0x6C, 0x79, 0x72, 0x48, 0x42, 0x59, 0x5A, 0x6D, 0x44, 0x52, 0x64, 0x39, 0x46, 0x42, 0x55, 0x62, 0x31, 0x4F, 0x76, 0x39, 0x0A, ++ 0x48, 0x35, 0x72, 0x32, 0x58, 0x70, 0x64, 0x70, 0x74, 0x78, 0x6F, 0x6C, 0x70, 0x41, 0x71, 0x7A, 0x6B, 0x54, 0x39, 0x66, 0x4E, 0x71, 0x79, 0x4C, 0x37, 0x46, 0x65, 0x6F, 0x50, 0x75, 0x65, 0x42, 0x69, 0x68, 0x68, 0x58, 0x4F, 0x59, 0x56, 0x30, ++ 0x47, 0x6B, 0x4C, 0x48, 0x36, 0x56, 0x73, 0x54, 0x58, 0x34, 0x2F, 0x35, 0x43, 0x4F, 0x6D, 0x53, 0x64, 0x49, 0x33, 0x31, 0x52, 0x39, 0x4B, 0x72, 0x4F, 0x39, 0x62, 0x37, 0x65, 0x47, 0x5A, 0x4F, 0x4E, 0x6E, 0x33, 0x35, 0x0A, 0x36, 0x5A, 0x4C, ++ 0x70, 0x42, 0x4E, 0x37, 0x39, 0x53, 0x57, 0x50, 0x38, 0x62, 0x66, 0x73, 0x55, 0x63, 0x5A, 0x4E, 0x6E, 0x4C, 0x30, 0x64, 0x4B, 0x74, 0x37, 0x6E, 0x2F, 0x48, 0x69, 0x70, 0x7A, 0x63, 0x45, 0x59, 0x77, 0x76, 0x31, 0x72, 0x79, 0x4C, 0x33, 0x6D, ++ 0x6C, 0x34, 0x59, 0x30, 0x4D, 0x32, 0x66, 0x6D, 0x79, 0x59, 0x7A, 0x65, 0x4D, 0x4E, 0x32, 0x57, 0x46, 0x63, 0x47, 0x70, 0x63, 0x57, 0x77, 0x6C, 0x79, 0x75, 0x61, 0x31, 0x6A, 0x50, 0x4C, 0x48, 0x64, 0x0A, 0x2B, 0x50, 0x77, 0x79, 0x76, 0x7A, ++ 0x65, 0x47, 0x35, 0x4C, 0x75, 0x4F, 0x6D, 0x43, 0x64, 0x2B, 0x75, 0x68, 0x38, 0x57, 0x34, 0x58, 0x41, 0x52, 0x38, 0x67, 0x50, 0x66, 0x4A, 0x57, 0x49, 0x79, 0x4A, 0x79, 0x59, 0x59, 0x4D, 0x6F, 0x53, 0x66, 0x2F, 0x77, 0x41, 0x36, 0x45, 0x37, ++ 0x71, 0x61, 0x54, 0x66, 0x52, 0x50, 0x75, 0x42, 0x52, 0x77, 0x49, 0x72, 0x48, 0x4B, 0x4B, 0x35, 0x44, 0x4F, 0x4B, 0x63, 0x46, 0x77, 0x39, 0x43, 0x2B, 0x64, 0x66, 0x2F, 0x4B, 0x51, 0x0A, 0x48, 0x74, 0x5A, 0x61, 0x33, 0x37, 0x64, 0x47, 0x2F, ++ 0x4F, 0x61, 0x47, 0x2B, 0x73, 0x76, 0x67, 0x49, 0x48, 0x5A, 0x36, 0x75, 0x71, 0x62, 0x4C, 0x39, 0x58, 0x7A, 0x65, 0x59, 0x71, 0x57, 0x78, 0x69, 0x2B, 0x37, 0x65, 0x67, 0x6D, 0x61, 0x4B, 0x54, 0x6A, 0x6F, 0x77, 0x48, 0x7A, 0x2B, 0x41, 0x79, ++ 0x36, 0x30, 0x6E, 0x75, 0x67, 0x78, 0x65, 0x31, 0x39, 0x43, 0x78, 0x56, 0x73, 0x70, 0x33, 0x63, 0x62, 0x4B, 0x31, 0x64, 0x61, 0x46, 0x51, 0x71, 0x55, 0x42, 0x44, 0x0A, 0x46, 0x38, 0x49, 0x6F, 0x32, 0x63, 0x39, 0x53, 0x69, 0x31, 0x76, 0x49, ++ 0x59, 0x39, 0x52, 0x43, 0x50, 0x71, 0x41, 0x7A, 0x65, 0x6B, 0x59, 0x75, 0x39, 0x77, 0x6F, 0x67, 0x52, 0x6C, 0x52, 0x2B, 0x61, 0x6B, 0x38, 0x78, 0x38, 0x59, 0x46, 0x2B, 0x51, 0x6E, 0x51, 0x34, 0x5A, 0x58, 0x4D, 0x6E, 0x37, 0x73, 0x5A, 0x38, ++ 0x75, 0x49, 0x37, 0x58, 0x70, 0x54, 0x72, 0x58, 0x6D, 0x4B, 0x47, 0x63, 0x6A, 0x42, 0x42, 0x56, 0x30, 0x39, 0x74, 0x4C, 0x37, 0x45, 0x43, 0x51, 0x0A, 0x38, 0x73, 0x31, 0x75, 0x56, 0x39, 0x4A, 0x69, 0x44, 0x6E, 0x78, 0x58, 0x6B, 0x37, 0x47, ++ 0x6E, 0x62, 0x63, 0x32, 0x64, 0x67, 0x37, 0x73, 0x71, 0x35, 0x2B, 0x57, 0x32, 0x4F, 0x33, 0x46, 0x59, 0x72, 0x66, 0x33, 0x52, 0x52, 0x62, 0x78, 0x61, 0x6B, 0x65, 0x35, 0x54, 0x46, 0x57, 0x2F, 0x54, 0x52, 0x51, 0x6C, 0x31, 0x62, 0x72, 0x71, ++ 0x51, 0x58, 0x52, 0x34, 0x45, 0x7A, 0x7A, 0x66, 0x66, 0x48, 0x71, 0x68, 0x6D, 0x73, 0x59, 0x7A, 0x6D, 0x49, 0x47, 0x72, 0x76, 0x0A, 0x2F, 0x45, 0x68, 0x4F, 0x64, 0x4A, 0x68, 0x43, 0x72, 0x79, 0x6C, 0x76, 0x4C, 0x6D, 0x72, 0x48, 0x2B, 0x33, ++ 0x33, 0x52, 0x5A, 0x6A, 0x45, 0x69, 0x7A, 0x49, 0x59, 0x41, 0x66, 0x6D, 0x61, 0x44, 0x44, 0x45, 0x4C, 0x30, 0x76, 0x54, 0x53, 0x53, 0x77, 0x78, 0x72, 0x71, 0x54, 0x38, 0x70, 0x2B, 0x63, 0x6B, 0x30, 0x4C, 0x63, 0x49, 0x79, 0x6D, 0x53, 0x4C, ++ 0x75, 0x6D, 0x6F, 0x52, 0x54, 0x32, 0x2B, 0x31, 0x68, 0x45, 0x6D, 0x52, 0x53, 0x75, 0x71, 0x67, 0x75, 0x54, 0x0A, 0x61, 0x61, 0x41, 0x70, 0x4A, 0x55, 0x71, 0x6C, 0x79, 0x79, 0x76, 0x64, 0x69, 0x6D, 0x59, 0x48, 0x46, 0x6E, 0x67, 0x56, 0x56, ++ 0x33, 0x45, 0x62, 0x37, 0x50, 0x56, 0x48, 0x68, 0x50, 0x4F, 0x65, 0x4D, 0x54, 0x64, 0x36, 0x31, 0x58, 0x38, 0x6B, 0x72, 0x65, 0x53, 0x38, 0x2F, 0x66, 0x33, 0x4D, 0x62, 0x6F, 0x50, 0x6F, 0x44, 0x4B, 0x69, 0x33, 0x51, 0x57, 0x77, 0x48, 0x33, ++ 0x62, 0x30, 0x38, 0x68, 0x70, 0x63, 0x76, 0x30, 0x67, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x53, ++ 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x53, 0x41, 0x0A, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x33, 0x54, 0x43, 0x43, 0x41, 0x38, 0x57, ++ 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x49, 0x65, 0x79, 0x79, 0x62, 0x30, 0x78, 0x61, 0x41, 0x4D, 0x70, 0x6B, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x42, 0x51, 0x41, ++ 0x77, 0x66, 0x44, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x56, 0x56, 0x4D, 0x78, 0x44, 0x6A, 0x41, 0x4D, 0x0A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x67, 0x4D, 0x42, 0x56, 0x52, 0x6C, 0x65, 0x47, ++ 0x46, 0x7A, 0x4D, 0x52, 0x41, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x48, 0x44, 0x41, 0x64, 0x49, 0x62, 0x33, 0x56, 0x7A, 0x64, 0x47, 0x39, 0x75, 0x4D, 0x52, 0x67, 0x77, 0x46, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x44, 0x41, ++ 0x39, 0x54, 0x55, 0x30, 0x77, 0x67, 0x51, 0x32, 0x39, 0x79, 0x63, 0x47, 0x39, 0x79, 0x59, 0x58, 0x52, 0x70, 0x62, 0x32, 0x34, 0x78, 0x0A, 0x4D, 0x54, 0x41, 0x76, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x4D, 0x4B, 0x46, 0x4E, 0x54, 0x54, ++ 0x43, 0x35, 0x6A, 0x62, 0x32, 0x30, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x61, 0x57, 0x5A, 0x70, 0x59, 0x32, 0x46, 0x30, 0x61, 0x57, 0x39, 0x75, 0x49, 0x45, 0x46, 0x31, 0x64, 0x47, 0x68, 0x76, 0x63, ++ 0x6D, 0x6C, 0x30, 0x65, 0x53, 0x42, 0x53, 0x55, 0x30, 0x45, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x54, 0x59, 0x77, 0x0A, 0x4D, 0x6A, 0x45, 0x79, 0x4D, 0x54, 0x63, 0x7A, 0x4F, 0x54, 0x4D, 0x35, 0x57, 0x68, 0x63, 0x4E, 0x4E, 0x44, 0x45, 0x77, ++ 0x4D, 0x6A, 0x45, 0x79, 0x4D, 0x54, 0x63, 0x7A, 0x4F, 0x54, 0x4D, 0x35, 0x57, 0x6A, 0x42, 0x38, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x56, 0x55, 0x7A, 0x45, 0x4F, 0x4D, 0x41, 0x77, 0x47, ++ 0x41, 0x31, 0x55, 0x45, 0x43, 0x41, 0x77, 0x46, 0x56, 0x47, 0x56, 0x34, 0x59, 0x58, 0x4D, 0x78, 0x0A, 0x45, 0x44, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x63, 0x4D, 0x42, 0x30, 0x68, 0x76, 0x64, 0x58, 0x4E, 0x30, 0x62, 0x32, 0x34, ++ 0x78, 0x47, 0x44, 0x41, 0x57, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x4D, 0x44, 0x31, 0x4E, 0x54, 0x54, 0x43, 0x42, 0x44, 0x62, 0x33, 0x4A, 0x77, 0x62, 0x33, 0x4A, 0x68, 0x64, 0x47, 0x6C, 0x76, 0x62, 0x6A, 0x45, 0x78, 0x4D, 0x43, 0x38, ++ 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x77, 0x77, 0x6F, 0x55, 0x31, 0x4E, 0x4D, 0x0A, 0x4C, 0x6D, 0x4E, 0x76, 0x62, 0x53, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x6C, 0x63, 0x6E, 0x52, 0x70, 0x5A, 0x6D, 0x6C, 0x6A, 0x59, 0x58, ++ 0x52, 0x70, 0x62, 0x32, 0x34, 0x67, 0x51, 0x58, 0x56, 0x30, 0x61, 0x47, 0x39, 0x79, 0x61, 0x58, 0x52, 0x35, 0x49, 0x46, 0x4A, 0x54, 0x51, 0x54, 0x43, 0x43, 0x41, 0x69, 0x49, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, ++ 0x63, 0x4E, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x0A, 0x67, 0x67, 0x49, 0x50, 0x41, 0x44, 0x43, 0x43, 0x41, 0x67, 0x6F, 0x43, 0x67, 0x67, 0x49, 0x42, 0x41, 0x50, 0x6B, 0x50, 0x33, 0x61, 0x4D, 0x72, 0x66, 0x63, 0x76, 0x51, 0x4B, ++ 0x76, 0x37, 0x73, 0x5A, 0x34, 0x57, 0x6D, 0x35, 0x79, 0x34, 0x62, 0x75, 0x6E, 0x66, 0x68, 0x34, 0x2F, 0x57, 0x76, 0x70, 0x4F, 0x7A, 0x36, 0x53, 0x6C, 0x32, 0x52, 0x78, 0x46, 0x64, 0x48, 0x61, 0x78, 0x68, 0x33, 0x61, 0x33, 0x62, 0x79, 0x2F, ++ 0x5A, 0x50, 0x6B, 0x50, 0x51, 0x2F, 0x43, 0x0A, 0x46, 0x70, 0x34, 0x4C, 0x5A, 0x73, 0x4E, 0x57, 0x6C, 0x4A, 0x34, 0x58, 0x67, 0x34, 0x58, 0x4F, 0x56, 0x75, 0x2F, 0x79, 0x46, 0x76, 0x30, 0x41, 0x59, 0x76, 0x55, 0x69, 0x43, 0x56, 0x54, 0x6F, ++ 0x5A, 0x52, 0x64, 0x4F, 0x51, 0x62, 0x6E, 0x67, 0x54, 0x30, 0x61, 0x58, 0x71, 0x68, 0x76, 0x49, 0x75, 0x47, 0x35, 0x69, 0x58, 0x6D, 0x6D, 0x78, 0x58, 0x39, 0x73, 0x71, 0x41, 0x6E, 0x37, 0x38, 0x62, 0x4D, 0x72, 0x7A, 0x51, 0x64, 0x6A, 0x74, ++ 0x30, 0x4F, 0x6A, 0x38, 0x0A, 0x50, 0x32, 0x46, 0x49, 0x37, 0x62, 0x41, 0x44, 0x46, 0x42, 0x30, 0x51, 0x44, 0x6B, 0x73, 0x5A, 0x34, 0x4C, 0x74, 0x4F, 0x37, 0x49, 0x5A, 0x6C, 0x2F, 0x7A, 0x62, 0x7A, 0x58, 0x6D, 0x63, 0x43, 0x43, 0x35, 0x32, ++ 0x47, 0x56, 0x57, 0x48, 0x39, 0x65, 0x6A, 0x6A, 0x74, 0x2F, 0x75, 0x49, 0x5A, 0x41, 0x4C, 0x64, 0x76, 0x6F, 0x56, 0x42, 0x69, 0x64, 0x58, 0x51, 0x38, 0x6F, 0x50, 0x72, 0x49, 0x4A, 0x5A, 0x4B, 0x30, 0x62, 0x6E, 0x6F, 0x69, 0x78, 0x2F, 0x67, ++ 0x65, 0x0A, 0x6F, 0x65, 0x4F, 0x79, 0x33, 0x5A, 0x45, 0x78, 0x71, 0x79, 0x73, 0x64, 0x42, 0x50, 0x2B, 0x6C, 0x53, 0x67, 0x51, 0x33, 0x36, 0x59, 0x57, 0x6B, 0x4D, 0x79, 0x76, 0x39, 0x34, 0x74, 0x5A, 0x56, 0x4E, 0x48, 0x77, 0x5A, 0x70, 0x45, ++ 0x70, 0x6F, 0x78, 0x37, 0x4B, 0x6F, 0x30, 0x37, 0x66, 0x4B, 0x6F, 0x5A, 0x4F, 0x49, 0x36, 0x38, 0x47, 0x58, 0x76, 0x49, 0x7A, 0x35, 0x48, 0x64, 0x6B, 0x69, 0x68, 0x43, 0x52, 0x30, 0x78, 0x77, 0x51, 0x39, 0x61, 0x71, 0x6B, 0x70, 0x0A, 0x6B, ++ 0x38, 0x7A, 0x72, 0x75, 0x46, 0x76, 0x68, 0x2F, 0x6C, 0x38, 0x6C, 0x71, 0x6A, 0x52, 0x59, 0x79, 0x4D, 0x45, 0x6A, 0x56, 0x4A, 0x30, 0x62, 0x6D, 0x42, 0x48, 0x44, 0x4F, 0x4A, 0x78, 0x2B, 0x50, 0x59, 0x5A, 0x73, 0x70, 0x51, 0x39, 0x41, 0x68, ++ 0x6E, 0x77, 0x43, 0x39, 0x46, 0x77, 0x43, 0x54, 0x79, 0x6A, 0x4C, 0x72, 0x6E, 0x47, 0x66, 0x44, 0x7A, 0x72, 0x49, 0x4D, 0x2F, 0x34, 0x52, 0x4A, 0x54, 0x58, 0x71, 0x2F, 0x4C, 0x72, 0x46, 0x59, 0x44, 0x33, 0x5A, 0x0A, 0x66, 0x42, 0x6A, 0x56, ++ 0x73, 0x71, 0x6E, 0x54, 0x64, 0x58, 0x67, 0x44, 0x63, 0x69, 0x4C, 0x4B, 0x4F, 0x73, 0x4D, 0x66, 0x37, 0x79, 0x7A, 0x6C, 0x4C, 0x71, 0x6E, 0x36, 0x6E, 0x69, 0x79, 0x32, 0x55, 0x55, 0x62, 0x39, 0x72, 0x77, 0x50, 0x57, 0x36, 0x6D, 0x42, 0x6F, ++ 0x36, 0x6F, 0x55, 0x57, 0x4E, 0x6D, 0x75, 0x46, 0x36, 0x52, 0x37, 0x41, 0x73, 0x39, 0x33, 0x45, 0x4A, 0x4E, 0x79, 0x41, 0x4B, 0x6F, 0x46, 0x42, 0x62, 0x5A, 0x51, 0x2B, 0x79, 0x4F, 0x44, 0x4A, 0x0A, 0x67, 0x55, 0x45, 0x41, 0x6E, 0x6C, 0x36, ++ 0x2F, 0x66, 0x38, 0x55, 0x49, 0x6D, 0x4B, 0x49, 0x59, 0x4C, 0x45, 0x4A, 0x41, 0x73, 0x2F, 0x6C, 0x76, 0x4F, 0x43, 0x64, 0x4C, 0x54, 0x6F, 0x44, 0x30, 0x50, 0x59, 0x46, 0x48, 0x34, 0x49, 0x68, 0x38, 0x36, 0x68, 0x7A, 0x4F, 0x74, 0x58, 0x56, ++ 0x63, 0x55, 0x53, 0x34, 0x63, 0x4B, 0x33, 0x38, 0x61, 0x63, 0x69, 0x6A, 0x6E, 0x41, 0x4C, 0x58, 0x52, 0x64, 0x4D, 0x62, 0x58, 0x35, 0x4A, 0x2B, 0x74, 0x42, 0x35, 0x4F, 0x32, 0x0A, 0x55, 0x7A, 0x55, 0x31, 0x2F, 0x44, 0x66, 0x6B, 0x77, 0x2F, ++ 0x5A, 0x64, 0x46, 0x72, 0x34, 0x68, 0x63, 0x39, 0x36, 0x53, 0x43, 0x76, 0x69, 0x67, 0x59, 0x32, 0x71, 0x38, 0x6C, 0x70, 0x4A, 0x71, 0x50, 0x76, 0x69, 0x38, 0x5A, 0x56, 0x57, 0x62, 0x33, 0x76, 0x55, 0x4E, 0x69, 0x53, 0x59, 0x45, 0x2F, 0x43, ++ 0x55, 0x61, 0x70, 0x69, 0x56, 0x70, 0x79, 0x38, 0x4A, 0x74, 0x79, 0x6E, 0x7A, 0x69, 0x57, 0x56, 0x2B, 0x58, 0x72, 0x4F, 0x76, 0x76, 0x4C, 0x73, 0x69, 0x38, 0x0A, 0x31, 0x78, 0x74, 0x5A, 0x50, 0x43, 0x76, 0x4D, 0x38, 0x68, 0x6E, 0x49, 0x6B, ++ 0x32, 0x73, 0x6E, 0x59, 0x78, 0x6E, 0x50, 0x2F, 0x4F, 0x6B, 0x6D, 0x2B, 0x4D, 0x70, 0x78, 0x6D, 0x33, 0x2B, 0x54, 0x2F, 0x6A, 0x52, 0x6E, 0x68, 0x45, 0x36, 0x5A, 0x36, 0x2F, 0x79, 0x7A, 0x65, 0x41, 0x6B, 0x7A, 0x63, 0x4C, 0x70, 0x6D, 0x70, ++ 0x6E, 0x62, 0x74, 0x47, 0x33, 0x50, 0x72, 0x47, 0x71, 0x55, 0x4E, 0x78, 0x43, 0x49, 0x54, 0x49, 0x4A, 0x52, 0x57, 0x43, 0x6B, 0x34, 0x73, 0x0A, 0x62, 0x45, 0x36, 0x78, 0x2F, 0x63, 0x2B, 0x63, 0x43, 0x62, 0x71, 0x69, 0x4D, 0x2B, 0x32, 0x48, ++ 0x41, 0x67, 0x4D, 0x42, 0x41, 0x41, 0x47, 0x6A, 0x59, 0x7A, 0x42, 0x68, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x54, 0x64, 0x42, 0x41, 0x6B, 0x48, 0x6F, 0x76, 0x56, 0x36, 0x66, 0x56, 0x4A, 0x54, ++ 0x45, 0x70, 0x4B, 0x56, 0x37, 0x6A, 0x69, 0x41, 0x4A, 0x51, 0x32, 0x6D, 0x57, 0x54, 0x41, 0x50, 0x42, 0x67, 0x4E, 0x56, 0x0A, 0x48, 0x52, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x54, 0x41, 0x44, 0x41, 0x51, 0x48, 0x2F, 0x4D, 0x42, 0x38, ++ 0x47, 0x41, 0x31, 0x55, 0x64, 0x49, 0x77, 0x51, 0x59, 0x4D, 0x42, 0x61, 0x41, 0x46, 0x4E, 0x30, 0x45, 0x43, 0x51, 0x65, 0x69, 0x39, 0x58, 0x70, 0x39, 0x55, 0x6C, 0x4D, 0x53, 0x6B, 0x70, 0x58, 0x75, 0x4F, 0x49, 0x41, 0x6C, 0x44, 0x61, 0x5A, ++ 0x5A, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, 0x0A, 0x41, 0x77, 0x49, 0x42, 0x68, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, ++ 0x73, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x67, 0x45, 0x41, 0x49, 0x42, 0x67, 0x52, 0x6C, 0x43, 0x6E, 0x37, 0x4A, 0x70, 0x30, 0x63, 0x48, 0x68, 0x35, 0x77, 0x59, 0x66, 0x47, 0x56, 0x63, 0x70, 0x4E, 0x78, 0x4A, 0x4B, 0x31, 0x6F, 0x6B, 0x31, ++ 0x69, 0x4F, 0x4D, 0x71, 0x38, 0x62, 0x73, 0x33, 0x41, 0x44, 0x2F, 0x43, 0x55, 0x72, 0x0A, 0x64, 0x49, 0x57, 0x51, 0x50, 0x58, 0x68, 0x71, 0x39, 0x4C, 0x6D, 0x4C, 0x70, 0x5A, 0x63, 0x37, 0x74, 0x52, 0x69, 0x52, 0x75, 0x78, 0x36, 0x6E, 0x2B, ++ 0x55, 0x42, 0x62, 0x6B, 0x66, 0x6C, 0x56, 0x6D, 0x61, 0x38, 0x65, 0x45, 0x64, 0x42, 0x63, 0x48, 0x61, 0x64, 0x6D, 0x34, 0x37, 0x47, 0x55, 0x42, 0x77, 0x77, 0x79, 0x4F, 0x61, 0x62, 0x71, 0x47, 0x37, 0x42, 0x35, 0x32, 0x42, 0x32, 0x63, 0x63, ++ 0x45, 0x54, 0x6A, 0x69, 0x74, 0x33, 0x45, 0x2B, 0x5A, 0x55, 0x66, 0x0A, 0x69, 0x6A, 0x68, 0x44, 0x50, 0x77, 0x47, 0x46, 0x70, 0x55, 0x65, 0x6E, 0x50, 0x55, 0x61, 0x79, 0x76, 0x4F, 0x55, 0x69, 0x61, 0x50, 0x64, 0x37, 0x6E, 0x4E, 0x67, 0x73, ++ 0x50, 0x67, 0x6F, 0x68, 0x79, 0x43, 0x30, 0x7A, 0x72, 0x4C, 0x2F, 0x46, 0x67, 0x5A, 0x6B, 0x78, 0x64, 0x4D, 0x46, 0x31, 0x63, 0x63, 0x57, 0x2B, 0x73, 0x66, 0x41, 0x6A, 0x52, 0x66, 0x53, 0x64, 0x61, 0x2F, 0x77, 0x5A, 0x59, 0x35, 0x32, 0x6A, ++ 0x76, 0x41, 0x54, 0x47, 0x47, 0x41, 0x73, 0x6C, 0x0A, 0x75, 0x31, 0x4F, 0x4A, 0x44, 0x37, 0x4F, 0x41, 0x55, 0x4E, 0x35, 0x46, 0x37, 0x6B, 0x52, 0x2F, 0x71, 0x35, 0x52, 0x34, 0x5A, 0x4A, 0x6A, 0x54, 0x39, 0x69, 0x6A, 0x64, 0x68, 0x39, 0x68, ++ 0x77, 0x5A, 0x58, 0x54, 0x37, 0x44, 0x72, 0x6B, 0x54, 0x36, 0x36, 0x63, 0x50, 0x59, 0x61, 0x6B, 0x79, 0x6C, 0x73, 0x7A, 0x65, 0x75, 0x2B, 0x31, 0x6A, 0x54, 0x42, 0x69, 0x37, 0x71, 0x55, 0x44, 0x33, 0x6F, 0x46, 0x52, 0x75, 0x49, 0x49, 0x68, ++ 0x78, 0x64, 0x52, 0x6A, 0x71, 0x0A, 0x65, 0x72, 0x51, 0x30, 0x63, 0x75, 0x41, 0x6A, 0x4A, 0x33, 0x64, 0x63, 0x74, 0x70, 0x44, 0x71, 0x68, 0x69, 0x56, 0x41, 0x71, 0x2B, 0x38, 0x7A, 0x44, 0x38, 0x75, 0x66, 0x67, 0x72, 0x36, 0x69, 0x49, 0x50, ++ 0x76, 0x32, 0x74, 0x53, 0x30, 0x61, 0x35, 0x73, 0x4B, 0x46, 0x73, 0x58, 0x51, 0x50, 0x2B, 0x38, 0x68, 0x6C, 0x41, 0x71, 0x52, 0x53, 0x41, 0x55, 0x66, 0x64, 0x53, 0x53, 0x4C, 0x42, 0x76, 0x39, 0x6A, 0x72, 0x61, 0x36, 0x78, 0x2B, 0x33, 0x75, ++ 0x78, 0x6A, 0x0A, 0x4D, 0x78, 0x57, 0x33, 0x49, 0x77, 0x69, 0x50, 0x78, 0x67, 0x2B, 0x4E, 0x51, 0x56, 0x72, 0x64, 0x6A, 0x73, 0x57, 0x35, 0x6A, 0x2B, 0x56, 0x46, 0x50, 0x33, 0x6A, 0x62, 0x75, 0x74, 0x49, 0x62, 0x51, 0x4C, 0x48, 0x2B, 0x63, ++ 0x55, 0x30, 0x2F, 0x34, 0x49, 0x47, 0x69, 0x75, 0x6C, 0x36, 0x30, 0x37, 0x42, 0x58, 0x67, 0x6B, 0x39, 0x30, 0x49, 0x48, 0x33, 0x37, 0x68, 0x56, 0x5A, 0x6B, 0x4C, 0x49, 0x64, 0x36, 0x54, 0x6E, 0x67, 0x72, 0x37, 0x35, 0x71, 0x4E, 0x4A, 0x0A, ++ 0x76, 0x54, 0x59, 0x77, 0x2F, 0x75, 0x64, 0x33, 0x73, 0x71, 0x42, 0x31, 0x6C, 0x37, 0x55, 0x74, 0x67, 0x59, 0x67, 0x58, 0x5A, 0x53, 0x44, 0x33, 0x32, 0x70, 0x41, 0x41, 0x6E, 0x38, 0x6C, 0x53, 0x7A, 0x44, 0x4C, 0x4B, 0x4E, 0x58, 0x7A, 0x31, ++ 0x50, 0x51, 0x2F, 0x59, 0x4B, 0x39, 0x66, 0x31, 0x4A, 0x6D, 0x7A, 0x4A, 0x42, 0x6A, 0x53, 0x57, 0x46, 0x75, 0x70, 0x77, 0x57, 0x52, 0x6F, 0x79, 0x65, 0x58, 0x6B, 0x4C, 0x74, 0x6F, 0x68, 0x2F, 0x44, 0x31, 0x4A, 0x49, 0x0A, 0x50, 0x62, 0x39, ++ 0x73, 0x32, 0x4B, 0x4A, 0x45, 0x4C, 0x74, 0x46, 0x4F, 0x74, 0x33, 0x4A, 0x59, 0x30, 0x34, 0x6B, 0x54, 0x6C, 0x66, 0x35, 0x45, 0x71, 0x2F, 0x6A, 0x58, 0x69, 0x78, 0x74, 0x75, 0x6E, 0x4C, 0x77, 0x73, 0x6F, 0x46, 0x76, 0x56, 0x61, 0x67, 0x43, ++ 0x76, 0x58, 0x7A, 0x66, 0x68, 0x31, 0x66, 0x6F, 0x51, 0x43, 0x35, 0x69, 0x63, 0x68, 0x75, 0x63, 0x6D, 0x6A, 0x38, 0x37, 0x77, 0x37, 0x47, 0x36, 0x4B, 0x56, 0x77, 0x75, 0x41, 0x34, 0x30, 0x36, 0x79, 0x0A, 0x77, 0x4B, 0x42, 0x6A, 0x59, 0x5A, ++ 0x43, 0x36, 0x56, 0x57, 0x67, 0x33, 0x64, 0x47, 0x71, 0x32, 0x6B, 0x74, 0x75, 0x66, 0x6F, 0x59, 0x59, 0x69, 0x74, 0x6D, 0x55, 0x6E, 0x44, 0x75, 0x79, 0x32, 0x6E, 0x30, 0x4A, 0x67, 0x35, 0x47, 0x66, 0x43, 0x74, 0x64, 0x70, 0x42, 0x43, 0x38, ++ 0x54, 0x54, 0x69, 0x32, 0x45, 0x62, 0x76, 0x50, 0x6F, 0x66, 0x6B, 0x53, 0x76, 0x58, 0x52, 0x41, 0x64, 0x65, 0x75, 0x69, 0x6D, 0x73, 0x32, 0x63, 0x58, 0x70, 0x37, 0x31, 0x4E, 0x49, 0x0A, 0x57, 0x75, 0x75, 0x41, 0x38, 0x53, 0x68, 0x59, 0x49, ++ 0x63, 0x32, 0x77, 0x42, 0x6C, 0x58, 0x37, 0x4A, 0x7A, 0x39, 0x54, 0x6B, 0x48, 0x43, 0x70, 0x42, 0x42, 0x35, 0x58, 0x4A, 0x37, 0x6B, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, ++ 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, ++ 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x45, 0x43, 0x43, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, ++ 0x0A, 0x4D, 0x49, 0x49, 0x43, 0x6A, 0x54, 0x43, 0x43, 0x41, 0x68, 0x53, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x49, 0x64, 0x65, 0x62, 0x66, 0x79, 0x38, 0x46, 0x6F, 0x57, 0x36, 0x67, 0x77, 0x43, 0x67, 0x59, 0x49, 0x4B, 0x6F, 0x5A, ++ 0x49, 0x7A, 0x6A, 0x30, 0x45, 0x41, 0x77, 0x49, 0x77, 0x66, 0x44, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x56, 0x56, 0x4D, 0x78, 0x44, 0x6A, 0x41, 0x4D, 0x42, 0x67, 0x4E, 0x56, 0x0A, 0x42, 0x41, ++ 0x67, 0x4D, 0x42, 0x56, 0x52, 0x6C, 0x65, 0x47, 0x46, 0x7A, 0x4D, 0x52, 0x41, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x48, 0x44, 0x41, 0x64, 0x49, 0x62, 0x33, 0x56, 0x7A, 0x64, 0x47, 0x39, 0x75, 0x4D, 0x52, 0x67, 0x77, 0x46, 0x67, ++ 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x44, 0x41, 0x39, 0x54, 0x55, 0x30, 0x77, 0x67, 0x51, 0x32, 0x39, 0x79, 0x63, 0x47, 0x39, 0x79, 0x59, 0x58, 0x52, 0x70, 0x62, 0x32, 0x34, 0x78, 0x4D, 0x54, 0x41, 0x76, 0x0A, 0x42, 0x67, 0x4E, 0x56, 0x42, ++ 0x41, 0x4D, 0x4D, 0x4B, 0x46, 0x4E, 0x54, 0x54, 0x43, 0x35, 0x6A, 0x62, 0x32, 0x30, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x61, 0x57, 0x5A, 0x70, 0x59, 0x32, 0x46, 0x30, 0x61, 0x57, 0x39, 0x75, 0x49, ++ 0x45, 0x46, 0x31, 0x64, 0x47, 0x68, 0x76, 0x63, 0x6D, 0x6C, 0x30, 0x65, 0x53, 0x42, 0x46, 0x51, 0x30, 0x4D, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x54, 0x59, 0x77, 0x4D, 0x6A, 0x45, 0x79, 0x0A, 0x4D, 0x54, 0x67, 0x78, 0x4E, 0x44, 0x41, 0x7A, ++ 0x57, 0x68, 0x63, 0x4E, 0x4E, 0x44, 0x45, 0x77, 0x4D, 0x6A, 0x45, 0x79, 0x4D, 0x54, 0x67, 0x78, 0x4E, 0x44, 0x41, 0x7A, 0x57, 0x6A, 0x42, 0x38, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x56, ++ 0x55, 0x7A, 0x45, 0x4F, 0x4D, 0x41, 0x77, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x41, 0x77, 0x46, 0x56, 0x47, 0x56, 0x34, 0x59, 0x58, 0x4D, 0x78, 0x45, 0x44, 0x41, 0x4F, 0x0A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x63, 0x4D, 0x42, 0x30, 0x68, ++ 0x76, 0x64, 0x58, 0x4E, 0x30, 0x62, 0x32, 0x34, 0x78, 0x47, 0x44, 0x41, 0x57, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x4D, 0x44, 0x31, 0x4E, 0x54, 0x54, 0x43, 0x42, 0x44, 0x62, 0x33, 0x4A, 0x77, 0x62, 0x33, 0x4A, 0x68, 0x64, 0x47, 0x6C, ++ 0x76, 0x62, 0x6A, 0x45, 0x78, 0x4D, 0x43, 0x38, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x77, 0x77, 0x6F, 0x55, 0x31, 0x4E, 0x4D, 0x4C, 0x6D, 0x4E, 0x76, 0x0A, 0x62, 0x53, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x6C, 0x63, 0x6E, ++ 0x52, 0x70, 0x5A, 0x6D, 0x6C, 0x6A, 0x59, 0x58, 0x52, 0x70, 0x62, 0x32, 0x34, 0x67, 0x51, 0x58, 0x56, 0x30, 0x61, 0x47, 0x39, 0x79, 0x61, 0x58, 0x52, 0x35, 0x49, 0x45, 0x56, 0x44, 0x51, 0x7A, 0x42, 0x32, 0x4D, 0x42, 0x41, 0x47, 0x42, 0x79, ++ 0x71, 0x47, 0x53, 0x4D, 0x34, 0x39, 0x41, 0x67, 0x45, 0x47, 0x42, 0x53, 0x75, 0x42, 0x42, 0x41, 0x41, 0x69, 0x41, 0x32, 0x49, 0x41, 0x0A, 0x42, 0x45, 0x56, 0x75, 0x71, 0x56, 0x44, 0x45, 0x70, 0x69, 0x4D, 0x32, 0x6E, 0x6C, 0x38, 0x6F, 0x6A, ++ 0x52, 0x66, 0x4C, 0x6C, 0x69, 0x4A, 0x6B, 0x50, 0x39, 0x78, 0x36, 0x6A, 0x68, 0x33, 0x4D, 0x43, 0x4C, 0x4F, 0x69, 0x63, 0x53, 0x53, 0x36, 0x6A, 0x6B, 0x6D, 0x35, 0x42, 0x42, 0x74, 0x48, 0x6C, 0x6C, 0x69, 0x72, 0x4C, 0x5A, 0x58, 0x49, 0x37, ++ 0x5A, 0x34, 0x49, 0x4E, 0x63, 0x67, 0x6E, 0x36, 0x34, 0x6D, 0x4D, 0x55, 0x31, 0x6A, 0x72, 0x59, 0x6F, 0x72, 0x2B, 0x0A, 0x38, 0x46, 0x73, 0x50, 0x61, 0x7A, 0x46, 0x53, 0x59, 0x30, 0x45, 0x37, 0x69, 0x63, 0x33, 0x73, 0x37, 0x4C, 0x61, 0x4E, ++ 0x47, 0x64, 0x4D, 0x30, 0x42, 0x39, 0x79, 0x37, 0x78, 0x67, 0x5A, 0x2F, 0x77, 0x6B, 0x57, 0x56, 0x37, 0x4D, 0x74, 0x2F, 0x71, 0x43, 0x50, 0x67, 0x43, 0x65, 0x6D, 0x42, 0x2B, 0x76, 0x4E, 0x48, 0x30, 0x36, 0x4E, 0x6A, 0x4D, 0x47, 0x45, 0x77, ++ 0x48, 0x51, 0x59, 0x44, 0x56, 0x52, 0x30, 0x4F, 0x42, 0x42, 0x59, 0x45, 0x46, 0x49, 0x4C, 0x52, 0x0A, 0x68, 0x58, 0x4D, 0x77, 0x35, 0x7A, 0x55, 0x45, 0x30, 0x34, 0x34, 0x43, 0x6B, 0x76, 0x76, 0x6C, 0x70, 0x4E, 0x48, 0x45, 0x49, 0x65, 0x6A, ++ 0x4E, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x48, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x6A, 0x42, 0x42, 0x67, 0x77, 0x46, 0x6F, 0x41, ++ 0x55, 0x67, 0x74, 0x47, 0x46, 0x63, 0x7A, 0x44, 0x6E, 0x4E, 0x51, 0x54, 0x54, 0x0A, 0x6A, 0x67, 0x4B, 0x53, 0x2B, 0x2B, 0x57, 0x6B, 0x30, 0x63, 0x51, 0x68, 0x36, 0x4D, 0x30, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x41, 0x51, ++ 0x48, 0x2F, 0x42, 0x41, 0x51, 0x44, 0x41, 0x67, 0x47, 0x47, 0x4D, 0x41, 0x6F, 0x47, 0x43, 0x43, 0x71, 0x47, 0x53, 0x4D, 0x34, 0x39, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x32, 0x63, 0x41, 0x4D, 0x47, 0x51, 0x43, 0x4D, 0x47, 0x2F, 0x6E, 0x36, 0x31, ++ 0x6B, 0x52, 0x70, 0x47, 0x44, 0x50, 0x59, 0x62, 0x43, 0x57, 0x0A, 0x65, 0x2B, 0x30, 0x46, 0x2B, 0x53, 0x38, 0x54, 0x6B, 0x64, 0x7A, 0x74, 0x35, 0x66, 0x78, 0x51, 0x61, 0x78, 0x46, 0x47, 0x52, 0x72, 0x4D, 0x63, 0x49, 0x51, 0x42, 0x69, 0x75, ++ 0x37, 0x37, 0x44, 0x35, 0x2B, 0x6A, 0x4E, 0x42, 0x35, 0x6E, 0x35, 0x44, 0x51, 0x74, 0x64, 0x63, 0x6A, 0x37, 0x45, 0x71, 0x67, 0x49, 0x77, 0x48, 0x37, 0x79, 0x36, 0x43, 0x2B, 0x49, 0x77, 0x4A, 0x50, 0x74, 0x38, 0x62, 0x59, 0x42, 0x56, 0x43, ++ 0x70, 0x6B, 0x2B, 0x67, 0x41, 0x30, 0x7A, 0x0A, 0x35, 0x57, 0x61, 0x6A, 0x73, 0x36, 0x4F, 0x37, 0x70, 0x64, 0x57, 0x4C, 0x6A, 0x77, 0x6B, 0x73, 0x70, 0x6C, 0x31, 0x2B, 0x34, 0x76, 0x41, 0x48, 0x43, 0x47, 0x68, 0x74, 0x30, 0x6E, 0x78, 0x70, ++ 0x62, 0x6C, 0x2F, 0x66, 0x35, 0x57, 0x70, 0x6C, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x53, 0x53, 0x4C, 0x2E, ++ 0x63, 0x6F, 0x6D, 0x20, 0x45, 0x56, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x53, 0x41, 0x20, ++ 0x52, 0x32, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, ++ 0x49, 0x46, 0x36, 0x7A, 0x43, 0x43, 0x41, 0x39, 0x4F, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x49, 0x56, 0x72, 0x59, 0x70, 0x7A, 0x54, 0x53, 0x38, 0x65, 0x50, 0x59, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, ++ 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x42, 0x51, 0x41, 0x77, 0x67, 0x59, 0x49, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6C, 0x56, 0x54, 0x4D, 0x51, 0x34, 0x77, 0x0A, 0x44, 0x41, 0x59, 0x44, 0x56, ++ 0x51, 0x51, 0x49, 0x44, 0x41, 0x56, 0x55, 0x5A, 0x58, 0x68, 0x68, 0x63, 0x7A, 0x45, 0x51, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x77, 0x77, 0x48, 0x53, 0x47, 0x39, 0x31, 0x63, 0x33, 0x52, 0x76, 0x62, 0x6A, 0x45, 0x59, 0x4D, ++ 0x42, 0x59, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, 0x50, 0x55, 0x31, 0x4E, 0x4D, 0x49, 0x45, 0x4E, 0x76, 0x63, 0x6E, 0x42, 0x76, 0x63, 0x6D, 0x46, 0x30, 0x61, 0x57, 0x39, 0x75, 0x0A, 0x4D, 0x54, 0x63, 0x77, 0x4E, 0x51, 0x59, 0x44, ++ 0x56, 0x51, 0x51, 0x44, 0x44, 0x43, 0x35, 0x54, 0x55, 0x30, 0x77, 0x75, 0x59, 0x32, 0x39, 0x74, 0x49, 0x45, 0x56, 0x57, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x32, 0x56, 0x79, 0x64, 0x47, 0x6C, 0x6D, 0x61, 0x57, 0x4E, 0x68, ++ 0x64, 0x47, 0x6C, 0x76, 0x62, 0x69, 0x42, 0x42, 0x64, 0x58, 0x52, 0x6F, 0x62, 0x33, 0x4A, 0x70, 0x64, 0x48, 0x6B, 0x67, 0x55, 0x6C, 0x4E, 0x42, 0x49, 0x46, 0x49, 0x79, 0x0A, 0x4D, 0x42, 0x34, 0x58, 0x44, 0x54, 0x45, 0x33, 0x4D, 0x44, 0x55, ++ 0x7A, 0x4D, 0x54, 0x45, 0x34, 0x4D, 0x54, 0x51, 0x7A, 0x4E, 0x31, 0x6F, 0x58, 0x44, 0x54, 0x51, 0x79, 0x4D, 0x44, 0x55, 0x7A, 0x4D, 0x44, 0x45, 0x34, 0x4D, 0x54, 0x51, 0x7A, 0x4E, 0x31, 0x6F, 0x77, 0x67, 0x59, 0x49, 0x78, 0x43, 0x7A, 0x41, ++ 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6C, 0x56, 0x54, 0x4D, 0x51, 0x34, 0x77, 0x44, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x49, 0x0A, 0x44, 0x41, 0x56, 0x55, 0x5A, 0x58, 0x68, 0x68, 0x63, 0x7A, 0x45, 0x51, 0x4D, 0x41, ++ 0x34, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x77, 0x77, 0x48, 0x53, 0x47, 0x39, 0x31, 0x63, 0x33, 0x52, 0x76, 0x62, 0x6A, 0x45, 0x59, 0x4D, 0x42, 0x59, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, 0x50, 0x55, 0x31, 0x4E, 0x4D, 0x49, 0x45, ++ 0x4E, 0x76, 0x63, 0x6E, 0x42, 0x76, 0x63, 0x6D, 0x46, 0x30, 0x61, 0x57, 0x39, 0x75, 0x4D, 0x54, 0x63, 0x77, 0x4E, 0x51, 0x59, 0x44, 0x0A, 0x56, 0x51, 0x51, 0x44, 0x44, 0x43, 0x35, 0x54, 0x55, 0x30, 0x77, 0x75, 0x59, 0x32, 0x39, 0x74, 0x49, ++ 0x45, 0x56, 0x57, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x32, 0x56, 0x79, 0x64, 0x47, 0x6C, 0x6D, 0x61, 0x57, 0x4E, 0x68, 0x64, 0x47, 0x6C, 0x76, 0x62, 0x69, 0x42, 0x42, 0x64, 0x58, 0x52, 0x6F, 0x62, 0x33, 0x4A, 0x70, 0x64, ++ 0x48, 0x6B, 0x67, 0x55, 0x6C, 0x4E, 0x42, 0x49, 0x46, 0x49, 0x79, 0x4D, 0x49, 0x49, 0x43, 0x49, 0x6A, 0x41, 0x4E, 0x0A, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x45, 0x46, 0x41, 0x41, 0x4F, 0x43, ++ 0x41, 0x67, 0x38, 0x41, 0x4D, 0x49, 0x49, 0x43, 0x43, 0x67, 0x4B, 0x43, 0x41, 0x67, 0x45, 0x41, 0x6A, 0x7A, 0x5A, 0x6C, 0x51, 0x4F, 0x48, 0x57, 0x54, 0x63, 0x44, 0x58, 0x74, 0x4F, 0x6C, 0x47, 0x32, 0x6D, 0x76, 0x71, 0x4D, 0x30, 0x66, 0x4E, ++ 0x54, 0x50, 0x6C, 0x39, 0x66, 0x62, 0x36, 0x39, 0x4C, 0x54, 0x33, 0x77, 0x32, 0x33, 0x6A, 0x68, 0x0A, 0x68, 0x71, 0x58, 0x5A, 0x75, 0x67, 0x6C, 0x58, 0x61, 0x4F, 0x31, 0x58, 0x50, 0x71, 0x44, 0x51, 0x43, 0x45, 0x47, 0x44, 0x35, 0x79, 0x68, ++ 0x42, 0x4A, 0x42, 0x2F, 0x6A, 0x63, 0x68, 0x58, 0x51, 0x41, 0x52, 0x72, 0x37, 0x58, 0x6E, 0x41, 0x6A, 0x73, 0x73, 0x75, 0x66, 0x4F, 0x65, 0x50, 0x50, 0x78, 0x55, 0x37, 0x47, 0x6B, 0x6D, 0x30, 0x6D, 0x78, 0x6E, 0x75, 0x37, 0x73, 0x39, 0x6F, ++ 0x6E, 0x6E, 0x51, 0x71, 0x47, 0x36, 0x59, 0x45, 0x33, 0x42, 0x66, 0x37, 0x77, 0x0A, 0x63, 0x58, 0x48, 0x73, 0x77, 0x78, 0x7A, 0x70, 0x59, 0x36, 0x49, 0x58, 0x46, 0x4A, 0x33, 0x76, 0x47, 0x32, 0x66, 0x54, 0x68, 0x56, 0x55, 0x43, 0x41, 0x74, ++ 0x5A, 0x4A, 0x79, 0x63, 0x78, 0x61, 0x34, 0x62, 0x48, 0x33, 0x62, 0x7A, 0x4B, 0x66, 0x79, 0x64, 0x51, 0x37, 0x69, 0x45, 0x47, 0x6F, 0x6E, 0x4C, 0x33, 0x4C, 0x71, 0x39, 0x74, 0x74, 0x65, 0x77, 0x6B, 0x66, 0x6F, 0x6B, 0x78, 0x79, 0x6B, 0x4E, ++ 0x6F, 0x72, 0x43, 0x50, 0x7A, 0x50, 0x50, 0x46, 0x54, 0x4F, 0x0A, 0x5A, 0x77, 0x2B, 0x6F, 0x7A, 0x31, 0x32, 0x57, 0x47, 0x51, 0x76, 0x45, 0x34, 0x33, 0x4C, 0x72, 0x72, 0x64, 0x46, 0x39, 0x48, 0x53, 0x66, 0x76, 0x6B, 0x75, 0x73, 0x51, 0x76, ++ 0x31, 0x76, 0x72, 0x4F, 0x36, 0x2F, 0x50, 0x67, 0x4E, 0x33, 0x42, 0x30, 0x70, 0x59, 0x45, 0x57, 0x33, 0x70, 0x2B, 0x70, 0x4B, 0x6B, 0x38, 0x4F, 0x48, 0x61, 0x6B, 0x59, 0x6F, 0x36, 0x67, 0x4F, 0x56, 0x37, 0x71, 0x64, 0x38, 0x39, 0x64, 0x41, ++ 0x46, 0x6D, 0x50, 0x5A, 0x69, 0x77, 0x2B, 0x0A, 0x42, 0x36, 0x4B, 0x6A, 0x42, 0x53, 0x59, 0x52, 0x61, 0x5A, 0x66, 0x71, 0x68, 0x62, 0x63, 0x50, 0x6C, 0x67, 0x74, 0x4C, 0x79, 0x45, 0x44, 0x68, 0x55, 0x4C, 0x6F, 0x75, 0x69, 0x73, 0x76, 0x33, ++ 0x44, 0x35, 0x6F, 0x69, 0x35, 0x33, 0x2B, 0x61, 0x4E, 0x78, 0x50, 0x4E, 0x38, 0x6B, 0x30, 0x54, 0x61, 0x79, 0x48, 0x52, 0x77, 0x4D, 0x77, 0x69, 0x38, 0x71, 0x46, 0x47, 0x39, 0x6B, 0x52, 0x70, 0x6E, 0x4D, 0x70, 0x68, 0x4E, 0x51, 0x63, 0x41, ++ 0x62, 0x39, 0x5A, 0x68, 0x0A, 0x43, 0x42, 0x48, 0x71, 0x75, 0x72, 0x6A, 0x32, 0x36, 0x62, 0x4E, 0x67, 0x35, 0x55, 0x32, 0x35, 0x37, 0x4A, 0x38, 0x55, 0x5A, 0x73, 0x6C, 0x58, 0x57, 0x4E, 0x76, 0x4E, 0x68, 0x32, 0x6E, 0x34, 0x69, 0x6F, 0x59, ++ 0x53, 0x41, 0x30, 0x65, 0x2F, 0x5A, 0x68, 0x4E, 0x32, 0x72, 0x48, 0x64, 0x39, 0x4E, 0x43, 0x53, 0x46, 0x67, 0x38, 0x33, 0x58, 0x71, 0x70, 0x79, 0x51, 0x47, 0x70, 0x38, 0x68, 0x4C, 0x48, 0x39, 0x34, 0x74, 0x32, 0x53, 0x34, 0x32, 0x4F, 0x69, ++ 0x6D, 0x0A, 0x39, 0x48, 0x69, 0x7A, 0x56, 0x63, 0x75, 0x45, 0x30, 0x6A, 0x4C, 0x45, 0x65, 0x4B, 0x36, 0x6A, 0x6A, 0x32, 0x48, 0x64, 0x7A, 0x67, 0x68, 0x54, 0x72, 0x65, 0x79, 0x49, 0x2F, 0x42, 0x58, 0x6B, 0x6D, 0x67, 0x33, 0x6D, 0x6E, 0x78, ++ 0x70, 0x33, 0x7A, 0x6B, 0x79, 0x50, 0x75, 0x42, 0x51, 0x56, 0x50, 0x57, 0x4B, 0x63, 0x68, 0x6A, 0x67, 0x47, 0x41, 0x47, 0x59, 0x53, 0x35, 0x46, 0x6C, 0x32, 0x57, 0x6C, 0x50, 0x41, 0x41, 0x70, 0x69, 0x69, 0x45, 0x43, 0x74, 0x6F, 0x0A, 0x52, ++ 0x48, 0x75, 0x4F, 0x65, 0x63, 0x34, 0x7A, 0x53, 0x6E, 0x61, 0x71, 0x57, 0x34, 0x45, 0x57, 0x47, 0x37, 0x57, 0x4B, 0x32, 0x4E, 0x41, 0x41, 0x65, 0x31, 0x35, 0x69, 0x74, 0x41, 0x6E, 0x57, 0x68, 0x6D, 0x4D, 0x4F, 0x70, 0x67, 0x57, 0x56, 0x53, ++ 0x62, 0x6F, 0x6F, 0x69, 0x34, 0x69, 0x54, 0x73, 0x6A, 0x51, 0x63, 0x32, 0x4B, 0x52, 0x56, 0x62, 0x72, 0x63, 0x63, 0x30, 0x4E, 0x36, 0x5A, 0x56, 0x54, 0x73, 0x6A, 0x39, 0x43, 0x4C, 0x67, 0x2B, 0x53, 0x6C, 0x6D, 0x0A, 0x4A, 0x75, 0x77, 0x67, ++ 0x55, 0x48, 0x66, 0x62, 0x53, 0x67, 0x75, 0x50, 0x76, 0x75, 0x55, 0x43, 0x59, 0x48, 0x42, 0x42, 0x58, 0x74, 0x53, 0x75, 0x55, 0x44, 0x6B, 0x69, 0x46, 0x43, 0x62, 0x4C, 0x73, 0x6A, 0x74, 0x7A, 0x64, 0x46, 0x56, 0x48, 0x42, 0x33, 0x6D, 0x42, ++ 0x4F, 0x61, 0x67, 0x77, 0x45, 0x30, 0x54, 0x6C, 0x42, 0x49, 0x71, 0x75, 0x6C, 0x68, 0x4D, 0x6C, 0x51, 0x67, 0x2B, 0x35, 0x55, 0x38, 0x53, 0x62, 0x2F, 0x4D, 0x33, 0x6B, 0x48, 0x4E, 0x34, 0x38, 0x0A, 0x2B, 0x71, 0x76, 0x57, 0x42, 0x6B, 0x6F, ++ 0x66, 0x5A, 0x36, 0x61, 0x59, 0x4D, 0x42, 0x7A, 0x64, 0x4C, 0x4E, 0x76, 0x63, 0x47, 0x4A, 0x56, 0x58, 0x5A, 0x73, 0x62, 0x2F, 0x58, 0x49, 0x74, 0x57, 0x39, 0x58, 0x63, 0x43, 0x41, 0x77, 0x45, 0x41, 0x41, 0x61, 0x4E, 0x6A, 0x4D, 0x47, 0x45, ++ 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x66, 0x42, 0x67, 0x4E, 0x56, 0x0A, 0x48, 0x53, 0x4D, 0x45, 0x47, 0x44, 0x41, 0x57, 0x67, 0x42, ++ 0x54, 0x35, 0x59, 0x4C, 0x76, 0x55, 0x34, 0x39, 0x55, 0x30, 0x39, 0x72, 0x6A, 0x31, 0x42, 0x6F, 0x41, 0x6C, 0x70, 0x33, 0x50, 0x62, 0x52, 0x6D, 0x6D, 0x6F, 0x6E, 0x6A, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, ++ 0x51, 0x55, 0x2B, 0x57, 0x43, 0x37, 0x31, 0x4F, 0x50, 0x56, 0x4E, 0x50, 0x61, 0x34, 0x39, 0x51, 0x61, 0x41, 0x4A, 0x61, 0x64, 0x7A, 0x32, 0x30, 0x5A, 0x70, 0x0A, 0x71, 0x4A, 0x34, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x41, ++ 0x51, 0x48, 0x2F, 0x42, 0x41, 0x51, 0x44, 0x41, 0x67, 0x47, 0x47, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x43, 0x77, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x41, 0x51, 0x42, 0x57, 0x73, ++ 0x34, 0x37, 0x4C, 0x43, 0x70, 0x31, 0x4A, 0x6A, 0x72, 0x2B, 0x6B, 0x78, 0x4A, 0x47, 0x37, 0x5A, 0x68, 0x63, 0x46, 0x55, 0x5A, 0x68, 0x31, 0x0A, 0x2B, 0x2B, 0x56, 0x51, 0x4C, 0x48, 0x71, 0x65, 0x38, 0x52, 0x54, 0x36, 0x71, 0x39, 0x4F, 0x4B, ++ 0x50, 0x76, 0x2B, 0x52, 0x4B, 0x59, 0x39, 0x6A, 0x69, 0x39, 0x69, 0x30, 0x71, 0x56, 0x51, 0x42, 0x44, 0x62, 0x36, 0x54, 0x68, 0x69, 0x2F, 0x35, 0x53, 0x6D, 0x33, 0x48, 0x58, 0x76, 0x56, 0x58, 0x2B, 0x63, 0x70, 0x56, 0x48, 0x42, 0x4B, 0x2B, ++ 0x52, 0x77, 0x38, 0x32, 0x78, 0x64, 0x39, 0x71, 0x74, 0x39, 0x74, 0x31, 0x77, 0x6B, 0x63, 0x6C, 0x66, 0x37, 0x6E, 0x78, 0x0A, 0x59, 0x2F, 0x68, 0x6F, 0x4C, 0x56, 0x55, 0x45, 0x30, 0x66, 0x4B, 0x4E, 0x73, 0x4B, 0x54, 0x50, 0x76, 0x44, 0x78, ++ 0x65, 0x48, 0x33, 0x6A, 0x6E, 0x70, 0x61, 0x41, 0x67, 0x63, 0x4C, 0x41, 0x45, 0x78, 0x62, 0x66, 0x33, 0x63, 0x71, 0x66, 0x65, 0x49, 0x67, 0x32, 0x39, 0x4D, 0x79, 0x56, 0x47, 0x6A, 0x47, 0x53, 0x53, 0x4A, 0x75, 0x4D, 0x2B, 0x4C, 0x6D, 0x4F, ++ 0x57, 0x32, 0x70, 0x75, 0x4D, 0x50, 0x66, 0x67, 0x59, 0x43, 0x64, 0x63, 0x44, 0x7A, 0x48, 0x32, 0x47, 0x0A, 0x67, 0x75, 0x44, 0x4B, 0x42, 0x41, 0x64, 0x52, 0x55, 0x4E, 0x66, 0x2F, 0x6B, 0x74, 0x55, 0x4D, 0x37, 0x39, 0x71, 0x47, 0x6E, 0x35, ++ 0x6E, 0x58, 0x36, 0x37, 0x65, 0x76, 0x61, 0x4F, 0x49, 0x35, 0x4A, 0x70, 0x53, 0x36, 0x61, 0x4C, 0x65, 0x2F, 0x67, 0x39, 0x50, 0x71, 0x65, 0x6D, 0x63, 0x39, 0x59, 0x6D, 0x65, 0x75, 0x4A, 0x65, 0x56, 0x79, 0x36, 0x4F, 0x4C, 0x6B, 0x37, 0x4B, ++ 0x34, 0x53, 0x39, 0x6B, 0x73, 0x72, 0x50, 0x4A, 0x2F, 0x70, 0x73, 0x45, 0x44, 0x7A, 0x0A, 0x4F, 0x46, 0x53, 0x7A, 0x2F, 0x62, 0x64, 0x6F, 0x79, 0x4E, 0x72, 0x47, 0x6A, 0x31, 0x45, 0x38, 0x73, 0x76, 0x75, 0x52, 0x33, 0x42, 0x7A, 0x6E, 0x6D, ++ 0x35, 0x33, 0x68, 0x74, 0x77, 0x31, 0x79, 0x6A, 0x2B, 0x4B, 0x6B, 0x78, 0x4B, 0x6C, 0x34, 0x2B, 0x65, 0x73, 0x55, 0x72, 0x4D, 0x5A, 0x44, 0x42, 0x63, 0x4A, 0x6C, 0x4F, 0x53, 0x67, 0x59, 0x41, 0x73, 0x4F, 0x43, 0x73, 0x70, 0x30, 0x46, 0x76, ++ 0x6D, 0x58, 0x74, 0x6C, 0x6C, 0x39, 0x6C, 0x64, 0x44, 0x7A, 0x37, 0x0A, 0x43, 0x54, 0x55, 0x75, 0x65, 0x35, 0x77, 0x54, 0x2F, 0x52, 0x73, 0x50, 0x58, 0x63, 0x64, 0x74, 0x67, 0x54, 0x70, 0x57, 0x44, 0x38, 0x77, 0x37, 0x34, 0x61, 0x38, 0x43, ++ 0x4C, 0x79, 0x4B, 0x73, 0x52, 0x73, 0x70, 0x47, 0x50, 0x4B, 0x41, 0x63, 0x54, 0x4E, 0x5A, 0x45, 0x74, 0x46, 0x34, 0x75, 0x58, 0x42, 0x56, 0x6D, 0x43, 0x65, 0x45, 0x6D, 0x4B, 0x66, 0x37, 0x47, 0x55, 0x6D, 0x47, 0x36, 0x73, 0x58, 0x50, 0x2F, ++ 0x77, 0x77, 0x79, 0x63, 0x35, 0x57, 0x78, 0x71, 0x0A, 0x6C, 0x44, 0x38, 0x55, 0x79, 0x6B, 0x41, 0x57, 0x6C, 0x59, 0x54, 0x7A, 0x57, 0x61, 0x6D, 0x73, 0x58, 0x30, 0x78, 0x68, 0x6B, 0x32, 0x33, 0x52, 0x4F, 0x38, 0x79, 0x69, 0x6C, 0x51, 0x77, ++ 0x69, 0x70, 0x6D, 0x64, 0x6E, 0x52, 0x43, 0x36, 0x35, 0x32, 0x64, 0x4B, 0x4B, 0x51, 0x62, 0x4E, 0x6D, 0x43, 0x31, 0x72, 0x37, 0x66, 0x53, 0x4F, 0x6C, 0x38, 0x68, 0x71, 0x77, 0x2F, 0x39, 0x36, 0x62, 0x67, 0x35, 0x51, 0x75, 0x30, 0x54, 0x2F, ++ 0x66, 0x6B, 0x72, 0x65, 0x52, 0x0A, 0x72, 0x77, 0x55, 0x37, 0x5A, 0x63, 0x65, 0x67, 0x62, 0x4C, 0x48, 0x4E, 0x59, 0x68, 0x4C, 0x44, 0x6B, 0x42, 0x76, 0x6A, 0x4A, 0x63, 0x34, 0x30, 0x76, 0x47, 0x39, 0x33, 0x64, 0x72, 0x45, 0x51, 0x77, 0x2F, ++ 0x63, 0x46, 0x47, 0x73, 0x44, 0x57, 0x72, 0x33, 0x52, 0x69, 0x53, 0x42, 0x64, 0x33, 0x6B, 0x6D, 0x6D, 0x51, 0x59, 0x52, 0x7A, 0x65, 0x6C, 0x59, 0x42, 0x30, 0x56, 0x49, 0x38, 0x59, 0x48, 0x4D, 0x50, 0x7A, 0x41, 0x39, 0x43, 0x2F, 0x70, 0x45, ++ 0x4E, 0x31, 0x0A, 0x68, 0x6C, 0x4D, 0x59, 0x65, 0x67, 0x6F, 0x75, 0x43, 0x52, 0x77, 0x32, 0x6E, 0x35, 0x48, 0x39, 0x67, 0x6F, 0x6F, 0x69, 0x53, 0x39, 0x45, 0x4F, 0x55, 0x43, 0x58, 0x64, 0x79, 0x77, 0x4D, 0x4D, 0x46, 0x38, 0x6D, 0x44, 0x41, ++ 0x41, 0x68, 0x4F, 0x4E, 0x55, 0x32, 0x4B, 0x69, 0x2B, 0x33, 0x77, 0x41, 0x70, 0x52, 0x6D, 0x4C, 0x45, 0x52, 0x2F, 0x79, 0x35, 0x55, 0x6E, 0x6C, 0x68, 0x65, 0x74, 0x43, 0x54, 0x43, 0x73, 0x74, 0x6E, 0x45, 0x58, 0x62, 0x6F, 0x73, 0x58, 0x0A, ++ 0x39, 0x68, 0x77, 0x4A, 0x31, 0x43, 0x30, 0x37, 0x6D, 0x4B, 0x56, 0x78, 0x30, 0x31, 0x51, 0x54, 0x32, 0x57, 0x44, 0x7A, 0x39, 0x55, 0x74, 0x6D, 0x54, 0x2F, 0x72, 0x78, 0x37, 0x69, 0x41, 0x53, 0x6A, 0x62, 0x53, 0x73, 0x56, 0x37, 0x46, 0x46, ++ 0x59, 0x36, 0x47, 0x73, 0x64, 0x71, 0x6E, 0x43, 0x2B, 0x77, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, ++ 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x45, 0x56, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, ++ 0x45, 0x43, 0x43, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x43, ++ 0x6C, 0x44, 0x43, 0x43, 0x41, 0x68, 0x71, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x49, 0x4C, 0x43, 0x6D, 0x63, 0x57, 0x78, 0x62, 0x74, 0x42, 0x5A, 0x55, 0x77, 0x43, 0x67, 0x59, 0x49, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x45, ++ 0x41, 0x77, 0x49, 0x77, 0x66, 0x7A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x56, 0x56, 0x4D, 0x78, 0x44, 0x6A, 0x41, 0x4D, 0x42, 0x67, 0x4E, 0x56, 0x0A, 0x42, 0x41, 0x67, 0x4D, 0x42, 0x56, 0x52, ++ 0x6C, 0x65, 0x47, 0x46, 0x7A, 0x4D, 0x52, 0x41, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x48, 0x44, 0x41, 0x64, 0x49, 0x62, 0x33, 0x56, 0x7A, 0x64, 0x47, 0x39, 0x75, 0x4D, 0x52, 0x67, 0x77, 0x46, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, ++ 0x4B, 0x44, 0x41, 0x39, 0x54, 0x55, 0x30, 0x77, 0x67, 0x51, 0x32, 0x39, 0x79, 0x63, 0x47, 0x39, 0x79, 0x59, 0x58, 0x52, 0x70, 0x62, 0x32, 0x34, 0x78, 0x4E, 0x44, 0x41, 0x79, 0x0A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x4D, 0x4B, 0x31, ++ 0x4E, 0x54, 0x54, 0x43, 0x35, 0x6A, 0x62, 0x32, 0x30, 0x67, 0x52, 0x56, 0x59, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x61, 0x57, 0x5A, 0x70, 0x59, 0x32, 0x46, 0x30, 0x61, 0x57, 0x39, 0x75, 0x49, 0x45, ++ 0x46, 0x31, 0x64, 0x47, 0x68, 0x76, 0x63, 0x6D, 0x6C, 0x30, 0x65, 0x53, 0x42, 0x46, 0x51, 0x30, 0x4D, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x54, 0x59, 0x77, 0x0A, 0x4D, 0x6A, 0x45, 0x79, 0x4D, 0x54, 0x67, 0x78, 0x4E, 0x54, 0x49, 0x7A, 0x57, ++ 0x68, 0x63, 0x4E, 0x4E, 0x44, 0x45, 0x77, 0x4D, 0x6A, 0x45, 0x79, 0x4D, 0x54, 0x67, 0x78, 0x4E, 0x54, 0x49, 0x7A, 0x57, 0x6A, 0x42, 0x2F, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x56, 0x55, ++ 0x7A, 0x45, 0x4F, 0x4D, 0x41, 0x77, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x41, 0x77, 0x46, 0x56, 0x47, 0x56, 0x34, 0x59, 0x58, 0x4D, 0x78, 0x0A, 0x45, 0x44, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x63, 0x4D, 0x42, 0x30, 0x68, 0x76, ++ 0x64, 0x58, 0x4E, 0x30, 0x62, 0x32, 0x34, 0x78, 0x47, 0x44, 0x41, 0x57, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x4D, 0x44, 0x31, 0x4E, 0x54, 0x54, 0x43, 0x42, 0x44, 0x62, 0x33, 0x4A, 0x77, 0x62, 0x33, 0x4A, 0x68, 0x64, 0x47, 0x6C, 0x76, ++ 0x62, 0x6A, 0x45, 0x30, 0x4D, 0x44, 0x49, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x77, 0x77, 0x72, 0x55, 0x31, 0x4E, 0x4D, 0x0A, 0x4C, 0x6D, 0x4E, 0x76, 0x62, 0x53, 0x42, 0x46, 0x56, 0x69, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, ++ 0x6C, 0x63, 0x6E, 0x52, 0x70, 0x5A, 0x6D, 0x6C, 0x6A, 0x59, 0x58, 0x52, 0x70, 0x62, 0x32, 0x34, 0x67, 0x51, 0x58, 0x56, 0x30, 0x61, 0x47, 0x39, 0x79, 0x61, 0x58, 0x52, 0x35, 0x49, 0x45, 0x56, 0x44, 0x51, 0x7A, 0x42, 0x32, 0x4D, 0x42, 0x41, ++ 0x47, 0x42, 0x79, 0x71, 0x47, 0x53, 0x4D, 0x34, 0x39, 0x41, 0x67, 0x45, 0x47, 0x42, 0x53, 0x75, 0x42, 0x0A, 0x42, 0x41, 0x41, 0x69, 0x41, 0x32, 0x49, 0x41, 0x42, 0x4B, 0x6F, 0x53, 0x52, 0x35, 0x43, 0x59, 0x47, 0x2F, 0x76, 0x76, 0x77, 0x30, ++ 0x41, 0x48, 0x67, 0x79, 0x42, 0x4F, 0x38, 0x54, 0x43, 0x43, 0x6F, 0x67, 0x62, 0x52, 0x38, 0x70, 0x4B, 0x47, 0x59, 0x66, 0x4C, 0x32, 0x49, 0x57, 0x6A, 0x4B, 0x41, 0x4D, 0x54, 0x48, 0x36, 0x6B, 0x4D, 0x41, 0x56, 0x49, 0x62, 0x63, 0x2F, 0x52, ++ 0x2F, 0x66, 0x41, 0x4C, 0x68, 0x42, 0x59, 0x6C, 0x7A, 0x63, 0x63, 0x42, 0x59, 0x79, 0x0A, 0x33, 0x68, 0x2B, 0x5A, 0x31, 0x4D, 0x7A, 0x46, 0x42, 0x38, 0x67, 0x49, 0x48, 0x32, 0x45, 0x57, 0x42, 0x31, 0x45, 0x39, 0x66, 0x56, 0x77, 0x48, 0x55, ++ 0x2B, 0x4D, 0x31, 0x4F, 0x49, 0x7A, 0x66, 0x7A, 0x5A, 0x2F, 0x5A, 0x4C, 0x67, 0x31, 0x4B, 0x74, 0x68, 0x6B, 0x75, 0x57, 0x6E, 0x42, 0x61, 0x42, 0x75, 0x32, 0x2B, 0x38, 0x4B, 0x47, 0x77, 0x79, 0x74, 0x41, 0x4A, 0x4B, 0x61, 0x4E, 0x6A, 0x4D, ++ 0x47, 0x45, 0x77, 0x48, 0x51, 0x59, 0x44, 0x56, 0x52, 0x30, 0x4F, 0x0A, 0x42, 0x42, 0x59, 0x45, 0x46, 0x46, 0x76, 0x4B, 0x58, 0x75, 0x58, 0x65, 0x30, 0x6F, 0x47, 0x71, 0x7A, 0x61, 0x67, 0x74, 0x5A, 0x46, 0x47, 0x32, 0x32, 0x58, 0x4B, 0x62, ++ 0x6C, 0x2B, 0x5A, 0x50, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x48, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x6A, 0x42, 0x42, 0x67, 0x77, ++ 0x46, 0x6F, 0x41, 0x55, 0x57, 0x38, 0x70, 0x65, 0x0A, 0x35, 0x64, 0x37, 0x53, 0x67, 0x61, 0x72, 0x4E, 0x71, 0x43, 0x31, 0x6B, 0x55, 0x62, 0x62, 0x5A, 0x63, 0x70, 0x75, 0x58, 0x35, 0x6B, 0x38, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, ++ 0x50, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x51, 0x44, 0x41, 0x67, 0x47, 0x47, 0x4D, 0x41, 0x6F, 0x47, 0x43, 0x43, 0x71, 0x47, 0x53, 0x4D, 0x34, 0x39, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x32, 0x67, 0x41, 0x4D, 0x47, 0x55, 0x43, 0x4D, 0x51, 0x43, ++ 0x4B, 0x35, 0x6B, 0x43, 0x4A, 0x0A, 0x4E, 0x2B, 0x76, 0x70, 0x31, 0x52, 0x50, 0x5A, 0x79, 0x74, 0x52, 0x72, 0x4A, 0x50, 0x4F, 0x77, 0x50, 0x59, 0x64, 0x47, 0x57, 0x42, 0x72, 0x73, 0x73, 0x64, 0x39, 0x76, 0x2B, 0x31, 0x61, 0x36, 0x63, 0x47, ++ 0x76, 0x48, 0x4F, 0x4D, 0x7A, 0x6F, 0x73, 0x59, 0x78, 0x50, 0x44, 0x2F, 0x66, 0x78, 0x5A, 0x33, 0x59, 0x4F, 0x67, 0x39, 0x41, 0x65, 0x55, 0x59, 0x38, 0x43, 0x4D, 0x44, 0x33, 0x32, 0x49, 0x79, 0x67, 0x6D, 0x54, 0x4D, 0x5A, 0x67, 0x68, 0x35, ++ 0x4D, 0x6D, 0x0A, 0x6D, 0x37, 0x49, 0x31, 0x48, 0x72, 0x72, 0x57, 0x39, 0x7A, 0x7A, 0x52, 0x48, 0x4D, 0x37, 0x36, 0x4A, 0x54, 0x79, 0x6D, 0x47, 0x6F, 0x45, 0x56, 0x57, 0x2F, 0x4D, 0x53, 0x44, 0x32, 0x7A, 0x75, 0x5A, 0x59, 0x72, 0x4A, 0x68, ++ 0x36, 0x6A, 0x35, 0x42, 0x2B, 0x42, 0x69, 0x6D, 0x6F, 0x78, 0x63, 0x53, 0x67, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, ++ 0x2D, 0x0A, 0x0A, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x52, 0x36, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, ++ 0x49, 0x49, 0x46, 0x67, 0x7A, 0x43, 0x43, 0x41, 0x32, 0x75, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x4F, 0x52, 0x65, 0x61, 0x37, 0x41, 0x34, 0x4D, 0x7A, 0x77, 0x34, 0x56, 0x6C, 0x53, 0x4F, 0x62, 0x2F, 0x52, 0x56, 0x45, 0x77, 0x44, ++ 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4D, 0x42, 0x51, 0x41, 0x77, 0x54, 0x44, 0x45, 0x67, 0x4D, 0x42, 0x34, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x78, 0x4D, 0x58, 0x0A, 0x52, 0x32, 0x78, 0x76, ++ 0x59, 0x6D, 0x46, 0x73, 0x55, 0x32, 0x6C, 0x6E, 0x62, 0x69, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x42, 0x49, 0x43, 0x30, 0x67, 0x55, 0x6A, 0x59, 0x78, 0x45, 0x7A, 0x41, 0x52, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, ++ 0x43, 0x6B, 0x64, 0x73, 0x62, 0x32, 0x4A, 0x68, 0x62, 0x46, 0x4E, 0x70, 0x5A, 0x32, 0x34, 0x78, 0x45, 0x7A, 0x41, 0x52, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x43, 0x6B, 0x64, 0x73, 0x0A, 0x62, 0x32, 0x4A, 0x68, 0x62, 0x46, 0x4E, ++ 0x70, 0x5A, 0x32, 0x34, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x54, 0x51, 0x78, 0x4D, 0x6A, 0x45, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x57, 0x68, 0x63, 0x4E, 0x4D, 0x7A, 0x51, 0x78, 0x4D, 0x6A, 0x45, 0x77, 0x4D, 0x44, 0x41, ++ 0x77, 0x4D, 0x44, 0x41, 0x77, 0x57, 0x6A, 0x42, 0x4D, 0x4D, 0x53, 0x41, 0x77, 0x48, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4C, 0x45, 0x78, 0x64, 0x48, 0x62, 0x47, 0x39, 0x69, 0x0A, 0x59, 0x57, 0x78, 0x54, 0x61, 0x57, 0x64, 0x75, 0x49, 0x46, ++ 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x67, 0x4C, 0x53, 0x42, 0x53, 0x4E, 0x6A, 0x45, 0x54, 0x4D, 0x42, 0x45, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x4B, 0x52, 0x32, 0x78, 0x76, 0x59, 0x6D, 0x46, 0x73, 0x55, 0x32, ++ 0x6C, 0x6E, 0x62, 0x6A, 0x45, 0x54, 0x4D, 0x42, 0x45, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x4B, 0x52, 0x32, 0x78, 0x76, 0x59, 0x6D, 0x46, 0x73, 0x0A, 0x55, 0x32, 0x6C, 0x6E, 0x62, 0x6A, 0x43, 0x43, 0x41, 0x69, 0x49, 0x77, 0x44, ++ 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x50, 0x41, 0x44, 0x43, 0x43, 0x41, 0x67, 0x6F, 0x43, 0x67, 0x67, 0x49, 0x42, 0x41, 0x4A, 0x55, 0x48, 0x36, ++ 0x48, 0x50, 0x4B, 0x5A, 0x76, 0x6E, 0x73, 0x46, 0x4D, 0x70, 0x37, 0x50, 0x50, 0x63, 0x4E, 0x43, 0x50, 0x47, 0x30, 0x52, 0x51, 0x73, 0x73, 0x0A, 0x67, 0x72, 0x52, 0x49, 0x78, 0x75, 0x74, 0x62, 0x50, 0x4B, 0x36, 0x44, 0x75, 0x45, 0x47, 0x53, ++ 0x4D, 0x78, 0x53, 0x6B, 0x62, 0x33, 0x2F, 0x70, 0x4B, 0x73, 0x7A, 0x47, 0x73, 0x49, 0x68, 0x72, 0x78, 0x62, 0x61, 0x4A, 0x30, 0x63, 0x61, 0x79, 0x2F, 0x78, 0x54, 0x4F, 0x55, 0x52, 0x51, 0x68, 0x37, 0x45, 0x72, 0x64, 0x47, 0x31, 0x72, 0x47, ++ 0x31, 0x6F, 0x66, 0x75, 0x54, 0x54, 0x6F, 0x56, 0x42, 0x75, 0x31, 0x6B, 0x5A, 0x67, 0x75, 0x53, 0x67, 0x4D, 0x70, 0x45, 0x0A, 0x33, 0x6E, 0x4F, 0x55, 0x54, 0x76, 0x4F, 0x6E, 0x69, 0x58, 0x39, 0x50, 0x65, 0x47, 0x4D, 0x49, 0x79, 0x42, 0x4A, ++ 0x51, 0x62, 0x55, 0x4A, 0x6D, 0x4C, 0x30, 0x32, 0x35, 0x65, 0x53, 0x68, 0x4E, 0x55, 0x68, 0x71, 0x4B, 0x47, 0x6F, 0x43, 0x33, 0x47, 0x59, 0x45, 0x4F, 0x66, 0x73, 0x53, 0x4B, 0x76, 0x47, 0x52, 0x4D, 0x49, 0x52, 0x78, 0x44, 0x61, 0x4E, 0x63, ++ 0x39, 0x50, 0x49, 0x72, 0x46, 0x73, 0x6D, 0x62, 0x56, 0x6B, 0x4A, 0x71, 0x33, 0x4D, 0x51, 0x62, 0x46, 0x0A, 0x76, 0x75, 0x4A, 0x74, 0x4D, 0x67, 0x61, 0x6D, 0x48, 0x76, 0x6D, 0x35, 0x36, 0x36, 0x71, 0x6A, 0x75, 0x4C, 0x2B, 0x2B, 0x67, 0x6D, ++ 0x4E, 0x51, 0x30, 0x50, 0x41, 0x59, 0x69, 0x64, 0x2F, 0x6B, 0x44, 0x33, 0x6E, 0x31, 0x36, 0x71, 0x49, 0x66, 0x4B, 0x74, 0x4A, 0x77, 0x4C, 0x6E, 0x76, 0x6E, 0x76, 0x4A, 0x4F, 0x37, 0x62, 0x56, 0x50, 0x69, 0x53, 0x48, 0x79, 0x4D, 0x45, 0x41, ++ 0x63, 0x34, 0x2F, 0x32, 0x61, 0x79, 0x64, 0x32, 0x46, 0x2B, 0x34, 0x4F, 0x71, 0x4D, 0x0A, 0x50, 0x4B, 0x71, 0x30, 0x70, 0x50, 0x62, 0x7A, 0x6C, 0x55, 0x6F, 0x53, 0x42, 0x32, 0x33, 0x39, 0x6A, 0x4C, 0x4B, 0x4A, 0x7A, 0x39, 0x43, 0x67, 0x59, ++ 0x58, 0x66, 0x49, 0x57, 0x48, 0x53, 0x77, 0x31, 0x43, 0x4D, 0x36, 0x39, 0x31, 0x30, 0x36, 0x79, 0x71, 0x4C, 0x62, 0x6E, 0x51, 0x6E, 0x65, 0x58, 0x55, 0x51, 0x74, 0x6B, 0x50, 0x47, 0x42, 0x7A, 0x56, 0x65, 0x53, 0x2B, 0x6E, 0x36, 0x38, 0x55, ++ 0x41, 0x52, 0x6A, 0x4E, 0x4E, 0x39, 0x72, 0x6B, 0x78, 0x69, 0x2B, 0x0A, 0x61, 0x7A, 0x61, 0x79, 0x4F, 0x65, 0x53, 0x73, 0x4A, 0x44, 0x61, 0x33, 0x38, 0x4F, 0x2B, 0x32, 0x48, 0x42, 0x4E, 0x58, 0x6B, 0x37, 0x62, 0x65, 0x73, 0x76, 0x6A, 0x69, ++ 0x68, 0x62, 0x64, 0x7A, 0x6F, 0x72, 0x67, 0x31, 0x71, 0x6B, 0x58, 0x79, 0x34, 0x4A, 0x30, 0x32, 0x6F, 0x57, 0x39, 0x55, 0x69, 0x76, 0x46, 0x79, 0x56, 0x6D, 0x34, 0x75, 0x69, 0x4D, 0x56, 0x52, 0x51, 0x6B, 0x51, 0x56, 0x6C, 0x4F, 0x36, 0x6A, ++ 0x78, 0x54, 0x69, 0x57, 0x6D, 0x30, 0x35, 0x4F, 0x0A, 0x57, 0x67, 0x74, 0x48, 0x38, 0x77, 0x59, 0x32, 0x53, 0x58, 0x63, 0x77, 0x76, 0x48, 0x45, 0x33, 0x35, 0x61, 0x62, 0x73, 0x49, 0x51, 0x68, 0x31, 0x2F, 0x4F, 0x5A, 0x68, 0x46, 0x6A, 0x39, ++ 0x33, 0x31, 0x64, 0x6D, 0x52, 0x6C, 0x34, 0x51, 0x4B, 0x62, 0x4E, 0x51, 0x43, 0x54, 0x58, 0x54, 0x41, 0x46, 0x4F, 0x33, 0x39, 0x4F, 0x66, 0x75, 0x44, 0x38, 0x6C, 0x34, 0x55, 0x6F, 0x51, 0x53, 0x77, 0x43, 0x2B, 0x6E, 0x2B, 0x37, 0x6F, 0x2F, ++ 0x68, 0x62, 0x67, 0x75, 0x79, 0x0A, 0x43, 0x4C, 0x4E, 0x68, 0x5A, 0x67, 0x6C, 0x71, 0x73, 0x51, 0x59, 0x36, 0x5A, 0x5A, 0x5A, 0x5A, 0x77, 0x50, 0x41, 0x31, 0x2F, 0x63, 0x6E, 0x61, 0x4B, 0x49, 0x30, 0x61, 0x45, 0x59, 0x64, 0x77, 0x67, 0x51, ++ 0x71, 0x6F, 0x6D, 0x6E, 0x55, 0x64, 0x6E, 0x6A, 0x71, 0x47, 0x42, 0x51, 0x43, 0x65, 0x32, 0x34, 0x44, 0x57, 0x4A, 0x66, 0x6E, 0x63, 0x42, 0x5A, 0x34, 0x6E, 0x57, 0x55, 0x78, 0x32, 0x4F, 0x56, 0x76, 0x71, 0x2B, 0x61, 0x57, 0x68, 0x32, 0x49, ++ 0x4D, 0x50, 0x0A, 0x30, 0x66, 0x2F, 0x66, 0x4D, 0x42, 0x48, 0x35, 0x68, 0x63, 0x38, 0x7A, 0x53, 0x50, 0x58, 0x4B, 0x62, 0x57, 0x51, 0x55, 0x4C, 0x48, 0x70, 0x59, 0x54, 0x39, 0x4E, 0x4C, 0x43, 0x45, 0x6E, 0x46, 0x6C, 0x57, 0x51, 0x61, 0x59, ++ 0x77, 0x35, 0x35, 0x50, 0x66, 0x57, 0x7A, 0x6A, 0x4D, 0x70, 0x59, 0x72, 0x5A, 0x78, 0x43, 0x52, 0x58, 0x6C, 0x75, 0x44, 0x6F, 0x63, 0x5A, 0x58, 0x46, 0x53, 0x78, 0x5A, 0x62, 0x61, 0x2F, 0x6A, 0x4A, 0x76, 0x63, 0x45, 0x2B, 0x6B, 0x4E, 0x0A, ++ 0x62, 0x37, 0x67, 0x75, 0x33, 0x47, 0x64, 0x75, 0x79, 0x59, 0x73, 0x52, 0x74, 0x59, 0x51, 0x55, 0x69, 0x67, 0x41, 0x5A, 0x63, 0x49, 0x4E, 0x35, 0x6B, 0x5A, 0x65, 0x52, 0x31, 0x42, 0x6F, 0x6E, 0x76, 0x7A, 0x63, 0x65, 0x4D, 0x67, 0x66, 0x59, ++ 0x46, 0x47, 0x4D, 0x38, 0x4B, 0x45, 0x79, 0x76, 0x41, 0x67, 0x4D, 0x42, 0x41, 0x41, 0x47, 0x6A, 0x59, 0x7A, 0x42, 0x68, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, 0x0A, 0x41, 0x77, 0x49, ++ 0x42, 0x42, 0x6A, 0x41, 0x50, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x52, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x54, 0x41, 0x44, 0x41, 0x51, 0x48, 0x2F, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x53, ++ 0x75, 0x62, 0x41, 0x57, 0x6A, 0x6B, 0x78, 0x50, 0x69, 0x6F, 0x75, 0x66, 0x69, 0x31, 0x78, 0x7A, 0x57, 0x78, 0x2F, 0x42, 0x2F, 0x79, 0x47, 0x64, 0x54, 0x6F, 0x44, 0x41, 0x66, 0x42, 0x67, 0x4E, 0x56, 0x0A, 0x48, 0x53, 0x4D, 0x45, 0x47, 0x44, ++ 0x41, 0x57, 0x67, 0x42, 0x53, 0x75, 0x62, 0x41, 0x57, 0x6A, 0x6B, 0x78, 0x50, 0x69, 0x6F, 0x75, 0x66, 0x69, 0x31, 0x78, 0x7A, 0x57, 0x78, 0x2F, 0x42, 0x2F, 0x79, 0x47, 0x64, 0x54, 0x6F, 0x44, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, ++ 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x77, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x67, 0x45, 0x41, 0x67, 0x79, 0x58, 0x74, 0x36, 0x4E, 0x48, 0x39, 0x6C, 0x56, 0x4C, 0x4E, 0x0A, 0x6E, 0x73, 0x41, 0x45, 0x6F, 0x4A, 0x46, 0x70, 0x35, ++ 0x6C, 0x7A, 0x51, 0x68, 0x4E, 0x37, 0x63, 0x72, 0x61, 0x4A, 0x50, 0x36, 0x45, 0x64, 0x34, 0x31, 0x6D, 0x57, 0x59, 0x71, 0x56, 0x75, 0x6F, 0x50, 0x49, 0x64, 0x38, 0x41, 0x6F, 0x72, 0x52, 0x62, 0x72, 0x63, 0x57, 0x63, 0x2B, 0x5A, 0x66, 0x77, ++ 0x46, 0x53, 0x59, 0x31, 0x58, 0x53, 0x2B, 0x77, 0x63, 0x33, 0x69, 0x45, 0x5A, 0x47, 0x74, 0x49, 0x78, 0x67, 0x39, 0x33, 0x65, 0x46, 0x79, 0x52, 0x4A, 0x61, 0x30, 0x0A, 0x6C, 0x56, 0x37, 0x41, 0x65, 0x34, 0x36, 0x5A, 0x65, 0x42, 0x5A, 0x44, ++ 0x45, 0x31, 0x5A, 0x58, 0x73, 0x36, 0x4B, 0x7A, 0x4F, 0x37, 0x56, 0x33, 0x33, 0x45, 0x42, 0x79, 0x72, 0x4B, 0x50, 0x72, 0x6D, 0x7A, 0x55, 0x2B, 0x73, 0x51, 0x67, 0x68, 0x6F, 0x65, 0x66, 0x45, 0x51, 0x7A, 0x64, 0x35, 0x4D, 0x72, 0x36, 0x31, ++ 0x35, 0x35, 0x77, 0x73, 0x54, 0x4C, 0x78, 0x44, 0x4B, 0x5A, 0x6D, 0x4F, 0x4D, 0x4E, 0x4F, 0x73, 0x49, 0x65, 0x44, 0x6A, 0x48, 0x66, 0x72, 0x59, 0x0A, 0x42, 0x7A, 0x4E, 0x32, 0x56, 0x41, 0x41, 0x69, 0x4B, 0x72, 0x6C, 0x4E, 0x49, 0x43, 0x35, ++ 0x77, 0x61, 0x4E, 0x72, 0x6C, 0x55, 0x2F, 0x79, 0x44, 0x58, 0x4E, 0x4F, 0x64, 0x38, 0x76, 0x39, 0x45, 0x44, 0x45, 0x52, 0x6D, 0x38, 0x74, 0x4C, 0x6A, 0x76, 0x55, 0x59, 0x41, 0x47, 0x6D, 0x30, 0x43, 0x75, 0x69, 0x56, 0x64, 0x6A, 0x61, 0x45, ++ 0x78, 0x55, 0x64, 0x31, 0x55, 0x52, 0x68, 0x78, 0x4E, 0x32, 0x35, 0x6D, 0x57, 0x37, 0x78, 0x6F, 0x63, 0x42, 0x46, 0x79, 0x6D, 0x0A, 0x46, 0x65, 0x39, 0x34, 0x34, 0x48, 0x6E, 0x2B, 0x58, 0x64, 0x73, 0x2B, 0x71, 0x6B, 0x78, 0x56, 0x2F, 0x5A, ++ 0x6F, 0x56, 0x71, 0x57, 0x2F, 0x68, 0x70, 0x76, 0x76, 0x66, 0x63, 0x44, 0x44, 0x70, 0x77, 0x2B, 0x35, 0x43, 0x52, 0x75, 0x33, 0x43, 0x6B, 0x77, 0x57, 0x4A, 0x2B, 0x6E, 0x31, 0x6A, 0x65, 0x7A, 0x2F, 0x51, 0x63, 0x59, 0x46, 0x38, 0x41, 0x4F, ++ 0x69, 0x59, 0x72, 0x67, 0x35, 0x34, 0x4E, 0x4D, 0x4D, 0x6C, 0x2B, 0x36, 0x38, 0x4B, 0x6E, 0x79, 0x42, 0x72, 0x0A, 0x33, 0x54, 0x73, 0x54, 0x6A, 0x78, 0x4B, 0x4D, 0x34, 0x6B, 0x45, 0x61, 0x53, 0x48, 0x70, 0x7A, 0x6F, 0x48, 0x64, 0x70, 0x78, ++ 0x37, 0x5A, 0x63, 0x66, 0x34, 0x4C, 0x49, 0x48, 0x76, 0x35, 0x59, 0x47, 0x79, 0x67, 0x72, 0x71, 0x47, 0x79, 0x74, 0x58, 0x6D, 0x33, 0x41, 0x42, 0x64, 0x4A, 0x37, 0x74, 0x2B, 0x75, 0x41, 0x2F, 0x69, 0x55, 0x33, 0x2F, 0x67, 0x4B, 0x62, 0x61, ++ 0x4B, 0x78, 0x43, 0x58, 0x63, 0x50, 0x75, 0x39, 0x63, 0x7A, 0x63, 0x38, 0x46, 0x42, 0x31, 0x0A, 0x30, 0x6A, 0x5A, 0x70, 0x6E, 0x4F, 0x5A, 0x37, 0x42, 0x4E, 0x39, 0x75, 0x42, 0x6D, 0x6D, 0x32, 0x33, 0x67, 0x6F, 0x4A, 0x53, 0x46, 0x6D, 0x48, ++ 0x36, 0x33, 0x73, 0x55, 0x59, 0x48, 0x70, 0x6B, 0x71, 0x6D, 0x6C, 0x44, 0x37, 0x35, 0x48, 0x48, 0x54, 0x4F, 0x77, 0x59, 0x33, 0x57, 0x7A, 0x76, 0x55, 0x79, 0x32, 0x4D, 0x6D, 0x65, 0x46, 0x65, 0x38, 0x6E, 0x49, 0x2B, 0x7A, 0x31, 0x54, 0x49, ++ 0x76, 0x57, 0x66, 0x73, 0x70, 0x41, 0x39, 0x4D, 0x52, 0x66, 0x2F, 0x54, 0x0A, 0x75, 0x54, 0x41, 0x6A, 0x42, 0x30, 0x79, 0x50, 0x45, 0x4C, 0x2B, 0x47, 0x6C, 0x74, 0x6D, 0x5A, 0x57, 0x72, 0x53, 0x5A, 0x56, 0x78, 0x79, 0x6B, 0x7A, 0x4C, 0x73, ++ 0x56, 0x69, 0x56, 0x4F, 0x36, 0x4C, 0x41, 0x55, 0x50, 0x35, 0x4D, 0x53, 0x65, 0x47, 0x62, 0x45, 0x59, 0x4E, 0x4E, 0x56, 0x4D, 0x6E, 0x62, 0x72, 0x74, 0x39, 0x78, 0x2B, 0x76, 0x4A, 0x4A, 0x55, 0x45, 0x65, 0x4B, 0x67, 0x44, 0x75, 0x2B, 0x36, ++ 0x42, 0x35, 0x64, 0x70, 0x66, 0x66, 0x49, 0x74, 0x4B, 0x0A, 0x6F, 0x5A, 0x42, 0x30, 0x4A, 0x61, 0x65, 0x7A, 0x50, 0x6B, 0x76, 0x49, 0x4C, 0x46, 0x61, 0x39, 0x78, 0x38, 0x6A, 0x76, 0x4F, 0x4F, 0x4A, 0x63, 0x6B, 0x76, 0x42, 0x35, 0x39, 0x35, ++ 0x79, 0x45, 0x75, 0x6E, 0x51, 0x74, 0x59, 0x51, 0x45, 0x67, 0x66, 0x6E, 0x37, 0x52, 0x38, 0x6B, 0x38, 0x48, 0x57, 0x56, 0x2B, 0x4C, 0x4C, 0x55, 0x4E, 0x53, 0x36, 0x30, 0x59, 0x4D, 0x6C, 0x4F, 0x48, 0x31, 0x5A, 0x6B, 0x64, 0x35, 0x64, 0x39, ++ 0x56, 0x55, 0x57, 0x78, 0x2B, 0x74, 0x0A, 0x4A, 0x44, 0x66, 0x4C, 0x52, 0x56, 0x70, 0x4F, 0x6F, 0x45, 0x52, 0x49, 0x79, 0x4E, 0x69, 0x77, 0x6D, 0x63, 0x55, 0x56, 0x68, 0x41, 0x6E, 0x32, 0x31, 0x6B, 0x6C, 0x4A, 0x77, 0x47, 0x57, 0x34, 0x35, ++ 0x68, 0x70, 0x78, 0x62, 0x71, 0x43, 0x6F, 0x38, 0x59, 0x4C, 0x6F, 0x52, 0x54, 0x35, 0x73, 0x31, 0x67, 0x4C, 0x58, 0x43, 0x6D, 0x65, 0x44, 0x42, 0x56, 0x72, 0x4A, 0x70, 0x42, 0x41, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, ++ 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x4F, 0x49, 0x53, 0x54, 0x45, 0x20, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, ++ 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x43, 0x20, 0x43, 0x41, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x43, 0x61, 0x54, 0x43, 0x43, 0x41, ++ 0x65, 0x2B, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x49, 0x53, 0x70, 0x57, 0x44, 0x4B, 0x37, 0x61, 0x44, 0x4B, 0x74, 0x41, 0x52, 0x62, 0x38, 0x72, 0x6F, 0x69, 0x30, 0x36, 0x36, 0x6A, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, ++ 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x7A, 0x42, 0x74, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x44, 0x0A, 0x53, 0x44, 0x45, 0x51, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x45, ++ 0x43, 0x68, 0x4D, 0x48, 0x56, 0x30, 0x6C, 0x54, 0x5A, 0x55, 0x74, 0x6C, 0x65, 0x54, 0x45, 0x69, 0x4D, 0x43, 0x41, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x78, 0x4D, 0x5A, 0x54, 0x30, 0x6C, 0x54, 0x56, 0x45, 0x55, 0x67, 0x52, 0x6D, 0x39, 0x31, ++ 0x62, 0x6D, 0x52, 0x68, 0x64, 0x47, 0x6C, 0x76, 0x62, 0x69, 0x42, 0x46, 0x62, 0x6D, 0x52, 0x76, 0x63, 0x6E, 0x4E, 0x6C, 0x5A, 0x44, 0x45, 0x6F, 0x0A, 0x4D, 0x43, 0x59, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x66, 0x54, 0x30, 0x6C, ++ 0x54, 0x56, 0x45, 0x55, 0x67, 0x56, 0x30, 0x6C, 0x54, 0x5A, 0x55, 0x74, 0x6C, 0x65, 0x53, 0x42, 0x48, 0x62, 0x47, 0x39, 0x69, 0x59, 0x57, 0x77, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x48, 0x51, 0x79, 0x42, 0x44, 0x51, 0x54, 0x41, ++ 0x65, 0x46, 0x77, 0x30, 0x78, 0x4E, 0x7A, 0x41, 0x31, 0x4D, 0x44, 0x6B, 0x77, 0x4F, 0x54, 0x51, 0x34, 0x4D, 0x7A, 0x52, 0x61, 0x0A, 0x46, 0x77, 0x30, 0x30, 0x4D, 0x6A, 0x41, 0x31, 0x4D, 0x44, 0x6B, 0x77, 0x4F, 0x54, 0x55, 0x34, 0x4D, 0x7A, ++ 0x4E, 0x61, 0x4D, 0x47, 0x30, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6B, 0x4E, 0x49, 0x4D, 0x52, 0x41, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x45, 0x77, 0x64, 0x58, 0x53, 0x56, ++ 0x4E, 0x6C, 0x53, 0x32, 0x56, 0x35, 0x4D, 0x53, 0x49, 0x77, 0x49, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4C, 0x0A, 0x45, 0x78, 0x6C, 0x50, 0x53, 0x56, 0x4E, 0x55, 0x52, 0x53, 0x42, 0x47, 0x62, 0x33, 0x56, 0x75, 0x5A, 0x47, 0x46, 0x30, 0x61, ++ 0x57, 0x39, 0x75, 0x49, 0x45, 0x56, 0x75, 0x5A, 0x47, 0x39, 0x79, 0x63, 0x32, 0x56, 0x6B, 0x4D, 0x53, 0x67, 0x77, 0x4A, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x39, 0x50, 0x53, 0x56, 0x4E, 0x55, 0x52, 0x53, 0x42, 0x58, 0x53, ++ 0x56, 0x4E, 0x6C, 0x53, 0x32, 0x56, 0x35, 0x49, 0x45, 0x64, 0x73, 0x62, 0x32, 0x4A, 0x68, 0x0A, 0x62, 0x43, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x64, 0x44, 0x49, 0x45, 0x4E, 0x42, 0x4D, 0x48, 0x59, 0x77, 0x45, 0x41, 0x59, 0x48, ++ 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x43, 0x41, 0x51, 0x59, 0x46, 0x4B, 0x34, 0x45, 0x45, 0x41, 0x43, 0x49, 0x44, 0x59, 0x67, 0x41, 0x45, 0x54, 0x4F, 0x6C, 0x51, 0x77, 0x4D, 0x59, 0x50, 0x63, 0x68, 0x69, 0x38, 0x32, 0x50, 0x47, 0x36, ++ 0x73, 0x34, 0x6E, 0x69, 0x65, 0x55, 0x71, 0x6A, 0x46, 0x71, 0x64, 0x72, 0x0A, 0x56, 0x43, 0x54, 0x62, 0x55, 0x66, 0x2F, 0x71, 0x39, 0x41, 0x6B, 0x6B, 0x77, 0x77, 0x73, 0x69, 0x6E, 0x38, 0x74, 0x71, 0x4A, 0x34, 0x4B, 0x42, 0x44, 0x64, 0x4C, ++ 0x41, 0x72, 0x7A, 0x48, 0x6B, 0x64, 0x49, 0x4A, 0x75, 0x79, 0x69, 0x58, 0x5A, 0x6A, 0x48, 0x57, 0x64, 0x38, 0x64, 0x76, 0x51, 0x6D, 0x71, 0x4A, 0x4C, 0x49, 0x58, 0x34, 0x57, 0x70, 0x32, 0x4F, 0x51, 0x30, 0x6A, 0x6E, 0x55, 0x73, 0x59, 0x64, ++ 0x34, 0x58, 0x78, 0x69, 0x57, 0x44, 0x31, 0x41, 0x62, 0x0A, 0x4E, 0x54, 0x63, 0x50, 0x61, 0x73, 0x62, 0x63, 0x32, 0x52, 0x4E, 0x4E, 0x70, 0x49, 0x36, 0x51, 0x4E, 0x2B, 0x61, 0x39, 0x57, 0x7A, 0x47, 0x52, 0x6F, 0x31, 0x51, 0x77, 0x55, 0x6A, ++ 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x51, 0x59, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, ++ 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x64, 0x0A, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x53, 0x49, 0x63, 0x55, 0x72, 0x4F, 0x50, 0x44, 0x6E, 0x70, 0x42, 0x67, 0x4F, 0x74, 0x66, 0x4B, 0x69, 0x65, 0x37, 0x54, 0x72, ++ 0x59, 0x79, 0x30, 0x55, 0x47, 0x59, 0x77, 0x45, 0x41, 0x59, 0x4A, 0x4B, 0x77, 0x59, 0x42, 0x42, 0x41, 0x47, 0x43, 0x4E, 0x78, 0x55, 0x42, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x51, 0x41, 0x77, 0x43, 0x67, 0x59, 0x49, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, ++ 0x6A, 0x30, 0x45, 0x0A, 0x41, 0x77, 0x4D, 0x44, 0x61, 0x41, 0x41, 0x77, 0x5A, 0x51, 0x49, 0x77, 0x4A, 0x73, 0x64, 0x70, 0x57, 0x39, 0x7A, 0x56, 0x35, 0x37, 0x4C, 0x6E, 0x79, 0x41, 0x79, 0x4D, 0x6A, 0x4D, 0x50, 0x64, 0x65, 0x59, 0x77, 0x62, ++ 0x59, 0x39, 0x58, 0x4A, 0x55, 0x70, 0x52, 0x4F, 0x54, 0x59, 0x4A, 0x4B, 0x63, 0x78, 0x36, 0x79, 0x67, 0x49, 0x53, 0x70, 0x4A, 0x63, 0x42, 0x4D, 0x57, 0x6D, 0x31, 0x4A, 0x4B, 0x57, 0x42, 0x34, 0x45, 0x2B, 0x4A, 0x2B, 0x53, 0x4F, 0x74, 0x6B, ++ 0x0A, 0x41, 0x6A, 0x45, 0x41, 0x32, 0x7A, 0x51, 0x67, 0x4D, 0x67, 0x6A, 0x2F, 0x6D, 0x6B, 0x6B, 0x43, 0x74, 0x6F, 0x6A, 0x65, 0x46, 0x4B, 0x39, 0x64, 0x62, 0x4A, 0x6C, 0x78, 0x6A, 0x52, 0x6F, 0x2F, 0x69, 0x39, 0x66, 0x67, 0x6F, 0x6A, 0x61, ++ 0x47, 0x48, 0x41, 0x65, 0x43, 0x4F, 0x6E, 0x5A, 0x54, 0x2F, 0x63, 0x4B, 0x69, 0x37, 0x65, 0x39, 0x37, 0x73, 0x49, 0x42, 0x50, 0x57, 0x41, 0x39, 0x4C, 0x55, 0x7A, 0x6D, 0x39, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, ++ 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x55, 0x43, 0x41, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x47, 0x32, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, ++ 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x52, 0x6A, 0x43, 0x43, 0x41, 0x79, 0x36, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x58, 0x64, 0x2B, 0x78, 0x32, 0x6C, 0x71, 0x6A, 0x37, 0x56, 0x32, 0x2B, 0x57, 0x6D, 0x55, 0x67, 0x5A, ++ 0x51, 0x4F, 0x51, 0x37, 0x7A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x44, 0x41, 0x39, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x0A, ++ 0x45, 0x77, 0x4A, 0x44, 0x54, 0x6A, 0x45, 0x52, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, 0x49, 0x56, 0x57, 0x35, 0x70, 0x56, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x51, 0x78, 0x47, 0x7A, 0x41, 0x5A, 0x42, 0x67, 0x4E, 0x56, ++ 0x42, 0x41, 0x4D, 0x4D, 0x45, 0x6C, 0x56, 0x44, 0x51, 0x53, 0x42, 0x48, 0x62, 0x47, 0x39, 0x69, 0x59, 0x57, 0x77, 0x67, 0x52, 0x7A, 0x49, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x44, 0x41, 0x65, 0x46, 0x77, 0x30, 0x78, 0x0A, 0x4E, 0x6A, 0x41, ++ 0x7A, 0x4D, 0x54, 0x45, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x44, 0x42, 0x61, 0x46, 0x77, 0x30, 0x30, 0x4D, 0x44, 0x45, 0x79, 0x4D, 0x7A, 0x45, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x44, 0x42, 0x61, 0x4D, 0x44, 0x30, 0x78, 0x43, 0x7A, 0x41, ++ 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6B, 0x4E, 0x4F, 0x4D, 0x52, 0x45, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x44, 0x41, 0x68, 0x56, 0x62, 0x6D, 0x6C, 0x55, 0x0A, 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x44, ++ 0x45, 0x62, 0x4D, 0x42, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x77, 0x77, 0x53, 0x56, 0x55, 0x4E, 0x42, 0x49, 0x45, 0x64, 0x73, 0x62, 0x32, 0x4A, 0x68, 0x62, 0x43, 0x42, 0x48, 0x4D, 0x69, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x4D, 0x49, ++ 0x49, 0x43, 0x49, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x45, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x67, 0x38, 0x41, 0x0A, 0x4D, 0x49, 0x49, 0x43, 0x43, 0x67, 0x4B, 0x43, 0x41, ++ 0x67, 0x45, 0x41, 0x78, 0x65, 0x59, 0x72, 0x62, 0x33, 0x7A, 0x76, 0x4A, 0x67, 0x55, 0x6E, 0x6F, 0x34, 0x45, 0x6B, 0x32, 0x6D, 0x2F, 0x4C, 0x41, 0x66, 0x6D, 0x5A, 0x6D, 0x71, 0x6B, 0x79, 0x77, 0x69, 0x4B, 0x48, 0x59, 0x55, 0x47, 0x52, 0x4F, ++ 0x38, 0x76, 0x44, 0x61, 0x42, 0x73, 0x47, 0x78, 0x55, 0x79, 0x70, 0x4B, 0x38, 0x46, 0x6E, 0x46, 0x79, 0x49, 0x64, 0x4B, 0x2B, 0x33, 0x35, 0x4B, 0x59, 0x6D, 0x54, 0x0A, 0x6F, 0x6E, 0x69, 0x39, 0x6B, 0x6D, 0x75, 0x67, 0x6F, 0x77, 0x32, 0x69, ++ 0x66, 0x73, 0x71, 0x54, 0x73, 0x36, 0x62, 0x52, 0x6A, 0x44, 0x58, 0x56, 0x64, 0x66, 0x6B, 0x58, 0x39, 0x73, 0x39, 0x46, 0x78, 0x65, 0x56, 0x36, 0x37, 0x48, 0x65, 0x54, 0x6F, 0x49, 0x38, 0x6A, 0x72, 0x67, 0x34, 0x61, 0x41, 0x33, 0x2B, 0x2B, ++ 0x31, 0x4E, 0x44, 0x74, 0x4C, 0x6E, 0x75, 0x72, 0x52, 0x69, 0x4E, 0x62, 0x2F, 0x79, 0x7A, 0x6D, 0x56, 0x48, 0x71, 0x55, 0x77, 0x43, 0x6F, 0x56, 0x0A, 0x38, 0x4D, 0x6D, 0x4E, 0x73, 0x48, 0x6F, 0x37, 0x4A, 0x4F, 0x48, 0x58, 0x61, 0x4F, 0x49, ++ 0x78, 0x50, 0x41, 0x59, 0x7A, 0x52, 0x72, 0x5A, 0x55, 0x45, 0x61, 0x61, 0x6C, 0x4C, 0x79, 0x4A, 0x55, 0x4B, 0x6C, 0x67, 0x4E, 0x41, 0x51, 0x4C, 0x78, 0x2B, 0x68, 0x56, 0x52, 0x5A, 0x32, 0x7A, 0x41, 0x2B, 0x74, 0x65, 0x32, 0x47, 0x33, 0x2F, ++ 0x52, 0x56, 0x6F, 0x67, 0x76, 0x47, 0x6A, 0x71, 0x4E, 0x4F, 0x37, 0x75, 0x43, 0x45, 0x65, 0x42, 0x48, 0x41, 0x4E, 0x42, 0x53, 0x0A, 0x68, 0x36, 0x76, 0x37, 0x68, 0x6E, 0x34, 0x50, 0x4A, 0x47, 0x74, 0x41, 0x6E, 0x54, 0x52, 0x6E, 0x76, 0x49, ++ 0x33, 0x48, 0x4C, 0x59, 0x5A, 0x76, 0x65, 0x54, 0x36, 0x4F, 0x71, 0x54, 0x77, 0x58, 0x53, 0x33, 0x2B, 0x77, 0x6D, 0x65, 0x4F, 0x77, 0x63, 0x57, 0x44, 0x63, 0x43, 0x2F, 0x56, 0x6B, 0x77, 0x38, 0x35, 0x44, 0x76, 0x47, 0x31, 0x78, 0x75, 0x64, ++ 0x4C, 0x65, 0x4A, 0x31, 0x75, 0x4B, 0x36, 0x4E, 0x6A, 0x47, 0x72, 0x75, 0x46, 0x5A, 0x66, 0x63, 0x38, 0x6F, 0x0A, 0x4C, 0x54, 0x57, 0x34, 0x6C, 0x56, 0x59, 0x61, 0x38, 0x62, 0x4A, 0x59, 0x53, 0x37, 0x63, 0x53, 0x4E, 0x38, 0x68, 0x38, 0x73, ++ 0x2B, 0x31, 0x4C, 0x67, 0x4F, 0x47, 0x4E, 0x2B, 0x6A, 0x49, 0x6A, 0x74, 0x6D, 0x2B, 0x33, 0x53, 0x4A, 0x55, 0x49, 0x73, 0x55, 0x52, 0x4F, 0x68, 0x59, 0x77, 0x36, 0x41, 0x6C, 0x51, 0x67, 0x4C, 0x39, 0x2B, 0x2F, 0x56, 0x30, 0x38, 0x37, 0x4F, ++ 0x70, 0x41, 0x68, 0x31, 0x38, 0x45, 0x6D, 0x4E, 0x56, 0x51, 0x67, 0x37, 0x4D, 0x63, 0x2F, 0x0A, 0x52, 0x2B, 0x7A, 0x76, 0x57, 0x72, 0x39, 0x4C, 0x65, 0x73, 0x47, 0x74, 0x4F, 0x78, 0x64, 0x51, 0x58, 0x47, 0x4C, 0x59, 0x44, 0x30, 0x74, 0x4B, ++ 0x33, 0x43, 0x76, 0x36, 0x62, 0x72, 0x78, 0x7A, 0x6B, 0x73, 0x33, 0x73, 0x78, 0x31, 0x44, 0x6F, 0x51, 0x5A, 0x62, 0x58, 0x71, 0x58, 0x35, 0x74, 0x32, 0x4F, 0x6B, 0x64, 0x6A, 0x34, 0x71, 0x31, 0x75, 0x56, 0x69, 0x53, 0x75, 0x6B, 0x71, 0x53, ++ 0x4B, 0x77, 0x78, 0x57, 0x2F, 0x59, 0x44, 0x72, 0x43, 0x50, 0x42, 0x65, 0x0A, 0x4B, 0x57, 0x34, 0x62, 0x48, 0x41, 0x79, 0x76, 0x6A, 0x35, 0x4F, 0x4A, 0x72, 0x64, 0x75, 0x39, 0x6F, 0x35, 0x34, 0x68, 0x79, 0x6F, 0x6B, 0x5A, 0x37, 0x4E, 0x2B, ++ 0x31, 0x77, 0x78, 0x72, 0x72, 0x46, 0x76, 0x35, 0x34, 0x4E, 0x6B, 0x7A, 0x57, 0x62, 0x74, 0x41, 0x2B, 0x46, 0x78, 0x79, 0x51, 0x46, 0x32, 0x73, 0x6D, 0x75, 0x76, 0x74, 0x36, 0x4C, 0x37, 0x38, 0x52, 0x48, 0x42, 0x67, 0x4F, 0x4C, 0x58, 0x4D, ++ 0x44, 0x6A, 0x36, 0x44, 0x6C, 0x4E, 0x61, 0x42, 0x61, 0x0A, 0x34, 0x6B, 0x78, 0x31, 0x48, 0x58, 0x48, 0x68, 0x4F, 0x54, 0x68, 0x54, 0x65, 0x45, 0x44, 0x4D, 0x67, 0x35, 0x50, 0x58, 0x43, 0x70, 0x36, 0x64, 0x57, 0x34, 0x2B, 0x4B, 0x35, 0x4F, ++ 0x58, 0x67, 0x53, 0x4F, 0x52, 0x49, 0x73, 0x6B, 0x66, 0x4E, 0x54, 0x69, 0x70, 0x31, 0x4B, 0x6E, 0x76, 0x79, 0x49, 0x76, 0x62, 0x4A, 0x76, 0x67, 0x6D, 0x52, 0x6C, 0x6C, 0x64, 0x36, 0x69, 0x49, 0x69, 0x73, 0x37, 0x6E, 0x43, 0x73, 0x2B, 0x64, ++ 0x77, 0x70, 0x34, 0x77, 0x77, 0x63, 0x0A, 0x4F, 0x78, 0x4A, 0x4F, 0x52, 0x4E, 0x61, 0x6E, 0x54, 0x72, 0x41, 0x6D, 0x79, 0x50, 0x50, 0x5A, 0x47, 0x70, 0x65, 0x52, 0x61, 0x4F, 0x72, 0x76, 0x6A, 0x55, 0x59, 0x47, 0x30, 0x6C, 0x5A, 0x46, 0x57, ++ 0x4A, 0x6F, 0x38, 0x44, 0x41, 0x2B, 0x44, 0x75, 0x41, 0x55, 0x6C, 0x77, 0x7A, 0x6E, 0x50, 0x4F, 0x36, 0x51, 0x30, 0x69, 0x62, 0x64, 0x35, 0x45, 0x69, 0x39, 0x48, 0x78, 0x65, 0x65, 0x70, 0x6C, 0x32, 0x6E, 0x38, 0x70, 0x6E, 0x64, 0x6E, 0x74, ++ 0x64, 0x39, 0x37, 0x0A, 0x38, 0x58, 0x70, 0x6C, 0x46, 0x65, 0x52, 0x68, 0x56, 0x6D, 0x55, 0x43, 0x41, 0x77, 0x45, 0x41, 0x41, 0x61, 0x4E, 0x43, 0x4D, 0x45, 0x41, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x41, 0x51, 0x48, 0x2F, ++ 0x42, 0x41, 0x51, 0x44, 0x41, 0x67, 0x45, 0x47, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x48, 0x51, 0x59, 0x44, 0x56, 0x52, 0x30, 0x4F, ++ 0x0A, 0x42, 0x42, 0x59, 0x45, 0x46, 0x49, 0x48, 0x45, 0x6A, 0x4D, 0x7A, 0x31, 0x35, 0x44, 0x44, 0x2F, 0x70, 0x51, 0x77, 0x49, 0x58, 0x34, 0x77, 0x56, 0x5A, 0x79, 0x46, 0x30, 0x41, 0x64, 0x2F, 0x66, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, ++ 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x43, 0x77, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x41, 0x51, 0x41, 0x54, 0x5A, 0x53, 0x4C, 0x31, 0x6A, 0x69, 0x75, 0x74, 0x52, 0x4F, 0x54, 0x4C, 0x2F, 0x37, 0x6C, 0x6F, 0x0A, 0x35, 0x73, ++ 0x4F, 0x41, 0x53, 0x44, 0x30, 0x45, 0x65, 0x2F, 0x6F, 0x6A, 0x4C, 0x33, 0x72, 0x74, 0x4E, 0x74, 0x71, 0x79, 0x7A, 0x6D, 0x33, 0x32, 0x35, 0x70, 0x37, 0x6C, 0x58, 0x31, 0x69, 0x50, 0x79, 0x7A, 0x63, 0x79, 0x6F, 0x63, 0x68, 0x6C, 0x74, 0x71, ++ 0x34, 0x34, 0x50, 0x54, 0x55, 0x62, 0x50, 0x72, 0x77, 0x37, 0x74, 0x67, 0x54, 0x51, 0x76, 0x50, 0x6C, 0x4A, 0x39, 0x5A, 0x76, 0x33, 0x68, 0x63, 0x55, 0x32, 0x74, 0x73, 0x75, 0x38, 0x2B, 0x4D, 0x67, 0x35, 0x0A, 0x31, 0x65, 0x52, 0x66, 0x42, ++ 0x37, 0x30, 0x56, 0x56, 0x4A, 0x64, 0x30, 0x79, 0x73, 0x72, 0x74, 0x54, 0x37, 0x71, 0x36, 0x5A, 0x48, 0x61, 0x66, 0x67, 0x62, 0x69, 0x45, 0x52, 0x55, 0x6C, 0x4D, 0x6A, 0x57, 0x2B, 0x69, 0x36, 0x37, 0x48, 0x4D, 0x30, 0x63, 0x4F, 0x55, 0x32, ++ 0x6B, 0x54, 0x43, 0x35, 0x75, 0x4C, 0x71, 0x47, 0x4F, 0x69, 0x69, 0x48, 0x79, 0x63, 0x46, 0x75, 0x74, 0x66, 0x6C, 0x31, 0x71, 0x6E, 0x4E, 0x33, 0x65, 0x39, 0x32, 0x6D, 0x49, 0x30, 0x41, 0x0A, 0x44, 0x73, 0x30, 0x62, 0x2B, 0x67, 0x4F, 0x33, ++ 0x6A, 0x6F, 0x42, 0x59, 0x44, 0x69, 0x63, 0x2F, 0x55, 0x76, 0x75, 0x55, 0x6F, 0x73, 0x70, 0x65, 0x5A, 0x63, 0x6E, 0x57, 0x68, 0x4E, 0x71, 0x35, 0x4E, 0x58, 0x48, 0x7A, 0x4A, 0x73, 0x42, 0x50, 0x64, 0x2B, 0x61, 0x42, 0x4A, 0x39, 0x4A, 0x33, ++ 0x4F, 0x35, 0x6F, 0x55, 0x62, 0x33, 0x6E, 0x30, 0x39, 0x74, 0x44, 0x68, 0x30, 0x35, 0x53, 0x36, 0x30, 0x46, 0x64, 0x52, 0x76, 0x53, 0x63, 0x46, 0x44, 0x63, 0x48, 0x39, 0x0A, 0x79, 0x42, 0x49, 0x77, 0x37, 0x6D, 0x2B, 0x4E, 0x45, 0x53, 0x73, ++ 0x49, 0x6E, 0x64, 0x54, 0x55, 0x76, 0x34, 0x42, 0x46, 0x46, 0x4A, 0x71, 0x49, 0x52, 0x4E, 0x6F, 0x77, 0x36, 0x72, 0x53, 0x6E, 0x34, 0x2B, 0x37, 0x76, 0x57, 0x34, 0x4C, 0x56, 0x50, 0x74, 0x61, 0x74, 0x65, 0x4A, 0x4C, 0x62, 0x58, 0x44, 0x7A, ++ 0x7A, 0x32, 0x4B, 0x33, 0x36, 0x75, 0x47, 0x74, 0x2F, 0x78, 0x44, 0x59, 0x6F, 0x74, 0x67, 0x49, 0x56, 0x69, 0x6C, 0x51, 0x73, 0x6E, 0x4C, 0x41, 0x58, 0x0A, 0x63, 0x34, 0x37, 0x51, 0x4E, 0x36, 0x4D, 0x55, 0x50, 0x4A, 0x69, 0x56, 0x41, 0x41, ++ 0x77, 0x70, 0x42, 0x56, 0x75, 0x65, 0x53, 0x55, 0x6D, 0x78, 0x58, 0x38, 0x66, 0x6A, 0x79, 0x38, 0x38, 0x6E, 0x5A, 0x59, 0x34, 0x31, 0x46, 0x37, 0x64, 0x58, 0x79, 0x44, 0x44, 0x5A, 0x51, 0x56, 0x75, 0x35, 0x46, 0x4C, 0x62, 0x6F, 0x77, 0x67, ++ 0x2B, 0x55, 0x4D, 0x61, 0x65, 0x55, 0x6D, 0x4D, 0x78, 0x71, 0x36, 0x37, 0x58, 0x68, 0x4A, 0x2F, 0x55, 0x51, 0x71, 0x41, 0x48, 0x6F, 0x0A, 0x6A, 0x68, 0x4A, 0x69, 0x36, 0x49, 0x6A, 0x4D, 0x74, 0x58, 0x39, 0x47, 0x6C, 0x38, 0x43, 0x62, 0x45, ++ 0x47, 0x59, 0x34, 0x47, 0x6A, 0x5A, 0x47, 0x58, 0x79, 0x4A, 0x6F, 0x50, 0x64, 0x2F, 0x4A, 0x78, 0x68, 0x4D, 0x6E, 0x71, 0x31, 0x4D, 0x47, 0x72, 0x4B, 0x49, 0x38, 0x68, 0x67, 0x5A, 0x6C, 0x62, 0x37, 0x46, 0x2B, 0x73, 0x53, 0x6C, 0x45, 0x6D, ++ 0x71, 0x4F, 0x36, 0x53, 0x57, 0x6B, 0x6F, 0x61, 0x59, 0x2F, 0x58, 0x35, 0x56, 0x2B, 0x74, 0x42, 0x49, 0x5A, 0x6B, 0x0A, 0x62, 0x78, 0x71, 0x67, 0x44, 0x4D, 0x55, 0x49, 0x59, 0x73, 0x36, 0x41, 0x6F, 0x39, 0x44, 0x7A, 0x37, 0x47, 0x6A, 0x65, ++ 0x76, 0x6A, 0x50, 0x48, 0x46, 0x31, 0x74, 0x2F, 0x67, 0x4D, 0x52, 0x4D, 0x54, 0x4C, 0x47, 0x6D, 0x68, 0x49, 0x72, 0x44, 0x4F, 0x37, 0x67, 0x4A, 0x7A, 0x52, 0x53, 0x42, 0x75, 0x68, 0x6A, 0x6A, 0x56, 0x46, 0x63, 0x32, 0x2F, 0x74, 0x73, 0x76, ++ 0x66, 0x45, 0x65, 0x68, 0x4F, 0x6A, 0x50, 0x49, 0x2B, 0x56, 0x67, 0x37, 0x52, 0x45, 0x2B, 0x78, 0x0A, 0x79, 0x67, 0x4B, 0x4A, 0x42, 0x4A, 0x59, 0x6F, 0x61, 0x4D, 0x56, 0x4C, 0x75, 0x43, 0x61, 0x4A, 0x75, 0x39, 0x59, 0x7A, 0x4C, 0x31, 0x44, ++ 0x56, 0x2F, 0x70, 0x71, 0x4A, 0x75, 0x68, 0x67, 0x79, 0x6B, 0x6C, 0x54, 0x47, 0x57, 0x2B, 0x43, 0x64, 0x2B, 0x56, 0x37, 0x6C, 0x44, 0x53, 0x4B, 0x62, 0x39, 0x74, 0x72, 0x69, 0x79, 0x43, 0x47, 0x79, 0x59, 0x69, 0x47, 0x71, 0x68, 0x6B, 0x43, ++ 0x79, 0x4C, 0x6D, 0x54, 0x54, 0x58, 0x38, 0x6A, 0x6A, 0x66, 0x68, 0x46, 0x6E, 0x0A, 0x52, 0x52, 0x38, 0x46, 0x2F, 0x75, 0x4F, 0x69, 0x37, 0x37, 0x4F, 0x6F, 0x73, 0x2F, 0x4E, 0x39, 0x6A, 0x2F, 0x67, 0x4D, 0x48, 0x79, 0x49, 0x66, 0x4C, 0x58, ++ 0x43, 0x30, 0x75, 0x41, 0x45, 0x30, 0x64, 0x6A, 0x41, 0x41, 0x35, 0x53, 0x4E, 0x34, 0x70, 0x31, 0x62, 0x58, 0x55, 0x42, 0x2B, 0x4B, 0x2B, 0x77, 0x62, 0x31, 0x77, 0x68, 0x6E, 0x77, 0x30, 0x41, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, ++ 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x55, 0x43, 0x41, 0x20, 0x45, 0x78, 0x74, 0x65, 0x6E, 0x64, 0x65, 0x64, 0x20, 0x56, 0x61, 0x6C, 0x69, 0x64, ++ 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, ++ 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x57, 0x6A, 0x43, 0x43, 0x41, 0x30, 0x4B, 0x67, ++ 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x54, 0x39, 0x49, 0x72, 0x6A, 0x2F, 0x56, 0x6B, 0x79, 0x44, 0x4F, 0x65, 0x54, 0x7A, 0x52, 0x59, 0x5A, 0x69, 0x4E, 0x77, 0x59, 0x44, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, ++ 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x44, 0x42, 0x48, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x0A, 0x45, 0x77, 0x4A, 0x44, 0x54, 0x6A, 0x45, 0x52, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, ++ 0x45, 0x43, 0x67, 0x77, 0x49, 0x56, 0x57, 0x35, 0x70, 0x56, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x51, 0x78, 0x4A, 0x54, 0x41, 0x6A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x4D, 0x48, 0x46, 0x56, 0x44, 0x51, 0x53, 0x42, 0x46, 0x65, 0x48, 0x52, ++ 0x6C, 0x62, 0x6D, 0x52, 0x6C, 0x5A, 0x43, 0x42, 0x57, 0x59, 0x57, 0x78, 0x70, 0x5A, 0x47, 0x46, 0x30, 0x61, 0x57, 0x39, 0x75, 0x0A, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x54, 0x55, 0x77, 0x4D, 0x7A, ++ 0x45, 0x7A, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x57, 0x68, 0x63, 0x4E, 0x4D, 0x7A, 0x67, 0x78, 0x4D, 0x6A, 0x4D, 0x78, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x57, 0x6A, 0x42, 0x48, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, ++ 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x44, 0x54, 0x6A, 0x45, 0x52, 0x4D, 0x41, 0x38, 0x47, 0x0A, 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, 0x49, 0x56, 0x57, 0x35, 0x70, 0x56, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x51, 0x78, 0x4A, ++ 0x54, 0x41, 0x6A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x4D, 0x48, 0x46, 0x56, 0x44, 0x51, 0x53, 0x42, 0x46, 0x65, 0x48, 0x52, 0x6C, 0x62, 0x6D, 0x52, 0x6C, 0x5A, 0x43, 0x42, 0x57, 0x59, 0x57, 0x78, 0x70, 0x5A, 0x47, 0x46, 0x30, 0x61, ++ 0x57, 0x39, 0x75, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x77, 0x67, 0x67, 0x49, 0x69, 0x0A, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, ++ 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x49, 0x4B, 0x41, 0x6F, 0x49, 0x43, 0x41, 0x51, 0x43, 0x70, 0x43, 0x51, 0x63, 0x6F, 0x45, 0x77, 0x4B, 0x77, 0x6D, 0x65, 0x42, 0x6B, 0x71, 0x68, 0x35, 0x44, 0x46, 0x6E, 0x70, 0x7A, 0x73, 0x5A, 0x47, 0x67, ++ 0x64, 0x54, 0x36, 0x6F, 0x2B, 0x75, 0x4D, 0x34, 0x41, 0x48, 0x72, 0x73, 0x0A, 0x69, 0x57, 0x6F, 0x67, 0x44, 0x34, 0x76, 0x46, 0x73, 0x4A, 0x73, 0x7A, 0x41, 0x31, 0x71, 0x47, 0x78, 0x6C, 0x69, 0x47, 0x31, 0x63, 0x47, 0x46, 0x75, 0x30, 0x2F, ++ 0x47, 0x6E, 0x45, 0x42, 0x4E, 0x79, 0x72, 0x37, 0x75, 0x61, 0x5A, 0x61, 0x34, 0x72, 0x59, 0x45, 0x77, 0x6D, 0x6E, 0x79, 0x53, 0x42, 0x65, 0x73, 0x46, 0x4B, 0x35, 0x70, 0x49, 0x30, 0x4C, 0x68, 0x32, 0x50, 0x70, 0x62, 0x49, 0x49, 0x4C, 0x76, ++ 0x53, 0x73, 0x50, 0x47, 0x50, 0x32, 0x4B, 0x78, 0x46, 0x0A, 0x52, 0x76, 0x2B, 0x71, 0x5A, 0x32, 0x43, 0x30, 0x64, 0x33, 0x35, 0x71, 0x48, 0x7A, 0x77, 0x61, 0x55, 0x6E, 0x6F, 0x45, 0x50, 0x51, 0x63, 0x38, 0x68, 0x51, 0x32, 0x45, 0x30, 0x42, ++ 0x39, 0x32, 0x43, 0x76, 0x64, 0x71, 0x46, 0x4E, 0x39, 0x79, 0x34, 0x7A, 0x52, 0x38, 0x56, 0x30, 0x35, 0x57, 0x41, 0x54, 0x35, 0x35, 0x38, 0x61, 0x6F, 0x70, 0x4F, 0x32, 0x7A, 0x36, 0x2B, 0x49, 0x39, 0x74, 0x54, 0x63, 0x67, 0x31, 0x33, 0x36, ++ 0x37, 0x72, 0x33, 0x43, 0x54, 0x75, 0x0A, 0x65, 0x55, 0x57, 0x6E, 0x68, 0x62, 0x59, 0x46, 0x69, 0x4E, 0x36, 0x49, 0x58, 0x53, 0x56, 0x38, 0x6C, 0x32, 0x52, 0x6E, 0x43, 0x64, 0x6D, 0x2F, 0x57, 0x68, 0x55, 0x46, 0x68, 0x76, 0x4D, 0x4A, 0x48, ++ 0x75, 0x78, 0x59, 0x4D, 0x6A, 0x4D, 0x52, 0x38, 0x33, 0x64, 0x6B, 0x73, 0x48, 0x59, 0x66, 0x35, 0x42, 0x41, 0x31, 0x46, 0x78, 0x76, 0x79, 0x44, 0x72, 0x46, 0x73, 0x70, 0x43, 0x71, 0x6A, 0x63, 0x2F, 0x77, 0x4A, 0x48, 0x78, 0x34, 0x79, 0x47, ++ 0x56, 0x4D, 0x52, 0x0A, 0x35, 0x39, 0x6D, 0x7A, 0x4C, 0x43, 0x35, 0x32, 0x4C, 0x71, 0x47, 0x6A, 0x33, 0x6E, 0x35, 0x71, 0x69, 0x41, 0x6E, 0x6F, 0x38, 0x67, 0x65, 0x4B, 0x2B, 0x4C, 0x4C, 0x4E, 0x45, 0x4F, 0x66, 0x69, 0x63, 0x30, 0x43, 0x54, ++ 0x75, 0x77, 0x6A, 0x52, 0x50, 0x2B, 0x48, 0x38, 0x43, 0x35, 0x53, 0x7A, 0x4A, 0x65, 0x39, 0x38, 0x70, 0x74, 0x66, 0x52, 0x72, 0x35, 0x2F, 0x2F, 0x6C, 0x70, 0x72, 0x31, 0x6B, 0x58, 0x75, 0x59, 0x43, 0x33, 0x66, 0x55, 0x66, 0x75, 0x67, 0x48, ++ 0x0A, 0x30, 0x6D, 0x4B, 0x31, 0x6C, 0x54, 0x6E, 0x6A, 0x38, 0x2F, 0x46, 0x74, 0x44, 0x77, 0x35, 0x6C, 0x68, 0x49, 0x70, 0x6A, 0x56, 0x4D, 0x57, 0x41, 0x74, 0x75, 0x43, 0x65, 0x53, 0x33, 0x31, 0x48, 0x4A, 0x71, 0x63, 0x42, 0x43, 0x46, 0x33, ++ 0x52, 0x69, 0x4A, 0x37, 0x58, 0x77, 0x7A, 0x4A, 0x45, 0x2B, 0x6F, 0x4A, 0x4B, 0x43, 0x6D, 0x68, 0x55, 0x66, 0x7A, 0x68, 0x54, 0x41, 0x38, 0x79, 0x6B, 0x41, 0x44, 0x4E, 0x6B, 0x55, 0x56, 0x6B, 0x4C, 0x6F, 0x34, 0x4B, 0x52, 0x0A, 0x65, 0x6C, ++ 0x37, 0x73, 0x46, 0x73, 0x4C, 0x7A, 0x4B, 0x75, 0x5A, 0x69, 0x32, 0x69, 0x72, 0x62, 0x57, 0x57, 0x49, 0x51, 0x4A, 0x55, 0x6F, 0x71, 0x67, 0x51, 0x74, 0x48, 0x42, 0x30, 0x4D, 0x47, 0x63, 0x49, 0x66, 0x53, 0x2B, 0x70, 0x4D, 0x52, 0x4B, 0x58, ++ 0x70, 0x49, 0x54, 0x65, 0x75, 0x55, 0x78, 0x33, 0x42, 0x4E, 0x72, 0x32, 0x66, 0x56, 0x55, 0x62, 0x47, 0x41, 0x49, 0x41, 0x45, 0x42, 0x74, 0x48, 0x6F, 0x49, 0x70, 0x70, 0x42, 0x2F, 0x54, 0x75, 0x44, 0x76, 0x0A, 0x42, 0x30, 0x47, 0x48, 0x72, ++ 0x32, 0x71, 0x6C, 0x58, 0x6F, 0x76, 0x37, 0x7A, 0x31, 0x43, 0x79, 0x6D, 0x6C, 0x53, 0x76, 0x77, 0x34, 0x6D, 0x36, 0x57, 0x43, 0x33, 0x31, 0x4D, 0x4A, 0x69, 0x78, 0x4E, 0x6E, 0x49, 0x35, 0x66, 0x6B, 0x6B, 0x45, 0x2F, 0x53, 0x6D, 0x6E, 0x54, ++ 0x48, 0x6E, 0x6B, 0x42, 0x56, 0x66, 0x62, 0x6C, 0x4C, 0x6B, 0x57, 0x55, 0x34, 0x31, 0x47, 0x73, 0x78, 0x32, 0x56, 0x59, 0x56, 0x64, 0x57, 0x66, 0x36, 0x2F, 0x77, 0x46, 0x6C, 0x74, 0x68, 0x0A, 0x57, 0x47, 0x38, 0x32, 0x55, 0x42, 0x45, 0x4C, ++ 0x32, 0x4B, 0x77, 0x72, 0x6C, 0x52, 0x59, 0x61, 0x44, 0x68, 0x38, 0x49, 0x7A, 0x54, 0x59, 0x30, 0x5A, 0x52, 0x42, 0x69, 0x5A, 0x74, 0x57, 0x41, 0x58, 0x78, 0x51, 0x67, 0x58, 0x79, 0x30, 0x4D, 0x6F, 0x48, 0x67, 0x4B, 0x61, 0x4E, 0x59, 0x73, ++ 0x31, 0x2B, 0x6C, 0x76, 0x4B, 0x39, 0x4A, 0x4B, 0x42, 0x5A, 0x50, 0x38, 0x6E, 0x6D, 0x39, 0x72, 0x5A, 0x2F, 0x2B, 0x49, 0x38, 0x55, 0x36, 0x6C, 0x61, 0x55, 0x70, 0x53, 0x0A, 0x4E, 0x77, 0x58, 0x71, 0x78, 0x68, 0x61, 0x4E, 0x30, 0x73, 0x53, ++ 0x5A, 0x30, 0x59, 0x49, 0x72, 0x4F, 0x37, 0x6F, 0x31, 0x64, 0x66, 0x64, 0x52, 0x55, 0x56, 0x6A, 0x7A, 0x79, 0x41, 0x66, 0x64, 0x35, 0x4C, 0x51, 0x44, 0x66, 0x77, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x6F, 0x30, 0x49, 0x77, 0x51, 0x44, 0x41, ++ 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x32, 0x58, 0x51, 0x36, 0x35, 0x44, 0x41, 0x39, 0x44, 0x66, 0x63, 0x53, 0x0A, 0x33, 0x48, 0x35, 0x61, 0x42, 0x5A, 0x38, 0x65, 0x4E, 0x4A, 0x72, 0x33, 0x34, 0x52, ++ 0x51, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x41, ++ 0x4D, 0x43, 0x41, 0x59, 0x59, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x0A, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x42, 0x41, 0x44, 0x61, 0x4E, 0x6C, 0x38, 0x78, 0x43, 0x46, ++ 0x57, 0x51, 0x70, 0x4E, 0x35, 0x73, 0x6D, 0x4C, 0x4E, 0x62, 0x37, 0x72, 0x68, 0x56, 0x70, 0x4C, 0x47, 0x73, 0x61, 0x47, 0x76, 0x64, 0x66, 0x74, 0x76, 0x6B, 0x48, 0x54, 0x46, 0x6E, 0x71, 0x38, 0x38, 0x6E, 0x49, 0x75, 0x61, 0x37, 0x4D, 0x75, ++ 0x69, 0x35, 0x36, 0x33, 0x4D, 0x44, 0x31, 0x73, 0x43, 0x33, 0x41, 0x4F, 0x36, 0x2B, 0x66, 0x63, 0x41, 0x55, 0x52, 0x0A, 0x61, 0x70, 0x38, 0x6C, 0x54, 0x77, 0x45, 0x70, 0x63, 0x4F, 0x50, 0x6C, 0x44, 0x4F, 0x48, 0x71, 0x57, 0x6E, 0x7A, 0x63, ++ 0x53, 0x62, 0x76, 0x42, 0x48, 0x69, 0x71, 0x42, 0x39, 0x52, 0x5A, 0x4C, 0x63, 0x70, 0x48, 0x49, 0x6F, 0x6A, 0x47, 0x35, 0x71, 0x74, 0x72, 0x38, 0x6E, 0x52, 0x2F, 0x7A, 0x58, 0x55, 0x41, 0x43, 0x45, 0x2F, 0x78, 0x4F, 0x48, 0x41, 0x62, 0x4B, ++ 0x73, 0x78, 0x53, 0x51, 0x56, 0x42, 0x63, 0x5A, 0x45, 0x68, 0x72, 0x78, 0x48, 0x39, 0x63, 0x4D, 0x0A, 0x61, 0x56, 0x72, 0x32, 0x63, 0x58, 0x6A, 0x30, 0x6C, 0x48, 0x32, 0x52, 0x43, 0x34, 0x37, 0x73, 0x6B, 0x46, 0x53, 0x4F, 0x76, 0x47, 0x2B, ++ 0x68, 0x54, 0x4B, 0x76, 0x38, 0x64, 0x47, 0x54, 0x39, 0x63, 0x5A, 0x72, 0x34, 0x51, 0x51, 0x65, 0x68, 0x7A, 0x5A, 0x48, 0x6B, 0x50, 0x4A, 0x72, 0x67, 0x6D, 0x7A, 0x49, 0x35, 0x63, 0x36, 0x73, 0x71, 0x31, 0x57, 0x6E, 0x49, 0x65, 0x4A, 0x45, ++ 0x6D, 0x4D, 0x58, 0x33, 0x69, 0x78, 0x7A, 0x44, 0x78, 0x2F, 0x42, 0x52, 0x34, 0x0A, 0x64, 0x78, 0x49, 0x4F, 0x45, 0x2F, 0x54, 0x64, 0x46, 0x70, 0x53, 0x2F, 0x53, 0x32, 0x64, 0x37, 0x63, 0x46, 0x4F, 0x46, 0x79, 0x72, 0x43, 0x37, 0x38, 0x7A, ++ 0x68, 0x4E, 0x4C, 0x4A, 0x41, 0x35, 0x77, 0x41, 0x33, 0x43, 0x58, 0x57, 0x76, 0x70, 0x34, 0x75, 0x58, 0x56, 0x69, 0x49, 0x33, 0x57, 0x4C, 0x4C, 0x2B, 0x72, 0x47, 0x37, 0x36, 0x31, 0x4B, 0x49, 0x63, 0x53, 0x46, 0x33, 0x52, 0x75, 0x2F, 0x48, ++ 0x33, 0x38, 0x6A, 0x39, 0x43, 0x48, 0x4A, 0x72, 0x41, 0x62, 0x0A, 0x2B, 0x37, 0x6C, 0x73, 0x71, 0x2B, 0x4B, 0x65, 0x50, 0x52, 0x58, 0x42, 0x4F, 0x79, 0x35, 0x6E, 0x41, 0x6C, 0x69, 0x52, 0x6E, 0x2B, 0x2F, 0x34, 0x51, 0x68, 0x38, 0x73, 0x74, ++ 0x32, 0x6A, 0x31, 0x64, 0x61, 0x33, 0x50, 0x74, 0x66, 0x62, 0x2F, 0x45, 0x58, 0x33, 0x43, 0x38, 0x43, 0x53, 0x6C, 0x72, 0x64, 0x50, 0x36, 0x6F, 0x44, 0x79, 0x70, 0x2B, 0x6C, 0x33, 0x63, 0x70, 0x61, 0x44, 0x76, 0x52, 0x4B, 0x53, 0x2B, 0x31, ++ 0x75, 0x6A, 0x6C, 0x35, 0x42, 0x4F, 0x57, 0x0A, 0x46, 0x33, 0x73, 0x47, 0x50, 0x6A, 0x4C, 0x74, 0x78, 0x37, 0x64, 0x43, 0x76, 0x48, 0x61, 0x6A, 0x32, 0x47, 0x55, 0x34, 0x4B, 0x7A, 0x67, 0x31, 0x55, 0x53, 0x45, 0x4F, 0x44, 0x6D, 0x38, 0x75, ++ 0x4E, 0x42, 0x4E, 0x41, 0x34, 0x53, 0x74, 0x6E, 0x44, 0x47, 0x31, 0x4B, 0x51, 0x54, 0x41, 0x59, 0x49, 0x31, 0x6F, 0x79, 0x56, 0x5A, 0x6E, 0x4A, 0x46, 0x2B, 0x41, 0x38, 0x33, 0x76, 0x62, 0x73, 0x65, 0x61, 0x30, 0x72, 0x57, 0x42, 0x6D, 0x69, ++ 0x72, 0x53, 0x77, 0x69, 0x0A, 0x47, 0x70, 0x57, 0x4F, 0x76, 0x70, 0x61, 0x51, 0x58, 0x55, 0x4A, 0x58, 0x78, 0x50, 0x6B, 0x55, 0x41, 0x7A, 0x55, 0x72, 0x48, 0x43, 0x31, 0x52, 0x56, 0x77, 0x69, 0x6E, 0x4F, 0x74, 0x34, 0x2F, 0x35, 0x4D, 0x69, ++ 0x30, 0x41, 0x33, 0x50, 0x43, 0x77, 0x53, 0x61, 0x41, 0x75, 0x77, 0x74, 0x43, 0x48, 0x36, 0x30, 0x4E, 0x72, 0x79, 0x5A, 0x79, 0x32, 0x73, 0x79, 0x2B, 0x73, 0x36, 0x4F, 0x44, 0x57, 0x41, 0x32, 0x43, 0x78, 0x52, 0x39, 0x47, 0x55, 0x65, 0x4F, ++ 0x63, 0x0A, 0x47, 0x4D, 0x79, 0x4E, 0x6D, 0x34, 0x33, 0x73, 0x53, 0x65, 0x74, 0x31, 0x55, 0x4E, 0x57, 0x4D, 0x4B, 0x46, 0x6E, 0x4B, 0x64, 0x44, 0x54, 0x61, 0x6A, 0x41, 0x73, 0x68, 0x71, 0x78, 0x37, 0x71, 0x47, 0x2B, 0x58, 0x48, 0x2F, 0x52, ++ 0x55, 0x2B, 0x77, 0x42, 0x65, 0x71, 0x2B, 0x79, 0x4E, 0x75, 0x4A, 0x6B, 0x62, 0x4C, 0x2B, 0x76, 0x6D, 0x78, 0x63, 0x6D, 0x74, 0x70, 0x7A, 0x79, 0x4B, 0x45, 0x43, 0x32, 0x49, 0x50, 0x72, 0x4E, 0x6B, 0x5A, 0x41, 0x4A, 0x53, 0x69, 0x0A, 0x64, ++ 0x6A, 0x7A, 0x55, 0x4C, 0x5A, 0x72, 0x74, 0x42, 0x4A, 0x34, 0x74, 0x42, 0x6D, 0x49, 0x51, 0x4E, 0x31, 0x49, 0x63, 0x68, 0x58, 0x49, 0x62, 0x4A, 0x2B, 0x58, 0x4D, 0x78, 0x6A, 0x48, 0x73, 0x4E, 0x2B, 0x78, 0x6A, 0x57, 0x5A, 0x73, 0x4C, 0x48, ++ 0x58, 0x62, 0x4D, 0x66, 0x6A, 0x4B, 0x61, 0x69, 0x4A, 0x55, 0x49, 0x4E, 0x6C, 0x4B, 0x37, 0x33, 0x6E, 0x5A, 0x66, 0x64, 0x6B, 0x6C, 0x4A, 0x72, 0x58, 0x2B, 0x39, 0x5A, 0x53, 0x43, 0x79, 0x79, 0x63, 0x45, 0x72, 0x0A, 0x64, 0x68, 0x68, 0x32, ++ 0x6E, 0x31, 0x61, 0x78, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x43, 0x65, 0x72, 0x74, 0x69, 0x67, 0x6E, 0x61, ++ 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, ++ 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x47, 0x57, 0x7A, 0x43, 0x43, 0x42, 0x45, 0x4F, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x52, 0x41, 0x4D, 0x72, 0x70, 0x47, 0x34, ++ 0x6E, 0x78, 0x56, 0x51, 0x4D, 0x4E, 0x6F, 0x2B, 0x5A, 0x42, 0x62, 0x63, 0x54, 0x6A, 0x70, 0x75, 0x45, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x42, 0x51, 0x41, 0x77, 0x57, 0x6A, ++ 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x0A, 0x42, 0x68, 0x4D, 0x43, 0x52, 0x6C, 0x49, 0x78, 0x45, 0x6A, 0x41, 0x51, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x4D, 0x43, 0x55, 0x52, 0x6F, 0x61, 0x57, 0x31, 0x35, 0x62, ++ 0x33, 0x52, 0x70, 0x63, 0x7A, 0x45, 0x63, 0x4D, 0x42, 0x6F, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x77, 0x77, 0x54, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x69, 0x41, 0x30, 0x4F, 0x44, 0x45, 0x30, 0x4E, 0x6A, 0x4D, 0x77, 0x4F, 0x44, 0x45, 0x77, 0x4D, ++ 0x44, 0x41, 0x7A, 0x4E, 0x6A, 0x45, 0x5A, 0x0A, 0x4D, 0x42, 0x63, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x77, 0x77, 0x51, 0x51, 0x32, 0x56, 0x79, 0x64, 0x47, 0x6C, 0x6E, 0x62, 0x6D, 0x45, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, ++ 0x51, 0x54, 0x41, 0x65, 0x46, 0x77, 0x30, 0x78, 0x4D, 0x7A, 0x45, 0x77, 0x4D, 0x44, 0x45, 0x77, 0x4F, 0x44, 0x4D, 0x79, 0x4D, 0x6A, 0x64, 0x61, 0x46, 0x77, 0x30, 0x7A, 0x4D, 0x7A, 0x45, 0x77, 0x4D, 0x44, 0x45, 0x77, 0x4F, 0x44, 0x4D, 0x79, ++ 0x4D, 0x6A, 0x64, 0x61, 0x0A, 0x4D, 0x46, 0x6F, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6B, 0x5A, 0x53, 0x4D, 0x52, 0x49, 0x77, 0x45, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x44, 0x41, 0x6C, ++ 0x45, 0x61, 0x47, 0x6C, 0x74, 0x65, 0x57, 0x39, 0x30, 0x61, 0x58, 0x4D, 0x78, 0x48, 0x44, 0x41, 0x61, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x73, 0x4D, 0x45, 0x7A, 0x41, 0x77, 0x4D, 0x44, 0x49, 0x67, 0x4E, 0x44, 0x67, 0x78, 0x4E, 0x44, 0x59, ++ 0x7A, 0x0A, 0x4D, 0x44, 0x67, 0x78, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x7A, 0x59, 0x78, 0x47, 0x54, 0x41, 0x58, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x4D, 0x45, 0x45, 0x4E, 0x6C, 0x63, 0x6E, 0x52, 0x70, 0x5A, 0x32, 0x35, 0x68, 0x49, 0x46, ++ 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x77, 0x67, 0x67, 0x49, 0x69, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x0A, 0x44, ++ 0x77, 0x41, 0x77, 0x67, 0x67, 0x49, 0x4B, 0x41, 0x6F, 0x49, 0x43, 0x41, 0x51, 0x44, 0x4E, 0x47, 0x44, 0x6C, 0x6C, 0x47, 0x6C, 0x6D, 0x78, 0x36, 0x6D, 0x51, 0x57, 0x44, 0x6F, 0x79, 0x55, 0x4A, 0x4A, 0x56, 0x38, 0x67, 0x39, 0x50, 0x46, 0x4F, ++ 0x53, 0x62, 0x63, 0x44, 0x4F, 0x38, 0x57, 0x56, 0x34, 0x33, 0x58, 0x32, 0x4B, 0x79, 0x6A, 0x51, 0x6E, 0x2B, 0x43, 0x79, 0x75, 0x33, 0x4E, 0x57, 0x39, 0x73, 0x4F, 0x74, 0x79, 0x33, 0x74, 0x52, 0x51, 0x67, 0x58, 0x0A, 0x73, 0x74, 0x6D, 0x7A, ++ 0x79, 0x39, 0x59, 0x58, 0x55, 0x6E, 0x49, 0x6F, 0x32, 0x34, 0x35, 0x4F, 0x6E, 0x6F, 0x71, 0x32, 0x43, 0x2F, 0x6D, 0x65, 0x68, 0x4A, 0x70, 0x4E, 0x64, 0x74, 0x34, 0x69, 0x4B, 0x56, 0x7A, 0x53, 0x73, 0x39, 0x49, 0x47, 0x50, 0x6A, 0x41, 0x35, ++ 0x71, 0x58, 0x53, 0x6A, 0x6B, 0x6C, 0x59, 0x63, 0x6F, 0x57, 0x39, 0x4D, 0x43, 0x69, 0x42, 0x74, 0x6E, 0x79, 0x4E, 0x36, 0x74, 0x4D, 0x62, 0x61, 0x4C, 0x4F, 0x51, 0x64, 0x4C, 0x4E, 0x79, 0x7A, 0x0A, 0x4B, 0x4E, 0x41, 0x54, 0x38, 0x6B, 0x78, ++ 0x4F, 0x41, 0x6B, 0x6D, 0x68, 0x56, 0x45, 0x43, 0x65, 0x35, 0x75, 0x55, 0x46, 0x6F, 0x43, 0x32, 0x45, 0x79, 0x50, 0x2B, 0x59, 0x62, 0x4E, 0x44, 0x72, 0x69, 0x68, 0x71, 0x45, 0x43, 0x42, 0x36, 0x33, 0x61, 0x43, 0x50, 0x75, 0x49, 0x39, 0x56, ++ 0x77, 0x7A, 0x6D, 0x31, 0x52, 0x61, 0x52, 0x44, 0x75, 0x6F, 0x58, 0x72, 0x43, 0x30, 0x53, 0x49, 0x78, 0x77, 0x6F, 0x4B, 0x46, 0x30, 0x76, 0x4A, 0x56, 0x64, 0x6C, 0x42, 0x38, 0x0A, 0x4A, 0x58, 0x72, 0x4A, 0x68, 0x46, 0x77, 0x4C, 0x72, 0x4E, ++ 0x31, 0x43, 0x54, 0x69, 0x76, 0x6E, 0x67, 0x71, 0x49, 0x6B, 0x69, 0x63, 0x75, 0x51, 0x73, 0x74, 0x44, 0x75, 0x49, 0x37, 0x70, 0x6D, 0x54, 0x4C, 0x74, 0x69, 0x70, 0x50, 0x6C, 0x54, 0x57, 0x6D, 0x52, 0x37, 0x66, 0x4A, 0x6A, 0x36, 0x6F, 0x30, ++ 0x69, 0x65, 0x44, 0x35, 0x57, 0x75, 0x70, 0x78, 0x6A, 0x30, 0x61, 0x75, 0x77, 0x75, 0x41, 0x30, 0x57, 0x76, 0x38, 0x48, 0x54, 0x34, 0x4B, 0x73, 0x31, 0x36, 0x0A, 0x58, 0x64, 0x47, 0x2B, 0x52, 0x43, 0x59, 0x79, 0x4B, 0x66, 0x48, 0x78, 0x39, ++ 0x57, 0x7A, 0x4D, 0x66, 0x67, 0x49, 0x68, 0x43, 0x35, 0x39, 0x76, 0x70, 0x44, 0x2B, 0x2B, 0x6E, 0x56, 0x50, 0x69, 0x7A, 0x33, 0x32, 0x70, 0x4C, 0x48, 0x78, 0x59, 0x47, 0x70, 0x66, 0x68, 0x50, 0x54, 0x63, 0x33, 0x47, 0x47, 0x59, 0x6F, 0x30, ++ 0x6B, 0x44, 0x46, 0x55, 0x59, 0x71, 0x4D, 0x77, 0x79, 0x33, 0x4F, 0x55, 0x34, 0x67, 0x6B, 0x57, 0x47, 0x51, 0x77, 0x46, 0x73, 0x57, 0x71, 0x0A, 0x34, 0x4E, 0x59, 0x4B, 0x70, 0x6B, 0x44, 0x66, 0x65, 0x50, 0x62, 0x31, 0x42, 0x48, 0x78, 0x70, ++ 0x45, 0x34, 0x53, 0x38, 0x30, 0x64, 0x47, 0x6E, 0x42, 0x73, 0x38, 0x42, 0x39, 0x32, 0x6A, 0x41, 0x71, 0x46, 0x65, 0x37, 0x4F, 0x6D, 0x47, 0x74, 0x42, 0x49, 0x79, 0x54, 0x34, 0x36, 0x33, 0x38, 0x38, 0x4E, 0x74, 0x45, 0x62, 0x56, 0x6E, 0x63, ++ 0x53, 0x56, 0x6D, 0x75, 0x72, 0x4A, 0x71, 0x5A, 0x4E, 0x6A, 0x42, 0x42, 0x65, 0x33, 0x59, 0x7A, 0x49, 0x6F, 0x65, 0x6A, 0x0A, 0x77, 0x70, 0x4B, 0x47, 0x62, 0x76, 0x6C, 0x77, 0x37, 0x71, 0x36, 0x48, 0x68, 0x35, 0x55, 0x62, 0x78, 0x48, 0x71, ++ 0x39, 0x4D, 0x66, 0x50, 0x55, 0x30, 0x75, 0x57, 0x5A, 0x2F, 0x37, 0x35, 0x49, 0x37, 0x48, 0x58, 0x31, 0x65, 0x42, 0x59, 0x64, 0x70, 0x6E, 0x44, 0x42, 0x66, 0x7A, 0x77, 0x62, 0x6F, 0x5A, 0x4C, 0x37, 0x7A, 0x38, 0x67, 0x38, 0x31, 0x73, 0x57, ++ 0x54, 0x43, 0x6F, 0x2F, 0x31, 0x56, 0x54, 0x70, 0x32, 0x6C, 0x63, 0x35, 0x5A, 0x6D, 0x49, 0x6F, 0x4A, 0x0A, 0x6C, 0x58, 0x63, 0x79, 0x6D, 0x6F, 0x4F, 0x36, 0x4C, 0x41, 0x51, 0x36, 0x6C, 0x37, 0x33, 0x55, 0x4C, 0x37, 0x37, 0x58, 0x62, 0x4A, ++ 0x75, 0x69, 0x79, 0x6E, 0x31, 0x74, 0x4A, 0x73, 0x6C, 0x56, 0x31, 0x63, 0x2F, 0x44, 0x65, 0x56, 0x49, 0x49, 0x43, 0x5A, 0x6B, 0x48, 0x4A, 0x43, 0x31, 0x6B, 0x4A, 0x57, 0x75, 0x6D, 0x49, 0x57, 0x6D, 0x62, 0x61, 0x74, 0x31, 0x30, 0x54, 0x57, ++ 0x75, 0x58, 0x65, 0x6B, 0x47, 0x39, 0x71, 0x78, 0x66, 0x35, 0x6B, 0x42, 0x64, 0x49, 0x0A, 0x6A, 0x7A, 0x62, 0x35, 0x4C, 0x64, 0x58, 0x46, 0x32, 0x2B, 0x36, 0x71, 0x68, 0x55, 0x56, 0x42, 0x2B, 0x73, 0x30, 0x36, 0x52, 0x62, 0x46, 0x6F, 0x35, ++ 0x6A, 0x5A, 0x4D, 0x6D, 0x35, 0x42, 0x58, 0x37, 0x43, 0x4F, 0x35, 0x68, 0x77, 0x6A, 0x43, 0x78, 0x41, 0x6E, 0x78, 0x6C, 0x34, 0x59, 0x71, 0x4B, 0x45, 0x33, 0x69, 0x64, 0x4D, 0x44, 0x61, 0x78, 0x49, 0x7A, 0x62, 0x33, 0x2B, 0x4B, 0x68, 0x46, ++ 0x31, 0x6E, 0x4F, 0x4A, 0x46, 0x6C, 0x30, 0x4D, 0x64, 0x70, 0x2F, 0x0A, 0x2F, 0x54, 0x42, 0x74, 0x32, 0x64, 0x7A, 0x68, 0x61, 0x75, 0x48, 0x38, 0x58, 0x77, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x6F, 0x34, 0x49, 0x42, 0x47, 0x6A, 0x43, 0x43, ++ 0x41, 0x52, 0x59, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x42, 0x41, 0x66, 0x38, 0x45, ++ 0x42, 0x41, 0x4D, 0x43, 0x41, 0x51, 0x59, 0x77, 0x0A, 0x48, 0x51, 0x59, 0x44, 0x56, 0x52, 0x30, 0x4F, 0x42, 0x42, 0x59, 0x45, 0x46, 0x42, 0x69, 0x48, 0x56, 0x75, 0x42, 0x75, 0x64, 0x2B, 0x34, 0x6B, 0x4E, 0x54, 0x78, 0x4F, 0x63, 0x35, 0x6F, ++ 0x66, 0x31, 0x75, 0x48, 0x69, 0x65, 0x58, 0x34, 0x72, 0x4D, 0x42, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x49, 0x77, 0x51, 0x59, 0x4D, 0x42, 0x61, 0x41, 0x46, 0x42, 0x69, 0x48, 0x56, 0x75, 0x42, 0x75, 0x64, 0x2B, 0x34, 0x6B, 0x4E, 0x54, 0x78, ++ 0x4F, 0x63, 0x35, 0x6F, 0x66, 0x0A, 0x31, 0x75, 0x48, 0x69, 0x65, 0x58, 0x34, 0x72, 0x4D, 0x45, 0x51, 0x47, 0x41, 0x31, 0x55, 0x64, 0x49, 0x41, 0x51, 0x39, 0x4D, 0x44, 0x73, 0x77, 0x4F, 0x51, 0x59, 0x45, 0x56, 0x52, 0x30, 0x67, 0x41, 0x44, ++ 0x41, 0x78, 0x4D, 0x43, 0x38, 0x47, 0x43, 0x43, 0x73, 0x47, 0x41, 0x51, 0x55, 0x46, 0x42, 0x77, 0x49, 0x42, 0x46, 0x69, 0x4E, 0x6F, 0x64, 0x48, 0x52, 0x77, 0x63, 0x7A, 0x6F, 0x76, 0x4C, 0x33, 0x64, 0x33, 0x64, 0x33, 0x63, 0x75, 0x59, 0x32, ++ 0x56, 0x79, 0x0A, 0x64, 0x47, 0x6C, 0x6E, 0x62, 0x6D, 0x45, 0x75, 0x5A, 0x6E, 0x49, 0x76, 0x59, 0x58, 0x56, 0x30, 0x62, 0x33, 0x4A, 0x70, 0x64, 0x47, 0x56, 0x7A, 0x4C, 0x7A, 0x42, 0x74, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x52, 0x38, 0x45, 0x5A, ++ 0x6A, 0x42, 0x6B, 0x4D, 0x43, 0x2B, 0x67, 0x4C, 0x61, 0x41, 0x72, 0x68, 0x69, 0x6C, 0x6F, 0x64, 0x48, 0x52, 0x77, 0x4F, 0x69, 0x38, 0x76, 0x59, 0x33, 0x4A, 0x73, 0x4C, 0x6D, 0x4E, 0x6C, 0x63, 0x6E, 0x52, 0x70, 0x5A, 0x32, 0x35, 0x68, 0x0A, ++ 0x4C, 0x6D, 0x5A, 0x79, 0x4C, 0x32, 0x4E, 0x6C, 0x63, 0x6E, 0x52, 0x70, 0x5A, 0x32, 0x35, 0x68, 0x63, 0x6D, 0x39, 0x76, 0x64, 0x47, 0x4E, 0x68, 0x4C, 0x6D, 0x4E, 0x79, 0x62, 0x44, 0x41, 0x78, 0x6F, 0x43, 0x2B, 0x67, 0x4C, 0x59, 0x59, 0x72, ++ 0x61, 0x48, 0x52, 0x30, 0x63, 0x44, 0x6F, 0x76, 0x4C, 0x32, 0x4E, 0x79, 0x62, 0x43, 0x35, 0x6B, 0x61, 0x47, 0x6C, 0x74, 0x65, 0x57, 0x39, 0x30, 0x61, 0x58, 0x4D, 0x75, 0x59, 0x32, 0x39, 0x74, 0x4C, 0x32, 0x4E, 0x6C, 0x0A, 0x63, 0x6E, 0x52, ++ 0x70, 0x5A, 0x32, 0x35, 0x68, 0x63, 0x6D, 0x39, 0x76, 0x64, 0x47, 0x4E, 0x68, 0x4C, 0x6D, 0x4E, 0x79, 0x62, 0x44, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x41, 0x4F, ++ 0x43, 0x41, 0x67, 0x45, 0x41, 0x6C, 0x4C, 0x69, 0x65, 0x54, 0x2F, 0x44, 0x6A, 0x6C, 0x51, 0x67, 0x69, 0x35, 0x38, 0x31, 0x6F, 0x51, 0x66, 0x63, 0x63, 0x56, 0x64, 0x56, 0x38, 0x41, 0x4F, 0x49, 0x74, 0x0A, 0x4F, 0x6F, 0x6C, 0x64, 0x61, 0x44, ++ 0x67, 0x76, 0x55, 0x53, 0x49, 0x4C, 0x53, 0x6F, 0x33, 0x4C, 0x36, 0x62, 0x74, 0x64, 0x50, 0x72, 0x74, 0x63, 0x50, 0x62, 0x45, 0x6F, 0x2F, 0x75, 0x52, 0x54, 0x56, 0x52, 0x50, 0x50, 0x6F, 0x5A, 0x41, 0x62, 0x41, 0x68, 0x31, 0x66, 0x5A, 0x6B, ++ 0x59, 0x4A, 0x4D, 0x79, 0x6A, 0x68, 0x44, 0x53, 0x53, 0x58, 0x63, 0x4E, 0x4D, 0x51, 0x48, 0x2B, 0x70, 0x6B, 0x56, 0x35, 0x61, 0x37, 0x58, 0x64, 0x72, 0x6E, 0x78, 0x49, 0x78, 0x50, 0x0A, 0x54, 0x47, 0x52, 0x47, 0x48, 0x56, 0x79, 0x48, 0x34, ++ 0x31, 0x6E, 0x65, 0x51, 0x74, 0x47, 0x62, 0x71, 0x48, 0x36, 0x6D, 0x69, 0x64, 0x32, 0x50, 0x48, 0x4D, 0x6B, 0x77, 0x67, 0x75, 0x30, 0x37, 0x6E, 0x4D, 0x33, 0x41, 0x36, 0x52, 0x6E, 0x67, 0x61, 0x74, 0x67, 0x43, 0x64, 0x54, 0x65, 0x72, 0x39, ++ 0x7A, 0x51, 0x6F, 0x4B, 0x4A, 0x48, 0x79, 0x42, 0x41, 0x70, 0x50, 0x4E, 0x65, 0x4E, 0x67, 0x4A, 0x67, 0x48, 0x36, 0x30, 0x42, 0x47, 0x4D, 0x2B, 0x52, 0x46, 0x71, 0x0A, 0x37, 0x71, 0x38, 0x39, 0x77, 0x31, 0x44, 0x54, 0x6A, 0x31, 0x38, 0x7A, ++ 0x65, 0x54, 0x79, 0x47, 0x71, 0x48, 0x4E, 0x46, 0x6B, 0x49, 0x77, 0x67, 0x74, 0x6E, 0x4A, 0x7A, 0x46, 0x79, 0x4F, 0x2B, 0x42, 0x32, 0x58, 0x6C, 0x65, 0x4A, 0x49, 0x4E, 0x75, 0x67, 0x48, 0x41, 0x36, 0x34, 0x77, 0x63, 0x5A, 0x72, 0x2B, 0x73, ++ 0x68, 0x6E, 0x63, 0x42, 0x6C, 0x41, 0x32, 0x63, 0x35, 0x75, 0x6B, 0x35, 0x6A, 0x52, 0x2B, 0x6D, 0x55, 0x59, 0x79, 0x5A, 0x44, 0x44, 0x6C, 0x33, 0x0A, 0x34, 0x62, 0x53, 0x62, 0x2B, 0x68, 0x78, 0x6E, 0x56, 0x32, 0x39, 0x71, 0x61, 0x6F, 0x36, ++ 0x70, 0x4B, 0x30, 0x78, 0x58, 0x65, 0x58, 0x70, 0x58, 0x49, 0x73, 0x2F, 0x4E, 0x58, 0x32, 0x4E, 0x47, 0x6A, 0x56, 0x78, 0x5A, 0x4F, 0x6F, 0x62, 0x34, 0x4D, 0x6B, 0x64, 0x69, 0x6F, 0x32, 0x63, 0x4E, 0x47, 0x4A, 0x48, 0x63, 0x2B, 0x36, 0x5A, ++ 0x72, 0x39, 0x55, 0x68, 0x68, 0x63, 0x79, 0x4E, 0x5A, 0x6A, 0x67, 0x4B, 0x6E, 0x76, 0x45, 0x54, 0x71, 0x39, 0x45, 0x6D, 0x64, 0x0A, 0x38, 0x56, 0x52, 0x59, 0x2B, 0x57, 0x43, 0x76, 0x32, 0x68, 0x69, 0x6B, 0x4C, 0x79, 0x68, 0x46, 0x33, 0x48, ++ 0x71, 0x67, 0x69, 0x49, 0x5A, 0x64, 0x38, 0x7A, 0x76, 0x6E, 0x2F, 0x79, 0x6B, 0x31, 0x67, 0x50, 0x78, 0x6B, 0x51, 0x35, 0x54, 0x6D, 0x34, 0x78, 0x78, 0x76, 0x76, 0x71, 0x30, 0x4F, 0x4B, 0x6D, 0x4F, 0x5A, 0x4B, 0x38, 0x6C, 0x2B, 0x68, 0x66, ++ 0x5A, 0x78, 0x36, 0x41, 0x59, 0x44, 0x6C, 0x66, 0x37, 0x65, 0x6A, 0x30, 0x67, 0x63, 0x57, 0x74, 0x53, 0x53, 0x0A, 0x36, 0x43, 0x76, 0x75, 0x35, 0x7A, 0x48, 0x62, 0x75, 0x67, 0x52, 0x71, 0x68, 0x35, 0x6A, 0x6E, 0x78, 0x56, 0x2F, 0x76, 0x66, ++ 0x61, 0x63, 0x69, 0x39, 0x77, 0x48, 0x59, 0x54, 0x66, 0x6D, 0x4A, 0x30, 0x41, 0x36, 0x61, 0x42, 0x56, 0x6D, 0x6B, 0x6E, 0x70, 0x6A, 0x5A, 0x62, 0x79, 0x76, 0x4B, 0x63, 0x4C, 0x35, 0x6B, 0x77, 0x6C, 0x57, 0x6A, 0x39, 0x4F, 0x6D, 0x76, 0x77, ++ 0x35, 0x49, 0x70, 0x33, 0x49, 0x67, 0x57, 0x4A, 0x4A, 0x6B, 0x38, 0x6A, 0x53, 0x61, 0x59, 0x0A, 0x74, 0x6C, 0x75, 0x33, 0x7A, 0x4D, 0x36, 0x33, 0x4E, 0x77, 0x66, 0x39, 0x4A, 0x74, 0x6D, 0x59, 0x68, 0x53, 0x54, 0x2F, 0x57, 0x53, 0x4D, 0x44, ++ 0x6D, 0x75, 0x32, 0x64, 0x6E, 0x61, 0x6A, 0x6B, 0x58, 0x6A, 0x6A, 0x4F, 0x31, 0x31, 0x49, 0x4E, 0x62, 0x39, 0x49, 0x2F, 0x62, 0x62, 0x45, 0x46, 0x61, 0x30, 0x6E, 0x4F, 0x69, 0x70, 0x46, 0x47, 0x63, 0x2F, 0x54, 0x32, 0x4C, 0x2F, 0x43, 0x6F, ++ 0x63, 0x33, 0x63, 0x4F, 0x5A, 0x61, 0x79, 0x68, 0x6A, 0x57, 0x5A, 0x53, 0x0A, 0x61, 0x58, 0x35, 0x4C, 0x61, 0x41, 0x7A, 0x48, 0x48, 0x6A, 0x63, 0x6E, 0x67, 0x36, 0x57, 0x4D, 0x78, 0x77, 0x4C, 0x6B, 0x46, 0x4D, 0x31, 0x4A, 0x41, 0x62, 0x42, ++ 0x7A, 0x73, 0x2F, 0x33, 0x47, 0x6B, 0x44, 0x70, 0x76, 0x30, 0x6D, 0x7A, 0x74, 0x4F, 0x2B, 0x37, 0x73, 0x6B, 0x62, 0x36, 0x69, 0x51, 0x31, 0x32, 0x4C, 0x41, 0x45, 0x70, 0x6D, 0x4A, 0x55, 0x52, 0x77, 0x33, 0x6B, 0x41, 0x50, 0x2B, 0x48, 0x77, ++ 0x56, 0x39, 0x36, 0x4C, 0x4F, 0x50, 0x4E, 0x64, 0x65, 0x0A, 0x45, 0x34, 0x79, 0x42, 0x46, 0x78, 0x67, 0x58, 0x30, 0x62, 0x33, 0x78, 0x64, 0x78, 0x41, 0x36, 0x31, 0x47, 0x55, 0x35, 0x77, 0x53, 0x65, 0x73, 0x56, 0x79, 0x77, 0x6C, 0x56, 0x50, ++ 0x2B, 0x69, 0x32, 0x6B, 0x2B, 0x4B, 0x59, 0x54, 0x6C, 0x65, 0x72, 0x6A, 0x31, 0x4B, 0x6A, 0x4C, 0x30, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, ++ 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x31, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x44, 0x6C, 0x44, ++ 0x43, 0x43, 0x41, 0x6E, 0x79, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x4B, 0x4D, 0x66, 0x58, 0x6B, 0x59, 0x67, 0x78, 0x73, 0x57, 0x4F, 0x33, 0x57, 0x32, 0x44, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, ++ 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x44, 0x42, 0x6E, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x4A, 0x54, 0x6A, 0x45, 0x54, 0x0A, 0x4D, 0x42, 0x45, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, ++ 0x78, 0x4D, 0x4B, 0x5A, 0x57, 0x31, 0x54, 0x61, 0x57, 0x64, 0x75, 0x49, 0x46, 0x42, 0x4C, 0x53, 0x54, 0x45, 0x6C, 0x4D, 0x43, 0x4D, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x63, 0x5A, 0x55, 0x31, 0x31, 0x5A, 0x47, 0x68, 0x79, 0x59, ++ 0x53, 0x42, 0x55, 0x5A, 0x57, 0x4E, 0x6F, 0x62, 0x6D, 0x39, 0x73, 0x62, 0x32, 0x64, 0x70, 0x5A, 0x58, 0x4D, 0x67, 0x54, 0x47, 0x6C, 0x74, 0x61, 0x58, 0x52, 0x6C, 0x0A, 0x5A, 0x44, 0x45, 0x63, 0x4D, 0x42, 0x6F, 0x47, 0x41, 0x31, 0x55, 0x45, ++ 0x41, 0x78, 0x4D, 0x54, 0x5A, 0x57, 0x31, 0x54, 0x61, 0x57, 0x64, 0x75, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x67, 0x4C, 0x53, 0x42, 0x48, 0x4D, 0x54, 0x41, 0x65, 0x46, 0x77, 0x30, 0x78, 0x4F, 0x44, 0x41, 0x79, ++ 0x4D, 0x54, 0x67, 0x78, 0x4F, 0x44, 0x4D, 0x77, 0x4D, 0x44, 0x42, 0x61, 0x46, 0x77, 0x30, 0x30, 0x4D, 0x7A, 0x41, 0x79, 0x4D, 0x54, 0x67, 0x78, 0x0A, 0x4F, 0x44, 0x4D, 0x77, 0x4D, 0x44, 0x42, 0x61, 0x4D, 0x47, 0x63, 0x78, 0x43, 0x7A, 0x41, ++ 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6B, 0x6C, 0x4F, 0x4D, 0x52, 0x4D, 0x77, 0x45, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4C, 0x45, 0x77, 0x70, 0x6C, 0x62, 0x56, 0x4E, 0x70, 0x5A, 0x32, 0x34, 0x67, 0x55, 0x45, 0x74, ++ 0x4A, 0x4D, 0x53, 0x55, 0x77, 0x49, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x45, 0x78, 0x78, 0x6C, 0x54, 0x58, 0x56, 0x6B, 0x0A, 0x61, 0x48, 0x4A, 0x68, 0x49, 0x46, 0x52, 0x6C, 0x59, 0x32, 0x68, 0x75, 0x62, 0x32, 0x78, 0x76, 0x5A, 0x32, ++ 0x6C, 0x6C, 0x63, 0x79, 0x42, 0x4D, 0x61, 0x57, 0x31, 0x70, 0x64, 0x47, 0x56, 0x6B, 0x4D, 0x52, 0x77, 0x77, 0x47, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x4E, 0x6C, 0x62, 0x56, 0x4E, 0x70, 0x5A, 0x32, 0x34, 0x67, 0x55, 0x6D, ++ 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x51, 0x53, 0x41, 0x74, 0x49, 0x45, 0x63, 0x78, 0x4D, 0x49, 0x49, 0x42, 0x0A, 0x49, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x45, 0x46, 0x41, ++ 0x41, 0x4F, 0x43, 0x41, 0x51, 0x38, 0x41, 0x4D, 0x49, 0x49, 0x42, 0x43, 0x67, 0x4B, 0x43, 0x41, 0x51, 0x45, 0x41, 0x6B, 0x30, 0x75, 0x37, 0x36, 0x57, 0x61, 0x4B, 0x37, 0x70, 0x31, 0x62, 0x31, 0x54, 0x53, 0x54, 0x30, 0x42, 0x73, 0x65, 0x77, ++ 0x2B, 0x65, 0x65, 0x75, 0x47, 0x51, 0x7A, 0x66, 0x32, 0x4E, 0x34, 0x61, 0x4C, 0x54, 0x4E, 0x0A, 0x4C, 0x6E, 0x46, 0x31, 0x31, 0x35, 0x73, 0x67, 0x78, 0x6B, 0x30, 0x70, 0x76, 0x4C, 0x5A, 0x6F, 0x59, 0x49, 0x72, 0x33, 0x49, 0x5A, 0x70, 0x57, ++ 0x4E, 0x56, 0x72, 0x7A, 0x64, 0x72, 0x33, 0x59, 0x7A, 0x5A, 0x72, 0x2F, 0x6B, 0x31, 0x5A, 0x4C, 0x70, 0x56, 0x6B, 0x47, 0x6F, 0x5A, 0x4D, 0x30, 0x4B, 0x64, 0x30, 0x57, 0x4E, 0x48, 0x56, 0x4F, 0x38, 0x6F, 0x47, 0x30, 0x78, 0x35, 0x5A, 0x4F, ++ 0x72, 0x52, 0x6B, 0x56, 0x55, 0x6B, 0x72, 0x2B, 0x50, 0x48, 0x42, 0x31, 0x0A, 0x63, 0x4D, 0x32, 0x76, 0x4B, 0x36, 0x73, 0x56, 0x6D, 0x6A, 0x4D, 0x38, 0x71, 0x72, 0x4F, 0x4C, 0x71, 0x73, 0x31, 0x44, 0x2F, 0x66, 0x58, 0x71, 0x63, 0x50, 0x2F, ++ 0x74, 0x7A, 0x78, 0x45, 0x37, 0x6C, 0x4D, 0x35, 0x4F, 0x4D, 0x68, 0x62, 0x54, 0x49, 0x30, 0x41, 0x71, 0x64, 0x37, 0x4F, 0x76, 0x50, 0x41, 0x45, 0x73, 0x62, 0x4F, 0x32, 0x5A, 0x4C, 0x49, 0x76, 0x5A, 0x54, 0x6D, 0x6D, 0x59, 0x73, 0x76, 0x65, ++ 0x50, 0x51, 0x62, 0x41, 0x79, 0x65, 0x47, 0x48, 0x57, 0x0A, 0x44, 0x56, 0x2F, 0x44, 0x2B, 0x71, 0x4A, 0x41, 0x6B, 0x68, 0x31, 0x63, 0x46, 0x2B, 0x5A, 0x77, 0x50, 0x6A, 0x58, 0x6E, 0x6F, 0x72, 0x66, 0x43, 0x59, 0x75, 0x4B, 0x72, 0x70, 0x44, ++ 0x68, 0x4D, 0x74, 0x54, 0x6B, 0x31, 0x62, 0x2B, 0x6F, 0x44, 0x61, 0x66, 0x6F, 0x36, 0x56, 0x47, 0x69, 0x46, 0x62, 0x64, 0x62, 0x79, 0x4C, 0x30, 0x4E, 0x56, 0x48, 0x70, 0x45, 0x4E, 0x44, 0x74, 0x6A, 0x56, 0x61, 0x71, 0x53, 0x57, 0x30, 0x52, ++ 0x4D, 0x38, 0x4C, 0x48, 0x68, 0x51, 0x0A, 0x36, 0x44, 0x71, 0x53, 0x30, 0x68, 0x64, 0x57, 0x35, 0x54, 0x55, 0x61, 0x51, 0x42, 0x77, 0x2B, 0x6A, 0x53, 0x7A, 0x74, 0x4F, 0x64, 0x39, 0x43, 0x34, 0x49, 0x4E, 0x42, 0x64, 0x4E, 0x2B, 0x6A, 0x7A, ++ 0x63, 0x4B, 0x47, 0x59, 0x45, 0x68, 0x6F, 0x34, 0x32, 0x6B, 0x4C, 0x56, 0x41, 0x43, 0x4C, 0x35, 0x48, 0x5A, 0x70, 0x49, 0x51, 0x31, 0x35, 0x54, 0x6A, 0x51, 0x49, 0x58, 0x68, 0x54, 0x43, 0x7A, 0x4C, 0x47, 0x33, 0x72, 0x64, 0x64, 0x38, 0x63, ++ 0x49, 0x72, 0x48, 0x0A, 0x68, 0x51, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x6F, 0x30, 0x49, 0x77, 0x51, 0x44, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x2B, 0x2B, 0x38, 0x4E, 0x68, 0x70, 0x36, 0x77, ++ 0x34, 0x39, 0x32, 0x70, 0x75, 0x66, 0x45, 0x68, 0x46, 0x33, 0x38, 0x2B, 0x2F, 0x50, 0x42, 0x33, 0x4B, 0x78, 0x6F, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x51, 0x44, 0x41, 0x67, 0x45, 0x47, ++ 0x0A, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, ++ 0x4C, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x45, 0x42, 0x41, 0x46, 0x6E, 0x2F, 0x38, 0x6F, 0x7A, 0x31, 0x68, 0x33, 0x31, 0x78, 0x50, 0x61, 0x4F, 0x66, 0x47, 0x31, 0x76, 0x52, 0x32, 0x76, 0x6A, 0x54, 0x6E, 0x47, 0x73, 0x32, 0x0A, 0x76, 0x5A, ++ 0x75, 0x70, 0x59, 0x65, 0x76, 0x65, 0x46, 0x69, 0x78, 0x30, 0x50, 0x5A, 0x37, 0x6D, 0x64, 0x64, 0x72, 0x58, 0x75, 0x71, 0x65, 0x38, 0x51, 0x68, 0x66, 0x6E, 0x50, 0x5A, 0x48, 0x72, 0x35, 0x58, 0x33, 0x64, 0x50, 0x70, 0x7A, 0x78, 0x7A, 0x35, ++ 0x4B, 0x73, 0x62, 0x45, 0x6A, 0x4D, 0x77, 0x69, 0x49, 0x2F, 0x61, 0x54, 0x76, 0x46, 0x74, 0x68, 0x55, 0x76, 0x6F, 0x7A, 0x58, 0x47, 0x61, 0x43, 0x6F, 0x63, 0x56, 0x36, 0x38, 0x35, 0x37, 0x34, 0x33, 0x51, 0x0A, 0x4E, 0x63, 0x4D, 0x59, 0x44, ++ 0x48, 0x73, 0x41, 0x56, 0x68, 0x7A, 0x4E, 0x69, 0x78, 0x6C, 0x30, 0x33, 0x72, 0x34, 0x50, 0x45, 0x75, 0x44, 0x51, 0x71, 0x71, 0x45, 0x2F, 0x41, 0x6A, 0x53, 0x78, 0x63, 0x4D, 0x36, 0x64, 0x47, 0x4E, 0x59, 0x49, 0x41, 0x77, 0x6C, 0x47, 0x37, ++ 0x6D, 0x44, 0x67, 0x66, 0x72, 0x62, 0x45, 0x53, 0x51, 0x52, 0x52, 0x66, 0x58, 0x42, 0x67, 0x76, 0x4B, 0x71, 0x79, 0x2F, 0x33, 0x6C, 0x79, 0x65, 0x71, 0x59, 0x64, 0x50, 0x56, 0x38, 0x71, 0x0A, 0x2B, 0x4D, 0x72, 0x69, 0x2F, 0x54, 0x6D, 0x33, ++ 0x52, 0x37, 0x6E, 0x72, 0x66, 0x74, 0x38, 0x45, 0x49, 0x36, 0x2F, 0x36, 0x6E, 0x41, 0x59, 0x48, 0x36, 0x66, 0x74, 0x6A, 0x6B, 0x34, 0x42, 0x41, 0x74, 0x63, 0x5A, 0x73, 0x43, 0x6A, 0x45, 0x6F, 0x7A, 0x67, 0x79, 0x66, 0x7A, 0x37, 0x4D, 0x6A, ++ 0x4E, 0x59, 0x42, 0x42, 0x6A, 0x57, 0x7A, 0x45, 0x4E, 0x33, 0x75, 0x42, 0x4C, 0x34, 0x43, 0x68, 0x51, 0x45, 0x4B, 0x46, 0x36, 0x64, 0x6B, 0x34, 0x6A, 0x65, 0x69, 0x68, 0x0A, 0x55, 0x38, 0x30, 0x42, 0x76, 0x32, 0x6E, 0x6F, 0x57, 0x67, 0x62, ++ 0x79, 0x52, 0x51, 0x75, 0x51, 0x2B, 0x71, 0x37, 0x68, 0x76, 0x35, 0x33, 0x79, 0x72, 0x6C, 0x63, 0x38, 0x70, 0x61, 0x36, 0x79, 0x56, 0x76, 0x53, 0x4C, 0x5A, 0x55, 0x44, 0x70, 0x2F, 0x54, 0x47, 0x42, 0x4C, 0x50, 0x51, 0x35, 0x43, 0x64, 0x6A, ++ 0x75, 0x61, 0x36, 0x65, 0x30, 0x70, 0x68, 0x30, 0x56, 0x70, 0x5A, 0x6A, 0x33, 0x41, 0x59, 0x48, 0x59, 0x68, 0x58, 0x33, 0x7A, 0x55, 0x56, 0x78, 0x78, 0x0A, 0x69, 0x4E, 0x36, 0x36, 0x7A, 0x42, 0x2B, 0x41, 0x66, 0x6B, 0x6F, 0x3D, 0x0A, 0x2D, ++ 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, ++ 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x33, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, ++ 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x43, 0x54, 0x6A, 0x43, 0x43, 0x41, 0x64, 0x4F, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, ++ 0x49, 0x4B, 0x50, 0x50, 0x59, 0x48, 0x71, 0x57, 0x68, 0x77, 0x44, 0x74, 0x71, 0x4C, 0x68, 0x44, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x7A, 0x42, 0x72, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, ++ 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x4A, 0x54, 0x6A, 0x45, 0x54, 0x4D, 0x42, 0x45, 0x47, 0x0A, 0x41, 0x31, 0x55, 0x45, 0x43, 0x78, 0x4D, 0x4B, 0x5A, 0x57, 0x31, 0x54, 0x61, 0x57, 0x64, 0x75, 0x49, 0x46, 0x42, 0x4C, 0x53, ++ 0x54, 0x45, 0x6C, 0x4D, 0x43, 0x4D, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x63, 0x5A, 0x55, 0x31, 0x31, 0x5A, 0x47, 0x68, 0x79, 0x59, 0x53, 0x42, 0x55, 0x5A, 0x57, 0x4E, 0x6F, 0x62, 0x6D, 0x39, 0x73, 0x62, 0x32, 0x64, 0x70, 0x5A, ++ 0x58, 0x4D, 0x67, 0x54, 0x47, 0x6C, 0x74, 0x61, 0x58, 0x52, 0x6C, 0x5A, 0x44, 0x45, 0x67, 0x0A, 0x4D, 0x42, 0x34, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x58, 0x5A, 0x57, 0x31, 0x54, 0x61, 0x57, 0x64, 0x75, 0x49, 0x45, 0x56, 0x44, ++ 0x51, 0x79, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x42, 0x49, 0x43, 0x30, 0x67, 0x52, 0x7A, 0x4D, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x54, 0x67, 0x77, 0x4D, 0x6A, 0x45, 0x34, 0x4D, 0x54, 0x67, 0x7A, 0x4D, 0x44, 0x41, 0x77, ++ 0x57, 0x68, 0x63, 0x4E, 0x4E, 0x44, 0x4D, 0x77, 0x4D, 0x6A, 0x45, 0x34, 0x0A, 0x4D, 0x54, 0x67, 0x7A, 0x4D, 0x44, 0x41, 0x77, 0x57, 0x6A, 0x42, 0x72, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, ++ 0x4A, 0x54, 0x6A, 0x45, 0x54, 0x4D, 0x42, 0x45, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x78, 0x4D, 0x4B, 0x5A, 0x57, 0x31, 0x54, 0x61, 0x57, 0x64, 0x75, 0x49, 0x46, 0x42, 0x4C, 0x53, 0x54, 0x45, 0x6C, 0x4D, 0x43, 0x4D, 0x47, 0x41, 0x31, 0x55, ++ 0x45, 0x43, 0x68, 0x4D, 0x63, 0x5A, 0x55, 0x31, 0x31, 0x0A, 0x5A, 0x47, 0x68, 0x79, 0x59, 0x53, 0x42, 0x55, 0x5A, 0x57, 0x4E, 0x6F, 0x62, 0x6D, 0x39, 0x73, 0x62, 0x32, 0x64, 0x70, 0x5A, 0x58, 0x4D, 0x67, 0x54, 0x47, 0x6C, 0x74, 0x61, 0x58, ++ 0x52, 0x6C, 0x5A, 0x44, 0x45, 0x67, 0x4D, 0x42, 0x34, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x58, 0x5A, 0x57, 0x31, 0x54, 0x61, 0x57, 0x64, 0x75, 0x49, 0x45, 0x56, 0x44, 0x51, 0x79, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, ++ 0x4E, 0x42, 0x49, 0x43, 0x30, 0x67, 0x0A, 0x52, 0x7A, 0x4D, 0x77, 0x64, 0x6A, 0x41, 0x51, 0x42, 0x67, 0x63, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x49, 0x42, 0x42, 0x67, 0x55, 0x72, 0x67, 0x51, 0x51, 0x41, 0x49, 0x67, 0x4E, 0x69, 0x41, ++ 0x41, 0x51, 0x6A, 0x70, 0x51, 0x79, 0x34, 0x4C, 0x52, 0x4C, 0x31, 0x4B, 0x50, 0x4F, 0x78, 0x73, 0x74, 0x33, 0x69, 0x41, 0x68, 0x4B, 0x41, 0x6E, 0x6A, 0x6C, 0x66, 0x53, 0x55, 0x32, 0x66, 0x79, 0x53, 0x55, 0x30, 0x57, 0x58, 0x54, 0x73, 0x75, ++ 0x77, 0x59, 0x63, 0x0A, 0x35, 0x38, 0x42, 0x79, 0x72, 0x2B, 0x69, 0x75, 0x4C, 0x2B, 0x46, 0x42, 0x56, 0x49, 0x63, 0x55, 0x71, 0x45, 0x71, 0x79, 0x36, 0x48, 0x79, 0x43, 0x35, 0x6C, 0x74, 0x71, 0x74, 0x64, 0x79, 0x7A, 0x64, 0x63, 0x36, 0x4C, ++ 0x42, 0x74, 0x43, 0x47, 0x49, 0x37, 0x39, 0x47, 0x31, 0x59, 0x34, 0x50, 0x50, 0x77, 0x54, 0x30, 0x31, 0x78, 0x79, 0x53, 0x66, 0x76, 0x61, 0x6C, 0x59, 0x38, 0x4C, 0x31, 0x58, 0x34, 0x34, 0x75, 0x54, 0x36, 0x45, 0x59, 0x47, 0x51, 0x49, 0x72, ++ 0x0A, 0x4D, 0x67, 0x71, 0x43, 0x5A, 0x48, 0x30, 0x57, 0x6B, 0x39, 0x47, 0x6A, 0x51, 0x6A, 0x42, 0x41, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x52, 0x38, 0x58, 0x51, 0x4B, 0x45, 0x45, 0x39, 0x54, ++ 0x4D, 0x69, 0x70, 0x75, 0x42, 0x7A, 0x68, 0x63, 0x63, 0x4C, 0x69, 0x6B, 0x65, 0x6E, 0x45, 0x68, 0x6A, 0x51, 0x6A, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x41, 0x4D, 0x43, 0x0A, 0x41, 0x51, ++ 0x59, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x77, ++ 0x4E, 0x70, 0x41, 0x44, 0x42, 0x6D, 0x41, 0x6A, 0x45, 0x41, 0x76, 0x76, 0x4E, 0x68, 0x7A, 0x77, 0x49, 0x51, 0x48, 0x57, 0x53, 0x56, 0x42, 0x37, 0x67, 0x59, 0x62, 0x6F, 0x69, 0x46, 0x42, 0x53, 0x2B, 0x44, 0x0A, 0x43, 0x42, 0x65, 0x51, 0x79, ++ 0x68, 0x2B, 0x4B, 0x54, 0x4F, 0x67, 0x4E, 0x47, 0x33, 0x71, 0x78, 0x72, 0x64, 0x57, 0x42, 0x43, 0x55, 0x66, 0x76, 0x4F, 0x36, 0x77, 0x49, 0x42, 0x48, 0x78, 0x63, 0x6D, 0x62, 0x48, 0x74, 0x52, 0x77, 0x66, 0x53, 0x41, 0x6A, 0x45, 0x41, 0x6E, ++ 0x62, 0x70, 0x56, 0x2F, 0x4B, 0x6C, 0x4B, 0x36, 0x4F, 0x33, 0x74, 0x35, 0x6E, 0x59, 0x42, 0x51, 0x6E, 0x76, 0x49, 0x2B, 0x47, 0x44, 0x5A, 0x6A, 0x56, 0x47, 0x4C, 0x56, 0x54, 0x76, 0x37, 0x0A, 0x6A, 0x48, 0x76, 0x72, 0x5A, 0x51, 0x6E, 0x44, ++ 0x2B, 0x4A, 0x62, 0x4E, 0x52, 0x36, 0x69, 0x43, 0x38, 0x68, 0x5A, 0x56, 0x64, 0x79, 0x52, 0x2B, 0x45, 0x68, 0x43, 0x56, 0x42, 0x43, 0x79, 0x6A, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, ++ 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x43, 0x31, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, ++ 0x4D, 0x49, 0x49, 0x44, 0x63, 0x7A, 0x43, 0x43, 0x41, 0x6C, 0x75, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x4C, 0x41, 0x4B, 0x37, 0x50, 0x41, 0x4C, 0x72, 0x45, 0x7A, 0x7A, 0x4C, 0x34, 0x51, 0x37, 0x49, 0x77, 0x44, 0x51, 0x59, 0x4A, ++ 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x42, 0x51, 0x41, 0x77, 0x56, 0x6A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x56, 0x56, 0x4D, 0x78, 0x0A, 0x45, 0x7A, 0x41, ++ 0x52, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x73, 0x54, 0x43, 0x6D, 0x56, 0x74, 0x55, 0x32, 0x6C, 0x6E, 0x62, 0x69, 0x42, 0x51, 0x53, 0x30, 0x6B, 0x78, 0x46, 0x44, 0x41, 0x53, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x43, 0x32, 0x56, ++ 0x4E, 0x64, 0x57, 0x52, 0x6F, 0x63, 0x6D, 0x45, 0x67, 0x53, 0x57, 0x35, 0x6A, 0x4D, 0x52, 0x77, 0x77, 0x47, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x4E, 0x6C, 0x62, 0x56, 0x4E, 0x70, 0x0A, 0x5A, 0x32, 0x34, 0x67, 0x55, 0x6D, ++ 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x51, 0x53, 0x41, 0x74, 0x49, 0x45, 0x4D, 0x78, 0x4D, 0x42, 0x34, 0x58, 0x44, 0x54, 0x45, 0x34, 0x4D, 0x44, 0x49, 0x78, 0x4F, 0x44, 0x45, 0x34, 0x4D, 0x7A, 0x41, 0x77, 0x4D, 0x46, 0x6F, 0x58, 0x44, 0x54, ++ 0x51, 0x7A, 0x4D, 0x44, 0x49, 0x78, 0x4F, 0x44, 0x45, 0x34, 0x4D, 0x7A, 0x41, 0x77, 0x4D, 0x46, 0x6F, 0x77, 0x56, 0x6A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x0A, 0x42, 0x68, 0x4D, 0x43, 0x56, 0x56, 0x4D, 0x78, 0x45, ++ 0x7A, 0x41, 0x52, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x73, 0x54, 0x43, 0x6D, 0x56, 0x74, 0x55, 0x32, 0x6C, 0x6E, 0x62, 0x69, 0x42, 0x51, 0x53, 0x30, 0x6B, 0x78, 0x46, 0x44, 0x41, 0x53, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x43, ++ 0x32, 0x56, 0x4E, 0x64, 0x57, 0x52, 0x6F, 0x63, 0x6D, 0x45, 0x67, 0x53, 0x57, 0x35, 0x6A, 0x4D, 0x52, 0x77, 0x77, 0x47, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x0A, 0x45, 0x78, 0x4E, 0x6C, 0x62, 0x56, 0x4E, 0x70, 0x5A, 0x32, 0x34, 0x67, ++ 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x51, 0x53, 0x41, 0x74, 0x49, 0x45, 0x4D, 0x78, 0x4D, 0x49, 0x49, 0x42, 0x49, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x45, 0x46, ++ 0x41, 0x41, 0x4F, 0x43, 0x41, 0x51, 0x38, 0x41, 0x4D, 0x49, 0x49, 0x42, 0x43, 0x67, 0x4B, 0x43, 0x41, 0x51, 0x45, 0x41, 0x7A, 0x2B, 0x75, 0x70, 0x0A, 0x75, 0x66, 0x47, 0x5A, 0x42, 0x63, 0x7A, 0x59, 0x4B, 0x43, 0x46, 0x4B, 0x38, 0x33, 0x4D, ++ 0x30, 0x55, 0x59, 0x52, 0x57, 0x45, 0x50, 0x57, 0x67, 0x54, 0x79, 0x77, 0x53, 0x34, 0x2F, 0x6F, 0x54, 0x6D, 0x69, 0x66, 0x51, 0x7A, 0x2F, 0x6C, 0x35, 0x47, 0x6E, 0x52, 0x66, 0x48, 0x58, 0x6B, 0x35, 0x2F, 0x46, 0x76, 0x34, 0x63, 0x49, 0x37, ++ 0x67, 0x6B, 0x6C, 0x4C, 0x33, 0x35, 0x43, 0x58, 0x35, 0x56, 0x49, 0x50, 0x5A, 0x48, 0x64, 0x50, 0x49, 0x57, 0x6F, 0x55, 0x2F, 0x0A, 0x58, 0x73, 0x65, 0x32, 0x42, 0x2B, 0x34, 0x2B, 0x77, 0x4D, 0x36, 0x61, 0x72, 0x36, 0x78, 0x57, 0x51, 0x69, ++ 0x6F, 0x35, 0x4A, 0x58, 0x44, 0x57, 0x76, 0x37, 0x56, 0x37, 0x4E, 0x71, 0x32, 0x73, 0x39, 0x6E, 0x50, 0x63, 0x7A, 0x64, 0x63, 0x64, 0x69, 0x6F, 0x4F, 0x6C, 0x2B, 0x79, 0x75, 0x51, 0x46, 0x54, 0x64, 0x72, 0x48, 0x43, 0x5A, 0x48, 0x33, 0x44, ++ 0x73, 0x70, 0x56, 0x70, 0x4E, 0x71, 0x73, 0x38, 0x46, 0x71, 0x4F, 0x70, 0x30, 0x39, 0x39, 0x63, 0x47, 0x58, 0x0A, 0x4F, 0x46, 0x67, 0x46, 0x69, 0x78, 0x77, 0x52, 0x34, 0x2B, 0x53, 0x30, 0x75, 0x46, 0x32, 0x46, 0x48, 0x59, 0x50, 0x2B, 0x65, ++ 0x46, 0x38, 0x4C, 0x52, 0x57, 0x67, 0x59, 0x53, 0x4B, 0x56, 0x47, 0x63, 0x7A, 0x51, 0x37, 0x2F, 0x67, 0x2F, 0x49, 0x64, 0x72, 0x76, 0x48, 0x47, 0x50, 0x4D, 0x46, 0x30, 0x59, 0x62, 0x7A, 0x68, 0x65, 0x33, 0x6E, 0x75, 0x64, 0x6B, 0x79, 0x72, ++ 0x56, 0x57, 0x49, 0x7A, 0x71, 0x61, 0x32, 0x6B, 0x62, 0x42, 0x50, 0x72, 0x48, 0x34, 0x56, 0x0A, 0x49, 0x35, 0x62, 0x32, 0x50, 0x2F, 0x41, 0x67, 0x4E, 0x42, 0x62, 0x65, 0x43, 0x73, 0x62, 0x45, 0x42, 0x45, 0x56, 0x35, 0x66, 0x36, 0x66, 0x39, ++ 0x76, 0x74, 0x4B, 0x70, 0x70, 0x61, 0x2B, 0x63, 0x78, 0x53, 0x4D, 0x71, 0x39, 0x7A, 0x77, 0x68, 0x62, 0x4C, 0x32, 0x76, 0x6A, 0x30, 0x37, 0x46, 0x4F, 0x72, 0x4C, 0x7A, 0x4E, 0x42, 0x4C, 0x38, 0x33, 0x34, 0x41, 0x61, 0x53, 0x61, 0x54, 0x55, ++ 0x71, 0x5A, 0x58, 0x33, 0x6E, 0x6F, 0x6C, 0x65, 0x6F, 0x6F, 0x6D, 0x73, 0x0A, 0x6C, 0x4D, 0x75, 0x6F, 0x61, 0x4A, 0x75, 0x76, 0x69, 0x6D, 0x55, 0x6E, 0x7A, 0x59, 0x6E, 0x75, 0x33, 0x59, 0x79, 0x31, 0x61, 0x79, 0x6C, 0x77, 0x51, 0x36, 0x42, ++ 0x70, 0x43, 0x2B, 0x53, 0x35, 0x44, 0x77, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x6F, 0x30, 0x49, 0x77, 0x51, 0x44, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x2F, 0x71, 0x48, 0x67, 0x63, 0x42, 0x34, ++ 0x71, 0x41, 0x7A, 0x6C, 0x53, 0x57, 0x6B, 0x4B, 0x2B, 0x0A, 0x58, 0x4A, 0x47, 0x46, 0x65, 0x68, 0x69, 0x71, 0x54, 0x62, 0x55, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x51, 0x44, 0x41, 0x67, ++ 0x45, 0x47, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, ++ 0x45, 0x4C, 0x42, 0x51, 0x41, 0x44, 0x0A, 0x67, 0x67, 0x45, 0x42, 0x41, 0x4D, 0x4A, 0x4B, 0x56, 0x76, 0x6F, 0x56, 0x49, 0x58, 0x73, 0x6F, 0x6F, 0x75, 0x6E, 0x6C, 0x48, 0x66, 0x76, 0x34, 0x4C, 0x63, 0x51, 0x35, 0x6C, 0x6B, 0x46, 0x4D, 0x4F, ++ 0x79, 0x63, 0x73, 0x78, 0x47, 0x77, 0x59, 0x46, 0x59, 0x44, 0x47, 0x72, 0x4B, 0x39, 0x48, 0x57, 0x53, 0x38, 0x6D, 0x43, 0x2B, 0x4D, 0x32, 0x73, 0x4F, 0x38, 0x37, 0x2F, 0x6B, 0x4F, 0x58, 0x53, 0x54, 0x4B, 0x5A, 0x45, 0x68, 0x56, 0x62, 0x33, ++ 0x78, 0x45, 0x70, 0x0A, 0x2F, 0x36, 0x74, 0x54, 0x2B, 0x4C, 0x76, 0x42, 0x65, 0x41, 0x2B, 0x73, 0x6E, 0x46, 0x4F, 0x76, 0x56, 0x37, 0x31, 0x6F, 0x6A, 0x44, 0x31, 0x70, 0x4D, 0x2F, 0x43, 0x6A, 0x6F, 0x43, 0x4E, 0x6A, 0x4F, 0x32, 0x52, 0x6E, ++ 0x49, 0x6B, 0x53, 0x74, 0x31, 0x58, 0x48, 0x4C, 0x56, 0x69, 0x70, 0x34, 0x6B, 0x71, 0x4E, 0x50, 0x45, 0x6A, 0x45, 0x32, 0x4E, 0x75, 0x4C, 0x65, 0x2F, 0x67, 0x44, 0x45, 0x6F, 0x32, 0x41, 0x50, 0x4A, 0x36, 0x32, 0x67, 0x73, 0x49, 0x71, 0x31, ++ 0x0A, 0x4E, 0x6E, 0x70, 0x53, 0x6F, 0x62, 0x30, 0x6E, 0x39, 0x43, 0x41, 0x6E, 0x59, 0x75, 0x68, 0x4E, 0x6C, 0x43, 0x51, 0x54, 0x35, 0x41, 0x6F, 0x45, 0x36, 0x54, 0x79, 0x72, 0x4C, 0x73, 0x68, 0x44, 0x43, 0x55, 0x72, 0x47, 0x59, 0x51, 0x54, ++ 0x6C, 0x53, 0x54, 0x52, 0x2B, 0x30, 0x38, 0x54, 0x49, 0x39, 0x51, 0x2F, 0x41, 0x71, 0x75, 0x6D, 0x36, 0x56, 0x46, 0x37, 0x7A, 0x59, 0x79, 0x74, 0x50, 0x54, 0x31, 0x44, 0x55, 0x2F, 0x72, 0x6C, 0x37, 0x6D, 0x59, 0x77, 0x39, 0x0A, 0x77, 0x43, ++ 0x36, 0x38, 0x41, 0x69, 0x76, 0x54, 0x78, 0x45, 0x44, 0x6B, 0x69, 0x67, 0x63, 0x78, 0x48, 0x70, 0x76, 0x4F, 0x4A, 0x70, 0x6B, 0x54, 0x2B, 0x78, 0x48, 0x71, 0x6D, 0x69, 0x49, 0x4D, 0x45, 0x52, 0x6E, 0x48, 0x58, 0x68, 0x75, 0x42, 0x55, 0x44, ++ 0x44, 0x49, 0x6C, 0x68, 0x4A, 0x75, 0x35, 0x38, 0x74, 0x42, 0x66, 0x35, 0x45, 0x37, 0x6F, 0x6B, 0x65, 0x33, 0x56, 0x49, 0x41, 0x62, 0x33, 0x41, 0x44, 0x4D, 0x6D, 0x70, 0x44, 0x71, 0x77, 0x38, 0x4E, 0x51, 0x0A, 0x42, 0x6D, 0x49, 0x4D, 0x4D, ++ 0x4D, 0x41, 0x56, 0x53, 0x4B, 0x65, 0x6F, 0x57, 0x58, 0x7A, 0x68, 0x72, 0x69, 0x4B, 0x69, 0x34, 0x67, 0x70, 0x36, 0x44, 0x2F, 0x70, 0x69, 0x71, 0x31, 0x4A, 0x4D, 0x34, 0x66, 0x48, 0x66, 0x79, 0x72, 0x36, 0x44, 0x44, 0x55, 0x49, 0x3D, 0x0A, ++ 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, ++ 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x43, 0x33, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, ++ 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x43, 0x4B, 0x7A, 0x43, 0x43, 0x41, 0x62, 0x47, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, ++ 0x67, 0x49, 0x4B, 0x65, 0x33, 0x47, 0x32, 0x67, 0x6C, 0x61, 0x34, 0x45, 0x6E, 0x79, 0x63, 0x71, 0x44, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x7A, 0x42, 0x61, 0x4D, 0x51, 0x73, 0x77, 0x43, ++ 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x56, 0x55, 0x7A, 0x45, 0x54, 0x4D, 0x42, 0x45, 0x47, 0x0A, 0x41, 0x31, 0x55, 0x45, 0x43, 0x78, 0x4D, 0x4B, 0x5A, 0x57, 0x31, 0x54, 0x61, 0x57, 0x64, 0x75, 0x49, 0x46, 0x42, 0x4C, ++ 0x53, 0x54, 0x45, 0x55, 0x4D, 0x42, 0x49, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x4C, 0x5A, 0x55, 0x31, 0x31, 0x5A, 0x47, 0x68, 0x79, 0x59, 0x53, 0x42, 0x4A, 0x62, 0x6D, 0x4D, 0x78, 0x49, 0x44, 0x41, 0x65, 0x42, 0x67, 0x4E, 0x56, ++ 0x42, 0x41, 0x4D, 0x54, 0x46, 0x32, 0x56, 0x74, 0x55, 0x32, 0x6C, 0x6E, 0x62, 0x69, 0x42, 0x46, 0x0A, 0x51, 0x30, 0x4D, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x51, 0x53, 0x41, 0x74, 0x49, 0x45, 0x4D, 0x7A, 0x4D, 0x42, 0x34, ++ 0x58, 0x44, 0x54, 0x45, 0x34, 0x4D, 0x44, 0x49, 0x78, 0x4F, 0x44, 0x45, 0x34, 0x4D, 0x7A, 0x41, 0x77, 0x4D, 0x46, 0x6F, 0x58, 0x44, 0x54, 0x51, 0x7A, 0x4D, 0x44, 0x49, 0x78, 0x4F, 0x44, 0x45, 0x34, 0x4D, 0x7A, 0x41, 0x77, 0x4D, 0x46, 0x6F, ++ 0x77, 0x57, 0x6A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x0A, 0x42, 0x68, 0x4D, 0x43, 0x56, 0x56, 0x4D, 0x78, 0x45, 0x7A, 0x41, 0x52, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x73, 0x54, 0x43, 0x6D, 0x56, 0x74, 0x55, 0x32, ++ 0x6C, 0x6E, 0x62, 0x69, 0x42, 0x51, 0x53, 0x30, 0x6B, 0x78, 0x46, 0x44, 0x41, 0x53, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x43, 0x32, 0x56, 0x4E, 0x64, 0x57, 0x52, 0x6F, 0x63, 0x6D, 0x45, 0x67, 0x53, 0x57, 0x35, 0x6A, 0x4D, 0x53, ++ 0x41, 0x77, 0x48, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x0A, 0x45, 0x78, 0x64, 0x6C, 0x62, 0x56, 0x4E, 0x70, 0x5A, 0x32, 0x34, 0x67, 0x52, 0x55, 0x4E, 0x44, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x67, 0x4C, ++ 0x53, 0x42, 0x44, 0x4D, 0x7A, 0x42, 0x32, 0x4D, 0x42, 0x41, 0x47, 0x42, 0x79, 0x71, 0x47, 0x53, 0x4D, 0x34, 0x39, 0x41, 0x67, 0x45, 0x47, 0x42, 0x53, 0x75, 0x42, 0x42, 0x41, 0x41, 0x69, 0x41, 0x32, 0x49, 0x41, 0x42, 0x50, 0x32, 0x6C, 0x59, ++ 0x61, 0x35, 0x37, 0x4A, 0x68, 0x41, 0x64, 0x0A, 0x36, 0x62, 0x63, 0x69, 0x4D, 0x4B, 0x34, 0x47, 0x39, 0x49, 0x47, 0x7A, 0x73, 0x55, 0x4A, 0x78, 0x6C, 0x54, 0x6D, 0x38, 0x30, 0x31, 0x4C, 0x6A, 0x72, 0x36, 0x2F, 0x35, 0x38, 0x70, 0x63, 0x31, ++ 0x6B, 0x6A, 0x5A, 0x47, 0x44, 0x6F, 0x65, 0x56, 0x6A, 0x62, 0x6B, 0x35, 0x57, 0x75, 0x6D, 0x37, 0x33, 0x39, 0x44, 0x2B, 0x79, 0x41, 0x64, 0x42, 0x50, 0x4C, 0x74, 0x56, 0x62, 0x34, 0x4F, 0x6A, 0x61, 0x76, 0x74, 0x69, 0x73, 0x49, 0x47, 0x4A, ++ 0x41, 0x6E, 0x42, 0x39, 0x0A, 0x53, 0x4D, 0x56, 0x4B, 0x34, 0x2B, 0x6B, 0x69, 0x56, 0x43, 0x4A, 0x4E, 0x6B, 0x37, 0x74, 0x43, 0x44, 0x4B, 0x39, 0x33, 0x6E, 0x43, 0x4F, 0x6D, 0x66, 0x64, 0x64, 0x68, 0x45, 0x63, 0x35, 0x6C, 0x78, 0x2F, 0x68, ++ 0x2F, 0x2F, 0x76, 0x58, 0x79, 0x71, 0x61, 0x4E, 0x43, 0x4D, 0x45, 0x41, 0x77, 0x48, 0x51, 0x59, 0x44, 0x56, 0x52, 0x30, 0x4F, 0x42, 0x42, 0x59, 0x45, 0x46, 0x50, 0x74, 0x61, 0x53, 0x4E, 0x43, 0x41, 0x49, 0x45, 0x44, 0x79, 0x71, 0x4F, 0x6B, ++ 0x41, 0x0A, 0x42, 0x32, 0x6B, 0x5A, 0x64, 0x36, 0x66, 0x6D, 0x77, 0x2F, 0x54, 0x50, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x42, 0x42, 0x6A, 0x41, 0x50, 0x42, 0x67, ++ 0x4E, 0x56, 0x48, 0x52, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x54, 0x41, 0x44, 0x41, 0x51, 0x48, 0x2F, 0x4D, 0x41, 0x6F, 0x47, 0x43, 0x43, 0x71, 0x47, 0x53, 0x4D, 0x34, 0x39, 0x42, 0x41, 0x4D, 0x44, 0x41, 0x32, 0x67, 0x41, 0x0A, 0x4D, ++ 0x47, 0x55, 0x43, 0x4D, 0x51, 0x43, 0x30, 0x32, 0x43, 0x38, 0x43, 0x69, 0x66, 0x32, 0x32, 0x54, 0x47, 0x4B, 0x36, 0x51, 0x30, 0x34, 0x54, 0x68, 0x48, 0x4B, 0x31, 0x72, 0x74, 0x30, 0x63, 0x33, 0x74, 0x61, 0x31, 0x33, 0x46, 0x61, 0x50, 0x57, ++ 0x45, 0x42, 0x61, 0x4C, 0x64, 0x34, 0x67, 0x54, 0x43, 0x4B, 0x44, 0x79, 0x70, 0x4F, 0x6F, 0x66, 0x75, 0x34, 0x53, 0x51, 0x4D, 0x66, 0x57, 0x68, 0x30, 0x2F, 0x34, 0x33, 0x34, 0x55, 0x43, 0x4D, 0x42, 0x77, 0x55, 0x0A, 0x5A, 0x4F, 0x52, 0x38, ++ 0x6C, 0x6F, 0x4D, 0x52, 0x6E, 0x4C, 0x44, 0x52, 0x57, 0x6D, 0x46, 0x4C, 0x70, 0x67, 0x39, 0x4A, 0x30, 0x77, 0x44, 0x38, 0x6F, 0x66, 0x7A, 0x6B, 0x70, 0x66, 0x39, 0x2F, 0x72, 0x64, 0x63, 0x77, 0x30, 0x4D, 0x64, 0x33, 0x66, 0x37, 0x36, 0x42, ++ 0x42, 0x31, 0x55, 0x77, 0x55, 0x43, 0x41, 0x55, 0x39, 0x56, 0x63, 0x34, 0x43, 0x71, 0x67, 0x78, 0x55, 0x51, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, ++ 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x48, 0x6F, 0x6E, 0x67, 0x6B, 0x6F, 0x6E, 0x67, 0x20, 0x50, 0x6F, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, ++ 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x7A, 0x7A, 0x43, 0x43, 0x41, 0x37, 0x65, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x55, 0x43, 0x42, 0x5A, 0x66, 0x69, 0x6B, 0x79, 0x6C, 0x37, 0x41, 0x44, 0x4A, 0x6B, 0x30, 0x44, 0x66, ++ 0x78, 0x4D, 0x61, 0x75, 0x49, 0x37, 0x67, 0x63, 0x57, 0x71, 0x51, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x42, 0x51, 0x41, 0x77, 0x62, 0x7A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, ++ 0x0A, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x53, 0x45, 0x73, 0x78, 0x45, 0x6A, 0x41, 0x51, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x67, 0x54, 0x43, 0x55, 0x68, 0x76, 0x62, 0x6D, 0x63, 0x67, 0x53, 0x32, 0x39, 0x75, 0x5A, 0x7A, 0x45, ++ 0x53, 0x4D, 0x42, 0x41, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x78, 0x4D, 0x4A, 0x53, 0x47, 0x39, 0x75, 0x5A, 0x79, 0x42, 0x4C, 0x62, 0x32, 0x35, 0x6E, 0x4D, 0x52, 0x59, 0x77, 0x46, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x0A, 0x45, 0x77, ++ 0x31, 0x49, 0x62, 0x32, 0x35, 0x6E, 0x61, 0x32, 0x39, 0x75, 0x5A, 0x79, 0x42, 0x51, 0x62, 0x33, 0x4E, 0x30, 0x4D, 0x53, 0x41, 0x77, 0x48, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x64, 0x49, 0x62, 0x32, 0x35, 0x6E, 0x61, 0x32, ++ 0x39, 0x75, 0x5A, 0x79, 0x42, 0x51, 0x62, 0x33, 0x4E, 0x30, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x67, 0x4D, 0x7A, 0x41, 0x65, 0x46, 0x77, 0x30, 0x78, 0x4E, 0x7A, 0x41, 0x32, 0x0A, 0x4D, 0x44, 0x4D, 0x77, 0x4D, ++ 0x6A, 0x49, 0x35, 0x4E, 0x44, 0x5A, 0x61, 0x46, 0x77, 0x30, 0x30, 0x4D, 0x6A, 0x41, 0x32, 0x4D, 0x44, 0x4D, 0x77, 0x4D, 0x6A, 0x49, 0x35, 0x4E, 0x44, 0x5A, 0x61, 0x4D, 0x47, 0x38, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, ++ 0x41, 0x59, 0x54, 0x41, 0x6B, 0x68, 0x4C, 0x4D, 0x52, 0x49, 0x77, 0x45, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x49, 0x45, 0x77, 0x6C, 0x49, 0x62, 0x32, 0x35, 0x6E, 0x49, 0x45, 0x74, 0x76, 0x0A, 0x62, 0x6D, 0x63, 0x78, 0x45, 0x6A, 0x41, 0x51, ++ 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x63, 0x54, 0x43, 0x55, 0x68, 0x76, 0x62, 0x6D, 0x63, 0x67, 0x53, 0x32, 0x39, 0x75, 0x5A, 0x7A, 0x45, 0x57, 0x4D, 0x42, 0x51, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x4E, 0x53, 0x47, 0x39, 0x75, ++ 0x5A, 0x32, 0x74, 0x76, 0x62, 0x6D, 0x63, 0x67, 0x55, 0x47, 0x39, 0x7A, 0x64, 0x44, 0x45, 0x67, 0x4D, 0x42, 0x34, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x58, 0x0A, 0x53, 0x47, 0x39, 0x75, 0x5A, 0x32, 0x74, 0x76, 0x62, 0x6D, 0x63, ++ 0x67, 0x55, 0x47, 0x39, 0x7A, 0x64, 0x43, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x42, 0x49, 0x44, 0x4D, 0x77, 0x67, 0x67, 0x49, 0x69, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, ++ 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x49, 0x4B, 0x41, 0x6F, 0x49, 0x43, 0x41, 0x51, 0x43, 0x7A, 0x0A, 0x69, 0x4E, 0x66, 0x71, 0x7A, 0x67, 0x38, 0x67, 0x54, 0x72, 0x37, 0x6D, 0x31, 0x67, ++ 0x4E, 0x74, 0x37, 0x6C, 0x6E, 0x38, 0x77, 0x6C, 0x66, 0x66, 0x4B, 0x57, 0x69, 0x68, 0x67, 0x77, 0x34, 0x2B, 0x61, 0x4D, 0x64, 0x6F, 0x57, 0x4A, 0x77, 0x63, 0x59, 0x45, 0x75, 0x4A, 0x51, 0x77, 0x79, 0x35, 0x31, 0x42, 0x57, 0x79, 0x37, 0x73, ++ 0x46, 0x4F, 0x64, 0x65, 0x6D, 0x31, 0x70, 0x2B, 0x2F, 0x6C, 0x36, 0x54, 0x57, 0x5A, 0x35, 0x4D, 0x77, 0x63, 0x35, 0x30, 0x74, 0x66, 0x0A, 0x6A, 0x54, 0x4D, 0x77, 0x49, 0x44, 0x4E, 0x54, 0x32, 0x61, 0x61, 0x37, 0x31, 0x54, 0x34, 0x54, 0x6A, ++ 0x75, 0x6B, 0x66, 0x68, 0x30, 0x6D, 0x74, 0x55, 0x43, 0x31, 0x51, 0x79, 0x68, 0x69, 0x2B, 0x41, 0x56, 0x69, 0x69, 0x45, 0x33, 0x43, 0x57, 0x75, 0x34, 0x6D, 0x49, 0x56, 0x6F, 0x42, 0x63, 0x2B, 0x4C, 0x30, 0x73, 0x50, 0x4F, 0x46, 0x4D, 0x56, ++ 0x34, 0x69, 0x37, 0x30, 0x37, 0x6D, 0x56, 0x37, 0x38, 0x76, 0x48, 0x39, 0x74, 0x6F, 0x78, 0x64, 0x43, 0x69, 0x6D, 0x0A, 0x35, 0x6C, 0x53, 0x4A, 0x39, 0x55, 0x45, 0x78, 0x79, 0x75, 0x55, 0x6D, 0x47, 0x73, 0x32, 0x43, 0x34, 0x48, 0x44, 0x61, ++ 0x4F, 0x79, 0x6D, 0x37, 0x31, 0x51, 0x50, 0x31, 0x6D, 0x62, 0x70, 0x56, 0x39, 0x57, 0x54, 0x52, 0x59, 0x41, 0x36, 0x7A, 0x69, 0x55, 0x6D, 0x34, 0x69, 0x69, 0x38, 0x46, 0x30, 0x6F, 0x52, 0x46, 0x4B, 0x48, 0x79, 0x50, 0x61, 0x46, 0x41, 0x53, ++ 0x65, 0x50, 0x77, 0x4C, 0x74, 0x56, 0x50, 0x4C, 0x77, 0x70, 0x67, 0x63, 0x68, 0x4B, 0x4F, 0x65, 0x0A, 0x73, 0x4C, 0x34, 0x6A, 0x70, 0x4E, 0x72, 0x63, 0x79, 0x43, 0x73, 0x65, 0x32, 0x6D, 0x35, 0x46, 0x48, 0x6F, 0x6D, 0x59, 0x32, 0x76, 0x6B, ++ 0x41, 0x4C, 0x67, 0x62, 0x70, 0x44, 0x44, 0x74, 0x77, 0x31, 0x56, 0x41, 0x6C, 0x69, 0x4A, 0x6E, 0x4C, 0x7A, 0x58, 0x4E, 0x67, 0x39, 0x39, 0x58, 0x2F, 0x4E, 0x57, 0x66, 0x46, 0x6F, 0x62, 0x78, 0x65, 0x71, 0x38, 0x31, 0x4B, 0x75, 0x45, 0x58, ++ 0x72, 0x79, 0x47, 0x67, 0x65, 0x44, 0x51, 0x30, 0x55, 0x52, 0x68, 0x4C, 0x6A, 0x0A, 0x30, 0x6D, 0x52, 0x69, 0x69, 0x6B, 0x4B, 0x59, 0x76, 0x4C, 0x54, 0x47, 0x43, 0x41, 0x6A, 0x34, 0x2F, 0x61, 0x68, 0x4D, 0x5A, 0x4A, 0x78, 0x32, 0x41, 0x62, ++ 0x30, 0x76, 0x71, 0x57, 0x77, 0x7A, 0x44, 0x39, 0x67, 0x2F, 0x4B, 0x4C, 0x67, 0x38, 0x61, 0x51, 0x46, 0x43, 0x68, 0x6E, 0x35, 0x70, 0x77, 0x63, 0x6B, 0x47, 0x79, 0x75, 0x56, 0x36, 0x52, 0x6D, 0x58, 0x70, 0x77, 0x74, 0x5A, 0x51, 0x51, 0x53, ++ 0x34, 0x2F, 0x74, 0x2B, 0x54, 0x74, 0x62, 0x4E, 0x65, 0x2F, 0x0A, 0x4A, 0x67, 0x45, 0x52, 0x6F, 0x68, 0x59, 0x70, 0x53, 0x6D, 0x73, 0x30, 0x42, 0x70, 0x44, 0x73, 0x45, 0x39, 0x4B, 0x32, 0x2B, 0x32, 0x70, 0x32, 0x30, 0x6A, 0x7A, 0x74, 0x38, ++ 0x4E, 0x59, 0x74, 0x33, 0x65, 0x45, 0x56, 0x37, 0x4B, 0x4F, 0x62, 0x4C, 0x79, 0x7A, 0x4A, 0x50, 0x69, 0x76, 0x6B, 0x61, 0x54, 0x76, 0x2F, 0x63, 0x69, 0x57, 0x78, 0x4E, 0x6F, 0x5A, 0x62, 0x78, 0x33, 0x39, 0x72, 0x69, 0x31, 0x55, 0x62, 0x53, ++ 0x73, 0x55, 0x67, 0x59, 0x54, 0x32, 0x75, 0x0A, 0x79, 0x31, 0x44, 0x68, 0x43, 0x44, 0x71, 0x2B, 0x73, 0x49, 0x39, 0x6A, 0x51, 0x56, 0x4D, 0x77, 0x43, 0x46, 0x6B, 0x38, 0x6D, 0x42, 0x31, 0x33, 0x75, 0x6D, 0x4F, 0x52, 0x65, 0x73, 0x6F, 0x51, ++ 0x55, 0x47, 0x43, 0x2F, 0x38, 0x4E, 0x65, 0x38, 0x6C, 0x59, 0x65, 0x50, 0x6C, 0x38, 0x58, 0x2B, 0x6C, 0x32, 0x6F, 0x42, 0x6C, 0x4B, 0x4E, 0x38, 0x57, 0x34, 0x55, 0x64, 0x4B, 0x6A, 0x6B, 0x36, 0x30, 0x46, 0x53, 0x68, 0x30, 0x54, 0x6C, 0x78, ++ 0x6E, 0x66, 0x30, 0x68, 0x0A, 0x2B, 0x62, 0x56, 0x37, 0x38, 0x4F, 0x4C, 0x67, 0x41, 0x6F, 0x39, 0x75, 0x6C, 0x69, 0x51, 0x6C, 0x4C, 0x4B, 0x41, 0x65, 0x4C, 0x4B, 0x6A, 0x45, 0x69, 0x61, 0x66, 0x76, 0x37, 0x5A, 0x6B, 0x47, 0x4C, 0x37, 0x59, ++ 0x4B, 0x54, 0x45, 0x2F, 0x62, 0x6F, 0x73, 0x77, 0x33, 0x47, 0x71, 0x39, 0x48, 0x68, 0x53, 0x32, 0x4B, 0x58, 0x38, 0x51, 0x30, 0x4E, 0x45, 0x77, 0x41, 0x2F, 0x52, 0x69, 0x54, 0x5A, 0x78, 0x50, 0x52, 0x4E, 0x2B, 0x5A, 0x49, 0x74, 0x49, 0x73, ++ 0x47, 0x0A, 0x78, 0x56, 0x64, 0x37, 0x47, 0x59, 0x59, 0x4B, 0x65, 0x63, 0x73, 0x41, 0x79, 0x56, 0x4B, 0x76, 0x51, 0x76, 0x38, 0x33, 0x6A, 0x2B, 0x47, 0x6A, 0x48, 0x6E, 0x6F, 0x39, 0x55, 0x4B, 0x74, 0x6A, 0x42, 0x75, 0x63, 0x56, 0x74, 0x54, ++ 0x2B, 0x32, 0x52, 0x54, 0x65, 0x55, 0x4E, 0x37, 0x46, 0x2B, 0x38, 0x6B, 0x6A, 0x44, 0x66, 0x38, 0x56, 0x31, 0x2F, 0x70, 0x65, 0x4E, 0x52, 0x59, 0x38, 0x61, 0x70, 0x78, 0x70, 0x79, 0x4B, 0x42, 0x70, 0x41, 0x44, 0x77, 0x49, 0x44, 0x0A, 0x41, ++ 0x51, 0x41, 0x42, 0x6F, 0x32, 0x4D, 0x77, 0x59, 0x54, 0x41, 0x50, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x52, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x54, 0x41, 0x44, 0x41, 0x51, 0x48, 0x2F, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, ++ 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x42, 0x42, 0x6A, 0x41, 0x66, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x53, 0x4D, 0x45, 0x47, 0x44, 0x41, 0x57, 0x67, 0x42, 0x51, 0x58, 0x6E, 0x63, 0x30, 0x65, 0x0A, 0x69, 0x39, 0x59, 0x35, ++ 0x4B, 0x33, 0x44, 0x54, 0x58, 0x4E, 0x53, 0x67, 0x75, 0x42, 0x2B, 0x77, 0x41, 0x50, 0x7A, 0x46, 0x59, 0x54, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x46, 0x35, 0x33, 0x4E, 0x48, 0x6F, 0x76, 0x57, ++ 0x4F, 0x53, 0x74, 0x77, 0x30, 0x31, 0x7A, 0x55, 0x6F, 0x4C, 0x67, 0x66, 0x73, 0x41, 0x44, 0x38, 0x78, 0x57, 0x45, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x0A, 0x41, 0x51, 0x45, 0x4C, 0x42, 0x51, 0x41, ++ 0x44, 0x67, 0x67, 0x49, 0x42, 0x41, 0x46, 0x62, 0x56, 0x65, 0x32, 0x37, 0x6D, 0x49, 0x67, 0x48, 0x53, 0x51, 0x70, 0x73, 0x59, 0x31, 0x51, 0x37, 0x58, 0x5A, 0x69, 0x4E, 0x63, 0x34, 0x2F, 0x36, 0x67, 0x78, 0x35, 0x4C, 0x53, 0x36, 0x5A, 0x53, ++ 0x74, 0x53, 0x36, 0x4C, 0x47, 0x37, 0x42, 0x4A, 0x38, 0x64, 0x4E, 0x56, 0x49, 0x30, 0x6C, 0x6B, 0x55, 0x6D, 0x63, 0x44, 0x72, 0x75, 0x64, 0x48, 0x72, 0x39, 0x45, 0x67, 0x77, 0x0A, 0x57, 0x36, 0x32, 0x6E, 0x56, 0x33, 0x4F, 0x5A, 0x71, 0x64, ++ 0x50, 0x6C, 0x74, 0x39, 0x45, 0x75, 0x57, 0x53, 0x52, 0x59, 0x33, 0x47, 0x67, 0x75, 0x4C, 0x6D, 0x4C, 0x59, 0x61, 0x75, 0x52, 0x77, 0x43, 0x79, 0x30, 0x67, 0x55, 0x43, 0x43, 0x6B, 0x4D, 0x70, 0x58, 0x52, 0x41, 0x4A, 0x69, 0x37, 0x30, 0x2F, ++ 0x33, 0x33, 0x4D, 0x76, 0x4A, 0x4A, 0x72, 0x73, 0x5A, 0x36, 0x34, 0x45, 0x65, 0x2B, 0x62, 0x73, 0x37, 0x4C, 0x6F, 0x33, 0x49, 0x36, 0x4C, 0x57, 0x6C, 0x64, 0x0A, 0x79, 0x38, 0x6A, 0x6F, 0x52, 0x54, 0x6E, 0x55, 0x2B, 0x6B, 0x4C, 0x42, 0x45, ++ 0x55, 0x78, 0x33, 0x58, 0x5A, 0x4C, 0x37, 0x61, 0x76, 0x39, 0x59, 0x52, 0x4F, 0x58, 0x72, 0x67, 0x5A, 0x36, 0x76, 0x6F, 0x4A, 0x6D, 0x74, 0x76, 0x71, 0x6B, 0x42, 0x5A, 0x73, 0x73, 0x34, 0x48, 0x54, 0x7A, 0x66, 0x51, 0x78, 0x2F, 0x30, 0x54, ++ 0x57, 0x36, 0x30, 0x75, 0x68, 0x64, 0x47, 0x2F, 0x48, 0x33, 0x39, 0x68, 0x34, 0x46, 0x35, 0x61, 0x67, 0x30, 0x7A, 0x44, 0x2F, 0x6F, 0x76, 0x0A, 0x2B, 0x42, 0x53, 0x35, 0x67, 0x4C, 0x4E, 0x64, 0x54, 0x61, 0x71, 0x58, 0x34, 0x66, 0x6E, 0x6B, ++ 0x47, 0x4D, 0x58, 0x34, 0x31, 0x54, 0x69, 0x4D, 0x4A, 0x6A, 0x7A, 0x39, 0x38, 0x69, 0x6A, 0x69, 0x37, 0x6C, 0x70, 0x4A, 0x69, 0x43, 0x7A, 0x66, 0x65, 0x54, 0x32, 0x4F, 0x6E, 0x70, 0x41, 0x38, 0x76, 0x55, 0x46, 0x4B, 0x4F, 0x74, 0x31, 0x62, ++ 0x39, 0x70, 0x71, 0x30, 0x7A, 0x6A, 0x38, 0x6C, 0x4D, 0x48, 0x38, 0x79, 0x66, 0x61, 0x49, 0x44, 0x6C, 0x4E, 0x44, 0x63, 0x0A, 0x65, 0x71, 0x46, 0x53, 0x33, 0x6D, 0x36, 0x54, 0x6A, 0x52, 0x67, 0x6D, 0x2F, 0x56, 0x57, 0x73, 0x76, 0x59, 0x2B, ++ 0x62, 0x30, 0x73, 0x2B, 0x76, 0x35, 0x34, 0x59, 0x73, 0x79, 0x78, 0x38, 0x4A, 0x62, 0x36, 0x4E, 0x76, 0x71, 0x59, 0x54, 0x55, 0x63, 0x37, 0x39, 0x4E, 0x6F, 0x58, 0x51, 0x62, 0x54, 0x69, 0x4E, 0x67, 0x38, 0x73, 0x77, 0x4F, 0x71, 0x6E, 0x2B, ++ 0x6B, 0x6E, 0x45, 0x77, 0x6C, 0x71, 0x4C, 0x4A, 0x6D, 0x4F, 0x7A, 0x6A, 0x2F, 0x32, 0x5A, 0x51, 0x77, 0x0A, 0x39, 0x6E, 0x4B, 0x45, 0x76, 0x6D, 0x68, 0x56, 0x45, 0x41, 0x2F, 0x47, 0x63, 0x79, 0x77, 0x57, 0x61, 0x5A, 0x4D, 0x48, 0x2F, 0x72, ++ 0x46, 0x46, 0x37, 0x62, 0x75, 0x69, 0x56, 0x57, 0x71, 0x77, 0x32, 0x72, 0x56, 0x4B, 0x41, 0x69, 0x55, 0x6E, 0x68, 0x64, 0x65, 0x33, 0x74, 0x34, 0x5A, 0x45, 0x46, 0x6F, 0x6C, 0x73, 0x67, 0x43, 0x73, 0x2B, 0x6C, 0x36, 0x6D, 0x63, 0x31, 0x58, ++ 0x35, 0x56, 0x54, 0x4D, 0x62, 0x65, 0x52, 0x52, 0x41, 0x63, 0x36, 0x75, 0x6B, 0x37, 0x0A, 0x6E, 0x77, 0x4E, 0x54, 0x37, 0x75, 0x35, 0x36, 0x41, 0x51, 0x49, 0x57, 0x65, 0x4E, 0x54, 0x6F, 0x77, 0x72, 0x35, 0x47, 0x64, 0x6F, 0x67, 0x54, 0x50, ++ 0x79, 0x4B, 0x37, 0x53, 0x42, 0x49, 0x64, 0x55, 0x67, 0x43, 0x30, 0x41, 0x6E, 0x34, 0x68, 0x47, 0x68, 0x36, 0x63, 0x4A, 0x66, 0x54, 0x7A, 0x50, 0x56, 0x34, 0x65, 0x30, 0x68, 0x7A, 0x35, 0x73, 0x79, 0x32, 0x32, 0x39, 0x7A, 0x64, 0x63, 0x78, ++ 0x73, 0x73, 0x68, 0x54, 0x72, 0x44, 0x33, 0x6D, 0x55, 0x63, 0x59, 0x0A, 0x68, 0x63, 0x45, 0x72, 0x75, 0x6C, 0x57, 0x75, 0x42, 0x75, 0x72, 0x51, 0x42, 0x37, 0x4C, 0x63, 0x71, 0x39, 0x43, 0x43, 0x6C, 0x6E, 0x58, 0x4F, 0x30, 0x6C, 0x44, 0x2B, ++ 0x6D, 0x65, 0x66, 0x50, 0x4C, 0x35, 0x2F, 0x6E, 0x64, 0x74, 0x46, 0x68, 0x4B, 0x76, 0x73, 0x68, 0x75, 0x7A, 0x48, 0x51, 0x71, 0x70, 0x39, 0x48, 0x70, 0x4C, 0x49, 0x69, 0x79, 0x68, 0x59, 0x36, 0x55, 0x46, 0x66, 0x45, 0x57, 0x30, 0x4E, 0x6E, ++ 0x78, 0x57, 0x56, 0x69, 0x41, 0x30, 0x6B, 0x42, 0x0A, 0x36, 0x30, 0x50, 0x5A, 0x32, 0x50, 0x69, 0x65, 0x72, 0x63, 0x2B, 0x78, 0x59, 0x77, 0x35, 0x46, 0x39, 0x4B, 0x42, 0x61, 0x4C, 0x4A, 0x73, 0x74, 0x78, 0x61, 0x62, 0x41, 0x72, 0x61, 0x68, ++ 0x48, 0x39, 0x43, 0x64, 0x4D, 0x4F, 0x41, 0x30, 0x75, 0x47, 0x30, 0x6B, 0x37, 0x55, 0x76, 0x54, 0x6F, 0x69, 0x49, 0x4D, 0x72, 0x56, 0x43, 0x6A, 0x55, 0x38, 0x6A, 0x56, 0x53, 0x74, 0x44, 0x4B, 0x44, 0x59, 0x6D, 0x6C, 0x6B, 0x44, 0x4A, 0x47, ++ 0x63, 0x6E, 0x35, 0x66, 0x71, 0x0A, 0x64, 0x42, 0x62, 0x39, 0x48, 0x78, 0x45, 0x47, 0x6D, 0x70, 0x76, 0x30, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, ++ 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, ++ 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x32, 0x30, 0x31, 0x37, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, ++ 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x43, 0x57, 0x54, 0x43, 0x43, 0x41, 0x64, 0x2B, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x5A, 0x76, 0x49, 0x39, 0x72, 0x34, 0x66, 0x65, 0x69, 0x37, 0x46, 0x4B, 0x36, 0x67, ++ 0x78, 0x58, 0x4D, 0x51, 0x48, 0x43, 0x37, 0x44, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x7A, 0x42, 0x6C, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, ++ 0x4A, 0x56, 0x0A, 0x55, 0x7A, 0x45, 0x65, 0x4D, 0x42, 0x77, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x56, 0x54, 0x57, 0x6C, 0x6A, 0x63, 0x6D, 0x39, 0x7A, 0x62, 0x32, 0x5A, 0x30, 0x49, 0x45, 0x4E, 0x76, 0x63, 0x6E, 0x42, 0x76, 0x63, ++ 0x6D, 0x46, 0x30, 0x61, 0x57, 0x39, 0x75, 0x4D, 0x54, 0x59, 0x77, 0x4E, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x79, 0x31, 0x4E, 0x61, 0x57, 0x4E, 0x79, 0x62, 0x33, 0x4E, 0x76, 0x5A, 0x6E, 0x51, 0x67, 0x52, 0x55, 0x4E, 0x44, 0x0A, ++ 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x32, 0x56, 0x79, 0x64, 0x47, 0x6C, 0x6D, 0x61, 0x57, 0x4E, 0x68, 0x64, 0x47, 0x55, 0x67, 0x51, 0x58, 0x56, 0x30, 0x61, 0x47, 0x39, 0x79, 0x61, 0x58, 0x52, 0x35, 0x49, 0x44, 0x49, 0x77, ++ 0x4D, 0x54, 0x63, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x54, 0x6B, 0x78, 0x4D, 0x6A, 0x45, 0x34, 0x4D, 0x6A, 0x4D, 0x77, 0x4E, 0x6A, 0x51, 0x31, 0x57, 0x68, 0x63, 0x4E, 0x4E, 0x44, 0x49, 0x77, 0x4E, 0x7A, 0x45, 0x34, 0x0A, 0x4D, 0x6A, 0x4D, ++ 0x78, 0x4E, 0x6A, 0x41, 0x30, 0x57, 0x6A, 0x42, 0x6C, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x56, 0x55, 0x7A, 0x45, 0x65, 0x4D, 0x42, 0x77, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, ++ 0x56, 0x54, 0x57, 0x6C, 0x6A, 0x63, 0x6D, 0x39, 0x7A, 0x62, 0x32, 0x5A, 0x30, 0x49, 0x45, 0x4E, 0x76, 0x63, 0x6E, 0x42, 0x76, 0x63, 0x6D, 0x46, 0x30, 0x61, 0x57, 0x39, 0x75, 0x4D, 0x54, 0x59, 0x77, 0x0A, 0x4E, 0x41, 0x59, 0x44, 0x56, 0x51, ++ 0x51, 0x44, 0x45, 0x79, 0x31, 0x4E, 0x61, 0x57, 0x4E, 0x79, 0x62, 0x33, 0x4E, 0x76, 0x5A, 0x6E, 0x51, 0x67, 0x52, 0x55, 0x4E, 0x44, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x32, 0x56, 0x79, 0x64, 0x47, 0x6C, 0x6D, 0x61, 0x57, ++ 0x4E, 0x68, 0x64, 0x47, 0x55, 0x67, 0x51, 0x58, 0x56, 0x30, 0x61, 0x47, 0x39, 0x79, 0x61, 0x58, 0x52, 0x35, 0x49, 0x44, 0x49, 0x77, 0x4D, 0x54, 0x63, 0x77, 0x64, 0x6A, 0x41, 0x51, 0x0A, 0x42, 0x67, 0x63, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, ++ 0x51, 0x49, 0x42, 0x42, 0x67, 0x55, 0x72, 0x67, 0x51, 0x51, 0x41, 0x49, 0x67, 0x4E, 0x69, 0x41, 0x41, 0x54, 0x55, 0x76, 0x44, 0x30, 0x43, 0x51, 0x6E, 0x56, 0x42, 0x45, 0x79, 0x50, 0x4E, 0x67, 0x41, 0x53, 0x47, 0x41, 0x6C, 0x45, 0x76, 0x61, ++ 0x71, 0x69, 0x42, 0x59, 0x67, 0x74, 0x6C, 0x7A, 0x50, 0x62, 0x4B, 0x6E, 0x52, 0x35, 0x76, 0x53, 0x6D, 0x5A, 0x52, 0x6F, 0x67, 0x50, 0x5A, 0x6E, 0x5A, 0x48, 0x36, 0x0A, 0x74, 0x68, 0x61, 0x78, 0x6A, 0x47, 0x37, 0x65, 0x66, 0x4D, 0x33, 0x62, ++ 0x65, 0x61, 0x59, 0x76, 0x7A, 0x72, 0x76, 0x4F, 0x63, 0x53, 0x2F, 0x6C, 0x70, 0x61, 0x73, 0x6F, 0x37, 0x47, 0x4D, 0x45, 0x5A, 0x70, 0x6E, 0x34, 0x2B, 0x76, 0x4B, 0x54, 0x45, 0x41, 0x58, 0x68, 0x67, 0x53, 0x68, 0x43, 0x34, 0x38, 0x5A, 0x6F, ++ 0x39, 0x4F, 0x59, 0x62, 0x68, 0x47, 0x42, 0x4B, 0x69, 0x61, 0x2F, 0x74, 0x65, 0x51, 0x38, 0x37, 0x7A, 0x76, 0x48, 0x32, 0x52, 0x50, 0x55, 0x42, 0x0A, 0x65, 0x4D, 0x43, 0x6A, 0x56, 0x44, 0x42, 0x53, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, ++ 0x64, 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x42, 0x68, 0x6A, 0x41, 0x50, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x52, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x54, 0x41, 0x44, 0x41, 0x51, 0x48, 0x2F, 0x4D, 0x42, 0x30, ++ 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x54, 0x49, 0x79, 0x35, 0x6C, 0x79, 0x63, 0x46, 0x49, 0x4D, 0x0A, 0x2B, 0x4F, 0x61, 0x2B, 0x73, 0x67, 0x52, 0x58, 0x4B, 0x53, 0x72, 0x50, 0x51, 0x68, 0x44, 0x74, 0x4E, 0x54, ++ 0x41, 0x51, 0x42, 0x67, 0x6B, 0x72, 0x42, 0x67, 0x45, 0x45, 0x41, 0x59, 0x49, 0x33, 0x46, 0x51, 0x45, 0x45, 0x41, 0x77, 0x49, 0x42, 0x41, 0x44, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x77, ++ 0x4E, 0x6F, 0x41, 0x44, 0x42, 0x6C, 0x41, 0x6A, 0x42, 0x59, 0x38, 0x6B, 0x33, 0x71, 0x44, 0x50, 0x6C, 0x66, 0x0A, 0x58, 0x75, 0x35, 0x67, 0x4B, 0x63, 0x73, 0x36, 0x38, 0x74, 0x76, 0x57, 0x4D, 0x6F, 0x51, 0x5A, 0x50, 0x33, 0x7A, 0x56, 0x4C, ++ 0x38, 0x4B, 0x78, 0x7A, 0x4A, 0x4F, 0x75, 0x55, 0x4C, 0x73, 0x4A, 0x4D, 0x73, 0x62, 0x47, 0x37, 0x58, 0x37, 0x4A, 0x4E, 0x70, 0x51, 0x53, 0x35, 0x47, 0x69, 0x46, 0x42, 0x71, 0x49, 0x62, 0x30, 0x43, 0x38, 0x43, 0x4D, 0x51, 0x43, 0x5A, 0x36, ++ 0x52, 0x61, 0x30, 0x44, 0x76, 0x70, 0x57, 0x53, 0x4E, 0x53, 0x6B, 0x4D, 0x42, 0x61, 0x52, 0x0A, 0x65, 0x4E, 0x74, 0x55, 0x6A, 0x47, 0x55, 0x42, 0x69, 0x75, 0x64, 0x51, 0x5A, 0x73, 0x49, 0x78, 0x74, 0x7A, 0x6D, 0x36, 0x75, 0x42, 0x6F, 0x69, ++ 0x42, 0x30, 0x37, 0x38, 0x61, 0x31, 0x51, 0x57, 0x49, 0x50, 0x38, 0x72, 0x74, 0x65, 0x64, 0x4D, 0x44, 0x45, 0x32, 0x6D, 0x54, 0x33, 0x4D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, ++ 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, ++ 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x32, 0x30, 0x31, 0x37, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, ++ 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x71, 0x44, 0x43, 0x43, 0x41, 0x35, 0x43, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x48, 0x74, 0x4F, 0x58, 0x43, 0x56, 0x2F, 0x59, ++ 0x74, 0x4C, 0x4E, 0x48, 0x63, 0x42, 0x36, 0x71, 0x76, 0x6E, 0x39, 0x46, 0x73, 0x7A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x77, 0x46, 0x41, 0x44, 0x42, 0x6C, 0x4D, 0x51, 0x73, 0x77, ++ 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x0A, 0x45, 0x77, 0x4A, 0x56, 0x55, 0x7A, 0x45, 0x65, 0x4D, 0x42, 0x77, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x56, 0x54, 0x57, 0x6C, 0x6A, 0x63, 0x6D, 0x39, 0x7A, 0x62, 0x32, 0x5A, ++ 0x30, 0x49, 0x45, 0x4E, 0x76, 0x63, 0x6E, 0x42, 0x76, 0x63, 0x6D, 0x46, 0x30, 0x61, 0x57, 0x39, 0x75, 0x4D, 0x54, 0x59, 0x77, 0x4E, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x79, 0x31, 0x4E, 0x61, 0x57, 0x4E, 0x79, 0x62, 0x33, 0x4E, ++ 0x76, 0x5A, 0x6E, 0x51, 0x67, 0x0A, 0x55, 0x6C, 0x4E, 0x42, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x32, 0x56, 0x79, 0x64, 0x47, 0x6C, 0x6D, 0x61, 0x57, 0x4E, 0x68, 0x64, 0x47, 0x55, 0x67, 0x51, 0x58, 0x56, 0x30, 0x61, 0x47, ++ 0x39, 0x79, 0x61, 0x58, 0x52, 0x35, 0x49, 0x44, 0x49, 0x77, 0x4D, 0x54, 0x63, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x54, 0x6B, 0x78, 0x4D, 0x6A, 0x45, 0x34, 0x4D, 0x6A, 0x49, 0x31, 0x4D, 0x54, 0x49, 0x79, 0x57, 0x68, 0x63, 0x4E, 0x4E, 0x44, ++ 0x49, 0x77, 0x0A, 0x4E, 0x7A, 0x45, 0x34, 0x4D, 0x6A, 0x4D, 0x77, 0x4D, 0x44, 0x49, 0x7A, 0x57, 0x6A, 0x42, 0x6C, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x56, 0x55, 0x7A, 0x45, 0x65, 0x4D, ++ 0x42, 0x77, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x56, 0x54, 0x57, 0x6C, 0x6A, 0x63, 0x6D, 0x39, 0x7A, 0x62, 0x32, 0x5A, 0x30, 0x49, 0x45, 0x4E, 0x76, 0x63, 0x6E, 0x42, 0x76, 0x63, 0x6D, 0x46, 0x30, 0x61, 0x57, 0x39, 0x75, 0x0A, ++ 0x4D, 0x54, 0x59, 0x77, 0x4E, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x79, 0x31, 0x4E, 0x61, 0x57, 0x4E, 0x79, 0x62, 0x33, 0x4E, 0x76, 0x5A, 0x6E, 0x51, 0x67, 0x55, 0x6C, 0x4E, 0x42, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, ++ 0x51, 0x32, 0x56, 0x79, 0x64, 0x47, 0x6C, 0x6D, 0x61, 0x57, 0x4E, 0x68, 0x64, 0x47, 0x55, 0x67, 0x51, 0x58, 0x56, 0x30, 0x61, 0x47, 0x39, 0x79, 0x61, 0x58, 0x52, 0x35, 0x49, 0x44, 0x49, 0x77, 0x4D, 0x54, 0x63, 0x77, 0x0A, 0x67, 0x67, 0x49, ++ 0x69, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x49, 0x4B, 0x41, 0x6F, 0x49, 0x43, 0x41, 0x51, 0x44, ++ 0x4B, 0x57, 0x37, 0x36, 0x55, 0x4D, 0x34, 0x77, 0x70, 0x6C, 0x5A, 0x45, 0x57, 0x43, 0x70, 0x57, 0x39, 0x52, 0x32, 0x4C, 0x42, 0x69, 0x66, 0x4F, 0x5A, 0x4E, 0x74, 0x39, 0x47, 0x6B, 0x4D, 0x6D, 0x6C, 0x0A, 0x37, 0x58, 0x68, 0x71, 0x62, 0x30, ++ 0x65, 0x52, 0x61, 0x50, 0x67, 0x6E, 0x5A, 0x31, 0x41, 0x7A, 0x48, 0x61, 0x47, 0x6D, 0x2B, 0x2B, 0x44, 0x6C, 0x51, 0x36, 0x4F, 0x45, 0x41, 0x6C, 0x63, 0x42, 0x58, 0x5A, 0x78, 0x49, 0x51, 0x49, 0x4A, 0x54, 0x45, 0x4C, 0x79, 0x2F, 0x78, 0x7A, ++ 0x74, 0x6F, 0x6B, 0x4C, 0x61, 0x43, 0x4C, 0x65, 0x58, 0x30, 0x5A, 0x64, 0x44, 0x4D, 0x62, 0x52, 0x6E, 0x4D, 0x6C, 0x66, 0x6C, 0x37, 0x72, 0x45, 0x71, 0x55, 0x72, 0x51, 0x37, 0x65, 0x0A, 0x53, 0x30, 0x4D, 0x64, 0x68, 0x77, 0x65, 0x53, 0x45, ++ 0x35, 0x43, 0x41, 0x67, 0x32, 0x51, 0x31, 0x4F, 0x51, 0x54, 0x38, 0x35, 0x65, 0x6C, 0x73, 0x73, 0x37, 0x59, 0x66, 0x55, 0x4A, 0x51, 0x34, 0x5A, 0x56, 0x42, 0x63, 0x46, 0x30, 0x61, 0x35, 0x74, 0x6F, 0x57, 0x31, 0x48, 0x4C, 0x55, 0x58, 0x36, ++ 0x4E, 0x5A, 0x46, 0x6E, 0x64, 0x69, 0x79, 0x4A, 0x72, 0x44, 0x4B, 0x78, 0x48, 0x42, 0x4B, 0x72, 0x6D, 0x43, 0x6B, 0x33, 0x62, 0x50, 0x5A, 0x37, 0x50, 0x77, 0x37, 0x0A, 0x31, 0x56, 0x64, 0x79, 0x76, 0x44, 0x2F, 0x49, 0x79, 0x62, 0x4C, 0x65, ++ 0x53, 0x32, 0x76, 0x34, 0x49, 0x32, 0x77, 0x44, 0x77, 0x41, 0x57, 0x39, 0x6C, 0x63, 0x66, 0x4E, 0x63, 0x7A, 0x74, 0x6D, 0x67, 0x47, 0x54, 0x6A, 0x47, 0x71, 0x77, 0x75, 0x2B, 0x55, 0x63, 0x46, 0x38, 0x67, 0x61, 0x32, 0x6D, 0x33, 0x50, 0x31, ++ 0x65, 0x44, 0x4E, 0x62, 0x78, 0x36, 0x48, 0x37, 0x4A, 0x79, 0x71, 0x68, 0x74, 0x4A, 0x71, 0x52, 0x6A, 0x4A, 0x48, 0x54, 0x4F, 0x6F, 0x49, 0x2B, 0x0A, 0x64, 0x6B, 0x43, 0x30, 0x7A, 0x56, 0x4A, 0x68, 0x55, 0x58, 0x41, 0x6F, 0x50, 0x38, 0x58, ++ 0x46, 0x57, 0x76, 0x4C, 0x4A, 0x6A, 0x45, 0x6D, 0x37, 0x46, 0x46, 0x74, 0x4E, 0x79, 0x50, 0x39, 0x6E, 0x54, 0x55, 0x77, 0x53, 0x6C, 0x71, 0x33, 0x31, 0x2F, 0x6E, 0x69, 0x6F, 0x6C, 0x34, 0x66, 0x58, 0x2F, 0x56, 0x34, 0x67, 0x67, 0x4E, 0x79, ++ 0x68, 0x53, 0x79, 0x4C, 0x37, 0x31, 0x49, 0x6D, 0x74, 0x75, 0x73, 0x35, 0x48, 0x6C, 0x30, 0x64, 0x56, 0x65, 0x34, 0x39, 0x46, 0x0A, 0x79, 0x47, 0x63, 0x6F, 0x68, 0x4A, 0x55, 0x63, 0x61, 0x44, 0x44, 0x76, 0x37, 0x30, 0x6E, 0x67, 0x4E, 0x58, ++ 0x74, 0x6B, 0x35, 0x35, 0x69, 0x77, 0x6C, 0x4E, 0x70, 0x4E, 0x68, 0x54, 0x73, 0x2B, 0x56, 0x63, 0x51, 0x6F, 0x72, 0x31, 0x66, 0x7A, 0x6E, 0x68, 0x50, 0x62, 0x52, 0x69, 0x65, 0x66, 0x48, 0x71, 0x4A, 0x65, 0x52, 0x49, 0x4F, 0x6B, 0x70, 0x63, ++ 0x72, 0x56, 0x45, 0x37, 0x4E, 0x4C, 0x50, 0x38, 0x54, 0x6A, 0x77, 0x75, 0x61, 0x47, 0x59, 0x61, 0x52, 0x53, 0x0A, 0x4D, 0x4C, 0x6C, 0x36, 0x49, 0x45, 0x39, 0x76, 0x44, 0x7A, 0x68, 0x54, 0x79, 0x7A, 0x4D, 0x4D, 0x45, 0x79, 0x75, 0x50, 0x31, ++ 0x70, 0x71, 0x39, 0x4B, 0x73, 0x67, 0x74, 0x73, 0x52, 0x78, 0x39, 0x53, 0x31, 0x48, 0x4B, 0x52, 0x39, 0x46, 0x49, 0x4A, 0x33, 0x4A, 0x64, 0x68, 0x2B, 0x76, 0x56, 0x52, 0x65, 0x5A, 0x49, 0x5A, 0x5A, 0x32, 0x76, 0x55, 0x70, 0x43, 0x36, 0x57, ++ 0x36, 0x49, 0x59, 0x5A, 0x56, 0x63, 0x53, 0x6E, 0x32, 0x69, 0x35, 0x31, 0x42, 0x56, 0x72, 0x0A, 0x6C, 0x4D, 0x52, 0x70, 0x49, 0x70, 0x6A, 0x30, 0x4D, 0x2B, 0x44, 0x74, 0x2B, 0x56, 0x47, 0x4F, 0x51, 0x56, 0x44, 0x4A, 0x4E, 0x45, 0x39, 0x32, ++ 0x6B, 0x4B, 0x7A, 0x38, 0x4F, 0x4D, 0x48, 0x59, 0x34, 0x58, 0x75, 0x35, 0x34, 0x2B, 0x4F, 0x55, 0x34, 0x55, 0x5A, 0x70, 0x79, 0x77, 0x34, 0x4B, 0x55, 0x47, 0x73, 0x54, 0x75, 0x71, 0x77, 0x50, 0x4E, 0x31, 0x71, 0x33, 0x45, 0x72, 0x57, 0x51, ++ 0x67, 0x52, 0x35, 0x57, 0x72, 0x6C, 0x63, 0x69, 0x68, 0x74, 0x6E, 0x4A, 0x0A, 0x30, 0x74, 0x48, 0x58, 0x55, 0x65, 0x4F, 0x72, 0x4F, 0x38, 0x5A, 0x56, 0x2F, 0x52, 0x34, 0x4F, 0x30, 0x33, 0x51, 0x4B, 0x30, 0x64, 0x71, 0x71, 0x36, 0x6D, 0x6D, ++ 0x34, 0x6C, 0x79, 0x69, 0x50, 0x53, 0x4D, 0x51, 0x48, 0x2B, 0x46, 0x4A, 0x44, 0x4F, 0x76, 0x54, 0x4B, 0x56, 0x54, 0x55, 0x73, 0x73, 0x4B, 0x5A, 0x71, 0x77, 0x4A, 0x7A, 0x35, 0x38, 0x6F, 0x48, 0x68, 0x45, 0x6D, 0x72, 0x41, 0x52, 0x64, 0x6C, ++ 0x6E, 0x73, 0x38, 0x37, 0x2F, 0x49, 0x36, 0x4B, 0x4A, 0x0A, 0x43, 0x6C, 0x54, 0x55, 0x46, 0x4C, 0x6B, 0x71, 0x71, 0x4E, 0x66, 0x73, 0x2B, 0x61, 0x76, 0x4E, 0x4A, 0x56, 0x67, 0x79, 0x65, 0x59, 0x2B, 0x51, 0x57, 0x35, 0x67, 0x35, 0x78, 0x41, ++ 0x67, 0x47, 0x77, 0x61, 0x78, 0x2F, 0x44, 0x6A, 0x30, 0x41, 0x70, 0x51, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x6F, 0x31, 0x51, 0x77, 0x55, 0x6A, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x41, ++ 0x4D, 0x43, 0x41, 0x59, 0x59, 0x77, 0x0A, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, ++ 0x67, 0x51, 0x55, 0x43, 0x63, 0x74, 0x5A, 0x66, 0x34, 0x61, 0x79, 0x63, 0x49, 0x38, 0x61, 0x77, 0x7A, 0x6E, 0x6A, 0x77, 0x4E, 0x6E, 0x70, 0x76, 0x37, 0x74, 0x4E, 0x73, 0x69, 0x4D, 0x77, 0x45, 0x41, 0x59, 0x4A, 0x4B, 0x77, 0x59, 0x42, 0x42, ++ 0x41, 0x47, 0x43, 0x0A, 0x4E, 0x78, 0x55, 0x42, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x51, 0x41, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4D, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x42, ++ 0x41, 0x4B, 0x79, 0x76, 0x50, 0x6C, 0x33, 0x43, 0x45, 0x5A, 0x61, 0x4A, 0x6A, 0x71, 0x50, 0x6E, 0x6B, 0x74, 0x61, 0x58, 0x46, 0x62, 0x67, 0x54, 0x6F, 0x71, 0x5A, 0x43, 0x4C, 0x67, 0x4C, 0x4E, 0x46, 0x67, 0x56, 0x5A, 0x4A, 0x38, 0x6F, 0x67, ++ 0x0A, 0x36, 0x4C, 0x71, 0x34, 0x36, 0x42, 0x72, 0x73, 0x54, 0x61, 0x69, 0x58, 0x56, 0x71, 0x35, 0x6C, 0x51, 0x37, 0x47, 0x50, 0x41, 0x4A, 0x74, 0x53, 0x7A, 0x56, 0x58, 0x4E, 0x55, 0x7A, 0x6C, 0x74, 0x59, 0x6B, 0x79, 0x4C, 0x44, 0x56, 0x74, ++ 0x38, 0x4C, 0x6B, 0x53, 0x2F, 0x67, 0x78, 0x43, 0x50, 0x38, 0x31, 0x4F, 0x43, 0x67, 0x4D, 0x4E, 0x50, 0x4F, 0x73, 0x64, 0x75, 0x45, 0x54, 0x2F, 0x6D, 0x34, 0x78, 0x61, 0x52, 0x68, 0x50, 0x74, 0x74, 0x68, 0x48, 0x38, 0x30, 0x0A, 0x64, 0x4B, ++ 0x32, 0x4A, 0x70, 0x38, 0x36, 0x35, 0x31, 0x39, 0x65, 0x66, 0x68, 0x47, 0x53, 0x53, 0x76, 0x70, 0x57, 0x68, 0x72, 0x51, 0x6C, 0x54, 0x4D, 0x39, 0x33, 0x75, 0x43, 0x75, 0x70, 0x4B, 0x55, 0x59, 0x35, 0x76, 0x56, 0x61, 0x75, 0x36, 0x74, 0x5A, ++ 0x52, 0x47, 0x72, 0x6F, 0x78, 0x2F, 0x32, 0x4B, 0x4A, 0x51, 0x4A, 0x57, 0x56, 0x67, 0x67, 0x45, 0x62, 0x62, 0x4D, 0x77, 0x53, 0x75, 0x62, 0x4C, 0x57, 0x59, 0x64, 0x46, 0x51, 0x6C, 0x33, 0x4A, 0x50, 0x6B, 0x0A, 0x2B, 0x4F, 0x4E, 0x56, 0x46, ++ 0x54, 0x32, 0x34, 0x62, 0x63, 0x4D, 0x4B, 0x70, 0x42, 0x4C, 0x42, 0x61, 0x59, 0x56, 0x75, 0x33, 0x32, 0x54, 0x78, 0x55, 0x35, 0x6E, 0x68, 0x53, 0x6E, 0x55, 0x67, 0x6E, 0x5A, 0x55, 0x50, 0x35, 0x4E, 0x62, 0x63, 0x41, 0x2F, 0x46, 0x5A, 0x47, ++ 0x4F, 0x68, 0x48, 0x69, 0x62, 0x4A, 0x58, 0x57, 0x70, 0x53, 0x32, 0x71, 0x64, 0x67, 0x58, 0x4B, 0x78, 0x64, 0x4A, 0x35, 0x58, 0x62, 0x4C, 0x77, 0x56, 0x61, 0x5A, 0x4F, 0x6A, 0x65, 0x78, 0x0A, 0x2F, 0x32, 0x6B, 0x73, 0x6B, 0x5A, 0x47, 0x54, ++ 0x34, 0x64, 0x39, 0x4D, 0x6F, 0x7A, 0x64, 0x32, 0x54, 0x61, 0x47, 0x66, 0x2B, 0x47, 0x30, 0x65, 0x48, 0x64, 0x50, 0x36, 0x37, 0x50, 0x76, 0x30, 0x52, 0x52, 0x30, 0x54, 0x62, 0x63, 0x2F, 0x33, 0x57, 0x65, 0x55, 0x69, 0x4A, 0x33, 0x49, 0x72, ++ 0x68, 0x76, 0x4E, 0x58, 0x75, 0x7A, 0x44, 0x74, 0x4A, 0x45, 0x33, 0x63, 0x66, 0x56, 0x61, 0x37, 0x6F, 0x37, 0x50, 0x34, 0x4E, 0x48, 0x6D, 0x4A, 0x77, 0x65, 0x44, 0x79, 0x0A, 0x41, 0x6D, 0x48, 0x33, 0x70, 0x76, 0x77, 0x50, 0x75, 0x78, 0x77, ++ 0x58, 0x43, 0x36, 0x35, 0x42, 0x32, 0x58, 0x79, 0x39, 0x4A, 0x36, 0x50, 0x39, 0x4C, 0x6A, 0x72, 0x52, 0x6B, 0x35, 0x53, 0x78, 0x63, 0x78, 0x30, 0x6B, 0x69, 0x36, 0x39, 0x62, 0x49, 0x49, 0x6D, 0x74, 0x74, 0x32, 0x64, 0x6D, 0x65, 0x66, 0x55, ++ 0x36, 0x78, 0x71, 0x61, 0x57, 0x4D, 0x2F, 0x35, 0x54, 0x6B, 0x73, 0x68, 0x47, 0x73, 0x52, 0x47, 0x52, 0x78, 0x70, 0x6C, 0x2F, 0x6A, 0x38, 0x6E, 0x57, 0x0A, 0x5A, 0x6A, 0x45, 0x67, 0x51, 0x52, 0x43, 0x48, 0x4C, 0x51, 0x7A, 0x57, 0x77, 0x61, ++ 0x38, 0x30, 0x6D, 0x4D, 0x70, 0x6B, 0x67, 0x2F, 0x73, 0x54, 0x56, 0x39, 0x48, 0x42, 0x38, 0x44, 0x78, 0x36, 0x6A, 0x4B, 0x58, 0x42, 0x2F, 0x5A, 0x55, 0x68, 0x6F, 0x48, 0x48, 0x42, 0x6B, 0x32, 0x64, 0x78, 0x45, 0x75, 0x71, 0x50, 0x69, 0x41, ++ 0x70, 0x70, 0x47, 0x57, 0x53, 0x5A, 0x49, 0x31, 0x62, 0x37, 0x72, 0x43, 0x6F, 0x75, 0x63, 0x4C, 0x35, 0x6D, 0x78, 0x41, 0x79, 0x45, 0x0A, 0x37, 0x2B, 0x57, 0x4C, 0x38, 0x35, 0x4D, 0x42, 0x2B, 0x47, 0x71, 0x51, 0x6B, 0x32, 0x64, 0x4C, 0x73, ++ 0x6D, 0x69, 0x6A, 0x74, 0x57, 0x4B, 0x50, 0x36, 0x54, 0x2B, 0x4D, 0x65, 0x6A, 0x74, 0x65, 0x44, 0x2B, 0x65, 0x4D, 0x75, 0x4D, 0x5A, 0x38, 0x37, 0x7A, 0x66, 0x39, 0x64, 0x4F, 0x4C, 0x49, 0x54, 0x7A, 0x4E, 0x79, 0x34, 0x5A, 0x51, 0x35, 0x62, ++ 0x62, 0x30, 0x53, 0x72, 0x37, 0x34, 0x4D, 0x54, 0x6E, 0x42, 0x38, 0x47, 0x32, 0x2B, 0x4E, 0x73, 0x7A, 0x4B, 0x54, 0x0A, 0x63, 0x30, 0x51, 0x57, 0x62, 0x65, 0x6A, 0x30, 0x39, 0x2B, 0x43, 0x56, 0x67, 0x49, 0x2B, 0x57, 0x58, 0x54, 0x69, 0x6B, ++ 0x39, 0x4B, 0x76, 0x65, 0x43, 0x6A, 0x43, 0x48, 0x6B, 0x39, 0x68, 0x4E, 0x41, 0x48, 0x46, 0x69, 0x52, 0x53, 0x64, 0x4C, 0x4F, 0x6B, 0x4B, 0x45, 0x57, 0x33, 0x39, 0x6C, 0x74, 0x32, 0x63, 0x30, 0x55, 0x69, 0x32, 0x63, 0x46, 0x6D, 0x75, 0x71, ++ 0x71, 0x4E, 0x68, 0x37, 0x6F, 0x30, 0x4A, 0x4D, 0x63, 0x63, 0x63, 0x4D, 0x79, 0x6A, 0x36, 0x44, 0x0A, 0x35, 0x4B, 0x62, 0x76, 0x74, 0x77, 0x45, 0x77, 0x58, 0x6C, 0x47, 0x6A, 0x65, 0x66, 0x56, 0x77, 0x61, 0x61, 0x5A, 0x42, 0x52, 0x41, 0x2B, ++ 0x47, 0x73, 0x43, 0x79, 0x52, 0x78, 0x6A, 0x33, 0x71, 0x72, 0x67, 0x2B, 0x45, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, ++ 0x0A, 0x65, 0x2D, 0x53, 0x7A, 0x69, 0x67, 0x6E, 0x6F, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, 0x37, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x43, 0x51, 0x44, 0x43, ++ 0x43, 0x41, 0x65, 0x57, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x4D, 0x41, 0x56, 0x52, 0x49, 0x37, 0x79, 0x48, 0x39, 0x6C, 0x31, 0x6B, 0x4E, 0x39, 0x51, 0x51, 0x4B, 0x4D, 0x41, 0x6F, 0x47, 0x43, 0x43, 0x71, 0x47, 0x53, 0x4D, 0x34, ++ 0x39, 0x42, 0x41, 0x4D, 0x43, 0x4D, 0x48, 0x45, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6B, 0x68, 0x56, 0x4D, 0x52, 0x45, 0x77, 0x0A, 0x44, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x48, 0x44, 0x41, ++ 0x68, 0x43, 0x64, 0x57, 0x52, 0x68, 0x63, 0x47, 0x56, 0x7A, 0x64, 0x44, 0x45, 0x57, 0x4D, 0x42, 0x51, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, 0x4E, 0x54, 0x57, 0x6C, 0x6A, 0x63, 0x6D, 0x39, 0x7A, 0x5A, 0x57, 0x4D, 0x67, 0x54, 0x48, ++ 0x52, 0x6B, 0x4C, 0x6A, 0x45, 0x58, 0x4D, 0x42, 0x55, 0x47, 0x41, 0x31, 0x55, 0x45, 0x59, 0x51, 0x77, 0x4F, 0x56, 0x6B, 0x46, 0x55, 0x53, 0x46, 0x55, 0x74, 0x0A, 0x4D, 0x6A, 0x4D, 0x31, 0x4F, 0x44, 0x51, 0x30, 0x4F, 0x54, 0x63, 0x78, 0x48, ++ 0x6A, 0x41, 0x63, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x4D, 0x46, 0x57, 0x55, 0x74, 0x55, 0x33, 0x70, 0x70, 0x5A, 0x32, 0x35, 0x76, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x67, 0x4D, 0x6A, 0x41, 0x78, 0x4E, ++ 0x7A, 0x41, 0x65, 0x46, 0x77, 0x30, 0x78, 0x4E, 0x7A, 0x41, 0x34, 0x4D, 0x6A, 0x49, 0x78, 0x4D, 0x6A, 0x41, 0x33, 0x4D, 0x44, 0x5A, 0x61, 0x0A, 0x46, 0x77, 0x30, 0x30, 0x4D, 0x6A, 0x41, 0x34, 0x4D, 0x6A, 0x49, 0x78, 0x4D, 0x6A, 0x41, 0x33, ++ 0x4D, 0x44, 0x5A, 0x61, 0x4D, 0x48, 0x45, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6B, 0x68, 0x56, 0x4D, 0x52, 0x45, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x48, 0x44, 0x41, 0x68, 0x43, ++ 0x64, 0x57, 0x52, 0x68, 0x63, 0x47, 0x56, 0x7A, 0x64, 0x44, 0x45, 0x57, 0x4D, 0x42, 0x51, 0x47, 0x41, 0x31, 0x55, 0x45, 0x0A, 0x43, 0x67, 0x77, 0x4E, 0x54, 0x57, 0x6C, 0x6A, 0x63, 0x6D, 0x39, 0x7A, 0x5A, 0x57, 0x4D, 0x67, 0x54, 0x48, 0x52, ++ 0x6B, 0x4C, 0x6A, 0x45, 0x58, 0x4D, 0x42, 0x55, 0x47, 0x41, 0x31, 0x55, 0x45, 0x59, 0x51, 0x77, 0x4F, 0x56, 0x6B, 0x46, 0x55, 0x53, 0x46, 0x55, 0x74, 0x4D, 0x6A, 0x4D, 0x31, 0x4F, 0x44, 0x51, 0x30, 0x4F, 0x54, 0x63, 0x78, 0x48, 0x6A, 0x41, ++ 0x63, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x4D, 0x46, 0x57, 0x55, 0x74, 0x55, 0x33, 0x70, 0x70, 0x0A, 0x5A, 0x32, 0x35, 0x76, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x67, 0x4D, 0x6A, 0x41, 0x78, 0x4E, 0x7A, ++ 0x42, 0x5A, 0x4D, 0x42, 0x4D, 0x47, 0x42, 0x79, 0x71, 0x47, 0x53, 0x4D, 0x34, 0x39, 0x41, 0x67, 0x45, 0x47, 0x43, 0x43, 0x71, 0x47, 0x53, 0x4D, 0x34, 0x39, 0x41, 0x77, 0x45, 0x48, 0x41, 0x30, 0x49, 0x41, 0x42, 0x4A, 0x62, 0x63, 0x50, 0x59, ++ 0x72, 0x59, 0x73, 0x48, 0x74, 0x76, 0x78, 0x69, 0x65, 0x2B, 0x52, 0x4A, 0x43, 0x78, 0x0A, 0x73, 0x31, 0x59, 0x56, 0x65, 0x34, 0x35, 0x44, 0x4A, 0x48, 0x30, 0x61, 0x68, 0x46, 0x6E, 0x75, 0x59, 0x32, 0x69, 0x79, 0x78, 0x6C, 0x36, 0x48, 0x30, ++ 0x42, 0x56, 0x49, 0x48, 0x71, 0x69, 0x51, 0x72, 0x62, 0x31, 0x54, 0x6F, 0x74, 0x72, 0x65, 0x4F, 0x70, 0x43, 0x6D, 0x59, 0x46, 0x39, 0x6F, 0x4D, 0x72, 0x57, 0x47, 0x51, 0x64, 0x2B, 0x48, 0x57, 0x79, 0x78, 0x37, 0x78, 0x66, 0x35, 0x38, 0x65, ++ 0x74, 0x71, 0x6A, 0x59, 0x7A, 0x42, 0x68, 0x4D, 0x41, 0x38, 0x47, 0x0A, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, ++ 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x51, 0x44, 0x41, 0x67, 0x45, 0x47, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x53, 0x48, 0x45, 0x52, 0x55, 0x49, 0x30, 0x61, 0x72, 0x42, 0x65, 0x41, 0x79, 0x78, ++ 0x72, 0x38, 0x37, 0x47, 0x79, 0x5A, 0x44, 0x76, 0x0A, 0x76, 0x7A, 0x41, 0x45, 0x77, 0x44, 0x41, 0x66, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x53, 0x4D, 0x45, 0x47, 0x44, 0x41, 0x57, 0x67, 0x42, 0x53, 0x48, 0x45, 0x52, 0x55, 0x49, 0x30, 0x61, 0x72, ++ 0x42, 0x65, 0x41, 0x79, 0x78, 0x72, 0x38, 0x37, 0x47, 0x79, 0x5A, 0x44, 0x76, 0x76, 0x7A, 0x41, 0x45, 0x77, 0x44, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x67, 0x4E, 0x4A, 0x41, 0x44, 0x42, ++ 0x47, 0x41, 0x69, 0x45, 0x41, 0x0A, 0x74, 0x56, 0x66, 0x64, 0x31, 0x34, 0x70, 0x56, 0x43, 0x7A, 0x62, 0x68, 0x68, 0x6B, 0x54, 0x36, 0x31, 0x4E, 0x6C, 0x6F, 0x6A, 0x62, 0x6A, 0x63, 0x49, 0x34, 0x71, 0x4B, 0x44, 0x64, 0x51, 0x76, 0x66, 0x65, ++ 0x70, 0x7A, 0x37, 0x4C, 0x39, 0x4E, 0x62, 0x4B, 0x67, 0x43, 0x49, 0x51, 0x44, 0x4C, 0x70, 0x62, 0x51, 0x53, 0x2B, 0x75, 0x65, 0x31, 0x36, 0x4D, 0x39, 0x2B, 0x6B, 0x2F, 0x7A, 0x7A, 0x4E, 0x59, 0x39, 0x76, 0x54, 0x6C, 0x70, 0x38, 0x74, 0x4C, ++ 0x78, 0x4F, 0x0A, 0x73, 0x76, 0x78, 0x79, 0x71, 0x6C, 0x74, 0x5A, 0x2B, 0x65, 0x66, 0x63, 0x4D, 0x51, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, ++ 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x63, 0x65, 0x72, 0x74, 0x53, 0x49, 0x47, 0x4E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x47, 0x32, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x52, ++ 0x7A, 0x43, 0x43, 0x41, 0x79, 0x2B, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x4A, 0x45, 0x51, 0x41, 0x30, 0x74, 0x6B, 0x37, 0x47, 0x4E, 0x69, 0x30, 0x32, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, ++ 0x51, 0x45, 0x42, 0x43, 0x77, 0x55, 0x41, 0x4D, 0x45, 0x45, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6C, 0x4A, 0x50, 0x4D, 0x52, 0x51, 0x77, 0x0A, 0x45, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, ++ 0x45, 0x77, 0x74, 0x44, 0x52, 0x56, 0x4A, 0x55, 0x55, 0x30, 0x6C, 0x48, 0x54, 0x69, 0x42, 0x54, 0x51, 0x54, 0x45, 0x63, 0x4D, 0x42, 0x6F, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x78, 0x4D, 0x54, 0x59, 0x32, 0x56, 0x79, 0x64, 0x46, 0x4E, 0x4A, ++ 0x52, 0x30, 0x34, 0x67, 0x55, 0x6B, 0x39, 0x50, 0x56, 0x43, 0x42, 0x44, 0x51, 0x53, 0x42, 0x48, 0x4D, 0x6A, 0x41, 0x65, 0x46, 0x77, 0x30, 0x78, 0x4E, 0x7A, 0x41, 0x79, 0x0A, 0x4D, 0x44, 0x59, 0x77, 0x4F, 0x54, 0x49, 0x33, 0x4D, 0x7A, 0x56, ++ 0x61, 0x46, 0x77, 0x30, 0x30, 0x4D, 0x6A, 0x41, 0x79, 0x4D, 0x44, 0x59, 0x77, 0x4F, 0x54, 0x49, 0x33, 0x4D, 0x7A, 0x56, 0x61, 0x4D, 0x45, 0x45, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6C, 0x4A, ++ 0x50, 0x4D, 0x52, 0x51, 0x77, 0x45, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x45, 0x77, 0x74, 0x44, 0x52, 0x56, 0x4A, 0x55, 0x55, 0x30, 0x6C, 0x48, 0x0A, 0x54, 0x69, 0x42, 0x54, 0x51, 0x54, 0x45, 0x63, 0x4D, 0x42, 0x6F, 0x47, 0x41, 0x31, ++ 0x55, 0x45, 0x43, 0x78, 0x4D, 0x54, 0x59, 0x32, 0x56, 0x79, 0x64, 0x46, 0x4E, 0x4A, 0x52, 0x30, 0x34, 0x67, 0x55, 0x6B, 0x39, 0x50, 0x56, 0x43, 0x42, 0x44, 0x51, 0x53, 0x42, 0x48, 0x4D, 0x6A, 0x43, 0x43, 0x41, 0x69, 0x49, 0x77, 0x44, 0x51, ++ 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x50, 0x0A, 0x41, 0x44, 0x43, 0x43, 0x41, 0x67, 0x6F, 0x43, 0x67, 0x67, 0x49, 0x42, 0x41, 0x4D, 0x44, 0x46, 0x64, ++ 0x52, 0x6D, 0x52, 0x66, 0x55, 0x52, 0x30, 0x64, 0x49, 0x66, 0x2B, 0x44, 0x6A, 0x75, 0x57, 0x33, 0x4E, 0x67, 0x42, 0x46, 0x73, 0x7A, 0x75, 0x59, 0x35, 0x48, 0x6E, 0x43, 0x32, 0x2F, 0x4F, 0x4F, 0x77, 0x70, 0x70, 0x47, 0x6E, 0x7A, 0x43, 0x34, ++ 0x36, 0x2B, 0x43, 0x6A, 0x6F, 0x62, 0x58, 0x58, 0x6F, 0x39, 0x58, 0x36, 0x39, 0x4D, 0x68, 0x57, 0x66, 0x30, 0x35, 0x0A, 0x4E, 0x30, 0x49, 0x77, 0x76, 0x6C, 0x44, 0x71, 0x74, 0x67, 0x2B, 0x70, 0x69, 0x4E, 0x67, 0x75, 0x4C, 0x57, 0x6B, 0x68, ++ 0x35, 0x39, 0x45, 0x33, 0x47, 0x45, 0x35, 0x39, 0x6B, 0x64, 0x55, 0x57, 0x58, 0x32, 0x74, 0x62, 0x41, 0x4D, 0x49, 0x35, 0x51, 0x77, 0x30, 0x32, 0x68, 0x56, 0x4B, 0x35, 0x55, 0x32, 0x55, 0x50, 0x48, 0x55, 0x4C, 0x6C, 0x6A, 0x38, 0x38, 0x46, ++ 0x30, 0x2B, 0x37, 0x63, 0x44, 0x42, 0x72, 0x5A, 0x75, 0x49, 0x74, 0x34, 0x49, 0x6D, 0x66, 0x6B, 0x0A, 0x61, 0x62, 0x42, 0x6F, 0x78, 0x54, 0x7A, 0x6B, 0x62, 0x46, 0x70, 0x47, 0x35, 0x38, 0x33, 0x48, 0x2B, 0x75, 0x2F, 0x45, 0x37, 0x45, 0x75, ++ 0x39, 0x61, 0x71, 0x53, 0x73, 0x2F, 0x63, 0x77, 0x6F, 0x55, 0x65, 0x2B, 0x53, 0x74, 0x43, 0x6D, 0x72, 0x71, 0x7A, 0x57, 0x61, 0x54, 0x4F, 0x54, 0x45, 0x43, 0x4D, 0x59, 0x6D, 0x7A, 0x50, 0x68, 0x70, 0x6E, 0x2B, 0x53, 0x63, 0x38, 0x43, 0x6E, ++ 0x54, 0x58, 0x50, 0x6E, 0x47, 0x46, 0x69, 0x57, 0x65, 0x49, 0x38, 0x4D, 0x67, 0x0A, 0x77, 0x54, 0x30, 0x50, 0x50, 0x7A, 0x68, 0x41, 0x73, 0x50, 0x36, 0x43, 0x52, 0x44, 0x69, 0x71, 0x57, 0x68, 0x71, 0x4B, 0x61, 0x32, 0x4E, 0x59, 0x4F, 0x4C, ++ 0x51, 0x56, 0x30, 0x37, 0x59, 0x52, 0x61, 0x58, 0x73, 0x65, 0x56, 0x4F, 0x36, 0x4D, 0x47, 0x69, 0x4B, 0x73, 0x63, 0x70, 0x63, 0x2F, 0x49, 0x31, 0x6D, 0x62, 0x79, 0x53, 0x4B, 0x45, 0x77, 0x51, 0x64, 0x50, 0x7A, 0x48, 0x2F, 0x69, 0x56, 0x38, ++ 0x6F, 0x53, 0x63, 0x4C, 0x75, 0x6D, 0x5A, 0x66, 0x4E, 0x70, 0x0A, 0x64, 0x57, 0x4F, 0x39, 0x6C, 0x66, 0x73, 0x62, 0x6C, 0x38, 0x33, 0x6B, 0x71, 0x4B, 0x2F, 0x32, 0x30, 0x55, 0x36, 0x6F, 0x32, 0x59, 0x70, 0x78, 0x4A, 0x4D, 0x30, 0x32, 0x50, ++ 0x62, 0x79, 0x57, 0x78, 0x50, 0x46, 0x73, 0x71, 0x61, 0x37, 0x6C, 0x7A, 0x77, 0x31, 0x75, 0x4B, 0x41, 0x32, 0x77, 0x44, 0x72, 0x58, 0x4B, 0x55, 0x58, 0x74, 0x34, 0x46, 0x4D, 0x4D, 0x67, 0x4C, 0x33, 0x2F, 0x37, 0x46, 0x46, 0x58, 0x68, 0x45, ++ 0x5A, 0x6E, 0x39, 0x31, 0x51, 0x71, 0x68, 0x0A, 0x6E, 0x67, 0x4C, 0x6A, 0x59, 0x6C, 0x2F, 0x72, 0x4E, 0x55, 0x73, 0x73, 0x75, 0x48, 0x4C, 0x6F, 0x50, 0x6A, 0x31, 0x50, 0x72, 0x43, 0x79, 0x37, 0x4C, 0x6F, 0x62, 0x69, 0x6F, 0x33, 0x61, 0x50, ++ 0x35, 0x5A, 0x4D, 0x71, 0x7A, 0x36, 0x57, 0x72, 0x79, 0x46, 0x79, 0x4E, 0x53, 0x77, 0x62, 0x2F, 0x45, 0x6B, 0x61, 0x73, 0x65, 0x4D, 0x73, 0x55, 0x42, 0x7A, 0x58, 0x67, 0x71, 0x64, 0x2B, 0x4C, 0x36, 0x61, 0x38, 0x56, 0x54, 0x78, 0x61, 0x4A, ++ 0x57, 0x37, 0x33, 0x32, 0x0A, 0x6A, 0x63, 0x5A, 0x5A, 0x72, 0x6F, 0x69, 0x46, 0x44, 0x73, 0x47, 0x4A, 0x36, 0x78, 0x39, 0x6E, 0x78, 0x55, 0x57, 0x4F, 0x2F, 0x32, 0x30, 0x33, 0x4E, 0x69, 0x74, 0x34, 0x5A, 0x6F, 0x4F, 0x52, 0x55, 0x53, 0x73, ++ 0x39, 0x2F, 0x31, 0x46, 0x33, 0x64, 0x6D, 0x4B, 0x68, 0x37, 0x47, 0x63, 0x2B, 0x50, 0x6F, 0x47, 0x44, 0x34, 0x46, 0x61, 0x70, 0x55, 0x42, 0x38, 0x66, 0x65, 0x70, 0x6D, 0x72, 0x59, 0x37, 0x2B, 0x45, 0x46, 0x33, 0x66, 0x78, 0x44, 0x54, 0x76, ++ 0x66, 0x0A, 0x39, 0x35, 0x78, 0x68, 0x73, 0x7A, 0x57, 0x59, 0x69, 0x6A, 0x71, 0x79, 0x37, 0x44, 0x77, 0x61, 0x4E, 0x7A, 0x39, 0x2B, 0x6A, 0x35, 0x4C, 0x50, 0x32, 0x52, 0x49, 0x55, 0x5A, 0x4E, 0x6F, 0x51, 0x41, 0x68, 0x56, 0x42, 0x2F, 0x30, ++ 0x2F, 0x45, 0x36, 0x78, 0x79, 0x6A, 0x79, 0x66, 0x71, 0x5A, 0x39, 0x30, 0x62, 0x70, 0x34, 0x52, 0x6A, 0x5A, 0x73, 0x62, 0x67, 0x79, 0x4C, 0x63, 0x73, 0x55, 0x44, 0x46, 0x44, 0x59, 0x67, 0x32, 0x57, 0x44, 0x37, 0x72, 0x6C, 0x63, 0x0A, 0x7A, ++ 0x38, 0x73, 0x46, 0x57, 0x6B, 0x7A, 0x36, 0x47, 0x5A, 0x64, 0x72, 0x31, 0x6C, 0x30, 0x54, 0x30, 0x38, 0x4A, 0x63, 0x56, 0x4C, 0x77, 0x79, 0x63, 0x36, 0x42, 0x34, 0x39, 0x66, 0x46, 0x74, 0x48, 0x73, 0x75, 0x66, 0x70, 0x61, 0x61, 0x66, 0x49, ++ 0x74, 0x7A, 0x52, 0x55, 0x5A, 0x36, 0x43, 0x65, 0x57, 0x52, 0x67, 0x4B, 0x52, 0x4D, 0x2B, 0x6F, 0x2F, 0x31, 0x50, 0x63, 0x6D, 0x71, 0x72, 0x34, 0x74, 0x54, 0x6C, 0x75, 0x43, 0x52, 0x56, 0x4C, 0x45, 0x52, 0x4C, 0x0A, 0x69, 0x6F, 0x68, 0x45, ++ 0x6E, 0x4D, 0x71, 0x45, 0x30, 0x79, 0x6F, 0x37, 0x41, 0x67, 0x4D, 0x42, 0x41, 0x41, 0x47, 0x6A, 0x51, 0x6A, 0x42, 0x41, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, ++ 0x41, 0x66, 0x38, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x51, 0x44, 0x41, 0x67, 0x45, 0x47, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x0A, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x53, ++ 0x43, 0x49, 0x53, 0x31, 0x6D, 0x78, 0x74, 0x65, 0x67, 0x34, 0x42, 0x58, 0x72, 0x7A, 0x6B, 0x77, 0x4A, 0x64, 0x38, 0x52, 0x67, 0x6E, 0x6C, 0x52, 0x75, 0x41, 0x7A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, ++ 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x67, 0x45, 0x41, 0x59, 0x4E, 0x34, 0x61, 0x75, 0x4F, 0x66, 0x79, 0x59, 0x49, 0x4C, 0x56, 0x41, 0x7A, 0x4F, 0x42, 0x0A, 0x79, 0x77, 0x61, 0x4B, 0x38, 0x53, 0x4A, 0x4A, 0x36, 0x65, ++ 0x6A, 0x71, 0x6B, 0x58, 0x2F, 0x47, 0x4D, 0x31, 0x35, 0x6F, 0x47, 0x51, 0x4F, 0x47, 0x4F, 0x30, 0x4D, 0x42, 0x7A, 0x77, 0x64, 0x77, 0x35, 0x41, 0x67, 0x65, 0x5A, 0x59, 0x57, 0x52, 0x35, 0x68, 0x45, 0x69, 0x74, 0x2F, 0x55, 0x43, 0x49, 0x34, ++ 0x36, 0x75, 0x75, 0x52, 0x35, 0x39, 0x48, 0x33, 0x35, 0x73, 0x35, 0x72, 0x30, 0x6C, 0x31, 0x5A, 0x55, 0x61, 0x38, 0x67, 0x57, 0x6D, 0x72, 0x34, 0x55, 0x43, 0x0A, 0x62, 0x36, 0x37, 0x34, 0x31, 0x6A, 0x48, 0x2F, 0x4A, 0x63, 0x6C, 0x4B, 0x79, ++ 0x4D, 0x65, 0x4B, 0x71, 0x64, 0x6D, 0x66, 0x53, 0x30, 0x6D, 0x62, 0x45, 0x56, 0x65, 0x5A, 0x6B, 0x6B, 0x4D, 0x52, 0x33, 0x72, 0x59, 0x7A, 0x70, 0x4D, 0x7A, 0x58, 0x6A, 0x57, 0x52, 0x39, 0x31, 0x4D, 0x30, 0x38, 0x4B, 0x43, 0x79, 0x30, 0x6D, ++ 0x70, 0x62, 0x71, 0x54, 0x66, 0x58, 0x45, 0x52, 0x4D, 0x51, 0x6C, 0x71, 0x69, 0x43, 0x41, 0x32, 0x43, 0x6C, 0x56, 0x39, 0x2B, 0x42, 0x42, 0x0A, 0x2F, 0x41, 0x59, 0x6D, 0x2F, 0x37, 0x6B, 0x32, 0x39, 0x55, 0x4D, 0x55, 0x41, 0x32, 0x5A, 0x34, ++ 0x34, 0x52, 0x47, 0x78, 0x32, 0x69, 0x42, 0x66, 0x52, 0x67, 0x42, 0x34, 0x41, 0x43, 0x47, 0x6C, 0x48, 0x67, 0x41, 0x6F, 0x59, 0x58, 0x68, 0x76, 0x71, 0x41, 0x45, 0x42, 0x6A, 0x35, 0x30, 0x30, 0x6D, 0x76, 0x2F, 0x30, 0x4F, 0x4A, 0x44, 0x37, ++ 0x75, 0x4E, 0x47, 0x7A, 0x63, 0x67, 0x62, 0x4A, 0x63, 0x65, 0x61, 0x42, 0x78, 0x58, 0x6E, 0x74, 0x43, 0x36, 0x5A, 0x35, 0x0A, 0x38, 0x68, 0x4D, 0x4C, 0x6E, 0x50, 0x64, 0x64, 0x44, 0x6E, 0x73, 0x6B, 0x6B, 0x37, 0x52, 0x49, 0x32, 0x34, 0x5A, ++ 0x66, 0x33, 0x6C, 0x43, 0x47, 0x65, 0x4F, 0x64, 0x41, 0x35, 0x6A, 0x47, 0x6F, 0x6B, 0x48, 0x5A, 0x77, 0x59, 0x61, 0x2B, 0x63, 0x4E, 0x79, 0x77, 0x52, 0x74, 0x59, 0x4B, 0x33, 0x71, 0x71, 0x34, 0x6B, 0x4E, 0x46, 0x74, 0x79, 0x44, 0x47, 0x6B, ++ 0x4E, 0x7A, 0x56, 0x6D, 0x66, 0x39, 0x6E, 0x47, 0x76, 0x6E, 0x41, 0x76, 0x52, 0x43, 0x6A, 0x6A, 0x35, 0x0A, 0x42, 0x69, 0x4B, 0x44, 0x55, 0x79, 0x55, 0x4D, 0x2F, 0x46, 0x48, 0x45, 0x35, 0x72, 0x37, 0x69, 0x4F, 0x5A, 0x55, 0x4C, 0x4A, 0x4B, ++ 0x32, 0x76, 0x30, 0x5A, 0x58, 0x6B, 0x6C, 0x74, 0x64, 0x30, 0x5A, 0x47, 0x74, 0x78, 0x54, 0x67, 0x49, 0x38, 0x71, 0x6F, 0x58, 0x7A, 0x49, 0x4B, 0x4E, 0x44, 0x4F, 0x58, 0x5A, 0x62, 0x62, 0x46, 0x44, 0x2B, 0x6D, 0x70, 0x77, 0x55, 0x48, 0x6D, ++ 0x55, 0x55, 0x69, 0x68, 0x57, 0x39, 0x6F, 0x34, 0x4A, 0x46, 0x57, 0x6B, 0x6C, 0x57, 0x0A, 0x61, 0x74, 0x4B, 0x63, 0x73, 0x57, 0x4D, 0x79, 0x35, 0x57, 0x48, 0x67, 0x55, 0x79, 0x49, 0x4F, 0x70, 0x77, 0x70, 0x4A, 0x36, 0x73, 0x74, 0x2B, 0x48, ++ 0x36, 0x6A, 0x69, 0x59, 0x6F, 0x44, 0x32, 0x45, 0x45, 0x56, 0x53, 0x6D, 0x41, 0x59, 0x59, 0x33, 0x71, 0x58, 0x4E, 0x4C, 0x33, 0x2B, 0x71, 0x31, 0x4F, 0x6B, 0x2B, 0x43, 0x48, 0x4C, 0x73, 0x49, 0x77, 0x4D, 0x43, 0x50, 0x4B, 0x61, 0x71, 0x32, ++ 0x4C, 0x78, 0x6E, 0x64, 0x44, 0x30, 0x55, 0x46, 0x2F, 0x74, 0x55, 0x0A, 0x53, 0x78, 0x66, 0x6A, 0x30, 0x33, 0x6B, 0x39, 0x62, 0x57, 0x74, 0x4A, 0x79, 0x53, 0x67, 0x4F, 0x4C, 0x6E, 0x52, 0x51, 0x76, 0x77, 0x7A, 0x5A, 0x52, 0x6A, 0x6F, 0x51, ++ 0x68, 0x73, 0x6D, 0x6E, 0x50, 0x2B, 0x6D, 0x67, 0x37, 0x48, 0x2F, 0x72, 0x70, 0x58, 0x64, 0x59, 0x61, 0x58, 0x48, 0x6D, 0x67, 0x77, 0x6F, 0x33, 0x38, 0x6F, 0x5A, 0x4A, 0x61, 0x72, 0x35, 0x35, 0x43, 0x4A, 0x44, 0x32, 0x41, 0x68, 0x5A, 0x6B, ++ 0x50, 0x75, 0x58, 0x61, 0x54, 0x48, 0x34, 0x4D, 0x0A, 0x4E, 0x4D, 0x6E, 0x35, 0x58, 0x37, 0x61, 0x7A, 0x4B, 0x46, 0x47, 0x6E, 0x70, 0x79, 0x75, 0x71, 0x53, 0x66, 0x71, 0x4E, 0x5A, 0x53, 0x6C, 0x4F, 0x34, 0x32, 0x73, 0x54, 0x70, 0x35, 0x53, ++ 0x6A, 0x4C, 0x56, 0x46, 0x74, 0x65, 0x41, 0x78, 0x45, 0x79, 0x39, 0x2F, 0x65, 0x43, 0x47, 0x2F, 0x4F, 0x6F, 0x32, 0x53, 0x72, 0x30, 0x35, 0x57, 0x45, 0x31, 0x4C, 0x6C, 0x53, 0x56, 0x48, 0x4A, 0x37, 0x6C, 0x69, 0x58, 0x4D, 0x76, 0x47, 0x6E, ++ 0x6A, 0x53, 0x47, 0x34, 0x4E, 0x0A, 0x30, 0x4D, 0x65, 0x64, 0x4A, 0x35, 0x71, 0x71, 0x2B, 0x42, 0x4F, 0x53, 0x33, 0x52, 0x37, 0x66, 0x59, 0x35, 0x38, 0x31, 0x71, 0x52, 0x59, 0x32, 0x37, 0x49, 0x79, 0x34, 0x67, 0x2F, 0x51, 0x39, 0x69, 0x59, ++ 0x2F, 0x4E, 0x74, 0x42, 0x64, 0x65, 0x31, 0x37, 0x4D, 0x58, 0x51, 0x52, 0x42, 0x64, 0x4A, 0x33, 0x4E, 0x67, 0x68, 0x56, 0x64, 0x4A, 0x49, 0x67, 0x63, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, ++ 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, ++ 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, ++ 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x32, 0x6A, 0x43, 0x43, 0x41, 0x38, 0x4B, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x4D, 0x42, 0x66, 0x63, 0x4F, 0x68, 0x74, 0x70, 0x4A, 0x38, 0x30, 0x59, 0x31, 0x4C, 0x72, 0x71, 0x79, ++ 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x43, 0x77, 0x55, 0x41, 0x4D, 0x49, 0x47, 0x49, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x56, ++ 0x0A, 0x55, 0x7A, 0x45, 0x52, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x41, 0x77, 0x49, 0x53, 0x57, 0x78, 0x73, 0x61, 0x57, 0x35, 0x76, 0x61, 0x58, 0x4D, 0x78, 0x45, 0x44, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x63, ++ 0x4D, 0x42, 0x30, 0x4E, 0x6F, 0x61, 0x57, 0x4E, 0x68, 0x5A, 0x32, 0x38, 0x78, 0x49, 0x54, 0x41, 0x66, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x4D, 0x47, 0x46, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x64, 0x32, 0x46, 0x32, 0x0A, 0x5A, 0x53, ++ 0x42, 0x49, 0x62, 0x32, 0x78, 0x6B, 0x61, 0x57, 0x35, 0x6E, 0x63, 0x79, 0x77, 0x67, 0x53, 0x57, 0x35, 0x6A, 0x4C, 0x6A, 0x45, 0x78, 0x4D, 0x43, 0x38, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x77, 0x77, 0x6F, 0x56, 0x48, 0x4A, 0x31, 0x63, 0x33, ++ 0x52, 0x33, 0x59, 0x58, 0x5A, 0x6C, 0x49, 0x45, 0x64, 0x73, 0x62, 0x32, 0x4A, 0x68, 0x62, 0x43, 0x42, 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x61, 0x57, 0x5A, 0x70, 0x59, 0x32, 0x46, 0x30, 0x61, 0x57, 0x39, 0x75, 0x0A, 0x49, 0x45, 0x46, 0x31, 0x64, ++ 0x47, 0x68, 0x76, 0x63, 0x6D, 0x6C, 0x30, 0x65, 0x54, 0x41, 0x65, 0x46, 0x77, 0x30, 0x78, 0x4E, 0x7A, 0x41, 0x34, 0x4D, 0x6A, 0x4D, 0x78, 0x4F, 0x54, 0x4D, 0x30, 0x4D, 0x54, 0x4A, 0x61, 0x46, 0x77, 0x30, 0x30, 0x4D, 0x6A, 0x41, 0x34, 0x4D, ++ 0x6A, 0x4D, 0x78, 0x4F, 0x54, 0x4D, 0x30, 0x4D, 0x54, 0x4A, 0x61, 0x4D, 0x49, 0x47, 0x49, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x56, 0x0A, 0x55, 0x7A, 0x45, 0x52, 0x4D, 0x41, 0x38, 0x47, ++ 0x41, 0x31, 0x55, 0x45, 0x43, 0x41, 0x77, 0x49, 0x53, 0x57, 0x78, 0x73, 0x61, 0x57, 0x35, 0x76, 0x61, 0x58, 0x4D, 0x78, 0x45, 0x44, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x63, 0x4D, 0x42, 0x30, 0x4E, 0x6F, 0x61, 0x57, 0x4E, 0x68, ++ 0x5A, 0x32, 0x38, 0x78, 0x49, 0x54, 0x41, 0x66, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x4D, 0x47, 0x46, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x64, 0x32, 0x46, 0x32, 0x0A, 0x5A, 0x53, 0x42, 0x49, 0x62, 0x32, 0x78, 0x6B, 0x61, 0x57, 0x35, ++ 0x6E, 0x63, 0x79, 0x77, 0x67, 0x53, 0x57, 0x35, 0x6A, 0x4C, 0x6A, 0x45, 0x78, 0x4D, 0x43, 0x38, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x77, 0x77, 0x6F, 0x56, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x52, 0x33, 0x59, 0x58, 0x5A, 0x6C, 0x49, 0x45, 0x64, ++ 0x73, 0x62, 0x32, 0x4A, 0x68, 0x62, 0x43, 0x42, 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x61, 0x57, 0x5A, 0x70, 0x59, 0x32, 0x46, 0x30, 0x61, 0x57, 0x39, 0x75, 0x0A, 0x49, 0x45, 0x46, 0x31, 0x64, 0x47, 0x68, 0x76, 0x63, 0x6D, 0x6C, 0x30, 0x65, 0x54, ++ 0x43, 0x43, 0x41, 0x69, 0x49, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x50, 0x41, 0x44, 0x43, 0x43, 0x41, 0x67, 0x6F, 0x43, 0x67, 0x67, ++ 0x49, 0x42, 0x41, 0x4C, 0x6C, 0x64, 0x55, 0x53, 0x68, 0x4C, 0x50, 0x44, 0x65, 0x53, 0x30, 0x59, 0x4C, 0x4F, 0x76, 0x52, 0x32, 0x39, 0x0A, 0x7A, 0x64, 0x32, 0x34, 0x71, 0x38, 0x38, 0x4B, 0x50, 0x75, 0x46, 0x64, 0x35, 0x64, 0x79, 0x71, 0x43, ++ 0x62, 0x6C, 0x58, 0x41, 0x6A, 0x37, 0x6D, 0x59, 0x32, 0x48, 0x66, 0x38, 0x67, 0x2B, 0x43, 0x59, 0x36, 0x36, 0x6A, 0x39, 0x36, 0x78, 0x7A, 0x30, 0x58, 0x7A, 0x6E, 0x73, 0x77, 0x75, 0x76, 0x43, 0x41, 0x41, 0x4A, 0x57, 0x58, 0x2F, 0x4E, 0x4B, ++ 0x53, 0x71, 0x49, 0x6B, 0x34, 0x63, 0x58, 0x47, 0x49, 0x44, 0x74, 0x69, 0x4C, 0x4B, 0x30, 0x74, 0x68, 0x41, 0x66, 0x0A, 0x4C, 0x64, 0x5A, 0x66, 0x56, 0x61, 0x49, 0x54, 0x58, 0x64, 0x48, 0x47, 0x36, 0x77, 0x5A, 0x57, 0x69, 0x59, 0x6A, 0x2B, ++ 0x72, 0x44, 0x4B, 0x64, 0x2F, 0x56, 0x7A, 0x44, 0x42, 0x63, 0x64, 0x75, 0x37, 0x6F, 0x61, 0x4A, 0x75, 0x6F, 0x67, 0x44, 0x6E, 0x58, 0x49, 0x68, 0x68, 0x70, 0x43, 0x75, 0x6A, 0x77, 0x4F, 0x6C, 0x33, 0x4A, 0x2B, 0x49, 0x4B, 0x4D, 0x75, 0x6A, ++ 0x6B, 0x6B, 0x6B, 0x50, 0x37, 0x4E, 0x41, 0x50, 0x34, 0x6D, 0x31, 0x45, 0x54, 0x34, 0x42, 0x71, 0x0A, 0x73, 0x74, 0x54, 0x6E, 0x6F, 0x41, 0x70, 0x54, 0x41, 0x62, 0x71, 0x4F, 0x6C, 0x35, 0x46, 0x32, 0x62, 0x72, 0x7A, 0x38, 0x31, 0x57, 0x73, ++ 0x32, 0x35, 0x6B, 0x43, 0x49, 0x31, 0x6E, 0x73, 0x76, 0x58, 0x77, 0x58, 0x6F, 0x4C, 0x47, 0x30, 0x52, 0x38, 0x2B, 0x65, 0x79, 0x76, 0x70, 0x4A, 0x45, 0x54, 0x4E, 0x4B, 0x58, 0x70, 0x50, 0x37, 0x53, 0x63, 0x6F, 0x46, 0x44, 0x42, 0x35, 0x7A, ++ 0x70, 0x45, 0x54, 0x37, 0x31, 0x69, 0x78, 0x70, 0x5A, 0x66, 0x52, 0x39, 0x6F, 0x0A, 0x57, 0x4E, 0x30, 0x45, 0x41, 0x43, 0x79, 0x57, 0x38, 0x30, 0x4F, 0x7A, 0x66, 0x70, 0x67, 0x5A, 0x64, 0x4E, 0x6D, 0x63, 0x63, 0x39, 0x6B, 0x59, 0x76, 0x6B, ++ 0x48, 0x48, 0x4E, 0x48, 0x6E, 0x5A, 0x39, 0x47, 0x4C, 0x43, 0x51, 0x37, 0x6D, 0x7A, 0x4A, 0x37, 0x41, 0x69, 0x79, 0x2F, 0x6B, 0x39, 0x55, 0x73, 0x63, 0x77, 0x52, 0x37, 0x50, 0x4A, 0x50, 0x72, 0x68, 0x71, 0x34, 0x75, 0x66, 0x6F, 0x67, 0x58, ++ 0x42, 0x65, 0x51, 0x6F, 0x74, 0x50, 0x4A, 0x71, 0x58, 0x2B, 0x0A, 0x4F, 0x73, 0x49, 0x67, 0x62, 0x72, 0x76, 0x34, 0x46, 0x6F, 0x37, 0x4E, 0x44, 0x4B, 0x6D, 0x30, 0x47, 0x32, 0x78, 0x32, 0x45, 0x4F, 0x46, 0x59, 0x65, 0x55, 0x59, 0x2B, 0x56, ++ 0x4D, 0x36, 0x41, 0x71, 0x46, 0x63, 0x4A, 0x4E, 0x79, 0x6B, 0x62, 0x6D, 0x52, 0x4F, 0x50, 0x44, 0x4D, 0x6A, 0x57, 0x4C, 0x42, 0x7A, 0x37, 0x42, 0x65, 0x67, 0x49, 0x6C, 0x54, 0x31, 0x6C, 0x52, 0x74, 0x7A, 0x75, 0x7A, 0x57, 0x6E, 0x69, 0x54, ++ 0x59, 0x2B, 0x48, 0x4B, 0x45, 0x34, 0x30, 0x0A, 0x43, 0x7A, 0x37, 0x50, 0x46, 0x4E, 0x6D, 0x37, 0x33, 0x62, 0x5A, 0x51, 0x6D, 0x71, 0x31, 0x33, 0x31, 0x42, 0x6E, 0x57, 0x32, 0x68, 0x71, 0x49, 0x79, 0x45, 0x34, 0x62, 0x4A, 0x33, 0x58, 0x59, ++ 0x73, 0x67, 0x6A, 0x78, 0x72, 0x6F, 0x4D, 0x77, 0x75, 0x52, 0x45, 0x4F, 0x7A, 0x59, 0x66, 0x77, 0x68, 0x49, 0x30, 0x56, 0x63, 0x6E, 0x79, 0x68, 0x37, 0x38, 0x7A, 0x79, 0x69, 0x47, 0x47, 0x36, 0x39, 0x47, 0x6D, 0x37, 0x44, 0x49, 0x77, 0x4C, ++ 0x64, 0x56, 0x63, 0x45, 0x0A, 0x75, 0x45, 0x34, 0x71, 0x46, 0x43, 0x34, 0x39, 0x44, 0x78, 0x77, 0x65, 0x4D, 0x71, 0x5A, 0x69, 0x4E, 0x75, 0x35, 0x6D, 0x34, 0x69, 0x4B, 0x34, 0x42, 0x55, 0x42, 0x6A, 0x45, 0x43, 0x4C, 0x7A, 0x4D, 0x78, 0x31, ++ 0x30, 0x63, 0x6F, 0x6F, 0x73, 0x39, 0x54, 0x6B, 0x70, 0x6F, 0x4E, 0x50, 0x6E, 0x47, 0x34, 0x43, 0x45, 0x4C, 0x63, 0x55, 0x39, 0x34, 0x30, 0x32, 0x78, 0x2F, 0x52, 0x70, 0x76, 0x75, 0x6D, 0x55, 0x48, 0x4F, 0x31, 0x6A, 0x73, 0x51, 0x6B, 0x55, ++ 0x6D, 0x0A, 0x2B, 0x39, 0x6A, 0x61, 0x4A, 0x58, 0x4C, 0x45, 0x39, 0x67, 0x43, 0x78, 0x49, 0x6E, 0x6D, 0x39, 0x34, 0x33, 0x78, 0x5A, 0x59, 0x6B, 0x71, 0x63, 0x42, 0x57, 0x38, 0x39, 0x7A, 0x75, 0x62, 0x57, 0x52, 0x32, 0x4F, 0x5A, 0x78, 0x69, ++ 0x52, 0x76, 0x63, 0x68, 0x4C, 0x49, 0x72, 0x48, 0x2B, 0x51, 0x74, 0x41, 0x75, 0x52, 0x63, 0x4F, 0x69, 0x33, 0x35, 0x68, 0x59, 0x51, 0x63, 0x52, 0x66, 0x4F, 0x33, 0x67, 0x5A, 0x50, 0x53, 0x45, 0x46, 0x39, 0x4E, 0x55, 0x71, 0x6A, 0x0A, 0x69, ++ 0x66, 0x4C, 0x4A, 0x53, 0x33, 0x74, 0x42, 0x45, 0x57, 0x31, 0x6E, 0x74, 0x77, 0x69, 0x59, 0x54, 0x4F, 0x55, 0x52, 0x47, 0x61, 0x35, 0x43, 0x67, 0x4E, 0x7A, 0x37, 0x6B, 0x41, 0x58, 0x55, 0x2B, 0x46, 0x44, 0x4B, 0x76, 0x75, 0x53, 0x74, 0x78, ++ 0x38, 0x4B, 0x55, 0x31, 0x78, 0x61, 0x64, 0x35, 0x68, 0x65, 0x50, 0x72, 0x7A, 0x62, 0x37, 0x41, 0x67, 0x4D, 0x42, 0x41, 0x41, 0x47, 0x6A, 0x51, 0x6A, 0x42, 0x41, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x0A, 0x45, 0x77, 0x45, 0x42, ++ 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x48, 0x51, 0x59, 0x44, 0x56, 0x52, 0x30, 0x4F, 0x42, 0x42, 0x59, 0x45, 0x46, 0x4A, 0x6E, 0x67, 0x47, 0x57, 0x63, 0x4E, 0x59, 0x74, 0x74, 0x32, 0x73, 0x39, 0x6F, 0x39, ++ 0x75, 0x46, 0x76, 0x6F, 0x2F, 0x55, 0x4C, 0x53, 0x4D, 0x51, 0x36, 0x48, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x42, 0x0A, 0x42, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, ++ 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x67, 0x45, 0x41, 0x6D, 0x48, 0x4E, 0x77, 0x34, 0x72, 0x44, 0x54, 0x37, 0x54, 0x6E, 0x73, 0x54, 0x47, 0x44, 0x5A, 0x71, 0x52, 0x4B, ++ 0x47, 0x46, 0x78, 0x36, 0x57, 0x30, 0x4F, 0x68, 0x55, 0x4B, 0x44, 0x74, 0x6B, 0x4C, 0x53, 0x47, 0x6D, 0x2B, 0x4A, 0x31, 0x57, 0x45, 0x32, 0x70, 0x49, 0x50, 0x55, 0x2F, 0x48, 0x0A, 0x50, 0x69, 0x6E, 0x62, 0x62, 0x56, 0x69, 0x44, 0x56, 0x44, ++ 0x32, 0x48, 0x66, 0x53, 0x4D, 0x46, 0x31, 0x4F, 0x51, 0x63, 0x33, 0x4F, 0x67, 0x34, 0x5A, 0x59, 0x62, 0x46, 0x64, 0x61, 0x64, 0x61, 0x32, 0x7A, 0x55, 0x46, 0x76, 0x58, 0x66, 0x65, 0x75, 0x79, 0x6B, 0x33, 0x51, 0x41, 0x55, 0x48, 0x77, 0x35, ++ 0x52, 0x53, 0x6E, 0x38, 0x70, 0x6B, 0x33, 0x66, 0x45, 0x62, 0x4B, 0x39, 0x78, 0x47, 0x43, 0x68, 0x41, 0x43, 0x4D, 0x66, 0x31, 0x4B, 0x61, 0x41, 0x30, 0x48, 0x0A, 0x5A, 0x4A, 0x44, 0x6D, 0x48, 0x76, 0x55, 0x71, 0x6F, 0x61, 0x69, 0x37, 0x50, ++ 0x46, 0x33, 0x35, 0x6F, 0x77, 0x67, 0x4C, 0x45, 0x51, 0x7A, 0x78, 0x50, 0x79, 0x30, 0x51, 0x6C, 0x47, 0x2F, 0x2B, 0x34, 0x6A, 0x53, 0x48, 0x67, 0x39, 0x62, 0x50, 0x35, 0x52, 0x73, 0x31, 0x62, 0x64, 0x49, 0x44, 0x34, 0x62, 0x41, 0x4E, 0x71, ++ 0x4B, 0x43, 0x71, 0x52, 0x69, 0x65, 0x43, 0x4E, 0x71, 0x63, 0x56, 0x74, 0x67, 0x69, 0x6D, 0x51, 0x6C, 0x52, 0x58, 0x74, 0x70, 0x6C, 0x61, 0x0A, 0x34, 0x67, 0x74, 0x35, 0x6B, 0x4E, 0x64, 0x58, 0x45, 0x6C, 0x45, 0x31, 0x47, 0x59, 0x68, 0x42, ++ 0x61, 0x43, 0x58, 0x55, 0x4E, 0x78, 0x65, 0x45, 0x46, 0x66, 0x73, 0x42, 0x63, 0x74, 0x79, 0x56, 0x33, 0x6C, 0x49, 0x6D, 0x49, 0x4A, 0x67, 0x6D, 0x34, 0x6E, 0x62, 0x31, 0x4A, 0x32, 0x2F, 0x36, 0x41, 0x44, 0x74, 0x4B, 0x59, 0x64, 0x6B, 0x4E, ++ 0x79, 0x31, 0x47, 0x54, 0x4B, 0x76, 0x30, 0x57, 0x42, 0x70, 0x61, 0x6E, 0x49, 0x35, 0x6F, 0x6A, 0x53, 0x50, 0x35, 0x52, 0x0A, 0x76, 0x62, 0x62, 0x45, 0x73, 0x4C, 0x46, 0x55, 0x7A, 0x74, 0x35, 0x73, 0x51, 0x61, 0x30, 0x57, 0x5A, 0x33, 0x37, ++ 0x62, 0x2F, 0x54, 0x6A, 0x4E, 0x75, 0x54, 0x68, 0x4F, 0x73, 0x73, 0x46, 0x67, 0x79, 0x35, 0x30, 0x58, 0x33, 0x31, 0x69, 0x65, 0x65, 0x6D, 0x4B, 0x79, 0x4A, 0x6F, 0x39, 0x30, 0x6C, 0x5A, 0x76, 0x6B, 0x57, 0x78, 0x33, 0x53, 0x44, 0x39, 0x32, ++ 0x59, 0x48, 0x4A, 0x74, 0x5A, 0x75, 0x53, 0x50, 0x54, 0x4D, 0x61, 0x43, 0x6D, 0x2F, 0x7A, 0x6A, 0x64, 0x0A, 0x7A, 0x79, 0x42, 0x50, 0x36, 0x56, 0x68, 0x57, 0x4F, 0x6D, 0x66, 0x44, 0x30, 0x66, 0x61, 0x5A, 0x6D, 0x5A, 0x32, 0x36, 0x4E, 0x72, ++ 0x61, 0x41, 0x4C, 0x34, 0x68, 0x48, 0x54, 0x34, 0x61, 0x2F, 0x52, 0x44, 0x71, 0x41, 0x35, 0x44, 0x63, 0x63, 0x70, 0x72, 0x72, 0x71, 0x6C, 0x35, 0x67, 0x52, 0x30, 0x49, 0x52, 0x69, 0x52, 0x32, 0x51, 0x65, 0x71, 0x75, 0x35, 0x41, 0x76, 0x7A, ++ 0x53, 0x78, 0x6E, 0x49, 0x39, 0x4F, 0x34, 0x66, 0x4B, 0x53, 0x54, 0x78, 0x2B, 0x4F, 0x0A, 0x38, 0x35, 0x36, 0x58, 0x33, 0x76, 0x4F, 0x6D, 0x65, 0x57, 0x71, 0x4A, 0x63, 0x55, 0x39, 0x4C, 0x4A, 0x78, 0x64, 0x49, 0x2F, 0x75, 0x7A, 0x30, 0x55, ++ 0x41, 0x39, 0x50, 0x53, 0x58, 0x33, 0x4D, 0x52, 0x65, 0x4F, 0x39, 0x65, 0x6B, 0x44, 0x46, 0x51, 0x64, 0x78, 0x68, 0x56, 0x69, 0x63, 0x47, 0x61, 0x65, 0x56, 0x79, 0x51, 0x59, 0x48, 0x54, 0x74, 0x67, 0x47, 0x4A, 0x6F, 0x43, 0x38, 0x36, 0x63, ++ 0x6E, 0x6E, 0x2B, 0x4F, 0x6A, 0x43, 0x2F, 0x51, 0x65, 0x7A, 0x48, 0x0A, 0x59, 0x6A, 0x36, 0x52, 0x53, 0x38, 0x66, 0x5A, 0x4D, 0x58, 0x5A, 0x43, 0x2B, 0x66, 0x63, 0x38, 0x59, 0x2B, 0x77, 0x6D, 0x6A, 0x48, 0x4D, 0x4D, 0x66, 0x52, 0x6F, 0x64, ++ 0x36, 0x71, 0x68, 0x38, 0x68, 0x36, 0x6A, 0x43, 0x4A, 0x33, 0x7A, 0x68, 0x4D, 0x30, 0x45, 0x50, 0x7A, 0x38, 0x2F, 0x38, 0x41, 0x4B, 0x41, 0x69, 0x67, 0x4A, 0x35, 0x4B, 0x70, 0x32, 0x38, 0x41, 0x73, 0x45, 0x46, 0x46, 0x74, 0x79, 0x4C, 0x4B, ++ 0x61, 0x45, 0x6A, 0x46, 0x51, 0x71, 0x4B, 0x75, 0x0A, 0x33, 0x52, 0x33, 0x79, 0x34, 0x47, 0x35, 0x4F, 0x42, 0x56, 0x69, 0x78, 0x77, 0x4A, 0x41, 0x57, 0x4B, 0x71, 0x51, 0x39, 0x45, 0x45, 0x43, 0x2B, 0x6A, 0x32, 0x4A, 0x6A, 0x67, 0x36, 0x6D, ++ 0x63, 0x67, 0x6E, 0x30, 0x74, 0x41, 0x75, 0x6D, 0x44, 0x4D, 0x48, 0x7A, 0x4C, 0x4A, 0x38, 0x6E, 0x39, 0x48, 0x6D, 0x59, 0x41, 0x73, 0x43, 0x37, 0x54, 0x49, 0x53, 0x2B, 0x4F, 0x4D, 0x78, 0x5A, 0x73, 0x6D, 0x4F, 0x30, 0x51, 0x71, 0x41, 0x66, ++ 0x57, 0x7A, 0x4A, 0x50, 0x50, 0x0A, 0x32, 0x39, 0x46, 0x70, 0x48, 0x4F, 0x54, 0x4B, 0x79, 0x65, 0x43, 0x32, 0x6E, 0x4F, 0x6E, 0x4F, 0x63, 0x58, 0x48, 0x65, 0x62, 0x44, 0x38, 0x57, 0x70, 0x48, 0x6B, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, ++ 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x45, ++ 0x43, 0x43, 0x20, 0x50, 0x32, 0x35, 0x36, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x43, 0x59, 0x44, 0x43, 0x43, 0x41, 0x67, ++ 0x65, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x4D, 0x44, 0x57, 0x70, 0x66, 0x43, 0x44, 0x38, 0x6F, 0x58, 0x44, 0x35, 0x52, 0x6C, 0x64, 0x39, 0x64, 0x4D, 0x41, 0x6F, 0x47, 0x43, 0x43, 0x71, 0x47, 0x53, 0x4D, 0x34, 0x39, 0x42, 0x41, ++ 0x4D, 0x43, 0x4D, 0x49, 0x47, 0x52, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x56, 0x55, 0x7A, 0x45, 0x52, 0x0A, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x42, 0x4D, 0x49, 0x53, ++ 0x57, 0x78, 0x73, 0x61, 0x57, 0x35, 0x76, 0x61, 0x58, 0x4D, 0x78, 0x45, 0x44, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x63, 0x54, 0x42, 0x30, 0x4E, 0x6F, 0x61, 0x57, 0x4E, 0x68, 0x5A, 0x32, 0x38, 0x78, 0x49, 0x54, 0x41, 0x66, 0x42, ++ 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x47, 0x46, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x64, 0x32, 0x46, 0x32, 0x5A, 0x53, 0x42, 0x49, 0x0A, 0x62, 0x32, 0x78, 0x6B, 0x61, 0x57, 0x35, 0x6E, 0x63, 0x79, 0x77, 0x67, 0x53, 0x57, 0x35, 0x6A, ++ 0x4C, 0x6A, 0x45, 0x36, 0x4D, 0x44, 0x67, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x78, 0x56, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x52, 0x33, 0x59, 0x58, 0x5A, 0x6C, 0x49, 0x45, 0x64, 0x73, 0x62, 0x32, 0x4A, 0x68, 0x62, 0x43, 0x42, 0x46, ++ 0x51, 0x30, 0x4D, 0x67, 0x55, 0x44, 0x49, 0x31, 0x4E, 0x69, 0x42, 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x61, 0x57, 0x5A, 0x70, 0x0A, 0x59, 0x32, 0x46, 0x30, 0x61, 0x57, 0x39, 0x75, 0x49, 0x45, 0x46, 0x31, 0x64, 0x47, 0x68, 0x76, 0x63, 0x6D, 0x6C, ++ 0x30, 0x65, 0x54, 0x41, 0x65, 0x46, 0x77, 0x30, 0x78, 0x4E, 0x7A, 0x41, 0x34, 0x4D, 0x6A, 0x4D, 0x78, 0x4F, 0x54, 0x4D, 0x31, 0x4D, 0x54, 0x42, 0x61, 0x46, 0x77, 0x30, 0x30, 0x4D, 0x6A, 0x41, 0x34, 0x4D, 0x6A, 0x4D, 0x78, 0x4F, 0x54, 0x4D, ++ 0x31, 0x4D, 0x54, 0x42, 0x61, 0x4D, 0x49, 0x47, 0x52, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x0A, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x56, 0x55, 0x7A, 0x45, 0x52, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x42, ++ 0x4D, 0x49, 0x53, 0x57, 0x78, 0x73, 0x61, 0x57, 0x35, 0x76, 0x61, 0x58, 0x4D, 0x78, 0x45, 0x44, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x63, 0x54, 0x42, 0x30, 0x4E, 0x6F, 0x61, 0x57, 0x4E, 0x68, 0x5A, 0x32, 0x38, 0x78, 0x49, 0x54, ++ 0x41, 0x66, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x47, 0x46, 0x52, 0x79, 0x0A, 0x64, 0x58, 0x4E, 0x30, 0x64, 0x32, 0x46, 0x32, 0x5A, 0x53, 0x42, 0x49, 0x62, 0x32, 0x78, 0x6B, 0x61, 0x57, 0x35, 0x6E, 0x63, 0x79, 0x77, 0x67, 0x53, ++ 0x57, 0x35, 0x6A, 0x4C, 0x6A, 0x45, 0x36, 0x4D, 0x44, 0x67, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x78, 0x56, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x52, 0x33, 0x59, 0x58, 0x5A, 0x6C, 0x49, 0x45, 0x64, 0x73, 0x62, 0x32, 0x4A, 0x68, 0x62, ++ 0x43, 0x42, 0x46, 0x51, 0x30, 0x4D, 0x67, 0x55, 0x44, 0x49, 0x31, 0x0A, 0x4E, 0x69, 0x42, 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x61, 0x57, 0x5A, 0x70, 0x59, 0x32, 0x46, 0x30, 0x61, 0x57, 0x39, 0x75, 0x49, 0x45, 0x46, 0x31, 0x64, 0x47, 0x68, 0x76, ++ 0x63, 0x6D, 0x6C, 0x30, 0x65, 0x54, 0x42, 0x5A, 0x4D, 0x42, 0x4D, 0x47, 0x42, 0x79, 0x71, 0x47, 0x53, 0x4D, 0x34, 0x39, 0x41, 0x67, 0x45, 0x47, 0x43, 0x43, 0x71, 0x47, 0x53, 0x4D, 0x34, 0x39, 0x41, 0x77, 0x45, 0x48, 0x41, 0x30, 0x49, 0x41, ++ 0x42, 0x48, 0x37, 0x37, 0x62, 0x4F, 0x59, 0x6A, 0x0A, 0x34, 0x33, 0x4D, 0x79, 0x43, 0x4D, 0x70, 0x67, 0x35, 0x6C, 0x4F, 0x63, 0x75, 0x6E, 0x53, 0x4E, 0x47, 0x4C, 0x42, 0x34, 0x6B, 0x46, 0x4B, 0x41, 0x33, 0x54, 0x6A, 0x41, 0x53, 0x68, 0x33, ++ 0x52, 0x71, 0x4D, 0x79, 0x54, 0x70, 0x4A, 0x63, 0x47, 0x4F, 0x4D, 0x6F, 0x4E, 0x46, 0x57, 0x4C, 0x47, 0x6A, 0x67, 0x45, 0x71, 0x5A, 0x5A, 0x32, 0x71, 0x33, 0x7A, 0x53, 0x52, 0x4C, 0x6F, 0x48, 0x42, 0x35, 0x44, 0x4F, 0x53, 0x4D, 0x63, 0x54, ++ 0x39, 0x43, 0x54, 0x71, 0x6D, 0x0A, 0x50, 0x36, 0x32, 0x6A, 0x51, 0x7A, 0x42, 0x42, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x44, 0x77, ++ 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x44, 0x41, 0x77, 0x63, 0x47, 0x41, 0x44, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x6F, 0x30, 0x45, 0x47, 0x72, 0x4A, ++ 0x42, 0x74, 0x0A, 0x30, 0x55, 0x72, 0x72, 0x64, 0x61, 0x56, 0x4B, 0x45, 0x4A, 0x6D, 0x7A, 0x73, 0x61, 0x47, 0x4C, 0x53, 0x76, 0x63, 0x77, 0x43, 0x67, 0x59, 0x49, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x45, 0x41, 0x77, 0x49, 0x44, 0x52, ++ 0x77, 0x41, 0x77, 0x52, 0x41, 0x49, 0x67, 0x42, 0x2B, 0x5A, 0x55, 0x32, 0x67, 0x36, 0x67, 0x57, 0x72, 0x4B, 0x75, 0x45, 0x5A, 0x2B, 0x48, 0x78, 0x62, 0x62, 0x2F, 0x61, 0x64, 0x34, 0x6C, 0x76, 0x76, 0x69, 0x67, 0x74, 0x77, 0x6A, 0x7A, 0x0A, ++ 0x52, 0x4D, 0x34, 0x71, 0x33, 0x77, 0x67, 0x68, 0x44, 0x44, 0x63, 0x43, 0x49, 0x43, 0x30, 0x6D, 0x41, 0x36, 0x41, 0x46, 0x76, 0x57, 0x76, 0x52, 0x39, 0x6C, 0x7A, 0x34, 0x5A, 0x63, 0x79, 0x47, 0x62, 0x62, 0x4F, 0x63, 0x4E, 0x45, 0x68, 0x6A, ++ 0x68, 0x41, 0x6E, 0x46, 0x6A, 0x58, 0x63, 0x61, 0x34, 0x73, 0x79, 0x63, 0x34, 0x58, 0x52, 0x37, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, ++ 0x2D, 0x2D, 0x0A, 0x0A, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x45, 0x43, 0x43, 0x20, 0x50, 0x33, 0x38, 0x34, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, ++ 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, ++ 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x43, 0x6E, 0x54, 0x43, 0x43, 0x41, 0x69, 0x53, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x4D, 0x43, 0x4C, 0x32, 0x46, 0x6C, 0x32, 0x79, 0x5A, ++ 0x4A, 0x36, 0x53, 0x41, 0x61, 0x45, 0x63, 0x37, 0x4D, 0x41, 0x6F, 0x47, 0x43, 0x43, 0x71, 0x47, 0x53, 0x4D, 0x34, 0x39, 0x42, 0x41, 0x4D, 0x44, 0x4D, 0x49, 0x47, 0x52, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, ++ 0x45, 0x77, 0x4A, 0x56, 0x55, 0x7A, 0x45, 0x52, 0x0A, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x42, 0x4D, 0x49, 0x53, 0x57, 0x78, 0x73, 0x61, 0x57, 0x35, 0x76, 0x61, 0x58, 0x4D, 0x78, 0x45, 0x44, 0x41, 0x4F, 0x42, 0x67, 0x4E, ++ 0x56, 0x42, 0x41, 0x63, 0x54, 0x42, 0x30, 0x4E, 0x6F, 0x61, 0x57, 0x4E, 0x68, 0x5A, 0x32, 0x38, 0x78, 0x49, 0x54, 0x41, 0x66, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x47, 0x46, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x64, 0x32, 0x46, ++ 0x32, 0x5A, 0x53, 0x42, 0x49, 0x0A, 0x62, 0x32, 0x78, 0x6B, 0x61, 0x57, 0x35, 0x6E, 0x63, 0x79, 0x77, 0x67, 0x53, 0x57, 0x35, 0x6A, 0x4C, 0x6A, 0x45, 0x36, 0x4D, 0x44, 0x67, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x78, 0x56, 0x48, ++ 0x4A, 0x31, 0x63, 0x33, 0x52, 0x33, 0x59, 0x58, 0x5A, 0x6C, 0x49, 0x45, 0x64, 0x73, 0x62, 0x32, 0x4A, 0x68, 0x62, 0x43, 0x42, 0x46, 0x51, 0x30, 0x4D, 0x67, 0x55, 0x44, 0x4D, 0x34, 0x4E, 0x43, 0x42, 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x61, 0x57, ++ 0x5A, 0x70, 0x0A, 0x59, 0x32, 0x46, 0x30, 0x61, 0x57, 0x39, 0x75, 0x49, 0x45, 0x46, 0x31, 0x64, 0x47, 0x68, 0x76, 0x63, 0x6D, 0x6C, 0x30, 0x65, 0x54, 0x41, 0x65, 0x46, 0x77, 0x30, 0x78, 0x4E, 0x7A, 0x41, 0x34, 0x4D, 0x6A, 0x4D, 0x78, 0x4F, ++ 0x54, 0x4D, 0x32, 0x4E, 0x44, 0x4E, 0x61, 0x46, 0x77, 0x30, 0x30, 0x4D, 0x6A, 0x41, 0x34, 0x4D, 0x6A, 0x4D, 0x78, 0x4F, 0x54, 0x4D, 0x32, 0x4E, 0x44, 0x4E, 0x61, 0x4D, 0x49, 0x47, 0x52, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x0A, ++ 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x56, 0x55, 0x7A, 0x45, 0x52, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x42, 0x4D, 0x49, 0x53, 0x57, 0x78, 0x73, 0x61, 0x57, 0x35, 0x76, 0x61, 0x58, 0x4D, 0x78, 0x45, 0x44, 0x41, 0x4F, ++ 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x63, 0x54, 0x42, 0x30, 0x4E, 0x6F, 0x61, 0x57, 0x4E, 0x68, 0x5A, 0x32, 0x38, 0x78, 0x49, 0x54, 0x41, 0x66, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x47, 0x46, 0x52, 0x79, 0x0A, 0x64, 0x58, 0x4E, ++ 0x30, 0x64, 0x32, 0x46, 0x32, 0x5A, 0x53, 0x42, 0x49, 0x62, 0x32, 0x78, 0x6B, 0x61, 0x57, 0x35, 0x6E, 0x63, 0x79, 0x77, 0x67, 0x53, 0x57, 0x35, 0x6A, 0x4C, 0x6A, 0x45, 0x36, 0x4D, 0x44, 0x67, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, ++ 0x78, 0x56, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x52, 0x33, 0x59, 0x58, 0x5A, 0x6C, 0x49, 0x45, 0x64, 0x73, 0x62, 0x32, 0x4A, 0x68, 0x62, 0x43, 0x42, 0x46, 0x51, 0x30, 0x4D, 0x67, 0x55, 0x44, 0x4D, 0x34, 0x0A, 0x4E, 0x43, 0x42, 0x44, 0x5A, 0x58, ++ 0x4A, 0x30, 0x61, 0x57, 0x5A, 0x70, 0x59, 0x32, 0x46, 0x30, 0x61, 0x57, 0x39, 0x75, 0x49, 0x45, 0x46, 0x31, 0x64, 0x47, 0x68, 0x76, 0x63, 0x6D, 0x6C, 0x30, 0x65, 0x54, 0x42, 0x32, 0x4D, 0x42, 0x41, 0x47, 0x42, 0x79, 0x71, 0x47, 0x53, 0x4D, ++ 0x34, 0x39, 0x41, 0x67, 0x45, 0x47, 0x42, 0x53, 0x75, 0x42, 0x42, 0x41, 0x41, 0x69, 0x41, 0x32, 0x49, 0x41, 0x42, 0x47, 0x76, 0x61, 0x44, 0x58, 0x55, 0x31, 0x43, 0x44, 0x46, 0x48, 0x0A, 0x42, 0x61, 0x35, 0x46, 0x6D, 0x56, 0x58, 0x78, 0x45, ++ 0x52, 0x4D, 0x75, 0x53, 0x76, 0x67, 0x51, 0x4D, 0x53, 0x4F, 0x6A, 0x66, 0x6F, 0x50, 0x54, 0x66, 0x79, 0x67, 0x49, 0x4F, 0x69, 0x59, 0x61, 0x4F, 0x73, 0x2B, 0x58, 0x67, 0x68, 0x2B, 0x41, 0x74, 0x79, 0x63, 0x4A, 0x6A, 0x39, 0x47, 0x4F, 0x4D, ++ 0x4D, 0x51, 0x4B, 0x6D, 0x77, 0x36, 0x73, 0x57, 0x41, 0x53, 0x72, 0x39, 0x7A, 0x5A, 0x39, 0x6C, 0x43, 0x4F, 0x6B, 0x6D, 0x77, 0x71, 0x4B, 0x69, 0x36, 0x76, 0x72, 0x0A, 0x2F, 0x54, 0x6B, 0x6C, 0x5A, 0x76, 0x46, 0x65, 0x2F, 0x6F, 0x79, 0x75, ++ 0x6A, 0x55, 0x46, 0x35, 0x6E, 0x51, 0x6C, 0x67, 0x7A, 0x69, 0x69, 0x70, 0x30, 0x34, 0x70, 0x74, 0x38, 0x39, 0x5A, 0x46, 0x31, 0x50, 0x4B, 0x59, 0x68, 0x44, 0x68, 0x6C, 0x6F, 0x4B, 0x4E, 0x44, 0x4D, 0x45, 0x45, 0x77, 0x44, 0x77, 0x59, 0x44, ++ 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x50, 0x42, 0x67, 0x4E, 0x56, 0x0A, 0x48, 0x51, 0x38, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x51, 0x4D, 0x44, 0x42, 0x77, 0x59, ++ 0x41, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x52, 0x56, 0x71, 0x59, 0x53, 0x4A, 0x30, 0x73, 0x45, 0x79, 0x76, 0x52, 0x6A, 0x4C, 0x62, 0x4B, 0x59, 0x48, 0x54, 0x73, 0x6A, 0x6E, 0x6E, 0x62, 0x36, ++ 0x43, 0x6B, 0x44, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x77, 0x4E, 0x6E, 0x0A, 0x41, 0x44, 0x42, 0x6B, 0x41, 0x6A, 0x41, 0x33, 0x41, 0x5A, 0x4B, 0x58, 0x52, 0x52, 0x4A, 0x2B, 0x6F, 0x50, ++ 0x4D, 0x2B, 0x72, 0x52, 0x6B, 0x36, 0x63, 0x74, 0x33, 0x30, 0x55, 0x4A, 0x4D, 0x44, 0x45, 0x72, 0x35, 0x45, 0x30, 0x6B, 0x39, 0x42, 0x70, 0x49, 0x79, 0x63, 0x6E, 0x52, 0x2B, 0x6A, 0x39, 0x73, 0x4B, 0x53, 0x35, 0x30, 0x67, 0x55, 0x2F, 0x6B, ++ 0x36, 0x62, 0x70, 0x5A, 0x46, 0x58, 0x72, 0x73, 0x59, 0x33, 0x63, 0x72, 0x73, 0x43, 0x4D, 0x47, 0x63, 0x6C, 0x0A, 0x43, 0x72, 0x45, 0x4D, 0x58, 0x75, 0x36, 0x70, 0x59, 0x35, 0x4A, 0x76, 0x35, 0x5A, 0x41, 0x4C, 0x2F, 0x6D, 0x59, 0x69, 0x79, ++ 0x6B, 0x66, 0x39, 0x69, 0x6A, 0x48, 0x33, 0x67, 0x2F, 0x35, 0x36, 0x76, 0x78, 0x43, 0x2B, 0x47, 0x43, 0x73, 0x65, 0x6A, 0x2F, 0x59, 0x70, 0x48, 0x70, 0x52, 0x5A, 0x37, 0x34, 0x34, 0x68, 0x4E, 0x38, 0x74, 0x52, 0x6D, 0x4B, 0x56, 0x75, 0x53, ++ 0x77, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x4E, 0x41, 0x56, 0x45, 0x52, 0x20, 0x47, 0x6C, 0x6F, ++ 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, ++ 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x6F, 0x6A, 0x43, 0x43, 0x41, 0x34, 0x71, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, ++ 0x67, 0x49, 0x55, 0x41, 0x5A, 0x51, 0x77, 0x48, 0x71, 0x49, 0x4C, 0x33, 0x66, 0x58, 0x46, 0x4D, 0x79, 0x71, 0x78, 0x51, 0x30, 0x52, 0x78, 0x2B, 0x4E, 0x5A, 0x51, 0x54, 0x51, 0x30, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, ++ 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4D, 0x42, 0x51, 0x41, 0x77, 0x61, 0x54, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x0A, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x53, 0x31, 0x49, 0x78, 0x4A, 0x6A, 0x41, 0x6B, 0x42, 0x67, 0x4E, 0x56, ++ 0x42, 0x41, 0x6F, 0x4D, 0x48, 0x55, 0x35, 0x42, 0x56, 0x6B, 0x56, 0x53, 0x49, 0x45, 0x4A, 0x56, 0x55, 0x30, 0x6C, 0x4F, 0x52, 0x56, 0x4E, 0x54, 0x49, 0x46, 0x42, 0x4D, 0x51, 0x56, 0x52, 0x47, 0x54, 0x31, 0x4A, 0x4E, 0x49, 0x45, 0x4E, 0x76, ++ 0x63, 0x6E, 0x41, 0x75, 0x4D, 0x54, 0x49, 0x77, 0x4D, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x0A, 0x44, 0x43, 0x6C, 0x4F, 0x51, 0x56, 0x5A, 0x46, 0x55, 0x69, 0x42, 0x48, 0x62, 0x47, 0x39, 0x69, 0x59, 0x57, 0x77, 0x67, 0x55, 0x6D, 0x39, ++ 0x76, 0x64, 0x43, 0x42, 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x61, 0x57, 0x5A, 0x70, 0x59, 0x32, 0x46, 0x30, 0x61, 0x57, 0x39, 0x75, 0x49, 0x45, 0x46, 0x31, 0x64, 0x47, 0x68, 0x76, 0x63, 0x6D, 0x6C, 0x30, 0x65, 0x54, 0x41, 0x65, 0x46, 0x77, 0x30, ++ 0x78, 0x4E, 0x7A, 0x41, 0x34, 0x4D, 0x54, 0x67, 0x77, 0x4F, 0x44, 0x55, 0x34, 0x0A, 0x4E, 0x44, 0x4A, 0x61, 0x46, 0x77, 0x30, 0x7A, 0x4E, 0x7A, 0x41, 0x34, 0x4D, 0x54, 0x67, 0x79, 0x4D, 0x7A, 0x55, 0x35, 0x4E, 0x54, 0x6C, 0x61, 0x4D, 0x47, ++ 0x6B, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6B, 0x74, 0x53, 0x4D, 0x53, 0x59, 0x77, 0x4A, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x44, 0x42, 0x31, 0x4F, 0x51, 0x56, 0x5A, 0x46, 0x55, 0x69, ++ 0x42, 0x43, 0x56, 0x56, 0x4E, 0x4A, 0x54, 0x6B, 0x56, 0x54, 0x0A, 0x55, 0x79, 0x42, 0x51, 0x54, 0x45, 0x46, 0x55, 0x52, 0x6B, 0x39, 0x53, 0x54, 0x53, 0x42, 0x44, 0x62, 0x33, 0x4A, 0x77, 0x4C, 0x6A, 0x45, 0x79, 0x4D, 0x44, 0x41, 0x47, 0x41, ++ 0x31, 0x55, 0x45, 0x41, 0x77, 0x77, 0x70, 0x54, 0x6B, 0x46, 0x57, 0x52, 0x56, 0x49, 0x67, 0x52, 0x32, 0x78, 0x76, 0x59, 0x6D, 0x46, 0x73, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x32, 0x56, 0x79, 0x64, 0x47, 0x6C, 0x6D, 0x61, ++ 0x57, 0x4E, 0x68, 0x64, 0x47, 0x6C, 0x76, 0x0A, 0x62, 0x69, 0x42, 0x42, 0x64, 0x58, 0x52, 0x6F, 0x62, 0x33, 0x4A, 0x70, 0x64, 0x48, 0x6B, 0x77, 0x67, 0x67, 0x49, 0x69, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, ++ 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x49, 0x4B, 0x41, 0x6F, 0x49, 0x43, 0x41, 0x51, 0x43, 0x32, 0x31, 0x50, 0x47, 0x54, 0x58, 0x4C, 0x56, 0x41, 0x69, 0x51, 0x71, 0x72, ++ 0x44, 0x5A, 0x42, 0x62, 0x0A, 0x55, 0x47, 0x4F, 0x75, 0x6B, 0x4A, 0x52, 0x30, 0x46, 0x30, 0x56, 0x79, 0x31, 0x6E, 0x74, 0x6C, 0x57, 0x69, 0x6C, 0x4C, 0x70, 0x31, 0x61, 0x67, 0x53, 0x37, 0x67, 0x76, 0x51, 0x6E, 0x58, 0x70, 0x32, 0x58, 0x73, ++ 0x6B, 0x57, 0x6A, 0x46, 0x6C, 0x71, 0x78, 0x63, 0x58, 0x30, 0x54, 0x4D, 0x36, 0x32, 0x52, 0x48, 0x63, 0x51, 0x44, 0x61, 0x48, 0x33, 0x38, 0x64, 0x71, 0x36, 0x53, 0x5A, 0x65, 0x57, 0x59, 0x70, 0x33, 0x34, 0x2B, 0x68, 0x49, 0x6E, 0x44, 0x45, ++ 0x57, 0x0A, 0x2B, 0x6A, 0x36, 0x52, 0x73, 0x63, 0x72, 0x4A, 0x6F, 0x2B, 0x4B, 0x66, 0x7A, 0x69, 0x46, 0x54, 0x6F, 0x77, 0x49, 0x32, 0x4D, 0x4D, 0x74, 0x53, 0x41, 0x75, 0x58, 0x61, 0x4D, 0x6C, 0x33, 0x44, 0x78, 0x65, 0x62, 0x35, 0x37, 0x68, ++ 0x48, 0x48, 0x69, 0x38, 0x6C, 0x45, 0x48, 0x6F, 0x53, 0x54, 0x47, 0x45, 0x71, 0x30, 0x6E, 0x2B, 0x55, 0x53, 0x5A, 0x47, 0x6E, 0x51, 0x4A, 0x6F, 0x56, 0x69, 0x41, 0x62, 0x62, 0x4A, 0x41, 0x68, 0x32, 0x2B, 0x67, 0x31, 0x47, 0x37, 0x0A, 0x58, ++ 0x4E, 0x72, 0x34, 0x72, 0x52, 0x56, 0x71, 0x6D, 0x66, 0x65, 0x53, 0x56, 0x50, 0x63, 0x30, 0x57, 0x2B, 0x6D, 0x2F, 0x36, 0x69, 0x6D, 0x42, 0x45, 0x74, 0x52, 0x54, 0x6B, 0x5A, 0x61, 0x7A, 0x6B, 0x56, 0x72, 0x64, 0x2F, 0x70, 0x42, 0x7A, 0x4B, ++ 0x50, 0x73, 0x77, 0x52, 0x72, 0x58, 0x4B, 0x43, 0x41, 0x66, 0x48, 0x63, 0x58, 0x4C, 0x4A, 0x5A, 0x74, 0x4D, 0x30, 0x6C, 0x2F, 0x61, 0x4D, 0x39, 0x42, 0x68, 0x4B, 0x34, 0x64, 0x41, 0x39, 0x57, 0x6B, 0x57, 0x32, 0x0A, 0x61, 0x61, 0x63, 0x70, ++ 0x2B, 0x79, 0x50, 0x4F, 0x69, 0x4E, 0x67, 0x53, 0x6E, 0x41, 0x42, 0x49, 0x71, 0x4B, 0x59, 0x50, 0x73, 0x7A, 0x75, 0x53, 0x6A, 0x58, 0x45, 0x4F, 0x64, 0x4D, 0x57, 0x4C, 0x79, 0x45, 0x7A, 0x35, 0x39, 0x4A, 0x75, 0x4F, 0x75, 0x44, 0x78, 0x70, ++ 0x37, 0x57, 0x38, 0x37, 0x55, 0x43, 0x39, 0x59, 0x37, 0x63, 0x53, 0x77, 0x30, 0x42, 0x77, 0x62, 0x61, 0x67, 0x7A, 0x69, 0x76, 0x45, 0x53, 0x71, 0x32, 0x4D, 0x30, 0x55, 0x58, 0x5A, 0x52, 0x34, 0x0A, 0x59, 0x62, 0x38, 0x4F, 0x62, 0x74, 0x6F, ++ 0x71, 0x76, 0x43, 0x38, 0x4D, 0x43, 0x33, 0x47, 0x6D, 0x73, 0x78, 0x59, 0x2F, 0x6E, 0x4F, 0x62, 0x35, 0x7A, 0x4A, 0x39, 0x54, 0x4E, 0x65, 0x49, 0x44, 0x6F, 0x4B, 0x41, 0x59, 0x76, 0x37, 0x76, 0x78, 0x76, 0x76, 0x54, 0x57, 0x6A, 0x49, 0x63, ++ 0x4E, 0x51, 0x76, 0x63, 0x47, 0x75, 0x66, 0x46, 0x74, 0x37, 0x51, 0x53, 0x55, 0x71, 0x50, 0x36, 0x32, 0x30, 0x77, 0x62, 0x47, 0x51, 0x47, 0x48, 0x66, 0x6E, 0x5A, 0x33, 0x7A, 0x0A, 0x56, 0x48, 0x62, 0x4F, 0x55, 0x7A, 0x6F, 0x42, 0x70, 0x70, ++ 0x4A, 0x42, 0x37, 0x41, 0x53, 0x6A, 0x6A, 0x77, 0x32, 0x69, 0x31, 0x51, 0x6E, 0x4B, 0x31, 0x73, 0x75, 0x61, 0x38, 0x65, 0x39, 0x44, 0x58, 0x63, 0x43, 0x72, 0x70, 0x55, 0x48, 0x50, 0x58, 0x46, 0x4E, 0x77, 0x63, 0x4D, 0x6D, 0x49, 0x70, 0x69, ++ 0x33, 0x55, 0x61, 0x32, 0x46, 0x7A, 0x55, 0x43, 0x61, 0x47, 0x59, 0x51, 0x35, 0x66, 0x47, 0x38, 0x49, 0x72, 0x34, 0x6F, 0x7A, 0x56, 0x75, 0x35, 0x33, 0x42, 0x0A, 0x41, 0x30, 0x4B, 0x36, 0x6C, 0x4E, 0x70, 0x66, 0x71, 0x62, 0x44, 0x4B, 0x7A, ++ 0x45, 0x30, 0x4B, 0x37, 0x30, 0x64, 0x70, 0x41, 0x79, 0x38, 0x69, 0x2B, 0x2F, 0x45, 0x6F, 0x7A, 0x72, 0x39, 0x64, 0x55, 0x47, 0x57, 0x6F, 0x6B, 0x47, 0x32, 0x7A, 0x64, 0x4C, 0x41, 0x49, 0x78, 0x36, 0x79, 0x6F, 0x30, 0x65, 0x73, 0x2B, 0x6E, ++ 0x50, 0x78, 0x64, 0x47, 0x6F, 0x4D, 0x75, 0x4B, 0x38, 0x75, 0x31, 0x38, 0x30, 0x53, 0x64, 0x4F, 0x71, 0x63, 0x58, 0x59, 0x5A, 0x61, 0x69, 0x0A, 0x63, 0x64, 0x4E, 0x77, 0x6C, 0x68, 0x56, 0x4E, 0x74, 0x30, 0x78, 0x7A, 0x37, 0x68, 0x6C, 0x63, ++ 0x78, 0x56, 0x73, 0x2B, 0x51, 0x66, 0x36, 0x73, 0x64, 0x57, 0x41, 0x37, 0x47, 0x32, 0x50, 0x4F, 0x41, 0x4E, 0x33, 0x61, 0x43, 0x4A, 0x42, 0x69, 0x74, 0x4F, 0x55, 0x74, 0x37, 0x6B, 0x69, 0x6E, 0x61, 0x78, 0x65, 0x5A, 0x56, 0x4C, 0x36, 0x48, ++ 0x53, 0x75, 0x4F, 0x70, 0x58, 0x67, 0x52, 0x4D, 0x36, 0x78, 0x42, 0x74, 0x56, 0x4E, 0x62, 0x76, 0x38, 0x65, 0x6A, 0x79, 0x0A, 0x59, 0x68, 0x62, 0x4C, 0x67, 0x47, 0x76, 0x74, 0x50, 0x65, 0x33, 0x31, 0x48, 0x7A, 0x43, 0x6C, 0x72, 0x6B, 0x76, ++ 0x4A, 0x45, 0x2B, 0x32, 0x4B, 0x41, 0x51, 0x48, 0x4A, 0x75, 0x46, 0x46, 0x59, 0x77, 0x47, 0x59, 0x36, 0x73, 0x57, 0x5A, 0x4C, 0x78, 0x4E, 0x55, 0x78, 0x41, 0x6D, 0x4C, 0x70, 0x64, 0x49, 0x51, 0x4D, 0x32, 0x30, 0x31, 0x47, 0x4C, 0x51, 0x49, ++ 0x44, 0x41, 0x51, 0x41, 0x42, 0x6F, 0x30, 0x49, 0x77, 0x51, 0x44, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x0A, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x30, 0x70, 0x2B, 0x49, 0x33, 0x36, 0x48, 0x4E, 0x4C, 0x4C, 0x33, 0x73, 0x39, 0x54, ++ 0x73, 0x42, 0x41, 0x5A, 0x4D, 0x7A, 0x4A, 0x37, 0x4C, 0x72, 0x59, 0x45, 0x73, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x51, 0x44, 0x41, 0x67, 0x45, 0x47, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, ++ 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x0A, 0x41, 0x66, 0x38, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4D, 0x42, 0x51, 0x41, 0x44, 0x67, ++ 0x67, 0x49, 0x42, 0x41, 0x44, 0x4C, 0x4B, 0x67, 0x4C, 0x4F, 0x64, 0x50, 0x56, 0x51, 0x47, 0x33, 0x64, 0x4C, 0x53, 0x4C, 0x76, 0x43, 0x6B, 0x41, 0x53, 0x45, 0x4C, 0x5A, 0x30, 0x6A, 0x4B, 0x62, 0x59, 0x37, 0x67, 0x79, 0x4B, 0x6F, 0x4E, 0x71, ++ 0x6F, 0x30, 0x68, 0x56, 0x34, 0x2F, 0x47, 0x50, 0x6E, 0x72, 0x4B, 0x0A, 0x32, 0x31, 0x48, 0x55, 0x55, 0x72, 0x50, 0x55, 0x6C, 0x6F, 0x53, 0x6C, 0x57, 0x47, 0x42, 0x2F, 0x35, 0x51, 0x75, 0x4F, 0x48, 0x2F, 0x58, 0x63, 0x43, 0x68, 0x57, 0x42, ++ 0x35, 0x54, 0x75, 0x32, 0x74, 0x79, 0x49, 0x76, 0x43, 0x5A, 0x77, 0x54, 0x46, 0x72, 0x46, 0x73, 0x44, 0x44, 0x55, 0x49, 0x62, 0x61, 0x74, 0x6A, 0x63, 0x75, 0x33, 0x63, 0x76, 0x75, 0x7A, 0x48, 0x56, 0x2B, 0x59, 0x77, 0x49, 0x48, 0x48, 0x57, ++ 0x31, 0x78, 0x44, 0x42, 0x45, 0x31, 0x55, 0x42, 0x0A, 0x6A, 0x43, 0x70, 0x44, 0x35, 0x45, 0x48, 0x78, 0x7A, 0x7A, 0x70, 0x36, 0x55, 0x35, 0x4C, 0x4F, 0x6F, 0x67, 0x4D, 0x46, 0x44, 0x54, 0x6A, 0x66, 0x41, 0x72, 0x73, 0x51, 0x4C, 0x74, 0x6B, ++ 0x37, 0x30, 0x70, 0x74, 0x36, 0x77, 0x4B, 0x47, 0x6D, 0x2B, 0x4C, 0x55, 0x78, 0x35, 0x76, 0x52, 0x31, 0x79, 0x62, 0x6C, 0x54, 0x6D, 0x58, 0x56, 0x48, 0x49, 0x6C, 0x6F, 0x55, 0x46, 0x63, 0x64, 0x34, 0x47, 0x37, 0x61, 0x64, 0x36, 0x51, 0x7A, ++ 0x34, 0x47, 0x33, 0x62, 0x78, 0x0A, 0x68, 0x59, 0x54, 0x65, 0x6F, 0x64, 0x6F, 0x53, 0x37, 0x36, 0x54, 0x69, 0x45, 0x4A, 0x64, 0x36, 0x65, 0x4E, 0x34, 0x4D, 0x55, 0x5A, 0x65, 0x6F, 0x49, 0x55, 0x43, 0x4C, 0x68, 0x72, 0x30, 0x4E, 0x38, 0x46, ++ 0x35, 0x4F, 0x53, 0x7A, 0x61, 0x37, 0x4F, 0x79, 0x41, 0x66, 0x69, 0x6B, 0x4A, 0x57, 0x34, 0x51, 0x73, 0x61, 0x76, 0x33, 0x76, 0x51, 0x49, 0x6B, 0x4D, 0x73, 0x52, 0x49, 0x7A, 0x37, 0x35, 0x53, 0x71, 0x30, 0x62, 0x42, 0x77, 0x63, 0x75, 0x70, ++ 0x54, 0x67, 0x0A, 0x45, 0x33, 0x34, 0x68, 0x35, 0x70, 0x72, 0x43, 0x79, 0x38, 0x56, 0x43, 0x5A, 0x4C, 0x51, 0x65, 0x6C, 0x48, 0x73, 0x49, 0x4A, 0x63, 0x68, 0x78, 0x7A, 0x49, 0x64, 0x46, 0x56, 0x34, 0x58, 0x54, 0x6E, 0x79, 0x6C, 0x69, 0x49, ++ 0x6F, 0x4E, 0x52, 0x6C, 0x77, 0x41, 0x59, 0x6C, 0x33, 0x64, 0x71, 0x6D, 0x4A, 0x4C, 0x4A, 0x66, 0x47, 0x42, 0x73, 0x33, 0x32, 0x78, 0x39, 0x53, 0x75, 0x52, 0x77, 0x54, 0x4D, 0x4B, 0x65, 0x75, 0x42, 0x33, 0x33, 0x30, 0x44, 0x54, 0x48, 0x0A, ++ 0x44, 0x38, 0x7A, 0x37, 0x70, 0x2F, 0x38, 0x44, 0x76, 0x71, 0x31, 0x77, 0x6B, 0x4E, 0x6F, 0x4C, 0x33, 0x63, 0x68, 0x74, 0x6C, 0x31, 0x2B, 0x61, 0x66, 0x77, 0x6B, 0x79, 0x51, 0x66, 0x33, 0x4E, 0x6F, 0x73, 0x78, 0x61, 0x62, 0x55, 0x7A, 0x79, ++ 0x71, 0x6B, 0x6E, 0x2B, 0x5A, 0x76, 0x6A, 0x70, 0x32, 0x44, 0x58, 0x72, 0x44, 0x69, 0x67, 0x65, 0x37, 0x6B, 0x67, 0x76, 0x4F, 0x74, 0x42, 0x35, 0x43, 0x54, 0x68, 0x38, 0x70, 0x69, 0x4B, 0x43, 0x6B, 0x35, 0x58, 0x51, 0x0A, 0x41, 0x37, 0x36, ++ 0x2B, 0x41, 0x71, 0x41, 0x46, 0x33, 0x53, 0x41, 0x69, 0x34, 0x32, 0x38, 0x64, 0x69, 0x44, 0x52, 0x67, 0x78, 0x75, 0x59, 0x4B, 0x75, 0x51, 0x6C, 0x31, 0x43, 0x2F, 0x41, 0x48, 0x36, 0x47, 0x6D, 0x57, 0x4E, 0x63, 0x66, 0x37, 0x49, 0x34, 0x47, ++ 0x4F, 0x4F, 0x44, 0x6D, 0x34, 0x52, 0x53, 0x74, 0x44, 0x65, 0x4B, 0x4C, 0x52, 0x4C, 0x42, 0x54, 0x2F, 0x44, 0x53, 0x68, 0x79, 0x63, 0x70, 0x57, 0x62, 0x58, 0x67, 0x6E, 0x62, 0x69, 0x55, 0x53, 0x59, 0x0A, 0x71, 0x71, 0x46, 0x4A, 0x75, 0x33, ++ 0x46, 0x53, 0x38, 0x72, 0x2F, 0x32, 0x2F, 0x79, 0x65, 0x68, 0x4E, 0x71, 0x2B, 0x34, 0x74, 0x6E, 0x65, 0x49, 0x33, 0x54, 0x71, 0x6B, 0x62, 0x5A, 0x73, 0x30, 0x6B, 0x4E, 0x77, 0x55, 0x58, 0x54, 0x43, 0x2F, 0x74, 0x2B, 0x73, 0x58, 0x35, 0x49, ++ 0x65, 0x33, 0x63, 0x64, 0x43, 0x68, 0x31, 0x33, 0x63, 0x56, 0x31, 0x45, 0x4C, 0x58, 0x38, 0x76, 0x4D, 0x78, 0x6D, 0x56, 0x32, 0x62, 0x33, 0x52, 0x5A, 0x74, 0x50, 0x2B, 0x6F, 0x47, 0x0A, 0x49, 0x2F, 0x68, 0x47, 0x6F, 0x69, 0x4C, 0x74, 0x6B, ++ 0x2F, 0x62, 0x64, 0x6D, 0x75, 0x59, 0x71, 0x68, 0x37, 0x47, 0x59, 0x56, 0x50, 0x45, 0x69, 0x39, 0x32, 0x74, 0x46, 0x34, 0x2B, 0x4B, 0x4F, 0x64, 0x68, 0x32, 0x61, 0x6A, 0x63, 0x51, 0x47, 0x6A, 0x54, 0x61, 0x33, 0x46, 0x50, 0x4F, 0x64, 0x56, ++ 0x47, 0x6D, 0x33, 0x6A, 0x6A, 0x7A, 0x56, 0x70, 0x47, 0x32, 0x54, 0x67, 0x62, 0x65, 0x74, 0x39, 0x72, 0x31, 0x6B, 0x65, 0x38, 0x4C, 0x4A, 0x61, 0x44, 0x6D, 0x67, 0x0A, 0x6B, 0x70, 0x7A, 0x4E, 0x4E, 0x49, 0x61, 0x52, 0x6B, 0x50, 0x70, 0x6B, ++ 0x55, 0x5A, 0x33, 0x2B, 0x2F, 0x75, 0x75, 0x6C, 0x39, 0x58, 0x58, 0x65, 0x69, 0x66, 0x64, 0x79, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, ++ 0x2D, 0x2D, 0x0A, 0x0A, 0x41, 0x43, 0x20, 0x52, 0x41, 0x49, 0x5A, 0x20, 0x46, 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, 0x4D, 0x20, 0x53, 0x45, 0x52, 0x56, 0x49, 0x44, 0x4F, 0x52, 0x45, 0x53, 0x20, 0x53, 0x45, 0x47, 0x55, 0x52, 0x4F, 0x53, 0x0A, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, ++ 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x43, 0x62, 0x6A, 0x43, 0x43, 0x41, 0x66, 0x4F, 0x67, 0x41, 0x77, 0x49, 0x42, ++ 0x41, 0x67, 0x49, 0x51, 0x59, 0x76, 0x59, 0x79, 0x62, 0x4F, 0x58, 0x45, 0x34, 0x32, 0x68, 0x63, 0x47, 0x32, 0x4C, 0x64, 0x6E, 0x43, 0x36, 0x64, 0x6C, 0x54, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, ++ 0x41, 0x7A, 0x42, 0x34, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x46, 0x0A, 0x55, 0x7A, 0x45, 0x52, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, 0x49, 0x52, 0x6B, 0x35, ++ 0x4E, 0x56, 0x43, 0x31, 0x53, 0x51, 0x30, 0x30, 0x78, 0x44, 0x6A, 0x41, 0x4D, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x73, 0x4D, 0x42, 0x55, 0x4E, 0x6C, 0x63, 0x6D, 0x56, 0x7A, 0x4D, 0x52, 0x67, 0x77, 0x46, 0x67, 0x59, 0x44, 0x56, 0x51, 0x52, ++ 0x68, 0x44, 0x41, 0x39, 0x57, 0x51, 0x56, 0x52, 0x46, 0x55, 0x79, 0x31, 0x52, 0x4D, 0x6A, 0x67, 0x79, 0x0A, 0x4E, 0x6A, 0x41, 0x77, 0x4E, 0x45, 0x6F, 0x78, 0x4C, 0x44, 0x41, 0x71, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x4D, 0x49, 0x30, ++ 0x46, 0x44, 0x49, 0x46, 0x4A, 0x42, 0x53, 0x56, 0x6F, 0x67, 0x52, 0x6B, 0x35, 0x4E, 0x56, 0x43, 0x31, 0x53, 0x51, 0x30, 0x30, 0x67, 0x55, 0x30, 0x56, 0x53, 0x56, 0x6B, 0x6C, 0x45, 0x54, 0x31, 0x4A, 0x46, 0x55, 0x79, 0x42, 0x54, 0x52, 0x55, ++ 0x64, 0x56, 0x55, 0x6B, 0x39, 0x54, 0x4D, 0x42, 0x34, 0x58, 0x44, 0x54, 0x45, 0x34, 0x0A, 0x4D, 0x54, 0x49, 0x79, 0x4D, 0x44, 0x41, 0x35, 0x4D, 0x7A, 0x63, 0x7A, 0x4D, 0x31, 0x6F, 0x58, 0x44, 0x54, 0x51, 0x7A, 0x4D, 0x54, 0x49, 0x79, 0x4D, ++ 0x44, 0x41, 0x35, 0x4D, 0x7A, 0x63, 0x7A, 0x4D, 0x31, 0x6F, 0x77, 0x65, 0x44, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x52, 0x56, 0x4D, 0x78, 0x45, 0x54, 0x41, 0x50, 0x42, 0x67, 0x4E, 0x56, 0x42, ++ 0x41, 0x6F, 0x4D, 0x43, 0x45, 0x5A, 0x4F, 0x54, 0x56, 0x51, 0x74, 0x0A, 0x55, 0x6B, 0x4E, 0x4E, 0x4D, 0x51, 0x34, 0x77, 0x44, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4C, 0x44, 0x41, 0x56, 0x44, 0x5A, 0x58, 0x4A, 0x6C, 0x63, 0x7A, 0x45, 0x59, ++ 0x4D, 0x42, 0x59, 0x47, 0x41, 0x31, 0x55, 0x45, 0x59, 0x51, 0x77, 0x50, 0x56, 0x6B, 0x46, 0x55, 0x52, 0x56, 0x4D, 0x74, 0x55, 0x54, 0x49, 0x34, 0x4D, 0x6A, 0x59, 0x77, 0x4D, 0x44, 0x52, 0x4B, 0x4D, 0x53, 0x77, 0x77, 0x4B, 0x67, 0x59, 0x44, ++ 0x56, 0x51, 0x51, 0x44, 0x44, 0x43, 0x4E, 0x42, 0x0A, 0x51, 0x79, 0x42, 0x53, 0x51, 0x55, 0x6C, 0x61, 0x49, 0x45, 0x5A, 0x4F, 0x54, 0x56, 0x51, 0x74, 0x55, 0x6B, 0x4E, 0x4E, 0x49, 0x46, 0x4E, 0x46, 0x55, 0x6C, 0x5A, 0x4A, 0x52, 0x45, 0x39, ++ 0x53, 0x52, 0x56, 0x4D, 0x67, 0x55, 0x30, 0x56, 0x48, 0x56, 0x56, 0x4A, 0x50, 0x55, 0x7A, 0x42, 0x32, 0x4D, 0x42, 0x41, 0x47, 0x42, 0x79, 0x71, 0x47, 0x53, 0x4D, 0x34, 0x39, 0x41, 0x67, 0x45, 0x47, 0x42, 0x53, 0x75, 0x42, 0x42, 0x41, 0x41, ++ 0x69, 0x41, 0x32, 0x49, 0x41, 0x0A, 0x42, 0x50, 0x61, 0x36, 0x56, 0x31, 0x50, 0x49, 0x79, 0x71, 0x76, 0x66, 0x4E, 0x6B, 0x70, 0x53, 0x49, 0x65, 0x53, 0x58, 0x30, 0x6F, 0x4E, 0x6E, 0x6E, 0x76, 0x42, 0x6C, 0x55, 0x64, 0x42, 0x65, 0x68, 0x38, ++ 0x64, 0x48, 0x73, 0x56, 0x6E, 0x79, 0x56, 0x30, 0x65, 0x62, 0x41, 0x41, 0x4B, 0x54, 0x52, 0x42, 0x64, 0x70, 0x32, 0x30, 0x4C, 0x48, 0x73, 0x62, 0x49, 0x36, 0x47, 0x41, 0x36, 0x30, 0x58, 0x59, 0x79, 0x7A, 0x5A, 0x6C, 0x32, 0x68, 0x4E, 0x50, ++ 0x6B, 0x32, 0x0A, 0x4C, 0x45, 0x6E, 0x62, 0x38, 0x30, 0x62, 0x38, 0x73, 0x30, 0x52, 0x70, 0x52, 0x42, 0x4E, 0x6D, 0x2F, 0x64, 0x66, 0x46, 0x2F, 0x61, 0x38, 0x32, 0x54, 0x63, 0x34, 0x44, 0x54, 0x51, 0x64, 0x78, 0x7A, 0x36, 0x39, 0x71, 0x42, ++ 0x64, 0x4B, 0x69, 0x51, 0x31, 0x6F, 0x4B, 0x55, 0x6D, 0x38, 0x42, 0x41, 0x30, 0x36, 0x4F, 0x69, 0x36, 0x4E, 0x43, 0x4D, 0x45, 0x41, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x0A, ++ 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x51, 0x59, 0x77, 0x48, 0x51, 0x59, 0x44, 0x56, 0x52, 0x30, 0x4F, 0x42, 0x42, 0x59, 0x45, ++ 0x46, 0x41, 0x47, 0x35, 0x4C, 0x2B, 0x2B, 0x2F, 0x45, 0x59, 0x5A, 0x67, 0x38, 0x6B, 0x2F, 0x51, 0x51, 0x57, 0x36, 0x72, 0x63, 0x78, 0x2F, 0x6E, 0x30, 0x6D, 0x35, 0x4A, 0x4D, 0x41, 0x6F, 0x47, 0x43, 0x43, 0x71, 0x47, 0x0A, 0x53, 0x4D, 0x34, ++ 0x39, 0x42, 0x41, 0x4D, 0x44, 0x41, 0x32, 0x6B, 0x41, 0x4D, 0x47, 0x59, 0x43, 0x4D, 0x51, 0x43, 0x75, 0x53, 0x75, 0x4D, 0x72, 0x51, 0x4D, 0x4E, 0x30, 0x45, 0x66, 0x4B, 0x56, 0x72, 0x52, 0x59, 0x6A, 0x33, 0x6B, 0x34, 0x4D, 0x47, 0x75, 0x5A, ++ 0x64, 0x70, 0x53, 0x52, 0x65, 0x61, 0x30, 0x52, 0x37, 0x2F, 0x44, 0x6A, 0x69, 0x54, 0x38, 0x75, 0x63, 0x52, 0x52, 0x63, 0x52, 0x54, 0x42, 0x51, 0x6E, 0x4A, 0x6C, 0x55, 0x35, 0x64, 0x55, 0x6F, 0x44, 0x0A, 0x7A, 0x42, 0x4F, 0x51, 0x6E, 0x35, ++ 0x49, 0x43, 0x4D, 0x51, 0x44, 0x36, 0x53, 0x6D, 0x78, 0x67, 0x69, 0x48, 0x50, 0x7A, 0x37, 0x72, 0x69, 0x59, 0x59, 0x71, 0x6E, 0x4F, 0x4B, 0x38, 0x4C, 0x5A, 0x69, 0x71, 0x5A, 0x77, 0x4D, 0x52, 0x32, 0x76, 0x73, 0x4A, 0x52, 0x4D, 0x36, 0x30, ++ 0x2F, 0x47, 0x34, 0x39, 0x48, 0x7A, 0x59, 0x71, 0x63, 0x38, 0x2F, 0x35, 0x4D, 0x75, 0x42, 0x31, 0x78, 0x4A, 0x41, 0x57, 0x64, 0x70, 0x45, 0x67, 0x4A, 0x79, 0x76, 0x2B, 0x63, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, ++ 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x34, 0x36, 0x0A, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, ++ 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x57, 0x6A, 0x43, 0x43, 0x41, 0x30, 0x4B, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x53, 0x45, 0x64, 0x4B, 0x37, 0x75, 0x64, 0x63, 0x6A, 0x47, 0x4A, 0x35, 0x41, 0x58, 0x77, ++ 0x71, 0x64, 0x4C, 0x64, 0x44, 0x66, 0x4A, 0x57, 0x66, 0x52, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x44, 0x41, 0x55, 0x41, 0x4D, 0x45, 0x59, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, ++ 0x4E, 0x56, 0x0A, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6B, 0x4A, 0x46, 0x4D, 0x52, 0x6B, 0x77, 0x46, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x45, 0x78, 0x42, 0x48, 0x62, 0x47, 0x39, 0x69, 0x59, 0x57, 0x78, 0x54, 0x61, 0x57, 0x64, 0x75, 0x49, ++ 0x47, 0x35, 0x32, 0x4C, 0x58, 0x4E, 0x68, 0x4D, 0x52, 0x77, 0x77, 0x47, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x4E, 0x48, 0x62, 0x47, 0x39, 0x69, 0x59, 0x57, 0x78, 0x54, 0x61, 0x57, 0x64, 0x75, 0x49, 0x46, 0x4A, 0x76, 0x0A, ++ 0x62, 0x33, 0x51, 0x67, 0x55, 0x6A, 0x51, 0x32, 0x4D, 0x42, 0x34, 0x58, 0x44, 0x54, 0x45, 0x35, 0x4D, 0x44, 0x4D, 0x79, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x46, 0x6F, 0x58, 0x44, 0x54, 0x51, 0x32, 0x4D, 0x44, 0x4D, 0x79, ++ 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x46, 0x6F, 0x77, 0x52, 0x6A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x51, 0x6B, 0x55, 0x78, 0x47, 0x54, 0x41, 0x58, 0x0A, 0x42, 0x67, 0x4E, ++ 0x56, 0x42, 0x41, 0x6F, 0x54, 0x45, 0x45, 0x64, 0x73, 0x62, 0x32, 0x4A, 0x68, 0x62, 0x46, 0x4E, 0x70, 0x5A, 0x32, 0x34, 0x67, 0x62, 0x6E, 0x59, 0x74, 0x63, 0x32, 0x45, 0x78, 0x48, 0x44, 0x41, 0x61, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, ++ 0x54, 0x45, 0x30, 0x64, 0x73, 0x62, 0x32, 0x4A, 0x68, 0x62, 0x46, 0x4E, 0x70, 0x5A, 0x32, 0x34, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x53, 0x4E, 0x44, 0x59, 0x77, 0x67, 0x67, 0x49, 0x69, 0x0A, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, ++ 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x49, 0x4B, 0x41, 0x6F, 0x49, 0x43, 0x41, 0x51, 0x43, 0x73, 0x72, 0x48, 0x51, 0x79, 0x36, 0x4C, ++ 0x4E, 0x6C, 0x35, 0x62, 0x72, 0x74, 0x51, 0x79, 0x59, 0x64, 0x70, 0x6F, 0x6B, 0x4E, 0x52, 0x62, 0x6F, 0x70, 0x69, 0x4C, 0x4B, 0x6B, 0x48, 0x57, 0x50, 0x64, 0x30, 0x38, 0x45, 0x73, 0x0A, 0x43, 0x56, 0x65, 0x4A, 0x4F, 0x61, 0x46, 0x56, 0x36, ++ 0x57, 0x63, 0x30, 0x64, 0x77, 0x78, 0x75, 0x35, 0x46, 0x55, 0x64, 0x55, 0x69, 0x58, 0x53, 0x45, 0x32, 0x74, 0x65, 0x34, 0x52, 0x32, 0x70, 0x74, 0x33, 0x32, 0x4A, 0x4D, 0x6C, 0x38, 0x4E, 0x6E, 0x70, 0x38, 0x73, 0x65, 0x6D, 0x4E, 0x67, 0x51, ++ 0x42, 0x2B, 0x6D, 0x73, 0x4C, 0x5A, 0x34, 0x6A, 0x35, 0x6C, 0x55, 0x6C, 0x67, 0x68, 0x59, 0x72, 0x75, 0x51, 0x47, 0x76, 0x47, 0x49, 0x46, 0x41, 0x68, 0x61, 0x2F, 0x0A, 0x72, 0x36, 0x67, 0x6A, 0x41, 0x37, 0x61, 0x55, 0x44, 0x37, 0x78, 0x75, ++ 0x62, 0x4D, 0x4C, 0x4C, 0x31, 0x61, 0x61, 0x37, 0x44, 0x4F, 0x6E, 0x32, 0x77, 0x51, 0x4C, 0x37, 0x49, 0x64, 0x35, 0x6D, 0x33, 0x52, 0x65, 0x72, 0x64, 0x45, 0x4C, 0x76, 0x38, 0x48, 0x51, 0x76, 0x4A, 0x66, 0x54, 0x71, 0x61, 0x31, 0x56, 0x62, ++ 0x6B, 0x4E, 0x75, 0x64, 0x33, 0x31, 0x36, 0x48, 0x43, 0x6B, 0x44, 0x37, 0x72, 0x52, 0x6C, 0x72, 0x2B, 0x2F, 0x66, 0x4B, 0x59, 0x49, 0x6A, 0x65, 0x0A, 0x32, 0x73, 0x47, 0x50, 0x31, 0x71, 0x37, 0x56, 0x66, 0x39, 0x51, 0x38, 0x67, 0x2B, 0x37, ++ 0x58, 0x46, 0x6B, 0x79, 0x44, 0x52, 0x54, 0x4E, 0x72, 0x4A, 0x39, 0x43, 0x47, 0x30, 0x42, 0x77, 0x74, 0x61, 0x2F, 0x4F, 0x72, 0x66, 0x66, 0x47, 0x46, 0x71, 0x66, 0x55, 0x6F, 0x30, 0x71, 0x33, 0x76, 0x38, 0x34, 0x52, 0x4C, 0x48, 0x49, 0x66, ++ 0x38, 0x45, 0x36, 0x4D, 0x36, 0x63, 0x71, 0x4A, 0x61, 0x45, 0x53, 0x76, 0x57, 0x4A, 0x33, 0x45, 0x6E, 0x37, 0x59, 0x45, 0x74, 0x0A, 0x62, 0x57, 0x61, 0x42, 0x6B, 0x6F, 0x65, 0x30, 0x47, 0x31, 0x68, 0x36, 0x7A, 0x44, 0x38, 0x4B, 0x2B, 0x6B, ++ 0x5A, 0x50, 0x54, 0x58, 0x68, 0x63, 0x2B, 0x43, 0x74, 0x49, 0x34, 0x77, 0x53, 0x45, 0x79, 0x31, 0x33, 0x32, 0x74, 0x47, 0x71, 0x7A, 0x5A, 0x66, 0x78, 0x43, 0x6E, 0x6C, 0x45, 0x6D, 0x49, 0x79, 0x44, 0x4C, 0x50, 0x52, 0x54, 0x35, 0x67, 0x65, ++ 0x31, 0x6C, 0x46, 0x67, 0x42, 0x50, 0x47, 0x6D, 0x53, 0x58, 0x5A, 0x67, 0x6A, 0x50, 0x6A, 0x48, 0x76, 0x6A, 0x0A, 0x4B, 0x38, 0x43, 0x64, 0x2B, 0x52, 0x54, 0x79, 0x47, 0x2F, 0x46, 0x57, 0x61, 0x68, 0x61, 0x2F, 0x4C, 0x49, 0x57, 0x46, 0x7A, ++ 0x58, 0x67, 0x34, 0x6D, 0x75, 0x74, 0x43, 0x61, 0x67, 0x49, 0x30, 0x47, 0x49, 0x4D, 0x58, 0x54, 0x70, 0x52, 0x57, 0x2B, 0x4C, 0x61, 0x43, 0x74, 0x66, 0x4F, 0x57, 0x33, 0x54, 0x33, 0x7A, 0x76, 0x6E, 0x38, 0x67, 0x64, 0x7A, 0x35, 0x37, 0x47, ++ 0x53, 0x4E, 0x72, 0x4C, 0x4E, 0x52, 0x79, 0x63, 0x30, 0x4E, 0x58, 0x66, 0x65, 0x44, 0x34, 0x0A, 0x31, 0x32, 0x6C, 0x50, 0x46, 0x7A, 0x59, 0x45, 0x2B, 0x63, 0x43, 0x51, 0x59, 0x44, 0x64, 0x46, 0x33, 0x75, 0x59, 0x4D, 0x32, 0x48, 0x53, 0x4E, ++ 0x72, 0x70, 0x79, 0x69, 0x62, 0x58, 0x52, 0x64, 0x51, 0x72, 0x34, 0x47, 0x39, 0x64, 0x6C, 0x6B, 0x62, 0x67, 0x49, 0x51, 0x72, 0x49, 0x6D, 0x77, 0x54, 0x44, 0x73, 0x48, 0x54, 0x55, 0x42, 0x2B, 0x4A, 0x4D, 0x57, 0x4B, 0x6D, 0x49, 0x4A, 0x35, ++ 0x6A, 0x71, 0x53, 0x6E, 0x67, 0x69, 0x43, 0x4E, 0x49, 0x2F, 0x6F, 0x6E, 0x0A, 0x63, 0x63, 0x6E, 0x66, 0x78, 0x6B, 0x46, 0x30, 0x6F, 0x45, 0x33, 0x32, 0x6B, 0x52, 0x62, 0x63, 0x52, 0x6F, 0x78, 0x66, 0x4B, 0x57, 0x4D, 0x78, 0x57, 0x58, 0x45, ++ 0x4D, 0x32, 0x47, 0x2F, 0x43, 0x74, 0x6A, 0x4A, 0x39, 0x2B, 0x2B, 0x5A, 0x64, 0x55, 0x36, 0x5A, 0x2B, 0x46, 0x66, 0x79, 0x37, 0x64, 0x58, 0x78, 0x64, 0x37, 0x50, 0x6A, 0x32, 0x46, 0x78, 0x7A, 0x73, 0x78, 0x32, 0x73, 0x5A, 0x79, 0x2F, 0x4E, ++ 0x37, 0x38, 0x43, 0x73, 0x48, 0x70, 0x64, 0x6C, 0x73, 0x0A, 0x65, 0x56, 0x52, 0x32, 0x62, 0x4A, 0x30, 0x63, 0x70, 0x6D, 0x34, 0x4F, 0x36, 0x58, 0x6B, 0x4D, 0x71, 0x43, 0x4E, 0x71, 0x6F, 0x39, 0x38, 0x62, 0x4D, 0x44, 0x47, 0x66, 0x73, 0x56, ++ 0x52, 0x37, 0x2F, 0x6D, 0x72, 0x4C, 0x5A, 0x71, 0x72, 0x63, 0x5A, 0x64, 0x43, 0x69, 0x6E, 0x6B, 0x71, 0x61, 0x42, 0x79, 0x46, 0x72, 0x67, 0x59, 0x2F, 0x62, 0x78, 0x46, 0x6E, 0x36, 0x33, 0x69, 0x4C, 0x41, 0x42, 0x4A, 0x7A, 0x6A, 0x71, 0x6C, ++ 0x73, 0x32, 0x6B, 0x2B, 0x67, 0x39, 0x0A, 0x76, 0x58, 0x71, 0x68, 0x6E, 0x51, 0x74, 0x32, 0x73, 0x51, 0x76, 0x48, 0x6E, 0x66, 0x33, 0x50, 0x6D, 0x4B, 0x67, 0x47, 0x77, 0x76, 0x67, 0x71, 0x6F, 0x36, 0x47, 0x44, 0x6F, 0x4C, 0x63, 0x6C, 0x63, ++ 0x71, 0x55, 0x43, 0x34, 0x77, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x6F, 0x30, 0x49, 0x77, 0x51, 0x44, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x59, 0x59, 0x77, 0x44, ++ 0x77, 0x59, 0x44, 0x0A, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x41, 0x31, 0x79, 0x72, ++ 0x63, 0x34, 0x47, 0x48, 0x71, 0x4D, 0x79, 0x77, 0x70, 0x74, 0x57, 0x55, 0x34, 0x6A, 0x61, 0x57, 0x53, 0x66, 0x38, 0x46, 0x6D, 0x53, 0x77, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4D, ++ 0x0A, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x42, 0x41, 0x48, 0x78, 0x34, 0x37, 0x50, 0x59, 0x43, 0x4C, 0x4C, 0x74, 0x62, 0x66, 0x70, 0x49, 0x72, 0x58, 0x54, 0x6E, 0x63, 0x76, 0x74, 0x67, 0x64, 0x6F, 0x6B, 0x49, 0x7A, 0x54, 0x66, 0x6E, ++ 0x76, 0x70, 0x43, 0x6F, 0x37, 0x52, 0x47, 0x6B, 0x65, 0x72, 0x4E, 0x6C, 0x46, 0x6F, 0x30, 0x34, 0x38, 0x70, 0x39, 0x67, 0x6B, 0x55, 0x62, 0x4A, 0x55, 0x48, 0x4A, 0x4E, 0x4F, 0x78, 0x4F, 0x39, 0x37, 0x6B, 0x34, 0x56, 0x67, 0x0A, 0x4A, 0x75, ++ 0x6F, 0x4A, 0x53, 0x4F, 0x44, 0x31, 0x75, 0x38, 0x66, 0x70, 0x61, 0x4E, 0x4B, 0x37, 0x61, 0x6A, 0x46, 0x78, 0x7A, 0x48, 0x6D, 0x75, 0x45, 0x61, 0x6A, 0x77, 0x6D, 0x66, 0x33, 0x6C, 0x48, 0x37, 0x77, 0x76, 0x71, 0x4D, 0x78, 0x58, 0x36, 0x33, ++ 0x62, 0x45, 0x49, 0x61, 0x5A, 0x48, 0x55, 0x31, 0x56, 0x4E, 0x61, 0x4C, 0x38, 0x46, 0x70, 0x4F, 0x37, 0x58, 0x4A, 0x71, 0x74, 0x69, 0x32, 0x6B, 0x4D, 0x33, 0x53, 0x2B, 0x4C, 0x47, 0x74, 0x65, 0x57, 0x79, 0x0A, 0x67, 0x78, 0x6B, 0x36, 0x78, ++ 0x39, 0x50, 0x62, 0x54, 0x5A, 0x34, 0x49, 0x65, 0x76, 0x50, 0x75, 0x7A, 0x7A, 0x35, 0x69, 0x2B, 0x36, 0x7A, 0x6F, 0x59, 0x4D, 0x7A, 0x52, 0x78, 0x36, 0x46, 0x63, 0x67, 0x30, 0x58, 0x45, 0x52, 0x63, 0x7A, 0x7A, 0x46, 0x32, 0x73, 0x55, 0x79, ++ 0x51, 0x51, 0x43, 0x50, 0x74, 0x49, 0x6B, 0x70, 0x6E, 0x6E, 0x70, 0x48, 0x73, 0x36, 0x69, 0x35, 0x38, 0x46, 0x5A, 0x46, 0x5A, 0x38, 0x64, 0x34, 0x6B, 0x75, 0x61, 0x50, 0x70, 0x39, 0x32, 0x0A, 0x43, 0x43, 0x31, 0x72, 0x32, 0x4C, 0x70, 0x58, ++ 0x46, 0x4E, 0x71, 0x44, 0x36, 0x76, 0x36, 0x4D, 0x56, 0x65, 0x6E, 0x51, 0x54, 0x71, 0x6E, 0x4D, 0x64, 0x7A, 0x47, 0x78, 0x52, 0x42, 0x46, 0x36, 0x58, 0x4C, 0x45, 0x2B, 0x30, 0x78, 0x52, 0x46, 0x46, 0x52, 0x68, 0x69, 0x4A, 0x42, 0x50, 0x53, ++ 0x79, 0x30, 0x33, 0x4F, 0x58, 0x49, 0x50, 0x42, 0x4E, 0x76, 0x49, 0x51, 0x74, 0x51, 0x36, 0x49, 0x62, 0x62, 0x6A, 0x68, 0x56, 0x70, 0x2B, 0x4A, 0x33, 0x70, 0x5A, 0x6D, 0x0A, 0x4F, 0x55, 0x64, 0x6B, 0x4C, 0x47, 0x35, 0x4E, 0x72, 0x6D, 0x4A, ++ 0x37, 0x76, 0x32, 0x42, 0x30, 0x47, 0x62, 0x68, 0x57, 0x72, 0x4A, 0x4B, 0x73, 0x46, 0x6A, 0x4C, 0x74, 0x72, 0x57, 0x68, 0x56, 0x2F, 0x70, 0x69, 0x36, 0x30, 0x7A, 0x54, 0x65, 0x39, 0x4D, 0x6C, 0x68, 0x77, 0x77, 0x36, 0x47, 0x39, 0x6B, 0x75, ++ 0x45, 0x59, 0x4F, 0x34, 0x4E, 0x65, 0x37, 0x55, 0x79, 0x57, 0x48, 0x6D, 0x52, 0x56, 0x53, 0x79, 0x42, 0x51, 0x37, 0x4E, 0x30, 0x48, 0x33, 0x71, 0x71, 0x0A, 0x4A, 0x5A, 0x34, 0x64, 0x31, 0x36, 0x47, 0x4C, 0x75, 0x63, 0x31, 0x43, 0x4C, 0x67, ++ 0x53, 0x6B, 0x5A, 0x6F, 0x4E, 0x4E, 0x69, 0x54, 0x57, 0x32, 0x62, 0x4B, 0x67, 0x32, 0x53, 0x6E, 0x6B, 0x68, 0x65, 0x43, 0x4C, 0x51, 0x51, 0x72, 0x7A, 0x52, 0x51, 0x44, 0x47, 0x51, 0x6F, 0x62, 0x34, 0x45, 0x7A, 0x38, 0x70, 0x6E, 0x37, 0x66, ++ 0x58, 0x77, 0x67, 0x4E, 0x4E, 0x67, 0x79, 0x59, 0x4D, 0x71, 0x49, 0x67, 0x58, 0x51, 0x42, 0x7A, 0x74, 0x53, 0x76, 0x77, 0x79, 0x65, 0x0A, 0x71, 0x69, 0x76, 0x35, 0x75, 0x2B, 0x59, 0x66, 0x6A, 0x79, 0x57, 0x36, 0x68, 0x59, 0x30, 0x58, 0x48, ++ 0x67, 0x4C, 0x2B, 0x58, 0x56, 0x41, 0x45, 0x56, 0x38, 0x2F, 0x2B, 0x4C, 0x62, 0x7A, 0x76, 0x58, 0x4D, 0x41, 0x61, 0x71, 0x37, 0x61, 0x66, 0x4A, 0x4D, 0x62, 0x66, 0x63, 0x32, 0x68, 0x49, 0x6B, 0x43, 0x77, 0x55, 0x39, 0x44, 0x39, 0x53, 0x47, ++ 0x75, 0x54, 0x53, 0x79, 0x78, 0x54, 0x44, 0x59, 0x57, 0x6E, 0x50, 0x34, 0x76, 0x6B, 0x59, 0x78, 0x62, 0x6F, 0x7A, 0x0A, 0x6E, 0x78, 0x53, 0x6A, 0x42, 0x46, 0x32, 0x35, 0x63, 0x66, 0x65, 0x31, 0x6C, 0x4E, 0x6A, 0x32, 0x4D, 0x38, 0x46, 0x61, ++ 0x77, 0x54, 0x53, 0x4C, 0x66, 0x4A, 0x76, 0x64, 0x6B, 0x7A, 0x72, 0x6E, 0x45, 0x36, 0x4A, 0x77, 0x59, 0x5A, 0x2B, 0x76, 0x6A, 0x2B, 0x76, 0x59, 0x78, 0x58, 0x58, 0x34, 0x4D, 0x32, 0x62, 0x55, 0x64, 0x47, 0x63, 0x36, 0x4E, 0x33, 0x65, 0x63, ++ 0x35, 0x39, 0x32, 0x6B, 0x44, 0x33, 0x5A, 0x44, 0x5A, 0x6F, 0x70, 0x44, 0x38, 0x70, 0x2F, 0x37, 0x0A, 0x44, 0x45, 0x4A, 0x34, 0x59, 0x39, 0x48, 0x69, 0x44, 0x32, 0x39, 0x37, 0x31, 0x4B, 0x45, 0x39, 0x64, 0x4A, 0x65, 0x46, 0x74, 0x30, 0x67, ++ 0x35, 0x51, 0x64, 0x59, 0x67, 0x2F, 0x4E, 0x41, 0x36, 0x73, 0x2F, 0x72, 0x6F, 0x62, 0x38, 0x53, 0x4B, 0x75, 0x6E, 0x45, 0x33, 0x76, 0x6F, 0x75, 0x58, 0x73, 0x58, 0x67, 0x78, 0x54, 0x37, 0x50, 0x6E, 0x74, 0x67, 0x4D, 0x54, 0x7A, 0x6C, 0x53, ++ 0x64, 0x72, 0x69, 0x56, 0x5A, 0x7A, 0x48, 0x38, 0x31, 0x58, 0x77, 0x6A, 0x33, 0x0A, 0x51, 0x45, 0x55, 0x78, 0x65, 0x43, 0x70, 0x36, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, ++ 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x45, 0x34, 0x36, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, ++ 0x49, 0x43, 0x43, 0x7A, 0x43, 0x43, 0x41, 0x5A, 0x47, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x53, 0x45, 0x64, 0x4B, 0x37, 0x75, 0x6A, 0x4E, 0x75, 0x31, 0x4C, 0x7A, 0x6D, 0x4A, 0x47, 0x6A, 0x46, 0x44, 0x59, 0x51, 0x64, 0x6D, 0x4F, ++ 0x68, 0x44, 0x4D, 0x41, 0x6F, 0x47, 0x43, 0x43, 0x71, 0x47, 0x53, 0x4D, 0x34, 0x39, 0x42, 0x41, 0x4D, 0x44, 0x4D, 0x45, 0x59, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x0A, 0x41, 0x6B, 0x4A, 0x46, 0x4D, ++ 0x52, 0x6B, 0x77, 0x46, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x45, 0x78, 0x42, 0x48, 0x62, 0x47, 0x39, 0x69, 0x59, 0x57, 0x78, 0x54, 0x61, 0x57, 0x64, 0x75, 0x49, 0x47, 0x35, 0x32, 0x4C, 0x58, 0x4E, 0x68, 0x4D, 0x52, 0x77, 0x77, 0x47, ++ 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x4E, 0x48, 0x62, 0x47, 0x39, 0x69, 0x59, 0x57, 0x78, 0x54, 0x61, 0x57, 0x64, 0x75, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x0A, 0x52, 0x54, 0x51, 0x32, 0x4D, 0x42, 0x34, 0x58, ++ 0x44, 0x54, 0x45, 0x35, 0x4D, 0x44, 0x4D, 0x79, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x46, 0x6F, 0x58, 0x44, 0x54, 0x51, 0x32, 0x4D, 0x44, 0x4D, 0x79, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x46, 0x6F, 0x77, ++ 0x52, 0x6A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x51, 0x6B, 0x55, 0x78, 0x47, 0x54, 0x41, 0x58, 0x42, 0x67, 0x4E, 0x56, 0x0A, 0x42, 0x41, 0x6F, 0x54, 0x45, 0x45, 0x64, 0x73, 0x62, 0x32, 0x4A, ++ 0x68, 0x62, 0x46, 0x4E, 0x70, 0x5A, 0x32, 0x34, 0x67, 0x62, 0x6E, 0x59, 0x74, 0x63, 0x32, 0x45, 0x78, 0x48, 0x44, 0x41, 0x61, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x45, 0x30, 0x64, 0x73, 0x62, 0x32, 0x4A, 0x68, 0x62, 0x46, 0x4E, ++ 0x70, 0x5A, 0x32, 0x34, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x46, 0x4E, 0x44, 0x59, 0x77, 0x64, 0x6A, 0x41, 0x51, 0x42, 0x67, 0x63, 0x71, 0x0A, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x49, 0x42, 0x42, 0x67, 0x55, 0x72, 0x67, 0x51, ++ 0x51, 0x41, 0x49, 0x67, 0x4E, 0x69, 0x41, 0x41, 0x53, 0x63, 0x44, 0x72, 0x48, 0x50, 0x74, 0x2B, 0x69, 0x65, 0x55, 0x6E, 0x64, 0x31, 0x4E, 0x50, 0x71, 0x6C, 0x52, 0x71, 0x65, 0x74, 0x4D, 0x68, 0x6B, 0x79, 0x74, 0x41, 0x65, 0x70, 0x4A, 0x38, ++ 0x71, 0x55, 0x75, 0x77, 0x7A, 0x53, 0x43, 0x68, 0x44, 0x48, 0x32, 0x6F, 0x6D, 0x77, 0x6C, 0x77, 0x78, 0x77, 0x45, 0x77, 0x6B, 0x42, 0x0A, 0x6A, 0x74, 0x6A, 0x71, 0x52, 0x2B, 0x71, 0x2B, 0x73, 0x6F, 0x41, 0x72, 0x7A, 0x66, 0x77, 0x6F, 0x44, ++ 0x64, 0x75, 0x73, 0x76, 0x4B, 0x53, 0x47, 0x4E, 0x2B, 0x31, 0x77, 0x43, 0x41, 0x42, 0x31, 0x36, 0x70, 0x4D, 0x4C, 0x65, 0x79, 0x35, 0x53, 0x6E, 0x43, 0x4E, 0x6F, 0x49, 0x77, 0x5A, 0x44, 0x37, 0x4A, 0x49, 0x76, 0x55, 0x34, 0x54, 0x62, 0x2B, ++ 0x30, 0x63, 0x55, 0x42, 0x2B, 0x68, 0x66, 0x6C, 0x47, 0x64, 0x64, 0x79, 0x58, 0x71, 0x42, 0x50, 0x43, 0x43, 0x6A, 0x0A, 0x51, 0x6A, 0x42, 0x41, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, ++ 0x41, 0x77, 0x49, 0x42, 0x68, 0x6A, 0x41, 0x50, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x52, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x54, 0x41, 0x44, 0x41, 0x51, 0x48, 0x2F, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, ++ 0x42, 0x42, 0x51, 0x78, 0x43, 0x70, 0x43, 0x50, 0x74, 0x73, 0x61, 0x64, 0x30, 0x6B, 0x52, 0x4C, 0x0A, 0x67, 0x4C, 0x57, 0x69, 0x35, 0x68, 0x2B, 0x78, 0x45, 0x6B, 0x38, 0x62, 0x6C, 0x54, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, ++ 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x77, 0x4E, 0x6F, 0x41, 0x44, 0x42, 0x6C, 0x41, 0x6A, 0x45, 0x41, 0x33, 0x31, 0x53, 0x51, 0x37, 0x5A, 0x76, 0x76, 0x69, 0x35, 0x51, 0x43, 0x6B, 0x78, 0x65, 0x43, 0x6D, 0x62, 0x36, 0x7A, 0x6E, 0x69, 0x7A, ++ 0x32, 0x43, 0x35, 0x47, 0x4D, 0x6E, 0x30, 0x6F, 0x55, 0x73, 0x66, 0x5A, 0x6B, 0x0A, 0x76, 0x4C, 0x74, 0x6F, 0x55, 0x52, 0x4D, 0x4D, 0x41, 0x2F, 0x63, 0x56, 0x69, 0x34, 0x52, 0x67, 0x75, 0x59, 0x76, 0x2F, 0x55, 0x6F, 0x37, 0x6E, 0x6A, 0x4C, ++ 0x77, 0x63, 0x41, 0x6A, 0x41, 0x38, 0x2B, 0x52, 0x48, 0x55, 0x6A, 0x45, 0x37, 0x41, 0x77, 0x57, 0x48, 0x43, 0x46, 0x55, 0x79, 0x71, 0x71, 0x78, 0x30, 0x4C, 0x4D, 0x56, 0x38, 0x37, 0x48, 0x4F, 0x49, 0x41, 0x6C, 0x30, 0x51, 0x78, 0x35, 0x76, ++ 0x35, 0x7A, 0x6C, 0x69, 0x2F, 0x61, 0x6C, 0x74, 0x50, 0x2B, 0x0A, 0x43, 0x41, 0x65, 0x7A, 0x4E, 0x49, 0x6D, 0x38, 0x42, 0x5A, 0x2F, 0x33, 0x48, 0x6F, 0x62, 0x75, 0x69, 0x33, 0x41, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, ++ 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x47, 0x4C, 0x4F, 0x42, 0x41, 0x4C, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x32, 0x30, 0x32, 0x30, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, ++ 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x67, 0x6A, 0x43, 0x43, 0x41, 0x32, 0x71, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x4C, 0x57, 0x6B, 0x75, 0x39, 0x57, 0x76, 0x74, 0x50, 0x69, 0x6C, 0x76, 0x36, 0x5A, 0x65, 0x55, 0x77, 0x44, 0x51, 0x59, ++ 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x42, 0x51, 0x41, 0x77, 0x54, 0x54, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x51, 0x56, 0x51, 0x78, 0x0A, 0x49, 0x7A, ++ 0x41, 0x68, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x47, 0x6D, 0x55, 0x74, 0x59, 0x32, 0x39, 0x74, 0x62, 0x57, 0x56, 0x79, 0x59, 0x32, 0x55, 0x67, 0x62, 0x57, 0x39, 0x75, 0x61, 0x58, 0x52, 0x76, 0x63, 0x6D, 0x6C, 0x75, 0x5A, 0x79, ++ 0x42, 0x48, 0x62, 0x57, 0x4A, 0x49, 0x4D, 0x52, 0x6B, 0x77, 0x46, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x42, 0x48, 0x54, 0x45, 0x39, 0x43, 0x51, 0x55, 0x78, 0x55, 0x55, 0x6C, 0x56, 0x54, 0x0A, 0x56, 0x43, 0x41, 0x79, 0x4D, ++ 0x44, 0x49, 0x77, 0x4D, 0x42, 0x34, 0x58, 0x44, 0x54, 0x49, 0x77, 0x4D, 0x44, 0x49, 0x78, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x46, 0x6F, 0x58, 0x44, 0x54, 0x51, 0x77, 0x4D, 0x44, 0x59, 0x78, 0x4D, 0x44, 0x41, 0x77, 0x4D, ++ 0x44, 0x41, 0x77, 0x4D, 0x46, 0x6F, 0x77, 0x54, 0x54, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x51, 0x56, 0x51, 0x78, 0x49, 0x7A, 0x41, 0x68, 0x0A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, ++ 0x47, 0x6D, 0x55, 0x74, 0x59, 0x32, 0x39, 0x74, 0x62, 0x57, 0x56, 0x79, 0x59, 0x32, 0x55, 0x67, 0x62, 0x57, 0x39, 0x75, 0x61, 0x58, 0x52, 0x76, 0x63, 0x6D, 0x6C, 0x75, 0x5A, 0x79, 0x42, 0x48, 0x62, 0x57, 0x4A, 0x49, 0x4D, 0x52, 0x6B, 0x77, ++ 0x46, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x42, 0x48, 0x54, 0x45, 0x39, 0x43, 0x51, 0x55, 0x78, 0x55, 0x55, 0x6C, 0x56, 0x54, 0x56, 0x43, 0x41, 0x79, 0x0A, 0x4D, 0x44, 0x49, 0x77, 0x4D, 0x49, 0x49, 0x43, 0x49, 0x6A, 0x41, ++ 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x45, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x67, 0x38, 0x41, 0x4D, 0x49, 0x49, 0x43, 0x43, 0x67, 0x4B, 0x43, 0x41, 0x67, 0x45, 0x41, 0x72, 0x69, 0x35, ++ 0x57, 0x72, 0x52, 0x73, 0x63, 0x37, 0x2F, 0x61, 0x56, 0x6A, 0x36, 0x42, 0x33, 0x47, 0x79, 0x76, 0x54, 0x59, 0x34, 0x2B, 0x45, 0x54, 0x55, 0x57, 0x69, 0x0A, 0x44, 0x35, 0x39, 0x62, 0x52, 0x61, 0x74, 0x5A, 0x65, 0x31, 0x45, 0x30, 0x2B, 0x65, ++ 0x79, 0x4C, 0x69, 0x6E, 0x6A, 0x46, 0x33, 0x57, 0x75, 0x76, 0x76, 0x63, 0x54, 0x66, 0x6B, 0x30, 0x55, 0x65, 0x76, 0x35, 0x45, 0x34, 0x43, 0x36, 0x34, 0x4F, 0x46, 0x75, 0x64, 0x42, 0x63, 0x2F, 0x6A, 0x62, 0x75, 0x39, 0x47, 0x34, 0x55, 0x65, ++ 0x44, 0x4C, 0x67, 0x7A, 0x74, 0x7A, 0x4F, 0x47, 0x35, 0x33, 0x69, 0x67, 0x39, 0x5A, 0x59, 0x79, 0x62, 0x4E, 0x70, 0x79, 0x72, 0x4F, 0x0A, 0x56, 0x50, 0x75, 0x34, 0x34, 0x73, 0x42, 0x38, 0x52, 0x38, 0x35, 0x67, 0x66, 0x44, 0x2B, 0x79, 0x63, ++ 0x2F, 0x4C, 0x41, 0x47, 0x62, 0x61, 0x4B, 0x6B, 0x6F, 0x63, 0x31, 0x44, 0x5A, 0x41, 0x6F, 0x6F, 0x75, 0x51, 0x56, 0x42, 0x47, 0x4D, 0x2B, 0x75, 0x71, 0x2F, 0x75, 0x66, 0x46, 0x37, 0x4D, 0x70, 0x6F, 0x74, 0x51, 0x73, 0x6A, 0x6A, 0x33, 0x51, ++ 0x57, 0x50, 0x4B, 0x7A, 0x76, 0x39, 0x70, 0x6A, 0x32, 0x67, 0x4F, 0x6C, 0x54, 0x62, 0x6C, 0x7A, 0x4C, 0x6D, 0x4D, 0x0A, 0x43, 0x63, 0x70, 0x4C, 0x33, 0x54, 0x47, 0x51, 0x6C, 0x73, 0x6A, 0x4D, 0x48, 0x2F, 0x31, 0x57, 0x6C, 0x6A, 0x54, 0x62, ++ 0x6A, 0x68, 0x7A, 0x71, 0x4C, 0x4C, 0x36, 0x46, 0x4C, 0x6D, 0x50, 0x64, 0x71, 0x71, 0x6D, 0x56, 0x30, 0x2F, 0x30, 0x70, 0x6C, 0x52, 0x50, 0x77, 0x79, 0x4A, 0x69, 0x54, 0x32, 0x53, 0x30, 0x57, 0x52, 0x35, 0x41, 0x52, 0x67, 0x36, 0x49, 0x36, ++ 0x49, 0x71, 0x49, 0x6F, 0x56, 0x36, 0x4C, 0x72, 0x2F, 0x73, 0x43, 0x4D, 0x4B, 0x4B, 0x43, 0x6D, 0x0A, 0x66, 0x65, 0x63, 0x71, 0x51, 0x6A, 0x75, 0x43, 0x67, 0x47, 0x4F, 0x6C, 0x59, 0x78, 0x38, 0x5A, 0x7A, 0x48, 0x79, 0x79, 0x5A, 0x71, 0x6A, ++ 0x43, 0x30, 0x32, 0x30, 0x33, 0x62, 0x2B, 0x4A, 0x2B, 0x42, 0x6C, 0x48, 0x5A, 0x52, 0x59, 0x51, 0x66, 0x45, 0x73, 0x34, 0x6B, 0x55, 0x6D, 0x53, 0x46, 0x43, 0x30, 0x69, 0x41, 0x54, 0x6F, 0x65, 0x78, 0x49, 0x69, 0x49, 0x77, 0x71, 0x75, 0x75, ++ 0x75, 0x76, 0x75, 0x41, 0x43, 0x34, 0x45, 0x44, 0x6F, 0x73, 0x45, 0x4B, 0x41, 0x0A, 0x41, 0x31, 0x47, 0x71, 0x74, 0x48, 0x36, 0x71, 0x52, 0x4E, 0x64, 0x44, 0x59, 0x66, 0x4F, 0x69, 0x61, 0x78, 0x61, 0x4A, 0x53, 0x61, 0x53, 0x6A, 0x70, 0x43, ++ 0x75, 0x4B, 0x41, 0x73, 0x52, 0x34, 0x39, 0x47, 0x69, 0x4B, 0x77, 0x65, 0x52, 0x36, 0x4E, 0x72, 0x46, 0x76, 0x47, 0x35, 0x59, 0x62, 0x64, 0x30, 0x6D, 0x4E, 0x31, 0x4D, 0x6B, 0x47, 0x63, 0x6F, 0x2F, 0x50, 0x55, 0x2B, 0x50, 0x63, 0x46, 0x34, ++ 0x55, 0x67, 0x53, 0x74, 0x79, 0x59, 0x4A, 0x39, 0x4F, 0x52, 0x0A, 0x4A, 0x69, 0x74, 0x48, 0x48, 0x6D, 0x6B, 0x48, 0x72, 0x39, 0x36, 0x69, 0x35, 0x4F, 0x54, 0x55, 0x61, 0x77, 0x75, 0x7A, 0x58, 0x6E, 0x7A, 0x55, 0x4A, 0x49, 0x42, 0x48, 0x4B, ++ 0x57, 0x6B, 0x37, 0x62, 0x75, 0x69, 0x73, 0x2F, 0x55, 0x44, 0x72, 0x32, 0x4F, 0x31, 0x78, 0x63, 0x53, 0x76, 0x79, 0x36, 0x46, 0x67, 0x64, 0x36, 0x30, 0x47, 0x58, 0x49, 0x73, 0x55, 0x66, 0x31, 0x44, 0x6E, 0x51, 0x4A, 0x34, 0x2B, 0x48, 0x34, ++ 0x78, 0x6A, 0x30, 0x34, 0x4B, 0x6C, 0x47, 0x0A, 0x44, 0x66, 0x56, 0x30, 0x4F, 0x6F, 0x49, 0x75, 0x30, 0x47, 0x34, 0x73, 0x6B, 0x61, 0x4D, 0x78, 0x58, 0x44, 0x74, 0x47, 0x36, 0x6E, 0x73, 0x45, 0x45, 0x46, 0x5A, 0x65, 0x67, 0x42, 0x33, 0x31, ++ 0x70, 0x57, 0x58, 0x6F, 0x67, 0x76, 0x7A, 0x69, 0x42, 0x34, 0x78, 0x69, 0x52, 0x66, 0x55, 0x67, 0x33, 0x6B, 0x5A, 0x77, 0x68, 0x71, 0x47, 0x38, 0x6B, 0x39, 0x4D, 0x65, 0x64, 0x4B, 0x5A, 0x73, 0x73, 0x43, 0x7A, 0x33, 0x41, 0x77, 0x79, 0x49, ++ 0x44, 0x4D, 0x76, 0x55, 0x0A, 0x63, 0x6C, 0x4F, 0x47, 0x76, 0x47, 0x42, 0x47, 0x38, 0x35, 0x68, 0x71, 0x77, 0x76, 0x47, 0x2F, 0x51, 0x2F, 0x6C, 0x77, 0x49, 0x48, 0x66, 0x4B, 0x4E, 0x30, 0x46, 0x35, 0x56, 0x56, 0x4A, 0x6A, 0x6A, 0x56, 0x73, ++ 0x53, 0x6E, 0x38, 0x56, 0x6F, 0x78, 0x49, 0x69, 0x64, 0x72, 0x50, 0x49, 0x77, 0x71, 0x37, 0x65, 0x6A, 0x4D, 0x5A, 0x64, 0x6E, 0x72, 0x59, 0x38, 0x58, 0x44, 0x32, 0x7A, 0x48, 0x63, 0x2B, 0x30, 0x6B, 0x6C, 0x47, 0x76, 0x49, 0x67, 0x35, 0x72, ++ 0x51, 0x0A, 0x6D, 0x6A, 0x64, 0x4A, 0x42, 0x4B, 0x75, 0x78, 0x46, 0x73, 0x68, 0x73, 0x53, 0x55, 0x6B, 0x74, 0x71, 0x36, 0x48, 0x51, 0x6A, 0x4A, 0x4C, 0x79, 0x51, 0x55, 0x70, 0x35, 0x49, 0x53, 0x58, 0x62, 0x59, 0x39, 0x65, 0x32, 0x6E, 0x4B, ++ 0x64, 0x2B, 0x51, 0x6D, 0x6E, 0x37, 0x4F, 0x6D, 0x4D, 0x43, 0x41, 0x77, 0x45, 0x41, 0x41, 0x61, 0x4E, 0x6A, 0x4D, 0x47, 0x45, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x0A, 0x41, ++ 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x51, 0x59, 0x77, 0x48, 0x51, 0x59, 0x44, 0x56, 0x52, 0x30, 0x4F, 0x42, 0x42, 0x59, 0x45, 0x46, ++ 0x4E, 0x77, 0x75, 0x48, 0x39, 0x46, 0x68, 0x4E, 0x33, 0x6E, 0x6B, 0x71, 0x39, 0x58, 0x56, 0x73, 0x78, 0x4A, 0x78, 0x61, 0x44, 0x31, 0x71, 0x61, 0x4A, 0x77, 0x69, 0x4D, 0x42, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x0A, 0x49, 0x77, 0x51, 0x59, ++ 0x4D, 0x42, 0x61, 0x41, 0x46, 0x4E, 0x77, 0x75, 0x48, 0x39, 0x46, 0x68, 0x4E, 0x33, 0x6E, 0x6B, 0x71, 0x39, 0x58, 0x56, 0x73, 0x78, 0x4A, 0x78, 0x61, 0x44, 0x31, 0x71, 0x61, 0x4A, 0x77, 0x69, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, ++ 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x43, 0x77, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x41, 0x51, 0x43, 0x52, 0x38, 0x45, 0x49, 0x43, 0x61, 0x45, 0x44, 0x75, 0x77, 0x32, 0x6A, 0x41, 0x0A, 0x56, 0x43, 0x2F, 0x66, 0x37, 0x47, 0x4C, ++ 0x44, 0x77, 0x35, 0x36, 0x4B, 0x6F, 0x44, 0x45, 0x6F, 0x71, 0x6F, 0x4F, 0x4F, 0x70, 0x46, 0x61, 0x57, 0x45, 0x68, 0x43, 0x47, 0x56, 0x72, 0x71, 0x58, 0x63, 0x74, 0x4A, 0x55, 0x4D, 0x48, 0x79, 0x74, 0x47, 0x64, 0x55, 0x64, 0x61, 0x47, 0x2F, ++ 0x37, 0x46, 0x45, 0x4C, 0x59, 0x6A, 0x51, 0x37, 0x7A, 0x74, 0x64, 0x47, 0x6C, 0x34, 0x77, 0x4A, 0x43, 0x58, 0x74, 0x7A, 0x6F, 0x52, 0x6C, 0x67, 0x48, 0x4E, 0x51, 0x49, 0x77, 0x0A, 0x34, 0x4C, 0x78, 0x30, 0x53, 0x73, 0x46, 0x44, 0x4B, 0x76, ++ 0x2F, 0x62, 0x47, 0x74, 0x43, 0x77, 0x72, 0x32, 0x7A, 0x44, 0x2F, 0x63, 0x75, 0x7A, 0x39, 0x58, 0x39, 0x74, 0x41, 0x79, 0x35, 0x5A, 0x56, 0x70, 0x30, 0x74, 0x4C, 0x54, 0x57, 0x4D, 0x73, 0x74, 0x5A, 0x44, 0x46, 0x79, 0x79, 0x53, 0x43, 0x73, ++ 0x74, 0x64, 0x36, 0x49, 0x77, 0x50, 0x53, 0x33, 0x42, 0x44, 0x30, 0x49, 0x4C, 0x2F, 0x71, 0x4D, 0x79, 0x2F, 0x70, 0x4A, 0x54, 0x41, 0x76, 0x6F, 0x65, 0x39, 0x0A, 0x69, 0x75, 0x4F, 0x54, 0x65, 0x38, 0x61, 0x50, 0x6D, 0x78, 0x61, 0x64, 0x4A, ++ 0x32, 0x57, 0x38, 0x65, 0x73, 0x56, 0x43, 0x67, 0x6D, 0x78, 0x63, 0x42, 0x39, 0x43, 0x70, 0x77, 0x59, 0x68, 0x67, 0x52, 0x4F, 0x6D, 0x59, 0x68, 0x52, 0x5A, 0x66, 0x2B, 0x49, 0x2F, 0x4B, 0x41, 0x52, 0x44, 0x4F, 0x4A, 0x63, 0x50, 0x35, 0x59, ++ 0x42, 0x75, 0x67, 0x78, 0x5A, 0x66, 0x44, 0x30, 0x79, 0x79, 0x49, 0x4D, 0x61, 0x4B, 0x39, 0x4D, 0x4F, 0x7A, 0x51, 0x30, 0x4D, 0x41, 0x53, 0x0A, 0x38, 0x63, 0x45, 0x35, 0x34, 0x2B, 0x58, 0x31, 0x2B, 0x4E, 0x5A, 0x4B, 0x33, 0x54, 0x54, 0x4E, ++ 0x2B, 0x32, 0x2F, 0x42, 0x54, 0x2B, 0x4D, 0x41, 0x69, 0x31, 0x62, 0x69, 0x6B, 0x76, 0x63, 0x6F, 0x73, 0x6B, 0x4A, 0x33, 0x63, 0x69, 0x4E, 0x6E, 0x78, 0x7A, 0x38, 0x52, 0x46, 0x62, 0x4C, 0x45, 0x41, 0x77, 0x57, 0x2B, 0x75, 0x78, 0x46, 0x37, ++ 0x43, 0x72, 0x2B, 0x6F, 0x62, 0x75, 0x66, 0x2F, 0x57, 0x45, 0x50, 0x50, 0x6D, 0x32, 0x65, 0x67, 0x67, 0x41, 0x65, 0x32, 0x0A, 0x48, 0x63, 0x71, 0x74, 0x62, 0x65, 0x70, 0x42, 0x45, 0x58, 0x34, 0x74, 0x64, 0x4A, 0x50, 0x37, 0x77, 0x72, 0x79, ++ 0x2B, 0x55, 0x55, 0x54, 0x46, 0x37, 0x32, 0x67, 0x6C, 0x4A, 0x34, 0x44, 0x6A, 0x79, 0x4B, 0x44, 0x55, 0x45, 0x75, 0x7A, 0x5A, 0x70, 0x54, 0x63, 0x64, 0x4E, 0x33, 0x79, 0x30, 0x6B, 0x63, 0x72, 0x61, 0x31, 0x4C, 0x47, 0x57, 0x67, 0x65, 0x39, ++ 0x6F, 0x58, 0x48, 0x59, 0x51, 0x53, 0x61, 0x39, 0x2B, 0x70, 0x54, 0x65, 0x41, 0x73, 0x52, 0x78, 0x53, 0x0A, 0x76, 0x54, 0x4F, 0x42, 0x54, 0x49, 0x2F, 0x35, 0x33, 0x57, 0x58, 0x5A, 0x46, 0x4D, 0x32, 0x4B, 0x4A, 0x56, 0x6A, 0x30, 0x34, 0x73, ++ 0x57, 0x44, 0x70, 0x51, 0x6D, 0x51, 0x31, 0x47, 0x77, 0x55, 0x59, 0x37, 0x56, 0x41, 0x33, 0x2B, 0x76, 0x41, 0x2F, 0x4D, 0x52, 0x59, 0x66, 0x67, 0x30, 0x55, 0x46, 0x6F, 0x64, 0x55, 0x4A, 0x32, 0x35, 0x57, 0x35, 0x48, 0x43, 0x45, 0x75, 0x47, ++ 0x77, 0x79, 0x45, 0x6E, 0x36, 0x43, 0x4D, 0x55, 0x4F, 0x2B, 0x31, 0x39, 0x31, 0x38, 0x0A, 0x6F, 0x61, 0x32, 0x75, 0x31, 0x71, 0x73, 0x67, 0x45, 0x75, 0x38, 0x4B, 0x77, 0x78, 0x43, 0x4D, 0x53, 0x5A, 0x59, 0x31, 0x33, 0x41, 0x74, 0x31, 0x58, ++ 0x72, 0x46, 0x50, 0x31, 0x55, 0x38, 0x30, 0x44, 0x68, 0x45, 0x67, 0x42, 0x33, 0x56, 0x44, 0x52, 0x65, 0x6D, 0x6A, 0x45, 0x64, 0x71, 0x73, 0x6F, 0x35, 0x6E, 0x43, 0x74, 0x6E, 0x6B, 0x6E, 0x34, 0x72, 0x6E, 0x76, 0x79, 0x4F, 0x4C, 0x32, 0x4E, ++ 0x53, 0x6C, 0x36, 0x64, 0x50, 0x72, 0x46, 0x66, 0x34, 0x49, 0x46, 0x0A, 0x59, 0x71, 0x59, 0x4B, 0x36, 0x6D, 0x69, 0x79, 0x65, 0x55, 0x63, 0x47, 0x62, 0x76, 0x4A, 0x58, 0x71, 0x42, 0x55, 0x7A, 0x78, 0x76, 0x64, 0x34, 0x53, 0x6A, 0x31, 0x43, ++ 0x65, 0x32, 0x74, 0x2B, 0x2F, 0x76, 0x64, 0x47, 0x36, 0x74, 0x48, 0x72, 0x6A, 0x75, 0x2B, 0x49, 0x61, 0x46, 0x76, 0x6F, 0x77, 0x64, 0x6C, 0x78, 0x66, 0x76, 0x31, 0x6B, 0x37, 0x2F, 0x39, 0x6E, 0x52, 0x34, 0x68, 0x59, 0x4A, 0x53, 0x38, 0x2B, ++ 0x68, 0x67, 0x65, 0x39, 0x2B, 0x36, 0x6A, 0x6C, 0x0A, 0x67, 0x71, 0x69, 0x73, 0x70, 0x64, 0x4E, 0x70, 0x51, 0x38, 0x30, 0x78, 0x69, 0x45, 0x6D, 0x45, 0x55, 0x35, 0x4C, 0x41, 0x73, 0x54, 0x6B, 0x62, 0x4F, 0x59, 0x4D, 0x42, 0x4D, 0x4D, 0x54, ++ 0x79, 0x71, 0x66, 0x72, 0x51, 0x41, 0x37, 0x31, 0x79, 0x4E, 0x32, 0x42, 0x57, 0x48, 0x7A, 0x5A, 0x38, 0x76, 0x54, 0x6D, 0x52, 0x39, 0x57, 0x30, 0x4E, 0x76, 0x33, 0x76, 0x58, 0x6B, 0x67, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, ++ 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x41, 0x4E, 0x46, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x52, ++ 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, ++ 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x37, 0x7A, 0x43, 0x43, 0x41, 0x39, 0x65, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, ++ 0x49, 0x44, 0x64, 0x50, 0x6A, 0x76, 0x47, 0x7A, 0x35, 0x61, 0x37, 0x45, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x42, 0x51, 0x41, 0x77, 0x67, 0x59, 0x51, 0x78, 0x45, 0x6A, 0x41, ++ 0x51, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x55, 0x54, 0x43, 0x55, 0x63, 0x32, 0x4D, 0x7A, 0x49, 0x34, 0x0A, 0x4E, 0x7A, 0x55, 0x78, 0x4D, 0x44, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x52, 0x56, ++ 0x4D, 0x78, 0x4A, 0x7A, 0x41, 0x6C, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x48, 0x6B, 0x46, 0x4F, 0x52, 0x69, 0x42, 0x42, 0x64, 0x58, 0x52, 0x76, 0x63, 0x6D, 0x6C, 0x6B, 0x59, 0x57, 0x51, 0x67, 0x5A, 0x47, 0x55, 0x67, 0x51, 0x32, ++ 0x56, 0x79, 0x64, 0x47, 0x6C, 0x6D, 0x61, 0x57, 0x4E, 0x68, 0x59, 0x32, 0x6C, 0x76, 0x0A, 0x62, 0x6A, 0x45, 0x55, 0x4D, 0x42, 0x49, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x78, 0x4D, 0x4C, 0x51, 0x55, 0x35, 0x47, 0x49, 0x45, 0x4E, 0x42, 0x49, ++ 0x46, 0x4A, 0x68, 0x61, 0x58, 0x6F, 0x78, 0x49, 0x6A, 0x41, 0x67, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x47, 0x55, 0x46, 0x4F, 0x52, 0x69, 0x42, 0x54, 0x5A, 0x57, 0x4E, 0x31, 0x63, 0x6D, 0x55, 0x67, 0x55, 0x32, 0x56, 0x79, 0x64, ++ 0x6D, 0x56, 0x79, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x0A, 0x51, 0x30, 0x45, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x54, 0x6B, 0x77, 0x4F, 0x54, 0x41, 0x30, 0x4D, 0x54, 0x41, 0x77, 0x4D, 0x44, 0x4D, 0x34, 0x57, 0x68, 0x63, 0x4E, ++ 0x4D, 0x7A, 0x6B, 0x77, 0x4F, 0x44, 0x4D, 0x77, 0x4D, 0x54, 0x41, 0x77, 0x4D, 0x44, 0x4D, 0x34, 0x57, 0x6A, 0x43, 0x42, 0x68, 0x44, 0x45, 0x53, 0x4D, 0x42, 0x41, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x52, 0x4D, 0x4A, 0x52, 0x7A, 0x59, 0x7A, ++ 0x4D, 0x6A, 0x67, 0x33, 0x4E, 0x54, 0x45, 0x77, 0x0A, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x46, 0x55, 0x7A, 0x45, 0x6E, 0x4D, 0x43, 0x55, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, ++ 0x65, 0x51, 0x55, 0x35, 0x47, 0x49, 0x45, 0x46, 0x31, 0x64, 0x47, 0x39, 0x79, 0x61, 0x57, 0x52, 0x68, 0x5A, 0x43, 0x42, 0x6B, 0x5A, 0x53, 0x42, 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x61, 0x57, 0x5A, 0x70, 0x59, 0x32, 0x46, 0x6A, 0x61, 0x57, 0x39, ++ 0x75, 0x4D, 0x52, 0x51, 0x77, 0x0A, 0x45, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4C, 0x45, 0x77, 0x74, 0x42, 0x54, 0x6B, 0x59, 0x67, 0x51, 0x30, 0x45, 0x67, 0x55, 0x6D, 0x46, 0x70, 0x65, 0x6A, 0x45, 0x69, 0x4D, 0x43, 0x41, 0x47, 0x41, 0x31, ++ 0x55, 0x45, 0x41, 0x78, 0x4D, 0x5A, 0x51, 0x55, 0x35, 0x47, 0x49, 0x46, 0x4E, 0x6C, 0x59, 0x33, 0x56, 0x79, 0x5A, 0x53, 0x42, 0x54, 0x5A, 0x58, 0x4A, 0x32, 0x5A, 0x58, 0x49, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x51, 0x54, ++ 0x43, 0x43, 0x0A, 0x41, 0x69, 0x49, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x50, 0x41, 0x44, 0x43, 0x43, 0x41, 0x67, 0x6F, 0x43, 0x67, ++ 0x67, 0x49, 0x42, 0x41, 0x4E, 0x76, 0x72, 0x61, 0x79, 0x76, 0x6D, 0x5A, 0x46, 0x53, 0x56, 0x67, 0x70, 0x43, 0x6A, 0x63, 0x71, 0x51, 0x5A, 0x41, 0x5A, 0x32, 0x63, 0x43, 0x34, 0x46, 0x66, 0x63, 0x30, 0x6D, 0x36, 0x70, 0x36, 0x7A, 0x7A, 0x0A, ++ 0x42, 0x45, 0x35, 0x37, 0x6C, 0x67, 0x76, 0x73, 0x45, 0x65, 0x42, 0x62, 0x70, 0x68, 0x7A, 0x4F, 0x47, 0x39, 0x49, 0x4E, 0x67, 0x78, 0x77, 0x72, 0x75, 0x4A, 0x34, 0x64, 0x66, 0x6B, 0x55, 0x79, 0x59, 0x41, 0x38, 0x48, 0x36, 0x58, 0x64, 0x59, ++ 0x66, 0x70, 0x39, 0x71, 0x79, 0x47, 0x46, 0x4F, 0x74, 0x69, 0x62, 0x42, 0x54, 0x49, 0x33, 0x2F, 0x54, 0x4F, 0x38, 0x30, 0x73, 0x68, 0x39, 0x6C, 0x32, 0x4C, 0x6C, 0x34, 0x39, 0x61, 0x32, 0x70, 0x63, 0x62, 0x6E, 0x76, 0x0A, 0x54, 0x31, 0x67, ++ 0x64, 0x70, 0x64, 0x35, 0x30, 0x49, 0x4A, 0x65, 0x68, 0x37, 0x57, 0x68, 0x4D, 0x33, 0x70, 0x49, 0x58, 0x53, 0x37, 0x79, 0x72, 0x2F, 0x32, 0x57, 0x61, 0x6E, 0x76, 0x74, 0x48, 0x32, 0x56, 0x64, 0x79, 0x38, 0x77, 0x6D, 0x68, 0x72, 0x6E, 0x5A, ++ 0x45, 0x45, 0x32, 0x36, 0x63, 0x4C, 0x55, 0x51, 0x35, 0x76, 0x50, 0x6E, 0x48, 0x4F, 0x36, 0x52, 0x59, 0x50, 0x55, 0x47, 0x39, 0x74, 0x4D, 0x4A, 0x4A, 0x6F, 0x38, 0x67, 0x4E, 0x30, 0x70, 0x63, 0x76, 0x0A, 0x42, 0x32, 0x56, 0x53, 0x41, 0x4B, ++ 0x64, 0x75, 0x79, 0x4B, 0x39, 0x6F, 0x37, 0x50, 0x51, 0x55, 0x6C, 0x72, 0x5A, 0x58, 0x48, 0x31, 0x62, 0x44, 0x4F, 0x5A, 0x38, 0x72, 0x62, 0x65, 0x54, 0x7A, 0x50, 0x76, 0x59, 0x31, 0x5A, 0x4E, 0x6F, 0x4D, 0x48, 0x4B, 0x47, 0x45, 0x53, 0x79, ++ 0x39, 0x4C, 0x53, 0x2B, 0x49, 0x73, 0x4A, 0x4A, 0x31, 0x74, 0x6B, 0x30, 0x44, 0x72, 0x74, 0x53, 0x4F, 0x4F, 0x4D, 0x73, 0x70, 0x76, 0x52, 0x64, 0x4F, 0x6F, 0x69, 0x58, 0x73, 0x65, 0x0A, 0x7A, 0x78, 0x37, 0x36, 0x57, 0x30, 0x4F, 0x4C, 0x7A, ++ 0x63, 0x32, 0x6F, 0x44, 0x32, 0x72, 0x4B, 0x44, 0x46, 0x36, 0x35, 0x6E, 0x6B, 0x65, 0x50, 0x38, 0x4E, 0x6D, 0x32, 0x43, 0x67, 0x74, 0x59, 0x5A, 0x52, 0x63, 0x7A, 0x75, 0x53, 0x50, 0x6B, 0x64, 0x78, 0x6C, 0x39, 0x79, 0x30, 0x6F, 0x75, 0x6B, ++ 0x6E, 0x74, 0x50, 0x4C, 0x78, 0x42, 0x33, 0x73, 0x59, 0x30, 0x76, 0x61, 0x4A, 0x78, 0x69, 0x7A, 0x4F, 0x42, 0x51, 0x2B, 0x4F, 0x79, 0x52, 0x70, 0x31, 0x52, 0x4D, 0x0A, 0x56, 0x77, 0x6E, 0x56, 0x64, 0x6D, 0x50, 0x46, 0x36, 0x47, 0x55, 0x65, ++ 0x37, 0x6D, 0x31, 0x71, 0x7A, 0x77, 0x6D, 0x64, 0x2B, 0x6E, 0x78, 0x50, 0x72, 0x57, 0x41, 0x49, 0x2F, 0x56, 0x61, 0x5A, 0x44, 0x78, 0x55, 0x73, 0x65, 0x36, 0x6D, 0x41, 0x71, 0x34, 0x78, 0x68, 0x6A, 0x30, 0x6F, 0x48, 0x64, 0x6B, 0x4C, 0x65, ++ 0x50, 0x66, 0x54, 0x64, 0x73, 0x69, 0x51, 0x7A, 0x57, 0x37, 0x69, 0x31, 0x6F, 0x30, 0x54, 0x4A, 0x72, 0x48, 0x39, 0x33, 0x50, 0x42, 0x30, 0x6A, 0x0A, 0x37, 0x49, 0x4B, 0x70, 0x70, 0x75, 0x4C, 0x49, 0x42, 0x6B, 0x77, 0x43, 0x2F, 0x71, 0x78, ++ 0x63, 0x6D, 0x5A, 0x6B, 0x4C, 0x4C, 0x78, 0x43, 0x4B, 0x70, 0x76, 0x52, 0x2F, 0x31, 0x59, 0x64, 0x30, 0x44, 0x56, 0x6C, 0x4A, 0x52, 0x66, 0x62, 0x77, 0x63, 0x56, 0x77, 0x35, 0x4B, 0x64, 0x61, 0x2F, 0x53, 0x69, 0x4F, 0x4C, 0x39, 0x56, 0x38, ++ 0x42, 0x59, 0x39, 0x4B, 0x48, 0x63, 0x79, 0x69, 0x31, 0x53, 0x77, 0x72, 0x31, 0x2B, 0x4B, 0x75, 0x43, 0x4C, 0x48, 0x35, 0x7A, 0x0A, 0x4A, 0x54, 0x49, 0x64, 0x43, 0x32, 0x4D, 0x4B, 0x46, 0x34, 0x45, 0x41, 0x2F, 0x37, 0x5A, 0x32, 0x58, 0x75, ++ 0x65, 0x30, 0x73, 0x55, 0x44, 0x4B, 0x49, 0x62, 0x76, 0x56, 0x67, 0x46, 0x48, 0x6C, 0x53, 0x46, 0x4A, 0x6E, 0x4C, 0x4E, 0x4A, 0x68, 0x69, 0x51, 0x63, 0x4E, 0x44, 0x38, 0x35, 0x43, 0x64, 0x38, 0x42, 0x45, 0x63, 0x35, 0x78, 0x45, 0x55, 0x4B, ++ 0x44, 0x62, 0x45, 0x41, 0x6F, 0x74, 0x6C, 0x52, 0x79, 0x42, 0x72, 0x2B, 0x51, 0x63, 0x35, 0x52, 0x51, 0x65, 0x0A, 0x38, 0x54, 0x5A, 0x42, 0x41, 0x51, 0x49, 0x76, 0x66, 0x58, 0x4F, 0x6E, 0x33, 0x6B, 0x4C, 0x4D, 0x54, 0x4F, 0x6D, 0x4A, 0x44, ++ 0x56, 0x62, 0x33, 0x6E, 0x35, 0x48, 0x55, 0x41, 0x38, 0x5A, 0x73, 0x79, 0x59, 0x2F, 0x62, 0x32, 0x42, 0x7A, 0x67, 0x51, 0x4A, 0x68, 0x64, 0x5A, 0x70, 0x6D, 0x59, 0x67, 0x47, 0x34, 0x74, 0x2F, 0x77, 0x48, 0x46, 0x7A, 0x73, 0x74, 0x47, 0x48, ++ 0x36, 0x77, 0x43, 0x78, 0x6B, 0x50, 0x6D, 0x72, 0x71, 0x4B, 0x45, 0x50, 0x4D, 0x56, 0x4F, 0x0A, 0x48, 0x6A, 0x31, 0x74, 0x79, 0x52, 0x52, 0x4D, 0x34, 0x79, 0x35, 0x42, 0x75, 0x38, 0x6F, 0x35, 0x76, 0x7A, 0x59, 0x38, 0x4B, 0x68, 0x6D, 0x71, ++ 0x51, 0x59, 0x64, 0x4F, 0x70, 0x63, 0x35, 0x4C, 0x4D, 0x6E, 0x6E, 0x64, 0x6B, 0x45, 0x6C, 0x2F, 0x41, 0x67, 0x4D, 0x42, 0x41, 0x41, 0x47, 0x6A, 0x59, 0x7A, 0x42, 0x68, 0x4D, 0x42, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x49, 0x77, 0x51, 0x59, ++ 0x4D, 0x42, 0x61, 0x41, 0x46, 0x4A, 0x78, 0x66, 0x30, 0x47, 0x78, 0x6A, 0x0A, 0x6F, 0x31, 0x2B, 0x54, 0x79, 0x70, 0x4F, 0x59, 0x43, 0x4B, 0x32, 0x4D, 0x68, 0x36, 0x55, 0x73, 0x58, 0x4D, 0x45, 0x33, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, ++ 0x64, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x53, 0x63, 0x58, 0x39, 0x42, 0x73, 0x59, 0x36, 0x4E, 0x66, 0x6B, 0x38, 0x71, 0x54, 0x6D, 0x41, 0x69, 0x74, 0x6A, 0x49, 0x65, 0x6C, 0x4C, 0x46, 0x7A, 0x42, 0x4E, 0x7A, 0x41, 0x4F, 0x42, 0x67, 0x4E, ++ 0x56, 0x48, 0x51, 0x38, 0x42, 0x41, 0x66, 0x38, 0x45, 0x0A, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x59, 0x59, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, ++ 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x67, 0x45, 0x41, 0x54, 0x68, 0x36, 0x35, 0x69, 0x73, 0x61, 0x67, 0x6D, 0x44, 0x39, 0x75, 0x77, 0x32, ++ 0x6E, 0x41, 0x61, 0x6C, 0x78, 0x4A, 0x0A, 0x55, 0x71, 0x7A, 0x4C, 0x4B, 0x31, 0x31, 0x34, 0x4F, 0x4D, 0x48, 0x56, 0x56, 0x49, 0x53, 0x66, 0x6B, 0x2F, 0x43, 0x48, 0x47, 0x54, 0x30, 0x73, 0x5A, 0x6F, 0x6E, 0x72, 0x44, 0x55, 0x4C, 0x38, 0x7A, ++ 0x50, 0x42, 0x31, 0x68, 0x54, 0x2B, 0x4C, 0x39, 0x49, 0x42, 0x64, 0x65, 0x65, 0x55, 0x58, 0x5A, 0x37, 0x30, 0x31, 0x67, 0x75, 0x4C, 0x79, 0x50, 0x49, 0x35, 0x39, 0x57, 0x7A, 0x62, 0x4C, 0x57, 0x6F, 0x41, 0x41, 0x4B, 0x66, 0x4C, 0x4F, 0x4B, ++ 0x79, 0x7A, 0x78, 0x0A, 0x6A, 0x36, 0x70, 0x74, 0x42, 0x5A, 0x4E, 0x73, 0x63, 0x73, 0x64, 0x57, 0x36, 0x39, 0x39, 0x51, 0x49, 0x79, 0x6A, 0x6C, 0x52, 0x52, 0x41, 0x39, 0x36, 0x47, 0x65, 0x6A, 0x72, 0x77, 0x35, 0x56, 0x44, 0x35, 0x41, 0x4A, ++ 0x59, 0x75, 0x39, 0x4C, 0x57, 0x61, 0x4C, 0x32, 0x55, 0x2F, 0x48, 0x41, 0x4E, 0x65, 0x51, 0x76, 0x77, 0x53, 0x53, 0x39, 0x65, 0x53, 0x39, 0x4F, 0x49, 0x43, 0x49, 0x37, 0x2F, 0x52, 0x6F, 0x67, 0x73, 0x4B, 0x51, 0x4F, 0x4C, 0x48, 0x44, 0x74, ++ 0x0A, 0x64, 0x44, 0x2B, 0x34, 0x45, 0x35, 0x55, 0x47, 0x55, 0x63, 0x6A, 0x6F, 0x68, 0x79, 0x62, 0x4B, 0x70, 0x46, 0x74, 0x71, 0x46, 0x69, 0x47, 0x53, 0x33, 0x58, 0x4E, 0x67, 0x6E, 0x68, 0x41, 0x59, 0x33, 0x6A, 0x79, 0x42, 0x36, 0x75, 0x67, ++ 0x59, 0x77, 0x33, 0x79, 0x4A, 0x38, 0x6F, 0x74, 0x51, 0x50, 0x72, 0x30, 0x52, 0x34, 0x68, 0x55, 0x44, 0x71, 0x44, 0x5A, 0x39, 0x4D, 0x77, 0x46, 0x73, 0x53, 0x42, 0x58, 0x58, 0x69, 0x4A, 0x43, 0x5A, 0x42, 0x4D, 0x58, 0x4D, 0x0A, 0x35, 0x67, ++ 0x66, 0x30, 0x76, 0x50, 0x53, 0x51, 0x37, 0x52, 0x50, 0x69, 0x36, 0x6F, 0x76, 0x44, 0x6A, 0x36, 0x4D, 0x7A, 0x44, 0x38, 0x45, 0x70, 0x54, 0x42, 0x4E, 0x4F, 0x32, 0x68, 0x56, 0x57, 0x63, 0x58, 0x4E, 0x79, 0x67, 0x6C, 0x44, 0x32, 0x6D, 0x6A, ++ 0x4E, 0x38, 0x6F, 0x72, 0x47, 0x6F, 0x47, 0x6A, 0x52, 0x30, 0x5A, 0x56, 0x7A, 0x4F, 0x30, 0x65, 0x75, 0x72, 0x55, 0x2B, 0x41, 0x61, 0x67, 0x4E, 0x6A, 0x71, 0x4F, 0x6B, 0x6E, 0x6B, 0x4A, 0x6A, 0x43, 0x62, 0x0A, 0x35, 0x52, 0x79, 0x4B, 0x71, ++ 0x4B, 0x6B, 0x56, 0x4D, 0x6F, 0x61, 0x5A, 0x6B, 0x67, 0x6F, 0x51, 0x49, 0x31, 0x59, 0x53, 0x34, 0x50, 0x62, 0x4F, 0x54, 0x4F, 0x4B, 0x37, 0x76, 0x74, 0x75, 0x4E, 0x6B, 0x6E, 0x4D, 0x42, 0x5A, 0x69, 0x39, 0x69, 0x50, 0x72, 0x4A, 0x79, 0x4A, ++ 0x30, 0x55, 0x32, 0x37, 0x55, 0x31, 0x57, 0x34, 0x35, 0x65, 0x5A, 0x2F, 0x7A, 0x6F, 0x31, 0x50, 0x71, 0x56, 0x55, 0x53, 0x6C, 0x4A, 0x5A, 0x53, 0x32, 0x44, 0x62, 0x37, 0x76, 0x35, 0x34, 0x0A, 0x45, 0x58, 0x39, 0x4B, 0x33, 0x42, 0x52, 0x35, ++ 0x59, 0x4C, 0x5A, 0x72, 0x5A, 0x41, 0x50, 0x62, 0x46, 0x59, 0x50, 0x68, 0x6F, 0x72, 0x37, 0x32, 0x49, 0x35, 0x64, 0x51, 0x38, 0x41, 0x6B, 0x7A, 0x4E, 0x71, 0x64, 0x78, 0x6C, 0x69, 0x58, 0x7A, 0x75, 0x55, 0x4A, 0x39, 0x32, 0x7A, 0x67, 0x2F, ++ 0x4C, 0x46, 0x69, 0x73, 0x36, 0x45, 0x4C, 0x68, 0x44, 0x74, 0x6A, 0x54, 0x4F, 0x30, 0x77, 0x75, 0x67, 0x75, 0x6D, 0x44, 0x4C, 0x6D, 0x73, 0x78, 0x32, 0x64, 0x31, 0x48, 0x0A, 0x68, 0x6B, 0x39, 0x74, 0x6C, 0x35, 0x45, 0x75, 0x54, 0x2B, 0x49, ++ 0x6F, 0x63, 0x54, 0x55, 0x57, 0x30, 0x66, 0x4A, 0x7A, 0x2F, 0x69, 0x55, 0x72, 0x42, 0x30, 0x63, 0x6B, 0x59, 0x79, 0x66, 0x49, 0x2B, 0x50, 0x62, 0x5A, 0x61, 0x2F, 0x77, 0x53, 0x4D, 0x56, 0x59, 0x49, 0x77, 0x46, 0x4E, 0x43, 0x72, 0x35, 0x7A, ++ 0x51, 0x4D, 0x33, 0x37, 0x38, 0x42, 0x76, 0x41, 0x78, 0x52, 0x41, 0x4D, 0x55, 0x38, 0x56, 0x6A, 0x71, 0x38, 0x6D, 0x6F, 0x4E, 0x71, 0x52, 0x47, 0x79, 0x0A, 0x67, 0x37, 0x37, 0x46, 0x47, 0x72, 0x38, 0x48, 0x36, 0x6C, 0x6E, 0x63, 0x6F, 0x34, ++ 0x67, 0x31, 0x37, 0x35, 0x78, 0x32, 0x4D, 0x6A, 0x78, 0x4E, 0x42, 0x69, 0x4C, 0x4F, 0x46, 0x65, 0x58, 0x64, 0x6E, 0x74, 0x69, 0x50, 0x32, 0x74, 0x37, 0x53, 0x78, 0x44, 0x6E, 0x6C, 0x46, 0x34, 0x48, 0x50, 0x4F, 0x45, 0x66, 0x72, 0x66, 0x34, ++ 0x68, 0x74, 0x57, 0x52, 0x76, 0x66, 0x6E, 0x30, 0x49, 0x55, 0x72, 0x6E, 0x37, 0x50, 0x71, 0x4C, 0x42, 0x6D, 0x5A, 0x64, 0x6F, 0x33, 0x0A, 0x72, 0x35, 0x2B, 0x71, 0x50, 0x65, 0x6F, 0x6F, 0x74, 0x74, 0x37, 0x56, 0x4D, 0x56, 0x67, 0x57, 0x67, ++ 0x6C, 0x76, 0x71, 0x75, 0x78, 0x6C, 0x31, 0x41, 0x6E, 0x4D, 0x61, 0x79, 0x6B, 0x67, 0x61, 0x49, 0x5A, 0x4F, 0x51, 0x43, 0x6F, 0x36, 0x54, 0x68, 0x4B, 0x64, 0x39, 0x4F, 0x79, 0x4D, 0x59, 0x6B, 0x6F, 0x6D, 0x67, 0x6A, 0x61, 0x77, 0x3D, 0x0A, ++ 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x45, 0x43, 0x2D, 0x33, 0x38, 0x34, ++ 0x20, 0x43, 0x41, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, ++ 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x43, 0x5A, 0x54, 0x43, 0x43, 0x41, 0x65, 0x75, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x65, 0x49, 0x38, 0x6E, 0x58, 0x49, 0x45, 0x53, 0x55, 0x69, 0x43, ++ 0x6C, 0x42, 0x4E, 0x41, 0x74, 0x33, 0x62, 0x70, 0x7A, 0x39, 0x44, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x7A, 0x42, 0x30, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, ++ 0x47, 0x45, 0x77, 0x4A, 0x51, 0x0A, 0x54, 0x44, 0x45, 0x68, 0x4D, 0x42, 0x38, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x59, 0x51, 0x58, 0x4E, 0x7A, 0x5A, 0x57, 0x4E, 0x76, 0x49, 0x45, 0x52, 0x68, 0x64, 0x47, 0x45, 0x67, 0x55, 0x33, ++ 0x6C, 0x7A, 0x64, 0x47, 0x56, 0x74, 0x63, 0x79, 0x42, 0x54, 0x4C, 0x6B, 0x45, 0x75, 0x4D, 0x53, 0x63, 0x77, 0x4A, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4C, 0x45, 0x78, 0x35, 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x64, 0x57, 0x30, 0x67, 0x51, 0x32, ++ 0x56, 0x79, 0x0A, 0x64, 0x47, 0x6C, 0x6D, 0x61, 0x57, 0x4E, 0x68, 0x64, 0x47, 0x6C, 0x76, 0x62, 0x69, 0x42, 0x42, 0x64, 0x58, 0x52, 0x6F, 0x62, 0x33, 0x4A, 0x70, 0x64, 0x48, 0x6B, 0x78, 0x47, 0x54, 0x41, 0x58, 0x42, 0x67, 0x4E, 0x56, 0x42, ++ 0x41, 0x4D, 0x54, 0x45, 0x45, 0x4E, 0x6C, 0x63, 0x6E, 0x52, 0x31, 0x62, 0x53, 0x42, 0x46, 0x51, 0x79, 0x30, 0x7A, 0x4F, 0x44, 0x51, 0x67, 0x51, 0x30, 0x45, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x54, 0x67, 0x77, 0x4D, 0x7A, 0x49, 0x32, 0x0A, ++ 0x4D, 0x44, 0x63, 0x79, 0x4E, 0x44, 0x55, 0x30, 0x57, 0x68, 0x63, 0x4E, 0x4E, 0x44, 0x4D, 0x77, 0x4D, 0x7A, 0x49, 0x32, 0x4D, 0x44, 0x63, 0x79, 0x4E, 0x44, 0x55, 0x30, 0x57, 0x6A, 0x42, 0x30, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, ++ 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x51, 0x54, 0x44, 0x45, 0x68, 0x4D, 0x42, 0x38, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x59, 0x51, 0x58, 0x4E, 0x7A, 0x5A, 0x57, 0x4E, 0x76, 0x49, 0x45, 0x52, 0x68, 0x0A, 0x64, 0x47, 0x45, ++ 0x67, 0x55, 0x33, 0x6C, 0x7A, 0x64, 0x47, 0x56, 0x74, 0x63, 0x79, 0x42, 0x54, 0x4C, 0x6B, 0x45, 0x75, 0x4D, 0x53, 0x63, 0x77, 0x4A, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4C, 0x45, 0x78, 0x35, 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x64, 0x57, 0x30, ++ 0x67, 0x51, 0x32, 0x56, 0x79, 0x64, 0x47, 0x6C, 0x6D, 0x61, 0x57, 0x4E, 0x68, 0x64, 0x47, 0x6C, 0x76, 0x62, 0x69, 0x42, 0x42, 0x64, 0x58, 0x52, 0x6F, 0x62, 0x33, 0x4A, 0x70, 0x64, 0x48, 0x6B, 0x78, 0x0A, 0x47, 0x54, 0x41, 0x58, 0x42, 0x67, ++ 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x45, 0x45, 0x4E, 0x6C, 0x63, 0x6E, 0x52, 0x31, 0x62, 0x53, 0x42, 0x46, 0x51, 0x79, 0x30, 0x7A, 0x4F, 0x44, 0x51, 0x67, 0x51, 0x30, 0x45, 0x77, 0x64, 0x6A, 0x41, 0x51, 0x42, 0x67, 0x63, 0x71, 0x68, 0x6B, ++ 0x6A, 0x4F, 0x50, 0x51, 0x49, 0x42, 0x42, 0x67, 0x55, 0x72, 0x67, 0x51, 0x51, 0x41, 0x49, 0x67, 0x4E, 0x69, 0x41, 0x41, 0x54, 0x45, 0x4B, 0x49, 0x36, 0x72, 0x47, 0x46, 0x74, 0x71, 0x0A, 0x76, 0x6D, 0x35, 0x6B, 0x4E, 0x32, 0x50, 0x6B, 0x7A, ++ 0x65, 0x79, 0x72, 0x4F, 0x76, 0x66, 0x4D, 0x6F, 0x62, 0x67, 0x4F, 0x67, 0x6B, 0x6E, 0x58, 0x68, 0x69, 0x6D, 0x66, 0x6F, 0x5A, 0x54, 0x79, 0x34, 0x32, 0x42, 0x34, 0x6D, 0x49, 0x46, 0x34, 0x42, 0x6B, 0x33, 0x79, 0x37, 0x4A, 0x6F, 0x4F, 0x56, ++ 0x32, 0x43, 0x44, 0x6E, 0x37, 0x54, 0x6D, 0x46, 0x79, 0x38, 0x61, 0x73, 0x31, 0x30, 0x43, 0x57, 0x34, 0x6B, 0x6A, 0x50, 0x4D, 0x49, 0x52, 0x42, 0x53, 0x71, 0x6E, 0x0A, 0x69, 0x42, 0x4D, 0x59, 0x38, 0x31, 0x43, 0x45, 0x31, 0x37, 0x30, 0x30, ++ 0x4C, 0x43, 0x65, 0x4A, 0x56, 0x66, 0x2F, 0x4F, 0x54, 0x4F, 0x66, 0x66, 0x70, 0x68, 0x38, 0x6F, 0x78, 0x50, 0x42, 0x55, 0x77, 0x37, 0x6C, 0x38, 0x74, 0x31, 0x4F, 0x74, 0x36, 0x38, 0x4B, 0x6A, 0x51, 0x6A, 0x42, 0x41, 0x4D, 0x41, 0x38, 0x47, ++ 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x48, 0x51, 0x59, 0x44, 0x0A, 0x56, 0x52, 0x30, 0x4F, 0x42, 0x42, 0x59, 0x45, 0x46, 0x49, 0x30, 0x47, 0x5A, 0x6E, 0x51, ++ 0x6B, 0x64, 0x6A, 0x72, 0x7A, 0x69, 0x66, 0x65, 0x38, 0x31, 0x72, 0x31, 0x48, 0x66, 0x53, 0x2B, 0x38, 0x45, 0x46, 0x39, 0x4C, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, ++ 0x42, 0x42, 0x6A, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x77, 0x4E, 0x6F, 0x0A, 0x41, 0x44, 0x42, 0x6C, 0x41, 0x6A, 0x41, 0x44, 0x56, 0x53, 0x32, 0x6D, 0x35, 0x68, 0x6A, 0x45, 0x66, 0x4F, ++ 0x2F, 0x4A, 0x55, 0x47, 0x37, 0x42, 0x4A, 0x77, 0x2B, 0x63, 0x68, 0x36, 0x39, 0x75, 0x31, 0x52, 0x73, 0x49, 0x47, 0x4C, 0x32, 0x53, 0x4B, 0x63, 0x48, 0x76, 0x6C, 0x4A, 0x46, 0x34, 0x30, 0x6A, 0x6F, 0x63, 0x56, 0x59, 0x6C, 0x69, 0x35, 0x52, ++ 0x73, 0x4A, 0x48, 0x72, 0x70, 0x6B, 0x61, 0x2F, 0x46, 0x32, 0x74, 0x4E, 0x51, 0x43, 0x4D, 0x51, 0x43, 0x30, 0x0A, 0x51, 0x6F, 0x53, 0x5A, 0x2F, 0x36, 0x76, 0x6E, 0x6E, 0x76, 0x75, 0x52, 0x6C, 0x79, 0x64, 0x64, 0x33, 0x4C, 0x42, 0x62, 0x4D, ++ 0x48, 0x48, 0x4F, 0x58, 0x6A, 0x67, 0x61, 0x61, 0x74, 0x6B, 0x6C, 0x35, 0x2B, 0x72, 0x33, 0x59, 0x5A, 0x4A, 0x57, 0x2B, 0x4F, 0x72, 0x61, 0x4E, 0x73, 0x4B, 0x48, 0x5A, 0x5A, 0x59, 0x75, 0x63, 0x69, 0x55, 0x76, 0x66, 0x39, 0x2F, 0x44, 0x45, ++ 0x38, 0x6B, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x54, 0x72, ++ 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, ++ 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x77, 0x44, 0x43, 0x43, 0x41, 0x36, 0x69, 0x67, 0x41, 0x77, 0x49, ++ 0x42, 0x41, 0x67, 0x49, 0x51, 0x48, 0x72, 0x39, 0x5A, 0x55, 0x4C, 0x6A, 0x4A, 0x67, 0x44, 0x64, 0x4D, 0x42, 0x76, 0x66, 0x72, 0x56, 0x55, 0x2B, 0x31, 0x37, 0x54, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, ++ 0x42, 0x41, 0x51, 0x30, 0x46, 0x41, 0x44, 0x42, 0x36, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x0A, 0x45, 0x77, 0x4A, 0x51, 0x54, 0x44, 0x45, 0x68, 0x4D, 0x42, 0x38, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, ++ 0x4D, 0x59, 0x51, 0x58, 0x4E, 0x7A, 0x5A, 0x57, 0x4E, 0x76, 0x49, 0x45, 0x52, 0x68, 0x64, 0x47, 0x45, 0x67, 0x55, 0x33, 0x6C, 0x7A, 0x64, 0x47, 0x56, 0x74, 0x63, 0x79, 0x42, 0x54, 0x4C, 0x6B, 0x45, 0x75, 0x4D, 0x53, 0x63, 0x77, 0x4A, 0x51, ++ 0x59, 0x44, 0x56, 0x51, 0x51, 0x4C, 0x45, 0x78, 0x35, 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x64, 0x57, 0x30, 0x67, 0x0A, 0x51, 0x32, 0x56, 0x79, 0x64, 0x47, 0x6C, 0x6D, 0x61, 0x57, 0x4E, 0x68, 0x64, 0x47, 0x6C, 0x76, 0x62, 0x69, 0x42, 0x42, 0x64, ++ 0x58, 0x52, 0x6F, 0x62, 0x33, 0x4A, 0x70, 0x64, 0x48, 0x6B, 0x78, 0x48, 0x7A, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x46, 0x6B, 0x4E, 0x6C, 0x63, 0x6E, 0x52, 0x31, 0x62, 0x53, 0x42, 0x55, 0x63, 0x6E, 0x56, 0x7A, 0x64, ++ 0x47, 0x56, 0x6B, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x77, 0x0A, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x54, 0x67, 0x77, 0x4D, 0x7A, 0x45, 0x32, 0x4D, 0x54, 0x49, 0x78, 0x4D, 0x44, 0x45, 0x7A, 0x57, 0x68, 0x63, 0x4E, ++ 0x4E, 0x44, 0x4D, 0x77, 0x4D, 0x7A, 0x45, 0x32, 0x4D, 0x54, 0x49, 0x78, 0x4D, 0x44, 0x45, 0x7A, 0x57, 0x6A, 0x42, 0x36, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x51, 0x54, 0x44, 0x45, 0x68, ++ 0x4D, 0x42, 0x38, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x59, 0x0A, 0x51, 0x58, 0x4E, 0x7A, 0x5A, 0x57, 0x4E, 0x76, 0x49, 0x45, 0x52, 0x68, 0x64, 0x47, 0x45, 0x67, 0x55, 0x33, 0x6C, 0x7A, 0x64, 0x47, 0x56, 0x74, 0x63, 0x79, 0x42, ++ 0x54, 0x4C, 0x6B, 0x45, 0x75, 0x4D, 0x53, 0x63, 0x77, 0x4A, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4C, 0x45, 0x78, 0x35, 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x64, 0x57, 0x30, 0x67, 0x51, 0x32, 0x56, 0x79, 0x64, 0x47, 0x6C, 0x6D, 0x61, 0x57, 0x4E, ++ 0x68, 0x64, 0x47, 0x6C, 0x76, 0x62, 0x69, 0x42, 0x42, 0x0A, 0x64, 0x58, 0x52, 0x6F, 0x62, 0x33, 0x4A, 0x70, 0x64, 0x48, 0x6B, 0x78, 0x48, 0x7A, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x46, 0x6B, 0x4E, 0x6C, 0x63, 0x6E, ++ 0x52, 0x31, 0x62, 0x53, 0x42, 0x55, 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x47, 0x56, 0x6B, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x77, 0x67, 0x67, 0x49, 0x69, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, ++ 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x0A, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x49, 0x4B, 0x41, 0x6F, 0x49, 0x43, 0x41, 0x51, 0x44, 0x52, 0x4C, 0x59, 0x36, 0x37, 0x74, 0x7A, 0x62, 0x71, 0x62, ++ 0x54, 0x65, 0x52, 0x6E, 0x30, 0x36, 0x54, 0x70, 0x77, 0x58, 0x6B, 0x4B, 0x51, 0x4D, 0x6C, 0x7A, 0x68, 0x79, 0x43, 0x39, 0x33, 0x79, 0x5A, 0x6E, 0x30, 0x45, 0x47, 0x7A, 0x65, 0x32, 0x6A, 0x75, 0x73, 0x44, 0x62, 0x43, 0x53, 0x7A, 0x42, 0x66, ++ 0x4E, 0x38, 0x70, 0x0A, 0x66, 0x6B, 0x74, 0x6C, 0x4C, 0x35, 0x4F, 0x6E, 0x31, 0x41, 0x46, 0x72, 0x41, 0x79, 0x67, 0x59, 0x6F, 0x39, 0x69, 0x64, 0x42, 0x63, 0x45, 0x71, 0x32, 0x45, 0x58, 0x78, 0x6B, 0x64, 0x37, 0x66, 0x4F, 0x39, 0x43, 0x41, ++ 0x41, 0x6F, 0x7A, 0x50, 0x4F, 0x41, 0x2F, 0x71, 0x70, 0x31, 0x78, 0x34, 0x45, 0x61, 0x54, 0x42, 0x79, 0x49, 0x56, 0x63, 0x4A, 0x64, 0x50, 0x54, 0x73, 0x75, 0x63, 0x6C, 0x7A, 0x78, 0x46, 0x55, 0x6C, 0x36, 0x73, 0x31, 0x77, 0x42, 0x35, 0x32, ++ 0x0A, 0x48, 0x4F, 0x38, 0x41, 0x55, 0x35, 0x38, 0x35, 0x33, 0x42, 0x53, 0x6C, 0x4C, 0x43, 0x49, 0x6C, 0x73, 0x33, 0x4A, 0x79, 0x2F, 0x49, 0x32, 0x7A, 0x35, 0x54, 0x34, 0x49, 0x48, 0x68, 0x51, 0x71, 0x4E, 0x77, 0x75, 0x49, 0x50, 0x4D, 0x71, ++ 0x77, 0x39, 0x4D, 0x6A, 0x43, 0x6F, 0x61, 0x36, 0x38, 0x77, 0x62, 0x34, 0x70, 0x5A, 0x31, 0x58, 0x69, 0x2F, 0x4B, 0x31, 0x5A, 0x58, 0x50, 0x36, 0x39, 0x56, 0x79, 0x79, 0x77, 0x6B, 0x49, 0x33, 0x43, 0x37, 0x54, 0x65, 0x32, 0x0A, 0x66, 0x4A, ++ 0x6D, 0x49, 0x74, 0x64, 0x55, 0x44, 0x6D, 0x6A, 0x30, 0x56, 0x44, 0x54, 0x30, 0x36, 0x71, 0x4B, 0x68, 0x46, 0x38, 0x4A, 0x56, 0x4F, 0x4A, 0x56, 0x6B, 0x64, 0x7A, 0x5A, 0x68, 0x70, 0x75, 0x39, 0x50, 0x4D, 0x4D, 0x73, 0x6D, 0x4E, 0x37, 0x34, ++ 0x48, 0x2B, 0x72, 0x58, 0x32, 0x4A, 0x75, 0x37, 0x70, 0x67, 0x45, 0x38, 0x70, 0x6C, 0x6C, 0x57, 0x65, 0x67, 0x38, 0x78, 0x6E, 0x32, 0x41, 0x31, 0x62, 0x55, 0x61, 0x74, 0x4D, 0x6E, 0x34, 0x71, 0x47, 0x74, 0x0A, 0x67, 0x2F, 0x42, 0x4B, 0x45, ++ 0x69, 0x4A, 0x33, 0x48, 0x41, 0x56, 0x7A, 0x34, 0x68, 0x6C, 0x78, 0x51, 0x73, 0x44, 0x73, 0x64, 0x55, 0x61, 0x61, 0x6B, 0x46, 0x6A, 0x67, 0x61, 0x6F, 0x34, 0x72, 0x70, 0x55, 0x59, 0x77, 0x42, 0x49, 0x34, 0x5A, 0x73, 0x68, 0x66, 0x6A, 0x76, ++ 0x71, 0x6D, 0x36, 0x66, 0x31, 0x62, 0x78, 0x4A, 0x41, 0x50, 0x58, 0x73, 0x69, 0x45, 0x6F, 0x64, 0x67, 0x34, 0x32, 0x4D, 0x45, 0x78, 0x35, 0x31, 0x55, 0x47, 0x61, 0x6D, 0x71, 0x69, 0x34, 0x0A, 0x4E, 0x62, 0x6F, 0x4D, 0x4F, 0x76, 0x4A, 0x45, ++ 0x47, 0x79, 0x43, 0x49, 0x39, 0x38, 0x55, 0x6C, 0x31, 0x7A, 0x33, 0x47, 0x34, 0x7A, 0x35, 0x44, 0x33, 0x59, 0x66, 0x2B, 0x78, 0x4F, 0x72, 0x31, 0x55, 0x7A, 0x35, 0x4D, 0x5A, 0x66, 0x38, 0x37, 0x53, 0x73, 0x74, 0x34, 0x57, 0x6D, 0x73, 0x58, ++ 0x58, 0x77, 0x33, 0x48, 0x77, 0x30, 0x39, 0x4F, 0x6D, 0x69, 0x71, 0x69, 0x37, 0x56, 0x64, 0x4E, 0x49, 0x75, 0x4A, 0x47, 0x6D, 0x6A, 0x38, 0x50, 0x6B, 0x54, 0x51, 0x6B, 0x0A, 0x66, 0x56, 0x58, 0x6A, 0x6A, 0x4A, 0x55, 0x33, 0x30, 0x78, 0x72, ++ 0x77, 0x43, 0x53, 0x73, 0x73, 0x30, 0x73, 0x6D, 0x4E, 0x74, 0x41, 0x30, 0x41, 0x71, 0x32, 0x63, 0x70, 0x4B, 0x4E, 0x67, 0x42, 0x39, 0x52, 0x6B, 0x45, 0x74, 0x68, 0x32, 0x2B, 0x64, 0x76, 0x35, 0x79, 0x58, 0x4D, 0x53, 0x46, 0x79, 0x74, 0x4B, ++ 0x41, 0x51, 0x64, 0x38, 0x46, 0x71, 0x4B, 0x50, 0x56, 0x68, 0x4A, 0x42, 0x50, 0x43, 0x2F, 0x50, 0x67, 0x50, 0x35, 0x73, 0x5A, 0x30, 0x6A, 0x65, 0x4A, 0x0A, 0x50, 0x2F, 0x4A, 0x37, 0x55, 0x68, 0x79, 0x4D, 0x39, 0x75, 0x48, 0x33, 0x50, 0x41, ++ 0x65, 0x58, 0x6A, 0x41, 0x36, 0x69, 0x57, 0x59, 0x45, 0x4D, 0x73, 0x70, 0x41, 0x39, 0x30, 0x2B, 0x4E, 0x5A, 0x52, 0x75, 0x30, 0x50, 0x71, 0x61, 0x66, 0x65, 0x67, 0x47, 0x74, 0x61, 0x71, 0x67, 0x65, 0x32, 0x47, 0x63, 0x75, 0x38, 0x56, 0x2F, ++ 0x4F, 0x58, 0x49, 0x58, 0x6F, 0x4D, 0x73, 0x53, 0x74, 0x30, 0x50, 0x75, 0x76, 0x61, 0x70, 0x32, 0x63, 0x74, 0x54, 0x4D, 0x53, 0x59, 0x0A, 0x6E, 0x6A, 0x59, 0x4A, 0x64, 0x6D, 0x5A, 0x6D, 0x2F, 0x42, 0x6F, 0x2F, 0x36, 0x6B, 0x68, 0x55, 0x48, ++ 0x4C, 0x34, 0x77, 0x76, 0x59, 0x42, 0x51, 0x76, 0x33, 0x79, 0x31, 0x7A, 0x67, 0x44, 0x32, 0x44, 0x47, 0x48, 0x5A, 0x35, 0x79, 0x51, 0x44, 0x34, 0x4F, 0x4D, 0x42, 0x67, 0x51, 0x36, 0x39, 0x32, 0x49, 0x55, 0x30, 0x69, 0x4C, 0x32, 0x79, 0x4E, ++ 0x71, 0x68, 0x37, 0x58, 0x41, 0x6A, 0x6C, 0x52, 0x49, 0x43, 0x4D, 0x62, 0x2F, 0x67, 0x76, 0x31, 0x53, 0x48, 0x4B, 0x0A, 0x48, 0x52, 0x7A, 0x51, 0x2B, 0x38, 0x53, 0x31, 0x68, 0x39, 0x45, 0x36, 0x54, 0x73, 0x64, 0x32, 0x74, 0x54, 0x56, 0x49, ++ 0x74, 0x51, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x6F, 0x30, 0x49, 0x77, 0x51, 0x44, 0x41, 0x50, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x52, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x54, 0x41, 0x44, 0x41, 0x51, 0x48, 0x2F, 0x4D, 0x42, 0x30, 0x47, ++ 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x53, 0x4D, 0x2B, 0x78, 0x78, 0x31, 0x0A, 0x76, 0x41, 0x4C, 0x54, 0x6E, 0x30, 0x34, 0x75, 0x53, 0x4E, 0x6E, 0x35, 0x59, 0x46, 0x53, 0x71, 0x78, 0x4C, 0x4E, 0x50, 0x2B, 0x6A, 0x41, ++ 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x51, 0x59, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4E, 0x42, 0x51, 0x41, ++ 0x44, 0x67, 0x67, 0x49, 0x42, 0x41, 0x45, 0x69, 0x69, 0x31, 0x51, 0x41, 0x4C, 0x0A, 0x4C, 0x74, 0x41, 0x2F, 0x76, 0x42, 0x7A, 0x56, 0x74, 0x56, 0x52, 0x4A, 0x48, 0x6C, 0x70, 0x72, 0x39, 0x4F, 0x54, 0x79, 0x34, 0x45, 0x41, 0x33, 0x34, 0x4D, ++ 0x77, 0x55, 0x65, 0x37, 0x6E, 0x4A, 0x2B, 0x6A, 0x57, 0x31, 0x64, 0x52, 0x65, 0x54, 0x61, 0x67, 0x56, 0x70, 0x68, 0x5A, 0x7A, 0x4E, 0x54, 0x78, 0x6C, 0x34, 0x57, 0x78, 0x6D, 0x42, 0x38, 0x32, 0x4D, 0x2B, 0x77, 0x38, 0x35, 0x62, 0x6A, 0x2F, ++ 0x55, 0x76, 0x58, 0x67, 0x46, 0x32, 0x45, 0x7A, 0x38, 0x73, 0x0A, 0x41, 0x4C, 0x6E, 0x4E, 0x6C, 0x6C, 0x49, 0x35, 0x53, 0x57, 0x30, 0x45, 0x54, 0x73, 0x58, 0x70, 0x44, 0x34, 0x59, 0x4E, 0x34, 0x66, 0x71, 0x7A, 0x58, 0x34, 0x49, 0x53, 0x38, ++ 0x54, 0x72, 0x4F, 0x5A, 0x67, 0x59, 0x6B, 0x4E, 0x43, 0x76, 0x6F, 0x7A, 0x4D, 0x72, 0x6E, 0x61, 0x64, 0x79, 0x48, 0x6E, 0x63, 0x49, 0x30, 0x31, 0x33, 0x6E, 0x52, 0x30, 0x33, 0x65, 0x34, 0x71, 0x6C, 0x6C, 0x59, 0x2F, 0x70, 0x30, 0x6D, 0x2B, ++ 0x6A, 0x69, 0x47, 0x50, 0x70, 0x32, 0x4B, 0x0A, 0x68, 0x32, 0x52, 0x58, 0x35, 0x52, 0x63, 0x36, 0x34, 0x76, 0x6D, 0x4E, 0x75, 0x65, 0x4D, 0x7A, 0x65, 0x4D, 0x47, 0x51, 0x32, 0x4C, 0x6A, 0x64, 0x74, 0x34, 0x4E, 0x52, 0x35, 0x4D, 0x54, 0x4D, ++ 0x49, 0x39, 0x55, 0x47, 0x66, 0x4F, 0x5A, 0x52, 0x30, 0x38, 0x30, 0x30, 0x4D, 0x63, 0x44, 0x32, 0x52, 0x72, 0x73, 0x4C, 0x72, 0x66, 0x77, 0x39, 0x45, 0x41, 0x55, 0x71, 0x4F, 0x30, 0x71, 0x52, 0x4A, 0x65, 0x36, 0x4D, 0x31, 0x49, 0x53, 0x48, ++ 0x67, 0x43, 0x71, 0x38, 0x0A, 0x43, 0x59, 0x79, 0x71, 0x4F, 0x68, 0x4E, 0x66, 0x36, 0x44, 0x52, 0x35, 0x55, 0x4D, 0x45, 0x51, 0x47, 0x66, 0x6E, 0x54, 0x4B, 0x42, 0x37, 0x55, 0x30, 0x56, 0x45, 0x77, 0x4B, 0x62, 0x4F, 0x75, 0x6B, 0x47, 0x66, ++ 0x57, 0x48, 0x77, 0x70, 0x6A, 0x73, 0x63, 0x57, 0x70, 0x78, 0x6B, 0x49, 0x78, 0x59, 0x78, 0x65, 0x55, 0x37, 0x32, 0x6E, 0x4C, 0x4C, 0x2F, 0x71, 0x4D, 0x46, 0x48, 0x33, 0x45, 0x51, 0x78, 0x69, 0x4A, 0x32, 0x66, 0x41, 0x79, 0x51, 0x4F, 0x61, ++ 0x41, 0x0A, 0x34, 0x6B, 0x5A, 0x66, 0x35, 0x65, 0x50, 0x42, 0x41, 0x46, 0x6D, 0x6F, 0x2B, 0x65, 0x67, 0x67, 0x76, 0x49, 0x6B, 0x73, 0x44, 0x6B, 0x63, 0x30, 0x43, 0x2B, 0x70, 0x58, 0x77, 0x6C, 0x4D, 0x32, 0x2F, 0x4B, 0x66, 0x55, 0x72, 0x7A, ++ 0x48, 0x4E, 0x2F, 0x67, 0x4C, 0x6C, 0x64, 0x66, 0x71, 0x35, 0x4A, 0x77, 0x6E, 0x35, 0x38, 0x2F, 0x55, 0x37, 0x79, 0x6E, 0x32, 0x66, 0x71, 0x53, 0x4C, 0x4C, 0x69, 0x4D, 0x6D, 0x71, 0x30, 0x55, 0x63, 0x39, 0x4E, 0x6E, 0x65, 0x6F, 0x0A, 0x57, ++ 0x57, 0x52, 0x72, 0x4A, 0x38, 0x2F, 0x76, 0x4A, 0x38, 0x48, 0x6A, 0x4A, 0x4C, 0x57, 0x47, 0x39, 0x36, 0x35, 0x2B, 0x4D, 0x6B, 0x32, 0x77, 0x65, 0x57, 0x6A, 0x52, 0x4F, 0x65, 0x69, 0x51, 0x57, 0x4D, 0x4F, 0x44, 0x76, 0x41, 0x38, 0x73, 0x31, ++ 0x70, 0x66, 0x72, 0x7A, 0x67, 0x7A, 0x68, 0x49, 0x4D, 0x66, 0x61, 0x74, 0x7A, 0x37, 0x44, 0x50, 0x37, 0x38, 0x76, 0x33, 0x44, 0x53, 0x6B, 0x2B, 0x79, 0x73, 0x68, 0x7A, 0x57, 0x65, 0x50, 0x53, 0x2F, 0x54, 0x6A, 0x0A, 0x36, 0x74, 0x51, 0x2F, ++ 0x35, 0x30, 0x2B, 0x36, 0x75, 0x61, 0x57, 0x54, 0x52, 0x52, 0x78, 0x6D, 0x48, 0x79, 0x48, 0x36, 0x5A, 0x46, 0x35, 0x76, 0x34, 0x48, 0x61, 0x55, 0x4D, 0x73, 0x74, 0x31, 0x39, 0x57, 0x37, 0x6C, 0x39, 0x6F, 0x2F, 0x48, 0x75, 0x4B, 0x54, 0x4D, ++ 0x71, 0x4A, 0x5A, 0x39, 0x5A, 0x50, 0x73, 0x6B, 0x57, 0x6B, 0x6F, 0x44, 0x62, 0x47, 0x73, 0x34, 0x78, 0x75, 0x67, 0x44, 0x51, 0x35, 0x72, 0x33, 0x56, 0x37, 0x6D, 0x7A, 0x4B, 0x57, 0x6D, 0x54, 0x0A, 0x4F, 0x50, 0x51, 0x44, 0x38, 0x72, 0x76, ++ 0x37, 0x67, 0x6D, 0x73, 0x48, 0x49, 0x4E, 0x46, 0x53, 0x48, 0x35, 0x70, 0x6B, 0x41, 0x6E, 0x75, 0x59, 0x5A, 0x74, 0x74, 0x63, 0x54, 0x56, 0x6F, 0x50, 0x30, 0x49, 0x53, 0x56, 0x6F, 0x44, 0x77, 0x55, 0x51, 0x77, 0x62, 0x4B, 0x79, 0x74, 0x75, ++ 0x34, 0x51, 0x54, 0x62, 0x61, 0x61, 0x6B, 0x52, 0x6E, 0x68, 0x36, 0x2B, 0x76, 0x34, 0x30, 0x55, 0x52, 0x46, 0x57, 0x6B, 0x49, 0x73, 0x72, 0x34, 0x57, 0x4F, 0x5A, 0x63, 0x6B, 0x0A, 0x62, 0x78, 0x4A, 0x46, 0x30, 0x57, 0x64, 0x64, 0x43, 0x61, ++ 0x6A, 0x4A, 0x46, 0x64, 0x72, 0x36, 0x30, 0x71, 0x5A, 0x66, 0x45, 0x32, 0x45, 0x66, 0x76, 0x34, 0x57, 0x73, 0x74, 0x4B, 0x32, 0x74, 0x42, 0x5A, 0x51, 0x49, 0x67, 0x78, 0x35, 0x31, 0x46, 0x39, 0x4E, 0x78, 0x4F, 0x35, 0x4E, 0x51, 0x49, 0x31, ++ 0x6D, 0x67, 0x37, 0x54, 0x79, 0x52, 0x56, 0x4A, 0x31, 0x32, 0x41, 0x4D, 0x58, 0x44, 0x75, 0x44, 0x6A, 0x62, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, ++ 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x54, 0x75, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, ++ 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x73, 0x7A, 0x43, 0x43, 0x41, 0x35, 0x75, 0x67, ++ 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x55, 0x45, 0x77, 0x4C, 0x56, 0x34, 0x6B, 0x42, 0x4D, 0x6B, 0x6B, 0x61, 0x47, 0x46, 0x6D, 0x64, 0x64, 0x74, 0x4C, 0x75, 0x37, 0x73, 0x6D, 0x73, 0x2B, 0x2F, 0x42, 0x4D, 0x77, 0x44, 0x51, 0x59, 0x4A, ++ 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x42, 0x51, 0x41, 0x77, 0x59, 0x54, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x0A, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x56, 0x45, 0x34, 0x78, 0x4E, 0x7A, 0x41, ++ 0x31, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x4D, 0x4C, 0x6B, 0x46, 0x6E, 0x5A, 0x57, 0x35, 0x6A, 0x5A, 0x53, 0x42, 0x4F, 0x59, 0x58, 0x52, 0x70, 0x62, 0x32, 0x35, 0x68, 0x62, 0x47, 0x55, 0x67, 0x5A, 0x47, 0x55, 0x67, 0x51, 0x32, 0x56, ++ 0x79, 0x64, 0x47, 0x6C, 0x6D, 0x61, 0x57, 0x4E, 0x68, 0x64, 0x47, 0x6C, 0x76, 0x62, 0x69, 0x42, 0x46, 0x62, 0x47, 0x56, 0x6A, 0x0A, 0x64, 0x48, 0x4A, 0x76, 0x62, 0x6D, 0x6C, 0x78, 0x64, 0x57, 0x55, 0x78, 0x47, 0x54, 0x41, 0x58, 0x42, 0x67, ++ 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x4D, 0x45, 0x46, 0x52, 0x31, 0x62, 0x6C, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x54, 0x6B, 0x77, 0x4E, 0x44, ++ 0x49, 0x32, 0x4D, 0x44, 0x67, 0x31, 0x4E, 0x7A, 0x55, 0x32, 0x57, 0x68, 0x63, 0x4E, 0x4E, 0x44, 0x51, 0x77, 0x0A, 0x4E, 0x44, 0x49, 0x32, 0x4D, 0x44, 0x67, 0x31, 0x4E, 0x7A, 0x55, 0x32, 0x57, 0x6A, 0x42, 0x68, 0x4D, 0x51, 0x73, 0x77, 0x43, ++ 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x55, 0x54, 0x6A, 0x45, 0x33, 0x4D, 0x44, 0x55, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, 0x75, 0x51, 0x57, 0x64, 0x6C, 0x62, 0x6D, 0x4E, 0x6C, 0x49, 0x45, 0x35, 0x68, 0x64, ++ 0x47, 0x6C, 0x76, 0x62, 0x6D, 0x46, 0x73, 0x5A, 0x53, 0x42, 0x6B, 0x5A, 0x53, 0x42, 0x44, 0x0A, 0x5A, 0x58, 0x4A, 0x30, 0x61, 0x57, 0x5A, 0x70, 0x59, 0x32, 0x46, 0x30, 0x61, 0x57, 0x39, 0x75, 0x49, 0x45, 0x56, 0x73, 0x5A, 0x57, 0x4E, 0x30, ++ 0x63, 0x6D, 0x39, 0x75, 0x61, 0x58, 0x46, 0x31, 0x5A, 0x54, 0x45, 0x5A, 0x4D, 0x42, 0x63, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x77, 0x77, 0x51, 0x56, 0x48, 0x56, 0x75, 0x56, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x51, 0x67, 0x55, 0x6D, 0x39, 0x76, ++ 0x64, 0x43, 0x42, 0x44, 0x51, 0x54, 0x43, 0x43, 0x41, 0x69, 0x49, 0x77, 0x0A, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x50, 0x41, 0x44, 0x43, ++ 0x43, 0x41, 0x67, 0x6F, 0x43, 0x67, 0x67, 0x49, 0x42, 0x41, 0x4D, 0x50, 0x4E, 0x30, 0x2F, 0x79, 0x39, 0x42, 0x46, 0x50, 0x64, 0x44, 0x43, 0x41, 0x36, 0x31, 0x59, 0x67, 0x75, 0x42, 0x55, 0x74, 0x42, 0x39, 0x59, 0x4F, 0x43, 0x66, 0x76, 0x64, ++ 0x5A, 0x6E, 0x35, 0x36, 0x65, 0x59, 0x2B, 0x68, 0x7A, 0x0A, 0x32, 0x76, 0x59, 0x47, 0x71, 0x55, 0x38, 0x66, 0x74, 0x50, 0x6B, 0x4C, 0x48, 0x7A, 0x6D, 0x4D, 0x6D, 0x69, 0x44, 0x51, 0x66, 0x67, 0x62, 0x55, 0x37, 0x44, 0x54, 0x5A, 0x68, 0x72, ++ 0x78, 0x31, 0x57, 0x34, 0x65, 0x49, 0x38, 0x4E, 0x4C, 0x5A, 0x31, 0x4B, 0x4D, 0x4B, 0x73, 0x6D, 0x77, 0x62, 0x36, 0x30, 0x6B, 0x73, 0x50, 0x71, 0x78, 0x64, 0x32, 0x4A, 0x51, 0x44, 0x6F, 0x4F, 0x77, 0x30, 0x35, 0x54, 0x44, 0x45, 0x4E, 0x58, ++ 0x33, 0x37, 0x4A, 0x6B, 0x30, 0x62, 0x0A, 0x62, 0x6A, 0x42, 0x55, 0x32, 0x50, 0x57, 0x41, 0x52, 0x5A, 0x77, 0x35, 0x72, 0x5A, 0x7A, 0x4A, 0x4A, 0x51, 0x52, 0x4E, 0x6D, 0x70, 0x41, 0x2B, 0x54, 0x6B, 0x42, 0x75, 0x69, 0x6D, 0x76, 0x4E, 0x4B, ++ 0x57, 0x66, 0x47, 0x7A, 0x43, 0x33, 0x67, 0x64, 0x4F, 0x67, 0x46, 0x56, 0x77, 0x70, 0x49, 0x55, 0x50, 0x70, 0x36, 0x51, 0x39, 0x70, 0x2B, 0x37, 0x46, 0x75, 0x61, 0x44, 0x6D, 0x4A, 0x32, 0x2F, 0x75, 0x71, 0x64, 0x48, 0x59, 0x56, 0x79, 0x37, ++ 0x42, 0x47, 0x37, 0x0A, 0x4E, 0x65, 0x67, 0x66, 0x4A, 0x37, 0x2F, 0x42, 0x6F, 0x63, 0x65, 0x37, 0x53, 0x42, 0x62, 0x64, 0x56, 0x74, 0x66, 0x4D, 0x54, 0x71, 0x44, 0x68, 0x75, 0x61, 0x7A, 0x62, 0x31, 0x59, 0x4D, 0x5A, 0x47, 0x6F, 0x58, 0x52, ++ 0x6C, 0x4A, 0x66, 0x58, 0x79, 0x71, 0x4E, 0x6C, 0x43, 0x2F, 0x4D, 0x34, 0x2B, 0x51, 0x4B, 0x75, 0x33, 0x66, 0x5A, 0x6E, 0x7A, 0x38, 0x6B, 0x2F, 0x39, 0x59, 0x6F, 0x73, 0x52, 0x78, 0x71, 0x5A, 0x62, 0x77, 0x55, 0x4E, 0x2F, 0x64, 0x41, 0x64, ++ 0x0A, 0x67, 0x6A, 0x48, 0x38, 0x4B, 0x63, 0x77, 0x41, 0x57, 0x4A, 0x65, 0x52, 0x54, 0x49, 0x41, 0x41, 0x48, 0x44, 0x4F, 0x46, 0x6C, 0x69, 0x2F, 0x4C, 0x51, 0x63, 0x4B, 0x4C, 0x45, 0x49, 0x54, 0x44, 0x43, 0x53, 0x53, 0x4A, 0x48, 0x37, 0x55, ++ 0x50, 0x32, 0x64, 0x6C, 0x33, 0x52, 0x78, 0x69, 0x53, 0x6C, 0x47, 0x42, 0x63, 0x78, 0x35, 0x6B, 0x44, 0x50, 0x50, 0x37, 0x33, 0x6C, 0x61, 0x64, 0x39, 0x55, 0x4B, 0x47, 0x41, 0x77, 0x71, 0x6D, 0x44, 0x72, 0x56, 0x69, 0x57, 0x0A, 0x56, 0x53, ++ 0x48, 0x62, 0x68, 0x6C, 0x6E, 0x55, 0x72, 0x38, 0x61, 0x38, 0x33, 0x59, 0x46, 0x75, 0x42, 0x39, 0x74, 0x67, 0x59, 0x76, 0x37, 0x73, 0x45, 0x47, 0x37, 0x61, 0x61, 0x41, 0x48, 0x30, 0x67, 0x78, 0x75, 0x70, 0x50, 0x71, 0x4A, 0x62, 0x49, 0x39, ++ 0x64, 0x6B, 0x78, 0x74, 0x2F, 0x63, 0x6F, 0x6E, 0x33, 0x59, 0x53, 0x37, 0x71, 0x43, 0x30, 0x6C, 0x48, 0x34, 0x5A, 0x72, 0x38, 0x47, 0x52, 0x75, 0x52, 0x35, 0x4B, 0x69, 0x59, 0x32, 0x65, 0x59, 0x38, 0x66, 0x0A, 0x54, 0x70, 0x6B, 0x64, 0x73, ++ 0x6F, 0x38, 0x4D, 0x44, 0x68, 0x7A, 0x2F, 0x79, 0x56, 0x33, 0x41, 0x2F, 0x5A, 0x41, 0x51, 0x70, 0x72, 0x45, 0x33, 0x38, 0x38, 0x30, 0x36, 0x4A, 0x47, 0x36, 0x30, 0x68, 0x5A, 0x43, 0x2F, 0x67, 0x4C, 0x6B, 0x4D, 0x6A, 0x4E, 0x57, 0x62, 0x31, ++ 0x73, 0x6A, 0x78, 0x56, 0x6A, 0x38, 0x61, 0x67, 0x49, 0x6C, 0x36, 0x71, 0x65, 0x49, 0x62, 0x4D, 0x6C, 0x45, 0x73, 0x50, 0x76, 0x4C, 0x66, 0x65, 0x2F, 0x5A, 0x64, 0x65, 0x69, 0x6B, 0x5A, 0x0A, 0x6A, 0x75, 0x58, 0x49, 0x76, 0x54, 0x5A, 0x78, ++ 0x69, 0x31, 0x31, 0x4D, 0x77, 0x68, 0x30, 0x2F, 0x72, 0x56, 0x69, 0x69, 0x7A, 0x7A, 0x31, 0x77, 0x54, 0x61, 0x5A, 0x51, 0x6D, 0x43, 0x58, 0x63, 0x49, 0x2F, 0x6D, 0x34, 0x57, 0x45, 0x45, 0x49, 0x63, 0x62, 0x39, 0x50, 0x75, 0x49, 0x53, 0x67, ++ 0x6A, 0x77, 0x42, 0x55, 0x46, 0x66, 0x79, 0x52, 0x62, 0x56, 0x69, 0x6E, 0x6C, 0x6A, 0x76, 0x72, 0x53, 0x35, 0x59, 0x6E, 0x7A, 0x57, 0x75, 0x69, 0x6F, 0x59, 0x61, 0x73, 0x0A, 0x44, 0x58, 0x78, 0x55, 0x35, 0x6D, 0x5A, 0x4D, 0x5A, 0x6C, 0x2B, ++ 0x51, 0x76, 0x69, 0x47, 0x61, 0x41, 0x6B, 0x59, 0x74, 0x35, 0x49, 0x50, 0x43, 0x67, 0x4C, 0x6E, 0x50, 0x53, 0x7A, 0x37, 0x6F, 0x66, 0x7A, 0x77, 0x42, 0x37, 0x49, 0x39, 0x65, 0x7A, 0x58, 0x2F, 0x53, 0x4B, 0x45, 0x49, 0x42, 0x6C, 0x59, 0x72, ++ 0x69, 0x6C, 0x7A, 0x30, 0x51, 0x49, 0x58, 0x33, 0x32, 0x6E, 0x52, 0x7A, 0x46, 0x4E, 0x4B, 0x48, 0x73, 0x4C, 0x41, 0x34, 0x4B, 0x55, 0x69, 0x77, 0x53, 0x0A, 0x56, 0x58, 0x41, 0x6B, 0x50, 0x63, 0x76, 0x43, 0x46, 0x44, 0x56, 0x44, 0x58, 0x53, ++ 0x64, 0x4F, 0x76, 0x73, 0x43, 0x39, 0x71, 0x6E, 0x79, 0x57, 0x35, 0x2F, 0x79, 0x65, 0x59, 0x61, 0x31, 0x45, 0x30, 0x77, 0x43, 0x58, 0x41, 0x67, 0x4D, 0x42, 0x41, 0x41, 0x47, 0x6A, 0x59, 0x7A, 0x42, 0x68, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, ++ 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x51, 0x47, 0x6D, 0x70, 0x73, 0x66, 0x55, 0x33, 0x33, 0x78, 0x39, 0x61, 0x54, 0x49, 0x0A, 0x30, 0x34, 0x59, 0x2B, 0x6F, 0x58, 0x4E, 0x5A, 0x74, 0x50, 0x64, 0x45, 0x49, 0x54, 0x41, 0x50, 0x42, ++ 0x67, 0x4E, 0x56, 0x48, 0x52, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x54, 0x41, 0x44, 0x41, 0x51, 0x48, 0x2F, 0x4D, 0x42, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x49, 0x77, 0x51, 0x59, 0x4D, 0x42, 0x61, 0x41, 0x46, 0x41, 0x61, 0x61, 0x6D, ++ 0x78, 0x39, 0x54, 0x66, 0x66, 0x48, 0x31, 0x70, 0x4D, 0x6A, 0x54, 0x68, 0x6A, 0x36, 0x68, 0x63, 0x31, 0x6D, 0x30, 0x0A, 0x39, 0x30, 0x51, 0x68, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, ++ 0x41, 0x77, 0x49, 0x42, 0x42, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x67, 0x45, 0x41, 0x71, 0x67, 0x56, 0x75, 0x74, 0x74, 0x30, 0x56, ++ 0x79, 0x62, 0x2B, 0x7A, 0x78, 0x69, 0x44, 0x32, 0x42, 0x6B, 0x65, 0x77, 0x68, 0x70, 0x4D, 0x6C, 0x0A, 0x30, 0x34, 0x32, 0x35, 0x79, 0x41, 0x41, 0x2F, 0x6C, 0x2F, 0x56, 0x53, 0x4A, 0x34, 0x68, 0x78, 0x79, 0x58, 0x54, 0x39, 0x36, 0x38, 0x70, ++ 0x6B, 0x32, 0x31, 0x76, 0x76, 0x48, 0x6C, 0x32, 0x36, 0x76, 0x39, 0x48, 0x72, 0x37, 0x6C, 0x78, 0x70, 0x75, 0x68, 0x62, 0x49, 0x38, 0x37, 0x6D, 0x50, 0x30, 0x7A, 0x59, 0x75, 0x51, 0x45, 0x6B, 0x48, 0x44, 0x56, 0x6E, 0x65, 0x69, 0x78, 0x43, ++ 0x77, 0x53, 0x51, 0x58, 0x69, 0x2F, 0x35, 0x45, 0x2F, 0x53, 0x37, 0x66, 0x64, 0x0A, 0x41, 0x6F, 0x37, 0x34, 0x67, 0x53, 0x68, 0x63, 0x7A, 0x4E, 0x78, 0x74, 0x72, 0x31, 0x38, 0x55, 0x6E, 0x48, 0x31, 0x59, 0x65, 0x41, 0x33, 0x32, 0x67, 0x41, ++ 0x6D, 0x35, 0x36, 0x51, 0x36, 0x58, 0x4B, 0x52, 0x6D, 0x34, 0x74, 0x2B, 0x76, 0x34, 0x46, 0x73, 0x74, 0x56, 0x45, 0x75, 0x54, 0x47, 0x66, 0x62, 0x76, 0x45, 0x37, 0x50, 0x69, 0x31, 0x48, 0x45, 0x34, 0x2B, 0x5A, 0x37, 0x2F, 0x46, 0x58, 0x78, ++ 0x74, 0x74, 0x62, 0x55, 0x63, 0x6F, 0x71, 0x67, 0x52, 0x59, 0x0A, 0x59, 0x64, 0x5A, 0x32, 0x76, 0x79, 0x4A, 0x2F, 0x30, 0x41, 0x64, 0x71, 0x70, 0x32, 0x52, 0x54, 0x38, 0x4A, 0x65, 0x4E, 0x6E, 0x59, 0x41, 0x2F, 0x75, 0x38, 0x45, 0x48, 0x32, ++ 0x32, 0x57, 0x76, 0x35, 0x70, 0x73, 0x79, 0x6D, 0x73, 0x4E, 0x55, 0x6B, 0x38, 0x51, 0x63, 0x43, 0x4D, 0x4E, 0x45, 0x2B, 0x33, 0x74, 0x6A, 0x45, 0x55, 0x50, 0x52, 0x61, 0x68, 0x70, 0x68, 0x61, 0x6E, 0x6C, 0x74, 0x6B, 0x45, 0x38, 0x70, 0x6A, ++ 0x6B, 0x63, 0x46, 0x77, 0x52, 0x4A, 0x70, 0x0A, 0x61, 0x64, 0x62, 0x47, 0x4E, 0x6A, 0x48, 0x68, 0x2F, 0x50, 0x71, 0x41, 0x75, 0x6C, 0x78, 0x50, 0x78, 0x4F, 0x75, 0x33, 0x4D, 0x71, 0x7A, 0x34, 0x64, 0x57, 0x45, 0x58, 0x31, 0x78, 0x41, 0x5A, ++ 0x75, 0x66, 0x48, 0x53, 0x43, 0x65, 0x39, 0x36, 0x51, 0x70, 0x31, 0x62, 0x57, 0x67, 0x76, 0x55, 0x78, 0x70, 0x56, 0x4F, 0x4B, 0x73, 0x37, 0x2F, 0x42, 0x39, 0x64, 0x50, 0x66, 0x68, 0x67, 0x47, 0x69, 0x50, 0x45, 0x5A, 0x74, 0x64, 0x6D, 0x59, ++ 0x75, 0x36, 0x35, 0x78, 0x0A, 0x78, 0x42, 0x7A, 0x6E, 0x64, 0x46, 0x6C, 0x59, 0x37, 0x77, 0x79, 0x4A, 0x7A, 0x34, 0x73, 0x66, 0x64, 0x5A, 0x4D, 0x61, 0x42, 0x42, 0x53, 0x53, 0x53, 0x46, 0x43, 0x70, 0x36, 0x31, 0x63, 0x70, 0x41, 0x42, 0x62, ++ 0x6A, 0x4E, 0x68, 0x7A, 0x49, 0x2B, 0x4C, 0x2F, 0x77, 0x4D, 0x39, 0x56, 0x42, 0x44, 0x38, 0x54, 0x4D, 0x50, 0x4E, 0x33, 0x70, 0x4D, 0x30, 0x4D, 0x42, 0x6B, 0x52, 0x41, 0x72, 0x48, 0x74, 0x47, 0x35, 0x58, 0x63, 0x30, 0x79, 0x47, 0x59, 0x75, ++ 0x50, 0x0A, 0x6A, 0x43, 0x42, 0x33, 0x31, 0x79, 0x4C, 0x45, 0x51, 0x74, 0x79, 0x45, 0x46, 0x70, 0x73, 0x6C, 0x62, 0x65, 0x69, 0x30, 0x56, 0x58, 0x46, 0x2F, 0x73, 0x48, 0x79, 0x7A, 0x30, 0x33, 0x46, 0x4A, 0x75, 0x63, 0x39, 0x53, 0x70, 0x41, ++ 0x51, 0x2F, 0x33, 0x44, 0x32, 0x67, 0x75, 0x36, 0x38, 0x7A, 0x6E, 0x67, 0x6F, 0x77, 0x59, 0x49, 0x37, 0x62, 0x6E, 0x56, 0x32, 0x55, 0x71, 0x4C, 0x31, 0x67, 0x35, 0x32, 0x4B, 0x41, 0x64, 0x6F, 0x47, 0x44, 0x44, 0x49, 0x7A, 0x4D, 0x0A, 0x4D, ++ 0x45, 0x5A, 0x4A, 0x34, 0x67, 0x7A, 0x53, 0x71, 0x4B, 0x2F, 0x72, 0x59, 0x58, 0x48, 0x76, 0x35, 0x79, 0x4A, 0x69, 0x71, 0x66, 0x64, 0x63, 0x5A, 0x47, 0x79, 0x66, 0x46, 0x6F, 0x78, 0x6E, 0x4E, 0x69, 0x64, 0x46, 0x39, 0x51, 0x6C, 0x37, 0x76, ++ 0x2F, 0x59, 0x51, 0x43, 0x76, 0x47, 0x77, 0x6A, 0x56, 0x52, 0x44, 0x6A, 0x41, 0x53, 0x36, 0x6F, 0x7A, 0x2F, 0x76, 0x34, 0x6A, 0x58, 0x48, 0x2B, 0x58, 0x54, 0x67, 0x62, 0x7A, 0x52, 0x42, 0x30, 0x4C, 0x39, 0x7A, 0x0A, 0x5A, 0x56, 0x63, 0x67, ++ 0x2B, 0x5A, 0x74, 0x6E, 0x65, 0x6D, 0x5A, 0x6F, 0x4A, 0x45, 0x36, 0x41, 0x5A, 0x62, 0x30, 0x51, 0x6D, 0x51, 0x5A, 0x5A, 0x38, 0x6D, 0x57, 0x76, 0x75, 0x4D, 0x5A, 0x48, 0x75, 0x2F, 0x32, 0x51, 0x65, 0x49, 0x74, 0x42, 0x63, 0x79, 0x36, 0x76, ++ 0x56, 0x52, 0x2F, 0x63, 0x4F, 0x35, 0x4A, 0x79, 0x62, 0x6F, 0x54, 0x54, 0x30, 0x47, 0x46, 0x4D, 0x44, 0x63, 0x78, 0x32, 0x56, 0x2B, 0x49, 0x74, 0x68, 0x53, 0x49, 0x56, 0x4E, 0x67, 0x33, 0x72, 0x0A, 0x41, 0x5A, 0x33, 0x72, 0x32, 0x4F, 0x76, ++ 0x45, 0x68, 0x4A, 0x6E, 0x37, 0x77, 0x41, 0x7A, 0x4D, 0x4D, 0x75, 0x6A, 0x6A, 0x64, 0x39, 0x71, 0x44, 0x52, 0x49, 0x75, 0x65, 0x56, 0x53, 0x6A, 0x41, 0x69, 0x31, 0x6A, 0x54, 0x6B, 0x44, 0x35, 0x4F, 0x47, 0x77, 0x44, 0x78, 0x46, 0x61, 0x32, ++ 0x44, 0x4B, 0x35, 0x6F, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x48, 0x41, 0x52, 0x49, 0x43, 0x41, 0x20, ++ 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x32, 0x31, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, ++ 0x46, 0x70, 0x44, 0x43, 0x43, 0x41, 0x34, 0x79, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x4F, 0x63, 0x71, 0x54, 0x48, 0x4F, 0x39, 0x44, 0x38, 0x38, 0x61, 0x4F, 0x6B, 0x38, 0x66, 0x30, 0x5A, 0x49, 0x6B, 0x34, 0x66, 0x6A, 0x41, ++ 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x44, 0x42, 0x73, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x0A, 0x45, 0x77, 0x4A, 0x48, 0x55, 0x6A, ++ 0x45, 0x33, 0x4D, 0x44, 0x55, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, 0x75, 0x53, 0x47, 0x56, 0x73, 0x62, 0x47, 0x56, 0x75, 0x61, 0x57, 0x4D, 0x67, 0x51, 0x57, 0x4E, 0x68, 0x5A, 0x47, 0x56, 0x74, 0x61, 0x57, 0x4D, 0x67, 0x59, 0x57, ++ 0x35, 0x6B, 0x49, 0x46, 0x4A, 0x6C, 0x63, 0x32, 0x56, 0x68, 0x63, 0x6D, 0x4E, 0x6F, 0x49, 0x45, 0x6C, 0x75, 0x63, 0x33, 0x52, 0x70, 0x64, 0x48, 0x56, 0x30, 0x61, 0x57, 0x39, 0x75, 0x0A, 0x63, 0x79, 0x42, 0x44, 0x51, 0x54, 0x45, 0x6B, 0x4D, ++ 0x43, 0x49, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x77, 0x77, 0x62, 0x53, 0x45, 0x46, 0x53, 0x53, 0x55, 0x4E, 0x42, 0x49, 0x46, 0x52, 0x4D, 0x55, 0x79, 0x42, 0x53, 0x55, 0x30, 0x45, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x51, ++ 0x53, 0x41, 0x79, 0x4D, 0x44, 0x49, 0x78, 0x4D, 0x42, 0x34, 0x58, 0x44, 0x54, 0x49, 0x78, 0x4D, 0x44, 0x49, 0x78, 0x4F, 0x54, 0x45, 0x77, 0x4E, 0x54, 0x55, 0x7A, 0x0A, 0x4F, 0x46, 0x6F, 0x58, 0x44, 0x54, 0x51, 0x31, 0x4D, 0x44, 0x49, 0x78, ++ 0x4D, 0x7A, 0x45, 0x77, 0x4E, 0x54, 0x55, 0x7A, 0x4E, 0x31, 0x6F, 0x77, 0x62, 0x44, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x52, 0x31, 0x49, 0x78, 0x4E, 0x7A, 0x41, 0x31, 0x42, 0x67, 0x4E, 0x56, ++ 0x42, 0x41, 0x6F, 0x4D, 0x4C, 0x6B, 0x68, 0x6C, 0x62, 0x47, 0x78, 0x6C, 0x62, 0x6D, 0x6C, 0x6A, 0x49, 0x45, 0x46, 0x6A, 0x59, 0x57, 0x52, 0x6C, 0x0A, 0x62, 0x57, 0x6C, 0x6A, 0x49, 0x47, 0x46, 0x75, 0x5A, 0x43, 0x42, 0x53, 0x5A, 0x58, 0x4E, ++ 0x6C, 0x59, 0x58, 0x4A, 0x6A, 0x61, 0x43, 0x42, 0x4A, 0x62, 0x6E, 0x4E, 0x30, 0x61, 0x58, 0x52, 0x31, 0x64, 0x47, 0x6C, 0x76, 0x62, 0x6E, 0x4D, 0x67, 0x51, 0x30, 0x45, 0x78, 0x4A, 0x44, 0x41, 0x69, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, ++ 0x4D, 0x47, 0x30, 0x68, 0x42, 0x55, 0x6B, 0x6C, 0x44, 0x51, 0x53, 0x42, 0x55, 0x54, 0x46, 0x4D, 0x67, 0x55, 0x6C, 0x4E, 0x42, 0x0A, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x67, 0x4D, 0x6A, 0x41, 0x79, 0x4D, 0x54, ++ 0x43, 0x43, 0x41, 0x69, 0x49, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x50, 0x41, 0x44, 0x43, 0x43, 0x41, 0x67, 0x6F, 0x43, 0x67, 0x67, ++ 0x49, 0x42, 0x41, 0x49, 0x76, 0x43, 0x35, 0x36, 0x39, 0x6C, 0x6D, 0x77, 0x56, 0x6E, 0x6C, 0x73, 0x6B, 0x4E, 0x0A, 0x4A, 0x4C, 0x6E, 0x51, 0x44, 0x6D, 0x54, 0x38, 0x7A, 0x75, 0x49, 0x6B, 0x47, 0x43, 0x79, 0x45, 0x66, 0x33, 0x64, 0x52, 0x79, ++ 0x77, 0x51, 0x52, 0x4E, 0x72, 0x68, 0x65, 0x37, 0x57, 0x6C, 0x78, 0x70, 0x35, 0x37, 0x6B, 0x4A, 0x51, 0x6D, 0x58, 0x5A, 0x38, 0x46, 0x48, 0x77, 0x73, 0x2B, 0x52, 0x46, 0x6A, 0x5A, 0x69, 0x50, 0x54, 0x67, 0x45, 0x34, 0x56, 0x47, 0x43, 0x2F, ++ 0x36, 0x7A, 0x53, 0x74, 0x47, 0x6E, 0x64, 0x4C, 0x75, 0x77, 0x52, 0x6F, 0x30, 0x58, 0x75, 0x0A, 0x61, 0x32, 0x73, 0x37, 0x54, 0x4C, 0x2B, 0x4D, 0x6A, 0x61, 0x51, 0x65, 0x6E, 0x52, 0x47, 0x35, 0x36, 0x54, 0x6A, 0x35, 0x65, 0x67, 0x34, 0x4D, ++ 0x6D, 0x4F, 0x49, 0x6A, 0x48, 0x64, 0x46, 0x4F, 0x59, 0x39, 0x54, 0x6E, 0x75, 0x45, 0x46, 0x45, 0x2B, 0x32, 0x75, 0x76, 0x61, 0x39, 0x6F, 0x66, 0x30, 0x38, 0x57, 0x52, 0x69, 0x46, 0x75, 0x6B, 0x69, 0x5A, 0x4C, 0x52, 0x67, 0x65, 0x61, 0x4D, ++ 0x4F, 0x56, 0x69, 0x67, 0x31, 0x6D, 0x6C, 0x44, 0x71, 0x61, 0x32, 0x59, 0x0A, 0x55, 0x6C, 0x68, 0x75, 0x32, 0x77, 0x72, 0x37, 0x61, 0x38, 0x39, 0x6F, 0x2B, 0x75, 0x4F, 0x6B, 0x58, 0x6A, 0x70, 0x46, 0x63, 0x35, 0x67, 0x48, 0x36, 0x6C, 0x38, ++ 0x43, 0x63, 0x74, 0x34, 0x4D, 0x70, 0x62, 0x4F, 0x66, 0x72, 0x71, 0x6B, 0x64, 0x74, 0x78, 0x32, 0x7A, 0x2F, 0x49, 0x70, 0x5A, 0x35, 0x32, 0x35, 0x79, 0x5A, 0x61, 0x33, 0x31, 0x4D, 0x4A, 0x51, 0x6A, 0x42, 0x2F, 0x4F, 0x43, 0x46, 0x6B, 0x73, ++ 0x31, 0x6D, 0x4A, 0x78, 0x54, 0x75, 0x79, 0x2F, 0x4B, 0x0A, 0x35, 0x46, 0x72, 0x5A, 0x78, 0x34, 0x30, 0x64, 0x2F, 0x4A, 0x69, 0x5A, 0x2B, 0x79, 0x79, 0x6B, 0x67, 0x6D, 0x76, 0x77, 0x4B, 0x68, 0x2B, 0x4F, 0x43, 0x31, 0x39, 0x78, 0x58, 0x46, ++ 0x79, 0x75, 0x51, 0x6E, 0x73, 0x70, 0x69, 0x59, 0x48, 0x4C, 0x41, 0x36, 0x4F, 0x5A, 0x79, 0x6F, 0x69, 0x65, 0x43, 0x30, 0x41, 0x4A, 0x51, 0x54, 0x50, 0x62, 0x35, 0x6C, 0x68, 0x36, 0x2F, 0x61, 0x36, 0x5A, 0x63, 0x4D, 0x42, 0x61, 0x44, 0x39, ++ 0x59, 0x54, 0x68, 0x6E, 0x45, 0x76, 0x0A, 0x64, 0x6D, 0x6E, 0x38, 0x6B, 0x4E, 0x33, 0x62, 0x4C, 0x57, 0x37, 0x52, 0x38, 0x70, 0x76, 0x31, 0x47, 0x6D, 0x75, 0x65, 0x62, 0x78, 0x57, 0x4D, 0x65, 0x76, 0x42, 0x4C, 0x4B, 0x4B, 0x41, 0x69, 0x4F, ++ 0x49, 0x41, 0x6B, 0x62, 0x44, 0x61, 0x6B, 0x4F, 0x2F, 0x49, 0x77, 0x6B, 0x66, 0x4E, 0x34, 0x45, 0x38, 0x2F, 0x42, 0x50, 0x7A, 0x57, 0x72, 0x38, 0x52, 0x30, 0x52, 0x49, 0x37, 0x56, 0x44, 0x49, 0x70, 0x34, 0x42, 0x6B, 0x72, 0x63, 0x59, 0x41, ++ 0x75, 0x55, 0x52, 0x0A, 0x30, 0x59, 0x4C, 0x62, 0x46, 0x51, 0x44, 0x4D, 0x59, 0x54, 0x66, 0x42, 0x4B, 0x6E, 0x79, 0x61, 0x34, 0x64, 0x43, 0x36, 0x73, 0x31, 0x42, 0x47, 0x37, 0x6F, 0x4B, 0x73, 0x6E, 0x54, 0x48, 0x34, 0x2B, 0x79, 0x50, 0x69, ++ 0x41, 0x77, 0x42, 0x49, 0x63, 0x4B, 0x4D, 0x4A, 0x4A, 0x6E, 0x6B, 0x56, 0x55, 0x32, 0x44, 0x7A, 0x4F, 0x46, 0x79, 0x74, 0x4F, 0x4F, 0x71, 0x42, 0x41, 0x47, 0x4D, 0x55, 0x75, 0x54, 0x4E, 0x65, 0x33, 0x51, 0x76, 0x62, 0x6F, 0x45, 0x55, 0x48, ++ 0x0A, 0x47, 0x6A, 0x4D, 0x4A, 0x2B, 0x45, 0x32, 0x30, 0x70, 0x77, 0x4B, 0x6D, 0x61, 0x66, 0x54, 0x43, 0x57, 0x51, 0x57, 0x49, 0x5A, 0x59, 0x56, 0x57, 0x72, 0x6B, 0x76, 0x4C, 0x34, 0x4E, 0x34, 0x38, 0x66, 0x53, 0x30, 0x61, 0x79, 0x4F, 0x6E, ++ 0x37, 0x48, 0x36, 0x4E, 0x68, 0x53, 0x74, 0x59, 0x71, 0x45, 0x36, 0x31, 0x33, 0x54, 0x42, 0x6F, 0x59, 0x6D, 0x35, 0x45, 0x50, 0x57, 0x4E, 0x67, 0x47, 0x56, 0x4D, 0x57, 0x58, 0x2B, 0x4B, 0x6F, 0x2F, 0x49, 0x49, 0x71, 0x6D, 0x0A, 0x68, 0x61, ++ 0x5A, 0x33, 0x39, 0x71, 0x62, 0x38, 0x48, 0x4F, 0x4C, 0x75, 0x62, 0x70, 0x51, 0x7A, 0x4B, 0x6F, 0x4E, 0x51, 0x68, 0x41, 0x72, 0x6C, 0x54, 0x34, 0x62, 0x34, 0x55, 0x45, 0x56, 0x34, 0x41, 0x49, 0x48, 0x72, 0x57, 0x32, 0x6A, 0x6A, 0x4A, 0x6F, ++ 0x33, 0x4D, 0x65, 0x31, 0x78, 0x52, 0x39, 0x42, 0x51, 0x73, 0x51, 0x4C, 0x34, 0x61, 0x59, 0x42, 0x31, 0x36, 0x63, 0x6D, 0x45, 0x64, 0x48, 0x32, 0x4D, 0x74, 0x69, 0x4B, 0x72, 0x4F, 0x6F, 0x6B, 0x57, 0x51, 0x0A, 0x43, 0x50, 0x78, 0x72, 0x76, ++ 0x72, 0x4E, 0x51, 0x4B, 0x6C, 0x72, 0x39, 0x71, 0x45, 0x67, 0x59, 0x52, 0x74, 0x61, 0x51, 0x51, 0x4A, 0x4B, 0x51, 0x43, 0x6F, 0x52, 0x65, 0x61, 0x44, 0x48, 0x34, 0x36, 0x2B, 0x30, 0x4E, 0x30, 0x78, 0x33, 0x47, 0x66, 0x5A, 0x6B, 0x59, 0x56, ++ 0x56, 0x59, 0x6E, 0x5A, 0x53, 0x36, 0x4E, 0x52, 0x63, 0x55, 0x6B, 0x37, 0x4D, 0x37, 0x6A, 0x41, 0x67, 0x4D, 0x42, 0x41, 0x41, 0x47, 0x6A, 0x51, 0x6A, 0x42, 0x41, 0x4D, 0x41, 0x38, 0x47, 0x0A, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, ++ 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x48, 0x51, 0x59, 0x44, 0x56, 0x52, 0x30, 0x4F, 0x42, 0x42, 0x59, 0x45, 0x46, 0x41, 0x70, 0x49, 0x49, 0x36, 0x5A, 0x67, 0x70, 0x4A, 0x49, 0x4B, 0x4D, 0x2B, 0x71, 0x54, ++ 0x57, 0x38, 0x56, 0x58, 0x36, 0x69, 0x56, 0x4E, 0x76, 0x52, 0x4C, 0x75, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, 0x0A, 0x41, 0x77, 0x49, 0x42, 0x68, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, ++ 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x67, 0x45, 0x41, 0x50, 0x70, 0x42, 0x49, 0x71, 0x6D, 0x35, 0x69, 0x46, 0x53, 0x56, 0x6D, 0x65, 0x77, 0x7A, 0x56, 0x6A, 0x49, 0x75, ++ 0x4A, 0x6E, 0x64, 0x66, 0x74, 0x54, 0x67, 0x66, 0x76, 0x6E, 0x4E, 0x41, 0x55, 0x58, 0x31, 0x35, 0x51, 0x76, 0x57, 0x69, 0x57, 0x6B, 0x4B, 0x51, 0x55, 0x0A, 0x45, 0x61, 0x70, 0x6F, 0x62, 0x51, 0x6B, 0x31, 0x4F, 0x55, 0x41, 0x4A, 0x32, 0x76, ++ 0x51, 0x4A, 0x4C, 0x44, 0x53, 0x6C, 0x65, 0x31, 0x6D, 0x45, 0x53, 0x53, 0x6D, 0x58, 0x64, 0x4D, 0x67, 0x48, 0x48, 0x6B, 0x64, 0x74, 0x38, 0x73, 0x34, 0x63, 0x55, 0x43, 0x62, 0x6A, 0x6E, 0x6A, 0x31, 0x41, 0x55, 0x7A, 0x2F, 0x33, 0x66, 0x35, ++ 0x5A, 0x32, 0x45, 0x4D, 0x56, 0x47, 0x70, 0x64, 0x41, 0x67, 0x53, 0x31, 0x44, 0x30, 0x4E, 0x54, 0x73, 0x59, 0x39, 0x46, 0x56, 0x71, 0x0A, 0x51, 0x52, 0x74, 0x48, 0x42, 0x6D, 0x67, 0x38, 0x75, 0x77, 0x6B, 0x49, 0x59, 0x74, 0x6C, 0x66, 0x56, ++ 0x55, 0x4B, 0x71, 0x72, 0x46, 0x4F, 0x46, 0x72, 0x4A, 0x56, 0x57, 0x4E, 0x6C, 0x61, 0x72, 0x35, 0x41, 0x57, 0x4D, 0x78, 0x61, 0x6A, 0x61, 0x48, 0x36, 0x4E, 0x70, 0x76, 0x56, 0x4D, 0x50, 0x78, 0x50, 0x2F, 0x63, 0x79, 0x75, 0x4E, 0x2B, 0x38, ++ 0x6B, 0x79, 0x49, 0x68, 0x6B, 0x64, 0x47, 0x47, 0x76, 0x4D, 0x41, 0x39, 0x59, 0x43, 0x52, 0x6F, 0x74, 0x78, 0x44, 0x0A, 0x51, 0x70, 0x53, 0x62, 0x49, 0x50, 0x44, 0x52, 0x7A, 0x62, 0x4C, 0x72, 0x4C, 0x46, 0x50, 0x43, 0x55, 0x33, 0x68, 0x4B, ++ 0x54, 0x77, 0x53, 0x55, 0x51, 0x5A, 0x71, 0x50, 0x4A, 0x7A, 0x4C, 0x42, 0x35, 0x55, 0x6B, 0x5A, 0x76, 0x2F, 0x48, 0x79, 0x77, 0x6F, 0x75, 0x6F, 0x43, 0x6A, 0x6B, 0x78, 0x4B, 0x4C, 0x52, 0x39, 0x59, 0x6A, 0x59, 0x73, 0x54, 0x65, 0x77, 0x66, ++ 0x4D, 0x37, 0x5A, 0x2B, 0x64, 0x32, 0x31, 0x2B, 0x55, 0x50, 0x43, 0x66, 0x44, 0x74, 0x63, 0x52, 0x0A, 0x6A, 0x38, 0x38, 0x59, 0x78, 0x65, 0x4D, 0x6E, 0x2F, 0x69, 0x62, 0x76, 0x42, 0x5A, 0x33, 0x50, 0x7A, 0x7A, 0x66, 0x46, 0x30, 0x48, 0x76, ++ 0x61, 0x4F, 0x37, 0x41, 0x57, 0x68, 0x41, 0x77, 0x36, 0x6B, 0x39, 0x61, 0x2B, 0x46, 0x39, 0x73, 0x50, 0x50, 0x67, 0x34, 0x5A, 0x65, 0x41, 0x6E, 0x48, 0x71, 0x51, 0x4A, 0x79, 0x49, 0x6B, 0x76, 0x33, 0x4E, 0x33, 0x61, 0x36, 0x64, 0x63, 0x53, ++ 0x46, 0x41, 0x31, 0x70, 0x6A, 0x31, 0x62, 0x46, 0x31, 0x42, 0x63, 0x4B, 0x35, 0x0A, 0x76, 0x5A, 0x53, 0x74, 0x6A, 0x42, 0x57, 0x5A, 0x70, 0x35, 0x4E, 0x39, 0x39, 0x73, 0x58, 0x7A, 0x71, 0x6E, 0x54, 0x50, 0x42, 0x49, 0x57, 0x55, 0x6D, 0x41, ++ 0x44, 0x30, 0x34, 0x76, 0x6E, 0x4B, 0x4A, 0x47, 0x57, 0x2F, 0x34, 0x47, 0x4B, 0x76, 0x79, 0x4D, 0x58, 0x36, 0x73, 0x73, 0x6D, 0x65, 0x56, 0x6B, 0x6A, 0x61, 0x65, 0x66, 0x32, 0x57, 0x64, 0x68, 0x57, 0x2B, 0x6F, 0x34, 0x35, 0x57, 0x78, 0x4C, ++ 0x4D, 0x30, 0x2F, 0x4C, 0x35, 0x48, 0x39, 0x4D, 0x47, 0x30, 0x0A, 0x71, 0x50, 0x7A, 0x56, 0x4D, 0x49, 0x68, 0x6F, 0x37, 0x73, 0x75, 0x75, 0x79, 0x57, 0x50, 0x45, 0x64, 0x72, 0x36, 0x73, 0x4F, 0x42, 0x6A, 0x68, 0x58, 0x6C, 0x7A, 0x50, 0x72, ++ 0x6A, 0x6F, 0x69, 0x55, 0x65, 0x76, 0x52, 0x69, 0x37, 0x50, 0x7A, 0x4B, 0x7A, 0x4D, 0x48, 0x56, 0x49, 0x66, 0x36, 0x74, 0x4C, 0x49, 0x54, 0x65, 0x37, 0x70, 0x54, 0x42, 0x47, 0x49, 0x42, 0x6E, 0x66, 0x48, 0x41, 0x54, 0x2B, 0x37, 0x68, 0x4F, ++ 0x74, 0x53, 0x4C, 0x49, 0x42, 0x44, 0x36, 0x0A, 0x41, 0x6C, 0x66, 0x6D, 0x37, 0x38, 0x45, 0x4C, 0x74, 0x35, 0x42, 0x47, 0x6E, 0x42, 0x6B, 0x70, 0x6A, 0x4E, 0x78, 0x76, 0x6F, 0x45, 0x70, 0x70, 0x61, 0x5A, 0x53, 0x33, 0x4A, 0x47, 0x57, 0x67, ++ 0x2F, 0x36, 0x77, 0x2F, 0x7A, 0x67, 0x48, 0x37, 0x49, 0x53, 0x37, 0x39, 0x61, 0x50, 0x69, 0x62, 0x38, 0x71, 0x58, 0x50, 0x4D, 0x54, 0x68, 0x63, 0x46, 0x61, 0x72, 0x6D, 0x6C, 0x77, 0x44, 0x42, 0x33, 0x31, 0x71, 0x6C, 0x70, 0x7A, 0x6D, 0x71, ++ 0x36, 0x59, 0x52, 0x2F, 0x0A, 0x50, 0x46, 0x47, 0x6F, 0x4F, 0x74, 0x6D, 0x55, 0x57, 0x34, 0x79, 0x2F, 0x54, 0x77, 0x68, 0x78, 0x35, 0x64, 0x75, 0x6F, 0x58, 0x4E, 0x54, 0x53, 0x70, 0x76, 0x34, 0x41, 0x6F, 0x38, 0x59, 0x57, 0x78, 0x77, 0x2F, ++ 0x6F, 0x67, 0x4D, 0x34, 0x63, 0x4B, 0x47, 0x52, 0x30, 0x47, 0x51, 0x6A, 0x54, 0x51, 0x75, 0x50, 0x4F, 0x41, 0x46, 0x31, 0x2F, 0x73, 0x64, 0x77, 0x54, 0x73, 0x4F, 0x45, 0x46, 0x79, 0x39, 0x45, 0x67, 0x71, 0x6F, 0x5A, 0x30, 0x6E, 0x6A, 0x6E, ++ 0x6E, 0x0A, 0x6B, 0x66, 0x33, 0x2F, 0x57, 0x39, 0x62, 0x33, 0x72, 0x61, 0x59, 0x76, 0x41, 0x77, 0x74, 0x74, 0x34, 0x31, 0x64, 0x55, 0x36, 0x33, 0x5A, 0x54, 0x47, 0x49, 0x30, 0x52, 0x6D, 0x4C, 0x6F, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, ++ 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x48, 0x41, 0x52, 0x49, 0x43, 0x41, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, ++ 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x32, 0x31, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, ++ 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x43, 0x56, 0x44, 0x43, 0x43, 0x41, 0x64, 0x75, 0x67, 0x41, 0x77, ++ 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x5A, 0x33, 0x53, 0x64, 0x6A, 0x58, 0x66, 0x59, 0x4F, 0x32, 0x72, 0x62, 0x49, 0x76, 0x54, 0x2F, 0x57, 0x65, 0x4B, 0x2F, 0x7A, 0x6A, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, ++ 0x51, 0x44, 0x41, 0x7A, 0x42, 0x73, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x48, 0x0A, 0x55, 0x6A, 0x45, 0x33, 0x4D, 0x44, 0x55, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, 0x75, 0x53, ++ 0x47, 0x56, 0x73, 0x62, 0x47, 0x56, 0x75, 0x61, 0x57, 0x4D, 0x67, 0x51, 0x57, 0x4E, 0x68, 0x5A, 0x47, 0x56, 0x74, 0x61, 0x57, 0x4D, 0x67, 0x59, 0x57, 0x35, 0x6B, 0x49, 0x46, 0x4A, 0x6C, 0x63, 0x32, 0x56, 0x68, 0x63, 0x6D, 0x4E, 0x6F, 0x49, ++ 0x45, 0x6C, 0x75, 0x63, 0x33, 0x52, 0x70, 0x64, 0x48, 0x56, 0x30, 0x61, 0x57, 0x39, 0x75, 0x63, 0x79, 0x42, 0x44, 0x0A, 0x51, 0x54, 0x45, 0x6B, 0x4D, 0x43, 0x49, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x77, 0x77, 0x62, 0x53, 0x45, 0x46, 0x53, ++ 0x53, 0x55, 0x4E, 0x42, 0x49, 0x46, 0x52, 0x4D, 0x55, 0x79, 0x42, 0x46, 0x51, 0x30, 0x4D, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x51, 0x53, 0x41, 0x79, 0x4D, 0x44, 0x49, 0x78, 0x4D, 0x42, 0x34, 0x58, 0x44, 0x54, 0x49, 0x78, ++ 0x4D, 0x44, 0x49, 0x78, 0x4F, 0x54, 0x45, 0x78, 0x4D, 0x44, 0x45, 0x78, 0x4D, 0x46, 0x6F, 0x58, 0x0A, 0x44, 0x54, 0x51, 0x31, 0x4D, 0x44, 0x49, 0x78, 0x4D, 0x7A, 0x45, 0x78, 0x4D, 0x44, 0x45, 0x77, 0x4F, 0x56, 0x6F, 0x77, 0x62, 0x44, 0x45, ++ 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x52, 0x31, 0x49, 0x78, 0x4E, 0x7A, 0x41, 0x31, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x4D, 0x4C, 0x6B, 0x68, 0x6C, 0x62, 0x47, 0x78, 0x6C, 0x62, 0x6D, 0x6C, ++ 0x6A, 0x49, 0x45, 0x46, 0x6A, 0x59, 0x57, 0x52, 0x6C, 0x62, 0x57, 0x6C, 0x6A, 0x0A, 0x49, 0x47, 0x46, 0x75, 0x5A, 0x43, 0x42, 0x53, 0x5A, 0x58, 0x4E, 0x6C, 0x59, 0x58, 0x4A, 0x6A, 0x61, 0x43, 0x42, 0x4A, 0x62, 0x6E, 0x4E, 0x30, 0x61, 0x58, ++ 0x52, 0x31, 0x64, 0x47, 0x6C, 0x76, 0x62, 0x6E, 0x4D, 0x67, 0x51, 0x30, 0x45, 0x78, 0x4A, 0x44, 0x41, 0x69, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x4D, 0x47, 0x30, 0x68, 0x42, 0x55, 0x6B, 0x6C, 0x44, 0x51, 0x53, 0x42, 0x55, 0x54, 0x46, ++ 0x4D, 0x67, 0x52, 0x55, 0x4E, 0x44, 0x49, 0x46, 0x4A, 0x76, 0x0A, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x67, 0x4D, 0x6A, 0x41, 0x79, 0x4D, 0x54, 0x42, 0x32, 0x4D, 0x42, 0x41, 0x47, 0x42, 0x79, 0x71, 0x47, 0x53, 0x4D, 0x34, 0x39, 0x41, ++ 0x67, 0x45, 0x47, 0x42, 0x53, 0x75, 0x42, 0x42, 0x41, 0x41, 0x69, 0x41, 0x32, 0x49, 0x41, 0x42, 0x44, 0x67, 0x49, 0x2F, 0x72, 0x47, 0x67, 0x6C, 0x74, 0x4A, 0x36, 0x72, 0x4B, 0x39, 0x4A, 0x4F, 0x74, 0x44, 0x41, 0x34, 0x4D, 0x4D, 0x37, 0x4B, ++ 0x4B, 0x72, 0x78, 0x63, 0x6D, 0x31, 0x6C, 0x0A, 0x41, 0x45, 0x65, 0x49, 0x68, 0x50, 0x79, 0x61, 0x4A, 0x6D, 0x75, 0x71, 0x53, 0x37, 0x70, 0x73, 0x42, 0x41, 0x71, 0x49, 0x58, 0x68, 0x66, 0x79, 0x56, 0x59, 0x66, 0x38, 0x4D, 0x4C, 0x41, 0x30, ++ 0x34, 0x6A, 0x52, 0x59, 0x56, 0x78, 0x71, 0x45, 0x55, 0x2B, 0x6B, 0x77, 0x32, 0x61, 0x6E, 0x79, 0x6C, 0x6E, 0x54, 0x44, 0x55, 0x52, 0x39, 0x59, 0x53, 0x54, 0x48, 0x4D, 0x6D, 0x45, 0x35, 0x67, 0x45, 0x59, 0x64, 0x31, 0x30, 0x33, 0x4B, 0x55, ++ 0x6B, 0x45, 0x2B, 0x62, 0x0A, 0x45, 0x43, 0x55, 0x71, 0x71, 0x48, 0x67, 0x74, 0x76, 0x70, 0x42, 0x42, 0x57, 0x4A, 0x41, 0x56, 0x63, 0x71, 0x65, 0x68, 0x74, 0x36, 0x4E, 0x43, 0x4D, 0x45, 0x41, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, ++ 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x79, 0x52, 0x74, 0x54, 0x67, 0x52, 0x4C, 0x2B, 0x42, 0x4E, 0x55, ++ 0x57, 0x0A, 0x30, 0x61, 0x71, 0x38, 0x6D, 0x6D, 0x2B, 0x33, 0x6F, 0x4A, 0x55, 0x5A, 0x62, 0x73, 0x6F, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x51, 0x44, 0x41, 0x67, 0x47, 0x47, 0x4D, 0x41, ++ 0x6F, 0x47, 0x43, 0x43, 0x71, 0x47, 0x53, 0x4D, 0x34, 0x39, 0x42, 0x41, 0x4D, 0x44, 0x41, 0x32, 0x63, 0x41, 0x4D, 0x47, 0x51, 0x43, 0x4D, 0x42, 0x48, 0x65, 0x72, 0x76, 0x6A, 0x63, 0x54, 0x6F, 0x69, 0x77, 0x71, 0x66, 0x41, 0x69, 0x0A, 0x72, ++ 0x63, 0x4A, 0x52, 0x51, 0x4F, 0x39, 0x67, 0x63, 0x53, 0x33, 0x75, 0x6A, 0x77, 0x4C, 0x45, 0x58, 0x51, 0x4E, 0x77, 0x53, 0x61, 0x53, 0x53, 0x36, 0x73, 0x55, 0x55, 0x69, 0x48, 0x43, 0x6D, 0x30, 0x77, 0x32, 0x77, 0x71, 0x73, 0x6F, 0x73, 0x51, ++ 0x4A, 0x7A, 0x37, 0x36, 0x59, 0x4A, 0x75, 0x6D, 0x67, 0x49, 0x77, 0x4B, 0x30, 0x65, 0x61, 0x42, 0x38, 0x62, 0x52, 0x77, 0x6F, 0x46, 0x38, 0x79, 0x67, 0x75, 0x57, 0x47, 0x45, 0x45, 0x62, 0x6F, 0x2F, 0x51, 0x77, 0x0A, 0x43, 0x5A, 0x36, 0x31, ++ 0x49, 0x79, 0x67, 0x4E, 0x6E, 0x78, 0x53, 0x32, 0x50, 0x46, 0x4F, 0x69, 0x54, 0x41, 0x5A, 0x70, 0x66, 0x66, 0x70, 0x73, 0x6B, 0x63, 0x59, 0x71, 0x53, 0x55, 0x58, 0x6D, 0x37, 0x4C, 0x63, 0x54, 0x34, 0x54, 0x70, 0x73, 0x0A, 0x2D, 0x2D, 0x2D, ++ 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x41, 0x75, 0x74, 0x6F, 0x72, 0x69, 0x64, 0x61, 0x64, 0x20, 0x64, 0x65, 0x20, 0x43, 0x65, 0x72, ++ 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x63, 0x69, 0x6F, 0x6E, 0x20, 0x46, 0x69, 0x72, 0x6D, 0x61, 0x70, 0x72, 0x6F, 0x66, 0x65, 0x73, 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x20, 0x43, 0x49, 0x46, 0x20, 0x41, 0x36, 0x32, 0x36, 0x33, 0x34, 0x30, 0x36, ++ 0x38, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, ++ 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x47, 0x46, 0x44, 0x43, 0x43, 0x41, 0x2F, 0x79, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x49, 0x47, 0x33, 0x44, 0x70, 0x30, 0x76, 0x2B, 0x75, 0x62, 0x48, 0x45, 0x77, ++ 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x42, 0x51, 0x41, 0x77, 0x55, 0x54, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x52, 0x56, 0x4D, 0x78, ++ 0x51, 0x6A, 0x42, 0x41, 0x0A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x4D, 0x4F, 0x55, 0x46, 0x31, 0x64, 0x47, 0x39, 0x79, 0x61, 0x57, 0x52, 0x68, 0x5A, 0x43, 0x42, 0x6B, 0x5A, 0x53, 0x42, 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x61, 0x57, 0x5A, ++ 0x70, 0x59, 0x32, 0x46, 0x6A, 0x61, 0x57, 0x39, 0x75, 0x49, 0x45, 0x5A, 0x70, 0x63, 0x6D, 0x31, 0x68, 0x63, 0x48, 0x4A, 0x76, 0x5A, 0x6D, 0x56, 0x7A, 0x61, 0x57, 0x39, 0x75, 0x59, 0x57, 0x77, 0x67, 0x51, 0x30, 0x6C, 0x47, 0x49, 0x45, 0x45, ++ 0x32, 0x0A, 0x4D, 0x6A, 0x59, 0x7A, 0x4E, 0x44, 0x41, 0x32, 0x4F, 0x44, 0x41, 0x65, 0x46, 0x77, 0x30, 0x78, 0x4E, 0x44, 0x41, 0x35, 0x4D, 0x6A, 0x4D, 0x78, 0x4E, 0x54, 0x49, 0x79, 0x4D, 0x44, 0x64, 0x61, 0x46, 0x77, 0x30, 0x7A, 0x4E, 0x6A, ++ 0x41, 0x31, 0x4D, 0x44, 0x55, 0x78, 0x4E, 0x54, 0x49, 0x79, 0x4D, 0x44, 0x64, 0x61, 0x4D, 0x46, 0x45, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6B, 0x56, 0x54, 0x4D, 0x55, 0x49, 0x77, 0x0A, 0x51, ++ 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x44, 0x44, 0x6C, 0x42, 0x64, 0x58, 0x52, 0x76, 0x63, 0x6D, 0x6C, 0x6B, 0x59, 0x57, 0x51, 0x67, 0x5A, 0x47, 0x55, 0x67, 0x51, 0x32, 0x56, 0x79, 0x64, 0x47, 0x6C, 0x6D, 0x61, 0x57, 0x4E, 0x68, 0x59, ++ 0x32, 0x6C, 0x76, 0x62, 0x69, 0x42, 0x47, 0x61, 0x58, 0x4A, 0x74, 0x59, 0x58, 0x42, 0x79, 0x62, 0x32, 0x5A, 0x6C, 0x63, 0x32, 0x6C, 0x76, 0x62, 0x6D, 0x46, 0x73, 0x49, 0x45, 0x4E, 0x4A, 0x52, 0x69, 0x42, 0x42, 0x0A, 0x4E, 0x6A, 0x49, 0x32, ++ 0x4D, 0x7A, 0x51, 0x77, 0x4E, 0x6A, 0x67, 0x77, 0x67, 0x67, 0x49, 0x69, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x44, 0x77, 0x41, 0x77, ++ 0x67, 0x67, 0x49, 0x4B, 0x41, 0x6F, 0x49, 0x43, 0x41, 0x51, 0x44, 0x4B, 0x6C, 0x6D, 0x75, 0x4F, 0x36, 0x76, 0x6A, 0x37, 0x38, 0x61, 0x49, 0x31, 0x34, 0x48, 0x39, 0x4D, 0x32, 0x75, 0x44, 0x44, 0x0A, 0x55, 0x74, 0x64, 0x39, 0x74, 0x68, 0x44, ++ 0x49, 0x41, 0x6C, 0x36, 0x7A, 0x51, 0x79, 0x72, 0x45, 0x54, 0x32, 0x71, 0x79, 0x79, 0x68, 0x78, 0x64, 0x4B, 0x4A, 0x70, 0x34, 0x45, 0x52, 0x70, 0x70, 0x57, 0x56, 0x65, 0x76, 0x74, 0x53, 0x42, 0x43, 0x35, 0x49, 0x73, 0x50, 0x35, 0x74, 0x39, ++ 0x62, 0x70, 0x67, 0x4F, 0x53, 0x4C, 0x2F, 0x55, 0x52, 0x35, 0x47, 0x4C, 0x58, 0x4D, 0x6E, 0x45, 0x34, 0x32, 0x51, 0x51, 0x4D, 0x63, 0x61, 0x73, 0x39, 0x55, 0x58, 0x34, 0x50, 0x0A, 0x42, 0x39, 0x39, 0x6A, 0x42, 0x56, 0x7A, 0x70, 0x76, 0x35, ++ 0x52, 0x76, 0x77, 0x53, 0x6D, 0x43, 0x77, 0x4C, 0x54, 0x61, 0x55, 0x62, 0x44, 0x42, 0x50, 0x4C, 0x75, 0x74, 0x4E, 0x30, 0x70, 0x63, 0x79, 0x76, 0x46, 0x4C, 0x4E, 0x67, 0x34, 0x6B, 0x71, 0x37, 0x2F, 0x44, 0x68, 0x48, 0x66, 0x39, 0x71, 0x46, ++ 0x44, 0x30, 0x73, 0x65, 0x66, 0x47, 0x4C, 0x39, 0x49, 0x74, 0x57, 0x59, 0x31, 0x36, 0x43, 0x6B, 0x36, 0x57, 0x61, 0x56, 0x49, 0x43, 0x71, 0x6A, 0x61, 0x59, 0x0A, 0x37, 0x50, 0x7A, 0x36, 0x46, 0x49, 0x4D, 0x4D, 0x4E, 0x78, 0x2F, 0x4A, 0x6B, ++ 0x6A, 0x64, 0x2F, 0x31, 0x34, 0x45, 0x74, 0x35, 0x63, 0x53, 0x35, 0x34, 0x44, 0x34, 0x30, 0x2F, 0x6D, 0x66, 0x30, 0x50, 0x6D, 0x62, 0x52, 0x30, 0x2F, 0x52, 0x41, 0x7A, 0x31, 0x35, 0x69, 0x4E, 0x41, 0x39, 0x77, 0x42, 0x6A, 0x34, 0x67, 0x47, ++ 0x46, 0x72, 0x4F, 0x39, 0x33, 0x49, 0x62, 0x4A, 0x57, 0x79, 0x54, 0x64, 0x42, 0x53, 0x54, 0x6F, 0x33, 0x4F, 0x78, 0x44, 0x71, 0x71, 0x48, 0x0A, 0x45, 0x43, 0x4E, 0x5A, 0x58, 0x79, 0x41, 0x46, 0x47, 0x55, 0x66, 0x74, 0x61, 0x49, 0x36, 0x53, ++ 0x45, 0x73, 0x70, 0x64, 0x2F, 0x4E, 0x59, 0x72, 0x73, 0x70, 0x49, 0x38, 0x49, 0x4D, 0x2F, 0x68, 0x58, 0x36, 0x38, 0x67, 0x76, 0x71, 0x42, 0x32, 0x66, 0x33, 0x62, 0x6C, 0x37, 0x42, 0x71, 0x47, 0x59, 0x54, 0x4D, 0x2B, 0x35, 0x33, 0x75, 0x30, ++ 0x50, 0x36, 0x41, 0x50, 0x6A, 0x71, 0x4B, 0x35, 0x61, 0x6D, 0x2B, 0x35, 0x68, 0x79, 0x5A, 0x76, 0x51, 0x57, 0x79, 0x49, 0x0A, 0x70, 0x6C, 0x44, 0x39, 0x61, 0x6D, 0x4D, 0x4C, 0x39, 0x5A, 0x4D, 0x57, 0x47, 0x78, 0x6D, 0x50, 0x73, 0x75, 0x32, ++ 0x62, 0x6D, 0x38, 0x6D, 0x51, 0x39, 0x51, 0x45, 0x4D, 0x33, 0x78, 0x6B, 0x39, 0x44, 0x7A, 0x34, 0x34, 0x49, 0x38, 0x6B, 0x76, 0x6A, 0x77, 0x7A, 0x52, 0x41, 0x76, 0x34, 0x62, 0x56, 0x64, 0x5A, 0x4F, 0x30, 0x49, 0x30, 0x38, 0x72, 0x30, 0x2B, ++ 0x6B, 0x38, 0x2F, 0x36, 0x76, 0x4B, 0x74, 0x4D, 0x46, 0x6E, 0x58, 0x6B, 0x49, 0x6F, 0x63, 0x74, 0x58, 0x0A, 0x4D, 0x62, 0x53, 0x63, 0x79, 0x4A, 0x43, 0x79, 0x5A, 0x2F, 0x51, 0x59, 0x46, 0x70, 0x4D, 0x36, 0x2F, 0x45, 0x66, 0x59, 0x30, 0x58, ++ 0x69, 0x57, 0x4D, 0x52, 0x2B, 0x36, 0x4B, 0x77, 0x78, 0x66, 0x58, 0x5A, 0x6D, 0x74, 0x59, 0x34, 0x6C, 0x61, 0x4A, 0x43, 0x42, 0x32, 0x32, 0x4E, 0x2F, 0x39, 0x71, 0x30, 0x36, 0x6D, 0x49, 0x71, 0x71, 0x64, 0x58, 0x75, 0x59, 0x6E, 0x69, 0x6E, ++ 0x31, 0x6F, 0x4B, 0x61, 0x50, 0x6E, 0x69, 0x72, 0x6A, 0x61, 0x45, 0x62, 0x73, 0x58, 0x0A, 0x4C, 0x5A, 0x6D, 0x64, 0x45, 0x79, 0x52, 0x47, 0x39, 0x38, 0x58, 0x69, 0x32, 0x4A, 0x2B, 0x4F, 0x66, 0x38, 0x65, 0x50, 0x64, 0x47, 0x31, 0x61, 0x73, ++ 0x75, 0x68, 0x79, 0x39, 0x61, 0x7A, 0x75, 0x4A, 0x42, 0x43, 0x74, 0x4C, 0x78, 0x54, 0x61, 0x2F, 0x79, 0x32, 0x61, 0x52, 0x6E, 0x46, 0x48, 0x76, 0x6B, 0x4C, 0x66, 0x75, 0x77, 0x48, 0x62, 0x39, 0x48, 0x2F, 0x54, 0x4B, 0x49, 0x38, 0x78, 0x57, ++ 0x56, 0x76, 0x54, 0x79, 0x51, 0x4B, 0x6D, 0x74, 0x46, 0x4C, 0x4B, 0x0A, 0x62, 0x70, 0x66, 0x37, 0x51, 0x38, 0x55, 0x49, 0x4A, 0x6D, 0x2B, 0x4B, 0x39, 0x4C, 0x76, 0x39, 0x6E, 0x79, 0x69, 0x71, 0x44, 0x64, 0x56, 0x46, 0x38, 0x78, 0x4D, 0x36, ++ 0x48, 0x64, 0x6A, 0x41, 0x65, 0x49, 0x39, 0x42, 0x5A, 0x7A, 0x77, 0x65, 0x6C, 0x47, 0x53, 0x75, 0x65, 0x77, 0x76, 0x46, 0x36, 0x4E, 0x6B, 0x42, 0x69, 0x44, 0x6B, 0x61, 0x6C, 0x34, 0x5A, 0x6B, 0x51, 0x64, 0x55, 0x37, 0x68, 0x77, 0x78, 0x75, ++ 0x2B, 0x67, 0x2F, 0x47, 0x76, 0x55, 0x67, 0x55, 0x0A, 0x76, 0x7A, 0x6C, 0x4E, 0x31, 0x4A, 0x35, 0x42, 0x74, 0x6F, 0x2B, 0x57, 0x48, 0x57, 0x4F, 0x57, 0x6B, 0x39, 0x6D, 0x56, 0x42, 0x6E, 0x67, 0x78, 0x61, 0x4A, 0x34, 0x33, 0x42, 0x6A, 0x75, ++ 0x41, 0x69, 0x55, 0x56, 0x68, 0x4F, 0x53, 0x50, 0x48, 0x47, 0x30, 0x53, 0x6A, 0x46, 0x65, 0x55, 0x63, 0x2B, 0x4A, 0x49, 0x77, 0x75, 0x77, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x6F, 0x34, 0x48, 0x76, 0x4D, 0x49, 0x48, 0x73, 0x4D, 0x42, 0x30, ++ 0x47, 0x41, 0x31, 0x55, 0x64, 0x0A, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x52, 0x6C, 0x7A, 0x65, 0x75, 0x72, 0x4E, 0x52, 0x34, 0x41, 0x50, 0x6E, 0x37, 0x56, 0x64, 0x4D, 0x41, 0x63, 0x74, 0x48, 0x4E, 0x48, 0x44, 0x68, 0x70, 0x6B, 0x4C, 0x7A, ++ 0x41, 0x53, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x52, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x45, 0x43, 0x44, 0x41, 0x47, 0x41, 0x51, 0x48, 0x2F, 0x41, 0x67, 0x45, 0x42, 0x4D, 0x49, 0x47, 0x6D, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x53, 0x41, 0x45, 0x67, 0x5A, ++ 0x34, 0x77, 0x0A, 0x67, 0x5A, 0x73, 0x77, 0x67, 0x5A, 0x67, 0x47, 0x42, 0x46, 0x55, 0x64, 0x49, 0x41, 0x41, 0x77, 0x67, 0x59, 0x38, 0x77, 0x4C, 0x77, 0x59, 0x49, 0x4B, 0x77, 0x59, 0x42, 0x42, 0x51, 0x55, 0x48, 0x41, 0x67, 0x45, 0x57, 0x49, ++ 0x32, 0x68, 0x30, 0x64, 0x48, 0x41, 0x36, 0x4C, 0x79, 0x39, 0x33, 0x64, 0x33, 0x63, 0x75, 0x5A, 0x6D, 0x6C, 0x79, 0x62, 0x57, 0x46, 0x77, 0x63, 0x6D, 0x39, 0x6D, 0x5A, 0x58, 0x4E, 0x70, 0x62, 0x32, 0x35, 0x68, 0x62, 0x43, 0x35, 0x6A, 0x0A, ++ 0x62, 0x32, 0x30, 0x76, 0x59, 0x33, 0x42, 0x7A, 0x4D, 0x46, 0x77, 0x47, 0x43, 0x43, 0x73, 0x47, 0x41, 0x51, 0x55, 0x46, 0x42, 0x77, 0x49, 0x43, 0x4D, 0x46, 0x41, 0x65, 0x54, 0x67, 0x42, 0x51, 0x41, 0x47, 0x45, 0x41, 0x63, 0x77, 0x42, 0x6C, ++ 0x41, 0x47, 0x38, 0x41, 0x49, 0x41, 0x42, 0x6B, 0x41, 0x47, 0x55, 0x41, 0x49, 0x41, 0x42, 0x73, 0x41, 0x47, 0x45, 0x41, 0x49, 0x41, 0x42, 0x43, 0x41, 0x47, 0x38, 0x41, 0x62, 0x67, 0x42, 0x68, 0x41, 0x47, 0x34, 0x41, 0x0A, 0x62, 0x77, 0x42, ++ 0x32, 0x41, 0x47, 0x45, 0x41, 0x49, 0x41, 0x41, 0x30, 0x41, 0x44, 0x63, 0x41, 0x49, 0x41, 0x42, 0x43, 0x41, 0x47, 0x45, 0x41, 0x63, 0x67, 0x42, 0x6A, 0x41, 0x47, 0x55, 0x41, 0x62, 0x41, 0x42, 0x76, 0x41, 0x47, 0x34, 0x41, 0x59, 0x51, 0x41, ++ 0x67, 0x41, 0x44, 0x41, 0x41, 0x4F, 0x41, 0x41, 0x77, 0x41, 0x44, 0x45, 0x41, 0x4E, 0x7A, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x41, 0x4D, 0x43, 0x0A, 0x41, 0x51, 0x59, 0x77, 0x44, 0x51, ++ 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x42, 0x41, 0x48, 0x53, 0x48, 0x4B, 0x41, 0x49, 0x72, 0x64, 0x78, 0x39, 0x6D, 0x69, 0x57, 0x54, 0x74, 0x6A, 0x33, ++ 0x51, 0x75, 0x52, 0x68, 0x79, 0x37, 0x71, 0x50, 0x6A, 0x34, 0x43, 0x78, 0x32, 0x44, 0x74, 0x6A, 0x71, 0x6E, 0x36, 0x45, 0x57, 0x4B, 0x42, 0x37, 0x66, 0x67, 0x50, 0x69, 0x44, 0x4C, 0x0A, 0x34, 0x51, 0x6A, 0x62, 0x45, 0x77, 0x6A, 0x34, 0x4B, ++ 0x4B, 0x45, 0x31, 0x73, 0x6F, 0x43, 0x7A, 0x43, 0x31, 0x48, 0x41, 0x30, 0x31, 0x61, 0x61, 0x6A, 0x54, 0x4E, 0x46, 0x53, 0x61, 0x39, 0x4A, 0x38, 0x4F, 0x41, 0x39, 0x42, 0x33, 0x70, 0x46, 0x45, 0x31, 0x72, 0x2F, 0x79, 0x4A, 0x66, 0x59, 0x30, ++ 0x78, 0x67, 0x73, 0x66, 0x5A, 0x62, 0x34, 0x33, 0x61, 0x4A, 0x6C, 0x51, 0x33, 0x43, 0x54, 0x6B, 0x42, 0x57, 0x36, 0x6B, 0x4E, 0x2F, 0x6F, 0x47, 0x62, 0x44, 0x62, 0x0A, 0x4C, 0x49, 0x70, 0x67, 0x44, 0x37, 0x64, 0x76, 0x6C, 0x41, 0x63, 0x65, ++ 0x48, 0x61, 0x62, 0x4A, 0x68, 0x66, 0x61, 0x39, 0x4E, 0x50, 0x68, 0x41, 0x65, 0x47, 0x49, 0x51, 0x63, 0x44, 0x71, 0x2B, 0x66, 0x55, 0x73, 0x35, 0x67, 0x61, 0x6B, 0x51, 0x31, 0x4A, 0x5A, 0x42, 0x75, 0x2F, 0x68, 0x66, 0x48, 0x41, 0x73, 0x64, ++ 0x43, 0x50, 0x4B, 0x78, 0x73, 0x49, 0x6C, 0x36, 0x38, 0x76, 0x65, 0x67, 0x34, 0x4D, 0x53, 0x50, 0x69, 0x33, 0x69, 0x31, 0x4F, 0x31, 0x69, 0x6C, 0x0A, 0x49, 0x34, 0x35, 0x50, 0x56, 0x66, 0x34, 0x32, 0x4F, 0x2B, 0x41, 0x4D, 0x74, 0x38, 0x6F, ++ 0x71, 0x4D, 0x45, 0x45, 0x67, 0x74, 0x49, 0x44, 0x4E, 0x72, 0x76, 0x78, 0x32, 0x5A, 0x6E, 0x4F, 0x6F, 0x72, 0x6D, 0x37, 0x68, 0x66, 0x4E, 0x6F, 0x44, 0x36, 0x4A, 0x51, 0x67, 0x35, 0x69, 0x4B, 0x6A, 0x30, 0x42, 0x2B, 0x51, 0x58, 0x53, 0x42, ++ 0x54, 0x46, 0x43, 0x5A, 0x58, 0x32, 0x6C, 0x53, 0x58, 0x33, 0x78, 0x5A, 0x45, 0x45, 0x41, 0x45, 0x65, 0x69, 0x47, 0x61, 0x50, 0x0A, 0x63, 0x6A, 0x69, 0x54, 0x33, 0x53, 0x43, 0x33, 0x4E, 0x4C, 0x37, 0x58, 0x38, 0x65, 0x35, 0x6A, 0x6A, 0x6B, ++ 0x64, 0x35, 0x4B, 0x41, 0x62, 0x38, 0x38, 0x31, 0x6C, 0x46, 0x4A, 0x57, 0x41, 0x69, 0x4D, 0x78, 0x75, 0x6A, 0x58, 0x36, 0x69, 0x36, 0x4B, 0x74, 0x6F, 0x61, 0x50, 0x63, 0x31, 0x41, 0x36, 0x6F, 0x7A, 0x75, 0x42, 0x52, 0x57, 0x56, 0x31, 0x61, ++ 0x55, 0x73, 0x49, 0x43, 0x2B, 0x6E, 0x6D, 0x43, 0x6A, 0x75, 0x52, 0x66, 0x7A, 0x78, 0x75, 0x49, 0x67, 0x41, 0x0A, 0x4C, 0x49, 0x39, 0x43, 0x32, 0x6C, 0x48, 0x56, 0x6E, 0x4F, 0x55, 0x54, 0x61, 0x48, 0x46, 0x46, 0x51, 0x34, 0x75, 0x65, 0x43, ++ 0x79, 0x45, 0x38, 0x53, 0x31, 0x77, 0x46, 0x33, 0x42, 0x71, 0x66, 0x6D, 0x49, 0x37, 0x61, 0x76, 0x53, 0x4B, 0x65, 0x63, 0x73, 0x32, 0x74, 0x43, 0x73, 0x76, 0x4D, 0x6F, 0x32, 0x65, 0x62, 0x4B, 0x48, 0x54, 0x45, 0x6D, 0x39, 0x63, 0x61, 0x50, ++ 0x41, 0x52, 0x59, 0x70, 0x6F, 0x4B, 0x64, 0x72, 0x63, 0x64, 0x37, 0x62, 0x2F, 0x2B, 0x41, 0x0A, 0x6C, 0x75, 0x6E, 0x34, 0x6A, 0x57, 0x71, 0x39, 0x47, 0x4A, 0x41, 0x64, 0x2F, 0x30, 0x6B, 0x61, 0x6B, 0x46, 0x49, 0x33, 0x6B, 0x79, 0x38, 0x38, ++ 0x41, 0x6C, 0x32, 0x43, 0x64, 0x67, 0x74, 0x52, 0x35, 0x78, 0x62, 0x48, 0x56, 0x2F, 0x67, 0x34, 0x2B, 0x61, 0x66, 0x4E, 0x6D, 0x79, 0x4A, 0x55, 0x37, 0x32, 0x4F, 0x77, 0x46, 0x57, 0x31, 0x54, 0x5A, 0x51, 0x4E, 0x4B, 0x58, 0x6B, 0x71, 0x67, ++ 0x73, 0x71, 0x65, 0x4F, 0x53, 0x51, 0x42, 0x5A, 0x4F, 0x4E, 0x58, 0x48, 0x0A, 0x39, 0x49, 0x42, 0x6B, 0x39, 0x57, 0x36, 0x56, 0x55, 0x4C, 0x67, 0x52, 0x66, 0x68, 0x56, 0x77, 0x4F, 0x45, 0x71, 0x77, 0x66, 0x39, 0x44, 0x45, 0x4D, 0x6E, 0x44, ++ 0x41, 0x47, 0x66, 0x2F, 0x4A, 0x4F, 0x43, 0x30, 0x55, 0x4C, 0x47, 0x62, 0x30, 0x51, 0x6B, 0x54, 0x6D, 0x56, 0x58, 0x59, 0x62, 0x67, 0x42, 0x56, 0x58, 0x2F, 0x38, 0x43, 0x6E, 0x70, 0x36, 0x6F, 0x35, 0x71, 0x74, 0x6A, 0x54, 0x63, 0x4E, 0x41, ++ 0x75, 0x75, 0x75, 0x75, 0x55, 0x61, 0x76, 0x70, 0x66, 0x0A, 0x4E, 0x49, 0x62, 0x6E, 0x59, 0x72, 0x58, 0x39, 0x69, 0x76, 0x41, 0x77, 0x68, 0x5A, 0x54, 0x4A, 0x72, 0x79, 0x51, 0x43, 0x4C, 0x32, 0x2F, 0x57, 0x33, 0x57, 0x66, 0x2B, 0x34, 0x37, ++ 0x42, 0x56, 0x54, 0x77, 0x53, 0x59, 0x54, 0x36, 0x52, 0x42, 0x56, 0x75, 0x4B, 0x54, 0x30, 0x47, 0x72, 0x6F, 0x31, 0x76, 0x50, 0x37, 0x5A, 0x65, 0x44, 0x4F, 0x64, 0x63, 0x51, 0x78, 0x57, 0x51, 0x7A, 0x75, 0x67, 0x73, 0x67, 0x4D, 0x59, 0x44, ++ 0x4E, 0x4B, 0x47, 0x62, 0x71, 0x45, 0x0A, 0x5A, 0x79, 0x63, 0x50, 0x76, 0x45, 0x4A, 0x64, 0x76, 0x53, 0x52, 0x55, 0x44, 0x65, 0x77, 0x64, 0x63, 0x41, 0x5A, 0x66, 0x70, 0x4C, 0x7A, 0x36, 0x49, 0x48, 0x78, 0x56, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, ++ 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x76, 0x54, 0x72, 0x75, 0x73, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, ++ 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, ++ 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x43, 0x44, 0x7A, 0x43, 0x43, 0x41, 0x5A, 0x57, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x55, 0x62, 0x6D, 0x71, 0x38, 0x57, 0x61, 0x70, 0x54, 0x76, 0x70, 0x67, 0x35, 0x5A, ++ 0x36, 0x4C, 0x53, 0x61, 0x36, 0x51, 0x37, 0x35, 0x6D, 0x30, 0x63, 0x31, 0x74, 0x6F, 0x77, 0x43, 0x67, 0x59, 0x49, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x45, 0x41, 0x77, 0x4D, 0x77, 0x52, 0x7A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, ++ 0x31, 0x55, 0x45, 0x0A, 0x42, 0x68, 0x4D, 0x43, 0x51, 0x30, 0x34, 0x78, 0x48, 0x44, 0x41, 0x61, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x45, 0x32, 0x6C, 0x55, 0x63, 0x6E, 0x56, 0x7A, 0x51, 0x32, 0x68, 0x70, 0x62, 0x6D, 0x45, 0x67, ++ 0x51, 0x32, 0x38, 0x75, 0x4C, 0x45, 0x78, 0x30, 0x5A, 0x43, 0x34, 0x78, 0x47, 0x6A, 0x41, 0x59, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x45, 0x58, 0x5A, 0x55, 0x63, 0x6E, 0x56, 0x7A, 0x49, 0x45, 0x56, 0x44, 0x51, 0x79, 0x42, 0x53, ++ 0x0A, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x42, 0x4D, 0x42, 0x34, 0x58, 0x44, 0x54, 0x45, 0x34, 0x4D, 0x44, 0x63, 0x7A, 0x4D, 0x54, 0x41, 0x33, 0x4D, 0x6A, 0x59, 0x30, 0x4E, 0x46, 0x6F, 0x58, 0x44, 0x54, 0x51, 0x7A, 0x4D, 0x44, 0x63, ++ 0x7A, 0x4D, 0x54, 0x41, 0x33, 0x4D, 0x6A, 0x59, 0x30, 0x4E, 0x46, 0x6F, 0x77, 0x52, 0x7A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x51, 0x30, 0x34, 0x78, 0x48, 0x44, 0x41, 0x61, 0x0A, 0x42, 0x67, ++ 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x45, 0x32, 0x6C, 0x55, 0x63, 0x6E, 0x56, 0x7A, 0x51, 0x32, 0x68, 0x70, 0x62, 0x6D, 0x45, 0x67, 0x51, 0x32, 0x38, 0x75, 0x4C, 0x45, 0x78, 0x30, 0x5A, 0x43, 0x34, 0x78, 0x47, 0x6A, 0x41, 0x59, 0x42, 0x67, ++ 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x45, 0x58, 0x5A, 0x55, 0x63, 0x6E, 0x56, 0x7A, 0x49, 0x45, 0x56, 0x44, 0x51, 0x79, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x42, 0x4D, 0x48, 0x59, 0x77, 0x0A, 0x45, 0x41, 0x59, 0x48, 0x4B, ++ 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x43, 0x41, 0x51, 0x59, 0x46, 0x4B, 0x34, 0x45, 0x45, 0x41, 0x43, 0x49, 0x44, 0x59, 0x67, 0x41, 0x45, 0x5A, 0x56, 0x42, 0x4B, 0x72, 0x6F, 0x78, 0x35, 0x6C, 0x6B, 0x71, 0x71, 0x48, 0x41, 0x6A, 0x44, 0x6F, ++ 0x36, 0x4C, 0x4E, 0x2F, 0x6C, 0x6C, 0x57, 0x51, 0x58, 0x66, 0x39, 0x4A, 0x70, 0x52, 0x43, 0x75, 0x78, 0x33, 0x4E, 0x43, 0x4E, 0x74, 0x7A, 0x73, 0x6C, 0x74, 0x31, 0x38, 0x38, 0x2B, 0x63, 0x0A, 0x54, 0x6F, 0x4C, 0x30, 0x76, 0x2F, 0x68, 0x68, ++ 0x4A, 0x6F, 0x56, 0x73, 0x31, 0x6F, 0x56, 0x62, 0x63, 0x6E, 0x44, 0x53, 0x2F, 0x64, 0x74, 0x69, 0x74, 0x4E, 0x39, 0x54, 0x69, 0x37, 0x32, 0x78, 0x52, 0x46, 0x68, 0x69, 0x51, 0x67, 0x6E, 0x48, 0x2B, 0x6E, 0x39, 0x62, 0x45, 0x4F, 0x66, 0x2B, ++ 0x51, 0x50, 0x33, 0x41, 0x32, 0x4D, 0x4D, 0x72, 0x4D, 0x75, 0x64, 0x77, 0x70, 0x72, 0x65, 0x6D, 0x49, 0x46, 0x55, 0x64, 0x65, 0x34, 0x42, 0x64, 0x53, 0x34, 0x39, 0x6E, 0x0A, 0x54, 0x50, 0x45, 0x51, 0x6F, 0x30, 0x49, 0x77, 0x51, 0x44, 0x41, ++ 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x6D, 0x44, 0x6E, 0x4E, 0x76, 0x74, 0x69, 0x79, 0x6A, 0x50, 0x65, 0x79, 0x71, 0x2B, 0x47, 0x74, 0x4A, 0x4B, 0x39, 0x37, 0x66, 0x4B, 0x48, 0x62, 0x48, 0x38, 0x38, ++ 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x4F, 0x0A, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x41, ++ 0x4D, 0x43, 0x41, 0x51, 0x59, 0x77, 0x43, 0x67, 0x59, 0x49, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x45, 0x41, 0x77, 0x4D, 0x44, 0x61, 0x41, 0x41, 0x77, 0x5A, 0x51, 0x49, 0x77, 0x56, 0x35, 0x33, 0x64, 0x56, 0x76, 0x48, 0x48, 0x34, 0x2B, ++ 0x6D, 0x34, 0x53, 0x56, 0x42, 0x72, 0x6D, 0x32, 0x6E, 0x44, 0x62, 0x2B, 0x7A, 0x44, 0x66, 0x53, 0x58, 0x6B, 0x56, 0x35, 0x55, 0x54, 0x0A, 0x51, 0x4A, 0x74, 0x53, 0x30, 0x7A, 0x76, 0x7A, 0x51, 0x42, 0x6D, 0x38, 0x4A, 0x73, 0x63, 0x74, 0x42, ++ 0x70, 0x36, 0x31, 0x65, 0x7A, 0x61, 0x66, 0x39, 0x53, 0x58, 0x55, 0x59, 0x32, 0x73, 0x41, 0x41, 0x6A, 0x45, 0x41, 0x36, 0x64, 0x50, 0x47, 0x6E, 0x6C, 0x61, 0x61, 0x4B, 0x73, 0x79, 0x68, 0x32, 0x6A, 0x2F, 0x49, 0x5A, 0x69, 0x76, 0x54, 0x57, ++ 0x4A, 0x77, 0x67, 0x68, 0x66, 0x71, 0x72, 0x6B, 0x59, 0x70, 0x77, 0x63, 0x42, 0x45, 0x34, 0x59, 0x47, 0x51, 0x4C, 0x0A, 0x59, 0x67, 0x6D, 0x52, 0x57, 0x41, 0x44, 0x35, 0x54, 0x66, 0x73, 0x30, 0x61, 0x4E, 0x6F, 0x4A, 0x72, 0x53, 0x45, 0x47, ++ 0x47, 0x4A, 0x54, 0x4F, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x76, 0x54, 0x72, 0x75, 0x73, 0x20, 0x52, 0x6F, ++ 0x6F, 0x74, 0x20, 0x43, 0x41, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, ++ 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x56, 0x6A, 0x43, 0x43, 0x41, 0x7A, 0x36, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x55, 0x51, 0x2B, 0x4E, 0x78, 0x45, 0x39, 0x69, 0x7A, 0x57, 0x52, 0x52, 0x64, ++ 0x74, 0x38, 0x36, 0x4D, 0x2F, 0x54, 0x58, 0x39, 0x62, 0x37, 0x77, 0x46, 0x6A, 0x55, 0x55, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x42, 0x51, 0x41, 0x77, 0x51, 0x7A, 0x45, 0x4C, ++ 0x4D, 0x41, 0x6B, 0x47, 0x0A, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x51, 0x30, 0x34, 0x78, 0x48, 0x44, 0x41, 0x61, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x45, 0x32, 0x6C, 0x55, 0x63, 0x6E, 0x56, 0x7A, 0x51, 0x32, 0x68, ++ 0x70, 0x62, 0x6D, 0x45, 0x67, 0x51, 0x32, 0x38, 0x75, 0x4C, 0x45, 0x78, 0x30, 0x5A, 0x43, 0x34, 0x78, 0x46, 0x6A, 0x41, 0x55, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x44, 0x58, 0x5A, 0x55, 0x63, 0x6E, 0x56, 0x7A, 0x49, 0x46, 0x4A, ++ 0x76, 0x0A, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x54, 0x67, 0x77, 0x4E, 0x7A, 0x4D, 0x78, 0x4D, 0x44, 0x63, 0x79, 0x4E, 0x44, 0x41, 0x31, 0x57, 0x68, 0x63, 0x4E, 0x4E, 0x44, 0x4D, 0x77, 0x4E, 0x7A, ++ 0x4D, 0x78, 0x4D, 0x44, 0x63, 0x79, 0x4E, 0x44, 0x41, 0x31, 0x57, 0x6A, 0x42, 0x44, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x44, 0x54, 0x6A, 0x45, 0x63, 0x4D, 0x42, 0x6F, 0x47, 0x0A, 0x41, ++ 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x54, 0x61, 0x56, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x44, 0x61, 0x47, 0x6C, 0x75, 0x59, 0x53, 0x42, 0x44, 0x62, 0x79, 0x34, 0x73, 0x54, 0x48, 0x52, 0x6B, 0x4C, 0x6A, 0x45, 0x57, 0x4D, 0x42, 0x51, 0x47, 0x41, ++ 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x4E, 0x64, 0x6C, 0x52, 0x79, 0x64, 0x58, 0x4D, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x51, 0x54, 0x43, 0x43, 0x41, 0x69, 0x49, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x0A, 0x4B, 0x6F, 0x5A, 0x49, ++ 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x50, 0x41, 0x44, 0x43, 0x43, 0x41, 0x67, 0x6F, 0x43, 0x67, 0x67, 0x49, 0x42, 0x41, 0x4C, 0x31, 0x56, 0x66, 0x47, 0x48, 0x54, 0x75, 0x42, 0x30, 0x45, ++ 0x59, 0x67, 0x57, 0x67, 0x72, 0x6D, 0x79, 0x33, 0x63, 0x4C, 0x52, 0x42, 0x36, 0x6B, 0x73, 0x44, 0x58, 0x68, 0x41, 0x2F, 0x6B, 0x46, 0x6F, 0x63, 0x69, 0x7A, 0x75, 0x77, 0x5A, 0x6F, 0x74, 0x73, 0x0A, 0x53, 0x4B, 0x59, 0x63, 0x49, 0x72, 0x72, ++ 0x56, 0x51, 0x4A, 0x4C, 0x75, 0x4D, 0x37, 0x49, 0x6A, 0x57, 0x63, 0x6D, 0x4F, 0x76, 0x46, 0x6A, 0x61, 0x69, 0x35, 0x37, 0x51, 0x47, 0x66, 0x49, 0x76, 0x57, 0x63, 0x61, 0x4D, 0x59, 0x31, 0x71, 0x36, 0x6E, 0x36, 0x4D, 0x4C, 0x73, 0x4C, 0x4F, ++ 0x61, 0x58, 0x4C, 0x6F, 0x52, 0x75, 0x42, 0x4C, 0x70, 0x44, 0x4C, 0x76, 0x50, 0x62, 0x6D, 0x79, 0x41, 0x68, 0x79, 0x6B, 0x55, 0x41, 0x79, 0x79, 0x4E, 0x4A, 0x4A, 0x72, 0x49, 0x0A, 0x5A, 0x49, 0x4F, 0x31, 0x61, 0x71, 0x77, 0x54, 0x4C, 0x44, ++ 0x50, 0x78, 0x6E, 0x39, 0x77, 0x73, 0x59, 0x54, 0x77, 0x61, 0x50, 0x33, 0x42, 0x56, 0x6D, 0x36, 0x30, 0x41, 0x55, 0x6E, 0x2F, 0x50, 0x42, 0x4C, 0x6E, 0x2B, 0x4E, 0x76, 0x71, 0x63, 0x77, 0x42, 0x61, 0x75, 0x59, 0x76, 0x36, 0x57, 0x54, 0x45, ++ 0x4E, 0x2B, 0x56, 0x52, 0x53, 0x2B, 0x47, 0x72, 0x50, 0x53, 0x62, 0x63, 0x4B, 0x76, 0x64, 0x6D, 0x61, 0x56, 0x61, 0x79, 0x71, 0x77, 0x6C, 0x48, 0x65, 0x46, 0x0A, 0x58, 0x67, 0x51, 0x50, 0x59, 0x68, 0x31, 0x6A, 0x64, 0x66, 0x64, 0x72, 0x35, ++ 0x38, 0x74, 0x62, 0x6D, 0x6E, 0x44, 0x73, 0x50, 0x6D, 0x63, 0x46, 0x38, 0x50, 0x34, 0x48, 0x43, 0x49, 0x44, 0x50, 0x4B, 0x4E, 0x73, 0x46, 0x78, 0x68, 0x51, 0x6E, 0x4C, 0x34, 0x5A, 0x39, 0x38, 0x43, 0x66, 0x65, 0x2F, 0x2B, 0x5A, 0x2B, 0x4D, ++ 0x30, 0x6A, 0x6E, 0x43, 0x78, 0x35, 0x59, 0x30, 0x53, 0x63, 0x72, 0x55, 0x77, 0x35, 0x58, 0x53, 0x6D, 0x58, 0x58, 0x2B, 0x36, 0x4B, 0x41, 0x0A, 0x59, 0x50, 0x78, 0x4D, 0x76, 0x44, 0x56, 0x54, 0x41, 0x57, 0x71, 0x58, 0x63, 0x6F, 0x4B, 0x76, ++ 0x38, 0x52, 0x31, 0x77, 0x36, 0x4A, 0x7A, 0x31, 0x37, 0x31, 0x37, 0x43, 0x62, 0x4D, 0x64, 0x48, 0x66, 0x6C, 0x71, 0x55, 0x68, 0x53, 0x5A, 0x4E, 0x4F, 0x37, 0x72, 0x72, 0x54, 0x4F, 0x69, 0x77, 0x43, 0x63, 0x4A, 0x6C, 0x77, 0x70, 0x32, 0x64, ++ 0x43, 0x5A, 0x74, 0x4F, 0x74, 0x5A, 0x63, 0x46, 0x72, 0x50, 0x55, 0x47, 0x6F, 0x50, 0x63, 0x32, 0x42, 0x58, 0x37, 0x30, 0x0A, 0x6B, 0x4C, 0x4A, 0x72, 0x78, 0x4C, 0x54, 0x35, 0x5A, 0x4F, 0x72, 0x70, 0x47, 0x67, 0x72, 0x49, 0x44, 0x61, 0x6A, ++ 0x74, 0x4A, 0x38, 0x6E, 0x55, 0x35, 0x37, 0x4F, 0x35, 0x71, 0x34, 0x49, 0x69, 0x6B, 0x43, 0x63, 0x39, 0x4B, 0x75, 0x68, 0x38, 0x6B, 0x4F, 0x2B, 0x38, 0x54, 0x2F, 0x33, 0x69, 0x43, 0x69, 0x53, 0x6E, 0x33, 0x6D, 0x55, 0x6B, 0x70, 0x46, 0x33, ++ 0x71, 0x77, 0x48, 0x59, 0x77, 0x30, 0x33, 0x64, 0x51, 0x2B, 0x41, 0x30, 0x45, 0x6D, 0x35, 0x51, 0x32, 0x0A, 0x41, 0x58, 0x50, 0x4B, 0x42, 0x6C, 0x69, 0x6D, 0x30, 0x7A, 0x76, 0x63, 0x2B, 0x67, 0x52, 0x47, 0x45, 0x31, 0x57, 0x4B, 0x79, 0x55, ++ 0x52, 0x48, 0x75, 0x46, 0x45, 0x35, 0x47, 0x69, 0x37, 0x6F, 0x4E, 0x4F, 0x4A, 0x35, 0x79, 0x31, 0x6C, 0x4B, 0x43, 0x6E, 0x2B, 0x38, 0x70, 0x75, 0x38, 0x66, 0x41, 0x32, 0x64, 0x71, 0x57, 0x53, 0x73, 0x6C, 0x59, 0x70, 0x50, 0x5A, 0x55, 0x78, ++ 0x6C, 0x6D, 0x50, 0x43, 0x64, 0x69, 0x4B, 0x59, 0x5A, 0x4E, 0x70, 0x47, 0x76, 0x75, 0x0A, 0x2F, 0x39, 0x52, 0x4F, 0x75, 0x74, 0x57, 0x30, 0x34, 0x6F, 0x35, 0x49, 0x57, 0x67, 0x41, 0x5A, 0x43, 0x66, 0x45, 0x46, 0x32, 0x63, 0x36, 0x52, 0x73, ++ 0x66, 0x66, 0x72, 0x36, 0x54, 0x6C, 0x50, 0x39, 0x6D, 0x38, 0x45, 0x51, 0x35, 0x70, 0x56, 0x39, 0x54, 0x34, 0x46, 0x46, 0x4C, 0x32, 0x2F, 0x73, 0x31, 0x6D, 0x30, 0x32, 0x49, 0x34, 0x7A, 0x68, 0x4B, 0x4F, 0x51, 0x55, 0x71, 0x71, 0x7A, 0x41, ++ 0x70, 0x56, 0x67, 0x2B, 0x51, 0x78, 0x4D, 0x61, 0x50, 0x6E, 0x75, 0x0A, 0x31, 0x52, 0x63, 0x4E, 0x2B, 0x48, 0x46, 0x58, 0x74, 0x53, 0x58, 0x6B, 0x4B, 0x65, 0x35, 0x6C, 0x58, 0x61, 0x2F, 0x52, 0x37, 0x6A, 0x77, 0x58, 0x43, 0x31, 0x70, 0x44, ++ 0x78, 0x61, 0x57, 0x47, 0x36, 0x69, 0x53, 0x65, 0x34, 0x67, 0x55, 0x48, 0x33, 0x44, 0x52, 0x43, 0x45, 0x70, 0x48, 0x57, 0x4F, 0x58, 0x53, 0x75, 0x54, 0x45, 0x47, 0x43, 0x32, 0x2F, 0x4B, 0x6D, 0x53, 0x4E, 0x47, 0x7A, 0x6D, 0x2F, 0x4D, 0x7A, ++ 0x71, 0x76, 0x4F, 0x6D, 0x77, 0x4D, 0x56, 0x4F, 0x0A, 0x39, 0x66, 0x53, 0x64, 0x64, 0x6D, 0x50, 0x6D, 0x41, 0x73, 0x59, 0x69, 0x53, 0x38, 0x47, 0x56, 0x50, 0x31, 0x42, 0x6B, 0x4C, 0x46, 0x54, 0x6C, 0x74, 0x76, 0x41, 0x38, 0x4B, 0x63, 0x39, ++ 0x58, 0x41, 0x67, 0x4D, 0x42, 0x41, 0x41, 0x47, 0x6A, 0x51, 0x6A, 0x42, 0x41, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x52, 0x55, 0x59, 0x6E, 0x42, 0x6A, 0x38, 0x58, 0x57, 0x45, 0x51, 0x31, 0x69, ++ 0x4F, 0x30, 0x52, 0x59, 0x67, 0x0A, 0x73, 0x63, 0x61, 0x73, 0x47, 0x72, 0x7A, 0x32, 0x69, 0x54, 0x41, 0x50, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x52, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x54, 0x41, 0x44, 0x41, 0x51, 0x48, 0x2F, 0x4D, 0x41, ++ 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x42, 0x42, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x41, ++ 0x4F, 0x43, 0x0A, 0x41, 0x67, 0x45, 0x41, 0x4B, 0x62, 0x71, 0x53, 0x53, 0x61, 0x65, 0x74, 0x38, 0x50, 0x46, 0x77, 0x77, 0x2B, 0x53, 0x58, 0x38, 0x4A, 0x2B, 0x70, 0x4A, 0x64, 0x56, 0x72, 0x6E, 0x6A, 0x54, 0x2B, 0x35, 0x68, 0x70, 0x6B, 0x39, ++ 0x6A, 0x70, 0x72, 0x55, 0x72, 0x49, 0x51, 0x65, 0x42, 0x71, 0x66, 0x54, 0x4E, 0x71, 0x4B, 0x32, 0x75, 0x77, 0x63, 0x4E, 0x31, 0x4C, 0x67, 0x51, 0x6B, 0x76, 0x37, 0x62, 0x48, 0x62, 0x4B, 0x4A, 0x41, 0x73, 0x35, 0x45, 0x68, 0x57, 0x64, 0x0A, ++ 0x6E, 0x78, 0x45, 0x74, 0x2F, 0x48, 0x6C, 0x6B, 0x33, 0x4F, 0x44, 0x67, 0x39, 0x64, 0x33, 0x67, 0x56, 0x38, 0x6D, 0x6C, 0x73, 0x6E, 0x5A, 0x77, 0x55, 0x4B, 0x54, 0x2B, 0x74, 0x77, 0x70, 0x77, 0x31, 0x61, 0x41, 0x30, 0x38, 0x58, 0x58, 0x58, ++ 0x54, 0x55, 0x6D, 0x36, 0x45, 0x64, 0x47, 0x7A, 0x32, 0x4F, 0x79, 0x43, 0x2F, 0x2B, 0x73, 0x4F, 0x78, 0x4C, 0x39, 0x6B, 0x4C, 0x58, 0x31, 0x6A, 0x62, 0x68, 0x64, 0x34, 0x37, 0x46, 0x31, 0x38, 0x69, 0x4D, 0x6A, 0x72, 0x0A, 0x6A, 0x6C, 0x64, ++ 0x32, 0x32, 0x56, 0x6B, 0x45, 0x2B, 0x72, 0x78, 0x53, 0x48, 0x30, 0x57, 0x73, 0x38, 0x48, 0x71, 0x41, 0x37, 0x4F, 0x78, 0x76, 0x64, 0x71, 0x36, 0x52, 0x32, 0x78, 0x43, 0x4F, 0x42, 0x4E, 0x79, 0x53, 0x33, 0x36, 0x44, 0x32, 0x35, 0x71, 0x35, ++ 0x4A, 0x30, 0x38, 0x46, 0x73, 0x45, 0x68, 0x76, 0x4D, 0x4B, 0x61, 0x72, 0x35, 0x43, 0x4B, 0x58, 0x69, 0x4E, 0x78, 0x54, 0x4B, 0x73, 0x62, 0x68, 0x6D, 0x37, 0x78, 0x71, 0x43, 0x35, 0x50, 0x44, 0x34, 0x0A, 0x38, 0x61, 0x63, 0x57, 0x61, 0x62, ++ 0x66, 0x62, 0x71, 0x57, 0x45, 0x38, 0x6E, 0x2F, 0x55, 0x78, 0x79, 0x2B, 0x51, 0x41, 0x52, 0x73, 0x49, 0x76, 0x64, 0x4C, 0x47, 0x78, 0x31, 0x34, 0x48, 0x75, 0x71, 0x43, 0x61, 0x56, 0x76, 0x49, 0x69, 0x76, 0x54, 0x44, 0x55, 0x48, 0x4B, 0x67, ++ 0x4C, 0x4B, 0x65, 0x42, 0x52, 0x74, 0x52, 0x79, 0x74, 0x41, 0x56, 0x75, 0x6E, 0x4C, 0x4B, 0x6D, 0x43, 0x68, 0x5A, 0x77, 0x4F, 0x67, 0x7A, 0x6F, 0x79, 0x38, 0x73, 0x48, 0x4A, 0x6E, 0x0A, 0x78, 0x44, 0x48, 0x4F, 0x32, 0x7A, 0x54, 0x6C, 0x4A, ++ 0x51, 0x4E, 0x67, 0x4A, 0x58, 0x74, 0x78, 0x6D, 0x4F, 0x54, 0x41, 0x47, 0x79, 0x74, 0x66, 0x64, 0x45, 0x4C, 0x53, 0x53, 0x38, 0x56, 0x5A, 0x43, 0x41, 0x65, 0x48, 0x76, 0x73, 0x58, 0x44, 0x66, 0x2B, 0x65, 0x57, 0x32, 0x65, 0x48, 0x63, 0x4B, ++ 0x4A, 0x66, 0x57, 0x6A, 0x77, 0x58, 0x6A, 0x39, 0x5A, 0x74, 0x4F, 0x79, 0x68, 0x31, 0x51, 0x52, 0x77, 0x56, 0x54, 0x73, 0x4D, 0x6F, 0x35, 0x35, 0x34, 0x57, 0x67, 0x0A, 0x69, 0x63, 0x45, 0x46, 0x4F, 0x77, 0x45, 0x33, 0x30, 0x7A, 0x39, 0x4A, ++ 0x34, 0x6E, 0x66, 0x72, 0x49, 0x38, 0x69, 0x49, 0x5A, 0x6A, 0x73, 0x39, 0x4F, 0x58, 0x59, 0x68, 0x52, 0x76, 0x48, 0x73, 0x58, 0x79, 0x4F, 0x34, 0x36, 0x36, 0x4A, 0x6D, 0x64, 0x58, 0x54, 0x42, 0x51, 0x50, 0x66, 0x59, 0x61, 0x4A, 0x71, 0x54, ++ 0x34, 0x69, 0x32, 0x70, 0x4C, 0x72, 0x30, 0x63, 0x6F, 0x78, 0x37, 0x49, 0x64, 0x4D, 0x61, 0x6B, 0x4C, 0x58, 0x6F, 0x67, 0x71, 0x7A, 0x75, 0x34, 0x0A, 0x73, 0x45, 0x62, 0x39, 0x62, 0x39, 0x31, 0x66, 0x55, 0x6C, 0x56, 0x31, 0x59, 0x76, 0x43, ++ 0x58, 0x6F, 0x48, 0x7A, 0x58, 0x4F, 0x50, 0x30, 0x6C, 0x33, 0x38, 0x32, 0x67, 0x6D, 0x78, 0x44, 0x50, 0x69, 0x37, 0x67, 0x34, 0x58, 0x6C, 0x37, 0x46, 0x74, 0x4B, 0x59, 0x43, 0x4E, 0x71, 0x45, 0x65, 0x58, 0x78, 0x7A, 0x50, 0x34, 0x70, 0x61, ++ 0x64, 0x4B, 0x61, 0x72, 0x39, 0x6D, 0x4B, 0x35, 0x53, 0x34, 0x66, 0x4E, 0x42, 0x55, 0x76, 0x75, 0x70, 0x4C, 0x6E, 0x4B, 0x57, 0x0A, 0x6E, 0x79, 0x66, 0x6A, 0x71, 0x6E, 0x4E, 0x39, 0x2B, 0x42, 0x6F, 0x6A, 0x5A, 0x6E, 0x73, 0x37, 0x71, 0x32, ++ 0x57, 0x77, 0x4D, 0x67, 0x46, 0x4C, 0x46, 0x54, 0x34, 0x39, 0x6F, 0x6B, 0x38, 0x4D, 0x4B, 0x7A, 0x57, 0x69, 0x78, 0x74, 0x6C, 0x6E, 0x45, 0x6A, 0x55, 0x77, 0x7A, 0x58, 0x59, 0x75, 0x46, 0x72, 0x4F, 0x5A, 0x6E, 0x6B, 0x31, 0x50, 0x54, 0x69, ++ 0x30, 0x37, 0x4E, 0x45, 0x50, 0x68, 0x6D, 0x67, 0x34, 0x4E, 0x70, 0x47, 0x61, 0x58, 0x75, 0x74, 0x49, 0x63, 0x0A, 0x53, 0x6B, 0x77, 0x73, 0x4B, 0x6F, 0x75, 0x4C, 0x67, 0x55, 0x39, 0x78, 0x47, 0x71, 0x6E, 0x64, 0x58, 0x48, 0x74, 0x37, 0x43, ++ 0x4D, 0x55, 0x41, 0x44, 0x54, 0x64, 0x41, 0x34, 0x33, 0x78, 0x37, 0x56, 0x46, 0x38, 0x76, 0x68, 0x56, 0x39, 0x32, 0x39, 0x76, 0x65, 0x6E, 0x73, 0x42, 0x78, 0x58, 0x56, 0x73, 0x46, 0x79, 0x36, 0x4B, 0x32, 0x69, 0x72, 0x34, 0x30, 0x7A, 0x53, ++ 0x62, 0x6F, 0x66, 0x69, 0x74, 0x7A, 0x6D, 0x64, 0x48, 0x78, 0x67, 0x68, 0x6D, 0x2B, 0x48, 0x0A, 0x6C, 0x33, 0x73, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, ++ 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x49, 0x53, 0x52, 0x47, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x58, 0x32, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, ++ 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x43, 0x47, 0x7A, 0x43, 0x43, 0x41, 0x61, 0x47, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, ++ 0x49, 0x51, 0x51, 0x64, 0x4B, 0x64, 0x30, 0x58, 0x4C, 0x71, 0x37, 0x71, 0x65, 0x41, 0x77, 0x53, 0x78, 0x73, 0x36, 0x53, 0x2B, 0x48, 0x55, 0x6A, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x7A, ++ 0x42, 0x50, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x56, 0x0A, 0x55, 0x7A, 0x45, 0x70, 0x4D, 0x43, 0x63, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x67, 0x53, 0x57, 0x35, 0x30, 0x5A, ++ 0x58, 0x4A, 0x75, 0x5A, 0x58, 0x51, 0x67, 0x55, 0x32, 0x56, 0x6A, 0x64, 0x58, 0x4A, 0x70, 0x64, 0x48, 0x6B, 0x67, 0x55, 0x6D, 0x56, 0x7A, 0x5A, 0x57, 0x46, 0x79, 0x59, 0x32, 0x67, 0x67, 0x52, 0x33, 0x4A, 0x76, 0x64, 0x58, 0x41, 0x78, 0x46, ++ 0x54, 0x41, 0x54, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x44, 0x45, 0x6C, 0x54, 0x0A, 0x55, 0x6B, 0x63, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x59, 0x4D, 0x6A, 0x41, 0x65, 0x46, 0x77, 0x30, 0x79, 0x4D, 0x44, 0x41, 0x35, ++ 0x4D, 0x44, 0x51, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x44, 0x42, 0x61, 0x46, 0x77, 0x30, 0x30, 0x4D, 0x44, 0x41, 0x35, 0x4D, 0x54, 0x63, 0x78, 0x4E, 0x6A, 0x41, 0x77, 0x4D, 0x44, 0x42, 0x61, 0x4D, 0x45, 0x38, 0x78, 0x43, 0x7A, 0x41, 0x4A, ++ 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6C, 0x56, 0x54, 0x0A, 0x4D, 0x53, 0x6B, 0x77, 0x4A, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x45, 0x79, 0x42, 0x4A, 0x62, 0x6E, 0x52, 0x6C, 0x63, 0x6D, 0x35, 0x6C, 0x64, 0x43, 0x42, ++ 0x54, 0x5A, 0x57, 0x4E, 0x31, 0x63, 0x6D, 0x6C, 0x30, 0x65, 0x53, 0x42, 0x53, 0x5A, 0x58, 0x4E, 0x6C, 0x59, 0x58, 0x4A, 0x6A, 0x61, 0x43, 0x42, 0x48, 0x63, 0x6D, 0x39, 0x31, 0x63, 0x44, 0x45, 0x56, 0x4D, 0x42, 0x4D, 0x47, 0x41, 0x31, 0x55, ++ 0x45, 0x41, 0x78, 0x4D, 0x4D, 0x53, 0x56, 0x4E, 0x53, 0x0A, 0x52, 0x79, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x46, 0x67, 0x79, 0x4D, 0x48, 0x59, 0x77, 0x45, 0x41, 0x59, 0x48, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x43, 0x41, 0x51, ++ 0x59, 0x46, 0x4B, 0x34, 0x45, 0x45, 0x41, 0x43, 0x49, 0x44, 0x59, 0x67, 0x41, 0x45, 0x7A, 0x5A, 0x76, 0x56, 0x6E, 0x34, 0x43, 0x44, 0x43, 0x75, 0x77, 0x4A, 0x53, 0x76, 0x4D, 0x57, 0x53, 0x6A, 0x35, 0x63, 0x7A, 0x33, 0x65, 0x73, 0x33, 0x6D, ++ 0x63, 0x46, 0x44, 0x52, 0x30, 0x48, 0x0A, 0x74, 0x74, 0x77, 0x57, 0x2B, 0x31, 0x71, 0x4C, 0x46, 0x4E, 0x76, 0x69, 0x63, 0x57, 0x44, 0x45, 0x75, 0x6B, 0x57, 0x56, 0x45, 0x59, 0x6D, 0x4F, 0x36, 0x67, 0x62, 0x66, 0x39, 0x79, 0x6F, 0x57, 0x48, ++ 0x4B, 0x53, 0x35, 0x78, 0x63, 0x55, 0x79, 0x34, 0x41, 0x50, 0x67, 0x48, 0x6F, 0x49, 0x59, 0x4F, 0x49, 0x76, 0x58, 0x52, 0x64, 0x67, 0x4B, 0x61, 0x6D, 0x37, 0x6D, 0x41, 0x48, 0x66, 0x37, 0x41, 0x6C, 0x46, 0x39, 0x49, 0x74, 0x67, 0x4B, 0x62, ++ 0x70, 0x70, 0x62, 0x0A, 0x64, 0x39, 0x2F, 0x77, 0x2B, 0x6B, 0x48, 0x73, 0x4F, 0x64, 0x78, 0x31, 0x79, 0x6D, 0x67, 0x48, 0x44, 0x42, 0x2F, 0x71, 0x6F, 0x30, 0x49, 0x77, 0x51, 0x44, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x42, ++ 0x41, 0x66, 0x38, 0x45, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x51, 0x59, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, ++ 0x0A, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x66, 0x45, 0x4B, 0x57, 0x72, 0x74, 0x35, 0x4C, 0x53, 0x44, 0x76, 0x36, 0x6B, 0x76, 0x69, 0x65, 0x6A, 0x4D, 0x39, 0x74, 0x69, 0x36, 0x6C, 0x79, 0x4E, 0x35, 0x55, 0x77, 0x43, 0x67, 0x59, ++ 0x49, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x45, 0x41, 0x77, 0x4D, 0x44, 0x61, 0x41, 0x41, 0x77, 0x5A, 0x51, 0x49, 0x77, 0x65, 0x33, 0x6C, 0x4F, 0x52, 0x6C, 0x43, 0x45, 0x77, 0x6B, 0x53, 0x48, 0x52, 0x68, 0x74, 0x46, 0x0A, 0x63, 0x50, ++ 0x39, 0x59, 0x6D, 0x64, 0x37, 0x30, 0x2F, 0x61, 0x54, 0x53, 0x56, 0x61, 0x59, 0x67, 0x4C, 0x58, 0x54, 0x57, 0x4E, 0x4C, 0x78, 0x42, 0x6F, 0x31, 0x42, 0x66, 0x41, 0x53, 0x64, 0x57, 0x74, 0x4C, 0x34, 0x6E, 0x64, 0x51, 0x61, 0x76, 0x45, 0x69, ++ 0x35, 0x31, 0x6D, 0x49, 0x33, 0x38, 0x41, 0x6A, 0x45, 0x41, 0x69, 0x2F, 0x56, 0x33, 0x62, 0x4E, 0x54, 0x49, 0x5A, 0x61, 0x72, 0x67, 0x43, 0x79, 0x7A, 0x75, 0x46, 0x4A, 0x30, 0x6E, 0x4E, 0x36, 0x54, 0x35, 0x0A, 0x55, 0x36, 0x56, 0x52, 0x35, ++ 0x43, 0x6D, 0x44, 0x31, 0x2F, 0x69, 0x51, 0x4D, 0x56, 0x74, 0x43, 0x6E, 0x77, 0x72, 0x31, 0x2F, 0x71, 0x34, 0x41, 0x61, 0x4F, 0x65, 0x4D, 0x53, 0x51, 0x2B, 0x32, 0x62, 0x31, 0x74, 0x62, 0x46, 0x66, 0x4C, 0x6E, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, ++ 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x48, 0x69, 0x50, 0x4B, 0x49, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, ++ 0x31, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, ++ 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x61, 0x6A, 0x43, 0x43, 0x41, 0x31, 0x4B, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x4C, 0x64, 0x32, 0x73, 0x7A, 0x6D, 0x4B, 0x58, 0x6C, 0x4B, 0x46, ++ 0x44, 0x36, 0x4C, 0x44, 0x4E, 0x64, 0x6D, 0x70, 0x65, 0x59, 0x44, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x44, 0x42, 0x50, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, ++ 0x44, 0x56, 0x51, 0x51, 0x47, 0x0A, 0x45, 0x77, 0x4A, 0x55, 0x56, 0x7A, 0x45, 0x6A, 0x4D, 0x43, 0x45, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, 0x61, 0x51, 0x32, 0x68, 0x31, 0x62, 0x6D, 0x64, 0x6F, 0x64, 0x32, 0x45, 0x67, 0x56, 0x47, ++ 0x56, 0x73, 0x5A, 0x57, 0x4E, 0x76, 0x62, 0x53, 0x42, 0x44, 0x62, 0x79, 0x34, 0x73, 0x49, 0x45, 0x78, 0x30, 0x5A, 0x43, 0x34, 0x78, 0x47, 0x7A, 0x41, 0x5A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x4D, 0x45, 0x6B, 0x68, 0x70, 0x55, 0x45, ++ 0x74, 0x4A, 0x0A, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x67, 0x4C, 0x53, 0x42, 0x48, 0x4D, 0x54, 0x41, 0x65, 0x46, 0x77, 0x30, 0x78, 0x4F, 0x54, 0x41, 0x79, 0x4D, 0x6A, 0x49, 0x77, 0x4F, 0x54, 0x51, 0x32, 0x4D, ++ 0x44, 0x52, 0x61, 0x46, 0x77, 0x30, 0x7A, 0x4E, 0x7A, 0x45, 0x79, 0x4D, 0x7A, 0x45, 0x78, 0x4E, 0x54, 0x55, 0x35, 0x4E, 0x54, 0x6C, 0x61, 0x4D, 0x45, 0x38, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x0A, ++ 0x41, 0x6C, 0x52, 0x58, 0x4D, 0x53, 0x4D, 0x77, 0x49, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x44, 0x42, 0x70, 0x44, 0x61, 0x48, 0x56, 0x75, 0x5A, 0x32, 0x68, 0x33, 0x59, 0x53, 0x42, 0x55, 0x5A, 0x57, 0x78, 0x6C, 0x59, 0x32, 0x39, 0x74, ++ 0x49, 0x45, 0x4E, 0x76, 0x4C, 0x69, 0x77, 0x67, 0x54, 0x48, 0x52, 0x6B, 0x4C, 0x6A, 0x45, 0x62, 0x4D, 0x42, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x77, 0x77, 0x53, 0x53, 0x47, 0x6C, 0x51, 0x53, 0x30, 0x6B, 0x67, 0x0A, 0x55, 0x6D, 0x39, ++ 0x76, 0x64, 0x43, 0x42, 0x44, 0x51, 0x53, 0x41, 0x74, 0x49, 0x45, 0x63, 0x78, 0x4D, 0x49, 0x49, 0x43, 0x49, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x45, 0x46, 0x41, 0x41, 0x4F, ++ 0x43, 0x41, 0x67, 0x38, 0x41, 0x4D, 0x49, 0x49, 0x43, 0x43, 0x67, 0x4B, 0x43, 0x41, 0x67, 0x45, 0x41, 0x39, 0x42, 0x35, 0x2F, 0x55, 0x6E, 0x4D, 0x79, 0x44, 0x48, 0x50, 0x6B, 0x76, 0x52, 0x4E, 0x30, 0x0A, 0x6F, 0x39, 0x51, 0x77, 0x71, 0x4E, ++ 0x43, 0x75, 0x53, 0x39, 0x69, 0x32, 0x33, 0x33, 0x56, 0x48, 0x5A, 0x76, 0x52, 0x38, 0x35, 0x7A, 0x6B, 0x45, 0x48, 0x6D, 0x70, 0x77, 0x49, 0x4E, 0x4A, 0x61, 0x52, 0x33, 0x4A, 0x6E, 0x56, 0x66, 0x53, 0x6C, 0x36, 0x4A, 0x33, 0x56, 0x48, 0x69, ++ 0x47, 0x68, 0x38, 0x47, 0x65, 0x36, 0x7A, 0x43, 0x46, 0x6F, 0x76, 0x6B, 0x52, 0x54, 0x76, 0x34, 0x33, 0x35, 0x34, 0x74, 0x77, 0x76, 0x56, 0x63, 0x67, 0x33, 0x50, 0x78, 0x2B, 0x6B, 0x0A, 0x77, 0x4A, 0x79, 0x7A, 0x35, 0x48, 0x64, 0x63, 0x6F, ++ 0x45, 0x62, 0x2B, 0x64, 0x2F, 0x6F, 0x61, 0x6F, 0x44, 0x6A, 0x71, 0x37, 0x5A, 0x70, 0x79, 0x33, 0x69, 0x75, 0x39, 0x6C, 0x46, 0x63, 0x36, 0x75, 0x75, 0x78, 0x35, 0x35, 0x31, 0x39, 0x39, 0x51, 0x6D, 0x51, 0x35, 0x65, 0x69, 0x59, 0x32, 0x39, ++ 0x79, 0x54, 0x77, 0x31, 0x53, 0x2B, 0x36, 0x6C, 0x5A, 0x67, 0x52, 0x5A, 0x71, 0x32, 0x58, 0x4E, 0x64, 0x5A, 0x31, 0x41, 0x59, 0x44, 0x67, 0x72, 0x2F, 0x53, 0x45, 0x0A, 0x59, 0x59, 0x77, 0x4E, 0x48, 0x6C, 0x39, 0x38, 0x68, 0x35, 0x5A, 0x65, ++ 0x51, 0x61, 0x2F, 0x72, 0x68, 0x2B, 0x72, 0x34, 0x58, 0x66, 0x45, 0x75, 0x69, 0x41, 0x55, 0x2B, 0x54, 0x43, 0x4B, 0x37, 0x32, 0x68, 0x38, 0x71, 0x33, 0x56, 0x4A, 0x47, 0x5A, 0x44, 0x6E, 0x7A, 0x51, 0x73, 0x37, 0x5A, 0x6E, 0x67, 0x79, 0x7A, ++ 0x73, 0x48, 0x65, 0x58, 0x5A, 0x4A, 0x7A, 0x41, 0x39, 0x4B, 0x4D, 0x75, 0x48, 0x35, 0x55, 0x48, 0x73, 0x42, 0x66, 0x66, 0x4D, 0x4E, 0x73, 0x41, 0x0A, 0x47, 0x4A, 0x5A, 0x4D, 0x6F, 0x59, 0x46, 0x4C, 0x33, 0x51, 0x52, 0x74, 0x55, 0x36, 0x4D, ++ 0x39, 0x2F, 0x41, 0x65, 0x73, 0x31, 0x4D, 0x55, 0x33, 0x67, 0x75, 0x76, 0x6B, 0x6C, 0x51, 0x67, 0x5A, 0x4B, 0x49, 0x4C, 0x53, 0x51, 0x6A, 0x71, 0x6A, 0x32, 0x46, 0x50, 0x73, 0x65, 0x59, 0x6C, 0x67, 0x53, 0x47, 0x44, 0x49, 0x63, 0x70, 0x4A, ++ 0x51, 0x33, 0x41, 0x4F, 0x50, 0x67, 0x7A, 0x2B, 0x79, 0x51, 0x6C, 0x64, 0x61, 0x32, 0x32, 0x72, 0x70, 0x45, 0x5A, 0x66, 0x64, 0x0A, 0x68, 0x53, 0x69, 0x38, 0x4D, 0x45, 0x79, 0x72, 0x34, 0x38, 0x4B, 0x78, 0x52, 0x55, 0x52, 0x48, 0x48, 0x2B, ++ 0x43, 0x4B, 0x46, 0x67, 0x65, 0x57, 0x30, 0x69, 0x45, 0x50, 0x55, 0x38, 0x44, 0x74, 0x71, 0x58, 0x37, 0x55, 0x54, 0x75, 0x79, 0x62, 0x43, 0x65, 0x79, 0x76, 0x51, 0x71, 0x77, 0x77, 0x31, 0x72, 0x2F, 0x52, 0x45, 0x45, 0x58, 0x67, 0x70, 0x68, ++ 0x61, 0x79, 0x70, 0x63, 0x58, 0x54, 0x54, 0x33, 0x4F, 0x55, 0x4D, 0x33, 0x45, 0x43, 0x6F, 0x57, 0x71, 0x6A, 0x0A, 0x31, 0x6A, 0x4F, 0x58, 0x54, 0x79, 0x46, 0x6A, 0x48, 0x6C, 0x75, 0x50, 0x32, 0x63, 0x46, 0x65, 0x52, 0x58, 0x46, 0x33, 0x44, ++ 0x34, 0x46, 0x64, 0x58, 0x79, 0x47, 0x61, 0x72, 0x59, 0x50, 0x4D, 0x2B, 0x6C, 0x37, 0x57, 0x6A, 0x53, 0x4E, 0x66, 0x47, 0x7A, 0x31, 0x42, 0x72, 0x79, 0x42, 0x31, 0x5A, 0x6C, 0x70, 0x4B, 0x39, 0x70, 0x2F, 0x37, 0x71, 0x78, 0x6A, 0x33, 0x63, ++ 0x63, 0x43, 0x32, 0x48, 0x54, 0x48, 0x73, 0x4F, 0x79, 0x44, 0x72, 0x79, 0x2B, 0x4B, 0x34, 0x0A, 0x39, 0x61, 0x36, 0x53, 0x73, 0x76, 0x66, 0x68, 0x68, 0x45, 0x76, 0x79, 0x6F, 0x76, 0x4B, 0x54, 0x6D, 0x69, 0x4B, 0x65, 0x30, 0x78, 0x52, 0x76, ++ 0x4E, 0x6C, 0x53, 0x39, 0x48, 0x31, 0x35, 0x5A, 0x46, 0x62, 0x6C, 0x7A, 0x71, 0x4D, 0x46, 0x38, 0x62, 0x33, 0x74, 0x69, 0x36, 0x52, 0x5A, 0x73, 0x52, 0x31, 0x70, 0x6C, 0x38, 0x77, 0x34, 0x52, 0x6D, 0x30, 0x62, 0x5A, 0x2F, 0x57, 0x33, 0x63, ++ 0x31, 0x70, 0x7A, 0x41, 0x74, 0x48, 0x32, 0x6C, 0x73, 0x4E, 0x30, 0x2F, 0x0A, 0x56, 0x6D, 0x2B, 0x68, 0x2B, 0x66, 0x62, 0x6B, 0x45, 0x6B, 0x6A, 0x39, 0x42, 0x6E, 0x38, 0x53, 0x56, 0x37, 0x61, 0x70, 0x49, 0x30, 0x39, 0x62, 0x41, 0x38, 0x50, ++ 0x67, 0x63, 0x53, 0x6F, 0x6A, 0x74, 0x2F, 0x65, 0x77, 0x73, 0x54, 0x75, 0x38, 0x6D, 0x4C, 0x33, 0x57, 0x6D, 0x4B, 0x67, 0x4D, 0x61, 0x2F, 0x61, 0x4F, 0x45, 0x6D, 0x65, 0x6D, 0x38, 0x72, 0x4A, 0x59, 0x35, 0x41, 0x49, 0x4A, 0x45, 0x7A, 0x79, ++ 0x70, 0x75, 0x78, 0x43, 0x30, 0x30, 0x6A, 0x42, 0x46, 0x0A, 0x38, 0x65, 0x7A, 0x33, 0x41, 0x42, 0x48, 0x66, 0x5A, 0x66, 0x6A, 0x63, 0x4B, 0x30, 0x4E, 0x56, 0x76, 0x78, 0x61, 0x58, 0x78, 0x41, 0x2F, 0x56, 0x4C, 0x47, 0x47, 0x45, 0x71, 0x6E, ++ 0x4B, 0x47, 0x2F, 0x75, 0x59, 0x36, 0x66, 0x73, 0x49, 0x2F, 0x66, 0x65, 0x37, 0x38, 0x4C, 0x78, 0x51, 0x2B, 0x35, 0x6F, 0x58, 0x64, 0x55, 0x47, 0x2B, 0x33, 0x53, 0x65, 0x30, 0x43, 0x41, 0x77, 0x45, 0x41, 0x41, 0x61, 0x4E, 0x43, 0x4D, 0x45, ++ 0x41, 0x77, 0x44, 0x77, 0x59, 0x44, 0x0A, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x38, ++ 0x6E, 0x63, 0x58, 0x2B, 0x6C, 0x36, 0x6F, 0x2F, 0x76, 0x59, 0x39, 0x63, 0x64, 0x56, 0x6F, 0x75, 0x73, 0x6C, 0x47, 0x44, 0x44, 0x6A, 0x59, 0x72, 0x37, 0x41, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x41, 0x51, 0x48, 0x2F, 0x42, ++ 0x41, 0x51, 0x44, 0x0A, 0x41, 0x67, 0x47, 0x47, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x43, 0x77, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x41, 0x51, 0x42, 0x51, 0x55, 0x66, 0x42, 0x31, ++ 0x33, 0x48, 0x41, 0x45, 0x34, 0x2F, 0x2B, 0x71, 0x64, 0x64, 0x52, 0x78, 0x6F, 0x73, 0x75, 0x65, 0x6A, 0x36, 0x69, 0x70, 0x30, 0x36, 0x39, 0x31, 0x78, 0x31, 0x54, 0x50, 0x4F, 0x68, 0x77, 0x45, 0x6D, 0x53, 0x4B, 0x73, 0x78, 0x42, 0x48, 0x69, ++ 0x0A, 0x37, 0x7A, 0x4E, 0x4B, 0x70, 0x69, 0x4D, 0x64, 0x44, 0x67, 0x31, 0x48, 0x32, 0x44, 0x66, 0x48, 0x62, 0x36, 0x38, 0x30, 0x66, 0x30, 0x2B, 0x42, 0x61, 0x7A, 0x56, 0x50, 0x36, 0x58, 0x4B, 0x6C, 0x4D, 0x65, 0x4A, 0x34, 0x35, 0x2F, 0x64, ++ 0x4F, 0x6C, 0x42, 0x68, 0x62, 0x51, 0x48, 0x33, 0x50, 0x61, 0x79, 0x46, 0x55, 0x68, 0x75, 0x61, 0x56, 0x65, 0x76, 0x76, 0x47, 0x79, 0x75, 0x71, 0x63, 0x53, 0x45, 0x35, 0x58, 0x43, 0x56, 0x30, 0x76, 0x72, 0x50, 0x53, 0x6C, 0x0A, 0x74, 0x4A, ++ 0x63, 0x7A, 0x57, 0x4E, 0x57, 0x73, 0x65, 0x61, 0x6E, 0x4D, 0x58, 0x2F, 0x6D, 0x46, 0x2B, 0x6C, 0x4C, 0x46, 0x6A, 0x66, 0x69, 0x52, 0x46, 0x4F, 0x73, 0x36, 0x44, 0x52, 0x66, 0x51, 0x55, 0x73, 0x4A, 0x37, 0x34, 0x38, 0x4A, 0x7A, 0x6A, 0x6B, ++ 0x5A, 0x34, 0x42, 0x6A, 0x67, 0x73, 0x36, 0x46, 0x7A, 0x61, 0x5A, 0x73, 0x54, 0x30, 0x70, 0x50, 0x42, 0x57, 0x47, 0x54, 0x4D, 0x70, 0x57, 0x6D, 0x57, 0x53, 0x42, 0x55, 0x64, 0x47, 0x53, 0x71, 0x75, 0x45, 0x0A, 0x77, 0x78, 0x34, 0x6E, 0x6F, ++ 0x52, 0x38, 0x52, 0x6B, 0x70, 0x6B, 0x6E, 0x64, 0x5A, 0x4D, 0x50, 0x76, 0x44, 0x59, 0x37, 0x6C, 0x31, 0x65, 0x50, 0x4A, 0x6C, 0x73, 0x4D, 0x75, 0x35, 0x77, 0x50, 0x31, 0x47, 0x34, 0x77, 0x42, 0x39, 0x54, 0x63, 0x58, 0x7A, 0x5A, 0x6F, 0x5A, ++ 0x6A, 0x6D, 0x44, 0x6C, 0x69, 0x63, 0x6D, 0x69, 0x73, 0x6A, 0x45, 0x4F, 0x66, 0x36, 0x61, 0x49, 0x57, 0x2F, 0x56, 0x63, 0x6F, 0x62, 0x70, 0x66, 0x32, 0x4C, 0x6C, 0x6C, 0x30, 0x37, 0x51, 0x0A, 0x4A, 0x4E, 0x42, 0x41, 0x73, 0x4E, 0x42, 0x31, ++ 0x43, 0x49, 0x36, 0x39, 0x61, 0x4F, 0x34, 0x49, 0x31, 0x32, 0x35, 0x38, 0x45, 0x48, 0x42, 0x47, 0x47, 0x33, 0x7A, 0x67, 0x69, 0x4C, 0x4B, 0x65, 0x63, 0x6F, 0x61, 0x5A, 0x41, 0x65, 0x4F, 0x2F, 0x6E, 0x30, 0x6B, 0x5A, 0x74, 0x43, 0x57, 0x2B, ++ 0x56, 0x6D, 0x57, 0x75, 0x46, 0x32, 0x50, 0x6C, 0x48, 0x74, 0x2F, 0x6F, 0x2F, 0x30, 0x65, 0x6C, 0x76, 0x2B, 0x45, 0x6D, 0x42, 0x59, 0x54, 0x6B, 0x73, 0x4D, 0x43, 0x76, 0x0A, 0x35, 0x77, 0x69, 0x5A, 0x71, 0x41, 0x78, 0x65, 0x4A, 0x6F, 0x42, ++ 0x46, 0x31, 0x50, 0x68, 0x6F, 0x4C, 0x35, 0x61, 0x50, 0x72, 0x75, 0x4A, 0x4B, 0x48, 0x4A, 0x77, 0x57, 0x44, 0x42, 0x4E, 0x76, 0x4F, 0x49, 0x66, 0x32, 0x75, 0x38, 0x67, 0x30, 0x58, 0x35, 0x49, 0x44, 0x55, 0x58, 0x6C, 0x77, 0x70, 0x74, 0x2F, ++ 0x4C, 0x39, 0x5A, 0x6C, 0x4E, 0x65, 0x63, 0x31, 0x4F, 0x76, 0x46, 0x65, 0x66, 0x51, 0x30, 0x35, 0x72, 0x4C, 0x69, 0x73, 0x59, 0x2B, 0x47, 0x70, 0x7A, 0x0A, 0x6A, 0x4C, 0x72, 0x46, 0x4E, 0x65, 0x38, 0x35, 0x61, 0x6B, 0x45, 0x65, 0x7A, 0x33, ++ 0x47, 0x6F, 0x6F, 0x72, 0x4B, 0x47, 0x42, 0x31, 0x73, 0x36, 0x79, 0x65, 0x48, 0x76, 0x50, 0x32, 0x55, 0x45, 0x67, 0x45, 0x63, 0x79, 0x52, 0x48, 0x43, 0x56, 0x54, 0x6A, 0x46, 0x6E, 0x61, 0x6E, 0x52, 0x62, 0x45, 0x45, 0x56, 0x31, 0x36, 0x72, ++ 0x43, 0x66, 0x30, 0x4F, 0x59, 0x31, 0x2F, 0x6B, 0x36, 0x66, 0x69, 0x38, 0x77, 0x72, 0x6B, 0x6B, 0x56, 0x62, 0x62, 0x69, 0x56, 0x67, 0x0A, 0x68, 0x55, 0x62, 0x4E, 0x30, 0x61, 0x71, 0x77, 0x64, 0x6D, 0x61, 0x54, 0x64, 0x35, 0x61, 0x2B, 0x67, ++ 0x37, 0x34, 0x34, 0x74, 0x69, 0x52, 0x4F, 0x4A, 0x67, 0x76, 0x4D, 0x37, 0x58, 0x70, 0x57, 0x47, 0x75, 0x44, 0x70, 0x57, 0x73, 0x5A, 0x6B, 0x72, 0x55, 0x78, 0x36, 0x41, 0x45, 0x68, 0x45, 0x4C, 0x37, 0x6C, 0x41, 0x75, 0x78, 0x4D, 0x2B, 0x76, ++ 0x68, 0x56, 0x34, 0x6E, 0x59, 0x57, 0x42, 0x53, 0x69, 0x70, 0x58, 0x33, 0x74, 0x55, 0x5A, 0x51, 0x39, 0x72, 0x62, 0x0A, 0x79, 0x6C, 0x74, 0x48, 0x68, 0x6F, 0x4D, 0x4C, 0x50, 0x37, 0x59, 0x4E, 0x64, 0x6E, 0x68, 0x7A, 0x65, 0x53, 0x4A, 0x65, ++ 0x73, 0x59, 0x41, 0x66, 0x7A, 0x37, 0x37, 0x52, 0x50, 0x31, 0x59, 0x51, 0x6D, 0x43, 0x75, 0x56, 0x68, 0x36, 0x45, 0x66, 0x6E, 0x57, 0x51, 0x55, 0x59, 0x44, 0x6B, 0x73, 0x73, 0x77, 0x42, 0x56, 0x4C, 0x75, 0x54, 0x31, 0x73, 0x77, 0x35, 0x58, ++ 0x78, 0x4A, 0x46, 0x42, 0x41, 0x4A, 0x77, 0x2F, 0x36, 0x4B, 0x58, 0x66, 0x36, 0x76, 0x62, 0x2F, 0x0A, 0x79, 0x50, 0x43, 0x74, 0x62, 0x56, 0x4B, 0x6F, 0x46, 0x36, 0x75, 0x62, 0x59, 0x66, 0x77, 0x53, 0x55, 0x54, 0x58, 0x6B, 0x4A, 0x66, 0x32, ++ 0x76, 0x71, 0x6D, 0x71, 0x47, 0x4F, 0x51, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x47, 0x6C, 0x6F, ++ 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x52, 0x34, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, ++ 0x0A, 0x4D, 0x49, 0x49, 0x42, 0x33, 0x44, 0x43, 0x43, 0x41, 0x59, 0x4F, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x4E, 0x41, 0x67, 0x50, 0x6C, 0x66, 0x76, 0x55, 0x2F, 0x6B, 0x2F, 0x32, 0x6C, 0x43, 0x53, 0x47, 0x79, 0x70, 0x6A, 0x41, ++ 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x6A, 0x42, 0x51, 0x4D, 0x53, 0x51, 0x77, 0x49, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4C, 0x45, 0x78, 0x74, 0x48, 0x62, 0x47, 0x39, 0x69, 0x0A, 0x59, 0x57, ++ 0x78, 0x54, 0x61, 0x57, 0x64, 0x75, 0x49, 0x45, 0x56, 0x44, 0x51, 0x79, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x42, 0x49, 0x43, 0x30, 0x67, 0x55, 0x6A, 0x51, 0x78, 0x45, 0x7A, 0x41, 0x52, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, ++ 0x6F, 0x54, 0x43, 0x6B, 0x64, 0x73, 0x62, 0x32, 0x4A, 0x68, 0x62, 0x46, 0x4E, 0x70, 0x5A, 0x32, 0x34, 0x78, 0x45, 0x7A, 0x41, 0x52, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x43, 0x6B, 0x64, 0x73, 0x0A, 0x62, 0x32, 0x4A, 0x68, 0x62, ++ 0x46, 0x4E, 0x70, 0x5A, 0x32, 0x34, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x54, 0x49, 0x78, 0x4D, 0x54, 0x45, 0x7A, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x57, 0x68, 0x63, 0x4E, 0x4D, 0x7A, 0x67, 0x77, 0x4D, 0x54, 0x45, 0x35, 0x4D, ++ 0x44, 0x4D, 0x78, 0x4E, 0x44, 0x41, 0x33, 0x57, 0x6A, 0x42, 0x51, 0x4D, 0x53, 0x51, 0x77, 0x49, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4C, 0x45, 0x78, 0x74, 0x48, 0x62, 0x47, 0x39, 0x69, 0x0A, 0x59, 0x57, 0x78, 0x54, 0x61, 0x57, 0x64, 0x75, ++ 0x49, 0x45, 0x56, 0x44, 0x51, 0x79, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x42, 0x49, 0x43, 0x30, 0x67, 0x55, 0x6A, 0x51, 0x78, 0x45, 0x7A, 0x41, 0x52, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x43, 0x6B, 0x64, 0x73, ++ 0x62, 0x32, 0x4A, 0x68, 0x62, 0x46, 0x4E, 0x70, 0x5A, 0x32, 0x34, 0x78, 0x45, 0x7A, 0x41, 0x52, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x43, 0x6B, 0x64, 0x73, 0x0A, 0x62, 0x32, 0x4A, 0x68, 0x62, 0x46, 0x4E, 0x70, 0x5A, 0x32, 0x34, ++ 0x77, 0x57, 0x54, 0x41, 0x54, 0x42, 0x67, 0x63, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x49, 0x42, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x4D, 0x42, 0x42, 0x77, 0x4E, 0x43, 0x41, 0x41, 0x53, 0x34, 0x78, 0x6E, 0x6E, ++ 0x54, 0x6A, 0x32, 0x77, 0x6C, 0x44, 0x70, 0x38, 0x75, 0x4F, 0x52, 0x6B, 0x63, 0x41, 0x36, 0x53, 0x75, 0x6D, 0x75, 0x55, 0x35, 0x42, 0x77, 0x6B, 0x57, 0x0A, 0x79, 0x6D, 0x4F, 0x78, 0x75, 0x59, 0x62, 0x34, 0x69, 0x6C, 0x66, 0x42, 0x56, 0x38, ++ 0x35, 0x43, 0x2B, 0x6E, 0x4F, 0x68, 0x39, 0x32, 0x56, 0x43, 0x2F, 0x78, 0x37, 0x42, 0x41, 0x4C, 0x4A, 0x75, 0x63, 0x77, 0x37, 0x2F, 0x78, 0x79, 0x48, 0x6C, 0x47, 0x4B, 0x53, 0x71, 0x32, 0x58, 0x45, 0x2F, 0x71, 0x4E, 0x53, 0x35, 0x7A, 0x6F, ++ 0x77, 0x64, 0x6F, 0x30, 0x49, 0x77, 0x51, 0x44, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x42, 0x41, 0x66, 0x38, 0x45, 0x0A, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x59, 0x59, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, ++ 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x56, 0x4C, 0x42, 0x37, 0x72, 0x55, 0x57, 0x34, 0x34, 0x6B, 0x42, 0x2F, 0x2B, ++ 0x77, 0x70, 0x75, 0x2B, 0x37, 0x34, 0x7A, 0x79, 0x54, 0x79, 0x6A, 0x68, 0x4E, 0x55, 0x77, 0x43, 0x67, 0x59, 0x49, 0x0A, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x45, 0x41, 0x77, 0x49, 0x44, 0x52, 0x77, 0x41, 0x77, 0x52, 0x41, 0x49, 0x67, ++ 0x49, 0x6B, 0x39, 0x30, 0x63, 0x72, 0x6C, 0x67, 0x72, 0x2F, 0x48, 0x6D, 0x6E, 0x4B, 0x41, 0x57, 0x42, 0x56, 0x42, 0x66, 0x77, 0x31, 0x34, 0x37, 0x62, 0x6D, 0x46, 0x30, 0x37, 0x37, 0x34, 0x42, 0x78, 0x4C, 0x34, 0x59, 0x53, 0x46, 0x6C, 0x68, ++ 0x67, 0x6A, 0x49, 0x43, 0x49, 0x43, 0x61, 0x64, 0x56, 0x47, 0x4E, 0x41, 0x33, 0x6A, 0x64, 0x67, 0x0A, 0x55, 0x4D, 0x2F, 0x49, 0x32, 0x4F, 0x32, 0x64, 0x67, 0x71, 0x34, 0x33, 0x6D, 0x4C, 0x79, 0x6A, 0x6A, 0x30, 0x78, 0x4D, 0x71, 0x54, 0x51, ++ 0x72, 0x62, 0x4F, 0x2F, 0x37, 0x6C, 0x5A, 0x73, 0x6D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x47, 0x54, 0x53, ++ 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x31, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, ++ 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x56, 0x7A, 0x43, 0x43, 0x41, 0x7A, 0x2B, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x4E, 0x41, 0x67, 0x50, 0x6C, 0x6B, 0x32, 0x38, 0x78, 0x73, 0x42, 0x4E, ++ 0x4A, 0x69, 0x47, 0x75, 0x69, 0x46, 0x7A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x77, 0x46, 0x41, 0x44, 0x42, 0x48, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, ++ 0x47, 0x45, 0x77, 0x4A, 0x56, 0x0A, 0x55, 0x7A, 0x45, 0x69, 0x4D, 0x43, 0x41, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x5A, 0x52, 0x32, 0x39, 0x76, 0x5A, 0x32, 0x78, 0x6C, 0x49, 0x46, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x49, 0x46, ++ 0x4E, 0x6C, 0x63, 0x6E, 0x5A, 0x70, 0x59, 0x32, 0x56, 0x7A, 0x49, 0x45, 0x78, 0x4D, 0x51, 0x7A, 0x45, 0x55, 0x4D, 0x42, 0x49, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x4C, 0x52, 0x31, 0x52, 0x54, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, ++ 0x51, 0x67, 0x0A, 0x55, 0x6A, 0x45, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x54, 0x59, 0x77, 0x4E, 0x6A, 0x49, 0x79, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x57, 0x68, 0x63, 0x4E, 0x4D, 0x7A, 0x59, 0x77, 0x4E, 0x6A, 0x49, 0x79, 0x4D, ++ 0x44, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x57, 0x6A, 0x42, 0x48, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x56, 0x55, 0x7A, 0x45, 0x69, 0x4D, 0x43, 0x41, 0x47, 0x41, 0x31, 0x55, 0x45, 0x0A, ++ 0x43, 0x68, 0x4D, 0x5A, 0x52, 0x32, 0x39, 0x76, 0x5A, 0x32, 0x78, 0x6C, 0x49, 0x46, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x49, 0x46, 0x4E, 0x6C, 0x63, 0x6E, 0x5A, 0x70, 0x59, 0x32, 0x56, 0x7A, 0x49, 0x45, 0x78, 0x4D, 0x51, 0x7A, 0x45, 0x55, ++ 0x4D, 0x42, 0x49, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x4C, 0x52, 0x31, 0x52, 0x54, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x55, 0x6A, 0x45, 0x77, 0x67, 0x67, 0x49, 0x69, 0x4D, 0x41, 0x30, 0x47, 0x0A, 0x43, 0x53, 0x71, ++ 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x49, 0x4B, 0x41, 0x6F, 0x49, 0x43, 0x41, 0x51, 0x43, 0x32, 0x45, 0x51, 0x4B, 0x4C, 0x48, 0x75, 0x4F, ++ 0x68, 0x64, 0x35, 0x73, 0x37, 0x33, 0x4C, 0x2B, 0x55, 0x50, 0x72, 0x65, 0x56, 0x70, 0x30, 0x41, 0x38, 0x6F, 0x66, 0x32, 0x43, 0x2B, 0x58, 0x30, 0x79, 0x42, 0x6F, 0x4A, 0x78, 0x39, 0x76, 0x61, 0x4D, 0x0A, 0x66, 0x2F, 0x76, 0x6F, 0x32, 0x37, ++ 0x78, 0x71, 0x4C, 0x70, 0x65, 0x58, 0x6F, 0x34, 0x78, 0x4C, 0x2B, 0x53, 0x76, 0x32, 0x73, 0x66, 0x6E, 0x4F, 0x68, 0x42, 0x32, 0x78, 0x2B, 0x63, 0x57, 0x58, 0x33, 0x75, 0x2B, 0x35, 0x38, 0x71, 0x50, 0x70, 0x76, 0x42, 0x4B, 0x4A, 0x58, 0x71, ++ 0x65, 0x71, 0x55, 0x71, 0x76, 0x34, 0x49, 0x79, 0x66, 0x4C, 0x70, 0x4C, 0x47, 0x63, 0x59, 0x39, 0x76, 0x58, 0x6D, 0x58, 0x37, 0x77, 0x43, 0x6C, 0x37, 0x72, 0x61, 0x4B, 0x62, 0x30, 0x0A, 0x78, 0x6C, 0x70, 0x48, 0x44, 0x55, 0x30, 0x51, 0x4D, ++ 0x2B, 0x4E, 0x4F, 0x73, 0x52, 0x4F, 0x6A, 0x79, 0x42, 0x68, 0x73, 0x53, 0x2B, 0x7A, 0x38, 0x43, 0x5A, 0x44, 0x66, 0x6E, 0x57, 0x51, 0x70, 0x4A, 0x53, 0x4D, 0x48, 0x6F, 0x62, 0x54, 0x53, 0x50, 0x53, 0x35, 0x67, 0x34, 0x4D, 0x2F, 0x53, 0x43, ++ 0x59, 0x65, 0x37, 0x7A, 0x55, 0x6A, 0x77, 0x54, 0x63, 0x4C, 0x43, 0x65, 0x6F, 0x69, 0x4B, 0x75, 0x37, 0x72, 0x50, 0x57, 0x52, 0x6E, 0x57, 0x72, 0x34, 0x2B, 0x77, 0x0A, 0x42, 0x37, 0x43, 0x65, 0x4D, 0x66, 0x47, 0x43, 0x77, 0x63, 0x44, 0x66, ++ 0x4C, 0x71, 0x5A, 0x74, 0x62, 0x42, 0x6B, 0x4F, 0x74, 0x64, 0x68, 0x2B, 0x4A, 0x68, 0x70, 0x46, 0x41, 0x7A, 0x32, 0x77, 0x65, 0x61, 0x53, 0x55, 0x4B, 0x4B, 0x30, 0x50, 0x66, 0x79, 0x62, 0x6C, 0x71, 0x41, 0x6A, 0x2B, 0x6C, 0x75, 0x67, 0x38, ++ 0x61, 0x4A, 0x52, 0x54, 0x37, 0x6F, 0x4D, 0x36, 0x69, 0x43, 0x73, 0x56, 0x6C, 0x67, 0x6D, 0x79, 0x34, 0x48, 0x71, 0x4D, 0x4C, 0x6E, 0x58, 0x57, 0x0A, 0x6E, 0x4F, 0x75, 0x6E, 0x56, 0x6D, 0x53, 0x50, 0x6C, 0x6B, 0x39, 0x6F, 0x72, 0x6A, 0x32, ++ 0x58, 0x77, 0x6F, 0x53, 0x50, 0x77, 0x4C, 0x78, 0x41, 0x77, 0x41, 0x74, 0x63, 0x76, 0x66, 0x61, 0x48, 0x73, 0x7A, 0x56, 0x73, 0x72, 0x42, 0x68, 0x51, 0x66, 0x34, 0x54, 0x67, 0x54, 0x4D, 0x32, 0x53, 0x30, 0x79, 0x44, 0x70, 0x4D, 0x37, 0x78, ++ 0x53, 0x6D, 0x61, 0x38, 0x79, 0x74, 0x53, 0x6D, 0x7A, 0x4A, 0x53, 0x71, 0x30, 0x53, 0x50, 0x6C, 0x79, 0x34, 0x63, 0x70, 0x6B, 0x0A, 0x39, 0x2B, 0x61, 0x43, 0x45, 0x49, 0x33, 0x6F, 0x6E, 0x63, 0x4B, 0x4B, 0x69, 0x50, 0x6F, 0x34, 0x5A, 0x6F, ++ 0x72, 0x38, 0x59, 0x2F, 0x6B, 0x42, 0x2B, 0x58, 0x6A, 0x39, 0x65, 0x31, 0x78, 0x33, 0x2B, 0x6E, 0x61, 0x48, 0x2B, 0x75, 0x7A, 0x66, 0x73, 0x51, 0x35, 0x35, 0x6C, 0x56, 0x65, 0x30, 0x76, 0x53, 0x62, 0x76, 0x31, 0x67, 0x48, 0x52, 0x36, 0x78, ++ 0x59, 0x4B, 0x75, 0x34, 0x34, 0x4C, 0x74, 0x63, 0x58, 0x46, 0x69, 0x6C, 0x57, 0x72, 0x30, 0x36, 0x7A, 0x71, 0x0A, 0x6B, 0x55, 0x73, 0x70, 0x7A, 0x42, 0x6D, 0x6B, 0x4D, 0x69, 0x56, 0x4F, 0x4B, 0x76, 0x46, 0x6C, 0x52, 0x4E, 0x41, 0x43, 0x7A, ++ 0x71, 0x72, 0x4F, 0x53, 0x62, 0x54, 0x71, 0x6E, 0x33, 0x79, 0x44, 0x73, 0x45, 0x42, 0x37, 0x35, 0x30, 0x4F, 0x72, 0x70, 0x32, 0x79, 0x6A, 0x6A, 0x33, 0x32, 0x4A, 0x67, 0x66, 0x70, 0x4D, 0x70, 0x66, 0x2F, 0x56, 0x6A, 0x73, 0x50, 0x4F, 0x53, ++ 0x2B, 0x43, 0x31, 0x32, 0x4C, 0x4F, 0x4F, 0x52, 0x63, 0x39, 0x32, 0x77, 0x4F, 0x31, 0x41, 0x0A, 0x4B, 0x2F, 0x31, 0x54, 0x44, 0x37, 0x43, 0x6E, 0x31, 0x54, 0x73, 0x4E, 0x73, 0x59, 0x71, 0x69, 0x41, 0x39, 0x34, 0x78, 0x72, 0x63, 0x78, 0x33, ++ 0x36, 0x6D, 0x39, 0x37, 0x50, 0x74, 0x62, 0x66, 0x6B, 0x53, 0x49, 0x53, 0x35, 0x72, 0x37, 0x36, 0x32, 0x44, 0x4C, 0x38, 0x45, 0x47, 0x4D, 0x55, 0x55, 0x58, 0x4C, 0x65, 0x58, 0x64, 0x59, 0x57, 0x6B, 0x37, 0x30, 0x70, 0x61, 0x44, 0x50, 0x76, ++ 0x4F, 0x6D, 0x62, 0x73, 0x42, 0x34, 0x6F, 0x6D, 0x33, 0x78, 0x50, 0x58, 0x0A, 0x56, 0x32, 0x56, 0x34, 0x4A, 0x39, 0x35, 0x65, 0x53, 0x52, 0x51, 0x41, 0x6F, 0x67, 0x42, 0x2F, 0x6D, 0x71, 0x67, 0x68, 0x74, 0x71, 0x6D, 0x78, 0x6C, 0x62, 0x43, ++ 0x6C, 0x75, 0x51, 0x30, 0x57, 0x45, 0x64, 0x72, 0x48, 0x62, 0x45, 0x67, 0x38, 0x51, 0x4F, 0x42, 0x2B, 0x44, 0x56, 0x72, 0x4E, 0x56, 0x6A, 0x7A, 0x52, 0x6C, 0x77, 0x57, 0x35, 0x79, 0x30, 0x76, 0x74, 0x4F, 0x55, 0x75, 0x63, 0x78, 0x44, 0x2F, ++ 0x53, 0x56, 0x52, 0x4E, 0x75, 0x4A, 0x4C, 0x44, 0x57, 0x0A, 0x63, 0x66, 0x72, 0x30, 0x77, 0x62, 0x72, 0x4D, 0x37, 0x52, 0x76, 0x31, 0x2F, 0x6F, 0x46, 0x42, 0x32, 0x41, 0x43, 0x59, 0x50, 0x54, 0x72, 0x49, 0x72, 0x6E, 0x71, 0x59, 0x4E, 0x78, ++ 0x67, 0x46, 0x6C, 0x51, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x6F, 0x30, 0x49, 0x77, 0x51, 0x44, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x59, 0x59, 0x77, 0x44, 0x77, ++ 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x0A, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x35, 0x4B, 0x38, 0x72, 0x4A, ++ 0x6E, 0x45, 0x61, 0x4B, 0x30, 0x67, 0x6E, 0x68, 0x53, 0x39, 0x53, 0x5A, 0x69, 0x7A, 0x76, 0x38, 0x49, 0x6B, 0x54, 0x63, 0x54, 0x34, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4D, 0x42, ++ 0x51, 0x41, 0x44, 0x0A, 0x67, 0x67, 0x49, 0x42, 0x41, 0x4A, 0x2B, 0x71, 0x51, 0x69, 0x62, 0x62, 0x43, 0x35, 0x75, 0x2B, 0x2F, 0x78, 0x36, 0x57, 0x6B, 0x69, 0x34, 0x2B, 0x6F, 0x6D, 0x56, 0x4B, 0x61, 0x70, 0x69, 0x36, 0x49, 0x73, 0x74, 0x39, ++ 0x77, 0x54, 0x72, 0x59, 0x67, 0x67, 0x6F, 0x47, 0x78, 0x76, 0x61, 0x6C, 0x33, 0x73, 0x42, 0x4F, 0x68, 0x32, 0x5A, 0x35, 0x6F, 0x66, 0x6D, 0x6D, 0x57, 0x4A, 0x79, 0x71, 0x2B, 0x62, 0x58, 0x6D, 0x59, 0x4F, 0x66, 0x67, 0x36, 0x4C, 0x45, 0x65, ++ 0x0A, 0x51, 0x6B, 0x45, 0x7A, 0x43, 0x7A, 0x63, 0x39, 0x7A, 0x6F, 0x6C, 0x77, 0x46, 0x63, 0x71, 0x31, 0x4A, 0x4B, 0x6A, 0x50, 0x61, 0x37, 0x58, 0x53, 0x51, 0x43, 0x47, 0x59, 0x7A, 0x79, 0x49, 0x30, 0x7A, 0x7A, 0x76, 0x46, 0x49, 0x6F, 0x54, ++ 0x67, 0x78, 0x51, 0x36, 0x4B, 0x66, 0x46, 0x32, 0x49, 0x35, 0x44, 0x55, 0x6B, 0x7A, 0x70, 0x73, 0x2B, 0x47, 0x6C, 0x51, 0x65, 0x62, 0x74, 0x75, 0x79, 0x68, 0x36, 0x66, 0x38, 0x38, 0x2F, 0x71, 0x42, 0x56, 0x52, 0x52, 0x69, 0x0A, 0x43, 0x6C, ++ 0x6D, 0x70, 0x49, 0x67, 0x55, 0x78, 0x50, 0x6F, 0x4C, 0x57, 0x37, 0x74, 0x74, 0x58, 0x4E, 0x4C, 0x77, 0x7A, 0x6C, 0x64, 0x4D, 0x58, 0x47, 0x2B, 0x67, 0x6E, 0x6F, 0x6F, 0x74, 0x37, 0x54, 0x69, 0x59, 0x61, 0x65, 0x6C, 0x70, 0x6B, 0x74, 0x74, ++ 0x47, 0x73, 0x4E, 0x2F, 0x48, 0x39, 0x6F, 0x50, 0x4D, 0x34, 0x37, 0x48, 0x4C, 0x77, 0x45, 0x58, 0x57, 0x64, 0x79, 0x7A, 0x52, 0x53, 0x6A, 0x65, 0x5A, 0x32, 0x61, 0x78, 0x66, 0x47, 0x33, 0x34, 0x61, 0x72, 0x0A, 0x4A, 0x34, 0x35, 0x4A, 0x4B, ++ 0x33, 0x56, 0x6D, 0x67, 0x52, 0x41, 0x68, 0x70, 0x75, 0x6F, 0x2B, 0x39, 0x4B, 0x34, 0x6C, 0x2F, 0x33, 0x77, 0x56, 0x33, 0x73, 0x36, 0x4D, 0x4A, 0x54, 0x2F, 0x4B, 0x59, 0x6E, 0x41, 0x4B, 0x39, 0x79, 0x38, 0x4A, 0x5A, 0x67, 0x66, 0x49, 0x50, ++ 0x78, 0x7A, 0x38, 0x38, 0x4E, 0x74, 0x46, 0x4D, 0x4E, 0x39, 0x69, 0x69, 0x4D, 0x47, 0x31, 0x44, 0x35, 0x33, 0x44, 0x6E, 0x30, 0x72, 0x65, 0x57, 0x56, 0x6C, 0x48, 0x78, 0x59, 0x63, 0x69, 0x0A, 0x4E, 0x75, 0x61, 0x43, 0x70, 0x2B, 0x30, 0x4B, ++ 0x75, 0x65, 0x49, 0x48, 0x6F, 0x49, 0x31, 0x37, 0x65, 0x6B, 0x6F, 0x38, 0x63, 0x64, 0x4C, 0x69, 0x41, 0x36, 0x45, 0x66, 0x4D, 0x67, 0x66, 0x64, 0x47, 0x2B, 0x52, 0x43, 0x7A, 0x67, 0x77, 0x41, 0x52, 0x57, 0x47, 0x41, 0x74, 0x51, 0x73, 0x67, ++ 0x57, 0x53, 0x6C, 0x34, 0x76, 0x66, 0x6C, 0x56, 0x79, 0x32, 0x50, 0x46, 0x50, 0x45, 0x7A, 0x30, 0x74, 0x76, 0x2F, 0x62, 0x61, 0x6C, 0x38, 0x78, 0x61, 0x35, 0x6D, 0x65, 0x0A, 0x4C, 0x4D, 0x46, 0x72, 0x55, 0x4B, 0x54, 0x58, 0x35, 0x68, 0x67, ++ 0x55, 0x76, 0x59, 0x55, 0x2F, 0x5A, 0x36, 0x74, 0x47, 0x6E, 0x36, 0x44, 0x2F, 0x51, 0x71, 0x63, 0x36, 0x66, 0x31, 0x7A, 0x4C, 0x58, 0x62, 0x42, 0x77, 0x48, 0x53, 0x73, 0x30, 0x39, 0x64, 0x52, 0x32, 0x43, 0x51, 0x7A, 0x72, 0x65, 0x45, 0x78, ++ 0x5A, 0x42, 0x66, 0x4D, 0x7A, 0x51, 0x73, 0x4E, 0x68, 0x46, 0x52, 0x41, 0x62, 0x64, 0x30, 0x33, 0x4F, 0x49, 0x6F, 0x7A, 0x55, 0x68, 0x66, 0x4A, 0x46, 0x0A, 0x66, 0x62, 0x64, 0x54, 0x36, 0x75, 0x39, 0x41, 0x57, 0x70, 0x51, 0x4B, 0x58, 0x43, ++ 0x42, 0x66, 0x54, 0x6B, 0x42, 0x64, 0x59, 0x69, 0x4A, 0x32, 0x33, 0x2F, 0x2F, 0x4F, 0x59, 0x62, 0x32, 0x4D, 0x49, 0x33, 0x6A, 0x53, 0x4E, 0x77, 0x4C, 0x67, 0x6A, 0x74, 0x37, 0x52, 0x45, 0x54, 0x65, 0x4A, 0x39, 0x72, 0x2F, 0x74, 0x53, 0x51, ++ 0x64, 0x69, 0x72, 0x70, 0x4C, 0x73, 0x51, 0x42, 0x71, 0x76, 0x46, 0x41, 0x6E, 0x5A, 0x30, 0x45, 0x36, 0x79, 0x6F, 0x76, 0x65, 0x2B, 0x0A, 0x37, 0x75, 0x37, 0x59, 0x2F, 0x39, 0x77, 0x61, 0x4C, 0x64, 0x36, 0x34, 0x4E, 0x6E, 0x48, 0x69, 0x2F, ++ 0x48, 0x6D, 0x33, 0x6C, 0x43, 0x58, 0x52, 0x53, 0x48, 0x4E, 0x62, 0x6F, 0x54, 0x58, 0x6E, 0x73, 0x35, 0x6C, 0x6E, 0x64, 0x63, 0x45, 0x5A, 0x4F, 0x69, 0x74, 0x48, 0x54, 0x74, 0x4E, 0x43, 0x6A, 0x76, 0x30, 0x78, 0x79, 0x42, 0x5A, 0x6D, 0x32, ++ 0x74, 0x49, 0x4D, 0x50, 0x4E, 0x75, 0x7A, 0x6A, 0x73, 0x6D, 0x68, 0x44, 0x59, 0x41, 0x50, 0x65, 0x78, 0x5A, 0x33, 0x0A, 0x46, 0x4C, 0x2F, 0x2F, 0x32, 0x77, 0x6D, 0x55, 0x73, 0x70, 0x4F, 0x38, 0x49, 0x46, 0x67, 0x56, 0x36, 0x64, 0x74, 0x78, ++ 0x51, 0x2F, 0x50, 0x65, 0x45, 0x4D, 0x4D, 0x41, 0x33, 0x4B, 0x67, 0x71, 0x6C, 0x62, 0x62, 0x43, 0x31, 0x6A, 0x2B, 0x51, 0x61, 0x33, 0x62, 0x62, 0x62, 0x50, 0x36, 0x4D, 0x76, 0x50, 0x4A, 0x77, 0x4E, 0x51, 0x7A, 0x63, 0x6D, 0x52, 0x6B, 0x31, ++ 0x33, 0x4E, 0x66, 0x49, 0x52, 0x6D, 0x50, 0x56, 0x4E, 0x6E, 0x47, 0x75, 0x56, 0x2F, 0x75, 0x33, 0x0A, 0x67, 0x6D, 0x33, 0x63, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, ++ 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x32, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, ++ 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x56, 0x7A, 0x43, 0x43, 0x41, 0x7A, 0x2B, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, ++ 0x4E, 0x41, 0x67, 0x50, 0x6C, 0x72, 0x73, 0x57, 0x4E, 0x42, 0x43, 0x55, 0x61, 0x71, 0x78, 0x45, 0x6C, 0x71, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x77, 0x46, 0x41, 0x44, 0x42, ++ 0x48, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x56, 0x0A, 0x55, 0x7A, 0x45, 0x69, 0x4D, 0x43, 0x41, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x5A, 0x52, 0x32, 0x39, 0x76, 0x5A, 0x32, ++ 0x78, 0x6C, 0x49, 0x46, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x49, 0x46, 0x4E, 0x6C, 0x63, 0x6E, 0x5A, 0x70, 0x59, 0x32, 0x56, 0x7A, 0x49, 0x45, 0x78, 0x4D, 0x51, 0x7A, 0x45, 0x55, 0x4D, 0x42, 0x49, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, ++ 0x4D, 0x4C, 0x52, 0x31, 0x52, 0x54, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x0A, 0x55, 0x6A, 0x49, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x54, 0x59, 0x77, 0x4E, 0x6A, 0x49, 0x79, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x57, ++ 0x68, 0x63, 0x4E, 0x4D, 0x7A, 0x59, 0x77, 0x4E, 0x6A, 0x49, 0x79, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x57, 0x6A, 0x42, 0x48, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x56, 0x55, ++ 0x7A, 0x45, 0x69, 0x4D, 0x43, 0x41, 0x47, 0x41, 0x31, 0x55, 0x45, 0x0A, 0x43, 0x68, 0x4D, 0x5A, 0x52, 0x32, 0x39, 0x76, 0x5A, 0x32, 0x78, 0x6C, 0x49, 0x46, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x49, 0x46, 0x4E, 0x6C, 0x63, 0x6E, 0x5A, 0x70, ++ 0x59, 0x32, 0x56, 0x7A, 0x49, 0x45, 0x78, 0x4D, 0x51, 0x7A, 0x45, 0x55, 0x4D, 0x42, 0x49, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x4C, 0x52, 0x31, 0x52, 0x54, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x55, 0x6A, 0x49, 0x77, ++ 0x67, 0x67, 0x49, 0x69, 0x4D, 0x41, 0x30, 0x47, 0x0A, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x49, 0x4B, 0x41, 0x6F, 0x49, ++ 0x43, 0x41, 0x51, 0x44, 0x4F, 0x33, 0x76, 0x32, 0x6D, 0x2B, 0x2B, 0x7A, 0x73, 0x46, 0x44, 0x51, 0x38, 0x42, 0x77, 0x5A, 0x61, 0x62, 0x46, 0x6E, 0x33, 0x47, 0x54, 0x58, 0x64, 0x39, 0x38, 0x47, 0x64, 0x56, 0x61, 0x72, 0x54, 0x7A, 0x54, 0x75, ++ 0x6B, 0x6B, 0x33, 0x4C, 0x76, 0x0A, 0x43, 0x76, 0x70, 0x74, 0x6E, 0x66, 0x62, 0x77, 0x68, 0x59, 0x42, 0x62, 0x6F, 0x55, 0x68, 0x53, 0x6E, 0x7A, 0x6E, 0x46, 0x74, 0x2B, 0x34, 0x6F, 0x72, 0x4F, 0x2F, 0x4C, 0x64, 0x6D, 0x67, 0x55, 0x75, 0x64, ++ 0x2B, 0x74, 0x41, 0x57, 0x79, 0x5A, 0x48, 0x38, 0x51, 0x69, 0x48, 0x5A, 0x2F, 0x2B, 0x63, 0x6E, 0x66, 0x67, 0x4C, 0x46, 0x75, 0x76, 0x35, 0x41, 0x53, 0x2F, 0x54, 0x33, 0x4B, 0x67, 0x47, 0x6A, 0x53, 0x59, 0x36, 0x44, 0x6C, 0x6F, 0x37, 0x4A, ++ 0x55, 0x6C, 0x0A, 0x65, 0x33, 0x61, 0x68, 0x35, 0x6D, 0x6D, 0x35, 0x68, 0x52, 0x6D, 0x39, 0x69, 0x59, 0x7A, 0x2B, 0x72, 0x65, 0x30, 0x32, 0x36, 0x6E, 0x4F, 0x38, 0x2F, 0x34, 0x50, 0x69, 0x79, 0x33, 0x33, 0x42, 0x30, 0x73, 0x35, 0x4B, 0x73, ++ 0x34, 0x30, 0x46, 0x6E, 0x6F, 0x74, 0x4A, 0x6B, 0x39, 0x2F, 0x42, 0x57, 0x39, 0x42, 0x75, 0x58, 0x76, 0x41, 0x75, 0x4D, 0x43, 0x36, 0x43, 0x2F, 0x50, 0x71, 0x38, 0x74, 0x42, 0x63, 0x4B, 0x53, 0x4F, 0x57, 0x49, 0x6D, 0x38, 0x57, 0x62, 0x0A, ++ 0x61, 0x39, 0x36, 0x77, 0x79, 0x72, 0x51, 0x44, 0x38, 0x4E, 0x72, 0x30, 0x6B, 0x4C, 0x68, 0x6C, 0x5A, 0x50, 0x64, 0x63, 0x54, 0x4B, 0x33, 0x6F, 0x66, 0x6D, 0x5A, 0x65, 0x6D, 0x64, 0x65, 0x34, 0x77, 0x6A, 0x37, 0x49, 0x30, 0x42, 0x4F, 0x64, ++ 0x72, 0x65, 0x37, 0x6B, 0x52, 0x58, 0x75, 0x4A, 0x56, 0x66, 0x65, 0x4B, 0x48, 0x32, 0x4A, 0x53, 0x68, 0x42, 0x4B, 0x7A, 0x77, 0x6B, 0x43, 0x58, 0x34, 0x34, 0x6F, 0x66, 0x52, 0x35, 0x47, 0x6D, 0x64, 0x46, 0x72, 0x53, 0x0A, 0x2B, 0x4C, 0x46, ++ 0x6A, 0x4B, 0x42, 0x43, 0x34, 0x73, 0x77, 0x6D, 0x34, 0x56, 0x6E, 0x64, 0x41, 0x6F, 0x69, 0x61, 0x59, 0x65, 0x63, 0x62, 0x2B, 0x33, 0x79, 0x58, 0x75, 0x50, 0x75, 0x57, 0x67, 0x66, 0x39, 0x52, 0x68, 0x44, 0x31, 0x46, 0x4C, 0x50, 0x44, 0x2B, ++ 0x4D, 0x32, 0x75, 0x46, 0x77, 0x64, 0x4E, 0x6A, 0x43, 0x61, 0x4B, 0x48, 0x35, 0x77, 0x51, 0x7A, 0x70, 0x6F, 0x65, 0x4A, 0x2F, 0x75, 0x31, 0x55, 0x38, 0x64, 0x67, 0x62, 0x75, 0x61, 0x6B, 0x37, 0x4D, 0x0A, 0x6B, 0x6F, 0x67, 0x77, 0x54, 0x5A, ++ 0x71, 0x39, 0x54, 0x77, 0x74, 0x49, 0x6D, 0x6F, 0x53, 0x31, 0x6D, 0x4B, 0x50, 0x56, 0x2B, 0x33, 0x50, 0x42, 0x56, 0x32, 0x48, 0x64, 0x4B, 0x46, 0x5A, 0x31, 0x45, 0x36, 0x36, 0x48, 0x6A, 0x75, 0x63, 0x4D, 0x55, 0x51, 0x6B, 0x51, 0x64, 0x59, ++ 0x68, 0x4D, 0x76, 0x49, 0x33, 0x35, 0x65, 0x7A, 0x7A, 0x55, 0x49, 0x6B, 0x67, 0x66, 0x4B, 0x74, 0x7A, 0x72, 0x61, 0x37, 0x74, 0x45, 0x73, 0x63, 0x73, 0x7A, 0x63, 0x54, 0x4A, 0x47, 0x0A, 0x72, 0x36, 0x31, 0x4B, 0x38, 0x59, 0x7A, 0x6F, 0x64, ++ 0x44, 0x71, 0x73, 0x35, 0x78, 0x6F, 0x69, 0x63, 0x34, 0x44, 0x53, 0x4D, 0x50, 0x63, 0x6C, 0x51, 0x73, 0x63, 0x69, 0x4F, 0x7A, 0x73, 0x53, 0x72, 0x5A, 0x59, 0x75, 0x78, 0x73, 0x4E, 0x32, 0x42, 0x36, 0x6F, 0x67, 0x74, 0x7A, 0x56, 0x4A, 0x56, ++ 0x2B, 0x6D, 0x53, 0x53, 0x65, 0x68, 0x32, 0x46, 0x6E, 0x49, 0x78, 0x5A, 0x79, 0x75, 0x57, 0x66, 0x6F, 0x71, 0x6A, 0x78, 0x35, 0x52, 0x57, 0x49, 0x72, 0x39, 0x71, 0x0A, 0x53, 0x33, 0x34, 0x42, 0x49, 0x62, 0x49, 0x6A, 0x4D, 0x74, 0x2F, 0x6B, ++ 0x6D, 0x6B, 0x52, 0x74, 0x57, 0x56, 0x74, 0x64, 0x39, 0x51, 0x43, 0x67, 0x48, 0x4A, 0x76, 0x47, 0x65, 0x4A, 0x65, 0x4E, 0x6B, 0x50, 0x2B, 0x62, 0x79, 0x4B, 0x71, 0x30, 0x72, 0x78, 0x46, 0x52, 0x4F, 0x56, 0x37, 0x5A, 0x2B, 0x32, 0x65, 0x74, ++ 0x31, 0x56, 0x73, 0x52, 0x6E, 0x54, 0x4B, 0x61, 0x47, 0x37, 0x33, 0x56, 0x75, 0x6C, 0x75, 0x6C, 0x79, 0x63, 0x73, 0x6C, 0x61, 0x56, 0x4E, 0x56, 0x0A, 0x4A, 0x31, 0x7A, 0x67, 0x79, 0x6A, 0x62, 0x4C, 0x69, 0x47, 0x48, 0x37, 0x48, 0x72, 0x66, ++ 0x51, 0x79, 0x2B, 0x34, 0x57, 0x2B, 0x39, 0x4F, 0x6D, 0x54, 0x4E, 0x36, 0x53, 0x70, 0x64, 0x54, 0x69, 0x33, 0x2F, 0x55, 0x47, 0x56, 0x4E, 0x34, 0x75, 0x6E, 0x55, 0x75, 0x30, 0x6B, 0x7A, 0x43, 0x71, 0x67, 0x63, 0x37, 0x64, 0x47, 0x74, 0x78, ++ 0x52, 0x63, 0x77, 0x31, 0x50, 0x63, 0x4F, 0x6E, 0x6C, 0x74, 0x68, 0x59, 0x68, 0x47, 0x58, 0x6D, 0x79, 0x35, 0x6F, 0x6B, 0x4C, 0x0A, 0x64, 0x57, 0x54, 0x4B, 0x31, 0x61, 0x75, 0x38, 0x43, 0x63, 0x45, 0x59, 0x6F, 0x66, 0x2F, 0x55, 0x56, 0x4B, ++ 0x47, 0x46, 0x50, 0x50, 0x30, 0x55, 0x4A, 0x41, 0x4F, 0x79, 0x68, 0x39, 0x4F, 0x6B, 0x74, 0x77, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x6F, 0x30, 0x49, 0x77, 0x51, 0x44, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x42, 0x41, 0x66, ++ 0x38, 0x45, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x59, 0x59, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x0A, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, ++ 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x75, 0x2F, 0x2F, 0x4B, 0x6A, 0x69, 0x4F, 0x66, 0x54, 0x35, 0x6E, 0x4B, 0x32, 0x2B, 0x4A, 0x6F, 0x70, 0x71, 0x55, 0x56, 0x4A, 0x78, 0x63, 0x65, 0x32, 0x51, 0x34, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, ++ 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4D, 0x42, 0x51, 0x41, 0x44, 0x0A, 0x67, 0x67, 0x49, 0x42, 0x41, 0x42, 0x2F, 0x4B, 0x7A, 0x74, 0x33, 0x48, 0x76, 0x71, 0x47, 0x66, 0x32, 0x53, 0x64, 0x4D, 0x43, 0x39, 0x77, 0x58, ++ 0x6D, 0x42, 0x46, 0x71, 0x69, 0x4E, 0x34, 0x39, 0x35, 0x6E, 0x46, 0x57, 0x63, 0x72, 0x4B, 0x65, 0x47, 0x6B, 0x36, 0x63, 0x31, 0x53, 0x75, 0x59, 0x4A, 0x46, 0x32, 0x62, 0x61, 0x33, 0x75, 0x77, 0x4D, 0x34, 0x49, 0x4A, 0x76, 0x64, 0x38, 0x6C, ++ 0x52, 0x75, 0x71, 0x59, 0x6E, 0x72, 0x59, 0x62, 0x2F, 0x6F, 0x4D, 0x38, 0x0A, 0x30, 0x6D, 0x4A, 0x68, 0x77, 0x51, 0x54, 0x74, 0x7A, 0x75, 0x44, 0x46, 0x79, 0x63, 0x67, 0x54, 0x45, 0x31, 0x58, 0x6E, 0x71, 0x47, 0x4F, 0x74, 0x6A, 0x48, 0x73, ++ 0x42, 0x2F, 0x6E, 0x63, 0x77, 0x34, 0x63, 0x35, 0x6F, 0x6D, 0x77, 0x58, 0x34, 0x45, 0x75, 0x35, 0x35, 0x4D, 0x61, 0x42, 0x42, 0x52, 0x54, 0x55, 0x6F, 0x43, 0x6E, 0x47, 0x6B, 0x4A, 0x45, 0x2B, 0x4D, 0x33, 0x44, 0x79, 0x43, 0x42, 0x31, 0x39, ++ 0x6D, 0x33, 0x48, 0x30, 0x51, 0x2F, 0x67, 0x78, 0x68, 0x0A, 0x73, 0x77, 0x57, 0x56, 0x37, 0x75, 0x47, 0x75, 0x67, 0x51, 0x2B, 0x6F, 0x2B, 0x4D, 0x65, 0x50, 0x54, 0x61, 0x67, 0x6A, 0x41, 0x69, 0x5A, 0x72, 0x48, 0x59, 0x4E, 0x53, 0x56, 0x63, ++ 0x36, 0x31, 0x4C, 0x77, 0x44, 0x4B, 0x67, 0x45, 0x44, 0x67, 0x34, 0x58, 0x53, 0x73, 0x59, 0x50, 0x57, 0x48, 0x67, 0x4A, 0x32, 0x75, 0x4E, 0x6D, 0x53, 0x52, 0x58, 0x62, 0x42, 0x6F, 0x47, 0x4F, 0x71, 0x4B, 0x59, 0x63, 0x6C, 0x33, 0x71, 0x4A, ++ 0x66, 0x45, 0x79, 0x63, 0x65, 0x6C, 0x0A, 0x2F, 0x46, 0x56, 0x4C, 0x38, 0x2F, 0x42, 0x2F, 0x75, 0x57, 0x55, 0x39, 0x4A, 0x32, 0x6A, 0x51, 0x7A, 0x47, 0x76, 0x36, 0x55, 0x35, 0x33, 0x68, 0x6B, 0x52, 0x72, 0x4A, 0x58, 0x52, 0x71, 0x57, 0x62, ++ 0x54, 0x4B, 0x48, 0x37, 0x51, 0x4D, 0x67, 0x79, 0x41, 0x4C, 0x4F, 0x57, 0x72, 0x37, 0x5A, 0x36, 0x76, 0x32, 0x79, 0x54, 0x63, 0x51, 0x76, 0x47, 0x39, 0x39, 0x66, 0x65, 0x76, 0x58, 0x34, 0x69, 0x38, 0x62, 0x75, 0x4D, 0x54, 0x6F, 0x6C, 0x55, ++ 0x56, 0x56, 0x6E, 0x0A, 0x6A, 0x57, 0x51, 0x79, 0x65, 0x2B, 0x6D, 0x65, 0x77, 0x34, 0x4B, 0x36, 0x4B, 0x69, 0x33, 0x70, 0x48, 0x72, 0x54, 0x67, 0x53, 0x41, 0x61, 0x69, 0x2F, 0x47, 0x65, 0x76, 0x48, 0x79, 0x49, 0x43, 0x63, 0x2F, 0x73, 0x67, ++ 0x43, 0x71, 0x2B, 0x64, 0x56, 0x45, 0x75, 0x68, 0x7A, 0x66, 0x39, 0x67, 0x52, 0x37, 0x41, 0x2F, 0x58, 0x65, 0x38, 0x62, 0x56, 0x72, 0x32, 0x58, 0x49, 0x5A, 0x59, 0x74, 0x43, 0x74, 0x46, 0x65, 0x6E, 0x54, 0x67, 0x43, 0x52, 0x32, 0x79, 0x35, ++ 0x0A, 0x39, 0x50, 0x59, 0x6A, 0x4A, 0x62, 0x69, 0x67, 0x61, 0x70, 0x6F, 0x72, 0x64, 0x77, 0x6A, 0x36, 0x78, 0x4C, 0x45, 0x6F, 0x6B, 0x43, 0x5A, 0x59, 0x43, 0x44, 0x7A, 0x69, 0x66, 0x71, 0x72, 0x58, 0x50, 0x57, 0x2B, 0x36, 0x4D, 0x59, 0x67, ++ 0x4B, 0x42, 0x65, 0x73, 0x6E, 0x74, 0x61, 0x46, 0x4A, 0x37, 0x71, 0x42, 0x46, 0x56, 0x48, 0x76, 0x6D, 0x4A, 0x32, 0x57, 0x5A, 0x49, 0x43, 0x47, 0x6F, 0x6F, 0x37, 0x7A, 0x37, 0x47, 0x4A, 0x61, 0x37, 0x55, 0x6D, 0x38, 0x4D, 0x0A, 0x37, 0x59, ++ 0x4E, 0x52, 0x54, 0x4F, 0x6C, 0x5A, 0x34, 0x69, 0x42, 0x67, 0x78, 0x63, 0x4A, 0x6C, 0x6B, 0x6F, 0x4B, 0x4D, 0x38, 0x78, 0x41, 0x66, 0x44, 0x6F, 0x71, 0x58, 0x76, 0x6E, 0x65, 0x43, 0x62, 0x54, 0x2B, 0x50, 0x48, 0x56, 0x32, 0x38, 0x53, 0x53, ++ 0x65, 0x39, 0x7A, 0x45, 0x38, 0x50, 0x34, 0x63, 0x35, 0x32, 0x68, 0x67, 0x51, 0x6A, 0x78, 0x63, 0x43, 0x4D, 0x45, 0x6C, 0x76, 0x39, 0x32, 0x34, 0x53, 0x67, 0x4A, 0x50, 0x46, 0x49, 0x2F, 0x32, 0x52, 0x38, 0x0A, 0x30, 0x4C, 0x35, 0x63, 0x46, ++ 0x74, 0x48, 0x76, 0x6D, 0x61, 0x33, 0x41, 0x48, 0x2F, 0x76, 0x4C, 0x72, 0x72, 0x77, 0x34, 0x49, 0x67, 0x59, 0x6D, 0x5A, 0x4E, 0x72, 0x61, 0x6C, 0x77, 0x34, 0x2F, 0x4B, 0x42, 0x56, 0x45, 0x71, 0x45, 0x38, 0x41, 0x79, 0x76, 0x43, 0x61, 0x7A, ++ 0x4D, 0x39, 0x30, 0x61, 0x72, 0x51, 0x2B, 0x50, 0x4F, 0x75, 0x56, 0x37, 0x4C, 0x58, 0x54, 0x57, 0x74, 0x69, 0x42, 0x6D, 0x65, 0x6C, 0x44, 0x47, 0x44, 0x66, 0x72, 0x73, 0x37, 0x76, 0x52, 0x0A, 0x57, 0x47, 0x4A, 0x42, 0x38, 0x32, 0x62, 0x53, ++ 0x6A, 0x36, 0x70, 0x34, 0x6C, 0x56, 0x51, 0x67, 0x77, 0x31, 0x6F, 0x75, 0x64, 0x43, 0x76, 0x56, 0x30, 0x62, 0x34, 0x59, 0x61, 0x63, 0x43, 0x73, 0x31, 0x61, 0x54, 0x50, 0x4F, 0x62, 0x70, 0x52, 0x68, 0x41, 0x4E, 0x6C, 0x36, 0x57, 0x4C, 0x41, ++ 0x59, 0x76, 0x37, 0x59, 0x54, 0x56, 0x57, 0x57, 0x34, 0x74, 0x41, 0x52, 0x2B, 0x6B, 0x67, 0x30, 0x45, 0x65, 0x79, 0x65, 0x37, 0x51, 0x55, 0x64, 0x35, 0x4D, 0x6A, 0x57, 0x0A, 0x48, 0x59, 0x62, 0x4C, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, ++ 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x33, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x43, 0x43, 0x54, 0x43, ++ 0x43, 0x41, 0x59, 0x36, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x4E, 0x41, 0x67, 0x50, 0x6C, 0x75, 0x49, 0x4C, 0x72, 0x49, 0x50, 0x67, 0x6C, 0x4A, 0x32, 0x30, 0x39, 0x5A, 0x6A, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, ++ 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x7A, 0x42, 0x48, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x56, 0x55, 0x7A, 0x45, 0x69, 0x0A, 0x4D, 0x43, 0x41, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, ++ 0x4D, 0x5A, 0x52, 0x32, 0x39, 0x76, 0x5A, 0x32, 0x78, 0x6C, 0x49, 0x46, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x49, 0x46, 0x4E, 0x6C, 0x63, 0x6E, 0x5A, 0x70, 0x59, 0x32, 0x56, 0x7A, 0x49, 0x45, 0x78, 0x4D, 0x51, 0x7A, 0x45, 0x55, 0x4D, 0x42, ++ 0x49, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x4C, 0x52, 0x31, 0x52, 0x54, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x55, 0x6A, 0x4D, 0x77, 0x0A, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x54, 0x59, 0x77, 0x4E, 0x6A, 0x49, 0x79, 0x4D, ++ 0x44, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x57, 0x68, 0x63, 0x4E, 0x4D, 0x7A, 0x59, 0x77, 0x4E, 0x6A, 0x49, 0x79, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x57, 0x6A, 0x42, 0x48, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, ++ 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x56, 0x55, 0x7A, 0x45, 0x69, 0x4D, 0x43, 0x41, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x5A, 0x0A, 0x52, 0x32, 0x39, 0x76, 0x5A, 0x32, 0x78, 0x6C, 0x49, 0x46, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, ++ 0x49, 0x46, 0x4E, 0x6C, 0x63, 0x6E, 0x5A, 0x70, 0x59, 0x32, 0x56, 0x7A, 0x49, 0x45, 0x78, 0x4D, 0x51, 0x7A, 0x45, 0x55, 0x4D, 0x42, 0x49, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x4C, 0x52, 0x31, 0x52, 0x54, 0x49, 0x46, 0x4A, 0x76, ++ 0x62, 0x33, 0x51, 0x67, 0x55, 0x6A, 0x4D, 0x77, 0x64, 0x6A, 0x41, 0x51, 0x42, 0x67, 0x63, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x0A, 0x50, 0x51, 0x49, 0x42, 0x42, 0x67, 0x55, 0x72, 0x67, 0x51, 0x51, 0x41, 0x49, 0x67, 0x4E, 0x69, 0x41, 0x41, 0x51, ++ 0x66, 0x54, 0x7A, 0x4F, 0x48, 0x4D, 0x79, 0x6D, 0x4B, 0x6F, 0x59, 0x54, 0x65, 0x79, 0x38, 0x63, 0x68, 0x57, 0x45, 0x47, 0x4A, 0x36, 0x6C, 0x61, 0x64, 0x4B, 0x30, 0x75, 0x46, 0x78, 0x68, 0x31, 0x4D, 0x4A, 0x37, 0x78, 0x2F, 0x4A, 0x6C, 0x46, ++ 0x79, 0x62, 0x2B, 0x4B, 0x66, 0x31, 0x71, 0x50, 0x4B, 0x7A, 0x45, 0x55, 0x55, 0x52, 0x6F, 0x75, 0x74, 0x0A, 0x37, 0x33, 0x36, 0x47, 0x6A, 0x4F, 0x79, 0x78, 0x66, 0x69, 0x2F, 0x2F, 0x71, 0x58, 0x47, 0x64, 0x47, 0x49, 0x52, 0x46, 0x42, 0x45, ++ 0x46, 0x56, 0x62, 0x69, 0x76, 0x71, 0x4A, 0x6E, 0x2B, 0x37, 0x6B, 0x41, 0x48, 0x6A, 0x53, 0x78, 0x6D, 0x36, 0x35, 0x46, 0x53, 0x57, 0x52, 0x51, 0x6D, 0x78, 0x31, 0x57, 0x79, 0x52, 0x52, 0x4B, 0x32, 0x45, 0x45, 0x34, 0x36, 0x61, 0x6A, 0x41, ++ 0x32, 0x41, 0x44, 0x44, 0x4C, 0x32, 0x34, 0x43, 0x65, 0x6A, 0x51, 0x6A, 0x42, 0x41, 0x0A, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x42, 0x68, 0x6A, 0x41, 0x50, 0x42, ++ 0x67, 0x4E, 0x56, 0x48, 0x52, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x54, 0x41, 0x44, 0x41, 0x51, 0x48, 0x2F, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x54, 0x42, 0x38, 0x53, 0x61, 0x36, 0x6F, ++ 0x43, 0x32, 0x75, 0x68, 0x59, 0x48, 0x50, 0x30, 0x2F, 0x45, 0x71, 0x0A, 0x45, 0x72, 0x32, 0x34, 0x43, 0x6D, 0x66, 0x39, 0x76, 0x44, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x77, 0x4E, 0x70, ++ 0x41, 0x44, 0x42, 0x6D, 0x41, 0x6A, 0x45, 0x41, 0x39, 0x75, 0x45, 0x67, 0x6C, 0x52, 0x52, 0x37, 0x56, 0x4B, 0x4F, 0x51, 0x46, 0x68, 0x47, 0x2F, 0x68, 0x4D, 0x6A, 0x71, 0x62, 0x32, 0x73, 0x58, 0x6E, 0x68, 0x35, 0x47, 0x6D, 0x43, 0x43, 0x62, ++ 0x6E, 0x39, 0x4D, 0x4E, 0x32, 0x61, 0x7A, 0x54, 0x0A, 0x4C, 0x38, 0x31, 0x38, 0x2B, 0x46, 0x73, 0x75, 0x56, 0x62, 0x75, 0x2F, 0x33, 0x5A, 0x4C, 0x33, 0x70, 0x41, 0x7A, 0x63, 0x4D, 0x65, 0x47, 0x69, 0x41, 0x6A, 0x45, 0x41, 0x2F, 0x4A, 0x64, ++ 0x6D, 0x5A, 0x75, 0x56, 0x44, 0x46, 0x68, 0x4F, 0x44, 0x33, 0x63, 0x66, 0x66, 0x4C, 0x37, 0x34, 0x55, 0x4F, 0x4F, 0x30, 0x42, 0x7A, 0x72, 0x45, 0x58, 0x47, 0x68, 0x46, 0x31, 0x36, 0x62, 0x30, 0x44, 0x6A, 0x79, 0x5A, 0x2B, 0x68, 0x4F, 0x58, ++ 0x4A, 0x59, 0x4B, 0x61, 0x56, 0x0A, 0x31, 0x31, 0x52, 0x5A, 0x74, 0x2B, 0x63, 0x52, 0x4C, 0x49, 0x6E, 0x55, 0x75, 0x65, 0x34, 0x58, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, ++ 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x34, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, ++ 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x43, 0x43, 0x54, 0x43, 0x43, 0x41, 0x59, 0x36, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, ++ 0x49, 0x4E, 0x41, 0x67, 0x50, 0x6C, 0x77, 0x47, 0x6A, 0x76, 0x59, 0x78, 0x71, 0x63, 0x63, 0x70, 0x42, 0x51, 0x55, 0x6A, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x7A, 0x42, 0x48, 0x4D, 0x51, ++ 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x56, 0x55, 0x7A, 0x45, 0x69, 0x0A, 0x4D, 0x43, 0x41, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x5A, 0x52, 0x32, 0x39, 0x76, 0x5A, 0x32, 0x78, 0x6C, 0x49, ++ 0x46, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x49, 0x46, 0x4E, 0x6C, 0x63, 0x6E, 0x5A, 0x70, 0x59, 0x32, 0x56, 0x7A, 0x49, 0x45, 0x78, 0x4D, 0x51, 0x7A, 0x45, 0x55, 0x4D, 0x42, 0x49, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x4C, 0x52, ++ 0x31, 0x52, 0x54, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x55, 0x6A, 0x51, 0x77, 0x0A, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x54, 0x59, 0x77, 0x4E, 0x6A, 0x49, 0x79, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x57, 0x68, 0x63, 0x4E, ++ 0x4D, 0x7A, 0x59, 0x77, 0x4E, 0x6A, 0x49, 0x79, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x57, 0x6A, 0x42, 0x48, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x56, 0x55, 0x7A, 0x45, 0x69, ++ 0x4D, 0x43, 0x41, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x5A, 0x0A, 0x52, 0x32, 0x39, 0x76, 0x5A, 0x32, 0x78, 0x6C, 0x49, 0x46, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x49, 0x46, 0x4E, 0x6C, 0x63, 0x6E, 0x5A, 0x70, 0x59, 0x32, 0x56, ++ 0x7A, 0x49, 0x45, 0x78, 0x4D, 0x51, 0x7A, 0x45, 0x55, 0x4D, 0x42, 0x49, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x4C, 0x52, 0x31, 0x52, 0x54, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x55, 0x6A, 0x51, 0x77, 0x64, 0x6A, 0x41, ++ 0x51, 0x42, 0x67, 0x63, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x0A, 0x50, 0x51, 0x49, 0x42, 0x42, 0x67, 0x55, 0x72, 0x67, 0x51, 0x51, 0x41, 0x49, 0x67, 0x4E, 0x69, 0x41, 0x41, 0x54, 0x7A, 0x64, 0x48, 0x4F, 0x6E, 0x61, 0x49, 0x74, 0x67, 0x72, 0x6B, ++ 0x4F, 0x34, 0x4E, 0x63, 0x57, 0x42, 0x4D, 0x48, 0x74, 0x4C, 0x53, 0x5A, 0x33, 0x37, 0x77, 0x57, 0x48, 0x4F, 0x35, 0x74, 0x35, 0x47, 0x76, 0x57, 0x76, 0x56, 0x59, 0x52, 0x67, 0x31, 0x72, 0x6B, 0x44, 0x64, 0x63, 0x2F, 0x65, 0x4A, 0x6B, 0x54, ++ 0x42, 0x61, 0x36, 0x7A, 0x7A, 0x75, 0x0A, 0x68, 0x58, 0x79, 0x69, 0x51, 0x48, 0x59, 0x37, 0x71, 0x63, 0x61, 0x34, 0x52, 0x39, 0x67, 0x71, 0x35, 0x35, 0x4B, 0x52, 0x61, 0x6E, 0x50, 0x70, 0x73, 0x58, 0x49, 0x35, 0x6E, 0x79, 0x6D, 0x66, 0x6F, ++ 0x70, 0x6A, 0x54, 0x58, 0x31, 0x35, 0x59, 0x68, 0x6D, 0x55, 0x50, 0x6F, 0x59, 0x52, 0x6C, 0x42, 0x74, 0x48, 0x63, 0x69, 0x38, 0x6E, 0x48, 0x63, 0x38, 0x69, 0x4D, 0x61, 0x69, 0x2F, 0x6C, 0x78, 0x4B, 0x76, 0x52, 0x48, 0x59, 0x71, 0x6A, 0x51, ++ 0x6A, 0x42, 0x41, 0x0A, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x42, 0x68, 0x6A, 0x41, 0x50, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x52, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x45, ++ 0x42, 0x54, 0x41, 0x44, 0x41, 0x51, 0x48, 0x2F, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x53, 0x41, 0x54, 0x4E, 0x62, 0x72, 0x64, 0x50, 0x39, 0x4A, 0x4E, 0x71, 0x50, 0x56, 0x32, 0x50, 0x79, 0x31, ++ 0x0A, 0x50, 0x73, 0x56, 0x71, 0x38, 0x4A, 0x51, 0x64, 0x6A, 0x44, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x77, 0x4E, 0x70, 0x41, 0x44, 0x42, 0x6D, 0x41, 0x6A, 0x45, 0x41, 0x36, 0x45, 0x44, ++ 0x2F, 0x67, 0x39, 0x34, 0x44, 0x39, 0x4A, 0x2B, 0x75, 0x48, 0x58, 0x71, 0x6E, 0x4C, 0x72, 0x6D, 0x76, 0x54, 0x2F, 0x61, 0x44, 0x48, 0x51, 0x34, 0x74, 0x68, 0x51, 0x45, 0x64, 0x30, 0x64, 0x6C, 0x71, 0x37, 0x41, 0x2F, 0x43, 0x0A, 0x72, 0x38, ++ 0x64, 0x65, 0x56, 0x6C, 0x35, 0x63, 0x31, 0x52, 0x78, 0x59, 0x49, 0x69, 0x67, 0x4C, 0x39, 0x7A, 0x43, 0x32, 0x4C, 0x37, 0x46, 0x38, 0x41, 0x6A, 0x45, 0x41, 0x38, 0x47, 0x45, 0x38, 0x70, 0x2F, 0x53, 0x67, 0x67, 0x75, 0x4D, 0x68, 0x31, 0x59, ++ 0x51, 0x64, 0x63, 0x34, 0x61, 0x63, 0x4C, 0x61, 0x2F, 0x4B, 0x4E, 0x4A, 0x76, 0x78, 0x6E, 0x37, 0x6B, 0x6A, 0x4E, 0x75, 0x4B, 0x38, 0x59, 0x41, 0x4F, 0x64, 0x67, 0x4C, 0x4F, 0x61, 0x56, 0x73, 0x6A, 0x68, 0x0A, 0x34, 0x72, 0x73, 0x55, 0x65, ++ 0x63, 0x72, 0x4E, 0x49, 0x64, 0x53, 0x55, 0x74, 0x55, 0x6C, 0x44, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x54, ++ 0x65, 0x6C, 0x69, 0x61, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x76, 0x32, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, ++ 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x64, 0x44, 0x43, 0x43, 0x41, 0x31, 0x79, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, ++ 0x50, 0x41, 0x57, 0x64, 0x66, 0x4A, 0x39, 0x62, 0x2B, 0x65, 0x75, 0x50, 0x6B, 0x72, 0x4C, 0x34, 0x4A, 0x57, 0x77, 0x57, 0x65, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x43, 0x77, 0x55, ++ 0x41, 0x4D, 0x45, 0x51, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x0A, 0x41, 0x6B, 0x5A, 0x4A, 0x4D, 0x52, 0x6F, 0x77, 0x47, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x44, 0x42, 0x46, 0x55, 0x5A, 0x57, ++ 0x78, 0x70, 0x59, 0x53, 0x42, 0x47, 0x61, 0x57, 0x35, 0x73, 0x59, 0x57, 0x35, 0x6B, 0x49, 0x45, 0x39, 0x35, 0x61, 0x6A, 0x45, 0x5A, 0x4D, 0x42, 0x63, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x77, 0x77, 0x51, 0x56, 0x47, 0x56, 0x73, 0x61, 0x57, ++ 0x45, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x51, 0x53, 0x42, 0x32, 0x0A, 0x4D, 0x6A, 0x41, 0x65, 0x46, 0x77, 0x30, 0x78, 0x4F, 0x44, 0x45, 0x78, 0x4D, 0x6A, 0x6B, 0x78, 0x4D, 0x54, 0x55, 0x31, 0x4E, 0x54, 0x52, 0x61, 0x46, ++ 0x77, 0x30, 0x30, 0x4D, 0x7A, 0x45, 0x78, 0x4D, 0x6A, 0x6B, 0x78, 0x4D, 0x54, 0x55, 0x31, 0x4E, 0x54, 0x52, 0x61, 0x4D, 0x45, 0x51, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6B, 0x5A, 0x4A, 0x4D, ++ 0x52, 0x6F, 0x77, 0x47, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x0A, 0x44, 0x42, 0x46, 0x55, 0x5A, 0x57, 0x78, 0x70, 0x59, 0x53, 0x42, 0x47, 0x61, 0x57, 0x35, 0x73, 0x59, 0x57, 0x35, 0x6B, 0x49, 0x45, 0x39, 0x35, 0x61, 0x6A, 0x45, 0x5A, ++ 0x4D, 0x42, 0x63, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x77, 0x77, 0x51, 0x56, 0x47, 0x56, 0x73, 0x61, 0x57, 0x45, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x51, 0x53, 0x42, 0x32, 0x4D, 0x6A, 0x43, 0x43, 0x41, 0x69, 0x49, 0x77, ++ 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x0A, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x50, 0x41, 0x44, 0x43, 0x43, 0x41, 0x67, 0x6F, 0x43, 0x67, 0x67, 0x49, 0x42, 0x41, 0x4C, 0x4C, ++ 0x51, 0x50, 0x77, 0x65, 0x38, 0x34, 0x6E, 0x76, 0x51, 0x61, 0x35, 0x6E, 0x34, 0x34, 0x6E, 0x64, 0x70, 0x35, 0x38, 0x36, 0x64, 0x70, 0x41, 0x4F, 0x38, 0x67, 0x6D, 0x32, 0x68, 0x2F, 0x6F, 0x46, 0x6C, 0x48, 0x30, 0x77, 0x6E, 0x72, 0x49, 0x34, ++ 0x41, 0x75, 0x68, 0x5A, 0x37, 0x0A, 0x36, 0x7A, 0x42, 0x71, 0x41, 0x4D, 0x43, 0x7A, 0x64, 0x47, 0x68, 0x2B, 0x73, 0x71, 0x2F, 0x48, 0x31, 0x57, 0x4B, 0x7A, 0x65, 0x6A, 0x39, 0x51, 0x79, 0x6F, 0x77, 0x32, 0x52, 0x43, 0x52, 0x6A, 0x30, 0x6A, ++ 0x62, 0x70, 0x44, 0x49, 0x58, 0x32, 0x51, 0x33, 0x62, 0x56, 0x54, 0x4B, 0x46, 0x67, 0x63, 0x6D, 0x66, 0x69, 0x4B, 0x44, 0x4F, 0x6C, 0x79, 0x7A, 0x47, 0x34, 0x4F, 0x69, 0x49, 0x6A, 0x4E, 0x4C, 0x68, 0x39, 0x76, 0x56, 0x59, 0x69, 0x51, 0x4A, ++ 0x33, 0x71, 0x0A, 0x39, 0x48, 0x73, 0x44, 0x72, 0x57, 0x6A, 0x38, 0x73, 0x6F, 0x46, 0x50, 0x6D, 0x4E, 0x42, 0x30, 0x36, 0x6F, 0x33, 0x6C, 0x66, 0x63, 0x31, 0x6A, 0x77, 0x36, 0x50, 0x32, 0x33, 0x70, 0x4C, 0x43, 0x57, 0x42, 0x6E, 0x67, 0x6C, ++ 0x72, 0x76, 0x46, 0x78, 0x4B, 0x6B, 0x39, 0x70, 0x58, 0x53, 0x57, 0x2F, 0x71, 0x2F, 0x35, 0x69, 0x61, 0x71, 0x39, 0x6C, 0x52, 0x64, 0x55, 0x32, 0x48, 0x68, 0x45, 0x38, 0x51, 0x78, 0x33, 0x46, 0x5A, 0x4C, 0x67, 0x6D, 0x45, 0x4B, 0x6E, 0x0A, ++ 0x70, 0x4E, 0x61, 0x71, 0x49, 0x4A, 0x4C, 0x4E, 0x77, 0x61, 0x43, 0x7A, 0x6C, 0x72, 0x49, 0x36, 0x68, 0x45, 0x4B, 0x4E, 0x66, 0x64, 0x57, 0x56, 0x35, 0x4E, 0x62, 0x62, 0x36, 0x57, 0x4C, 0x45, 0x57, 0x4C, 0x4E, 0x35, 0x78, 0x59, 0x7A, 0x54, ++ 0x4E, 0x54, 0x4F, 0x44, 0x6E, 0x33, 0x57, 0x68, 0x55, 0x69, 0x64, 0x68, 0x4F, 0x50, 0x46, 0x5A, 0x50, 0x59, 0x35, 0x51, 0x34, 0x4C, 0x31, 0x35, 0x50, 0x4F, 0x64, 0x73, 0x6C, 0x76, 0x35, 0x65, 0x32, 0x51, 0x4A, 0x6C, 0x0A, 0x74, 0x49, 0x35, ++ 0x63, 0x30, 0x42, 0x45, 0x30, 0x33, 0x31, 0x32, 0x2F, 0x55, 0x71, 0x65, 0x42, 0x41, 0x4D, 0x4E, 0x2F, 0x6D, 0x55, 0x57, 0x5A, 0x46, 0x64, 0x55, 0x58, 0x79, 0x41, 0x70, 0x54, 0x37, 0x47, 0x50, 0x7A, 0x6D, 0x58, 0x33, 0x4D, 0x61, 0x52, 0x4B, ++ 0x47, 0x77, 0x68, 0x66, 0x77, 0x41, 0x5A, 0x36, 0x2F, 0x68, 0x4C, 0x7A, 0x52, 0x55, 0x73, 0x73, 0x62, 0x6B, 0x6D, 0x62, 0x4F, 0x70, 0x46, 0x50, 0x6C, 0x6F, 0x62, 0x2F, 0x45, 0x32, 0x77, 0x6E, 0x57, 0x0A, 0x35, 0x6F, 0x6C, 0x57, 0x4B, 0x38, ++ 0x6A, 0x6A, 0x66, 0x4E, 0x37, 0x6A, 0x2F, 0x34, 0x6E, 0x6C, 0x4E, 0x57, 0x34, 0x6F, 0x36, 0x47, 0x77, 0x4C, 0x49, 0x31, 0x47, 0x70, 0x4A, 0x51, 0x58, 0x72, 0x53, 0x50, 0x6A, 0x64, 0x73, 0x63, 0x72, 0x36, 0x62, 0x41, 0x68, 0x52, 0x37, 0x37, ++ 0x63, 0x59, 0x62, 0x45, 0x54, 0x4B, 0x4A, 0x75, 0x46, 0x7A, 0x78, 0x6F, 0x6B, 0x47, 0x67, 0x65, 0x57, 0x4B, 0x72, 0x4C, 0x44, 0x69, 0x4B, 0x63, 0x61, 0x35, 0x4A, 0x4C, 0x4E, 0x72, 0x0A, 0x52, 0x42, 0x48, 0x30, 0x70, 0x55, 0x50, 0x43, 0x54, ++ 0x45, 0x50, 0x6C, 0x63, 0x44, 0x61, 0x4D, 0x74, 0x6A, 0x4E, 0x58, 0x65, 0x70, 0x55, 0x75, 0x67, 0x71, 0x44, 0x30, 0x58, 0x42, 0x43, 0x7A, 0x59, 0x59, 0x50, 0x32, 0x41, 0x67, 0x57, 0x47, 0x4C, 0x6E, 0x77, 0x74, 0x62, 0x4E, 0x77, 0x44, 0x52, ++ 0x6D, 0x34, 0x31, 0x6B, 0x39, 0x56, 0x36, 0x6C, 0x53, 0x2F, 0x65, 0x49, 0x4E, 0x68, 0x62, 0x66, 0x70, 0x53, 0x51, 0x42, 0x47, 0x71, 0x36, 0x57, 0x54, 0x30, 0x45, 0x0A, 0x42, 0x58, 0x57, 0x64, 0x4E, 0x36, 0x49, 0x4F, 0x4C, 0x6A, 0x33, 0x72, ++ 0x77, 0x61, 0x52, 0x53, 0x67, 0x2F, 0x37, 0x51, 0x61, 0x39, 0x52, 0x6D, 0x6A, 0x74, 0x7A, 0x47, 0x36, 0x52, 0x4A, 0x4F, 0x48, 0x53, 0x70, 0x58, 0x71, 0x68, 0x43, 0x38, 0x66, 0x46, 0x36, 0x43, 0x66, 0x61, 0x61, 0x6D, 0x79, 0x66, 0x49, 0x74, ++ 0x75, 0x66, 0x55, 0x58, 0x4A, 0x36, 0x33, 0x52, 0x44, 0x6F, 0x6C, 0x55, 0x4B, 0x35, 0x58, 0x36, 0x77, 0x4B, 0x30, 0x64, 0x6D, 0x42, 0x52, 0x34, 0x0A, 0x4D, 0x30, 0x4B, 0x47, 0x43, 0x71, 0x6C, 0x7A, 0x74, 0x66, 0x74, 0x30, 0x44, 0x62, 0x63, ++ 0x62, 0x4D, 0x42, 0x6E, 0x45, 0x57, 0x67, 0x34, 0x63, 0x4A, 0x37, 0x66, 0x61, 0x47, 0x4E, 0x44, 0x2F, 0x69, 0x73, 0x67, 0x46, 0x75, 0x76, 0x47, 0x71, 0x48, 0x4B, 0x49, 0x33, 0x74, 0x2B, 0x5A, 0x49, 0x70, 0x45, 0x59, 0x73, 0x6C, 0x4F, 0x71, ++ 0x6F, 0x64, 0x6D, 0x4A, 0x48, 0x69, 0x78, 0x42, 0x54, 0x42, 0x30, 0x68, 0x58, 0x62, 0x4F, 0x4B, 0x53, 0x54, 0x62, 0x61, 0x75, 0x0A, 0x42, 0x63, 0x76, 0x63, 0x77, 0x55, 0x70, 0x65, 0x6A, 0x36, 0x77, 0x39, 0x47, 0x55, 0x37, 0x43, 0x37, 0x57, ++ 0x42, 0x31, 0x4B, 0x39, 0x76, 0x42, 0x79, 0x6B, 0x4C, 0x56, 0x41, 0x67, 0x4D, 0x42, 0x41, 0x41, 0x47, 0x6A, 0x59, 0x7A, 0x42, 0x68, 0x4D, 0x42, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x49, 0x77, 0x51, 0x59, 0x4D, 0x42, 0x61, 0x41, 0x46, 0x48, ++ 0x4B, 0x73, 0x35, 0x44, 0x4E, 0x35, 0x71, 0x6B, 0x57, 0x48, 0x39, 0x76, 0x32, 0x73, 0x48, 0x5A, 0x37, 0x57, 0x0A, 0x78, 0x79, 0x2B, 0x47, 0x32, 0x43, 0x51, 0x35, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, 0x42, ++ 0x42, 0x52, 0x79, 0x72, 0x4F, 0x51, 0x7A, 0x65, 0x61, 0x70, 0x46, 0x68, 0x2F, 0x62, 0x39, 0x72, 0x42, 0x32, 0x65, 0x31, 0x73, 0x63, 0x76, 0x68, 0x74, 0x67, 0x6B, 0x4F, 0x54, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x42, 0x41, ++ 0x66, 0x38, 0x45, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x51, 0x59, 0x77, 0x44, 0x77, 0x59, 0x44, 0x0A, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, ++ 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x67, 0x45, 0x41, 0x6F, 0x44, 0x74, 0x5A, 0x70, 0x77, 0x6D, 0x55, 0x50, 0x6A, 0x61, 0x45, 0x30, 0x6E, 0x34, 0x76, 0x4F, 0x61, 0x57, 0x57, ++ 0x6C, 0x2F, 0x6F, 0x52, 0x72, 0x66, 0x78, 0x6E, 0x38, 0x33, 0x45, 0x4A, 0x0A, 0x38, 0x72, 0x4B, 0x4A, 0x68, 0x47, 0x64, 0x45, 0x72, 0x37, 0x6E, 0x76, 0x37, 0x5A, 0x62, 0x73, 0x6E, 0x47, 0x54, 0x62, 0x4D, 0x6A, 0x42, 0x76, 0x5A, 0x35, 0x71, ++ 0x73, 0x66, 0x6C, 0x2B, 0x79, 0x71, 0x77, 0x45, 0x32, 0x66, 0x6F, 0x48, 0x36, 0x35, 0x49, 0x52, 0x65, 0x30, 0x71, 0x77, 0x32, 0x34, 0x47, 0x74, 0x69, 0x78, 0x58, 0x31, 0x4C, 0x44, 0x6F, 0x4A, 0x74, 0x30, 0x6E, 0x5A, 0x69, 0x30, 0x66, 0x36, ++ 0x58, 0x2B, 0x4A, 0x38, 0x77, 0x66, 0x42, 0x6A, 0x35, 0x0A, 0x74, 0x46, 0x4A, 0x33, 0x67, 0x68, 0x31, 0x32, 0x32, 0x39, 0x4D, 0x64, 0x71, 0x66, 0x44, 0x42, 0x6D, 0x67, 0x43, 0x39, 0x62, 0x58, 0x58, 0x59, 0x66, 0x65, 0x66, 0x36, 0x78, 0x7A, ++ 0x69, 0x6A, 0x6E, 0x48, 0x44, 0x6F, 0x52, 0x6E, 0x6B, 0x44, 0x72, 0x79, 0x35, 0x30, 0x32, 0x33, 0x58, 0x34, 0x62, 0x6C, 0x4D, 0x4D, 0x41, 0x38, 0x69, 0x5A, 0x47, 0x6F, 0x6B, 0x31, 0x47, 0x54, 0x7A, 0x54, 0x79, 0x56, 0x52, 0x38, 0x71, 0x50, ++ 0x41, 0x73, 0x35, 0x6D, 0x34, 0x48, 0x0A, 0x65, 0x57, 0x39, 0x71, 0x34, 0x65, 0x62, 0x71, 0x6B, 0x59, 0x4A, 0x70, 0x43, 0x68, 0x33, 0x44, 0x66, 0x6C, 0x6D, 0x69, 0x6E, 0x6D, 0x74, 0x47, 0x46, 0x5A, 0x68, 0x62, 0x30, 0x36, 0x39, 0x47, 0x48, ++ 0x57, 0x4C, 0x49, 0x7A, 0x6F, 0x42, 0x53, 0x53, 0x52, 0x45, 0x2F, 0x79, 0x51, 0x51, 0x53, 0x77, 0x78, 0x4E, 0x38, 0x50, 0x7A, 0x75, 0x4B, 0x6C, 0x74, 0x73, 0x38, 0x6F, 0x42, 0x34, 0x4B, 0x74, 0x49, 0x74, 0x55, 0x73, 0x69, 0x52, 0x6E, 0x44, ++ 0x65, 0x2B, 0x43, 0x0A, 0x79, 0x37, 0x34, 0x38, 0x66, 0x64, 0x48, 0x69, 0x66, 0x36, 0x34, 0x57, 0x31, 0x6C, 0x5A, 0x59, 0x75, 0x64, 0x6F, 0x67, 0x73, 0x59, 0x4D, 0x56, 0x6F, 0x65, 0x2B, 0x4B, 0x54, 0x54, 0x4A, 0x76, 0x51, 0x53, 0x38, 0x54, ++ 0x55, 0x6F, 0x4B, 0x55, 0x31, 0x78, 0x72, 0x42, 0x65, 0x4B, 0x4A, 0x52, 0x33, 0x53, 0x74, 0x77, 0x62, 0x62, 0x63, 0x61, 0x2B, 0x66, 0x65, 0x77, 0x34, 0x47, 0x65, 0x58, 0x56, 0x74, 0x74, 0x38, 0x59, 0x56, 0x4D, 0x4A, 0x41, 0x79, 0x67, 0x43, ++ 0x0A, 0x51, 0x4D, 0x65, 0x7A, 0x32, 0x50, 0x32, 0x63, 0x63, 0x47, 0x72, 0x47, 0x4B, 0x4D, 0x4F, 0x46, 0x36, 0x65, 0x4C, 0x74, 0x47, 0x70, 0x4F, 0x67, 0x33, 0x6B, 0x75, 0x59, 0x6F, 0x6F, 0x51, 0x2B, 0x42, 0x58, 0x63, 0x42, 0x6C, 0x6A, 0x33, ++ 0x37, 0x74, 0x43, 0x41, 0x50, 0x6E, 0x48, 0x49, 0x43, 0x65, 0x68, 0x49, 0x76, 0x31, 0x61, 0x4F, 0x36, 0x55, 0x58, 0x69, 0x76, 0x4B, 0x69, 0x74, 0x45, 0x5A, 0x55, 0x36, 0x31, 0x2F, 0x51, 0x72, 0x6F, 0x77, 0x63, 0x31, 0x35, 0x0A, 0x68, 0x32, ++ 0x45, 0x72, 0x33, 0x6F, 0x42, 0x58, 0x52, 0x62, 0x39, 0x6E, 0x38, 0x5A, 0x75, 0x52, 0x58, 0x71, 0x57, 0x6B, 0x37, 0x46, 0x6C, 0x49, 0x45, 0x41, 0x30, 0x34, 0x78, 0x37, 0x44, 0x36, 0x77, 0x30, 0x52, 0x74, 0x42, 0x50, 0x56, 0x34, 0x55, 0x42, ++ 0x79, 0x53, 0x6C, 0x6C, 0x76, 0x61, 0x39, 0x62, 0x67, 0x75, 0x75, 0x6C, 0x76, 0x50, 0x35, 0x66, 0x42, 0x71, 0x6E, 0x55, 0x73, 0x76, 0x57, 0x48, 0x4D, 0x74, 0x54, 0x79, 0x33, 0x45, 0x48, 0x44, 0x37, 0x30, 0x0A, 0x73, 0x7A, 0x2B, 0x72, 0x46, ++ 0x51, 0x34, 0x37, 0x47, 0x55, 0x47, 0x4B, 0x70, 0x4D, 0x46, 0x58, 0x45, 0x6D, 0x5A, 0x78, 0x54, 0x50, 0x70, 0x54, 0x34, 0x31, 0x66, 0x72, 0x59, 0x70, 0x55, 0x4A, 0x6E, 0x6C, 0x54, 0x64, 0x30, 0x63, 0x49, 0x38, 0x56, 0x7A, 0x79, 0x39, 0x4F, ++ 0x4B, 0x32, 0x59, 0x5A, 0x4C, 0x65, 0x34, 0x41, 0x35, 0x70, 0x54, 0x56, 0x6D, 0x42, 0x64, 0x73, 0x39, 0x68, 0x43, 0x47, 0x31, 0x78, 0x4C, 0x45, 0x6F, 0x6F, 0x63, 0x36, 0x2B, 0x74, 0x39, 0x0A, 0x78, 0x6E, 0x70, 0x70, 0x78, 0x79, 0x64, 0x2F, ++ 0x70, 0x50, 0x69, 0x4C, 0x38, 0x75, 0x53, 0x55, 0x5A, 0x6F, 0x64, 0x4C, 0x36, 0x5A, 0x51, 0x48, 0x43, 0x52, 0x4A, 0x35, 0x69, 0x72, 0x4C, 0x72, 0x64, 0x41, 0x54, 0x63, 0x7A, 0x76, 0x52, 0x45, 0x57, 0x65, 0x41, 0x57, 0x79, 0x73, 0x55, 0x73, ++ 0x57, 0x4E, 0x63, 0x38, 0x65, 0x38, 0x39, 0x69, 0x68, 0x6D, 0x70, 0x51, 0x66, 0x54, 0x55, 0x32, 0x5A, 0x71, 0x66, 0x37, 0x4E, 0x2B, 0x63, 0x6F, 0x78, 0x39, 0x6A, 0x51, 0x0A, 0x72, 0x61, 0x56, 0x70, 0x6C, 0x49, 0x2F, 0x6F, 0x77, 0x64, 0x38, ++ 0x6B, 0x2B, 0x42, 0x73, 0x48, 0x4D, 0x59, 0x65, 0x42, 0x32, 0x46, 0x33, 0x32, 0x36, 0x43, 0x6A, 0x59, 0x53, 0x6C, 0x4B, 0x41, 0x72, 0x42, 0x50, 0x75, 0x55, 0x42, 0x51, 0x65, 0x6D, 0x4D, 0x63, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, ++ 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x42, 0x52, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, ++ 0x31, 0x20, 0x32, 0x30, 0x32, 0x30, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, ++ 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x43, 0x32, 0x7A, 0x43, 0x43, 0x41, 0x6D, 0x43, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, ++ 0x51, 0x66, 0x4D, 0x6D, 0x50, 0x4B, 0x34, 0x54, 0x58, 0x33, 0x2B, 0x6F, 0x50, 0x79, 0x57, 0x57, 0x61, 0x30, 0x30, 0x74, 0x4E, 0x6C, 0x6A, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x7A, 0x42, ++ 0x49, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x45, 0x0A, 0x52, 0x54, 0x45, 0x56, 0x4D, 0x42, 0x4D, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x4D, 0x52, 0x43, 0x31, 0x55, 0x63, 0x6E, ++ 0x56, 0x7A, 0x64, 0x43, 0x42, 0x48, 0x62, 0x57, 0x4A, 0x49, 0x4D, 0x53, 0x49, 0x77, 0x49, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x6C, 0x45, 0x4C, 0x56, 0x52, 0x53, 0x56, 0x56, 0x4E, 0x55, 0x49, 0x45, 0x4A, 0x53, 0x49, 0x46, ++ 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x67, 0x4D, 0x53, 0x41, 0x79, 0x0A, 0x4D, 0x44, 0x49, 0x77, 0x4D, 0x42, 0x34, 0x58, 0x44, 0x54, 0x49, 0x77, 0x4D, 0x44, 0x49, 0x78, 0x4D, 0x54, 0x41, 0x35, 0x4E, 0x44, 0x55, 0x77, 0x4D, ++ 0x46, 0x6F, 0x58, 0x44, 0x54, 0x4D, 0x31, 0x4D, 0x44, 0x49, 0x78, 0x4D, 0x54, 0x41, 0x35, 0x4E, 0x44, 0x51, 0x31, 0x4F, 0x56, 0x6F, 0x77, 0x53, 0x44, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x52, ++ 0x45, 0x55, 0x78, 0x46, 0x54, 0x41, 0x54, 0x42, 0x67, 0x4E, 0x56, 0x0A, 0x42, 0x41, 0x6F, 0x54, 0x44, 0x45, 0x51, 0x74, 0x56, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x51, 0x67, 0x52, 0x32, 0x31, 0x69, 0x53, 0x44, 0x45, 0x69, 0x4D, 0x43, 0x41, 0x47, ++ 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x5A, 0x52, 0x43, 0x31, 0x55, 0x55, 0x6C, 0x56, 0x54, 0x56, 0x43, 0x42, 0x43, 0x55, 0x69, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x42, 0x49, 0x44, 0x45, 0x67, 0x4D, 0x6A, 0x41, 0x79, ++ 0x4D, 0x44, 0x42, 0x32, 0x4D, 0x42, 0x41, 0x47, 0x0A, 0x42, 0x79, 0x71, 0x47, 0x53, 0x4D, 0x34, 0x39, 0x41, 0x67, 0x45, 0x47, 0x42, 0x53, 0x75, 0x42, 0x42, 0x41, 0x41, 0x69, 0x41, 0x32, 0x49, 0x41, 0x42, 0x4D, 0x62, 0x4C, 0x78, 0x79, 0x6A, ++ 0x52, 0x2B, 0x34, 0x54, 0x31, 0x6D, 0x75, 0x39, 0x43, 0x46, 0x43, 0x44, 0x68, 0x51, 0x32, 0x74, 0x75, 0x64, 0x61, 0x33, 0x38, 0x4B, 0x77, 0x4F, 0x45, 0x31, 0x48, 0x61, 0x54, 0x4A, 0x64, 0x64, 0x5A, 0x4F, 0x30, 0x46, 0x6C, 0x61, 0x78, 0x37, ++ 0x6D, 0x4E, 0x43, 0x71, 0x37, 0x0A, 0x64, 0x50, 0x59, 0x53, 0x7A, 0x75, 0x68, 0x74, 0x35, 0x36, 0x76, 0x6B, 0x50, 0x45, 0x34, 0x2F, 0x52, 0x41, 0x69, 0x4C, 0x7A, 0x52, 0x5A, 0x78, 0x79, 0x37, 0x2B, 0x53, 0x6D, 0x66, 0x53, 0x6B, 0x31, 0x7A, ++ 0x78, 0x51, 0x56, 0x46, 0x4B, 0x51, 0x68, 0x59, 0x4E, 0x34, 0x6C, 0x47, 0x64, 0x6E, 0x6F, 0x78, 0x77, 0x4A, 0x47, 0x54, 0x31, 0x31, 0x4E, 0x49, 0x58, 0x65, 0x37, 0x57, 0x42, 0x39, 0x78, 0x77, 0x79, 0x30, 0x51, 0x56, 0x4B, 0x35, 0x62, 0x75, ++ 0x58, 0x75, 0x0A, 0x51, 0x71, 0x4F, 0x43, 0x41, 0x51, 0x30, 0x77, 0x67, 0x67, 0x45, 0x4A, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x48, ++ 0x51, 0x59, 0x44, 0x56, 0x52, 0x30, 0x4F, 0x42, 0x42, 0x59, 0x45, 0x46, 0x48, 0x4F, 0x52, 0x45, 0x4B, 0x76, 0x2F, 0x56, 0x62, 0x4E, 0x61, 0x66, 0x41, 0x6B, 0x6C, 0x31, 0x62, 0x4B, 0x36, 0x43, 0x4B, 0x42, 0x72, 0x71, 0x78, 0x39, 0x74, 0x0A, ++ 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x42, 0x42, 0x6A, 0x43, 0x42, 0x78, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x66, 0x42, 0x49, 0x47, 0x2B, 0x4D, 0x49, 0x47, 0x37, ++ 0x4D, 0x44, 0x36, 0x67, 0x50, 0x4B, 0x41, 0x36, 0x68, 0x6A, 0x68, 0x6F, 0x64, 0x48, 0x52, 0x77, 0x4F, 0x69, 0x38, 0x76, 0x59, 0x33, 0x4A, 0x73, 0x4C, 0x6D, 0x51, 0x74, 0x64, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x51, 0x75, 0x0A, 0x62, 0x6D, 0x56, ++ 0x30, 0x4C, 0x32, 0x4E, 0x79, 0x62, 0x43, 0x39, 0x6B, 0x4C, 0x58, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x58, 0x32, 0x4A, 0x79, 0x58, 0x33, 0x4A, 0x76, 0x62, 0x33, 0x52, 0x66, 0x59, 0x32, 0x46, 0x66, 0x4D, 0x56, 0x38, 0x79, 0x4D, 0x44, 0x49, ++ 0x77, 0x4C, 0x6D, 0x4E, 0x79, 0x62, 0x44, 0x42, 0x35, 0x6F, 0x48, 0x65, 0x67, 0x64, 0x59, 0x5A, 0x7A, 0x62, 0x47, 0x52, 0x68, 0x63, 0x44, 0x6F, 0x76, 0x4C, 0x32, 0x52, 0x70, 0x63, 0x6D, 0x56, 0x6A, 0x0A, 0x64, 0x47, 0x39, 0x79, 0x65, 0x53, ++ 0x35, 0x6B, 0x4C, 0x58, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x4C, 0x6D, 0x35, 0x6C, 0x64, 0x43, 0x39, 0x44, 0x54, 0x6A, 0x31, 0x45, 0x4C, 0x56, 0x52, 0x53, 0x56, 0x56, 0x4E, 0x55, 0x4A, 0x54, 0x49, 0x77, 0x51, 0x6C, 0x49, 0x6C, 0x4D, 0x6A, ++ 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x4A, 0x54, 0x49, 0x77, 0x51, 0x30, 0x45, 0x6C, 0x4D, 0x6A, 0x41, 0x78, 0x4A, 0x54, 0x49, 0x77, 0x4D, 0x6A, 0x41, 0x79, 0x4D, 0x43, 0x78, 0x50, 0x0A, 0x50, 0x55, 0x51, 0x74, 0x56, 0x48, 0x4A, 0x31, 0x63, ++ 0x33, 0x51, 0x6C, 0x4D, 0x6A, 0x42, 0x48, 0x62, 0x57, 0x4A, 0x49, 0x4C, 0x45, 0x4D, 0x39, 0x52, 0x45, 0x55, 0x2F, 0x59, 0x32, 0x56, 0x79, 0x64, 0x47, 0x6C, 0x6D, 0x61, 0x57, 0x4E, 0x68, 0x64, 0x47, 0x56, 0x79, 0x5A, 0x58, 0x5A, 0x76, 0x59, ++ 0x32, 0x46, 0x30, 0x61, 0x57, 0x39, 0x75, 0x62, 0x47, 0x6C, 0x7A, 0x64, 0x44, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x0A, 0x41, 0x77, 0x4E, 0x70, 0x41, 0x44, 0x42, 0x6D, 0x41, 0x6A, 0x45, 0x41, ++ 0x6C, 0x4A, 0x41, 0x74, 0x45, 0x2F, 0x72, 0x68, 0x59, 0x2F, 0x68, 0x68, 0x59, 0x2B, 0x69, 0x74, 0x68, 0x58, 0x68, 0x55, 0x6B, 0x5A, 0x79, 0x34, 0x6B, 0x7A, 0x67, 0x2B, 0x47, 0x6B, 0x48, 0x61, 0x51, 0x42, 0x5A, 0x54, 0x51, 0x67, 0x6A, 0x4B, ++ 0x4C, 0x34, 0x37, 0x78, 0x50, 0x6F, 0x46, 0x57, 0x77, 0x4B, 0x72, 0x59, 0x37, 0x52, 0x6A, 0x45, 0x73, 0x4B, 0x37, 0x30, 0x50, 0x76, 0x6F, 0x6D, 0x0A, 0x41, 0x6A, 0x45, 0x41, 0x38, 0x79, 0x6A, 0x69, 0x78, 0x74, 0x73, 0x72, 0x6D, 0x66, 0x75, ++ 0x33, 0x55, 0x62, 0x67, 0x6B, 0x6F, 0x36, 0x53, 0x55, 0x65, 0x68, 0x6F, 0x2F, 0x35, 0x6A, 0x62, 0x69, 0x41, 0x31, 0x63, 0x7A, 0x69, 0x6A, 0x44, 0x4C, 0x67, 0x73, 0x66, 0x57, 0x46, 0x42, 0x48, 0x56, 0x64, 0x57, 0x4E, 0x62, 0x46, 0x4A, 0x57, ++ 0x63, 0x48, 0x77, 0x48, 0x50, 0x32, 0x4E, 0x56, 0x79, 0x70, 0x77, 0x38, 0x37, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, ++ 0x0A, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x45, 0x56, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x20, 0x32, 0x30, 0x32, 0x30, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, ++ 0x0A, 0x4D, 0x49, 0x49, 0x43, 0x32, 0x7A, 0x43, 0x43, 0x41, 0x6D, 0x43, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x58, 0x77, 0x4A, 0x42, 0x31, 0x33, 0x71, 0x48, 0x66, 0x45, 0x77, 0x44, 0x6F, 0x36, 0x79, 0x57, 0x6A, 0x66, 0x76, ++ 0x2F, 0x30, 0x44, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x7A, 0x42, 0x49, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x45, 0x0A, 0x52, 0x54, ++ 0x45, 0x56, 0x4D, 0x42, 0x4D, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x4D, 0x52, 0x43, 0x31, 0x55, 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x43, 0x42, 0x48, 0x62, 0x57, 0x4A, 0x49, 0x4D, 0x53, 0x49, 0x77, 0x49, 0x41, 0x59, 0x44, 0x56, 0x51, ++ 0x51, 0x44, 0x45, 0x78, 0x6C, 0x45, 0x4C, 0x56, 0x52, 0x53, 0x56, 0x56, 0x4E, 0x55, 0x49, 0x45, 0x56, 0x57, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x67, 0x4D, 0x53, 0x41, 0x79, 0x0A, 0x4D, 0x44, 0x49, 0x77, 0x4D, ++ 0x42, 0x34, 0x58, 0x44, 0x54, 0x49, 0x77, 0x4D, 0x44, 0x49, 0x78, 0x4D, 0x54, 0x45, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x46, 0x6F, 0x58, 0x44, 0x54, 0x4D, 0x31, 0x4D, 0x44, 0x49, 0x78, 0x4D, 0x54, 0x41, 0x35, 0x4E, 0x54, 0x6B, 0x31, 0x4F, ++ 0x56, 0x6F, 0x77, 0x53, 0x44, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x52, 0x45, 0x55, 0x78, 0x46, 0x54, 0x41, 0x54, 0x42, 0x67, 0x4E, 0x56, 0x0A, 0x42, 0x41, 0x6F, 0x54, 0x44, 0x45, 0x51, 0x74, ++ 0x56, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x51, 0x67, 0x52, 0x32, 0x31, 0x69, 0x53, 0x44, 0x45, 0x69, 0x4D, 0x43, 0x41, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x5A, 0x52, 0x43, 0x31, 0x55, 0x55, 0x6C, 0x56, 0x54, 0x56, 0x43, 0x42, 0x46, ++ 0x56, 0x69, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x42, 0x49, 0x44, 0x45, 0x67, 0x4D, 0x6A, 0x41, 0x79, 0x4D, 0x44, 0x42, 0x32, 0x4D, 0x42, 0x41, 0x47, 0x0A, 0x42, 0x79, 0x71, 0x47, 0x53, 0x4D, 0x34, 0x39, 0x41, 0x67, 0x45, ++ 0x47, 0x42, 0x53, 0x75, 0x42, 0x42, 0x41, 0x41, 0x69, 0x41, 0x32, 0x49, 0x41, 0x42, 0x50, 0x45, 0x4C, 0x33, 0x59, 0x5A, 0x44, 0x49, 0x42, 0x6E, 0x66, 0x6C, 0x34, 0x58, 0x6F, 0x49, 0x6B, 0x71, 0x62, 0x7A, 0x35, 0x32, 0x59, 0x76, 0x37, 0x51, ++ 0x46, 0x4A, 0x73, 0x6E, 0x4C, 0x34, 0x36, 0x62, 0x53, 0x6A, 0x38, 0x57, 0x65, 0x65, 0x48, 0x73, 0x78, 0x69, 0x61, 0x6D, 0x4A, 0x72, 0x53, 0x63, 0x38, 0x0A, 0x5A, 0x52, 0x43, 0x43, 0x2F, 0x4E, 0x2F, 0x44, 0x6E, 0x55, 0x37, 0x77, 0x4D, 0x79, ++ 0x50, 0x45, 0x30, 0x6A, 0x4C, 0x31, 0x48, 0x4C, 0x44, 0x66, 0x4D, 0x78, 0x64, 0x64, 0x78, 0x66, 0x43, 0x78, 0x69, 0x76, 0x6E, 0x76, 0x75, 0x62, 0x63, 0x55, 0x79, 0x69, 0x6C, 0x4B, 0x77, 0x67, 0x2B, 0x70, 0x66, 0x33, 0x56, 0x6C, 0x53, 0x53, ++ 0x6F, 0x77, 0x5A, 0x2F, 0x52, 0x6B, 0x39, 0x39, 0x59, 0x61, 0x64, 0x39, 0x72, 0x44, 0x77, 0x70, 0x64, 0x68, 0x51, 0x6E, 0x74, 0x4A, 0x0A, 0x72, 0x61, 0x4F, 0x43, 0x41, 0x51, 0x30, 0x77, 0x67, 0x67, 0x45, 0x4A, 0x4D, 0x41, 0x38, 0x47, 0x41, ++ 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x48, 0x51, 0x59, 0x44, 0x56, 0x52, 0x30, 0x4F, 0x42, 0x42, 0x59, 0x45, 0x46, 0x48, 0x38, 0x51, 0x41, 0x52, 0x59, 0x33, 0x4F, ++ 0x71, 0x51, 0x6F, 0x35, 0x46, 0x44, 0x34, 0x70, 0x50, 0x66, 0x73, 0x61, 0x7A, 0x4B, 0x32, 0x2F, 0x75, 0x6D, 0x4C, 0x0A, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x42, ++ 0x42, 0x6A, 0x43, 0x42, 0x78, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x66, 0x42, 0x49, 0x47, 0x2B, 0x4D, 0x49, 0x47, 0x37, 0x4D, 0x44, 0x36, 0x67, 0x50, 0x4B, 0x41, 0x36, 0x68, 0x6A, 0x68, 0x6F, 0x64, 0x48, 0x52, 0x77, 0x4F, 0x69, 0x38, 0x76, ++ 0x59, 0x33, 0x4A, 0x73, 0x4C, 0x6D, 0x51, 0x74, 0x64, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x51, 0x75, 0x0A, 0x62, 0x6D, 0x56, 0x30, 0x4C, 0x32, 0x4E, 0x79, 0x62, 0x43, 0x39, 0x6B, 0x4C, 0x58, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x58, 0x32, 0x56, ++ 0x32, 0x58, 0x33, 0x4A, 0x76, 0x62, 0x33, 0x52, 0x66, 0x59, 0x32, 0x46, 0x66, 0x4D, 0x56, 0x38, 0x79, 0x4D, 0x44, 0x49, 0x77, 0x4C, 0x6D, 0x4E, 0x79, 0x62, 0x44, 0x42, 0x35, 0x6F, 0x48, 0x65, 0x67, 0x64, 0x59, 0x5A, 0x7A, 0x62, 0x47, 0x52, ++ 0x68, 0x63, 0x44, 0x6F, 0x76, 0x4C, 0x32, 0x52, 0x70, 0x63, 0x6D, 0x56, 0x6A, 0x0A, 0x64, 0x47, 0x39, 0x79, 0x65, 0x53, 0x35, 0x6B, 0x4C, 0x58, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x4C, 0x6D, 0x35, 0x6C, 0x64, 0x43, 0x39, 0x44, 0x54, 0x6A, ++ 0x31, 0x45, 0x4C, 0x56, 0x52, 0x53, 0x56, 0x56, 0x4E, 0x55, 0x4A, 0x54, 0x49, 0x77, 0x52, 0x56, 0x59, 0x6C, 0x4D, 0x6A, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x4A, 0x54, 0x49, 0x77, 0x51, 0x30, 0x45, 0x6C, 0x4D, 0x6A, 0x41, 0x78, 0x4A, 0x54, ++ 0x49, 0x77, 0x4D, 0x6A, 0x41, 0x79, 0x4D, 0x43, 0x78, 0x50, 0x0A, 0x50, 0x55, 0x51, 0x74, 0x56, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x51, 0x6C, 0x4D, 0x6A, 0x42, 0x48, 0x62, 0x57, 0x4A, 0x49, 0x4C, 0x45, 0x4D, 0x39, 0x52, 0x45, 0x55, 0x2F, 0x59, ++ 0x32, 0x56, 0x79, 0x64, 0x47, 0x6C, 0x6D, 0x61, 0x57, 0x4E, 0x68, 0x64, 0x47, 0x56, 0x79, 0x5A, 0x58, 0x5A, 0x76, 0x59, 0x32, 0x46, 0x30, 0x61, 0x57, 0x39, 0x75, 0x62, 0x47, 0x6C, 0x7A, 0x64, 0x44, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, ++ 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x0A, 0x41, 0x77, 0x4E, 0x70, 0x41, 0x44, 0x42, 0x6D, 0x41, 0x6A, 0x45, 0x41, 0x79, 0x6A, 0x7A, 0x47, 0x4B, 0x6E, 0x58, 0x43, 0x58, 0x6E, 0x56, 0x69, 0x4F, 0x54, 0x59, 0x41, 0x59, 0x46, 0x71, 0x4C, ++ 0x77, 0x5A, 0x4F, 0x5A, 0x7A, 0x4E, 0x6E, 0x62, 0x51, 0x54, 0x73, 0x37, 0x68, 0x35, 0x6B, 0x58, 0x4F, 0x39, 0x58, 0x4D, 0x54, 0x38, 0x6F, 0x69, 0x39, 0x36, 0x43, 0x41, 0x79, 0x2F, 0x6D, 0x30, 0x73, 0x52, 0x74, 0x57, 0x39, 0x58, 0x4C, 0x53, ++ 0x2F, 0x42, 0x6E, 0x52, 0x0A, 0x41, 0x6A, 0x45, 0x41, 0x6B, 0x66, 0x63, 0x77, 0x6B, 0x7A, 0x38, 0x51, 0x52, 0x69, 0x74, 0x78, 0x70, 0x4E, 0x41, 0x37, 0x52, 0x4A, 0x76, 0x41, 0x4B, 0x51, 0x49, 0x46, 0x73, 0x6B, 0x46, 0x33, 0x55, 0x66, 0x4E, ++ 0x35, 0x57, 0x70, 0x36, 0x4F, 0x46, 0x4B, 0x42, 0x4F, 0x51, 0x74, 0x4A, 0x62, 0x67, 0x66, 0x4D, 0x30, 0x61, 0x67, 0x50, 0x6E, 0x49, 0x6A, 0x68, 0x51, 0x57, 0x2B, 0x30, 0x5A, 0x54, 0x30, 0x4D, 0x57, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, ++ 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, 0x43, 0x20, 0x50, 0x33, ++ 0x38, 0x34, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x35, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x43, 0x47, 0x54, 0x43, 0x43, 0x41, 0x5A, 0x2B, ++ 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x43, 0x65, 0x43, 0x54, 0x5A, 0x61, 0x7A, 0x33, 0x32, 0x63, 0x69, 0x35, 0x50, 0x68, 0x77, 0x4C, 0x42, 0x43, 0x6F, 0x75, 0x38, 0x7A, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, ++ 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x7A, 0x42, 0x4F, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x56, 0x0A, 0x55, 0x7A, 0x45, 0x58, 0x4D, 0x42, 0x55, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, ++ 0x4D, 0x4F, 0x52, 0x47, 0x6C, 0x6E, 0x61, 0x55, 0x4E, 0x6C, 0x63, 0x6E, 0x51, 0x73, 0x49, 0x45, 0x6C, 0x75, 0x59, 0x79, 0x34, 0x78, 0x4A, 0x6A, 0x41, 0x6B, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x48, 0x55, 0x52, 0x70, 0x5A, 0x32, ++ 0x6C, 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x49, 0x46, 0x52, 0x4D, 0x55, 0x79, 0x42, 0x46, 0x51, 0x30, 0x4D, 0x67, 0x55, 0x44, 0x4D, 0x34, 0x0A, 0x4E, 0x43, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x63, 0x31, 0x4D, 0x42, 0x34, 0x58, 0x44, ++ 0x54, 0x49, 0x78, 0x4D, 0x44, 0x45, 0x78, 0x4E, 0x54, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x46, 0x6F, 0x58, 0x44, 0x54, 0x51, 0x32, 0x4D, 0x44, 0x45, 0x78, 0x4E, 0x44, 0x49, 0x7A, 0x4E, 0x54, 0x6B, 0x31, 0x4F, 0x56, 0x6F, 0x77, 0x54, ++ 0x6A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x56, 0x56, 0x4D, 0x78, 0x0A, 0x46, 0x7A, 0x41, 0x56, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x44, 0x6B, 0x52, 0x70, 0x5A, 0x32, 0x6C, 0x44, ++ 0x5A, 0x58, 0x4A, 0x30, 0x4C, 0x43, 0x42, 0x4A, 0x62, 0x6D, 0x4D, 0x75, 0x4D, 0x53, 0x59, 0x77, 0x4A, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x31, 0x45, 0x61, 0x57, 0x64, 0x70, 0x51, 0x32, 0x56, 0x79, 0x64, 0x43, 0x42, 0x55, ++ 0x54, 0x46, 0x4D, 0x67, 0x52, 0x55, 0x4E, 0x44, 0x49, 0x46, 0x41, 0x7A, 0x4F, 0x44, 0x51, 0x67, 0x0A, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x48, 0x4E, 0x54, 0x42, 0x32, 0x4D, 0x42, 0x41, 0x47, 0x42, 0x79, 0x71, 0x47, 0x53, 0x4D, 0x34, ++ 0x39, 0x41, 0x67, 0x45, 0x47, 0x42, 0x53, 0x75, 0x42, 0x42, 0x41, 0x41, 0x69, 0x41, 0x32, 0x49, 0x41, 0x42, 0x4D, 0x46, 0x45, 0x6F, 0x63, 0x38, 0x52, 0x6C, 0x31, 0x43, 0x61, 0x33, 0x69, 0x4F, 0x43, 0x4E, 0x51, 0x66, 0x4E, 0x30, 0x4D, 0x73, ++ 0x59, 0x6E, 0x64, 0x4C, 0x78, 0x66, 0x33, 0x63, 0x31, 0x54, 0x7A, 0x76, 0x64, 0x0A, 0x6C, 0x48, 0x4A, 0x53, 0x37, 0x63, 0x49, 0x37, 0x2B, 0x4F, 0x7A, 0x36, 0x65, 0x32, 0x74, 0x59, 0x49, 0x4F, 0x79, 0x5A, 0x72, 0x73, 0x6E, 0x38, 0x61, 0x4C, ++ 0x4E, 0x31, 0x75, 0x64, 0x73, 0x4A, 0x37, 0x4D, 0x67, 0x54, 0x39, 0x55, 0x37, 0x47, 0x43, 0x68, 0x31, 0x6D, 0x4D, 0x45, 0x79, 0x37, 0x48, 0x30, 0x63, 0x4B, 0x50, 0x47, 0x45, 0x51, 0x51, 0x69, 0x6C, 0x38, 0x70, 0x51, 0x67, 0x4F, 0x34, 0x43, ++ 0x4C, 0x70, 0x30, 0x7A, 0x56, 0x6F, 0x7A, 0x70, 0x74, 0x6A, 0x0A, 0x6E, 0x34, 0x53, 0x31, 0x6D, 0x55, 0x31, 0x59, 0x6F, 0x49, 0x37, 0x31, 0x56, 0x4F, 0x65, 0x56, 0x79, 0x61, 0x4E, 0x43, 0x4D, 0x45, 0x41, 0x77, 0x48, 0x51, 0x59, 0x44, 0x56, ++ 0x52, 0x30, 0x4F, 0x42, 0x42, 0x59, 0x45, 0x46, 0x4D, 0x46, 0x52, 0x52, 0x56, 0x42, 0x5A, 0x71, 0x7A, 0x37, 0x6E, 0x4C, 0x46, 0x72, 0x36, 0x49, 0x43, 0x49, 0x53, 0x42, 0x34, 0x43, 0x49, 0x66, 0x42, 0x46, 0x71, 0x4D, 0x41, 0x34, 0x47, 0x41, ++ 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x0A, 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x42, 0x68, 0x6A, 0x41, 0x50, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x52, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x54, 0x41, 0x44, 0x41, 0x51, 0x48, 0x2F, ++ 0x4D, 0x41, 0x6F, 0x47, 0x43, 0x43, 0x71, 0x47, 0x53, 0x4D, 0x34, 0x39, 0x42, 0x41, 0x4D, 0x44, 0x41, 0x32, 0x67, 0x41, 0x4D, 0x47, 0x55, 0x43, 0x4D, 0x51, 0x43, 0x4A, 0x61, 0x6F, 0x31, 0x48, 0x35, 0x2B, 0x7A, 0x38, 0x62, 0x6C, 0x55, 0x44, ++ 0x32, 0x57, 0x64, 0x73, 0x0A, 0x4A, 0x6B, 0x36, 0x44, 0x78, 0x76, 0x33, 0x4A, 0x2B, 0x79, 0x73, 0x54, 0x76, 0x4C, 0x64, 0x36, 0x6A, 0x4C, 0x52, 0x6C, 0x30, 0x6D, 0x6C, 0x70, 0x59, 0x78, 0x4E, 0x6A, 0x4F, 0x79, 0x5A, 0x51, 0x4C, 0x67, 0x47, ++ 0x68, 0x65, 0x51, 0x61, 0x52, 0x6E, 0x55, 0x69, 0x2F, 0x77, 0x72, 0x34, 0x43, 0x4D, 0x45, 0x66, 0x44, 0x46, 0x58, 0x75, 0x78, 0x6F, 0x4A, 0x47, 0x5A, 0x53, 0x5A, 0x4F, 0x6F, 0x50, 0x48, 0x7A, 0x6F, 0x52, 0x67, 0x61, 0x4C, 0x4C, 0x50, 0x49, ++ 0x78, 0x0A, 0x41, 0x4A, 0x53, 0x64, 0x59, 0x73, 0x69, 0x4A, 0x76, 0x52, 0x6D, 0x45, 0x46, 0x4F, 0x6D, 0x6C, 0x2B, 0x77, 0x47, 0x34, 0x44, 0x58, 0x5A, 0x44, 0x6A, 0x43, 0x35, 0x54, 0x79, 0x33, 0x7A, 0x66, 0x44, 0x42, 0x65, 0x57, 0x55, 0x41, ++ 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x54, ++ 0x4C, 0x53, 0x20, 0x52, 0x53, 0x41, 0x34, 0x30, 0x39, 0x36, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x35, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, ++ 0x5A, 0x6A, 0x43, 0x43, 0x41, 0x30, 0x36, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x43, 0x50, 0x6D, 0x30, 0x65, 0x4B, 0x6A, 0x36, 0x66, 0x74, 0x70, 0x71, 0x4D, 0x7A, 0x65, 0x4A, 0x33, 0x6E, 0x7A, 0x50, 0x69, 0x6A, 0x41, 0x4E, ++ 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x77, 0x46, 0x41, 0x44, 0x42, 0x4E, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x0A, 0x45, 0x77, 0x4A, 0x56, 0x55, 0x7A, 0x45, ++ 0x58, 0x4D, 0x42, 0x55, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x4F, 0x52, 0x47, 0x6C, 0x6E, 0x61, 0x55, 0x4E, 0x6C, 0x63, 0x6E, 0x51, 0x73, 0x49, 0x45, 0x6C, 0x75, 0x59, 0x79, 0x34, 0x78, 0x4A, 0x54, 0x41, 0x6A, 0x42, 0x67, 0x4E, ++ 0x56, 0x42, 0x41, 0x4D, 0x54, 0x48, 0x45, 0x52, 0x70, 0x5A, 0x32, 0x6C, 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x49, 0x46, 0x52, 0x4D, 0x55, 0x79, 0x42, 0x53, 0x55, 0x30, 0x45, 0x30, 0x0A, 0x4D, 0x44, 0x6B, 0x32, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, ++ 0x51, 0x67, 0x52, 0x7A, 0x55, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x6A, 0x45, 0x77, 0x4D, 0x54, 0x45, 0x31, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x57, 0x68, 0x63, 0x4E, 0x4E, 0x44, 0x59, 0x77, 0x4D, 0x54, 0x45, 0x30, 0x4D, 0x6A, ++ 0x4D, 0x31, 0x4F, 0x54, 0x55, 0x35, 0x57, 0x6A, 0x42, 0x4E, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x56, 0x0A, 0x55, 0x7A, 0x45, 0x58, 0x4D, 0x42, 0x55, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, ++ 0x68, 0x4D, 0x4F, 0x52, 0x47, 0x6C, 0x6E, 0x61, 0x55, 0x4E, 0x6C, 0x63, 0x6E, 0x51, 0x73, 0x49, 0x45, 0x6C, 0x75, 0x59, 0x79, 0x34, 0x78, 0x4A, 0x54, 0x41, 0x6A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x48, 0x45, 0x52, 0x70, 0x5A, ++ 0x32, 0x6C, 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x49, 0x46, 0x52, 0x4D, 0x55, 0x79, 0x42, 0x53, 0x55, 0x30, 0x45, 0x30, 0x4D, 0x44, 0x6B, 0x32, 0x0A, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x52, 0x7A, 0x55, 0x77, 0x67, 0x67, 0x49, 0x69, ++ 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x49, 0x4B, 0x41, 0x6F, 0x49, 0x43, 0x41, 0x51, 0x43, 0x7A, ++ 0x30, 0x50, 0x54, 0x4A, 0x65, 0x52, 0x47, 0x64, 0x2F, 0x66, 0x78, 0x6D, 0x67, 0x65, 0x66, 0x4D, 0x31, 0x65, 0x53, 0x38, 0x0A, 0x37, 0x49, 0x45, 0x2B, 0x61, 0x6A, 0x57, 0x4F, 0x4C, 0x72, 0x66, 0x6E, 0x33, 0x71, 0x2F, 0x35, 0x42, 0x30, 0x33, ++ 0x50, 0x4D, 0x4A, 0x33, 0x71, 0x43, 0x51, 0x75, 0x5A, 0x76, 0x57, 0x78, 0x58, 0x32, 0x68, 0x68, 0x4B, 0x75, 0x48, 0x69, 0x73, 0x4F, 0x6A, 0x6D, 0x6F, 0x70, 0x6B, 0x69, 0x73, 0x4C, 0x6E, 0x4C, 0x6C, 0x76, 0x65, 0x76, 0x78, 0x47, 0x73, 0x33, ++ 0x6E, 0x70, 0x41, 0x4F, 0x70, 0x50, 0x78, 0x47, 0x30, 0x32, 0x43, 0x2B, 0x4A, 0x46, 0x76, 0x75, 0x55, 0x0A, 0x41, 0x54, 0x32, 0x37, 0x4C, 0x2F, 0x67, 0x54, 0x42, 0x61, 0x46, 0x34, 0x48, 0x49, 0x34, 0x6F, 0x34, 0x45, 0x58, 0x67, 0x67, 0x2F, ++ 0x52, 0x5A, 0x47, 0x35, 0x57, 0x7A, 0x72, 0x6E, 0x34, 0x44, 0x52, 0x65, 0x57, 0x2B, 0x77, 0x6B, 0x4C, 0x2B, 0x37, 0x76, 0x49, 0x38, 0x74, 0x6F, 0x55, 0x54, 0x6D, 0x44, 0x4B, 0x64, 0x46, 0x71, 0x67, 0x70, 0x77, 0x67, 0x73, 0x63, 0x4F, 0x4E, ++ 0x79, 0x66, 0x4D, 0x58, 0x64, 0x63, 0x76, 0x79, 0x65, 0x6A, 0x2F, 0x43, 0x65, 0x73, 0x0A, 0x74, 0x79, 0x75, 0x39, 0x64, 0x4A, 0x73, 0x58, 0x4C, 0x66, 0x4B, 0x42, 0x32, 0x6C, 0x32, 0x77, 0x34, 0x53, 0x4D, 0x58, 0x50, 0x6F, 0x68, 0x4B, 0x45, ++ 0x69, 0x50, 0x51, 0x36, 0x73, 0x2B, 0x64, 0x33, 0x67, 0x4D, 0x58, 0x73, 0x55, 0x4A, 0x4B, 0x6F, 0x42, 0x5A, 0x4D, 0x70, 0x47, 0x32, 0x54, 0x36, 0x54, 0x38, 0x36, 0x37, 0x6A, 0x70, 0x38, 0x6E, 0x56, 0x69, 0x64, 0x39, 0x45, 0x36, 0x50, 0x2F, ++ 0x44, 0x73, 0x6A, 0x79, 0x47, 0x32, 0x34, 0x34, 0x67, 0x58, 0x61, 0x0A, 0x7A, 0x4F, 0x76, 0x73, 0x77, 0x7A, 0x48, 0x30, 0x31, 0x36, 0x63, 0x70, 0x56, 0x49, 0x44, 0x50, 0x52, 0x46, 0x74, 0x4D, 0x62, 0x7A, 0x43, 0x65, 0x38, 0x38, 0x7A, 0x64, ++ 0x48, 0x35, 0x52, 0x44, 0x6E, 0x55, 0x31, 0x2F, 0x63, 0x48, 0x41, 0x4E, 0x31, 0x44, 0x72, 0x52, 0x4E, 0x2F, 0x42, 0x73, 0x6E, 0x5A, 0x76, 0x41, 0x46, 0x4A, 0x4E, 0x59, 0x37, 0x38, 0x31, 0x42, 0x4F, 0x48, 0x57, 0x38, 0x45, 0x77, 0x4F, 0x56, ++ 0x66, 0x48, 0x2F, 0x6A, 0x58, 0x4F, 0x6E, 0x56, 0x0A, 0x44, 0x64, 0x58, 0x69, 0x66, 0x42, 0x42, 0x69, 0x71, 0x6D, 0x76, 0x77, 0x50, 0x58, 0x62, 0x7A, 0x50, 0x36, 0x50, 0x6F, 0x73, 0x4D, 0x48, 0x39, 0x37, 0x36, 0x70, 0x58, 0x54, 0x61, 0x79, ++ 0x47, 0x70, 0x78, 0x69, 0x30, 0x4B, 0x63, 0x45, 0x73, 0x44, 0x72, 0x39, 0x6B, 0x76, 0x69, 0x6D, 0x4D, 0x32, 0x41, 0x49, 0x74, 0x7A, 0x56, 0x77, 0x76, 0x38, 0x6E, 0x2F, 0x76, 0x46, 0x66, 0x51, 0x4D, 0x46, 0x61, 0x77, 0x4B, 0x73, 0x50, 0x48, ++ 0x54, 0x44, 0x55, 0x39, 0x71, 0x0A, 0x54, 0x58, 0x65, 0x58, 0x41, 0x61, 0x44, 0x78, 0x5A, 0x72, 0x65, 0x33, 0x7A, 0x75, 0x2F, 0x4F, 0x37, 0x4F, 0x79, 0x6C, 0x64, 0x63, 0x71, 0x73, 0x34, 0x2B, 0x46, 0x6A, 0x39, 0x37, 0x69, 0x68, 0x42, 0x4D, ++ 0x69, 0x38, 0x65, 0x7A, 0x39, 0x64, 0x4C, 0x52, 0x59, 0x69, 0x56, 0x75, 0x31, 0x49, 0x53, 0x66, 0x36, 0x6E, 0x4C, 0x33, 0x6B, 0x77, 0x4A, 0x5A, 0x75, 0x36, 0x61, 0x79, 0x30, 0x2F, 0x6E, 0x54, 0x76, 0x45, 0x46, 0x2B, 0x63, 0x64, 0x4C, 0x76, ++ 0x76, 0x79, 0x0A, 0x7A, 0x36, 0x62, 0x38, 0x34, 0x78, 0x51, 0x73, 0x6C, 0x70, 0x67, 0x68, 0x6A, 0x4C, 0x53, 0x52, 0x36, 0x52, 0x6C, 0x67, 0x67, 0x2F, 0x49, 0x77, 0x4B, 0x77, 0x5A, 0x7A, 0x55, 0x4E, 0x57, 0x59, 0x4F, 0x77, 0x62, 0x70, 0x78, ++ 0x34, 0x6F, 0x4D, 0x59, 0x49, 0x77, 0x6F, 0x2B, 0x46, 0x4B, 0x62, 0x62, 0x75, 0x48, 0x32, 0x54, 0x62, 0x73, 0x47, 0x4A, 0x4A, 0x76, 0x58, 0x4B, 0x79, 0x59, 0x2F, 0x2F, 0x53, 0x6F, 0x76, 0x63, 0x66, 0x58, 0x57, 0x4A, 0x4C, 0x35, 0x2F, 0x0A, ++ 0x4D, 0x5A, 0x34, 0x50, 0x62, 0x65, 0x69, 0x50, 0x54, 0x30, 0x32, 0x6A, 0x50, 0x2F, 0x38, 0x31, 0x36, 0x74, 0x39, 0x4A, 0x58, 0x6B, 0x47, 0x50, 0x68, 0x76, 0x6E, 0x78, 0x64, 0x33, 0x6C, 0x4C, 0x47, 0x37, 0x53, 0x6A, 0x58, 0x69, 0x2F, 0x37, ++ 0x52, 0x67, 0x4C, 0x51, 0x5A, 0x68, 0x4E, 0x65, 0x58, 0x6F, 0x56, 0x50, 0x7A, 0x74, 0x68, 0x77, 0x69, 0x48, 0x76, 0x4F, 0x41, 0x62, 0x57, 0x57, 0x6C, 0x39, 0x66, 0x4E, 0x66, 0x66, 0x32, 0x43, 0x2B, 0x4D, 0x49, 0x6B, 0x0A, 0x77, 0x63, 0x6F, ++ 0x42, 0x4F, 0x55, 0x2B, 0x4E, 0x6F, 0x73, 0x45, 0x55, 0x51, 0x42, 0x2B, 0x63, 0x5A, 0x74, 0x55, 0x4D, 0x43, 0x55, 0x62, 0x57, 0x38, 0x74, 0x44, 0x52, 0x53, 0x48, 0x5A, 0x57, 0x4F, 0x6B, 0x50, 0x4C, 0x74, 0x67, 0x6F, 0x52, 0x4F, 0x62, 0x71, ++ 0x4D, 0x45, 0x32, 0x77, 0x47, 0x74, 0x5A, 0x37, 0x50, 0x36, 0x77, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x6F, 0x30, 0x49, 0x77, 0x51, 0x44, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x0A, 0x46, 0x67, 0x51, 0x55, 0x55, 0x54, ++ 0x4D, 0x63, 0x37, 0x54, 0x5A, 0x41, 0x72, 0x78, 0x66, 0x54, 0x4A, 0x63, 0x31, 0x70, 0x61, 0x50, 0x4B, 0x76, 0x54, 0x69, 0x4D, 0x2B, 0x73, 0x30, 0x45, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, ++ 0x51, 0x44, 0x41, 0x67, 0x47, 0x47, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x0A, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, ++ 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4D, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x42, 0x41, 0x47, 0x43, 0x6D, 0x72, 0x31, 0x74, 0x66, 0x56, 0x39, 0x71, 0x4A, 0x32, 0x30, 0x74, 0x51, 0x71, 0x63, 0x51, 0x6A, 0x4E, 0x53, 0x48, 0x2F, 0x30, ++ 0x47, 0x45, 0x77, 0x68, 0x4A, 0x47, 0x33, 0x50, 0x78, 0x44, 0x50, 0x4A, 0x59, 0x37, 0x4A, 0x76, 0x30, 0x59, 0x30, 0x32, 0x63, 0x45, 0x68, 0x4A, 0x68, 0x78, 0x77, 0x0A, 0x47, 0x58, 0x49, 0x65, 0x6F, 0x38, 0x6D, 0x48, 0x2F, 0x71, 0x6C, 0x44, ++ 0x5A, 0x4A, 0x59, 0x36, 0x79, 0x46, 0x4D, 0x45, 0x43, 0x72, 0x5A, 0x42, 0x75, 0x38, 0x52, 0x48, 0x41, 0x4E, 0x6D, 0x66, 0x47, 0x42, 0x67, 0x37, 0x73, 0x67, 0x37, 0x7A, 0x4E, 0x4F, 0x6F, 0x6B, 0x39, 0x39, 0x32, 0x76, 0x49, 0x47, 0x43, 0x75, ++ 0x6B, 0x69, 0x68, 0x66, 0x4E, 0x75, 0x64, 0x64, 0x35, 0x4E, 0x37, 0x48, 0x50, 0x4E, 0x74, 0x51, 0x4F, 0x61, 0x32, 0x37, 0x50, 0x53, 0x68, 0x4E, 0x0A, 0x6C, 0x6E, 0x78, 0x32, 0x78, 0x6C, 0x76, 0x30, 0x77, 0x64, 0x73, 0x55, 0x70, 0x61, 0x73, ++ 0x5A, 0x59, 0x67, 0x63, 0x59, 0x51, 0x46, 0x2B, 0x58, 0x6B, 0x64, 0x79, 0x63, 0x78, 0x36, 0x75, 0x31, 0x55, 0x51, 0x33, 0x6D, 0x61, 0x56, 0x4E, 0x56, 0x7A, 0x44, 0x6C, 0x39, 0x32, 0x73, 0x55, 0x52, 0x56, 0x58, 0x4C, 0x46, 0x4F, 0x34, 0x75, ++ 0x4A, 0x2B, 0x44, 0x51, 0x74, 0x70, 0x42, 0x66, 0x6C, 0x46, 0x2B, 0x61, 0x5A, 0x66, 0x54, 0x43, 0x49, 0x49, 0x54, 0x66, 0x4E, 0x0A, 0x4D, 0x42, 0x63, 0x39, 0x75, 0x50, 0x4B, 0x38, 0x71, 0x48, 0x57, 0x67, 0x51, 0x39, 0x77, 0x2B, 0x69, 0x55, ++ 0x75, 0x51, 0x72, 0x6D, 0x30, 0x44, 0x34, 0x42, 0x79, 0x6A, 0x6F, 0x4A, 0x59, 0x4A, 0x75, 0x33, 0x32, 0x6A, 0x74, 0x79, 0x6F, 0x51, 0x52, 0x45, 0x74, 0x47, 0x42, 0x7A, 0x52, 0x6A, 0x37, 0x54, 0x47, 0x35, 0x42, 0x4F, 0x36, 0x6A, 0x6D, 0x35, ++ 0x71, 0x75, 0x35, 0x6A, 0x46, 0x34, 0x39, 0x4F, 0x6F, 0x6B, 0x59, 0x54, 0x75, 0x72, 0x57, 0x47, 0x54, 0x2F, 0x0A, 0x75, 0x34, 0x63, 0x6E, 0x59, 0x69, 0x57, 0x42, 0x33, 0x39, 0x79, 0x68, 0x4C, 0x2F, 0x62, 0x74, 0x70, 0x2F, 0x39, 0x36, 0x6A, ++ 0x31, 0x45, 0x75, 0x4D, 0x50, 0x69, 0x6B, 0x41, 0x64, 0x4B, 0x46, 0x4F, 0x56, 0x38, 0x42, 0x6D, 0x5A, 0x5A, 0x76, 0x57, 0x6C, 0x74, 0x77, 0x47, 0x55, 0x62, 0x2B, 0x68, 0x6D, 0x41, 0x2B, 0x72, 0x59, 0x41, 0x51, 0x43, 0x64, 0x30, 0x35, 0x4A, ++ 0x53, 0x39, 0x59, 0x66, 0x37, 0x76, 0x53, 0x64, 0x50, 0x44, 0x33, 0x52, 0x68, 0x39, 0x47, 0x0A, 0x4F, 0x55, 0x72, 0x59, 0x55, 0x39, 0x44, 0x7A, 0x4C, 0x6A, 0x74, 0x78, 0x70, 0x64, 0x52, 0x76, 0x2F, 0x50, 0x4E, 0x6E, 0x35, 0x41, 0x65, 0x50, ++ 0x33, 0x53, 0x59, 0x5A, 0x34, 0x59, 0x31, 0x62, 0x2B, 0x71, 0x4F, 0x54, 0x45, 0x5A, 0x76, 0x70, 0x79, 0x44, 0x72, 0x44, 0x56, 0x57, 0x69, 0x61, 0x6B, 0x75, 0x46, 0x53, 0x64, 0x6A, 0x6A, 0x6F, 0x34, 0x62, 0x71, 0x39, 0x2B, 0x30, 0x2F, 0x56, ++ 0x37, 0x37, 0x50, 0x6E, 0x53, 0x49, 0x4D, 0x78, 0x38, 0x49, 0x49, 0x68, 0x0A, 0x34, 0x37, 0x61, 0x2B, 0x70, 0x36, 0x74, 0x76, 0x37, 0x35, 0x2F, 0x66, 0x54, 0x4D, 0x38, 0x42, 0x75, 0x47, 0x4A, 0x71, 0x49, 0x7A, 0x33, 0x6E, 0x43, 0x55, 0x32, ++ 0x41, 0x47, 0x33, 0x73, 0x77, 0x70, 0x4D, 0x50, 0x64, 0x42, 0x33, 0x38, 0x30, 0x76, 0x71, 0x51, 0x6D, 0x73, 0x76, 0x5A, 0x42, 0x36, 0x41, 0x6B, 0x64, 0x34, 0x79, 0x43, 0x59, 0x71, 0x6A, 0x64, 0x50, 0x2F, 0x2F, 0x66, 0x78, 0x34, 0x69, 0x6C, ++ 0x77, 0x4D, 0x55, 0x63, 0x2F, 0x64, 0x4E, 0x41, 0x55, 0x0A, 0x46, 0x76, 0x6F, 0x68, 0x69, 0x67, 0x4C, 0x56, 0x69, 0x67, 0x6D, 0x55, 0x64, 0x79, 0x37, 0x79, 0x57, 0x53, 0x69, 0x4C, 0x66, 0x46, 0x43, 0x53, 0x43, 0x6D, 0x5A, 0x34, 0x4F, 0x49, ++ 0x4E, 0x31, 0x78, 0x4C, 0x56, 0x61, 0x71, 0x42, 0x48, 0x47, 0x35, 0x63, 0x47, 0x64, 0x5A, 0x6C, 0x58, 0x50, 0x55, 0x38, 0x53, 0x76, 0x31, 0x33, 0x57, 0x46, 0x71, 0x55, 0x49, 0x54, 0x56, 0x75, 0x77, 0x68, 0x64, 0x34, 0x47, 0x54, 0x57, 0x67, ++ 0x7A, 0x71, 0x6C, 0x74, 0x6C, 0x4A, 0x0A, 0x79, 0x71, 0x45, 0x49, 0x38, 0x70, 0x63, 0x37, 0x62, 0x5A, 0x73, 0x45, 0x47, 0x43, 0x52, 0x45, 0x6A, 0x6E, 0x77, 0x42, 0x38, 0x74, 0x77, 0x6C, 0x32, 0x46, 0x36, 0x47, 0x6D, 0x72, 0x45, 0x35, 0x32, ++ 0x2F, 0x57, 0x52, 0x4D, 0x6D, 0x72, 0x52, 0x70, 0x6E, 0x43, 0x4B, 0x6F, 0x76, 0x66, 0x65, 0x70, 0x45, 0x57, 0x46, 0x4A, 0x71, 0x67, 0x65, 0x6A, 0x46, 0x30, 0x70, 0x57, 0x38, 0x68, 0x4C, 0x32, 0x4A, 0x70, 0x71, 0x41, 0x31, 0x35, 0x77, 0x38, ++ 0x6F, 0x56, 0x50, 0x0A, 0x62, 0x45, 0x74, 0x6F, 0x4C, 0x38, 0x70, 0x55, 0x39, 0x6F, 0x7A, 0x61, 0x4D, 0x76, 0x37, 0x44, 0x61, 0x34, 0x4D, 0x2F, 0x4F, 0x4D, 0x5A, 0x2B, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, ++ 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x43, 0x65, 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x31, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, ++ 0x4D, 0x49, 0x49, 0x46, 0x52, 0x7A, 0x43, 0x43, 0x41, 0x79, 0x2B, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x52, 0x41, 0x49, 0x34, 0x50, 0x2B, 0x55, 0x75, 0x51, 0x63, 0x57, 0x68, 0x6C, 0x4D, 0x31, 0x54, 0x30, 0x31, 0x45, 0x51, 0x35, ++ 0x74, 0x2B, 0x41, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x42, 0x51, 0x41, 0x77, 0x50, 0x54, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x0A, 0x42, 0x68, 0x4D, ++ 0x43, 0x56, 0x56, 0x4D, 0x78, 0x45, 0x6A, 0x41, 0x51, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x43, 0x55, 0x4E, 0x6C, 0x63, 0x6E, 0x52, 0x68, 0x61, 0x57, 0x35, 0x73, 0x65, 0x54, 0x45, 0x61, 0x4D, 0x42, 0x67, 0x47, 0x41, 0x31, 0x55, ++ 0x45, 0x41, 0x78, 0x4D, 0x52, 0x51, 0x32, 0x56, 0x79, 0x64, 0x47, 0x46, 0x70, 0x62, 0x6D, 0x78, 0x35, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x55, 0x6A, 0x45, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x0A, 0x4D, 0x6A, 0x45, 0x77, 0x4E, 0x44, ++ 0x41, 0x78, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x57, 0x68, 0x63, 0x4E, 0x4E, 0x44, 0x59, 0x77, 0x4E, 0x44, 0x41, 0x78, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x57, 0x6A, 0x41, 0x39, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, ++ 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x56, 0x55, 0x7A, 0x45, 0x53, 0x4D, 0x42, 0x41, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x4A, 0x51, 0x32, 0x56, 0x79, 0x0A, 0x64, 0x47, 0x46, 0x70, 0x62, 0x6D, 0x78, 0x35, 0x4D, ++ 0x52, 0x6F, 0x77, 0x47, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x46, 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x59, 0x57, 0x6C, 0x75, 0x62, 0x48, 0x6B, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x53, 0x4D, 0x54, 0x43, 0x43, 0x41, ++ 0x69, 0x49, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x50, 0x0A, 0x41, 0x44, 0x43, 0x43, 0x41, 0x67, 0x6F, 0x43, 0x67, 0x67, 0x49, 0x42, ++ 0x41, 0x4E, 0x41, 0x32, 0x31, 0x42, 0x2F, 0x71, 0x33, 0x61, 0x76, 0x6B, 0x30, 0x62, 0x62, 0x6D, 0x2B, 0x79, 0x4C, 0x41, 0x33, 0x52, 0x4D, 0x4E, 0x61, 0x6E, 0x73, 0x69, 0x45, 0x78, 0x79, 0x58, 0x50, 0x47, 0x68, 0x6A, 0x5A, 0x6A, 0x4B, 0x63, ++ 0x41, 0x37, 0x57, 0x4E, 0x70, 0x49, 0x47, 0x44, 0x32, 0x6E, 0x67, 0x77, 0x45, 0x63, 0x2F, 0x63, 0x73, 0x69, 0x75, 0x2B, 0x6B, 0x72, 0x2B, 0x4F, 0x0A, 0x35, 0x4D, 0x51, 0x54, 0x76, 0x71, 0x52, 0x6F, 0x54, 0x4E, 0x6F, 0x43, 0x61, 0x42, 0x5A, ++ 0x30, 0x76, 0x72, 0x4C, 0x64, 0x42, 0x4F, 0x52, 0x72, 0x4B, 0x74, 0x30, 0x33, 0x48, 0x32, 0x41, 0x73, 0x32, 0x2F, 0x58, 0x33, 0x6F, 0x58, 0x79, 0x56, 0x74, 0x77, 0x78, 0x77, 0x68, 0x69, 0x37, 0x78, 0x4F, 0x75, 0x39, 0x53, 0x39, 0x38, 0x7A, ++ 0x54, 0x6D, 0x2F, 0x6D, 0x4C, 0x76, 0x67, 0x37, 0x66, 0x4D, 0x62, 0x65, 0x64, 0x61, 0x46, 0x79, 0x53, 0x70, 0x76, 0x58, 0x6C, 0x0A, 0x38, 0x77, 0x6F, 0x30, 0x74, 0x66, 0x39, 0x37, 0x6F, 0x75, 0x53, 0x48, 0x6F, 0x63, 0x61, 0x76, 0x46, 0x77, ++ 0x44, 0x76, 0x41, 0x35, 0x48, 0x74, 0x71, 0x52, 0x78, 0x4F, 0x63, 0x54, 0x33, 0x53, 0x69, 0x32, 0x79, 0x4A, 0x39, 0x48, 0x69, 0x47, 0x35, 0x6D, 0x70, 0x4A, 0x6F, 0x4D, 0x36, 0x31, 0x30, 0x72, 0x43, 0x72, 0x6D, 0x2F, 0x62, 0x30, 0x31, 0x43, ++ 0x37, 0x6A, 0x63, 0x76, 0x6B, 0x32, 0x78, 0x75, 0x73, 0x56, 0x74, 0x79, 0x57, 0x4D, 0x4F, 0x76, 0x77, 0x6C, 0x0A, 0x44, 0x62, 0x4D, 0x69, 0x63, 0x79, 0x46, 0x30, 0x79, 0x45, 0x71, 0x57, 0x59, 0x5A, 0x4C, 0x31, 0x4C, 0x77, 0x73, 0x59, 0x70, ++ 0x66, 0x53, 0x74, 0x34, 0x75, 0x35, 0x42, 0x76, 0x51, 0x46, 0x35, 0x2B, 0x70, 0x61, 0x4D, 0x6A, 0x52, 0x63, 0x43, 0x4D, 0x4C, 0x54, 0x35, 0x72, 0x33, 0x67, 0x61, 0x6A, 0x4C, 0x51, 0x32, 0x45, 0x42, 0x41, 0x48, 0x42, 0x58, 0x44, 0x51, 0x39, ++ 0x44, 0x47, 0x51, 0x69, 0x6C, 0x48, 0x46, 0x68, 0x69, 0x5A, 0x35, 0x73, 0x68, 0x47, 0x49, 0x0A, 0x58, 0x73, 0x58, 0x77, 0x43, 0x6C, 0x54, 0x4E, 0x53, 0x61, 0x61, 0x2F, 0x41, 0x70, 0x7A, 0x53, 0x52, 0x4B, 0x66, 0x74, 0x34, 0x33, 0x6A, 0x76, ++ 0x52, 0x6C, 0x35, 0x74, 0x63, 0x64, 0x46, 0x35, 0x63, 0x42, 0x78, 0x47, 0x58, 0x31, 0x48, 0x70, 0x79, 0x54, 0x66, 0x63, 0x58, 0x33, 0x35, 0x70, 0x65, 0x30, 0x48, 0x66, 0x4E, 0x45, 0x58, 0x67, 0x4F, 0x34, 0x54, 0x30, 0x6F, 0x59, 0x6F, 0x4B, ++ 0x4E, 0x70, 0x34, 0x33, 0x7A, 0x47, 0x4A, 0x53, 0x34, 0x59, 0x6B, 0x4E, 0x0A, 0x4B, 0x50, 0x6C, 0x36, 0x49, 0x37, 0x45, 0x4E, 0x50, 0x54, 0x32, 0x61, 0x2F, 0x5A, 0x32, 0x42, 0x37, 0x79, 0x79, 0x51, 0x77, 0x48, 0x74, 0x45, 0x54, 0x72, 0x74, ++ 0x4A, 0x34, 0x41, 0x35, 0x4B, 0x56, 0x70, 0x4B, 0x38, 0x79, 0x37, 0x58, 0x64, 0x65, 0x52, 0x65, 0x4A, 0x6B, 0x64, 0x35, 0x68, 0x69, 0x58, 0x53, 0x53, 0x71, 0x4F, 0x4D, 0x79, 0x68, 0x62, 0x35, 0x4F, 0x68, 0x61, 0x52, 0x4C, 0x57, 0x63, 0x73, ++ 0x72, 0x78, 0x58, 0x69, 0x4F, 0x63, 0x56, 0x54, 0x51, 0x0A, 0x41, 0x6A, 0x65, 0x5A, 0x6A, 0x4F, 0x56, 0x4A, 0x36, 0x75, 0x42, 0x55, 0x63, 0x71, 0x51, 0x52, 0x42, 0x69, 0x38, 0x4C, 0x6A, 0x4D, 0x46, 0x62, 0x76, 0x72, 0x57, 0x68, 0x73, 0x46, ++ 0x4E, 0x75, 0x6E, 0x4C, 0x68, 0x67, 0x6B, 0x52, 0x39, 0x5A, 0x61, 0x2F, 0x6B, 0x74, 0x39, 0x4A, 0x51, 0x4B, 0x6C, 0x37, 0x58, 0x73, 0x78, 0x58, 0x59, 0x44, 0x56, 0x42, 0x74, 0x6C, 0x55, 0x72, 0x70, 0x4D, 0x6B, 0x6C, 0x5A, 0x52, 0x4E, 0x61, ++ 0x42, 0x41, 0x32, 0x43, 0x6E, 0x62, 0x0A, 0x72, 0x6C, 0x4A, 0x32, 0x4F, 0x79, 0x30, 0x77, 0x51, 0x4A, 0x75, 0x4B, 0x30, 0x45, 0x4A, 0x57, 0x74, 0x4C, 0x65, 0x49, 0x41, 0x61, 0x53, 0x48, 0x4F, 0x31, 0x4F, 0x57, 0x7A, 0x61, 0x4D, 0x57, 0x6A, ++ 0x2F, 0x4E, 0x6D, 0x71, 0x68, 0x65, 0x78, 0x78, 0x32, 0x44, 0x67, 0x77, 0x55, 0x4D, 0x46, 0x44, 0x4F, 0x36, 0x62, 0x57, 0x32, 0x42, 0x76, 0x42, 0x6C, 0x79, 0x48, 0x57, 0x79, 0x66, 0x35, 0x51, 0x42, 0x47, 0x65, 0x6E, 0x44, 0x50, 0x42, 0x74, ++ 0x2B, 0x55, 0x31, 0x0A, 0x56, 0x77, 0x56, 0x2F, 0x4A, 0x38, 0x34, 0x58, 0x49, 0x49, 0x77, 0x63, 0x2F, 0x50, 0x48, 0x37, 0x32, 0x6A, 0x45, 0x70, 0x53, 0x65, 0x33, 0x31, 0x43, 0x34, 0x53, 0x6E, 0x54, 0x38, 0x48, 0x32, 0x54, 0x73, 0x49, 0x6F, ++ 0x6E, 0x50, 0x72, 0x75, 0x34, 0x4B, 0x38, 0x48, 0x2B, 0x7A, 0x4D, 0x52, 0x65, 0x69, 0x46, 0x50, 0x43, 0x79, 0x45, 0x51, 0x74, 0x6B, 0x41, 0x36, 0x71, 0x79, 0x49, 0x36, 0x42, 0x4A, 0x79, 0x4C, 0x6D, 0x34, 0x53, 0x47, 0x63, 0x70, 0x72, 0x53, ++ 0x0A, 0x70, 0x36, 0x58, 0x45, 0x74, 0x48, 0x57, 0x52, 0x71, 0x53, 0x73, 0x6A, 0x41, 0x67, 0x4D, 0x42, 0x41, 0x41, 0x47, 0x6A, 0x51, 0x6A, 0x42, 0x41, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, ++ 0x45, 0x41, 0x77, 0x49, 0x42, 0x42, 0x6A, 0x41, 0x50, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x52, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x54, 0x41, 0x44, 0x41, 0x51, 0x48, 0x2F, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x0A, 0x44, 0x67, ++ 0x51, 0x57, 0x42, 0x42, 0x54, 0x67, 0x71, 0x6A, 0x38, 0x6C, 0x6A, 0x5A, 0x39, 0x45, 0x58, 0x4D, 0x45, 0x36, 0x36, 0x43, 0x36, 0x75, 0x64, 0x30, 0x79, 0x45, 0x50, 0x6D, 0x63, 0x4D, 0x39, 0x44, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, ++ 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x67, 0x45, 0x41, 0x75, 0x56, 0x65, 0x76, 0x75, 0x42, 0x4C, 0x61, 0x56, 0x34, 0x4F, 0x50, 0x61, 0x41, 0x73, 0x7A, 0x0A, 0x48, 0x51, 0x4E, 0x54, 0x56, ++ 0x66, 0x53, 0x56, 0x63, 0x4F, 0x51, 0x72, 0x50, 0x62, 0x41, 0x35, 0x36, 0x2F, 0x71, 0x4A, 0x59, 0x76, 0x33, 0x33, 0x31, 0x68, 0x67, 0x45, 0x4C, 0x79, 0x45, 0x30, 0x33, 0x66, 0x46, 0x6F, 0x38, 0x4E, 0x57, 0x57, 0x57, 0x74, 0x37, 0x43, 0x67, ++ 0x4B, 0x50, 0x42, 0x6A, 0x63, 0x5A, 0x71, 0x39, 0x31, 0x6C, 0x33, 0x72, 0x68, 0x56, 0x6B, 0x7A, 0x31, 0x74, 0x35, 0x42, 0x58, 0x64, 0x6D, 0x36, 0x6F, 0x7A, 0x54, 0x61, 0x77, 0x33, 0x64, 0x0A, 0x38, 0x56, 0x6B, 0x73, 0x77, 0x54, 0x4F, 0x6C, ++ 0x4D, 0x49, 0x41, 0x56, 0x52, 0x51, 0x64, 0x46, 0x47, 0x6A, 0x45, 0x69, 0x74, 0x70, 0x49, 0x41, 0x71, 0x35, 0x6C, 0x4E, 0x4F, 0x6F, 0x39, 0x33, 0x72, 0x36, 0x6B, 0x69, 0x79, 0x69, 0x39, 0x6A, 0x79, 0x68, 0x58, 0x57, 0x78, 0x38, 0x62, 0x77, ++ 0x50, 0x57, 0x7A, 0x38, 0x48, 0x41, 0x32, 0x59, 0x45, 0x47, 0x47, 0x65, 0x45, 0x61, 0x49, 0x69, 0x31, 0x77, 0x72, 0x79, 0x6B, 0x58, 0x70, 0x72, 0x4F, 0x51, 0x34, 0x76, 0x0A, 0x4D, 0x4D, 0x4D, 0x32, 0x53, 0x5A, 0x2F, 0x67, 0x36, 0x51, 0x38, ++ 0x43, 0x52, 0x46, 0x41, 0x33, 0x6C, 0x46, 0x56, 0x39, 0x36, 0x70, 0x2F, 0x32, 0x4F, 0x37, 0x71, 0x55, 0x70, 0x55, 0x7A, 0x70, 0x76, 0x44, 0x35, 0x52, 0x74, 0x4F, 0x6A, 0x4B, 0x6B, 0x6A, 0x5A, 0x55, 0x62, 0x56, 0x77, 0x6C, 0x4B, 0x4E, 0x72, ++ 0x64, 0x72, 0x52, 0x54, 0x39, 0x30, 0x2B, 0x37, 0x69, 0x49, 0x67, 0x58, 0x72, 0x30, 0x50, 0x4B, 0x33, 0x61, 0x42, 0x4C, 0x58, 0x57, 0x6F, 0x70, 0x42, 0x0A, 0x47, 0x73, 0x61, 0x53, 0x70, 0x56, 0x6F, 0x37, 0x59, 0x30, 0x56, 0x50, 0x76, 0x2B, ++ 0x45, 0x36, 0x64, 0x79, 0x49, 0x76, 0x58, 0x4C, 0x39, 0x47, 0x2B, 0x56, 0x6F, 0x44, 0x68, 0x52, 0x4E, 0x43, 0x58, 0x38, 0x72, 0x65, 0x55, 0x39, 0x64, 0x69, 0x74, 0x61, 0x59, 0x31, 0x42, 0x4D, 0x4A, 0x48, 0x2F, 0x35, 0x6E, 0x39, 0x68, 0x4E, ++ 0x39, 0x63, 0x7A, 0x75, 0x6C, 0x65, 0x67, 0x43, 0x68, 0x42, 0x38, 0x6E, 0x33, 0x6E, 0x48, 0x70, 0x44, 0x59, 0x54, 0x33, 0x59, 0x2B, 0x0A, 0x67, 0x6A, 0x77, 0x4E, 0x2F, 0x4B, 0x55, 0x44, 0x2B, 0x6E, 0x73, 0x61, 0x32, 0x55, 0x55, 0x65, 0x59, ++ 0x4E, 0x72, 0x45, 0x6A, 0x76, 0x6E, 0x38, 0x4B, 0x38, 0x6C, 0x37, 0x6C, 0x63, 0x55, 0x71, 0x2F, 0x36, 0x71, 0x4A, 0x33, 0x34, 0x49, 0x78, 0x44, 0x33, 0x4C, 0x2F, 0x44, 0x43, 0x66, 0x58, 0x43, 0x68, 0x35, 0x57, 0x41, 0x46, 0x41, 0x65, 0x44, ++ 0x4A, 0x44, 0x42, 0x6C, 0x72, 0x58, 0x59, 0x46, 0x49, 0x57, 0x37, 0x70, 0x77, 0x30, 0x57, 0x77, 0x66, 0x67, 0x48, 0x0A, 0x4A, 0x42, 0x75, 0x36, 0x68, 0x61, 0x45, 0x61, 0x42, 0x51, 0x6D, 0x41, 0x75, 0x70, 0x56, 0x6A, 0x79, 0x54, 0x72, 0x73, ++ 0x4A, 0x5A, 0x39, 0x2F, 0x6E, 0x62, 0x71, 0x6B, 0x52, 0x78, 0x57, 0x62, 0x52, 0x48, 0x44, 0x78, 0x61, 0x6B, 0x76, 0x57, 0x4F, 0x46, 0x35, 0x44, 0x38, 0x78, 0x68, 0x2B, 0x55, 0x47, 0x37, 0x70, 0x57, 0x69, 0x6A, 0x6D, 0x5A, 0x65, 0x5A, 0x33, ++ 0x47, 0x7A, 0x72, 0x39, 0x48, 0x62, 0x34, 0x44, 0x4A, 0x71, 0x50, 0x62, 0x31, 0x4F, 0x47, 0x37, 0x0A, 0x66, 0x70, 0x59, 0x6E, 0x4B, 0x78, 0x33, 0x75, 0x70, 0x50, 0x76, 0x61, 0x4A, 0x56, 0x51, 0x54, 0x41, 0x39, 0x34, 0x35, 0x78, 0x73, 0x4D, ++ 0x66, 0x54, 0x5A, 0x44, 0x73, 0x6A, 0x78, 0x74, 0x4B, 0x30, 0x68, 0x7A, 0x74, 0x68, 0x5A, 0x55, 0x34, 0x55, 0x48, 0x6C, 0x47, 0x31, 0x73, 0x47, 0x51, 0x55, 0x44, 0x47, 0x70, 0x58, 0x4A, 0x70, 0x75, 0x48, 0x66, 0x55, 0x7A, 0x56, 0x6F, 0x75, ++ 0x6E, 0x6D, 0x64, 0x4C, 0x79, 0x79, 0x43, 0x77, 0x7A, 0x6B, 0x35, 0x49, 0x77, 0x0A, 0x78, 0x30, 0x36, 0x4D, 0x5A, 0x54, 0x4D, 0x51, 0x5A, 0x42, 0x66, 0x39, 0x4A, 0x42, 0x65, 0x57, 0x30, 0x59, 0x33, 0x43, 0x4F, 0x6D, 0x6F, 0x72, 0x36, 0x78, ++ 0x4F, 0x4C, 0x52, 0x50, 0x49, 0x68, 0x38, 0x30, 0x6F, 0x61, 0x74, 0x33, 0x64, 0x66, 0x31, 0x2B, 0x32, 0x49, 0x70, 0x48, 0x4C, 0x6C, 0x4F, 0x52, 0x2B, 0x56, 0x6E, 0x62, 0x35, 0x6E, 0x77, 0x58, 0x41, 0x52, 0x50, 0x62, 0x76, 0x30, 0x2B, 0x45, ++ 0x6D, 0x33, 0x34, 0x79, 0x61, 0x58, 0x4F, 0x70, 0x2F, 0x53, 0x0A, 0x58, 0x33, 0x7A, 0x37, 0x77, 0x4A, 0x6C, 0x38, 0x4F, 0x53, 0x6E, 0x67, 0x65, 0x78, 0x32, 0x2F, 0x44, 0x61, 0x65, 0x50, 0x30, 0x69, 0x6B, 0x30, 0x62, 0x69, 0x51, 0x56, 0x79, ++ 0x39, 0x36, 0x51, 0x58, 0x72, 0x38, 0x61, 0x78, 0x47, 0x62, 0x71, 0x77, 0x75, 0x61, 0x36, 0x4F, 0x56, 0x2B, 0x4B, 0x6D, 0x61, 0x6C, 0x42, 0x57, 0x51, 0x65, 0x77, 0x4C, 0x4B, 0x38, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, ++ 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x43, 0x65, 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x45, 0x31, 0x0A, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, ++ 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x42, 0x39, 0x7A, 0x43, 0x43, 0x41, 0x58, 0x32, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x42, 0x69, 0x55, 0x7A, 0x73, 0x55, 0x63, 0x44, 0x4D, 0x79, 0x64, 0x63, 0x2B, 0x59, 0x32, 0x61, 0x75, ++ 0x62, 0x2F, 0x4D, 0x2B, 0x44, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x7A, 0x41, 0x39, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x56, 0x0A, ++ 0x55, 0x7A, 0x45, 0x53, 0x4D, 0x42, 0x41, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x4A, 0x51, 0x32, 0x56, 0x79, 0x64, 0x47, 0x46, 0x70, 0x62, 0x6D, 0x78, 0x35, 0x4D, 0x52, 0x6F, 0x77, 0x47, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, ++ 0x45, 0x78, 0x46, 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x59, 0x57, 0x6C, 0x75, 0x62, 0x48, 0x6B, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x46, 0x4D, 0x54, 0x41, 0x65, 0x46, 0x77, 0x30, 0x79, 0x4D, 0x54, 0x41, 0x30, 0x0A, 0x4D, 0x44, 0x45, ++ 0x77, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x44, 0x42, 0x61, 0x46, 0x77, 0x30, 0x30, 0x4E, 0x6A, 0x41, 0x30, 0x4D, 0x44, 0x45, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x44, 0x42, 0x61, 0x4D, 0x44, 0x30, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, ++ 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6C, 0x56, 0x54, 0x4D, 0x52, 0x49, 0x77, 0x45, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x45, 0x77, 0x6C, 0x44, 0x5A, 0x58, 0x4A, 0x30, 0x59, 0x57, 0x6C, 0x75, 0x0A, 0x62, 0x48, 0x6B, 0x78, 0x47, 0x6A, ++ 0x41, 0x59, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x45, 0x55, 0x4E, 0x6C, 0x63, 0x6E, 0x52, 0x68, 0x61, 0x57, 0x35, 0x73, 0x65, 0x53, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x55, 0x78, 0x4D, 0x48, 0x59, 0x77, 0x45, 0x41, ++ 0x59, 0x48, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x43, 0x41, 0x51, 0x59, 0x46, 0x4B, 0x34, 0x45, 0x45, 0x41, 0x43, 0x49, 0x44, 0x59, 0x67, 0x41, 0x45, 0x33, 0x6D, 0x2F, 0x34, 0x0A, 0x66, 0x78, 0x7A, 0x66, 0x37, 0x66, 0x6C, 0x48, 0x68, ++ 0x34, 0x61, 0x78, 0x70, 0x4D, 0x43, 0x4B, 0x2B, 0x49, 0x4B, 0x58, 0x67, 0x4F, 0x71, 0x50, 0x79, 0x45, 0x70, 0x65, 0x4B, 0x6E, 0x32, 0x49, 0x61, 0x4B, 0x63, 0x42, 0x59, 0x68, 0x53, 0x52, 0x4A, 0x48, 0x70, 0x63, 0x6E, 0x71, 0x4D, 0x58, 0x66, ++ 0x59, 0x71, 0x47, 0x49, 0x54, 0x51, 0x59, 0x55, 0x42, 0x73, 0x51, 0x33, 0x74, 0x41, 0x33, 0x53, 0x79, 0x62, 0x48, 0x47, 0x57, 0x43, 0x41, 0x36, 0x54, 0x53, 0x39, 0x0A, 0x59, 0x42, 0x6B, 0x32, 0x51, 0x4E, 0x59, 0x70, 0x68, 0x77, 0x6B, 0x38, ++ 0x6B, 0x58, 0x72, 0x32, 0x76, 0x42, 0x4D, 0x6A, 0x33, 0x56, 0x6C, 0x4F, 0x42, 0x46, 0x37, 0x50, 0x79, 0x41, 0x49, 0x63, 0x47, 0x46, 0x50, 0x42, 0x4D, 0x64, 0x6A, 0x61, 0x49, 0x4F, 0x6C, 0x45, 0x6A, 0x65, 0x52, 0x32, 0x6F, 0x30, 0x49, 0x77, ++ 0x51, 0x44, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x51, 0x59, 0x77, 0x0A, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, ++ 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x38, 0x79, 0x67, 0x59, 0x79, 0x32, 0x52, 0x31, 0x37, 0x69, 0x6B, 0x71, 0x36, 0x2B, 0x32, 0x75, 0x49, 0x31, 0x67, ++ 0x34, 0x68, 0x65, 0x76, 0x49, 0x49, 0x67, 0x63, 0x77, 0x43, 0x67, 0x59, 0x49, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x45, 0x0A, 0x41, 0x77, 0x4D, 0x44, 0x61, 0x41, 0x41, 0x77, 0x5A, 0x51, 0x49, 0x78, 0x41, 0x4C, 0x47, 0x4F, 0x57, 0x69, ++ 0x44, 0x44, 0x73, 0x68, 0x6C, 0x69, 0x54, 0x64, 0x36, 0x77, 0x54, 0x39, 0x39, 0x75, 0x30, 0x6E, 0x43, 0x4B, 0x38, 0x5A, 0x39, 0x2B, 0x61, 0x6F, 0x7A, 0x6D, 0x75, 0x74, 0x36, 0x44, 0x61, 0x63, 0x70, 0x70, 0x73, 0x36, 0x6B, 0x46, 0x74, 0x5A, ++ 0x61, 0x53, 0x46, 0x34, 0x66, 0x43, 0x30, 0x75, 0x72, 0x51, 0x65, 0x38, 0x37, 0x59, 0x51, 0x56, 0x74, 0x38, 0x0A, 0x72, 0x67, 0x49, 0x77, 0x52, 0x74, 0x37, 0x71, 0x79, 0x31, 0x32, 0x61, 0x37, 0x44, 0x4C, 0x43, 0x5A, 0x52, 0x61, 0x77, 0x54, ++ 0x44, 0x42, 0x63, 0x4D, 0x50, 0x50, 0x61, 0x54, 0x6E, 0x4F, 0x47, 0x42, 0x74, 0x6A, 0x4F, 0x69, 0x51, 0x52, 0x49, 0x4E, 0x7A, 0x66, 0x34, 0x33, 0x54, 0x4E, 0x52, 0x6E, 0x58, 0x43, 0x76, 0x65, 0x31, 0x58, 0x59, 0x41, 0x53, 0x35, 0x39, 0x42, ++ 0x57, 0x51, 0x4F, 0x68, 0x72, 0x69, 0x52, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x53, 0x65, 0x63, 0x75, 0x72, ++ 0x69, 0x74, 0x79, 0x20, 0x43, 0x6F, 0x6D, 0x6D, 0x75, 0x6E, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x43, 0x41, 0x31, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, ++ 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x43, 0x4F, 0x44, 0x43, 0x43, 0x41, 0x62, 0x36, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x4A, 0x41, 0x4E, 0x5A, 0x64, 0x6D, 0x37, 0x4E, ++ 0x34, 0x67, 0x53, 0x37, 0x72, 0x4D, 0x41, 0x6F, 0x47, 0x43, 0x43, 0x71, 0x47, 0x53, 0x4D, 0x34, 0x39, 0x42, 0x41, 0x4D, 0x44, 0x4D, 0x47, 0x45, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6B, 0x70, ++ 0x51, 0x4D, 0x53, 0x55, 0x77, 0x49, 0x77, 0x59, 0x44, 0x0A, 0x56, 0x51, 0x51, 0x4B, 0x45, 0x78, 0x78, 0x54, 0x52, 0x55, 0x4E, 0x50, 0x54, 0x53, 0x42, 0x55, 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x43, 0x42, 0x54, 0x65, 0x58, 0x4E, 0x30, 0x5A, 0x57, ++ 0x31, 0x7A, 0x49, 0x45, 0x4E, 0x50, 0x4C, 0x69, 0x78, 0x4D, 0x56, 0x45, 0x51, 0x75, 0x4D, 0x53, 0x73, 0x77, 0x4B, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x79, 0x4A, 0x54, 0x5A, 0x57, 0x4E, 0x31, 0x63, 0x6D, 0x6C, 0x30, 0x65, 0x53, ++ 0x42, 0x44, 0x62, 0x32, 0x31, 0x74, 0x0A, 0x64, 0x57, 0x35, 0x70, 0x59, 0x32, 0x46, 0x30, 0x61, 0x57, 0x39, 0x75, 0x49, 0x45, 0x56, 0x44, 0x51, 0x79, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x51, 0x30, 0x45, 0x78, 0x4D, 0x42, 0x34, 0x58, 0x44, ++ 0x54, 0x45, 0x32, 0x4D, 0x44, 0x59, 0x78, 0x4E, 0x6A, 0x41, 0x31, 0x4D, 0x54, 0x55, 0x79, 0x4F, 0x46, 0x6F, 0x58, 0x44, 0x54, 0x4D, 0x34, 0x4D, 0x44, 0x45, 0x78, 0x4F, 0x44, 0x41, 0x31, 0x4D, 0x54, 0x55, 0x79, 0x4F, 0x46, 0x6F, 0x77, 0x59, ++ 0x54, 0x45, 0x4C, 0x0A, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x53, 0x6C, 0x41, 0x78, 0x4A, 0x54, 0x41, 0x6A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x48, 0x46, 0x4E, 0x46, 0x51, 0x30, 0x39, 0x4E, ++ 0x49, 0x46, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x49, 0x46, 0x4E, 0x35, 0x63, 0x33, 0x52, 0x6C, 0x62, 0x58, 0x4D, 0x67, 0x51, 0x30, 0x38, 0x75, 0x4C, 0x45, 0x78, 0x55, 0x52, 0x43, 0x34, 0x78, 0x4B, 0x7A, 0x41, 0x70, 0x42, 0x67, 0x4E, 0x56, ++ 0x0A, 0x42, 0x41, 0x4D, 0x54, 0x49, 0x6C, 0x4E, 0x6C, 0x59, 0x33, 0x56, 0x79, 0x61, 0x58, 0x52, 0x35, 0x49, 0x45, 0x4E, 0x76, 0x62, 0x57, 0x31, 0x31, 0x62, 0x6D, 0x6C, 0x6A, 0x59, 0x58, 0x52, 0x70, 0x62, 0x32, 0x34, 0x67, 0x52, 0x55, 0x4E, ++ 0x44, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x52, 0x44, 0x51, 0x54, 0x45, 0x77, 0x64, 0x6A, 0x41, 0x51, 0x42, 0x67, 0x63, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x49, 0x42, 0x42, 0x67, 0x55, 0x72, 0x67, 0x51, 0x51, 0x41, 0x0A, 0x49, 0x67, ++ 0x4E, 0x69, 0x41, 0x41, 0x53, 0x6B, 0x70, 0x57, 0x39, 0x67, 0x41, 0x77, 0x50, 0x44, 0x76, 0x54, 0x48, 0x30, 0x30, 0x78, 0x65, 0x63, 0x4B, 0x34, 0x52, 0x31, 0x72, 0x4F, 0x58, 0x39, 0x50, 0x56, 0x64, 0x75, 0x31, 0x32, 0x4F, 0x2F, 0x35, 0x67, ++ 0x53, 0x4A, 0x6B, 0x6F, 0x36, 0x42, 0x6E, 0x4F, 0x50, 0x70, 0x52, 0x32, 0x37, 0x4B, 0x6B, 0x42, 0x4C, 0x49, 0x45, 0x2B, 0x43, 0x6E, 0x6E, 0x66, 0x64, 0x6C, 0x64, 0x42, 0x39, 0x73, 0x45, 0x4C, 0x4C, 0x6F, 0x0A, 0x35, 0x4F, 0x6E, 0x76, 0x62, ++ 0x59, 0x55, 0x79, 0x6D, 0x55, 0x53, 0x78, 0x58, 0x76, 0x33, 0x4D, 0x64, 0x68, 0x44, 0x59, 0x57, 0x37, 0x32, 0x69, 0x78, 0x76, 0x6E, 0x57, 0x51, 0x75, 0x52, 0x58, 0x64, 0x74, 0x79, 0x51, 0x77, 0x6A, 0x57, 0x70, 0x53, 0x34, 0x67, 0x38, 0x45, ++ 0x6B, 0x64, 0x74, 0x58, 0x50, 0x39, 0x4A, 0x54, 0x78, 0x70, 0x4B, 0x55, 0x4C, 0x47, 0x6A, 0x51, 0x6A, 0x42, 0x41, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, 0x0A, 0x42, 0x42, 0x53, 0x47, 0x48, 0x4F, 0x66, 0x2B, ++ 0x4C, 0x61, 0x56, 0x4B, 0x69, 0x77, 0x6A, 0x2B, 0x4B, 0x42, 0x48, 0x36, 0x76, 0x71, 0x4E, 0x6D, 0x2B, 0x47, 0x42, 0x5A, 0x4C, 0x7A, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x41, 0x4D, 0x43, ++ 0x41, 0x51, 0x59, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x4B, 0x0A, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, ++ 0x44, 0x41, 0x77, 0x4E, 0x6F, 0x41, 0x44, 0x42, 0x6C, 0x41, 0x6A, 0x41, 0x56, 0x58, 0x55, 0x49, 0x39, 0x2F, 0x4C, 0x62, 0x75, 0x39, 0x7A, 0x75, 0x78, 0x4E, 0x75, 0x69, 0x65, 0x39, 0x73, 0x52, 0x47, 0x4B, 0x45, 0x6B, 0x7A, 0x30, 0x46, 0x68, ++ 0x44, 0x4B, 0x6D, 0x4D, 0x70, 0x7A, 0x45, 0x32, 0x78, 0x74, 0x48, 0x71, 0x69, 0x75, 0x51, 0x30, 0x34, 0x70, 0x56, 0x31, 0x49, 0x4B, 0x76, 0x33, 0x4C, 0x0A, 0x73, 0x6E, 0x4E, 0x64, 0x6F, 0x34, 0x67, 0x49, 0x78, 0x77, 0x77, 0x43, 0x4D, 0x51, ++ 0x44, 0x41, 0x71, 0x79, 0x30, 0x4F, 0x62, 0x65, 0x30, 0x59, 0x6F, 0x74, 0x74, 0x54, 0x36, 0x53, 0x58, 0x62, 0x56, 0x51, 0x6A, 0x67, 0x55, 0x4D, 0x7A, 0x66, 0x52, 0x47, 0x45, 0x57, 0x67, 0x71, 0x74, 0x4A, 0x73, 0x4C, 0x4B, 0x42, 0x37, 0x48, ++ 0x4F, 0x48, 0x65, 0x4C, 0x52, 0x4D, 0x73, 0x6D, 0x49, 0x62, 0x45, 0x76, 0x6F, 0x57, 0x54, 0x53, 0x56, 0x4C, 0x59, 0x37, 0x30, 0x65, 0x0A, 0x4E, 0x39, 0x6B, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, ++ 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x42, 0x4A, 0x43, 0x41, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, ++ 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x64, 0x44, 0x43, 0x43, 0x41, 0x31, 0x79, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x56, 0x57, 0x39, 0x6C, 0x34, 0x37, 0x54, 0x5A, 0x6B, 0x47, 0x6F, 0x62, 0x43, 0x64, 0x46, ++ 0x73, 0x50, 0x73, 0x42, 0x73, 0x49, 0x44, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x44, 0x42, 0x55, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, ++ 0x47, 0x0A, 0x45, 0x77, 0x4A, 0x44, 0x54, 0x6A, 0x45, 0x6D, 0x4D, 0x43, 0x51, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, 0x64, 0x51, 0x6B, 0x56, 0x4A, 0x53, 0x6B, 0x6C, 0x4F, 0x52, 0x79, 0x42, 0x44, 0x52, 0x56, 0x4A, 0x55, 0x53, 0x55, ++ 0x5A, 0x4A, 0x51, 0x30, 0x46, 0x55, 0x52, 0x53, 0x42, 0x42, 0x56, 0x56, 0x52, 0x49, 0x54, 0x31, 0x4A, 0x4A, 0x56, 0x46, 0x6B, 0x78, 0x48, 0x54, 0x41, 0x62, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x4D, 0x46, 0x45, 0x4A, 0x4B, 0x0A, 0x51, ++ 0x30, 0x45, 0x67, 0x52, 0x32, 0x78, 0x76, 0x59, 0x6D, 0x46, 0x73, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x78, 0x4D, 0x42, 0x34, 0x58, 0x44, 0x54, 0x45, 0x35, 0x4D, 0x54, 0x49, 0x78, 0x4F, 0x54, 0x41, 0x7A, 0x4D, ++ 0x54, 0x59, 0x78, 0x4E, 0x31, 0x6F, 0x58, 0x44, 0x54, 0x51, 0x30, 0x4D, 0x54, 0x49, 0x78, 0x4D, 0x6A, 0x41, 0x7A, 0x4D, 0x54, 0x59, 0x78, 0x4E, 0x31, 0x6F, 0x77, 0x56, 0x44, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x0A, 0x41, 0x31, 0x55, 0x45, ++ 0x42, 0x68, 0x4D, 0x43, 0x51, 0x30, 0x34, 0x78, 0x4A, 0x6A, 0x41, 0x6B, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x4D, 0x48, 0x55, 0x4A, 0x46, 0x53, 0x55, 0x70, 0x4A, 0x54, 0x6B, 0x63, 0x67, 0x51, 0x30, 0x56, 0x53, 0x56, 0x45, 0x6C, 0x47, ++ 0x53, 0x55, 0x4E, 0x42, 0x56, 0x45, 0x55, 0x67, 0x51, 0x56, 0x56, 0x55, 0x53, 0x45, 0x39, 0x53, 0x53, 0x56, 0x52, 0x5A, 0x4D, 0x52, 0x30, 0x77, 0x47, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x0A, 0x44, 0x42, 0x52, 0x43, 0x53, 0x6B, 0x4E, ++ 0x42, 0x49, 0x45, 0x64, 0x73, 0x62, 0x32, 0x4A, 0x68, 0x62, 0x43, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x42, 0x4D, 0x54, 0x43, 0x43, 0x41, 0x69, 0x49, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, ++ 0x4E, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x50, 0x41, 0x44, 0x43, 0x43, 0x41, 0x67, 0x6F, 0x43, 0x67, 0x67, 0x49, 0x42, 0x41, 0x50, 0x46, 0x6D, 0x0A, 0x43, 0x4C, 0x33, 0x5A, 0x78, 0x52, 0x56, 0x68, 0x79, 0x34, ++ 0x51, 0x45, 0x51, 0x61, 0x56, 0x70, 0x4E, 0x33, 0x63, 0x64, 0x77, 0x62, 0x42, 0x37, 0x2B, 0x73, 0x4E, 0x33, 0x53, 0x4A, 0x41, 0x54, 0x63, 0x6D, 0x54, 0x52, 0x75, 0x48, 0x79, 0x51, 0x4E, 0x5A, 0x30, 0x59, 0x65, 0x59, 0x6A, 0x6A, 0x6C, 0x77, ++ 0x45, 0x38, 0x52, 0x34, 0x48, 0x79, 0x44, 0x71, 0x4B, 0x59, 0x44, 0x5A, 0x34, 0x2F, 0x4E, 0x2B, 0x41, 0x5A, 0x73, 0x70, 0x44, 0x79, 0x52, 0x68, 0x79, 0x53, 0x0A, 0x73, 0x54, 0x70, 0x68, 0x7A, 0x76, 0x71, 0x33, 0x52, 0x70, 0x34, 0x44, 0x68, ++ 0x74, 0x63, 0x7A, 0x62, 0x75, 0x33, 0x33, 0x52, 0x59, 0x78, 0x32, 0x4E, 0x39, 0x35, 0x75, 0x6C, 0x70, 0x48, 0x33, 0x31, 0x33, 0x34, 0x72, 0x68, 0x78, 0x66, 0x56, 0x69, 0x7A, 0x58, 0x75, 0x68, 0x4A, 0x46, 0x79, 0x56, 0x39, 0x78, 0x67, 0x77, ++ 0x38, 0x4F, 0x35, 0x35, 0x38, 0x64, 0x6E, 0x4A, 0x43, 0x4E, 0x50, 0x59, 0x77, 0x70, 0x6A, 0x39, 0x6D, 0x5A, 0x39, 0x53, 0x31, 0x57, 0x6E, 0x0A, 0x50, 0x33, 0x68, 0x6B, 0x53, 0x57, 0x6B, 0x53, 0x6C, 0x2B, 0x42, 0x4D, 0x44, 0x64, 0x4D, 0x4A, ++ 0x6F, 0x44, 0x49, 0x77, 0x4F, 0x76, 0x71, 0x66, 0x77, 0x50, 0x4B, 0x63, 0x78, 0x52, 0x49, 0x71, 0x4C, 0x68, 0x79, 0x31, 0x42, 0x44, 0x50, 0x61, 0x70, 0x44, 0x67, 0x52, 0x61, 0x74, 0x37, 0x47, 0x47, 0x50, 0x5A, 0x48, 0x4F, 0x69, 0x4A, 0x42, ++ 0x68, 0x79, 0x4C, 0x38, 0x78, 0x49, 0x6B, 0x6F, 0x56, 0x4E, 0x69, 0x4D, 0x70, 0x54, 0x41, 0x4B, 0x2B, 0x42, 0x63, 0x57, 0x0A, 0x79, 0x71, 0x77, 0x33, 0x2F, 0x58, 0x6D, 0x6E, 0x6B, 0x52, 0x64, 0x34, 0x4F, 0x4A, 0x6D, 0x74, 0x57, 0x4F, 0x32, ++ 0x79, 0x33, 0x73, 0x79, 0x4A, 0x66, 0x51, 0x4F, 0x63, 0x73, 0x34, 0x6C, 0x6C, 0x35, 0x2B, 0x4D, 0x37, 0x73, 0x53, 0x4B, 0x47, 0x6A, 0x77, 0x5A, 0x74, 0x65, 0x41, 0x66, 0x39, 0x6B, 0x52, 0x4A, 0x2F, 0x73, 0x47, 0x73, 0x63, 0x69, 0x51, 0x33, ++ 0x35, 0x75, 0x4D, 0x74, 0x30, 0x57, 0x77, 0x66, 0x43, 0x79, 0x50, 0x51, 0x31, 0x30, 0x57, 0x52, 0x6A, 0x0A, 0x65, 0x75, 0x6C, 0x75, 0x6D, 0x69, 0x6A, 0x57, 0x4D, 0x4C, 0x33, 0x6D, 0x47, 0x39, 0x30, 0x56, 0x72, 0x34, 0x54, 0x71, 0x6E, 0x4D, ++ 0x66, 0x4B, 0x39, 0x51, 0x37, 0x71, 0x38, 0x6C, 0x30, 0x70, 0x68, 0x34, 0x39, 0x70, 0x63, 0x7A, 0x6D, 0x2B, 0x4C, 0x69, 0x52, 0x76, 0x52, 0x53, 0x47, 0x73, 0x78, 0x64, 0x52, 0x70, 0x4A, 0x51, 0x61, 0x44, 0x72, 0x58, 0x70, 0x49, 0x68, 0x52, ++ 0x4D, 0x73, 0x44, 0x51, 0x61, 0x34, 0x62, 0x48, 0x6C, 0x57, 0x2F, 0x4B, 0x4E, 0x6E, 0x0A, 0x4D, 0x6F, 0x48, 0x31, 0x56, 0x36, 0x58, 0x4B, 0x56, 0x30, 0x4A, 0x70, 0x36, 0x56, 0x77, 0x6B, 0x59, 0x65, 0x2F, 0x69, 0x4D, 0x42, 0x68, 0x4F, 0x52, ++ 0x4A, 0x68, 0x56, 0x62, 0x33, 0x72, 0x43, 0x6B, 0x39, 0x67, 0x5A, 0x74, 0x74, 0x35, 0x38, 0x52, 0x34, 0x6F, 0x52, 0x54, 0x6B, 0x6C, 0x48, 0x32, 0x79, 0x69, 0x55, 0x41, 0x67, 0x75, 0x55, 0x53, 0x69, 0x7A, 0x35, 0x45, 0x74, 0x42, 0x50, 0x36, ++ 0x44, 0x46, 0x2B, 0x62, 0x48, 0x71, 0x2F, 0x70, 0x6A, 0x2B, 0x62, 0x0A, 0x4F, 0x54, 0x30, 0x43, 0x46, 0x71, 0x4D, 0x59, 0x73, 0x32, 0x65, 0x73, 0x57, 0x7A, 0x38, 0x73, 0x67, 0x79, 0x74, 0x6E, 0x4F, 0x59, 0x46, 0x63, 0x75, 0x58, 0x36, 0x55, ++ 0x31, 0x57, 0x54, 0x64, 0x6E, 0x6F, 0x39, 0x75, 0x72, 0x75, 0x68, 0x38, 0x57, 0x37, 0x54, 0x58, 0x61, 0x6B, 0x64, 0x49, 0x31, 0x33, 0x36, 0x7A, 0x31, 0x43, 0x32, 0x4F, 0x56, 0x6E, 0x5A, 0x4F, 0x7A, 0x32, 0x6E, 0x78, 0x62, 0x6B, 0x52, 0x73, ++ 0x31, 0x43, 0x54, 0x71, 0x6A, 0x53, 0x53, 0x68, 0x0A, 0x47, 0x4C, 0x2B, 0x39, 0x56, 0x2F, 0x36, 0x70, 0x6D, 0x54, 0x57, 0x31, 0x32, 0x78, 0x42, 0x33, 0x75, 0x44, 0x31, 0x49, 0x75, 0x74, 0x62, 0x42, 0x35, 0x2F, 0x45, 0x6A, 0x50, 0x74, 0x66, ++ 0x66, 0x68, 0x5A, 0x30, 0x6E, 0x50, 0x4E, 0x52, 0x41, 0x76, 0x51, 0x6F, 0x4D, 0x76, 0x66, 0x58, 0x6E, 0x6A, 0x53, 0x58, 0x57, 0x67, 0x58, 0x53, 0x48, 0x52, 0x74, 0x51, 0x70, 0x64, 0x61, 0x4A, 0x43, 0x62, 0x50, 0x64, 0x7A, 0x69, 0x65, 0x64, ++ 0x39, 0x76, 0x33, 0x70, 0x4B, 0x0A, 0x48, 0x39, 0x4D, 0x69, 0x79, 0x52, 0x56, 0x56, 0x7A, 0x39, 0x39, 0x76, 0x66, 0x46, 0x58, 0x51, 0x70, 0x49, 0x73, 0x48, 0x45, 0x54, 0x64, 0x66, 0x67, 0x36, 0x59, 0x6D, 0x56, 0x36, 0x59, 0x42, 0x57, 0x33, ++ 0x37, 0x2B, 0x57, 0x47, 0x67, 0x48, 0x71, 0x65, 0x6C, 0x36, 0x32, 0x62, 0x6E, 0x6F, 0x2F, 0x31, 0x41, 0x66, 0x71, 0x38, 0x4B, 0x30, 0x77, 0x4D, 0x37, 0x6F, 0x36, 0x76, 0x30, 0x50, 0x76, 0x59, 0x31, 0x4E, 0x75, 0x4C, 0x78, 0x78, 0x41, 0x67, ++ 0x4D, 0x42, 0x0A, 0x41, 0x41, 0x47, 0x6A, 0x51, 0x6A, 0x42, 0x41, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x54, 0x46, 0x37, 0x2B, 0x33, 0x4D, 0x32, 0x49, 0x30, 0x68, 0x78, 0x6B, 0x6A, 0x6B, 0x34, ++ 0x39, 0x63, 0x55, 0x4C, 0x71, 0x63, 0x57, 0x6B, 0x2B, 0x57, 0x59, 0x41, 0x54, 0x41, 0x50, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x52, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x54, 0x41, 0x44, 0x41, 0x51, 0x48, 0x2F, 0x4D, 0x41, 0x34, 0x47, 0x0A, ++ 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x42, 0x42, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x41, 0x4F, 0x43, ++ 0x41, 0x67, 0x45, 0x41, 0x55, 0x6F, 0x4B, 0x73, 0x49, 0x54, 0x51, 0x66, 0x49, 0x2F, 0x4B, 0x69, 0x32, 0x50, 0x6D, 0x34, 0x72, 0x7A, 0x63, 0x32, 0x49, 0x49, 0x6E, 0x52, 0x4E, 0x77, 0x50, 0x57, 0x61, 0x5A, 0x2B, 0x34, 0x0A, 0x59, 0x52, 0x43, ++ 0x36, 0x6F, 0x6A, 0x47, 0x59, 0x57, 0x55, 0x66, 0x6F, 0x30, 0x51, 0x30, 0x6C, 0x48, 0x68, 0x56, 0x42, 0x44, 0x4F, 0x41, 0x71, 0x56, 0x64, 0x56, 0x58, 0x55, 0x73, 0x76, 0x34, 0x35, 0x4D, 0x64, 0x70, 0x6F, 0x78, 0x31, 0x4E, 0x63, 0x51, 0x4A, ++ 0x65, 0x58, 0x79, 0x46, 0x46, 0x59, 0x45, 0x68, 0x63, 0x43, 0x59, 0x35, 0x4A, 0x45, 0x4D, 0x45, 0x45, 0x33, 0x4B, 0x6C, 0x69, 0x61, 0x77, 0x4C, 0x77, 0x51, 0x38, 0x68, 0x4F, 0x6E, 0x54, 0x68, 0x4A, 0x0A, 0x64, 0x4D, 0x6B, 0x79, 0x63, 0x46, ++ 0x52, 0x74, 0x77, 0x55, 0x66, 0x38, 0x6A, 0x72, 0x51, 0x32, 0x6E, 0x74, 0x53, 0x63, 0x76, 0x64, 0x30, 0x67, 0x31, 0x6C, 0x50, 0x4A, 0x47, 0x4B, 0x6D, 0x31, 0x56, 0x72, 0x6C, 0x32, 0x69, 0x35, 0x56, 0x6E, 0x5A, 0x75, 0x36, 0x39, 0x6D, 0x50, ++ 0x36, 0x75, 0x37, 0x37, 0x35, 0x75, 0x2B, 0x32, 0x44, 0x32, 0x2F, 0x56, 0x6E, 0x47, 0x4B, 0x68, 0x73, 0x2F, 0x49, 0x30, 0x71, 0x55, 0x4A, 0x44, 0x41, 0x6E, 0x79, 0x49, 0x6D, 0x38, 0x0A, 0x36, 0x30, 0x51, 0x6B, 0x6D, 0x73, 0x73, 0x39, 0x76, ++ 0x6B, 0x2F, 0x56, 0x65, 0x73, 0x36, 0x4F, 0x46, 0x38, 0x74, 0x69, 0x77, 0x64, 0x6E, 0x65, 0x48, 0x67, 0x35, 0x36, 0x2F, 0x30, 0x4F, 0x47, 0x4E, 0x46, 0x4B, 0x38, 0x59, 0x54, 0x38, 0x38, 0x58, 0x37, 0x76, 0x5A, 0x64, 0x72, 0x52, 0x54, 0x76, ++ 0x4A, 0x65, 0x7A, 0x2F, 0x6F, 0x70, 0x4D, 0x45, 0x69, 0x34, 0x72, 0x38, 0x39, 0x66, 0x4F, 0x34, 0x61, 0x4C, 0x2F, 0x33, 0x58, 0x74, 0x77, 0x2B, 0x7A, 0x75, 0x68, 0x0A, 0x54, 0x61, 0x52, 0x6A, 0x41, 0x76, 0x30, 0x34, 0x6C, 0x35, 0x55, 0x2F, ++ 0x42, 0x58, 0x43, 0x67, 0x61, 0x39, 0x39, 0x69, 0x67, 0x55, 0x4F, 0x4C, 0x74, 0x46, 0x6B, 0x4E, 0x53, 0x6F, 0x78, 0x55, 0x6E, 0x4D, 0x57, 0x37, 0x67, 0x5A, 0x2F, 0x4E, 0x66, 0x61, 0x58, 0x76, 0x43, 0x79, 0x55, 0x65, 0x4F, 0x69, 0x44, 0x62, ++ 0x48, 0x50, 0x77, 0x66, 0x6D, 0x47, 0x63, 0x43, 0x43, 0x74, 0x52, 0x7A, 0x52, 0x42, 0x50, 0x62, 0x55, 0x59, 0x51, 0x61, 0x56, 0x51, 0x4E, 0x57, 0x0A, 0x34, 0x41, 0x42, 0x2B, 0x64, 0x41, 0x62, 0x2F, 0x4F, 0x4D, 0x52, 0x79, 0x48, 0x64, 0x4F, ++ 0x6F, 0x50, 0x32, 0x67, 0x78, 0x58, 0x64, 0x4D, 0x4A, 0x78, 0x79, 0x36, 0x4D, 0x57, 0x32, 0x50, 0x67, 0x36, 0x4E, 0x77, 0x65, 0x30, 0x75, 0x78, 0x68, 0x48, 0x76, 0x4C, 0x65, 0x35, 0x65, 0x2F, 0x32, 0x6D, 0x58, 0x5A, 0x67, 0x4C, 0x52, 0x36, ++ 0x55, 0x63, 0x6E, 0x48, 0x47, 0x43, 0x79, 0x6F, 0x79, 0x78, 0x35, 0x4A, 0x4F, 0x31, 0x55, 0x62, 0x58, 0x48, 0x66, 0x6D, 0x70, 0x0A, 0x47, 0x51, 0x72, 0x49, 0x2B, 0x70, 0x58, 0x4F, 0x62, 0x53, 0x4F, 0x59, 0x71, 0x67, 0x73, 0x34, 0x72, 0x5A, ++ 0x70, 0x57, 0x44, 0x57, 0x2B, 0x4E, 0x38, 0x54, 0x45, 0x41, 0x69, 0x4D, 0x45, 0x58, 0x6E, 0x4D, 0x30, 0x5A, 0x4E, 0x6A, 0x58, 0x2B, 0x56, 0x56, 0x4F, 0x67, 0x34, 0x44, 0x77, 0x7A, 0x58, 0x35, 0x5A, 0x65, 0x34, 0x6A, 0x4C, 0x70, 0x33, 0x7A, ++ 0x4F, 0x37, 0x42, 0x6B, 0x71, 0x70, 0x32, 0x49, 0x52, 0x7A, 0x7A, 0x6E, 0x66, 0x53, 0x78, 0x71, 0x78, 0x78, 0x0A, 0x34, 0x56, 0x79, 0x6A, 0x48, 0x51, 0x79, 0x37, 0x43, 0x74, 0x39, 0x66, 0x34, 0x71, 0x4E, 0x78, 0x32, 0x4E, 0x6F, 0x33, 0x57, ++ 0x71, 0x42, 0x34, 0x4B, 0x2F, 0x54, 0x55, 0x66, 0x65, 0x74, 0x32, 0x37, 0x66, 0x4A, 0x68, 0x63, 0x4B, 0x56, 0x6C, 0x6D, 0x74, 0x4F, 0x4A, 0x4E, 0x42, 0x69, 0x72, 0x2B, 0x33, 0x49, 0x2B, 0x31, 0x37, 0x51, 0x39, 0x65, 0x56, 0x7A, 0x59, 0x48, ++ 0x36, 0x45, 0x7A, 0x65, 0x39, 0x6D, 0x43, 0x55, 0x41, 0x79, 0x54, 0x46, 0x36, 0x70, 0x73, 0x0A, 0x33, 0x4D, 0x4B, 0x43, 0x75, 0x77, 0x4A, 0x58, 0x4E, 0x71, 0x2B, 0x59, 0x4A, 0x79, 0x6F, 0x35, 0x55, 0x4F, 0x47, 0x77, 0x69, 0x66, 0x55, 0x6C, ++ 0x6C, 0x33, 0x35, 0x48, 0x61, 0x42, 0x43, 0x30, 0x37, 0x48, 0x50, 0x4B, 0x73, 0x35, 0x66, 0x52, 0x4A, 0x4E, 0x7A, 0x32, 0x59, 0x71, 0x41, 0x6F, 0x30, 0x37, 0x57, 0x6A, 0x75, 0x47, 0x53, 0x33, 0x69, 0x47, 0x4A, 0x43, 0x7A, 0x35, 0x31, 0x54, ++ 0x7A, 0x5A, 0x6D, 0x2B, 0x5A, 0x47, 0x69, 0x50, 0x54, 0x78, 0x34, 0x53, 0x0A, 0x53, 0x50, 0x66, 0x53, 0x4B, 0x63, 0x4F, 0x59, 0x4B, 0x4D, 0x72, 0x79, 0x4D, 0x67, 0x75, 0x54, 0x6A, 0x43, 0x6C, 0x50, 0x50, 0x47, 0x41, 0x79, 0x7A, 0x51, 0x57, ++ 0x57, 0x59, 0x65, 0x7A, 0x79, 0x72, 0x2F, 0x36, 0x7A, 0x63, 0x43, 0x77, 0x75, 0x70, 0x76, 0x49, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, ++ 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x42, 0x4A, 0x43, 0x41, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x32, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x43, 0x4A, ++ 0x54, 0x43, 0x43, 0x41, 0x61, 0x75, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x4C, 0x42, 0x63, 0x49, 0x66, 0x57, 0x51, 0x71, 0x77, 0x50, 0x36, 0x46, 0x47, 0x46, 0x6B, 0x47, 0x7A, 0x37, 0x52, 0x4B, 0x36, 0x7A, 0x41, 0x4B, 0x42, ++ 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x7A, 0x42, 0x55, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x44, 0x0A, 0x54, 0x6A, 0x45, 0x6D, 0x4D, 0x43, 0x51, 0x47, ++ 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, 0x64, 0x51, 0x6B, 0x56, 0x4A, 0x53, 0x6B, 0x6C, 0x4F, 0x52, 0x79, 0x42, 0x44, 0x52, 0x56, 0x4A, 0x55, 0x53, 0x55, 0x5A, 0x4A, 0x51, 0x30, 0x46, 0x55, 0x52, 0x53, 0x42, 0x42, 0x56, 0x56, 0x52, 0x49, ++ 0x54, 0x31, 0x4A, 0x4A, 0x56, 0x46, 0x6B, 0x78, 0x48, 0x54, 0x41, 0x62, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x4D, 0x46, 0x45, 0x4A, 0x4B, 0x51, 0x30, 0x45, 0x67, 0x0A, 0x52, 0x32, 0x78, 0x76, 0x59, 0x6D, 0x46, 0x73, 0x49, 0x46, 0x4A, ++ 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x79, 0x4D, 0x42, 0x34, 0x58, 0x44, 0x54, 0x45, 0x35, 0x4D, 0x54, 0x49, 0x78, 0x4F, 0x54, 0x41, 0x7A, 0x4D, 0x54, 0x67, 0x79, 0x4D, 0x56, 0x6F, 0x58, 0x44, 0x54, 0x51, 0x30, 0x4D, 0x54, 0x49, ++ 0x78, 0x4D, 0x6A, 0x41, 0x7A, 0x4D, 0x54, 0x67, 0x79, 0x4D, 0x56, 0x6F, 0x77, 0x56, 0x44, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x0A, 0x42, 0x68, 0x4D, 0x43, 0x51, 0x30, 0x34, 0x78, 0x4A, 0x6A, 0x41, 0x6B, 0x42, 0x67, ++ 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x4D, 0x48, 0x55, 0x4A, 0x46, 0x53, 0x55, 0x70, 0x4A, 0x54, 0x6B, 0x63, 0x67, 0x51, 0x30, 0x56, 0x53, 0x56, 0x45, 0x6C, 0x47, 0x53, 0x55, 0x4E, 0x42, 0x56, 0x45, 0x55, 0x67, 0x51, 0x56, 0x56, 0x55, 0x53, 0x45, ++ 0x39, 0x53, 0x53, 0x56, 0x52, 0x5A, 0x4D, 0x52, 0x30, 0x77, 0x47, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x44, 0x42, 0x52, 0x43, 0x0A, 0x53, 0x6B, 0x4E, 0x42, 0x49, 0x45, 0x64, 0x73, 0x62, 0x32, 0x4A, 0x68, 0x62, 0x43, 0x42, 0x53, 0x62, ++ 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x42, 0x4D, 0x6A, 0x42, 0x32, 0x4D, 0x42, 0x41, 0x47, 0x42, 0x79, 0x71, 0x47, 0x53, 0x4D, 0x34, 0x39, 0x41, 0x67, 0x45, 0x47, 0x42, 0x53, 0x75, 0x42, 0x42, 0x41, 0x41, 0x69, 0x41, 0x32, 0x49, 0x41, 0x42, ++ 0x4A, 0x33, 0x4C, 0x67, 0x4A, 0x47, 0x4E, 0x55, 0x32, 0x65, 0x31, 0x75, 0x56, 0x43, 0x78, 0x41, 0x2F, 0x6A, 0x6C, 0x0A, 0x53, 0x52, 0x39, 0x42, 0x49, 0x67, 0x6D, 0x77, 0x55, 0x56, 0x4A, 0x59, 0x31, 0x69, 0x73, 0x30, 0x6A, 0x38, 0x55, 0x53, ++ 0x52, 0x68, 0x54, 0x46, 0x69, 0x79, 0x38, 0x73, 0x68, 0x50, 0x38, 0x73, 0x62, 0x71, 0x6A, 0x56, 0x38, 0x51, 0x6E, 0x6A, 0x41, 0x79, 0x45, 0x55, 0x78, 0x45, 0x4D, 0x39, 0x66, 0x4D, 0x45, 0x73, 0x78, 0x45, 0x74, 0x71, 0x53, 0x73, 0x33, 0x70, ++ 0x68, 0x2B, 0x42, 0x39, 0x39, 0x69, 0x4B, 0x2B, 0x2B, 0x6B, 0x70, 0x52, 0x75, 0x44, 0x43, 0x4B, 0x0A, 0x2F, 0x65, 0x48, 0x65, 0x47, 0x42, 0x49, 0x4B, 0x39, 0x6B, 0x65, 0x33, 0x35, 0x78, 0x65, 0x2F, 0x4A, 0x34, 0x72, 0x55, 0x51, 0x55, 0x79, ++ 0x57, 0x50, 0x47, 0x43, 0x57, 0x77, 0x66, 0x30, 0x56, 0x48, 0x4B, 0x4E, 0x43, 0x4D, 0x45, 0x41, 0x77, 0x48, 0x51, 0x59, 0x44, 0x56, 0x52, 0x30, 0x4F, 0x42, 0x42, 0x59, 0x45, 0x46, 0x4E, 0x4A, 0x4B, 0x73, 0x56, 0x46, 0x2F, 0x42, 0x76, 0x44, ++ 0x52, 0x67, 0x68, 0x39, 0x4F, 0x62, 0x6C, 0x2B, 0x72, 0x67, 0x2F, 0x78, 0x49, 0x0A, 0x31, 0x4C, 0x43, 0x52, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, ++ 0x38, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x51, 0x44, 0x41, 0x67, 0x45, 0x47, 0x4D, 0x41, 0x6F, 0x47, 0x43, 0x43, 0x71, 0x47, 0x53, 0x4D, 0x34, 0x39, 0x42, 0x41, 0x4D, 0x44, 0x41, 0x32, ++ 0x67, 0x41, 0x4D, 0x47, 0x55, 0x43, 0x4D, 0x42, 0x71, 0x38, 0x0A, 0x57, 0x39, 0x66, 0x2B, 0x71, 0x64, 0x4A, 0x55, 0x44, 0x6B, 0x70, 0x64, 0x30, 0x6D, 0x32, 0x78, 0x51, 0x4E, 0x7A, 0x30, 0x51, 0x39, 0x58, 0x53, 0x53, 0x70, 0x6B, 0x5A, 0x45, ++ 0x6C, 0x61, 0x41, 0x39, 0x34, 0x4D, 0x30, 0x34, 0x54, 0x56, 0x4F, 0x53, 0x47, 0x30, 0x45, 0x44, 0x31, 0x63, 0x78, 0x4D, 0x44, 0x41, 0x74, 0x73, 0x61, 0x71, 0x64, 0x41, 0x7A, 0x6A, 0x62, 0x42, 0x67, 0x49, 0x78, 0x41, 0x4D, 0x76, 0x4D, 0x68, ++ 0x31, 0x50, 0x4C, 0x65, 0x74, 0x38, 0x67, 0x0A, 0x55, 0x58, 0x4F, 0x51, 0x77, 0x4B, 0x68, 0x62, 0x59, 0x64, 0x44, 0x46, 0x55, 0x44, 0x6E, 0x39, 0x68, 0x66, 0x37, 0x42, 0x34, 0x33, 0x6A, 0x34, 0x70, 0x74, 0x5A, 0x4C, 0x76, 0x5A, 0x75, 0x48, ++ 0x6A, 0x77, 0x2F, 0x6C, 0x31, 0x6C, 0x4F, 0x57, 0x71, 0x7A, 0x7A, 0x49, 0x51, 0x4E, 0x70, 0x68, 0x39, 0x31, 0x4F, 0x6A, 0x39, 0x77, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, ++ 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6E, ++ 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x45, 0x34, 0x36, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, ++ 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x43, 0x4F, 0x6A, 0x43, 0x43, 0x41, 0x63, 0x47, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x51, 0x76, 0x4C, 0x4D, 0x32, 0x68, 0x74, 0x70, ++ 0x4E, 0x30, 0x52, 0x66, 0x46, 0x66, 0x35, 0x31, 0x4B, 0x42, 0x43, 0x34, 0x39, 0x44, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x7A, 0x42, 0x66, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, ++ 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x48, 0x0A, 0x51, 0x6A, 0x45, 0x59, 0x4D, 0x42, 0x59, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x50, 0x55, 0x32, 0x56, 0x6A, 0x64, 0x47, 0x6C, 0x6E, 0x62, 0x79, 0x42, 0x4D, 0x61, 0x57, 0x31, ++ 0x70, 0x64, 0x47, 0x56, 0x6B, 0x4D, 0x54, 0x59, 0x77, 0x4E, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x79, 0x31, 0x54, 0x5A, 0x57, 0x4E, 0x30, 0x61, 0x57, 0x64, 0x76, 0x49, 0x46, 0x42, 0x31, 0x59, 0x6D, 0x78, 0x70, 0x59, 0x79, 0x42, ++ 0x54, 0x5A, 0x58, 0x4A, 0x32, 0x0A, 0x5A, 0x58, 0x49, 0x67, 0x51, 0x58, 0x56, 0x30, 0x61, 0x47, 0x56, 0x75, 0x64, 0x47, 0x6C, 0x6A, 0x59, 0x58, 0x52, 0x70, 0x62, 0x32, 0x34, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x46, 0x4E, 0x44, ++ 0x59, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x6A, 0x45, 0x77, 0x4D, 0x7A, 0x49, 0x79, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x57, 0x68, 0x63, 0x4E, 0x4E, 0x44, 0x59, 0x77, 0x4D, 0x7A, 0x49, 0x78, 0x4D, 0x6A, 0x4D, 0x31, 0x4F, 0x54, ++ 0x55, 0x35, 0x0A, 0x57, 0x6A, 0x42, 0x66, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x48, 0x51, 0x6A, 0x45, 0x59, 0x4D, 0x42, 0x59, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x50, 0x55, ++ 0x32, 0x56, 0x6A, 0x64, 0x47, 0x6C, 0x6E, 0x62, 0x79, 0x42, 0x4D, 0x61, 0x57, 0x31, 0x70, 0x64, 0x47, 0x56, 0x6B, 0x4D, 0x54, 0x59, 0x77, 0x4E, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x79, 0x31, 0x54, 0x5A, 0x57, 0x4E, 0x30, 0x0A, ++ 0x61, 0x57, 0x64, 0x76, 0x49, 0x46, 0x42, 0x31, 0x59, 0x6D, 0x78, 0x70, 0x59, 0x79, 0x42, 0x54, 0x5A, 0x58, 0x4A, 0x32, 0x5A, 0x58, 0x49, 0x67, 0x51, 0x58, 0x56, 0x30, 0x61, 0x47, 0x56, 0x75, 0x64, 0x47, 0x6C, 0x6A, 0x59, 0x58, 0x52, 0x70, ++ 0x62, 0x32, 0x34, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x46, 0x4E, 0x44, 0x59, 0x77, 0x64, 0x6A, 0x41, 0x51, 0x42, 0x67, 0x63, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x49, 0x42, 0x42, 0x67, 0x55, 0x72, 0x0A, 0x67, 0x51, 0x51, ++ 0x41, 0x49, 0x67, 0x4E, 0x69, 0x41, 0x41, 0x52, 0x32, 0x2B, 0x70, 0x6D, 0x70, 0x62, 0x69, 0x44, 0x74, 0x2B, 0x64, 0x64, 0x33, 0x34, 0x77, 0x63, 0x37, 0x71, 0x4E, 0x73, 0x39, 0x58, 0x7A, 0x6A, 0x6F, 0x71, 0x31, 0x57, 0x6D, 0x56, 0x6B, 0x2F, ++ 0x57, 0x53, 0x4F, 0x72, 0x73, 0x66, 0x79, 0x32, 0x71, 0x77, 0x37, 0x4C, 0x46, 0x65, 0x65, 0x79, 0x5A, 0x59, 0x58, 0x38, 0x51, 0x65, 0x63, 0x63, 0x43, 0x57, 0x76, 0x6B, 0x45, 0x4E, 0x2F, 0x55, 0x30, 0x0A, 0x4E, 0x53, 0x74, 0x33, 0x7A, 0x6E, ++ 0x38, 0x67, 0x6A, 0x31, 0x4B, 0x6A, 0x41, 0x49, 0x6E, 0x73, 0x31, 0x61, 0x65, 0x69, 0x62, 0x56, 0x76, 0x6A, 0x53, 0x35, 0x4B, 0x54, 0x6F, 0x49, 0x44, 0x31, 0x41, 0x5A, 0x54, 0x63, 0x38, 0x47, 0x67, 0x48, 0x48, 0x73, 0x33, 0x75, 0x2F, 0x69, ++ 0x56, 0x53, 0x74, 0x53, 0x42, 0x44, 0x48, 0x42, 0x76, 0x2B, 0x36, 0x78, 0x6E, 0x4F, 0x51, 0x36, 0x4F, 0x6A, 0x51, 0x6A, 0x42, 0x41, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x0A, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x54, 0x52, 0x49, ++ 0x74, 0x70, 0x4D, 0x57, 0x66, 0x46, 0x4C, 0x58, 0x79, 0x59, 0x34, 0x71, 0x70, 0x33, 0x57, 0x37, 0x75, 0x73, 0x4E, 0x77, 0x2F, 0x75, 0x70, 0x59, 0x54, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, ++ 0x41, 0x4D, 0x43, 0x41, 0x59, 0x59, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x0A, 0x2F, 0x7A, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, ++ 0x50, 0x51, 0x51, 0x44, 0x41, 0x77, 0x4E, 0x6E, 0x41, 0x44, 0x42, 0x6B, 0x41, 0x6A, 0x41, 0x6E, 0x37, 0x71, 0x52, 0x61, 0x71, 0x43, 0x47, 0x37, 0x36, 0x55, 0x65, 0x58, 0x6C, 0x49, 0x6D, 0x6C, 0x64, 0x43, 0x42, 0x74, 0x65, 0x55, 0x2F, 0x49, ++ 0x76, 0x5A, 0x4E, 0x65, 0x57, 0x42, 0x6A, 0x37, 0x4C, 0x52, 0x6F, 0x41, 0x61, 0x73, 0x6D, 0x34, 0x50, 0x64, 0x43, 0x6B, 0x54, 0x30, 0x52, 0x48, 0x0A, 0x6C, 0x41, 0x46, 0x57, 0x6F, 0x76, 0x67, 0x7A, 0x4A, 0x51, 0x78, 0x43, 0x33, 0x36, 0x6F, ++ 0x43, 0x4D, 0x42, 0x33, 0x71, 0x34, 0x53, 0x36, 0x49, 0x4C, 0x75, 0x48, 0x35, 0x70, 0x78, 0x30, 0x43, 0x4D, 0x6B, 0x37, 0x79, 0x6E, 0x32, 0x78, 0x56, 0x64, 0x4F, 0x4F, 0x75, 0x72, 0x76, 0x75, 0x6C, 0x47, 0x75, 0x37, 0x74, 0x30, 0x76, 0x7A, ++ 0x43, 0x41, 0x78, 0x48, 0x72, 0x52, 0x56, 0x78, 0x67, 0x45, 0x44, 0x31, 0x63, 0x66, 0x35, 0x6B, 0x44, 0x57, 0x32, 0x31, 0x55, 0x0A, 0x53, 0x41, 0x47, 0x4B, 0x63, 0x77, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, ++ 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, ++ 0x41, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x34, 0x36, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, ++ 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x69, 0x6A, 0x43, 0x43, 0x41, 0x33, 0x4B, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x64, 0x59, ++ 0x33, 0x39, 0x69, 0x36, 0x35, 0x38, 0x42, 0x77, 0x44, 0x36, 0x71, 0x53, 0x57, 0x6E, 0x34, 0x63, 0x65, 0x74, 0x46, 0x44, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x77, 0x46, 0x41, 0x44, ++ 0x42, 0x66, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x0A, 0x45, 0x77, 0x4A, 0x48, 0x51, 0x6A, 0x45, 0x59, 0x4D, 0x42, 0x59, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x50, 0x55, 0x32, 0x56, 0x6A, 0x64, ++ 0x47, 0x6C, 0x6E, 0x62, 0x79, 0x42, 0x4D, 0x61, 0x57, 0x31, 0x70, 0x64, 0x47, 0x56, 0x6B, 0x4D, 0x54, 0x59, 0x77, 0x4E, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x79, 0x31, 0x54, 0x5A, 0x57, 0x4E, 0x30, 0x61, 0x57, 0x64, 0x76, 0x49, ++ 0x46, 0x42, 0x31, 0x59, 0x6D, 0x78, 0x70, 0x59, 0x79, 0x42, 0x54, 0x0A, 0x5A, 0x58, 0x4A, 0x32, 0x5A, 0x58, 0x49, 0x67, 0x51, 0x58, 0x56, 0x30, 0x61, 0x47, 0x56, 0x75, 0x64, 0x47, 0x6C, 0x6A, 0x59, 0x58, 0x52, 0x70, 0x62, 0x32, 0x34, 0x67, ++ 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x53, 0x4E, 0x44, 0x59, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x6A, 0x45, 0x77, 0x4D, 0x7A, 0x49, 0x79, 0x4D, 0x44, 0x41, 0x77, 0x4D, 0x44, 0x41, 0x77, 0x57, 0x68, 0x63, 0x4E, 0x4E, 0x44, 0x59, 0x77, ++ 0x4D, 0x7A, 0x49, 0x78, 0x4D, 0x6A, 0x4D, 0x31, 0x0A, 0x4F, 0x54, 0x55, 0x35, 0x57, 0x6A, 0x42, 0x66, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x48, 0x51, 0x6A, 0x45, 0x59, 0x4D, 0x42, 0x59, ++ 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x50, 0x55, 0x32, 0x56, 0x6A, 0x64, 0x47, 0x6C, 0x6E, 0x62, 0x79, 0x42, 0x4D, 0x61, 0x57, 0x31, 0x70, 0x64, 0x47, 0x56, 0x6B, 0x4D, 0x54, 0x59, 0x77, 0x4E, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, ++ 0x44, 0x45, 0x79, 0x31, 0x54, 0x0A, 0x5A, 0x57, 0x4E, 0x30, 0x61, 0x57, 0x64, 0x76, 0x49, 0x46, 0x42, 0x31, 0x59, 0x6D, 0x78, 0x70, 0x59, 0x79, 0x42, 0x54, 0x5A, 0x58, 0x4A, 0x32, 0x5A, 0x58, 0x49, 0x67, 0x51, 0x58, 0x56, 0x30, 0x61, 0x47, ++ 0x56, 0x75, 0x64, 0x47, 0x6C, 0x6A, 0x59, 0x58, 0x52, 0x70, 0x62, 0x32, 0x34, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x53, 0x4E, 0x44, 0x59, 0x77, 0x67, 0x67, 0x49, 0x69, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, ++ 0x62, 0x33, 0x0A, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x49, 0x4B, 0x41, 0x6F, 0x49, 0x43, 0x41, 0x51, 0x43, 0x54, 0x76, 0x74, 0x55, 0x32, 0x55, 0x6E, 0x58, 0x59, 0x41, ++ 0x53, 0x4F, 0x67, 0x48, 0x45, 0x64, 0x43, 0x53, 0x65, 0x35, 0x6A, 0x74, 0x72, 0x63, 0x68, 0x2F, 0x63, 0x53, 0x56, 0x31, 0x55, 0x67, 0x72, 0x4A, 0x6E, 0x77, 0x55, 0x55, 0x78, 0x44, 0x61, 0x65, 0x66, 0x30, 0x72, 0x74, 0x79, 0x32, 0x6B, 0x0A, ++ 0x31, 0x43, 0x7A, 0x36, 0x36, 0x6A, 0x4C, 0x64, 0x53, 0x63, 0x4B, 0x35, 0x76, 0x51, 0x39, 0x49, 0x50, 0x58, 0x74, 0x61, 0x6D, 0x46, 0x53, 0x76, 0x6E, 0x6C, 0x30, 0x78, 0x64, 0x45, 0x38, 0x48, 0x2F, 0x46, 0x41, 0x68, 0x33, 0x61, 0x54, 0x50, ++ 0x61, 0x45, 0x38, 0x62, 0x45, 0x6D, 0x4E, 0x74, 0x4A, 0x5A, 0x6C, 0x4D, 0x4B, 0x70, 0x6E, 0x7A, 0x53, 0x44, 0x42, 0x68, 0x2B, 0x6F, 0x46, 0x38, 0x48, 0x71, 0x63, 0x49, 0x53, 0x74, 0x77, 0x2B, 0x4B, 0x78, 0x77, 0x66, 0x0A, 0x47, 0x45, 0x78, ++ 0x78, 0x71, 0x6A, 0x57, 0x4D, 0x72, 0x66, 0x68, 0x75, 0x36, 0x44, 0x74, 0x4B, 0x32, 0x65, 0x57, 0x55, 0x41, 0x74, 0x61, 0x4A, 0x68, 0x42, 0x4F, 0x71, 0x62, 0x63, 0x68, 0x50, 0x4D, 0x38, 0x78, 0x51, 0x6C, 0x6A, 0x65, 0x53, 0x4D, 0x39, 0x78, ++ 0x66, 0x69, 0x4F, 0x65, 0x66, 0x56, 0x4E, 0x6C, 0x49, 0x38, 0x4A, 0x68, 0x44, 0x31, 0x6D, 0x62, 0x39, 0x6E, 0x78, 0x63, 0x34, 0x51, 0x38, 0x55, 0x42, 0x55, 0x51, 0x76, 0x58, 0x34, 0x79, 0x4D, 0x50, 0x0A, 0x46, 0x46, 0x31, 0x62, 0x46, 0x4F, ++ 0x64, 0x4C, 0x76, 0x74, 0x33, 0x30, 0x79, 0x4E, 0x6F, 0x44, 0x4E, 0x39, 0x48, 0x57, 0x4F, 0x61, 0x45, 0x68, 0x55, 0x54, 0x43, 0x44, 0x73, 0x47, 0x33, 0x58, 0x4D, 0x45, 0x36, 0x57, 0x57, 0x35, 0x48, 0x77, 0x63, 0x43, 0x53, 0x72, 0x76, 0x30, ++ 0x57, 0x42, 0x5A, 0x45, 0x4D, 0x4E, 0x76, 0x53, 0x45, 0x36, 0x4C, 0x7A, 0x7A, 0x70, 0x6E, 0x67, 0x33, 0x4C, 0x49, 0x4C, 0x56, 0x43, 0x4A, 0x38, 0x7A, 0x61, 0x62, 0x35, 0x76, 0x75, 0x0A, 0x5A, 0x44, 0x43, 0x51, 0x4F, 0x63, 0x32, 0x54, 0x5A, ++ 0x59, 0x45, 0x68, 0x4D, 0x62, 0x55, 0x6A, 0x55, 0x44, 0x4D, 0x33, 0x49, 0x75, 0x4D, 0x34, 0x37, 0x66, 0x67, 0x78, 0x4D, 0x4D, 0x78, 0x46, 0x2F, 0x6D, 0x4C, 0x35, 0x30, 0x56, 0x30, 0x79, 0x65, 0x55, 0x4B, 0x48, 0x33, 0x32, 0x72, 0x4D, 0x56, ++ 0x68, 0x6C, 0x41, 0x54, 0x63, 0x36, 0x71, 0x75, 0x2F, 0x6D, 0x31, 0x64, 0x6B, 0x6D, 0x55, 0x38, 0x53, 0x66, 0x34, 0x6B, 0x61, 0x57, 0x44, 0x35, 0x51, 0x61, 0x7A, 0x0A, 0x59, 0x77, 0x36, 0x41, 0x33, 0x4F, 0x41, 0x53, 0x56, 0x59, 0x43, 0x6D, ++ 0x4F, 0x32, 0x61, 0x30, 0x4F, 0x59, 0x63, 0x74, 0x79, 0x50, 0x44, 0x51, 0x30, 0x52, 0x54, 0x70, 0x35, 0x41, 0x31, 0x4E, 0x44, 0x76, 0x5A, 0x64, 0x56, 0x33, 0x4C, 0x46, 0x4F, 0x78, 0x78, 0x48, 0x56, 0x70, 0x33, 0x69, 0x31, 0x66, 0x75, 0x42, ++ 0x59, 0x59, 0x7A, 0x4D, 0x54, 0x59, 0x43, 0x51, 0x4E, 0x46, 0x75, 0x33, 0x31, 0x78, 0x52, 0x31, 0x33, 0x4E, 0x67, 0x45, 0x53, 0x4A, 0x2F, 0x41, 0x0A, 0x77, 0x53, 0x69, 0x49, 0x74, 0x4F, 0x6B, 0x63, 0x79, 0x71, 0x65, 0x78, 0x38, 0x56, 0x61, ++ 0x33, 0x65, 0x30, 0x6C, 0x4D, 0x57, 0x65, 0x55, 0x67, 0x46, 0x61, 0x69, 0x45, 0x41, 0x69, 0x6E, 0x36, 0x4F, 0x4A, 0x52, 0x70, 0x6D, 0x6B, 0x6B, 0x47, 0x6A, 0x38, 0x30, 0x66, 0x65, 0x52, 0x51, 0x58, 0x45, 0x67, 0x79, 0x44, 0x65, 0x74, 0x34, ++ 0x66, 0x73, 0x5A, 0x66, 0x75, 0x2B, 0x5A, 0x64, 0x34, 0x4B, 0x4B, 0x54, 0x49, 0x52, 0x4A, 0x4C, 0x70, 0x66, 0x53, 0x59, 0x46, 0x0A, 0x70, 0x6C, 0x68, 0x79, 0x6D, 0x33, 0x6B, 0x54, 0x32, 0x42, 0x46, 0x66, 0x72, 0x73, 0x55, 0x34, 0x59, 0x6A, ++ 0x52, 0x6F, 0x73, 0x6F, 0x59, 0x77, 0x6A, 0x76, 0x69, 0x51, 0x59, 0x5A, 0x34, 0x79, 0x62, 0x50, 0x55, 0x48, 0x4E, 0x73, 0x32, 0x69, 0x54, 0x47, 0x37, 0x73, 0x69, 0x6A, 0x62, 0x74, 0x38, 0x75, 0x61, 0x5A, 0x46, 0x55, 0x52, 0x77, 0x77, 0x33, ++ 0x79, 0x38, 0x6E, 0x44, 0x6E, 0x41, 0x74, 0x4F, 0x46, 0x72, 0x39, 0x34, 0x4D, 0x6C, 0x49, 0x31, 0x66, 0x5A, 0x0A, 0x45, 0x6F, 0x44, 0x6C, 0x53, 0x66, 0x42, 0x31, 0x44, 0x2B, 0x2B, 0x4E, 0x36, 0x78, 0x79, 0x62, 0x56, 0x43, 0x69, 0x30, 0x49, ++ 0x54, 0x7A, 0x38, 0x66, 0x41, 0x72, 0x2F, 0x37, 0x33, 0x74, 0x72, 0x64, 0x66, 0x2B, 0x4C, 0x48, 0x61, 0x41, 0x5A, 0x42, 0x61, 0x76, 0x36, 0x2B, 0x43, 0x75, 0x42, 0x51, 0x75, 0x67, 0x34, 0x75, 0x72, 0x76, 0x37, 0x71, 0x76, 0x30, 0x39, 0x34, ++ 0x50, 0x50, 0x4B, 0x33, 0x30, 0x36, 0x58, 0x6C, 0x79, 0x6E, 0x74, 0x38, 0x78, 0x68, 0x57, 0x0A, 0x36, 0x61, 0x57, 0x57, 0x72, 0x4C, 0x33, 0x44, 0x6B, 0x4A, 0x69, 0x79, 0x34, 0x50, 0x6D, 0x69, 0x31, 0x4B, 0x5A, 0x48, 0x51, 0x33, 0x78, 0x74, ++ 0x7A, 0x77, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x6F, 0x30, 0x49, 0x77, 0x51, 0x44, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x56, 0x6E, 0x4E, 0x59, 0x5A, 0x4A, 0x58, 0x35, 0x6B, 0x68, 0x71, 0x77, ++ 0x45, 0x69, 0x6F, 0x45, 0x59, 0x6E, 0x6D, 0x68, 0x51, 0x42, 0x57, 0x49, 0x0A, 0x49, 0x55, 0x6B, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x51, 0x44, 0x41, 0x67, 0x47, 0x47, 0x4D, 0x41, 0x38, ++ 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4D, 0x42, 0x51, 0x41, ++ 0x44, 0x67, 0x67, 0x49, 0x42, 0x41, 0x43, 0x39, 0x63, 0x0A, 0x6D, 0x54, 0x7A, 0x38, 0x42, 0x6C, 0x36, 0x4D, 0x6C, 0x43, 0x35, 0x77, 0x36, 0x74, 0x49, 0x79, 0x4D, 0x59, 0x32, 0x30, 0x38, 0x46, 0x48, 0x56, 0x76, 0x41, 0x72, 0x7A, 0x5A, 0x4A, ++ 0x38, 0x48, 0x58, 0x74, 0x58, 0x42, 0x63, 0x32, 0x68, 0x6B, 0x65, 0x71, 0x4B, 0x35, 0x44, 0x75, 0x6A, 0x35, 0x58, 0x59, 0x55, 0x74, 0x71, 0x44, 0x64, 0x46, 0x71, 0x69, 0x6A, 0x30, 0x6C, 0x67, 0x56, 0x51, 0x59, 0x4B, 0x6C, 0x4A, 0x66, 0x70, ++ 0x2F, 0x69, 0x6D, 0x54, 0x59, 0x70, 0x0A, 0x45, 0x30, 0x52, 0x48, 0x61, 0x70, 0x31, 0x56, 0x49, 0x44, 0x7A, 0x59, 0x6D, 0x2F, 0x45, 0x44, 0x4D, 0x72, 0x72, 0x61, 0x51, 0x4B, 0x46, 0x7A, 0x36, 0x6F, 0x4F, 0x68, 0x74, 0x30, 0x53, 0x6D, 0x44, ++ 0x70, 0x6B, 0x42, 0x6D, 0x2B, 0x53, 0x38, 0x66, 0x37, 0x34, 0x54, 0x6C, 0x48, 0x37, 0x4B, 0x70, 0x68, 0x35, 0x32, 0x67, 0x44, 0x59, 0x39, 0x68, 0x41, 0x61, 0x4C, 0x4D, 0x79, 0x5A, 0x6C, 0x62, 0x63, 0x70, 0x2B, 0x6E, 0x76, 0x34, 0x66, 0x6A, ++ 0x46, 0x67, 0x34, 0x0A, 0x65, 0x78, 0x71, 0x44, 0x73, 0x51, 0x2B, 0x38, 0x46, 0x78, 0x47, 0x37, 0x35, 0x67, 0x62, 0x4D, 0x59, 0x2F, 0x71, 0x42, 0x38, 0x6F, 0x46, 0x4D, 0x32, 0x67, 0x73, 0x51, 0x61, 0x36, 0x48, 0x36, 0x31, 0x53, 0x69, 0x6C, ++ 0x7A, 0x77, 0x5A, 0x41, 0x46, 0x76, 0x39, 0x37, 0x66, 0x52, 0x68, 0x65, 0x4F, 0x52, 0x4B, 0x6B, 0x55, 0x35, 0x35, 0x2B, 0x4D, 0x6B, 0x49, 0x51, 0x70, 0x69, 0x47, 0x52, 0x71, 0x52, 0x78, 0x4F, 0x46, 0x33, 0x79, 0x45, 0x76, 0x4A, 0x2B, 0x4D, ++ 0x0A, 0x30, 0x65, 0x6A, 0x66, 0x35, 0x6C, 0x47, 0x35, 0x4E, 0x6B, 0x63, 0x2F, 0x6B, 0x4C, 0x6E, 0x48, 0x76, 0x41, 0x4C, 0x63, 0x57, 0x78, 0x78, 0x50, 0x44, 0x6B, 0x6A, 0x42, 0x4A, 0x59, 0x4F, 0x63, 0x43, 0x6A, 0x2B, 0x65, 0x73, 0x51, 0x4D, ++ 0x7A, 0x45, 0x68, 0x6F, 0x6E, 0x72, 0x50, 0x63, 0x69, 0x62, 0x43, 0x54, 0x52, 0x41, 0x55, 0x48, 0x34, 0x57, 0x41, 0x50, 0x2B, 0x4A, 0x57, 0x67, 0x69, 0x48, 0x35, 0x70, 0x61, 0x50, 0x48, 0x78, 0x73, 0x6E, 0x6E, 0x56, 0x49, 0x0A, 0x38, 0x34, ++ 0x48, 0x78, 0x5A, 0x6D, 0x64, 0x75, 0x54, 0x49, 0x4C, 0x41, 0x37, 0x72, 0x70, 0x58, 0x44, 0x68, 0x6A, 0x76, 0x4C, 0x70, 0x72, 0x33, 0x45, 0x74, 0x69, 0x67, 0x61, 0x2B, 0x6B, 0x46, 0x70, 0x61, 0x48, 0x70, 0x61, 0x50, 0x69, 0x38, 0x54, 0x44, ++ 0x38, 0x53, 0x48, 0x6B, 0x58, 0x6F, 0x55, 0x73, 0x43, 0x6A, 0x76, 0x78, 0x49, 0x6E, 0x65, 0x62, 0x6E, 0x4D, 0x4D, 0x54, 0x7A, 0x44, 0x39, 0x6A, 0x6F, 0x69, 0x46, 0x67, 0x4F, 0x67, 0x79, 0x59, 0x39, 0x6D, 0x0A, 0x70, 0x46, 0x75, 0x69, 0x54, ++ 0x64, 0x61, 0x42, 0x4A, 0x51, 0x62, 0x70, 0x64, 0x71, 0x51, 0x41, 0x43, 0x6A, 0x37, 0x4C, 0x7A, 0x54, 0x57, 0x62, 0x34, 0x4F, 0x45, 0x34, 0x79, 0x32, 0x42, 0x54, 0x68, 0x69, 0x68, 0x43, 0x51, 0x52, 0x78, 0x45, 0x56, 0x2B, 0x69, 0x6F, 0x72, ++ 0x61, 0x74, 0x46, 0x34, 0x79, 0x55, 0x51, 0x76, 0x4E, 0x73, 0x2B, 0x5A, 0x55, 0x48, 0x37, 0x47, 0x36, 0x61, 0x58, 0x44, 0x2B, 0x75, 0x35, 0x64, 0x48, 0x6E, 0x35, 0x48, 0x72, 0x77, 0x64, 0x0A, 0x56, 0x77, 0x31, 0x48, 0x72, 0x38, 0x4D, 0x76, ++ 0x6E, 0x34, 0x64, 0x47, 0x70, 0x2B, 0x73, 0x6D, 0x57, 0x67, 0x39, 0x57, 0x59, 0x37, 0x56, 0x69, 0x59, 0x47, 0x34, 0x41, 0x2B, 0x2B, 0x4D, 0x6E, 0x45, 0x53, 0x4C, 0x6E, 0x2F, 0x70, 0x6D, 0x50, 0x4E, 0x50, 0x57, 0x35, 0x36, 0x4D, 0x4F, 0x52, ++ 0x63, 0x72, 0x33, 0x59, 0x77, 0x78, 0x36, 0x35, 0x4C, 0x76, 0x4B, 0x52, 0x52, 0x46, 0x48, 0x51, 0x56, 0x38, 0x30, 0x4D, 0x4E, 0x4E, 0x56, 0x49, 0x49, 0x62, 0x2F, 0x62, 0x0A, 0x45, 0x2F, 0x46, 0x6D, 0x4A, 0x55, 0x4E, 0x53, 0x30, 0x6E, 0x41, ++ 0x69, 0x4E, 0x73, 0x32, 0x66, 0x78, 0x42, 0x78, 0x31, 0x49, 0x4B, 0x31, 0x6A, 0x63, 0x6D, 0x4D, 0x47, 0x44, 0x77, 0x34, 0x6E, 0x7A, 0x74, 0x4A, 0x71, 0x44, 0x62, 0x79, 0x31, 0x4F, 0x52, 0x72, 0x70, 0x30, 0x58, 0x5A, 0x36, 0x30, 0x56, 0x7A, ++ 0x6B, 0x35, 0x30, 0x6C, 0x4A, 0x4C, 0x56, 0x55, 0x33, 0x61, 0x50, 0x41, 0x61, 0x4F, 0x70, 0x67, 0x2B, 0x56, 0x42, 0x65, 0x48, 0x56, 0x4F, 0x6D, 0x6D, 0x0A, 0x4A, 0x31, 0x43, 0x4A, 0x65, 0x79, 0x41, 0x76, 0x50, 0x2F, 0x2B, 0x2F, 0x6F, 0x59, ++ 0x74, 0x4B, 0x52, 0x35, 0x6A, 0x2F, 0x4B, 0x33, 0x74, 0x4A, 0x50, 0x73, 0x4D, 0x70, 0x52, 0x6D, 0x41, 0x59, 0x51, 0x71, 0x73, 0x7A, 0x4B, 0x62, 0x72, 0x41, 0x4B, 0x62, 0x6B, 0x54, 0x69, 0x64, 0x4F, 0x49, 0x69, 0x6A, 0x6C, 0x42, 0x4F, 0x38, ++ 0x6E, 0x39, 0x70, 0x75, 0x30, 0x66, 0x39, 0x47, 0x42, 0x6A, 0x33, 0x39, 0x49, 0x74, 0x56, 0x51, 0x47, 0x4C, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, ++ 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x32, 0x32, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, ++ 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x69, 0x54, 0x43, 0x43, 0x41, 0x33, 0x47, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x62, 0x37, 0x37, 0x61, 0x72, 0x58, 0x4F, 0x39, ++ 0x43, 0x45, 0x44, 0x69, 0x69, 0x30, 0x32, 0x2B, 0x31, 0x50, 0x64, 0x62, 0x6B, 0x54, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x44, 0x42, 0x4F, 0x4D, 0x51, 0x73, 0x77, ++ 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x0A, 0x45, 0x77, 0x4A, 0x56, 0x55, 0x7A, 0x45, 0x59, 0x4D, 0x42, 0x59, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, 0x50, 0x55, 0x31, 0x4E, 0x4D, 0x49, 0x45, 0x4E, 0x76, 0x63, 0x6E, 0x42, ++ 0x76, 0x63, 0x6D, 0x46, 0x30, 0x61, 0x57, 0x39, 0x75, 0x4D, 0x53, 0x55, 0x77, 0x49, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x44, 0x42, 0x78, 0x54, 0x55, 0x30, 0x77, 0x75, 0x59, 0x32, 0x39, 0x74, 0x49, 0x46, 0x52, 0x4D, 0x55, 0x79, 0x42, ++ 0x53, 0x55, 0x30, 0x45, 0x67, 0x0A, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x51, 0x53, 0x41, 0x79, 0x4D, 0x44, 0x49, 0x79, 0x4D, 0x42, 0x34, 0x58, 0x44, 0x54, 0x49, 0x79, 0x4D, 0x44, 0x67, 0x79, 0x4E, 0x54, 0x45, 0x32, 0x4D, 0x7A, ++ 0x51, 0x79, 0x4D, 0x6C, 0x6F, 0x58, 0x44, 0x54, 0x51, 0x32, 0x4D, 0x44, 0x67, 0x78, 0x4F, 0x54, 0x45, 0x32, 0x4D, 0x7A, 0x51, 0x79, 0x4D, 0x56, 0x6F, 0x77, 0x54, 0x6A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, ++ 0x4D, 0x43, 0x0A, 0x56, 0x56, 0x4D, 0x78, 0x47, 0x44, 0x41, 0x57, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x4D, 0x44, 0x31, 0x4E, 0x54, 0x54, 0x43, 0x42, 0x44, 0x62, 0x33, 0x4A, 0x77, 0x62, 0x33, 0x4A, 0x68, 0x64, 0x47, 0x6C, 0x76, 0x62, ++ 0x6A, 0x45, 0x6C, 0x4D, 0x43, 0x4D, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x77, 0x77, 0x63, 0x55, 0x31, 0x4E, 0x4D, 0x4C, 0x6D, 0x4E, 0x76, 0x62, 0x53, 0x42, 0x55, 0x54, 0x46, 0x4D, 0x67, 0x55, 0x6C, 0x4E, 0x42, 0x49, 0x46, 0x4A, 0x76, 0x0A, ++ 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x67, 0x4D, 0x6A, 0x41, 0x79, 0x4D, 0x6A, 0x43, 0x43, 0x41, 0x69, 0x49, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, ++ 0x67, 0x67, 0x49, 0x50, 0x41, 0x44, 0x43, 0x43, 0x41, 0x67, 0x6F, 0x43, 0x67, 0x67, 0x49, 0x42, 0x41, 0x4E, 0x43, 0x6B, 0x43, 0x58, 0x4A, 0x50, 0x51, 0x49, 0x67, 0x53, 0x59, 0x54, 0x34, 0x31, 0x49, 0x35, 0x37, 0x75, 0x0A, 0x39, 0x6E, 0x54, ++ 0x50, 0x4C, 0x33, 0x74, 0x59, 0x50, 0x63, 0x34, 0x38, 0x44, 0x52, 0x41, 0x6F, 0x6B, 0x43, 0x2B, 0x58, 0x39, 0x34, 0x78, 0x49, 0x32, 0x4B, 0x44, 0x59, 0x4A, 0x62, 0x46, 0x4D, 0x73, 0x42, 0x46, 0x4D, 0x46, 0x33, 0x4E, 0x51, 0x30, 0x43, 0x4A, ++ 0x4B, 0x59, 0x37, 0x75, 0x42, 0x30, 0x79, 0x6C, 0x75, 0x31, 0x62, 0x55, 0x4A, 0x50, 0x69, 0x59, 0x59, 0x66, 0x37, 0x49, 0x53, 0x66, 0x35, 0x4F, 0x59, 0x74, 0x36, 0x2F, 0x77, 0x4E, 0x72, 0x2F, 0x79, 0x0A, 0x37, 0x68, 0x69, 0x65, 0x6E, 0x44, ++ 0x74, 0x53, 0x78, 0x55, 0x63, 0x5A, 0x58, 0x58, 0x54, 0x7A, 0x5A, 0x47, 0x62, 0x56, 0x58, 0x63, 0x64, 0x6F, 0x74, 0x4C, 0x38, 0x62, 0x48, 0x41, 0x61, 0x6A, 0x76, 0x49, 0x39, 0x41, 0x49, 0x37, 0x59, 0x65, 0x78, 0x6F, 0x53, 0x39, 0x55, 0x63, ++ 0x51, 0x62, 0x4F, 0x63, 0x47, 0x56, 0x30, 0x69, 0x6E, 0x73, 0x53, 0x36, 0x35, 0x37, 0x4C, 0x62, 0x38, 0x35, 0x2F, 0x62, 0x52, 0x69, 0x33, 0x70, 0x5A, 0x37, 0x51, 0x63, 0x61, 0x63, 0x0A, 0x6F, 0x4F, 0x41, 0x47, 0x63, 0x76, 0x76, 0x77, 0x42, ++ 0x35, 0x63, 0x4A, 0x4F, 0x59, 0x46, 0x30, 0x72, 0x2F, 0x63, 0x30, 0x57, 0x52, 0x46, 0x58, 0x43, 0x73, 0x4A, 0x62, 0x77, 0x53, 0x54, 0x30, 0x4D, 0x58, 0x4D, 0x77, 0x67, 0x73, 0x61, 0x64, 0x75, 0x67, 0x4C, 0x33, 0x50, 0x6E, 0x78, 0x45, 0x58, ++ 0x34, 0x4D, 0x4E, 0x38, 0x2F, 0x48, 0x64, 0x49, 0x47, 0x6B, 0x57, 0x43, 0x56, 0x44, 0x69, 0x31, 0x46, 0x57, 0x32, 0x34, 0x49, 0x42, 0x79, 0x64, 0x6D, 0x35, 0x4D, 0x0A, 0x52, 0x37, 0x64, 0x31, 0x56, 0x56, 0x6D, 0x30, 0x55, 0x33, 0x54, 0x5A, ++ 0x6C, 0x4D, 0x5A, 0x42, 0x72, 0x56, 0x69, 0x4B, 0x4D, 0x57, 0x59, 0x50, 0x48, 0x71, 0x49, 0x62, 0x4B, 0x55, 0x42, 0x4F, 0x4C, 0x39, 0x39, 0x37, 0x35, 0x68, 0x59, 0x73, 0x4C, 0x66, 0x79, 0x2F, 0x37, 0x50, 0x4F, 0x30, 0x2B, 0x72, 0x34, 0x59, ++ 0x39, 0x70, 0x74, 0x4A, 0x31, 0x4F, 0x34, 0x46, 0x62, 0x74, 0x6B, 0x30, 0x38, 0x35, 0x7A, 0x78, 0x37, 0x41, 0x47, 0x4C, 0x30, 0x53, 0x44, 0x47, 0x0A, 0x44, 0x36, 0x43, 0x31, 0x76, 0x42, 0x64, 0x4F, 0x53, 0x48, 0x74, 0x52, 0x77, 0x76, 0x7A, ++ 0x70, 0x58, 0x47, 0x6B, 0x33, 0x52, 0x32, 0x61, 0x7A, 0x61, 0x50, 0x67, 0x56, 0x4B, 0x50, 0x43, 0x35, 0x30, 0x36, 0x51, 0x56, 0x7A, 0x46, 0x70, 0x50, 0x75, 0x6C, 0x4A, 0x77, 0x6F, 0x78, 0x4A, 0x46, 0x33, 0x63, 0x61, 0x36, 0x54, 0x76, 0x76, ++ 0x43, 0x30, 0x50, 0x65, 0x6F, 0x55, 0x69, 0x64, 0x74, 0x62, 0x6E, 0x6D, 0x31, 0x6A, 0x50, 0x78, 0x37, 0x6A, 0x4D, 0x45, 0x57, 0x0A, 0x54, 0x4F, 0x36, 0x41, 0x66, 0x37, 0x37, 0x77, 0x64, 0x72, 0x35, 0x42, 0x55, 0x78, 0x49, 0x7A, 0x72, 0x6C, ++ 0x6F, 0x34, 0x51, 0x71, 0x76, 0x58, 0x44, 0x7A, 0x35, 0x42, 0x6A, 0x58, 0x59, 0x48, 0x4D, 0x74, 0x57, 0x72, 0x69, 0x66, 0x5A, 0x4F, 0x5A, 0x39, 0x6D, 0x78, 0x51, 0x6E, 0x55, 0x6A, 0x62, 0x76, 0x50, 0x4E, 0x51, 0x72, 0x4C, 0x38, 0x56, 0x66, ++ 0x56, 0x54, 0x68, 0x78, 0x63, 0x37, 0x77, 0x44, 0x4E, 0x59, 0x38, 0x56, 0x4C, 0x53, 0x2B, 0x59, 0x43, 0x6B, 0x0A, 0x38, 0x4F, 0x6A, 0x77, 0x4F, 0x34, 0x73, 0x34, 0x7A, 0x4B, 0x54, 0x47, 0x6B, 0x48, 0x38, 0x50, 0x6E, 0x50, 0x32, 0x4C, 0x30, ++ 0x61, 0x50, 0x50, 0x32, 0x6F, 0x4F, 0x6E, 0x61, 0x63, 0x6C, 0x51, 0x4E, 0x74, 0x56, 0x63, 0x42, 0x64, 0x49, 0x4B, 0x51, 0x58, 0x54, 0x62, 0x59, 0x78, 0x45, 0x33, 0x77, 0x61, 0x57, 0x67, 0x6C, 0x6B, 0x73, 0x65, 0x6A, 0x42, 0x59, 0x53, 0x64, ++ 0x36, 0x36, 0x55, 0x4E, 0x48, 0x73, 0x65, 0x66, 0x38, 0x4A, 0x6D, 0x41, 0x4F, 0x53, 0x71, 0x0A, 0x67, 0x2B, 0x71, 0x4B, 0x6B, 0x4B, 0x33, 0x4F, 0x4E, 0x6B, 0x52, 0x4E, 0x30, 0x56, 0x48, 0x70, 0x76, 0x42, 0x2F, 0x7A, 0x61, 0x67, 0x58, 0x39, ++ 0x77, 0x48, 0x51, 0x66, 0x4A, 0x52, 0x6C, 0x41, 0x55, 0x57, 0x37, 0x71, 0x67, 0x6C, 0x46, 0x41, 0x33, 0x35, 0x75, 0x35, 0x43, 0x43, 0x6F, 0x47, 0x41, 0x74, 0x55, 0x6A, 0x48, 0x42, 0x50, 0x57, 0x36, 0x64, 0x76, 0x62, 0x78, 0x72, 0x42, 0x36, ++ 0x79, 0x33, 0x73, 0x6E, 0x6D, 0x2F, 0x76, 0x67, 0x31, 0x55, 0x59, 0x6B, 0x0A, 0x37, 0x52, 0x42, 0x4C, 0x59, 0x30, 0x75, 0x6C, 0x42, 0x59, 0x2B, 0x36, 0x75, 0x42, 0x30, 0x72, 0x70, 0x76, 0x71, 0x52, 0x34, 0x70, 0x4A, 0x53, 0x76, 0x65, 0x7A, ++ 0x72, 0x5A, 0x35, 0x64, 0x74, 0x6D, 0x69, 0x32, 0x66, 0x67, 0x54, 0x49, 0x46, 0x5A, 0x7A, 0x4C, 0x37, 0x53, 0x41, 0x67, 0x2F, 0x32, 0x53, 0x57, 0x34, 0x42, 0x43, 0x55, 0x76, 0x41, 0x67, 0x4D, 0x42, 0x41, 0x41, 0x47, 0x6A, 0x59, 0x7A, 0x42, ++ 0x68, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x0A, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x48, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x6A, 0x42, 0x42, 0x67, 0x77, 0x46, 0x6F, ++ 0x41, 0x55, 0x2B, 0x79, 0x34, 0x33, 0x37, 0x75, 0x4F, 0x45, 0x65, 0x69, 0x63, 0x75, 0x7A, 0x52, 0x6B, 0x31, 0x73, 0x54, 0x4E, 0x38, 0x2F, 0x39, 0x52, 0x45, 0x51, 0x72, 0x6B, 0x77, 0x48, 0x51, 0x59, 0x44, 0x56, 0x52, 0x30, 0x4F, 0x42, 0x42, ++ 0x59, 0x45, 0x46, 0x50, 0x73, 0x75, 0x0A, 0x4E, 0x2B, 0x37, 0x6A, 0x68, 0x48, 0x6F, 0x6E, 0x4C, 0x73, 0x30, 0x5A, 0x4E, 0x62, 0x45, 0x7A, 0x66, 0x50, 0x2F, 0x55, 0x52, 0x45, 0x4B, 0x35, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, ++ 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x42, 0x68, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x67, 0x45, 0x41, 0x6A, ++ 0x59, 0x6C, 0x74, 0x0A, 0x68, 0x45, 0x55, 0x59, 0x38, 0x55, 0x2B, 0x7A, 0x6F, 0x4F, 0x39, 0x6F, 0x70, 0x4D, 0x41, 0x64, 0x72, 0x44, 0x43, 0x38, 0x5A, 0x32, 0x61, 0x77, 0x6D, 0x73, 0x32, 0x32, 0x71, 0x79, 0x49, 0x5A, 0x5A, 0x74, 0x4D, 0x37, ++ 0x51, 0x62, 0x55, 0x51, 0x6E, 0x52, 0x43, 0x36, 0x63, 0x6D, 0x34, 0x70, 0x4A, 0x43, 0x41, 0x63, 0x41, 0x5A, 0x6C, 0x69, 0x30, 0x35, 0x62, 0x67, 0x34, 0x76, 0x73, 0x4D, 0x51, 0x74, 0x66, 0x68, 0x57, 0x73, 0x53, 0x57, 0x54, 0x56, 0x54, 0x4E, ++ 0x0A, 0x6A, 0x38, 0x70, 0x44, 0x55, 0x2F, 0x30, 0x71, 0x75, 0x4F, 0x72, 0x34, 0x5A, 0x63, 0x6F, 0x42, 0x77, 0x71, 0x31, 0x67, 0x61, 0x41, 0x61, 0x66, 0x4F, 0x52, 0x70, 0x52, 0x32, 0x65, 0x43, 0x4E, 0x4A, 0x76, 0x6B, 0x4C, 0x54, 0x71, 0x56, ++ 0x54, 0x4A, 0x58, 0x6F, 0x6A, 0x70, 0x42, 0x7A, 0x4F, 0x43, 0x42, 0x76, 0x66, 0x52, 0x34, 0x69, 0x79, 0x72, 0x54, 0x37, 0x67, 0x4A, 0x34, 0x65, 0x4C, 0x53, 0x59, 0x77, 0x66, 0x71, 0x55, 0x64, 0x59, 0x65, 0x35, 0x62, 0x79, 0x0A, 0x69, 0x42, ++ 0x30, 0x59, 0x72, 0x72, 0x50, 0x52, 0x70, 0x67, 0x71, 0x55, 0x2B, 0x74, 0x76, 0x54, 0x35, 0x54, 0x67, 0x4B, 0x61, 0x33, 0x6B, 0x53, 0x4D, 0x2F, 0x74, 0x4B, 0x57, 0x54, 0x63, 0x57, 0x51, 0x41, 0x36, 0x37, 0x33, 0x76, 0x57, 0x4A, 0x44, 0x50, ++ 0x46, 0x73, 0x30, 0x2F, 0x64, 0x52, 0x61, 0x31, 0x34, 0x31, 0x39, 0x64, 0x76, 0x41, 0x4A, 0x75, 0x6F, 0x53, 0x63, 0x30, 0x36, 0x70, 0x6B, 0x5A, 0x43, 0x6D, 0x46, 0x38, 0x4E, 0x73, 0x4C, 0x7A, 0x6A, 0x55, 0x0A, 0x6F, 0x33, 0x4B, 0x55, 0x51, ++ 0x79, 0x78, 0x69, 0x34, 0x55, 0x35, 0x63, 0x4D, 0x6A, 0x32, 0x39, 0x54, 0x48, 0x30, 0x5A, 0x52, 0x36, 0x4C, 0x44, 0x53, 0x65, 0x65, 0x57, 0x50, 0x34, 0x2B, 0x61, 0x30, 0x7A, 0x76, 0x6B, 0x45, 0x64, 0x69, 0x4C, 0x41, 0x39, 0x7A, 0x32, 0x74, ++ 0x6D, 0x42, 0x56, 0x47, 0x4B, 0x61, 0x42, 0x55, 0x66, 0x50, 0x68, 0x71, 0x42, 0x56, 0x71, 0x36, 0x2B, 0x41, 0x4C, 0x38, 0x42, 0x51, 0x78, 0x31, 0x72, 0x6D, 0x4D, 0x52, 0x54, 0x71, 0x6F, 0x0A, 0x45, 0x4E, 0x6A, 0x77, 0x75, 0x53, 0x66, 0x72, ++ 0x39, 0x38, 0x74, 0x36, 0x37, 0x77, 0x56, 0x79, 0x6C, 0x72, 0x58, 0x45, 0x6A, 0x35, 0x5A, 0x7A, 0x78, 0x4F, 0x68, 0x57, 0x63, 0x35, 0x79, 0x38, 0x61, 0x56, 0x46, 0x6A, 0x76, 0x4F, 0x39, 0x6E, 0x48, 0x45, 0x4D, 0x61, 0x58, 0x33, 0x63, 0x5A, ++ 0x48, 0x78, 0x6A, 0x34, 0x48, 0x43, 0x55, 0x70, 0x2B, 0x55, 0x6D, 0x5A, 0x4B, 0x62, 0x61, 0x53, 0x50, 0x61, 0x4B, 0x44, 0x4E, 0x37, 0x45, 0x67, 0x6B, 0x61, 0x69, 0x62, 0x0A, 0x4D, 0x4F, 0x6C, 0x71, 0x62, 0x4C, 0x51, 0x6A, 0x6B, 0x32, 0x55, ++ 0x45, 0x71, 0x78, 0x48, 0x7A, 0x44, 0x68, 0x31, 0x54, 0x4A, 0x45, 0x6C, 0x54, 0x48, 0x61, 0x45, 0x2F, 0x6E, 0x55, 0x69, 0x53, 0x45, 0x65, 0x4A, 0x39, 0x44, 0x55, 0x2F, 0x31, 0x31, 0x37, 0x32, 0x69, 0x57, 0x44, 0x35, 0x34, 0x6E, 0x52, 0x34, ++ 0x66, 0x4B, 0x2F, 0x34, 0x68, 0x75, 0x78, 0x6F, 0x54, 0x74, 0x72, 0x45, 0x6F, 0x5A, 0x50, 0x32, 0x77, 0x41, 0x67, 0x44, 0x48, 0x62, 0x49, 0x43, 0x69, 0x0A, 0x76, 0x52, 0x5A, 0x51, 0x49, 0x41, 0x39, 0x79, 0x67, 0x56, 0x2F, 0x4D, 0x6C, 0x50, ++ 0x2B, 0x37, 0x6D, 0x65, 0x61, 0x36, 0x6B, 0x4D, 0x76, 0x71, 0x2B, 0x63, 0x59, 0x4D, 0x77, 0x71, 0x37, 0x46, 0x47, 0x63, 0x34, 0x7A, 0x6F, 0x57, 0x74, 0x63, 0x75, 0x33, 0x35, 0x38, 0x4E, 0x46, 0x63, 0x58, 0x72, 0x66, 0x41, 0x2F, 0x72, 0x73, ++ 0x33, 0x71, 0x72, 0x35, 0x6E, 0x73, 0x4C, 0x46, 0x52, 0x2B, 0x6A, 0x4D, 0x34, 0x75, 0x45, 0x6C, 0x5A, 0x49, 0x37, 0x78, 0x63, 0x37, 0x0A, 0x50, 0x30, 0x70, 0x65, 0x59, 0x4E, 0x4C, 0x63, 0x64, 0x44, 0x61, 0x38, 0x70, 0x55, 0x4E, 0x6A, 0x79, ++ 0x77, 0x39, 0x62, 0x6F, 0x77, 0x4A, 0x57, 0x43, 0x5A, 0x34, 0x6B, 0x4C, 0x4F, 0x47, 0x47, 0x67, 0x59, 0x7A, 0x2B, 0x71, 0x78, 0x63, 0x73, 0x2B, 0x73, 0x6A, 0x69, 0x4D, 0x68, 0x6F, 0x36, 0x2F, 0x34, 0x55, 0x49, 0x79, 0x59, 0x4F, 0x66, 0x38, ++ 0x6B, 0x70, 0x49, 0x45, 0x46, 0x52, 0x33, 0x4E, 0x2B, 0x32, 0x69, 0x76, 0x45, 0x43, 0x2B, 0x35, 0x42, 0x42, 0x30, 0x0A, 0x39, 0x2B, 0x52, 0x62, 0x75, 0x37, 0x6E, 0x7A, 0x69, 0x66, 0x6D, 0x50, 0x51, 0x64, 0x6A, 0x48, 0x35, 0x46, 0x43, 0x51, ++ 0x4E, 0x59, 0x41, 0x2B, 0x48, 0x4C, 0x68, 0x4E, 0x6B, 0x4E, 0x50, 0x55, 0x39, 0x38, 0x4F, 0x77, 0x6F, 0x58, 0x36, 0x45, 0x79, 0x6E, 0x65, 0x53, 0x4D, 0x53, 0x79, 0x34, 0x6B, 0x4C, 0x47, 0x43, 0x65, 0x6E, 0x52, 0x4F, 0x6D, 0x78, 0x4D, 0x6D, ++ 0x74, 0x4E, 0x56, 0x51, 0x5A, 0x6C, 0x52, 0x34, 0x72, 0x6D, 0x41, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, ++ 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x32, 0x32, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, ++ 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x43, 0x4F, 0x6A, 0x43, 0x43, 0x41, 0x63, 0x43, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x46, 0x41, 0x50, 0x31, 0x71, 0x2F, 0x73, 0x33, 0x69, 0x78, 0x64, 0x41, 0x57, 0x2B, ++ 0x4A, 0x44, 0x73, 0x71, 0x58, 0x52, 0x78, 0x44, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x7A, 0x42, 0x4F, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, ++ 0x4A, 0x56, 0x0A, 0x55, 0x7A, 0x45, 0x59, 0x4D, 0x42, 0x59, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, 0x50, 0x55, 0x31, 0x4E, 0x4D, 0x49, 0x45, 0x4E, 0x76, 0x63, 0x6E, 0x42, 0x76, 0x63, 0x6D, 0x46, 0x30, 0x61, 0x57, 0x39, 0x75, 0x4D, ++ 0x53, 0x55, 0x77, 0x49, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x44, 0x42, 0x78, 0x54, 0x55, 0x30, 0x77, 0x75, 0x59, 0x32, 0x39, 0x74, 0x49, 0x46, 0x52, 0x4D, 0x55, 0x79, 0x42, 0x46, 0x51, 0x30, 0x4D, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x0A, ++ 0x64, 0x43, 0x42, 0x44, 0x51, 0x53, 0x41, 0x79, 0x4D, 0x44, 0x49, 0x79, 0x4D, 0x42, 0x34, 0x58, 0x44, 0x54, 0x49, 0x79, 0x4D, 0x44, 0x67, 0x79, 0x4E, 0x54, 0x45, 0x32, 0x4D, 0x7A, 0x4D, 0x30, 0x4F, 0x46, 0x6F, 0x58, 0x44, 0x54, 0x51, 0x32, ++ 0x4D, 0x44, 0x67, 0x78, 0x4F, 0x54, 0x45, 0x32, 0x4D, 0x7A, 0x4D, 0x30, 0x4E, 0x31, 0x6F, 0x77, 0x54, 0x6A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x56, 0x56, 0x4D, 0x78, 0x0A, 0x47, 0x44, 0x41, ++ 0x57, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x4D, 0x44, 0x31, 0x4E, 0x54, 0x54, 0x43, 0x42, 0x44, 0x62, 0x33, 0x4A, 0x77, 0x62, 0x33, 0x4A, 0x68, 0x64, 0x47, 0x6C, 0x76, 0x62, 0x6A, 0x45, 0x6C, 0x4D, 0x43, 0x4D, 0x47, 0x41, 0x31, 0x55, ++ 0x45, 0x41, 0x77, 0x77, 0x63, 0x55, 0x31, 0x4E, 0x4D, 0x4C, 0x6D, 0x4E, 0x76, 0x62, 0x53, 0x42, 0x55, 0x54, 0x46, 0x4D, 0x67, 0x52, 0x55, 0x4E, 0x44, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x0A, 0x51, 0x30, 0x45, 0x67, 0x4D, 0x6A, ++ 0x41, 0x79, 0x4D, 0x6A, 0x42, 0x32, 0x4D, 0x42, 0x41, 0x47, 0x42, 0x79, 0x71, 0x47, 0x53, 0x4D, 0x34, 0x39, 0x41, 0x67, 0x45, 0x47, 0x42, 0x53, 0x75, 0x42, 0x42, 0x41, 0x41, 0x69, 0x41, 0x32, 0x49, 0x41, 0x42, 0x45, 0x55, 0x70, 0x4E, 0x58, ++ 0x50, 0x36, 0x77, 0x72, 0x67, 0x6A, 0x7A, 0x68, 0x52, 0x39, 0x71, 0x4C, 0x46, 0x4E, 0x6F, 0x46, 0x73, 0x32, 0x37, 0x69, 0x6F, 0x73, 0x55, 0x38, 0x4E, 0x67, 0x43, 0x54, 0x57, 0x79, 0x0A, 0x4A, 0x47, 0x59, 0x6D, 0x61, 0x63, 0x43, 0x7A, 0x6C, ++ 0x64, 0x5A, 0x64, 0x6B, 0x6B, 0x41, 0x5A, 0x44, 0x73, 0x61, 0x6C, 0x45, 0x33, 0x44, 0x30, 0x37, 0x78, 0x4A, 0x52, 0x4B, 0x46, 0x33, 0x6E, 0x7A, 0x4C, 0x33, 0x35, 0x50, 0x49, 0x58, 0x42, 0x7A, 0x35, 0x53, 0x51, 0x79, 0x53, 0x76, 0x4F, 0x6B, ++ 0x6B, 0x4A, 0x59, 0x57, 0x57, 0x66, 0x39, 0x6C, 0x43, 0x63, 0x51, 0x5A, 0x49, 0x78, 0x50, 0x42, 0x4C, 0x46, 0x4E, 0x53, 0x65, 0x52, 0x37, 0x54, 0x35, 0x76, 0x31, 0x0A, 0x35, 0x77, 0x6A, 0x34, 0x41, 0x34, 0x6A, 0x33, 0x70, 0x38, 0x4F, 0x53, ++ 0x53, 0x78, 0x6C, 0x55, 0x67, 0x61, 0x4E, 0x6A, 0x4D, 0x47, 0x45, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x66, 0x42, 0x67, 0x4E, 0x56, ++ 0x48, 0x53, 0x4D, 0x45, 0x47, 0x44, 0x41, 0x57, 0x67, 0x42, 0x53, 0x4A, 0x6A, 0x79, 0x2B, 0x6A, 0x36, 0x43, 0x75, 0x67, 0x46, 0x46, 0x52, 0x37, 0x0A, 0x38, 0x31, 0x61, 0x34, 0x4A, 0x6C, 0x39, 0x6E, 0x4F, 0x41, 0x75, 0x63, 0x30, 0x44, 0x41, ++ 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x69, 0x59, 0x38, 0x76, 0x6F, 0x2B, 0x67, 0x72, 0x6F, 0x42, 0x52, 0x55, 0x65, 0x2F, 0x4E, 0x57, 0x75, 0x43, 0x5A, 0x66, 0x5A, 0x7A, 0x67, 0x4C, 0x6E, 0x4E, 0x41, ++ 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x51, 0x44, 0x41, 0x67, 0x47, 0x47, 0x0A, 0x4D, 0x41, 0x6F, 0x47, 0x43, 0x43, 0x71, 0x47, 0x53, 0x4D, 0x34, 0x39, 0x42, 0x41, 0x4D, 0x44, 0x41, 0x32, ++ 0x67, 0x41, 0x4D, 0x47, 0x55, 0x43, 0x4D, 0x46, 0x58, 0x6A, 0x49, 0x6C, 0x62, 0x70, 0x31, 0x35, 0x49, 0x6B, 0x57, 0x45, 0x38, 0x65, 0x6C, 0x44, 0x49, 0x50, 0x44, 0x41, 0x49, 0x32, 0x77, 0x76, 0x32, 0x73, 0x64, 0x44, 0x4A, 0x4F, 0x34, 0x66, ++ 0x73, 0x63, 0x67, 0x49, 0x69, 0x6A, 0x7A, 0x50, 0x76, 0x58, 0x36, 0x79, 0x76, 0x2F, 0x4E, 0x33, 0x33, 0x77, 0x0A, 0x37, 0x64, 0x65, 0x65, 0x64, 0x57, 0x6F, 0x31, 0x64, 0x6C, 0x4A, 0x46, 0x34, 0x41, 0x49, 0x78, 0x41, 0x4D, 0x65, 0x4E, 0x62, ++ 0x30, 0x49, 0x67, 0x6A, 0x37, 0x36, 0x32, 0x54, 0x56, 0x6E, 0x74, 0x64, 0x30, 0x30, 0x70, 0x78, 0x43, 0x41, 0x67, 0x52, 0x57, 0x53, 0x47, 0x4F, 0x6C, 0x44, 0x47, 0x78, 0x4B, 0x30, 0x74, 0x6B, 0x2F, 0x55, 0x59, 0x66, 0x58, 0x4C, 0x74, 0x71, ++ 0x63, 0x2F, 0x45, 0x72, 0x46, 0x63, 0x32, 0x4B, 0x41, 0x68, 0x6C, 0x33, 0x7A, 0x78, 0x35, 0x0A, 0x5A, 0x6E, 0x36, 0x67, 0x36, 0x67, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, ++ 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x41, 0x74, 0x6F, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x45, 0x43, 0x43, ++ 0x20, 0x54, 0x4C, 0x53, 0x20, 0x32, 0x30, 0x32, 0x31, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x43, ++ 0x46, 0x54, 0x43, 0x43, 0x41, 0x5A, 0x75, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x50, 0x5A, 0x67, 0x37, 0x70, 0x6D, 0x59, 0x39, 0x6B, 0x47, 0x50, 0x33, 0x66, 0x69, 0x5A, 0x58, 0x4F, 0x41, 0x54, 0x76, 0x41, 0x44, 0x41, 0x4B, ++ 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x7A, 0x42, 0x4D, 0x4D, 0x53, 0x34, 0x77, 0x4C, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x44, 0x43, 0x56, 0x42, 0x0A, 0x64, 0x47, 0x39, 0x7A, 0x49, 0x46, 0x52, ++ 0x79, 0x64, 0x58, 0x4E, 0x30, 0x5A, 0x57, 0x52, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x67, 0x52, 0x55, 0x4E, 0x44, 0x49, 0x46, 0x52, 0x4D, 0x55, 0x79, 0x41, 0x79, 0x4D, 0x44, 0x49, ++ 0x78, 0x4D, 0x51, 0x30, 0x77, 0x43, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x44, 0x41, 0x52, 0x42, 0x64, 0x47, 0x39, 0x7A, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x0A, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x45, 0x52, 0x54, ++ 0x41, 0x65, 0x46, 0x77, 0x30, 0x79, 0x4D, 0x54, 0x41, 0x30, 0x4D, 0x6A, 0x49, 0x77, 0x4F, 0x54, 0x49, 0x32, 0x4D, 0x6A, 0x4E, 0x61, 0x46, 0x77, 0x30, 0x30, 0x4D, 0x54, 0x41, 0x30, 0x4D, 0x54, 0x63, 0x77, 0x4F, 0x54, 0x49, 0x32, 0x4D, 0x6A, ++ 0x4A, 0x61, 0x4D, 0x45, 0x77, 0x78, 0x4C, 0x6A, 0x41, 0x73, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x4D, 0x4A, 0x55, 0x46, 0x30, 0x62, 0x33, 0x4D, 0x67, 0x0A, 0x56, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x52, 0x6C, 0x5A, 0x46, 0x4A, 0x76, 0x62, ++ 0x33, 0x51, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x51, 0x53, 0x42, 0x46, 0x51, 0x30, 0x4D, 0x67, 0x56, 0x45, 0x78, 0x54, 0x49, 0x44, 0x49, 0x77, 0x4D, 0x6A, 0x45, 0x78, 0x44, 0x54, 0x41, 0x4C, 0x42, 0x67, 0x4E, 0x56, 0x42, ++ 0x41, 0x6F, 0x4D, 0x42, 0x45, 0x46, 0x30, 0x62, 0x33, 0x4D, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x0A, 0x41, 0x6B, 0x52, 0x46, 0x4D, 0x48, 0x59, 0x77, 0x45, 0x41, 0x59, 0x48, 0x4B, 0x6F, 0x5A, 0x49, ++ 0x7A, 0x6A, 0x30, 0x43, 0x41, 0x51, 0x59, 0x46, 0x4B, 0x34, 0x45, 0x45, 0x41, 0x43, 0x49, 0x44, 0x59, 0x67, 0x41, 0x45, 0x6C, 0x6F, 0x5A, 0x59, 0x4B, 0x44, 0x63, 0x4B, 0x5A, 0x39, 0x43, 0x67, 0x33, 0x69, 0x51, 0x5A, 0x47, 0x65, 0x48, 0x6B, ++ 0x42, 0x51, 0x63, 0x66, 0x6C, 0x2B, 0x33, 0x6F, 0x5A, 0x49, 0x4B, 0x35, 0x39, 0x73, 0x52, 0x78, 0x55, 0x4D, 0x36, 0x4B, 0x0A, 0x44, 0x50, 0x2F, 0x58, 0x74, 0x58, 0x61, 0x37, 0x6F, 0x57, 0x79, 0x54, 0x62, 0x49, 0x4F, 0x69, 0x61, 0x47, 0x36, ++ 0x6C, 0x32, 0x62, 0x34, 0x73, 0x69, 0x4A, 0x56, 0x42, 0x7A, 0x56, 0x33, 0x64, 0x73, 0x63, 0x71, 0x44, 0x59, 0x34, 0x50, 0x4D, 0x77, 0x4C, 0x35, 0x30, 0x32, 0x65, 0x43, 0x64, 0x70, 0x4F, 0x35, 0x4B, 0x54, 0x6C, 0x62, 0x67, 0x6D, 0x43, 0x6C, ++ 0x42, 0x6B, 0x31, 0x49, 0x51, 0x31, 0x53, 0x51, 0x34, 0x41, 0x6A, 0x4A, 0x6E, 0x38, 0x5A, 0x51, 0x53, 0x0A, 0x62, 0x2B, 0x2F, 0x58, 0x78, 0x64, 0x34, 0x75, 0x2F, 0x52, 0x6D, 0x41, 0x6F, 0x30, 0x49, 0x77, 0x51, 0x44, 0x41, 0x50, 0x42, 0x67, ++ 0x4E, 0x56, 0x48, 0x52, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x54, 0x41, 0x44, 0x41, 0x51, 0x48, 0x2F, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x52, 0x32, 0x4B, 0x43, 0x58, 0x57, 0x66, 0x65, ++ 0x42, 0x6D, 0x6D, 0x6E, 0x6F, 0x4A, 0x73, 0x6D, 0x6F, 0x37, 0x6A, 0x6A, 0x50, 0x58, 0x0A, 0x4E, 0x74, 0x4E, 0x50, 0x6F, 0x6A, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x41, 0x4D, 0x43, 0x41, ++ 0x59, 0x59, 0x77, 0x43, 0x67, 0x59, 0x49, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x45, 0x41, 0x77, 0x4D, 0x44, 0x61, 0x41, 0x41, 0x77, 0x5A, 0x51, 0x49, 0x77, 0x57, 0x35, 0x6B, 0x70, 0x38, 0x35, 0x77, 0x78, 0x74, 0x6F, 0x6C, 0x72, 0x62, ++ 0x4E, 0x61, 0x39, 0x64, 0x2B, 0x46, 0x38, 0x35, 0x31, 0x46, 0x2B, 0x0A, 0x75, 0x44, 0x72, 0x4E, 0x6F, 0x7A, 0x5A, 0x66, 0x66, 0x50, 0x63, 0x38, 0x64, 0x7A, 0x37, 0x6B, 0x55, 0x4B, 0x32, 0x6F, 0x35, 0x39, 0x4A, 0x5A, 0x44, 0x43, 0x61, 0x4F, ++ 0x4D, 0x44, 0x74, 0x75, 0x43, 0x43, 0x72, 0x43, 0x70, 0x31, 0x72, 0x49, 0x41, 0x6A, 0x45, 0x41, 0x6D, 0x65, 0x4D, 0x4D, 0x35, 0x36, 0x50, 0x44, 0x72, 0x39, 0x4E, 0x4A, 0x4C, 0x6B, 0x61, 0x43, 0x49, 0x32, 0x5A, 0x64, 0x79, 0x51, 0x41, 0x55, ++ 0x45, 0x76, 0x30, 0x34, 0x39, 0x4F, 0x47, 0x59, 0x0A, 0x61, 0x33, 0x63, 0x70, 0x65, 0x74, 0x73, 0x6B, 0x7A, 0x32, 0x56, 0x41, 0x76, 0x39, 0x4C, 0x63, 0x6A, 0x42, 0x48, 0x6F, 0x39, 0x48, 0x31, 0x2F, 0x49, 0x49, 0x53, 0x70, 0x51, 0x75, 0x51, ++ 0x6F, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x41, 0x74, 0x6F, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, ++ 0x64, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x52, 0x53, 0x41, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x32, 0x30, 0x32, 0x31, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, ++ 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x5A, 0x44, 0x43, 0x43, 0x41, 0x30, 0x79, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x55, 0x39, 0x58, 0x50, 0x35, 0x68, 0x6D, ++ 0x54, 0x43, 0x2F, 0x73, 0x72, 0x42, 0x52, 0x4C, 0x59, 0x77, 0x69, 0x71, 0x69, 0x70, 0x44, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x77, 0x46, 0x41, 0x44, 0x42, 0x4D, 0x4D, 0x53, 0x34, ++ 0x77, 0x4C, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x0A, 0x44, 0x43, 0x56, 0x42, 0x64, 0x47, 0x39, 0x7A, 0x49, 0x46, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x5A, 0x57, 0x52, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, ++ 0x51, 0x67, 0x51, 0x30, 0x45, 0x67, 0x55, 0x6C, 0x4E, 0x42, 0x49, 0x46, 0x52, 0x4D, 0x55, 0x79, 0x41, 0x79, 0x4D, 0x44, 0x49, 0x78, 0x4D, 0x51, 0x30, 0x77, 0x43, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x44, 0x41, 0x52, 0x42, 0x64, 0x47, ++ 0x39, 0x7A, 0x4D, 0x51, 0x73, 0x77, 0x0A, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x45, 0x52, 0x54, 0x41, 0x65, 0x46, 0x77, 0x30, 0x79, 0x4D, 0x54, 0x41, 0x30, 0x4D, 0x6A, 0x49, 0x77, 0x4F, 0x54, 0x49, 0x78, 0x4D, ++ 0x54, 0x42, 0x61, 0x46, 0x77, 0x30, 0x30, 0x4D, 0x54, 0x41, 0x30, 0x4D, 0x54, 0x63, 0x77, 0x4F, 0x54, 0x49, 0x78, 0x4D, 0x44, 0x6C, 0x61, 0x4D, 0x45, 0x77, 0x78, 0x4C, 0x6A, 0x41, 0x73, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x4D, 0x4A, ++ 0x55, 0x46, 0x30, 0x0A, 0x62, 0x33, 0x4D, 0x67, 0x56, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x52, 0x6C, 0x5A, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x51, 0x53, 0x42, 0x53, 0x55, 0x30, 0x45, 0x67, ++ 0x56, 0x45, 0x78, 0x54, 0x49, 0x44, 0x49, 0x77, 0x4D, 0x6A, 0x45, 0x78, 0x44, 0x54, 0x41, 0x4C, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x4D, 0x42, 0x45, 0x46, 0x30, 0x62, 0x33, 0x4D, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, ++ 0x0A, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6B, 0x52, 0x46, 0x4D, 0x49, 0x49, 0x43, 0x49, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x45, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x67, 0x38, ++ 0x41, 0x4D, 0x49, 0x49, 0x43, 0x43, 0x67, 0x4B, 0x43, 0x41, 0x67, 0x45, 0x41, 0x74, 0x6F, 0x41, 0x4F, 0x78, 0x48, 0x6D, 0x39, 0x42, 0x59, 0x78, 0x39, 0x73, 0x4B, 0x4F, 0x64, 0x54, 0x53, 0x4A, 0x4E, 0x79, 0x2F, 0x42, 0x42, 0x0A, 0x6C, 0x30, ++ 0x31, 0x5A, 0x34, 0x4E, 0x48, 0x2B, 0x56, 0x6F, 0x79, 0x58, 0x38, 0x74, 0x65, 0x39, 0x6A, 0x32, 0x79, 0x33, 0x49, 0x34, 0x39, 0x66, 0x31, 0x63, 0x54, 0x59, 0x51, 0x63, 0x76, 0x79, 0x41, 0x68, 0x35, 0x78, 0x35, 0x65, 0x6E, 0x32, 0x58, 0x73, ++ 0x73, 0x49, 0x4B, 0x6C, 0x34, 0x77, 0x38, 0x69, 0x31, 0x6D, 0x78, 0x34, 0x51, 0x62, 0x5A, 0x46, 0x63, 0x34, 0x6E, 0x58, 0x55, 0x74, 0x56, 0x73, 0x59, 0x76, 0x59, 0x65, 0x2B, 0x57, 0x2F, 0x43, 0x42, 0x47, 0x0A, 0x76, 0x65, 0x76, 0x55, 0x65, ++ 0x7A, 0x38, 0x2F, 0x66, 0x45, 0x63, 0x34, 0x42, 0x4B, 0x6B, 0x62, 0x71, 0x6C, 0x4C, 0x66, 0x45, 0x7A, 0x66, 0x54, 0x46, 0x52, 0x56, 0x4F, 0x76, 0x56, 0x39, 0x38, 0x72, 0x36, 0x31, 0x6A, 0x78, 0x33, 0x6E, 0x63, 0x43, 0x48, 0x76, 0x56, 0x6F, ++ 0x4F, 0x58, 0x33, 0x57, 0x33, 0x57, 0x73, 0x67, 0x46, 0x57, 0x5A, 0x6B, 0x6D, 0x47, 0x62, 0x7A, 0x53, 0x6F, 0x58, 0x66, 0x64, 0x75, 0x50, 0x39, 0x4C, 0x56, 0x71, 0x36, 0x68, 0x64, 0x4B, 0x0A, 0x5A, 0x43, 0x68, 0x6D, 0x46, 0x53, 0x6C, 0x73, ++ 0x41, 0x76, 0x46, 0x72, 0x31, 0x62, 0x71, 0x6A, 0x4D, 0x39, 0x78, 0x61, 0x5A, 0x36, 0x63, 0x46, 0x34, 0x72, 0x39, 0x6C, 0x74, 0x68, 0x61, 0x77, 0x45, 0x4F, 0x33, 0x4E, 0x55, 0x44, 0x50, 0x4A, 0x63, 0x46, 0x44, 0x73, 0x47, 0x59, 0x36, 0x77, ++ 0x78, 0x2F, 0x4A, 0x30, 0x57, 0x32, 0x74, 0x45, 0x78, 0x6E, 0x32, 0x57, 0x75, 0x5A, 0x67, 0x49, 0x57, 0x57, 0x62, 0x65, 0x4B, 0x51, 0x47, 0x62, 0x39, 0x43, 0x70, 0x74, 0x0A, 0x30, 0x78, 0x55, 0x36, 0x6B, 0x47, 0x70, 0x6E, 0x38, 0x62, 0x52, ++ 0x72, 0x5A, 0x74, 0x6B, 0x68, 0x36, 0x38, 0x72, 0x5A, 0x59, 0x6E, 0x78, 0x47, 0x45, 0x46, 0x7A, 0x65, 0x64, 0x55, 0x6C, 0x6E, 0x6E, 0x6B, 0x4C, 0x35, 0x2F, 0x6E, 0x57, 0x70, 0x6F, 0x36, 0x33, 0x2F, 0x64, 0x67, 0x70, 0x6E, 0x51, 0x4F, 0x50, ++ 0x46, 0x39, 0x34, 0x33, 0x48, 0x68, 0x5A, 0x70, 0x5A, 0x6E, 0x6D, 0x4B, 0x61, 0x61, 0x75, 0x31, 0x46, 0x68, 0x35, 0x68, 0x6E, 0x73, 0x74, 0x56, 0x4B, 0x0A, 0x50, 0x4E, 0x65, 0x30, 0x4F, 0x77, 0x41, 0x4E, 0x77, 0x49, 0x38, 0x66, 0x34, 0x55, ++ 0x44, 0x45, 0x72, 0x6D, 0x77, 0x68, 0x33, 0x45, 0x6C, 0x2B, 0x66, 0x73, 0x71, 0x79, 0x6A, 0x57, 0x32, 0x32, 0x76, 0x35, 0x4D, 0x76, 0x6F, 0x56, 0x77, 0x2B, 0x6A, 0x38, 0x72, 0x74, 0x67, 0x49, 0x35, 0x59, 0x34, 0x64, 0x74, 0x58, 0x7A, 0x34, ++ 0x55, 0x32, 0x4F, 0x4C, 0x4A, 0x78, 0x70, 0x41, 0x6D, 0x4D, 0x6B, 0x6F, 0x6B, 0x49, 0x69, 0x45, 0x6A, 0x78, 0x51, 0x47, 0x4D, 0x59, 0x0A, 0x73, 0x6C, 0x75, 0x4D, 0x57, 0x75, 0x50, 0x44, 0x30, 0x78, 0x65, 0x71, 0x71, 0x78, 0x6D, 0x6A, 0x4C, ++ 0x42, 0x76, 0x6B, 0x31, 0x63, 0x62, 0x69, 0x5A, 0x6E, 0x72, 0x58, 0x67, 0x68, 0x6D, 0x6D, 0x4F, 0x78, 0x59, 0x73, 0x4C, 0x33, 0x47, 0x48, 0x58, 0x30, 0x57, 0x65, 0x6C, 0x58, 0x4F, 0x54, 0x77, 0x6B, 0x4B, 0x42, 0x49, 0x52, 0x4F, 0x57, 0x31, ++ 0x35, 0x32, 0x37, 0x6B, 0x32, 0x67, 0x56, 0x2B, 0x70, 0x32, 0x6B, 0x48, 0x59, 0x7A, 0x79, 0x67, 0x65, 0x42, 0x59, 0x0A, 0x42, 0x72, 0x33, 0x4A, 0x74, 0x75, 0x50, 0x32, 0x69, 0x56, 0x32, 0x4A, 0x2B, 0x61, 0x78, 0x45, 0x6F, 0x63, 0x74, 0x72, ++ 0x2B, 0x68, 0x62, 0x78, 0x78, 0x31, 0x41, 0x39, 0x4A, 0x4E, 0x72, 0x33, 0x77, 0x2B, 0x53, 0x48, 0x31, 0x56, 0x62, 0x78, 0x54, 0x35, 0x41, 0x77, 0x2B, 0x6B, 0x55, 0x4A, 0x57, 0x64, 0x6F, 0x30, 0x7A, 0x75, 0x41, 0x54, 0x48, 0x41, 0x52, 0x38, ++ 0x41, 0x4E, 0x53, 0x62, 0x68, 0x71, 0x52, 0x41, 0x76, 0x4E, 0x6E, 0x63, 0x54, 0x46, 0x64, 0x2B, 0x0A, 0x72, 0x72, 0x63, 0x7A, 0x74, 0x6C, 0x35, 0x32, 0x34, 0x57, 0x57, 0x4C, 0x5A, 0x74, 0x2B, 0x4E, 0x79, 0x74, 0x65, 0x59, 0x72, 0x38, 0x34, ++ 0x32, 0x6D, 0x49, 0x79, 0x63, 0x67, 0x35, 0x6B, 0x44, 0x63, 0x50, 0x4F, 0x76, 0x64, 0x4F, 0x33, 0x47, 0x44, 0x6A, 0x62, 0x6E, 0x76, 0x65, 0x7A, 0x42, 0x63, 0x36, 0x65, 0x55, 0x57, 0x73, 0x75, 0x53, 0x5A, 0x49, 0x4B, 0x6D, 0x41, 0x4D, 0x46, ++ 0x77, 0x6F, 0x57, 0x34, 0x73, 0x4B, 0x65, 0x46, 0x59, 0x56, 0x2B, 0x78, 0x61, 0x0A, 0x66, 0x4A, 0x6C, 0x72, 0x4A, 0x61, 0x53, 0x51, 0x4F, 0x6F, 0x44, 0x30, 0x49, 0x4A, 0x32, 0x61, 0x7A, 0x73, 0x63, 0x74, 0x2B, 0x62, 0x4A, 0x4C, 0x4B, 0x5A, ++ 0x57, 0x44, 0x36, 0x54, 0x57, 0x4E, 0x70, 0x30, 0x6C, 0x49, 0x70, 0x77, 0x39, 0x4D, 0x47, 0x5A, 0x48, 0x51, 0x39, 0x62, 0x38, 0x51, 0x34, 0x48, 0x45, 0x43, 0x41, 0x77, 0x45, 0x41, 0x41, 0x61, 0x4E, 0x43, 0x4D, 0x45, 0x41, 0x77, 0x44, 0x77, ++ 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x0A, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x64, 0x45, 0x6D, 0x5A, 0x30, ++ 0x66, 0x2B, 0x30, 0x65, 0x6D, 0x68, 0x46, 0x64, 0x63, 0x4E, 0x2B, 0x74, 0x4E, 0x7A, 0x4D, 0x7A, 0x6A, 0x6B, 0x7A, 0x32, 0x67, 0x67, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x51, 0x44, 0x41, ++ 0x67, 0x47, 0x47, 0x4D, 0x41, 0x30, 0x47, 0x0A, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x44, 0x41, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x41, 0x51, 0x41, 0x6A, 0x51, 0x31, 0x4D, 0x6B, 0x59, 0x6C, 0x78, 0x74, ++ 0x2F, 0x54, 0x37, 0x43, 0x7A, 0x31, 0x55, 0x41, 0x62, 0x4D, 0x56, 0x57, 0x69, 0x4C, 0x6B, 0x4F, 0x33, 0x54, 0x72, 0x69, 0x4A, 0x51, 0x32, 0x56, 0x53, 0x70, 0x66, 0x4B, 0x67, 0x49, 0x6E, 0x75, 0x4B, 0x73, 0x31, 0x6C, 0x2B, 0x4E, 0x73, 0x57, ++ 0x34, 0x41, 0x6D, 0x53, 0x0A, 0x34, 0x42, 0x6A, 0x48, 0x65, 0x4A, 0x69, 0x37, 0x38, 0x2B, 0x78, 0x43, 0x55, 0x76, 0x75, 0x70, 0x70, 0x49, 0x4C, 0x58, 0x54, 0x64, 0x69, 0x4B, 0x2F, 0x4F, 0x52, 0x4F, 0x2F, 0x61, 0x75, 0x51, 0x78, 0x44, 0x68, ++ 0x31, 0x4D, 0x6F, 0x53, 0x66, 0x2F, 0x37, 0x4F, 0x77, 0x4B, 0x77, 0x49, 0x7A, 0x4E, 0x73, 0x41, 0x51, 0x6B, 0x47, 0x38, 0x64, 0x6E, 0x4B, 0x2F, 0x68, 0x61, 0x5A, 0x50, 0x73, 0x6F, 0x30, 0x55, 0x76, 0x46, 0x4A, 0x2F, 0x31, 0x54, 0x43, 0x70, ++ 0x6C, 0x0A, 0x51, 0x33, 0x49, 0x4D, 0x39, 0x38, 0x50, 0x34, 0x6C, 0x59, 0x73, 0x55, 0x38, 0x34, 0x55, 0x67, 0x59, 0x74, 0x31, 0x55, 0x55, 0x39, 0x30, 0x73, 0x33, 0x42, 0x69, 0x56, 0x61, 0x55, 0x2B, 0x44, 0x52, 0x33, 0x42, 0x41, 0x4D, 0x31, ++ 0x68, 0x33, 0x45, 0x67, 0x79, 0x69, 0x36, 0x31, 0x49, 0x78, 0x48, 0x6B, 0x7A, 0x4A, 0x71, 0x4D, 0x37, 0x46, 0x37, 0x38, 0x50, 0x52, 0x72, 0x65, 0x42, 0x72, 0x41, 0x77, 0x41, 0x30, 0x4A, 0x72, 0x52, 0x55, 0x49, 0x54, 0x57, 0x58, 0x0A, 0x41, ++ 0x64, 0x78, 0x66, 0x47, 0x2F, 0x46, 0x38, 0x35, 0x31, 0x58, 0x36, 0x4C, 0x57, 0x68, 0x33, 0x65, 0x39, 0x4E, 0x70, 0x7A, 0x4E, 0x4D, 0x4F, 0x61, 0x37, 0x70, 0x4E, 0x64, 0x6B, 0x54, 0x57, 0x77, 0x68, 0x57, 0x61, 0x4A, 0x75, 0x79, 0x77, 0x78, ++ 0x66, 0x57, 0x37, 0x30, 0x58, 0x70, 0x30, 0x77, 0x6D, 0x7A, 0x4E, 0x78, 0x62, 0x56, 0x65, 0x39, 0x6B, 0x7A, 0x6D, 0x57, 0x79, 0x32, 0x42, 0x32, 0x37, 0x4F, 0x33, 0x4F, 0x70, 0x65, 0x65, 0x37, 0x63, 0x39, 0x47, 0x0A, 0x73, 0x6C, 0x41, 0x39, ++ 0x68, 0x47, 0x43, 0x5A, 0x63, 0x62, 0x55, 0x7A, 0x74, 0x56, 0x64, 0x46, 0x35, 0x6B, 0x4A, 0x48, 0x64, 0x57, 0x6F, 0x4F, 0x73, 0x41, 0x67, 0x4D, 0x72, 0x72, 0x33, 0x65, 0x39, 0x37, 0x73, 0x50, 0x57, 0x44, 0x32, 0x50, 0x41, 0x7A, 0x48, 0x6F, ++ 0x50, 0x59, 0x4A, 0x51, 0x79, 0x69, 0x39, 0x65, 0x44, 0x46, 0x32, 0x30, 0x6C, 0x37, 0x34, 0x67, 0x4E, 0x41, 0x66, 0x30, 0x78, 0x42, 0x4C, 0x68, 0x37, 0x74, 0x65, 0x77, 0x32, 0x56, 0x6B, 0x74, 0x0A, 0x61, 0x66, 0x63, 0x78, 0x42, 0x50, 0x54, ++ 0x79, 0x2B, 0x61, 0x76, 0x35, 0x45, 0x7A, 0x48, 0x34, 0x41, 0x58, 0x63, 0x4F, 0x50, 0x55, 0x49, 0x6A, 0x4A, 0x73, 0x79, 0x61, 0x63, 0x6D, 0x64, 0x52, 0x49, 0x58, 0x72, 0x4D, 0x50, 0x49, 0x57, 0x6F, 0x36, 0x69, 0x46, 0x71, 0x4F, 0x39, 0x74, ++ 0x61, 0x50, 0x4B, 0x55, 0x30, 0x6E, 0x70, 0x72, 0x41, 0x4C, 0x4E, 0x2B, 0x41, 0x6E, 0x43, 0x6E, 0x67, 0x33, 0x33, 0x65, 0x55, 0x30, 0x61, 0x4B, 0x41, 0x51, 0x76, 0x39, 0x71, 0x0A, 0x54, 0x46, 0x73, 0x52, 0x30, 0x50, 0x58, 0x4E, 0x6F, 0x72, ++ 0x36, 0x75, 0x7A, 0x46, 0x46, 0x63, 0x77, 0x39, 0x56, 0x55, 0x65, 0x77, 0x79, 0x75, 0x31, 0x72, 0x6B, 0x47, 0x64, 0x34, 0x44, 0x69, 0x37, 0x77, 0x63, 0x61, 0x61, 0x4D, 0x78, 0x5A, 0x55, 0x61, 0x31, 0x2B, 0x58, 0x47, 0x64, 0x72, 0x75, 0x64, ++ 0x76, 0x69, 0x42, 0x30, 0x4A, 0x62, 0x75, 0x41, 0x45, 0x46, 0x57, 0x44, 0x6C, 0x4E, 0x35, 0x4C, 0x75, 0x59, 0x6F, 0x37, 0x45, 0x79, 0x37, 0x4E, 0x6D, 0x6A, 0x0A, 0x31, 0x6D, 0x2B, 0x55, 0x49, 0x2F, 0x38, 0x37, 0x74, 0x79, 0x6C, 0x6C, 0x35, ++ 0x67, 0x66, 0x70, 0x37, 0x37, 0x59, 0x5A, 0x36, 0x75, 0x66, 0x43, 0x4F, 0x42, 0x30, 0x79, 0x69, 0x4A, 0x41, 0x38, 0x45, 0x79, 0x74, 0x75, 0x7A, 0x4F, 0x2B, 0x72, 0x64, 0x77, 0x59, 0x30, 0x64, 0x34, 0x52, 0x50, 0x63, 0x75, 0x53, 0x42, 0x68, ++ 0x50, 0x6D, 0x35, 0x64, 0x44, 0x54, 0x65, 0x64, 0x6B, 0x2B, 0x53, 0x4B, 0x6C, 0x4F, 0x78, 0x4A, 0x54, 0x6E, 0x62, 0x50, 0x50, 0x2F, 0x6C, 0x0A, 0x50, 0x71, 0x59, 0x4F, 0x35, 0x57, 0x75, 0x65, 0x2F, 0x39, 0x76, 0x73, 0x4C, 0x33, 0x53, 0x44, ++ 0x33, 0x34, 0x36, 0x30, 0x73, 0x36, 0x6E, 0x65, 0x46, 0x45, 0x33, 0x2F, 0x4D, 0x61, 0x4E, 0x46, 0x63, 0x79, 0x54, 0x36, 0x6C, 0x53, 0x6E, 0x4D, 0x45, 0x70, 0x63, 0x45, 0x6F, 0x6A, 0x69, 0x32, 0x6A, 0x62, 0x44, 0x77, 0x4E, 0x2F, 0x7A, 0x49, ++ 0x49, 0x58, 0x38, 0x2F, 0x73, 0x79, 0x51, 0x62, 0x50, 0x59, 0x74, 0x75, 0x7A, 0x45, 0x32, 0x77, 0x46, 0x67, 0x32, 0x57, 0x0A, 0x48, 0x59, 0x4D, 0x66, 0x52, 0x73, 0x43, 0x62, 0x76, 0x55, 0x4F, 0x5A, 0x35, 0x38, 0x53, 0x57, 0x4C, 0x73, 0x35, ++ 0x66, 0x79, 0x51, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, ++ 0x69, 0x61, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x47, 0x33, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, ++ 0x46, 0x70, 0x54, 0x43, 0x43, 0x41, 0x34, 0x32, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x55, 0x5A, 0x50, 0x59, 0x4F, 0x5A, 0x58, 0x64, 0x68, 0x61, 0x71, 0x73, 0x37, 0x74, 0x4F, 0x71, 0x46, 0x68, 0x4C, 0x75, 0x78, 0x69, 0x62, 0x68, ++ 0x78, 0x6B, 0x77, 0x38, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4D, 0x42, 0x51, 0x41, 0x77, 0x57, 0x6A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x0A, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, ++ 0x4D, 0x43, 0x51, 0x30, 0x34, 0x78, 0x4A, 0x54, 0x41, 0x6A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x4D, 0x48, 0x46, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x51, 0x58, 0x4E, 0x70, 0x59, 0x53, 0x42, 0x55, 0x5A, 0x57, 0x4E, 0x6F, 0x62, 0x6D, ++ 0x39, 0x73, 0x62, 0x32, 0x64, 0x70, 0x5A, 0x58, 0x4D, 0x73, 0x49, 0x45, 0x6C, 0x75, 0x59, 0x79, 0x34, 0x78, 0x4A, 0x44, 0x41, 0x69, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x4D, 0x0A, 0x47, 0x31, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x51, ++ 0x58, 0x4E, 0x70, 0x59, 0x53, 0x42, 0x48, 0x62, 0x47, 0x39, 0x69, 0x59, 0x57, 0x77, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x51, 0x53, 0x42, 0x48, 0x4D, 0x7A, 0x41, 0x65, 0x46, 0x77, 0x30, 0x79, 0x4D, 0x54, 0x41, 0x31, 0x4D, ++ 0x6A, 0x41, 0x77, 0x4D, 0x6A, 0x45, 0x77, 0x4D, 0x54, 0x6C, 0x61, 0x46, 0x77, 0x30, 0x30, 0x4E, 0x6A, 0x41, 0x31, 0x4D, 0x54, 0x6B, 0x77, 0x4D, 0x6A, 0x45, 0x77, 0x0A, 0x4D, 0x54, 0x6C, 0x61, 0x4D, 0x46, 0x6F, 0x78, 0x43, 0x7A, 0x41, 0x4A, ++ 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6B, 0x4E, 0x4F, 0x4D, 0x53, 0x55, 0x77, 0x49, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x44, 0x42, 0x78, 0x55, 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x45, 0x46, 0x7A, 0x61, 0x57, 0x45, 0x67, ++ 0x56, 0x47, 0x56, 0x6A, 0x61, 0x47, 0x35, 0x76, 0x62, 0x47, 0x39, 0x6E, 0x61, 0x57, 0x56, 0x7A, 0x4C, 0x43, 0x42, 0x4A, 0x62, 0x6D, 0x4D, 0x75, 0x0A, 0x4D, 0x53, 0x51, 0x77, 0x49, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x44, 0x42, 0x74, ++ 0x55, 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x45, 0x46, 0x7A, 0x61, 0x57, 0x45, 0x67, 0x52, 0x32, 0x78, 0x76, 0x59, 0x6D, 0x46, 0x73, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x67, 0x52, 0x7A, 0x4D, 0x77, 0x67, 0x67, 0x49, ++ 0x69, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x0A, 0x41, 0x34, 0x49, 0x43, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x49, 0x4B, 0x41, 0x6F, 0x49, 0x43, 0x41, 0x51, ++ 0x44, 0x41, 0x4D, 0x59, 0x4A, 0x68, 0x6B, 0x75, 0x53, 0x55, 0x47, 0x77, 0x6F, 0x71, 0x5A, 0x64, 0x43, 0x2B, 0x42, 0x71, 0x6D, 0x48, 0x4F, 0x31, 0x45, 0x53, 0x36, 0x6E, 0x42, 0x42, 0x72, 0x75, 0x4C, 0x37, 0x64, 0x4F, 0x6F, 0x4B, 0x6A, 0x62, ++ 0x6D, 0x7A, 0x54, 0x4E, 0x79, 0x50, 0x74, 0x78, 0x4E, 0x53, 0x54, 0x31, 0x51, 0x59, 0x34, 0x53, 0x78, 0x7A, 0x0A, 0x6C, 0x5A, 0x48, 0x46, 0x5A, 0x6A, 0x74, 0x71, 0x7A, 0x36, 0x78, 0x6A, 0x62, 0x59, 0x64, 0x54, 0x38, 0x50, 0x66, 0x78, 0x4F, ++ 0x62, 0x65, 0x67, 0x51, 0x32, 0x4F, 0x77, 0x78, 0x41, 0x4E, 0x64, 0x56, 0x36, 0x6E, 0x6E, 0x52, 0x4D, 0x37, 0x45, 0x6F, 0x59, 0x4E, 0x6C, 0x39, 0x6C, 0x41, 0x2B, 0x73, 0x58, 0x34, 0x57, 0x75, 0x44, 0x71, 0x4B, 0x41, 0x74, 0x43, 0x57, 0x48, ++ 0x77, 0x44, 0x4E, 0x42, 0x53, 0x48, 0x76, 0x42, 0x6D, 0x33, 0x64, 0x49, 0x5A, 0x77, 0x5A, 0x0A, 0x51, 0x30, 0x57, 0x68, 0x78, 0x65, 0x69, 0x41, 0x79, 0x73, 0x4B, 0x74, 0x51, 0x47, 0x49, 0x58, 0x42, 0x73, 0x61, 0x71, 0x76, 0x50, 0x50, 0x57, ++ 0x35, 0x76, 0x78, 0x51, 0x66, 0x6D, 0x5A, 0x43, 0x48, 0x7A, 0x79, 0x4C, 0x70, 0x6E, 0x6C, 0x35, 0x68, 0x6B, 0x41, 0x31, 0x6E, 0x79, 0x44, 0x76, 0x50, 0x2B, 0x75, 0x4C, 0x52, 0x78, 0x2B, 0x50, 0x6A, 0x73, 0x58, 0x55, 0x6A, 0x72, 0x59, 0x73, ++ 0x79, 0x55, 0x51, 0x45, 0x34, 0x39, 0x52, 0x44, 0x64, 0x54, 0x2F, 0x56, 0x0A, 0x50, 0x36, 0x38, 0x63, 0x7A, 0x48, 0x35, 0x47, 0x58, 0x36, 0x7A, 0x66, 0x5A, 0x42, 0x43, 0x4B, 0x37, 0x30, 0x62, 0x77, 0x6B, 0x50, 0x41, 0x50, 0x4C, 0x66, 0x53, ++ 0x49, 0x43, 0x37, 0x45, 0x70, 0x71, 0x71, 0x2B, 0x46, 0x71, 0x6B, 0x6C, 0x59, 0x71, 0x4C, 0x39, 0x6A, 0x6F, 0x44, 0x69, 0x52, 0x35, 0x72, 0x50, 0x6D, 0x64, 0x32, 0x6A, 0x45, 0x2B, 0x53, 0x6F, 0x5A, 0x68, 0x4C, 0x73, 0x4F, 0x34, 0x66, 0x57, ++ 0x76, 0x69, 0x65, 0x79, 0x6C, 0x4C, 0x31, 0x41, 0x67, 0x0A, 0x64, 0x42, 0x34, 0x53, 0x51, 0x58, 0x4D, 0x65, 0x4A, 0x4E, 0x6E, 0x4B, 0x7A, 0x69, 0x79, 0x68, 0x57, 0x54, 0x58, 0x41, 0x79, 0x42, 0x31, 0x47, 0x4A, 0x32, 0x46, 0x61, 0x6A, 0x2F, ++ 0x6C, 0x4E, 0x30, 0x33, 0x4A, 0x35, 0x5A, 0x68, 0x36, 0x66, 0x46, 0x5A, 0x41, 0x68, 0x4C, 0x66, 0x33, 0x74, 0x69, 0x31, 0x5A, 0x77, 0x41, 0x30, 0x70, 0x4A, 0x50, 0x6E, 0x39, 0x70, 0x4D, 0x52, 0x4A, 0x70, 0x78, 0x78, 0x35, 0x63, 0x79, 0x6E, ++ 0x6F, 0x54, 0x69, 0x2B, 0x6A, 0x6D, 0x0A, 0x39, 0x57, 0x41, 0x50, 0x7A, 0x4A, 0x4D, 0x73, 0x68, 0x48, 0x2F, 0x78, 0x2F, 0x47, 0x72, 0x38, 0x6D, 0x30, 0x65, 0x64, 0x32, 0x36, 0x32, 0x49, 0x50, 0x66, 0x4E, 0x32, 0x64, 0x54, 0x50, 0x58, 0x53, ++ 0x36, 0x54, 0x49, 0x69, 0x2F, 0x6E, 0x31, 0x51, 0x31, 0x68, 0x50, 0x79, 0x38, 0x67, 0x44, 0x56, 0x49, 0x2B, 0x6C, 0x68, 0x58, 0x67, 0x45, 0x47, 0x76, 0x4E, 0x7A, 0x38, 0x74, 0x65, 0x48, 0x48, 0x55, 0x47, 0x66, 0x35, 0x39, 0x67, 0x58, 0x7A, ++ 0x68, 0x71, 0x63, 0x0A, 0x44, 0x30, 0x72, 0x38, 0x33, 0x45, 0x52, 0x6F, 0x56, 0x47, 0x6A, 0x69, 0x51, 0x54, 0x7A, 0x2B, 0x4C, 0x49, 0x53, 0x47, 0x4E, 0x7A, 0x7A, 0x4E, 0x50, 0x79, 0x2B, 0x69, 0x32, 0x2B, 0x66, 0x33, 0x56, 0x41, 0x4E, 0x66, ++ 0x57, 0x64, 0x50, 0x33, 0x6B, 0x58, 0x6A, 0x48, 0x69, 0x33, 0x64, 0x71, 0x46, 0x75, 0x56, 0x4A, 0x68, 0x5A, 0x42, 0x46, 0x63, 0x6E, 0x41, 0x76, 0x6B, 0x56, 0x33, 0x34, 0x50, 0x6D, 0x56, 0x41, 0x43, 0x78, 0x6D, 0x5A, 0x79, 0x53, 0x59, 0x67, ++ 0x0A, 0x57, 0x6D, 0x6A, 0x42, 0x4E, 0x62, 0x39, 0x50, 0x70, 0x31, 0x48, 0x78, 0x32, 0x42, 0x45, 0x72, 0x57, 0x2B, 0x43, 0x61, 0x6E, 0x69, 0x67, 0x37, 0x43, 0x6A, 0x6F, 0x4B, 0x48, 0x38, 0x47, 0x42, 0x35, 0x53, 0x37, 0x77, 0x70, 0x72, 0x6C, ++ 0x70, 0x70, 0x59, 0x69, 0x55, 0x35, 0x6D, 0x73, 0x54, 0x66, 0x39, 0x46, 0x6B, 0x50, 0x7A, 0x32, 0x63, 0x63, 0x45, 0x62, 0x6C, 0x6F, 0x6F, 0x56, 0x37, 0x57, 0x49, 0x51, 0x6E, 0x33, 0x4D, 0x53, 0x41, 0x50, 0x6D, 0x65, 0x61, 0x0A, 0x6D, 0x73, ++ 0x65, 0x61, 0x4D, 0x51, 0x34, 0x77, 0x37, 0x4F, 0x59, 0x58, 0x51, 0x4A, 0x58, 0x5A, 0x52, 0x65, 0x30, 0x42, 0x6C, 0x71, 0x71, 0x2F, 0x44, 0x50, 0x4E, 0x4C, 0x30, 0x57, 0x50, 0x33, 0x45, 0x31, 0x6A, 0x41, 0x75, 0x50, 0x50, 0x36, 0x5A, 0x39, ++ 0x32, 0x62, 0x66, 0x57, 0x31, 0x4B, 0x2F, 0x7A, 0x4A, 0x4D, 0x74, 0x53, 0x55, 0x37, 0x2F, 0x78, 0x78, 0x6E, 0x44, 0x34, 0x55, 0x69, 0x57, 0x51, 0x57, 0x52, 0x6B, 0x55, 0x46, 0x33, 0x67, 0x64, 0x43, 0x46, 0x0A, 0x54, 0x49, 0x63, 0x51, 0x63, ++ 0x66, 0x2B, 0x65, 0x51, 0x78, 0x75, 0x75, 0x6C, 0x58, 0x55, 0x74, 0x67, 0x51, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x6F, 0x32, 0x4D, 0x77, 0x59, 0x54, 0x41, 0x50, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x52, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, ++ 0x54, 0x41, 0x44, 0x41, 0x51, 0x48, 0x2F, 0x4D, 0x42, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x49, 0x77, 0x51, 0x59, 0x4D, 0x42, 0x61, 0x41, 0x46, 0x45, 0x44, 0x6B, 0x35, 0x50, 0x49, 0x6A, 0x0A, 0x37, 0x7A, 0x6A, 0x4B, 0x73, 0x4B, 0x35, 0x58, ++ 0x66, 0x2F, 0x49, 0x68, 0x4D, 0x42, 0x59, 0x30, 0x32, 0x37, 0x79, 0x53, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x52, 0x41, 0x35, 0x4F, 0x54, 0x79, 0x49, 0x2B, 0x38, 0x34, 0x79, 0x72, 0x43, 0x75, ++ 0x56, 0x33, 0x2F, 0x79, 0x49, 0x54, 0x41, 0x57, 0x4E, 0x4E, 0x75, 0x38, 0x6B, 0x6A, 0x41, 0x4F, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x42, 0x41, 0x66, 0x38, 0x45, 0x0A, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x51, 0x59, 0x77, 0x44, 0x51, 0x59, ++ 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4D, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x42, 0x41, 0x43, 0x59, 0x37, 0x55, 0x65, 0x46, 0x4E, 0x4F, 0x50, 0x4D, 0x79, 0x47, 0x4C, 0x53, 0x30, 0x58, 0x75, 0x46, ++ 0x6C, 0x58, 0x73, 0x53, 0x55, 0x54, 0x39, 0x53, 0x6E, 0x59, 0x61, 0x50, 0x34, 0x77, 0x4D, 0x38, 0x7A, 0x41, 0x51, 0x4C, 0x70, 0x77, 0x36, 0x6F, 0x31, 0x0A, 0x44, 0x2F, 0x47, 0x55, 0x45, 0x33, 0x64, 0x33, 0x4E, 0x5A, 0x34, 0x74, 0x56, 0x6C, ++ 0x46, 0x45, 0x62, 0x75, 0x48, 0x47, 0x4C, 0x69, 0x67, 0x65, 0x2F, 0x39, 0x72, 0x73, 0x52, 0x38, 0x32, 0x58, 0x52, 0x42, 0x66, 0x33, 0x34, 0x45, 0x7A, 0x43, 0x34, 0x58, 0x78, 0x38, 0x4D, 0x6E, 0x70, 0x6D, 0x79, 0x46, 0x71, 0x32, 0x58, 0x46, ++ 0x4E, 0x46, 0x56, 0x31, 0x70, 0x46, 0x31, 0x41, 0x57, 0x5A, 0x4C, 0x79, 0x34, 0x6A, 0x56, 0x65, 0x35, 0x6A, 0x61, 0x4E, 0x2F, 0x54, 0x0A, 0x47, 0x33, 0x69, 0x6E, 0x45, 0x70, 0x51, 0x47, 0x41, 0x48, 0x55, 0x4E, 0x63, 0x6F, 0x54, 0x70, 0x4C, ++ 0x72, 0x78, 0x61, 0x61, 0x74, 0x58, 0x65, 0x4C, 0x31, 0x6E, 0x48, 0x6F, 0x2B, 0x7A, 0x53, 0x68, 0x32, 0x62, 0x62, 0x74, 0x31, 0x53, 0x31, 0x4A, 0x4B, 0x76, 0x30, 0x51, 0x33, 0x6A, 0x62, 0x53, 0x77, 0x54, 0x45, 0x62, 0x39, 0x33, 0x6D, 0x50, ++ 0x6D, 0x59, 0x2B, 0x4B, 0x66, 0x4A, 0x4C, 0x61, 0x48, 0x45, 0x69, 0x68, 0x36, 0x44, 0x34, 0x73, 0x54, 0x4E, 0x6A, 0x0A, 0x64, 0x75, 0x4D, 0x4E, 0x68, 0x58, 0x4A, 0x45, 0x49, 0x6C, 0x55, 0x2F, 0x48, 0x48, 0x7A, 0x70, 0x2F, 0x4C, 0x67, 0x56, ++ 0x36, 0x46, 0x4C, 0x36, 0x71, 0x6A, 0x36, 0x6A, 0x49, 0x54, 0x6B, 0x31, 0x64, 0x49, 0x6D, 0x6D, 0x61, 0x73, 0x49, 0x35, 0x2B, 0x6E, 0x6A, 0x50, 0x74, 0x71, 0x7A, 0x6E, 0x35, 0x39, 0x5A, 0x57, 0x2F, 0x79, 0x4F, 0x53, 0x4C, 0x6C, 0x41, 0x4C, ++ 0x71, 0x62, 0x55, 0x48, 0x4D, 0x2F, 0x51, 0x34, 0x58, 0x36, 0x52, 0x4A, 0x70, 0x73, 0x74, 0x6C, 0x0A, 0x63, 0x48, 0x62, 0x6F, 0x43, 0x6F, 0x57, 0x41, 0x53, 0x7A, 0x59, 0x39, 0x4D, 0x2F, 0x65, 0x56, 0x56, 0x48, 0x55, 0x6C, 0x32, 0x71, 0x7A, ++ 0x45, 0x63, 0x34, 0x4A, 0x6C, 0x36, 0x56, 0x4C, 0x31, 0x58, 0x50, 0x30, 0x34, 0x6C, 0x51, 0x4A, 0x71, 0x61, 0x54, 0x44, 0x46, 0x48, 0x41, 0x70, 0x58, 0x42, 0x36, 0x34, 0x69, 0x70, 0x43, 0x7A, 0x35, 0x78, 0x55, 0x47, 0x33, 0x75, 0x4F, 0x79, ++ 0x66, 0x54, 0x30, 0x67, 0x41, 0x2B, 0x51, 0x45, 0x45, 0x56, 0x63, 0x79, 0x73, 0x0A, 0x2B, 0x54, 0x49, 0x78, 0x78, 0x48, 0x57, 0x56, 0x42, 0x71, 0x42, 0x2F, 0x30, 0x59, 0x30, 0x6E, 0x33, 0x62, 0x4F, 0x70, 0x70, 0x48, 0x4B, 0x48, 0x2F, 0x6C, ++ 0x6D, 0x4C, 0x6D, 0x6E, 0x70, 0x30, 0x46, 0x74, 0x30, 0x57, 0x70, 0x57, 0x49, 0x70, 0x36, 0x7A, 0x71, 0x57, 0x33, 0x49, 0x75, 0x6E, 0x61, 0x46, 0x6E, 0x54, 0x36, 0x33, 0x65, 0x52, 0x4F, 0x66, 0x6A, 0x58, 0x79, 0x39, 0x6D, 0x50, 0x58, 0x31, ++ 0x6F, 0x6E, 0x41, 0x58, 0x31, 0x64, 0x61, 0x42, 0x6C, 0x69, 0x0A, 0x32, 0x4D, 0x6A, 0x4E, 0x39, 0x4C, 0x64, 0x79, 0x52, 0x37, 0x35, 0x62, 0x6C, 0x38, 0x37, 0x79, 0x72, 0x61, 0x4B, 0x5A, 0x6B, 0x36, 0x32, 0x55, 0x79, 0x35, 0x50, 0x32, 0x45, ++ 0x67, 0x6D, 0x56, 0x74, 0x71, 0x76, 0x58, 0x4F, 0x39, 0x41, 0x2F, 0x45, 0x63, 0x73, 0x77, 0x46, 0x69, 0x35, 0x35, 0x67, 0x4F, 0x52, 0x6E, 0x67, 0x53, 0x31, 0x64, 0x37, 0x58, 0x42, 0x34, 0x74, 0x6D, 0x42, 0x5A, 0x72, 0x4F, 0x46, 0x64, 0x52, ++ 0x57, 0x4F, 0x50, 0x79, 0x4E, 0x39, 0x79, 0x0A, 0x61, 0x46, 0x76, 0x71, 0x48, 0x62, 0x67, 0x42, 0x38, 0x58, 0x37, 0x37, 0x35, 0x34, 0x71, 0x7A, 0x34, 0x31, 0x53, 0x67, 0x4F, 0x41, 0x6E, 0x67, 0x50, 0x4E, 0x35, 0x43, 0x38, 0x73, 0x4C, 0x74, ++ 0x4C, 0x70, 0x76, 0x7A, 0x48, 0x7A, 0x57, 0x32, 0x4E, 0x74, 0x6A, 0x6A, 0x67, 0x4B, 0x47, 0x4C, 0x7A, 0x5A, 0x6C, 0x6B, 0x44, 0x38, 0x4B, 0x71, 0x71, 0x37, 0x48, 0x4B, 0x39, 0x57, 0x2B, 0x65, 0x51, 0x34, 0x32, 0x45, 0x56, 0x4A, 0x6D, 0x7A, ++ 0x62, 0x73, 0x41, 0x53, 0x0A, 0x5A, 0x74, 0x68, 0x77, 0x45, 0x50, 0x45, 0x47, 0x4E, 0x54, 0x4E, 0x44, 0x71, 0x4A, 0x77, 0x75, 0x75, 0x68, 0x51, 0x78, 0x7A, 0x68, 0x42, 0x2F, 0x48, 0x49, 0x62, 0x6A, 0x6A, 0x39, 0x4C, 0x56, 0x2B, 0x48, 0x66, ++ 0x73, 0x6D, 0x36, 0x76, 0x78, 0x4C, 0x32, 0x50, 0x5A, 0x51, 0x6C, 0x2F, 0x67, 0x5A, 0x34, 0x46, 0x6B, 0x6B, 0x66, 0x47, 0x58, 0x4C, 0x2F, 0x78, 0x75, 0x4A, 0x76, 0x59, 0x7A, 0x2B, 0x4E, 0x4F, 0x31, 0x2B, 0x4D, 0x52, 0x69, 0x71, 0x7A, 0x46, ++ 0x52, 0x0A, 0x4A, 0x51, 0x4A, 0x36, 0x2B, 0x4E, 0x31, 0x72, 0x5A, 0x64, 0x56, 0x74, 0x54, 0x54, 0x44, 0x49, 0x5A, 0x62, 0x70, 0x6F, 0x46, 0x47, 0x57, 0x73, 0x4A, 0x77, 0x74, 0x30, 0x69, 0x76, 0x4B, 0x48, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, ++ 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, 0x69, 0x61, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, ++ 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x47, 0x34, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, ++ 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x43, 0x56, 0x54, 0x43, 0x43, 0x41, 0x64, 0x79, 0x67, 0x41, 0x77, ++ 0x49, 0x42, 0x41, 0x67, 0x49, 0x55, 0x54, 0x79, 0x4E, 0x6B, 0x75, 0x49, 0x36, 0x58, 0x59, 0x35, 0x37, 0x47, 0x55, 0x34, 0x48, 0x42, 0x64, 0x6B, 0x37, 0x4C, 0x4B, 0x6E, 0x51, 0x56, 0x31, 0x74, 0x63, 0x77, 0x43, 0x67, 0x59, 0x49, 0x4B, 0x6F, ++ 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x45, 0x41, 0x77, 0x4D, 0x77, 0x57, 0x6A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x0A, 0x42, 0x68, 0x4D, 0x43, 0x51, 0x30, 0x34, 0x78, 0x4A, 0x54, 0x41, 0x6A, 0x42, 0x67, 0x4E, 0x56, 0x42, ++ 0x41, 0x6F, 0x4D, 0x48, 0x46, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x51, 0x58, 0x4E, 0x70, 0x59, 0x53, 0x42, 0x55, 0x5A, 0x57, 0x4E, 0x6F, 0x62, 0x6D, 0x39, 0x73, 0x62, 0x32, 0x64, 0x70, 0x5A, 0x58, 0x4D, 0x73, 0x49, 0x45, 0x6C, 0x75, 0x59, ++ 0x79, 0x34, 0x78, 0x4A, 0x44, 0x41, 0x69, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x4D, 0x47, 0x31, 0x52, 0x79, 0x0A, 0x64, 0x58, 0x4E, 0x30, 0x51, 0x58, 0x4E, 0x70, 0x59, 0x53, 0x42, 0x48, 0x62, 0x47, 0x39, 0x69, 0x59, 0x57, 0x77, 0x67, ++ 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x51, 0x53, 0x42, 0x48, 0x4E, 0x44, 0x41, 0x65, 0x46, 0x77, 0x30, 0x79, 0x4D, 0x54, 0x41, 0x31, 0x4D, 0x6A, 0x41, 0x77, 0x4D, 0x6A, 0x45, 0x77, 0x4D, 0x6A, 0x4A, 0x61, 0x46, 0x77, 0x30, 0x30, ++ 0x4E, 0x6A, 0x41, 0x31, 0x4D, 0x54, 0x6B, 0x77, 0x4D, 0x6A, 0x45, 0x77, 0x4D, 0x6A, 0x4A, 0x61, 0x0A, 0x4D, 0x46, 0x6F, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6B, 0x4E, 0x4F, 0x4D, 0x53, 0x55, ++ 0x77, 0x49, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x44, 0x42, 0x78, 0x55, 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x45, 0x46, 0x7A, 0x61, 0x57, 0x45, 0x67, 0x56, 0x47, 0x56, 0x6A, 0x61, 0x47, 0x35, 0x76, 0x62, 0x47, 0x39, 0x6E, 0x61, 0x57, 0x56, ++ 0x7A, 0x4C, 0x43, 0x42, 0x4A, 0x62, 0x6D, 0x4D, 0x75, 0x4D, 0x53, 0x51, 0x77, 0x0A, 0x49, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x44, 0x42, 0x74, 0x55, 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x45, 0x46, 0x7A, 0x61, 0x57, 0x45, 0x67, 0x52, 0x32, ++ 0x78, 0x76, 0x59, 0x6D, 0x46, 0x73, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x67, 0x52, 0x7A, 0x51, 0x77, 0x64, 0x6A, 0x41, 0x51, 0x42, 0x67, 0x63, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x49, 0x42, 0x42, 0x67, ++ 0x55, 0x72, 0x67, 0x51, 0x51, 0x41, 0x49, 0x67, 0x4E, 0x69, 0x0A, 0x41, 0x41, 0x54, 0x78, 0x73, 0x38, 0x30, 0x34, 0x35, 0x43, 0x56, 0x44, 0x35, 0x64, 0x34, 0x5A, 0x43, 0x62, 0x75, 0x42, 0x65, 0x61, 0x49, 0x56, 0x58, 0x78, 0x56, 0x6A, 0x41, ++ 0x64, 0x37, 0x43, 0x71, 0x39, 0x32, 0x7A, 0x70, 0x68, 0x74, 0x6E, 0x53, 0x34, 0x43, 0x44, 0x72, 0x35, 0x6E, 0x4C, 0x72, 0x42, 0x66, 0x62, 0x4B, 0x35, 0x62, 0x4B, 0x66, 0x46, 0x4A, 0x56, 0x34, 0x68, 0x72, 0x68, 0x50, 0x56, 0x62, 0x77, 0x4C, ++ 0x78, 0x59, 0x49, 0x2B, 0x68, 0x57, 0x38, 0x0A, 0x6D, 0x37, 0x74, 0x48, 0x35, 0x6A, 0x2F, 0x75, 0x71, 0x4F, 0x46, 0x4D, 0x6A, 0x50, 0x58, 0x54, 0x4E, 0x76, 0x6B, 0x34, 0x58, 0x61, 0x74, 0x77, 0x6D, 0x6B, 0x63, 0x4E, 0x34, 0x6F, 0x46, 0x42, ++ 0x42, 0x75, 0x74, 0x4A, 0x2B, 0x62, 0x41, 0x70, 0x33, 0x54, 0x50, 0x73, 0x55, 0x4B, 0x56, 0x2F, 0x65, 0x53, 0x6D, 0x34, 0x49, 0x4A, 0x69, 0x6A, 0x59, 0x7A, 0x42, 0x68, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, ++ 0x2F, 0x77, 0x51, 0x46, 0x0A, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x48, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x6A, 0x42, 0x42, 0x67, 0x77, 0x46, 0x6F, 0x41, 0x55, 0x70, 0x62, 0x74, 0x4B, 0x6C, 0x38, 0x36, 0x7A, 0x4B, 0x33, 0x2B, ++ 0x6B, 0x4D, 0x64, 0x36, 0x58, 0x67, 0x31, 0x6D, 0x44, 0x70, 0x6D, 0x39, 0x78, 0x79, 0x39, 0x34, 0x77, 0x48, 0x51, 0x59, 0x44, 0x56, 0x52, 0x30, 0x4F, 0x42, 0x42, 0x59, 0x45, 0x46, 0x4B, 0x57, 0x37, 0x53, 0x70, 0x66, 0x4F, 0x73, 0x79, 0x74, ++ 0x2F, 0x0A, 0x70, 0x44, 0x48, 0x65, 0x6C, 0x34, 0x4E, 0x5A, 0x67, 0x36, 0x5A, 0x76, 0x63, 0x63, 0x76, 0x65, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x42, 0x42, 0x6A, ++ 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x77, 0x4E, 0x6E, 0x41, 0x44, 0x42, 0x6B, 0x41, 0x6A, 0x42, 0x65, 0x38, 0x75, 0x73, 0x47, 0x7A, 0x45, 0x6B, 0x78, 0x6E, 0x30, 0x41, 0x41, 0x0A, 0x62, ++ 0x62, 0x64, 0x2B, 0x4E, 0x76, 0x42, 0x4E, 0x45, 0x55, 0x2F, 0x7A, 0x79, 0x34, 0x6B, 0x36, 0x4C, 0x48, 0x69, 0x52, 0x55, 0x4B, 0x4E, 0x62, 0x77, 0x4D, 0x70, 0x31, 0x4A, 0x76, 0x4B, 0x2F, 0x6B, 0x46, 0x30, 0x4C, 0x67, 0x6F, 0x78, 0x67, 0x4B, ++ 0x4A, 0x2F, 0x47, 0x63, 0x4A, 0x70, 0x6F, 0x35, 0x50, 0x45, 0x43, 0x4D, 0x46, 0x78, 0x59, 0x44, 0x6C, 0x5A, 0x32, 0x7A, 0x31, 0x6A, 0x44, 0x31, 0x78, 0x43, 0x4D, 0x75, 0x6F, 0x36, 0x75, 0x34, 0x37, 0x78, 0x6B, 0x0A, 0x64, 0x55, 0x66, 0x46, ++ 0x56, 0x5A, 0x44, 0x6A, 0x2F, 0x62, 0x70, 0x56, 0x36, 0x77, 0x66, 0x45, 0x55, 0x36, 0x73, 0x33, 0x71, 0x65, 0x34, 0x68, 0x73, 0x69, 0x46, 0x62, 0x59, 0x49, 0x38, 0x39, 0x4D, 0x76, 0x48, 0x56, 0x49, 0x35, 0x54, 0x57, 0x57, 0x41, 0x3D, 0x3D, ++ 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x54, 0x65, 0x6C, 0x65, 0x6B, 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, ++ 0x72, 0x69, 0x74, 0x79, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x32, 0x30, 0x32, 0x30, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, ++ 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x43, 0x51, 0x6A, 0x43, 0x43, 0x41, 0x63, 0x6D, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x4E, 0x6A, 0x71, 0x57, 0x6A, 0x4D, 0x6C, 0x63, 0x73, 0x6C, 0x6A, 0x4E, 0x30, 0x41, ++ 0x46, 0x64, 0x78, 0x65, 0x56, 0x58, 0x41, 0x44, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x7A, 0x42, 0x6A, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, ++ 0x4A, 0x45, 0x0A, 0x52, 0x54, 0x45, 0x6E, 0x4D, 0x43, 0x55, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, 0x65, 0x52, 0x47, 0x56, 0x31, 0x64, 0x48, 0x4E, 0x6A, 0x61, 0x47, 0x55, 0x67, 0x56, 0x47, 0x56, 0x73, 0x5A, 0x57, 0x74, 0x76, 0x62, ++ 0x53, 0x42, 0x54, 0x5A, 0x57, 0x4E, 0x31, 0x63, 0x6D, 0x6C, 0x30, 0x65, 0x53, 0x42, 0x48, 0x62, 0x57, 0x4A, 0x49, 0x4D, 0x53, 0x73, 0x77, 0x4B, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x44, 0x43, 0x4A, 0x55, 0x5A, 0x57, 0x78, 0x6C, 0x0A, ++ 0x61, 0x32, 0x39, 0x74, 0x49, 0x46, 0x4E, 0x6C, 0x59, 0x33, 0x56, 0x79, 0x61, 0x58, 0x52, 0x35, 0x49, 0x46, 0x52, 0x4D, 0x55, 0x79, 0x42, 0x46, 0x51, 0x30, 0x4D, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x41, 0x79, 0x4D, 0x44, 0x49, 0x77, ++ 0x4D, 0x42, 0x34, 0x58, 0x44, 0x54, 0x49, 0x77, 0x4D, 0x44, 0x67, 0x79, 0x4E, 0x54, 0x41, 0x33, 0x4E, 0x44, 0x67, 0x79, 0x4D, 0x46, 0x6F, 0x58, 0x44, 0x54, 0x51, 0x31, 0x4D, 0x44, 0x67, 0x79, 0x4E, 0x54, 0x49, 0x7A, 0x0A, 0x4E, 0x54, 0x6B, ++ 0x31, 0x4F, 0x56, 0x6F, 0x77, 0x59, 0x7A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x52, 0x45, 0x55, 0x78, 0x4A, 0x7A, 0x41, 0x6C, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x4D, 0x48, 0x6B, 0x52, ++ 0x6C, 0x64, 0x58, 0x52, 0x7A, 0x59, 0x32, 0x68, 0x6C, 0x49, 0x46, 0x52, 0x6C, 0x62, 0x47, 0x56, 0x72, 0x62, 0x32, 0x30, 0x67, 0x55, 0x32, 0x56, 0x6A, 0x64, 0x58, 0x4A, 0x70, 0x64, 0x48, 0x6B, 0x67, 0x0A, 0x52, 0x32, 0x31, 0x69, 0x53, 0x44, ++ 0x45, 0x72, 0x4D, 0x43, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x77, 0x77, 0x69, 0x56, 0x47, 0x56, 0x73, 0x5A, 0x57, 0x74, 0x76, 0x62, 0x53, 0x42, 0x54, 0x5A, 0x57, 0x4E, 0x31, 0x63, 0x6D, 0x6C, 0x30, 0x65, 0x53, 0x42, 0x55, 0x54, 0x46, ++ 0x4D, 0x67, 0x52, 0x55, 0x4E, 0x44, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x4D, 0x6A, 0x41, 0x79, 0x4D, 0x44, 0x42, 0x32, 0x4D, 0x42, 0x41, 0x47, 0x42, 0x79, 0x71, 0x47, 0x0A, 0x53, 0x4D, 0x34, 0x39, 0x41, 0x67, 0x45, 0x47, 0x42, ++ 0x53, 0x75, 0x42, 0x42, 0x41, 0x41, 0x69, 0x41, 0x32, 0x49, 0x41, 0x42, 0x4D, 0x36, 0x2F, 0x2F, 0x6C, 0x65, 0x6F, 0x76, 0x39, 0x57, 0x71, 0x39, 0x78, 0x43, 0x61, 0x7A, 0x62, 0x7A, 0x52, 0x45, 0x61, 0x4B, 0x39, 0x5A, 0x30, 0x4C, 0x4D, 0x6B, ++ 0x4F, 0x73, 0x56, 0x47, 0x4A, 0x44, 0x5A, 0x6F, 0x73, 0x30, 0x4D, 0x4B, 0x69, 0x58, 0x72, 0x50, 0x6B, 0x2F, 0x4F, 0x74, 0x64, 0x4B, 0x50, 0x44, 0x2F, 0x4D, 0x31, 0x0A, 0x32, 0x6B, 0x4F, 0x4C, 0x41, 0x6F, 0x43, 0x2B, 0x62, 0x31, 0x45, 0x6B, ++ 0x48, 0x51, 0x39, 0x72, 0x4B, 0x38, 0x71, 0x66, 0x77, 0x6D, 0x39, 0x51, 0x4D, 0x75, 0x55, 0x33, 0x49, 0x4C, 0x59, 0x67, 0x2F, 0x34, 0x67, 0x4E, 0x44, 0x32, 0x31, 0x4A, 0x75, 0x39, 0x73, 0x47, 0x70, 0x49, 0x65, 0x51, 0x6B, 0x70, 0x54, 0x30, ++ 0x43, 0x64, 0x44, 0x50, 0x66, 0x38, 0x69, 0x41, 0x43, 0x38, 0x47, 0x58, 0x73, 0x37, 0x73, 0x31, 0x4A, 0x38, 0x6E, 0x43, 0x47, 0x36, 0x4E, 0x43, 0x0A, 0x4D, 0x45, 0x41, 0x77, 0x48, 0x51, 0x59, 0x44, 0x56, 0x52, 0x30, 0x4F, 0x42, 0x42, 0x59, ++ 0x45, 0x46, 0x4F, 0x4E, 0x79, 0x7A, 0x47, 0x36, 0x56, 0x6D, 0x55, 0x65, 0x78, 0x35, 0x72, 0x4E, 0x68, 0x54, 0x4E, 0x48, 0x4C, 0x71, 0x2B, 0x4F, 0x36, 0x7A, 0x64, 0x36, 0x66, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, ++ 0x42, 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x0A, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x51, 0x44, 0x41, 0x67, 0x45, 0x47, 0x4D, 0x41, 0x6F, 0x47, 0x43, 0x43, ++ 0x71, 0x47, 0x53, 0x4D, 0x34, 0x39, 0x42, 0x41, 0x4D, 0x44, 0x41, 0x32, 0x63, 0x41, 0x4D, 0x47, 0x51, 0x43, 0x4D, 0x48, 0x56, 0x53, 0x69, 0x37, 0x65, 0x6B, 0x45, 0x45, 0x2B, 0x75, 0x53, 0x68, 0x43, 0x4C, 0x73, 0x6F, 0x52, 0x62, 0x51, 0x75, ++ 0x48, 0x6D, 0x4B, 0x6A, 0x59, 0x43, 0x32, 0x71, 0x42, 0x75, 0x47, 0x54, 0x38, 0x6C, 0x76, 0x39, 0x70, 0x5A, 0x0A, 0x4D, 0x6F, 0x37, 0x6B, 0x2B, 0x35, 0x44, 0x63, 0x6B, 0x32, 0x54, 0x4F, 0x72, 0x62, 0x52, 0x42, 0x52, 0x32, 0x44, 0x69, 0x7A, ++ 0x36, 0x66, 0x4C, 0x48, 0x67, 0x49, 0x77, 0x4E, 0x30, 0x47, 0x4D, 0x5A, 0x74, 0x39, 0x42, 0x61, 0x39, 0x61, 0x44, 0x41, 0x45, 0x48, 0x39, 0x4C, 0x31, 0x72, 0x33, 0x55, 0x4C, 0x52, 0x6E, 0x30, 0x53, 0x79, 0x6F, 0x63, 0x64, 0x64, 0x44, 0x79, ++ 0x70, 0x77, 0x6E, 0x4A, 0x4A, 0x47, 0x44, 0x53, 0x41, 0x33, 0x50, 0x7A, 0x66, 0x64, 0x55, 0x0A, 0x67, 0x61, 0x2F, 0x73, 0x66, 0x2B, 0x52, 0x6E, 0x32, 0x37, 0x69, 0x51, 0x37, 0x74, 0x30, 0x6C, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, ++ 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x54, 0x65, 0x6C, 0x65, 0x6B, 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x54, 0x4C, 0x53, ++ 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x32, 0x30, 0x32, 0x33, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, ++ 0x49, 0x46, 0x73, 0x7A, 0x43, 0x43, 0x41, 0x35, 0x75, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x49, 0x5A, 0x78, 0x55, 0x4C, 0x65, 0x6A, 0x32, 0x37, 0x48, 0x46, 0x33, 0x2B, 0x6B, 0x37, 0x6F, 0x77, 0x33, 0x42, 0x58, 0x6C, 0x7A, ++ 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x77, 0x46, 0x41, 0x44, 0x42, 0x6A, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x0A, 0x45, 0x77, 0x4A, 0x45, 0x52, ++ 0x54, 0x45, 0x6E, 0x4D, 0x43, 0x55, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, 0x65, 0x52, 0x47, 0x56, 0x31, 0x64, 0x48, 0x4E, 0x6A, 0x61, 0x47, 0x55, 0x67, 0x56, 0x47, 0x56, 0x73, 0x5A, 0x57, 0x74, 0x76, 0x62, 0x53, 0x42, 0x54, 0x5A, ++ 0x57, 0x4E, 0x31, 0x63, 0x6D, 0x6C, 0x30, 0x65, 0x53, 0x42, 0x48, 0x62, 0x57, 0x4A, 0x49, 0x4D, 0x53, 0x73, 0x77, 0x4B, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x44, 0x43, 0x4A, 0x55, 0x0A, 0x5A, 0x57, 0x78, 0x6C, 0x61, 0x32, 0x39, 0x74, ++ 0x49, 0x46, 0x4E, 0x6C, 0x59, 0x33, 0x56, 0x79, 0x61, 0x58, 0x52, 0x35, 0x49, 0x46, 0x52, 0x4D, 0x55, 0x79, 0x42, 0x53, 0x55, 0x30, 0x45, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x41, 0x79, 0x4D, 0x44, 0x49, 0x7A, 0x4D, 0x42, 0x34, 0x58, ++ 0x44, 0x54, 0x49, 0x7A, 0x4D, 0x44, 0x4D, 0x79, 0x4F, 0x44, 0x45, 0x79, 0x4D, 0x54, 0x59, 0x30, 0x4E, 0x56, 0x6F, 0x58, 0x44, 0x54, 0x51, 0x34, 0x4D, 0x44, 0x4D, 0x79, 0x0A, 0x4E, 0x7A, 0x49, 0x7A, 0x4E, 0x54, 0x6B, 0x31, 0x4F, 0x56, 0x6F, ++ 0x77, 0x59, 0x7A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x52, 0x45, 0x55, 0x78, 0x4A, 0x7A, 0x41, 0x6C, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x4D, 0x48, 0x6B, 0x52, 0x6C, 0x64, 0x58, 0x52, ++ 0x7A, 0x59, 0x32, 0x68, 0x6C, 0x49, 0x46, 0x52, 0x6C, 0x62, 0x47, 0x56, 0x72, 0x62, 0x32, 0x30, 0x67, 0x55, 0x32, 0x56, 0x6A, 0x64, 0x58, 0x4A, 0x70, 0x0A, 0x64, 0x48, 0x6B, 0x67, 0x52, 0x32, 0x31, 0x69, 0x53, 0x44, 0x45, 0x72, 0x4D, 0x43, ++ 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x77, 0x77, 0x69, 0x56, 0x47, 0x56, 0x73, 0x5A, 0x57, 0x74, 0x76, 0x62, 0x53, 0x42, 0x54, 0x5A, 0x57, 0x4E, 0x31, 0x63, 0x6D, 0x6C, 0x30, 0x65, 0x53, 0x42, 0x55, 0x54, 0x46, 0x4D, 0x67, 0x55, 0x6C, ++ 0x4E, 0x42, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x4D, 0x6A, 0x41, 0x79, 0x4D, 0x7A, 0x43, 0x43, 0x41, 0x69, 0x49, 0x77, 0x0A, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x42, 0x42, ++ 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x50, 0x41, 0x44, 0x43, 0x43, 0x41, 0x67, 0x6F, 0x43, 0x67, 0x67, 0x49, 0x42, 0x41, 0x4F, 0x30, 0x31, 0x6F, 0x59, 0x47, 0x41, 0x38, 0x38, 0x74, 0x4B, 0x61, 0x56, 0x76, 0x43, 0x2B, 0x31, 0x47, 0x44, 0x72, ++ 0x69, 0x62, 0x39, 0x34, 0x57, 0x37, 0x7A, 0x67, 0x52, 0x4A, 0x39, 0x63, 0x55, 0x44, 0x2F, 0x68, 0x33, 0x56, 0x43, 0x0A, 0x4B, 0x53, 0x48, 0x74, 0x67, 0x56, 0x49, 0x73, 0x33, 0x78, 0x4C, 0x42, 0x47, 0x59, 0x53, 0x4A, 0x77, 0x62, 0x33, 0x46, ++ 0x4B, 0x4E, 0x58, 0x56, 0x53, 0x32, 0x78, 0x45, 0x31, 0x6B, 0x7A, 0x62, 0x42, 0x35, 0x5A, 0x4B, 0x56, 0x58, 0x72, 0x4B, 0x4E, 0x6F, 0x49, 0x45, 0x4E, 0x71, 0x69, 0x6C, 0x2F, 0x43, 0x66, 0x32, 0x53, 0x66, 0x48, 0x56, 0x63, 0x70, 0x36, 0x52, ++ 0x2B, 0x53, 0x50, 0x57, 0x63, 0x48, 0x75, 0x37, 0x39, 0x5A, 0x76, 0x42, 0x37, 0x4A, 0x50, 0x50, 0x0A, 0x47, 0x65, 0x70, 0x6C, 0x66, 0x6F, 0x68, 0x77, 0x6F, 0x48, 0x50, 0x38, 0x39, 0x76, 0x2B, 0x31, 0x56, 0x6D, 0x4C, 0x68, 0x63, 0x32, 0x6F, ++ 0x30, 0x6D, 0x44, 0x36, 0x43, 0x75, 0x4B, 0x79, 0x56, 0x55, 0x2F, 0x51, 0x42, 0x6F, 0x43, 0x63, 0x48, 0x63, 0x71, 0x4D, 0x41, 0x55, 0x36, 0x44, 0x6B, 0x73, 0x71, 0x75, 0x44, 0x4F, 0x46, 0x63, 0x7A, 0x4A, 0x5A, 0x53, 0x66, 0x76, 0x6B, 0x67, ++ 0x64, 0x6D, 0x4F, 0x47, 0x6A, 0x75, 0x70, 0x35, 0x63, 0x7A, 0x51, 0x52, 0x78, 0x0A, 0x55, 0x58, 0x31, 0x31, 0x65, 0x4B, 0x76, 0x7A, 0x57, 0x61, 0x72, 0x45, 0x34, 0x47, 0x43, 0x2B, 0x6A, 0x34, 0x4E, 0x53, 0x75, 0x48, 0x55, 0x61, 0x51, 0x54, ++ 0x58, 0x74, 0x76, 0x50, 0x4D, 0x36, 0x59, 0x2B, 0x6D, 0x70, 0x46, 0x45, 0x58, 0x58, 0x35, 0x6C, 0x4C, 0x52, 0x62, 0x74, 0x4C, 0x65, 0x76, 0x4F, 0x50, 0x31, 0x43, 0x7A, 0x76, 0x6D, 0x34, 0x4D, 0x53, 0x39, 0x51, 0x32, 0x51, 0x54, 0x70, 0x73, ++ 0x37, 0x30, 0x6D, 0x44, 0x64, 0x73, 0x69, 0x70, 0x57, 0x6F, 0x0A, 0x6C, 0x38, 0x68, 0x48, 0x44, 0x2F, 0x42, 0x65, 0x45, 0x49, 0x76, 0x6E, 0x48, 0x52, 0x7A, 0x2B, 0x73, 0x54, 0x75, 0x67, 0x42, 0x54, 0x4E, 0x6F, 0x42, 0x55, 0x47, 0x43, 0x77, ++ 0x51, 0x4D, 0x72, 0x41, 0x63, 0x6A, 0x6E, 0x6A, 0x30, 0x32, 0x72, 0x36, 0x4C, 0x58, 0x32, 0x7A, 0x57, 0x74, 0x45, 0x74, 0x65, 0x66, 0x64, 0x69, 0x2B, 0x7A, 0x71, 0x4A, 0x62, 0x51, 0x41, 0x49, 0x6C, 0x64, 0x4E, 0x73, 0x4C, 0x47, 0x79, 0x4D, ++ 0x63, 0x45, 0x57, 0x7A, 0x76, 0x2F, 0x39, 0x0A, 0x46, 0x49, 0x53, 0x33, 0x52, 0x2F, 0x71, 0x79, 0x38, 0x58, 0x44, 0x65, 0x32, 0x34, 0x74, 0x73, 0x4E, 0x6C, 0x69, 0x6B, 0x66, 0x4C, 0x4D, 0x52, 0x30, 0x63, 0x4E, 0x33, 0x66, 0x31, 0x2B, 0x32, ++ 0x4A, 0x65, 0x41, 0x4E, 0x78, 0x64, 0x4B, 0x7A, 0x2B, 0x62, 0x69, 0x34, 0x64, 0x39, 0x73, 0x33, 0x63, 0x58, 0x46, 0x48, 0x34, 0x32, 0x41, 0x59, 0x54, 0x79, 0x53, 0x32, 0x64, 0x54, 0x64, 0x34, 0x75, 0x61, 0x4E, 0x69, 0x72, 0x37, 0x33, 0x4A, ++ 0x63, 0x6F, 0x34, 0x76, 0x0A, 0x7A, 0x4C, 0x75, 0x75, 0x32, 0x2B, 0x51, 0x56, 0x55, 0x68, 0x6B, 0x48, 0x4D, 0x2F, 0x74, 0x71, 0x74, 0x79, 0x31, 0x4C, 0x6B, 0x43, 0x69, 0x43, 0x63, 0x2F, 0x34, 0x59, 0x69, 0x7A, 0x57, 0x4E, 0x32, 0x36, 0x63, ++ 0x45, 0x61, 0x72, 0x37, 0x71, 0x77, 0x55, 0x30, 0x32, 0x4F, 0x78, 0x59, 0x32, 0x6B, 0x54, 0x4C, 0x76, 0x74, 0x6B, 0x43, 0x4A, 0x6B, 0x55, 0x50, 0x67, 0x38, 0x71, 0x4B, 0x72, 0x42, 0x43, 0x37, 0x6D, 0x38, 0x6B, 0x77, 0x4F, 0x46, 0x6A, 0x51, ++ 0x67, 0x0A, 0x72, 0x49, 0x66, 0x42, 0x4C, 0x58, 0x37, 0x4A, 0x5A, 0x6B, 0x63, 0x58, 0x46, 0x42, 0x47, 0x6B, 0x38, 0x2F, 0x65, 0x68, 0x4A, 0x49, 0x6D, 0x72, 0x32, 0x42, 0x72, 0x49, 0x6F, 0x56, 0x79, 0x78, 0x6F, 0x2F, 0x65, 0x4D, 0x62, 0x63, ++ 0x67, 0x42, 0x79, 0x55, 0x2F, 0x4A, 0x37, 0x4D, 0x54, 0x38, 0x72, 0x46, 0x45, 0x7A, 0x30, 0x63, 0x69, 0x44, 0x30, 0x63, 0x6D, 0x66, 0x48, 0x64, 0x52, 0x48, 0x4E, 0x43, 0x6B, 0x2B, 0x79, 0x37, 0x41, 0x4F, 0x2B, 0x6F, 0x4D, 0x4C, 0x0A, 0x4B, ++ 0x46, 0x6A, 0x6C, 0x4B, 0x64, 0x77, 0x2F, 0x66, 0x4B, 0x69, 0x66, 0x79, 0x62, 0x59, 0x4B, 0x75, 0x36, 0x62, 0x6F, 0x52, 0x68, 0x59, 0x50, 0x6C, 0x75, 0x56, 0x37, 0x35, 0x47, 0x70, 0x36, 0x53, 0x47, 0x31, 0x32, 0x6D, 0x41, 0x57, 0x6C, 0x33, ++ 0x47, 0x30, 0x65, 0x51, 0x68, 0x35, 0x43, 0x32, 0x68, 0x72, 0x67, 0x55, 0x76, 0x65, 0x31, 0x67, 0x38, 0x41, 0x61, 0x65, 0x33, 0x67, 0x31, 0x4C, 0x44, 0x6A, 0x31, 0x48, 0x2F, 0x31, 0x4A, 0x6F, 0x79, 0x37, 0x53, 0x0A, 0x57, 0x57, 0x4F, 0x2F, ++ 0x67, 0x4C, 0x43, 0x4D, 0x6B, 0x33, 0x50, 0x4C, 0x4E, 0x61, 0x61, 0x5A, 0x6C, 0x53, 0x4A, 0x68, 0x5A, 0x51, 0x4E, 0x67, 0x2B, 0x79, 0x2B, 0x54, 0x53, 0x2F, 0x71, 0x61, 0x6E, 0x49, 0x41, 0x37, 0x41, 0x67, 0x4D, 0x42, 0x41, 0x41, 0x47, 0x6A, ++ 0x59, 0x7A, 0x42, 0x68, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x42, 0x42, 0x6A, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x0A, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, ++ 0x55, 0x74, 0x71, 0x65, 0x58, 0x67, 0x6A, 0x31, 0x30, 0x68, 0x5A, 0x76, 0x33, 0x50, 0x4A, 0x2B, 0x54, 0x6D, 0x70, 0x56, 0x35, 0x64, 0x56, 0x4B, 0x4D, 0x62, 0x55, 0x63, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, ++ 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x66, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x53, 0x4D, 0x45, 0x47, 0x44, 0x41, 0x57, 0x67, 0x42, 0x53, 0x32, 0x0A, 0x70, 0x35, 0x65, 0x43, 0x50, 0x58, 0x53, 0x46, 0x6D, 0x2F, ++ 0x63, 0x38, 0x6E, 0x35, 0x4F, 0x61, 0x6C, 0x58, 0x6C, 0x31, 0x55, 0x6F, 0x78, 0x74, 0x52, 0x7A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x77, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x67, ++ 0x45, 0x41, 0x71, 0x4D, 0x78, 0x68, 0x70, 0x72, 0x35, 0x31, 0x6E, 0x68, 0x56, 0x51, 0x70, 0x47, 0x76, 0x37, 0x71, 0x48, 0x42, 0x46, 0x66, 0x4C, 0x70, 0x2B, 0x0A, 0x73, 0x56, 0x72, 0x38, 0x57, 0x79, 0x50, 0x36, 0x43, 0x6E, 0x66, 0x34, 0x6D, ++ 0x48, 0x47, 0x43, 0x44, 0x47, 0x33, 0x67, 0x58, 0x6B, 0x61, 0x71, 0x6B, 0x2F, 0x51, 0x65, 0x6F, 0x4D, 0x50, 0x68, 0x6B, 0x39, 0x74, 0x4C, 0x72, 0x62, 0x4B, 0x6D, 0x58, 0x61, 0x75, 0x77, 0x31, 0x47, 0x4C, 0x4C, 0x58, 0x72, 0x74, 0x6D, 0x39, ++ 0x53, 0x33, 0x75, 0x6C, 0x30, 0x41, 0x38, 0x59, 0x75, 0x74, 0x65, 0x31, 0x68, 0x54, 0x57, 0x6A, 0x4F, 0x4B, 0x57, 0x69, 0x30, 0x46, 0x70, 0x0A, 0x6B, 0x7A, 0x58, 0x6D, 0x75, 0x5A, 0x6C, 0x72, 0x59, 0x72, 0x53, 0x68, 0x46, 0x32, 0x59, 0x30, ++ 0x70, 0x6D, 0x74, 0x6A, 0x78, 0x72, 0x6C, 0x4F, 0x38, 0x69, 0x4C, 0x70, 0x57, 0x41, 0x31, 0x57, 0x51, 0x64, 0x48, 0x36, 0x44, 0x45, 0x72, 0x77, 0x4D, 0x38, 0x30, 0x37, 0x75, 0x32, 0x30, 0x68, 0x4F, 0x71, 0x36, 0x4F, 0x63, 0x72, 0x58, 0x44, ++ 0x53, 0x76, 0x76, 0x70, 0x66, 0x65, 0x57, 0x78, 0x6D, 0x34, 0x62, 0x75, 0x34, 0x75, 0x42, 0x39, 0x74, 0x50, 0x63, 0x79, 0x0A, 0x2F, 0x53, 0x4B, 0x45, 0x38, 0x59, 0x58, 0x4A, 0x4E, 0x33, 0x6E, 0x70, 0x74, 0x54, 0x2B, 0x2F, 0x58, 0x4F, 0x52, ++ 0x30, 0x73, 0x6F, 0x38, 0x52, 0x59, 0x67, 0x44, 0x64, 0x47, 0x47, 0x61, 0x68, 0x32, 0x58, 0x73, 0x6A, 0x58, 0x2F, 0x47, 0x4F, 0x31, 0x57, 0x66, 0x6F, 0x56, 0x4E, 0x70, 0x62, 0x4F, 0x6D, 0x73, 0x32, 0x62, 0x2F, 0x6D, 0x42, 0x73, 0x54, 0x4E, ++ 0x48, 0x4D, 0x33, 0x64, 0x41, 0x2B, 0x56, 0x4B, 0x71, 0x33, 0x64, 0x53, 0x44, 0x7A, 0x34, 0x56, 0x34, 0x0A, 0x6D, 0x5A, 0x71, 0x54, 0x75, 0x58, 0x4E, 0x6E, 0x51, 0x6B, 0x59, 0x52, 0x49, 0x65, 0x72, 0x2B, 0x43, 0x71, 0x6B, 0x62, 0x47, 0x6D, ++ 0x56, 0x70, 0x73, 0x34, 0x2B, 0x75, 0x46, 0x72, 0x62, 0x32, 0x53, 0x31, 0x61, 0x79, 0x4C, 0x66, 0x6D, 0x6C, 0x79, 0x4F, 0x77, 0x37, 0x59, 0x71, 0x50, 0x74, 0x61, 0x39, 0x42, 0x4F, 0x31, 0x55, 0x41, 0x4A, 0x70, 0x42, 0x2B, 0x59, 0x31, 0x7A, ++ 0x71, 0x6C, 0x6B, 0x6C, 0x6B, 0x67, 0x35, 0x4C, 0x42, 0x39, 0x7A, 0x56, 0x74, 0x7A, 0x0A, 0x61, 0x4C, 0x31, 0x74, 0x78, 0x4B, 0x49, 0x54, 0x44, 0x6D, 0x63, 0x5A, 0x75, 0x49, 0x31, 0x43, 0x66, 0x6D, 0x77, 0x4D, 0x6D, 0x6D, 0x36, 0x67, 0x4A, ++ 0x43, 0x33, 0x56, 0x52, 0x52, 0x76, 0x63, 0x78, 0x41, 0x49, 0x55, 0x2F, 0x6F, 0x56, 0x62, 0x5A, 0x5A, 0x66, 0x4B, 0x54, 0x70, 0x42, 0x51, 0x43, 0x48, 0x70, 0x43, 0x4E, 0x66, 0x6E, 0x71, 0x77, 0x6D, 0x62, 0x55, 0x2B, 0x41, 0x47, 0x75, 0x48, ++ 0x72, 0x53, 0x2B, 0x77, 0x36, 0x6A, 0x76, 0x2F, 0x6E, 0x61, 0x61, 0x0A, 0x6F, 0x71, 0x59, 0x66, 0x52, 0x76, 0x61, 0x45, 0x37, 0x66, 0x7A, 0x62, 0x7A, 0x73, 0x51, 0x43, 0x7A, 0x6E, 0x64, 0x49, 0x4C, 0x49, 0x79, 0x79, 0x37, 0x4D, 0x4D, 0x41, ++ 0x6F, 0x2B, 0x77, 0x73, 0x56, 0x52, 0x6A, 0x42, 0x66, 0x68, 0x6E, 0x75, 0x34, 0x53, 0x2F, 0x79, 0x72, 0x59, 0x4F, 0x62, 0x6E, 0x71, 0x73, 0x5A, 0x33, 0x38, 0x61, 0x4B, 0x4C, 0x34, 0x78, 0x33, 0x35, 0x62, 0x63, 0x46, 0x37, 0x44, 0x76, 0x42, ++ 0x37, 0x4C, 0x36, 0x47, 0x73, 0x34, 0x61, 0x38, 0x0A, 0x77, 0x50, 0x66, 0x63, 0x35, 0x2B, 0x70, 0x62, 0x72, 0x72, 0x4C, 0x4D, 0x74, 0x54, 0x57, 0x47, 0x53, 0x39, 0x44, 0x69, 0x50, 0x37, 0x62, 0x59, 0x2B, 0x41, 0x34, 0x41, 0x37, 0x6C, 0x33, ++ 0x6A, 0x39, 0x34, 0x31, 0x59, 0x2F, 0x38, 0x2B, 0x4C, 0x4E, 0x2B, 0x6C, 0x6A, 0x58, 0x32, 0x37, 0x33, 0x43, 0x58, 0x45, 0x32, 0x77, 0x68, 0x4A, 0x64, 0x56, 0x2F, 0x4C, 0x49, 0x74, 0x4D, 0x33, 0x7A, 0x37, 0x67, 0x4C, 0x66, 0x45, 0x64, 0x78, ++ 0x71, 0x75, 0x56, 0x65, 0x45, 0x0A, 0x48, 0x56, 0x6C, 0x4E, 0x6A, 0x4D, 0x37, 0x49, 0x44, 0x69, 0x50, 0x43, 0x74, 0x79, 0x61, 0x61, 0x45, 0x42, 0x52, 0x78, 0x2F, 0x70, 0x4F, 0x79, 0x69, 0x72, 0x69, 0x41, 0x38, 0x41, 0x34, 0x51, 0x6E, 0x74, ++ 0x4F, 0x6F, 0x55, 0x41, 0x77, 0x33, 0x67, 0x69, 0x2F, 0x71, 0x34, 0x49, 0x71, 0x64, 0x34, 0x53, 0x77, 0x35, 0x2F, 0x37, 0x57, 0x30, 0x63, 0x77, 0x44, 0x6B, 0x39, 0x30, 0x69, 0x6D, 0x63, 0x36, 0x79, 0x2F, 0x73, 0x74, 0x35, 0x33, 0x42, 0x49, ++ 0x65, 0x30, 0x0A, 0x6F, 0x38, 0x32, 0x62, 0x4E, 0x53, 0x51, 0x33, 0x2B, 0x70, 0x43, 0x54, 0x45, 0x34, 0x46, 0x43, 0x78, 0x70, 0x67, 0x6D, 0x64, 0x54, 0x64, 0x6D, 0x51, 0x52, 0x43, 0x73, 0x75, 0x2F, 0x57, 0x55, 0x34, 0x38, 0x49, 0x78, 0x4B, ++ 0x36, 0x33, 0x6E, 0x49, 0x31, 0x62, 0x4D, 0x4E, 0x53, 0x57, 0x53, 0x73, 0x31, 0x41, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, ++ 0x2D, 0x0A, 0x0A, 0x46, 0x49, 0x52, 0x4D, 0x41, 0x50, 0x52, 0x4F, 0x46, 0x45, 0x53, 0x49, 0x4F, 0x4E, 0x41, 0x4C, 0x20, 0x43, 0x41, 0x20, 0x52, 0x4F, 0x4F, 0x54, 0x2D, 0x41, 0x20, 0x57, 0x45, 0x42, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, ++ 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x43, 0x65, 0x6A, 0x43, 0x43, 0x41, 0x67, 0x43, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x4D, 0x5A, 0x63, 0x68, 0x37, 0x61, 0x2B, ++ 0x4A, 0x51, 0x6E, 0x38, 0x31, 0x51, 0x59, 0x65, 0x68, 0x5A, 0x31, 0x5A, 0x4D, 0x62, 0x54, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x7A, 0x42, 0x75, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, ++ 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x46, 0x0A, 0x55, 0x7A, 0x45, 0x63, 0x4D, 0x42, 0x6F, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, 0x54, 0x52, 0x6D, 0x6C, 0x79, 0x62, 0x57, 0x46, 0x77, 0x63, 0x6D, 0x39, 0x6D, 0x5A, 0x58, ++ 0x4E, 0x70, 0x62, 0x32, 0x35, 0x68, 0x62, 0x43, 0x42, 0x54, 0x51, 0x54, 0x45, 0x59, 0x4D, 0x42, 0x59, 0x47, 0x41, 0x31, 0x55, 0x45, 0x59, 0x51, 0x77, 0x50, 0x56, 0x6B, 0x46, 0x55, 0x52, 0x56, 0x4D, 0x74, 0x51, 0x54, 0x59, 0x79, 0x4E, 0x6A, ++ 0x4D, 0x30, 0x4D, 0x44, 0x59, 0x34, 0x0A, 0x4D, 0x53, 0x63, 0x77, 0x4A, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x44, 0x42, 0x35, 0x47, 0x53, 0x56, 0x4A, 0x4E, 0x51, 0x56, 0x42, 0x53, 0x54, 0x30, 0x5A, 0x46, 0x55, 0x30, 0x6C, 0x50, 0x54, ++ 0x6B, 0x46, 0x4D, 0x49, 0x45, 0x4E, 0x42, 0x49, 0x46, 0x4A, 0x50, 0x54, 0x31, 0x51, 0x74, 0x51, 0x53, 0x42, 0x58, 0x52, 0x55, 0x49, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x6A, 0x49, 0x77, 0x4E, 0x44, 0x41, 0x32, 0x4D, 0x44, 0x6B, 0x77, 0x4D, ++ 0x54, 0x4D, 0x32, 0x0A, 0x57, 0x68, 0x63, 0x4E, 0x4E, 0x44, 0x63, 0x77, 0x4D, 0x7A, 0x4D, 0x78, 0x4D, 0x44, 0x6B, 0x77, 0x4D, 0x54, 0x4D, 0x32, 0x57, 0x6A, 0x42, 0x75, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, ++ 0x45, 0x77, 0x4A, 0x46, 0x55, 0x7A, 0x45, 0x63, 0x4D, 0x42, 0x6F, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, 0x54, 0x52, 0x6D, 0x6C, 0x79, 0x62, 0x57, 0x46, 0x77, 0x63, 0x6D, 0x39, 0x6D, 0x5A, 0x58, 0x4E, 0x70, 0x62, 0x32, 0x35, 0x68, ++ 0x0A, 0x62, 0x43, 0x42, 0x54, 0x51, 0x54, 0x45, 0x59, 0x4D, 0x42, 0x59, 0x47, 0x41, 0x31, 0x55, 0x45, 0x59, 0x51, 0x77, 0x50, 0x56, 0x6B, 0x46, 0x55, 0x52, 0x56, 0x4D, 0x74, 0x51, 0x54, 0x59, 0x79, 0x4E, 0x6A, 0x4D, 0x30, 0x4D, 0x44, 0x59, ++ 0x34, 0x4D, 0x53, 0x63, 0x77, 0x4A, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x44, 0x42, 0x35, 0x47, 0x53, 0x56, 0x4A, 0x4E, 0x51, 0x56, 0x42, 0x53, 0x54, 0x30, 0x5A, 0x46, 0x55, 0x30, 0x6C, 0x50, 0x54, 0x6B, 0x46, 0x4D, 0x0A, 0x49, 0x45, ++ 0x4E, 0x42, 0x49, 0x46, 0x4A, 0x50, 0x54, 0x31, 0x51, 0x74, 0x51, 0x53, 0x42, 0x58, 0x52, 0x55, 0x49, 0x77, 0x64, 0x6A, 0x41, 0x51, 0x42, 0x67, 0x63, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x49, 0x42, 0x42, 0x67, 0x55, 0x72, 0x67, 0x51, ++ 0x51, 0x41, 0x49, 0x67, 0x4E, 0x69, 0x41, 0x41, 0x52, 0x48, 0x55, 0x2B, 0x6F, 0x73, 0x45, 0x61, 0x52, 0x33, 0x78, 0x79, 0x72, 0x71, 0x38, 0x39, 0x5A, 0x66, 0x65, 0x39, 0x4D, 0x45, 0x6B, 0x56, 0x7A, 0x36, 0x0A, 0x69, 0x4D, 0x59, 0x69, 0x75, ++ 0x59, 0x4D, 0x51, 0x59, 0x6E, 0x65, 0x45, 0x4D, 0x79, 0x33, 0x70, 0x41, 0x34, 0x6A, 0x55, 0x34, 0x44, 0x50, 0x33, 0x37, 0x58, 0x63, 0x73, 0x53, 0x6D, 0x44, 0x71, 0x35, 0x47, 0x2B, 0x74, 0x62, 0x62, 0x54, 0x34, 0x54, 0x49, 0x71, 0x6B, 0x35, ++ 0x42, 0x2F, 0x4B, 0x36, 0x6B, 0x38, 0x34, 0x53, 0x69, 0x36, 0x43, 0x63, 0x79, 0x76, 0x48, 0x5A, 0x70, 0x73, 0x4B, 0x6A, 0x45, 0x43, 0x63, 0x66, 0x49, 0x72, 0x32, 0x38, 0x6A, 0x6C, 0x67, 0x0A, 0x73, 0x74, 0x37, 0x4C, 0x37, 0x4C, 0x6A, 0x6B, ++ 0x62, 0x2B, 0x71, 0x62, 0x58, 0x62, 0x64, 0x54, 0x6B, 0x42, 0x67, 0x79, 0x56, 0x63, 0x55, 0x67, 0x74, 0x35, 0x53, 0x6A, 0x59, 0x7A, 0x42, 0x68, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, ++ 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x48, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x6A, 0x42, 0x42, 0x67, 0x77, 0x46, 0x6F, 0x41, 0x55, 0x6B, 0x2B, 0x46, 0x44, 0x0A, 0x59, 0x31, 0x77, 0x38, 0x6E, 0x64, 0x59, 0x6E, 0x38, 0x31, 0x4C, ++ 0x73, 0x46, 0x37, 0x4B, 0x70, 0x72, 0x79, 0x7A, 0x33, 0x64, 0x76, 0x67, 0x77, 0x48, 0x51, 0x59, 0x44, 0x56, 0x52, 0x30, 0x4F, 0x42, 0x42, 0x59, 0x45, 0x46, 0x4A, 0x50, 0x68, 0x51, 0x32, 0x4E, 0x63, 0x50, 0x4A, 0x33, 0x57, 0x4A, 0x2F, 0x4E, ++ 0x53, 0x37, 0x42, 0x65, 0x79, 0x71, 0x61, 0x38, 0x73, 0x39, 0x33, 0x62, 0x34, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x0A, 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x42, 0x42, 0x6A, 0x41, 0x4B, 0x42, 0x67, ++ 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x77, 0x4E, 0x6F, 0x41, 0x44, 0x42, 0x6C, 0x41, 0x6A, 0x41, 0x64, 0x66, 0x4B, 0x52, 0x37, 0x77, 0x34, 0x6C, 0x31, 0x4D, 0x2B, 0x45, 0x37, 0x71, 0x55, 0x57, 0x2F, 0x52, 0x75, ++ 0x6E, 0x70, 0x6F, 0x64, 0x33, 0x4A, 0x49, 0x68, 0x61, 0x33, 0x52, 0x78, 0x45, 0x4C, 0x32, 0x4A, 0x71, 0x36, 0x38, 0x63, 0x67, 0x4C, 0x0A, 0x63, 0x46, 0x42, 0x54, 0x41, 0x70, 0x46, 0x77, 0x68, 0x56, 0x6D, 0x70, 0x48, 0x71, 0x54, 0x6D, 0x36, ++ 0x69, 0x4D, 0x78, 0x6F, 0x41, 0x41, 0x43, 0x4D, 0x51, 0x44, 0x39, 0x34, 0x76, 0x69, 0x7A, 0x72, 0x78, 0x61, 0x35, 0x48, 0x6E, 0x50, 0x45, 0x6C, 0x75, 0x50, 0x42, 0x4D, 0x42, 0x6E, 0x59, 0x66, 0x75, 0x62, 0x44, 0x6C, 0x39, 0x34, 0x63, 0x54, ++ 0x37, 0x69, 0x4A, 0x4C, 0x7A, 0x50, 0x72, 0x53, 0x41, 0x38, 0x5A, 0x39, 0x34, 0x64, 0x47, 0x58, 0x53, 0x61, 0x51, 0x0A, 0x70, 0x59, 0x58, 0x46, 0x75, 0x58, 0x71, 0x55, 0x50, 0x6F, 0x65, 0x6F, 0x76, 0x51, 0x41, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, ++ 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x54, 0x57, 0x43, 0x41, 0x20, 0x43, 0x59, 0x42, 0x45, 0x52, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, ++ 0x43, 0x41, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, ++ 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x6A, 0x54, 0x43, 0x43, 0x41, 0x33, 0x57, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x51, 0x41, 0x45, 0x30, 0x6A, 0x4D, 0x49, 0x41, 0x41, 0x41, ++ 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x54, 0x7A, 0x79, 0x78, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x77, 0x46, 0x41, 0x44, 0x42, 0x51, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, ++ 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x0A, 0x45, 0x77, 0x4A, 0x55, 0x56, 0x7A, 0x45, 0x53, 0x4D, 0x42, 0x41, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x4A, 0x56, 0x45, 0x46, 0x4A, 0x56, 0x30, 0x46, 0x4F, 0x4C, 0x55, 0x4E, 0x42, 0x4D, ++ 0x52, 0x41, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4C, 0x45, 0x77, 0x64, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x42, 0x4D, 0x52, 0x73, 0x77, 0x47, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x4A, 0x55, 0x56, ++ 0x30, 0x4E, 0x42, 0x0A, 0x49, 0x45, 0x4E, 0x5A, 0x51, 0x6B, 0x56, 0x53, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x6A, 0x49, 0x78, 0x4D, 0x54, 0x49, 0x79, 0x4D, 0x44, 0x59, 0x31, ++ 0x4E, 0x44, 0x49, 0x35, 0x57, 0x68, 0x63, 0x4E, 0x4E, 0x44, 0x63, 0x78, 0x4D, 0x54, 0x49, 0x79, 0x4D, 0x54, 0x55, 0x31, 0x4F, 0x54, 0x55, 0x35, 0x57, 0x6A, 0x42, 0x51, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, ++ 0x0A, 0x45, 0x77, 0x4A, 0x55, 0x56, 0x7A, 0x45, 0x53, 0x4D, 0x42, 0x41, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x4A, 0x56, 0x45, 0x46, 0x4A, 0x56, 0x30, 0x46, 0x4F, 0x4C, 0x55, 0x4E, 0x42, 0x4D, 0x52, 0x41, 0x77, 0x44, 0x67, 0x59, ++ 0x44, 0x56, 0x51, 0x51, 0x4C, 0x45, 0x77, 0x64, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x42, 0x4D, 0x52, 0x73, 0x77, 0x47, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x4A, 0x55, 0x56, 0x30, 0x4E, 0x42, 0x0A, 0x49, 0x45, ++ 0x4E, 0x5A, 0x51, 0x6B, 0x56, 0x53, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x77, 0x67, 0x67, 0x49, 0x69, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, ++ 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x49, 0x4B, 0x41, 0x6F, 0x49, 0x43, 0x41, 0x51, 0x44, 0x47, 0x2B, 0x4D, 0x6F, 0x65, 0x32, 0x51, 0x6B, 0x67, 0x66, 0x68, 0x31, 0x73, 0x0A, 0x54, 0x73, 0x36, 0x50, 0x34, ++ 0x30, 0x63, 0x7A, 0x52, 0x4A, 0x7A, 0x48, 0x79, 0x57, 0x6D, 0x71, 0x4F, 0x6C, 0x74, 0x34, 0x37, 0x6E, 0x44, 0x53, 0x6B, 0x76, 0x67, 0x45, 0x73, 0x31, 0x4A, 0x53, 0x48, 0x57, 0x64, 0x79, 0x4B, 0x4B, 0x48, 0x66, 0x69, 0x31, 0x32, 0x56, 0x43, ++ 0x76, 0x37, 0x71, 0x7A, 0x65, 0x33, 0x33, 0x4B, 0x63, 0x37, 0x77, 0x62, 0x33, 0x2B, 0x73, 0x7A, 0x54, 0x33, 0x76, 0x73, 0x78, 0x78, 0x46, 0x61, 0x76, 0x63, 0x6F, 0x6B, 0x50, 0x46, 0x68, 0x0A, 0x56, 0x38, 0x55, 0x4D, 0x78, 0x4B, 0x4E, 0x51, ++ 0x58, 0x64, 0x37, 0x55, 0x74, 0x63, 0x73, 0x5A, 0x79, 0x6F, 0x43, 0x35, 0x64, 0x63, 0x34, 0x70, 0x7A, 0x74, 0x4B, 0x46, 0x49, 0x75, 0x77, 0x43, 0x59, 0x38, 0x78, 0x45, 0x4D, 0x43, 0x44, 0x61, 0x36, 0x70, 0x46, 0x62, 0x56, 0x75, 0x59, 0x64, ++ 0x48, 0x4E, 0x57, 0x64, 0x5A, 0x73, 0x63, 0x2F, 0x33, 0x34, 0x62, 0x4B, 0x53, 0x31, 0x50, 0x45, 0x32, 0x59, 0x32, 0x79, 0x48, 0x65, 0x72, 0x34, 0x33, 0x43, 0x64, 0x54, 0x0A, 0x6F, 0x30, 0x66, 0x68, 0x59, 0x63, 0x78, 0x39, 0x74, 0x62, 0x44, ++ 0x34, 0x37, 0x6E, 0x4F, 0x52, 0x78, 0x63, 0x35, 0x7A, 0x62, 0x38, 0x37, 0x75, 0x45, 0x42, 0x38, 0x61, 0x42, 0x73, 0x2F, 0x70, 0x4A, 0x32, 0x44, 0x46, 0x54, 0x78, 0x6E, 0x6B, 0x36, 0x38, 0x34, 0x69, 0x4A, 0x6B, 0x58, 0x58, 0x59, 0x4A, 0x6E, ++ 0x64, 0x7A, 0x6B, 0x38, 0x33, 0x34, 0x48, 0x2F, 0x6E, 0x59, 0x36, 0x32, 0x77, 0x75, 0x46, 0x6D, 0x34, 0x30, 0x41, 0x5A, 0x6F, 0x4E, 0x57, 0x44, 0x54, 0x0A, 0x4E, 0x71, 0x35, 0x78, 0x51, 0x77, 0x54, 0x78, 0x61, 0x57, 0x56, 0x34, 0x66, 0x50, ++ 0x4D, 0x66, 0x38, 0x38, 0x6F, 0x6F, 0x6E, 0x31, 0x6F, 0x67, 0x6C, 0x57, 0x61, 0x30, 0x7A, 0x62, 0x66, 0x75, 0x6A, 0x33, 0x69, 0x6B, 0x52, 0x52, 0x6A, 0x70, 0x4A, 0x69, 0x2B, 0x4E, 0x6D, 0x79, 0x6B, 0x6F, 0x73, 0x61, 0x53, 0x33, 0x4F, 0x6D, ++ 0x32, 0x35, 0x31, 0x42, 0x77, 0x34, 0x63, 0x6B, 0x56, 0x59, 0x73, 0x56, 0x37, 0x72, 0x38, 0x43, 0x69, 0x62, 0x74, 0x34, 0x4C, 0x4B, 0x0A, 0x2F, 0x63, 0x2F, 0x57, 0x4D, 0x77, 0x2B, 0x66, 0x2B, 0x35, 0x65, 0x65, 0x73, 0x52, 0x79, 0x63, 0x6E, ++ 0x75, 0x70, 0x66, 0x58, 0x74, 0x75, 0x71, 0x33, 0x56, 0x54, 0x70, 0x4D, 0x43, 0x45, 0x6F, 0x62, 0x59, 0x35, 0x35, 0x38, 0x33, 0x57, 0x53, 0x6A, 0x43, 0x62, 0x2B, 0x33, 0x4D, 0x58, 0x32, 0x77, 0x37, 0x44, 0x66, 0x52, 0x46, 0x6C, 0x44, 0x6F, ++ 0x37, 0x59, 0x44, 0x4B, 0x50, 0x59, 0x49, 0x4D, 0x4B, 0x6F, 0x4E, 0x4D, 0x2B, 0x48, 0x76, 0x6E, 0x4B, 0x6B, 0x48, 0x0A, 0x49, 0x75, 0x4E, 0x5A, 0x57, 0x30, 0x43, 0x50, 0x32, 0x6F, 0x69, 0x33, 0x61, 0x51, 0x69, 0x6F, 0x74, 0x79, 0x4D, 0x75, ++ 0x52, 0x41, 0x6C, 0x5A, 0x4E, 0x31, 0x76, 0x48, 0x34, 0x78, 0x66, 0x79, 0x49, 0x75, 0x74, 0x75, 0x4F, 0x56, 0x4C, 0x46, 0x33, 0x6C, 0x53, 0x6E, 0x6D, 0x4D, 0x6C, 0x4C, 0x49, 0x4A, 0x58, 0x63, 0x52, 0x6F, 0x6C, 0x66, 0x74, 0x42, 0x4C, 0x35, ++ 0x68, 0x53, 0x6D, 0x4F, 0x36, 0x38, 0x67, 0x6E, 0x46, 0x53, 0x44, 0x41, 0x53, 0x39, 0x54, 0x4D, 0x0A, 0x66, 0x41, 0x78, 0x73, 0x4E, 0x41, 0x77, 0x6D, 0x6D, 0x79, 0x59, 0x78, 0x70, 0x6A, 0x79, 0x6E, 0x39, 0x74, 0x6E, 0x51, 0x53, 0x36, 0x4A, ++ 0x6B, 0x2F, 0x7A, 0x75, 0x5A, 0x51, 0x58, 0x4C, 0x42, 0x34, 0x48, 0x43, 0x58, 0x38, 0x53, 0x53, 0x37, 0x4B, 0x38, 0x52, 0x30, 0x49, 0x72, 0x47, 0x73, 0x61, 0x79, 0x49, 0x79, 0x4A, 0x4E, 0x4E, 0x34, 0x4B, 0x73, 0x44, 0x41, 0x6F, 0x53, 0x2F, ++ 0x78, 0x55, 0x67, 0x58, 0x4A, 0x50, 0x2B, 0x39, 0x32, 0x5A, 0x75, 0x4A, 0x46, 0x0A, 0x32, 0x41, 0x30, 0x39, 0x72, 0x5A, 0x58, 0x49, 0x78, 0x34, 0x6B, 0x6D, 0x79, 0x41, 0x2B, 0x75, 0x70, 0x77, 0x4D, 0x75, 0x2B, 0x38, 0x46, 0x66, 0x2B, 0x69, ++ 0x44, 0x68, 0x63, 0x4B, 0x32, 0x77, 0x5A, 0x53, 0x41, 0x33, 0x4D, 0x32, 0x43, 0x77, 0x31, 0x61, 0x2F, 0x58, 0x44, 0x42, 0x7A, 0x43, 0x6B, 0x48, 0x44, 0x58, 0x53, 0x68, 0x69, 0x38, 0x66, 0x67, 0x47, 0x77, 0x73, 0x4F, 0x73, 0x56, 0x48, 0x6B, ++ 0x51, 0x47, 0x7A, 0x61, 0x52, 0x50, 0x36, 0x41, 0x7A, 0x52, 0x0A, 0x77, 0x79, 0x41, 0x51, 0x34, 0x56, 0x52, 0x6C, 0x6E, 0x72, 0x5A, 0x52, 0x30, 0x42, 0x70, 0x32, 0x61, 0x30, 0x4A, 0x61, 0x57, 0x48, 0x59, 0x30, 0x36, 0x72, 0x63, 0x33, 0x47, ++ 0x61, 0x34, 0x75, 0x64, 0x66, 0x6D, 0x57, 0x35, 0x63, 0x46, 0x5A, 0x39, 0x35, 0x52, 0x58, 0x4B, 0x53, 0x57, 0x4E, 0x4F, 0x6B, 0x79, 0x72, 0x54, 0x5A, 0x70, 0x42, 0x30, 0x46, 0x38, 0x6D, 0x41, 0x77, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x6F, ++ 0x32, 0x4D, 0x77, 0x59, 0x54, 0x41, 0x4F, 0x0A, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x38, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x41, 0x4D, 0x43, 0x41, 0x51, 0x59, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, ++ 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, 0x41, 0x66, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x53, 0x4D, 0x45, 0x47, 0x44, 0x41, 0x57, 0x67, 0x42, 0x53, 0x64, 0x68, 0x57, 0x45, 0x55, 0x66, 0x4D, 0x46, 0x69, 0x62, 0x35, 0x64, 0x6F, ++ 0x35, 0x45, 0x38, 0x33, 0x0A, 0x51, 0x4F, 0x47, 0x74, 0x34, 0x41, 0x31, 0x57, 0x4E, 0x7A, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x6E, 0x59, 0x56, 0x68, 0x46, 0x48, 0x7A, 0x42, 0x59, 0x6D, 0x2B, ++ 0x58, 0x61, 0x4F, 0x52, 0x50, 0x4E, 0x30, 0x44, 0x68, 0x72, 0x65, 0x41, 0x4E, 0x56, 0x6A, 0x63, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4D, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, ++ 0x42, 0x0A, 0x41, 0x47, 0x53, 0x50, 0x65, 0x73, 0x52, 0x69, 0x44, 0x72, 0x57, 0x49, 0x7A, 0x4C, 0x6A, 0x48, 0x68, 0x67, 0x36, 0x68, 0x53, 0x68, 0x62, 0x4E, 0x63, 0x41, 0x75, 0x33, 0x70, 0x34, 0x55, 0x4C, 0x73, 0x33, 0x61, 0x32, 0x44, 0x36, ++ 0x66, 0x2F, 0x43, 0x49, 0x73, 0x4C, 0x4A, 0x63, 0x2B, 0x6F, 0x31, 0x49, 0x4E, 0x31, 0x4B, 0x72, 0x69, 0x57, 0x69, 0x4C, 0x62, 0x37, 0x33, 0x79, 0x30, 0x74, 0x74, 0x47, 0x6C, 0x54, 0x49, 0x54, 0x56, 0x58, 0x31, 0x6F, 0x6C, 0x4E, 0x0A, 0x63, ++ 0x37, 0x39, 0x70, 0x6A, 0x33, 0x43, 0x6A, 0x59, 0x63, 0x79, 0x61, 0x32, 0x78, 0x36, 0x61, 0x34, 0x43, 0x44, 0x34, 0x62, 0x4C, 0x75, 0x62, 0x49, 0x70, 0x31, 0x64, 0x68, 0x44, 0x47, 0x61, 0x4C, 0x49, 0x72, 0x64, 0x61, 0x71, 0x48, 0x58, 0x4B, ++ 0x47, 0x6E, 0x4B, 0x2F, 0x6E, 0x5A, 0x56, 0x65, 0x6B, 0x5A, 0x6E, 0x36, 0x38, 0x78, 0x44, 0x69, 0x42, 0x61, 0x69, 0x41, 0x39, 0x61, 0x35, 0x46, 0x2F, 0x67, 0x5A, 0x62, 0x47, 0x30, 0x6A, 0x41, 0x6E, 0x2F, 0x78, 0x0A, 0x58, 0x39, 0x41, 0x4B, ++ 0x4B, 0x53, 0x4D, 0x37, 0x30, 0x61, 0x6F, 0x4B, 0x37, 0x61, 0x6B, 0x58, 0x4A, 0x6C, 0x51, 0x4B, 0x54, 0x63, 0x4B, 0x6C, 0x54, 0x66, 0x6A, 0x46, 0x2F, 0x62, 0x69, 0x42, 0x7A, 0x79, 0x73, 0x73, 0x65, 0x4B, 0x4E, 0x6E, 0x54, 0x4B, 0x6B, 0x48, ++ 0x6D, 0x76, 0x50, 0x66, 0x58, 0x76, 0x74, 0x38, 0x39, 0x59, 0x6E, 0x4E, 0x64, 0x4A, 0x64, 0x68, 0x45, 0x47, 0x6F, 0x48, 0x4B, 0x34, 0x46, 0x61, 0x30, 0x6F, 0x36, 0x33, 0x35, 0x79, 0x44, 0x52, 0x0A, 0x49, 0x47, 0x34, 0x6B, 0x71, 0x49, 0x51, ++ 0x6E, 0x6F, 0x56, 0x65, 0x73, 0x71, 0x6C, 0x56, 0x59, 0x4C, 0x39, 0x7A, 0x5A, 0x79, 0x76, 0x70, 0x6F, 0x42, 0x4A, 0x37, 0x74, 0x52, 0x43, 0x54, 0x35, 0x64, 0x45, 0x41, 0x37, 0x49, 0x7A, 0x4F, 0x72, 0x67, 0x31, 0x6F, 0x59, 0x4A, 0x6B, 0x4B, ++ 0x32, 0x62, 0x56, 0x53, 0x31, 0x46, 0x6D, 0x41, 0x77, 0x62, 0x4C, 0x47, 0x67, 0x2B, 0x4C, 0x68, 0x42, 0x6F, 0x46, 0x31, 0x4A, 0x53, 0x64, 0x4A, 0x6C, 0x42, 0x54, 0x72, 0x71, 0x0A, 0x2F, 0x70, 0x31, 0x68, 0x76, 0x49, 0x62, 0x5A, 0x76, 0x39, ++ 0x37, 0x54, 0x75, 0x6A, 0x71, 0x78, 0x66, 0x33, 0x36, 0x53, 0x4E, 0x49, 0x37, 0x4A, 0x41, 0x47, 0x37, 0x63, 0x6D, 0x4C, 0x33, 0x63, 0x37, 0x49, 0x41, 0x46, 0x72, 0x51, 0x49, 0x39, 0x33, 0x32, 0x58, 0x74, 0x43, 0x77, 0x50, 0x33, 0x39, 0x78, ++ 0x61, 0x45, 0x42, 0x44, 0x47, 0x36, 0x6B, 0x35, 0x54, 0x59, 0x38, 0x68, 0x4C, 0x34, 0x69, 0x75, 0x4F, 0x2F, 0x51, 0x71, 0x2B, 0x6E, 0x31, 0x4D, 0x30, 0x52, 0x0A, 0x46, 0x78, 0x62, 0x49, 0x51, 0x68, 0x30, 0x55, 0x71, 0x45, 0x4C, 0x32, 0x30, ++ 0x6B, 0x43, 0x47, 0x6F, 0x45, 0x38, 0x6A, 0x79, 0x70, 0x5A, 0x46, 0x56, 0x6D, 0x41, 0x47, 0x7A, 0x62, 0x64, 0x56, 0x41, 0x61, 0x59, 0x42, 0x6C, 0x47, 0x58, 0x2B, 0x62, 0x67, 0x55, 0x4A, 0x75, 0x72, 0x53, 0x6B, 0x71, 0x75, 0x4C, 0x76, 0x57, ++ 0x4C, 0x36, 0x39, 0x4A, 0x31, 0x62, 0x59, 0x37, 0x33, 0x4E, 0x78, 0x57, 0x30, 0x51, 0x7A, 0x38, 0x70, 0x70, 0x79, 0x36, 0x72, 0x42, 0x65, 0x0A, 0x50, 0x6D, 0x36, 0x70, 0x55, 0x6C, 0x76, 0x73, 0x63, 0x47, 0x32, 0x31, 0x68, 0x34, 0x38, 0x33, ++ 0x58, 0x6A, 0x79, 0x4D, 0x6E, 0x4D, 0x37, 0x6B, 0x38, 0x4D, 0x34, 0x4D, 0x5A, 0x30, 0x48, 0x4D, 0x7A, 0x76, 0x61, 0x41, 0x71, 0x30, 0x37, 0x4D, 0x54, 0x46, 0x62, 0x31, 0x77, 0x57, 0x46, 0x5A, 0x6B, 0x37, 0x51, 0x2B, 0x70, 0x74, 0x71, 0x34, ++ 0x4E, 0x78, 0x4B, 0x66, 0x4B, 0x6A, 0x4C, 0x6A, 0x69, 0x37, 0x67, 0x68, 0x37, 0x4D, 0x4D, 0x72, 0x5A, 0x51, 0x7A, 0x76, 0x0A, 0x49, 0x74, 0x36, 0x49, 0x4B, 0x54, 0x74, 0x4D, 0x31, 0x2F, 0x72, 0x2B, 0x74, 0x2B, 0x46, 0x48, 0x76, 0x70, 0x77, ++ 0x2B, 0x50, 0x6F, 0x50, 0x37, 0x55, 0x56, 0x33, 0x31, 0x61, 0x50, 0x63, 0x75, 0x49, 0x59, 0x58, 0x63, 0x76, 0x2F, 0x46, 0x61, 0x34, 0x6E, 0x7A, 0x58, 0x78, 0x65, 0x53, 0x44, 0x77, 0x57, 0x72, 0x72, 0x75, 0x6F, 0x42, 0x61, 0x33, 0x6C, 0x77, ++ 0x74, 0x63, 0x48, 0x62, 0x34, 0x79, 0x4F, 0x57, 0x48, 0x68, 0x38, 0x71, 0x67, 0x6E, 0x61, 0x48, 0x6C, 0x0A, 0x49, 0x68, 0x49, 0x6E, 0x44, 0x30, 0x51, 0x39, 0x48, 0x57, 0x7A, 0x71, 0x31, 0x4D, 0x4B, 0x4C, 0x4C, 0x32, 0x39, 0x35, 0x71, 0x33, ++ 0x39, 0x51, 0x70, 0x73, 0x51, 0x5A, 0x70, 0x36, 0x46, 0x36, 0x74, 0x35, 0x62, 0x35, 0x77, 0x52, 0x39, 0x69, 0x57, 0x71, 0x4A, 0x44, 0x42, 0x30, 0x42, 0x65, 0x4A, 0x73, 0x61, 0x73, 0x37, 0x61, 0x35, 0x77, 0x46, 0x73, 0x57, 0x71, 0x79, 0x6E, ++ 0x4B, 0x4B, 0x54, 0x62, 0x44, 0x50, 0x41, 0x59, 0x73, 0x44, 0x50, 0x32, 0x37, 0x58, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, ++ 0x0A, 0x0A, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x32, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x44, 0x63, 0x6A, 0x43, 0x43, ++ 0x41, 0x6C, 0x71, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x55, 0x5A, 0x76, 0x6E, 0x48, 0x77, 0x61, 0x2F, 0x73, 0x77, 0x6C, 0x47, 0x30, 0x37, 0x56, 0x4F, 0x58, 0x35, 0x75, 0x61, 0x43, 0x77, 0x79, 0x73, 0x63, 0x6B, 0x42, 0x59, 0x77, ++ 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x42, 0x51, 0x41, 0x77, 0x55, 0x54, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x0A, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x53, 0x6C, 0x41, ++ 0x78, 0x49, 0x7A, 0x41, 0x68, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x47, 0x6B, 0x4E, 0x35, 0x59, 0x6D, 0x56, 0x79, 0x64, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x51, 0x67, 0x53, 0x6D, 0x46, 0x77, 0x59, 0x57, 0x34, 0x67, 0x51, 0x32, 0x38, ++ 0x75, 0x4C, 0x43, 0x42, 0x4D, 0x64, 0x47, 0x51, 0x75, 0x4D, 0x52, 0x30, 0x77, 0x47, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x52, 0x54, 0x0A, 0x5A, 0x57, 0x4E, 0x31, 0x63, 0x6D, 0x56, 0x54, 0x61, 0x57, 0x64, 0x75, 0x49, 0x46, ++ 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x78, 0x4D, 0x6A, 0x41, 0x65, 0x46, 0x77, 0x30, 0x79, 0x4D, 0x44, 0x41, 0x30, 0x4D, 0x44, 0x67, 0x77, 0x4E, 0x54, 0x4D, 0x32, 0x4E, 0x44, 0x5A, 0x61, 0x46, 0x77, 0x30, 0x30, 0x4D, 0x44, ++ 0x41, 0x30, 0x4D, 0x44, 0x67, 0x77, 0x4E, 0x54, 0x4D, 0x32, 0x4E, 0x44, 0x5A, 0x61, 0x4D, 0x46, 0x45, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x0A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6B, 0x70, 0x51, 0x4D, 0x53, 0x4D, 0x77, 0x49, ++ 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x45, 0x78, 0x70, 0x44, 0x65, 0x57, 0x4A, 0x6C, 0x63, 0x6E, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x49, 0x45, 0x70, 0x68, 0x63, 0x47, 0x46, 0x75, 0x49, 0x45, 0x4E, 0x76, 0x4C, 0x69, 0x77, 0x67, 0x54, ++ 0x48, 0x52, 0x6B, 0x4C, 0x6A, 0x45, 0x64, 0x4D, 0x42, 0x73, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x55, 0x0A, 0x55, 0x32, 0x56, 0x6A, 0x64, 0x58, 0x4A, 0x6C, 0x55, 0x32, 0x6C, 0x6E, 0x62, 0x69, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, ++ 0x49, 0x45, 0x4E, 0x42, 0x4D, 0x54, 0x49, 0x77, 0x67, 0x67, 0x45, 0x69, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x42, 0x44, 0x77, 0x41, 0x77, ++ 0x67, 0x67, 0x45, 0x4B, 0x41, 0x6F, 0x49, 0x42, 0x41, 0x51, 0x43, 0x36, 0x4F, 0x63, 0x45, 0x33, 0x0A, 0x65, 0x6D, 0x68, 0x46, 0x4B, 0x78, 0x53, 0x30, 0x36, 0x2B, 0x51, 0x54, 0x36, 0x31, 0x64, 0x31, 0x49, 0x30, 0x32, 0x50, 0x4A, 0x43, 0x30, ++ 0x57, 0x36, 0x4B, 0x36, 0x4F, 0x79, 0x58, 0x32, 0x6B, 0x56, 0x7A, 0x73, 0x71, 0x64, 0x69, 0x55, 0x7A, 0x67, 0x32, 0x7A, 0x71, 0x4D, 0x6F, 0x71, 0x55, 0x6D, 0x30, 0x34, 0x38, 0x6C, 0x75, 0x54, 0x39, 0x55, 0x62, 0x2B, 0x5A, 0x79, 0x5A, 0x4E, ++ 0x2B, 0x76, 0x2F, 0x6D, 0x74, 0x70, 0x37, 0x4A, 0x49, 0x4B, 0x77, 0x63, 0x63, 0x0A, 0x4A, 0x2F, 0x56, 0x4D, 0x76, 0x48, 0x41, 0x53, 0x64, 0x36, 0x53, 0x46, 0x56, 0x4C, 0x58, 0x39, 0x6B, 0x48, 0x72, 0x6B, 0x6F, 0x2B, 0x52, 0x52, 0x57, 0x41, ++ 0x50, 0x4E, 0x45, 0x48, 0x6C, 0x35, 0x37, 0x6D, 0x75, 0x54, 0x48, 0x32, 0x53, 0x4F, 0x61, 0x32, 0x53, 0x72, 0x6F, 0x78, 0x50, 0x6A, 0x63, 0x66, 0x35, 0x39, 0x71, 0x35, 0x7A, 0x64, 0x4A, 0x31, 0x4D, 0x33, 0x73, 0x36, 0x6F, 0x59, 0x77, 0x6C, ++ 0x6B, 0x6D, 0x37, 0x46, 0x73, 0x66, 0x30, 0x75, 0x5A, 0x6C, 0x0A, 0x66, 0x4F, 0x2B, 0x54, 0x76, 0x64, 0x68, 0x59, 0x58, 0x41, 0x76, 0x41, 0x34, 0x32, 0x56, 0x76, 0x50, 0x4D, 0x66, 0x4B, 0x57, 0x65, 0x50, 0x2B, 0x62, 0x6C, 0x2B, 0x73, 0x67, ++ 0x37, 0x37, 0x39, 0x58, 0x53, 0x56, 0x4F, 0x4B, 0x69, 0x6B, 0x37, 0x31, 0x67, 0x75, 0x72, 0x46, 0x7A, 0x4A, 0x34, 0x70, 0x4F, 0x45, 0x2B, 0x6C, 0x45, 0x61, 0x2B, 0x59, 0x6D, 0x36, 0x62, 0x33, 0x6B, 0x61, 0x6F, 0x73, 0x52, 0x62, 0x6E, 0x68, ++ 0x57, 0x37, 0x30, 0x43, 0x45, 0x42, 0x46, 0x0A, 0x45, 0x61, 0x43, 0x65, 0x56, 0x45, 0x53, 0x45, 0x39, 0x39, 0x67, 0x32, 0x7A, 0x76, 0x56, 0x51, 0x52, 0x39, 0x77, 0x73, 0x4D, 0x4A, 0x76, 0x75, 0x77, 0x50, 0x57, 0x57, 0x30, 0x76, 0x34, 0x4A, ++ 0x68, 0x73, 0x63, 0x47, 0x57, 0x61, 0x35, 0x50, 0x72, 0x6F, 0x34, 0x52, 0x6D, 0x48, 0x76, 0x7A, 0x43, 0x31, 0x4B, 0x71, 0x59, 0x69, 0x61, 0x71, 0x49, 0x64, 0x2B, 0x4F, 0x4A, 0x54, 0x4E, 0x35, 0x6C, 0x78, 0x5A, 0x4A, 0x6A, 0x66, 0x55, 0x2B, ++ 0x31, 0x55, 0x65, 0x66, 0x0A, 0x4E, 0x7A, 0x46, 0x4A, 0x4D, 0x33, 0x49, 0x46, 0x54, 0x51, 0x79, 0x32, 0x56, 0x59, 0x7A, 0x78, 0x56, 0x34, 0x2B, 0x4B, 0x68, 0x39, 0x47, 0x74, 0x78, 0x52, 0x45, 0x53, 0x4F, 0x61, 0x43, 0x74, 0x41, 0x67, 0x4D, ++ 0x42, 0x41, 0x41, 0x47, 0x6A, 0x51, 0x6A, 0x42, 0x41, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, ++ 0x50, 0x0A, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x51, 0x44, 0x41, 0x67, 0x45, 0x47, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x52, 0x58, 0x4E, 0x50, 0x4E, 0x30, 0x7A, 0x77, 0x52, 0x4C, 0x31, 0x53, ++ 0x58, 0x6D, 0x38, 0x55, 0x43, 0x32, 0x4C, 0x45, 0x7A, 0x5A, 0x4C, 0x65, 0x6D, 0x67, 0x72, 0x54, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x0A, 0x41, ++ 0x51, 0x45, 0x41, 0x50, 0x72, 0x76, 0x62, 0x46, 0x78, 0x62, 0x53, 0x38, 0x68, 0x51, 0x42, 0x49, 0x43, 0x77, 0x34, 0x67, 0x30, 0x75, 0x74, 0x76, 0x73, 0x71, 0x46, 0x65, 0x70, 0x71, 0x32, 0x6D, 0x32, 0x75, 0x6D, 0x34, 0x66, 0x79, 0x6C, 0x4F, ++ 0x71, 0x79, 0x74, 0x74, 0x43, 0x67, 0x36, 0x72, 0x39, 0x63, 0x42, 0x67, 0x30, 0x6B, 0x72, 0x59, 0x36, 0x4C, 0x64, 0x6D, 0x6D, 0x51, 0x4F, 0x6D, 0x46, 0x78, 0x76, 0x33, 0x59, 0x36, 0x37, 0x69, 0x6C, 0x51, 0x69, 0x0A, 0x4C, 0x55, 0x6F, 0x54, ++ 0x38, 0x36, 0x35, 0x41, 0x51, 0x39, 0x74, 0x50, 0x6B, 0x62, 0x65, 0x47, 0x47, 0x75, 0x77, 0x41, 0x74, 0x45, 0x47, 0x42, 0x70, 0x45, 0x2F, 0x36, 0x61, 0x6F, 0x75, 0x49, 0x73, 0x33, 0x59, 0x49, 0x63, 0x69, 0x70, 0x4A, 0x51, 0x4D, 0x50, 0x54, ++ 0x77, 0x34, 0x57, 0x4A, 0x6D, 0x42, 0x43, 0x6C, 0x6E, 0x57, 0x38, 0x5A, 0x74, 0x37, 0x76, 0x50, 0x65, 0x6D, 0x56, 0x56, 0x32, 0x7A, 0x66, 0x72, 0x50, 0x49, 0x70, 0x79, 0x4D, 0x70, 0x63, 0x65, 0x0A, 0x6D, 0x69, 0x6B, 0x2B, 0x72, 0x59, 0x33, ++ 0x6D, 0x6F, 0x78, 0x74, 0x74, 0x39, 0x58, 0x55, 0x61, 0x35, 0x72, 0x42, 0x6F, 0x75, 0x56, 0x75, 0x69, 0x37, 0x6D, 0x6C, 0x48, 0x4A, 0x7A, 0x57, 0x68, 0x68, 0x70, 0x6D, 0x41, 0x38, 0x7A, 0x4E, 0x4C, 0x34, 0x57, 0x75, 0x6B, 0x4A, 0x73, 0x50, ++ 0x76, 0x64, 0x46, 0x6C, 0x73, 0x65, 0x71, 0x4A, 0x6B, 0x74, 0x68, 0x35, 0x45, 0x77, 0x31, 0x44, 0x67, 0x44, 0x7A, 0x6B, 0x39, 0x71, 0x54, 0x50, 0x78, 0x70, 0x66, 0x50, 0x53, 0x0A, 0x76, 0x57, 0x4B, 0x45, 0x72, 0x49, 0x34, 0x63, 0x71, 0x63, ++ 0x31, 0x61, 0x76, 0x54, 0x63, 0x37, 0x62, 0x67, 0x6F, 0x69, 0x74, 0x50, 0x51, 0x56, 0x35, 0x35, 0x46, 0x59, 0x78, 0x54, 0x70, 0x45, 0x30, 0x35, 0x55, 0x6F, 0x32, 0x63, 0x42, 0x6C, 0x36, 0x58, 0x4C, 0x4B, 0x30, 0x41, 0x2B, 0x39, 0x48, 0x37, ++ 0x4D, 0x56, 0x32, 0x61, 0x6E, 0x6A, 0x70, 0x45, 0x63, 0x4A, 0x6E, 0x75, 0x44, 0x4C, 0x4E, 0x2F, 0x76, 0x39, 0x76, 0x5A, 0x66, 0x56, 0x76, 0x68, 0x67, 0x61, 0x0A, 0x61, 0x61, 0x49, 0x35, 0x67, 0x64, 0x6B, 0x61, 0x39, 0x61, 0x74, 0x2F, 0x79, ++ 0x4F, 0x50, 0x69, 0x5A, 0x77, 0x75, 0x64, 0x39, 0x41, 0x7A, 0x71, 0x56, 0x4E, 0x2F, 0x53, 0x73, 0x71, 0x2B, 0x78, 0x49, 0x76, 0x45, 0x67, 0x33, 0x37, 0x78, 0x45, 0x48, 0x41, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, ++ 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x34, 0x0A, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, ++ 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x63, 0x6A, 0x43, 0x43, 0x41, 0x31, 0x71, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x55, 0x5A, 0x4E, 0x74, 0x61, 0x44, 0x43, 0x42, 0x4F, 0x36, 0x4E, 0x63, ++ 0x70, 0x64, 0x38, 0x68, 0x51, 0x4A, 0x36, 0x4A, 0x61, 0x4A, 0x39, 0x30, 0x74, 0x38, 0x73, 0x73, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4D, 0x42, 0x51, 0x41, 0x77, 0x55, 0x54, 0x45, ++ 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x0A, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x53, 0x6C, 0x41, 0x78, 0x49, 0x7A, 0x41, 0x68, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x47, 0x6B, 0x4E, 0x35, 0x59, 0x6D, 0x56, 0x79, 0x64, 0x48, ++ 0x4A, 0x31, 0x63, 0x33, 0x51, 0x67, 0x53, 0x6D, 0x46, 0x77, 0x59, 0x57, 0x34, 0x67, 0x51, 0x32, 0x38, 0x75, 0x4C, 0x43, 0x42, 0x4D, 0x64, 0x47, 0x51, 0x75, 0x4D, 0x52, 0x30, 0x77, 0x47, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, ++ 0x52, 0x54, 0x0A, 0x5A, 0x57, 0x4E, 0x31, 0x63, 0x6D, 0x56, 0x54, 0x61, 0x57, 0x64, 0x75, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x78, 0x4E, 0x44, 0x41, 0x65, 0x46, 0x77, 0x30, 0x79, 0x4D, 0x44, 0x41, 0x30, 0x4D, ++ 0x44, 0x67, 0x77, 0x4E, 0x7A, 0x41, 0x32, 0x4D, 0x54, 0x6C, 0x61, 0x46, 0x77, 0x30, 0x30, 0x4E, 0x54, 0x41, 0x30, 0x4D, 0x44, 0x67, 0x77, 0x4E, 0x7A, 0x41, 0x32, 0x4D, 0x54, 0x6C, 0x61, 0x4D, 0x46, 0x45, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x0A, ++ 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6B, 0x70, 0x51, 0x4D, 0x53, 0x4D, 0x77, 0x49, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x45, 0x78, 0x70, 0x44, 0x65, 0x57, 0x4A, 0x6C, 0x63, 0x6E, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, ++ 0x49, 0x45, 0x70, 0x68, 0x63, 0x47, 0x46, 0x75, 0x49, 0x45, 0x4E, 0x76, 0x4C, 0x69, 0x77, 0x67, 0x54, 0x48, 0x52, 0x6B, 0x4C, 0x6A, 0x45, 0x64, 0x4D, 0x42, 0x73, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x55, 0x0A, 0x55, 0x32, 0x56, ++ 0x6A, 0x64, 0x58, 0x4A, 0x6C, 0x55, 0x32, 0x6C, 0x6E, 0x62, 0x69, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x42, 0x4D, 0x54, 0x51, 0x77, 0x67, 0x67, 0x49, 0x69, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, ++ 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x49, 0x4B, 0x41, 0x6F, 0x49, 0x43, 0x41, 0x51, 0x44, 0x46, 0x30, 0x6E, 0x71, 0x68, 0x0A, 0x31, 0x6F, 0x71, 0x2F, 0x46, 0x6A, ++ 0x48, 0x51, 0x6D, 0x4E, 0x45, 0x36, 0x6C, 0x50, 0x78, 0x61, 0x75, 0x47, 0x34, 0x69, 0x77, 0x57, 0x4C, 0x33, 0x70, 0x77, 0x6F, 0x6E, 0x37, 0x31, 0x44, 0x32, 0x4C, 0x72, 0x47, 0x65, 0x61, 0x42, 0x4C, 0x77, 0x62, 0x43, 0x52, 0x6A, 0x4F, 0x66, ++ 0x48, 0x77, 0x33, 0x78, 0x44, 0x47, 0x33, 0x72, 0x64, 0x53, 0x49, 0x4E, 0x56, 0x53, 0x57, 0x30, 0x4B, 0x5A, 0x6E, 0x76, 0x4F, 0x67, 0x76, 0x6C, 0x49, 0x66, 0x58, 0x38, 0x78, 0x6E, 0x0A, 0x62, 0x61, 0x63, 0x75, 0x55, 0x4B, 0x4C, 0x42, 0x6C, ++ 0x34, 0x32, 0x32, 0x2B, 0x4A, 0x58, 0x31, 0x73, 0x4C, 0x72, 0x63, 0x6E, 0x65, 0x43, 0x2B, 0x79, 0x39, 0x2F, 0x33, 0x4F, 0x50, 0x4A, 0x48, 0x39, 0x61, 0x61, 0x61, 0x6B, 0x70, 0x55, 0x71, 0x59, 0x6C, 0x6C, 0x51, 0x43, 0x36, 0x4B, 0x78, 0x4E, ++ 0x65, 0x64, 0x6C, 0x73, 0x6D, 0x47, 0x79, 0x36, 0x70, 0x4A, 0x78, 0x61, 0x65, 0x51, 0x70, 0x38, 0x45, 0x2B, 0x42, 0x67, 0x51, 0x51, 0x38, 0x73, 0x71, 0x56, 0x62, 0x0A, 0x31, 0x4D, 0x57, 0x6F, 0x57, 0x57, 0x64, 0x37, 0x56, 0x52, 0x78, 0x4A, ++ 0x71, 0x33, 0x71, 0x64, 0x77, 0x75, 0x64, 0x7A, 0x54, 0x65, 0x2F, 0x4E, 0x43, 0x63, 0x4C, 0x45, 0x56, 0x78, 0x4C, 0x62, 0x41, 0x51, 0x34, 0x6A, 0x65, 0x51, 0x6B, 0x48, 0x4F, 0x36, 0x4C, 0x6F, 0x2F, 0x49, 0x72, 0x50, 0x6A, 0x38, 0x42, 0x47, ++ 0x4A, 0x4A, 0x77, 0x34, 0x4A, 0x2B, 0x43, 0x44, 0x6E, 0x52, 0x75, 0x67, 0x76, 0x33, 0x67, 0x56, 0x45, 0x4F, 0x75, 0x47, 0x54, 0x67, 0x70, 0x61, 0x0A, 0x2F, 0x64, 0x2F, 0x61, 0x4C, 0x49, 0x4A, 0x2B, 0x37, 0x73, 0x72, 0x32, 0x4B, 0x65, 0x48, ++ 0x36, 0x63, 0x61, 0x48, 0x33, 0x69, 0x47, 0x69, 0x63, 0x6E, 0x50, 0x43, 0x4E, 0x76, 0x67, 0x39, 0x4A, 0x6B, 0x64, 0x6A, 0x71, 0x4F, 0x76, 0x6E, 0x39, 0x30, 0x47, 0x68, 0x78, 0x32, 0x2B, 0x6D, 0x31, 0x4B, 0x30, 0x36, 0x43, 0x6B, 0x6D, 0x39, ++ 0x6D, 0x48, 0x2B, 0x44, 0x77, 0x33, 0x45, 0x7A, 0x73, 0x79, 0x74, 0x48, 0x71, 0x75, 0x6E, 0x51, 0x47, 0x2B, 0x62, 0x4F, 0x45, 0x0A, 0x6B, 0x4A, 0x54, 0x52, 0x58, 0x34, 0x35, 0x7A, 0x47, 0x52, 0x42, 0x64, 0x41, 0x75, 0x56, 0x77, 0x70, 0x63, ++ 0x41, 0x51, 0x30, 0x42, 0x42, 0x38, 0x62, 0x38, 0x56, 0x59, 0x53, 0x62, 0x53, 0x77, 0x62, 0x70, 0x72, 0x61, 0x66, 0x5A, 0x58, 0x31, 0x7A, 0x4E, 0x6F, 0x43, 0x72, 0x37, 0x67, 0x73, 0x66, 0x58, 0x6D, 0x50, 0x76, 0x6B, 0x50, 0x78, 0x2B, 0x53, ++ 0x67, 0x6F, 0x6A, 0x51, 0x6C, 0x44, 0x2B, 0x41, 0x6A, 0x64, 0x61, 0x38, 0x69, 0x4C, 0x4C, 0x43, 0x53, 0x78, 0x0A, 0x6A, 0x56, 0x49, 0x48, 0x76, 0x58, 0x69, 0x62, 0x79, 0x38, 0x70, 0x6F, 0x73, 0x71, 0x54, 0x64, 0x44, 0x45, 0x78, 0x35, 0x59, ++ 0x4D, 0x61, 0x5A, 0x30, 0x5A, 0x50, 0x78, 0x4D, 0x42, 0x6F, 0x48, 0x30, 0x36, 0x34, 0x69, 0x77, 0x75, 0x72, 0x4F, 0x38, 0x59, 0x51, 0x4A, 0x7A, 0x4F, 0x41, 0x55, 0x62, 0x6E, 0x38, 0x2F, 0x66, 0x74, 0x4B, 0x43, 0x68, 0x61, 0x7A, 0x63, 0x71, ++ 0x52, 0x5A, 0x4F, 0x68, 0x61, 0x42, 0x67, 0x79, 0x2F, 0x61, 0x63, 0x31, 0x38, 0x69, 0x7A, 0x0A, 0x6A, 0x75, 0x33, 0x47, 0x6D, 0x35, 0x68, 0x31, 0x44, 0x56, 0x58, 0x6F, 0x58, 0x2B, 0x57, 0x56, 0x69, 0x77, 0x4B, 0x6B, 0x72, 0x6B, 0x4D, 0x70, ++ 0x4B, 0x42, 0x47, 0x6B, 0x35, 0x68, 0x49, 0x77, 0x41, 0x55, 0x74, 0x31, 0x61, 0x78, 0x35, 0x6D, 0x6E, 0x58, 0x6B, 0x76, 0x70, 0x58, 0x59, 0x76, 0x48, 0x55, 0x43, 0x30, 0x62, 0x63, 0x6C, 0x39, 0x65, 0x51, 0x6A, 0x73, 0x30, 0x57, 0x71, 0x32, ++ 0x58, 0x53, 0x71, 0x79, 0x70, 0x57, 0x61, 0x39, 0x61, 0x34, 0x58, 0x30, 0x0A, 0x64, 0x46, 0x62, 0x44, 0x39, 0x65, 0x64, 0x31, 0x55, 0x69, 0x67, 0x73, 0x70, 0x66, 0x39, 0x6D, 0x52, 0x36, 0x58, 0x55, 0x2F, 0x76, 0x36, 0x65, 0x56, 0x4C, 0x39, ++ 0x6C, 0x66, 0x67, 0x48, 0x57, 0x4D, 0x49, 0x2B, 0x6C, 0x4E, 0x70, 0x79, 0x69, 0x55, 0x42, 0x7A, 0x75, 0x4F, 0x49, 0x41, 0x42, 0x53, 0x4D, 0x62, 0x48, 0x64, 0x50, 0x54, 0x47, 0x72, 0x4D, 0x4E, 0x41, 0x53, 0x52, 0x5A, 0x68, 0x64, 0x43, 0x79, ++ 0x76, 0x6A, 0x47, 0x38, 0x31, 0x37, 0x58, 0x73, 0x59, 0x0A, 0x41, 0x46, 0x73, 0x32, 0x50, 0x4A, 0x78, 0x51, 0x44, 0x63, 0x71, 0x53, 0x4D, 0x78, 0x44, 0x78, 0x4A, 0x6B, 0x6C, 0x74, 0x33, 0x33, 0x55, 0x6B, 0x4E, 0x34, 0x49, 0x69, 0x31, 0x2B, ++ 0x69, 0x57, 0x2F, 0x52, 0x56, 0x4C, 0x41, 0x70, 0x59, 0x2B, 0x42, 0x33, 0x4B, 0x56, 0x66, 0x71, 0x73, 0x39, 0x54, 0x43, 0x37, 0x58, 0x79, 0x76, 0x44, 0x66, 0x34, 0x46, 0x67, 0x2F, 0x4C, 0x53, 0x38, 0x45, 0x6D, 0x6A, 0x69, 0x6A, 0x41, 0x51, ++ 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x0A, 0x6F, 0x30, 0x49, 0x77, 0x51, 0x44, 0x41, 0x50, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x52, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, 0x54, 0x41, 0x44, 0x41, 0x51, 0x48, 0x2F, 0x4D, 0x41, 0x34, 0x47, 0x41, ++ 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x42, 0x42, 0x6A, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x42, 0x70, 0x4F, 0x6A, 0x43, 0x6C, 0x34, 0x6F, 0x61, ++ 0x54, 0x65, 0x71, 0x0A, 0x59, 0x52, 0x33, 0x72, 0x36, 0x2F, 0x77, 0x74, 0x62, 0x79, 0x50, 0x6B, 0x38, 0x36, 0x41, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4D, 0x42, 0x51, 0x41, 0x44, ++ 0x67, 0x67, 0x49, 0x42, 0x41, 0x4A, 0x61, 0x41, 0x63, 0x67, 0x6B, 0x47, 0x66, 0x70, 0x7A, 0x4D, 0x6B, 0x77, 0x51, 0x57, 0x75, 0x36, 0x41, 0x36, 0x6A, 0x5A, 0x4A, 0x4F, 0x74, 0x78, 0x45, 0x61, 0x43, 0x6E, 0x46, 0x78, 0x45, 0x4D, 0x30, 0x45, ++ 0x0A, 0x72, 0x58, 0x2B, 0x6C, 0x52, 0x56, 0x41, 0x51, 0x5A, 0x6B, 0x35, 0x4B, 0x51, 0x61, 0x49, 0x44, 0x32, 0x52, 0x46, 0x50, 0x65, 0x6A, 0x65, 0x35, 0x53, 0x2B, 0x4C, 0x47, 0x6A, 0x7A, 0x4A, 0x6D, 0x64, 0x53, 0x58, 0x37, 0x36, 0x38, 0x34, ++ 0x2F, 0x41, 0x79, 0x6B, 0x6D, 0x6A, 0x62, 0x67, 0x57, 0x48, 0x66, 0x59, 0x66, 0x4D, 0x32, 0x35, 0x49, 0x35, 0x75, 0x6A, 0x34, 0x56, 0x37, 0x49, 0x62, 0x65, 0x64, 0x38, 0x37, 0x68, 0x77, 0x72, 0x69, 0x5A, 0x4C, 0x6F, 0x41, 0x0A, 0x79, 0x6D, ++ 0x7A, 0x76, 0x66, 0x74, 0x41, 0x6A, 0x36, 0x33, 0x69, 0x50, 0x2F, 0x32, 0x53, 0x62, 0x4E, 0x44, 0x65, 0x66, 0x4E, 0x57, 0x57, 0x69, 0x70, 0x41, 0x41, 0x39, 0x45, 0x69, 0x4F, 0x57, 0x57, 0x46, 0x33, 0x4B, 0x59, 0x34, 0x66, 0x47, 0x6F, 0x77, ++ 0x65, 0x49, 0x54, 0x65, 0x64, 0x70, 0x64, 0x6F, 0x70, 0x54, 0x7A, 0x66, 0x46, 0x50, 0x37, 0x45, 0x4C, 0x79, 0x6B, 0x2B, 0x4F, 0x5A, 0x70, 0x44, 0x63, 0x38, 0x68, 0x37, 0x68, 0x69, 0x32, 0x2F, 0x44, 0x73, 0x0A, 0x48, 0x7A, 0x63, 0x2F, 0x4E, ++ 0x31, 0x39, 0x44, 0x7A, 0x46, 0x47, 0x64, 0x74, 0x66, 0x43, 0x58, 0x77, 0x72, 0x65, 0x46, 0x61, 0x6D, 0x67, 0x4C, 0x52, 0x42, 0x37, 0x6C, 0x55, 0x65, 0x36, 0x54, 0x7A, 0x6B, 0x74, 0x75, 0x68, 0x73, 0x48, 0x53, 0x44, 0x43, 0x52, 0x5A, 0x4E, ++ 0x68, 0x71, 0x66, 0x4C, 0x4A, 0x47, 0x50, 0x34, 0x78, 0x6A, 0x62, 0x6C, 0x4A, 0x55, 0x4B, 0x37, 0x5A, 0x47, 0x71, 0x44, 0x70, 0x6E, 0x63, 0x6C, 0x6C, 0x50, 0x6A, 0x59, 0x59, 0x50, 0x47, 0x0A, 0x46, 0x72, 0x6F, 0x6A, 0x75, 0x74, 0x7A, 0x64, ++ 0x66, 0x68, 0x72, 0x47, 0x65, 0x30, 0x4B, 0x32, 0x32, 0x56, 0x6F, 0x46, 0x33, 0x4A, 0x70, 0x66, 0x31, 0x64, 0x2B, 0x34, 0x32, 0x6B, 0x64, 0x39, 0x32, 0x6A, 0x6A, 0x62, 0x72, 0x44, 0x6E, 0x56, 0x48, 0x6D, 0x74, 0x73, 0x4B, 0x68, 0x65, 0x4D, ++ 0x59, 0x63, 0x32, 0x78, 0x62, 0x58, 0x49, 0x42, 0x77, 0x38, 0x4D, 0x67, 0x41, 0x47, 0x4A, 0x6F, 0x46, 0x6A, 0x48, 0x56, 0x64, 0x71, 0x71, 0x47, 0x75, 0x77, 0x36, 0x71, 0x0A, 0x6E, 0x73, 0x62, 0x35, 0x38, 0x4E, 0x6E, 0x34, 0x44, 0x53, 0x45, ++ 0x43, 0x35, 0x4D, 0x55, 0x6F, 0x46, 0x6C, 0x6B, 0x52, 0x75, 0x64, 0x6C, 0x70, 0x63, 0x79, 0x71, 0x53, 0x65, 0x4C, 0x69, 0x53, 0x56, 0x35, 0x73, 0x49, 0x38, 0x6A, 0x72, 0x6C, 0x4C, 0x35, 0x57, 0x77, 0x57, 0x4C, 0x64, 0x72, 0x49, 0x42, 0x52, ++ 0x74, 0x46, 0x4F, 0x38, 0x4B, 0x76, 0x48, 0x37, 0x59, 0x56, 0x64, 0x69, 0x49, 0x32, 0x69, 0x2F, 0x36, 0x47, 0x61, 0x58, 0x37, 0x69, 0x2B, 0x42, 0x2F, 0x0A, 0x4F, 0x66, 0x56, 0x79, 0x4B, 0x34, 0x58, 0x45, 0x4C, 0x4B, 0x7A, 0x76, 0x47, 0x55, ++ 0x57, 0x53, 0x54, 0x4C, 0x4E, 0x68, 0x42, 0x39, 0x78, 0x4E, 0x48, 0x32, 0x37, 0x53, 0x67, 0x52, 0x4E, 0x63, 0x6D, 0x76, 0x4D, 0x53, 0x5A, 0x34, 0x50, 0x50, 0x6D, 0x7A, 0x2B, 0x4C, 0x6E, 0x35, 0x32, 0x6B, 0x75, 0x61, 0x69, 0x57, 0x41, 0x33, ++ 0x72, 0x46, 0x37, 0x69, 0x44, 0x65, 0x4D, 0x39, 0x6F, 0x76, 0x6E, 0x68, 0x70, 0x36, 0x64, 0x42, 0x37, 0x68, 0x37, 0x73, 0x78, 0x61, 0x0A, 0x4F, 0x67, 0x54, 0x64, 0x73, 0x78, 0x6F, 0x45, 0x71, 0x42, 0x52, 0x6A, 0x72, 0x4C, 0x64, 0x48, 0x45, ++ 0x6F, 0x4F, 0x61, 0x62, 0x50, 0x58, 0x6D, 0x36, 0x52, 0x55, 0x56, 0x6B, 0x52, 0x71, 0x45, 0x47, 0x51, 0x36, 0x55, 0x52, 0x4F, 0x63, 0x53, 0x6A, 0x69, 0x56, 0x62, 0x67, 0x47, 0x63, 0x5A, 0x33, 0x47, 0x4F, 0x54, 0x45, 0x41, 0x74, 0x6C, 0x4C, ++ 0x6F, 0x72, 0x36, 0x43, 0x5A, 0x70, 0x4F, 0x32, 0x6F, 0x59, 0x6F, 0x66, 0x61, 0x70, 0x68, 0x4E, 0x64, 0x67, 0x4F, 0x0A, 0x70, 0x79, 0x67, 0x61, 0x75, 0x31, 0x4C, 0x67, 0x65, 0x50, 0x68, 0x73, 0x75, 0x6D, 0x79, 0x77, 0x62, 0x72, 0x6D, 0x48, ++ 0x58, 0x75, 0x6D, 0x5A, 0x4E, 0x54, 0x66, 0x78, 0x50, 0x57, 0x51, 0x72, 0x71, 0x61, 0x41, 0x30, 0x6B, 0x38, 0x39, 0x6A, 0x4C, 0x39, 0x57, 0x42, 0x33, 0x36, 0x35, 0x6A, 0x4A, 0x36, 0x55, 0x65, 0x54, 0x6F, 0x33, 0x63, 0x4B, 0x58, 0x68, 0x5A, ++ 0x2B, 0x50, 0x6D, 0x68, 0x49, 0x49, 0x79, 0x6E, 0x4A, 0x6B, 0x42, 0x75, 0x67, 0x6E, 0x4C, 0x4E, 0x0A, 0x65, 0x4C, 0x4C, 0x49, 0x6A, 0x7A, 0x77, 0x65, 0x63, 0x2B, 0x66, 0x42, 0x48, 0x37, 0x2F, 0x50, 0x7A, 0x71, 0x55, 0x71, 0x6D, 0x39, 0x74, ++ 0x45, 0x5A, 0x44, 0x4B, 0x67, 0x75, 0x33, 0x39, 0x63, 0x4A, 0x52, 0x4E, 0x49, 0x74, 0x58, 0x2B, 0x53, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, ++ 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x35, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x43, 0x49, ++ 0x7A, 0x43, 0x43, 0x41, 0x61, 0x6D, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x55, 0x46, 0x68, 0x58, 0x48, 0x77, 0x39, 0x68, 0x4A, 0x70, 0x37, 0x35, 0x70, 0x44, 0x49, 0x71, 0x49, 0x37, 0x66, 0x42, 0x77, 0x2B, 0x64, 0x32, 0x33, 0x50, ++ 0x6F, 0x63, 0x77, 0x43, 0x67, 0x59, 0x49, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x45, 0x41, 0x77, 0x4D, 0x77, 0x55, 0x54, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x0A, 0x42, 0x68, 0x4D, 0x43, 0x53, 0x6C, 0x41, 0x78, ++ 0x49, 0x7A, 0x41, 0x68, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x47, 0x6B, 0x4E, 0x35, 0x59, 0x6D, 0x56, 0x79, 0x64, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x51, 0x67, 0x53, 0x6D, 0x46, 0x77, 0x59, 0x57, 0x34, 0x67, 0x51, 0x32, 0x38, 0x75, ++ 0x4C, 0x43, 0x42, 0x4D, 0x64, 0x47, 0x51, 0x75, 0x4D, 0x52, 0x30, 0x77, 0x47, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x52, 0x54, 0x5A, 0x57, 0x4E, 0x31, 0x0A, 0x63, 0x6D, 0x56, 0x54, 0x61, 0x57, 0x64, 0x75, 0x49, 0x46, 0x4A, ++ 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x78, 0x4E, 0x54, 0x41, 0x65, 0x46, 0x77, 0x30, 0x79, 0x4D, 0x44, 0x41, 0x30, 0x4D, 0x44, 0x67, 0x77, 0x4F, 0x44, 0x4D, 0x79, 0x4E, 0x54, 0x5A, 0x61, 0x46, 0x77, 0x30, 0x30, 0x4E, 0x54, 0x41, ++ 0x30, 0x4D, 0x44, 0x67, 0x77, 0x4F, 0x44, 0x4D, 0x79, 0x4E, 0x54, 0x5A, 0x61, 0x4D, 0x46, 0x45, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x0A, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6B, 0x70, 0x51, 0x4D, 0x53, 0x4D, 0x77, 0x49, 0x51, ++ 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x45, 0x78, 0x70, 0x44, 0x65, 0x57, 0x4A, 0x6C, 0x63, 0x6E, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x49, 0x45, 0x70, 0x68, 0x63, 0x47, 0x46, 0x75, 0x49, 0x45, 0x4E, 0x76, 0x4C, 0x69, 0x77, 0x67, 0x54, 0x48, ++ 0x52, 0x6B, 0x4C, 0x6A, 0x45, 0x64, 0x4D, 0x42, 0x73, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x55, 0x55, 0x32, 0x56, 0x6A, 0x0A, 0x64, 0x58, 0x4A, 0x6C, 0x55, 0x32, 0x6C, 0x6E, 0x62, 0x69, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, ++ 0x45, 0x4E, 0x42, 0x4D, 0x54, 0x55, 0x77, 0x64, 0x6A, 0x41, 0x51, 0x42, 0x67, 0x63, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x49, 0x42, 0x42, 0x67, 0x55, 0x72, 0x67, 0x51, 0x51, 0x41, 0x49, 0x67, 0x4E, 0x69, 0x41, 0x41, 0x51, 0x4C, 0x55, ++ 0x48, 0x53, 0x4E, 0x5A, 0x44, 0x4B, 0x5A, 0x6D, 0x62, 0x50, 0x53, 0x59, 0x41, 0x69, 0x34, 0x49, 0x6F, 0x35, 0x47, 0x0A, 0x64, 0x43, 0x78, 0x34, 0x77, 0x43, 0x74, 0x45, 0x4C, 0x57, 0x31, 0x66, 0x48, 0x63, 0x6D, 0x75, 0x53, 0x31, 0x49, 0x67, ++ 0x67, 0x7A, 0x32, 0x34, 0x46, 0x47, 0x31, 0x54, 0x68, 0x32, 0x43, 0x65, 0x58, 0x32, 0x79, 0x46, 0x32, 0x77, 0x59, 0x55, 0x6C, 0x65, 0x44, 0x48, 0x4B, 0x50, 0x2B, 0x64, 0x58, 0x2B, 0x53, 0x71, 0x38, 0x62, 0x4F, 0x4C, 0x62, 0x65, 0x31, 0x50, ++ 0x4C, 0x30, 0x76, 0x4A, 0x53, 0x70, 0x53, 0x52, 0x5A, 0x48, 0x58, 0x2B, 0x41, 0x65, 0x7A, 0x42, 0x0A, 0x32, 0x4F, 0x74, 0x36, 0x6C, 0x48, 0x68, 0x57, 0x47, 0x45, 0x4E, 0x66, 0x61, 0x34, 0x48, 0x4C, 0x39, 0x72, 0x7A, 0x61, 0x74, 0x41, 0x79, ++ 0x32, 0x4B, 0x5A, 0x4D, 0x49, 0x61, 0x59, 0x2B, 0x6A, 0x51, 0x6A, 0x42, 0x41, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x44, 0x67, 0x59, ++ 0x44, 0x56, 0x52, 0x30, 0x50, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x51, 0x44, 0x0A, 0x41, 0x67, 0x45, 0x47, 0x4D, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x54, 0x72, 0x51, 0x63, 0x69, 0x75, 0x2F, 0x4E, ++ 0x57, 0x65, 0x55, 0x55, 0x6A, 0x31, 0x76, 0x59, 0x76, 0x30, 0x68, 0x79, 0x43, 0x54, 0x51, 0x53, 0x76, 0x54, 0x39, 0x44, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x77, 0x4E, 0x6F, 0x41, 0x44, ++ 0x42, 0x6C, 0x41, 0x6A, 0x45, 0x41, 0x32, 0x53, 0x36, 0x4A, 0x0A, 0x66, 0x6C, 0x35, 0x4F, 0x70, 0x42, 0x45, 0x48, 0x76, 0x56, 0x6E, 0x43, 0x42, 0x39, 0x36, 0x72, 0x4D, 0x6A, 0x68, 0x54, 0x4B, 0x6B, 0x5A, 0x45, 0x42, 0x68, 0x64, 0x36, 0x7A, ++ 0x6C, 0x48, 0x70, 0x34, 0x50, 0x39, 0x6D, 0x4C, 0x51, 0x6C, 0x4F, 0x34, 0x45, 0x2F, 0x30, 0x42, 0x64, 0x47, 0x46, 0x39, 0x6A, 0x56, 0x67, 0x33, 0x50, 0x56, 0x79, 0x73, 0x30, 0x5A, 0x39, 0x41, 0x6A, 0x42, 0x45, 0x6D, 0x45, 0x59, 0x61, 0x67, ++ 0x6F, 0x55, 0x65, 0x59, 0x57, 0x6D, 0x4A, 0x0A, 0x53, 0x77, 0x64, 0x4C, 0x5A, 0x72, 0x57, 0x65, 0x71, 0x72, 0x71, 0x67, 0x48, 0x6B, 0x48, 0x5A, 0x41, 0x58, 0x51, 0x36, 0x62, 0x6B, 0x55, 0x36, 0x69, 0x59, 0x41, 0x5A, 0x65, 0x7A, 0x4B, 0x59, ++ 0x56, 0x57, 0x4F, 0x72, 0x36, 0x32, 0x4E, 0x75, 0x6B, 0x32, 0x32, 0x72, 0x47, 0x77, 0x6C, 0x67, 0x4D, 0x55, 0x34, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, ++ 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x42, 0x52, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, 0x32, 0x30, 0x32, 0x33, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, ++ 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x71, 0x54, 0x43, 0x43, 0x41, 0x35, 0x47, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x63, 0x7A, 0x73, 0x77, 0x42, 0x45, 0x68, 0x62, 0x32, 0x55, 0x31, 0x34, ++ 0x4C, 0x6E, 0x4E, 0x4C, 0x79, 0x61, 0x48, 0x63, 0x5A, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x30, 0x46, 0x41, 0x44, 0x42, 0x49, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, ++ 0x56, 0x51, 0x51, 0x47, 0x0A, 0x45, 0x77, 0x4A, 0x45, 0x52, 0x54, 0x45, 0x56, 0x4D, 0x42, 0x4D, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x4D, 0x52, 0x43, 0x31, 0x55, 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x43, 0x42, 0x48, 0x62, 0x57, 0x4A, ++ 0x49, 0x4D, 0x53, 0x49, 0x77, 0x49, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x6C, 0x45, 0x4C, 0x56, 0x52, 0x53, 0x56, 0x56, 0x4E, 0x55, 0x49, 0x45, 0x4A, 0x53, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, ++ 0x67, 0x0A, 0x4D, 0x69, 0x41, 0x79, 0x4D, 0x44, 0x49, 0x7A, 0x4D, 0x42, 0x34, 0x58, 0x44, 0x54, 0x49, 0x7A, 0x4D, 0x44, 0x55, 0x77, 0x4F, 0x54, 0x41, 0x34, 0x4E, 0x54, 0x59, 0x7A, 0x4D, 0x56, 0x6F, 0x58, 0x44, 0x54, 0x4D, 0x34, 0x4D, 0x44, ++ 0x55, 0x77, 0x4F, 0x54, 0x41, 0x34, 0x4E, 0x54, 0x59, 0x7A, 0x4D, 0x46, 0x6F, 0x77, 0x53, 0x44, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x52, 0x45, 0x55, 0x78, 0x46, 0x54, 0x41, 0x54, 0x0A, 0x42, ++ 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x44, 0x45, 0x51, 0x74, 0x56, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x51, 0x67, 0x52, 0x32, 0x31, 0x69, 0x53, 0x44, 0x45, 0x69, 0x4D, 0x43, 0x41, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x5A, 0x52, ++ 0x43, 0x31, 0x55, 0x55, 0x6C, 0x56, 0x54, 0x56, 0x43, 0x42, 0x43, 0x55, 0x69, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x42, 0x49, 0x44, 0x49, 0x67, 0x4D, 0x6A, 0x41, 0x79, 0x4D, 0x7A, 0x43, 0x43, 0x0A, 0x41, 0x69, 0x49, 0x77, ++ 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x50, 0x41, 0x44, 0x43, 0x43, 0x41, 0x67, 0x6F, 0x43, 0x67, 0x67, 0x49, 0x42, 0x41, 0x4B, 0x37, 0x2F, ++ 0x43, 0x56, 0x6D, 0x52, 0x67, 0x41, 0x70, 0x4B, 0x61, 0x4F, 0x59, 0x6B, 0x50, 0x37, 0x69, 0x6E, 0x35, 0x4D, 0x67, 0x36, 0x43, 0x6A, 0x6F, 0x57, 0x7A, 0x63, 0x6B, 0x6A, 0x59, 0x61, 0x43, 0x54, 0x0A, 0x63, 0x66, 0x4B, 0x72, 0x69, 0x33, 0x4F, ++ 0x50, 0x6F, 0x47, 0x64, 0x6C, 0x59, 0x4E, 0x4A, 0x55, 0x61, 0x32, 0x4E, 0x52, 0x62, 0x30, 0x6B, 0x7A, 0x34, 0x48, 0x49, 0x48, 0x45, 0x33, 0x30, 0x34, 0x7A, 0x51, 0x61, 0x53, 0x42, 0x79, 0x6C, 0x53, 0x61, 0x30, 0x35, 0x33, 0x62, 0x41, 0x54, ++ 0x54, 0x6C, 0x66, 0x72, 0x64, 0x54, 0x49, 0x7A, 0x5A, 0x58, 0x63, 0x46, 0x68, 0x66, 0x55, 0x76, 0x6E, 0x4B, 0x4C, 0x4E, 0x45, 0x67, 0x58, 0x74, 0x52, 0x72, 0x39, 0x30, 0x7A, 0x0A, 0x73, 0x57, 0x68, 0x38, 0x31, 0x6B, 0x35, 0x4D, 0x2F, 0x69, ++ 0x74, 0x6F, 0x75, 0x63, 0x70, 0x6D, 0x61, 0x63, 0x54, 0x73, 0x58, 0x6C, 0x64, 0x2F, 0x39, 0x77, 0x33, 0x48, 0x6E, 0x44, 0x59, 0x32, 0x35, 0x51, 0x64, 0x67, 0x72, 0x4D, 0x42, 0x4D, 0x36, 0x67, 0x68, 0x73, 0x37, 0x77, 0x5A, 0x38, 0x54, 0x31, ++ 0x73, 0x6F, 0x65, 0x67, 0x6A, 0x38, 0x6B, 0x31, 0x32, 0x62, 0x39, 0x70, 0x79, 0x30, 0x69, 0x34, 0x61, 0x36, 0x49, 0x62, 0x6E, 0x30, 0x38, 0x4F, 0x68, 0x5A, 0x0A, 0x57, 0x69, 0x69, 0x68, 0x4E, 0x49, 0x51, 0x61, 0x4A, 0x5A, 0x47, 0x32, 0x74, ++ 0x59, 0x2F, 0x76, 0x73, 0x76, 0x6D, 0x41, 0x2B, 0x76, 0x6B, 0x39, 0x50, 0x42, 0x46, 0x79, 0x32, 0x4F, 0x4D, 0x76, 0x68, 0x6E, 0x62, 0x46, 0x65, 0x53, 0x7A, 0x42, 0x71, 0x5A, 0x43, 0x54, 0x52, 0x70, 0x68, 0x6E, 0x79, 0x34, 0x4E, 0x71, 0x6F, ++ 0x46, 0x41, 0x6A, 0x70, 0x7A, 0x76, 0x32, 0x67, 0x54, 0x6E, 0x67, 0x37, 0x66, 0x43, 0x35, 0x76, 0x32, 0x58, 0x78, 0x32, 0x4D, 0x74, 0x36, 0x0A, 0x2B, 0x2B, 0x39, 0x7A, 0x41, 0x38, 0x34, 0x41, 0x39, 0x48, 0x33, 0x58, 0x34, 0x46, 0x30, 0x37, ++ 0x5A, 0x72, 0x6A, 0x63, 0x6A, 0x72, 0x71, 0x44, 0x79, 0x34, 0x64, 0x32, 0x41, 0x2F, 0x77, 0x6C, 0x32, 0x65, 0x63, 0x6A, 0x62, 0x77, 0x62, 0x39, 0x5A, 0x2F, 0x50, 0x67, 0x2F, 0x34, 0x53, 0x38, 0x52, 0x37, 0x2B, 0x31, 0x46, 0x68, 0x68, 0x47, ++ 0x61, 0x52, 0x54, 0x4D, 0x42, 0x66, 0x66, 0x62, 0x30, 0x30, 0x6D, 0x73, 0x61, 0x38, 0x79, 0x72, 0x35, 0x4C, 0x55, 0x4C, 0x0A, 0x51, 0x79, 0x52, 0x65, 0x53, 0x32, 0x74, 0x4E, 0x5A, 0x39, 0x2F, 0x57, 0x74, 0x54, 0x35, 0x50, 0x65, 0x42, 0x2B, ++ 0x55, 0x63, 0x53, 0x54, 0x71, 0x33, 0x6E, 0x44, 0x38, 0x38, 0x5A, 0x50, 0x2B, 0x6E, 0x70, 0x4E, 0x61, 0x35, 0x4A, 0x52, 0x61, 0x6C, 0x31, 0x51, 0x4D, 0x4E, 0x58, 0x74, 0x66, 0x62, 0x4F, 0x34, 0x41, 0x48, 0x79, 0x54, 0x73, 0x41, 0x37, 0x6F, ++ 0x43, 0x39, 0x58, 0x62, 0x30, 0x6E, 0x39, 0x53, 0x61, 0x37, 0x59, 0x55, 0x73, 0x4F, 0x43, 0x49, 0x76, 0x0A, 0x78, 0x39, 0x67, 0x76, 0x64, 0x68, 0x46, 0x50, 0x2F, 0x57, 0x78, 0x63, 0x36, 0x50, 0x57, 0x4F, 0x4A, 0x34, 0x64, 0x2F, 0x47, 0x55, ++ 0x6F, 0x68, 0x52, 0x35, 0x41, 0x64, 0x65, 0x59, 0x30, 0x63, 0x57, 0x2F, 0x6A, 0x50, 0x53, 0x6F, 0x58, 0x6B, 0x37, 0x62, 0x4E, 0x62, 0x6A, 0x62, 0x37, 0x45, 0x5A, 0x43, 0x68, 0x64, 0x51, 0x63, 0x52, 0x75, 0x72, 0x44, 0x68, 0x61, 0x54, 0x79, ++ 0x4E, 0x30, 0x64, 0x4B, 0x6B, 0x53, 0x77, 0x2F, 0x62, 0x53, 0x75, 0x52, 0x45, 0x56, 0x0A, 0x4D, 0x77, 0x65, 0x52, 0x32, 0x44, 0x73, 0x33, 0x4F, 0x6D, 0x4D, 0x77, 0x42, 0x74, 0x48, 0x46, 0x49, 0x6A, 0x59, 0x6F, 0x59, 0x69, 0x4D, 0x51, 0x34, ++ 0x45, 0x62, 0x4D, 0x6C, 0x36, 0x7A, 0x57, 0x4B, 0x31, 0x31, 0x6B, 0x4A, 0x4E, 0x58, 0x75, 0x48, 0x41, 0x37, 0x65, 0x2B, 0x77, 0x68, 0x61, 0x64, 0x53, 0x72, 0x32, 0x59, 0x32, 0x33, 0x4F, 0x43, 0x30, 0x4B, 0x2B, 0x30, 0x62, 0x70, 0x77, 0x48, ++ 0x4A, 0x77, 0x68, 0x35, 0x51, 0x38, 0x78, 0x61, 0x52, 0x66, 0x58, 0x0A, 0x2F, 0x41, 0x71, 0x30, 0x33, 0x75, 0x32, 0x41, 0x6E, 0x4D, 0x75, 0x53, 0x74, 0x49, 0x76, 0x31, 0x33, 0x6C, 0x6D, 0x69, 0x57, 0x41, 0x6D, 0x6C, 0x59, 0x30, 0x63, 0x4C, ++ 0x34, 0x55, 0x45, 0x79, 0x4E, 0x45, 0x48, 0x5A, 0x6D, 0x72, 0x48, 0x5A, 0x71, 0x4C, 0x41, 0x62, 0x57, 0x74, 0x34, 0x4E, 0x44, 0x66, 0x54, 0x69, 0x73, 0x6C, 0x30, 0x31, 0x67, 0x4C, 0x6D, 0x42, 0x31, 0x49, 0x52, 0x70, 0x6B, 0x51, 0x4C, 0x4C, ++ 0x64, 0x64, 0x43, 0x4E, 0x78, 0x62, 0x55, 0x39, 0x0A, 0x43, 0x5A, 0x45, 0x4A, 0x6A, 0x78, 0x53, 0x68, 0x46, 0x48, 0x52, 0x35, 0x50, 0x74, 0x62, 0x4A, 0x46, 0x52, 0x32, 0x6B, 0x57, 0x56, 0x6B, 0x69, 0x33, 0x50, 0x61, 0x4B, 0x52, 0x54, 0x30, ++ 0x38, 0x45, 0x74, 0x59, 0x2B, 0x58, 0x54, 0x49, 0x76, 0x41, 0x67, 0x4D, 0x42, 0x41, 0x41, 0x47, 0x6A, 0x67, 0x59, 0x34, 0x77, 0x67, 0x59, 0x73, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, ++ 0x77, 0x41, 0x77, 0x45, 0x42, 0x0A, 0x2F, 0x7A, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x5A, 0x35, 0x44, 0x77, 0x31, 0x74, 0x36, 0x31, 0x47, 0x4E, 0x56, 0x47, 0x4B, 0x58, 0x35, 0x63, 0x71, 0x2F, ++ 0x69, 0x65, 0x43, 0x4C, 0x78, 0x6B, 0x6C, 0x52, 0x41, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x51, 0x44, 0x41, 0x67, 0x45, 0x47, 0x4D, 0x45, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x64, 0x48, 0x77, ++ 0x52, 0x43, 0x0A, 0x4D, 0x45, 0x41, 0x77, 0x50, 0x71, 0x41, 0x38, 0x6F, 0x44, 0x71, 0x47, 0x4F, 0x47, 0x68, 0x30, 0x64, 0x48, 0x41, 0x36, 0x4C, 0x79, 0x39, 0x6A, 0x63, 0x6D, 0x77, 0x75, 0x5A, 0x43, 0x31, 0x30, 0x63, 0x6E, 0x56, 0x7A, 0x64, ++ 0x43, 0x35, 0x75, 0x5A, 0x58, 0x51, 0x76, 0x59, 0x33, 0x4A, 0x73, 0x4C, 0x32, 0x51, 0x74, 0x64, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x52, 0x66, 0x59, 0x6E, 0x4A, 0x66, 0x63, 0x6D, 0x39, 0x76, 0x64, 0x46, 0x39, 0x6A, 0x59, 0x56, 0x38, 0x79, 0x0A, ++ 0x58, 0x7A, 0x49, 0x77, 0x4D, 0x6A, 0x4D, 0x75, 0x59, 0x33, 0x4A, 0x73, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x44, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x41, 0x51, 0x41, 0x30, ++ 0x39, 0x37, 0x4E, 0x33, 0x55, 0x39, 0x73, 0x77, 0x46, 0x72, 0x6B, 0x74, 0x70, 0x53, 0x48, 0x78, 0x51, 0x43, 0x46, 0x31, 0x36, 0x2B, 0x74, 0x49, 0x46, 0x6F, 0x45, 0x39, 0x63, 0x2B, 0x43, 0x65, 0x4A, 0x79, 0x72, 0x72, 0x0A, 0x64, 0x36, 0x6B, ++ 0x54, 0x70, 0x47, 0x6F, 0x4B, 0x57, 0x6C, 0x6F, 0x55, 0x4D, 0x7A, 0x31, 0x6F, 0x48, 0x34, 0x47, 0x75, 0x61, 0x66, 0x32, 0x4D, 0x6E, 0x32, 0x56, 0x73, 0x4E, 0x45, 0x4C, 0x5A, 0x4C, 0x64, 0x42, 0x2F, 0x65, 0x42, 0x61, 0x78, 0x4F, 0x71, 0x77, ++ 0x6A, 0x4D, 0x61, 0x31, 0x65, 0x66, 0x36, 0x37, 0x6E, 0x72, 0x69, 0x76, 0x36, 0x75, 0x76, 0x77, 0x38, 0x6C, 0x35, 0x56, 0x41, 0x6B, 0x31, 0x2F, 0x44, 0x4C, 0x51, 0x4F, 0x6A, 0x37, 0x61, 0x52, 0x76, 0x0A, 0x55, 0x39, 0x66, 0x36, 0x51, 0x41, ++ 0x34, 0x77, 0x39, 0x51, 0x41, 0x67, 0x4C, 0x41, 0x42, 0x4D, 0x6A, 0x44, 0x75, 0x30, 0x6F, 0x78, 0x2B, 0x32, 0x76, 0x35, 0x45, 0x79, 0x71, 0x36, 0x2B, 0x53, 0x6D, 0x4E, 0x4D, 0x57, 0x35, 0x74, 0x54, 0x52, 0x56, 0x46, 0x78, 0x44, 0x57, 0x79, ++ 0x36, 0x75, 0x37, 0x31, 0x63, 0x71, 0x71, 0x4C, 0x52, 0x76, 0x70, 0x4F, 0x38, 0x4E, 0x56, 0x68, 0x54, 0x61, 0x49, 0x61, 0x73, 0x67, 0x64, 0x70, 0x34, 0x44, 0x2F, 0x43, 0x61, 0x34, 0x0A, 0x6E, 0x6A, 0x38, 0x2B, 0x41, 0x79, 0x62, 0x6D, 0x54, ++ 0x4E, 0x75, 0x64, 0x58, 0x30, 0x4B, 0x45, 0x50, 0x55, 0x55, 0x44, 0x41, 0x78, 0x78, 0x5A, 0x69, 0x4D, 0x72, 0x63, 0x4C, 0x6D, 0x45, 0x6B, 0x57, 0x71, 0x54, 0x71, 0x4A, 0x77, 0x74, 0x7A, 0x45, 0x72, 0x35, 0x53, 0x73, 0x77, 0x72, 0x50, 0x4D, ++ 0x68, 0x66, 0x69, 0x48, 0x6F, 0x63, 0x61, 0x46, 0x70, 0x56, 0x49, 0x62, 0x56, 0x72, 0x67, 0x30, 0x4D, 0x38, 0x4A, 0x6B, 0x69, 0x5A, 0x6D, 0x6B, 0x64, 0x69, 0x6A, 0x0A, 0x59, 0x51, 0x36, 0x71, 0x67, 0x59, 0x46, 0x2F, 0x36, 0x46, 0x4B, 0x43, ++ 0x30, 0x55, 0x4C, 0x6E, 0x34, 0x42, 0x30, 0x59, 0x2B, 0x71, 0x53, 0x46, 0x4E, 0x75, 0x65, 0x47, 0x34, 0x41, 0x33, 0x72, 0x76, 0x4E, 0x54, 0x4A, 0x31, 0x6A, 0x78, 0x44, 0x38, 0x56, 0x31, 0x4A, 0x62, 0x6E, 0x36, 0x42, 0x6D, 0x32, 0x6D, 0x31, ++ 0x69, 0x57, 0x4B, 0x50, 0x69, 0x46, 0x4C, 0x59, 0x31, 0x2F, 0x34, 0x6E, 0x77, 0x53, 0x50, 0x46, 0x79, 0x79, 0x73, 0x43, 0x75, 0x37, 0x46, 0x66, 0x0A, 0x2F, 0x76, 0x74, 0x44, 0x68, 0x51, 0x4E, 0x47, 0x76, 0x6C, 0x33, 0x47, 0x79, 0x69, 0x45, ++ 0x6D, 0x2F, 0x39, 0x63, 0x43, 0x6E, 0x6E, 0x52, 0x4B, 0x33, 0x50, 0x67, 0x54, 0x46, 0x62, 0x47, 0x42, 0x56, 0x7A, 0x62, 0x4C, 0x5A, 0x56, 0x7A, 0x52, 0x48, 0x54, 0x46, 0x33, 0x36, 0x53, 0x58, 0x44, 0x77, 0x37, 0x49, 0x79, 0x4E, 0x39, 0x58, ++ 0x78, 0x6D, 0x41, 0x6E, 0x6B, 0x62, 0x57, 0x4F, 0x41, 0x43, 0x4B, 0x73, 0x47, 0x6B, 0x6F, 0x48, 0x55, 0x36, 0x58, 0x43, 0x50, 0x0A, 0x70, 0x7A, 0x2B, 0x79, 0x37, 0x59, 0x61, 0x4D, 0x67, 0x6D, 0x6F, 0x31, 0x79, 0x45, 0x4A, 0x61, 0x67, 0x74, ++ 0x46, 0x53, 0x47, 0x6B, 0x55, 0x50, 0x46, 0x61, 0x55, 0x41, 0x38, 0x4A, 0x52, 0x37, 0x5A, 0x53, 0x64, 0x58, 0x4F, 0x55, 0x50, 0x50, 0x66, 0x48, 0x2F, 0x6D, 0x76, 0x54, 0x57, 0x7A, 0x65, 0x2F, 0x45, 0x5A, 0x54, 0x4E, 0x34, 0x36, 0x6C, 0x73, ++ 0x2F, 0x70, 0x64, 0x75, 0x34, 0x44, 0x35, 0x38, 0x4A, 0x44, 0x55, 0x6A, 0x78, 0x71, 0x67, 0x65, 0x6A, 0x42, 0x0A, 0x57, 0x6F, 0x43, 0x39, 0x45, 0x56, 0x32, 0x54, 0x61, 0x2F, 0x76, 0x48, 0x35, 0x6D, 0x51, 0x2F, 0x75, 0x32, 0x6B, 0x63, 0x36, ++ 0x64, 0x30, 0x6C, 0x69, 0x36, 0x39, 0x30, 0x79, 0x56, 0x52, 0x41, 0x79, 0x73, 0x75, 0x54, 0x45, 0x77, 0x72, 0x74, 0x2B, 0x32, 0x61, 0x53, 0x45, 0x63, 0x72, 0x31, 0x77, 0x50, 0x72, 0x59, 0x67, 0x31, 0x55, 0x44, 0x66, 0x4E, 0x50, 0x46, 0x49, ++ 0x6B, 0x5A, 0x31, 0x63, 0x47, 0x74, 0x35, 0x53, 0x41, 0x59, 0x71, 0x67, 0x70, 0x71, 0x2F, 0x0A, 0x35, 0x75, 0x73, 0x57, 0x44, 0x69, 0x4A, 0x46, 0x41, 0x62, 0x7A, 0x64, 0x4E, 0x70, 0x51, 0x30, 0x71, 0x54, 0x55, 0x6D, 0x69, 0x74, 0x65, 0x58, ++ 0x75, 0x65, 0x34, 0x49, 0x63, 0x72, 0x38, 0x30, 0x6B, 0x6E, 0x43, 0x44, 0x67, 0x4B, 0x73, 0x34, 0x71, 0x6C, 0x6C, 0x6F, 0x33, 0x55, 0x43, 0x6B, 0x47, 0x4A, 0x43, 0x79, 0x38, 0x39, 0x55, 0x44, 0x79, 0x69, 0x62, 0x4B, 0x37, 0x39, 0x58, 0x48, ++ 0x34, 0x49, 0x39, 0x54, 0x6A, 0x76, 0x41, 0x41, 0x34, 0x36, 0x6A, 0x74, 0x0A, 0x6E, 0x2F, 0x6D, 0x74, 0x64, 0x2B, 0x41, 0x72, 0x59, 0x30, 0x2B, 0x65, 0x77, 0x2B, 0x34, 0x33, 0x75, 0x33, 0x67, 0x4A, 0x68, 0x4A, 0x36, 0x35, 0x62, 0x76, 0x73, ++ 0x70, 0x6D, 0x5A, 0x44, 0x6F, 0x67, 0x4E, 0x4F, 0x66, 0x4A, 0x41, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, ++ 0x0A, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, 0x69, 0x61, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, ++ 0x0A, 0x4D, 0x49, 0x49, 0x43, 0x4D, 0x54, 0x43, 0x43, 0x41, 0x62, 0x65, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x55, 0x4E, 0x6E, 0x54, 0x68, 0x54, 0x58, 0x78, 0x6C, 0x45, 0x38, 0x6D, 0x73, 0x67, 0x31, 0x55, 0x6C, 0x6F, 0x44, 0x35, ++ 0x53, 0x66, 0x69, 0x39, 0x51, 0x61, 0x4D, 0x63, 0x77, 0x43, 0x67, 0x59, 0x49, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x45, 0x41, 0x77, 0x4D, 0x77, 0x57, 0x44, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x0A, 0x42, 0x68, ++ 0x4D, 0x43, 0x51, 0x30, 0x34, 0x78, 0x4A, 0x54, 0x41, 0x6A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x48, 0x46, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x51, 0x58, 0x4E, 0x70, 0x59, 0x53, 0x42, 0x55, 0x5A, 0x57, 0x4E, 0x6F, 0x62, 0x6D, ++ 0x39, 0x73, 0x62, 0x32, 0x64, 0x70, 0x5A, 0x58, 0x4D, 0x73, 0x49, 0x45, 0x6C, 0x75, 0x59, 0x79, 0x34, 0x78, 0x49, 0x6A, 0x41, 0x67, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x47, 0x56, 0x52, 0x79, 0x0A, 0x64, 0x58, 0x4E, 0x30, 0x51, ++ 0x58, 0x4E, 0x70, 0x59, 0x53, 0x42, 0x55, 0x54, 0x46, 0x4D, 0x67, 0x52, 0x55, 0x4E, 0x44, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x6A, 0x51, 0x77, 0x4E, 0x54, 0x45, 0x31, 0x4D, ++ 0x44, 0x55, 0x30, 0x4D, 0x54, 0x55, 0x32, 0x57, 0x68, 0x63, 0x4E, 0x4E, 0x44, 0x51, 0x77, 0x4E, 0x54, 0x45, 0x31, 0x4D, 0x44, 0x55, 0x30, 0x4D, 0x54, 0x55, 0x31, 0x57, 0x6A, 0x42, 0x59, 0x0A, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, ++ 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x44, 0x54, 0x6A, 0x45, 0x6C, 0x4D, 0x43, 0x4D, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x63, 0x56, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x52, 0x42, 0x63, 0x32, 0x6C, 0x68, 0x49, 0x46, 0x52, 0x6C, ++ 0x59, 0x32, 0x68, 0x75, 0x62, 0x32, 0x78, 0x76, 0x5A, 0x32, 0x6C, 0x6C, 0x63, 0x79, 0x77, 0x67, 0x53, 0x57, 0x35, 0x6A, 0x4C, 0x6A, 0x45, 0x69, 0x4D, 0x43, 0x41, 0x47, 0x0A, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x5A, 0x56, 0x48, 0x4A, ++ 0x31, 0x63, 0x33, 0x52, 0x42, 0x63, 0x32, 0x6C, 0x68, 0x49, 0x46, 0x52, 0x4D, 0x55, 0x79, 0x42, 0x46, 0x51, 0x30, 0x4D, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x51, 0x54, 0x42, 0x32, 0x4D, 0x42, 0x41, 0x47, 0x42, 0x79, 0x71, ++ 0x47, 0x53, 0x4D, 0x34, 0x39, 0x41, 0x67, 0x45, 0x47, 0x42, 0x53, 0x75, 0x42, 0x42, 0x41, 0x41, 0x69, 0x41, 0x32, 0x49, 0x41, 0x42, 0x4C, 0x68, 0x2F, 0x0A, 0x70, 0x56, 0x73, 0x2F, 0x41, 0x54, 0x35, 0x39, 0x38, 0x49, 0x68, 0x74, 0x72, 0x69, ++ 0x6D, 0x59, 0x34, 0x5A, 0x74, 0x63, 0x55, 0x35, 0x6E, 0x62, 0x39, 0x77, 0x6A, 0x2F, 0x31, 0x57, 0x72, 0x67, 0x6A, 0x73, 0x74, 0x45, 0x70, 0x76, 0x44, 0x42, 0x6A, 0x4C, 0x31, 0x50, 0x31, 0x4D, 0x37, 0x55, 0x69, 0x46, 0x50, 0x6F, 0x58, 0x6C, ++ 0x66, 0x58, 0x54, 0x72, 0x34, 0x73, 0x50, 0x2F, 0x4D, 0x53, 0x70, 0x77, 0x44, 0x70, 0x67, 0x75, 0x4D, 0x71, 0x57, 0x7A, 0x4A, 0x38, 0x0A, 0x53, 0x35, 0x73, 0x55, 0x4B, 0x5A, 0x37, 0x34, 0x4C, 0x59, 0x4F, 0x31, 0x36, 0x34, 0x34, 0x78, 0x53, ++ 0x54, 0x30, 0x6D, 0x59, 0x65, 0x6B, 0x64, 0x63, 0x6F, 0x75, 0x4A, 0x74, 0x67, 0x71, 0x37, 0x6E, 0x44, 0x4D, 0x31, 0x44, 0x39, 0x72, 0x73, 0x33, 0x71, 0x6C, 0x4B, 0x48, 0x38, 0x6B, 0x7A, 0x73, 0x61, 0x4E, 0x43, 0x4D, 0x45, 0x41, 0x77, 0x44, ++ 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x0A, 0x2F, 0x7A, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x4C, 0x49, 0x56, 0x54, ++ 0x75, 0x37, 0x46, 0x44, 0x7A, 0x54, 0x4C, 0x71, 0x6E, 0x71, 0x4F, 0x48, 0x2F, 0x71, 0x4B, 0x59, 0x71, 0x4B, 0x61, 0x54, 0x36, 0x52, 0x41, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x51, 0x44, ++ 0x41, 0x67, 0x45, 0x47, 0x4D, 0x41, 0x6F, 0x47, 0x43, 0x43, 0x71, 0x47, 0x53, 0x4D, 0x34, 0x39, 0x0A, 0x42, 0x41, 0x4D, 0x44, 0x41, 0x32, 0x67, 0x41, 0x4D, 0x47, 0x55, 0x43, 0x4D, 0x46, 0x52, 0x48, 0x31, 0x38, 0x4D, 0x74, 0x59, 0x59, 0x5A, ++ 0x49, 0x39, 0x48, 0x6C, 0x61, 0x56, 0x51, 0x30, 0x31, 0x4C, 0x31, 0x38, 0x4E, 0x39, 0x6D, 0x64, 0x73, 0x64, 0x30, 0x41, 0x61, 0x52, 0x75, 0x66, 0x34, 0x61, 0x46, 0x74, 0x4F, 0x4A, 0x78, 0x32, 0x34, 0x6D, 0x48, 0x31, 0x2F, 0x6B, 0x37, 0x38, ++ 0x49, 0x54, 0x63, 0x54, 0x61, 0x52, 0x54, 0x43, 0x68, 0x44, 0x31, 0x35, 0x4B, 0x0A, 0x65, 0x41, 0x49, 0x78, 0x41, 0x4B, 0x4F, 0x52, 0x68, 0x2F, 0x49, 0x52, 0x4D, 0x34, 0x50, 0x44, 0x77, 0x59, 0x71, 0x52, 0x4F, 0x6B, 0x77, 0x72, 0x55, 0x4C, ++ 0x47, 0x39, 0x49, 0x70, 0x52, 0x64, 0x4E, 0x59, 0x6C, 0x7A, 0x67, 0x38, 0x57, 0x62, 0x47, 0x66, 0x36, 0x30, 0x6F, 0x65, 0x6E, 0x55, 0x6F, 0x57, 0x61, 0x32, 0x41, 0x61, 0x55, 0x32, 0x2B, 0x64, 0x68, 0x6F, 0x59, 0x53, 0x69, 0x33, 0x64, 0x4F, ++ 0x47, 0x69, 0x4D, 0x51, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, ++ 0x73, 0x69, 0x61, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x67, 0x44, ++ 0x43, 0x43, 0x41, 0x32, 0x69, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x55, 0x48, 0x42, 0x6A, 0x59, 0x7A, 0x2B, 0x56, 0x54, 0x50, 0x79, 0x49, 0x31, 0x52, 0x6C, 0x4E, 0x55, 0x4A, 0x44, 0x78, 0x73, 0x52, 0x39, 0x46, 0x63, 0x53, 0x70, ++ 0x77, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4D, 0x42, 0x51, 0x41, 0x77, 0x57, 0x44, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x0A, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x51, ++ 0x30, 0x34, 0x78, 0x4A, 0x54, 0x41, 0x6A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x48, 0x46, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x51, 0x58, 0x4E, 0x70, 0x59, 0x53, 0x42, 0x55, 0x5A, 0x57, 0x4E, 0x6F, 0x62, 0x6D, 0x39, 0x73, 0x62, ++ 0x32, 0x64, 0x70, 0x5A, 0x58, 0x4D, 0x73, 0x49, 0x45, 0x6C, 0x75, 0x59, 0x79, 0x34, 0x78, 0x49, 0x6A, 0x41, 0x67, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x0A, 0x47, 0x56, 0x52, 0x79, 0x64, 0x58, 0x4E, 0x30, 0x51, 0x58, 0x4E, 0x70, ++ 0x59, 0x53, 0x42, 0x55, 0x54, 0x46, 0x4D, 0x67, 0x55, 0x6C, 0x4E, 0x42, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x6A, 0x51, 0x77, 0x4E, 0x54, 0x45, 0x31, 0x4D, 0x44, 0x55, 0x30, ++ 0x4D, 0x54, 0x55, 0x33, 0x57, 0x68, 0x63, 0x4E, 0x4E, 0x44, 0x51, 0x77, 0x4E, 0x54, 0x45, 0x31, 0x4D, 0x44, 0x55, 0x30, 0x4D, 0x54, 0x55, 0x32, 0x0A, 0x57, 0x6A, 0x42, 0x59, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, ++ 0x47, 0x45, 0x77, 0x4A, 0x44, 0x54, 0x6A, 0x45, 0x6C, 0x4D, 0x43, 0x4D, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x63, 0x56, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x52, 0x42, 0x63, 0x32, 0x6C, 0x68, 0x49, 0x46, 0x52, 0x6C, 0x59, 0x32, 0x68, ++ 0x75, 0x62, 0x32, 0x78, 0x76, 0x5A, 0x32, 0x6C, 0x6C, 0x63, 0x79, 0x77, 0x67, 0x53, 0x57, 0x35, 0x6A, 0x4C, 0x6A, 0x45, 0x69, 0x0A, 0x4D, 0x43, 0x41, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x5A, 0x56, 0x48, 0x4A, 0x31, 0x63, 0x33, ++ 0x52, 0x42, 0x63, 0x32, 0x6C, 0x68, 0x49, 0x46, 0x52, 0x4D, 0x55, 0x79, 0x42, 0x53, 0x55, 0x30, 0x45, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x51, 0x54, 0x43, 0x43, 0x41, 0x69, 0x49, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, ++ 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x50, 0x0A, 0x41, 0x44, 0x43, 0x43, 0x41, 0x67, 0x6F, 0x43, 0x67, 0x67, 0x49, 0x42, 0x41, 0x4D, 0x4D, 0x57, 0x75, 0x42, 0x74, 0x71, 0x70, ++ 0x45, 0x52, 0x7A, 0x35, 0x64, 0x5A, 0x4F, 0x39, 0x4C, 0x6E, 0x50, 0x57, 0x77, 0x76, 0x42, 0x30, 0x5A, 0x71, 0x42, 0x39, 0x57, 0x4F, 0x77, 0x6A, 0x30, 0x50, 0x42, 0x75, 0x77, 0x68, 0x61, 0x47, 0x6E, 0x72, 0x68, 0x42, 0x33, 0x59, 0x6D, 0x48, ++ 0x34, 0x39, 0x70, 0x56, 0x72, 0x37, 0x2B, 0x4E, 0x6D, 0x44, 0x51, 0x44, 0x49, 0x50, 0x4E, 0x0A, 0x6C, 0x4F, 0x72, 0x6E, 0x78, 0x53, 0x31, 0x63, 0x4C, 0x77, 0x55, 0x57, 0x41, 0x70, 0x34, 0x4B, 0x71, 0x43, 0x2F, 0x6C, 0x59, 0x43, 0x5A, 0x55, ++ 0x6C, 0x76, 0x69, 0x59, 0x51, 0x42, 0x32, 0x73, 0x72, 0x70, 0x31, 0x30, 0x5A, 0x79, 0x39, 0x55, 0x2B, 0x35, 0x52, 0x6A, 0x6D, 0x4F, 0x4D, 0x6D, 0x53, 0x6F, 0x50, 0x47, 0x6C, 0x62, 0x59, 0x4A, 0x51, 0x31, 0x44, 0x4E, 0x44, 0x58, 0x33, 0x65, ++ 0x52, 0x41, 0x35, 0x67, 0x45, 0x6B, 0x39, 0x62, 0x4E, 0x62, 0x32, 0x2F, 0x0A, 0x6D, 0x54, 0x68, 0x74, 0x66, 0x57, 0x7A, 0x61, 0x34, 0x6D, 0x68, 0x7A, 0x48, 0x2F, 0x6B, 0x78, 0x70, 0x52, 0x6B, 0x51, 0x63, 0x77, 0x55, 0x71, 0x77, 0x7A, 0x49, ++ 0x5A, 0x68, 0x65, 0x6F, 0x30, 0x71, 0x74, 0x31, 0x43, 0x48, 0x6A, 0x43, 0x4E, 0x50, 0x35, 0x36, 0x31, 0x48, 0x6D, 0x48, 0x56, 0x62, 0x37, 0x30, 0x41, 0x63, 0x6E, 0x4B, 0x74, 0x45, 0x6A, 0x2B, 0x71, 0x70, 0x6B, 0x6C, 0x7A, 0x38, 0x6F, 0x59, ++ 0x56, 0x6C, 0x51, 0x77, 0x51, 0x58, 0x31, 0x46, 0x6B, 0x0A, 0x7A, 0x76, 0x39, 0x33, 0x75, 0x4D, 0x6C, 0x74, 0x72, 0x4F, 0x58, 0x56, 0x6D, 0x50, 0x47, 0x5A, 0x4C, 0x6D, 0x7A, 0x6A, 0x79, 0x55, 0x54, 0x35, 0x74, 0x55, 0x4D, 0x6E, 0x43, 0x45, ++ 0x33, 0x32, 0x66, 0x74, 0x35, 0x45, 0x65, 0x62, 0x75, 0x79, 0x6A, 0x42, 0x7A, 0x61, 0x30, 0x30, 0x74, 0x73, 0x4C, 0x74, 0x62, 0x44, 0x65, 0x4C, 0x64, 0x4D, 0x31, 0x61, 0x54, 0x6B, 0x32, 0x74, 0x79, 0x4B, 0x6A, 0x67, 0x37, 0x2F, 0x44, 0x38, ++ 0x4F, 0x6D, 0x59, 0x43, 0x59, 0x6F, 0x0A, 0x7A, 0x7A, 0x61, 0x2F, 0x2B, 0x6C, 0x63, 0x4B, 0x37, 0x46, 0x73, 0x2F, 0x36, 0x54, 0x41, 0x57, 0x65, 0x38, 0x54, 0x62, 0x78, 0x4E, 0x52, 0x6B, 0x6F, 0x44, 0x44, 0x37, 0x35, 0x66, 0x30, 0x64, 0x63, ++ 0x5A, 0x4C, 0x64, 0x4B, 0x59, 0x39, 0x42, 0x57, 0x4E, 0x34, 0x41, 0x72, 0x54, 0x72, 0x39, 0x50, 0x58, 0x77, 0x61, 0x71, 0x4C, 0x45, 0x58, 0x38, 0x45, 0x34, 0x30, 0x65, 0x46, 0x67, 0x6C, 0x31, 0x6F, 0x55, 0x68, 0x36, 0x33, 0x6B, 0x64, 0x30, ++ 0x4E, 0x79, 0x72, 0x0A, 0x7A, 0x32, 0x49, 0x38, 0x73, 0x4D, 0x65, 0x58, 0x69, 0x39, 0x62, 0x51, 0x6E, 0x39, 0x50, 0x2B, 0x50, 0x4E, 0x37, 0x46, 0x34, 0x2F, 0x77, 0x36, 0x67, 0x33, 0x43, 0x45, 0x49, 0x52, 0x30, 0x4A, 0x77, 0x71, 0x48, 0x38, ++ 0x75, 0x79, 0x67, 0x68, 0x5A, 0x56, 0x4E, 0x67, 0x65, 0x70, 0x42, 0x74, 0x6C, 0x6A, 0x68, 0x62, 0x2F, 0x2F, 0x48, 0x58, 0x65, 0x6C, 0x74, 0x74, 0x30, 0x38, 0x6C, 0x77, 0x53, 0x55, 0x71, 0x36, 0x48, 0x54, 0x72, 0x51, 0x55, 0x4E, 0x6F, 0x79, ++ 0x0A, 0x49, 0x42, 0x6E, 0x6B, 0x69, 0x7A, 0x2F, 0x72, 0x31, 0x52, 0x59, 0x6D, 0x4E, 0x7A, 0x7A, 0x37, 0x64, 0x5A, 0x36, 0x77, 0x42, 0x33, 0x43, 0x34, 0x46, 0x47, 0x42, 0x33, 0x33, 0x50, 0x59, 0x50, 0x58, 0x46, 0x49, 0x4B, 0x76, 0x46, 0x31, ++ 0x74, 0x6A, 0x56, 0x45, 0x4B, 0x32, 0x73, 0x55, 0x59, 0x79, 0x4A, 0x74, 0x74, 0x33, 0x4C, 0x43, 0x44, 0x73, 0x33, 0x2B, 0x6A, 0x54, 0x6E, 0x68, 0x4D, 0x6D, 0x43, 0x57, 0x72, 0x38, 0x6E, 0x34, 0x75, 0x49, 0x46, 0x36, 0x43, 0x0A, 0x46, 0x61, ++ 0x62, 0x57, 0x32, 0x49, 0x2B, 0x73, 0x35, 0x63, 0x30, 0x79, 0x68, 0x73, 0x6A, 0x35, 0x35, 0x4E, 0x71, 0x4A, 0x34, 0x6A, 0x73, 0x2B, 0x6B, 0x38, 0x55, 0x54, 0x61, 0x76, 0x2F, 0x48, 0x39, 0x78, 0x6A, 0x38, 0x5A, 0x37, 0x58, 0x76, 0x47, 0x43, ++ 0x78, 0x55, 0x71, 0x30, 0x44, 0x54, 0x62, 0x45, 0x33, 0x74, 0x78, 0x63, 0x69, 0x33, 0x4F, 0x45, 0x39, 0x6B, 0x78, 0x4A, 0x52, 0x4D, 0x54, 0x36, 0x44, 0x4E, 0x72, 0x71, 0x58, 0x47, 0x4A, 0x79, 0x56, 0x31, 0x0A, 0x4A, 0x32, 0x33, 0x47, 0x32, ++ 0x70, 0x79, 0x4F, 0x73, 0x41, 0x57, 0x5A, 0x31, 0x53, 0x67, 0x52, 0x78, 0x53, 0x48, 0x55, 0x75, 0x50, 0x7A, 0x48, 0x6C, 0x71, 0x74, 0x4B, 0x5A, 0x46, 0x6C, 0x68, 0x61, 0x78, 0x50, 0x38, 0x53, 0x38, 0x79, 0x53, 0x70, 0x67, 0x2B, 0x6B, 0x55, ++ 0x62, 0x38, 0x4F, 0x57, 0x4A, 0x44, 0x5A, 0x67, 0x6F, 0x4D, 0x35, 0x70, 0x6C, 0x2B, 0x7A, 0x2B, 0x6D, 0x36, 0x53, 0x73, 0x38, 0x30, 0x7A, 0x44, 0x6F, 0x57, 0x6F, 0x38, 0x53, 0x6E, 0x54, 0x0A, 0x71, 0x31, 0x6D, 0x74, 0x31, 0x74, 0x76, 0x65, ++ 0x31, 0x43, 0x75, 0x42, 0x41, 0x67, 0x4D, 0x42, 0x41, 0x41, 0x47, 0x6A, 0x51, 0x6A, 0x42, 0x41, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, ++ 0x48, 0x51, 0x59, 0x44, 0x56, 0x52, 0x30, 0x4F, 0x42, 0x42, 0x59, 0x45, 0x46, 0x4C, 0x67, 0x48, 0x6B, 0x58, 0x6C, 0x63, 0x42, 0x76, 0x52, 0x47, 0x2F, 0x58, 0x74, 0x5A, 0x0A, 0x79, 0x6C, 0x6F, 0x6D, 0x6B, 0x61, 0x64, 0x46, 0x4B, 0x2F, 0x68, ++ 0x54, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x42, 0x42, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x77, ++ 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x67, 0x45, 0x41, 0x49, 0x5A, 0x74, 0x71, 0x42, 0x53, 0x42, 0x64, 0x47, 0x42, 0x61, 0x6E, 0x45, 0x71, 0x54, 0x33, 0x0A, 0x52, 0x7A, 0x2F, 0x4E, 0x79, 0x6A, 0x75, 0x75, 0x6A, 0x73, 0x43, 0x43, 0x7A, 0x74, ++ 0x78, 0x49, 0x4A, 0x58, 0x67, 0x58, 0x62, 0x4F, 0x44, 0x67, 0x63, 0x4D, 0x54, 0x57, 0x6C, 0x74, 0x6E, 0x5A, 0x39, 0x72, 0x39, 0x36, 0x6E, 0x42, 0x4F, 0x37, 0x55, 0x35, 0x57, 0x53, 0x2F, 0x38, 0x2B, 0x53, 0x34, 0x50, 0x50, 0x46, 0x4A, 0x7A, ++ 0x56, 0x58, 0x71, 0x44, 0x75, 0x69, 0x47, 0x65, 0x76, 0x34, 0x69, 0x71, 0x4D, 0x45, 0x33, 0x6D, 0x6D, 0x4C, 0x35, 0x44, 0x77, 0x38, 0x0A, 0x76, 0x65, 0x57, 0x76, 0x30, 0x42, 0x49, 0x62, 0x35, 0x59, 0x6C, 0x72, 0x63, 0x35, 0x74, 0x76, 0x4A, ++ 0x51, 0x4A, 0x4C, 0x6B, 0x49, 0x4B, 0x76, 0x51, 0x4D, 0x4B, 0x74, 0x75, 0x70, 0x70, 0x67, 0x4A, 0x46, 0x71, 0x42, 0x54, 0x51, 0x55, 0x59, 0x6F, 0x2B, 0x49, 0x7A, 0x65, 0x58, 0x6F, 0x4C, 0x48, 0x35, 0x50, 0x74, 0x37, 0x44, 0x6C, 0x4B, 0x39, ++ 0x52, 0x4D, 0x45, 0x37, 0x49, 0x31, 0x30, 0x6E, 0x59, 0x45, 0x4B, 0x71, 0x47, 0x2F, 0x6F, 0x64, 0x76, 0x36, 0x4C, 0x0A, 0x54, 0x79, 0x74, 0x70, 0x45, 0x6F, 0x59, 0x4B, 0x4E, 0x44, 0x62, 0x64, 0x67, 0x70, 0x74, 0x76, 0x54, 0x2B, 0x42, 0x7A, ++ 0x33, 0x55, 0x6C, 0x2F, 0x4B, 0x44, 0x37, 0x4A, 0x4F, 0x36, 0x4E, 0x58, 0x42, 0x4E, 0x69, 0x54, 0x32, 0x54, 0x77, 0x70, 0x32, 0x78, 0x49, 0x51, 0x61, 0x4F, 0x48, 0x45, 0x69, 0x62, 0x67, 0x47, 0x49, 0x4F, 0x63, 0x62, 0x65, 0x72, 0x79, 0x78, ++ 0x6B, 0x32, 0x47, 0x61, 0x47, 0x55, 0x41, 0x52, 0x74, 0x57, 0x71, 0x46, 0x56, 0x77, 0x48, 0x78, 0x0A, 0x74, 0x6C, 0x6F, 0x74, 0x4A, 0x6E, 0x4D, 0x6E, 0x6C, 0x76, 0x6D, 0x35, 0x50, 0x31, 0x76, 0x51, 0x69, 0x4A, 0x33, 0x6B, 0x6F, 0x50, 0x32, ++ 0x36, 0x54, 0x70, 0x55, 0x4A, 0x67, 0x33, 0x39, 0x33, 0x33, 0x46, 0x45, 0x46, 0x6C, 0x4A, 0x30, 0x67, 0x63, 0x58, 0x61, 0x78, 0x37, 0x50, 0x71, 0x4A, 0x74, 0x5A, 0x77, 0x75, 0x68, 0x66, 0x47, 0x35, 0x57, 0x79, 0x52, 0x61, 0x73, 0x51, 0x6D, ++ 0x72, 0x32, 0x73, 0x6F, 0x61, 0x42, 0x38, 0x32, 0x47, 0x33, 0x39, 0x74, 0x70, 0x0A, 0x32, 0x37, 0x52, 0x49, 0x47, 0x41, 0x41, 0x74, 0x76, 0x4B, 0x4C, 0x45, 0x69, 0x55, 0x55, 0x6A, 0x70, 0x51, 0x37, 0x68, 0x52, 0x47, 0x55, 0x2B, 0x69, 0x73, ++ 0x46, 0x71, 0x4D, 0x42, 0x33, 0x69, 0x59, 0x50, 0x67, 0x36, 0x71, 0x6F, 0x63, 0x4A, 0x51, 0x72, 0x6D, 0x42, 0x6B, 0x74, 0x77, 0x6C, 0x69, 0x4A, 0x69, 0x4A, 0x38, 0x58, 0x77, 0x31, 0x38, 0x57, 0x4C, 0x4B, 0x37, 0x6E, 0x6E, 0x34, 0x47, 0x53, ++ 0x2F, 0x2B, 0x58, 0x2F, 0x6A, 0x62, 0x68, 0x38, 0x37, 0x71, 0x0A, 0x71, 0x41, 0x38, 0x4D, 0x70, 0x75, 0x67, 0x4C, 0x6F, 0x44, 0x7A, 0x67, 0x61, 0x35, 0x53, 0x59, 0x6E, 0x48, 0x2B, 0x74, 0x42, 0x75, 0x59, 0x63, 0x36, 0x6B, 0x49, 0x51, 0x58, ++ 0x2B, 0x49, 0x6D, 0x46, 0x54, 0x77, 0x33, 0x4F, 0x66, 0x66, 0x58, 0x76, 0x4F, 0x36, 0x34, 0x35, 0x65, 0x38, 0x44, 0x37, 0x72, 0x30, 0x69, 0x2B, 0x79, 0x69, 0x47, 0x4E, 0x46, 0x6A, 0x45, 0x57, 0x6E, 0x39, 0x68, 0x6F, 0x6E, 0x67, 0x50, 0x58, ++ 0x76, 0x50, 0x4B, 0x6E, 0x62, 0x77, 0x62, 0x0A, 0x50, 0x4B, 0x66, 0x49, 0x4C, 0x66, 0x61, 0x6E, 0x49, 0x68, 0x48, 0x4B, 0x41, 0x39, 0x6A, 0x6E, 0x5A, 0x77, 0x71, 0x4B, 0x44, 0x73, 0x73, 0x31, 0x6A, 0x6A, 0x51, 0x35, 0x32, 0x4D, 0x6A, 0x71, ++ 0x6A, 0x5A, 0x39, 0x6B, 0x34, 0x44, 0x65, 0x77, 0x62, 0x4E, 0x66, 0x46, 0x6A, 0x38, 0x47, 0x51, 0x59, 0x53, 0x62, 0x62, 0x4A, 0x49, 0x77, 0x65, 0x53, 0x73, 0x43, 0x49, 0x33, 0x7A, 0x57, 0x51, 0x7A, 0x6A, 0x38, 0x43, 0x39, 0x47, 0x52, 0x68, ++ 0x33, 0x73, 0x66, 0x49, 0x0A, 0x42, 0x35, 0x58, 0x65, 0x4D, 0x68, 0x67, 0x36, 0x6A, 0x36, 0x4A, 0x43, 0x51, 0x43, 0x54, 0x6C, 0x31, 0x6A, 0x4E, 0x64, 0x66, 0x4B, 0x37, 0x76, 0x73, 0x55, 0x31, 0x50, 0x31, 0x46, 0x65, 0x51, 0x4E, 0x57, 0x72, ++ 0x63, 0x72, 0x67, 0x53, 0x58, 0x53, 0x59, 0x6B, 0x30, 0x6C, 0x79, 0x34, 0x77, 0x42, 0x4F, 0x65, 0x59, 0x39, 0x39, 0x73, 0x4C, 0x41, 0x5A, 0x44, 0x42, 0x48, 0x77, 0x6F, 0x2F, 0x2B, 0x4D, 0x4C, 0x2B, 0x54, 0x76, 0x72, 0x62, 0x6D, 0x6E, 0x4E, ++ 0x7A, 0x0A, 0x46, 0x72, 0x77, 0x46, 0x75, 0x48, 0x6E, 0x59, 0x57, 0x61, 0x38, 0x47, 0x35, 0x7A, 0x39, 0x6E, 0x4F, 0x44, 0x6D, 0x78, 0x66, 0x4B, 0x75, 0x55, 0x34, 0x43, 0x6B, 0x55, 0x70, 0x69, 0x6A, 0x79, 0x33, 0x32, 0x33, 0x69, 0x6D, 0x74, ++ 0x74, 0x55, 0x51, 0x2F, 0x68, 0x48, 0x57, 0x4B, 0x4E, 0x64, 0x64, 0x42, 0x57, 0x63, 0x77, 0x61, 0x75, 0x77, 0x78, 0x7A, 0x51, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, ++ 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x45, 0x56, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, 0x32, 0x30, 0x32, 0x33, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, ++ 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x71, 0x54, 0x43, 0x43, 0x41, 0x35, 0x47, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x61, 0x53, 0x59, 0x4A, 0x66, 0x6F, 0x42, 0x4C, 0x54, 0x4B, ++ 0x43, 0x6E, 0x6A, 0x48, 0x68, 0x69, 0x55, 0x31, 0x39, 0x61, 0x62, 0x7A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x30, 0x46, 0x41, 0x44, 0x42, 0x49, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, ++ 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x0A, 0x45, 0x77, 0x4A, 0x45, 0x52, 0x54, 0x45, 0x56, 0x4D, 0x42, 0x4D, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4D, 0x4D, 0x52, 0x43, 0x31, 0x55, 0x63, 0x6E, 0x56, 0x7A, 0x64, 0x43, 0x42, 0x48, 0x62, ++ 0x57, 0x4A, 0x49, 0x4D, 0x53, 0x49, 0x77, 0x49, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x78, 0x6C, 0x45, 0x4C, 0x56, 0x52, 0x53, 0x56, 0x56, 0x4E, 0x55, 0x49, 0x45, 0x56, 0x57, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, ++ 0x30, 0x45, 0x67, 0x0A, 0x4D, 0x69, 0x41, 0x79, 0x4D, 0x44, 0x49, 0x7A, 0x4D, 0x42, 0x34, 0x58, 0x44, 0x54, 0x49, 0x7A, 0x4D, 0x44, 0x55, 0x77, 0x4F, 0x54, 0x41, 0x35, 0x4D, 0x54, 0x41, 0x7A, 0x4D, 0x31, 0x6F, 0x58, 0x44, 0x54, 0x4D, 0x34, ++ 0x4D, 0x44, 0x55, 0x77, 0x4F, 0x54, 0x41, 0x35, 0x4D, 0x54, 0x41, 0x7A, 0x4D, 0x6C, 0x6F, 0x77, 0x53, 0x44, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x52, 0x45, 0x55, 0x78, 0x46, 0x54, 0x41, 0x54, ++ 0x0A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x54, 0x44, 0x45, 0x51, 0x74, 0x56, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x51, 0x67, 0x52, 0x32, 0x31, 0x69, 0x53, 0x44, 0x45, 0x69, 0x4D, 0x43, 0x41, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, ++ 0x5A, 0x52, 0x43, 0x31, 0x55, 0x55, 0x6C, 0x56, 0x54, 0x56, 0x43, 0x42, 0x46, 0x56, 0x69, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, 0x45, 0x4E, 0x42, 0x49, 0x44, 0x49, 0x67, 0x4D, 0x6A, 0x41, 0x79, 0x4D, 0x7A, 0x43, 0x43, 0x0A, 0x41, 0x69, ++ 0x49, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x50, 0x41, 0x44, 0x43, 0x43, 0x41, 0x67, 0x6F, 0x43, 0x67, 0x67, 0x49, 0x42, 0x41, 0x4E, ++ 0x69, 0x4F, 0x6F, 0x34, 0x6D, 0x41, 0x43, 0x37, 0x4A, 0x58, 0x55, 0x74, 0x79, 0x70, 0x55, 0x30, 0x77, 0x33, 0x75, 0x58, 0x39, 0x6A, 0x46, 0x78, 0x50, 0x76, 0x70, 0x31, 0x73, 0x6A, 0x57, 0x32, 0x6C, 0x31, 0x0A, 0x73, 0x4A, 0x6B, 0x4B, 0x46, ++ 0x38, 0x47, 0x4C, 0x78, 0x4E, 0x75, 0x6F, 0x34, 0x4D, 0x77, 0x78, 0x75, 0x73, 0x4C, 0x79, 0x7A, 0x56, 0x33, 0x70, 0x74, 0x2F, 0x67, 0x64, 0x72, 0x32, 0x72, 0x45, 0x6C, 0x59, 0x66, 0x58, 0x52, 0x38, 0x6D, 0x56, 0x32, 0x49, 0x49, 0x45, 0x55, ++ 0x44, 0x32, 0x42, 0x43, 0x50, 0x2F, 0x6B, 0x50, 0x62, 0x4F, 0x78, 0x31, 0x73, 0x57, 0x79, 0x2F, 0x59, 0x67, 0x4A, 0x32, 0x35, 0x79, 0x45, 0x37, 0x43, 0x55, 0x58, 0x46, 0x49, 0x64, 0x2F, 0x0A, 0x4D, 0x48, 0x69, 0x62, 0x61, 0x6C, 0x6A, 0x4A, ++ 0x74, 0x6E, 0x4D, 0x6F, 0x50, 0x44, 0x54, 0x33, 0x6D, 0x66, 0x64, 0x2F, 0x30, 0x36, 0x62, 0x34, 0x48, 0x45, 0x56, 0x38, 0x72, 0x53, 0x79, 0x4D, 0x6C, 0x44, 0x2F, 0x59, 0x5A, 0x78, 0x42, 0x54, 0x66, 0x69, 0x4C, 0x4E, 0x54, 0x69, 0x56, 0x52, ++ 0x38, 0x43, 0x55, 0x6B, 0x4E, 0x52, 0x46, 0x65, 0x45, 0x4D, 0x62, 0x73, 0x68, 0x32, 0x61, 0x4A, 0x67, 0x57, 0x69, 0x36, 0x7A, 0x43, 0x75, 0x64, 0x52, 0x33, 0x4D, 0x66, 0x0A, 0x76, 0x63, 0x32, 0x52, 0x70, 0x48, 0x4A, 0x71, 0x6E, 0x4B, 0x49, ++ 0x62, 0x47, 0x4B, 0x42, 0x76, 0x37, 0x46, 0x44, 0x30, 0x66, 0x55, 0x44, 0x43, 0x71, 0x44, 0x44, 0x50, 0x76, 0x58, 0x50, 0x49, 0x45, 0x79, 0x73, 0x51, 0x45, 0x78, 0x36, 0x4C, 0x6D, 0x71, 0x67, 0x36, 0x6C, 0x48, 0x50, 0x54, 0x47, 0x47, 0x6B, ++ 0x4B, 0x53, 0x76, 0x2F, 0x42, 0x41, 0x51, 0x50, 0x2F, 0x65, 0x58, 0x2B, 0x31, 0x53, 0x48, 0x39, 0x37, 0x37, 0x75, 0x67, 0x70, 0x62, 0x7A, 0x5A, 0x4D, 0x0A, 0x6C, 0x57, 0x47, 0x47, 0x32, 0x50, 0x6D, 0x69, 0x63, 0x34, 0x72, 0x75, 0x72, 0x69, ++ 0x2B, 0x57, 0x37, 0x6D, 0x6A, 0x4E, 0x50, 0x55, 0x30, 0x6F, 0x51, 0x76, 0x6C, 0x46, 0x4B, 0x7A, 0x49, 0x62, 0x52, 0x6C, 0x55, 0x57, 0x61, 0x71, 0x5A, 0x4C, 0x4B, 0x66, 0x6D, 0x37, 0x6C, 0x56, 0x61, 0x2F, 0x52, 0x68, 0x33, 0x73, 0x48, 0x5A, ++ 0x4D, 0x64, 0x77, 0x47, 0x57, 0x79, 0x48, 0x36, 0x46, 0x44, 0x72, 0x6C, 0x61, 0x65, 0x6F, 0x4C, 0x47, 0x50, 0x61, 0x78, 0x4B, 0x33, 0x0A, 0x59, 0x47, 0x31, 0x34, 0x43, 0x38, 0x71, 0x4B, 0x58, 0x4F, 0x30, 0x65, 0x6C, 0x67, 0x36, 0x44, 0x70, ++ 0x6B, 0x69, 0x56, 0x6A, 0x54, 0x75, 0x6A, 0x49, 0x63, 0x53, 0x75, 0x57, 0x4D, 0x59, 0x41, 0x73, 0x6F, 0x53, 0x30, 0x49, 0x36, 0x53, 0x57, 0x68, 0x6A, 0x57, 0x34, 0x32, 0x4A, 0x37, 0x59, 0x72, 0x44, 0x52, 0x4A, 0x6D, 0x47, 0x4F, 0x56, 0x78, ++ 0x63, 0x74, 0x74, 0x53, 0x45, 0x66, 0x69, 0x38, 0x69, 0x34, 0x59, 0x48, 0x74, 0x41, 0x78, 0x71, 0x39, 0x31, 0x30, 0x0A, 0x37, 0x50, 0x6E, 0x63, 0x6A, 0x4C, 0x67, 0x63, 0x6A, 0x6D, 0x67, 0x6A, 0x75, 0x74, 0x44, 0x7A, 0x55, 0x4E, 0x7A, 0x50, ++ 0x5A, 0x59, 0x39, 0x7A, 0x4F, 0x6A, 0x4C, 0x48, 0x66, 0x50, 0x37, 0x4B, 0x67, 0x69, 0x4A, 0x50, 0x76, 0x6F, 0x35, 0x69, 0x52, 0x32, 0x62, 0x6C, 0x7A, 0x59, 0x66, 0x69, 0x36, 0x4E, 0x55, 0x50, 0x47, 0x4A, 0x2F, 0x6C, 0x42, 0x48, 0x4A, 0x4C, ++ 0x52, 0x6A, 0x77, 0x51, 0x38, 0x6B, 0x54, 0x43, 0x5A, 0x46, 0x5A, 0x78, 0x54, 0x6E, 0x58, 0x6F, 0x0A, 0x6E, 0x4D, 0x6B, 0x6D, 0x64, 0x4D, 0x56, 0x39, 0x57, 0x64, 0x45, 0x4B, 0x57, 0x77, 0x39, 0x74, 0x2F, 0x70, 0x35, 0x31, 0x48, 0x42, 0x6A, ++ 0x47, 0x47, 0x6A, 0x70, 0x38, 0x32, 0x41, 0x30, 0x45, 0x7A, 0x4D, 0x32, 0x33, 0x52, 0x57, 0x56, 0x36, 0x73, 0x59, 0x2B, 0x34, 0x72, 0x6F, 0x52, 0x49, 0x50, 0x72, 0x4E, 0x36, 0x54, 0x61, 0x67, 0x44, 0x34, 0x75, 0x4A, 0x2B, 0x41, 0x52, 0x5A, ++ 0x5A, 0x61, 0x42, 0x68, 0x44, 0x4D, 0x37, 0x44, 0x53, 0x33, 0x4C, 0x41, 0x61, 0x0A, 0x51, 0x7A, 0x58, 0x75, 0x70, 0x64, 0x71, 0x70, 0x52, 0x6C, 0x79, 0x75, 0x68, 0x6F, 0x46, 0x42, 0x41, 0x55, 0x70, 0x30, 0x4A, 0x75, 0x79, 0x66, 0x42, 0x72, ++ 0x2F, 0x43, 0x42, 0x54, 0x64, 0x6B, 0x64, 0x58, 0x67, 0x70, 0x61, 0x50, 0x33, 0x46, 0x39, 0x65, 0x76, 0x2B, 0x52, 0x2F, 0x6E, 0x6B, 0x68, 0x62, 0x44, 0x68, 0x65, 0x7A, 0x47, 0x64, 0x70, 0x6E, 0x39, 0x79, 0x6F, 0x37, 0x6E, 0x45, 0x4C, 0x43, ++ 0x37, 0x4D, 0x6D, 0x56, 0x63, 0x4F, 0x49, 0x51, 0x78, 0x46, 0x0A, 0x41, 0x5A, 0x52, 0x6C, 0x36, 0x32, 0x55, 0x4A, 0x78, 0x6D, 0x4D, 0x69, 0x43, 0x7A, 0x4E, 0x4A, 0x6B, 0x6B, 0x67, 0x38, 0x2F, 0x4D, 0x33, 0x4F, 0x73, 0x44, 0x36, 0x4F, 0x6E, ++ 0x6F, 0x76, 0x34, 0x2F, 0x6B, 0x6E, 0x46, 0x4E, 0x58, 0x4A, 0x48, 0x41, 0x67, 0x4D, 0x42, 0x41, 0x41, 0x47, 0x6A, 0x67, 0x59, 0x34, 0x77, 0x67, 0x59, 0x73, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, ++ 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x0A, 0x2F, 0x7A, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x71, 0x76, 0x79, 0x52, 0x45, 0x42, 0x75, 0x48, 0x6B, 0x56, 0x38, 0x57, 0x75, 0x62, 0x39, 0x50, ++ 0x53, 0x35, 0x46, 0x65, 0x41, 0x42, 0x79, 0x78, 0x4D, 0x6F, 0x41, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x51, 0x44, 0x41, 0x67, 0x45, 0x47, 0x4D, 0x45, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x64, ++ 0x48, 0x77, 0x52, 0x43, 0x0A, 0x4D, 0x45, 0x41, 0x77, 0x50, 0x71, 0x41, 0x38, 0x6F, 0x44, 0x71, 0x47, 0x4F, 0x47, 0x68, 0x30, 0x64, 0x48, 0x41, 0x36, 0x4C, 0x79, 0x39, 0x6A, 0x63, 0x6D, 0x77, 0x75, 0x5A, 0x43, 0x31, 0x30, 0x63, 0x6E, 0x56, ++ 0x7A, 0x64, 0x43, 0x35, 0x75, 0x5A, 0x58, 0x51, 0x76, 0x59, 0x33, 0x4A, 0x73, 0x4C, 0x32, 0x51, 0x74, 0x64, 0x48, 0x4A, 0x31, 0x63, 0x33, 0x52, 0x66, 0x5A, 0x58, 0x5A, 0x66, 0x63, 0x6D, 0x39, 0x76, 0x64, 0x46, 0x39, 0x6A, 0x59, 0x56, 0x38, ++ 0x79, 0x0A, 0x58, 0x7A, 0x49, 0x77, 0x4D, 0x6A, 0x4D, 0x75, 0x59, 0x33, 0x4A, 0x73, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x44, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x41, 0x51, ++ 0x43, 0x54, 0x79, 0x36, 0x55, 0x66, 0x6D, 0x52, 0x48, 0x73, 0x6D, 0x67, 0x31, 0x66, 0x4C, 0x42, 0x57, 0x54, 0x78, 0x6A, 0x2B, 0x2B, 0x45, 0x49, 0x31, 0x34, 0x51, 0x76, 0x42, 0x75, 0x6B, 0x45, 0x64, 0x48, 0x6A, 0x71, 0x4F, 0x53, 0x0A, 0x4D, ++ 0x6F, 0x31, 0x77, 0x6A, 0x2F, 0x5A, 0x62, 0x6A, 0x62, 0x36, 0x4A, 0x7A, 0x6B, 0x63, 0x42, 0x61, 0x68, 0x73, 0x67, 0x49, 0x49, 0x6C, 0x62, 0x79, 0x49, 0x49, 0x51, 0x62, 0x4F, 0x44, 0x6E, 0x6D, 0x61, 0x70, 0x72, 0x78, 0x69, 0x71, 0x67, 0x59, ++ 0x7A, 0x57, 0x52, 0x61, 0x6F, 0x55, 0x6C, 0x72, 0x52, 0x63, 0x34, 0x70, 0x5A, 0x74, 0x2B, 0x55, 0x50, 0x4A, 0x32, 0x36, 0x6F, 0x55, 0x46, 0x4B, 0x69, 0x64, 0x42, 0x4B, 0x37, 0x47, 0x42, 0x30, 0x61, 0x4C, 0x32, 0x0A, 0x51, 0x48, 0x57, 0x70, ++ 0x44, 0x73, 0x76, 0x78, 0x56, 0x55, 0x6A, 0x59, 0x37, 0x4E, 0x48, 0x73, 0x73, 0x2B, 0x6A, 0x4F, 0x46, 0x4B, 0x45, 0x31, 0x37, 0x4D, 0x4A, 0x65, 0x4E, 0x52, 0x71, 0x72, 0x70, 0x68, 0x59, 0x42, 0x42, 0x6F, 0x37, 0x71, 0x33, 0x43, 0x2B, 0x6A, ++ 0x69, 0x73, 0x6F, 0x73, 0x6B, 0x65, 0x74, 0x53, 0x6A, 0x6C, 0x38, 0x4D, 0x6D, 0x78, 0x66, 0x50, 0x79, 0x33, 0x4D, 0x48, 0x47, 0x63, 0x52, 0x71, 0x77, 0x6E, 0x4E, 0x55, 0x37, 0x33, 0x78, 0x44, 0x0A, 0x55, 0x6D, 0x50, 0x42, 0x45, 0x63, 0x72, ++ 0x43, 0x52, 0x62, 0x48, 0x30, 0x4F, 0x31, 0x50, 0x31, 0x61, 0x61, 0x34, 0x38, 0x34, 0x36, 0x58, 0x65, 0x72, 0x4F, 0x68, 0x55, 0x74, 0x37, 0x4B, 0x52, 0x2F, 0x61, 0x79, 0x70, 0x48, 0x2F, 0x4B, 0x48, 0x35, 0x42, 0x66, 0x47, 0x53, 0x61, 0x68, ++ 0x38, 0x32, 0x41, 0x70, 0x42, 0x39, 0x50, 0x49, 0x2B, 0x35, 0x33, 0x63, 0x30, 0x42, 0x46, 0x4C, 0x64, 0x36, 0x49, 0x48, 0x79, 0x54, 0x53, 0x39, 0x55, 0x52, 0x5A, 0x30, 0x56, 0x0A, 0x34, 0x55, 0x2F, 0x4D, 0x35, 0x64, 0x34, 0x30, 0x56, 0x78, ++ 0x44, 0x4A, 0x49, 0x33, 0x49, 0x58, 0x63, 0x49, 0x31, 0x51, 0x63, 0x42, 0x39, 0x57, 0x62, 0x4D, 0x79, 0x35, 0x2F, 0x7A, 0x70, 0x61, 0x54, 0x32, 0x4E, 0x36, 0x77, 0x32, 0x35, 0x6C, 0x42, 0x78, 0x32, 0x45, 0x6F, 0x66, 0x2B, 0x70, 0x44, 0x47, ++ 0x4F, 0x4A, 0x62, 0x62, 0x4A, 0x41, 0x69, 0x44, 0x6E, 0x58, 0x48, 0x33, 0x64, 0x6F, 0x74, 0x66, 0x79, 0x63, 0x31, 0x64, 0x5A, 0x6E, 0x61, 0x56, 0x75, 0x6F, 0x0A, 0x64, 0x4E, 0x76, 0x38, 0x69, 0x66, 0x59, 0x62, 0x4D, 0x76, 0x65, 0x6B, 0x4A, ++ 0x4B, 0x5A, 0x32, 0x74, 0x30, 0x64, 0x54, 0x37, 0x34, 0x31, 0x4A, 0x6A, 0x36, 0x6D, 0x32, 0x67, 0x31, 0x71, 0x6C, 0x6C, 0x70, 0x42, 0x46, 0x59, 0x66, 0x58, 0x65, 0x41, 0x30, 0x38, 0x6D, 0x44, 0x36, 0x69, 0x4C, 0x38, 0x41, 0x4F, 0x57, 0x73, ++ 0x4B, 0x77, 0x56, 0x30, 0x48, 0x46, 0x61, 0x61, 0x6E, 0x75, 0x55, 0x35, 0x6E, 0x43, 0x54, 0x32, 0x76, 0x46, 0x70, 0x34, 0x4C, 0x4A, 0x69, 0x0A, 0x54, 0x5A, 0x36, 0x50, 0x2F, 0x34, 0x6D, 0x64, 0x6D, 0x31, 0x33, 0x4E, 0x52, 0x65, 0x6D, 0x55, ++ 0x41, 0x69, 0x4B, 0x4E, 0x34, 0x44, 0x56, 0x2F, 0x36, 0x50, 0x45, 0x45, 0x65, 0x58, 0x46, 0x73, 0x56, 0x49, 0x50, 0x34, 0x4D, 0x37, 0x6B, 0x46, 0x4D, 0x68, 0x74, 0x59, 0x56, 0x52, 0x46, 0x50, 0x30, 0x4F, 0x55, 0x6E, 0x52, 0x33, 0x48, 0x73, ++ 0x37, 0x64, 0x70, 0x6E, 0x31, 0x6D, 0x4B, 0x6D, 0x53, 0x30, 0x30, 0x50, 0x61, 0x61, 0x4C, 0x4A, 0x76, 0x4F, 0x77, 0x69, 0x0A, 0x53, 0x35, 0x54, 0x48, 0x61, 0x4A, 0x51, 0x58, 0x66, 0x75, 0x4B, 0x4F, 0x4B, 0x44, 0x36, 0x32, 0x78, 0x75, 0x72, ++ 0x31, 0x4E, 0x47, 0x79, 0x66, 0x4E, 0x34, 0x67, 0x48, 0x4F, 0x4E, 0x75, 0x47, 0x63, 0x66, 0x72, 0x4E, 0x6C, 0x55, 0x68, 0x44, 0x62, 0x71, 0x4E, 0x50, 0x67, 0x6F, 0x66, 0x58, 0x4E, 0x4A, 0x68, 0x75, 0x53, 0x35, 0x4E, 0x35, 0x59, 0x48, 0x56, ++ 0x70, 0x44, 0x2F, 0x41, 0x61, 0x31, 0x56, 0x50, 0x36, 0x49, 0x51, 0x7A, 0x43, 0x50, 0x2B, 0x6B, 0x2F, 0x0A, 0x48, 0x78, 0x69, 0x4D, 0x6B, 0x6C, 0x31, 0x34, 0x70, 0x33, 0x5A, 0x6E, 0x47, 0x62, 0x75, 0x79, 0x36, 0x6E, 0x2F, 0x70, 0x63, 0x41, ++ 0x6C, 0x57, 0x56, 0x71, 0x4F, 0x77, 0x44, 0x41, 0x73, 0x74, 0x4E, 0x6C, 0x37, 0x46, 0x36, 0x63, 0x54, 0x56, 0x67, 0x38, 0x75, 0x47, 0x46, 0x35, 0x63, 0x73, 0x62, 0x42, 0x4E, 0x76, 0x68, 0x31, 0x71, 0x76, 0x53, 0x61, 0x59, 0x64, 0x32, 0x38, ++ 0x30, 0x34, 0x42, 0x43, 0x35, 0x66, 0x34, 0x6B, 0x6F, 0x31, 0x44, 0x69, 0x31, 0x4C, 0x0A, 0x2B, 0x4B, 0x49, 0x6B, 0x42, 0x49, 0x33, 0x59, 0x34, 0x57, 0x4E, 0x65, 0x41, 0x70, 0x49, 0x30, 0x32, 0x70, 0x68, 0x68, 0x58, 0x42, 0x78, 0x76, 0x57, ++ 0x48, 0x5A, 0x6B, 0x73, 0x2F, 0x77, 0x43, 0x75, 0x50, 0x57, 0x64, 0x43, 0x67, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, ++ 0x2D, 0x0A, 0x0A, 0x53, 0x77, 0x69, 0x73, 0x73, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x52, 0x53, 0x41, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x32, 0x32, 0x20, 0x2D, 0x20, 0x31, 0x0A, 0x3D, 0x3D, ++ 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, ++ 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x6B, 0x7A, 0x43, 0x43, 0x41, 0x33, 0x75, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, ++ 0x55, 0x51, 0x2F, 0x6F, 0x4D, 0x58, 0x30, 0x34, 0x62, 0x67, 0x42, 0x68, 0x45, 0x37, 0x39, 0x47, 0x30, 0x54, 0x7A, 0x55, 0x66, 0x52, 0x50, 0x53, 0x41, 0x37, 0x63, 0x73, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, ++ 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x42, 0x51, 0x41, 0x77, 0x55, 0x54, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x0A, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4D, 0x43, 0x51, 0x30, 0x67, 0x78, 0x46, 0x54, 0x41, 0x54, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, ++ 0x6F, 0x54, 0x44, 0x46, 0x4E, 0x33, 0x61, 0x58, 0x4E, 0x7A, 0x55, 0x32, 0x6C, 0x6E, 0x62, 0x69, 0x42, 0x42, 0x52, 0x7A, 0x45, 0x72, 0x4D, 0x43, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x69, 0x55, 0x33, 0x64, 0x70, 0x63, 0x33, ++ 0x4E, 0x54, 0x61, 0x57, 0x64, 0x75, 0x49, 0x46, 0x4A, 0x54, 0x51, 0x53, 0x42, 0x55, 0x0A, 0x54, 0x46, 0x4D, 0x67, 0x55, 0x6D, 0x39, 0x76, 0x64, 0x43, 0x42, 0x44, 0x51, 0x53, 0x41, 0x79, 0x4D, 0x44, 0x49, 0x79, 0x49, 0x43, 0x30, 0x67, 0x4D, ++ 0x54, 0x41, 0x65, 0x46, 0x77, 0x30, 0x79, 0x4D, 0x6A, 0x41, 0x32, 0x4D, 0x44, 0x67, 0x78, 0x4D, 0x54, 0x41, 0x34, 0x4D, 0x6A, 0x4A, 0x61, 0x46, 0x77, 0x30, 0x30, 0x4E, 0x7A, 0x41, 0x32, 0x4D, 0x44, 0x67, 0x78, 0x4D, 0x54, 0x41, 0x34, 0x4D, ++ 0x6A, 0x4A, 0x61, 0x4D, 0x46, 0x45, 0x78, 0x43, 0x7A, 0x41, 0x4A, 0x0A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6B, 0x4E, 0x49, 0x4D, 0x52, 0x55, 0x77, 0x45, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x45, 0x77, 0x78, 0x54, ++ 0x64, 0x32, 0x6C, 0x7A, 0x63, 0x31, 0x4E, 0x70, 0x5A, 0x32, 0x34, 0x67, 0x51, 0x55, 0x63, 0x78, 0x4B, 0x7A, 0x41, 0x70, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x54, 0x49, 0x6C, 0x4E, 0x33, 0x61, 0x58, 0x4E, 0x7A, 0x55, 0x32, 0x6C, 0x6E, ++ 0x62, 0x69, 0x42, 0x53, 0x55, 0x30, 0x45, 0x67, 0x0A, 0x56, 0x45, 0x78, 0x54, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x51, 0x30, 0x45, 0x67, 0x4D, 0x6A, 0x41, 0x79, 0x4D, 0x69, 0x41, 0x74, 0x49, 0x44, 0x45, 0x77, 0x67, 0x67, 0x49, ++ 0x69, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x49, 0x4B, 0x41, 0x6F, 0x49, 0x43, 0x41, 0x51, 0x44, ++ 0x4C, 0x4B, 0x6D, 0x6A, 0x69, 0x0A, 0x43, 0x38, 0x4E, 0x58, 0x76, 0x44, 0x56, 0x6A, 0x76, 0x48, 0x43, 0x6C, 0x4F, 0x2F, 0x4F, 0x4D, 0x50, 0x45, 0x35, 0x58, 0x6C, 0x6D, 0x37, 0x44, 0x54, 0x6A, 0x61, 0x6B, 0x39, 0x67, 0x4C, 0x4B, 0x48, 0x71, ++ 0x71, 0x75, 0x75, 0x4E, 0x36, 0x6F, 0x72, 0x78, 0x31, 0x32, 0x32, 0x72, 0x6F, 0x31, 0x30, 0x4A, 0x46, 0x77, 0x42, 0x39, 0x2B, 0x7A, 0x42, 0x76, 0x4B, 0x4B, 0x38, 0x69, 0x35, 0x56, 0x55, 0x58, 0x75, 0x37, 0x4C, 0x43, 0x54, 0x4C, 0x66, 0x35, ++ 0x49, 0x6D, 0x0A, 0x67, 0x4B, 0x4F, 0x30, 0x6C, 0x50, 0x61, 0x43, 0x6F, 0x61, 0x54, 0x6F, 0x2B, 0x6E, 0x55, 0x64, 0x57, 0x66, 0x4D, 0x48, 0x61, 0x6D, 0x46, 0x6B, 0x34, 0x73, 0x61, 0x4D, 0x6C, 0x61, 0x2B, 0x6A, 0x75, 0x34, 0x35, 0x76, 0x56, ++ 0x73, 0x39, 0x78, 0x7A, 0x46, 0x36, 0x42, 0x59, 0x51, 0x31, 0x74, 0x38, 0x71, 0x73, 0x43, 0x4C, 0x71, 0x53, 0x58, 0x35, 0x58, 0x48, 0x38, 0x69, 0x72, 0x43, 0x52, 0x49, 0x46, 0x75, 0x63, 0x64, 0x46, 0x4A, 0x74, 0x72, 0x68, 0x55, 0x6E, 0x0A, ++ 0x57, 0x58, 0x6A, 0x79, 0x43, 0x63, 0x70, 0x6C, 0x44, 0x6E, 0x2F, 0x4C, 0x39, 0x4F, 0x76, 0x6E, 0x33, 0x4B, 0x6C, 0x4D, 0x64, 0x2F, 0x59, 0x72, 0x46, 0x67, 0x53, 0x56, 0x72, 0x70, 0x78, 0x78, 0x70, 0x54, 0x38, 0x71, 0x32, 0x6B, 0x46, 0x43, ++ 0x35, 0x7A, 0x79, 0x45, 0x45, 0x50, 0x54, 0x68, 0x50, 0x59, 0x78, 0x72, 0x34, 0x69, 0x75, 0x52, 0x52, 0x31, 0x56, 0x50, 0x75, 0x46, 0x61, 0x2B, 0x52, 0x64, 0x34, 0x69, 0x55, 0x55, 0x31, 0x4F, 0x4B, 0x4E, 0x6C, 0x66, 0x0A, 0x47, 0x55, 0x45, ++ 0x47, 0x6A, 0x77, 0x35, 0x4E, 0x42, 0x75, 0x42, 0x77, 0x51, 0x43, 0x4D, 0x42, 0x61, 0x75, 0x54, 0x4C, 0x45, 0x35, 0x74, 0x7A, 0x72, 0x45, 0x30, 0x55, 0x53, 0x4A, 0x49, 0x74, 0x2F, 0x6D, 0x32, 0x6E, 0x2B, 0x49, 0x64, 0x72, 0x65, 0x58, 0x58, ++ 0x68, 0x76, 0x68, 0x43, 0x78, 0x71, 0x6F, 0x68, 0x41, 0x57, 0x56, 0x54, 0x58, 0x7A, 0x38, 0x54, 0x51, 0x6D, 0x30, 0x53, 0x7A, 0x4F, 0x47, 0x6C, 0x6B, 0x6A, 0x49, 0x48, 0x52, 0x49, 0x33, 0x36, 0x71, 0x0A, 0x4F, 0x54, 0x77, 0x37, 0x44, 0x35, ++ 0x39, 0x4B, 0x65, 0x34, 0x4C, 0x4B, 0x61, 0x32, 0x2F, 0x4B, 0x49, 0x6A, 0x34, 0x78, 0x30, 0x4C, 0x44, 0x51, 0x4B, 0x68, 0x79, 0x53, 0x69, 0x6F, 0x2F, 0x59, 0x47, 0x5A, 0x78, 0x48, 0x35, 0x44, 0x34, 0x4D, 0x75, 0x63, 0x4C, 0x4E, 0x76, 0x6B, ++ 0x45, 0x4D, 0x2B, 0x4B, 0x52, 0x48, 0x42, 0x64, 0x76, 0x42, 0x46, 0x7A, 0x41, 0x34, 0x4F, 0x6D, 0x6E, 0x63, 0x7A, 0x63, 0x4E, 0x70, 0x49, 0x2F, 0x32, 0x61, 0x44, 0x77, 0x4C, 0x4F, 0x0A, 0x45, 0x47, 0x72, 0x4F, 0x79, 0x76, 0x69, 0x35, 0x4B, ++ 0x61, 0x4D, 0x32, 0x69, 0x59, 0x61, 0x75, 0x43, 0x38, 0x42, 0x50, 0x59, 0x37, 0x6B, 0x47, 0x57, 0x55, 0x6C, 0x65, 0x44, 0x73, 0x46, 0x70, 0x73, 0x77, 0x72, 0x7A, 0x64, 0x33, 0x34, 0x75, 0x6E, 0x59, 0x79, 0x7A, 0x4A, 0x35, 0x6A, 0x53, 0x6D, ++ 0x59, 0x30, 0x6C, 0x70, 0x78, 0x2B, 0x47, 0x73, 0x36, 0x5A, 0x55, 0x63, 0x44, 0x6A, 0x38, 0x66, 0x56, 0x33, 0x6F, 0x54, 0x34, 0x4D, 0x4D, 0x30, 0x5A, 0x50, 0x6C, 0x0A, 0x45, 0x75, 0x52, 0x55, 0x32, 0x6A, 0x37, 0x79, 0x72, 0x54, 0x72, 0x65, ++ 0x50, 0x6A, 0x78, 0x46, 0x38, 0x43, 0x67, 0x50, 0x42, 0x72, 0x6E, 0x68, 0x32, 0x35, 0x64, 0x37, 0x6D, 0x55, 0x57, 0x65, 0x33, 0x66, 0x36, 0x56, 0x57, 0x51, 0x51, 0x76, 0x64, 0x54, 0x2F, 0x54, 0x72, 0x6F, 0x6D, 0x5A, 0x68, 0x71, 0x77, 0x55, ++ 0x74, 0x4B, 0x69, 0x45, 0x2B, 0x73, 0x68, 0x64, 0x4F, 0x78, 0x74, 0x59, 0x6B, 0x38, 0x45, 0x58, 0x6C, 0x46, 0x58, 0x49, 0x43, 0x2B, 0x4F, 0x43, 0x0A, 0x65, 0x59, 0x53, 0x66, 0x38, 0x77, 0x43, 0x45, 0x4E, 0x4F, 0x37, 0x63, 0x4D, 0x64, 0x57, ++ 0x50, 0x38, 0x76, 0x70, 0x50, 0x6C, 0x6B, 0x77, 0x47, 0x71, 0x6E, 0x6A, 0x37, 0x33, 0x6D, 0x53, 0x69, 0x49, 0x38, 0x30, 0x66, 0x50, 0x73, 0x57, 0x4D, 0x76, 0x44, 0x64, 0x55, 0x44, 0x72, 0x74, 0x61, 0x63, 0x6C, 0x58, 0x76, 0x79, 0x46, 0x75, ++ 0x31, 0x63, 0x76, 0x68, 0x34, 0x33, 0x7A, 0x63, 0x67, 0x54, 0x46, 0x65, 0x52, 0x63, 0x35, 0x4A, 0x7A, 0x72, 0x42, 0x68, 0x33, 0x0A, 0x51, 0x34, 0x49, 0x67, 0x61, 0x65, 0x7A, 0x70, 0x72, 0x43, 0x6C, 0x47, 0x35, 0x51, 0x74, 0x4F, 0x2B, 0x44, ++ 0x64, 0x7A, 0x69, 0x5A, 0x61, 0x4B, 0x48, 0x47, 0x32, 0x39, 0x37, 0x37, 0x37, 0x59, 0x74, 0x76, 0x54, 0x4B, 0x77, 0x50, 0x31, 0x48, 0x38, 0x4B, 0x34, 0x4C, 0x57, 0x43, 0x44, 0x46, 0x79, 0x42, 0x30, 0x32, 0x72, 0x70, 0x65, 0x4E, 0x55, 0x49, ++ 0x4D, 0x6D, 0x4A, 0x43, 0x6E, 0x33, 0x6E, 0x54, 0x73, 0x50, 0x42, 0x51, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x0A, 0x6F, 0x32, 0x4D, 0x77, 0x59, 0x54, 0x41, 0x50, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x52, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x45, 0x42, ++ 0x54, 0x41, 0x44, 0x41, 0x51, 0x48, 0x2F, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x42, 0x42, 0x6A, 0x41, 0x66, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x53, 0x4D, 0x45, 0x47, ++ 0x44, 0x41, 0x57, 0x67, 0x42, 0x52, 0x76, 0x6A, 0x6D, 0x4B, 0x4C, 0x6B, 0x30, 0x4F, 0x77, 0x0A, 0x34, 0x55, 0x44, 0x32, 0x70, 0x38, 0x50, 0x39, 0x38, 0x51, 0x2B, 0x34, 0x44, 0x78, 0x55, 0x34, 0x70, 0x54, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, ++ 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x62, 0x34, 0x35, 0x69, 0x69, 0x35, 0x4E, 0x44, 0x73, 0x4F, 0x46, 0x41, 0x39, 0x71, 0x66, 0x44, 0x2F, 0x66, 0x45, 0x50, 0x75, 0x41, 0x38, 0x56, 0x4F, 0x4B, 0x55, 0x77, 0x44, 0x51, 0x59, 0x4A, ++ 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x0A, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x42, 0x41, 0x4B, 0x77, 0x73, 0x4B, 0x55, 0x46, 0x39, 0x2B, 0x6C, 0x7A, 0x31, 0x47, 0x70, 0x55, 0x59, 0x76, 0x79, 0x79, ++ 0x70, 0x69, 0x71, 0x6B, 0x6B, 0x56, 0x48, 0x58, 0x31, 0x75, 0x45, 0x43, 0x72, 0x79, 0x36, 0x67, 0x6B, 0x55, 0x53, 0x73, 0x59, 0x50, 0x32, 0x4F, 0x70, 0x72, 0x70, 0x68, 0x57, 0x4B, 0x77, 0x56, 0x44, 0x49, 0x71, 0x4F, 0x33, 0x31, 0x30, 0x61, ++ 0x65, 0x77, 0x43, 0x6F, 0x53, 0x50, 0x59, 0x36, 0x57, 0x0A, 0x6C, 0x6B, 0x44, 0x66, 0x44, 0x44, 0x4F, 0x4C, 0x61, 0x7A, 0x65, 0x52, 0x4F, 0x70, 0x57, 0x37, 0x4F, 0x53, 0x6C, 0x74, 0x77, 0x41, 0x4A, 0x73, 0x69, 0x70, 0x51, 0x4C, 0x42, 0x77, ++ 0x4A, 0x4E, 0x47, 0x44, 0x37, 0x37, 0x2B, 0x33, 0x76, 0x31, 0x64, 0x6A, 0x32, 0x62, 0x39, 0x6C, 0x34, 0x77, 0x42, 0x6C, 0x67, 0x7A, 0x48, 0x71, 0x70, 0x34, 0x31, 0x65, 0x5A, 0x55, 0x42, 0x44, 0x71, 0x79, 0x67, 0x67, 0x6D, 0x4E, 0x7A, 0x68, ++ 0x59, 0x7A, 0x57, 0x55, 0x55, 0x6F, 0x0A, 0x38, 0x61, 0x57, 0x6A, 0x6C, 0x77, 0x35, 0x44, 0x49, 0x2F, 0x30, 0x4C, 0x49, 0x49, 0x43, 0x51, 0x2F, 0x2B, 0x4D, 0x6D, 0x7A, 0x37, 0x68, 0x6B, 0x6B, 0x65, 0x55, 0x46, 0x6A, 0x78, 0x4F, 0x67, 0x64, ++ 0x67, 0x33, 0x58, 0x4E, 0x77, 0x77, 0x51, 0x69, 0x4A, 0x62, 0x30, 0x50, 0x72, 0x36, 0x56, 0x76, 0x66, 0x48, 0x44, 0x66, 0x66, 0x43, 0x6A, 0x77, 0x33, 0x6C, 0x48, 0x43, 0x31, 0x79, 0x53, 0x46, 0x57, 0x50, 0x74, 0x55, 0x6E, 0x57, 0x4B, 0x35, ++ 0x30, 0x5A, 0x70, 0x0A, 0x79, 0x31, 0x46, 0x56, 0x43, 0x79, 0x70, 0x4D, 0x39, 0x66, 0x4A, 0x6B, 0x54, 0x36, 0x6C, 0x63, 0x2F, 0x32, 0x63, 0x79, 0x6A, 0x6C, 0x55, 0x74, 0x4D, 0x6F, 0x49, 0x63, 0x67, 0x43, 0x39, 0x71, 0x6B, 0x66, 0x6A, 0x4C, ++ 0x76, 0x48, 0x34, 0x59, 0x6F, 0x69, 0x61, 0x6F, 0x4C, 0x71, 0x4E, 0x54, 0x4B, 0x49, 0x66, 0x74, 0x56, 0x2B, 0x56, 0x6C, 0x65, 0x6B, 0x34, 0x41, 0x53, 0x6C, 0x74, 0x4F, 0x55, 0x38, 0x6C, 0x69, 0x4E, 0x72, 0x33, 0x43, 0x6A, 0x6C, 0x76, 0x72, ++ 0x0A, 0x7A, 0x47, 0x34, 0x6E, 0x67, 0x52, 0x68, 0x5A, 0x69, 0x30, 0x52, 0x6A, 0x6E, 0x39, 0x55, 0x4D, 0x5A, 0x66, 0x51, 0x70, 0x5A, 0x58, 0x2B, 0x52, 0x4C, 0x4F, 0x56, 0x2F, 0x66, 0x75, 0x69, 0x4A, 0x7A, 0x34, 0x38, 0x67, 0x79, 0x32, 0x30, ++ 0x48, 0x51, 0x68, 0x46, 0x52, 0x4A, 0x6A, 0x4B, 0x4B, 0x4C, 0x6A, 0x70, 0x48, 0x45, 0x37, 0x69, 0x4E, 0x76, 0x55, 0x63, 0x4E, 0x43, 0x66, 0x41, 0x57, 0x70, 0x4F, 0x32, 0x57, 0x68, 0x69, 0x34, 0x5A, 0x32, 0x4C, 0x36, 0x4D, 0x0A, 0x4F, 0x75, ++ 0x68, 0x46, 0x4C, 0x68, 0x47, 0x36, 0x72, 0x6C, 0x72, 0x6E, 0x75, 0x62, 0x2B, 0x78, 0x7A, 0x49, 0x2F, 0x67, 0x6F, 0x50, 0x2B, 0x34, 0x73, 0x39, 0x47, 0x46, 0x65, 0x33, 0x6C, 0x6D, 0x6F, 0x7A, 0x6D, 0x31, 0x4F, 0x32, 0x62, 0x59, 0x51, 0x4C, ++ 0x37, 0x50, 0x74, 0x32, 0x65, 0x4C, 0x53, 0x4D, 0x6B, 0x5A, 0x4A, 0x56, 0x58, 0x38, 0x76, 0x59, 0x33, 0x50, 0x58, 0x74, 0x70, 0x4F, 0x70, 0x76, 0x4A, 0x70, 0x7A, 0x76, 0x31, 0x2F, 0x54, 0x48, 0x66, 0x51, 0x0A, 0x77, 0x55, 0x59, 0x31, 0x6D, ++ 0x46, 0x77, 0x6A, 0x6D, 0x77, 0x4A, 0x46, 0x51, 0x35, 0x52, 0x61, 0x33, 0x62, 0x78, 0x48, 0x72, 0x53, 0x4C, 0x2B, 0x75, 0x6C, 0x34, 0x76, 0x6B, 0x53, 0x6B, 0x70, 0x68, 0x6E, 0x73, 0x68, 0x33, 0x6D, 0x35, 0x6B, 0x74, 0x38, 0x73, 0x4E, 0x6A, ++ 0x7A, 0x64, 0x62, 0x6F, 0x77, 0x68, 0x71, 0x36, 0x2F, 0x54, 0x64, 0x41, 0x6F, 0x39, 0x51, 0x41, 0x77, 0x4B, 0x78, 0x75, 0x44, 0x64, 0x6F, 0x6C, 0x6C, 0x44, 0x72, 0x75, 0x46, 0x2F, 0x55, 0x0A, 0x4B, 0x49, 0x71, 0x6C, 0x49, 0x67, 0x79, 0x4B, ++ 0x68, 0x50, 0x42, 0x5A, 0x4C, 0x74, 0x55, 0x33, 0x30, 0x57, 0x48, 0x6C, 0x51, 0x6E, 0x4E, 0x59, 0x4B, 0x6F, 0x48, 0x33, 0x64, 0x74, 0x76, 0x69, 0x34, 0x6B, 0x30, 0x4E, 0x58, 0x2F, 0x61, 0x33, 0x76, 0x67, 0x57, 0x30, 0x72, 0x6B, 0x34, 0x4E, ++ 0x33, 0x68, 0x59, 0x39, 0x41, 0x34, 0x47, 0x7A, 0x4A, 0x6C, 0x35, 0x4C, 0x75, 0x45, 0x73, 0x41, 0x7A, 0x2F, 0x2B, 0x4D, 0x46, 0x37, 0x70, 0x73, 0x59, 0x43, 0x30, 0x6E, 0x0A, 0x68, 0x7A, 0x63, 0x6B, 0x35, 0x6E, 0x70, 0x67, 0x4C, 0x37, 0x58, ++ 0x54, 0x67, 0x77, 0x53, 0x71, 0x54, 0x30, 0x4E, 0x31, 0x6F, 0x73, 0x47, 0x44, 0x73, 0x69, 0x65, 0x59, 0x4B, 0x37, 0x45, 0x4F, 0x67, 0x4C, 0x72, 0x41, 0x68, 0x56, 0x35, 0x43, 0x75, 0x64, 0x2B, 0x78, 0x59, 0x4A, 0x48, 0x54, 0x36, 0x78, 0x68, ++ 0x2B, 0x63, 0x48, 0x69, 0x75, 0x64, 0x6F, 0x4F, 0x2B, 0x63, 0x56, 0x72, 0x51, 0x6B, 0x4F, 0x50, 0x4B, 0x77, 0x52, 0x59, 0x6C, 0x5A, 0x30, 0x72, 0x77, 0x0A, 0x74, 0x6E, 0x75, 0x36, 0x34, 0x5A, 0x7A, 0x5A, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, ++ 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x4F, 0x49, 0x53, 0x54, 0x45, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, ++ 0x45, 0x43, 0x43, 0x20, 0x47, 0x31, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, ++ 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x43, 0x4E, 0x54, 0x43, 0x43, 0x41, 0x62, 0x71, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, ++ 0x49, 0x2F, 0x6E, 0x44, 0x31, 0x6A, 0x57, 0x76, 0x6A, 0x79, 0x68, 0x4C, 0x48, 0x2F, 0x42, 0x55, 0x36, 0x6E, 0x36, 0x58, 0x6E, 0x54, 0x41, 0x4B, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x51, 0x44, 0x41, 0x7A, 0x42, 0x4C, ++ 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4A, 0x44, 0x0A, 0x53, 0x44, 0x45, 0x5A, 0x4D, 0x42, 0x63, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, 0x51, 0x54, 0x30, 0x6C, 0x54, 0x56, 0x45, 0x55, ++ 0x67, 0x52, 0x6D, 0x39, 0x31, 0x62, 0x6D, 0x52, 0x68, 0x64, 0x47, 0x6C, 0x76, 0x62, 0x6A, 0x45, 0x68, 0x4D, 0x42, 0x38, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x77, 0x77, 0x59, 0x54, 0x30, 0x6C, 0x54, 0x56, 0x45, 0x55, 0x67, 0x55, 0x32, 0x56, ++ 0x79, 0x64, 0x6D, 0x56, 0x79, 0x49, 0x46, 0x4A, 0x76, 0x62, 0x33, 0x51, 0x67, 0x0A, 0x52, 0x55, 0x4E, 0x44, 0x49, 0x45, 0x63, 0x78, 0x4D, 0x42, 0x34, 0x58, 0x44, 0x54, 0x49, 0x7A, 0x4D, 0x44, 0x55, 0x7A, 0x4D, 0x54, 0x45, 0x30, 0x4E, 0x44, ++ 0x49, 0x79, 0x4F, 0x46, 0x6F, 0x58, 0x44, 0x54, 0x51, 0x34, 0x4D, 0x44, 0x55, 0x79, 0x4E, 0x44, 0x45, 0x30, 0x4E, 0x44, 0x49, 0x79, 0x4E, 0x31, 0x6F, 0x77, 0x53, 0x7A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, ++ 0x4D, 0x43, 0x51, 0x30, 0x67, 0x78, 0x47, 0x54, 0x41, 0x58, 0x0A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x4D, 0x45, 0x45, 0x39, 0x4A, 0x55, 0x31, 0x52, 0x46, 0x49, 0x45, 0x5A, 0x76, 0x64, 0x57, 0x35, 0x6B, 0x59, 0x58, 0x52, 0x70, 0x62, ++ 0x32, 0x34, 0x78, 0x49, 0x54, 0x41, 0x66, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x4D, 0x47, 0x45, 0x39, 0x4A, 0x55, 0x31, 0x52, 0x46, 0x49, 0x46, 0x4E, 0x6C, 0x63, 0x6E, 0x5A, 0x6C, 0x63, 0x69, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, 0x49, ++ 0x45, 0x56, 0x44, 0x51, 0x79, 0x42, 0x48, 0x0A, 0x4D, 0x54, 0x42, 0x32, 0x4D, 0x42, 0x41, 0x47, 0x42, 0x79, 0x71, 0x47, 0x53, 0x4D, 0x34, 0x39, 0x41, 0x67, 0x45, 0x47, 0x42, 0x53, 0x75, 0x42, 0x42, 0x41, 0x41, 0x69, 0x41, 0x32, 0x49, 0x41, ++ 0x42, 0x42, 0x63, 0x76, 0x2B, 0x68, 0x4B, 0x38, 0x72, 0x42, 0x6A, 0x7A, 0x43, 0x76, 0x52, 0x45, 0x31, 0x6E, 0x5A, 0x43, 0x6E, 0x72, 0x50, 0x6F, 0x48, 0x37, 0x64, 0x35, 0x71, 0x56, 0x69, 0x32, 0x2B, 0x47, 0x58, 0x52, 0x4F, 0x69, 0x46, 0x50, ++ 0x71, 0x4F, 0x75, 0x6A, 0x0A, 0x76, 0x71, 0x51, 0x79, 0x63, 0x76, 0x4F, 0x32, 0x41, 0x63, 0x6B, 0x72, 0x2F, 0x58, 0x65, 0x46, 0x62, 0x6C, 0x50, 0x64, 0x72, 0x65, 0x71, 0x71, 0x4C, 0x69, 0x57, 0x53, 0x74, 0x75, 0x6B, 0x68, 0x45, 0x61, 0x69, ++ 0x76, 0x74, 0x55, 0x77, 0x4C, 0x38, 0x35, 0x5A, 0x67, 0x6D, 0x6A, 0x76, 0x6E, 0x36, 0x68, 0x70, 0x34, 0x4C, 0x72, 0x51, 0x39, 0x35, 0x53, 0x6A, 0x65, 0x48, 0x49, 0x43, 0x36, 0x58, 0x47, 0x34, 0x4E, 0x32, 0x78, 0x6D, 0x6C, 0x34, 0x7A, 0x2B, ++ 0x63, 0x0A, 0x4B, 0x72, 0x68, 0x41, 0x53, 0x39, 0x33, 0x6D, 0x54, 0x36, 0x4E, 0x6A, 0x4D, 0x47, 0x45, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x2F, 0x7A, ++ 0x41, 0x66, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x53, 0x4D, 0x45, 0x47, 0x44, 0x41, 0x57, 0x67, 0x42, 0x51, 0x33, 0x54, 0x59, 0x68, 0x6C, 0x7A, 0x2F, 0x77, 0x39, 0x69, 0x74, 0x57, 0x6A, 0x38, 0x55, 0x6E, 0x41, 0x54, 0x67, 0x77, 0x51, 0x0A, 0x62, ++ 0x30, 0x4B, 0x30, 0x6E, 0x44, 0x41, 0x64, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x4E, 0x30, 0x32, 0x49, 0x5A, 0x63, 0x2F, 0x38, 0x50, 0x59, 0x72, 0x56, 0x6F, 0x2F, 0x46, 0x4A, 0x77, 0x45, 0x34, 0x4D, 0x45, ++ 0x47, 0x39, 0x43, 0x74, 0x4A, 0x77, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x41, 0x51, 0x48, 0x2F, 0x42, 0x41, 0x51, 0x44, 0x41, 0x67, 0x47, 0x47, 0x4D, 0x41, 0x6F, 0x47, 0x43, 0x43, 0x71, 0x47, 0x0A, 0x53, 0x4D, 0x34, 0x39, ++ 0x42, 0x41, 0x4D, 0x44, 0x41, 0x32, 0x6B, 0x41, 0x4D, 0x47, 0x59, 0x43, 0x4D, 0x51, 0x43, 0x70, 0x4B, 0x6A, 0x41, 0x64, 0x30, 0x4D, 0x4B, 0x66, 0x6B, 0x46, 0x46, 0x52, 0x51, 0x44, 0x36, 0x56, 0x56, 0x43, 0x48, 0x4E, 0x46, 0x6D, 0x62, 0x33, ++ 0x55, 0x32, 0x77, 0x49, 0x46, 0x6A, 0x6E, 0x51, 0x45, 0x6E, 0x78, 0x2F, 0x59, 0x78, 0x76, 0x66, 0x34, 0x7A, 0x67, 0x41, 0x4F, 0x64, 0x6B, 0x74, 0x55, 0x79, 0x42, 0x46, 0x43, 0x78, 0x78, 0x67, 0x0A, 0x5A, 0x7A, 0x46, 0x44, 0x4A, 0x65, 0x30, ++ 0x43, 0x4D, 0x51, 0x43, 0x53, 0x69, 0x61, 0x37, 0x70, 0x58, 0x47, 0x4B, 0x44, 0x59, 0x6D, 0x48, 0x35, 0x4C, 0x56, 0x65, 0x72, 0x56, 0x72, 0x6B, 0x52, 0x33, 0x53, 0x57, 0x2B, 0x61, 0x6B, 0x35, 0x4B, 0x47, 0x6F, 0x4A, 0x72, 0x33, 0x4D, 0x2F, ++ 0x54, 0x76, 0x45, 0x71, 0x7A, 0x50, 0x4E, 0x63, 0x75, 0x6D, 0x39, 0x76, 0x34, 0x4B, 0x47, 0x6D, 0x38, 0x61, 0x79, 0x33, 0x73, 0x4D, 0x61, 0x45, 0x36, 0x34, 0x31, 0x63, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, ++ 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x0A, 0x20, 0x4F, 0x49, 0x53, 0x54, 0x45, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x53, 0x41, 0x20, ++ 0x47, 0x31, 0x0A, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, ++ 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x46, 0x67, 0x7A, 0x43, 0x43, 0x41, 0x32, 0x75, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x51, 0x56, 0x61, 0x58, ++ 0x5A, 0x5A, 0x35, 0x51, 0x6F, 0x78, 0x75, 0x30, 0x4D, 0x2B, 0x69, 0x66, 0x64, 0x57, 0x77, 0x46, 0x4E, 0x47, 0x44, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x77, 0x46, 0x41, 0x44, 0x42, ++ 0x4C, 0x4D, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x0A, 0x45, 0x77, 0x4A, 0x44, 0x53, 0x44, 0x45, 0x5A, 0x4D, 0x42, 0x63, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, 0x51, 0x54, 0x30, 0x6C, 0x54, 0x56, 0x45, ++ 0x55, 0x67, 0x52, 0x6D, 0x39, 0x31, 0x62, 0x6D, 0x52, 0x68, 0x64, 0x47, 0x6C, 0x76, 0x62, 0x6A, 0x45, 0x68, 0x4D, 0x42, 0x38, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x77, 0x77, 0x59, 0x54, 0x30, 0x6C, 0x54, 0x56, 0x45, 0x55, 0x67, 0x55, 0x32, ++ 0x56, 0x79, 0x64, 0x6D, 0x56, 0x79, 0x49, 0x46, 0x4A, 0x76, 0x0A, 0x62, 0x33, 0x51, 0x67, 0x55, 0x6C, 0x4E, 0x42, 0x49, 0x45, 0x63, 0x78, 0x4D, 0x42, 0x34, 0x58, 0x44, 0x54, 0x49, 0x7A, 0x4D, 0x44, 0x55, 0x7A, 0x4D, 0x54, 0x45, 0x30, 0x4D, ++ 0x7A, 0x63, 0x78, 0x4E, 0x6C, 0x6F, 0x58, 0x44, 0x54, 0x51, 0x34, 0x4D, 0x44, 0x55, 0x79, 0x4E, 0x44, 0x45, 0x30, 0x4D, 0x7A, 0x63, 0x78, 0x4E, 0x56, 0x6F, 0x77, 0x53, 0x7A, 0x45, 0x4C, 0x4D, 0x41, 0x6B, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, ++ 0x68, 0x4D, 0x43, 0x51, 0x30, 0x67, 0x78, 0x0A, 0x47, 0x54, 0x41, 0x58, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x6F, 0x4D, 0x45, 0x45, 0x39, 0x4A, 0x55, 0x31, 0x52, 0x46, 0x49, 0x45, 0x5A, 0x76, 0x64, 0x57, 0x35, 0x6B, 0x59, 0x58, 0x52, 0x70, ++ 0x62, 0x32, 0x34, 0x78, 0x49, 0x54, 0x41, 0x66, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x4D, 0x4D, 0x47, 0x45, 0x39, 0x4A, 0x55, 0x31, 0x52, 0x46, 0x49, 0x46, 0x4E, 0x6C, 0x63, 0x6E, 0x5A, 0x6C, 0x63, 0x69, 0x42, 0x53, 0x62, 0x32, 0x39, 0x30, ++ 0x49, 0x46, 0x4A, 0x54, 0x0A, 0x51, 0x53, 0x42, 0x48, 0x4D, 0x54, 0x43, 0x43, 0x41, 0x69, 0x49, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, ++ 0x50, 0x41, 0x44, 0x43, 0x43, 0x41, 0x67, 0x6F, 0x43, 0x67, 0x67, 0x49, 0x42, 0x41, 0x4B, 0x71, 0x75, 0x39, 0x4B, 0x75, 0x43, 0x7A, 0x2F, 0x76, 0x6C, 0x4E, 0x77, 0x76, 0x6E, 0x31, 0x5A, 0x61, 0x74, 0x6B, 0x4F, 0x68, 0x4C, 0x4B, 0x64, 0x78, ++ 0x56, 0x0A, 0x59, 0x4F, 0x50, 0x4D, 0x76, 0x4C, 0x4F, 0x38, 0x4C, 0x5A, 0x4B, 0x35, 0x35, 0x4B, 0x4E, 0x36, 0x38, 0x59, 0x47, 0x30, 0x6E, 0x6E, 0x4A, 0x79, 0x51, 0x39, 0x38, 0x2F, 0x71, 0x77, 0x73, 0x6D, 0x74, 0x4F, 0x35, 0x37, 0x47, 0x6D, ++ 0x6E, 0x37, 0x4B, 0x4E, 0x42, 0x79, 0x58, 0x45, 0x70, 0x74, 0x61, 0x5A, 0x6E, 0x77, 0x59, 0x78, 0x34, 0x4D, 0x30, 0x72, 0x48, 0x2F, 0x31, 0x6F, 0x77, 0x30, 0x30, 0x4F, 0x37, 0x62, 0x72, 0x45, 0x69, 0x35, 0x36, 0x72, 0x41, 0x55, 0x0A, 0x6A, ++ 0x74, 0x67, 0x48, 0x71, 0x53, 0x53, 0x59, 0x33, 0x65, 0x6B, 0x4A, 0x76, 0x71, 0x67, 0x69, 0x47, 0x31, 0x6B, 0x35, 0x30, 0x53, 0x65, 0x48, 0x33, 0x42, 0x7A, 0x4E, 0x2B, 0x50, 0x75, 0x7A, 0x36, 0x2B, 0x6D, 0x54, 0x65, 0x4F, 0x30, 0x50, 0x7A, ++ 0x6A, 0x64, 0x38, 0x4A, 0x6E, 0x64, 0x75, 0x6F, 0x64, 0x67, 0x73, 0x49, 0x55, 0x7A, 0x6B, 0x69, 0x6B, 0x2F, 0x48, 0x45, 0x7A, 0x78, 0x75, 0x78, 0x39, 0x55, 0x54, 0x6C, 0x37, 0x4B, 0x6F, 0x32, 0x79, 0x52, 0x70, 0x0A, 0x67, 0x31, 0x62, 0x54, ++ 0x61, 0x63, 0x75, 0x43, 0x45, 0x72, 0x75, 0x64, 0x47, 0x2F, 0x4C, 0x34, 0x4E, 0x50, 0x4B, 0x59, 0x4B, 0x79, 0x71, 0x4F, 0x42, 0x47, 0x66, 0x32, 0x34, 0x34, 0x65, 0x68, 0x48, 0x61, 0x31, 0x75, 0x7A, 0x6A, 0x5A, 0x30, 0x44, 0x6C, 0x34, 0x7A, ++ 0x4F, 0x38, 0x76, 0x62, 0x55, 0x5A, 0x65, 0x55, 0x61, 0x70, 0x55, 0x38, 0x7A, 0x68, 0x68, 0x61, 0x62, 0x6B, 0x76, 0x47, 0x2F, 0x41, 0x65, 0x50, 0x4C, 0x68, 0x71, 0x35, 0x53, 0x76, 0x64, 0x6B, 0x0A, 0x4E, 0x43, 0x6E, 0x63, 0x70, 0x6F, 0x31, ++ 0x51, 0x34, 0x59, 0x32, 0x4C, 0x53, 0x2B, 0x56, 0x49, 0x47, 0x32, 0x34, 0x75, 0x67, 0x42, 0x41, 0x2F, 0x35, 0x4A, 0x38, 0x62, 0x5A, 0x54, 0x38, 0x52, 0x74, 0x4F, 0x70, 0x58, 0x61, 0x5A, 0x2B, 0x30, 0x41, 0x4F, 0x75, 0x46, 0x4A, 0x4A, 0x6B, ++ 0x6B, 0x39, 0x53, 0x47, 0x64, 0x6C, 0x36, 0x72, 0x37, 0x4E, 0x48, 0x38, 0x43, 0x61, 0x78, 0x57, 0x51, 0x72, 0x62, 0x75, 0x65, 0x57, 0x68, 0x6C, 0x2F, 0x70, 0x49, 0x7A, 0x59, 0x0A, 0x2B, 0x6D, 0x30, 0x6F, 0x2F, 0x44, 0x6A, 0x48, 0x34, 0x30, ++ 0x79, 0x74, 0x61, 0x73, 0x37, 0x5A, 0x54, 0x70, 0x4F, 0x53, 0x6A, 0x73, 0x77, 0x4D, 0x5A, 0x37, 0x38, 0x4C, 0x53, 0x35, 0x62, 0x4F, 0x5A, 0x6D, 0x64, 0x54, 0x61, 0x4D, 0x73, 0x58, 0x45, 0x59, 0x35, 0x5A, 0x39, 0x36, 0x79, 0x63, 0x47, 0x37, ++ 0x6D, 0x4F, 0x61, 0x45, 0x53, 0x33, 0x47, 0x4B, 0x2F, 0x6D, 0x35, 0x51, 0x39, 0x6C, 0x33, 0x4A, 0x55, 0x4A, 0x73, 0x4A, 0x4D, 0x53, 0x74, 0x52, 0x38, 0x2B, 0x0A, 0x6C, 0x4B, 0x58, 0x48, 0x69, 0x48, 0x55, 0x68, 0x73, 0x64, 0x34, 0x4A, 0x4A, ++ 0x43, 0x70, 0x4D, 0x34, 0x72, 0x7A, 0x73, 0x54, 0x47, 0x64, 0x48, 0x77, 0x69, 0x6D, 0x49, 0x75, 0x51, 0x71, 0x36, 0x2B, 0x63, 0x46, 0x30, 0x7A, 0x6F, 0x77, 0x59, 0x4A, 0x6D, 0x58, 0x61, 0x39, 0x32, 0x2F, 0x47, 0x6A, 0x48, 0x74, 0x6F, 0x58, ++ 0x41, 0x76, 0x75, 0x59, 0x38, 0x42, 0x65, 0x53, 0x2F, 0x46, 0x4F, 0x7A, 0x4A, 0x38, 0x76, 0x44, 0x2B, 0x48, 0x6F, 0x6D, 0x6E, 0x71, 0x54, 0x0A, 0x38, 0x65, 0x44, 0x49, 0x32, 0x37, 0x38, 0x6E, 0x35, 0x6D, 0x55, 0x70, 0x65, 0x7A, 0x62, 0x67, ++ 0x4D, 0x78, 0x56, 0x7A, 0x38, 0x70, 0x31, 0x72, 0x68, 0x41, 0x68, 0x6F, 0x4B, 0x7A, 0x59, 0x48, 0x4B, 0x79, 0x66, 0x4D, 0x65, 0x4E, 0x68, 0x71, 0x68, 0x77, 0x35, 0x48, 0x64, 0x50, 0x53, 0x71, 0x6F, 0x42, 0x4E, 0x64, 0x5A, 0x48, 0x37, 0x30, ++ 0x32, 0x78, 0x53, 0x75, 0x2B, 0x7A, 0x72, 0x6B, 0x4C, 0x38, 0x46, 0x6C, 0x34, 0x37, 0x6C, 0x36, 0x51, 0x47, 0x7A, 0x77, 0x0A, 0x42, 0x72, 0x64, 0x37, 0x4B, 0x4A, 0x76, 0x58, 0x34, 0x56, 0x38, 0x34, 0x63, 0x35, 0x53, 0x73, 0x32, 0x58, 0x43, ++ 0x54, 0x4C, 0x64, 0x79, 0x45, 0x72, 0x30, 0x59, 0x63, 0x6F, 0x6E, 0x6F, 0x73, 0x50, 0x34, 0x45, 0x6D, 0x51, 0x75, 0x66, 0x55, 0x32, 0x4D, 0x56, 0x73, 0x68, 0x47, 0x59, 0x52, 0x69, 0x33, 0x64, 0x72, 0x56, 0x42, 0x79, 0x6A, 0x74, 0x64, 0x67, ++ 0x51, 0x38, 0x4B, 0x34, 0x70, 0x39, 0x32, 0x63, 0x49, 0x69, 0x42, 0x64, 0x63, 0x75, 0x4A, 0x64, 0x35, 0x0A, 0x7A, 0x2B, 0x6F, 0x72, 0x4B, 0x75, 0x35, 0x59, 0x4D, 0x2B, 0x56, 0x74, 0x36, 0x53, 0x6D, 0x71, 0x5A, 0x51, 0x45, 0x4E, 0x67, 0x68, ++ 0x50, 0x73, 0x4A, 0x51, 0x74, 0x64, 0x4C, 0x45, 0x42, 0x79, 0x46, 0x53, 0x6E, 0x54, 0x6B, 0x43, 0x7A, 0x33, 0x47, 0x6B, 0x50, 0x56, 0x61, 0x76, 0x42, 0x70, 0x41, 0x67, 0x4D, 0x42, 0x41, 0x41, 0x47, 0x6A, 0x59, 0x7A, 0x42, 0x68, 0x4D, 0x41, ++ 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x46, 0x0A, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x48, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x6A, 0x42, 0x42, 0x67, 0x77, 0x46, 0x6F, 0x41, 0x55, 0x38, ++ 0x73, 0x6E, 0x42, 0x44, 0x77, 0x31, 0x6A, 0x41, 0x4C, 0x76, 0x73, 0x52, 0x51, 0x35, 0x4B, 0x48, 0x37, 0x57, 0x78, 0x73, 0x7A, 0x62, 0x4E, 0x44, 0x6F, 0x30, 0x77, 0x48, 0x51, 0x59, 0x44, 0x56, 0x52, 0x30, 0x4F, 0x42, 0x42, 0x59, 0x45, 0x46, ++ 0x50, 0x4C, 0x4A, 0x77, 0x51, 0x38, 0x4E, 0x59, 0x77, 0x43, 0x37, 0x0A, 0x37, 0x45, 0x55, 0x4F, 0x53, 0x68, 0x2B, 0x31, 0x73, 0x62, 0x4D, 0x32, 0x7A, 0x51, 0x36, 0x4E, 0x4D, 0x41, 0x34, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, ++ 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x42, 0x68, 0x6A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x77, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x67, 0x45, 0x41, 0x4E, 0x47, 0x64, 0x35, ++ 0x73, 0x6A, 0x72, 0x47, 0x35, 0x54, 0x33, 0x33, 0x0A, 0x49, 0x33, 0x4B, 0x35, 0x43, 0x65, 0x2B, 0x53, 0x72, 0x53, 0x63, 0x66, 0x6F, 0x45, 0x34, 0x4B, 0x73, 0x76, 0x58, 0x61, 0x46, 0x77, 0x79, 0x69, 0x68, 0x64, 0x4A, 0x2B, 0x6B, 0x6C, 0x48, ++ 0x39, 0x46, 0x57, 0x58, 0x58, 0x58, 0x47, 0x74, 0x6B, 0x46, 0x75, 0x36, 0x4B, 0x52, 0x63, 0x6F, 0x4D, 0x51, 0x7A, 0x5A, 0x45, 0x4E, 0x64, 0x6C, 0x2F, 0x2F, 0x6E, 0x6B, 0x36, 0x48, 0x4F, 0x6A, 0x47, 0x35, 0x44, 0x31, 0x72, 0x64, 0x39, 0x51, ++ 0x68, 0x45, 0x4F, 0x50, 0x32, 0x0A, 0x38, 0x79, 0x42, 0x4F, 0x71, 0x62, 0x36, 0x4A, 0x38, 0x78, 0x79, 0x63, 0x71, 0x64, 0x2B, 0x38, 0x4D, 0x44, 0x6F, 0x58, 0x30, 0x54, 0x4A, 0x44, 0x30, 0x4B, 0x71, 0x4B, 0x63, 0x68, 0x78, 0x52, 0x4B, 0x45, ++ 0x7A, 0x64, 0x4E, 0x73, 0x6A, 0x6B, 0x4C, 0x57, 0x64, 0x39, 0x6B, 0x59, 0x63, 0x63, 0x6E, 0x62, 0x7A, 0x38, 0x71, 0x79, 0x69, 0x57, 0x58, 0x6D, 0x46, 0x63, 0x75, 0x43, 0x49, 0x7A, 0x47, 0x45, 0x67, 0x57, 0x55, 0x4F, 0x72, 0x4B, 0x4C, 0x2B, ++ 0x6D, 0x6C, 0x0A, 0x53, 0x64, 0x78, 0x2F, 0x50, 0x4B, 0x51, 0x5A, 0x76, 0x44, 0x61, 0x74, 0x6B, 0x75, 0x4B, 0x35, 0x39, 0x45, 0x76, 0x56, 0x36, 0x77, 0x69, 0x74, 0x35, 0x33, 0x6A, 0x2B, 0x46, 0x38, 0x42, 0x64, 0x68, 0x33, 0x66, 0x6F, 0x5A, ++ 0x33, 0x64, 0x50, 0x41, 0x47, 0x61, 0x76, 0x39, 0x4C, 0x45, 0x44, 0x4F, 0x72, 0x34, 0x53, 0x66, 0x45, 0x45, 0x31, 0x35, 0x66, 0x53, 0x6D, 0x47, 0x30, 0x65, 0x4C, 0x79, 0x33, 0x6E, 0x33, 0x31, 0x72, 0x38, 0x58, 0x62, 0x6B, 0x35, 0x6C, 0x0A, ++ 0x38, 0x50, 0x6A, 0x61, 0x56, 0x38, 0x47, 0x55, 0x67, 0x65, 0x56, 0x36, 0x56, 0x67, 0x32, 0x37, 0x52, 0x6E, 0x39, 0x76, 0x6B, 0x66, 0x31, 0x39, 0x35, 0x68, 0x66, 0x6B, 0x67, 0x53, 0x65, 0x37, 0x42, 0x59, 0x68, 0x57, 0x33, 0x53, 0x43, 0x6C, ++ 0x39, 0x35, 0x67, 0x74, 0x6B, 0x52, 0x6C, 0x70, 0x4D, 0x56, 0x2B, 0x62, 0x4D, 0x50, 0x4B, 0x5A, 0x72, 0x58, 0x4A, 0x41, 0x6C, 0x73, 0x7A, 0x59, 0x64, 0x32, 0x61, 0x62, 0x74, 0x4E, 0x55, 0x4F, 0x73, 0x68, 0x44, 0x2B, 0x0A, 0x46, 0x4B, 0x72, ++ 0x44, 0x67, 0x48, 0x47, 0x64, 0x50, 0x59, 0x33, 0x6F, 0x66, 0x52, 0x52, 0x73, 0x59, 0x57, 0x53, 0x47, 0x52, 0x71, 0x62, 0x58, 0x56, 0x4D, 0x57, 0x32, 0x31, 0x35, 0x41, 0x57, 0x52, 0x71, 0x57, 0x46, 0x79, 0x70, 0x34, 0x36, 0x34, 0x2B, 0x59, ++ 0x54, 0x46, 0x72, 0x59, 0x56, 0x49, 0x38, 0x79, 0x70, 0x4B, 0x56, 0x4C, 0x39, 0x41, 0x4D, 0x62, 0x32, 0x6B, 0x49, 0x35, 0x57, 0x6A, 0x34, 0x6B, 0x49, 0x33, 0x5A, 0x61, 0x71, 0x35, 0x74, 0x4E, 0x71, 0x0A, 0x71, 0x59, 0x59, 0x31, 0x39, 0x74, ++ 0x56, 0x46, 0x65, 0x45, 0x4A, 0x4B, 0x52, 0x76, 0x77, 0x44, 0x79, 0x46, 0x37, 0x59, 0x5A, 0x76, 0x5A, 0x46, 0x5A, 0x53, 0x53, 0x30, 0x76, 0x6F, 0x64, 0x37, 0x56, 0x53, 0x43, 0x64, 0x39, 0x35, 0x32, 0x31, 0x4B, 0x76, 0x79, 0x35, 0x59, 0x68, ++ 0x6E, 0x4C, 0x62, 0x44, 0x75, 0x76, 0x30, 0x32, 0x30, 0x34, 0x62, 0x4B, 0x74, 0x37, 0x70, 0x68, 0x36, 0x4E, 0x2F, 0x4F, 0x6D, 0x65, 0x2F, 0x6D, 0x73, 0x56, 0x75, 0x64, 0x75, 0x43, 0x0A, 0x6D, 0x73, 0x75, 0x59, 0x33, 0x33, 0x4F, 0x68, 0x6B, ++ 0x4B, 0x43, 0x67, 0x78, 0x65, 0x44, 0x6F, 0x41, 0x61, 0x69, 0x6A, 0x46, 0x4A, 0x7A, 0x49, 0x77, 0x5A, 0x71, 0x73, 0x46, 0x56, 0x41, 0x7A, 0x6A, 0x65, 0x31, 0x38, 0x4B, 0x6F, 0x74, 0x7A, 0x6C, 0x55, 0x42, 0x44, 0x4A, 0x76, 0x79, 0x42, 0x70, ++ 0x43, 0x70, 0x66, 0x4F, 0x5A, 0x43, 0x33, 0x4A, 0x38, 0x74, 0x52, 0x64, 0x2F, 0x69, 0x57, 0x6B, 0x78, 0x37, 0x50, 0x38, 0x6E, 0x64, 0x39, 0x48, 0x30, 0x61, 0x54, 0x0A, 0x6F, 0x6C, 0x6B, 0x65, 0x6C, 0x55, 0x54, 0x46, 0x4C, 0x58, 0x56, 0x6B, ++ 0x73, 0x4E, 0x62, 0x35, 0x34, 0x44, 0x78, 0x70, 0x36, 0x67, 0x53, 0x31, 0x48, 0x41, 0x76, 0x69, 0x52, 0x6B, 0x52, 0x4E, 0x51, 0x7A, 0x75, 0x58, 0x53, 0x58, 0x45, 0x52, 0x76, 0x53, 0x53, 0x32, 0x77, 0x71, 0x31, 0x79, 0x56, 0x41, 0x62, 0x2B, ++ 0x61, 0x78, 0x6A, 0x35, 0x64, 0x39, 0x73, 0x70, 0x4C, 0x46, 0x4B, 0x65, 0x62, 0x58, 0x64, 0x37, 0x59, 0x76, 0x30, 0x50, 0x54, 0x59, 0x36, 0x59, 0x0A, 0x4D, 0x6A, 0x41, 0x77, 0x63, 0x52, 0x4C, 0x57, 0x4A, 0x54, 0x58, 0x6A, 0x6E, 0x2F, 0x68, ++ 0x76, 0x6E, 0x4C, 0x58, 0x72, 0x61, 0x68, 0x75, 0x74, 0x36, 0x68, 0x44, 0x54, 0x6C, 0x68, 0x5A, 0x79, 0x42, 0x69, 0x45, 0x6C, 0x78, 0x6B, 0x79, 0x38, 0x6A, 0x33, 0x43, 0x37, 0x44, 0x4F, 0x52, 0x65, 0x49, 0x6F, 0x4D, 0x74, 0x30, 0x72, 0x37, ++ 0x2B, 0x68, 0x56, 0x75, 0x30, 0x35, 0x4C, 0x30, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x00 ++}; ++const size_t _accacert_len = sizeof(_accacert); ++/*************************** End of file ****************************/ +diff -rupbN melonDS.orig/src/frontend/qt_sdl/AchievementItemWidget.cpp melonDS.ra/src/frontend/qt_sdl/AchievementItemWidget.cpp +--- melonDS.orig/src/frontend/qt_sdl/AchievementItemWidget.cpp 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/frontend/qt_sdl/AchievementItemWidget.cpp 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,125 @@ ++#include "AchievementItemWidget.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++AchievementItemWidget::AchievementItemWidget( ++ const QString& title, ++ const QString& description, ++ bool unlocked, ++ bool measured, ++ const QString& progressText, ++ float progressPercent, ++ float uiScale, ++ QWidget* parent ++) : QWidget(parent) ++{ ++ uiScale = std::clamp(uiScale, 0.65f, 1.0f); ++ setAttribute(Qt::WA_StyledBackground, true); ++ setFocusPolicy(Qt::StrongFocus); ++ ++ setStyleSheet(R"( ++ AchievementItemWidget { ++ background: transparent; ++ border-bottom: 1px solid rgba(255, 255, 255, 15); ++ } ++ AchievementItemWidget:focus { ++ background: rgba(255, 255, 255, 25); ++ border: 1px solid rgba(255, 255, 255, 50); ++ } ++ )"); ++ ++ iconLabel = new QLabel(this); ++ int iconSize = int(64 * uiScale); ++ iconLabel->setFixedSize(iconSize, iconSize); ++ iconLabel->setScaledContents(true); ++ iconLabel->setStyleSheet("background: transparent; border: none;"); ++ iconLabel->setPixmap(QPixmap(unlocked ? ":/ra/unlocked.png" : ":/ra/locked.png")); ++ ++ auto* rightLayout = new QVBoxLayout(); ++ rightLayout->setSpacing(int(4 * uiScale)); ++ rightLayout->setContentsMargins(0, int(5 * uiScale), 0, int(5 * uiScale)); ++ ++ titleLabel = new QLabel(title, this); ++ titleLabel->setStyleSheet(QString( ++ "font-weight: bold; color: white; font-size: %1px; background: transparent; border: none;" ++ ).arg(int(15 * uiScale))); ++ titleLabel->setWordWrap(true); ++ rightLayout->addWidget(titleLabel); ++ ++ descLabel = new QLabel(description, this); ++ descLabel->setStyleSheet(QString( ++ "color: #ccc; font-size: %1px; background: transparent; border: none;" ++ ).arg(int(13 * uiScale))); ++ descLabel->setWordWrap(true); ++ rightLayout->addWidget(descLabel); ++ ++ progressBar = new QProgressBar(this); ++ int barHeight = int(14 * uiScale); ++ int barFont = int(10 * uiScale); ++ ++ progressBar->setStyleSheet(QString(R"( ++ QProgressBar { ++ border: none; ++ background: rgba(0, 0, 0, 100); ++ height: %1px; ++ border-radius: %2px; ++ color: white; ++ font-weight: bold; ++ font-size: %3px; ++ text-align: center; ++ } ++ QProgressBar::chunk { ++ background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #005c99, stop:1 #0099ff); ++ border-radius: %2px; ++ } ++ )").arg(barHeight).arg(barHeight / 2).arg(barFont)); ++ ++ bool showBar = measured || !progressText.isEmpty(); ++ progressBar->setVisible(showBar); ++ ++ if (showBar) { ++ progressBar->setRange(0, 100); ++ progressBar->setValue(static_cast(progressPercent)); ++ ++ if (progressText.isEmpty()) { ++ progressBar->setFormat("%p%"); ++ } else { ++ progressBar->setFormat(progressText); ++ } ++ } ++ ++ rightLayout->addWidget(progressBar); ++ ++ auto* mainLayout = new QHBoxLayout(this); ++ mainLayout->setContentsMargins( ++ int(10 * uiScale), ++ int(5 * uiScale), ++ int(10 * uiScale), ++ int(5 * uiScale) ++ ); ++ mainLayout->addWidget(iconLabel); ++ mainLayout->addLayout(rightLayout); ++} ++ ++void AchievementItemWidget::paintEvent(QPaintEvent* event) ++{ ++ QStyleOption opt; ++ opt.initFrom(this); ++ QPainter p(this); ++ style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); ++} ++ ++void AchievementItemWidget::updateIcon(const QPixmap& pix) { ++ if (!pix.isNull()) { ++ iconLabel->setPixmap(pix.scaled( ++ iconSize, iconSize, ++ Qt::KeepAspectRatio, ++ Qt::SmoothTransformation ++ )); ++ } ++} +diff -rupbN melonDS.orig/src/frontend/qt_sdl/AchievementItemWidget.h melonDS.ra/src/frontend/qt_sdl/AchievementItemWidget.h +--- melonDS.orig/src/frontend/qt_sdl/AchievementItemWidget.h 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/frontend/qt_sdl/AchievementItemWidget.h 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,34 @@ ++#pragma once ++#include ++#include ++ ++class QLabel; ++class QProgressBar; ++class QPaintEvent; ++ ++class AchievementItemWidget : public QWidget ++{ ++ Q_OBJECT ++public: ++ void updateIcon(const QPixmap& pix); ++ explicit AchievementItemWidget( ++ const QString& title, ++ const QString& description, ++ bool unlocked, ++ bool measured, ++ const QString& progressText, ++ float progressPercent, ++ float uiScale, ++ QWidget* parent = nullptr ++ ); ++ ++protected: ++ void paintEvent(QPaintEvent* event) override; ++ ++private: ++ int iconSize = 64; ++ QLabel* titleLabel; ++ QLabel* descLabel; ++ QLabel* iconLabel; ++ QProgressBar* progressBar; ++}; +\ No newline at end of file +diff -rupbN melonDS.orig/src/frontend/qt_sdl/CMakeLists.txt melonDS.ra/src/frontend/qt_sdl/CMakeLists.txt +--- melonDS.orig/src/frontend/qt_sdl/CMakeLists.txt 2026-03-06 21:36:14.554057405 +0000 ++++ melonDS.ra/src/frontend/qt_sdl/CMakeLists.txt 2026-03-06 21:37:07.046799886 +0000 +@@ -62,6 +62,22 @@ set(SOURCES_QT_SDL + NetplayDialog.cpp + ) + ++if (ENABLE_RETROACHIEVEMENTS) ++ list(APPEND SOURCES_QT_SDL ++ toast/ToastManager.cpp ++ toast/ToastManager.h ++ toast/ToastOverlay.cpp ++ toast/ToastOverlay.h ++ toast/BadgeCache.h ++ toast/BadgeCache.cpp ++ retroachievements/resources/ra.qrc ++ RASettingsDialog.cpp ++ RAOverlayWidget.cpp ++ AchievementItemWidget.cpp ++ ) ++ add_compile_definitions(RETROACHIEVEMENTS_ENABLED) ++endif() ++ + option(USE_QT6 "Use Qt 6 instead of Qt 5" ON) + + if (USE_QT6) +diff -rupbN melonDS.orig/src/frontend/qt_sdl/Config.cpp melonDS.ra/src/frontend/qt_sdl/Config.cpp +--- melonDS.orig/src/frontend/qt_sdl/Config.cpp 2026-03-06 21:36:14.558057462 +0000 ++++ melonDS.ra/src/frontend/qt_sdl/Config.cpp 2026-03-06 21:37:07.046799886 +0000 +@@ -103,6 +103,10 @@ DefaultList DefaultBools = + {"Emu.DirectBoot", true}, + {"Instance*.DS.Battery.LevelOkay", true}, + {"Instance*.DSi.Battery.Charging", true}, ++//#ifdef RETROACHIEVEMENTS_ENABLED ++// {"Instance*.RetroAchievements.Enabled", true}, ++// {"Instance*.RetroAchievements.HardcoreMode", false}, ++//#endif + #ifdef JIT_ENABLED + {"JIT.BranchOptimisations", true}, + {"JIT.LiteralOptimisations", true}, +@@ -117,6 +121,11 @@ DefaultList DefaultStrings + { + {"DLDI.ImagePath", "dldi.bin"}, + {"DSi.SD.ImagePath", "dsisd.bin"}, ++ //#ifdef RETROACHIEVEMENTS_ENABLED ++ //{"Instance*.RetroAchievements.Username", ""}, ++ //{"Instance*.RetroAchievements.Password", ""}, ++ //{"Instance*.RetroAchievements.Token", ""}, ++ //#endif + {"Instance*.Firmware.Username", "melonDS"} + }; + +@@ -162,6 +171,9 @@ LegacyEntry LegacyFile[] = + {"HKKey_FastForward", 0, "Keyboard.HK_FastForward", true}, + {"HKKey_FastForwardToggle", 0, "Keyboard.HK_FrameLimitToggle", true}, + {"HKKey_FullscreenToggle", 0, "Keyboard.HK_FullscreenToggle", true}, ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ {"HKKey_RAOverlayToggle", 0, "Keyboard.HK_RAOverlayToggle", true}, ++ #endif + {"HKKey_SwapScreens", 0, "Keyboard.HK_SwapScreens", true}, + {"HKKey_SwapScreenEmphasis", 0, "Keyboard.HK_SwapScreenEmphasis", true}, + {"HKKey_SolarSensorDecrease", 0, "Keyboard.HK_SolarSensorDecrease", true}, +@@ -182,6 +194,9 @@ LegacyEntry LegacyFile[] = + {"HKJoy_FastForward", 0, "Joystick.HK_FastForward", true}, + {"HKJoy_FastForwardToggle", 0, "Joystick.HK_FrameLimitToggle", true}, + {"HKJoy_FullscreenToggle", 0, "Joystick.HK_FullscreenToggle", true}, ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ {"HKJoy_RAOverlayToggle", 0, "Joystick.HK_RAOverlayToggle", true}, ++ #endif + {"HKJoy_SwapScreens", 0, "Joystick.HK_SwapScreens", true}, + {"HKJoy_SwapScreenEmphasis", 0, "Joystick.HK_SwapScreenEmphasis", true}, + {"HKJoy_SolarSensorDecrease", 0, "Joystick.HK_SolarSensorDecrease", true}, +@@ -332,7 +347,19 @@ LegacyEntry LegacyFile[] = + {"Camera1_ImagePath", 2, "DSi.Camera1.ImagePath", false}, + {"Camera1_CamDeviceName", 2, "DSi.Camera1.DeviceName", false}, + {"Camera1_XFlip", 1, "DSi.Camera1.XFlip", false}, +- ++#ifdef RETROACHIEVEMENTS_ENABLED ++ {"RA_Enabled", 1, "RetroAchievements.Enabled", true}, ++ {"RA_Username", 2, "RetroAchievements.Username", true}, ++ {"RA_Password", 2, "RetroAchievements.Password", true}, ++ {"RA_Token", 2, "RetroAchievements.Token", true}, ++ {"RA_HardcoreMode", 1, "RetroAchievements.HardcoreMode", true}, ++ {"RA_EncoreMode", 1, "RetroAchievements.EncoreMode", true}, ++ {"RA_Unofficial", 1, "RetroAchievements.Unofficial", true}, ++ {"RA_HideLeaderboardToasts", 1, "RetroAchievements.HideLeaderboardToasts", true}, ++ {"RA_HideChallengeIndicators", 1, "RetroAchievements.HideChallengeIndicators", true}, ++ {"RA_HideToasts", 1, "RetroAchievements.HideToasts", true}, ++ {"RA_HideLeaderboardCounter", 1, "RetroAchievements.HideLeaderboardCounter", true}, ++#endif + {"", -1, "", false} + }; + +@@ -831,4 +858,17 @@ Table GetLocalTable(int instance) + return Table(tbl, key); + } + ++#ifdef RETROACHIEVEMENTS_ENABLED ++Table GetRAPlaytimeTable() ++{ ++ std::string key = "RetroAchievements.Playtime"; ++ toml::value& tbl = RootTable["RetroAchievements"]["Playtime"]; ++ ++ if (!tbl.is_table()) ++ tbl = toml::table(); ++ ++ return Table(tbl, key); ++} ++#endif ++ + } +diff -rupbN melonDS.orig/src/frontend/qt_sdl/Config.h melonDS.ra/src/frontend/qt_sdl/Config.h +--- melonDS.orig/src/frontend/qt_sdl/Config.h 2026-03-06 21:36:14.558057462 +0000 ++++ melonDS.ra/src/frontend/qt_sdl/Config.h 2026-03-06 21:37:07.046799886 +0000 +@@ -92,6 +92,13 @@ public: + Table(toml::value& data, const std::string& path); + ~Table() {} + ++ //#ifdef RETROACHIEVEMENTS_ENABLED ++ //bool RA_Enabled = false; ++ //bool RA_HardcoreMode = false; ++ //std::string RA_Username; ++ //std::string RA_Password; ++ //#endif ++ + Table& operator=(const Table& b); + + Array GetArray(const std::string& path); +@@ -134,6 +141,9 @@ bool Load(); + void Save(); + + Table GetLocalTable(int instance); ++#ifdef RETROACHIEVEMENTS_ENABLED ++Table GetRAPlaytimeTable(); ++#endif + inline Table GetGlobalTable() { return GetLocalTable(-1); } + + } +diff -rupbN melonDS.orig/src/frontend/qt_sdl/EmuInstance.cpp melonDS.ra/src/frontend/qt_sdl/EmuInstance.cpp +--- melonDS.orig/src/frontend/qt_sdl/EmuInstance.cpp 2026-03-06 21:36:14.558057462 +0000 ++++ melonDS.ra/src/frontend/qt_sdl/EmuInstance.cpp 2026-03-06 21:37:07.046799886 +0000 +@@ -48,6 +48,10 @@ + #include "FreeBIOS.h" + #include "main.h" + ++#ifdef RETROACHIEVEMENTS_ENABLED ++#include "../../RetroAchievements/RAClient.h" ++#endif ++ + using std::make_unique; + using std::pair; + using std::string; +@@ -136,6 +140,10 @@ EmuInstance::EmuInstance(int inst) : del + for (int i = 0; i < kMaxWindows; i++) + windowList[i] = nullptr; + ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ ra = std::make_unique(); ++ #endif ++ + if (inst == 0) topWindow = nullptr; + createWindow(); + +@@ -158,6 +166,10 @@ EmuInstance::~EmuInstance() + + emuThread->emuExit(); + emuThread->wait(); ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ RAContext* ra = getRA(); ++ ra->Shutdown(); ++ #endif + delete emuThread; + + net.UnregisterInstance(instanceID); +@@ -222,6 +234,12 @@ void EmuInstance::createWindow(int id) + { + win->actNewWindow->setEnabled(enable); + }); ++ if (id == 0) ++ { ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ SyncRetroAchievementsFromConfig(); ++ #endif ++ } + } + + void EmuInstance::deleteWindow(int id, bool close) +@@ -1335,6 +1353,13 @@ bool EmuInstance::updateConsole() noexce + else + nds = new NDS(std::move(ndsargs), this); + ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ if (ra) ++ { ++ nds->SetRAContext(ra.get()); ++ } ++ #endif ++ + nds->Reset(); + loadRTCData(); + emuThread->updateVideoRenderer(); +@@ -2256,3 +2281,30 @@ void EmuInstance::animatedROMIcon(const + animatedSequenceRef.push_back(i); + } + } ++#ifdef RETROACHIEVEMENTS_ENABLED ++ ++void EmuInstance::SyncRetroAchievementsFromConfig() ++{ ++ auto& cfg = getLocalConfig(); ++ ++ if (!ra) ++ return; ++ ++ if (!cfg.GetBool("RetroAchievements.Enabled")) ++ { ++ ra->Disable(); ++ return; ++ } ++ ++ ra->SetCredentials( ++ cfg.GetString("RetroAchievements.Username").c_str(), ++ cfg.GetString("RetroAchievements.Password").c_str(), ++ cfg.GetBool("RetroAchievements.HardcoreMode") ++ ); ++ ++ ra->SetEncoreMode(cfg.GetBool("RetroAchievements.EncoreMode")); ++ ra->SetUnofficialEnabled(cfg.GetBool("RetroAchievements.Unofficial")); ++ ++ ra->Enable(); ++} ++#endif +\ No newline at end of file +diff -rupbN melonDS.orig/src/frontend/qt_sdl/EmuInstance.h melonDS.ra/src/frontend/qt_sdl/EmuInstance.h +--- melonDS.orig/src/frontend/qt_sdl/EmuInstance.h 2026-03-06 21:36:14.558057462 +0000 ++++ melonDS.ra/src/frontend/qt_sdl/EmuInstance.h 2026-03-06 21:37:07.046799886 +0000 +@@ -29,6 +29,10 @@ + #include "Config.h" + #include "SaveManager.h" + ++#ifdef RETROACHIEVEMENTS_ENABLED ++#include "../../RetroAchievements/RAClient.h" ++#endif ++ + const int kMaxWindows = 4; + + enum +@@ -56,6 +60,9 @@ enum + HK_GuitarGripRed, + HK_GuitarGripYellow, + HK_GuitarGripBlue, ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ HK_RAOverlayToggle, ++ #endif + HK_MAX + }; + +@@ -84,6 +91,17 @@ int getEventKeyVal(QKeyEvent* event); + class EmuInstance + { + public: ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ bool isOverlayActive() const { return overlayActive; } ++ void setOverlayActive(bool v) { overlayActive = v; } ++ void setRAOverlay(RAOverlayWidget* overlay) { raOverlay = overlay; } ++ RAOverlayWidget* getRAOverlay() const { return raOverlay; } ++ RAContext* getRA() const { return ra.get(); } ++ std::unique_ptr ra; ++ void SyncRetroAchievementsFromConfig(); ++ bool overlayActive = false; ++ RAOverlayWidget* raOverlay = nullptr; ++ #endif + EmuInstance(int inst); + ~EmuInstance(); + +@@ -379,6 +397,9 @@ private: + + friend class EmuThread; + friend class MainWindow; ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ friend class RAOverlayWidget; ++ #endif + }; + + #endif //EMUINSTANCE_H +diff -rupbN melonDS.orig/src/frontend/qt_sdl/EmuInstanceInput.cpp melonDS.ra/src/frontend/qt_sdl/EmuInstanceInput.cpp +--- melonDS.orig/src/frontend/qt_sdl/EmuInstanceInput.cpp 2026-03-06 21:36:14.558057462 +0000 ++++ melonDS.ra/src/frontend/qt_sdl/EmuInstanceInput.cpp 2026-03-06 21:37:07.046799886 +0000 +@@ -52,6 +52,9 @@ const char* EmuInstance::hotkeyNames[HK_ + "HK_FastForward", + "HK_FrameLimitToggle", + "HK_FullscreenToggle", ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ "HK_RAOverlayToggle", ++ #endif + "HK_SwapScreens", + "HK_SwapScreenEmphasis", + "HK_SolarSensorDecrease", +@@ -439,6 +442,22 @@ void EmuInstance::inputProcess() + joyInputMask &= ~(1 << i); + } + ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ static u32 lastJoyInputMask = 0xFFF; ++ u32 joyPress = lastJoyInputMask & ~joyInputMask; ++ lastJoyInputMask = joyInputMask; ++ ++ if (overlayActive && raOverlay && raOverlay->isVisible()) ++ { ++ uint32_t padState = ~joyInputMask & 0xFFF; ++ raOverlay->updateJoystick(padState); ++ ++ inputMask = 0xFFF; ++ keyInputMask = 0xFFF; ++ joyInputMask = 0xFFF; ++ } ++ #endif ++ + inputMask = keyInputMask & joyInputMask; + + joyHotkeyMask = 0; +diff -rupbN melonDS.orig/src/frontend/qt_sdl/EmuThread.cpp melonDS.ra/src/frontend/qt_sdl/EmuThread.cpp +--- melonDS.orig/src/frontend/qt_sdl/EmuThread.cpp 2026-03-06 21:36:14.558057462 +0000 ++++ melonDS.ra/src/frontend/qt_sdl/EmuThread.cpp 2026-03-06 21:37:07.046799886 +0000 +@@ -51,6 +51,10 @@ + #include "GPU_Soft.h" + #include "GPU_OpenGL.h" + ++#ifdef RETROACHIEVEMENTS_ENABLED ++#include "../../RetroAchievements/RAClient.h" ++#endif ++ + #include "Savestate.h" + + #include "EmuInstance.h" +@@ -76,6 +80,9 @@ void EmuThread::attachWindow(MainWindow* + connect(this, SIGNAL(windowEmuReset()), window, SLOT(onEmuReset())); + connect(this, SIGNAL(autoScreenSizingChange(int)), window->panel, SLOT(onAutoScreenSizingChanged(int))); + connect(this, SIGNAL(windowFullscreenToggle()), window, SLOT(onFullscreenToggled())); ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ connect(this, SIGNAL(RAOverlayToggle()), window, SLOT(onRAOverlayToggled())); ++ #endif + connect(this, SIGNAL(screenEmphasisToggle()), window, SLOT(onScreenEmphasisToggled())); + + if (window->winHasMenu()) +@@ -94,6 +101,9 @@ void EmuThread::detachWindow(MainWindow* + disconnect(this, SIGNAL(windowEmuReset()), window, SLOT(onEmuReset())); + disconnect(this, SIGNAL(autoScreenSizingChange(int)), window->panel, SLOT(onAutoScreenSizingChanged(int))); + disconnect(this, SIGNAL(windowFullscreenToggle()), window, SLOT(onFullscreenToggled())); ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ disconnect(this, SIGNAL(RAOverlayToggle()), window, SLOT(onRAOverlayToggled())); ++ #endif + disconnect(this, SIGNAL(screenEmphasisToggle()), window, SLOT(onScreenEmphasisToggled())); + + if (window->winHasMenu()) +@@ -165,6 +175,9 @@ void EmuThread::run() + + if (emuInstance->hotkeyPressed(HK_FullscreenToggle)) emit windowFullscreenToggle(); + ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ if (emuInstance->hotkeyPressed(HK_RAOverlayToggle)) emit RAOverlayToggle(); ++ #endif + if (emuInstance->hotkeyPressed(HK_SwapScreens)) emit swapScreensToggle(); + if (emuInstance->hotkeyPressed(HK_SwapScreenEmphasis)) emit screenEmphasisToggle(); + +@@ -330,6 +343,18 @@ void EmuThread::run() + winUpdateCount = 0; + } + ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ if (Config::GetGlobalTable().GetBool("RetroAchievements.Enabled") && ++ Config::GetGlobalTable().GetBool("RetroAchievements.HardcoreMode")) { ++ if (emuInstance->hotkeyPressed(HK_FastForwardToggle) || emuInstance->hotkeyPressed(HK_FastForward)) { ++ emuInstance->osdAddMessage(0xFFA0A0, "HARDCORE: Fast Forward is blocked!"); ++ } ++ if (emuInstance->hotkeyPressed(HK_SlowMoToggle) || emuInstance->hotkeyPressed(HK_SlowMo)) { ++ emuInstance->osdAddMessage(0xFFA0A0, "HARDCORE: Slow-mo is blocked!"); ++ } ++ } ++ #endif ++ + if (emuInstance->hotkeyPressed(HK_FastForwardToggle)) emuInstance->fastForwardToggled = !emuInstance->fastForwardToggled; + if (emuInstance->hotkeyPressed(HK_SlowMoToggle)) emuInstance->slowmoToggled = !emuInstance->slowmoToggled; + +@@ -338,6 +363,16 @@ void EmuThread::run() + bool enablefastforward = emuInstance->hotkeyDown(HK_FastForward) | emuInstance->fastForwardToggled; + bool enableslowmo = emuInstance->hotkeyDown(HK_SlowMo) | emuInstance->slowmoToggled; + ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ if (Config::GetGlobalTable().GetBool("RetroAchievements.Enabled") && ++ Config::GetGlobalTable().GetBool("RetroAchievements.HardcoreMode")) { ++ enablefastforward = false; ++ enableslowmo = false; ++ emuInstance->fastForwardToggled = false; ++ emuInstance->slowmoToggled = false; ++ } ++ #endif ++ + if (useOpenGL) + { + // when using OpenGL: when toggling fast-forward or slowmo, change the vsync interval +@@ -614,19 +649,51 @@ void EmuThread::handleMessages() + break; + + case msg_SaveState: ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ if (Config::GetGlobalTable().GetBool("RetroAchievements.Enabled") && ++ Config::GetGlobalTable().GetBool("RetroAchievements.HardcoreMode")) ++ { ++ emuInstance->osdAddMessage(0xFFA0A0, "Hardcore: Save states are disabled"); ++ break; ++ } ++ #endif + msgResult = emuInstance->saveState(msg.param.value().toStdString()); + break; + + case msg_LoadState: ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ if (Config::GetGlobalTable().GetBool("RetroAchievements.Enabled") && ++ Config::GetGlobalTable().GetBool("RetroAchievements.HardcoreMode")) ++ { ++ emuInstance->osdAddMessage(0xFFA0A0, "Hardcore: Load states are disabled"); ++ break; ++ } ++ #endif + msgResult = emuInstance->loadState(msg.param.value().toStdString()); + break; + + case msg_UndoStateLoad: ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ if (Config::GetGlobalTable().GetBool("RetroAchievements.Enabled") && ++ Config::GetGlobalTable().GetBool("RetroAchievements.HardcoreMode")) ++ { ++ emuInstance->osdAddMessage(0xFFA0A0, "Hardcore: Undo load is disabled"); ++ break; ++ } ++ #endif + emuInstance->undoStateLoad(); + msgResult = 1; + break; + + case msg_ImportSavefile: ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ if (Config::GetGlobalTable().GetBool("RetroAchievements.Enabled") && ++ Config::GetGlobalTable().GetBool("RetroAchievements.HardcoreMode")) ++ { ++ emuInstance->osdAddMessage(0xFFA0A0, "Hardcore: Importing savefiles is disabled"); ++ break; ++ } ++ #endif + { + msgResult = 0; + auto f = Platform::OpenFile(msg.param.value().toStdString(), Platform::FileMode::Read); +@@ -647,6 +714,14 @@ void EmuThread::handleMessages() + break; + + case msg_EnableCheats: ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ if (Config::GetGlobalTable().GetBool("RetroAchievements.Enabled") && ++ Config::GetGlobalTable().GetBool("RetroAchievements.HardcoreMode")) ++ { ++ emuInstance->osdAddMessage(0xFFA0A0, "HARDCORE: Cheats are forbidden!"); ++ break; ++ } ++ #endif + emuInstance->enableCheats(msg.param.value()); + break; + } +@@ -701,6 +776,26 @@ void EmuThread::emuRun() + + void EmuThread::emuPause(bool broadcast) + { ++#ifdef RETROACHIEVEMENTS_ENABLED ++ RAContext* ra = emuInstance->getRA(); ++ if (ra && ra->IsHardcoreEnabled()) ++ { ++ uint32_t frames_left = 0; ++ if (!ra->CanPause(&frames_left)) ++ { ++ if (frames_left > 0) ++ { ++ float seconds = frames_left / 60.0f; ++ emuInstance->osdAddMessage( ++ 0xFFA0A0, ++ "Hardcore: Wait %.1f seconds to pause", ++ seconds ++ ); ++ } ++ return; ++ } ++ } ++#endif + sendMessage(msg_EmuPause); + waitMessage(); + +@@ -739,6 +834,14 @@ void EmuThread::emuExit() + + void EmuThread::emuFrameStep() + { ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ RAContext* ra = emuInstance->getRA(); ++ if (ra->IsHardcoreEnabled()) ++ { ++ emuInstance->osdAddMessage(0xFFA0A0, "Frame step is disabled in Hardcore Mode"); ++ return; ++ } ++ #endif + if (emuPauseStack < emuPauseStackPauseThreshold) + sendMessage(msg_EmuPause); + sendMessage(msg_EmuFrameStep); +diff -rupbN melonDS.orig/src/frontend/qt_sdl/EmuThread.h melonDS.ra/src/frontend/qt_sdl/EmuThread.h +--- melonDS.orig/src/frontend/qt_sdl/EmuThread.h 2026-03-06 21:36:14.558057462 +0000 ++++ melonDS.ra/src/frontend/qt_sdl/EmuThread.h 2026-03-06 21:37:07.046799886 +0000 +@@ -155,6 +155,9 @@ signals: + + void windowFullscreenToggle(); + ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ void RAOverlayToggle(); ++ #endif + void swapScreensToggle(); + void screenEmphasisToggle(); + +diff -rupbN melonDS.orig/src/frontend/qt_sdl/InputConfig/InputConfigDialog.h melonDS.ra/src/frontend/qt_sdl/InputConfig/InputConfigDialog.h +--- melonDS.orig/src/frontend/qt_sdl/InputConfig/InputConfigDialog.h 2026-03-06 21:36:14.558057462 +0000 ++++ melonDS.ra/src/frontend/qt_sdl/InputConfig/InputConfigDialog.h 2026-03-06 21:37:07.046799886 +0000 +@@ -61,6 +61,9 @@ static constexpr std::initializer_list ++#include "RetroAchievements/RAClient.h" ++#include "EmuInstance.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "Config.h" ++#include ++#include ++#include ++#include ++#include ++ ++QWidget* RAOverlayWidget::CreateCollapsibleSection(const QString& title, int count, QVBoxLayout** innerLayout) { ++ QPushButton* btn = new QPushButton(); ++ btn->setCheckable(true); ++ ++ btn->setStyleSheet( ++ "QPushButton {" ++ " background-color: #333;" ++ " color: #eee;" ++ " border: 1px solid #444;" ++ " border-radius: 4px;" ++ " padding: 5px;" ++ " text-align: left;" ++ " font-weight: bold;" ++ "}" ++ "QPushButton:hover {" ++ " background-color: #444;" ++ " border: 1px solid #666;" ++ "}" ++ "QPushButton:focus {" ++ " background-color: #555;" ++ " border: 2px solid #0078d7;" ++ "}" ++ ); ++ ++ bool isCollapsed = collapsedSections.count(title) > 0; ++ btn->setChecked(isCollapsed); ++ ++ QWidget* container = new QWidget(); ++ *innerLayout = new QVBoxLayout(container); ++ (*innerLayout)->setContentsMargins(10, 0, 0, 5); ++ (*innerLayout)->setSpacing(2); ++ ++ auto updateBtnText = [btn, title, count](bool collapsed) { ++ btn->setText(QString("%1 %2 (%3)").arg(collapsed ? "▶" : "▼").arg(title).arg(count)); ++ }; ++ ++ container->setVisible(!isCollapsed); ++ updateBtnText(isCollapsed); ++ ++ listLayout->addWidget(btn); ++ listLayout->addWidget(container); ++ ++ connect(btn, &QPushButton::toggled, [this, title, container, updateBtnText, count](bool checked) { ++ container->setVisible(!checked); ++ updateBtnText(checked); ++ ++ if (checked) collapsedSections.insert(title); ++ else collapsedSections.erase(title); ++ }); ++ ++ return container; ++} ++ ++RAOverlayWidget::RAOverlayWidget(EmuInstance* emu, QWidget* parent) ++ : QGraphicsView(parent), emuInstance(emu) ++{ ++ netManager = new QNetworkAccessManager(this); ++ setWindowFlags(Qt::FramelessWindowHint | Qt::SubWindow); ++ setAttribute(Qt::WA_TranslucentBackground); ++ setStyleSheet("background: rgba(0, 0, 0, 150); border: none;"); ++ setFrameShape(QFrame::NoFrame); ++ setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); ++ setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); ++ setFocusPolicy(Qt::StrongFocus); ++ ++ scene = new QGraphicsScene(this); ++ setScene(scene); ++ ++ scene->setBackgroundBrush(QColor(0, 0, 0, 150)); ++ ++ contentWidget = new QWidget(); ++ contentWidget->setAttribute(Qt::WA_TranslucentBackground); ++ contentWidget->setStyleSheet("background: rgba(0, 0, 0, 160); border: 1px solid rgba(255, 255, 255, 30); color: white;"); ++ ++ if (parent && parent->window()) ++ parent->window()->installEventFilter(this); ++ ++ auto* root = new QVBoxLayout(contentWidget); ++ root->setContentsMargins(20, 20, 20, 20); ++ root->setSpacing(15); ++ ++ auto* headerBar = new QHBoxLayout(); ++ headerBar->setSpacing(10); ++ ++ avatarLabel = new QLabel(); ++ avatarLabel->setFixedSize(48, 48); ++ avatarLabel->setStyleSheet("background: #555; border-radius: 24px; border: 2px solid #ffcc00;"); ++ avatarLabel->setScaledContents(true); ++ ++ usernameLabel = new QLabel("Not Logged In"); ++ usernameLabel->setStyleSheet("color: white; font-size: 16px; font-weight: bold; background: transparent; border: none;"); ++ ++ gameTitleLabel = new QLabel("No Game"); ++ gameTitleLabel->setStyleSheet("color: #ddd; font-size: 16px; background: transparent; border: none;"); ++ gameTitleLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter); ++ ++ gameImgLabel = new QLabel(); ++ gameImgLabel->setFixedSize(48, 48); ++ gameImgLabel->setStyleSheet("background: #333; border-radius: 4px;"); ++ gameImgLabel->setScaledContents(true); ++ ++ timeLabel = new QLabel("--:--"); ++ timeLabel->setStyleSheet("color: #ffffff; font-size: 14px; font-family: monospace; background: transparent; border: none;"); ++ ++ playtimeLabel = new QLabel(""); ++ playtimeLabel->setStyleSheet("color: #ffffff; font-size: 11px; background: transparent; border: none;"); ++ playtimeLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter); ++ ++ headerBar->addWidget(playtimeLabel); ++ headerBar->addSpacing(10); ++ headerBar->addWidget(avatarLabel); ++ headerBar->addWidget(usernameLabel); ++ headerBar->addStretch(); ++ headerBar->addWidget(gameTitleLabel); ++ headerBar->addSpacing(10); ++ headerBar->addWidget(gameImgLabel); ++ headerBar->addSpacing(20); ++ headerBar->addWidget(timeLabel); ++ root->addLayout(headerBar); ++ ++ QLabel* title = new QLabel("Achievements"); ++ title->setAlignment(Qt::AlignCenter); ++ title->setStyleSheet("font-size: 28px; font-weight: bold; color: #ffffff; margin-top: 5px; margin-bottom: 10px; background: transparent; border: none;"); ++ root->addWidget(title); ++ ++ QScrollArea* scroll = new QScrollArea; ++ scroll->setWidgetResizable(true); ++ scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); ++ scroll->setFrameShape(QFrame::NoFrame); ++ ++ float scale = 1.0f; ++ if (parent && parent->window()) { ++ constexpr float refShortSide = 384.0f; ++ float shortSide = std::min(parent->window()->width(), parent->window()->height()); ++ scale = std::clamp(shortSide / refShortSide, 0.65f, 1.25f); ++ } ++ ++ int scrollWidth = std::clamp(int(10 * scale), 8, 14); ++ int radius = scrollWidth / 2; ++ ++ scroll->setStyleSheet(QString( ++ "QScrollArea { background: transparent; border: none; }" ++ "QScrollBar:vertical {" ++ " background: #2d2d2d;" ++ " width: %1px;" ++ " border-radius: %2px;" ++ " margin: 0px;" ++ "}" ++ "QScrollBar::handle:vertical {" ++ " background: #555;" ++ " border-radius: %2px;" ++ " min-height: 25px;" ++ "}" ++ "QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical { height: 0px; }" ++ ).arg(scrollWidth).arg(radius)); ++ ++ listContainer = new QWidget; ++ listLayout = new QVBoxLayout(listContainer); ++ listLayout->setSpacing(5); ++ listLayout->setContentsMargins(0, 0, 0, 0); ++ listLayout->setAlignment(Qt::AlignTop); ++ ++ scroll->setWidget(listContainer); ++ root->addWidget(scroll, 1); ++ ++ proxy = scene->addWidget(contentWidget); ++ ++ if (auto* ra = emuInstance->getRA()) { ++ ra->SetOnMeasuredProgress([this](unsigned, unsigned, unsigned, const char*) { ++ QMetaObject::invokeMethod(this, [this]() { if (isVisible()) refresh(); }); ++ }); ++ } ++ ++ clockTimer = new QTimer(this); ++ connect(clockTimer, &QTimer::timeout, this, &RAOverlayWidget::updateClock); ++ clockTimer->start(1000); ++ updateClock(); ++} ++ ++RAOverlayWidget::~RAOverlayWidget() { ++ if (clockTimer) clockTimer->stop(); ++ if (emuInstance && emuInstance->getRA()) emuInstance->getRA()->SetOnMeasuredProgress(nullptr); ++} ++ ++void RAOverlayWidget::toggle() { ++ m_isOpen = !m_isOpen; ++ if (isVisible()) { ++ hide(); ++ emuInstance->overlayActive = false; ++ if (parentWidget()) parentWidget()->setFocus(Qt::OtherFocusReason); ++ } else { ++ int instanceID = emuInstance->getInstanceID(); ++ Config::Table cfg = Config::GetLocalTable(instanceID); ++ int rotMode = cfg.GetInt("Window0.ScreenRotation"); ++ m_currentRotation = rotMode * 90; ++ ++ if (parentWidget()) { ++ QRect pRect = parentWidget()->rect(); ++ setGeometry(pRect); ++ scene->setSceneRect(0, 0, pRect.width(), pRect.height()); ++ proxy->setRotation(0); ++ proxy->setPos(0, 0); ++ ++ if (rotMode == 1 || rotMode == 3) { ++ contentWidget->setFixedSize(pRect.height(), pRect.width()); ++ proxy->setRotation(m_currentRotation); ++ if (rotMode == 1) proxy->setPos(pRect.width(), 0); ++ else if (rotMode == 3) proxy->setPos(0, pRect.height()); ++ } else { ++ contentWidget->setFixedSize(pRect.size()); ++ if (rotMode == 2) { proxy->setRotation(180); proxy->setPos(pRect.width(), pRect.height()); } ++ } ++ } ++ ApplyRotationAndResize(); ++ refresh(); ++ show(); ++ raise(); ++ setFocus(); ++ emuInstance->overlayActive = true; ++ } ++} ++ ++void RAOverlayWidget::refresh() { ++ RAContext* ra = emuInstance->getRA(); ++ if (!ra) return; ++ ++ QRect r = contentWidget->rect(); ++ int shortSide = std::min(r.width(), r.height()); ++ ++ float uiScale = shortSide / 600.0f; ++ uiScale = std::clamp(uiScale, 0.65f, 1.0f); ++ ++ if (ra->IsLoggedIn()) { ++ usernameLabel->setText(QString::fromStdString(ra->GetUser())); ++ const char* picUrl = ra->GetUserPicURL(); ++ if (picUrl) LoadHeaderImage(avatarLabel, picUrl, QSize(48, 48)); ++ } ++ ++ if (ra->IsGameLoaded()) { ++ QString titleStr = QString::fromUtf8(ra->GetGameTitle()); ++ if (titleStr.length() > 30) titleStr = titleStr.left(27) + "..."; ++ gameTitleLabel->setText(titleStr); ++ const char* iconUrl = ra->GetGameIconURL(); ++ if (iconUrl) LoadHeaderImage(gameImgLabel, iconUrl, QSize(48, 48)); ++ } ++ ++ int hours = 0; ++ int mins = 0; ++ ++ if (ra->IsGameLoaded()) { ++ auto* gameInfo = ra->GetCurrentGameInfo(); ++ uint32_t gameID = gameInfo ? gameInfo->id : 0; ++ ++ if (gameID != 0) { ++ std::string gameKey = std::to_string(gameID); ++ int totalSeconds = Config::GetRAPlaytimeTable().GetInt(gameKey); ++ ++ hours = totalSeconds / 3600; ++ mins = (totalSeconds % 3600) / 60; ++ } ++ } ++ ++ QString playtimeStr; ++ if (hours > 0) { ++ playtimeStr = QString("Playtime: %1h %2m").arg(hours).arg(mins); ++ } else { ++ playtimeStr = QString("Playtime: %1m").arg(mins); ++ } ++ ++ playtimeLabel->setText(playtimeStr); ++ playtimeLabel->show(); ++ ++ if (contentWidget) { ++ contentWidget->setFocus(); ++ } ++ ++ QLayoutItem* child; ++ while ((child = listLayout->takeAt(0)) != nullptr) { ++ if (QWidget* w = child->widget()) { ++ w->hide(); ++ w->setFocusPolicy(Qt::NoFocus); ++ w->deleteLater(); ++ } ++ delete child; ++ } ++ ++ if (!ra->IsGameLoaded()) { ++ QLabel* info = new QLabel("Load a game with RetroAchievements support."); ++ info->setStyleSheet("color: #aaa; background: transparent; border: none;"); ++ info->setAlignment(Qt::AlignCenter); ++ listLayout->addWidget(info); ++ } else { ++ const auto& achievements = ra->GetAllAchievements(); ++ if (!achievements.empty()) { ++ QVector unlockedList; ++ QVector inProgressList; ++ QVector lockedList; ++ ++ for (const auto& ach : achievements) { ++ if (ach.unlocked) { ++ unlockedList.append(&ach); ++ } else { ++ bool hasProgress = ach.measured || !ach.progressText.empty(); ++ if (hasProgress) inProgressList.append(&ach); ++ else lockedList.append(&ach); ++ } ++ } ++ ++ if (!unlockedList.isEmpty()) { ++ QVBoxLayout* uLayout = nullptr; ++ CreateCollapsibleSection("Unlocked", unlockedList.size(), &uLayout); ++ for (const auto* ach : unlockedList) { ++ auto* item = new AchievementItemWidget(QString::fromUtf8(ach->title.c_str()), QString::fromUtf8(ach->description.c_str()), true, false, "", 0.0f, uiScale, listContainer); ++ uLayout->addWidget(item); ++ if (ach->badge_url && ach->badge_url[0] != '\0') SetBadgeImage(item, ach->badge_url); ++ } ++ } ++ ++ if (!inProgressList.isEmpty()) { ++ QVBoxLayout* pLayout = nullptr; ++ CreateCollapsibleSection("In Progress", inProgressList.size(), &pLayout); ++ for (const auto* ach : inProgressList) { ++ auto* item = new AchievementItemWidget(QString::fromUtf8(ach->title.c_str()), QString::fromUtf8(ach->description.c_str()), false, true, QString::fromStdString(ach->progressText), ach->measured_percent, uiScale, listContainer); ++ pLayout->addWidget(item); ++ if (ach->badge_locked_url && ach->badge_locked_url[0] != '\0') SetBadgeImage(item, ach->badge_locked_url); ++ } ++ } ++ ++ if (!lockedList.isEmpty()) { ++ QVBoxLayout* lLayout = nullptr; ++ CreateCollapsibleSection("Locked", lockedList.size(), &lLayout); ++ for (const auto* ach : lockedList) { ++ auto* item = new AchievementItemWidget(QString::fromUtf8(ach->title.c_str()), QString::fromUtf8(ach->description.c_str()), false, false, "", 0.0f, uiScale, listContainer); ++ lLayout->addWidget(item); ++ if (ach->badge_locked_url && ach->badge_locked_url[0] != '\0') SetBadgeImage(item, ach->badge_locked_url); ++ } ++ } ++ } ++ } ++ listLayout->addStretch(); ++} ++ ++void RAOverlayWidget::updateJoystick(uint32_t joyState) { ++ if (!isVisible()) return; ++ ++ constexpr int BIT_UP = 6, BIT_DOWN = 7, BIT_A = 0; ++ ++ uint32_t navMask = joyState & ((1 << BIT_UP) | (1 << BIT_DOWN)); ++ if ((navMask & ~heldMask) != 0) { repeatTimer.restart(); repeating = false; } ++ heldMask = navMask; ++ ++ bool doRepeat = false; ++ if (heldMask != 0) { ++ if (!repeating && repeatTimer.elapsed() >= 200) { repeating = true; repeatTimer.restart(); doRepeat = true; } ++ else if (repeating && repeatTimer.elapsed() >= 60) { repeatTimer.restart(); doRepeat = true; } ++ } ++ ++ if (navMask != 0 || doRepeat) { ++ Qt::Key key = (heldMask & (1 << BIT_UP)) ? Qt::Key_Backtab : Qt::Key_Tab; ++ QKeyEvent event(QEvent::KeyPress, key, Qt::NoModifier); ++ QCoreApplication::sendEvent(scene, &event); ++ } ++ ++ bool isAPressed = (joyState & (1 << BIT_A)); ++ bool wasAPressed = (lastJoyState & (1 << BIT_A)); ++ ++ if (isAPressed && !wasAPressed) { ++ if (auto* btn = qobject_cast(contentWidget->focusWidget())) { ++ btn->click(); ++ } ++ } ++ ++ if (auto* next = contentWidget->focusWidget()) { ++ if (auto* scroll = contentWidget->findChild()) { ++ scroll->ensureWidgetVisible(next, 20, 20); ++ } ++ } ++ ++ if (navMask == 0) { heldMask = 0; repeating = false; } ++ ++ lastJoyState = joyState; ++} ++ ++bool RAOverlayWidget::event(QEvent* e) { ++ if (e->type() == QEvent::KeyPress) { ++ QKeyEvent* ke = static_cast(e); ++ Config::Table cfg = Config::GetLocalTable(emuInstance->getInstanceID()); ++ ++ int cfgUp = cfg.GetInt("Keyboard.Up"); ++ int cfgDown = cfg.GetInt("Keyboard.Down"); ++ int cfgA = cfg.GetInt("Keyboard.A"); ++ ++ bool isUp = (ke->key() == cfgUp || ke->key() == Qt::Key_Up); ++ bool isDown = (ke->key() == cfgDown || ke->key() == Qt::Key_Down); ++ ++ bool isConfirm = (ke->key() == cfgA || ke->key() == Qt::Key_Return || ke->key() == Qt::Key_Enter); ++ ++ if (isUp || isDown) { ++ Qt::Key key = isDown ? Qt::Key_Tab : Qt::Key_Backtab; ++ QKeyEvent event(QEvent::KeyPress, key, Qt::NoModifier); ++ QCoreApplication::sendEvent(scene, &event); ++ return true; ++ } ++ ++ if (isConfirm) { ++ if (!ke->isAutoRepeat()) { ++ if (auto* btn = qobject_cast(contentWidget->focusWidget())) { ++ btn->click(); ++ return true; ++ } ++ } ++ return true; ++ } ++ ++ if (parentWidget()) { ++ return QCoreApplication::sendEvent(parentWidget(), e); ++ } ++ } ++ return QGraphicsView::event(e); ++} ++ ++void RAOverlayWidget::updateClock() { ++ timeLabel->setText(QDateTime::currentDateTime().toString("HH:mm")); ++ ++ if (isVisible()) { ++ RAContext* ra = emuInstance->getRA(); ++ if (ra && ra->IsGameLoaded()) { ++ ++ auto* gameInfo = ra->GetCurrentGameInfo(); ++ uint32_t gameID = gameInfo ? gameInfo->id : 0; ++ ++ int totalSeconds = 0; ++ if (gameID != 0) { ++ std::string gameKey = std::to_string(gameID); ++ totalSeconds = Config::GetRAPlaytimeTable().GetInt(gameKey); ++ } ++ ++ int hours = totalSeconds / 3600; ++ int mins = (totalSeconds % 3600) / 60; ++ ++ QString playtimeStr; ++ if (hours > 0) { ++ playtimeStr = QString("Playtime: %1h %2m").arg(hours).arg(mins); ++ } else { ++ playtimeStr = QString("Playtime: %1m").arg(mins); ++ } ++ ++ playtimeLabel->setText(playtimeStr); ++ if (playtimeLabel->isHidden()) playtimeLabel->show(); ++ } else { ++ playtimeLabel->hide(); ++ } ++ } ++} ++ ++bool RAOverlayWidget::eventFilter(QObject* obj, QEvent* event) { ++ if (obj == parentWidget()->window() && ++ (event->type() == QEvent::Resize || ++ event->type() == QEvent::Move || ++ event->type() == QEvent::WindowStateChange)) ++ { ++ if (isVisible()) { ++ ApplyRotationAndResize(); ++ } ++ } ++ return QGraphicsView::eventFilter(obj, event); ++} ++ ++void RAOverlayWidget::SetBadgeImage(AchievementItemWidget* item, const char* url) { ++ if (!url || !*url) return; ++ QString qurl = QString::fromUtf8(url); ++ if (badgeCache.contains(qurl)) { item->updateIcon(badgeCache[qurl]); return; } ++ QPointer safeItem(item); ++ QNetworkReply* reply = netManager->get(QNetworkRequest(QUrl(qurl))); ++ connect(reply, &QNetworkReply::finished, this, [this, reply, safeItem, qurl]() { ++ reply->deleteLater(); ++ if (safeItem && reply->error() == QNetworkReply::NoError) { ++ QPixmap pix; if (pix.loadFromData(reply->readAll())) { badgeCache.insert(qurl, pix); safeItem->updateIcon(pix); } ++ } ++ }); ++} ++ ++void RAOverlayWidget::LoadHeaderImage(QLabel* targetLabel, const char* url, QSize size) { ++ if (!url || !*url || !targetLabel) return; ++ QString qurl = QString::fromUtf8(url); ++ if (headerImageCache.contains(qurl)) { targetLabel->setPixmap(headerImageCache[qurl]); targetLabel->setStyleSheet("background: transparent; border: none;"); return; } ++ QPointer safeLabel(targetLabel); ++ QNetworkReply* reply = netManager->get(QNetworkRequest(QUrl(qurl))); ++ connect(reply, &QNetworkReply::finished, this, [this, reply, safeLabel, qurl, size]() { ++ reply->deleteLater(); ++ if (safeLabel && reply->error() == QNetworkReply::NoError) { ++ QPixmap pix; if (pix.loadFromData(reply->readAll())) { ++ QPixmap scaled = pix.scaled(size, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation); ++ headerImageCache.insert(qurl, scaled); safeLabel->setPixmap(scaled); safeLabel->setStyleSheet("background: transparent; border: none;"); ++ } ++ } ++ }); ++} ++void RAOverlayWidget::ApplyRotationAndResize() ++{ ++ if (!parentWidget()) return; ++ ++ int instanceID = emuInstance->getInstanceID(); ++ Config::Table cfg = Config::GetLocalTable(instanceID); ++ int rotMode = cfg.GetInt("Window0.ScreenRotation"); ++ m_currentRotation = rotMode * 90; ++ ++ QRect pRect = parentWidget()->rect(); ++ setGeometry(pRect); ++ scene->setSceneRect(0, 0, pRect.width(), pRect.height()); ++ ++ proxy->setRotation(0); ++ proxy->setPos(0, 0); ++ ++ if (rotMode == 1 || rotMode == 3) { ++ contentWidget->setFixedSize(pRect.height(), pRect.width()); ++ proxy->setRotation(m_currentRotation); ++ if (rotMode == 1) proxy->setPos(pRect.width(), 0); ++ else proxy->setPos(0, pRect.height()); ++ } else { ++ contentWidget->setFixedSize(pRect.size()); ++ if (rotMode == 2) { ++ proxy->setRotation(180); ++ proxy->setPos(pRect.width(), pRect.height()); ++ } ++ } ++ ++ int shortSide = std::min(contentWidget->width(), contentWidget->height()); ++ bool mini = (shortSide < 420); ++ ++ avatarLabel->setVisible(!mini); ++ usernameLabel->setVisible(!mini); ++ timeLabel->setVisible(!mini); ++ gameTitleLabel->setVisible(!mini); ++ ++ if (auto* root = qobject_cast(contentWidget->layout())) { ++ if (mini) { ++ root->setContentsMargins(10, 5, 10, 10); ++ root->setSpacing(5); ++ } else { ++ root->setContentsMargins(20, 20, 20, 20); ++ root->setSpacing(15); ++ } ++ } ++} +\ No newline at end of file +diff -rupbN melonDS.orig/src/frontend/qt_sdl/RAOverlayWidget.h melonDS.ra/src/frontend/qt_sdl/RAOverlayWidget.h +--- melonDS.orig/src/frontend/qt_sdl/RAOverlayWidget.h 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/frontend/qt_sdl/RAOverlayWidget.h 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,74 @@ ++#pragma once ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++class EmuInstance; ++class AchievementItemWidget; ++ ++class RAOverlayWidget : public QGraphicsView ++{ ++ Q_OBJECT ++public: ++ bool isOpen() const { return m_isOpen; } ++ explicit RAOverlayWidget(EmuInstance* emu, QWidget* parent); ++ ~RAOverlayWidget(); ++ ++ void updateJoystick(uint32_t joyState); ++ void refresh(); ++ void toggle(); ++ ++protected: ++ bool eventFilter(QObject* obj, QEvent* event) override; ++ bool event(QEvent* e) override; ++ ++private: ++ void ApplyRotationAndResize(); ++ std::set collapsedSections; ++ uint32_t lastJoyState = 0; ++ bool m_isOpen = false; ++ void updateClock(); ++ void SetBadgeImage(AchievementItemWidget* item, const char* url); ++ void LoadHeaderImage(QLabel* targetLabel, const char* url, QSize size); ++ ++ QWidget* CreateCollapsibleSection(const QString& title, int count, QVBoxLayout** innerLayout); ++ ++ EmuInstance* emuInstance; ++ QNetworkAccessManager* netManager; ++ ++ QGraphicsScene* scene; ++ QGraphicsProxyWidget* proxy; ++ QWidget* contentWidget; ++ ++ QLabel* avatarLabel; ++ QLabel* usernameLabel; ++ QLabel* gameTitleLabel; ++ QLabel* gameImgLabel; ++ QLabel* timeLabel; ++ QLabel* playtimeLabel; ++ QWidget* listContainer; ++ QVBoxLayout* listLayout; ++ ++ QHash badgeCache; ++ QHash headerImageCache; ++ QTimer* clockTimer; ++ ++ int m_currentRotation = 0; ++ ++ static constexpr int INITIAL_DELAY_MS = 400; ++ static constexpr int REPEAT_DELAY_MS = 80; ++ QElapsedTimer repeatTimer; ++ uint32_t heldMask = 0; ++ bool repeating = false; ++}; +\ No newline at end of file +diff -rupbN melonDS.orig/src/frontend/qt_sdl/RASettingsDialog.cpp melonDS.ra/src/frontend/qt_sdl/RASettingsDialog.cpp +--- melonDS.orig/src/frontend/qt_sdl/RASettingsDialog.cpp 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/frontend/qt_sdl/RASettingsDialog.cpp 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,214 @@ ++#include "RASettingsDialog.h" ++#include "ui_RASettingsDialog.h" ++ ++#include "Config.h" ++#include "main.h" ++#include "RetroAchievements/RAClient.h" ++ ++#include ++#include ++#include ++#include ++#include ++ ++bool RASettingsDialog::needsReset = false; ++RASettingsDialog::RASettingsDialog(EmuInstance* inst, QWidget* parent) ++ : QDialog(parent) ++ , ui(new Ui::RASettingsDialog) ++ , emuInstance(inst) ++{ ++ ui->setupUi(this); ++ ++ connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &RASettingsDialog::accept); ++ connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &RASettingsDialog::reject); ++ ++ setAttribute(Qt::WA_DeleteOnClose); ++ ++ auto& instcfg = emuInstance->getLocalConfig(); ++ ui->cbRAEnabled->setChecked(instcfg.GetBool("RetroAchievements.Enabled")); ++ ui->cbRAHardcore->setChecked(instcfg.GetBool("RetroAchievements.HardcoreMode")); ++ ui->leRAUsername->setText(QString::fromStdString(instcfg.GetString("RetroAchievements.Username"))); ++ ui->leRAPassword->setText(QString::fromStdString(instcfg.GetString("RetroAchievements.Password"))); ++ ui->cbRAAchievementToasts->setChecked(instcfg.GetBool("RetroAchievements.HideToasts")); ++ ui->cbRAChallengeIndicators->setChecked(instcfg.GetBool("RetroAchievements.HideChallengeIndicators")); ++ ui->cbRAEncoreMode->setChecked(instcfg.GetBool("RetroAchievements.EncoreMode")); ++ ui->cbRAUnofficialMode->setChecked(instcfg.GetBool("RetroAchievements.Unofficial")); ++ ui->cbRALeaderboardCounter->setChecked(instcfg.GetBool("RetroAchievements.HideLeaderboardCounter")); ++ ui->cbRALeaderboardToasts->setChecked(instcfg.GetBool("RetroAchievements.HideLeaderboardToasts")); ++ ++ auto UpdateRAUI = [this]() { ++ RAContext* ra = emuInstance->getRA(); ++ if (!ra) return; ++ ++ bool loggedIn = ra->IsLoggedIn(); ++ bool emuRunning = emuInstance->emuIsActive(); ++ ++ ui->cbRAEnabled->setEnabled(!loggedIn); ++ ui->cbRAHardcore->setEnabled(!loggedIn); ++ ui->leRAUsername->setEnabled(!loggedIn); ++ ui->leRAPassword->setEnabled(!loggedIn); ++ ui->btnRALogin->setEnabled(!emuRunning); ++ ++ if (emuRunning) { ++ ui->btnRALogin->setToolTip( ++ "Stop the emulation before logging in or out of RetroAchievements." ++ ); ++ } else { ++ ui->btnRALogin->setToolTip(QString()); ++ } ++ ++ if (loggedIn) { ++ ui->btnRALogin->setText("Logout"); ++ ++ const rc_client_user_t* user = rc_client_get_user_info(ra->client); ++ if (user && user->display_name) ++ ui->lblRAStatus->setText(QString("Logged in as: %1").arg(user->display_name)); ++ else ++ ui->lblRAStatus->setText("Logged in"); ++ ++ ui->lblRAStatus->setStyleSheet("font-weight: bold; color: #2ecc71;"); ++ } else { ++ ui->btnRALogin->setText("Login Now"); ++ ui->lblRAStatus->setText("Not logged in"); ++ ui->lblRAStatus->setStyleSheet("color: gray;"); ++ } ++ }; ++ ++ UpdateRAUI(); ++ ++ connect(ui->btnRALogin, &QPushButton::clicked, this, [this, UpdateRAUI]() { ++ RAContext* ra = emuInstance->getRA(); ++ if (!ra) return; ++ ++ if (ra->IsLoggedIn()) { ++ ra->SetLoggedIn(false); ++ ra->SetToken(""); ++ UpdateRAUI(); ++ ++ ui->cbRAEnabled->setProperty("user_originalValue", !ui->cbRAEnabled->isChecked()); ++ ui->cbRAHardcore->setProperty("user_originalValue", !ui->cbRAHardcore->isChecked()); ++ ui->leRAUsername->setProperty("user_originalValue", ""); ++ ui->leRAPassword->setProperty("user_originalValue", ""); ++ ++ if (emuInstance && emuInstance->emuIsActive()) { ++ done(QDialog::Accepted); ++ } ++ ++ } else { ++ std::string user = ui->leRAUsername->text().toStdString(); ++ std::string pass = ui->leRAPassword->text().toStdString(); ++ if (user.empty() || pass.empty()) return; ++ ++ ra->LoginWithPassword(user.c_str(), pass.c_str(), ui->cbRAHardcore->isChecked()); ++ ++ ui->cbRAEnabled->setProperty("user_originalValue", !ui->cbRAEnabled->isChecked()); ++ ui->cbRAHardcore->setProperty("user_originalValue", !ui->cbRAHardcore->isChecked()); ++ ui->leRAUsername->setProperty("user_originalValue", ""); ++ ui->leRAPassword->setProperty("user_originalValue", ""); ++ ++ if (emuInstance && emuInstance->emuIsActive()) { ++ done(QDialog::Accepted); ++ } ++ } ++ }); ++ ++ RAContext* raTmp = emuInstance->getRA(); ++ if (raTmp) { ++ auto mainWin = emuInstance->getMainWindow(); ++ raTmp->onLoginResponse = [this, UpdateRAUI, mainWin](bool success, const std::string& msg) { ++ QMetaObject::invokeMethod(this, [this, UpdateRAUI, mainWin, success, msg]() { ++ UpdateRAUI(); ++ if (mainWin) { ++ mainWin->ShowRALoginToast(success, msg); ++ } ++ }); ++ }; ++ } ++ ++#define SET_ORIGVAL(type, val) \ ++ for (type* w : findChildren(nullptr)) \ ++ w->setProperty("user_originalValue", w->val()); ++ ++ SET_ORIGVAL(QLineEdit, text); ++ SET_ORIGVAL(QCheckBox, isChecked); ++ ++#undef SET_ORIGVAL ++} ++ ++RASettingsDialog::~RASettingsDialog() ++{ ++ if (emuInstance) { ++ if (auto* ra = emuInstance->getRA()) { ++ ra->onLoginResponse = nullptr; ++ } ++ } ++ delete ui; ++} ++ ++void RASettingsDialog::done(int r) ++{ ++ if (!emuInstance) ++ { ++ QDialog::done(r); ++ return; ++ } ++ ++ needsReset = false; ++ ++#ifdef RETROACHIEVEMENTS_ENABLED ++ if (r == QDialog::Accepted) ++ { ++ bool modified = false; ++ ++#define CHECK_ORIGVAL(type, val) \ ++ if (!modified) for (type* w : findChildren(nullptr)) \ ++ { \ ++ QVariant v = w->val(); \ ++ if (v != w->property("user_originalValue")) \ ++ { \ ++ modified = true; \ ++ break; \ ++ } \ ++ } ++ ++ CHECK_ORIGVAL(QLineEdit, text); ++ CHECK_ORIGVAL(QCheckBox, isChecked); ++ ++#undef CHECK_ORIGVAL ++ ++ if (modified) ++ { ++ if (emuInstance->emuIsActive() ++ && QMessageBox::warning( ++ this, ++ "Reset necessary to apply changes", ++ "The emulation will be reset for the changes to take place.", ++ QMessageBox::Ok, ++ QMessageBox::Cancel) != QMessageBox::Ok) ++ { ++ return; ++ } ++ ++ auto& instcfg = emuInstance->getLocalConfig(); ++ ++ instcfg.SetBool("RetroAchievements.Enabled", ui->cbRAEnabled->isChecked()); ++ instcfg.SetBool("RetroAchievements.HardcoreMode", ui->cbRAHardcore->isChecked()); ++ instcfg.SetString("RetroAchievements.Username", ui->leRAUsername->text().toStdString()); ++ instcfg.SetString("RetroAchievements.Password", ui->leRAPassword->text().toStdString()); ++ instcfg.SetBool("RetroAchievements.HideToasts", ui->cbRAAchievementToasts->isChecked()); ++ instcfg.SetBool("RetroAchievements.HideChallengeIndicators", ui->cbRAChallengeIndicators->isChecked()); ++ instcfg.SetBool("RetroAchievements.EncoreMode", ui->cbRAEncoreMode->isChecked()); ++ instcfg.SetBool("RetroAchievements.Unofficial", ui->cbRAUnofficialMode->isChecked()); ++ instcfg.SetBool("RetroAchievements.HideLeaderboardCounter", ui->cbRALeaderboardCounter->isChecked()); ++ instcfg.SetBool("RetroAchievements.HideLeaderboardToasts", ui->cbRALeaderboardToasts->isChecked()); ++ ++ emuInstance->SyncRetroAchievementsFromConfig(); ++ Config::Save(); ++ ++ needsReset = true; ++ } ++ } ++#endif ++ ++ QDialog::done(r); ++} +\ No newline at end of file +diff -rupbN melonDS.orig/src/frontend/qt_sdl/RASettingsDialog.h melonDS.ra/src/frontend/qt_sdl/RASettingsDialog.h +--- melonDS.orig/src/frontend/qt_sdl/RASettingsDialog.h 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/frontend/qt_sdl/RASettingsDialog.h 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,42 @@ ++#pragma once ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++class EmuInstance; ++ ++namespace Ui { ++class RASettingsDialog; ++} ++ ++class RASettingsDialog : public QDialog ++{ ++ Q_OBJECT ++ ++public: ++ static bool needsReset; ++ explicit RASettingsDialog(EmuInstance* inst, QWidget* parent = nullptr); ++ ~RASettingsDialog() override; ++ ++ void done(int r) override; ++ ++private: ++ Ui::RASettingsDialog* ui; ++ ++ QGroupBox* groupRA; ++ QCheckBox* cbRAEnabled; ++ QCheckBox* cbRAHardcore; ++ QLineEdit* leRAUsername; ++ QLineEdit* leRAPassword; ++ QPushButton* btnRALogin; ++ QLabel* lblRAStatus; ++ ++ EmuInstance* emuInstance; ++}; +\ No newline at end of file +diff -rupbN melonDS.orig/src/frontend/qt_sdl/RASettingsDialog.ui melonDS.ra/src/frontend/qt_sdl/RASettingsDialog.ui +--- melonDS.orig/src/frontend/qt_sdl/RASettingsDialog.ui 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/frontend/qt_sdl/RASettingsDialog.ui 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,187 @@ ++ ++ ++ RASettingsDialog ++ ++ ++ ++ 0 ++ 0 ++ 420 ++ 300 ++ ++ ++ ++ RetroAchievements Settings ++ ++ ++ ++ ++ ++ ++ Login ++ ++ ++ ++ ++ ++ RetroAchievements – Login ++ ++ ++ ++ ++ ++ Enable RetroAchievements ++ ++ ++ ++ ++ ++ ++ Hardcore Mode (No Savestates) ++ ++ ++ ++ ++ ++ ++ Username: ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Password: ++ ++ ++ ++ ++ ++ ++ QLineEdit::Password ++ ++ ++ ++ ++ ++ ++ Login Now ++ ++ ++ ++ ++ ++ ++ Not logged in ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Qt::Vertical ++ ++ ++ ++ 20 ++ 40 ++ ++ ++ ++ ++ ++ ++ ++ ++Options ++ ++ ++ ++ ++ ++ RetroAchievements – Options ++ ++ ++ ++ ++ ++ Disable achievement toasts ++ ++ ++ ++ ++ ++ ++ Hide challenge indicators ++ ++ ++ ++ ++ ++ ++ Enable Encore Mode ++ ++ ++ ++ ++ ++ ++ Allow unofficial achievements ++ ++ ++ ++ ++ ++ ++ Hide leaderboard counter ++ ++ ++ ++ ++ ++ ++ Disable leaderboard toasts ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Qt::Vertical ++ ++ ++ ++ 20 ++ 40 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Qt::Horizontal ++ ++ ++ QDialogButtonBox::Ok|QDialogButtonBox::Cancel ++ ++ ++ ++ ++ ++ ++ ++ +\ No newline at end of file +diff -rupbN melonDS.orig/src/frontend/qt_sdl/Window.cpp melonDS.ra/src/frontend/qt_sdl/Window.cpp +--- melonDS.orig/src/frontend/qt_sdl/Window.cpp 2026-03-06 21:36:14.566057575 +0000 ++++ melonDS.ra/src/frontend/qt_sdl/Window.cpp 2026-03-06 21:37:07.046799886 +0000 +@@ -82,6 +82,14 @@ + #include "Window.h" + #include "AboutDialog.h" + ++#ifdef RETROACHIEVEMENTS_ENABLED ++#include "RASettingsDialog.h" ++#include "RetroAchievements/RAClient.h" ++#include "toast/BadgeCache.h" ++#include "RAOverlayWidget.h" ++#include ++#endif ++ + using namespace melonDS; + + +@@ -234,6 +242,10 @@ MainWindow::MainWindow(int id, EmuInstan + windowCfg(localCfg.GetTable("Window"+std::to_string(id), "Window0")), + emuThread(inst->getEmuThread()), + enabledSaved(false), ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ m_badgeCache(this), ++ m_toastManager(this), ++ #endif + focused(true) + { + #ifndef _WIN32 +@@ -640,6 +652,11 @@ MainWindow::MainWindow(int id, EmuInstan + actMPSettings = menu->addAction("Multiplayer settings"); + connect(actMPSettings, &QAction::triggered, this, &MainWindow::onOpenMPSettings); + ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ actRASettings = menu->addAction("RA settings"); ++ connect(actRASettings, &QAction::triggered, this, &MainWindow::onOpenRASettings); ++ #endif ++ + actWifiSettings = menu->addAction("Wifi settings"); + connect(actWifiSettings, &QAction::triggered, this, &MainWindow::onOpenWifiSettings); + +@@ -784,6 +801,132 @@ MainWindow::MainWindow(int id, EmuInstan + #endif // __APPLE__ + } + ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ m_oldRAEnabled = Config::GetLocalTable(emuInstance->instanceID).GetBool("Instance*.RetroAchievements.Enabled"); ++ m_toastManager.Init(this); ++ if (auto* ra = inst->getRA()) ++ { ++ ra->SetOnGameLoadedCallback([this]() { ++ QMetaObject::invokeMethod(this, [this]() { ++ ShowGameLoadToast(); ++ }, Qt::QueuedConnection); ++ }); ++ ++ ra->onLoginResponse = [this](bool success, const std::string& message) { ++ ShowRALoginToast(success, message); ++ }; ++ ++ ra->SetOnAchievementUnlocked( ++ [this](const char* title, ++ const char* desc, ++ const char* badgeUrl) ++ { ++ QMetaObject::invokeMethod( ++ this, ++ [this, ++ t = QString::fromUtf8(title), ++ d = QString::fromUtf8(desc), ++ b = QString::fromUtf8(badgeUrl)]() ++ { ++ OnAchievementUnlocked(t, d, b); ++ }, ++ Qt::QueuedConnection ++ ); ++ }); ++ ra->SetOnAchievementProgress( ++ [this](const char* title, ++ const char* progress, ++ const char* badgeUrl) ++ { ++ QMetaObject::invokeMethod( ++ this, ++ [this, ++ t = QString::fromUtf8(title), ++ p = QString::fromUtf8(progress), ++ b = QString::fromUtf8(badgeUrl)]() ++ { ++ OnAchievementProgress(t, p, b); ++ }, ++ Qt::QueuedConnection ++ ); ++ }); ++ ra->SetOnChallenge([this](const char* badgeUrl) { ++ if (!badgeUrl) return; ++ QString b = QString::fromUtf8(badgeUrl); ++ ++ QMetaObject::invokeMethod(this, [this, b]() { ++ OnChallengeShow(b); ++ }, Qt::QueuedConnection); ++ }); ++ ++ ra->SetOnChallengeHide([this]() { ++ QMetaObject::invokeMethod(this, [this]() { ++ m_toastManager.HideChallengeIndicator(""); ++ }, Qt::QueuedConnection); ++ }); ++ ++ ra->SetOnLeaderboardTrackerUpdate([this](const char* display) { ++ QString d = QString::fromUtf8(display); ++ QMetaObject::invokeMethod(this, [this, d]() { ++ this->OnLeaderboardTrackerUpdate(d); // Dodaj this-> dla jasności ++ }, Qt::QueuedConnection); ++ }); ++ ++ ra->SetOnLeaderboardSubmitted([this](const char* title, const char* score, unsigned rank) { ++ QString t = QString::fromUtf8(title); ++ QString s = QString::fromUtf8(score); ++ QMetaObject::invokeMethod(this, [this, t, s, rank]() { ++ OnLeaderboardSubmitted(t, s, rank); ++ }, Qt::QueuedConnection); ++ }); ++ ++ QPointer self(this); ++ ++ ra->SetOnRADisconnected([self]() { ++ if (!self) return; ++ QMetaObject::invokeMethod(self, [self]() { ++ if (!self) return; ++ self->OnRADisconnected(); ++ }, Qt::QueuedConnection); ++ }); ++ ++ ra->SetOnRAReconnected([self]() { ++ if (!self) return; ++ QMetaObject::invokeMethod(self, [self]() { ++ if (!self) return; ++ self->OnRAReconnected(); ++ }, Qt::QueuedConnection); ++ }); ++ ++ ra->SetOnRAPendingSent([self](int count) { ++ if (!self) return; ++ QMetaObject::invokeMethod(self, [self, count]() { ++ if (!self) return; ++ self->OnRAPendingSent(count); ++ }, Qt::QueuedConnection); ++ }); ++ ++ ra->SetOnGameMastered( ++ [this, ra](const std::string& title, const std::string& /*rp_text*/) ++ { ++ QString gameBadgeUrl; ++ const rc_client_game_t* gameInfo = ra->GetCurrentGameInfo(); ++ if (gameInfo && gameInfo->badge_url) { ++ gameBadgeUrl = QString::fromUtf8(gameInfo->badge_url); ++ } ++ ++ QMetaObject::invokeMethod(this, [this, ++ t = QString::fromStdString(title), ++ b = gameBadgeUrl]() ++ { ++ OnGameMastered(t, b); ++ }, Qt::QueuedConnection); ++ }); ++ } ++ raOverlay = new RAOverlayWidget(emuInstance, this); ++ raOverlay->setGeometry(rect()); ++ emuInstance->setRAOverlay(raOverlay); ++ #endif + if (emuThread->emuIsActive()) + onEmuStart(); + } +@@ -1554,6 +1697,17 @@ void MainWindow::onEjectGBACart() + + void MainWindow::onSaveState() + { ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ RAContext* ra = emuInstance->getRA(); ++ auto cfg = Config::GetLocalTable(emuInstance->instanceID); ++ if (cfg.GetBool("Instance*.RetroAchievements.Enabled") && ++ cfg.GetBool("Instance*.RetroAchievements.HardcoreMode") && ++ ra->IsLoggedIn()) ++ { ++ emuInstance->osdAddMessage(0xFFA0A0, "Savestates states is disabled in Hardcore Mode"); ++ return; ++ } ++ #endif + int slot = ((QAction*)sender())->data().toInt(); + + QString filename; +@@ -1589,6 +1743,17 @@ void MainWindow::onSaveState() + + void MainWindow::onLoadState() + { ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ RAContext* ra = emuInstance->getRA(); ++ auto cfg = Config::GetLocalTable(emuInstance->instanceID); ++ if (cfg.GetBool("Instance*.RetroAchievements.Enabled") && ++ cfg.GetBool("Instance*.RetroAchievements.HardcoreMode") && ++ ra->IsLoggedIn()) ++ { ++ emuInstance->osdAddMessage(0xFFA0A0, "Savestates disabled in Hardcore Mode"); ++ return; ++ } ++ #endif + int slot = ((QAction*)sender())->data().toInt(); + + QString filename; +@@ -1639,6 +1804,17 @@ void MainWindow::onUndoStateLoad() + + void MainWindow::onImportSavefile() + { ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ RAContext* ra = emuInstance->getRA(); ++ auto cfg = Config::GetLocalTable(emuInstance->instanceID); ++ if (cfg.GetBool("Instance*.RetroAchievements.Enabled") && ++ cfg.GetBool("Instance*.RetroAchievements.HardcoreMode") && ++ ra->IsLoggedIn()) ++ { ++ QMessageBox::critical(this, "melonDS", "Importing savefiles is disabled in Hardcore Mode."); ++ return; ++ } ++ #endif + QString path = QFileDialog::getOpenFileName(this, + "Select savefile", + globalCfg.GetQString("LastROMFolder"), +@@ -1699,6 +1875,9 @@ void MainWindow::onPause(bool checked) + + void MainWindow::onReset() + { ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ m_toastManager.HideChallengeIndicator(""); ++ #endif + if (!emuThread->emuIsActive()) return; + + emuThread->emuReset(); +@@ -1706,6 +1885,9 @@ void MainWindow::onReset() + + void MainWindow::onStop() + { ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ m_toastManager.HideChallengeIndicator(""); ++ #endif + if (!emuThread->emuIsActive()) return; + + emuThread->emuStop(true); +@@ -1730,6 +1912,18 @@ void MainWindow::onOpenPowerManagement() + + void MainWindow::onEnableCheats(bool checked) + { ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ RAContext* ra = emuInstance->getRA(); ++ auto cfg = Config::GetLocalTable(emuInstance->instanceID); ++ if (checked && cfg.GetBool("Instance*.RetroAchievements.Enabled") && ++ cfg.GetBool("Instance*.RetroAchievements.HardcoreMode") && ++ ra->IsLoggedIn()) ++ { ++ emuInstance->osdAddMessage(0xFFA0A0, "Cheats are disabled in Hardcore Mode"); ++ actEnableCheats->setChecked(false); ++ return; ++ } ++ #endif + localCfg.SetBool("EnableCheats", checked); + emuThread->enableCheats(checked); + +@@ -1741,6 +1935,17 @@ void MainWindow::onEnableCheats(bool che + + void MainWindow::onSetupCheats() + { ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ RAContext* ra = emuInstance->getRA(); ++ auto cfg = Config::GetLocalTable(emuInstance->instanceID); ++ if (cfg.GetBool("Instance*.RetroAchievements.Enabled") && ++ cfg.GetBool("Instance*.RetroAchievements.HardcoreMode") && ++ ra->IsLoggedIn()) ++ { ++ emuInstance->osdAddMessage(0xFFA0A0, "Cheat menu is disabled in Hardcore Mode"); ++ return; ++ } ++ #endif + emuThread->emuPause(); + + CheatsDialog* dlg = CheatsDialog::openDlg(this); +@@ -1870,6 +2075,52 @@ void MainWindow::onEmuSettingsDialogFini + if (!emuThread->emuIsActive()) + actTitleManager->setEnabled(!globalCfg.GetString("DSi.NANDPath").empty()); + ++#ifdef RETROACHIEVEMENTS_ENABLED ++if (auto* ra = emuInstance->getRA()) ++{ ++ const bool newRAEnabled = ++ localCfg.GetBool("Instance*.RetroAchievements.Enabled"); ++ if (m_oldRAEnabled != newRAEnabled) ++ { ++ if (newRAEnabled) ++ { ++ std::string user = ++ localCfg.GetString("Instance*.RetroAchievements.Username"); ++ std::string pass = ++ localCfg.GetString("Instance*.RetroAchievements.Password"); ++ bool hardcore = ++ localCfg.GetBool("Instance*.RetroAchievements.Hardcore"); ++ ++ ra->SetCredentials( ++ user.c_str(), ++ pass.c_str(), ++ hardcore ++ ); ++ ++ ra->Enable(); ++ ++ m_toastManager.ShowAchievement( ++ "RetroAchievements", ++ "Enabled", ++ QPixmap(":/ra/icons/ra-icon.png") ++ ); ++ } ++ else ++ { ++ ra->Disable(); ++ ++ m_toastManager.ShowAchievement( ++ "RetroAchievements", ++ "Disabled", ++ QPixmap(":/ra/icons/ra-icon.png") ++ ); ++ } ++ ++ m_oldRAEnabled = newRAEnabled; ++ } ++} ++#endif ++ + emuThread->emuUnpause(); + } + +@@ -1997,6 +2248,35 @@ void MainWindow::onMPSettingsFinished(in + + emuThread->emuUnpause(); + } ++#ifdef RETROACHIEVEMENTS_ENABLED ++void MainWindow::onOpenRASettings() ++{ ++ emuThread->emuPause(); ++ if (!emuInstance) ++ return; ++ ++ RASettingsDialog* dlg = new RASettingsDialog(emuInstance, this); ++ connect(dlg, &QDialog::finished, ++ this, &MainWindow::onRASettingsFinished); ++ ++ dlg->show(); ++} ++ ++void MainWindow::onRASettingsFinished(int res) ++{ ++ if (!emuInstance) ++ return; ++ ++ if (res == QDialog::Accepted) ++ { ++ emuInstance->SyncRetroAchievementsFromConfig(); ++ } ++ ++ if (RASettingsDialog::needsReset) ++ onReset(); ++ emuThread->emuUnpause(); ++} ++#endif + + void MainWindow::onOpenWifiSettings() + { +@@ -2160,6 +2440,13 @@ void MainWindow::onChangeAudioSync(bool + + void MainWindow::onTitleUpdate(QString title) + { ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ if (emuInstance) { ++ if (RAContext* ra = emuInstance->getRA()) { ++ ra->ProcessAsyncCallbacks(); ++ } ++ } ++ #endif + if (!emuInstance) return; + + int numinst = numEmuInstances(); +@@ -2210,6 +2497,38 @@ void MainWindow::onFullscreenToggled() + toggleFullscreen(); + } + ++#ifdef RETROACHIEVEMENTS_ENABLED ++void MainWindow::onRAOverlayToggled() ++{ ++ if (!emuInstance || !this->isActiveWindow()) ++ return; ++ ++ RAOverlayWidget* currentOverlay = emuInstance->getRAOverlay(); ++ ++ if (!currentOverlay) { ++ currentOverlay = new RAOverlayWidget(emuInstance, this->centralWidget()); ++ emuInstance->setRAOverlay(currentOverlay); ++ raOverlay = currentOverlay; ++ } ++ ++ if (currentOverlay->isOpen()) { ++ currentOverlay->toggle(); ++ emuThread->emuUnpause(); ++ this->centralWidget()->setFocus(); ++ } else { ++ if (currentOverlay->parentWidget() != this->centralWidget()) { ++ currentOverlay->setParent(this->centralWidget()); ++ } ++ ++ currentOverlay->setGeometry(this->centralWidget()->rect()); ++ currentOverlay->toggle(); ++ ++ emuThread->emuPause(); ++ currentOverlay->setFocus(); ++ } ++} ++#endif ++ + void MainWindow::onScreenEmphasisToggled() + { + int currentSizing = windowCfg.GetInt("ScreenSizing"); +@@ -2293,6 +2612,229 @@ void MainWindow::onEmuReset() + actUndoStateLoad->setEnabled(false); + } + ++#ifdef RETROACHIEVEMENTS_ENABLED ++void MainWindow::OnChallengeShow(const QString& badgeName) ++{ ++ QString fullUrl = QString("https://media.retroachievements.org/Badge/%1.png").arg(badgeName); ++ ++ m_badgeCache.DownloadBadge(fullUrl, [this, badgeName](const QPixmap& pix) { ++ if (pix.isNull()) return; ++ ++ QMetaObject::invokeMethod(this, [this, pix, badgeName]() { ++ m_toastManager.ShowChallengeIndicator(pix, badgeName); ++ }); ++ }); ++} ++ ++void MainWindow::OnChallengeHide(const QString& badgeName) ++{ ++ QMetaObject::invokeMethod(this, [this, badgeName]() { ++ m_toastManager.HideChallengeIndicator(badgeName); ++ }); ++} ++ ++void MainWindow::OnLeaderboardTrackerUpdate(const QString& display) ++{ ++ m_toastManager.UpdateLeaderboardTracker(display); ++} ++ ++void MainWindow::OnLeaderboardSubmitted(const QString& title, const QString& score, unsigned rank) ++{ ++ QString msg = QString("Wynik: %1 (Miejsce: %2)").arg(score).arg(rank); ++ m_toastManager.ShowLeaderboardToast(title, msg, QPixmap(":/ra/icons/ra-icon.png")); ++} ++ ++void MainWindow::OnRADisconnected() ++{ ++ m_toastManager.ShowAchievement( ++ tr("RetroAchievements"), ++ tr("There is no connection with the internet"), ++ QPixmap(":/ra/icons/ra-icon.png") ++ ); ++ m_toastManager.UpdateNetworkStatus("~RA~"); ++} ++ ++void MainWindow::OnRAReconnected() ++{ ++ m_toastManager.ShowAchievement( ++ tr("RetroAchievements"), ++ tr("Connection restored"), ++ QPixmap(":/ra/icons/ra-icon.png") ++ ); ++ m_toastManager.UpdateNetworkStatus(""); ++} ++ ++void MainWindow::OnRAPendingSent(int count) // Upewnij się, że jest tu "int count" ++{ ++ if (count <= 0) return; ++ ++ // Tutaj Twoja logika wyświetlania tosta ++ QString message = tr("Sent %1 pending achievements").arg(count); ++ ++ m_toastManager.ShowAchievement( ++ tr("RetroAchievements"), ++ message, ++ QPixmap(":/ra/icons/ra-icon.png") ++ ); ++} ++ ++void MainWindow::OnGameMastered(const QString& title, const QString& gameBadge) ++{ ++ m_badgeCache.DownloadBadge(gameBadge, [this, title](const QPixmap& pix) ++ { ++ QString msg = QString("Mastered %1!").arg(title); ++ ++ m_toastManager.ShowAchievement("MASTERED!", msg, pix); ++ }); ++} ++ ++void MainWindow::OnAchievementProgress( ++ const QString& title, ++ const QString& progress, ++ const QString& badgeUrl) ++{ ++ m_badgeCache.DownloadBadge(badgeUrl, ++ [this, title, progress](const QPixmap& pix) ++ { ++ m_toastManager.ShowProgress( ++ title, ++ progress, ++ pix); ++ }); ++} ++ ++void MainWindow::OnAchievementUnlocked( ++ const QString& title, ++ const QString& desc, ++ const QString& badgeUrl) ++{ ++ m_badgeCache.DownloadBadge(badgeUrl, ++ [this, title, desc](const QPixmap& pix) ++ { ++ m_toastManager.ShowAchievement(title, desc, pix); ++ }); ++} ++ ++void MainWindow::ShowRALoginToast(bool success, const std::string& message) ++{ ++ QString title = "RetroAchievements"; ++ QString toastMsg; ++ QPixmap pixmap(":/ra/icons/ra-icon.png"); ++ ++ if (success && emuInstance) ++ { ++ RAContext* ra = emuInstance->getRA(); ++ const rc_client_user_t* user = ++ (ra && ra->client) ? rc_client_get_user_info(ra->client) : nullptr; ++ ++ if (user && user->display_name) ++ { ++ toastMsg = QString("Logged in as %1").arg(user->display_name); ++ ++ if (user->avatar_url && !QString(user->avatar_url).isEmpty()) ++ { ++ QString avatarUrl = QString::fromUtf8(user->avatar_url); ++ ++ m_badgeCache.DownloadBadge(avatarUrl, [this, title, toastMsg](const QPixmap& avatarPix) ++ { ++ QMetaObject::invokeMethod(this, [this, title, toastMsg, avatarPix]() { ++ m_toastManager.ShowAchievement(title, toastMsg, avatarPix); ++ }); ++ }); ++ ++ return; ++ } ++ } ++ else ++ { ++ toastMsg = "Logged in!"; ++ } ++ } ++ else ++ { ++ toastMsg = QString("Login Error: %1") ++ .arg(QString::fromStdString(message)); ++ } ++ ++ QMetaObject::invokeMethod(this, [this, title, toastMsg, pixmap]() { ++ m_toastManager.ShowAchievement(title, toastMsg, pixmap); ++ }); ++} ++ ++void MainWindow::ShowGameLoadToast() ++{ ++ RAContext* ra = emuInstance->getRA(); ++ if (ra->pendingLoadFailed) ++ { ++ QString errorMsg = QString::fromStdString(ra->pendingLoadError); ++ ++ QTimer::singleShot(100, this, [this, errorMsg]() ++ { ++ QMetaObject::invokeMethod(QApplication::instance(), [this, errorMsg]() ++ { ++ m_toastManager.ShowAchievement( ++ "RetroAchievements", ++ QString("ERROR: %1").arg(errorMsg), ++ QPixmap(":/ra/icons/ra-icon.png") ++ ); ++ }); ++ }); ++ ++ return; ++ } ++ ++ const rc_client_game_t* game = ra->GetCurrentGameInfo(); ++ if (!game) ++ return; ++ ++ QString title = QString::fromUtf8(game->title); ++ QString badgeUrl = QString::fromUtf8(game->badge_url); ++ ++ int totalAchievements = 0; ++ int unlockedAchievements = 0; ++ ++ rc_client_achievement_list_t* achList = ++ rc_client_create_achievement_list( ++ ra->client, ++ RC_CLIENT_ACHIEVEMENT_CATEGORY_CORE_AND_UNOFFICIAL, ++ RC_CLIENT_ACHIEVEMENT_LIST_GROUPING_LOCK_STATE); ++ ++ if (achList) ++ { ++ for (uint32_t b = 0; b < achList->num_buckets; ++b) ++ { ++ const rc_client_achievement_bucket_t* bucket = ++ &achList->buckets[b]; ++ ++ for (uint32_t i = 0; i < bucket->num_achievements; ++i) ++ { ++ const rc_client_achievement_t* ach = ++ bucket->achievements[i]; ++ ++ ++totalAchievements; ++ ++ if (ach && ach->unlocked) ++ ++unlockedAchievements; ++ } ++ } ++ ++ rc_client_destroy_achievement_list(achList); ++ } ++ ++ //stupid function to subtract 1 from achiv because they are showing up incorectly because of hardcore achievement ++ if (totalAchievements > 0) totalAchievements -= 1; ++ if (unlockedAchievements > 0) unlockedAchievements -= 1; ++ ++ QString desc = QString("Game loaded! (%1/%2 Achievements)") ++ .arg(unlockedAchievements) ++ .arg(totalAchievements); ++ ++ QTimer::singleShot(100, this, [this, title, desc]() ++ { ++ m_toastManager.ShowAchievement(title, desc, QPixmap(":/ra/icons/ra-icon.png")); ++ }); ++} ++#endif + void MainWindow::onUpdateVideoSettings(bool glchange) + { + if (!emuInstance) return; +diff -rupbN melonDS.orig/src/frontend/qt_sdl/Window.h melonDS.ra/src/frontend/qt_sdl/Window.h +--- melonDS.orig/src/frontend/qt_sdl/Window.h 2026-03-06 21:36:14.566057575 +0000 ++++ melonDS.ra/src/frontend/qt_sdl/Window.h 2026-03-06 21:37:07.046799886 +0000 +@@ -37,6 +37,13 @@ + #include "Config.h" + #include "MPInterface.h" + ++#ifdef RETROACHIEVEMENTS_ENABLED ++#include "../../RetroAchievements/RAClient.h" ++#include "toast/ToastManager.h" ++#include "toast/BadgeCache.h" ++#include "RAOverlayWidget.h" ++#endif ++ + + class EmuInstance; + class EmuThread; +@@ -48,6 +55,26 @@ class MainWindow : public QMainWindow + Q_OBJECT + + public: ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ void OnLeaderboardTrackerUpdate(const QString& display); ++ void OnLeaderboardSubmitted(const QString& title, const QString& score, unsigned rank); ++ RAOverlayWidget* raOverlay = nullptr; ++ ToastManager m_toastManager; ++ BadgeCache m_badgeCache; ++ void ShowRALoginToast(bool success, const std::string& message); ++ bool m_oldRAEnabled; ++ void showRALoginToast(); ++ void ShowGameLoadToast(); ++ void OnAchievementUnlocked(const QString& title, const QString& desc, const QString& badgeUrl); ++ void OnAchievementProgress(const QString& title, const QString& progress, const QString& badge); ++ void OnChallengeShow(const QString& badgeName); ++ void OnChallengeHide(const QString& badgeName); ++ void OnGameMastered(const QString& title, const QString& gameBadge); ++ void OnRADisconnected(); ++ void OnRAReconnected(); ++ void OnRAPendingSent(int count); ++ #endif ++ + explicit MainWindow(int id, EmuInstance* inst, QWidget* parent = nullptr); + ~MainWindow(); + +@@ -149,6 +176,10 @@ private slots: + void onAudioSettingsFinished(int res); + void onOpenMPSettings(); + void onMPSettingsFinished(int res); ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ void onOpenRASettings(); ++ void onRASettingsFinished(int res); ++ #endif + void onOpenWifiSettings(); + void onWifiSettingsFinished(int res); + void onOpenFirmwareSettings(); +@@ -182,6 +213,9 @@ private slots: + void onUpdateVideoSettings(bool glchange); + + void onFullscreenToggled(); ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ void onRAOverlayToggled(); ++ #endif + void onScreenEmphasisToggled(); + + private: +@@ -269,6 +303,9 @@ public: + QAction* actCameraSettings; + QAction* actAudioSettings; + QAction* actMPSettings; ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ QAction* actRASettings; ++ #endif + QAction* actWifiSettings; + QAction* actFirmwareSettings; + QAction* actPathSettings; +diff -rupbN melonDS.orig/src/frontend/qt_sdl/main.cpp melonDS.ra/src/frontend/qt_sdl/main.cpp +--- melonDS.orig/src/frontend/qt_sdl/main.cpp 2026-03-06 21:36:14.566057575 +0000 ++++ melonDS.ra/src/frontend/qt_sdl/main.cpp 2026-03-06 21:37:07.046799886 +0000 +@@ -65,6 +65,11 @@ + #include "Net_PCap.h" + #include "Net_Slirp.h" + ++#ifdef RETROACHIEVEMENTS_ENABLED ++#include "RetroAchievements/RAClient.h" ++#include ++#endif ++ + using namespace melonDS; + + QString* systemThemeName; +@@ -266,6 +271,38 @@ bool MelonApplication::event(QEvent *eve + return QApplication::event(event); + } + ++#ifdef RETROACHIEVEMENTS_ENABLED ++u32 currentRASeconds = 0; ++QTimer* raPlaytimeTimer = nullptr; ++ ++ ++void updateRAPlaytime() ++{ ++ if (emuInstances[0]) ++ { ++ auto& raCtx = emuInstances[0]->ra; ++ ++ if (raCtx && raCtx->IsGameLoaded()) ++ { ++ auto* gameInfo = raCtx->GetCurrentGameInfo(); ++ uint32_t gameID = gameInfo ? gameInfo->id : 0; ++ ++ if (gameID != 0) ++ { ++ currentRASeconds++; ++ if (currentRASeconds % 60 == 0) ++ { ++ std::string gameKey = std::to_string(gameID); ++ int totalTime = Config::GetRAPlaytimeTable().GetInt(gameKey); ++ Config::GetRAPlaytimeTable().SetInt(gameKey, totalTime + 60); ++ Config::Save(); ++ } ++ } ++ } ++ } ++} ++#endif ++ + int main(int argc, char** argv) + { + sysTimer.start(); +@@ -366,6 +403,13 @@ int main(int argc, char** argv) + + createEmuInstance(); + ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ if (emuInstances[0]) ++ { ++ emuInstances[0]->SyncRetroAchievementsFromConfig(); ++ } ++ #endif ++ + { + MainWindow* win = emuInstances[0]->getMainWindow(); + bool memberSyntaxUsed = false; +@@ -394,6 +438,14 @@ int main(int argc, char** argv) + win->toggleFullscreen(); + } + ++ #ifdef RETROACHIEVEMENTS_ENABLED ++ raPlaytimeTimer = new QTimer(&melon); ++ QObject::connect(raPlaytimeTimer, &QTimer::timeout, []() { ++ updateRAPlaytime(); ++ }); ++ raPlaytimeTimer->start(1000); ++ #endif ++ + int ret = melon.exec(); + + delete options; +diff -rupbN melonDS.orig/src/frontend/qt_sdl/retroachievements/resources/ra.qrc melonDS.ra/src/frontend/qt_sdl/retroachievements/resources/ra.qrc +--- melonDS.orig/src/frontend/qt_sdl/retroachievements/resources/ra.qrc 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/frontend/qt_sdl/retroachievements/resources/ra.qrc 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,10 @@ ++ ++ ++ ++ icons/placeholder.png ++ icons/ra-icon.png ++ ++ ++ sounds/unlock.wav ++ ++ +\ No newline at end of file +diff -rupbN melonDS.orig/src/frontend/qt_sdl/toast/BadgeCache.cpp melonDS.ra/src/frontend/qt_sdl/toast/BadgeCache.cpp +--- melonDS.orig/src/frontend/qt_sdl/toast/BadgeCache.cpp 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/frontend/qt_sdl/toast/BadgeCache.cpp 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,50 @@ ++#include "BadgeCache.h" ++#include ++#include ++ ++BadgeCache::BadgeCache(QObject* parent) ++ : QObject(parent) ++{} ++ ++QPixmap BadgeCache::GetBadge(const QString& url) ++{ ++ if (m_cache.contains(url)) ++ return m_cache[url]; ++ ++ DownloadBadge(url, [](const QPixmap&){}); ++ ++ return QPixmap(":/ra/placeholder.png"); ++} ++ ++void BadgeCache::DownloadBadge(const QString& url, std::function callback) ++{ ++ if (QThread::currentThread() != thread()) ++ { ++ QMetaObject::invokeMethod(this, [this, url, callback]() { ++ DownloadBadge(url, callback); ++ }, Qt::QueuedConnection); ++ return; ++ } ++ ++ if (m_cache.contains(url)) { ++ callback(m_cache[url]); ++ return; ++ } ++ ++ QNetworkRequest req{ QUrl(url) }; ++ auto* reply = m_net.get(req); ++ ++ QObject::connect(reply, &QNetworkReply::finished, [this, reply, url, callback]() { ++ QPixmap pix; ++ if (reply->error() == QNetworkReply::NoError) ++ pix.loadFromData(reply->readAll()); ++ ++ if (pix.isNull()) ++ pix = QPixmap(":/ra/placeholder.png"); ++ ++ m_cache[url] = pix; ++ emit BadgeReady(url, pix); ++ callback(pix); ++ reply->deleteLater(); ++ }); ++} +diff -rupbN melonDS.orig/src/frontend/qt_sdl/toast/BadgeCache.h melonDS.ra/src/frontend/qt_sdl/toast/BadgeCache.h +--- melonDS.orig/src/frontend/qt_sdl/toast/BadgeCache.h 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/frontend/qt_sdl/toast/BadgeCache.h 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,21 @@ ++#pragma once ++#include ++#include ++ ++class BadgeCache : public QObject ++{ ++ Q_OBJECT ++public: ++ explicit BadgeCache(QObject* parent = nullptr); ++ ++ QPixmap GetBadge(const QString& url); ++ void DownloadBadge(const QString& url, ++ std::function callback); ++ ++signals: ++ void BadgeReady(const QString& url, const QPixmap& pix); ++ ++private: ++ QNetworkAccessManager m_net; ++ QHash m_cache; ++}; +\ No newline at end of file +diff -rupbN melonDS.orig/src/frontend/qt_sdl/toast/ToastManager.cpp melonDS.ra/src/frontend/qt_sdl/toast/ToastManager.cpp +--- melonDS.orig/src/frontend/qt_sdl/toast/ToastManager.cpp 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/frontend/qt_sdl/toast/ToastManager.cpp 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,149 @@ ++#include "ToastManager.h" ++#include "toast/ToastOverlay.h" ++#include ++#include "Config.h" ++#include "Window.h" ++#include "EmuInstance.h" ++ ++ToastManager::ToastManager(QObject* parent) ++ : QObject(parent) ++{ ++} ++ ++void ToastManager::Init(QWidget* widget) ++{ ++ if (m_overlay) return; ++ m_overlay = new ToastOverlay(widget); ++ ++ m_overlay->setGeometry(widget->rect()); ++ widget->installEventFilter(m_overlay); ++ m_overlay->show(); ++ m_overlay->raise(); ++} ++ ++void ToastManager::EnsureOnTop() ++{ ++ if (!m_overlay) return; ++ m_overlay->raise(); ++ if (m_leaderboardLabel) m_leaderboardLabel->raise(); ++ if (m_networkLabel) m_networkLabel->raise(); ++} ++ ++void ToastManager::ShowAchievement(const QString& title, const QString& description, const QPixmap& icon) ++{ ++ if (!m_overlay) return; ++ EnsureOnTop(); ++ m_overlay->ShowToast(title, description, icon); ++} ++ ++void ToastManager::ShowLeaderboardToast(const QString& title, const QString& description, const QPixmap& icon, bool playSound) ++{ ++ if (!m_overlay) return; ++ EnsureOnTop(); ++ m_overlay->ShowLeaderboardToast(title, description, icon, false); ++} ++ ++void ToastManager::ShowProgress(const QString& title, const QString& description, const QPixmap& icon) ++{ ++ if (!m_overlay) return; ++ EnsureOnTop(); ++ m_overlay->ShowToast(title, description, icon, false); ++} ++ ++void ToastManager::ShowChallengeIndicator(const QPixmap& icon, const QString& badgeName) ++{ ++ if (!m_overlay) return; ++ EnsureOnTop(); ++ m_overlay->ShowChallenge(icon, badgeName); ++} ++ ++void ToastManager::HideChallengeIndicator(const QString& badgeName) ++{ ++ if (m_overlay) ++ m_overlay->HideChallenge(badgeName); ++} ++ ++void ToastManager::UpdateLeaderboardTracker(const QString& display) ++{ ++ MainWindow* mainWin = qobject_cast(this->parent()); ++ ++ if (mainWin) { ++ if (mainWin->getEmuInstance()->getLocalConfig().GetBool("RetroAchievements.HideLeaderboardCounter")) { ++ if (m_leaderboardLabel) m_leaderboardLabel->hide(); ++ return; ++ } ++ } ++ ++ QWidget* parent = qobject_cast(this->parent()); ++ if (!parent) return; ++ ++ if (display.isEmpty()) { ++ if (m_leaderboardLabel) m_leaderboardLabel->hide(); ++ return; ++ } ++ ++ if (!m_leaderboardLabel) { ++ m_leaderboardLabel = new QLabel(parent); ++ m_leaderboardLabel->setStyleSheet( ++ "background-color: rgba(0, 0, 0, 160);" ++ "color: white;" ++ "padding: 4px 8px;" ++ "border-radius: 4px;" ++ "font-family: 'Consolas', 'Monospace';" ++ "font-weight: bold;" ++ "font-size: 13px;" ++ ); ++ m_leaderboardLabel->setAttribute(Qt::WA_TransparentForMouseEvents); ++ } ++ ++ m_leaderboardLabel->setText(display); ++ m_leaderboardLabel->adjustSize(); ++ ++ int x = parent->width() - m_leaderboardLabel->width() - 10; ++ int y = parent->height() - m_leaderboardLabel->height() - 10; ++ ++ m_leaderboardLabel->move(x, y); ++ m_leaderboardLabel->show(); ++ m_leaderboardLabel->raise(); ++} ++ ++void ToastManager::UpdateNetworkStatus(const QString& display) ++{ ++ QWidget* parent = qobject_cast(this->parent()); ++ if (!parent) return; ++ ++ if (display.isEmpty()) { ++ if (m_networkLabel) m_networkLabel->hide(); ++ return; ++ } ++ ++ if (!m_networkLabel) { ++ m_networkLabel = new QLabel(parent); ++ m_networkLabel->setStyleSheet( ++ "background-color: rgba(0, 0, 0, 180);" ++ "color: white;" ++ "padding: 4px 8px;" ++ "font-family: 'Consolas', 'Monospace';" ++ "font-weight: bold;" ++ ); ++ m_networkLabel->setAttribute(Qt::WA_TransparentForMouseEvents); ++ } ++ ++ m_networkLabel->setText(display); ++ m_networkLabel->adjustSize(); ++ ++ int offset = (m_leaderboardLabel && m_leaderboardLabel->isVisible()) ++ ? m_leaderboardLabel->height() + 15 : 10; ++ int x = parent->width() - m_networkLabel->width() - 10; ++ int y = parent->height() - m_networkLabel->height() - offset; ++ ++ m_networkLabel->move(x, y); ++ m_networkLabel->show(); ++ m_networkLabel->raise(); ++} ++ ++void ToastManager::ClearAll() ++{ ++ if (m_overlay) ++ m_overlay->HideChallenge(""); ++} +diff -rupbN melonDS.orig/src/frontend/qt_sdl/toast/ToastManager.h melonDS.ra/src/frontend/qt_sdl/toast/ToastManager.h +--- melonDS.orig/src/frontend/qt_sdl/toast/ToastManager.h 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/frontend/qt_sdl/toast/ToastManager.h 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,26 @@ ++#pragma once ++#include ++#include ++class ToastOverlay; ++class ToastManager : public QObject ++{ ++ Q_OBJECT ++public: ++ void UpdateNetworkStatus(const QString& display); ++ void UpdateLeaderboardTracker(const QString& display); ++ explicit ToastManager(QObject* parent = nullptr); ++ void Init(QWidget* screenWidget); ++ void ShowAchievement(const QString& title, ++ const QString& desc, ++ const QPixmap& icon); ++ void ShowLeaderboardToast(const QString& title, const QString& description, const QPixmap& icon, bool playSound = true); ++ void ShowProgress(const QString& title, const QString& description, const QPixmap& icon); ++ void ShowChallengeIndicator(const QPixmap& icon, const QString& badgeName); ++ void HideChallengeIndicator(const QString& badgeName = ""); ++ void ClearAll(); ++private: ++ void EnsureOnTop(); ++ QLabel* m_leaderboardLabel = nullptr; ++ QLabel* m_networkLabel = nullptr; ++ ToastOverlay* m_overlay = nullptr; ++}; +diff -rupbN melonDS.orig/src/frontend/qt_sdl/toast/ToastOverlay.cpp melonDS.ra/src/frontend/qt_sdl/toast/ToastOverlay.cpp +--- melonDS.orig/src/frontend/qt_sdl/toast/ToastOverlay.cpp 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/frontend/qt_sdl/toast/ToastOverlay.cpp 2026-03-06 21:38:33.640023242 +0000 +@@ -0,0 +1,377 @@ ++#include "ToastOverlay.h" ++#include ++#include ++#include ++#include ++#include ++#include "Config.h" ++#include "EmuInstance.h" ++#include "Window.h" ++ ++static float ComputeToastScale(const QSize& size) ++{ ++ constexpr float refShortSide = 384.0f; ++ float shortSide = std::min(size.width(), size.height()); ++ float scale = shortSide / refShortSide; ++ return std::clamp(scale, 0.975f, 1.875f); ++} ++ ++static int ConfigureLabelAutoFit(QLabel* label, const QString& text, int maxWidth) ++{ ++ if (text.isEmpty()) return 0; ++ ++ label->setText(text); ++ QFont font = label->font(); ++ QFontMetrics fm(font); ++ int textWidth = fm.horizontalAdvance(text); ++ ++ if (textWidth <= maxWidth) { ++ label->setFont(font); ++ label->setWordWrap(false); ++ return textWidth; ++ } ++ ++ float originalSize = font.pointSizeF(); ++ if (originalSize <= 0) originalSize = 10.0f; ++ ++ QFont smallerFont = font; ++ smallerFont.setPointSizeF(originalSize * 0.85f); ++ QFontMetrics fmSmall(smallerFont); ++ ++ if (fmSmall.horizontalAdvance(text) <= maxWidth) { ++ label->setFont(smallerFont); ++ label->setWordWrap(false); ++ return fmSmall.horizontalAdvance(text); ++ } ++ ++ label->setFont(font); ++ label->setWordWrap(true); ++ label->setMinimumWidth(maxWidth); ++ return maxWidth; ++} ++ ++ToastWidget::ToastWidget( ++ const QString& title, ++ const QString& description, ++ const QPixmap& icon, ++ float scale, ++ int maxWidth, ++ QWidget* parent ++) : QWidget(parent) ++{ ++ const int iconSize = int(66 * scale); ++ const int marginsH = int(10 * scale) + int(12 * scale) + int(8 * scale); ++ const int maxTextWidth = maxWidth - iconSize - marginsH; ++ ++ auto* layout = new QHBoxLayout(this); ++ layout->setSpacing(int(8 * scale)); ++ layout->setContentsMargins(int(10 * scale), int(8 * scale), int(12 * scale), int(8 * scale)); ++ ++ auto* iconLabel = new QLabel; ++ iconLabel->setPixmap(icon.scaled(iconSize, iconSize, Qt::KeepAspectRatio, Qt::SmoothTransformation)); ++ iconLabel->setFixedSize(iconSize, iconSize); ++ iconLabel->setAlignment(Qt::AlignCenter); ++ layout->addWidget(iconLabel); ++ ++ float basePt = font().pointSizeF(); ++ if (basePt <= 0) basePt = 10.0f; ++ int titlePt = qRound(basePt * scale); ++ int descPt = qRound(basePt * scale * 0.85f); ++ ++ if (!title.isEmpty() || !description.isEmpty()) { ++ auto* textLayout = new QVBoxLayout(); ++ textLayout->setSpacing(int(0 * scale)); ++ textLayout->setContentsMargins(0, 0, 0, 0); ++ ++ int actualTitleW = 0; ++ int actualDescW = 0; ++ ++ if (!title.isEmpty()) { ++ auto* titleLabel = new QLabel; ++ titleLabel->setStyleSheet(QString("font-weight: bold; color: white; background: transparent; padding-left: 2px; font-size: %1pt;").arg(titlePt)); ++ actualTitleW = ConfigureLabelAutoFit(titleLabel, title, maxTextWidth); ++ titleLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum); ++ titleLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); ++ textLayout->addWidget(titleLabel); ++ } ++ ++ if (!description.isEmpty()) { ++ auto* descLabel = new QLabel; ++ descLabel->setStyleSheet(QString("color: #bbb; background: transparent; padding-left: 2px; font-size: %1pt;").arg(descPt)); ++ actualDescW = ConfigureLabelAutoFit(descLabel, description, maxTextWidth); ++ descLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); ++ descLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); ++ textLayout->addWidget(descLabel); ++ } ++ ++ layout->addLayout(textLayout); ++ ++ setMinimumWidth(int(120 * scale)); ++ setMaximumWidth(maxWidth); ++ adjustSize(); ++ } ++ else { ++ setFixedWidth(iconSize + marginsH); ++ } ++ ++ setAttribute(Qt::WA_StyledBackground, false); ++ setAttribute(Qt::WA_TranslucentBackground); ++ setStyleSheet("background: transparent;"); ++} ++ ++QSize ToastWidget::sizeHint() const ++{ ++ return layout()->sizeHint(); ++} ++ ++void ToastWidget::paintEvent(QPaintEvent*) ++{ ++ QPainter p(this); ++ p.setRenderHint(QPainter::Antialiasing); ++ QRect r = rect().adjusted(1, 1, -1, -1); ++ p.setBrush(QColor(40, 40, 40, 230)); ++ p.setPen(Qt::NoPen); ++ p.drawRoundedRect(r, 8, 8); ++} ++ ++ToastOverlay::ToastOverlay(QWidget* parent) ++ : QGraphicsView(static_cast(nullptr)) ++ , m_anchor(parent) ++{ ++ m_scene = new QGraphicsScene(this); ++ setScene(m_scene); ++ setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | ++ Qt::WindowStaysOnTopHint | Qt::WindowDoesNotAcceptFocus | ++ Qt::WindowTransparentForInput); ++ setAttribute(Qt::WA_ShowWithoutActivating); ++ setAttribute(Qt::WA_NoSystemBackground); ++ setWindowFlag(Qt::X11BypassWindowManagerHint); ++ setFrameShape(QFrame::NoFrame); ++ setBackgroundRole(QPalette::NoRole); ++ setStyleSheet("background: transparent; border: none;"); ++ setAttribute(Qt::WA_TransparentForMouseEvents); ++ setAttribute(Qt::WA_TranslucentBackground); ++ setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); ++ setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); ++ setRenderHint(QPainter::Antialiasing); ++ ++ m_soundEffect.setSource(QUrl("qrc:/ra/sounds/unlock.wav")); ++ m_soundEffect.setVolume(0.7f); ++} ++ ++void ToastOverlay::ShowToast(const QString& title, const QString& description, const QPixmap& icon, bool playSound) ++{ ++ MainWindow* mainWin = qobject_cast(m_anchor); ++ if (mainWin) { ++ if (mainWin->getEmuInstance()->getLocalConfig().GetBool("RetroAchievements.HideToasts")) { ++ return; ++ } ++ } ++ if (!m_anchor) return; ++ float scale = ComputeToastScale(m_anchor->size()); ++ const int maxToastWidth = int(m_anchor->width() * 0.825f); ++ ++ auto* toast = new ToastWidget(title, description, icon, scale, maxToastWidth); ++ QGraphicsProxyWidget* proxy = m_scene->addWidget(toast); ++ m_toastProxies.append(proxy); ++ if (playSound) { ++ m_soundEffect.play(); ++ } ++ ++ RepositionToasts(); ++ ++ QTimer::singleShot(3000, this, [this, proxy]() { ++ m_toastProxies.removeOne(proxy); ++ m_scene->removeItem(proxy); ++ if (proxy->widget()) proxy->widget()->deleteLater(); ++ delete proxy; ++ RepositionToasts(); ++ }); ++} ++ ++void ToastOverlay::ShowChallenge(const QPixmap& icon, const QString& badgeName) ++{ ++ MainWindow* mainWin = qobject_cast(m_anchor); ++ if (mainWin) { ++ if (mainWin->getEmuInstance()->getLocalConfig().GetBool("RetroAchievements.HideChallengeIndicators")) { ++ return; ++ } ++ } ++ ++ if (!m_anchor || icon.isNull()) return; ++ ++ float scale = ComputeToastScale(m_anchor->size()); ++ int scaledSize = int(48 * scale); ++ ++ QLabel* label = new QLabel(); ++ label->setPixmap(icon.scaled(scaledSize, scaledSize, Qt::KeepAspectRatio, Qt::SmoothTransformation)); ++ label->setStyleSheet("background: transparent; border: none; padding: 0px;"); ++ label->setAttribute(Qt::WA_TransparentForMouseEvents); ++ label->adjustSize(); ++ ++ QGraphicsProxyWidget* proxy = m_scene->addWidget(label); ++ proxy->setProperty("badgeName", badgeName); ++ ++ m_challengeProxies.append(proxy); ++ RepositionChallenge(); ++} ++ ++void ToastOverlay::ShowLeaderboardToast( ++ const QString& title, ++ const QString& description, ++ const QPixmap& icon, ++ bool playSound ++) ++{ ++ MainWindow* mainWin = qobject_cast(m_anchor); ++ if (mainWin) ++ { ++ if (mainWin->getEmuInstance()->getLocalConfig().GetBool("RetroAchievements.HideLeaderboardToasts")) { ++ return; ++ } ++ } ++ ++ ShowToast(title, description, icon, playSound); ++} ++ ++void ToastOverlay::HideChallenge(const QString& badgeName) ++{ ++ if (badgeName.isEmpty()) { ++ for (auto* proxy : m_challengeProxies) { ++ m_scene->removeItem(proxy); ++ if (proxy->widget()) proxy->widget()->deleteLater(); ++ delete proxy; ++ } ++ m_challengeProxies.clear(); ++ } else { ++ for (int i = 0; i < m_challengeProxies.size(); ++i) { ++ if (m_challengeProxies[i]->property("badgeName").toString() == badgeName) { ++ auto* proxy = m_challengeProxies.takeAt(i); ++ m_scene->removeItem(proxy); ++ if (proxy->widget()) proxy->widget()->deleteLater(); ++ delete proxy; ++ break; ++ } ++ } ++ } ++ RepositionChallenge(); ++} ++ ++void ToastOverlay::RepositionToasts() ++{ ++ if (!m_anchor) return; ++ int rotMode = Config::GetLocalTable(0).GetInt("Window0.ScreenRotation"); ++ int angle = rotMode * 90; ++ QRect pRect = m_anchor->rect(); ++ m_scene->setSceneRect(0, 0, pRect.width(), pRect.height()); ++ ++ const int margin = 20; ++ int offset = 60; ++ ++ for (auto* proxy : m_toastProxies) ++ { ++ proxy->widget()->adjustSize(); ++ QSize s = proxy->widget()->size(); ++ proxy->setTransformOriginPoint(s.width() / 2.0, s.height() / 2.0); ++ proxy->setRotation(angle); ++ ++ int finalW = (rotMode % 2 == 0) ? s.width() : s.height(); ++ int finalH = (rotMode % 2 == 0) ? s.height() : s.width(); ++ int centerX, centerY; ++ ++ if (rotMode == 0) { ++ centerX = margin + finalW / 2; ++ centerY = offset + finalH / 2; ++ } else if (rotMode == 1) { ++ centerX = pRect.width() - offset - finalW / 2; ++ centerY = pRect.height() - margin - finalH / 2; ++ } else if (rotMode == 2) { ++ centerX = margin + finalW / 2; ++ centerY = pRect.height() - offset - finalH / 2; ++ } else { ++ centerX = offset + finalW / 2; ++ centerY = margin + finalH / 2; ++ } ++ ++ proxy->setPos(centerX - s.width() / 2.0, centerY - s.height() / 2.0); ++ offset += finalH + 10; ++ } ++} ++ ++void ToastOverlay::RepositionChallenge() ++{ ++ if (m_challengeProxies.isEmpty() || !m_anchor) return; ++ ++ int rotMode = Config::GetLocalTable(0).GetInt("Window0.ScreenRotation"); ++ int angle = rotMode * 90; ++ QRect pRect = m_anchor->rect(); ++ ++ const int margin = 20; ++ const int spacing = 8; ++ int currentOffset = 0; ++ ++ for (auto* proxy : m_challengeProxies) { ++ proxy->widget()->adjustSize(); ++ QSize s = proxy->widget()->size(); ++ ++ proxy->setTransformOriginPoint(s.width() / 2.0, s.height() / 2.0); ++ proxy->setRotation(angle); ++ ++ int finalW = (rotMode % 2 == 0) ? s.width() : s.height(); ++ int finalH = (rotMode % 2 == 0) ? s.height() : s.width(); ++ ++ int centerX, centerY; ++ ++ if (rotMode == 0) { ++ centerX = pRect.width() - margin - (finalW / 2) - currentOffset; ++ centerY = pRect.height() - margin - (finalH / 2); ++ } else if (rotMode == 1) { ++ centerX = margin + (finalW / 2); ++ centerY = pRect.height() - margin - (finalH / 2) - currentOffset; ++ } else if (rotMode == 2) { ++ centerX = margin + (finalW / 2) + currentOffset; ++ centerY = margin + (finalH / 2); ++ } else { ++ centerX = pRect.width() - margin - (finalW / 2); ++ centerY = margin + (finalH / 2) + currentOffset; ++ } ++ ++ proxy->setPos(centerX - s.width() / 2.0, centerY - s.height() / 2.0); ++ currentOffset += (rotMode % 2 == 0 ? finalW : finalH) + spacing; ++ } ++} ++ ++void ToastOverlay::resizeEvent(QResizeEvent* event) ++{ ++ if (m_anchor) ++ { ++ QPoint globalPos = m_anchor->mapToGlobal(QPoint(0, 0)); ++ setGeometry(globalPos.x(), globalPos.y(), m_anchor->width(), m_anchor->height()); ++ } ++ RepositionToasts(); ++ RepositionChallenge(); ++ QGraphicsView::resizeEvent(event); ++} ++ ++bool ToastOverlay::eventFilter(QObject* obj, QEvent* event) ++{ ++ if (obj == m_anchor || obj == m_anchor->window()) ++ { ++ if (event->type() == QEvent::Resize || ++ event->type() == QEvent::Move || ++ event->type() == QEvent::WindowStateChange) ++ { ++ if (m_anchor) ++ { ++ if (!m_anchor->window()->isMinimized()) ++ { ++ QPoint globalPos = m_anchor->mapToGlobal(QPoint(0, 0)); ++ setGeometry(globalPos.x(), globalPos.y(), m_anchor->width(), m_anchor->height()); ++ RepositionToasts(); ++ RepositionChallenge(); ++ } ++ } ++ } ++ } ++ return QGraphicsView::eventFilter(obj, event); ++} +diff -rupbN melonDS.orig/src/frontend/qt_sdl/toast/ToastOverlay.h melonDS.ra/src/frontend/qt_sdl/toast/ToastOverlay.h +--- melonDS.orig/src/frontend/qt_sdl/toast/ToastOverlay.h 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/frontend/qt_sdl/toast/ToastOverlay.h 2026-03-06 21:39:48.805083859 +0000 +@@ -0,0 +1,52 @@ ++#pragma once ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++class ToastWidget : public QWidget ++{ ++ Q_OBJECT ++public: ++ ToastWidget(const QString& title, ++ const QString& description, ++ const QPixmap& icon, ++ float scale, ++ int maxWidth, ++ QWidget* parent = nullptr); ++ QSize sizeHint() const override; ++ ++protected: ++ void paintEvent(QPaintEvent* event) override; ++}; ++ ++class ToastOverlay : public QGraphicsView ++{ ++ Q_OBJECT ++public: ++ explicit ToastOverlay(QWidget* parent = nullptr); ++ void ShowToast(const QString& title, const QString& description, const QPixmap& icon, bool playSound = true); ++ void ShowLeaderboardToast(const QString& title, const QString& description, const QPixmap& icon, bool playSound = true); ++ void ShowChallenge(const QPixmap& icon, const QString& badgeName); ++ void HideChallenge(const QString& badgeName = ""); ++ ++protected: ++ bool eventFilter(QObject* obj, QEvent* event) override; ++ void resizeEvent(QResizeEvent* event) override; ++ ++private: ++ void RepositionToasts(); ++ void RepositionChallenge(); ++ QGraphicsScene* m_scene = nullptr; ++ QList m_toastProxies; ++ QList m_challengeProxies; ++ QSoundEffect m_soundEffect; ++ QWidget* m_anchor = nullptr; ++}; +diff -rupbN melonDS.orig/src/rcheevos/include/rc_api_editor.h melonDS.ra/src/rcheevos/include/rc_api_editor.h +--- melonDS.orig/src/rcheevos/include/rc_api_editor.h 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/include/rc_api_editor.h 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,296 @@ ++#ifndef RC_API_EDITOR_H ++#define RC_API_EDITOR_H ++ ++#include "rc_api_request.h" ++ ++#include ++ ++RC_BEGIN_C_DECLS ++ ++/* --- Fetch Code Notes --- */ ++ ++/** ++ * API parameters for a fetch code notes request. ++ */ ++typedef struct rc_api_fetch_code_notes_request_t { ++ /* The unique identifier of the game */ ++ uint32_t game_id; ++} ++rc_api_fetch_code_notes_request_t; ++ ++/* A code note definiton */ ++typedef struct rc_api_code_note_t { ++ /* The address the note is associated to */ ++ uint32_t address; ++ /* The name of the use who last updated the note */ ++ const char* author; ++ /* The contents of the note */ ++ const char* note; ++} rc_api_code_note_t; ++ ++/** ++ * Response data for a fetch code notes request. ++ */ ++typedef struct rc_api_fetch_code_notes_response_t { ++ /* An array of code notes for the game */ ++ rc_api_code_note_t* notes; ++ /* The number of items in the notes array */ ++ uint32_t num_notes; ++ ++ /* Common server-provided response information */ ++ rc_api_response_t response; ++} ++rc_api_fetch_code_notes_response_t; ++ ++RC_EXPORT int RC_CCONV rc_api_init_fetch_code_notes_request(rc_api_request_t* request, const rc_api_fetch_code_notes_request_t* api_params); ++RC_EXPORT int RC_CCONV rc_api_init_fetch_code_notes_request_hosted(rc_api_request_t* request, const rc_api_fetch_code_notes_request_t* api_params, const rc_api_host_t* host); ++/* [deprecated] use rc_api_process_fetch_code_notes_server_response instead */ ++RC_EXPORT int RC_CCONV rc_api_process_fetch_code_notes_response(rc_api_fetch_code_notes_response_t* response, const char* server_response); ++RC_EXPORT int RC_CCONV rc_api_process_fetch_code_notes_server_response(rc_api_fetch_code_notes_response_t* response, const rc_api_server_response_t* server_response); ++RC_EXPORT void RC_CCONV rc_api_destroy_fetch_code_notes_response(rc_api_fetch_code_notes_response_t* response); ++ ++/* --- Update Code Note --- */ ++ ++/** ++ * API parameters for an update code note request. ++ */ ++typedef struct rc_api_update_code_note_request_t { ++ /* The username of the developer */ ++ const char* username; ++ /* The API token from the login request */ ++ const char* api_token; ++ /* The unique identifier of the game */ ++ uint32_t game_id; ++ /* The address the note is associated to */ ++ uint32_t address; ++ /* The contents of the note (NULL or empty to delete a note) */ ++ const char* note; ++} ++rc_api_update_code_note_request_t; ++ ++/** ++ * Response data for an update code note request. ++ */ ++typedef struct rc_api_update_code_note_response_t { ++ /* Common server-provided response information */ ++ rc_api_response_t response; ++} ++rc_api_update_code_note_response_t; ++ ++RC_EXPORT int RC_CCONV rc_api_init_update_code_note_request(rc_api_request_t* request, const rc_api_update_code_note_request_t* api_params); ++RC_EXPORT int RC_CCONV rc_api_init_update_code_note_request_hosted(rc_api_request_t* request, const rc_api_update_code_note_request_t* api_params, const rc_api_host_t* host); ++/* [deprecated] use rc_api_process_update_code_note_server_response instead */ ++RC_EXPORT int RC_CCONV rc_api_process_update_code_note_response(rc_api_update_code_note_response_t* response, const char* server_response); ++RC_EXPORT int RC_CCONV rc_api_process_update_code_note_server_response(rc_api_update_code_note_response_t* response, const rc_api_server_response_t* server_response); ++RC_EXPORT void RC_CCONV rc_api_destroy_update_code_note_response(rc_api_update_code_note_response_t* response); ++ ++/* --- Update Achievement --- */ ++ ++/** ++ * API parameters for an update achievement request. ++ */ ++typedef struct rc_api_update_achievement_request_t { ++ /* The username of the developer */ ++ const char* username; ++ /* The API token from the login request */ ++ const char* api_token; ++ /* The unique identifier of the achievement (0 to create a new achievement) */ ++ uint32_t achievement_id; ++ /* The unique identifier of the game */ ++ uint32_t game_id; ++ /* The name of the achievement */ ++ const char* title; ++ /* The description of the achievement */ ++ const char* description; ++ /* The badge name for the achievement */ ++ const char* badge; ++ /* The serialized trigger for the achievement */ ++ const char* trigger; ++ /* The number of points the achievement is worth */ ++ uint32_t points; ++ /* The category of the achievement */ ++ uint32_t category; ++ /* The type of the achievement */ ++ uint32_t type; ++} ++rc_api_update_achievement_request_t; ++ ++/** ++ * Response data for an update achievement request. ++ */ ++typedef struct rc_api_update_achievement_response_t { ++ /* The unique identifier of the achievement */ ++ uint32_t achievement_id; ++ ++ /* Common server-provided response information */ ++ rc_api_response_t response; ++} ++rc_api_update_achievement_response_t; ++ ++RC_EXPORT int RC_CCONV rc_api_init_update_achievement_request(rc_api_request_t* request, const rc_api_update_achievement_request_t* api_params); ++RC_EXPORT int RC_CCONV rc_api_init_update_achievement_request_hosted(rc_api_request_t* request, const rc_api_update_achievement_request_t* api_params, const rc_api_host_t* host); ++/* [deprecated] use rc_api_process_update_achievement_server_response instead */ ++RC_EXPORT int RC_CCONV rc_api_process_update_achievement_response(rc_api_update_achievement_response_t* response, const char* server_response); ++RC_EXPORT int RC_CCONV rc_api_process_update_achievement_server_response(rc_api_update_achievement_response_t* response, const rc_api_server_response_t* server_response); ++RC_EXPORT void RC_CCONV rc_api_destroy_update_achievement_response(rc_api_update_achievement_response_t* response); ++ ++/* --- Update Leaderboard --- */ ++ ++/** ++ * API parameters for an update leaderboard request. ++ */ ++typedef struct rc_api_update_leaderboard_request_t { ++ /* The username of the developer */ ++ const char* username; ++ /* The API token from the login request */ ++ const char* api_token; ++ /* The unique identifier of the leaderboard (0 to create a new leaderboard) */ ++ uint32_t leaderboard_id; ++ /* The unique identifier of the game */ ++ uint32_t game_id; ++ /* The name of the leaderboard */ ++ const char* title; ++ /* The description of the leaderboard */ ++ const char* description; ++ /* The start trigger for the leaderboard */ ++ const char* start_trigger; ++ /* The submit trigger for the leaderboard */ ++ const char* submit_trigger; ++ /* The cancel trigger for the leaderboard */ ++ const char* cancel_trigger; ++ /* The value definition for the leaderboard */ ++ const char* value_definition; ++ /* The format of leaderboard values */ ++ const char* format; ++ /* Whether or not lower scores are better for the leaderboard */ ++ uint32_t lower_is_better; ++} ++rc_api_update_leaderboard_request_t; ++ ++/** ++ * Response data for an update leaderboard request. ++ */ ++typedef struct rc_api_update_leaderboard_response_t { ++ /* The unique identifier of the leaderboard */ ++ uint32_t leaderboard_id; ++ ++ /* Common server-provided response information */ ++ rc_api_response_t response; ++} ++rc_api_update_leaderboard_response_t; ++ ++RC_EXPORT int RC_CCONV rc_api_init_update_leaderboard_request(rc_api_request_t* request, const rc_api_update_leaderboard_request_t* api_params); ++RC_EXPORT int RC_CCONV rc_api_init_update_leaderboard_request_hosted(rc_api_request_t* request, const rc_api_update_leaderboard_request_t* api_params, const rc_api_host_t* host); ++/* [deprecated] use rc_api_process_update_leaderboard_server_response instead */ ++RC_EXPORT int RC_CCONV rc_api_process_update_leaderboard_response(rc_api_update_leaderboard_response_t* response, const char* server_response); ++RC_EXPORT int RC_CCONV rc_api_process_update_leaderboard_server_response(rc_api_update_leaderboard_response_t* response, const rc_api_server_response_t* server_response); ++RC_EXPORT void RC_CCONV rc_api_destroy_update_leaderboard_response(rc_api_update_leaderboard_response_t* response); ++ ++/* --- Update Rich Presence --- */ ++ ++/** ++ * API parameters for an update rich presence request. ++ */ ++typedef struct rc_api_update_rich_presence_request_t { ++ /* The username of the developer */ ++ const char* username; ++ /* The API token from the login request */ ++ const char* api_token; ++ /* The unique identifier of the game */ ++ uint32_t game_id; ++ /* The script for the rich_presence */ ++ const char* script; ++} ++rc_api_update_rich_presence_request_t; ++ ++/** ++ * Response data for an update rich presence request. ++ */ ++typedef struct rc_api_update_rich_presence_response_t { ++ /* Common server-provided response information */ ++ rc_api_response_t response; ++} ++rc_api_update_rich_presence_response_t; ++ ++RC_EXPORT int RC_CCONV rc_api_init_update_rich_presence_request(rc_api_request_t* request, const rc_api_update_rich_presence_request_t* api_params); ++RC_EXPORT int RC_CCONV rc_api_init_update_rich_presence_request_hosted(rc_api_request_t* request, const rc_api_update_rich_presence_request_t* api_params, const rc_api_host_t* host); ++RC_EXPORT int RC_CCONV rc_api_process_update_rich_presence_server_response(rc_api_update_rich_presence_response_t* response, const rc_api_server_response_t* server_response); ++RC_EXPORT void RC_CCONV rc_api_destroy_update_rich_presence_response(rc_api_update_rich_presence_response_t* response); ++ ++/* --- Fetch Badge Range --- */ ++ ++/** ++ * API parameters for a fetch badge range request. ++ */ ++typedef struct rc_api_fetch_badge_range_request_t { ++ /* Unused */ ++ uint32_t unused; ++} ++rc_api_fetch_badge_range_request_t; ++ ++/** ++ * Response data for a fetch badge range request. ++ */ ++typedef struct rc_api_fetch_badge_range_response_t { ++ /* The numeric identifier of the first valid badge ID */ ++ uint32_t first_badge_id; ++ /* The numeric identifier of the first unassigned badge ID */ ++ uint32_t next_badge_id; ++ ++ /* Common server-provided response information */ ++ rc_api_response_t response; ++} ++rc_api_fetch_badge_range_response_t; ++ ++RC_EXPORT int RC_CCONV rc_api_init_fetch_badge_range_request(rc_api_request_t* request, const rc_api_fetch_badge_range_request_t* api_params); ++RC_EXPORT int RC_CCONV rc_api_init_fetch_badge_range_request_hosted(rc_api_request_t* request, const rc_api_fetch_badge_range_request_t* api_params, const rc_api_host_t* host); ++/* [deprecated] use rc_api_process_fetch_badge_range_server_response instead */ ++RC_EXPORT int RC_CCONV rc_api_process_fetch_badge_range_response(rc_api_fetch_badge_range_response_t* response, const char* server_response); ++RC_EXPORT int RC_CCONV rc_api_process_fetch_badge_range_server_response(rc_api_fetch_badge_range_response_t* response, const rc_api_server_response_t* server_response); ++RC_EXPORT void RC_CCONV rc_api_destroy_fetch_badge_range_response(rc_api_fetch_badge_range_response_t* response); ++ ++/* --- Add Game Hash --- */ ++ ++/** ++ * API parameters for an add game hash request. ++ */ ++typedef struct rc_api_add_game_hash_request_t { ++ /* The username of the developer */ ++ const char* username; ++ /* The API token from the login request */ ++ const char* api_token; ++ /* The unique identifier of the game (0 to create a new game entry) */ ++ uint32_t game_id; ++ /* The unique identifier of the console for the game */ ++ uint32_t console_id; ++ /* The title of the game */ ++ const char* title; ++ /* The hash being added */ ++ const char* hash; ++ /* A description of the hash being added (usually the normalized ROM name) */ ++ const char* hash_description; ++} ++rc_api_add_game_hash_request_t; ++ ++/** ++ * Response data for an update code note request. ++ */ ++typedef struct rc_api_add_game_hash_response_t { ++ /* The unique identifier of the game */ ++ uint32_t game_id; ++ ++ /* Common server-provided response information */ ++ rc_api_response_t response; ++} ++rc_api_add_game_hash_response_t; ++ ++RC_EXPORT int RC_CCONV rc_api_init_add_game_hash_request(rc_api_request_t* request, const rc_api_add_game_hash_request_t* api_params); ++RC_EXPORT int RC_CCONV rc_api_init_add_game_hash_request_hosted(rc_api_request_t* request, const rc_api_add_game_hash_request_t* api_params, const rc_api_host_t* host); ++/* [deprecated] use rc_api_process_add_game_hash_server_response instead */ ++RC_EXPORT int RC_CCONV rc_api_process_add_game_hash_response(rc_api_add_game_hash_response_t* response, const char* server_response); ++RC_EXPORT int RC_CCONV rc_api_process_add_game_hash_server_response(rc_api_add_game_hash_response_t* response, const rc_api_server_response_t* server_response); ++RC_EXPORT void RC_CCONV rc_api_destroy_add_game_hash_response(rc_api_add_game_hash_response_t* response); ++ ++RC_END_C_DECLS ++ ++#endif /* RC_EDITOR_H */ +diff -rupbN melonDS.orig/src/rcheevos/include/rc_api_info.h melonDS.ra/src/rcheevos/include/rc_api_info.h +--- melonDS.orig/src/rcheevos/include/rc_api_info.h 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/include/rc_api_info.h 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,278 @@ ++#ifndef RC_API_INFO_H ++#define RC_API_INFO_H ++ ++#include "rc_api_request.h" ++ ++#include ++#include ++ ++RC_BEGIN_C_DECLS ++ ++/* --- Fetch Achievement Info --- */ ++ ++/** ++ * API parameters for a fetch achievement info request. ++ */ ++typedef struct rc_api_fetch_achievement_info_request_t { ++ /* The username of the player */ ++ const char* username; ++ /* The API token from the login request */ ++ const char* api_token; ++ /* The unique identifier of the achievement */ ++ uint32_t achievement_id; ++ /* The 1-based index of the first entry to retrieve */ ++ uint32_t first_entry; ++ /* The number of entries to retrieve */ ++ uint32_t count; ++ /* Non-zero to only return unlocks earned by the user's friends */ ++ uint32_t friends_only; ++} ++rc_api_fetch_achievement_info_request_t; ++ ++/* An achievement awarded entry */ ++typedef struct rc_api_achievement_awarded_entry_t { ++ /* The user associated to the entry */ ++ const char* username; ++ /* A URL to the user's avatar image */ ++ const char* avatar_url; ++ /* When the achievement was awarded */ ++ time_t awarded; ++} ++rc_api_achievement_awarded_entry_t; ++ ++/** ++ * Response data for a fetch achievement info request. ++ */ ++typedef struct rc_api_fetch_achievement_info_response_t { ++ /* The unique identifier of the achievement */ ++ uint32_t id; ++ /* The unique identifier of the game to which the leaderboard is associated */ ++ uint32_t game_id; ++ /* The number of times the achievement has been awarded */ ++ uint32_t num_awarded; ++ /* The number of players that have earned at least one achievement for the game */ ++ uint32_t num_players; ++ ++ /* An array of recently rewarded entries */ ++ rc_api_achievement_awarded_entry_t* recently_awarded; ++ /* The number of items in the recently_awarded array */ ++ uint32_t num_recently_awarded; ++ ++ /* Common server-provided response information */ ++ rc_api_response_t response; ++} ++rc_api_fetch_achievement_info_response_t; ++ ++RC_EXPORT int RC_CCONV rc_api_init_fetch_achievement_info_request(rc_api_request_t* request, const rc_api_fetch_achievement_info_request_t* api_params); ++RC_EXPORT int RC_CCONV rc_api_init_fetch_achievement_info_request_hosted(rc_api_request_t* request, const rc_api_fetch_achievement_info_request_t* api_params, const rc_api_host_t* host); ++/* [deprecated] use rc_api_process_fetch_achievement_info_server_response instead */ ++RC_EXPORT int RC_CCONV rc_api_process_fetch_achievement_info_response(rc_api_fetch_achievement_info_response_t* response, const char* server_response); ++RC_EXPORT int RC_CCONV rc_api_process_fetch_achievement_info_server_response(rc_api_fetch_achievement_info_response_t* response, const rc_api_server_response_t* server_response); ++RC_EXPORT void RC_CCONV rc_api_destroy_fetch_achievement_info_response(rc_api_fetch_achievement_info_response_t* response); ++ ++/* --- Fetch Leaderboard Info --- */ ++ ++/** ++ * API parameters for a fetch leaderboard info request. ++ */ ++typedef struct rc_api_fetch_leaderboard_info_request_t { ++ /* The unique identifier of the leaderboard */ ++ uint32_t leaderboard_id; ++ /* The number of entries to retrieve */ ++ uint32_t count; ++ /* The 1-based index of the first entry to retrieve */ ++ uint32_t first_entry; ++ /* The username of the player around whom the entries should be returned */ ++ const char* username; ++} ++rc_api_fetch_leaderboard_info_request_t; ++ ++/* A leaderboard info entry */ ++typedef struct rc_api_lboard_info_entry_t { ++ /* The user associated to the entry */ ++ const char* username; ++ /* A URL to the user's avatar image */ ++ const char* avatar_url; ++ /* The rank of the entry */ ++ uint32_t rank; ++ /* The index of the entry */ ++ uint32_t index; ++ /* The value of the entry */ ++ int32_t score; ++ /* When the entry was submitted */ ++ time_t submitted; ++} ++rc_api_lboard_info_entry_t; ++ ++/** ++ * Response data for a fetch leaderboard info request. ++ */ ++typedef struct rc_api_fetch_leaderboard_info_response_t { ++ /* The unique identifier of the leaderboard */ ++ uint32_t id; ++ /* The format to pass to rc_format_value to format the leaderboard value */ ++ int format; ++ /* If non-zero, indicates that lower scores appear first */ ++ uint32_t lower_is_better; ++ /* The title of the leaderboard */ ++ const char* title; ++ /* The description of the leaderboard */ ++ const char* description; ++ /* The definition of the leaderboard to be passed to rc_runtime_activate_lboard */ ++ const char* definition; ++ /* The unique identifier of the game to which the leaderboard is associated */ ++ uint32_t game_id; ++ /* The author of the leaderboard */ ++ const char* author; ++ /* When the leaderboard was first uploaded to the server */ ++ time_t created; ++ /* When the leaderboard was last modified on the server */ ++ time_t updated; ++ ++ /* An array of requested entries */ ++ rc_api_lboard_info_entry_t* entries; ++ /* The number of items in the entries array */ ++ uint32_t num_entries; ++ ++ /* The total number of entries on the server */ ++ uint32_t total_entries; ++ ++ /* Common server-provided response information */ ++ rc_api_response_t response; ++} ++rc_api_fetch_leaderboard_info_response_t; ++ ++RC_EXPORT int RC_CCONV rc_api_init_fetch_leaderboard_info_request(rc_api_request_t* request, const rc_api_fetch_leaderboard_info_request_t* api_params); ++RC_EXPORT int RC_CCONV rc_api_init_fetch_leaderboard_info_request_hosted(rc_api_request_t* request, const rc_api_fetch_leaderboard_info_request_t* api_params, const rc_api_host_t* host); ++/* [deprecated] use rc_api_process_fetch_leaderboard_info_server_response instead */ ++RC_EXPORT int RC_CCONV rc_api_process_fetch_leaderboard_info_response(rc_api_fetch_leaderboard_info_response_t* response, const char* server_response); ++RC_EXPORT int RC_CCONV rc_api_process_fetch_leaderboard_info_server_response(rc_api_fetch_leaderboard_info_response_t* response, const rc_api_server_response_t* server_response); ++RC_EXPORT void RC_CCONV rc_api_destroy_fetch_leaderboard_info_response(rc_api_fetch_leaderboard_info_response_t* response); ++ ++/* --- Fetch Games List --- */ ++ ++/** ++ * API parameters for a fetch games list request. ++ */ ++typedef struct rc_api_fetch_games_list_request_t { ++ /* The unique identifier of the console to query */ ++ uint32_t console_id; ++} ++rc_api_fetch_games_list_request_t; ++ ++/* A game list entry */ ++typedef struct rc_api_game_list_entry_t { ++ /* The unique identifier of the game */ ++ uint32_t id; ++ /* The name of the game */ ++ const char* name; ++} ++rc_api_game_list_entry_t; ++ ++/** ++ * Response data for a fetch games list request. ++ */ ++typedef struct rc_api_fetch_games_list_response_t { ++ /* An array of requested entries */ ++ rc_api_game_list_entry_t* entries; ++ /* The number of items in the entries array */ ++ uint32_t num_entries; ++ ++ /* Common server-provided response information */ ++ rc_api_response_t response; ++} ++rc_api_fetch_games_list_response_t; ++ ++RC_EXPORT int RC_CCONV rc_api_init_fetch_games_list_request(rc_api_request_t* request, const rc_api_fetch_games_list_request_t* api_params); ++RC_EXPORT int RC_CCONV rc_api_init_fetch_games_list_request_hosted(rc_api_request_t* request, const rc_api_fetch_games_list_request_t* api_params, const rc_api_host_t* host); ++/* [deprecated] use rc_api_process_fetch_games_list_server_response instead */ ++RC_EXPORT int RC_CCONV rc_api_process_fetch_games_list_response(rc_api_fetch_games_list_response_t* response, const char* server_response); ++RC_EXPORT int RC_CCONV rc_api_process_fetch_games_list_server_response(rc_api_fetch_games_list_response_t* response, const rc_api_server_response_t* server_response); ++RC_EXPORT void RC_CCONV rc_api_destroy_fetch_games_list_response(rc_api_fetch_games_list_response_t* response); ++ ++/* --- Fetch Game Titles --- */ ++ ++/** ++ * API parameters for a fetch games list request. ++ */ ++typedef struct rc_api_fetch_game_titles_request_t { ++ /* An array of game ids to fetch titles for */ ++ const uint32_t* game_ids; ++ /* The number of items in the game_ids array */ ++ uint32_t num_game_ids; ++} ++rc_api_fetch_game_titles_request_t; ++ ++/* A game title entry */ ++typedef struct rc_api_game_title_entry_t { ++ /* The unique identifier of the game */ ++ uint32_t id; ++ /* The title of the game */ ++ const char* title; ++ /* The image name for the game badge */ ++ const char* image_name; ++} ++rc_api_game_title_entry_t; ++ ++/** ++ * Response data for a fetch games title request. ++ */ ++typedef struct rc_api_fetch_game_titles_response_t { ++ /* An array of requested entries */ ++ rc_api_game_title_entry_t* entries; ++ /* The number of items in the entries array */ ++ uint32_t num_entries; ++ ++ /* Common server-provided response information */ ++ rc_api_response_t response; ++} ++rc_api_fetch_game_titles_response_t; ++ ++RC_EXPORT int RC_CCONV rc_api_init_fetch_game_titles_request(rc_api_request_t* request, const rc_api_fetch_game_titles_request_t* api_params); ++RC_EXPORT int RC_CCONV rc_api_init_fetch_game_titles_request_hosted(rc_api_request_t* request, const rc_api_fetch_game_titles_request_t* api_params, const rc_api_host_t* host); ++RC_EXPORT int RC_CCONV rc_api_process_fetch_game_titles_server_response(rc_api_fetch_game_titles_response_t* response, const rc_api_server_response_t* server_response); ++RC_EXPORT void RC_CCONV rc_api_destroy_fetch_game_titles_response(rc_api_fetch_game_titles_response_t* response); ++ ++/* --- Fetch Game Hashes --- */ ++ ++/** ++ * API parameters for a fetch games list request. ++ */ ++typedef struct rc_api_fetch_hash_library_request_t { ++ /** ++ * The unique identifier of the console to query. ++ * Passing RC_CONSOLE_UNKNOWN will return hashes for all consoles. ++ */ ++ uint32_t console_id; ++} rc_api_fetch_hash_library_request_t; ++ ++/* A hash library entry */ ++typedef struct rc_api_hash_library_entry_t { ++ /* The hash for the game */ ++ const char* hash; ++ /* The unique identifier of the game */ ++ uint32_t game_id; ++} rc_api_hash_library_entry_t; ++ ++/** ++ * Response data for a fetch hash library request. ++ */ ++typedef struct rc_api_fetch_hash_library_response_t { ++ /* An array of entries, one per game */ ++ rc_api_hash_library_entry_t* entries; ++ /* The number of items in the entries array */ ++ uint32_t num_entries; ++ ++ /* Common server-provided response information */ ++ rc_api_response_t response; ++} ++rc_api_fetch_hash_library_response_t; ++ ++RC_EXPORT int RC_CCONV rc_api_init_fetch_hash_library_request(rc_api_request_t* request, const rc_api_fetch_hash_library_request_t* api_params); ++RC_EXPORT int RC_CCONV rc_api_init_fetch_hash_library_request_hosted(rc_api_request_t* request, const rc_api_fetch_hash_library_request_t* api_params, const rc_api_host_t* host); ++RC_EXPORT int RC_CCONV rc_api_process_fetch_hash_library_server_response(rc_api_fetch_hash_library_response_t* response, const rc_api_server_response_t* server_response); ++RC_EXPORT void RC_CCONV rc_api_destroy_fetch_hash_library_response(rc_api_fetch_hash_library_response_t* response); ++ ++RC_END_C_DECLS ++ ++#endif /* RC_API_INFO_H */ +diff -rupbN melonDS.orig/src/rcheevos/include/rc_api_request.h melonDS.ra/src/rcheevos/include/rc_api_request.h +--- melonDS.orig/src/rcheevos/include/rc_api_request.h 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/include/rc_api_request.h 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,77 @@ ++#ifndef RC_API_REQUEST_H ++#define RC_API_REQUEST_H ++ ++#include "rc_error.h" ++#include "rc_util.h" ++ ++#include ++ ++RC_BEGIN_C_DECLS ++ ++/** ++ * Information about the server being connected to. ++ */ ++typedef struct rc_api_host_t { ++ /* The host name for the API calls (retroachievements.org) */ ++ const char* host; ++ /* The host name for media URLs (media.retroachievements.org) */ ++ const char* media_host; ++} ++rc_api_host_t; ++ ++/** ++ * A constructed request to send to the retroachievements server. ++ */ ++typedef struct rc_api_request_t { ++ /* The URL to send the request to (contains protocol, host, path, and query args) */ ++ const char* url; ++ /* Additional query args that should be sent via a POST command. If null, GET may be used */ ++ const char* post_data; ++ /* The HTTP Content-Type of the POST data. */ ++ const char* content_type; ++ ++ /* Storage for the url and post_data */ ++ rc_buffer_t buffer; ++} ++rc_api_request_t; ++ ++/** ++ * Common attributes for all server responses. ++ */ ++typedef struct rc_api_response_t { ++ /* Server-provided success indicator (non-zero on success, zero on failure) */ ++ int succeeded; ++ /* Server-provided message associated to the failure */ ++ const char* error_message; ++ /* Server-provided error code associated to the failure */ ++ const char* error_code; ++ ++ /* Storage for the response data */ ++ rc_buffer_t buffer; ++} ++rc_api_response_t; ++ ++RC_EXPORT void RC_CCONV rc_api_destroy_request(rc_api_request_t* request); ++ ++/* [deprecated] use rc_api_init_*_hosted instead */ ++RC_EXPORT void RC_CCONV rc_api_set_host(const char* hostname); ++/* [deprecated] use rc_api_init_*_hosted instead */ ++RC_EXPORT void RC_CCONV rc_api_set_image_host(const char* hostname); ++ ++typedef struct rc_api_server_response_t { ++ /* Pointer to the data returned from the server */ ++ const char* body; ++ /* Length of data returned from the server (Content-Length) */ ++ size_t body_length; ++ /* HTTP status code returned from the server */ ++ int http_status_code; ++} rc_api_server_response_t; ++ ++enum { ++ RC_API_SERVER_RESPONSE_CLIENT_ERROR = -1, ++ RC_API_SERVER_RESPONSE_RETRYABLE_CLIENT_ERROR = -2 ++}; ++ ++RC_END_C_DECLS ++ ++#endif /* RC_API_REQUEST_H */ +diff -rupbN melonDS.orig/src/rcheevos/include/rc_api_runtime.h melonDS.ra/src/rcheevos/include/rc_api_runtime.h +--- melonDS.orig/src/rcheevos/include/rc_api_runtime.h 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/include/rc_api_runtime.h 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,417 @@ ++#ifndef RC_API_RUNTIME_H ++#define RC_API_RUNTIME_H ++ ++#include "rc_api_request.h" ++ ++#include ++#include ++ ++RC_BEGIN_C_DECLS ++ ++/* --- Fetch Image --- */ ++ ++/** ++ * API parameters for a fetch image request. ++ * NOTE: fetch image server response is the raw image data. There is no rc_api_process_fetch_image_response function. ++ */ ++typedef struct rc_api_fetch_image_request_t { ++ /* The name of the image to fetch */ ++ const char* image_name; ++ /* The type of image to fetch */ ++ uint32_t image_type; ++} ++rc_api_fetch_image_request_t; ++ ++#define RC_IMAGE_TYPE_GAME 1 ++#define RC_IMAGE_TYPE_ACHIEVEMENT 2 ++#define RC_IMAGE_TYPE_ACHIEVEMENT_LOCKED 3 ++#define RC_IMAGE_TYPE_USER 4 ++ ++RC_EXPORT int RC_CCONV rc_api_init_fetch_image_request(rc_api_request_t* request, const rc_api_fetch_image_request_t* api_params); ++RC_EXPORT int RC_CCONV rc_api_init_fetch_image_request_hosted(rc_api_request_t* request, const rc_api_fetch_image_request_t* api_params, const rc_api_host_t* host); ++ ++/* --- Resolve Hash --- */ ++ ++/** ++ * API parameters for a resolve hash request. ++ */ ++typedef struct rc_api_resolve_hash_request_t { ++ /* Unused - hash lookup does not require credentials */ ++ const char* username; ++ /* Unused - hash lookup does not require credentials */ ++ const char* api_token; ++ /* The generated hash of the game to be identified */ ++ const char* game_hash; ++} ++rc_api_resolve_hash_request_t; ++ ++/** ++ * Response data for a resolve hash request. ++ */ ++typedef struct rc_api_resolve_hash_response_t { ++ /* The unique identifier of the game, 0 if no match was found */ ++ uint32_t game_id; ++ ++ /* Common server-provided response information */ ++ rc_api_response_t response; ++} ++rc_api_resolve_hash_response_t; ++ ++RC_EXPORT int RC_CCONV rc_api_init_resolve_hash_request(rc_api_request_t* request, const rc_api_resolve_hash_request_t* api_params); ++RC_EXPORT int RC_CCONV rc_api_init_resolve_hash_request_hosted(rc_api_request_t* request, const rc_api_resolve_hash_request_t* api_params, const rc_api_host_t* host); ++/* [deprecated] use rc_api_process_resolve_hash_server_response instead */ ++RC_EXPORT int RC_CCONV rc_api_process_resolve_hash_response(rc_api_resolve_hash_response_t* response, const char* server_response); ++RC_EXPORT int RC_CCONV rc_api_process_resolve_hash_server_response(rc_api_resolve_hash_response_t* response, const rc_api_server_response_t* server_response); ++RC_EXPORT void RC_CCONV rc_api_destroy_resolve_hash_response(rc_api_resolve_hash_response_t* response); ++ ++/* --- Fetch Game Data --- */ ++ ++/** ++ * API parameters for a fetch game data request. ++ */ ++typedef struct rc_api_fetch_game_data_request_t { ++ /* The username of the player */ ++ const char* username; ++ /* The API token from the login request */ ++ const char* api_token; ++ /* The unique identifier of the game */ ++ uint32_t game_id; ++ /* The generated hash of the game to be identified (ignored if game_id is not 0) */ ++ const char* game_hash; ++} ++rc_api_fetch_game_data_request_t; ++ ++/* A leaderboard definition */ ++typedef struct rc_api_leaderboard_definition_t { ++ /* The unique identifier of the leaderboard */ ++ uint32_t id; ++ /* The format to pass to rc_format_value to format the leaderboard value */ ++ int format; ++ /* The title of the leaderboard */ ++ const char* title; ++ /* The description of the leaderboard */ ++ const char* description; ++ /* The definition of the leaderboard to be passed to rc_runtime_activate_lboard */ ++ const char* definition; ++ /* Non-zero if lower values are better for this leaderboard */ ++ uint8_t lower_is_better; ++ /* Non-zero if the leaderboard should not be displayed in a list of leaderboards */ ++ uint8_t hidden; ++} ++rc_api_leaderboard_definition_t; ++ ++/* An achievement definition */ ++typedef struct rc_api_achievement_definition_t { ++ /* The unique identifier of the achievement */ ++ uint32_t id; ++ /* The number of points the achievement is worth */ ++ uint32_t points; ++ /* The achievement category (core, unofficial) */ ++ uint32_t category; ++ /* The title of the achievement */ ++ const char* title; ++ /* The description of the achievement */ ++ const char* description; ++ /* The definition of the achievement to be passed to rc_runtime_activate_achievement */ ++ const char* definition; ++ /* The author of the achievment */ ++ const char* author; ++ /* The image name for the achievement badge */ ++ const char* badge_name; ++ /* When the achievement was first uploaded to the server */ ++ time_t created; ++ /* When the achievement was last modified on the server */ ++ time_t updated; ++ /* The achievement type (win/progression/missable) */ ++ uint32_t type; ++ /* The approximate rarity of the achievement (X% of users have earned the achievement) */ ++ float rarity; ++ /* The approximate rarity of the achievement in hardcore (X% of users have earned the achievement in hardcore) */ ++ float rarity_hardcore; ++ /* The URL for the achievement badge */ ++ const char* badge_url; ++ /* The URL for the locked achievement badge */ ++ const char* badge_locked_url; ++} ++rc_api_achievement_definition_t; ++ ++#define RC_ACHIEVEMENT_CATEGORY_CORE 3 ++#define RC_ACHIEVEMENT_CATEGORY_UNOFFICIAL 5 ++ ++#define RC_ACHIEVEMENT_TYPE_STANDARD 0 ++#define RC_ACHIEVEMENT_TYPE_MISSABLE 1 ++#define RC_ACHIEVEMENT_TYPE_PROGRESSION 2 ++#define RC_ACHIEVEMENT_TYPE_WIN 3 ++ ++/** ++ * Response data for a fetch game data request. ++ */ ++typedef struct rc_api_fetch_game_data_response_t { ++ /* The unique identifier of the game */ ++ uint32_t id; ++ /* The console associated to the game */ ++ uint32_t console_id; ++ /* The title of the game */ ++ const char* title; ++ /* The image name for the game badge */ ++ const char* image_name; ++ /* The URL for the game badge */ ++ const char* image_url; ++ /* The rich presence script for the game to be passed to rc_runtime_activate_richpresence */ ++ const char* rich_presence_script; ++ ++ /* An array of achievements for the game */ ++ rc_api_achievement_definition_t* achievements; ++ /* The number of items in the achievements array */ ++ uint32_t num_achievements; ++ ++ /* An array of leaderboards for the game */ ++ rc_api_leaderboard_definition_t* leaderboards; ++ /* The number of items in the leaderboards array */ ++ uint32_t num_leaderboards; ++ ++ /* Common server-provided response information */ ++ rc_api_response_t response; ++} ++rc_api_fetch_game_data_response_t; ++ ++RC_EXPORT int RC_CCONV rc_api_init_fetch_game_data_request(rc_api_request_t* request, const rc_api_fetch_game_data_request_t* api_params); ++RC_EXPORT int RC_CCONV rc_api_init_fetch_game_data_request_hosted(rc_api_request_t* request, const rc_api_fetch_game_data_request_t* api_params, const rc_api_host_t* host); ++/* [deprecated] use rc_api_process_fetch_game_data_server_response instead */ ++RC_EXPORT int RC_CCONV rc_api_process_fetch_game_data_response(rc_api_fetch_game_data_response_t* response, const char* server_response); ++RC_EXPORT int RC_CCONV rc_api_process_fetch_game_data_server_response(rc_api_fetch_game_data_response_t* response, const rc_api_server_response_t* server_response); ++RC_EXPORT void RC_CCONV rc_api_destroy_fetch_game_data_response(rc_api_fetch_game_data_response_t* response); ++ ++/* --- Fetch Game Sets --- */ ++ ++/** ++ * API parameters for a fetch game data request. ++ */ ++typedef struct rc_api_fetch_game_sets_request_t { ++ /* The username of the player */ ++ const char* username; ++ /* The API token from the login request */ ++ const char* api_token; ++ /* The unique identifier of the game */ ++ uint32_t game_id; ++ /* The generated hash of the game to be identified (ignored if game_id is not 0) */ ++ const char* game_hash; ++} ++rc_api_fetch_game_sets_request_t; ++ ++#define RC_ACHIEVEMENT_SET_TYPE_CORE 0 ++#define RC_ACHIEVEMENT_SET_TYPE_BONUS 1 ++#define RC_ACHIEVEMENT_SET_TYPE_SPECIALTY 2 ++#define RC_ACHIEVEMENT_SET_TYPE_EXCLUSIVE 3 ++ ++/* A game subset definition */ ++typedef struct rc_api_achievement_set_definition_t { ++ /* The unique identifier of the achievement set */ ++ uint32_t id; ++ /* The legacy game_id of the achievement set (used for editor API calls) */ ++ uint32_t game_id; ++ /* The title of the achievement set */ ++ const char* title; ++ /* The image name for the achievement set badge */ ++ const char* image_name; ++ /* The URL for the achievement set badge */ ++ const char* image_url; ++ ++ /* An array of achievements for the achievement set */ ++ rc_api_achievement_definition_t* achievements; ++ /* The number of items in the achievements array */ ++ uint32_t num_achievements; ++ ++ /* An array of leaderboards for the achievement set */ ++ rc_api_leaderboard_definition_t* leaderboards; ++ /* The number of items in the leaderboards array */ ++ uint32_t num_leaderboards; ++ ++ /* The type of the achievement set */ ++ uint8_t type; ++} ++rc_api_achievement_set_definition_t; ++ ++/** ++ * Response data for a fetch game sets request. ++ */ ++typedef struct rc_api_fetch_game_sets_response_t { ++ /* The unique identifier of the game */ ++ uint32_t id; ++ /* The console associated to the game */ ++ uint32_t console_id; ++ /* The title of the game */ ++ const char* title; ++ /* The image name for the game badge */ ++ const char* image_name; ++ /* The URL for the game badge */ ++ const char* image_url; ++ /* The rich presence script for the game to be passed to rc_runtime_activate_richpresence */ ++ const char* rich_presence_script; ++ /* The unique identifier of the game to use for session requests (startsession/ping/etc) */ ++ uint32_t session_game_id; ++ ++ /* An array of sets for the game */ ++ rc_api_achievement_set_definition_t* sets; ++ /* The number of items in the sets array */ ++ uint32_t num_sets; ++ ++ /* Common server-provided response information */ ++ rc_api_response_t response; ++} ++rc_api_fetch_game_sets_response_t; ++ ++RC_EXPORT int RC_CCONV rc_api_init_fetch_game_sets_request(rc_api_request_t* request, const rc_api_fetch_game_sets_request_t* api_params); ++RC_EXPORT int RC_CCONV rc_api_init_fetch_game_sets_request_hosted(rc_api_request_t* request, const rc_api_fetch_game_sets_request_t* api_params, const rc_api_host_t* host); ++RC_EXPORT int RC_CCONV rc_api_process_fetch_game_sets_server_response(rc_api_fetch_game_sets_response_t* response, const rc_api_server_response_t* server_response); ++RC_EXPORT void RC_CCONV rc_api_destroy_fetch_game_sets_response(rc_api_fetch_game_sets_response_t* response); ++ ++/* --- Ping --- */ ++ ++/** ++ * API parameters for a ping request. ++ */ ++typedef struct rc_api_ping_request_t { ++ /* The username of the player */ ++ const char* username; ++ /* The API token from the login request */ ++ const char* api_token; ++ /* The unique identifier of the game */ ++ uint32_t game_id; ++ /* (optional) The current rich presence evaluation for the user */ ++ const char* rich_presence; ++ /* (recommended) The hash associated to the game being played */ ++ const char* game_hash; ++ /* Non-zero if hardcore is currently enabled (ignored if game_hash is null) */ ++ uint32_t hardcore; ++} ++rc_api_ping_request_t; ++ ++/** ++ * Response data for a ping request. ++ */ ++typedef struct rc_api_ping_response_t { ++ /* Common server-provided response information */ ++ rc_api_response_t response; ++} ++rc_api_ping_response_t; ++ ++RC_EXPORT int RC_CCONV rc_api_init_ping_request(rc_api_request_t* request, const rc_api_ping_request_t* api_params); ++RC_EXPORT int RC_CCONV rc_api_init_ping_request_hosted(rc_api_request_t* request, const rc_api_ping_request_t* api_params, const rc_api_host_t* host); ++/* [deprecated] use rc_api_process_ping_server_response instead */ ++RC_EXPORT int RC_CCONV rc_api_process_ping_response(rc_api_ping_response_t* response, const char* server_response); ++RC_EXPORT int RC_CCONV rc_api_process_ping_server_response(rc_api_ping_response_t* response, const rc_api_server_response_t* server_response); ++RC_EXPORT void RC_CCONV rc_api_destroy_ping_response(rc_api_ping_response_t* response); ++ ++/* --- Award Achievement --- */ ++ ++/** ++ * API parameters for an award achievement request. ++ */ ++typedef struct rc_api_award_achievement_request_t { ++ /* The username of the player */ ++ const char* username; ++ /* The API token from the login request */ ++ const char* api_token; ++ /* The unique identifier of the achievement */ ++ uint32_t achievement_id; ++ /* Non-zero if the achievement was earned in hardcore */ ++ uint32_t hardcore; ++ /* The hash associated to the game being played */ ++ const char* game_hash; ++ /* The number of seconds since the achievement was unlocked */ ++ uint32_t seconds_since_unlock; ++} ++rc_api_award_achievement_request_t; ++ ++/** ++ * Response data for an award achievement request. ++ */ ++typedef struct rc_api_award_achievement_response_t { ++ /* The unique identifier of the achievement that was awarded */ ++ uint32_t awarded_achievement_id; ++ /* The updated player score */ ++ uint32_t new_player_score; ++ /* The updated player softcore score */ ++ uint32_t new_player_score_softcore; ++ /* The number of achievements the user has not yet unlocked for this game ++ * (in hardcore/non-hardcore per hardcore flag in request) */ ++ uint32_t achievements_remaining; ++ ++ /* Common server-provided response information */ ++ rc_api_response_t response; ++} ++rc_api_award_achievement_response_t; ++ ++RC_EXPORT int RC_CCONV rc_api_init_award_achievement_request(rc_api_request_t* request, const rc_api_award_achievement_request_t* api_params); ++RC_EXPORT int RC_CCONV rc_api_init_award_achievement_request_hosted(rc_api_request_t* request, const rc_api_award_achievement_request_t* api_params, const rc_api_host_t* host); ++/* [deprecated] use rc_api_process_award_achievement_server_response instead */ ++RC_EXPORT int RC_CCONV rc_api_process_award_achievement_response(rc_api_award_achievement_response_t* response, const char* server_response); ++RC_EXPORT int RC_CCONV rc_api_process_award_achievement_server_response(rc_api_award_achievement_response_t* response, const rc_api_server_response_t* server_response); ++RC_EXPORT void RC_CCONV rc_api_destroy_award_achievement_response(rc_api_award_achievement_response_t* response); ++ ++/* --- Submit Leaderboard Entry --- */ ++ ++/** ++ * API parameters for a submit lboard entry request. ++ */ ++typedef struct rc_api_submit_lboard_entry_request_t { ++ /* The username of the player */ ++ const char* username; ++ /* The API token from the login request */ ++ const char* api_token; ++ /* The unique identifier of the leaderboard */ ++ uint32_t leaderboard_id; ++ /* The value being submitted */ ++ int32_t score; ++ /* The hash associated to the game being played */ ++ const char* game_hash; ++ /* The number of seconds since the leaderboard attempt was completed */ ++ uint32_t seconds_since_completion; ++} ++rc_api_submit_lboard_entry_request_t; ++ ++/* A leaderboard entry */ ++typedef struct rc_api_lboard_entry_t { ++ /* The user associated to the entry */ ++ const char* username; ++ /* The rank of the entry */ ++ uint32_t rank; ++ /* The value of the entry */ ++ int32_t score; ++} ++rc_api_lboard_entry_t; ++ ++/** ++ * Response data for a submit lboard entry request. ++ */ ++typedef struct rc_api_submit_lboard_entry_response_t { ++ /* The value that was submitted */ ++ int32_t submitted_score; ++ /* The player's best submitted value */ ++ int32_t best_score; ++ /* The player's new rank within the leaderboard */ ++ uint32_t new_rank; ++ /* The total number of entries in the leaderboard */ ++ uint32_t num_entries; ++ ++ /* An array of the top entries for the leaderboard */ ++ rc_api_lboard_entry_t* top_entries; ++ /* The number of items in the top_entries array */ ++ uint32_t num_top_entries; ++ ++ /* Common server-provided response information */ ++ rc_api_response_t response; ++} ++rc_api_submit_lboard_entry_response_t; ++ ++RC_EXPORT int RC_CCONV rc_api_init_submit_lboard_entry_request(rc_api_request_t* request, const rc_api_submit_lboard_entry_request_t* api_params); ++RC_EXPORT int RC_CCONV rc_api_init_submit_lboard_entry_request_hosted(rc_api_request_t* request, const rc_api_submit_lboard_entry_request_t* api_params, const rc_api_host_t* host); ++/* [deprecated] use rc_api_process_submit_lboard_entry_server_response instead */ ++RC_EXPORT int RC_CCONV rc_api_process_submit_lboard_entry_response(rc_api_submit_lboard_entry_response_t* response, const char* server_response); ++RC_EXPORT int RC_CCONV rc_api_process_submit_lboard_entry_server_response(rc_api_submit_lboard_entry_response_t* response, const rc_api_server_response_t* server_response); ++RC_EXPORT void RC_CCONV rc_api_destroy_submit_lboard_entry_response(rc_api_submit_lboard_entry_response_t* response); ++ ++RC_END_C_DECLS ++ ++#endif /* RC_API_RUNTIME_H */ +diff -rupbN melonDS.orig/src/rcheevos/include/rc_api_user.h melonDS.ra/src/rcheevos/include/rc_api_user.h +--- melonDS.orig/src/rcheevos/include/rc_api_user.h 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/include/rc_api_user.h 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,262 @@ ++#ifndef RC_API_USER_H ++#define RC_API_USER_H ++ ++#include "rc_api_request.h" ++ ++#include ++#include ++ ++RC_BEGIN_C_DECLS ++ ++/* --- Login --- */ ++ ++/** ++ * API parameters for a login request. ++ * If both password and api_token are provided, api_token will be ignored. ++ */ ++typedef struct rc_api_login_request_t { ++ /* The username of the player being logged in */ ++ const char* username; ++ /* The API token from a previous login */ ++ const char* api_token; ++ /* The player's password */ ++ const char* password; ++} ++rc_api_login_request_t; ++ ++/** ++ * Response data for a login request. ++ */ ++typedef struct rc_api_login_response_t { ++ /* The case-corrected username of the player */ ++ const char* username; ++ /* The API token to use for all future requests */ ++ const char* api_token; ++ /* The current score of the player */ ++ uint32_t score; ++ /* The current softcore score of the player */ ++ uint32_t score_softcore; ++ /* The number of unread messages waiting for the player on the web site */ ++ uint32_t num_unread_messages; ++ /* The preferred name to display for the player */ ++ const char* display_name; ++ /* A URL to the user's avatar image */ ++ const char* avatar_url; ++ ++ /* Common server-provided response information */ ++ rc_api_response_t response; ++} ++rc_api_login_response_t; ++ ++RC_EXPORT int RC_CCONV rc_api_init_login_request(rc_api_request_t* request, const rc_api_login_request_t* api_params); ++RC_EXPORT int RC_CCONV rc_api_init_login_request_hosted(rc_api_request_t* request, const rc_api_login_request_t* api_params, const rc_api_host_t* host); ++/* [deprecated] use rc_api_process_login_server_response instead */ ++RC_EXPORT int RC_CCONV rc_api_process_login_response(rc_api_login_response_t* response, const char* server_response); ++RC_EXPORT int RC_CCONV rc_api_process_login_server_response(rc_api_login_response_t* response, const rc_api_server_response_t* server_response); ++RC_EXPORT void RC_CCONV rc_api_destroy_login_response(rc_api_login_response_t* response); ++ ++/* --- Start Session --- */ ++ ++/** ++ * API parameters for a start session request. ++ */ ++typedef struct rc_api_start_session_request_t { ++ /* The username of the player */ ++ const char* username; ++ /* The API token from the login request */ ++ const char* api_token; ++ /* The unique identifier of the game */ ++ uint32_t game_id; ++ /* (recommended) The hash associated to the game being played */ ++ const char* game_hash; ++ /* Non-zero if hardcore is currently enabled (ignored if game_hash is null) */ ++ uint32_t hardcore; ++} ++rc_api_start_session_request_t; ++ ++/** ++ * Response data for an achievement unlock. ++ */ ++typedef struct rc_api_unlock_entry_t { ++ /* The unique identifier of the unlocked achievement */ ++ uint32_t achievement_id; ++ /* When the achievement was unlocked */ ++ time_t when; ++} ++rc_api_unlock_entry_t; ++ ++/** ++ * Response data for a start session request. ++ */ ++typedef struct rc_api_start_session_response_t { ++ /* An array of hardcore user unlocks */ ++ rc_api_unlock_entry_t* hardcore_unlocks; ++ /* An array of user unlocks */ ++ rc_api_unlock_entry_t* unlocks; ++ ++ /* The number of items in the hardcore_unlocks array */ ++ uint32_t num_hardcore_unlocks; ++ /* The number of items in the unlocks array */ ++ uint32_t num_unlocks; ++ ++ /* The server timestamp when the response was generated */ ++ time_t server_now; ++ ++ /* Common server-provided response information */ ++ rc_api_response_t response; ++} ++rc_api_start_session_response_t; ++ ++RC_EXPORT int RC_CCONV rc_api_init_start_session_request(rc_api_request_t* request, const rc_api_start_session_request_t* api_params); ++RC_EXPORT int RC_CCONV rc_api_init_start_session_request_hosted(rc_api_request_t* request, const rc_api_start_session_request_t* api_params, const rc_api_host_t* host); ++/* [deprecated] use rc_api_process_start_session_server_response instead */ ++RC_EXPORT int RC_CCONV rc_api_process_start_session_response(rc_api_start_session_response_t* response, const char* server_response); ++RC_EXPORT int RC_CCONV rc_api_process_start_session_server_response(rc_api_start_session_response_t* response, const rc_api_server_response_t* server_response); ++RC_EXPORT void RC_CCONV rc_api_destroy_start_session_response(rc_api_start_session_response_t* response); ++ ++/* --- Fetch User Unlocks --- */ ++ ++/** ++ * API parameters for a fetch user unlocks request. ++ */ ++typedef struct rc_api_fetch_user_unlocks_request_t { ++ /* The username of the player */ ++ const char* username; ++ /* The API token from the login request */ ++ const char* api_token; ++ /* The unique identifier of the game */ ++ uint32_t game_id; ++ /* Non-zero to fetch hardcore unlocks, 0 to fetch non-hardcore unlocks */ ++ uint32_t hardcore; ++} ++rc_api_fetch_user_unlocks_request_t; ++ ++/** ++ * Response data for a fetch user unlocks request. ++ */ ++typedef struct rc_api_fetch_user_unlocks_response_t { ++ /* An array of achievement IDs previously unlocked by the user */ ++ uint32_t* achievement_ids; ++ /* The number of items in the achievement_ids array */ ++ uint32_t num_achievement_ids; ++ ++ /* Common server-provided response information */ ++ rc_api_response_t response; ++} ++rc_api_fetch_user_unlocks_response_t; ++ ++RC_EXPORT int RC_CCONV rc_api_init_fetch_user_unlocks_request(rc_api_request_t* request, const rc_api_fetch_user_unlocks_request_t* api_params); ++RC_EXPORT int RC_CCONV rc_api_init_fetch_user_unlocks_request_hosted(rc_api_request_t* request, const rc_api_fetch_user_unlocks_request_t* api_params, const rc_api_host_t* host); ++/* [deprecated] use rc_api_process_fetch_user_unlocks_server_response instead */ ++RC_EXPORT int RC_CCONV rc_api_process_fetch_user_unlocks_response(rc_api_fetch_user_unlocks_response_t* response, const char* server_response); ++RC_EXPORT int RC_CCONV rc_api_process_fetch_user_unlocks_server_response(rc_api_fetch_user_unlocks_response_t* response, const rc_api_server_response_t* server_response); ++RC_EXPORT void RC_CCONV rc_api_destroy_fetch_user_unlocks_response(rc_api_fetch_user_unlocks_response_t* response); ++ ++/* --- Fetch Followed Users --- */ ++ ++/** ++ * API parameters for a fetch followed users request. ++ */ ++typedef struct rc_api_fetch_followed_users_request_t { ++ /* The username of the player */ ++ const char* username; ++ /* The API token from the login request */ ++ const char* api_token; ++} ++rc_api_fetch_followed_users_request_t; ++ ++typedef struct rc_api_followed_user_activity_t { ++ /* The record associated to the activity */ ++ const char* context; ++ /* The image of the record associated to the activity */ ++ const char* context_image_url; ++ /* The description of the activity */ ++ const char* description; ++ /* The time of the activity */ ++ time_t when; ++ /* The unique identifier of the record associated to the activity */ ++ uint32_t context_id; ++} ++rc_api_followed_user_activity_t; ++ ++/** ++ * Response data for a followed user. ++ */ ++typedef struct rc_api_followed_user_t { ++ /* The preferred name to display for the player */ ++ const char* display_name; ++ /* A URL to the user's avatar image */ ++ const char* avatar_url; ++ /* The player's last registered activity */ ++ rc_api_followed_user_activity_t recent_activity; ++ /* The current score of the player */ ++ uint32_t score; ++} ++rc_api_followed_user_t; ++ ++/** ++ * Response data for a fetch followed users request. ++ */ ++typedef struct rc_api_fetch_followed_users_response_t { ++ /* An array of followed user information */ ++ rc_api_followed_user_t* users; ++ /* The number of items in the users array */ ++ uint32_t num_users; ++ ++ /* Common server-provided response information */ ++ rc_api_response_t response; ++} ++rc_api_fetch_followed_users_response_t; ++ ++RC_EXPORT int RC_CCONV rc_api_init_fetch_followed_users_request(rc_api_request_t* request, const rc_api_fetch_followed_users_request_t* api_params); ++RC_EXPORT int RC_CCONV rc_api_init_fetch_followed_users_request_hosted(rc_api_request_t* request, const rc_api_fetch_followed_users_request_t* api_params, const rc_api_host_t* host); ++RC_EXPORT int RC_CCONV rc_api_process_fetch_followed_users_server_response(rc_api_fetch_followed_users_response_t* response, const rc_api_server_response_t* server_response); ++RC_EXPORT void RC_CCONV rc_api_destroy_fetch_followed_users_response(rc_api_fetch_followed_users_response_t* response); ++ ++/* --- Fetch All Progress --- */ ++ ++/** ++ * API parameters for a fetch all user progress request. ++ */ ++typedef struct rc_api_fetch_all_user_progress_request_t { ++ /* The username of the player */ ++ const char* username; ++ /* The API token from the login request */ ++ const char* api_token; ++ /* The unique identifier of the console to query */ ++ uint32_t console_id; ++} rc_api_fetch_all_user_progress_request_t; ++ ++/* An all-user-progress entry */ ++typedef struct rc_api_all_user_progress_entry_t { ++ /* The unique identifier of the game */ ++ uint32_t game_id; ++ /* The total number of achievements for this game */ ++ uint32_t num_achievements; ++ /* The total number of unlocked achievements for this game in softcore mode */ ++ uint32_t num_unlocked_achievements; ++ /* The total number of unlocked achievements for this game in hardcore mode */ ++ uint32_t num_unlocked_achievements_hardcore; ++} rc_api_all_user_progress_entry_t; ++ ++/** ++ * Response data for a fetch all user progress request. ++ */ ++typedef struct rc_api_fetch_all_user_progress_response_t { ++ /* An array of entries, one per game */ ++ rc_api_all_user_progress_entry_t* entries; ++ /* The number of items in the entries array */ ++ uint32_t num_entries; ++ ++ /* Common server-provided response information */ ++ rc_api_response_t response; ++} rc_api_fetch_all_user_progress_response_t; ++ ++RC_EXPORT int RC_CCONV rc_api_init_fetch_all_user_progress_request(rc_api_request_t* request, const rc_api_fetch_all_user_progress_request_t* api_params); ++RC_EXPORT int RC_CCONV rc_api_init_fetch_all_user_progress_request_hosted(rc_api_request_t* request, const rc_api_fetch_all_user_progress_request_t* api_params, const rc_api_host_t* host); ++RC_EXPORT int RC_CCONV rc_api_process_fetch_all_user_progress_server_response(rc_api_fetch_all_user_progress_response_t* response, const rc_api_server_response_t* server_response); ++RC_EXPORT void RC_CCONV rc_api_destroy_fetch_all_user_progress_response(rc_api_fetch_all_user_progress_response_t* response); ++ ++RC_END_C_DECLS ++ ++#endif /* RC_API_H */ +diff -rupbN melonDS.orig/src/rcheevos/include/rc_client.h melonDS.ra/src/rcheevos/include/rc_client.h +--- melonDS.orig/src/rcheevos/include/rc_client.h 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/include/rc_client.h 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,871 @@ ++#ifndef RC_CLIENT_H ++#define RC_CLIENT_H ++ ++#include "rc_api_request.h" ++#include "rc_error.h" ++ ++#include ++#include ++#include ++ ++RC_BEGIN_C_DECLS ++ ++/* implementation abstracted in rc_client_internal.h */ ++typedef struct rc_client_t rc_client_t; ++typedef struct rc_client_async_handle_t rc_client_async_handle_t; ++ ++/*****************************************************************************\ ++| Callbacks | ++\*****************************************************************************/ ++ ++/** ++ * Callback used to read num_bytes bytes from memory starting at address into buffer. ++ * Returns the number of bytes read. A return value of 0 indicates the address was invalid. ++ */ ++typedef uint32_t (RC_CCONV *rc_client_read_memory_func_t)(uint32_t address, uint8_t* buffer, uint32_t num_bytes, rc_client_t* client); ++ ++/** ++ * Internal method passed to rc_client_server_call_t to process the server response. ++ */ ++typedef void (RC_CCONV *rc_client_server_callback_t)(const rc_api_server_response_t* server_response, void* callback_data); ++ ++/** ++ * Callback used to issue a request to the server. ++ */ ++typedef void (RC_CCONV *rc_client_server_call_t)(const rc_api_request_t* request, rc_client_server_callback_t callback, void* callback_data, rc_client_t* client); ++ ++/** ++ * Generic callback for asynchronous eventing. ++ */ ++typedef void (RC_CCONV *rc_client_callback_t)(int result, const char* error_message, rc_client_t* client, void* userdata); ++ ++/** ++ * Callback for logging or displaying a message. ++ */ ++typedef void (RC_CCONV *rc_client_message_callback_t)(const char* message, const rc_client_t* client); ++ ++/*****************************************************************************\ ++| Runtime | ++\*****************************************************************************/ ++ ++/** ++ * Creates a new rc_client_t object. ++ */ ++RC_EXPORT rc_client_t* RC_CCONV rc_client_create(rc_client_read_memory_func_t read_memory_function, rc_client_server_call_t server_call_function); ++ ++/** ++ * Releases resources associated to a rc_client_t object. ++ * Pointer will no longer be valid after making this call. ++ */ ++RC_EXPORT void RC_CCONV rc_client_destroy(rc_client_t* client); ++ ++/** ++ * Sets whether hardcore is enabled (on by default). ++ * Can be called with a game loaded. ++ * Enabling hardcore with a game loaded will raise an RC_CLIENT_EVENT_RESET ++ * event. Processing will be disabled until rc_client_reset is called. ++ */ ++RC_EXPORT void RC_CCONV rc_client_set_hardcore_enabled(rc_client_t* client, int enabled); ++ ++/** ++ * Gets whether hardcore is enabled (on by default). ++ */ ++RC_EXPORT int RC_CCONV rc_client_get_hardcore_enabled(const rc_client_t* client); ++ ++/** ++ * Sets whether encore mode is enabled (off by default). ++ * Evaluated when loading a game. Has no effect while a game is loaded. ++ */ ++RC_EXPORT void RC_CCONV rc_client_set_encore_mode_enabled(rc_client_t* client, int enabled); ++ ++/** ++ * Gets whether encore mode is enabled (off by default). ++ */ ++RC_EXPORT int RC_CCONV rc_client_get_encore_mode_enabled(const rc_client_t* client); ++ ++/** ++ * Sets whether unofficial achievements should be loaded. ++ * Evaluated when loading a game. Has no effect while a game is loaded. ++ */ ++RC_EXPORT void RC_CCONV rc_client_set_unofficial_enabled(rc_client_t* client, int enabled); ++ ++/** ++ * Gets whether unofficial achievements should be loaded. ++ */ ++RC_EXPORT int RC_CCONV rc_client_get_unofficial_enabled(const rc_client_t* client); ++ ++/** ++ * Sets whether spectator mode is enabled (off by default). ++ * If enabled, events for achievement unlocks and leaderboard submissions will be ++ * raised, but server calls to actually perform the unlock/submit will not occur. ++ * Can be modified while a game is loaded. Evaluated at unlock/submit time. ++ * Cannot be modified if disabled before a game is loaded. ++ */ ++RC_EXPORT void RC_CCONV rc_client_set_spectator_mode_enabled(rc_client_t* client, int enabled); ++ ++/** ++ * Gets whether spectator mode is enabled (off by default). ++ */ ++RC_EXPORT int RC_CCONV rc_client_get_spectator_mode_enabled(const rc_client_t* client); ++ ++/** ++ * Attaches client-specific data to the runtime. ++ */ ++RC_EXPORT void RC_CCONV rc_client_set_userdata(rc_client_t* client, void* userdata); ++ ++/** ++ * Gets the client-specific data attached to the runtime. ++ */ ++RC_EXPORT void* RC_CCONV rc_client_get_userdata(const rc_client_t* client); ++ ++/** ++ * Sets the name of the server to use. ++ */ ++RC_EXPORT void RC_CCONV rc_client_set_host(rc_client_t* client, const char* hostname); ++ ++typedef uint64_t rc_clock_t; ++typedef rc_clock_t (RC_CCONV *rc_get_time_millisecs_func_t)(const rc_client_t* client); ++ ++/** ++ * Specifies a function that returns a value that increases once per millisecond. ++ */ ++RC_EXPORT void RC_CCONV rc_client_set_get_time_millisecs_function(rc_client_t* client, rc_get_time_millisecs_func_t handler); ++ ++/** ++ * Marks an async process as aborted. The associated callback will not be called. ++ */ ++RC_EXPORT void RC_CCONV rc_client_abort_async(rc_client_t* client, rc_client_async_handle_t* async_handle); ++ ++/** ++ * Gets a clause that can be added to the User-Agent to identify the version of rcheevos being used. ++ */ ++RC_EXPORT size_t RC_CCONV rc_client_get_user_agent_clause(rc_client_t* client, char buffer[], size_t buffer_size); ++ ++/*****************************************************************************\ ++| Logging | ++\*****************************************************************************/ ++ ++/** ++ * Sets the logging level and provides a callback to be called to do the logging. ++ */ ++RC_EXPORT void RC_CCONV rc_client_enable_logging(rc_client_t* client, int level, rc_client_message_callback_t callback); ++enum { ++ RC_CLIENT_LOG_LEVEL_NONE = 0, ++ RC_CLIENT_LOG_LEVEL_ERROR = 1, ++ RC_CLIENT_LOG_LEVEL_WARN = 2, ++ RC_CLIENT_LOG_LEVEL_INFO = 3, ++ RC_CLIENT_LOG_LEVEL_VERBOSE = 4, ++ NUM_RC_CLIENT_LOG_LEVELS = 5 ++}; ++ ++/*****************************************************************************\ ++| User | ++\*****************************************************************************/ ++ ++/** ++ * Attempt to login a user. ++ */ ++RC_EXPORT rc_client_async_handle_t* RC_CCONV rc_client_begin_login_with_password(rc_client_t* client, ++ const char* username, const char* password, ++ rc_client_callback_t callback, void* callback_userdata); ++ ++/** ++ * Attempt to login a user. ++ */ ++RC_EXPORT rc_client_async_handle_t* RC_CCONV rc_client_begin_login_with_token(rc_client_t* client, ++ const char* username, const char* token, ++ rc_client_callback_t callback, void* callback_userdata); ++ ++/** ++ * Logout the user. ++ */ ++RC_EXPORT void RC_CCONV rc_client_logout(rc_client_t* client); ++ ++typedef struct rc_client_user_t { ++ const char* display_name; ++ const char* username; ++ const char* token; ++ uint32_t score; ++ uint32_t score_softcore; ++ uint32_t num_unread_messages; ++ /* minimum version: 12.0 */ ++ const char* avatar_url; ++} rc_client_user_t; ++ ++/** ++ * Gets information about the logged in user. Will return NULL if the user is not logged in. ++ */ ++RC_EXPORT const rc_client_user_t* RC_CCONV rc_client_get_user_info(const rc_client_t* client); ++ ++/** ++ * Gets the URL for the user's profile picture. ++ * Returns RC_OK on success. ++ */ ++RC_EXPORT int RC_CCONV rc_client_user_get_image_url(const rc_client_user_t* user, char buffer[], size_t buffer_size); ++ ++typedef struct rc_client_user_game_summary_t { ++ uint32_t num_core_achievements; ++ uint32_t num_unofficial_achievements; ++ uint32_t num_unlocked_achievements; ++ uint32_t num_unsupported_achievements; ++ ++ uint32_t points_core; ++ uint32_t points_unlocked; ++ ++ /* minimum version: 12.1 */ ++ time_t beaten_time; ++ time_t completed_time; ++} rc_client_user_game_summary_t; ++ ++/** ++ * Gets a breakdown of the number of achievements in the game, and how many the user has unlocked. ++ * Used for the "You have unlocked X of Y achievements" message shown when the game starts. ++ */ ++RC_EXPORT void RC_CCONV rc_client_get_user_game_summary(const rc_client_t* client, rc_client_user_game_summary_t* summary); ++ ++typedef struct rc_client_all_user_progress_entry_t { ++ uint32_t game_id; ++ uint32_t num_achievements; ++ uint32_t num_unlocked_achievements; ++ uint32_t num_unlocked_achievements_hardcore; ++} rc_client_all_user_progress_entry_t; ++ ++typedef struct rc_client_all_user_progress_t { ++ rc_client_all_user_progress_entry_t* entries; ++ uint32_t num_entries; ++} rc_client_all_user_progress_t; ++ ++/** ++ * Callback that is fired when an all progress query completes. list may be null if the query failed. ++ */ ++typedef void(RC_CCONV* rc_client_fetch_all_user_progress_callback_t)(int result, const char* error_message, ++ rc_client_all_user_progress_t* list, ++ rc_client_t* client, void* callback_userdata); ++ ++/** ++ * Starts an asynchronous request for all progress for the given console. ++ * This query returns the total number of achievements for all games tracked by this console, as well as ++ * the user's achievement unlock count for both softcore and hardcore modes. ++ */ ++RC_EXPORT rc_client_async_handle_t* RC_CCONV ++rc_client_begin_fetch_all_user_progress(rc_client_t* client, uint32_t console_id, ++ rc_client_fetch_all_user_progress_callback_t callback, void* callback_userdata); ++ ++/** ++ * Destroys a previously-allocated result from the rc_client_begin_fetch_all_progress_list() callback. ++ */ ++RC_EXPORT void RC_CCONV rc_client_destroy_all_user_progress(rc_client_all_user_progress_t* list); ++ ++/*****************************************************************************\ ++| Game | ++\*****************************************************************************/ ++ ++#ifdef RC_CLIENT_SUPPORTS_HASH ++/** ++ * Start loading an unidentified game. ++ */ ++RC_EXPORT rc_client_async_handle_t* RC_CCONV rc_client_begin_identify_and_load_game(rc_client_t* client, ++ uint32_t console_id, const char* file_path, ++ const uint8_t* data, size_t data_size, ++ rc_client_callback_t callback, void* callback_userdata); ++ ++struct rc_hash_callbacks; ++/** ++ * Provide callback functions for interacting with the file system and processing disc-based files when generating hashes. ++ */ ++RC_EXPORT void rc_client_set_hash_callbacks(rc_client_t* client, const struct rc_hash_callbacks* callbacks); ++#endif ++ ++/** ++ * Start loading a game. ++ */ ++RC_EXPORT rc_client_async_handle_t* RC_CCONV rc_client_begin_load_game(rc_client_t* client, const char* hash, ++ rc_client_callback_t callback, void* callback_userdata); ++ ++/** ++ * Gets the current progress of the asynchronous load game process. ++ */ ++RC_EXPORT int RC_CCONV rc_client_get_load_game_state(const rc_client_t* client); ++enum { ++ RC_CLIENT_LOAD_GAME_STATE_NONE, ++ RC_CLIENT_LOAD_GAME_STATE_AWAIT_LOGIN, ++ RC_CLIENT_LOAD_GAME_STATE_IDENTIFYING_GAME, ++ RC_CLIENT_LOAD_GAME_STATE_FETCHING_GAME_DATA, /* [deprecated] - game data is now returned by identify call */ ++ RC_CLIENT_LOAD_GAME_STATE_STARTING_SESSION, ++ RC_CLIENT_LOAD_GAME_STATE_DONE, ++ RC_CLIENT_LOAD_GAME_STATE_ABORTED ++}; ++ ++/** ++ * Determines if a game was successfully identified and loaded. ++ */ ++RC_EXPORT int RC_CCONV rc_client_is_game_loaded(const rc_client_t* client); ++ ++/** ++ * Unloads the current game. ++ */ ++RC_EXPORT void RC_CCONV rc_client_unload_game(rc_client_t* client); ++ ++typedef struct rc_client_game_t { ++ uint32_t id; ++ uint32_t console_id; ++ const char* title; ++ const char* hash; ++ const char* badge_name; ++ /* minimum version: 12.0 */ ++ const char* badge_url; ++} rc_client_game_t; ++ ++/** ++ * Get information about the current game. Returns NULL if no game is loaded. ++ * NOTE: returns a dummy game record if an unidentified game is loaded. ++ */ ++RC_EXPORT const rc_client_game_t* RC_CCONV rc_client_get_game_info(const rc_client_t* client); ++ ++/** ++ * Gets the URL for the game image. ++ * Returns RC_OK on success. ++ */ ++RC_EXPORT int RC_CCONV rc_client_game_get_image_url(const rc_client_game_t* game, char buffer[], size_t buffer_size); ++ ++#ifdef RC_CLIENT_SUPPORTS_HASH ++/** ++ * Changes the active disc in a multi-disc game. ++ */ ++RC_EXPORT rc_client_async_handle_t* RC_CCONV rc_client_begin_identify_and_change_media(rc_client_t* client, const char* file_path, ++ const uint8_t* data, size_t data_size, rc_client_callback_t callback, void* callback_userdata); ++#endif ++ ++/** ++ * Changes the active disc in a multi-disc game. ++ */ ++RC_EXPORT rc_client_async_handle_t* RC_CCONV rc_client_begin_change_media(rc_client_t* client, const char* hash, ++ rc_client_callback_t callback, void* callback_userdata); ++/* this function was renamed in rcheevos 12.0 */ ++#define rc_client_begin_change_media_from_hash rc_client_begin_change_media ++ ++/*****************************************************************************\ ++| Subsets | ++\*****************************************************************************/ ++ ++typedef struct rc_client_subset_t { ++ uint32_t id; ++ const char* title; ++ char badge_name[16]; ++ ++ uint32_t num_achievements; ++ uint32_t num_leaderboards; ++ ++ /* minimum version: 12.0 */ ++ const char* badge_url; ++} rc_client_subset_t; ++ ++RC_EXPORT const rc_client_subset_t* RC_CCONV rc_client_get_subset_info(rc_client_t* client, uint32_t subset_id); ++ ++RC_EXPORT void RC_CCONV rc_client_get_user_subset_summary(const rc_client_t* client, uint32_t subset_id, rc_client_user_game_summary_t* summary); ++ ++typedef struct rc_client_subset_list_t { ++ const rc_client_subset_t** subsets; ++ uint32_t num_subsets; ++} rc_client_subset_list_t; ++ ++/** ++ * Creates a list of subsets for the currently loaded game. ++ * Returns an allocated list that must be free'd by calling rc_client_destroy_subset_list. ++ */ ++RC_EXPORT rc_client_subset_list_t* RC_CCONV rc_client_create_subset_list(rc_client_t* client); ++ ++/** ++ * Destroys a list allocated by rc_client_create_subset_list_list. ++ */ ++RC_EXPORT void RC_CCONV rc_client_destroy_subset_list(rc_client_subset_list_t* list); ++ ++/*****************************************************************************\ ++| Fetch Game Hashes | ++\*****************************************************************************/ ++ ++typedef struct rc_client_hash_library_entry_t { ++ char hash[33]; ++ uint32_t game_id; ++} rc_client_hash_library_entry_t; ++ ++typedef struct rc_client_hash_library_t { ++ rc_client_hash_library_entry_t* entries; ++ uint32_t num_entries; ++} rc_client_hash_library_t; ++ ++/** ++ * Callback that is fired when a hash library request completes. list may be null if the query failed. ++ */ ++typedef void(RC_CCONV* rc_client_fetch_hash_library_callback_t)(int result, const char* error_message, ++ rc_client_hash_library_t* list, rc_client_t* client, ++ void* callback_userdata); ++ ++/** ++ * Starts an asynchronous request for all hashes for the given console. ++ * This request returns a mapping from hashes to the game's unique identifier. A single game may have multiple ++ * hashes in the case of multi-disc games, or variants that are still compatible with the same achievement set. ++ */ ++RC_EXPORT rc_client_async_handle_t* RC_CCONV rc_client_begin_fetch_hash_library( ++ rc_client_t* client, uint32_t console_id, rc_client_fetch_hash_library_callback_t callback, void* callback_userdata); ++ ++/** ++ * Destroys a previously-allocated result from the rc_client_destroy_hash_library() callback. ++ */ ++RC_EXPORT void RC_CCONV rc_client_destroy_hash_library(rc_client_hash_library_t* list); ++ ++/*****************************************************************************\ ++| Fetch Game Titles | ++\*****************************************************************************/ ++ ++typedef struct rc_client_game_title_entry_t { ++ uint32_t game_id; ++ const char* title; ++ char badge_name[16]; ++} rc_client_game_title_entry_t; ++ ++typedef struct rc_client_game_title_list_t { ++ rc_client_game_title_entry_t* entries; ++ uint32_t num_entries; ++} rc_client_game_title_list_t; ++ ++/** ++ * Callback that is fired when a game titles request completes. list may be null if the query failed. ++ */ ++typedef void(RC_CCONV* rc_client_fetch_game_titles_callback_t)(int result, const char* error_message, ++ rc_client_game_title_list_t* list, rc_client_t* client, ++ void* callback_userdata); ++ ++/** ++ * Starts an asynchronous request for titles and badge names for the specified games. ++ * The caller must provide an array of game IDs and the number of IDs in the array. ++ */ ++RC_EXPORT rc_client_async_handle_t* RC_CCONV rc_client_begin_fetch_game_titles( ++ rc_client_t* client, const uint32_t* game_ids, uint32_t num_game_ids, ++ rc_client_fetch_game_titles_callback_t callback, void* callback_userdata); ++ ++/** ++ * Destroys a previously-allocated result from the rc_client_begin_fetch_game_titles() callback. ++ */ ++RC_EXPORT void RC_CCONV rc_client_destroy_game_title_list(rc_client_game_title_list_t* list); ++ ++/*****************************************************************************\ ++| Achievements | ++\*****************************************************************************/ ++ ++enum { ++ RC_CLIENT_ACHIEVEMENT_STATE_INACTIVE = 0, /* unprocessed */ ++ RC_CLIENT_ACHIEVEMENT_STATE_ACTIVE = 1, /* eligible to trigger */ ++ RC_CLIENT_ACHIEVEMENT_STATE_UNLOCKED = 2, /* earned by user */ ++ RC_CLIENT_ACHIEVEMENT_STATE_DISABLED = 3, /* not supported by this version of the runtime */ ++ NUM_RC_CLIENT_ACHIEVEMENT_STATES = 4 ++}; ++ ++enum { ++ RC_CLIENT_ACHIEVEMENT_CATEGORY_NONE = 0, ++ RC_CLIENT_ACHIEVEMENT_CATEGORY_CORE = (1 << 0), ++ RC_CLIENT_ACHIEVEMENT_CATEGORY_UNOFFICIAL = (1 << 1), ++ RC_CLIENT_ACHIEVEMENT_CATEGORY_CORE_AND_UNOFFICIAL = RC_CLIENT_ACHIEVEMENT_CATEGORY_CORE | RC_CLIENT_ACHIEVEMENT_CATEGORY_UNOFFICIAL ++}; ++ ++enum { ++ RC_CLIENT_ACHIEVEMENT_TYPE_STANDARD = 0, ++ RC_CLIENT_ACHIEVEMENT_TYPE_MISSABLE = 1, ++ RC_CLIENT_ACHIEVEMENT_TYPE_PROGRESSION = 2, ++ RC_CLIENT_ACHIEVEMENT_TYPE_WIN = 3 ++}; ++ ++enum { ++ RC_CLIENT_ACHIEVEMENT_BUCKET_UNKNOWN = 0, ++ RC_CLIENT_ACHIEVEMENT_BUCKET_LOCKED = 1, ++ RC_CLIENT_ACHIEVEMENT_BUCKET_UNLOCKED = 2, ++ RC_CLIENT_ACHIEVEMENT_BUCKET_UNSUPPORTED = 3, ++ RC_CLIENT_ACHIEVEMENT_BUCKET_UNOFFICIAL = 4, ++ RC_CLIENT_ACHIEVEMENT_BUCKET_RECENTLY_UNLOCKED = 5, ++ RC_CLIENT_ACHIEVEMENT_BUCKET_ACTIVE_CHALLENGE = 6, ++ RC_CLIENT_ACHIEVEMENT_BUCKET_ALMOST_THERE = 7, ++ RC_CLIENT_ACHIEVEMENT_BUCKET_UNSYNCED = 8, ++ NUM_RC_CLIENT_ACHIEVEMENT_BUCKETS = 9 ++}; ++ ++enum { ++ RC_CLIENT_ACHIEVEMENT_UNLOCKED_NONE = 0, ++ RC_CLIENT_ACHIEVEMENT_UNLOCKED_SOFTCORE = (1 << 0), ++ RC_CLIENT_ACHIEVEMENT_UNLOCKED_HARDCORE = (1 << 1), ++ RC_CLIENT_ACHIEVEMENT_UNLOCKED_BOTH = RC_CLIENT_ACHIEVEMENT_UNLOCKED_SOFTCORE | RC_CLIENT_ACHIEVEMENT_UNLOCKED_HARDCORE ++}; ++ ++typedef struct rc_client_achievement_t { ++ const char* title; ++ const char* description; ++ char badge_name[8]; ++ char measured_progress[24]; ++ float measured_percent; ++ uint32_t id; ++ uint32_t points; ++ time_t unlock_time; ++ uint8_t state; ++ uint8_t category; ++ uint8_t bucket; ++ uint8_t unlocked; ++ /* minimum version: 11.1 */ ++ float rarity; ++ float rarity_hardcore; ++ uint8_t type; ++ /* minimum version: 12.0 */ ++ const char* badge_url; ++ const char* badge_locked_url; ++} rc_client_achievement_t; ++ ++/** ++ * Get information about an achievement. Returns NULL if not found. ++ */ ++RC_EXPORT const rc_client_achievement_t* RC_CCONV rc_client_get_achievement_info(rc_client_t* client, uint32_t id); ++ ++/** ++ * Gets the URL for the achievement image. ++ * Returns RC_OK on success. ++ */ ++RC_EXPORT int RC_CCONV rc_client_achievement_get_image_url(const rc_client_achievement_t* achievement, int state, char buffer[], size_t buffer_size); ++ ++typedef struct rc_client_achievement_bucket_t { ++ const rc_client_achievement_t** achievements; ++ uint32_t num_achievements; ++ ++ const char* label; ++ uint32_t subset_id; ++ uint8_t bucket_type; ++} rc_client_achievement_bucket_t; ++ ++typedef struct rc_client_achievement_list_t { ++ const rc_client_achievement_bucket_t* buckets; ++ uint32_t num_buckets; ++} rc_client_achievement_list_t; ++ ++enum { ++ RC_CLIENT_ACHIEVEMENT_LIST_GROUPING_LOCK_STATE = 0, ++ RC_CLIENT_ACHIEVEMENT_LIST_GROUPING_PROGRESS = 1 ++}; ++ ++/** ++ * Creates a list of achievements matching the specified category and grouping. ++ * Returns an allocated list that must be free'd by calling rc_client_destroy_achievement_list. ++ */ ++RC_EXPORT rc_client_achievement_list_t* RC_CCONV rc_client_create_achievement_list(rc_client_t* client, int category, int grouping); ++ ++/** ++ * Destroys a list allocated by rc_client_create_achievement_list. ++ */ ++RC_EXPORT void RC_CCONV rc_client_destroy_achievement_list(rc_client_achievement_list_t* list); ++ ++/** ++ * Returns non-zero if there are any achievements that can be queried through rc_client_create_achievement_list(). ++ */ ++RC_EXPORT int RC_CCONV rc_client_has_achievements(rc_client_t* client); ++ ++/*****************************************************************************\ ++| Leaderboards | ++\*****************************************************************************/ ++ ++enum { ++ RC_CLIENT_LEADERBOARD_STATE_INACTIVE = 0, ++ RC_CLIENT_LEADERBOARD_STATE_ACTIVE = 1, ++ RC_CLIENT_LEADERBOARD_STATE_TRACKING = 2, ++ RC_CLIENT_LEADERBOARD_STATE_DISABLED = 3, ++ NUM_RC_CLIENT_LEADERBOARD_STATES = 4 ++}; ++ ++enum { ++ RC_CLIENT_LEADERBOARD_FORMAT_TIME = 0, ++ RC_CLIENT_LEADERBOARD_FORMAT_SCORE = 1, ++ RC_CLIENT_LEADERBOARD_FORMAT_VALUE = 2, ++ NUM_RC_CLIENT_LEADERBOARD_FORMATS = 3 ++}; ++ ++#define RC_CLIENT_LEADERBOARD_DISPLAY_SIZE 24 ++ ++typedef struct rc_client_leaderboard_t { ++ const char* title; ++ const char* description; ++ const char* tracker_value; ++ uint32_t id; ++ uint8_t state; ++ uint8_t format; ++ uint8_t lower_is_better; ++} rc_client_leaderboard_t; ++ ++/** ++ * Get information about a leaderboard. Returns NULL if not found. ++ */ ++RC_EXPORT const rc_client_leaderboard_t* RC_CCONV rc_client_get_leaderboard_info(const rc_client_t* client, uint32_t id); ++ ++typedef struct rc_client_leaderboard_tracker_t { ++ char display[RC_CLIENT_LEADERBOARD_DISPLAY_SIZE]; ++ uint32_t id; ++} rc_client_leaderboard_tracker_t; ++ ++typedef struct rc_client_leaderboard_bucket_t { ++ const rc_client_leaderboard_t** leaderboards; ++ uint32_t num_leaderboards; ++ ++ const char* label; ++ uint32_t subset_id; ++ uint8_t bucket_type; ++} rc_client_leaderboard_bucket_t; ++ ++typedef struct rc_client_leaderboard_list_t { ++ const rc_client_leaderboard_bucket_t* buckets; ++ uint32_t num_buckets; ++} rc_client_leaderboard_list_t; ++ ++enum { ++ RC_CLIENT_LEADERBOARD_BUCKET_UNKNOWN = 0, ++ RC_CLIENT_LEADERBOARD_BUCKET_INACTIVE = 1, ++ RC_CLIENT_LEADERBOARD_BUCKET_ACTIVE = 2, ++ RC_CLIENT_LEADERBOARD_BUCKET_UNSUPPORTED = 3, ++ RC_CLIENT_LEADERBOARD_BUCKET_ALL = 4, ++ NUM_RC_CLIENT_LEADERBOARD_BUCKETS = 5 ++}; ++ ++enum { ++ RC_CLIENT_LEADERBOARD_LIST_GROUPING_NONE = 0, ++ RC_CLIENT_LEADERBOARD_LIST_GROUPING_TRACKING = 1 ++}; ++ ++/** ++ * Creates a list of leaderboards matching the specified grouping. ++ * Returns an allocated list that must be free'd by calling rc_client_destroy_leaderboard_list. ++ */ ++RC_EXPORT rc_client_leaderboard_list_t* RC_CCONV rc_client_create_leaderboard_list(rc_client_t* client, int grouping); ++ ++/** ++ * Destroys a list allocated by rc_client_create_leaderboard_list. ++ */ ++RC_EXPORT void RC_CCONV rc_client_destroy_leaderboard_list(rc_client_leaderboard_list_t* list); ++ ++/** ++ * Returns non-zero if the current game has any leaderboards. ++ */ ++RC_EXPORT int RC_CCONV rc_client_has_leaderboards(rc_client_t* client); ++ ++typedef struct rc_client_leaderboard_entry_t { ++ const char* user; ++ char display[RC_CLIENT_LEADERBOARD_DISPLAY_SIZE]; ++ time_t submitted; ++ uint32_t rank; ++ uint32_t index; ++} rc_client_leaderboard_entry_t; ++ ++typedef struct rc_client_leaderboard_entry_list_t { ++ rc_client_leaderboard_entry_t* entries; ++ uint32_t num_entries; ++ uint32_t total_entries; ++ int32_t user_index; ++} rc_client_leaderboard_entry_list_t; ++ ++typedef void (RC_CCONV *rc_client_fetch_leaderboard_entries_callback_t)(int result, const char* error_message, ++ rc_client_leaderboard_entry_list_t* list, rc_client_t* client, void* callback_userdata); ++ ++/** ++ * Fetches a list of leaderboard entries from the server. ++ * Callback receives an allocated list that must be free'd by calling rc_client_destroy_leaderboard_entry_list. ++ */ ++RC_EXPORT rc_client_async_handle_t* RC_CCONV rc_client_begin_fetch_leaderboard_entries(rc_client_t* client, uint32_t leaderboard_id, ++ uint32_t first_entry, uint32_t count, rc_client_fetch_leaderboard_entries_callback_t callback, void* callback_userdata); ++ ++/** ++ * Fetches a list of leaderboard entries from the server containing the logged-in user. ++ * Callback receives an allocated list that must be free'd by calling rc_client_destroy_leaderboard_entry_list. ++ */ ++RC_EXPORT rc_client_async_handle_t* RC_CCONV rc_client_begin_fetch_leaderboard_entries_around_user(rc_client_t* client, uint32_t leaderboard_id, ++ uint32_t count, rc_client_fetch_leaderboard_entries_callback_t callback, void* callback_userdata); ++ ++/** ++ * Gets the URL for the profile picture of the user associated to a leaderboard entry. ++ * Returns RC_OK on success. ++ */ ++RC_EXPORT int RC_CCONV rc_client_leaderboard_entry_get_user_image_url(const rc_client_leaderboard_entry_t* entry, char buffer[], size_t buffer_size); ++ ++/** ++ * Destroys a list allocated by rc_client_begin_fetch_leaderboard_entries or rc_client_begin_fetch_leaderboard_entries_around_user. ++ */ ++RC_EXPORT void RC_CCONV rc_client_destroy_leaderboard_entry_list(rc_client_leaderboard_entry_list_t* list); ++ ++/** ++ * Used for scoreboard events. Contains the response from the server when a leaderboard entry is submitted. ++ * NOTE: This structure is only valid within the event callback. If you want to make use of the data outside ++ * of the callback, you should create copies of both the top entries and usernames within. ++ */ ++typedef struct rc_client_leaderboard_scoreboard_entry_t { ++ /* The user associated to the entry */ ++ const char* username; ++ /* The rank of the entry */ ++ uint32_t rank; ++ /* The value of the entry */ ++ char score[RC_CLIENT_LEADERBOARD_DISPLAY_SIZE]; ++} rc_client_leaderboard_scoreboard_entry_t; ++ ++typedef struct rc_client_leaderboard_scoreboard_t { ++ /* The ID of the leaderboard which was submitted */ ++ uint32_t leaderboard_id; ++ /* The value that was submitted */ ++ char submitted_score[RC_CLIENT_LEADERBOARD_DISPLAY_SIZE]; ++ /* The player's best submitted value */ ++ char best_score[RC_CLIENT_LEADERBOARD_DISPLAY_SIZE]; ++ /* The player's new rank within the leaderboard */ ++ uint32_t new_rank; ++ /* The total number of entries in the leaderboard */ ++ uint32_t num_entries; ++ ++ /* An array of the top entries for the leaderboard */ ++ rc_client_leaderboard_scoreboard_entry_t* top_entries; ++ /* The number of items in the top_entries array */ ++ uint32_t num_top_entries; ++} rc_client_leaderboard_scoreboard_t; ++ ++/*****************************************************************************\ ++| Rich Presence | ++\*****************************************************************************/ ++ ++/** ++ * Returns non-zero if the current game supports rich presence. ++ */ ++RC_EXPORT int RC_CCONV rc_client_has_rich_presence(rc_client_t* client); ++ ++/** ++ * Gets the current rich presence message. ++ * Returns the number of characters written to buffer. ++ */ ++RC_EXPORT size_t RC_CCONV rc_client_get_rich_presence_message(rc_client_t* client, char buffer[], size_t buffer_size); ++ ++/*****************************************************************************\ ++| Processing | ++\*****************************************************************************/ ++ ++enum { ++ RC_CLIENT_EVENT_TYPE_NONE = 0, ++ RC_CLIENT_EVENT_ACHIEVEMENT_TRIGGERED = 1, /* [achievement] was earned by the player */ ++ RC_CLIENT_EVENT_LEADERBOARD_STARTED = 2, /* [leaderboard] attempt has started */ ++ RC_CLIENT_EVENT_LEADERBOARD_FAILED = 3, /* [leaderboard] attempt failed */ ++ RC_CLIENT_EVENT_LEADERBOARD_SUBMITTED = 4, /* [leaderboard] attempt submitted */ ++ RC_CLIENT_EVENT_ACHIEVEMENT_CHALLENGE_INDICATOR_SHOW = 5, /* [achievement] challenge indicator should be shown */ ++ RC_CLIENT_EVENT_ACHIEVEMENT_CHALLENGE_INDICATOR_HIDE = 6, /* [achievement] challenge indicator should be hidden */ ++ RC_CLIENT_EVENT_ACHIEVEMENT_PROGRESS_INDICATOR_SHOW = 7, /* progress indicator should be shown for [achievement] */ ++ RC_CLIENT_EVENT_ACHIEVEMENT_PROGRESS_INDICATOR_HIDE = 8, /* progress indicator should be hidden */ ++ RC_CLIENT_EVENT_ACHIEVEMENT_PROGRESS_INDICATOR_UPDATE = 9, /* progress indicator should be updated to reflect new badge/progress for [achievement] */ ++ RC_CLIENT_EVENT_LEADERBOARD_TRACKER_SHOW = 10, /* [leaderboard_tracker] should be shown */ ++ RC_CLIENT_EVENT_LEADERBOARD_TRACKER_HIDE = 11, /* [leaderboard_tracker] should be hidden */ ++ RC_CLIENT_EVENT_LEADERBOARD_TRACKER_UPDATE = 12, /* [leaderboard_tracker] updated */ ++ RC_CLIENT_EVENT_LEADERBOARD_SCOREBOARD = 13, /* [leaderboard_scoreboard] possibly-new ranking received for [leaderboard] */ ++ RC_CLIENT_EVENT_RESET = 14, /* emulated system should be reset (as the result of enabling hardcore) */ ++ RC_CLIENT_EVENT_GAME_COMPLETED = 15, /* all achievements for the game have been earned */ ++ RC_CLIENT_EVENT_SERVER_ERROR = 16, /* an API response returned a [server_error] and will not be retried */ ++ RC_CLIENT_EVENT_DISCONNECTED = 17, /* an unlock request could not be completed and is pending */ ++ RC_CLIENT_EVENT_RECONNECTED = 18, /* all pending unlocks have been completed */ ++ RC_CLIENT_EVENT_SUBSET_COMPLETED = 19 /* all achievements for the subset have been earned */ ++}; ++ ++typedef struct rc_client_server_error_t { ++ const char* error_message; ++ const char* api; ++ int result; ++ uint32_t related_id; ++} rc_client_server_error_t; ++ ++typedef struct rc_client_event_t { ++ uint32_t type; ++ ++ rc_client_achievement_t* achievement; ++ rc_client_leaderboard_t* leaderboard; ++ rc_client_leaderboard_tracker_t* leaderboard_tracker; ++ rc_client_leaderboard_scoreboard_t* leaderboard_scoreboard; ++ rc_client_server_error_t* server_error; ++ rc_client_subset_t* subset; ++ ++} rc_client_event_t; ++ ++/** ++ * Callback used to notify the client when certain events occur. ++ */ ++typedef void (RC_CCONV *rc_client_event_handler_t)(const rc_client_event_t* event, rc_client_t* client); ++ ++/** ++ * Provides a callback for event handling. ++ */ ++RC_EXPORT void RC_CCONV rc_client_set_event_handler(rc_client_t* client, rc_client_event_handler_t handler); ++ ++/** ++ * Provides a callback for reading memory. ++ */ ++RC_EXPORT void RC_CCONV rc_client_set_read_memory_function(rc_client_t* client, rc_client_read_memory_func_t handler); ++ ++/** ++ * Specifies whether rc_client is allowed to read memory outside of rc_client_do_frame/rc_client_idle. ++ */ ++RC_EXPORT void RC_CCONV rc_client_set_allow_background_memory_reads(rc_client_t* client, int allowed); ++ ++/** ++ * Determines if there are any active achievements/leaderboards/rich presence that need processing. ++ */ ++RC_EXPORT int RC_CCONV rc_client_is_processing_required(rc_client_t* client); ++ ++/** ++ * Processes achievements for the current frame. ++ */ ++RC_EXPORT void RC_CCONV rc_client_do_frame(rc_client_t* client); ++ ++/** ++ * Processes the periodic queue. ++ * Called internally by rc_client_do_frame. ++ * Should be explicitly called if rc_client_do_frame is not being called because emulation is paused. ++ */ ++RC_EXPORT void RC_CCONV rc_client_idle(rc_client_t* client); ++ ++/** ++ * Determines if a sufficient amount of frames have been processed since the last call to rc_client_can_pause. ++ * Should not be called unless the client is trying to pause. ++ * If false is returned, and frames_remaining is not NULL, frames_remaining will be set to the number of frames ++ * still required before pause is allowed, which can be converted to a time in seconds for displaying to the user. ++ */ ++RC_EXPORT int RC_CCONV rc_client_can_pause(rc_client_t* client, uint32_t* frames_remaining); ++ ++/** ++ * Informs the runtime that the emulator has been reset. Will reset all achievements and leaderboards ++ * to their initial state (includes hiding indicators/trackers). ++ */ ++RC_EXPORT void RC_CCONV rc_client_reset(rc_client_t* client); ++ ++/** ++ * Gets the number of bytes needed to serialized the runtime state. ++ */ ++RC_EXPORT size_t RC_CCONV rc_client_progress_size(rc_client_t* client); ++ ++/** ++ * Serializes the runtime state into a buffer. ++ * Returns RC_OK on success, or an error indicator. ++ * [deprecated] use rc_client_serialize_progress_sized instead ++ */ ++RC_EXPORT int RC_CCONV rc_client_serialize_progress(rc_client_t* client, uint8_t* buffer); ++ ++/** ++ * Serializes the runtime state into a buffer. ++ * Returns RC_OK on success, or an error indicator. ++ */ ++RC_EXPORT int RC_CCONV rc_client_serialize_progress_sized(rc_client_t* client, uint8_t* buffer, size_t buffer_size); ++ ++/** ++ * Deserializes the runtime state from a buffer. ++ * Returns RC_OK on success, or an error indicator. ++ * [deprecated] use rc_client_deserialize_progress_sized instead ++ */ ++RC_EXPORT int RC_CCONV rc_client_deserialize_progress(rc_client_t* client, const uint8_t* serialized); ++ ++/** ++ * Serializes the runtime state into a buffer. ++ * Returns RC_OK on success, or an error indicator. ++ */ ++RC_EXPORT int RC_CCONV rc_client_deserialize_progress_sized(rc_client_t* client, const uint8_t* serialized, size_t serialized_size); ++ ++RC_END_C_DECLS ++ ++#endif /* RC_RUNTIME_H */ +diff -rupbN melonDS.orig/src/rcheevos/include/rc_client_raintegration.h melonDS.ra/src/rcheevos/include/rc_client_raintegration.h +--- melonDS.orig/src/rcheevos/include/rc_client_raintegration.h 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/include/rc_client_raintegration.h 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,101 @@ ++#ifndef RC_CLIENT_RAINTEGRATION_H ++#define RC_CLIENT_RAINTEGRATION_H ++ ++#ifndef _WIN32 ++ #undef RC_CLIENT_SUPPORTS_RAINTEGRATION /* Windows required for RAIntegration */ ++#endif ++ ++#include ++ ++#include "rc_export.h" ++ ++RC_BEGIN_C_DECLS ++ ++typedef struct rc_client_t rc_client_t; /* forward reference; in rc_client.h */ ++ ++/* types needed to implement raintegration */ ++ ++typedef struct rc_client_raintegration_menu_item_t { ++ const char* label; ++ uint32_t id; ++ uint8_t checked; ++ uint8_t enabled; ++} rc_client_raintegration_menu_item_t; ++ ++typedef struct rc_client_raintegration_menu_t { ++ rc_client_raintegration_menu_item_t* items; ++ uint32_t num_items; ++} rc_client_raintegration_menu_t; ++ ++enum { ++ RC_CLIENT_RAINTEGRATION_ACHIEVEMENT_STATE_NONE = 0, ++ RC_CLIENT_RAINTEGRATION_ACHIEVEMENT_STATE_PUBLISHED = 1, ++ RC_CLIENT_RAINTEGRATION_ACHIEVEMENT_STATE_LOCAL = 2, ++ RC_CLIENT_RAINTEGRATION_ACHIEVEMENT_STATE_MODIFIED = 3, ++ RC_CLIENT_RAINTEGRATION_ACHIEVEMENT_STATE_INSECURE = 4, ++}; ++ ++enum { ++ RC_CLIENT_RAINTEGRATION_EVENT_TYPE_NONE = 0, ++ RC_CLIENT_RAINTEGRATION_EVENT_MENUITEM_CHECKED_CHANGED = 1, /* [menu_item] checked changed */ ++ RC_CLIENT_RAINTEGRATION_EVENT_HARDCORE_CHANGED = 2, /* hardcore was enabled or disabled */ ++ RC_CLIENT_RAINTEGRATION_EVENT_PAUSE = 3, /* emulated system should be paused */ ++ RC_CLIENT_RAINTEGRATION_EVENT_MENU_CHANGED = 4 /* one or more items were added/removed from the menu and it should be rebuilt */ ++}; ++ ++typedef struct rc_client_raintegration_event_t { ++ uint32_t type; ++ ++ const rc_client_raintegration_menu_item_t* menu_item; ++} rc_client_raintegration_event_t; ++ ++typedef void (RC_CCONV *rc_client_raintegration_event_handler_t)(const rc_client_raintegration_event_t* event, ++ rc_client_t* client); ++ ++typedef void (RC_CCONV *rc_client_raintegration_write_memory_func_t)(uint32_t address, uint8_t* buffer, ++ uint32_t num_bytes, rc_client_t* client); ++ ++typedef void (RC_CCONV* rc_client_raintegration_get_game_name_func_t)(char* buffer, uint32_t buffer_size, rc_client_t* client); ++ ++/* types needed to integrate raintegration */ ++ ++#ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION ++ ++#ifndef RC_CLIENT_SUPPORTS_EXTERNAL ++ #define RC_CLIENT_SUPPORTS_EXTERNAL /* external rc_client required for RAIntegration */ ++#endif ++ ++#include /* HWND */ ++ ++#include "rc_client.h" ++ ++RC_EXPORT rc_client_async_handle_t* RC_CCONV rc_client_begin_load_raintegration(rc_client_t* client, ++ const wchar_t* search_directory, HWND main_window_handle, ++ const char* client_name, const char* client_version, ++ rc_client_callback_t callback, void* callback_userdata); ++ ++RC_EXPORT void RC_CCONV rc_client_unload_raintegration(rc_client_t* client); ++ ++RC_EXPORT void RC_CCONV rc_client_raintegration_update_main_window_handle(rc_client_t* client, HWND main_window_handle); ++ ++RC_EXPORT const rc_client_raintegration_menu_t* RC_CCONV rc_client_raintegration_get_menu(const rc_client_t* client); ++ ++RC_EXPORT void RC_CCONV rc_client_raintegration_rebuild_submenu(rc_client_t* client, HMENU hMenu); ++RC_EXPORT void RC_CCONV rc_client_raintegration_update_menu_item(const rc_client_t* client, const rc_client_raintegration_menu_item_t* menu_item); ++RC_EXPORT int RC_CCONV rc_client_raintegration_activate_menu_item(const rc_client_t* client, uint32_t menu_item_id); ++ ++RC_EXPORT void RC_CCONV rc_client_raintegration_set_write_memory_function(rc_client_t* client, rc_client_raintegration_write_memory_func_t handler); ++RC_EXPORT void RC_CCONV rc_client_raintegration_set_get_game_name_function(rc_client_t* client, rc_client_raintegration_get_game_name_func_t handler); ++RC_EXPORT void RC_CCONV rc_client_raintegration_set_console_id(rc_client_t* client, uint32_t console_id); ++RC_EXPORT int RC_CCONV rc_client_raintegration_has_modifications(const rc_client_t* client); ++ ++RC_EXPORT void RC_CCONV rc_client_raintegration_set_event_handler(rc_client_t* client, ++ rc_client_raintegration_event_handler_t handler); ++ ++RC_EXPORT int RC_CCONV rc_client_raintegration_get_achievement_state(const rc_client_t* client, uint32_t achievement_id); ++ ++#endif /* RC_CLIENT_SUPPORTS_RAINTEGRATION */ ++ ++RC_END_C_DECLS ++ ++#endif /* RC_CLIENT_RAINTEGRATION_H */ +diff -rupbN melonDS.orig/src/rcheevos/include/rc_consoles.h melonDS.ra/src/rcheevos/include/rc_consoles.h +--- melonDS.orig/src/rcheevos/include/rc_consoles.h 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/include/rc_consoles.h 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,138 @@ ++#ifndef RC_CONSOLES_H ++#define RC_CONSOLES_H ++ ++#include "rc_export.h" ++ ++#include ++ ++RC_BEGIN_C_DECLS ++ ++/*****************************************************************************\ ++| Console identifiers | ++\*****************************************************************************/ ++ ++enum { ++ RC_CONSOLE_UNKNOWN = 0, ++ RC_CONSOLE_MEGA_DRIVE = 1, ++ RC_CONSOLE_NINTENDO_64 = 2, ++ RC_CONSOLE_SUPER_NINTENDO = 3, ++ RC_CONSOLE_GAMEBOY = 4, ++ RC_CONSOLE_GAMEBOY_ADVANCE = 5, ++ RC_CONSOLE_GAMEBOY_COLOR = 6, ++ RC_CONSOLE_NINTENDO = 7, ++ RC_CONSOLE_PC_ENGINE = 8, ++ RC_CONSOLE_SEGA_CD = 9, ++ RC_CONSOLE_SEGA_32X = 10, ++ RC_CONSOLE_MASTER_SYSTEM = 11, ++ RC_CONSOLE_PLAYSTATION = 12, ++ RC_CONSOLE_ATARI_LYNX = 13, ++ RC_CONSOLE_NEOGEO_POCKET = 14, ++ RC_CONSOLE_GAME_GEAR = 15, ++ RC_CONSOLE_GAMECUBE = 16, ++ RC_CONSOLE_ATARI_JAGUAR = 17, ++ RC_CONSOLE_NINTENDO_DS = 18, ++ RC_CONSOLE_WII = 19, ++ RC_CONSOLE_WII_U = 20, ++ RC_CONSOLE_PLAYSTATION_2 = 21, ++ RC_CONSOLE_XBOX = 22, ++ RC_CONSOLE_MAGNAVOX_ODYSSEY2 = 23, ++ RC_CONSOLE_POKEMON_MINI = 24, ++ RC_CONSOLE_ATARI_2600 = 25, ++ RC_CONSOLE_MS_DOS = 26, ++ RC_CONSOLE_ARCADE = 27, ++ RC_CONSOLE_VIRTUAL_BOY = 28, ++ RC_CONSOLE_MSX = 29, ++ RC_CONSOLE_COMMODORE_64 = 30, ++ RC_CONSOLE_ZX81 = 31, ++ RC_CONSOLE_ORIC = 32, ++ RC_CONSOLE_SG1000 = 33, ++ RC_CONSOLE_VIC20 = 34, ++ RC_CONSOLE_AMIGA = 35, ++ RC_CONSOLE_ATARI_ST = 36, ++ RC_CONSOLE_AMSTRAD_PC = 37, ++ RC_CONSOLE_APPLE_II = 38, ++ RC_CONSOLE_SATURN = 39, ++ RC_CONSOLE_DREAMCAST = 40, ++ RC_CONSOLE_PSP = 41, ++ RC_CONSOLE_CDI = 42, ++ RC_CONSOLE_3DO = 43, ++ RC_CONSOLE_COLECOVISION = 44, ++ RC_CONSOLE_INTELLIVISION = 45, ++ RC_CONSOLE_VECTREX = 46, ++ RC_CONSOLE_PC8800 = 47, ++ RC_CONSOLE_PC9800 = 48, ++ RC_CONSOLE_PCFX = 49, ++ RC_CONSOLE_ATARI_5200 = 50, ++ RC_CONSOLE_ATARI_7800 = 51, ++ RC_CONSOLE_X68K = 52, ++ RC_CONSOLE_WONDERSWAN = 53, ++ RC_CONSOLE_CASSETTEVISION = 54, ++ RC_CONSOLE_SUPER_CASSETTEVISION = 55, ++ RC_CONSOLE_NEO_GEO_CD = 56, ++ RC_CONSOLE_FAIRCHILD_CHANNEL_F = 57, ++ RC_CONSOLE_FM_TOWNS = 58, ++ RC_CONSOLE_ZX_SPECTRUM = 59, ++ RC_CONSOLE_GAME_AND_WATCH = 60, ++ RC_CONSOLE_NOKIA_NGAGE = 61, ++ RC_CONSOLE_NINTENDO_3DS = 62, ++ RC_CONSOLE_SUPERVISION = 63, ++ RC_CONSOLE_SHARPX1 = 64, ++ RC_CONSOLE_TIC80 = 65, ++ RC_CONSOLE_THOMSONTO8 = 66, ++ RC_CONSOLE_PC6000 = 67, ++ RC_CONSOLE_PICO = 68, ++ RC_CONSOLE_MEGADUCK = 69, ++ RC_CONSOLE_ZEEBO = 70, ++ RC_CONSOLE_ARDUBOY = 71, ++ RC_CONSOLE_WASM4 = 72, ++ RC_CONSOLE_ARCADIA_2001 = 73, ++ RC_CONSOLE_INTERTON_VC_4000 = 74, ++ RC_CONSOLE_ELEKTOR_TV_GAMES_COMPUTER = 75, ++ RC_CONSOLE_PC_ENGINE_CD = 76, ++ RC_CONSOLE_ATARI_JAGUAR_CD = 77, ++ RC_CONSOLE_NINTENDO_DSI = 78, ++ RC_CONSOLE_TI83 = 79, ++ RC_CONSOLE_UZEBOX = 80, ++ RC_CONSOLE_FAMICOM_DISK_SYSTEM = 81, ++ ++ RC_CONSOLE_HUBS = 100, ++ RC_CONSOLE_EVENTS = 101, ++ RC_CONSOLE_STANDALONE = 102 ++}; ++ ++RC_EXPORT const char* RC_CCONV rc_console_name(uint32_t console_id); ++ ++/*****************************************************************************\ ++| Memory mapping | ++\*****************************************************************************/ ++ ++enum { ++ RC_MEMORY_TYPE_SYSTEM_RAM, /* normal system memory */ ++ RC_MEMORY_TYPE_SAVE_RAM, /* memory that persists between sessions */ ++ RC_MEMORY_TYPE_VIDEO_RAM, /* memory reserved for graphical processing */ ++ RC_MEMORY_TYPE_READONLY, /* memory that maps to read only data */ ++ RC_MEMORY_TYPE_HARDWARE_CONTROLLER, /* memory for interacting with system components */ ++ RC_MEMORY_TYPE_VIRTUAL_RAM, /* secondary address space that maps to real memory in system RAM */ ++ RC_MEMORY_TYPE_UNUSED /* these addresses don't really exist */ ++}; ++ ++typedef struct rc_memory_region_t { ++ uint32_t start_address; /* first address of block as queried by RetroAchievements */ ++ uint32_t end_address; /* last address of block as queried by RetroAchievements */ ++ uint32_t real_address; /* real address for first address of block */ ++ uint8_t type; /* RC_MEMORY_TYPE_ for block */ ++ const char* description; /* short description of block */ ++} ++rc_memory_region_t; ++ ++typedef struct rc_memory_regions_t { ++ const rc_memory_region_t* region; ++ uint32_t num_regions; ++} ++rc_memory_regions_t; ++ ++RC_EXPORT const rc_memory_regions_t* RC_CCONV rc_console_memory_regions(uint32_t console_id); ++ ++RC_END_C_DECLS ++ ++#endif /* RC_CONSOLES_H */ +diff -rupbN melonDS.orig/src/rcheevos/include/rc_error.h melonDS.ra/src/rcheevos/include/rc_error.h +--- melonDS.orig/src/rcheevos/include/rc_error.h 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/include/rc_error.h 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,59 @@ ++#ifndef RC_ERROR_H ++#define RC_ERROR_H ++ ++#include "rc_export.h" ++ ++RC_BEGIN_C_DECLS ++ ++/*****************************************************************************\ ++| Return values | ++\*****************************************************************************/ ++ ++enum { ++ RC_OK = 0, ++ RC_INVALID_FUNC_OPERAND = -1, ++ RC_INVALID_MEMORY_OPERAND = -2, ++ RC_INVALID_CONST_OPERAND = -3, ++ RC_INVALID_FP_OPERAND = -4, ++ RC_INVALID_CONDITION_TYPE = -5, ++ RC_INVALID_OPERATOR = -6, ++ RC_INVALID_REQUIRED_HITS = -7, ++ RC_DUPLICATED_START = -8, ++ RC_DUPLICATED_CANCEL = -9, ++ RC_DUPLICATED_SUBMIT = -10, ++ RC_DUPLICATED_VALUE = -11, ++ RC_DUPLICATED_PROGRESS = -12, ++ RC_MISSING_START = -13, ++ RC_MISSING_CANCEL = -14, ++ RC_MISSING_SUBMIT = -15, ++ RC_MISSING_VALUE = -16, ++ RC_INVALID_LBOARD_FIELD = -17, ++ RC_MISSING_DISPLAY_STRING = -18, ++ RC_OUT_OF_MEMORY = -19, ++ RC_INVALID_VALUE_FLAG = -20, ++ RC_MISSING_VALUE_MEASURED = -21, ++ RC_MULTIPLE_MEASURED = -22, ++ RC_INVALID_MEASURED_TARGET = -23, ++ RC_INVALID_COMPARISON = -24, ++ RC_INVALID_STATE = -25, ++ RC_INVALID_JSON = -26, ++ RC_API_FAILURE = -27, ++ RC_LOGIN_REQUIRED = -28, ++ RC_NO_GAME_LOADED = -29, ++ RC_HARDCORE_DISABLED = -30, ++ RC_ABORTED = -31, ++ RC_NO_RESPONSE = -32, ++ RC_ACCESS_DENIED = -33, ++ RC_INVALID_CREDENTIALS = -34, ++ RC_EXPIRED_TOKEN = -35, ++ RC_INSUFFICIENT_BUFFER = -36, ++ RC_INVALID_VARIABLE_NAME = -37, ++ RC_UNKNOWN_VARIABLE_NAME = -38, ++ RC_NOT_FOUND = -39 ++}; ++ ++RC_EXPORT const char* RC_CCONV rc_error_str(int ret); ++ ++RC_END_C_DECLS ++ ++#endif /* RC_ERROR_H */ +diff -rupbN melonDS.orig/src/rcheevos/include/rc_export.h melonDS.ra/src/rcheevos/include/rc_export.h +--- melonDS.orig/src/rcheevos/include/rc_export.h 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/include/rc_export.h 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,100 @@ ++#ifndef RC_EXPORT_H ++#define RC_EXPORT_H ++ ++/* These macros control how callbacks and public functions are defined */ ++ ++/* RC_SHARED should be defined when building rcheevos as a shared library (e.g. dll/dylib/so). External code should not define this macro. */ ++/* RC_STATIC should be defined when building rcheevos as a static library. External code should also define this macro. */ ++/* RC_IMPORT should be defined for external code using rcheevos as a shared library. */ ++ ++/* For compatibility, if none of these three macros are defined, then the build is assumed to be RC_STATIC */ ++ ++#if !defined(RC_SHARED) && !defined(RC_STATIC) && !defined(RC_IMPORT) ++ #define RC_STATIC ++#endif ++ ++#if (defined(RC_SHARED) && defined(RC_STATIC)) || (defined(RC_SHARED) && defined(RC_IMPORT)) || (defined(RC_STATIC) && defined(RC_IMPORT)) ++ #error RC_SHARED, RC_STATIC, and RC_IMPORT are mutually exclusive ++#endif ++ ++/* RC_BEGIN_C_DECLS and RC_END_C_DECLS should be used for all headers, to enforce C linkage and the C calling convention */ ++/* RC_BEGIN_C_DECLS should be placed after #include's and before header declarations */ ++/* RC_END_C_DECLS should be placed after header declarations */ ++ ++/* example usage ++ * ++ * #ifndef RC_HEADER_H ++ * #define RC_HEADER_H ++ * ++ * #include ++ * ++ * RC_BEGIN_C_DECLS ++ * ++ * uint8_t rc_function(void); ++ * ++ * RC_END_C_DECLS ++ * ++ * #endif ++ */ ++ ++#if defined(__cplusplus) && !defined(CXX_BUILD) ++ #define RC_BEGIN_C_DECLS extern "C" { ++ #define RC_END_C_DECLS } ++#else ++ #define RC_BEGIN_C_DECLS ++ #define RC_END_C_DECLS ++#endif ++ ++/* RC_CCONV should be used for public functions and callbacks, to enforce the cdecl calling convention, if applicable */ ++/* RC_CCONV should be placed after the return type, and between the ( and * for callbacks */ ++ ++/* example usage */ ++/* void RC_CCONV rc_function(void) */ ++/* void (RC_CCONV *rc_callback)(void) */ ++ ++#if defined(_WIN32) ++ /* Windows compilers will ignore __cdecl when not applicable */ ++ #define RC_CCONV __cdecl ++#elif defined(__GNUC__) && defined(__i386__) ++ /* GNU C compilers will warn if cdecl is defined on an unsupported platform */ ++ #define RC_CCONV __attribute__((cdecl)) ++#else ++ #define RC_CCONV ++#endif ++ ++/* RC_EXPORT should be used for public functions */ ++/* RC_EXPORT will provide necessary hints for shared library usage, if applicable */ ++/* RC_EXPORT should be placed before the return type */ ++ ++/* example usage */ ++/* RC_EXPORT void rc_function(void) */ ++ ++#ifdef RC_SHARED ++ #if defined(_WIN32) ++ #define RC_EXPORT __declspec(dllexport) ++ #elif defined(__GNUC__) && __GNUC__ >= 4 ++ #define RC_EXPORT __attribute__((visibility("default"))) ++ #else ++ #define RC_EXPORT ++ #endif ++#endif ++ ++#ifdef RC_IMPORT ++ #if defined(_WIN32) ++ #define RC_EXPORT __declspec(dllimport) ++ #elif defined(__GNUC__) && __GNUC__ >= 4 ++ #define RC_EXPORT __attribute__((visibility("default"))) ++ #else ++ #define RC_EXPORT ++ #endif ++#endif ++ ++#ifdef RC_STATIC ++ #if defined(__GNUC__) && __GNUC__ >= 4 ++ #define RC_EXPORT __attribute__((visibility("default"))) ++ #else ++ #define RC_EXPORT ++ #endif ++#endif ++ ++#endif /* RC_EXPORT_H */ +diff -rupbN melonDS.orig/src/rcheevos/include/rc_hash.h melonDS.ra/src/rcheevos/include/rc_hash.h +--- melonDS.orig/src/rcheevos/include/rc_hash.h 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/include/rc_hash.h 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,200 @@ ++#ifndef RC_HASH_H ++#define RC_HASH_H ++ ++#include ++#include ++#include ++ ++#include "rc_consoles.h" ++ ++RC_BEGIN_C_DECLS ++ ++ struct rc_hash_iterator; ++ ++ /* ===================================================== */ ++ ++ typedef void (RC_CCONV *rc_hash_message_callback_deprecated)(const char*); ++ ++ /* specifies a function to call when an error occurs to display the error message */ ++ /* [deprecated] set callbacks in rc_hash_iterator_t */ ++ RC_EXPORT void RC_CCONV rc_hash_init_error_message_callback(rc_hash_message_callback_deprecated callback); ++ ++ /* specifies a function to call for verbose logging */ ++ /* [deprecated] set callbacks in rc_hash_iterator_t */ ++ RC_EXPORT void rc_hash_init_verbose_message_callback(rc_hash_message_callback_deprecated callback); ++ ++ /* ===================================================== */ ++ ++ /* opens a file */ ++ typedef void* (RC_CCONV *rc_hash_filereader_open_file_handler)(const char* path_utf8); ++ ++ /* moves the file pointer - standard fseek parameters */ ++ typedef void (RC_CCONV *rc_hash_filereader_seek_handler)(void* file_handle, int64_t offset, int origin); ++ ++ /* locates the file pointer */ ++ typedef int64_t (RC_CCONV *rc_hash_filereader_tell_handler)(void* file_handle); ++ ++ /* reads the specified number of bytes from the file starting at the read pointer. ++ * returns the number of bytes actually read. ++ */ ++ typedef size_t (RC_CCONV *rc_hash_filereader_read_handler)(void* file_handle, void* buffer, size_t requested_bytes); ++ ++ /* closes the file */ ++ typedef void (RC_CCONV *rc_hash_filereader_close_file_handler)(void* file_handle); ++ ++ typedef struct rc_hash_filereader ++ { ++ rc_hash_filereader_open_file_handler open; ++ rc_hash_filereader_seek_handler seek; ++ rc_hash_filereader_tell_handler tell; ++ rc_hash_filereader_read_handler read; ++ rc_hash_filereader_close_file_handler close; ++ } rc_hash_filereader_t; ++ ++ /* [deprecated] set callbacks in rc_hash_iterator_t */ ++ RC_EXPORT void RC_CCONV rc_hash_init_custom_filereader(struct rc_hash_filereader* reader); ++ ++ /* ===================================================== */ ++ ++#ifndef RC_HASH_NO_DISC ++ ++ #define RC_HASH_CDTRACK_FIRST_DATA ((uint32_t)-1) /* the first data track (skip audio tracks) */ ++ #define RC_HASH_CDTRACK_LAST ((uint32_t)-2) /* the last data/audio track */ ++ #define RC_HASH_CDTRACK_LARGEST ((uint32_t)-3) /* the largest data/audio track */ ++ #define RC_HASH_CDTRACK_FIRST_OF_SECOND_SESSION ((uint32_t)-4) /* the first data/audio track of the second session */ ++ ++ /* opens a track from the specified file. see the RC_HASH_CDTRACK_ defines for special tracks. ++ * returns a handle to be passed to the other functions, or NULL if the track could not be opened. ++ */ ++ typedef void* (RC_CCONV *rc_hash_cdreader_open_track_handler)(const char* path, uint32_t track); ++ typedef void* (RC_CCONV* rc_hash_cdreader_open_track_iterator_handler)(const char* path, uint32_t track, const struct rc_hash_iterator* iterator); ++ ++ /* attempts to read the specified number of bytes from the file starting at the specified absolute sector. ++ * returns the number of bytes actually read. ++ */ ++ typedef size_t (RC_CCONV *rc_hash_cdreader_read_sector_handler)(void* track_handle, uint32_t sector, void* buffer, size_t requested_bytes); ++ ++ /* closes the track handle */ ++ typedef void (RC_CCONV *rc_hash_cdreader_close_track_handler)(void* track_handle); ++ ++ /* gets the absolute sector index for the first sector of a track */ ++ typedef uint32_t(RC_CCONV *rc_hash_cdreader_first_track_sector_handler)(void* track_handle); ++ ++ typedef struct rc_hash_cdreader ++ { ++ rc_hash_cdreader_open_track_handler open_track; ++ rc_hash_cdreader_read_sector_handler read_sector; ++ rc_hash_cdreader_close_track_handler close_track; ++ rc_hash_cdreader_first_track_sector_handler first_track_sector; ++ rc_hash_cdreader_open_track_iterator_handler open_track_iterator; ++ } rc_hash_cdreader_t; ++ ++ RC_EXPORT void RC_CCONV rc_hash_get_default_cdreader(struct rc_hash_cdreader* cdreader); ++ /* [deprecated] don't set callbacks in rc_hash_iterator_t */ ++ RC_EXPORT void RC_CCONV rc_hash_init_default_cdreader(void); ++ /* [deprecated] set callbacks in rc_hash_iterator_t */ ++ RC_EXPORT void RC_CCONV rc_hash_init_custom_cdreader(struct rc_hash_cdreader* reader); ++ ++#endif /* RC_HASH_NO_DISC */ ++ ++#ifndef RC_HASH_NO_ENCRYPTED ++ ++ /* specifies a function called to obtain a 3DS CIA decryption normal key. ++ * this key would be derived from slot0x3DKeyX and the common key specified by the passed index. ++ * the normal key should be written in big endian format ++ * returns non-zero on success, or zero on failure. ++ */ ++ typedef int (RC_CCONV *rc_hash_3ds_get_cia_normal_key_func)(uint8_t common_key_index, uint8_t out_normal_key[16]); ++ /* [deprecated] set callbacks in rc_hash_iterator_t */ ++ RC_EXPORT void RC_CCONV rc_hash_init_3ds_get_cia_normal_key_func(rc_hash_3ds_get_cia_normal_key_func func); ++ ++ /* specifies a function called to obtain 3DS NCCH decryption normal keys. ++ * the primary key will always use slot0x2CKeyX and the passed primary KeyY. ++ * the secondary key will use the KeyX slot passed ++ * the secondary KeyY will be identical to the primary keyY if the passed program id is NULL ++ * if the program id is not null, then the secondary KeyY will be obtained with "seed crypto" ++ * with "seed crypto" the 8 byte program id can be used to obtain a 16 byte "seed" within the seeddb.bin firmware file ++ * the primary KeyY then the seed will then be hashed with SHA256, and the upper 16 bytes of the digest will be the secondary KeyY used ++ * the normal keys should be written in big endian format ++ * returns non-zero on success, or zero on failure. ++ */ ++ typedef int (RC_CCONV *rc_hash_3ds_get_ncch_normal_keys_func)(uint8_t primary_key_y[16], uint8_t secondary_key_x_slot, uint8_t* optional_program_id, ++ uint8_t out_primary_key[16], uint8_t out_secondary_key[16]); ++ /* [deprecated] set callbacks in rc_hash_iterator_t */ ++ RC_EXPORT void RC_CCONV rc_hash_init_3ds_get_ncch_normal_keys_func(rc_hash_3ds_get_ncch_normal_keys_func func); ++ ++#endif /* RC_HASH_NO_ENCRYPTED */ ++ ++/* ===================================================== */ ++ ++typedef void (RC_CCONV* rc_hash_message_callback_func)(const char*, const struct rc_hash_iterator* iterator); ++ ++typedef struct rc_hash_callbacks { ++ rc_hash_message_callback_func verbose_message; ++ rc_hash_message_callback_func error_message; ++ ++ rc_hash_filereader_t filereader; ++#ifndef RC_HASH_NO_DISC ++ rc_hash_cdreader_t cdreader; ++#endif ++ ++#ifndef RC_HASH_NO_ENCRYPTED ++ struct rc_hash_encryption_callbacks { ++ rc_hash_3ds_get_cia_normal_key_func get_3ds_cia_normal_key; ++ rc_hash_3ds_get_ncch_normal_keys_func get_3ds_ncch_normal_keys; ++ } encryption; ++#endif ++} rc_hash_callbacks_t; ++ ++/* data for rc_hash_iterate ++ */ ++typedef struct rc_hash_iterator { ++ const uint8_t* buffer; ++ size_t buffer_size; ++ uint8_t consoles[12]; ++ int index; ++ const char* path; ++ void* userdata; ++ ++ rc_hash_callbacks_t callbacks; ++} rc_hash_iterator_t; ++ ++/* initializes a rc_hash_iterator ++ * - path must be provided ++ * - if buffer and buffer_size are provided, path may be a filename (i.e. for something extracted from a zip file) ++ */ ++RC_EXPORT void RC_CCONV rc_hash_initialize_iterator(rc_hash_iterator_t* iterator, const char* path, const uint8_t* buffer, size_t buffer_size); ++ ++/* releases resources associated to a rc_hash_iterator ++ */ ++RC_EXPORT void RC_CCONV rc_hash_destroy_iterator(rc_hash_iterator_t* iterator); ++ ++/* generates the next hash for the data in the rc_hash_iterator. ++ * returns non-zero if a hash was generated, or zero if no more hashes can be generated for the data. ++ */ ++RC_EXPORT int RC_CCONV rc_hash_iterate(char hash[33], rc_hash_iterator_t* iterator); ++ ++/* generates a hash for the data in the rc_hash_iterator. ++ * returns non-zero if a hash was generated. ++ */ ++RC_EXPORT int RC_CCONV rc_hash_generate(char hash[33], uint32_t console_id, const rc_hash_iterator_t* iterator); ++ ++/* ===================================================== */ ++ ++/* generates a hash from a block of memory. ++ * returns non-zero on success, or zero on failure. ++ */ ++/* [deprecated] use rc_hash_generate instead */ ++RC_EXPORT int RC_CCONV rc_hash_generate_from_buffer(char hash[33], uint32_t console_id, const uint8_t* buffer, size_t buffer_size); ++ ++/* generates a hash from a file. ++ * returns non-zero on success, or zero on failure. ++ */ ++/* [deprecated] use rc_hash_generate instead */ ++RC_EXPORT int RC_CCONV rc_hash_generate_from_file(char hash[33], uint32_t console_id, const char* path); ++ ++/* ===================================================== */ ++ ++RC_END_C_DECLS ++ ++#endif /* RC_HASH_H */ +diff -rupbN melonDS.orig/src/rcheevos/include/rc_runtime.h melonDS.ra/src/rcheevos/include/rc_runtime.h +--- melonDS.orig/src/rcheevos/include/rc_runtime.h 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/include/rc_runtime.h 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,148 @@ ++#ifndef RC_RUNTIME_H ++#define RC_RUNTIME_H ++ ++#include "rc_error.h" ++ ++#include ++#include ++ ++RC_BEGIN_C_DECLS ++ ++/*****************************************************************************\ ++| Forward Declarations (defined in rc_runtime_types.h) | ++\*****************************************************************************/ ++ ++#ifndef RC_RUNTIME_TYPES_H /* prevents pedantic redefinition error */ ++ ++typedef struct rc_trigger_t rc_trigger_t; ++typedef struct rc_lboard_t rc_lboard_t; ++typedef struct rc_richpresence_t rc_richpresence_t; ++typedef struct rc_memref_t rc_memref_t; ++typedef struct rc_value_t rc_value_t; ++ ++#endif ++ ++/*****************************************************************************\ ++| Callbacks | ++\*****************************************************************************/ ++ ++/** ++ * Callback used to read num_bytes bytes from memory starting at address. If ++ * num_bytes is greater than 1, the value is read in little-endian from ++ * memory. ++ */ ++typedef uint32_t(RC_CCONV *rc_runtime_peek_t)(uint32_t address, uint32_t num_bytes, void* ud); ++ ++/*****************************************************************************\ ++| Runtime | ++\*****************************************************************************/ ++ ++typedef struct rc_runtime_trigger_t { ++ uint32_t id; ++ rc_trigger_t* trigger; ++ void* buffer; ++ rc_memref_t* invalid_memref; ++ uint8_t md5[16]; ++ int32_t serialized_size; ++} ++rc_runtime_trigger_t; ++ ++typedef struct rc_runtime_lboard_t { ++ uint32_t id; ++ int32_t value; ++ rc_lboard_t* lboard; ++ void* buffer; ++ rc_memref_t* invalid_memref; ++ uint8_t md5[16]; ++ uint32_t serialized_size; ++} ++rc_runtime_lboard_t; ++ ++typedef struct rc_runtime_richpresence_t { ++ rc_richpresence_t* richpresence; ++ void* buffer; ++ uint8_t md5[16]; ++} ++rc_runtime_richpresence_t; ++ ++typedef struct rc_runtime_t { ++ rc_runtime_trigger_t* triggers; ++ uint32_t trigger_count; ++ uint32_t trigger_capacity; ++ ++ rc_runtime_lboard_t* lboards; ++ uint32_t lboard_count; ++ uint32_t lboard_capacity; ++ ++ rc_runtime_richpresence_t* richpresence; ++ ++ struct rc_memrefs_t* memrefs; ++ ++ uint8_t owns_self; ++} ++rc_runtime_t; ++ ++RC_EXPORT rc_runtime_t* RC_CCONV rc_runtime_alloc(void); ++RC_EXPORT void RC_CCONV rc_runtime_init(rc_runtime_t* runtime); ++RC_EXPORT void RC_CCONV rc_runtime_destroy(rc_runtime_t* runtime); ++ ++RC_EXPORT int RC_CCONV rc_runtime_activate_achievement(rc_runtime_t* runtime, uint32_t id, const char* memaddr, void* unused_L, int unused_funcs_idx); ++RC_EXPORT void RC_CCONV rc_runtime_deactivate_achievement(rc_runtime_t* runtime, uint32_t id); ++RC_EXPORT rc_trigger_t* RC_CCONV rc_runtime_get_achievement(const rc_runtime_t* runtime, uint32_t id); ++RC_EXPORT int RC_CCONV rc_runtime_get_achievement_measured(const rc_runtime_t* runtime, uint32_t id, unsigned* measured_value, unsigned* measured_target); ++RC_EXPORT int RC_CCONV rc_runtime_format_achievement_measured(const rc_runtime_t* runtime, uint32_t id, char *buffer, size_t buffer_size); ++ ++RC_EXPORT int RC_CCONV rc_runtime_activate_lboard(rc_runtime_t* runtime, uint32_t id, const char* memaddr, void* unused_L, int unused_funcs_idx); ++RC_EXPORT void RC_CCONV rc_runtime_deactivate_lboard(rc_runtime_t* runtime, uint32_t id); ++RC_EXPORT rc_lboard_t* RC_CCONV rc_runtime_get_lboard(const rc_runtime_t* runtime, uint32_t id); ++RC_EXPORT int RC_CCONV rc_runtime_format_lboard_value(char* buffer, int size, int32_t value, int format); ++ ++ ++RC_EXPORT int RC_CCONV rc_runtime_activate_richpresence(rc_runtime_t* runtime, const char* script, void* unused_L, int unused_funcs_idx); ++RC_EXPORT int RC_CCONV rc_runtime_get_richpresence(const rc_runtime_t* runtime, char* buffer, size_t buffersize, rc_runtime_peek_t peek, void* peek_ud, void* unused_L); ++ ++enum { ++ RC_RUNTIME_EVENT_ACHIEVEMENT_ACTIVATED, /* from WAITING, PAUSED, or PRIMED to ACTIVE */ ++ RC_RUNTIME_EVENT_ACHIEVEMENT_PAUSED, ++ RC_RUNTIME_EVENT_ACHIEVEMENT_RESET, ++ RC_RUNTIME_EVENT_ACHIEVEMENT_TRIGGERED, ++ RC_RUNTIME_EVENT_ACHIEVEMENT_PRIMED, ++ RC_RUNTIME_EVENT_LBOARD_STARTED, ++ RC_RUNTIME_EVENT_LBOARD_CANCELED, ++ RC_RUNTIME_EVENT_LBOARD_UPDATED, ++ RC_RUNTIME_EVENT_LBOARD_TRIGGERED, ++ RC_RUNTIME_EVENT_ACHIEVEMENT_DISABLED, ++ RC_RUNTIME_EVENT_LBOARD_DISABLED, ++ RC_RUNTIME_EVENT_ACHIEVEMENT_UNPRIMED, ++ RC_RUNTIME_EVENT_ACHIEVEMENT_PROGRESS_UPDATED ++}; ++ ++typedef struct rc_runtime_event_t { ++ uint32_t id; ++ int32_t value; ++ uint8_t type; ++} ++rc_runtime_event_t; ++ ++typedef void (RC_CCONV *rc_runtime_event_handler_t)(const rc_runtime_event_t* runtime_event); ++ ++RC_EXPORT void RC_CCONV rc_runtime_do_frame(rc_runtime_t* runtime, rc_runtime_event_handler_t event_handler, rc_runtime_peek_t peek, void* ud, void* unused_L); ++RC_EXPORT void RC_CCONV rc_runtime_reset(rc_runtime_t* runtime); ++ ++typedef int (RC_CCONV *rc_runtime_validate_address_t)(uint32_t address); ++RC_EXPORT void RC_CCONV rc_runtime_validate_addresses(rc_runtime_t* runtime, rc_runtime_event_handler_t event_handler, rc_runtime_validate_address_t validate_handler); ++RC_EXPORT void RC_CCONV rc_runtime_invalidate_address(rc_runtime_t* runtime, uint32_t address); ++ ++RC_EXPORT uint32_t RC_CCONV rc_runtime_progress_size(const rc_runtime_t* runtime, void* unused_L); ++ ++/* [deprecated] use rc_runtime_serialize_progress_sized instead */ ++RC_EXPORT int RC_CCONV rc_runtime_serialize_progress(void* buffer, const rc_runtime_t* runtime, void* unused_L); ++RC_EXPORT int RC_CCONV rc_runtime_serialize_progress_sized(uint8_t* buffer, uint32_t buffer_size, const rc_runtime_t* runtime, void* unused_L); ++ ++/* [deprecated] use rc_runtime_deserialize_progress_sized instead */ ++RC_EXPORT int RC_CCONV rc_runtime_deserialize_progress(rc_runtime_t* runtime, const uint8_t* serialized, void* unused_L); ++RC_EXPORT int RC_CCONV rc_runtime_deserialize_progress_sized(rc_runtime_t* runtime, const uint8_t* serialized, uint32_t serialized_size, void* unused_L); ++ ++RC_END_C_DECLS ++ ++#endif /* RC_RUNTIME_H */ +diff -rupbN melonDS.orig/src/rcheevos/include/rc_runtime_types.h melonDS.ra/src/rcheevos/include/rc_runtime_types.h +--- melonDS.orig/src/rcheevos/include/rc_runtime_types.h 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/include/rc_runtime_types.h 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,452 @@ ++#ifndef RC_RUNTIME_TYPES_H ++#define RC_RUNTIME_TYPES_H ++ ++#include "rc_error.h" ++ ++#include ++#include ++ ++RC_BEGIN_C_DECLS ++ ++#ifndef RC_RUNTIME_H /* prevents pedantic redefiniton error */ ++ ++typedef struct rc_trigger_t rc_trigger_t; ++typedef struct rc_lboard_t rc_lboard_t; ++typedef struct rc_richpresence_t rc_richpresence_t; ++typedef struct rc_memref_t rc_memref_t; ++typedef struct rc_value_t rc_value_t; ++ ++#endif ++ ++/*****************************************************************************\ ++| Callbacks | ++\*****************************************************************************/ ++ ++/** ++ * Callback used to read num_bytes bytes from memory starting at address. If ++ * num_bytes is greater than 1, the value is read in little-endian from ++ * memory. ++ */ ++typedef uint32_t(RC_CCONV* rc_peek_t)(uint32_t address, uint32_t num_bytes, void* ud); ++ ++/*****************************************************************************\ ++| Memory References | ++\*****************************************************************************/ ++ ++/* Sizes. */ ++enum { ++ RC_MEMSIZE_8_BITS, ++ RC_MEMSIZE_16_BITS, ++ RC_MEMSIZE_24_BITS, ++ RC_MEMSIZE_32_BITS, ++ RC_MEMSIZE_LOW, ++ RC_MEMSIZE_HIGH, ++ RC_MEMSIZE_BIT_0, ++ RC_MEMSIZE_BIT_1, ++ RC_MEMSIZE_BIT_2, ++ RC_MEMSIZE_BIT_3, ++ RC_MEMSIZE_BIT_4, ++ RC_MEMSIZE_BIT_5, ++ RC_MEMSIZE_BIT_6, ++ RC_MEMSIZE_BIT_7, ++ RC_MEMSIZE_BITCOUNT, ++ RC_MEMSIZE_16_BITS_BE, ++ RC_MEMSIZE_24_BITS_BE, ++ RC_MEMSIZE_32_BITS_BE, ++ RC_MEMSIZE_FLOAT, ++ RC_MEMSIZE_MBF32, ++ RC_MEMSIZE_MBF32_LE, ++ RC_MEMSIZE_FLOAT_BE, ++ RC_MEMSIZE_DOUBLE32, ++ RC_MEMSIZE_DOUBLE32_BE, ++ RC_MEMSIZE_VARIABLE ++}; ++ ++typedef struct rc_memref_value_t { ++ /* The current value of this memory reference. */ ++ uint32_t value; ++ /* The last differing value of this memory reference. */ ++ uint32_t prior; ++ ++ /* The size of the value. (RC_MEMSIZE_*) */ ++ uint8_t size; ++ /* True if the value changed this frame. */ ++ uint8_t changed; ++ /* The value type of the value. (RC_VALUE_TYPE_*) */ ++ uint8_t type; ++ /* The type of memref (RC_MEMREF_TYPE_*) */ ++ uint8_t memref_type; ++} ++rc_memref_value_t; ++ ++struct rc_memref_t { ++ /* The current value at the specified memory address. */ ++ rc_memref_value_t value; ++ ++ /* The memory address of this variable. */ ++ uint32_t address; ++}; ++ ++/*****************************************************************************\ ++| Operands | ++\*****************************************************************************/ ++ ++/* types */ ++enum { ++ RC_OPERAND_ADDRESS, /* The value of a live address in RAM. */ ++ RC_OPERAND_DELTA, /* The value last known at this address. */ ++ RC_OPERAND_CONST, /* A 32-bit unsigned integer. */ ++ RC_OPERAND_FP, /* A floating point value. */ ++ RC_OPERAND_FUNC, /* A function that provides the value. */ ++ RC_OPERAND_PRIOR, /* The last differing value at this address. */ ++ RC_OPERAND_BCD, /* The BCD-decoded value of a live address in RAM. */ ++ RC_OPERAND_INVERTED, /* The twos-complement value of a live address in RAM. */ ++ RC_OPERAND_RECALL /* The value captured by the last RC_CONDITION_REMEMBER condition */ ++}; ++ ++typedef struct rc_operand_t { ++ union { ++ /* A value read from memory. */ ++ rc_memref_t* memref; ++ ++ /* An integer value. */ ++ uint32_t num; ++ ++ /* A floating point value. */ ++ double dbl; ++ } value; ++ ++ /* specifies which member of the value union is being used (RC_OPERAND_*) */ ++ uint8_t type; ++ ++ /* the RC_MEMSIZE of the operand specified in the condition definition - memref.size may differ */ ++ uint8_t size; ++ ++ /* specifies how to read the memref for some types (RC_OPERAND_*) */ ++ uint8_t memref_access_type; ++ ++ /* if set, this operand is combining the current condition with the previous one */ ++ uint8_t is_combining; ++} ++rc_operand_t; ++ ++RC_EXPORT int RC_CCONV rc_operand_is_memref(const rc_operand_t* operand); ++ ++/*****************************************************************************\ ++| Conditions | ++\*****************************************************************************/ ++ ++/* types */ ++enum { ++ RC_CONDITION_STANDARD, /* this should always be 0 */ ++ RC_CONDITION_PAUSE_IF, ++ RC_CONDITION_RESET_IF, ++ RC_CONDITION_MEASURED_IF, ++ RC_CONDITION_TRIGGER, ++ RC_CONDITION_MEASURED, ++ RC_CONDITION_ADD_SOURCE, ++ RC_CONDITION_SUB_SOURCE, ++ RC_CONDITION_ADD_ADDRESS, ++ RC_CONDITION_REMEMBER, ++ RC_CONDITION_ADD_HITS, ++ RC_CONDITION_SUB_HITS, ++ RC_CONDITION_RESET_NEXT_IF, ++ RC_CONDITION_AND_NEXT, ++ RC_CONDITION_OR_NEXT ++}; ++ ++/* operators */ ++enum { ++ RC_OPERATOR_EQ, ++ RC_OPERATOR_LT, ++ RC_OPERATOR_LE, ++ RC_OPERATOR_GT, ++ RC_OPERATOR_GE, ++ RC_OPERATOR_NE, ++ RC_OPERATOR_NONE, ++ RC_OPERATOR_MULT, ++ RC_OPERATOR_DIV, ++ RC_OPERATOR_AND, ++ RC_OPERATOR_XOR, ++ RC_OPERATOR_MOD, ++ RC_OPERATOR_ADD, ++ RC_OPERATOR_SUB, ++ ++ RC_OPERATOR_SUB_PARENT, /* internal use */ ++ RC_OPERATOR_ADD_ACCUMULATOR, /* internal use */ ++ RC_OPERATOR_SUB_ACCUMULATOR, /* internal use */ ++ RC_OPERATOR_INDIRECT_READ /* internal use */ ++}; ++ ++typedef struct rc_condition_t rc_condition_t; ++ ++struct rc_condition_t { ++ /* The condition's operands. */ ++ rc_operand_t operand1; ++ rc_operand_t operand2; ++ ++ /* Required hits to fire this condition. */ ++ uint32_t required_hits; ++ /* Number of hits so far. */ ++ uint32_t current_hits; ++ ++ /* The next condition in the chain. */ ++ rc_condition_t* next; ++ ++ /* The type of the condition. (RC_CONDITION_*) */ ++ uint8_t type; ++ ++ /* The comparison operator to use. (RC_OPERATOR_*) */ ++ uint8_t oper; /* operator is a reserved word in C++. */ ++ ++ /* Will be non-zero if the condition evaluated true on the last check. ++ * - The lowest bit indicates whether the condition itself was true. ++ * - The second lowest bit will only ever be set on ResetIf conditions. ++ * If set, it indicates that the condition was responsible for resetting the ++ * trigger. A reset clears all hit counts, so the condition may not appear to ++ * be true just from looking at it (in which case the lower bit will be 0). ++ * Also, the condition might have only met its required_hits target though ++ * an AddHits chain which will have also been reset. ++ */ ++ uint8_t is_true; ++ ++ /* Unique identifier of optimized comparator to use. (RC_PROCESSING_COMPARE_*) */ ++ uint8_t optimized_comparator; ++}; ++ ++/*****************************************************************************\ ++| Condition sets | ++\*****************************************************************************/ ++ ++typedef struct rc_condset_t rc_condset_t; ++ ++struct rc_condset_t { ++ /* The next condition set in the chain. */ ++ rc_condset_t* next; ++ ++ /* The first condition in this condition set. Then follow ->next chain. */ ++ rc_condition_t* conditions; ++ ++ /* The number of pause conditions in this condition set. */ ++ /* The first pause condition is at "this + RC_ALIGN(sizeof(this)). */ ++ uint16_t num_pause_conditions; ++ ++ /* The number of reset conditions in this condition set. */ ++ uint16_t num_reset_conditions; ++ ++ /* The number of hittarget conditions in this condition set. */ ++ uint16_t num_hittarget_conditions; ++ ++ /* The number of non-hittarget measured conditions in this condition set. */ ++ uint16_t num_measured_conditions; ++ ++ /* The number of other conditions in this condition set. */ ++ uint16_t num_other_conditions; ++ ++ /* The number of indirect conditions in this condition set. */ ++ uint16_t num_indirect_conditions; ++ ++ /* True if any condition in the set is a pause condition. */ ++ uint8_t has_pause; /* DEPRECATED - just check num_pause_conditions != 0 */ ++ /* True if the set is currently paused. */ ++ uint8_t is_paused; ++}; ++ ++/*****************************************************************************\ ++| Trigger | ++\*****************************************************************************/ ++ ++enum { ++ RC_TRIGGER_STATE_INACTIVE, /* achievement is not being processed */ ++ RC_TRIGGER_STATE_WAITING, /* achievement cannot trigger until it has been false for at least one frame */ ++ RC_TRIGGER_STATE_ACTIVE, /* achievement is active and may trigger */ ++ RC_TRIGGER_STATE_PAUSED, /* achievement is currently paused and will not trigger */ ++ RC_TRIGGER_STATE_RESET, /* achievement hit counts were reset */ ++ RC_TRIGGER_STATE_TRIGGERED, /* achievement has triggered */ ++ RC_TRIGGER_STATE_PRIMED, /* all non-Trigger conditions are true */ ++ RC_TRIGGER_STATE_DISABLED /* achievement cannot be processed at this time */ ++}; ++ ++struct rc_trigger_t { ++ /* The main condition set. */ ++ rc_condset_t* requirement; ++ ++ /* The list of sub condition sets in this test. */ ++ rc_condset_t* alternative; ++ ++ /* The current state of the MEASURED condition. */ ++ uint32_t measured_value; ++ ++ /* The target state of the MEASURED condition */ ++ uint32_t measured_target; ++ ++ /* The current state of the trigger */ ++ uint8_t state; ++ ++ /* True if at least one condition has a non-zero hit count */ ++ uint8_t has_hits; ++ ++ /* True if the measured value should be displayed as a percentage */ ++ uint8_t measured_as_percent; ++ ++ /* True if the trigger has its own rc_memrefs_t */ ++ uint8_t has_memrefs; ++}; ++ ++RC_EXPORT int RC_CCONV rc_trigger_size(const char* memaddr); ++RC_EXPORT rc_trigger_t* RC_CCONV rc_parse_trigger(void* buffer, const char* memaddr, void* unused_L, int unused_funcs_idx); ++RC_EXPORT int RC_CCONV rc_evaluate_trigger(rc_trigger_t* trigger, rc_peek_t peek, void* ud, void* unused_L); ++RC_EXPORT int RC_CCONV rc_test_trigger(rc_trigger_t* trigger, rc_peek_t peek, void* ud, void* unused_L); ++RC_EXPORT void RC_CCONV rc_reset_trigger(rc_trigger_t* self); ++ ++/*****************************************************************************\ ++| Values | ++\*****************************************************************************/ ++ ++#define RC_VALUE_MAX_NAME_LENGTH 15 ++ ++struct rc_value_t { ++ /* The current value of the variable. */ ++ rc_memref_value_t value; ++ ++ /* True if the value has its own rc_memrefs_t */ ++ uint8_t has_memrefs; ++ ++ /* The list of possible values (traverse next chain, pick max). */ ++ rc_condset_t* conditions; ++ ++ /* The name of the variable. */ ++ const char* name; ++ ++ /* The next variable in the chain. */ ++ rc_value_t* next; ++}; ++ ++RC_EXPORT int RC_CCONV rc_value_size(const char* memaddr); ++RC_EXPORT rc_value_t* RC_CCONV rc_parse_value(void* buffer, const char* memaddr, void* unused_L, int unused_funcs_idx); ++RC_EXPORT int32_t RC_CCONV rc_evaluate_value(rc_value_t* value, rc_peek_t peek, void* ud, void* unused_L); ++ ++/*****************************************************************************\ ++| Leaderboards | ++\*****************************************************************************/ ++ ++/* Return values for rc_evaluate_lboard. */ ++enum { ++ RC_LBOARD_STATE_INACTIVE, /* leaderboard is not being processed */ ++ RC_LBOARD_STATE_WAITING, /* leaderboard cannot activate until the start condition has been false for at least one frame */ ++ RC_LBOARD_STATE_ACTIVE, /* leaderboard is active and may start */ ++ RC_LBOARD_STATE_STARTED, /* leaderboard attempt in progress */ ++ RC_LBOARD_STATE_CANCELED, /* leaderboard attempt canceled */ ++ RC_LBOARD_STATE_TRIGGERED, /* leaderboard attempt complete, value should be submitted */ ++ RC_LBOARD_STATE_DISABLED /* leaderboard cannot be processed at this time */ ++}; ++ ++struct rc_lboard_t { ++ rc_trigger_t start; ++ rc_trigger_t submit; ++ rc_trigger_t cancel; ++ rc_value_t value; ++ rc_value_t* progress; ++ ++ uint8_t state; ++ uint8_t has_memrefs; ++}; ++ ++RC_EXPORT int RC_CCONV rc_lboard_size(const char* memaddr); ++RC_EXPORT rc_lboard_t* RC_CCONV rc_parse_lboard(void* buffer, const char* memaddr, void* unused_L, int unused_funcs_idx); ++RC_EXPORT int RC_CCONV rc_evaluate_lboard(rc_lboard_t* lboard, int32_t* value, rc_peek_t peek, void* peek_ud, void* unused_L); ++RC_EXPORT void RC_CCONV rc_reset_lboard(rc_lboard_t* lboard); ++ ++/*****************************************************************************\ ++| Value formatting | ++\*****************************************************************************/ ++ ++/* Supported formats. */ ++enum { ++ RC_FORMAT_FRAMES, ++ RC_FORMAT_SECONDS, ++ RC_FORMAT_CENTISECS, ++ RC_FORMAT_SCORE, ++ RC_FORMAT_VALUE, ++ RC_FORMAT_MINUTES, ++ RC_FORMAT_SECONDS_AS_MINUTES, ++ RC_FORMAT_FLOAT1, ++ RC_FORMAT_FLOAT2, ++ RC_FORMAT_FLOAT3, ++ RC_FORMAT_FLOAT4, ++ RC_FORMAT_FLOAT5, ++ RC_FORMAT_FLOAT6, ++ RC_FORMAT_FIXED1, ++ RC_FORMAT_FIXED2, ++ RC_FORMAT_FIXED3, ++ RC_FORMAT_TENS, ++ RC_FORMAT_HUNDREDS, ++ RC_FORMAT_THOUSANDS, ++ RC_FORMAT_UNSIGNED_VALUE, ++ RC_FORMAT_UNFORMATTED ++}; ++ ++RC_EXPORT int RC_CCONV rc_parse_format(const char* format_str); ++RC_EXPORT int RC_CCONV rc_format_value(char* buffer, int size, int32_t value, int format); ++ ++/*****************************************************************************\ ++| Rich Presence | ++\*****************************************************************************/ ++ ++typedef struct rc_richpresence_lookup_item_t rc_richpresence_lookup_item_t; ++ ++struct rc_richpresence_lookup_item_t { ++ uint32_t first; ++ uint32_t last; ++ rc_richpresence_lookup_item_t* left; ++ rc_richpresence_lookup_item_t* right; ++ const char* label; ++}; ++ ++typedef struct rc_richpresence_lookup_t rc_richpresence_lookup_t; ++ ++struct rc_richpresence_lookup_t { ++ rc_richpresence_lookup_item_t* root; ++ rc_richpresence_lookup_t* next; ++ const char* name; ++ const char* default_label; ++ uint8_t format; ++}; ++ ++typedef struct rc_richpresence_display_part_t rc_richpresence_display_part_t; ++ ++struct rc_richpresence_display_part_t { ++ rc_richpresence_display_part_t* next; ++ const char* text; ++ rc_richpresence_lookup_t* lookup; ++ rc_operand_t value; ++ uint8_t display_type; ++}; ++ ++typedef struct rc_richpresence_display_t rc_richpresence_display_t; ++ ++struct rc_richpresence_display_t { ++ rc_trigger_t trigger; ++ rc_richpresence_display_t* next; ++ rc_richpresence_display_part_t* display; ++ uint8_t has_required_hits; ++}; ++ ++struct rc_richpresence_t { ++ rc_richpresence_display_t* first_display; ++ rc_richpresence_lookup_t* first_lookup; ++ rc_value_t* values; ++ uint8_t has_memrefs; ++}; ++ ++RC_EXPORT int RC_CCONV rc_richpresence_size(const char* script); ++RC_EXPORT int RC_CCONV rc_richpresence_size_lines(const char* script, int* lines_read); ++RC_EXPORT rc_richpresence_t* RC_CCONV rc_parse_richpresence(void* buffer, const char* script, void* unused_L, int unused_funcs_idx); ++RC_EXPORT int RC_CCONV rc_evaluate_richpresence(rc_richpresence_t* richpresence, char* buffer, size_t buffersize, rc_peek_t peek, void* peek_ud, void* unused_L); ++RC_EXPORT void RC_CCONV rc_update_richpresence(rc_richpresence_t* richpresence, rc_peek_t peek, void* peek_ud, void* unused_L); ++RC_EXPORT int RC_CCONV rc_get_richpresence_display_string(rc_richpresence_t* richpresence, char* buffer, size_t buffersize, rc_peek_t peek, void* peek_ud, void* unused_L); ++RC_EXPORT void RC_CCONV rc_reset_richpresence(rc_richpresence_t* self); ++ ++RC_END_C_DECLS ++ ++#endif /* RC_RUNTIME_TYPES_H */ +diff -rupbN melonDS.orig/src/rcheevos/include/rc_util.h melonDS.ra/src/rcheevos/include/rc_util.h +--- melonDS.orig/src/rcheevos/include/rc_util.h 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/include/rc_util.h 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,51 @@ ++#ifndef RC_UTIL_H ++#define RC_UTIL_H ++ ++#include "rc_export.h" ++ ++#include ++#include ++ ++RC_BEGIN_C_DECLS ++ ++/** ++ * A block of memory for variable length data (like strings and arrays). ++ */ ++typedef struct rc_buffer_chunk_t { ++ /* The current location where data is being written */ ++ uint8_t* write; ++ /* The first byte past the end of data where writing cannot occur */ ++ uint8_t* end; ++ /* The first byte of the data */ ++ uint8_t* start; ++ /* The next block in the allocated memory chain */ ++ struct rc_buffer_chunk_t* next; ++} ++rc_buffer_chunk_t; ++ ++/** ++ * A preallocated block of memory for variable length data (like strings and arrays). ++ */ ++typedef struct rc_buffer_t { ++ /* The chunk data (will point at the local data member) */ ++ struct rc_buffer_chunk_t chunk; ++ /* Small chunk of memory pre-allocated for the chunk */ ++ uint8_t data[256]; ++} ++rc_buffer_t; ++ ++void rc_buffer_init(rc_buffer_t* buffer); ++void rc_buffer_destroy(rc_buffer_t* buffer); ++uint8_t* rc_buffer_reserve(rc_buffer_t* buffer, size_t amount); ++void rc_buffer_consume(rc_buffer_t* buffer, const uint8_t* start, uint8_t* end); ++void* rc_buffer_alloc(rc_buffer_t* buffer, size_t amount); ++char* rc_buffer_strcpy(rc_buffer_t* buffer, const char* src); ++char* rc_buffer_strncpy(rc_buffer_t* buffer, const char* src, size_t len); ++ ++uint32_t rc_djb2(const char* input); ++ ++void rc_format_md5(char checksum[33], const uint8_t digest[16]); ++ ++RC_END_C_DECLS ++ ++#endif /* RC_UTIL_H */ +diff -rupbN melonDS.orig/src/rcheevos/include/rcheevos.h melonDS.ra/src/rcheevos/include/rcheevos.h +--- melonDS.orig/src/rcheevos/include/rcheevos.h 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/include/rcheevos.h 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,8 @@ ++#ifndef RCHEEVOS_H ++#define RCHEEVOS_H ++ ++#include "rc_runtime.h" ++#include "rc_runtime_types.h" ++#include "rc_consoles.h" ++ ++#endif /* RCHEEVOS_H */ +diff -rupbN melonDS.orig/src/rcheevos/src/rapi/rc_api_common.c melonDS.ra/src/rcheevos/src/rapi/rc_api_common.c +--- melonDS.orig/src/rcheevos/src/rapi/rc_api_common.c 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rapi/rc_api_common.c 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,1379 @@ ++#include "rc_api_common.h" ++#include "rc_api_request.h" ++#include "rc_api_runtime.h" ++ ++#include "../rc_compat.h" ++ ++#include ++#include ++#include ++#include ++ ++#define RETROACHIEVEMENTS_HOST "https://retroachievements.org" ++#define RETROACHIEVEMENTS_IMAGE_HOST "https://media.retroachievements.org" ++#define RETROACHIEVEMENTS_HOST_NONSSL "http://retroachievements.org" ++#define RETROACHIEVEMENTS_IMAGE_HOST_NONSSL "http://media.retroachievements.org" ++rc_api_host_t g_host = { NULL, NULL }; ++ ++/* --- rc_json --- */ ++ ++static int rc_json_parse_object(rc_json_iterator_t* iterator, rc_json_field_t* fields, size_t field_count, uint32_t* fields_seen); ++static int rc_json_parse_array(rc_json_iterator_t* iterator, rc_json_field_t* field); ++ ++static int rc_json_match_char(rc_json_iterator_t* iterator, char c) ++{ ++ if (iterator->json < iterator->end && *iterator->json == c) { ++ ++iterator->json; ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static void rc_json_skip_whitespace(rc_json_iterator_t* iterator) ++{ ++ while (iterator->json < iterator->end && isspace((unsigned char)*iterator->json)) ++ ++iterator->json; ++} ++ ++static int rc_json_find_substring(rc_json_iterator_t* iterator, const char* substring) ++{ ++ const char first = *substring; ++ const size_t substring_len = strlen(substring); ++ const char* end = iterator->end - substring_len; ++ ++ while (iterator->json <= end) { ++ if (*iterator->json == first) { ++ if (memcmp(iterator->json, substring, substring_len) == 0) ++ return 1; ++ } ++ ++ ++iterator->json; ++ } ++ ++ return 0; ++} ++ ++static int rc_json_find_closing_quote(rc_json_iterator_t* iterator) ++{ ++ while (iterator->json < iterator->end) { ++ if (*iterator->json == '"') ++ return 1; ++ ++ if (*iterator->json == '\\') { ++ ++iterator->json; ++ if (iterator->json == iterator->end) ++ return 0; ++ } ++ ++ if (*iterator->json == '\0') ++ return 0; ++ ++ ++iterator->json; ++ } ++ ++ return 0; ++} ++ ++static int rc_json_parse_field(rc_json_iterator_t* iterator, rc_json_field_t* field) { ++ int result; ++ ++ if (iterator->json >= iterator->end) ++ return RC_INVALID_JSON; ++ ++ field->value_start = iterator->json; ++ ++ switch (*iterator->json) ++ { ++ case '"': /* quoted string */ ++ ++iterator->json; ++ if (!rc_json_find_closing_quote(iterator)) ++ return RC_INVALID_JSON; ++ ++iterator->json; ++ break; ++ ++ case '-': ++ case '+': /* signed number */ ++ ++iterator->json; ++ /* fallthrough to number */ ++ case '0': case '1': case '2': case '3': case '4': ++ case '5': case '6': case '7': case '8': case '9': /* number */ ++ while (iterator->json < iterator->end && *iterator->json >= '0' && *iterator->json <= '9') ++ ++iterator->json; ++ ++ if (rc_json_match_char(iterator, '.')) { ++ while (iterator->json < iterator->end && *iterator->json >= '0' && *iterator->json <= '9') ++ ++iterator->json; ++ } ++ break; ++ ++ case '[': /* array */ ++ result = rc_json_parse_array(iterator, field); ++ if (result != RC_OK) ++ return result; ++ ++ break; ++ ++ case '{': /* object */ ++ result = rc_json_parse_object(iterator, NULL, 0, &field->array_size); ++ if (result != RC_OK) ++ return result; ++ ++ break; ++ ++ default: /* non-quoted text [true,false,null] */ ++ if (!isalpha((unsigned char)*iterator->json)) ++ return RC_INVALID_JSON; ++ ++ while (iterator->json < iterator->end && isalnum((unsigned char)*iterator->json)) ++ ++iterator->json; ++ break; ++ } ++ ++ field->value_end = iterator->json; ++ return RC_OK; ++} ++ ++static int rc_json_parse_array(rc_json_iterator_t* iterator, rc_json_field_t* field) { ++ rc_json_field_t unused_field; ++ int result; ++ ++ if (!rc_json_match_char(iterator, '[')) ++ return RC_INVALID_JSON; ++ ++ field->array_size = 0; ++ ++ if (rc_json_match_char(iterator, ']')) /* empty array */ ++ return RC_OK; ++ ++ do ++ { ++ rc_json_skip_whitespace(iterator); ++ ++ result = rc_json_parse_field(iterator, &unused_field); ++ if (result != RC_OK) ++ return result; ++ ++ ++field->array_size; ++ ++ rc_json_skip_whitespace(iterator); ++ } while (rc_json_match_char(iterator, ',')); ++ ++ if (!rc_json_match_char(iterator, ']')) ++ return RC_INVALID_JSON; ++ ++ return RC_OK; ++} ++ ++static int rc_json_get_next_field(rc_json_iterator_t* iterator, rc_json_field_t* field) { ++ rc_json_skip_whitespace(iterator); ++ ++ if (!rc_json_match_char(iterator, '"')) ++ return RC_INVALID_JSON; ++ ++ field->name = iterator->json; ++ while (iterator->json < iterator->end && *iterator->json != '"') { ++ if (!*iterator->json) ++ return RC_INVALID_JSON; ++ ++iterator->json; ++ } ++ ++ if (iterator->json == iterator->end) ++ return RC_INVALID_JSON; ++ ++ field->name_len = iterator->json - field->name; ++ ++iterator->json; ++ ++ rc_json_skip_whitespace(iterator); ++ ++ if (!rc_json_match_char(iterator, ':')) ++ return RC_INVALID_JSON; ++ ++ rc_json_skip_whitespace(iterator); ++ ++ if (rc_json_parse_field(iterator, field) < 0) ++ return RC_INVALID_JSON; ++ ++ rc_json_skip_whitespace(iterator); ++ ++ return RC_OK; ++} ++ ++static int rc_json_parse_object(rc_json_iterator_t* iterator, rc_json_field_t* fields, size_t field_count, uint32_t* fields_seen) { ++ size_t i; ++ uint32_t num_fields = 0; ++ rc_json_field_t field; ++ int result; ++ ++ if (fields_seen) ++ *fields_seen = 0; ++ ++ for (i = 0; i < field_count; ++i) ++ fields[i].value_start = fields[i].value_end = NULL; ++ ++ if (!rc_json_match_char(iterator, '{')) ++ return RC_INVALID_JSON; ++ ++ if (rc_json_match_char(iterator, '}')) /* empty object */ ++ return RC_OK; ++ ++ do ++ { ++ result = rc_json_get_next_field(iterator, &field); ++ if (result != RC_OK) ++ return result; ++ ++ for (i = 0; i < field_count; ++i) { ++ if (!fields[i].value_start && fields[i].name_len == field.name_len && ++ memcmp(fields[i].name, field.name, field.name_len) == 0) { ++ fields[i].value_start = field.value_start; ++ fields[i].value_end = field.value_end; ++ fields[i].array_size = field.array_size; ++ break; ++ } ++ } ++ ++ ++num_fields; ++ ++ } while (rc_json_match_char(iterator, ',')); ++ ++ if (!rc_json_match_char(iterator, '}')) ++ return RC_INVALID_JSON; ++ ++ if (fields_seen) ++ *fields_seen = num_fields; ++ ++ return RC_OK; ++} ++ ++int rc_json_get_next_object_field(rc_json_iterator_t* iterator, rc_json_field_t* field) { ++ if (!rc_json_match_char(iterator, ',') && !rc_json_match_char(iterator, '{')) ++ return 0; ++ ++ return (rc_json_get_next_field(iterator, field) == RC_OK); ++} ++ ++int rc_json_get_object_string_length(const char* json) { ++ rc_json_iterator_t iterator; ++ memset(&iterator, 0, sizeof(iterator)); ++ iterator.json = json; ++ iterator.end = json + (1024 * 1024 * 1024); /* arbitrary 1GB limit on JSON response */ ++ ++ rc_json_parse_object(&iterator, NULL, 0, NULL); ++ ++ if (iterator.json == json) /* not JSON */ ++ return (int)strlen(json); ++ ++ return (int)(iterator.json - json); ++} ++ ++static int rc_json_extract_html_error(rc_api_response_t* response, const rc_api_server_response_t* server_response) { ++ rc_json_iterator_t iterator; ++ memset(&iterator, 0, sizeof(iterator)); ++ iterator.json = server_response->body; ++ iterator.end = server_response->body + server_response->body_length; ++ ++ /* assume the title contains the most appropriate message to display to the user */ ++ if (rc_json_find_substring(&iterator, "")) { ++ const char* title_start = iterator.json + 7; ++ if (rc_json_find_substring(&iterator, "")) { ++ response->error_message = rc_buffer_strncpy(&response->buffer, title_start, iterator.json - title_start); ++ response->succeeded = 0; ++ return RC_INVALID_JSON; ++ } ++ } ++ ++ /* title not found, return the first line of the response (up to 200 characters) */ ++ iterator.json = server_response->body; ++ ++ while (iterator.json < iterator.end && *iterator.json != '\n' && ++ iterator.json - server_response->body < 200) { ++ ++iterator.json; ++ } ++ ++ if (iterator.json > server_response->body && iterator.json[-1] == '\r') ++ --iterator.json; ++ ++ if (iterator.json > server_response->body) ++ response->error_message = rc_buffer_strncpy(&response->buffer, server_response->body, iterator.json - server_response->body); ++ ++ response->succeeded = 0; ++ return RC_INVALID_JSON; ++} ++ ++static int rc_json_convert_error_code(const char* server_error_code) ++{ ++ switch (server_error_code[0]) { ++ case 'a': ++ if (strcmp(server_error_code, "access_denied") == 0) ++ return RC_ACCESS_DENIED; ++ break; ++ ++ case 'e': ++ if (strcmp(server_error_code, "expired_token") == 0) ++ return RC_EXPIRED_TOKEN; ++ break; ++ ++ case 'i': ++ if (strcmp(server_error_code, "invalid_credentials") == 0) ++ return RC_INVALID_CREDENTIALS; ++ if (strcmp(server_error_code, "invalid_parameter") == 0) ++ return RC_INVALID_STATE; ++ break; ++ ++ case 'm': ++ if (strcmp(server_error_code, "missing_parameter") == 0) ++ return RC_INVALID_STATE; ++ break; ++ ++ case 'n': ++ if (strcmp(server_error_code, "not_found") == 0) ++ return RC_NOT_FOUND; ++ break; ++ ++ default: ++ break; ++ } ++ ++ return RC_API_FAILURE; ++} ++ ++int rc_json_parse_server_response(rc_api_response_t* response, const rc_api_server_response_t* server_response, rc_json_field_t* fields, size_t field_count) { ++ int result; ++ ++#ifndef NDEBUG ++ if (field_count < 2) ++ return RC_INVALID_STATE; ++ if (strcmp(fields[0].name, "Success") != 0) ++ return RC_INVALID_STATE; ++ if (strcmp(fields[1].name, "Error") != 0) ++ return RC_INVALID_STATE; ++#endif ++ ++ response->error_message = NULL; ++ ++ if (!server_response) { ++ response->succeeded = 0; ++ return RC_NO_RESPONSE; ++ } ++ ++ if (server_response->http_status_code == RC_API_SERVER_RESPONSE_CLIENT_ERROR || ++ server_response->http_status_code == RC_API_SERVER_RESPONSE_RETRYABLE_CLIENT_ERROR) { ++ /* client provided error message is passed as the response body */ ++ response->error_message = server_response->body; ++ response->succeeded = 0; ++ return RC_NO_RESPONSE; ++ } ++ ++ if (!server_response->body || !*server_response->body) { ++ /* expect valid HTTP status codes to have bodies that we can extract the message from, ++ * but provide some default messages in case they don't. */ ++ switch (server_response->http_status_code) { ++ case 504: /* 504 Gateway Timeout */ ++ case 522: /* 522 Connection Timed Out */ ++ case 524: /* 524 A Timeout Occurred */ ++ response->error_message = "Request has timed out."; ++ break; ++ ++ case 521: /* 521 Web Server is Down */ ++ case 523: /* 523 Origin is Unreachable */ ++ response->error_message = "Could not connect to server."; ++ break; ++ ++ default: ++ break; ++ } ++ ++ response->succeeded = 0; ++ return RC_NO_RESPONSE; ++ } ++ ++ if (*server_response->body != '{') { ++ result = rc_json_extract_html_error(response, server_response); ++ } ++ else { ++ rc_json_iterator_t iterator; ++ memset(&iterator, 0, sizeof(iterator)); ++ iterator.json = server_response->body; ++ iterator.end = server_response->body + server_response->body_length; ++ result = rc_json_parse_object(&iterator, fields, field_count, NULL); ++ ++ rc_json_get_optional_string(&response->error_message, response, &fields[1], "Error", NULL); ++ rc_json_get_optional_bool(&response->succeeded, &fields[0], "Success", 1); ++ ++ /* Code will be the third field in the fields array, but may not always be present */ ++ if (field_count > 2 && strcmp(fields[2].name, "Code") == 0) { ++ rc_json_get_optional_string(&response->error_code, response, &fields[2], "Code", NULL); ++ if (response->error_code != NULL) ++ result = rc_json_convert_error_code(response->error_code); ++ } ++ } ++ ++ return result; ++} ++ ++static int rc_json_missing_field(rc_api_response_t* response, const rc_json_field_t* field) { ++ const char* not_found = " not found in response"; ++ const size_t not_found_len = strlen(not_found); ++ const size_t field_len = strlen(field->name); ++ ++ uint8_t* write = rc_buffer_reserve(&response->buffer, field_len + not_found_len + 1); ++ if (write) { ++ response->error_message = (char*)write; ++ memcpy(write, field->name, field_len); ++ write += field_len; ++ memcpy(write, not_found, not_found_len + 1); ++ write += not_found_len + 1; ++ rc_buffer_consume(&response->buffer, (uint8_t*)response->error_message, write); ++ } ++ ++ response->succeeded = 0; ++ return 0; ++} ++ ++int rc_json_get_required_object(rc_json_field_t* fields, size_t field_count, rc_api_response_t* response, rc_json_field_t* field, const char* field_name) { ++ rc_json_iterator_t iterator; ++ ++#ifndef NDEBUG ++ if (strcmp(field->name, field_name) != 0) ++ return 0; ++#else ++ (void)field_name; ++#endif ++ ++ if (!field->value_start) ++ return rc_json_missing_field(response, field); ++ ++ memset(&iterator, 0, sizeof(iterator)); ++ iterator.json = field->value_start; ++ iterator.end = field->value_end; ++ return (rc_json_parse_object(&iterator, fields, field_count, &field->array_size) == RC_OK); ++} ++ ++static int rc_json_get_array_entry_value(rc_json_field_t* field, rc_json_iterator_t* iterator) { ++ rc_json_skip_whitespace(iterator); ++ ++ if (iterator->json >= iterator->end) ++ return 0; ++ ++ if (rc_json_parse_field(iterator, field) != RC_OK) ++ return 0; ++ ++ rc_json_skip_whitespace(iterator); ++ ++ if (!rc_json_match_char(iterator, ',')) ++ rc_json_match_char(iterator, ']'); ++ ++ return 1; ++} ++ ++int rc_json_get_required_unum_array(uint32_t** entries, uint32_t* num_entries, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name) { ++ rc_json_iterator_t iterator; ++ rc_json_field_t array; ++ rc_json_field_t value; ++ uint32_t* entry; ++ ++ memset(&array, 0, sizeof(array)); ++ if (!rc_json_get_required_array(num_entries, &array, response, field, field_name)) ++ return RC_MISSING_VALUE; ++ ++ if (*num_entries) { ++ *entries = (uint32_t*)rc_buffer_alloc(&response->buffer, *num_entries * sizeof(uint32_t)); ++ if (!*entries) ++ return RC_OUT_OF_MEMORY; ++ ++ value.name = field_name; ++ ++ memset(&iterator, 0, sizeof(iterator)); ++ iterator.json = array.value_start; ++ iterator.end = array.value_end; ++ ++ entry = *entries; ++ while (rc_json_get_array_entry_value(&value, &iterator)) { ++ if (!rc_json_get_unum(entry, &value, field_name)) ++ return RC_MISSING_VALUE; ++ ++ ++entry; ++ } ++ } ++ else { ++ *entries = NULL; ++ } ++ ++ return RC_OK; ++} ++ ++int rc_json_get_required_array(uint32_t* num_entries, rc_json_field_t* array_field, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name) { ++#ifndef NDEBUG ++ if (strcmp(field->name, field_name) != 0) ++ return 0; ++#endif ++ ++ if (!rc_json_get_optional_array(num_entries, array_field, field, field_name)) ++ return rc_json_missing_field(response, field); ++ ++ return 1; ++} ++ ++int rc_json_get_optional_array(uint32_t* num_entries, rc_json_field_t* array_field, const rc_json_field_t* field, const char* field_name) { ++#ifndef NDEBUG ++ if (strcmp(field->name, field_name) != 0) ++ return 0; ++#else ++ (void)field_name; ++#endif ++ ++ if (!field->value_start || *field->value_start != '[') { ++ *num_entries = 0; ++ return 0; ++ } ++ ++ memcpy(array_field, field, sizeof(*array_field)); ++ ++array_field->value_start; /* skip [ */ ++ ++ *num_entries = field->array_size; ++ return 1; ++} ++ ++int rc_json_get_array_entry_object(rc_json_field_t* fields, size_t field_count, rc_json_iterator_t* iterator) { ++ rc_json_skip_whitespace(iterator); ++ ++ if (iterator->json >= iterator->end) ++ return 0; ++ ++ if (rc_json_parse_object(iterator, fields, field_count, NULL) != RC_OK) ++ return 0; ++ ++ rc_json_skip_whitespace(iterator); ++ ++ if (!rc_json_match_char(iterator, ',')) ++ rc_json_match_char(iterator, ']'); ++ ++ return 1; ++} ++ ++static uint32_t rc_json_decode_hex4(const char* input) { ++ char hex[5]; ++ ++ memcpy(hex, input, 4); ++ hex[4] = '\0'; ++ ++ return (uint32_t)strtoul(hex, NULL, 16); ++} ++ ++static int rc_json_ucs32_to_utf8(uint8_t* dst, uint32_t ucs32_char) { ++ if (ucs32_char < 0x80) { ++ dst[0] = (ucs32_char & 0x7F); ++ return 1; ++ } ++ ++ if (ucs32_char < 0x0800) { ++ dst[1] = 0x80 | (ucs32_char & 0x3F); ucs32_char >>= 6; ++ dst[0] = 0xC0 | (ucs32_char & 0x1F); ++ return 2; ++ } ++ ++ if (ucs32_char < 0x010000) { ++ dst[2] = 0x80 | (ucs32_char & 0x3F); ucs32_char >>= 6; ++ dst[1] = 0x80 | (ucs32_char & 0x3F); ucs32_char >>= 6; ++ dst[0] = 0xE0 | (ucs32_char & 0x0F); ++ return 3; ++ } ++ ++ if (ucs32_char < 0x200000) { ++ dst[3] = 0x80 | (ucs32_char & 0x3F); ucs32_char >>= 6; ++ dst[2] = 0x80 | (ucs32_char & 0x3F); ucs32_char >>= 6; ++ dst[1] = 0x80 | (ucs32_char & 0x3F); ucs32_char >>= 6; ++ dst[0] = 0xF0 | (ucs32_char & 0x07); ++ return 4; ++ } ++ ++ if (ucs32_char < 0x04000000) { ++ dst[4] = 0x80 | (ucs32_char & 0x3F); ucs32_char >>= 6; ++ dst[3] = 0x80 | (ucs32_char & 0x3F); ucs32_char >>= 6; ++ dst[2] = 0x80 | (ucs32_char & 0x3F); ucs32_char >>= 6; ++ dst[1] = 0x80 | (ucs32_char & 0x3F); ucs32_char >>= 6; ++ dst[0] = 0xF8 | (ucs32_char & 0x03); ++ return 5; ++ } ++ ++ dst[5] = 0x80 | (ucs32_char & 0x3F); ucs32_char >>= 6; ++ dst[4] = 0x80 | (ucs32_char & 0x3F); ucs32_char >>= 6; ++ dst[3] = 0x80 | (ucs32_char & 0x3F); ucs32_char >>= 6; ++ dst[2] = 0x80 | (ucs32_char & 0x3F); ucs32_char >>= 6; ++ dst[1] = 0x80 | (ucs32_char & 0x3F); ucs32_char >>= 6; ++ dst[0] = 0xFC | (ucs32_char & 0x01); ++ return 6; ++} ++ ++int rc_json_get_string(const char** out, rc_buffer_t* buffer, const rc_json_field_t* field, const char* field_name) { ++ const char* src = field->value_start; ++ size_t len = field->value_end - field->value_start; ++ char* dst; ++ ++#ifndef NDEBUG ++ if (strcmp(field->name, field_name) != 0) ++ return 0; ++#else ++ (void)field_name; ++#endif ++ ++ if (!src) { ++ *out = NULL; ++ return 0; ++ } ++ ++ if (len == 4 && memcmp(field->value_start, "null", 4) == 0) { ++ *out = NULL; ++ return 1; ++ } ++ ++ if (*src == '\"') { ++ ++src; ++ ++ if (*src == '\"') { ++ /* simple optimization for empty string - don't allocate space */ ++ *out = ""; ++ return 1; ++ } ++ ++ *out = dst = (char*)rc_buffer_reserve(buffer, len - 1); /* -2 for quotes, +1 for null terminator */ ++ ++ do { ++ if (*src == '\\') { ++ ++src; ++ if (*src == 'n') { ++ /* newline */ ++ ++src; ++ *dst++ = '\n'; ++ continue; ++ } ++ ++ if (*src == 'r') { ++ /* carriage return */ ++ ++src; ++ *dst++ = '\r'; ++ continue; ++ } ++ ++ if (*src == 'u') { ++ /* unicode character */ ++ uint32_t ucs32_char = rc_json_decode_hex4(src + 1); ++ src += 5; ++ ++ if (ucs32_char >= 0xD800 && ucs32_char < 0xE000) { ++ /* surrogate lead - look for surrogate tail */ ++ if (ucs32_char < 0xDC00 && src[0] == '\\' && src[1] == 'u') { ++ const uint32_t surrogate = rc_json_decode_hex4(src + 2); ++ src += 6; ++ ++ if (surrogate >= 0xDC00 && surrogate < 0xE000) { ++ /* found a surrogate tail, merge them */ ++ ucs32_char = (((ucs32_char - 0xD800) << 10) | (surrogate - 0xDC00)) + 0x10000; ++ } ++ } ++ ++ if (!(ucs32_char & 0xFFFF0000)) { ++ /* invalid surrogate pair, fallback to replacement char */ ++ ucs32_char = 0xFFFD; ++ } ++ } ++ ++ dst += rc_json_ucs32_to_utf8((unsigned char*)dst, ucs32_char); ++ continue; ++ } ++ ++ if (*src == 't') { ++ /* tab */ ++ ++src; ++ *dst++ = '\t'; ++ continue; ++ } ++ ++ /* just an escaped character, fallthrough to normal copy */ ++ } ++ ++ *dst++ = *src++; ++ } while (*src != '\"'); ++ ++ } else { ++ *out = dst = (char*)rc_buffer_reserve(buffer, len + 1); /* +1 for null terminator */ ++ memcpy(dst, src, len); ++ dst += len; ++ } ++ ++ *dst++ = '\0'; ++ rc_buffer_consume(buffer, (uint8_t*)(*out), (uint8_t*)dst); ++ return 1; ++} ++ ++int rc_json_field_string_matches(const rc_json_field_t* field, const char* text) { ++ int is_quoted = 0; ++ const char* ptr = field->value_start; ++ if (!ptr) ++ return 0; ++ ++ if (*ptr == '"') { ++ is_quoted = 1; ++ ++ptr; ++ } ++ ++ while (ptr < field->value_end) { ++ if (*ptr != *text) { ++ if (*ptr != '\\') { ++ if (*ptr == '"' && is_quoted && (*text == '\0')) { ++ is_quoted = 0; ++ ++ptr; ++ continue; ++ } ++ ++ return 0; ++ } ++ ++ ++ptr; ++ switch (*ptr) { ++ case 'n': ++ if (*text != '\n') ++ return 0; ++ break; ++ case 'r': ++ if (*text != '\r') ++ return 0; ++ break; ++ case 't': ++ if (*text != '\t') ++ return 0; ++ break; ++ default: ++ if (*text != *ptr) ++ return 0; ++ break; ++ } ++ } ++ ++ ++text; ++ ++ptr; ++ } ++ ++ return !is_quoted && (*text == '\0'); ++} ++ ++void rc_json_get_optional_string(const char** out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name, const char* default_value) { ++ if (!rc_json_get_string(out, &response->buffer, field, field_name)) ++ *out = default_value; ++} ++ ++int rc_json_get_required_string(const char** out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name) { ++ if (rc_json_get_string(out, &response->buffer, field, field_name)) ++ return 1; ++ ++ return rc_json_missing_field(response, field); ++} ++ ++int rc_json_get_num(int32_t* out, const rc_json_field_t* field, const char* field_name) { ++ const char* src = field->value_start; ++ int32_t value = 0; ++ int negative = 0; ++ ++#ifndef NDEBUG ++ if (strcmp(field->name, field_name) != 0) ++ return 0; ++#else ++ (void)field_name; ++#endif ++ ++ if (!src) { ++ *out = 0; ++ return 0; ++ } ++ ++ /* assert: string contains only numerals and an optional sign per rc_json_parse_field */ ++ if (*src == '-') { ++ negative = 1; ++ ++src; ++ } else if (*src == '+') { ++ ++src; ++ } else if (*src < '0' || *src > '9') { ++ *out = 0; ++ return 0; ++ } ++ ++ while (src < field->value_end && *src != '.') { ++ value *= 10; ++ value += *src - '0'; ++ ++src; ++ } ++ ++ if (negative) ++ *out = -value; ++ else ++ *out = value; ++ ++ return 1; ++} ++ ++void rc_json_get_optional_num(int32_t* out, const rc_json_field_t* field, const char* field_name, int default_value) { ++ if (!rc_json_get_num(out, field, field_name)) ++ *out = default_value; ++} ++ ++int rc_json_get_required_num(int32_t* out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name) { ++ if (rc_json_get_num(out, field, field_name)) ++ return 1; ++ ++ return rc_json_missing_field(response, field); ++} ++ ++int rc_json_get_unum(uint32_t* out, const rc_json_field_t* field, const char* field_name) { ++ const char* src = field->value_start; ++ uint32_t value = 0; ++ ++#ifndef NDEBUG ++ if (strcmp(field->name, field_name) != 0) ++ return 0; ++#else ++ (void)field_name; ++#endif ++ ++ if (!src) { ++ *out = 0; ++ return 0; ++ } ++ ++ if (*src < '0' || *src > '9') { ++ *out = 0; ++ return 0; ++ } ++ ++ /* assert: string contains only numerals per rc_json_parse_field */ ++ while (src < field->value_end && *src != '.') { ++ value *= 10; ++ value += *src - '0'; ++ ++src; ++ } ++ ++ *out = value; ++ return 1; ++} ++ ++void rc_json_get_optional_unum(uint32_t* out, const rc_json_field_t* field, const char* field_name, uint32_t default_value) { ++ if (!rc_json_get_unum(out, field, field_name)) ++ *out = default_value; ++} ++ ++int rc_json_get_required_unum(uint32_t* out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name) { ++ if (rc_json_get_unum(out, field, field_name)) ++ return 1; ++ ++ return rc_json_missing_field(response, field); ++} ++ ++int rc_json_get_float(float* out, const rc_json_field_t* field, const char* field_name) { ++ int32_t whole, fraction, fraction_denominator; ++ const char* decimal = field->value_start; ++ ++ if (!decimal) { ++ *out = 0.0f; ++ return 0; ++ } ++ ++ if (!rc_json_get_num(&whole, field, field_name)) ++ return 0; ++ ++ while (decimal < field->value_end && *decimal != '.') ++ ++decimal; ++ ++ fraction = 0; ++ fraction_denominator = 1; ++ if (decimal) { ++ ++decimal; ++ while (decimal < field->value_end && *decimal >= '0' && *decimal <= '9') { ++ fraction *= 10; ++ fraction += *decimal - '0'; ++ fraction_denominator *= 10; ++ ++decimal; ++ } ++ } ++ ++ if (whole < 0) ++ fraction = -fraction; ++ ++ *out = (float)whole + ((float)fraction / (float)fraction_denominator); ++ return 1; ++} ++ ++void rc_json_get_optional_float(float* out, const rc_json_field_t* field, const char* field_name, float default_value) { ++ if (!rc_json_get_float(out, field, field_name)) ++ *out = default_value; ++} ++ ++int rc_json_get_required_float(float* out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name) { ++ if (rc_json_get_float(out, field, field_name)) ++ return 1; ++ ++ return rc_json_missing_field(response, field); ++} ++ ++int rc_json_get_datetime(time_t* out, const rc_json_field_t* field, const char* field_name) { ++ struct tm tm; ++ ++#ifndef NDEBUG ++ if (strcmp(field->name, field_name) != 0) ++ return 0; ++#else ++ (void)field_name; ++#endif ++ ++ if (*field->value_start == '\"') { ++ memset(&tm, 0, sizeof(tm)); ++ if (sscanf_s(field->value_start + 1, "%d-%d-%d %d:%d:%d", /* DB format "2013-10-20 22:12:21" */ ++ &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) == 6 || ++ /* NOTE: relies on sscanf stopping when it sees a non-digit after the seconds. could be 'Z', '.', '+', or '-' */ ++ sscanf_s(field->value_start + 1, "%d-%d-%dT%d:%d:%d", /* ISO format "2013-10-20T22:12:21.000000Z */ ++ &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) == 6) { ++ tm.tm_mon--; /* 0-based */ ++ tm.tm_year -= 1900; /* 1900 based */ ++ ++ /* mktime converts a struct tm to a time_t using the local timezone. ++ * the input string is UTC. since timegm is not universally cross-platform, ++ * figure out the offset between UTC and local time by applying the ++ * timezone conversion twice and manually removing the difference */ ++ { ++ time_t local_timet = mktime(&tm); ++ time_t skewed_timet, tz_offset; ++ struct tm gmt_tm; ++ gmtime_s(&gmt_tm, &local_timet); ++ skewed_timet = mktime(&gmt_tm); /* applies local time adjustment second time */ ++ tz_offset = skewed_timet - local_timet; ++ *out = local_timet - tz_offset; ++ } ++ ++ return 1; ++ } ++ } ++ ++ *out = 0; ++ return 0; ++} ++ ++int rc_json_get_required_datetime(time_t* out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name) { ++ if (rc_json_get_datetime(out, field, field_name)) ++ return 1; ++ ++ return rc_json_missing_field(response, field); ++} ++ ++int rc_json_get_bool(int* out, const rc_json_field_t* field, const char* field_name) { ++ const char* src = field->value_start; ++ ++#ifndef NDEBUG ++ if (strcmp(field->name, field_name) != 0) ++ return 0; ++#else ++ (void)field_name; ++#endif ++ ++ if (src) { ++ const size_t len = field->value_end - field->value_start; ++ if (len == 4 && strncasecmp(src, "true", 4) == 0) { ++ *out = 1; ++ return 1; ++ } else if (len == 5 && strncasecmp(src, "false", 5) == 0) { ++ *out = 0; ++ return 1; ++ } else if (len == 1) { ++ *out = (*src != '0'); ++ return 1; ++ } ++ } ++ ++ *out = 0; ++ return 0; ++} ++ ++void rc_json_get_optional_bool(int* out, const rc_json_field_t* field, const char* field_name, int default_value) { ++ if (!rc_json_get_bool(out, field, field_name)) ++ *out = default_value; ++} ++ ++int rc_json_get_required_bool(int* out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name) { ++ if (rc_json_get_bool(out, field, field_name)) ++ return 1; ++ ++ return rc_json_missing_field(response, field); ++} ++ ++void rc_json_extract_filename(rc_json_field_t* field) { ++ if (field->value_end) { ++ const char* str = field->value_end; ++ ++ /* remove the extension */ ++ while (str > field->value_start && str[-1] != '/') { ++ --str; ++ if (*str == '.') { ++ field->value_end = str; ++ break; ++ } ++ } ++ ++ /* find the path separator */ ++ while (str > field->value_start && str[-1] != '/') ++ --str; ++ ++ field->value_start = str; ++ } ++} ++ ++/* --- rc_api_request --- */ ++ ++void rc_api_destroy_request(rc_api_request_t* request) ++{ ++ rc_buffer_destroy(&request->buffer); ++} ++ ++/* --- rc_url_builder --- */ ++ ++void rc_url_builder_init(rc_api_url_builder_t* builder, rc_buffer_t* buffer, size_t estimated_size) { ++ rc_buffer_chunk_t* used_buffer; ++ ++ memset(builder, 0, sizeof(*builder)); ++ builder->buffer = buffer; ++ builder->write = builder->start = (char*)rc_buffer_reserve(buffer, estimated_size); ++ ++ used_buffer = &buffer->chunk; ++ while (used_buffer && used_buffer->write != (uint8_t*)builder->write) ++ used_buffer = used_buffer->next; ++ ++ builder->end = (used_buffer) ? (char*)used_buffer->end : builder->start + estimated_size; ++} ++ ++const char* rc_url_builder_finalize(rc_api_url_builder_t* builder) { ++ rc_url_builder_append(builder, "", 1); ++ ++ if (builder->result != RC_OK) ++ return NULL; ++ ++ rc_buffer_consume(builder->buffer, (uint8_t*)builder->start, (uint8_t*)builder->write); ++ return builder->start; ++} ++ ++static int rc_url_builder_reserve(rc_api_url_builder_t* builder, size_t amount) { ++ if (builder->result == RC_OK) { ++ size_t remaining = builder->end - builder->write; ++ if (remaining < amount) { ++ const size_t used = builder->write - builder->start; ++ const size_t current_size = builder->end - builder->start; ++ const size_t buffer_prefix_size = sizeof(rc_buffer_chunk_t); ++ char* new_start; ++ size_t new_size = (current_size < 256) ? 256 : current_size * 2; ++ do { ++ remaining = new_size - used; ++ if (remaining >= amount) ++ break; ++ ++ new_size *= 2; ++ } while (1); ++ ++ /* rc_buffer_reserve will align to 256 bytes after including the buffer prefix. attempt to account for that */ ++ if ((remaining - amount) > buffer_prefix_size) ++ new_size -= buffer_prefix_size; ++ ++ new_start = (char*)rc_buffer_reserve(builder->buffer, new_size); ++ if (!new_start) { ++ builder->result = RC_OUT_OF_MEMORY; ++ return RC_OUT_OF_MEMORY; ++ } ++ ++ if (new_start != builder->start) { ++ memcpy(new_start, builder->start, used); ++ builder->start = new_start; ++ builder->write = new_start + used; ++ } ++ ++ builder->end = builder->start + new_size; ++ } ++ } ++ ++ return builder->result; ++} ++ ++void rc_url_builder_append_encoded_str(rc_api_url_builder_t* builder, const char* str) { ++ static const char hex[] = "0123456789abcdef"; ++ const char* start = str; ++ size_t len = 0; ++ for (;;) { ++ const char c = *str++; ++ switch (c) { ++ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': ++ case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': ++ case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': ++ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': ++ case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': ++ case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': ++ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': ++ case '-': case '_': case '.': case '~': ++ len++; ++ continue; ++ ++ case '\0': ++ if (len) ++ rc_url_builder_append(builder, start, len); ++ ++ return; ++ ++ default: ++ if (rc_url_builder_reserve(builder, len + 3) != RC_OK) ++ return; ++ ++ if (len) { ++ memcpy(builder->write, start, len); ++ builder->write += len; ++ } ++ ++ if (c == ' ') { ++ *builder->write++ = '+'; ++ } else { ++ *builder->write++ = '%'; ++ *builder->write++ = hex[((unsigned char)c) >> 4]; ++ *builder->write++ = hex[c & 0x0F]; ++ } ++ break; ++ } ++ ++ start = str; ++ len = 0; ++ } ++} ++ ++void rc_url_builder_append(rc_api_url_builder_t* builder, const char* data, size_t len) { ++ if (rc_url_builder_reserve(builder, len) == RC_OK) { ++ memcpy(builder->write, data, len); ++ builder->write += len; ++ } ++} ++ ++static int rc_url_builder_append_param_equals(rc_api_url_builder_t* builder, const char* param) { ++ size_t param_len = strlen(param); ++ ++ if (rc_url_builder_reserve(builder, param_len + 2) == RC_OK) { ++ if (builder->write > builder->start) { ++ if (builder->write[-1] != '?') ++ *builder->write++ = '&'; ++ } ++ ++ memcpy(builder->write, param, param_len); ++ builder->write += param_len; ++ *builder->write++ = '='; ++ } ++ ++ return builder->result; ++} ++ ++void rc_url_builder_append_unum_param(rc_api_url_builder_t* builder, const char* param, uint32_t value) { ++ if (rc_url_builder_append_param_equals(builder, param) == RC_OK) { ++ char num[16]; ++ int chars = snprintf(num, sizeof(num), "%u", value); ++ rc_url_builder_append(builder, num, chars); ++ } ++} ++ ++void rc_url_builder_append_num_param(rc_api_url_builder_t* builder, const char* param, int32_t value) { ++ if (rc_url_builder_append_param_equals(builder, param) == RC_OK) { ++ char num[16]; ++ int chars = snprintf(num, sizeof(num), "%d", value); ++ rc_url_builder_append(builder, num, chars); ++ } ++} ++ ++void rc_url_builder_append_str_param(rc_api_url_builder_t* builder, const char* param, const char* value) { ++ rc_url_builder_append_param_equals(builder, param); ++ rc_url_builder_append_encoded_str(builder, value); ++} ++ ++void rc_api_url_build_dorequest_url(rc_api_request_t* request, const rc_api_host_t* host) { ++ #define DOREQUEST_ENDPOINT "/dorequest.php" ++ rc_buffer_init(&request->buffer); ++ ++ if (!host || !host->host) { ++ request->url = RETROACHIEVEMENTS_HOST DOREQUEST_ENDPOINT; ++ } ++ else { ++ const size_t endpoint_len = sizeof(DOREQUEST_ENDPOINT); ++ const size_t host_len = strlen(host->host); ++ const size_t protocol_len = (strstr(host->host, "://")) ? 0 : 7; ++ const size_t url_len = protocol_len + host_len + endpoint_len; ++ uint8_t* url = rc_buffer_reserve(&request->buffer, url_len); ++ ++ if (protocol_len) ++ memcpy(url, "http://", protocol_len); ++ ++ memcpy(url + protocol_len, host->host, host_len); ++ memcpy(url + protocol_len + host_len, DOREQUEST_ENDPOINT, endpoint_len); ++ rc_buffer_consume(&request->buffer, url, url + url_len); ++ ++ request->url = (char*)url; ++ } ++ #undef DOREQUEST_ENDPOINT ++} ++ ++int rc_api_url_build_dorequest(rc_api_url_builder_t* builder, const char* api, const char* username, const char* api_token) { ++ if (!username || !*username || !api_token || !*api_token) { ++ builder->result = RC_INVALID_STATE; ++ return 0; ++ } ++ ++ rc_url_builder_append_str_param(builder, "r", api); ++ rc_url_builder_append_str_param(builder, "u", username); ++ rc_url_builder_append_str_param(builder, "t", api_token); ++ ++ return (builder->result == RC_OK); ++} ++ ++/* --- Set Host --- */ ++ ++static void rc_api_update_host(const char** host, const char* hostname) { ++ if (*host != NULL) ++ free((void*)*host); ++ ++ if (hostname != NULL) { ++ if (strstr(hostname, "://")) { ++ *host = strdup(hostname); ++ } ++ else { ++ const size_t hostname_len = strlen(hostname); ++ if (hostname_len == 0) { ++ *host = NULL; ++ } ++ else { ++ char* newhost = (char*)malloc(hostname_len + 7 + 1); ++ if (newhost) { ++ memcpy(newhost, "http://", 7); ++ memcpy(&newhost[7], hostname, hostname_len + 1); ++ *host = newhost; ++ } ++ else { ++ *host = NULL; ++ } ++ } ++ } ++ } ++ else { ++ *host = NULL; ++ } ++} ++ ++const char* rc_api_default_host(void) { ++ return RETROACHIEVEMENTS_HOST; ++} ++ ++void rc_api_set_host(const char* hostname) { ++ if (hostname && strcmp(hostname, RETROACHIEVEMENTS_HOST) == 0) ++ hostname = NULL; ++ ++ rc_api_update_host(&g_host.host, hostname); ++ ++ if (!hostname) { ++ /* also clear out the image hostname */ ++ rc_api_set_image_host(NULL); ++ } ++ else if (strcmp(hostname, RETROACHIEVEMENTS_HOST_NONSSL) == 0) { ++ /* if just pointing at the non-HTTPS host, explicitly use the default image host ++ * so it doesn't try to use the web host directly */ ++ rc_api_set_image_host(RETROACHIEVEMENTS_IMAGE_HOST_NONSSL); ++ } ++} ++ ++void rc_api_set_image_host(const char* hostname) { ++ rc_api_update_host(&g_host.media_host, hostname); ++} ++ ++/* --- Fetch Image --- */ ++ ++int rc_api_init_fetch_image_request(rc_api_request_t* request, const rc_api_fetch_image_request_t* api_params) { ++ return rc_api_init_fetch_image_request_hosted(request, api_params, &g_host); ++} ++ ++int rc_api_init_fetch_image_request_hosted(rc_api_request_t* request, const rc_api_fetch_image_request_t* api_params, const rc_api_host_t* host) { ++ rc_api_url_builder_t builder; ++ ++ rc_buffer_init(&request->buffer); ++ rc_url_builder_init(&builder, &request->buffer, 64); ++ ++ if (host && host->media_host) { ++ /* custom media host provided */ ++ if (!strstr(host->host, "://")) ++ rc_url_builder_append(&builder, "http://", 7); ++ rc_url_builder_append(&builder, host->media_host, strlen(host->media_host)); ++ } ++ else if (host && host->host) { ++ if (strcmp(host->host, RETROACHIEVEMENTS_HOST_NONSSL) == 0) { ++ /* if host specifically set to non-ssl host, and no media host provided, use non-ssl media host */ ++ rc_url_builder_append(&builder, RETROACHIEVEMENTS_IMAGE_HOST_NONSSL, sizeof(RETROACHIEVEMENTS_IMAGE_HOST_NONSSL) - 1); ++ } ++ else if (strcmp(host->host, RETROACHIEVEMENTS_HOST) == 0) { ++ /* if host specifically set to ssl host, and no media host provided, use media host */ ++ rc_url_builder_append(&builder, RETROACHIEVEMENTS_IMAGE_HOST, sizeof(RETROACHIEVEMENTS_IMAGE_HOST) - 1); ++ } ++ else { ++ /* custom host and no media host provided. assume custom host is also media host */ ++ if (!strstr(host->host, "://")) ++ rc_url_builder_append(&builder, "http://", 7); ++ rc_url_builder_append(&builder, host->host, strlen(host->host)); ++ } ++ } ++ else { ++ /* no custom host provided */ ++ rc_url_builder_append(&builder, RETROACHIEVEMENTS_IMAGE_HOST, sizeof(RETROACHIEVEMENTS_IMAGE_HOST) - 1); ++ } ++ ++ switch (api_params->image_type) ++ { ++ case RC_IMAGE_TYPE_GAME: ++ rc_url_builder_append(&builder, "/Images/", 8); ++ rc_url_builder_append(&builder, api_params->image_name, strlen(api_params->image_name)); ++ rc_url_builder_append(&builder, ".png", 4); ++ break; ++ ++ case RC_IMAGE_TYPE_ACHIEVEMENT: ++ rc_url_builder_append(&builder, "/Badge/", 7); ++ rc_url_builder_append(&builder, api_params->image_name, strlen(api_params->image_name)); ++ rc_url_builder_append(&builder, ".png", 4); ++ break; ++ ++ case RC_IMAGE_TYPE_ACHIEVEMENT_LOCKED: ++ rc_url_builder_append(&builder, "/Badge/", 7); ++ rc_url_builder_append(&builder, api_params->image_name, strlen(api_params->image_name)); ++ rc_url_builder_append(&builder, "_lock.png", 9); ++ break; ++ ++ case RC_IMAGE_TYPE_USER: ++ rc_url_builder_append(&builder, "/UserPic/", 9); ++ rc_url_builder_append(&builder, api_params->image_name, strlen(api_params->image_name)); ++ rc_url_builder_append(&builder, ".png", 4); ++ break; ++ ++ default: ++ return RC_INVALID_STATE; ++ } ++ ++ request->url = rc_url_builder_finalize(&builder); ++ request->post_data = NULL; ++ ++ return builder.result; ++} ++ ++const char* rc_api_build_avatar_url(rc_buffer_t* buffer, uint32_t image_type, const char* image_name) { ++ rc_api_fetch_image_request_t image_request; ++ rc_api_request_t request; ++ int result; ++ ++ memset(&image_request, 0, sizeof(image_request)); ++ image_request.image_type = image_type; ++ image_request.image_name = image_name; ++ ++ result = rc_api_init_fetch_image_request(&request, &image_request); ++ if (result == RC_OK) ++ return rc_buffer_strcpy(buffer, request.url); ++ ++ return NULL; ++} +diff -rupbN melonDS.orig/src/rcheevos/src/rapi/rc_api_common.h melonDS.ra/src/rcheevos/src/rapi/rc_api_common.h +--- melonDS.orig/src/rcheevos/src/rapi/rc_api_common.h 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rapi/rc_api_common.h 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,88 @@ ++#ifndef RC_API_COMMON_H ++#define RC_API_COMMON_H ++ ++#include "rc_api_request.h" ++ ++#include ++#include ++ ++RC_BEGIN_C_DECLS ++ ++#define RC_CONTENT_TYPE_URLENCODED "application/x-www-form-urlencoded" ++ ++typedef struct rc_api_url_builder_t { ++ char* write; ++ char* start; ++ char* end; ++ /* pointer to a preallocated rc_buffer_t */ ++ rc_buffer_t* buffer; ++ int result; ++} ++rc_api_url_builder_t; ++ ++void rc_url_builder_init(rc_api_url_builder_t* builder, rc_buffer_t* buffer, size_t estimated_size); ++void rc_url_builder_append(rc_api_url_builder_t* builder, const char* data, size_t len); ++const char* rc_url_builder_finalize(rc_api_url_builder_t* builder); ++ ++extern rc_api_host_t g_host; ++ ++#define RC_JSON_NEW_FIELD(n) {NULL,NULL,n,sizeof(n)-1,0} ++ ++typedef struct rc_json_field_t { ++ const char* value_start; ++ const char* value_end; ++ const char* name; ++ size_t name_len; ++ uint32_t array_size; ++} ++rc_json_field_t; ++ ++typedef struct rc_json_iterator_t { ++ const char* json; ++ const char* end; ++} ++rc_json_iterator_t; ++ ++int rc_json_parse_server_response(rc_api_response_t* response, const rc_api_server_response_t* server_response, rc_json_field_t* fields, size_t field_count); ++int rc_json_get_string(const char** out, rc_buffer_t* buffer, const rc_json_field_t* field, const char* field_name); ++int rc_json_get_num(int32_t* out, const rc_json_field_t* field, const char* field_name); ++int rc_json_get_unum(uint32_t* out, const rc_json_field_t* field, const char* field_name); ++int rc_json_get_float(float* out, const rc_json_field_t* field, const char* field_name); ++int rc_json_get_bool(int* out, const rc_json_field_t* field, const char* field_name); ++int rc_json_get_datetime(time_t* out, const rc_json_field_t* field, const char* field_name); ++void rc_json_get_optional_string(const char** out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name, const char* default_value); ++void rc_json_get_optional_num(int32_t* out, const rc_json_field_t* field, const char* field_name, int default_value); ++void rc_json_get_optional_unum(uint32_t* out, const rc_json_field_t* field, const char* field_name, uint32_t default_value); ++void rc_json_get_optional_float(float* out, const rc_json_field_t* field, const char* field_name, float default_value); ++void rc_json_get_optional_bool(int* out, const rc_json_field_t* field, const char* field_name, int default_value); ++int rc_json_get_optional_array(uint32_t* num_entries, rc_json_field_t* iterator, const rc_json_field_t* field, const char* field_name); ++int rc_json_get_required_string(const char** out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name); ++int rc_json_get_required_num(int32_t* out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name); ++int rc_json_get_required_unum(uint32_t* out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name); ++int rc_json_get_required_float(float* out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name); ++int rc_json_get_required_bool(int* out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name); ++int rc_json_get_required_datetime(time_t* out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name); ++int rc_json_get_required_object(rc_json_field_t* fields, size_t field_count, rc_api_response_t* response, rc_json_field_t* field, const char* field_name); ++int rc_json_get_required_unum_array(uint32_t** entries, uint32_t* num_entries, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name); ++int rc_json_get_required_array(uint32_t* num_entries, rc_json_field_t* array_field, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name); ++int rc_json_get_array_entry_object(rc_json_field_t* fields, size_t field_count, rc_json_iterator_t* iterator); ++int rc_json_get_next_object_field(rc_json_iterator_t* iterator, rc_json_field_t* field); ++int rc_json_get_object_string_length(const char* json); ++int rc_json_field_string_matches(const rc_json_field_t* field, const char* text); ++ ++void rc_json_extract_filename(rc_json_field_t* field); ++ ++void rc_url_builder_append_encoded_str(rc_api_url_builder_t* builder, const char* str); ++void rc_url_builder_append_num_param(rc_api_url_builder_t* builder, const char* param, int32_t value); ++void rc_url_builder_append_unum_param(rc_api_url_builder_t* builder, const char* param, uint32_t value); ++void rc_url_builder_append_str_param(rc_api_url_builder_t* builder, const char* param, const char* value); ++ ++const char* rc_api_default_host(void); ++void rc_api_url_build_dorequest_url(rc_api_request_t* request, const rc_api_host_t* host); ++int rc_api_url_build_dorequest(rc_api_url_builder_t* builder, const char* api, const char* username, const char* api_token); ++ ++const char* rc_api_build_avatar_url(rc_buffer_t* buffer, uint32_t image_type, const char* image_name); ++ ++RC_END_C_DECLS ++ ++#endif /* RC_API_COMMON_H */ +diff -rupbN melonDS.orig/src/rcheevos/src/rapi/rc_api_editor.c melonDS.ra/src/rcheevos/src/rapi/rc_api_editor.c +--- melonDS.orig/src/rcheevos/src/rapi/rc_api_editor.c 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rapi/rc_api_editor.c 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,625 @@ ++#include "rc_api_editor.h" ++#include "rc_api_common.h" ++#include "rc_api_runtime.h" ++ ++#include "../rc_compat.h" ++#include "../rhash/md5.h" ++ ++#include ++#include ++ ++/* --- Fetch Code Notes --- */ ++ ++int rc_api_init_fetch_code_notes_request(rc_api_request_t* request, const rc_api_fetch_code_notes_request_t* api_params) { ++ return rc_api_init_fetch_code_notes_request_hosted(request, api_params, &g_host); ++} ++ ++int rc_api_init_fetch_code_notes_request_hosted(rc_api_request_t* request, ++ const rc_api_fetch_code_notes_request_t* api_params, ++ const rc_api_host_t* host) { ++ rc_api_url_builder_t builder; ++ ++ rc_api_url_build_dorequest_url(request, host); ++ ++ if (api_params->game_id == 0) ++ return RC_INVALID_STATE; ++ ++ rc_url_builder_init(&builder, &request->buffer, 48); ++ rc_url_builder_append_str_param(&builder, "r", "codenotes2"); ++ rc_url_builder_append_unum_param(&builder, "g", api_params->game_id); ++ ++ request->post_data = rc_url_builder_finalize(&builder); ++ request->content_type = RC_CONTENT_TYPE_URLENCODED; ++ ++ return builder.result; ++} ++ ++int rc_api_process_fetch_code_notes_response(rc_api_fetch_code_notes_response_t* response, const char* server_response) { ++ rc_api_server_response_t response_obj; ++ ++ memset(&response_obj, 0, sizeof(response_obj)); ++ response_obj.body = server_response; ++ response_obj.body_length = rc_json_get_object_string_length(server_response); ++ ++ return rc_api_process_fetch_code_notes_server_response(response, &response_obj); ++} ++ ++int rc_api_process_fetch_code_notes_server_response(rc_api_fetch_code_notes_response_t* response, const rc_api_server_response_t* server_response) { ++ rc_json_field_t array_field; ++ rc_json_iterator_t iterator; ++ rc_api_code_note_t* note; ++ const char* address_str; ++ const char* last_author = ""; ++ size_t last_author_len = 0; ++ size_t len; ++ int result; ++ ++ rc_json_field_t fields[] = { ++ RC_JSON_NEW_FIELD("Success"), ++ RC_JSON_NEW_FIELD("Error"), ++ RC_JSON_NEW_FIELD("CodeNotes") ++ }; ++ ++ rc_json_field_t note_fields[] = { ++ RC_JSON_NEW_FIELD("Address"), ++ RC_JSON_NEW_FIELD("User"), ++ RC_JSON_NEW_FIELD("Note") ++ }; ++ ++ memset(response, 0, sizeof(*response)); ++ rc_buffer_init(&response->response.buffer); ++ ++ result = rc_json_parse_server_response(&response->response, server_response, fields, sizeof(fields) / sizeof(fields[0])); ++ if (result != RC_OK || !response->response.succeeded) ++ return result; ++ ++ if (!rc_json_get_required_array(&response->num_notes, &array_field, &response->response, &fields[2], "CodeNotes")) ++ return RC_MISSING_VALUE; ++ ++ if (response->num_notes) { ++ response->notes = (rc_api_code_note_t*)rc_buffer_alloc(&response->response.buffer, response->num_notes * sizeof(rc_api_code_note_t)); ++ if (!response->notes) ++ return RC_OUT_OF_MEMORY; ++ ++ memset(&iterator, 0, sizeof(iterator)); ++ iterator.json = array_field.value_start; ++ iterator.end = array_field.value_end; ++ ++ note = response->notes; ++ while (rc_json_get_array_entry_object(note_fields, sizeof(note_fields) / sizeof(note_fields[0]), &iterator)) { ++ /* an empty note represents a record that was deleted on the server */ ++ /* a note set to '' also represents a deleted note (remnant of a bug) */ ++ /* NOTE: len will include the quotes */ ++ if (note_fields[2].value_start) { ++ len = note_fields[2].value_end - note_fields[2].value_start; ++ if (len == 2 || (len == 4 && note_fields[2].value_start[1] == '\'' && note_fields[2].value_start[2] == '\'')) { ++ --response->num_notes; ++ continue; ++ } ++ } ++ ++ if (!rc_json_get_required_string(&address_str, &response->response, ¬e_fields[0], "Address")) ++ return RC_MISSING_VALUE; ++ note->address = (uint32_t)strtoul(address_str, NULL, 16); ++ if (!rc_json_get_required_string(¬e->note, &response->response, ¬e_fields[2], "Note")) ++ return RC_MISSING_VALUE; ++ ++ len = note_fields[1].value_end - note_fields[1].value_start; ++ if (len == last_author_len && memcmp(note_fields[1].value_start, last_author, len) == 0) { ++ note->author = last_author; ++ } ++ else { ++ if (!rc_json_get_required_string(¬e->author, &response->response, ¬e_fields[1], "User")) ++ return RC_MISSING_VALUE; ++ ++ if (note->author == NULL) { ++ /* ensure we don't pass NULL out to client */ ++ last_author = note->author = ""; ++ last_author_len = 0; ++ } else { ++ last_author = note->author; ++ last_author_len = len; ++ } ++ } ++ ++ ++note; ++ } ++ } ++ ++ return RC_OK; ++} ++ ++void rc_api_destroy_fetch_code_notes_response(rc_api_fetch_code_notes_response_t* response) { ++ rc_buffer_destroy(&response->response.buffer); ++} ++ ++/* --- Update Code Note --- */ ++ ++int rc_api_init_update_code_note_request(rc_api_request_t* request, const rc_api_update_code_note_request_t* api_params) { ++ return rc_api_init_update_code_note_request_hosted(request, api_params, &g_host); ++} ++ ++int rc_api_init_update_code_note_request_hosted(rc_api_request_t* request, ++ const rc_api_update_code_note_request_t* api_params, ++ const rc_api_host_t* host) { ++ rc_api_url_builder_t builder; ++ ++ rc_api_url_build_dorequest_url(request, host); ++ ++ if (api_params->game_id == 0) ++ return RC_INVALID_STATE; ++ ++ rc_url_builder_init(&builder, &request->buffer, 128); ++ if (!rc_api_url_build_dorequest(&builder, "submitcodenote", api_params->username, api_params->api_token)) ++ return builder.result; ++ ++ rc_url_builder_append_unum_param(&builder, "g", api_params->game_id); ++ rc_url_builder_append_unum_param(&builder, "m", api_params->address); ++ ++ if (api_params->note && *api_params->note) ++ rc_url_builder_append_str_param(&builder, "n", api_params->note); ++ ++ request->post_data = rc_url_builder_finalize(&builder); ++ request->content_type = RC_CONTENT_TYPE_URLENCODED; ++ ++ return builder.result; ++} ++ ++int rc_api_process_update_code_note_response(rc_api_update_code_note_response_t* response, const char* server_response) { ++ rc_api_server_response_t response_obj; ++ ++ memset(&response_obj, 0, sizeof(response_obj)); ++ response_obj.body = server_response; ++ response_obj.body_length = rc_json_get_object_string_length(server_response); ++ ++ return rc_api_process_update_code_note_server_response(response, &response_obj); ++} ++ ++int rc_api_process_update_code_note_server_response(rc_api_update_code_note_response_t* response, const rc_api_server_response_t* server_response) { ++ int result; ++ ++ rc_json_field_t fields[] = { ++ RC_JSON_NEW_FIELD("Success"), ++ RC_JSON_NEW_FIELD("Error") ++ /* unused fields ++ RC_JSON_NEW_FIELD("GameID"), ++ RC_JSON_NEW_FIELD("Address"), ++ RC_JSON_NEW_FIELD("Note") ++ */ ++ }; ++ ++ memset(response, 0, sizeof(*response)); ++ rc_buffer_init(&response->response.buffer); ++ ++ result = rc_json_parse_server_response(&response->response, server_response, fields, sizeof(fields) / sizeof(fields[0])); ++ if (result != RC_OK || !response->response.succeeded) ++ return result; ++ ++ return RC_OK; ++} ++ ++void rc_api_destroy_update_code_note_response(rc_api_update_code_note_response_t* response) { ++ rc_buffer_destroy(&response->response.buffer); ++} ++ ++/* --- Update Achievement --- */ ++ ++static const char* rc_type_string(uint32_t type) { ++ switch (type) { ++ case RC_ACHIEVEMENT_TYPE_MISSABLE: return "missable"; ++ case RC_ACHIEVEMENT_TYPE_PROGRESSION: return "progression"; ++ case RC_ACHIEVEMENT_TYPE_WIN: return "win_condition"; ++ default: return ""; ++ } ++} ++ ++int rc_api_init_update_achievement_request(rc_api_request_t* request, const rc_api_update_achievement_request_t* api_params) { ++ return rc_api_init_update_achievement_request_hosted(request, api_params, &g_host); ++} ++ ++int rc_api_init_update_achievement_request_hosted(rc_api_request_t* request, ++ const rc_api_update_achievement_request_t* api_params, ++ const rc_api_host_t* host) { ++ rc_api_url_builder_t builder; ++ char buffer[33]; ++ md5_state_t md5; ++ md5_byte_t hash[16]; ++ ++ rc_api_url_build_dorequest_url(request, host); ++ ++ if (api_params->game_id == 0 || api_params->category == 0) ++ return RC_INVALID_STATE; ++ if (!api_params->title || !*api_params->title) ++ return RC_INVALID_STATE; ++ if (!api_params->description || !*api_params->description) ++ return RC_INVALID_STATE; ++ if (!api_params->trigger || !*api_params->trigger) ++ return RC_INVALID_STATE; ++ ++ rc_url_builder_init(&builder, &request->buffer, 128); ++ if (!rc_api_url_build_dorequest(&builder, "uploadachievement", api_params->username, api_params->api_token)) ++ return builder.result; ++ ++ if (api_params->achievement_id) ++ rc_url_builder_append_unum_param(&builder, "a", api_params->achievement_id); ++ rc_url_builder_append_unum_param(&builder, "g", api_params->game_id); ++ rc_url_builder_append_str_param(&builder, "n", api_params->title); ++ rc_url_builder_append_str_param(&builder, "d", api_params->description); ++ rc_url_builder_append_str_param(&builder, "m", api_params->trigger); ++ rc_url_builder_append_unum_param(&builder, "z", api_params->points); ++ rc_url_builder_append_unum_param(&builder, "f", api_params->category); ++ if (api_params->badge) ++ rc_url_builder_append_str_param(&builder, "b", api_params->badge); ++ rc_url_builder_append_str_param(&builder, "x", rc_type_string(api_params->type)); ++ ++ /* Evaluate the signature. */ ++ md5_init(&md5); ++ md5_append(&md5, (md5_byte_t*)api_params->username, (int)strlen(api_params->username)); ++ md5_append(&md5, (md5_byte_t*)"SECRET", 6); ++ snprintf(buffer, sizeof(buffer), "%u", api_params->achievement_id); ++ md5_append(&md5, (md5_byte_t*)buffer, (int)strlen(buffer)); ++ md5_append(&md5, (md5_byte_t*)"SEC", 3); ++ md5_append(&md5, (md5_byte_t*)api_params->trigger, (int)strlen(api_params->trigger)); ++ snprintf(buffer, sizeof(buffer), "%u", api_params->points); ++ md5_append(&md5, (md5_byte_t*)buffer, (int)strlen(buffer)); ++ md5_append(&md5, (md5_byte_t*)"RE2", 3); ++ snprintf(buffer, sizeof(buffer), "%u", api_params->points * 3); ++ md5_append(&md5, (md5_byte_t*)buffer, (int)strlen(buffer)); ++ md5_finish(&md5, hash); ++ rc_format_md5(buffer, hash); ++ rc_url_builder_append_str_param(&builder, "h", buffer); ++ ++ request->post_data = rc_url_builder_finalize(&builder); ++ request->content_type = RC_CONTENT_TYPE_URLENCODED; ++ ++ return builder.result; ++} ++ ++int rc_api_process_update_achievement_response(rc_api_update_achievement_response_t* response, const char* server_response) { ++ rc_api_server_response_t response_obj; ++ ++ memset(&response_obj, 0, sizeof(response_obj)); ++ response_obj.body = server_response; ++ response_obj.body_length = rc_json_get_object_string_length(server_response); ++ ++ return rc_api_process_update_achievement_server_response(response, &response_obj); ++} ++ ++int rc_api_process_update_achievement_server_response(rc_api_update_achievement_response_t* response, const rc_api_server_response_t* server_response) { ++ int result; ++ ++ rc_json_field_t fields[] = { ++ RC_JSON_NEW_FIELD("Success"), ++ RC_JSON_NEW_FIELD("Error"), ++ RC_JSON_NEW_FIELD("AchievementID") ++ }; ++ ++ memset(response, 0, sizeof(*response)); ++ rc_buffer_init(&response->response.buffer); ++ ++ result = rc_json_parse_server_response(&response->response, server_response, fields, sizeof(fields) / sizeof(fields[0])); ++ if (result != RC_OK || !response->response.succeeded) ++ return result; ++ ++ if (!rc_json_get_required_unum(&response->achievement_id, &response->response, &fields[2], "AchievementID")) ++ return RC_MISSING_VALUE; ++ ++ return RC_OK; ++} ++ ++void rc_api_destroy_update_achievement_response(rc_api_update_achievement_response_t* response) { ++ rc_buffer_destroy(&response->response.buffer); ++} ++ ++/* --- Update Leaderboard --- */ ++ ++int rc_api_init_update_leaderboard_request(rc_api_request_t* request, const rc_api_update_leaderboard_request_t* api_params) { ++ return rc_api_init_update_leaderboard_request_hosted(request, api_params, &g_host); ++} ++ ++int rc_api_init_update_leaderboard_request_hosted(rc_api_request_t* request, ++ const rc_api_update_leaderboard_request_t* api_params, ++ const rc_api_host_t* host) { ++ rc_api_url_builder_t builder; ++ char buffer[33]; ++ md5_state_t md5; ++ md5_byte_t hash[16]; ++ ++ rc_api_url_build_dorequest_url(request, host); ++ ++ if (api_params->game_id == 0) ++ return RC_INVALID_STATE; ++ if (!api_params->title || !*api_params->title) ++ return RC_INVALID_STATE; ++ if (!api_params->description) ++ return RC_INVALID_STATE; ++ if (!api_params->start_trigger || !*api_params->start_trigger) ++ return RC_INVALID_STATE; ++ if (!api_params->submit_trigger || !*api_params->submit_trigger) ++ return RC_INVALID_STATE; ++ if (!api_params->cancel_trigger || !*api_params->cancel_trigger) ++ return RC_INVALID_STATE; ++ if (!api_params->value_definition || !*api_params->value_definition) ++ return RC_INVALID_STATE; ++ if (!api_params->format || !*api_params->format) ++ return RC_INVALID_STATE; ++ ++ rc_url_builder_init(&builder, &request->buffer, 128); ++ if (!rc_api_url_build_dorequest(&builder, "uploadleaderboard", api_params->username, api_params->api_token)) ++ return builder.result; ++ ++ if (api_params->leaderboard_id) ++ rc_url_builder_append_unum_param(&builder, "i", api_params->leaderboard_id); ++ rc_url_builder_append_unum_param(&builder, "g", api_params->game_id); ++ rc_url_builder_append_str_param(&builder, "n", api_params->title); ++ rc_url_builder_append_str_param(&builder, "d", api_params->description); ++ rc_url_builder_append_str_param(&builder, "s", api_params->start_trigger); ++ rc_url_builder_append_str_param(&builder, "b", api_params->submit_trigger); ++ rc_url_builder_append_str_param(&builder, "c", api_params->cancel_trigger); ++ rc_url_builder_append_str_param(&builder, "l", api_params->value_definition); ++ rc_url_builder_append_num_param(&builder, "w", api_params->lower_is_better); ++ rc_url_builder_append_str_param(&builder, "f", api_params->format); ++ ++ /* Evaluate the signature. */ ++ md5_init(&md5); ++ md5_append(&md5, (md5_byte_t*)api_params->username, (int)strlen(api_params->username)); ++ md5_append(&md5, (md5_byte_t*)"SECRET", 6); ++ snprintf(buffer, sizeof(buffer), "%u", api_params->leaderboard_id); ++ md5_append(&md5, (md5_byte_t*)buffer, (int)strlen(buffer)); ++ md5_append(&md5, (md5_byte_t*)"SEC", 3); ++ md5_append(&md5, (md5_byte_t*)api_params->start_trigger, (int)strlen(api_params->start_trigger)); ++ md5_append(&md5, (md5_byte_t*)api_params->submit_trigger, (int)strlen(api_params->submit_trigger)); ++ md5_append(&md5, (md5_byte_t*)api_params->cancel_trigger, (int)strlen(api_params->cancel_trigger)); ++ md5_append(&md5, (md5_byte_t*)api_params->value_definition, (int)strlen(api_params->value_definition)); ++ md5_append(&md5, (md5_byte_t*)"RE2", 3); ++ md5_append(&md5, (md5_byte_t*)api_params->format, (int)strlen(api_params->format)); ++ md5_finish(&md5, hash); ++ rc_format_md5(buffer, hash); ++ rc_url_builder_append_str_param(&builder, "h", buffer); ++ ++ request->post_data = rc_url_builder_finalize(&builder); ++ request->content_type = RC_CONTENT_TYPE_URLENCODED; ++ ++ return builder.result; ++} ++ ++int rc_api_process_update_leaderboard_response(rc_api_update_leaderboard_response_t* response, const char* server_response) { ++ rc_api_server_response_t response_obj; ++ ++ memset(&response_obj, 0, sizeof(response_obj)); ++ response_obj.body = server_response; ++ response_obj.body_length = rc_json_get_object_string_length(server_response); ++ ++ return rc_api_process_update_leaderboard_server_response(response, &response_obj); ++} ++ ++int rc_api_process_update_leaderboard_server_response(rc_api_update_leaderboard_response_t* response, const rc_api_server_response_t* server_response) { ++ int result; ++ ++ rc_json_field_t fields[] = { ++ RC_JSON_NEW_FIELD("Success"), ++ RC_JSON_NEW_FIELD("Error"), ++ RC_JSON_NEW_FIELD("LeaderboardID") ++ }; ++ ++ memset(response, 0, sizeof(*response)); ++ rc_buffer_init(&response->response.buffer); ++ ++ result = rc_json_parse_server_response(&response->response, server_response, fields, sizeof(fields) / sizeof(fields[0])); ++ if (result != RC_OK || !response->response.succeeded) ++ return result; ++ ++ if (!rc_json_get_required_unum(&response->leaderboard_id, &response->response, &fields[2], "LeaderboardID")) ++ return RC_MISSING_VALUE; ++ ++ return RC_OK; ++} ++ ++void rc_api_destroy_update_leaderboard_response(rc_api_update_leaderboard_response_t* response) { ++ rc_buffer_destroy(&response->response.buffer); ++} ++ ++/* --- Update Rich Presence --- */ ++ ++int rc_api_init_update_rich_presence_request(rc_api_request_t* request, const rc_api_update_rich_presence_request_t* api_params) { ++ return rc_api_init_update_rich_presence_request_hosted(request, api_params, &g_host); ++} ++ ++int rc_api_init_update_rich_presence_request_hosted(rc_api_request_t* request, ++ const rc_api_update_rich_presence_request_t* api_params, ++ const rc_api_host_t* host) { ++ rc_api_url_builder_t builder; ++ ++ rc_api_url_build_dorequest_url(request, host); ++ ++ if (api_params->game_id == 0) ++ return RC_INVALID_STATE; ++ if (!api_params->script) ++ return RC_INVALID_STATE; ++ ++ rc_url_builder_init(&builder, &request->buffer, 128); ++ if (!rc_api_url_build_dorequest(&builder, "submitrichpresence", api_params->username, api_params->api_token)) ++ return builder.result; ++ ++ rc_url_builder_append_unum_param(&builder, "g", api_params->game_id); ++ rc_url_builder_append_str_param(&builder, "d", api_params->script); ++ ++ request->post_data = rc_url_builder_finalize(&builder); ++ request->content_type = RC_CONTENT_TYPE_URLENCODED; ++ ++ return builder.result; ++} ++ ++int rc_api_process_update_rich_presence_server_response(rc_api_update_rich_presence_response_t* response, const rc_api_server_response_t* server_response) { ++ int result; ++ ++ rc_json_field_t fields[] = { ++ RC_JSON_NEW_FIELD("Success"), ++ RC_JSON_NEW_FIELD("Error"), ++ RC_JSON_NEW_FIELD("Code"), ++ }; ++ ++ memset(response, 0, sizeof(*response)); ++ rc_buffer_init(&response->response.buffer); ++ ++ result = rc_json_parse_server_response(&response->response, server_response, fields, sizeof(fields) / sizeof(fields[0])); ++ if (result != RC_OK || !response->response.succeeded) ++ return result; ++ ++ return RC_OK; ++} ++ ++void rc_api_destroy_update_rich_presence_response(rc_api_update_rich_presence_response_t* response) { ++ rc_buffer_destroy(&response->response.buffer); ++} ++ ++/* --- Fetch Badge Range --- */ ++ ++int rc_api_init_fetch_badge_range_request(rc_api_request_t* request, const rc_api_fetch_badge_range_request_t* api_params) { ++ return rc_api_init_fetch_badge_range_request_hosted(request, api_params, &g_host); ++} ++ ++int rc_api_init_fetch_badge_range_request_hosted(rc_api_request_t* request, ++ const rc_api_fetch_badge_range_request_t* api_params, ++ const rc_api_host_t* host) { ++ rc_api_url_builder_t builder; ++ ++ rc_api_url_build_dorequest_url(request, host); ++ ++ rc_url_builder_init(&builder, &request->buffer, 48); ++ rc_url_builder_append_str_param(&builder, "r", "badgeiter"); ++ ++ request->post_data = rc_url_builder_finalize(&builder); ++ request->content_type = RC_CONTENT_TYPE_URLENCODED; ++ ++ (void)api_params; ++ ++ return builder.result; ++} ++ ++int rc_api_process_fetch_badge_range_response(rc_api_fetch_badge_range_response_t* response, const char* server_response) { ++ rc_api_server_response_t response_obj; ++ ++ memset(&response_obj, 0, sizeof(response_obj)); ++ response_obj.body = server_response; ++ response_obj.body_length = rc_json_get_object_string_length(server_response); ++ ++ return rc_api_process_fetch_badge_range_server_response(response, &response_obj); ++} ++ ++int rc_api_process_fetch_badge_range_server_response(rc_api_fetch_badge_range_response_t* response, const rc_api_server_response_t* server_response) { ++ int result; ++ ++ rc_json_field_t fields[] = { ++ RC_JSON_NEW_FIELD("Success"), ++ RC_JSON_NEW_FIELD("Error"), ++ RC_JSON_NEW_FIELD("FirstBadge"), ++ RC_JSON_NEW_FIELD("NextBadge") ++ }; ++ ++ memset(response, 0, sizeof(*response)); ++ rc_buffer_init(&response->response.buffer); ++ ++ result = rc_json_parse_server_response(&response->response, server_response, fields, sizeof(fields) / sizeof(fields[0])); ++ if (result != RC_OK || !response->response.succeeded) ++ return result; ++ ++ if (!rc_json_get_required_unum(&response->first_badge_id, &response->response, &fields[2], "FirstBadge")) ++ return RC_MISSING_VALUE; ++ if (!rc_json_get_required_unum(&response->next_badge_id, &response->response, &fields[3], "NextBadge")) ++ return RC_MISSING_VALUE; ++ ++ return RC_OK; ++} ++ ++void rc_api_destroy_fetch_badge_range_response(rc_api_fetch_badge_range_response_t* response) { ++ rc_buffer_destroy(&response->response.buffer); ++} ++ ++/* --- Add Game Hash --- */ ++ ++int rc_api_init_add_game_hash_request(rc_api_request_t* request, const rc_api_add_game_hash_request_t* api_params) { ++ return rc_api_init_add_game_hash_request_hosted(request, api_params, &g_host); ++} ++ ++int rc_api_init_add_game_hash_request_hosted(rc_api_request_t* request, ++ const rc_api_add_game_hash_request_t* api_params, ++ const rc_api_host_t* host) { ++ rc_api_url_builder_t builder; ++ ++ rc_api_url_build_dorequest_url(request, host); ++ ++ if (api_params->console_id == 0) ++ return RC_INVALID_STATE; ++ if (!api_params->hash || !*api_params->hash) ++ return RC_INVALID_STATE; ++ if (api_params->game_id == 0 && (!api_params->title || !*api_params->title)) ++ return RC_INVALID_STATE; ++ ++ rc_url_builder_init(&builder, &request->buffer, 128); ++ if (!rc_api_url_build_dorequest(&builder, "submitgametitle", api_params->username, api_params->api_token)) ++ return builder.result; ++ ++ rc_url_builder_append_unum_param(&builder, "c", api_params->console_id); ++ rc_url_builder_append_str_param(&builder, "m", api_params->hash); ++ if (api_params->title) ++ rc_url_builder_append_str_param(&builder, "i", api_params->title); ++ if (api_params->game_id) ++ rc_url_builder_append_unum_param(&builder, "g", api_params->game_id); ++ if (api_params->hash_description && *api_params->hash_description) ++ rc_url_builder_append_str_param(&builder, "d", api_params->hash_description); ++ ++ request->post_data = rc_url_builder_finalize(&builder); ++ request->content_type = RC_CONTENT_TYPE_URLENCODED; ++ ++ return builder.result; ++} ++ ++int rc_api_process_add_game_hash_response(rc_api_add_game_hash_response_t* response, const char* server_response) { ++ rc_api_server_response_t response_obj; ++ ++ memset(&response_obj, 0, sizeof(response_obj)); ++ response_obj.body = server_response; ++ response_obj.body_length = rc_json_get_object_string_length(server_response); ++ ++ return rc_api_process_add_game_hash_server_response(response, &response_obj); ++} ++ ++int rc_api_process_add_game_hash_server_response(rc_api_add_game_hash_response_t* response, const rc_api_server_response_t* server_response) { ++ int result; ++ ++ rc_json_field_t fields[] = { ++ RC_JSON_NEW_FIELD("Success"), ++ RC_JSON_NEW_FIELD("Error"), ++ RC_JSON_NEW_FIELD("Response") ++ }; ++ ++ rc_json_field_t response_fields[] = { ++ RC_JSON_NEW_FIELD("GameID") ++ /* unused fields ++ RC_JSON_NEW_FIELD("MD5"), ++ RC_JSON_NEW_FIELD("ConsoleID"), ++ RC_JSON_NEW_FIELD("GameTitle"), ++ RC_JSON_NEW_FIELD("Success") ++ */ ++ }; ++ ++ memset(response, 0, sizeof(*response)); ++ rc_buffer_init(&response->response.buffer); ++ ++ result = rc_json_parse_server_response(&response->response, server_response, fields, sizeof(fields) / sizeof(fields[0])); ++ if (result != RC_OK || !response->response.succeeded) ++ return result; ++ ++ if (!rc_json_get_required_object(response_fields, sizeof(response_fields) / sizeof(response_fields[0]), &response->response, &fields[2], "Response")) ++ return RC_MISSING_VALUE; ++ ++ if (!rc_json_get_required_unum(&response->game_id, &response->response, &response_fields[0], "GameID")) ++ return RC_MISSING_VALUE; ++ ++ return RC_OK; ++} ++ ++void rc_api_destroy_add_game_hash_response(rc_api_add_game_hash_response_t* response) { ++ rc_buffer_destroy(&response->response.buffer); ++} +diff -rupbN melonDS.orig/src/rcheevos/src/rapi/rc_api_info.c melonDS.ra/src/rcheevos/src/rapi/rc_api_info.c +--- melonDS.orig/src/rcheevos/src/rapi/rc_api_info.c 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rapi/rc_api_info.c 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,582 @@ ++#include "rc_api_info.h" ++#include "rc_api_common.h" ++#include "rc_api_runtime.h" ++ ++#include "rc_runtime_types.h" ++ ++#include "../rc_compat.h" ++ ++#include ++#include ++ ++/* --- Fetch Achievement Info --- */ ++ ++int rc_api_init_fetch_achievement_info_request(rc_api_request_t* request, const rc_api_fetch_achievement_info_request_t* api_params) { ++ return rc_api_init_fetch_achievement_info_request_hosted(request, api_params, &g_host); ++} ++ ++int rc_api_init_fetch_achievement_info_request_hosted(rc_api_request_t* request, ++ const rc_api_fetch_achievement_info_request_t* api_params, ++ const rc_api_host_t* host) { ++ rc_api_url_builder_t builder; ++ ++ rc_api_url_build_dorequest_url(request, host); ++ ++ if (api_params->achievement_id == 0) ++ return RC_INVALID_STATE; ++ ++ rc_url_builder_init(&builder, &request->buffer, 48); ++ if (rc_api_url_build_dorequest(&builder, "achievementwondata", api_params->username, api_params->api_token)) { ++ rc_url_builder_append_unum_param(&builder, "a", api_params->achievement_id); ++ ++ if (api_params->friends_only) ++ rc_url_builder_append_unum_param(&builder, "f", 1); ++ if (api_params->first_entry > 1) ++ rc_url_builder_append_unum_param(&builder, "o", api_params->first_entry - 1); /* number of entries to skip */ ++ rc_url_builder_append_unum_param(&builder, "c", api_params->count); ++ ++ request->post_data = rc_url_builder_finalize(&builder); ++ request->content_type = RC_CONTENT_TYPE_URLENCODED; ++ } ++ ++ return builder.result; ++} ++ ++int rc_api_process_fetch_achievement_info_response(rc_api_fetch_achievement_info_response_t* response, const char* server_response) { ++ rc_api_server_response_t response_obj; ++ ++ memset(&response_obj, 0, sizeof(response_obj)); ++ response_obj.body = server_response; ++ response_obj.body_length = rc_json_get_object_string_length(server_response); ++ ++ return rc_api_process_fetch_achievement_info_server_response(response, &response_obj); ++} ++ ++int rc_api_process_fetch_achievement_info_server_response(rc_api_fetch_achievement_info_response_t* response, const rc_api_server_response_t* server_response) { ++ rc_api_achievement_awarded_entry_t* entry; ++ rc_json_field_t array_field; ++ rc_json_iterator_t iterator; ++ uint32_t timet; ++ int result; ++ ++ rc_json_field_t fields[] = { ++ RC_JSON_NEW_FIELD("Success"), ++ RC_JSON_NEW_FIELD("Error"), ++ RC_JSON_NEW_FIELD("AchievementID"), ++ RC_JSON_NEW_FIELD("Response") ++ /* unused fields ++ RC_JSON_NEW_FIELD("Offset"), ++ RC_JSON_NEW_FIELD("Count"), ++ RC_JSON_NEW_FIELD("FriendsOnly") ++ * unused fields */ ++ }; ++ ++ rc_json_field_t response_fields[] = { ++ RC_JSON_NEW_FIELD("NumEarned"), ++ RC_JSON_NEW_FIELD("TotalPlayers"), ++ RC_JSON_NEW_FIELD("GameID"), ++ RC_JSON_NEW_FIELD("RecentWinner") /* array */ ++ }; ++ ++ rc_json_field_t entry_fields[] = { ++ RC_JSON_NEW_FIELD("User"), ++ RC_JSON_NEW_FIELD("DateAwarded"), ++ RC_JSON_NEW_FIELD("AvatarUrl") ++ }; ++ ++ memset(response, 0, sizeof(*response)); ++ rc_buffer_init(&response->response.buffer); ++ ++ result = rc_json_parse_server_response(&response->response, server_response, fields, sizeof(fields) / sizeof(fields[0])); ++ if (result != RC_OK) ++ return result; ++ ++ if (!rc_json_get_required_unum(&response->id, &response->response, &fields[2], "AchievementID")) ++ return RC_MISSING_VALUE; ++ if (!rc_json_get_required_object(response_fields, sizeof(response_fields) / sizeof(response_fields[0]), &response->response, &fields[3], "Response")) ++ return RC_MISSING_VALUE; ++ ++ if (!rc_json_get_required_unum(&response->num_awarded, &response->response, &response_fields[0], "NumEarned")) ++ return RC_MISSING_VALUE; ++ if (!rc_json_get_required_unum(&response->num_players, &response->response, &response_fields[1], "TotalPlayers")) ++ return RC_MISSING_VALUE; ++ if (!rc_json_get_required_unum(&response->game_id, &response->response, &response_fields[2], "GameID")) ++ return RC_MISSING_VALUE; ++ ++ if (!rc_json_get_required_array(&response->num_recently_awarded, &array_field, &response->response, &response_fields[3], "RecentWinner")) ++ return RC_MISSING_VALUE; ++ ++ if (response->num_recently_awarded) { ++ response->recently_awarded = (rc_api_achievement_awarded_entry_t*)rc_buffer_alloc(&response->response.buffer, response->num_recently_awarded * sizeof(rc_api_achievement_awarded_entry_t)); ++ if (!response->recently_awarded) ++ return RC_OUT_OF_MEMORY; ++ ++ memset(&iterator, 0, sizeof(iterator)); ++ iterator.json = array_field.value_start; ++ iterator.end = array_field.value_end; ++ ++ entry = response->recently_awarded; ++ while (rc_json_get_array_entry_object(entry_fields, sizeof(entry_fields) / sizeof(entry_fields[0]), &iterator)) { ++ if (!rc_json_get_required_string(&entry->username, &response->response, &entry_fields[0], "User")) ++ return RC_MISSING_VALUE; ++ ++ if (!rc_json_get_required_unum(&timet, &response->response, &entry_fields[1], "DateAwarded")) ++ return RC_MISSING_VALUE; ++ entry->awarded = (time_t)timet; ++ ++ rc_json_get_optional_string(&entry->avatar_url, &response->response, &entry_fields[2], "AvatarUrl", NULL); ++ if (!entry->avatar_url) ++ entry->avatar_url = rc_api_build_avatar_url(&response->response.buffer, RC_IMAGE_TYPE_USER, entry->username); ++ ++ ++entry; ++ } ++ } ++ ++ return RC_OK; ++} ++ ++void rc_api_destroy_fetch_achievement_info_response(rc_api_fetch_achievement_info_response_t* response) { ++ rc_buffer_destroy(&response->response.buffer); ++} ++ ++/* --- Fetch Leaderboard Info --- */ ++ ++int rc_api_init_fetch_leaderboard_info_request(rc_api_request_t* request, const rc_api_fetch_leaderboard_info_request_t* api_params) { ++ return rc_api_init_fetch_leaderboard_info_request_hosted(request, api_params, &g_host); ++} ++ ++int rc_api_init_fetch_leaderboard_info_request_hosted(rc_api_request_t* request, ++ const rc_api_fetch_leaderboard_info_request_t* api_params, ++ const rc_api_host_t* host) { ++ rc_api_url_builder_t builder; ++ ++ rc_api_url_build_dorequest_url(request, host); ++ ++ if (api_params->leaderboard_id == 0) ++ return RC_INVALID_STATE; ++ ++ rc_url_builder_init(&builder, &request->buffer, 48); ++ rc_url_builder_append_str_param(&builder, "r", "lbinfo"); ++ rc_url_builder_append_unum_param(&builder, "i", api_params->leaderboard_id); ++ ++ if (api_params->username) ++ rc_url_builder_append_str_param(&builder, "u", api_params->username); ++ else if (api_params->first_entry > 1) ++ rc_url_builder_append_unum_param(&builder, "o", api_params->first_entry - 1); /* number of entries to skip */ ++ ++ rc_url_builder_append_unum_param(&builder, "c", api_params->count); ++ request->post_data = rc_url_builder_finalize(&builder); ++ request->content_type = RC_CONTENT_TYPE_URLENCODED; ++ ++ return builder.result; ++} ++ ++int rc_api_process_fetch_leaderboard_info_response(rc_api_fetch_leaderboard_info_response_t* response, const char* server_response) { ++ rc_api_server_response_t response_obj; ++ ++ memset(&response_obj, 0, sizeof(response_obj)); ++ response_obj.body = server_response; ++ response_obj.body_length = rc_json_get_object_string_length(server_response); ++ ++ return rc_api_process_fetch_leaderboard_info_server_response(response, &response_obj); ++} ++ ++int rc_api_process_fetch_leaderboard_info_server_response(rc_api_fetch_leaderboard_info_response_t* response, const rc_api_server_response_t* server_response) { ++ rc_api_lboard_info_entry_t* entry; ++ rc_json_field_t array_field; ++ rc_json_iterator_t iterator; ++ uint32_t timet; ++ int result; ++ size_t len; ++ char format[16]; ++ ++ rc_json_field_t fields[] = { ++ RC_JSON_NEW_FIELD("Success"), ++ RC_JSON_NEW_FIELD("Error"), ++ RC_JSON_NEW_FIELD("LeaderboardData") ++ }; ++ ++ rc_json_field_t leaderboarddata_fields[] = { ++ RC_JSON_NEW_FIELD("LBID"), ++ RC_JSON_NEW_FIELD("LBFormat"), ++ RC_JSON_NEW_FIELD("LowerIsBetter"), ++ RC_JSON_NEW_FIELD("LBTitle"), ++ RC_JSON_NEW_FIELD("LBDesc"), ++ RC_JSON_NEW_FIELD("LBMem"), ++ RC_JSON_NEW_FIELD("GameID"), ++ RC_JSON_NEW_FIELD("LBAuthor"), ++ RC_JSON_NEW_FIELD("LBCreated"), ++ RC_JSON_NEW_FIELD("LBUpdated"), ++ RC_JSON_NEW_FIELD("Entries"), /* array */ ++ RC_JSON_NEW_FIELD("TotalEntries") ++ }; ++ ++ rc_json_field_t entry_fields[] = { ++ RC_JSON_NEW_FIELD("User"), ++ RC_JSON_NEW_FIELD("Rank"), ++ RC_JSON_NEW_FIELD("Index"), ++ RC_JSON_NEW_FIELD("Score"), ++ RC_JSON_NEW_FIELD("DateSubmitted"), ++ RC_JSON_NEW_FIELD("AvatarUrl") ++ }; ++ ++ memset(response, 0, sizeof(*response)); ++ rc_buffer_init(&response->response.buffer); ++ ++ result = rc_json_parse_server_response(&response->response, server_response, fields, sizeof(fields) / sizeof(fields[0])); ++ if (result != RC_OK) ++ return result; ++ ++ if (!rc_json_get_required_object(leaderboarddata_fields, sizeof(leaderboarddata_fields) / sizeof(leaderboarddata_fields[0]), &response->response, &fields[2], "LeaderboardData")) ++ return RC_MISSING_VALUE; ++ ++ if (!rc_json_get_required_unum(&response->id, &response->response, &leaderboarddata_fields[0], "LBID")) ++ return RC_MISSING_VALUE; ++ if (!rc_json_get_required_unum(&response->lower_is_better, &response->response, &leaderboarddata_fields[2], "LowerIsBetter")) ++ return RC_MISSING_VALUE; ++ if (!rc_json_get_required_string(&response->title, &response->response, &leaderboarddata_fields[3], "LBTitle")) ++ return RC_MISSING_VALUE; ++ if (!rc_json_get_required_string(&response->description, &response->response, &leaderboarddata_fields[4], "LBDesc")) ++ return RC_MISSING_VALUE; ++ if (!rc_json_get_required_string(&response->definition, &response->response, &leaderboarddata_fields[5], "LBMem")) ++ return RC_MISSING_VALUE; ++ if (!rc_json_get_required_unum(&response->game_id, &response->response, &leaderboarddata_fields[6], "GameID")) ++ return RC_MISSING_VALUE; ++ if (!rc_json_get_required_string(&response->author, &response->response, &leaderboarddata_fields[7], "LBAuthor")) ++ return RC_MISSING_VALUE; ++ if (!rc_json_get_required_datetime(&response->created, &response->response, &leaderboarddata_fields[8], "LBCreated")) ++ return RC_MISSING_VALUE; ++ if (!rc_json_get_required_datetime(&response->updated, &response->response, &leaderboarddata_fields[9], "LBUpdated")) ++ return RC_MISSING_VALUE; ++ if (!rc_json_get_required_unum(&response->total_entries, &response->response, &leaderboarddata_fields[11], "TotalEntries")) ++ return RC_MISSING_VALUE; ++ ++ if (!leaderboarddata_fields[1].value_end) ++ return RC_MISSING_VALUE; ++ len = leaderboarddata_fields[1].value_end - leaderboarddata_fields[1].value_start - 2; ++ if (len < sizeof(format) - 1) { ++ memcpy(format, leaderboarddata_fields[1].value_start + 1, len); ++ format[len] = '\0'; ++ response->format = rc_parse_format(format); ++ } ++ else { ++ response->format = RC_FORMAT_VALUE; ++ } ++ ++ if (!rc_json_get_required_array(&response->num_entries, &array_field, &response->response, &leaderboarddata_fields[10], "Entries")) ++ return RC_MISSING_VALUE; ++ ++ if (response->num_entries) { ++ response->entries = (rc_api_lboard_info_entry_t*)rc_buffer_alloc(&response->response.buffer, response->num_entries * sizeof(rc_api_lboard_info_entry_t)); ++ if (!response->entries) ++ return RC_OUT_OF_MEMORY; ++ ++ memset(&iterator, 0, sizeof(iterator)); ++ iterator.json = array_field.value_start; ++ iterator.end = array_field.value_end; ++ ++ entry = response->entries; ++ while (rc_json_get_array_entry_object(entry_fields, sizeof(entry_fields) / sizeof(entry_fields[0]), &iterator)) { ++ if (!rc_json_get_required_string(&entry->username, &response->response, &entry_fields[0], "User")) ++ return RC_MISSING_VALUE; ++ ++ if (!rc_json_get_required_unum(&entry->rank, &response->response, &entry_fields[1], "Rank")) ++ return RC_MISSING_VALUE; ++ ++ if (!rc_json_get_required_unum(&entry->index, &response->response, &entry_fields[2], "Index")) ++ return RC_MISSING_VALUE; ++ ++ if (!rc_json_get_required_num(&entry->score, &response->response, &entry_fields[3], "Score")) ++ return RC_MISSING_VALUE; ++ ++ if (!rc_json_get_required_unum(&timet, &response->response, &entry_fields[4], "DateSubmitted")) ++ return RC_MISSING_VALUE; ++ entry->submitted = (time_t)timet; ++ ++ rc_json_get_optional_string(&entry->avatar_url, &response->response, &entry_fields[5], "AvatarUrl", NULL); ++ if (!entry->avatar_url) ++ entry->avatar_url = rc_api_build_avatar_url(&response->response.buffer, RC_IMAGE_TYPE_USER, entry->username); ++ ++ ++entry; ++ } ++ } ++ ++ return RC_OK; ++} ++ ++void rc_api_destroy_fetch_leaderboard_info_response(rc_api_fetch_leaderboard_info_response_t* response) { ++ rc_buffer_destroy(&response->response.buffer); ++} ++ ++/* --- Fetch Games List --- */ ++ ++int rc_api_init_fetch_games_list_request(rc_api_request_t* request, const rc_api_fetch_games_list_request_t* api_params) { ++ return rc_api_init_fetch_games_list_request_hosted(request, api_params, &g_host); ++} ++ ++int rc_api_init_fetch_games_list_request_hosted(rc_api_request_t* request, ++ const rc_api_fetch_games_list_request_t* api_params, ++ const rc_api_host_t* host) { ++ rc_api_url_builder_t builder; ++ ++ rc_api_url_build_dorequest_url(request, host); ++ ++ if (api_params->console_id == 0) ++ return RC_INVALID_STATE; ++ ++ rc_url_builder_init(&builder, &request->buffer, 48); ++ rc_url_builder_append_str_param(&builder, "r", "gameslist"); ++ rc_url_builder_append_unum_param(&builder, "c", api_params->console_id); ++ ++ request->post_data = rc_url_builder_finalize(&builder); ++ request->content_type = RC_CONTENT_TYPE_URLENCODED; ++ ++ return builder.result; ++} ++ ++int rc_api_process_fetch_games_list_response(rc_api_fetch_games_list_response_t* response, const char* server_response) { ++ rc_api_server_response_t response_obj; ++ ++ memset(&response_obj, 0, sizeof(response_obj)); ++ response_obj.body = server_response; ++ response_obj.body_length = rc_json_get_object_string_length(server_response); ++ ++ return rc_api_process_fetch_games_list_server_response(response, &response_obj); ++} ++ ++int rc_api_process_fetch_games_list_server_response(rc_api_fetch_games_list_response_t* response, const rc_api_server_response_t* server_response) { ++ rc_api_game_list_entry_t* entry; ++ rc_json_iterator_t iterator; ++ rc_json_field_t field; ++ int result; ++ char* end; ++ ++ rc_json_field_t fields[] = { ++ RC_JSON_NEW_FIELD("Success"), ++ RC_JSON_NEW_FIELD("Error"), ++ RC_JSON_NEW_FIELD("Response") ++ }; ++ ++ memset(response, 0, sizeof(*response)); ++ rc_buffer_init(&response->response.buffer); ++ ++ result = rc_json_parse_server_response(&response->response, server_response, fields, sizeof(fields) / sizeof(fields[0])); ++ if (result != RC_OK) ++ return result; ++ ++ if (!fields[2].value_start) { ++ /* call rc_json_get_required_object to generate the error message */ ++ rc_json_get_required_object(NULL, 0, &response->response, &fields[2], "Response"); ++ return RC_MISSING_VALUE; ++ } ++ ++ response->num_entries = fields[2].array_size; ++ rc_buffer_reserve(&response->response.buffer, response->num_entries * (32 + sizeof(rc_api_game_list_entry_t))); ++ ++ response->entries = (rc_api_game_list_entry_t*)rc_buffer_alloc(&response->response.buffer, response->num_entries * sizeof(rc_api_game_list_entry_t)); ++ if (!response->entries) ++ return RC_OUT_OF_MEMORY; ++ ++ memset(&iterator, 0, sizeof(iterator)); ++ iterator.json = fields[2].value_start; ++ iterator.end = fields[2].value_end; ++ ++ entry = response->entries; ++ while (rc_json_get_next_object_field(&iterator, &field)) { ++ entry->id = strtol(field.name, &end, 10); ++ ++ field.name = ""; ++ if (!rc_json_get_string(&entry->name, &response->response.buffer, &field, "")) ++ return RC_MISSING_VALUE; ++ ++ ++entry; ++ } ++ ++ return RC_OK; ++} ++ ++void rc_api_destroy_fetch_games_list_response(rc_api_fetch_games_list_response_t* response) { ++ rc_buffer_destroy(&response->response.buffer); ++} ++ ++/* --- Fetch Game Titles --- */ ++ ++int rc_api_init_fetch_game_titles_request(rc_api_request_t* request, const rc_api_fetch_game_titles_request_t* api_params) { ++ return rc_api_init_fetch_game_titles_request_hosted(request, api_params, &g_host); ++} ++ ++int rc_api_init_fetch_game_titles_request_hosted(rc_api_request_t* request, ++ const rc_api_fetch_game_titles_request_t* api_params, ++ const rc_api_host_t* host) { ++ rc_api_url_builder_t builder; ++ char num[16]; ++ uint32_t i; ++ ++ rc_api_url_build_dorequest_url(request, host); ++ ++ if (api_params->num_game_ids == 0) ++ return RC_INVALID_STATE; ++ ++ rc_url_builder_init(&builder, &request->buffer, 48); ++ rc_url_builder_append_str_param(&builder, "r", "gameinfolist"); ++ rc_url_builder_append_unum_param(&builder, "g", api_params->game_ids[0]); ++ ++ for (i = 1; i < api_params->num_game_ids; i++) { ++ int chars = snprintf(num, sizeof(num), "%u", api_params->game_ids[i]); ++ rc_url_builder_append(&builder, ",", 1); ++ rc_url_builder_append(&builder, num, chars); ++ } ++ ++ request->post_data = rc_url_builder_finalize(&builder); ++ request->content_type = RC_CONTENT_TYPE_URLENCODED; ++ ++ return builder.result; ++} ++ ++int rc_api_process_fetch_game_titles_server_response(rc_api_fetch_game_titles_response_t* response, const rc_api_server_response_t* server_response) { ++ rc_api_game_title_entry_t* entry; ++ rc_json_iterator_t iterator; ++ rc_json_field_t array_field; ++ int result; ++ ++ rc_json_field_t fields[] = { ++ RC_JSON_NEW_FIELD("Success"), ++ RC_JSON_NEW_FIELD("Error"), ++ RC_JSON_NEW_FIELD("Response") ++ }; ++ ++ rc_json_field_t entry_fields[] = { ++ RC_JSON_NEW_FIELD("ID"), ++ RC_JSON_NEW_FIELD("Title"), ++ RC_JSON_NEW_FIELD("ImageIcon") ++ }; ++ ++ memset(response, 0, sizeof(*response)); ++ rc_buffer_init(&response->response.buffer); ++ ++ result = rc_json_parse_server_response(&response->response, server_response, fields, sizeof(fields) / sizeof(fields[0])); ++ if (result != RC_OK) ++ return result; ++ ++ if (!rc_json_get_required_array(&response->num_entries, &array_field, &response->response, &fields[2], "Response")) ++ return RC_MISSING_VALUE; ++ ++ if (response->num_entries) { ++ response->entries = (rc_api_game_title_entry_t*)rc_buffer_alloc(&response->response.buffer, response->num_entries * sizeof(rc_api_game_title_entry_t)); ++ if (!response->entries) ++ return RC_OUT_OF_MEMORY; ++ ++ memset(&iterator, 0, sizeof(iterator)); ++ iterator.json = array_field.value_start; ++ iterator.end = array_field.value_end; ++ ++ entry = response->entries; ++ while (rc_json_get_array_entry_object(entry_fields, sizeof(entry_fields) / sizeof(entry_fields[0]), &iterator)) { ++ if (!rc_json_get_required_unum(&entry->id, &response->response, &entry_fields[0], "ID")) ++ return RC_MISSING_VALUE; ++ if (!rc_json_get_required_string(&entry->title, &response->response, &entry_fields[1], "Title")) ++ return RC_MISSING_VALUE; ++ ++ /* ImageIcon will be '/Images/0123456.png' - only return the '0123456' */ ++ rc_json_extract_filename(&entry_fields[2]); ++ if (!rc_json_get_required_string(&entry->image_name, &response->response, &entry_fields[2], "ImageIcon")) ++ return RC_MISSING_VALUE; ++ ++ ++entry; ++ } ++ } ++ ++ return RC_OK; ++} ++ ++void rc_api_destroy_fetch_game_titles_response(rc_api_fetch_game_titles_response_t* response) { ++ rc_buffer_destroy(&response->response.buffer); ++} ++ ++/* --- Fetch Game Hashes --- */ ++ ++int rc_api_init_fetch_hash_library_request(rc_api_request_t* request, ++ const rc_api_fetch_hash_library_request_t* api_params) ++{ ++ return rc_api_init_fetch_hash_library_request_hosted(request, api_params, &g_host); ++} ++ ++int rc_api_init_fetch_hash_library_request_hosted(rc_api_request_t* request, ++ const rc_api_fetch_hash_library_request_t* api_params, ++ const rc_api_host_t* host) ++{ ++ rc_api_url_builder_t builder; ++ rc_api_url_build_dorequest_url(request, host); ++ ++ /* note: unauthenticated request */ ++ rc_url_builder_init(&builder, &request->buffer, 48); ++ rc_url_builder_append_str_param(&builder, "r", "hashlibrary"); ++ if (api_params->console_id != 0) ++ rc_url_builder_append_unum_param(&builder, "c", api_params->console_id); ++ ++ request->post_data = rc_url_builder_finalize(&builder); ++ request->content_type = RC_CONTENT_TYPE_URLENCODED; ++ ++ return builder.result; ++} ++ ++int rc_api_process_fetch_hash_library_server_response(rc_api_fetch_hash_library_response_t* response, ++ const rc_api_server_response_t* server_response) ++{ ++ rc_api_hash_library_entry_t* entry; ++ rc_json_iterator_t iterator; ++ rc_json_field_t field; ++ int result; ++ ++ rc_json_field_t fields[] = { ++ RC_JSON_NEW_FIELD("Success"), ++ RC_JSON_NEW_FIELD("Error"), ++ RC_JSON_NEW_FIELD("MD5List"), ++ }; ++ ++ memset(response, 0, sizeof(*response)); ++ rc_buffer_init(&response->response.buffer); ++ ++ result = ++ rc_json_parse_server_response(&response->response, server_response, fields, sizeof(fields) / sizeof(fields[0])); ++ if (result != RC_OK) ++ return result; ++ ++ if (!fields[2].value_start) { ++ /* call rc_json_get_required_object to generate the error message */ ++ rc_json_get_required_object(NULL, 0, &response->response, &fields[2], "MD5List"); ++ return RC_MISSING_VALUE; ++ } ++ ++ response->num_entries = fields[2].array_size; ++ if (response->num_entries > 0) { ++ rc_buffer_reserve(&response->response.buffer, response->num_entries * (33 + sizeof(rc_api_hash_library_entry_t))); ++ ++ response->entries = (rc_api_hash_library_entry_t*)rc_buffer_alloc( ++ &response->response.buffer, response->num_entries * sizeof(rc_api_hash_library_entry_t)); ++ if (!response->entries) ++ return RC_OUT_OF_MEMORY; ++ ++ memset(&iterator, 0, sizeof(iterator)); ++ iterator.json = fields[2].value_start; ++ iterator.end = fields[2].value_end; ++ ++ entry = response->entries; ++ while (rc_json_get_next_object_field(&iterator, &field)) { ++ entry->hash = rc_buffer_strncpy(&response->response.buffer, field.name, field.name_len); ++ ++ field.name = ""; ++ if (!rc_json_get_unum(&entry->game_id, &field, "")) ++ return RC_MISSING_VALUE; ++ ++ ++entry; ++ } ++ } ++ ++ return RC_OK; ++} ++ ++void rc_api_destroy_fetch_hash_library_response(rc_api_fetch_hash_library_response_t* response) ++{ ++ rc_buffer_destroy(&response->response.buffer); ++} +diff -rupbN melonDS.orig/src/rcheevos/src/rapi/rc_api_runtime.c melonDS.ra/src/rcheevos/src/rapi/rc_api_runtime.c +--- melonDS.orig/src/rcheevos/src/rapi/rc_api_runtime.c 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rapi/rc_api_runtime.c 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,901 @@ ++#include "rc_api_runtime.h" ++#include "rc_api_common.h" ++ ++#include "rc_runtime.h" ++#include "rc_runtime_types.h" ++#include "../rc_compat.h" ++#include "../rhash/md5.h" ++ ++#include ++#include ++#include ++ ++/* --- Resolve Hash --- */ ++ ++int rc_api_init_resolve_hash_request(rc_api_request_t* request, const rc_api_resolve_hash_request_t* api_params) { ++ return rc_api_init_resolve_hash_request_hosted(request, api_params, &g_host); ++} ++ ++int rc_api_init_resolve_hash_request_hosted(rc_api_request_t* request, ++ const rc_api_resolve_hash_request_t* api_params, ++ const rc_api_host_t* host) { ++ rc_api_url_builder_t builder; ++ ++ rc_api_url_build_dorequest_url(request, host); ++ ++ if (!api_params->game_hash || !*api_params->game_hash) ++ return RC_INVALID_STATE; ++ ++ rc_url_builder_init(&builder, &request->buffer, 48); ++ rc_url_builder_append_str_param(&builder, "r", "gameid"); ++ rc_url_builder_append_str_param(&builder, "m", api_params->game_hash); ++ request->post_data = rc_url_builder_finalize(&builder); ++ request->content_type = RC_CONTENT_TYPE_URLENCODED; ++ ++ return builder.result; ++} ++ ++int rc_api_process_resolve_hash_response(rc_api_resolve_hash_response_t* response, const char* server_response) { ++ rc_api_server_response_t response_obj; ++ ++ memset(&response_obj, 0, sizeof(response_obj)); ++ response_obj.body = server_response; ++ response_obj.body_length = rc_json_get_object_string_length(server_response); ++ ++ return rc_api_process_resolve_hash_server_response(response, &response_obj); ++} ++ ++int rc_api_process_resolve_hash_server_response(rc_api_resolve_hash_response_t* response, const rc_api_server_response_t* server_response) { ++ int result; ++ rc_json_field_t fields[] = { ++ RC_JSON_NEW_FIELD("Success"), ++ RC_JSON_NEW_FIELD("Error"), ++ RC_JSON_NEW_FIELD("GameID") ++ }; ++ ++ memset(response, 0, sizeof(*response)); ++ rc_buffer_init(&response->response.buffer); ++ ++ result = rc_json_parse_server_response(&response->response, server_response, fields, sizeof(fields) / sizeof(fields[0])); ++ if (result != RC_OK) ++ return result; ++ ++ rc_json_get_required_unum(&response->game_id, &response->response, &fields[2], "GameID"); ++ return RC_OK; ++} ++ ++void rc_api_destroy_resolve_hash_response(rc_api_resolve_hash_response_t* response) { ++ rc_buffer_destroy(&response->response.buffer); ++} ++ ++/* --- Fetch Game Data --- */ ++ ++int rc_api_init_fetch_game_data_request(rc_api_request_t* request, const rc_api_fetch_game_data_request_t* api_params) { ++ return rc_api_init_fetch_game_data_request_hosted(request, api_params, &g_host); ++} ++ ++int rc_api_init_fetch_game_data_request_hosted(rc_api_request_t* request, ++ const rc_api_fetch_game_data_request_t* api_params, ++ const rc_api_host_t* host) { ++ rc_api_url_builder_t builder; ++ ++ rc_api_url_build_dorequest_url(request, host); ++ ++ if (api_params->game_id == 0 && (!api_params->game_hash || !api_params->game_hash[0])) ++ return RC_INVALID_STATE; ++ ++ rc_url_builder_init(&builder, &request->buffer, 48); ++ if (rc_api_url_build_dorequest(&builder, "patch", api_params->username, api_params->api_token)) { ++ if (api_params->game_id) ++ rc_url_builder_append_unum_param(&builder, "g", api_params->game_id); ++ else ++ rc_url_builder_append_str_param(&builder, "m", api_params->game_hash); ++ ++ request->post_data = rc_url_builder_finalize(&builder); ++ request->content_type = RC_CONTENT_TYPE_URLENCODED; ++ } ++ ++ return builder.result; ++} ++ ++int rc_api_process_fetch_game_data_response(rc_api_fetch_game_data_response_t* response, const char* server_response) { ++ rc_api_server_response_t response_obj; ++ ++ memset(&response_obj, 0, sizeof(response_obj)); ++ response_obj.body = server_response; ++ response_obj.body_length = rc_json_get_object_string_length(server_response); ++ ++ return rc_api_process_fetch_game_data_server_response(response, &response_obj); ++} ++ ++static int rc_api_process_fetch_game_data_achievements(rc_api_response_t* response, rc_api_achievement_definition_t* achievement, rc_json_field_t* array_field) { ++ rc_json_iterator_t iterator; ++ const char* last_author = ""; ++ const char* last_author_field = ""; ++ size_t last_author_len = 0; ++ uint32_t timet; ++ size_t len; ++ ++ rc_json_field_t achievement_fields[] = { ++ RC_JSON_NEW_FIELD("ID"), ++ RC_JSON_NEW_FIELD("Title"), ++ RC_JSON_NEW_FIELD("Description"), ++ RC_JSON_NEW_FIELD("Flags"), ++ RC_JSON_NEW_FIELD("Points"), ++ RC_JSON_NEW_FIELD("MemAddr"), ++ RC_JSON_NEW_FIELD("Author"), ++ RC_JSON_NEW_FIELD("BadgeName"), ++ RC_JSON_NEW_FIELD("Created"), ++ RC_JSON_NEW_FIELD("Modified"), ++ RC_JSON_NEW_FIELD("Type"), ++ RC_JSON_NEW_FIELD("Rarity"), ++ RC_JSON_NEW_FIELD("RarityHardcore"), ++ RC_JSON_NEW_FIELD("BadgeURL"), ++ RC_JSON_NEW_FIELD("BadgeLockedURL") ++ }; ++ ++ memset(&iterator, 0, sizeof(iterator)); ++ iterator.json = array_field->value_start; ++ iterator.end = array_field->value_end; ++ ++ while (rc_json_get_array_entry_object(achievement_fields, sizeof(achievement_fields) / sizeof(achievement_fields[0]), &iterator)) { ++ if (!rc_json_get_required_unum(&achievement->id, response, &achievement_fields[0], "ID")) ++ return RC_MISSING_VALUE; ++ if (!rc_json_get_required_string(&achievement->title, response, &achievement_fields[1], "Title")) ++ return RC_MISSING_VALUE; ++ if (!rc_json_get_required_string(&achievement->description, response, &achievement_fields[2], "Description")) ++ return RC_MISSING_VALUE; ++ if (!rc_json_get_required_unum(&achievement->category, response, &achievement_fields[3], "Flags")) ++ return RC_MISSING_VALUE; ++ if (!rc_json_get_required_unum(&achievement->points, response, &achievement_fields[4], "Points")) ++ return RC_MISSING_VALUE; ++ if (!rc_json_get_required_string(&achievement->definition, response, &achievement_fields[5], "MemAddr")) ++ return RC_MISSING_VALUE; ++ if (!rc_json_get_required_string(&achievement->badge_name, response, &achievement_fields[7], "BadgeName")) ++ return RC_MISSING_VALUE; ++ ++ rc_json_get_optional_string(&achievement->badge_url, response, &achievement_fields[13], "BadgeURL", ""); ++ if (!achievement->badge_url[0]) ++ achievement->badge_url = rc_api_build_avatar_url(&response->buffer, RC_IMAGE_TYPE_ACHIEVEMENT, achievement->badge_name); ++ ++ rc_json_get_optional_string(&achievement->badge_locked_url, response, &achievement_fields[14], "BadgeLockedURL", ""); ++ if (!achievement->badge_locked_url[0]) ++ achievement->badge_locked_url = rc_api_build_avatar_url(&response->buffer, RC_IMAGE_TYPE_ACHIEVEMENT_LOCKED, achievement->badge_name); ++ ++ len = achievement_fields[6].value_end - achievement_fields[6].value_start; ++ if (len == last_author_len && memcmp(achievement_fields[6].value_start, last_author_field, len) == 0) { ++ achievement->author = last_author; ++ } ++ else { ++ if (!rc_json_get_required_string(&achievement->author, response, &achievement_fields[6], "Author")) ++ return RC_MISSING_VALUE; ++ ++ if (achievement->author == NULL) { ++ /* ensure we don't pass NULL out to client */ ++ last_author = achievement->author = ""; ++ last_author_len = 0; ++ } else { ++ last_author = achievement->author; ++ last_author_field = achievement_fields[6].value_start; ++ last_author_len = len; ++ } ++ } ++ ++ if (!rc_json_get_required_unum(&timet, response, &achievement_fields[8], "Created")) ++ return RC_MISSING_VALUE; ++ achievement->created = (time_t)timet; ++ if (!rc_json_get_required_unum(&timet, response, &achievement_fields[9], "Modified")) ++ return RC_MISSING_VALUE; ++ achievement->updated = (time_t)timet; ++ ++ if (rc_json_field_string_matches(&achievement_fields[10], "")) ++ achievement->type = RC_ACHIEVEMENT_TYPE_STANDARD; ++ else if (rc_json_field_string_matches(&achievement_fields[10], "progression")) ++ achievement->type = RC_ACHIEVEMENT_TYPE_PROGRESSION; ++ else if (rc_json_field_string_matches(&achievement_fields[10], "missable")) ++ achievement->type = RC_ACHIEVEMENT_TYPE_MISSABLE; ++ else if (rc_json_field_string_matches(&achievement_fields[10], "win_condition")) ++ achievement->type = RC_ACHIEVEMENT_TYPE_WIN; ++ else ++ achievement->type = RC_ACHIEVEMENT_TYPE_STANDARD; ++ ++ /* legacy support : if title contains[m], change type to missable and remove[m] from title */ ++ if (memcmp(achievement->title, "[m]", 3) == 0) { ++ len = 3; ++ while (achievement->title[len] == ' ') ++ ++len; ++ achievement->title += len; ++ achievement->type = RC_ACHIEVEMENT_TYPE_MISSABLE; ++ } ++ else if (achievement_fields[1].value_end && memcmp(achievement_fields[1].value_end - 4, "[m]", 3) == 0) { ++ len = strlen(achievement->title) - 3; ++ while (achievement->title[len - 1] == ' ') ++ --len; ++ ((char*)achievement->title)[len] = '\0'; ++ achievement->type = RC_ACHIEVEMENT_TYPE_MISSABLE; ++ } ++ ++ rc_json_get_optional_float(&achievement->rarity, &achievement_fields[11], "Rarity", 100.0); ++ rc_json_get_optional_float(&achievement->rarity_hardcore, &achievement_fields[12], "RarityHardcore", 100.0); ++ ++ ++achievement; ++ } ++ ++ return RC_OK; ++} ++ ++static int rc_api_process_fetch_game_data_leaderboards(rc_api_response_t* response, rc_api_leaderboard_definition_t* leaderboard, rc_json_field_t* array_field) { ++ rc_json_iterator_t iterator; ++ size_t len; ++ int result; ++ char format[16]; ++ ++ rc_json_field_t leaderboard_fields[] = { ++ RC_JSON_NEW_FIELD("ID"), ++ RC_JSON_NEW_FIELD("Title"), ++ RC_JSON_NEW_FIELD("Description"), ++ RC_JSON_NEW_FIELD("Mem"), ++ RC_JSON_NEW_FIELD("Format"), ++ RC_JSON_NEW_FIELD("LowerIsBetter"), ++ RC_JSON_NEW_FIELD("Hidden") ++ }; ++ ++ memset(&iterator, 0, sizeof(iterator)); ++ iterator.json = array_field->value_start; ++ iterator.end = array_field->value_end; ++ ++ while (rc_json_get_array_entry_object(leaderboard_fields, sizeof(leaderboard_fields) / sizeof(leaderboard_fields[0]), &iterator)) { ++ if (!rc_json_get_required_unum(&leaderboard->id, response, &leaderboard_fields[0], "ID")) ++ return RC_MISSING_VALUE; ++ if (!rc_json_get_required_string(&leaderboard->title, response, &leaderboard_fields[1], "Title")) ++ return RC_MISSING_VALUE; ++ if (!rc_json_get_required_string(&leaderboard->description, response, &leaderboard_fields[2], "Description")) ++ return RC_MISSING_VALUE; ++ if (!rc_json_get_required_string(&leaderboard->definition, response, &leaderboard_fields[3], "Mem")) ++ return RC_MISSING_VALUE; ++ rc_json_get_optional_bool(&result, &leaderboard_fields[5], "LowerIsBetter", 0); ++ leaderboard->lower_is_better = (uint8_t)result; ++ rc_json_get_optional_bool(&result, &leaderboard_fields[6], "Hidden", 0); ++ leaderboard->hidden = (uint8_t)result; ++ ++ if (!leaderboard_fields[4].value_end) ++ return RC_MISSING_VALUE; ++ len = leaderboard_fields[4].value_end - leaderboard_fields[4].value_start - 2; ++ if (len < sizeof(format) - 1) { ++ memcpy(format, leaderboard_fields[4].value_start + 1, len); ++ format[len] = '\0'; ++ leaderboard->format = rc_parse_format(format); ++ } ++ else { ++ leaderboard->format = RC_FORMAT_VALUE; ++ } ++ ++ ++leaderboard; ++ } ++ ++ return RC_OK; ++} ++ ++int rc_api_process_fetch_game_data_server_response(rc_api_fetch_game_data_response_t* response, const rc_api_server_response_t* server_response) { ++ rc_json_field_t array_field; ++ size_t len; ++ int result; ++ ++ rc_json_field_t fields[] = { ++ RC_JSON_NEW_FIELD("Success"), ++ RC_JSON_NEW_FIELD("Error"), ++ RC_JSON_NEW_FIELD("Code"), ++ RC_JSON_NEW_FIELD("PatchData") /* nested object */ ++ }; ++ ++ rc_json_field_t patchdata_fields[] = { ++ RC_JSON_NEW_FIELD("ID"), ++ RC_JSON_NEW_FIELD("Title"), ++ RC_JSON_NEW_FIELD("ConsoleID"), ++ RC_JSON_NEW_FIELD("ImageIcon"), ++ RC_JSON_NEW_FIELD("ImageIconURL"), ++ RC_JSON_NEW_FIELD("RichPresencePatch"), ++ RC_JSON_NEW_FIELD("Achievements"), /* array */ ++ RC_JSON_NEW_FIELD("Leaderboards"), /* array */ ++ }; ++ ++ memset(response, 0, sizeof(*response)); ++ rc_buffer_init(&response->response.buffer); ++ ++ result = rc_json_parse_server_response(&response->response, server_response, fields, sizeof(fields) / sizeof(fields[0])); ++ if (result != RC_OK || !response->response.succeeded) ++ return result; ++ ++ if (!rc_json_get_required_object(patchdata_fields, sizeof(patchdata_fields) / sizeof(patchdata_fields[0]), &response->response, &fields[3], "PatchData")) ++ return RC_MISSING_VALUE; ++ ++ if (!rc_json_get_required_unum(&response->id, &response->response, &patchdata_fields[0], "ID")) ++ return RC_MISSING_VALUE; ++ if (!rc_json_get_required_string(&response->title, &response->response, &patchdata_fields[1], "Title")) ++ return RC_MISSING_VALUE; ++ if (!rc_json_get_required_unum(&response->console_id, &response->response, &patchdata_fields[2], "ConsoleID")) ++ return RC_MISSING_VALUE; ++ ++ /* ImageIcon will be '/Images/0123456.png' - only return the '0123456' */ ++ rc_json_extract_filename(&patchdata_fields[3]); ++ rc_json_get_optional_string(&response->image_name, &response->response, &patchdata_fields[3], "ImageIcon", ""); ++ rc_json_get_optional_string(&response->image_url, &response->response, &patchdata_fields[4], "ImageIconURL", ""); ++ if (!response->image_url[0]) ++ response->image_url = rc_api_build_avatar_url(&response->response.buffer, RC_IMAGE_TYPE_GAME, response->image_name); ++ ++ /* estimate the amount of space necessary to store the rich presence script, achievements, and leaderboards. ++ determine how much space each takes as a string in the JSON, then subtract out the non-data (field names, punctuation) ++ and add space for the structures. */ ++ len = patchdata_fields[5].value_end - patchdata_fields[5].value_start; /* rich presence */ ++ ++ len += (patchdata_fields[6].value_end - patchdata_fields[6].value_start) - /* achievements */ ++ patchdata_fields[6].array_size * (80 - sizeof(rc_api_achievement_definition_t)); ++ ++ len += (patchdata_fields[7].value_end - patchdata_fields[7].value_start) - /* leaderboards */ ++ patchdata_fields[7].array_size * (60 - sizeof(rc_api_leaderboard_definition_t)); ++ ++ rc_buffer_reserve(&response->response.buffer, len); ++ /* end estimation */ ++ ++ rc_json_get_optional_string(&response->rich_presence_script, &response->response, &patchdata_fields[5], "RichPresencePatch", ""); ++ if (!response->rich_presence_script) ++ response->rich_presence_script = ""; ++ ++ if (!rc_json_get_required_array(&response->num_achievements, &array_field, &response->response, &patchdata_fields[6], "Achievements")) ++ return RC_MISSING_VALUE; ++ ++ if (response->num_achievements) { ++ response->achievements = (rc_api_achievement_definition_t*)rc_buffer_alloc(&response->response.buffer, response->num_achievements * sizeof(rc_api_achievement_definition_t)); ++ if (!response->achievements) ++ return RC_OUT_OF_MEMORY; ++ ++ result = rc_api_process_fetch_game_data_achievements(&response->response, response->achievements, &array_field); ++ if (result != RC_OK) ++ return result; ++ } ++ ++ if (!rc_json_get_required_array(&response->num_leaderboards, &array_field, &response->response, &patchdata_fields[7], "Leaderboards")) ++ return RC_MISSING_VALUE; ++ ++ if (response->num_leaderboards) { ++ response->leaderboards = (rc_api_leaderboard_definition_t*)rc_buffer_alloc(&response->response.buffer, response->num_leaderboards * sizeof(rc_api_leaderboard_definition_t)); ++ if (!response->leaderboards) ++ return RC_OUT_OF_MEMORY; ++ ++ result = rc_api_process_fetch_game_data_leaderboards(&response->response, response->leaderboards, &array_field); ++ if (result != RC_OK) ++ return result; ++ } ++ ++ return RC_OK; ++} ++ ++void rc_api_destroy_fetch_game_data_response(rc_api_fetch_game_data_response_t* response) { ++ rc_buffer_destroy(&response->response.buffer); ++} ++ ++/* --- Fetch Game Sets --- */ ++ ++int rc_api_init_fetch_game_sets_request(rc_api_request_t* request, const rc_api_fetch_game_sets_request_t* api_params) { ++ return rc_api_init_fetch_game_sets_request_hosted(request, api_params, &g_host); ++} ++ ++int rc_api_init_fetch_game_sets_request_hosted(rc_api_request_t* request, ++ const rc_api_fetch_game_sets_request_t* api_params, ++ const rc_api_host_t* host) { ++ rc_api_url_builder_t builder; ++ ++ rc_api_url_build_dorequest_url(request, host); ++ ++ if (!api_params->game_id && (!api_params->game_hash || !api_params->game_hash[0])) ++ return RC_INVALID_STATE; ++ ++ rc_url_builder_init(&builder, &request->buffer, 48); ++ if (rc_api_url_build_dorequest(&builder, "achievementsets", api_params->username, api_params->api_token)) { ++ if (api_params->game_id) ++ rc_url_builder_append_unum_param(&builder, "g", api_params->game_id); ++ else ++ rc_url_builder_append_str_param(&builder, "m", api_params->game_hash); ++ ++ request->post_data = rc_url_builder_finalize(&builder); ++ request->content_type = RC_CONTENT_TYPE_URLENCODED; ++ } ++ ++ return builder.result; ++} ++ ++static int rc_api_process_fetch_game_sets_achievement_sets(rc_api_fetch_game_sets_response_t* response, ++ rc_api_achievement_set_definition_t* subset, ++ rc_json_field_t* subset_array_field) { ++ rc_json_iterator_t iterator; ++ rc_json_field_t array_field; ++ size_t len; ++ int result; ++ ++ rc_json_field_t subset_fields[] = { ++ RC_JSON_NEW_FIELD("AchievementSetId"), ++ RC_JSON_NEW_FIELD("GameId"), ++ RC_JSON_NEW_FIELD("Title"), ++ RC_JSON_NEW_FIELD("Type"), ++ RC_JSON_NEW_FIELD("ImageIconUrl"), ++ RC_JSON_NEW_FIELD("Achievements"), /* array */ ++ RC_JSON_NEW_FIELD("Leaderboards") /* array */ ++ }; ++ ++ memset(&iterator, 0, sizeof(iterator)); ++ iterator.json = subset_array_field->value_start; ++ iterator.end = subset_array_field->value_end; ++ ++ while (rc_json_get_array_entry_object(subset_fields, sizeof(subset_fields) / sizeof(subset_fields[0]), &iterator)) { ++ if (!rc_json_get_required_unum(&subset->id, &response->response, &subset_fields[0], "AchievementSetId")) ++ return RC_MISSING_VALUE; ++ if (!rc_json_get_required_unum(&subset->game_id, &response->response, &subset_fields[1], "GameId")) ++ return RC_MISSING_VALUE; ++ ++ if (!rc_json_get_required_string(&subset->title, &response->response, &subset_fields[2], "Title")) ++ return RC_MISSING_VALUE; ++ if (!subset->title || !subset->title[0]) ++ subset->title = response->title; ++ ++ if (rc_json_field_string_matches(&subset_fields[3], "core")) ++ subset->type = RC_ACHIEVEMENT_SET_TYPE_CORE; ++ else if (rc_json_field_string_matches(&subset_fields[3], "bonus")) ++ subset->type = RC_ACHIEVEMENT_SET_TYPE_BONUS; ++ else if (rc_json_field_string_matches(&subset_fields[3], "specialty")) ++ subset->type = RC_ACHIEVEMENT_SET_TYPE_SPECIALTY; ++ else if (rc_json_field_string_matches(&subset_fields[3], "exclusive")) ++ subset->type = RC_ACHIEVEMENT_SET_TYPE_EXCLUSIVE; ++ else ++ subset->type = RC_ACHIEVEMENT_SET_TYPE_BONUS; ++ ++ if (rc_json_field_string_matches(&subset_fields[4], response->image_url)) { ++ subset->image_url = response->image_url; ++ subset->image_name = response->image_name; ++ } ++ else { ++ if (!rc_json_get_required_string(&subset->image_url, &response->response, &subset_fields[4], "ImageIconUrl")) ++ return RC_MISSING_VALUE; ++ rc_json_extract_filename(&subset_fields[4]); ++ rc_json_get_optional_string(&subset->image_name, &response->response, &subset_fields[4], "ImageIconUrl", ""); ++ } ++ ++ /* estimate the amount of space necessary to store the achievements, and leaderboards. ++ determine how much space each takes as a string in the JSON, then subtract out the non-data (field names, punctuation) ++ and add space for the structures. */ ++ len = (subset_fields[5].value_end - subset_fields[5].value_start) - /* achievements */ ++ subset_fields[5].array_size * (80 - sizeof(rc_api_achievement_definition_t)); ++ len += (subset_fields[6].value_end - subset_fields[6].value_start) - /* leaderboards */ ++ subset_fields[6].array_size * (60 - sizeof(rc_api_leaderboard_definition_t)); ++ ++ rc_buffer_reserve(&response->response.buffer, len); ++ /* end estimation */ ++ ++ if (!rc_json_get_required_array(&subset->num_achievements, &array_field, &response->response, &subset_fields[5], "Achievements")) ++ return RC_MISSING_VALUE; ++ ++ if (subset->num_achievements) { ++ subset->achievements = (rc_api_achievement_definition_t*)rc_buffer_alloc(&response->response.buffer, subset->num_achievements * sizeof(rc_api_achievement_definition_t)); ++ if (!subset->achievements) ++ return RC_OUT_OF_MEMORY; ++ ++ result = rc_api_process_fetch_game_data_achievements(&response->response, subset->achievements, &array_field); ++ if (result != RC_OK) ++ return result; ++ } ++ ++ if (!rc_json_get_required_array(&subset->num_leaderboards, &array_field, &response->response, &subset_fields[6], "Leaderboards")) ++ return RC_MISSING_VALUE; ++ ++ if (subset->num_leaderboards) { ++ subset->leaderboards = (rc_api_leaderboard_definition_t*)rc_buffer_alloc(&response->response.buffer, subset->num_leaderboards * sizeof(rc_api_leaderboard_definition_t)); ++ if (!subset->leaderboards) ++ return RC_OUT_OF_MEMORY; ++ ++ result = rc_api_process_fetch_game_data_leaderboards(&response->response, subset->leaderboards, &array_field); ++ if (result != RC_OK) ++ return result; ++ } ++ ++ ++subset; ++ } ++ ++ return RC_OK; ++} ++ ++int rc_api_process_fetch_game_sets_server_response(rc_api_fetch_game_sets_response_t* response, const rc_api_server_response_t* server_response) { ++ rc_json_field_t array_field; ++ int result; ++ ++ rc_json_field_t fields[] = { ++ RC_JSON_NEW_FIELD("Success"), ++ RC_JSON_NEW_FIELD("Error"), ++ RC_JSON_NEW_FIELD("Code"), ++ RC_JSON_NEW_FIELD("GameId"), ++ RC_JSON_NEW_FIELD("Title"), ++ RC_JSON_NEW_FIELD("ConsoleId"), ++ RC_JSON_NEW_FIELD("ImageIconUrl"), ++ RC_JSON_NEW_FIELD("RichPresenceGameId"), ++ RC_JSON_NEW_FIELD("RichPresencePatch"), ++ RC_JSON_NEW_FIELD("Sets") /* array */ ++ }; ++ ++ memset(response, 0, sizeof(*response)); ++ rc_buffer_init(&response->response.buffer); ++ ++ result = rc_json_parse_server_response(&response->response, server_response, fields, sizeof(fields) / sizeof(fields[0])); ++ if (result != RC_OK || !response->response.succeeded) ++ return result; ++ ++ if (!rc_json_get_required_unum(&response->id, &response->response, &fields[3], "GameId")) ++ return RC_MISSING_VALUE; ++ if (!rc_json_get_required_string(&response->title, &response->response, &fields[4], "Title")) ++ return RC_MISSING_VALUE; ++ if (!rc_json_get_required_unum(&response->console_id, &response->response, &fields[5], "ConsoleId")) ++ return RC_MISSING_VALUE; ++ ++ rc_json_get_required_string(&response->image_url, &response->response, &fields[6], "ImageIconUrl"); ++ rc_json_extract_filename(&fields[6]); ++ rc_json_get_required_string(&response->image_name, &response->response, &fields[6], "ImageIconUrl"); ++ ++ rc_json_get_optional_unum(&response->session_game_id, &fields[7], "RichPresenceGameId", response->id); ++ ++ rc_json_get_optional_string(&response->rich_presence_script, &response->response, &fields[8], "RichPresencePatch", ""); ++ if (!response->rich_presence_script) ++ response->rich_presence_script = ""; ++ ++ rc_json_get_optional_array(&response->num_sets, &array_field, &fields[9], "Sets"); ++ if (response->num_sets) { ++ response->sets = (rc_api_achievement_set_definition_t*)rc_buffer_alloc(&response->response.buffer, response->num_sets * sizeof(rc_api_achievement_set_definition_t)); ++ if (!response->sets) ++ return RC_OUT_OF_MEMORY; ++ ++ result = rc_api_process_fetch_game_sets_achievement_sets(response, response->sets, &array_field); ++ if (result != RC_OK) ++ return result; ++ } ++ ++ return RC_OK; ++} ++ ++void rc_api_destroy_fetch_game_sets_response(rc_api_fetch_game_sets_response_t* response) { ++ rc_buffer_destroy(&response->response.buffer); ++} ++ ++/* --- Ping --- */ ++ ++int rc_api_init_ping_request(rc_api_request_t* request, const rc_api_ping_request_t* api_params) { ++ return rc_api_init_ping_request_hosted(request, api_params, &g_host); ++} ++ ++int rc_api_init_ping_request_hosted(rc_api_request_t* request, ++ const rc_api_ping_request_t* api_params, ++ const rc_api_host_t* host) { ++ rc_api_url_builder_t builder; ++ ++ rc_api_url_build_dorequest_url(request, host); ++ ++ if (api_params->game_id == 0) ++ return RC_INVALID_STATE; ++ ++ rc_url_builder_init(&builder, &request->buffer, 48); ++ if (rc_api_url_build_dorequest(&builder, "ping", api_params->username, api_params->api_token)) { ++ rc_url_builder_append_unum_param(&builder, "g", api_params->game_id); ++ ++ if (api_params->rich_presence && *api_params->rich_presence) ++ rc_url_builder_append_str_param(&builder, "m", api_params->rich_presence); ++ ++ if (api_params->game_hash && *api_params->game_hash) { ++ rc_url_builder_append_unum_param(&builder, "h", api_params->hardcore); ++ rc_url_builder_append_str_param(&builder, "x", api_params->game_hash); ++ } ++ ++ request->post_data = rc_url_builder_finalize(&builder); ++ request->content_type = RC_CONTENT_TYPE_URLENCODED; ++ } ++ ++ return builder.result; ++} ++ ++int rc_api_process_ping_response(rc_api_ping_response_t* response, const char* server_response) { ++ rc_api_server_response_t response_obj; ++ ++ memset(&response_obj, 0, sizeof(response_obj)); ++ response_obj.body = server_response; ++ response_obj.body_length = rc_json_get_object_string_length(server_response); ++ ++ return rc_api_process_ping_server_response(response, &response_obj); ++} ++ ++int rc_api_process_ping_server_response(rc_api_ping_response_t* response, const rc_api_server_response_t* server_response) { ++ rc_json_field_t fields[] = { ++ RC_JSON_NEW_FIELD("Success"), ++ RC_JSON_NEW_FIELD("Error") ++ }; ++ ++ memset(response, 0, sizeof(*response)); ++ rc_buffer_init(&response->response.buffer); ++ ++ return rc_json_parse_server_response(&response->response, server_response, fields, sizeof(fields) / sizeof(fields[0])); ++} ++ ++void rc_api_destroy_ping_response(rc_api_ping_response_t* response) { ++ rc_buffer_destroy(&response->response.buffer); ++} ++ ++/* --- Award Achievement --- */ ++ ++int rc_api_init_award_achievement_request(rc_api_request_t* request, const rc_api_award_achievement_request_t* api_params) { ++ return rc_api_init_award_achievement_request_hosted(request, api_params, &g_host); ++} ++ ++int rc_api_init_award_achievement_request_hosted(rc_api_request_t* request, ++ const rc_api_award_achievement_request_t* api_params, ++ const rc_api_host_t* host) { ++ rc_api_url_builder_t builder; ++ char buffer[33]; ++ md5_state_t md5; ++ md5_byte_t digest[16]; ++ ++ rc_api_url_build_dorequest_url(request, host); ++ ++ if (api_params->achievement_id == 0) ++ return RC_INVALID_STATE; ++ ++ rc_url_builder_init(&builder, &request->buffer, 96); ++ if (rc_api_url_build_dorequest(&builder, "awardachievement", api_params->username, api_params->api_token)) { ++ rc_url_builder_append_unum_param(&builder, "a", api_params->achievement_id); ++ rc_url_builder_append_unum_param(&builder, "h", api_params->hardcore ? 1 : 0); ++ if (api_params->game_hash && *api_params->game_hash) ++ rc_url_builder_append_str_param(&builder, "m", api_params->game_hash); ++ if (api_params->seconds_since_unlock) ++ rc_url_builder_append_unum_param(&builder, "o", api_params->seconds_since_unlock); ++ ++ /* Evaluate the signature. */ ++ md5_init(&md5); ++ snprintf(buffer, sizeof(buffer), "%u", api_params->achievement_id); ++ md5_append(&md5, (md5_byte_t*)buffer, (int)strlen(buffer)); ++ md5_append(&md5, (md5_byte_t*)api_params->username, (int)strlen(api_params->username)); ++ snprintf(buffer, sizeof(buffer), "%d", api_params->hardcore ? 1 : 0); ++ md5_append(&md5, (md5_byte_t*)buffer, (int)strlen(buffer)); ++ if (api_params->seconds_since_unlock) { ++ /* second achievement id is needed by delegated unlock. including it here allows overloading ++ * the hash generating code on the server */ ++ snprintf(buffer, sizeof(buffer), "%u", api_params->achievement_id); ++ md5_append(&md5, (md5_byte_t*)buffer, (int)strlen(buffer)); ++ snprintf(buffer, sizeof(buffer), "%u", api_params->seconds_since_unlock); ++ md5_append(&md5, (md5_byte_t*)buffer, (int)strlen(buffer)); ++ } ++ md5_finish(&md5, digest); ++ rc_format_md5(buffer, digest); ++ rc_url_builder_append_str_param(&builder, "v", buffer); ++ ++ request->post_data = rc_url_builder_finalize(&builder); ++ request->content_type = RC_CONTENT_TYPE_URLENCODED; ++ } ++ ++ return builder.result; ++} ++ ++int rc_api_process_award_achievement_response(rc_api_award_achievement_response_t* response, const char* server_response) { ++ rc_api_server_response_t response_obj; ++ ++ memset(&response_obj, 0, sizeof(response_obj)); ++ response_obj.body = server_response; ++ response_obj.body_length = rc_json_get_object_string_length(server_response); ++ ++ return rc_api_process_award_achievement_server_response(response, &response_obj); ++} ++ ++int rc_api_process_award_achievement_server_response(rc_api_award_achievement_response_t* response, const rc_api_server_response_t* server_response) { ++ int result; ++ rc_json_field_t fields[] = { ++ RC_JSON_NEW_FIELD("Success"), ++ RC_JSON_NEW_FIELD("Error"), ++ RC_JSON_NEW_FIELD("Score"), ++ RC_JSON_NEW_FIELD("SoftcoreScore"), ++ RC_JSON_NEW_FIELD("AchievementID"), ++ RC_JSON_NEW_FIELD("AchievementsRemaining") ++ }; ++ ++ memset(response, 0, sizeof(*response)); ++ rc_buffer_init(&response->response.buffer); ++ ++ result = rc_json_parse_server_response(&response->response, server_response, fields, sizeof(fields) / sizeof(fields[0])); ++ if (result != RC_OK) ++ return result; ++ ++ if (!response->response.succeeded) { ++ if (response->response.error_message && ++ memcmp(response->response.error_message, "User already has", 16) == 0) { ++ /* not really an error, the achievement is unlocked, just not by the current call. ++ * hardcore: User already has hardcore and regular achievements awarded. ++ * non-hardcore: User already has this achievement awarded. ++ */ ++ response->response.succeeded = 1; ++ } else { ++ return result; ++ } ++ } ++ ++ rc_json_get_optional_unum(&response->new_player_score, &fields[2], "Score", 0); ++ rc_json_get_optional_unum(&response->new_player_score_softcore, &fields[3], "SoftcoreScore", 0); ++ rc_json_get_optional_unum(&response->awarded_achievement_id, &fields[4], "AchievementID", 0); ++ rc_json_get_optional_unum(&response->achievements_remaining, &fields[5], "AchievementsRemaining", (unsigned)-1); ++ ++ return RC_OK; ++} ++ ++void rc_api_destroy_award_achievement_response(rc_api_award_achievement_response_t* response) { ++ rc_buffer_destroy(&response->response.buffer); ++} ++ ++/* --- Submit Leaderboard Entry --- */ ++ ++int rc_api_init_submit_lboard_entry_request(rc_api_request_t* request, const rc_api_submit_lboard_entry_request_t* api_params) { ++ return rc_api_init_submit_lboard_entry_request_hosted(request, api_params, &g_host); ++} ++ ++int rc_api_init_submit_lboard_entry_request_hosted(rc_api_request_t* request, ++ const rc_api_submit_lboard_entry_request_t* api_params, ++ const rc_api_host_t* host) { ++ rc_api_url_builder_t builder; ++ char buffer[33]; ++ md5_state_t md5; ++ md5_byte_t digest[16]; ++ ++ rc_api_url_build_dorequest_url(request, host); ++ ++ if (api_params->leaderboard_id == 0) ++ return RC_INVALID_STATE; ++ ++ rc_url_builder_init(&builder, &request->buffer, 96); ++ if (rc_api_url_build_dorequest(&builder, "submitlbentry", api_params->username, api_params->api_token)) { ++ rc_url_builder_append_unum_param(&builder, "i", api_params->leaderboard_id); ++ rc_url_builder_append_num_param(&builder, "s", api_params->score); ++ ++ if (api_params->game_hash && *api_params->game_hash) ++ rc_url_builder_append_str_param(&builder, "m", api_params->game_hash); ++ ++ if (api_params->seconds_since_completion) ++ rc_url_builder_append_unum_param(&builder, "o", api_params->seconds_since_completion); ++ ++ /* Evaluate the signature. */ ++ md5_init(&md5); ++ snprintf(buffer, sizeof(buffer), "%u", api_params->leaderboard_id); ++ md5_append(&md5, (md5_byte_t*)buffer, (int)strlen(buffer)); ++ md5_append(&md5, (md5_byte_t*)api_params->username, (int)strlen(api_params->username)); ++ snprintf(buffer, sizeof(buffer), "%d", api_params->score); ++ md5_append(&md5, (md5_byte_t*)buffer, (int)strlen(buffer)); ++ if (api_params->seconds_since_completion) { ++ snprintf(buffer, sizeof(buffer), "%u", api_params->seconds_since_completion); ++ md5_append(&md5, (md5_byte_t*)buffer, (int)strlen(buffer)); ++ } ++ md5_finish(&md5, digest); ++ rc_format_md5(buffer, digest); ++ rc_url_builder_append_str_param(&builder, "v", buffer); ++ ++ request->post_data = rc_url_builder_finalize(&builder); ++ request->content_type = RC_CONTENT_TYPE_URLENCODED; ++ } ++ ++ return builder.result; ++} ++ ++int rc_api_process_submit_lboard_entry_response(rc_api_submit_lboard_entry_response_t* response, const char* server_response) { ++ rc_api_server_response_t response_obj; ++ ++ memset(&response_obj, 0, sizeof(response_obj)); ++ response_obj.body = server_response; ++ response_obj.body_length = rc_json_get_object_string_length(server_response); ++ ++ return rc_api_process_submit_lboard_entry_server_response(response, &response_obj); ++} ++ ++int rc_api_process_submit_lboard_entry_server_response(rc_api_submit_lboard_entry_response_t* response, const rc_api_server_response_t* server_response) { ++ rc_api_lboard_entry_t* entry; ++ rc_json_field_t array_field; ++ rc_json_iterator_t iterator; ++ const char* str; ++ int result; ++ ++ rc_json_field_t fields[] = { ++ RC_JSON_NEW_FIELD("Success"), ++ RC_JSON_NEW_FIELD("Error"), ++ RC_JSON_NEW_FIELD("Response") /* nested object */ ++ }; ++ ++ rc_json_field_t response_fields[] = { ++ RC_JSON_NEW_FIELD("Score"), ++ RC_JSON_NEW_FIELD("BestScore"), ++ RC_JSON_NEW_FIELD("RankInfo"), /* nested object */ ++ RC_JSON_NEW_FIELD("TopEntries") /* array */ ++ /* unused fields ++ RC_JSON_NEW_FIELD("LBData"), / * array * / ++ RC_JSON_NEW_FIELD("ScoreFormatted"), ++ RC_JSON_NEW_FIELD("TopEntriesFriends") / * array * / ++ * unused fields */ ++ }; ++ ++ /* unused fields ++ rc_json_field_t lbdata_fields[] = { ++ RC_JSON_NEW_FIELD("Format"), ++ RC_JSON_NEW_FIELD("LeaderboardID"), ++ RC_JSON_NEW_FIELD("GameID"), ++ RC_JSON_NEW_FIELD("Title"), ++ RC_JSON_NEW_FIELD("LowerIsBetter") ++ }; ++ * unused fields */ ++ ++ rc_json_field_t entry_fields[] = { ++ RC_JSON_NEW_FIELD("User"), ++ RC_JSON_NEW_FIELD("Rank"), ++ RC_JSON_NEW_FIELD("Score") ++ /* unused fields ++ RC_JSON_NEW_FIELD("DateSubmitted") ++ * unused fields */ ++ }; ++ ++ rc_json_field_t rank_info_fields[] = { ++ RC_JSON_NEW_FIELD("Rank"), ++ RC_JSON_NEW_FIELD("NumEntries") ++ /* unused fields ++ RC_JSON_NEW_FIELD("LowerIsBetter"), ++ RC_JSON_NEW_FIELD("UserRank") ++ * unused fields */ ++ }; ++ ++ memset(response, 0, sizeof(*response)); ++ rc_buffer_init(&response->response.buffer); ++ ++ result = rc_json_parse_server_response(&response->response, server_response, fields, sizeof(fields) / sizeof(fields[0])); ++ if (result != RC_OK || !response->response.succeeded) ++ return result; ++ ++ if (!rc_json_get_required_object(response_fields, sizeof(response_fields) / sizeof(response_fields[0]), &response->response, &fields[2], "Response")) ++ return RC_MISSING_VALUE; ++ if (!rc_json_get_required_num(&response->submitted_score, &response->response, &response_fields[0], "Score")) ++ return RC_MISSING_VALUE; ++ if (!rc_json_get_required_num(&response->best_score, &response->response, &response_fields[1], "BestScore")) ++ return RC_MISSING_VALUE; ++ ++ if (!rc_json_get_required_object(rank_info_fields, sizeof(rank_info_fields) / sizeof(rank_info_fields[0]), &response->response, &response_fields[2], "RankInfo")) ++ return RC_MISSING_VALUE; ++ if (!rc_json_get_required_unum(&response->new_rank, &response->response, &rank_info_fields[0], "Rank")) ++ return RC_MISSING_VALUE; ++ if (!rc_json_get_required_string(&str, &response->response, &rank_info_fields[1], "NumEntries")) ++ return RC_MISSING_VALUE; ++ response->num_entries = (unsigned)atoi(str); ++ ++ if (!rc_json_get_required_array(&response->num_top_entries, &array_field, &response->response, &response_fields[3], "TopEntries")) ++ return RC_MISSING_VALUE; ++ ++ if (response->num_top_entries) { ++ response->top_entries = (rc_api_lboard_entry_t*)rc_buffer_alloc(&response->response.buffer, response->num_top_entries * sizeof(rc_api_lboard_entry_t)); ++ if (!response->top_entries) ++ return RC_OUT_OF_MEMORY; ++ ++ memset(&iterator, 0, sizeof(iterator)); ++ iterator.json = array_field.value_start; ++ iterator.end = array_field.value_end; ++ ++ entry = response->top_entries; ++ while (rc_json_get_array_entry_object(entry_fields, sizeof(entry_fields) / sizeof(entry_fields[0]), &iterator)) { ++ if (!rc_json_get_required_string(&entry->username, &response->response, &entry_fields[0], "User")) ++ return RC_MISSING_VALUE; ++ ++ if (!rc_json_get_required_unum(&entry->rank, &response->response, &entry_fields[1], "Rank")) ++ return RC_MISSING_VALUE; ++ ++ if (!rc_json_get_required_num(&entry->score, &response->response, &entry_fields[2], "Score")) ++ return RC_MISSING_VALUE; ++ ++ ++entry; ++ } ++ } ++ ++ return RC_OK; ++} ++ ++void rc_api_destroy_submit_lboard_entry_response(rc_api_submit_lboard_entry_response_t* response) { ++ rc_buffer_destroy(&response->response.buffer); ++} +diff -rupbN melonDS.orig/src/rcheevos/src/rapi/rc_api_user.c melonDS.ra/src/rcheevos/src/rapi/rc_api_user.c +--- melonDS.orig/src/rcheevos/src/rapi/rc_api_user.c 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rapi/rc_api_user.c 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,483 @@ ++#include "rc_api_user.h" ++#include "rc_api_common.h" ++#include "rc_api_runtime.h" ++#include "rc_consoles.h" ++ ++#include "../rc_version.h" ++ ++#include ++#include ++ ++/* --- Login --- */ ++ ++int rc_api_init_login_request(rc_api_request_t* request, const rc_api_login_request_t* api_params) { ++ return rc_api_init_login_request_hosted(request, api_params, &g_host); ++} ++ ++int rc_api_init_login_request_hosted(rc_api_request_t* request, ++ const rc_api_login_request_t* api_params, ++ const rc_api_host_t* host) { ++ rc_api_url_builder_t builder; ++ ++ rc_api_url_build_dorequest_url(request, host); ++ ++ if (!api_params->username || !*api_params->username) ++ return RC_INVALID_STATE; ++ ++ rc_url_builder_init(&builder, &request->buffer, 48); ++ rc_url_builder_append_str_param(&builder, "r", "login2"); ++ rc_url_builder_append_str_param(&builder, "u", api_params->username); ++ ++ if (api_params->password && api_params->password[0]) ++ rc_url_builder_append_str_param(&builder, "p", api_params->password); ++ else if (api_params->api_token && api_params->api_token[0]) ++ rc_url_builder_append_str_param(&builder, "t", api_params->api_token); ++ else ++ return RC_INVALID_STATE; ++ ++ request->post_data = rc_url_builder_finalize(&builder); ++ request->content_type = RC_CONTENT_TYPE_URLENCODED; ++ ++ return builder.result; ++} ++ ++int rc_api_process_login_response(rc_api_login_response_t* response, const char* server_response) { ++ rc_api_server_response_t response_obj; ++ ++ memset(&response_obj, 0, sizeof(response_obj)); ++ response_obj.body = server_response; ++ response_obj.body_length = rc_json_get_object_string_length(server_response); ++ ++ return rc_api_process_login_server_response(response, &response_obj); ++} ++ ++int rc_api_process_login_server_response(rc_api_login_response_t* response, const rc_api_server_response_t* server_response) { ++ int result; ++ rc_json_field_t fields[] = { ++ RC_JSON_NEW_FIELD("Success"), ++ RC_JSON_NEW_FIELD("Error"), ++ RC_JSON_NEW_FIELD("Code"), ++ RC_JSON_NEW_FIELD("User"), ++ RC_JSON_NEW_FIELD("Token"), ++ RC_JSON_NEW_FIELD("Score"), ++ RC_JSON_NEW_FIELD("SoftcoreScore"), ++ RC_JSON_NEW_FIELD("Messages"), ++ RC_JSON_NEW_FIELD("AvatarUrl") ++ }; ++ ++ memset(response, 0, sizeof(*response)); ++ rc_buffer_init(&response->response.buffer); ++ ++ result = rc_json_parse_server_response(&response->response, server_response, fields, sizeof(fields) / sizeof(fields[0])); ++ if (result != RC_OK || !response->response.succeeded) ++ return result; ++ ++ if (!rc_json_get_required_string(&response->username, &response->response, &fields[3], "User")) ++ return RC_MISSING_VALUE; ++ if (!rc_json_get_required_string(&response->api_token, &response->response, &fields[4], "Token")) ++ return RC_MISSING_VALUE; ++ ++ rc_json_get_optional_unum(&response->score, &fields[5], "Score", 0); ++ rc_json_get_optional_unum(&response->score_softcore, &fields[6], "SoftcoreScore", 0); ++ rc_json_get_optional_unum(&response->num_unread_messages, &fields[7], "Messages", 0); ++ ++ /* For the highest level of backwards compatibility, we have decided to just send the ++ * display_name back to the client as the "case-corrected username", and allow it to ++ * be used as the Username field for the other APIs. */ ++ response->display_name = response->username; ++ ++ rc_json_get_optional_string(&response->avatar_url, &response->response, &fields[8], "AvatarUrl", NULL); ++ if (!response->avatar_url) ++ response->avatar_url = rc_api_build_avatar_url(&response->response.buffer, RC_IMAGE_TYPE_USER, response->username); ++ ++ return RC_OK; ++} ++ ++void rc_api_destroy_login_response(rc_api_login_response_t* response) { ++ rc_buffer_destroy(&response->response.buffer); ++} ++ ++/* --- Start Session --- */ ++ ++int rc_api_init_start_session_request(rc_api_request_t* request, const rc_api_start_session_request_t* api_params) { ++ return rc_api_init_start_session_request_hosted(request, api_params, &g_host); ++} ++ ++int rc_api_init_start_session_request_hosted(rc_api_request_t* request, ++ const rc_api_start_session_request_t* api_params, ++ const rc_api_host_t* host) { ++ rc_api_url_builder_t builder; ++ ++ rc_api_url_build_dorequest_url(request, host); ++ ++ if (api_params->game_id == 0) ++ return RC_INVALID_STATE; ++ ++ rc_url_builder_init(&builder, &request->buffer, 48); ++ if (rc_api_url_build_dorequest(&builder, "startsession", api_params->username, api_params->api_token)) { ++ rc_url_builder_append_unum_param(&builder, "g", api_params->game_id); ++ ++ if (api_params->game_hash && *api_params->game_hash) { ++ rc_url_builder_append_unum_param(&builder, "h", api_params->hardcore); ++ rc_url_builder_append_str_param(&builder, "m", api_params->game_hash); ++ } ++ ++ rc_url_builder_append_str_param(&builder, "l", RCHEEVOS_VERSION_STRING); ++ ++ request->post_data = rc_url_builder_finalize(&builder); ++ request->content_type = RC_CONTENT_TYPE_URLENCODED; ++ } ++ ++ return builder.result; ++} ++ ++int rc_api_process_start_session_response(rc_api_start_session_response_t* response, const char* server_response) { ++ rc_api_server_response_t response_obj; ++ ++ memset(&response_obj, 0, sizeof(response_obj)); ++ response_obj.body = server_response; ++ response_obj.body_length = rc_json_get_object_string_length(server_response); ++ ++ return rc_api_process_start_session_server_response(response, &response_obj); ++} ++ ++int rc_api_process_start_session_server_response(rc_api_start_session_response_t* response, const rc_api_server_response_t* server_response) { ++ rc_api_unlock_entry_t* unlock; ++ rc_json_field_t array_field; ++ rc_json_iterator_t iterator; ++ uint32_t timet; ++ int result; ++ ++ rc_json_field_t fields[] = { ++ RC_JSON_NEW_FIELD("Success"), ++ RC_JSON_NEW_FIELD("Error"), ++ RC_JSON_NEW_FIELD("Unlocks"), ++ RC_JSON_NEW_FIELD("HardcoreUnlocks"), ++ RC_JSON_NEW_FIELD("ServerNow") ++ }; ++ ++ rc_json_field_t unlock_entry_fields[] = { ++ RC_JSON_NEW_FIELD("ID"), ++ RC_JSON_NEW_FIELD("When") ++ }; ++ ++ memset(response, 0, sizeof(*response)); ++ rc_buffer_init(&response->response.buffer); ++ ++ result = rc_json_parse_server_response(&response->response, server_response, fields, sizeof(fields) / sizeof(fields[0])); ++ if (result != RC_OK || !response->response.succeeded) ++ return result; ++ ++ if (rc_json_get_optional_array(&response->num_unlocks, &array_field, &fields[2], "Unlocks") && response->num_unlocks) { ++ response->unlocks = (rc_api_unlock_entry_t*)rc_buffer_alloc(&response->response.buffer, response->num_unlocks * sizeof(rc_api_unlock_entry_t)); ++ if (!response->unlocks) ++ return RC_OUT_OF_MEMORY; ++ ++ memset(&iterator, 0, sizeof(iterator)); ++ iterator.json = array_field.value_start; ++ iterator.end = array_field.value_end; ++ ++ unlock = response->unlocks; ++ while (rc_json_get_array_entry_object(unlock_entry_fields, sizeof(unlock_entry_fields) / sizeof(unlock_entry_fields[0]), &iterator)) { ++ if (!rc_json_get_required_unum(&unlock->achievement_id, &response->response, &unlock_entry_fields[0], "ID")) ++ return RC_MISSING_VALUE; ++ if (!rc_json_get_required_unum(&timet, &response->response, &unlock_entry_fields[1], "When")) ++ return RC_MISSING_VALUE; ++ unlock->when = (time_t)timet; ++ ++ ++unlock; ++ } ++ } ++ ++ if (rc_json_get_optional_array(&response->num_hardcore_unlocks, &array_field, &fields[3], "HardcoreUnlocks") && response->num_hardcore_unlocks) { ++ response->hardcore_unlocks = (rc_api_unlock_entry_t*)rc_buffer_alloc(&response->response.buffer, response->num_hardcore_unlocks * sizeof(rc_api_unlock_entry_t)); ++ if (!response->hardcore_unlocks) ++ return RC_OUT_OF_MEMORY; ++ ++ memset(&iterator, 0, sizeof(iterator)); ++ iterator.json = array_field.value_start; ++ iterator.end = array_field.value_end; ++ ++ unlock = response->hardcore_unlocks; ++ while (rc_json_get_array_entry_object(unlock_entry_fields, sizeof(unlock_entry_fields) / sizeof(unlock_entry_fields[0]), &iterator)) { ++ if (!rc_json_get_required_unum(&unlock->achievement_id, &response->response, &unlock_entry_fields[0], "ID")) ++ return RC_MISSING_VALUE; ++ if (!rc_json_get_required_unum(&timet, &response->response, &unlock_entry_fields[1], "When")) ++ return RC_MISSING_VALUE; ++ unlock->when = (time_t)timet; ++ ++ ++unlock; ++ } ++ } ++ ++ rc_json_get_optional_unum(&timet, &fields[4], "ServerNow", 0); ++ response->server_now = (time_t)timet; ++ ++ return RC_OK; ++} ++ ++void rc_api_destroy_start_session_response(rc_api_start_session_response_t* response) { ++ rc_buffer_destroy(&response->response.buffer); ++} ++ ++/* --- Fetch User Unlocks --- */ ++ ++int rc_api_init_fetch_user_unlocks_request(rc_api_request_t* request, const rc_api_fetch_user_unlocks_request_t* api_params) { ++ return rc_api_init_fetch_user_unlocks_request_hosted(request, api_params, &g_host); ++} ++ ++int rc_api_init_fetch_user_unlocks_request_hosted(rc_api_request_t* request, ++ const rc_api_fetch_user_unlocks_request_t* api_params, ++ const rc_api_host_t* host) { ++ rc_api_url_builder_t builder; ++ ++ rc_api_url_build_dorequest_url(request, host); ++ ++ rc_url_builder_init(&builder, &request->buffer, 48); ++ if (rc_api_url_build_dorequest(&builder, "unlocks", api_params->username, api_params->api_token)) { ++ rc_url_builder_append_unum_param(&builder, "g", api_params->game_id); ++ rc_url_builder_append_unum_param(&builder, "h", api_params->hardcore ? 1 : 0); ++ request->post_data = rc_url_builder_finalize(&builder); ++ request->content_type = RC_CONTENT_TYPE_URLENCODED; ++ } ++ ++ return builder.result; ++} ++ ++int rc_api_process_fetch_user_unlocks_response(rc_api_fetch_user_unlocks_response_t* response, const char* server_response) { ++ rc_api_server_response_t response_obj; ++ ++ memset(&response_obj, 0, sizeof(response_obj)); ++ response_obj.body = server_response; ++ response_obj.body_length = rc_json_get_object_string_length(server_response); ++ ++ return rc_api_process_fetch_user_unlocks_server_response(response, &response_obj); ++} ++ ++int rc_api_process_fetch_user_unlocks_server_response(rc_api_fetch_user_unlocks_response_t* response, const rc_api_server_response_t* server_response) { ++ int result; ++ rc_json_field_t fields[] = { ++ RC_JSON_NEW_FIELD("Success"), ++ RC_JSON_NEW_FIELD("Error"), ++ RC_JSON_NEW_FIELD("UserUnlocks") ++ /* unused fields ++ RC_JSON_NEW_FIELD("GameID"), ++ RC_JSON_NEW_FIELD("HardcoreMode") ++ * unused fields */ ++ }; ++ ++ memset(response, 0, sizeof(*response)); ++ rc_buffer_init(&response->response.buffer); ++ ++ result = rc_json_parse_server_response(&response->response, server_response, fields, sizeof(fields) / sizeof(fields[0])); ++ if (result != RC_OK || !response->response.succeeded) ++ return result; ++ ++ result = rc_json_get_required_unum_array(&response->achievement_ids, &response->num_achievement_ids, &response->response, &fields[2], "UserUnlocks"); ++ return result; ++} ++ ++void rc_api_destroy_fetch_user_unlocks_response(rc_api_fetch_user_unlocks_response_t* response) { ++ rc_buffer_destroy(&response->response.buffer); ++} ++ ++/* --- Fetch Followed Users --- */ ++ ++int rc_api_init_fetch_followed_users_request(rc_api_request_t* request, const rc_api_fetch_followed_users_request_t* api_params) { ++ return rc_api_init_fetch_followed_users_request_hosted(request, api_params, &g_host); ++} ++ ++int rc_api_init_fetch_followed_users_request_hosted(rc_api_request_t* request, ++ const rc_api_fetch_followed_users_request_t* api_params, ++ const rc_api_host_t* host) { ++ rc_api_url_builder_t builder; ++ ++ rc_api_url_build_dorequest_url(request, host); ++ ++ rc_url_builder_init(&builder, &request->buffer, 48); ++ if (rc_api_url_build_dorequest(&builder, "getfriendlist", api_params->username, api_params->api_token)) { ++ request->post_data = rc_url_builder_finalize(&builder); ++ request->content_type = RC_CONTENT_TYPE_URLENCODED; ++ } ++ ++ return builder.result; ++} ++ ++int rc_api_process_fetch_followed_users_server_response(rc_api_fetch_followed_users_response_t* response, const rc_api_server_response_t* server_response) { ++ rc_json_field_t array_field; ++ rc_json_iterator_t iterator; ++ rc_api_followed_user_t* user; ++ uint32_t timet; ++ int result; ++ rc_json_field_t fields[] = { ++ RC_JSON_NEW_FIELD("Success"), ++ RC_JSON_NEW_FIELD("Error"), ++ RC_JSON_NEW_FIELD("Friends") ++ }; ++ ++ rc_json_field_t followed_user_entry_fields[] = { ++ RC_JSON_NEW_FIELD("Friend"), ++ RC_JSON_NEW_FIELD("AvatarUrl"), ++ RC_JSON_NEW_FIELD("RAPoints"), ++ RC_JSON_NEW_FIELD("LastSeen"), ++ RC_JSON_NEW_FIELD("LastSeenTime"), ++ RC_JSON_NEW_FIELD("LastGameId"), ++ RC_JSON_NEW_FIELD("LastGameTitle"), ++ RC_JSON_NEW_FIELD("LastGameIconUrl"), ++ }; ++ ++ memset(response, 0, sizeof(*response)); ++ rc_buffer_init(&response->response.buffer); ++ ++ result = rc_json_parse_server_response(&response->response, server_response, fields, sizeof(fields) / sizeof(fields[0])); ++ if (result != RC_OK || !response->response.succeeded) ++ return result; ++ ++ if (!rc_json_get_required_array(&response->num_users, &array_field, &response->response, &fields[2], "Friends")) ++ return RC_MISSING_VALUE; ++ ++ if (response->num_users) { ++ response->users = (rc_api_followed_user_t*)rc_buffer_alloc(&response->response.buffer, response->num_users * sizeof(rc_api_followed_user_t)); ++ if (!response->users) ++ return RC_OUT_OF_MEMORY; ++ ++ memset(&iterator, 0, sizeof(iterator)); ++ iterator.json = array_field.value_start; ++ iterator.end = array_field.value_end; ++ ++ user = response->users; ++ while (rc_json_get_array_entry_object(followed_user_entry_fields, sizeof(followed_user_entry_fields) / sizeof(followed_user_entry_fields[0]), &iterator)) { ++ if (!rc_json_get_required_string(&user->display_name, &response->response, &followed_user_entry_fields[0], "Friend")) ++ return RC_MISSING_VALUE; ++ if (!rc_json_get_required_string(&user->avatar_url, &response->response, &followed_user_entry_fields[1], "AvatarUrl")) ++ return RC_MISSING_VALUE; ++ if (!rc_json_get_required_unum(&user->score, &response->response, &followed_user_entry_fields[2], "RAPoints")) ++ return RC_MISSING_VALUE; ++ ++ rc_json_get_optional_string(&user->recent_activity.description, &response->response, &followed_user_entry_fields[3], "LastSeen", NULL); ++ ++ rc_json_get_optional_unum(&timet, &followed_user_entry_fields[4], "LastSeenTime", 0); ++ user->recent_activity.when = (time_t)timet; ++ ++ rc_json_get_optional_unum(&user->recent_activity.context_id, &followed_user_entry_fields[5], "LastGameId", 0); ++ rc_json_get_optional_string(&user->recent_activity.context, &response->response, &followed_user_entry_fields[6], "LastGameTitle", NULL); ++ rc_json_get_optional_string(&user->recent_activity.context_image_url, &response->response, &followed_user_entry_fields[7], "LastGameIconUrl", NULL); ++ ++ ++user; ++ } ++ } ++ ++ return RC_OK; ++} ++ ++void rc_api_destroy_fetch_followed_users_response(rc_api_fetch_followed_users_response_t* response) { ++ rc_buffer_destroy(&response->response.buffer); ++} ++ ++/* --- Fetch All Progress --- */ ++ ++int rc_api_init_fetch_all_user_progress_request(rc_api_request_t* request, ++ const rc_api_fetch_all_user_progress_request_t* api_params) ++{ ++ return rc_api_init_fetch_all_user_progress_request_hosted(request, api_params, &g_host); ++} ++ ++int rc_api_init_fetch_all_user_progress_request_hosted(rc_api_request_t* request, ++ const rc_api_fetch_all_user_progress_request_t* api_params, ++ const rc_api_host_t* host) ++{ ++ rc_api_url_builder_t builder; ++ ++ rc_api_url_build_dorequest_url(request, host); ++ ++ if (api_params->console_id == RC_CONSOLE_UNKNOWN) ++ return RC_INVALID_STATE; ++ ++ rc_url_builder_init(&builder, &request->buffer, 48); ++ if (rc_api_url_build_dorequest(&builder, "allprogress", api_params->username, api_params->api_token)) ++ { ++ rc_url_builder_append_unum_param(&builder, "c", api_params->console_id); ++ request->post_data = rc_url_builder_finalize(&builder); ++ request->content_type = RC_CONTENT_TYPE_URLENCODED; ++ } ++ ++ return builder.result; ++} ++ ++int rc_api_process_fetch_all_user_progress_server_response(rc_api_fetch_all_user_progress_response_t* response, ++ const rc_api_server_response_t* server_response) ++{ ++ rc_api_all_user_progress_entry_t* entry; ++ int result; ++ ++ rc_json_field_t fields[] = { ++ RC_JSON_NEW_FIELD("Success"), ++ RC_JSON_NEW_FIELD("Error"), ++ RC_JSON_NEW_FIELD("Response"), ++ }; ++ ++ rc_json_field_t entry_fields[] = { ++ RC_JSON_NEW_FIELD("Achievements"), ++ RC_JSON_NEW_FIELD("Unlocked"), ++ RC_JSON_NEW_FIELD("UnlockedHardcore"), ++ }; ++ ++ memset(response, 0, sizeof(*response)); ++ rc_buffer_init(&response->response.buffer); ++ ++ result = ++ rc_json_parse_server_response(&response->response, server_response, fields, sizeof(fields) / sizeof(fields[0])); ++ if (result != RC_OK || !response->response.succeeded) ++ return result; ++ ++ if (!fields[2].value_start) { ++ /* call rc_json_get_required_object to generate the error message */ ++ rc_json_get_required_object(NULL, 0, &response->response, &fields[2], "Response"); ++ return RC_MISSING_VALUE; ++ } ++ ++ response->num_entries = fields[2].array_size; ++ ++ if (response->num_entries > 0) { ++ rc_json_iterator_t iterator; ++ rc_json_field_t field; ++ char* end; ++ ++ rc_buffer_reserve(&response->response.buffer, response->num_entries * sizeof(rc_api_all_user_progress_entry_t)); ++ ++ response->entries = (rc_api_all_user_progress_entry_t*)rc_buffer_alloc( ++ &response->response.buffer, response->num_entries * sizeof(rc_api_all_user_progress_entry_t)); ++ if (!response->entries) ++ return RC_OUT_OF_MEMORY; ++ ++ memset(&iterator, 0, sizeof(iterator)); ++ iterator.json = fields[2].value_start; ++ iterator.end = fields[2].value_end; ++ ++ entry = response->entries; ++ while (rc_json_get_next_object_field(&iterator, &field)) ++ { ++ entry->game_id = strtol(field.name, &end, 10); ++ ++ field.name = ""; ++ if (!rc_json_get_required_object(entry_fields, sizeof(entry_fields) / sizeof(entry_fields[0]), ++ &response->response, &field, "")) ++ { ++ return RC_MISSING_VALUE; ++ } ++ ++ rc_json_get_optional_unum(&entry->num_achievements, &entry_fields[0], "Achievements", 0); ++ rc_json_get_optional_unum(&entry->num_unlocked_achievements, &entry_fields[1], "Unlocked", 0); ++ rc_json_get_optional_unum(&entry->num_unlocked_achievements_hardcore, &entry_fields[2], "UnlockedHardcore", 0); ++ ++ ++entry; ++ } ++ } ++ ++ return RC_OK; ++} ++ ++void rc_api_destroy_fetch_all_user_progress_response(rc_api_fetch_all_user_progress_response_t* response) ++{ ++ rc_buffer_destroy(&response->response.buffer); ++} +diff -rupbN melonDS.orig/src/rcheevos/src/rc_client.c melonDS.ra/src/rcheevos/src/rc_client.c +--- melonDS.orig/src/rcheevos/src/rc_client.c 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rc_client.c 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,6775 @@ ++#include "rc_client_internal.h" ++ ++#include "rc_api_info.h" ++#include "rc_api_runtime.h" ++#include "rc_api_user.h" ++#include "rc_consoles.h" ++#include "rc_hash.h" ++#include "rc_version.h" ++ ++#include "rapi/rc_api_common.h" ++ ++#include "rcheevos/rc_internal.h" ++ ++#include ++ ++#ifdef _WIN32 ++#define WIN32_LEAN_AND_MEAN ++#include ++#include ++#else ++#include ++#endif ++ ++#define RC_CLIENT_UNKNOWN_GAME_ID (uint32_t)-1 ++#define RC_CLIENT_RECENT_UNLOCK_DELAY_SECONDS (10 * 60) /* ten minutes */ ++ ++#define RC_MINIMUM_UNPAUSED_FRAMES 20 ++#define RC_PAUSE_DECAY_MULTIPLIER 4 ++ ++enum { ++ RC_CLIENT_ASYNC_NOT_ABORTED = 0, ++ RC_CLIENT_ASYNC_ABORTED = 1, ++ RC_CLIENT_ASYNC_DESTROYED = 2 ++}; ++ ++typedef struct rc_client_generic_callback_data_t { ++ rc_client_t* client; ++ rc_client_callback_t callback; ++ void* callback_userdata; ++ rc_client_async_handle_t async_handle; ++} rc_client_generic_callback_data_t; ++ ++typedef struct rc_client_pending_media_t ++{ ++#ifdef RC_CLIENT_SUPPORTS_HASH ++ const char* file_path; ++ uint8_t* data; ++ size_t data_size; ++#endif ++ const char* hash; ++ rc_client_callback_t callback; ++ void* callback_userdata; ++} rc_client_pending_media_t; ++ ++typedef struct rc_client_load_state_t ++{ ++ rc_client_t* client; ++ rc_client_callback_t callback; ++ void* callback_userdata; ++ ++ rc_client_game_info_t* game; ++ rc_client_subset_info_t* subset; ++ rc_client_game_hash_t* hash; ++ ++#ifdef RC_CLIENT_SUPPORTS_HASH ++ rc_hash_iterator_t hash_iterator; ++ rc_client_game_hash_t* tried_hashes[4]; ++#endif ++ rc_client_pending_media_t* pending_media; ++ ++ rc_api_start_session_response_t *start_session_response; ++ ++ rc_client_async_handle_t async_handle; ++ ++ uint8_t progress; ++ uint8_t outstanding_requests; ++#ifdef RC_CLIENT_SUPPORTS_HASH ++ uint8_t hash_console_id; ++#endif ++} rc_client_load_state_t; ++ ++static void rc_client_process_resolved_hash(rc_client_load_state_t* load_state); ++static void rc_client_begin_fetch_game_sets(rc_client_load_state_t* callback_data); ++static void rc_client_hide_progress_tracker(rc_client_t* client, rc_client_game_info_t* game); ++static void rc_client_load_error(rc_client_load_state_t* load_state, int result, const char* error_message); ++static rc_client_async_handle_t* rc_client_load_game(rc_client_load_state_t* load_state, const char* hash, const char* file_path); ++static void rc_client_ping(rc_client_scheduled_callback_data_t* callback_data, rc_client_t* client, rc_clock_t now); ++static void rc_client_raise_leaderboard_events(rc_client_t* client, rc_client_subset_info_t* subset); ++static void rc_client_raise_pending_events(rc_client_t* client, rc_client_game_info_t* game); ++static void rc_client_reschedule_callback(rc_client_t* client, rc_client_scheduled_callback_data_t* callback, rc_clock_t when); ++static void rc_client_award_achievement_retry(rc_client_scheduled_callback_data_t* callback_data, rc_client_t* client, rc_clock_t now); ++static int rc_client_is_award_achievement_pending(const rc_client_t* client, uint32_t achievement_id); ++static void rc_client_submit_leaderboard_entry_retry(rc_client_scheduled_callback_data_t* callback_data, rc_client_t* client, rc_clock_t now); ++ ++/* ===== natvis extensions ===== */ ++ ++typedef struct __rc_client_achievement_state_enum_t { uint8_t value; } __rc_client_achievement_state_enum_t; ++typedef struct __rc_client_achievement_category_enum_t { uint8_t value; } __rc_client_achievement_category_enum_t; ++typedef struct __rc_client_achievement_type_enum_t { uint8_t value; } __rc_client_achievement_type_enum_t; ++typedef struct __rc_client_achievement_bucket_enum_t { uint8_t value; } __rc_client_achievement_bucket_enum_t; ++typedef struct __rc_client_achievement_unlocked_enum_t { uint8_t value; } __rc_client_achievement_unlocked_enum_t; ++typedef struct __rc_client_leaderboard_state_enum_t { uint8_t value; } __rc_client_leaderboard_state_enum_t; ++typedef struct __rc_client_leaderboard_format_enum_t { uint8_t value; } __rc_client_leaderboard_format_enum_t; ++typedef struct __rc_client_log_level_enum_t { uint8_t value; } __rc_client_log_level_enum_t; ++typedef struct __rc_client_event_type_enum_t { uint8_t value; } __rc_client_event_type_enum_t; ++typedef struct __rc_client_load_game_state_enum_t { uint8_t value; } __rc_client_load_game_state_enum_t; ++typedef struct __rc_client_user_state_enum_t { uint8_t value; } __rc_client_user_state_enum_t; ++typedef struct __rc_client_mastery_state_enum_t { uint8_t value; } __rc_client_mastery_state_enum_t; ++typedef struct __rc_client_spectator_mode_enum_t { uint8_t value; } __rc_client_spectator_mode_enum_t; ++typedef struct __rc_client_disconnect_enum_t { uint8_t value; } __rc_client_disconnect_enum_t; ++typedef struct __rc_client_leaderboard_tracker_list_t { rc_client_leaderboard_tracker_info_t* first; } __rc_client_leaderboard_tracker_list_t; ++typedef struct __rc_client_subset_info_list_t { rc_client_subset_info_t* first; } __rc_client_subset_info_list_t; ++typedef struct __rc_client_media_hash_list_t { rc_client_media_hash_t* first; } __rc_client_media_hash_list_t; ++typedef struct __rc_client_subset_info_achievements_list_t { rc_client_subset_info_t info; } __rc_client_subset_info_achievements_list_t; ++typedef struct __rc_client_subset_info_leaderboards_list_t { rc_client_subset_info_t info; } __rc_client_subset_info_leaderboards_list_t; ++typedef struct __rc_client_scheduled_callback_list_t { rc_client_state_t state; } __rc_client_scheduled_callback_list_t; ++typedef struct __rc_client_game_hash_list_t { rc_client_t client; } __rc_client_game_hash_list_t; ++ ++static void rc_client_natvis_helper(const rc_client_event_t* event, rc_client_t* client) ++{ ++ struct natvis_extensions { ++ __rc_client_achievement_state_enum_t achievement_state; ++ __rc_client_achievement_category_enum_t achievement_category; ++ __rc_client_achievement_type_enum_t achievement_type; ++ __rc_client_achievement_bucket_enum_t achievement_bucket; ++ __rc_client_achievement_unlocked_enum_t achievement_unlocked; ++ __rc_client_leaderboard_state_enum_t leaderboard_state; ++ __rc_client_leaderboard_format_enum_t leaderboard_format; ++ __rc_client_log_level_enum_t log_level; ++ __rc_client_event_type_enum_t event_type; ++ __rc_client_load_game_state_enum_t load_game_state; ++ __rc_client_user_state_enum_t user_state; ++ __rc_client_mastery_state_enum_t mastery_state; ++ __rc_client_spectator_mode_enum_t spectator_mode; ++ __rc_client_disconnect_enum_t disconnect; ++ __rc_client_leaderboard_tracker_list_t leaderboard_tracker_list; ++ __rc_client_subset_info_list_t subset_info_list; ++ __rc_client_media_hash_list_t media_hash_list; ++ __rc_client_subset_info_achievements_list_t subset_info_achievements_list; ++ __rc_client_subset_info_leaderboards_list_t subset_info_leaderboards_list; ++ __rc_client_scheduled_callback_list_t scheduled_callback_list; ++ __rc_client_game_hash_list_t client_game_hash_list; ++ } natvis; ++ ++ memset(&natvis, 0, sizeof(natvis)); ++ (void)event; ++ (void)client; ++ ++ /* this code should never be executed. it just ensures these constants get defined for ++ * the natvis VisualStudio extension as they're not used directly in the code. */ ++ natvis.achievement_type.value = RC_CLIENT_ACHIEVEMENT_TYPE_STANDARD; ++ natvis.achievement_type.value = RC_CLIENT_ACHIEVEMENT_TYPE_MISSABLE; ++ natvis.achievement_type.value = RC_CLIENT_ACHIEVEMENT_TYPE_PROGRESSION; ++ natvis.achievement_type.value = RC_CLIENT_ACHIEVEMENT_TYPE_WIN; ++ natvis.achievement_category.value = RC_CLIENT_ACHIEVEMENT_CATEGORY_NONE; ++ natvis.event_type.value = RC_CLIENT_EVENT_TYPE_NONE; ++} ++ ++/* ===== Construction/Destruction ===== */ ++ ++static void rc_client_dummy_event_handler(const rc_client_event_t* event, rc_client_t* client) ++{ ++ (void)event; ++ (void)client; ++} ++ ++rc_client_t* rc_client_create(rc_client_read_memory_func_t read_memory_function, rc_client_server_call_t server_call_function) ++{ ++ rc_client_t* client = (rc_client_t*)calloc(1, sizeof(rc_client_t)); ++ if (!client) ++ return NULL; ++ ++ client->state.hardcore = 1; ++ client->state.required_unpaused_frames = RC_MINIMUM_UNPAUSED_FRAMES; ++ client->state.allow_background_memory_reads = 1; ++ ++ client->callbacks.read_memory = read_memory_function; ++ client->callbacks.server_call = server_call_function; ++ client->callbacks.event_handler = rc_client_natvis_helper; ++ client->callbacks.event_handler = rc_client_dummy_event_handler; ++ rc_client_set_legacy_peek(client, RC_CLIENT_LEGACY_PEEK_AUTO); ++ rc_client_set_get_time_millisecs_function(client, NULL); ++ ++ rc_mutex_init(&client->state.mutex); ++ ++ rc_buffer_init(&client->state.buffer); ++ ++ return client; ++} ++ ++void rc_client_destroy(rc_client_t* client) ++{ ++ if (!client) ++ return; ++ ++ rc_mutex_lock(&client->state.mutex); ++ { ++ size_t i; ++ for (i = 0; i < sizeof(client->state.async_handles) / sizeof(client->state.async_handles[0]); ++i) { ++ if (client->state.async_handles[i]) ++ client->state.async_handles[i]->aborted = RC_CLIENT_ASYNC_DESTROYED; ++ } ++ ++ if (client->state.load) { ++ client->state.load->async_handle.aborted = RC_CLIENT_ASYNC_DESTROYED; ++ client->state.load = NULL; ++ } ++ } ++ rc_mutex_unlock(&client->state.mutex); ++ ++ rc_client_unload_game(client); ++ ++#ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION ++ rc_client_unload_raintegration(client); ++#endif ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->destroy) ++ client->state.external_client->destroy(); ++#endif ++ ++ rc_buffer_destroy(&client->state.buffer); ++ ++ rc_mutex_destroy(&client->state.mutex); ++ ++ free(client); ++} ++ ++/* ===== Logging ===== */ ++ ++void rc_client_log_message(const rc_client_t* client, const char* message) ++{ ++ if (client->callbacks.log_call) ++ client->callbacks.log_call(message, client); ++} ++ ++static void rc_client_log_message_va(const rc_client_t* client, const char* format, va_list args) ++{ ++ if (client->callbacks.log_call) { ++ char buffer[2048]; ++ ++#ifdef __STDC_SECURE_LIB__ ++ vsprintf_s(buffer, sizeof(buffer), format, args); ++#elif __STDC_VERSION__ >= 199901L /* vsnprintf requires c99 */ ++ vsnprintf(buffer, sizeof(buffer), format, args); ++#else /* c89 doesn't have a size-limited vsprintf function - assume the buffer is large enough */ ++ vsprintf(buffer, format, args); ++#endif ++ ++ client->callbacks.log_call(buffer, client); ++ } ++} ++ ++#ifdef RC_NO_VARIADIC_MACROS ++ ++void RC_CLIENT_LOG_ERR_FORMATTED(const rc_client_t* client, const char* format, ...) ++{ ++ if (client->state.log_level >= RC_CLIENT_LOG_LEVEL_ERROR) { ++ va_list args; ++ va_start(args, format); ++ rc_client_log_message_va(client, format, args); ++ va_end(args); ++ } ++} ++ ++void RC_CLIENT_LOG_WARN_FORMATTED(const rc_client_t* client, const char* format, ...) ++{ ++ if (client->state.log_level >= RC_CLIENT_LOG_LEVEL_WARN) { ++ va_list args; ++ va_start(args, format); ++ rc_client_log_message_va(client, format, args); ++ va_end(args); ++ } ++} ++ ++void RC_CLIENT_LOG_INFO_FORMATTED(const rc_client_t* client, const char* format, ...) ++{ ++ if (client->state.log_level >= RC_CLIENT_LOG_LEVEL_INFO) { ++ va_list args; ++ va_start(args, format); ++ rc_client_log_message_va(client, format, args); ++ va_end(args); ++ } ++} ++ ++void RC_CLIENT_LOG_VERBOSE_FORMATTED(const rc_client_t* client, const char* format, ...) ++{ ++ if (client->state.log_level >= RC_CLIENT_LOG_LEVEL_VERBOSE) { ++ va_list args; ++ va_start(args, format); ++ rc_client_log_message_va(client, format, args); ++ va_end(args); ++ } ++} ++ ++#else ++ ++void rc_client_log_message_formatted(const rc_client_t* client, const char* format, ...) ++{ ++ va_list args; ++ va_start(args, format); ++ rc_client_log_message_va(client, format, args); ++ va_end(args); ++} ++ ++#endif /* RC_NO_VARIADIC_MACROS */ ++ ++void rc_client_enable_logging(rc_client_t* client, int level, rc_client_message_callback_t callback) ++{ ++ client->callbacks.log_call = callback; ++ client->state.log_level = callback ? level : RC_CLIENT_LOG_LEVEL_NONE; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->enable_logging) ++ client->state.external_client->enable_logging(client, level, callback); ++#endif ++} ++ ++/* ===== Common ===== */ ++ ++static rc_clock_t rc_client_clock_get_now_millisecs(const rc_client_t* client) ++{ ++#if defined(CLOCK_MONOTONIC) ++ struct timespec now; ++ (void)client; ++ ++ if (clock_gettime(CLOCK_MONOTONIC, &now) < 0) ++ return 0; ++ ++ /* round nanoseconds to nearest millisecond and add to seconds */ ++ return ((rc_clock_t)now.tv_sec * 1000 + ((rc_clock_t)now.tv_nsec / 1000000)); ++#elif defined(_WIN32) ++ static LARGE_INTEGER freq; ++ LARGE_INTEGER ticks; ++ ++ (void)client; ++ ++ /* Frequency is the number of ticks per second and is guaranteed to not change. */ ++ if (!freq.QuadPart) { ++ if (!QueryPerformanceFrequency(&freq)) ++ return 0; ++ ++ /* convert to number of ticks per millisecond to simplify later calculations */ ++ freq.QuadPart /= 1000; ++ } ++ ++ if (!QueryPerformanceCounter(&ticks)) ++ return 0; ++ ++ return (rc_clock_t)(ticks.QuadPart / freq.QuadPart); ++#else ++ const clock_t clock_now = clock(); ++ ++ (void)client; ++ ++ if (sizeof(clock_t) == 4) { ++ static uint32_t clock_wraps = 0; ++ static clock_t last_clock = 0; ++ static time_t last_timet = 0; ++ const time_t time_now = time(NULL); ++ ++ if (last_timet != 0) { ++ const time_t seconds_per_clock_t = (time_t)(((uint64_t)1 << 32) / CLOCKS_PER_SEC); ++ if (clock_now < last_clock) { ++ /* clock() has wrapped */ ++ ++clock_wraps; ++ } ++ else if (time_now - last_timet > seconds_per_clock_t) { ++ /* it's been long enough that clock() has wrapped and is higher than the last time it was read */ ++ ++clock_wraps; ++ } ++ } ++ ++ last_timet = time_now; ++ last_clock = clock_now; ++ ++ return (rc_clock_t)((((uint64_t)clock_wraps << 32) | clock_now) / (CLOCKS_PER_SEC / 1000)); ++ } ++ else { ++ return (rc_clock_t)(clock_now / (CLOCKS_PER_SEC / 1000)); ++ } ++#endif ++} ++ ++void rc_client_set_get_time_millisecs_function(rc_client_t* client, rc_get_time_millisecs_func_t handler) ++{ ++ client->callbacks.get_time_millisecs = handler ? handler : rc_client_clock_get_now_millisecs; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->set_get_time_millisecs) ++ client->state.external_client->set_get_time_millisecs(client, handler); ++#endif ++} ++ ++int rc_client_async_handle_aborted(rc_client_t* client, rc_client_async_handle_t* async_handle) ++{ ++ int aborted; ++ ++ rc_mutex_lock(&client->state.mutex); ++ aborted = async_handle->aborted; ++ rc_mutex_unlock(&client->state.mutex); ++ ++ return aborted; ++} ++ ++static void rc_client_begin_async(rc_client_t* client, rc_client_async_handle_t* async_handle) ++{ ++ size_t i; ++ ++ rc_mutex_lock(&client->state.mutex); ++ for (i = 0; i < sizeof(client->state.async_handles) / sizeof(client->state.async_handles[0]); ++i) { ++ if (!client->state.async_handles[i]) { ++ client->state.async_handles[i] = async_handle; ++ break; ++ } ++ } ++ rc_mutex_unlock(&client->state.mutex); ++} ++ ++static int rc_client_end_async(rc_client_t* client, rc_client_async_handle_t* async_handle) ++{ ++ int aborted = async_handle->aborted; ++ ++ /* if client was destroyed, mutex doesn't exist and we don't need to remove the handle from the collection */ ++ if (aborted != RC_CLIENT_ASYNC_DESTROYED) { ++ size_t i; ++ ++ rc_mutex_lock(&client->state.mutex); ++ for (i = 0; i < sizeof(client->state.async_handles) / sizeof(client->state.async_handles[0]); ++i) { ++ if (client->state.async_handles[i] == async_handle) { ++ client->state.async_handles[i] = NULL; ++ break; ++ } ++ } ++ aborted = async_handle->aborted; ++ ++ rc_mutex_unlock(&client->state.mutex); ++ } ++ ++ return aborted; ++} ++ ++void rc_client_abort_async(rc_client_t* client, rc_client_async_handle_t* async_handle) ++{ ++ if (async_handle && client) { ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->abort_async) { ++ client->state.external_client->abort_async(async_handle); ++ return; ++ } ++#endif ++ ++ rc_mutex_lock(&client->state.mutex); ++ async_handle->aborted = RC_CLIENT_ASYNC_ABORTED; ++ rc_mutex_unlock(&client->state.mutex); ++ } ++} ++ ++static int rc_client_async_handle_valid(rc_client_t* client, rc_client_async_handle_t* async_handle) ++{ ++ int valid = 0; ++ size_t i; ++ ++ /* there is a small window of opportunity where the client could have been destroyed before calling ++ * this function, but this function assumes the possibility that the handle has been destroyed, so ++ * we can't check it for RC_CLIENT_ASYNC_DESTROYED before attempting to scan the client data */ ++ rc_mutex_lock(&client->state.mutex); ++ ++ for (i = 0; i < sizeof(client->state.async_handles) / sizeof(client->state.async_handles[0]); ++i) { ++ if (client->state.async_handles[i] == async_handle) { ++ valid = 1; ++ break; ++ } ++ } ++ ++ rc_mutex_unlock(&client->state.mutex); ++ ++ return valid; ++} ++ ++static const char* rc_client_server_error_message(int* result, int http_status_code, const rc_api_response_t* response) ++{ ++ if (!response->succeeded) { ++ if (*result == RC_OK) { ++ *result = RC_API_FAILURE; ++ if (!response->error_message) ++ return "Unexpected API failure with no error message"; ++ } ++ ++ if (response->error_message) ++ return response->error_message; ++ } ++ ++ (void)http_status_code; ++ ++ if (*result != RC_OK) ++ return rc_error_str(*result); ++ ++ return NULL; ++} ++ ++static void rc_client_raise_server_error_event(rc_client_t* client, ++ const char* api, uint32_t related_id, int result, const char* error_message) ++{ ++ rc_client_server_error_t server_error; ++ rc_client_event_t client_event; ++ ++ server_error.api = api; ++ server_error.error_message = error_message; ++ server_error.result = result; ++ server_error.related_id = related_id; ++ ++ memset(&client_event, 0, sizeof(client_event)); ++ client_event.type = RC_CLIENT_EVENT_SERVER_ERROR; ++ client_event.server_error = &server_error; ++ ++ client->callbacks.event_handler(&client_event, client); ++} ++ ++static void rc_client_update_disconnect_state(rc_client_t* client) ++{ ++ rc_client_scheduled_callback_data_t* scheduled_callback; ++ uint8_t new_state = RC_CLIENT_DISCONNECT_HIDDEN; ++ ++ rc_mutex_lock(&client->state.mutex); ++ ++ scheduled_callback = client->state.scheduled_callbacks; ++ for (; scheduled_callback; scheduled_callback = scheduled_callback->next) { ++ if (scheduled_callback->callback == rc_client_award_achievement_retry || ++ scheduled_callback->callback == rc_client_submit_leaderboard_entry_retry) { ++ new_state = RC_CLIENT_DISCONNECT_VISIBLE; ++ break; ++ } ++ } ++ ++ if ((client->state.disconnect & RC_CLIENT_DISCONNECT_VISIBLE) != new_state) { ++ if (new_state == RC_CLIENT_DISCONNECT_VISIBLE) ++ client->state.disconnect = RC_CLIENT_DISCONNECT_HIDDEN | RC_CLIENT_DISCONNECT_SHOW_PENDING; ++ else ++ client->state.disconnect = RC_CLIENT_DISCONNECT_VISIBLE | RC_CLIENT_DISCONNECT_HIDE_PENDING; ++ } ++ else { ++ client->state.disconnect = new_state; ++ } ++ ++ rc_mutex_unlock(&client->state.mutex); ++} ++ ++static void rc_client_raise_disconnect_events(rc_client_t* client) ++{ ++ rc_client_event_t client_event; ++ uint8_t new_state; ++ ++ rc_mutex_lock(&client->state.mutex); ++ ++ if (client->state.disconnect & RC_CLIENT_DISCONNECT_SHOW_PENDING) ++ new_state = RC_CLIENT_DISCONNECT_VISIBLE; ++ else ++ new_state = RC_CLIENT_DISCONNECT_HIDDEN; ++ client->state.disconnect = new_state; ++ ++ rc_mutex_unlock(&client->state.mutex); ++ ++ memset(&client_event, 0, sizeof(client_event)); ++ client_event.type = (new_state == RC_CLIENT_DISCONNECT_VISIBLE) ? ++ RC_CLIENT_EVENT_DISCONNECTED : RC_CLIENT_EVENT_RECONNECTED; ++ client->callbacks.event_handler(&client_event, client); ++} ++ ++static int rc_client_should_retry(const rc_api_server_response_t* server_response) ++{ ++ switch (server_response->http_status_code) { ++ case 502: /* 502 Bad Gateway */ ++ /* nginx connection pool full */ ++ return 1; ++ ++ case 503: /* 503 Service Temporarily Unavailable */ ++ /* site is in maintenance mode */ ++ return 1; ++ ++ case 504: /* 504 Gateway Timeout */ ++ /* timeout between web server and database server */ ++ return 1; ++ ++ case 429: /* 429 Too Many Requests */ ++ /* too many unlocks occurred at the same time */ ++ return 1; ++ ++ case 521: /* 521 Web Server is Down */ ++ /* cloudfare could not find the server */ ++ return 1; ++ ++ case 522: /* 522 Connection Timed Out */ ++ /* timeout connecting to server from cloudfare */ ++ return 1; ++ ++ case 523: /* 523 Origin is Unreachable */ ++ /* cloudfare cannot find server */ ++ return 1; ++ ++ case 524: /* 524 A Timeout Occurred */ ++ /* connection to server from cloudfare was dropped before request was completed */ ++ return 1; ++ ++ case 525: /* 525 SSL Handshake Failed */ ++ /* web server worker connection pool is exhausted */ ++ return 1; ++ ++ case RC_API_SERVER_RESPONSE_RETRYABLE_CLIENT_ERROR: ++ /* client provided non-HTTP error (explicitly retryable) */ ++ return 1; ++ ++ case RC_API_SERVER_RESPONSE_CLIENT_ERROR: ++ /* client provided non-HTTP error (implicitly non-retryable) */ ++ return 0; ++ ++ default: ++ /* assume any error not handled above where no response was received should be retried */ ++ if (server_response->body_length == 0 || !server_response->body || !server_response->body[0]) ++ return 1; ++ ++ return 0; ++ } ++} ++ ++static int rc_client_get_image_url(char buffer[], size_t buffer_size, int image_type, const char* image_name) ++{ ++ rc_api_fetch_image_request_t image_request; ++ rc_api_request_t request; ++ int result; ++ ++ if (!buffer) ++ return RC_INVALID_STATE; ++ ++ memset(&image_request, 0, sizeof(image_request)); ++ image_request.image_type = image_type; ++ image_request.image_name = image_name; ++ result = rc_api_init_fetch_image_request_hosted(&request, &image_request, NULL); ++ if (result == RC_OK) ++ snprintf(buffer, buffer_size, "%s", request.url); ++ ++ rc_api_destroy_request(&request); ++ return result; ++} ++ ++/* ===== User ===== */ ++ ++static void rc_client_login_callback(const rc_api_server_response_t* server_response, void* callback_data) ++{ ++ rc_client_generic_callback_data_t* login_callback_data = (rc_client_generic_callback_data_t*)callback_data; ++ rc_client_t* client = login_callback_data->client; ++ rc_api_login_response_t login_response; ++ rc_client_load_state_t* load_state; ++ const char* error_message; ++ int result; ++ ++ result = rc_client_end_async(client, &login_callback_data->async_handle); ++ if (result) { ++ if (result != RC_CLIENT_ASYNC_DESTROYED) ++ rc_client_logout(client); /* logout will reset the user state and call the load game callback */ ++ ++ free(login_callback_data); ++ return; ++ } ++ ++ if (client->state.user == RC_CLIENT_USER_STATE_NONE) { ++ /* logout was called */ ++ if (login_callback_data->callback) ++ login_callback_data->callback(RC_ABORTED, "Login aborted", client, login_callback_data->callback_userdata); ++ ++ free(login_callback_data); ++ /* logout call will immediately abort load game before this callback gets called */ ++ return; ++ } ++ ++ result = rc_api_process_login_server_response(&login_response, server_response); ++ error_message = rc_client_server_error_message(&result, server_response->http_status_code, &login_response.response); ++ if (error_message) { ++ rc_mutex_lock(&client->state.mutex); ++ client->state.user = RC_CLIENT_USER_STATE_NONE; ++ load_state = client->state.load; ++ rc_mutex_unlock(&client->state.mutex); ++ ++ RC_CLIENT_LOG_ERR_FORMATTED(client, "Login failed: %s", error_message); ++ if (login_callback_data->callback) ++ login_callback_data->callback(result, error_message, client, login_callback_data->callback_userdata); ++ ++ if (load_state && load_state->progress == RC_CLIENT_LOAD_GAME_STATE_AWAIT_LOGIN) ++ rc_client_begin_fetch_game_sets(load_state); ++ } ++ else { ++ client->user.username = rc_buffer_strcpy(&client->state.buffer, login_response.username); ++ ++ if (strcmp(login_response.username, login_response.display_name) == 0) ++ client->user.display_name = client->user.username; ++ else ++ client->user.display_name = rc_buffer_strcpy(&client->state.buffer, login_response.display_name); ++ ++ client->user.avatar_url = rc_buffer_strcpy(&client->state.buffer, login_response.avatar_url); ++ client->user.token = rc_buffer_strcpy(&client->state.buffer, login_response.api_token); ++ client->user.score = login_response.score; ++ client->user.score_softcore = login_response.score_softcore; ++ client->user.num_unread_messages = login_response.num_unread_messages; ++ ++ rc_mutex_lock(&client->state.mutex); ++ client->state.user = RC_CLIENT_USER_STATE_LOGGED_IN; ++ load_state = client->state.load; ++ rc_mutex_unlock(&client->state.mutex); ++ ++ RC_CLIENT_LOG_INFO_FORMATTED(client, "%s logged in successfully", login_response.display_name); ++ ++ if (load_state && load_state->progress == RC_CLIENT_LOAD_GAME_STATE_AWAIT_LOGIN) ++ rc_client_begin_fetch_game_sets(load_state); ++ ++ if (login_callback_data->callback) ++ login_callback_data->callback(RC_OK, NULL, client, login_callback_data->callback_userdata); ++ } ++ ++ rc_api_destroy_login_response(&login_response); ++ free(login_callback_data); ++} ++ ++static rc_client_async_handle_t* rc_client_begin_login(rc_client_t* client, ++ const rc_api_login_request_t* login_request, rc_client_callback_t callback, void* callback_userdata) ++{ ++ rc_client_generic_callback_data_t* callback_data; ++ rc_api_request_t request; ++ int result = rc_api_init_login_request_hosted(&request, login_request, &client->state.host); ++ const char* error_message = rc_error_str(result); ++ ++ if (result == RC_OK) { ++ rc_mutex_lock(&client->state.mutex); ++ ++ if (client->state.user == RC_CLIENT_USER_STATE_LOGIN_REQUESTED) { ++ error_message = "Login already in progress"; ++ result = RC_INVALID_STATE; ++ } ++ client->state.user = RC_CLIENT_USER_STATE_LOGIN_REQUESTED; ++ ++ rc_mutex_unlock(&client->state.mutex); ++ } ++ ++ if (result != RC_OK) { ++ callback(result, error_message, client, callback_userdata); ++ return NULL; ++ } ++ ++ callback_data = (rc_client_generic_callback_data_t*)calloc(1, sizeof(*callback_data)); ++ if (!callback_data) { ++ callback(RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY), client, callback_userdata); ++ return NULL; ++ } ++ ++ callback_data->client = client; ++ callback_data->callback = callback; ++ callback_data->callback_userdata = callback_userdata; ++ ++ rc_client_begin_async(client, &callback_data->async_handle); ++ client->callbacks.server_call(&request, rc_client_login_callback, callback_data, client); ++ ++ rc_api_destroy_request(&request); ++ ++ /* if the user state has changed, the async operation completed synchronously */ ++ rc_mutex_lock(&client->state.mutex); ++ if (client->state.user != RC_CLIENT_USER_STATE_LOGIN_REQUESTED) ++ callback_data = NULL; ++ rc_mutex_unlock(&client->state.mutex); ++ ++ return callback_data ? &callback_data->async_handle : NULL; ++} ++ ++rc_client_async_handle_t* rc_client_begin_login_with_password(rc_client_t* client, ++ const char* username, const char* password, rc_client_callback_t callback, void* callback_userdata) ++{ ++ rc_api_login_request_t login_request; ++ ++ if (!client) { ++ callback(RC_INVALID_STATE, "client is required", client, callback_userdata); ++ return NULL; ++ } ++ ++ if (!username || !username[0]) { ++ callback(RC_INVALID_STATE, "username is required", client, callback_userdata); ++ return NULL; ++ } ++ ++ if (!password || !password[0]) { ++ callback(RC_INVALID_STATE, "password is required", client, callback_userdata); ++ return NULL; ++ } ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->begin_login_with_password) ++ return client->state.external_client->begin_login_with_password(client, username, password, callback, callback_userdata); ++#endif ++ ++ memset(&login_request, 0, sizeof(login_request)); ++ login_request.username = username; ++ login_request.password = password; ++ ++ RC_CLIENT_LOG_INFO_FORMATTED(client, "Attempting to log in %s (with password)", username); ++ return rc_client_begin_login(client, &login_request, callback, callback_userdata); ++} ++ ++rc_client_async_handle_t* rc_client_begin_login_with_token(rc_client_t* client, ++ const char* username, const char* token, rc_client_callback_t callback, void* callback_userdata) ++{ ++ rc_api_login_request_t login_request; ++ ++ if (!client) { ++ callback(RC_INVALID_STATE, "client is required", client, callback_userdata); ++ return NULL; ++ } ++ ++ if (!username || !username[0]) { ++ callback(RC_INVALID_STATE, "username is required", client, callback_userdata); ++ return NULL; ++ } ++ ++ if (!token || !token[0]) { ++ callback(RC_INVALID_STATE, "token is required", client, callback_userdata); ++ return NULL; ++ } ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->begin_login_with_token) ++ return client->state.external_client->begin_login_with_token(client, username, token, callback, callback_userdata); ++#endif ++ ++ memset(&login_request, 0, sizeof(login_request)); ++ login_request.username = username; ++ login_request.api_token = token; ++ ++ RC_CLIENT_LOG_INFO_FORMATTED(client, "Attempting to log in %s (with token)", username); ++ return rc_client_begin_login(client, &login_request, callback, callback_userdata); ++} ++ ++void rc_client_logout(rc_client_t* client) ++{ ++ rc_client_load_state_t* load_state; ++ ++ if (!client) ++ return; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->logout) { ++ client->state.external_client->logout(); ++ return; ++ } ++#endif ++ ++ switch (client->state.user) { ++ case RC_CLIENT_USER_STATE_LOGGED_IN: ++ RC_CLIENT_LOG_INFO_FORMATTED(client, "Logging %s out", client->user.display_name); ++ break; ++ ++ case RC_CLIENT_USER_STATE_LOGIN_REQUESTED: ++ RC_CLIENT_LOG_INFO(client, "Aborting login"); ++ break; ++ } ++ ++ rc_mutex_lock(&client->state.mutex); ++ ++ client->state.user = RC_CLIENT_USER_STATE_NONE; ++ memset(&client->user, 0, sizeof(client->user)); ++ ++ load_state = client->state.load; ++ ++ rc_mutex_unlock(&client->state.mutex); ++ ++ rc_client_unload_game(client); ++ ++ if (load_state && load_state->progress == RC_CLIENT_LOAD_GAME_STATE_AWAIT_LOGIN) ++ rc_client_load_error(load_state, RC_ABORTED, "Login aborted"); ++} ++ ++const rc_client_user_t* rc_client_get_user_info(const rc_client_t* client) ++{ ++ if (!client) ++ return NULL; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client) { ++ if (client->state.external_client->get_user_info_v3) ++ return client->state.external_client->get_user_info_v3(); ++ ++ if (client->state.external_client->get_user_info) ++ return rc_client_external_convert_v1_user(client, client->state.external_client->get_user_info()); ++ } ++#endif ++ ++ return (client->state.user == RC_CLIENT_USER_STATE_LOGGED_IN) ? &client->user : NULL; ++} ++ ++int rc_client_user_get_image_url(const rc_client_user_t* user, char buffer[], size_t buffer_size) ++{ ++ if (!user) ++ return RC_INVALID_STATE; ++ ++ if (user->avatar_url) { ++ snprintf(buffer, buffer_size, "%s", user->avatar_url); ++ return RC_OK; ++ } ++ ++ return rc_client_get_image_url(buffer, buffer_size, RC_IMAGE_TYPE_USER, user->display_name); ++} ++ ++static void rc_client_subset_get_user_game_summary(const rc_client_t* client, ++ const rc_client_subset_info_t* subset, rc_client_user_game_summary_t* summary) ++{ ++ rc_client_achievement_info_t* achievement = subset->achievements; ++ rc_client_achievement_info_t* stop = achievement + subset->public_.num_achievements; ++ time_t last_unlock_time = 0; ++ time_t last_progression_time = 0; ++ time_t first_win_time = 0; ++ int num_progression_achievements = 0; ++ int num_win_achievements = 0; ++ int num_unlocked_progression_achievements = 0; ++ const uint8_t unlock_bit = (client->state.hardcore) ? ++ RC_CLIENT_ACHIEVEMENT_UNLOCKED_HARDCORE : RC_CLIENT_ACHIEVEMENT_UNLOCKED_SOFTCORE; ++ ++ rc_mutex_lock((rc_mutex_t*)&client->state.mutex); /* remove const cast for mutex access */ ++ ++ for (; achievement < stop; ++achievement) { ++ switch (achievement->public_.category) { ++ case RC_CLIENT_ACHIEVEMENT_CATEGORY_CORE: ++ ++summary->num_core_achievements; ++ summary->points_core += achievement->public_.points; ++ ++ if (achievement->public_.unlocked & unlock_bit) { ++ ++summary->num_unlocked_achievements; ++ summary->points_unlocked += achievement->public_.points; ++ ++ if (achievement->public_.unlock_time > last_unlock_time) ++ last_unlock_time = achievement->public_.unlock_time; ++ ++ if (achievement->public_.type == RC_CLIENT_ACHIEVEMENT_TYPE_PROGRESSION) { ++ ++num_unlocked_progression_achievements; ++ if (achievement->public_.unlock_time > last_progression_time) ++ last_progression_time = achievement->public_.unlock_time; ++ } ++ else if (achievement->public_.type == RC_CLIENT_ACHIEVEMENT_TYPE_WIN) { ++ if (first_win_time == 0 || achievement->public_.unlock_time < first_win_time) ++ first_win_time = achievement->public_.unlock_time; ++ } ++ } ++ ++ if (achievement->public_.type == RC_CLIENT_ACHIEVEMENT_TYPE_PROGRESSION) ++ ++num_progression_achievements; ++ else if (achievement->public_.type == RC_CLIENT_ACHIEVEMENT_TYPE_WIN) ++ ++num_win_achievements; ++ ++ if (achievement->public_.bucket == RC_CLIENT_ACHIEVEMENT_BUCKET_UNSUPPORTED) ++ ++summary->num_unsupported_achievements; ++ ++ break; ++ ++ case RC_CLIENT_ACHIEVEMENT_CATEGORY_UNOFFICIAL: ++ ++summary->num_unofficial_achievements; ++ break; ++ ++ default: ++ continue; ++ } ++ } ++ ++ rc_mutex_unlock((rc_mutex_t*)&client->state.mutex); /* remove const cast for mutex access */ ++ ++ if (summary->num_unlocked_achievements == summary->num_core_achievements) ++ summary->completed_time = last_unlock_time; ++ ++ if ((first_win_time || num_win_achievements == 0) && num_unlocked_progression_achievements == num_progression_achievements) ++ summary->beaten_time = (first_win_time > last_progression_time) ? first_win_time : last_progression_time; ++} ++ ++void rc_client_get_user_game_summary(const rc_client_t* client, rc_client_user_game_summary_t* summary) ++{ ++ if (!summary) ++ return; ++ ++ memset(summary, 0, sizeof(*summary)); ++ if (!client) ++ return; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client) { ++ if (client->state.external_client->get_user_game_summary_v5) { ++ client->state.external_client->get_user_game_summary_v5(summary); ++ return; ++ } ++ if (client->state.external_client->get_user_game_summary) { ++ client->state.external_client->get_user_game_summary(summary); ++ return; ++ } ++ } ++#endif ++ ++ if (rc_client_is_game_loaded(client)) ++ rc_client_subset_get_user_game_summary(client, client->game->subsets, summary); ++} ++ ++void rc_client_get_user_subset_summary(const rc_client_t* client, uint32_t subset_id, rc_client_user_game_summary_t* summary) ++{ ++ if (!summary) ++ return; ++ ++ memset(summary, 0, sizeof(*summary)); ++ if (!client || !subset_id) ++ return; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->get_user_subset_summary) { ++ client->state.external_client->get_user_subset_summary(subset_id, summary); ++ return; ++ } ++#endif ++ ++ if (rc_client_is_game_loaded(client)) { ++ const rc_client_subset_info_t* subset = client->game->subsets; ++ for (; subset; subset = subset->next) { ++ if (subset->public_.id == subset_id) { ++ rc_client_subset_get_user_game_summary(client, subset, summary); ++ break; ++ } ++ } ++ } ++} ++ ++typedef struct rc_client_fetch_all_user_progress_callback_data_t { ++ rc_client_t* client; ++ rc_client_fetch_all_user_progress_callback_t callback; ++ void* callback_userdata; ++ uint32_t console_id; ++ rc_client_async_handle_t async_handle; ++} rc_client_fetch_all_user_progress_callback_data_t; ++ ++static void rc_client_fetch_all_user_progress_callback(const rc_api_server_response_t* server_response, ++ void* callback_data) ++{ ++ rc_client_fetch_all_user_progress_callback_data_t* ap_callback_data = ++ (rc_client_fetch_all_user_progress_callback_data_t*)callback_data; ++ rc_client_t* client = ap_callback_data->client; ++ rc_api_fetch_all_user_progress_response_t ap_response; ++ const char* error_message; ++ int result; ++ ++ result = rc_client_end_async(client, &ap_callback_data->async_handle); ++ if (result) { ++ if (result != RC_CLIENT_ASYNC_DESTROYED) ++ RC_CLIENT_LOG_VERBOSE(client, "Fetch all progress aborted"); ++ ++ free(ap_callback_data); ++ return; ++ } ++ ++ result = rc_api_process_fetch_all_user_progress_server_response(&ap_response, server_response); ++ error_message = rc_client_server_error_message(&result, server_response->http_status_code, &ap_response.response); ++ if (error_message) { ++ RC_CLIENT_LOG_ERR_FORMATTED(client, "Fetch all progress for console %u failed: %s", ap_callback_data->console_id, ++ error_message); ++ ap_callback_data->callback(result, error_message, NULL, client, ap_callback_data->callback_userdata); ++ } else { ++ rc_client_all_user_progress_t* list; ++ const size_t list_size = sizeof(*list) + sizeof(rc_client_all_user_progress_entry_t) * ap_response.num_entries; ++ ++ list = (rc_client_all_user_progress_t*)malloc(list_size); ++ if (!list) { ++ ap_callback_data->callback(RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY), NULL, client, ++ ap_callback_data->callback_userdata); ++ } else { ++ rc_client_all_user_progress_entry_t* entry = list->entries = ++ (rc_client_all_user_progress_entry_t*)((uint8_t*)list + sizeof(*list)); ++ const rc_api_all_user_progress_entry_t* hlentry = ap_response.entries; ++ const rc_api_all_user_progress_entry_t* stop = hlentry + ap_response.num_entries; ++ ++ for (; hlentry < stop; ++hlentry, ++entry) ++ { ++ entry->game_id = hlentry->game_id; ++ entry->num_achievements = hlentry->num_achievements; ++ entry->num_unlocked_achievements = hlentry->num_unlocked_achievements; ++ entry->num_unlocked_achievements_hardcore = hlentry->num_unlocked_achievements_hardcore; ++ } ++ ++ list->num_entries = ap_response.num_entries; ++ ++ ap_callback_data->callback(RC_OK, NULL, list, client, ap_callback_data->callback_userdata); ++ } ++ } ++ ++ rc_api_destroy_fetch_all_user_progress_response(&ap_response); ++ free(ap_callback_data); ++} ++ ++rc_client_async_handle_t* rc_client_begin_fetch_all_user_progress(rc_client_t* client, uint32_t console_id, ++ rc_client_fetch_all_user_progress_callback_t callback, ++ void* callback_userdata) ++{ ++ rc_api_fetch_all_user_progress_request_t api_params; ++ rc_client_fetch_all_user_progress_callback_data_t* callback_data; ++ rc_client_async_handle_t* async_handle; ++ rc_api_request_t request; ++ int result; ++ const char* error_message; ++ ++ if (!client) { ++ callback(RC_INVALID_STATE, "client is required", NULL, client, callback_userdata); ++ return NULL; ++ } else if (client->state.user != RC_CLIENT_USER_STATE_LOGGED_IN) { ++ callback(RC_INVALID_STATE, "client must be logged in", NULL, client, callback_userdata); ++ return NULL; ++ } ++ ++ api_params.username = client->user.username; ++ api_params.api_token = client->user.token; ++ api_params.console_id = console_id; ++ ++ result = rc_api_init_fetch_all_user_progress_request_hosted(&request, &api_params, &client->state.host); ++ ++ if (result != RC_OK) { ++ error_message = rc_error_str(result); ++ callback(result, error_message, NULL, client, callback_userdata); ++ return NULL; ++ } ++ ++ callback_data = (rc_client_fetch_all_user_progress_callback_data_t*)calloc(1, sizeof(*callback_data)); ++ if (!callback_data) { ++ callback(RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY), NULL, client, callback_userdata); ++ return NULL; ++ } ++ ++ callback_data->client = client; ++ callback_data->callback = callback; ++ callback_data->callback_userdata = callback_userdata; ++ callback_data->console_id = console_id; ++ ++ async_handle = &callback_data->async_handle; ++ rc_client_begin_async(client, async_handle); ++ client->callbacks.server_call(&request, rc_client_fetch_all_user_progress_callback, callback_data, client); ++ rc_api_destroy_request(&request); ++ ++ return rc_client_async_handle_valid(client, async_handle) ? async_handle : NULL; ++} ++ ++void rc_client_destroy_all_user_progress(rc_client_all_user_progress_t* list) ++{ ++ free(list); ++} ++ ++/* ===== Game ===== */ ++ ++static void rc_client_free_game(rc_client_game_info_t* game) ++{ ++ rc_runtime_destroy(&game->runtime); ++ ++ rc_buffer_destroy(&game->buffer); ++ ++ free(game); ++} ++ ++static void rc_client_free_load_state(rc_client_load_state_t* load_state) ++{ ++ if (load_state->game) ++ rc_client_free_game(load_state->game); ++ ++ if (load_state->start_session_response) { ++ rc_api_destroy_start_session_response(load_state->start_session_response); ++ free(load_state->start_session_response); ++ } ++ ++#ifdef RC_CLIENT_SUPPORTS_HASH ++ rc_hash_destroy_iterator(&load_state->hash_iterator); ++#endif ++ ++ free(load_state); ++} ++ ++static void rc_client_begin_load_state(rc_client_load_state_t* load_state, uint8_t state, uint8_t num_requests) ++{ ++ rc_mutex_lock(&load_state->client->state.mutex); ++ ++ load_state->progress = state; ++ load_state->outstanding_requests += num_requests; ++ ++ rc_mutex_unlock(&load_state->client->state.mutex); ++} ++ ++static int rc_client_end_load_state(rc_client_load_state_t* load_state) ++{ ++ int remaining_requests = 0; ++ int aborted = 0; ++ ++ rc_mutex_lock(&load_state->client->state.mutex); ++ ++ if (load_state->outstanding_requests > 0) ++ --load_state->outstanding_requests; ++ remaining_requests = load_state->outstanding_requests; ++ ++ if (load_state->client->state.load != load_state) ++ aborted = 1; ++ ++ rc_mutex_unlock(&load_state->client->state.mutex); ++ ++ if (aborted) { ++ /* we can't actually free the load_state itself if there are any outstanding requests ++ * or their callbacks will try to use the free'd memory. As they call end_load_state, ++ * the outstanding_requests count will reach zero and the memory will be free'd then. */ ++ if (remaining_requests == 0) { ++ /* if one of the callbacks called rc_client_load_error, progress will be set to ++ * RC_CLIENT_LOAD_STATE_ABORTED. There's no need to call the callback with RC_ABORTED ++ * in that case, as it will have already been called with something more appropriate. */ ++ if (load_state->progress != RC_CLIENT_LOAD_GAME_STATE_ABORTED && load_state->callback) ++ load_state->callback(RC_ABORTED, "The requested game is no longer active", load_state->client, load_state->callback_userdata); ++ ++ rc_client_free_load_state(load_state); ++ } ++ ++ return -1; ++ } ++ ++ return remaining_requests; ++} ++ ++static void rc_client_load_error(rc_client_load_state_t* load_state, int result, const char* error_message) ++{ ++ int remaining_requests = 0; ++ ++ rc_mutex_lock(&load_state->client->state.mutex); ++ ++ load_state->progress = RC_CLIENT_LOAD_GAME_STATE_ABORTED; ++ if (load_state->client->state.load == load_state) ++ load_state->client->state.load = NULL; ++ ++ remaining_requests = load_state->outstanding_requests; ++ ++ rc_mutex_unlock(&load_state->client->state.mutex); ++ ++ RC_CLIENT_LOG_ERR_FORMATTED(load_state->client, "Load failed (%d): %s", result, error_message); ++ ++ if (load_state->callback) ++ load_state->callback(result, error_message, load_state->client, load_state->callback_userdata); ++ ++ /* we can't actually free the load_state itself if there are any outstanding requests ++ * or their callbacks will try to use the free'd memory. as they call end_load_state, ++ * the outstanding_requests count will reach zero and the memory will be free'd then. */ ++ if (remaining_requests == 0) ++ rc_client_free_load_state(load_state); ++} ++ ++static void rc_client_load_aborted(rc_client_load_state_t* load_state) ++{ ++ /* prevent callback from being called when manually aborted */ ++ load_state->callback = NULL; ++ ++ /* mark the game as no longer being loaded */ ++ rc_client_load_error(load_state, RC_ABORTED, NULL); ++ ++ /* decrement the async counter and potentially free the load_state object */ ++ rc_client_end_load_state(load_state); ++} ++ ++static void rc_client_invalidate_memref_achievements(rc_client_game_info_t* game, rc_client_t* client, rc_memref_t* memref) ++{ ++ rc_client_subset_info_t* subset = game->subsets; ++ for (; subset; subset = subset->next) { ++ rc_client_achievement_info_t* achievement = subset->achievements; ++ rc_client_achievement_info_t* stop = achievement + subset->public_.num_achievements; ++ for (; achievement < stop; ++achievement) { ++ if (achievement->public_.state == RC_CLIENT_ACHIEVEMENT_STATE_DISABLED) ++ continue; ++ ++ if (rc_trigger_contains_memref(achievement->trigger, memref)) { ++ achievement->public_.state = RC_CLIENT_ACHIEVEMENT_STATE_DISABLED; ++ achievement->public_.bucket = RC_CLIENT_ACHIEVEMENT_BUCKET_UNSUPPORTED; ++ ++ if (achievement->trigger) ++ achievement->trigger->state = RC_TRIGGER_STATE_DISABLED; ++ ++ RC_CLIENT_LOG_WARN_FORMATTED(client, "Disabled achievement %u. Invalid address %06X", achievement->public_.id, memref->address); ++ } ++ } ++ } ++} ++ ++static void rc_client_invalidate_memref_leaderboards(rc_client_game_info_t* game, rc_client_t* client, rc_memref_t* memref) ++{ ++ rc_client_subset_info_t* subset = game->subsets; ++ for (; subset; subset = subset->next) { ++ rc_client_leaderboard_info_t* leaderboard = subset->leaderboards; ++ rc_client_leaderboard_info_t* stop = leaderboard + subset->public_.num_leaderboards; ++ for (; leaderboard < stop; ++leaderboard) { ++ if (leaderboard->public_.state == RC_CLIENT_LEADERBOARD_STATE_DISABLED) ++ continue; ++ if (!leaderboard->lboard) ++ continue; ++ ++ if (rc_trigger_contains_memref(&leaderboard->lboard->start, memref)) ++ leaderboard->public_.state = RC_CLIENT_LEADERBOARD_STATE_DISABLED; ++ else if (rc_trigger_contains_memref(&leaderboard->lboard->cancel, memref)) ++ leaderboard->public_.state = RC_CLIENT_LEADERBOARD_STATE_DISABLED; ++ else if (rc_trigger_contains_memref(&leaderboard->lboard->submit, memref)) ++ leaderboard->public_.state = RC_CLIENT_LEADERBOARD_STATE_DISABLED; ++ else if (rc_value_contains_memref(&leaderboard->lboard->value, memref)) ++ leaderboard->public_.state = RC_CLIENT_LEADERBOARD_STATE_DISABLED; ++ else ++ continue; ++ ++ leaderboard->lboard->state = RC_LBOARD_STATE_DISABLED; ++ ++ RC_CLIENT_LOG_WARN_FORMATTED(client, "Disabled leaderboard %u. Invalid address %06X", leaderboard->public_.id, memref->address); ++ } ++ } ++} ++ ++static void rc_client_validate_addresses(rc_client_game_info_t* game, rc_client_t* client) ++{ ++ const rc_memory_regions_t* regions = rc_console_memory_regions(game->public_.console_id); ++ const uint32_t max_address = (regions && regions->num_regions > 0) ? ++ regions->region[regions->num_regions - 1].end_address : 0xFFFFFFFF; ++ uint8_t buffer[8]; ++ uint32_t total_count = 0; ++ uint32_t invalid_count = 0; ++ ++ rc_memref_list_t* memref_list = &game->runtime.memrefs->memrefs; ++ for (; memref_list; memref_list = memref_list->next) { ++ rc_memref_t* memref = memref_list->items; ++ const rc_memref_t* memref_end = memref + memref_list->count; ++ total_count += memref_list->count; ++ ++ for (; memref < memref_end; ++memref) { ++ if (memref->address > max_address || ++ client->callbacks.read_memory(memref->address, buffer, 1, client) == 0) { ++ memref->value.type = RC_VALUE_TYPE_NONE; ++ ++ rc_client_invalidate_memref_achievements(game, client, memref); ++ rc_client_invalidate_memref_leaderboards(game, client, memref); ++ ++ invalid_count++; ++ } ++ } ++ } ++ ++ game->max_valid_address = max_address; ++ RC_CLIENT_LOG_VERBOSE_FORMATTED(client, "%u/%u memory addresses valid", total_count - invalid_count, total_count); ++} ++ ++static void rc_client_update_legacy_runtime_achievements(rc_client_game_info_t* game, uint32_t active_count) ++{ ++ if (active_count > 0) { ++ rc_client_achievement_info_t* achievement; ++ rc_client_achievement_info_t* stop; ++ rc_runtime_trigger_t* trigger; ++ rc_client_subset_info_t* subset; ++ ++ if (active_count <= game->runtime.trigger_capacity) { ++ if (active_count != 0) ++ memset(game->runtime.triggers, 0, active_count * sizeof(rc_runtime_trigger_t)); ++ } else { ++ if (game->runtime.triggers) ++ free(game->runtime.triggers); ++ ++ game->runtime.trigger_capacity = active_count; ++ game->runtime.triggers = (rc_runtime_trigger_t*)calloc(1, active_count * sizeof(rc_runtime_trigger_t)); ++ } ++ ++ trigger = game->runtime.triggers; ++ if (!trigger) { ++ /* malloc failed, no way to report error, just bail */ ++ game->runtime.trigger_count = 0; ++ return; ++ } ++ ++ for (subset = game->subsets; subset; subset = subset->next) { ++ if (!subset->active) ++ continue; ++ ++ achievement = subset->achievements; ++ stop = achievement + subset->public_.num_achievements; ++ ++ for (; achievement < stop; ++achievement) { ++ if (achievement->public_.state == RC_CLIENT_ACHIEVEMENT_STATE_ACTIVE) { ++ trigger->id = achievement->public_.id; ++ memcpy(trigger->md5, achievement->md5, 16); ++ trigger->trigger = achievement->trigger; ++ ++trigger; ++ } ++ } ++ } ++ } ++ ++ game->runtime.trigger_count = active_count; ++} ++ ++static uint32_t rc_client_subset_count_active_achievements(const rc_client_subset_info_t* subset) ++{ ++ rc_client_achievement_info_t* achievement = subset->achievements; ++ rc_client_achievement_info_t* stop = achievement + subset->public_.num_achievements; ++ uint32_t active_count = 0; ++ ++ for (; achievement < stop; ++achievement) { ++ if (achievement->public_.state == RC_CLIENT_ACHIEVEMENT_STATE_ACTIVE) ++ ++active_count; ++ } ++ ++ return active_count; ++} ++ ++void rc_client_update_active_achievements(rc_client_game_info_t* game) ++{ ++ uint32_t active_count = 0; ++ rc_client_subset_info_t* subset = game->subsets; ++ for (; subset; subset = subset->next) { ++ if (subset->active) ++ active_count += rc_client_subset_count_active_achievements(subset); ++ } ++ ++ rc_client_update_legacy_runtime_achievements(game, active_count); ++} ++ ++static uint32_t rc_client_subset_toggle_hardcore_achievements(rc_client_subset_info_t* subset, rc_client_t* client, uint8_t active_bit) ++{ ++ rc_client_achievement_info_t* achievement = subset->achievements; ++ rc_client_achievement_info_t* stop = achievement + subset->public_.num_achievements; ++ uint32_t active_count = 0; ++ ++ for (; achievement < stop; ++achievement) { ++ if ((achievement->public_.unlocked & active_bit) == 0) { ++ switch (achievement->public_.state) { ++ case RC_CLIENT_ACHIEVEMENT_STATE_UNLOCKED: ++ case RC_CLIENT_ACHIEVEMENT_STATE_INACTIVE: ++ rc_reset_trigger(achievement->trigger); ++ achievement->public_.state = RC_CLIENT_ACHIEVEMENT_STATE_ACTIVE; ++ ++active_count; ++ break; ++ ++ case RC_CLIENT_ACHIEVEMENT_STATE_ACTIVE: ++ ++active_count; ++ break; ++ } ++ } ++ else { ++ achievement->public_.unlock_time = (active_bit == RC_CLIENT_ACHIEVEMENT_UNLOCKED_HARDCORE) ? ++ achievement->unlock_time_hardcore : achievement->unlock_time_softcore; ++ ++ if (achievement->public_.state == RC_CLIENT_ACHIEVEMENT_STATE_ACTIVE || ++ achievement->public_.state == RC_CLIENT_ACHIEVEMENT_STATE_INACTIVE) { ++ /* if it's active despite being unlocked, and we're in encore mode, leave it active */ ++ if (client->state.encore_mode) { ++ ++active_count; ++ continue; ++ } ++ ++ /* switch to inactive */ ++ achievement->public_.state = RC_CLIENT_ACHIEVEMENT_STATE_UNLOCKED; ++ ++ if (achievement->trigger && rc_trigger_state_active(achievement->trigger->state)) { ++ /* hide any active challenge indicators */ ++ if (achievement->trigger->state == RC_TRIGGER_STATE_PRIMED) { ++ rc_client_event_t client_event; ++ memset(&client_event, 0, sizeof(client_event)); ++ client_event.type = RC_CLIENT_EVENT_ACHIEVEMENT_CHALLENGE_INDICATOR_HIDE; ++ client_event.achievement = &achievement->public_; ++ client->callbacks.event_handler(&client_event, client); ++ } ++ ++ achievement->trigger->state = RC_TRIGGER_STATE_TRIGGERED; ++ } ++ } ++ } ++ } ++ ++ return active_count; ++} ++ ++static void rc_client_toggle_hardcore_achievements(rc_client_game_info_t* game, rc_client_t* client, uint8_t active_bit) ++{ ++ uint32_t active_count = 0; ++ rc_client_subset_info_t* subset = game->subsets; ++ for (; subset; subset = subset->next) { ++ if (subset->active) ++ active_count += rc_client_subset_toggle_hardcore_achievements(subset, client, active_bit); ++ } ++ ++ rc_client_update_legacy_runtime_achievements(game, active_count); ++} ++ ++static void rc_client_activate_achievements(rc_client_game_info_t* game, rc_client_t* client) ++{ ++ const uint8_t active_bit = (client->state.encore_mode) ? ++ RC_CLIENT_ACHIEVEMENT_UNLOCKED_NONE : (client->state.hardcore) ? ++ RC_CLIENT_ACHIEVEMENT_UNLOCKED_HARDCORE : RC_CLIENT_ACHIEVEMENT_UNLOCKED_SOFTCORE; ++ ++ rc_client_toggle_hardcore_achievements(game, client, active_bit); ++} ++ ++static void rc_client_update_legacy_runtime_leaderboards(rc_client_game_info_t* game, uint32_t active_count) ++{ ++ if (active_count > 0) { ++ rc_client_leaderboard_info_t* leaderboard; ++ rc_client_leaderboard_info_t* stop; ++ rc_client_subset_info_t* subset; ++ rc_runtime_lboard_t* lboard; ++ ++ if (active_count <= game->runtime.lboard_capacity) { ++ if (active_count != 0) ++ memset(game->runtime.lboards, 0, active_count * sizeof(rc_runtime_lboard_t)); ++ } else { ++ if (game->runtime.lboards) ++ free(game->runtime.lboards); ++ ++ game->runtime.lboard_capacity = active_count; ++ game->runtime.lboards = (rc_runtime_lboard_t*)calloc(1, active_count * sizeof(rc_runtime_lboard_t)); ++ } ++ ++ lboard = game->runtime.lboards; ++ if (!lboard) { ++ /* malloc failed. no way to report error, just bail */ ++ game->runtime.lboard_count = 0; ++ return; ++ } ++ ++ for (subset = game->subsets; subset; subset = subset->next) { ++ if (!subset->active) ++ continue; ++ ++ leaderboard = subset->leaderboards; ++ stop = leaderboard + subset->public_.num_leaderboards; ++ for (; leaderboard < stop; ++leaderboard) { ++ if (leaderboard->public_.state == RC_CLIENT_LEADERBOARD_STATE_ACTIVE || ++ leaderboard->public_.state == RC_CLIENT_LEADERBOARD_STATE_TRACKING) { ++ lboard->id = leaderboard->public_.id; ++ memcpy(lboard->md5, leaderboard->md5, 16); ++ lboard->lboard = leaderboard->lboard; ++ ++lboard; ++ } ++ } ++ } ++ } ++ ++ game->runtime.lboard_count = active_count; ++} ++ ++void rc_client_update_active_leaderboards(rc_client_game_info_t* game) ++{ ++ rc_client_leaderboard_info_t* leaderboard; ++ rc_client_leaderboard_info_t* stop; ++ ++ uint32_t active_count = 0; ++ rc_client_subset_info_t* subset = game->subsets; ++ for (; subset; subset = subset->next) ++ { ++ if (!subset->active) ++ continue; ++ ++ leaderboard = subset->leaderboards; ++ stop = leaderboard + subset->public_.num_leaderboards; ++ ++ for (; leaderboard < stop; ++leaderboard) ++ { ++ switch (leaderboard->public_.state) ++ { ++ case RC_CLIENT_LEADERBOARD_STATE_ACTIVE: ++ case RC_CLIENT_LEADERBOARD_STATE_TRACKING: ++ ++active_count; ++ break; ++ } ++ } ++ } ++ ++ rc_client_update_legacy_runtime_leaderboards(game, active_count); ++} ++ ++static void rc_client_activate_leaderboards(rc_client_game_info_t* game, rc_client_t* client) ++{ ++ rc_client_leaderboard_info_t* leaderboard; ++ rc_client_leaderboard_info_t* stop; ++ const uint8_t leaderboards_allowed = ++ client->state.hardcore || client->state.allow_leaderboards_in_softcore; ++ ++ uint32_t active_count = 0; ++ rc_client_subset_info_t* subset = game->subsets; ++ for (; subset; subset = subset->next) { ++ if (!subset->active) ++ continue; ++ ++ leaderboard = subset->leaderboards; ++ stop = leaderboard + subset->public_.num_leaderboards; ++ ++ for (; leaderboard < stop; ++leaderboard) { ++ switch (leaderboard->public_.state) { ++ case RC_CLIENT_LEADERBOARD_STATE_DISABLED: ++ continue; ++ ++ case RC_CLIENT_LEADERBOARD_STATE_INACTIVE: ++ if (leaderboards_allowed) { ++ rc_reset_lboard(leaderboard->lboard); ++ leaderboard->public_.state = RC_CLIENT_LEADERBOARD_STATE_ACTIVE; ++ ++active_count; ++ } ++ break; ++ ++ default: ++ if (leaderboards_allowed) ++ ++active_count; ++ else ++ leaderboard->public_.state = RC_CLIENT_LEADERBOARD_STATE_INACTIVE; ++ break; ++ } ++ } ++ } ++ ++ rc_client_update_legacy_runtime_leaderboards(game, active_count); ++} ++ ++static void rc_client_deactivate_leaderboards(rc_client_game_info_t* game, rc_client_t* client) ++{ ++ rc_client_leaderboard_info_t* leaderboard; ++ rc_client_leaderboard_info_t* stop; ++ ++ rc_client_subset_info_t* subset = game->subsets; ++ for (; subset; subset = subset->next) { ++ if (!subset->active) ++ continue; ++ ++ leaderboard = subset->leaderboards; ++ stop = leaderboard + subset->public_.num_leaderboards; ++ ++ for (; leaderboard < stop; ++leaderboard) { ++ switch (leaderboard->public_.state) { ++ case RC_CLIENT_LEADERBOARD_STATE_DISABLED: ++ case RC_CLIENT_LEADERBOARD_STATE_INACTIVE: ++ continue; ++ ++ case RC_CLIENT_LEADERBOARD_STATE_TRACKING: ++ rc_client_release_leaderboard_tracker(client->game, leaderboard); ++ /* fallthrough */ /* to default */ ++ default: ++ leaderboard->public_.state = RC_CLIENT_LEADERBOARD_STATE_INACTIVE; ++ break; ++ } ++ } ++ } ++ ++ game->runtime.lboard_count = 0; ++} ++ ++static void rc_client_apply_unlocks(rc_client_subset_info_t* subset, rc_api_unlock_entry_t* unlocks, uint32_t num_unlocks, uint8_t mode) ++{ ++ rc_client_achievement_info_t* start = subset->achievements; ++ rc_client_achievement_info_t* stop = start + subset->public_.num_achievements; ++ rc_client_achievement_info_t* scan; ++ rc_api_unlock_entry_t* unlock = unlocks; ++ rc_api_unlock_entry_t* unlock_stop = unlocks + num_unlocks; ++ ++ for (; unlock < unlock_stop; ++unlock) { ++ for (scan = start; scan < stop; ++scan) { ++ if (scan->public_.id == unlock->achievement_id) { ++ scan->public_.unlocked |= mode; ++ ++ if (mode & RC_CLIENT_ACHIEVEMENT_UNLOCKED_HARDCORE) ++ scan->unlock_time_hardcore = unlock->when; ++ if (mode & RC_CLIENT_ACHIEVEMENT_UNLOCKED_SOFTCORE) ++ scan->unlock_time_softcore = unlock->when; ++ ++ if (scan == start) ++ ++start; ++ else if (scan + 1 == stop) ++ --stop; ++ break; ++ } ++ } ++ } ++ ++ if (subset->next) ++ rc_client_apply_unlocks(subset->next, unlocks, num_unlocks, mode); ++} ++ ++static void rc_client_free_pending_media(rc_client_pending_media_t* pending_media) ++{ ++ if (pending_media->hash) ++ free((void*)pending_media->hash); ++#ifdef RC_CLIENT_SUPPORTS_HASH ++ if (pending_media->data) ++ free(pending_media->data); ++ free((void*)pending_media->file_path); ++#endif ++ free(pending_media); ++} ++ ++/* NOTE: address validation uses the read_memory callback to make sure the client ++ * will return data for the requested address. As such, this function must ++ * respect the `client->state.allow_background_memory_reads setting. Use ++ * rc_client_queue_activate_game to dispatch this function to the do_frame loop/ ++ */ ++static void rc_client_activate_game(rc_client_load_state_t* load_state, rc_api_start_session_response_t *start_session_response) ++{ ++ rc_client_t* client = load_state->client; ++ ++ rc_mutex_lock(&client->state.mutex); ++ load_state->progress = (client->state.load == load_state) ? ++ RC_CLIENT_LOAD_GAME_STATE_DONE : RC_CLIENT_LOAD_GAME_STATE_ABORTED; ++ rc_mutex_unlock(&client->state.mutex); ++ ++ if (load_state->progress != RC_CLIENT_LOAD_GAME_STATE_DONE) { ++ /* previous load state was aborted */ ++ if (load_state->callback) ++ load_state->callback(RC_ABORTED, "The requested game is no longer active", client, load_state->callback_userdata); ++ } ++ else if (!start_session_response && client->state.spectator_mode == RC_CLIENT_SPECTATOR_MODE_OFF) { ++ /* unlocks not available - assume malloc failed */ ++ if (load_state->callback) ++ load_state->callback(RC_INVALID_STATE, "Unlock arrays were not allocated", client, load_state->callback_userdata); ++ } ++ else { ++ if (client->state.spectator_mode == RC_CLIENT_SPECTATOR_MODE_OFF) { ++ rc_client_apply_unlocks(load_state->subset, start_session_response->hardcore_unlocks, ++ start_session_response->num_hardcore_unlocks, RC_CLIENT_ACHIEVEMENT_UNLOCKED_BOTH); ++ rc_client_apply_unlocks(load_state->subset, start_session_response->unlocks, ++ start_session_response->num_unlocks, RC_CLIENT_ACHIEVEMENT_UNLOCKED_SOFTCORE); ++ } ++ ++ /* make the loaded game active if another game is not aleady being loaded. */ ++ rc_mutex_lock(&client->state.mutex); ++ if (client->state.load == load_state) { ++ client->game = load_state->game; ++ client->state.frames_processed = client->state.frames_at_last_ping = 0; ++ } ++ else { ++ load_state->progress = RC_CLIENT_LOAD_GAME_STATE_ABORTED; ++ } ++ rc_mutex_unlock(&client->state.mutex); ++ ++ if (load_state->progress != RC_CLIENT_LOAD_GAME_STATE_ABORTED) { ++ /* if a change media request is pending, kick it off */ ++ rc_client_pending_media_t* pending_media; ++ ++ rc_mutex_lock(&load_state->client->state.mutex); ++ pending_media = load_state->pending_media; ++ load_state->pending_media = NULL; ++ rc_mutex_unlock(&load_state->client->state.mutex); ++ ++ if (pending_media) { ++ /* rc_client_check_pending_media will fail if it can't find the game in client->game or ++ * client->state.load->game. since we've detached the load_state, this has to occur after ++ * we've made the game active. */ ++ if (pending_media->hash) { ++ rc_client_begin_change_media(client, pending_media->hash, ++ pending_media->callback, pending_media->callback_userdata); ++ } else { ++#ifdef RC_CLIENT_SUPPORTS_HASH ++ rc_client_begin_identify_and_change_media(client, pending_media->file_path, ++ pending_media->data, pending_media->data_size, ++ pending_media->callback, pending_media->callback_userdata); ++#endif ++ } ++ rc_client_free_pending_media(pending_media); ++ } ++ ++ rc_mutex_lock(&client->state.mutex); ++ if (client->state.load != load_state) ++ load_state->progress = RC_CLIENT_LOAD_GAME_STATE_ABORTED; ++ rc_mutex_unlock(&client->state.mutex); ++ } ++ ++ /* if the game is still being loaded, make sure all the required memory addresses are accessible ++ * so we can mark achievements as unsupported before loading them into the runtime. */ ++ if (load_state->progress != RC_CLIENT_LOAD_GAME_STATE_ABORTED) { ++ /* ASSERT: client->game must be set before calling this function so the read_memory callback can query the console_id */ ++ rc_client_validate_addresses(load_state->game, client); ++ ++ rc_mutex_lock(&client->state.mutex); ++ if (client->state.load != load_state) ++ load_state->progress = RC_CLIENT_LOAD_GAME_STATE_ABORTED; ++ rc_mutex_unlock(&client->state.mutex); ++ } ++ ++ /* if the game is still being loaded, load any active acheivements/leaderboards into the runtime */ ++ if (load_state->progress != RC_CLIENT_LOAD_GAME_STATE_ABORTED) { ++ rc_client_activate_achievements(load_state->game, client); ++ rc_client_activate_leaderboards(load_state->game, client); ++ ++ /* detach the load state to indicate that loading is fully complete */ ++ rc_mutex_lock(&client->state.mutex); ++ if (client->state.load == load_state) ++ client->state.load = NULL; ++ else ++ load_state->progress = RC_CLIENT_LOAD_GAME_STATE_ABORTED; ++ rc_mutex_unlock(&client->state.mutex); ++ } ++ ++ /* one last sanity check to make sure the game is still being loaded. */ ++ if (load_state->progress == RC_CLIENT_LOAD_GAME_STATE_ABORTED) { ++ /* game has been unloaded, or another game is being loaded over the top of this game */ ++ if (load_state->callback) ++ load_state->callback(RC_ABORTED, "The requested game is no longer active", client, load_state->callback_userdata); ++ } ++ else { ++ if (load_state->hash->hash[0] != '[') { ++ if (load_state->client->state.spectator_mode != RC_CLIENT_SPECTATOR_MODE_LOCKED) { ++ /* schedule the periodic ping */ ++ rc_client_scheduled_callback_data_t* callback_data = (rc_client_scheduled_callback_data_t*) ++ rc_buffer_alloc(&load_state->game->buffer, sizeof(rc_client_scheduled_callback_data_t)); ++ ++ memset(callback_data, 0, sizeof(*callback_data)); ++ callback_data->callback = rc_client_ping; ++ callback_data->related_id = load_state->game->public_.id; ++ callback_data->when = client->callbacks.get_time_millisecs(client) + 30 * 1000; ++ rc_client_schedule_callback(client, callback_data); ++ } ++ ++ RC_CLIENT_LOG_INFO_FORMATTED(client, "Game %u loaded, hardcore %s%s", load_state->game->public_.id, ++ client->state.hardcore ? "enabled" : "disabled", ++ (client->state.spectator_mode != RC_CLIENT_SPECTATOR_MODE_OFF) ? ", spectating" : ""); ++ } ++ else { ++ RC_CLIENT_LOG_INFO_FORMATTED(client, "Subset %u loaded", load_state->subset->public_.id); ++ } ++ ++ if (load_state->callback) ++ load_state->callback(RC_OK, NULL, client, load_state->callback_userdata); ++ ++ /* detach the game object so it doesn't get freed by free_load_state */ ++ load_state->game = NULL; ++ } ++ } ++ ++ rc_client_free_load_state(load_state); ++} ++ ++static void rc_client_dispatch_activate_game(struct rc_client_scheduled_callback_data_t* callback_data, rc_client_t* client, rc_clock_t now) ++{ ++ rc_client_load_state_t* load_state = (rc_client_load_state_t*)callback_data->data; ++ free(callback_data); ++ ++ (void)client; ++ (void)now; ++ ++ rc_client_activate_game(load_state, load_state->start_session_response); ++} ++ ++static void rc_client_queue_activate_game(rc_client_load_state_t* load_state) ++{ ++ rc_client_scheduled_callback_data_t* scheduled_callback_data = ++ (rc_client_scheduled_callback_data_t*)calloc(1, sizeof(rc_client_scheduled_callback_data_t)); ++ ++ if (!scheduled_callback_data) { ++ rc_client_load_error(load_state, RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY)); ++ return; ++ } ++ ++ scheduled_callback_data->callback = rc_client_dispatch_activate_game; ++ scheduled_callback_data->data = load_state; ++ ++ rc_client_schedule_callback(load_state->client, scheduled_callback_data); ++} ++ ++static void rc_client_start_session_callback(const rc_api_server_response_t* server_response, void* callback_data) ++{ ++ rc_client_load_state_t* load_state = (rc_client_load_state_t*)callback_data; ++ rc_api_start_session_response_t start_session_response; ++ int outstanding_requests; ++ const char* error_message; ++ int result; ++ ++ result = rc_client_end_async(load_state->client, &load_state->async_handle); ++ if (result) { ++ if (result != RC_CLIENT_ASYNC_DESTROYED) { ++ rc_client_t* client = load_state->client; ++ rc_client_load_aborted(load_state); ++ RC_CLIENT_LOG_VERBOSE(client, "Load aborted while starting session"); ++ } else { ++ rc_client_free_load_state(load_state); ++ } ++ return; ++ } ++ ++ result = rc_api_process_start_session_server_response(&start_session_response, server_response); ++ error_message = rc_client_server_error_message(&result, server_response->http_status_code, &start_session_response.response); ++ outstanding_requests = rc_client_end_load_state(load_state); ++ ++ if (error_message) { ++ rc_client_load_error(load_state, result, error_message); ++ } ++ else if (outstanding_requests < 0) { ++ /* previous load state was aborted, load_state was free'd */ ++ } ++ else if (outstanding_requests == 0 && load_state->client->state.allow_background_memory_reads) { ++ rc_client_activate_game(load_state, &start_session_response); ++ } ++ else { ++ load_state->start_session_response = ++ (rc_api_start_session_response_t*)malloc(sizeof(rc_api_start_session_response_t)); ++ ++ if (!load_state->start_session_response) { ++ rc_client_load_error(load_state, RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY)); ++ } ++ else { ++ /* safer to parse the response again than to try to copy it */ ++ rc_api_process_start_session_response(load_state->start_session_response, server_response->body); ++ } ++ ++ if (outstanding_requests == 0) { ++ if (load_state->client->state.allow_background_memory_reads) ++ rc_client_activate_game(load_state, load_state->start_session_response); ++ else ++ rc_client_queue_activate_game(load_state); ++ } ++ } ++ ++ rc_api_destroy_start_session_response(&start_session_response); ++} ++ ++static void rc_client_begin_start_session(rc_client_load_state_t* load_state) ++{ ++ rc_api_start_session_request_t start_session_params; ++ rc_client_t* client = load_state->client; ++ rc_api_request_t start_session_request; ++ int result; ++ ++ memset(&start_session_params, 0, sizeof(start_session_params)); ++ start_session_params.username = client->user.username; ++ start_session_params.api_token = client->user.token; ++ start_session_params.game_id = load_state->hash->game_id; ++ start_session_params.game_hash = load_state->hash->hash; ++ start_session_params.hardcore = client->state.hardcore; ++ ++ result = rc_api_init_start_session_request_hosted(&start_session_request, &start_session_params, &client->state.host); ++ if (result != RC_OK) { ++ rc_client_load_error(load_state, result, rc_error_str(result)); ++ } ++ else { ++ rc_client_begin_load_state(load_state, RC_CLIENT_LOAD_GAME_STATE_STARTING_SESSION, 1); ++ RC_CLIENT_LOG_VERBOSE_FORMATTED(client, "Starting session for game %u", start_session_params.game_id); ++ rc_client_begin_async(client, &load_state->async_handle); ++ client->callbacks.server_call(&start_session_request, rc_client_start_session_callback, load_state, client); ++ rc_api_destroy_request(&start_session_request); ++ } ++} ++ ++static void rc_client_copy_achievements(rc_client_load_state_t* load_state, ++ rc_client_subset_info_t* subset, ++ const rc_api_achievement_definition_t* achievement_definitions, uint32_t num_achievements) ++{ ++ const rc_api_achievement_definition_t* read; ++ const rc_api_achievement_definition_t* stop; ++ rc_client_achievement_info_t* achievements; ++ rc_client_achievement_info_t* achievement; ++ rc_client_achievement_info_t* scan; ++ rc_buffer_t* buffer; ++ rc_preparse_state_t preparse; ++ const char* memaddr; ++ size_t size; ++ rc_trigger_t* trigger; ++ int trigger_size; ++ ++ subset->achievements = NULL; ++ subset->public_.num_achievements = num_achievements; ++ ++ if (num_achievements == 0) ++ return; ++ ++ stop = achievement_definitions + num_achievements; ++ ++ /* if not testing unofficial, filter them out */ ++ if (!load_state->client->state.unofficial_enabled) { ++ for (read = achievement_definitions; read < stop; ++read) { ++ if (read->category != RC_ACHIEVEMENT_CATEGORY_CORE) ++ --num_achievements; ++ } ++ ++ subset->public_.num_achievements = num_achievements; ++ ++ if (num_achievements == 0) ++ return; ++ } ++ ++ /* preallocate space for achievements */ ++ size = 24 /* assume average title length of 24 */ ++ + 48 /* assume average description length of 48 */ ++ + sizeof(rc_trigger_t) + sizeof(rc_condset_t) * 2 /* trigger container */ ++ + sizeof(rc_condition_t) * 8 /* assume average trigger length of 8 conditions */ ++ + sizeof(rc_client_achievement_info_t); ++ buffer = &load_state->game->buffer; ++ rc_buffer_reserve(buffer, size * num_achievements); ++ ++ /* allocate the achievement array */ ++ size = sizeof(rc_client_achievement_info_t) * num_achievements; ++ achievement = achievements = (rc_client_achievement_info_t*)rc_buffer_alloc(buffer, size); ++ memset(achievements, 0, size); ++ ++ /* copy the achievement data */ ++ for (read = achievement_definitions; read < stop; ++read) { ++ if (read->category != RC_ACHIEVEMENT_CATEGORY_CORE && !load_state->client->state.unofficial_enabled) ++ continue; ++ ++ achievement->public_.title = rc_buffer_strcpy(buffer, read->title); ++ achievement->public_.description = rc_buffer_strcpy(buffer, read->description); ++ snprintf(achievement->public_.badge_name, sizeof(achievement->public_.badge_name), "%s", read->badge_name); ++ achievement->public_.id = read->id; ++ achievement->public_.points = read->points; ++ achievement->public_.category = (read->category != RC_ACHIEVEMENT_CATEGORY_CORE) ? ++ RC_CLIENT_ACHIEVEMENT_CATEGORY_UNOFFICIAL : RC_CLIENT_ACHIEVEMENT_CATEGORY_CORE; ++ achievement->public_.rarity = read->rarity; ++ achievement->public_.rarity_hardcore = read->rarity_hardcore; ++ achievement->public_.type = read->type; /* assert: mapping is 1:1 */ ++ achievement->public_.badge_url = rc_buffer_strcpy(buffer, read->badge_url); ++ achievement->public_.badge_locked_url = rc_buffer_strcpy(buffer, read->badge_locked_url); ++ ++ memaddr = read->definition; ++ rc_runtime_checksum(memaddr, achievement->md5); ++ ++ rc_init_preparse_state(&preparse); ++ preparse.parse.existing_memrefs = load_state->game->runtime.memrefs; ++ trigger = RC_ALLOC(rc_trigger_t, &preparse.parse); ++ rc_parse_trigger_internal(trigger, &memaddr, &preparse.parse); ++ ++ trigger_size = preparse.parse.offset; ++ if (trigger_size < 0) { ++ RC_CLIENT_LOG_WARN_FORMATTED(load_state->client, "Parse error %d processing achievement %u", trigger_size, read->id); ++ achievement->public_.state = RC_CLIENT_ACHIEVEMENT_STATE_DISABLED; ++ achievement->public_.bucket = RC_CLIENT_ACHIEVEMENT_BUCKET_UNSUPPORTED; ++ } ++ else { ++ /* populate the item, using the communal memrefs pool */ ++ rc_reset_parse_state(&preparse.parse, rc_buffer_reserve(buffer, trigger_size)); ++ rc_preparse_reserve_memrefs(&preparse, load_state->game->runtime.memrefs); ++ achievement->trigger = RC_ALLOC(rc_trigger_t, &preparse.parse); ++ memaddr = read->definition; ++ rc_parse_trigger_internal(achievement->trigger, &memaddr, &preparse.parse); ++ ++ if (preparse.parse.offset < 0) { ++ RC_CLIENT_LOG_WARN_FORMATTED(load_state->client, "Parse error %d processing achievement %u", preparse.parse.offset, read->id); ++ achievement->public_.state = RC_CLIENT_ACHIEVEMENT_STATE_DISABLED; ++ achievement->public_.bucket = RC_CLIENT_ACHIEVEMENT_BUCKET_UNSUPPORTED; ++ } ++ else { ++ rc_buffer_consume(buffer, (const uint8_t*)preparse.parse.buffer, (uint8_t*)preparse.parse.buffer + preparse.parse.offset); ++ } ++ ++ rc_destroy_preparse_state(&preparse); ++ } ++ ++ achievement->created_time = read->created; ++ achievement->updated_time = read->updated; ++ ++ scan = achievement; ++ while (scan > achievements) { ++ --scan; ++ if (strcmp(scan->author, read->author) == 0) { ++ achievement->author = scan->author; ++ break; ++ } ++ } ++ if (!achievement->author) ++ achievement->author = rc_buffer_strcpy(buffer, read->author); ++ ++ ++achievement; ++ } ++ ++ subset->achievements = achievements; ++} ++ ++uint8_t rc_client_map_leaderboard_format(int format) ++{ ++ switch (format) { ++ case RC_FORMAT_SECONDS: ++ case RC_FORMAT_CENTISECS: ++ case RC_FORMAT_MINUTES: ++ case RC_FORMAT_SECONDS_AS_MINUTES: ++ case RC_FORMAT_FRAMES: ++ return RC_CLIENT_LEADERBOARD_FORMAT_TIME; ++ ++ case RC_FORMAT_SCORE: ++ return RC_CLIENT_LEADERBOARD_FORMAT_SCORE; ++ ++ case RC_FORMAT_VALUE: ++ case RC_FORMAT_FLOAT1: ++ case RC_FORMAT_FLOAT2: ++ case RC_FORMAT_FLOAT3: ++ case RC_FORMAT_FLOAT4: ++ case RC_FORMAT_FLOAT5: ++ case RC_FORMAT_FLOAT6: ++ case RC_FORMAT_FIXED1: ++ case RC_FORMAT_FIXED2: ++ case RC_FORMAT_FIXED3: ++ case RC_FORMAT_TENS: ++ case RC_FORMAT_HUNDREDS: ++ case RC_FORMAT_THOUSANDS: ++ case RC_FORMAT_UNSIGNED_VALUE: ++ default: ++ return RC_CLIENT_LEADERBOARD_FORMAT_VALUE; ++ } ++} ++ ++static void rc_client_copy_leaderboards(rc_client_load_state_t* load_state, ++ rc_client_subset_info_t* subset, ++ const rc_api_leaderboard_definition_t* leaderboard_definitions, uint32_t num_leaderboards) ++{ ++ const rc_api_leaderboard_definition_t* read; ++ const rc_api_leaderboard_definition_t* stop; ++ rc_client_leaderboard_info_t* leaderboards; ++ rc_client_leaderboard_info_t* leaderboard; ++ rc_buffer_t* buffer; ++ rc_preparse_state_t preparse; ++ const char* memaddr; ++ const char* ptr; ++ size_t size; ++ rc_lboard_t* lboard; ++ int lboard_size; ++ ++ subset->leaderboards = NULL; ++ subset->public_.num_leaderboards = num_leaderboards; ++ ++ if (num_leaderboards == 0) ++ return; ++ ++ /* preallocate space for achievements */ ++ size = 24 /* assume average title length of 24 */ ++ + 48 /* assume average description length of 48 */ ++ + sizeof(rc_lboard_t) /* lboard container */ ++ + (sizeof(rc_trigger_t) + sizeof(rc_condset_t) * 2) * 3 /* start/submit/cancel */ ++ + (sizeof(rc_value_t) + sizeof(rc_condset_t)) /* value */ ++ + sizeof(rc_condition_t) * 4 * 4 /* assume average of 4 conditions in each start/submit/cancel/value */ ++ + sizeof(rc_client_leaderboard_info_t); ++ rc_buffer_reserve(&load_state->game->buffer, size * num_leaderboards); ++ ++ /* allocate the achievement array */ ++ size = sizeof(rc_client_leaderboard_info_t) * num_leaderboards; ++ buffer = &load_state->game->buffer; ++ leaderboard = leaderboards = (rc_client_leaderboard_info_t*)rc_buffer_alloc(buffer, size); ++ memset(leaderboards, 0, size); ++ ++ /* copy the achievement data */ ++ read = leaderboard_definitions; ++ stop = read + num_leaderboards; ++ do { ++ leaderboard->public_.title = rc_buffer_strcpy(buffer, read->title); ++ leaderboard->public_.description = rc_buffer_strcpy(buffer, read->description); ++ leaderboard->public_.id = read->id; ++ leaderboard->public_.format = rc_client_map_leaderboard_format(read->format); ++ leaderboard->public_.lower_is_better = read->lower_is_better; ++ leaderboard->format = (uint8_t)read->format; ++ leaderboard->hidden = (uint8_t)read->hidden; ++ ++ memaddr = read->definition; ++ rc_runtime_checksum(memaddr, leaderboard->md5); ++ ++ ptr = strstr(memaddr, "VAL:"); ++ if (ptr != NULL) { ++ /* calculate the DJB2 hash of the VAL portion of the string*/ ++ uint32_t hash = 5381; ++ ptr += 4; /* skip 'VAL:' */ ++ while (*ptr && (ptr[0] != ':' || ptr[1] != ':')) ++ hash = (hash << 5) + hash + *ptr++; ++ leaderboard->value_djb2 = hash; ++ } ++ ++ rc_init_preparse_state(&preparse); ++ preparse.parse.existing_memrefs = load_state->game->runtime.memrefs; ++ lboard = RC_ALLOC(rc_lboard_t, &preparse.parse); ++ rc_parse_lboard_internal(lboard, memaddr, &preparse.parse); ++ ++ lboard_size = preparse.parse.offset; ++ if (lboard_size < 0) { ++ RC_CLIENT_LOG_WARN_FORMATTED(load_state->client, "Parse error %d processing leaderboard %u", lboard_size, read->id); ++ leaderboard->public_.state = RC_CLIENT_LEADERBOARD_STATE_DISABLED; ++ } ++ else { ++ /* populate the item, using the communal memrefs pool */ ++ rc_reset_parse_state(&preparse.parse, rc_buffer_reserve(buffer, lboard_size)); ++ rc_preparse_reserve_memrefs(&preparse, load_state->game->runtime.memrefs); ++ leaderboard->lboard = RC_ALLOC(rc_lboard_t, &preparse.parse); ++ rc_parse_lboard_internal(leaderboard->lboard, memaddr, &preparse.parse); ++ ++ if (preparse.parse.offset < 0) { ++ RC_CLIENT_LOG_WARN_FORMATTED(load_state->client, "Parse error %d processing leaderboard %u", preparse.parse.offset, read->id); ++ leaderboard->public_.state = RC_CLIENT_LEADERBOARD_STATE_DISABLED; ++ } ++ else { ++ rc_buffer_consume(buffer, (const uint8_t*)preparse.parse.buffer, (uint8_t*)preparse.parse.buffer + preparse.parse.offset); ++ } ++ ++ rc_destroy_preparse_state(&preparse); ++ } ++ ++ ++leaderboard; ++ ++read; ++ } while (read < stop); ++ ++ subset->leaderboards = leaderboards; ++} ++ ++static void rc_client_fetch_game_sets_callback(const rc_api_server_response_t* server_response, void* callback_data) ++{ ++ rc_client_load_state_t* load_state = (rc_client_load_state_t*)callback_data; ++ rc_api_fetch_game_sets_response_t fetch_game_sets_response; ++ int outstanding_requests; ++ const char* error_message; ++ int result; ++ ++ result = rc_client_end_async(load_state->client, &load_state->async_handle); ++ if (result) { ++ if (result != RC_CLIENT_ASYNC_DESTROYED) { ++ rc_client_t* client = load_state->client; ++ rc_client_load_aborted(load_state); ++ RC_CLIENT_LOG_VERBOSE(client, "Load aborted while fetching game data"); ++ } else { ++ rc_client_free_load_state(load_state); ++ } ++ return; ++ } ++ ++ result = rc_api_process_fetch_game_sets_server_response(&fetch_game_sets_response, server_response); ++ error_message = rc_client_server_error_message(&result, server_response->http_status_code, &fetch_game_sets_response.response); ++ ++ outstanding_requests = rc_client_end_load_state(load_state); ++ ++ if (error_message && result != RC_NOT_FOUND) { ++ rc_client_load_error(load_state, result, error_message); ++ } ++ else if (outstanding_requests < 0) { ++ /* previous load state was aborted, load_state was free'd */ ++ } ++ else if (fetch_game_sets_response.id == 0) { ++ load_state->hash->game_id = 0; ++ rc_client_process_resolved_hash(load_state); ++ } ++ else { ++ rc_client_subset_info_t** next_subset; ++ rc_client_subset_info_t* first_subset = NULL; ++ uint32_t set_index; ++ ++ /* hash exists outside the load state - always update it */ ++ load_state->hash->game_id = fetch_game_sets_response.id; ++ RC_CLIENT_LOG_INFO_FORMATTED(load_state->client, "Identified game: %u \"%s\" (%s)", load_state->hash->game_id, fetch_game_sets_response.title, load_state->hash->hash); ++ ++ if (load_state->hash->hash[0] != '[') { ++ /* not [NO HASH] or [SUBSETxx] */ ++ load_state->game->public_.id = load_state->hash->game_id; ++ load_state->game->public_.hash = load_state->hash->hash; ++ } ++ ++ if (load_state->game->public_.console_id != RC_CONSOLE_UNKNOWN && ++ fetch_game_sets_response.console_id != load_state->game->public_.console_id) { ++ RC_CLIENT_LOG_WARN_FORMATTED(load_state->client, "Data for game %u is for console %u, expecting console %u", ++ fetch_game_sets_response.id, fetch_game_sets_response.console_id, load_state->game->public_.console_id); ++ } ++ ++ /* kick off the start session request while we process the game data */ ++ rc_client_begin_load_state(load_state, RC_CLIENT_LOAD_GAME_STATE_STARTING_SESSION, 1); ++ if (load_state->client->state.spectator_mode != RC_CLIENT_SPECTATOR_MODE_OFF) { ++ /* we can't unlock achievements without a session, lock spectator mode for the game */ ++ load_state->client->state.spectator_mode = RC_CLIENT_SPECTATOR_MODE_LOCKED; ++ } ++ else { ++ rc_client_begin_start_session(load_state); ++ } ++ ++ /* process the game data */ ++ next_subset = &first_subset; ++ for (set_index = 0; set_index < fetch_game_sets_response.num_sets; ++set_index) { ++ rc_api_achievement_set_definition_t* set = &fetch_game_sets_response.sets[set_index]; ++ rc_client_subset_info_t* subset; ++ ++ subset = (rc_client_subset_info_t*)rc_buffer_alloc(&load_state->game->buffer, sizeof(rc_client_subset_info_t)); ++ memset(subset, 0, sizeof(*subset)); ++ subset->public_.id = set->id; ++ subset->active = 1; ++ snprintf(subset->public_.badge_name, sizeof(subset->public_.badge_name), "%s", set->image_name); ++ subset->public_.badge_url = rc_buffer_strcpy(&load_state->game->buffer, set->image_url); ++ subset->public_.title = rc_buffer_strcpy(&load_state->game->buffer, set->title); ++ ++ rc_client_copy_achievements(load_state, subset, set->achievements, set->num_achievements); ++ rc_client_copy_leaderboards(load_state, subset, set->leaderboards, set->num_leaderboards); ++ ++ if (set->type == RC_ACHIEVEMENT_SET_TYPE_CORE) { ++ if (!first_subset) ++ next_subset = &subset->next; ++ subset->next = first_subset; ++ first_subset = subset; ++ } ++ else { ++ *next_subset = subset; ++ next_subset = &subset->next; ++ } ++ } ++ ++ if (!first_subset) { ++ rc_client_load_error(load_state, RC_NOT_FOUND, "Response contained no sets"); ++ } else { ++ load_state->subset = first_subset; ++ ++ /* core set */ ++ rc_mutex_lock(&load_state->client->state.mutex); ++ load_state->game->public_.title = rc_buffer_strcpy(&load_state->game->buffer, fetch_game_sets_response.title); ++ load_state->game->subsets = first_subset; ++ load_state->game->public_.badge_name = first_subset->public_.badge_name; ++ load_state->game->public_.badge_url = first_subset->public_.badge_url; ++ load_state->game->public_.console_id = fetch_game_sets_response.console_id; ++ rc_mutex_unlock(&load_state->client->state.mutex); ++ ++ if (fetch_game_sets_response.rich_presence_script && fetch_game_sets_response.rich_presence_script[0]) { ++ result = rc_runtime_activate_richpresence(&load_state->game->runtime, fetch_game_sets_response.rich_presence_script, NULL, 0); ++ if (result != RC_OK) { ++ RC_CLIENT_LOG_WARN_FORMATTED(load_state->client, "Parse error %d processing rich presence", result); ++ } ++ } ++ ++ if (load_state->client->callbacks.post_process_game_sets_response) { ++ load_state->client->callbacks.post_process_game_sets_response(server_response, ++ &fetch_game_sets_response, load_state->client, load_state->callback_userdata); ++ } ++ } ++ ++ outstanding_requests = rc_client_end_load_state(load_state); ++ if (outstanding_requests < 0) { ++ /* previous load state was aborted, load_state was free'd */ ++ } ++ else if (outstanding_requests == 0) { ++ if (load_state->client->state.allow_background_memory_reads) ++ rc_client_activate_game(load_state, load_state->start_session_response); ++ else ++ rc_client_queue_activate_game(load_state); ++ } ++ } ++ ++ rc_api_destroy_fetch_game_sets_response(&fetch_game_sets_response); ++} ++ ++static rc_client_game_info_t* rc_client_allocate_game(void) ++{ ++ rc_client_game_info_t* game = (rc_client_game_info_t*)calloc(1, sizeof(*game)); ++ if (!game) ++ return NULL; ++ ++ rc_buffer_init(&game->buffer); ++ rc_runtime_init(&game->runtime); ++ ++ return game; ++} ++ ++static int rc_client_attach_load_state(rc_client_t* client, rc_client_load_state_t* load_state) ++{ ++ if (client->state.load == NULL) { ++ rc_client_unload_game(client); ++ ++ if (load_state->game == NULL) { ++ load_state->game = rc_client_allocate_game(); ++ if (!load_state->game) { ++ if (load_state->callback) ++ load_state->callback(RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY), client, load_state->callback_userdata); ++ ++ return 0; ++ } ++ } ++ ++ rc_mutex_lock(&client->state.mutex); ++ client->state.load = load_state; ++ client->state.frames_processed = client->state.frames_at_last_ping = 0; ++ rc_mutex_unlock(&client->state.mutex); ++ } ++ else if (client->state.load != load_state) { ++ /* previous load was aborted */ ++ if (load_state->callback) ++ load_state->callback(RC_ABORTED, "The requested game is no longer active", client, load_state->callback_userdata); ++ ++ return 0; ++ } ++ ++ return 1; ++} ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ ++static void rc_client_external_load_state_callback(int result, const char* error_message, rc_client_t* client, void* userdata) ++{ ++ rc_client_load_state_t* load_state = (rc_client_load_state_t*)userdata; ++ int async_aborted; ++ ++ client = load_state->client; ++ async_aborted = rc_client_end_async(client, &load_state->async_handle); ++ if (async_aborted) { ++ if (async_aborted != RC_CLIENT_ASYNC_DESTROYED) { ++ RC_CLIENT_LOG_VERBOSE(client, "Load aborted during external loading"); ++ } ++ ++ rc_client_unload_game(client); /* unload the game from the external client */ ++ rc_client_free_load_state(load_state); ++ return; ++ } ++ ++ if (result != RC_OK) { ++ rc_client_load_error(load_state, result, error_message); ++ return; ++ } ++ ++ rc_mutex_lock(&client->state.mutex); ++ load_state->progress = (client->state.load == load_state) ? ++ RC_CLIENT_LOAD_GAME_STATE_DONE : RC_CLIENT_LOAD_GAME_STATE_ABORTED; ++ client->state.load = NULL; ++ rc_mutex_unlock(&client->state.mutex); ++ ++ if (load_state->progress != RC_CLIENT_LOAD_GAME_STATE_DONE) { ++ /* previous load state was aborted */ ++ if (load_state->callback) ++ load_state->callback(RC_ABORTED, "The requested game is no longer active", client, load_state->callback_userdata); ++ } ++ else { ++ /* keep partial game object for media_hash management */ ++ if (client->state.external_client) { ++ const rc_client_game_t* info = rc_client_get_game_info(client); ++ load_state->game->public_.console_id = info->console_id; ++ client->game = load_state->game; ++ load_state->game = NULL; ++ } ++ ++ if (load_state->callback) ++ load_state->callback(RC_OK, NULL, client, load_state->callback_userdata); ++ } ++ ++ rc_client_free_load_state(load_state); ++} ++ ++#endif ++ ++static void rc_client_initialize_unknown_game(rc_client_game_info_t* game) ++{ ++ rc_client_subset_info_t* subset; ++ char buffer[64]; ++ ++ subset = (rc_client_subset_info_t*)rc_buffer_alloc(&game->buffer, sizeof(rc_client_subset_info_t)); ++ memset(subset, 0, sizeof(*subset)); ++ subset->public_.title = ""; ++ game->subsets = subset; ++ ++ game->public_.title = "Unknown Game"; ++ game->public_.badge_name = ""; ++ ++ rc_client_get_image_url(buffer, sizeof(buffer), RC_IMAGE_TYPE_GAME, "000001"); ++ game->public_.badge_url = rc_buffer_strcpy(&game->buffer, buffer); ++} ++ ++static void rc_client_process_resolved_hash(rc_client_load_state_t* load_state) ++{ ++ rc_client_t* client = load_state->client; ++ ++ if (load_state->hash->game_id == 0) { ++#ifdef RC_CLIENT_SUPPORTS_HASH ++ char hash[33]; ++ ++ if (rc_hash_iterate(hash, &load_state->hash_iterator)) { ++ /* found another hash to try */ ++ load_state->hash_console_id = load_state->hash_iterator.consoles[load_state->hash_iterator.index - 1]; ++ rc_client_load_game(load_state, hash, NULL); ++ return; ++ } ++ ++ if (load_state->tried_hashes[1]) { ++ /* multiple hashes were tried, create a CSV */ ++ size_t i; ++ size_t count = 0; ++ char* ptr; ++ size_t size = 0; ++ ++ for (i = 0; i < sizeof(load_state->tried_hashes) / sizeof(load_state->tried_hashes[0]); ++i) { ++ if (!load_state->tried_hashes[i]) ++ break; ++ ++ size += strlen(load_state->tried_hashes[i]->hash) + 1; ++ count++; ++ } ++ ++ ptr = (char*)rc_buffer_alloc(&load_state->game->buffer, size); ++ load_state->game->public_.hash = ptr; ++ for (i = 0; i < count; i++) { ++ const size_t hash_len = strlen(load_state->tried_hashes[i]->hash); ++ memcpy(ptr, load_state->tried_hashes[i]->hash, hash_len); ++ ptr += hash_len; ++ *ptr++ = ','; ++ } ++ *(ptr - 1) = '\0'; ++ ++ load_state->game->public_.console_id = RC_CONSOLE_UNKNOWN; ++ } else { ++ /* only a single hash was tried, capture it */ ++ load_state->game->public_.console_id = load_state->hash_console_id; ++ load_state->game->public_.hash = load_state->hash->hash; ++ ++ if (client->callbacks.identify_unknown_hash) { ++ load_state->hash->game_id = client->callbacks.identify_unknown_hash( ++ load_state->hash_console_id, load_state->hash->hash, client, load_state->callback_userdata); ++ ++ if (load_state->hash->game_id != 0) { ++ load_state->hash->is_unknown = 1; ++ RC_CLIENT_LOG_INFO_FORMATTED(load_state->client, "Client says to load game %u for unidentified hash %s", ++ load_state->hash->game_id, load_state->hash->hash); ++ } ++ } ++ } ++ ++ rc_hash_destroy_iterator(&load_state->hash_iterator); /* done with this now */ ++#else ++ load_state->game->public_.console_id = RC_CONSOLE_UNKNOWN; ++ load_state->game->public_.hash = load_state->hash->hash; ++#endif /* RC_CLIENT_SUPPORTS_HASH */ ++ ++ if (load_state->hash->game_id == 0) { ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ #ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION ++ if (client->state.raintegration && client->state.raintegration->set_console_id) { ++ if (load_state->game->public_.console_id != RC_CONSOLE_UNKNOWN) ++ client->state.raintegration->set_console_id(load_state->game->public_.console_id); ++ } ++ #endif ++ if (client->state.external_client) { ++ if (client->state.external_client->load_unknown_game) { ++ client->state.external_client->load_unknown_game(load_state->game->public_.hash); ++ rc_client_load_error(load_state, RC_NO_GAME_LOADED, "Unknown game"); ++ return; ++ } ++ /* no external method specifically for unknown game, just pass the hash through to begin_load_game below */ ++ } ++ else { ++#endif ++ rc_client_initialize_unknown_game(load_state->game); ++ ++ client->game = load_state->game; ++ load_state->game = NULL; ++ ++ rc_client_load_error(load_state, RC_NO_GAME_LOADED, "Unknown game"); ++ return; ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ } ++#endif ++ } ++ } ++ ++ if (load_state->hash->hash[0] != '[') { /* not [NO HASH] or [SUBSETxx] */ ++ load_state->game->public_.id = load_state->hash->game_id; ++ load_state->game->public_.hash = load_state->hash->hash; ++ } ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client) { ++ if (client->state.external_client->add_game_hash) ++ client->state.external_client->add_game_hash(load_state->hash->hash, load_state->hash->game_id); ++ ++ if (client->state.external_client->begin_load_game) { ++ rc_client_begin_async(client, &load_state->async_handle); ++ client->state.external_client->begin_load_game(client, load_state->hash->hash, rc_client_external_load_state_callback, load_state); ++ } ++ return; ++ } ++#endif ++ ++ rc_client_begin_fetch_game_sets(load_state); ++} ++ ++void rc_client_load_unknown_game(rc_client_t* client, const char* tried_hashes) ++{ ++ rc_client_game_info_t* game; ++ ++ game = rc_client_allocate_game(); ++ if (!game) ++ return; ++ ++ rc_client_initialize_unknown_game(game); ++ game->public_.console_id = RC_CONSOLE_UNKNOWN; ++ ++ if (strlen(tried_hashes) == 32) { /* only one hash tried, add it to the list */ ++ rc_client_game_hash_t* game_hash = rc_client_find_game_hash(client, tried_hashes); ++ game_hash->game_id = 0; ++ game->public_.hash = game_hash->hash; ++ } ++ else { ++ game->public_.hash = rc_buffer_strcpy(&game->buffer, tried_hashes); ++ } ++ ++ rc_client_unload_game(client); ++ client->game = game; ++} ++ ++static void rc_client_begin_fetch_game_sets(rc_client_load_state_t* load_state) ++{ ++ rc_api_fetch_game_sets_request_t fetch_game_sets_request; ++ rc_client_t* client = load_state->client; ++ rc_api_request_t request; ++ int result; ++ ++ rc_mutex_lock(&client->state.mutex); ++ result = client->state.user; ++ if (result == RC_CLIENT_USER_STATE_LOGIN_REQUESTED) ++ load_state->progress = RC_CLIENT_LOAD_GAME_STATE_AWAIT_LOGIN; ++ else ++ load_state->progress = RC_CLIENT_LOAD_GAME_STATE_FETCHING_GAME_DATA; ++ rc_mutex_unlock(&client->state.mutex); ++ ++ switch (result) { ++ case RC_CLIENT_USER_STATE_LOGGED_IN: ++ break; ++ ++ case RC_CLIENT_USER_STATE_LOGIN_REQUESTED: ++ /* do nothing, this function will be called again after login completes */ ++ return; ++ ++ default: ++ rc_client_load_error(load_state, RC_LOGIN_REQUIRED, rc_error_str(RC_LOGIN_REQUIRED)); ++ return; ++ } ++ ++ memset(&fetch_game_sets_request, 0, sizeof(fetch_game_sets_request)); ++ fetch_game_sets_request.username = client->user.username; ++ fetch_game_sets_request.api_token = client->user.token; ++ ++ if (load_state->hash->is_unknown) /* lookup failed, but client provided a mapping */ ++ fetch_game_sets_request.game_id = load_state->hash->game_id; ++ else ++ fetch_game_sets_request.game_hash = load_state->hash->hash; ++ ++ result = rc_api_init_fetch_game_sets_request_hosted(&request, &fetch_game_sets_request, &client->state.host); ++ if (result != RC_OK) { ++ rc_client_load_error(load_state, result, rc_error_str(result)); ++ return; ++ } ++ ++ rc_client_begin_load_state(load_state, RC_CLIENT_LOAD_GAME_STATE_IDENTIFYING_GAME, 1); ++ RC_CLIENT_LOG_VERBOSE_FORMATTED(client, "Fetching data for hash %s", fetch_game_sets_request.game_hash); ++ ++ rc_client_begin_async(client, &load_state->async_handle); ++ client->callbacks.server_call(&request, rc_client_fetch_game_sets_callback, load_state, client); ++ ++ rc_api_destroy_request(&request); ++} ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++static void rc_client_identify_game_callback(const rc_api_server_response_t* server_response, void* callback_data) ++{ ++ rc_client_load_state_t* load_state = (rc_client_load_state_t*)callback_data; ++ rc_client_t* client = load_state->client; ++ rc_api_resolve_hash_response_t resolve_hash_response; ++ int outstanding_requests; ++ const char* error_message; ++ int result; ++ ++ result = rc_client_end_async(client, &load_state->async_handle); ++ if (result) { ++ if (result != RC_CLIENT_ASYNC_DESTROYED) { ++ rc_client_load_aborted(load_state); ++ RC_CLIENT_LOG_VERBOSE(client, "Load aborted during game identification"); ++ } else { ++ rc_client_free_load_state(load_state); ++ } ++ return; ++ } ++ ++ result = rc_api_process_resolve_hash_server_response(&resolve_hash_response, server_response); ++ error_message = rc_client_server_error_message(&result, server_response->http_status_code, &resolve_hash_response.response); ++ ++ if (error_message) { ++ rc_client_end_load_state(load_state); ++ rc_client_load_error(load_state, result, error_message); ++ } ++ else { ++ /* hash exists outside the load state - always update it */ ++ load_state->hash->game_id = resolve_hash_response.game_id; ++ RC_CLIENT_LOG_INFO_FORMATTED(client, "Identified game: %u (%s)", load_state->hash->game_id, load_state->hash->hash); ++ ++ /* have to call end_load_state after updating hash in case the load_state gets free'd */ ++ outstanding_requests = rc_client_end_load_state(load_state); ++ if (outstanding_requests < 0) { ++ /* previous load state was aborted, load_state was free'd */ ++ } ++ else { ++ rc_client_process_resolved_hash(load_state); ++ } ++ } ++ ++ rc_api_destroy_resolve_hash_response(&resolve_hash_response); ++} ++#endif ++ ++rc_client_game_hash_t* rc_client_find_game_hash(rc_client_t* client, const char* hash) ++{ ++ rc_client_game_hash_t* game_hash; ++ ++ rc_mutex_lock(&client->state.mutex); ++ game_hash = client->hashes; ++ while (game_hash) { ++ if (strcasecmp(game_hash->hash, hash) == 0) ++ break; ++ ++ game_hash = game_hash->next; ++ } ++ ++ if (!game_hash) { ++ game_hash = (rc_client_game_hash_t*)rc_buffer_alloc(&client->state.buffer, sizeof(rc_client_game_hash_t)); ++ memset(game_hash, 0, sizeof(*game_hash)); ++ snprintf(game_hash->hash, sizeof(game_hash->hash), "%s", hash); ++ game_hash->game_id = RC_CLIENT_UNKNOWN_GAME_ID; ++ game_hash->next = client->hashes; ++ client->hashes = game_hash; ++ } ++ rc_mutex_unlock(&client->state.mutex); ++ ++ return game_hash; ++} ++ ++void rc_client_add_game_hash(rc_client_t* client, const char* hash, uint32_t game_id) ++{ ++ /* store locally, even if passing to external client */ ++ rc_client_game_hash_t* game_hash = rc_client_find_game_hash(client, hash); ++ game_hash->game_id = game_id; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->add_game_hash) ++ client->state.external_client->add_game_hash(hash, game_id); ++#endif ++} ++ ++static rc_client_async_handle_t* rc_client_load_game(rc_client_load_state_t* load_state, ++ const char* hash, const char* file_path) ++{ ++ rc_client_t* client = load_state->client; ++ rc_client_game_hash_t* old_hash; ++#ifdef RC_CLIENT_SUPPORTS_HASH ++ size_t i; ++#endif ++ ++ if (!rc_client_attach_load_state(client, load_state)) { ++ rc_client_free_load_state(load_state); ++ return NULL; ++ } ++ ++ old_hash = load_state->hash; ++ load_state->hash = rc_client_find_game_hash(client, hash); ++ ++#ifdef RC_CLIENT_SUPPORTS_HASH ++ i = 0; ++ do { ++ if (!load_state->tried_hashes[i]) { ++ load_state->tried_hashes[i] = load_state->hash; ++ break; ++ } ++ ++ if (load_state->tried_hashes[i] == load_state->hash) ++ break; ++ ++ if (++i == sizeof(load_state->tried_hashes) / sizeof(load_state->tried_hashes[0])) { ++ RC_CLIENT_LOG_VERBOSE(client, "tried_hashes buffer is full"); ++ break; ++ } ++ } while (1); ++#endif ++ ++ if (file_path) { ++ rc_client_media_hash_t* media_hash = ++ (rc_client_media_hash_t*)rc_buffer_alloc(&load_state->game->buffer, sizeof(*media_hash)); ++ media_hash->game_hash = load_state->hash; ++ media_hash->path_djb2 = rc_djb2(file_path); ++ media_hash->next = load_state->game->media_hash; ++ load_state->game->media_hash = media_hash; ++ } ++ else if (load_state->game->media_hash && load_state->game->media_hash->game_hash == old_hash) { ++ load_state->game->media_hash->game_hash = load_state->hash; ++ } ++ ++ if (load_state->hash->game_id == 0) { ++ rc_client_process_resolved_hash(load_state); ++ } ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ else if (load_state->hash->game_id == RC_CLIENT_UNKNOWN_GAME_ID && ++ client->state.external_client && client->state.external_client->add_game_hash) { ++ /* if an add_game_hash external handler exists, do the identification locally, then ++ * pass the resulting game_id/hash to the external client */ ++ rc_api_resolve_hash_request_t resolve_hash_request; ++ rc_api_request_t request; ++ int result; ++ ++ memset(&resolve_hash_request, 0, sizeof(resolve_hash_request)); ++ resolve_hash_request.game_hash = hash; ++ ++ result = rc_api_init_resolve_hash_request_hosted(&request, &resolve_hash_request, &client->state.host); ++ if (result != RC_OK) { ++ rc_client_load_error(load_state, result, rc_error_str(result)); ++ return NULL; ++ } ++ ++ rc_client_begin_load_state(load_state, RC_CLIENT_LOAD_GAME_STATE_IDENTIFYING_GAME, 1); ++ ++ rc_client_begin_async(client, &load_state->async_handle); ++ client->callbacks.server_call(&request, rc_client_identify_game_callback, load_state, client); ++ ++ rc_api_destroy_request(&request); ++ } ++ else if (load_state->hash->game_id != RC_CLIENT_UNKNOWN_GAME_ID && ++ client->state.external_client && client->state.external_client->begin_load_game) { ++ rc_client_begin_async(client, &load_state->async_handle); ++ client->state.external_client->begin_load_game(client, load_state->hash->hash, rc_client_external_load_state_callback, load_state); ++ } ++#endif ++ else { ++ rc_client_begin_fetch_game_sets(load_state); ++ } ++ ++ return (client->state.load == load_state) ? &load_state->async_handle : NULL; ++} ++ ++static void rc_client_abort_load_in_progress(rc_client_t* client) ++{ ++ rc_client_load_state_t* load_state; ++ ++ rc_mutex_lock(&client->state.mutex); ++ ++ load_state = client->state.load; ++ if (load_state) { ++ /* this mimics rc_client_abort_async without nesting the lock */ ++ load_state->async_handle.aborted = RC_CLIENT_ASYNC_ABORTED; ++ ++ client->state.load = NULL; ++ } ++ ++ rc_mutex_unlock(&client->state.mutex); ++ ++ if (load_state && load_state->callback) ++ load_state->callback(RC_ABORTED, "The requested game is no longer active", load_state->client, load_state->callback_userdata); ++} ++ ++rc_client_async_handle_t* rc_client_begin_load_game(rc_client_t* client, const char* hash, rc_client_callback_t callback, void* callback_userdata) ++{ ++ rc_client_load_state_t* load_state; ++ ++ if (!client) { ++ callback(RC_INVALID_STATE, "client is required", client, callback_userdata); ++ return NULL; ++ } ++ ++ if (!hash || !hash[0]) { ++ callback(RC_INVALID_STATE, "hash is required", client, callback_userdata); ++ return NULL; ++ } ++ ++ rc_client_abort_load_in_progress(client); ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->begin_load_game) ++ return client->state.external_client->begin_load_game(client, hash, callback, callback_userdata); ++#endif ++ ++ load_state = (rc_client_load_state_t*)calloc(1, sizeof(*load_state)); ++ if (!load_state) { ++ callback(RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY), client, callback_userdata); ++ return NULL; ++ } ++ ++ load_state->client = client; ++ load_state->callback = callback; ++ load_state->callback_userdata = callback_userdata; ++ ++ return rc_client_load_game(load_state, hash, NULL); ++} ++ ++#ifdef RC_CLIENT_SUPPORTS_HASH ++ ++rc_hash_iterator_t* rc_client_get_load_state_hash_iterator(rc_client_t* client) ++{ ++ if (client && client->state.load) ++ return &client->state.load->hash_iterator; ++ ++ return NULL; ++} ++ ++static void rc_client_log_hash_message_verbose(const char* message, const rc_hash_iterator_t* iterator) ++{ ++ const rc_client_load_state_t* load_state = (const rc_client_load_state_t*)iterator->userdata; ++ if (load_state->client->state.log_level >= RC_CLIENT_LOG_LEVEL_INFO) ++ rc_client_log_message(load_state->client, message); ++} ++ ++static void rc_client_log_hash_message_error(const char* message, const rc_hash_iterator_t* iterator) ++{ ++ const rc_client_load_state_t* load_state = (const rc_client_load_state_t*)iterator->userdata; ++ if (load_state->client->state.log_level >= RC_CLIENT_LOG_LEVEL_ERROR) ++ rc_client_log_message(load_state->client, message); ++} ++ ++void rc_client_set_hash_callbacks(rc_client_t* client, const struct rc_hash_callbacks* callbacks) ++{ ++ memcpy(&client->callbacks.hash, callbacks, sizeof(*callbacks)); ++ ++ if (!callbacks->verbose_message) ++ client->callbacks.hash.verbose_message = rc_client_log_hash_message_verbose; ++ if (!callbacks->error_message) ++ client->callbacks.hash.error_message = rc_client_log_hash_message_error; ++} ++ ++rc_client_async_handle_t* rc_client_begin_identify_and_load_game(rc_client_t* client, ++ uint32_t console_id, const char* file_path, ++ const uint8_t* data, size_t data_size, ++ rc_client_callback_t callback, void* callback_userdata) ++{ ++ rc_client_load_state_t* load_state; ++ char hash[33]; ++ ++ if (!client) { ++ callback(RC_INVALID_STATE, "client is required", client, callback_userdata); ++ return NULL; ++ } ++ ++ rc_client_abort_load_in_progress(client); ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ /* if a add_game_hash handler exists, do the identification locally, then pass the ++ * resulting game_id/hash to the external client */ ++ if (client->state.external_client && !client->state.external_client->add_game_hash) { ++ if (client->state.external_client->begin_identify_and_load_game) ++ return client->state.external_client->begin_identify_and_load_game(client, console_id, file_path, data, data_size, callback, callback_userdata); ++ } ++#endif ++ ++ if (data) { ++ if (file_path) { ++ RC_CLIENT_LOG_INFO_FORMATTED(client, "Identifying game: %zu bytes at %p (%s)", data_size, data, file_path); ++ } ++ else { ++ RC_CLIENT_LOG_INFO_FORMATTED(client, "Identifying game: %zu bytes at %p", data_size, data); ++ } ++ } ++ else if (file_path) { ++ RC_CLIENT_LOG_INFO_FORMATTED(client, "Identifying game: %s", file_path); ++ } ++ else { ++ callback(RC_INVALID_STATE, "either data or file_path is required", client, callback_userdata); ++ return NULL; ++ } ++ ++ if (!file_path) ++ file_path = "?"; ++ ++ load_state = (rc_client_load_state_t*)calloc(1, sizeof(*load_state)); ++ if (!load_state) { ++ callback(RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY), client, callback_userdata); ++ return NULL; ++ } ++ load_state->client = client; ++ load_state->callback = callback; ++ load_state->callback_userdata = callback_userdata; ++ ++ /* initialize the iterator */ ++ rc_hash_initialize_iterator(&load_state->hash_iterator, file_path, data, data_size); ++ rc_hash_merge_callbacks(&load_state->hash_iterator, &client->callbacks.hash); ++ load_state->hash_iterator.userdata = load_state; ++ ++ if (!load_state->hash_iterator.callbacks.verbose_message) ++ load_state->hash_iterator.callbacks.verbose_message = rc_client_log_hash_message_verbose; ++ if (!load_state->hash_iterator.callbacks.error_message) ++ load_state->hash_iterator.callbacks.error_message = rc_client_log_hash_message_error; ++ ++ /* calculate the hash */ ++ if (console_id == RC_CONSOLE_UNKNOWN) { ++ if (!rc_hash_iterate(hash, &load_state->hash_iterator)) { ++ rc_client_load_error(load_state, RC_INVALID_STATE, "hash generation failed"); ++ return NULL; ++ } ++ ++ load_state->hash_console_id = load_state->hash_iterator.consoles[load_state->hash_iterator.index - 1]; ++ } ++ else { ++ /* ASSERT: hash_iterator->index and hash_iterator->consoles[0] will be 0 from calloc */ ++ load_state->hash_console_id = console_id; ++ ++ /* prevent initializing the iterator so it won't try other consoles in rc_client_process_resolved_hash */ ++ load_state->hash_iterator.index = 0; ++ ++ if (!rc_hash_generate(hash, console_id, &load_state->hash_iterator)) { ++ rc_client_load_error(load_state, RC_INVALID_STATE, "hash generation failed"); ++ return NULL; ++ } ++ } ++ ++ return rc_client_load_game(load_state, hash, file_path); ++} ++ ++#endif /* RC_CLIENT_SUPPORTS_HASH */ ++ ++int rc_client_get_load_game_state(const rc_client_t* client) ++{ ++ int state = RC_CLIENT_LOAD_GAME_STATE_NONE; ++ if (client) { ++ const rc_client_load_state_t* load_state = client->state.load; ++ if (load_state) ++ state = load_state->progress; ++ else if (client->game) ++ state = RC_CLIENT_LOAD_GAME_STATE_DONE; ++ } ++ ++ return state; ++} ++ ++int rc_client_is_game_loaded(const rc_client_t* client) ++{ ++ if (!client) ++ return 0; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client) { ++ const rc_client_game_t* game = rc_client_get_game_info(client); ++ return (game && game->id != 0); ++ } ++#endif ++ ++ return (client->game && client->game->public_.id != 0); ++} ++ ++static void rc_client_game_mark_ui_to_be_hidden(rc_client_t* client, rc_client_game_info_t* game) ++{ ++ rc_client_achievement_info_t* achievement; ++ rc_client_achievement_info_t* achievement_stop; ++ rc_client_leaderboard_info_t* leaderboard; ++ rc_client_leaderboard_info_t* leaderboard_stop; ++ rc_client_subset_info_t* subset; ++ ++ for (subset = game->subsets; subset; subset = subset->next) { ++ achievement = subset->achievements; ++ achievement_stop = achievement + subset->public_.num_achievements; ++ for (; achievement < achievement_stop; ++achievement) { ++ if (achievement->public_.state == RC_CLIENT_ACHIEVEMENT_STATE_ACTIVE && ++ achievement->trigger && achievement->trigger->state == RC_TRIGGER_STATE_PRIMED) { ++ achievement->pending_events |= RC_CLIENT_ACHIEVEMENT_PENDING_EVENT_CHALLENGE_INDICATOR_HIDE; ++ subset->pending_events |= RC_CLIENT_SUBSET_PENDING_EVENT_ACHIEVEMENT; ++ } ++ } ++ ++ leaderboard = subset->leaderboards; ++ leaderboard_stop = leaderboard + subset->public_.num_leaderboards; ++ for (; leaderboard < leaderboard_stop; ++leaderboard) { ++ if (leaderboard->public_.state == RC_CLIENT_LEADERBOARD_STATE_TRACKING) ++ rc_client_release_leaderboard_tracker(game, leaderboard); ++ } ++ } ++ ++ rc_client_hide_progress_tracker(client, game); ++} ++ ++void rc_client_unload_game(rc_client_t* client) ++{ ++ rc_client_game_info_t* game; ++ ++ if (!client) ++ return; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->unload_game) { ++ client->state.external_client->unload_game(); ++ ++ /* a game object may have been allocated to manage hashes */ ++ game = client->game; ++ client->game = NULL; ++ if (game != NULL) ++ rc_client_free_game(game); ++ ++ return; ++ } ++#endif ++ ++ rc_mutex_lock(&client->state.mutex); ++ ++ game = client->game; ++ client->game = NULL; ++ ++ if (client->state.load) { ++ /* this mimics rc_client_abort_async without nesting the lock */ ++ client->state.load->async_handle.aborted = RC_CLIENT_ASYNC_ABORTED; ++ ++ /* if the game is still being loaded, let the load process clean it up */ ++ if (client->state.load->game == game) ++ game = NULL; ++ ++ client->state.load = NULL; ++ } ++ ++ if (client->state.spectator_mode == RC_CLIENT_SPECTATOR_MODE_LOCKED) ++ client->state.spectator_mode = RC_CLIENT_SPECTATOR_MODE_ON; ++ ++ if (game != NULL) { ++ rc_client_scheduled_callback_data_t** last; ++ rc_client_scheduled_callback_data_t* next; ++ ++ rc_client_game_mark_ui_to_be_hidden(client, game); ++ ++ last = &client->state.scheduled_callbacks; ++ do { ++ next = *last; ++ if (!next) ++ break; ++ ++ /* remove rich presence ping scheduled event for game */ ++ if (next->callback == rc_client_ping && next->related_id == game->public_.id) { ++ *last = next->next; ++ continue; ++ } ++ ++ last = &next->next; ++ } while (1); ++ } ++ ++ rc_mutex_unlock(&client->state.mutex); ++ ++ if (game != NULL) { ++ rc_client_raise_pending_events(client, game); ++ ++ RC_CLIENT_LOG_INFO_FORMATTED(client, "Unloading game %u", game->public_.id); ++ rc_client_free_game(game); ++ } ++} ++ ++static void rc_client_change_media_internal(rc_client_t* client, const rc_client_game_hash_t* game_hash, rc_client_callback_t callback, void* callback_userdata) ++{ ++ client->game->public_.hash = game_hash->hash; ++ ++ if (game_hash->game_id == client->game->public_.id) { ++ RC_CLIENT_LOG_INFO_FORMATTED(client, "Switching to valid media for game %u: %s", game_hash->game_id, game_hash->hash); ++ } ++ else if (game_hash->game_id == RC_CLIENT_UNKNOWN_GAME_ID) { ++ RC_CLIENT_LOG_INFO(client, "Switching to unknown media"); ++ } ++ else if (game_hash->game_id == 0) { ++ if (client->state.hardcore) { ++ RC_CLIENT_LOG_WARN_FORMATTED(client, "Disabling hardcore for unidentified media: %s", game_hash->hash); ++ rc_client_set_hardcore_enabled(client, 0); ++ callback(RC_HARDCORE_DISABLED, "Hardcore disabled. Unidentified media inserted.", client, callback_userdata); ++ return; ++ } ++ ++ RC_CLIENT_LOG_INFO_FORMATTED(client, "Switching to unrecognized media: %s", game_hash->hash); ++ } ++ else { ++ RC_CLIENT_LOG_INFO_FORMATTED(client, "Switching to known media for game %u: %s", game_hash->game_id, game_hash->hash); ++ } ++ ++ callback(RC_OK, NULL, client, callback_userdata); ++} ++ ++static void rc_client_identify_changed_media_callback(const rc_api_server_response_t* server_response, void* callback_data) ++{ ++ rc_client_load_state_t* load_state = (rc_client_load_state_t*)callback_data; ++ rc_client_t* client = load_state->client; ++ rc_api_resolve_hash_response_t resolve_hash_response; ++ ++ int result = rc_api_process_resolve_hash_server_response(&resolve_hash_response, server_response); ++ const char* error_message = rc_client_server_error_message(&result, server_response->http_status_code, &resolve_hash_response.response); ++ ++ const int async_aborted = rc_client_end_async(client, &load_state->async_handle); ++ if (async_aborted) { ++ if (async_aborted != RC_CLIENT_ASYNC_DESTROYED) { ++ RC_CLIENT_LOG_VERBOSE(client, "Media change aborted"); ++ /* if lookup succeeded, still capture the new hash */ ++ if (result == RC_OK) ++ load_state->hash->game_id = resolve_hash_response.game_id; ++ } ++ } ++ else if (client->game != load_state->game) { ++ /* loaded game changed. return success regardless of result */ ++ load_state->callback(RC_ABORTED, "The requested game is no longer active", client, load_state->callback_userdata); ++ } ++ else if (error_message) { ++ load_state->callback(result, error_message, client, load_state->callback_userdata); ++ } ++ else { ++ load_state->hash->game_id = resolve_hash_response.game_id; ++ ++ if (resolve_hash_response.game_id != 0) { ++ RC_CLIENT_LOG_INFO_FORMATTED(client, "Identified game: %u (%s)", load_state->hash->game_id, load_state->hash->hash); ++ } ++ ++ rc_client_change_media_internal(client, load_state->hash, load_state->callback, load_state->callback_userdata); ++ } ++ ++ free(load_state); ++ rc_api_destroy_resolve_hash_response(&resolve_hash_response); ++} ++ ++static rc_client_async_handle_t* rc_client_begin_change_media_internal(rc_client_t* client, ++ rc_client_game_info_t* game, rc_client_game_hash_t* game_hash, rc_client_callback_t callback, void* callback_userdata) ++{ ++ rc_client_load_state_t* callback_data; ++ rc_client_async_handle_t* async_handle; ++ rc_api_resolve_hash_request_t resolve_hash_request; ++ rc_api_request_t request; ++ int result; ++ ++ if (game_hash->game_id != RC_CLIENT_UNKNOWN_GAME_ID || /* previously looked up */ ++ game_hash->hash[0] == '[') { /* internal use - don't try to look up */ ++ rc_client_change_media_internal(client, game_hash, callback, callback_userdata); ++ return NULL; ++ } ++ ++ /* call the server to make sure the hash is valid for the loaded game */ ++ memset(&resolve_hash_request, 0, sizeof(resolve_hash_request)); ++ resolve_hash_request.game_hash = game_hash->hash; ++ ++ result = rc_api_init_resolve_hash_request_hosted(&request, &resolve_hash_request, &client->state.host); ++ if (result != RC_OK) { ++ callback(result, rc_error_str(result), client, callback_userdata); ++ return NULL; ++ } ++ ++ callback_data = (rc_client_load_state_t*)calloc(1, sizeof(rc_client_load_state_t)); ++ if (!callback_data) { ++ callback(RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY), client, callback_userdata); ++ return NULL; ++ } ++ ++ callback_data->callback = callback; ++ callback_data->callback_userdata = callback_userdata; ++ callback_data->client = client; ++ callback_data->hash = game_hash; ++ callback_data->game = game; ++ ++ async_handle = &callback_data->async_handle; ++ rc_client_begin_async(client, async_handle); ++ client->callbacks.server_call(&request, rc_client_identify_changed_media_callback, callback_data, client); ++ ++ rc_api_destroy_request(&request); ++ ++ /* if handle is no longer valid, the async operation completed synchronously */ ++ return rc_client_async_handle_valid(client, async_handle) ? async_handle : NULL; ++} ++ ++static rc_client_game_info_t* rc_client_check_pending_media(rc_client_t* client, const rc_client_pending_media_t* media) ++{ ++ rc_client_game_info_t* game; ++ rc_client_pending_media_t* pending_media = NULL; ++ ++ rc_mutex_lock(&client->state.mutex); ++ if (client->state.load) { ++ game = client->state.load->game; ++ if (!game || game->public_.console_id == 0) { ++ /* still waiting for game data */ ++ pending_media = client->state.load->pending_media; ++ if (pending_media) ++ rc_client_free_pending_media(pending_media); ++ ++ pending_media = (rc_client_pending_media_t*)malloc(sizeof(*pending_media)); ++ if (!pending_media) { ++ rc_mutex_unlock(&client->state.mutex); ++ media->callback(RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY), client, media->callback_userdata); ++ return NULL; ++ } ++ ++ memcpy(pending_media, media, sizeof(*pending_media)); ++ if (media->hash) ++ pending_media->hash = strdup(media->hash); ++ ++#ifdef RC_CLIENT_SUPPORTS_HASH ++ if (media->file_path) ++ pending_media->file_path = strdup(media->file_path); ++ ++ if (media->data && media->data_size) { ++ pending_media->data = (uint8_t*)malloc(media->data_size); ++ if (!pending_media->data) { ++ rc_mutex_unlock(&client->state.mutex); ++ media->callback(RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY), client, media->callback_userdata); ++ return NULL; ++ } ++ memcpy(pending_media->data, media->data, media->data_size); ++ } else { ++ pending_media->data = NULL; ++ } ++#endif ++ ++ client->state.load->pending_media = pending_media; ++ } ++ } ++ else { ++ game = client->game; ++ } ++ rc_mutex_unlock(&client->state.mutex); ++ ++ if (!game) { ++ media->callback(RC_NO_GAME_LOADED, rc_error_str(RC_NO_GAME_LOADED), client, media->callback_userdata); ++ return NULL; ++ } ++ ++ /* still waiting for game data - don't call callback - it's queued */ ++ if (pending_media) ++ return NULL; ++ ++ return game; ++} ++ ++#ifdef RC_CLIENT_SUPPORTS_HASH ++ ++rc_client_async_handle_t* rc_client_begin_identify_and_change_media(rc_client_t* client, const char* file_path, ++ const uint8_t* data, size_t data_size, rc_client_callback_t callback, void* callback_userdata) ++{ ++ rc_client_pending_media_t media; ++ rc_client_game_hash_t* game_hash = NULL; ++ rc_client_game_info_t* game; ++ rc_client_media_hash_t* media_hash; ++ uint32_t path_djb2; ++ ++ if (!client) { ++ callback(RC_INVALID_STATE, "client is required", client, callback_userdata); ++ return NULL; ++ } ++ ++ if (!data && !file_path) { ++ callback(RC_INVALID_STATE, "either data or file_path is required", client, callback_userdata); ++ return NULL; ++ } ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && !client->state.external_client->begin_change_media) { ++ if (client->state.external_client->begin_identify_and_change_media) ++ return client->state.external_client->begin_identify_and_change_media(client, file_path, data, data_size, callback, callback_userdata); ++ } ++#endif ++ ++ memset(&media, 0, sizeof(media)); ++ media.file_path = file_path; ++ media.data = (uint8_t*)data; ++ media.data_size = data_size; ++ media.callback = callback; ++ media.callback_userdata = callback_userdata; ++ ++ game = rc_client_check_pending_media(client, &media); ++ if (game == NULL) ++ return NULL; ++ ++ /* check to see if we've already hashed this file */ ++ path_djb2 = rc_djb2(file_path); ++ rc_mutex_lock(&client->state.mutex); ++ for (media_hash = game->media_hash; media_hash; media_hash = media_hash->next) { ++ if (media_hash->path_djb2 == path_djb2) { ++ game_hash = media_hash->game_hash; ++ break; ++ } ++ } ++ rc_mutex_unlock(&client->state.mutex); ++ ++ if (!game_hash) { ++ char hash[33]; ++ int result; ++ ++ if (data != NULL) ++ result = rc_hash_generate_from_buffer(hash, game->public_.console_id, data, data_size); ++ else ++ result = rc_hash_generate_from_file(hash, game->public_.console_id, file_path); ++ ++ if (!result) { ++ /* when changing discs, if the disc is not supported by the system, allow it. this is ++ * primarily for games that support user-provided audio CDs, but does allow using discs ++ * from other systems for games that leverage user-provided discs. */ ++ strcpy_s(hash, sizeof(hash), "[NO HASH]"); ++ } ++ ++ game_hash = rc_client_find_game_hash(client, hash); ++ ++ media_hash = (rc_client_media_hash_t*)rc_buffer_alloc(&game->buffer, sizeof(*media_hash)); ++ media_hash->game_hash = game_hash; ++ media_hash->path_djb2 = path_djb2; ++ ++ rc_mutex_lock(&client->state.mutex); ++ media_hash->next = game->media_hash; ++ game->media_hash = media_hash; ++ rc_mutex_unlock(&client->state.mutex); ++ ++ if (!result) { ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->begin_change_media) ++ return client->state.external_client->begin_change_media(client, game_hash->hash, callback, callback_userdata); ++#endif ++ ++ rc_client_change_media_internal(client, game_hash, callback, callback_userdata); ++ return NULL; ++ } ++ } ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client) { ++ if (client->state.external_client->add_game_hash) ++ client->state.external_client->add_game_hash(game_hash->hash, game_hash->game_id); ++ if (client->state.external_client->begin_change_media) ++ return client->state.external_client->begin_change_media(client, game_hash->hash, callback, callback_userdata); ++ } ++#endif ++ ++ return rc_client_begin_change_media_internal(client, game, game_hash, callback, callback_userdata); ++} ++ ++#endif /* RC_CLIENT_SUPPORTS_HASH */ ++ ++rc_client_async_handle_t* rc_client_begin_change_media(rc_client_t* client, const char* hash, ++ rc_client_callback_t callback, void* callback_userdata) ++{ ++ rc_client_pending_media_t media; ++ rc_client_game_hash_t* game_hash; ++ rc_client_game_info_t* game; ++ ++ if (!client) { ++ callback(RC_INVALID_STATE, "client is required", client, callback_userdata); ++ return NULL; ++ } ++ ++ if (!hash || !hash[0]) { ++ callback(RC_INVALID_STATE, "hash is required", client, callback_userdata); ++ return NULL; ++ } ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->begin_change_media) { ++ return client->state.external_client->begin_change_media(client, hash, callback, callback_userdata); ++ } ++#endif ++ ++ memset(&media, 0, sizeof(media)); ++ media.hash = hash; ++ media.callback = callback; ++ media.callback_userdata = callback_userdata; ++ ++ game = rc_client_check_pending_media(client, &media); ++ if (game == NULL) ++ return NULL; ++ ++ /* check to see if we've already hashed this file. */ ++ game_hash = rc_client_find_game_hash(client, hash); ++ return rc_client_begin_change_media_internal(client, game, game_hash, callback, callback_userdata); ++} ++ ++const rc_client_game_t* rc_client_get_game_info(const rc_client_t* client) ++{ ++ if (!client) ++ return NULL; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client) { ++ if (client->state.external_client->get_game_info_v3) ++ return client->state.external_client->get_game_info_v3(); ++ ++ if (client->state.external_client->get_game_info) ++ return rc_client_external_convert_v1_game(client, client->state.external_client->get_game_info()); ++ } ++#endif ++ ++ return client->game ? &client->game->public_ : NULL; ++} ++ ++int rc_client_game_get_image_url(const rc_client_game_t* game, char buffer[], size_t buffer_size) ++{ ++ if (!game) ++ return RC_INVALID_STATE; ++ ++ if (game->badge_url) { ++ snprintf(buffer, buffer_size, "%s", game->badge_url); ++ return RC_OK; ++ } ++ ++ return rc_client_get_image_url(buffer, buffer_size, RC_IMAGE_TYPE_GAME, game->badge_name); ++} ++ ++/* ===== Subsets ===== */ ++ ++const rc_client_subset_t* rc_client_get_subset_info(rc_client_t* client, uint32_t subset_id) ++{ ++ rc_client_subset_info_t* subset; ++ ++ if (!client) ++ return NULL; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client) { ++ if (client->state.external_client->get_subset_info_v3) ++ return client->state.external_client->get_subset_info_v3(subset_id); ++ ++ if (client->state.external_client->get_subset_info) ++ return rc_client_external_convert_v1_subset(client, client->state.external_client->get_subset_info(subset_id)); ++ } ++#endif ++ ++ if (!client->game) ++ return NULL; ++ ++ for (subset = client->game->subsets; subset; subset = subset->next) { ++ if (subset->public_.id == subset_id) ++ return &subset->public_; ++ } ++ ++ return NULL; ++} ++ ++rc_client_subset_list_t* rc_client_create_subset_list(rc_client_t* client) ++{ ++ rc_client_subset_list_info_t* list; ++ const rc_client_subset_info_t* subset; ++ const rc_client_subset_t** subset_ptr; ++ const uint32_t list_size = RC_ALIGN(sizeof(*list)); ++ uint32_t num_subsets = 0; ++ ++ if (!client) ++ return (rc_client_subset_list_t*)calloc(1, list_size); ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->create_subset_list) ++ return (rc_client_subset_list_t*)client->state.external_client->create_subset_list(); ++#endif ++ ++ if (!client->game) ++ return (rc_client_subset_list_t*)calloc(1, list_size); ++ ++ rc_mutex_lock(&client->state.mutex); ++ ++ subset = client->game->subsets; ++ for (; subset; subset = subset->next) { ++ if (subset->active) ++ num_subsets++; ++ } ++ ++ list = (rc_client_subset_list_info_t*)malloc(list_size + num_subsets * sizeof(rc_client_subset_t*)); ++ list->public_.subsets = subset_ptr = (const rc_client_subset_t**)((uint8_t*)list + list_size); ++ ++ subset = client->game->subsets; ++ for (; subset; subset = subset->next) { ++ if (subset->active) ++ *subset_ptr++ = &subset->public_; ++ } ++ ++ rc_mutex_unlock(&client->state.mutex); ++ ++ list->destroy_func = NULL; ++ list->public_.num_subsets = (uint32_t)(subset_ptr - list->public_.subsets); ++ return &list->public_; ++} ++ ++void rc_client_destroy_subset_list(rc_client_subset_list_t* list) ++{ ++ rc_client_subset_list_info_t* info = (rc_client_subset_list_info_t*)list; ++ if (info->destroy_func) ++ info->destroy_func(info); ++ else ++ free(list); ++} ++ ++/* ===== Fetch Game Hashes ===== */ ++ ++typedef struct rc_client_fetch_hash_library_callback_data_t { ++ rc_client_t* client; ++ rc_client_fetch_hash_library_callback_t callback; ++ void* callback_userdata; ++ uint32_t console_id; ++ rc_client_async_handle_t async_handle; ++} rc_client_fetch_hash_library_callback_data_t; ++ ++static void rc_client_fetch_hash_library_callback(const rc_api_server_response_t* server_response, void* callback_data) ++{ ++ rc_client_fetch_hash_library_callback_data_t* hashlib_callback_data = ++ (rc_client_fetch_hash_library_callback_data_t*)callback_data; ++ rc_client_t* client = hashlib_callback_data->client; ++ rc_api_fetch_hash_library_response_t hashlib_response; ++ const char* error_message; ++ int result; ++ ++ result = rc_client_end_async(client, &hashlib_callback_data->async_handle); ++ if (result) { ++ if (result != RC_CLIENT_ASYNC_DESTROYED) ++ RC_CLIENT_LOG_VERBOSE(client, "Fetch hash library aborted"); ++ ++ free(hashlib_callback_data); ++ return; ++ } ++ ++ result = rc_api_process_fetch_hash_library_server_response(&hashlib_response, server_response); ++ error_message = ++ rc_client_server_error_message(&result, server_response->http_status_code, &hashlib_response.response); ++ if (error_message) { ++ RC_CLIENT_LOG_ERR_FORMATTED(client, "Fetch hash library for console %u failed: %s", ++ hashlib_callback_data->console_id, error_message); ++ hashlib_callback_data->callback(result, error_message, NULL, client, hashlib_callback_data->callback_userdata); ++ } else { ++ rc_client_hash_library_t* list; ++ const size_t list_size = sizeof(*list) + sizeof(rc_client_hash_library_entry_t) * hashlib_response.num_entries; ++ list = (rc_client_hash_library_t*)malloc(list_size); ++ if (!list) { ++ hashlib_callback_data->callback(RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY), NULL, client, ++ hashlib_callback_data->callback_userdata); ++ } else { ++ rc_client_hash_library_entry_t* entry = list->entries = ++ (rc_client_hash_library_entry_t*)((uint8_t*)list + sizeof(*list)); ++ const rc_api_hash_library_entry_t* hlentry = hashlib_response.entries; ++ const rc_api_hash_library_entry_t* stop = hlentry + hashlib_response.num_entries; ++ ++ for (; hlentry < stop; ++hlentry, ++entry) { ++ snprintf(entry->hash, sizeof(entry->hash), "%s", hlentry->hash); ++ entry->game_id = hlentry->game_id; ++ } ++ ++ list->num_entries = hashlib_response.num_entries; ++ ++ hashlib_callback_data->callback(RC_OK, NULL, list, client, hashlib_callback_data->callback_userdata); ++ } ++ } ++ ++ rc_api_destroy_fetch_hash_library_response(&hashlib_response); ++ free(hashlib_callback_data); ++} ++ ++rc_client_async_handle_t* rc_client_begin_fetch_hash_library(rc_client_t* client, uint32_t console_id, ++ rc_client_fetch_hash_library_callback_t callback, ++ void* callback_userdata) ++{ ++ rc_api_fetch_hash_library_request_t api_params; ++ rc_client_fetch_hash_library_callback_data_t* callback_data; ++ rc_client_async_handle_t* async_handle; ++ rc_api_request_t request; ++ int result; ++ const char* error_message; ++ ++ if (!client) { ++ callback(RC_INVALID_STATE, "client is required", NULL, client, callback_userdata); ++ return NULL; ++ } ++ ++ api_params.console_id = console_id; ++ result = rc_api_init_fetch_hash_library_request_hosted(&request, &api_params, &client->state.host); ++ ++ if (result != RC_OK) { ++ error_message = rc_error_str(result); ++ callback(result, error_message, NULL, client, callback_userdata); ++ return NULL; ++ } ++ ++ callback_data = (rc_client_fetch_hash_library_callback_data_t*)calloc(1, sizeof(*callback_data)); ++ if (!callback_data) { ++ callback(RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY), NULL, client, callback_userdata); ++ return NULL; ++ } ++ ++ callback_data->client = client; ++ callback_data->callback = callback; ++ callback_data->callback_userdata = callback_userdata; ++ callback_data->console_id = console_id; ++ ++ async_handle = &callback_data->async_handle; ++ rc_client_begin_async(client, async_handle); ++ client->callbacks.server_call(&request, rc_client_fetch_hash_library_callback, callback_data, client); ++ rc_api_destroy_request(&request); ++ ++ return rc_client_async_handle_valid(client, async_handle) ? async_handle : NULL; ++} ++ ++void rc_client_destroy_hash_library(rc_client_hash_library_t* list) ++{ ++ free(list); ++} ++ ++/* ===== Fetch Game Titles ===== */ ++ ++typedef struct rc_client_fetch_game_titles_callback_data_t { ++ rc_client_t* client; ++ rc_client_fetch_game_titles_callback_t callback; ++ void* callback_userdata; ++ rc_client_async_handle_t async_handle; ++} rc_client_fetch_game_titles_callback_data_t; ++ ++static void rc_client_fetch_game_titles_callback(const rc_api_server_response_t* server_response, void* callback_data) ++{ ++ rc_client_fetch_game_titles_callback_data_t* titles_callback_data = ++ (rc_client_fetch_game_titles_callback_data_t*)callback_data; ++ rc_client_t* client = titles_callback_data->client; ++ rc_api_fetch_game_titles_response_t titles_response; ++ const char* error_message; ++ int result; ++ ++ result = rc_client_end_async(client, &titles_callback_data->async_handle); ++ if (result) { ++ if (result != RC_CLIENT_ASYNC_DESTROYED) ++ RC_CLIENT_LOG_VERBOSE(client, "Fetch game titles aborted"); ++ ++ free(titles_callback_data); ++ return; ++ } ++ ++ result = rc_api_process_fetch_game_titles_server_response(&titles_response, server_response); ++ error_message = ++ rc_client_server_error_message(&result, server_response->http_status_code, &titles_response.response); ++ if (error_message) { ++ RC_CLIENT_LOG_ERR_FORMATTED(client, "Fetch game titles failed: %s", error_message); ++ titles_callback_data->callback(result, error_message, NULL, client, titles_callback_data->callback_userdata); ++ } else { ++ rc_client_game_title_list_t* list; ++ size_t strings_size = 0; ++ const rc_api_game_title_entry_t* src; ++ const rc_api_game_title_entry_t* stop; ++ size_t list_size; ++ ++ /* calculate string buffer size */ ++ for (src = titles_response.entries, stop = src + titles_response.num_entries; src < stop; ++src) { ++ if (src->title) ++ strings_size += strlen(src->title) + 1; ++ } ++ ++ list_size = sizeof(*list) + sizeof(rc_client_game_title_entry_t) * titles_response.num_entries + strings_size; ++ list = (rc_client_game_title_list_t*)malloc(list_size); ++ if (!list) { ++ titles_callback_data->callback(RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY), NULL, client, ++ titles_callback_data->callback_userdata); ++ } else { ++ rc_client_game_title_entry_t* entry = list->entries = ++ (rc_client_game_title_entry_t*)((uint8_t*)list + sizeof(*list)); ++ char* strings = (char*)((uint8_t*)list + sizeof(*list) + ++ sizeof(rc_client_game_title_entry_t) * titles_response.num_entries); ++ ++ for (src = titles_response.entries, stop = src + titles_response.num_entries; src < stop; ++src, ++entry) { ++ entry->game_id = src->id; ++ ++ if (src->title) { ++ const size_t len = strlen(src->title) + 1; ++ entry->title = strings; ++ memcpy(strings, src->title, len); ++ strings += len; ++ } else { ++ entry->title = NULL; ++ } ++ ++ if (src->image_name) ++ snprintf(entry->badge_name, sizeof(entry->badge_name), "%s", src->image_name); ++ else ++ entry->badge_name[0] = '\0'; ++ } ++ ++ list->num_entries = titles_response.num_entries; ++ ++ titles_callback_data->callback(RC_OK, NULL, list, client, titles_callback_data->callback_userdata); ++ } ++ } ++ ++ rc_api_destroy_fetch_game_titles_response(&titles_response); ++ free(titles_callback_data); ++} ++ ++rc_client_async_handle_t* rc_client_begin_fetch_game_titles(rc_client_t* client, const uint32_t* game_ids, ++ uint32_t num_game_ids, ++ rc_client_fetch_game_titles_callback_t callback, ++ void* callback_userdata) ++{ ++ rc_api_fetch_game_titles_request_t api_params; ++ rc_client_fetch_game_titles_callback_data_t* callback_data; ++ rc_client_async_handle_t* async_handle; ++ rc_api_request_t request; ++ int result; ++ const char* error_message; ++ ++ if (!client) { ++ callback(RC_INVALID_STATE, "client is required", NULL, client, callback_userdata); ++ return NULL; ++ } ++ ++ if (!game_ids || num_game_ids == 0) { ++ callback(RC_INVALID_STATE, "game_ids is required", NULL, client, callback_userdata); ++ return NULL; ++ } ++ ++ api_params.game_ids = game_ids; ++ api_params.num_game_ids = num_game_ids; ++ result = rc_api_init_fetch_game_titles_request_hosted(&request, &api_params, &client->state.host); ++ ++ if (result != RC_OK) { ++ error_message = rc_error_str(result); ++ callback(result, error_message, NULL, client, callback_userdata); ++ return NULL; ++ } ++ ++ callback_data = (rc_client_fetch_game_titles_callback_data_t*)calloc(1, sizeof(*callback_data)); ++ if (!callback_data) { ++ callback(RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY), NULL, client, callback_userdata); ++ return NULL; ++ } ++ ++ callback_data->client = client; ++ callback_data->callback = callback; ++ callback_data->callback_userdata = callback_userdata; ++ ++ async_handle = &callback_data->async_handle; ++ rc_client_begin_async(client, async_handle); ++ client->callbacks.server_call(&request, rc_client_fetch_game_titles_callback, callback_data, client); ++ rc_api_destroy_request(&request); ++ ++ return rc_client_async_handle_valid(client, async_handle) ? async_handle : NULL; ++} ++ ++void rc_client_destroy_game_title_list(rc_client_game_title_list_t* list) ++{ ++ free(list); ++} ++ ++/* ===== Achievements ===== */ ++ ++static void rc_client_update_achievement_display_information(rc_client_t* client, rc_client_achievement_info_t* achievement, time_t recent_unlock_time) ++{ ++ uint8_t new_bucket = RC_CLIENT_ACHIEVEMENT_BUCKET_UNKNOWN; ++ uint32_t new_measured_value = 0; ++ ++ if (achievement->public_.bucket == RC_CLIENT_ACHIEVEMENT_BUCKET_UNSUPPORTED) ++ return; ++ ++ achievement->public_.measured_progress[0] = '\0'; ++ ++ if (achievement->public_.state == RC_CLIENT_ACHIEVEMENT_STATE_UNLOCKED) { ++ /* achievement unlocked */ ++ if (achievement->public_.unlock_time >= recent_unlock_time) { ++ new_bucket = RC_CLIENT_ACHIEVEMENT_BUCKET_RECENTLY_UNLOCKED; ++ } else { ++ new_bucket = RC_CLIENT_ACHIEVEMENT_BUCKET_UNLOCKED; ++ ++ if (client->state.disconnect && rc_client_is_award_achievement_pending(client, achievement->public_.id)) ++ new_bucket = RC_CLIENT_ACHIEVEMENT_BUCKET_UNSYNCED; ++ } ++ } ++ else { ++ /* active achievement */ ++ new_bucket = (achievement->public_.category == RC_CLIENT_ACHIEVEMENT_CATEGORY_UNOFFICIAL) ? ++ RC_CLIENT_ACHIEVEMENT_BUCKET_UNOFFICIAL : RC_CLIENT_ACHIEVEMENT_BUCKET_LOCKED; ++ ++ if (achievement->trigger) { ++ if (achievement->trigger->measured_target) { ++ if (achievement->trigger->measured_value == RC_MEASURED_UNKNOWN) { ++ /* value hasn't been initialized yet, leave progress string empty */ ++ } ++ else if (achievement->trigger->measured_value == 0) { ++ /* value is 0, leave progress string empty. update progress to 0.0 */ ++ achievement->public_.measured_percent = 0.0; ++ } ++ else { ++ /* clamp measured value at target (can't get more than 100%) */ ++ new_measured_value = (achievement->trigger->measured_value > achievement->trigger->measured_target) ? ++ achievement->trigger->measured_target : achievement->trigger->measured_value; ++ ++ achievement->public_.measured_percent = ((float)new_measured_value * 100) / (float)achievement->trigger->measured_target; ++ ++ if (!achievement->trigger->measured_as_percent) { ++ char* ptr = achievement->public_.measured_progress; ++ const int buffer_size = (int)sizeof(achievement->public_.measured_progress); ++ const int chars = rc_format_value(ptr, buffer_size, (int32_t)new_measured_value, RC_FORMAT_UNSIGNED_VALUE); ++ ptr[chars] = '/'; ++ rc_format_value(ptr + chars + 1, buffer_size - chars - 1, (int32_t)achievement->trigger->measured_target, RC_FORMAT_UNSIGNED_VALUE); ++ } ++ else if (achievement->public_.measured_percent >= 1.0) { ++ snprintf(achievement->public_.measured_progress, sizeof(achievement->public_.measured_progress), ++ "%lu%%", (unsigned long)achievement->public_.measured_percent); ++ } ++ } ++ } ++ ++ if (achievement->trigger->state == RC_TRIGGER_STATE_PRIMED) ++ new_bucket = RC_CLIENT_ACHIEVEMENT_BUCKET_ACTIVE_CHALLENGE; ++ else if (achievement->public_.measured_percent >= 80.0) ++ new_bucket = RC_CLIENT_ACHIEVEMENT_BUCKET_ALMOST_THERE; ++ } ++ } ++ ++ achievement->public_.bucket = new_bucket; ++} ++ ++static const char* rc_client_get_achievement_bucket_label(uint8_t bucket_type) ++{ ++ switch (bucket_type) { ++ case RC_CLIENT_ACHIEVEMENT_BUCKET_LOCKED: return "Locked"; ++ case RC_CLIENT_ACHIEVEMENT_BUCKET_UNLOCKED: return "Unlocked"; ++ case RC_CLIENT_ACHIEVEMENT_BUCKET_UNSUPPORTED: return "Unsupported"; ++ case RC_CLIENT_ACHIEVEMENT_BUCKET_UNOFFICIAL: return "Unofficial"; ++ case RC_CLIENT_ACHIEVEMENT_BUCKET_RECENTLY_UNLOCKED: return "Recently Unlocked"; ++ case RC_CLIENT_ACHIEVEMENT_BUCKET_ACTIVE_CHALLENGE: return "Active Challenges"; ++ case RC_CLIENT_ACHIEVEMENT_BUCKET_ALMOST_THERE: return "Almost There"; ++ case RC_CLIENT_ACHIEVEMENT_BUCKET_UNSYNCED: return "Unlocks Not Synced to Server"; ++ default: return "Unknown"; ++ } ++} ++ ++static const char* rc_client_get_subset_achievement_bucket_label(uint8_t bucket_type, rc_client_game_info_t* game, rc_client_subset_info_t* subset) ++{ ++ const char** ptr; ++ const char* label; ++ char* new_label; ++ size_t new_label_len; ++ ++ switch (bucket_type) { ++ case RC_CLIENT_ACHIEVEMENT_BUCKET_LOCKED: ptr = &subset->locked_label; break; ++ case RC_CLIENT_ACHIEVEMENT_BUCKET_UNLOCKED: ptr = &subset->unlocked_label; break; ++ case RC_CLIENT_ACHIEVEMENT_BUCKET_UNSUPPORTED: ptr = &subset->unsupported_label; break; ++ case RC_CLIENT_ACHIEVEMENT_BUCKET_UNOFFICIAL: ptr = &subset->unofficial_label; break; ++ default: return rc_client_get_achievement_bucket_label(bucket_type); ++ } ++ ++ if (*ptr) ++ return *ptr; ++ ++ label = rc_client_get_achievement_bucket_label(bucket_type); ++ new_label_len = strlen(subset->public_.title) + strlen(label) + 4; ++ new_label = (char*)rc_buffer_alloc(&game->buffer, new_label_len); ++ snprintf(new_label, new_label_len, "%s - %s", subset->public_.title, label); ++ ++ *ptr = new_label; ++ return new_label; ++} ++ ++static int rc_client_compare_achievement_unlock_times(const void* a, const void* b) ++{ ++ const rc_client_achievement_t* unlock_a = *(const rc_client_achievement_t**)a; ++ const rc_client_achievement_t* unlock_b = *(const rc_client_achievement_t**)b; ++ if (unlock_b->unlock_time == unlock_a->unlock_time) ++ return 0; ++ return (unlock_b->unlock_time < unlock_a->unlock_time) ? -1 : 1; ++} ++ ++static int rc_client_compare_achievement_progress(const void* a, const void* b) ++{ ++ const rc_client_achievement_t* unlock_a = *(const rc_client_achievement_t**)a; ++ const rc_client_achievement_t* unlock_b = *(const rc_client_achievement_t**)b; ++ if (unlock_b->measured_percent == unlock_a->measured_percent) { ++ if (unlock_a->id == unlock_b->id) ++ return 0; ++ return (unlock_a->id < unlock_b->id) ? -1 : 1; ++ } ++ return (unlock_b->measured_percent < unlock_a->measured_percent) ? -1 : 1; ++} ++ ++static uint8_t rc_client_map_bucket(uint8_t bucket, int grouping) ++{ ++ if (grouping == RC_CLIENT_ACHIEVEMENT_LIST_GROUPING_LOCK_STATE) { ++ switch (bucket) { ++ case RC_CLIENT_ACHIEVEMENT_BUCKET_RECENTLY_UNLOCKED: ++ case RC_CLIENT_ACHIEVEMENT_BUCKET_UNSYNCED: ++ return RC_CLIENT_ACHIEVEMENT_BUCKET_UNLOCKED; ++ ++ case RC_CLIENT_ACHIEVEMENT_BUCKET_ACTIVE_CHALLENGE: ++ case RC_CLIENT_ACHIEVEMENT_BUCKET_ALMOST_THERE: ++ return RC_CLIENT_ACHIEVEMENT_BUCKET_LOCKED; ++ ++ default: ++ return bucket; ++ } ++ } ++ ++ return bucket; ++} ++ ++rc_client_achievement_list_t* rc_client_create_achievement_list(rc_client_t* client, int category, int grouping) ++{ ++ rc_client_achievement_info_t* achievement; ++ rc_client_achievement_info_t* stop; ++ const rc_client_achievement_t** bucket_achievements; ++ const rc_client_achievement_t** achievement_ptr; ++ rc_client_achievement_bucket_t* bucket_ptr; ++ rc_client_achievement_list_info_t* list; ++ rc_client_subset_info_t* subset; ++ const uint32_t list_size = RC_ALIGN(sizeof(*list)); ++ uint32_t bucket_counts[NUM_RC_CLIENT_ACHIEVEMENT_BUCKETS]; ++ uint32_t num_buckets; ++ uint32_t num_achievements; ++ size_t buckets_size; ++ uint8_t bucket_type; ++ uint32_t num_subsets = 0; ++ uint32_t i, j; ++ const uint8_t shared_bucket_order[] = { ++ RC_CLIENT_ACHIEVEMENT_BUCKET_ACTIVE_CHALLENGE, ++ RC_CLIENT_ACHIEVEMENT_BUCKET_RECENTLY_UNLOCKED, ++ RC_CLIENT_ACHIEVEMENT_BUCKET_ALMOST_THERE, ++ RC_CLIENT_ACHIEVEMENT_BUCKET_UNSYNCED, ++ }; ++ const uint8_t subset_bucket_order[] = { ++ RC_CLIENT_ACHIEVEMENT_BUCKET_LOCKED, ++ RC_CLIENT_ACHIEVEMENT_BUCKET_UNOFFICIAL, ++ RC_CLIENT_ACHIEVEMENT_BUCKET_UNSUPPORTED, ++ RC_CLIENT_ACHIEVEMENT_BUCKET_UNLOCKED ++ }; ++ const time_t recent_unlock_time = time(NULL) - RC_CLIENT_RECENT_UNLOCK_DELAY_SECONDS; ++ ++ if (!client) ++ return (rc_client_achievement_list_t*)calloc(1, sizeof(rc_client_achievement_list_info_t)); ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client) { ++ if (client->state.external_client->create_achievement_list_v3) ++ return (rc_client_achievement_list_t*)client->state.external_client->create_achievement_list_v3(category, grouping); ++ ++ if (client->state.external_client->create_achievement_list) ++ return rc_client_external_convert_v1_achievement_list(client, ++ (rc_client_achievement_list_t*)client->state.external_client->create_achievement_list(category, grouping)); ++ } ++#endif ++ ++ if (!client->game) ++ return (rc_client_achievement_list_t*)calloc(1, sizeof(rc_client_achievement_list_info_t)); ++ ++ memset(&bucket_counts, 0, sizeof(bucket_counts)); ++ ++ rc_mutex_lock(&client->state.mutex); ++ ++ subset = client->game->subsets; ++ for (; subset; subset = subset->next) { ++ if (!subset->active) ++ continue; ++ ++ num_subsets++; ++ achievement = subset->achievements; ++ stop = achievement + subset->public_.num_achievements; ++ for (; achievement < stop; ++achievement) { ++ if (achievement->public_.category & category) { ++ rc_client_update_achievement_display_information(client, achievement, recent_unlock_time); ++ bucket_counts[rc_client_map_bucket(achievement->public_.bucket, grouping)]++; ++ } ++ } ++ } ++ ++ num_buckets = 0; ++ num_achievements = 0; ++ for (i = 0; i < sizeof(bucket_counts) / sizeof(bucket_counts[0]); ++i) { ++ if (bucket_counts[i]) { ++ int needs_split = 0; ++ ++ num_achievements += bucket_counts[i]; ++ ++ if (num_subsets > 1) { ++ for (j = 0; j < sizeof(subset_bucket_order) / sizeof(subset_bucket_order[0]); ++j) { ++ if (subset_bucket_order[j] == i) { ++ needs_split = 1; ++ break; ++ } ++ } ++ } ++ ++ if (!needs_split) { ++ ++num_buckets; ++ continue; ++ } ++ ++ subset = client->game->subsets; ++ for (; subset; subset = subset->next) { ++ if (!subset->active) ++ continue; ++ ++ achievement = subset->achievements; ++ stop = achievement + subset->public_.num_achievements; ++ for (; achievement < stop; ++achievement) { ++ if (achievement->public_.category & category) { ++ if (rc_client_map_bucket(achievement->public_.bucket, grouping) == i) { ++ ++num_buckets; ++ break; ++ } ++ } ++ } ++ } ++ } ++ } ++ ++ buckets_size = RC_ALIGN(num_buckets * sizeof(rc_client_achievement_bucket_t)); ++ ++ list = (rc_client_achievement_list_info_t*)malloc(list_size + buckets_size + num_achievements * sizeof(rc_client_achievement_t*)); ++ list->public_.buckets = bucket_ptr = (rc_client_achievement_bucket_t*)((uint8_t*)list + list_size); ++ achievement_ptr = (const rc_client_achievement_t**)((uint8_t*)bucket_ptr + buckets_size); ++ ++ if (grouping == RC_CLIENT_ACHIEVEMENT_LIST_GROUPING_PROGRESS) { ++ for (i = 0; i < sizeof(shared_bucket_order) / sizeof(shared_bucket_order[0]); ++i) { ++ bucket_type = shared_bucket_order[i]; ++ if (!bucket_counts[bucket_type]) ++ continue; ++ ++ bucket_achievements = achievement_ptr; ++ for (subset = client->game->subsets; subset; subset = subset->next) { ++ if (!subset->active) ++ continue; ++ ++ achievement = subset->achievements; ++ stop = achievement + subset->public_.num_achievements; ++ for (; achievement < stop; ++achievement) { ++ if (achievement->public_.category & category && ++ rc_client_map_bucket(achievement->public_.bucket, grouping) == bucket_type) { ++ *achievement_ptr++ = &achievement->public_; ++ } ++ } ++ } ++ ++ if (achievement_ptr > bucket_achievements) { ++ bucket_ptr->achievements = bucket_achievements; ++ bucket_ptr->num_achievements = (uint32_t)(achievement_ptr - bucket_achievements); ++ bucket_ptr->subset_id = 0; ++ bucket_ptr->label = rc_client_get_achievement_bucket_label(bucket_type); ++ bucket_ptr->bucket_type = bucket_type; ++ ++ if (bucket_type == RC_CLIENT_ACHIEVEMENT_BUCKET_RECENTLY_UNLOCKED) ++ qsort((void*)bucket_ptr->achievements, bucket_ptr->num_achievements, sizeof(rc_client_achievement_t*), rc_client_compare_achievement_unlock_times); ++ else if (bucket_type == RC_CLIENT_ACHIEVEMENT_BUCKET_ALMOST_THERE) ++ qsort((void*)bucket_ptr->achievements, bucket_ptr->num_achievements, sizeof(rc_client_achievement_t*), rc_client_compare_achievement_progress); ++ ++ ++bucket_ptr; ++ } ++ } ++ } ++ ++ for (subset = client->game->subsets; subset; subset = subset->next) { ++ if (!subset->active) ++ continue; ++ ++ for (i = 0; i < sizeof(subset_bucket_order) / sizeof(subset_bucket_order[0]); ++i) { ++ bucket_type = subset_bucket_order[i]; ++ if (!bucket_counts[bucket_type]) ++ continue; ++ ++ bucket_achievements = achievement_ptr; ++ ++ achievement = subset->achievements; ++ stop = achievement + subset->public_.num_achievements; ++ for (; achievement < stop; ++achievement) { ++ if (achievement->public_.category & category && ++ rc_client_map_bucket(achievement->public_.bucket, grouping) == bucket_type) { ++ *achievement_ptr++ = &achievement->public_; ++ } ++ } ++ ++ if (achievement_ptr > bucket_achievements) { ++ bucket_ptr->achievements = bucket_achievements; ++ bucket_ptr->num_achievements = (uint32_t)(achievement_ptr - bucket_achievements); ++ bucket_ptr->subset_id = (num_subsets > 1) ? subset->public_.id : 0; ++ bucket_ptr->bucket_type = bucket_type; ++ ++ if (num_subsets > 1) ++ bucket_ptr->label = rc_client_get_subset_achievement_bucket_label(bucket_type, client->game, subset); ++ else ++ bucket_ptr->label = rc_client_get_achievement_bucket_label(bucket_type); ++ ++ ++bucket_ptr; ++ } ++ } ++ } ++ ++ rc_mutex_unlock(&client->state.mutex); ++ ++ list->destroy_func = NULL; ++ list->public_.num_buckets = (uint32_t)(bucket_ptr - list->public_.buckets); ++ return &list->public_; ++} ++ ++void rc_client_destroy_achievement_list(rc_client_achievement_list_t* list) ++{ ++ rc_client_achievement_list_info_t* info = (rc_client_achievement_list_info_t*)list; ++ if (info->destroy_func) ++ info->destroy_func(info); ++ else ++ free(list); ++} ++ ++int rc_client_has_achievements(rc_client_t* client) ++{ ++ rc_client_subset_info_t* subset; ++ int result; ++ ++ if (!client) ++ return 0; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->has_achievements) ++ return client->state.external_client->has_achievements(); ++#endif ++ ++ if (!client->game) ++ return 0; ++ ++ rc_mutex_lock(&client->state.mutex); ++ ++ subset = client->game->subsets; ++ result = 0; ++ for (; subset; subset = subset->next) ++ { ++ if (!subset->active) ++ continue; ++ ++ if (subset->public_.num_achievements > 0) { ++ result = 1; ++ break; ++ } ++ } ++ ++ rc_mutex_unlock(&client->state.mutex); ++ ++ return result; ++} ++ ++static const rc_client_achievement_t* rc_client_subset_get_achievement_info( ++ rc_client_t* client, rc_client_subset_info_t* subset, uint32_t id) ++{ ++ rc_client_achievement_info_t* achievement = subset->achievements; ++ rc_client_achievement_info_t* stop = achievement + subset->public_.num_achievements; ++ ++ for (; achievement < stop; ++achievement) { ++ if (achievement->public_.id == id) { ++ const time_t recent_unlock_time = time(NULL) - RC_CLIENT_RECENT_UNLOCK_DELAY_SECONDS; ++ rc_mutex_lock((rc_mutex_t*)(&client->state.mutex)); ++ rc_client_update_achievement_display_information(client, achievement, recent_unlock_time); ++ rc_mutex_unlock((rc_mutex_t*)(&client->state.mutex)); ++ return &achievement->public_; ++ } ++ } ++ ++ return NULL; ++} ++ ++const rc_client_achievement_t* rc_client_get_achievement_info(rc_client_t* client, uint32_t id) ++{ ++ rc_client_subset_info_t* subset; ++ ++ if (!client) ++ return NULL; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client) { ++ if (client->state.external_client->get_achievement_info_v3) ++ return client->state.external_client->get_achievement_info_v3(id); ++ ++ if (client->state.external_client->get_achievement_info) ++ return rc_client_external_convert_v1_achievement(client, client->state.external_client->get_achievement_info(id)); ++ } ++#endif ++ ++ if (!client->game) ++ return NULL; ++ ++ for (subset = client->game->subsets; subset; subset = subset->next) { ++ const rc_client_achievement_t* achievement = rc_client_subset_get_achievement_info(client, subset, id); ++ if (achievement != NULL) ++ return achievement; ++ } ++ ++ return NULL; ++} ++ ++int rc_client_achievement_get_image_url(const rc_client_achievement_t* achievement, int state, char buffer[], size_t buffer_size) ++{ ++ const int image_type = (state == RC_CLIENT_ACHIEVEMENT_STATE_UNLOCKED) ? ++ RC_IMAGE_TYPE_ACHIEVEMENT : RC_IMAGE_TYPE_ACHIEVEMENT_LOCKED; ++ ++ if (!achievement || !achievement->badge_name[0]) ++ return rc_client_get_image_url(buffer, buffer_size, image_type, "00000"); ++ ++ if (image_type == RC_IMAGE_TYPE_ACHIEVEMENT && achievement->badge_url) { ++ snprintf(buffer, buffer_size, "%s", achievement->badge_url); ++ return RC_OK; ++ } ++ ++ if (image_type == RC_IMAGE_TYPE_ACHIEVEMENT_LOCKED && achievement->badge_locked_url) { ++ snprintf(buffer, buffer_size, "%s", achievement->badge_locked_url); ++ return RC_OK; ++ } ++ ++ return rc_client_get_image_url(buffer, buffer_size, image_type, achievement->badge_name); ++} ++ ++typedef struct rc_client_award_achievement_callback_data_t ++{ ++ uint32_t id; ++ uint32_t retry_count; ++ uint8_t hardcore; ++ const char* game_hash; ++ rc_clock_t unlock_time; ++ rc_client_t* client; ++ rc_client_scheduled_callback_data_t* scheduled_callback_data; ++} rc_client_award_achievement_callback_data_t; ++ ++static int rc_client_is_award_achievement_pending(const rc_client_t* client, uint32_t achievement_id) ++{ ++ /* assume lock already held */ ++ rc_client_scheduled_callback_data_t* scheduled_callback = client->state.scheduled_callbacks; ++ for (; scheduled_callback; scheduled_callback = scheduled_callback->next) ++ { ++ if (scheduled_callback->callback == rc_client_award_achievement_retry) ++ { ++ rc_client_award_achievement_callback_data_t* ach_data = ++ (rc_client_award_achievement_callback_data_t*)scheduled_callback->data; ++ if (ach_data->id == achievement_id) ++ return 1; ++ } ++ } ++ ++ return 0; ++} ++ ++static void rc_client_award_achievement_server_call(rc_client_award_achievement_callback_data_t* ach_data); ++ ++static void rc_client_award_achievement_retry(rc_client_scheduled_callback_data_t* callback_data, rc_client_t* client, rc_clock_t now) ++{ ++ rc_client_award_achievement_callback_data_t* ach_data = ++ (rc_client_award_achievement_callback_data_t*)callback_data->data; ++ ++ (void)client; ++ (void)now; ++ ++ rc_client_award_achievement_server_call(ach_data); ++} ++ ++static void rc_client_award_achievement_callback(const rc_api_server_response_t* server_response, void* callback_data) ++{ ++ rc_client_award_achievement_callback_data_t* ach_data = ++ (rc_client_award_achievement_callback_data_t*)callback_data; ++ rc_api_award_achievement_response_t award_achievement_response; ++ ++ int result = rc_api_process_award_achievement_server_response(&award_achievement_response, server_response); ++ const char* error_message = rc_client_server_error_message(&result, server_response->http_status_code, &award_achievement_response.response); ++ ++ if (error_message) { ++ if (award_achievement_response.response.error_message && !rc_client_should_retry(server_response)) { ++ /* actual error from server */ ++ RC_CLIENT_LOG_ERR_FORMATTED(ach_data->client, "Error awarding achievement %u: %s", ach_data->id, error_message); ++ rc_client_raise_server_error_event(ach_data->client, "award_achievement", ach_data->id, result, award_achievement_response.response.error_message); ++ } ++ else if (ach_data->retry_count++ == 0) { ++ /* first retry is immediate */ ++ RC_CLIENT_LOG_ERR_FORMATTED(ach_data->client, "Error awarding achievement %u: %s, retrying immediately", ach_data->id, error_message); ++ rc_client_award_achievement_server_call(ach_data); ++ return; ++ } ++ else { ++ /* double wait time between each attempt until we hit a maximum delay of two minutes */ ++ /* 1s -> 2s -> 4s -> 8s -> 16s -> 32s -> 64s -> 120s -> 120s -> 120s ...*/ ++ const uint32_t delay = (ach_data->retry_count > 8) ? 120 : (1 << (ach_data->retry_count - 2)); ++ RC_CLIENT_LOG_ERR_FORMATTED(ach_data->client, "Error awarding achievement %u: %s, retrying in %u seconds", ach_data->id, error_message, delay); ++ ++ if (!ach_data->scheduled_callback_data) { ++ ach_data->scheduled_callback_data = (rc_client_scheduled_callback_data_t*)calloc(1, sizeof(*ach_data->scheduled_callback_data)); ++ if (!ach_data->scheduled_callback_data) { ++ RC_CLIENT_LOG_ERR_FORMATTED(ach_data->client, "Failed to allocate scheduled callback data for reattempt to unlock achievement %u", ach_data->id); ++ rc_client_raise_server_error_event(ach_data->client, "award_achievement", ach_data->id, RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY)); ++ return; ++ } ++ ach_data->scheduled_callback_data->callback = rc_client_award_achievement_retry; ++ ach_data->scheduled_callback_data->data = ach_data; ++ ach_data->scheduled_callback_data->related_id = ach_data->id; ++ } ++ ++ ach_data->scheduled_callback_data->when = ++ ach_data->client->callbacks.get_time_millisecs(ach_data->client) + delay * 1000; ++ ++ rc_client_schedule_callback(ach_data->client, ach_data->scheduled_callback_data); ++ ++ rc_client_update_disconnect_state(ach_data->client); ++ return; ++ } ++ } ++ else { ++ ach_data->client->user.score = award_achievement_response.new_player_score; ++ ach_data->client->user.score_softcore = award_achievement_response.new_player_score_softcore; ++ ++ if (award_achievement_response.awarded_achievement_id != ach_data->id) { ++ RC_CLIENT_LOG_ERR_FORMATTED(ach_data->client, "Awarded achievement %u instead of %u", award_achievement_response.awarded_achievement_id, error_message); ++ } ++ else { ++ if (award_achievement_response.response.error_message) { ++ /* previously unlocked achievements are returned as a success with an error message */ ++ RC_CLIENT_LOG_INFO_FORMATTED(ach_data->client, "Achievement %u: %s", ach_data->id, award_achievement_response.response.error_message); ++ } ++ else if (ach_data->retry_count) { ++ RC_CLIENT_LOG_INFO_FORMATTED(ach_data->client, "Achievement %u awarded after %u attempts, new score: %u", ++ ach_data->id, ach_data->retry_count + 1, ++ ach_data->hardcore ? award_achievement_response.new_player_score : award_achievement_response.new_player_score_softcore); ++ } ++ else { ++ RC_CLIENT_LOG_INFO_FORMATTED(ach_data->client, "Achievement %u awarded, new score: %u", ++ ach_data->id, ++ ach_data->hardcore ? award_achievement_response.new_player_score : award_achievement_response.new_player_score_softcore); ++ } ++ ++ if (award_achievement_response.achievements_remaining == 0) { ++ rc_client_subset_info_t* subset; ++ for (subset = ach_data->client->game->subsets; subset; subset = subset->next) { ++ if (subset->mastery == RC_CLIENT_MASTERY_STATE_NONE && ++ rc_client_subset_get_achievement_info(ach_data->client, subset, ach_data->id)) { ++ if (subset->public_.id == ach_data->client->game->public_.id) { ++ RC_CLIENT_LOG_INFO_FORMATTED(ach_data->client, "Game %u %s", ach_data->client->game->public_.id, ++ ach_data->client->state.hardcore ? "mastered" : "completed"); ++ subset->mastery = RC_CLIENT_MASTERY_STATE_PENDING; ++ } ++ else { ++ RC_CLIENT_LOG_INFO_FORMATTED(ach_data->client, "Subset %u %s", ach_data->client->game->public_.id, ++ ach_data->client->state.hardcore ? "mastered" : "completed"); ++ ++ subset->mastery = RC_CLIENT_MASTERY_STATE_PENDING; ++ } ++ } ++ } ++ } ++ } ++ } ++ ++ if (ach_data->retry_count) ++ rc_client_update_disconnect_state(ach_data->client); ++ ++ if (ach_data->scheduled_callback_data) ++ free(ach_data->scheduled_callback_data); ++ free(ach_data); ++} ++ ++static void rc_client_award_achievement_server_call(rc_client_award_achievement_callback_data_t* ach_data) ++{ ++ rc_api_award_achievement_request_t api_params; ++ rc_api_request_t request; ++ int result; ++ ++ memset(&api_params, 0, sizeof(api_params)); ++ api_params.username = ach_data->client->user.username; ++ api_params.api_token = ach_data->client->user.token; ++ api_params.achievement_id = ach_data->id; ++ api_params.hardcore = ach_data->hardcore; ++ api_params.game_hash = ach_data->game_hash; ++ ++ if (ach_data->retry_count) { ++ const rc_clock_t now = ach_data->client->callbacks.get_time_millisecs(ach_data->client); ++ api_params.seconds_since_unlock = (uint32_t)((now - ach_data->unlock_time) / 1000); ++ } ++ ++ result = rc_api_init_award_achievement_request_hosted(&request, &api_params, &ach_data->client->state.host); ++ if (result != RC_OK) { ++ RC_CLIENT_LOG_ERR_FORMATTED(ach_data->client, "Error constructing unlock request for achievement %u: %s", ach_data->id, rc_error_str(result)); ++ free(ach_data); ++ return; ++ } ++ ++ ach_data->client->callbacks.server_call(&request, rc_client_award_achievement_callback, ach_data, ach_data->client); ++ ++ rc_api_destroy_request(&request); ++} ++ ++static void rc_client_award_achievement(rc_client_t* client, rc_client_achievement_info_t* achievement) ++{ ++ rc_client_award_achievement_callback_data_t* callback_data; ++ ++ rc_mutex_lock(&client->state.mutex); ++ ++ if (client->state.hardcore) { ++ achievement->public_.unlock_time = achievement->unlock_time_hardcore = time(NULL); ++ if (achievement->unlock_time_softcore == 0) ++ achievement->unlock_time_softcore = achievement->unlock_time_hardcore; ++ ++ /* adjust score now - will get accurate score back from server */ ++ client->user.score += achievement->public_.points; ++ } ++ else { ++ achievement->public_.unlock_time = achievement->unlock_time_softcore = time(NULL); ++ ++ /* adjust score now - will get accurate score back from server */ ++ client->user.score_softcore += achievement->public_.points; ++ } ++ ++ achievement->public_.state = RC_CLIENT_ACHIEVEMENT_STATE_UNLOCKED; ++ achievement->public_.unlocked |= (client->state.hardcore) ? ++ RC_CLIENT_ACHIEVEMENT_UNLOCKED_BOTH : RC_CLIENT_ACHIEVEMENT_UNLOCKED_SOFTCORE; ++ ++ rc_mutex_unlock(&client->state.mutex); ++ ++ if (client->callbacks.can_submit_achievement_unlock && ++ !client->callbacks.can_submit_achievement_unlock(achievement->public_.id, client)) { ++ RC_CLIENT_LOG_INFO_FORMATTED(client, "Achievement %u unlock blocked by client", achievement->public_.id); ++ return; ++ } ++ ++ /* can't unlock unofficial achievements on the server */ ++ if (achievement->public_.category != RC_CLIENT_ACHIEVEMENT_CATEGORY_CORE) { ++ RC_CLIENT_LOG_INFO_FORMATTED(client, "Unlocked unofficial achievement %u: %s", achievement->public_.id, achievement->public_.title); ++ return; ++ } ++ ++ /* don't actually unlock achievements when spectating */ ++ if (client->state.spectator_mode != RC_CLIENT_SPECTATOR_MODE_OFF) { ++ RC_CLIENT_LOG_INFO_FORMATTED(client, "Spectated achievement %u: %s", achievement->public_.id, achievement->public_.title); ++ return; ++ } ++ ++ callback_data = (rc_client_award_achievement_callback_data_t*)calloc(1, sizeof(*callback_data)); ++ if (!callback_data) { ++ RC_CLIENT_LOG_ERR_FORMATTED(client, "Failed to allocate callback data for unlocking achievement %u", achievement->public_.id); ++ rc_client_raise_server_error_event(client, "award_achievement", achievement->public_.id, RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY)); ++ return; ++ } ++ callback_data->client = client; ++ callback_data->id = achievement->public_.id; ++ callback_data->hardcore = client->state.hardcore; ++ callback_data->game_hash = client->game->public_.hash; ++ callback_data->unlock_time = client->callbacks.get_time_millisecs(client); ++ ++ if (client->game) /* may be NULL if this gets called while unloading the game (from another thread - events are raised outside the lock) */ ++ callback_data->game_hash = client->game->public_.hash; ++ ++ RC_CLIENT_LOG_INFO_FORMATTED(client, "Awarding achievement %u: %s", achievement->public_.id, achievement->public_.title); ++ rc_client_award_achievement_server_call(callback_data); ++} ++ ++static void rc_client_subset_reset_achievements(rc_client_subset_info_t* subset) ++{ ++ rc_client_achievement_info_t* achievement = subset->achievements; ++ rc_client_achievement_info_t* stop = achievement + subset->public_.num_achievements; ++ ++ for (; achievement < stop; ++achievement) { ++ rc_trigger_t* trigger = achievement->trigger; ++ if (!trigger || achievement->public_.state != RC_CLIENT_ACHIEVEMENT_STATE_ACTIVE) ++ continue; ++ ++ if (trigger->state == RC_TRIGGER_STATE_PRIMED) { ++ achievement->pending_events |= RC_CLIENT_ACHIEVEMENT_PENDING_EVENT_CHALLENGE_INDICATOR_HIDE; ++ subset->pending_events |= RC_CLIENT_SUBSET_PENDING_EVENT_ACHIEVEMENT; ++ } ++ ++ rc_reset_trigger(trigger); ++ } ++} ++ ++static void rc_client_reset_achievements(rc_client_t* client) ++{ ++ rc_client_subset_info_t* subset; ++ for (subset = client->game->subsets; subset; subset = subset->next) ++ rc_client_subset_reset_achievements(subset); ++} ++ ++/* ===== Leaderboards ===== */ ++ ++static rc_client_leaderboard_info_t* rc_client_subset_get_leaderboard_info(const rc_client_subset_info_t* subset, uint32_t id) ++{ ++ rc_client_leaderboard_info_t* leaderboard = subset->leaderboards; ++ rc_client_leaderboard_info_t* stop = leaderboard + subset->public_.num_leaderboards; ++ ++ for (; leaderboard < stop; ++leaderboard) { ++ if (leaderboard->public_.id == id) ++ return leaderboard; ++ } ++ ++ return NULL; ++} ++ ++const rc_client_leaderboard_t* rc_client_get_leaderboard_info(const rc_client_t* client, uint32_t id) ++{ ++ rc_client_subset_info_t* subset; ++ ++ if (!client) ++ return NULL; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->get_leaderboard_info) ++ return client->state.external_client->get_leaderboard_info(id); ++#endif ++ ++ if (!client->game) ++ return NULL; ++ ++ for (subset = client->game->subsets; subset; subset = subset->next) { ++ const rc_client_leaderboard_info_t* leaderboard = rc_client_subset_get_leaderboard_info(subset, id); ++ if (leaderboard != NULL) ++ return &leaderboard->public_; ++ } ++ ++ return NULL; ++} ++ ++static const char* rc_client_get_leaderboard_bucket_label(uint8_t bucket_type) ++{ ++ switch (bucket_type) { ++ case RC_CLIENT_LEADERBOARD_BUCKET_INACTIVE: return "Inactive"; ++ case RC_CLIENT_LEADERBOARD_BUCKET_ACTIVE: return "Active"; ++ case RC_CLIENT_LEADERBOARD_BUCKET_UNSUPPORTED: return "Unsupported"; ++ case RC_CLIENT_LEADERBOARD_BUCKET_ALL: return "All"; ++ default: return "Unknown"; ++ } ++} ++ ++static const char* rc_client_get_subset_leaderboard_bucket_label(uint8_t bucket_type, rc_client_game_info_t* game, rc_client_subset_info_t* subset) ++{ ++ const char** ptr; ++ const char* label; ++ char* new_label; ++ size_t new_label_len; ++ ++ switch (bucket_type) { ++ case RC_CLIENT_LEADERBOARD_BUCKET_INACTIVE: ptr = &subset->inactive_label; break; ++ case RC_CLIENT_LEADERBOARD_BUCKET_UNSUPPORTED: ptr = &subset->unsupported_label; break; ++ case RC_CLIENT_LEADERBOARD_BUCKET_ALL: ptr = &subset->all_label; break; ++ default: return rc_client_get_achievement_bucket_label(bucket_type); ++ } ++ ++ if (*ptr) ++ return *ptr; ++ ++ label = rc_client_get_leaderboard_bucket_label(bucket_type); ++ new_label_len = strlen(subset->public_.title) + strlen(label) + 4; ++ new_label = (char*)rc_buffer_alloc(&game->buffer, new_label_len); ++ snprintf(new_label, new_label_len, "%s - %s", subset->public_.title, label); ++ ++ *ptr = new_label; ++ return new_label; ++} ++ ++static uint8_t rc_client_get_leaderboard_bucket(const rc_client_leaderboard_info_t* leaderboard, int grouping) ++{ ++ switch (leaderboard->public_.state) { ++ case RC_CLIENT_LEADERBOARD_STATE_TRACKING: ++ return (grouping == RC_CLIENT_LEADERBOARD_LIST_GROUPING_NONE) ? ++ RC_CLIENT_LEADERBOARD_BUCKET_ALL : RC_CLIENT_LEADERBOARD_BUCKET_ACTIVE; ++ ++ case RC_CLIENT_LEADERBOARD_STATE_DISABLED: ++ return RC_CLIENT_LEADERBOARD_BUCKET_UNSUPPORTED; ++ ++ default: ++ return (grouping == RC_CLIENT_LEADERBOARD_LIST_GROUPING_NONE) ? ++ RC_CLIENT_LEADERBOARD_BUCKET_ALL : RC_CLIENT_LEADERBOARD_BUCKET_INACTIVE; ++ } ++} ++ ++rc_client_leaderboard_list_t* rc_client_create_leaderboard_list(rc_client_t* client, int grouping) ++{ ++ rc_client_leaderboard_info_t* leaderboard; ++ rc_client_leaderboard_info_t* stop; ++ const rc_client_leaderboard_t** bucket_leaderboards; ++ const rc_client_leaderboard_t** leaderboard_ptr; ++ rc_client_leaderboard_bucket_t* bucket_ptr; ++ rc_client_leaderboard_list_info_t* list; ++ rc_client_subset_info_t* subset; ++ const uint32_t list_size = RC_ALIGN(sizeof(*list)); ++ uint32_t bucket_counts[8]; ++ uint32_t num_buckets; ++ uint32_t num_leaderboards; ++ size_t buckets_size; ++ uint8_t bucket_type; ++ uint32_t num_subsets = 0; ++ uint32_t i, j; ++ const uint8_t shared_bucket_order[] = { ++ RC_CLIENT_LEADERBOARD_BUCKET_ACTIVE ++ }; ++ const uint8_t subset_bucket_order[] = { ++ RC_CLIENT_LEADERBOARD_BUCKET_ALL, ++ RC_CLIENT_LEADERBOARD_BUCKET_INACTIVE, ++ RC_CLIENT_LEADERBOARD_BUCKET_UNSUPPORTED ++ }; ++ ++ if (!client) ++ return (rc_client_leaderboard_list_t*)calloc(1, list_size); ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->create_leaderboard_list) ++ return (rc_client_leaderboard_list_t*)client->state.external_client->create_leaderboard_list(grouping); ++#endif ++ ++ if (!client->game) ++ return (rc_client_leaderboard_list_t*)calloc(1, list_size); ++ ++ memset(&bucket_counts, 0, sizeof(bucket_counts)); ++ ++ rc_mutex_lock(&client->state.mutex); ++ ++ subset = client->game->subsets; ++ for (; subset; subset = subset->next) { ++ if (!subset->active) ++ continue; ++ ++ num_subsets++; ++ leaderboard = subset->leaderboards; ++ stop = leaderboard + subset->public_.num_leaderboards; ++ for (; leaderboard < stop; ++leaderboard) { ++ if (leaderboard->hidden) ++ continue; ++ ++ leaderboard->bucket = rc_client_get_leaderboard_bucket(leaderboard, grouping); ++ bucket_counts[leaderboard->bucket]++; ++ } ++ } ++ ++ num_buckets = 0; ++ num_leaderboards = 0; ++ for (i = 0; i < sizeof(bucket_counts) / sizeof(bucket_counts[0]); ++i) { ++ if (bucket_counts[i]) { ++ int needs_split = 0; ++ ++ num_leaderboards += bucket_counts[i]; ++ ++ if (num_subsets > 1) { ++ for (j = 0; j < sizeof(subset_bucket_order) / sizeof(subset_bucket_order[0]); ++j) { ++ if (subset_bucket_order[j] == i) { ++ needs_split = 1; ++ break; ++ } ++ } ++ } ++ ++ if (!needs_split) { ++ ++num_buckets; ++ continue; ++ } ++ ++ subset = client->game->subsets; ++ for (; subset; subset = subset->next) { ++ if (!subset->active) ++ continue; ++ ++ leaderboard = subset->leaderboards; ++ stop = leaderboard + subset->public_.num_leaderboards; ++ for (; leaderboard < stop; ++leaderboard) { ++ if (leaderboard->bucket == i) { ++ ++num_buckets; ++ break; ++ } ++ } ++ } ++ } ++ } ++ ++ buckets_size = RC_ALIGN(num_buckets * sizeof(rc_client_leaderboard_bucket_t)); ++ ++ list = (rc_client_leaderboard_list_info_t*)malloc(list_size + buckets_size + num_leaderboards * sizeof(rc_client_leaderboard_t*)); ++ list->public_.buckets = bucket_ptr = (rc_client_leaderboard_bucket_t*)((uint8_t*)list + list_size); ++ leaderboard_ptr = (const rc_client_leaderboard_t**)((uint8_t*)bucket_ptr + buckets_size); ++ ++ if (grouping == RC_CLIENT_LEADERBOARD_LIST_GROUPING_TRACKING) { ++ for (i = 0; i < sizeof(shared_bucket_order) / sizeof(shared_bucket_order[0]); ++i) { ++ bucket_type = shared_bucket_order[i]; ++ if (!bucket_counts[bucket_type]) ++ continue; ++ ++ bucket_leaderboards = leaderboard_ptr; ++ for (subset = client->game->subsets; subset; subset = subset->next) { ++ if (!subset->active) ++ continue; ++ ++ leaderboard = subset->leaderboards; ++ stop = leaderboard + subset->public_.num_leaderboards; ++ for (; leaderboard < stop; ++leaderboard) { ++ if (leaderboard->bucket == bucket_type && !leaderboard->hidden) ++ *leaderboard_ptr++ = &leaderboard->public_; ++ } ++ } ++ ++ if (leaderboard_ptr > bucket_leaderboards) { ++ bucket_ptr->leaderboards = bucket_leaderboards; ++ bucket_ptr->num_leaderboards = (uint32_t)(leaderboard_ptr - bucket_leaderboards); ++ bucket_ptr->subset_id = 0; ++ bucket_ptr->label = rc_client_get_leaderboard_bucket_label(bucket_type); ++ bucket_ptr->bucket_type = bucket_type; ++ ++bucket_ptr; ++ } ++ } ++ } ++ ++ for (subset = client->game->subsets; subset; subset = subset->next) { ++ if (!subset->active) ++ continue; ++ ++ for (i = 0; i < sizeof(subset_bucket_order) / sizeof(subset_bucket_order[0]); ++i) { ++ bucket_type = subset_bucket_order[i]; ++ if (!bucket_counts[bucket_type]) ++ continue; ++ ++ bucket_leaderboards = leaderboard_ptr; ++ ++ leaderboard = subset->leaderboards; ++ stop = leaderboard + subset->public_.num_leaderboards; ++ for (; leaderboard < stop; ++leaderboard) { ++ if (leaderboard->bucket == bucket_type && !leaderboard->hidden) ++ *leaderboard_ptr++ = &leaderboard->public_; ++ } ++ ++ if (leaderboard_ptr > bucket_leaderboards) { ++ bucket_ptr->leaderboards = bucket_leaderboards; ++ bucket_ptr->num_leaderboards = (uint32_t)(leaderboard_ptr - bucket_leaderboards); ++ bucket_ptr->subset_id = (num_subsets > 1) ? subset->public_.id : 0; ++ bucket_ptr->bucket_type = bucket_type; ++ ++ if (num_subsets > 1) ++ bucket_ptr->label = rc_client_get_subset_leaderboard_bucket_label(bucket_type, client->game, subset); ++ else ++ bucket_ptr->label = rc_client_get_leaderboard_bucket_label(bucket_type); ++ ++ ++bucket_ptr; ++ } ++ } ++ } ++ ++ rc_mutex_unlock(&client->state.mutex); ++ ++ list->destroy_func = NULL; ++ list->public_.num_buckets = (uint32_t)(bucket_ptr - list->public_.buckets); ++ return &list->public_; ++} ++ ++void rc_client_destroy_leaderboard_list(rc_client_leaderboard_list_t* list) ++{ ++ rc_client_leaderboard_list_info_t* info = (rc_client_leaderboard_list_info_t*)list; ++ if (info->destroy_func) ++ info->destroy_func(info); ++ else ++ free(list); ++} ++ ++int rc_client_has_leaderboards(rc_client_t* client) ++{ ++ rc_client_subset_info_t* subset; ++ int result; ++ ++ if (!client) ++ return 0; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->has_leaderboards) ++ return client->state.external_client->has_leaderboards(); ++#endif ++ ++ if (!client->game) ++ return 0; ++ ++ rc_mutex_lock(&client->state.mutex); ++ ++ subset = client->game->subsets; ++ result = 0; ++ for (; subset; subset = subset->next) ++ { ++ if (!subset->active) ++ continue; ++ ++ if (subset->public_.num_leaderboards > 0) { ++ result = 1; ++ break; ++ } ++ } ++ ++ rc_mutex_unlock(&client->state.mutex); ++ ++ return result; ++} ++ ++void rc_client_allocate_leaderboard_tracker(rc_client_game_info_t* game, rc_client_leaderboard_info_t* leaderboard) ++{ ++ rc_client_leaderboard_tracker_info_t* tracker; ++ rc_client_leaderboard_tracker_info_t* available_tracker = NULL; ++ ++ for (tracker = game->leaderboard_trackers; tracker; tracker = tracker->next) { ++ if (tracker->reference_count == 0) { ++ if (available_tracker == NULL && tracker->pending_events == RC_CLIENT_LEADERBOARD_TRACKER_PENDING_EVENT_NONE) ++ available_tracker = tracker; ++ ++ continue; ++ } ++ ++ if (tracker->value_djb2 != leaderboard->value_djb2 || tracker->format != leaderboard->format) ++ continue; ++ ++ if (tracker->raw_value != leaderboard->value) { ++ /* if the value comes from tracking hits, we can't assume the trackers started in the ++ * same frame, so we can't share the tracker */ ++ if (tracker->value_from_hits) ++ continue; ++ ++ /* value has changed. prepare an update event */ ++ tracker->raw_value = leaderboard->value; ++ tracker->pending_events |= RC_CLIENT_LEADERBOARD_TRACKER_PENDING_EVENT_UPDATE; ++ game->pending_events |= RC_CLIENT_GAME_PENDING_EVENT_LEADERBOARD_TRACKER; ++ } ++ ++ /* attach to the existing tracker */ ++ ++tracker->reference_count; ++ tracker->pending_events &= ~RC_CLIENT_LEADERBOARD_TRACKER_PENDING_EVENT_HIDE; ++ leaderboard->tracker = tracker; ++ leaderboard->public_.tracker_value = tracker->public_.display; ++ return; ++ } ++ ++ if (!available_tracker) { ++ rc_client_leaderboard_tracker_info_t** next = &game->leaderboard_trackers; ++ ++ available_tracker = (rc_client_leaderboard_tracker_info_t*)rc_buffer_alloc(&game->buffer, sizeof(*available_tracker)); ++ memset(available_tracker, 0, sizeof(*available_tracker)); ++ available_tracker->public_.id = 1; ++ ++ for (tracker = *next; tracker; next = &tracker->next, tracker = *next) ++ available_tracker->public_.id++; ++ ++ *next = available_tracker; ++ } ++ ++ /* update the claimed tracker */ ++ available_tracker->reference_count = 1; ++ available_tracker->value_djb2 = leaderboard->value_djb2; ++ available_tracker->format = leaderboard->format; ++ available_tracker->raw_value = leaderboard->value; ++ available_tracker->pending_events = RC_CLIENT_LEADERBOARD_TRACKER_PENDING_EVENT_SHOW; ++ available_tracker->value_from_hits = rc_value_from_hits(&leaderboard->lboard->value); ++ leaderboard->tracker = available_tracker; ++ leaderboard->public_.tracker_value = available_tracker->public_.display; ++ game->pending_events |= RC_CLIENT_GAME_PENDING_EVENT_LEADERBOARD_TRACKER; ++} ++ ++void rc_client_release_leaderboard_tracker(rc_client_game_info_t* game, rc_client_leaderboard_info_t* leaderboard) ++{ ++ rc_client_leaderboard_tracker_info_t* tracker = leaderboard->tracker; ++ leaderboard->tracker = NULL; ++ ++ if (tracker && --tracker->reference_count == 0) { ++ tracker->pending_events |= RC_CLIENT_LEADERBOARD_TRACKER_PENDING_EVENT_HIDE; ++ game->pending_events |= RC_CLIENT_GAME_PENDING_EVENT_LEADERBOARD_TRACKER; ++ } ++} ++ ++static void rc_client_update_leaderboard_tracker(rc_client_game_info_t* game, rc_client_leaderboard_info_t* leaderboard) ++{ ++ rc_client_leaderboard_tracker_info_t* tracker = leaderboard->tracker; ++ if (tracker && tracker->raw_value != leaderboard->value) { ++ tracker->raw_value = leaderboard->value; ++ tracker->pending_events |= RC_CLIENT_LEADERBOARD_TRACKER_PENDING_EVENT_UPDATE; ++ game->pending_events |= RC_CLIENT_GAME_PENDING_EVENT_LEADERBOARD_TRACKER; ++ } ++} ++ ++typedef struct rc_client_submit_leaderboard_entry_callback_data_t ++{ ++ uint32_t id; ++ int32_t score; ++ uint32_t retry_count; ++ const char* game_hash; ++ rc_clock_t submit_time; ++ rc_client_t* client; ++ rc_client_scheduled_callback_data_t* scheduled_callback_data; ++} rc_client_submit_leaderboard_entry_callback_data_t; ++ ++static void rc_client_submit_leaderboard_entry_server_call(rc_client_submit_leaderboard_entry_callback_data_t* lboard_data); ++ ++static void rc_client_submit_leaderboard_entry_retry(rc_client_scheduled_callback_data_t* callback_data, rc_client_t* client, rc_clock_t now) ++{ ++ rc_client_submit_leaderboard_entry_callback_data_t* lboard_data = ++ (rc_client_submit_leaderboard_entry_callback_data_t*)callback_data->data; ++ ++ (void)client; ++ (void)now; ++ ++ rc_client_submit_leaderboard_entry_server_call(lboard_data); ++} ++ ++static void rc_client_raise_scoreboard_event(rc_client_submit_leaderboard_entry_callback_data_t* lboard_data, ++ const rc_api_submit_lboard_entry_response_t* response) ++{ ++ rc_client_leaderboard_scoreboard_t sboard; ++ rc_client_event_t client_event; ++ rc_client_subset_info_t* subset; ++ rc_client_t* client = lboard_data->client; ++ rc_client_leaderboard_info_t* leaderboard = NULL; ++ ++ if (!client || !client->game) ++ return; ++ ++ for (subset = client->game->subsets; subset; subset = subset->next) { ++ leaderboard = rc_client_subset_get_leaderboard_info(subset, lboard_data->id); ++ if (leaderboard != NULL) ++ break; ++ } ++ if (leaderboard == NULL) { ++ RC_CLIENT_LOG_ERR_FORMATTED(client, "Trying to raise scoreboard for unknown leaderboard %u", lboard_data->id); ++ return; ++ } ++ ++ memset(&sboard, 0, sizeof(sboard)); ++ sboard.leaderboard_id = lboard_data->id; ++ rc_format_value(sboard.submitted_score, sizeof(sboard.submitted_score), response->submitted_score, leaderboard->format); ++ rc_format_value(sboard.best_score, sizeof(sboard.best_score), response->best_score, leaderboard->format); ++ sboard.new_rank = response->new_rank; ++ sboard.num_entries = response->num_entries; ++ sboard.num_top_entries = response->num_top_entries; ++ if (sboard.num_top_entries > 0) { ++ sboard.top_entries = (rc_client_leaderboard_scoreboard_entry_t*)calloc( ++ response->num_top_entries, sizeof(rc_client_leaderboard_scoreboard_entry_t)); ++ if (sboard.top_entries != NULL) { ++ uint32_t i; ++ for (i = 0; i < response->num_top_entries; i++) { ++ sboard.top_entries[i].username = response->top_entries[i].username; ++ sboard.top_entries[i].rank = response->top_entries[i].rank; ++ rc_format_value(sboard.top_entries[i].score, sizeof(sboard.top_entries[i].score), response->top_entries[i].score, ++ leaderboard->format); ++ } ++ } ++ } ++ ++ memset(&client_event, 0, sizeof(client_event)); ++ client_event.type = RC_CLIENT_EVENT_LEADERBOARD_SCOREBOARD; ++ client_event.leaderboard = &leaderboard->public_; ++ client_event.leaderboard_scoreboard = &sboard; ++ ++ lboard_data->client->callbacks.event_handler(&client_event, lboard_data->client); ++ ++ if (sboard.top_entries != NULL) { ++ free(sboard.top_entries); ++ } ++} ++ ++static void rc_client_submit_leaderboard_entry_callback(const rc_api_server_response_t* server_response, void* callback_data) ++{ ++ rc_client_submit_leaderboard_entry_callback_data_t* lboard_data = ++ (rc_client_submit_leaderboard_entry_callback_data_t*)callback_data; ++ rc_api_submit_lboard_entry_response_t submit_lboard_entry_response; ++ ++ int result = rc_api_process_submit_lboard_entry_server_response(&submit_lboard_entry_response, server_response); ++ const char* error_message = rc_client_server_error_message(&result, server_response->http_status_code, &submit_lboard_entry_response.response); ++ ++ if (error_message) { ++ if (submit_lboard_entry_response.response.error_message && !rc_client_should_retry(server_response)) { ++ /* actual error from server */ ++ RC_CLIENT_LOG_ERR_FORMATTED(lboard_data->client, "Error submitting leaderboard entry %u: %s", lboard_data->id, error_message); ++ rc_client_raise_server_error_event(lboard_data->client, "submit_lboard_entry", lboard_data->id, result, submit_lboard_entry_response.response.error_message); ++ } ++ else if (lboard_data->retry_count++ == 0) { ++ /* first retry is immediate */ ++ RC_CLIENT_LOG_ERR_FORMATTED(lboard_data->client, "Error submitting leaderboard entry %u: %s, retrying immediately", lboard_data->id, error_message); ++ rc_client_submit_leaderboard_entry_server_call(lboard_data); ++ return; ++ } ++ else { ++ /* double wait time between each attempt until we hit a maximum delay of two minutes */ ++ /* 1s -> 2s -> 4s -> 8s -> 16s -> 32s -> 64s -> 120s -> 120s -> 120s ...*/ ++ const uint32_t delay = (lboard_data->retry_count > 8) ? 120 : (1 << (lboard_data->retry_count - 2)); ++ RC_CLIENT_LOG_ERR_FORMATTED(lboard_data->client, "Error submitting leaderboard entry %u: %s, retrying in %u seconds", lboard_data->id, error_message, delay); ++ ++ if (!lboard_data->scheduled_callback_data) { ++ lboard_data->scheduled_callback_data = (rc_client_scheduled_callback_data_t*)calloc(1, sizeof(*lboard_data->scheduled_callback_data)); ++ if (!lboard_data->scheduled_callback_data) { ++ RC_CLIENT_LOG_ERR_FORMATTED(lboard_data->client, "Failed to allocate scheduled callback data for reattempt to submit entry for leaderboard %u", lboard_data->id); ++ rc_client_raise_server_error_event(lboard_data->client, "submit_lboard_entry", lboard_data->id, RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY)); ++ return; ++ } ++ lboard_data->scheduled_callback_data->callback = rc_client_submit_leaderboard_entry_retry; ++ lboard_data->scheduled_callback_data->data = lboard_data; ++ lboard_data->scheduled_callback_data->related_id = lboard_data->id; ++ } ++ ++ lboard_data->scheduled_callback_data->when = ++ lboard_data->client->callbacks.get_time_millisecs(lboard_data->client) + delay * 1000; ++ ++ rc_client_schedule_callback(lboard_data->client, lboard_data->scheduled_callback_data); ++ ++ rc_client_update_disconnect_state(lboard_data->client); ++ return; ++ } ++ } ++ else { ++ /* raise event for scoreboard */ ++ if (lboard_data->retry_count < 2) { ++ rc_client_raise_scoreboard_event(lboard_data, &submit_lboard_entry_response); ++ } ++ ++ /* not currently doing anything with the response */ ++ if (lboard_data->retry_count) { ++ RC_CLIENT_LOG_INFO_FORMATTED(lboard_data->client, "Leaderboard %u submission %d completed after %u attempts", ++ lboard_data->id, lboard_data->score, lboard_data->retry_count); ++ } ++ } ++ ++ if (lboard_data->retry_count) ++ rc_client_update_disconnect_state(lboard_data->client); ++ ++ if (lboard_data->scheduled_callback_data) ++ free(lboard_data->scheduled_callback_data); ++ free(lboard_data); ++} ++ ++static void rc_client_submit_leaderboard_entry_server_call(rc_client_submit_leaderboard_entry_callback_data_t* lboard_data) ++{ ++ rc_api_submit_lboard_entry_request_t api_params; ++ rc_api_request_t request; ++ int result; ++ ++ memset(&api_params, 0, sizeof(api_params)); ++ api_params.username = lboard_data->client->user.username; ++ api_params.api_token = lboard_data->client->user.token; ++ api_params.leaderboard_id = lboard_data->id; ++ api_params.score = lboard_data->score; ++ api_params.game_hash = lboard_data->game_hash; ++ ++ if (lboard_data->retry_count) { ++ const rc_clock_t now = lboard_data->client->callbacks.get_time_millisecs(lboard_data->client); ++ api_params.seconds_since_completion = (uint32_t)((now - lboard_data->submit_time) / 1000); ++ } ++ ++ result = rc_api_init_submit_lboard_entry_request_hosted(&request, &api_params, &lboard_data->client->state.host); ++ if (result != RC_OK) { ++ RC_CLIENT_LOG_ERR_FORMATTED(lboard_data->client, "Error constructing submit leaderboard entry for leaderboard %u: %s", lboard_data->id, rc_error_str(result)); ++ return; ++ } ++ ++ lboard_data->client->callbacks.server_call(&request, rc_client_submit_leaderboard_entry_callback, lboard_data, lboard_data->client); ++ ++ rc_api_destroy_request(&request); ++} ++ ++static void rc_client_submit_leaderboard_entry(rc_client_t* client, rc_client_leaderboard_info_t* leaderboard) ++{ ++ rc_client_submit_leaderboard_entry_callback_data_t* callback_data; ++ ++ if (!client->state.hardcore) { ++ RC_CLIENT_LOG_INFO_FORMATTED(client, "Leaderboard %u entry submission not allowed in softcore", leaderboard->public_.id); ++ return; ++ } ++ ++ if (client->callbacks.can_submit_leaderboard_entry && ++ !client->callbacks.can_submit_leaderboard_entry(leaderboard->public_.id, client)) { ++ RC_CLIENT_LOG_INFO_FORMATTED(client, "Leaderboard %u entry submission blocked by client", leaderboard->public_.id); ++ return; ++ } ++ ++ /* don't actually submit leaderboard entries when spectating */ ++ if (client->state.spectator_mode != RC_CLIENT_SPECTATOR_MODE_OFF) { ++ RC_CLIENT_LOG_INFO_FORMATTED(client, "Spectated %s (%d) for leaderboard %u: %s", ++ leaderboard->public_.tracker_value, leaderboard->value, leaderboard->public_.id, leaderboard->public_.title); ++ return; ++ } ++ ++ callback_data = (rc_client_submit_leaderboard_entry_callback_data_t*)calloc(1, sizeof(*callback_data)); ++ if (!callback_data) { ++ RC_CLIENT_LOG_ERR_FORMATTED(client, "Failed to allocate callback data for submitting entry for leaderboard %u", leaderboard->public_.id); ++ rc_client_raise_server_error_event(client, "submit_lboard_entry", leaderboard->public_.id, RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY)); ++ return; ++ } ++ callback_data->client = client; ++ callback_data->id = leaderboard->public_.id; ++ callback_data->score = leaderboard->value; ++ callback_data->game_hash = client->game->public_.hash; ++ callback_data->submit_time = client->callbacks.get_time_millisecs(client); ++ ++ RC_CLIENT_LOG_INFO_FORMATTED(client, "Submitting %s (%d) for leaderboard %u: %s", ++ leaderboard->public_.tracker_value, leaderboard->value, leaderboard->public_.id, leaderboard->public_.title); ++ rc_client_submit_leaderboard_entry_server_call(callback_data); ++} ++ ++static void rc_client_subset_reset_leaderboards(rc_client_game_info_t* game, rc_client_subset_info_t* subset) ++{ ++ rc_client_leaderboard_info_t* leaderboard = subset->leaderboards; ++ rc_client_leaderboard_info_t* stop = leaderboard + subset->public_.num_leaderboards; ++ ++ for (; leaderboard < stop; ++leaderboard) { ++ rc_lboard_t* lboard = leaderboard->lboard; ++ if (!lboard) ++ continue; ++ ++ switch (leaderboard->public_.state) { ++ case RC_CLIENT_LEADERBOARD_STATE_INACTIVE: ++ case RC_CLIENT_LEADERBOARD_STATE_DISABLED: ++ continue; ++ ++ case RC_CLIENT_LEADERBOARD_STATE_TRACKING: ++ rc_client_release_leaderboard_tracker(game, leaderboard); ++ /* fallthrough */ /* to default */ ++ default: ++ leaderboard->public_.state = RC_CLIENT_LEADERBOARD_STATE_ACTIVE; ++ rc_reset_lboard(lboard); ++ break; ++ } ++ } ++} ++ ++static void rc_client_reset_leaderboards(rc_client_t* client) ++{ ++ rc_client_subset_info_t* subset; ++ for (subset = client->game->subsets; subset; subset = subset->next) ++ rc_client_subset_reset_leaderboards(client->game, subset); ++} ++ ++typedef struct rc_client_fetch_leaderboard_entries_callback_data_t { ++ rc_client_t* client; ++ rc_client_fetch_leaderboard_entries_callback_t callback; ++ void* callback_userdata; ++ uint32_t leaderboard_id; ++ rc_client_async_handle_t async_handle; ++} rc_client_fetch_leaderboard_entries_callback_data_t; ++ ++static void rc_client_fetch_leaderboard_entries_callback(const rc_api_server_response_t* server_response, void* callback_data) ++{ ++ rc_client_fetch_leaderboard_entries_callback_data_t* lbinfo_callback_data = (rc_client_fetch_leaderboard_entries_callback_data_t*)callback_data; ++ rc_client_t* client = lbinfo_callback_data->client; ++ rc_api_fetch_leaderboard_info_response_t lbinfo_response; ++ const char* error_message; ++ int result; ++ ++ result = rc_client_end_async(client, &lbinfo_callback_data->async_handle); ++ if (result) { ++ if (result != RC_CLIENT_ASYNC_DESTROYED) { ++ RC_CLIENT_LOG_VERBOSE(client, "Fetch leaderbord entries aborted"); ++ } ++ free(lbinfo_callback_data); ++ return; ++ } ++ ++ result = rc_api_process_fetch_leaderboard_info_server_response(&lbinfo_response, server_response); ++ error_message = rc_client_server_error_message(&result, server_response->http_status_code, &lbinfo_response.response); ++ if (error_message) { ++ RC_CLIENT_LOG_ERR_FORMATTED(client, "Fetch leaderboard %u info failed: %s", lbinfo_callback_data->leaderboard_id, error_message); ++ lbinfo_callback_data->callback(result, error_message, NULL, client, lbinfo_callback_data->callback_userdata); ++ } ++ else { ++ rc_client_leaderboard_entry_list_info_t* info; ++ const size_t list_size = sizeof(*info) + sizeof(rc_client_leaderboard_entry_t) * lbinfo_response.num_entries; ++ size_t needed_size = list_size; ++ uint32_t i; ++ ++ for (i = 0; i < lbinfo_response.num_entries; i++) ++ needed_size += strlen(lbinfo_response.entries[i].username) + 1; ++ ++ info = (rc_client_leaderboard_entry_list_info_t*)malloc(needed_size); ++ if (!info) { ++ lbinfo_callback_data->callback(RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY), NULL, client, lbinfo_callback_data->callback_userdata); ++ } ++ else { ++ rc_client_leaderboard_entry_list_t* list = &info->public_; ++ rc_client_leaderboard_entry_t* entry = list->entries = (rc_client_leaderboard_entry_t*)((uint8_t*)info + sizeof(*info)); ++ char* user = (char*)((uint8_t*)list + list_size); ++ const rc_api_lboard_info_entry_t* lbentry = lbinfo_response.entries; ++ const rc_api_lboard_info_entry_t* stop = lbentry + lbinfo_response.num_entries; ++ const size_t logged_in_user_len = strlen(client->user.display_name) + 1; ++ info->destroy_func = NULL; ++ list->user_index = -1; ++ ++ for (; lbentry < stop; ++lbentry, ++entry) { ++ const size_t len = strlen(lbentry->username) + 1; ++ entry->user = user; ++ memcpy(user, lbentry->username, len); ++ user += len; ++ ++ if (len == logged_in_user_len && memcmp(entry->user, client->user.display_name, len) == 0) ++ list->user_index = (int)(entry - list->entries); ++ ++ entry->index = lbentry->index; ++ entry->rank = lbentry->rank; ++ entry->submitted = lbentry->submitted; ++ ++ rc_format_value(entry->display, sizeof(entry->display), lbentry->score, lbinfo_response.format); ++ } ++ ++ list->num_entries = lbinfo_response.num_entries; ++ list->total_entries = lbinfo_response.total_entries; ++ ++ lbinfo_callback_data->callback(RC_OK, NULL, list, client, lbinfo_callback_data->callback_userdata); ++ } ++ } ++ ++ rc_api_destroy_fetch_leaderboard_info_response(&lbinfo_response); ++ free(lbinfo_callback_data); ++} ++ ++static rc_client_async_handle_t* rc_client_begin_fetch_leaderboard_info(rc_client_t* client, ++ const rc_api_fetch_leaderboard_info_request_t* lbinfo_request, ++ rc_client_fetch_leaderboard_entries_callback_t callback, void* callback_userdata) ++{ ++ rc_client_fetch_leaderboard_entries_callback_data_t* callback_data; ++ rc_client_async_handle_t* async_handle; ++ rc_api_request_t request; ++ int result; ++ const char* error_message; ++ ++ result = rc_api_init_fetch_leaderboard_info_request_hosted(&request, lbinfo_request, &client->state.host); ++ ++ if (result != RC_OK) { ++ error_message = rc_error_str(result); ++ callback(result, error_message, NULL, client, callback_userdata); ++ return NULL; ++ } ++ ++ callback_data = (rc_client_fetch_leaderboard_entries_callback_data_t*)calloc(1, sizeof(*callback_data)); ++ if (!callback_data) { ++ callback(RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY), NULL, client, callback_userdata); ++ return NULL; ++ } ++ ++ callback_data->client = client; ++ callback_data->callback = callback; ++ callback_data->callback_userdata = callback_userdata; ++ callback_data->leaderboard_id = lbinfo_request->leaderboard_id; ++ ++ async_handle = &callback_data->async_handle; ++ rc_client_begin_async(client, async_handle); ++ client->callbacks.server_call(&request, rc_client_fetch_leaderboard_entries_callback, callback_data, client); ++ rc_api_destroy_request(&request); ++ ++ return rc_client_async_handle_valid(client, async_handle) ? async_handle : NULL; ++} ++ ++rc_client_async_handle_t* rc_client_begin_fetch_leaderboard_entries(rc_client_t* client, uint32_t leaderboard_id, ++ uint32_t first_entry, uint32_t count, rc_client_fetch_leaderboard_entries_callback_t callback, void* callback_userdata) ++{ ++ rc_api_fetch_leaderboard_info_request_t lbinfo_request; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->begin_fetch_leaderboard_entries) ++ return client->state.external_client->begin_fetch_leaderboard_entries(client, leaderboard_id, first_entry, count, callback, callback_userdata); ++#endif ++ ++ memset(&lbinfo_request, 0, sizeof(lbinfo_request)); ++ lbinfo_request.leaderboard_id = leaderboard_id; ++ lbinfo_request.first_entry = first_entry; ++ lbinfo_request.count = count; ++ ++ return rc_client_begin_fetch_leaderboard_info(client, &lbinfo_request, callback, callback_userdata); ++} ++ ++rc_client_async_handle_t* rc_client_begin_fetch_leaderboard_entries_around_user(rc_client_t* client, uint32_t leaderboard_id, ++ uint32_t count, rc_client_fetch_leaderboard_entries_callback_t callback, void* callback_userdata) ++{ ++ rc_api_fetch_leaderboard_info_request_t lbinfo_request; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->begin_fetch_leaderboard_entries_around_user) ++ return client->state.external_client->begin_fetch_leaderboard_entries_around_user(client, leaderboard_id, count, callback, callback_userdata); ++#endif ++ ++ memset(&lbinfo_request, 0, sizeof(lbinfo_request)); ++ lbinfo_request.leaderboard_id = leaderboard_id; ++ lbinfo_request.username = client->user.username; ++ lbinfo_request.count = count; ++ ++ if (!lbinfo_request.username) { ++ callback(RC_LOGIN_REQUIRED, rc_error_str(RC_LOGIN_REQUIRED), NULL, client, callback_userdata); ++ return NULL; ++ } ++ ++ return rc_client_begin_fetch_leaderboard_info(client, &lbinfo_request, callback, callback_userdata); ++} ++ ++void rc_client_destroy_leaderboard_entry_list(rc_client_leaderboard_entry_list_t* list) ++{ ++ rc_client_leaderboard_entry_list_info_t* info = (rc_client_leaderboard_entry_list_info_t*)list; ++ if (info->destroy_func) ++ info->destroy_func(info); ++ else ++ free(list); ++} ++ ++int rc_client_leaderboard_entry_get_user_image_url(const rc_client_leaderboard_entry_t* entry, char buffer[], size_t buffer_size) ++{ ++ if (!entry) ++ return RC_INVALID_STATE; ++ ++ return rc_client_get_image_url(buffer, buffer_size, RC_IMAGE_TYPE_USER, entry->user); ++} ++ ++/* ===== Rich Presence ===== */ ++ ++static void rc_client_ping_callback(const rc_api_server_response_t* server_response, void* callback_data) ++{ ++ rc_client_t* client = (rc_client_t*)callback_data; ++ rc_api_ping_response_t response; ++ ++ int result = rc_api_process_ping_server_response(&response, server_response); ++ const char* error_message = rc_client_server_error_message(&result, server_response->http_status_code, &response.response); ++ if (error_message) { ++ RC_CLIENT_LOG_WARN_FORMATTED(client, "Ping response error: %s", error_message); ++ } ++ ++ rc_api_destroy_ping_response(&response); ++} ++ ++static void rc_client_ping(rc_client_scheduled_callback_data_t* callback_data, rc_client_t* client, rc_clock_t now) ++{ ++ rc_api_ping_request_t api_params; ++ rc_api_request_t request; ++ char buffer[256]; ++ int result; ++ ++ /* if no frames have been processed since the last ping, the emulator is idle. let the ++ * server session expire. it will be resumed/restarted once frames start getting ++ * processed again. */ ++ if (client->state.frames_processed != client->state.frames_at_last_ping) { ++ client->state.frames_at_last_ping = client->state.frames_processed; ++ ++ if (!client->callbacks.rich_presence_override || ++ !client->callbacks.rich_presence_override(client, buffer, sizeof(buffer))) { ++ rc_mutex_lock(&client->state.mutex); ++ ++ rc_runtime_get_richpresence(&client->game->runtime, buffer, sizeof(buffer), ++ client->state.legacy_peek, client, NULL); ++ ++ rc_mutex_unlock(&client->state.mutex); ++ } ++ ++ memset(&api_params, 0, sizeof(api_params)); ++ api_params.username = client->user.username; ++ api_params.api_token = client->user.token; ++ api_params.game_id = client->game->public_.id; ++ api_params.rich_presence = buffer; ++ api_params.game_hash = client->game->public_.hash; ++ api_params.hardcore = client->state.hardcore; ++ ++ result = rc_api_init_ping_request_hosted(&request, &api_params, &client->state.host); ++ if (result != RC_OK) { ++ RC_CLIENT_LOG_WARN_FORMATTED(client, "Error generating ping request: %s", rc_error_str(result)); ++ } ++ else { ++ client->callbacks.server_call(&request, rc_client_ping_callback, client, client); ++ } ++ } ++ ++ callback_data->when = now + 120 * 1000; ++ rc_client_schedule_callback(client, callback_data); ++} ++ ++int rc_client_has_rich_presence(rc_client_t* client) ++{ ++ if (!client) ++ return 0; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->has_rich_presence) ++ return client->state.external_client->has_rich_presence(); ++#endif ++ ++ if (!client->game || !client->game->runtime.richpresence || !client->game->runtime.richpresence->richpresence) ++ return 0; ++ ++ return 1; ++} ++ ++size_t rc_client_get_rich_presence_message(rc_client_t* client, char buffer[], size_t buffer_size) ++{ ++ int result; ++ ++ if (!client || !buffer) ++ return 0; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->get_rich_presence_message) ++ return client->state.external_client->get_rich_presence_message(buffer, buffer_size); ++#endif ++ ++ if (!client->game) ++ return 0; ++ ++ rc_mutex_lock(&client->state.mutex); ++ ++ result = rc_runtime_get_richpresence(&client->game->runtime, buffer, (unsigned)buffer_size, ++ client->state.legacy_peek, client, NULL); ++ ++ rc_mutex_unlock(&client->state.mutex); ++ ++ if (result == 0) { ++ result = snprintf(buffer, buffer_size, "Playing %s", client->game->public_.title); ++ /* snprintf will return the amount of space needed, we want to return the number of chars written */ ++ if ((size_t)result >= buffer_size) ++ return (buffer_size - 1); ++ } ++ ++ return result; ++} ++ ++/* ===== Processing ===== */ ++ ++void rc_client_set_event_handler(rc_client_t* client, rc_client_event_handler_t handler) ++{ ++ if (!client) ++ return; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->set_event_handler) ++ client->state.external_client->set_event_handler(client, handler); ++#endif ++ ++ client->callbacks.event_handler = handler; ++} ++ ++void rc_client_set_read_memory_function(rc_client_t* client, rc_client_read_memory_func_t handler) ++{ ++ if (!client) ++ return; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->set_read_memory) ++ client->state.external_client->set_read_memory(client, handler); ++#endif ++ ++ client->callbacks.read_memory = handler; ++} ++ ++void rc_client_set_allow_background_memory_reads(rc_client_t* client, int allowed) ++{ ++ if (!client) ++ return; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->set_allow_background_memory_reads) ++ client->state.external_client->set_allow_background_memory_reads(allowed); ++#endif ++ ++ client->state.allow_background_memory_reads = allowed; ++} ++ ++static void rc_client_invalidate_processing_memref(rc_client_t* client) ++{ ++ /* if processing_memref is not set, this occurred following a pointer chain. ignore it. */ ++ if (!client->state.processing_memref) ++ return; ++ ++ client->state.processing_memref->value.type = RC_VALUE_TYPE_NONE; ++ ++ rc_client_invalidate_memref_achievements(client->game, client, client->state.processing_memref); ++ rc_client_invalidate_memref_leaderboards(client->game, client, client->state.processing_memref); ++ ++ client->state.processing_memref = NULL; ++} ++ ++static uint32_t rc_client_peek_le(uint32_t address, uint32_t num_bytes, void* ud) ++{ ++ rc_client_t* client = (rc_client_t*)ud; ++ uint32_t value = 0; ++ uint32_t num_read = 0; ++ ++ /* if we know the address is out of range, and it's part of a pointer chain ++ * (processing_memref is null), don't bother processing it. */ ++ if (address > client->game->max_valid_address && !client->state.processing_memref) ++ return 0; ++ ++ if (num_bytes <= sizeof(value)) { ++ num_read = client->callbacks.read_memory(address, (uint8_t*)&value, num_bytes, client); ++ if (num_read == num_bytes) ++ return value; ++ } ++ ++ if (num_read < num_bytes) ++ rc_client_invalidate_processing_memref(client); ++ ++ return 0; ++} ++ ++static uint32_t rc_client_peek(uint32_t address, uint32_t num_bytes, void* ud) ++{ ++ rc_client_t* client = (rc_client_t*)ud; ++ uint8_t buffer[4]; ++ uint32_t num_read = 0; ++ ++ /* if we know the address is out of range, and it's part of a pointer chain ++ * (processing_memref is null), don't bother processing it. */ ++ if (address > client->game->max_valid_address && !client->state.processing_memref) ++ return 0; ++ ++ switch (num_bytes) { ++ case 1: ++ num_read = client->callbacks.read_memory(address, buffer, 1, client); ++ if (num_read == 1) ++ return buffer[0]; ++ break; ++ case 2: ++ num_read = client->callbacks.read_memory(address, buffer, 2, client); ++ if (num_read == 2) ++ return buffer[0] | (buffer[1] << 8); ++ break; ++ case 3: ++ num_read = client->callbacks.read_memory(address, buffer, 3, client); ++ if (num_read == 3) ++ return buffer[0] | (buffer[1] << 8) | (buffer[2] << 16); ++ break; ++ case 4: ++ num_read = client->callbacks.read_memory(address, buffer, 4, client); ++ if (num_read == 4) ++ return buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24); ++ break; ++ default: ++ break; ++ } ++ ++ if (num_read < num_bytes) ++ rc_client_invalidate_processing_memref(client); ++ ++ return 0; ++} ++ ++void rc_client_set_legacy_peek(rc_client_t* client, int method) ++{ ++ if (method == RC_CLIENT_LEGACY_PEEK_AUTO) { ++ union { ++ uint32_t whole; ++ uint8_t parts[4]; ++ } u; ++ u.whole = 1; ++ method = (u.parts[0] == 1) ? ++ RC_CLIENT_LEGACY_PEEK_LITTLE_ENDIAN_READS : RC_CLIENT_LEGACY_PEEK_CONSTRUCTED; ++ } ++ ++ client->state.legacy_peek = (method == RC_CLIENT_LEGACY_PEEK_LITTLE_ENDIAN_READS) ? ++ rc_client_peek_le : rc_client_peek; ++} ++ ++int rc_client_is_processing_required(rc_client_t* client) ++{ ++ if (!client) ++ return 0; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->is_processing_required) ++ return client->state.external_client->is_processing_required(); ++#endif ++ ++ if (!client->game) ++ return 0; ++ ++ if (client->game->runtime.trigger_count || client->game->runtime.lboard_count) ++ return 1; ++ ++ return (client->game->runtime.richpresence && client->game->runtime.richpresence->richpresence); ++} ++ ++static void rc_client_update_memref_values(rc_client_t* client) { ++ rc_memrefs_t* memrefs = client->game->runtime.memrefs; ++ rc_memref_list_t* memref_list; ++ rc_modified_memref_list_t* modified_memref_list; ++ int invalidated_memref = 0; ++ ++ memref_list = &memrefs->memrefs; ++ do { ++ rc_memref_t* memref = memref_list->items; ++ const rc_memref_t* memref_stop = memref + memref_list->count; ++ uint32_t value; ++ ++ for (; memref < memref_stop; ++memref) { ++ if (memref->value.type == RC_VALUE_TYPE_NONE) ++ continue; ++ ++ /* if processing_memref is set, and the memory read fails, all dependent achievements will be disabled */ ++ client->state.processing_memref = memref; ++ ++ value = rc_peek_value(memref->address, memref->value.size, client->state.legacy_peek, client); ++ ++ if (client->state.processing_memref) { ++ rc_update_memref_value(&memref->value, value); ++ } ++ else { ++ /* if the peek function cleared the processing_memref, the memref was invalidated */ ++ invalidated_memref = 1; ++ } ++ } ++ ++ memref_list = memref_list->next; ++ } while (memref_list); ++ ++ client->state.processing_memref = NULL; ++ ++ modified_memref_list = &memrefs->modified_memrefs; ++ if (modified_memref_list->count) { ++ do { ++ rc_modified_memref_t* modified_memref = modified_memref_list->items; ++ const rc_modified_memref_t* modified_memref_stop = modified_memref + modified_memref_list->count; ++ ++ for (; modified_memref < modified_memref_stop; ++modified_memref) ++ rc_update_memref_value(&modified_memref->memref.value, rc_get_modified_memref_value(modified_memref, client->state.legacy_peek, client)); ++ ++ modified_memref_list = modified_memref_list->next; ++ } while (modified_memref_list); ++ } ++ ++ if (client->game->runtime.richpresence && client->game->runtime.richpresence->richpresence) ++ rc_update_values(client->game->runtime.richpresence->richpresence->values, client->state.legacy_peek, client); ++ ++ if (invalidated_memref) ++ rc_client_update_active_achievements(client->game); ++} ++ ++static void rc_client_do_frame_process_achievements(rc_client_t* client, rc_client_subset_info_t* subset) ++{ ++ rc_client_achievement_info_t* achievement = subset->achievements; ++ rc_client_achievement_info_t* stop = achievement + subset->public_.num_achievements; ++ ++ for (; achievement < stop; ++achievement) { ++ rc_trigger_t* trigger = achievement->trigger; ++ int old_state, new_state; ++ uint32_t old_measured_value; ++ ++ if (!trigger || achievement->public_.state != RC_CLIENT_ACHIEVEMENT_STATE_ACTIVE) ++ continue; ++ ++ old_measured_value = trigger->measured_value; ++ old_state = trigger->state; ++ new_state = rc_evaluate_trigger(trigger, client->state.legacy_peek, client, NULL); ++ ++ /* trigger->state doesn't actually change to RESET - RESET just serves as a notification. ++ * we don't care about that particular notification, so look at the actual state. */ ++ if (new_state == RC_TRIGGER_STATE_RESET) ++ new_state = trigger->state; ++ ++ /* if the measured value changed and the achievement hasn't triggered, show a progress indicator */ ++ if (trigger->measured_value != old_measured_value && old_measured_value != RC_MEASURED_UNKNOWN && ++ trigger->measured_value <= trigger->measured_target && ++ rc_trigger_state_active(new_state) && new_state != RC_TRIGGER_STATE_WAITING) { ++ ++ /* only show a popup for the achievement closest to triggering */ ++ float progress = (float)trigger->measured_value / (float)trigger->measured_target; ++ ++ if (trigger->measured_as_percent) { ++ /* if reporting the measured value as a percentage, only show the popup if the percentage changes */ ++ const uint32_t old_percent = (uint32_t)(((unsigned long long)old_measured_value * 100) / trigger->measured_target); ++ const uint32_t new_percent = (uint32_t)(((unsigned long long)trigger->measured_value * 100) / trigger->measured_target); ++ if (old_percent == new_percent) ++ progress = -1.0; ++ } ++ ++ if (progress > client->game->progress_tracker.progress) { ++ client->game->progress_tracker.progress = progress; ++ client->game->progress_tracker.achievement = achievement; ++ client->game->pending_events |= RC_CLIENT_GAME_PENDING_EVENT_PROGRESS_TRACKER; ++ subset->pending_events |= RC_CLIENT_SUBSET_PENDING_EVENT_ACHIEVEMENT; ++ achievement->pending_events |= RC_CLIENT_ACHIEVEMENT_PENDING_EVENT_UPDATE; ++ } ++ } ++ ++ /* if the state hasn't changed, there won't be any events raised */ ++ if (new_state == old_state) ++ continue; ++ ++ /* raise a CHALLENGE_INDICATOR_HIDE event when changing from PRIMED to anything else */ ++ if (old_state == RC_TRIGGER_STATE_PRIMED) ++ achievement->pending_events |= RC_CLIENT_ACHIEVEMENT_PENDING_EVENT_CHALLENGE_INDICATOR_HIDE; ++ ++ /* raise events for each of the possible new states */ ++ if (new_state == RC_TRIGGER_STATE_TRIGGERED) ++ achievement->pending_events |= RC_CLIENT_ACHIEVEMENT_PENDING_EVENT_TRIGGERED; ++ else if (new_state == RC_TRIGGER_STATE_PRIMED) ++ achievement->pending_events |= RC_CLIENT_ACHIEVEMENT_PENDING_EVENT_CHALLENGE_INDICATOR_SHOW; ++ ++ subset->pending_events |= RC_CLIENT_SUBSET_PENDING_EVENT_ACHIEVEMENT; ++ } ++} ++ ++static void rc_client_hide_progress_tracker(rc_client_t* client, rc_client_game_info_t* game) ++{ ++ /* ASSERT: this should only be called if the mutex is held */ ++ ++ if (game->progress_tracker.hide_callback && ++ game->progress_tracker.hide_callback->when && ++ game->progress_tracker.action == RC_CLIENT_PROGRESS_TRACKER_ACTION_NONE) { ++ rc_client_reschedule_callback(client, game->progress_tracker.hide_callback, 0); ++ game->progress_tracker.action = RC_CLIENT_PROGRESS_TRACKER_ACTION_HIDE; ++ game->pending_events |= RC_CLIENT_GAME_PENDING_EVENT_PROGRESS_TRACKER; ++ } ++} ++ ++static void rc_client_progress_tracker_timer_elapsed(rc_client_scheduled_callback_data_t* callback_data, rc_client_t* client, rc_clock_t now) ++{ ++ rc_client_event_t client_event; ++ memset(&client_event, 0, sizeof(client_event)); ++ ++ (void)callback_data; ++ (void)now; ++ ++ rc_mutex_lock(&client->state.mutex); ++ if (client->game->progress_tracker.action == RC_CLIENT_PROGRESS_TRACKER_ACTION_NONE) { ++ client->game->progress_tracker.hide_callback->when = 0; ++ client_event.type = RC_CLIENT_EVENT_ACHIEVEMENT_PROGRESS_INDICATOR_HIDE; ++ } ++ rc_mutex_unlock(&client->state.mutex); ++ ++ if (client_event.type) ++ client->callbacks.event_handler(&client_event, client); ++} ++ ++static void rc_client_do_frame_update_progress_tracker(rc_client_t* client, rc_client_game_info_t* game) ++{ ++ /* ASSERT: this should only be called if the mutex is held */ ++ ++ if (!game->progress_tracker.hide_callback) { ++ game->progress_tracker.hide_callback = (rc_client_scheduled_callback_data_t*) ++ rc_buffer_alloc(&game->buffer, sizeof(rc_client_scheduled_callback_data_t)); ++ memset(game->progress_tracker.hide_callback, 0, sizeof(rc_client_scheduled_callback_data_t)); ++ game->progress_tracker.hide_callback->callback = rc_client_progress_tracker_timer_elapsed; ++ } ++ ++ if (game->progress_tracker.hide_callback->when == 0) ++ game->progress_tracker.action = RC_CLIENT_PROGRESS_TRACKER_ACTION_SHOW; ++ else ++ game->progress_tracker.action = RC_CLIENT_PROGRESS_TRACKER_ACTION_UPDATE; ++ ++ rc_client_reschedule_callback(client, game->progress_tracker.hide_callback, ++ client->callbacks.get_time_millisecs(client) + 2 * 1000); ++} ++ ++static void rc_client_raise_progress_tracker_events(rc_client_t* client, rc_client_game_info_t* game) ++{ ++ rc_client_event_t client_event; ++ ++ memset(&client_event, 0, sizeof(client_event)); ++ ++ switch (game->progress_tracker.action) { ++ case RC_CLIENT_PROGRESS_TRACKER_ACTION_SHOW: ++ client_event.type = RC_CLIENT_EVENT_ACHIEVEMENT_PROGRESS_INDICATOR_SHOW; ++ break; ++ case RC_CLIENT_PROGRESS_TRACKER_ACTION_HIDE: ++ client_event.type = RC_CLIENT_EVENT_ACHIEVEMENT_PROGRESS_INDICATOR_HIDE; ++ break; ++ default: ++ client_event.type = RC_CLIENT_EVENT_ACHIEVEMENT_PROGRESS_INDICATOR_UPDATE; ++ break; ++ } ++ game->progress_tracker.action = RC_CLIENT_PROGRESS_TRACKER_ACTION_NONE; ++ ++ client_event.achievement = &game->progress_tracker.achievement->public_; ++ client->callbacks.event_handler(&client_event, client); ++} ++ ++static void rc_client_raise_achievement_events(rc_client_t* client, rc_client_subset_info_t* subset) ++{ ++ rc_client_achievement_info_t* achievement = subset->achievements; ++ rc_client_achievement_info_t* stop = achievement + subset->public_.num_achievements; ++ rc_client_event_t client_event; ++ time_t recent_unlock_time = 0; ++ ++ memset(&client_event, 0, sizeof(client_event)); ++ ++ for (; achievement < stop; ++achievement) { ++ if (achievement->pending_events == RC_CLIENT_ACHIEVEMENT_PENDING_EVENT_NONE) ++ continue; ++ ++ /* kick off award achievement request first */ ++ if (achievement->pending_events & RC_CLIENT_ACHIEVEMENT_PENDING_EVENT_TRIGGERED) { ++ rc_client_award_achievement(client, achievement); ++ client->game->pending_events |= RC_CLIENT_GAME_PENDING_EVENT_UPDATE_ACTIVE_ACHIEVEMENTS; ++ } ++ ++ /* update display state */ ++ if (recent_unlock_time == 0) ++ recent_unlock_time = time(NULL) - RC_CLIENT_RECENT_UNLOCK_DELAY_SECONDS; ++ rc_client_update_achievement_display_information(client, achievement, recent_unlock_time); ++ ++ /* raise events */ ++ client_event.achievement = &achievement->public_; ++ ++ if (achievement->pending_events & RC_CLIENT_ACHIEVEMENT_PENDING_EVENT_CHALLENGE_INDICATOR_HIDE) { ++ client_event.type = RC_CLIENT_EVENT_ACHIEVEMENT_CHALLENGE_INDICATOR_HIDE; ++ client->callbacks.event_handler(&client_event, client); ++ } ++ else if (achievement->pending_events & RC_CLIENT_ACHIEVEMENT_PENDING_EVENT_CHALLENGE_INDICATOR_SHOW) { ++ client_event.type = RC_CLIENT_EVENT_ACHIEVEMENT_CHALLENGE_INDICATOR_SHOW; ++ client->callbacks.event_handler(&client_event, client); ++ } ++ ++ if (achievement->pending_events & RC_CLIENT_ACHIEVEMENT_PENDING_EVENT_TRIGGERED) { ++ client_event.type = RC_CLIENT_EVENT_ACHIEVEMENT_TRIGGERED; ++ client->callbacks.event_handler(&client_event, client); ++ } ++ ++ /* clear pending flags */ ++ achievement->pending_events = RC_CLIENT_ACHIEVEMENT_PENDING_EVENT_NONE; ++ } ++} ++ ++static void rc_client_raise_mastery_event(rc_client_t* client, rc_client_subset_info_t* subset) ++{ ++ rc_client_event_t client_event; ++ ++ memset(&client_event, 0, sizeof(client_event)); ++ client_event.subset = &subset->public_; ++ ++ if (subset == client->game->subsets) ++ client_event.type = RC_CLIENT_EVENT_GAME_COMPLETED; ++ else ++ client_event.type = RC_CLIENT_EVENT_SUBSET_COMPLETED; ++ ++ subset->mastery = RC_CLIENT_MASTERY_STATE_SHOWN; ++ ++ client->callbacks.event_handler(&client_event, client); ++} ++ ++static void rc_client_do_frame_process_leaderboards(rc_client_t* client, rc_client_subset_info_t* subset) ++{ ++ rc_client_leaderboard_info_t* leaderboard = subset->leaderboards; ++ rc_client_leaderboard_info_t* stop = leaderboard + subset->public_.num_leaderboards; ++ ++ for (; leaderboard < stop; ++leaderboard) { ++ rc_lboard_t* lboard = leaderboard->lboard; ++ int old_state, new_state; ++ ++ switch (leaderboard->public_.state) { ++ case RC_CLIENT_LEADERBOARD_STATE_INACTIVE: ++ case RC_CLIENT_LEADERBOARD_STATE_DISABLED: ++ continue; ++ ++ default: ++ if (!lboard) ++ continue; ++ ++ break; ++ } ++ ++ old_state = lboard->state; ++ new_state = rc_evaluate_lboard(lboard, &leaderboard->value, client->state.legacy_peek, client, NULL); ++ ++ switch (new_state) { ++ case RC_LBOARD_STATE_STARTED: /* leaderboard is running */ ++ if (old_state != RC_LBOARD_STATE_STARTED) { ++ leaderboard->public_.state = RC_CLIENT_LEADERBOARD_STATE_TRACKING; ++ leaderboard->pending_events |= RC_CLIENT_LEADERBOARD_PENDING_EVENT_STARTED; ++ rc_client_allocate_leaderboard_tracker(client->game, leaderboard); ++ } ++ else { ++ rc_client_update_leaderboard_tracker(client->game, leaderboard); ++ } ++ break; ++ ++ case RC_LBOARD_STATE_CANCELED: ++ if (old_state != RC_LBOARD_STATE_CANCELED) { ++ leaderboard->public_.state = RC_CLIENT_LEADERBOARD_STATE_ACTIVE; ++ leaderboard->pending_events |= RC_CLIENT_LEADERBOARD_PENDING_EVENT_FAILED; ++ rc_client_release_leaderboard_tracker(client->game, leaderboard); ++ } ++ break; ++ ++ case RC_LBOARD_STATE_TRIGGERED: ++ if (old_state != RC_RUNTIME_EVENT_LBOARD_TRIGGERED) { ++ leaderboard->public_.state = RC_CLIENT_LEADERBOARD_STATE_ACTIVE; ++ leaderboard->pending_events |= RC_CLIENT_LEADERBOARD_PENDING_EVENT_SUBMITTED; ++ ++ if (old_state != RC_LBOARD_STATE_STARTED) ++ rc_client_allocate_leaderboard_tracker(client->game, leaderboard); ++ else ++ rc_client_update_leaderboard_tracker(client->game, leaderboard); ++ ++ rc_client_release_leaderboard_tracker(client->game, leaderboard); ++ } ++ break; ++ } ++ ++ if (leaderboard->pending_events) ++ subset->pending_events |= RC_CLIENT_SUBSET_PENDING_EVENT_LEADERBOARD; ++ } ++} ++ ++static void rc_client_raise_leaderboard_tracker_events(rc_client_t* client, rc_client_game_info_t* game) ++{ ++ rc_client_leaderboard_tracker_info_t* tracker = game->leaderboard_trackers; ++ rc_client_event_t client_event; ++ ++ memset(&client_event, 0, sizeof(client_event)); ++ ++ tracker = game->leaderboard_trackers; ++ for (; tracker; tracker = tracker->next) { ++ if (tracker->pending_events == RC_CLIENT_LEADERBOARD_TRACKER_PENDING_EVENT_NONE) ++ continue; ++ ++ client_event.leaderboard_tracker = &tracker->public_; ++ ++ /* update display text for new trackers or updated trackers */ ++ if (tracker->pending_events & (RC_CLIENT_LEADERBOARD_TRACKER_PENDING_EVENT_SHOW | RC_CLIENT_LEADERBOARD_TRACKER_PENDING_EVENT_UPDATE)) ++ rc_format_value(tracker->public_.display, sizeof(tracker->public_.display), tracker->raw_value, tracker->format); ++ ++ if (tracker->pending_events & RC_CLIENT_LEADERBOARD_TRACKER_PENDING_EVENT_HIDE) { ++ if (tracker->pending_events & RC_CLIENT_LEADERBOARD_TRACKER_PENDING_EVENT_SHOW) { ++ /* request to show and hide in the same frame - ignore the event */ ++ } ++ else { ++ client_event.type = RC_CLIENT_EVENT_LEADERBOARD_TRACKER_HIDE; ++ client->callbacks.event_handler(&client_event, client); ++ } ++ } ++ else if (tracker->pending_events & RC_CLIENT_LEADERBOARD_TRACKER_PENDING_EVENT_SHOW) { ++ client_event.type = RC_CLIENT_EVENT_LEADERBOARD_TRACKER_SHOW; ++ client->callbacks.event_handler(&client_event, client); ++ } ++ else if (tracker->pending_events & RC_CLIENT_LEADERBOARD_TRACKER_PENDING_EVENT_UPDATE) { ++ client_event.type = RC_CLIENT_EVENT_LEADERBOARD_TRACKER_UPDATE; ++ client->callbacks.event_handler(&client_event, client); ++ } ++ ++ tracker->pending_events = RC_CLIENT_LEADERBOARD_TRACKER_PENDING_EVENT_NONE; ++ } ++} ++ ++static void rc_client_raise_leaderboard_events(rc_client_t* client, rc_client_subset_info_t* subset) ++{ ++ rc_client_leaderboard_info_t* leaderboard = subset->leaderboards; ++ rc_client_leaderboard_info_t* leaderboard_stop = leaderboard + subset->public_.num_leaderboards; ++ rc_client_event_t client_event; ++ ++ memset(&client_event, 0, sizeof(client_event)); ++ ++ for (; leaderboard < leaderboard_stop; ++leaderboard) { ++ if (leaderboard->pending_events == RC_CLIENT_LEADERBOARD_PENDING_EVENT_NONE) ++ continue; ++ ++ client_event.leaderboard = &leaderboard->public_; ++ ++ if (leaderboard->pending_events & RC_CLIENT_LEADERBOARD_PENDING_EVENT_FAILED) { ++ RC_CLIENT_LOG_VERBOSE_FORMATTED(client, "Leaderboard %u canceled: %s", leaderboard->public_.id, leaderboard->public_.title); ++ client_event.type = RC_CLIENT_EVENT_LEADERBOARD_FAILED; ++ client->callbacks.event_handler(&client_event, client); ++ } ++ else if (leaderboard->pending_events & RC_CLIENT_LEADERBOARD_PENDING_EVENT_SUBMITTED) { ++ /* kick off submission request before raising event */ ++ rc_client_submit_leaderboard_entry(client, leaderboard); ++ ++ client_event.type = RC_CLIENT_EVENT_LEADERBOARD_SUBMITTED; ++ client->callbacks.event_handler(&client_event, client); ++ } ++ else if (leaderboard->pending_events & RC_CLIENT_LEADERBOARD_PENDING_EVENT_STARTED) { ++ RC_CLIENT_LOG_VERBOSE_FORMATTED(client, "Leaderboard %u started: %s", leaderboard->public_.id, leaderboard->public_.title); ++ client_event.type = RC_CLIENT_EVENT_LEADERBOARD_STARTED; ++ client->callbacks.event_handler(&client_event, client); ++ } ++ ++ leaderboard->pending_events = RC_CLIENT_LEADERBOARD_PENDING_EVENT_NONE; ++ } ++} ++ ++static void rc_client_reset_pending_events(rc_client_t* client) ++{ ++ rc_client_subset_info_t* subset; ++ ++ client->game->pending_events = RC_CLIENT_GAME_PENDING_EVENT_NONE; ++ ++ for (subset = client->game->subsets; subset; subset = subset->next) ++ subset->pending_events = RC_CLIENT_SUBSET_PENDING_EVENT_NONE; ++} ++ ++static void rc_client_subset_raise_pending_events(rc_client_t* client, rc_client_subset_info_t* subset) ++{ ++ /* raise any pending achievement events */ ++ if (subset->pending_events & RC_CLIENT_SUBSET_PENDING_EVENT_ACHIEVEMENT) ++ rc_client_raise_achievement_events(client, subset); ++ ++ /* raise any pending leaderboard events */ ++ if (subset->pending_events & RC_CLIENT_SUBSET_PENDING_EVENT_LEADERBOARD) ++ rc_client_raise_leaderboard_events(client, subset); ++ ++ /* raise mastery event if pending */ ++ if (subset->mastery == RC_CLIENT_MASTERY_STATE_PENDING) ++ rc_client_raise_mastery_event(client, subset); ++} ++ ++static void rc_client_raise_pending_events(rc_client_t* client, rc_client_game_info_t* game) ++{ ++ rc_client_subset_info_t* subset; ++ ++ /* raise tracker events before leaderboard events so formatted values are updated for leaderboard events */ ++ if (game->pending_events & RC_CLIENT_GAME_PENDING_EVENT_LEADERBOARD_TRACKER) ++ rc_client_raise_leaderboard_tracker_events(client, game); ++ ++ for (subset = game->subsets; subset; subset = subset->next) ++ rc_client_subset_raise_pending_events(client, subset); ++ ++ /* raise progress tracker events after achievement events so formatted values are updated for tracker event */ ++ if (game->pending_events & RC_CLIENT_GAME_PENDING_EVENT_PROGRESS_TRACKER) ++ rc_client_raise_progress_tracker_events(client, game); ++ ++ /* if any achievements were unlocked, resync the active achievements list */ ++ if (game->pending_events & RC_CLIENT_GAME_PENDING_EVENT_UPDATE_ACTIVE_ACHIEVEMENTS) { ++ rc_mutex_lock(&client->state.mutex); ++ rc_client_update_active_achievements(game); ++ rc_mutex_unlock(&client->state.mutex); ++ } ++ ++ game->pending_events = RC_CLIENT_GAME_PENDING_EVENT_NONE; ++} ++ ++void rc_client_do_frame(rc_client_t* client) ++{ ++ if (!client) ++ return; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->do_frame) { ++ client->state.external_client->do_frame(); ++ return; ++ } ++#endif ++ ++ if (client->game && !client->game->waiting_for_reset) { ++ rc_runtime_richpresence_t* richpresence; ++ rc_client_subset_info_t* subset; ++ ++ rc_mutex_lock(&client->state.mutex); ++ ++ rc_client_reset_pending_events(client); ++ ++ rc_client_update_memref_values(client); ++ ++ client->game->progress_tracker.progress = 0.0; ++ for (subset = client->game->subsets; subset; subset = subset->next) { ++ if (subset->active) ++ rc_client_do_frame_process_achievements(client, subset); ++ } ++ if (client->game->pending_events & RC_CLIENT_GAME_PENDING_EVENT_PROGRESS_TRACKER) ++ rc_client_do_frame_update_progress_tracker(client, client->game); ++ ++ if (client->state.hardcore || client->state.allow_leaderboards_in_softcore) { ++ for (subset = client->game->subsets; subset; subset = subset->next) { ++ if (subset->active) ++ rc_client_do_frame_process_leaderboards(client, subset); ++ } ++ } ++ ++ richpresence = client->game->runtime.richpresence; ++ if (richpresence && richpresence->richpresence) ++ rc_update_richpresence_internal(richpresence->richpresence, client->state.legacy_peek, client); ++ ++ rc_mutex_unlock(&client->state.mutex); ++ ++ rc_client_raise_pending_events(client, client->game); ++ ++ ++client->state.frames_processed; ++ } ++ ++ /* we've processed a frame. if there's a pause delay in effect, process it */ ++ if (client->state.unpaused_frame_decay > 0) { ++ client->state.unpaused_frame_decay--; ++ ++ if (client->state.unpaused_frame_decay == 0 && ++ client->state.required_unpaused_frames > RC_MINIMUM_UNPAUSED_FRAMES) { ++ /* the full decay has elapsed and a penalty still exists. ++ * lower the penalty and reset the decay counter */ ++ client->state.required_unpaused_frames >>= 1; ++ ++ if (client->state.required_unpaused_frames <= RC_MINIMUM_UNPAUSED_FRAMES) ++ client->state.required_unpaused_frames = RC_MINIMUM_UNPAUSED_FRAMES; ++ ++ client->state.unpaused_frame_decay = ++ client->state.required_unpaused_frames * (RC_PAUSE_DECAY_MULTIPLIER - 1) - 1; ++ } ++ } ++ ++ rc_client_idle(client); ++} ++ ++void rc_client_idle(rc_client_t* client) ++{ ++ rc_client_scheduled_callback_data_t* scheduled_callback; ++ ++ if (!client) ++ return; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->idle) { ++ client->state.external_client->idle(); ++ return; ++ } ++#endif ++ ++ scheduled_callback = client->state.scheduled_callbacks; ++ if (scheduled_callback) { ++ const rc_clock_t now = client->callbacks.get_time_millisecs(client); ++ ++ do { ++ rc_mutex_lock(&client->state.mutex); ++ scheduled_callback = client->state.scheduled_callbacks; ++ if (scheduled_callback) { ++ if (scheduled_callback->when > now) { ++ /* not time for next callback yet, ignore it */ ++ scheduled_callback = NULL; ++ } ++ else { ++ /* remove the callback from the queue while we process it. callback can requeue if desired */ ++ client->state.scheduled_callbacks = scheduled_callback->next; ++ scheduled_callback->next = NULL; ++ } ++ } ++ rc_mutex_unlock(&client->state.mutex); ++ ++ if (!scheduled_callback) ++ break; ++ ++ scheduled_callback->callback(scheduled_callback, client, now); ++ } while (1); ++ } ++ ++ if (client->state.disconnect & ~RC_CLIENT_DISCONNECT_VISIBLE) ++ rc_client_raise_disconnect_events(client); ++} ++ ++void rc_client_schedule_callback(rc_client_t* client, rc_client_scheduled_callback_data_t* scheduled_callback) ++{ ++ rc_client_scheduled_callback_data_t** last; ++ rc_client_scheduled_callback_data_t* next; ++ ++ rc_mutex_lock(&client->state.mutex); ++ ++ last = &client->state.scheduled_callbacks; ++ do { ++ next = *last; ++ if (!next || scheduled_callback->when < next->when) { ++ scheduled_callback->next = next; ++ *last = scheduled_callback; ++ break; ++ } ++ ++ last = &next->next; ++ } while (1); ++ ++ rc_mutex_unlock(&client->state.mutex); ++} ++ ++static void rc_client_reschedule_callback(rc_client_t* client, ++ rc_client_scheduled_callback_data_t* callback, rc_clock_t when) ++{ ++ rc_client_scheduled_callback_data_t** last; ++ rc_client_scheduled_callback_data_t* next; ++ ++ /* ASSERT: this should only be called if the mutex is held */ ++ ++ callback->when = when; ++ ++ last = &client->state.scheduled_callbacks; ++ do { ++ next = *last; ++ ++ if (next == callback) { ++ if (when == 0) { ++ /* request to unschedule the callback */ ++ *last = next->next; ++ next->next = NULL; ++ break; ++ } ++ ++ if (!next->next) { ++ /* end of list, just append it */ ++ break; ++ } ++ ++ if (when < next->next->when) { ++ /* already in the correct place */ ++ break; ++ } ++ ++ /* remove from current position - will insert later */ ++ *last = next->next; ++ next->next = NULL; ++ continue; ++ } ++ ++ if (!next || (when < next->when && when != 0)) { ++ /* insert here */ ++ callback->next = next; ++ *last = callback; ++ break; ++ } ++ ++ last = &next->next; ++ } while (1); ++} ++ ++static void rc_client_reset_richpresence(rc_client_t* client) ++{ ++ rc_runtime_richpresence_t* richpresence = client->game->runtime.richpresence; ++ if (richpresence && richpresence->richpresence) ++ rc_reset_richpresence(richpresence->richpresence); ++} ++ ++static void rc_client_reset_variables(rc_client_t* client) ++{ ++ if (client->game->runtime.richpresence && client->game->runtime.richpresence->richpresence) ++ rc_reset_values(client->game->runtime.richpresence->richpresence->values); ++} ++ ++static void rc_client_reset_all(rc_client_t* client) ++{ ++ rc_client_reset_achievements(client); ++ rc_client_reset_leaderboards(client); ++ rc_client_reset_richpresence(client); ++ rc_client_reset_variables(client); ++} ++ ++void rc_client_reset(rc_client_t* client) ++{ ++ rc_client_game_hash_t* game_hash; ++ if (!client) ++ return; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->reset) { ++ client->state.external_client->reset(); ++ return; ++ } ++#endif ++ ++ if (!client->game) ++ return; ++ ++ game_hash = rc_client_find_game_hash(client, client->game->public_.hash); ++ if (game_hash && game_hash->game_id != client->game->public_.id) { ++ /* current media is not for loaded game. unload game */ ++ RC_CLIENT_LOG_WARN_FORMATTED(client, "Disabling runtime. Reset with non-game media loaded: %u (%s)", ++ (game_hash->game_id == RC_CLIENT_UNKNOWN_GAME_ID) ? 0 : game_hash->game_id, game_hash->hash); ++ rc_client_unload_game(client); ++ return; ++ } ++ ++ RC_CLIENT_LOG_INFO(client, "Resetting runtime"); ++ ++ rc_mutex_lock(&client->state.mutex); ++ ++ client->game->waiting_for_reset = 0; ++ rc_client_reset_pending_events(client); ++ ++ rc_client_hide_progress_tracker(client, client->game); ++ rc_client_reset_all(client); ++ ++ rc_mutex_unlock(&client->state.mutex); ++ ++ rc_client_raise_pending_events(client, client->game); ++} ++ ++int rc_client_can_pause(rc_client_t* client, uint32_t* frames_remaining) ++{ ++ if (!client) ++ return 1; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->can_pause) ++ return client->state.external_client->can_pause(frames_remaining); ++#endif ++ ++ if (frames_remaining) ++ *frames_remaining = 0; ++ ++ /* pause is always allowed in softcore */ ++ if (!rc_client_get_hardcore_enabled(client)) ++ return 1; ++ ++ /* a full decay means we haven't processed any frames since the last time this was called. */ ++ if (client->state.unpaused_frame_decay == client->state.required_unpaused_frames * RC_PAUSE_DECAY_MULTIPLIER) ++ return 1; ++ ++ /* if less than RC_MINIMUM_UNPAUSED_FRAMES have been processed, don't allow the pause */ ++ if (client->state.unpaused_frame_decay > client->state.required_unpaused_frames * (RC_PAUSE_DECAY_MULTIPLIER - 1)) { ++ if (frames_remaining) { ++ *frames_remaining = client->state.unpaused_frame_decay - ++ client->state.required_unpaused_frames * (RC_PAUSE_DECAY_MULTIPLIER - 1); ++ } ++ return 0; ++ } ++ ++ /* we're going to allow the emulator to pause. calculate how many frames are needed before the next ++ * pause will be allowed. */ ++ ++ if (client->state.unpaused_frame_decay > 0) { ++ /* The user has paused within the decay window. Require a longer ++ * run of unpaused frames before allowing the next pause */ ++ if (client->state.required_unpaused_frames < 5 * 60) /* don't make delay longer then 5 seconds */ ++ client->state.required_unpaused_frames += RC_MINIMUM_UNPAUSED_FRAMES; ++ } ++ ++ /* require multiple unpaused_frames windows to decay the penalty */ ++ client->state.unpaused_frame_decay = client->state.required_unpaused_frames * RC_PAUSE_DECAY_MULTIPLIER; ++ ++ return 1; ++} ++ ++size_t rc_client_progress_size(rc_client_t* client) ++{ ++ size_t result; ++ ++ if (!client) ++ return 0; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->progress_size) ++ return client->state.external_client->progress_size(); ++#endif ++ ++ if (!rc_client_is_game_loaded(client)) ++ return 0; ++ ++ rc_mutex_lock(&client->state.mutex); ++ result = rc_runtime_progress_size(&client->game->runtime, NULL); ++ rc_mutex_unlock(&client->state.mutex); ++ ++ return result; ++} ++ ++int rc_client_serialize_progress(rc_client_t* client, uint8_t* buffer) ++{ ++ return rc_client_serialize_progress_sized(client, buffer, 0xFFFFFFFF); ++} ++ ++int rc_client_serialize_progress_sized(rc_client_t* client, uint8_t* buffer, size_t buffer_size) ++{ ++ int result; ++ ++ if (!client) ++ return RC_NO_GAME_LOADED; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->serialize_progress) ++ return client->state.external_client->serialize_progress(buffer, buffer_size); ++#endif ++ ++ if (!rc_client_is_game_loaded(client)) ++ return RC_NO_GAME_LOADED; ++ ++ if (!buffer) ++ return RC_INVALID_STATE; ++ ++ rc_mutex_lock(&client->state.mutex); ++ result = rc_runtime_serialize_progress_sized(buffer, (uint32_t)buffer_size, &client->game->runtime, NULL); ++ rc_mutex_unlock(&client->state.mutex); ++ ++ return result; ++} ++ ++static void rc_client_subset_before_deserialize_progress(rc_client_subset_info_t* subset) ++{ ++ rc_client_achievement_info_t* achievement; ++ rc_client_achievement_info_t* achievement_stop; ++ rc_client_leaderboard_info_t* leaderboard; ++ rc_client_leaderboard_info_t* leaderboard_stop; ++ ++ /* flag any visible challenge indicators to be hidden */ ++ achievement = subset->achievements; ++ achievement_stop = achievement + subset->public_.num_achievements; ++ for (; achievement < achievement_stop; ++achievement) { ++ rc_trigger_t* trigger = achievement->trigger; ++ if (trigger && trigger->state == RC_TRIGGER_STATE_PRIMED && ++ achievement->public_.state == RC_CLIENT_ACHIEVEMENT_STATE_ACTIVE) { ++ achievement->pending_events |= RC_CLIENT_ACHIEVEMENT_PENDING_EVENT_CHALLENGE_INDICATOR_HIDE; ++ subset->pending_events |= RC_CLIENT_SUBSET_PENDING_EVENT_ACHIEVEMENT; ++ } ++ } ++ ++ /* flag any visible trackers to be hidden */ ++ leaderboard = subset->leaderboards; ++ leaderboard_stop = leaderboard + subset->public_.num_leaderboards; ++ for (; leaderboard < leaderboard_stop; ++leaderboard) { ++ rc_lboard_t* lboard = leaderboard->lboard; ++ if (lboard && lboard->state == RC_LBOARD_STATE_STARTED && ++ leaderboard->public_.state == RC_CLIENT_LEADERBOARD_STATE_TRACKING) { ++ leaderboard->pending_events |= RC_CLIENT_LEADERBOARD_PENDING_EVENT_FAILED; ++ subset->pending_events |= RC_CLIENT_SUBSET_PENDING_EVENT_LEADERBOARD; ++ } ++ } ++} ++ ++static void rc_client_subset_after_deserialize_progress(rc_client_game_info_t* game, rc_client_subset_info_t* subset) ++{ ++ rc_client_achievement_info_t* achievement; ++ rc_client_achievement_info_t* achievement_stop; ++ rc_client_leaderboard_info_t* leaderboard; ++ rc_client_leaderboard_info_t* leaderboard_stop; ++ ++ /* flag any challenge indicators that should be shown */ ++ achievement = subset->achievements; ++ achievement_stop = achievement + subset->public_.num_achievements; ++ for (; achievement < achievement_stop; ++achievement) { ++ rc_trigger_t* trigger = achievement->trigger; ++ if (!trigger || achievement->public_.state != RC_CLIENT_ACHIEVEMENT_STATE_ACTIVE) ++ continue; ++ ++ if (trigger->state == RC_TRIGGER_STATE_PRIMED) { ++ /* if it's already shown, just keep it. otherwise flag it to be shown */ ++ if (achievement->pending_events & RC_CLIENT_ACHIEVEMENT_PENDING_EVENT_CHALLENGE_INDICATOR_HIDE) { ++ achievement->pending_events &= ~RC_CLIENT_ACHIEVEMENT_PENDING_EVENT_CHALLENGE_INDICATOR_HIDE; ++ } ++ else { ++ achievement->pending_events |= RC_CLIENT_ACHIEVEMENT_PENDING_EVENT_CHALLENGE_INDICATOR_SHOW; ++ subset->pending_events |= RC_CLIENT_SUBSET_PENDING_EVENT_ACHIEVEMENT; ++ } ++ } ++ /* ASSERT: only active achievements are serialized, so we don't have to worry about ++ * deserialization deactiving them. */ ++ } ++ ++ /* flag any trackers that need to be shown */ ++ leaderboard = subset->leaderboards; ++ leaderboard_stop = leaderboard + subset->public_.num_leaderboards; ++ for (; leaderboard < leaderboard_stop; ++leaderboard) { ++ rc_lboard_t* lboard = leaderboard->lboard; ++ if (!lboard || ++ leaderboard->public_.state == RC_CLIENT_LEADERBOARD_STATE_INACTIVE || ++ leaderboard->public_.state == RC_CLIENT_LEADERBOARD_STATE_DISABLED) ++ continue; ++ ++ if (lboard->state == RC_LBOARD_STATE_STARTED) { ++ leaderboard->value = (int)lboard->value.value.value; ++ leaderboard->public_.state = RC_CLIENT_LEADERBOARD_STATE_TRACKING; ++ ++ /* if it's already being tracked, just update tracker. otherwise, allocate one */ ++ if (leaderboard->pending_events & RC_CLIENT_LEADERBOARD_PENDING_EVENT_FAILED) { ++ leaderboard->pending_events &= ~RC_CLIENT_LEADERBOARD_PENDING_EVENT_FAILED; ++ rc_client_update_leaderboard_tracker(game, leaderboard); ++ } ++ else { ++ rc_client_allocate_leaderboard_tracker(game, leaderboard); ++ } ++ } ++ else if (leaderboard->pending_events & RC_CLIENT_LEADERBOARD_PENDING_EVENT_FAILED) { ++ /* deallocate the tracker (don't actually raise the failed event) */ ++ leaderboard->pending_events &= ~RC_CLIENT_LEADERBOARD_PENDING_EVENT_FAILED; ++ leaderboard->public_.state = RC_CLIENT_LEADERBOARD_STATE_ACTIVE; ++ rc_client_release_leaderboard_tracker(game, leaderboard); ++ } ++ } ++} ++ ++int rc_client_deserialize_progress(rc_client_t* client, const uint8_t* serialized) ++{ ++ return rc_client_deserialize_progress_sized(client, serialized, 0xFFFFFFFF); ++} ++ ++int rc_client_deserialize_progress_sized(rc_client_t* client, const uint8_t* serialized, size_t serialized_size) ++{ ++ rc_client_subset_info_t* subset; ++ int result; ++ ++ if (!client) ++ return RC_NO_GAME_LOADED; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->deserialize_progress) ++ return client->state.external_client->deserialize_progress(serialized, serialized_size); ++#endif ++ ++ if (!rc_client_is_game_loaded(client)) ++ return RC_NO_GAME_LOADED; ++ ++ rc_mutex_lock(&client->state.mutex); ++ ++ rc_client_reset_pending_events(client); ++ ++ for (subset = client->game->subsets; subset; subset = subset->next) ++ rc_client_subset_before_deserialize_progress(subset); ++ ++ rc_client_hide_progress_tracker(client, client->game); ++ ++ if (!serialized) { ++ rc_client_reset_all(client); ++ result = RC_OK; ++ } ++ else { ++ result = rc_runtime_deserialize_progress_sized(&client->game->runtime, serialized, (uint32_t)serialized_size, NULL); ++ } ++ ++ for (subset = client->game->subsets; subset; subset = subset->next) ++ rc_client_subset_after_deserialize_progress(client->game, subset); ++ ++ rc_mutex_unlock(&client->state.mutex); ++ ++ rc_client_raise_pending_events(client, client->game); ++ ++ return result; ++} ++ ++/* ===== Toggles ===== */ ++ ++static void rc_client_enable_hardcore(rc_client_t* client) ++{ ++ client->state.hardcore = 1; ++ ++ if (client->game) { ++ rc_client_toggle_hardcore_achievements(client->game, client, RC_CLIENT_ACHIEVEMENT_UNLOCKED_HARDCORE); ++ rc_client_activate_leaderboards(client->game, client); ++ ++ /* disable processing until the client acknowledges the reset event by calling rc_runtime_reset() */ ++ RC_CLIENT_LOG_INFO(client, "Hardcore enabled, waiting for reset"); ++ client->game->waiting_for_reset = 1; ++ } ++ else { ++ RC_CLIENT_LOG_INFO(client, "Hardcore enabled"); ++ } ++} ++ ++static void rc_client_disable_hardcore(rc_client_t* client) ++{ ++ client->state.hardcore = 0; ++ RC_CLIENT_LOG_INFO(client, "Hardcore disabled"); ++ ++ if (client->game) { ++ rc_client_toggle_hardcore_achievements(client->game, client, RC_CLIENT_ACHIEVEMENT_UNLOCKED_SOFTCORE); ++ ++ if (!client->state.allow_leaderboards_in_softcore) ++ rc_client_deactivate_leaderboards(client->game, client); ++ } ++} ++ ++void rc_client_set_hardcore_enabled(rc_client_t* client, int enabled) ++{ ++ int changed = 0; ++ ++ if (!client) ++ return; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->get_hardcore_enabled) { ++ client->state.external_client->set_hardcore_enabled(enabled); ++ return; ++ } ++#endif ++ ++ rc_mutex_lock(&client->state.mutex); ++ ++ enabled = enabled ? 1 : 0; ++ if (client->state.hardcore != enabled) { ++ if (enabled) ++ rc_client_enable_hardcore(client); ++ else ++ rc_client_disable_hardcore(client); ++ ++ changed = 1; ++ } ++ ++ rc_mutex_unlock(&client->state.mutex); ++ ++ /* events must be raised outside of lock */ ++ if (changed && client->game) { ++ if (enabled) { ++ /* if enabling hardcore, notify client that a reset is requested */ ++ if (client->game->waiting_for_reset) { ++ rc_client_event_t client_event; ++ memset(&client_event, 0, sizeof(client_event)); ++ client_event.type = RC_CLIENT_EVENT_RESET; ++ client->callbacks.event_handler(&client_event, client); ++ } ++ } ++ else { ++ /* if disabling hardcore, leaderboards will be deactivated. raise events for hiding trackers */ ++ rc_client_raise_pending_events(client, client->game); ++ } ++ } ++} ++ ++int rc_client_get_hardcore_enabled(const rc_client_t* client) ++{ ++ if (!client) ++ return 0; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->get_hardcore_enabled) ++ return client->state.external_client->get_hardcore_enabled(); ++#endif ++ ++ return client->state.hardcore; ++} ++ ++void rc_client_set_unofficial_enabled(rc_client_t* client, int enabled) ++{ ++ if (!client) ++ return; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->set_unofficial_enabled) { ++ client->state.external_client->set_unofficial_enabled(enabled); ++ return; ++ } ++#endif ++ ++ RC_CLIENT_LOG_INFO_FORMATTED(client, "Unofficial %s", enabled ? "enabled" : "disabled"); ++ client->state.unofficial_enabled = enabled ? 1 : 0; ++} ++ ++int rc_client_get_unofficial_enabled(const rc_client_t* client) ++{ ++ if (!client) ++ return 0; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->get_unofficial_enabled) ++ return client->state.external_client->get_unofficial_enabled(); ++#endif ++ ++ return client->state.unofficial_enabled; ++} ++ ++void rc_client_set_encore_mode_enabled(rc_client_t* client, int enabled) ++{ ++ if (!client) ++ return; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->set_encore_mode_enabled) { ++ client->state.external_client->set_encore_mode_enabled(enabled); ++ return; ++ } ++#endif ++ ++ RC_CLIENT_LOG_INFO_FORMATTED(client, "Encore mode %s", enabled ? "enabled" : "disabled"); ++ client->state.encore_mode = enabled ? 1 : 0; ++} ++ ++int rc_client_get_encore_mode_enabled(const rc_client_t* client) ++{ ++ if (!client) ++ return 0; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->get_encore_mode_enabled) ++ return client->state.external_client->get_encore_mode_enabled(); ++#endif ++ ++ return client->state.encore_mode; ++} ++ ++void rc_client_set_spectator_mode_enabled(rc_client_t* client, int enabled) ++{ ++ if (!client) ++ return; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->set_spectator_mode_enabled) { ++ client->state.external_client->set_spectator_mode_enabled(enabled); ++ return; ++ } ++#endif ++ ++ if (!enabled && client->state.spectator_mode == RC_CLIENT_SPECTATOR_MODE_LOCKED) { ++ RC_CLIENT_LOG_WARN(client, "Spectator mode cannot be disabled if it was enabled prior to loading game."); ++ return; ++ } ++ ++ RC_CLIENT_LOG_INFO_FORMATTED(client, "Spectator mode %s", enabled ? "enabled" : "disabled"); ++ client->state.spectator_mode = enabled ? RC_CLIENT_SPECTATOR_MODE_ON : RC_CLIENT_SPECTATOR_MODE_OFF; ++} ++ ++int rc_client_get_spectator_mode_enabled(const rc_client_t* client) ++{ ++ if (!client) ++ return 0; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->get_spectator_mode_enabled) ++ return client->state.external_client->get_spectator_mode_enabled(); ++#endif ++ ++ return (client->state.spectator_mode == RC_CLIENT_SPECTATOR_MODE_OFF) ? 0 : 1; ++} ++ ++void rc_client_set_userdata(rc_client_t* client, void* userdata) ++{ ++ if (client) ++ client->callbacks.client_data = userdata; ++} ++ ++void* rc_client_get_userdata(const rc_client_t* client) ++{ ++ return client ? client->callbacks.client_data : NULL; ++} ++ ++void rc_client_set_host(rc_client_t* client, const char* hostname) ++{ ++ if (!client) ++ return; ++ ++ if (client->state.host.host && hostname && strcmp(hostname, client->state.host.host) == 0) ++ return; ++ ++ /* clear out any previously specified host information */ ++ memset(&client->state.host, 0, sizeof(client->state.host)); ++ ++ if (hostname && (!hostname[0] || strcmp(hostname, rc_api_default_host()) == 0)) { ++ RC_CLIENT_LOG_VERBOSE_FORMATTED(client, "Using host: %s", rc_api_default_host()); ++ hostname = rc_api_default_host(); ++ } ++ else { ++ RC_CLIENT_LOG_VERBOSE_FORMATTED(client, "Using host: %s", hostname); ++ client->state.host.host = rc_buffer_strcpy(&client->state.buffer, hostname); ++ } ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client->state.external_client && client->state.external_client->set_host) ++ client->state.external_client->set_host(hostname); ++#endif ++} ++ ++size_t rc_client_get_user_agent_clause(rc_client_t* client, char buffer[], size_t buffer_size) ++{ ++ size_t result; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ if (client && client->state.external_client && client->state.external_client->get_user_agent_clause) { ++ result = client->state.external_client->get_user_agent_clause(buffer, buffer_size); ++ if (result > 0) { ++ result += snprintf(buffer + result, buffer_size - result, " rc_client/" RCHEEVOS_VERSION_STRING); ++ buffer[buffer_size - 1] = '\0'; ++ return result; ++ } ++ } ++#else ++ (void)client; ++#endif ++ ++ result = snprintf(buffer, buffer_size, "rcheevos/" RCHEEVOS_VERSION_STRING); ++ ++ /* some implementations of snprintf will fill the buffer without null terminating. ++ * make sure the buffer is null terminated */ ++ buffer[buffer_size - 1] = '\0'; ++ return result; ++} +diff -rupbN melonDS.orig/src/rcheevos/src/rc_client_internal.h melonDS.ra/src/rcheevos/src/rc_client_internal.h +--- melonDS.orig/src/rcheevos/src/rc_client_internal.h 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rc_client_internal.h 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,409 @@ ++#ifndef RC_CLIENT_INTERNAL_H ++#define RC_CLIENT_INTERNAL_H ++ ++#include "rc_client.h" ++ ++#ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION ++ #include "rc_client_raintegration_internal.h" ++#endif ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ #include "rc_client_external.h" ++#endif ++#ifdef RC_CLIENT_SUPPORTS_HASH ++ #include "rhash/rc_hash_internal.h" ++#endif ++ ++#include "rc_compat.h" ++#include "rc_runtime.h" ++#include "rc_runtime_types.h" ++ ++RC_BEGIN_C_DECLS ++ ++/*****************************************************************************\ ++| Callbacks | ++\*****************************************************************************/ ++ ++struct rc_api_fetch_game_sets_response_t; ++typedef void (RC_CCONV *rc_client_post_process_game_sets_response_t)(const rc_api_server_response_t* server_response, ++ struct rc_api_fetch_game_sets_response_t* game_sets_response, rc_client_t* client, void* userdata); ++typedef int (RC_CCONV *rc_client_can_submit_achievement_unlock_t)(uint32_t achievement_id, rc_client_t* client); ++typedef int (RC_CCONV *rc_client_can_submit_leaderboard_entry_t)(uint32_t leaderboard_id, rc_client_t* client); ++typedef int (RC_CCONV *rc_client_rich_presence_override_t)(rc_client_t* client, char buffer[], size_t buffersize); ++typedef uint32_t (RC_CCONV* rc_client_identify_hash_func_t)(uint32_t console_id, const char* hash, ++ rc_client_t* client, void* callback_userdata); ++ ++typedef struct rc_client_callbacks_t { ++ rc_client_read_memory_func_t read_memory; ++ rc_client_event_handler_t event_handler; ++ rc_client_server_call_t server_call; ++ rc_client_message_callback_t log_call; ++ rc_get_time_millisecs_func_t get_time_millisecs; ++ rc_client_identify_hash_func_t identify_unknown_hash; ++ rc_client_post_process_game_sets_response_t post_process_game_sets_response; ++ rc_client_can_submit_achievement_unlock_t can_submit_achievement_unlock; ++ rc_client_can_submit_leaderboard_entry_t can_submit_leaderboard_entry; ++ rc_client_rich_presence_override_t rich_presence_override; ++ ++#ifdef RC_CLIENT_SUPPORTS_HASH ++ rc_hash_callbacks_t hash; ++#endif ++ ++ void* client_data; ++} rc_client_callbacks_t; ++ ++struct rc_client_scheduled_callback_data_t; ++typedef void (RC_CCONV *rc_client_scheduled_callback_t)(struct rc_client_scheduled_callback_data_t* callback_data, rc_client_t* client, rc_clock_t now); ++ ++typedef struct rc_client_scheduled_callback_data_t ++{ ++ rc_clock_t when; ++ uint32_t related_id; ++ rc_client_scheduled_callback_t callback; ++ void* data; ++ struct rc_client_scheduled_callback_data_t* next; ++} rc_client_scheduled_callback_data_t; ++ ++void rc_client_schedule_callback(rc_client_t* client, rc_client_scheduled_callback_data_t* scheduled_callback); ++ ++struct rc_client_async_handle_t { ++ uint8_t aborted; ++}; ++ ++int rc_client_async_handle_aborted(rc_client_t* client, rc_client_async_handle_t* async_handle); ++ ++/*****************************************************************************\ ++| Achievements | ++\*****************************************************************************/ ++ ++enum { ++ RC_CLIENT_ACHIEVEMENT_PENDING_EVENT_NONE = 0, ++ RC_CLIENT_ACHIEVEMENT_PENDING_EVENT_TRIGGERED = (1 << 1), ++ RC_CLIENT_ACHIEVEMENT_PENDING_EVENT_CHALLENGE_INDICATOR_SHOW = (1 << 2), ++ RC_CLIENT_ACHIEVEMENT_PENDING_EVENT_CHALLENGE_INDICATOR_HIDE = (1 << 3), ++ RC_CLIENT_ACHIEVEMENT_PENDING_EVENT_UPDATE = (1 << 4) /* not a real event, just triggers update */ ++}; ++ ++typedef struct rc_client_achievement_info_t { ++ rc_client_achievement_t public_; ++ ++ rc_trigger_t* trigger; ++ uint8_t md5[16]; ++ ++ time_t unlock_time_hardcore; ++ time_t unlock_time_softcore; ++ ++ uint8_t pending_events; ++ ++ const char* author; ++ time_t created_time; ++ time_t updated_time; ++} rc_client_achievement_info_t; ++ ++struct rc_client_achievement_list_info_t; ++typedef void (RC_CCONV *rc_client_destroy_achievement_list_func_t)(struct rc_client_achievement_list_info_t* list); ++ ++typedef struct rc_client_achievement_list_info_t { ++ rc_client_achievement_list_t public_; ++ rc_client_destroy_achievement_list_func_t destroy_func; ++} rc_client_achievement_list_info_t; ++ ++enum { ++ RC_CLIENT_PROGRESS_TRACKER_ACTION_NONE, ++ RC_CLIENT_PROGRESS_TRACKER_ACTION_SHOW, ++ RC_CLIENT_PROGRESS_TRACKER_ACTION_UPDATE, ++ RC_CLIENT_PROGRESS_TRACKER_ACTION_HIDE ++}; ++ ++typedef struct rc_client_progress_tracker_t { ++ rc_client_achievement_info_t* achievement; ++ float progress; ++ ++ rc_client_scheduled_callback_data_t* hide_callback; ++ uint8_t action; ++} rc_client_progress_tracker_t; ++ ++/*****************************************************************************\ ++| Leaderboard Trackers | ++\*****************************************************************************/ ++ ++enum { ++ RC_CLIENT_LEADERBOARD_TRACKER_PENDING_EVENT_NONE = 0, ++ RC_CLIENT_LEADERBOARD_TRACKER_PENDING_EVENT_UPDATE = (1 << 1), ++ RC_CLIENT_LEADERBOARD_TRACKER_PENDING_EVENT_SHOW = (1 << 2), ++ RC_CLIENT_LEADERBOARD_TRACKER_PENDING_EVENT_HIDE = (1 << 3) ++}; ++ ++typedef struct rc_client_leaderboard_tracker_info_t { ++ rc_client_leaderboard_tracker_t public_; ++ struct rc_client_leaderboard_tracker_info_t* next; ++ int32_t raw_value; ++ ++ uint32_t value_djb2; ++ ++ uint8_t format; ++ uint8_t pending_events; ++ uint8_t reference_count; ++ uint8_t value_from_hits; ++} rc_client_leaderboard_tracker_info_t; ++ ++/*****************************************************************************\ ++| Leaderboards | ++\*****************************************************************************/ ++ ++enum { ++ RC_CLIENT_LEADERBOARD_PENDING_EVENT_NONE = 0, ++ RC_CLIENT_LEADERBOARD_PENDING_EVENT_STARTED = (1 << 1), ++ RC_CLIENT_LEADERBOARD_PENDING_EVENT_FAILED = (1 << 2), ++ RC_CLIENT_LEADERBOARD_PENDING_EVENT_SUBMITTED = (1 << 3) ++}; ++ ++typedef struct rc_client_leaderboard_info_t { ++ rc_client_leaderboard_t public_; ++ ++ rc_lboard_t* lboard; ++ uint8_t md5[16]; ++ ++ rc_client_leaderboard_tracker_info_t* tracker; ++ ++ uint32_t value_djb2; ++ int32_t value; ++ ++ uint8_t format; ++ uint8_t pending_events; ++ uint8_t bucket; ++ uint8_t hidden; ++} rc_client_leaderboard_info_t; ++ ++struct rc_client_leaderboard_list_info_t; ++typedef void (RC_CCONV *rc_client_destroy_leaderboard_list_func_t)(struct rc_client_leaderboard_list_info_t* list); ++ ++typedef struct rc_client_leaderboard_list_info_t { ++ rc_client_leaderboard_list_t public_; ++ rc_client_destroy_leaderboard_list_func_t destroy_func; ++} rc_client_leaderboard_list_info_t; ++ ++struct rc_client_leaderboard_entry_list_info_t; ++typedef void (RC_CCONV *rc_client_destroy_leaderboard_entry_list_func_t)(struct rc_client_leaderboard_entry_list_info_t* list); ++ ++typedef struct rc_client_leaderboard_entry_list_info_t { ++ rc_client_leaderboard_entry_list_t public_; ++ rc_client_destroy_leaderboard_entry_list_func_t destroy_func; ++} rc_client_leaderboard_entry_list_info_t; ++ ++uint8_t rc_client_map_leaderboard_format(int format); ++ ++/*****************************************************************************\ ++| Subsets | ++\*****************************************************************************/ ++ ++enum { ++ RC_CLIENT_SUBSET_PENDING_EVENT_NONE = 0, ++ RC_CLIENT_SUBSET_PENDING_EVENT_ACHIEVEMENT = (1 << 1), ++ RC_CLIENT_SUBSET_PENDING_EVENT_LEADERBOARD = (1 << 2) ++}; ++ ++typedef struct rc_client_subset_info_t { ++ rc_client_subset_t public_; ++ ++ rc_client_achievement_info_t* achievements; ++ rc_client_leaderboard_info_t* leaderboards; ++ ++ struct rc_client_subset_info_t* next; ++ ++ const char* all_label; ++ const char* inactive_label; ++ const char* locked_label; ++ const char* unlocked_label; ++ const char* unofficial_label; ++ const char* unsupported_label; ++ ++ uint8_t active; ++ uint8_t mastery; ++ uint8_t pending_events; ++} rc_client_subset_info_t; ++ ++struct rc_client_subset_list_info_t; ++typedef void (RC_CCONV* rc_client_destroy_subset_list_func_t)(struct rc_client_subset_list_info_t* list); ++ ++typedef struct rc_client_subset_list_info_t { ++ rc_client_subset_list_t public_; ++ rc_client_destroy_subset_list_func_t destroy_func; ++} rc_client_subset_list_info_t; ++ ++/*****************************************************************************\ ++| Game | ++\*****************************************************************************/ ++ ++typedef struct rc_client_game_hash_t { ++ char hash[33]; ++ uint8_t is_unknown; ++ uint32_t game_id; ++ struct rc_client_game_hash_t* next; ++} rc_client_game_hash_t; ++ ++rc_client_game_hash_t* rc_client_find_game_hash(rc_client_t* client, const char* hash); ++ ++typedef struct rc_client_media_hash_t { ++ rc_client_game_hash_t* game_hash; ++ struct rc_client_media_hash_t* next; ++ uint32_t path_djb2; ++} rc_client_media_hash_t; ++ ++enum { ++ RC_CLIENT_GAME_PENDING_EVENT_NONE = 0, ++ RC_CLIENT_GAME_PENDING_EVENT_LEADERBOARD_TRACKER = (1 << 1), ++ RC_CLIENT_GAME_PENDING_EVENT_UPDATE_ACTIVE_ACHIEVEMENTS = (1 << 2), ++ RC_CLIENT_GAME_PENDING_EVENT_PROGRESS_TRACKER = (1 << 3) ++}; ++ ++typedef struct rc_client_game_info_t { ++ rc_client_game_t public_; ++ rc_client_leaderboard_tracker_info_t* leaderboard_trackers; ++ rc_client_progress_tracker_t progress_tracker; ++ ++ rc_client_subset_info_t* subsets; ++ ++ rc_client_media_hash_t* media_hash; ++ ++ rc_runtime_t runtime; ++ ++ uint32_t max_valid_address; ++ ++ uint8_t waiting_for_reset; ++ uint8_t pending_events; ++ ++ rc_buffer_t buffer; ++} rc_client_game_info_t; ++ ++void rc_client_update_active_achievements(rc_client_game_info_t* game); ++void rc_client_update_active_leaderboards(rc_client_game_info_t* game); ++ ++/*****************************************************************************\ ++| Client | ++\*****************************************************************************/ ++ ++enum { ++ RC_CLIENT_USER_STATE_NONE, ++ RC_CLIENT_USER_STATE_LOGIN_REQUESTED, ++ RC_CLIENT_USER_STATE_LOGGED_IN ++}; ++ ++enum { ++ RC_CLIENT_MASTERY_STATE_NONE, ++ RC_CLIENT_MASTERY_STATE_PENDING, ++ RC_CLIENT_MASTERY_STATE_SHOWN ++}; ++ ++enum { ++ RC_CLIENT_SPECTATOR_MODE_OFF, ++ RC_CLIENT_SPECTATOR_MODE_ON, ++ RC_CLIENT_SPECTATOR_MODE_LOCKED ++}; ++ ++enum { ++ RC_CLIENT_DISCONNECT_HIDDEN = 0, ++ RC_CLIENT_DISCONNECT_VISIBLE = (1 << 0), ++ RC_CLIENT_DISCONNECT_SHOW_PENDING = (1 << 1), ++ RC_CLIENT_DISCONNECT_HIDE_PENDING = (1 << 2) ++}; ++ ++struct rc_client_load_state_t; ++ ++typedef struct rc_client_state_t { ++ rc_mutex_t mutex; ++ rc_buffer_t buffer; ++ ++ rc_client_scheduled_callback_data_t* scheduled_callbacks; ++ rc_api_host_t host; ++ ++#ifdef RC_CLIENT_SUPPORTS_EXTERNAL ++ rc_client_external_t* external_client; ++ struct rc_client_external_conversions_t* external_client_conversions; ++#endif ++#ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION ++ rc_client_raintegration_t* raintegration; ++#endif ++ ++ uint32_t frames_processed; ++ uint32_t frames_at_last_ping; ++ uint16_t unpaused_frame_decay; ++ uint16_t required_unpaused_frames; ++ ++ uint8_t hardcore; ++ uint8_t encore_mode; ++ uint8_t spectator_mode; ++ uint8_t unofficial_enabled; ++ uint8_t log_level; ++ uint8_t user; ++ uint8_t disconnect; ++ uint8_t allow_leaderboards_in_softcore; ++ uint8_t allow_background_memory_reads; ++ ++ struct rc_client_load_state_t* load; ++ struct rc_client_async_handle_t* async_handles[4]; ++ rc_memref_t* processing_memref; ++ ++ rc_peek_t legacy_peek; ++} rc_client_state_t; ++ ++struct rc_client_t { ++ rc_client_game_info_t* game; ++ rc_client_game_hash_t* hashes; ++ ++ rc_client_user_t user; ++ ++ rc_client_callbacks_t callbacks; ++ ++ rc_client_state_t state; ++}; ++ ++/*****************************************************************************\ ++| Helpers | ++\*****************************************************************************/ ++ ++#ifdef RC_NO_VARIADIC_MACROS ++ void RC_CLIENT_LOG_ERR_FORMATTED(const rc_client_t* client, const char* format, ...); ++ void RC_CLIENT_LOG_WARN_FORMATTED(const rc_client_t* client, const char* format, ...); ++ void RC_CLIENT_LOG_INFO_FORMATTED(const rc_client_t* client, const char* format, ...); ++ void RC_CLIENT_LOG_VERBOSE_FORMATTED(const rc_client_t* client, const char* format, ...); ++#else ++ void rc_client_log_message_formatted(const rc_client_t* client, const char* format, ...); ++ #define RC_CLIENT_LOG_ERR_FORMATTED(client, format, ...) { if (client->state.log_level >= RC_CLIENT_LOG_LEVEL_ERROR) rc_client_log_message_formatted(client, format, __VA_ARGS__); } ++ #define RC_CLIENT_LOG_WARN_FORMATTED(client, format, ...) { if (client->state.log_level >= RC_CLIENT_LOG_LEVEL_WARN) rc_client_log_message_formatted(client, format, __VA_ARGS__); } ++ #define RC_CLIENT_LOG_INFO_FORMATTED(client, format, ...) { if (client->state.log_level >= RC_CLIENT_LOG_LEVEL_INFO) rc_client_log_message_formatted(client, format, __VA_ARGS__); } ++ #define RC_CLIENT_LOG_VERBOSE_FORMATTED(client, format, ...) { if (client->state.log_level >= RC_CLIENT_LOG_LEVEL_VERBOSE) rc_client_log_message_formatted(client, format, __VA_ARGS__); } ++#endif ++ ++void rc_client_log_message(const rc_client_t* client, const char* message); ++#define RC_CLIENT_LOG_ERR(client, message) { if (client->state.log_level >= RC_CLIENT_LOG_LEVEL_ERROR) rc_client_log_message(client, message); } ++#define RC_CLIENT_LOG_WARN(client, message) { if (client->state.log_level >= RC_CLIENT_LOG_LEVEL_WARN) rc_client_log_message(client, message); } ++#define RC_CLIENT_LOG_INFO(client, message) { if (client->state.log_level >= RC_CLIENT_LOG_LEVEL_INFO) rc_client_log_message(client, message); } ++#define RC_CLIENT_LOG_VERBOSE(client, message) { if (client->state.log_level >= RC_CLIENT_LOG_LEVEL_VERBOSE) rc_client_log_message(client, message); } ++ ++/* internals pulled from runtime.c */ ++void rc_runtime_checksum(const char* memaddr, uint8_t* md5); ++int rc_trigger_contains_memref(const rc_trigger_t* trigger, const rc_memref_t* memref); ++int rc_value_contains_memref(const rc_value_t* value, const rc_memref_t* memref); ++/* end runtime.c internals */ ++ ++/* helper functions for unit tests */ ++#ifdef RC_CLIENT_SUPPORTS_HASH ++struct rc_hash_iterator; ++struct rc_hash_iterator* rc_client_get_load_state_hash_iterator(rc_client_t* client); ++#endif ++/* end helper functions for unit tests */ ++ ++enum { ++ RC_CLIENT_LEGACY_PEEK_AUTO, ++ RC_CLIENT_LEGACY_PEEK_CONSTRUCTED, ++ RC_CLIENT_LEGACY_PEEK_LITTLE_ENDIAN_READS ++}; ++ ++void rc_client_set_legacy_peek(rc_client_t* client, int method); ++ ++void rc_client_allocate_leaderboard_tracker(rc_client_game_info_t* game, rc_client_leaderboard_info_t* leaderboard); ++void rc_client_release_leaderboard_tracker(rc_client_game_info_t* game, rc_client_leaderboard_info_t* leaderboard); ++ ++RC_END_C_DECLS ++ ++#endif /* RC_CLIENT_INTERNAL_H */ +diff -rupbN melonDS.orig/src/rcheevos/src/rc_compat.c melonDS.ra/src/rcheevos/src/rc_compat.c +--- melonDS.orig/src/rcheevos/src/rc_compat.c 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rc_compat.c 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,251 @@ ++#if !defined(RC_NO_THREADS) && !defined(_WIN32) && !defined(GEKKO) && !defined(_3DS) && (!defined(_XOPEN_SOURCE) || (_XOPEN_SOURCE - 0) < 500) ++/* We'll want to use pthread_mutexattr_settype/PTHREAD_MUTEX_RECURSIVE, but glibc only conditionally exposes pthread_mutexattr_settype and PTHREAD_MUTEX_RECURSIVE depending on feature flags ++ * Defining _XOPEN_SOURCE must be done at the top of the source file, before including any headers ++ * pthread_mutexattr_settype/PTHREAD_MUTEX_RECURSIVE are specified the Single UNIX Specification (Version 2, 1997), along with POSIX later on (IEEE Standard 1003.1-2008), so should cover practically any pthread implementation ++ */ ++#undef _XOPEN_SOURCE ++#define _XOPEN_SOURCE 500 ++#endif ++ ++#include "rc_compat.h" ++ ++#include ++#include ++#include ++ ++#ifdef RC_C89_HELPERS ++ ++int rc_strncasecmp(const char* left, const char* right, size_t length) ++{ ++ while (length) ++ { ++ if (*left != *right) ++ { ++ const int diff = tolower(*left) - tolower(*right); ++ if (diff != 0) ++ return diff; ++ } ++ ++ ++left; ++ ++right; ++ --length; ++ } ++ ++ return 0; ++} ++ ++int rc_strcasecmp(const char* left, const char* right) ++{ ++ while (*left || *right) ++ { ++ if (*left != *right) ++ { ++ const int diff = tolower(*left) - tolower(*right); ++ if (diff != 0) ++ return diff; ++ } ++ ++ ++left; ++ ++right; ++ } ++ ++ return 0; ++} ++ ++char* rc_strdup(const char* str) ++{ ++ const size_t length = strlen(str); ++ char* buffer = (char*)malloc(length + 1); ++ if (buffer) ++ memcpy(buffer, str, length + 1); ++ return buffer; ++} ++ ++int rc_snprintf(char* buffer, size_t size, const char* format, ...) ++{ ++ int result; ++ va_list args; ++ ++ va_start(args, format); ++ ++#ifdef __STDC_SECURE_LIB__ ++ result = vsprintf_s(buffer, size, format, args); ++#else ++ /* assume buffer is large enough and ignore size */ ++ (void)size; ++ result = vsprintf(buffer, format, args); ++#endif ++ ++ va_end(args); ++ ++ return result; ++} ++ ++#endif ++ ++#ifndef __STDC_SECURE_LIB__ ++ ++struct tm* rc_gmtime_s(struct tm* buf, const time_t* timer) ++{ ++ struct tm* tm = gmtime(timer); ++ memcpy(buf, tm, sizeof(*tm)); ++ return buf; ++} ++ ++#endif ++ ++#ifndef RC_NO_THREADS ++ ++#if defined(_WIN32) ++ ++/* https://learn.microsoft.com/en-us/archive/msdn-magazine/2012/november/windows-with-c-the-evolution-of-synchronization-in-windows-and-c */ ++/* implementation largely taken from https://github.com/libsdl-org/SDL/blob/0fc3574/src/thread/windows/SDL_sysmutex.c */ ++ ++#if defined(WINVER) && WINVER >= 0x0600 ++ ++void rc_mutex_init(rc_mutex_t* mutex) ++{ ++ InitializeSRWLock(&mutex->srw_lock); ++ /* https://learn.microsoft.com/en-us/windows/win32/procthread/thread-handles-and-identifiers */ ++ /* thread ids are never 0 */ ++ mutex->owner = 0; ++ mutex->count = 0; ++} ++ ++void rc_mutex_destroy(rc_mutex_t* mutex) ++{ ++ /* Nothing to do here */ ++ (void)mutex; ++} ++ ++void rc_mutex_lock(rc_mutex_t* mutex) ++{ ++ DWORD current_thread = GetCurrentThreadId(); ++ if (mutex->owner == current_thread) { ++ ++mutex->count; ++ assert(mutex->count > 0); ++ } ++ else { ++ AcquireSRWLockExclusive(&mutex->srw_lock); ++ assert(mutex->owner == 0 && mutex->count == 0); ++ mutex->owner = current_thread; ++ mutex->count = 1; ++ } ++} ++ ++void rc_mutex_unlock(rc_mutex_t* mutex) ++{ ++ if (mutex->owner == GetCurrentThreadId()) { ++ assert(mutex->count > 0); ++ if (--mutex->count == 0) { ++ mutex->owner = 0; ++ ReleaseSRWLockExclusive(&mutex->srw_lock); ++ } ++ } ++ else { ++ assert(!"Tried to unlock unowned mutex"); ++ } ++} ++ ++#else ++ ++void rc_mutex_init(rc_mutex_t* mutex) ++{ ++ InitializeCriticalSection(&mutex->critical_section); ++} ++ ++void rc_mutex_destroy(rc_mutex_t* mutex) ++{ ++ DeleteCriticalSection(&mutex->critical_section); ++} ++ ++void rc_mutex_lock(rc_mutex_t* mutex) ++{ ++ EnterCriticalSection(&mutex->critical_section); ++} ++ ++void rc_mutex_unlock(rc_mutex_t* mutex) ++{ ++ LeaveCriticalSection(&mutex->critical_section); ++} ++ ++#endif ++ ++#elif defined(GEKKO) ++ ++/* https://github.com/libretro/RetroArch/pull/16116 */ ++ ++void rc_mutex_init(rc_mutex_t* mutex) ++{ ++ /* LWP_MutexInit has the handle passed by reference */ ++ /* Other LWP_Mutex* calls have the handle passed by value */ ++ LWP_MutexInit(&mutex->handle, 1); ++} ++ ++void rc_mutex_destroy(rc_mutex_t* mutex) ++{ ++ LWP_MutexDestroy(mutex->handle); ++} ++ ++void rc_mutex_lock(rc_mutex_t* mutex) ++{ ++ LWP_MutexLock(mutex->handle); ++} ++ ++void rc_mutex_unlock(rc_mutex_t* mutex) ++{ ++ LWP_MutexUnlock(mutex->handle); ++} ++ ++#elif defined(_3DS) ++ ++void rc_mutex_init(rc_mutex_t* mutex) ++{ ++ RecursiveLock_Init(mutex); ++} ++ ++void rc_mutex_destroy(rc_mutex_t* mutex) ++{ ++ /* Nothing to do here */ ++ (void)mutex; ++} ++ ++void rc_mutex_lock(rc_mutex_t* mutex) ++{ ++ RecursiveLock_Lock(mutex); ++} ++ ++void rc_mutex_unlock(rc_mutex_t* mutex) ++{ ++ RecursiveLock_Unlock(mutex); ++} ++ ++#else ++ ++void rc_mutex_init(rc_mutex_t* mutex) ++{ ++ /* Define the mutex as recursive, for consistent semantics against other rc_mutex_t implementations */ ++ pthread_mutexattr_t attr; ++ pthread_mutexattr_init(&attr); ++ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); ++ pthread_mutex_init(mutex, &attr); ++ pthread_mutexattr_destroy(&attr); ++} ++ ++void rc_mutex_destroy(rc_mutex_t* mutex) ++{ ++ pthread_mutex_destroy(mutex); ++} ++ ++void rc_mutex_lock(rc_mutex_t* mutex) ++{ ++ pthread_mutex_lock(mutex); ++} ++ ++void rc_mutex_unlock(rc_mutex_t* mutex) ++{ ++ pthread_mutex_unlock(mutex); ++} ++ ++#endif ++#endif /* RC_NO_THREADS */ +diff -rupbN melonDS.orig/src/rcheevos/src/rc_compat.h melonDS.ra/src/rcheevos/src/rc_compat.h +--- melonDS.orig/src/rcheevos/src/rc_compat.h 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rc_compat.h 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,121 @@ ++#ifndef RC_COMPAT_H ++#define RC_COMPAT_H ++ ++#ifdef _WIN32 ++ #ifndef WIN32_LEAN_AND_MEAN ++ #define WIN32_LEAN_AND_MEAN ++ #endif ++ #include ++#endif ++ ++#include "rc_export.h" ++ ++#include ++#include ++#include ++ ++RC_BEGIN_C_DECLS ++ ++#if defined(MINGW) || defined(__MINGW32__) || defined(__MINGW64__) ++ ++/* MinGW redefinitions */ ++ ++#define RC_NO_VARIADIC_MACROS 1 ++ ++#elif defined(_MSC_VER) ++ ++/* Visual Studio redefinitions */ ++ ++#ifndef strcasecmp ++ #define strcasecmp _stricmp ++#endif ++#ifndef strncasecmp ++ #define strncasecmp _strnicmp ++#endif ++#ifndef strdup ++ #define strdup _strdup ++#endif ++ ++#elif __STDC_VERSION__ < 199901L ++ ++/* C89 redefinitions */ ++#define RC_C89_HELPERS 1 ++ ++#define RC_NO_VARIADIC_MACROS 1 ++ ++#ifndef snprintf ++ extern int rc_snprintf(char* buffer, size_t size, const char* format, ...); ++ #define snprintf rc_snprintf ++#endif ++ ++#ifndef strncasecmp ++ extern int rc_strncasecmp(const char* left, const char* right, size_t length); ++ #define strncasecmp rc_strncasecmp ++#endif ++ ++#ifndef strcasecmp ++ extern int rc_strcasecmp(const char* left, const char* right); ++ #define strcasecmp rc_strcasecmp ++#endif ++ ++#ifndef strdup ++ extern char* rc_strdup(const char* str); ++ #define strdup rc_strdup ++#endif ++ ++#endif /* __STDC_VERSION__ < 199901L */ ++ ++#ifndef __STDC_SECURE_LIB__ ++ /* _CRT_SECURE_NO_WARNINGS redefinitions */ ++ #define strcpy_s(dest, sz, src) strcpy(dest, src) ++ #define sscanf_s sscanf ++ ++ /* NOTE: Microsoft secure gmtime_s parameter order differs from C11 standard */ ++ #include ++ extern struct tm* rc_gmtime_s(struct tm* buf, const time_t* timer); ++ #define gmtime_s rc_gmtime_s ++#endif ++ ++#ifdef RC_NO_THREADS ++ typedef int rc_mutex_t; ++ ++ #define rc_mutex_init(mutex) ++ #define rc_mutex_destroy(mutex) ++ #define rc_mutex_lock(mutex) ++ #define rc_mutex_unlock(mutex) ++#else ++ #if defined(_WIN32) ++ typedef struct rc_mutex_t { ++ #if defined(WINVER) && WINVER >= 0x0600 ++ /* Windows Vista and later can use a slim reader/writer (SRW) lock */ ++ SRWLOCK srw_lock; ++ /* Current thread owner needs to be tracked (for recursive mutex usage) */ ++ DWORD owner; ++ DWORD count; ++ #else ++ /* Pre-Vista must use a critical section */ ++ CRITICAL_SECTION critical_section; ++ #endif ++ } rc_mutex_t; ++ #elif defined(GEKKO) ++ #include ++ typedef struct rc_mutex_t { ++ mutex_t handle; ++ } rc_mutex_t; ++ #elif defined(_3DS) ++ #include <3ds/synchronization.h> ++ typedef RecursiveLock rc_mutex_t; ++ #else ++ #include ++ typedef pthread_mutex_t rc_mutex_t; ++ #endif ++ ++ void rc_mutex_init(rc_mutex_t* mutex); ++ void rc_mutex_destroy(rc_mutex_t* mutex); ++ void rc_mutex_lock(rc_mutex_t* mutex); ++ void rc_mutex_unlock(rc_mutex_t* mutex); ++#endif ++ ++RC_END_C_DECLS ++ ++#endif /* RC_COMPAT_H */ +diff -rupbN melonDS.orig/src/rcheevos/src/rc_util.c melonDS.ra/src/rcheevos/src/rc_util.c +--- melonDS.orig/src/rcheevos/src/rc_util.c 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rc_util.c 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,199 @@ ++#include "rc_util.h" ++ ++#include "rc_compat.h" ++#include "rc_error.h" ++ ++#include ++#include ++ ++#undef DEBUG_BUFFERS ++ ++/* --- rc_buffer --- */ ++ ++void rc_buffer_init(rc_buffer_t* buffer) ++{ ++ buffer->chunk.write = buffer->chunk.start = &buffer->data[0]; ++ buffer->chunk.end = &buffer->data[sizeof(buffer->data)]; ++ buffer->chunk.next = NULL; ++ /* leave buffer->data uninitialized */ ++} ++ ++void rc_buffer_destroy(rc_buffer_t* buffer) ++{ ++ rc_buffer_chunk_t* chunk; ++#ifdef DEBUG_BUFFERS ++ int count = 0; ++ int wasted = 0; ++ int total = 0; ++#endif ++ ++ /* first chunk is not allocated. skip it. */ ++ chunk = buffer->chunk.next; ++ ++ /* deallocate any additional buffers */ ++ while (chunk) ++ { ++ rc_buffer_chunk_t* next = chunk->next; ++#ifdef DEBUG_BUFFERS ++ total += (int)(chunk->end - chunk->start); ++ wasted += (int)(chunk->end - chunk->write); ++ ++count; ++#endif ++#ifdef DEBUG_BUFFERS ++ printf("< free %p.%p\n", (void*)buffer, (void*)chunk); ++#endif ++ free(chunk); ++ chunk = next; ++ } ++ ++#ifdef DEBUG_BUFFERS ++ printf("-- %d allocated buffers (%d/%d used, %d wasted, %0.2f%% efficiency)\n", count, ++ total - wasted, total, wasted, (float)(100.0 - (wasted * 100.0) / total)); ++#endif ++} ++ ++uint8_t* rc_buffer_reserve(rc_buffer_t* buffer, size_t amount) ++{ ++ rc_buffer_chunk_t* chunk = &buffer->chunk; ++ size_t remaining; ++ while (chunk) ++ { ++ remaining = chunk->end - chunk->write; ++ if (remaining >= amount) ++ return chunk->write; ++ ++ if (!chunk->next) ++ { ++ /* allocate a chunk of memory that is a multiple of 256-bytes. the first 32 bytes will be associated ++ * to the chunk header, and the remaining will be used for data. ++ */ ++ const size_t chunk_header_size = sizeof(rc_buffer_chunk_t); ++ const size_t alloc_size = (chunk_header_size + amount + 0xFF) & ~0xFF; ++ chunk->next = (rc_buffer_chunk_t*)malloc(alloc_size); ++ if (!chunk->next) ++ break; ++ ++#ifdef DEBUG_BUFFERS ++ printf("> alloc %p.%p\n", (void*)buffer, (void*)chunk->next); ++#endif ++ ++ chunk->next->start = (uint8_t*)chunk->next + chunk_header_size; ++ chunk->next->write = chunk->next->start; ++ chunk->next->end = (uint8_t*)chunk->next + alloc_size; ++ chunk->next->next = NULL; ++ } ++ ++ chunk = chunk->next; ++ } ++ ++ return NULL; ++} ++ ++void rc_buffer_consume(rc_buffer_t* buffer, const uint8_t* start, uint8_t* end) ++{ ++ rc_buffer_chunk_t* chunk = &buffer->chunk; ++ do ++ { ++ if (chunk->write == start) ++ { ++ size_t offset = (end - chunk->start); ++ offset = (offset + 7) & ~7; ++ chunk->write = &chunk->start[offset]; ++ ++ if (chunk->write > chunk->end) ++ chunk->write = chunk->end; ++ break; ++ } ++ ++ chunk = chunk->next; ++ } while (chunk); ++} ++ ++void* rc_buffer_alloc(rc_buffer_t* buffer, size_t amount) ++{ ++ uint8_t* ptr = rc_buffer_reserve(buffer, amount); ++ rc_buffer_consume(buffer, ptr, ptr + amount); ++ return (void*)ptr; ++} ++ ++char* rc_buffer_strncpy(rc_buffer_t* buffer, const char* src, size_t len) ++{ ++ uint8_t* dst = rc_buffer_reserve(buffer, len + 1); ++ memcpy(dst, src, len); ++ dst[len] = '\0'; ++ rc_buffer_consume(buffer, dst, dst + len + 2); ++ return (char*)dst; ++} ++ ++char* rc_buffer_strcpy(rc_buffer_t* buffer, const char* src) ++{ ++ return rc_buffer_strncpy(buffer, src, strlen(src)); ++} ++ ++/* --- other --- */ ++ ++void rc_format_md5(char checksum[33], const uint8_t digest[16]) ++{ ++ snprintf(checksum, 33, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", ++ digest[0], digest[1], digest[2], digest[3], digest[4], digest[5], digest[6], digest[7], ++ digest[8], digest[9], digest[10], digest[11], digest[12], digest[13], digest[14], digest[15] ++ ); ++} ++ ++uint32_t rc_djb2(const char* input) ++{ ++ uint32_t result = 5381; ++ char c; ++ ++ while ((c = *input++) != '\0') ++ result = ((result << 5) + result) + c; /* result = result * 33 + c */ ++ ++ return result; ++} ++ ++const char* rc_error_str(int ret) ++{ ++ switch (ret) { ++ case RC_OK: return "OK"; ++ case RC_INVALID_FUNC_OPERAND: return "Invalid function operand"; ++ case RC_INVALID_MEMORY_OPERAND: return "Invalid memory operand"; ++ case RC_INVALID_CONST_OPERAND: return "Invalid constant operand"; ++ case RC_INVALID_FP_OPERAND: return "Invalid floating-point operand"; ++ case RC_INVALID_CONDITION_TYPE: return "Invalid condition type"; ++ case RC_INVALID_OPERATOR: return "Invalid operator"; ++ case RC_INVALID_REQUIRED_HITS: return "Invalid required hits"; ++ case RC_DUPLICATED_START: return "Duplicated start condition"; ++ case RC_DUPLICATED_CANCEL: return "Duplicated cancel condition"; ++ case RC_DUPLICATED_SUBMIT: return "Duplicated submit condition"; ++ case RC_DUPLICATED_VALUE: return "Duplicated value expression"; ++ case RC_DUPLICATED_PROGRESS: return "Duplicated progress expression"; ++ case RC_MISSING_START: return "Missing start condition"; ++ case RC_MISSING_CANCEL: return "Missing cancel condition"; ++ case RC_MISSING_SUBMIT: return "Missing submit condition"; ++ case RC_MISSING_VALUE: return "Missing value expression"; ++ case RC_INVALID_LBOARD_FIELD: return "Invalid field in leaderboard"; ++ case RC_MISSING_DISPLAY_STRING: return "Missing display string"; ++ case RC_OUT_OF_MEMORY: return "Out of memory"; ++ case RC_INVALID_VALUE_FLAG: return "Invalid flag in value expression"; ++ case RC_MISSING_VALUE_MEASURED: return "Missing measured flag in value expression"; ++ case RC_MULTIPLE_MEASURED: return "Multiple measured targets"; ++ case RC_INVALID_MEASURED_TARGET: return "Invalid measured target"; ++ case RC_INVALID_COMPARISON: return "Invalid comparison"; ++ case RC_INVALID_STATE: return "Invalid state"; ++ case RC_INVALID_JSON: return "Invalid JSON"; ++ case RC_API_FAILURE: return "API call failed"; ++ case RC_LOGIN_REQUIRED: return "Login required"; ++ case RC_NO_GAME_LOADED: return "No game loaded"; ++ case RC_HARDCORE_DISABLED: return "Hardcore disabled"; ++ case RC_ABORTED: return "Aborted"; ++ case RC_NO_RESPONSE: return "No response"; ++ case RC_ACCESS_DENIED: return "Access denied"; ++ case RC_INVALID_CREDENTIALS: return "Invalid credentials"; ++ case RC_EXPIRED_TOKEN: return "Expired token"; ++ case RC_INSUFFICIENT_BUFFER: return "Buffer not large enough"; ++ case RC_INVALID_VARIABLE_NAME: return "Invalid variable name"; ++ case RC_UNKNOWN_VARIABLE_NAME: return "Unknown variable name"; ++ case RC_NOT_FOUND: return "Not found"; ++ default: return "Unknown error"; ++ } ++} +diff -rupbN melonDS.orig/src/rcheevos/src/rc_version.c melonDS.ra/src/rcheevos/src/rc_version.c +--- melonDS.orig/src/rcheevos/src/rc_version.c 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rc_version.c 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,11 @@ ++#include "rc_version.h" ++ ++uint32_t rc_version(void) ++{ ++ return RCHEEVOS_VERSION; ++} ++ ++const char* rc_version_string(void) ++{ ++ return RCHEEVOS_VERSION_STRING; ++} +diff -rupbN melonDS.orig/src/rcheevos/src/rc_version.h melonDS.ra/src/rcheevos/src/rc_version.h +--- melonDS.orig/src/rcheevos/src/rc_version.h 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rc_version.h 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,32 @@ ++#ifndef RC_VERSION_H ++#define RC_VERSION_H ++ ++#include "rc_export.h" ++ ++#include ++ ++RC_BEGIN_C_DECLS ++ ++#define RCHEEVOS_VERSION_MAJOR 12 ++#define RCHEEVOS_VERSION_MINOR 1 ++#define RCHEEVOS_VERSION_PATCH 0 ++ ++#define RCHEEVOS_MAKE_VERSION(major, minor, patch) (major * 1000000 + minor * 1000 + patch) ++#define RCHEEVOS_VERSION RCHEEVOS_MAKE_VERSION(RCHEEVOS_VERSION_MAJOR, RCHEEVOS_VERSION_MINOR, RCHEEVOS_VERSION_PATCH) ++ ++#define RCHEEVOS_MAKE_STRING(num) #num ++#define RCHEEVOS_MAKE_VERSION_STRING(major, minor, patch) RCHEEVOS_MAKE_STRING(major) "." RCHEEVOS_MAKE_STRING(minor) "." RCHEEVOS_MAKE_STRING(patch) ++#define RCHEEVOS_MAKE_VERSION_STRING_SHORT(major, minor) RCHEEVOS_MAKE_STRING(major) "." RCHEEVOS_MAKE_STRING(minor) ++ ++#if RCHEEVOS_VERSION_PATCH > 0 ++ #define RCHEEVOS_VERSION_STRING RCHEEVOS_MAKE_VERSION_STRING(RCHEEVOS_VERSION_MAJOR, RCHEEVOS_VERSION_MINOR, RCHEEVOS_VERSION_PATCH) ++#else ++ #define RCHEEVOS_VERSION_STRING RCHEEVOS_MAKE_VERSION_STRING_SHORT(RCHEEVOS_VERSION_MAJOR, RCHEEVOS_VERSION_MINOR) ++#endif ++ ++RC_EXPORT uint32_t rc_version(void); ++RC_EXPORT const char* rc_version_string(void); ++ ++RC_END_C_DECLS ++ ++#endif /* RC_VERSION_H */ +diff -rupbN melonDS.orig/src/rcheevos/src/rcheevos/alloc.c melonDS.ra/src/rcheevos/src/rcheevos/alloc.c +--- melonDS.orig/src/rcheevos/src/rcheevos/alloc.c 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rcheevos/alloc.c 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,312 @@ ++#include "rc_internal.h" ++ ++#include ++#include ++ ++void* rc_alloc_scratch(void* pointer, int32_t* offset, uint32_t size, uint32_t alignment, rc_scratch_t* scratch, uint32_t scratch_object_pointer_offset) ++{ ++ void* data; ++ ++ /* if we have a real buffer, then allocate the data there */ ++ if (pointer) ++ return rc_alloc(pointer, offset, size, alignment, NULL, scratch_object_pointer_offset); ++ ++ /* update how much space will be required in the real buffer */ ++ { ++ const int32_t aligned_offset = (*offset + alignment - 1) & ~(alignment - 1); ++ *offset += (aligned_offset - *offset); ++ *offset += size; ++ } ++ ++ /* find a scratch buffer to hold the temporary data */ ++ data = rc_buffer_alloc(&scratch->buffer, size); ++ if (!data) { ++ *offset = RC_OUT_OF_MEMORY; ++ return NULL; ++ } ++ ++ return data; ++} ++ ++void* rc_alloc(void* pointer, int32_t* offset, uint32_t size, uint32_t alignment, rc_scratch_t* scratch, uint32_t scratch_object_pointer_offset) { ++ void* ptr; ++ ++ *offset = (*offset + alignment - 1) & ~(alignment - 1); ++ ++ if (pointer != 0) { ++ /* valid buffer, grab the next chunk */ ++ ptr = (void*)((uint8_t*)pointer + *offset); ++ } ++ else if (scratch != 0 && scratch_object_pointer_offset < sizeof(scratch->objs)) { ++ /* only allocate one instance of each object type (indentified by scratch_object_pointer_offset) */ ++ void** scratch_object_pointer = (void**)((uint8_t*)&scratch->objs + scratch_object_pointer_offset); ++ ptr = *scratch_object_pointer; ++ if (!ptr) { ++ int32_t used; ++ ptr = *scratch_object_pointer = rc_alloc_scratch(NULL, &used, size, alignment, scratch, -1); ++ } ++ } ++ else { ++ /* nowhere to get memory from, return NULL */ ++ ptr = NULL; ++ } ++ ++ *offset += size; ++ return ptr; ++} ++ ++char* rc_alloc_str(rc_parse_state_t* parse, const char* text, size_t length) { ++ int32_t used = 0; ++ char* ptr; ++ ++ rc_scratch_string_t** next = &parse->scratch.strings; ++ while (*next) { ++ int diff = strncmp(text, (*next)->value, length); ++ if (diff == 0) { ++ diff = (*next)->value[length]; ++ if (diff == 0) ++ return (*next)->value; ++ } ++ ++ if (diff < 0) ++ next = &(*next)->left; ++ else ++ next = &(*next)->right; ++ } ++ ++ *next = (rc_scratch_string_t*)rc_alloc_scratch(NULL, &used, sizeof(rc_scratch_string_t), RC_ALIGNOF(rc_scratch_string_t), &parse->scratch, RC_OFFSETOF(parse->scratch.objs, __rc_scratch_string_t)); ++ ptr = (char*)rc_alloc_scratch(parse->buffer, &parse->offset, (uint32_t)length + 1, RC_ALIGNOF(char), &parse->scratch, -1); ++ ++ if (!ptr || !*next) { ++ if (parse->offset >= 0) ++ parse->offset = RC_OUT_OF_MEMORY; ++ ++ return NULL; ++ } ++ ++ memcpy(ptr, text, length); ++ ptr[length] = '\0'; ++ ++ (*next)->left = NULL; ++ (*next)->right = NULL; ++ (*next)->value = ptr; ++ ++ return ptr; ++} ++ ++void rc_init_preparse_state(rc_preparse_state_t* preparse) ++{ ++ rc_init_parse_state(&preparse->parse, NULL); ++ rc_init_parse_state_memrefs(&preparse->parse, &preparse->memrefs); ++} ++ ++void rc_destroy_preparse_state(rc_preparse_state_t* preparse) ++{ ++ rc_destroy_parse_state(&preparse->parse); ++} ++ ++void rc_preparse_alloc_memrefs(rc_memrefs_t* memrefs, rc_preparse_state_t* preparse) ++{ ++ const uint32_t num_memrefs = rc_memrefs_count_memrefs(&preparse->memrefs); ++ const uint32_t num_modified_memrefs = rc_memrefs_count_modified_memrefs(&preparse->memrefs); ++ ++ if (preparse->parse.offset < 0) ++ return; ++ ++ if (memrefs) { ++ memset(memrefs, 0, sizeof(*memrefs)); ++ preparse->parse.memrefs = memrefs; ++ } ++ ++ if (num_memrefs) { ++ rc_memref_t* memref_items = RC_ALLOC_ARRAY(rc_memref_t, num_memrefs, &preparse->parse); ++ ++ if (memrefs) { ++ memrefs->memrefs.capacity = num_memrefs; ++ memrefs->memrefs.items = memref_items; ++ } ++ } ++ ++ if (num_modified_memrefs) { ++ rc_modified_memref_t* modified_memref_items = ++ RC_ALLOC_ARRAY(rc_modified_memref_t, num_modified_memrefs, &preparse->parse); ++ ++ if (memrefs) { ++ memrefs->modified_memrefs.capacity = num_modified_memrefs; ++ memrefs->modified_memrefs.items = modified_memref_items; ++ } ++ } ++ ++ /* when preparsing, this structure will be allocated at the end. when it's allocated earlier ++ * in the buffer, it could be followed by something aligned at 8 bytes. force the offset to ++ * an 8-byte boundary */ ++ if (!memrefs) { ++ rc_alloc(preparse->parse.buffer, &preparse->parse.offset, 0, 8, &preparse->parse.scratch, 0); ++ } ++} ++ ++static uint32_t rc_preparse_array_size(uint32_t needed, uint32_t minimum) ++{ ++ while (minimum < needed) ++ minimum <<= 1; ++ ++ return minimum; ++} ++ ++void rc_preparse_reserve_memrefs(rc_preparse_state_t* preparse, rc_memrefs_t* memrefs) ++{ ++ uint32_t num_memrefs = rc_memrefs_count_memrefs(&preparse->memrefs); ++ uint32_t num_modified_memrefs = rc_memrefs_count_modified_memrefs(&preparse->memrefs); ++ uint32_t available; ++ ++ if (preparse->parse.offset < 0) ++ return; ++ ++ if (num_memrefs) { ++ rc_memref_list_t* memref_list = &memrefs->memrefs; ++ while (memref_list->count == memref_list->capacity) { ++ if (!memref_list->next) ++ break; ++ ++ memref_list = memref_list->next; ++ } ++ ++ available = memref_list->capacity - memref_list->count; ++ if (available < num_memrefs) { ++ rc_memref_list_t* new_memref_list = (rc_memref_list_t*)calloc(1, sizeof(rc_memref_list_t)); ++ if (!new_memref_list) ++ return; ++ ++ new_memref_list->capacity = rc_preparse_array_size(num_memrefs - available, 16); ++ new_memref_list->items = (rc_memref_t*)malloc(new_memref_list->capacity * sizeof(rc_memref_t)); ++ new_memref_list->allocated = 1; ++ memref_list->next = new_memref_list; ++ } ++ } ++ ++ if (num_modified_memrefs) { ++ rc_modified_memref_list_t* modified_memref_list = &memrefs->modified_memrefs; ++ while (modified_memref_list->count == modified_memref_list->capacity) { ++ if (!modified_memref_list->next) ++ break; ++ ++ modified_memref_list = modified_memref_list->next; ++ } ++ ++ available = modified_memref_list->capacity - modified_memref_list->count; ++ if (available < num_modified_memrefs) { ++ rc_modified_memref_list_t* new_modified_memref_list = (rc_modified_memref_list_t*)calloc(1, sizeof(rc_modified_memref_list_t)); ++ if (!new_modified_memref_list) ++ return; ++ ++ new_modified_memref_list->capacity = rc_preparse_array_size(num_modified_memrefs - available, 8); ++ new_modified_memref_list->items = (rc_modified_memref_t*)malloc(new_modified_memref_list->capacity * sizeof(rc_modified_memref_t)); ++ new_modified_memref_list->allocated = 1; ++ modified_memref_list->next = new_modified_memref_list; ++ } ++ } ++ ++ preparse->parse.memrefs = memrefs; ++} ++ ++static void rc_preparse_sync_operand(rc_operand_t* operand, rc_parse_state_t* parse, const rc_memrefs_t* memrefs) ++{ ++ if (rc_operand_is_memref(operand) || rc_operand_is_recall(operand)) { ++ const rc_memref_t* src_memref = operand->value.memref; ++ ++ if (src_memref->value.memref_type == RC_MEMREF_TYPE_MODIFIED_MEMREF) { ++ const rc_modified_memref_list_t* modified_memref_list = &memrefs->modified_memrefs; ++ for (; modified_memref_list; modified_memref_list = modified_memref_list->next) { ++ const rc_modified_memref_t* modified_memref = modified_memref_list->items; ++ const rc_modified_memref_t* modified_memref_end = modified_memref + modified_memref_list->count; ++ ++ for (; modified_memref < modified_memref_end; ++modified_memref) { ++ if ((const rc_modified_memref_t*)src_memref == modified_memref) { ++ rc_modified_memref_t* dst_modified_memref = rc_alloc_modified_memref(parse, modified_memref->memref.value.size, ++ &modified_memref->parent, modified_memref->modifier_type, &modified_memref->modifier); ++ ++ operand->value.memref = &dst_modified_memref->memref; ++ return; ++ } ++ } ++ } ++ } ++ else { ++ const rc_memref_list_t* memref_list = &memrefs->memrefs; ++ for (; memref_list; memref_list = memref_list->next) { ++ const rc_memref_t* memref = memref_list->items; ++ const rc_memref_t* memref_end = memref + memref_list->count; ++ ++ for (; memref < memref_end; ++memref) { ++ if (src_memref == memref) { ++ operand->value.memref = rc_alloc_memref(parse, memref->address, memref->value.size); ++ return; ++ } ++ } ++ } ++ } ++ } ++} ++ ++void rc_preparse_copy_memrefs(rc_parse_state_t* parse, rc_memrefs_t* memrefs) ++{ ++ const rc_memref_list_t* memref_list = &memrefs->memrefs; ++ const rc_modified_memref_list_t* modified_memref_list = &memrefs->modified_memrefs; ++ ++ for (; memref_list; memref_list = memref_list->next) { ++ const rc_memref_t* memref = memref_list->items; ++ const rc_memref_t* memref_end = memref + memref_list->count; ++ ++ for (; memref < memref_end; ++memref) ++ rc_alloc_memref(parse, memref->address, memref->value.size); ++ } ++ ++ for (; modified_memref_list; modified_memref_list = modified_memref_list->next) { ++ rc_modified_memref_t* modified_memref = modified_memref_list->items; ++ const rc_modified_memref_t* modified_memref_end = modified_memref + modified_memref_list->count; ++ ++ for (; modified_memref < modified_memref_end; ++modified_memref) { ++ rc_preparse_sync_operand(&modified_memref->parent, parse, memrefs); ++ rc_preparse_sync_operand(&modified_memref->modifier, parse, memrefs); ++ ++ rc_alloc_modified_memref(parse, modified_memref->memref.value.size, ++ &modified_memref->parent, modified_memref->modifier_type, &modified_memref->modifier); ++ } ++ } ++} ++ ++void rc_reset_parse_state(rc_parse_state_t* parse, void* buffer) ++{ ++ parse->buffer = buffer; ++ ++ parse->offset = 0; ++ parse->memrefs = NULL; ++ parse->existing_memrefs = NULL; ++ parse->variables = NULL; ++ parse->measured_target = 0; ++ parse->lines_read = 0; ++ parse->addsource_oper = RC_OPERATOR_NONE; ++ parse->addsource_parent.type = RC_OPERAND_NONE; ++ parse->indirect_parent.type = RC_OPERAND_NONE; ++ parse->remember.type = RC_OPERAND_NONE; ++ parse->is_value = 0; ++ parse->has_required_hits = 0; ++ parse->measured_as_percent = 0; ++ parse->ignore_non_parse_errors = 0; ++ ++ parse->scratch.strings = NULL; ++} ++ ++void rc_init_parse_state(rc_parse_state_t* parse, void* buffer) ++{ ++ /* could use memset here, but rc_parse_state_t contains a 512 byte buffer that doesn't need to be initialized */ ++ rc_buffer_init(&parse->scratch.buffer); ++ memset(&parse->scratch.objs, 0, sizeof(parse->scratch.objs)); ++ ++ rc_reset_parse_state(parse, buffer); ++} ++ ++void rc_destroy_parse_state(rc_parse_state_t* parse) ++{ ++ rc_buffer_destroy(&parse->scratch.buffer); ++} +diff -rupbN melonDS.orig/src/rcheevos/src/rcheevos/condition.c melonDS.ra/src/rcheevos/src/rcheevos/condition.c +--- melonDS.orig/src/rcheevos/src/rcheevos/condition.c 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rcheevos/condition.c 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,754 @@ ++#include "rc_internal.h" ++ ++#include ++#include ++#include ++ ++static int rc_test_condition_compare(uint32_t value1, uint32_t value2, uint8_t oper) { ++ switch (oper) { ++ case RC_OPERATOR_EQ: return value1 == value2; ++ case RC_OPERATOR_NE: return value1 != value2; ++ case RC_OPERATOR_LT: return value1 < value2; ++ case RC_OPERATOR_LE: return value1 <= value2; ++ case RC_OPERATOR_GT: return value1 > value2; ++ case RC_OPERATOR_GE: return value1 >= value2; ++ default: return 1; ++ } ++} ++ ++static uint8_t rc_condition_determine_comparator(const rc_condition_t* self) { ++ switch (self->oper) { ++ case RC_OPERATOR_EQ: ++ case RC_OPERATOR_NE: ++ case RC_OPERATOR_LT: ++ case RC_OPERATOR_LE: ++ case RC_OPERATOR_GT: ++ case RC_OPERATOR_GE: ++ break; ++ ++ default: ++ /* not a comparison. should not be getting compared. but if it is, legacy behavior was to return 1 */ ++ return RC_PROCESSING_COMPARE_ALWAYS_TRUE; ++ } ++ ++ if ((self->operand1.type == RC_OPERAND_ADDRESS || self->operand1.type == RC_OPERAND_DELTA) && ++ /* TODO: allow modified memref comparisons */ ++ self->operand1.value.memref->value.memref_type == RC_MEMREF_TYPE_MEMREF && !rc_operand_is_float(&self->operand1)) { ++ /* left side is an integer memory reference */ ++ int needs_translate = (self->operand1.size != self->operand1.value.memref->value.size); ++ ++ if (self->operand2.type == RC_OPERAND_CONST) { ++ /* right side is a constant */ ++ if (self->operand1.type == RC_OPERAND_ADDRESS) ++ return needs_translate ? RC_PROCESSING_COMPARE_MEMREF_TO_CONST_TRANSFORMED : RC_PROCESSING_COMPARE_MEMREF_TO_CONST; ++ ++ return needs_translate ? RC_PROCESSING_COMPARE_DELTA_TO_CONST_TRANSFORMED : RC_PROCESSING_COMPARE_DELTA_TO_CONST; ++ } ++ else if ((self->operand2.type == RC_OPERAND_ADDRESS || self->operand2.type == RC_OPERAND_DELTA) && ++ self->operand2.value.memref->value.memref_type == RC_MEMREF_TYPE_MEMREF && !rc_operand_is_float(&self->operand2)) { ++ /* right side is an integer memory reference */ ++ const int is_same_memref = (self->operand1.value.memref == self->operand2.value.memref); ++ needs_translate |= (self->operand2.size != self->operand2.value.memref->value.size); ++ ++ if (self->operand1.type == RC_OPERAND_ADDRESS) { ++ if (self->operand2.type == RC_OPERAND_ADDRESS) { ++ if (is_same_memref && !needs_translate) { ++ /* comparing a memref to itself, will evaluate to a constant */ ++ return rc_test_condition_compare(0, 0, self->oper) ? RC_PROCESSING_COMPARE_ALWAYS_TRUE : RC_PROCESSING_COMPARE_ALWAYS_FALSE; ++ } ++ ++ return needs_translate ? RC_PROCESSING_COMPARE_MEMREF_TO_MEMREF_TRANSFORMED : RC_PROCESSING_COMPARE_MEMREF_TO_MEMREF; ++ } ++ ++ assert(self->operand2.type == RC_OPERAND_DELTA); ++ ++ if (is_same_memref) { ++ /* delta comparison is optimized to compare with itself (for detecting change) */ ++ return needs_translate ? RC_PROCESSING_COMPARE_MEMREF_TO_DELTA_TRANSFORMED : RC_PROCESSING_COMPARE_MEMREF_TO_DELTA; ++ } ++ } ++ else { ++ assert(self->operand1.type == RC_OPERAND_DELTA); ++ ++ if (self->operand2.type == RC_OPERAND_ADDRESS) { ++ if (is_same_memref) { ++ /* delta comparison is optimized to compare with itself (for detecting change) */ ++ return needs_translate ? RC_PROCESSING_COMPARE_DELTA_TO_MEMREF_TRANSFORMED : RC_PROCESSING_COMPARE_DELTA_TO_MEMREF; ++ } ++ } ++ } ++ } ++ } ++ ++ if (self->operand1.type == RC_OPERAND_CONST && self->operand2.type == RC_OPERAND_CONST) { ++ /* comparing constants will always generate a constant result */ ++ return rc_test_condition_compare(self->operand1.value.num, self->operand2.value.num, self->oper) ? ++ RC_PROCESSING_COMPARE_ALWAYS_TRUE : RC_PROCESSING_COMPARE_ALWAYS_FALSE; ++ } ++ ++ return RC_PROCESSING_COMPARE_DEFAULT; ++} ++ ++static int rc_parse_operator(const char** memaddr) { ++ const char* oper = *memaddr; ++ ++ switch (*oper) { ++ case '=': ++ ++(*memaddr); ++ (*memaddr) += (**memaddr == '='); ++ return RC_OPERATOR_EQ; ++ ++ case '!': ++ if (oper[1] == '=') { ++ (*memaddr) += 2; ++ return RC_OPERATOR_NE; ++ } ++ /* fall through */ ++ default: ++ return RC_INVALID_OPERATOR; ++ ++ case '<': ++ if (oper[1] == '=') { ++ (*memaddr) += 2; ++ return RC_OPERATOR_LE; ++ } ++ ++ ++(*memaddr); ++ return RC_OPERATOR_LT; ++ ++ case '>': ++ if (oper[1] == '=') { ++ (*memaddr) += 2; ++ return RC_OPERATOR_GE; ++ } ++ ++ ++(*memaddr); ++ return RC_OPERATOR_GT; ++ ++ case '*': ++ ++(*memaddr); ++ return RC_OPERATOR_MULT; ++ ++ case '/': ++ ++(*memaddr); ++ return RC_OPERATOR_DIV; ++ ++ case '&': ++ ++(*memaddr); ++ return RC_OPERATOR_AND; ++ ++ case '^': ++ ++(*memaddr); ++ return RC_OPERATOR_XOR; ++ ++ case '%': ++ ++(*memaddr); ++ return RC_OPERATOR_MOD; ++ ++ case '+': ++ ++(*memaddr); ++ return RC_OPERATOR_ADD; ++ ++ case '-': ++ ++(*memaddr); ++ return RC_OPERATOR_SUB; ++ ++ case '\0':/* end of string */ ++ case '_': /* next condition */ ++ case 'S': /* next condset */ ++ case ')': /* end of macro */ ++ case '$': /* maximum of values */ ++ /* valid condition separator, condition may not have an operator */ ++ return RC_OPERATOR_NONE; ++ } ++} ++ ++void rc_condition_convert_to_operand(const rc_condition_t* condition, rc_operand_t* operand, rc_parse_state_t* parse) { ++ if (condition->oper == RC_OPERATOR_NONE) { ++ if (operand != &condition->operand1) ++ memcpy(operand, &condition->operand1, sizeof(*operand)); ++ } ++ else { ++ uint8_t new_size = RC_MEMSIZE_32_BITS; ++ if (rc_operand_is_float(&condition->operand1) || rc_operand_is_float(&condition->operand2)) ++ new_size = RC_MEMSIZE_FLOAT; ++ ++ /* NOTE: this makes the operand include the modification, but we have to also ++ * leave the modification in the condition so the condition reflects the actual ++ * definition. This doesn't affect the evaluation logic since this method is only ++ * called for combining conditions and Measured, and the Measured handling function ++ * ignores the operator assuming it's been handled by a modified memref chain */ ++ operand->value.memref = (rc_memref_t*)rc_alloc_modified_memref(parse, ++ new_size, &condition->operand1, condition->oper, &condition->operand2); ++ ++ /* not actually an address, just a non-delta memref read */ ++ operand->type = operand->memref_access_type = RC_OPERAND_ADDRESS; ++ ++ operand->size = new_size; ++ } ++} ++ ++rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse) { ++ rc_condition_t * self = RC_ALLOC(rc_condition_t, parse); ++ rc_parse_condition_internal(self, memaddr, parse); ++ return (parse->offset < 0) ? NULL : self; ++} ++ ++void rc_parse_condition_internal(rc_condition_t* self, const char** memaddr, rc_parse_state_t* parse) { ++ const char* aux; ++ int result; ++ int can_modify = 0; ++ ++ aux = *memaddr; ++ self->current_hits = 0; ++ self->is_true = 0; ++ self->optimized_comparator = RC_PROCESSING_COMPARE_DEFAULT; ++ ++ if (*aux != 0 && aux[1] == ':') { ++ switch (*aux) { ++ case 'p': case 'P': self->type = RC_CONDITION_PAUSE_IF; break; ++ case 'r': case 'R': self->type = RC_CONDITION_RESET_IF; break; ++ case 'a': case 'A': self->type = RC_CONDITION_ADD_SOURCE; can_modify = 1; break; ++ case 'b': case 'B': self->type = RC_CONDITION_SUB_SOURCE; can_modify = 1; break; ++ case 'c': case 'C': self->type = RC_CONDITION_ADD_HITS; break; ++ case 'd': case 'D': self->type = RC_CONDITION_SUB_HITS; break; ++ case 'n': case 'N': self->type = RC_CONDITION_AND_NEXT; break; ++ case 'o': case 'O': self->type = RC_CONDITION_OR_NEXT; break; ++ case 'm': case 'M': self->type = RC_CONDITION_MEASURED; break; ++ case 'q': case 'Q': self->type = RC_CONDITION_MEASURED_IF; break; ++ case 'i': case 'I': self->type = RC_CONDITION_ADD_ADDRESS; can_modify = 1; break; ++ case 't': case 'T': self->type = RC_CONDITION_TRIGGER; break; ++ case 'k': case 'K': self->type = RC_CONDITION_REMEMBER; can_modify = 1; break; ++ case 'z': case 'Z': self->type = RC_CONDITION_RESET_NEXT_IF; break; ++ case 'g': case 'G': ++ parse->measured_as_percent = 1; ++ self->type = RC_CONDITION_MEASURED; ++ break; ++ ++ /* e f h j l s u v w x y */ ++ default: ++ parse->offset = RC_INVALID_CONDITION_TYPE; ++ return; ++ } ++ ++ aux += 2; ++ } ++ else { ++ self->type = RC_CONDITION_STANDARD; ++ } ++ ++ result = rc_parse_operand(&self->operand1, &aux, parse); ++ if (result < 0) { ++ parse->offset = result; ++ return; ++ } ++ ++ result = rc_parse_operator(&aux); ++ if (result < 0) { ++ parse->offset = result; ++ return; ++ } ++ ++ self->oper = (uint8_t)result; ++ ++ if (self->oper == RC_OPERATOR_NONE) { ++ /* non-modifying statements must have a second operand */ ++ if (!can_modify) { ++ /* measured does not require a second operand when used in a value */ ++ if (self->type != RC_CONDITION_MEASURED && !parse->ignore_non_parse_errors) { ++ parse->offset = RC_INVALID_OPERATOR; ++ return; ++ } ++ } ++ ++ /* provide dummy operand of '1' and no required hits */ ++ rc_operand_set_const(&self->operand2, 1); ++ self->required_hits = 0; ++ *memaddr = aux; ++ return; ++ } ++ ++ if (can_modify && !rc_operator_is_modifying(self->oper)) { ++ /* comparison operators are not valid on modifying statements */ ++ switch (self->type) { ++ case RC_CONDITION_ADD_SOURCE: ++ case RC_CONDITION_SUB_SOURCE: ++ case RC_CONDITION_ADD_ADDRESS: ++ /* prevent parse errors on legacy achievements where a condition was present before changing the type */ ++ self->oper = RC_OPERATOR_NONE; ++ break; ++ ++ default: ++ if (!parse->ignore_non_parse_errors) { ++ parse->offset = RC_INVALID_OPERATOR; ++ return; ++ } ++ break; ++ } ++ } ++ ++ result = rc_parse_operand(&self->operand2, &aux, parse); ++ if (result < 0) { ++ parse->offset = result; ++ return; ++ } ++ ++ if (self->oper == RC_OPERATOR_NONE) { ++ /* if operator is none, explicitly clear out the right side */ ++ rc_operand_set_const(&self->operand2, 0); ++ } ++ ++ if (*aux == '(') { ++ char* end; ++ self->required_hits = (unsigned)strtoul(++aux, &end, 10); ++ ++ if (end == aux || *end != ')') { ++ parse->offset = RC_INVALID_REQUIRED_HITS; ++ return; ++ } ++ ++ /* if operator is none, explicitly clear out the required hits */ ++ if (self->oper == RC_OPERATOR_NONE) ++ self->required_hits = 0; ++ else ++ parse->has_required_hits = 1; ++ ++ aux = end + 1; ++ } ++ else if (*aux == '.') { ++ char* end; ++ self->required_hits = (unsigned)strtoul(++aux, &end, 10); ++ ++ if (end == aux || *end != '.') { ++ parse->offset = RC_INVALID_REQUIRED_HITS; ++ return; ++ } ++ ++ /* if operator is none, explicitly clear out the required hits */ ++ if (self->oper == RC_OPERATOR_NONE) ++ self->required_hits = 0; ++ else ++ parse->has_required_hits = 1; ++ ++ aux = end + 1; ++ } ++ else { ++ self->required_hits = 0; ++ } ++ ++ if (parse->buffer != 0) ++ self->optimized_comparator = rc_condition_determine_comparator(self); ++ ++ *memaddr = aux; ++} ++ ++void rc_condition_update_parse_state(rc_condition_t* condition, rc_parse_state_t* parse) { ++ /* type of values in the chain are determined by the parent. ++ * the last element of a chain is determined by the operand ++ * ++ * 1 + 1.5 + 1.75 + 1.0 => (int)1 + (int)1 + (int)1 + (float)1 = (float)4.0 ++ * 1.0 + 1.5 + 1.75 + 1.0 => (float)1.0 + (float)1.5 + (float)1.75 + (float)1.0 = (float)5.25 ++ * 1.0 + 1.5 + 1.75 + 1 => (float)1.0 + (float)1.5 + (float)1.75 + (int)1 = (int)5 ++ */ ++ ++ switch (condition->type) { ++ case RC_CONDITION_ADD_ADDRESS: ++ if (condition->oper != RC_OPERAND_NONE) ++ rc_condition_convert_to_operand(condition, &parse->indirect_parent, parse); ++ else ++ memcpy(&parse->indirect_parent, &condition->operand1, sizeof(parse->indirect_parent)); ++ ++ break; ++ ++ case RC_CONDITION_ADD_SOURCE: ++ if (parse->addsource_parent.type == RC_OPERAND_NONE) { ++ rc_condition_convert_to_operand(condition, &parse->addsource_parent, parse); ++ } ++ else { ++ rc_operand_t cond_operand; ++ /* type determined by parent */ ++ const uint8_t new_size = rc_operand_is_float(&parse->addsource_parent) ? RC_MEMSIZE_FLOAT : RC_MEMSIZE_32_BITS; ++ ++ rc_condition_convert_to_operand(condition, &cond_operand, parse); ++ rc_operand_addsource(&cond_operand, parse, new_size); ++ memcpy(&parse->addsource_parent, &cond_operand, sizeof(cond_operand)); ++ } ++ ++ parse->addsource_oper = RC_OPERATOR_ADD_ACCUMULATOR; ++ parse->indirect_parent.type = RC_OPERAND_NONE; ++ break; ++ ++ case RC_CONDITION_SUB_SOURCE: ++ if (parse->addsource_parent.type == RC_OPERAND_NONE) { ++ rc_condition_convert_to_operand(condition, &parse->addsource_parent, parse); ++ parse->addsource_oper = RC_OPERATOR_SUB_PARENT; ++ } ++ else { ++ rc_operand_t cond_operand; ++ /* type determined by parent */ ++ const uint8_t new_size = rc_operand_is_float(&parse->addsource_parent) ? RC_MEMSIZE_FLOAT : RC_MEMSIZE_32_BITS; ++ ++ if (parse->addsource_oper == RC_OPERATOR_ADD_ACCUMULATOR && !rc_operand_is_memref(&parse->addsource_parent)) { ++ /* if the previous element was a constant we have to turn it into a memref by adding zero */ ++ rc_modified_memref_t* memref; ++ rc_operand_t zero; ++ rc_operand_set_const(&zero, 0); ++ memref = rc_alloc_modified_memref(parse, ++ parse->addsource_parent.size, &parse->addsource_parent, RC_OPERATOR_ADD_ACCUMULATOR, &zero); ++ parse->addsource_parent.value.memref = (rc_memref_t*)memref; ++ parse->addsource_parent.type = RC_OPERAND_ADDRESS; ++ } ++ else if (parse->addsource_oper == RC_OPERATOR_SUB_PARENT) { ++ /* if the previous element was also a SubSource, we have to insert a 0 and start subtracting from there */ ++ rc_modified_memref_t* negate; ++ rc_operand_t zero; ++ ++ if (rc_operand_is_float(&parse->addsource_parent)) ++ rc_operand_set_float_const(&zero, 0.0); ++ else ++ rc_operand_set_const(&zero, 0); ++ ++ negate = rc_alloc_modified_memref(parse, new_size, &parse->addsource_parent, RC_OPERATOR_SUB_PARENT, &zero); ++ parse->addsource_parent.value.memref = (rc_memref_t*)negate; ++ parse->addsource_parent.size = zero.size; ++ } ++ ++ /* subtract the condition from the chain */ ++ parse->addsource_oper = rc_operand_is_memref(&parse->addsource_parent) ? RC_OPERATOR_SUB_ACCUMULATOR : RC_OPERATOR_SUB_PARENT; ++ rc_condition_convert_to_operand(condition, &cond_operand, parse); ++ rc_operand_addsource(&cond_operand, parse, new_size); ++ memcpy(&parse->addsource_parent, &cond_operand, sizeof(cond_operand)); ++ ++ /* indicate the next value can be added to the chain */ ++ parse->addsource_oper = RC_OPERATOR_ADD_ACCUMULATOR; ++ } ++ ++ parse->indirect_parent.type = RC_OPERAND_NONE; ++ break; ++ ++ case RC_CONDITION_REMEMBER: ++ if (condition->operand1.type == RC_OPERAND_RECALL && ++ condition->oper == RC_OPERATOR_NONE && ++ parse->addsource_parent.type == RC_OPERAND_NONE && ++ parse->indirect_parent.type == RC_OPERAND_NONE) { ++ /* Remembering {recall} without any modifications is a no-op */ ++ break; ++ } ++ ++ rc_condition_convert_to_operand(condition, &condition->operand1, parse); ++ ++ if (parse->addsource_parent.type != RC_OPERAND_NONE) { ++ /* type determined by leaf */ ++ rc_operand_addsource(&condition->operand1, parse, condition->operand1.size); ++ condition->operand1.is_combining = 1; ++ } ++ ++ memcpy(&parse->remember, &condition->operand1, sizeof(parse->remember)); ++ ++ parse->addsource_parent.type = RC_OPERAND_NONE; ++ parse->indirect_parent.type = RC_OPERAND_NONE; ++ break; ++ ++ case RC_CONDITION_MEASURED: ++ /* Measured condition can have modifiers in values */ ++ if (parse->is_value) { ++ switch (condition->oper) { ++ case RC_OPERATOR_AND: ++ case RC_OPERATOR_XOR: ++ case RC_OPERATOR_DIV: ++ case RC_OPERATOR_MULT: ++ case RC_OPERATOR_MOD: ++ case RC_OPERATOR_ADD: ++ case RC_OPERATOR_SUB: ++ rc_condition_convert_to_operand(condition, &condition->operand1, parse); ++ break; ++ ++ default: ++ break; ++ } ++ } ++ ++ /* fallthrough */ /* to default */ ++ ++ default: ++ if (parse->addsource_parent.type != RC_OPERAND_NONE) { ++ /* type determined by leaf */ ++ if (parse->addsource_oper == RC_OPERATOR_ADD_ACCUMULATOR) ++ parse->addsource_oper = RC_OPERATOR_ADD; ++ ++ rc_operand_addsource(&condition->operand1, parse, condition->operand1.size); ++ condition->operand1.is_combining = 1; ++ ++ if (parse->buffer) ++ condition->optimized_comparator = rc_condition_determine_comparator(condition); ++ } ++ ++ parse->addsource_parent.type = RC_OPERAND_NONE; ++ parse->indirect_parent.type = RC_OPERAND_NONE; ++ break; ++ } ++} ++ ++static const rc_modified_memref_t* rc_operand_get_modified_memref(const rc_operand_t* operand) { ++ if (!rc_operand_is_memref(operand)) ++ return NULL; ++ ++ if (operand->value.memref->value.memref_type != RC_MEMREF_TYPE_MODIFIED_MEMREF) ++ return NULL; ++ ++ return (rc_modified_memref_t*)operand->value.memref; ++} ++ ++/* rc_condition_update_parse_state will mutate the operand1 to point at the modified memref ++ * containing the accumulated result up until that point. this function returns the original ++ * unmodified operand1 from parsing the definition. ++ */ ++const rc_operand_t* rc_condition_get_real_operand1(const rc_condition_t* self) { ++ const rc_operand_t* operand = &self->operand1; ++ const rc_modified_memref_t* modified_memref; ++ ++ if (operand->is_combining) { ++ /* operand = "previous + current" - extract current */ ++ const rc_modified_memref_t* combining_modified_memref = rc_operand_get_modified_memref(operand); ++ if (combining_modified_memref) ++ operand = &combining_modified_memref->modifier; ++ } ++ ++ /* modifying operators are merged into an rc_modified_memref_t ++ * if operand1 is a modified memref, assume it's been merged with the right side and ++ * extract the parent which is the actual operand1. */ ++ modified_memref = rc_operand_get_modified_memref(operand); ++ if (modified_memref) { ++ if (modified_memref->modifier_type == RC_OPERATOR_INDIRECT_READ) { ++ /* if the modified memref is an indirect read, the parent is the indirect ++ * address and the modifier is the offset. the actual size and address are ++ * stored in the modified memref - use it */ ++ } else if (rc_operator_is_modifying(self->oper) && self->oper != RC_OPERATOR_NONE) { ++ /* operand = "parent*modifier" - extract parent.modifier will already be in operand2 */ ++ operand = &modified_memref->parent; ++ } ++ } ++ ++ return operand; ++} ++ ++int rc_condition_is_combining(const rc_condition_t* self) { ++ switch (self->type) { ++ case RC_CONDITION_STANDARD: ++ case RC_CONDITION_PAUSE_IF: ++ case RC_CONDITION_RESET_IF: ++ case RC_CONDITION_MEASURED_IF: ++ case RC_CONDITION_TRIGGER: ++ case RC_CONDITION_MEASURED: ++ return 0; ++ ++ default: ++ return 1; ++ } ++} ++ ++static int rc_test_condition_compare_memref_to_const(rc_condition_t* self) { ++ const uint32_t value1 = self->operand1.value.memref->value.value; ++ const uint32_t value2 = self->operand2.value.num; ++ assert(self->operand1.size == self->operand1.value.memref->value.size); ++ return rc_test_condition_compare(value1, value2, self->oper); ++} ++ ++static int rc_test_condition_compare_delta_to_const(rc_condition_t* self) { ++ const rc_memref_value_t* memref1 = &self->operand1.value.memref->value; ++ const uint32_t value1 = (memref1->changed) ? memref1->prior : memref1->value; ++ const uint32_t value2 = self->operand2.value.num; ++ assert(self->operand1.size == self->operand1.value.memref->value.size); ++ return rc_test_condition_compare(value1, value2, self->oper); ++} ++ ++static int rc_test_condition_compare_memref_to_memref(rc_condition_t* self) { ++ const uint32_t value1 = self->operand1.value.memref->value.value; ++ const uint32_t value2 = self->operand2.value.memref->value.value; ++ assert(self->operand1.size == self->operand1.value.memref->value.size); ++ assert(self->operand2.size == self->operand2.value.memref->value.size); ++ return rc_test_condition_compare(value1, value2, self->oper); ++} ++ ++static int rc_test_condition_compare_memref_to_delta(rc_condition_t* self) { ++ const rc_memref_value_t* memref = &self->operand1.value.memref->value; ++ assert(self->operand1.value.memref == self->operand2.value.memref); ++ assert(self->operand1.size == self->operand1.value.memref->value.size); ++ assert(self->operand2.size == self->operand2.value.memref->value.size); ++ ++ if (memref->changed) ++ return rc_test_condition_compare(memref->value, memref->prior, self->oper); ++ ++ switch (self->oper) { ++ case RC_OPERATOR_EQ: ++ case RC_OPERATOR_GE: ++ case RC_OPERATOR_LE: ++ return 1; ++ ++ default: ++ return 0; ++ } ++} ++ ++static int rc_test_condition_compare_delta_to_memref(rc_condition_t* self) { ++ const rc_memref_value_t* memref = &self->operand1.value.memref->value; ++ assert(self->operand1.value.memref == self->operand2.value.memref); ++ assert(self->operand1.size == self->operand1.value.memref->value.size); ++ assert(self->operand2.size == self->operand2.value.memref->value.size); ++ ++ if (memref->changed) ++ return rc_test_condition_compare(memref->prior, memref->value, self->oper); ++ ++ switch (self->oper) { ++ case RC_OPERATOR_EQ: ++ case RC_OPERATOR_GE: ++ case RC_OPERATOR_LE: ++ return 1; ++ ++ default: ++ return 0; ++ } ++} ++ ++static int rc_test_condition_compare_memref_to_const_transformed(rc_condition_t* self) { ++ rc_typed_value_t value1; ++ const uint32_t value2 = self->operand2.value.num; ++ ++ value1.type = RC_VALUE_TYPE_UNSIGNED; ++ value1.value.u32 = self->operand1.value.memref->value.value; ++ rc_transform_memref_value(&value1, self->operand1.size); ++ ++ return rc_test_condition_compare(value1.value.u32, value2, self->oper); ++} ++ ++static int rc_test_condition_compare_delta_to_const_transformed(rc_condition_t* self) { ++ rc_typed_value_t value1; ++ const rc_memref_value_t* memref1 = &self->operand1.value.memref->value; ++ const uint32_t value2 = self->operand2.value.num; ++ ++ value1.type = RC_VALUE_TYPE_UNSIGNED; ++ value1.value.u32 = (memref1->changed) ? memref1->prior : memref1->value; ++ rc_transform_memref_value(&value1, self->operand1.size); ++ ++ return rc_test_condition_compare(value1.value.u32, value2, self->oper); ++} ++ ++static int rc_test_condition_compare_memref_to_memref_transformed(rc_condition_t* self) { ++ rc_typed_value_t value1, value2; ++ ++ value1.type = RC_VALUE_TYPE_UNSIGNED; ++ value1.value.u32 = self->operand1.value.memref->value.value; ++ rc_transform_memref_value(&value1, self->operand1.size); ++ ++ value2.type = RC_VALUE_TYPE_UNSIGNED; ++ value2.value.u32 = self->operand2.value.memref->value.value; ++ rc_transform_memref_value(&value2, self->operand2.size); ++ ++ return rc_test_condition_compare(value1.value.u32, value2.value.u32, self->oper); ++} ++ ++static int rc_test_condition_compare_memref_to_delta_transformed(rc_condition_t* self) { ++ const rc_memref_value_t* memref = &self->operand1.value.memref->value; ++ assert(self->operand1.value.memref == self->operand2.value.memref); ++ ++ if (memref->changed) { ++ rc_typed_value_t value1, value2; ++ ++ value1.type = RC_VALUE_TYPE_UNSIGNED; ++ value1.value.u32 = memref->value; ++ rc_transform_memref_value(&value1, self->operand1.size); ++ ++ value2.type = RC_VALUE_TYPE_UNSIGNED; ++ value2.value.u32 = memref->prior; ++ rc_transform_memref_value(&value2, self->operand2.size); ++ ++ return rc_test_condition_compare(value1.value.u32, value2.value.u32, self->oper); ++ } ++ ++ switch (self->oper) { ++ case RC_OPERATOR_EQ: ++ case RC_OPERATOR_GE: ++ case RC_OPERATOR_LE: ++ return 1; ++ ++ default: ++ return 0; ++ } ++} ++ ++static int rc_test_condition_compare_delta_to_memref_transformed(rc_condition_t* self) { ++ const rc_memref_value_t* memref = &self->operand1.value.memref->value; ++ assert(self->operand1.value.memref == self->operand2.value.memref); ++ ++ if (memref->changed) { ++ rc_typed_value_t value1, value2; ++ ++ value1.type = RC_VALUE_TYPE_UNSIGNED; ++ value1.value.u32 = memref->prior; ++ rc_transform_memref_value(&value1, self->operand1.size); ++ ++ value2.type = RC_VALUE_TYPE_UNSIGNED; ++ value2.value.u32 = memref->value; ++ rc_transform_memref_value(&value2, self->operand2.size); ++ ++ return rc_test_condition_compare(value1.value.u32, value2.value.u32, self->oper); ++ } ++ ++ switch (self->oper) { ++ case RC_OPERATOR_EQ: ++ case RC_OPERATOR_GE: ++ case RC_OPERATOR_LE: ++ return 1; ++ ++ default: ++ return 0; ++ } ++} ++ ++int rc_test_condition(rc_condition_t* self, rc_eval_state_t* eval_state) { ++ rc_typed_value_t value1, value2; ++ ++ /* use an optimized comparator whenever possible */ ++ switch (self->optimized_comparator) { ++ case RC_PROCESSING_COMPARE_MEMREF_TO_CONST: ++ return rc_test_condition_compare_memref_to_const(self); ++ case RC_PROCESSING_COMPARE_MEMREF_TO_DELTA: ++ return rc_test_condition_compare_memref_to_delta(self); ++ case RC_PROCESSING_COMPARE_MEMREF_TO_MEMREF: ++ return rc_test_condition_compare_memref_to_memref(self); ++ case RC_PROCESSING_COMPARE_DELTA_TO_CONST: ++ return rc_test_condition_compare_delta_to_const(self); ++ case RC_PROCESSING_COMPARE_DELTA_TO_MEMREF: ++ return rc_test_condition_compare_delta_to_memref(self); ++ case RC_PROCESSING_COMPARE_MEMREF_TO_CONST_TRANSFORMED: ++ return rc_test_condition_compare_memref_to_const_transformed(self); ++ case RC_PROCESSING_COMPARE_MEMREF_TO_DELTA_TRANSFORMED: ++ return rc_test_condition_compare_memref_to_delta_transformed(self); ++ case RC_PROCESSING_COMPARE_MEMREF_TO_MEMREF_TRANSFORMED: ++ return rc_test_condition_compare_memref_to_memref_transformed(self); ++ case RC_PROCESSING_COMPARE_DELTA_TO_CONST_TRANSFORMED: ++ return rc_test_condition_compare_delta_to_const_transformed(self); ++ case RC_PROCESSING_COMPARE_DELTA_TO_MEMREF_TRANSFORMED: ++ return rc_test_condition_compare_delta_to_memref_transformed(self); ++ case RC_PROCESSING_COMPARE_ALWAYS_TRUE: ++ return 1; ++ case RC_PROCESSING_COMPARE_ALWAYS_FALSE: ++ return 0; ++ default: ++ rc_evaluate_operand(&value1, &self->operand1, eval_state); ++ break; ++ } ++ ++ rc_evaluate_operand(&value2, &self->operand2, eval_state); ++ ++ return rc_typed_value_compare(&value1, &value2, self->oper); ++} ++ ++void rc_evaluate_condition_value(rc_typed_value_t* value, rc_condition_t* self, rc_eval_state_t* eval_state) { ++ rc_typed_value_t amount; ++ ++ rc_evaluate_operand(value, &self->operand1, eval_state); ++ rc_evaluate_operand(&amount, &self->operand2, eval_state); ++ ++ rc_typed_value_combine(value, &amount, self->oper); ++} +diff -rupbN melonDS.orig/src/rcheevos/src/rcheevos/condset.c melonDS.ra/src/rcheevos/src/rcheevos/condset.c +--- melonDS.orig/src/rcheevos/src/rcheevos/condset.c 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rcheevos/condset.c 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,770 @@ ++#include "rc_internal.h" ++ ++#include /* memcpy */ ++ ++enum { ++ RC_CONDITION_CLASSIFICATION_COMBINING, ++ RC_CONDITION_CLASSIFICATION_PAUSE, ++ RC_CONDITION_CLASSIFICATION_RESET, ++ RC_CONDITION_CLASSIFICATION_HITTARGET, ++ RC_CONDITION_CLASSIFICATION_MEASURED, ++ RC_CONDITION_CLASSIFICATION_OTHER, ++ RC_CONDITION_CLASSIFICATION_INDIRECT ++}; ++ ++static int rc_classify_condition(const rc_condition_t* cond) { ++ switch (cond->type) { ++ case RC_CONDITION_PAUSE_IF: ++ return RC_CONDITION_CLASSIFICATION_PAUSE; ++ ++ case RC_CONDITION_RESET_IF: ++ return RC_CONDITION_CLASSIFICATION_RESET; ++ ++ case RC_CONDITION_ADD_ADDRESS: ++ case RC_CONDITION_ADD_SOURCE: ++ case RC_CONDITION_SUB_SOURCE: ++ /* these are handled by rc_modified_memref_t */ ++ return RC_CONDITION_CLASSIFICATION_INDIRECT; ++ ++ case RC_CONDITION_ADD_HITS: ++ case RC_CONDITION_AND_NEXT: ++ case RC_CONDITION_OR_NEXT: ++ case RC_CONDITION_REMEMBER: ++ case RC_CONDITION_RESET_NEXT_IF: ++ case RC_CONDITION_SUB_HITS: ++ return RC_CONDITION_CLASSIFICATION_COMBINING; ++ ++ case RC_CONDITION_MEASURED: ++ case RC_CONDITION_MEASURED_IF: ++ /* even if not measuring a hit target, we still want to evaluate it every frame */ ++ return RC_CONDITION_CLASSIFICATION_MEASURED; ++ ++ default: ++ if (cond->required_hits != 0) ++ return RC_CONDITION_CLASSIFICATION_HITTARGET; ++ ++ return RC_CONDITION_CLASSIFICATION_OTHER; ++ } ++} ++ ++static int32_t rc_classify_conditions(rc_condset_t* self, const char* memaddr, const rc_parse_state_t* parent_parse) { ++ rc_parse_state_t parse; ++ rc_memrefs_t memrefs; ++ rc_condition_t condition; ++ int classification; ++ uint32_t index = 0; ++ uint32_t chain_length = 1; ++ ++ rc_init_parse_state(&parse, NULL); ++ rc_init_parse_state_memrefs(&parse, &memrefs); ++ parse.ignore_non_parse_errors = parent_parse->ignore_non_parse_errors; ++ ++ do { ++ rc_parse_condition_internal(&condition, &memaddr, &parse); ++ ++ if (parse.offset < 0) { ++ rc_destroy_parse_state(&parse); ++ return parse.offset; ++ } ++ ++ ++index; ++ ++ classification = rc_classify_condition(&condition); ++ switch (classification) { ++ case RC_CONDITION_CLASSIFICATION_COMBINING: ++ ++chain_length; ++ continue; ++ ++ case RC_CONDITION_CLASSIFICATION_INDIRECT: ++ ++self->num_indirect_conditions; ++ continue; ++ ++ case RC_CONDITION_CLASSIFICATION_PAUSE: ++ self->num_pause_conditions += chain_length; ++ break; ++ ++ case RC_CONDITION_CLASSIFICATION_RESET: ++ self->num_reset_conditions += chain_length; ++ break; ++ ++ case RC_CONDITION_CLASSIFICATION_HITTARGET: ++ self->num_hittarget_conditions += chain_length; ++ break; ++ ++ case RC_CONDITION_CLASSIFICATION_MEASURED: ++ self->num_measured_conditions += chain_length; ++ break; ++ ++ default: ++ self->num_other_conditions += chain_length; ++ break; ++ } ++ ++ chain_length = 1; ++ } while (*memaddr++ == '_'); ++ ++ /* any combining conditions that don't actually feed into a non-combining condition ++ * need to still have space allocated for them. put them in "other" to match the ++ * logic in rc_find_next_classification */ ++ self->num_other_conditions += chain_length - 1; ++ ++ rc_destroy_parse_state(&parse); ++ ++ return (int32_t)index; ++} ++ ++static int rc_find_next_classification(const char* memaddr) { ++ rc_parse_state_t parse; ++ rc_memrefs_t memrefs; ++ rc_condition_t condition; ++ int classification; ++ ++ rc_init_parse_state(&parse, NULL); ++ rc_init_parse_state_memrefs(&parse, &memrefs); ++ ++ do { ++ rc_parse_condition_internal(&condition, &memaddr, &parse); ++ if (parse.offset < 0) ++ break; ++ ++ classification = rc_classify_condition(&condition); ++ switch (classification) { ++ case RC_CONDITION_CLASSIFICATION_COMBINING: ++ case RC_CONDITION_CLASSIFICATION_INDIRECT: ++ break; ++ ++ default: ++ return classification; ++ } ++ } while (*memaddr++ == '_'); ++ ++ return RC_CONDITION_CLASSIFICATION_OTHER; ++} ++ ++static void rc_condition_update_recall_operand(rc_operand_t* operand, const rc_operand_t* remember) ++{ ++ if (operand->type == RC_OPERAND_RECALL) { ++ if (rc_operand_type_is_memref(operand->memref_access_type) && operand->value.memref == NULL) { ++ memcpy(operand, remember, sizeof(*remember)); ++ operand->memref_access_type = operand->type; ++ operand->type = RC_OPERAND_RECALL; ++ } ++ } ++ else if (rc_operand_is_memref(operand) && operand->value.memref->value.memref_type == RC_MEMREF_TYPE_MODIFIED_MEMREF) { ++ rc_modified_memref_t* modified_memref = (rc_modified_memref_t*)operand->value.memref; ++ rc_condition_update_recall_operand(&modified_memref->parent, remember); ++ rc_condition_update_recall_operand(&modified_memref->modifier, remember); ++ } ++} ++ ++static void rc_update_condition_pause_remember(rc_condset_t* self) { ++ rc_operand_t* pause_remember = NULL; ++ rc_condition_t* condition; ++ rc_condition_t* pause_conditions; ++ const rc_condition_t* end_pause_condition; ++ ++ /* ASSERT: pause conditions are first conditions */ ++ pause_conditions = rc_condset_get_conditions(self); ++ end_pause_condition = pause_conditions + self->num_pause_conditions; ++ ++ for (condition = pause_conditions; condition < end_pause_condition; ++condition) { ++ if (condition->type == RC_CONDITION_REMEMBER) { ++ pause_remember = &condition->operand1; ++ } ++ else if (pause_remember == NULL) { ++ /* if we picked up a non-pause remember, discard it */ ++ if (condition->operand1.type == RC_OPERAND_RECALL && ++ rc_operand_type_is_memref(condition->operand1.memref_access_type)) { ++ condition->operand1.value.memref = NULL; ++ } ++ ++ if (condition->operand2.type == RC_OPERAND_RECALL && ++ rc_operand_type_is_memref(condition->operand2.memref_access_type)) { ++ condition->operand2.value.memref = NULL; ++ } ++ } ++ } ++ ++ if (pause_remember) { ++ for (condition = self->conditions; condition; condition = condition->next) { ++ if (condition >= end_pause_condition) { ++ /* if we didn't find a remember for a non-pause condition, use the last pause remember */ ++ rc_condition_update_recall_operand(&condition->operand1, pause_remember); ++ rc_condition_update_recall_operand(&condition->operand2, pause_remember); ++ } ++ ++ /* Anything after this point will have already been handled */ ++ if (condition->type == RC_CONDITION_REMEMBER) ++ break; ++ } ++ } ++} ++ ++rc_condset_t* rc_parse_condset(const char** memaddr, rc_parse_state_t* parse) { ++ rc_condset_with_trailing_conditions_t* condset_with_conditions; ++ rc_condset_t local_condset; ++ rc_condset_t* self; ++ rc_condition_t condition; ++ rc_condition_t* conditions; ++ rc_condition_t** next; ++ rc_condition_t* pause_conditions = NULL; ++ rc_condition_t* reset_conditions = NULL; ++ rc_condition_t* hittarget_conditions = NULL; ++ rc_condition_t* measured_conditions = NULL; ++ rc_condition_t* other_conditions = NULL; ++ rc_condition_t* indirect_conditions = NULL; ++ int classification, combining_classification = RC_CONDITION_CLASSIFICATION_COMBINING; ++ uint32_t measured_target = 0; ++ int32_t result; ++ ++ if (**memaddr == 'S' || **memaddr == 's' || !**memaddr) { ++ /* empty group - editor allows it, so we have to support it */ ++ self = RC_ALLOC(rc_condset_t, parse); ++ memset(self, 0, sizeof(*self)); ++ return self; ++ } ++ ++ memset(&local_condset, 0, sizeof(local_condset)); ++ result = rc_classify_conditions(&local_condset, *memaddr, parse); ++ if (result < 0) { ++ parse->offset = result; ++ return NULL; ++ } ++ ++ condset_with_conditions = RC_ALLOC_WITH_TRAILING(rc_condset_with_trailing_conditions_t, ++ rc_condition_t, conditions, result, parse); ++ if (parse->offset < 0) ++ return NULL; ++ ++ self = (rc_condset_t*)condset_with_conditions; ++ memcpy(self, &local_condset, sizeof(local_condset)); ++ conditions = &condset_with_conditions->conditions[0]; ++ ++ if (parse->buffer) { ++ pause_conditions = conditions; ++ conditions += self->num_pause_conditions; ++ ++ reset_conditions = conditions; ++ conditions += self->num_reset_conditions; ++ ++ hittarget_conditions = conditions; ++ conditions += self->num_hittarget_conditions; ++ ++ measured_conditions = conditions; ++ conditions += self->num_measured_conditions; ++ ++ other_conditions = conditions; ++ conditions += self->num_other_conditions; ++ ++ indirect_conditions = conditions; ++ } ++ ++ next = &self->conditions; ++ ++ /* each condition set has a functionally new recall accumulator */ ++ parse->remember.type = RC_OPERAND_NONE; ++ ++ for (;;) { ++ rc_parse_condition_internal(&condition, memaddr, parse); ++ ++ if (parse->offset < 0) ++ return NULL; ++ ++ if (condition.oper == RC_OPERATOR_NONE && !parse->ignore_non_parse_errors) { ++ switch (condition.type) { ++ case RC_CONDITION_ADD_ADDRESS: ++ case RC_CONDITION_ADD_SOURCE: ++ case RC_CONDITION_SUB_SOURCE: ++ case RC_CONDITION_REMEMBER: ++ /* these conditions don't require a right hand side (implied *1) */ ++ break; ++ ++ case RC_CONDITION_MEASURED: ++ /* right hand side is not required when Measured is used in a value */ ++ if (parse->is_value) ++ break; ++ /* fallthrough */ /* to default */ ++ ++ default: ++ parse->offset = RC_INVALID_OPERATOR; ++ return NULL; ++ } ++ } ++ ++ switch (condition.type) { ++ case RC_CONDITION_MEASURED: ++ if (measured_target != 0) { ++ /* multiple Measured flags cannot exist in the same group */ ++ if (!parse->ignore_non_parse_errors) { ++ parse->offset = RC_MULTIPLE_MEASURED; ++ return NULL; ++ } ++ } ++ else if (parse->is_value) { ++ measured_target = (uint32_t)-1; ++ if (!rc_operator_is_modifying(condition.oper)) { ++ /* measuring comparison in a value results in a tally (hit count). set target to MAX_INT */ ++ condition.required_hits = measured_target; ++ } ++ } ++ else if (condition.required_hits != 0) { ++ measured_target = condition.required_hits; ++ } ++ else if (condition.operand2.type == RC_OPERAND_CONST) { ++ measured_target = condition.operand2.value.num; ++ } ++ else if (condition.operand2.type == RC_OPERAND_FP) { ++ measured_target = (unsigned)condition.operand2.value.dbl; ++ } ++ else if (!parse->ignore_non_parse_errors) { ++ parse->offset = RC_INVALID_MEASURED_TARGET; ++ return NULL; ++ } ++ ++ if (parse->measured_target && measured_target != parse->measured_target) { ++ /* multiple Measured flags in separate groups must have the same target */ ++ if (!parse->ignore_non_parse_errors) { ++ parse->offset = RC_MULTIPLE_MEASURED; ++ return NULL; ++ } ++ } ++ ++ parse->measured_target = measured_target; ++ break; ++ ++ case RC_CONDITION_STANDARD: ++ case RC_CONDITION_TRIGGER: ++ /* these flags are not allowed in value expressions */ ++ if (parse->is_value && !parse->ignore_non_parse_errors) { ++ parse->offset = RC_INVALID_VALUE_FLAG; ++ return NULL; ++ } ++ break; ++ } ++ ++ rc_condition_update_parse_state(&condition, parse); ++ ++ if (parse->buffer) { ++ classification = rc_classify_condition(&condition); ++ if (classification == RC_CONDITION_CLASSIFICATION_COMBINING) { ++ if (combining_classification == RC_CONDITION_CLASSIFICATION_COMBINING) { ++ if (**memaddr == '_') ++ combining_classification = rc_find_next_classification(&(*memaddr)[1]); /* skip over '_' */ ++ else ++ combining_classification = RC_CONDITION_CLASSIFICATION_OTHER; ++ } ++ ++ classification = combining_classification; ++ } ++ else { ++ combining_classification = RC_CONDITION_CLASSIFICATION_COMBINING; ++ } ++ ++ switch (classification) { ++ case RC_CONDITION_CLASSIFICATION_PAUSE: ++ memcpy(pause_conditions, &condition, sizeof(condition)); ++ *next = pause_conditions++; ++ break; ++ ++ case RC_CONDITION_CLASSIFICATION_RESET: ++ memcpy(reset_conditions, &condition, sizeof(condition)); ++ *next = reset_conditions++; ++ break; ++ ++ case RC_CONDITION_CLASSIFICATION_HITTARGET: ++ memcpy(hittarget_conditions, &condition, sizeof(condition)); ++ *next = hittarget_conditions++; ++ break; ++ ++ case RC_CONDITION_CLASSIFICATION_MEASURED: ++ memcpy(measured_conditions, &condition, sizeof(condition)); ++ *next = measured_conditions++; ++ break; ++ ++ case RC_CONDITION_CLASSIFICATION_INDIRECT: ++ memcpy(indirect_conditions, &condition, sizeof(condition)); ++ *next = indirect_conditions++; ++ break; ++ ++ default: ++ memcpy(other_conditions, &condition, sizeof(condition)); ++ *next = other_conditions++; ++ break; ++ } ++ ++ next = &(*next)->next; ++ } ++ ++ if (**memaddr != '_') ++ break; ++ ++ (*memaddr)++; ++ } ++ ++ *next = NULL; ++ ++ self->has_pause = self->num_pause_conditions > 0; ++ if (self->has_pause && parse->buffer && parse->remember.type != RC_OPERAND_NONE) ++ rc_update_condition_pause_remember(self); ++ ++ return self; ++} ++ ++static uint8_t rc_condset_evaluate_condition_no_add_hits(rc_condition_t* condition, rc_eval_state_t* eval_state) { ++ /* evaluate the current condition */ ++ uint8_t cond_valid = (uint8_t)rc_test_condition(condition, eval_state); ++ condition->is_true = cond_valid; ++ ++ if (eval_state->reset_next) { ++ /* previous ResetNextIf resets the hit count on this condition and prevents it from being true */ ++ eval_state->was_cond_reset |= (condition->current_hits != 0); ++ ++ condition->current_hits = 0; ++ cond_valid = 0; ++ } ++ else { ++ /* apply chained logic flags */ ++ cond_valid &= eval_state->and_next; ++ cond_valid |= eval_state->or_next; ++ ++ if (cond_valid) { ++ /* true conditions should update their hit count */ ++ eval_state->has_hits = 1; ++ ++ if (condition->required_hits == 0) { ++ /* no target hit count, just keep tallying */ ++ ++condition->current_hits; ++ } ++ else if (condition->current_hits < condition->required_hits) { ++ /* target hit count hasn't been met, tally and revalidate - only true if hit count becomes met */ ++ ++condition->current_hits; ++ cond_valid = (condition->current_hits == condition->required_hits); ++ } ++ else { ++ /* target hit count has been met, do nothing */ ++ } ++ } ++ else if (condition->current_hits > 0) { ++ /* target has been true in the past, if the hit target is met, consider it true now */ ++ eval_state->has_hits = 1; ++ cond_valid = (condition->current_hits == condition->required_hits); ++ } ++ } ++ ++ /* reset chained logic flags for the next condition */ ++ eval_state->and_next = 1; ++ eval_state->or_next = 0; ++ ++ return cond_valid; ++} ++ ++static uint32_t rc_condset_evaluate_total_hits(rc_condition_t* condition, rc_eval_state_t* eval_state) { ++ uint32_t total_hits = condition->current_hits; ++ ++ if (condition->required_hits != 0) { ++ /* if the condition has a target hit count, we have to recalculate cond_valid including the AddHits counter */ ++ const int32_t signed_hits = (int32_t)condition->current_hits + eval_state->add_hits; ++ total_hits = (signed_hits >= 0) ? (uint32_t)signed_hits : 0; ++ } ++ else { ++ /* no target hit count. we can't tell if the add_hits value is from this frame or not, so ignore it. ++ complex condition will only be true if the current condition is true */ ++ } ++ ++ eval_state->add_hits = 0; ++ ++ return total_hits; ++} ++ ++static uint8_t rc_condset_evaluate_condition(rc_condition_t* condition, rc_eval_state_t* eval_state) { ++ uint8_t cond_valid = rc_condset_evaluate_condition_no_add_hits(condition, eval_state); ++ ++ if (eval_state->add_hits != 0 && condition->required_hits != 0) { ++ uint32_t total_hits = rc_condset_evaluate_total_hits(condition, eval_state); ++ cond_valid = (total_hits >= condition->required_hits); ++ } ++ ++ /* reset logic flags for the next condition */ ++ eval_state->reset_next = 0; ++ ++ return cond_valid; ++} ++ ++static void rc_condset_evaluate_standard(rc_condition_t* condition, rc_eval_state_t* eval_state) { ++ const uint8_t cond_valid = rc_condset_evaluate_condition(condition, eval_state); ++ ++ eval_state->is_true &= cond_valid; ++ eval_state->is_primed &= cond_valid; ++ ++ if (!cond_valid && eval_state->can_short_curcuit) ++ eval_state->stop_processing = 1; ++} ++ ++static void rc_condset_evaluate_pause_if(rc_condition_t* condition, rc_eval_state_t* eval_state) { ++ const uint8_t cond_valid = rc_condset_evaluate_condition(condition, eval_state); ++ ++ if (cond_valid) { ++ eval_state->is_paused = 1; ++ ++ /* set cannot be valid if it's paused */ ++ eval_state->is_true = eval_state->is_primed = 0; ++ ++ /* as soon as we find a PauseIf that evaluates to true, stop processing the rest of the group */ ++ eval_state->stop_processing = 1; ++ } ++ else if (condition->required_hits == 0) { ++ /* PauseIf didn't evaluate true, and doesn't have a HitCount, reset the HitCount to indicate the condition didn't match */ ++ condition->current_hits = 0; ++ } ++ else { ++ /* PauseIf has a HitCount that hasn't been met, ignore it for now. */ ++ } ++} ++ ++static void rc_condset_evaluate_reset_if(rc_condition_t* condition, rc_eval_state_t* eval_state) { ++ const uint8_t cond_valid = rc_condset_evaluate_condition(condition, eval_state); ++ ++ if (cond_valid) { ++ /* flag the condition as being responsible for the reset */ ++ /* make sure not to modify bit0, as we use bitwise-and operators to combine truthiness */ ++ condition->is_true |= 0x02; ++ ++ /* set cannot be valid if we've hit a reset condition */ ++ eval_state->is_true = eval_state->is_primed = 0; ++ ++ /* let caller know to reset all hit counts */ ++ eval_state->was_reset = 1; ++ ++ /* can stop processing once an active ResetIf is encountered */ ++ eval_state->stop_processing = 1; ++ } ++} ++ ++static void rc_condset_evaluate_trigger(rc_condition_t* condition, rc_eval_state_t* eval_state) { ++ const uint8_t cond_valid = rc_condset_evaluate_condition(condition, eval_state); ++ ++ eval_state->is_true &= cond_valid; ++} ++ ++static void rc_condset_evaluate_measured(rc_condition_t* condition, rc_eval_state_t* eval_state) { ++ if (condition->required_hits == 0) { ++ rc_condset_evaluate_standard(condition, eval_state); ++ ++ /* Measured condition without a hit target measures the value of the left operand */ ++ rc_evaluate_operand(&eval_state->measured_value, &condition->operand1, eval_state); ++ eval_state->measured_from_hits = 0; ++ } ++ else { ++ /* this largely mimicks rc_condset_evaluate_condition, but captures the total_hits */ ++ uint8_t cond_valid = rc_condset_evaluate_condition_no_add_hits(condition, eval_state); ++ const uint32_t total_hits = rc_condset_evaluate_total_hits(condition, eval_state); ++ ++ cond_valid = (total_hits >= condition->required_hits); ++ eval_state->is_true &= cond_valid; ++ eval_state->is_primed &= cond_valid; ++ ++ /* if there is a hit target, capture the current hits */ ++ eval_state->measured_value.value.u32 = total_hits; ++ eval_state->measured_value.type = RC_VALUE_TYPE_UNSIGNED; ++ eval_state->measured_from_hits = 1; ++ ++ /* reset logic flags for the next condition */ ++ eval_state->reset_next = 0; ++ } ++} ++ ++static void rc_condset_evaluate_measured_if(rc_condition_t* condition, rc_eval_state_t* eval_state) { ++ const uint8_t cond_valid = rc_condset_evaluate_condition(condition, eval_state); ++ ++ eval_state->is_true &= cond_valid; ++ eval_state->is_primed &= cond_valid; ++ eval_state->can_measure &= cond_valid; ++} ++ ++static void rc_condset_evaluate_add_hits(rc_condition_t* condition, rc_eval_state_t* eval_state) { ++ rc_condset_evaluate_condition_no_add_hits(condition, eval_state); ++ ++ eval_state->add_hits += (int32_t)condition->current_hits; ++ ++ /* ResetNextIf was applied to this AddHits condition; don't apply it to future conditions */ ++ eval_state->reset_next = 0; ++} ++ ++static void rc_condset_evaluate_sub_hits(rc_condition_t* condition, rc_eval_state_t* eval_state) { ++ rc_condset_evaluate_condition_no_add_hits(condition, eval_state); ++ ++ eval_state->add_hits -= (int32_t)condition->current_hits; ++ ++ /* ResetNextIf was applied to this AddHits condition; don't apply it to future conditions */ ++ eval_state->reset_next = 0; ++} ++ ++static void rc_condset_evaluate_reset_next_if(rc_condition_t* condition, rc_eval_state_t* eval_state) { ++ eval_state->reset_next = rc_condset_evaluate_condition_no_add_hits(condition, eval_state); ++} ++ ++static void rc_condset_evaluate_and_next(rc_condition_t* condition, rc_eval_state_t* eval_state) { ++ eval_state->and_next = rc_condset_evaluate_condition_no_add_hits(condition, eval_state); ++} ++ ++static void rc_condset_evaluate_or_next(rc_condition_t* condition, rc_eval_state_t* eval_state) { ++ eval_state->or_next = rc_condset_evaluate_condition_no_add_hits(condition, eval_state); ++} ++ ++void rc_test_condset_internal(rc_condition_t* condition, uint32_t num_conditions, ++ rc_eval_state_t* eval_state, int can_short_circuit) { ++ const rc_condition_t* condition_end = condition + num_conditions; ++ for (; condition < condition_end; ++condition) { ++ switch (condition->type) { ++ case RC_CONDITION_STANDARD: ++ rc_condset_evaluate_standard(condition, eval_state); ++ break; ++ case RC_CONDITION_PAUSE_IF: ++ rc_condset_evaluate_pause_if(condition, eval_state); ++ break; ++ case RC_CONDITION_RESET_IF: ++ rc_condset_evaluate_reset_if(condition, eval_state); ++ break; ++ case RC_CONDITION_TRIGGER: ++ rc_condset_evaluate_trigger(condition, eval_state); ++ break; ++ case RC_CONDITION_MEASURED: ++ rc_condset_evaluate_measured(condition, eval_state); ++ break; ++ case RC_CONDITION_MEASURED_IF: ++ rc_condset_evaluate_measured_if(condition, eval_state); ++ break; ++ case RC_CONDITION_ADD_SOURCE: ++ case RC_CONDITION_SUB_SOURCE: ++ case RC_CONDITION_ADD_ADDRESS: ++ case RC_CONDITION_REMEMBER: ++ /* these are handled by rc_modified_memref_t */ ++ break; ++ case RC_CONDITION_ADD_HITS: ++ rc_condset_evaluate_add_hits(condition, eval_state); ++ break; ++ case RC_CONDITION_SUB_HITS: ++ rc_condset_evaluate_sub_hits(condition, eval_state); ++ break; ++ case RC_CONDITION_RESET_NEXT_IF: ++ rc_condset_evaluate_reset_next_if(condition, eval_state); ++ break; ++ case RC_CONDITION_AND_NEXT: ++ rc_condset_evaluate_and_next(condition, eval_state); ++ break; ++ case RC_CONDITION_OR_NEXT: ++ rc_condset_evaluate_or_next(condition, eval_state); ++ break; ++ default: ++ eval_state->stop_processing = 1; ++ eval_state->is_true = eval_state->is_primed = 0; ++ break; ++ } ++ ++ if (eval_state->stop_processing && can_short_circuit) ++ break; ++ } ++} ++ ++rc_condition_t* rc_condset_get_conditions(rc_condset_t* self) { ++ if (self->conditions) ++ return RC_GET_TRAILING(self, rc_condset_with_trailing_conditions_t, rc_condition_t, conditions); ++ ++ return NULL; ++} ++ ++int rc_test_condset(rc_condset_t* self, rc_eval_state_t* eval_state) { ++ rc_condition_t* conditions; ++ ++ /* reset the processing state before processing each condset. do not reset the result state. */ ++ eval_state->measured_value.type = RC_VALUE_TYPE_NONE; ++ eval_state->add_hits = 0; ++ eval_state->is_true = 1; ++ eval_state->is_primed = 1; ++ eval_state->is_paused = 0; ++ eval_state->can_measure = 1; ++ eval_state->measured_from_hits = 0; ++ eval_state->and_next = 1; ++ eval_state->or_next = 0; ++ eval_state->reset_next = 0; ++ eval_state->stop_processing = 0; ++ ++ /* the conditions array is allocated immediately after the rc_condset_t, without a separate pointer */ ++ conditions = rc_condset_get_conditions(self); ++ ++ if (self->num_pause_conditions) { ++ /* one or more Pause conditions exist. if any of them are true (eval_state->is_paused), ++ * stop processing this group */ ++ rc_test_condset_internal(conditions, self->num_pause_conditions, eval_state, 1); ++ ++ self->is_paused = eval_state->is_paused; ++ if (self->is_paused) { ++ /* condset is paused. stop processing immediately. */ ++ return 0; ++ } ++ ++ conditions += self->num_pause_conditions; ++ } ++ ++ if (self->num_reset_conditions) { ++ /* one or more Reset conditions exists. if any of them are true (eval_state->was_reset), ++ * we'll skip some of the later steps */ ++ rc_test_condset_internal(conditions, self->num_reset_conditions, eval_state, eval_state->can_short_curcuit); ++ conditions += self->num_reset_conditions; ++ } ++ ++ if (self->num_hittarget_conditions) { ++ /* one or more hit target conditions exists. these must be processed every frame, ++ * unless their hit count is going to be reset */ ++ if (!eval_state->was_reset) ++ rc_test_condset_internal(conditions, self->num_hittarget_conditions, eval_state, 0); ++ ++ conditions += self->num_hittarget_conditions; ++ } ++ ++ if (self->num_measured_conditions) { ++ /* IMPORTANT: reset hit counts on these conditions before processing them so ++ * the MeasuredIf logic and Measured value are correct. ++ * NOTE: a ResetIf in a later alt group may not have been processed yet. ++ * Accept that as a weird edge case, and just recommend the user ++ * move the ResetIf if it becomes a problem. */ ++ if (eval_state->was_reset) { ++ int i; ++ for (i = 0; i < self->num_measured_conditions; ++i) ++ conditions[i].current_hits = 0; ++ } ++ ++ /* the measured value must be calculated every frame, even if hit counts will be reset */ ++ rc_test_condset_internal(conditions, self->num_measured_conditions, eval_state, 0); ++ conditions += self->num_measured_conditions; ++ ++ if (eval_state->measured_value.type != RC_VALUE_TYPE_NONE) { ++ /* if a MeasuredIf was false (!eval_state->can_measure), or the measured ++ * value is a hitcount and a ResetIf is true, zero out the measured value */ ++ if (!eval_state->can_measure || ++ (eval_state->measured_from_hits && eval_state->was_reset)) { ++ eval_state->measured_value.type = RC_VALUE_TYPE_UNSIGNED; ++ eval_state->measured_value.value.u32 = 0; ++ } ++ } ++ } ++ ++ if (self->num_other_conditions) { ++ /* the remaining conditions only need to be evaluated if the rest of the condset is true */ ++ if (eval_state->is_true) ++ rc_test_condset_internal(conditions, self->num_other_conditions, eval_state, eval_state->can_short_curcuit); ++ /* something else is false. if we can't short circuit, and there wasn't a reset, we still need to evaluate these */ ++ else if (!eval_state->can_short_curcuit && !eval_state->was_reset) ++ rc_test_condset_internal(conditions, self->num_other_conditions, eval_state, eval_state->can_short_curcuit); ++ } ++ ++ return eval_state->is_true; ++} ++ ++void rc_reset_condset(rc_condset_t* self) { ++ rc_condition_t* condition; ++ ++ for (condition = self->conditions; condition != 0; condition = condition->next) { ++ condition->current_hits = 0; ++ } ++} +diff -rupbN melonDS.orig/src/rcheevos/src/rcheevos/consoleinfo.c melonDS.ra/src/rcheevos/src/rcheevos/consoleinfo.c +--- melonDS.orig/src/rcheevos/src/rcheevos/consoleinfo.c 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rcheevos/consoleinfo.c 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,1215 @@ ++#include "rc_consoles.h" ++ ++#include ++ ++const char* rc_console_name(uint32_t console_id) ++{ ++ switch (console_id) ++ { ++ case RC_CONSOLE_3DO: ++ return "3DO"; ++ ++ case RC_CONSOLE_AMIGA: ++ return "Amiga"; ++ ++ case RC_CONSOLE_AMSTRAD_PC: ++ return "Amstrad CPC"; ++ ++ case RC_CONSOLE_APPLE_II: ++ return "Apple II"; ++ ++ case RC_CONSOLE_ARCADE: ++ return "Arcade"; ++ ++ case RC_CONSOLE_ARCADIA_2001: ++ return "Arcadia 2001"; ++ ++ case RC_CONSOLE_ARDUBOY: ++ return "Arduboy"; ++ ++ case RC_CONSOLE_ATARI_2600: ++ return "Atari 2600"; ++ ++ case RC_CONSOLE_ATARI_5200: ++ return "Atari 5200"; ++ ++ case RC_CONSOLE_ATARI_7800: ++ return "Atari 7800"; ++ ++ case RC_CONSOLE_ATARI_JAGUAR: ++ return "Atari Jaguar"; ++ ++ case RC_CONSOLE_ATARI_JAGUAR_CD: ++ return "Atari Jaguar CD"; ++ ++ case RC_CONSOLE_ATARI_LYNX: ++ return "Atari Lynx"; ++ ++ case RC_CONSOLE_ATARI_ST: ++ return "Atari ST"; ++ ++ case RC_CONSOLE_CASSETTEVISION: ++ return "CassetteVision"; ++ ++ case RC_CONSOLE_CDI: ++ return "CD-I"; ++ ++ case RC_CONSOLE_COLECOVISION: ++ return "ColecoVision"; ++ ++ case RC_CONSOLE_COMMODORE_64: ++ return "Commodore 64"; ++ ++ case RC_CONSOLE_DREAMCAST: ++ return "Dreamcast"; ++ ++ case RC_CONSOLE_ELEKTOR_TV_GAMES_COMPUTER: ++ return "Elektor TV Games Computer"; ++ ++ case RC_CONSOLE_EVENTS: ++ return "Events"; ++ ++ case RC_CONSOLE_FAIRCHILD_CHANNEL_F: ++ return "Fairchild Channel F"; ++ ++ case RC_CONSOLE_FAMICOM_DISK_SYSTEM: ++ return "Famicom Disk System"; ++ ++ case RC_CONSOLE_FM_TOWNS: ++ return "FM Towns"; ++ ++ case RC_CONSOLE_GAME_AND_WATCH: ++ return "Game & Watch"; ++ ++ case RC_CONSOLE_GAMEBOY: ++ return "GameBoy"; ++ ++ case RC_CONSOLE_GAMEBOY_ADVANCE: ++ return "GameBoy Advance"; ++ ++ case RC_CONSOLE_GAMEBOY_COLOR: ++ return "GameBoy Color"; ++ ++ case RC_CONSOLE_GAMECUBE: ++ return "GameCube"; ++ ++ case RC_CONSOLE_GAME_GEAR: ++ return "Game Gear"; ++ ++ case RC_CONSOLE_HUBS: ++ return "Hubs"; ++ ++ case RC_CONSOLE_INTELLIVISION: ++ return "Intellivision"; ++ ++ case RC_CONSOLE_INTERTON_VC_4000: ++ return "Interton VC 4000"; ++ ++ case RC_CONSOLE_MAGNAVOX_ODYSSEY2: ++ return "Magnavox Odyssey 2"; ++ ++ case RC_CONSOLE_MASTER_SYSTEM: ++ return "Master System"; ++ ++ case RC_CONSOLE_MEGA_DRIVE: ++ return "Sega Genesis"; ++ ++ case RC_CONSOLE_MEGADUCK: ++ return "Mega Duck"; ++ ++ case RC_CONSOLE_MS_DOS: ++ return "MS-DOS"; ++ ++ case RC_CONSOLE_MSX: ++ return "MSX"; ++ ++ case RC_CONSOLE_NEO_GEO_CD: ++ return "Neo Geo CD"; ++ ++ case RC_CONSOLE_NEOGEO_POCKET: ++ return "Neo Geo Pocket"; ++ ++ case RC_CONSOLE_NINTENDO: ++ return "Nintendo Entertainment System"; ++ ++ case RC_CONSOLE_NINTENDO_64: ++ return "Nintendo 64"; ++ ++ case RC_CONSOLE_NINTENDO_DS: ++ return "Nintendo DS"; ++ ++ case RC_CONSOLE_NINTENDO_DSI: ++ return "Nintendo DSi"; ++ ++ case RC_CONSOLE_NINTENDO_3DS: ++ return "Nintendo 3DS"; ++ ++ case RC_CONSOLE_NOKIA_NGAGE: ++ return "Nokia N-Gage"; ++ ++ case RC_CONSOLE_ORIC: ++ return "Oric"; ++ ++ case RC_CONSOLE_PC6000: ++ return "PC-6000"; ++ ++ case RC_CONSOLE_PC8800: ++ return "PC-8000/8800"; ++ ++ case RC_CONSOLE_PC9800: ++ return "PC-9800"; ++ ++ case RC_CONSOLE_PCFX: ++ return "PC-FX"; ++ ++ case RC_CONSOLE_PC_ENGINE: ++ return "PC Engine"; ++ ++ case RC_CONSOLE_PC_ENGINE_CD: ++ return "PC Engine CD"; ++ ++ case RC_CONSOLE_PLAYSTATION: ++ return "PlayStation"; ++ ++ case RC_CONSOLE_PLAYSTATION_2: ++ return "PlayStation 2"; ++ ++ case RC_CONSOLE_PSP: ++ return "PlayStation Portable"; ++ ++ case RC_CONSOLE_POKEMON_MINI: ++ return "Pokemon Mini"; ++ ++ case RC_CONSOLE_SEGA_32X: ++ return "Sega 32X"; ++ ++ case RC_CONSOLE_SEGA_CD: ++ return "Sega CD"; ++ ++ case RC_CONSOLE_PICO: ++ return "Sega Pico"; ++ ++ case RC_CONSOLE_SATURN: ++ return "Sega Saturn"; ++ ++ case RC_CONSOLE_SG1000: ++ return "SG-1000"; ++ ++ case RC_CONSOLE_SHARPX1: ++ return "Sharp X1"; ++ ++ case RC_CONSOLE_STANDALONE: ++ return "Standalone"; ++ ++ case RC_CONSOLE_SUPER_NINTENDO: ++ return "Super Nintendo Entertainment System"; ++ ++ case RC_CONSOLE_SUPER_CASSETTEVISION: ++ return "Super CassetteVision"; ++ ++ case RC_CONSOLE_SUPERVISION: ++ return "Watara Supervision"; ++ ++ case RC_CONSOLE_THOMSONTO8: ++ return "Thomson TO8"; ++ ++ case RC_CONSOLE_TI83: ++ return "TI-83"; ++ ++ case RC_CONSOLE_TIC80: ++ return "TIC-80"; ++ ++ case RC_CONSOLE_UZEBOX: ++ return "Uzebox"; ++ ++ case RC_CONSOLE_VECTREX: ++ return "Vectrex"; ++ ++ case RC_CONSOLE_VIC20: ++ return "VIC-20"; ++ ++ case RC_CONSOLE_VIRTUAL_BOY: ++ return "Virtual Boy"; ++ ++ case RC_CONSOLE_WASM4: ++ return "WASM-4"; ++ ++ case RC_CONSOLE_WII: ++ return "Wii"; ++ ++ case RC_CONSOLE_WII_U: ++ return "Wii-U"; ++ ++ case RC_CONSOLE_WONDERSWAN: ++ return "WonderSwan"; ++ ++ case RC_CONSOLE_X68K: ++ return "X68K"; ++ ++ case RC_CONSOLE_XBOX: ++ return "XBOX"; ++ ++ case RC_CONSOLE_ZEEBO: ++ return "Zeebo"; ++ ++ case RC_CONSOLE_ZX81: ++ return "ZX-81"; ++ ++ case RC_CONSOLE_ZX_SPECTRUM: ++ return "ZX Spectrum"; ++ ++ default: ++ return "Unknown"; ++ } ++} ++ ++/* ===== 3DO ===== */ ++/* http://www.arcaderestoration.com/memorymap/48/3DO+Bios.aspx */ ++/* NOTE: the Opera core attempts to expose the NVRAM as RETRO_SAVE_RAM, but the 3DO documentation ++ * says that applications should only access NVRAM through API calls as it's shared across mulitple ++ * games. This suggests that even if the core does expose it, it may change depending on which other ++ * games the user has played - so ignore it. ++ */ ++static const rc_memory_region_t _rc_memory_regions_3do[] = { ++ { 0x000000U, 0x1FFFFFU, 0x000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Main RAM" }, ++}; ++static const rc_memory_regions_t rc_memory_regions_3do = { _rc_memory_regions_3do, 1 }; ++ ++/* ===== Amiga ===== */ ++/* http://amigadev.elowar.com/read/ADCD_2.1/Hardware_Manual_guide/node00D3.html */ ++static const rc_memory_region_t _rc_memory_regions_amiga[] = { ++ { 0x000000U, 0x07FFFFU, 0x000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Main RAM" }, /* 512KB main RAM */ ++ { 0x080000U, 0x0FFFFFU, 0x080000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Extended RAM" }, /* 512KB extended RAM */ ++}; ++static const rc_memory_regions_t rc_memory_regions_amiga = { _rc_memory_regions_amiga, 2 }; ++ ++/* ===== Amstrad CPC ===== */ ++/* http://www.cpcalive.com/docs/amstrad_cpc_6128_memory_map.html */ ++/* https://www.cpcwiki.eu/index.php/File:AWMG_page151.jpg */ ++/* The original CPC only had 64KB of memory, but the newer model has 128KB (expandable to 576KB) */ ++/* https://www.grimware.org/doku.php/documentations/devices/gatearraydo=export_xhtml#mmr */ ++static const rc_memory_region_t _rc_memory_regions_amstrad_pc[] = { ++ { 0x000000U, 0x00003FU, 0x000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Firmware" }, ++ { 0x000040U, 0x00B0FFU, 0x000040U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, ++ { 0x00B100U, 0x00BFFFU, 0x00B100U, RC_MEMORY_TYPE_SYSTEM_RAM, "Stack and Firmware Data" }, ++ { 0x00C000U, 0x00FFFFU, 0x00C000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Screen Memory" }, ++ { 0x010000U, 0x08FFFFU, 0x010000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Extended RAM" }, ++}; ++static const rc_memory_regions_t rc_memory_regions_amstrad_pc = { _rc_memory_regions_amstrad_pc, 5 }; ++ ++/* ===== Apple II ===== */ ++static const rc_memory_region_t _rc_memory_regions_appleii[] = { ++ { 0x000000U, 0x00FFFFU, 0x000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Main RAM" }, ++ { 0x010000U, 0x01FFFFU, 0x010000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Auxillary RAM" } ++}; ++static const rc_memory_regions_t rc_memory_regions_appleii = { _rc_memory_regions_appleii, 2 }; ++ ++/* ===== Arcadia 2001 ===== */ ++/* https://amigan.yatho.com/a-coding.txt */ ++/* RAM banks 1 and 2 only exist on some variant models - no game actually uses them */ ++static const rc_memory_region_t _rc_memory_regions_arcadia_2001[] = { ++ { 0x000000U, 0x0000FFU, 0x001800U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, /* RAM bank 3 */ ++ { 0x000100U, 0x0001FFU, 0x001900U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "I/O Area" }, ++ { 0x000200U, 0x0002FFU, 0x001A00U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, /* RAM bank 4 */ ++}; ++static const rc_memory_regions_t rc_memory_regions_arcadia_2001 = { _rc_memory_regions_arcadia_2001, 3 }; ++ ++/* ===== Arduboy ===== */ ++/* https://scienceprog.com/avr-microcontroller-memory-map/ (Atmega32) */ ++static const rc_memory_region_t _rc_memory_regions_arduboy[] = { ++ { 0x000000U, 0x0000FFU, 0x00000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Registers" }, ++ /* https://www.dailydot.com/debug/arduboy-kickstarter/ 2.5KB of RAM */ ++ /* https://github.com/buserror/simavr/blob/1d227277b3d0039f9faef9ea62880ca3051b14f8/simavr/cores/avr/iom32u4.h#L1444-L1445 */ ++ { 0x000100U, 0x000AFFU, 0x00000100U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, ++ /* 1KB of EEPROM https://github.com/libretro/arduous/blob/93e1a6289b42ef48de1fcfb96443981725955ad0/src/arduous/arduous.cpp#L453-L455 ++ * https://github.com/buserror/simavr/blob/1d227277b3d0039f9faef9ea62880ca3051b14f8/simavr/cores/avr/iom32u4.h#L1450 */ ++ /* EEPROM has it's own addressing scheme starting at $0000. I've chosen to virtualize the address ++ * at $80000000 to avoid a conflict */ ++ { 0x000B00U, 0x000EFFU, 0x80000000U, RC_MEMORY_TYPE_SAVE_RAM, "EEPROM" } ++}; ++static const rc_memory_regions_t rc_memory_regions_arduboy = { _rc_memory_regions_arduboy, 3 }; ++ ++/* ===== Atari 2600 ===== */ ++static const rc_memory_region_t _rc_memory_regions_atari2600[] = { ++ { 0x000000U, 0x00007FU, 0x000080U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" } ++}; ++static const rc_memory_regions_t rc_memory_regions_atari2600 = { _rc_memory_regions_atari2600, 1 }; ++ ++/* ===== Atari 7800 ===== */ ++/* http://www.atarihq.com/danb/files/78map.txt */ ++/* http://pdf.textfiles.com/technical/7800_devkit.pdf */ ++static const rc_memory_region_t _rc_memory_regions_atari7800[] = { ++ { 0x000000U, 0x0017FFU, 0x000000U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "Hardware Interface" }, ++ { 0x001800U, 0x0027FFU, 0x001800U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, ++ { 0x002800U, 0x002FFFU, 0x002800U, RC_MEMORY_TYPE_VIRTUAL_RAM, "Mirrored RAM" }, ++ { 0x003000U, 0x0037FFU, 0x003000U, RC_MEMORY_TYPE_VIRTUAL_RAM, "Mirrored RAM" }, ++ { 0x003800U, 0x003FFFU, 0x003800U, RC_MEMORY_TYPE_VIRTUAL_RAM, "Mirrored RAM" }, ++ { 0x004000U, 0x007FFFU, 0x004000U, RC_MEMORY_TYPE_SAVE_RAM, "Cartridge RAM" }, ++ { 0x008000U, 0x00FFFFU, 0x008000U, RC_MEMORY_TYPE_READONLY, "Cartridge ROM" } ++}; ++static const rc_memory_regions_t rc_memory_regions_atari7800 = { _rc_memory_regions_atari7800, 7 }; ++ ++/* ===== Atari Jaguar ===== */ ++/* https://www.mulle-kybernetik.com/jagdox/memorymap.html */ ++static const rc_memory_region_t _rc_memory_regions_atari_jaguar[] = { ++ { 0x000000U, 0x1FFFFFU, 0x000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" } ++}; ++static const rc_memory_regions_t rc_memory_regions_atari_jaguar = { _rc_memory_regions_atari_jaguar, 1 }; ++ ++/* ===== Atari Lynx ===== */ ++/* http://www.retroisle.com/atari/lynx/Technical/Programming/lynxprgdumm.php */ ++static const rc_memory_region_t _rc_memory_regions_atari_lynx[] = { ++ { 0x000000U, 0x0000FFU, 0x000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Zero Page" }, ++ { 0x000100U, 0x0001FFU, 0x000100U, RC_MEMORY_TYPE_SYSTEM_RAM, "Stack" }, ++ { 0x000200U, 0x00FBFFU, 0x000200U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, ++ { 0x00FC00U, 0x00FCFFU, 0x00FC00U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "SUZY hardware access" }, ++ { 0x00FD00U, 0x00FDFFU, 0x00FD00U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "MIKEY hardware access" }, ++ { 0x00FE00U, 0x00FFF7U, 0x00FE00U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "Boot ROM" }, ++ { 0x00FFF8U, 0x00FFFFU, 0x00FFF8U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "Hardware vectors" } ++}; ++static const rc_memory_regions_t rc_memory_regions_atari_lynx = { _rc_memory_regions_atari_lynx, 7 }; ++ ++/* ===== ColecoVision ===== */ ++static const rc_memory_region_t _rc_memory_regions_colecovision[] = { ++ /* "System RAM" refers to the main RAM at 0x6000-0x63FF. However, this RAM might not always be visible. ++ * If the Super Game Module (SGM) is active, then it might overlay its own RAM at 0x0000-0x1FFF and 0x2000-0x7FFF. ++ * These positions overlap the BIOS and System RAM, therefore we use virtual addresses for these memory spaces. */ ++ { 0x000000U, 0x0003FFU, 0x006000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, ++ { 0x000400U, 0x0023FFU, 0x010000U, RC_MEMORY_TYPE_SYSTEM_RAM, "SGM Low RAM" }, /* Normally situated at 0x0000-0x1FFF, which overlaps the BIOS */ ++ { 0x002400U, 0x0083FFU, 0x012000U, RC_MEMORY_TYPE_SYSTEM_RAM, "SGM High RAM" } /* Normally situated at 0x2000-0x7FFF, which overlaps System RAM */ ++}; ++static const rc_memory_regions_t rc_memory_regions_colecovision = { _rc_memory_regions_colecovision, 3 }; ++ ++/* ===== Commodore 64 ===== */ ++/* https://www.c64-wiki.com/wiki/Memory_Map */ ++/* https://sta.c64.org/cbm64mem.html */ ++/* NOTE: Several blocks of C64 memory can be bank-switched for ROM data (see https://www.c64-wiki.com/wiki/Bank_Switching). ++ * Achievement triggers rely on values changing, so we don't really need to look at the ROM data. ++ * The achievement logic assumes the RAM data is always present in the bankable blocks. As such, ++ * clients providing memory to achievements should always return the RAM values at the queried address. */ ++static const rc_memory_region_t _rc_memory_regions_c64[] = { ++ { 0x000000U, 0x0003FFU, 0x000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Kernel RAM" }, ++ { 0x000400U, 0x0007FFU, 0x000400U, RC_MEMORY_TYPE_VIDEO_RAM, "Screen RAM" }, ++ { 0x000800U, 0x009FFFU, 0x000800U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, /* BASIC area. $8000-$9FFF can bank to cartridge ROM */ ++ { 0x00A000U, 0x00BFFFU, 0x00A000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, /* can bank to BASIC ROM or cartridge ROM */ ++ { 0x00C000U, 0x00CFFFU, 0x00C000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, ++ { 0x00D000U, 0x00DFFFU, 0x00D000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, /* can bank to I/O Area or character ROM */ ++ { 0x00E000U, 0x00FFFFU, 0x00E000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, /* can bank to kernel ROM */ ++}; ++static const rc_memory_regions_t rc_memory_regions_c64 = { _rc_memory_regions_c64, 7 }; ++ ++/* ===== Dreamcast ===== */ ++/* http://archiv.sega-dc.de/munkeechuff/hardware/Memory.html */ ++static const rc_memory_region_t _rc_memory_regions_dreamcast[] = { ++ { 0x00000000U, 0x00FFFFFFU, 0x0C000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" } ++}; ++static const rc_memory_regions_t rc_memory_regions_dreamcast = { _rc_memory_regions_dreamcast, 1 }; ++ ++/* ===== Elektor TV Games Computer ===== */ ++/* https://amigan.yatho.com/e-coding.txt */ ++static const rc_memory_region_t _rc_memory_regions_elektor_tv_games[] = { ++ { 0x000000U, 0x0013FFU, 0x000800U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, ++ { 0x001400U, 0x0014FFU, 0x001C00U, RC_MEMORY_TYPE_UNUSED, "Unused" }, /* mirror of $1D00-$1DFF */ ++ { 0x001500U, 0x0016FFU, 0x001D00U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "I/O Area" }, /* two 256-byte I/O areas */ ++ { 0x001700U, 0x0017FFU, 0x001F00U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, ++}; ++static const rc_memory_regions_t rc_memory_regions_elektor_tv_games = { _rc_memory_regions_elektor_tv_games, 4 }; ++ ++/* ===== Fairchild Channel F ===== */ ++static const rc_memory_region_t _rc_memory_regions_fairchild_channel_f[] = { ++ /* "System RAM" is actually just a bunch of registers internal to CPU so all carts have it. ++ * "Video RAM" is part of the console so it's always available but it is write-only by the ROMs. ++ * "Cartridge RAM" is the cart BUS. Most carts only have ROMs on this bus. Exception are ++ * German Schach and homebrew carts that have 2K of RAM there in addition to ROM. ++ * "F2102 RAM" is used by Maze for 1K of RAM. ++ * https://discord.com/channels/310192285306454017/645777658319208448/967001438087708714 */ ++ { 0x00000000U, 0x0000003FU, 0x00100000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, ++ { 0x00000040U, 0x0000083FU, 0x00300000U, RC_MEMORY_TYPE_VIDEO_RAM, "Video RAM" }, ++ { 0x00000840U, 0x0001083FU, 0x00000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Cartridge RAM" }, ++ { 0x00010840U, 0x00010C3FU, 0x00200000U, RC_MEMORY_TYPE_SYSTEM_RAM, "F2102 RAM" } ++}; ++static const rc_memory_regions_t rc_memory_regions_fairchild_channel_f = { _rc_memory_regions_fairchild_channel_f, 4 }; ++ ++/* ===== Famicon Disk System ===== */ ++/* https://fms.komkon.org/EMUL8/NES.html */ ++static const rc_memory_region_t _rc_memory_regions_famicom_disk_system[] = { ++ { 0x0000U, 0x07FFU, 0x0000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, ++ { 0x0800U, 0x0FFFU, 0x0000U, RC_MEMORY_TYPE_VIRTUAL_RAM, "Mirror RAM" }, /* duplicates memory from $0000-$07FF */ ++ { 0x1000U, 0x17FFU, 0x0000U, RC_MEMORY_TYPE_VIRTUAL_RAM, "Mirror RAM" }, /* duplicates memory from $0000-$07FF */ ++ { 0x1800U, 0x1FFFU, 0x0000U, RC_MEMORY_TYPE_VIRTUAL_RAM, "Mirror RAM" }, /* duplicates memory from $0000-$07FF */ ++ { 0x2000U, 0x2007U, 0x2000U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "PPU Register" }, ++ { 0x2008U, 0x3FFFU, 0x2008U, RC_MEMORY_TYPE_VIRTUAL_RAM, "Mirrored PPU Register" }, /* repeats every 8 bytes */ ++ { 0x4000U, 0x4017U, 0x4000U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "APU and I/O register" }, ++ { 0x4018U, 0x401FU, 0x4018U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "APU and I/O test register" }, ++ { 0x4020U, 0x40FFU, 0x4020U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "FDS I/O registers"}, ++ { 0x4100U, 0x5FFFU, 0x4100U, RC_MEMORY_TYPE_READONLY, "Cartridge data"}, /* varies by mapper */ ++ { 0x6000U, 0xDFFFU, 0x6000U, RC_MEMORY_TYPE_SYSTEM_RAM, "FDS RAM"}, ++ { 0xE000U, 0xFFFFU, 0xE000U, RC_MEMORY_TYPE_READONLY, "FDS BIOS ROM"}, ++}; ++static const rc_memory_regions_t rc_memory_regions_famicom_disk_system = { _rc_memory_regions_famicom_disk_system, 12 }; ++ ++/* ===== GameBoy / MegaDuck ===== */ ++static const rc_memory_region_t _rc_memory_regions_gameboy[] = { ++ { 0x000000U, 0x0000FFU, 0x000000U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "Interrupt vector" }, ++ { 0x000100U, 0x00014FU, 0x000100U, RC_MEMORY_TYPE_READONLY, "Cartridge header" }, ++ { 0x000150U, 0x003FFFU, 0x000150U, RC_MEMORY_TYPE_READONLY, "Cartridge ROM (fixed)" }, /* bank 0 */ ++ { 0x004000U, 0x007FFFU, 0x004000U, RC_MEMORY_TYPE_READONLY, "Cartridge ROM (paged)" }, /* bank 1-XX (switchable) */ ++ { 0x008000U, 0x0097FFU, 0x008000U, RC_MEMORY_TYPE_VIDEO_RAM, "Tile RAM" }, ++ { 0x009800U, 0x009BFFU, 0x009800U, RC_MEMORY_TYPE_VIDEO_RAM, "BG1 map data" }, ++ { 0x009C00U, 0x009FFFU, 0x009C00U, RC_MEMORY_TYPE_VIDEO_RAM, "BG2 map data" }, ++ { 0x00A000U, 0x00BFFFU, 0x00A000U, RC_MEMORY_TYPE_SAVE_RAM, "Cartridge RAM (bank 0)"}, ++ { 0x00C000U, 0x00CFFFU, 0x00C000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM (fixed)" }, ++ { 0x00D000U, 0x00DFFFU, 0x00D000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM (fixed)" }, ++ { 0x00E000U, 0x00FDFFU, 0x00C000U, RC_MEMORY_TYPE_VIRTUAL_RAM, "Echo RAM" }, ++ { 0x00FE00U, 0x00FE9FU, 0x00FE00U, RC_MEMORY_TYPE_VIDEO_RAM, "Sprite RAM"}, ++ { 0x00FEA0U, 0x00FEFFU, 0x00FEA0U, RC_MEMORY_TYPE_UNUSED, ""}, ++ { 0x00FF00U, 0x00FF7FU, 0x00FF00U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "Hardware I/O"}, ++ { 0x00FF80U, 0x00FFFEU, 0x00FF80U, RC_MEMORY_TYPE_SYSTEM_RAM, "Quick RAM"}, ++ { 0x00FFFFU, 0x00FFFFU, 0x00FFFFU, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "Interrupt enable"}, ++ ++ /* GameBoy's cartridge RAM may have a total of up to 16 banks that can be paged through $A000-$BFFF. ++ * It is desirable to always have access to these extra banks. We do this by expecting the extra banks ++ * to be addressable at addresses not supported by the native system. 0x10000-0x16000 is reserved ++ * for the extra banks of system memory that are exclusive to the GameBoy Color. */ ++ { 0x010000U, 0x015FFFU, 0x010000U, RC_MEMORY_TYPE_UNUSED, "Unused (GameBoy Color exclusive)" }, ++ { 0x016000U, 0x033FFFU, 0x016000U, RC_MEMORY_TYPE_SAVE_RAM, "Cartridge RAM (banks 1-15)" }, ++}; ++static const rc_memory_regions_t rc_memory_regions_megaduck = { _rc_memory_regions_gameboy, 16 }; ++static const rc_memory_regions_t rc_memory_regions_gameboy = { _rc_memory_regions_gameboy, 18 }; ++ ++/* ===== GameBoy Color ===== */ ++static const rc_memory_region_t _rc_memory_regions_gameboy_color[] = { ++ { 0x000000U, 0x0000FFU, 0x000000U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "Interrupt vector" }, ++ { 0x000100U, 0x00014FU, 0x000100U, RC_MEMORY_TYPE_READONLY, "Cartridge header" }, ++ { 0x000150U, 0x003FFFU, 0x000150U, RC_MEMORY_TYPE_READONLY, "Cartridge ROM (fixed)" }, /* bank 0 */ ++ { 0x004000U, 0x007FFFU, 0x004000U, RC_MEMORY_TYPE_READONLY, "Cartridge ROM (paged)" }, /* bank 1-XX (switchable) */ ++ { 0x008000U, 0x0097FFU, 0x008000U, RC_MEMORY_TYPE_VIDEO_RAM, "Tile RAM" }, ++ { 0x009800U, 0x009BFFU, 0x009800U, RC_MEMORY_TYPE_VIDEO_RAM, "BG1 map data" }, ++ { 0x009C00U, 0x009FFFU, 0x009C00U, RC_MEMORY_TYPE_VIDEO_RAM, "BG2 map data" }, ++ { 0x00A000U, 0x00BFFFU, 0x00A000U, RC_MEMORY_TYPE_SAVE_RAM, "Cartridge RAM (bank 0)"}, ++ { 0x00C000U, 0x00CFFFU, 0x00C000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM (bank 0)" }, ++ { 0x00D000U, 0x00DFFFU, 0x00D000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM (bank 1)" }, ++ { 0x00E000U, 0x00FDFFU, 0x00C000U, RC_MEMORY_TYPE_VIRTUAL_RAM, "Echo RAM" }, ++ { 0x00FE00U, 0x00FE9FU, 0x00FE00U, RC_MEMORY_TYPE_VIDEO_RAM, "Sprite RAM"}, ++ { 0x00FEA0U, 0x00FEFFU, 0x00FEA0U, RC_MEMORY_TYPE_UNUSED, ""}, ++ { 0x00FF00U, 0x00FF7FU, 0x00FF00U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "Hardware I/O"}, ++ { 0x00FF80U, 0x00FFFEU, 0x00FF80U, RC_MEMORY_TYPE_SYSTEM_RAM, "Quick RAM"}, ++ { 0x00FFFFU, 0x00FFFFU, 0x00FFFFU, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "Interrupt enable"}, ++ ++ /* GameBoy Color provides 6 extra banks of system memory that can be paged out through the $D000-$DFFF, ++ * and the cartridge RAM may have a total of up to 16 banks page through $A000-$BFFF. ++ * It is desirable to always have access to these extra banks. We do this by expecting the extra banks ++ * to be addressable at addresses not supported by the native system. */ ++ { 0x010000U, 0x015FFFU, 0x010000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM (banks 2-7)" }, ++ { 0x016000U, 0x033FFFU, 0x016000U, RC_MEMORY_TYPE_SAVE_RAM, "Cartridge RAM (banks 1-15)" }, ++}; ++static const rc_memory_regions_t rc_memory_regions_gameboy_color = { _rc_memory_regions_gameboy_color, 18 }; ++ ++/* ===== GameBoy Advance ===== */ ++/* http://problemkaputt.de/gbatek-gba-memory-map.htm */ ++static const rc_memory_region_t _rc_memory_regions_gameboy_advance[] = { ++ { 0x000000U, 0x007FFFU, 0x03000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, /* 32KB Internal Work RAM */ ++ { 0x008000U, 0x047FFFU, 0x02000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, /* 256KB External Work RAM */ ++ { 0x048000U, 0x057FFFU, 0x0E000000U, RC_MEMORY_TYPE_SAVE_RAM, "Save RAM" } /* 64KB Game Pak SRAM */ ++}; ++static const rc_memory_regions_t rc_memory_regions_gameboy_advance = { _rc_memory_regions_gameboy_advance, 3 }; ++ ++/* ===== GameCube ===== */ ++/* https://wiibrew.org/wiki/Memory_map */ ++static const rc_memory_region_t _rc_memory_regions_gamecube[] = { ++ { 0x00000000U, 0x017FFFFF, 0x80000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" } ++}; ++static const rc_memory_regions_t rc_memory_regions_gamecube = { _rc_memory_regions_gamecube, 1 }; ++ ++/* ===== Game Gear ===== */ ++/* https://www.smspower.org/Development/MemoryMap */ ++/* https://www.smspower.org/Development/Mappers */ ++static const rc_memory_region_t _rc_memory_regions_game_gear[] = { ++ { 0x000000U, 0x001FFFU, 0x00C000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, ++ /* GG/SMS have various possible mappings for cartridge memory depending on the mapper used. ++ * However, these ultimately do not map all of their memory at once, typically requiring banking. ++ * Thus, the "real address" used is just a virtual address mapping all cartridge memory in one contiguous block. ++ * Note that this may possibly refer to non-battery backed "extended RAM" so this isn't strictly RC_MEMORY_TYPE_SAVE_RAM. ++ * libretro cores expose "extended RAM" as RETRO_MEMORY_SAVE_RAM regardless however. ++ */ ++ { 0x002000U, 0x009FFFU, 0x010000U, RC_MEMORY_TYPE_SAVE_RAM, "Cartridge RAM" } ++}; ++static const rc_memory_regions_t rc_memory_regions_game_gear = { _rc_memory_regions_game_gear, 2 }; ++ ++/* ===== Intellivision ===== */ ++/* http://wiki.intellivision.us/index.php/Memory_Map */ ++/* NOTE: Intellivision memory addresses point at 16-bit values. FreeIntv exposes them as little-endian ++ * 32-bit values. As such, the addresses are off by a factor of 4 _and_ the data is only where we ++ * expect it on little-endian systems. ++ */ ++static const rc_memory_region_t _rc_memory_regions_intellivision[] = { ++ /* For backwards compatibility, register a 128-byte chunk of video RAM so the system memory ++ * will start at $0080. $0000-$007F previously tried to map to the STIC video registers as ++ * RETRO_MEMORY_VIDEO_RAM, and FreeIntv didn't expose any RETRO_MEMORY_VIDEO_RAM, so the first ++ * byte of RETRO_MEMORY_SYSTEM_RAM was registered at $0080. The data at $0080 is actually the ++ * STIC registers (4 bytes each), so we need to provide an arbitrary 128-byte padding that ++ * claims to be video RAM to ensure the system RAM ends up at the right address. ++ */ ++ { 0x000000U, 0x00007FU, 0xFFFFFFU, RC_MEMORY_TYPE_VIDEO_RAM, "" }, ++ ++ /* RetroAchievements address = real address x4 + 0x80. ++ * These all have to map to RETRO_MEMORY_SYSTEM_RAM (even the video-related fields) as the ++ * entire block is exposed as a single entity by FreeIntv */ ++ ++ /* $0000-$007F: STIC registers, $0040-$007F are readonly */ ++ { 0x000080U, 0x00027FU, 0x000000U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "STIC Registers" }, ++ /* $0080-$00FF: unused */ ++ { 0x000280U, 0x00047FU, 0x000080U, RC_MEMORY_TYPE_UNUSED, "" }, ++ /* $0100-$035F: system RAM, $0100-$01EF is scratch memory and only 8-bits per address */ ++ { 0x000480U, 0x000DFFU, 0x000100U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, ++ /* $0360-$03FF: unused */ ++ { 0x000E00U, 0x00107FU, 0x000360U, RC_MEMORY_TYPE_UNUSED, "" }, ++ /* $0400-$0FFF: cartridge RAM */ ++ { 0x001080U, 0x00407FU, 0x000400U, RC_MEMORY_TYPE_SYSTEM_RAM, "Cartridge RAM" }, ++ /* $1000-$1FFF: unused */ ++ { 0x004080U, 0x00807FU, 0x001000U, RC_MEMORY_TYPE_UNUSED, "" }, ++ /* $2000-$2FFF: cartridge RAM */ ++ { 0x008080U, 0x00C07FU, 0x002000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Cartridge RAM" }, ++ /* $3000-$3FFF: video RAM */ ++ { 0x00C080U, 0x01007FU, 0x003000U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "Video RAM" }, ++ /* $4000-$FFFF: cartridge RAM */ ++ { 0x010080U, 0x04007FU, 0x004000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Cartridge RAM" }, ++}; ++static const rc_memory_regions_t rc_memory_regions_intellivision = { _rc_memory_regions_intellivision, 10 }; ++ ++/* ===== Interton VC 4000 ===== */ ++/* https://amigan.yatho.com/i-coding.txt */ ++/* Cartridge RAM is not persisted, it's just expanded storage */ ++static const rc_memory_region_t _rc_memory_regions_interton_vc_4000[] = { ++ { 0x000000U, 0x0003FFU, 0x001800U, RC_MEMORY_TYPE_SYSTEM_RAM, "Cartridge RAM" }, ++ { 0x000400U, 0x0004FFU, 0x001E00U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "I/O Area" }, ++ { 0x000500U, 0x0005FFU, 0x001F00U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, ++}; ++static const rc_memory_regions_t rc_memory_regions_interton_vc_4000 = { _rc_memory_regions_interton_vc_4000, 3 }; ++ ++/* ===== Magnavox Odyssey 2 ===== */ ++/* https://sudonull.com/post/76885-Architecture-and-programming-Philips-Videopac-Magnavox-Odyssey-2 */ ++static const rc_memory_region_t _rc_memory_regions_magnavox_odyssey_2[] = { ++ /* Internal and external RAMs are reachable using unique instructions. ++ * The real addresses provided are virtual and for mapping purposes only. */ ++ { 0x000000U, 0x00003FU, 0x000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Internal RAM" }, ++ { 0x000040U, 0x00013FU, 0x000040U, RC_MEMORY_TYPE_SYSTEM_RAM, "External RAM" } ++}; ++static const rc_memory_regions_t rc_memory_regions_magnavox_odyssey_2 = { _rc_memory_regions_magnavox_odyssey_2, 2 }; ++ ++/* ===== Master System ===== */ ++/* https://www.smspower.org/Development/MemoryMap */ ++/* https://www.smspower.org/Development/Mappers */ ++static const rc_memory_region_t _rc_memory_regions_master_system[] = { ++ { 0x000000U, 0x001FFFU, 0x00C000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, ++ /* GG/SMS have various possible mappings for cartridge memory depending on the mapper used. ++ * However, these ultimately do not map all of their memory at once, typically requiring banking. ++ * Thus, the "real address" used is just a virtual address mapping all cartridge memory in one contiguous block. ++ * Note that this may possibly refer to non-battery backed "extended RAM" so this isn't strictly RC_MEMORY_TYPE_SAVE_RAM. ++ * libretro cores expose "extended RAM" as RETRO_MEMORY_SAVE_RAM regardless however. ++ */ ++ { 0x002000U, 0x009FFFU, 0x010000U, RC_MEMORY_TYPE_SAVE_RAM, "Cartridge RAM" } ++}; ++static const rc_memory_regions_t rc_memory_regions_master_system = { _rc_memory_regions_master_system, 2 }; ++ ++/* ===== MegaDrive (Genesis) ===== */ ++/* https://www.smspower.org/Development/MemoryMap */ ++static const rc_memory_region_t _rc_memory_regions_megadrive[] = { ++ { 0x000000U, 0x00FFFFU, 0xFF0000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, ++ { 0x010000U, 0x01FFFFU, 0x000000U, RC_MEMORY_TYPE_SAVE_RAM, "Cartridge RAM" } ++}; ++static const rc_memory_regions_t rc_memory_regions_megadrive = { _rc_memory_regions_megadrive, 2 }; ++ ++/* ===== MegaDrive 32X (Genesis 32X) ===== */ ++/* http://devster.monkeeh.com/sega/32xguide1.txt */ ++static const rc_memory_region_t _rc_memory_regions_megadrive_32x[] = { ++ { 0x000000U, 0x00FFFFU, 0x00FF0000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, /* Main MegaDrive RAM */ ++ { 0x010000U, 0x04FFFFU, 0x06000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "32X RAM"}, /* Additional 32X RAM */ ++ { 0x050000U, 0x05FFFFU, 0x00000000U, RC_MEMORY_TYPE_SAVE_RAM, "Cartridge RAM" } ++}; ++static const rc_memory_regions_t rc_memory_regions_megadrive_32x = { _rc_memory_regions_megadrive_32x, 3 }; ++ ++/* ===== MSX ===== */ ++/* https://www.msx.org/wiki/The_Memory */ ++/* MSX only has 64KB of addressable RAM, of which 32KB is reserved for the system/BIOS. ++ * However, the system has up to 512KB of RAM, which is paged into the addressable RAM ++ * We expect the raw RAM to be exposed, rather than force the devs to worry about the ++ * paging system. The entire RAM is expected to appear starting at $10000, which is not ++ * addressable by the system itself. ++ */ ++static const rc_memory_region_t _rc_memory_regions_msx[] = { ++ { 0x000000U, 0x07FFFFU, 0x010000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, ++}; ++static const rc_memory_regions_t rc_memory_regions_msx = { _rc_memory_regions_msx, 1 }; ++ ++/* ===== MS DOS ===== */ ++static const rc_memory_region_t _rc_memory_regions_ms_dos[] = { ++ /* DOS emulators split the 640 KB conventional memory into two regions. ++ * First the part of the conventional memory given to the running game at $000000. ++ * The part of the conventional memory containing DOS and BIOS controlled memory ++ * is at $100000. The length of these can vary depending on the hardware ++ * and DOS version (or emulated DOS shell). ++ * These first two regions will only ever total to 640 KB but the regions map ++ * to 1 MB bounds to make resulting memory addresses more readable. ++ * When emulating a game not under DOS (so called 'PC Booter' games), the entirety ++ * of the 640 KB conventional memory block will be at $000000. ++ */ ++ { 0x00000000U, 0x0009FFFFU, 0x00000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Game Conventional Memory" }, ++ { 0x000A0000U, 0x000FFFFFU, 0x000A0000U, RC_MEMORY_TYPE_UNUSED, "Padding to align OS Conventional Memory" }, ++ { 0x00100000U, 0x0019FFFFU, 0x00100000U, RC_MEMORY_TYPE_SYSTEM_RAM, "OS Conventional Memory" }, ++ { 0x001A0000U, 0x001FFFFFU, 0x001A0000U, RC_MEMORY_TYPE_UNUSED, "Padding to align Expanded Memory" }, ++ /* Last is all the expanded memory which for now we map up to 64 MB which should be ++ * enough for the games we want to cover. An emulator might emulate more than that. ++ */ ++ { 0x00200000U, 0x041FFFFFU, 0x00200000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Expanded Memory" } ++}; ++static const rc_memory_regions_t rc_memory_regions_ms_dos = { _rc_memory_regions_ms_dos, 5 }; ++ ++/* ===== Neo Geo Pocket ===== */ ++/* http://neopocott.emuunlim.com/docs/tech-11.txt */ ++static const rc_memory_region_t _rc_memory_regions_neo_geo_pocket[] = { ++ /* The docs suggest there's Work RAM exposed from $0000-$6FFF, Sound RAM from $7000-$7FFF, and Video ++ * RAM from $8000-$BFFF, but both MednafenNGP and FBNeo only expose system RAM from $4000-$7FFF */ ++ { 0x000000U, 0x003FFFU, 0x004000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" } ++}; ++static const rc_memory_regions_t rc_memory_regions_neo_geo_pocket = { _rc_memory_regions_neo_geo_pocket, 1 }; ++ ++/* ===== Neo Geo CD ===== */ ++/* https://wiki.neogeodev.org/index.php?title=68k_memory_map */ ++/* NeoCD exposes $000000-$1FFFFF as System RAM, but it seems like only the WORKRAM section is used. ++ * This is consistent with http://www.hardmvs.fr/manuals/NeoGeoProgrammersGuide.pdf (page25), which says: ++ * ++ * Furthermore, the NEO-GEO provides addresses 100000H-10FFFFH as a work area, out of which the ++ * addresses 10F300H-10FFFFH are reserved exclusively for use by the system program. Therefore, ++ * every game is to use addresses 100000H-10F2FFH. ++ * ++ * Also note that PRG files (game ROM) can be loaded anywhere else in the $000000-$1FFFFF range. ++ * AoF3 illustrates this pretty clearly: https://wiki.neogeodev.org/index.php?title=IPL_file ++ * ++ * PROG_CD.PRG,0,0 ++ * PROG_CDX.PRG,0,058000 ++ * CNV_NM.PRG,0,0C0000 ++ * FIX_DATA.PRG,0,0FD000 ++ * OBJACTLK.PRG,0,130000 ++ * SSEL_CNV.PRG,0,15A000 ++ * SSEL_BAK.PRG,0,16F000 ++ * HITMSG.PRG,0,170000 ++ * SSEL_SPR.PRG,0,19D000 ++ */ ++static const rc_memory_region_t _rc_memory_regions_neo_geo_cd[] = { ++ { 0x000000U, 0x00F2FFU, 0x00100000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, ++ /* NOTE: some BIOS settings are exposed through the reserved RAM: https://wiki.neogeodev.org/index.php?title=68k_ASM_defines */ ++ { 0x00F300U, 0x00FFFFU, 0x0010F300U, RC_MEMORY_TYPE_SYSTEM_RAM, "Reserved RAM" }, ++}; ++static const rc_memory_regions_t rc_memory_regions_neo_geo_cd = { _rc_memory_regions_neo_geo_cd, 2 }; ++ ++/* ===== Nintendo Entertainment System ===== */ ++/* https://wiki.nesdev.com/w/index.php/CPU_memory_map */ ++static const rc_memory_region_t _rc_memory_regions_nes[] = { ++ { 0x0000U, 0x07FFU, 0x0000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, ++ { 0x0800U, 0x0FFFU, 0x0000U, RC_MEMORY_TYPE_VIRTUAL_RAM, "Mirror RAM" }, /* duplicates memory from $0000-$07FF */ ++ { 0x1000U, 0x17FFU, 0x0000U, RC_MEMORY_TYPE_VIRTUAL_RAM, "Mirror RAM" }, /* duplicates memory from $0000-$07FF */ ++ { 0x1800U, 0x1FFFU, 0x0000U, RC_MEMORY_TYPE_VIRTUAL_RAM, "Mirror RAM" }, /* duplicates memory from $0000-$07FF */ ++ { 0x2000U, 0x2007U, 0x2000U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "PPU Register" }, ++ { 0x2008U, 0x3FFFU, 0x2008U, RC_MEMORY_TYPE_VIRTUAL_RAM, "Mirrored PPU Register" }, /* repeats every 8 bytes */ ++ { 0x4000U, 0x4017U, 0x4000U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "APU and I/O register" }, ++ { 0x4018U, 0x401FU, 0x4018U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "APU and I/O test register" }, ++ ++ /* NOTE: these are for the original NES/Famicom */ ++ { 0x4020U, 0x5FFFU, 0x4020U, RC_MEMORY_TYPE_READONLY, "Cartridge data"}, /* varies by mapper */ ++ { 0x6000U, 0x7FFFU, 0x6000U, RC_MEMORY_TYPE_SAVE_RAM, "Cartridge RAM"}, ++ { 0x8000U, 0xFFFFU, 0x8000U, RC_MEMORY_TYPE_READONLY, "Cartridge ROM"}, ++}; ++static const rc_memory_regions_t rc_memory_regions_nes = { _rc_memory_regions_nes, 11 }; ++ ++/* ===== Nintendo 64 ===== */ ++/* https://raw.githubusercontent.com/mikeryan/n64dev/master/docs/n64ops/n64ops%23h.txt */ ++/* https://n64brew.dev/wiki/Memory_map#Virtual_Memory_Map */ ++static const rc_memory_region_t _rc_memory_regions_n64[] = { ++ { 0x000000U, 0x1FFFFFU, 0x80000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, /* RDRAM 1 */ ++ { 0x200000U, 0x3FFFFFU, 0x80200000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, /* RDRAM 2 */ ++ { 0x400000U, 0x7FFFFFU, 0x80400000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" } /* expansion pak */ ++}; ++static const rc_memory_regions_t rc_memory_regions_n64 = { _rc_memory_regions_n64, 3 }; ++ ++/* ===== Nintendo DS ===== */ ++/* https://www.akkit.org/info/gbatek.htm#dsmemorymaps */ ++static const rc_memory_region_t _rc_memory_regions_nintendo_ds[] = { ++ { 0x0000000U, 0x03FFFFFU, 0x02000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, ++ /* To keep DS/DSi memory maps aligned, padding is set here for the DSi's extra RAM */ ++ { 0x0400000U, 0x0FFFFFFU, 0x02400000U, RC_MEMORY_TYPE_UNUSED, "Unused (DSi exclusive)" }, ++ /* The DS/DSi have "tightly coupled memory": very fast memory directly connected to the CPU. ++ * This memory has an instruction variant (ITCM) and a data variant (DTCM). ++ * For achievement purposes it is useful to be able to access the data variant. ++ * This memory does not have a fixed address on console, being able to be moved to any $0xxxx000 region. ++ * While normally this kind of memory is addressed outside of the possible native addressing space, this is simply not possible, ++ * as the DS/DSi's address space covers all possible uint32_t values. ++ * $0E000000 is used here as a "pseudo-end," as this is nearly the end of all the memory actually mapped to addresses ++ * This means that (with the exception of $FFFF0000 onwards, which has the ARM9 BIOS mapped) $0E000000 onwards has nothing mapped to it ++ */ ++ { 0x1000000U, 0x1003FFFU, 0x0E000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Data TCM" } ++}; ++static const rc_memory_regions_t rc_memory_regions_nintendo_ds = { _rc_memory_regions_nintendo_ds, 3 }; ++ ++/* ===== Nintendo DSi ===== */ ++/* https://problemkaputt.de/gbatek.htm#dsiiomap */ ++static const rc_memory_region_t _rc_memory_regions_nintendo_dsi[] = { ++ { 0x0000000U, 0x0FFFFFFU, 0x02000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, ++ { 0x1000000U, 0x1003FFFU, 0x0E000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Data TCM" } ++}; ++static const rc_memory_regions_t rc_memory_regions_nintendo_dsi = { _rc_memory_regions_nintendo_dsi, 2 }; ++ ++/* ===== Oric ===== */ ++static const rc_memory_region_t _rc_memory_regions_oric[] = { ++ /* actual size depends on machine type - up to 64KB */ ++ { 0x000000U, 0x00FFFFU, 0x000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" } ++}; ++static const rc_memory_regions_t rc_memory_regions_oric = { _rc_memory_regions_oric, 1 }; ++ ++/* ===== PC-8800 ===== */ ++static const rc_memory_region_t _rc_memory_regions_pc8800[] = { ++ { 0x000000U, 0x00FFFFU, 0x000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Main RAM" }, ++ { 0x010000U, 0x010FFFU, 0x010000U, RC_MEMORY_TYPE_VIDEO_RAM, "Text VRAM" } /* technically VRAM, but often used as system RAM */ ++}; ++static const rc_memory_regions_t rc_memory_regions_pc8800 = { _rc_memory_regions_pc8800, 2 }; ++ ++/* ===== PC Engine ===== */ ++/* http://www.archaicpixels.com/Memory_Map */ ++static const rc_memory_region_t _rc_memory_regions_pc_engine[] = { ++ { 0x000000U, 0x001FFFU, 0x1F0000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, ++}; ++static const rc_memory_regions_t rc_memory_regions_pc_engine = { _rc_memory_regions_pc_engine, 1 }; ++ ++/* ===== PC Engine CD===== */ ++/* http://www.archaicpixels.com/Memory_Map */ ++static const rc_memory_region_t _rc_memory_regions_pc_engine_cd[] = { ++ { 0x000000U, 0x001FFFU, 0x1F0000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, ++ { 0x002000U, 0x011FFFU, 0x100000U, RC_MEMORY_TYPE_SYSTEM_RAM, "CD RAM" }, ++ { 0x012000U, 0x041FFFU, 0x0D0000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Super System Card RAM" }, ++ { 0x042000U, 0x0427FFU, 0x1EE000U, RC_MEMORY_TYPE_SAVE_RAM, "CD Battery-backed RAM" } ++}; ++static const rc_memory_regions_t rc_memory_regions_pc_engine_cd = { _rc_memory_regions_pc_engine_cd, 4 }; ++ ++/* ===== PC-FX ===== */ ++/* http://daifukkat.su/pcfx/data/memmap.html */ ++static const rc_memory_region_t _rc_memory_regions_pcfx[] = { ++ { 0x000000U, 0x1FFFFFU, 0x00000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, ++ { 0x200000U, 0x207FFFU, 0xE0000000U, RC_MEMORY_TYPE_SAVE_RAM, "Internal Backup Memory" }, ++ { 0x208000U, 0x20FFFFU, 0xE8000000U, RC_MEMORY_TYPE_SAVE_RAM, "External Backup Memory" }, ++}; ++static const rc_memory_regions_t rc_memory_regions_pcfx = { _rc_memory_regions_pcfx, 3 }; ++ ++/* ===== PlayStation ===== */ ++/* http://www.raphnet.net/electronique/psx_adaptor/Playstation.txt */ ++static const rc_memory_region_t _rc_memory_regions_playstation[] = { ++ { 0x000000U, 0x00FFFFU, 0x00000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Kernel RAM" }, ++ { 0x010000U, 0x1FFFFFU, 0x00010000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, ++ { 0x200000U, 0x2003FFU, 0x1F800000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Scratchpad RAM" } ++}; ++static const rc_memory_regions_t rc_memory_regions_playstation = { _rc_memory_regions_playstation, 3 }; ++ ++/* ===== PlayStation 2 ===== */ ++/* https://psi-rockin.github.io/ps2tek/ */ ++static const rc_memory_region_t _rc_memory_regions_playstation2[] = { ++ { 0x00000000U, 0x000FFFFFU, 0x00000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Kernel RAM" }, ++ { 0x00100000U, 0x01FFFFFFU, 0x00100000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, ++ { 0x02000000U, 0x02003FFFU, 0x70000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Scratchpad RAM" }, ++}; ++static const rc_memory_regions_t rc_memory_regions_playstation2 = { _rc_memory_regions_playstation2, 3 }; ++ ++/* ===== PlayStation Portable ===== */ ++/* https://github.com/uofw/upspd/wiki/Memory-map */ ++static const rc_memory_region_t _rc_memory_regions_psp[] = { ++ { 0x00000000U, 0x007FFFFFU, 0x08000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Kernel RAM" }, ++ { 0x00800000U, 0x01FFFFFFU, 0x08800000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, ++}; ++static const rc_memory_regions_t rc_memory_regions_psp = { _rc_memory_regions_psp, 2 }; ++ ++/* ===== Pokemon Mini ===== */ ++/* https://www.pokemon-mini.net/documentation/memory-map/ */ ++static const rc_memory_region_t _rc_memory_regions_pokemini[] = { ++ { 0x000000U, 0x000FFFU, 0x000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "BIOS RAM" }, ++ { 0x001000U, 0x001FFFU, 0x001000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" } ++}; ++static const rc_memory_regions_t rc_memory_regions_pokemini = { _rc_memory_regions_pokemini, 2 }; ++ ++/* ===== Sega CD ===== */ ++/* https://en.wikibooks.org/wiki/Genesis_Programming/68K_Memory_map/ */ ++static const rc_memory_region_t _rc_memory_regions_segacd[] = { ++ { 0x000000U, 0x00FFFFU, 0x00FF0000U, RC_MEMORY_TYPE_SYSTEM_RAM, "68000 RAM" }, ++ { 0x010000U, 0x08FFFFU, 0x80020000U, RC_MEMORY_TYPE_SYSTEM_RAM, "CD PRG RAM" }, /* normally banked into $020000-$03FFFF */ ++ { 0x090000U, 0x0AFFFFU, 0x00200000U, RC_MEMORY_TYPE_SYSTEM_RAM, "CD WORD RAM" } ++}; ++static const rc_memory_regions_t rc_memory_regions_segacd = { _rc_memory_regions_segacd, 3 }; ++ ++/* ===== Sega Saturn ===== */ ++/* https://segaretro.org/Sega_Saturn_hardware_notes_(2004-04-27) */ ++static const rc_memory_region_t _rc_memory_regions_saturn[] = { ++ { 0x000000U, 0x0FFFFFU, 0x00200000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Work RAM Low" }, ++ { 0x100000U, 0x1FFFFFU, 0x06000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Work RAM High" } ++}; ++static const rc_memory_regions_t rc_memory_regions_saturn = { _rc_memory_regions_saturn, 2 }; ++ ++/* ===== SG-1000 ===== */ ++/* https://www.smspower.org/Development/MemoryMap */ ++static const rc_memory_region_t _rc_memory_regions_sg1000[] = { ++ { 0x000000U, 0x0003FFU, 0xC000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, ++ /* https://github.com/libretro/FBNeo/blob/697801c6262be6ca91615cf905444d3e039bc06f/src/burn/drv/sg1000/d_sg1000.cpp#L210-L237 */ ++ /* Expansion mode B exposes 8KB at $C000. The first 2KB hides the System RAM, but since the address matches, ++ we'll leverage that definition and expand it another 6KB */ ++ { 0x000400U, 0x001FFFU, 0xC400U, RC_MEMORY_TYPE_SYSTEM_RAM, "Extended RAM" }, ++ /* Expansion mode A exposes 8KB at $2000 */ ++ { 0x002000U, 0x003FFFU, 0x2000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Extended RAM" }, ++ /* Othello exposes 2KB at $8000, and The Castle exposes 8KB at $8000 */ ++ { 0x004000U, 0x005FFFU, 0x8000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Extended RAM" } ++}; ++static const rc_memory_regions_t rc_memory_regions_sg1000 = { _rc_memory_regions_sg1000, 4 }; ++ ++/* ===== Super Cassette Vision ===== */ ++/* https://github.com/mamedev/mame/blob/f32bb79e8541ba96d3a8144b220c48fb7536ba4b/src/mame/epoch/scv.cpp#L78-L86 */ ++/* SCV only has 128 bytes of system RAM, any additional memory is provided on the individual carts and is ++ * not backed up by battery. */ ++/* http://www.videogameconsolelibrary.com/pg80-super_cass_vis.htm#page=specs */ ++static const rc_memory_region_t _rc_memory_regions_scv[] = { ++ { 0x000000U, 0x000FFFU, 0x000000U, RC_MEMORY_TYPE_READONLY, "System ROM" }, /* BIOS */ ++ { 0x001000U, 0x001FFFU, 0x001000U, RC_MEMORY_TYPE_UNUSED, "" }, ++ { 0x002000U, 0x003FFFU, 0x002000U, RC_MEMORY_TYPE_VIDEO_RAM, "Video RAM" }, /* only really goes to $33FF? */ ++ { 0x004000U, 0x007FFFU, 0x004000U, RC_MEMORY_TYPE_UNUSED, "" }, ++ { 0x008000U, 0x00FF7FU, 0x008000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Cartridge RAM" }, ++ { 0x00FF80U, 0x00FFFFU, 0x00FF80U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" } ++}; ++static const rc_memory_regions_t rc_memory_regions_scv = { _rc_memory_regions_scv, 6 }; ++ ++/* ===== Super Nintendo ===== */ ++/* https://en.wikibooks.org/wiki/Super_NES_Programming/SNES_memory_map#LoROM */ ++static const rc_memory_region_t _rc_memory_regions_snes[] = { ++ { 0x000000U, 0x01FFFFU, 0x07E0000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, ++ /* Cartridge RAM here could be in a variety of places in SNES memory, depending on the ROM type. ++ * Due to this, we place Cartridge RAM outside of the possible native addressing space. ++ * Note that this also covers SA-1 BW-RAM (which is exposed as RETRO_MEMORY_SAVE_RAM for libretro). ++ */ ++ { 0x020000U, 0x09FFFFU, 0x1000000U, RC_MEMORY_TYPE_SAVE_RAM, "Cartridge RAM" }, ++ /* I-RAM on the SA-1 is normally at 0x003000. However, this address typically just has a mirror of System RAM for other ROM types. ++ * To avoid conflicts, don't use 0x003000, instead map it outside of the possible native addressing space. ++ */ ++ { 0x0A0000U, 0x0A07FFU, 0x1080000U, RC_MEMORY_TYPE_SYSTEM_RAM, "I-RAM (SA-1)" } ++}; ++static const rc_memory_regions_t rc_memory_regions_snes = { _rc_memory_regions_snes, 3 }; ++ ++/* ===== Thomson TO8 ===== */ ++/* https://github.com/mamedev/mame/blob/master/src/mame/drivers/thomson.cpp#L1617 */ ++static const rc_memory_region_t _rc_memory_regions_thomson_to8[] = { ++ { 0x000000U, 0x07FFFFU, 0x000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" } ++}; ++static const rc_memory_regions_t rc_memory_regions_thomson_to8 = { _rc_memory_regions_thomson_to8, 1 }; ++ ++/* ===== TI-83 ===== */ ++/* https://tutorials.eeems.ca/ASMin28Days/lesson/day03.html#mem */ ++static const rc_memory_region_t _rc_memory_regions_ti83[] = { ++ { 0x000000U, 0x007FFFU, 0x008000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, ++}; ++static const rc_memory_regions_t rc_memory_regions_ti83 = { _rc_memory_regions_ti83, 1 }; ++ ++/* ===== TIC-80 ===== */ ++/* https://github.com/nesbox/TIC-80/wiki/RAM */ ++static const rc_memory_region_t _rc_memory_regions_tic80[] = { ++ { 0x000000U, 0x003FFFU, 0x000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Video RAM" }, /* have to classify this as system RAM because the core exposes it as part of the RETRO_MEMORY_SYSTEM_RAM */ ++ { 0x004000U, 0x005FFFU, 0x004000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Tile RAM" }, ++ { 0x006000U, 0x007FFFU, 0x006000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Sprite RAM" }, ++ { 0x008000U, 0x00FF7FU, 0x008000U, RC_MEMORY_TYPE_SYSTEM_RAM, "MAP RAM" }, ++ { 0x00FF80U, 0x00FF8BU, 0x00FF80U, RC_MEMORY_TYPE_SYSTEM_RAM, "Input State" }, ++ { 0x00FF8CU, 0x014003U, 0x00FF8CU, RC_MEMORY_TYPE_SYSTEM_RAM, "Sound RAM" }, ++ { 0x014004U, 0x014403U, 0x014004U, RC_MEMORY_TYPE_SAVE_RAM, "Persistent Memory" }, /* this is also returned as part of RETRO_MEMORY_SYSTEM_RAM, but can be extrapolated correctly because the pointer starts at the first SYSTEM_RAM region */ ++ { 0x014404U, 0x014603U, 0x014404U, RC_MEMORY_TYPE_SYSTEM_RAM, "Sprite Flags" }, ++ { 0x014604U, 0x014E03U, 0x014604U, RC_MEMORY_TYPE_SYSTEM_RAM, "System Font" }, ++ { 0x014E04U, 0x017FFFU, 0x014E04U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM"} ++}; ++static const rc_memory_regions_t rc_memory_regions_tic80 = { _rc_memory_regions_tic80, 10 }; ++ ++/* ===== Uzebox ===== */ ++/* https://uzebox.org/index.php */ ++static const rc_memory_region_t _rc_memory_regions_uzebox[] = { ++ { 0x000000U, 0x000FFFU, 0x000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" } ++}; ++static const rc_memory_regions_t rc_memory_regions_uzebox = { _rc_memory_regions_uzebox, 1 }; ++ ++/* ===== Vectrex ===== */ ++/* https://roadsidethoughts.com/vectrex/vectrex-memory-map.htm */ ++static const rc_memory_region_t _rc_memory_regions_vectrex[] = { ++ { 0x000000U, 0x0003FFU, 0x00C800U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" } ++}; ++static const rc_memory_regions_t rc_memory_regions_vectrex = { _rc_memory_regions_vectrex, 1 }; ++ ++/* ===== Virtual Boy ===== */ ++static const rc_memory_region_t _rc_memory_regions_virtualboy[] = { ++ { 0x000000U, 0x00FFFFU, 0x05000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, ++ { 0x010000U, 0x01FFFFU, 0x06000000U, RC_MEMORY_TYPE_SAVE_RAM, "Cartridge RAM" } ++}; ++static const rc_memory_regions_t rc_memory_regions_virtualboy = { _rc_memory_regions_virtualboy, 2 }; ++ ++/* ===== Watara Supervision ===== */ ++/* https://github.com/libretro/potator/blob/b5e5ba02914fcdf4a8128072dbc709da28e08832/common/memorymap.c#L231-L259 */ ++static const rc_memory_region_t _rc_memory_regions_watara_supervision[] = { ++ { 0x0000U, 0x001FFFU, 0x0000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, ++ { 0x2000U, 0x003FFFU, 0x2000U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "Registers" }, ++ { 0x4000U, 0x005FFFU, 0x4000U, RC_MEMORY_TYPE_VIDEO_RAM, "Video RAM" } ++}; ++static const rc_memory_regions_t rc_memory_regions_watara_supervision = { _rc_memory_regions_watara_supervision, 3 }; ++ ++/* ===== WASM-4 ===== */ ++/* fantasy console that runs specifically designed WebAssembly games */ ++/* https://github.com/aduros/wasm4/blob/main/site/docs/intro.md#hardware-specs */ ++static const rc_memory_region_t _rc_memory_regions_wasm4[] = { ++ { 0x000000U, 0x00FFFFU, 0x00000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, ++ /* Persistent storage is not directly accessible from the game. It has to be loaded into System RAM first ++ { 0x010000U, 0x0103FFU, 0x80000000U, RC_MEMORY_TYPE_SAVE_RAM, "Disk Storage"} ++ */ ++}; ++static const rc_memory_regions_t rc_memory_regions_wasm4 = { _rc_memory_regions_wasm4, 1 }; ++ ++/* ===== Wii ===== */ ++/* https://wiibrew.org/wiki/Memory_map */ ++static const rc_memory_region_t _rc_memory_regions_wii[] = { ++ { 0x00000000U, 0x017FFFFF, 0x80000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, ++ { 0x01800000U, 0x0FFFFFFF, 0x81800000U, RC_MEMORY_TYPE_UNUSED, "Unused" }, ++ { 0x10000000U, 0x13FFFFFF, 0x90000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" } ++}; ++static const rc_memory_regions_t rc_memory_regions_wii = { _rc_memory_regions_wii, 3 }; ++ ++/* ===== WonderSwan ===== */ ++/* http://daifukkat.su/docs/wsman/#ovr_memmap */ ++static const rc_memory_region_t _rc_memory_regions_wonderswan[] = { ++ /* RAM ends at 0x3FFF for WonderSwan, WonderSwan color uses all 64KB */ ++ { 0x000000U, 0x00FFFFU, 0x000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, ++ /* Only 64KB of SRAM is accessible via the addressing scheme, but the cartridge ++ * may have up to 512KB of SRAM. http://daifukkat.su/docs/wsman/#cart_meta ++ * Since beetle_wswan exposes it as a contiguous block, assume its contiguous ++ * even though the documentation says $20000-$FFFFF is ROM data. If this causes ++ * a conflict in the future, we can revisit. A new region with a virtual address ++ * could be added to pick up the additional SRAM data. As long as it immediately ++ * follows the 64KB at $10000, all existing achievements should be unaffected. ++ */ ++ { 0x010000U, 0x08FFFFU, 0x010000U, RC_MEMORY_TYPE_SAVE_RAM, "Cartridge RAM" } ++}; ++static const rc_memory_regions_t rc_memory_regions_wonderswan = { _rc_memory_regions_wonderswan, 2 }; ++ ++/* ===== ZX Spectrum ===== */ ++/* https://github.com/TASEmulators/BizHawk/blob/3a3b22c/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum16K/ZX16.cs ++ * https://github.com/TASEmulators/BizHawk/blob/3a3b22c/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum48K/ZX48.Memory.cs ++ * https://worldofspectrum.org/faq/reference/128kreference.htm */ ++static const rc_memory_region_t _rc_memory_regions_zx_spectrum[] = { ++ /* ZX Spectrum is complicated as multiple models exist with varying amounts of memory. ++ * In practice, this can be reduced to two categories: 16K/48K units, and 128K units. ++ * 16K/48K units have RAM starting at $4000 onwards, 16K ending at $7FFF, 48K ending at $FFFF. ++ * 128K units have banked memory, with $4000-$7FFF normally having RAM bank 5, and $8000-$BFFF normally having RAM bank 2. ++ * $C000-$FFFF is normally reserved for banked RAM, having any of banks 0-7. ++ * For the purposes of the RAM map, $C000-$FFFF is assumed to be bank 0, and $10000 onwards has the other banks in order (1, 3, 4, 6, 7) ++ * Doing it this way always for 16K/48K games to have the same memory map on the 128K, and thus avoid issues due to the model selected. ++ * Later 128K units also have a special banking mode that changes up banking completely, but for 16K/48K compatibility purposes this doesn't matter, and so is irrelevant. ++ */ ++ { 0x00000U, 0x03FFFU, 0x04000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Screen RAM" }, /* RAM bank 5 on 128K units */ ++ { 0x04000U, 0x07FFFU, 0x08000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, /* RAM bank 2 on 128K units */ ++ { 0x08000U, 0x0BFFFU, 0x0C000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, /* RAM bank 0-7 on 128K units, assumed to be bank 0 here */ ++ { 0x0C000U, 0x0FFFFU, 0x10000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, /* RAM bank 1 on 128K units */ ++ { 0x10000U, 0x13FFFU, 0x14000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, /* RAM bank 3 on 128K units */ ++ { 0x14000U, 0x17FFFU, 0x18000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, /* RAM bank 4 on 128K units */ ++ { 0x18000U, 0x1BFFFU, 0x1C000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, /* RAM bank 6 on 128K units */ ++ { 0x1C000U, 0x1FFFFU, 0x20000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Screen RAM" } /* RAM bank 7 on 128K units */ ++}; ++static const rc_memory_regions_t rc_memory_regions_zx_spectrum = { _rc_memory_regions_zx_spectrum, 8 }; ++ ++/* ===== default ===== */ ++static const rc_memory_regions_t rc_memory_regions_none = { 0, 0 }; ++ ++const rc_memory_regions_t* rc_console_memory_regions(uint32_t console_id) ++{ ++ switch (console_id) ++ { ++ case RC_CONSOLE_3DO: ++ return &rc_memory_regions_3do; ++ ++ case RC_CONSOLE_AMIGA: ++ return &rc_memory_regions_amiga; ++ ++ case RC_CONSOLE_AMSTRAD_PC: ++ return &rc_memory_regions_amstrad_pc; ++ ++ case RC_CONSOLE_APPLE_II: ++ return &rc_memory_regions_appleii; ++ ++ case RC_CONSOLE_ARCADIA_2001: ++ return &rc_memory_regions_arcadia_2001; ++ ++ case RC_CONSOLE_ARDUBOY: ++ return &rc_memory_regions_arduboy; ++ ++ case RC_CONSOLE_ATARI_2600: ++ return &rc_memory_regions_atari2600; ++ ++ case RC_CONSOLE_ATARI_7800: ++ return &rc_memory_regions_atari7800; ++ ++ case RC_CONSOLE_ATARI_JAGUAR: ++ case RC_CONSOLE_ATARI_JAGUAR_CD: ++ return &rc_memory_regions_atari_jaguar; ++ ++ case RC_CONSOLE_ATARI_LYNX: ++ return &rc_memory_regions_atari_lynx; ++ ++ case RC_CONSOLE_COLECOVISION: ++ return &rc_memory_regions_colecovision; ++ ++ case RC_CONSOLE_COMMODORE_64: ++ return &rc_memory_regions_c64; ++ ++ case RC_CONSOLE_DREAMCAST: ++ return &rc_memory_regions_dreamcast; ++ ++ case RC_CONSOLE_ELEKTOR_TV_GAMES_COMPUTER: ++ return &rc_memory_regions_elektor_tv_games; ++ ++ case RC_CONSOLE_FAIRCHILD_CHANNEL_F: ++ return &rc_memory_regions_fairchild_channel_f; ++ ++ case RC_CONSOLE_FAMICOM_DISK_SYSTEM: ++ return &rc_memory_regions_famicom_disk_system; ++ ++ case RC_CONSOLE_GAMEBOY: ++ return &rc_memory_regions_gameboy; ++ ++ case RC_CONSOLE_GAMEBOY_COLOR: ++ return &rc_memory_regions_gameboy_color; ++ ++ case RC_CONSOLE_GAMEBOY_ADVANCE: ++ return &rc_memory_regions_gameboy_advance; ++ ++ case RC_CONSOLE_GAMECUBE: ++ return &rc_memory_regions_gamecube; ++ ++ case RC_CONSOLE_GAME_GEAR: ++ return &rc_memory_regions_game_gear; ++ ++ case RC_CONSOLE_INTELLIVISION: ++ return &rc_memory_regions_intellivision; ++ ++ case RC_CONSOLE_INTERTON_VC_4000: ++ return &rc_memory_regions_interton_vc_4000; ++ ++ case RC_CONSOLE_MAGNAVOX_ODYSSEY2: ++ return &rc_memory_regions_magnavox_odyssey_2; ++ ++ case RC_CONSOLE_MASTER_SYSTEM: ++ return &rc_memory_regions_master_system; ++ ++ case RC_CONSOLE_MEGA_DRIVE: ++ return &rc_memory_regions_megadrive; ++ ++ case RC_CONSOLE_MEGADUCK: ++ return &rc_memory_regions_megaduck; ++ ++ case RC_CONSOLE_SEGA_32X: ++ return &rc_memory_regions_megadrive_32x; ++ ++ case RC_CONSOLE_MSX: ++ return &rc_memory_regions_msx; ++ ++ case RC_CONSOLE_MS_DOS: ++ return &rc_memory_regions_ms_dos; ++ ++ case RC_CONSOLE_NEOGEO_POCKET: ++ return &rc_memory_regions_neo_geo_pocket; ++ ++ case RC_CONSOLE_NEO_GEO_CD: ++ return &rc_memory_regions_neo_geo_cd; ++ ++ case RC_CONSOLE_NINTENDO: ++ return &rc_memory_regions_nes; ++ ++ case RC_CONSOLE_NINTENDO_64: ++ return &rc_memory_regions_n64; ++ ++ case RC_CONSOLE_NINTENDO_DS: ++ return &rc_memory_regions_nintendo_ds; ++ ++ case RC_CONSOLE_NINTENDO_DSI: ++ return &rc_memory_regions_nintendo_dsi; ++ ++ case RC_CONSOLE_ORIC: ++ return &rc_memory_regions_oric; ++ ++ case RC_CONSOLE_PC8800: ++ return &rc_memory_regions_pc8800; ++ ++ case RC_CONSOLE_PC_ENGINE: ++ return &rc_memory_regions_pc_engine; ++ ++ case RC_CONSOLE_PC_ENGINE_CD: ++ return &rc_memory_regions_pc_engine_cd; ++ ++ case RC_CONSOLE_PCFX: ++ return &rc_memory_regions_pcfx; ++ ++ case RC_CONSOLE_PLAYSTATION: ++ return &rc_memory_regions_playstation; ++ ++ case RC_CONSOLE_PLAYSTATION_2: ++ return &rc_memory_regions_playstation2; ++ ++ case RC_CONSOLE_PSP: ++ return &rc_memory_regions_psp; ++ ++ case RC_CONSOLE_POKEMON_MINI: ++ return &rc_memory_regions_pokemini; ++ ++ case RC_CONSOLE_SATURN: ++ return &rc_memory_regions_saturn; ++ ++ case RC_CONSOLE_SEGA_CD: ++ return &rc_memory_regions_segacd; ++ ++ case RC_CONSOLE_SG1000: ++ return &rc_memory_regions_sg1000; ++ ++ case RC_CONSOLE_SUPER_CASSETTEVISION: ++ return &rc_memory_regions_scv; ++ ++ case RC_CONSOLE_SUPER_NINTENDO: ++ return &rc_memory_regions_snes; ++ ++ case RC_CONSOLE_SUPERVISION: ++ return &rc_memory_regions_watara_supervision; ++ ++ case RC_CONSOLE_THOMSONTO8: ++ return &rc_memory_regions_thomson_to8; ++ ++ case RC_CONSOLE_TI83: ++ return &rc_memory_regions_ti83; ++ ++ case RC_CONSOLE_TIC80: ++ return &rc_memory_regions_tic80; ++ ++ case RC_CONSOLE_UZEBOX: ++ return &rc_memory_regions_uzebox; ++ ++ case RC_CONSOLE_VECTREX: ++ return &rc_memory_regions_vectrex; ++ ++ case RC_CONSOLE_VIRTUAL_BOY: ++ return &rc_memory_regions_virtualboy; ++ ++ case RC_CONSOLE_WASM4: ++ return &rc_memory_regions_wasm4; ++ ++ case RC_CONSOLE_WII: ++ return &rc_memory_regions_wii; ++ ++ case RC_CONSOLE_WONDERSWAN: ++ return &rc_memory_regions_wonderswan; ++ ++ case RC_CONSOLE_ZX_SPECTRUM: ++ return &rc_memory_regions_zx_spectrum; ++ ++ default: ++ return &rc_memory_regions_none; ++ } ++} +diff -rupbN melonDS.orig/src/rcheevos/src/rcheevos/format.c melonDS.ra/src/rcheevos/src/rcheevos/format.c +--- melonDS.orig/src/rcheevos/src/rcheevos/format.c 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rcheevos/format.c 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,330 @@ ++#include "rc_internal.h" ++ ++#include "../rc_compat.h" ++ ++#include ++#include ++#include ++ ++int rc_parse_format(const char* format_str) { ++ switch (*format_str++) { ++ case 'F': ++ if (!strcmp(format_str, "RAMES")) { ++ return RC_FORMAT_FRAMES; ++ } ++ if (!strncmp(format_str, "LOAT", 4) && format_str[4] >= '1' && format_str[4] <= '6' && format_str[5] == '\0') { ++ return RC_FORMAT_FLOAT1 + (format_str[4] - '1'); ++ } ++ if (!strncmp(format_str, "IXED", 4) && format_str[4] >= '1' && format_str[4] <= '3' && format_str[5] == '\0') { ++ return RC_FORMAT_FIXED1 + (format_str[4] - '1'); ++ } ++ ++ break; ++ ++ case 'T': ++ if (!strcmp(format_str, "IME")) { ++ return RC_FORMAT_FRAMES; ++ } ++ if (!strcmp(format_str, "IMESECS")) { ++ return RC_FORMAT_SECONDS; ++ } ++ if (!strcmp(format_str, "HOUSANDS")) { ++ return RC_FORMAT_THOUSANDS; ++ } ++ if (!strcmp(format_str, "ENS")) { ++ return RC_FORMAT_TENS; ++ } ++ ++ break; ++ ++ case 'S': ++ if (!strcmp(format_str, "ECS")) { ++ return RC_FORMAT_SECONDS; ++ } ++ if (!strcmp(format_str, "CORE")) { ++ return RC_FORMAT_SCORE; ++ } ++ if (!strcmp(format_str, "ECS_AS_MINS")) { ++ return RC_FORMAT_SECONDS_AS_MINUTES; ++ } ++ ++ break; ++ ++ case 'M': ++ if (!strcmp(format_str, "ILLISECS")) { ++ return RC_FORMAT_CENTISECS; ++ } ++ if (!strcmp(format_str, "INUTES")) { ++ return RC_FORMAT_MINUTES; ++ } ++ ++ break; ++ ++ case 'P': ++ if (!strcmp(format_str, "OINTS")) { ++ return RC_FORMAT_SCORE; ++ } ++ ++ break; ++ ++ case 'V': ++ if (!strcmp(format_str, "ALUE")) { ++ return RC_FORMAT_VALUE; ++ } ++ ++ break; ++ ++ case 'U': ++ if (!strcmp(format_str, "NSIGNED")) { ++ return RC_FORMAT_UNSIGNED_VALUE; ++ } ++ ++ break; ++ ++ case 'O': ++ if (!strcmp(format_str, "THER")) { ++ return RC_FORMAT_SCORE; ++ } ++ ++ break; ++ ++ case 'H': ++ if (!strcmp(format_str, "UNDREDS")) { ++ return RC_FORMAT_HUNDREDS; ++ } ++ ++ break; ++ } ++ ++ return RC_FORMAT_VALUE; ++} ++ ++static int rc_format_value_minutes(char* buffer, size_t size, uint32_t minutes) { ++ uint32_t hours; ++ ++ hours = minutes / 60; ++ minutes -= hours * 60; ++ return snprintf(buffer, size, "%uh%02u", hours, minutes); ++} ++ ++static int rc_format_value_seconds(char* buffer, size_t size, uint32_t seconds) { ++ uint32_t hours, minutes; ++ ++ /* apply modulus math to split the seconds into hours/minutes/seconds */ ++ minutes = seconds / 60; ++ seconds -= minutes * 60; ++ if (minutes < 60) { ++ return snprintf(buffer, size, "%u:%02u", minutes, seconds); ++ } ++ ++ hours = minutes / 60; ++ minutes -= hours * 60; ++ return snprintf(buffer, size, "%uh%02u:%02u", hours, minutes, seconds); ++} ++ ++static int rc_format_value_centiseconds(char* buffer, size_t size, uint32_t centiseconds) { ++ uint32_t seconds; ++ int chars, chars2; ++ ++ /* modulus off the centiseconds */ ++ seconds = centiseconds / 100; ++ centiseconds -= seconds * 100; ++ ++ chars = rc_format_value_seconds(buffer, size, seconds); ++ if (chars > 0) { ++ chars2 = snprintf(buffer + chars, size - chars, ".%02u", centiseconds); ++ if (chars2 > 0) { ++ chars += chars2; ++ } else { ++ chars = chars2; ++ } ++ } ++ ++ return chars; ++} ++ ++static int rc_format_value_fixed(char* buffer, size_t size, const char* format, int32_t value, int32_t factor) ++{ ++ if (value >= 0) ++ return snprintf(buffer, size, format, value / factor, value % factor); ++ ++ return snprintf(buffer, size, format, value / factor, (-value) % factor); ++} ++ ++static int rc_format_value_padded(char* buffer, size_t size, const char* format, int32_t value) ++{ ++ if (value == 0) ++ return snprintf(buffer, size, "0"); ++ ++ return snprintf(buffer, size, format, value); ++} ++ ++static int rc_format_insert_commas(int chars, char* buffer, size_t size) ++{ ++ int to_insert; ++ char* src = buffer; ++ char* ptr; ++ char* dst = &buffer[chars]; ++ if (chars == 0) ++ return 0; ++ ++ /* ignore leading negative sign */ ++ if (*src == '-') ++ src++; ++ ++ /* determine how many digits are present in the leading number */ ++ ptr = src; ++ while (ptr < dst && isdigit((int)*ptr)) ++ ++ptr; ++ ++ /* determine how many commas are needed */ ++ to_insert = (int)((ptr - src - 1) / 3); ++ if (to_insert == 0) /* no commas needed */ ++ return chars; ++ ++ /* if there's not enough room to insert the commas, leave string as-is, but return wanted space */ ++ chars += to_insert; ++ if (chars >= (int)size) ++ return chars; ++ ++ /* move the trailing part of the string */ ++ memmove(ptr + to_insert, ptr, dst - ptr + 1); ++ ++ /* shift blocks of three digits at a time, inserting commas in front of them */ ++ src = ptr - 1; ++ dst = src + to_insert; ++ while (to_insert > 0) { ++ *dst-- = *src--; ++ *dst-- = *src--; ++ *dst-- = *src--; ++ *dst-- = ','; ++ ++ --to_insert; ++ } ++ ++ return chars; ++} ++ ++int rc_format_typed_value(char* buffer, size_t size, const rc_typed_value_t* value, int format) { ++ int chars; ++ rc_typed_value_t converted_value; ++ ++ memcpy(&converted_value, value, sizeof(converted_value)); ++ ++ switch (format) { ++ default: ++ case RC_FORMAT_VALUE: ++ rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_SIGNED); ++ chars = snprintf(buffer, size, "%d", converted_value.value.i32); ++ break; ++ ++ case RC_FORMAT_FRAMES: ++ /* 60 frames per second = 100 centiseconds / 60 frames; multiply frames by 100 / 60 */ ++ rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_UNSIGNED); ++ chars = rc_format_value_centiseconds(buffer, size, converted_value.value.u32 * 10 / 6); ++ break; ++ ++ case RC_FORMAT_CENTISECS: ++ rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_UNSIGNED); ++ chars = rc_format_value_centiseconds(buffer, size, converted_value.value.u32); ++ break; ++ ++ case RC_FORMAT_SECONDS: ++ rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_UNSIGNED); ++ chars = rc_format_value_seconds(buffer, size, converted_value.value.u32); ++ break; ++ ++ case RC_FORMAT_SECONDS_AS_MINUTES: ++ rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_UNSIGNED); ++ chars = rc_format_value_minutes(buffer, size, converted_value.value.u32 / 60); ++ break; ++ ++ case RC_FORMAT_MINUTES: ++ rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_UNSIGNED); ++ chars = rc_format_value_minutes(buffer, size, converted_value.value.u32); ++ break; ++ ++ case RC_FORMAT_SCORE: ++ rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_SIGNED); ++ return snprintf(buffer, size, "%06d", converted_value.value.i32); ++ ++ case RC_FORMAT_FLOAT1: ++ rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_FLOAT); ++ chars = snprintf(buffer, size, "%.1f", converted_value.value.f32); ++ break; ++ ++ case RC_FORMAT_FLOAT2: ++ rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_FLOAT); ++ chars = snprintf(buffer, size, "%.2f", converted_value.value.f32); ++ break; ++ ++ case RC_FORMAT_FLOAT3: ++ rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_FLOAT); ++ chars = snprintf(buffer, size, "%.3f", converted_value.value.f32); ++ break; ++ ++ case RC_FORMAT_FLOAT4: ++ rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_FLOAT); ++ chars = snprintf(buffer, size, "%.4f", converted_value.value.f32); ++ break; ++ ++ case RC_FORMAT_FLOAT5: ++ rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_FLOAT); ++ chars = snprintf(buffer, size, "%.5f", converted_value.value.f32); ++ break; ++ ++ case RC_FORMAT_FLOAT6: ++ rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_FLOAT); ++ chars = snprintf(buffer, size, "%.6f", converted_value.value.f32); ++ break; ++ ++ case RC_FORMAT_FIXED1: ++ rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_SIGNED); ++ chars = rc_format_value_fixed(buffer, size, "%d.%u", converted_value.value.i32, 10); ++ break; ++ ++ case RC_FORMAT_FIXED2: ++ rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_SIGNED); ++ chars = rc_format_value_fixed(buffer, size, "%d.%02u", converted_value.value.i32, 100); ++ break; ++ ++ case RC_FORMAT_FIXED3: ++ rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_SIGNED); ++ chars = rc_format_value_fixed(buffer, size, "%d.%03u", converted_value.value.i32, 1000); ++ break; ++ ++ case RC_FORMAT_TENS: ++ rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_SIGNED); ++ chars = rc_format_value_padded(buffer, size, "%d0", converted_value.value.i32); ++ break; ++ ++ case RC_FORMAT_HUNDREDS: ++ rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_SIGNED); ++ chars = rc_format_value_padded(buffer, size, "%d00", converted_value.value.i32); ++ break; ++ ++ case RC_FORMAT_THOUSANDS: ++ rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_SIGNED); ++ chars = rc_format_value_padded(buffer, size, "%d000", converted_value.value.i32); ++ break; ++ ++ case RC_FORMAT_UNSIGNED_VALUE: ++ rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_UNSIGNED); ++ chars = snprintf(buffer, size, "%u", converted_value.value.u32); ++ break; ++ ++ case RC_FORMAT_UNFORMATTED: ++ rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_UNSIGNED); ++ return snprintf(buffer, size, "%u", converted_value.value.u32); ++ } ++ ++ return rc_format_insert_commas(chars, buffer, size); ++} ++ ++int rc_format_value(char* buffer, int size, int32_t value, int format) { ++ rc_typed_value_t typed_value; ++ ++ typed_value.value.i32 = value; ++ typed_value.type = RC_VALUE_TYPE_SIGNED; ++ return rc_format_typed_value(buffer, size, &typed_value, format); ++} +diff -rupbN melonDS.orig/src/rcheevos/src/rcheevos/lboard.c melonDS.ra/src/rcheevos/src/rcheevos/lboard.c +--- melonDS.orig/src/rcheevos/src/rcheevos/lboard.c 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rcheevos/lboard.c 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,287 @@ ++#include "rc_internal.h" ++ ++enum { ++ RC_LBOARD_START = 1 << 0, ++ RC_LBOARD_CANCEL = 1 << 1, ++ RC_LBOARD_SUBMIT = 1 << 2, ++ RC_LBOARD_VALUE = 1 << 3, ++ RC_LBOARD_PROGRESS = 1 << 4, ++ RC_LBOARD_COMPLETE = RC_LBOARD_START | RC_LBOARD_CANCEL | RC_LBOARD_SUBMIT | RC_LBOARD_VALUE ++}; ++ ++void rc_parse_lboard_internal(rc_lboard_t* self, const char* memaddr, rc_parse_state_t* parse) { ++ int found; ++ ++ self->progress = 0; ++ found = 0; ++ ++ for (;;) ++ { ++ if ((memaddr[0] == 's' || memaddr[0] == 'S') && ++ (memaddr[1] == 't' || memaddr[1] == 'T') && ++ (memaddr[2] == 'a' || memaddr[2] == 'A') && memaddr[3] == ':') { ++ if ((found & RC_LBOARD_START) != 0) { ++ parse->offset = RC_DUPLICATED_START; ++ return; ++ } ++ ++ memaddr += 4; ++ if (*memaddr && *memaddr != ':') { ++ found |= RC_LBOARD_START; ++ rc_parse_trigger_internal(&self->start, &memaddr, parse); ++ } ++ } ++ else if ((memaddr[0] == 'c' || memaddr[0] == 'C') && ++ (memaddr[1] == 'a' || memaddr[1] == 'A') && ++ (memaddr[2] == 'n' || memaddr[2] == 'N') && memaddr[3] == ':') { ++ if ((found & RC_LBOARD_CANCEL) != 0) { ++ parse->offset = RC_DUPLICATED_CANCEL; ++ return; ++ } ++ ++ memaddr += 4; ++ if (*memaddr && *memaddr != ':') { ++ found |= RC_LBOARD_CANCEL; ++ rc_parse_trigger_internal(&self->cancel, &memaddr, parse); ++ } ++ } ++ else if ((memaddr[0] == 's' || memaddr[0] == 'S') && ++ (memaddr[1] == 'u' || memaddr[1] == 'U') && ++ (memaddr[2] == 'b' || memaddr[2] == 'B') && memaddr[3] == ':') { ++ if ((found & RC_LBOARD_SUBMIT) != 0) { ++ parse->offset = RC_DUPLICATED_SUBMIT; ++ return; ++ } ++ ++ memaddr += 4; ++ if (*memaddr && *memaddr != ':') { ++ found |= RC_LBOARD_SUBMIT; ++ rc_parse_trigger_internal(&self->submit, &memaddr, parse); ++ } ++ } ++ else if ((memaddr[0] == 'v' || memaddr[0] == 'V') && ++ (memaddr[1] == 'a' || memaddr[1] == 'A') && ++ (memaddr[2] == 'l' || memaddr[2] == 'L') && memaddr[3] == ':') { ++ if ((found & RC_LBOARD_VALUE) != 0) { ++ parse->offset = RC_DUPLICATED_VALUE; ++ return; ++ } ++ ++ memaddr += 4; ++ if (*memaddr && *memaddr != ':') { ++ found |= RC_LBOARD_VALUE; ++ rc_parse_value_internal(&self->value, &memaddr, parse); ++ } ++ } ++ else if ((memaddr[0] == 'p' || memaddr[0] == 'P') && ++ (memaddr[1] == 'r' || memaddr[1] == 'R') && ++ (memaddr[2] == 'o' || memaddr[2] == 'O') && memaddr[3] == ':') { ++ if ((found & RC_LBOARD_PROGRESS) != 0) { ++ parse->offset = RC_DUPLICATED_PROGRESS; ++ return; ++ } ++ ++ memaddr += 4; ++ if (*memaddr && *memaddr != ':') { ++ found |= RC_LBOARD_PROGRESS; ++ ++ self->progress = RC_ALLOC(rc_value_t, parse); ++ rc_parse_value_internal(self->progress, &memaddr, parse); ++ } ++ } ++ ++ /* encountered an error parsing one of the parts */ ++ if (parse->offset < 0) ++ return; ++ ++ /* end of string, or end of quoted string - stop processing */ ++ if (memaddr[0] == '\0' || memaddr[0] == '\"') ++ break; ++ ++ /* expect two colons between fields */ ++ if (memaddr[0] != ':' || memaddr[1] != ':') { ++ parse->offset = RC_INVALID_LBOARD_FIELD; ++ return; ++ } ++ ++ memaddr += 2; ++ } ++ ++ if ((found & RC_LBOARD_COMPLETE) != RC_LBOARD_COMPLETE) { ++ if ((found & RC_LBOARD_START) == 0) { ++ parse->offset = RC_MISSING_START; ++ } ++ else if ((found & RC_LBOARD_CANCEL) == 0) { ++ parse->offset = RC_MISSING_CANCEL; ++ } ++ else if ((found & RC_LBOARD_SUBMIT) == 0) { ++ parse->offset = RC_MISSING_SUBMIT; ++ } ++ else if ((found & RC_LBOARD_VALUE) == 0) { ++ parse->offset = RC_MISSING_VALUE; ++ } ++ ++ return; ++ } ++ ++ self->state = RC_LBOARD_STATE_WAITING; ++ self->has_memrefs = 0; ++} ++ ++int rc_lboard_size(const char* memaddr) { ++ rc_lboard_with_memrefs_t* lboard; ++ rc_preparse_state_t preparse; ++ rc_init_preparse_state(&preparse); ++ ++ lboard = RC_ALLOC(rc_lboard_with_memrefs_t, &preparse.parse); ++ rc_parse_lboard_internal(&lboard->lboard, memaddr, &preparse.parse); ++ rc_preparse_alloc_memrefs(NULL, &preparse); ++ ++ rc_destroy_preparse_state(&preparse); ++ return preparse.parse.offset; ++} ++ ++rc_lboard_t* rc_parse_lboard(void* buffer, const char* memaddr, void* unused_L, int unused_funcs_idx) { ++ rc_lboard_with_memrefs_t* lboard; ++ rc_preparse_state_t preparse; ++ ++ (void)unused_L; ++ (void)unused_funcs_idx; ++ ++ if (!buffer || !memaddr) ++ return 0; ++ ++ rc_init_preparse_state(&preparse); ++ lboard = RC_ALLOC(rc_lboard_with_memrefs_t, &preparse.parse); ++ rc_parse_lboard_internal(&lboard->lboard, memaddr, &preparse.parse); ++ ++ rc_reset_parse_state(&preparse.parse, buffer); ++ lboard = RC_ALLOC(rc_lboard_with_memrefs_t, &preparse.parse); ++ rc_preparse_alloc_memrefs(&lboard->memrefs, &preparse); ++ ++ rc_parse_lboard_internal(&lboard->lboard, memaddr, &preparse.parse); ++ lboard->lboard.has_memrefs = 1; ++ ++ rc_destroy_preparse_state(&preparse); ++ return (preparse.parse.offset >= 0) ? &lboard->lboard : NULL; ++} ++ ++static void rc_update_lboard_memrefs(rc_lboard_t* self, rc_peek_t peek, void* ud) { ++ if (self->has_memrefs) { ++ rc_lboard_with_memrefs_t* lboard = (rc_lboard_with_memrefs_t*)self; ++ rc_update_memref_values(&lboard->memrefs, peek, ud); ++ } ++} ++ ++int rc_evaluate_lboard(rc_lboard_t* self, int32_t* value, rc_peek_t peek, void* peek_ud, void* unused_L) { ++ int start_ok, cancel_ok, submit_ok; ++ ++ rc_update_lboard_memrefs(self, peek, peek_ud); ++ ++ if (self->state == RC_LBOARD_STATE_INACTIVE || self->state == RC_LBOARD_STATE_DISABLED) ++ return RC_LBOARD_STATE_INACTIVE; ++ ++ /* these are always tested once every frame, to ensure hit counts work properly */ ++ start_ok = rc_test_trigger(&self->start, peek, peek_ud, unused_L); ++ cancel_ok = rc_test_trigger(&self->cancel, peek, peek_ud, unused_L); ++ submit_ok = rc_test_trigger(&self->submit, peek, peek_ud, unused_L); ++ ++ switch (self->state) ++ { ++ case RC_LBOARD_STATE_WAITING: ++ case RC_LBOARD_STATE_TRIGGERED: ++ case RC_LBOARD_STATE_CANCELED: ++ /* don't activate/reactivate until the start condition becomes false */ ++ if (start_ok) { ++ *value = 0; ++ return RC_LBOARD_STATE_INACTIVE; /* just return inactive for all of these */ ++ } ++ ++ /* start condition is false, allow the leaderboard to start on future frames */ ++ self->state = RC_LBOARD_STATE_ACTIVE; ++ break; ++ ++ case RC_LBOARD_STATE_ACTIVE: ++ /* leaderboard attempt is not in progress. if the start condition is true and the cancel condition is not, start the attempt */ ++ if (start_ok && !cancel_ok) { ++ if (submit_ok) { ++ /* start and submit are both true in the same frame, just submit without announcing the leaderboard is available */ ++ self->state = RC_LBOARD_STATE_TRIGGERED; ++ } ++ else if (!self->start.requirement && !self->start.alternative) { ++ /* start trigger is empty. assume the leaderboard is in development and ignore */ ++ } ++ else { ++ /* start the leaderboard attempt */ ++ self->state = RC_LBOARD_STATE_STARTED; ++ } ++ ++ /* reset any hit counts in the value */ ++ if (self->progress) ++ rc_reset_value(self->progress); ++ ++ rc_reset_value(&self->value); ++ } ++ break; ++ ++ case RC_LBOARD_STATE_STARTED: ++ /* leaderboard attempt in progress */ ++ if (cancel_ok) { ++ /* cancel condition is true, abort the attempt */ ++ self->state = RC_LBOARD_STATE_CANCELED; ++ } ++ else if (submit_ok) { ++ /* submit condition is true, submit the current value */ ++ self->state = RC_LBOARD_STATE_TRIGGERED; ++ } ++ break; ++ } ++ ++ /* Calculate the value */ ++ switch (self->state) { ++ case RC_LBOARD_STATE_STARTED: ++ if (self->progress) { ++ *value = rc_evaluate_value(self->progress, peek, peek_ud, unused_L); ++ break; ++ } ++ /* fallthrough */ /* to RC_LBOARD_STATE_TRIGGERED */ ++ ++ case RC_LBOARD_STATE_TRIGGERED: ++ *value = rc_evaluate_value(&self->value, peek, peek_ud, unused_L); ++ break; ++ ++ default: ++ *value = 0; ++ break; ++ } ++ ++ return self->state; ++} ++ ++int rc_lboard_state_active(int state) { ++ switch (state) ++ { ++ case RC_LBOARD_STATE_DISABLED: ++ case RC_LBOARD_STATE_INACTIVE: ++ return 0; ++ ++ default: ++ return 1; ++ } ++} ++ ++void rc_reset_lboard(rc_lboard_t* self) { ++ if (!self) ++ return; ++ ++ self->state = RC_LBOARD_STATE_WAITING; ++ ++ rc_reset_trigger(&self->start); ++ rc_reset_trigger(&self->submit); ++ rc_reset_trigger(&self->cancel); ++ ++ if (self->progress) ++ rc_reset_value(self->progress); ++ ++ rc_reset_value(&self->value); ++} +diff -rupbN melonDS.orig/src/rcheevos/src/rcheevos/memref.c melonDS.ra/src/rcheevos/src/rcheevos/memref.c +--- melonDS.orig/src/rcheevos/src/rcheevos/memref.c 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rcheevos/memref.c 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,805 @@ ++#include "rc_internal.h" ++ ++#include /* malloc/realloc */ ++#include /* memcpy */ ++#include /* INFINITY/NAN */ ++ ++#define MEMREF_PLACEHOLDER_ADDRESS 0xFFFFFFFF ++ ++rc_memref_t* rc_alloc_memref(rc_parse_state_t* parse, uint32_t address, uint8_t size) { ++ rc_memref_list_t* memref_list = NULL; ++ rc_memref_t* memref = NULL; ++ int i; ++ ++ for (i = 0; i < 2; i++) { ++ if (i == 0) { ++ if (!parse->existing_memrefs) ++ continue; ++ ++ memref_list = &parse->existing_memrefs->memrefs; ++ } ++ else { ++ memref_list = &parse->memrefs->memrefs; ++ } ++ ++ do ++ { ++ const rc_memref_t* memref_stop; ++ ++ memref = memref_list->items; ++ memref_stop = memref + memref_list->count; ++ ++ for (; memref < memref_stop; ++memref) { ++ if (memref->address == address && memref->value.size == size) ++ return memref; ++ } ++ ++ if (!memref_list->next) ++ break; ++ ++ memref_list = memref_list->next; ++ } while (1); ++ } ++ ++ /* no match found, find a place to put the new entry */ ++ memref_list = &parse->memrefs->memrefs; ++ while (memref_list->count == memref_list->capacity && memref_list->next) ++ memref_list = memref_list->next; ++ ++ /* create a new entry */ ++ if (memref_list->count < memref_list->capacity) { ++ memref = &memref_list->items[memref_list->count++]; ++ } else { ++ const int32_t old_offset = parse->offset; ++ ++ if (memref_list->capacity != 0) { ++ memref_list = memref_list->next = RC_ALLOC_SCRATCH(rc_memref_list_t, parse); ++ memref_list->next = NULL; ++ } ++ ++ memref_list->items = RC_ALLOC_ARRAY_SCRATCH(rc_memref_t, 8, parse); ++ memref_list->count = 1; ++ memref_list->capacity = 8; ++ memref_list->allocated = 0; ++ ++ memref = memref_list->items; ++ ++ /* in preparse mode, don't count this memory, we'll do a single allocation once we have ++ * the final total */ ++ if (!parse->buffer) ++ parse->offset = old_offset; ++ } ++ ++ memset(memref, 0, sizeof(*memref)); ++ memref->value.memref_type = RC_MEMREF_TYPE_MEMREF; ++ memref->value.type = RC_VALUE_TYPE_UNSIGNED; ++ memref->value.size = size; ++ memref->address = address; ++ ++ return memref; ++} ++ ++rc_modified_memref_t* rc_alloc_modified_memref(rc_parse_state_t* parse, uint8_t size, const rc_operand_t* parent, ++ uint8_t modifier_type, const rc_operand_t* modifier) { ++ rc_modified_memref_list_t* modified_memref_list = NULL; ++ rc_modified_memref_t* modified_memref = NULL; ++ int i = 0; ++ ++ for (i = 0; i < 2; i++) { ++ if (i == 0) { ++ if (!parse->existing_memrefs) ++ continue; ++ ++ modified_memref_list = &parse->existing_memrefs->modified_memrefs; ++ } ++ else { ++ modified_memref_list = &parse->memrefs->modified_memrefs; ++ } ++ ++ do { ++ const rc_modified_memref_t* memref_stop; ++ ++ modified_memref = modified_memref_list->items; ++ memref_stop = modified_memref + modified_memref_list->count; ++ ++ for (; modified_memref < memref_stop; ++modified_memref) { ++ if (modified_memref->memref.value.size == size && ++ modified_memref->modifier_type == modifier_type && ++ rc_operands_are_equal(&modified_memref->parent, parent) && ++ rc_operands_are_equal(&modified_memref->modifier, modifier)) { ++ return modified_memref; ++ } ++ } ++ ++ if (!modified_memref_list->next) ++ break; ++ ++ modified_memref_list = modified_memref_list->next; ++ } while (1); ++ } ++ ++ /* no match found, find a place to put the new entry */ ++ modified_memref_list = &parse->memrefs->modified_memrefs; ++ while (modified_memref_list->count == modified_memref_list->capacity && modified_memref_list->next) ++ modified_memref_list = modified_memref_list->next; ++ ++ /* create a new entry */ ++ if (modified_memref_list->count < modified_memref_list->capacity) { ++ modified_memref = &modified_memref_list->items[modified_memref_list->count++]; ++ } else { ++ const int32_t old_offset = parse->offset; ++ ++ if (modified_memref_list->capacity != 0) { ++ modified_memref_list = modified_memref_list->next = RC_ALLOC_SCRATCH(rc_modified_memref_list_t, parse); ++ modified_memref_list->next = NULL; ++ } ++ ++ modified_memref_list->items = RC_ALLOC_ARRAY_SCRATCH(rc_modified_memref_t, 8, parse); ++ modified_memref_list->count = 1; ++ modified_memref_list->capacity = 8; ++ modified_memref_list->allocated = 0; ++ ++ modified_memref = modified_memref_list->items; ++ ++ /* in preparse mode, don't count this memory, we'll do a single allocation once we have ++ * the final total */ ++ if (!parse->buffer) ++ parse->offset = old_offset; ++ } ++ ++ memset(modified_memref, 0, sizeof(*modified_memref)); ++ modified_memref->memref.value.memref_type = RC_MEMREF_TYPE_MODIFIED_MEMREF; ++ modified_memref->memref.value.size = size; ++ modified_memref->memref.value.type = rc_memsize_is_float(size) ? RC_VALUE_TYPE_FLOAT : RC_VALUE_TYPE_UNSIGNED; ++ memcpy(&modified_memref->parent, parent, sizeof(modified_memref->parent)); ++ memcpy(&modified_memref->modifier, modifier, sizeof(modified_memref->modifier)); ++ modified_memref->modifier_type = modifier_type; ++ modified_memref->depth = 0; ++ modified_memref->memref.address = rc_operand_is_memref(modifier) ? modifier->value.memref->address : modifier->value.num; ++ ++ if (rc_operand_is_memref(parent) && parent->value.memref->value.memref_type == RC_MEMREF_TYPE_MODIFIED_MEMREF) { ++ const rc_modified_memref_t* parent_modified_memref = (rc_modified_memref_t*)parent->value.memref; ++ modified_memref->depth = parent_modified_memref->depth + 1; ++ } ++ ++ return modified_memref; ++} ++ ++void rc_memrefs_init(rc_memrefs_t* memrefs) ++{ ++ memset(memrefs, 0, sizeof(*memrefs)); ++ ++ memrefs->memrefs.capacity = 32; ++ memrefs->memrefs.items = ++ (rc_memref_t*)malloc(memrefs->memrefs.capacity * sizeof(rc_memref_t)); ++ memrefs->memrefs.allocated = 1; ++ ++ memrefs->modified_memrefs.capacity = 16; ++ memrefs->modified_memrefs.items = ++ (rc_modified_memref_t*)malloc(memrefs->modified_memrefs.capacity * sizeof(rc_modified_memref_t)); ++ memrefs->modified_memrefs.allocated = 1; ++} ++ ++void rc_memrefs_destroy(rc_memrefs_t* memrefs) ++{ ++ rc_memref_list_t* memref_list = &memrefs->memrefs; ++ rc_modified_memref_list_t* modified_memref_list = &memrefs->modified_memrefs; ++ ++ do { ++ rc_memref_list_t* current_memref_list = memref_list; ++ memref_list = memref_list->next; ++ ++ if (current_memref_list->allocated) { ++ if (current_memref_list->items) ++ free(current_memref_list->items); ++ ++ if (current_memref_list != &memrefs->memrefs) ++ free(current_memref_list); ++ } ++ } while (memref_list); ++ ++ do { ++ rc_modified_memref_list_t* current_modified_memref_list = modified_memref_list; ++ modified_memref_list = modified_memref_list->next; ++ ++ if (current_modified_memref_list->allocated) { ++ if (current_modified_memref_list->items) ++ free(current_modified_memref_list->items); ++ ++ if (current_modified_memref_list != &memrefs->modified_memrefs) ++ free(current_modified_memref_list); ++ } ++ } while (modified_memref_list); ++ ++ free(memrefs); ++} ++ ++uint32_t rc_memrefs_count_memrefs(const rc_memrefs_t* memrefs) ++{ ++ uint32_t count = 0; ++ const rc_memref_list_t* memref_list = &memrefs->memrefs; ++ while (memref_list) { ++ count += memref_list->count; ++ memref_list = memref_list->next; ++ } ++ ++ return count; ++} ++ ++uint32_t rc_memrefs_count_modified_memrefs(const rc_memrefs_t* memrefs) ++{ ++ uint32_t count = 0; ++ const rc_modified_memref_list_t* modified_memref_list = &memrefs->modified_memrefs; ++ while (modified_memref_list) { ++ count += modified_memref_list->count; ++ modified_memref_list = modified_memref_list->next; ++ } ++ ++ return count; ++} ++ ++int rc_parse_memref(const char** memaddr, uint8_t* size, uint32_t* address) { ++ const char* aux = *memaddr; ++ char* end; ++ unsigned long value; ++ ++ if (aux[0] == '0') { ++ if (aux[1] != 'x' && aux[1] != 'X') ++ return RC_INVALID_MEMORY_OPERAND; ++ ++ aux += 2; ++ switch (*aux++) { ++ /* ordered by estimated frequency in case compiler doesn't build a jump table */ ++ case 'h': case 'H': *size = RC_MEMSIZE_8_BITS; break; ++ case ' ': *size = RC_MEMSIZE_16_BITS; break; ++ case 'x': case 'X': *size = RC_MEMSIZE_32_BITS; break; ++ ++ case 'm': case 'M': *size = RC_MEMSIZE_BIT_0; break; ++ case 'n': case 'N': *size = RC_MEMSIZE_BIT_1; break; ++ case 'o': case 'O': *size = RC_MEMSIZE_BIT_2; break; ++ case 'p': case 'P': *size = RC_MEMSIZE_BIT_3; break; ++ case 'q': case 'Q': *size = RC_MEMSIZE_BIT_4; break; ++ case 'r': case 'R': *size = RC_MEMSIZE_BIT_5; break; ++ case 's': case 'S': *size = RC_MEMSIZE_BIT_6; break; ++ case 't': case 'T': *size = RC_MEMSIZE_BIT_7; break; ++ case 'l': case 'L': *size = RC_MEMSIZE_LOW; break; ++ case 'u': case 'U': *size = RC_MEMSIZE_HIGH; break; ++ case 'k': case 'K': *size = RC_MEMSIZE_BITCOUNT; break; ++ case 'w': case 'W': *size = RC_MEMSIZE_24_BITS; break; ++ case 'g': case 'G': *size = RC_MEMSIZE_32_BITS_BE; break; ++ case 'i': case 'I': *size = RC_MEMSIZE_16_BITS_BE; break; ++ case 'j': case 'J': *size = RC_MEMSIZE_24_BITS_BE; break; ++ ++ /* case 'v': case 'V': */ ++ /* case 'y': case 'Y': 64 bit? */ ++ /* case 'z': case 'Z': 128 bit? */ ++ ++ case '0': ++ if (*aux == 'x') /* user mistyped an extra 0x: 0x0xabcd */ ++ return RC_INVALID_MEMORY_OPERAND; ++ /* fallthrough */ ++ ++ case '1': case '2': case '3': case '4': ++ case '5': case '6': case '7': case '8': case '9': ++ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': ++ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': ++ /* legacy support - addresses without a size prefix are assumed to be 16-bit */ ++ aux--; ++ *size = RC_MEMSIZE_16_BITS; ++ break; ++ ++ default: ++ return RC_INVALID_MEMORY_OPERAND; ++ } ++ } ++ else if (aux[0] == 'f' || aux[0] == 'F') { ++ ++aux; ++ switch (*aux++) { ++ case 'f': case 'F': *size = RC_MEMSIZE_FLOAT; break; ++ case 'b': case 'B': *size = RC_MEMSIZE_FLOAT_BE; break; ++ case 'h': case 'H': *size = RC_MEMSIZE_DOUBLE32; break; ++ case 'i': case 'I': *size = RC_MEMSIZE_DOUBLE32_BE; break; ++ case 'm': case 'M': *size = RC_MEMSIZE_MBF32; break; ++ case 'l': case 'L': *size = RC_MEMSIZE_MBF32_LE; break; ++ ++ default: ++ return RC_INVALID_FP_OPERAND; ++ } ++ } ++ else { ++ return RC_INVALID_MEMORY_OPERAND; ++ } ++ ++ value = strtoul(aux, &end, 16); ++ ++ if (end == aux) ++ return RC_INVALID_MEMORY_OPERAND; ++ ++ if (value > 0xffffffffU) ++ value = 0xffffffffU; ++ ++ *address = (uint32_t)value; ++ *memaddr = end; ++ return RC_OK; ++} ++ ++static float rc_build_float(uint32_t mantissa_bits, int32_t exponent, int sign) { ++ /* 32-bit float has a 23-bit mantissa and 8-bit exponent */ ++ const uint32_t implied_bit = 1 << 23; ++ const uint32_t mantissa = mantissa_bits | implied_bit; ++ double dbl = ((double)mantissa) / ((double)implied_bit); ++ ++ if (exponent > 127) { ++ /* exponent above 127 is a special number */ ++ if (mantissa_bits == 0) { ++ /* infinity */ ++#ifdef INFINITY /* INFINITY and NAN #defines require C99 */ ++ dbl = (double)INFINITY; ++#else ++ dbl = -log(0.0); ++#endif ++ } ++ else { ++ /* NaN */ ++#ifdef NAN ++ dbl = NAN; ++#else ++ dbl = -sqrt(-1); ++#endif ++ } ++ } ++ else if (exponent > 0) { ++ /* exponent from 1 to 127 is a number greater than 1 */ ++ while (exponent > 30) { ++ dbl *= (double)(1 << 30); ++ exponent -= 30; ++ } ++ dbl *= (double)((long long)1 << exponent); ++ } ++ else if (exponent < 0) { ++ /* exponent from -1 to -127 is a number less than 1 */ ++ ++ if (exponent == -127) { ++ /* exponent -127 (all exponent bits were zero) is a denormalized value ++ * (no implied leading bit) with exponent -126 */ ++ dbl = ((double)mantissa_bits) / ((double)implied_bit); ++ exponent = 126; ++ } else { ++ exponent = -exponent; ++ } ++ ++ while (exponent > 30) { ++ dbl /= (double)(1 << 30); ++ exponent -= 30; ++ } ++ dbl /= (double)((long long)1 << exponent); ++ } ++ else { ++ /* exponent of 0 requires no adjustment */ ++ } ++ ++ return (sign) ? (float)-dbl : (float)dbl; ++} ++ ++static void rc_transform_memref_float(rc_typed_value_t* value) { ++ /* decodes an IEEE 754 float */ ++ const uint32_t mantissa = (value->value.u32 & 0x7FFFFF); ++ const int32_t exponent = (int32_t)((value->value.u32 >> 23) & 0xFF) - 127; ++ const int sign = (value->value.u32 & 0x80000000); ++ value->value.f32 = rc_build_float(mantissa, exponent, sign); ++ value->type = RC_VALUE_TYPE_FLOAT; ++} ++ ++static void rc_transform_memref_float_be(rc_typed_value_t* value) { ++ /* decodes an IEEE 754 float in big endian format */ ++ const uint32_t mantissa = ((value->value.u32 & 0xFF000000) >> 24) | ++ ((value->value.u32 & 0x00FF0000) >> 8) | ++ ((value->value.u32 & 0x00007F00) << 8); ++ const int32_t exponent = (int32_t)(((value->value.u32 & 0x0000007F) << 1) | ++ ((value->value.u32 & 0x00008000) >> 15)) - 127; ++ const int sign = (value->value.u32 & 0x00000080); ++ value->value.f32 = rc_build_float(mantissa, exponent, sign); ++ value->type = RC_VALUE_TYPE_FLOAT; ++} ++ ++static void rc_transform_memref_double32(rc_typed_value_t* value) ++{ ++ /* decodes the four most significant bytes of an IEEE 754 double into a float */ ++ const uint32_t mantissa = (value->value.u32 & 0x000FFFFF) << 3; ++ const int32_t exponent = (int32_t)((value->value.u32 >> 20) & 0x7FF) - 1023; ++ const int sign = (value->value.u32 & 0x80000000); ++ value->value.f32 = rc_build_float(mantissa, exponent, sign); ++ value->type = RC_VALUE_TYPE_FLOAT; ++} ++ ++static void rc_transform_memref_double32_be(rc_typed_value_t* value) ++{ ++ /* decodes the four most significant bytes of an IEEE 754 double in big endian format into a float */ ++ const uint32_t mantissa = (((value->value.u32 & 0xFF000000) >> 24) | ++ ((value->value.u32 & 0x00FF0000) >> 8) | ++ ((value->value.u32 & 0x00000F00) << 8)) << 3; ++ const int32_t exponent = (int32_t)(((value->value.u32 & 0x0000007F) << 4) | ++ ((value->value.u32 & 0x0000F000) >> 12)) - 1023; ++ const int sign = (value->value.u32 & 0x00000080); ++ value->value.f32 = rc_build_float(mantissa, exponent, sign); ++ value->type = RC_VALUE_TYPE_FLOAT; ++} ++ ++static void rc_transform_memref_mbf32(rc_typed_value_t* value) { ++ /* decodes a Microsoft Binary Format float */ ++ /* NOTE: 32-bit MBF is stored in memory as big endian (at least for Apple II) */ ++ const uint32_t mantissa = ((value->value.u32 & 0xFF000000) >> 24) | ++ ((value->value.u32 & 0x00FF0000) >> 8) | ++ ((value->value.u32 & 0x00007F00) << 8); ++ const int32_t exponent = (int32_t)(value->value.u32 & 0xFF) - 129; ++ const int sign = (value->value.u32 & 0x00008000); ++ ++ if (mantissa == 0 && exponent == -129) ++ value->value.f32 = (sign) ? -0.0f : 0.0f; ++ else ++ value->value.f32 = rc_build_float(mantissa, exponent, sign); ++ ++ value->type = RC_VALUE_TYPE_FLOAT; ++} ++ ++static void rc_transform_memref_mbf32_le(rc_typed_value_t* value) { ++ /* decodes a Microsoft Binary Format float */ ++ /* Locomotive BASIC (CPC) uses MBF40, but in little endian format */ ++ const uint32_t mantissa = value->value.u32 & 0x007FFFFF; ++ const int32_t exponent = (int32_t)(value->value.u32 >> 24) - 129; ++ const int sign = (value->value.u32 & 0x00800000); ++ ++ if (mantissa == 0 && exponent == -129) ++ value->value.f32 = (sign) ? -0.0f : 0.0f; ++ else ++ value->value.f32 = rc_build_float(mantissa, exponent, sign); ++ ++ value->type = RC_VALUE_TYPE_FLOAT; ++} ++ ++static const uint8_t rc_bits_set[16] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4 }; ++ ++void rc_transform_memref_value(rc_typed_value_t* value, uint8_t size) { ++ /* ASSERT: value->type == RC_VALUE_TYPE_UNSIGNED */ ++ switch (size) ++ { ++ case RC_MEMSIZE_8_BITS: ++ value->value.u32 = (value->value.u32 & 0x000000ff); ++ break; ++ ++ case RC_MEMSIZE_16_BITS: ++ value->value.u32 = (value->value.u32 & 0x0000ffff); ++ break; ++ ++ case RC_MEMSIZE_24_BITS: ++ value->value.u32 = (value->value.u32 & 0x00ffffff); ++ break; ++ ++ case RC_MEMSIZE_32_BITS: ++ break; ++ ++ case RC_MEMSIZE_BIT_0: ++ value->value.u32 = (value->value.u32 >> 0) & 1; ++ break; ++ ++ case RC_MEMSIZE_BIT_1: ++ value->value.u32 = (value->value.u32 >> 1) & 1; ++ break; ++ ++ case RC_MEMSIZE_BIT_2: ++ value->value.u32 = (value->value.u32 >> 2) & 1; ++ break; ++ ++ case RC_MEMSIZE_BIT_3: ++ value->value.u32 = (value->value.u32 >> 3) & 1; ++ break; ++ ++ case RC_MEMSIZE_BIT_4: ++ value->value.u32 = (value->value.u32 >> 4) & 1; ++ break; ++ ++ case RC_MEMSIZE_BIT_5: ++ value->value.u32 = (value->value.u32 >> 5) & 1; ++ break; ++ ++ case RC_MEMSIZE_BIT_6: ++ value->value.u32 = (value->value.u32 >> 6) & 1; ++ break; ++ ++ case RC_MEMSIZE_BIT_7: ++ value->value.u32 = (value->value.u32 >> 7) & 1; ++ break; ++ ++ case RC_MEMSIZE_LOW: ++ value->value.u32 = value->value.u32 & 0x0f; ++ break; ++ ++ case RC_MEMSIZE_HIGH: ++ value->value.u32 = (value->value.u32 >> 4) & 0x0f; ++ break; ++ ++ case RC_MEMSIZE_BITCOUNT: ++ value->value.u32 = rc_bits_set[(value->value.u32 & 0x0F)] ++ + rc_bits_set[((value->value.u32 >> 4) & 0x0F)]; ++ break; ++ ++ case RC_MEMSIZE_16_BITS_BE: ++ value->value.u32 = ((value->value.u32 & 0xFF00) >> 8) | ++ ((value->value.u32 & 0x00FF) << 8); ++ break; ++ ++ case RC_MEMSIZE_24_BITS_BE: ++ value->value.u32 = ((value->value.u32 & 0xFF0000) >> 16) | ++ (value->value.u32 & 0x00FF00) | ++ ((value->value.u32 & 0x0000FF) << 16); ++ break; ++ ++ case RC_MEMSIZE_32_BITS_BE: ++ value->value.u32 = ((value->value.u32 & 0xFF000000) >> 24) | ++ ((value->value.u32 & 0x00FF0000) >> 8) | ++ ((value->value.u32 & 0x0000FF00) << 8) | ++ ((value->value.u32 & 0x000000FF) << 24); ++ break; ++ ++ case RC_MEMSIZE_FLOAT: ++ rc_transform_memref_float(value); ++ break; ++ ++ case RC_MEMSIZE_FLOAT_BE: ++ rc_transform_memref_float_be(value); ++ break; ++ ++ case RC_MEMSIZE_DOUBLE32: ++ rc_transform_memref_double32(value); ++ break; ++ ++ case RC_MEMSIZE_DOUBLE32_BE: ++ rc_transform_memref_double32_be(value); ++ break; ++ ++ case RC_MEMSIZE_MBF32: ++ rc_transform_memref_mbf32(value); ++ break; ++ ++ case RC_MEMSIZE_MBF32_LE: ++ rc_transform_memref_mbf32_le(value); ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++static const uint32_t rc_memref_masks[] = { ++ 0x000000ff, /* RC_MEMSIZE_8_BITS */ ++ 0x0000ffff, /* RC_MEMSIZE_16_BITS */ ++ 0x00ffffff, /* RC_MEMSIZE_24_BITS */ ++ 0xffffffff, /* RC_MEMSIZE_32_BITS */ ++ 0x0000000f, /* RC_MEMSIZE_LOW */ ++ 0x000000f0, /* RC_MEMSIZE_HIGH */ ++ 0x00000001, /* RC_MEMSIZE_BIT_0 */ ++ 0x00000002, /* RC_MEMSIZE_BIT_1 */ ++ 0x00000004, /* RC_MEMSIZE_BIT_2 */ ++ 0x00000008, /* RC_MEMSIZE_BIT_3 */ ++ 0x00000010, /* RC_MEMSIZE_BIT_4 */ ++ 0x00000020, /* RC_MEMSIZE_BIT_5 */ ++ 0x00000040, /* RC_MEMSIZE_BIT_6 */ ++ 0x00000080, /* RC_MEMSIZE_BIT_7 */ ++ 0x000000ff, /* RC_MEMSIZE_BITCOUNT */ ++ 0x0000ffff, /* RC_MEMSIZE_16_BITS_BE */ ++ 0x00ffffff, /* RC_MEMSIZE_24_BITS_BE */ ++ 0xffffffff, /* RC_MEMSIZE_32_BITS_BE */ ++ 0xffffffff, /* RC_MEMSIZE_FLOAT */ ++ 0xffffffff, /* RC_MEMSIZE_MBF32 */ ++ 0xffffffff, /* RC_MEMSIZE_MBF32_LE */ ++ 0xffffffff, /* RC_MEMSIZE_FLOAT_BE */ ++ 0xffffffff, /* RC_MEMSIZE_DOUBLE32 */ ++ 0xffffffff, /* RC_MEMSIZE_DOUBLE32_BE*/ ++ 0xffffffff /* RC_MEMSIZE_VARIABLE */ ++}; ++ ++uint32_t rc_memref_mask(uint8_t size) { ++ const size_t index = (size_t)size; ++ if (index >= sizeof(rc_memref_masks) / sizeof(rc_memref_masks[0])) ++ return 0xffffffff; ++ ++ return rc_memref_masks[index]; ++} ++ ++/* all sizes less than 8-bits (1 byte) are mapped to 8-bits. 24-bit is mapped to 32-bit ++ * as we don't expect the client to understand a request for 3 bytes. all other reads are ++ * mapped to the little-endian read of the same size. */ ++static const uint8_t rc_memref_shared_sizes[] = { ++ RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_8_BITS */ ++ RC_MEMSIZE_16_BITS, /* RC_MEMSIZE_16_BITS */ ++ RC_MEMSIZE_32_BITS, /* RC_MEMSIZE_24_BITS */ ++ RC_MEMSIZE_32_BITS, /* RC_MEMSIZE_32_BITS */ ++ RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_LOW */ ++ RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_HIGH */ ++ RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_BIT_0 */ ++ RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_BIT_1 */ ++ RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_BIT_2 */ ++ RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_BIT_3 */ ++ RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_BIT_4 */ ++ RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_BIT_5 */ ++ RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_BIT_6 */ ++ RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_BIT_7 */ ++ RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_BITCOUNT */ ++ RC_MEMSIZE_16_BITS, /* RC_MEMSIZE_16_BITS_BE */ ++ RC_MEMSIZE_32_BITS, /* RC_MEMSIZE_24_BITS_BE */ ++ RC_MEMSIZE_32_BITS, /* RC_MEMSIZE_32_BITS_BE */ ++ RC_MEMSIZE_32_BITS, /* RC_MEMSIZE_FLOAT */ ++ RC_MEMSIZE_32_BITS, /* RC_MEMSIZE_MBF32 */ ++ RC_MEMSIZE_32_BITS, /* RC_MEMSIZE_MBF32_LE */ ++ RC_MEMSIZE_32_BITS, /* RC_MEMSIZE_FLOAT_BE */ ++ RC_MEMSIZE_32_BITS, /* RC_MEMSIZE_DOUBLE32 */ ++ RC_MEMSIZE_32_BITS, /* RC_MEMSIZE_DOUBLE32_BE*/ ++ RC_MEMSIZE_32_BITS /* RC_MEMSIZE_VARIABLE */ ++}; ++ ++uint8_t rc_memref_shared_size(uint8_t size) { ++ const size_t index = (size_t)size; ++ if (index >= sizeof(rc_memref_shared_sizes) / sizeof(rc_memref_shared_sizes[0])) ++ return size; ++ ++ return rc_memref_shared_sizes[index]; ++} ++ ++uint32_t rc_peek_value(uint32_t address, uint8_t size, rc_peek_t peek, void* ud) { ++ if (!peek) ++ return 0; ++ ++ switch (size) ++ { ++ case RC_MEMSIZE_8_BITS: ++ return peek(address, 1, ud); ++ ++ case RC_MEMSIZE_16_BITS: ++ return peek(address, 2, ud); ++ ++ case RC_MEMSIZE_32_BITS: ++ return peek(address, 4, ud); ++ ++ default: ++ { ++ uint32_t value; ++ const size_t index = (size_t)size; ++ if (index >= sizeof(rc_memref_shared_sizes) / sizeof(rc_memref_shared_sizes[0])) ++ return 0; ++ ++ /* fetch the larger value and mask off the bits associated to the specified size ++ * for correct deduction of prior value. non-prior memrefs should already be using ++ * shared size memrefs to minimize the total number of memory reads required. */ ++ value = rc_peek_value(address, rc_memref_shared_sizes[index], peek, ud); ++ return value & rc_memref_masks[index]; ++ } ++ } ++} ++ ++void rc_update_memref_value(rc_memref_value_t* memref, uint32_t new_value) { ++ if (memref->value == new_value) { ++ memref->changed = 0; ++ } ++ else { ++ memref->prior = memref->value; ++ memref->value = new_value; ++ memref->changed = 1; ++ } ++} ++ ++void rc_init_parse_state_memrefs(rc_parse_state_t* parse, rc_memrefs_t* memrefs) ++{ ++ if (memrefs) ++ memset(memrefs, 0, sizeof(*memrefs)); ++ ++ parse->memrefs = memrefs; ++} ++ ++static uint32_t rc_get_memref_value_value(const rc_memref_value_t* memref, int operand_type) { ++ switch (operand_type) ++ { ++ /* most common case explicitly first, even though it could be handled by default case. ++ * this helps the compiler to optimize if it turns the switch into a series of if/elses */ ++ case RC_OPERAND_ADDRESS: ++ return memref->value; ++ ++ case RC_OPERAND_DELTA: ++ if (!memref->changed) { ++ /* fallthrough */ ++ default: ++ return memref->value; ++ } ++ /* fallthrough */ ++ case RC_OPERAND_PRIOR: ++ return memref->prior; ++ } ++} ++ ++void rc_get_memref_value(rc_typed_value_t* value, rc_memref_t* memref, int operand_type) { ++ value->type = memref->value.type; ++ value->value.u32 = rc_get_memref_value_value(&memref->value, operand_type); ++} ++ ++uint32_t rc_get_modified_memref_value(const rc_modified_memref_t* memref, rc_peek_t peek, void* ud) { ++ rc_typed_value_t value, modifier; ++ ++ rc_evaluate_operand(&value, &memref->parent, NULL); ++ rc_evaluate_operand(&modifier, &memref->modifier, NULL); ++ ++ switch (memref->modifier_type) { ++ case RC_OPERATOR_INDIRECT_READ: ++ rc_typed_value_add(&value, &modifier); ++ rc_typed_value_convert(&value, RC_VALUE_TYPE_UNSIGNED); ++ value.value.u32 = rc_peek_value(value.value.u32, memref->memref.value.size, peek, ud); ++ value.type = memref->memref.value.type; ++ break; ++ ++ case RC_OPERATOR_SUB_PARENT: ++ /* sub parent is "-parent + modifier" */ ++ rc_typed_value_negate(&value); ++ rc_typed_value_add(&value, &modifier); ++ rc_typed_value_convert(&value, memref->memref.value.type); ++ break; ++ ++ case RC_OPERATOR_SUB_ACCUMULATOR: ++ rc_typed_value_negate(&modifier); ++ /* fallthrough */ /* to case RC_OPERATOR_SUB_ACCUMULATOR */ ++ ++ case RC_OPERATOR_ADD_ACCUMULATOR: ++ /* when modifying the accumulator, force the modifier to match the accumulator ++ * type instead of promoting them both to the less restrictive type. ++ * ++ * 18 - 17.5 will result in an integer. should it be 0 or 1? ++ * ++ * default: float is less restrictive, convert both to float for combine, ++ * then convert to the memref type. ++ * (int)((float)18 - 17.5) -> (int)(0.5) -> 0 ++ * ++ * accumulator is integer: force modifier to be integer before combining ++ * (int)(18 - (int)17.5) -> (int)(18 - 17) -> 1 ++ */ ++ rc_typed_value_convert(&modifier, value.type); ++ rc_typed_value_add(&value, &modifier); ++ rc_typed_value_convert(&value, memref->memref.value.type); ++ break; ++ ++ default: ++ rc_typed_value_combine(&value, &modifier, memref->modifier_type); ++ rc_typed_value_convert(&value, memref->memref.value.type); ++ break; ++ } ++ ++ return value.value.u32; ++} ++ ++void rc_update_memref_values(rc_memrefs_t* memrefs, rc_peek_t peek, void* ud) { ++ rc_memref_list_t* memref_list; ++ rc_modified_memref_list_t* modified_memref_list; ++ ++ memref_list = &memrefs->memrefs; ++ do ++ { ++ rc_memref_t* memref = memref_list->items; ++ const rc_memref_t* memref_stop = memref + memref_list->count; ++ ++ for (; memref < memref_stop; ++memref) { ++ if (memref->value.type != RC_VALUE_TYPE_NONE) ++ rc_update_memref_value(&memref->value, rc_peek_value(memref->address, memref->value.size, peek, ud)); ++ } ++ ++ memref_list = memref_list->next; ++ } while (memref_list); ++ ++ modified_memref_list = &memrefs->modified_memrefs; ++ if (modified_memref_list->count) { ++ do { ++ rc_modified_memref_t* modified_memref = modified_memref_list->items; ++ const rc_modified_memref_t* modified_memref_stop = modified_memref + modified_memref_list->count; ++ ++ for (; modified_memref < modified_memref_stop; ++modified_memref) ++ rc_update_memref_value(&modified_memref->memref.value, rc_get_modified_memref_value(modified_memref, peek, ud)); ++ ++ modified_memref_list = modified_memref_list->next; ++ } while (modified_memref_list); ++ } ++} +diff -rupbN melonDS.orig/src/rcheevos/src/rcheevos/operand.c melonDS.ra/src/rcheevos/src/rcheevos/operand.c +--- melonDS.orig/src/rcheevos/src/rcheevos/operand.c 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rcheevos/operand.c 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,607 @@ ++#include "rc_internal.h" ++ ++#include ++#include ++#include ++#include ++ ++static int rc_parse_operand_func_call(rc_operand_t* self, const char** memaddr) { ++ const char* aux = *memaddr; ++ ++ if (*aux++ != '@') { ++ return RC_INVALID_FUNC_OPERAND; ++ } ++ ++ if (!isalpha((unsigned char)*aux)) { ++ return RC_INVALID_FUNC_OPERAND; ++ } ++ ++ while (isalnum((unsigned char)*aux) || *aux == '_') { ++ aux++; ++ } ++ ++ self->type = RC_OPERAND_FUNC; ++ self->size = RC_MEMSIZE_32_BITS; ++ self->memref_access_type = RC_OPERAND_ADDRESS; ++ *memaddr = aux; ++ return RC_OK; ++} ++ ++static int rc_parse_operand_variable(rc_operand_t* self, const char** memaddr, rc_parse_state_t* parse) { ++ const char* aux = *memaddr; ++ size_t i; ++ char varName[RC_VALUE_MAX_NAME_LENGTH + 1] = { 0 }; ++ ++ for (i = 0; i < RC_VALUE_MAX_NAME_LENGTH && *aux != '}'; i++) { ++ if (!rc_is_valid_variable_character(*aux, i == 0)) ++ return RC_INVALID_VARIABLE_NAME; ++ ++ varName[i] = *aux++; ++ } ++ ++ if (i == 0) ++ return RC_INVALID_VARIABLE_NAME; ++ ++ if (*aux != '}') ++ return RC_INVALID_VARIABLE_NAME; ++ ++ ++aux; ++ ++ if (strcmp(varName, "recall") == 0) { ++ if (parse->remember.type == RC_OPERAND_NONE) { ++ self->value.memref = NULL; ++ self->size = RC_MEMSIZE_32_BITS; ++ self->memref_access_type = RC_OPERAND_ADDRESS; ++ } ++ else { ++ memcpy(self, &parse->remember, sizeof(*self)); ++ self->is_combining = 0; ++ self->memref_access_type = self->type; ++ } ++ self->type = RC_OPERAND_RECALL; ++ } ++ else { /* process named variable when feature is available.*/ ++ return RC_UNKNOWN_VARIABLE_NAME; ++ } ++ ++ *memaddr = aux; ++ return RC_OK; ++} ++ ++static int rc_parse_operand_memory(rc_operand_t* self, const char** memaddr, rc_parse_state_t* parse) { ++ const char* aux = *memaddr; ++ uint32_t address; ++ uint8_t size; ++ int ret; ++ ++ switch (*aux) { ++ case 'd': case 'D': ++ self->type = RC_OPERAND_DELTA; ++ ++aux; ++ break; ++ ++ case 'p': case 'P': ++ self->type = RC_OPERAND_PRIOR; ++ ++aux; ++ break; ++ ++ case 'b': case 'B': ++ self->type = RC_OPERAND_BCD; ++ ++aux; ++ break; ++ ++ case '~': ++ self->type = RC_OPERAND_INVERTED; ++ ++aux; ++ break; ++ ++ default: ++ self->type = RC_OPERAND_ADDRESS; ++ break; ++ } ++ ++ self->memref_access_type = self->type; ++ ++ ret = rc_parse_memref(&aux, &self->size, &address); ++ if (ret != RC_OK) ++ return ret; ++ ++ size = rc_memref_shared_size(self->size); ++ if (size != self->size && self->type == RC_OPERAND_PRIOR) { ++ /* if the shared size differs from the requested size and it's a prior operation, we ++ * have to check to make sure both sizes use the same mask, or the prior value may be ++ * updated when bits outside the mask are modified, which would make it look like the ++ * current value once the mask is applied. if the mask differs, create a new ++ * non-shared record for tracking the prior data. */ ++ if (rc_memref_mask(size) != rc_memref_mask(self->size)) ++ size = self->size; ++ } ++ ++ if (parse->indirect_parent.type != RC_OPERAND_NONE) { ++ rc_operand_t offset; ++ rc_operand_set_const(&offset, address); ++ ++ self->value.memref = (rc_memref_t*)rc_alloc_modified_memref(parse, ++ size, &parse->indirect_parent, RC_OPERATOR_INDIRECT_READ, &offset); ++ } ++ else { ++ self->value.memref = rc_alloc_memref(parse, address, size); ++ } ++ ++ if (parse->offset < 0) ++ return parse->offset; ++ ++ *memaddr = aux; ++ return RC_OK; ++} ++ ++int rc_parse_operand(rc_operand_t* self, const char** memaddr, rc_parse_state_t* parse) { ++ const char* aux = *memaddr; ++ char* end; ++ int ret; ++ unsigned long value; ++ int negative; ++ int allow_decimal = 0; ++ ++ self->is_combining = 0; ++ ++ switch (*aux) { ++ case 'h': case 'H': /* hex constant */ ++ if (aux[2] == 'x' || aux[2] == 'X') { ++ /* H0x1234 is a typo - either H1234 or 0xH1234 was probably meant */ ++ return RC_INVALID_CONST_OPERAND; ++ } ++ ++ value = strtoul(++aux, &end, 16); ++ if (end == aux) ++ return RC_INVALID_CONST_OPERAND; ++ ++ if (value > 0xffffffffU) ++ value = 0xffffffffU; ++ ++ rc_operand_set_const(self, (unsigned)value); ++ ++ aux = end; ++ break; ++ ++ case 'f': case 'F': /* floating point constant */ ++ if (isalpha((unsigned char)aux[1])) { ++ ret = rc_parse_operand_memory(self, &aux, parse); ++ ++ if (ret < 0) ++ return ret; ++ ++ break; ++ } ++ allow_decimal = 1; ++ /* fall through */ ++ case 'v': case 'V': /* signed integer constant */ ++ ++aux; ++ /* fall through */ ++ case '+': case '-': /* signed integer constant */ ++ negative = 0; ++ if (*aux == '-') { ++ negative = 1; ++ ++aux; ++ } ++ else if (*aux == '+') { ++ ++aux; ++ } ++ ++ value = strtoul(aux, &end, 10); ++ ++ if (*end == '.' && allow_decimal) { ++ /* custom parser for decimal values to ignore locale */ ++ unsigned long shift = 1; ++ unsigned long fraction = 0; ++ double dbl_val; ++ ++ aux = end + 1; ++ if (*aux < '0' || *aux > '9') ++ return RC_INVALID_FP_OPERAND; ++ ++ do { ++ /* only keep as many digits as will fit in a 32-bit value to prevent overflow. ++ * float only has around 7 digits of precision anyway. */ ++ if (shift < 1000000000) { ++ fraction *= 10; ++ fraction += (*aux - '0'); ++ shift *= 10; ++ } ++ ++aux; ++ } while (*aux >= '0' && *aux <= '9'); ++ ++ if (fraction != 0) { ++ /* non-zero fractional part, convert to double and merge in integer portion */ ++ const double dbl_fraction = ((double)fraction) / ((double)shift); ++ if (negative) ++ dbl_val = ((double)(-((long)value))) - dbl_fraction; ++ else ++ dbl_val = (double)value + dbl_fraction; ++ } ++ else { ++ /* fractional part is 0, just convert the integer portion */ ++ if (negative) ++ dbl_val = (double)(-((long)value)); ++ else ++ dbl_val = (double)value; ++ } ++ ++ rc_operand_set_float_const(self, dbl_val); ++ } ++ else { ++ /* not a floating point value, make sure something was read and advance the read pointer */ ++ if (end == aux) ++ return allow_decimal ? RC_INVALID_FP_OPERAND : RC_INVALID_CONST_OPERAND; ++ ++ aux = end; ++ ++ if (value > 0x7fffffffU) ++ value = 0x7fffffffU; ++ ++ if (negative) ++ rc_operand_set_const(self, (unsigned)(-((long)value))); ++ else ++ rc_operand_set_const(self, (unsigned)value); ++ } ++ break; ++ case '{': /* variable */ ++ ++aux; ++ ret = rc_parse_operand_variable(self, &aux, parse); ++ if (ret < 0) ++ return ret; ++ ++ break; ++ ++ case '0': ++ if (aux[1] == 'x' || aux[1] == 'X') { /* hex integer constant */ ++ /* fallthrough */ /* to default */ ++ default: ++ ret = rc_parse_operand_memory(self, &aux, parse); ++ ++ if (ret < 0) ++ return ret; ++ ++ break; ++ } ++ /* fallthrough */ /* to case '1' for case '0' where not '0x' */ ++ case '1': case '2': case '3': case '4': case '5': /* unsigned integer constant */ ++ case '6': case '7': case '8': case '9': ++ value = strtoul(aux, &end, 10); ++ if (end == aux) ++ return RC_INVALID_CONST_OPERAND; ++ ++ if (value > 0xffffffffU) ++ value = 0xffffffffU; ++ ++ rc_operand_set_const(self, (unsigned)value); ++ ++ aux = end; ++ break; ++ ++ case '@': ++ ret = rc_parse_operand_func_call(self, &aux); ++ ++ if (ret < 0) ++ return ret; ++ ++ break; ++ } ++ ++ *memaddr = aux; ++ return RC_OK; ++} ++ ++void rc_operand_set_const(rc_operand_t* self, uint32_t value) { ++ self->size = RC_MEMSIZE_32_BITS; ++ self->type = RC_OPERAND_CONST; ++ self->memref_access_type = RC_OPERAND_NONE; ++ self->value.num = value; ++} ++ ++void rc_operand_set_float_const(rc_operand_t* self, double value) { ++ self->size = RC_MEMSIZE_FLOAT; ++ self->type = RC_OPERAND_FP; ++ self->memref_access_type = RC_OPERAND_NONE; ++ self->value.dbl = value; ++} ++ ++int rc_operands_are_equal(const rc_operand_t* left, const rc_operand_t* right) { ++ if (left == right) ++ return 1; ++ ++ if (left->type != right->type) ++ return 0; ++ ++ switch (left->type) { ++ case RC_OPERAND_CONST: ++ return (left->value.num == right->value.num); ++ case RC_OPERAND_FP: ++ return (left->value.dbl == right->value.dbl); ++ case RC_OPERAND_RECALL: ++ return (left->value.memref == right->value.memref); ++ default: ++ break; ++ } ++ ++ /* comparing two memrefs - look for exact matches on type and size */ ++ if (left->size != right->size || left->value.memref->value.memref_type != right->value.memref->value.memref_type) ++ return 0; ++ ++ switch (left->value.memref->value.memref_type) { ++ case RC_MEMREF_TYPE_MODIFIED_MEMREF: ++ { ++ const rc_modified_memref_t* left_memref = (const rc_modified_memref_t*)left->value.memref; ++ const rc_modified_memref_t* right_memref = (const rc_modified_memref_t*)right->value.memref; ++ return (left_memref->modifier_type == right_memref->modifier_type && ++ left_memref->depth == right_memref->depth && ++ rc_operands_are_equal(&left_memref->modifier, &right_memref->modifier) && ++ rc_operands_are_equal(&left_memref->parent, &right_memref->parent) && ++ 1 == 1 ++ ); ++ } ++ ++ default: ++ return (left->value.memref->address == right->value.memref->address && ++ left->value.memref->value.size == right->value.memref->value.size); ++ } ++} ++ ++int rc_operator_is_modifying(int oper) { ++ switch (oper) { ++ case RC_OPERATOR_AND: ++ case RC_OPERATOR_XOR: ++ case RC_OPERATOR_DIV: ++ case RC_OPERATOR_MULT: ++ case RC_OPERATOR_MOD: ++ case RC_OPERATOR_ADD: ++ case RC_OPERATOR_SUB: ++ case RC_OPERATOR_NONE: /* NONE operator implies "* 1" */ ++ return 1; ++ ++ default: ++ return 0; ++ } ++} ++ ++int rc_memsize_is_float(uint8_t size) { ++ switch (size) { ++ case RC_MEMSIZE_FLOAT: ++ case RC_MEMSIZE_FLOAT_BE: ++ case RC_MEMSIZE_DOUBLE32: ++ case RC_MEMSIZE_DOUBLE32_BE: ++ case RC_MEMSIZE_MBF32: ++ case RC_MEMSIZE_MBF32_LE: ++ return 1; ++ ++ default: ++ return 0; ++ } ++} ++ ++int rc_operand_is_float_memref(const rc_operand_t* self) { ++ if (!rc_operand_is_memref(self)) ++ return 0; ++ ++ if (self->value.memref->value.memref_type == RC_MEMREF_TYPE_MODIFIED_MEMREF) { ++ const rc_modified_memref_t* memref = (const rc_modified_memref_t*)self->value.memref; ++ if (memref->modifier_type != RC_OPERATOR_INDIRECT_READ) ++ return rc_memsize_is_float(self->value.memref->value.size); ++ } ++ ++ return rc_memsize_is_float(self->size); ++} ++ ++int rc_operand_type_is_memref(uint8_t type) { ++ switch (type) { ++ case RC_OPERAND_CONST: ++ case RC_OPERAND_FP: ++ case RC_OPERAND_FUNC: ++ case RC_OPERAND_RECALL: ++ return 0; ++ ++ default: ++ return 1; ++ } ++} ++ ++int rc_operand_type_is_transform(uint8_t type) { ++ switch (type) { ++ case RC_OPERAND_BCD: ++ case RC_OPERAND_INVERTED: ++ return 1; ++ ++ default: ++ return 0; ++ } ++} ++ ++int rc_operand_is_memref(const rc_operand_t* self) { ++ return rc_operand_type_is_memref(self->type); ++} ++ ++int rc_operand_is_recall(const rc_operand_t* self) { ++ switch (self->type) { ++ case RC_OPERAND_RECALL: ++ return 1; ++ ++ default: ++ return 0; ++ } ++} ++ ++int rc_operand_is_float(const rc_operand_t* self) { ++ if (self->type == RC_OPERAND_FP) ++ return 1; ++ ++ if (self->type == RC_OPERAND_RECALL) ++ return rc_memsize_is_float(self->size); ++ ++ return rc_operand_is_float_memref(self); ++} ++ ++static uint32_t rc_transform_operand_value(uint32_t value, const rc_operand_t* self) { ++ switch (self->type) ++ { ++ case RC_OPERAND_BCD: ++ switch (self->size) ++ { ++ case RC_MEMSIZE_8_BITS: ++ value = ((value >> 4) & 0x0f) * 10 ++ + ((value ) & 0x0f); ++ break; ++ ++ case RC_MEMSIZE_16_BITS: ++ case RC_MEMSIZE_16_BITS_BE: ++ value = ((value >> 12) & 0x0f) * 1000 ++ + ((value >> 8) & 0x0f) * 100 ++ + ((value >> 4) & 0x0f) * 10 ++ + ((value ) & 0x0f); ++ break; ++ ++ case RC_MEMSIZE_24_BITS: ++ case RC_MEMSIZE_24_BITS_BE: ++ value = ((value >> 20) & 0x0f) * 100000 ++ + ((value >> 16) & 0x0f) * 10000 ++ + ((value >> 12) & 0x0f) * 1000 ++ + ((value >> 8) & 0x0f) * 100 ++ + ((value >> 4) & 0x0f) * 10 ++ + ((value ) & 0x0f); ++ break; ++ ++ case RC_MEMSIZE_32_BITS: ++ case RC_MEMSIZE_32_BITS_BE: ++ case RC_MEMSIZE_VARIABLE: ++ value = ((value >> 28) & 0x0f) * 10000000 ++ + ((value >> 24) & 0x0f) * 1000000 ++ + ((value >> 20) & 0x0f) * 100000 ++ + ((value >> 16) & 0x0f) * 10000 ++ + ((value >> 12) & 0x0f) * 1000 ++ + ((value >> 8) & 0x0f) * 100 ++ + ((value >> 4) & 0x0f) * 10 ++ + ((value ) & 0x0f); ++ break; ++ ++ default: ++ break; ++ } ++ break; ++ ++ case RC_OPERAND_INVERTED: ++ switch (self->size) ++ { ++ case RC_MEMSIZE_LOW: ++ case RC_MEMSIZE_HIGH: ++ value ^= 0x0f; ++ break; ++ ++ case RC_MEMSIZE_8_BITS: ++ value ^= 0xff; ++ break; ++ ++ case RC_MEMSIZE_16_BITS: ++ case RC_MEMSIZE_16_BITS_BE: ++ value ^= 0xffff; ++ break; ++ ++ case RC_MEMSIZE_24_BITS: ++ case RC_MEMSIZE_24_BITS_BE: ++ value ^= 0xffffff; ++ break; ++ ++ case RC_MEMSIZE_32_BITS: ++ case RC_MEMSIZE_32_BITS_BE: ++ case RC_MEMSIZE_VARIABLE: ++ value ^= 0xffffffff; ++ break; ++ ++ default: ++ value ^= 0x01; ++ break; ++ } ++ break; ++ ++ default: ++ break; ++ } ++ ++ return value; ++} ++ ++void rc_operand_addsource(rc_operand_t* self, rc_parse_state_t* parse, uint8_t new_size) { ++ rc_modified_memref_t* modified_memref; ++ ++ if ((self->type == RC_OPERAND_DELTA || self->type == RC_OPERAND_PRIOR) && ++ self->type == parse->addsource_parent.type) { ++ /* if adding prev(x) and prev(y), just add x and y and take the prev of that. ++ * same for adding prior(x) and prior(y). */ ++ rc_operand_t modifier; ++ memcpy(&modifier, self, sizeof(modifier)); ++ modifier.type = parse->addsource_parent.type = RC_OPERAND_ADDRESS; ++ ++ modified_memref = rc_alloc_modified_memref(parse, ++ new_size, &parse->addsource_parent, parse->addsource_oper, &modifier); ++ } ++ else { ++ modified_memref = rc_alloc_modified_memref(parse, ++ new_size, &parse->addsource_parent, parse->addsource_oper, self); ++ ++ /* the modified memref will contain the combination of modified values, take the current value from that */ ++ self->type = self->memref_access_type = RC_OPERAND_ADDRESS; ++ } ++ ++ self->value.memref = (rc_memref_t*)modified_memref; ++ ++ /* result of an AddSource operation is always a 32-bit integer (even if parent or modifier is a float) */ ++ self->size = RC_MEMSIZE_32_BITS; ++} ++ ++void rc_evaluate_operand(rc_typed_value_t* result, const rc_operand_t* self, rc_eval_state_t* eval_state) { ++ /* step 1: read memory */ ++ switch (self->type) { ++ case RC_OPERAND_CONST: ++ result->type = RC_VALUE_TYPE_UNSIGNED; ++ result->value.u32 = self->value.num; ++ return; ++ ++ case RC_OPERAND_FP: ++ result->type = RC_VALUE_TYPE_FLOAT; ++ result->value.f32 = (float)self->value.dbl; ++ return; ++ ++ case RC_OPERAND_FUNC: ++ /* this feature was never actualized */ ++ result->type = RC_VALUE_TYPE_UNSIGNED; ++ result->value.u32 = 0; ++ return; ++ ++ case RC_OPERAND_RECALL: ++ if (!rc_operand_type_is_memref(self->memref_access_type)) { ++ rc_operand_t recall; ++ memcpy(&recall, self, sizeof(recall)); ++ recall.type = self->memref_access_type; ++ rc_evaluate_operand(result, &recall, eval_state); ++ return; ++ } ++ ++ if (!self->value.memref) { ++ result->type = RC_VALUE_TYPE_UNSIGNED; ++ result->value.u32 = 0; ++ return; ++ } ++ ++ rc_get_memref_value(result, self->value.memref, self->memref_access_type); ++ break; ++ ++ default: ++ rc_get_memref_value(result, self->value.memref, self->type); ++ break; ++ } ++ ++ /* step 2: convert read memory to desired format */ ++ rc_transform_memref_value(result, self->size); ++ ++ /* step 3: apply logic (BCD/invert) */ ++ if (result->type == RC_VALUE_TYPE_UNSIGNED) ++ result->value.u32 = rc_transform_operand_value(result->value.u32, self); ++} +diff -rupbN melonDS.orig/src/rcheevos/src/rcheevos/rc_internal.h melonDS.ra/src/rcheevos/src/rcheevos/rc_internal.h +--- melonDS.orig/src/rcheevos/src/rcheevos/rc_internal.h 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rcheevos/rc_internal.h 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,390 @@ ++#ifndef RC_INTERNAL_H ++#define RC_INTERNAL_H ++ ++#include "rc_runtime_types.h" ++#include "rc_util.h" ++ ++RC_BEGIN_C_DECLS ++ ++typedef struct rc_scratch_string { ++ char* value; ++ struct rc_scratch_string* left; ++ struct rc_scratch_string* right; ++} ++rc_scratch_string_t; ++ ++typedef struct rc_modified_memref_t { ++ rc_memref_t memref; /* For compatibility with rc_operand_t.value.memref */ ++ rc_operand_t parent; /* The parent memref this memref is derived from (type will always be a memref type) */ ++ rc_operand_t modifier; /* The modifier to apply to the parent. */ ++ uint8_t modifier_type; /* How to apply the modifier to the parent. (RC_OPERATOR_*) */ ++ uint16_t depth; /* The number of parents this memref has. */ ++} ++rc_modified_memref_t; ++ ++typedef struct rc_memref_list_t { ++ rc_memref_t* items; ++ struct rc_memref_list_t* next; ++ uint16_t count; ++ uint16_t capacity; ++ uint8_t allocated; ++} rc_memref_list_t; ++ ++typedef struct rc_modified_memref_list_t { ++ rc_modified_memref_t* items; ++ struct rc_modified_memref_list_t* next; ++ uint16_t count; ++ uint16_t capacity; ++ uint8_t allocated; ++} rc_modified_memref_list_t; ++ ++typedef struct rc_memrefs_t { ++ rc_memref_list_t memrefs; ++ rc_modified_memref_list_t modified_memrefs; ++} rc_memrefs_t; ++ ++typedef struct rc_trigger_with_memrefs_t { ++ rc_trigger_t trigger; ++ rc_memrefs_t memrefs; ++} rc_trigger_with_memrefs_t; ++ ++typedef struct rc_lboard_with_memrefs_t { ++ rc_lboard_t lboard; ++ rc_memrefs_t memrefs; ++} rc_lboard_with_memrefs_t; ++ ++typedef struct rc_richpresence_with_memrefs_t { ++ rc_richpresence_t richpresence; ++ rc_memrefs_t memrefs; ++} rc_richpresence_with_memrefs_t; ++ ++typedef struct rc_value_with_memrefs_t { ++ rc_value_t value; ++ rc_memrefs_t memrefs; ++} rc_value_with_memrefs_t; ++ ++/* enum helpers for natvis expansion. Have to use a struct to define the mapping, ++ * and a single field to allow the conditional logic to switch on the value */ ++typedef struct __rc_bool_enum_t { uint8_t value; } __rc_bool_enum_t; ++typedef struct __rc_memsize_enum_t { uint8_t value; } __rc_memsize_enum_t; ++typedef struct __rc_memsize_enum_func_t { uint8_t value; } __rc_memsize_enum_func_t; ++typedef struct __rc_operand_enum_t { uint8_t value; } __rc_operand_enum_t; ++typedef struct __rc_value_type_enum_t { uint8_t value; } __rc_value_type_enum_t; ++typedef struct __rc_memref_type_enum_t { uint8_t value; } __rc_memref_type_enum_t; ++typedef struct __rc_condition_enum_t { uint8_t value; } __rc_condition_enum_t; ++typedef struct __rc_condition_enum_str_t { uint8_t value; } __rc_condition_enum_str_t; ++typedef struct __rc_condset_list_t { rc_condset_t* first_condset; } __rc_condset_list_t; ++typedef struct __rc_operator_enum_t { uint8_t value; } __rc_operator_enum_t; ++typedef struct __rc_operator_enum_str_t { uint8_t value; } __rc_operator_enum_str_t; ++typedef struct __rc_operand_memref_t { rc_operand_t operand; } __rc_operand_memref_t; /* requires &rc_operand_t to be the same as &rc_operand_t.value.memref */ ++typedef struct __rc_value_list_t { rc_value_t* first_value; } __rc_value_list_t; ++typedef struct __rc_trigger_state_enum_t { uint8_t value; } __rc_trigger_state_enum_t; ++typedef struct __rc_lboard_state_enum_t { uint8_t value; } __rc_lboard_state_enum_t; ++typedef struct __rc_richpresence_display_list_t { rc_richpresence_display_t* first_display; } __rc_richpresence_display_list_t; ++typedef struct __rc_richpresence_display_part_list_t { rc_richpresence_display_part_t* display; } __rc_richpresence_display_part_list_t; ++typedef struct __rc_richpresence_lookup_list_t { rc_richpresence_lookup_t* first_lookup; } __rc_richpresence_lookup_list_t; ++typedef struct __rc_format_enum_t { uint8_t value; } __rc_format_enum_t; ++ ++#define RC_ALLOW_ALIGN(T) struct __align_ ## T { uint8_t ch; T t; }; ++ ++RC_ALLOW_ALIGN(rc_condition_t) ++RC_ALLOW_ALIGN(rc_condset_t) ++RC_ALLOW_ALIGN(rc_modified_memref_t) ++RC_ALLOW_ALIGN(rc_lboard_t) ++RC_ALLOW_ALIGN(rc_lboard_with_memrefs_t) ++RC_ALLOW_ALIGN(rc_memref_t) ++RC_ALLOW_ALIGN(rc_memref_list_t) ++RC_ALLOW_ALIGN(rc_memrefs_t) ++RC_ALLOW_ALIGN(rc_modified_memref_list_t) ++RC_ALLOW_ALIGN(rc_operand_t) ++RC_ALLOW_ALIGN(rc_richpresence_t) ++RC_ALLOW_ALIGN(rc_richpresence_display_t) ++RC_ALLOW_ALIGN(rc_richpresence_display_part_t) ++RC_ALLOW_ALIGN(rc_richpresence_lookup_t) ++RC_ALLOW_ALIGN(rc_richpresence_lookup_item_t) ++RC_ALLOW_ALIGN(rc_richpresence_with_memrefs_t) ++RC_ALLOW_ALIGN(rc_scratch_string_t) ++RC_ALLOW_ALIGN(rc_trigger_t) ++RC_ALLOW_ALIGN(rc_trigger_with_memrefs_t) ++RC_ALLOW_ALIGN(rc_value_t) ++RC_ALLOW_ALIGN(rc_value_with_memrefs_t) ++RC_ALLOW_ALIGN(char) ++ ++#define RC_ALIGNOF(T) (sizeof(struct __align_ ## T) - sizeof(T)) ++#define RC_OFFSETOF(o, t) (int)((uint8_t*)&(o.t) - (uint8_t*)&(o)) ++ ++#define RC_ALLOC(t, p) ((t*)rc_alloc((p)->buffer, &(p)->offset, sizeof(t), RC_ALIGNOF(t), &(p)->scratch, RC_OFFSETOF((p)->scratch.objs, __ ## t))) ++#define RC_ALLOC_SCRATCH(t, p) ((t*)rc_alloc_scratch((p)->buffer, &(p)->offset, sizeof(t), RC_ALIGNOF(t), &(p)->scratch, RC_OFFSETOF((p)->scratch.objs, __ ## t))) ++#define RC_ALLOC_ARRAY(t, n, p) ((t*)rc_alloc((p)->buffer, &(p)->offset, (n) * sizeof(t), RC_ALIGNOF(t), &(p)->scratch, RC_OFFSETOF((p)->scratch.objs, __ ## t))) ++#define RC_ALLOC_ARRAY_SCRATCH(t, n, p) ((t*)rc_alloc_scratch((p)->buffer, &(p)->offset, (n) * sizeof(t), RC_ALIGNOF(t), &(p)->scratch, RC_OFFSETOF((p)->scratch.objs, __ ## t))) ++ ++#define RC_ALLOC_WITH_TRAILING(container_type, trailing_type, trailing_field, trailing_count, parse) ((container_type*)rc_alloc(\ ++ (parse)->buffer, &(parse)->offset, \ ++ RC_OFFSETOF((*(container_type*)NULL),trailing_field) + trailing_count * sizeof(trailing_type), \ ++ RC_ALIGNOF(container_type), &(parse)->scratch, 0)) ++#define RC_GET_TRAILING(container_pointer, container_type, trailing_type, trailing_field) (trailing_type*)(&((container_type*)(container_pointer))->trailing_field) ++ ++/* force alignment to 4 bytes on 32-bit systems, or 8 bytes on 64-bit systems */ ++#define RC_ALIGN(n) (((n) + (sizeof(void*)-1)) & ~(sizeof(void*)-1)) ++ ++typedef struct { ++ rc_buffer_t buffer; ++ rc_scratch_string_t* strings; ++ ++ struct objs { ++ rc_condition_t* __rc_condition_t; ++ rc_condset_t* __rc_condset_t; ++ rc_modified_memref_t* __rc_modified_memref_t; ++ rc_lboard_t* __rc_lboard_t; ++ rc_lboard_with_memrefs_t* __rc_lboard_with_memrefs_t; ++ rc_memref_t* __rc_memref_t; ++ rc_memref_list_t* __rc_memref_list_t; ++ rc_memrefs_t* __rc_memrefs_t; ++ rc_modified_memref_list_t* __rc_modified_memref_list_t; ++ rc_operand_t* __rc_operand_t; ++ rc_richpresence_t* __rc_richpresence_t; ++ rc_richpresence_display_t* __rc_richpresence_display_t; ++ rc_richpresence_display_part_t* __rc_richpresence_display_part_t; ++ rc_richpresence_lookup_t* __rc_richpresence_lookup_t; ++ rc_richpresence_lookup_item_t* __rc_richpresence_lookup_item_t; ++ rc_richpresence_with_memrefs_t* __rc_richpresence_with_memrefs_t; ++ rc_scratch_string_t __rc_scratch_string_t; ++ rc_trigger_t* __rc_trigger_t; ++ rc_trigger_with_memrefs_t* __rc_trigger_with_memrefs_t; ++ rc_value_t* __rc_value_t; ++ rc_value_with_memrefs_t* __rc_value_with_memrefs_t; ++ ++ /* these fields aren't actually used by the code, but they force the ++ * virtual enum wrapper types to exist so natvis can use them */ ++ union { ++ __rc_bool_enum_t boolean; ++ __rc_memsize_enum_t memsize; ++ __rc_memsize_enum_func_t memsize_func; ++ __rc_operand_enum_t operand; ++ __rc_value_type_enum_t value_type; ++ __rc_memref_type_enum_t memref_type; ++ __rc_condition_enum_t condition; ++ __rc_condition_enum_str_t condition_str; ++ __rc_condset_list_t condset_list; ++ __rc_operator_enum_t oper; ++ __rc_operator_enum_str_t oper_str; ++ __rc_operand_memref_t operand_memref; ++ __rc_value_list_t value_list; ++ __rc_trigger_state_enum_t trigger_state; ++ __rc_lboard_state_enum_t lboard_state; ++ __rc_richpresence_display_list_t richpresence_display_list; ++ __rc_richpresence_display_part_list_t richpresence_display_part_list; ++ __rc_richpresence_lookup_list_t richpresence_lookup_list; ++ __rc_format_enum_t format; ++ } natvis_extension; ++ } objs; ++} ++rc_scratch_t; ++ ++enum { ++ RC_VALUE_TYPE_NONE, ++ RC_VALUE_TYPE_UNSIGNED, ++ RC_VALUE_TYPE_SIGNED, ++ RC_VALUE_TYPE_FLOAT ++}; ++ ++typedef struct { ++ union { ++ uint32_t u32; ++ int32_t i32; ++ float f32; ++ } value; ++ ++ char type; ++} ++rc_typed_value_t; ++ ++enum { ++ RC_MEMREF_TYPE_MEMREF, /* rc_memref_t */ ++ RC_MEMREF_TYPE_MODIFIED_MEMREF, /* rc_modified_memref_t */ ++ RC_MEMREF_TYPE_VALUE /* rc_value_t */ ++}; ++ ++#define RC_MEASURED_UNKNOWN 0xFFFFFFFF ++#define RC_OPERAND_NONE 0xFF ++ ++typedef struct { ++ /* memory accessors */ ++ rc_peek_t peek; ++ void* peek_userdata; ++ ++ /* processing state */ ++ rc_typed_value_t measured_value; /* captured Measured value */ ++ int32_t add_hits; /* AddHits/SubHits accumulator */ ++ uint8_t is_true; /* true if all conditions are true */ ++ uint8_t is_primed; /* true if all non-Trigger conditions are true */ ++ uint8_t is_paused; /* true if one or more PauseIf conditions is true */ ++ uint8_t can_measure; /* false if the measured value should be ignored */ ++ uint8_t measured_from_hits; /* true if the measured_value came from a condition's hit count */ ++ uint8_t and_next; /* true if the previous condition was AndNext true */ ++ uint8_t or_next; /* true if the previous condition was OrNext true */ ++ uint8_t reset_next; /* true if the previous condition was ResetNextIf true */ ++ uint8_t stop_processing; /* true to abort the processing loop */ ++ ++ /* result state */ ++ uint8_t has_hits; /* true if one of more hit counts is non-zero */ ++ uint8_t was_reset; /* true if one or more ResetIf conditions is true */ ++ uint8_t was_cond_reset; /* true if one or more ResetNextIf conditions is true */ ++ ++ /* control settings */ ++ uint8_t can_short_curcuit; /* allows logic processing to stop as soon as a false condition is encountered */ ++} ++rc_eval_state_t; ++ ++typedef struct { ++ int32_t offset; ++ ++ void* buffer; ++ rc_scratch_t scratch; ++ ++ rc_memrefs_t* memrefs; ++ rc_memrefs_t* existing_memrefs; ++ rc_value_t** variables; ++ ++ uint32_t measured_target; ++ int lines_read; ++ ++ rc_operand_t addsource_parent; ++ rc_operand_t indirect_parent; ++ rc_operand_t remember; ++ uint8_t addsource_oper; ++ ++ uint8_t is_value; ++ uint8_t has_required_hits; ++ uint8_t measured_as_percent; ++ uint8_t ignore_non_parse_errors; ++} ++rc_parse_state_t; ++ ++typedef struct rc_preparse_state_t { ++ rc_parse_state_t parse; ++ rc_memrefs_t memrefs; ++} rc_preparse_state_t; ++ ++void rc_init_parse_state(rc_parse_state_t* parse, void* buffer); ++void rc_init_parse_state_memrefs(rc_parse_state_t* parse, rc_memrefs_t* memrefs); ++void rc_reset_parse_state(rc_parse_state_t* parse, void* buffer); ++void rc_destroy_parse_state(rc_parse_state_t* parse); ++void rc_init_preparse_state(rc_preparse_state_t* preparse); ++void rc_preparse_alloc_memrefs(rc_memrefs_t* memrefs, rc_preparse_state_t* preparse); ++void rc_preparse_reserve_memrefs(rc_preparse_state_t* preparse, rc_memrefs_t* memrefs); ++void rc_preparse_copy_memrefs(rc_parse_state_t* parse, rc_memrefs_t* memrefs); ++void rc_destroy_preparse_state(rc_preparse_state_t *preparse); ++ ++void* rc_alloc(void* pointer, int32_t* offset, uint32_t size, uint32_t alignment, rc_scratch_t* scratch, uint32_t scratch_object_pointer_offset); ++void* rc_alloc_scratch(void* pointer, int32_t* offset, uint32_t size, uint32_t alignment, rc_scratch_t* scratch, uint32_t scratch_object_pointer_offset); ++char* rc_alloc_str(rc_parse_state_t* parse, const char* text, size_t length); ++ ++rc_memref_t* rc_alloc_memref(rc_parse_state_t* parse, uint32_t address, uint8_t size); ++rc_modified_memref_t* rc_alloc_modified_memref(rc_parse_state_t* parse, uint8_t size, const rc_operand_t* parent, ++ uint8_t modifier_type, const rc_operand_t* modifier); ++int rc_parse_memref(const char** memaddr, uint8_t* size, uint32_t* address); ++void rc_update_memref_values(rc_memrefs_t* memrefs, rc_peek_t peek, void* ud); ++void rc_update_memref_value(rc_memref_value_t* memref, uint32_t value); ++void rc_get_memref_value(rc_typed_value_t* value, rc_memref_t* memref, int operand_type); ++uint32_t rc_get_modified_memref_value(const rc_modified_memref_t* memref, rc_peek_t peek, void* ud); ++uint8_t rc_memref_shared_size(uint8_t size); ++uint32_t rc_memref_mask(uint8_t size); ++void rc_transform_memref_value(rc_typed_value_t* value, uint8_t size); ++uint32_t rc_peek_value(uint32_t address, uint8_t size, rc_peek_t peek, void* ud); ++ ++void rc_memrefs_init(rc_memrefs_t* memrefs); ++void rc_memrefs_destroy(rc_memrefs_t* memrefs); ++uint32_t rc_memrefs_count_memrefs(const rc_memrefs_t* memrefs); ++uint32_t rc_memrefs_count_modified_memrefs(const rc_memrefs_t* memrefs); ++ ++void rc_parse_trigger_internal(rc_trigger_t* self, const char** memaddr, rc_parse_state_t* parse); ++int rc_trigger_state_active(int state); ++rc_memrefs_t* rc_trigger_get_memrefs(rc_trigger_t* self); ++ ++typedef struct rc_condset_with_trailing_conditions_t { ++ rc_condset_t condset; ++ rc_condition_t conditions[2]; ++} rc_condset_with_trailing_conditions_t; ++RC_ALLOW_ALIGN(rc_condset_with_trailing_conditions_t) ++ ++rc_condset_t* rc_parse_condset(const char** memaddr, rc_parse_state_t* parse); ++int rc_test_condset(rc_condset_t* self, rc_eval_state_t* eval_state); ++void rc_reset_condset(rc_condset_t* self); ++rc_condition_t* rc_condset_get_conditions(rc_condset_t* self); ++void rc_test_condset_internal(rc_condition_t* condition, uint32_t num_conditions, rc_eval_state_t* eval_state, int can_short_circuit); ++ ++enum { ++ RC_PROCESSING_COMPARE_DEFAULT = 0, ++ RC_PROCESSING_COMPARE_MEMREF_TO_CONST, ++ RC_PROCESSING_COMPARE_MEMREF_TO_DELTA, ++ RC_PROCESSING_COMPARE_MEMREF_TO_MEMREF, ++ RC_PROCESSING_COMPARE_DELTA_TO_MEMREF, ++ RC_PROCESSING_COMPARE_DELTA_TO_CONST, ++ RC_PROCESSING_COMPARE_MEMREF_TO_CONST_TRANSFORMED, ++ RC_PROCESSING_COMPARE_MEMREF_TO_DELTA_TRANSFORMED, ++ RC_PROCESSING_COMPARE_MEMREF_TO_MEMREF_TRANSFORMED, ++ RC_PROCESSING_COMPARE_DELTA_TO_MEMREF_TRANSFORMED, ++ RC_PROCESSING_COMPARE_DELTA_TO_CONST_TRANSFORMED, ++ RC_PROCESSING_COMPARE_ALWAYS_TRUE, ++ RC_PROCESSING_COMPARE_ALWAYS_FALSE ++}; ++ ++rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse); ++void rc_parse_condition_internal(rc_condition_t* self, const char** memaddr, rc_parse_state_t* parse); ++void rc_condition_update_parse_state(rc_condition_t* condition, rc_parse_state_t* parse); ++int rc_test_condition(rc_condition_t* self, rc_eval_state_t* eval_state); ++void rc_evaluate_condition_value(rc_typed_value_t* value, rc_condition_t* self, rc_eval_state_t* eval_state); ++int rc_condition_is_combining(const rc_condition_t* self); ++void rc_condition_convert_to_operand(const rc_condition_t* condition, rc_operand_t* operand, rc_parse_state_t* parse); ++const rc_operand_t* rc_condition_get_real_operand1(const rc_condition_t* self); ++ ++int rc_parse_operand(rc_operand_t* self, const char** memaddr, rc_parse_state_t* parse); ++void rc_evaluate_operand(rc_typed_value_t* value, const rc_operand_t* self, rc_eval_state_t* eval_state); ++int rc_operator_is_modifying(int oper); ++int rc_memsize_is_float(uint8_t size); ++int rc_operand_is_float_memref(const rc_operand_t* self); ++int rc_operand_is_float(const rc_operand_t* self); ++int rc_operand_is_recall(const rc_operand_t* self); ++int rc_operand_type_is_memref(uint8_t type); ++int rc_operand_type_is_transform(uint8_t type); ++int rc_operands_are_equal(const rc_operand_t* left, const rc_operand_t* right); ++void rc_operand_addsource(rc_operand_t* self, rc_parse_state_t* parse, uint8_t new_size); ++void rc_operand_set_const(rc_operand_t* self, uint32_t value); ++void rc_operand_set_float_const(rc_operand_t* self, double value); ++ ++int rc_is_valid_variable_character(char ch, int is_first); ++void rc_parse_value_internal(rc_value_t* self, const char** memaddr, rc_parse_state_t* parse); ++int rc_evaluate_value_typed(rc_value_t* self, rc_typed_value_t* value, rc_peek_t peek, void* ud); ++void rc_reset_value(rc_value_t* self); ++int rc_value_from_hits(rc_value_t* self); ++rc_value_t* rc_alloc_variable(const char* memaddr, size_t memaddr_len, rc_parse_state_t* parse); ++uint32_t rc_count_values(const rc_value_t* values); ++void rc_update_values(rc_value_t* values, rc_peek_t peek, void* ud); ++void rc_reset_values(rc_value_t* values); ++ ++void rc_typed_value_convert(rc_typed_value_t* value, char new_type); ++void rc_typed_value_add(rc_typed_value_t* value, const rc_typed_value_t* amount); ++void rc_typed_value_multiply(rc_typed_value_t* value, const rc_typed_value_t* amount); ++void rc_typed_value_divide(rc_typed_value_t* value, const rc_typed_value_t* amount); ++void rc_typed_value_modulus(rc_typed_value_t* value, const rc_typed_value_t* amount); ++void rc_typed_value_negate(rc_typed_value_t* value); ++int rc_typed_value_compare(const rc_typed_value_t* value1, const rc_typed_value_t* value2, char oper); ++void rc_typed_value_combine(rc_typed_value_t* value, rc_typed_value_t* amount, uint8_t oper); ++void rc_typed_value_from_memref_value(rc_typed_value_t* value, const rc_memref_value_t* memref); ++ ++int rc_format_typed_value(char* buffer, size_t size, const rc_typed_value_t* value, int format); ++ ++void rc_parse_lboard_internal(rc_lboard_t* self, const char* memaddr, rc_parse_state_t* parse); ++int rc_lboard_state_active(int state); ++ ++void rc_parse_richpresence_internal(rc_richpresence_t* self, const char* script, rc_parse_state_t* parse); ++rc_memrefs_t* rc_richpresence_get_memrefs(rc_richpresence_t* self); ++void rc_reset_richpresence_triggers(rc_richpresence_t* self); ++void rc_update_richpresence_internal(rc_richpresence_t* richpresence, rc_peek_t peek, void* peek_ud); ++ ++int rc_validate_memrefs_for_console(const rc_memrefs_t* memrefs, char result[], const size_t result_size, uint32_t console_id); ++ ++RC_END_C_DECLS ++ ++#endif /* RC_INTERNAL_H */ +diff -rupbN melonDS.orig/src/rcheevos/src/rcheevos/rc_validate.c melonDS.ra/src/rcheevos/src/rcheevos/rc_validate.c +--- melonDS.orig/src/rcheevos/src/rcheevos/rc_validate.c 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rcheevos/rc_validate.c 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,1370 @@ ++#include "rc_validate.h" ++ ++#include "rc_consoles.h" ++#include "rc_internal.h" ++ ++#include "../rc_compat.h" ++ ++#include ++#include ++ ++enum ++{ ++ RC_VALIDATION_ERR_NONE, ++ ++ /* sorted by severity - most severe first */ ++ ++ /* errors that prevent the achievement from functioning */ ++ RC_VALIDATION_ERR_ADDRESS_OUT_OF_RANGE, ++ RC_VALIDATION_ERR_RECALL_BEFORE_REMEMBER, ++ RC_VALIDATION_ERR_COMPARISON_NEVER_TRUE_WITH_MAX, ++ RC_VALIDATION_ERR_COMPARISON_NEVER_TRUE_INTEGER_TO_FLOAT, ++ RC_VALIDATION_ERR_COMPARISON_NEVER_TRUE, ++ RC_VALIDATION_ERR_CONFLICTING_CONDITION, ++ ++ /* warnings about logic that does nothing */ ++ RC_VALIDATION_ERR_COMPARISON_ALWAYS_TRUE_INTEGER_TO_FLOAT, ++ RC_VALIDATION_ERR_COMPARISON_ALWAYS_TRUE_WITH_MAX, ++ RC_VALIDATION_ERR_TRAILING_CHAINING_CONDITION, ++ RC_VALIDATION_ERR_MEASUREDIF_WITHOUT_MEASURED, ++ RC_VALIDATION_ERR_ADDHITS_WITHOUT_TARGET, ++ ++ /* warnings about pointer math */ ++ RC_VALIDATION_ERR_POINTER_FROM_PREVIOUS_FRAME, ++ RC_VALIDATION_ERR_POINTER_NON_INTEGER_OFFSET, ++ RC_VALIDATION_ERR_POINTER_TRANSFORMED_OFFSET, ++ ++ /* warnings about potential logic errors */ ++ RC_VALIDATION_ERR_COMPARING_DIFFERENT_MEMORY_SIZES, ++ RC_VALIDATION_ERR_MASK_RESULT_ALWAYS_ZERO, ++ ++ /* warnings that some areas of memory should be avoided */ ++ RC_VALIDATION_ERR_KERNAL_RAM_REQUIRES_BIOS, ++ RC_VALIDATION_ERR_VIRTUAL_RAM_MAY_NOT_BE_EXPOSED, ++ ++ /* warnings about redundant logic */ ++ RC_VALIDATION_ERR_REDUNDANT_CONDITION, ++ RC_VALIDATION_ERR_NO_HITS_TO_RESET, ++ RC_VALIDATION_ERR_RESET_HIT_TARGET_OF_ONE, ++ RC_VALIDATION_ERR_MASK_TOO_LARGE, ++ ++ RC_VALIDATION_ERR_COUNT ++}; ++ ++enum ++{ ++ RC_VALIDATION_VIRTUAL_RAM_OTHER, ++ RC_VALIDATION_VIRTUAL_RAM_MIRROR, ++ RC_VALIDATION_VIRTUAL_RAM_ECHO ++}; ++ ++typedef struct rc_validation_error_t ++{ ++ uint32_t err; ++ uint16_t group_index; ++ uint16_t cond_index; ++ uint32_t data1; ++ uint32_t data2; ++} rc_validation_error_t; ++ ++typedef struct rc_validation_state_t ++{ ++ rc_validation_error_t errors[64]; ++ uint32_t error_count; ++ uint16_t group_index; ++ uint16_t cond_index; ++ uint32_t console_id; ++ uint32_t max_address; ++ uint8_t has_alt_groups; ++ uint8_t has_hit_targets; ++} rc_validation_state_t; ++ ++/* this returns a negative value if err1 is more severe than err2, or ++ * a positive value is err2 is more severe than err1. */ ++static int rc_validation_compare_severity(const rc_validation_error_t* err1, const rc_validation_error_t* err2) ++{ ++ /* lower err value is more severe */ ++ int diff = (err1->err - err2->err); ++ if (diff != 0) ++ return diff; ++ ++ /* lower group index is more severe */ ++ diff = (err1->group_index - err2->group_index); ++ if (diff != 0) ++ return diff; ++ ++ /* lower condition value is more severe */ ++ return (err1->cond_index - err2->cond_index); ++} ++ ++static const rc_validation_error_t* rc_validate_find_most_severe_error(const rc_validation_state_t* state) ++{ ++ const rc_validation_error_t* error = &state->errors[0]; ++ const rc_validation_error_t* most_severe_error = error; ++ const rc_validation_error_t* stop = &state->errors[state->error_count]; ++ ++ while (++error < stop) { ++ if (rc_validation_compare_severity(error, most_severe_error) < 0) ++ most_severe_error = error; ++ } ++ ++ return most_severe_error; ++} ++ ++static rc_validation_error_t* rc_validate_find_least_severe_error(rc_validation_state_t* state) ++{ ++ rc_validation_error_t* error = &state->errors[0]; ++ rc_validation_error_t* least_severe_error = error; ++ rc_validation_error_t* stop = &state->errors[state->error_count]; ++ ++ while (++error < stop) { ++ if (rc_validation_compare_severity(error, least_severe_error) > 0) ++ least_severe_error = error; ++ } ++ ++ return least_severe_error; ++} ++ ++static size_t rc_validate_format_cond_index(char buffer[], size_t buffer_size, const rc_validation_state_t* state, uint32_t group_index, uint32_t cond_index) ++{ ++ int written = 0; ++ ++ if (cond_index == 0) ++ return 0; ++ ++ if (state->has_alt_groups) { ++ if (group_index == 0) ++ written = snprintf(buffer, buffer_size, "Core "); ++ else ++ written = snprintf(buffer, buffer_size, "Alt%u ", group_index); ++ ++ buffer += written; ++ buffer_size -= written; ++ } ++ ++ written += snprintf(buffer, buffer_size, "Condition %u", cond_index); ++ return written; ++} ++ ++static const char* rc_validate_get_condition_type_string(uint32_t type) ++{ ++ switch (type) { ++ case RC_CONDITION_ADD_ADDRESS: return "AddAddress"; ++ case RC_CONDITION_ADD_HITS: return "AddHits"; ++ case RC_CONDITION_ADD_SOURCE: return "AddSource"; ++ case RC_CONDITION_AND_NEXT: return "AndNext"; ++ case RC_CONDITION_MEASURED: return "Measured"; ++ case RC_CONDITION_MEASURED_IF: return "MeasuredIf"; ++ case RC_CONDITION_OR_NEXT: return "OrNext"; ++ case RC_CONDITION_PAUSE_IF: return "PauseIf"; ++ case RC_CONDITION_REMEMBER: return "Remember"; ++ case RC_CONDITION_RESET_IF: return "ResetIf"; ++ case RC_CONDITION_RESET_NEXT_IF: return "ResetNextIf"; ++ case RC_CONDITION_SUB_HITS: return "SubHits"; ++ case RC_CONDITION_SUB_SOURCE: return "SubSource"; ++ case RC_CONDITION_TRIGGER: return "Trigger"; ++ default: return "???"; ++ } ++} ++ ++static void rc_validate_format_error_compare_int_to_float(char buffer[], size_t buffer_size, uint32_t encoded_data, const char* limiter) ++{ ++ int written; ++ rc_typed_value_t value; ++ value.value.u32 = encoded_data; ++ ++ written = snprintf(buffer, buffer_size, "Comparison is %s true (integer can never be %.06f", limiter, value.value.f32); ++ while (buffer[written - 1] == '0') ++ written--; ++ if (buffer[written] == '.') ++ written++; ++ buffer[written] = ')'; ++ buffer[written + 1] = '\0'; ++} ++ ++static int rc_validate_format_error(char buffer[], size_t buffer_size, const rc_validation_state_t* state, const rc_validation_error_t* error) ++{ ++ size_t written = rc_validate_format_cond_index(buffer, buffer_size, state, error->group_index, error->cond_index); ++ buffer += written; ++ buffer_size -= written; ++ ++ if (buffer_size < 2) ++ return 0; ++ ++ buffer_size -= 2; ++ *buffer++ = ':'; ++ *buffer++ = ' '; ++ ++ switch (error->err) { ++ case RC_VALIDATION_ERR_ADDHITS_WITHOUT_TARGET: ++ snprintf(buffer, buffer_size, "Final condition in AddHits chain must have a hit target"); ++ break; ++ ++ case RC_VALIDATION_ERR_ADDRESS_OUT_OF_RANGE: ++ snprintf(buffer, buffer_size, "Address %04X out of range (max %04X)", error->data1, error->data2); ++ break; ++ ++ case RC_VALIDATION_ERR_COMPARING_DIFFERENT_MEMORY_SIZES: ++ snprintf(buffer, buffer_size, "Comparing different memory sizes"); ++ break; ++ ++ case RC_VALIDATION_ERR_COMPARISON_ALWAYS_TRUE_INTEGER_TO_FLOAT: ++ rc_validate_format_error_compare_int_to_float(buffer, buffer_size, error->data1, "always"); ++ break; ++ ++ case RC_VALIDATION_ERR_COMPARISON_ALWAYS_TRUE_WITH_MAX: ++ snprintf(buffer, buffer_size, "Comparison is always true (max %u)", error->data1); ++ break; ++ ++ case RC_VALIDATION_ERR_COMPARISON_NEVER_TRUE: ++ snprintf(buffer, buffer_size, "Comparison is never true"); ++ break; ++ ++ case RC_VALIDATION_ERR_COMPARISON_NEVER_TRUE_INTEGER_TO_FLOAT: ++ rc_validate_format_error_compare_int_to_float(buffer, buffer_size, error->data1, "never"); ++ break; ++ ++ case RC_VALIDATION_ERR_COMPARISON_NEVER_TRUE_WITH_MAX: ++ snprintf(buffer, buffer_size, "Comparison is never true (max %u)", error->data1); ++ break; ++ ++ case RC_VALIDATION_ERR_CONFLICTING_CONDITION: ++ written = snprintf(buffer, buffer_size, "Conflicts with "); ++ buffer += written; ++ buffer_size -= written; ++ rc_validate_format_cond_index(buffer, buffer_size, state, error->data1, error->data2); ++ break; ++ ++ case RC_VALIDATION_ERR_KERNAL_RAM_REQUIRES_BIOS: ++ snprintf(buffer, buffer_size, "Kernel RAM may not be initialized without real BIOS (address %04X)", error->data1); ++ break; ++ ++ case RC_VALIDATION_ERR_MASK_RESULT_ALWAYS_ZERO: ++ snprintf(buffer, buffer_size, "Result of mask is always 0"); ++ break; ++ ++ case RC_VALIDATION_ERR_MASK_TOO_LARGE: ++ snprintf(buffer, buffer_size, "Mask has more bits than source"); ++ break; ++ ++ case RC_VALIDATION_ERR_MEASUREDIF_WITHOUT_MEASURED: ++ snprintf(buffer, buffer_size, "MeasuredIf without Measured"); ++ break; ++ ++ case RC_VALIDATION_ERR_NO_HITS_TO_RESET: ++ snprintf(buffer, buffer_size, "No captured hits to reset"); ++ break; ++ ++ case RC_VALIDATION_ERR_POINTER_FROM_PREVIOUS_FRAME: ++ snprintf(buffer, buffer_size, "Using pointer from previous frame"); ++ break; ++ ++ case RC_VALIDATION_ERR_POINTER_NON_INTEGER_OFFSET: ++ snprintf(buffer, buffer_size, "Using non-integer value in AddAddress calculation"); ++ break; ++ ++ case RC_VALIDATION_ERR_POINTER_TRANSFORMED_OFFSET: ++ snprintf(buffer, buffer_size, "Using transformed value in AddAddress calculation"); ++ break; ++ ++ case RC_VALIDATION_ERR_RECALL_BEFORE_REMEMBER: ++ snprintf(buffer, buffer_size, "Recall used before Remember"); ++ break; ++ ++ case RC_VALIDATION_ERR_RESET_HIT_TARGET_OF_ONE: ++ snprintf(buffer, buffer_size, "Hit target of 1 is redundant on ResetIf"); ++ break; ++ ++ case RC_VALIDATION_ERR_REDUNDANT_CONDITION: ++ written = snprintf(buffer, buffer_size, "Redundant with "); ++ buffer += written; ++ buffer_size -= written; ++ rc_validate_format_cond_index(buffer, buffer_size, state, error->data1, error->data2); ++ break; ++ ++ case RC_VALIDATION_ERR_TRAILING_CHAINING_CONDITION: ++ snprintf(buffer, buffer_size, "%s condition type expects another condition to follow", rc_validate_get_condition_type_string(error->data1)); ++ break; ++ ++ case RC_VALIDATION_ERR_VIRTUAL_RAM_MAY_NOT_BE_EXPOSED: ++ snprintf(buffer, buffer_size, "%s RAM may not be exposed by emulator (address %04X)", ++ error->data2 == RC_VALIDATION_VIRTUAL_RAM_MIRROR ? "Mirror" : ++ error->data2 == RC_VALIDATION_VIRTUAL_RAM_ECHO ? "Echo" : "Virtual", ++ error->data1); ++ break; ++ } ++ ++ return 0; ++} ++ ++static void rc_validate_add_error(rc_validation_state_t* state, uint32_t error_code, uint32_t data1, uint32_t data2) ++{ ++ rc_validation_error_t* error; ++ if (state->error_count == sizeof(state->errors) / sizeof(state->errors[0])) ++ error = rc_validate_find_least_severe_error(state); ++ else ++ error = &state->errors[state->error_count++]; ++ ++ error->err = error_code; ++ error->group_index = state->group_index; ++ error->cond_index = state->cond_index; ++ error->data1 = data1; ++ error->data2 = data2; ++} ++ ++static void rc_validate_memref(const rc_memref_t* memref, rc_validation_state_t* state) ++{ ++ if (memref->address > state->max_address) { ++ rc_validate_add_error(state, RC_VALIDATION_ERR_ADDRESS_OUT_OF_RANGE, memref->address, state->max_address); ++ return; ++ } ++ ++ switch (state->console_id) { ++ case RC_CONSOLE_NINTENDO: ++ case RC_CONSOLE_FAMICOM_DISK_SYSTEM: ++ if (memref->address >= 0x0800 && memref->address <= 0x1FFF) ++ rc_validate_add_error(state, RC_VALIDATION_ERR_VIRTUAL_RAM_MAY_NOT_BE_EXPOSED, memref->address, RC_VALIDATION_VIRTUAL_RAM_MIRROR); ++ break; ++ ++ case RC_CONSOLE_GAMEBOY: ++ case RC_CONSOLE_GAMEBOY_COLOR: ++ if (memref->address >= 0xE000 && memref->address <= 0xFDFF) ++ rc_validate_add_error(state, RC_VALIDATION_ERR_VIRTUAL_RAM_MAY_NOT_BE_EXPOSED, memref->address, RC_VALIDATION_VIRTUAL_RAM_ECHO); ++ break; ++ ++ case RC_CONSOLE_PLAYSTATION: ++ if (memref->address <= 0xFFFF) ++ rc_validate_add_error(state, RC_VALIDATION_ERR_KERNAL_RAM_REQUIRES_BIOS, memref->address, 0); ++ break; ++ } ++} ++ ++static uint32_t rc_console_max_address(uint32_t console_id) ++{ ++ const rc_memory_regions_t* memory_regions; ++ memory_regions = rc_console_memory_regions(console_id); ++ if (memory_regions && memory_regions->num_regions > 0) ++ return memory_regions->region[memory_regions->num_regions - 1].end_address; ++ ++ return 0xFFFFFFFF; ++} ++ ++int rc_validate_memrefs_for_console(const rc_memrefs_t* memrefs, char result[], const size_t result_size, uint32_t console_id) ++{ ++ const rc_memref_list_t* memref_list = &memrefs->memrefs; ++ ++ rc_validation_state_t state; ++ memset(&state, 0, sizeof(state)); ++ state.console_id = console_id; ++ state.max_address = rc_console_max_address(console_id); ++ ++ result[0] = '\0'; ++ do ++ { ++ const rc_memref_t* memref = memref_list->items; ++ const rc_memref_t* memref_stop = memref + memref_list->count; ++ for (; memref < memref_stop; ++memref) ++ { ++ rc_validate_memref(memref, &state); ++ if (state.error_count) { ++ rc_validate_format_error(result, result_size, &state, &state.errors[0]); ++ return 0; ++ } ++ } ++ ++ memref_list = memref_list->next; ++ } while (memref_list); ++ ++ return 1; ++} ++ ++static uint32_t rc_max_value(const rc_operand_t* operand) ++{ ++ if (operand->type == RC_OPERAND_CONST) ++ return operand->value.num; ++ ++ if (!rc_operand_is_memref(operand)) ++ return 0xFFFFFFFF; ++ ++ switch (operand->size) { ++ case RC_MEMSIZE_BIT_0: ++ case RC_MEMSIZE_BIT_1: ++ case RC_MEMSIZE_BIT_2: ++ case RC_MEMSIZE_BIT_3: ++ case RC_MEMSIZE_BIT_4: ++ case RC_MEMSIZE_BIT_5: ++ case RC_MEMSIZE_BIT_6: ++ case RC_MEMSIZE_BIT_7: ++ return 1; ++ ++ case RC_MEMSIZE_LOW: ++ case RC_MEMSIZE_HIGH: ++ return 0xF; ++ ++ case RC_MEMSIZE_BITCOUNT: ++ return 8; ++ ++ case RC_MEMSIZE_8_BITS: ++ /* NOTE: BCD should max out at 0x99, but because each digit can be 15, it actually maxes at 15*10 + 15 */ ++ return (operand->type == RC_OPERAND_BCD) ? 165 : 0xFF; ++ ++ case RC_MEMSIZE_16_BITS: ++ case RC_MEMSIZE_16_BITS_BE: ++ return (operand->type == RC_OPERAND_BCD) ? 16665 : 0xFFFF; ++ ++ case RC_MEMSIZE_24_BITS: ++ case RC_MEMSIZE_24_BITS_BE: ++ return (operand->type == RC_OPERAND_BCD) ? 1666665 : 0xFFFFFF; ++ ++ default: ++ return (operand->type == RC_OPERAND_BCD) ? 166666665 : 0xFFFFFFFF; ++ } ++} ++ ++static void rc_combine_ranges(uint32_t* min_val, uint32_t* max_val, uint8_t oper, uint32_t oper_min_val, uint32_t oper_max_val) ++{ ++ switch (oper) { ++ case RC_OPERATOR_MULT: ++ { ++ unsigned long long scaled = ((unsigned long long)*min_val) * oper_min_val; ++ *min_val = (scaled > 0xFFFFFFFF) ? 0xFFFFFFFF : (uint32_t)scaled; ++ ++ scaled = ((unsigned long long)*max_val) * oper_max_val; ++ *max_val = (scaled > 0xFFFFFFFF) ? 0xFFFFFFFF : (uint32_t)scaled; ++ break; ++ } ++ ++ case RC_OPERATOR_DIV: ++ *min_val = (oper_max_val == 0) ? *min_val : (*min_val / oper_max_val); ++ *max_val = (oper_min_val == 0) ? *max_val : (*max_val / oper_min_val); ++ break; ++ ++ case RC_OPERATOR_AND: ++ *min_val = 0; ++ *max_val &= oper_max_val; ++ break; ++ ++ case RC_OPERATOR_XOR: ++ *min_val = 0; ++ *max_val |= oper_max_val; ++ break; ++ ++ case RC_OPERATOR_MOD: ++ *min_val = 0; ++ *max_val = (*max_val >= oper_max_val) ? oper_max_val - 1 : *max_val; ++ break; ++ ++ case RC_OPERATOR_ADD: ++ if (*min_val > *max_val) { /* underflow occurred */ ++ *max_val += oper_max_val; ++ } ++ else { ++ unsigned long long scaled = ((unsigned long long)*max_val) + oper_max_val; ++ *max_val = (scaled > 0xFFFFFFFF) ? 0xFFFFFFFF : (uint32_t)scaled; ++ } ++ ++ *min_val += oper_min_val; ++ break; ++ ++ case RC_OPERATOR_SUB: ++ *min_val -= oper_max_val; ++ *max_val -= oper_min_val; ++ break; ++ ++ case RC_OPERATOR_SUB_PARENT: ++ { ++ uint32_t temp = oper_min_val - *max_val; ++ *max_val = oper_max_val - *min_val; ++ *min_val = temp; ++ break; ++ } ++ ++ default: ++ break; ++ } ++} ++ ++static void rc_chain_get_value_range(const rc_operand_t* operand, uint32_t* min_val, uint32_t* max_val) ++{ ++ if (rc_operand_is_memref(operand) && operand->value.memref->value.memref_type == RC_MEMREF_TYPE_MODIFIED_MEMREF) { ++ const rc_modified_memref_t* modified_memref = (const rc_modified_memref_t*)operand->value.memref; ++ if (modified_memref->modifier_type != RC_OPERATOR_INDIRECT_READ) { ++ if (modified_memref->modifier_type == RC_OPERATOR_DIV && ++ rc_operand_is_memref(&modified_memref->modifier) && ++ rc_operands_are_equal(&modified_memref->modifier, &modified_memref->parent)) { ++ /* division by self can only return 0 or 1. */ ++ *min_val = 0; ++ *max_val = 1; ++ } ++ else { ++ uint32_t modifier_min_val, modifier_max_val; ++ rc_chain_get_value_range(&modified_memref->parent, min_val, max_val); ++ rc_chain_get_value_range(&modified_memref->modifier, &modifier_min_val, &modifier_max_val); ++ rc_combine_ranges(min_val, max_val, modified_memref->modifier_type, modifier_min_val, modifier_max_val); ++ } ++ return; ++ } ++ } ++ ++ *min_val = (operand->type == RC_OPERAND_CONST) ? operand->value.num : 0; ++ *max_val = rc_max_value(operand); ++} ++ ++static int rc_validate_get_condition_index(const rc_condset_t* condset, const rc_condition_t* condition) ++{ ++ int index = 1; ++ const rc_condition_t* scan; ++ for (scan = condset->conditions; scan != NULL; scan = scan->next) ++ { ++ if (scan == condition) ++ return index; ++ ++ ++index; ++ } ++ ++ return 0; ++} ++ ++static void rc_validate_range(uint32_t min_val, uint32_t max_val, char oper, uint32_t max, rc_validation_state_t* state) ++{ ++ switch (oper) { ++ case RC_OPERATOR_AND: ++ if (min_val > max) ++ rc_validate_add_error(state, RC_VALIDATION_ERR_MASK_TOO_LARGE, 0, 0); ++ else if (min_val == 0 && max_val == 0) ++ rc_validate_add_error(state, RC_VALIDATION_ERR_MASK_RESULT_ALWAYS_ZERO, 0, 0); ++ break; ++ ++ case RC_OPERATOR_EQ: ++ if (min_val > max) ++ rc_validate_add_error(state, RC_VALIDATION_ERR_COMPARISON_NEVER_TRUE_WITH_MAX, max, 0); ++ break; ++ ++ case RC_OPERATOR_NE: ++ if (min_val > max) ++ rc_validate_add_error(state, RC_VALIDATION_ERR_COMPARISON_ALWAYS_TRUE_WITH_MAX, max, 0); ++ break; ++ ++ case RC_OPERATOR_GE: ++ if (min_val > max) ++ rc_validate_add_error(state, RC_VALIDATION_ERR_COMPARISON_NEVER_TRUE_WITH_MAX, max, 0); ++ else if (max_val == 0) ++ rc_validate_add_error(state, RC_VALIDATION_ERR_COMPARISON_ALWAYS_TRUE_WITH_MAX, max, 0); ++ break; ++ ++ case RC_OPERATOR_GT: ++ if (min_val >= max) ++ rc_validate_add_error(state, RC_VALIDATION_ERR_COMPARISON_NEVER_TRUE_WITH_MAX, max, 0); ++ break; ++ ++ case RC_OPERATOR_LE: ++ if (min_val >= max) ++ rc_validate_add_error(state, RC_VALIDATION_ERR_COMPARISON_ALWAYS_TRUE_WITH_MAX, max, 0); ++ break; ++ ++ case RC_OPERATOR_LT: ++ if (min_val > max) ++ rc_validate_add_error(state, RC_VALIDATION_ERR_COMPARISON_ALWAYS_TRUE_WITH_MAX, max, 0); ++ else if (max_val == 0) ++ rc_validate_add_error(state, RC_VALIDATION_ERR_COMPARISON_NEVER_TRUE, 0, 0); ++ break; ++ } ++} ++ ++static int rc_validate_condset_internal(const rc_condset_t* condset, rc_validation_state_t* state) ++{ ++ const rc_condition_t* cond; ++ int in_add_hits = 0; ++ int in_add_address = 0; ++ int is_combining = 0; ++ int has_measured = 0; ++ int measuredif_index = -1; ++ uint32_t errors_before = state->error_count; ++ ++ if (!condset) ++ return 1; ++ ++ state->cond_index = 1; ++ ++ for (cond = condset->conditions; cond; cond = cond->next, ++state->cond_index) { ++ /* validate the original operands first */ ++ const rc_operand_t* operand1 = rc_condition_get_real_operand1(cond); ++ int is_memref1 = rc_operand_is_memref(operand1); ++ const int is_memref2 = rc_operand_is_memref(&cond->operand2); ++ ++ if (!in_add_address) { ++ if (is_memref1) ++ rc_validate_memref(operand1->value.memref, state); ++ if (is_memref2) ++ rc_validate_memref(cond->operand2.value.memref, state); ++ } ++ else { ++ in_add_address = 0; ++ } ++ ++ /* if operand is {recall}, but memref is null, that means the Remember wasn't found */ ++ if (rc_operand_is_recall(operand1) && ++ rc_operand_type_is_memref(operand1->memref_access_type) && ++ !operand1->value.memref) { ++ rc_validate_add_error(state, RC_VALIDATION_ERR_RECALL_BEFORE_REMEMBER, 0, 0); ++ } ++ if (rc_operand_is_recall(&cond->operand2) && ++ rc_operand_type_is_memref(cond->operand2.memref_access_type) && ++ !cond->operand2.value.memref) { ++ rc_validate_add_error(state, RC_VALIDATION_ERR_RECALL_BEFORE_REMEMBER, 0, 0); ++ } ++ ++ switch (cond->type) { ++ case RC_CONDITION_ADD_SOURCE: ++ case RC_CONDITION_SUB_SOURCE: ++ case RC_CONDITION_REMEMBER: ++ is_combining = 1; ++ continue; ++ ++ case RC_CONDITION_ADD_ADDRESS: ++ if (operand1->type == RC_OPERAND_DELTA || operand1->type == RC_OPERAND_PRIOR) ++ rc_validate_add_error(state, RC_VALIDATION_ERR_POINTER_FROM_PREVIOUS_FRAME, 0, 0); ++ else if (rc_operand_is_float(operand1) || rc_operand_is_float(&cond->operand2)) ++ rc_validate_add_error(state, RC_VALIDATION_ERR_POINTER_NON_INTEGER_OFFSET, 0, 0); ++ else if (rc_operand_type_is_transform(operand1->type) && cond->oper != RC_OPERATOR_MULT) ++ rc_validate_add_error(state, RC_VALIDATION_ERR_POINTER_TRANSFORMED_OFFSET, 0, 0); ++ ++ in_add_address = 1; ++ is_combining = 1; ++ continue; ++ ++ case RC_CONDITION_ADD_HITS: ++ case RC_CONDITION_SUB_HITS: ++ in_add_hits = 1; ++ is_combining = 1; ++ break; ++ ++ case RC_CONDITION_AND_NEXT: ++ case RC_CONDITION_OR_NEXT: ++ case RC_CONDITION_RESET_NEXT_IF: ++ is_combining = 1; ++ break; ++ ++ case RC_CONDITION_RESET_IF: ++ if (in_add_hits) { ++ /* ResetIf at the end of a hit chain does not require a hit target. ++ * It's meant to reset things if some subset of conditions have been true. */ ++ in_add_hits = 0; ++ is_combining = 0; ++ break; ++ } ++ if (!state->has_hit_targets) ++ rc_validate_add_error(state, RC_VALIDATION_ERR_NO_HITS_TO_RESET, 0, 0); ++ else if (cond->required_hits == 1) ++ rc_validate_add_error(state, RC_VALIDATION_ERR_RESET_HIT_TARGET_OF_ONE, 0, 0); ++ /* fallthrough */ /* to default */ ++ default: ++ if (in_add_hits) { ++ if (cond->required_hits == 0) ++ rc_validate_add_error(state, RC_VALIDATION_ERR_ADDHITS_WITHOUT_TARGET, 0, 0); ++ ++ in_add_hits = 0; ++ } ++ ++ has_measured |= (cond->type == RC_CONDITION_MEASURED); ++ if (cond->type == RC_CONDITION_MEASURED_IF && measuredif_index == -1) ++ measuredif_index = state->cond_index; ++ ++ is_combining = 0; ++ break; ++ } ++ ++ /* original operands are valid. now switch to the derived operands for logic ++ * combining/comparing them */ ++ operand1 = &cond->operand1; ++ is_memref1 = rc_operand_is_memref(operand1); ++ ++ /* check for comparing two differently sized memrefs */ ++ if (is_memref1 && is_memref2 && ++ operand1->value.memref->value.memref_type == RC_MEMREF_TYPE_MEMREF && ++ cond->operand2.value.memref->value.memref_type == RC_MEMREF_TYPE_MEMREF && ++ rc_max_value(operand1) != rc_max_value(&cond->operand2)) { ++ rc_validate_add_error(state, RC_VALIDATION_ERR_COMPARING_DIFFERENT_MEMORY_SIZES, 0, 0); ++ } ++ ++ if (is_memref1 && rc_operand_is_float(operand1)) { ++ /* if left side is a float, right side will be converted to a float, so don't do range validation */ ++ } ++ else if (is_memref1 || is_memref2) { ++ /* if either side is a memref, check for impossible comparisons */ ++ const rc_operand_t* operand2 = &cond->operand2; ++ uint8_t oper = cond->oper; ++ uint32_t min, max; ++ uint32_t max_val = rc_max_value(operand2); ++ uint32_t min_val; ++ rc_typed_value_t typed_value; ++ ++ rc_chain_get_value_range(operand1, &min, &max); ++ if (min > max) { /* underflow */ ++ min = 0; ++ max = 0xFFFFFFFF; ++ } ++ ++ if (!is_memref1) { ++ /* pretend constant was on right side */ ++ operand2 = operand1; ++ operand1 = &cond->operand2; ++ max_val = max; ++ max = rc_max_value(&cond->operand2); ++ ++ switch (oper) { ++ case RC_OPERATOR_LT: oper = RC_OPERATOR_GT; break; ++ case RC_OPERATOR_LE: oper = RC_OPERATOR_GE; break; ++ case RC_OPERATOR_GT: oper = RC_OPERATOR_LT; break; ++ case RC_OPERATOR_GE: oper = RC_OPERATOR_LE; break; ++ } ++ } ++ ++ switch (operand2->type) { ++ case RC_OPERAND_CONST: ++ min_val = operand2->value.num; ++ break; ++ ++ case RC_OPERAND_FP: ++ min_val = (int)operand2->value.dbl; ++ ++ /* cannot compare an integer memory reference to a non-integral floating point value */ ++ if (!rc_operand_is_float_memref(operand1) && (float)min_val != operand2->value.dbl) { ++ switch (oper) { ++ case RC_OPERATOR_EQ: ++ typed_value.value.f32 = (float)operand2->value.dbl; ++ rc_validate_add_error(state, RC_VALIDATION_ERR_COMPARISON_NEVER_TRUE_INTEGER_TO_FLOAT, typed_value.value.u32, 0); ++ break; ++ ++ case RC_OPERATOR_NE: ++ typed_value.value.f32 = (float)operand2->value.dbl; ++ rc_validate_add_error(state, RC_VALIDATION_ERR_COMPARISON_ALWAYS_TRUE_INTEGER_TO_FLOAT, typed_value.value.u32, 0); ++ break; ++ ++ case RC_OPERATOR_GT: /* value could be greater than floor(float) */ ++ case RC_OPERATOR_LE: /* value could be less than or equal to floor(float) */ ++ break; ++ ++ case RC_OPERATOR_GE: /* value could be greater than or equal to ceil(float) */ ++ case RC_OPERATOR_LT: /* value could be less than ceil(float) */ ++ ++min_val; ++ break; ++ } ++ } ++ ++ break; ++ ++ default: /* right side is memref or add source chain */ ++ min_val = 0; ++ break; ++ } ++ ++ /* min_val and max_val are the range allowed by operand2. max is the upper value from operand1. */ ++ rc_validate_range(min_val, max_val, oper, max, state); ++ } ++ } ++ ++ if (is_combining) { ++ /* find the final condition so we can extract the type */ ++ state->cond_index--; ++ cond = condset->conditions; ++ while (cond->next) ++ cond = cond->next; ++ ++ rc_validate_add_error(state, RC_VALIDATION_ERR_TRAILING_CHAINING_CONDITION, cond->type, 0); ++ } ++ ++ if (measuredif_index != -1 && !has_measured) { ++ state->cond_index = measuredif_index; ++ rc_validate_add_error(state, RC_VALIDATION_ERR_MEASUREDIF_WITHOUT_MEASURED, 0, 0); ++ } ++ ++ return (state->error_count == errors_before); ++} ++ ++static int rc_condset_has_hittargets(const rc_condset_t* condset) ++{ ++ if (condset->num_hittarget_conditions > 0) ++ return 1; ++ ++ /* pause and reset conditions may have hittargets and won't be classified as hittarget conditions. ++ * measured conditions may also have hittargets. ++ * other conditions may have hittarget conditions in an AndNext/OrNext chain. ++ * basically, check everything other than hittarget (explicitly known) and indirect (cannot have). ++ */ ++ if (condset->num_pause_conditions || condset->num_reset_conditions || condset->num_measured_conditions || condset->num_other_conditions) { ++ const rc_condition_t* condition = rc_condset_get_conditions((rc_condset_t*)condset); ++ /* ASSERT: don't need to add num_hittarget_conditions because it must be 0 per earlier check */ ++ const rc_condition_t* stop = condition + condset->num_pause_conditions ++ + condset->num_reset_conditions + condset->num_measured_conditions ++ + condset->num_other_conditions; ++ for (; condition < stop; ++condition) { ++ if (condition->required_hits) ++ return 1; ++ } ++ } ++ ++ return 0; ++} ++ ++int rc_validate_condset(const rc_condset_t* condset, char result[], const size_t result_size, uint32_t max_address) ++{ ++ rc_validation_state_t state; ++ memset(&state, 0, sizeof(state)); ++ state.has_hit_targets = rc_condset_has_hittargets(condset); ++ state.max_address = max_address; ++ ++ result[0] = '\0'; ++ if (rc_validate_condset_internal(condset, &state)) { ++ const rc_validation_error_t* most_severe_error = rc_validate_find_most_severe_error(&state); ++ return rc_validate_format_error(result, result_size, &state, most_severe_error); ++ } ++ ++ return 1; ++} ++ ++int rc_validate_condset_for_console(const rc_condset_t* condset, char result[], const size_t result_size, uint32_t console_id) ++{ ++ rc_validation_state_t state; ++ memset(&state, 0, sizeof(state)); ++ state.console_id = console_id; ++ state.max_address = rc_console_max_address(console_id); ++ state.has_hit_targets = rc_condset_has_hittargets(condset); ++ ++ result[0] = '\0'; ++ if (rc_validate_condset_internal(condset, &state)) { ++ const rc_validation_error_t* most_severe_error = rc_validate_find_most_severe_error(&state); ++ return rc_validate_format_error(result, result_size, &state, most_severe_error); ++ } ++ ++ return 1; ++} ++ ++/* rc_condition_is_combining doesn't look at conditions that build a memref (like AddSource) */ ++static int rc_validate_is_combining_condition(const rc_condition_t* condition) ++{ ++ switch (condition->type) ++ { ++ case RC_CONDITION_ADD_ADDRESS: ++ case RC_CONDITION_ADD_HITS: ++ case RC_CONDITION_ADD_SOURCE: ++ case RC_CONDITION_AND_NEXT: ++ case RC_CONDITION_OR_NEXT: ++ case RC_CONDITION_RESET_NEXT_IF: ++ case RC_CONDITION_SUB_HITS: ++ case RC_CONDITION_SUB_SOURCE: ++ case RC_CONDITION_REMEMBER: ++ return 1; ++ ++ default: ++ return 0; ++ } ++} ++ ++static int rc_validate_get_opposite_comparison(int oper) ++{ ++ switch (oper) ++ { ++ case RC_OPERATOR_EQ: return RC_OPERATOR_NE; ++ case RC_OPERATOR_NE: return RC_OPERATOR_EQ; ++ case RC_OPERATOR_LT: return RC_OPERATOR_GE; ++ case RC_OPERATOR_LE: return RC_OPERATOR_GT; ++ case RC_OPERATOR_GT: return RC_OPERATOR_LE; ++ case RC_OPERATOR_GE: return RC_OPERATOR_LT; ++ default: return oper; ++ } ++} ++ ++static const rc_operand_t* rc_validate_get_comparison(const rc_condition_t* condition, int* comparison, unsigned* value) ++{ ++ if (rc_operand_is_memref(&condition->operand1)) ++ { ++ if (condition->operand2.type != RC_OPERAND_CONST) ++ return NULL; ++ ++ *comparison = condition->oper; ++ *value = condition->operand2.value.num; ++ return &condition->operand1; ++ } ++ ++ if (condition->operand1.type != RC_OPERAND_CONST) ++ return NULL; ++ ++ if (!rc_operand_is_memref(&condition->operand2)) ++ return NULL; ++ ++ *comparison = rc_validate_get_opposite_comparison(condition->oper); ++ *value = condition->operand1.value.num; ++ return &condition->operand2; ++} ++ ++enum { ++ RC_OVERLAP_NONE = 0, ++ RC_OVERLAP_CONFLICTING, ++ RC_OVERLAP_REDUNDANT, ++ RC_OVERLAP_DEFER ++}; ++ ++static int rc_validate_comparison_overlap(int comparison1, uint32_t value1, int comparison2, uint32_t value2) ++{ ++ /* NOTE: this only cares if comp2 conflicts with comp1. ++ * If comp1 conflicts with comp2, we'll catch that later (return RC_OVERLAP_NONE for now) */ ++ switch (comparison2) ++ { ++ case RC_OPERATOR_EQ: ++ switch (comparison1) /* comp1 comp2 comp1 comp2 comp1 comp2 */ ++ { /* value1 = value2 value1 < value2 value1 > value2 */ ++ case RC_OPERATOR_EQ: /* a == 1 && a == 1 | a == 1 && a == 2 | a == 2 && a == 1 */ ++ /* redundant conflict conflict */ ++ return (value1 == value2) ? RC_OVERLAP_REDUNDANT : RC_OVERLAP_CONFLICTING; ++ case RC_OPERATOR_LE: /* a <= 1 && a == 1 | a <= 1 && a == 2 | a <= 2 && a == 1 */ ++ /* defer conflict defer */ ++ return (value1 < value2) ? RC_OVERLAP_CONFLICTING : RC_OVERLAP_DEFER; ++ case RC_OPERATOR_GE: /* a >= 1 && a == 1 | a >= 1 && a == 2 | a >= 2 && a == 1 */ ++ /* defer defer conflict */ ++ return (value1 > value2) ? RC_OVERLAP_CONFLICTING : RC_OVERLAP_DEFER; ++ case RC_OPERATOR_NE: /* a != 1 && a == 1 | a != 1 && a == 2 | a != 2 && a == 1 */ ++ /* conflict defer defer */ ++ return (value1 == value2) ? RC_OVERLAP_CONFLICTING : RC_OVERLAP_DEFER; ++ case RC_OPERATOR_LT: /* a < 1 && a == 1 | a < 1 && a == 2 | a < 2 && a == 1 */ ++ /* conflict conflict defer */ ++ return (value1 <= value2) ? RC_OVERLAP_CONFLICTING : RC_OVERLAP_DEFER; ++ case RC_OPERATOR_GT: /* a > 1 && a == 1 | a > 1 && a == 2 | a > 2 && a == 1 */ ++ /* conflict defer conflict */ ++ return (value1 >= value2) ? RC_OVERLAP_CONFLICTING : RC_OVERLAP_DEFER; ++ } ++ break; ++ ++ case RC_OPERATOR_NE: ++ switch (comparison1) /* comp1 comp2 comp1 comp2 comp1 comp2 */ ++ { /* value1 = value2 value1 < value2 value1 > value2 */ ++ case RC_OPERATOR_EQ: /* a == 1 && a != 1 | a == 1 && a != 2 | a == 2 && a != 1 */ ++ /* conflict redundant redundant */ ++ return (value1 == value2) ? RC_OVERLAP_CONFLICTING : RC_OVERLAP_REDUNDANT; ++ case RC_OPERATOR_LE: /* a <= 1 && a != 1 | a <= 1 && a != 2 | a <= 2 && a != 1 */ ++ /* none redundant none */ ++ return (value1 < value2) ? RC_OVERLAP_REDUNDANT : RC_OVERLAP_NONE; ++ case RC_OPERATOR_GE: /* a >= 1 && a != 1 | a >= 1 && a != 2 | a >= 2 && a != 1 */ ++ /* none none redundant */ ++ return (value1 > value2) ? RC_OVERLAP_REDUNDANT : RC_OVERLAP_NONE; ++ case RC_OPERATOR_NE: /* a != 1 && a != 1 | a != 1 && a != 2 | a != 2 && a != 1 */ ++ /* redundant none none */ ++ return (value1 == value2) ? RC_OVERLAP_REDUNDANT : RC_OVERLAP_NONE; ++ case RC_OPERATOR_LT: /* a < 1 && a != 1 | a < 1 && a != 2 | a < 2 && a != 1 */ ++ /* redundant redundant none */ ++ return (value1 <= value2) ? RC_OVERLAP_REDUNDANT : RC_OVERLAP_NONE; ++ case RC_OPERATOR_GT: /* a > 1 && a != 1 | a > 1 && a != 2 | a > 2 && a != 1 */ ++ /* redundant none redundant */ ++ return (value1 >= value2) ? RC_OVERLAP_REDUNDANT : RC_OVERLAP_NONE; ++ } ++ break; ++ ++ case RC_OPERATOR_LT: ++ switch (comparison1) /* comp1 comp2 comp1 comp2 comp1 comp2 */ ++ { /* value1 = value2 value1 < value2 value1 > value2 */ ++ case RC_OPERATOR_EQ: /* a == 1 && a < 1 | a == 1 && a < 2 | a == 2 && a < 1 */ ++ /* conflict redundant conflict */ ++ return (value1 < value2) ? RC_OVERLAP_REDUNDANT : RC_OVERLAP_CONFLICTING; ++ case RC_OPERATOR_LE: /* a <= 1 && a < 1 | a <= 1 && a < 2 | a <= 2 && a < 1 */ ++ /* defer redundant defer */ ++ return (value1 < value2) ? RC_OVERLAP_REDUNDANT : RC_OVERLAP_DEFER; ++ case RC_OPERATOR_GE: /* a >= 1 && a < 1 | a >= 1 && a < 2 | a >= 2 && a < 1 */ ++ /* conflict none conflict */ ++ return (value1 >= value2) ? RC_OVERLAP_CONFLICTING : RC_OVERLAP_NONE; ++ case RC_OPERATOR_NE: /* a != 1 && a < 1 | a != 1 && a < 2 | a != 2 && a < 1 */ ++ /* defer none defer */ ++ return (value1 >= value2) ? RC_OVERLAP_DEFER : RC_OVERLAP_NONE; ++ case RC_OPERATOR_LT: /* a < 1 && a < 1 | a < 1 && a < 2 | a < 2 && a < 1 */ ++ /* redundant redundant defer */ ++ return (value1 <= value2) ? RC_OVERLAP_REDUNDANT : RC_OVERLAP_DEFER; ++ case RC_OPERATOR_GT: /* a > 1 && a < 1 | a > 1 && a < 2 | a > 2 && a < 1 */ ++ /* conflict none conflict */ ++ return (value1 >= value2) ? RC_OVERLAP_CONFLICTING : RC_OVERLAP_NONE; ++ } ++ break; ++ ++ case RC_OPERATOR_LE: ++ switch (comparison1) /* comp1 comp2 comp1 comp2 comp1 comp2 */ ++ { /* value1 = value2 value1 < value2 value1 > value2 */ ++ case RC_OPERATOR_EQ: /* a == 1 && a <= 1 | a == 1 && a <= 2 | a == 2 && a <= 1 */ ++ /* redundant redundant conflict */ ++ return (value1 <= value2) ? RC_OVERLAP_REDUNDANT : RC_OVERLAP_CONFLICTING; ++ case RC_OPERATOR_LE: /* a <= 1 && a <= 1 | a <= 1 && a <= 2 | a <= 2 && a <= 1 */ ++ /* redundant redundant defer */ ++ return (value1 <= value2) ? RC_OVERLAP_REDUNDANT : RC_OVERLAP_DEFER; ++ case RC_OPERATOR_GE: /* a >= 1 && a <= 1 | a >= 1 && a <= 2 | a >= 2 && a <= 1 */ ++ /* none none conflict */ ++ return (value1 > value2) ? RC_OVERLAP_CONFLICTING : RC_OVERLAP_NONE; ++ case RC_OPERATOR_NE: /* a != 1 && a <= 1 | a != 1 && a <= 2 | a != 2 && a <= 1 */ ++ /* none none defer */ ++ return (value1 > value2) ? RC_OVERLAP_DEFER : RC_OVERLAP_NONE; ++ case RC_OPERATOR_LT: /* a < 1 && a <= 1 | a < 1 && a <= 2 | a < 2 && a <= 1 */ ++ /* redundant redundant defer */ ++ return (value1 <= value2) ? RC_OVERLAP_REDUNDANT : RC_OVERLAP_DEFER; ++ case RC_OPERATOR_GT: /* a > 1 && a <= 1 | a > 1 && a <= 2 | a > 2 && a <= 1 */ ++ /* conflict none conflict */ ++ return (value1 >= value2) ? RC_OVERLAP_CONFLICTING : RC_OVERLAP_NONE; ++ } ++ break; ++ ++ case RC_OPERATOR_GT: ++ switch (comparison1) /* comp1 comp2 comp1 comp2 comp1 comp2 */ ++ { /* value1 = value2 value1 < value2 value1 > value2 */ ++ case RC_OPERATOR_EQ: /* a == 1 && a > 1 | a == 1 && a > 2 | a == 2 && a > 1 */ ++ /* conflict conflict redundant */ ++ return (value1 > value2) ? RC_OVERLAP_REDUNDANT : RC_OVERLAP_CONFLICTING; ++ case RC_OPERATOR_LE: /* a <= 1 && a > 1 | a <= 1 && a > 2 | a <= 2 && a > 1 */ ++ /* conflict conflict defer */ ++ return (value1 <= value2) ? RC_OVERLAP_CONFLICTING : RC_OVERLAP_DEFER; ++ case RC_OPERATOR_GE: /* a >= 1 && a > 1 | a >= 1 && a > 2 | a >= 2 && a > 1 */ ++ /* defer defer redundant */ ++ return (value1 > value2) ? RC_OVERLAP_REDUNDANT : RC_OVERLAP_DEFER; ++ case RC_OPERATOR_NE: /* a != 1 && a > 1 | a != 1 && a > 2 | a != 2 && a > 1 */ ++ /* defer defer none */ ++ return (value1 <= value2) ? RC_OVERLAP_DEFER : RC_OVERLAP_NONE; ++ case RC_OPERATOR_LT: /* a < 1 && a > 1 | a < 1 && a > 2 | a < 2 && a > 1 */ ++ /* conflict conflict none */ ++ return (value1 <= value2) ? RC_OVERLAP_CONFLICTING : RC_OVERLAP_NONE; ++ case RC_OPERATOR_GT: /* a > 1 && a > 1 | a > 1 && a > 2 | a > 2 && a > 1 */ ++ /* redundant defer redundant */ ++ return (value1 >= value2) ? RC_OVERLAP_REDUNDANT : RC_OVERLAP_DEFER; ++ } ++ break; ++ ++ case RC_OPERATOR_GE: ++ switch (comparison1) /* comp1 comp2 comp1 comp2 comp1 comp2 */ ++ { /* value1 = value2 value1 < value2 value1 > value2 */ ++ case RC_OPERATOR_EQ: /* a == 1 && a >= 1 | a == 1 && a >= 2 | a == 2 && a >= 1 */ ++ /* redundant conflict redundant */ ++ return (value1 >= value2) ? RC_OVERLAP_REDUNDANT : RC_OVERLAP_CONFLICTING; ++ case RC_OPERATOR_LE: /* a <= 1 && a >= 1 | a <= 1 && a >= 2 | a <= 2 && a >= 1 */ ++ /* none conflict none */ ++ return (value1 < value2) ? RC_OVERLAP_CONFLICTING : RC_OVERLAP_NONE; ++ case RC_OPERATOR_GE: /* a >= 1 && a >= 1 | a >= 1 && a >= 2 | a >= 2 && a >= 1 */ ++ /* redundant redundant defer */ ++ return (value1 <= value2) ? RC_OVERLAP_REDUNDANT : RC_OVERLAP_DEFER; ++ case RC_OPERATOR_NE: /* a != 1 && a >= 1 | a != 1 && a >= 2 | a != 2 && a >= 1 */ ++ /* none defer none */ ++ return (value1 < value2) ? RC_OVERLAP_DEFER : RC_OVERLAP_NONE; ++ case RC_OPERATOR_LT: /* a < 1 && a >= 1 | a < 1 && a >= 2 | a < 2 && a >= 1 */ ++ /* conflict conflict none */ ++ return (value1 <= value2) ? RC_OVERLAP_CONFLICTING : RC_OVERLAP_NONE; ++ case RC_OPERATOR_GT: /* a > 1 && a >= 1 | a > 1 && a >= 2 | a > 2 && a >= 1 */ ++ /* redundant defer redundant */ ++ return (value1 >= value2) ? RC_OVERLAP_REDUNDANT : RC_OVERLAP_DEFER; ++ } ++ break; ++ } ++ ++ return RC_OVERLAP_NONE; ++} ++ ++static int rc_validate_conflicting_conditions(const rc_condset_t* conditions, const rc_condset_t* compare_conditions, ++ uint32_t group_index, rc_validation_state_t* state) ++{ ++ int comparison1, comparison2; ++ uint32_t value1, value2; ++ const rc_operand_t* operand1; ++ const rc_operand_t* operand2; ++ const rc_condition_t* compare_condition; ++ const rc_condition_t* condition; ++ const rc_condition_t* condition_chain_start; ++ uint32_t errors_before = state->error_count; ++ int overlap; ++ int chain_matches; ++ ++ /* empty group */ ++ if (conditions == NULL || compare_conditions == NULL) ++ return 1; ++ ++ /* outer loop is the source conditions */ ++ for (condition = conditions->conditions; condition != NULL; condition = condition->next, ++state->cond_index) { ++ condition_chain_start = condition; ++ while (condition && rc_condition_is_combining(condition)) { ++ condition = condition->next; ++ } ++ if (!condition) ++ break; ++ ++ /* hits can be captured at any time, so any potential conflict will not be conflicting at another time */ ++ if (condition->required_hits) ++ continue; ++ ++ operand1 = rc_validate_get_comparison(condition, &comparison1, &value1); ++ if (!operand1) ++ continue; ++ ++ switch (condition->type) { ++ case RC_CONDITION_PAUSE_IF: ++ if (conditions != compare_conditions) ++ break; ++ /* fallthrough */ ++ case RC_CONDITION_RESET_IF: ++ comparison1 = rc_validate_get_opposite_comparison(comparison1); ++ break; ++ default: ++ if (rc_validate_is_combining_condition(condition)) ++ continue; ++ break; ++ } ++ ++ /* inner loop is the potentially conflicting conditions */ ++ state->cond_index = 1; ++ for (compare_condition = compare_conditions->conditions; compare_condition != NULL; compare_condition = compare_condition->next, ++state->cond_index) { ++ if (compare_condition == condition_chain_start) { ++ /* skip condition we're already looking at */ ++ while (compare_condition != condition) { ++ ++state->cond_index; ++ compare_condition = compare_condition->next; ++ } ++ ++ continue; ++ } ++ ++ /* if combining conditions exist, make sure the same combining conditions exist in the ++ * compare logic. conflicts can only occur if the combinining conditions match. */ ++ chain_matches = 1; ++ if (condition_chain_start != condition) { ++ const rc_condition_t* condition_chain_iter = condition_chain_start; ++ while (condition_chain_iter != condition) { ++ if (compare_condition->type != condition_chain_iter->type || ++ compare_condition->oper != condition_chain_iter->oper || ++ compare_condition->required_hits != condition_chain_iter->required_hits || ++ !rc_operands_are_equal(&compare_condition->operand1, &condition_chain_iter->operand1)) ++ { ++ chain_matches = 0; ++ break; ++ } ++ ++ if (compare_condition->oper != RC_OPERATOR_NONE && ++ !rc_operands_are_equal(&compare_condition->operand2, &condition_chain_iter->operand2)) ++ { ++ chain_matches = 0; ++ break; ++ } ++ ++ if (!compare_condition->next) { ++ chain_matches = 0; ++ break; ++ } ++ ++ if (compare_condition->type != RC_CONDITION_ADD_ADDRESS && ++ compare_condition->type != RC_CONDITION_ADD_SOURCE && ++ compare_condition->type != RC_CONDITION_SUB_SOURCE && ++ compare_condition->type != RC_CONDITION_AND_NEXT) ++ { ++ /* things like AddHits and OrNext are hard to definitively detect conflicts. ignore them. */ ++ chain_matches = 0; ++ break; ++ } ++ ++ ++state->cond_index; ++ compare_condition = compare_condition->next; ++ condition_chain_iter = condition_chain_iter->next; ++ } ++ } ++ ++ /* combining field didn't match, or there's more unmatched combining fields. ignore this condition */ ++ if (!chain_matches || rc_validate_is_combining_condition(compare_condition)) { ++ while (compare_condition->next && rc_validate_is_combining_condition(compare_condition)) ++ compare_condition = compare_condition->next; ++ continue; ++ } ++ ++ if (compare_condition->required_hits) ++ continue; ++ ++ operand2 = rc_validate_get_comparison(compare_condition, &comparison2, &value2); ++ if (!operand2 || !rc_operands_are_equal(operand1, operand2)) ++ continue; ++ ++ switch (compare_condition->type) { ++ case RC_CONDITION_PAUSE_IF: ++ if (conditions != compare_conditions) /* PauseIf only affects conditions in same group */ ++ break; ++ /* fallthrough */ ++ case RC_CONDITION_RESET_IF: ++ comparison2 = rc_validate_get_opposite_comparison(comparison2); ++ break; ++ default: ++ if (rc_validate_is_combining_condition(compare_condition)) ++ continue; ++ break; ++ } ++ ++ overlap = rc_validate_comparison_overlap(comparison1, value1, comparison2, value2); ++ switch (overlap) ++ { ++ case RC_OVERLAP_CONFLICTING: ++ if (compare_condition->type == RC_CONDITION_PAUSE_IF || condition->type == RC_CONDITION_PAUSE_IF) ++ { ++ /* ignore PauseIf conflicts between groups, unless both conditions are PauseIfs */ ++ if (conditions != compare_conditions && compare_condition->type != condition->type) ++ continue; ++ } ++ break; ++ ++ case RC_OVERLAP_REDUNDANT: ++ if (group_index != state->group_index && state->group_index == 0) ++ { ++ /* if the alt condition is more restrictive than the core condition, ignore it */ ++ if (rc_validate_comparison_overlap(comparison2, value2, comparison1, value1) != RC_OVERLAP_REDUNDANT) ++ continue; ++ } ++ ++ if (compare_condition->type == RC_CONDITION_PAUSE_IF || condition->type == RC_CONDITION_PAUSE_IF) ++ { ++ /* ignore PauseIf redundancies between groups */ ++ if (conditions != compare_conditions) ++ continue; ++ ++ /* if the PauseIf is less restrictive than the other condition, it's just a guard. ignore it */ ++ if (rc_validate_comparison_overlap(comparison2, value2, comparison1, value1) != RC_OVERLAP_REDUNDANT) ++ continue; ++ ++ /* PauseIf redundant with ResetIf is a conflict (both are inverted comparisons) */ ++ if (compare_condition->type == RC_CONDITION_RESET_IF || condition->type == RC_CONDITION_RESET_IF) ++ overlap = RC_OVERLAP_CONFLICTING; ++ } ++ else if (compare_condition->type == RC_CONDITION_RESET_IF && condition->type != RC_CONDITION_RESET_IF) ++ { ++ /* only ever report the redundancy on the non-ResetIf condition. The ResetIf is allowed to ++ * fire when the non-ResetIf condition is not true. */ ++ if (state->has_hit_targets) ++ continue; ++ } ++ else if (condition->type == RC_CONDITION_RESET_IF && compare_condition->type != RC_CONDITION_RESET_IF) ++ { ++ /* if the ResetIf condition is more restrictive than the non-ResetIf condition, ++ and there aren't any hits to clear, ignore it */ ++ if (state->has_hit_targets) ++ continue; ++ } ++ else if (compare_condition->type == RC_CONDITION_MEASURED_IF || condition->type == RC_CONDITION_MEASURED_IF) ++ { ++ /* ignore MeasuredIf redundancies between groups */ ++ if (conditions != compare_conditions) ++ continue; ++ ++ if (compare_condition->type == RC_CONDITION_MEASURED_IF && condition->type != RC_CONDITION_MEASURED_IF) ++ { ++ /* only ever report the redundancy on the non-MeasuredIf condition. The MeasuredIf provides ++ * additional functionality. */ ++ continue; ++ } ++ } ++ else if (condition->type == RC_CONDITION_TRIGGER && compare_condition->type != RC_CONDITION_TRIGGER) ++ { ++ /* Trigger is allowed to be redundant with non-trigger conditions as there may be limits that start a ++ * challenge that are further reduced for the completion of the challenge */ ++ continue; ++ } ++ break; ++ ++ default: ++ continue; ++ } ++ ++ /* if condition A conflicts with condition B, condition B will also conflict with ++ * condition A. don't report both. */ ++ { ++ int already_reported = 0; ++ const rc_validation_error_t* error = state->errors; ++ const rc_validation_error_t* stop = state->errors + state->error_count; ++ for (; error < stop; ++error) { ++ if (error->data2 == state->cond_index && error->data1 == state->group_index) { ++ if (error->err == RC_VALIDATION_ERR_REDUNDANT_CONDITION || ++ error->err == RC_VALIDATION_ERR_CONFLICTING_CONDITION) { ++ already_reported = 1; ++ } ++ } ++ } ++ ++ if (already_reported) ++ continue; ++ } ++ ++ rc_validate_add_error(state, (overlap == RC_OVERLAP_REDUNDANT) ? ++ RC_VALIDATION_ERR_REDUNDANT_CONDITION : RC_VALIDATION_ERR_CONFLICTING_CONDITION, ++ group_index, rc_validate_get_condition_index(conditions, condition)); ++ } ++ } ++ ++ return (state->error_count == errors_before); ++} ++ ++static int rc_validate_trigger_internal(const rc_trigger_t* trigger, rc_validation_state_t* state) ++{ ++ rc_condset_t* alt; ++ uint32_t index; ++ ++ state->has_alt_groups = (trigger->alternative != NULL); ++ ++ state->has_hit_targets = trigger->requirement && rc_condset_has_hittargets(trigger->requirement); ++ if (!state->has_hit_targets) { ++ for (alt = trigger->alternative; alt; alt = alt->next) { ++ if (rc_condset_has_hittargets(alt)) { ++ state->has_hit_targets = 1; ++ break; ++ } ++ } ++ } ++ ++ state->group_index = 0; ++ if (rc_validate_condset_internal(trigger->requirement, state)) { ++ /* compare core to itself */ ++ rc_validate_conflicting_conditions(trigger->requirement, trigger->requirement, 0, state); ++ } ++ ++ index = 1; ++ for (alt = trigger->alternative; alt; alt = alt->next, ++index) { ++ state->group_index = index; ++ if (rc_validate_condset_internal(alt, state)) { ++ /* compare alt to itself */ ++ if (!rc_validate_conflicting_conditions(alt, alt, index, state)) ++ continue; ++ ++ /* compare alt to core */ ++ if (!rc_validate_conflicting_conditions(trigger->requirement, alt, 0, state)) ++ continue; ++ ++ /* compare core to alt */ ++ state->group_index = 0; ++ if (!rc_validate_conflicting_conditions(alt, trigger->requirement, index, state)) ++ continue; ++ } ++ } ++ ++ return (state->error_count == 0); ++} ++ ++int rc_validate_trigger(const rc_trigger_t* trigger, char result[], const size_t result_size, uint32_t max_address) ++{ ++ rc_validation_state_t state; ++ memset(&state, 0, sizeof(state)); ++ state.max_address = max_address; ++ ++ result[0] = '\0'; ++ if (!rc_validate_trigger_internal(trigger, &state)) { ++ const rc_validation_error_t* most_severe_error = rc_validate_find_most_severe_error(&state); ++ return rc_validate_format_error(result, result_size, &state, most_severe_error); ++ } ++ ++ return 1; ++} ++ ++int rc_validate_trigger_for_console(const rc_trigger_t* trigger, char result[], const size_t result_size, uint32_t console_id) ++{ ++ rc_validation_state_t state; ++ memset(&state, 0, sizeof(state)); ++ state.console_id = console_id; ++ state.max_address = rc_console_max_address(console_id); ++ ++ result[0] = '\0'; ++ if (!rc_validate_trigger_internal(trigger, &state)) { ++ const rc_validation_error_t* most_severe_error = rc_validate_find_most_severe_error(&state); ++ return rc_validate_format_error(result, result_size, &state, most_severe_error); ++ } ++ ++ return 1; ++} +diff -rupbN melonDS.orig/src/rcheevos/src/rcheevos/rc_validate.h melonDS.ra/src/rcheevos/src/rcheevos/rc_validate.h +--- melonDS.orig/src/rcheevos/src/rcheevos/rc_validate.h 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rcheevos/rc_validate.h 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,18 @@ ++#ifndef RC_VALIDATE_H ++#define RC_VALIDATE_H ++ ++#include "rc_runtime_types.h" ++ ++#include ++ ++RC_BEGIN_C_DECLS ++ ++int rc_validate_condset(const rc_condset_t* condset, char result[], const size_t result_size, uint32_t max_address); ++int rc_validate_trigger(const rc_trigger_t* trigger, char result[], const size_t result_size, uint32_t max_address); ++ ++int rc_validate_condset_for_console(const rc_condset_t* condset, char result[], const size_t result_size, uint32_t console_id); ++int rc_validate_trigger_for_console(const rc_trigger_t* trigger, char result[], const size_t result_size, uint32_t console_id); ++ ++RC_END_C_DECLS ++ ++#endif /* RC_VALIDATE_H */ +diff -rupbN melonDS.orig/src/rcheevos/src/rcheevos/richpresence.c melonDS.ra/src/rcheevos/src/rcheevos/richpresence.c +--- melonDS.orig/src/rcheevos/src/rcheevos/richpresence.c 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rcheevos/richpresence.c 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,922 @@ ++#include "rc_internal.h" ++ ++#include "../rc_compat.h" ++ ++#include ++ ++/* special formats only used by rc_richpresence_display_part_t.display_type. must not overlap other RC_FORMAT values */ ++enum { ++ RC_FORMAT_STRING = 101, ++ RC_FORMAT_LOOKUP = 102, ++ RC_FORMAT_UNKNOWN_MACRO = 103, ++ RC_FORMAT_ASCIICHAR = 104, ++ RC_FORMAT_UNICODECHAR = 105 ++}; ++ ++static void rc_alloc_helper_variable_memref_value(rc_richpresence_display_part_t* part, const char* memaddr, int memaddr_len, rc_parse_state_t* parse) { ++ rc_preparse_state_t preparse; ++ const char* test_memaddr = memaddr; ++ rc_condset_t* condset; ++ rc_value_t* value; ++ int32_t size; ++ ++ part->value.type = RC_OPERAND_NONE; ++ ++ /* if the expression can be represented as just a memory reference, do so */ ++ rc_init_preparse_state(&preparse); ++ preparse.parse.existing_memrefs = parse->memrefs; ++ value = RC_ALLOC(rc_value_t, &preparse.parse); ++ rc_parse_value_internal(value, &test_memaddr, &preparse.parse); ++ ++ size = preparse.parse.offset; ++ if (size < 0) { ++ parse->offset = size; ++ rc_destroy_preparse_state(&preparse); ++ return; ++ } ++ ++ /* ensure new needed memrefs are allocated in the primary buffer */ ++ rc_preparse_copy_memrefs(parse, &preparse.memrefs); ++ ++ /* parse the value into the scratch buffer so we can look at it */ ++ rc_reset_parse_state(&preparse.parse, rc_buffer_alloc(&preparse.parse.scratch.buffer, (size_t)size)); ++ preparse.parse.memrefs = parse->memrefs; ++ preparse.parse.existing_memrefs = parse->existing_memrefs; ++ value = RC_ALLOC(rc_value_t, &preparse.parse); ++ test_memaddr = memaddr; ++ rc_parse_value_internal(value, &test_memaddr, &preparse.parse); ++ ++ condset = value->conditions; ++ if (condset && !condset->next) { ++ /* single value - if it's a single Measured clause (including any AddSource/AddAddress helpers), we can ++ * simplify to a memref. If there are supporting clauses like MeasuredIf or ResetIf, we can't */ ++ if (condset->num_measured_conditions == 1 && ++ !condset->num_pause_conditions && !condset->num_reset_conditions && ++ !condset->num_other_conditions && !condset->num_hittarget_conditions) { ++ rc_condition_t* condition = condset->conditions; ++ for (; condition; condition = condition->next) { ++ if (condition->type == RC_CONDITION_MEASURED && condition->required_hits == 0) { ++ memcpy(&part->value, &condition->operand1, sizeof(condition->operand1)); ++ break; ++ } ++ } ++ } ++ } ++ ++ rc_destroy_preparse_state(&preparse); ++ ++ /* could not express value with just a memory reference, create a helper variable */ ++ if (part->value.type == RC_OPERAND_NONE) { ++ value = rc_alloc_variable(memaddr, memaddr_len, parse); ++ if (value) { ++ part->value.value.memref = (rc_memref_t*)&value->value; ++ part->value.type = RC_OPERAND_ADDRESS; ++ part->value.size = RC_MEMSIZE_32_BITS; ++ part->value.memref_access_type = RC_OPERAND_ADDRESS; ++ } ++ } ++} ++ ++static const char* rc_parse_line(const char* line, const char** end, rc_parse_state_t* parse) { ++ const char* nextline; ++ const char* endline; ++ ++ /* get a single line */ ++ nextline = line; ++ while (*nextline && *nextline != '\n') ++ ++nextline; ++ ++ /* if a trailing comment marker (//) exists, the line stops there */ ++ endline = line; ++ while (endline < nextline && (endline[0] != '/' || endline[1] != '/' || (endline > line && endline[-1] == '\\'))) ++ ++endline; ++ ++ if (endline == nextline) { ++ /* trailing whitespace on a line without a comment marker may be significant, just remove the line ending */ ++ if (endline > line && endline[-1] == '\r') ++ --endline; ++ } else { ++ /* remove trailing whitespace before the comment marker */ ++ while (endline > line && isspace((int)((unsigned char*)endline)[-1])) ++ --endline; ++ } ++ ++ /* point end at the first character to ignore, it makes subtraction for length easier */ ++ *end = endline; ++ ++ /* tally the line */ ++ ++parse->lines_read; ++ ++ /* skip the newline character so we're pointing at the next line */ ++ if (*nextline == '\n') ++ ++nextline; ++ ++ return nextline; ++} ++ ++typedef struct rc_richpresence_builtin_macro_t { ++ const char* name; ++ size_t name_len; ++ uint8_t display_type; ++} rc_richpresence_builtin_macro_t; ++ ++static rc_richpresence_display_t* rc_parse_richpresence_display_internal(const char* line, const char* endline, rc_parse_state_t* parse, rc_richpresence_lookup_t* first_lookup) { ++ rc_richpresence_display_t* self; ++ rc_richpresence_display_part_t* part; ++ rc_richpresence_display_part_t** next; ++ rc_richpresence_lookup_t* lookup; ++ const char* ptr; ++ const char* in; ++ char* out; ++ ++ if (endline - line < 1) { ++ parse->offset = RC_MISSING_DISPLAY_STRING; ++ return 0; ++ } ++ ++ { ++ self = RC_ALLOC(rc_richpresence_display_t, parse); ++ memset(self, 0, sizeof(rc_richpresence_display_t)); ++ next = &self->display; ++ } ++ ++ /* break the string up on macros: text @macro() moretext */ ++ do { ++ ptr = line; ++ while (ptr < endline) { ++ if (*ptr == '@' && (ptr == line || ptr[-1] != '\\')) /* ignore escaped @s */ ++ break; ++ ++ ++ptr; ++ } ++ ++ if (ptr > line) { ++ part = RC_ALLOC(rc_richpresence_display_part_t, parse); ++ memset(part, 0, sizeof(rc_richpresence_display_part_t)); ++ *next = part; ++ next = &part->next; ++ ++ /* handle string part */ ++ part->display_type = RC_FORMAT_STRING; ++ part->text = rc_alloc_str(parse, line, (int)(ptr - line)); ++ if (part->text) { ++ /* remove backslashes used for escaping */ ++ in = part->text; ++ while (*in && *in != '\\') ++ ++in; ++ ++ if (*in == '\\') { ++ out = (char*)in++; ++ while (*in) { ++ *out++ = *in++; ++ if (*in == '\\') ++ ++in; ++ } ++ *out = '\0'; ++ } ++ } ++ } ++ ++ if (*ptr == '@') { ++ /* handle macro part */ ++ size_t macro_len; ++ ++ line = ++ptr; ++ while (ptr < endline && *ptr != '(') ++ ++ptr; ++ ++ if (ptr == endline) { ++ parse->offset = RC_MISSING_VALUE; ++ return 0; ++ } ++ ++ macro_len = ptr - line; ++ ++ part = RC_ALLOC(rc_richpresence_display_part_t, parse); ++ memset(part, 0, sizeof(rc_richpresence_display_part_t)); ++ *next = part; ++ next = &part->next; ++ ++ part->display_type = RC_FORMAT_UNKNOWN_MACRO; ++ ++ /* find the lookup and hook it up */ ++ lookup = first_lookup; ++ while (lookup) { ++ if (strncmp(lookup->name, line, macro_len) == 0 && lookup->name[macro_len] == '\0') { ++ part->text = lookup->name; ++ part->lookup = lookup; ++ part->display_type = lookup->format; ++ break; ++ } ++ ++ lookup = lookup->next; ++ } ++ ++ if (!lookup) { ++ static const rc_richpresence_builtin_macro_t builtin_macros[] = { ++ {"Number", 6, RC_FORMAT_VALUE}, ++ {"Score", 5, RC_FORMAT_SCORE}, ++ {"Centiseconds", 12, RC_FORMAT_CENTISECS}, ++ {"Seconds", 7, RC_FORMAT_SECONDS}, ++ {"Minutes", 7, RC_FORMAT_MINUTES}, ++ {"SecondsAsMinutes", 16, RC_FORMAT_SECONDS_AS_MINUTES}, ++ {"ASCIIChar", 9, RC_FORMAT_ASCIICHAR}, ++ {"UnicodeChar", 11, RC_FORMAT_UNICODECHAR}, ++ {"Float1", 6, RC_FORMAT_FLOAT1}, ++ {"Float2", 6, RC_FORMAT_FLOAT2}, ++ {"Float3", 6, RC_FORMAT_FLOAT3}, ++ {"Float4", 6, RC_FORMAT_FLOAT4}, ++ {"Float5", 6, RC_FORMAT_FLOAT5}, ++ {"Float6", 6, RC_FORMAT_FLOAT6}, ++ {"Fixed1", 6, RC_FORMAT_FIXED1}, ++ {"Fixed2", 6, RC_FORMAT_FIXED2}, ++ {"Fixed3", 6, RC_FORMAT_FIXED3}, ++ {"Unsigned", 8, RC_FORMAT_UNSIGNED_VALUE}, ++ {"Unformatted", 11, RC_FORMAT_UNFORMATTED} ++ }; ++ size_t i; ++ ++ for (i = 0; i < sizeof(builtin_macros) / sizeof(builtin_macros[0]); ++i) { ++ if (macro_len == builtin_macros[i].name_len && ++ memcmp(builtin_macros[i].name, line, builtin_macros[i].name_len) == 0) { ++ part->text = builtin_macros[i].name; ++ part->lookup = NULL; ++ part->display_type = builtin_macros[i].display_type; ++ break; ++ } ++ } ++ } ++ ++ /* find the closing parenthesis */ ++ in = line; ++ line = ++ptr; ++ while (ptr < endline && *ptr != ')') ++ ++ptr; ++ ++ if (*ptr != ')') { ++ /* non-terminated macro, dump the macro and the remaining portion of the line */ ++ --in; /* already skipped over @ */ ++ part->display_type = RC_FORMAT_STRING; ++ part->text = rc_alloc_str(parse, in, (int)(ptr - in)); ++ } ++ else if (part->display_type != RC_FORMAT_UNKNOWN_MACRO) { ++ rc_alloc_helper_variable_memref_value(part, line, (int)(ptr - line), parse); ++ if (parse->offset < 0) ++ return 0; ++ ++ ++ptr; ++ } ++ else { ++ /* assert: the allocated string is going to be smaller than the memory used for the parameter of the macro */ ++ ++ptr; ++ part->text = rc_alloc_str(parse, in, (int)(ptr - in)); ++ } ++ } ++ ++ line = ptr; ++ } while (line < endline); ++ ++ *next = 0; ++ ++ return self; ++} ++ ++static int rc_richpresence_lookup_item_count(rc_richpresence_lookup_item_t* item) ++{ ++ if (item == NULL) ++ return 0; ++ ++ return (rc_richpresence_lookup_item_count(item->left) + rc_richpresence_lookup_item_count(item->right) + 1); ++} ++ ++static void rc_rebalance_richpresence_lookup_get_items(rc_richpresence_lookup_item_t* root, ++ rc_richpresence_lookup_item_t** items, int* index) ++{ ++ if (root->left != NULL) ++ rc_rebalance_richpresence_lookup_get_items(root->left, items, index); ++ ++ items[*index] = root; ++ ++(*index); ++ ++ if (root->right != NULL) ++ rc_rebalance_richpresence_lookup_get_items(root->right, items, index); ++} ++ ++static void rc_rebalance_richpresence_lookup_rebuild(rc_richpresence_lookup_item_t** root, ++ rc_richpresence_lookup_item_t** items, int first, int last) ++{ ++ int mid = (first + last) / 2; ++ rc_richpresence_lookup_item_t* item = items[mid]; ++ *root = item; ++ ++ if (mid == first) ++ item->left = NULL; ++ else ++ rc_rebalance_richpresence_lookup_rebuild(&item->left, items, first, mid - 1); ++ ++ if (mid == last) ++ item->right = NULL; ++ else ++ rc_rebalance_richpresence_lookup_rebuild(&item->right, items, mid + 1, last); ++} ++ ++static void rc_rebalance_richpresence_lookup(rc_richpresence_lookup_item_t** root, rc_parse_state_t* parse) ++{ ++ rc_richpresence_lookup_item_t** items; ++ int index; ++ int size; ++ ++ /* don't bother rebalancing one or two items */ ++ int count = rc_richpresence_lookup_item_count(*root); ++ if (count < 3) ++ return; ++ ++ /* allocate space for the flattened list in scratch memory */ ++ size = count * sizeof(rc_richpresence_lookup_item_t*); ++ items = (rc_richpresence_lookup_item_t**)rc_buffer_alloc(&parse->scratch.buffer, size); ++ ++ /* if allocation fails, we can still use the unbalanced tree, so just bail out */ ++ if (items == NULL) ++ return; ++ ++ /* flatten the list */ ++ index = 0; ++ rc_rebalance_richpresence_lookup_get_items(*root, items, &index); ++ ++ /* and rebuild it as a balanced tree */ ++ rc_rebalance_richpresence_lookup_rebuild(root, items, 0, count - 1); ++} ++ ++static void rc_insert_richpresence_lookup_item(rc_richpresence_lookup_t* lookup, ++ uint32_t first, uint32_t last, const char* label, size_t label_len, rc_parse_state_t* parse) ++{ ++ rc_richpresence_lookup_item_t** next; ++ rc_richpresence_lookup_item_t* item; ++ ++ next = &lookup->root; ++ while ((item = *next) != NULL) { ++ if (first > item->last) { ++ if (first == item->last + 1 && ++ strncmp(label, item->label, label_len) == 0 && item->label[label_len] == '\0') { ++ item->last = last; ++ return; ++ } ++ ++ next = &item->right; ++ } ++ else if (last < item->first) { ++ if (last == item->first - 1 && ++ strncmp(label, item->label, label_len) == 0 && item->label[label_len] == '\0') { ++ item->first = first; ++ return; ++ } ++ ++ next = &item->left; ++ } ++ else { ++ parse->offset = RC_DUPLICATED_VALUE; ++ return; ++ } ++ } ++ ++ item = RC_ALLOC_SCRATCH(rc_richpresence_lookup_item_t, parse); ++ item->first = first; ++ item->last = last; ++ item->label = rc_alloc_str(parse, label, label_len); ++ item->left = item->right = NULL; ++ ++ *next = item; ++} ++ ++static const char* rc_parse_richpresence_lookup(rc_richpresence_lookup_t* lookup, const char* nextline, rc_parse_state_t* parse) ++{ ++ const char* line; ++ const char* endline; ++ const char* label; ++ char* endptr = 0; ++ uint32_t first, last; ++ int base; ++ ++ do ++ { ++ line = nextline; ++ if (line == NULL) ++ break; ++ ++ nextline = rc_parse_line(line, &endline, parse); ++ ++ if (endline - line < 2) { ++ /* ignore full line comments inside a lookup */ ++ if (line[0] == '/' && line[1] == '/') ++ continue; ++ ++ /* empty line indicates end of lookup */ ++ if (lookup->root) ++ rc_rebalance_richpresence_lookup(&lookup->root, parse); ++ break; ++ } ++ ++ /* "*=XXX" specifies default label if lookup does not provide a mapping for the value */ ++ if (line[0] == '*' && line[1] == '=') { ++ line += 2; ++ lookup->default_label = rc_alloc_str(parse, line, (int)(endline - line)); ++ continue; ++ } ++ ++ label = line; ++ while (label < endline && *label != '=') ++ ++label; ++ ++ if (label == endline) { ++ parse->offset = RC_MISSING_VALUE; ++ break; ++ } ++ ++label; ++ ++ do { ++ /* get the value for the mapping */ ++ if (line[0] == '0' && line[1] == 'x') { ++ line += 2; ++ base = 16; ++ } else { ++ base = 10; ++ } ++ ++ first = (unsigned)strtoul(line, &endptr, base); ++ ++ /* check for a range */ ++ if (*endptr != '-') { ++ /* no range, just set last to first */ ++ last = first; ++ } ++ else { ++ /* range, get last value */ ++ line = endptr + 1; ++ ++ if (line[0] == '0' && line[1] == 'x') { ++ line += 2; ++ base = 16; ++ } else { ++ base = 10; ++ } ++ ++ last = (unsigned)strtoul(line, &endptr, base); ++ } ++ ++ /* ignore spaces after the number - was previously ignored as string was split on equals */ ++ while (*endptr == ' ') ++ ++endptr; ++ ++ /* if we've found the equal sign, this is the last item */ ++ if (*endptr == '=') { ++ rc_insert_richpresence_lookup_item(lookup, first, last, label, (int)(endline - label), parse); ++ break; ++ } ++ ++ /* otherwise, if it's not a comma, it's an error */ ++ if (*endptr != ',') { ++ parse->offset = RC_INVALID_CONST_OPERAND; ++ break; ++ } ++ ++ /* insert the current item and continue scanning the next one */ ++ rc_insert_richpresence_lookup_item(lookup, first, last, label, (int)(endline - label), parse); ++ if (parse->offset < 0) ++ break; ++ ++ line = endptr + 1; ++ } while (line < endline); ++ ++ } while (parse->offset > 0); ++ ++ return nextline; ++} ++ ++void rc_parse_richpresence_internal(rc_richpresence_t* self, const char* script, rc_parse_state_t* parse) { ++ rc_richpresence_display_t** nextdisplay; ++ rc_richpresence_lookup_t* firstlookup = NULL; ++ rc_richpresence_lookup_t** nextlookup = &firstlookup; ++ rc_richpresence_lookup_t* lookup; ++ rc_trigger_t* trigger; ++ char format[64]; ++ const char* display = 0; ++ const char* line; ++ const char* nextline; ++ const char* endline; ++ const char* ptr; ++ int hasdisplay = 0; ++ int display_line = 0; ++ int chars; ++ ++ self->values = NULL; ++ ++ /* special case for empty script to return 1 line read */ ++ if (!*script) { ++ parse->lines_read = 1; ++ parse->offset = RC_MISSING_DISPLAY_STRING; ++ return; ++ } ++ ++ /* first pass: process macro initializers */ ++ line = script; ++ while (*line) { ++ nextline = rc_parse_line(line, &endline, parse); ++ if (strncmp(line, "Lookup:", 7) == 0) { ++ line += 7; ++ ++ lookup = RC_ALLOC_SCRATCH(rc_richpresence_lookup_t, parse); ++ lookup->name = rc_alloc_str(parse, line, (int)(endline - line)); ++ lookup->format = RC_FORMAT_LOOKUP; ++ lookup->root = NULL; ++ lookup->default_label = ""; ++ *nextlookup = lookup; ++ nextlookup = &lookup->next; ++ ++ nextline = rc_parse_richpresence_lookup(lookup, nextline, parse); ++ if (parse->offset < 0) ++ return; ++ ++ } else if (strncmp(line, "Format:", 7) == 0) { ++ line += 7; ++ if (endline - line == 11 && memcmp(line, "Unformatted", 11) == 0) { ++ /* for backwards compatibility with the comma rollout, we allow old scripts ++ * to define an Unformatted type mapped to VALUE, and new versions will ignore ++ * the definition and use the built-in macro. skip the next line (FormatType=) */ ++ line = rc_parse_line(nextline, &endline, parse); ++ continue; ++ } ++ ++ lookup = RC_ALLOC_SCRATCH(rc_richpresence_lookup_t, parse); ++ lookup->name = rc_alloc_str(parse, line, (int)(endline - line)); ++ lookup->root = NULL; ++ lookup->default_label = ""; ++ *nextlookup = lookup; ++ nextlookup = &lookup->next; ++ ++ line = nextline; ++ nextline = rc_parse_line(line, &endline, parse); ++ if (parse->buffer && strncmp(line, "FormatType=", 11) == 0) { ++ line += 11; ++ ++ chars = (int)(endline - line); ++ if (chars > 63) ++ chars = 63; ++ memcpy(format, line, chars); ++ format[chars] = '\0'; ++ ++ lookup->format = (uint8_t)rc_parse_format(format); ++ } else { ++ lookup->format = RC_FORMAT_VALUE; ++ } ++ } else if (strncmp(line, "Display:", 8) == 0) { ++ display = nextline; ++ display_line = parse->lines_read; ++ ++ /* scan as long as we find conditional lines or full line comments */ ++ do { ++ line = nextline; ++ nextline = rc_parse_line(line, &endline, parse); ++ } while (*line == '?' || (line[0] == '/' && line[1] == '/')); ++ } ++ ++ line = nextline; ++ } ++ ++ *nextlookup = 0; ++ self->first_lookup = firstlookup; ++ ++ nextdisplay = &self->first_display; ++ ++ /* second pass, process display string*/ ++ if (display) { ++ /* point the parser back at the display strings */ ++ int lines_read = parse->lines_read; ++ parse->lines_read = display_line; ++ line = display; ++ ++ nextline = rc_parse_line(line, &endline, parse); ++ ++ do { ++ if (line[0] == '?') { ++ /* conditional display: ?trigger?string */ ++ ptr = ++line; ++ while (ptr < endline && *ptr != '?') ++ ++ptr; ++ ++ if (ptr < endline) { ++ *nextdisplay = rc_parse_richpresence_display_internal(ptr + 1, endline, parse, firstlookup); ++ if (parse->offset < 0) ++ return; ++ ++ trigger = &((*nextdisplay)->trigger); ++ rc_parse_trigger_internal(trigger, &line, parse); ++ if (parse->offset < 0) ++ return; ++ ++ if (line != ptr) { ++ /* incomplete read */ ++ parse->offset = RC_INVALID_OPERATOR; ++ return; ++ } ++ ++ (*nextdisplay)->has_required_hits = parse->has_required_hits; ++ ++ if (parse->buffer) ++ nextdisplay = &((*nextdisplay)->next); ++ } ++ } ++ else if (line[0] != '/' || line[1] != '/') { ++ break; ++ } ++ ++ line = nextline; ++ nextline = rc_parse_line(line, &endline, parse); ++ } while (1); ++ ++ /* non-conditional display: string */ ++ *nextdisplay = rc_parse_richpresence_display_internal(line, endline, parse, firstlookup); ++ if (*nextdisplay) { ++ hasdisplay = 1; ++ nextdisplay = &((*nextdisplay)->next); ++ ++ /* restore the parser state */ ++ parse->lines_read = lines_read; ++ } ++ else { ++ /* this should only happen if the line is blank. ++ * expect parse->offset to be RC_MISSING_DISPLAY_STRING and leave parse->lines_read ++ * on the current line for error tracking. */ ++ } ++ } ++ ++ /* finalize */ ++ *nextdisplay = 0; ++ self->has_memrefs = 0; ++ ++ if (!hasdisplay && parse->offset > 0) { ++ parse->offset = RC_MISSING_DISPLAY_STRING; ++ } ++} ++ ++int rc_richpresence_size_lines(const char* script, int* lines_read) { ++ rc_richpresence_with_memrefs_t* richpresence; ++ rc_preparse_state_t preparse; ++ rc_init_preparse_state(&preparse); ++ ++ richpresence = RC_ALLOC(rc_richpresence_with_memrefs_t, &preparse.parse); ++ preparse.parse.variables = &richpresence->richpresence.values; ++ rc_parse_richpresence_internal(&richpresence->richpresence, script, &preparse.parse); ++ rc_preparse_alloc_memrefs(NULL, &preparse); ++ ++ if (lines_read) ++ *lines_read = preparse.parse.lines_read; ++ ++ rc_destroy_preparse_state(&preparse); ++ return preparse.parse.offset; ++} ++ ++int rc_richpresence_size(const char* script) { ++ return rc_richpresence_size_lines(script, NULL); ++} ++ ++rc_richpresence_t* rc_parse_richpresence(void* buffer, const char* script, void* unused_L, int unused_funcs_idx) { ++ rc_richpresence_with_memrefs_t* richpresence; ++ rc_preparse_state_t preparse; ++ ++ (void)unused_L; ++ (void)unused_funcs_idx; ++ ++ if (!buffer || !script) ++ return NULL; ++ ++ rc_init_preparse_state(&preparse); ++ richpresence = RC_ALLOC(rc_richpresence_with_memrefs_t, &preparse.parse); ++ preparse.parse.variables = &richpresence->richpresence.values; ++ rc_parse_richpresence_internal(&richpresence->richpresence, script, &preparse.parse); ++ ++ rc_reset_parse_state(&preparse.parse, buffer); ++ richpresence = RC_ALLOC(rc_richpresence_with_memrefs_t, &preparse.parse); ++ preparse.parse.variables = &richpresence->richpresence.values; ++ rc_preparse_alloc_memrefs(&richpresence->memrefs, &preparse); ++ ++ rc_parse_richpresence_internal(&richpresence->richpresence, script, &preparse.parse); ++ richpresence->richpresence.has_memrefs = 1; ++ ++ rc_destroy_preparse_state(&preparse); ++ return (preparse.parse.offset >= 0) ? &richpresence->richpresence : NULL; ++} ++ ++static void rc_update_richpresence_memrefs(rc_richpresence_t* self, rc_peek_t peek, void* ud) { ++ if (self->has_memrefs) { ++ rc_richpresence_with_memrefs_t* richpresence = (rc_richpresence_with_memrefs_t*)self; ++ rc_update_memref_values(&richpresence->memrefs, peek, ud); ++ } ++} ++ ++rc_memrefs_t* rc_richpresence_get_memrefs(rc_richpresence_t* self) { ++ if (self->has_memrefs) { ++ rc_richpresence_with_memrefs_t* richpresence = (rc_richpresence_with_memrefs_t*)self; ++ return &richpresence->memrefs; ++ } ++ ++ return NULL; ++} ++ ++void rc_update_richpresence(rc_richpresence_t* richpresence, rc_peek_t peek, void* peek_ud, void* unused_L) { ++ (void)unused_L; ++ ++ rc_update_richpresence_memrefs(richpresence, peek, peek_ud); ++ rc_update_values(richpresence->values, peek, peek_ud); ++ rc_update_richpresence_internal(richpresence, peek, peek_ud); ++} ++ ++void rc_update_richpresence_internal(rc_richpresence_t* richpresence, rc_peek_t peek, void* peek_ud) { ++ rc_richpresence_display_t* display; ++ ++ for (display = richpresence->first_display; display; display = display->next) { ++ if (display->has_required_hits) ++ rc_test_trigger(&display->trigger, peek, peek_ud, NULL); ++ } ++} ++ ++static int rc_evaluate_richpresence_display(rc_richpresence_display_part_t* part, char* buffer, size_t buffersize) ++{ ++ rc_richpresence_lookup_item_t* item; ++ rc_typed_value_t value; ++ char tmp[256]; ++ char* ptr = buffer; ++ const char* text; ++ size_t chars; ++ ++ *ptr = '\0'; ++ while (part) { ++ switch (part->display_type) { ++ case RC_FORMAT_STRING: ++ text = part->text; ++ chars = strlen(text); ++ break; ++ ++ case RC_FORMAT_LOOKUP: ++ rc_evaluate_operand(&value, &part->value, NULL); ++ rc_typed_value_convert(&value, RC_VALUE_TYPE_UNSIGNED); ++ ++ text = part->lookup->default_label; ++ item = part->lookup->root; ++ while (item) { ++ if (value.value.u32 > item->last) { ++ item = item->right; ++ } ++ else if (value.value.u32 < item->first) { ++ item = item->left; ++ } ++ else { ++ text = item->label; ++ break; ++ } ++ } ++ ++ chars = strlen(text); ++ break; ++ ++ case RC_FORMAT_ASCIICHAR: ++ chars = 0; ++ text = tmp; ++ value.type = RC_VALUE_TYPE_UNSIGNED; ++ ++ do { ++ rc_evaluate_operand(&value, &part->value, NULL); ++ if (value.value.u32 == 0) { ++ /* null terminator - skip over remaining character macros */ ++ while (part->next && part->next->display_type == RC_FORMAT_ASCIICHAR) ++ part = part->next; ++ break; ++ } ++ ++ if (value.value.u32 < 32 || value.value.u32 >= 127) ++ value.value.u32 = '?'; ++ ++ tmp[chars++] = (char)value.value.u32; ++ if (chars == sizeof(tmp) || !part->next || part->next->display_type != RC_FORMAT_ASCIICHAR) ++ break; ++ ++ part = part->next; ++ } while (1); ++ ++ tmp[chars] = '\0'; ++ break; ++ ++ case RC_FORMAT_UNICODECHAR: ++ chars = 0; ++ text = tmp; ++ value.type = RC_VALUE_TYPE_UNSIGNED; ++ ++ do { ++ rc_evaluate_operand(&value, &part->value, NULL); ++ if (value.value.u32 == 0) { ++ /* null terminator - skip over remaining character macros */ ++ while (part->next && part->next->display_type == RC_FORMAT_UNICODECHAR) ++ part = part->next; ++ break; ++ } ++ ++ if (value.value.u32 < 32 || value.value.u32 > 65535) ++ value.value.u32 = 0xFFFD; /* unicode replacement char */ ++ ++ if (value.value.u32 < 0x80) { ++ tmp[chars++] = (char)value.value.u32; ++ } ++ else if (value.value.u32 < 0x0800) { ++ tmp[chars + 1] = (char)(0x80 | (value.value.u32 & 0x3F)); value.value.u32 >>= 6; ++ tmp[chars] = (char)(0xC0 | (value.value.u32 & 0x1F)); ++ chars += 2; ++ } ++ else { ++ /* surrogate pair not supported, convert to replacement char */ ++ if (value.value.u32 >= 0xD800 && value.value.u32 < 0xE000) ++ value.value.u32 = 0xFFFD; ++ ++ tmp[chars + 2] = (char)(0x80 | (value.value.u32 & 0x3F)); value.value.u32 >>= 6; ++ tmp[chars + 1] = (char)(0x80 | (value.value.u32 & 0x3F)); value.value.u32 >>= 6; ++ tmp[chars] = (char)(0xE0 | (value.value.u32 & 0x1F)); ++ chars += 3; ++ } ++ ++ if (chars >= sizeof(tmp) - 3 || !part->next || part->next->display_type != RC_FORMAT_UNICODECHAR) ++ break; ++ ++ part = part->next; ++ } while (1); ++ ++ tmp[chars] = '\0'; ++ break; ++ ++ case RC_FORMAT_UNKNOWN_MACRO: ++ chars = snprintf(tmp, sizeof(tmp), "[Unknown macro]%s", part->text); ++ text = tmp; ++ break; ++ ++ default: ++ rc_evaluate_operand(&value, &part->value, NULL); ++ chars = rc_format_typed_value(tmp, sizeof(tmp), &value, part->display_type); ++ text = tmp; ++ break; ++ } ++ ++ if (chars > 0 && buffersize > 0) { ++ if ((unsigned)chars >= buffersize) { ++ /* prevent write past end of buffer */ ++ memcpy(ptr, text, buffersize - 1); ++ ptr[buffersize - 1] = '\0'; ++ buffersize = 0; ++ } ++ else { ++ memcpy(ptr, text, chars); ++ ptr[chars] = '\0'; ++ buffersize -= (unsigned)chars; ++ } ++ } ++ ++ ptr += chars; ++ part = part->next; ++ } ++ ++ return (int)(ptr - buffer); ++} ++ ++int rc_get_richpresence_display_string(rc_richpresence_t* richpresence, char* buffer, size_t buffersize, rc_peek_t peek, void* peek_ud, void* unused_L) { ++ rc_richpresence_display_t* display; ++ ++ for (display = richpresence->first_display; display; display = display->next) { ++ /* if we've reached the end of the condition list, process it */ ++ if (!display->next) ++ return rc_evaluate_richpresence_display(display->display, buffer, buffersize); ++ ++ /* triggers with required hits will be updated in rc_update_richpresence */ ++ if (!display->has_required_hits) ++ rc_test_trigger(&display->trigger, peek, peek_ud, unused_L); ++ ++ /* if we've found a valid condition, process it */ ++ if (display->trigger.state == RC_TRIGGER_STATE_TRIGGERED) ++ return rc_evaluate_richpresence_display(display->display, buffer, buffersize); ++ } ++ ++ buffer[0] = '\0'; ++ return 0; ++} ++ ++int rc_evaluate_richpresence(rc_richpresence_t* richpresence, char* buffer, size_t buffersize, rc_peek_t peek, void* peek_ud, void* unused_L) { ++ rc_update_richpresence(richpresence, peek, peek_ud, unused_L); ++ return rc_get_richpresence_display_string(richpresence, buffer, buffersize, peek, peek_ud, unused_L); ++} ++ ++void rc_reset_richpresence_triggers(rc_richpresence_t* self) { ++ rc_richpresence_display_t* display; ++ ++ for (display = self->first_display; display; display = display->next) ++ rc_reset_trigger(&display->trigger); ++} ++ ++void rc_reset_richpresence(rc_richpresence_t* self) { ++ rc_reset_richpresence_triggers(self); ++ rc_reset_values(self->values); ++} +diff -rupbN melonDS.orig/src/rcheevos/src/rcheevos/runtime.c melonDS.ra/src/rcheevos/src/rcheevos/runtime.c +--- melonDS.orig/src/rcheevos/src/rcheevos/runtime.c 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rcheevos/runtime.c 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,852 @@ ++#include "rc_runtime.h" ++#include "rc_internal.h" ++ ++#include "../rc_compat.h" ++#include "../rhash/md5.h" ++ ++#include ++#include ++ ++#define RC_RICHPRESENCE_DISPLAY_BUFFER_SIZE 256 ++ ++/* ===== natvis extensions ===== */ ++ ++typedef struct __rc_runtime_trigger_list_t { rc_runtime_t runtime; } __rc_runtime_trigger_list_t; ++typedef struct __rc_runtime_lboard_list_t { rc_runtime_t runtime; } __rc_runtime_lboard_list_t; ++ ++static void rc_runtime_natvis_helper(const rc_runtime_event_t* runtime_event) ++{ ++ struct natvis_extensions { ++ __rc_runtime_trigger_list_t trigger_list; ++ __rc_runtime_lboard_list_t lboard_list; ++ } natvis; ++ ++ memset(&natvis, 0, sizeof(natvis)); ++ (void)runtime_event; ++ ++ natvis.lboard_list.runtime.lboard_count = 0; ++} ++ ++/* ============================= */ ++ ++rc_runtime_t* rc_runtime_alloc(void) { ++ rc_runtime_t* self; ++ ++ /* create a reference to rc_runtime_natvis_helper so the extensions get compiled in. */ ++ rc_runtime_event_handler_t unused = &rc_runtime_natvis_helper; ++ (void)unused; ++ ++ self = (rc_runtime_t*)malloc(sizeof(rc_runtime_t)); ++ ++ if (self) { ++ rc_runtime_init(self); ++ self->owns_self = 1; ++ } ++ ++ return self; ++} ++ ++void rc_runtime_init(rc_runtime_t* self) { ++ memset(self, 0, sizeof(rc_runtime_t)); ++ ++ self->memrefs = (rc_memrefs_t*)malloc(sizeof(*self->memrefs)); ++ rc_memrefs_init(self->memrefs); ++} ++ ++void rc_runtime_destroy(rc_runtime_t* self) { ++ uint32_t i; ++ ++ if (self->triggers) { ++ for (i = 0; i < self->trigger_count; ++i) { ++ if (self->triggers[i].buffer) ++ free(self->triggers[i].buffer); ++ } ++ ++ free(self->triggers); ++ self->triggers = NULL; ++ ++ self->trigger_count = self->trigger_capacity = 0; ++ } ++ ++ if (self->lboards) { ++ for (i = 0; i < self->lboard_count; ++i) { ++ if (self->lboards[i].buffer) ++ free(self->lboards[i].buffer); ++ } ++ ++ free(self->lboards); ++ self->lboards = NULL; ++ ++ self->lboard_count = self->lboard_capacity = 0; ++ } ++ ++ if (self->richpresence) { ++ if (self->richpresence->buffer) ++ free(self->richpresence->buffer); ++ free(self->richpresence); ++ } ++ ++ if (self->memrefs) ++ rc_memrefs_destroy(self->memrefs); ++ ++ if (self->owns_self) ++ free(self); ++} ++ ++void rc_runtime_checksum(const char* memaddr, uint8_t* md5) { ++ md5_state_t state; ++ md5_init(&state); ++ md5_append(&state, (unsigned char*)memaddr, (int)strlen(memaddr)); ++ md5_finish(&state, md5); ++} ++ ++static void rc_runtime_deactivate_trigger_by_index(rc_runtime_t* self, uint32_t index) { ++ /* free the trigger, then replace it with the last trigger */ ++ free(self->triggers[index].buffer); ++ ++ if (--self->trigger_count > index) ++ memcpy(&self->triggers[index], &self->triggers[self->trigger_count], sizeof(rc_runtime_trigger_t)); ++} ++ ++void rc_runtime_deactivate_achievement(rc_runtime_t* self, uint32_t id) { ++ uint32_t i; ++ ++ for (i = 0; i < self->trigger_count; ++i) { ++ if (self->triggers[i].id == id && self->triggers[i].trigger != NULL) ++ rc_runtime_deactivate_trigger_by_index(self, i); ++ } ++} ++ ++int rc_runtime_activate_achievement(rc_runtime_t* self, uint32_t id, const char* memaddr, void* unused_L, int unused_funcs_idx) { ++ void* trigger_buffer; ++ rc_trigger_t* trigger; ++ rc_runtime_trigger_t* runtime_trigger; ++ rc_preparse_state_t preparse; ++ const char* preparse_memaddr = memaddr; ++ uint8_t md5[16]; ++ int32_t size; ++ uint32_t i; ++ ++ (void)unused_L; ++ (void)unused_funcs_idx; ++ ++ if (memaddr == NULL) ++ return RC_INVALID_MEMORY_OPERAND; ++ ++ rc_runtime_checksum(memaddr, md5); ++ ++ /* check to see if the id is already registered with an active trigger */ ++ for (i = 0; i < self->trigger_count; ++i) { ++ if (self->triggers[i].id == id && self->triggers[i].trigger != NULL) { ++ if (memcmp(self->triggers[i].md5, md5, 16) == 0) { ++ /* if the checksum hasn't changed, we can reuse the existing item */ ++ rc_reset_trigger(self->triggers[i].trigger); ++ return RC_OK; ++ } ++ ++ /* checksum has changed, deactivate the the item */ ++ rc_runtime_deactivate_trigger_by_index(self, i); ++ ++ /* deactivate may reorder the list so we should continue from the current index. however, we ++ * assume that only one trigger is active per id, so having found that, just stop scanning. ++ */ ++ break; ++ } ++ } ++ ++ /* check to see if a disabled trigger for the specific id matches the trigger being registered */ ++ for (i = 0; i < self->trigger_count; ++i) { ++ if (self->triggers[i].id == id && memcmp(self->triggers[i].md5, md5, 16) == 0) { ++ /* retrieve the trigger pointer from the buffer */ ++ size = 0; ++ trigger = (rc_trigger_t*)rc_alloc(self->triggers[i].buffer, &size, sizeof(rc_trigger_t), RC_ALIGNOF(rc_trigger_t), NULL, -1); ++ self->triggers[i].trigger = trigger; ++ ++ rc_reset_trigger(trigger); ++ return RC_OK; ++ } ++ } ++ ++ /* item has not been previously registered, determine how much space we need for it, and allocate it */ ++ rc_init_preparse_state(&preparse); ++ preparse.parse.existing_memrefs = self->memrefs; ++ trigger = RC_ALLOC(rc_trigger_t, &preparse.parse); ++ rc_parse_trigger_internal(trigger, &preparse_memaddr, &preparse.parse); ++ ++ size = preparse.parse.offset; ++ if (size < 0) ++ return size; ++ ++ trigger_buffer = malloc(size); ++ if (!trigger_buffer) ++ return RC_OUT_OF_MEMORY; ++ ++ /* populate the item, using the communal memrefs pool */ ++ rc_reset_parse_state(&preparse.parse, trigger_buffer); ++ rc_preparse_reserve_memrefs(&preparse, self->memrefs); ++ trigger = RC_ALLOC(rc_trigger_t, &preparse.parse); ++ rc_parse_trigger_internal(trigger, &memaddr, &preparse.parse); ++ rc_destroy_preparse_state(&preparse); ++ ++ if (preparse.parse.offset < 0) { ++ free(trigger_buffer); ++ return preparse.parse.offset; ++ } ++ ++ /* grow the trigger buffer if necessary */ ++ if (self->trigger_count == self->trigger_capacity) { ++ self->trigger_capacity += 32; ++ if (!self->triggers) ++ self->triggers = (rc_runtime_trigger_t*)malloc(self->trigger_capacity * sizeof(rc_runtime_trigger_t)); ++ else ++ self->triggers = (rc_runtime_trigger_t*)realloc(self->triggers, self->trigger_capacity * sizeof(rc_runtime_trigger_t)); ++ ++ if (!self->triggers) { ++ free(trigger_buffer); ++ return RC_OUT_OF_MEMORY; ++ } ++ } ++ ++ /* assign the new trigger */ ++ runtime_trigger = &self->triggers[self->trigger_count]; ++ runtime_trigger->id = id; ++ runtime_trigger->trigger = trigger; ++ runtime_trigger->buffer = trigger_buffer; ++ runtime_trigger->invalid_memref = NULL; ++ memcpy(runtime_trigger->md5, md5, 16); ++ runtime_trigger->serialized_size = 0; ++ ++self->trigger_count; ++ ++ /* reset it, and return it */ ++ rc_reset_trigger(trigger); ++ return RC_OK; ++} ++ ++rc_trigger_t* rc_runtime_get_achievement(const rc_runtime_t* self, uint32_t id) ++{ ++ uint32_t i; ++ ++ for (i = 0; i < self->trigger_count; ++i) { ++ if (self->triggers[i].id == id && self->triggers[i].trigger != NULL) ++ return self->triggers[i].trigger; ++ } ++ ++ return NULL; ++} ++ ++int rc_runtime_get_achievement_measured(const rc_runtime_t* runtime, uint32_t id, unsigned* measured_value, unsigned* measured_target) ++{ ++ const rc_trigger_t* trigger = rc_runtime_get_achievement(runtime, id); ++ if (!measured_value || !measured_target) ++ return 0; ++ ++ if (!trigger) { ++ *measured_value = *measured_target = 0; ++ return 0; ++ } ++ ++ if (rc_trigger_state_active(trigger->state)) { ++ *measured_value = (trigger->measured_value == RC_MEASURED_UNKNOWN) ? 0 : trigger->measured_value; ++ *measured_target = trigger->measured_target; ++ } ++ else { ++ /* don't report measured information for inactive triggers */ ++ *measured_value = *measured_target = 0; ++ } ++ ++ return 1; ++} ++ ++int rc_runtime_format_achievement_measured(const rc_runtime_t* runtime, uint32_t id, char* buffer, size_t buffer_size) ++{ ++ const rc_trigger_t* trigger = rc_runtime_get_achievement(runtime, id); ++ uint32_t value; ++ if (!buffer || !buffer_size) ++ return 0; ++ ++ if (!trigger || /* no trigger */ ++ trigger->measured_target == 0 || /* not measured */ ++ !rc_trigger_state_active(trigger->state)) { /* don't report measured value for inactive triggers */ ++ *buffer = '\0'; ++ return 0; ++ } ++ ++ /* cap the value at the target so we can count past the target: "107 >= 100" */ ++ value = (trigger->measured_value == RC_MEASURED_UNKNOWN) ? 0 : trigger->measured_value; ++ if (value > trigger->measured_target) ++ value = trigger->measured_target; ++ ++ if (trigger->measured_as_percent) { ++ const uint32_t percent = (uint32_t)(((unsigned long long)value * 100) / trigger->measured_target); ++ return snprintf(buffer, buffer_size, "%u%%", percent); ++ } ++ ++ return snprintf(buffer, buffer_size, "%u/%u", value, trigger->measured_target); ++} ++ ++static void rc_runtime_deactivate_lboard_by_index(rc_runtime_t* self, uint32_t index) { ++ /* free the lboard, then replace it with the last lboard */ ++ free(self->lboards[index].buffer); ++ ++ if (--self->lboard_count > index) ++ memcpy(&self->lboards[index], &self->lboards[self->lboard_count], sizeof(rc_runtime_lboard_t)); ++} ++ ++void rc_runtime_deactivate_lboard(rc_runtime_t* self, uint32_t id) { ++ uint32_t i; ++ ++ for (i = 0; i < self->lboard_count; ++i) { ++ if (self->lboards[i].id == id && self->lboards[i].lboard != NULL) ++ rc_runtime_deactivate_lboard_by_index(self, i); ++ } ++} ++ ++int rc_runtime_activate_lboard(rc_runtime_t* self, uint32_t id, const char* memaddr, void* unused_L, int unused_funcs_idx) { ++ void* lboard_buffer; ++ uint8_t md5[16]; ++ rc_lboard_t* lboard; ++ rc_preparse_state_t preparse; ++ rc_runtime_lboard_t* runtime_lboard; ++ int32_t size; ++ uint32_t i; ++ ++ (void)unused_L; ++ (void)unused_funcs_idx; ++ ++ if (memaddr == 0) ++ return RC_INVALID_MEMORY_OPERAND; ++ ++ rc_runtime_checksum(memaddr, md5); ++ ++ /* check to see if the id is already registered with an active lboard */ ++ for (i = 0; i < self->lboard_count; ++i) { ++ if (self->lboards[i].id == id && self->lboards[i].lboard != NULL) { ++ if (memcmp(self->lboards[i].md5, md5, 16) == 0) { ++ /* if the checksum hasn't changed, we can reuse the existing item */ ++ rc_reset_lboard(self->lboards[i].lboard); ++ return RC_OK; ++ } ++ ++ /* checksum has changed, deactivate the the item */ ++ rc_runtime_deactivate_lboard_by_index(self, i); ++ ++ /* deactivate may reorder the list so we should continue from the current index. however, we ++ * assume that only one trigger is active per id, so having found that, just stop scanning. ++ */ ++ break; ++ } ++ } ++ ++ /* check to see if a disabled lboard for the specific id matches the lboard being registered */ ++ for (i = 0; i < self->lboard_count; ++i) { ++ if (self->lboards[i].id == id && memcmp(self->lboards[i].md5, md5, 16) == 0) { ++ /* retrieve the lboard pointer from the buffer */ ++ size = 0; ++ lboard = (rc_lboard_t*)rc_alloc(self->lboards[i].buffer, &size, sizeof(rc_lboard_t), RC_ALIGNOF(rc_lboard_t), NULL, -1); ++ self->lboards[i].lboard = lboard; ++ ++ rc_reset_lboard(lboard); ++ return RC_OK; ++ } ++ } ++ ++ /* item has not been previously registered, determine how much space we need for it, and allocate it */ ++ rc_init_preparse_state(&preparse); ++ preparse.parse.existing_memrefs = self->memrefs; ++ lboard = RC_ALLOC(rc_lboard_t, &preparse.parse); ++ rc_parse_lboard_internal(lboard, memaddr, &preparse.parse); ++ ++ size = preparse.parse.offset; ++ if (size < 0) ++ return size; ++ ++ lboard_buffer = malloc(size); ++ if (!lboard_buffer) ++ return RC_OUT_OF_MEMORY; ++ ++ /* populate the item, using the communal memrefs pool */ ++ rc_reset_parse_state(&preparse.parse, lboard_buffer); ++ rc_preparse_reserve_memrefs(&preparse, self->memrefs); ++ lboard = RC_ALLOC(rc_lboard_t, &preparse.parse); ++ rc_parse_lboard_internal(lboard, memaddr, &preparse.parse); ++ rc_destroy_preparse_state(&preparse); ++ ++ if (preparse.parse.offset < 0) { ++ free(lboard_buffer); ++ return preparse.parse.offset; ++ } ++ ++ /* grow the lboard buffer if necessary */ ++ if (self->lboard_count == self->lboard_capacity) { ++ self->lboard_capacity += 16; ++ if (!self->lboards) ++ self->lboards = (rc_runtime_lboard_t*)malloc(self->lboard_capacity * sizeof(rc_runtime_lboard_t)); ++ else ++ self->lboards = (rc_runtime_lboard_t*)realloc(self->lboards, self->lboard_capacity * sizeof(rc_runtime_lboard_t)); ++ ++ if (!self->lboards) { ++ free(lboard_buffer); ++ return RC_OUT_OF_MEMORY; ++ } ++ } ++ ++ /* assign the new lboard */ ++ runtime_lboard = &self->lboards[self->lboard_count++]; ++ runtime_lboard->id = id; ++ runtime_lboard->value = 0; ++ runtime_lboard->lboard = lboard; ++ runtime_lboard->buffer = lboard_buffer; ++ runtime_lboard->invalid_memref = NULL; ++ memcpy(runtime_lboard->md5, md5, 16); ++ runtime_lboard->serialized_size = 0; ++ ++ /* reset it, and return it */ ++ rc_reset_lboard(lboard); ++ return RC_OK; ++} ++ ++rc_lboard_t* rc_runtime_get_lboard(const rc_runtime_t* self, uint32_t id) ++{ ++ uint32_t i; ++ ++ for (i = 0; i < self->lboard_count; ++i) { ++ if (self->lboards[i].id == id && self->lboards[i].lboard != NULL) ++ return self->lboards[i].lboard; ++ } ++ ++ return NULL; ++} ++ ++int rc_runtime_format_lboard_value(char* buffer, int size, int32_t value, int format) ++{ ++ return rc_format_value(buffer, size, value, format); ++} ++ ++int rc_runtime_activate_richpresence(rc_runtime_t* self, const char* script, void* unused_L, int unused_funcs_idx) { ++ rc_richpresence_t* richpresence; ++ rc_preparse_state_t preparse; ++ uint8_t md5[16]; ++ int size; ++ ++ (void)unused_L; ++ (void)unused_funcs_idx; ++ ++ if (script == NULL) ++ return RC_MISSING_DISPLAY_STRING; ++ ++ rc_runtime_checksum(script, md5); ++ ++ /* look for existing match */ ++ if (self->richpresence && self->richpresence->richpresence && memcmp(self->richpresence->md5, md5, 16) == 0) { ++ /* unchanged. reset all of the conditions */ ++ rc_reset_richpresence(self->richpresence->richpresence); ++ ++ /* return success*/ ++ return RC_OK; ++ } ++ ++ /* no existing match found, parse script */ ++ rc_init_preparse_state(&preparse); ++ preparse.parse.existing_memrefs = self->memrefs; ++ richpresence = RC_ALLOC(rc_richpresence_t, &preparse.parse); ++ preparse.parse.variables = &richpresence->values; ++ rc_parse_richpresence_internal(richpresence, script, &preparse.parse); ++ ++ size = preparse.parse.offset; ++ if (size < 0) ++ return size; ++ ++ /* if there's a previous script, free it */ ++ if (self->richpresence) { ++ free(self->richpresence->buffer); ++ free(self->richpresence); ++ } ++ ++ /* allocate and process the new script */ ++ self->richpresence = (rc_runtime_richpresence_t*)malloc(sizeof(rc_runtime_richpresence_t)); ++ if (!self->richpresence) ++ return RC_OUT_OF_MEMORY; ++ ++ memcpy(self->richpresence->md5, md5, sizeof(md5)); ++ ++ self->richpresence->buffer = malloc(size); ++ if (!self->richpresence->buffer) ++ return RC_OUT_OF_MEMORY; ++ ++ rc_reset_parse_state(&preparse.parse, self->richpresence->buffer); ++ rc_preparse_reserve_memrefs(&preparse, self->memrefs); ++ richpresence = RC_ALLOC(rc_richpresence_t, &preparse.parse); ++ preparse.parse.variables = &richpresence->values; ++ rc_parse_richpresence_internal(richpresence, script, &preparse.parse); ++ rc_destroy_preparse_state(&preparse); ++ ++ if (preparse.parse.offset < 0) { ++ free(self->richpresence->buffer); ++ free(self->richpresence); ++ self->richpresence = NULL; ++ return preparse.parse.offset; ++ } ++ ++ if (!richpresence->first_display || !richpresence->first_display->display) { ++ /* non-existant rich presence */ ++ self->richpresence->richpresence = NULL; ++ } ++ else { ++ /* reset all of the conditions */ ++ rc_reset_richpresence(richpresence); ++ self->richpresence->richpresence = richpresence; ++ } ++ ++ return RC_OK; ++} ++ ++int rc_runtime_get_richpresence(const rc_runtime_t* self, char* buffer, size_t buffersize, rc_runtime_peek_t peek, void* peek_ud, void* unused_L) { ++ if (self->richpresence && self->richpresence->richpresence) ++ return rc_get_richpresence_display_string(self->richpresence->richpresence, buffer, buffersize, peek, peek_ud, unused_L); ++ ++ *buffer = '\0'; ++ return 0; ++} ++ ++void rc_runtime_do_frame(rc_runtime_t* self, rc_runtime_event_handler_t event_handler, rc_runtime_peek_t peek, void* ud, void* unused_L) { ++ rc_runtime_event_t runtime_event; ++ int i; ++ ++ runtime_event.value = 0; ++ ++ rc_update_memref_values(self->memrefs, peek, ud); ++ ++ for (i = self->trigger_count - 1; i >= 0; --i) { ++ rc_trigger_t* trigger = self->triggers[i].trigger; ++ int old_state, new_state; ++ uint32_t old_measured_value; ++ ++ if (!trigger) ++ continue; ++ ++ if (self->triggers[i].invalid_memref) { ++ runtime_event.type = RC_RUNTIME_EVENT_ACHIEVEMENT_DISABLED; ++ runtime_event.id = self->triggers[i].id; ++ runtime_event.value = self->triggers[i].invalid_memref->address; ++ ++ trigger->state = RC_TRIGGER_STATE_DISABLED; ++ self->triggers[i].invalid_memref = NULL; ++ ++ event_handler(&runtime_event); ++ ++ runtime_event.value = 0; /* achievement loop expects this to stay at 0 */ ++ continue; ++ } ++ ++ old_measured_value = trigger->measured_value; ++ old_state = trigger->state; ++ new_state = rc_evaluate_trigger(trigger, peek, ud, unused_L); ++ ++ /* trigger->state doesn't actually change to RESET, RESET just serves as a notification. ++ * handle the notification, then look at the actual state */ ++ if (new_state == RC_TRIGGER_STATE_RESET) { ++ runtime_event.type = RC_RUNTIME_EVENT_ACHIEVEMENT_RESET; ++ runtime_event.id = self->triggers[i].id; ++ event_handler(&runtime_event); ++ ++ new_state = trigger->state; ++ } ++ ++ /* if the measured value changed and the achievement hasn't triggered, send a notification */ ++ if (trigger->measured_value != old_measured_value && old_measured_value != RC_MEASURED_UNKNOWN && ++ trigger->measured_target != 0 && trigger->measured_value <= trigger->measured_target && ++ new_state != RC_TRIGGER_STATE_TRIGGERED && ++ new_state != RC_TRIGGER_STATE_INACTIVE && new_state != RC_TRIGGER_STATE_WAITING) { ++ ++ runtime_event.type = RC_RUNTIME_EVENT_ACHIEVEMENT_PROGRESS_UPDATED; ++ runtime_event.id = self->triggers[i].id; ++ ++ if (trigger->measured_as_percent) { ++ /* if reporting measured value as a percentage, only send the notification if the percentage changes */ ++ const int32_t old_percent = (int32_t)(((unsigned long long)old_measured_value * 100) / trigger->measured_target); ++ const int32_t new_percent = (int32_t)(((unsigned long long)trigger->measured_value * 100) / trigger->measured_target); ++ if (old_percent != new_percent) { ++ runtime_event.value = new_percent; ++ event_handler(&runtime_event); ++ } ++ } ++ else { ++ runtime_event.value = trigger->measured_value; ++ event_handler(&runtime_event); ++ } ++ ++ runtime_event.value = 0; /* achievement loop expects this to stay at 0 */ ++ } ++ ++ /* if the state hasn't changed, there won't be any events raised */ ++ if (new_state == old_state) ++ continue; ++ ++ /* raise an UNPRIMED event when changing from PRIMED to anything else */ ++ if (old_state == RC_TRIGGER_STATE_PRIMED) { ++ runtime_event.type = RC_RUNTIME_EVENT_ACHIEVEMENT_UNPRIMED; ++ runtime_event.id = self->triggers[i].id; ++ event_handler(&runtime_event); ++ } ++ ++ /* raise events for each of the possible new states */ ++ switch (new_state) ++ { ++ case RC_TRIGGER_STATE_TRIGGERED: ++ runtime_event.type = RC_RUNTIME_EVENT_ACHIEVEMENT_TRIGGERED; ++ runtime_event.id = self->triggers[i].id; ++ event_handler(&runtime_event); ++ break; ++ ++ case RC_TRIGGER_STATE_PAUSED: ++ runtime_event.type = RC_RUNTIME_EVENT_ACHIEVEMENT_PAUSED; ++ runtime_event.id = self->triggers[i].id; ++ event_handler(&runtime_event); ++ break; ++ ++ case RC_TRIGGER_STATE_PRIMED: ++ runtime_event.type = RC_RUNTIME_EVENT_ACHIEVEMENT_PRIMED; ++ runtime_event.id = self->triggers[i].id; ++ event_handler(&runtime_event); ++ break; ++ ++ case RC_TRIGGER_STATE_ACTIVE: ++ /* only raise ACTIVATED event when transitioning from an inactive state. ++ * note that inactive in this case means active but cannot trigger. */ ++ if (old_state == RC_TRIGGER_STATE_WAITING || old_state == RC_TRIGGER_STATE_PAUSED) { ++ runtime_event.type = RC_RUNTIME_EVENT_ACHIEVEMENT_ACTIVATED; ++ runtime_event.id = self->triggers[i].id; ++ event_handler(&runtime_event); ++ } ++ break; ++ } ++ } ++ ++ for (i = self->lboard_count - 1; i >= 0; --i) { ++ rc_lboard_t* lboard = self->lboards[i].lboard; ++ int lboard_state; ++ ++ if (!lboard) ++ continue; ++ ++ if (self->lboards[i].invalid_memref) { ++ runtime_event.type = RC_RUNTIME_EVENT_LBOARD_DISABLED; ++ runtime_event.id = self->lboards[i].id; ++ runtime_event.value = self->lboards[i].invalid_memref->address; ++ ++ lboard->state = RC_LBOARD_STATE_DISABLED; ++ self->lboards[i].invalid_memref = NULL; ++ ++ event_handler(&runtime_event); ++ continue; ++ } ++ ++ lboard_state = lboard->state; ++ switch (rc_evaluate_lboard(lboard, &runtime_event.value, peek, ud, unused_L)) ++ { ++ case RC_LBOARD_STATE_STARTED: /* leaderboard is running */ ++ if (lboard_state != RC_LBOARD_STATE_STARTED) { ++ self->lboards[i].value = runtime_event.value; ++ ++ runtime_event.type = RC_RUNTIME_EVENT_LBOARD_STARTED; ++ runtime_event.id = self->lboards[i].id; ++ event_handler(&runtime_event); ++ } ++ else if (runtime_event.value != self->lboards[i].value) { ++ self->lboards[i].value = runtime_event.value; ++ ++ runtime_event.type = RC_RUNTIME_EVENT_LBOARD_UPDATED; ++ runtime_event.id = self->lboards[i].id; ++ event_handler(&runtime_event); ++ } ++ break; ++ ++ case RC_LBOARD_STATE_CANCELED: ++ if (lboard_state != RC_LBOARD_STATE_CANCELED) { ++ runtime_event.type = RC_RUNTIME_EVENT_LBOARD_CANCELED; ++ runtime_event.id = self->lboards[i].id; ++ event_handler(&runtime_event); ++ } ++ break; ++ ++ case RC_LBOARD_STATE_TRIGGERED: ++ if (lboard_state != RC_RUNTIME_EVENT_LBOARD_TRIGGERED) { ++ runtime_event.type = RC_RUNTIME_EVENT_LBOARD_TRIGGERED; ++ runtime_event.id = self->lboards[i].id; ++ event_handler(&runtime_event); ++ } ++ break; ++ } ++ } ++ ++ if (self->richpresence && self->richpresence->richpresence) ++ rc_update_richpresence(self->richpresence->richpresence, peek, ud, unused_L); ++} ++ ++void rc_runtime_reset(rc_runtime_t* self) { ++ uint32_t i; ++ ++ for (i = 0; i < self->trigger_count; ++i) { ++ if (self->triggers[i].trigger) ++ rc_reset_trigger(self->triggers[i].trigger); ++ } ++ ++ for (i = 0; i < self->lboard_count; ++i) { ++ if (self->lboards[i].lboard) ++ rc_reset_lboard(self->lboards[i].lboard); ++ } ++ ++ if (self->richpresence && self->richpresence->richpresence) ++ rc_reset_richpresence(self->richpresence->richpresence); ++} ++ ++static int rc_condset_contains_memref(const rc_condset_t* condset, const rc_memref_t* memref) { ++ rc_condition_t* cond; ++ if (!condset) ++ return 0; ++ ++ for (cond = condset->conditions; cond; cond = cond->next) { ++ if (rc_operand_is_memref(&cond->operand1) && cond->operand1.value.memref == memref) ++ return 1; ++ if (rc_operand_is_memref(&cond->operand2) && cond->operand2.value.memref == memref) ++ return 1; ++ } ++ ++ return 0; ++} ++ ++int rc_value_contains_memref(const rc_value_t* value, const rc_memref_t* memref) { ++ rc_condset_t* condset; ++ if (!value) ++ return 0; ++ ++ for (condset = value->conditions; condset; condset = condset->next) { ++ if (rc_condset_contains_memref(condset, memref)) ++ return 1; ++ } ++ ++ return 0; ++} ++ ++int rc_trigger_contains_memref(const rc_trigger_t* trigger, const rc_memref_t* memref) { ++ rc_condset_t* condset; ++ if (!trigger) ++ return 0; ++ ++ if (rc_condset_contains_memref(trigger->requirement, memref)) ++ return 1; ++ ++ for (condset = trigger->alternative; condset; condset = condset->next) { ++ if (rc_condset_contains_memref(condset, memref)) ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static void rc_runtime_invalidate_memref(rc_runtime_t* self, rc_memref_t* memref) { ++ uint32_t i; ++ ++ /* disable any achievements dependent on the address */ ++ for (i = 0; i < self->trigger_count; ++i) { ++ if (!self->triggers[i].invalid_memref && rc_trigger_contains_memref(self->triggers[i].trigger, memref)) ++ self->triggers[i].invalid_memref = memref; ++ } ++ ++ /* disable any leaderboards dependent on the address */ ++ for (i = 0; i < self->lboard_count; ++i) { ++ if (!self->lboards[i].invalid_memref) { ++ rc_lboard_t* lboard = self->lboards[i].lboard; ++ if (lboard) { ++ if (rc_trigger_contains_memref(&lboard->start, memref)) { ++ lboard->start.state = RC_TRIGGER_STATE_DISABLED; ++ self->lboards[i].invalid_memref = memref; ++ } ++ ++ if (rc_trigger_contains_memref(&lboard->cancel, memref)) { ++ lboard->cancel.state = RC_TRIGGER_STATE_DISABLED; ++ self->lboards[i].invalid_memref = memref; ++ } ++ ++ if (rc_trigger_contains_memref(&lboard->submit, memref)) { ++ lboard->submit.state = RC_TRIGGER_STATE_DISABLED; ++ self->lboards[i].invalid_memref = memref; ++ } ++ ++ if (rc_value_contains_memref(&lboard->value, memref)) ++ self->lboards[i].invalid_memref = memref; ++ } ++ } ++ } ++} ++ ++void rc_runtime_invalidate_address(rc_runtime_t* self, uint32_t address) { ++ rc_memref_list_t* memref_list = &self->memrefs->memrefs; ++ do { ++ rc_memref_t* memref = memref_list->items; ++ const rc_memref_t* memref_stop = memref + memref_list->count; ++ ++ for (; memref < memref_stop; ++memref) { ++ if (memref->address == address) { ++ memref->value.type = RC_VALUE_TYPE_NONE; ++ rc_runtime_invalidate_memref(self, memref); ++ } ++ } ++ ++ memref_list = memref_list->next; ++ } while (memref_list); ++} ++ ++void rc_runtime_validate_addresses(rc_runtime_t* self, rc_runtime_event_handler_t event_handler, ++ rc_runtime_validate_address_t validate_handler) { ++ int num_invalid = 0; ++ rc_memref_list_t* memref_list = &self->memrefs->memrefs; ++ do { ++ rc_memref_t* memref = memref_list->items; ++ const rc_memref_t* memref_stop = memref + memref_list->count; ++ ++ for (; memref < memref_stop; ++memref) { ++ if (!validate_handler(memref->address)) { ++ memref->value.type = RC_VALUE_TYPE_NONE; ++ rc_runtime_invalidate_memref(self, memref); ++ ++ ++num_invalid; ++ } ++ } ++ ++ memref_list = memref_list->next; ++ } while (memref_list); ++ ++ if (num_invalid) { ++ rc_runtime_event_t runtime_event; ++ int i; ++ ++ for (i = self->trigger_count - 1; i >= 0; --i) { ++ rc_trigger_t* trigger = self->triggers[i].trigger; ++ if (trigger && self->triggers[i].invalid_memref) { ++ runtime_event.type = RC_RUNTIME_EVENT_ACHIEVEMENT_DISABLED; ++ runtime_event.id = self->triggers[i].id; ++ runtime_event.value = self->triggers[i].invalid_memref->address; ++ ++ trigger->state = RC_TRIGGER_STATE_DISABLED; ++ self->triggers[i].invalid_memref = NULL; ++ ++ event_handler(&runtime_event); ++ } ++ } ++ ++ for (i = self->lboard_count - 1; i >= 0; --i) { ++ rc_lboard_t* lboard = self->lboards[i].lboard; ++ if (lboard && self->lboards[i].invalid_memref) { ++ runtime_event.type = RC_RUNTIME_EVENT_LBOARD_DISABLED; ++ runtime_event.id = self->lboards[i].id; ++ runtime_event.value = self->lboards[i].invalid_memref->address; ++ ++ lboard->state = RC_LBOARD_STATE_DISABLED; ++ self->lboards[i].invalid_memref = NULL; ++ ++ event_handler(&runtime_event); ++ } ++ } ++ } ++} +diff -rupbN melonDS.orig/src/rcheevos/src/rcheevos/runtime_progress.c melonDS.ra/src/rcheevos/src/rcheevos/runtime_progress.c +--- melonDS.orig/src/rcheevos/src/rcheevos/runtime_progress.c 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rcheevos/runtime_progress.c 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,1073 @@ ++#include "rc_runtime.h" ++#include "rc_internal.h" ++ ++#include "rc_util.h" ++#include "../rhash/md5.h" ++ ++#include ++#include ++#include ++ ++#define RC_RUNTIME_MARKER 0x0A504152 /* RAP\n */ ++ ++#define RC_RUNTIME_CHUNK_MEMREFS 0x4645524D /* MREF */ ++#define RC_RUNTIME_CHUNK_VARIABLES 0x53524156 /* VARS */ ++#define RC_RUNTIME_CHUNK_ACHIEVEMENT 0x56484341 /* ACHV */ ++#define RC_RUNTIME_CHUNK_LEADERBOARD 0x4452424C /* LBRD */ ++#define RC_RUNTIME_CHUNK_RICHPRESENCE 0x48434952 /* RICH */ ++ ++#define RC_RUNTIME_CHUNK_DONE 0x454E4F44 /* DONE */ ++ ++#define RC_RUNTIME_MIN_BUFFER_SIZE 4 + 8 + 16 /* RUNTIME_MARKER, CHUNK_DONE, MD5 */ ++ ++typedef struct rc_runtime_progress_t { ++ const rc_runtime_t* runtime; ++ ++ uint32_t offset; ++ uint8_t* buffer; ++ uint32_t buffer_size; ++ ++ uint32_t chunk_size_offset; ++} rc_runtime_progress_t; ++ ++#define assert_chunk_size(expected_size) assert((uint32_t)(progress->offset - progress->chunk_size_offset - 4) == (uint32_t)(expected_size)) ++ ++#define RC_TRIGGER_STATE_UNUPDATED 0x7F ++ ++#define RC_MEMREF_FLAG_CHANGED_THIS_FRAME 0x00010000 ++ ++#define RC_VAR_FLAG_HAS_COND_DATA 0x01000000 ++ ++#define RC_COND_FLAG_IS_TRUE_MASK 0x00000003 ++#define RC_COND_FLAG_OPERAND1_IS_INDIRECT_MEMREF 0x00010000 ++#define RC_COND_FLAG_OPERAND1_MEMREF_CHANGED_THIS_FRAME 0x00020000 ++#define RC_COND_FLAG_OPERAND2_IS_INDIRECT_MEMREF 0x00100000 ++#define RC_COND_FLAG_OPERAND2_MEMREF_CHANGED_THIS_FRAME 0x00200000 ++ ++static void rc_runtime_progress_write_uint(rc_runtime_progress_t* progress, uint32_t value) ++{ ++ if (progress->buffer) { ++ progress->buffer[progress->offset + 0] = value & 0xFF; value >>= 8; ++ progress->buffer[progress->offset + 1] = value & 0xFF; value >>= 8; ++ progress->buffer[progress->offset + 2] = value & 0xFF; value >>= 8; ++ progress->buffer[progress->offset + 3] = value & 0xFF; ++ } ++ ++ progress->offset += 4; ++} ++ ++static uint32_t rc_runtime_progress_read_uint(rc_runtime_progress_t* progress) ++{ ++ uint32_t value = progress->buffer[progress->offset + 0] | ++ (progress->buffer[progress->offset + 1] << 8) | ++ (progress->buffer[progress->offset + 2] << 16) | ++ (progress->buffer[progress->offset + 3] << 24); ++ ++ progress->offset += 4; ++ return value; ++} ++ ++static void rc_runtime_progress_write_md5(rc_runtime_progress_t* progress, uint8_t* md5) ++{ ++ if (progress->buffer) ++ memcpy(&progress->buffer[progress->offset], md5, 16); ++ ++ progress->offset += 16; ++} ++ ++static int rc_runtime_progress_match_md5(rc_runtime_progress_t* progress, uint8_t* md5) ++{ ++ int result = 0; ++ if (progress->buffer) ++ result = (memcmp(&progress->buffer[progress->offset], md5, 16) == 0); ++ ++ progress->offset += 16; ++ ++ return result; ++} ++ ++static void rc_runtime_progress_start_chunk(rc_runtime_progress_t* progress, uint32_t chunk_id) ++{ ++ rc_runtime_progress_write_uint(progress, chunk_id); ++ ++ progress->chunk_size_offset = progress->offset; ++ ++ progress->offset += 4; ++} ++ ++static void rc_runtime_progress_end_chunk(rc_runtime_progress_t* progress) ++{ ++ uint32_t length; ++ uint32_t offset; ++ ++ progress->offset = (progress->offset + 3) & ~0x03; /* align to 4 byte boundary */ ++ ++ if (progress->buffer) { ++ /* ignore chunk size field when calculating chunk size */ ++ length = (uint32_t)(progress->offset - progress->chunk_size_offset - 4); ++ ++ /* temporarily update the write pointer to write the chunk size field */ ++ offset = progress->offset; ++ progress->offset = progress->chunk_size_offset; ++ rc_runtime_progress_write_uint(progress, length); ++ progress->offset = offset; ++ } ++} ++ ++static void rc_runtime_progress_init(rc_runtime_progress_t* progress, const rc_runtime_t* runtime) ++{ ++ memset(progress, 0, sizeof(rc_runtime_progress_t)); ++ progress->runtime = runtime; ++} ++ ++#define RC_RUNTIME_SERIALIZED_MEMREF_SIZE 16 /* 4x uint: address, flags, value, prior */ ++ ++static int rc_runtime_progress_write_memrefs(rc_runtime_progress_t* progress) ++{ ++ uint32_t count = rc_memrefs_count_memrefs(progress->runtime->memrefs); ++ if (count == 0) ++ return RC_OK; ++ ++ if (progress->offset + 8 + count * RC_RUNTIME_SERIALIZED_MEMREF_SIZE > progress->buffer_size) ++ return RC_INSUFFICIENT_BUFFER; ++ ++ rc_runtime_progress_start_chunk(progress, RC_RUNTIME_CHUNK_MEMREFS); ++ ++ if (!progress->buffer) { ++ progress->offset += count * RC_RUNTIME_SERIALIZED_MEMREF_SIZE; ++ } ++ else { ++ uint32_t flags = 0; ++ const rc_memref_list_t* memref_list = &progress->runtime->memrefs->memrefs; ++ const rc_memref_t* memref; ++ ++ for (; memref_list; memref_list = memref_list->next) { ++ const rc_memref_t* memref_end; ++ ++ memref = memref_list->items; ++ memref_end = memref + memref_list->count; ++ for (; memref < memref_end; ++memref) { ++ flags = memref->value.size; ++ if (memref->value.changed) ++ flags |= RC_MEMREF_FLAG_CHANGED_THIS_FRAME; ++ ++ rc_runtime_progress_write_uint(progress, memref->address); ++ rc_runtime_progress_write_uint(progress, flags); ++ rc_runtime_progress_write_uint(progress, memref->value.value); ++ rc_runtime_progress_write_uint(progress, memref->value.prior); ++ } ++ } ++ } ++ ++ assert_chunk_size(count * RC_RUNTIME_SERIALIZED_MEMREF_SIZE); ++ rc_runtime_progress_end_chunk(progress); ++ return RC_OK; ++} ++ ++static void rc_runtime_progress_update_modified_memrefs(rc_runtime_progress_t* progress) ++{ ++ rc_typed_value_t value, prior_value, modifier, prior_modifier; ++ rc_modified_memref_list_t* modified_memref_list; ++ rc_modified_memref_t* modified_memref; ++ rc_operand_t prior_parent_operand, prior_modifier_operand; ++ rc_memref_t prior_parent_memref, prior_modifier_memref; ++ ++ modified_memref_list = &progress->runtime->memrefs->modified_memrefs; ++ for (; modified_memref_list; modified_memref_list = modified_memref_list->next) { ++ const rc_modified_memref_t* modified_memref_end; ++ modified_memref = modified_memref_list->items; ++ modified_memref_end = modified_memref + modified_memref_list->count; ++ for (; modified_memref < modified_memref_end; ++modified_memref) { ++ modified_memref->memref.value.changed = 0; ++ ++ /* indirect memref values are stored in conditions */ ++ if (modified_memref->modifier_type == RC_OPERATOR_INDIRECT_READ) ++ continue; ++ ++ /* non-indirect memref values can be reconstructed from the parents */ ++ memcpy(&prior_parent_operand, &modified_memref->parent, sizeof(prior_parent_operand)); ++ if (rc_operand_is_memref(&prior_parent_operand)) { ++ memcpy(&prior_parent_memref, modified_memref->parent.value.memref, sizeof(prior_parent_memref)); ++ prior_parent_memref.value.value = prior_parent_memref.value.prior; ++ modified_memref->memref.value.changed |= prior_parent_memref.value.changed; ++ prior_parent_operand.value.memref = &prior_parent_memref; ++ } ++ ++ memcpy(&prior_modifier_operand, &modified_memref->modifier, sizeof(prior_modifier_operand)); ++ if (rc_operand_is_memref(&prior_modifier_operand)) { ++ memcpy(&prior_modifier_memref, modified_memref->modifier.value.memref, sizeof(prior_modifier_memref)); ++ prior_modifier_memref.value.value = prior_modifier_memref.value.prior; ++ modified_memref->memref.value.changed |= prior_modifier_memref.value.changed; ++ prior_modifier_operand.value.memref = &prior_modifier_memref; ++ } ++ ++ rc_evaluate_operand(&value, &modified_memref->parent, NULL); ++ rc_evaluate_operand(&modifier, &modified_memref->modifier, NULL); ++ rc_evaluate_operand(&prior_value, &prior_parent_operand, NULL); ++ rc_evaluate_operand(&prior_modifier, &prior_modifier_operand, NULL); ++ ++ if (modified_memref->modifier_type == RC_OPERATOR_SUB_PARENT) { ++ rc_typed_value_negate(&value); ++ rc_typed_value_add(&value, &modifier); ++ ++ rc_typed_value_negate(&prior_value); ++ rc_typed_value_add(&prior_value, &prior_modifier); ++ } ++ else { ++ rc_typed_value_combine(&value, &modifier, modified_memref->modifier_type); ++ rc_typed_value_combine(&prior_value, &prior_modifier, modified_memref->modifier_type); ++ } ++ ++ rc_typed_value_convert(&value, modified_memref->memref.value.type); ++ modified_memref->memref.value.value = value.value.u32; ++ ++ rc_typed_value_convert(&prior_value, modified_memref->memref.value.type); ++ modified_memref->memref.value.prior = prior_value.value.u32; ++ } ++ } ++} ++ ++static int rc_runtime_progress_read_memrefs(rc_runtime_progress_t* progress) ++{ ++ uint32_t entries; ++ uint32_t address, flags, value, prior; ++ uint8_t size; ++ rc_memref_list_t* unmatched_memref_list = &progress->runtime->memrefs->memrefs; ++ rc_memref_t* first_unmatched_memref = unmatched_memref_list->items; ++ rc_memref_t* memref; ++ ++ /* re-read the chunk size to determine how many memrefs are present */ ++ progress->offset -= 4; ++ entries = rc_runtime_progress_read_uint(progress) / RC_RUNTIME_SERIALIZED_MEMREF_SIZE; ++ ++ while (entries != 0) { ++ address = rc_runtime_progress_read_uint(progress); ++ flags = rc_runtime_progress_read_uint(progress); ++ value = rc_runtime_progress_read_uint(progress); ++ prior = rc_runtime_progress_read_uint(progress); ++ ++ size = flags & 0xFF; ++ ++ memref = first_unmatched_memref; ++ if (memref->address == address && memref->value.size == size) { ++ memref->value.value = value; ++ memref->value.changed = (flags & RC_MEMREF_FLAG_CHANGED_THIS_FRAME) ? 1 : 0; ++ memref->value.prior = prior; ++ ++ first_unmatched_memref++; ++ if (first_unmatched_memref >= unmatched_memref_list->items + unmatched_memref_list->count) { ++ unmatched_memref_list = unmatched_memref_list->next; ++ if (!unmatched_memref_list) ++ break; ++ first_unmatched_memref = unmatched_memref_list->items; ++ } ++ } ++ else { ++ rc_memref_list_t* memref_list = unmatched_memref_list; ++ do { ++ ++memref; ++ if (memref >= memref_list->items + memref_list->count) { ++ memref_list = memref_list->next; ++ if (!memref_list) ++ break; ++ ++ memref = memref_list->items; ++ } ++ ++ if (memref->address == address && memref->value.size == size) { ++ memref->value.value = value; ++ memref->value.changed = (flags & RC_MEMREF_FLAG_CHANGED_THIS_FRAME) ? 1 : 0; ++ memref->value.prior = prior; ++ break; ++ } ++ ++ } while (1); ++ } ++ ++ --entries; ++ } ++ ++ rc_runtime_progress_update_modified_memrefs(progress); ++ ++ return RC_OK; ++} ++ ++static int rc_runtime_progress_is_indirect_memref(rc_operand_t* oper) ++{ ++ switch (oper->type) ++ { ++ case RC_OPERAND_CONST: ++ case RC_OPERAND_FP: ++ case RC_OPERAND_RECALL: ++ case RC_OPERAND_FUNC: ++ return 0; ++ ++ default: ++ if (oper->value.memref->value.memref_type != RC_MEMREF_TYPE_MODIFIED_MEMREF) ++ return 0; ++ ++ return ((const rc_modified_memref_t*)oper->value.memref)->modifier_type == RC_OPERATOR_INDIRECT_READ; ++ } ++} ++ ++static int rc_runtime_progress_write_condset(rc_runtime_progress_t* progress, rc_condset_t* condset) ++{ ++ rc_condition_t* cond; ++ uint32_t flags; ++ ++ if (progress->offset + 4 > progress->buffer_size) ++ return RC_INSUFFICIENT_BUFFER; ++ ++ rc_runtime_progress_write_uint(progress, condset->is_paused); ++ ++ cond = condset->conditions; ++ while (cond) { ++ flags = (cond->is_true & RC_COND_FLAG_IS_TRUE_MASK); ++ ++ if (rc_runtime_progress_is_indirect_memref(&cond->operand1)) { ++ flags |= RC_COND_FLAG_OPERAND1_IS_INDIRECT_MEMREF; ++ if (cond->operand1.value.memref->value.changed) ++ flags |= RC_COND_FLAG_OPERAND1_MEMREF_CHANGED_THIS_FRAME; ++ } ++ ++ if (rc_runtime_progress_is_indirect_memref(&cond->operand2)) { ++ flags |= RC_COND_FLAG_OPERAND2_IS_INDIRECT_MEMREF; ++ if (cond->operand2.value.memref->value.changed) ++ flags |= RC_COND_FLAG_OPERAND2_MEMREF_CHANGED_THIS_FRAME; ++ } ++ ++ if (progress->offset + 8 > progress->buffer_size) ++ return RC_INSUFFICIENT_BUFFER; ++ ++ rc_runtime_progress_write_uint(progress, cond->current_hits); ++ rc_runtime_progress_write_uint(progress, flags); ++ ++ if (flags & RC_COND_FLAG_OPERAND1_IS_INDIRECT_MEMREF) { ++ if (progress->offset + 8 > progress->buffer_size) ++ return RC_INSUFFICIENT_BUFFER; ++ ++ rc_runtime_progress_write_uint(progress, cond->operand1.value.memref->value.value); ++ rc_runtime_progress_write_uint(progress, cond->operand1.value.memref->value.prior); ++ } ++ ++ if (flags & RC_COND_FLAG_OPERAND2_IS_INDIRECT_MEMREF) { ++ if (progress->offset + 8 > progress->buffer_size) ++ return RC_INSUFFICIENT_BUFFER; ++ ++ rc_runtime_progress_write_uint(progress, cond->operand2.value.memref->value.value); ++ rc_runtime_progress_write_uint(progress, cond->operand2.value.memref->value.prior); ++ } ++ ++ cond = cond->next; ++ } ++ ++ return RC_OK; ++} ++ ++static int rc_runtime_progress_read_condset(rc_runtime_progress_t* progress, rc_condset_t* condset) ++{ ++ rc_condition_t* cond; ++ uint32_t flags; ++ ++ condset->is_paused = (char)rc_runtime_progress_read_uint(progress); ++ ++ cond = condset->conditions; ++ while (cond) { ++ cond->current_hits = rc_runtime_progress_read_uint(progress); ++ flags = rc_runtime_progress_read_uint(progress); ++ ++ cond->is_true = (flags & RC_COND_FLAG_IS_TRUE_MASK); ++ ++ if (flags & RC_COND_FLAG_OPERAND1_IS_INDIRECT_MEMREF) { ++ if (!rc_operand_is_memref(&cond->operand1)) /* this should never happen, but better safe than sorry */ ++ return RC_INVALID_STATE; ++ ++ cond->operand1.value.memref->value.value = rc_runtime_progress_read_uint(progress); ++ cond->operand1.value.memref->value.prior = rc_runtime_progress_read_uint(progress); ++ cond->operand1.value.memref->value.changed = (flags & RC_COND_FLAG_OPERAND1_MEMREF_CHANGED_THIS_FRAME) ? 1 : 0; ++ } ++ ++ if (flags & RC_COND_FLAG_OPERAND2_IS_INDIRECT_MEMREF) { ++ if (!rc_operand_is_memref(&cond->operand2)) /* this should never happen, but better safe than sorry */ ++ return RC_INVALID_STATE; ++ ++ cond->operand2.value.memref->value.value = rc_runtime_progress_read_uint(progress); ++ cond->operand2.value.memref->value.prior = rc_runtime_progress_read_uint(progress); ++ cond->operand2.value.memref->value.changed = (flags & RC_COND_FLAG_OPERAND2_MEMREF_CHANGED_THIS_FRAME) ? 1 : 0; ++ } ++ ++ cond = cond->next; ++ } ++ ++ return RC_OK; ++} ++ ++static uint32_t rc_runtime_progress_should_serialize_variable_condset(const rc_condset_t* conditions) ++{ ++ const rc_condition_t* condition; ++ ++ /* predetermined presence of pause flag - must serialize */ ++ if (conditions->has_pause) ++ return RC_VAR_FLAG_HAS_COND_DATA; ++ ++ /* if any conditions has required hits, must serialize */ ++ /* ASSERT: Measured with comparison and no explicit target will set hit target to 0xFFFFFFFF */ ++ for (condition = conditions->conditions; condition; condition = condition->next) { ++ if (condition->required_hits > 0) ++ return RC_VAR_FLAG_HAS_COND_DATA; ++ } ++ ++ /* can safely be reset without affecting behavior */ ++ return 0; ++} ++ ++static int rc_runtime_progress_write_variable(rc_runtime_progress_t* progress, const rc_value_t* variable) ++{ ++ uint32_t flags; ++ ++ if (progress->offset + 12 > progress->buffer_size) ++ return RC_INSUFFICIENT_BUFFER; ++ ++ flags = rc_runtime_progress_should_serialize_variable_condset(variable->conditions); ++ if (variable->value.changed) ++ flags |= RC_MEMREF_FLAG_CHANGED_THIS_FRAME; ++ ++ rc_runtime_progress_write_uint(progress, flags); ++ rc_runtime_progress_write_uint(progress, variable->value.value); ++ rc_runtime_progress_write_uint(progress, variable->value.prior); ++ ++ if (flags & RC_VAR_FLAG_HAS_COND_DATA) { ++ int result = rc_runtime_progress_write_condset(progress, variable->conditions); ++ if (result != RC_OK) ++ return result; ++ } ++ ++ return RC_OK; ++} ++ ++static int rc_runtime_progress_write_variables(rc_runtime_progress_t* progress) ++{ ++ uint32_t count; ++ const rc_value_t* value; ++ int result; ++ ++ if (!progress->runtime->richpresence || !progress->runtime->richpresence->richpresence) ++ return RC_OK; ++ ++ value = progress->runtime->richpresence->richpresence->values; ++ count = rc_count_values(value); ++ if (count == 0) ++ return RC_OK; ++ ++ /* header + count + count(djb2,flags,value,prior,?cond) */ ++ if (progress->offset + 8 + 4 + count * 16 > progress->buffer_size) ++ return RC_INSUFFICIENT_BUFFER; ++ ++ rc_runtime_progress_start_chunk(progress, RC_RUNTIME_CHUNK_VARIABLES); ++ rc_runtime_progress_write_uint(progress, count); ++ ++ for (; value; value = value->next) { ++ const uint32_t djb2 = rc_djb2(value->name); ++ if (progress->offset + 16 > progress->buffer_size) ++ return RC_INSUFFICIENT_BUFFER; ++ ++ rc_runtime_progress_write_uint(progress, djb2); ++ ++ result = rc_runtime_progress_write_variable(progress, value); ++ if (result != RC_OK) ++ return result; ++ } ++ ++ rc_runtime_progress_end_chunk(progress); ++ return RC_OK; ++} ++ ++static int rc_runtime_progress_read_variable(rc_runtime_progress_t* progress, rc_value_t* variable) ++{ ++ uint32_t flags = rc_runtime_progress_read_uint(progress); ++ variable->value.changed = (flags & RC_MEMREF_FLAG_CHANGED_THIS_FRAME) ? 1 : 0; ++ variable->value.value = rc_runtime_progress_read_uint(progress); ++ variable->value.prior = rc_runtime_progress_read_uint(progress); ++ ++ if (flags & RC_VAR_FLAG_HAS_COND_DATA) { ++ int result = rc_runtime_progress_read_condset(progress, variable->conditions); ++ if (result != RC_OK) ++ return result; ++ } ++ else { ++ rc_reset_condset(variable->conditions); ++ } ++ ++ return RC_OK; ++} ++ ++static int rc_runtime_progress_read_variables(rc_runtime_progress_t* progress) ++{ ++ struct rc_pending_value_t ++ { ++ rc_value_t* variable; ++ uint32_t djb2; ++ }; ++ struct rc_pending_value_t local_pending_variables[32]; ++ struct rc_pending_value_t* pending_variables; ++ rc_value_t* value; ++ uint32_t count, serialized_count; ++ int result; ++ int32_t i; ++ ++ serialized_count = rc_runtime_progress_read_uint(progress); ++ if (serialized_count == 0) ++ return RC_OK; ++ ++ if (!progress->runtime->richpresence || !progress->runtime->richpresence->richpresence) ++ return RC_OK; ++ ++ value = progress->runtime->richpresence->richpresence->values; ++ count = rc_count_values(value); ++ if (count == 0) ++ return RC_OK; ++ ++ if (count <= sizeof(local_pending_variables) / sizeof(local_pending_variables[0])) { ++ pending_variables = local_pending_variables; ++ } ++ else { ++ pending_variables = (struct rc_pending_value_t*)malloc(count * sizeof(struct rc_pending_value_t)); ++ if (pending_variables == NULL) ++ return RC_OUT_OF_MEMORY; ++ } ++ ++ i = (int32_t)count; ++ for (; value; value = value->next) { ++ --i; ++ pending_variables[i].variable = value; ++ pending_variables[i].djb2 = rc_djb2(value->name); ++ } ++ ++ result = RC_OK; ++ for (; serialized_count > 0 && result == RC_OK; --serialized_count) { ++ uint32_t djb2 = rc_runtime_progress_read_uint(progress); ++ for (i = (int32_t)count - 1; i >= 0; --i) { ++ if (pending_variables[i].djb2 == djb2) { ++ value = pending_variables[i].variable; ++ result = rc_runtime_progress_read_variable(progress, value); ++ if (result == RC_OK) { ++ if (i < (int32_t)count - 1) ++ memcpy(&pending_variables[i], &pending_variables[count - 1], sizeof(struct rc_pending_value_t)); ++ count--; ++ } ++ break; ++ } ++ } ++ } ++ ++ /* VS raises a C6385 warning here because it thinks count can exceed the size of the local_pending_variables array. ++ * When count is larger, pending_variables points to allocated memory, so the warning is wrong. */ ++#if defined (_MSC_VER) ++ #pragma warning(push) ++ #pragma warning(disable:6385) ++#endif ++ while (count > 0) ++ rc_reset_value(pending_variables[--count].variable); ++#if defined (_MSC_VER) ++ #pragma warning(pop) ++#endif ++ ++ if (pending_variables != local_pending_variables) ++ free(pending_variables); ++ ++ return result; ++} ++ ++static int rc_runtime_progress_write_trigger(rc_runtime_progress_t* progress, const rc_trigger_t* trigger) ++{ ++ rc_condset_t* condset; ++ int result; ++ ++ rc_runtime_progress_write_uint(progress, trigger->state); ++ rc_runtime_progress_write_uint(progress, trigger->measured_value); ++ ++ if (trigger->requirement) { ++ result = rc_runtime_progress_write_condset(progress, trigger->requirement); ++ if (result != RC_OK) ++ return result; ++ } ++ ++ condset = trigger->alternative; ++ while (condset) { ++ result = rc_runtime_progress_write_condset(progress, condset); ++ if (result != RC_OK) ++ return result; ++ ++ condset = condset->next; ++ } ++ ++ return RC_OK; ++} ++ ++static int rc_runtime_progress_read_trigger(rc_runtime_progress_t* progress, rc_trigger_t* trigger) ++{ ++ rc_condset_t* condset; ++ int result; ++ ++ trigger->state = (char)rc_runtime_progress_read_uint(progress); ++ trigger->measured_value = rc_runtime_progress_read_uint(progress); ++ ++ if (trigger->requirement) { ++ result = rc_runtime_progress_read_condset(progress, trigger->requirement); ++ if (result != RC_OK) ++ return result; ++ } ++ ++ condset = trigger->alternative; ++ while (condset) { ++ result = rc_runtime_progress_read_condset(progress, condset); ++ if (result != RC_OK) ++ return result; ++ ++ condset = condset->next; ++ } ++ ++ return RC_OK; ++} ++ ++static int rc_runtime_progress_write_achievements(rc_runtime_progress_t* progress) ++{ ++ uint32_t i; ++ int initial_offset = 0; ++ int result; ++ ++ for (i = 0; i < progress->runtime->trigger_count; ++i) { ++ rc_runtime_trigger_t* runtime_trigger = &progress->runtime->triggers[i]; ++ if (!runtime_trigger->trigger) ++ continue; ++ ++ /* don't store state for inactive or triggered achievements */ ++ if (!rc_trigger_state_active(runtime_trigger->trigger->state)) ++ continue; ++ ++ if (!progress->buffer) { ++ if (runtime_trigger->serialized_size) { ++ progress->offset += runtime_trigger->serialized_size; ++ continue; ++ } ++ ++ initial_offset = progress->offset; ++ } else { ++ if (progress->offset + runtime_trigger->serialized_size > progress->buffer_size) ++ return RC_INSUFFICIENT_BUFFER; ++ } ++ ++ rc_runtime_progress_start_chunk(progress, RC_RUNTIME_CHUNK_ACHIEVEMENT); ++ rc_runtime_progress_write_uint(progress, runtime_trigger->id); ++ rc_runtime_progress_write_md5(progress, runtime_trigger->md5); ++ ++ result = rc_runtime_progress_write_trigger(progress, runtime_trigger->trigger); ++ if (result != RC_OK) ++ return result; ++ ++ if (runtime_trigger->serialized_size) { ++ /* runtime_trigger->serialized_size includes the header */ ++ assert_chunk_size(runtime_trigger->serialized_size - 8); ++ } ++ ++ rc_runtime_progress_end_chunk(progress); ++ ++ if (!progress->buffer) ++ runtime_trigger->serialized_size = progress->offset - initial_offset; ++ } ++ ++ return RC_OK; ++} ++ ++static int rc_runtime_progress_read_achievement(rc_runtime_progress_t* progress) ++{ ++ uint32_t id = rc_runtime_progress_read_uint(progress); ++ uint32_t i; ++ ++ for (i = 0; i < progress->runtime->trigger_count; ++i) { ++ rc_runtime_trigger_t* runtime_trigger = &progress->runtime->triggers[i]; ++ if (runtime_trigger->id == id && runtime_trigger->trigger != NULL) { ++ /* ignore triggered and waiting achievements */ ++ if (runtime_trigger->trigger->state == RC_TRIGGER_STATE_UNUPDATED) { ++ /* only update state if definition hasn't changed (md5 matches) */ ++ if (rc_runtime_progress_match_md5(progress, runtime_trigger->md5)) ++ return rc_runtime_progress_read_trigger(progress, runtime_trigger->trigger); ++ break; ++ } ++ } ++ } ++ ++ return RC_OK; ++} ++ ++static int rc_runtime_progress_write_leaderboards(rc_runtime_progress_t* progress) ++{ ++ uint32_t i; ++ uint32_t flags; ++ int initial_offset = 0; ++ int result; ++ ++ for (i = 0; i < progress->runtime->lboard_count; ++i) { ++ rc_runtime_lboard_t* runtime_lboard = &progress->runtime->lboards[i]; ++ if (!runtime_lboard->lboard) ++ continue; ++ ++ /* don't store state for inactive leaderboards */ ++ if (!rc_lboard_state_active(runtime_lboard->lboard->state)) ++ continue; ++ ++ if (!progress->buffer) { ++ if (runtime_lboard->serialized_size) { ++ progress->offset += runtime_lboard->serialized_size; ++ continue; ++ } ++ ++ initial_offset = progress->offset; ++ } else { ++ if (progress->offset + runtime_lboard->serialized_size > progress->buffer_size) ++ return RC_INSUFFICIENT_BUFFER; ++ } ++ ++ rc_runtime_progress_start_chunk(progress, RC_RUNTIME_CHUNK_LEADERBOARD); ++ rc_runtime_progress_write_uint(progress, runtime_lboard->id); ++ rc_runtime_progress_write_md5(progress, runtime_lboard->md5); ++ ++ flags = runtime_lboard->lboard->state; ++ rc_runtime_progress_write_uint(progress, flags); ++ ++ result = rc_runtime_progress_write_trigger(progress, &runtime_lboard->lboard->start); ++ if (result != RC_OK) ++ return result; ++ ++ result = rc_runtime_progress_write_trigger(progress, &runtime_lboard->lboard->submit); ++ if (result != RC_OK) ++ return result; ++ ++ result = rc_runtime_progress_write_trigger(progress, &runtime_lboard->lboard->cancel); ++ if (result != RC_OK) ++ return result; ++ ++ result = rc_runtime_progress_write_variable(progress, &runtime_lboard->lboard->value); ++ if (result != RC_OK) ++ return result; ++ ++ if (runtime_lboard->serialized_size) { ++ /* runtime_lboard->serialized_size includes the header */ ++ assert_chunk_size(runtime_lboard->serialized_size - 8); ++ } ++ ++ rc_runtime_progress_end_chunk(progress); ++ ++ if (!progress->buffer) ++ runtime_lboard->serialized_size = progress->offset - initial_offset; ++ } ++ ++ return RC_OK; ++} ++ ++static int rc_runtime_progress_read_leaderboard(rc_runtime_progress_t* progress) ++{ ++ uint32_t id = rc_runtime_progress_read_uint(progress); ++ uint32_t i; ++ int result; ++ ++ for (i = 0; i < progress->runtime->lboard_count; ++i) { ++ rc_runtime_lboard_t* runtime_lboard = &progress->runtime->lboards[i]; ++ if (runtime_lboard->id == id && runtime_lboard->lboard != NULL) { ++ /* ignore triggered and waiting achievements */ ++ if (runtime_lboard->lboard->state == RC_TRIGGER_STATE_UNUPDATED) { ++ /* only update state if definition hasn't changed (md5 matches) */ ++ if (rc_runtime_progress_match_md5(progress, runtime_lboard->md5)) { ++ uint32_t flags = rc_runtime_progress_read_uint(progress); ++ ++ result = rc_runtime_progress_read_trigger(progress, &runtime_lboard->lboard->start); ++ if (result != RC_OK) ++ return result; ++ ++ result = rc_runtime_progress_read_trigger(progress, &runtime_lboard->lboard->submit); ++ if (result != RC_OK) ++ return result; ++ ++ result = rc_runtime_progress_read_trigger(progress, &runtime_lboard->lboard->cancel); ++ if (result != RC_OK) ++ return result; ++ ++ result = rc_runtime_progress_read_variable(progress, &runtime_lboard->lboard->value); ++ if (result != RC_OK) ++ return result; ++ ++ runtime_lboard->lboard->state = (char)(flags & 0x7F); ++ } ++ break; ++ } ++ } ++ } ++ ++ return RC_OK; ++} ++ ++static int rc_runtime_progress_write_rich_presence(rc_runtime_progress_t* progress) ++{ ++ const rc_richpresence_display_t* display; ++ int result; ++ ++ if (!progress->runtime->richpresence || !progress->runtime->richpresence->richpresence) ++ return RC_OK; ++ ++ /* if there are no conditional display strings, there's nothing to capture */ ++ display = progress->runtime->richpresence->richpresence->first_display; ++ if (!display->next) ++ return RC_OK; ++ ++ if (progress->offset + 8 + 16 > progress->buffer_size) ++ return RC_INSUFFICIENT_BUFFER; ++ ++ rc_runtime_progress_start_chunk(progress, RC_RUNTIME_CHUNK_RICHPRESENCE); ++ rc_runtime_progress_write_md5(progress, progress->runtime->richpresence->md5); ++ ++ for (; display->next; display = display->next) { ++ result = rc_runtime_progress_write_trigger(progress, &display->trigger); ++ if (result != RC_OK) ++ return result; ++ } ++ ++ rc_runtime_progress_end_chunk(progress); ++ return RC_OK; ++} ++ ++static int rc_runtime_progress_read_rich_presence(rc_runtime_progress_t* progress) ++{ ++ rc_richpresence_display_t* display; ++ int result; ++ ++ if (!progress->runtime->richpresence || !progress->runtime->richpresence->richpresence) ++ return RC_OK; ++ ++ if (!rc_runtime_progress_match_md5(progress, progress->runtime->richpresence->md5)) { ++ rc_reset_richpresence_triggers(progress->runtime->richpresence->richpresence); ++ return RC_OK; ++ } ++ ++ display = progress->runtime->richpresence->richpresence->first_display; ++ for (; display->next; display = display->next) { ++ result = rc_runtime_progress_read_trigger(progress, &display->trigger); ++ if (result != RC_OK) ++ return result; ++ } ++ ++ return RC_OK; ++} ++ ++static int rc_runtime_progress_serialize_internal(rc_runtime_progress_t* progress) ++{ ++ md5_state_t state; ++ uint8_t md5[16]; ++ int result; ++ ++ if (progress->buffer_size < RC_RUNTIME_MIN_BUFFER_SIZE) ++ return RC_INSUFFICIENT_BUFFER; ++ ++ rc_runtime_progress_write_uint(progress, RC_RUNTIME_MARKER); ++ ++ if ((result = rc_runtime_progress_write_memrefs(progress)) != RC_OK) ++ return result; ++ ++ if ((result = rc_runtime_progress_write_variables(progress)) != RC_OK) ++ return result; ++ ++ if ((result = rc_runtime_progress_write_achievements(progress)) != RC_OK) ++ return result; ++ ++ if ((result = rc_runtime_progress_write_leaderboards(progress)) != RC_OK) ++ return result; ++ ++ if ((result = rc_runtime_progress_write_rich_presence(progress)) != RC_OK) ++ return result; ++ ++ if (progress->offset + 8 + 16 > progress->buffer_size) ++ return RC_INSUFFICIENT_BUFFER; ++ ++ rc_runtime_progress_write_uint(progress, RC_RUNTIME_CHUNK_DONE); ++ rc_runtime_progress_write_uint(progress, 16); ++ ++ if (progress->buffer) { ++ md5_init(&state); ++ md5_append(&state, progress->buffer, progress->offset); ++ md5_finish(&state, md5); ++ } ++ ++ rc_runtime_progress_write_md5(progress, md5); ++ ++ return RC_OK; ++} ++ ++uint32_t rc_runtime_progress_size(const rc_runtime_t* runtime, void* unused_L) ++{ ++ rc_runtime_progress_t progress; ++ int result; ++ ++ (void)unused_L; ++ ++ rc_runtime_progress_init(&progress, runtime); ++ progress.buffer_size = 0xFFFFFFFF; ++ ++ result = rc_runtime_progress_serialize_internal(&progress); ++ if (result != RC_OK) ++ return result; ++ ++ return progress.offset; ++} ++ ++int rc_runtime_serialize_progress(void* buffer, const rc_runtime_t* runtime, void* unused_L) ++{ ++ return rc_runtime_serialize_progress_sized((uint8_t*)buffer, 0xFFFFFFFF, runtime, unused_L); ++} ++ ++int rc_runtime_serialize_progress_sized(uint8_t* buffer, uint32_t buffer_size, const rc_runtime_t* runtime, void* unused_L) ++{ ++ rc_runtime_progress_t progress; ++ ++ (void)unused_L; ++ ++ if (!buffer) ++ return RC_INVALID_STATE; ++ ++ rc_runtime_progress_init(&progress, runtime); ++ progress.buffer = (uint8_t*)buffer; ++ progress.buffer_size = buffer_size; ++ ++ return rc_runtime_progress_serialize_internal(&progress); ++} ++ ++int rc_runtime_deserialize_progress(rc_runtime_t* runtime, const uint8_t* serialized, void* unused_L) ++{ ++ return rc_runtime_deserialize_progress_sized(runtime, serialized, 0xFFFFFFFF, unused_L); ++} ++ ++int rc_runtime_deserialize_progress_sized(rc_runtime_t* runtime, const uint8_t* serialized, uint32_t serialized_size, void* unused_L) ++{ ++ rc_runtime_progress_t progress; ++ md5_state_t state; ++ uint8_t md5[16]; ++ uint32_t chunk_id; ++ uint32_t chunk_size; ++ uint32_t next_chunk_offset; ++ uint32_t i; ++ int seen_rich_presence = 0; ++ int result = RC_OK; ++ ++ (void)unused_L; ++ ++ if (!serialized || serialized_size < RC_RUNTIME_MIN_BUFFER_SIZE) { ++ rc_runtime_reset(runtime); ++ return RC_INSUFFICIENT_BUFFER; ++ } ++ ++ rc_runtime_progress_init(&progress, runtime); ++ progress.buffer = (uint8_t*)serialized; ++ ++ if (rc_runtime_progress_read_uint(&progress) != RC_RUNTIME_MARKER) { ++ rc_runtime_reset(runtime); ++ return RC_INVALID_STATE; ++ } ++ ++ for (i = 0; i < runtime->trigger_count; ++i) { ++ rc_runtime_trigger_t* runtime_trigger = &runtime->triggers[i]; ++ if (runtime_trigger->trigger) { ++ /* don't update state for inactive or triggered achievements */ ++ if (rc_trigger_state_active(runtime_trigger->trigger->state)) { ++ /* mark active achievements as unupdated. anything that's still unupdated ++ * after deserializing the progress will be reset to waiting */ ++ runtime_trigger->trigger->state = RC_TRIGGER_STATE_UNUPDATED; ++ } ++ } ++ } ++ ++ for (i = 0; i < runtime->lboard_count; ++i) { ++ rc_runtime_lboard_t* runtime_lboard = &runtime->lboards[i]; ++ if (runtime_lboard->lboard) { ++ /* don't update state for inactive or triggered achievements */ ++ if (rc_lboard_state_active(runtime_lboard->lboard->state)) { ++ /* mark active achievements as unupdated. anything that's still unupdated ++ * after deserializing the progress will be reset to waiting */ ++ runtime_lboard->lboard->state = RC_TRIGGER_STATE_UNUPDATED; ++ } ++ } ++ } ++ ++ do { ++ if (progress.offset + 8 >= serialized_size) { ++ result = RC_INSUFFICIENT_BUFFER; ++ break; ++ } ++ ++ chunk_id = rc_runtime_progress_read_uint(&progress); ++ chunk_size = rc_runtime_progress_read_uint(&progress); ++ next_chunk_offset = progress.offset + chunk_size; ++ ++ if (next_chunk_offset > serialized_size) { ++ result = RC_INSUFFICIENT_BUFFER; ++ break; ++ } ++ ++ switch (chunk_id) { ++ case RC_RUNTIME_CHUNK_MEMREFS: ++ result = rc_runtime_progress_read_memrefs(&progress); ++ break; ++ ++ case RC_RUNTIME_CHUNK_VARIABLES: ++ result = rc_runtime_progress_read_variables(&progress); ++ break; ++ ++ case RC_RUNTIME_CHUNK_ACHIEVEMENT: ++ result = rc_runtime_progress_read_achievement(&progress); ++ break; ++ ++ case RC_RUNTIME_CHUNK_LEADERBOARD: ++ result = rc_runtime_progress_read_leaderboard(&progress); ++ break; ++ ++ case RC_RUNTIME_CHUNK_RICHPRESENCE: ++ seen_rich_presence = 1; ++ result = rc_runtime_progress_read_rich_presence(&progress); ++ break; ++ ++ case RC_RUNTIME_CHUNK_DONE: ++ md5_init(&state); ++ md5_append(&state, progress.buffer, progress.offset); ++ md5_finish(&state, md5); ++ if (!rc_runtime_progress_match_md5(&progress, md5)) ++ result = RC_INVALID_STATE; ++ break; ++ ++ default: ++ if (chunk_size & 0xFFFF0000) ++ result = RC_INVALID_STATE; /* assume unknown chunk > 64KB is invalid */ ++ break; ++ } ++ ++ progress.offset = next_chunk_offset; ++ } while (result == RC_OK && chunk_id != RC_RUNTIME_CHUNK_DONE); ++ ++ if (result != RC_OK) { ++ rc_runtime_reset(runtime); ++ } ++ else { ++ for (i = 0; i < runtime->trigger_count; ++i) { ++ rc_trigger_t* trigger = runtime->triggers[i].trigger; ++ if (trigger && trigger->state == RC_TRIGGER_STATE_UNUPDATED) ++ rc_reset_trigger(trigger); ++ } ++ ++ for (i = 0; i < runtime->lboard_count; ++i) { ++ rc_lboard_t* lboard = runtime->lboards[i].lboard; ++ if (lboard && lboard->state == RC_TRIGGER_STATE_UNUPDATED) ++ rc_reset_lboard(lboard); ++ } ++ ++ if (!seen_rich_presence && runtime->richpresence && runtime->richpresence->richpresence) ++ rc_reset_richpresence_triggers(runtime->richpresence->richpresence); ++ } ++ ++ return result; ++} +diff -rupbN melonDS.orig/src/rcheevos/src/rcheevos/trigger.c melonDS.ra/src/rcheevos/src/rcheevos/trigger.c +--- melonDS.orig/src/rcheevos/src/rcheevos/trigger.c 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rcheevos/trigger.c 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,344 @@ ++#include "rc_internal.h" ++ ++#include ++#include /* memset */ ++ ++void rc_parse_trigger_internal(rc_trigger_t* self, const char** memaddr, rc_parse_state_t* parse) { ++ rc_condset_t** next; ++ const char* aux; ++ ++ aux = *memaddr; ++ next = &self->alternative; ++ ++ /* reset in case multiple triggers are parsed by the same parse_state */ ++ parse->measured_target = 0; ++ parse->has_required_hits = 0; ++ parse->measured_as_percent = 0; ++ ++ if (*aux == 's' || *aux == 'S') { ++ self->requirement = NULL; ++ } ++ else { ++ self->requirement = rc_parse_condset(&aux, parse); ++ ++ if (parse->offset < 0) ++ return; ++ ++ self->requirement->next = NULL; ++ } ++ ++ while (*aux == 's' || *aux == 'S') { ++ aux++; ++ *next = rc_parse_condset(&aux, parse); ++ ++ if (parse->offset < 0) { ++ return; ++ } ++ ++ next = &(*next)->next; ++ } ++ ++ *next = NULL; ++ *memaddr = aux; ++ ++ self->measured_target = parse->measured_target; ++ self->measured_value = parse->measured_target ? RC_MEASURED_UNKNOWN : 0; ++ self->measured_as_percent = parse->measured_as_percent; ++ self->state = RC_TRIGGER_STATE_WAITING; ++ self->has_hits = 0; ++ self->has_memrefs = 0; ++} ++ ++int rc_trigger_size(const char* memaddr) { ++ rc_trigger_with_memrefs_t* trigger; ++ rc_preparse_state_t preparse; ++ rc_init_preparse_state(&preparse); ++ ++ trigger = RC_ALLOC(rc_trigger_with_memrefs_t, &preparse.parse); ++ rc_parse_trigger_internal(&trigger->trigger, &memaddr, &preparse.parse); ++ rc_preparse_alloc_memrefs(NULL, &preparse); ++ ++ rc_destroy_preparse_state(&preparse); ++ return preparse.parse.offset; ++} ++ ++rc_trigger_t* rc_parse_trigger(void* buffer, const char* memaddr, void* unused_L, int unused_funcs_idx) { ++ rc_trigger_with_memrefs_t* trigger; ++ rc_preparse_state_t preparse; ++ const char* preparse_memaddr = memaddr; ++ ++ (void)unused_L; ++ (void)unused_funcs_idx; ++ ++ if (!buffer || !memaddr) ++ return NULL; ++ ++ /* first pass : determine how many memrefs are needed */ ++ rc_init_preparse_state(&preparse); ++ trigger = RC_ALLOC(rc_trigger_with_memrefs_t, &preparse.parse); ++ rc_parse_trigger_internal(&trigger->trigger, &preparse_memaddr, &preparse.parse); ++ ++ /* allocate the trigger and memrefs */ ++ rc_reset_parse_state(&preparse.parse, buffer); ++ trigger = RC_ALLOC(rc_trigger_with_memrefs_t, &preparse.parse); ++ rc_preparse_alloc_memrefs(&trigger->memrefs, &preparse); ++ ++ /* parse the trigger */ ++ rc_parse_trigger_internal(&trigger->trigger, &memaddr, &preparse.parse); ++ trigger->trigger.has_memrefs = 1; ++ ++ rc_destroy_preparse_state(&preparse); ++ return (preparse.parse.offset >= 0) ? &trigger->trigger : NULL; ++} ++ ++int rc_trigger_state_active(int state) ++{ ++ switch (state) ++ { ++ case RC_TRIGGER_STATE_DISABLED: ++ case RC_TRIGGER_STATE_INACTIVE: ++ case RC_TRIGGER_STATE_TRIGGERED: ++ return 0; ++ ++ default: ++ return 1; ++ } ++} ++ ++static int rc_condset_is_measured_from_hitcount(const rc_condset_t* condset, uint32_t measured_value) ++{ ++ const rc_condition_t* condition; ++ for (condition = condset->conditions; condition; condition = condition->next) { ++ if (condition->type == RC_CONDITION_MEASURED && condition->required_hits && ++ condition->current_hits == measured_value) { ++ return 1; ++ } ++ } ++ ++ return 0; ++} ++ ++static void rc_reset_trigger_hitcounts(rc_trigger_t* self) { ++ rc_condset_t* condset; ++ ++ if (self->requirement) { ++ rc_reset_condset(self->requirement); ++ } ++ ++ condset = self->alternative; ++ ++ while (condset) { ++ rc_reset_condset(condset); ++ condset = condset->next; ++ } ++} ++ ++static void rc_update_trigger_memrefs(rc_trigger_t* self, rc_peek_t peek, void* ud) { ++ if (self->has_memrefs) { ++ rc_trigger_with_memrefs_t* trigger = (rc_trigger_with_memrefs_t*)self; ++ rc_update_memref_values(&trigger->memrefs, peek, ud); ++ } ++} ++ ++rc_memrefs_t* rc_trigger_get_memrefs(rc_trigger_t* self) { ++ if (self->has_memrefs) { ++ rc_trigger_with_memrefs_t* trigger = (rc_trigger_with_memrefs_t*)self; ++ return &trigger->memrefs; ++ } ++ ++ return NULL; ++} ++ ++int rc_evaluate_trigger(rc_trigger_t* self, rc_peek_t peek, void* ud, void* unused_L) { ++ rc_eval_state_t eval_state; ++ rc_condset_t* condset; ++ rc_typed_value_t measured_value; ++ int measured_from_hits = 0; ++ int ret; ++ char is_paused; ++ char is_primed; ++ ++ (void)unused_L; ++ ++ switch (self->state) ++ { ++ case RC_TRIGGER_STATE_TRIGGERED: ++ /* previously triggered. do nothing - return INACTIVE so caller doesn't think it triggered again */ ++ return RC_TRIGGER_STATE_INACTIVE; ++ ++ case RC_TRIGGER_STATE_DISABLED: ++ /* unsupported. do nothing - return INACTIVE */ ++ return RC_TRIGGER_STATE_INACTIVE; ++ ++ case RC_TRIGGER_STATE_INACTIVE: ++ /* not yet active. update the memrefs so deltas are correct when it becomes active, then return INACTIVE */ ++ rc_update_trigger_memrefs(self, peek, ud); ++ return RC_TRIGGER_STATE_INACTIVE; ++ ++ default: ++ break; ++ } ++ ++ /* update the memory references */ ++ rc_update_trigger_memrefs(self, peek, ud); ++ ++ /* process the trigger */ ++ memset(&eval_state, 0, sizeof(eval_state)); ++ eval_state.peek = peek; ++ eval_state.peek_userdata = ud; ++ ++ measured_value.type = RC_VALUE_TYPE_NONE; ++ ++ if (self->requirement != NULL) { ++ ret = rc_test_condset(self->requirement, &eval_state); ++ is_paused = eval_state.is_paused; ++ is_primed = eval_state.is_primed; ++ ++ if (eval_state.measured_value.type != RC_VALUE_TYPE_NONE) { ++ memcpy(&measured_value, &eval_state.measured_value, sizeof(measured_value)); ++ measured_from_hits = eval_state.measured_from_hits; ++ } ++ } else { ++ ret = 1; ++ is_paused = 0; ++ is_primed = 1; ++ } ++ ++ condset = self->alternative; ++ if (condset) { ++ int sub = 0; ++ char sub_paused = 1; ++ char sub_primed = 0; ++ ++ do { ++ sub |= rc_test_condset(condset, &eval_state); ++ sub_paused &= eval_state.is_paused; ++ sub_primed |= eval_state.is_primed; ++ ++ if (eval_state.measured_value.type != RC_VALUE_TYPE_NONE) { ++ /* if no previous Measured value was captured, or the new one is greater, keep the new one */ ++ if (measured_value.type == RC_VALUE_TYPE_NONE || ++ rc_typed_value_compare(&eval_state.measured_value, &measured_value, RC_OPERATOR_GT)) { ++ memcpy(&measured_value, &eval_state.measured_value, sizeof(measured_value)); ++ measured_from_hits = eval_state.measured_from_hits; ++ } ++ } ++ ++ condset = condset->next; ++ } while (condset); ++ ++ /* to trigger, the core must be true and at least one alt must be true */ ++ ret &= sub; ++ is_primed &= sub_primed; ++ ++ /* if the core is not paused, all alts must be paused to count as a paused trigger */ ++ is_paused |= sub_paused; ++ } ++ ++ if (is_paused) { ++ /* if the trigger is fully paused, ignore any updates to the measured value */ ++ } ++ else if (measured_value.type == RC_VALUE_TYPE_NONE) { ++ /* if a measured value was not captured, keep the old value (it's possible to pause ++ * an alt that is generating the measured value without fully pausing the trigger) */ ++ } ++ else { ++ rc_typed_value_convert(&measured_value, RC_VALUE_TYPE_UNSIGNED); ++ self->measured_value = measured_value.value.u32; ++ } ++ ++ /* if any ResetIf condition was true, reset the hit counts */ ++ if (eval_state.was_reset) { ++ /* if the measured value came from a hit count, reset it. do this before calling ++ * rc_reset_trigger_hitcounts in case we need to call rc_condset_is_measured_from_hitcount */ ++ if (measured_from_hits) { ++ self->measured_value = 0; ++ } ++ else if (is_paused && self->measured_value) { ++ /* if the measured value is in a paused group, measured_from_hits won't have been set. ++ * attempt to determine if it should have been */ ++ if (self->requirement && self->requirement->is_paused && ++ rc_condset_is_measured_from_hitcount(self->requirement, self->measured_value)) { ++ self->measured_value = 0; ++ } ++ else { ++ for (condset = self->alternative; condset; condset = condset->next) { ++ if (condset->is_paused && rc_condset_is_measured_from_hitcount(condset, self->measured_value)) { ++ self->measured_value = 0; ++ break; ++ } ++ } ++ } ++ } ++ ++ rc_reset_trigger_hitcounts(self); ++ ++ /* if there were hit counts to clear, return RESET, but don't change the state */ ++ if (self->has_hits) { ++ self->has_hits = 0; ++ ++ /* cannot be PRIMED while ResetIf is true */ ++ if (self->state == RC_TRIGGER_STATE_PRIMED) ++ self->state = RC_TRIGGER_STATE_ACTIVE; ++ ++ return RC_TRIGGER_STATE_RESET; ++ } ++ ++ /* any hits that were tallied were just reset */ ++ eval_state.has_hits = 0; ++ is_primed = 0; ++ } ++ else if (ret) { ++ /* if the state is WAITING and the trigger is ready to fire, ignore it and reset the hit counts */ ++ if (self->state == RC_TRIGGER_STATE_WAITING) { ++ rc_reset_trigger(self); ++ self->has_hits = 0; ++ return RC_TRIGGER_STATE_WAITING; ++ } ++ ++ /* trigger was triggered */ ++ self->state = RC_TRIGGER_STATE_TRIGGERED; ++ return RC_TRIGGER_STATE_TRIGGERED; ++ } ++ ++ /* did not trigger this frame - update the information we'll need for next time */ ++ self->has_hits = eval_state.has_hits; ++ ++ if (is_paused) { ++ self->state = RC_TRIGGER_STATE_PAUSED; ++ } ++ else if (is_primed) { ++ self->state = RC_TRIGGER_STATE_PRIMED; ++ } ++ else { ++ self->state = RC_TRIGGER_STATE_ACTIVE; ++ } ++ ++ /* if an individual condition was reset, notify the caller */ ++ if (eval_state.was_cond_reset) ++ return RC_TRIGGER_STATE_RESET; ++ ++ /* otherwise, just return the current state */ ++ return self->state; ++} ++ ++int rc_test_trigger(rc_trigger_t* self, rc_peek_t peek, void* ud, void* unused_L) { ++ /* for backwards compatibilty, rc_test_trigger always assumes the achievement is active */ ++ self->state = RC_TRIGGER_STATE_ACTIVE; ++ ++ return (rc_evaluate_trigger(self, peek, ud, unused_L) == RC_TRIGGER_STATE_TRIGGERED); ++} ++ ++void rc_reset_trigger(rc_trigger_t* self) { ++ if (!self) ++ return; ++ ++ rc_reset_trigger_hitcounts(self); ++ ++ self->state = RC_TRIGGER_STATE_WAITING; ++ ++ if (self->measured_target) ++ self->measured_value = RC_MEASURED_UNKNOWN; ++ ++ self->has_hits = 0; ++} +diff -rupbN melonDS.orig/src/rcheevos/src/rcheevos/value.c melonDS.ra/src/rcheevos/src/rcheevos/value.c +--- melonDS.orig/src/rcheevos/src/rcheevos/value.c 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rcheevos/value.c 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,933 @@ ++#include "rc_internal.h" ++ ++#include /* memset */ ++#include /* isdigit */ ++#include /* FLT_EPSILON */ ++#include /* fmod */ ++ ++int rc_is_valid_variable_character(char ch, int is_first) { ++ if (is_first) { ++ if (!isalpha((unsigned char)ch)) ++ return 0; ++ } ++ else { ++ if (!isalnum((unsigned char)ch)) ++ return 0; ++ } ++ return 1; ++} ++ ++static void rc_parse_cond_value(rc_value_t* self, const char** memaddr, rc_parse_state_t* parse) { ++ rc_condset_t** next_clause; ++ ++ next_clause = &self->conditions; ++ ++ do ++ { ++ parse->measured_target = 0; /* passing is_value=1 should prevent any conflicts, but clear it out anyway */ ++ *next_clause = rc_parse_condset(memaddr, parse); ++ if (parse->offset < 0) { ++ return; ++ } ++ ++ if (**memaddr == 'S' || **memaddr == 's') { ++ /* alt groups not supported */ ++ parse->offset = RC_INVALID_VALUE_FLAG; ++ } ++ else if (parse->measured_target == 0) { ++ parse->offset = RC_MISSING_VALUE_MEASURED; ++ } ++ else if (**memaddr == '$') { ++ /* maximum of */ ++ ++(*memaddr); ++ next_clause = &(*next_clause)->next; ++ continue; ++ } ++ ++ break; ++ } while (1); ++ ++ (*next_clause)->next = 0; ++} ++ ++static void rc_parse_legacy_value(rc_value_t* self, const char** memaddr, rc_parse_state_t* parse) { ++ rc_condset_with_trailing_conditions_t* condset_with_conditions; ++ rc_condition_t** next; ++ rc_condset_t** next_clause; ++ rc_condset_t* condset; ++ rc_condition_t local_cond; ++ rc_condition_t* cond; ++ uint32_t num_measured_conditions; ++ char buffer[64] = "A:"; ++ const char* buffer_ptr; ++ char* ptr; ++ int done; ++ ++ /* convert legacy format into condset */ ++ next_clause = &self->conditions; ++ do { ++ /* count the number of joiners and add one to determine the number of clauses. */ ++ buffer[0] = 'A'; /* reset to AddSource */ ++ done = 0; ++ num_measured_conditions = 1; ++ buffer_ptr = *memaddr; ++ do { ++ switch (*buffer_ptr++) { ++ case '_': /* add next */ ++ ++num_measured_conditions; ++ buffer[0] = 'A'; /* reset to AddSource */ ++ break; ++ ++ case '*': /* multiply */ ++ if (*buffer_ptr == '-') { ++ /* multiplication by a negative number will convert to SubSource */ ++ ++buffer_ptr; ++ buffer[0] = 'B'; ++ } ++ break; ++ ++ case '\0': /* end of string */ ++ case '$': /* maximum of */ ++ case ':': /* end of leaderboard clause */ ++ case ')': /* end of rich presence macro */ ++ done = 1; ++ break; ++ ++ default: /* assume everything else is valid - bad stuff will be filtered out later */ ++ break; ++ } ++ } while (!done); ++ ++ /* if last condition is not AddSource, we'll need to add a dummy condition for the Measured */ ++ if (buffer[0] != 'A') ++ ++num_measured_conditions; ++ ++ condset_with_conditions = RC_ALLOC_WITH_TRAILING(rc_condset_with_trailing_conditions_t, ++ rc_condition_t, conditions, num_measured_conditions, parse); ++ if (parse->offset < 0) ++ return; ++ ++ condset = (rc_condset_t*)condset_with_conditions; ++ memset(condset, 0, sizeof(*condset)); ++ condset->num_measured_conditions = num_measured_conditions; ++ cond = &condset_with_conditions->conditions[0]; ++ ++ next = &condset->conditions; ++ ++ for (;; ++(*memaddr)) { ++ buffer[0] = 'A'; /* reset to AddSource */ ++ ptr = &buffer[2]; ++ ++ /* extract the next clause */ ++ for (;; ++(*memaddr)) { ++ switch (**memaddr) { ++ case '_': /* add next */ ++ *ptr = '\0'; ++ break; ++ ++ case '$': /* maximum of */ ++ case '\0': /* end of string */ ++ case ':': /* end of leaderboard clause */ ++ case ')': /* end of rich presence macro */ ++ /* the last condition needs to be Measured - AddSource can be changed here, ++ * SubSource will be handled later */ ++ if (buffer[0] == 'A') ++ buffer[0] = 'M'; ++ ++ *ptr = '\0'; ++ break; ++ ++ case '*': ++ *ptr++ = '*'; ++ ++ buffer_ptr = *memaddr + 1; ++ if (*buffer_ptr == '-') { ++ buffer[0] = 'B'; /* change to SubSource */ ++ ++(*memaddr); /* don't copy sign */ ++ ++buffer_ptr; /* ignore sign when doing floating point check */ ++ } ++ else if (*buffer_ptr == '+') { ++ ++buffer_ptr; /* ignore sign when doing floating point check */ ++ } ++ ++ /* if it looks like a floating point number, add the 'f' prefix */ ++ while (isdigit((unsigned char)*buffer_ptr)) ++ ++buffer_ptr; ++ if (*buffer_ptr == '.') ++ *ptr++ = 'f'; ++ continue; ++ ++ default: ++ *ptr++ = **memaddr; ++ continue; ++ } ++ ++ break; ++ } ++ ++ /* process the clause */ ++ if (!parse->buffer) ++ cond = &local_cond; ++ ++ buffer_ptr = buffer; ++ rc_parse_condition_internal(cond, &buffer_ptr, parse); ++ if (parse->offset < 0) ++ return; ++ ++ if (*buffer_ptr) { ++ /* whatever we copied as a single condition was not fully consumed */ ++ parse->offset = RC_INVALID_COMPARISON; ++ return; ++ } ++ ++ if (!rc_operator_is_modifying(cond->oper)) { ++ parse->offset = RC_INVALID_OPERATOR; ++ return; ++ } ++ ++ rc_condition_update_parse_state(cond, parse); ++ ++ *next = cond; ++ next = &cond->next; ++ ++ if (**memaddr != '_') /* add next */ ++ break; ++ ++ ++cond; ++ } ++ ++ /* -- end of clause -- */ ++ ++ /* clause must end in a Measured. if it doesn't, append one */ ++ if (cond->type != RC_CONDITION_MEASURED) { ++ if (!parse->buffer) ++ cond = &local_cond; ++ else ++ ++cond; ++ ++ buffer_ptr = "M:0"; ++ rc_parse_condition_internal(cond, &buffer_ptr, parse); ++ *next = cond; ++ next = &cond->next; ++ rc_condition_update_parse_state(cond, parse); ++ } ++ ++ *next = NULL; ++ ++ /* finalize clause */ ++ *next_clause = condset; ++ next_clause = &condset->next; ++ ++ if (**memaddr != '$') { ++ /* end of valid string */ ++ *next_clause = NULL; ++ break; ++ } ++ ++ /* max of ($), start a new clause */ ++ ++(*memaddr); ++ } while (1); ++} ++ ++void rc_parse_value_internal(rc_value_t* self, const char** memaddr, rc_parse_state_t* parse) { ++ const uint8_t was_value = parse->is_value; ++ const rc_condition_t* condition; ++ parse->is_value = 1; ++ ++ /* if it starts with a condition flag (M: A: B: C:), parse the conditions */ ++ if ((*memaddr)[1] == ':') ++ rc_parse_cond_value(self, memaddr, parse); ++ else ++ rc_parse_legacy_value(self, memaddr, parse); ++ ++ if (parse->offset >= 0 && parse->buffer) { ++ self->name = "(unnamed)"; ++ self->value.value = self->value.prior = 0; ++ self->value.memref_type = RC_MEMREF_TYPE_VALUE; ++ self->value.changed = 0; ++ self->has_memrefs = 0; ++ ++ for (condition = self->conditions->conditions; condition; condition = condition->next) { ++ if (condition->type == RC_CONDITION_MEASURED) { ++ if (rc_operand_is_float(&condition->operand1)) { ++ self->value.size = RC_MEMSIZE_FLOAT; ++ self->value.type = RC_VALUE_TYPE_FLOAT; ++ } ++ else { ++ self->value.size = RC_MEMSIZE_32_BITS; ++ self->value.type = RC_VALUE_TYPE_UNSIGNED; ++ } ++ break; ++ } ++ } ++ } ++ ++ parse->is_value = was_value; ++} ++ ++int rc_value_size(const char* memaddr) { ++ rc_value_with_memrefs_t* value; ++ rc_preparse_state_t preparse; ++ rc_init_preparse_state(&preparse); ++ ++ value = RC_ALLOC(rc_value_with_memrefs_t, &preparse.parse); ++ rc_parse_value_internal(&value->value, &memaddr, &preparse.parse); ++ rc_preparse_alloc_memrefs(NULL, &preparse); ++ ++ rc_destroy_preparse_state(&preparse); ++ return preparse.parse.offset; ++} ++ ++rc_value_t* rc_parse_value(void* buffer, const char* memaddr, void* unused_L, int unused_funcs_idx) { ++ rc_value_with_memrefs_t* value; ++ rc_preparse_state_t preparse; ++ const char* preparse_memaddr = memaddr; ++ ++ (void)unused_L; ++ (void)unused_funcs_idx; ++ ++ if (!buffer || !memaddr) ++ return NULL; ++ ++ rc_init_preparse_state(&preparse); ++ value = RC_ALLOC(rc_value_with_memrefs_t, &preparse.parse); ++ rc_parse_value_internal(&value->value, &preparse_memaddr, &preparse.parse); ++ ++ rc_reset_parse_state(&preparse.parse, buffer); ++ value = RC_ALLOC(rc_value_with_memrefs_t, &preparse.parse); ++ rc_preparse_alloc_memrefs(&value->memrefs, &preparse); ++ ++ rc_parse_value_internal(&value->value, &memaddr, &preparse.parse); ++ value->value.has_memrefs = 1; ++ ++ rc_destroy_preparse_state(&preparse); ++ return (preparse.parse.offset >= 0) ? &value->value : NULL; ++} ++ ++static void rc_update_value_memrefs(rc_value_t* self, rc_peek_t peek, void* ud) { ++ if (self->has_memrefs) { ++ rc_value_with_memrefs_t* value = (rc_value_with_memrefs_t*)self; ++ rc_update_memref_values(&value->memrefs, peek, ud); ++ } ++} ++ ++int rc_evaluate_value_typed(rc_value_t* self, rc_typed_value_t* value, rc_peek_t peek, void* ud) { ++ rc_eval_state_t eval_state; ++ rc_condset_t* condset; ++ int valid = 0; ++ ++ rc_update_value_memrefs(self, peek, ud); ++ ++ value->value.i32 = 0; ++ value->type = RC_VALUE_TYPE_SIGNED; ++ ++ for (condset = self->conditions; condset != NULL; condset = condset->next) { ++ memset(&eval_state, 0, sizeof(eval_state)); ++ eval_state.peek = peek; ++ eval_state.peek_userdata = ud; ++ ++ rc_test_condset(condset, &eval_state); ++ ++ if (condset->is_paused) ++ continue; ++ ++ if (eval_state.was_reset) { ++ /* if any ResetIf condition was true, reset the hit counts ++ * NOTE: ResetIf only affects the current condset when used in values! ++ */ ++ rc_reset_condset(condset); ++ } ++ ++ if (eval_state.measured_value.type != RC_VALUE_TYPE_NONE) { ++ if (!valid) { ++ /* capture the first valid measurement, which may be negative */ ++ memcpy(value, &eval_state.measured_value, sizeof(*value)); ++ valid = 1; ++ } ++ else { ++ /* multiple condsets are currently only used for the MAX_OF operation. ++ * only keep the condset's value if it's higher than the current highest value. ++ */ ++ if (rc_typed_value_compare(&eval_state.measured_value, value, RC_OPERATOR_GT)) ++ memcpy(value, &eval_state.measured_value, sizeof(*value)); ++ } ++ } ++ } ++ ++ return valid; ++} ++ ++int32_t rc_evaluate_value(rc_value_t* self, rc_peek_t peek, void* ud, void* unused_L) { ++ rc_typed_value_t result; ++ int valid = rc_evaluate_value_typed(self, &result, peek, ud); ++ ++ (void)unused_L; ++ ++ if (valid) { ++ /* if not paused, store the value so that it's available when paused. */ ++ rc_typed_value_convert(&result, RC_VALUE_TYPE_UNSIGNED); ++ rc_update_memref_value(&self->value, result.value.u32); ++ } ++ else { ++ /* when paused, the Measured value will not be captured, use the last captured value. */ ++ result.value.u32 = self->value.value; ++ result.type = RC_VALUE_TYPE_UNSIGNED; ++ } ++ ++ rc_typed_value_convert(&result, RC_VALUE_TYPE_SIGNED); ++ return result.value.i32; ++} ++ ++void rc_reset_value(rc_value_t* self) { ++ rc_condset_t* condset = self->conditions; ++ while (condset != NULL) { ++ rc_reset_condset(condset); ++ condset = condset->next; ++ } ++ ++ self->value.value = self->value.prior = 0; ++ self->value.changed = 0; ++} ++ ++int rc_value_from_hits(rc_value_t* self) ++{ ++ rc_condset_t* condset = self->conditions; ++ for (; condset != NULL; condset = condset->next) { ++ rc_condition_t* condition = condset->conditions; ++ for (; condition != NULL; condition = condition->next) { ++ if (condition->type == RC_CONDITION_MEASURED) ++ return (condition->required_hits != 0); ++ } ++ } ++ ++ return 0; ++} ++ ++rc_value_t* rc_alloc_variable(const char* memaddr, size_t memaddr_len, rc_parse_state_t* parse) { ++ rc_value_t** value_ptr = parse->variables; ++ rc_value_t* value; ++ const char* name; ++ uint32_t measured_target; ++ ++ if (!value_ptr) ++ return NULL; ++ ++ while (*value_ptr) { ++ value = *value_ptr; ++ if (strncmp(value->name, memaddr, memaddr_len) == 0 && value->name[memaddr_len] == 0) ++ return value; ++ ++ value_ptr = &value->next; ++ } ++ ++ /* capture name before calling parse as parse will update memaddr pointer */ ++ name = rc_alloc_str(parse, memaddr, memaddr_len); ++ if (!name) ++ return NULL; ++ ++ /* no match found, create a new entry */ ++ value = RC_ALLOC_SCRATCH(rc_value_t, parse); ++ memset(value, 0, sizeof(value->value)); ++ value->value.size = RC_MEMSIZE_VARIABLE; ++ value->next = NULL; ++ ++ /* the helper variable likely has a Measured condition. capture the current measured_target so we can restore it ++ * after generating the variable so the variable's Measured target doesn't conflict with the rest of the trigger. */ ++ measured_target = parse->measured_target; ++ rc_parse_value_internal(value, &memaddr, parse); ++ parse->measured_target = measured_target; ++ ++ /* store name after calling parse as parse will set name to (unnamed) */ ++ value->name = name; ++ ++ *value_ptr = value; ++ return value; ++} ++ ++uint32_t rc_count_values(const rc_value_t* values) { ++ uint32_t count = 0; ++ while (values) { ++ ++count; ++ values = values->next; ++ } ++ ++ return count; ++} ++ ++void rc_update_values(rc_value_t* values, rc_peek_t peek, void* ud) { ++ rc_typed_value_t result; ++ ++ rc_value_t* value = values; ++ for (; value; value = value->next) { ++ if (rc_evaluate_value_typed(value, &result, peek, ud)) { ++ /* store the raw bytes and type to be restored by rc_typed_value_from_memref_value */ ++ rc_update_memref_value(&value->value, result.value.u32); ++ value->value.type = result.type; ++ } ++ } ++} ++ ++void rc_reset_values(rc_value_t* values) { ++ rc_value_t* value = values; ++ ++ for (; value; value = value->next) ++ rc_reset_value(value); ++} ++ ++void rc_typed_value_from_memref_value(rc_typed_value_t* value, const rc_memref_value_t* memref) { ++ /* raw value is always u32, type can mark it as something else */ ++ value->value.u32 = memref->value; ++ value->type = memref->type; ++} ++ ++void rc_typed_value_convert(rc_typed_value_t* value, char new_type) { ++ switch (new_type) { ++ case RC_VALUE_TYPE_UNSIGNED: ++ switch (value->type) { ++ case RC_VALUE_TYPE_UNSIGNED: ++ return; ++ case RC_VALUE_TYPE_SIGNED: ++ value->value.u32 = (unsigned)value->value.i32; ++ break; ++ case RC_VALUE_TYPE_FLOAT: ++ value->value.u32 = (unsigned)value->value.f32; ++ break; ++ default: ++ value->value.u32 = 0; ++ break; ++ } ++ break; ++ ++ case RC_VALUE_TYPE_SIGNED: ++ switch (value->type) { ++ case RC_VALUE_TYPE_SIGNED: ++ return; ++ case RC_VALUE_TYPE_UNSIGNED: ++ value->value.i32 = (int)value->value.u32; ++ break; ++ case RC_VALUE_TYPE_FLOAT: ++ value->value.i32 = (int)value->value.f32; ++ break; ++ default: ++ value->value.i32 = 0; ++ break; ++ } ++ break; ++ ++ case RC_VALUE_TYPE_FLOAT: ++ switch (value->type) { ++ case RC_VALUE_TYPE_FLOAT: ++ return; ++ case RC_VALUE_TYPE_UNSIGNED: ++ value->value.f32 = (float)value->value.u32; ++ break; ++ case RC_VALUE_TYPE_SIGNED: ++ value->value.f32 = (float)value->value.i32; ++ break; ++ default: ++ value->value.f32 = 0.0; ++ break; ++ } ++ break; ++ ++ default: ++ break; ++ } ++ ++ value->type = new_type; ++} ++ ++static rc_typed_value_t* rc_typed_value_convert_into(rc_typed_value_t* dest, const rc_typed_value_t* source, char new_type) { ++ memcpy(dest, source, sizeof(rc_typed_value_t)); ++ rc_typed_value_convert(dest, new_type); ++ return dest; ++} ++ ++void rc_typed_value_negate(rc_typed_value_t* value) { ++ switch (value->type) ++ { ++ case RC_VALUE_TYPE_UNSIGNED: ++ rc_typed_value_convert(value, RC_VALUE_TYPE_SIGNED); ++ /* fallthrough */ /* to RC_VALUE_TYPE_SIGNED */ ++ ++ case RC_VALUE_TYPE_SIGNED: ++ value->value.i32 = -(value->value.i32); ++ break; ++ ++ case RC_VALUE_TYPE_FLOAT: ++ value->value.f32 = -(value->value.f32); ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++void rc_typed_value_add(rc_typed_value_t* value, const rc_typed_value_t* amount) { ++ rc_typed_value_t converted; ++ ++ if (amount->type != value->type && value->type != RC_VALUE_TYPE_NONE) { ++ if (amount->type == RC_VALUE_TYPE_FLOAT) ++ rc_typed_value_convert(value, RC_VALUE_TYPE_FLOAT); ++ else ++ amount = rc_typed_value_convert_into(&converted, amount, value->type); ++ } ++ ++ switch (value->type) ++ { ++ case RC_VALUE_TYPE_UNSIGNED: ++ value->value.u32 += amount->value.u32; ++ break; ++ ++ case RC_VALUE_TYPE_SIGNED: ++ value->value.i32 += amount->value.i32; ++ break; ++ ++ case RC_VALUE_TYPE_FLOAT: ++ value->value.f32 += amount->value.f32; ++ break; ++ ++ case RC_VALUE_TYPE_NONE: ++ memcpy(value, amount, sizeof(rc_typed_value_t)); ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++void rc_typed_value_multiply(rc_typed_value_t* value, const rc_typed_value_t* amount) { ++ rc_typed_value_t converted; ++ ++ switch (value->type) ++ { ++ case RC_VALUE_TYPE_UNSIGNED: ++ switch (amount->type) ++ { ++ case RC_VALUE_TYPE_UNSIGNED: ++ /* the c standard for unsigned multiplication is well defined as non-overflowing truncation ++ * to the type's size. this allows negative multiplication through twos-complements. i.e. ++ * 1 * -1 (0xFFFFFFFF) = 0xFFFFFFFF = -1 ++ * 3 * -2 (0xFFFFFFFE) = 0x2FFFFFFFA & 0xFFFFFFFF = 0xFFFFFFFA = -6 ++ * 10 * -5 (0xFFFFFFFB) = 0x9FFFFFFCE & 0xFFFFFFFF = 0xFFFFFFCE = -50 ++ */ ++ value->value.u32 *= amount->value.u32; ++ break; ++ ++ case RC_VALUE_TYPE_SIGNED: ++ value->value.u32 *= (unsigned)amount->value.i32; ++ break; ++ ++ case RC_VALUE_TYPE_FLOAT: ++ rc_typed_value_convert(value, RC_VALUE_TYPE_FLOAT); ++ value->value.f32 *= amount->value.f32; ++ break; ++ ++ default: ++ value->type = RC_VALUE_TYPE_NONE; ++ break; ++ } ++ break; ++ ++ case RC_VALUE_TYPE_SIGNED: ++ switch (amount->type) ++ { ++ case RC_VALUE_TYPE_SIGNED: ++ value->value.i32 *= amount->value.i32; ++ break; ++ ++ case RC_VALUE_TYPE_UNSIGNED: ++ value->value.i32 *= (int)amount->value.u32; ++ break; ++ ++ case RC_VALUE_TYPE_FLOAT: ++ rc_typed_value_convert(value, RC_VALUE_TYPE_FLOAT); ++ value->value.f32 *= amount->value.f32; ++ break; ++ ++ default: ++ value->type = RC_VALUE_TYPE_NONE; ++ break; ++ } ++ break; ++ ++ case RC_VALUE_TYPE_FLOAT: ++ if (amount->type == RC_VALUE_TYPE_NONE) { ++ value->type = RC_VALUE_TYPE_NONE; ++ } ++ else { ++ amount = rc_typed_value_convert_into(&converted, amount, RC_VALUE_TYPE_FLOAT); ++ value->value.f32 *= amount->value.f32; ++ } ++ break; ++ ++ default: ++ value->type = RC_VALUE_TYPE_NONE; ++ break; ++ } ++} ++ ++void rc_typed_value_divide(rc_typed_value_t* value, const rc_typed_value_t* amount) { ++ rc_typed_value_t converted; ++ ++ switch (amount->type) ++ { ++ case RC_VALUE_TYPE_UNSIGNED: ++ if (amount->value.u32 == 0) { /* divide by zero */ ++ value->type = RC_VALUE_TYPE_NONE; ++ return; ++ } ++ ++ switch (value->type) { ++ case RC_VALUE_TYPE_UNSIGNED: /* integer math */ ++ value->value.u32 /= amount->value.u32; ++ return; ++ case RC_VALUE_TYPE_SIGNED: /* integer math */ ++ value->value.i32 /= (int)amount->value.u32; ++ return; ++ case RC_VALUE_TYPE_FLOAT: ++ amount = rc_typed_value_convert_into(&converted, amount, RC_VALUE_TYPE_FLOAT); ++ break; ++ default: ++ value->type = RC_VALUE_TYPE_NONE; ++ return; ++ } ++ break; ++ ++ case RC_VALUE_TYPE_SIGNED: ++ if (amount->value.i32 == 0) { /* divide by zero */ ++ value->type = RC_VALUE_TYPE_NONE; ++ return; ++ } ++ ++ switch (value->type) { ++ case RC_VALUE_TYPE_SIGNED: /* integer math */ ++ value->value.i32 /= amount->value.i32; ++ return; ++ case RC_VALUE_TYPE_UNSIGNED: /* integer math */ ++ value->value.u32 /= (unsigned)amount->value.i32; ++ return; ++ case RC_VALUE_TYPE_FLOAT: ++ amount = rc_typed_value_convert_into(&converted, amount, RC_VALUE_TYPE_FLOAT); ++ break; ++ default: ++ value->type = RC_VALUE_TYPE_NONE; ++ return; ++ } ++ break; ++ ++ case RC_VALUE_TYPE_FLOAT: ++ break; ++ ++ default: ++ value->type = RC_VALUE_TYPE_NONE; ++ return; ++ } ++ ++ if (amount->value.f32 == 0.0) { /* divide by zero */ ++ value->type = RC_VALUE_TYPE_NONE; ++ return; ++ } ++ ++ rc_typed_value_convert(value, RC_VALUE_TYPE_FLOAT); ++ value->value.f32 /= amount->value.f32; ++} ++ ++void rc_typed_value_modulus(rc_typed_value_t* value, const rc_typed_value_t* amount) { ++ rc_typed_value_t converted; ++ ++ switch (amount->type) ++ { ++ case RC_VALUE_TYPE_UNSIGNED: ++ if (amount->value.u32 == 0) { /* divide by zero */ ++ value->type = RC_VALUE_TYPE_NONE; ++ return; ++ } ++ ++ switch (value->type) { ++ case RC_VALUE_TYPE_UNSIGNED: /* integer math */ ++ value->value.u32 %= amount->value.u32; ++ return; ++ case RC_VALUE_TYPE_SIGNED: /* integer math */ ++ value->value.i32 %= (int)amount->value.u32; ++ return; ++ case RC_VALUE_TYPE_FLOAT: ++ amount = rc_typed_value_convert_into(&converted, amount, RC_VALUE_TYPE_FLOAT); ++ break; ++ default: ++ value->type = RC_VALUE_TYPE_NONE; ++ return; ++ } ++ break; ++ ++ case RC_VALUE_TYPE_SIGNED: ++ if (amount->value.i32 == 0) { /* divide by zero */ ++ value->type = RC_VALUE_TYPE_NONE; ++ return; ++ } ++ ++ switch (value->type) { ++ case RC_VALUE_TYPE_SIGNED: /* integer math */ ++ value->value.i32 %= amount->value.i32; ++ return; ++ case RC_VALUE_TYPE_UNSIGNED: /* integer math */ ++ value->value.u32 %= (unsigned)amount->value.i32; ++ return; ++ case RC_VALUE_TYPE_FLOAT: ++ amount = rc_typed_value_convert_into(&converted, amount, RC_VALUE_TYPE_FLOAT); ++ break; ++ default: ++ value->type = RC_VALUE_TYPE_NONE; ++ return; ++ } ++ break; ++ ++ case RC_VALUE_TYPE_FLOAT: ++ break; ++ ++ default: ++ value->type = RC_VALUE_TYPE_NONE; ++ return; ++ } ++ ++ if (amount->value.f32 == 0.0) { /* divide by zero */ ++ value->type = RC_VALUE_TYPE_NONE; ++ return; ++ } ++ ++ rc_typed_value_convert(value, RC_VALUE_TYPE_FLOAT); ++ value->value.f32 = (float)fmod(value->value.f32, amount->value.f32); ++} ++ ++void rc_typed_value_combine(rc_typed_value_t* value, rc_typed_value_t* amount, uint8_t oper) { ++ switch (oper) { ++ case RC_OPERATOR_MULT: ++ rc_typed_value_multiply(value, amount); ++ break; ++ ++ case RC_OPERATOR_DIV: ++ rc_typed_value_divide(value, amount); ++ break; ++ ++ case RC_OPERATOR_AND: ++ rc_typed_value_convert(value, RC_VALUE_TYPE_UNSIGNED); ++ rc_typed_value_convert(amount, RC_VALUE_TYPE_UNSIGNED); ++ value->value.u32 &= amount->value.u32; ++ break; ++ ++ case RC_OPERATOR_XOR: ++ rc_typed_value_convert(value, RC_VALUE_TYPE_UNSIGNED); ++ rc_typed_value_convert(amount, RC_VALUE_TYPE_UNSIGNED); ++ value->value.u32 ^= amount->value.u32; ++ break; ++ ++ case RC_OPERATOR_MOD: ++ rc_typed_value_modulus(value, amount); ++ break; ++ ++ case RC_OPERATOR_ADD: ++ rc_typed_value_add(value, amount); ++ break; ++ ++ case RC_OPERATOR_SUB: ++ rc_typed_value_negate(amount); ++ rc_typed_value_add(value, amount); ++ break; ++ } ++} ++ ++ ++static int rc_typed_value_compare_floats(float f1, float f2, char oper) { ++ if (f1 == f2) { ++ /* exactly equal */ ++ } ++ else { ++ /* attempt to match 7 significant digits (24-bit mantissa supports just over 7 significant decimal digits) */ ++ /* https://stackoverflow.com/questions/17333/what-is-the-most-effective-way-for-float-and-double-comparison */ ++ const float abs1 = (f1 < 0) ? -f1 : f1; ++ const float abs2 = (f2 < 0) ? -f2 : f2; ++ const float threshold = ((abs1 < abs2) ? abs1 : abs2) * FLT_EPSILON; ++ const float diff = f1 - f2; ++ const float abs_diff = (diff < 0) ? -diff : diff; ++ ++ if (abs_diff <= threshold) { ++ /* approximately equal */ ++ } ++ else if (diff > threshold) { ++ /* greater */ ++ switch (oper) { ++ case RC_OPERATOR_NE: ++ case RC_OPERATOR_GT: ++ case RC_OPERATOR_GE: ++ return 1; ++ ++ default: ++ return 0; ++ } ++ } ++ else { ++ /* lesser */ ++ switch (oper) { ++ case RC_OPERATOR_NE: ++ case RC_OPERATOR_LT: ++ case RC_OPERATOR_LE: ++ return 1; ++ ++ default: ++ return 0; ++ } ++ } ++ } ++ ++ /* exactly or approximately equal */ ++ switch (oper) { ++ case RC_OPERATOR_EQ: ++ case RC_OPERATOR_GE: ++ case RC_OPERATOR_LE: ++ return 1; ++ ++ default: ++ return 0; ++ } ++} ++ ++int rc_typed_value_compare(const rc_typed_value_t* value1, const rc_typed_value_t* value2, char oper) { ++ rc_typed_value_t converted_value; ++ if (value2->type != value1->type) { ++ /* if either side is a float, convert both sides to float. otherwise, assume the signed-ness of the left side. */ ++ if (value2->type == RC_VALUE_TYPE_FLOAT) ++ value1 = rc_typed_value_convert_into(&converted_value, value1, value2->type); ++ else ++ value2 = rc_typed_value_convert_into(&converted_value, value2, value1->type); ++ } ++ ++ switch (value1->type) { ++ case RC_VALUE_TYPE_UNSIGNED: ++ switch (oper) { ++ case RC_OPERATOR_EQ: return value1->value.u32 == value2->value.u32; ++ case RC_OPERATOR_NE: return value1->value.u32 != value2->value.u32; ++ case RC_OPERATOR_LT: return value1->value.u32 < value2->value.u32; ++ case RC_OPERATOR_LE: return value1->value.u32 <= value2->value.u32; ++ case RC_OPERATOR_GT: return value1->value.u32 > value2->value.u32; ++ case RC_OPERATOR_GE: return value1->value.u32 >= value2->value.u32; ++ default: return 1; ++ } ++ ++ case RC_VALUE_TYPE_SIGNED: ++ switch (oper) { ++ case RC_OPERATOR_EQ: return value1->value.i32 == value2->value.i32; ++ case RC_OPERATOR_NE: return value1->value.i32 != value2->value.i32; ++ case RC_OPERATOR_LT: return value1->value.i32 < value2->value.i32; ++ case RC_OPERATOR_LE: return value1->value.i32 <= value2->value.i32; ++ case RC_OPERATOR_GT: return value1->value.i32 > value2->value.i32; ++ case RC_OPERATOR_GE: return value1->value.i32 >= value2->value.i32; ++ default: return 1; ++ } ++ ++ case RC_VALUE_TYPE_FLOAT: ++ return rc_typed_value_compare_floats(value1->value.f32, value2->value.f32, oper); ++ ++ default: ++ return 1; ++ } ++} +diff -rupbN melonDS.orig/src/rcheevos/src/rhash/aes.h melonDS.ra/src/rcheevos/src/rhash/aes.h +--- melonDS.orig/src/rcheevos/src/rhash/aes.h 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rhash/aes.h 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,49 @@ ++#ifndef AES_H ++#define AES_H ++ ++/* This file is sourced from https://github.com/kokke/tiny-AES-c, with unused code excised. ++ * This code is licensed under the Unlicense license, effectively public domain. ++ * https://github.com/kokke/tiny-AES-c/blob/f06ac37/unlicense.txt ++ */ ++ ++#include ++#include ++ ++#define AES_BLOCKLEN 16 /* Block length in bytes - AES is 128b block only */ ++#define AES_KEYLEN 16 /* Key length in bytes */ ++#define AES_keyExpSize 176 ++ ++struct AES_ctx ++{ ++ uint8_t RoundKey[AES_keyExpSize]; ++ uint8_t Iv[AES_BLOCKLEN]; ++}; ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++void AES_init_ctx(struct AES_ctx* ctx, const uint8_t key[AES_KEYLEN]); ++void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t key[AES_KEYLEN], const uint8_t iv[AES_BLOCKLEN]); ++void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t iv[AES_BLOCKLEN]); ++ ++/* buffer size MUST be mutile of AES_BLOCKLEN; ++ * Suggest https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme ++ * NOTES: you need to set IV in ctx via AES_init_ctx_iv() or AES_ctx_set_iv() ++ * no IV should ever be reused with the same key ++ */ ++void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length); ++ ++/* Same function for encrypting as for decrypting. ++ * IV is incremented for every block, and used after encryption as XOR-compliment for output ++ * Suggesting https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme ++ * NOTES: you need to set IV in ctx with AES_init_ctx_iv() or AES_ctx_set_iv() ++ * no IV should ever be reused with the same key ++ */ ++void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* AES_H */ +diff -rupbN melonDS.orig/src/rcheevos/src/rhash/cdreader.c melonDS.ra/src/rcheevos/src/rhash/cdreader.c +--- melonDS.orig/src/rcheevos/src/rhash/cdreader.c 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rhash/cdreader.c 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,838 @@ ++#include "rc_hash_internal.h" ++ ++#include "../rc_compat.h" ++ ++#include ++#include ++#include ++ ++static int cdreader_get_sector(uint8_t header[16]) ++{ ++ int minutes = (header[12] >> 4) * 10 + (header[12] & 0x0F); ++ int seconds = (header[13] >> 4) * 10 + (header[13] & 0x0F); ++ int frames = (header[14] >> 4) * 10 + (header[14] & 0x0F); ++ ++ /* convert the MSF value to a sector index, and subtract 150 (2 seconds) per: ++ * For data and mixed mode media (those conforming to ISO/IEC 10149), logical block address ++ * zero shall be assigned to the block at MSF address 00/02/00 */ ++ return ((minutes * 60) + seconds) * 75 + frames - 150; ++} ++ ++static void cdreader_determine_sector_size(rc_hash_cdrom_track_t* cdrom) ++{ ++ /* Attempt to determine the sector and header sizes. The CUE file may be lying. ++ * Look for the sync pattern using each of the supported sector sizes. ++ * Then check for the presence of "CD001", which is gauranteed to be in either the ++ * boot record or primary volume descriptor, one of which is always at sector 16. ++ */ ++ const uint8_t sync_pattern[] = { ++ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00 ++ }; ++ ++ uint8_t header[32]; ++ const int64_t toc_sector = 16 + cdrom->track_pregap_sectors; ++ ++ cdrom->sector_size = 0; ++ cdrom->sector_header_size = 0; ++ cdrom->raw_data_size = 2048; ++ ++ cdrom->file_reader->seek(cdrom->file_handle, toc_sector * 2352 + cdrom->file_track_offset, SEEK_SET); ++ if (cdrom->file_reader->read(cdrom->file_handle, header, sizeof(header)) < sizeof(header)) ++ return; ++ ++ if (memcmp(header, sync_pattern, 12) == 0) ++ { ++ cdrom->sector_size = 2352; ++ ++ if (memcmp(&header[25], "CD001", 5) == 0) ++ cdrom->sector_header_size = 24; ++ else ++ cdrom->sector_header_size = 16; ++ ++ cdrom->track_first_sector = cdreader_get_sector(header) - (int)toc_sector; ++ } ++ else ++ { ++ cdrom->file_reader->seek(cdrom->file_handle, toc_sector * 2336 + cdrom->file_track_offset, SEEK_SET); ++ cdrom->file_reader->read(cdrom->file_handle, header, sizeof(header)); ++ ++ if (memcmp(header, sync_pattern, 12) == 0) ++ { ++ cdrom->sector_size = 2336; ++ ++ if (memcmp(&header[25], "CD001", 5) == 0) ++ cdrom->sector_header_size = 24; ++ else ++ cdrom->sector_header_size = 16; ++ ++ cdrom->track_first_sector = cdreader_get_sector(header) - (int)toc_sector; ++ } ++ else ++ { ++ cdrom->file_reader->seek(cdrom->file_handle, toc_sector * 2048 + cdrom->file_track_offset, SEEK_SET); ++ cdrom->file_reader->read(cdrom->file_handle, header, sizeof(header)); ++ ++ if (memcmp(&header[1], "CD001", 5) == 0) ++ { ++ cdrom->sector_size = 2048; ++ cdrom->sector_header_size = 0; ++ } ++ } ++ } ++} ++ ++static void* cdreader_open_bin_track(const char* path, uint32_t track, const rc_hash_iterator_t* iterator) ++{ ++ void* file_handle; ++ rc_hash_cdrom_track_t* cdrom; ++ ++ if (track > 1) { ++ rc_hash_iterator_verbose(iterator, "Cannot locate secondary tracks without a cue sheet"); ++ return NULL; ++ } ++ ++ file_handle = iterator->callbacks.filereader.open(path); ++ if (!file_handle) ++ return NULL; ++ ++ cdrom = (rc_hash_cdrom_track_t*)calloc(1, sizeof(*cdrom)); ++ if (!cdrom) ++ return NULL; ++ cdrom->file_reader = &iterator->callbacks.filereader; ++ cdrom->file_handle = file_handle; ++#ifndef NDEBUG ++ cdrom->track_id = track; ++#endif ++ ++ cdreader_determine_sector_size(cdrom); ++ ++ if (cdrom->sector_size == 0) ++ { ++ int64_t size; ++ ++ iterator->callbacks.filereader.seek(file_handle, 0, SEEK_END); ++ size = iterator->callbacks.filereader.tell(file_handle); ++ ++ if ((size % 2352) == 0) ++ { ++ /* raw tracks use all 2352 bytes and have a 24 byte header */ ++ cdrom->sector_size = 2352; ++ cdrom->sector_header_size = 24; ++ } ++ else if ((size % 2048) == 0) ++ { ++ /* cooked tracks eliminate all header/footer data */ ++ cdrom->sector_size = 2048; ++ cdrom->sector_header_size = 0; ++ } ++ else if ((size % 2336) == 0) ++ { ++ /* MODE 2 format without 16-byte sync data */ ++ cdrom->sector_size = 2336; ++ cdrom->sector_header_size = 8; ++ } ++ else ++ { ++ if (iterator->callbacks.filereader.close) ++ iterator->callbacks.filereader.close(file_handle); ++ free(cdrom); ++ ++ rc_hash_iterator_verbose(iterator, "Could not determine sector size"); ++ ++ return NULL; ++ } ++ } ++ ++ return cdrom; ++} ++ ++static int cdreader_open_bin(rc_hash_cdrom_track_t* cdrom, const char* path, const char* mode) ++{ ++ cdrom->file_handle = cdrom->file_reader->open(path); ++ if (!cdrom->file_handle) ++ return 0; ++ ++ /* determine sector size */ ++ cdreader_determine_sector_size(cdrom); ++ ++ /* could not determine, which means we'll probably have more issues later ++ * but use the CUE provided information anyway ++ */ ++ if (cdrom->sector_size == 0) ++ { ++ /* All of these modes have 2048 byte payloads. In MODE1/2352 and MODE2/2352 ++ * modes, the mode can actually be specified per sector to change the payload ++ * size, but that reduces the ability to recover from errors when the disc ++ * is damaged, so it's seldomly used, and when it is, it's mostly for audio ++ * or video data where a blip or two probably won't be noticed by the user. ++ * So, while we techincally support all of the following modes, we only do ++ * so with 2048 byte payloads. ++ * http://totalsonicmastering.com/cuesheetsyntax.htm ++ * MODE1/2048 ? CDROM Mode1 Data (cooked) [no header, no footer] ++ * MODE1/2352 ? CDROM Mode1 Data (raw) [16 byte header, 288 byte footer] ++ * MODE2/2336 ? CDROM-XA Mode2 Data [8 byte header, 280 byte footer] ++ * MODE2/2352 ? CDROM-XA Mode2 Data [24 byte header, 280 byte footer] ++ */ ++ if (memcmp(mode, "MODE2/2352", 10) == 0) ++ { ++ cdrom->sector_size = 2352; ++ cdrom->sector_header_size = 24; ++ } ++ else if (memcmp(mode, "MODE1/2048", 10) == 0) ++ { ++ cdrom->sector_size = 2048; ++ cdrom->sector_header_size = 0; ++ } ++ else if (memcmp(mode, "MODE2/2336", 10) == 0) ++ { ++ cdrom->sector_size = 2336; ++ cdrom->sector_header_size = 8; ++ } ++ else if (memcmp(mode, "MODE1/2352", 10) == 0) ++ { ++ cdrom->sector_size = 2352; ++ cdrom->sector_header_size = 16; ++ } ++ else if (memcmp(mode, "AUDIO", 5) == 0) ++ { ++ cdrom->sector_size = 2352; ++ cdrom->sector_header_size = 0; ++ cdrom->raw_data_size = 2352; /* no header or footer data on audio tracks */ ++ } ++ } ++ ++ return (cdrom->sector_size != 0); ++} ++ ++static char* cdreader_get_bin_path(const char* cue_path, const char* bin_name, const rc_hash_iterator_t* iterator) ++{ ++ const char* filename = rc_path_get_filename(cue_path); ++ const size_t bin_name_len = strlen(bin_name); ++ const size_t cue_path_len = filename - cue_path; ++ const size_t needed = cue_path_len + bin_name_len + 1; ++ ++ char* bin_filename = (char*)malloc(needed); ++ if (!bin_filename) ++ { ++ rc_hash_iterator_error_formatted(iterator, "Failed to allocate %u bytes", (unsigned)needed); ++ } ++ else ++ { ++ memcpy(bin_filename, cue_path, cue_path_len); ++ memcpy(bin_filename + cue_path_len, bin_name, bin_name_len + 1); ++ } ++ ++ return bin_filename; ++} ++ ++static int64_t cdreader_get_bin_size(const char* cue_path, const char* bin_name, const rc_hash_iterator_t* iterator) ++{ ++ int64_t size = 0; ++ char* bin_filename = cdreader_get_bin_path(cue_path, bin_name, iterator); ++ if (bin_filename) ++ { ++ void* handle = iterator->callbacks.filereader.open(bin_filename); ++ if (handle) ++ { ++ iterator->callbacks.filereader.seek(handle, 0, SEEK_END); ++ size = iterator->callbacks.filereader.tell(handle); ++ ++ if (iterator->callbacks.filereader.close) ++ iterator->callbacks.filereader.close(handle); ++ } ++ ++ free(bin_filename); ++ } ++ ++ return size; ++} ++ ++static void* cdreader_open_cue_track(const char* path, uint32_t track, const rc_hash_iterator_t* iterator) ++{ ++ void* cue_handle; ++ int64_t cue_offset = 0; ++ char buffer[1024]; ++ char* bin_filename = NULL; ++ char *ptr, *ptr2, *end; ++ int done = 0; ++ int session = 1; ++ size_t num_read = 0; ++ rc_hash_cdrom_track_t* cdrom = NULL; ++ ++ struct track_t ++ { ++ uint32_t id; ++ int sector_size; ++ int sector_count; ++ int first_sector; ++ int pregap_sectors; ++ int is_data; ++ int file_track_offset; ++ int file_first_sector; ++ char mode[16]; ++ char filename[256]; ++ } current_track, previous_track, largest_track; ++ ++ cue_handle = iterator->callbacks.filereader.open(path); ++ if (!cue_handle) ++ return NULL; ++ ++ memset(¤t_track, 0, sizeof(current_track)); ++ memset(&previous_track, 0, sizeof(previous_track)); ++ memset(&largest_track, 0, sizeof(largest_track)); ++ ++ do ++ { ++ num_read = iterator->callbacks.filereader.read(cue_handle, buffer, sizeof(buffer) - 1); ++ if (num_read == 0) ++ break; ++ ++ buffer[num_read] = 0; ++ if (num_read == sizeof(buffer) - 1) ++ end = buffer + sizeof(buffer) * 3 / 4; ++ else ++ end = buffer + num_read; ++ ++ for (ptr = buffer; ptr < end; ++ptr) ++ { ++ while (*ptr == ' ') ++ ++ptr; ++ ++ if (strncasecmp(ptr, "INDEX ", 6) == 0) ++ { ++ int m = 0, s = 0, f = 0; ++ int index; ++ int sector_offset; ++ ++ ptr += 6; ++ index = atoi(ptr); ++ ++ while (*ptr != ' ' && *ptr != '\n') ++ ++ptr; ++ while (*ptr == ' ') ++ ++ptr; ++ ++ /* convert mm:ss:ff to sector count */ ++ sscanf_s(ptr, "%d:%d:%d", &m, &s, &f); ++ sector_offset = ((m * 60) + s) * 75 + f; ++ ++ if (current_track.first_sector == -1) ++ { ++ current_track.first_sector = sector_offset; ++ if (strcmp(current_track.filename, previous_track.filename) == 0) ++ { ++ previous_track.sector_count = current_track.first_sector - previous_track.first_sector; ++ current_track.file_track_offset += previous_track.sector_count * previous_track.sector_size; ++ } ++ ++ /* if looking for the largest data track, determine previous track size */ ++ if (track == RC_HASH_CDTRACK_LARGEST && previous_track.sector_count > largest_track.sector_count && ++ previous_track.is_data) ++ { ++ memcpy(&largest_track, &previous_track, sizeof(largest_track)); ++ } ++ } ++ ++ if (index == 1) ++ { ++ current_track.pregap_sectors = (sector_offset - current_track.first_sector); ++ ++ { ++ char* scan = current_track.mode; ++ while (*scan && !isspace((unsigned char)*scan)) ++ ++scan; ++ *scan = '\0'; ++ ++ /* it's undesirable to truncate offset to 32-bits, but %lld isn't defined in c89. */ ++ rc_hash_iterator_verbose_formatted(iterator, "Found %s track %d (first sector %d, sector size %d, %d pregap sectors)", ++ current_track.mode, current_track.id, current_track.first_sector, current_track.sector_size, current_track.pregap_sectors); ++ } ++ ++ if (current_track.id == track) ++ { ++ done = 1; ++ break; ++ } ++ ++ if (track == RC_HASH_CDTRACK_FIRST_DATA && current_track.is_data) ++ { ++ track = current_track.id; ++ done = 1; ++ break; ++ } ++ ++ if (track == RC_HASH_CDTRACK_FIRST_OF_SECOND_SESSION && session == 2) ++ { ++ track = current_track.id; ++ done = 1; ++ break; ++ } ++ } ++ } ++ else if (strncasecmp(ptr, "TRACK ", 6) == 0) ++ { ++ if (current_track.sector_size) ++ memcpy(&previous_track, ¤t_track, sizeof(current_track)); ++ ++ ptr += 6; ++ current_track.id = atoi(ptr); ++ ++ current_track.pregap_sectors = -1; ++ current_track.first_sector = -1; ++ ++ while (*ptr != ' ') ++ ++ptr; ++ while (*ptr == ' ') ++ ++ptr; ++ memcpy(current_track.mode, ptr, sizeof(current_track.mode)); ++ current_track.is_data = (memcmp(current_track.mode, "MODE", 4) == 0); ++ ++ if (current_track.is_data) ++ { ++ current_track.sector_size = atoi(ptr + 6); ++ } ++ else ++ { ++ /* assume AUDIO */ ++ current_track.sector_size = 2352; ++ } ++ } ++ else if (strncasecmp(ptr, "FILE ", 5) == 0) ++ { ++ if (current_track.sector_size) ++ { ++ memcpy(&previous_track, ¤t_track, sizeof(previous_track)); ++ ++ if (previous_track.sector_count == 0) ++ { ++ const int64_t bin_size = cdreader_get_bin_size(path, previous_track.filename, iterator); ++ const uint32_t file_sector_count = (uint32_t)bin_size / previous_track.sector_size; ++ previous_track.sector_count = file_sector_count - previous_track.first_sector; ++ } ++ ++ /* if looking for the largest data track, check to see if this one is larger */ ++ if (track == RC_HASH_CDTRACK_LARGEST && previous_track.is_data && ++ previous_track.sector_count > largest_track.sector_count) ++ { ++ memcpy(&largest_track, &previous_track, sizeof(largest_track)); ++ } ++ } ++ ++ memset(¤t_track, 0, sizeof(current_track)); ++ ++ current_track.file_first_sector = previous_track.file_first_sector + ++ previous_track.first_sector + previous_track.sector_count; ++ ++ ptr += 5; ++ ptr2 = ptr; ++ if (*ptr == '"') ++ { ++ ++ptr; ++ do ++ { ++ ++ptr2; ++ } while (*ptr2 && *ptr2 != '\n' && *ptr2 != '"'); ++ } ++ else ++ { ++ do ++ { ++ ++ptr2; ++ } while (*ptr2 && *ptr2 != '\n' && *ptr2 != ' '); ++ } ++ ++ if (ptr2 - ptr < (int)sizeof(current_track.filename)) ++ memcpy(current_track.filename, ptr, ptr2 - ptr); ++ } ++ else if (strncasecmp(ptr, "REM ", 4) == 0) ++ { ++ ptr += 4; ++ while (*ptr == ' ') ++ ++ptr; ++ ++ if (strncasecmp(ptr, "SESSION ", 8) == 0) ++ { ++ ptr += 8; ++ while (*ptr == ' ') ++ ++ptr; ++ session = atoi(ptr); ++ } ++ } ++ ++ while (*ptr && *ptr != '\n') ++ ++ptr; ++ } ++ ++ if (done) ++ break; ++ ++ cue_offset += (ptr - buffer); ++ iterator->callbacks.filereader.seek(cue_handle, cue_offset, SEEK_SET); ++ ++ } while (1); ++ ++ if (iterator->callbacks.filereader.close) ++ iterator->callbacks.filereader.close(cue_handle); ++ ++ if (track == RC_HASH_CDTRACK_LARGEST) ++ { ++ if (current_track.sector_size && current_track.is_data) ++ { ++ const int64_t bin_size = cdreader_get_bin_size(path, current_track.filename, iterator); ++ const uint32_t file_sector_count = (uint32_t)bin_size / current_track.sector_size; ++ current_track.sector_count = file_sector_count - current_track.first_sector; ++ ++ if (largest_track.sector_count > current_track.sector_count) ++ memcpy(¤t_track, &largest_track, sizeof(current_track)); ++ } ++ else ++ { ++ memcpy(¤t_track, &largest_track, sizeof(current_track)); ++ } ++ ++ track = current_track.id; ++ } ++ else if (track == RC_HASH_CDTRACK_LAST && !done) ++ { ++ track = current_track.id; ++ } ++ ++ if (current_track.id == track) ++ { ++ cdrom = (rc_hash_cdrom_track_t*)calloc(1, sizeof(*cdrom)); ++ if (!cdrom) ++ { ++ rc_hash_iterator_error_formatted(iterator, "Failed to allocate %u bytes", (unsigned)sizeof(*cdrom)); ++ return NULL; ++ } ++ ++ cdrom->file_reader = &iterator->callbacks.filereader; ++ cdrom->file_track_offset = current_track.file_track_offset; ++ cdrom->track_pregap_sectors = current_track.pregap_sectors; ++ cdrom->track_first_sector = current_track.file_first_sector + current_track.first_sector; ++#ifndef NDEBUG ++ cdrom->track_id = current_track.id; ++#endif ++ ++ /* verify existance of bin file */ ++ bin_filename = cdreader_get_bin_path(path, current_track.filename, iterator); ++ if (bin_filename) ++ { ++ if (cdreader_open_bin(cdrom, bin_filename, current_track.mode)) ++ { ++ if (cdrom->track_pregap_sectors) ++ rc_hash_iterator_verbose_formatted(iterator, "Opened track %d (sector size %d, %d pregap sectors)", ++ track, cdrom->sector_size, cdrom->track_pregap_sectors); ++ else ++ rc_hash_iterator_verbose_formatted(iterator, "Opened track %d (sector size %d)", track, cdrom->sector_size); ++ } ++ else ++ { ++ if (cdrom->file_handle) ++ { ++ cdrom->file_reader->close(cdrom->file_handle); ++ rc_hash_iterator_error_formatted(iterator, "Could not determine sector size for %s track", current_track.mode); ++ } ++ else ++ { ++ rc_hash_iterator_error_formatted(iterator, "Could not open %s", bin_filename); ++ } ++ ++ free(cdrom); ++ cdrom = NULL; ++ } ++ ++ free(bin_filename); ++ } ++ } ++ ++ return cdrom; ++} ++ ++static void* cdreader_open_gdi_track(const char* path, uint32_t track, const rc_hash_iterator_t* iterator) ++{ ++ void* file_handle; ++ char buffer[1024]; ++ char mode[16] = "MODE1/"; ++ char sector_size[16]; ++ char file[256]; ++ int64_t track_size; ++ int track_type; ++ char* bin_path = NULL; ++ uint32_t current_track = 0; ++ char* ptr, *ptr2, *end; ++ int lba = 0; ++ ++ uint32_t largest_track = 0; ++ int64_t largest_track_size = 0; ++ char largest_track_file[256]; ++ char largest_track_sector_size[16]; ++ int largest_track_lba = 0; ++ ++ int found = 0; ++ size_t num_read = 0; ++ int64_t file_offset = 0; ++ rc_hash_cdrom_track_t* cdrom = NULL; ++ ++ file_handle = iterator->callbacks.filereader.open(path); ++ if (!file_handle) ++ return NULL; ++ ++ file[0] = '\0'; ++ do ++ { ++ num_read = iterator->callbacks.filereader.read(file_handle, buffer, sizeof(buffer) - 1); ++ if (num_read == 0) ++ break; ++ ++ buffer[num_read] = 0; ++ if (num_read == sizeof(buffer) - 1) ++ end = buffer + sizeof(buffer) * 3 / 4; ++ else ++ end = buffer + num_read; ++ ++ ptr = buffer; ++ ++ /* the first line contains the number of tracks, so we can get the last track index from it */ ++ if (track == RC_HASH_CDTRACK_LAST) ++ track = atoi(ptr); ++ ++ /* first line contains the number of tracks and will be skipped */ ++ while (ptr < end) ++ { ++ /* skip until next newline */ ++ while (*ptr != '\n' && ptr < end) ++ ++ptr; ++ ++ /* skip newlines */ ++ while ((*ptr == '\n' || *ptr == '\r') && ptr < end) ++ ++ptr; ++ ++ /* line format: [trackid] [lba] [type] [sectorsize] [file] [?] */ ++ while (isspace((unsigned char)*ptr)) ++ ++ptr; ++ ++ current_track = (uint32_t)atoi(ptr); ++ if (track && current_track != track && track != RC_HASH_CDTRACK_FIRST_DATA) ++ continue; ++ ++ while (isdigit((unsigned char)*ptr)) ++ ++ptr; ++ ++ptr; ++ ++ while (isspace((unsigned char)*ptr)) ++ ++ptr; ++ ++ lba = atoi(ptr); ++ while (isdigit((unsigned char)*ptr)) ++ ++ptr; ++ ++ptr; ++ ++ while (isspace((unsigned char)*ptr)) ++ ++ptr; ++ ++ track_type = atoi(ptr); ++ while (isdigit((unsigned char)*ptr)) ++ ++ptr; ++ ++ptr; ++ ++ while (isspace((unsigned char)*ptr)) ++ ++ptr; ++ ++ ptr2 = sector_size; ++ while (isdigit((unsigned char)*ptr)) ++ *ptr2++ = *ptr++; ++ *ptr2 = '\0'; ++ ++ptr; ++ ++ while (isspace((unsigned char)*ptr)) ++ ++ptr; ++ ++ ptr2 = file; ++ if (*ptr == '\"') ++ { ++ ++ptr; ++ while (*ptr != '\"') ++ *ptr2++ = *ptr++; ++ ++ptr; ++ } ++ else ++ { ++ while (*ptr != ' ') ++ *ptr2++ = *ptr++; ++ } ++ *ptr2 = '\0'; ++ ++ if (track == current_track) ++ { ++ found = 1; ++ break; ++ } ++ else if (track == RC_HASH_CDTRACK_FIRST_DATA && track_type == 4) ++ { ++ track = current_track; ++ found = 1; ++ break; ++ } ++ else if (track == RC_HASH_CDTRACK_LARGEST && track_type == 4) ++ { ++ track_size = cdreader_get_bin_size(path, file, iterator); ++ if (track_size > largest_track_size) ++ { ++ largest_track_size = track_size; ++ largest_track = current_track; ++ largest_track_lba = lba; ++ strcpy_s(largest_track_file, sizeof(largest_track_file), file); ++ strcpy_s(largest_track_sector_size, sizeof(largest_track_sector_size), sector_size); ++ } ++ } ++ } ++ ++ if (found) ++ break; ++ ++ file_offset += (ptr - buffer); ++ iterator->callbacks.filereader.seek(file_handle, file_offset, SEEK_SET); ++ ++ } while (1); ++ ++ if (iterator->callbacks.filereader.close) ++ iterator->callbacks.filereader.close(file_handle); ++ ++ cdrom = (rc_hash_cdrom_track_t*)calloc(1, sizeof(*cdrom)); ++ if (!cdrom) ++ { ++ rc_hash_iterator_error_formatted(iterator, "Failed to allocate %u bytes", (unsigned)sizeof(*cdrom)); ++ return NULL; ++ } ++ ++ cdrom->file_reader = &iterator->callbacks.filereader; ++ ++ /* if we were tracking the largest track, make it the current track. ++ * otherwise, current_track will be the requested track, or last track. */ ++ if (largest_track != 0 && largest_track != current_track) ++ { ++ current_track = largest_track; ++ strcpy_s(file, sizeof(file), largest_track_file); ++ strcpy_s(sector_size, sizeof(sector_size), largest_track_sector_size); ++ lba = largest_track_lba; ++ } ++ ++ /* open the bin file for the track - construct mode parameter from sector_size */ ++ ptr = &mode[6]; ++ ptr2 = sector_size; ++ while (*ptr2 && *ptr2 != '\"') ++ *ptr++ = *ptr2++; ++ *ptr = '\0'; ++ ++ bin_path = cdreader_get_bin_path(path, file, iterator); ++ if (cdreader_open_bin(cdrom, bin_path, mode)) ++ { ++ cdrom->track_pregap_sectors = 0; ++ cdrom->track_first_sector = lba; ++#ifndef NDEBUG ++ cdrom->track_id = current_track; ++#endif ++ ++ rc_hash_iterator_verbose_formatted(iterator, "Opened track %d (sector size %d)", current_track, cdrom->sector_size); ++ } ++ else ++ { ++ rc_hash_iterator_error_formatted(iterator, "Could not open %s", bin_path); ++ ++ free(cdrom); ++ cdrom = NULL; ++ } ++ ++ free(bin_path); ++ ++ return cdrom; ++} ++ ++static void* cdreader_open_track_iterator(const char* path, uint32_t track, const rc_hash_iterator_t* iterator) ++{ ++ /* backwards compatibility - 0 used to mean largest */ ++ if (track == 0) ++ track = RC_HASH_CDTRACK_LARGEST; ++ ++ if (rc_path_compare_extension(path, "cue")) ++ return cdreader_open_cue_track(path, track, iterator); ++ if (rc_path_compare_extension(path, "gdi")) ++ return cdreader_open_gdi_track(path, track, iterator); ++ ++ return cdreader_open_bin_track(path, track, iterator); ++} ++ ++static size_t cdreader_read_sector(void* track_handle, uint32_t sector, void* buffer, size_t requested_bytes) ++{ ++ int64_t sector_start; ++ size_t num_read, total_read = 0; ++ uint8_t* buffer_ptr = (uint8_t*)buffer; ++ ++ rc_hash_cdrom_track_t* cdrom = (rc_hash_cdrom_track_t*)track_handle; ++ if (!cdrom) ++ return 0; ++ ++ if (sector < (uint32_t)cdrom->track_first_sector) ++ return 0; ++ ++ sector_start = (int64_t)(sector - cdrom->track_first_sector) * cdrom->sector_size + ++ cdrom->sector_header_size + cdrom->file_track_offset; ++ ++ while (requested_bytes > (size_t)cdrom->raw_data_size) ++ { ++ cdrom->file_reader->seek(cdrom->file_handle, sector_start, SEEK_SET); ++ num_read = cdrom->file_reader->read(cdrom->file_handle, buffer_ptr, cdrom->raw_data_size); ++ total_read += num_read; ++ ++ if (num_read < (size_t)cdrom->raw_data_size) ++ return total_read; ++ ++ buffer_ptr += cdrom->raw_data_size; ++ sector_start += cdrom->sector_size; ++ requested_bytes -= cdrom->raw_data_size; ++ } ++ ++ cdrom->file_reader->seek(cdrom->file_handle, sector_start, SEEK_SET); ++ num_read = cdrom->file_reader->read(cdrom->file_handle, buffer_ptr, (int)requested_bytes); ++ total_read += num_read; ++ ++ return total_read; ++} ++ ++static void cdreader_close_track(void* track_handle) ++{ ++ rc_hash_cdrom_track_t* cdrom = (rc_hash_cdrom_track_t*)track_handle; ++ if (cdrom) ++ { ++ if (cdrom->file_handle && cdrom->file_reader->close) ++ cdrom->file_reader->close(cdrom->file_handle); ++ ++ free(track_handle); ++ } ++} ++ ++static uint32_t cdreader_first_track_sector(void* track_handle) ++{ ++ rc_hash_cdrom_track_t* cdrom = (rc_hash_cdrom_track_t*)track_handle; ++ if (cdrom) ++ return cdrom->track_first_sector + cdrom->track_pregap_sectors; ++ ++ return 0; ++} ++ ++void rc_hash_get_default_cdreader(struct rc_hash_cdreader* cdreader) ++{ ++ cdreader->open_track = NULL; ++ cdreader->read_sector = cdreader_read_sector; ++ cdreader->close_track = cdreader_close_track; ++ cdreader->first_track_sector = cdreader_first_track_sector; ++ cdreader->open_track_iterator = cdreader_open_track_iterator; ++} ++ ++void rc_hash_init_default_cdreader(void) ++{ ++ struct rc_hash_cdreader cdreader; ++ rc_hash_get_default_cdreader(&cdreader); ++ rc_hash_init_custom_cdreader(&cdreader); ++} +diff -rupbN melonDS.orig/src/rcheevos/src/rhash/hash.c melonDS.ra/src/rcheevos/src/rhash/hash.c +--- melonDS.orig/src/rcheevos/src/rhash/hash.c 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rhash/hash.c 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,1402 @@ ++#include "rc_hash.h" ++ ++#include "rc_hash_internal.h" ++ ++#include "../rc_compat.h" ++ ++#if defined(_WIN32) ++#define WIN32_LEAN_AND_MEAN ++#include ++#include ++#endif ++ ++#include ++#include ++ ++const char* rc_path_get_filename(const char* path); ++static int rc_hash_from_file(char hash[33], uint32_t console_id, const rc_hash_iterator_t* iterator); ++ ++/* ===================================================== */ ++ ++static rc_hash_message_callback_deprecated g_error_message_callback = NULL; ++static rc_hash_message_callback_deprecated g_verbose_message_callback = NULL; ++ ++static void rc_hash_call_g_error_message_callback(const char* message, const rc_hash_iterator_t* iterator) ++{ ++ (void)iterator; ++ g_error_message_callback(message); ++} ++ ++static void rc_hash_call_g_verbose_message_callback(const char* message, const rc_hash_iterator_t* iterator) ++{ ++ (void)iterator; ++ g_verbose_message_callback(message); ++} ++ ++static void rc_hash_dispatch_message_va(const rc_hash_message_callback_func callback, ++ const rc_hash_iterator_t* iterator, const char* format, va_list args) ++{ ++ char buffer[1024]; ++ ++#ifdef __STDC_SECURE_LIB__ ++ vsprintf_s(buffer, sizeof(buffer), format, args); ++#elif __STDC_VERSION__ >= 199901L /* vsnprintf requires c99 */ ++ vsnprintf(buffer, sizeof(buffer), format, args); ++#else /* c89 doesn't have a size-limited vsprintf function - assume the buffer is large enough */ ++ vsprintf(buffer, format, args); ++#endif ++ ++ callback(buffer, iterator); ++} ++ ++void rc_hash_init_error_message_callback(rc_hash_message_callback_deprecated callback) ++{ ++ g_error_message_callback = callback; ++} ++ ++static rc_hash_message_callback_func rc_hash_get_error_message_callback(const rc_hash_callbacks_t* callbacks) ++{ ++ if (callbacks && callbacks->error_message) ++ return callbacks->error_message; ++ ++ if (g_error_message_callback) ++ return rc_hash_call_g_error_message_callback; ++ ++ if (callbacks && callbacks->verbose_message) ++ return callbacks->verbose_message; ++ ++ if (g_verbose_message_callback) ++ return rc_hash_call_g_verbose_message_callback; ++ ++ return NULL; ++} ++ ++int rc_hash_iterator_error(const rc_hash_iterator_t* iterator, const char* message) ++{ ++ rc_hash_message_callback_func message_callback = rc_hash_get_error_message_callback(&iterator->callbacks); ++ ++ if (message_callback) ++ message_callback(message, iterator); ++ ++ return 0; ++} ++ ++int rc_hash_iterator_error_formatted(const rc_hash_iterator_t* iterator, const char* format, ...) ++{ ++ rc_hash_message_callback_func message_callback = rc_hash_get_error_message_callback(&iterator->callbacks); ++ ++ if (message_callback) { ++ va_list args; ++ va_start(args, format); ++ rc_hash_dispatch_message_va(message_callback, iterator, format, args); ++ va_end(args); ++ } ++ ++ return 0; ++} ++ ++void rc_hash_init_verbose_message_callback(rc_hash_message_callback_deprecated callback) ++{ ++ g_verbose_message_callback = callback; ++} ++ ++void rc_hash_iterator_verbose(const rc_hash_iterator_t* iterator, const char* message) ++{ ++ if (iterator->callbacks.verbose_message) ++ iterator->callbacks.verbose_message(message, iterator); ++ else if (g_verbose_message_callback) ++ g_verbose_message_callback(message); ++} ++ ++void rc_hash_iterator_verbose_formatted(const rc_hash_iterator_t* iterator, const char* format, ...) ++{ ++ if (iterator->callbacks.verbose_message) { ++ va_list args; ++ va_start(args, format); ++ rc_hash_dispatch_message_va(iterator->callbacks.verbose_message, iterator, format, args); ++ va_end(args); ++ } ++ else if (g_verbose_message_callback) { ++ va_list args; ++ va_start(args, format); ++ rc_hash_dispatch_message_va(rc_hash_call_g_verbose_message_callback, iterator, format, args); ++ va_end(args); ++ } ++} ++ ++/* ===================================================== */ ++ ++static struct rc_hash_filereader g_filereader_funcs; ++static struct rc_hash_filereader* g_filereader = NULL; ++ ++#if defined(WINVER) && WINVER >= 0x0500 ++static void* filereader_open(const char* path) ++{ ++ /* Windows requires using wchar APIs for Unicode paths */ ++ /* Note that MultiByteToWideChar will only be defined for >= Windows 2000 */ ++ wchar_t* wpath; ++ int wpath_length; ++ FILE* fp; ++ ++ /* Calculate wpath length from path */ ++ wpath_length = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, path, -1, NULL, 0); ++ if (wpath_length == 0) /* 0 indicates error (this is likely from invalid UTF-8) */ ++ return NULL; ++ ++ wpath = (wchar_t*)malloc(wpath_length * sizeof(wchar_t)); ++ if (!wpath) ++ return NULL; ++ ++ if (MultiByteToWideChar(CP_UTF8, 0, path, -1, wpath, wpath_length) == 0) { ++ free(wpath); ++ return NULL; ++ } ++ ++ #if defined(__STDC_SECURE_LIB__) ++ /* have to use _SH_DENYNO because some cores lock the file while its loaded */ ++ fp = _wfsopen(wpath, L"rb", _SH_DENYNO); ++ #else ++ fp = _wfopen(wpath, L"rb"); ++ #endif ++ ++ free(wpath); ++ return fp; ++} ++#else /* !WINVER >= 0x0500 */ ++static void* filereader_open(const char* path) ++{ ++ #if defined(__STDC_SECURE_LIB__) ++ #if defined(WINVER) ++ /* have to use _SH_DENYNO because some cores lock the file while its loaded */ ++ return _fsopen(path, "rb", _SH_DENYNO); ++ #else /* !WINVER */ ++ FILE *fp; ++ fopen_s(&fp, path, "rb"); ++ return fp; ++ #endif ++ #else /* !__STDC_SECURE_LIB__ */ ++ return fopen(path, "rb"); ++ #endif ++} ++#endif /* WINVER >= 0x0500 */ ++ ++static void filereader_seek(void* file_handle, int64_t offset, int origin) ++{ ++#if defined(_WIN32) ++ _fseeki64((FILE*)file_handle, offset, origin); ++#elif defined(_LARGEFILE64_SOURCE) ++ fseeko64((FILE*)file_handle, offset, origin); ++#else ++ fseek((FILE*)file_handle, offset, origin); ++#endif ++} ++ ++static int64_t filereader_tell(void* file_handle) ++{ ++#if defined(_WIN32) ++ return _ftelli64((FILE*)file_handle); ++#elif defined(_LARGEFILE64_SOURCE) ++ return ftello64((FILE*)file_handle); ++#else ++ return ftell((FILE*)file_handle); ++#endif ++} ++ ++static size_t filereader_read(void* file_handle, void* buffer, size_t requested_bytes) ++{ ++ return fread(buffer, 1, requested_bytes, (FILE*)file_handle); ++} ++ ++static void filereader_close(void* file_handle) ++{ ++ fclose((FILE*)file_handle); ++} ++ ++/* for unit tests - normally would call rc_hash_init_custom_filereader(NULL) */ ++void rc_hash_reset_filereader(void) ++{ ++ g_filereader = NULL; ++} ++ ++void rc_hash_init_custom_filereader(struct rc_hash_filereader* reader) ++{ ++ /* initialize with defaults first */ ++ g_filereader_funcs.open = filereader_open; ++ g_filereader_funcs.seek = filereader_seek; ++ g_filereader_funcs.tell = filereader_tell; ++ g_filereader_funcs.read = filereader_read; ++ g_filereader_funcs.close = filereader_close; ++ ++ /* hook up any provided custom handlers */ ++ if (reader) { ++ if (reader->open) ++ g_filereader_funcs.open = reader->open; ++ ++ if (reader->seek) ++ g_filereader_funcs.seek = reader->seek; ++ ++ if (reader->tell) ++ g_filereader_funcs.tell = reader->tell; ++ ++ if (reader->read) ++ g_filereader_funcs.read = reader->read; ++ ++ if (reader->close) ++ g_filereader_funcs.close = reader->close; ++ } ++ ++ g_filereader = &g_filereader_funcs; ++} ++ ++void* rc_file_open(const rc_hash_iterator_t* iterator, const char* path) ++{ ++ void* handle = NULL; ++ ++ if (!iterator->callbacks.filereader.open) { ++ rc_hash_iterator_error(iterator, "No callback registered for opening files"); ++ } else { ++ handle = iterator->callbacks.filereader.open(path); ++ if (handle) ++ rc_hash_iterator_verbose_formatted(iterator, "Opened %s", rc_path_get_filename(path)); ++ } ++ ++ return handle; ++} ++ ++void rc_file_seek(const rc_hash_iterator_t* iterator, void* file_handle, int64_t offset, int origin) ++{ ++ if (iterator->callbacks.filereader.seek) ++ iterator->callbacks.filereader.seek(file_handle, offset, origin); ++} ++ ++int64_t rc_file_tell(const rc_hash_iterator_t* iterator, void* file_handle) ++{ ++ return iterator->callbacks.filereader.tell ? iterator->callbacks.filereader.tell(file_handle) : 0; ++} ++ ++size_t rc_file_read(const rc_hash_iterator_t* iterator, void* file_handle, void* buffer, int requested_bytes) ++{ ++ return iterator->callbacks.filereader.read ? iterator->callbacks.filereader.read(file_handle, buffer, requested_bytes) : 0; ++} ++ ++void rc_file_close(const rc_hash_iterator_t* iterator, void* file_handle) ++{ ++ if (iterator->callbacks.filereader.close) ++ iterator->callbacks.filereader.close(file_handle); ++} ++ ++int64_t rc_file_size(const rc_hash_iterator_t* iterator, const char* path) ++{ ++ int64_t size = 0; ++ ++ /* don't use rc_file_open to avoid log statements */ ++ if (!iterator->callbacks.filereader.open) { ++ rc_hash_iterator_error(iterator, "No callback registered for opening files"); ++ } else { ++ void* handle = iterator->callbacks.filereader.open(path); ++ if (handle) { ++ rc_file_seek(iterator, handle, 0, SEEK_END); ++ size = rc_file_tell(iterator, handle); ++ rc_file_close(iterator, handle); ++ } ++ } ++ ++ return size; ++} ++ ++/* ===================================================== */ ++ ++const char* rc_path_get_filename(const char* path) ++{ ++ const char* ptr = path + strlen(path); ++ do { ++ if (ptr[-1] == '/' || ptr[-1] == '\\') ++ break; ++ ++ --ptr; ++ } while (ptr > path); ++ ++ return ptr; ++} ++ ++const char* rc_path_get_extension(const char* path) ++{ ++ const char* ptr = path + strlen(path); ++ do { ++ if (ptr[-1] == '.') ++ return ptr; ++ ++ --ptr; ++ } while (ptr > path); ++ ++ return path + strlen(path); ++} ++ ++int rc_path_compare_extension(const char* path, const char* ext) ++{ ++ size_t path_len = strlen(path); ++ size_t ext_len = strlen(ext); ++ const char* ptr = path + path_len - ext_len; ++ if (ptr[-1] != '.') ++ return 0; ++ ++ if (memcmp(ptr, ext, ext_len) == 0) ++ return 1; ++ ++ do { ++ if (tolower(*ptr) != *ext) ++ return 0; ++ ++ ++ext; ++ ++ptr; ++ } while (*ptr); ++ ++ return 1; ++} ++ ++/* ===================================================== */ ++ ++void rc_hash_byteswap16(uint8_t* buffer, const uint8_t* stop) ++{ ++ uint32_t* ptr = (uint32_t*)buffer; ++ const uint32_t* stop32 = (const uint32_t*)stop; ++ while (ptr < stop32) { ++ uint32_t temp = *ptr; ++ temp = (temp & 0xFF00FF00) >> 8 | ++ (temp & 0x00FF00FF) << 8; ++ *ptr++ = temp; ++ } ++} ++ ++void rc_hash_byteswap32(uint8_t* buffer, const uint8_t* stop) ++{ ++ uint32_t* ptr = (uint32_t*)buffer; ++ const uint32_t* stop32 = (const uint32_t*)stop; ++ while (ptr < stop32) { ++ uint32_t temp = *ptr; ++ temp = (temp & 0xFF000000) >> 24 | ++ (temp & 0x00FF0000) >> 8 | ++ (temp & 0x0000FF00) << 8 | ++ (temp & 0x000000FF) << 24; ++ *ptr++ = temp; ++ } ++} ++ ++int rc_hash_finalize(const rc_hash_iterator_t* iterator, md5_state_t* md5, char hash[33]) ++{ ++ md5_byte_t digest[16]; ++ ++ md5_finish(md5, digest); ++ ++ /* NOTE: sizeof(hash) is 4 because it's still treated like a pointer, despite specifying a size */ ++ snprintf(hash, 33, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", ++ digest[0], digest[1], digest[2], digest[3], digest[4], digest[5], digest[6], digest[7], ++ digest[8], digest[9], digest[10], digest[11], digest[12], digest[13], digest[14], digest[15] ++ ); ++ ++ rc_hash_iterator_verbose_formatted(iterator, "Generated hash %s", hash); ++ ++ return 1; ++} ++ ++int rc_hash_buffer(char hash[33], const uint8_t* buffer, size_t buffer_size, const rc_hash_iterator_t* iterator) ++{ ++ md5_state_t md5; ++ ++ if (buffer_size > MAX_BUFFER_SIZE) ++ buffer_size = MAX_BUFFER_SIZE; ++ ++ md5_init(&md5); ++ ++ md5_append(&md5, buffer, (int)buffer_size); ++ ++ rc_hash_iterator_verbose_formatted(iterator, "Hashing %u byte buffer", (unsigned)buffer_size); ++ ++ return rc_hash_finalize(iterator, &md5, hash); ++} ++ ++struct rc_buffered_file ++{ ++ const uint8_t* read_ptr; ++ const uint8_t* data; ++ size_t data_size; ++}; ++ ++static struct rc_buffered_file rc_buffered_file; ++ ++static void* rc_file_open_buffered_file(const char* path) ++{ ++ struct rc_buffered_file* handle = (struct rc_buffered_file*)malloc(sizeof(struct rc_buffered_file)); ++ (void)path; ++ ++ if (handle) ++ memcpy(handle, &rc_buffered_file, sizeof(rc_buffered_file)); ++ ++ return handle; ++} ++ ++static void rc_file_seek_buffered_file(void* file_handle, int64_t offset, int origin) ++{ ++ struct rc_buffered_file* buffered_file = (struct rc_buffered_file*)file_handle; ++ switch (origin) { ++ case SEEK_SET: buffered_file->read_ptr = buffered_file->data + offset; break; ++ case SEEK_CUR: buffered_file->read_ptr += offset; break; ++ case SEEK_END: buffered_file->read_ptr = buffered_file->data + buffered_file->data_size + offset; break; ++ } ++ ++ if (buffered_file->read_ptr < buffered_file->data) ++ buffered_file->read_ptr = buffered_file->data; ++ else if (buffered_file->read_ptr > buffered_file->data + buffered_file->data_size) ++ buffered_file->read_ptr = buffered_file->data + buffered_file->data_size; ++} ++ ++static int64_t rc_file_tell_buffered_file(void* file_handle) ++{ ++ struct rc_buffered_file* buffered_file = (struct rc_buffered_file*)file_handle; ++ return (buffered_file->read_ptr - buffered_file->data); ++} ++ ++static size_t rc_file_read_buffered_file(void* file_handle, void* buffer, size_t requested_bytes) ++{ ++ struct rc_buffered_file* buffered_file = (struct rc_buffered_file*)file_handle; ++ const int64_t remaining = buffered_file->data_size - (buffered_file->read_ptr - buffered_file->data); ++ if ((int)requested_bytes > remaining) ++ requested_bytes = (int)remaining; ++ ++ memcpy(buffer, buffered_file->read_ptr, requested_bytes); ++ buffered_file->read_ptr += requested_bytes; ++ return requested_bytes; ++} ++ ++static void rc_file_close_buffered_file(void* file_handle) ++{ ++ free(file_handle); ++} ++ ++static int rc_hash_file_from_buffer(char hash[33], uint32_t console_id, const rc_hash_iterator_t* iterator) ++{ ++ int result; ++ ++ rc_hash_iterator_t buffered_file_iterator; ++ memset(&buffered_file_iterator, 0, sizeof(buffered_file_iterator)); ++ memcpy(&buffered_file_iterator.callbacks, &iterator->callbacks, sizeof(iterator->callbacks)); ++ buffered_file_iterator.userdata = iterator->userdata; ++ ++ buffered_file_iterator.callbacks.filereader.open = rc_file_open_buffered_file; ++ buffered_file_iterator.callbacks.filereader.close = rc_file_close_buffered_file; ++ buffered_file_iterator.callbacks.filereader.read = rc_file_read_buffered_file; ++ buffered_file_iterator.callbacks.filereader.seek = rc_file_seek_buffered_file; ++ buffered_file_iterator.callbacks.filereader.tell = rc_file_tell_buffered_file; ++ buffered_file_iterator.path = "memory stream"; ++ ++ rc_buffered_file.data = rc_buffered_file.read_ptr = iterator->buffer; ++ rc_buffered_file.data_size = iterator->buffer_size; ++ ++ result = rc_hash_from_file(hash, console_id, &buffered_file_iterator); ++ ++ buffered_file_iterator.path = NULL; ++ rc_hash_destroy_iterator(&buffered_file_iterator); ++ return result; ++} ++ ++static int rc_hash_from_buffer(char hash[33], uint32_t console_id, const rc_hash_iterator_t* iterator) ++{ ++ switch (console_id) { ++ default: ++ return rc_hash_iterator_error_formatted(iterator, "Unsupported console for buffer hash: %d", console_id); ++ ++ case RC_CONSOLE_AMSTRAD_PC: ++ case RC_CONSOLE_APPLE_II: ++ case RC_CONSOLE_ARCADIA_2001: ++ case RC_CONSOLE_ATARI_2600: ++ case RC_CONSOLE_ATARI_JAGUAR: ++ case RC_CONSOLE_COLECOVISION: ++ case RC_CONSOLE_COMMODORE_64: ++ case RC_CONSOLE_ELEKTOR_TV_GAMES_COMPUTER: ++ case RC_CONSOLE_FAIRCHILD_CHANNEL_F: ++ case RC_CONSOLE_GAMEBOY: ++ case RC_CONSOLE_GAMEBOY_ADVANCE: ++ case RC_CONSOLE_GAMEBOY_COLOR: ++ case RC_CONSOLE_GAME_GEAR: ++ case RC_CONSOLE_INTELLIVISION: ++ case RC_CONSOLE_INTERTON_VC_4000: ++ case RC_CONSOLE_MAGNAVOX_ODYSSEY2: ++ case RC_CONSOLE_MASTER_SYSTEM: ++ case RC_CONSOLE_MEGA_DRIVE: ++ case RC_CONSOLE_MEGADUCK: ++ case RC_CONSOLE_MSX: ++ case RC_CONSOLE_NEOGEO_POCKET: ++ case RC_CONSOLE_ORIC: ++ case RC_CONSOLE_PC8800: ++ case RC_CONSOLE_POKEMON_MINI: ++ case RC_CONSOLE_SEGA_32X: ++ case RC_CONSOLE_SG1000: ++ case RC_CONSOLE_SUPERVISION: ++ case RC_CONSOLE_TI83: ++ case RC_CONSOLE_TIC80: ++ case RC_CONSOLE_UZEBOX: ++ case RC_CONSOLE_VECTREX: ++ case RC_CONSOLE_VIRTUAL_BOY: ++ case RC_CONSOLE_WASM4: ++ case RC_CONSOLE_WONDERSWAN: ++ case RC_CONSOLE_ZX_SPECTRUM: ++ return rc_hash_buffer(hash, iterator->buffer, iterator->buffer_size, iterator); ++ ++#ifndef RC_HASH_NO_ROM ++ case RC_CONSOLE_ARDUBOY: ++ return rc_hash_arduboy(hash, iterator); ++ ++ case RC_CONSOLE_ATARI_7800: ++ return rc_hash_7800(hash, iterator); ++ ++ case RC_CONSOLE_ATARI_LYNX: ++ return rc_hash_lynx(hash, iterator); ++ ++ case RC_CONSOLE_FAMICOM_DISK_SYSTEM: ++ case RC_CONSOLE_NINTENDO: ++ return rc_hash_nes(hash, iterator); ++ ++ case RC_CONSOLE_PC_ENGINE: /* NOTE: does not support PCEngine CD */ ++ return rc_hash_pce(hash, iterator); ++ ++ case RC_CONSOLE_SUPER_CASSETTEVISION: ++ return rc_hash_scv(hash, iterator); ++ ++ case RC_CONSOLE_SUPER_NINTENDO: ++ return rc_hash_snes(hash, iterator); ++#endif ++ ++ case RC_CONSOLE_NINTENDO_64: ++ case RC_CONSOLE_NINTENDO_3DS: ++ case RC_CONSOLE_NINTENDO_DS: ++ case RC_CONSOLE_NINTENDO_DSI: ++ return rc_hash_file_from_buffer(hash, console_id, iterator); ++ } ++} ++ ++int rc_hash_whole_file(char hash[33], const rc_hash_iterator_t* iterator) ++{ ++ md5_state_t md5; ++ uint8_t* buffer; ++ int64_t size; ++ const size_t buffer_size = 65536; ++ void* file_handle; ++ size_t remaining; ++ int result = 0; ++ ++ file_handle = rc_file_open(iterator, iterator->path); ++ if (!file_handle) ++ return rc_hash_iterator_error(iterator, "Could not open file"); ++ ++ rc_file_seek(iterator, file_handle, 0, SEEK_END); ++ size = rc_file_tell(iterator, file_handle); ++ ++ if (size > MAX_BUFFER_SIZE) { ++ rc_hash_iterator_verbose_formatted(iterator, "Hashing first %u bytes (of %u bytes) of %s", MAX_BUFFER_SIZE, (unsigned)size, rc_path_get_filename(iterator->path)); ++ remaining = MAX_BUFFER_SIZE; ++ } ++ else { ++ rc_hash_iterator_verbose_formatted(iterator, "Hashing %s (%u bytes)", rc_path_get_filename(iterator->path), (unsigned)size); ++ remaining = (size_t)size; ++ } ++ ++ md5_init(&md5); ++ ++ buffer = (uint8_t*)malloc(buffer_size); ++ if (buffer) { ++ rc_file_seek(iterator, file_handle, 0, SEEK_SET); ++ while (remaining >= buffer_size) { ++ rc_file_read(iterator, file_handle, buffer, (int)buffer_size); ++ md5_append(&md5, buffer, (int)buffer_size); ++ remaining -= buffer_size; ++ } ++ ++ if (remaining > 0) { ++ rc_file_read(iterator, file_handle, buffer, (int)remaining); ++ md5_append(&md5, buffer, (int)remaining); ++ } ++ ++ free(buffer); ++ result = rc_hash_finalize(iterator, &md5, hash); ++ } ++ ++ rc_file_close(iterator, file_handle); ++ return result; ++} ++ ++int rc_hash_buffered_file(char hash[33], uint32_t console_id, const rc_hash_iterator_t* iterator) ++{ ++ uint8_t* buffer; ++ int64_t size; ++ int result = 0; ++ void* file_handle; ++ ++ file_handle = rc_file_open(iterator, iterator->path); ++ if (!file_handle) ++ return rc_hash_iterator_error(iterator, "Could not open file"); ++ ++ rc_file_seek(iterator, file_handle, 0, SEEK_END); ++ size = rc_file_tell(iterator, file_handle); ++ ++ if (size > MAX_BUFFER_SIZE) { ++ rc_hash_iterator_verbose_formatted(iterator, "Buffering first %u bytes (of %d bytes) of %s", MAX_BUFFER_SIZE, (unsigned)size, rc_path_get_filename(iterator->path)); ++ size = MAX_BUFFER_SIZE; ++ } ++ else { ++ rc_hash_iterator_verbose_formatted(iterator, "Buffering %s (%d bytes)", rc_path_get_filename(iterator->path), (unsigned)size); ++ } ++ ++ buffer = (uint8_t*)malloc((size_t)size); ++ if (buffer) { ++ rc_hash_iterator_t buffer_iterator; ++ memset(&buffer_iterator, 0, sizeof(buffer_iterator)); ++ memcpy(&buffer_iterator.callbacks, &iterator->callbacks, sizeof(iterator->callbacks)); ++ buffer_iterator.userdata = iterator->userdata; ++ buffer_iterator.path = iterator->path; ++ buffer_iterator.buffer = buffer; ++ buffer_iterator.buffer_size = (size_t)size; ++ ++ rc_file_seek(iterator, file_handle, 0, SEEK_SET); ++ rc_file_read(iterator, file_handle, buffer, (int)size); ++ ++ result = rc_hash_from_buffer(hash, console_id, &buffer_iterator); ++ ++ free(buffer); ++ } ++ ++ rc_file_close(iterator, file_handle); ++ return result; ++} ++ ++static int rc_hash_path_is_absolute(const char* path) ++{ ++ if (!path[0]) ++ return 0; ++ ++ /* "/path/to/file" or "\path\to\file" */ ++ if (path[0] == '/' || path[0] == '\\') ++ return 1; ++ ++ /* "C:\path\to\file" */ ++ if (path[1] == ':' && path[2] == '\\') ++ return 1; ++ ++ /* "scheme:/path/to/file" */ ++ while (*path) { ++ if (path[0] == ':' && path[1] == '/') ++ return 1; ++ ++ ++path; ++ } ++ ++ return 0; ++} ++ ++static const char* rc_hash_get_first_item_from_playlist(const rc_hash_iterator_t* iterator) { ++ char buffer[1024]; ++ char* disc_path; ++ char* ptr, *start, *next; ++ size_t num_read, path_len, file_len; ++ void* file_handle; ++ ++ file_handle = rc_file_open(iterator, iterator->path); ++ if (!file_handle) { ++ rc_hash_iterator_error(iterator, "Could not open playlist"); ++ return NULL; ++ } ++ ++ num_read = rc_file_read(iterator, file_handle, buffer, sizeof(buffer) - 1); ++ buffer[num_read] = '\0'; ++ ++ rc_file_close(iterator, file_handle); ++ ++ ptr = start = buffer; ++ do { ++ /* ignore empty and commented lines */ ++ while (*ptr == '#' || *ptr == '\r' || *ptr == '\n') { ++ while (*ptr && *ptr != '\n') ++ ++ptr; ++ if (*ptr) ++ ++ptr; ++ } ++ ++ /* find and extract the current line */ ++ start = ptr; ++ while (*ptr && *ptr != '\n') ++ ++ptr; ++ next = ptr; ++ ++ /* remove trailing whitespace - especially '\r' */ ++ while (ptr > start && isspace((unsigned char)ptr[-1])) ++ --ptr; ++ ++ /* if we found a non-empty line, break out of the loop to process it */ ++ file_len = ptr - start; ++ if (file_len) ++ break; ++ ++ /* did we reach the end of the file? */ ++ if (!*next) ++ return NULL; ++ ++ /* if the line only contained whitespace, keep searching */ ++ ptr = next + 1; ++ } while (1); ++ ++ rc_hash_iterator_verbose_formatted(iterator, "Extracted %.*s from playlist", (int)file_len, start); ++ ++ start[file_len++] = '\0'; ++ if (rc_hash_path_is_absolute(start)) ++ path_len = 0; ++ else ++ path_len = rc_path_get_filename(iterator->path) - iterator->path; ++ ++ disc_path = (char*)malloc(path_len + file_len + 1); ++ if (!disc_path) ++ return NULL; ++ ++ if (path_len) ++ memcpy(disc_path, iterator->path, path_len); ++ ++ memcpy(&disc_path[path_len], start, file_len); ++ return disc_path; ++} ++ ++static int rc_hash_generate_from_playlist(char hash[33], uint32_t console_id, const rc_hash_iterator_t* iterator) { ++ rc_hash_iterator_t first_file_iterator; ++ const char* disc_path; ++ int result; ++ ++ rc_hash_iterator_verbose_formatted(iterator, "Processing playlist: %s", rc_path_get_filename(iterator->path)); ++ ++ disc_path = rc_hash_get_first_item_from_playlist(iterator); ++ if (!disc_path) ++ return rc_hash_iterator_error(iterator, "Failed to get first item from playlist"); ++ ++ memset(&first_file_iterator, 0, sizeof(first_file_iterator)); ++ memcpy(&first_file_iterator.callbacks, &iterator->callbacks, sizeof(iterator->callbacks)); ++ first_file_iterator.userdata = iterator->userdata; ++ first_file_iterator.path = disc_path; /* rc_hash_destory_iterator will free */ ++ ++ result = rc_hash_from_file(hash, console_id, &first_file_iterator); ++ ++ rc_hash_destroy_iterator(&first_file_iterator); ++ return result; ++} ++ ++static int rc_hash_from_file(char hash[33], uint32_t console_id, const rc_hash_iterator_t* iterator) ++{ ++ const char* path = iterator->path; ++ ++ switch (console_id) { ++ default: ++ return rc_hash_iterator_error_formatted(iterator, "Unsupported console for file hash: %d", console_id); ++ ++ case RC_CONSOLE_ARCADIA_2001: ++ case RC_CONSOLE_ATARI_2600: ++ case RC_CONSOLE_ATARI_JAGUAR: ++ case RC_CONSOLE_COLECOVISION: ++ case RC_CONSOLE_ELEKTOR_TV_GAMES_COMPUTER: ++ case RC_CONSOLE_FAIRCHILD_CHANNEL_F: ++ case RC_CONSOLE_GAMEBOY: ++ case RC_CONSOLE_GAMEBOY_ADVANCE: ++ case RC_CONSOLE_GAMEBOY_COLOR: ++ case RC_CONSOLE_GAME_GEAR: ++ case RC_CONSOLE_INTELLIVISION: ++ case RC_CONSOLE_INTERTON_VC_4000: ++ case RC_CONSOLE_MAGNAVOX_ODYSSEY2: ++ case RC_CONSOLE_MASTER_SYSTEM: ++ case RC_CONSOLE_MEGADUCK: ++ case RC_CONSOLE_NEOGEO_POCKET: ++ case RC_CONSOLE_ORIC: ++ case RC_CONSOLE_POKEMON_MINI: ++ case RC_CONSOLE_SEGA_32X: ++ case RC_CONSOLE_SG1000: ++ case RC_CONSOLE_SUPERVISION: ++ case RC_CONSOLE_TI83: ++ case RC_CONSOLE_TIC80: ++ case RC_CONSOLE_UZEBOX: ++ case RC_CONSOLE_VECTREX: ++ case RC_CONSOLE_VIRTUAL_BOY: ++ case RC_CONSOLE_WASM4: ++ case RC_CONSOLE_WONDERSWAN: ++ case RC_CONSOLE_ZX_SPECTRUM: ++ /* generic whole-file hash - don't buffer */ ++ return rc_hash_whole_file(hash, iterator); ++ ++ case RC_CONSOLE_MEGA_DRIVE: ++ /* generic whole-file hash with m3u support - don't buffer */ ++ if (rc_path_compare_extension(path, "m3u")) ++ return rc_hash_generate_from_playlist(hash, console_id, iterator); ++ ++ return rc_hash_whole_file(hash, iterator); ++ ++ case RC_CONSOLE_ATARI_7800: ++ case RC_CONSOLE_ATARI_LYNX: ++ case RC_CONSOLE_FAMICOM_DISK_SYSTEM: ++ case RC_CONSOLE_NINTENDO: ++ case RC_CONSOLE_PC_ENGINE: ++ case RC_CONSOLE_SUPER_CASSETTEVISION: ++ case RC_CONSOLE_SUPER_NINTENDO: ++ /* additional logic whole-file hash - buffer then call rc_hash_generate_from_buffer */ ++ return rc_hash_buffered_file(hash, console_id, iterator); ++ ++ case RC_CONSOLE_AMSTRAD_PC: ++ case RC_CONSOLE_APPLE_II: ++ case RC_CONSOLE_COMMODORE_64: ++ case RC_CONSOLE_MSX: ++ case RC_CONSOLE_PC8800: ++ /* generic whole-file hash with m3u support - don't buffer */ ++ if (rc_path_compare_extension(path, "m3u")) ++ return rc_hash_generate_from_playlist(hash, console_id, iterator); ++ ++ return rc_hash_whole_file(hash, iterator); ++ ++#ifndef RC_HASH_NO_DISC ++ case RC_CONSOLE_3DO: ++ if (rc_path_compare_extension(path, "m3u")) ++ return rc_hash_generate_from_playlist(hash, console_id, iterator); ++ ++ return rc_hash_3do(hash, iterator); ++#endif ++ ++#ifndef RC_HASH_NO_ROM ++ case RC_CONSOLE_ARCADE: ++ return rc_hash_arcade(hash, iterator); ++ ++ case RC_CONSOLE_ARDUBOY: ++ return rc_hash_arduboy(hash, iterator); ++#endif ++ ++#ifndef RC_HASH_NO_DISC ++ case RC_CONSOLE_ATARI_JAGUAR_CD: ++ return rc_hash_jaguar_cd(hash, iterator); ++ ++ case RC_CONSOLE_DREAMCAST: ++ if (rc_path_compare_extension(path, "m3u")) ++ return rc_hash_generate_from_playlist(hash, console_id, iterator); ++ ++ return rc_hash_dreamcast(hash, iterator); ++ ++ case RC_CONSOLE_GAMECUBE: ++ return rc_hash_gamecube(hash, iterator); ++#endif ++ ++#ifndef RC_HASH_NO_ZIP ++ case RC_CONSOLE_MS_DOS: ++ return rc_hash_ms_dos(hash, iterator); ++#endif ++ ++#ifndef RC_HASH_NO_DISC ++ case RC_CONSOLE_NEO_GEO_CD: ++ return rc_hash_neogeo_cd(hash, iterator); ++#endif ++ ++#ifndef RC_HASH_NO_ROM ++ case RC_CONSOLE_NINTENDO_64: ++ return rc_hash_n64(hash, iterator); ++#endif ++ ++#ifndef RC_HASH_NO_ENCRYPTED ++ case RC_CONSOLE_NINTENDO_3DS: ++ return rc_hash_nintendo_3ds(hash, iterator); ++#endif ++ ++#ifndef RC_HASH_NO_ROM ++ case RC_CONSOLE_NINTENDO_DS: ++ case RC_CONSOLE_NINTENDO_DSI: ++ return rc_hash_nintendo_ds(hash, iterator); ++#endif ++ ++#ifndef RC_HASH_NO_DISC ++ case RC_CONSOLE_PC_ENGINE_CD: ++ if (rc_path_compare_extension(path, "cue") || rc_path_compare_extension(path, "chd")) ++ return rc_hash_pce_cd(hash, iterator); ++ ++ if (rc_path_compare_extension(path, "m3u")) ++ return rc_hash_generate_from_playlist(hash, console_id, iterator); ++ ++ return rc_hash_buffered_file(hash, console_id, iterator); ++ ++ case RC_CONSOLE_PCFX: ++ if (rc_path_compare_extension(path, "m3u")) ++ return rc_hash_generate_from_playlist(hash, console_id, iterator); ++ ++ return rc_hash_pcfx_cd(hash, iterator); ++ ++ case RC_CONSOLE_PLAYSTATION: ++ if (rc_path_compare_extension(path, "m3u")) ++ return rc_hash_generate_from_playlist(hash, console_id, iterator); ++ ++ return rc_hash_psx(hash, iterator); ++ ++ case RC_CONSOLE_PLAYSTATION_2: ++ if (rc_path_compare_extension(path, "m3u")) ++ return rc_hash_generate_from_playlist(hash, console_id, iterator); ++ ++ return rc_hash_ps2(hash, iterator); ++ ++ case RC_CONSOLE_PSP: ++ return rc_hash_psp(hash, iterator); ++ ++ case RC_CONSOLE_SEGA_CD: ++ case RC_CONSOLE_SATURN: ++ if (rc_path_compare_extension(path, "m3u")) ++ return rc_hash_generate_from_playlist(hash, console_id, iterator); ++ ++ return rc_hash_sega_cd(hash, iterator); ++ ++ case RC_CONSOLE_WII: ++ return rc_hash_wii(hash, iterator); ++#endif ++ } ++} ++ ++static void rc_hash_initialize_iterator_from_path(rc_hash_iterator_t* iterator, const char* path); ++ ++static void rc_hash_iterator_append_console(struct rc_hash_iterator* iterator, uint8_t console_id) { ++ int i = 0; ++ while (iterator->consoles[i] != 0) { ++ if (iterator->consoles[i] == console_id) ++ return; ++ ++ ++i; ++ } ++ ++ iterator->consoles[i] = console_id; ++} ++ ++void rc_hash_merge_callbacks(rc_hash_iterator_t* iterator, const rc_hash_callbacks_t* callbacks) ++{ ++ if (callbacks->verbose_message) ++ iterator->callbacks.verbose_message = callbacks->verbose_message; ++ if (callbacks->error_message) ++ iterator->callbacks.verbose_message = callbacks->error_message; ++ ++ if (callbacks->filereader.open) ++ memcpy(&iterator->callbacks.filereader, &callbacks->filereader, sizeof(callbacks->filereader)); ++ ++#ifndef RC_HASH_NO_DISC ++ if (callbacks->cdreader.open_track) ++ memcpy(&iterator->callbacks.cdreader, &callbacks->cdreader, sizeof(callbacks->cdreader)); ++#endif ++ ++#ifndef RC_HASH_NO_ENCRYPTED ++ if (callbacks->encryption.get_3ds_cia_normal_key) ++ iterator->callbacks.encryption.get_3ds_cia_normal_key = callbacks->encryption.get_3ds_cia_normal_key; ++ if (callbacks->encryption.get_3ds_ncch_normal_keys) ++ iterator->callbacks.encryption.get_3ds_ncch_normal_keys = callbacks->encryption.get_3ds_ncch_normal_keys; ++#endif ++} ++ ++ ++static void rc_hash_reset_iterator(rc_hash_iterator_t* iterator) { ++ memset(iterator, 0, sizeof(*iterator)); ++ iterator->index = -1; ++ ++ if (g_verbose_message_callback) ++ iterator->callbacks.verbose_message = rc_hash_call_g_verbose_message_callback; ++ if (g_error_message_callback) ++ iterator->callbacks.error_message = rc_hash_call_g_error_message_callback; ++ ++ if (g_filereader) { ++ memcpy(&iterator->callbacks.filereader, g_filereader, sizeof(*g_filereader)); ++ } else if (!iterator->callbacks.filereader.open) { ++ iterator->callbacks.filereader.open = filereader_open; ++ iterator->callbacks.filereader.close = filereader_close; ++ iterator->callbacks.filereader.seek = filereader_seek; ++ iterator->callbacks.filereader.tell = filereader_tell; ++ iterator->callbacks.filereader.read = filereader_read; ++ } ++ ++#ifndef RC_HASH_NO_DISC ++ rc_hash_reset_iterator_disc(iterator); ++#endif ++ ++#ifndef RC_HASH_NO_ENCRYPTED ++ rc_hash_reset_iterator_encrypted(iterator); ++#endif ++} ++ ++static void rc_hash_initialize_iterator_single(rc_hash_iterator_t* iterator, int data) { ++ iterator->consoles[0] = (uint8_t)data; ++} ++ ++static void rc_hash_initialize_iterator_bin(rc_hash_iterator_t* iterator, int data) { ++ (void)data; ++ ++ if (iterator->buffer_size == 0) { ++ /* raw bin file may be a CD track. if it's more than 32MB, try a CD hash. */ ++ const int64_t size = rc_file_size(iterator, iterator->path); ++ if (size > 32 * 1024 * 1024) { ++ iterator->consoles[0] = RC_CONSOLE_3DO; /* 4DO supports directly opening the bin file */ ++ iterator->consoles[1] = RC_CONSOLE_PLAYSTATION; /* PCSX ReARMed supports directly opening the bin file*/ ++ iterator->consoles[2] = RC_CONSOLE_PLAYSTATION_2; /* PCSX2 supports directly opening the bin file*/ ++ iterator->consoles[3] = RC_CONSOLE_SEGA_CD; /* Genesis Plus GX supports directly opening the bin file*/ ++ ++ /* fallback to megadrive which just does a full hash. */ ++ iterator->consoles[4] = RC_CONSOLE_MEGA_DRIVE; ++ return; ++ } ++ } ++ ++ /* bin is associated with MegaDrive, Sega32X, Atari 2600, Watara Supervision, MegaDuck, ++ * Fairchild Channel F, Arcadia 2001, Interton VC 4000, and Super Cassette Vision. ++ * Since they all use the same hashing algorithm, only specify one of them */ ++ iterator->consoles[0] = RC_CONSOLE_MEGA_DRIVE; ++} ++ ++static void rc_hash_initialize_iterator_chd(rc_hash_iterator_t* iterator, int data) { ++ (void)data; ++ ++ iterator->consoles[0] = RC_CONSOLE_PLAYSTATION; ++ iterator->consoles[1] = RC_CONSOLE_PLAYSTATION_2; ++ iterator->consoles[2] = RC_CONSOLE_DREAMCAST; ++ iterator->consoles[3] = RC_CONSOLE_SEGA_CD; /* ASSERT: handles both Sega CD and Saturn */ ++ iterator->consoles[4] = RC_CONSOLE_PSP; ++ iterator->consoles[5] = RC_CONSOLE_PC_ENGINE_CD; ++ iterator->consoles[6] = RC_CONSOLE_3DO; ++ iterator->consoles[7] = RC_CONSOLE_NEO_GEO_CD; ++ iterator->consoles[8] = RC_CONSOLE_PCFX; ++} ++ ++static void rc_hash_initialize_iterator_cue(rc_hash_iterator_t* iterator, int data) { ++ (void)data; ++ ++ iterator->consoles[0] = RC_CONSOLE_PLAYSTATION; ++ iterator->consoles[1] = RC_CONSOLE_PLAYSTATION_2; ++ iterator->consoles[2] = RC_CONSOLE_DREAMCAST; ++ iterator->consoles[3] = RC_CONSOLE_SEGA_CD; /* ASSERT: handles both Sega CD and Saturn */ ++ iterator->consoles[4] = RC_CONSOLE_PC_ENGINE_CD; ++ iterator->consoles[5] = RC_CONSOLE_3DO; ++ iterator->consoles[6] = RC_CONSOLE_PCFX; ++ iterator->consoles[7] = RC_CONSOLE_NEO_GEO_CD; ++ iterator->consoles[8] = RC_CONSOLE_ATARI_JAGUAR_CD; ++} ++ ++static void rc_hash_initialize_iterator_d88(rc_hash_iterator_t* iterator, int data) { ++ (void)data; ++ ++ iterator->consoles[0] = RC_CONSOLE_PC8800; ++ iterator->consoles[1] = RC_CONSOLE_SHARPX1; ++} ++ ++static void rc_hash_initialize_iterator_dsk(rc_hash_iterator_t* iterator, int data) { ++ size_t size = iterator->buffer_size; ++ if (size == 0) ++ size = (size_t)rc_file_size(iterator, iterator->path); ++ ++ (void)data; ++ ++ if (size == 512 * 9 * 80) { /* 360KB */ ++ /* FAT-12 3.5" DD (512 byte sectors, 9 sectors per track, 80 tracks per side */ ++ /* FAT-12 5.25" DD double-sided (512 byte sectors, 9 sectors per track, 80 tracks per side */ ++ iterator->consoles[0] = RC_CONSOLE_MSX; ++ } ++ else if (size == 512 * 9 * 80 * 2) { /* 720KB */ ++ /* FAT-12 3.5" DD double-sided (512 byte sectors, 9 sectors per track, 80 tracks per side */ ++ iterator->consoles[0] = RC_CONSOLE_MSX; ++ } ++ else if (size == 512 * 9 * 40) { /* 180KB */ ++ /* FAT-12 5.25" DD (512 byte sectors, 9 sectors per track, 40 tracks per side */ ++ iterator->consoles[0] = RC_CONSOLE_MSX; ++ ++ /* AMSDOS 3" - 40 tracks */ ++ iterator->consoles[1] = RC_CONSOLE_AMSTRAD_PC; ++ } ++ else if (size == 256 * 16 * 35) { /* 140KB */ ++ /* Apple II new format - 256 byte sectors, 16 sectors per track, 35 tracks per side */ ++ iterator->consoles[0] = RC_CONSOLE_APPLE_II; ++ } ++ else if (size == 256 * 13 * 35) { /* 113.75KB */ ++ /* Apple II old format - 256 byte sectors, 13 sectors per track, 35 tracks per side */ ++ iterator->consoles[0] = RC_CONSOLE_APPLE_II; ++ } ++ ++ /* once a best guess has been identified, make sure the others are added as fallbacks */ ++ ++ /* check MSX first, as Apple II isn't supported by RetroArch, and RAppleWin won't use the iterator */ ++ rc_hash_iterator_append_console(iterator, RC_CONSOLE_MSX); ++ rc_hash_iterator_append_console(iterator, RC_CONSOLE_AMSTRAD_PC); ++ rc_hash_iterator_append_console(iterator, RC_CONSOLE_ZX_SPECTRUM); ++ rc_hash_iterator_append_console(iterator, RC_CONSOLE_APPLE_II); ++} ++ ++static void rc_hash_initialize_iterator_iso(rc_hash_iterator_t* iterator, int data) { ++ (void)data; ++ ++ iterator->consoles[0] = RC_CONSOLE_PLAYSTATION_2; ++ iterator->consoles[1] = RC_CONSOLE_PSP; ++ iterator->consoles[2] = RC_CONSOLE_3DO; ++ iterator->consoles[3] = RC_CONSOLE_SEGA_CD; /* ASSERT: handles both Sega CD and Saturn */ ++ iterator->consoles[4] = RC_CONSOLE_GAMECUBE; ++ iterator->consoles[5] = RC_CONSOLE_WII; ++} ++ ++static void rc_hash_initialize_iterator_m3u(rc_hash_iterator_t* iterator, int data) { ++ const char* first_file_path; ++ ++ (void)data; ++ ++ /* temporarily set the iterator path to the m3u file so we can extract the ++ * path of the first disc. rc_hash_get_first_item_from_playlist will return ++ * an allocated string or NULL, so rc_hash_destroy_iterator won't get tripped ++ * up by the non-allocted value we're about to assign. ++ */ ++ first_file_path = rc_hash_get_first_item_from_playlist(iterator); ++ if (!first_file_path) /* did not find a disc */ ++ return; ++ ++ /* release the m3u path and replace with the first file path */ ++ free((void*)iterator->path); ++ iterator->path = first_file_path; /* assert: already malloc'd; don't need to strdup */ ++ ++ iterator->buffer = NULL; /* ignore buffer; assume it's the m3u contents */ ++ ++ rc_hash_initialize_iterator_from_path(iterator, iterator->path); ++} ++ ++static void rc_hash_initialize_iterator_nib(rc_hash_iterator_t* iterator, int data) { ++ (void)data; ++ ++ iterator->consoles[0] = RC_CONSOLE_APPLE_II; ++ iterator->consoles[1] = RC_CONSOLE_COMMODORE_64; ++} ++ ++static void rc_hash_initialize_iterator_rom(rc_hash_iterator_t* iterator, int data) { ++ (void)data; ++ ++ /* rom is associated with MSX, Thomson TO-8, and Fairchild Channel F. ++ * Since they all use the same hashing algorithm, only specify one of them */ ++ iterator->consoles[0] = RC_CONSOLE_MSX; ++} ++ ++static void rc_hash_initialize_iterator_tap(rc_hash_iterator_t* iterator, int data) { ++ (void)data; ++ ++ /* also Oric and ZX Spectrum, but all are full file hashes */ ++ iterator->consoles[0] = RC_CONSOLE_COMMODORE_64; ++} ++ ++static const rc_hash_iterator_ext_handler_entry_t rc_hash_iterator_ext_handlers[] = { ++ { "2d", rc_hash_initialize_iterator_single, RC_CONSOLE_SHARPX1 }, ++ { "3ds", rc_hash_initialize_iterator_single, RC_CONSOLE_NINTENDO_3DS }, ++ { "3dsx", rc_hash_initialize_iterator_single, RC_CONSOLE_NINTENDO_3DS }, ++ { "7z", rc_hash_initialize_iterator_single, RC_CONSOLE_ARCADE }, ++ { "83g", rc_hash_initialize_iterator_single, RC_CONSOLE_TI83 }, /* http://tibasicdev.wikidot.com/file-extensions */ ++ { "83p", rc_hash_initialize_iterator_single, RC_CONSOLE_TI83 }, ++ { "a26", rc_hash_initialize_iterator_single, RC_CONSOLE_ATARI_2600 }, ++ { "a78", rc_hash_initialize_iterator_single, RC_CONSOLE_ATARI_7800 }, ++ { "app", rc_hash_initialize_iterator_single, RC_CONSOLE_NINTENDO_3DS }, ++ { "arduboy", rc_hash_initialize_iterator_single, RC_CONSOLE_ARDUBOY }, ++ { "axf", rc_hash_initialize_iterator_single, RC_CONSOLE_NINTENDO_3DS }, ++ { "bin", rc_hash_initialize_iterator_bin, 0 }, ++ { "bs", rc_hash_initialize_iterator_single, RC_CONSOLE_SUPER_NINTENDO }, ++ { "cart", rc_hash_initialize_iterator_single, RC_CONSOLE_SUPER_CASSETTEVISION }, ++ { "cas", rc_hash_initialize_iterator_single, RC_CONSOLE_MSX }, ++ { "cci", rc_hash_initialize_iterator_single, RC_CONSOLE_NINTENDO_3DS }, ++ { "chd", rc_hash_initialize_iterator_chd, 0 }, ++ { "chf", rc_hash_initialize_iterator_single, RC_CONSOLE_FAIRCHILD_CHANNEL_F }, ++ { "cia", rc_hash_initialize_iterator_single, RC_CONSOLE_NINTENDO_3DS }, ++ { "col", rc_hash_initialize_iterator_single, RC_CONSOLE_COLECOVISION }, ++ { "csw", rc_hash_initialize_iterator_single, RC_CONSOLE_ZX_SPECTRUM }, ++ { "cue", rc_hash_initialize_iterator_cue, 0 }, ++ { "cxi", rc_hash_initialize_iterator_single, RC_CONSOLE_NINTENDO_3DS }, ++ { "d64", rc_hash_initialize_iterator_single, RC_CONSOLE_COMMODORE_64 }, ++ { "d88", rc_hash_initialize_iterator_d88, 0 }, ++ { "dosz", rc_hash_initialize_iterator_single, RC_CONSOLE_MS_DOS }, ++ { "dsk", rc_hash_initialize_iterator_dsk, 0 }, ++ { "elf", rc_hash_initialize_iterator_single, RC_CONSOLE_NINTENDO_3DS }, ++ { "fd", rc_hash_initialize_iterator_single, RC_CONSOLE_THOMSONTO8 }, ++ { "fds", rc_hash_initialize_iterator_single, RC_CONSOLE_NINTENDO }, ++ { "fig", rc_hash_initialize_iterator_single, RC_CONSOLE_SUPER_NINTENDO }, ++ { "gb", rc_hash_initialize_iterator_single, RC_CONSOLE_GAMEBOY }, ++ { "gba", rc_hash_initialize_iterator_single, RC_CONSOLE_GAMEBOY_ADVANCE }, ++ { "gbc", rc_hash_initialize_iterator_single, RC_CONSOLE_GAMEBOY_COLOR }, ++ { "gdi", rc_hash_initialize_iterator_single, RC_CONSOLE_DREAMCAST }, ++ { "gg", rc_hash_initialize_iterator_single, RC_CONSOLE_GAME_GEAR }, ++ { "hex", rc_hash_initialize_iterator_single, RC_CONSOLE_ARDUBOY }, ++ { "iso", rc_hash_initialize_iterator_iso, 0 }, ++ { "jag", rc_hash_initialize_iterator_single, RC_CONSOLE_ATARI_JAGUAR }, ++ { "k7", rc_hash_initialize_iterator_single, RC_CONSOLE_THOMSONTO8 }, /* tape */ ++ { "lnx", rc_hash_initialize_iterator_single, RC_CONSOLE_ATARI_LYNX }, ++ { "m3u", rc_hash_initialize_iterator_m3u, 0 }, ++ { "m5", rc_hash_initialize_iterator_single, RC_CONSOLE_THOMSONTO8 }, /* cartridge */ ++ { "m7", rc_hash_initialize_iterator_single, RC_CONSOLE_THOMSONTO8 }, /* cartridge */ ++ { "md", rc_hash_initialize_iterator_single, RC_CONSOLE_MEGA_DRIVE }, ++ { "min", rc_hash_initialize_iterator_single, RC_CONSOLE_POKEMON_MINI }, ++ { "mx1", rc_hash_initialize_iterator_single, RC_CONSOLE_MSX }, ++ { "mx2", rc_hash_initialize_iterator_single, RC_CONSOLE_MSX }, ++ { "n64", rc_hash_initialize_iterator_single, RC_CONSOLE_NINTENDO_64 }, ++ { "ndd", rc_hash_initialize_iterator_single, RC_CONSOLE_NINTENDO_64 }, ++ { "nds", rc_hash_initialize_iterator_single, RC_CONSOLE_NINTENDO_DS }, /* handles both DS and DSi */ ++ { "nes", rc_hash_initialize_iterator_single, RC_CONSOLE_NINTENDO }, ++ { "ngc", rc_hash_initialize_iterator_single, RC_CONSOLE_NEOGEO_POCKET }, ++ { "nib", rc_hash_initialize_iterator_nib, 0 }, ++ { "pbp", rc_hash_initialize_iterator_single, RC_CONSOLE_PSP }, ++ { "pce", rc_hash_initialize_iterator_single, RC_CONSOLE_PC_ENGINE }, ++ { "pgm", rc_hash_initialize_iterator_single, RC_CONSOLE_ELEKTOR_TV_GAMES_COMPUTER }, ++ { "pzx", rc_hash_initialize_iterator_single, RC_CONSOLE_ZX_SPECTRUM }, ++ { "ri", rc_hash_initialize_iterator_single, RC_CONSOLE_MSX }, ++ { "rom", rc_hash_initialize_iterator_rom, 0 }, ++ { "sap", rc_hash_initialize_iterator_single, RC_CONSOLE_THOMSONTO8 }, /* disk */ ++ { "scl", rc_hash_initialize_iterator_single, RC_CONSOLE_ZX_SPECTRUM }, ++ { "sfc", rc_hash_initialize_iterator_single, RC_CONSOLE_SUPER_NINTENDO }, ++ { "sg", rc_hash_initialize_iterator_single, RC_CONSOLE_SG1000 }, ++ { "sgx", rc_hash_initialize_iterator_single, RC_CONSOLE_PC_ENGINE }, ++ { "smc", rc_hash_initialize_iterator_single, RC_CONSOLE_SUPER_NINTENDO }, ++ { "sv", rc_hash_initialize_iterator_single, RC_CONSOLE_SUPERVISION }, ++ { "swc", rc_hash_initialize_iterator_single, RC_CONSOLE_SUPER_NINTENDO }, ++ { "tap", rc_hash_initialize_iterator_tap, 0 }, ++ { "tic", rc_hash_initialize_iterator_single, RC_CONSOLE_TIC80 }, ++ { "trd", rc_hash_initialize_iterator_single, RC_CONSOLE_ZX_SPECTRUM }, ++ { "tvc", rc_hash_initialize_iterator_single, RC_CONSOLE_ELEKTOR_TV_GAMES_COMPUTER }, ++ { "tzx", rc_hash_initialize_iterator_single, RC_CONSOLE_ZX_SPECTRUM }, ++ { "uze", rc_hash_initialize_iterator_single, RC_CONSOLE_UZEBOX }, ++ { "v64", rc_hash_initialize_iterator_single, RC_CONSOLE_NINTENDO_64 }, ++ { "vb", rc_hash_initialize_iterator_single, RC_CONSOLE_VIRTUAL_BOY }, ++ { "wad", rc_hash_initialize_iterator_single, RC_CONSOLE_WII }, ++ { "wasm", rc_hash_initialize_iterator_single, RC_CONSOLE_WASM4 }, ++ { "woz", rc_hash_initialize_iterator_single, RC_CONSOLE_APPLE_II }, ++ { "wsc", rc_hash_initialize_iterator_single, RC_CONSOLE_WONDERSWAN }, ++ { "z64", rc_hash_initialize_iterator_single, RC_CONSOLE_NINTENDO_64 }, ++ { "zip", rc_hash_initialize_iterator_single, RC_CONSOLE_ARCADE } ++}; ++ ++const rc_hash_iterator_ext_handler_entry_t* rc_hash_get_iterator_ext_handlers(size_t* num_handlers) { ++ *num_handlers = sizeof(rc_hash_iterator_ext_handlers) / sizeof(rc_hash_iterator_ext_handlers[0]); ++ return rc_hash_iterator_ext_handlers; ++} ++ ++static int rc_hash_iterator_find_handler(const void* left, const void* right) { ++ const rc_hash_iterator_ext_handler_entry_t* left_handler = ++ (const rc_hash_iterator_ext_handler_entry_t*)left; ++ const rc_hash_iterator_ext_handler_entry_t* right_handler = ++ (const rc_hash_iterator_ext_handler_entry_t*)right; ++ ++ return strcmp(left_handler->ext, right_handler->ext); ++} ++ ++static void rc_hash_initialize_iterator_from_path(rc_hash_iterator_t* iterator, const char* path) { ++ size_t num_handlers; ++ const rc_hash_iterator_ext_handler_entry_t* handlers = rc_hash_get_iterator_ext_handlers(&num_handlers); ++ const rc_hash_iterator_ext_handler_entry_t* handler; ++ rc_hash_iterator_ext_handler_entry_t search; ++ const char* ext = rc_path_get_extension(path); ++ size_t index; ++ ++ /* lowercase the extension as we copy it into the search object */ ++ memset(&search, 0, sizeof(search)); ++ for (index = 0; index < sizeof(search.ext) - 1; ++index) { ++ const int c = (int)ext[index]; ++ if (!c) ++ break; ++ ++ search.ext[index] = tolower(c); ++ } ++ ++ /* find the handler for the extension */ ++ handler = (const rc_hash_iterator_ext_handler_entry_t*) ++ bsearch(&search, handlers, num_handlers, sizeof(*handler), rc_hash_iterator_find_handler); ++ if (handler) { ++ handler->handler(iterator, handler->data); ++ ++ if (iterator->callbacks.verbose_message) { ++ int count = 0; ++ while (iterator->consoles[count]) ++ ++count; ++ ++ rc_hash_iterator_verbose_formatted(iterator, "Found %d potential consoles for %s file extension", count, ext); ++ } ++ } ++ else { ++ rc_hash_iterator_error_formatted(iterator, "No console mapping specified for %s file extension - trying full file hash", ext); ++ ++ /* if we didn't match the extension, default to something that does a whole file hash */ ++ if (!iterator->consoles[0]) ++ iterator->consoles[0] = RC_CONSOLE_GAMEBOY; ++ } ++} ++ ++void rc_hash_initialize_iterator(rc_hash_iterator_t* iterator, const char* path, const uint8_t* buffer, size_t buffer_size) ++{ ++ rc_hash_reset_iterator(iterator); ++ iterator->buffer = buffer; ++ iterator->buffer_size = buffer_size; ++ ++ if (path) ++ iterator->path = strdup(path); ++} ++ ++void rc_hash_destroy_iterator(rc_hash_iterator_t* iterator) { ++ if (iterator->path) { ++ free((void*)iterator->path); ++ iterator->path = NULL; ++ } ++ ++ iterator->buffer = NULL; ++} ++ ++int rc_hash_iterate(char hash[33], rc_hash_iterator_t* iterator) { ++ int next_console; ++ int result = 0; ++ ++ if (iterator->index == -1) { ++ rc_hash_initialize_iterator_from_path(iterator, iterator->path); ++ iterator->index = 0; ++ } ++ ++ do { ++ next_console = iterator->consoles[iterator->index]; ++ if (next_console == 0) { ++ hash[0] = '\0'; ++ break; ++ } ++ ++ ++iterator->index; ++ ++ rc_hash_iterator_verbose_formatted(iterator, "Trying console %d", next_console); ++ ++ result = rc_hash_generate(hash, next_console, iterator); ++ } while (!result); ++ ++ return result; ++} ++ ++int rc_hash_generate(char hash[33], uint32_t console_id, const rc_hash_iterator_t* iterator) { ++ if (iterator->buffer) ++ return rc_hash_from_buffer(hash, console_id, iterator); ++ ++ return rc_hash_from_file(hash, console_id, iterator); ++} ++ ++int rc_hash_generate_from_buffer(char hash[33], uint32_t console_id, const uint8_t* buffer, size_t buffer_size) { ++ rc_hash_iterator_t iterator; ++ int result; ++ ++ rc_hash_reset_iterator(&iterator); ++ iterator.buffer = buffer; ++ iterator.buffer_size = buffer_size; ++ ++ result = rc_hash_from_buffer(hash, console_id, &iterator); ++ ++ rc_hash_destroy_iterator(&iterator); ++ ++ return result; ++} ++ ++int rc_hash_generate_from_file(char hash[33], uint32_t console_id, const char* path){ ++ rc_hash_iterator_t iterator; ++ int result; ++ ++ rc_hash_reset_iterator(&iterator); ++ iterator.path = path; ++ ++ result = rc_hash_from_file(hash, console_id, &iterator); ++ ++ iterator.path = NULL; /* prevent free. we didn't strdup */ ++ ++ rc_hash_destroy_iterator(&iterator); ++ ++ return result; ++} +diff -rupbN melonDS.orig/src/rcheevos/src/rhash/hash_disc.c melonDS.ra/src/rcheevos/src/rhash/hash_disc.c +--- melonDS.orig/src/rcheevos/src/rhash/hash_disc.c 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rhash/hash_disc.c 2026-03-06 21:37:07.046799886 +0000 +@@ -0,0 +1,1340 @@ ++#include "rc_hash.h" ++ ++#include "rc_hash_internal.h" ++ ++#include "../rc_compat.h" ++ ++#include ++ ++/* ===================================================== */ ++ ++static struct rc_hash_cdreader g_cdreader_funcs; ++static struct rc_hash_cdreader* g_cdreader = NULL; ++ ++void rc_hash_reset_iterator_disc(rc_hash_iterator_t* iterator) ++{ ++ if (g_cdreader) ++ memcpy(&iterator->callbacks.cdreader, g_cdreader, sizeof(*g_cdreader)); ++ else ++ rc_hash_get_default_cdreader(&iterator->callbacks.cdreader); ++} ++ ++void rc_hash_init_custom_cdreader(struct rc_hash_cdreader* reader) ++{ ++ if (reader) { ++ memcpy(&g_cdreader_funcs, reader, sizeof(g_cdreader_funcs)); ++ g_cdreader = &g_cdreader_funcs; ++ } ++ else { ++ g_cdreader = NULL; ++ } ++} ++ ++static void* rc_cd_open_track(const rc_hash_iterator_t* iterator, uint32_t track) ++{ ++ if (iterator->callbacks.cdreader.open_track_iterator) ++ return iterator->callbacks.cdreader.open_track_iterator(iterator->path, track, iterator); ++ ++ if (iterator->callbacks.cdreader.open_track) ++ return iterator->callbacks.cdreader.open_track(iterator->path, track); ++ ++ if (g_cdreader && g_cdreader->open_track) ++ return g_cdreader->open_track(iterator->path, track); ++ ++ rc_hash_iterator_error(iterator, "no hook registered for cdreader_open_track"); ++ return NULL; ++} ++ ++static size_t rc_cd_read_sector(const rc_hash_iterator_t* iterator, void* track_handle, uint32_t sector, void* buffer, size_t requested_bytes) ++{ ++ if (iterator->callbacks.cdreader.read_sector) ++ return iterator->callbacks.cdreader.read_sector(track_handle, sector, buffer, requested_bytes); ++ ++ if (g_cdreader && g_cdreader->read_sector) ++ return g_cdreader->read_sector(track_handle, sector, buffer, requested_bytes); ++ ++ rc_hash_iterator_error(iterator, "no hook registered for cdreader_read_sector"); ++ return 0; ++} ++ ++static uint32_t rc_cd_first_track_sector(const rc_hash_iterator_t* iterator, void* track_handle) ++{ ++ if (iterator->callbacks.cdreader.first_track_sector) ++ return iterator->callbacks.cdreader.first_track_sector(track_handle); ++ ++ if (g_cdreader && g_cdreader->first_track_sector) ++ return g_cdreader->first_track_sector(track_handle); ++ ++ rc_hash_iterator_error(iterator, "no hook registered for cdreader_first_track_sector"); ++ return 0; ++} ++ ++static void rc_cd_close_track(const rc_hash_iterator_t* iterator, void* track_handle) ++{ ++ if (iterator->callbacks.cdreader.close_track) ++ iterator->callbacks.cdreader.close_track(track_handle); ++ else if (g_cdreader && g_cdreader->close_track) ++ g_cdreader->close_track(track_handle); ++ else ++ rc_hash_iterator_error(iterator, "no hook registered for cdreader_close_track"); ++} ++ ++static uint32_t rc_cd_find_file_sector(const rc_hash_iterator_t* iterator, void* track_handle, const char* path, uint32_t* size) ++{ ++ uint8_t buffer[2048], *tmp; ++ int sector; ++ uint32_t num_sectors = 0; ++ size_t filename_length; ++ const char* slash; ++ ++ if (!track_handle) ++ return 0; ++ ++ /* we start at the root. don't need to explicitly find it */ ++ if (*path == '\\') ++ ++path; ++ ++ filename_length = strlen(path); ++ slash = strrchr(path, '\\'); ++ if (slash) { ++ /* find the directory record for the first part of the path */ ++ memcpy(buffer, path, slash - path); ++ buffer[slash - path] = '\0'; ++ ++ sector = rc_cd_find_file_sector(iterator, track_handle, (const char *)buffer, NULL); ++ if (!sector) ++ return 0; ++ ++ ++slash; ++ filename_length -= (slash - path); ++ path = slash; ++ } ++ else { ++ uint32_t logical_block_size; ++ ++ /* find the cd information */ ++ if (!rc_cd_read_sector(iterator, track_handle, rc_cd_first_track_sector(iterator, track_handle) + 16, buffer, 256)) ++ return 0; ++ ++ /* the directory_record starts at 156, the sector containing the table of contents is 2 bytes into that. ++ * https://www.cdroller.com/htm/readdata.html ++ */ ++ sector = buffer[156 + 2] | (buffer[156 + 3] << 8) | (buffer[156 + 4] << 16); ++ ++ /* if the table of contents spans more than one sector, it's length of section will exceed it's logical block size */ ++ logical_block_size = (buffer[128] | (buffer[128 + 1] << 8)); /* logical block size */ ++ if (logical_block_size == 0) { ++ num_sectors = 1; ++ } else { ++ num_sectors = (buffer[156 + 10] | (buffer[156 + 11] << 8) | (buffer[156 + 12] << 16) | (buffer[156 + 13] << 24)); /* length of section */ ++ num_sectors /= logical_block_size; ++ } ++ } ++ ++ /* fetch and process the directory record */ ++ if (!rc_cd_read_sector(iterator, track_handle, sector, buffer, sizeof(buffer))) ++ return 0; ++ ++ tmp = buffer; ++ do { ++ if (tmp >= buffer + sizeof(buffer) || !*tmp) { ++ /* end of this path table block. if the path table spans multiple sectors, keep scanning */ ++ if (num_sectors > 1) { ++ --num_sectors; ++ if (rc_cd_read_sector(iterator, track_handle, ++sector, buffer, sizeof(buffer))) { ++ tmp = buffer; ++ continue; ++ } ++ } ++ break; ++ } ++ ++ /* filename is 33 bytes into the record and the format is "FILENAME;version" or "DIRECTORY" */ ++ if ((tmp[32] == filename_length || tmp[33 + filename_length] == ';') && ++ strncasecmp((const char*)(tmp + 33), path, filename_length) == 0) { ++ sector = tmp[2] | (tmp[3] << 8) | (tmp[4] << 16); ++ ++ rc_hash_iterator_verbose_formatted(iterator, "Found %s at sector %d", path, sector); ++ ++ if (size) ++ *size = tmp[10] | (tmp[11] << 8) | (tmp[12] << 16) | (tmp[13] << 24); ++ ++ return sector; ++ } ++ ++ /* the first byte of the record is the length of the record */ ++ tmp += *tmp; ++ } while (1); ++ ++ return 0; ++} ++ ++/* ===================================================== */ ++ ++static int rc_hash_cd_file(md5_state_t* md5, const rc_hash_iterator_t* iterator, void* track_handle, uint32_t sector, const char* name, uint32_t size, const char* description) ++{ ++ uint8_t buffer[2048]; ++ size_t num_read; ++ ++ if ((num_read = rc_cd_read_sector(iterator, track_handle, sector, buffer, sizeof(buffer))) < sizeof(buffer)) ++ return rc_hash_iterator_error_formatted(iterator, "Could not read %s", description); ++ ++ if (size > MAX_BUFFER_SIZE) ++ size = MAX_BUFFER_SIZE; ++ ++ if (name) ++ rc_hash_iterator_verbose_formatted(iterator, "Hashing %s title (%u bytes) and contents (%u bytes) ", name, (unsigned)strlen(name), size); ++ else ++ rc_hash_iterator_verbose_formatted(iterator, "Hashing %s contents (%u bytes @ sector %u)", description, size, sector); ++ ++ if (size < (unsigned)num_read) /* we read a whole sector - only hash the part containing file data */ ++ num_read = (size_t)size; ++ ++ do { ++ md5_append(md5, buffer, (int)num_read); ++ ++ if (size <= (unsigned)num_read) ++ break; ++ size -= (unsigned)num_read; ++ ++ ++sector; ++ if (size >= sizeof(buffer)) ++ num_read = rc_cd_read_sector(iterator, track_handle, sector, buffer, sizeof(buffer)); ++ else ++ num_read = rc_cd_read_sector(iterator, track_handle, sector, buffer, size); ++ } while (num_read > 0); ++ ++ return 1; ++} ++ ++/* ===================================================== */ ++ ++int rc_hash_3do(char hash[33], const rc_hash_iterator_t* iterator) ++{ ++ uint8_t buffer[2048]; ++ const uint8_t operafs_identifier[7] = { 0x01, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x01 }; ++ void* track_handle; ++ md5_state_t md5; ++ int sector; ++ int block_size, block_location; ++ int offset, stop; ++ size_t size = 0; ++ ++ track_handle = rc_cd_open_track(iterator, 1); ++ if (!track_handle) ++ return rc_hash_iterator_error(iterator, "Could not open track"); ++ ++ /* the Opera filesystem stores the volume information in the first 132 bytes of sector 0 ++ * https://github.com/barbeque/3dodump/blob/master/OperaFS-Format.md ++ */ ++ rc_cd_read_sector(iterator, track_handle, 0, buffer, 132); ++ ++ if (memcmp(buffer, operafs_identifier, sizeof(operafs_identifier)) == 0) { ++ rc_hash_iterator_verbose_formatted(iterator, "Found 3DO CD, title=%.32s", &buffer[0x28]); ++ ++ /* include the volume header in the hash */ ++ md5_init(&md5); ++ md5_append(&md5, buffer, 132); ++ ++ /* the block size is at offset 0x4C (assume 0x4C is always 0) */ ++ block_size = buffer[0x4D] * 65536 + buffer[0x4E] * 256 + buffer[0x4F]; ++ ++ /* the root directory block location is at offset 0x64 (and duplicated several ++ * times, but we just look at the primary record) (assume 0x64 is always 0)*/ ++ block_location = buffer[0x65] * 65536 + buffer[0x66] * 256 + buffer[0x67]; ++ ++ /* multiply the block index by the block size to get the real address */ ++ block_location *= block_size; ++ ++ /* convert that to a sector and read it */ ++ sector = block_location / 2048; ++ ++ do { ++ rc_cd_read_sector(iterator, track_handle, sector, buffer, sizeof(buffer)); ++ ++ /* offset to start of entries is at offset 0x10 (assume 0x10 and 0x11 are always 0) */ ++ offset = buffer[0x12] * 256 + buffer[0x13]; ++ ++ /* offset to end of entries is at offset 0x0C (assume 0x0C is always 0) */ ++ stop = buffer[0x0D] * 65536 + buffer[0x0E] * 256 + buffer[0x0F]; ++ ++ while (offset < stop) { ++ if (buffer[offset + 0x03] == 0x02) { /* file */ ++ if (strcasecmp((const char*)&buffer[offset + 0x20], "LaunchMe") == 0) { ++ /* the block size is at offset 0x0C (assume 0x0C is always 0) */ ++ block_size = buffer[offset + 0x0D] * 65536 + buffer[offset + 0x0E] * 256 + buffer[offset + 0x0F]; ++ ++ /* the block location is at offset 0x44 (assume 0x44 is always 0) */ ++ block_location = buffer[offset + 0x45] * 65536 + buffer[offset + 0x46] * 256 + buffer[offset + 0x47]; ++ block_location *= block_size; ++ ++ /* the file size is at offset 0x10 (assume 0x10 is always 0) */ ++ size = (size_t)buffer[offset + 0x11] * 65536 + buffer[offset + 0x12] * 256 + buffer[offset + 0x13]; ++ ++ rc_hash_iterator_verbose_formatted(iterator, "Hashing header (%u bytes) and %.32s (%u bytes) ", 132, &buffer[offset + 0x20], (unsigned)size); ++ ++ break; ++ } ++ } ++ ++ /* the number of extra copies of the file is at offset 0x40 (assume 0x40-0x42 are always 0) */ ++ offset += 0x48 + buffer[offset + 0x43] * 4; ++ } ++ ++ if (size != 0) ++ break; ++ ++ /* did not find the file, see if the directory listing is continued in another sector */ ++ offset = buffer[0x02] * 256 + buffer[0x03]; ++ ++ /* no more sectors to search*/ ++ if (offset == 0xFFFF) ++ break; ++ ++ /* get next sector */ ++ offset *= block_size; ++ sector = (block_location + offset) / 2048; ++ } while (1); ++ ++ if (size == 0) { ++ rc_cd_close_track(iterator, track_handle); ++ return rc_hash_iterator_error(iterator, "Could not find LaunchMe"); ++ } ++ ++ sector = block_location / 2048; ++ ++ while (size > 2048) { ++ rc_cd_read_sector(iterator, track_handle, sector, buffer, sizeof(buffer)); ++ md5_append(&md5, buffer, sizeof(buffer)); ++ ++ ++sector; ++ size -= 2048; ++ } ++ ++ rc_cd_read_sector(iterator, track_handle, sector, buffer, size); ++ md5_append(&md5, buffer, (int)size); ++ } ++ else { ++ rc_cd_close_track(iterator, track_handle); ++ return rc_hash_iterator_error(iterator, "Not a 3DO CD"); ++ } ++ ++ rc_cd_close_track(iterator, track_handle); ++ ++ return rc_hash_finalize(iterator, &md5, hash); ++} ++ ++int rc_hash_dreamcast(char hash[33], const rc_hash_iterator_t* iterator) ++{ ++ uint8_t buffer[256] = ""; ++ void* track_handle; ++ char exe_file[32] = ""; ++ uint32_t size; ++ uint32_t sector; ++ int result = 0; ++ md5_state_t md5; ++ int i = 0; ++ ++ /* track 03 is the data track that contains the TOC and IP.BIN */ ++ track_handle = rc_cd_open_track(iterator, 3); ++ if (track_handle) { ++ /* first 256 bytes from first sector should have IP.BIN structure that stores game meta information ++ * https://mc.pp.se/dc/ip.bin.html */ ++ rc_cd_read_sector(iterator, track_handle, rc_cd_first_track_sector(iterator, track_handle), buffer, sizeof(buffer)); ++ } ++ ++ if (memcmp(&buffer[0], "SEGA SEGAKATANA ", 16) != 0) { ++ if (track_handle) ++ rc_cd_close_track(iterator, track_handle); ++ ++ /* not a gd-rom dreamcast file. check for mil-cd by looking for the marker in the first data track */ ++ track_handle = rc_cd_open_track(iterator, RC_HASH_CDTRACK_FIRST_DATA); ++ if (!track_handle) ++ return rc_hash_iterator_error(iterator, "Could not open track"); ++ ++ rc_cd_read_sector(iterator, track_handle, rc_cd_first_track_sector(iterator, track_handle), buffer, sizeof(buffer)); ++ if (memcmp(&buffer[0], "SEGA SEGAKATANA ", 16) != 0) { ++ /* did not find marker on track 3 or first data track */ ++ rc_cd_close_track(iterator, track_handle); ++ return rc_hash_iterator_error(iterator, "Not a Dreamcast CD"); ++ } ++ } ++ ++ /* start the hash with the game meta information */ ++ md5_init(&md5); ++ md5_append(&md5, (md5_byte_t*)buffer, 256); ++ ++ if (iterator->callbacks.verbose_message) { ++ uint8_t* ptr = &buffer[0xFF]; ++ while (ptr > &buffer[0x80] && ptr[-1] == ' ') ++ --ptr; ++ *ptr = '\0'; ++ ++ rc_hash_iterator_verbose_formatted(iterator, "Found Dreamcast CD: %.128s (%.16s)", (const char*)&buffer[0x80], (const char*)&buffer[0x40]); ++ } ++ ++ /* the boot filename is 96 bytes into the meta information (https://mc.pp.se/dc/ip0000.bin.html) */ ++ /* remove whitespace from bootfile */ ++ i = 0; ++ while (!isspace((unsigned char)buffer[96 + i]) && i < 16) ++ ++i; ++ ++ /* sometimes boot file isn't present on meta information. ++ * nothing can be done, as even the core doesn't run the game in this case. */ ++ if (i == 0) { ++ rc_cd_close_track(iterator, track_handle); ++ return rc_hash_iterator_error(iterator, "Boot executable not specified on IP.BIN"); ++ } ++ ++ memcpy(exe_file, &buffer[96], i); ++ exe_file[i] = '\0'; ++ ++ sector = rc_cd_find_file_sector(iterator, track_handle, exe_file, &size); ++ if (sector == 0) { ++ rc_cd_close_track(iterator, track_handle); ++ return rc_hash_iterator_error(iterator, "Could not locate boot executable"); ++ } ++ ++ if (rc_cd_read_sector(iterator, track_handle, sector, buffer, 1)) { ++ /* the boot executable is in the primary data track */ ++ } ++ else { ++ rc_cd_close_track(iterator, track_handle); ++ ++ /* the boot executable is normally in the last track */ ++ track_handle = rc_cd_open_track(iterator, RC_HASH_CDTRACK_LAST); ++ } ++ ++ result = rc_hash_cd_file(&md5, iterator, track_handle, sector, NULL, size, "boot executable"); ++ rc_cd_close_track(iterator, track_handle); ++ ++ rc_hash_finalize(iterator, &md5, hash); ++ return result; ++} ++ ++static int rc_hash_nintendo_disc_partition(md5_state_t* md5, const rc_hash_iterator_t* iterator, ++ void* file_handle, const uint32_t part_offset, uint8_t wii_shift) ++{ ++ const uint32_t BASE_HEADER_SIZE = 0x2440; ++ const uint32_t MAX_HEADER_SIZE = 1024 * 1024; ++ ++ uint32_t apploader_header_size, apploader_body_size, apploader_trailer_size, header_size; ++ ++ uint8_t quad_buffer[4]; ++ uint8_t addr_buffer[0xD8]; ++ uint8_t* buffer; ++ ++ uint64_t dol_offset; ++ uint64_t dol_offsets[18]; ++ uint64_t dol_sizes[18]; ++ ++ uint8_t ix; ++ uint64_t remaining_size; ++ const uint32_t MAX_CHUNK_SIZE = 1024 * 1024; ++ ++ /* GetApploaderSize */ ++ rc_file_seek(iterator, file_handle, part_offset + BASE_HEADER_SIZE + 0x14, SEEK_SET); ++ apploader_header_size = 0x20; ++ rc_file_read(iterator, file_handle, quad_buffer, 4); ++ apploader_body_size = ++ (quad_buffer[0] << 24) | (quad_buffer[1] << 16) | (quad_buffer[2] << 8) | quad_buffer[3]; ++ rc_file_read(iterator, file_handle, quad_buffer, 4); ++ apploader_trailer_size = ++ (quad_buffer[0] << 24) | (quad_buffer[1] << 16) | (quad_buffer[2] << 8) | quad_buffer[3]; ++ header_size = BASE_HEADER_SIZE + apploader_header_size + apploader_body_size + apploader_trailer_size; ++ if (header_size > MAX_HEADER_SIZE) header_size = MAX_HEADER_SIZE; ++ ++ /* Hash headers */ ++ buffer = (uint8_t*)malloc(header_size); ++ if (!buffer) { ++ rc_file_close(iterator, file_handle); ++ return rc_hash_iterator_error(iterator, "Could not allocate temporary buffer"); ++ } ++ rc_file_seek(iterator, file_handle, part_offset, SEEK_SET); ++ rc_file_read(iterator, file_handle, buffer, header_size); ++ rc_hash_iterator_verbose_formatted(iterator, "Hashing %u byte partition header", header_size); ++ md5_append(md5, buffer, header_size); ++ ++ /* GetBootDOLOffset ++ * Base header size is guaranteed larger than 0x423 therefore buffer contains dol_offset right now ++ */ ++ dol_offset = (((uint64_t)buffer[0x420] << 24) | ++ ((uint64_t)buffer[0x421] << 16) | ++ ((uint64_t)buffer[0x422] << 8) | ++ (uint64_t)buffer[0x423]) << wii_shift; ++ free(buffer); ++ ++ /* Find offsets and sizes for the 7 main.dol code segments and 11 main.dol data segments */ ++ rc_file_seek(iterator, file_handle, part_offset + dol_offset, SEEK_SET); ++ rc_file_read(iterator, file_handle, addr_buffer, 0xD8); ++ for (ix = 0; ix < 18; ix++) { ++ dol_offsets[ix] = (((uint64_t)addr_buffer[0x0 + ix * 4] << 24) | ++ ((uint64_t)addr_buffer[0x1 + ix * 4] << 16) | ++ ((uint64_t)addr_buffer[0x2 + ix * 4] << 8) | ++ (uint64_t)addr_buffer[0x3 + ix * 4]) << wii_shift; ++ dol_sizes[ix] = (((uint64_t)addr_buffer[0x90 + ix * 4] << 24) | ++ ((uint64_t)addr_buffer[0x91 + ix * 4] << 16) | ++ ((uint64_t)addr_buffer[0x92 + ix * 4] << 8) | ++ (uint64_t)addr_buffer[0x93 + ix * 4]) << wii_shift; ++ } ++ ++ /* Iterate through the 18 main.dol segments and hash each */ ++ buffer = (uint8_t*)malloc(MAX_CHUNK_SIZE); ++ if (!buffer) { ++ rc_file_close(iterator, file_handle); ++ return rc_hash_iterator_error(iterator, "Could not allocate temporary buffer"); ++ } ++ ++ for (ix = 0; ix < 18; ix++) { ++ if (dol_sizes[ix] == 0) ++ continue; ++ ++ rc_file_seek(iterator, file_handle, part_offset + dol_offsets[ix], SEEK_SET); ++ if (ix < 7) ++ rc_hash_iterator_verbose_formatted(iterator, "Hashing %u byte main.dol code segment %u", dol_sizes[ix], ix); ++ else ++ rc_hash_iterator_verbose_formatted(iterator, "Hashing %u byte main.dol data segment %u", dol_sizes[ix], ix - 7); ++ ++ remaining_size = dol_sizes[ix]; ++ while (remaining_size > MAX_CHUNK_SIZE) { ++ rc_file_read(iterator, file_handle, buffer, MAX_CHUNK_SIZE); ++ md5_append(md5, buffer, MAX_CHUNK_SIZE); ++ remaining_size -= MAX_CHUNK_SIZE; ++ } ++ rc_file_read(iterator, file_handle, buffer, (int32_t)remaining_size); ++ md5_append(md5, buffer, (int32_t)remaining_size); ++ } ++ ++ free(buffer); ++ return 1; ++} ++ ++int rc_hash_gamecube(char hash[33], const rc_hash_iterator_t* iterator) ++{ ++ md5_state_t md5; ++ void* file_handle; ++ ++ uint8_t quad_buffer[4]; ++ uint8_t success; ++ ++ file_handle = rc_file_open(iterator, iterator->path); ++ if (!file_handle) ++ return rc_hash_iterator_error(iterator, "Could not open file"); ++ ++ md5_init(&md5); ++ /* Check Magic Word */ ++ rc_file_seek(iterator, file_handle, 0x1c, SEEK_SET); ++ rc_file_read(iterator, file_handle, quad_buffer, 4); ++ if (quad_buffer[0] == 0xC2 && quad_buffer[1] == 0x33 && quad_buffer[2] == 0x9F && quad_buffer[3] == 0x3D) ++ success = rc_hash_nintendo_disc_partition(&md5, iterator, file_handle, 0, 0); ++ else ++ success = rc_hash_iterator_error(iterator, "Not a Gamecube disc"); ++ ++ /* Finalize */ ++ rc_file_close(iterator, file_handle); ++ ++ if (success) ++ return rc_hash_finalize(iterator, &md5, hash); ++ ++ return 0; ++} ++ ++/* helper variable only used for testing */ ++const char* _rc_hash_jaguar_cd_homebrew_hash = NULL; ++ ++int rc_hash_jaguar_cd(char hash[33], const rc_hash_iterator_t* iterator) ++{ ++ uint8_t buffer[2352]; ++ void* track_handle; ++ md5_state_t md5; ++ int byteswapped = 0; ++ uint32_t size = 0; ++ uint32_t offset = 0; ++ uint32_t sector = 0; ++ uint32_t remaining; ++ uint32_t i; ++ ++ /* Jaguar CD header is in the first sector of the first data track OF THE SECOND SESSION. ++ * The first track must be an audio track, but may be a warning message or actual game audio */ ++ track_handle = rc_cd_open_track(iterator, RC_HASH_CDTRACK_FIRST_OF_SECOND_SESSION); ++ if (!track_handle) ++ return rc_hash_iterator_error(iterator, "Could not open track"); ++ ++ /* The header is an unspecified distance into the first sector, but usually two bytes in. ++ * It consists of 64 bytes of "TAIR" or "ATRI" repeating, depending on whether or not the data ++ * is byteswapped. Then another 32 byte that reads "ATARI APPROVED DATA HEADER ATRI " ++ * (possibly byteswapped). Then a big-endian 32-bit value for the address where the boot code ++ * should be loaded, and a second big-endian 32-bit value for the size of the boot code. */ ++ sector = rc_cd_first_track_sector(iterator, track_handle); ++ rc_cd_read_sector(iterator, track_handle, sector, buffer, sizeof(buffer)); ++ ++ for (i = 64; i < sizeof(buffer) - 32 - 4 * 3; i++) { ++ if (memcmp(&buffer[i], "TARA IPARPVODED TA AEHDAREA RT I", 32) == 0) { ++ byteswapped = 1; ++ offset = i + 32 + 4; ++ size = (buffer[offset] << 16) | (buffer[offset + 1] << 24) | (buffer[offset + 2]) | (buffer[offset + 3] << 8); ++ break; ++ } ++ else if (memcmp(&buffer[i], "ATARI APPROVED DATA HEADER ATRI ", 32) == 0) { ++ byteswapped = 0; ++ offset = i + 32 + 4; ++ size = (buffer[offset] << 24) | (buffer[offset + 1] << 16) | (buffer[offset + 2] << 8) | (buffer[offset + 3]); ++ break; ++ } ++ } ++ ++ if (size == 0) { /* did not see ATARI APPROVED DATA HEADER */ ++ rc_cd_close_track(iterator, track_handle); ++ return rc_hash_iterator_error(iterator, "Not a Jaguar CD"); ++ } ++ ++ i = 0; /* only loop once */ ++ do { ++ md5_init(&md5); ++ ++ offset += 4; ++ ++ rc_hash_iterator_verbose_formatted(iterator, "Hashing boot executable (%u bytes starting at %u bytes into sector %u)", size, offset, sector); ++ ++ if (size > MAX_BUFFER_SIZE) ++ size = MAX_BUFFER_SIZE; ++ ++ do { ++ if (byteswapped) ++ rc_hash_byteswap16(buffer, &buffer[sizeof(buffer)]); ++ ++ remaining = sizeof(buffer) - offset; ++ if (remaining >= size) { ++ md5_append(&md5, &buffer[offset], size); ++ size = 0; ++ break; ++ } ++ ++ md5_append(&md5, &buffer[offset], remaining); ++ size -= remaining; ++ offset = 0; ++ } while (rc_cd_read_sector(iterator, track_handle, ++sector, buffer, sizeof(buffer)) == sizeof(buffer)); ++ ++ rc_cd_close_track(iterator, track_handle); ++ ++ if (size > 0) ++ return rc_hash_iterator_error(iterator, "Not enough data"); ++ ++ rc_hash_finalize(iterator, &md5, hash); ++ ++ /* homebrew games all seem to have the same boot executable and store the actual game code in track 2. ++ * if we generated something other than the homebrew hash, return it. assume all homebrews are byteswapped. */ ++ if (strcmp(hash, "254487b59ab21bc005338e85cbf9fd2f") != 0 || !byteswapped) { ++ if (_rc_hash_jaguar_cd_homebrew_hash == NULL || strcmp(hash, _rc_hash_jaguar_cd_homebrew_hash) != 0) ++ return 1; ++ } ++ ++ /* if we've already been through the loop a second time, just return the hash */ ++ if (i == 1) ++ return 1; ++ ++i; ++ ++ rc_hash_iterator_verbose_formatted(iterator, "Potential homebrew at sector %u, checking for KART data in track 2", sector); ++ ++ track_handle = rc_cd_open_track(iterator, 2); ++ if (!track_handle) ++ return rc_hash_iterator_error(iterator, "Could not open track"); ++ ++ /* track 2 of the homebrew code has the 64 bytes or ATRI followed by 32 bytes of "ATARI APPROVED DATA HEADER ATRI!", ++ * then 64 bytes of KART repeating. */ ++ sector = rc_cd_first_track_sector(iterator, track_handle); ++ rc_cd_read_sector(iterator, track_handle, sector, buffer, sizeof(buffer)); ++ if (memcmp(&buffer[0x5E], "RT!IRTKA", 8) != 0) ++ return rc_hash_iterator_error(iterator, "Homebrew executable not found in track 2"); ++ ++ /* found KART data*/ ++ rc_hash_iterator_verbose(iterator, "Found KART data in track 2"); ++ ++ offset = 0xA6; ++ size = (buffer[offset] << 16) | (buffer[offset + 1] << 24) | (buffer[offset + 2]) | (buffer[offset + 3] << 8); ++ } while (1); ++} ++ ++int rc_hash_neogeo_cd(char hash[33], const rc_hash_iterator_t* iterator) ++{ ++ char buffer[1024], *ptr; ++ void* track_handle; ++ uint32_t sector; ++ uint32_t size; ++ md5_state_t md5; ++ ++ track_handle = rc_cd_open_track(iterator, 1); ++ if (!track_handle) ++ return rc_hash_iterator_error(iterator, "Could not open track"); ++ ++ /* https://wiki.neogeodev.org/index.php?title=IPL_file, https://wiki.neogeodev.org/index.php?title=PRG_file ++ * IPL file specifies data to be loaded before the game starts. PRG files are the executable code ++ */ ++ sector = rc_cd_find_file_sector(iterator, track_handle, "IPL.TXT", &size); ++ if (!sector) { ++ rc_cd_close_track(iterator, track_handle); ++ return rc_hash_iterator_error(iterator, "Not a NeoGeo CD game disc"); ++ } ++ ++ if (rc_cd_read_sector(iterator, track_handle, sector, buffer, sizeof(buffer)) == 0) { ++ rc_cd_close_track(iterator, track_handle); ++ return 0; ++ } ++ ++ md5_init(&md5); ++ ++ buffer[sizeof(buffer) - 1] = '\0'; ++ ptr = &buffer[0]; ++ do { ++ char* start = ptr; ++ while (*ptr && *ptr != '.') ++ ++ptr; ++ ++ if (strncasecmp(ptr, ".PRG", 4) == 0) { ++ ptr += 4; ++ *ptr++ = '\0'; ++ ++ sector = rc_cd_find_file_sector(iterator, track_handle, start, &size); ++ if (!sector || !rc_hash_cd_file(&md5, iterator, track_handle, sector, NULL, size, start)) { ++ rc_cd_close_track(iterator, track_handle); ++ return rc_hash_iterator_error_formatted(iterator, "Could not read %.16s", start); ++ } ++ } ++ ++ while (*ptr && *ptr != '\n') ++ ++ptr; ++ if (*ptr != '\n') ++ break; ++ ++ptr; ++ } while (*ptr != '\0' && *ptr != '\x1a'); ++ ++ rc_cd_close_track(iterator, track_handle); ++ return rc_hash_finalize(iterator, &md5, hash); ++} ++ ++static int rc_hash_pce_track(char hash[33], void* track_handle, const rc_hash_iterator_t* iterator) ++{ ++ uint8_t buffer[2048]; ++ md5_state_t md5; ++ uint32_t sector, num_sectors; ++ uint32_t size; ++ ++ /* the PC-Engine uses the second sector to specify boot information and program name. ++ * the string "PC Engine CD-ROM SYSTEM" should exist at 32 bytes into the sector ++ * http://shu.sheldows.com/shu/download/pcedocs/pce_cdrom.html ++ */ ++ if (rc_cd_read_sector(iterator, track_handle, rc_cd_first_track_sector(iterator, track_handle) + 1, buffer, 128) < 128) ++ return rc_hash_iterator_error(iterator, "Not a PC Engine CD"); ++ ++ /* normal PC Engine CD will have a header block in sector 1 */ ++ if (memcmp("PC Engine CD-ROM SYSTEM", &buffer[32], 23) == 0) { ++ /* the title of the disc is the last 22 bytes of the header */ ++ md5_init(&md5); ++ md5_append(&md5, &buffer[106], 22); ++ ++ buffer[128] = '\0'; ++ rc_hash_iterator_verbose_formatted(iterator, "Found PC Engine CD, title=%.22s", &buffer[106]); ++ ++ /* the first three bytes specify the sector of the program data, and the fourth byte ++ * is the number of sectors. ++ */ ++ sector = (buffer[0] << 16) + (buffer[1] << 8) + buffer[2]; ++ num_sectors = buffer[3]; ++ ++ rc_hash_iterator_verbose_formatted(iterator, "Hashing %d sectors starting at sector %d", num_sectors, sector); ++ ++ sector += rc_cd_first_track_sector(iterator, track_handle); ++ while (num_sectors > 0) { ++ rc_cd_read_sector(iterator, track_handle, sector, buffer, sizeof(buffer)); ++ md5_append(&md5, buffer, sizeof(buffer)); ++ ++ ++sector; ++ --num_sectors; ++ } ++ } ++ /* GameExpress CDs use a standard Joliet filesystem - locate and hash the BOOT.BIN */ ++ else if ((sector = rc_cd_find_file_sector(iterator, track_handle, "BOOT.BIN", &size)) != 0 && size < MAX_BUFFER_SIZE) { ++ md5_init(&md5); ++ while (size > sizeof(buffer)) { ++ rc_cd_read_sector(iterator, track_handle, sector, buffer, sizeof(buffer)); ++ md5_append(&md5, buffer, sizeof(buffer)); ++ ++ ++sector; ++ size -= sizeof(buffer); ++ } ++ ++ if (size > 0) { ++ rc_cd_read_sector(iterator, track_handle, sector, buffer, size); ++ md5_append(&md5, buffer, size); ++ } ++ } ++ else { ++ return rc_hash_iterator_error(iterator, "Not a PC Engine CD"); ++ } ++ ++ return rc_hash_finalize(iterator, &md5, hash); ++} ++ ++int rc_hash_pce_cd(char hash[33], const rc_hash_iterator_t* iterator) ++{ ++ int result; ++ void* track_handle = rc_cd_open_track(iterator, RC_HASH_CDTRACK_FIRST_DATA); ++ if (!track_handle) ++ return rc_hash_iterator_error(iterator, "Could not open track"); ++ ++ result = rc_hash_pce_track(hash, track_handle, iterator); ++ ++ rc_cd_close_track(iterator, track_handle); ++ ++ return result; ++} ++ ++int rc_hash_pcfx_cd(char hash[33], const rc_hash_iterator_t* iterator) ++{ ++ uint8_t buffer[2048]; ++ void* track_handle; ++ md5_state_t md5; ++ int sector, num_sectors; ++ ++ /* PC-FX executable can be in any track. Assume it's in the largest data track and check there first */ ++ track_handle = rc_cd_open_track(iterator, RC_HASH_CDTRACK_LARGEST); ++ if (!track_handle) ++ return rc_hash_iterator_error(iterator, "Could not open track"); ++ ++ /* PC-FX CD will have a header marker in sector 0 */ ++ sector = rc_cd_first_track_sector(iterator, track_handle); ++ rc_cd_read_sector(iterator, track_handle, sector, buffer, 32); ++ if (memcmp("PC-FX:Hu_CD-ROM", &buffer[0], 15) != 0) { ++ rc_cd_close_track(iterator, track_handle); ++ ++ /* not found in the largest data track, check track 2 */ ++ track_handle = rc_cd_open_track(iterator, 2); ++ if (!track_handle) ++ return rc_hash_iterator_error(iterator, "Could not open track"); ++ ++ sector = rc_cd_first_track_sector(iterator, track_handle); ++ rc_cd_read_sector(iterator, track_handle, sector, buffer, 32); ++ } ++ ++ if (memcmp("PC-FX:Hu_CD-ROM", &buffer[0], 15) == 0) { ++ /* PC-FX boot header fills the first two sectors of the disc ++ * https://bitbucket.org/trap15/pcfxtools/src/master/pcfx-cdlink.c ++ * the important stuff is the first 128 bytes of the second sector (title being the first 32) */ ++ rc_cd_read_sector(iterator, track_handle, sector + 1, buffer, 128); ++ ++ md5_init(&md5); ++ md5_append(&md5, buffer, 128); ++ ++ rc_hash_iterator_verbose_formatted(iterator, "Found PC-FX CD, title=%.32s", &buffer[0]); ++ ++ /* the program sector is in bytes 33-36 (assume byte 36 is 0) */ ++ sector = (buffer[34] << 16) + (buffer[33] << 8) + buffer[32]; ++ ++ /* the number of sectors the program occupies is in bytes 37-40 (assume byte 40 is 0) */ ++ num_sectors = (buffer[38] << 16) + (buffer[37] << 8) + buffer[36]; ++ ++ rc_hash_iterator_verbose_formatted(iterator, "Hashing %d sectors starting at sector %d", num_sectors, sector); ++ ++ sector += rc_cd_first_track_sector(iterator, track_handle); ++ while (num_sectors > 0) { ++ rc_cd_read_sector(iterator, track_handle, sector, buffer, sizeof(buffer)); ++ md5_append(&md5, buffer, sizeof(buffer)); ++ ++ ++sector; ++ --num_sectors; ++ } ++ } ++ else { ++ int result = 0; ++ rc_cd_read_sector(iterator, track_handle, sector + 1, buffer, 128); ++ ++ /* some PC-FX CDs still identify as PCE CDs */ ++ if (memcmp("PC Engine CD-ROM SYSTEM", &buffer[32], 23) == 0) ++ result = rc_hash_pce_track(hash, track_handle, iterator); ++ ++ rc_cd_close_track(iterator, track_handle); ++ if (result) ++ return result; ++ ++ return rc_hash_iterator_error(iterator, "Not a PC-FX CD"); ++ } ++ ++ rc_cd_close_track(iterator, track_handle); ++ ++ return rc_hash_finalize(iterator, &md5, hash); ++} ++ ++static int rc_hash_find_playstation_executable(const rc_hash_iterator_t* iterator, void* track_handle, ++ const char* boot_key, const char* cdrom_prefix, ++ char exe_name[], uint32_t exe_name_size, uint32_t* exe_size) ++{ ++ uint8_t buffer[2048]; ++ uint32_t size; ++ char* ptr; ++ char* start; ++ const size_t boot_key_len = strlen(boot_key); ++ const size_t cdrom_prefix_len = strlen(cdrom_prefix); ++ int sector; ++ ++ sector = rc_cd_find_file_sector(iterator, track_handle, "SYSTEM.CNF", NULL); ++ if (!sector) ++ return 0; ++ ++ size = (uint32_t)rc_cd_read_sector(iterator, track_handle, sector, buffer, sizeof(buffer) - 1); ++ buffer[size] = '\0'; ++ ++ sector = 0; ++ for (ptr = (char*)buffer; *ptr; ++ptr) { ++ if (strncmp(ptr, boot_key, boot_key_len) == 0) { ++ ptr += boot_key_len; ++ while (isspace((unsigned char)*ptr)) ++ ++ptr; ++ ++ if (*ptr == '=') { ++ ++ptr; ++ while (isspace((unsigned char)*ptr)) ++ ++ptr; ++ ++ if (strncmp(ptr, cdrom_prefix, cdrom_prefix_len) == 0) ++ ptr += cdrom_prefix_len; ++ while (*ptr == '\\') ++ ++ptr; ++ ++ start = ptr; ++ while (!isspace((unsigned char)*ptr) && *ptr != ';') ++ ++ptr; ++ ++ size = (uint32_t)(ptr - start); ++ if (size >= exe_name_size) ++ size = exe_name_size - 1; ++ ++ memcpy(exe_name, start, size); ++ exe_name[size] = '\0'; ++ ++ rc_hash_iterator_verbose_formatted(iterator, "Looking for boot executable: %s", exe_name); ++ ++ sector = rc_cd_find_file_sector(iterator, track_handle, exe_name, exe_size); ++ break; ++ } ++ } ++ ++ /* advance to end of line */ ++ while (*ptr && *ptr != '\n') ++ ++ptr; ++ } ++ ++ return sector; ++} ++ ++int rc_hash_psx(char hash[33], const rc_hash_iterator_t* iterator) ++{ ++ uint8_t buffer[32]; ++ char exe_name[64] = ""; ++ void* track_handle; ++ uint32_t sector; ++ uint32_t size; ++ int result = 0; ++ md5_state_t md5; ++ ++ track_handle = rc_cd_open_track(iterator, 1); ++ if (!track_handle) ++ return rc_hash_iterator_error(iterator, "Could not open track"); ++ ++ sector = rc_hash_find_playstation_executable(iterator, track_handle, "BOOT", "cdrom:", exe_name, sizeof(exe_name), &size); ++ if (!sector) { ++ sector = rc_cd_find_file_sector(iterator, track_handle, "PSX.EXE", &size); ++ if (sector) ++ memcpy(exe_name, "PSX.EXE", 8); ++ } ++ ++ if (!sector) { ++ rc_hash_iterator_error(iterator, "Could not locate primary executable"); ++ } ++ else if (rc_cd_read_sector(iterator, track_handle, sector, buffer, sizeof(buffer)) < sizeof(buffer)) { ++ rc_hash_iterator_error(iterator, "Could not read primary executable"); ++ } ++ else { ++ if (memcmp(buffer, "PS-X EXE", 7) != 0) { ++ rc_hash_iterator_verbose_formatted(iterator, "%s did not contain PS-X EXE marker", exe_name); ++ } ++ else { ++ /* the PS-X EXE header specifies the executable size as a 4-byte value 28 bytes into the header, which doesn't ++ * include the header itself. We want to include the header in the hash, so append another 2048 to that value. ++ */ ++ size = (((uint8_t)buffer[31] << 24) | ((uint8_t)buffer[30] << 16) | ((uint8_t)buffer[29] << 8) | (uint8_t)buffer[28]) + 2048; ++ } ++ ++ /* there's a few games that use a singular engine and only differ via their data files. luckily, they have unique ++ * serial numbers, and use the serial number as the boot file in the standard way. include the boot file name in the hash. ++ */ ++ md5_init(&md5); ++ md5_append(&md5, (md5_byte_t*)exe_name, (int)strlen(exe_name)); ++ ++ result = rc_hash_cd_file(&md5, iterator, track_handle, sector, exe_name, size, "primary executable"); ++ rc_hash_finalize(iterator, &md5, hash); ++ } ++ ++ rc_cd_close_track(iterator, track_handle); ++ ++ return result; ++} ++ ++int rc_hash_ps2(char hash[33], const rc_hash_iterator_t* iterator) ++{ ++ uint8_t buffer[4]; ++ char exe_name[64] = ""; ++ void* track_handle; ++ uint32_t sector; ++ uint32_t size; ++ int result = 0; ++ md5_state_t md5; ++ ++ track_handle = rc_cd_open_track(iterator, 1); ++ if (!track_handle) ++ return rc_hash_iterator_error(iterator, "Could not open track"); ++ ++ sector = rc_hash_find_playstation_executable(iterator, track_handle, "BOOT2", "cdrom0:", exe_name, sizeof(exe_name), &size); ++ if (!sector) { ++ rc_hash_iterator_error(iterator, "Could not locate primary executable"); ++ } ++ else if (rc_cd_read_sector(iterator, track_handle, sector, buffer, sizeof(buffer)) < sizeof(buffer)) { ++ rc_hash_iterator_error(iterator, "Could not read primary executable"); ++ } ++ else { ++ if (memcmp(buffer, "\x7f\x45\x4c\x46", 4) != 0) ++ rc_hash_iterator_verbose_formatted(iterator, "%s did not contain ELF marker", exe_name); ++ ++ /* there's a few games that use a singular engine and only differ via their data files. luckily, they have unique ++ * serial numbers, and use the serial number as the boot file in the standard way. include the boot file name in the hash. ++ */ ++ md5_init(&md5); ++ md5_append(&md5, (md5_byte_t*)exe_name, (int)strlen(exe_name)); ++ ++ result = rc_hash_cd_file(&md5, iterator, track_handle, sector, exe_name, size, "primary executable"); ++ rc_hash_finalize(iterator, &md5, hash); ++ } ++ ++ rc_cd_close_track(iterator, track_handle); ++ ++ return result; ++} ++ ++int rc_hash_psp(char hash[33], const rc_hash_iterator_t* iterator) ++{ ++ void* track_handle; ++ uint32_t sector; ++ uint32_t size; ++ md5_state_t md5; ++ ++ /* https://www.psdevwiki.com/psp/PBP ++ * A PBP file is an archive containing the PARAM.SFO, primary executable, and a bunch of metadata. ++ * While we could extract the PARAM.SFO and primary executable to mimic the normal PSP hashing logic, ++ * it's easier to just hash the entire file. This also helps alleviate issues where the primary ++ * executable is just a game engine and the only differentiating data would be the metadata. */ ++ if (rc_path_compare_extension(iterator->path, "pbp")) ++ return rc_hash_whole_file(hash, iterator); ++ ++ track_handle = rc_cd_open_track(iterator, 1); ++ if (!track_handle) ++ return rc_hash_iterator_error(iterator, "Could not open track"); ++ ++ /* http://www.romhacking.net/forum/index.php?topic=30899.0 ++ * PSP_GAME/PARAM.SFO contains key/value pairs identifying the game for the system (i.e. serial number, ++ * name, version). PSP_GAME/SYSDIR/EBOOT.BIN is the encrypted primary executable. ++ */ ++ sector = rc_cd_find_file_sector(iterator, track_handle, "PSP_GAME\\PARAM.SFO", &size); ++ if (!sector) { ++ rc_cd_close_track(iterator, track_handle); ++ return rc_hash_iterator_error(iterator, "Not a PSP game disc"); ++ } ++ ++ md5_init(&md5); ++ if (!rc_hash_cd_file(&md5, iterator, track_handle, sector, NULL, size, "PSP_GAME\\PARAM.SFO")) { ++ rc_cd_close_track(iterator, track_handle); ++ return 0; ++ } ++ ++ sector = rc_cd_find_file_sector(iterator, track_handle, "PSP_GAME\\SYSDIR\\EBOOT.BIN", &size); ++ if (!sector) { ++ rc_cd_close_track(iterator, track_handle); ++ return rc_hash_iterator_error(iterator, "Could not find primary executable"); ++ } ++ ++ if (!rc_hash_cd_file(&md5, iterator, track_handle, sector, NULL, size, "PSP_GAME\\SYSDIR\\EBOOT.BIN")) { ++ rc_cd_close_track(iterator, track_handle); ++ return 0; ++ } ++ ++ rc_cd_close_track(iterator, track_handle); ++ return rc_hash_finalize(iterator, &md5, hash); ++} ++ ++int rc_hash_sega_cd(char hash[33], const rc_hash_iterator_t* iterator) ++{ ++ uint8_t buffer[512]; ++ void* track_handle; ++ ++ track_handle = rc_cd_open_track(iterator, 1); ++ if (!track_handle) ++ return rc_hash_iterator_error(iterator, "Could not open track"); ++ ++ /* the first 512 bytes of sector 0 are a volume header and ROM header that uniquely identify the game. ++ * After that is an arbitrary amount of code that ensures the game is being run in the correct region. ++ * Then more arbitrary code follows that actually starts the boot process. Somewhere in there, the ++ * primary executable is loaded. In many cases, a single game will have multiple executables, so even ++ * if we could determine the primary one, it's just the tip of the iceberg. As such, we've decided that ++ * hashing the volume and ROM headers is sufficient for identifying the game, and we'll have to trust ++ * that our players aren't modifying anything else on the disc. ++ */ ++ rc_cd_read_sector(iterator, track_handle, 0, buffer, sizeof(buffer)); ++ rc_cd_close_track(iterator, track_handle); ++ ++ if (memcmp(buffer, "SEGADISCSYSTEM ", 16) != 0 && /* Sega CD */ ++ memcmp(buffer, "SEGA SEGASATURN ", 16) != 0) { /* Sega Saturn */ ++ return rc_hash_iterator_error(iterator, "Not a Sega CD"); ++ } ++ ++ return rc_hash_buffer(hash, buffer, sizeof(buffer), iterator); ++} ++ ++static int rc_hash_wii_disc(md5_state_t* md5, const rc_hash_iterator_t* iterator, void* file_handle) ++{ ++ const uint32_t MAIN_HEADER_SIZE = 0x80; ++ const uint64_t REGION_CODE_ADDRESS = 0x4E000; ++ const uint32_t CLUSTER_SIZE = 0x7C00; ++ const uint32_t MAX_CLUSTER_COUNT = 1024; ++ ++ uint32_t partition_info_table[8]; ++ uint32_t total_partition_count = 0; ++ uint32_t* partition_table; ++ uint64_t tmd_offset; ++ uint32_t tmd_size; ++ uint64_t part_offset; ++ uint64_t part_size; ++ uint32_t cluster_count; ++ ++ uint8_t quad_buffer[4]; ++ uint8_t* buffer; ++ ++ uint32_t ix, jx, kx; ++ uint8_t encrypted; ++ ++ /* Check encryption byte - if 0x61 is 0, disc is encrypted */ ++ rc_file_seek(iterator, file_handle, 0x61, SEEK_SET); ++ rc_file_read(iterator, file_handle, quad_buffer, 1); ++ encrypted = (quad_buffer[0] == 0); ++ ++ /* Hash main headers */ ++ buffer = (uint8_t*)malloc(CLUSTER_SIZE); ++ if (!buffer) { ++ rc_file_close(iterator, file_handle); ++ return rc_hash_iterator_error(iterator, "Could not allocate temporary buffer"); ++ } ++ ++ rc_hash_iterator_verbose_formatted(iterator, "Hashing %u byte main header for [%c%c%c%c%c%c]", ++ MAIN_HEADER_SIZE, buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]); ++ rc_file_seek(iterator, file_handle, 0, SEEK_SET); ++ rc_file_read(iterator, file_handle, buffer, MAIN_HEADER_SIZE); ++ md5_append(md5, buffer, MAIN_HEADER_SIZE); ++ ++ /* Hash region code */ ++ rc_file_seek(iterator, file_handle, REGION_CODE_ADDRESS, SEEK_SET); ++ rc_file_read(iterator, file_handle, quad_buffer, 4); ++ md5_append(md5, quad_buffer, 4); ++ ++ /* Scan partition table */ ++ rc_file_seek(iterator, file_handle, 0x40000, SEEK_SET); ++ for (ix = 0; ix < 8; ix++) { ++ rc_file_read(iterator, file_handle, quad_buffer, 4); ++ partition_info_table[ix] = ++ (quad_buffer[0] << 24) | (quad_buffer[1] << 16) | (quad_buffer[2] << 8) | quad_buffer[3]; ++ if (ix % 2 == 0) ++ total_partition_count += partition_info_table[ix]; ++ } ++ ++ if (total_partition_count == 0) { ++ free(buffer); ++ rc_file_close(iterator, file_handle); ++ return rc_hash_iterator_error(iterator, "No partitions found"); ++ } ++ ++ partition_table = (uint32_t*)malloc(total_partition_count * 4 * 2); ++ kx = 0; ++ for (jx = 0; jx < 8; jx += 2) { ++ rc_file_seek(iterator, file_handle, ((uint64_t)partition_info_table[jx + 1]) << 2, SEEK_SET); ++ for (ix = 0; ix < partition_info_table[jx]; ix++) { ++ rc_file_read(iterator, file_handle, quad_buffer, 4); ++ partition_table[kx++] = ++ (quad_buffer[0] << 24) | (quad_buffer[1] << 16) | (quad_buffer[2] << 8) | quad_buffer[3]; ++ rc_file_read(iterator, file_handle, quad_buffer, 4); ++ partition_table[kx++] = ++ (quad_buffer[0] << 24) | (quad_buffer[1] << 16) | (quad_buffer[2] << 8) | quad_buffer[3]; ++ } ++ } ++ ++ /* Read each partition */ ++ for (jx = 0; jx < total_partition_count * 2; jx += 2) { ++ /* Don't hash Update partition*/ ++ if (partition_table[jx + 1] == 1) ++ continue; ++ ++ /* Hash title metadata */ ++ rc_file_seek(iterator, file_handle, ((uint64_t)partition_table[jx] << 2) + 0x2A4, SEEK_SET); ++ rc_file_read(iterator, file_handle, quad_buffer, 4); ++ tmd_size = ++ (quad_buffer[0] << 24) | (quad_buffer[1] << 16) | (quad_buffer[2] << 8) | quad_buffer[3]; ++ rc_file_read(iterator, file_handle, quad_buffer, 4); ++ tmd_offset = ++ ((uint64_t)((quad_buffer[0] << 24) | (quad_buffer[1] << 16) | (quad_buffer[2] << 8) | quad_buffer[3])) << 2; ++ ++ if (tmd_size > CLUSTER_SIZE) ++ tmd_size = CLUSTER_SIZE; ++ ++ rc_file_seek(iterator, file_handle, ((uint64_t)partition_table[jx] << 2) + tmd_offset, SEEK_SET); ++ rc_file_read(iterator, file_handle, buffer, tmd_size); ++ rc_hash_iterator_verbose_formatted(iterator, "Hashing %u byte title metadata (partition type %u)", ++ tmd_size, partition_table[jx + 1]); ++ md5_append(md5, buffer, tmd_size); ++ ++ /* Hash partition */ ++ rc_file_seek(iterator, file_handle, ((uint64_t)partition_table[jx] << 2) + 0x2B8, SEEK_SET); ++ rc_file_read(iterator, file_handle, quad_buffer, 4); ++ part_offset = ++ ((uint64_t)((quad_buffer[0] << 24) | (quad_buffer[1] << 16) | (quad_buffer[2] << 8) | quad_buffer[3])) << 2; ++ rc_file_read(iterator, file_handle, quad_buffer, 4); ++ part_size = ++ ((uint64_t)((quad_buffer[0] << 24) | (quad_buffer[1] << 16) | (quad_buffer[2] << 8) | quad_buffer[3])) << 2; ++ ++ if (encrypted) { ++ cluster_count = (part_size / 0x8000 > MAX_CLUSTER_COUNT) ? MAX_CLUSTER_COUNT : (uint32_t)(part_size / 0x8000); ++ rc_hash_iterator_verbose_formatted(iterator, "Hashing %u encrypted clusters (%u bytes)", ++ cluster_count, cluster_count * CLUSTER_SIZE); ++ for (ix = 0; ix < cluster_count; ix++) { ++ rc_file_seek(iterator, file_handle, part_offset + (ix * 0x8000) + 0x400, SEEK_SET); ++ rc_file_read(iterator, file_handle, buffer, CLUSTER_SIZE); ++ md5_append(md5, buffer, CLUSTER_SIZE); ++ } ++ } ++ else { /* Decrypted */ ++ if (rc_hash_nintendo_disc_partition(md5, iterator, file_handle, (uint32_t)part_offset, 2) == 0) { ++ free(partition_table); ++ free(buffer); ++ return rc_hash_iterator_error(iterator, "Failed to hash Wii partition"); ++ } ++ } ++ } ++ free(partition_table); ++ free(buffer); ++ return 1; ++} ++ ++static int rc_hash_wiiware(md5_state_t* md5, const rc_hash_iterator_t* iterator, void* file_handle) ++{ ++ uint32_t cert_chain_size, ticket_size, tmd_size; ++ uint32_t tmd_start_addr, content_count, content_addr, content_size, buffer_size; ++ uint32_t ix; ++ ++ uint8_t quad_buffer[4]; ++ uint8_t* buffer; ++ ++ rc_file_seek(iterator, file_handle, 0x08, SEEK_SET); ++ rc_file_read(iterator, file_handle, quad_buffer, 4); ++ cert_chain_size = ++ (quad_buffer[0] << 24) | (quad_buffer[1] << 16) | (quad_buffer[2] << 8) | quad_buffer[3]; ++ /* Each content is individually aligned to a 0x40-byte boundary. */ ++ cert_chain_size = (cert_chain_size + 0x3F) & ~0x3F; ++ rc_file_seek(iterator, file_handle, 0x10, SEEK_SET); ++ rc_file_read(iterator, file_handle, quad_buffer, 4); ++ ticket_size = ++ (quad_buffer[0] << 24) | (quad_buffer[1] << 16) | (quad_buffer[2] << 8) | quad_buffer[3]; ++ ticket_size = (ticket_size + 0x3F) & ~0x3F; ++ rc_file_read(iterator, file_handle, quad_buffer, 4); ++ tmd_size = ++ (quad_buffer[0] << 24) | (quad_buffer[1] << 16) | (quad_buffer[2] << 8) | quad_buffer[3]; ++ tmd_size = (tmd_size + 0x3F) & ~0x3F; ++ if (tmd_size > MAX_BUFFER_SIZE) ++ tmd_size = MAX_BUFFER_SIZE; ++ ++ tmd_start_addr = 0x40 + cert_chain_size + ticket_size; ++ ++ /* Hash TMD */ ++ buffer = (uint8_t*)malloc(tmd_size); ++ rc_file_seek(iterator, file_handle, tmd_start_addr, SEEK_SET); ++ rc_file_read(iterator, file_handle, buffer, tmd_size); ++ rc_hash_iterator_verbose_formatted(iterator, "Hashing %u byte TMD", tmd_size); ++ md5_append(md5, buffer, tmd_size); ++ free(buffer); ++ ++ /* Get count of content sections */ ++ rc_file_seek(iterator, file_handle, (uint64_t)tmd_start_addr + 0x1de, SEEK_SET); ++ rc_file_read(iterator, file_handle, quad_buffer, 2); ++ content_count = (quad_buffer[0] << 8) | quad_buffer[1]; ++ rc_hash_iterator_verbose_formatted(iterator, "Hashing %u content sections", content_count); ++ content_addr = tmd_start_addr + tmd_size; ++ for (ix = 0; ix < content_count; ix++) { ++ /* Get content section size */ ++ rc_file_seek(iterator, file_handle, (uint64_t)tmd_start_addr + 0x1e4 + 8 + ix * 0x24, SEEK_SET); ++ rc_file_read(iterator, file_handle, quad_buffer, 4); ++ if (quad_buffer[0] == 0x00 && quad_buffer[1] == 0x00 && quad_buffer[2] == 0x00 && quad_buffer[3] == 0x00) { ++ rc_file_read(iterator, file_handle, quad_buffer, 4); ++ content_size = ++ (quad_buffer[0] << 24) | (quad_buffer[1] << 16) | (quad_buffer[2] << 8) | quad_buffer[3]; ++ /* Padding between content should be ignored. But because the content data is encrypted, ++ the size to hash for each content should be rounded up to the size of an AES block (16 bytes). */ ++ content_size = (content_size + 0x0F) & ~0x0F; ++ } ++ else { ++ /* size > 4GB, just assume MAX_BUFFER_SIZE */ ++ content_size = MAX_BUFFER_SIZE; ++ } ++ buffer_size = (content_size > MAX_BUFFER_SIZE) ? MAX_BUFFER_SIZE : content_size; ++ ++ /* Hash content */ ++ buffer = (uint8_t*)malloc(buffer_size); ++ rc_file_seek(iterator, file_handle, content_addr, SEEK_SET); ++ rc_file_read(iterator, file_handle, buffer, buffer_size); ++ md5_append(md5, buffer, buffer_size); ++ content_addr += content_size; ++ content_addr = (content_addr + 0x3F) & ~0x3F; ++ free(buffer); ++ } ++ ++ return 1; ++} ++ ++int rc_hash_wii(char hash[33], const rc_hash_iterator_t* iterator) ++{ ++ md5_state_t md5; ++ void* file_handle; ++ ++ uint8_t quad_buffer[4]; ++ uint8_t success; ++ ++ file_handle = rc_file_open(iterator, iterator->path); ++ if (!file_handle) ++ return rc_hash_iterator_error(iterator, "Could not open file"); ++ ++ md5_init(&md5); ++ /* Check Magic Words */ ++ rc_file_seek(iterator, file_handle, 0x18, SEEK_SET); ++ rc_file_read(iterator, file_handle, quad_buffer, 4); ++ if (quad_buffer[0] == 0x5D && quad_buffer[1] == 0x1C && quad_buffer[2] == 0x9E && quad_buffer[3] == 0xA3) { ++ success = rc_hash_wii_disc(&md5, iterator, file_handle); ++ } ++ else { ++ rc_file_seek(iterator, file_handle, 0x04, SEEK_SET); ++ rc_file_read(iterator, file_handle, quad_buffer, 4); ++ if (quad_buffer[0] == 'I' && quad_buffer[1] == 's' && quad_buffer[2] == 0x00 && quad_buffer[3] == 0x00) ++ success = rc_hash_wiiware(&md5, iterator, file_handle); ++ else ++ success = rc_hash_iterator_error(iterator, "Not a supported Wii file"); ++ } ++ ++ /* Finalize */ ++ rc_file_close(iterator, file_handle); ++ ++ if (success) ++ return rc_hash_finalize(iterator, &md5, hash); ++ ++ return 0; ++} +diff -rupbN melonDS.orig/src/rcheevos/src/rhash/hash_encrypted.c melonDS.ra/src/rcheevos/src/rhash/hash_encrypted.c +--- melonDS.orig/src/rcheevos/src/rhash/hash_encrypted.c 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rhash/hash_encrypted.c 2026-03-06 21:37:07.050799942 +0000 +@@ -0,0 +1,566 @@ ++#include "rc_hash_internal.h" ++ ++#include "../rc_compat.h" ++ ++#include "aes.h" ++ ++/* ===================================================== */ ++ ++static rc_hash_3ds_get_cia_normal_key_func _3ds_get_cia_normal_key_func = NULL; ++static rc_hash_3ds_get_ncch_normal_keys_func _3ds_get_ncch_normal_keys_func = NULL; ++ ++void rc_hash_reset_iterator_encrypted(rc_hash_iterator_t* iterator) ++{ ++ iterator->callbacks.encryption.get_3ds_cia_normal_key = _3ds_get_cia_normal_key_func; ++ iterator->callbacks.encryption.get_3ds_ncch_normal_keys = _3ds_get_ncch_normal_keys_func; ++} ++ ++void rc_hash_init_3ds_get_cia_normal_key_func(rc_hash_3ds_get_cia_normal_key_func func) ++{ ++ _3ds_get_cia_normal_key_func = func; ++} ++ ++void rc_hash_init_3ds_get_ncch_normal_keys_func(rc_hash_3ds_get_ncch_normal_keys_func func) ++{ ++ _3ds_get_ncch_normal_keys_func = func; ++} ++ ++/* ===================================================== */ ++ ++static int rc_hash_nintendo_3ds_ncch(md5_state_t* md5, void* file_handle, uint8_t header[0x200], ++ struct AES_ctx* cia_aes, const rc_hash_iterator_t* iterator) ++{ ++ struct AES_ctx ncch_aes; ++ uint8_t* hash_buffer; ++ uint64_t exefs_offset, exefs_real_size; ++ uint32_t exefs_buffer_size; ++ uint8_t primary_key[AES_KEYLEN], secondary_key[AES_KEYLEN]; ++ uint8_t fixed_key_flag, no_crypto_flag, seed_crypto_flag; ++ uint8_t crypto_method, secondary_key_x_slot; ++ uint16_t ncch_version; ++ uint32_t i; ++ uint8_t primary_key_y[AES_KEYLEN], program_id[sizeof(uint64_t)]; ++ uint8_t iv[AES_BLOCKLEN], cia_iv[AES_BLOCKLEN]; ++ uint8_t exefs_section_name[8]; ++ uint64_t exefs_section_offset, exefs_section_size; ++ ++ exefs_offset = ((uint32_t)header[0x1A3] << 24) | (header[0x1A2] << 16) | (header[0x1A1] << 8) | header[0x1A0]; ++ exefs_real_size = ((uint32_t)header[0x1A7] << 24) | (header[0x1A6] << 16) | (header[0x1A5] << 8) | header[0x1A4]; ++ ++ /* Offset and size are in "media units" (1 media unit = 0x200 bytes) */ ++ exefs_offset *= 0x200; ++ exefs_real_size *= 0x200; ++ ++ if (exefs_real_size > MAX_BUFFER_SIZE) ++ exefs_buffer_size = MAX_BUFFER_SIZE; ++ else ++ exefs_buffer_size = (uint32_t)exefs_real_size; ++ ++ /* This region is technically optional, but it should always be present for executable content (i.e. games) */ ++ if (exefs_offset == 0 || exefs_real_size == 0) ++ return rc_hash_iterator_error(iterator, "ExeFS was not available"); ++ ++ /* NCCH flag 7 is a bitfield of various crypto related flags */ ++ fixed_key_flag = header[0x188 + 7] & 0x01; ++ no_crypto_flag = header[0x188 + 7] & 0x04; ++ seed_crypto_flag = header[0x188 + 7] & 0x20; ++ ++ ncch_version = (header[0x113] << 8) | header[0x112]; ++ ++ if (no_crypto_flag == 0) { ++ rc_hash_iterator_verbose(iterator, "Encrypted NCCH detected"); ++ ++ if (fixed_key_flag != 0) { ++ /* Fixed crypto key means all 0s for both keys */ ++ memset(primary_key, 0, sizeof(primary_key)); ++ memset(secondary_key, 0, sizeof(secondary_key)); ++ rc_hash_iterator_verbose(iterator, "Using fixed key crypto"); ++ } ++ else { ++ if (iterator->callbacks.encryption.get_3ds_ncch_normal_keys == NULL) ++ return rc_hash_iterator_error(iterator, "An encrypted NCCH was detected, but the NCCH normal keys callback was not set"); ++ ++ /* Primary key y is just the first 16 bytes of the header */ ++ memcpy(primary_key_y, header, sizeof(primary_key_y)); ++ ++ /* NCCH flag 3 indicates which secondary key x slot is used */ ++ crypto_method = header[0x188 + 3]; ++ ++ switch (crypto_method) { ++ case 0x00: ++ rc_hash_iterator_verbose(iterator, "Using NCCH crypto method v1"); ++ secondary_key_x_slot = 0x2C; ++ break; ++ case 0x01: ++ rc_hash_iterator_verbose(iterator, "Using NCCH crypto method v2"); ++ secondary_key_x_slot = 0x25; ++ break; ++ case 0x0A: ++ rc_hash_iterator_verbose(iterator, "Using NCCH crypto method v3"); ++ secondary_key_x_slot = 0x18; ++ break; ++ case 0x0B: ++ rc_hash_iterator_verbose(iterator, "Using NCCH crypto method v4"); ++ secondary_key_x_slot = 0x1B; ++ break; ++ default: ++ return rc_hash_iterator_error_formatted(iterator, "Invalid crypto method %02X", (unsigned)crypto_method); ++ } ++ ++ /* We only need the program id if we're doing seed crypto */ ++ if (seed_crypto_flag != 0) { ++ rc_hash_iterator_verbose(iterator, "Using seed crypto"); ++ memcpy(program_id, &header[0x118], sizeof(program_id)); ++ } ++ ++ if (iterator->callbacks.encryption.get_3ds_ncch_normal_keys(primary_key_y, secondary_key_x_slot, seed_crypto_flag != 0 ? program_id : NULL, primary_key, secondary_key) == 0) ++ return rc_hash_iterator_error(iterator, "Could not obtain NCCH normal keys"); ++ } ++ ++ switch (ncch_version) { ++ case 0: ++ case 2: ++ rc_hash_iterator_verbose(iterator, "Detected NCCH version 0/2"); ++ for (i = 0; i < 8; i++) { ++ /* First 8 bytes is the partition id in reverse byte order */ ++ iv[7 - i] = header[0x108 + i]; ++ } ++ ++ /* Magic number for ExeFS */ ++ iv[8] = 2; ++ ++ /* Rest of the bytes are 0 */ ++ memset(&iv[9], 0, sizeof(iv) - 9); ++ break; ++ ++ case 1: ++ rc_hash_iterator_verbose(iterator, "Detected NCCH version 1"); ++ for (i = 0; i < 8; i++) { ++ /* First 8 bytes is the partition id in normal byte order */ ++ iv[i] = header[0x108 + i]; ++ } ++ ++ /* Next 4 bytes are 0 */ ++ memset(&iv[8], 0, 4); ++ ++ /* Last 4 bytes is the ExeFS byte offset in big endian */ ++ iv[12] = (exefs_offset >> 24) & 0xFF; ++ iv[13] = (exefs_offset >> 16) & 0xFF; ++ iv[14] = (exefs_offset >> 8) & 0xFF; ++ iv[15] = exefs_offset & 0xFF; ++ break; ++ ++ default: ++ return rc_hash_iterator_error_formatted(iterator, "Invalid NCCH version %04X", (unsigned)ncch_version); ++ } ++ } ++ ++ /* ASSERT: file position must be +0x200 from start of NCCH (i.e. end of header) */ ++ exefs_offset -= 0x200; ++ ++ if (cia_aes) { ++ /* CBC decryption works by setting the IV to the encrypted previous block. ++ * Normally this means we would need to decrypt the data between the header and the ExeFS so the CIA AES state is correct. ++ * However, we can abuse how CBC decryption works and just set the IV to last block we would otherwise decrypt. ++ * We don't care about the data betweeen the header and ExeFS, so this works fine. */ ++ ++ rc_file_seek(iterator, file_handle, (int64_t)exefs_offset - AES_BLOCKLEN, SEEK_CUR); ++ if (rc_file_read(iterator, file_handle, cia_iv, AES_BLOCKLEN) != AES_BLOCKLEN) ++ return rc_hash_iterator_error(iterator, "Could not read NCCH data"); ++ ++ AES_ctx_set_iv(cia_aes, cia_iv); ++ } ++ else { ++ /* No encryption present, just skip over the in-between data */ ++ rc_file_seek(iterator, file_handle, (int64_t)exefs_offset, SEEK_CUR); ++ } ++ ++ hash_buffer = (uint8_t*)malloc(exefs_buffer_size); ++ if (!hash_buffer) ++ return rc_hash_iterator_error_formatted(iterator, "Failed to allocate %u bytes", (unsigned)exefs_buffer_size); ++ ++ /* Clear out crypto flags to ensure we get the same hash for decrypted and encrypted ROMs */ ++ memset(&header[0x114], 0, 4); ++ header[0x188 + 3] = 0; ++ header[0x188 + 7] &= ~(0x20 | 0x04 | 0x01); ++ ++ rc_hash_iterator_verbose(iterator, "Hashing 512 byte NCCH header"); ++ md5_append(md5, header, 0x200); ++ ++ rc_hash_iterator_verbose_formatted(iterator, "Hashing %u bytes for ExeFS (at NCCH offset %08X%08X)", ++ (unsigned)exefs_buffer_size, (unsigned)(exefs_offset >> 32), (unsigned)exefs_offset); ++ ++ if (rc_file_read(iterator, file_handle, hash_buffer, exefs_buffer_size) != exefs_buffer_size) { ++ free(hash_buffer); ++ return rc_hash_iterator_error(iterator, "Could not read ExeFS data"); ++ } ++ ++ if (cia_aes) { ++ rc_hash_iterator_verbose(iterator, "Performing CIA decryption for ExeFS"); ++ AES_CBC_decrypt_buffer(cia_aes, hash_buffer, exefs_buffer_size); ++ } ++ ++ if (no_crypto_flag == 0) { ++ rc_hash_iterator_verbose(iterator, "Performing NCCH decryption for ExeFS"); ++ ++ AES_init_ctx_iv(&ncch_aes, primary_key, iv); ++ AES_CTR_xcrypt_buffer(&ncch_aes, hash_buffer, 0x200); ++ ++ for (i = 0; i < 8; i++) { ++ memcpy(exefs_section_name, &hash_buffer[i * 16], sizeof(exefs_section_name)); ++ exefs_section_offset = ((uint32_t)hash_buffer[i * 16 + 11] << 24) | (hash_buffer[i * 16 + 10] << 16) | (hash_buffer[i * 16 + 9] << 8) | hash_buffer[i * 16 + 8]; ++ exefs_section_size = ((uint32_t)hash_buffer[i * 16 + 15] << 24) | (hash_buffer[i * 16 + 14] << 16) | (hash_buffer[i * 16 + 13] << 8) | hash_buffer[i * 16 + 12]; ++ ++ /* 0 size indicates an unused section */ ++ if (exefs_section_size == 0) ++ continue; ++ ++ /* Offsets must be aligned by a media unit */ ++ if (exefs_section_offset & 0x1FF) ++ return rc_hash_iterator_error(iterator, "ExeFS section offset is misaligned"); ++ ++ /* Offset is relative to the end of the header */ ++ exefs_section_offset += 0x200; ++ ++ /* Check against malformed sections */ ++ if (exefs_section_offset + ((exefs_section_size + 0x1FF) & ~(uint64_t)0x1FF) > (uint64_t)exefs_real_size) ++ return rc_hash_iterator_error(iterator, "ExeFS section would overflow"); ++ ++ if (memcmp(exefs_section_name, "icon", 4) == 0 || ++ memcmp(exefs_section_name, "banner", 6) == 0) { ++ /* Align size up by a media unit */ ++ exefs_section_size = (exefs_section_size + 0x1FF) & ~(uint64_t)0x1FF; ++ AES_init_ctx(&ncch_aes, primary_key); ++ } ++ else { ++ /* We don't align size up here, as the padding bytes will use the primary key rather than the secondary key */ ++ AES_init_ctx(&ncch_aes, secondary_key); ++ } ++ ++ /* In theory, the section offset + size could be greater than the buffer size */ ++ /* In practice, this likely never occurs, but just in case it does, ignore the section or constrict the size */ ++ if (exefs_section_offset + exefs_section_size > exefs_buffer_size) { ++ if (exefs_section_offset >= exefs_buffer_size) ++ continue; ++ ++ exefs_section_size = exefs_buffer_size - exefs_section_offset; ++ } ++ ++ exefs_section_name[7] = '\0'; ++ rc_hash_iterator_verbose_formatted(iterator, "Decrypting ExeFS file %s at ExeFS offset %08X with size %08X", ++ (const char*)exefs_section_name, (unsigned)exefs_section_offset, (unsigned)exefs_section_size); ++ ++ AES_CTR_xcrypt_buffer(&ncch_aes, &hash_buffer[exefs_section_offset], exefs_section_size & ~(uint64_t)0xF); ++ ++ if (exefs_section_size & 0x1FF) { ++ /* Handle padding bytes, these always use the primary key */ ++ exefs_section_offset += exefs_section_size; ++ exefs_section_size = 0x200 - (exefs_section_size & 0x1FF); ++ ++ rc_hash_iterator_verbose_formatted(iterator, "Decrypting ExeFS padding at ExeFS offset %08X with size %08X", ++ (unsigned)exefs_section_offset, (unsigned)exefs_section_size); ++ ++ /* Align our decryption start to an AES block boundary */ ++ if (exefs_section_size & 0xF) { ++ /* We're a little evil here re-using the IV like this, but this seems to be the best way to deal with this... */ ++ memcpy(iv, ncch_aes.Iv, sizeof(iv)); ++ exefs_section_offset &= ~(uint64_t)0xF; ++ ++ /* First decrypt these last bytes using the secondary key */ ++ AES_CTR_xcrypt_buffer(&ncch_aes, &hash_buffer[exefs_section_offset], 0x10 - (exefs_section_size & 0xF)); ++ ++ /* Now re-encrypt these bytes using the primary key */ ++ AES_init_ctx_iv(&ncch_aes, primary_key, iv); ++ AES_CTR_xcrypt_buffer(&ncch_aes, &hash_buffer[exefs_section_offset], 0x10 - (exefs_section_size & 0xF)); ++ ++ /* All of the padding can now be decrypted using the primary key */ ++ AES_ctx_set_iv(&ncch_aes, iv); ++ exefs_section_size += 0x10 - (exefs_section_size & 0xF); ++ } ++ ++ AES_init_ctx(&ncch_aes, primary_key); ++ AES_CTR_xcrypt_buffer(&ncch_aes, &hash_buffer[exefs_section_offset], (size_t)exefs_section_size); ++ } ++ } ++ } ++ ++ md5_append(md5, hash_buffer, exefs_buffer_size); ++ ++ free(hash_buffer); ++ return 1; ++} ++ ++static uint32_t rc_hash_nintendo_3ds_cia_signature_size(uint8_t header[0x200], const rc_hash_iterator_t* iterator) ++{ ++ uint32_t signature_type; ++ ++ signature_type = ((uint32_t)header[0] << 24) | (header[1] << 16) | (header[2] << 8) | header[3]; ++ switch (signature_type) { ++ case 0x010000: ++ case 0x010003: ++ return 0x200 + 0x3C; ++ ++ case 0x010001: ++ case 0x010004: ++ return 0x100 + 0x3C; ++ ++ case 0x010002: ++ case 0x010005: ++ return 0x3C + 0x40; ++ ++ default: ++ return rc_hash_iterator_error_formatted(iterator, "Invalid signature type %08X", (unsigned)signature_type); ++ } ++} ++ ++static int rc_hash_nintendo_3ds_cia(md5_state_t* md5, void* file_handle, uint8_t header[0x200], ++ const rc_hash_iterator_t* iterator) ++{ ++ const uint32_t CIA_HEADER_SIZE = 0x2020; /* Yes, this is larger than the header[0x200], but we only use the beginning of the header */ ++ const uint64_t CIA_ALIGNMENT_MASK = 64 - 1; /* sizes are aligned by 64 bytes */ ++ struct AES_ctx aes; ++ uint8_t iv[AES_BLOCKLEN], normal_key[AES_KEYLEN], title_key[AES_KEYLEN], title_id[sizeof(uint64_t)]; ++ uint32_t cert_size, tik_size, tmd_size; ++ int64_t cert_offset, tik_offset, tmd_offset, content_offset; ++ uint32_t signature_size, i; ++ uint16_t content_count; ++ uint8_t common_key_index; ++ ++ cert_size = ((uint32_t)header[0x0B] << 24) | (header[0x0A] << 16) | (header[0x09] << 8) | header[0x08]; ++ tik_size = ((uint32_t)header[0x0F] << 24) | (header[0x0E] << 16) | (header[0x0D] << 8) | header[0x0C]; ++ tmd_size = ((uint32_t)header[0x13] << 24) | (header[0x12] << 16) | (header[0x11] << 8) | header[0x10]; ++ ++ cert_offset = (CIA_HEADER_SIZE + CIA_ALIGNMENT_MASK) & ~CIA_ALIGNMENT_MASK; ++ tik_offset = (cert_offset + cert_size + CIA_ALIGNMENT_MASK) & ~CIA_ALIGNMENT_MASK; ++ tmd_offset = (tik_offset + tik_size + CIA_ALIGNMENT_MASK) & ~CIA_ALIGNMENT_MASK; ++ content_offset = (tmd_offset + tmd_size + CIA_ALIGNMENT_MASK) & ~CIA_ALIGNMENT_MASK; ++ ++ /* Check if this CIA is encrypted, if it isn't, we can hash it right away */ ++ ++ rc_file_seek(iterator, file_handle, tmd_offset, SEEK_SET); ++ if (rc_file_read(iterator, file_handle, header, 4) != 4) ++ return rc_hash_iterator_error(iterator, "Could not read TMD signature type"); ++ ++ signature_size = rc_hash_nintendo_3ds_cia_signature_size(header, iterator); ++ if (signature_size == 0) ++ return 0; /* rc_hash_nintendo_3ds_cia_signature_size will call rc_hash_error, so we don't need to do so here */ ++ ++ rc_file_seek(iterator, file_handle, signature_size + 0x9E, SEEK_CUR); ++ if (rc_file_read(iterator, file_handle, header, 2) != 2) ++ return rc_hash_iterator_error(iterator, "Could not read TMD content count"); ++ ++ content_count = (header[0] << 8) | header[1]; ++ ++ rc_file_seek(iterator, file_handle, 0x9C4 - 0x9E - 2, SEEK_CUR); ++ for (i = 0; i < content_count; i++) { ++ if (rc_file_read(iterator, file_handle, header, 0x30) != 0x30) ++ return rc_hash_iterator_error(iterator, "Could not read TMD content chunk"); ++ ++ /* Content index 0 is the main content (i.e. the 3DS executable) */ ++ if (((header[4] << 8) | header[5]) == 0) ++ break; ++ ++ content_offset += ((uint32_t)header[0xC] << 24) | (header[0xD] << 16) | (header[0xE] << 8) | header[0xF]; ++ } ++ ++ if (i == content_count) ++ return rc_hash_iterator_error(iterator, "Could not find main content chunk in TMD"); ++ ++ if ((header[7] & 1) == 0) { ++ /* Not encrypted, we can hash the NCCH immediately */ ++ rc_file_seek(iterator, file_handle, content_offset, SEEK_SET); ++ if (rc_file_read(iterator, file_handle, header, 0x200) != 0x200) ++ return rc_hash_iterator_error(iterator, "Could not read NCCH header"); ++ ++ if (memcmp(&header[0x100], "NCCH", 4) != 0) ++ return rc_hash_iterator_error_formatted(iterator, "NCCH header was not at %08X%08X", (unsigned)(content_offset >> 32), (unsigned)content_offset); ++ ++ return rc_hash_nintendo_3ds_ncch(md5, file_handle, header, NULL, iterator); ++ } ++ ++ if (iterator->callbacks.encryption.get_3ds_cia_normal_key == NULL) ++ return rc_hash_iterator_error(iterator, "An encrypted CIA was detected, but the CIA normal key callback was not set"); ++ ++ /* Acquire the encrypted title key, title id, and common key index from the ticket */ ++ /* These will be needed to decrypt the title key, and that will be needed to decrypt the CIA */ ++ ++ rc_file_seek(iterator, file_handle, tik_offset, SEEK_SET); ++ if (rc_file_read(iterator, file_handle, header, 4) != 4) ++ return rc_hash_iterator_error(iterator, "Could not read ticket signature type"); ++ ++ signature_size = rc_hash_nintendo_3ds_cia_signature_size(header, iterator); ++ if (signature_size == 0) ++ return 0; ++ ++ rc_file_seek(iterator, file_handle, signature_size, SEEK_CUR); ++ if (rc_file_read(iterator, file_handle, header, 0xB2) != 0xB2) ++ return rc_hash_iterator_error(iterator, "Could not read ticket data"); ++ ++ memcpy(title_key, &header[0x7F], sizeof(title_key)); ++ memcpy(title_id, &header[0x9C], sizeof(title_id)); ++ common_key_index = header[0xB1]; ++ ++ if (common_key_index > 5) ++ return rc_hash_iterator_error_formatted(iterator, "Invalid common key index %02X", (unsigned)common_key_index); ++ ++ if (iterator->callbacks.encryption.get_3ds_cia_normal_key(common_key_index, normal_key) == 0) ++ return rc_hash_iterator_error_formatted(iterator, "Could not obtain common key %02X", (unsigned)common_key_index); ++ ++ memset(iv, 0, sizeof(iv)); ++ memcpy(iv, title_id, sizeof(title_id)); ++ AES_init_ctx_iv(&aes, normal_key, iv); ++ ++ /* Finally, decrypt the title key */ ++ AES_CBC_decrypt_buffer(&aes, title_key, sizeof(title_key)); ++ ++ /* Now we can hash the NCCH */ ++ ++ rc_file_seek(iterator, file_handle, content_offset, SEEK_SET); ++ if (rc_file_read(iterator, file_handle, header, 0x200) != 0x200) ++ return rc_hash_iterator_error(iterator, "Could not read NCCH header"); ++ ++ memset(iv, 0, sizeof(iv)); /* Content index is iv (which is always 0 for main content) */ ++ AES_init_ctx_iv(&aes, title_key, iv); ++ AES_CBC_decrypt_buffer(&aes, header, 0x200); ++ ++ if (memcmp(&header[0x100], "NCCH", 4) != 0) ++ return rc_hash_iterator_error_formatted(iterator, "NCCH header was not at %08X%08X", (unsigned)(content_offset >> 32), (unsigned)content_offset); ++ ++ return rc_hash_nintendo_3ds_ncch(md5, file_handle, header, &aes, iterator); ++} ++ ++static int rc_hash_nintendo_3ds_3dsx(md5_state_t* md5, void* file_handle, uint8_t header[0x200], const rc_hash_iterator_t* iterator) ++{ ++ uint8_t* hash_buffer; ++ uint32_t header_size, reloc_header_size, code_size; ++ int64_t code_offset; ++ ++ header_size = (header[5] << 8) | header[4]; ++ reloc_header_size = (header[7] << 8) | header[6]; ++ code_size = ((uint32_t)header[0x13] << 24) | (header[0x12] << 16) | (header[0x11] << 8) | header[0x10]; ++ ++ /* 3 relocation headers are in-between the 3DSX header and code segment */ ++ code_offset = header_size + reloc_header_size * 3; ++ ++ if (code_size > MAX_BUFFER_SIZE) ++ code_size = MAX_BUFFER_SIZE; ++ ++ hash_buffer = (uint8_t*)malloc(code_size); ++ if (!hash_buffer) ++ return rc_hash_iterator_error_formatted(iterator, "Failed to allocate %u bytes", (unsigned)code_size); ++ ++ rc_file_seek(iterator, file_handle, code_offset, SEEK_SET); ++ ++ rc_hash_iterator_verbose_formatted(iterator, "Hashing %u bytes for 3DSX (at %08X)", (unsigned)code_size, (unsigned)code_offset); ++ ++ if (rc_file_read(iterator, file_handle, hash_buffer, code_size) != code_size) { ++ free(hash_buffer); ++ return rc_hash_iterator_error(iterator, "Could not read 3DSX code segment"); ++ } ++ ++ md5_append(md5, hash_buffer, code_size); ++ ++ free(hash_buffer); ++ return 1; ++} ++ ++int rc_hash_nintendo_3ds(char hash[33], const rc_hash_iterator_t* iterator) ++{ ++ md5_state_t md5; ++ void* file_handle; ++ uint8_t header[0x200]; /* NCCH and NCSD headers are both 0x200 bytes */ ++ int64_t header_offset; ++ ++ file_handle = rc_file_open(iterator, iterator->path); ++ if (!file_handle) ++ return rc_hash_iterator_error(iterator, "Could not open file"); ++ ++ rc_file_seek(iterator, file_handle, 0, SEEK_SET); ++ ++ /* If we don't have a full header, this is probably not a 3DS ROM */ ++ if (rc_file_read(iterator, file_handle, header, sizeof(header)) != sizeof(header)) { ++ rc_file_close(iterator, file_handle); ++ return rc_hash_iterator_error(iterator, "Could not read 3DS ROM header"); ++ } ++ ++ md5_init(&md5); ++ ++ if (memcmp(&header[0x100], "NCSD", 4) == 0) { ++ /* A NCSD container contains 1-8 NCCH partitions */ ++ /* The first partition (index 0) is reserved for executable content */ ++ header_offset = ((uint32_t)header[0x123] << 24) | (header[0x122] << 16) | (header[0x121] << 8) | header[0x120]; ++ /* Offset is in "media units" (1 media unit = 0x200 bytes) */ ++ header_offset *= 0x200; ++ ++ /* We include the NCSD header in the hash, as that will ensure different versions of a game result in a different hash ++ * This is due to some revisions / languages only ever changing other NCCH paritions (e.g. the game manual) ++ */ ++ rc_hash_iterator_verbose(iterator, "Hashing 512 byte NCSD header"); ++ md5_append(&md5, header, sizeof(header)); ++ ++ rc_hash_iterator_verbose_formatted(iterator, ++ "Detected NCSD header, seeking to NCCH partition at %08X%08X", ++ (unsigned)(header_offset >> 32), (unsigned)header_offset); ++ ++ rc_file_seek(iterator, file_handle, header_offset, SEEK_SET); ++ if (rc_file_read(iterator, file_handle, header, sizeof(header)) != sizeof(header)) { ++ rc_file_close(iterator, file_handle); ++ return rc_hash_iterator_error(iterator, "Could not read 3DS NCCH header"); ++ } ++ ++ if (memcmp(&header[0x100], "NCCH", 4) != 0) { ++ rc_file_close(iterator, file_handle); ++ return rc_hash_iterator_error_formatted(iterator, "3DS NCCH header was not at %08X%08X", (unsigned)(header_offset >> 32), (unsigned)header_offset); ++ } ++ } ++ ++ if (memcmp(&header[0x100], "NCCH", 4) == 0) { ++ if (rc_hash_nintendo_3ds_ncch(&md5, file_handle, header, NULL, iterator)) { ++ rc_file_close(iterator, file_handle); ++ return rc_hash_finalize(iterator, &md5, hash); ++ } ++ ++ rc_file_close(iterator, file_handle); ++ return rc_hash_iterator_error(iterator, "Failed to hash 3DS NCCH container"); ++ } ++ ++ /* Couldn't identify either an NCSD or NCCH */ ++ ++ /* Try to identify this as a CIA */ ++ if (header[0] == 0x20 && header[1] == 0x20 && header[2] == 0x00 && header[3] == 0x00) { ++ rc_hash_iterator_verbose(iterator, "Detected CIA, attempting to find executable NCCH"); ++ ++ if (rc_hash_nintendo_3ds_cia(&md5, file_handle, header, iterator)) { ++ rc_file_close(iterator, file_handle); ++ return rc_hash_finalize(iterator, &md5, hash); ++ } ++ ++ rc_file_close(iterator, file_handle); ++ return rc_hash_iterator_error(iterator, "Failed to hash 3DS CIA container"); ++ } ++ ++ /* This might be a homebrew game, try to detect that */ ++ if (memcmp(&header[0], "3DSX", 4) == 0) { ++ rc_hash_iterator_verbose(iterator, "Detected 3DSX"); ++ ++ if (rc_hash_nintendo_3ds_3dsx(&md5, file_handle, header, iterator)) { ++ rc_file_close(iterator, file_handle); ++ return rc_hash_finalize(iterator, &md5, hash); ++ } ++ ++ rc_file_close(iterator, file_handle); ++ return rc_hash_iterator_error(iterator, "Failed to hash 3DS 3DSX container"); ++ } ++ ++ /* Raw ELF marker (AXF/ELF files) */ ++ if (memcmp(&header[0], "\x7f\x45\x4c\x46", 4) == 0) { ++ rc_hash_iterator_verbose(iterator, "Detected AXF/ELF file, hashing entire file"); ++ ++ /* Don't bother doing anything fancy here, just hash entire file */ ++ rc_file_close(iterator, file_handle); ++ return rc_hash_whole_file(hash, iterator); ++ } ++ ++ rc_file_close(iterator, file_handle); ++ return rc_hash_iterator_error(iterator, "Not a 3DS ROM"); ++} +diff -rupbN melonDS.orig/src/rcheevos/src/rhash/hash_rom.c melonDS.ra/src/rcheevos/src/rhash/hash_rom.c +--- melonDS.orig/src/rcheevos/src/rhash/hash_rom.c 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rhash/hash_rom.c 2026-03-06 21:37:07.050799942 +0000 +@@ -0,0 +1,426 @@ ++#include "rc_hash_internal.h" ++ ++#include "../rc_compat.h" ++ ++#include ++ ++/* ===================================================== */ ++ ++static int rc_hash_unheadered_iterator_buffer(char hash[33], const rc_hash_iterator_t* iterator, size_t header_size) ++{ ++ return rc_hash_buffer(hash, iterator->buffer + header_size, iterator->buffer_size - header_size, iterator); ++} ++ ++static int rc_hash_iterator_buffer(char hash[33], const rc_hash_iterator_t* iterator) ++{ ++ return rc_hash_buffer(hash, iterator->buffer, iterator->buffer_size, iterator); ++} ++ ++/* ===================================================== */ ++ ++int rc_hash_7800(char hash[33], const rc_hash_iterator_t* iterator) ++{ ++ /* if the file contains a header, ignore it */ ++ if (memcmp(&iterator->buffer[1], "ATARI7800", 9) == 0) { ++ rc_hash_iterator_verbose(iterator, "Ignoring 7800 header"); ++ return rc_hash_unheadered_iterator_buffer(hash, iterator, 128); ++ } ++ ++ return rc_hash_iterator_buffer(hash, iterator); ++} ++ ++int rc_hash_arcade(char hash[33], const rc_hash_iterator_t* iterator) ++{ ++ /* arcade hash is just the hash of the filename (no extension) - the cores are pretty stringent about having the right ROM data */ ++ const char* filename = rc_path_get_filename(iterator->path); ++ const char* ext = rc_path_get_extension(filename); ++ char buffer[128]; /* realistically, this should never need more than ~32 characters */ ++ size_t filename_length = ext - filename - 1; ++ ++ /* fbneo supports loading subsystems by using specific folder names. ++ * if one is found, include it in the hash. ++ * https://github.com/libretro/FBNeo/blob/master/src/burner/libretro/README.md#emulating-consoles-and-computers ++ */ ++ if (filename > iterator->path + 1) { ++ int include_folder = 0; ++ const char* folder = filename - 1; ++ size_t parent_folder_length = 0; ++ ++ do { ++ if (folder[-1] == '/' || folder[-1] == '\\') ++ break; ++ ++ --folder; ++ } while (folder > iterator->path); ++ ++ parent_folder_length = filename - folder - 1; ++ if (parent_folder_length < 16) { ++ char* ptr = buffer; ++ while (folder < filename - 1) ++ *ptr++ = tolower(*folder++); ++ *ptr = '\0'; ++ ++ folder = buffer; ++ } ++ ++ switch (parent_folder_length) { ++ case 3: ++ if (memcmp(folder, "nes", 3) == 0 || /* NES */ ++ memcmp(folder, "fds", 3) == 0 || /* FDS */ ++ memcmp(folder, "sms", 3) == 0 || /* Master System */ ++ memcmp(folder, "msx", 3) == 0 || /* MSX */ ++ memcmp(folder, "ngp", 3) == 0 || /* NeoGeo Pocket */ ++ memcmp(folder, "pce", 3) == 0 || /* PCEngine */ ++ memcmp(folder, "chf", 3) == 0 || /* ChannelF */ ++ memcmp(folder, "sgx", 3) == 0) /* SuperGrafX */ ++ include_folder = 1; ++ break; ++ case 4: ++ if (memcmp(folder, "tg16", 4) == 0 || /* TurboGrafx-16 */ ++ memcmp(folder, "msx1", 4) == 0) /* MSX */ ++ include_folder = 1; ++ break; ++ case 5: ++ if (memcmp(folder, "neocd", 5) == 0) /* NeoGeo CD */ ++ include_folder = 1; ++ break; ++ case 6: ++ if (memcmp(folder, "coleco", 6) == 0 || /* Colecovision */ ++ memcmp(folder, "sg1000", 6) == 0) /* SG-1000 */ ++ include_folder = 1; ++ break; ++ case 7: ++ if (memcmp(folder, "genesis", 7) == 0) /* Megadrive (Genesis) */ ++ include_folder = 1; ++ break; ++ case 8: ++ if (memcmp(folder, "gamegear", 8) == 0 || /* Game Gear */ ++ memcmp(folder, "megadriv", 8) == 0 || /* Megadrive */ ++ memcmp(folder, "pcengine", 8) == 0 || /* PCEngine */ ++ memcmp(folder, "channelf", 8) == 0 || /* ChannelF */ ++ memcmp(folder, "spectrum", 8) == 0) /* ZX Spectrum */ ++ include_folder = 1; ++ break; ++ case 9: ++ if (memcmp(folder, "megadrive", 9) == 0) /* Megadrive */ ++ include_folder = 1; ++ break; ++ case 10: ++ if (memcmp(folder, "supergrafx", 10) == 0 || /* SuperGrafX */ ++ memcmp(folder, "zxspectrum", 10) == 0) /* ZX Spectrum */ ++ include_folder = 1; ++ break; ++ case 12: ++ if (memcmp(folder, "mastersystem", 12) == 0 || /* Master System */ ++ memcmp(folder, "colecovision", 12) == 0) /* Colecovision */ ++ include_folder = 1; ++ break; ++ default: ++ break; ++ } ++ ++ if (include_folder) { ++ if (parent_folder_length + filename_length + 1 < sizeof(buffer)) { ++ buffer[parent_folder_length] = '_'; ++ memcpy(&buffer[parent_folder_length + 1], filename, filename_length); ++ return rc_hash_buffer(hash, (uint8_t*)&buffer[0], parent_folder_length + filename_length + 1, iterator); ++ } ++ } ++ } ++ ++ return rc_hash_buffer(hash, (uint8_t*)filename, filename_length, iterator); ++} ++ ++static int rc_hash_text(char hash[33], const rc_hash_iterator_t* iterator) ++{ ++ md5_state_t md5; ++ const uint8_t* scan = iterator->buffer; ++ const uint8_t* stop = iterator->buffer + iterator->buffer_size; ++ ++ md5_init(&md5); ++ ++ do { ++ const uint8_t* line = scan; ++ ++ /* find end of line */ ++ while (scan < stop && *scan != '\r' && *scan != '\n') ++ ++scan; ++ ++ md5_append(&md5, line, (int)(scan - line)); ++ ++ /* include a normalized line ending */ ++ /* NOTE: this causes a line ending to be hashed at the end of the file, even if one was not present */ ++ md5_append(&md5, (const uint8_t*)"\n", 1); ++ ++ /* skip newline */ ++ if (scan < stop && *scan == '\r') ++ ++scan; ++ if (scan < stop && *scan == '\n') ++ ++scan; ++ ++ } while (scan < stop); ++ ++ return rc_hash_finalize(iterator, &md5, hash); ++} ++ ++int rc_hash_arduboy(char hash[33], const rc_hash_iterator_t* iterator) ++{ ++ if (iterator->path && rc_path_compare_extension(iterator->path, "arduboy")) { ++#ifndef RC_HASH_NO_ZIP ++ return rc_hash_arduboyfx(hash, iterator); ++#else ++ rc_hash_iterator_verbose(iterator, ".arduboy file processing not enabled"); ++ return 0; ++#endif ++ } ++ ++ if (!iterator->buffer) ++ return rc_hash_buffered_file(hash, RC_CONSOLE_ARDUBOY, iterator); ++ ++ /* https://en.wikipedia.org/wiki/Intel_HEX */ ++ return rc_hash_text(hash, iterator); ++} ++ ++int rc_hash_lynx(char hash[33], const rc_hash_iterator_t* iterator) ++{ ++ /* if the file contains a header, ignore it */ ++ if (memcmp(&iterator->buffer[0], "LYNX", 5) == 0) { ++ rc_hash_iterator_verbose(iterator, "Ignoring LYNX header"); ++ return rc_hash_unheadered_iterator_buffer(hash, iterator, 64); ++ } ++ ++ return rc_hash_iterator_buffer(hash, iterator); ++} ++ ++int rc_hash_nes(char hash[33], const rc_hash_iterator_t* iterator) ++{ ++ /* if the file contains a header, ignore it */ ++ if (memcmp(&iterator->buffer[0], "NES\x1a", 4) == 0) { ++ rc_hash_iterator_verbose(iterator, "Ignoring NES header"); ++ return rc_hash_unheadered_iterator_buffer(hash, iterator, 16); ++ } ++ ++ if (memcmp(&iterator->buffer[0], "FDS\x1a", 4) == 0) { ++ rc_hash_iterator_verbose(iterator, "Ignoring FDS header"); ++ return rc_hash_unheadered_iterator_buffer(hash, iterator, 16); ++ } ++ ++ return rc_hash_iterator_buffer(hash, iterator); ++} ++ ++int rc_hash_n64(char hash[33], const rc_hash_iterator_t* iterator) ++{ ++ uint8_t* buffer; ++ uint8_t* stop; ++ const size_t buffer_size = 65536; ++ md5_state_t md5; ++ size_t remaining; ++ void* file_handle; ++ int is_v64 = 0; ++ int is_n64 = 0; ++ ++ file_handle = rc_file_open(iterator, iterator->path); ++ if (!file_handle) ++ return rc_hash_iterator_error(iterator, "Could not open file"); ++ ++ buffer = (uint8_t*)malloc(buffer_size); ++ if (!buffer) { ++ rc_file_close(iterator, file_handle); ++ return rc_hash_iterator_error(iterator, "Could not allocate temporary buffer"); ++ } ++ stop = buffer + buffer_size; ++ ++ /* read first byte so we can detect endianness */ ++ rc_file_seek(iterator, file_handle, 0, SEEK_SET); ++ rc_file_read(iterator, file_handle, buffer, 1); ++ ++ if (buffer[0] == 0x80) { /* z64 format (big endian [native]) */ ++ } ++ else if (buffer[0] == 0x37) { /* v64 format (byteswapped) */ ++ rc_hash_iterator_verbose(iterator, "converting v64 to z64"); ++ is_v64 = 1; ++ } ++ else if (buffer[0] == 0x40) { /* n64 format (little endian) */ ++ rc_hash_iterator_verbose(iterator, "converting n64 to z64"); ++ is_n64 = 1; ++ } ++ else if (buffer[0] == 0xE8 || buffer[0] == 0x22) { /* ndd format (don't byteswap) */ ++ } ++ else { ++ free(buffer); ++ rc_file_close(iterator, file_handle); ++ ++ rc_hash_iterator_verbose(iterator, "Not a Nintendo 64 ROM"); ++ return 0; ++ } ++ ++ /* calculate total file size */ ++ rc_file_seek(iterator, file_handle, 0, SEEK_END); ++ remaining = (size_t)rc_file_tell(iterator, file_handle); ++ if (remaining > MAX_BUFFER_SIZE) ++ remaining = MAX_BUFFER_SIZE; ++ ++ rc_hash_iterator_verbose_formatted(iterator, "Hashing %u bytes", (unsigned)remaining); ++ ++ /* begin hashing */ ++ md5_init(&md5); ++ ++ rc_file_seek(iterator, file_handle, 0, SEEK_SET); ++ while (remaining >= buffer_size) { ++ rc_file_read(iterator, file_handle, buffer, (int)buffer_size); ++ ++ if (is_v64) ++ rc_hash_byteswap16(buffer, stop); ++ else if (is_n64) ++ rc_hash_byteswap32(buffer, stop); ++ ++ md5_append(&md5, buffer, (int)buffer_size); ++ remaining -= buffer_size; ++ } ++ ++ if (remaining > 0) { ++ rc_file_read(iterator, file_handle, buffer, (int)remaining); ++ ++ stop = buffer + remaining; ++ if (is_v64) ++ rc_hash_byteswap16(buffer, stop); ++ else if (is_n64) ++ rc_hash_byteswap32(buffer, stop); ++ ++ md5_append(&md5, buffer, (int)remaining); ++ } ++ ++ /* cleanup */ ++ rc_file_close(iterator, file_handle); ++ free(buffer); ++ ++ return rc_hash_finalize(iterator, &md5, hash); ++} ++ ++int rc_hash_nintendo_ds(char hash[33], const rc_hash_iterator_t* iterator) ++{ ++ uint8_t header[512]; ++ uint8_t* hash_buffer; ++ uint32_t hash_size, arm9_size, arm9_addr, arm7_size, arm7_addr, icon_addr; ++ size_t num_read; ++ int64_t offset = 0; ++ md5_state_t md5; ++ void* file_handle; ++ ++ file_handle = rc_file_open(iterator, iterator->path); ++ if (!file_handle) ++ return rc_hash_iterator_error(iterator, "Could not open file"); ++ ++ rc_file_seek(iterator, file_handle, 0, SEEK_SET); ++ if (rc_file_read(iterator, file_handle, header, sizeof(header)) != 512) ++ return rc_hash_iterator_error(iterator, "Failed to read header"); ++ ++ if (header[0] == 0x2E && header[1] == 0x00 && header[2] == 0x00 && header[3] == 0xEA && ++ header[0xB0] == 0x44 && header[0xB1] == 0x46 && header[0xB2] == 0x96 && header[0xB3] == 0) { ++ /* SuperCard header detected, ignore it */ ++ rc_hash_iterator_verbose(iterator, "Ignoring SuperCard header"); ++ ++ offset = 512; ++ rc_file_seek(iterator, file_handle, offset, SEEK_SET); ++ rc_file_read(iterator, file_handle, header, sizeof(header)); ++ } ++ ++ arm9_addr = header[0x20] | (header[0x21] << 8) | (header[0x22] << 16) | (header[0x23] << 24); ++ arm9_size = header[0x2C] | (header[0x2D] << 8) | (header[0x2E] << 16) | (header[0x2F] << 24); ++ arm7_addr = header[0x30] | (header[0x31] << 8) | (header[0x32] << 16) | (header[0x33] << 24); ++ arm7_size = header[0x3C] | (header[0x3D] << 8) | (header[0x3E] << 16) | (header[0x3F] << 24); ++ icon_addr = header[0x68] | (header[0x69] << 8) | (header[0x6A] << 16) | (header[0x6B] << 24); ++ ++ if (arm9_size + arm7_size > 16 * 1024 * 1024) { ++ /* sanity check - code blocks are typically less than 1MB each - assume not a DS ROM */ ++ return rc_hash_iterator_error_formatted(iterator, "arm9 code size (%u) + arm7 code size (%u) exceeds 16MB", arm9_size, arm7_size); ++ } ++ ++ hash_size = 0xA00; ++ if (arm9_size > hash_size) ++ hash_size = arm9_size; ++ if (arm7_size > hash_size) ++ hash_size = arm7_size; ++ ++ hash_buffer = (uint8_t*)malloc(hash_size); ++ if (!hash_buffer) { ++ rc_file_close(iterator, file_handle); ++ return rc_hash_iterator_error_formatted(iterator, "Failed to allocate %u bytes", hash_size); ++ } ++ ++ md5_init(&md5); ++ ++ rc_hash_iterator_verbose(iterator, "Hashing 352 byte header"); ++ md5_append(&md5, header, 0x160); ++ ++ rc_hash_iterator_verbose_formatted(iterator, "Hashing %u byte arm9 code (at %08X)", arm9_size, arm9_addr); ++ ++ rc_file_seek(iterator, file_handle, arm9_addr + offset, SEEK_SET); ++ rc_file_read(iterator, file_handle, hash_buffer, arm9_size); ++ md5_append(&md5, hash_buffer, arm9_size); ++ ++ rc_hash_iterator_verbose_formatted(iterator, "Hashing %u byte arm7 code (at %08X)", arm7_size, arm7_addr); ++ ++ rc_file_seek(iterator, file_handle, arm7_addr + offset, SEEK_SET); ++ rc_file_read(iterator, file_handle, hash_buffer, arm7_size); ++ md5_append(&md5, hash_buffer, arm7_size); ++ ++ rc_hash_iterator_verbose_formatted(iterator, "Hashing 2560 byte icon and labels data (at %08X)", icon_addr); ++ ++ rc_file_seek(iterator, file_handle, icon_addr + offset, SEEK_SET); ++ num_read = rc_file_read(iterator, file_handle, hash_buffer, 0xA00); ++ if (num_read < 0xA00) { ++ /* some homebrew games don't provide a full icon block, and no data after the icon block. ++ * if we didn't get a full icon block, fill the remaining portion with 0s ++ */ ++ rc_hash_iterator_verbose_formatted(iterator, ++ "Warning: only got %u bytes for icon and labels data, 0-padding to 2560 bytes", (unsigned)num_read); ++ ++ memset(&hash_buffer[num_read], 0, 0xA00 - num_read); ++ } ++ md5_append(&md5, hash_buffer, 0xA00); ++ ++ free(hash_buffer); ++ rc_file_close(iterator, file_handle); ++ ++ return rc_hash_finalize(iterator, &md5, hash); ++} ++ ++int rc_hash_pce(char hash[33], const rc_hash_iterator_t* iterator) ++{ ++ /* The PCE header doesn't bear any distinguishable marks, so we have to detect ++ * it by looking at the file size. The core looks for anything that's 512 bytes ++ * more than a multiple of 8KB, so we'll do that too. ++ * https://github.com/libretro/beetle-pce-libretro/blob/af28fb0385d00e0292c4703b3aa7e72762b564d2/mednafen/pce/huc.cpp#L196-L202 ++ */ ++ if (iterator->buffer_size & 512) { ++ rc_hash_iterator_verbose(iterator, "Ignoring PCE header"); ++ return rc_hash_unheadered_iterator_buffer(hash, iterator, 512); ++ } ++ ++ return rc_hash_iterator_buffer(hash, iterator); ++} ++ ++int rc_hash_scv(char hash[33], const rc_hash_iterator_t* iterator) ++{ ++ /* if the file contains a header, ignore it */ ++ /* https://gitlab.com/MaaaX-EmuSCV/libretro-emuscv/-/blob/master/readme.txt#L211 */ ++ if (memcmp(iterator->buffer, "EmuSCV", 6) == 0) { ++ rc_hash_iterator_verbose(iterator, "Ignoring SCV header"); ++ return rc_hash_unheadered_iterator_buffer(hash, iterator, 32); ++ } ++ ++ return rc_hash_iterator_buffer(hash, iterator); ++} ++ ++int rc_hash_snes(char hash[33], const rc_hash_iterator_t* iterator) ++{ ++ /* if the file contains a header, ignore it */ ++ uint32_t calc_size = ((uint32_t)iterator->buffer_size / 0x2000) * 0x2000; ++ if (iterator->buffer_size - calc_size == 512) { ++ rc_hash_iterator_verbose(iterator, "Ignoring SNES header"); ++ return rc_hash_unheadered_iterator_buffer(hash, iterator, 512); ++ } ++ ++ return rc_hash_iterator_buffer(hash, iterator); ++} +diff -rupbN melonDS.orig/src/rcheevos/src/rhash/hash_zip.c melonDS.ra/src/rcheevos/src/rhash/hash_zip.c +--- melonDS.orig/src/rcheevos/src/rhash/hash_zip.c 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rhash/hash_zip.c 2026-03-06 21:37:07.050799942 +0000 +@@ -0,0 +1,460 @@ ++#include "rc_hash_internal.h" ++ ++#include "../rc_compat.h" ++ ++struct rc_hash_zip_idx ++{ ++ size_t length; ++ uint8_t* data; ++}; ++ ++static int rc_hash_zip_idx_sort(const void* a, const void* b) ++{ ++ struct rc_hash_zip_idx* A = (struct rc_hash_zip_idx*)a, * B = (struct rc_hash_zip_idx*)b; ++ size_t len = (A->length < B->length ? A->length : B->length); ++ return memcmp(A->data, B->data, len); ++} ++ ++typedef int (RC_CCONV* rc_hash_zip_filter_t)(const char* filename, uint32_t filename_len, uint64_t decomp_size, void* userdata); ++ ++static int rc_hash_zip_file(md5_state_t* md5, void* file_handle, ++ const rc_hash_iterator_t* iterator, ++ rc_hash_zip_filter_t filter_func, void* filter_userdata) ++{ ++ uint8_t buf[2048], *alloc_buf, *cdir_start, *cdir_max, *cdir, *hashdata, eocdirhdr_size, cdirhdr_size, nparents; ++ uint32_t cdir_entry_len; ++ size_t sizeof_idx, indices_offset, alloc_size; ++ int64_t i_file, archive_size, ecdh_ofs, total_files, cdir_size, cdir_ofs; ++ struct rc_hash_zip_idx* hashindices, *hashindex; ++ ++ rc_file_seek(iterator, file_handle, 0, SEEK_END); ++ archive_size = rc_file_tell(iterator, file_handle); ++ ++ /* Basic sanity checks - reject files which are too small */ ++ eocdirhdr_size = 22; /* the 'end of central directory header' is 22 bytes */ ++ if (archive_size < eocdirhdr_size) ++ return rc_hash_iterator_error(iterator, "ZIP is too small"); ++ ++ /* Macros used for reading ZIP and writing to a buffer for hashing (undefined again at the end of the function) */ ++ #define RC_ZIP_READ_LE16(p) ((uint16_t)(((const uint8_t*)(p))[0]) | ((uint16_t)(((const uint8_t*)(p))[1]) << 8U)) ++ #define RC_ZIP_READ_LE32(p) ((uint32_t)(((const uint8_t*)(p))[0]) | ((uint32_t)(((const uint8_t*)(p))[1]) << 8U) | ((uint32_t)(((const uint8_t*)(p))[2]) << 16U) | ((uint32_t)(((const uint8_t*)(p))[3]) << 24U)) ++ #define RC_ZIP_READ_LE64(p) ((uint64_t)(((const uint8_t*)(p))[0]) | ((uint64_t)(((const uint8_t*)(p))[1]) << 8U) | ((uint64_t)(((const uint8_t*)(p))[2]) << 16U) | ((uint64_t)(((const uint8_t*)(p))[3]) << 24U) | ((uint64_t)(((const uint8_t*)(p))[4]) << 32U) | ((uint64_t)(((const uint8_t*)(p))[5]) << 40U) | ((uint64_t)(((const uint8_t*)(p))[6]) << 48U) | ((uint64_t)(((const uint8_t*)(p))[7]) << 56U)) ++ #define RC_ZIP_WRITE_LE32(p,v) { ((uint8_t*)(p))[0] = (uint8_t)((uint32_t)(v) & 0xFF); ((uint8_t*)(p))[1] = (uint8_t)(((uint32_t)(v) >> 8) & 0xFF); ((uint8_t*)(p))[2] = (uint8_t)(((uint32_t)(v) >> 16) & 0xFF); ((uint8_t*)(p))[3] = (uint8_t)((uint32_t)(v) >> 24); } ++ #define RC_ZIP_WRITE_LE64(p,v) { ((uint8_t*)(p))[0] = (uint8_t)((uint64_t)(v) & 0xFF); ((uint8_t*)(p))[1] = (uint8_t)(((uint64_t)(v) >> 8) & 0xFF); ((uint8_t*)(p))[2] = (uint8_t)(((uint64_t)(v) >> 16) & 0xFF); ((uint8_t*)(p))[3] = (uint8_t)(((uint64_t)(v) >> 24) & 0xFF); ((uint8_t*)(p))[4] = (uint8_t)(((uint64_t)(v) >> 32) & 0xFF); ((uint8_t*)(p))[5] = (uint8_t)(((uint64_t)(v) >> 40) & 0xFF); ((uint8_t*)(p))[6] = (uint8_t)(((uint64_t)(v) >> 48) & 0xFF); ((uint8_t*)(p))[7] = (uint8_t)((uint64_t)(v) >> 56); } ++ ++ /* Find the end of central directory record by scanning the file from the end towards the beginning */ ++ for (ecdh_ofs = archive_size - sizeof(buf); ; ecdh_ofs -= (sizeof(buf) - 3)) { ++ int i, n = sizeof(buf); ++ if (ecdh_ofs < 0) ++ ecdh_ofs = 0; ++ if (n > archive_size) ++ n = (int)archive_size; ++ ++ rc_file_seek(iterator, file_handle, ecdh_ofs, SEEK_SET); ++ if (rc_file_read(iterator, file_handle, buf, n) != (size_t)n) ++ return rc_hash_iterator_error(iterator, "ZIP read error"); ++ ++ for (i = n - 4; i >= 0; --i) { ++ if (buf[i] == 'P' && RC_ZIP_READ_LE32(buf + i) == 0x06054b50) /* end of central directory header signature */ ++ break; ++ } ++ ++ if (i >= 0) { ++ ecdh_ofs += i; ++ break; ++ } ++ ++ if (!ecdh_ofs || (archive_size - ecdh_ofs) >= (0xFFFF + eocdirhdr_size)) ++ return rc_hash_iterator_error(iterator, "Failed to find ZIP central directory"); ++ } ++ ++ /* Read and verify the end of central directory record. */ ++ rc_file_seek(iterator, file_handle, ecdh_ofs, SEEK_SET); ++ if (rc_file_read(iterator, file_handle, buf, eocdirhdr_size) != eocdirhdr_size) ++ return rc_hash_iterator_error(iterator, "Failed to read ZIP central directory"); ++ ++ /* Read central dir information from end of central directory header */ ++ total_files = RC_ZIP_READ_LE16(buf + 0x0A); ++ cdir_size = RC_ZIP_READ_LE32(buf + 0x0C); ++ cdir_ofs = RC_ZIP_READ_LE32(buf + 0x10); ++ ++ /* Check if this is a Zip64 file. In the block of code below: ++ * - 20 is the size of the ZIP64 end of central directory locator ++ * - 56 is the size of the ZIP64 end of central directory header ++ */ ++ if ((cdir_ofs == 0xFFFFFFFF || cdir_size == 0xFFFFFFFF || total_files == 0xFFFF) && ecdh_ofs >= (20 + 56)) { ++ /* Read the ZIP64 end of central directory locator if it actually exists */ ++ rc_file_seek(iterator, file_handle, ecdh_ofs - 20, SEEK_SET); ++ if (rc_file_read(iterator, file_handle, buf, 20) == 20 && RC_ZIP_READ_LE32(buf) == 0x07064b50) { /* locator signature */ ++ /* Found the locator, now read the actual ZIP64 end of central directory header */ ++ int64_t ecdh64_ofs = (int64_t)RC_ZIP_READ_LE64(buf + 0x08); ++ if (ecdh64_ofs <= (archive_size - 56)) { ++ rc_file_seek(iterator, file_handle, ecdh64_ofs, SEEK_SET); ++ if (rc_file_read(iterator, file_handle, buf, 56) == 56 && RC_ZIP_READ_LE32(buf) == 0x06064b50) { /* header signature */ ++ total_files = RC_ZIP_READ_LE64(buf + 0x20); ++ cdir_size = RC_ZIP_READ_LE64(buf + 0x28); ++ cdir_ofs = RC_ZIP_READ_LE64(buf + 0x30); ++ } ++ } ++ } ++ } ++ ++ /* Basic verificaton of central directory (limit to a 256MB content directory) */ ++ cdirhdr_size = 46; /* the 'central directory header' is 46 bytes */ ++ if ((cdir_size >= 0x10000000) || (cdir_size < total_files * cdirhdr_size) || ((cdir_ofs + cdir_size) > archive_size)) ++ return rc_hash_iterator_error(iterator, "Central directory of ZIP file is invalid"); ++ ++ /* Allocate once for both directory and our temporary sort index (memory aligned to sizeof(rc_hash_zip_idx)) */ ++ sizeof_idx = sizeof(struct rc_hash_zip_idx); ++ indices_offset = (size_t)((cdir_size + sizeof_idx - 1) / sizeof_idx * sizeof_idx); ++ alloc_size = (size_t)(indices_offset + total_files * sizeof_idx); ++ alloc_buf = (uint8_t*)malloc(alloc_size); ++ ++ /* Read entire central directory to a buffer */ ++ if (!alloc_buf) ++ return rc_hash_iterator_error(iterator, "Could not allocate temporary buffer"); ++ ++ rc_file_seek(iterator, file_handle, cdir_ofs, SEEK_SET); ++ if ((int64_t)rc_file_read(iterator, file_handle, alloc_buf, (int)cdir_size) != cdir_size) { ++ free(alloc_buf); ++ return rc_hash_iterator_error(iterator, "Failed to read central directory of ZIP file"); ++ } ++ ++ cdir_start = alloc_buf; ++ cdir_max = cdir_start + cdir_size - cdirhdr_size; ++ cdir = cdir_start; ++ ++ /* Write our temporary hash data to the same buffer we read the central directory from. ++ * We can do that because the amount of data we keep for each file is guaranteed to be less than the file record. ++ */ ++ hashdata = alloc_buf; ++ hashindices = (struct rc_hash_zip_idx*)(alloc_buf + indices_offset); ++ hashindex = hashindices; ++ ++ /* Now process the central directory file records */ ++ for (i_file = nparents = 0, cdir = cdir_start; i_file < total_files && cdir >= cdir_start && cdir <= cdir_max; i_file++, cdir += cdir_entry_len) { ++ const uint8_t* name, * name_end; ++ uint32_t signature = RC_ZIP_READ_LE32(cdir + 0x00); ++ uint32_t method = RC_ZIP_READ_LE16(cdir + 0x0A); ++ uint32_t crc32 = RC_ZIP_READ_LE32(cdir + 0x10); ++ uint64_t comp_size = RC_ZIP_READ_LE32(cdir + 0x14); ++ uint64_t decomp_size = RC_ZIP_READ_LE32(cdir + 0x18); ++ uint32_t filename_len = RC_ZIP_READ_LE16(cdir + 0x1C); ++ int32_t extra_len = RC_ZIP_READ_LE16(cdir + 0x1E); ++ int32_t comment_len = RC_ZIP_READ_LE16(cdir + 0x20); ++ int32_t external_attr = RC_ZIP_READ_LE16(cdir + 0x26); ++ uint64_t local_hdr_ofs = RC_ZIP_READ_LE32(cdir + 0x2A); ++ cdir_entry_len = cdirhdr_size + filename_len + extra_len + comment_len; ++ ++ if (signature != 0x02014b50) /* expected central directory entry signature */ ++ break; ++ ++ /* Ignore records describing a directory (we only hash file records) */ ++ name = (cdir + cdirhdr_size); ++ if (name[filename_len - 1] == '/' || name[filename_len - 1] == '\\' || (external_attr & 0x10)) ++ continue; ++ ++ /* Handle Zip64 fields */ ++ if (decomp_size == 0xFFFFFFFF || comp_size == 0xFFFFFFFF || local_hdr_ofs == 0xFFFFFFFF) { ++ int invalid = 0; ++ const uint8_t* x = cdir + cdirhdr_size + filename_len, * xEnd, * field, * fieldEnd; ++ for (xEnd = x + extra_len; (x + (sizeof(uint16_t) * 2)) < xEnd; x = fieldEnd) { ++ field = x + (sizeof(uint16_t) * 2); ++ fieldEnd = field + RC_ZIP_READ_LE16(x + 2); ++ if (RC_ZIP_READ_LE16(x) != 0x0001 || fieldEnd > xEnd) ++ continue; /* Not the Zip64 extended information extra field */ ++ ++ if (decomp_size == 0xFFFFFFFF) { ++ if ((unsigned)(fieldEnd - field) < sizeof(uint64_t)) { ++ invalid = 1; ++ break; ++ } ++ ++ decomp_size = RC_ZIP_READ_LE64(field); ++ field += sizeof(uint64_t); ++ } ++ ++ if (comp_size == 0xFFFFFFFF) { ++ if ((unsigned)(fieldEnd - field) < sizeof(uint64_t)) { ++ invalid = 1; ++ break; ++ } ++ ++ comp_size = RC_ZIP_READ_LE64(field); ++ field += sizeof(uint64_t); ++ } ++ ++ if (local_hdr_ofs == 0xFFFFFFFF) { ++ if ((unsigned)(fieldEnd - field) < sizeof(uint64_t)) { ++ invalid = 1; ++ break; ++ } ++ ++ local_hdr_ofs = RC_ZIP_READ_LE64(field); ++ field += sizeof(uint64_t); ++ } ++ ++ break; ++ } ++ ++ if (invalid) { ++ free(alloc_buf); ++ return rc_hash_iterator_error(iterator, "Encountered invalid Zip64 file"); ++ } ++ } ++ ++ /* Basic sanity check on file record */ ++ /* 30 is the length of the local directory header preceeding the compressed data */ ++ if ((!method && decomp_size != comp_size) || (decomp_size && !comp_size) || ++ ((local_hdr_ofs + 30 + comp_size) > (uint64_t)archive_size)) { ++ free(alloc_buf); ++ return rc_hash_iterator_error(iterator, "Encountered invalid entry in ZIP central directory"); ++ } ++ ++ if (filter_func) { ++ int filtered = filter_func((const char*)name, filename_len, decomp_size, filter_userdata); ++ if (filtered < 0) { ++ free(alloc_buf); ++ return 0; ++ } ++ ++ if (filtered) /* this file shouldn't be hashed */ ++ continue; ++ } ++ ++ /* Write the pointer and length of the data we record about this file */ ++ hashindex->data = hashdata; ++ hashindex->length = filename_len + 1 + 4 + 8; ++ hashindex++; ++ ++ rc_hash_iterator_verbose_formatted(iterator, "File in ZIP: %.*s (%u bytes, CRC32 = %08X)", filename_len, (const char*)name, (unsigned)decomp_size, crc32); ++ ++ /* Convert and store the file name in the hash data buffer */ ++ for (name_end = name + filename_len; name != name_end; name++) { ++ *(hashdata++) = ++ (*name == '\\' ? '/' : /* convert back-slashes to regular slashes */ ++ (*name >= 'A' && *name <= 'Z') ? (*name | 0x20) : /* convert upper case letters to lower case */ ++ *name); /* else use the byte as-is */ ++ } ++ ++ /* Add zero terminator, CRC32 and decompressed size to the hash data buffer */ ++ *(hashdata++) = '\0'; ++ RC_ZIP_WRITE_LE32(hashdata, crc32); ++ hashdata += 4; ++ RC_ZIP_WRITE_LE64(hashdata, decomp_size); ++ hashdata += 8; ++ } ++ ++ rc_hash_iterator_verbose_formatted(iterator, "Hashing %u files in ZIP archive", (unsigned)(hashindex - hashindices)); ++ ++ /* Sort the file list indices */ ++ qsort(hashindices, (hashindex - hashindices), sizeof(struct rc_hash_zip_idx), rc_hash_zip_idx_sort); ++ ++ /* Hash the data in the order of the now sorted indices */ ++ for (; hashindices != hashindex; hashindices++) ++ md5_append(md5, hashindices->data, (int)hashindices->length); ++ ++ free(alloc_buf); ++ ++ return 1; ++ ++ #undef RC_ZIP_READ_LE16 ++ #undef RC_ZIP_READ_LE32 ++ #undef RC_ZIP_READ_LE64 ++ #undef RC_ZIP_WRITE_LE32 ++ #undef RC_ZIP_WRITE_LE64 ++} ++ ++/* ===================================================== */ ++ ++static int rc_hash_arduboyfx_filter(const char* filename, uint32_t filename_len, uint64_t decomp_size, void* userdata) ++{ ++ (void)decomp_size; ++ (void)userdata; ++ ++ /* An .arduboy file is a zip file containing an info.json pointing at one or more bin ++ * and hex files. It can also contain a bunch of screenshots, but we don't care about ++ * those. As they're also referenced in the info.json, we have to ignore that too. ++ * Instead of ignoring the info.json and all image files, only process any bin/hex files */ ++ if (filename_len > 4) { ++ const char* ext = &filename[filename_len - 4]; ++ if (strncasecmp(ext, ".hex", 4) == 0 || strncasecmp(ext, ".bin", 4) == 0) ++ return 0; /* keep hex and bin */ ++ } ++ ++ return 1; /* filter everything else */ ++} ++ ++int rc_hash_arduboyfx(char hash[33], const rc_hash_iterator_t* iterator) ++{ ++ md5_state_t md5; ++ int res; ++ ++ void* file_handle = rc_file_open(iterator, iterator->path); ++ if (!file_handle) ++ return rc_hash_iterator_error(iterator, "Could not open file"); ++ ++ md5_init(&md5); ++ res = rc_hash_zip_file(&md5, file_handle, iterator, rc_hash_arduboyfx_filter, NULL); ++ rc_file_close(iterator, file_handle); ++ ++ if (!res) ++ return 0; ++ ++ return rc_hash_finalize(iterator, &md5, hash); ++} ++ ++/* ===================================================== */ ++ ++struct rc_hash_ms_dos_dosz_state { ++ const char* path; ++ const struct rc_hash_ms_dos_dosz_state* child; ++ ++ md5_state_t* md5; ++ const rc_hash_iterator_t* iterator; ++ void* file_handle; ++ uint32_t nparents; ++}; ++ ++static int rc_hash_dosz(struct rc_hash_ms_dos_dosz_state* dosz); ++ ++static int rc_hash_ms_dos_parent(const struct rc_hash_ms_dos_dosz_state* child, ++ const char* parentname, uint32_t parentname_len) ++{ ++ const char* lastfslash = strrchr(child->path, '/'); ++ const char* lastbslash = strrchr(child->path, '\\'); ++ const char* lastslash = (lastbslash > lastfslash ? lastbslash : lastfslash); ++ size_t dir_len = (lastslash ? (lastslash + 1 - child->path) : 0); ++ char* parent_path = (char*)malloc(dir_len + parentname_len + 1); ++ struct rc_hash_ms_dos_dosz_state parent; ++ const struct rc_hash_ms_dos_dosz_state* check; ++ void* parent_handle; ++ int parent_res; ++ ++ /* Build the path of the parent by combining the directory of the current file with the name */ ++ if (!parent_path) ++ return rc_hash_iterator_error(child->iterator, "Could not allocate temporary buffer"); ++ ++ memcpy(parent_path, child->path, dir_len); ++ memcpy(parent_path + dir_len, parentname, parentname_len); ++ parent_path[dir_len + parentname_len] = '\0'; ++ ++ /* Make sure there is no recursion where a parent DOSZ is an already seen child DOSZ */ ++ for (check = child->child; check; check = check->child) { ++ if (!strcmp(check->path, parent_path)) { ++ free(parent_path); ++ return rc_hash_iterator_error(child->iterator, "Invalid DOSZ file with recursive parents"); ++ } ++ } ++ ++ /* Try to open the parent DOSZ file */ ++ parent_handle = rc_file_open(child->iterator, parent_path); ++ if (!parent_handle) { ++ rc_hash_iterator_error_formatted(child->iterator, "DOSZ parent file '%s' does not exist", parent_path); ++ free(parent_path); ++ return 0; ++ } ++ ++ /* Fully hash the parent DOSZ ahead of the child */ ++ memcpy(&parent, child, sizeof(parent)); ++ parent.path = parent_path; ++ parent.child = child; ++ parent.file_handle = parent_handle; ++ parent_res = rc_hash_dosz(&parent); ++ rc_file_close(child->iterator, parent_handle); ++ free(parent_path); ++ return parent_res; ++} ++ ++static int rc_hash_ms_dos_dosc(const struct rc_hash_ms_dos_dosz_state* dosz) ++{ ++ size_t path_len = strlen(dosz->path); ++ if (dosz->path[path_len - 1] == 'z' || dosz->path[path_len - 1] == 'Z') { ++ void* file_handle; ++ char* dosc_path = strdup(dosz->path); ++ if (!dosc_path) ++ return rc_hash_iterator_error(dosz->iterator, "Could not allocate temporary buffer"); ++ ++ /* Swap the z to c and use the same capitalization, hash the file if it exists */ ++ dosc_path[path_len - 1] = (dosz->path[path_len - 1] == 'z' ? 'c' : 'C'); ++ file_handle = rc_file_open(dosz->iterator, dosc_path); ++ free(dosc_path); ++ ++ if (file_handle) { ++ /* Hash the entire contents of the DOSC file */ ++ int res = rc_hash_zip_file(dosz->md5, file_handle, dosz->iterator, NULL, NULL); ++ rc_file_close(dosz->iterator, file_handle); ++ if (!res) ++ return 0; ++ } ++ } ++ ++ return 1; ++} ++ ++static int rc_hash_dosz_filter(const char* filename, uint32_t filename_len, uint64_t decomp_size, void* userdata) ++{ ++ struct rc_hash_ms_dos_dosz_state* dosz = (struct rc_hash_ms_dos_dosz_state*)userdata; ++ ++ /* A DOSZ file can contain a special empty .dosz.parent file in its root which means a parent dosz file is used */ ++ if (decomp_size == 0 && filename_len > 7 && ++ strncasecmp(&filename[filename_len - 7], ".parent", 7) == 0 && ++ !memchr(filename, '/', filename_len) && ++ !memchr(filename, '\\', filename_len)) ++ { ++ /* A DOSZ file can only have one parent file */ ++ if (dosz->nparents++) ++ return -1; ++ ++ /* process the parent. if it fails, stop */ ++ if (!rc_hash_ms_dos_parent(dosz, filename, (filename_len - 7))) ++ return -1; ++ ++ /* We don't hash this meta file so a user is free to rename it and the parent file */ ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static int rc_hash_dosz(struct rc_hash_ms_dos_dosz_state* dosz) ++{ ++ if (!rc_hash_zip_file(dosz->md5, dosz->file_handle, dosz->iterator, rc_hash_dosz_filter, dosz)) ++ return 0; ++ ++ /* A DOSZ file can only have one parent file */ ++ if (dosz->nparents > 1) ++ return rc_hash_iterator_error(dosz->iterator, "Invalid DOSZ file with multiple parents"); ++ ++ /* Check if an associated .dosc file exists */ ++ if (!rc_hash_ms_dos_dosc(dosz)) ++ return 0; ++ ++ return 1; ++} ++ ++int rc_hash_ms_dos(char hash[33], const rc_hash_iterator_t* iterator) ++{ ++ struct rc_hash_ms_dos_dosz_state dosz; ++ md5_state_t md5; ++ int res; ++ ++ void* file_handle = rc_file_open(iterator, iterator->path); ++ if (!file_handle) ++ return rc_hash_iterator_error(iterator, "Could not open file"); ++ ++ memset(&dosz, 0, sizeof(dosz)); ++ dosz.path = iterator->path; ++ dosz.file_handle = file_handle; ++ dosz.iterator = iterator; ++ dosz.md5 = &md5; ++ ++ md5_init(&md5); ++ res = rc_hash_dosz(&dosz); ++ rc_file_close(iterator, file_handle); ++ ++ if (!res) ++ return 0; ++ ++ return rc_hash_finalize(iterator, &md5, hash); ++} +diff -rupbN melonDS.orig/src/rcheevos/src/rhash/md5.c melonDS.ra/src/rcheevos/src/rhash/md5.c +--- melonDS.orig/src/rcheevos/src/rhash/md5.c 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rhash/md5.c 2026-03-06 21:37:07.050799942 +0000 +@@ -0,0 +1,382 @@ ++/* ++ Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved. ++ ++ This software is provided 'as-is', without any express or implied ++ warranty. In no event will the authors be held liable for any damages ++ arising from the use of 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 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 notice may not be removed or altered from any source distribution. ++ ++ L. Peter Deutsch ++ ghost@aladdin.com ++ ++ */ ++/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */ ++/* ++ Independent implementation of MD5 (RFC 1321). ++ ++ This code implements the MD5 Algorithm defined in RFC 1321, whose ++ text is available at ++ http://www.ietf.org/rfc/rfc1321.txt ++ The code is derived from the text of the RFC, including the test suite ++ (section A.5) but excluding the rest of Appendix A. It does not include ++ any code or documentation that is identified in the RFC as being ++ copyrighted. ++ ++ The original and principal author of md5.c is L. Peter Deutsch ++ . Other authors are noted in the change history ++ that follows (in reverse chronological order): ++ ++ 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order ++ either statically or dynamically; added missing #include ++ in library. ++ 2002-03-11 lpd Corrected argument list for main(), and added int return ++ type, in test program and T value program. ++ 2002-02-21 lpd Added missing #include in test program. ++ 2000-07-03 lpd Patched to eliminate warnings about "constant is ++ unsigned in ANSI C, signed in traditional"; made test program ++ self-checking. ++ 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. ++ 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). ++ 1999-05-03 lpd Original version. ++ */ ++ ++#include "md5.h" ++#include ++#include ++ ++#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */ ++#ifdef ARCH_IS_BIG_ENDIAN ++# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1) ++#else ++# define BYTE_ORDER 0 ++#endif ++ ++#define T_MASK ((md5_word_t)~0) ++#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) ++#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) ++#define T3 0x242070db ++#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) ++#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) ++#define T6 0x4787c62a ++#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) ++#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) ++#define T9 0x698098d8 ++#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) ++#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) ++#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) ++#define T13 0x6b901122 ++#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) ++#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) ++#define T16 0x49b40821 ++#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) ++#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) ++#define T19 0x265e5a51 ++#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) ++#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) ++#define T22 0x02441453 ++#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) ++#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) ++#define T25 0x21e1cde6 ++#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) ++#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) ++#define T28 0x455a14ed ++#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) ++#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) ++#define T31 0x676f02d9 ++#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) ++#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) ++#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) ++#define T35 0x6d9d6122 ++#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) ++#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) ++#define T38 0x4bdecfa9 ++#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) ++#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) ++#define T41 0x289b7ec6 ++#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) ++#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) ++#define T44 0x04881d05 ++#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) ++#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) ++#define T47 0x1fa27cf8 ++#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) ++#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) ++#define T50 0x432aff97 ++#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) ++#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) ++#define T53 0x655b59c3 ++#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) ++#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) ++#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) ++#define T57 0x6fa87e4f ++#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) ++#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) ++#define T60 0x4e0811a1 ++#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) ++#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) ++#define T63 0x2ad7d2bb ++#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) ++ ++ ++static void ++md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) ++{ ++ md5_word_t ++ a = pms->abcd[0], b = pms->abcd[1], ++ c = pms->abcd[2], d = pms->abcd[3]; ++ md5_word_t t; ++#if BYTE_ORDER > 0 ++ /* Define storage only for big-endian CPUs. */ ++ md5_word_t X[16]; ++#else ++ /* Define storage for little-endian or both types of CPUs. */ ++ md5_word_t xbuf[16]; ++ const md5_word_t *X; ++#endif ++ ++ { ++#if BYTE_ORDER == 0 ++ /* ++ * Determine dynamically whether this is a big-endian or ++ * little-endian machine, since we can use a more efficient ++ * algorithm on the latter. ++ */ ++ static const int w = 1; ++ ++ if (*((const md5_byte_t *)&w)) /* dynamic little-endian */ ++#endif ++#if BYTE_ORDER <= 0 /* little-endian */ ++ { ++ /* ++ * On little-endian machines, we can process properly aligned ++ * data without copying it. ++ */ ++ if (!((ptrdiff_t)data & 3)) { ++ /* data are properly aligned */ ++ X = (const md5_word_t *)data; ++ } else { ++ /* not aligned */ ++ memcpy(xbuf, data, 64); ++ X = xbuf; ++ } ++ } ++#endif ++#if BYTE_ORDER == 0 ++ else /* dynamic big-endian */ ++#endif ++#if BYTE_ORDER >= 0 /* big-endian */ ++ { ++ /* ++ * On big-endian machines, we must arrange the bytes in the ++ * right order. ++ */ ++ const md5_byte_t *xp = data; ++ int i; ++ ++# if BYTE_ORDER == 0 ++ X = xbuf; /* (dynamic only) */ ++# else ++# define xbuf X /* (static only) */ ++# endif ++ for (i = 0; i < 16; ++i, xp += 4) ++ xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); ++ } ++#endif ++ } ++ ++#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) ++ ++ /* Round 1. */ ++ /* Let [abcd k s i] denote the operation ++ a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ ++#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) ++#define SET(a, b, c, d, k, s, Ti)\ ++ t = a + F(b,c,d) + X[k] + Ti;\ ++ a = ROTATE_LEFT(t, s) + b ++ /* Do the following 16 operations. */ ++ SET(a, b, c, d, 0, 7, T1); ++ SET(d, a, b, c, 1, 12, T2); ++ SET(c, d, a, b, 2, 17, T3); ++ SET(b, c, d, a, 3, 22, T4); ++ SET(a, b, c, d, 4, 7, T5); ++ SET(d, a, b, c, 5, 12, T6); ++ SET(c, d, a, b, 6, 17, T7); ++ SET(b, c, d, a, 7, 22, T8); ++ SET(a, b, c, d, 8, 7, T9); ++ SET(d, a, b, c, 9, 12, T10); ++ SET(c, d, a, b, 10, 17, T11); ++ SET(b, c, d, a, 11, 22, T12); ++ SET(a, b, c, d, 12, 7, T13); ++ SET(d, a, b, c, 13, 12, T14); ++ SET(c, d, a, b, 14, 17, T15); ++ SET(b, c, d, a, 15, 22, T16); ++#undef SET ++ ++ /* Round 2. */ ++ /* Let [abcd k s i] denote the operation ++ a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ ++#define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) ++#define SET(a, b, c, d, k, s, Ti)\ ++ t = a + G(b,c,d) + X[k] + Ti;\ ++ a = ROTATE_LEFT(t, s) + b ++ /* Do the following 16 operations. */ ++ SET(a, b, c, d, 1, 5, T17); ++ SET(d, a, b, c, 6, 9, T18); ++ SET(c, d, a, b, 11, 14, T19); ++ SET(b, c, d, a, 0, 20, T20); ++ SET(a, b, c, d, 5, 5, T21); ++ SET(d, a, b, c, 10, 9, T22); ++ SET(c, d, a, b, 15, 14, T23); ++ SET(b, c, d, a, 4, 20, T24); ++ SET(a, b, c, d, 9, 5, T25); ++ SET(d, a, b, c, 14, 9, T26); ++ SET(c, d, a, b, 3, 14, T27); ++ SET(b, c, d, a, 8, 20, T28); ++ SET(a, b, c, d, 13, 5, T29); ++ SET(d, a, b, c, 2, 9, T30); ++ SET(c, d, a, b, 7, 14, T31); ++ SET(b, c, d, a, 12, 20, T32); ++#undef SET ++ ++ /* Round 3. */ ++ /* Let [abcd k s t] denote the operation ++ a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ ++#define H(x, y, z) ((x) ^ (y) ^ (z)) ++#define SET(a, b, c, d, k, s, Ti)\ ++ t = a + H(b,c,d) + X[k] + Ti;\ ++ a = ROTATE_LEFT(t, s) + b ++ /* Do the following 16 operations. */ ++ SET(a, b, c, d, 5, 4, T33); ++ SET(d, a, b, c, 8, 11, T34); ++ SET(c, d, a, b, 11, 16, T35); ++ SET(b, c, d, a, 14, 23, T36); ++ SET(a, b, c, d, 1, 4, T37); ++ SET(d, a, b, c, 4, 11, T38); ++ SET(c, d, a, b, 7, 16, T39); ++ SET(b, c, d, a, 10, 23, T40); ++ SET(a, b, c, d, 13, 4, T41); ++ SET(d, a, b, c, 0, 11, T42); ++ SET(c, d, a, b, 3, 16, T43); ++ SET(b, c, d, a, 6, 23, T44); ++ SET(a, b, c, d, 9, 4, T45); ++ SET(d, a, b, c, 12, 11, T46); ++ SET(c, d, a, b, 15, 16, T47); ++ SET(b, c, d, a, 2, 23, T48); ++#undef SET ++ ++ /* Round 4. */ ++ /* Let [abcd k s t] denote the operation ++ a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ ++#define I(x, y, z) ((y) ^ ((x) | ~(z))) ++#define SET(a, b, c, d, k, s, Ti)\ ++ t = a + I(b,c,d) + X[k] + Ti;\ ++ a = ROTATE_LEFT(t, s) + b ++ /* Do the following 16 operations. */ ++ SET(a, b, c, d, 0, 6, T49); ++ SET(d, a, b, c, 7, 10, T50); ++ SET(c, d, a, b, 14, 15, T51); ++ SET(b, c, d, a, 5, 21, T52); ++ SET(a, b, c, d, 12, 6, T53); ++ SET(d, a, b, c, 3, 10, T54); ++ SET(c, d, a, b, 10, 15, T55); ++ SET(b, c, d, a, 1, 21, T56); ++ SET(a, b, c, d, 8, 6, T57); ++ SET(d, a, b, c, 15, 10, T58); ++ SET(c, d, a, b, 6, 15, T59); ++ SET(b, c, d, a, 13, 21, T60); ++ SET(a, b, c, d, 4, 6, T61); ++ SET(d, a, b, c, 11, 10, T62); ++ SET(c, d, a, b, 2, 15, T63); ++ SET(b, c, d, a, 9, 21, T64); ++#undef SET ++ ++ /* Then perform the following additions. (That is increment each ++ of the four registers by the value it had before this block ++ was started.) */ ++ pms->abcd[0] += a; ++ pms->abcd[1] += b; ++ pms->abcd[2] += c; ++ pms->abcd[3] += d; ++} ++ ++void ++md5_init(md5_state_t *pms) ++{ ++ pms->count[0] = pms->count[1] = 0; ++ pms->abcd[0] = 0x67452301; ++ pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; ++ pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; ++ pms->abcd[3] = 0x10325476; ++} ++ ++void ++md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) ++{ ++ const md5_byte_t *p = data; ++ int left = nbytes; ++ int offset = (pms->count[0] >> 3) & 63; ++ md5_word_t nbits = (md5_word_t)(nbytes << 3); ++ ++ if (nbytes <= 0) ++ return; ++ ++ /* Update the message length. */ ++ pms->count[1] += nbytes >> 29; ++ pms->count[0] += nbits; ++ if (pms->count[0] < nbits) ++ pms->count[1]++; ++ ++ /* Process an initial partial block. */ ++ if (offset) { ++ int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); ++ ++ memcpy(pms->buf + offset, p, copy); ++ if (offset + copy < 64) ++ return; ++ p += copy; ++ left -= copy; ++ md5_process(pms, pms->buf); ++ } ++ ++ /* Process full blocks. */ ++ for (; left >= 64; p += 64, left -= 64) ++ md5_process(pms, p); ++ ++ /* Process a final partial block. */ ++ if (left) ++ memcpy(pms->buf, p, left); ++} ++ ++void ++md5_finish(md5_state_t *pms, md5_byte_t digest[16]) ++{ ++ static const md5_byte_t pad[64] = { ++ 0x80, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ++ }; ++ md5_byte_t data[8]; ++ int i; ++ ++ /* Save the length before padding. */ ++ for (i = 0; i < 8; ++i) ++ data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); ++ /* Pad to 56 bytes mod 64. */ ++ md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); ++ /* Append the length. */ ++ md5_append(pms, data, 8); ++ for (i = 0; i < 16; ++i) ++ digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); ++} +diff -rupbN melonDS.orig/src/rcheevos/src/rhash/md5.h melonDS.ra/src/rcheevos/src/rhash/md5.h +--- melonDS.orig/src/rcheevos/src/rhash/md5.h 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rhash/md5.h 2026-03-06 21:37:07.050799942 +0000 +@@ -0,0 +1,91 @@ ++/* ++ Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. ++ ++ This software is provided 'as-is', without any express or implied ++ warranty. In no event will the authors be held liable for any damages ++ arising from the use of 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 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 notice may not be removed or altered from any source distribution. ++ ++ L. Peter Deutsch ++ ghost@aladdin.com ++ ++ */ ++/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */ ++/* ++ Independent implementation of MD5 (RFC 1321). ++ ++ This code implements the MD5 Algorithm defined in RFC 1321, whose ++ text is available at ++ http://www.ietf.org/rfc/rfc1321.txt ++ The code is derived from the text of the RFC, including the test suite ++ (section A.5) but excluding the rest of Appendix A. It does not include ++ any code or documentation that is identified in the RFC as being ++ copyrighted. ++ ++ The original and principal author of md5.h is L. Peter Deutsch ++ . Other authors are noted in the change history ++ that follows (in reverse chronological order): ++ ++ 2002-04-13 lpd Removed support for non-ANSI compilers; removed ++ references to Ghostscript; clarified derivation from RFC 1321; ++ now handles byte order either statically or dynamically. ++ 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. ++ 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); ++ added conditionalization for C++ compilation from Martin ++ Purschke . ++ 1999-05-03 lpd Original version. ++ */ ++ ++#ifndef md5_INCLUDED ++# define md5_INCLUDED ++ ++/* ++ * This package supports both compile-time and run-time determination of CPU ++ * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be ++ * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is ++ * defined as non-zero, the code will be compiled to run only on big-endian ++ * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to ++ * run on either big- or little-endian CPUs, but will run slightly less ++ * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. ++ */ ++ ++typedef unsigned char md5_byte_t; /* 8-bit byte */ ++typedef unsigned int md5_word_t; /* 32-bit word */ ++ ++/* Define the state of the MD5 Algorithm. */ ++typedef struct md5_state_s { ++ md5_word_t count[2]; /* message length in bits, lsw first */ ++ md5_word_t abcd[4]; /* digest buffer */ ++ md5_byte_t buf[64]; /* accumulate block */ ++} md5_state_t; ++ ++#ifdef __cplusplus ++extern "C" ++{ ++#endif ++ ++/* Initialize the algorithm. */ ++void md5_init(md5_state_t *pms); ++ ++/* Append a string to the message. */ ++void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); ++ ++/* Finish the message and return the digest. */ ++void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); ++ ++#ifdef __cplusplus ++} /* end extern "C" */ ++#endif ++ ++#endif /* md5_INCLUDED */ +diff -rupbN melonDS.orig/src/rcheevos/src/rhash/rc_hash_internal.h melonDS.ra/src/rcheevos/src/rhash/rc_hash_internal.h +--- melonDS.orig/src/rcheevos/src/rhash/rc_hash_internal.h 1970-01-01 00:00:00.000000000 +0000 ++++ melonDS.ra/src/rcheevos/src/rhash/rc_hash_internal.h 2026-03-06 21:37:07.050799942 +0000 +@@ -0,0 +1,116 @@ ++#ifndef RC_HASH_INTERNAL_H ++#define RC_HASH_INTERNAL_H ++ ++#include "rc_hash.h" ++#include "md5.h" ++ ++RC_BEGIN_C_DECLS ++ ++/* hash.c */ ++ ++void* rc_file_open(const rc_hash_iterator_t* iterator, const char* path); ++void rc_file_seek(const rc_hash_iterator_t* iterator, void* file_handle, int64_t offset, int origin); ++int64_t rc_file_tell(const rc_hash_iterator_t* iterator, void* file_handle); ++size_t rc_file_read(const rc_hash_iterator_t* iterator, void* file_handle, void* buffer, int requested_bytes); ++void rc_file_close(const rc_hash_iterator_t* iterator, void* file_handle); ++int64_t rc_file_size(const rc_hash_iterator_t* iterator, const char* path); ++ ++ ++void rc_hash_iterator_verbose(const rc_hash_iterator_t* iterator, const char* message); ++void rc_hash_iterator_verbose_formatted(const rc_hash_iterator_t* iterator, const char* format, ...); ++int rc_hash_iterator_error(const rc_hash_iterator_t* iterator, const char* message); ++int rc_hash_iterator_error_formatted(const rc_hash_iterator_t* iterator, const char* format, ...); ++ ++ ++/* arbitrary limit to prevent allocating and hashing large files */ ++#define MAX_BUFFER_SIZE 64 * 1024 * 1024 ++ ++void rc_hash_merge_callbacks(rc_hash_iterator_t* iterator, const rc_hash_callbacks_t* callbacks); ++int rc_hash_finalize(const rc_hash_iterator_t* iterator, md5_state_t* md5, char hash[33]); ++ ++int rc_hash_buffer(char hash[33], const uint8_t* buffer, size_t buffer_size, const rc_hash_iterator_t* iterator); ++void rc_hash_byteswap16(uint8_t* buffer, const uint8_t* stop); ++void rc_hash_byteswap32(uint8_t* buffer, const uint8_t* stop); ++ ++ ++const char* rc_path_get_filename(const char* path); ++const char* rc_path_get_extension(const char* path); ++int rc_path_compare_extension(const char* path, const char* ext); ++ ++ ++typedef void (RC_CCONV* rc_hash_iterator_ext_handler_t)(rc_hash_iterator_t* iterator, int data); ++typedef struct rc_hash_iterator_ext_handler_entry_t { ++ char ext[8]; ++ rc_hash_iterator_ext_handler_t handler; ++ int data; ++} rc_hash_iterator_ext_handler_entry_t; ++ ++const rc_hash_iterator_ext_handler_entry_t* rc_hash_get_iterator_ext_handlers(size_t* num_handlers); ++ ++ ++typedef struct rc_hash_cdrom_track_t { ++ void* file_handle; /* the file handle for reading the track data */ ++ const rc_hash_filereader_t* file_reader; /* functions to perform raw file I/O */ ++ int64_t file_track_offset;/* the offset of the track data within the file */ ++ int sector_size; /* the size of each sector in the track data */ ++ int sector_header_size; /* the offset to the raw data within a sector block */ ++ int raw_data_size; /* the amount of raw data within a sector block */ ++ int track_first_sector; /* the first absolute sector associated to the track (includes pregap) */ ++ int track_pregap_sectors; /* the number of pregap sectors */ ++#ifndef NDEBUG ++ uint32_t track_id; /* the index of the track */ ++#endif ++} rc_hash_cdrom_track_t; ++ ++ ++int rc_hash_whole_file(char hash[33], const rc_hash_iterator_t* iterator); ++int rc_hash_buffered_file(char hash[33], uint32_t console_id, const rc_hash_iterator_t* iterator); ++ ++#ifndef RC_HASH_NO_ROM ++ /* hash_rom.c */ ++ int rc_hash_7800(char hash[33], const rc_hash_iterator_t* iterator); ++ int rc_hash_arcade(char hash[33], const rc_hash_iterator_t* iterator); ++ int rc_hash_arduboy(char hash[33], const rc_hash_iterator_t* iterator); ++ int rc_hash_lynx(char hash[33], const rc_hash_iterator_t* iterator); ++ int rc_hash_nes(char hash[33], const rc_hash_iterator_t* iterator); ++ int rc_hash_n64(char hash[33], const rc_hash_iterator_t* iterator); ++ int rc_hash_nintendo_ds(char hash[33], const rc_hash_iterator_t* iterator); ++ int rc_hash_pce(char hash[33], const rc_hash_iterator_t* iterator); ++ int rc_hash_scv(char hash[33], const rc_hash_iterator_t* iterator); ++ int rc_hash_snes(char hash[33], const rc_hash_iterator_t* iterator); ++#endif ++ ++#ifndef RC_HASH_NO_DISC ++ /* hash_disc.c */ ++ void rc_hash_reset_iterator_disc(rc_hash_iterator_t* iterator); ++ ++ int rc_hash_3do(char hash[33], const rc_hash_iterator_t* iterator); ++ int rc_hash_dreamcast(char hash[33], const rc_hash_iterator_t* iterator); ++ int rc_hash_gamecube(char hash[33], const rc_hash_iterator_t* iterator); ++ int rc_hash_jaguar_cd(char hash[33], const rc_hash_iterator_t* iterator); ++ int rc_hash_neogeo_cd(char hash[33], const rc_hash_iterator_t* iterator); ++ int rc_hash_pce_cd(char hash[33], const rc_hash_iterator_t* iterator); ++ int rc_hash_pcfx_cd(char hash[33], const rc_hash_iterator_t* iterator); ++ int rc_hash_psx(char hash[33], const rc_hash_iterator_t* iterator); ++ int rc_hash_ps2(char hash[33], const rc_hash_iterator_t* iterator); ++ int rc_hash_psp(char hash[33], const rc_hash_iterator_t* iterator); ++ int rc_hash_sega_cd(char hash[33], const rc_hash_iterator_t* iterator); ++ int rc_hash_wii(char hash[33], const rc_hash_iterator_t* iterator); ++#endif ++ ++#ifndef RC_HASH_NO_ENCRYPTED ++ /* hash_encrypted.c */ ++ void rc_hash_reset_iterator_encrypted(rc_hash_iterator_t* iterator); ++ ++ int rc_hash_nintendo_3ds(char hash[33], const rc_hash_iterator_t* iterator); ++#endif ++ ++#ifndef RC_HASH_NO_ZIP ++ /* hash_zip.c */ ++ int rc_hash_ms_dos(char hash[33], const rc_hash_iterator_t* iterator); ++ int rc_hash_arduboyfx(char hash[33], const rc_hash_iterator_t* iterator); ++#endif ++ ++RC_END_C_DECLS ++ ++#endif /* RC_HASH_INTERNAL_H */ diff --git a/projects/ArchR/packages/emulators/standalone/melonds-sa/patches/001-default-config.patch b/projects/ArchR/packages/emulators/standalone/melonds-sa/patches/001-default-config.patch new file mode 100644 index 0000000000..0ac79d4a6c --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/melonds-sa/patches/001-default-config.patch @@ -0,0 +1,44 @@ +diff --git a/src/frontend/qt_sdl/Config.cpp b/src/frontend/qt_sdl/Config.cpp +index f767fcc9..86981f1f 100644 +--- a/src/frontend/qt_sdl/Config.cpp ++++ b/src/frontend/qt_sdl/Config.cpp +@@ -39,10 +39,9 @@ namespace Config + using namespace melonDS; + + +-const char* kConfigFile = "melonDS.toml"; ++const char* kConfigFile = "/storage/.config/melonDS/melonDS.toml"; + +-const char* kLegacyConfigFile = "melonDS.ini"; +-const char* kLegacyUniqueConfigFile = "melonDS.%d.ini"; ++const char* kLegacyConfigFile = "/storage/.config/melonDS/melonDS.ini"; + + toml::value RootTable; + +@@ -682,16 +681,7 @@ template T Table::FindDefault(const std::string& path, T def, Defaul + bool LoadLegacyFile(int inst) + { + Platform::FileHandle* f; +- if (inst > 0) +- { +- char name[100] = {0}; +- snprintf(name, 99, kLegacyUniqueConfigFile, inst+1); +- f = Platform::OpenLocalFile(name, Platform::FileMode::ReadText); +- } +- else +- { +- f = Platform::OpenLocalFile(kLegacyConfigFile, Platform::FileMode::ReadText); +- } ++ f = Platform::OpenLocalFile(kLegacyConfigFile, Platform::FileMode::ReadText); + + if (!f) return true; + +@@ -717,8 +707,6 @@ bool LoadLegacyFile(int inst) + { + if (!strncmp(entry->Name, entryname, 32)) + { +- if (!(entry->InstanceUnique ^ (inst == -1))) +- break; + + std::string path = entry->TOMLPath; + toml::value* table = root; diff --git a/projects/ArchR/packages/emulators/standalone/melonds-sa/patches/002-enable-dual-screen-fullscreen.patch b/projects/ArchR/packages/emulators/standalone/melonds-sa/patches/002-enable-dual-screen-fullscreen.patch new file mode 100644 index 0000000000..7c46523df0 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/melonds-sa/patches/002-enable-dual-screen-fullscreen.patch @@ -0,0 +1,33 @@ +diff --git a/src/frontend/qt_sdl/Config.cpp b/src/frontend/qt_sdl/Config.cpp +index 156d539..67978c0 100644 +--- a/src/frontend/qt_sdl/Config.cpp ++++ b/src/frontend/qt_sdl/Config.cpp +@@ -208,6 +208,10 @@ LegacyEntry LegacyFile[] = + {"IntegerScaling", 1, "Window0.IntegerScaling", true}, + {"ScreenAspectTop",0, "Window0.ScreenAspectTop", true}, + {"ScreenAspectBot",0, "Window0.ScreenAspectBot", true}, ++ {"Screen1Layout", 0, "Window1.ScreenLayout", true}, ++ {"Screen1Enabled", 1, "Window1.Enabled", true}, ++ {"Screen1Sizing", 0, "Window1.ScreenSizing", true}, ++ + + {"ScreenFilter", 1, "Screen.Filter", false}, + {"ScreenUseGL", 1, "Screen.UseGL", false}, +diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp +index 6514266..cc1b892 100644 +--- a/src/frontend/qt_sdl/main.cpp ++++ b/src/frontend/qt_sdl/main.cpp +@@ -380,9 +380,12 @@ int main(int argc, char** argv) + if (memberSyntaxUsed) printf("Warning: use the a.zip|b.nds format at your own risk!\n"); + + win->preloadROMs(dsfile, gbafile, options->boot); +- + if (options->fullscreen) ++ QTimer::singleShot(500, [=]() { ++ emuInstances[0]->doOnAllWindows([](MainWindow* win){ + win->toggleFullscreen(); ++ }); ++ }); + } + + int ret = melon.exec(); diff --git a/projects/ArchR/packages/emulators/standalone/melonds-sa/patches/003-hotkey-savestates.patch b/projects/ArchR/packages/emulators/standalone/melonds-sa/patches/003-hotkey-savestates.patch new file mode 100644 index 0000000000..4bf7c16721 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/melonds-sa/patches/003-hotkey-savestates.patch @@ -0,0 +1,106 @@ +diff -rupbN melonDS.orig/src/frontend/qt_sdl/Config.cpp melonDS/src/frontend/qt_sdl/Config.cpp +--- melonDS.orig/src/frontend/qt_sdl/Config.cpp 2026-02-20 05:47:47.879009667 +0000 ++++ melonDS/src/frontend/qt_sdl/Config.cpp 2026-02-20 05:53:32.362245865 +0000 +@@ -186,6 +186,8 @@ LegacyEntry LegacyFile[] = + {"HKKey_GuitarGripRed", 0, "Keyboard.HK_GuitarGripRed", true}, + {"HKKey_GuitarGripYellow", 0, "Keyboard.HK_GuitarGripYellow", true}, + {"HKKey_GuitarGripBlue", 0, "Keyboard.HK_GuitarGripBlue", true}, ++ {"HKKey_SaveState", 0, "Keyboard.HK_SaveState", true}, ++ {"HKKey_LoadState", 0, "Keyboard.HK_LoadState", true}, + + {"HKJoy_Lid", 0, "Joystick.HK_Lid", true}, + {"HKJoy_Mic", 0, "Joystick.HK_Mic", true}, +@@ -209,6 +211,8 @@ LegacyEntry LegacyFile[] = + {"HKJoy_GuitarGripRed", 0, "Joystick.HK_GuitarGripRed", true}, + {"HKJoy_GuitarGripYellow", 0, "Joystick.HK_GuitarGripYellow", true}, + {"HKJoy_GuitarGripBlue", 0, "Joystick.HK_GuitarGripBlue", true}, ++ {"HKJoy_SaveState", 0, "Joystick.HK_SaveState", true}, ++ {"HKJoy_LoadState", 0, "Joystick.HK_LoadState", true}, + + {"JoystickID", 0, "JoystickID", true}, + +diff -rupbN melonDS.orig/src/frontend/qt_sdl/EmuInstance.h melonDS/src/frontend/qt_sdl/EmuInstance.h +--- melonDS.orig/src/frontend/qt_sdl/EmuInstance.h 2026-02-20 05:47:47.879009667 +0000 ++++ melonDS/src/frontend/qt_sdl/EmuInstance.h 2026-02-20 05:57:07.948569265 +0000 +@@ -63,6 +63,8 @@ enum + #ifdef RETROACHIEVEMENTS_ENABLED + HK_RAOverlayToggle, + #endif ++ HK_SaveState, ++ HK_LoadState, + HK_MAX + }; + +diff -rupbN melonDS.orig/src/frontend/qt_sdl/EmuInstanceInput.cpp melonDS/src/frontend/qt_sdl/EmuInstanceInput.cpp +--- melonDS.orig/src/frontend/qt_sdl/EmuInstanceInput.cpp 2026-02-20 05:47:47.879009667 +0000 ++++ melonDS/src/frontend/qt_sdl/EmuInstanceInput.cpp 2026-02-20 05:53:32.362245865 +0000 +@@ -70,7 +70,9 @@ const char* EmuInstance::hotkeyNames[HK_ + "HK_GuitarGripGreen", + "HK_GuitarGripRed", + "HK_GuitarGripYellow", +- "HK_GuitarGripBlue" ++ "HK_GuitarGripBlue", ++ "HK_SaveState", ++ "HK_LoadState" + }; + + std::shared_ptr EmuInstance::joyMutexGlobal = nullptr; +diff -rupbN melonDS.orig/src/frontend/qt_sdl/EmuThread.cpp melonDS/src/frontend/qt_sdl/EmuThread.cpp +--- melonDS.orig/src/frontend/qt_sdl/EmuThread.cpp 2026-02-20 05:47:47.879009667 +0000 ++++ melonDS/src/frontend/qt_sdl/EmuThread.cpp 2026-02-20 05:55:13.083310458 +0000 +@@ -84,6 +84,8 @@ void EmuThread::attachWindow(MainWindow* + connect(this, SIGNAL(RAOverlayToggle()), window, SLOT(onRAOverlayToggled())); + #endif + connect(this, SIGNAL(screenEmphasisToggle()), window, SLOT(onScreenEmphasisToggled())); ++ connect(this, SIGNAL(SaveState()), window->actSaveState[1], SLOT(trigger())); ++ connect(this, SIGNAL(LoadState()), window->actLoadState[1], SLOT(trigger())); + + if (window->winHasMenu()) + { +@@ -180,6 +182,8 @@ void EmuThread::run() + #endif + if (emuInstance->hotkeyPressed(HK_SwapScreens)) emit swapScreensToggle(); + if (emuInstance->hotkeyPressed(HK_SwapScreenEmphasis)) emit screenEmphasisToggle(); ++ if (emuInstance->hotkeyPressed(HK_SaveState)) emit SaveState(); ++ if (emuInstance->hotkeyPressed(HK_LoadState)) emit LoadState(); + + if (emuStatus == emuStatus_Running || emuStatus == emuStatus_FrameStep) + { +diff -rupbN melonDS.orig/src/frontend/qt_sdl/EmuThread.h melonDS/src/frontend/qt_sdl/EmuThread.h +--- melonDS.orig/src/frontend/qt_sdl/EmuThread.h 2026-02-20 05:47:47.879009667 +0000 ++++ melonDS/src/frontend/qt_sdl/EmuThread.h 2026-02-20 05:53:32.362245865 +0000 +@@ -161,6 +161,9 @@ signals: + void swapScreensToggle(); + void screenEmphasisToggle(); + ++ void SaveState(); ++ void LoadState(); ++ + void syncVolumeLevel(); + + private: +diff -rupbN melonDS.orig/src/frontend/qt_sdl/InputConfig/InputConfigDialog.h melonDS/src/frontend/qt_sdl/InputConfig/InputConfigDialog.h +--- melonDS.orig/src/frontend/qt_sdl/InputConfig/InputConfigDialog.h 2026-02-20 05:47:47.879009667 +0000 ++++ melonDS/src/frontend/qt_sdl/InputConfig/InputConfigDialog.h 2026-02-20 05:56:25.112094849 +0000 +@@ -71,7 +71,9 @@ static constexpr std::initializer_list hk_general_labels = +@@ -95,7 +97,9 @@ static constexpr std::initializer_list "${LOG_FILE}" + +log() { + printf '%s - %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*" >> "${LOG_FILE}" +} + +# Extract username, password, token, if enabled, and hardcore mode from system.cfg +username=$(get_setting "global.retroachievements.username") +password=$(get_setting "global.retroachievements.password") +token=$(get_setting "global.retroachievements.token") +enabled=$(get_setting "global.retroachievements") +hardcore=$(get_setting "global.retroachievements.hardcore") +encore=$(get_setting "global.retroachievements.encore") +unofficial=$(get_setting "global.retroachievements.testunofficial") + +# Check if RetroAchievements are enabled in Emulation Station +if [ "${enabled}" = 1 ]; then + enabled="1" +else + log "RetroAchievements are not enabled, please turn them on in Emulation Station." + enabled="0" +fi + +# Check if username is present in system.cfg +if [ -z "${username}" ]; then + log "RetroAchievements username is empty, please log in with your RetroAchievements credentials in Emulation Station." + enabled="0" + username="null" +fi + +# Check if password is present in system.cfg +if [ -z "${password}" ]; then + log "RetroAchievements password is empty, please log in with your RetroAchievements credentials in Emulation Station." + enabled="0" + password="null" +fi + +# Check if api token is present in system.cfg +if [ -z "${token}" ]; then + log "RetroAchievements token is empty, please log in with your RetroAchievements credentials in Emulation Station." + enabled="0" + token="null" +fi + +# Set hardcore mode +if [ "${hardcore}" = 1 ]; then + hardcore="1" +else + hardcore="0" +fi + +# Set encore mode +if [ "${encore}" = 1 ]; then + encore="1" +else + encore="0" +fi + +# Set unofficial mode +if [ "${unofficial}" = 1 ]; then + unofficial="1" +else + unofficial="0" +fi + +# Clean up any special characters +escape_sed() { + printf '%s\n' "$1" | sed 's/[\/&]/\\&/g' +} + +username_esc=$(escape_sed "${username}") +password_esc=$(escape_sed "${password}") +token_esc=$(escape_sed "${token}") + +# Update emulator config with RetroAchievements settings +set_key() { + key="$1" + value="$2" + + if grep -q "^[[:space:]]*${key}[[:space:]]*=" "${MELONDS_CFG}"; then + sed -i "s|^[[:space:]]*${key}[[:space:]]*=.*|${key}=${value}|g" "${MELONDS_CFG}" + else + printf '%s=%s\n' "${key}" "${value}" >> "${MELONDS_CFG}" + fi +} + +set_key RA_Enabled "${enabled}" +set_key RA_Username "${username_esc}" +set_key RA_Password "${password_esc}" +set_key RA_Token "${token_esc}" +set_key RA_HardcoreMode "${hardcore}" +set_key RA_EncoreMode "${encore}" +set_key RA_Unofficial "${unofficial}" diff --git a/projects/ArchR/packages/emulators/standalone/melonds-sa/scripts/start_melonds.sh b/projects/ArchR/packages/emulators/standalone/melonds-sa/scripts/start_melonds.sh new file mode 100644 index 0000000000..1c95b1f248 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/melonds-sa/scripts/start_melonds.sh @@ -0,0 +1,209 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile + +set_kill set "-9 melonDS" + +#load gptokeyb support files +control-gen_init.sh +source /storage/.config/gptokeyb/control.ini +get_controls + +CONF_DIR="/storage/.config/melonDS" +MELONDS_INI="melonDS.ini" +SWAY_CONFIG="/storage/.config/sway/config" + +if [ ! -d "${CONF_DIR}" ]; then + cp -r "/usr/config/melonDS" "/storage/.config/" +fi + +if [ ! -d "/storage/roms/savestates/nds" ]; then + mkdir -p "/storage/roms/savestates/nds" +fi + +#Make sure melonDS gptk config exists +if [ ! -f "${CONF_DIR}/melonDS.gptk" ]; then + cp -r "/usr/config/melonDS/melonDS.gptk" "${CONF_DIR}/melonDS.gptk" +fi + +#Make sure melonDS config exists +if [ ! -f "${CONF_DIR}/${MELONDS_INI}" ]; then + cp -r "/usr/config/melonDS/melonDS.ini" "${CONF_DIR}/${MELONDS_INI}" +fi + +#Emulation Station Features +GAME=$(echo "${1}" | sed "s#^/.*/##") +PLATFORM=$(echo "${2}"| sed "s#^/.*/##") +CONTYPE=$(get_setting console_type "${PLATFORM}" "${GAME}") +DBOOT=$(get_setting direct_boot "${PLATFORM}" "${GAME}") +GRENDERER=$(get_setting graphics_backend "${PLATFORM}" "${GAME}") +IRES=$(get_setting internal_resolution "${PLATFORM}" "${GAME}") +SORIENTATION=$(get_setting screen_orientation "${PLATFORM}" "${GAME}") +SLAYOUT=$(get_setting screen_layout "${PLATFORM}" "${GAME}") +SWAP=$(get_setting screen_swap "${PLATFORM}" "${GAME}") +SROTATION=$(get_setting screen_rotation "${PLATFORM}" "${GAME}") +VSYNC=$(get_setting vsync "${PLATFORM}" "${GAME}") + +#Set the cores to use +CORES=$(get_setting "cores" "${PLATFORM}" "${GAME}") +unset EMUPERF +[ "${CORES}" = "little" ] && EMUPERF="${SLOW_CORES}" +[ "${CORES}" = "big" ] && EMUPERF="${FAST_CORES}" + +#Console Type +if [ "$PLATFORM" = "ndsiware" ]; then + sed -i '/^ConsoleType=/c\ConsoleType=1' /storage/.config/melonDS/melonDS.ini +else + if [ "$CONTYPE" = "1" ]; then + sed -i '/^ConsoleType=/c\ConsoleType=1' /storage/.config/melonDS/melonDS.ini + else + sed -i '/^ConsoleType=/c\ConsoleType=0' /storage/.config/melonDS/melonDS.ini + fi +fi + +#Direct Boot +if [ "$PLATFORM" = "ndsiware" ]; then + sed -i '/^DirectBoot=/c\DirectBoot=0' /storage/.config/melonDS/melonDS.ini +else + if [ "$DBOOT" = "0" ]; then + sed -i '/^DirectBoot=/c\DirectBoot=0' /storage/.config/melonDS/melonDS.ini + sed -i '/^ExternalBIOSEnable=/c\ExternalBIOSEnable=1' /storage/.config/melonDS/melonDS.ini + else + sed -i '/^DirectBoot=/c\DirectBoot=1' /storage/.config/melonDS/melonDS.ini + sed -i '/^ExternalBIOSEnable=/c\ExternalBIOSEnable=0' /storage/.config/melonDS/melonDS.ini + fi +fi + +#Graphics Backend +case "$GRENDERER" in + "1"|"2") + sed -i "/^ScreenUseGL=/c\ScreenUseGL=1" "${CONF_DIR}/${MELONDS_INI}" + sed -i "/^3DRenderer=/c\3DRenderer=$GRENDERER" "${CONF_DIR}/${MELONDS_INI}" + ;; + *) + sed -i '/^ScreenUseGL=/c\ScreenUseGL=0' "${CONF_DIR}/${MELONDS_INI}" + sed -i '/^3DRenderer=/c\3DRenderer=0' "${CONF_DIR}/${MELONDS_INI}" + ;; +esac + +#Internal Resolution +if [ "${IRES:-0}" -gt 0 ] 2>/dev/null; then + sed -i "/^GL_ScaleFactor=/c\GL_ScaleFactor=$IRES" "${CONF_DIR}/${MELONDS_INI}" +else + sed -i '/^GL_ScaleFactor=/c\GL_ScaleFactor=1' "${CONF_DIR}/${MELONDS_INI}" +fi + +#Screen Orientation +if [ "${SORIENTATION:-0}" -gt 0 ] 2>/dev/null; then + sed -i "/^ScreenLayout=/c\ScreenLayout=$SORIENTATION" "${CONF_DIR}/${MELONDS_INI}" +else + sed -i '/^ScreenLayout=/c\ScreenLayout=2' "${CONF_DIR}/${MELONDS_INI}" +fi + +#Screen Layout +# Screen Layout +sed -i '/^Screen1Enabled=/c\Screen1Enabled=0' "${CONF_DIR}/${MELONDS_INI}" + +enable_second_screen() { + sed -i '/^ScreenSizing=/c\ScreenSizing=4' "${CONF_DIR}/${MELONDS_INI}" + sed -i '/^Screen1Enabled=/d$ a Screen1Enabled=1' "${CONF_DIR}/${MELONDS_INI}" + sed -i '/^Screen1Layout=/d$ a Screen1Layout=2' "${CONF_DIR}/${MELONDS_INI}" +} + +if [ "$SLAYOUT" = "6" ]; then + enable_second_screen +elif [ -n "$SLAYOUT" ] && [ "$SLAYOUT" != "0" ]; then + sed -i "/^ScreenSizing=/c\ScreenSizing=$SLAYOUT" "${CONF_DIR}/${MELONDS_INI}" +elif [ "${DEVICE_HAS_DUAL_SCREEN}" = "true" ]; then + enable_second_screen +else + sed -i '/^ScreenSizing=/c\ScreenSizing=0' "${CONF_DIR}/${MELONDS_INI}" +fi + +# Screen Swap +if [[ "${DEVICE_HAS_DUAL_SCREEN}" = "true" && ( -z "$SLAYOUT" || "$SLAYOUT" = "6" ) ]]; then + if [ "$SWAP" = "1" ]; then + sed -i '/^ScreenSizing=/c\ScreenSizing=5' "${CONF_DIR}/${MELONDS_INI}" + sed -i '/^Screen1Sizing=/d$ a Screen1Sizing=4' "${CONF_DIR}/${MELONDS_INI}" + else + sed -i '/^ScreenSizing=/c\ScreenSizing=4' "${CONF_DIR}/${MELONDS_INI}" + sed -i '/^Screen1Sizing=/d$ a Screen1Sizing=5' "${CONF_DIR}/${MELONDS_INI}" + fi +else + sed -i "/^ScreenSwap=/c\ScreenSwap=${SWAP:-0}" "${CONF_DIR}/${MELONDS_INI}" +fi + +#Screen Rotation +if [ "${SROTATION:-0}" -gt 0 ] 2>/dev/null; then + sed -i "/^ScreenRotation=/c\ScreenRotation=$SROTATION" "${CONF_DIR}/${MELONDS_INI}" +else + sed -i '/^ScreenRotation=/c\ScreenRotation=0' "${CONF_DIR}/${MELONDS_INI}" +fi + +#Vsync +if [ "$VSYNC" = "1" ]; then + sed -i '/^ScreenVSync=/c\ScreenVSync=1' "${CONF_DIR}/${MELONDS_INI}" +else + sed -i '/^ScreenVSync=/c\ScreenVSync=1' "${CONF_DIR}/${MELONDS_INI}" +fi + +# Extract archive to /tmp/melonds +TEMP="/tmp/melonds" +rm -rf "${TEMP}" +mkdir -p "${TEMP}" +if [[ "${1}" == *.zip ]]; then + unzip -o "${1}" -d "${TEMP}" + ROM=$(find "${TEMP}" -maxdepth 1 -type f -name "*.nds" | head -n 1) +elif [[ "${1}" == *.7z ]]; then + 7z x -y -o"${TEMP}" "${1}" + ROM=$(find "${TEMP}" -maxdepth 1 -type f -name "*.nds" | head -n 1) +else + ROM="${1}" +fi + +# QT platform - use wayland on Wayland compositors, xcb otherwise +if [ -n "${WAYLAND_DISPLAY}" ]; then + export QT_QPA_PLATFORM=wayland +else + export QT_QPA_PLATFORM=xcb +fi + +# Qt requires UTF-8 locale +export LC_ALL=en_US.UTF-8 2>/dev/null || export LC_ALL=C.UTF-8 + +# Performance: disable Qt animations, reduce rendering overhead +export QT_QPA_NO_SIGNAL_SPY=1 +export QSG_RENDER_LOOP=basic +export QT_ENABLE_HIGHDPI_SCALING=0 + +@PANFROST@ +@HOTKEY@ +@LIBMALI@ + +#Generate a new MelonDS.toml each run (temporary hack) +rm -rf "${CONF_DIR}/melonDS.toml" + +# Force JIT and software renderer for max performance on weak SoCs +sed -i '/^JIT_Enable=/c\JIT_Enable=1' "${CONF_DIR}/${MELONDS_INI}" +sed -i '/^3DRenderer=/c\3DRenderer=0' "${CONF_DIR}/${MELONDS_INI}" +sed -i '/^Threaded3D=/c\Threaded3D=1' "${CONF_DIR}/${MELONDS_INI}" +sed -i '/^ScreenUseGL=/c\ScreenUseGL=0' "${CONF_DIR}/${MELONDS_INI}" +sed -i '/^ShowOSD=/c\ShowOSD=0' "${CONF_DIR}/${MELONDS_INI}" +sed -i '/^AudioInterp=/c\AudioInterp=0' "${CONF_DIR}/${MELONDS_INI}" +sed -i '/^AudioBitrate=/c\AudioBitrate=0' "${CONF_DIR}/${MELONDS_INI}" + +#Retroachievements +/usr/bin/cheevos_melonds.sh + +#Run MelonDS emulator - set CPU to performance for max speed +if [ -w "/sys/devices/system/cpu/cpufreq/policy0/scaling_governor" ]; then + echo performance > /sys/devices/system/cpu/cpufreq/policy0/scaling_governor 2>/dev/null +fi + +$GPTOKEYB "melonDS" -c "${CONF_DIR}/melonDS.gptk" & +${EMUPERF} /usr/bin/melonDS -f "${ROM}" +_gptokeyb_pid="$(pidof gptokeyb 2>/dev/null)" +[ -n "${_gptokeyb_pid}" ] && kill -9 ${_gptokeyb_pid} diff --git a/projects/ArchR/packages/emulators/standalone/minivmacsa/package.mk b/projects/ArchR/packages/emulators/standalone/minivmacsa/package.mk new file mode 100644 index 0000000000..d0100d2751 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/minivmacsa/package.mk @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="minivmacsa" +PKG_VERSION="37.03" +PKG_LICENSE="GPLv2" +PKG_SITE="https://www.gryphel.com/c/minivmac/" +PKG_URL="https://www.gryphel.com/d/minivmac/minivmac-${PKG_VERSION}/minivmac-${PKG_VERSION}.src.tgz" +PKG_DEPENDS_TARGET="toolchain libX11" +PKG_LONGDESC="Virtual Macintosh Plus" +PKG_TOOLCHAIN="make" + +pre_make_target() { + cd ${PKG_BUILD} + ${TOOLCHAIN}/bin/host-gcc setup/tool.c -o setup_t + ./setup_t -t lx64 -fullscreen 1 > setup.sh + . setup.sh + sed -i "s|gcc|${TARGET_PREFIX}gcc|" ${PKG_BUILD}/Makefile +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp ${PKG_BUILD}/minivmac ${INSTALL}/usr/bin + chmod 0755 ${INSTALL}/usr/bin/* +} diff --git a/projects/ArchR/packages/emulators/standalone/minivmacsa/sources/start_minivmac.sh b/projects/ArchR/packages/emulators/standalone/minivmacsa/sources/start_minivmac.sh new file mode 100644 index 0000000000..7279cb1977 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/minivmacsa/sources/start_minivmac.sh @@ -0,0 +1,9 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile + +ARG=${1//[\\]/} +echo "[${ARG}]" +minivmac diff --git a/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-audio-sdl/package.mk b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-audio-sdl/package.mk new file mode 100644 index 0000000000..cbe61652b0 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-audio-sdl/package.mk @@ -0,0 +1,77 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2023 Nicholas Ricciuti (rishooty@gmail.com) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="mupen64plus-sa-audio-sdl" +PKG_VERSION="cec70e42b4535ce5bd1be24e7d816c54b3e75673" +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 libpng SDL2 SDL2_net zlib freetype nasm:host mupen64plus-sa-core" +PKG_LONGDESC="mupen64plus-audio-sdl" +PKG_LONGDESC="Mupen64Plus Standalone Audio SDL" +PKG_TOOLCHAIN="manual" + +case ${DEVICE} in + RK3588|S922X|RK3399|RK3566*|SM8250|SM8550|SM8650) + PKG_DEPENDS_TARGET+=" mupen64plus-sa-simplecore" + ;; +esac + +case ${OPENGL} in + no) + PKG_DEPENDS_TARGET+=" ${OPENGLES}" + export USE_GLES=1 + ;; + *) + PKG_DEPENDS_TARGET+=" ${OPENGL} glu libglvnd" + export USE_GLES=0 + ;; +esac + +make_target() { + + export HOST_CPU=${TARGET_ARCH} \ + NEW_DYNAREC=1 \ + VFP_HARD=1 \ + V=1 \ + VC=0 \ + OSD=0 + + export BINUTILS="$(get_build_dir binutils)/.${TARGET_NAME}" + export SDL_CFLAGS="-I${SYSROOT_PREFIX}/usr/include/SDL2 -pthread -D_REENTRANT" + export SDL_LDLIBS="-lSDL2_net -lSDL2" + export CROSS_COMPILE="${TARGET_PREFIX}" + + export APIDIR=$(get_build_dir mupen64plus-sa-core)/src/api + + sed -i 's/\-O[23]/-Ofast/' ${PKG_BUILD}/projects/unix/Makefile + + make -C projects/unix clean + make -C projects/unix all ${PKG_MAKE_OPTS_TARGET} + cp ${PKG_BUILD}/projects/unix/mupen64plus-audio-sdl.so ${PKG_BUILD}/projects/unix/mupen64plus-audio-sdl-base.so + + case ${DEVICE} in + RK3588|S922X|RK3399|RK3566*) + export APIDIR=$(get_build_dir mupen64plus-sa-simplecore)/src/api + make -C projects/unix all ${PKG_MAKE_OPTS_TARGET} + cp ${PKG_BUILD}/projects/unix/mupen64plus-audio-sdl.so ${PKG_BUILD}/projects/unix/mupen64plus-audio-sdl-simple.so + ;; + esac +} + +makeinstall_target() { + UPREFIX=${INSTALL}/usr/local + ULIBDIR=${UPREFIX}/lib + UPLUGINDIR=${ULIBDIR}/mupen64plus + mkdir -p ${UPLUGINDIR} + cp ${PKG_BUILD}/projects/unix/mupen64plus-audio-sdl-base.so ${UPLUGINDIR}/mupen64plus-audio-sdl.so + chmod 0644 ${UPLUGINDIR}/mupen64plus-audio-sdl.so + if [ -e "${PKG_BUILD}/projects/unix/mupen64plus-audio-sdl-simple.so" ] + then + cp ${PKG_BUILD}/projects/unix/mupen64plus-audio-sdl-simple.so ${UPLUGINDIR} + chmod 0644 ${UPLUGINDIR}/mupen64plus-audio-sdl-simple.so + fi +} + diff --git a/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/H700/mupen64plus.cfg b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/H700/mupen64plus.cfg new file mode 100644 index 0000000000..26abb8e457 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/H700/mupen64plus.cfg @@ -0,0 +1,667 @@ +# 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/screenshots" +# 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/.config/game/configs/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 = "J0B8/B9" +# Joystick event string for switching between fullscreen/windowed modes +Joy Mapping Fullscreen = "" +# Joystick event string for saving the emulator state +Joy Mapping Save State = "J0B8/B5" +# Joystick event string for loading the emulator state +Joy Mapping Load State = "J0B8/B4" +# Joystick event string for advancing the save state slot +Joy Mapping Increment Slot = "" +# Joystick event string for resetting the emulator +Joy Mapping Reset = "J0B8/B0" +# 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 = "J0B8/B3" +# 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 = "J0B8/B7" +# 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 = "J0B8/B2" +# 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 = "H700 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(16) +DPad L = button(15) +DPad D = button(14) +DPad U = button(13) +Start = button(9) +Z Trig = button(5) +B Button = button(3) +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 = +# 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 = 427 +# Height of output window or fullscreen height +ScreenHeight = 320 +# Use fullscreen mode if True, or windowed mode if False +Fullscreen = True +# 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-GLideN64] + +###### Hardware Compatibility ###### +# Leave enabled unless a mobile gpu doesn't support it. +EnableFragmentDepthWrite = 0 +# Hardware per pixel lighting, supposedly good for GLES3.1 devices or higher. +EnableHWLighting = 0 + +###### Enhancements ####### +# Internal render resoluton rather than output. So 2 x 240p is 480p, etc. +UseNativeResolutionFactor = 1 +# Enable/Disable MultiSampling (0=off, 2,4,8,16=quality) +MultiSampling = 0 +# Enable/Disable Fast Approximate Anti-Aliasing FXAA +FXAA = 0 +# Max level of Anisotropic Filtering, 0 for off +anisotropy = 0 +# Bilinear filtering mode (0=N64 3point, 1=standard) +# @rishooty: best to use this at 1x native res, any higher turn it off. +bilinearMode = 1 + +###### Compatibility ###### +# Make texrect coordinates continuous to avoid black lines between them. (0=Off/default, 1=Auto, 2=Force) +CorrectTexrectCoords = 1 +# Copy auxiliary buffers to RDRAM (default: 0) +EnableCopyAuxiliaryToRDRAM = 1 +# Render 2D texrects in native resolution to fix misalignment between parts of 2D image. (0=Off/default, 1=Optimized, 2=Unoptimized)") +EnableNativeResTexrects = 1 + +###### Other ###### +# Enable threaded video backend at the cost of input lag +ThreadedVideo = 1 +# Screen aspect ratio (0=stretch, 1=force 4:3, 2=force 16:9, 3=adjust) +AspectRatio = 1 +# Display On-screen FPS +ShowFPS = False + +[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] + +# Hack to accomodate widescreen devices +ResolutionWidth = 480 +# 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/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/RK3326/mupen64plus.cfg b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/RK3326/mupen64plus.cfg new file mode 100644 index 0000000000..67652179aa --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/RK3326/mupen64plus.cfg @@ -0,0 +1,680 @@ +# 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 = 4096 +# 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 = "/tmp/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 = "J0B8/B11" +# 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 = True +# 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-GLideN64] + +###### Hardware Compatibility ###### +# Leave enabled unless a mobile gpu doesn't support it. +EnableFragmentDepthWrite = 0 +# Hardware per pixel lighting, supposedly good for GLES3.1 devices or higher. +EnableHWLighting = 0 + +###### Enhancements ####### +# Internal render resoluton rather than output. So 2 x 240p is 480p, etc. +UseNativeResolutionFactor = 1 +# Enable/Disable MultiSampling (0=off, 2,4,8,16=quality) +MultiSampling = 0 +# Enable/Disable Fast Approximate Anti-Aliasing FXAA +FXAA = 0 +# Max level of Anisotropic Filtering, 0 for off +anisotropy = 0 +# Bilinear filtering mode (0=N64 3point, 1=standard) +bilinearMode = 1 +# Hybrid texture filter (reduces texture aliasing, costs GPU) +EnableHybridFilter = 0 +# Inaccurate texture coords (faster but less precise) +EnableInaccurateTextureCoordinates = 1 + +###### Compatibility ###### +# Make texrect coordinates continuous to avoid black lines between them. (0=Off/default, 1=Auto, 2=Force) +CorrectTexrectCoords = 0 +# Copy auxiliary buffers to RDRAM (default: 0) +EnableCopyAuxiliaryToRDRAM = 0 +# Render 2D texrects in native resolution to fix misalignment between parts of 2D image. (0=Off/default, 1=Optimized, 2=Unoptimized)") +EnableNativeResTexrects = 1 +# Copy color buffer to RDRAM (0=off, 1=sync, 2=async) +EnableCopyColorToRDRAM = 0 +# Copy depth buffer to RDRAM (0=off, 1=from video, 2=software) +EnableCopyDepthToRDRAM = 0 +# Enable legacy blending (faster on low-end GPUs) +EnableLegacyBlending = 1 +# LOD emulation (costly, disable for performance) +EnableLOD = 0 +# Background rendering mode (0=onepiece, 1=stripped) +BackgroundsMode = 0 + +###### Other ###### +# Enable threaded video backend at the cost of input lag +ThreadedVideo = 1 +# Screen aspect ratio (0=stretch, 1=force 4:3, 2=force 16:9, 3=adjust) +AspectRatio = 1 +# Display On-screen FPS +ShowFPS = False + +[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] + +# Hack to accomodate widescreen devices +ResolutionWidth = 480 +# 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 = True +# 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/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/RK3326/mupen64plus.cfg.oga b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/RK3326/mupen64plus.cfg.oga new file mode 100644 index 0000000000..95e63ce889 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/RK3326/mupen64plus.cfg.oga @@ -0,0 +1,670 @@ +# 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 = "/tmp/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 = "J0B10/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 = "J0B10/B5" +# Joystick event string for loading the emulator state +Joy Mapping Load State = "J0B10/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 = "J0B10/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 = "J0B10/B12" +# 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 = "odroidgo2_joypad" +# 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 +plugged = True +mouse = False +AnalogDeadzone = 0,0 +AnalogPeak = 32768,32768 +DPad R = button(9) +DPad L = button(8) +DPad D = button(7) +DPad U = button(6) +Start = button(13) +Z Trig = button(4) +B Button = button(3) +A Button = button(0) +C Button R = button(11) +C Button L = button(1) +C Button D = button(12) +C Button U = button(2) +R Trig = button(5) +L Trig = +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 = 427 +# Height of output window or fullscreen height +ScreenHeight = 320 +# Use fullscreen mode if True, or windowed mode if False +Fullscreen = True +# 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-GLideN64] + +###### Hardware Compatibility ###### +# Leave enabled unless a mobile gpu doesn't support it. +EnableFragmentDepthWrite = 0 +# Hardware per pixel lighting, supposedly good for GLES3.1 devices or higher. +EnableHWLighting = 0 + +###### Enhancements ####### +# Internal render resoluton rather than output. So 2 x 240p is 480p, etc. +UseNativeResolutionFactor = 1 +# Enable/Disable MultiSampling (0=off, 2,4,8,16=quality) +MultiSampling = 0 +# Enable/Disable Fast Approximate Anti-Aliasing FXAA +FXAA = 0 +# Max level of Anisotropic Filtering, 0 for off +anisotropy = 0 +# Bilinear filtering mode (0=N64 3point, 1=standard) +# @rishooty: best to use this at 1x native res, any higher turn it off. +bilinearMode = 1 + +###### Compatibility ###### +# Make texrect coordinates continuous to avoid black lines between them. (0=Off/default, 1=Auto, 2=Force) +CorrectTexrectCoords = 1 +# Copy auxiliary buffers to RDRAM (default: 0) +EnableCopyAuxiliaryToRDRAM = 1 +# Render 2D texrects in native resolution to fix misalignment between parts of 2D image. (0=Off/default, 1=Optimized, 2=Unoptimized)") +EnableNativeResTexrects = 1 + +###### Other ###### +# Enable threaded video backend at the cost of input lag +ThreadedVideo = 1 +# Screen aspect ratio (0=stretch, 1=force 4:3, 2=force 16:9, 3=adjust) +AspectRatio = 1 +# Display On-screen FPS +ShowFPS = False + +[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] + +# Hack to accomodate widescreen devices +ResolutionWidth = 480 +# 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/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/RK3326/mupen64plus.cfg.ogabe b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/RK3326/mupen64plus.cfg.ogabe new file mode 100644 index 0000000000..9448465756 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/RK3326/mupen64plus.cfg.ogabe @@ -0,0 +1,670 @@ +# 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 = "/tmp/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/B15" +# 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/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 = "J0B12/B14" +# 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 = "odroidgo2_v11_joypad" +# 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 +plugged = True +mouse = False +AnalogDeadzone = 0,0 +AnalogPeak = 32768,32768 +DPad R = button(15) +DPad L = button(14) +DPad D = button(13) +DPad U = button(12) +Start = button(8) +Z Trig = button(4) +B Button = button(3) +A Button = button(0) +C Button R = button(9) +C Button L = button(11) +C Button D = button(1) +C Button U = button(2) +R Trig = button(5) +L Trig = button(6) +Mempak switch = +Rumblepak switch = +# Analog axis configuration mappings +X Axis = axis(1+,1-) +Y Axis = axis(0+,0-) + +[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 = 427 +# Height of output window or fullscreen height +ScreenHeight = 320 +# Use fullscreen mode if True, or windowed mode if False +Fullscreen = True +# 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-GLideN64] + +###### Hardware Compatibility ###### +# Leave enabled unless a mobile gpu doesn't support it. +EnableFragmentDepthWrite = 0 +# Hardware per pixel lighting, supposedly good for GLES3.1 devices or higher. +EnableHWLighting = 0 + +###### Enhancements ####### +# Internal render resoluton rather than output. So 2 x 240p is 480p, etc. +UseNativeResolutionFactor = 1 +# Enable/Disable MultiSampling (0=off, 2,4,8,16=quality) +MultiSampling = 0 +# Enable/Disable Fast Approximate Anti-Aliasing FXAA +FXAA = 0 +# Max level of Anisotropic Filtering, 0 for off +anisotropy = 0 +# Bilinear filtering mode (0=N64 3point, 1=standard) +# @rishooty: best to use this at 1x native res, any higher turn it off. +bilinearMode = 1 + +###### Compatibility ###### +# Make texrect coordinates continuous to avoid black lines between them. (0=Off/default, 1=Auto, 2=Force) +CorrectTexrectCoords = 1 +# Copy auxiliary buffers to RDRAM (default: 0) +EnableCopyAuxiliaryToRDRAM = 1 +# Render 2D texrects in native resolution to fix misalignment between parts of 2D image. (0=Off/default, 1=Optimized, 2=Unoptimized)") +EnableNativeResTexrects = 1 + +###### Other ###### +# Enable threaded video backend at the cost of input lag +ThreadedVideo = 1 +# Screen aspect ratio (0=stretch, 1=force 4:3, 2=force 16:9, 3=adjust) +AspectRatio = 1 +# Display On-screen FPS +ShowFPS = False + +[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] + +# Hack to accomodate widescreen devices +ResolutionWidth = 480 +# 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/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/RK3326/mupen64plus.cfg.ogs b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/RK3326/mupen64plus.cfg.ogs new file mode 100644 index 0000000000..6b767fcf3e --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/RK3326/mupen64plus.cfg.ogs @@ -0,0 +1,670 @@ +# 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 = "/tmp/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/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 = "J0B12/B14" +# 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 = "odroidgo3_joypad" +# 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 +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(4) +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 = button(5) +L Trig = button(6) +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 = 427 +# Height of output window or fullscreen height +ScreenHeight = 320 +# Use fullscreen mode if True, or windowed mode if False +Fullscreen = True +# 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-GLideN64] + +###### Hardware Compatibility ###### +# Leave enabled unless a mobile gpu doesn't support it. +EnableFragmentDepthWrite = 0 +# Hardware per pixel lighting, supposedly good for GLES3.1 devices or higher. +EnableHWLighting = 0 + +###### Enhancements ####### +# Internal render resoluton rather than output. So 2 x 240p is 480p, etc. +UseNativeResolutionFactor = 1 +# Enable/Disable MultiSampling (0=off, 2,4,8,16=quality) +MultiSampling = 0 +# Enable/Disable Fast Approximate Anti-Aliasing FXAA +FXAA = 0 +# Max level of Anisotropic Filtering, 0 for off +anisotropy = 0 +# Bilinear filtering mode (0=N64 3point, 1=standard) +# @rishooty: best to use this at 1x native res, any higher turn it off. +bilinearMode = 1 + +###### Compatibility ###### +# Make texrect coordinates continuous to avoid black lines between them. (0=Off/default, 1=Auto, 2=Force) +CorrectTexrectCoords = 1 +# Copy auxiliary buffers to RDRAM (default: 0) +EnableCopyAuxiliaryToRDRAM = 1 +# Render 2D texrects in native resolution to fix misalignment between parts of 2D image. (0=Off/default, 1=Optimized, 2=Unoptimized)") +EnableNativeResTexrects = 1 + +###### Other ###### +# Enable threaded video backend at the cost of input lag +ThreadedVideo = 1 +# Screen aspect ratio (0=stretch, 1=force 4:3, 2=force 16:9, 3=adjust) +AspectRatio = 1 +# Display On-screen FPS +ShowFPS = False + +[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] + +# Hack to accomodate widescreen devices +ResolutionWidth = 480 +# 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/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/RK3326/mupen64plus.cfg.r33s b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/RK3326/mupen64plus.cfg.r33s new file mode 100644 index 0000000000..13f53c3898 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/RK3326/mupen64plus.cfg.r33s @@ -0,0 +1,670 @@ +# 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 = "/tmp/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 = "J0B8/B9" +# Joystick event string for switching between fullscreen/windowed modes +Joy Mapping Fullscreen = "" +# Joystick event string for saving the emulator state +Joy Mapping Save State = "J0B8/B5" +# Joystick event string for loading the emulator state +Joy Mapping Load State = "J0B8/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 = "J0B8/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 = "J0B8/B7" +# 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 = "r33s_joypad" +# 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 +plugged = True +mouse = False +AnalogDeadzone = 0,0 +AnalogPeak = 32768,32768 +DPad R = +DPad L = +DPad D = +DPad U = +Start = button(9) +Z Trig = button(4) +B Button = button(3) +A Button = button(0) +C Button R = button(7) +C Button L = button(6) +C Button D = button(1) +C Button U = button(2) +R Trig = button(5) +L Trig = button(4) +Mempak switch = +Rumblepak switch = +# Analog axis configuration mappings +X Axis = button(12,13)axis(0-,0+) +Y Axis = butoon(10,11)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 = 427 +# Height of output window or fullscreen height +ScreenHeight = 320 +# Use fullscreen mode if True, or windowed mode if False +Fullscreen = True +# 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-GLideN64] + +###### Hardware Compatibility ###### +# Leave enabled unless a mobile gpu doesn't support it. +EnableFragmentDepthWrite = 0 +# Hardware per pixel lighting, supposedly good for GLES3.1 devices or higher. +EnableHWLighting = 0 + +###### Enhancements ####### +# Internal render resoluton rather than output. So 2 x 240p is 480p, etc. +UseNativeResolutionFactor = 1 +# Enable/Disable MultiSampling (0=off, 2,4,8,16=quality) +MultiSampling = 0 +# Enable/Disable Fast Approximate Anti-Aliasing FXAA +FXAA = 0 +# Max level of Anisotropic Filtering, 0 for off +anisotropy = 0 +# Bilinear filtering mode (0=N64 3point, 1=standard) +# @rishooty: best to use this at 1x native res, any higher turn it off. +bilinearMode = 1 + +###### Compatibility ###### +# Make texrect coordinates continuous to avoid black lines between them. (0=Off/default, 1=Auto, 2=Force) +CorrectTexrectCoords = 1 +# Copy auxiliary buffers to RDRAM (default: 0) +EnableCopyAuxiliaryToRDRAM = 1 +# Render 2D texrects in native resolution to fix misalignment between parts of 2D image. (0=Off/default, 1=Optimized, 2=Unoptimized)") +EnableNativeResTexrects = 1 + +###### Other ###### +# Enable threaded video backend at the cost of input lag +ThreadedVideo = 1 +# Screen aspect ratio (0=stretch, 1=force 4:3, 2=force 16:9, 3=adjust) +AspectRatio = 1 +# Display On-screen FPS +ShowFPS = False + +[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] + +# Hack to accomodate widescreen devices +ResolutionWidth = 480 +# 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/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/RK3326/mupen64plus.cfg.s1_f2 b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/RK3326/mupen64plus.cfg.s1_f2 new file mode 100644 index 0000000000..0737ebb4bb --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/RK3326/mupen64plus.cfg.s1_f2 @@ -0,0 +1,670 @@ +# 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 = "/tmp/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 = "J0B10/B9" +# Joystick event string for switching between fullscreen/windowed modes +Joy Mapping Fullscreen = "" +# Joystick event string for saving the emulator state +Joy Mapping Save State = "J0B10/B5" +# Joystick event string for loading the emulator state +Joy Mapping Load State = "J0B10/B4" +# Joystick event string for advancing the save state slot +Joy Mapping Increment Slot = "" +# Joystick event string for resetting the emulator +Joy Mapping Reset = "J0B10/B0" +# 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 = "J0B10/B3" +# Joystick event string for pausing the emulator +Joy Mapping Pause = "" +# 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 = 0 +# 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 = "retrogame_joypad_s1_f2" +# 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 +plugged = True +mouse = False +AnalogDeadzone = 0,0 +AnalogPeak = 32768,32768 +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(3) +A Button = button(0) +C Button R = button(1) +C Button L = +C Button D = +C Button U = button(2) +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 = 427 +# Height of output window or fullscreen height +ScreenHeight = 320 +# Use fullscreen mode if True, or windowed mode if False +Fullscreen = True +# 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-GLideN64] + +###### Hardware Compatibility ###### +# Leave enabled unless a mobile gpu doesn't support it. +EnableFragmentDepthWrite = 0 +# Hardware per pixel lighting, supposedly good for GLES3.1 devices or higher. +EnableHWLighting = 0 + +###### Enhancements ####### +# Internal render resoluton rather than output. So 2 x 240p is 480p, etc. +UseNativeResolutionFactor = 1 +# Enable/Disable MultiSampling (0=off, 2,4,8,16=quality) +MultiSampling = 0 +# Enable/Disable Fast Approximate Anti-Aliasing FXAA +FXAA = 0 +# Max level of Anisotropic Filtering, 0 for off +anisotropy = 0 +# Bilinear filtering mode (0=N64 3point, 1=standard) +# @rishooty: best to use this at 1x native res, any higher turn it off. +bilinearMode = 1 + +###### Compatibility ###### +# Make texrect coordinates continuous to avoid black lines between them. (0=Off/default, 1=Auto, 2=Force) +CorrectTexrectCoords = 1 +# Copy auxiliary buffers to RDRAM (default: 0) +EnableCopyAuxiliaryToRDRAM = 1 +# Render 2D texrects in native resolution to fix misalignment between parts of 2D image. (0=Off/default, 1=Optimized, 2=Unoptimized)") +EnableNativeResTexrects = 1 + +###### Other ###### +# Enable threaded video backend at the cost of input lag +ThreadedVideo = 1 +# Screen aspect ratio (0=stretch, 1=force 4:3, 2=force 16:9, 3=adjust) +AspectRatio = 1 +# Display On-screen FPS +ShowFPS = False + +[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] + +# Hack to accomodate widescreen devices +ResolutionWidth = 480 +# 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/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/RK3326/mupen64plus.cfg.xut b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/RK3326/mupen64plus.cfg.xut new file mode 100644 index 0000000000..32d61c6265 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/RK3326/mupen64plus.cfg.xut @@ -0,0 +1,670 @@ +# 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 = "/tmp/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 = "J0B16/B9" +# Joystick event string for switching between fullscreen/windowed modes +Joy Mapping Fullscreen = "" +# Joystick event string for saving the emulator state +Joy Mapping Save State = "J0B16/B5" +# Joystick event string for loading the emulator state +Joy Mapping Load State = "J0B16/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 = "J0B16/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 = "J0B16/B15" +# 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 = "XU10 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 +plugged = True +mouse = False +AnalogDeadzone = 0,0 +AnalogPeak = 32768,32768 +DPad R = button(15) +DPad L = button(14) +DPad D = button(13) +DPad U = button(12) +Start = button(9) +Z Trig = button(7) +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 = +# 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 = 427 +# Height of output window or fullscreen height +ScreenHeight = 320 +# Use fullscreen mode if True, or windowed mode if False +Fullscreen = True +# If true, activate the SDL_GL_SWAP_CONTROL attribute +VerticalSync = False +# Rotate screen contents: 0=0 degree, 1=90 degree, 2 = 180 degree, 3=270 degree +Rotate = 0 + +[Video-GLideN64] + +###### Hardware Compatibility ###### +# Leave enabled unless a mobile gpu doesn't support it. +EnableFragmentDepthWrite = 0 +# Hardware per pixel lighting, supposedly good for GLES3.1 devices or higher. +EnableHWLighting = 0 + +###### Enhancements ####### +# Internal render resoluton rather than output. So 2 x 240p is 480p, etc. +UseNativeResolutionFactor = 1 +# Enable/Disable MultiSampling (0=off, 2,4,8,16=quality) +MultiSampling = 0 +# Enable/Disable Fast Approximate Anti-Aliasing FXAA +FXAA = 0 +# Max level of Anisotropic Filtering, 0 for off +anisotropy = 0 +# Bilinear filtering mode (0=N64 3point, 1=standard) +# @rishooty: best to use this at 1x native res, any higher turn it off. +bilinearMode = 1 + +###### Compatibility ###### +# Make texrect coordinates continuous to avoid black lines between them. (0=Off/default, 1=Auto, 2=Force) +CorrectTexrectCoords = 1 +# Copy auxiliary buffers to RDRAM (default: 0) +EnableCopyAuxiliaryToRDRAM = 1 +# Render 2D texrects in native resolution to fix misalignment between parts of 2D image. (0=Off/default, 1=Optimized, 2=Unoptimized)") +EnableNativeResTexrects = 1 + +###### Other ###### +# Enable threaded video backend at the cost of input lag +ThreadedVideo = 1 +# Screen aspect ratio (0=stretch, 1=force 4:3, 2=force 16:9, 3=adjust) +AspectRatio = 1 +# Display On-screen FPS +ShowFPS = False + +[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] + +# Hack to accomodate widescreen devices +ResolutionWidth = 480 +# 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 = True +# Use different texture coordinate clamping code +AccurateTextureMapping = False +# 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 = 0 +# 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/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/RK3399/mupen64plus.cfg b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/RK3399/mupen64plus.cfg new file mode 100644 index 0000000000..c637c1119f --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/RK3399/mupen64plus.cfg @@ -0,0 +1,665 @@ +# 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/screenshots" +# 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/.config/game/configs/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 = "J0B8/B9" +# Joystick event string for switching between fullscreen/windowed modes +Joy Mapping Fullscreen = "" +# Joystick event string for saving the emulator state +Joy Mapping Save State = "J0B8/B5" +# Joystick event string for loading the emulator state +Joy Mapping Load State = "J0B8/B4" +# Joystick event string for advancing the save state slot +Joy Mapping Increment Slot = "" +# Joystick event string for resetting the emulator +Joy Mapping Reset = "J0B8/B0" +# 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 = "J0B8/B3" +# 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 = "J0B8/B7" +# 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 = "J0B8/B2" +# 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 = "rg552_joypad" +# 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(16) +DPad L = button(15) +DPad D = button(14) +DPad U = button(13) +Start = button(9) +Z Trig = button(5) +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 = button(7) +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 = True +# 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-GLideN64] + +###### Hardware Compatibility ###### +# Leave enabled unless a mobile gpu doesn't support it. +EnableFragmentDepthWrite = 1 +# Hardware per pixel lighting, supposedly good for GLES3.1 devices or higher. +EnableHWLighting = 0 + +###### Enhancements ####### +# Internal render resoluton rather than output. So 2 x 240p is 480p, etc. +UseNativeResolutionFactor = 1 +# Enable/Disable MultiSampling (0=off, 2,4,8,16=quality) +MultiSampling = 0 +# Enable/Disable Fast Approximate Anti-Aliasing FXAA +FXAA = 0 +# Max level of Anisotropic Filtering, 0 for off +anisotropy = 0 +# Bilinear filtering mode (0=N64 3point, 1=standard) +# @rishooty: best to use this at 1x native res, any higher turn it off. +bilinearMode = 1 + +###### Compatibility ###### +# Make texrect coordinates continuous to avoid black lines between them. (0=Off/default, 1=Auto, 2=Force) +CorrectTexrectCoords = 1 +# Copy auxiliary buffers to RDRAM (default: 0) +EnableCopyAuxiliaryToRDRAM = 1 +# Render 2D texrects in native resolution to fix misalignment between parts of 2D image. (0=Off/default, 1=Optimized, 2=Unoptimized)") +EnableNativeResTexrects = 1 + +###### Other ###### +# Enable threaded video backend at the cost of input lag +ThreadedVideo = 1 +# Screen aspect ratio (0=stretch, 1=force 4:3, 2=force 16:9, 3=adjust) +AspectRatio = 1 +# Display On-screen FPS +ShowFPS = False + +[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/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/RK3566/mupen64plus.cfg b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/RK3566/mupen64plus.cfg new file mode 100644 index 0000000000..9eb571253b --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/RK3566/mupen64plus.cfg @@ -0,0 +1,665 @@ +# 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/screenshots" +# 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/.config/game/configs/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 = "J0B8/B9" +# Joystick event string for switching between fullscreen/windowed modes +Joy Mapping Fullscreen = "" +# Joystick event string for saving the emulator state +Joy Mapping Save State = "J0B8/B5" +# Joystick event string for loading the emulator state +Joy Mapping Load State = "J0B8/B4" +# Joystick event string for advancing the save state slot +Joy Mapping Increment Slot = "" +# Joystick event string for resetting the emulator +Joy Mapping Reset = "J0B8/B0" +# 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 = "J0B8/B3" +# 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 = "J0B8/B7" +# 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 = "J0B8/B2" +# 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 = "retrogame_joypad" +# 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(16) +DPad L = button(15) +DPad D = button(14) +DPad U = button(13) +Start = button(9) +Z Trig = button(5) +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 = button(7) +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 = True +# 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-GLideN64] + +###### Hardware Compatibility ###### +# Leave enabled unless a mobile gpu doesn't support it. +EnableFragmentDepthWrite = 0 +# Hardware per pixel lighting, supposedly good for GLES3.1 devices or higher. +EnableHWLighting = 0 + +###### Enhancements ####### +# Internal render resoluton rather than output. So 2 x 240p is 480p, etc. +UseNativeResolutionFactor = 1 +# Enable/Disable MultiSampling (0=off, 2,4,8,16=quality) +MultiSampling = 0 +# Enable/Disable Fast Approximate Anti-Aliasing FXAA +FXAA = 0 +# Max level of Anisotropic Filtering, 0 for off +anisotropy = 0 +# Bilinear filtering mode (0=N64 3point, 1=standard) +# @rishooty: best to use this at 1x native res, any higher turn it off. +bilinearMode = 1 + +###### Compatibility ###### +# Make texrect coordinates continuous to avoid black lines between them. (0=Off/default, 1=Auto, 2=Force) +CorrectTexrectCoords = 1 +# Copy auxiliary buffers to RDRAM (default: 0) +EnableCopyAuxiliaryToRDRAM = 1 +# Render 2D texrects in native resolution to fix misalignment between parts of 2D image. (0=Off/default, 1=Optimized, 2=Unoptimized)") +EnableNativeResTexrects = 1 + +###### Other ###### +# Enable threaded video backend at the cost of input lag +ThreadedVideo = 1 +# Screen aspect ratio (0=stretch, 1=force 4:3, 2=force 16:9, 3=adjust) +AspectRatio = 1 +# Display On-screen FPS +ShowFPS = False + +[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/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/RK3566/mupen64plus.cfg.rgarc b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/RK3566/mupen64plus.cfg.rgarc new file mode 100644 index 0000000000..058c75774f --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/RK3566/mupen64plus.cfg.rgarc @@ -0,0 +1,665 @@ +# 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/screenshots" +# 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/.config/game/configs/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 = "J0B8/B9" +# Joystick event string for switching between fullscreen/windowed modes +Joy Mapping Fullscreen = "" +# Joystick event string for saving the emulator state +Joy Mapping Save State = "J0B8/B5" +# Joystick event string for loading the emulator state +Joy Mapping Load State = "J0B8/B4" +# Joystick event string for advancing the save state slot +Joy Mapping Increment Slot = "" +# Joystick event string for resetting the emulator +Joy Mapping Reset = "J0B8/B0" +# 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 = "J0B8/B3" +# Joystick event string for pausing the emulator +Joy Mapping Pause = "J0B8/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 = "J0B8/B7" +# 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 = "J0B8/B2" +# 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 = "rg_arc_joypad" +# 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 = +DPad L = +DPad D = +DPad U = +Start = button(11) +Z Trig = button(8) +B Button = button(3) +A Button = button(1) +C Button R = button(2) +C Button L = button(4) +C Button D = button(0) +C Button U = button(5) +R Trig = button(7) +L Trig = button(6) +Mempak switch = +Rumblepak switch = +# Analog axis configuration mappings +X Axis = button(14,15) +Y Axis = button(12,13) + + +[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 = True +# 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-GLideN64] + +###### Hardware Compatibility ###### +# Leave enabled unless a mobile gpu doesn't support it. +EnableFragmentDepthWrite = 0 +# Hardware per pixel lighting, supposedly good for GLES3.1 devices or higher. +EnableHWLighting = 0 + +###### Enhancements ####### +# Internal render resoluton rather than output. So 2 x 240p is 480p, etc. +UseNativeResolutionFactor = 1 +# Enable/Disable MultiSampling (0=off, 2,4,8,16=quality) +MultiSampling = 0 +# Enable/Disable Fast Approximate Anti-Aliasing FXAA +FXAA = 0 +# Max level of Anisotropic Filtering, 0 for off +anisotropy = 0 +# Bilinear filtering mode (0=N64 3point, 1=standard) +# @rishooty: best to use this at 1x native res, any higher turn it off. +bilinearMode = 1 + +###### Compatibility ###### +# Make texrect coordinates continuous to avoid black lines between them. (0=Off/default, 1=Auto, 2=Force) +CorrectTexrectCoords = 1 +# Copy auxiliary buffers to RDRAM (default: 0) +EnableCopyAuxiliaryToRDRAM = 1 +# Render 2D texrects in native resolution to fix misalignment between parts of 2D image. (0=Off/default, 1=Optimized, 2=Unoptimized)") +EnableNativeResTexrects = 1 + +###### Other ###### +# Enable threaded video backend at the cost of input lag +ThreadedVideo = 1 +# Screen aspect ratio (0=stretch, 1=force 4:3, 2=force 16:9, 3=adjust) +AspectRatio = 1 +# Display On-screen FPS +ShowFPS = False + +[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/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/RK3588/mupen64plus.cfg b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/RK3588/mupen64plus.cfg new file mode 100644 index 0000000000..77a651a3ba --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/RK3588/mupen64plus.cfg @@ -0,0 +1,664 @@ +# 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/screenshots" +# 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/.config/game/configs/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 = "J0B9/B8" +# Joystick event string for switching between fullscreen/windowed modes +Joy Mapping Fullscreen = "" +# Joystick event string for saving the emulator state +Joy Mapping Save State = "J0B9/B6" +# Joystick event string for loading the emulator state +Joy Mapping Load State = "J0B9/B5" +# Joystick event string for advancing the save state slot +Joy Mapping Increment Slot = "" +# Joystick event string for resetting the emulator +Joy Mapping Reset = "J0B9/B0" +# 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 = "J0B9/B4" +# Joystick event string for pausing the emulator +Joy Mapping Pause = "" +# 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 = "GameForce ACE 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(15) +DPad L = button(14) +DPad D = button(13) +DPad U = button(12) +Start = button(8) +Z Trig = axis(5-) +B Button = button(4) +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(6) +L Trig = button(5) +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 = True +# 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-GLideN64] + +###### Hardware Compatibility ###### +# Leave enabled unless a mobile gpu doesn't support it. +EnableFragmentDepthWrite = 1 +# Hardware per pixel lighting, supposedly good for GLES3.1 devices or higher. +EnableHWLighting = 0 + +###### Enhancements ####### +# Internal render resoluton rather than output. So 2 x 240p is 480p, etc. +UseNativeResolutionFactor = 1 +# Enable/Disable MultiSampling (0=off, 2,4,8,16=quality) +MultiSampling = 0 +# Enable/Disable Fast Approximate Anti-Aliasing FXAA +FXAA = 0 +# Max level of Anisotropic Filtering, 0 for off +anisotropy = 0 +# Bilinear filtering mode (0=N64 3point, 1=standard) +# @rishooty: best to use this at 1x native res, any higher turn it off. +bilinearMode = 1 + +###### Compatibility ###### +# Make texrect coordinates continuous to avoid black lines between them. (0=Off/default, 1=Auto, 2=Force) +CorrectTexrectCoords = 1 +# Copy auxiliary buffers to RDRAM (default: 0) +EnableCopyAuxiliaryToRDRAM = 1 +# Render 2D texrects in native resolution to fix misalignment between parts of 2D image. (0=Off/default, 1=Optimized, 2=Unoptimized)") +EnableNativeResTexrects = 1 + +###### Other ###### +# Enable threaded video backend at the cost of input lag +ThreadedVideo = 1 +# Screen aspect ratio (0=stretch, 1=force 4:3, 2=force 16:9, 3=adjust) +AspectRatio = 1 +# Display On-screen FPS +ShowFPS = False + +[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/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/S922X/mupen64plus.cfg b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/S922X/mupen64plus.cfg new file mode 100644 index 0000000000..9d75f74f35 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/S922X/mupen64plus.cfg @@ -0,0 +1,708 @@ +# 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/screenshots" +# 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/.config/game/configs/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 = "J0B11/B10" +# Joystick event string for switching between fullscreen/windowed modes +Joy Mapping Fullscreen = "" +# Joystick event string for saving the emulator state +Joy Mapping Save State = "J0B11/B6" +# Joystick event string for loading the emulator state +Joy Mapping Load State = "J0B11/B5" +# Joystick event string for advancing the save state slot +Joy Mapping Increment Slot = "" +# Joystick event string for resetting the emulator +Joy Mapping Reset = "J0B11/B0" +# 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 = "J0B11/B4" +# Joystick event string for pausing the emulator +Joy Mapping Pause = "" +# 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-Ultra 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 +AnalogDeadzone = 0,0 +AnalogPeak = 32768,32768 +DPad R = button(17) +DPad L = button(16) +DPad D = button(15) +DPad U = button(14) +Start = button(10) +Z Trig = button(5) button(8) +B Button = button(4) +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(7) +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-cxd4.so" + + +[Video-General] + +# Width of output window or fullscreen width +ScreenWidth = 854 +# Height of output window or fullscreen height +ScreenHeight = 480 +# Use fullscreen mode if True, or windowed mode if False +Fullscreen = True +# 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-Parallel] + +# Amount of rescaling: 1=None, 2=2x, 4=4x +Upscaling = 1 +# Enable VSync +VSync = True +# Widescreen mode (stretched) +WidescreenStretch = False +# Deinterlacing method. False=Bob, True=Weave +DeinterlaceWeave = False +# Enable superscaling of readbacks when upsampling +SuperscaledReads = False +# Enable superscaling of dithering when upsampling +SuperscaledDither = True +# Enable synchronizing RDP and CPU +SynchronousRDP = True +# Amount of overscan pixels to crop on all sides +CropOverscan = 0 +# Amount of pixels to stretch by vertically. Can fix PAL ports that didn't fill the PAL resolution of 288p (use value of 24 in that case). +VerticalStretch = 0 +# VI anti-aliasing, smooths polygon edges. +VIAA = True +# Allow VI divot filter, cleans up stray black pixels. +Divot = True +# Allow VI gamma dither +GammaDither = True +# Allow VI bilinear scaling +VIBilerp = True +# Allow VI dedither filter +VIDither = True +# Downsampling factor, downscales output after VI, equivalent to SSAA. 0=disabled, 1=1/2, 2=1/4, 3=1/8 +DownScale = 0 +# Use native texture LOD computation when upscaling, effectively a LOD bias +NativeTextLOD = False +# Native resolution TEX_RECT. TEX_RECT primitives should generally be rendered at native resolution to avoid seams +NativeTextRECT = True +# Use fullscreen mode if True, or windowed mode if False +Fullscreen = True +# Screen width +ScreenWidth = 854 +# Screen height +ScreenHeight = 480 +# Deinterlacing method. False=Bob, True=Weave +DeinterlaceMode = False + +[Video-GLideN64] + +###### Hardware Compatibility ###### +# Leave enabled unless a mobile gpu doesn't support it. +EnableFragmentDepthWrite = 1 +# Hardware per pixel lighting, supposedly good for GLES3.1 devices or higher. +EnableHWLighting = 0 + +###### Enhancements ####### +# Internal render resoluton rather than output. So 2 x 240p is 480p, etc. +UseNativeResolutionFactor = 1 +# Enable/Disable MultiSampling (0=off, 2,4,8,16=quality) +MultiSampling = 0 +# Enable/Disable Fast Approximate Anti-Aliasing FXAA +FXAA = 0 +# Max level of Anisotropic Filtering, 0 for off +anisotropy = 0 +# Bilinear filtering mode (0=N64 3point, 1=standard) +# @rishooty: best to use this at 1x native res, any higher turn it off. +bilinearMode = 1 + +###### Compatibility ###### +# Make texrect coordinates continuous to avoid black lines between them. (0=Off/default, 1=Auto, 2=Force) +CorrectTexrectCoords = 1 +# Copy auxiliary buffers to RDRAM (default: 0) +EnableCopyAuxiliaryToRDRAM = 1 +# Render 2D texrects in native resolution to fix misalignment between parts of 2D image. (0=Off/default, 1=Optimized, 2=Unoptimized)") +EnableNativeResTexrects = 1 + +###### Other ###### +# Enable threaded video backend at the cost of input lag +ThreadedVideo = 1 +# Screen aspect ratio (0=stretch, 1=force 4:3, 2=force 16:9, 3=adjust) +AspectRatio = 1 +# Display On-screen FPS +ShowFPS = False + +[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/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/SDM845/mupen64plus.cfg b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/SDM845/mupen64plus.cfg new file mode 100644 index 0000000000..590878aad8 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/SDM845/mupen64plus.cfg @@ -0,0 +1,670 @@ +# 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/screenshots" +# 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/.config/game/configs/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/B8" +# Joystick event string for switching between fullscreen/windowed modes +Joy Mapping Fullscreen = "" +# Joystick event string for saving the emulator state +Joy Mapping Save State = "J0B10/B5" +# Joystick event string for loading the emulator state +Joy Mapping Load State = "J0B10/B4" +# Joystick event string for advancing the save state slot +Joy Mapping Increment Slot = "" +# Joystick event string for resetting the emulator +Joy Mapping Reset = "J0B10/B0" +# 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 = "J0B10/B1" +# Joystick event string for pausing the emulator +Joy Mapping Pause = "" +# 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 = "rg552_joypad" +# 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 +; AYN Odin Gamepad - default.ini +[AYN Odin Gamepad] +plugged = True +mouse = False +AnalogDeadzone = 0,0 +AnalogPeak = 32768,32768 +DPad R = button(16) +DPad L = button(15) +DPad D = button(14) +DPad U = button(13) +Start = button(9) +Z Trig = axis(5+) +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 = 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 = 1280 +# Height of output window or fullscreen height +ScreenHeight = 960 +# Use fullscreen mode if True, or windowed mode if False +Fullscreen = True +# 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-GLideN64] + +###### Hardware Compatibility ###### +# Leave enabled unless a mobile gpu doesn't support it. +EnableFragmentDepthWrite = 1 +# Hardware per pixel lighting, supposedly good for GLES3.1 devices or higher. +EnableHWLighting = 0 + +###### Enhancements ####### +# Internal render resoluton rather than output. So 2 x 240p is 480p, etc. +UseNativeResolutionFactor = 1 +# Enable/Disable MultiSampling (0=off, 2,4,8,16=quality) +MultiSampling = 0 +# Enable/Disable Fast Approximate Anti-Aliasing FXAA +FXAA = 0 +# Max level of Anisotropic Filtering, 0 for off +anisotropy = 0 +# Bilinear filtering mode (0=N64 3point, 1=standard) +# @rishooty: best to use this at 1x native res, any higher turn it off. +bilinearMode = 1 + +###### Compatibility ###### +# Make texrect coordinates continuous to avoid black lines between them. (0=Off/default, 1=Auto, 2=Force) +CorrectTexrectCoords = 1 +# Copy auxiliary buffers to RDRAM (default: 0) +EnableCopyAuxiliaryToRDRAM = 1 +# Render 2D texrects in native resolution to fix misalignment between parts of 2D image. (0=Off/default, 1=Optimized, 2=Unoptimized)") +EnableNativeResTexrects = 1 + +###### Other ###### +# Enable threaded video backend at the cost of input lag +ThreadedVideo = 1 +# Screen aspect ratio (0=stretch, 1=force 4:3, 2=force 16:9, 3=adjust) +AspectRatio = 1 +# Display On-screen FPS +ShowFPS = False + +[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/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/SM8250/mupen64plus.cfg b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/SM8250/mupen64plus.cfg new file mode 100644 index 0000000000..80fddb807b --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/SM8250/mupen64plus.cfg @@ -0,0 +1,670 @@ +# 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/screenshots" +# 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/.config/game/configs/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/B8" +# Joystick event string for switching between fullscreen/windowed modes +Joy Mapping Fullscreen = "" +# Joystick event string for saving the emulator state +Joy Mapping Save State = "J0B6/B5" +# Joystick event string for loading the emulator state +Joy Mapping Load State = "J0B6/B4" +# Joystick event string for advancing the save state slot +Joy Mapping Increment Slot = "" +# Joystick event string for resetting the emulator +Joy Mapping Reset = "J0B6/B0" +# 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 = "J0B6/B3" +# 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 = "rg552_joypad" +# 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 +; Retroid Pocket Gamepad - default.ini +[Retroid Pocket Gamepad] +plugged = True +mouse = False +AnalogDeadzone = 0,0 +AnalogPeak = 32768,32768 +DPad R = button(14) +DPad L = button(13) +DPad D = button(12) +DPad U = button(11) +Start = button(7) +Z Trig = axis(7+) +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 = +# 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 = 1280 +# Height of output window or fullscreen height +ScreenHeight = 960 +# Use fullscreen mode if True, or windowed mode if False +Fullscreen = True +# 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-GLideN64] + +###### Hardware Compatibility ###### +# Leave enabled unless a mobile gpu doesn't support it. +EnableFragmentDepthWrite = 1 +# Hardware per pixel lighting, supposedly good for GLES3.1 devices or higher. +EnableHWLighting = 0 + +###### Enhancements ####### +# Internal render resoluton rather than output. So 2 x 240p is 480p, etc. +UseNativeResolutionFactor = 1 +# Enable/Disable MultiSampling (0=off, 2,4,8,16=quality) +MultiSampling = 0 +# Enable/Disable Fast Approximate Anti-Aliasing FXAA +FXAA = 0 +# Max level of Anisotropic Filtering, 0 for off +anisotropy = 0 +# Bilinear filtering mode (0=N64 3point, 1=standard) +# @rishooty: best to use this at 1x native res, any higher turn it off. +bilinearMode = 1 + +###### Compatibility ###### +# Make texrect coordinates continuous to avoid black lines between them. (0=Off/default, 1=Auto, 2=Force) +CorrectTexrectCoords = 1 +# Copy auxiliary buffers to RDRAM (default: 0) +EnableCopyAuxiliaryToRDRAM = 1 +# Render 2D texrects in native resolution to fix misalignment between parts of 2D image. (0=Off/default, 1=Optimized, 2=Unoptimized)") +EnableNativeResTexrects = 1 + +###### Other ###### +# Enable threaded video backend at the cost of input lag +ThreadedVideo = 1 +# Screen aspect ratio (0=stretch, 1=force 4:3, 2=force 16:9, 3=adjust) +AspectRatio = 1 +# Display On-screen FPS +ShowFPS = False + +[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/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/SM8550/mupen64plus.cfg b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/SM8550/mupen64plus.cfg new file mode 100644 index 0000000000..8f707630dd --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/SM8550/mupen64plus.cfg @@ -0,0 +1,665 @@ +# 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/screenshots" +# 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/.config/game/configs/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/B8" +# Joystick event string for switching between fullscreen/windowed modes +Joy Mapping Fullscreen = "" +# Joystick event string for saving the emulator state +Joy Mapping Save State = "J0B6/B5" +# Joystick event string for loading the emulator state +Joy Mapping Load State = "J0B6/B4" +# Joystick event string for advancing the save state slot +Joy Mapping Increment Slot = "" +# Joystick event string for resetting the emulator +Joy Mapping Reset = "J0B6/B0" +# 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 = "J0B6/B3" +# 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 = "Xbox Series X 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 = "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-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 = 1280 +# Height of output window or fullscreen height +ScreenHeight = 960 +# Use fullscreen mode if True, or windowed mode if False +Fullscreen = True +# 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-GLideN64] + +###### Hardware Compatibility ###### +# Leave enabled unless a mobile gpu doesn't support it. +EnableFragmentDepthWrite = 1 +# Hardware per pixel lighting, supposedly good for GLES3.1 devices or higher. +EnableHWLighting = 0 + +###### Enhancements ####### +# Internal render resoluton rather than output. So 2 x 240p is 480p, etc. +UseNativeResolutionFactor = 1 +# Enable/Disable MultiSampling (0=off, 2,4,8,16=quality) +MultiSampling = 0 +# Enable/Disable Fast Approximate Anti-Aliasing FXAA +FXAA = 0 +# Max level of Anisotropic Filtering, 0 for off +anisotropy = 0 +# Bilinear filtering mode (0=N64 3point, 1=standard) +# @rishooty: best to use this at 1x native res, any higher turn it off. +bilinearMode = 1 + +###### Compatibility ###### +# Make texrect coordinates continuous to avoid black lines between them. (0=Off/default, 1=Auto, 2=Force) +CorrectTexrectCoords = 1 +# Copy auxiliary buffers to RDRAM (default: 0) +EnableCopyAuxiliaryToRDRAM = 1 +# Render 2D texrects in native resolution to fix misalignment between parts of 2D image. (0=Off/default, 1=Optimized, 2=Unoptimized)") +EnableNativeResTexrects = 1 + +###### Other ###### +# Enable threaded video backend at the cost of input lag +ThreadedVideo = 1 +# Screen aspect ratio (0=stretch, 1=force 4:3, 2=force 16:9, 3=adjust) +AspectRatio = 1 +# Display On-screen FPS +ShowFPS = False + +[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/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/SM8650/mupen64plus.cfg b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/SM8650/mupen64plus.cfg new file mode 100644 index 0000000000..8f707630dd --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/config/SM8650/mupen64plus.cfg @@ -0,0 +1,665 @@ +# 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/screenshots" +# 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/.config/game/configs/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/B8" +# Joystick event string for switching between fullscreen/windowed modes +Joy Mapping Fullscreen = "" +# Joystick event string for saving the emulator state +Joy Mapping Save State = "J0B6/B5" +# Joystick event string for loading the emulator state +Joy Mapping Load State = "J0B6/B4" +# Joystick event string for advancing the save state slot +Joy Mapping Increment Slot = "" +# Joystick event string for resetting the emulator +Joy Mapping Reset = "J0B6/B0" +# 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 = "J0B6/B3" +# 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 = "Xbox Series X 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 = "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-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 = 1280 +# Height of output window or fullscreen height +ScreenHeight = 960 +# Use fullscreen mode if True, or windowed mode if False +Fullscreen = True +# 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-GLideN64] + +###### Hardware Compatibility ###### +# Leave enabled unless a mobile gpu doesn't support it. +EnableFragmentDepthWrite = 1 +# Hardware per pixel lighting, supposedly good for GLES3.1 devices or higher. +EnableHWLighting = 0 + +###### Enhancements ####### +# Internal render resoluton rather than output. So 2 x 240p is 480p, etc. +UseNativeResolutionFactor = 1 +# Enable/Disable MultiSampling (0=off, 2,4,8,16=quality) +MultiSampling = 0 +# Enable/Disable Fast Approximate Anti-Aliasing FXAA +FXAA = 0 +# Max level of Anisotropic Filtering, 0 for off +anisotropy = 0 +# Bilinear filtering mode (0=N64 3point, 1=standard) +# @rishooty: best to use this at 1x native res, any higher turn it off. +bilinearMode = 1 + +###### Compatibility ###### +# Make texrect coordinates continuous to avoid black lines between them. (0=Off/default, 1=Auto, 2=Force) +CorrectTexrectCoords = 1 +# Copy auxiliary buffers to RDRAM (default: 0) +EnableCopyAuxiliaryToRDRAM = 1 +# Render 2D texrects in native resolution to fix misalignment between parts of 2D image. (0=Off/default, 1=Optimized, 2=Unoptimized)") +EnableNativeResTexrects = 1 + +###### Other ###### +# Enable threaded video backend at the cost of input lag +ThreadedVideo = 1 +# Screen aspect ratio (0=stretch, 1=force 4:3, 2=force 16:9, 3=adjust) +AspectRatio = 1 +# Display On-screen FPS +ShowFPS = False + +[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/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/package.mk b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/package.mk new file mode 100644 index 0000000000..1305e5a187 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/package.mk @@ -0,0 +1,74 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2023 Nicholas Ricciuti (rishooty@gmail.com) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) +PKG_NAME="mupen64plus-sa-core" +PKG_VERSION="5340dafcc0f5e8284057ab931dd5c66222d3d49e" +#PKG_VERSION="d4f3e12db0609158c7b4e0beef2bb950aad0ccb9" +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 boost libpng SDL2 SDL2_net zlib freetype nasm:host" +PKG_LONGDESC="mupen64plus" +PKG_LONGDESC="Mupen64Plus Standalone" +PKG_TOOLCHAIN="manual" + +if [ "${VULKAN_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${VULKAN}" + PKG_MAKE_OPTS_TARGET+=" VULKAN=1" +else + PKG_MAKE_OPTS_TARGET+=" VULKAN=0" +fi + +case ${DEVICE} in + SM8250|SM8550|SM8650) + PKG_DEPENDS_TARGET+=" ${OPENGL} glu libglvnd" + export USE_GLES=0 + ;; + *) + PKG_DEPENDS_TARGET+=" ${OPENGLES}" + export USE_GLES=1 + ;; +esac + +make_target() { + export HOST_CPU=${TARGET_ARCH} \ + NEW_DYNAREC=1 \ + VFP_HARD=1 \ + V=1 \ + VC=0 \ + OSD=0 + + export BINUTILS="$(get_build_dir binutils)/.${TARGET_NAME}" + export NEW_DYNAREC=1 + export SDL_CFLAGS="-I${SYSROOT_PREFIX}/usr/include/SDL2 -pthread -D_REENTRANT" + export SDL_LDLIBS="-lSDL2_net -lSDL2" + export CROSS_COMPILE="${TARGET_PREFIX}" + + sed -i 's/\-O[23]/-Ofast/' ${PKG_BUILD}/projects/unix/Makefile + + make -C projects/unix clean ${PKG_MAKE_OPTS_TARGET} + 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/* + + if [ -e "${PKG_DIR}/config/${DEVICE}/mupen64plus.cfg" ] + then + cp ${PKG_DIR}/config/${DEVICE}/* ${INSTALL}/usr/local/share/mupen64plus/ + chmod 644 ${INSTALL}/usr/local/share/mupen64plus/mupen64plus.cfg + fi + + mkdir -p ${INSTALL}/usr/bin + cp ${PKG_DIR}/scripts/start_mupen64plus.sh ${INSTALL}/usr/bin + chmod 755 ${INSTALL}/usr/bin/start_mupen64plus.sh +} + diff --git a/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/scripts/start_mupen64plus.sh b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/scripts/start_mupen64plus.sh new file mode 100644 index 0000000000..c72aedc5a8 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-core/scripts/start_mupen64plus.sh @@ -0,0 +1,193 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present 351ELEC (https://github.com/351ELEC) +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile + +set_kill set "-9 mupen64plus" + +# Emulation Station features +GAME=$(echo "${1}"| sed "s#^/.*/##") +PLATFORM=$(echo "${2}"| sed "s#^/.*/##") +SCREENWIDTH=$(fbwidth) +SCREENHEIGHT=$(fbheight) +ASPECT=$(get_setting game_aspect_ratio "${PLATFORM}" "${GAME}") +IRES=$(get_setting internal_resolution "${PLATFORM}" "${GAME}") +RSP=$(get_setting rsp_plugin "${PLATFORM}" "${GAME}") +SIMPLECORE=$(get_setting core_plugin "${PLATFORM}" "${GAME}") +FPS=$(get_setting show_fps "${PLATFORM}" "${GAME}") +PAK=$(get_setting controller_pak "${PLATFORM}" "${GAME}") +CON=$(get_setting input_configuration "${PLATFORM}" "${GAME}") +VPLUGIN=$(get_setting video_plugin "${PLATFORM}" "${GAME}") +CORES=$(get_setting "cores" "${PLATFORM}" "${GAME}") +GLIDEN64CONF=$(get_setting gliden64_profiles "${PLATFORM}" "${GAME}") + +# File locations +SHARE="/usr/local/share/mupen64plus" +GAMEDATA="/storage/.config/mupen64plus" +M64PCONF="${GAMEDATA}/mupen64plus.cfg" +CUSTOMINP="${GAMEDATA}/custominput.ini" +TMP="/tmp/mupen64plus" + +# Clean and create directories +rm -rf ${TMP} +mkdir -p ${TMP} +mkdir -p ${GAMEDATA} + +# Copy files to GAMEDATA +if [[ ! -f "${M64PCONF}" ]]; then + cp ${SHARE}/mupen64plus.cfg* ${GAMEDATA} +fi +if [[ ! -f "${CUSTOMINP}" ]]; then + cp ${SHARE}/default.ini ${CUSTOMINP} +fi + +# Copy files to TMP +cp ${M64PCONF} ${TMP} +if [ "${CON}" = "custom" ]; then + cp ${CUSTOMINP} ${TMP}/InputAutoCfg.ini +elif [ "${CON}" = "standard" ]; then + cp ${SHARE}/default.ini ${TMP}/InputAutoCfg.ini +else + cp ${SHARE}/default.ini ${TMP}/InputAutoCfg.ini +fi +if [ $(echo $1 | grep -i .zip | wc -l) -eq 1 ]; then + # Unzip the game ROM if needed + unzip -q -o "$1" -d ${TMP} + ROM=$(unzip -Zl -1 "$1") +else + cp "$1" ${TMP} + ROM="${GAME}" +fi + +# CPU core settings +if [ "${CORES}" = "little" ]; then + EMUPERF="${SLOW_CORES}" +elif [ "${CORES}" = "big" ]; then + EMUPERF="${FAST_CORES}" +else + unset EMUPERF +fi + +# Configure Mupen64Plus-SA parameters +SET_PARAMS="" + +# Emulator core settings +SET_PARAMS+=" --set Core[SharedDataPath]=${TMP}" +if [ "${SIMPLECORE}" = "simple" ]; then + SIMPLESUFFIX="-simple" + SET_PARAMS+=" --set Core[R4300Emulator]=1" +else + SIMPLESUFFIX="" + SET_PARAMS+=" --set Core[R4300Emulator]=2" +fi + +# Input settings +SET_PARAMS+=" --set Input-SDL-Control1[plugin]=${PAK}" +SET_PARAMS+=" --set Input-SDL-Control2[plugin]=${PAK}" +SET_PARAMS+=" --set Input-SDL-Control3[plugin]=${PAK}" +SET_PARAMS+=" --set Input-SDL-Control4[plugin]=${PAK}" + +# Video settings +SET_PARAMS+=" --set Video-General[ScreenHeight]=${SCREENHEIGHT}" +SET_PARAMS+=" --set Video-Parallel[ScreenWidth]=${SCREENWIDTH}" +SET_PARAMS+=" --set Video-Parallel[ScreenHeight]=${SCREENHEIGHT}" +SET_PARAMS+=" --set Video-Parallel[Upscaling]=${IRES}" +SET_PARAMS+=" --set Video-GLideN64[UseNativeResolutionFactor]=${IRES}" +SET_PARAMS+=" --set Video-Rice[ResolutionWidth]=${SCREENWIDTH}" +if [ "${ASPECT}" = "fullscreen" ]; then + SET_PARAMS+=" --set Video-General[ScreenWidth]=${SCREENWIDTH}" + SET_PARAMS+=" --set Video-Parallel[WidescreenStretch]=False" + SET_PARAMS+=" --set Video-GLideN64[AspectRatio]=3" + SET_PARAMS+=" --set Video-Glide64mk2[aspect]=2" +else + if [ -z "${VPLUGIN}" ] || [ "${VPLUGIN}" = "rice" ]; then + GAMEWIDTH=$(((SCREENHEIGHT * 4) / 3)) + SET_PARAMS+=" --set Video-General[ScreenWidth]=${GAMEWIDTH}" + else + SET_PARAMS+=" --set Video-General[ScreenWidth]=${SCREENWIDTH}" + fi + SET_PARAMS+=" --set Video-Parallel[WidescreenStretch]=False" + SET_PARAMS+=" --set Video-GLideN64[AspectRatio]=1" + SET_PARAMS+=" --set Video-Glide64mk2[aspect]=0" +fi +if [ "${FPS}" = "true" ]; then + export LIBGL_SHOW_FPS="1" + export GALLIUM_HUD="cpu+GPU-load+fps" + SET_PARAMS+=" --set Video-GLideN64[ShowFPS]=True" + SET_PARAMS+=" --set Video-Glide64mk2[show_fps]=1" + SET_PARAMS+=" --set Video-Rice[ShowFPS]=True" +else + export LIBGL_SHOW_FPS="0" + export GALLIUM_HUD="off" + SET_PARAMS+=" --set Video-GLideN64[ShowFPS]=False" + SET_PARAMS+=" --set Video-Glide64mk2[show_fps]=0" + SET_PARAMS+=" --set Video-Rice[ShowFPS]=False" +fi + +# GLideN64 Profiles +if [ "${GLIDEN64CONF}" = "performance" ]; then + SET_PARAMS+=" --set Video-GLideN64[EnableLOD]=False" + SET_PARAMS+=" --set Video-GLideN64[EnableLegacyBlending]=True" + SET_PARAMS+=" --set Video-GLideN64[EnableHybridFilter]=False" + SET_PARAMS+=" --set Video-GLideN64[EnableInaccurateTextureCoordinates]=True" + SET_PARAMS+=" --set Video-GLideN64[EnableCopyColorToRDRAM]=0" + SET_PARAMS+=" --set Video-GLideN64[EnableCopyDepthToRDRAM]=0" + SET_PARAMS+=" --set Video-GLideN64[BackgroundsMode]=0" + SET_PARAMS+=" --set Video-GLideN64[RDRAMImageDitheringMode]=0" + SET_PARAMS+=" --set Video-GLideN64[CorrectTexrectCoords]=0" +else + SET_PARAMS+=" --set Video-GLideN64[EnableLOD]=True" + SET_PARAMS+=" --set Video-GLideN64[EnableLegacyBlending]=False" + SET_PARAMS+=" --set Video-GLideN64[EnableHybridFilter]=False" + SET_PARAMS+=" --set Video-GLideN64[EnableInaccurateTextureCoordinates]=False" + SET_PARAMS+=" --set Video-GLideN64[EnableCopyColorToRDRAM]=2" +fi + +# Set the video plugin +case ${VPLUGIN} in + "rmg_parallel") + SET_PARAMS+=" --gfx mupen64plus-video-parallel${SIMPLESUFFIX}.so" + RSP="parallel" + ;; + "gliden64") + SET_PARAMS+=" --gfx mupen64plus-video-GLideN64${SIMPLESUFFIX}.so" + ;; + "gl64mk2") + SET_PARAMS+=" --gfx mupen64plus-video-glide64mk2${SIMPLESUFFIX}.so" + ;; + "rice") + SET_PARAMS+=" --gfx mupen64plus-video-rice${SIMPLESUFFIX}.so" + ;; + *) + SET_PARAMS+=" --gfx mupen64plus-video-rice${SIMPLESUFFIX}.so" + ;; +esac + +# Set the RSP plugin +case "${RSP}" in + "parallel") + SET_PARAMS+=" --rsp mupen64plus-rsp-parallel${SIMPLESUFFIX}.so" + ;; + "hle") + SET_PARAMS+=" --rsp mupen64plus-rsp-hle${SIMPLESUFFIX}.so" + ;; + *) + SET_PARAMS+=" --rsp mupen64plus-rsp-cxd4${SIMPLESUFFIX}.so" + ;; +esac + +# Set the remaining plugins +SET_PARAMS+=" --input mupen64plus-input-sdl${SIMPLESUFFIX}.so" +SET_PARAMS+=" --audio mupen64plus-audio-sdl${SIMPLESUFFIX}.so" + +# Echo the command line options to the log for debugging +echo ${SET_PARAMS} + +# Panfrost optimization: forcepack reduces draw call overhead on Mali-G31 +export PAN_MESA_DEBUG=forcepack +export MESA_NO_ERROR=1 + +${EMUPERF} /usr/local/bin/mupen64plus${SIMPLESUFFIX} --configdir ${TMP} ${SET_PARAMS} "${TMP}/${ROM}" diff --git a/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/H700/default.ini b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/H700/default.ini new file mode 100644 index 0000000000..b9c13645ac --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/H700/default.ini @@ -0,0 +1,25 @@ +; H700 analog joypad - default.ini +[H700 Gamepad] +plugged = True +mouse = False +AnalogDeadzone = 0,0 +AnalogPeak = 32768,32768 +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(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 = +# Analog axis configuration mappings +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) diff --git a/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/H700/zlswap.ini b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/H700/zlswap.ini new file mode 100644 index 0000000000..d84ef18af8 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/H700/zlswap.ini @@ -0,0 +1,25 @@ +; H700 analog joypad - zlswap.ini +[H700 Gamepad] +plugged = True +mouse = False +AnalogDeadzone = 0,0 +AnalogPeak = 32768,32768 +DPad R = button(16) +DPad L = button(15) +DPad D = button(14) +DPad U = button(13) +Start = button(9) +Z Trig = button(4) +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(6) +Mempak switch = +Rumblepak switch = +# Analog axis configuration mappings +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) diff --git a/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/InputAutoCfg.ini b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/InputAutoCfg.ini new file mode 100644 index 0000000000..e4de820adc --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/InputAutoCfg.ini @@ -0,0 +1,2073 @@ +; 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+) diff --git a/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/InputPlumber/default.ini b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/InputPlumber/default.ini new file mode 100644 index 0000000000..ee081da6c6 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/InputPlumber/default.ini @@ -0,0 +1,23 @@ +[Xbox Series X 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+,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+) diff --git a/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/InputPlumber/zlswap.ini b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/InputPlumber/zlswap.ini new file mode 100644 index 0000000000..2334eb3a4f --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/InputPlumber/zlswap.ini @@ -0,0 +1,23 @@ +[Xbox Series X 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 = button(4) +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 = axis(2+) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) diff --git a/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/RK3326/default.ini b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/RK3326/default.ini new file mode 100644 index 0000000000..b62b91ecef --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/RK3326/default.ini @@ -0,0 +1,225 @@ +; RK3326 Gamepad - default.ini +[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 = 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 = +# Analog axis configuration mappings +X Axis = axis(0+,0-) +Y Axis = axis(1+,1-) + +[odroidgo2_joypad] +plugged = True +mouse = False +AnalogDeadzone = 0,0 +AnalogPeak = 32768,32768 +DPad R = button(9) +DPad L = button(8) +DPad D = button(7) +DPad U = button(6) +Start = button(13) +Z Trig = button(4) +B Button = button(3) +A Button = button(0) +C Button R = button(11) +C Button L = button(1) +C Button D = button(12) +C Button U = button(2) +R Trig = button(5) +L Trig = +Mempak switch = +Rumblepak switch = +# Analog axis configuration mappings +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[odroidgo2_v11_joypad] +plugged = True +mouse = False +AnalogDeadzone = 0,0 +AnalogPeak = 32768,32768 +DPad R = button(15) +DPad L = button(14) +DPad D = button(13) +DPad U = button(12) +Start = button(8) +Z Trig = button(4) +B Button = button(3) +A Button = button(0) +C Button R = button(9) +C Button L = button(11) +C Button D = button(1) +C Button U = button(2) +R Trig = button(5) +L Trig = button(6) +Mempak switch = +Rumblepak switch = +# Analog axis configuration mappings +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[retrogame_joypad_s1_f2] +plugged = True +mouse = False +AnalogDeadzone = 0,0 +AnalogPeak = 32768,32768 +DPad R = button(16) +DPad L = button(15) +DPad D = button(14) +DPad U = button(13) +Start = button(9) +Z Trig = button(4) +B Button = button(3) +A Button = button(1) +C Button R = button(9) +C Button L = button(11) +C Button D = button(0) +C Button U = button(2) +R Trig = button(5) +L Trig = button(6) +Mempak switch = +Rumblepak switch = +# Analog axis configuration mappings +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[odroidgo3_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(13) +Z Trig = button(4) +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 = button(5) +L Trig = button(6) +Mempak switch = +Rumblepak switch = +# Analog axis configuration mappings +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[r33s_joypad] +plugged = True +mouse = False +AnalogDeadzone = 0,0 +AnalogPeak = 32768,32768 +DPad R = +DPad L = +DPad D = +DPad U = +Start = button(9) +Z Trig = button(4) +B Button = button(3) +A Button = button(0) +C Button R = button(7) +C Button L = button(6) +C Button D = button(1) +C Button U = button(2) +R Trig = button(5) +L Trig = button(4) +Mempak switch = +Rumblepak switch = +# Analog axis configuration mappings +X Axis = button(12,13)axis(0-,0+) +Y Axis = button(10,11)axis(1-,1+) + +[r36s_Gamepad] +plugged = True +mouse = False +AnalogDeadzone = 0,0 +AnalogPeak = 32768,32768 +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(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 = button(5) +L Trig = button(4) +Mempak switch = +Rumblepak switch = +# Analog axis configuration mappings +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[XU10 Gamepad] +plugged = True +mouse = False +AnalogDeadzone = 0,0 +AnalogPeak = 32768, 32768 +DPad R = button(15) +DPad L = button(14) +DPad D = button(13) +DPad U = button(12) +Start = button(9) +Z Trig = button(7) +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 = +#Analog axis configuration mappings +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[XU Mini M Gamepad] +plugged = True +mouse = False +AnalogDeadzone = 0,0 +AnalogPeak = 28000, 28000 +DPad R = button(15) +DPad L = button(14) +DPad D = button(13) +DPad U = button(12) +Start = button(9) +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(2-) +C Button U = axis(2+) +R Trig = button(5) +L Trig = button(6) +Mempak switch = +Rumblepak switch = +#Analog axis configuration mappings +X Axis = axis(1-,1+) +Y Axis = axis(0+,0-) diff --git a/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/RK3326/zlswap.ini b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/RK3326/zlswap.ini new file mode 100644 index 0000000000..f6edd414f7 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/RK3326/zlswap.ini @@ -0,0 +1,25 @@ +; RG351P Gamepad - zlswap.ini +[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(4) +B Button = button(3) +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(9) +Mempak switch = +Rumblepak switch = +# Analog axis configuration mappings +X Axis = axis(0+,0-) +Y Axis = axis(1+,1-) diff --git a/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/RK3399/default.ini b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/RK3399/default.ini new file mode 100644 index 0000000000..c062c8c8c4 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/RK3399/default.ini @@ -0,0 +1,25 @@ +; RG552 Gamepad - default.ini +[rg552_joypad] +plugged = True +mouse = False +AnalogDeadzone = 0,0 +AnalogPeak = 32768,32768 +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(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 = button(5) +L Trig = button(4) +Mempak switch = +Rumblepak switch = +# Analog axis configuration mappings +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) diff --git a/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/RK3399/zlswap.ini b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/RK3399/zlswap.ini new file mode 100644 index 0000000000..6735db0daa --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/RK3399/zlswap.ini @@ -0,0 +1,25 @@ +; RG552 Gamepad - zlswap.ini +[rg552_joypad] +plugged = True +mouse = False +AnalogDeadzone = 0,0 +AnalogPeak = 32768,32768 +DPad R = button(16) +DPad L = button(15) +DPad D = button(14) +DPad U = button(13) +Start = button(9) +Z Trig = button(4) +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 = button(5) +L Trig = button(6) +Mempak switch = +Rumblepak switch = +# Analog axis configuration mappings +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) diff --git a/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/RK3566/default.ini b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/RK3566/default.ini new file mode 100644 index 0000000000..97ef8f71a6 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/RK3566/default.ini @@ -0,0 +1,51 @@ +; RG552 Gamepad - default.ini +[retrogame_joypad] +plugged = True +mouse = False +AnalogDeadzone = 0,0 +AnalogPeak = 32768,32768 +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(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 = button(5) +L Trig = button(4) +Mempak switch = +Rumblepak switch = +# Analog axis configuration mappings +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +; RG ARC Gamepad - default.ini +[rg_arc_joypad] +plugged = True +mouse = False +AnalogDeadzone = 0,0 +AnalogPeak = 32768,32768 +DPad R = +DPad L = +DPad D = +DPad U = +Start = button(11) +Z Trig = button(8) +B Button = button(3) +A Button = button(1) +C Button R = button(2) +C Button L = button(4) +C Button D = button(0) +C Button U = button(5) +R Trig = button(7) +L Trig = button(6) +Mempak switch = +Rumblepak switch = +# Analog axis configuration mappings +X Axis = button(14,15) +Y Axis = button(12,13) diff --git a/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/RK3566/zlswap.ini b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/RK3566/zlswap.ini new file mode 100644 index 0000000000..7606cad774 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/RK3566/zlswap.ini @@ -0,0 +1,25 @@ +; RG552 Gamepad - zlswap.ini +[retrogame_joypad] +plugged = True +mouse = False +AnalogDeadzone = 0,0 +AnalogPeak = 32768,32768 +DPad R = button(16) +DPad L = button(15) +DPad D = button(14) +DPad U = button(13) +Start = button(9) +Z Trig = button(4) +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 = button(5) +L Trig = button(6) +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/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/RK3588/default.ini b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/RK3588/default.ini new file mode 100644 index 0000000000..02591396c9 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/RK3588/default.ini @@ -0,0 +1,25 @@ +; GameForce ACE Gamepad - default.ini +[GameForce ACE Gamepad] +plugged = True +mouse = False +AnalogDeadzone = 0,0 +AnalogPeak = 32768,32768 +DPad R = button(15) +DPad L = button(14) +DPad D = button(13) +DPad U = button(12) +Start = button(8) +Z Trig = axis(5-) +B Button = button(4) +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(6) +L Trig = button(5) +Mempak switch = +Rumblepak switch = +# Analog axis configuration mappings +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) diff --git a/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/RK3588/zlswap.ini b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/RK3588/zlswap.ini new file mode 100644 index 0000000000..869358f338 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/RK3588/zlswap.ini @@ -0,0 +1,25 @@ +; GameForce ACE Gamepad - default.ini +[GameForce ACE Gamepad] +plugged = True +mouse = False +AnalogDeadzone = 0,0 +AnalogPeak = 32768,32768 +DPad R = button(15) +DPad L = button(14) +DPad D = button(13) +DPad U = button(12) +Start = button(8) +Z Trig = button(5) +B Button = button(4) +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(6) +L Trig = axis(2-) +Mempak switch = +Rumblepak switch = +# Analog axis configuration mappings +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) diff --git a/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/S922X/default.ini b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/S922X/default.ini new file mode 100644 index 0000000000..27ad6e29af --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/S922X/default.ini @@ -0,0 +1,21 @@ +[GO-Ultra Gamepad] +plugged = True +mouse = False +AnalogDeadzone = 0,0 +AnalogPeak = 32768,32768 +DPad R = button(17) +DPad L = button(16) +DPad D = button(15) +DPad U = button(14) +Start = button(10) +Z Trig = button(5) button(8) +B Button = button(4) +A Button = button(0) +C Button R = axis(2+) +C Button L = axis(2-) button (2) +C Button D = axis(3+) button (1) +C Button U = axis(3-) +R Trig = button(6) +L Trig = button(7) +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) diff --git a/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/SDM845/default.ini b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/SDM845/default.ini new file mode 100644 index 0000000000..348e7a61f3 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/SDM845/default.ini @@ -0,0 +1,25 @@ +; AYN Odin Gamepad - default.ini +[AYN Odin Gamepad] +plugged = True +mouse = False +AnalogDeadzone = 0,0 +AnalogPeak = 32768,32768 +DPad R = button(16) +DPad L = button(15) +DPad D = button(14) +DPad U = button(13) +Start = button(9) +Z Trig = axis(5+) +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 = button(5) +L Trig = button(4) +Mempak switch = +Rumblepak switch = +# Analog axis configuration mappings +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) diff --git a/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/SDM845/zlswap.ini b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/SDM845/zlswap.ini new file mode 100644 index 0000000000..348e7a61f3 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/SDM845/zlswap.ini @@ -0,0 +1,25 @@ +; AYN Odin Gamepad - default.ini +[AYN Odin Gamepad] +plugged = True +mouse = False +AnalogDeadzone = 0,0 +AnalogPeak = 32768,32768 +DPad R = button(16) +DPad L = button(15) +DPad D = button(14) +DPad U = button(13) +Start = button(9) +Z Trig = axis(5+) +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 = button(5) +L Trig = button(4) +Mempak switch = +Rumblepak switch = +# Analog axis configuration mappings +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) diff --git a/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/SM8250/default.ini b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/SM8250/default.ini new file mode 100644 index 0000000000..351da05b4e --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/SM8250/default.ini @@ -0,0 +1,25 @@ +; Retroid Pocket Gamepad - default.ini +[Retroid Pocket Gamepad] +plugged = True +mouse = False +AnalogDeadzone = 0,0 +AnalogPeak = 32768,32768 +DPad R = button(14) +DPad L = button(13) +DPad D = button(12) +DPad U = button(11) +Start = button(7) +Z Trig = axis(7+) +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 = +# Analog axis configuration mappings +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) diff --git a/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/SM8250/zlswap.ini b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/SM8250/zlswap.ini new file mode 100644 index 0000000000..6735db0daa --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/SM8250/zlswap.ini @@ -0,0 +1,25 @@ +; RG552 Gamepad - zlswap.ini +[rg552_joypad] +plugged = True +mouse = False +AnalogDeadzone = 0,0 +AnalogPeak = 32768,32768 +DPad R = button(16) +DPad L = button(15) +DPad D = button(14) +DPad U = button(13) +Start = button(9) +Z Trig = button(4) +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 = button(5) +L Trig = button(6) +Mempak switch = +Rumblepak switch = +# Analog axis configuration mappings +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) diff --git a/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/SM8550 b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/SM8550 new file mode 120000 index 0000000000..72081d3859 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/SM8550 @@ -0,0 +1 @@ +InputPlumber \ No newline at end of file diff --git a/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/SM8650 b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/SM8650 new file mode 120000 index 0000000000..72081d3859 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/config/SM8650 @@ -0,0 +1 @@ +InputPlumber \ No newline at end of file diff --git a/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/package.mk b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/package.mk new file mode 100644 index 0000000000..03f390b427 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-input-sdl/package.mk @@ -0,0 +1,77 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2023 Nicholas Ricciuti (rishooty@gmail.com) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="mupen64plus-sa-input-sdl" +PKG_VERSION="3698a2b12b1dc536801649de2705b4a79ffb8a08" +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 libpng SDL2 SDL2_net zlib freetype nasm:host mupen64plus-sa-core" +PKG_LONGDESC="mupen64plus-input-sdl" +PKG_LONGDESC="Mupen64Plus Standalone Input SDL" +PKG_TOOLCHAIN="manual" + +case ${DEVICE} in + RK3588|S922X|RK3399|RK3566*|SM8250|SM8550|SM8650) + PKG_DEPENDS_TARGET+=" mupen64plus-sa-simplecore" + ;; +esac + +case ${DEVICE} in + *) + PKG_DEPENDS_TARGET+=" ${OPENGLES}" + export USE_GLES=1 + ;; +esac + +make_target() { + + export HOST_CPU=${TARGET_ARCH} \ + NEW_DYNAREC=1 \ + VFP_HARD=1 \ + V=1 \ + VC=0 \ + OSD=0 + + export BINUTILS="$(get_build_dir binutils)/.${TARGET_NAME}" + export SDL_CFLAGS="-I${SYSROOT_PREFIX}/usr/include/SDL2 -pthread -D_REENTRANT" + export SDL_LDLIBS="-lSDL2_net -lSDL2" + export CROSS_COMPILE="${TARGET_PREFIX}" + + export APIDIR=$(get_build_dir mupen64plus-sa-core)/src/api + + sed -i 's/\-O[23]/-Ofast/' ${PKG_BUILD}/projects/unix/Makefile + + make -C projects/unix clean + make -C projects/unix all ${PKG_MAKE_OPTS_TARGET} + cp ${PKG_BUILD}/projects/unix/mupen64plus-input-sdl.so ${PKG_BUILD}/projects/unix/mupen64plus-input-sdl-base.so + + case ${DEVICE} in + RK3588|S922X|RK3399|RK3566*|SM8250|SM8550|SM8650) + export APIDIR=$(get_build_dir mupen64plus-sa-simplecore)/src/api + make -C projects/unix all ${PKG_MAKE_OPTS_TARGET} + cp ${PKG_BUILD}/projects/unix/mupen64plus-input-sdl.so ${PKG_BUILD}/projects/unix/mupen64plus-input-sdl-simple.so + ;; + esac +} + +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-base.so ${UPLUGINDIR}/mupen64plus-input-sdl.so + chmod 0644 ${UPLUGINDIR}/mupen64plus-input-sdl.so + + if [ -e "${PKG_BUILD}/projects/unix/mupen64plus-input-sdl-simple.so" ] + then + cp ${PKG_BUILD}/projects/unix/mupen64plus-input-sdl-simple.so ${UPLUGINDIR} + chmod 0644 ${UPLUGINDIR}/mupen64plus-input-sdl-simple.so + fi + + mkdir -p ${USHAREDIR} + cp ${PKG_DIR}/config/${DEVICE}/* ${USHAREDIR} +} diff --git a/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-rsp-cxd4/package.mk b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-rsp-cxd4/package.mk new file mode 100644 index 0000000000..6c15eb0186 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-rsp-cxd4/package.mk @@ -0,0 +1,86 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2023 Nicholas Ricciuti (rishooty@gmail.com) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="mupen64plus-sa-rsp-cxd4" +PKG_VERSION="f6ff3719cb68d3e1c1497fc87a661921671db719" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/mupen64plus/mupen64plus-rsp-cxd4" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain libpng SDL2 SDL2_net zlib freetype nasm:host mupen64plus-sa-core" +PKG_LONGDESC="mupen64plus-rsp-cxd4" +PKG_LONGDESC="Mupen64Plus Standalone RSP CXD4" +PKG_TOOLCHAIN="manual" +PKG_BUILD_FLAGS="-fpic" + +case ${DEVICE} in + RK3588|S922X|RK3399|RK3566*|SM8250|SM8550|SM8650) + PKG_DEPENDS_TARGET+=" mupen64plus-sa-simplecore" + ;; +esac + +case ${DEVICE} in + SM8250|SM8550|SM8650) + PKG_DEPENDS_TARGET+=" ${OPENGL} glu libglvnd" + export USE_GLES=0 + ;; + *) + PKG_DEPENDS_TARGET+=" ${OPENGLES}" + export USE_GLES=1 + ;; +esac + +make_target() { + + export HOST_CPU=${TARGET_ARCH} \ + NEW_DYNAREC=1 \ + VFP_HARD=1 \ + HLEVIDEO=1 \ + V=1 \ + VC=0 \ + OSD=0 + + case ${TARGET_ARCH} in + x86_64) + export SUFFIX="-sse2" + ;; + esac + + export BINUTILS="$(get_build_dir binutils)/.${TARGET_NAME}" + export APIDIR=$(get_build_dir mupen64plus-sa-core)/src/api + export SDL_CFLAGS="-I${SYSROOT_PREFIX}/usr/include/SDL2 -pthread -D_REENTRANT" + export SDL_LDLIBS="-lSDL2_net -lSDL2" + export CROSS_COMPILE="${TARGET_PREFIX}" + + sed -i 's/\-O[23]/-Ofast/' ${PKG_BUILD}/projects/unix/Makefile + + make -C projects/unix clean + make -C projects/unix all ${PKG_MAKE_OPTS_TARGET} + cp ${PKG_BUILD}/projects/unix/mupen64plus-rsp-cxd4${SUFFIX}.so ${PKG_BUILD}/projects/unix/mupen64plus-rsp-cxd4-base.so + + case ${DEVICE} in + RK3588|S922X|RK3399|RK3566*|SM8250|SM8550|SM8650) + PKG_MAKE_OPTS_TARGET+=" cxd4VIDEO=1" + export APIDIR=$(get_build_dir mupen64plus-sa-simplecore)/src/api + make -C projects/unix all ${PKG_MAKE_OPTS_TARGET} + cp ${PKG_BUILD}/projects/unix/mupen64plus-rsp-cxd4${SUFFIX}.so ${PKG_BUILD}/projects/unix/mupen64plus-rsp-cxd4-simple.so + ;; + esac +} + +makeinstall_target() { + UPREFIX=${INSTALL}/usr/local + ULIBDIR=${UPREFIX}/lib + UPLUGINDIR=${ULIBDIR}/mupen64plus + mkdir -p ${UPLUGINDIR} + cp ${PKG_BUILD}/projects/unix/mupen64plus-rsp-cxd4-base.so ${UPLUGINDIR}/mupen64plus-rsp-cxd4.so + chmod 0644 ${UPLUGINDIR}/mupen64plus-rsp-cxd4.so + + if [ -e "${PKG_BUILD}/projects/unix/mupen64plus-rsp-cxd4-simple.so" ] + then + cp ${PKG_BUILD}/projects/unix/mupen64plus-rsp-cxd4-simple.so ${UPLUGINDIR} + chmod 0644 ${UPLUGINDIR}/mupen64plus-rsp-cxd4-simple.so + fi +} + diff --git a/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-rsp-hle/package.mk b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-rsp-hle/package.mk new file mode 100644 index 0000000000..30791062a2 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-rsp-hle/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) 2023 Nicholas Ricciuti (rishooty@gmail.com) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="mupen64plus-sa-rsp-hle" +PKG_VERSION="9d13986f764b14bb4fb8eaa5846ff8be5a9fa4f6" +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 libpng SDL2 SDL2_net zlib freetype nasm:host mupen64plus-sa-core" +PKG_LONGDESC="mupen64plus-rsp-hle" +PKG_LONGDESC="Mupen64Plus Standalone RSP HLE" +PKG_TOOLCHAIN="manual" + +case ${DEVICE} in + RK3588|S922X|RK3399|RK3566*) + PKG_DEPENDS_TARGET+=" mupen64plus-sa-simplecore" + ;; +esac + +case ${DEVICE} in + *) + PKG_DEPENDS_TARGET+=" ${OPENGLES}" + export USE_GLES=1 + ;; +esac + +make_target() { + + export HOST_CPU=${TARGET_ARCH} \ + NEW_DYNAREC=1 \ + VFP_HARD=1 \ + V=1 \ + VC=0 \ + OSD=0 + + export BINUTILS="$(get_build_dir binutils)/.${TARGET_NAME}" + export APIDIR=$(get_build_dir mupen64plus-sa-core)/src/api + export SDL_CFLAGS="-I${SYSROOT_PREFIX}/usr/include/SDL2 -pthread -D_REENTRANT" + export SDL_LDLIBS="-lSDL2_net -lSDL2" + export CROSS_COMPILE="${TARGET_PREFIX}" + + sed -i 's/\-O[23]/-Ofast/' ${PKG_BUILD}/projects/unix/Makefile + + make -C projects/unix clean + make -C projects/unix all ${PKG_MAKE_OPTS_TARGET} + cp ${PKG_BUILD}/projects/unix/mupen64plus-rsp-hle.so ${PKG_BUILD}/projects/unix/mupen64plus-rsp-hle-base.so + + case ${DEVICE} in + RK3588|S922X|RK3399|RK3566*) + export APIDIR=$(get_build_dir mupen64plus-sa-simplecore)/src/api + make -C projects/unix all ${PKG_MAKE_OPTS_TARGET} + cp ${PKG_BUILD}/projects/unix/mupen64plus-rsp-hle.so ${PKG_BUILD}/projects/unix/mupen64plus-rsp-hle-simple.so + ;; + esac +} + +makeinstall_target() { + UPREFIX=${INSTALL}/usr/local + ULIBDIR=${UPREFIX}/lib + UPLUGINDIR=${ULIBDIR}/mupen64plus + mkdir -p ${UPLUGINDIR} + cp ${PKG_BUILD}/projects/unix/mupen64plus-rsp-hle-base.so ${UPLUGINDIR}/mupen64plus-rsp-hle.so + chmod 0644 ${UPLUGINDIR}/mupen64plus-rsp-hle.so + + if [ -e "${PKG_BUILD}/projects/unix/mupen64plus-rsp-hle-simple.so" ] + then + cp ${PKG_BUILD}/projects/unix/mupen64plus-rsp-hle-simple.so ${UPLUGINDIR} + chmod 0644 ${UPLUGINDIR}/mupen64plus-rsp-hle-simple.so + fi +} + diff --git a/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-simplecore/package.mk b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-simplecore/package.mk new file mode 100644 index 0000000000..546e11102e --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-simplecore/package.mk @@ -0,0 +1,61 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2023 Nicholas Ricciuti (rishooty@gmail.com) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="mupen64plus-sa-simplecore" +PKG_VERSION="5340dafcc0f5e8284057ab931dd5c66222d3d49e" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/simple64/mupen64plus-core" +PKG_URL="https://github.com/simple64/mupen64plus-core/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain boost libpng SDL2 SDL2_net zlib freetype nasm:host mupen64plus-sa-core" +PKG_LONGDESC="simple64" +PKG_LONGDESC="Simple64's core" +PKG_TOOLCHAIN="manual" +PKG_GIT_CLONE_BRANCH="simple64" + +case ${DEVICE} in + SM8250|SM8550|SM8650) + PKG_DEPENDS_TARGET+=" ${OPENGL} glu libglvnd" + export USE_GLES=0 + ;; + *) + PKG_DEPENDS_TARGET+=" ${OPENGLES}" + export USE_GLES=1 + ;; +esac + +make_target() { +# export TARGET_CLFAGS="${TARGET_CFLAGS} -Wno-implicit-function-declaration -Wno-error=incompatible-pointer-types" +# export TARGET_CXXLFAGS="${TARGET_CXXFLAGS} -Wno-implicit-function-declaration -Wno-error=incompatible-pointer-types" + case ${ARCH} in + arm|aarch64) + export HOST_CPU=aarch64 + ARM="-DARM=1" + ;; + x86_64) + export HOST_CPU=x86_64 + unset ARM + ;; + esac + + # Always diable Vulkan + PKG_MAKE_OPTS_TARGET+=" VULKAN=0" + + export BINUTILS="$(get_build_dir binutils)/.${TARGET_NAME}" + export NEW_DYNAREC=1 + export SDL_CFLAGS="-I${SYSROOT_PREFIX}/usr/include/SDL2 -pthread -D_REENTRANT" + export SDL_LDLIBS="-lSDL2_net -lSDL2" + export CROSS_COMPILE="${TARGET_PREFIX}" + + sed -i 's/\-O[23]/-Ofast/' ${PKG_BUILD}/projects/unix/Makefile + + make -C projects/unix clean ${PKG_MAKE_OPTS_TARGET} + make -C projects/unix all ${PKG_MAKE_OPTS_TARGET} +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/local/lib + cp ${PKG_BUILD}/projects/unix/libsimple64.so.2.0.0 ${INSTALL}/usr/local/lib/libsimple64.so.2 + chmod 644 ${INSTALL}/usr/local/lib/libsimple64.so.2 +} diff --git a/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-simplecore/patches/000-cross-compile.patch b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-simplecore/patches/000-cross-compile.patch new file mode 100644 index 0000000000..b10ab24c59 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-simplecore/patches/000-cross-compile.patch @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Frank Hartung (supervisedthinking (@) gmail.com) + +--- a/projects/unix/Makefile ++++ b/projects/unix/Makefile +@@ -320,7 +320,7 @@ + + # test for presence of SDL + ifeq ($(origin SDL_CFLAGS) $(origin SDL_LDLIBS), undefined undefined) +- SDL_CONFIG = $(CROSS_COMPILE)sdl2-config ++ SDL_CONFIG = $(SYSROOT_PREFIX)/usr/bin/sdl2-config + ifeq ($(shell which $(SDL_CONFIG) 2>/dev/null),) + SDL_CONFIG = $(CROSS_COMPILE)sdl-config + ifeq ($(shell which $(SDL_CONFIG) 2>/dev/null),) +@@ -403,9 +403,6 @@ + endif + + # set base program pointers and flags +-CC = $(CROSS_COMPILE)gcc +-CXX = $(CROSS_COMPILE)g++ +-STRINGS = $(CROSS_COMPILE)strings + AS = nasm + TR ?= tr + RM ?= rm -f diff --git a/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-simplecore/patches/001-librename.patch b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-simplecore/patches/001-librename.patch new file mode 100644 index 0000000000..5d8947b772 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-simplecore/patches/001-librename.patch @@ -0,0 +1,15 @@ +diff --git a/projects/unix/Makefile b/projects/unix/Makefile +index 2222fe78..0fec2cbe 100755 +--- a/projects/unix/Makefile ++++ b/projects/unix/Makefile +@@ -209,8 +209,8 @@ ifeq ($(OS), FREEBSD) + endif + endif + ifeq ($(OS), LINUX) +- TARGET = libmupen64plus$(POSTFIX).so.2.0.0 +- SONAME = libmupen64plus$(POSTFIX).so.2 ++ TARGET = libsimple64$(POSTFIX).so.2.0.0 ++ SONAME = libsimple64$(POSTFIX).so.2 + LDFLAGS += -Wl,-Bsymbolic -shared -Wl,-export-dynamic -Wl,-soname,$(SONAME) + LDLIBS += -ldl + # only export api symbols diff --git a/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-ui-console/package.mk b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-ui-console/package.mk new file mode 100644 index 0000000000..44a33b47d7 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-ui-console/package.mk @@ -0,0 +1,91 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2023 Nicholas Ricciuti (rishooty@gmail.com) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="mupen64plus-sa-ui-console" +PKG_VERSION="1340c4bdfc9ec53d3fccda5e085930dd79eb08b3" +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 libpng SDL2 SDL2_net zlib freetype nasm:host mupen64plus-sa-core" +PKG_LONGDESC="mupen64plus-ui-console" +PKG_LONGDESC="Mupen64Plus Standalone Console" +PKG_TOOLCHAIN="manual" + +case ${DEVICE} in + RK3588|S922X|RK3399|RK3566*|SM8250|SM8550|SM8650) + PKG_DEPENDS_TARGET+=" mupen64plus-sa-simplecore" + ;; +esac + +case ${DEVICE} in + SM8250|SM8550|SM8650) + PKG_DEPENDS_TARGET+=" ${OPENGL} glu libglvnd" + export USE_GLES=0 + ;; + *) + PKG_DEPENDS_TARGET+=" ${OPENGLES}" + export USE_GLES=1 + ;; +esac + +make_target() { + export CFLAGS="${CFLAGS} -Wno-error=incompatible-pointer-types" + + export V=1 \ + VC=0 + + export BINUTILS="$(get_build_dir binutils)/.${TARGET_NAME}" + export APIDIR=$(get_build_dir mupen64plus-sa-core)/src/api + export SDL_CFLAGS="-I${SYSROOT_PREFIX}/usr/include/SDL2 -pthread -D_REENTRANT" + export SDL_LDLIBS="-lSDL2_net -lSDL2" + export CROSS_COMPILE="${TARGET_PREFIX}" + + sed -i 's/\-O[23]/-Ofast/' ${PKG_BUILD}/projects/unix/Makefile + + make -C projects/unix clean + make -C projects/unix all ${PKG_MAKE_OPTS_TARGET} + cp ${PKG_BUILD}/projects/unix/mupen64plus ${PKG_BUILD}/projects/unix/mupen64plus-base + + case ${DEVICE} in + RK3588|S922X|RK3399|RK3566*|SM8250|SM8550|SM8650) + export APIDIR=$(get_build_dir mupen64plus-sa-simplecore)/src/api + export CFLAGS="${CFLAGS} -DSIMPLECORE" + make -C projects/unix all ${PKG_MAKE_OPTS_TARGET} + cp ${PKG_BUILD}/projects/unix/mupen64plus ${PKG_BUILD}/projects/unix/mupen64plus-simple + ;; + esac +} + +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-base ${UBINDIR}/mupen64plus + chmod 0755 ${UBINDIR}/mupen64plus + + if [ -e "${PKG_BUILD}/projects/unix/mupen64plus-simple" ] + then + cp ${PKG_BUILD}/projects/unix/mupen64plus-simple ${UBINDIR} + chmod 0755 ${UBINDIR}/mupen64plus-simple + fi + + 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/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-video-glide64mk2/package.mk b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-video-glide64mk2/package.mk new file mode 100644 index 0000000000..093fc8c9d2 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-video-glide64mk2/package.mk @@ -0,0 +1,82 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2023 Nicholas Ricciuti (rishooty@gmail.com) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="mupen64plus-sa-video-glide64mk2" +PKG_VERSION="992b5942078fe77987e8c40bcd396f44be19be2b" +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 boost libpng SDL2 SDL2_net zlib freetype nasm:host mupen64plus-sa-core" +PKG_LONGDESC="mupen64plus-video-glide64mk2" +PKG_LONGDESC="Mupen64Plus Standalone Glide64 Video Driver" +PKG_TOOLCHAIN="manual" + +case ${DEVICE} in + RK3588|S922X|RK3399|RK3566*|SM8250|SM8550|SM8650) + PKG_DEPENDS_TARGET+=" mupen64plus-sa-simplecore" + ;; +esac + +case ${DEVICE} in + SM8250|SM8550|SM8650) + PKG_DEPENDS_TARGET+=" ${OPENGL} glu libglvnd" + export USE_GLES=0 + ;; + *) + PKG_DEPENDS_TARGET+=" ${OPENGLES}" + export USE_GLES=1 + ;; +esac + +make_target() { + + export HOST_CPU=${TARGET_ARCH} \ + NEW_DYNAREC=1 \ + VFP_HARD=1 \ + V=1 \ + VC=0 \ + OSD=0 + + export BINUTILS="$(get_build_dir binutils)/.${TARGET_NAME}" + export APIDIR=$(get_build_dir mupen64plus-sa-core)/src/api + export SDL_CFLAGS="-I${SYSROOT_PREFIX}/usr/include/SDL2 -pthread -D_REENTRANT" + export SDL_LDLIBS="-lSDL2_net -lSDL2" + export CROSS_COMPILE="${TARGET_PREFIX}" + + sed -i 's/\-O[23]/-Ofast/' ${PKG_BUILD}/projects/unix/Makefile + + make -C projects/unix clean + make -C projects/unix all ${PKG_MAKE_OPTS_TARGET} + cp ${PKG_BUILD}/projects/unix/mupen64plus-video-glide64mk2.so ${PKG_BUILD}/projects/unix/mupen64plus-video-glide64mk2-base.so + + case ${DEVICE} in + RK3588|S922X|RK3399|RK3566*|SM8250|SM8550|SM8650) + export APIDIR=$(get_build_dir mupen64plus-sa-simplecore)/src/api + make -C projects/unix all ${PKG_MAKE_OPTS_TARGET} + cp ${PKG_BUILD}/projects/unix/mupen64plus-video-glide64mk2.so ${PKG_BUILD}/projects/unix/mupen64plus-video-glide64mk2-simple.so + ;; + esac +} + +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-base.so ${UPLUGINDIR}/mupen64plus-video-glide64mk2.so + chmod 0644 ${UPLUGINDIR}/mupen64plus-video-glide64mk2.so + + if [ -e "${PKG_BUILD}/projects/unix/mupen64plus-video-glide64mk2-simple.so" ] + then + cp ${PKG_BUILD}/projects/unix/mupen64plus-video-glide64mk2-simple.so ${UPLUGINDIR} + chmod 0644 ${UPLUGINDIR}/mupen64plus-video-glide64mk2-simple.so + fi + + mkdir -p ${USHAREDIR} + cp ${PKG_BUILD}/data/Glide64mk2.ini ${USHAREDIR} + chmod 0644 ${USHAREDIR}/Glide64mk2.ini +} + diff --git a/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-video-gliden64/package.mk b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-video-gliden64/package.mk new file mode 100644 index 0000000000..c93c8b8672 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-video-gliden64/package.mk @@ -0,0 +1,83 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2023 Nicholas Ricciuti (rishooty@gmail.com) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="mupen64plus-sa-video-gliden64" +PKG_VERSION="85bdd452d7090f78a0f76d02121fa59ad079b7f6" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/gonetz/GLideN64" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain boost libpng SDL2 SDL2_net zlib freetype nasm:host mupen64plus-sa-core" +PKG_LONGDESC="mupen64plus-video-gliden64" +PKG_LONGDESC="Mupen64Plus Standalone GLide64 Video Driver" +PKG_TOOLCHAIN="manual" + +case ${DEVICE} in + RK3588|S922X|RK3399|RK3566*|SM8250|SM8550|SM8650) + PKG_DEPENDS_TARGET+=" mupen64plus-sa-simplecore" + ;; +esac + +case ${DEVICE} in + SM8250|SM8550|SM8650) + PKG_DEPENDS_TARGET+=" ${OPENGL} glu libglvnd" + export USE_GLES=0 + ;; + *) + PKG_DEPENDS_TARGET+=" ${OPENGLES}" + export USE_GLES=1 + ;; +esac + +make_target() { + + export HOST_CPU=${TARGET_ARCH} \ + NEW_DYNAREC=1 \ + VFP_HARD=1 \ + V=1 \ + VC=0 \ + OSD=0 + + case ${TARGET_ARCH} in + arm|aarch64) + PKG_MAKE_OPTS_TARGET+="-DNOHQ=On -DCRC_ARMV8=On -DEGL=On -DNEON_OPT=On" + ;; + esac + + export BINUTILS="$(get_build_dir binutils)/.${TARGET_NAME}" + export APIDIR=$(get_build_dir mupen64plus-sa-core)/src/api + export SDL_CFLAGS="-I${SYSROOT_PREFIX}/usr/include/SDL2 -pthread -D_REENTRANT" + export SDL_LDLIBS="-lSDL2_net -lSDL2" + export CROSS_COMPILE="${TARGET_PREFIX}" + + sed -i 's/\-O[23]/-Ofast/' ${PKG_BUILD}/src/CMakeLists.txt + + ./src/getRevision.sh + cmake ${PKG_MAKE_OPTS_TARGET} -DAPIDIR=${APIDIR} -DMUPENPLUSAPI=On -DGLIDEN64_BUILD_TYPE=Release -DCMAKE_C_COMPILER="${CC}" -DCMAKE_CXX_COMPILER="${CXX}" -DCMAKE_C_FLAGS="${CFLAGS}" -DCMAKE_CXX_FLAGS="${CXXFLAGS} -pthread" -S src -B projects/cmake + make clean -C projects/cmake + make -Wno-unused-variable -C projects/cmake + cp ${PKG_BUILD}/projects/cmake/plugin/Release/mupen64plus-video-GLideN64.so ${PKG_BUILD}/projects/cmake/plugin/Release/mupen64plus-video-GLideN64-base.so + + export APIDIR=$(get_build_dir mupen64plus-sa-simplecore)/src/api + cmake ${PKG_MAKE_OPTS_TARGET} -DAPIDIR=${APIDIR} -DMUPENPLUSAPI=On -DGLIDEN64_BUILD_TYPE=Release -DCMAKE_C_COMPILER="${CC}" -DCMAKE_CXX_COMPILER="${CXX}" -DCMAKE_C_FLAGS="${CFLAGS}" -DCMAKE_CXX_FLAGS="${CXXFLAGS} -pthread" -S src -B projects/cmake + make -Wno-unused-variable -C projects/cmake + cp ${PKG_BUILD}/projects/cmake/plugin/Release/mupen64plus-video-GLideN64.so ${PKG_BUILD}/projects/cmake/plugin/Release/mupen64plus-video-GLideN64-simple.so +} + +makeinstall_target() { + UPREFIX=${INSTALL}/usr/local + ULIBDIR=${UPREFIX}/lib + USHAREDIR=${UPREFIX}/share/mupen64plus + UPLUGINDIR=${ULIBDIR}/mupen64plus + mkdir -p ${UPLUGINDIR} + cp ${PKG_BUILD}/projects/cmake/plugin/Release/mupen64plus-video-GLideN64-base.so ${UPLUGINDIR}/mupen64plus-video-GLideN64.so + chmod 0644 ${UPLUGINDIR}/mupen64plus-video-GLideN64.so + + cp ${PKG_BUILD}/projects/cmake/plugin/Release/mupen64plus-video-GLideN64-simple.so ${UPLUGINDIR} + chmod 0644 ${UPLUGINDIR}/mupen64plus-video-GLideN64-simple.so + + mkdir -p ${USHAREDIR} + cp ${PKG_BUILD}/ini/GLideN64.ini ${USHAREDIR} + chmod 0644 ${USHAREDIR}/GLideN64.ini +} diff --git a/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-video-gliden64/patches/001-txfilter-stub-fix.patch b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-video-gliden64/patches/001-txfilter-stub-fix.patch new file mode 100644 index 0000000000..513e8201bb --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-video-gliden64/patches/001-txfilter-stub-fix.patch @@ -0,0 +1,30 @@ +diff --git a/src/TxFilterStub.cpp b/src/TxFilterStub.cpp +index fea57bc..fa33356 100644 +--- a/src/TxFilterStub.cpp ++++ b/src/TxFilterStub.cpp +@@ -31,12 +31,25 @@ txfilter_checksum(uint8 *src, int width, int height, int size, int rowStride, ui + return 0U; + } + ++ ++TAPI uint64 TAPIENTRY ++txfilter_checksum_strong(uint8 *src, int width, int height, int size, int rowStride, uint8 *palette) ++{ ++ return 0; ++} ++ + TAPI boolean TAPIENTRY + txfilter_dmptx(uint8 *src, int width, int height, int rowStridePixel, uint16 gfmt, N64FormatSize n64FmtSz, Checksum r_crc64) + { + return 0; + } + ++TAPI boolean TAPIENTRY ++txfilter_dmptx_strong(uint8 *src, int width, int height, int rowStridePixel, uint16 gfmt, N64FormatSize n64FmtSz, Checksum r_crc64) ++{ ++ return 0; ++} ++ + TAPI boolean TAPIENTRY + txfilter_reloadhirestex() + { diff --git a/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-video-gliden64/patches/002-fix-no-video.patch b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-video-gliden64/patches/002-fix-no-video.patch new file mode 100644 index 0000000000..5b410a6317 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-video-gliden64/patches/002-fix-no-video.patch @@ -0,0 +1,41 @@ +diff --git a/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilderCommon.cpp b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilderCommon.cpp +index 901d17ab..5ef84042 100644 +--- a/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilderCommon.cpp ++++ b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilderCommon.cpp +@@ -1004,11 +1004,11 @@ public: + ShaderNoise(const opengl::GLInfo & _glinfo) + { + m_part = +- "uniform float uNoiseSeed; \n" ++ "uniform mediump float uNoiseSeed; \n" + "lowp float snoise() \n" + "{ \n" +- " mediump vec2 coord = floor(gl_FragCoord.xy/uScreenScale); \n" +- " mediump vec3 p3 = vec3(uNoiseSeed, coord); \n" ++ " highp vec2 coord = floor(gl_FragCoord.xy/uScreenScale); \n" ++ " highp vec3 p3 = vec3(uNoiseSeed, coord); \n" + // hash13 from https://www.shadertoy.com/view/4djSRW + " p3 = fract(p3 * .1031); \n" + " p3 += dot(p3, p3.zyx + 31.32); \n" +@@ -1068,8 +1068,8 @@ public: + m_part += + " lowp float mult = 1.0; \n"; + m_part += +- " mediump vec2 coord = floor(mult * (gl_FragCoord.xy/uScreenScale)); \n" +- " mediump vec3 p3 = vec3(uNoiseSeed, coord); \n" ++ " highp vec2 coord = floor(mult * (gl_FragCoord.xy/uScreenScale)); \n" ++ " highp vec3 p3 = vec3(uNoiseSeed, coord); \n" + // hash33 from https://www.shadertoy.com/view/4djSRW + " p3 = fract(p3 * vec3(.1031, .1030, .0973)); \n" + " p3 += dot(p3, p3.yxz+33.33); \n" +@@ -1087,8 +1087,8 @@ public: + " lowp float mult = 1.0; \n"; + m_part += + " \n" +- " mediump vec2 coord = floor(mult * (gl_FragCoord.xy/uScreenScale)); \n" +- " mediump vec3 p3 = vec3(uNoiseSeed, coord); \n" ++ " highp vec2 coord = floor(mult * (gl_FragCoord.xy/uScreenScale)); \n" ++ " highp vec3 p3 = vec3(uNoiseSeed, coord); \n" + // hash13 from https://www.shadertoy.com/view/4djSRW + " p3 = fract(p3 * .1031); \n" + " p3 += dot(p3, p3.zyx + 31.32); \n" diff --git a/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-video-rice/package.mk b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-video-rice/package.mk new file mode 100644 index 0000000000..c2bb165f3d --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-video-rice/package.mk @@ -0,0 +1,82 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2023 Nicholas Ricciuti (rishooty@gmail.com) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="mupen64plus-sa-video-rice" +PKG_VERSION="470865c6c64bdb44645faa88eae59cd87ce561b6" +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 libpng SDL2 SDL2_net zlib freetype nasm:host mupen64plus-sa-core" +PKG_LONGDESC="mupen64plus-video-rice" +PKG_LONGDESC="Mupen64Plus Standalone Rice Video Driver" +PKG_TOOLCHAIN="manual" + +case ${DEVICE} in + RK3588|S922X|RK3399|RK3566*|SM8250|SM8550|SM8650) + PKG_DEPENDS_TARGET+=" mupen64plus-sa-simplecore" + ;; +esac + +case ${DEVICE} in + SM8250|SM8550|SM8650) + PKG_DEPENDS_TARGET+=" ${OPENGL} glu libglvnd" + export USE_GLES=0 + ;; + *) + PKG_DEPENDS_TARGET+=" ${OPENGLES}" + export USE_GLES=1 + ;; +esac + +make_target() { + + export HOST_CPU=${TARGET_ARCH} \ + NEW_DYNAREC=1 \ + VFP_HARD=1 \ + V=1 \ + VC=0 \ + OSD=0 + + export BINUTILS="$(get_build_dir binutils)/.${TARGET_NAME}" + export APIDIR=$(get_build_dir mupen64plus-sa-core)/src/api + export SDL_CFLAGS="-I${SYSROOT_PREFIX}/usr/include/SDL2 -pthread -D_REENTRANT" + export SDL_LDLIBS="-lSDL2_net -lSDL2" + export CROSS_COMPILE="${TARGET_PREFIX}" + + sed -i 's/\-O[23]/-Ofast/' ${PKG_BUILD}/projects/unix/Makefile + + make -C projects/unix clean + make -C projects/unix all ${PKG_MAKE_OPTS_TARGET} + cp ${PKG_BUILD}/projects/unix/mupen64plus-video-rice.so ${PKG_BUILD}/projects/unix/mupen64plus-video-rice-base.so + + case ${DEVICE} in + RK3588|S922X|RK3399|RK3566*|SM8250|SM8550|SM8650) + export APIDIR=$(get_build_dir mupen64plus-sa-simplecore)/src/api + make -C projects/unix all ${PKG_MAKE_OPTS_TARGET} + cp ${PKG_BUILD}/projects/unix/mupen64plus-video-rice.so ${PKG_BUILD}/projects/unix/mupen64plus-video-rice-simple.so + ;; + esac +} + +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-base.so ${UPLUGINDIR}/mupen64plus-video-rice.so + chmod 0644 ${UPLUGINDIR}/mupen64plus-video-rice.so + + if [ -e "${PKG_BUILD}/projects/unix/mupen64plus-video-rice-simple.so" ] + then + cp ${PKG_BUILD}/projects/unix/mupen64plus-video-rice-simple.so ${UPLUGINDIR} + chmod 0644 ${UPLUGINDIR}/mupen64plus-video-rice-simple.so + fi + + mkdir -p ${USHAREDIR} + cp ${PKG_BUILD}/data/RiceVideoLinux.ini ${USHAREDIR} + chmod 0644 ${USHAREDIR}/RiceVideoLinux.ini +} + diff --git a/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-video-rice/patches/mupen-rice.patch b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-video-rice/patches/mupen-rice.patch new file mode 100644 index 0000000000..ad551d7065 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/mupen64plus-sa-video-rice/patches/mupen-rice.patch @@ -0,0 +1,76 @@ +diff --git a/src/Config.cpp b/src/Config.cpp +index 961a1c7..1b4ef28 100644 +--- a/src/Config.cpp ++++ b/src/Config.cpp +@@ -425,6 +425,12 @@ static void ReadConfiguration(void) + windowSetting.uDisplayWidth = ConfigGetParamInt(l_ConfigVideoGeneral, "ScreenWidth"); + windowSetting.uDisplayHeight = ConfigGetParamInt(l_ConfigVideoGeneral, "ScreenHeight"); + windowSetting.bVerticalSync = ConfigGetParamBool(l_ConfigVideoGeneral, "VerticalSync"); ++ windowSetting.uResolutionWidth = ConfigGetParamInt(l_ConfigVideoRice, "ResolutionWidth"); ++ if (windowSetting.uResolutionWidth) { ++ windowSetting.uXOffset = (windowSetting.uResolutionWidth - windowSetting.uDisplayWidth)/2; ++ } else { ++ windowSetting.uXOffset = 0; ++ } + + defaultRomOptions.N64FrameBufferEmuType = ConfigGetParamInt(l_ConfigVideoRice, "FrameBufferSetting"); + defaultRomOptions.N64FrameBufferWriteBackControl = ConfigGetParamInt(l_ConfigVideoRice, "FrameBufferWriteBackControl"); +diff --git a/src/OGLRender.cpp b/src/OGLRender.cpp +index 6f9d0e2..6618d21 100644 +--- a/src/OGLRender.cpp ++++ b/src/OGLRender.cpp +@@ -935,7 +935,7 @@ void OGLRender::UpdateScissor() + uint32 height = (gRDP.scissor.right*gRDP.scissor.bottom)/width; + glEnable(GL_SCISSOR_TEST); + OPENGL_CHECK_ERRORS; +- glScissor(0, int(height*windowSetting.fMultY+windowSetting.statusBarHeightToUse), ++ glScissor(windowSetting.uXOffset, int(height*windowSetting.fMultY+windowSetting.statusBarHeightToUse), + int(width*windowSetting.fMultX), int(height*windowSetting.fMultY) ); + OPENGL_CHECK_ERRORS; + } +@@ -956,13 +956,13 @@ void OGLRender::ApplyRDPScissor(bool force) + uint32 height = (gRDP.scissor.right*gRDP.scissor.bottom)/width; + glEnable(GL_SCISSOR_TEST); + OPENGL_CHECK_ERRORS; +- glScissor(0, int(height*windowSetting.fMultY+windowSetting.statusBarHeightToUse), ++ glScissor(windowSetting.uXOffset, int(height*windowSetting.fMultY+windowSetting.statusBarHeightToUse), + int(width*windowSetting.fMultX), int(height*windowSetting.fMultY) ); + OPENGL_CHECK_ERRORS; + } + else + { +- glScissor(int(gRDP.scissor.left*windowSetting.fMultX), int((windowSetting.uViHeight-gRDP.scissor.bottom)*windowSetting.fMultY+windowSetting.statusBarHeightToUse), ++ glScissor(int(gRDP.scissor.left*windowSetting.fMultX + windowSetting.uXOffset), int((windowSetting.uViHeight-gRDP.scissor.bottom)*windowSetting.fMultY+windowSetting.statusBarHeightToUse), + int((gRDP.scissor.right-gRDP.scissor.left)*windowSetting.fMultX), int((gRDP.scissor.bottom-gRDP.scissor.top)*windowSetting.fMultY )); + OPENGL_CHECK_ERRORS; + } +@@ -976,7 +976,7 @@ void OGLRender::ApplyScissorWithClipRatio(bool force) + + glEnable(GL_SCISSOR_TEST); + OPENGL_CHECK_ERRORS; +- glScissor(windowSetting.clipping.left, int((windowSetting.uViHeight-gRSP.real_clip_scissor_bottom)*windowSetting.fMultY)+windowSetting.statusBarHeightToUse, ++ glScissor(windowSetting.clipping.left + windowSetting.uXOffset, int((windowSetting.uViHeight-gRSP.real_clip_scissor_bottom)*windowSetting.fMultY)+windowSetting.statusBarHeightToUse, + windowSetting.clipping.width, windowSetting.clipping.height); + OPENGL_CHECK_ERRORS; + +@@ -1019,7 +1019,7 @@ void OGLRender::glViewportWrapper(GLint x, GLint y, GLsizei width, GLsizei heigh + mflag=flag; + glLoadIdentity(); + OPENGL_CHECK_ERRORS; +- glViewport(x,y,width,height); ++ glViewport(windowSetting.uXOffset + x,y,width,height); + OPENGL_CHECK_ERRORS; + } + } +diff --git a/src/Video.h b/src/Video.h +index 7fbbcaa..25812c9 100644 +--- a/src/Video.h ++++ b/src/Video.h +@@ -37,6 +37,7 @@ typedef struct { + float fViWidth, fViHeight; + unsigned short uViWidth, uViHeight; + unsigned short uDisplayWidth, uDisplayHeight; ++ unsigned short uResolutionWidth, uXOffset; + + BOOL bDisplayFullscreen; + BOOL bVerticalSync; diff --git a/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/package.mk b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/package.mk new file mode 100644 index 0000000000..09c9804c95 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/mupen64plus-sa/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) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="mupen64plus-sa" +PKG_VERSION="f8adbe08805d9fe9171cb2e3078f383631d1331d" +PKG_LICENSE="GPL" +PKG_SITE="https://mupen64plus.org/" +PKG_URL="" +PKG_DEPENDS_TARGET="toolchain mupen64plus-sa-ui-console mupen64plus-sa-audio-sdl mupen64plus-sa-input-sdl mupen64plus-sa-rsp-hle mupen64plus-sa-rsp-cxd4 mupen64plus-sa-video-rice mupen64plus-sa-video-glide64mk2 mupen64plus-sa-video-gliden64" +PKG_SECTION="virtual" +PKG_LONGDESC="Meta package for installing the different Mupen64Plus standalone modules" diff --git a/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/config/RK3326/keymap.toml b/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/config/RK3326/keymap.toml new file mode 100644 index 0000000000..8b010d4e05 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/config/RK3326/keymap.toml @@ -0,0 +1,18 @@ +# See https://wiki.libsdl.org/SDL_Keycode for key names + +[general] +fastforward = "Space" +reset = "F9" +fullscreen = "F10" + +[gba] +a = "A" +b = "S" +l = "D" +r = "F" +start = "Return" +select = "Backspace" +up = "Up" +down = "Down" +left = "Left" +right = "Right" diff --git a/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/config/RK3326/keympa.toml b/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/config/RK3326/keympa.toml new file mode 100644 index 0000000000..8b010d4e05 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/config/RK3326/keympa.toml @@ -0,0 +1,18 @@ +# See https://wiki.libsdl.org/SDL_Keycode for key names + +[general] +fastforward = "Space" +reset = "F9" +fullscreen = "F10" + +[gba] +a = "A" +b = "S" +l = "D" +r = "F" +start = "Return" +select = "Backspace" +up = "Up" +down = "Down" +left = "Left" +right = "Right" diff --git a/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/config/RK3399/keymap.toml b/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/config/RK3399/keymap.toml new file mode 100644 index 0000000000..8b010d4e05 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/config/RK3399/keymap.toml @@ -0,0 +1,18 @@ +# See https://wiki.libsdl.org/SDL_Keycode for key names + +[general] +fastforward = "Space" +reset = "F9" +fullscreen = "F10" + +[gba] +a = "A" +b = "S" +l = "D" +r = "F" +start = "Return" +select = "Backspace" +up = "Up" +down = "Down" +left = "Left" +right = "Right" diff --git a/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/config/RK3399/keympa.toml b/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/config/RK3399/keympa.toml new file mode 100644 index 0000000000..8b010d4e05 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/config/RK3399/keympa.toml @@ -0,0 +1,18 @@ +# See https://wiki.libsdl.org/SDL_Keycode for key names + +[general] +fastforward = "Space" +reset = "F9" +fullscreen = "F10" + +[gba] +a = "A" +b = "S" +l = "D" +r = "F" +start = "Return" +select = "Backspace" +up = "Up" +down = "Down" +left = "Left" +right = "Right" diff --git a/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/config/RK3588/keymap.toml b/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/config/RK3588/keymap.toml new file mode 100644 index 0000000000..8b010d4e05 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/config/RK3588/keymap.toml @@ -0,0 +1,18 @@ +# See https://wiki.libsdl.org/SDL_Keycode for key names + +[general] +fastforward = "Space" +reset = "F9" +fullscreen = "F10" + +[gba] +a = "A" +b = "S" +l = "D" +r = "F" +start = "Return" +select = "Backspace" +up = "Up" +down = "Down" +left = "Left" +right = "Right" diff --git a/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/config/RK3588/keympa.toml b/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/config/RK3588/keympa.toml new file mode 100644 index 0000000000..8b010d4e05 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/config/RK3588/keympa.toml @@ -0,0 +1,18 @@ +# See https://wiki.libsdl.org/SDL_Keycode for key names + +[general] +fastforward = "Space" +reset = "F9" +fullscreen = "F10" + +[gba] +a = "A" +b = "S" +l = "D" +r = "F" +start = "Return" +select = "Backspace" +up = "Up" +down = "Down" +left = "Left" +right = "Right" diff --git a/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/config/SDM845/keymap.toml b/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/config/SDM845/keymap.toml new file mode 100644 index 0000000000..8b010d4e05 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/config/SDM845/keymap.toml @@ -0,0 +1,18 @@ +# See https://wiki.libsdl.org/SDL_Keycode for key names + +[general] +fastforward = "Space" +reset = "F9" +fullscreen = "F10" + +[gba] +a = "A" +b = "S" +l = "D" +r = "F" +start = "Return" +select = "Backspace" +up = "Up" +down = "Down" +left = "Left" +right = "Right" diff --git a/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/config/SM8250/keymap.toml b/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/config/SM8250/keymap.toml new file mode 100644 index 0000000000..8b010d4e05 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/config/SM8250/keymap.toml @@ -0,0 +1,18 @@ +# See https://wiki.libsdl.org/SDL_Keycode for key names + +[general] +fastforward = "Space" +reset = "F9" +fullscreen = "F10" + +[gba] +a = "A" +b = "S" +l = "D" +r = "F" +start = "Return" +select = "Backspace" +up = "Up" +down = "Down" +left = "Left" +right = "Right" diff --git a/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/config/SM8550/keymap.toml b/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/config/SM8550/keymap.toml new file mode 100644 index 0000000000..8b010d4e05 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/config/SM8550/keymap.toml @@ -0,0 +1,18 @@ +# See https://wiki.libsdl.org/SDL_Keycode for key names + +[general] +fastforward = "Space" +reset = "F9" +fullscreen = "F10" + +[gba] +a = "A" +b = "S" +l = "D" +r = "F" +start = "Return" +select = "Backspace" +up = "Up" +down = "Down" +left = "Left" +right = "Right" diff --git a/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/config/SM8650/keymap.toml b/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/config/SM8650/keymap.toml new file mode 100644 index 0000000000..8b010d4e05 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/config/SM8650/keymap.toml @@ -0,0 +1,18 @@ +# See https://wiki.libsdl.org/SDL_Keycode for key names + +[general] +fastforward = "Space" +reset = "F9" +fullscreen = "F10" + +[gba] +a = "A" +b = "S" +l = "D" +r = "F" +start = "Return" +select = "Backspace" +up = "Up" +down = "Down" +left = "Left" +right = "Right" diff --git a/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/config/config.toml b/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/config/config.toml new file mode 100644 index 0000000000..95f925d0ea --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/config/config.toml @@ -0,0 +1,29 @@ +[general] +bios_path = "/storage/roms/bios/gba_bios.bin" +bios_skip = false +sync_to_audio = false + +[cartridge] +# Possible values: detect, none, sram, flash64, flash128, eeprom512, eeprom8192 +save_type = "detect" +# Force-enable RTC emulation, otherwise rely on game database. +force_rtc = true + +[video] +fullscreen = false +scale = 2 +# Set empty string for no shader. +shader_vs = "/storage/.config/nanoboyadvance/shader/gba_colors.vs" +shader_fs = "/storage/.config/nanoboyadvance/shader/gba_colors.fs" + +[audio] +# Possible values: cosine, cubic, sinc64, sinc128, sinc256 +resampler = "cubic" +# Filter FIFO audio before passing it to the mixer. +# This will reduce the dity high-frequency aliasing typical to the GBA. +interpolate_fifo = true +# Reimplementation of the popular MP2K/M4A audio mixer with higher quality. +# This is experimental and may still have issues. +mp2k_hle_enable = false +# Use cubic interpolation in the MP2K reimplementation. +mp2k_hle_cubic = false diff --git a/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/package.mk b/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/package.mk new file mode 100644 index 0000000000..433963f5d4 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/package.mk @@ -0,0 +1,37 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="nanoboyadvance-sa" +PKG_VERSION="3bb6f478f977dbfd3106508536e5fbce90d1898b" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/nba-emu/NanoBoyAdvance" +PKG_URL="${PKG_SITE}.git" +PKG_OPEN_SOURCE_BIOS="https://github.com/Nebuleon/ReGBA/raw/master/bios/gba_bios.bin" +PKG_DEPENDS_TARGET="toolchain SDL2 glew" +PKG_LONGDESC="NanoBoyAdvance is a cycle-accurate Game Boy Advance emulator." +PKG_TOOLCHAIN="cmake" +PKG_PATCH_DIRS+="${DEVICE}" + +if [ "${OPENGL_SUPPORT}" = "yes" ] && [ ! "${PREFER_GLES}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL} glu libglvnd" +elif [ "${OPENGLES_SUPPORT}" = yes ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" +fi + +PKG_CMAKE_OPTS_TARGET+=" -DPLATFORM_SDL2=ON \ + -DPLATFORM_QT=OFF \ + -DCMAKE_POLICY_VERSION_MINIMUM=3.5" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp -rf ${PKG_BUILD}/.${TARGET_NAME}/bin/sdl/NanoBoyAdvance ${INSTALL}/usr/bin + cp -rf ${PKG_DIR}/scripts/* ${INSTALL}/usr/bin + chmod 755 ${INSTALL}/usr/bin/* + + mkdir -p ${INSTALL}/usr/config/nanoboyadvance + cp -rf ${PKG_DIR}/config/config.toml ${INSTALL}/usr/config/nanoboyadvance/ + cp -rf ${PKG_DIR}/config/${DEVICE}/keymap.toml ${INSTALL}/usr/config/nanoboyadvance/ + + mkdir -p ${INSTALL}/usr/config/nanoboyadvance/bios + curl -Lo ${INSTALL}/usr/config/nanoboyadvance/bios/gba_bios.bin ${PKG_OPEN_SOURCE_BIOS} +} diff --git a/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/patches/000-config-path.patch b/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/patches/000-config-path.patch new file mode 100644 index 0000000000..dd43f200e3 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/patches/000-config-path.patch @@ -0,0 +1,22 @@ +diff --git a/src/platform/sdl/main.cpp b/src/platform/sdl/main.cpp +index 432d984..96d4848 100644 +--- a/src/platform/sdl/main.cpp ++++ b/src/platform/sdl/main.cpp +@@ -216,7 +216,7 @@ void load_keymap() { + toml::value data; + + try { +- data = toml::parse("keymap.toml"); ++ data = toml::parse("/storage/.config/nanoboyadvance/keymap.toml"); + } catch (std::exception& ex) { + Log("SDL: failed to load keymap configuration."); + return; +@@ -290,7 +290,7 @@ void init(int argc, char** argv) { + if (argc >= 1) { + fs::current_path(fs::absolute(argv[0]).replace_filename(fs::path{ })); + } +- g_config->Load("config.toml"); ++ g_config->Load("/storage/.config/nanoboyadvance/config.toml"); + parse_arguments(argc, argv); + load_keymap(); + SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMECONTROLLER); diff --git a/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/patches/001-rework-dma-interleave.patch b/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/patches/001-rework-dma-interleave.patch new file mode 100644 index 0000000000..4121b652ee --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/patches/001-rework-dma-interleave.patch @@ -0,0 +1,322 @@ +From 5d199dd8742f858b83beb55abd7cd0da45d3721e Mon Sep 17 00:00:00 2001 +From: fleroviux +Date: Mon, 13 Feb 2023 23:11:05 +0100 +Subject: [PATCH] Bus: rework DMA interleave to be more robust and simpler + +--- + src/nba/CMakeLists.txt | 1 + + src/nba/include/nba/common/scope_exit.hpp | 24 +++++++++++++++++++++++ + src/nba/include/nba/save_state.hpp | 7 ++----- + src/nba/src/bus/bus.cpp | 16 +++++++++++++-- + src/nba/src/bus/bus.hpp | 8 +++----- + src/nba/src/bus/io.cpp | 2 +- + src/nba/src/bus/serialization.cpp | 6 ++---- + src/nba/src/bus/timing.cpp | 11 ++--------- + src/nba/src/core.cpp | 4 +++- + src/nba/src/hw/dma/dma.cpp | 16 +++++++-------- + 10 files changed, 60 insertions(+), 35 deletions(-) + create mode 100644 src/nba/include/nba/common/scope_exit.hpp + +diff --git a/src/nba/CMakeLists.txt b/src/nba/CMakeLists.txt +index 9c9c6e8ab..887bcac7a 100644 +--- a/src/nba/CMakeLists.txt ++++ b/src/nba/CMakeLists.txt +@@ -91,6 +91,7 @@ set(HEADERS_PUBLIC + include/nba/common/crc32.hpp + include/nba/common/meta.hpp + include/nba/common/punning.hpp ++ include/nba/common/scope_exit.hpp + include/nba/device/audio_device.hpp + include/nba/device/input_device.hpp + include/nba/device/video_device.hpp +diff --git a/src/nba/include/nba/common/scope_exit.hpp b/src/nba/include/nba/common/scope_exit.hpp +new file mode 100644 +index 000000000..888c3703c +--- /dev/null ++++ b/src/nba/include/nba/common/scope_exit.hpp +@@ -0,0 +1,24 @@ ++/* ++ * Copyright (C) 2023 fleroviux ++ * ++ * Licensed under GPLv3 or any later version. ++ * Refer to the included LICENSE file. ++ */ ++ ++#pragma once ++ ++namespace nba { ++ ++template ++struct ScopeExit { ++ ScopeExit(Functor&& fn) : fn{fn} {} ++ ++ ScopeExit(ScopeExit&& other) = delete; ++ ScopeExit(ScopeExit const& other) = delete; ++ ++ ~ScopeExit() { fn.operator()(); } ++ ++ Functor fn; ++}; ++ ++} // namespace nba +\ No newline at end of file +diff --git a/src/nba/include/nba/save_state.hpp b/src/nba/include/nba/save_state.hpp +index 5e3c1dd00..7e8865dba 100644 +--- a/src/nba/include/nba/save_state.hpp ++++ b/src/nba/include/nba/save_state.hpp +@@ -16,7 +16,7 @@ namespace nba { + + struct SaveState { + static constexpr u32 kMagicNumber = 0x5353424E; // NBSS +- static constexpr u32 kCurrentVersion = 3; ++ static constexpr u32 kCurrentVersion = 4; + + u32 magic; + u32 version; +@@ -76,10 +76,7 @@ struct SaveState { + u8 countdown; + } prefetch; + +- struct DMA { +- bool active; +- bool openbus; +- } dma; ++ int last_access; + } bus; + + // TODO: keep track of IRQ delay: +diff --git a/src/nba/src/bus/bus.cpp b/src/nba/src/bus/bus.cpp +index 2a6b53a86..ef9f50ed4 100644 +--- a/src/nba/src/bus/bus.cpp ++++ b/src/nba/src/bus/bus.cpp +@@ -7,6 +7,7 @@ + + #include + #include ++#include + #include + + #include "arm/arm7tdmi.hpp" +@@ -32,7 +33,7 @@ void Bus::Reset() { + hw.rcnt[1] = 0; + hw.postflg = 0; + prefetch = {}; +- dma = {}; ++ last_access = 0; + UpdateWaitStateTable(); + } + +@@ -77,6 +78,13 @@ auto Bus::Read(u32 address, int access) -> T { + auto page = address >> 24; + auto is_u32 = std::is_same_v; + ++ // Set last_access to access right before returning. ++ auto _ = ScopeExit{[&]() { ++ last_access = access; ++ }}; ++ ++ if(!(access & Dma) && hw.dma.IsRunning()) hw.dma.Run(); ++ + switch (page) { + // BIOS + case 0x00: { +@@ -170,6 +178,8 @@ void Bus::Write(u32 address, int access, T value) { + auto page = address >> 24; + auto is_u32 = std::is_same_v; + ++ if(!(access & Dma) && hw.dma.IsRunning()) hw.dma.Run(); ++ + switch (page) { + // EWRAM (external work RAM) + case 0x02: { +@@ -255,6 +265,8 @@ void Bus::Write(u32 address, int access, T value) { + break; + } + } ++ ++ last_access = access; + } + + auto Bus::ReadBIOS(u32 address) -> u32 { +@@ -279,7 +291,7 @@ auto Bus::ReadOpenBus(u32 address) -> u32 { + + Log("Bus: illegal memory read: 0x{:08X}", address); + +- if (hw.dma.IsRunning() || dma.openbus) { ++ if(last_access & Dma) { + return hw.dma.GetOpenBusValue() >> shift; + } + +diff --git a/src/nba/src/bus/bus.hpp b/src/nba/src/bus/bus.hpp +index 8c1bc64af..472ae5dc6 100644 +--- a/src/nba/src/bus/bus.hpp ++++ b/src/nba/src/bus/bus.hpp +@@ -30,7 +30,8 @@ struct Bus { + enum Access { + Nonsequential = 0, + Sequential = 1, +- Code = 2 ++ Code = 2, ++ Dma = 4 + }; + + void Reset(); +@@ -109,10 +110,7 @@ struct Bus { + int duty; + } prefetch; + +- struct DMA { +- bool active = false; +- bool openbus = false; +- } dma; ++ int last_access; + + template + auto Read(u32 address, int access) -> T; +diff --git a/src/nba/src/bus/io.cpp b/src/nba/src/bus/io.cpp +index ab5175e9e..51a7fcf1a 100644 +--- a/src/nba/src/bus/io.cpp ++++ b/src/nba/src/bus/io.cpp +@@ -551,7 +551,7 @@ void Bus::Hardware::WriteByte(u32 address, u8 value) { + haltcnt = HaltControl::Stop; + } else { + haltcnt = HaltControl::Halt; +- bus->Idle(); ++ bus->Step(1); + } + } + break; +diff --git a/src/nba/src/bus/serialization.cpp b/src/nba/src/bus/serialization.cpp +index 48d31d1ed..50283cad8 100644 +--- a/src/nba/src/bus/serialization.cpp ++++ b/src/nba/src/bus/serialization.cpp +@@ -44,8 +44,7 @@ void Bus::LoadState(SaveState const& state) { + prefetch.duty = wait32[int(Access::Sequential)][prefetch.last_address >> 24]; + } + +- dma.active = state.bus.dma.active; +- dma.openbus = state.bus.dma.openbus; ++ last_access = state.bus.last_access; + } + + void Bus::CopyState(SaveState& state) { +@@ -73,8 +72,7 @@ void Bus::CopyState(SaveState& state) { + state.bus.prefetch.count = prefetch.count; + state.bus.prefetch.countdown = prefetch.countdown; + +- state.bus.dma.active = dma.active; +- state.bus.dma.openbus = dma.openbus; ++ state.bus.last_access = last_access; + } + + } // namespace nba::core +\ No newline at end of file +diff --git a/src/nba/src/bus/timing.cpp b/src/nba/src/bus/timing.cpp +index ecdf105f8..c1e92ae6a 100644 +--- a/src/nba/src/bus/timing.cpp ++++ b/src/nba/src/bus/timing.cpp +@@ -11,6 +11,8 @@ + namespace nba::core { + + void Bus::Idle() { ++ if(hw.dma.IsRunning()) hw.dma.Run(); ++ + Step(1); + } + +@@ -85,15 +87,6 @@ void Bus::StopPrefetch() { + } + + void Bus::Step(int cycles) { +- dma.openbus = false; +- +- if (hw.dma.IsRunning() && !dma.active) { +- dma.active = true; +- hw.dma.Run(); +- dma.active = false; +- dma.openbus = true; +- } +- + scheduler.AddCycles(cycles); + + if (prefetch.active) { +diff --git a/src/nba/src/core.cpp b/src/nba/src/core.cpp +index 3749778cb..6d0257544 100644 +--- a/src/nba/src/core.cpp ++++ b/src/nba/src/core.cpp +@@ -81,7 +81,7 @@ void Core::Run(int cycles) { + + while (scheduler.GetTimestampNow() < limit) { + if (bus.hw.haltcnt == HaltControl::Halt && irq.HasServableIRQ()) { +- bus.Idle(); ++ bus.Step(1); + bus.hw.haltcnt = HaltControl::Run; + } + +@@ -96,6 +96,8 @@ void Core::Run(int cycles) { + } + cpu.Run(); + } else { ++ if(dma.IsRunning()) dma.Run(); ++ + bus.Step(scheduler.GetRemainingCycleCount()); + } + } +diff --git a/src/nba/src/hw/dma/dma.cpp b/src/nba/src/hw/dma/dma.cpp +index 8bb07a3c7..db5bb4b72 100644 +--- a/src/nba/src/hw/dma/dma.cpp ++++ b/src/nba/src/hw/dma/dma.cpp +@@ -151,13 +151,13 @@ bool DMA::HasVideoTransferDMA() { + } + + void DMA::Run() { +- bus.Idle(); ++ bus.Step(1); + + do { + RunChannel(); + } while (IsRunning()); + +- bus.Idle(); ++ bus.Step(1); + } + + void DMA::RunChannel() { +@@ -186,15 +186,15 @@ void DMA::RunChannel() { + auto src_addr = channel.latch.src_addr; + auto dst_addr = channel.latch.dst_addr; + +- auto access_src = Bus::Access::Sequential; +- auto access_dst = Bus::Access::Sequential; ++ auto access_src = Bus::Access::Sequential | Bus::Access::Dma; ++ auto access_dst = Bus::Access::Sequential | Bus::Access::Dma; + + if (!did_access_rom) { + if (src_addr >= 0x08000000) { +- access_src = Bus::Access::Nonsequential; ++ access_src = Bus::Access::Nonsequential | Bus::Access::Dma; + did_access_rom = true; + } else if (dst_addr >= 0x08000000) { +- access_dst = Bus::Access::Nonsequential; ++ access_dst = Bus::Access::Nonsequential | Bus::Access::Dma; + did_access_rom = true; + } + } +@@ -212,7 +212,7 @@ void DMA::RunChannel() { + } else { + value = channel.latch.bus; + } +- bus.Idle(); ++ bus.Step(1); + } + + bus.WriteHalf(dst_addr, value, access_dst); +@@ -221,7 +221,7 @@ void DMA::RunChannel() { + channel.latch.bus = bus.ReadWord(src_addr, access_src); + latch = channel.latch.bus; + } else { +- bus.Idle(); ++ bus.Step(1); + } + + bus.WriteWord(dst_addr, channel.latch.bus, access_dst); diff --git a/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/scripts/start_nanoboyadvance.sh b/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/scripts/start_nanoboyadvance.sh new file mode 100644 index 0000000000..71c0eb5788 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/nanoboyadvance-sa/scripts/start_nanoboyadvance.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile +set_kill set "-9 NanoBoyAdvance" + +#Check if nanoboyadvance exists in .config +if [ ! -d "/storage/.config/nanoboyadvance" ]; then + mkdir -p "/storage/.config/nanoboyadvance" + cp -r "/usr/config/nanoboyadvance" "/storage/.config/" +fi + +#Make nanoboyadvance bios folder +if [ ! -d "/storage/roms/bios/gba" ]; then + mkdir -p "/storage/roms/bios/gba" +fi + +#Copy open source bios if no other bios exists +if [ ! -f "/storage/roms/bios/gba/gba_bios.bin" ]; then + cp -r "/usr/config/nanoboyadvance" "/storage/roms/bios/gba/gba_bios.bin" +fi + +#Set the cores to use +GAME=$(echo "${1}"| sed "s#^/.*/##") +PLATFORM=$(echo "${2}"| sed "s#^/.*/##") +CORES=$(get_setting "cores" "${PLATFORM}" "${GAME}") +if [ "${CORES}" = "little" ] +then + EMUPERF="${SLOW_CORES}" +elif [ "${CORES}" = "big" ] +then + EMUPERF="${FAST_CORES}" +else + ### All.. + unset EMUPERF +fi + +#Run nanoboyadvance emulator +${EMUPERF} /usr/bin/NanoBoyAdvance "${1}" diff --git a/projects/ArchR/packages/emulators/standalone/openbor/config/Saves/default.cfg b/projects/ArchR/packages/emulators/standalone/openbor/config/Saves/default.cfg new file mode 100755 index 0000000000..a5276276eb Binary files /dev/null and b/projects/ArchR/packages/emulators/standalone/openbor/config/Saves/default.cfg differ diff --git a/projects/ArchR/packages/emulators/standalone/openbor/config/master.cfg b/projects/ArchR/packages/emulators/standalone/openbor/config/master.cfg new file mode 100644 index 0000000000..abe3f75ca6 Binary files /dev/null and b/projects/ArchR/packages/emulators/standalone/openbor/config/master.cfg differ diff --git a/projects/ArchR/packages/emulators/standalone/openbor/package.mk b/projects/ArchR/packages/emulators/standalone/openbor/package.mk new file mode 100644 index 0000000000..bd2cbf8be2 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/openbor/package.mk @@ -0,0 +1,35 @@ +# 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) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="openbor" +PKG_VERSION="b8303cce992a0db93c3a465df3c943942fe322f8" +PKG_SITE="https://github.com/DCurrent/openbor" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain SDL2 libogg libvorbisidec libvpx libpng" +PKG_LONGDESC="OpenBOR is the ultimate 2D side scrolling engine for beat em' ups, shooters, and more!" +PKG_TOOLCHAIN="make" +GET_HANDLER_SUPPORT="git" + +pre_configure_target() { + PKG_MAKE_OPTS_TARGET="BUILD_LINUX_${ARCH}=1 -C ${PKG_BUILD}/engine SDKPATH=${SYSROOT_PREFIX} PREFIX=${TARGET_NAME}" + cd ${PKG_BUILD} + #sed -i "s|device->mappings\[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}/sources/start_OpenBOR.sh ${INSTALL}/usr/bin + chmod 0777 ${INSTALL}/usr/bin/* + mkdir -p ${INSTALL}/usr/config/openbor + cp ${PKG_DIR}/config/master.cfg ${INSTALL}/usr/config/openbor/master.cfg +} diff --git a/projects/ArchR/packages/emulators/standalone/openbor/patches/openbor-02-addplatform.patch b/projects/ArchR/packages/emulators/standalone/openbor/patches/openbor-02-addplatform.patch new file mode 100644 index 0000000000..50473bdfaf --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/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/projects/ArchR/packages/emulators/standalone/openbor/sources/start_OpenBOR.sh b/projects/ArchR/packages/emulators/standalone/openbor/sources/start_OpenBOR.sh new file mode 100755 index 0000000000..c10fcd12e9 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/openbor/sources/start_OpenBOR.sh @@ -0,0 +1,45 @@ +#!/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) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# 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}" + OpenBOR + +# We stop the fake keyboard + killall gptokeyb & diff --git a/projects/ArchR/packages/emulators/standalone/pico-8/package.mk b/projects/ArchR/packages/emulators/standalone/pico-8/package.mk new file mode 100644 index 0000000000..742b48a45b --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/pico-8/package.mk @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="pico-8" +PKG_VERSION="95cb4d4f28e1743c6a7f3c0266049f68b2134b60" +PKG_LICENSE="GPLv2" +PKG_SITE="" +PKG_URL="" +PKG_DEPENDS_TARGET="toolchain SDL2" +PKG_LONGDESC="PICO-8 Fantasy Console" +PKG_TOOLCHAIN="manual" + +if [ ! "${OPENGL}" = "no" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL} glu libglvnd" +fi + +if [ "${OPENGLES_SUPPORT}" = yes ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" +fi + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp ${PKG_DIR}/sources/start_pico8.sh ${INSTALL}/usr/bin + chmod 0755 ${INSTALL}/usr/bin/start_pico8.sh + + mkdir -p ${INSTALL}/usr/lib/autostart/common + cp ${PKG_DIR}/sources/autostart/common/* ${INSTALL}/usr/lib/autostart/common + chmod 0755 ${INSTALL}/usr/lib/autostart/common/* +} diff --git a/projects/ArchR/packages/emulators/standalone/pico-8/sources/autostart/common/010-pico8 b/projects/ArchR/packages/emulators/standalone/pico-8/sources/autostart/common/010-pico8 new file mode 100755 index 0000000000..9185251a60 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/pico-8/sources/autostart/common/010-pico8 @@ -0,0 +1,9 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PICO_DIR="/storage/roms/pico-8" +if [ -d "${PICO_DIR}" ] && [ ! -f "${PICO_DIR}/.disable_splore" ] +then + touch "${PICO_DIR}/Splore.png" +fi diff --git a/projects/ArchR/packages/emulators/standalone/pico-8/sources/start_pico8.sh b/projects/ArchR/packages/emulators/standalone/pico-8/sources/start_pico8.sh new file mode 100644 index 0000000000..52159c9207 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/pico-8/sources/start_pico8.sh @@ -0,0 +1,48 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Source predefined functions and variables +. /etc/profile + +GAME_DIR="/storage/roms/pico-8/" + +case ${HW_ARCH} in + aarch64) + STATIC_BIN="pico8_64" + ;; + *) + STATIC_BIN="pico8_dyn" + ;; +esac + +# check if the file being launched contains "Splore" and if so launch Pico-8 Splore otherwise run the game directly +shopt -s nocasematch +if [[ "${1}" == *splore* ]]; then + OPTIONS="-splore" +else + OPTIONS="-run" + CART="${1}" +fi +shopt -u nocasematch + +INTEGER_SCALE=$(get_setting pico-8.integerscale) +if [ "${INTEGER_SCALE}" = "1" ] +then + OPTIONS="${OPTIONS} -pixel_perfect 1" +fi + +if [ -d "${GAME_DIR}/${HW_ARCH}" ] +then + LAUNCH_DIR="${GAME_DIR}/${HW_ARCH}" +else + LAUNCH_DIR="${GAME_DIR}" +fi + +# store sdl_controllers in root directory so its shared across devices - will look to revisit this with controller refactor work +cp -f /usr/config/SDL-GameControllerDB/gamecontrollerdb.txt ${GAME_DIR}/sdl_controllers.txt + +# mark the binary executable to cover cases where the user adding the binaries doesn't know or forgets. +chmod 0755 ${LAUNCH_DIR}/${STATIC_BIN} +set_kill set "-9 ${STATIC_BIN} start_pico8.sh" +${LAUNCH_DIR}/${STATIC_BIN} -home -root_path ${GAME_DIR} -joystick 0 ${OPTIONS} "${CART}" \ No newline at end of file diff --git a/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/NPEG00023.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/NPEG00023.ini new file mode 100644 index 0000000000..3bb22e2448 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/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/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/NPEG00044.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/NPEG00044.ini new file mode 100644 index 0000000000..eff298988a --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/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/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/NPUG80325.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/NPUG80325.ini new file mode 100644 index 0000000000..d7b2640d03 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/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/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/UCES00019.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/UCES00019.ini new file mode 100644 index 0000000000..645546a3fe --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/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/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/UCES00842.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/UCES00842.ini new file mode 100644 index 0000000000..e7617352c5 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/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/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/UCES01184.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/UCES01184.ini new file mode 100644 index 0000000000..031e0dfb8f --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/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/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/UCES01401.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/UCES01401.ini new file mode 100644 index 0000000000..390b942d37 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/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/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/UCES01473.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/UCES01473.ini new file mode 100644 index 0000000000..5dc49929e5 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/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/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/UCUS98640.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/UCUS98640.ini new file mode 100644 index 0000000000..76c0eb4d9e --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/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/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/UCUS98653.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/UCUS98653.ini new file mode 100644 index 0000000000..fa614adbad --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/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/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/UCUS98668.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/UCUS98668.ini new file mode 100644 index 0000000000..c70649b0c6 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/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/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/UCUS98737.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/UCUS98737.ini new file mode 100644 index 0000000000..41a9c38029 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/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/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULES00033.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULES00033.ini new file mode 100644 index 0000000000..f89c600b5f --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/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/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULES00034.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULES00034.ini new file mode 100644 index 0000000000..4772465789 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/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/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULES00035.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULES00035.ini new file mode 100644 index 0000000000..66485ec7fd --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/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/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULES00125.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULES00125.ini new file mode 100644 index 0000000000..2fc9333c8f --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/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/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULES00483.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULES00483.ini new file mode 100644 index 0000000000..e84e8b3cb4 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/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/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULES00625.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULES00625.ini new file mode 100644 index 0000000000..f21d010222 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/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/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULES00626.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULES00626.ini new file mode 100644 index 0000000000..1ddbb82782 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/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/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULES00703.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULES00703.ini new file mode 100644 index 0000000000..652c66050e --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/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/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULES00968.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULES00968.ini new file mode 100644 index 0000000000..e440020e98 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/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/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULES00981.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULES00981.ini new file mode 100644 index 0000000000..994966b1bc --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/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/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULES00982.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULES00982.ini new file mode 100644 index 0000000000..3d0a33daa3 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/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/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULES01214.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULES01214.ini new file mode 100644 index 0000000000..350b782627 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/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/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULES01402.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULES01402.ini new file mode 100644 index 0000000000..95d2f1c697 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/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/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULES01406.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULES01406.ini new file mode 100644 index 0000000000..3a93436dad --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/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/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULUS00125.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULUS00125.ini new file mode 100644 index 0000000000..fb37e5b8b7 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/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/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULUS10014.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULUS10014.ini new file mode 100644 index 0000000000..19434ecf32 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/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/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULUS10189.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULUS10189.ini new file mode 100644 index 0000000000..56b2311dcf --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/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/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULUS10197.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULUS10197.ini new file mode 100644 index 0000000000..2b62c5435d --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/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/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULUS10213.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULUS10213.ini new file mode 100644 index 0000000000..7d89a978d6 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/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/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULUS10236.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULUS10236.ini new file mode 100644 index 0000000000..64da0ba1cb --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/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/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULUS10328.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULUS10328.ini new file mode 100644 index 0000000000..794f4823d6 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/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/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULUS10345.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULUS10345.ini new file mode 100644 index 0000000000..befe16bde8 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/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/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULUS10390.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULUS10390.ini new file mode 100644 index 0000000000..ea9aa6c92b --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/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/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULUS10507.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/Cheats/ULUS10507.ini new file mode 100644 index 0000000000..30770423e7 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/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/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/SYSTEM/CACHE/UCAS40015.glshadercache b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/SYSTEM/CACHE/UCAS40015.glshadercache new file mode 100644 index 0000000000..af57dc9549 Binary files /dev/null and b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/SYSTEM/CACHE/UCAS40015.glshadercache differ diff --git a/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/SYSTEM/CACHE/ULJM05600.glshadercache b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/SYSTEM/CACHE/ULJM05600.glshadercache new file mode 100644 index 0000000000..411b76175d Binary files /dev/null and b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/PSP/SYSTEM/CACHE/ULJM05600.glshadercache differ diff --git a/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/assets/NotoSansJP-Regular.ttf b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/assets/NotoSansJP-Regular.ttf new file mode 100644 index 0000000000..1583096a2d Binary files /dev/null and b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/config/assets/NotoSansJP-Regular.ttf differ diff --git a/projects/ArchR/packages/emulators/standalone/ppsspp-sa/package.mk b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/package.mk new file mode 100644 index 0000000000..5148feb391 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/package.mk @@ -0,0 +1,106 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="ppsspp-sa" +PKG_SITE="https://github.com/hrydgard/ppsspp" +PKG_URL="${PKG_SITE}.git" +PKG_VERSION="afbc66a318b86432642b532c575241f3716642ef" # v1.20.2 +CHEAT_DB_VERSION="7c9fe1ae71155626cea767aed53f968de9f4051f" # Update cheat.db (17/01/2026) +PKG_LICENSE="GPLv2" +PKG_DEPENDS_TARGET="toolchain libzip SDL2 zlib zip" +PKG_LONGDESC="PPSSPPDL" +GET_HANDLER_SUPPORT="git" + +### Note: +### This package includes the NotoSansJP-Regular.ttf font. This font is licensed under +### SIL Open Font License, Version 1.1. The license can be found in the licenses +### directory in the root of this project, OFL.txt. +### + +PKG_PATCH_DIRS+="${DEVICE}" + +PKG_CMAKE_OPTS_TARGET=" -DUSE_SYSTEM_FFMPEG=OFF \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_SYSTEM_NAME=Linux \ + -DBUILD_SHARED_LIBS=OFF \ + -DUSE_SYSTEM_LIBPNG=OFF \ + -DANDROID=OFF \ + -DWIN32=OFF \ + -DAPPLE=OFF \ + -DCMAKE_CROSSCOMPILING=ON \ + -DUSING_QT_UI=OFF \ + -DUNITTEST=OFF \ + -DSIMULATOR=OFF \ + -DHEADLESS=OFF \ + -DUSE_DISCORD=OFF" + +if [ "${OPENGL_SUPPORT}" = "yes" ] && [ ! "${PREFER_GLES}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL} glu libglvnd glew" + PKG_CMAKE_OPTS_TARGET+=" -DUSING_FBDEV=OFF \ + -DUSING_GLES2=OFF" + +elif [ "${OPENGLES_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" + PKG_CMAKE_OPTS_TARGET+=" -DUSING_FBDEV=ON \ + -DUSING_EGL=OFF \ + -DUSING_GLES2=ON" +fi + +if [ "${VULKAN_SUPPORT}" = "yes" ] +then + PKG_DEPENDS_TARGET+=" ${VULKAN}" + PKG_CMAKE_OPTS_TARGET+=" -DUSE_VULKAN_DISPLAY_KHR=ON \ + -DVULKAN=ON \ + -DEGL_NO_X11=1 \ + -DMESA_EGL_NO_X11_HEADERS=1" + GRENDERER="3 (VULKAN)" +else + PKG_CMAKE_OPTS_TARGET+=" -DVULKAN=OFF \ + -DUSE_VULKAN_DISPLAY_KHR=OFF \ + -DUSING_X11_VULKAN=OFF" + GRENDERER="0 (OPENGL)" +fi + +if [ "${DISPLAYSERVER}" = "wl" ]; then + PKG_DEPENDS_TARGET+=" wayland ${WINDOWMANAGER}" + PKG_CMAKE_OPTS_TARGET+=" -DUSE_WAYLAND_WSI=ON" +else + PKG_CMAKE_OPTS_TARGET+=" -DUSE_WAYLAND_WSI=OFF" +fi + +pre_configure_target() { + sed -i 's/\-O[23]//g' ${PKG_BUILD}/CMakeLists.txt + 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}/scripts/* ${INSTALL}/usr/bin + cp PPSSPPSDL ${INSTALL}/usr/bin/ppsspp + chmod 0755 ${INSTALL}/usr/bin/* + 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 [ -d "${PKG_DIR}/sources/${DEVICE}" ] + then + cp ${PKG_DIR}/sources/${DEVICE}/* ${INSTALL}/usr/config/ppsspp/PSP/SYSTEM + fi + rm ${INSTALL}/usr/config/ppsspp/assets/gamecontrollerdb.txt + ln -sf NotoSansJP-Regular.ttf ${INSTALL}/usr/config/ppsspp/assets/Roboto-Condensed.ttf + curl -Lo ${INSTALL}/usr/config/ppsspp/PSP/Cheats/cheat.db https://raw.githubusercontent.com/Saramagrean/CWCheat-Database-Plus-/${CHEAT_DB_VERSION}/cheat.db +} + +post_install() { + sed -e "s/@GRENDERER@/${GRENDERER}/g" -i ${INSTALL}/usr/bin/start_ppsspp.sh +} diff --git a/projects/ArchR/packages/emulators/standalone/ppsspp-sa/patches/001-do-not-mute.patch b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/patches/001-do-not-mute.patch new file mode 100644 index 0000000000..8a0700bcde --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/patches/001-do-not-mute.patch @@ -0,0 +1,17 @@ +diff --git a/Core/Config.cpp b/Core/Config.cpp +index 4f6ee43dce..e61e3eda4c 100644 +--- a/Core/Config.cpp ++++ b/Core/Config.cpp +@@ -1616,12 +1616,6 @@ void Config::PostLoadCleanup() { + g_Config.bSkipBufferEffects = false; + } + +- // Automatically silence secondary instances. Could be an option I guess, but meh. +- if (PPSSPP_ID > 1) { +- NOTICE_LOG(Log::Audio, "Secondary instance %d - silencing audio", (int)PPSSPP_ID); +- g_Config.iGameVolume = 0; +- } +- + // Automatically switch away from deprecated setting value. + if (iTexScalingLevel <= 0) { + iTexScalingLevel = 1; diff --git a/projects/ArchR/packages/emulators/standalone/ppsspp-sa/patches/002-fullscreen-drm.patch b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/patches/002-fullscreen-drm.patch new file mode 100644 index 0000000000..d194f6bc36 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/patches/002-fullscreen-drm.patch @@ -0,0 +1,95 @@ +diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp +index 04c16ca7a0..cecc4b7f0f 100644 +--- a/SDL/SDLMain.cpp ++++ b/SDL/SDLMain.cpp +@@ -824,9 +824,9 @@ void UpdateWindowState(SDL_Window *window) { + + Uint32 window_flags = SDL_GetWindowFlags(window); + if (g_Config.bFullScreen) { +- window_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; ++ window_flags |= SDL_WINDOW_FULLSCREEN; + } else { +- window_flags &= ~SDL_WINDOW_FULLSCREEN_DESKTOP; ++ window_flags &= ~SDL_WINDOW_FULLSCREEN; + } + SDL_SetWindowFullscreen(window, window_flags); + } +@@ -956,7 +956,7 @@ static void ProcessSDLEvent(SDL_Window *window, const SDL_Event &event, InputSta + Native_NotifyWindowHidden(false); + + Uint32 window_flags = SDL_GetWindowFlags(window); +- bool fullscreen = (window_flags & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_FULLSCREEN_DESKTOP)); ++ bool fullscreen = (window_flags & (SDL_WINDOW_FULLSCREEN)); + + // This one calls NativeResized if the size changed. + Native_UpdateScreenScale(new_width_px, new_height_px, UIScaleFactorToMultiplier(g_Config.iUIScaleFactor)); +@@ -986,7 +986,7 @@ static void ProcessSDLEvent(SDL_Window *window, const SDL_Event &event, InputSta + case SDL_WINDOWEVENT_MOVED: + { + Uint32 window_flags = SDL_GetWindowFlags(window); +- bool fullscreen = (window_flags & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_FULLSCREEN_DESKTOP)); ++ bool fullscreen = (window_flags & (SDL_WINDOW_FULLSCREEN)); + if (!fullscreen) { + g_Config.iWindowX = (int)event.window.data1; + g_Config.iWindowY = (int)event.window.data2; +@@ -1466,7 +1466,7 @@ int main(int argc, char *argv[]) { + Uint32 mode = 0; + for (int i = 1; i < argc; i++) { + if (!strcmp(argv[i], "--fullscreen")) { +- mode |= SDL_WINDOW_FULLSCREEN_DESKTOP; ++ mode |= SDL_WINDOW_FULLSCREEN; + g_Config.DoNotSaveSetting(&g_Config.bFullScreen); + } else if (set_xres == -2) + set_xres = parseInt(argv[i]); +@@ -1559,19 +1559,19 @@ int main(int argc, char *argv[]) { + + // Force fullscreen if the resolution is too low to run windowed. + if (g_DesktopWidth < 480 * 2 && g_DesktopHeight < 272 * 2) { +- mode |= SDL_WINDOW_FULLSCREEN_DESKTOP; ++ mode |= SDL_WINDOW_FULLSCREEN; + } + + // If we're on mobile, don't try for windowed either. + #if defined(MOBILE_DEVICE) && !PPSSPP_PLATFORM(SWITCH) + mode |= SDL_WINDOW_FULLSCREEN; + #elif defined(USING_FBDEV) || PPSSPP_PLATFORM(SWITCH) +- mode |= SDL_WINDOW_FULLSCREEN_DESKTOP; ++ mode |= SDL_WINDOW_FULLSCREEN; + #else + mode |= SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI; + #endif + +- if (mode & SDL_WINDOW_FULLSCREEN_DESKTOP) { ++ if (mode & SDL_WINDOW_FULLSCREEN) { + g_display.pixel_xres = g_DesktopWidth; + g_display.pixel_yres = g_DesktopHeight; + g_Config.bFullScreen = true; +@@ -1634,7 +1634,7 @@ int main(int argc, char *argv[]) { + + // Use the setting from the config when initing the window. + if (g_Config.bFullScreen) { +- mode |= SDL_WINDOW_FULLSCREEN_DESKTOP; ++ mode |= SDL_WINDOW_FULLSCREEN; + g_display.pixel_xres = g_DesktopWidth; + g_display.pixel_yres = g_DesktopHeight; + } +diff --git a/UI/MainScreen.cpp b/UI/MainScreen.cpp +--- a/UI/MainScreen.cpp ++++ b/UI/MainScreen.cpp +@@ -1459,18 +1459,6 @@ + LinearLayout *rightColumnItems = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)); + rightColumnItems->SetSpacing(0.0f); + ViewGroup *logo = new LogoView(false, new LinearLayoutParams(FILL_PARENT, 80.0f)); +-#if !defined(MOBILE_DEVICE) +- auto gr = GetI18NCategory(I18NCat::GRAPHICS); +- Button *fullscreenButton = logo->Add(new Button("", ImageID(), new AnchorLayoutParams(48, 48, NONE, 0, 0, NONE, Centering::None))); +- fullscreenButton->SetIgnoreText(true); +- fullscreenButton->OnClick.Add([](UI::EventParams &e) { +- g_Config.bFullScreen = !g_Config.bFullScreen; +- System_ApplyFullscreenState(); +- }); +- fullscreenButton->SetImageIDFunc([]() { +- return g_Config.bFullScreen ? ImageID("I_RESTORE") : ImageID("I_FULLSCREEN"); +- }); +-#endif + rightColumnItems->Add(logo); diff --git a/projects/ArchR/packages/emulators/standalone/ppsspp-sa/patches/003-disable-mouse.patch b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/patches/003-disable-mouse.patch new file mode 100644 index 0000000000..8bb2544ed3 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/patches/003-disable-mouse.patch @@ -0,0 +1,28 @@ +diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp +index 04c16ca7a0..f2ae555923 100644 +--- a/SDL/SDLMain.cpp ++++ b/SDL/SDLMain.cpp +@@ -974,12 +974,7 @@ static void ProcessSDLEvent(SDL_Window *window, const SDL_Event &event, InputSta + g_Config.iWindowWidth = new_width; + g_Config.iWindowHeight = new_height; + } +- // 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); +- } ++ SDL_ShowCursor(SDL_DISABLE); + break; + } + +@@ -1746,9 +1741,7 @@ int main(int argc, char *argv[]) { + // OK, we have a valid graphics backend selected. Let's clear the failures. + g_Config.sFailedGPUBackends.clear(); + +-#ifdef MOBILE_DEVICE + SDL_ShowCursor(SDL_DISABLE); +-#endif + + // Avoid the IME popup when holding keys. This doesn't affect all versions of SDL. + // Note: We re-enable it in text input fields! This is necessary otherwise we don't receive diff --git a/projects/ArchR/packages/emulators/standalone/ppsspp-sa/patches/004-set-paths.patch b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/patches/004-set-paths.patch new file mode 100644 index 0000000000..d31dce81b5 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/patches/004-set-paths.patch @@ -0,0 +1,125 @@ +diff --git a/Core/Config.cpp b/Core/Config.cpp +index 4f6ee43dce..188bbca207 100644 +--- a/Core/Config.cpp ++++ b/Core/Config.cpp +@@ -1271,7 +1271,7 @@ void Config::UpdateIniLocation(const char *iniFileName, const char *controllerIn + const bool useIniFilename = iniFileName != nullptr && strlen(iniFileName) > 0; + const char *ppssppIniFilename = IsVREnabled() ? "ppssppvr.ini" : "ppsspp.ini"; + bool exists; +- iniFilename_ = FindConfigFile(searchPath_, useIniFilename ? iniFileName : ppssppIniFilename, &exists); ++ iniFilename_ = Path("/storage/.config/ppsspp/PSP/SYSTEM") / ppssppIniFilename; + const bool useControllerIniFilename = controllerIniFilename != nullptr && strlen(controllerIniFilename) > 0; + const char *controlsIniFilename = IsVREnabled() ? "controlsvr.ini" : "controls.ini"; + controllerIniFilename_ = FindConfigFile(searchPath_, useControllerIniFilename ? controllerIniFilename : controlsIniFilename, &exists); +diff --git a/Core/Util/PathUtil.cpp b/Core/Util/PathUtil.cpp +index a82bc95fe6..4c1a926cd8 100644 +--- a/Core/Util/PathUtil.cpp ++++ b/Core/Util/PathUtil.cpp +@@ -42,14 +42,8 @@ Path FindConfigFile(const Path &searchPath, std::string_view baseFilename, bool + } + + Path GetSysDirectory(PSPDirectories directoryType) { +- const Path &memStickDirectory = g_Config.memStickDirectory; +- Path pspDirectory; +- if (!strcasecmp(memStickDirectory.GetFilename().c_str(), "PSP")) { +- // Let's strip this off, to easily allow choosing a root directory named "PSP" on Android. +- pspDirectory = memStickDirectory; +- } else { +- pspDirectory = memStickDirectory / "PSP"; +- } ++ Path memStickDirectory = Path("/storage/roms/psp/"); ++ Path pspDirectory = Path("/storage/.config/ppsspp/PSP/"); + + switch (directoryType) { + case DIRECTORY_PSP: +@@ -59,9 +53,9 @@ Path GetSysDirectory(PSPDirectories directoryType) { + case DIRECTORY_GAME: + return pspDirectory / "GAME"; + case DIRECTORY_SAVEDATA: +- return pspDirectory / "SAVEDATA"; ++ return Path("/storage/roms/psp/"); + case DIRECTORY_SCREENSHOT: +- return pspDirectory / "SCREENSHOT"; ++ return Path("/storage/roms/screenshots/"); + case DIRECTORY_SYSTEM: + return pspDirectory / "SYSTEM"; + case DIRECTORY_PAUTH: +@@ -71,7 +65,7 @@ Path GetSysDirectory(PSPDirectories directoryType) { + case DIRECTORY_DUMP: + return pspDirectory / "SYSTEM/DUMP"; + case DIRECTORY_SAVESTATE: +- return pspDirectory / "PPSSPP_STATE"; ++ return Path("/storage/roms/savestates/psp/ppsspp-sa"); + case DIRECTORY_CACHE: + return pspDirectory / "SYSTEM/CACHE"; + case DIRECTORY_TEXTURES: +@@ -93,11 +87,11 @@ Path GetSysDirectory(PSPDirectories directoryType) { + return pspDirectory / "themes"; + + case DIRECTORY_MEMSTICK_ROOT: +- return g_Config.memStickDirectory; ++ return memStickDirectory; + // Just return the memory stick root if we run into some sort of problem. + default: + ERROR_LOG(Log::FileSystem, "Unknown directory type."); +- return g_Config.memStickDirectory; ++ return pspDirectory; + } + } + +diff --git a/SDL/SDLJoystick.cpp b/SDL/SDLJoystick.cpp +index 290cf57ce1..5d2e13da4d 100644 +--- a/SDL/SDLJoystick.cpp ++++ b/SDL/SDLJoystick.cpp +@@ -24,7 +24,7 @@ SDLJoystick::SDLJoystick(bool init_SDL ) : registeredAsEventHandler(false) { + SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER); + } + +- const char *dbPath = "gamecontrollerdb.txt"; ++ const char *dbPath = "/storage/.config/SDL-GameControllerDB/gamecontrollerdb.txt"; + INFO_LOG(Log::System, "loading control pad mappings from %s:", dbPath); + + size_t size; +@@ -33,7 +33,7 @@ SDLJoystick::SDLJoystick(bool init_SDL ) : registeredAsEventHandler(false) { + SDL_RWops *rw = SDL_RWFromConstMem(mappingData, size); + // 1 to free the rw after use + if (SDL_GameControllerAddMappingsFromRW(rw, 1) == -1) { +- ERROR_LOG(Log::System, "Failed to read mapping data - corrupt?"); ++ ERROR_LOG(Log::System, "/storage/.config/SDL-GameControllerDB/gamecontrollerdb.txt missing"); + } + delete[] mappingData; + } else { +diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp +index 84596b04ec..8e89a7bb13 100644 +--- a/UI/NativeApp.cpp ++++ b/UI/NativeApp.cpp +@@ -367,7 +367,7 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch + #if !defined(MOBILE_DEVICE) && !defined(_WIN32) && !PPSSPP_PLATFORM(SWITCH) + g_VFS.Register("", new DirectoryReader(File::GetExeDirectory() / "assets")); + g_VFS.Register("", new DirectoryReader(File::GetExeDirectory())); +- g_VFS.Register("", new DirectoryReader(Path("/usr/local/share/ppsspp/assets"))); ++ g_VFS.Register("", new DirectoryReader(Path("/storage/.config/ppsspp/assets"))); + g_VFS.Register("", new DirectoryReader(Path("/usr/local/share/games/ppsspp/assets"))); + g_VFS.Register("", new DirectoryReader(Path("/usr/share/ppsspp/assets"))); + g_VFS.Register("", new DirectoryReader(Path("/usr/share/games/ppsspp/assets"))); +@@ -474,7 +474,7 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch + else // Just in case + config = "./config"; + +- g_Config.memStickDirectory = Path(config) / "ppsspp"; ++ g_Config.memStickDirectory = Path("/storage/roms/psp/"); + g_Config.flash0Directory = File::GetExeDirectory() / "assets/flash0"; + if (getenv("HOME") != nullptr) { + g_Config.defaultCurrentDirectory = Path(getenv("HOME")); +index a8300543d..37c12caa4 100644 +--- a/Core/SaveState.cpp ++++ b/Core/SaveState.cpp +@@ -333,7 +333,7 @@ int g_screenshotFailures; + } + + std::string GetGamePrefix(const ParamSFOData ¶mSFO) { +- return GenerateFullDiscId(paramSFO); ++ return PSP_CoreParameter().fileToStart.WithReplacedExtension("").GetFilename(); + } + + // The prefix is always based on GenerateFullDiscId. So we can find these by scanning, too. diff --git a/projects/ArchR/packages/emulators/standalone/ppsspp-sa/patches/SM8250/000-swap-guid-and-misc.patch b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/patches/SM8250/000-swap-guid-and-misc.patch new file mode 100644 index 0000000000..0aa3aee6e1 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/patches/SM8250/000-swap-guid-and-misc.patch @@ -0,0 +1,22 @@ +diff --git a/SDL/SDLJoystick.cpp b/SDL/SDLJoystick.cpp +index 94a6f481ba..977617b77d 100644 +--- a/SDL/SDLJoystick.cpp ++++ b/SDL/SDLJoystick.cpp +@@ -141,7 +141,7 @@ InputKeyCode SDLJoystick::getKeycodeForButton(SDL_GameControllerButton button) { + case SDL_CONTROLLER_BUTTON_BACK: + return NKCODE_BUTTON_9; // select button + case SDL_CONTROLLER_BUTTON_GUIDE: +- return NKCODE_BACK; // pause menu ++ return NKCODE_BUTTON_11; + case SDL_CONTROLLER_BUTTON_LEFTSTICK: + return NKCODE_BUTTON_THUMBL; + case SDL_CONTROLLER_BUTTON_RIGHTSTICK: +@@ -150,7 +150,7 @@ InputKeyCode SDLJoystick::getKeycodeForButton(SDL_GameControllerButton button) { + // Found these limits by checking out the SDL2 branch of the SDL repo, doing git blame, then `git tag --contains (commit)` etc. + #if SDL_VERSION_ATLEAST(2, 0, 16) + case SDL_CONTROLLER_BUTTON_MISC1: +- return NKCODE_BUTTON_11; ++ return NKCODE_BACK; // pause menu + #endif + #if SDL_VERSION_ATLEAST(2, 0, 28) + case SDL_CONTROLLER_BUTTON_PADDLE1: diff --git a/projects/ArchR/packages/emulators/standalone/ppsspp-sa/patches/SM8550/000-swap-guid-and-misc.patch b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/patches/SM8550/000-swap-guid-and-misc.patch new file mode 100644 index 0000000000..0aa3aee6e1 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/patches/SM8550/000-swap-guid-and-misc.patch @@ -0,0 +1,22 @@ +diff --git a/SDL/SDLJoystick.cpp b/SDL/SDLJoystick.cpp +index 94a6f481ba..977617b77d 100644 +--- a/SDL/SDLJoystick.cpp ++++ b/SDL/SDLJoystick.cpp +@@ -141,7 +141,7 @@ InputKeyCode SDLJoystick::getKeycodeForButton(SDL_GameControllerButton button) { + case SDL_CONTROLLER_BUTTON_BACK: + return NKCODE_BUTTON_9; // select button + case SDL_CONTROLLER_BUTTON_GUIDE: +- return NKCODE_BACK; // pause menu ++ return NKCODE_BUTTON_11; + case SDL_CONTROLLER_BUTTON_LEFTSTICK: + return NKCODE_BUTTON_THUMBL; + case SDL_CONTROLLER_BUTTON_RIGHTSTICK: +@@ -150,7 +150,7 @@ InputKeyCode SDLJoystick::getKeycodeForButton(SDL_GameControllerButton button) { + // Found these limits by checking out the SDL2 branch of the SDL repo, doing git blame, then `git tag --contains (commit)` etc. + #if SDL_VERSION_ATLEAST(2, 0, 16) + case SDL_CONTROLLER_BUTTON_MISC1: +- return NKCODE_BUTTON_11; ++ return NKCODE_BACK; // pause menu + #endif + #if SDL_VERSION_ATLEAST(2, 0, 28) + case SDL_CONTROLLER_BUTTON_PADDLE1: diff --git a/projects/ArchR/packages/emulators/standalone/ppsspp-sa/scripts/cheevos_ppsspp.sh b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/scripts/cheevos_ppsspp.sh new file mode 100644 index 0000000000..736b642fc6 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/scripts/cheevos_ppsspp.sh @@ -0,0 +1,62 @@ +#! /bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-present Hector Calvarro (https://github.com/kelvfimer) +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile + +PPSSPP_ACHIEVEMENTS="/storage/.config/ppsspp/PSP/SYSTEM/ppsspp_retroachievements.dat" +PPSSPP_INI="/storage/.config/ppsspp/PSP/SYSTEM/ppsspp.ini" +LOG_FILE="/var/log/cheevos.log" + +# Extract username, password, token, if enabled, and hardcore mode from system.cfg +username=$(get_setting "global.retroachievements.username") +password=$(get_setting "global.retroachievements.password") +token=$(get_setting "global.retroachievements.token") +enabled=$(get_setting "global.retroachievements") +hardcore=$(get_setting "global.retroachievements.hardcore") + +# Check if RetroAchievements are enabled in Emulation Station +if [ ! ${enabled} = 1 ]; then + echo "RetroAchievements are not enabled, please turn them on in Emulation Station." > ${LOG_FILE} + sed -i '/^AchievementsEnable =/c\AchievementsEnable = False' ${PPSSPP_INI} + exit 1 +fi + +# Check if api token is present in system.cfg +if [ -z "${token}" ]; then + echo "RetroAchievements token is empty, please log in with your RetroAchievements credentials in Emulation Station." > ${LOG_FILE} + exit 1 +fi + +echo "${token}" > ${PPSSPP_ACHIEVEMENTS} + +# Set hardcore mode +if [ "${hardcore}" = 1 ]; then + hardcore="True" +else + hardcore="False" +fi + +# Update emulator config with RetroAchievements settings +zcheevos=$(grep -Fx "[Achievements]" ${PPSSPP_INI}) +echo "${token}" > ${PPSSPP_ACHIEVEMENTS} + +if [ -z "${zcheevos}" ] +then + echo -e "[Achievements]\nAchievementsEnable = True\nAchievementsUserName = ${username}\nAchievementsChallengeMode = ${hardcore}" >> ${PPSSPP_INI} +else + sed -i '/^AchievementsEnable =/c\AchievementsEnable = True' ${PPSSPP_INI} + if ! grep -q "^AchievementsUserName = " ${PPSSPP_INI}; then + sed -i "/^\[Achievements\]/a AchievementsUserName = ${username}" ${PPSSPP_INI} + else + sed -i "/^\[Achievements\]/,/^\[/{s/^AchievementsUserName = .*/AchievementsUserName = ${username}/;}" ${PPSSPP_INI} + fi + + if ! grep -q "^AchievementsChallengeMode = " ${PPSSPP_INI}; then + sed -i "/^\[Achievements\]/a AchievementsChallengeMode = ${hardcore}" ${PPSSPP_INI} + else + sed -i "/^\[Achievements\]/,/^\[/{s/^AchievementsChallengeMode = .*/AchievementsChallengeMode = ${hardcore}/;}" ${PPSSPP_INI} + fi +fi diff --git a/projects/ArchR/packages/emulators/standalone/ppsspp-sa/scripts/psp_save_mover.sh b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/scripts/psp_save_mover.sh new file mode 100644 index 0000000000..a90e750b65 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/scripts/psp_save_mover.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +#This will copy saves to the correct directory after making changes to PPSSPP +if [ ! -d "/storage/roms/psp/PSP" ]; then + mkdir -p "/storage/roms/psp/PSP" + cp -r /storage/.config/ppsspp/PSP/SAVEDATA /storage/roms/psp/PSP/ +fi + +if [ ! -d "/storage/roms/savestates/psp/ppsspp-sa" ]; then + mkdir -p /storage/roms/savestates/psp/ppsspp-sa + cp -r /storage/.config/ppsspp/PSP/PPSSPP_STATE/* /storage/roms/savestates/psp/ppsspp-sa/ +fi diff --git a/projects/ArchR/packages/emulators/standalone/ppsspp-sa/scripts/start_ppsspp.sh b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/scripts/start_ppsspp.sh new file mode 100755 index 0000000000..9dc391b9e7 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/scripts/start_ppsspp.sh @@ -0,0 +1,133 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile +set_kill set "-9 ppsspp" + +SOURCE_DIR="/usr/config/ppsspp" +CONF_DIR="/storage/.config/ppsspp" +PPSSPP_INI="PSP/SYSTEM/ppsspp.ini" + +# Check if conf dir exists +if [ ! -d "${CONF_DIR}" ] +then + cp -rf ${SOURCE_DIR} ${CONF_DIR} +fi + +# Check if savestate dir exists +if [ ! -d "/storage/roms/savestates/psp/ppsspp-sa" ]; then + mkdir -p "/storage/roms/savestates/psp/ppsspp-sa" +fi + +#Emulation Station Features +GAME=$(echo "${1}"| sed "s#^/.*/##") +PLATFORM=$(echo "${2}"| sed "s#^/.*/##") +ASKIP=$(get_setting auto_frame_skip "${PLATFORM}" "${GAME}") +FPS=$(get_setting show_fps "${PLATFORM}" "${GAME}") +IRES=$(get_setting internal_resolution "${PLATFORM}" "${GAME}") +GRENDERER=$(get_setting graphics_backend "${PLATFORM}" "${GAME}") +SKIPB=$(get_setting skip_buffer_effects "${PLATFORM}" "${GAME}") +VSYNC=$(get_setting vsync "${PLATFORM}" "${GAME}") +CLOCK_SPEED=$(get_setting clock_speed "${PLATFORM}" "${GAME}") + +#Set the cores to use +CORES=$(get_setting "cores" "${PLATFORM}" "${GAME}") +if [ "${CORES}" = "little" ]; then + EMUPERF="${SLOW_CORES}" +elif [ "${CORES}" = "big" ]; then + EMUPERF="${FAST_CORES}" +else + ### All.. + unset EMUPERF +fi + + #Auto Frame Skip — default ON when no explicit setting. RK3326 cannot + #sustain 60fps in heavier PSP titles; without auto-skip the user sees + #15fps stutter instead of a smooth 25-30. Users that prefer no skipping + #can flip the per-platform / per-game setting to "0". + if [ "${ASKIP}" = "0" ]; then + sed -i '/^AutoFrameSkip =/c\AutoFrameSkip = False' ${CONF_DIR}/${PPSSPP_INI} + else + sed -i '/AutoFrameSkip =/c\AutoFrameSkip = True' ${CONF_DIR}/${PPSSPP_INI} + fi + + #Graphics Backend + if [ "${GRENDERER}" = "opengl" ]; then + sed -i '/^GraphicsBackend =/c\GraphicsBackend = 0 (OPENGL)' ${CONF_DIR}/${PPSSPP_INI} + elif [ "${GRENDERER}" = "vulkan" ]; then + sed -i '/^GraphicsBackend =/c\GraphicsBackend = 3 (VULKAN)' ${CONF_DIR}/${PPSSPP_INI} + else + sed -i '/^GraphicsBackend =/c\GraphicsBackend = @GRENDERER@' ${CONF_DIR}/${PPSSPP_INI} + fi + + #Internal Resolution + if [ "${IRES}" = "2" ]; then + sed -i '/^InternalResolution/c\InternalResolution = 2' ${CONF_DIR}/${PPSSPP_INI} + elif [ "${IRES}" = "3" ]; then + sed -i '/^InternalResolution/c\InternalResolution = 3' ${CONF_DIR}/${PPSSPP_INI} + elif [ "${IRES}" = "4" ]; then + sed -i '/^InternalResolution/c\InternalResolution = 4' ${CONF_DIR}/${PPSSPP_INI} + else + sed -i '/^InternalResolution/c\InternalResolution = 1' ${CONF_DIR}/${PPSSPP_INI} + fi + + #Show FPS + if [ "${FPS}" = "1" ]; then + sed -i '/^iShowStatusFlags =/c\iShowStatusFlags = 2' ${CONF_DIR}/${PPSSPP_INI} + else + sed -i '/^iShowStatusFlags =/c\iShowStatusFlags = 0' ${CONF_DIR}/${PPSSPP_INI} + fi + + #Skip Buffer Effects + if [ "${SKIPB}" = "1" ]; then + sed -i '/^SkipBufferEffects =/c\SkipBufferEffects = True' ${CONF_DIR}/${PPSSPP_INI} + else + sed -i '/^SkipBufferEffects =/c\SkipBufferEffects = False' ${CONF_DIR}/${PPSSPP_INI} + fi + + #VSYNC + if [ "${VSYNC}" = "1" ]; then + sed -i '/^VSyncInterval =/c\VSyncInterval = True' ${CONF_DIR}/${PPSSPP_INI} + else + sed -i '/^VSyncInterval =/c\VSyncInterval = False' ${CONF_DIR}/${PPSSPP_INI} + fi + + #Clock Speed + if [ "${CLOCK_SPEED}" = "222" ]; then + sed -i '/^CPUSpeed =/c\CPUSpeed = 222' ${CONF_DIR}/${PPSSPP_INI} + elif [ "${CLOCK_SPEED}" = "333" ]; then + sed -i '/^CPUSpeed =/c\CPUSpeed = 333' ${CONF_DIR}/${PPSSPP_INI} + else + sed -i '/^CPUSpeed =/c\CPUSpeed = 0' ${CONF_DIR}/${PPSSPP_INI} + fi + +#Retroachievements +/usr/bin/cheevos_ppsspp.sh + +ARG=${1//[\\]/} + +# Debugging info: + echo "GAME set to: ${GAME}" + echo "PLATFORM set to: ${PLATFORM}" + echo "CONF DIR: ${CONF_DIR}/${PPSSPP_INI}" + echo "CPU CORES set to: ${EMUPERF}" + echo "AUTO FRAME SKIP set to: ${ASKIP}" + echo "GRAPHICS RENDERER set to: ${GRENDERER}" + echo "INTERNAL RESOLUTION set to: ${IRES}" + echo "FPS set to: ${FPS}" + echo "SKIP BUFFER EFFECTS set to: ${SKIPB}" + echo "VSYNC set to: ${VSYNC}" + echo "Launching /usr/bin/ppsspp ${ARG}" + +# Panfrost optimization: forcepack reduces draw call overhead on Mali-G31 +export PAN_MESA_DEBUG=forcepack +export MESA_NO_ERROR=1 +# Mesa GL command thread: PPSSPP issues many small GL calls per frame +# (sprite/draw bursts) and the standalone build keeps render and CPU on +# separate threads internally. Letting Mesa marshal GL on its own +# thread cuts per-call dispatch latency on Cortex-A35. See +# docs/mesa-glthread-matrix.md. +export MESA_GLTHREAD=true + +${EMUPERF} ppsspp --pause-menu-exit "${ARG}" diff --git a/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/H700/controls.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/H700/controls.ini new file mode 100755 index 0000000000..ecab3f6cb2 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/H700/controls.ini @@ -0,0 +1,25 @@ +[ControlMapping] +Up = 10-19 +Down = 10-20 +Left = 10-21 +Right = 10-22 +Circle = 10-189 +Cross = 10-190 +Square = 10-188 +Triangle = 10-191 +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 +Fast-forward = 1-61 +Pause = 10-106 +Save State = 10-4010 +Load State = 10-4008 +RightAn.Up = 10-4007 +RightAn.Down = 10-4006 +RightAn.Left = 10-4005 +RightAn.Right = 10-4004 diff --git a/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/H700/ppsspp.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/H700/ppsspp.ini new file mode 100755 index 0000000000..8be2d8b3ab --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/H700/ppsspp.ini @@ -0,0 +1,557 @@ +[General] +FirstRun = False +RunCount = 0 +Enable Logging = False +AutoRun = True +Browse = False +IgnoreBadMemAccess = False +CurrentDirectory = /storage/roms/psp +ShowDebuggerOnLoad = False +CheckForNewVersion = False +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 +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 = 1 +AndroidHwScale = 1 +HighQualityDepth = 1 +FrameSkip = 3 +FrameSkipType = 0 +AutoFrameSkip = True +FrameRate = -1 +FrameRate2 = -1 +FrameSkipUnthrottle = True +ForceMaxEmulatedFPS = 30 +AnisotropyLevel = 4 +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 = 0 +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 = 3 +RenderDuplicateFrames = True +ShaderChainRequires60FPS = False +ClearFramebuffersOnFirstUseHack = False +SoftwareRendererJit = True +UnthrottlingMode = CONTINUOUS +ReplaceTexturesAllowLate = True +iShowStatusFlags = 0 +AndroidFramerateMode = 1 +UseGeometryShader = False +SkipBufferEffects = False +DisableRangeCulling = False +Smart2DTexFiltering = False +StereoRendering = False +StereoToMonoShader = RedBlue +AnalogFrameRate = 240 +MultiSampleLevel = 0 +DisplayOffsetX = 0.500000 +DisplayOffsetY = 0.500000 +DisplayScale = 1.000000 +DisplayIntegerScale = False +DisplayAspectRatio = 1.000000 +DisplayStretch = False +DisplayCropTo16x9 = False +VSync = True +SkipGPUReadbackMode = 1 +MultiThreading = True +GpuLogProfiler = False +UberShaderVertex = True +UberShaderFragment = True +[Sound] +Enable = True +AudioBackend = 0 +AudioLatency = 1 +ExtraAudioBuffering = False +SoundSpeedHack = False +AudioResampler = False +GlobalVolume = 10 +AltSpeedVolume = -1 +AutoAudioDevice = True +ReverbVolume = 10 +AchievementSoundVolume = 6 +AudioDevice = +[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 +ThemeName = Default +[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 +[VR] +VREnable = True +VREnable6DoF = True +VREnableStereo = False +VREnableMotions = True +VRForce72Hz = True +VRManualForceVR = False +VRPassthrough = False +VRRescaleHUD = True +VRCameraDistance = 0.000000 +VRCameraHeight = 0.000000 +VRCameraSide = 0.000000 +VRCameraPitch = 0 +VRCanvasDistance = 12.000000 +VRCanvas3DDistance = 3.000000 +VRHeadUpDisplayScale = 0.300000 +VRMotionLength = 0.500000 +VRHeadRotationScale = 5.000000 +VRHeadRotationEnabled = False +VRHeadRotationSmoothing = False diff --git a/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/InputPlumber/controls.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/InputPlumber/controls.ini new file mode 100644 index 0000000000..a18390fa46 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/InputPlumber/controls.ini @@ -0,0 +1,26 @@ +[ControlMapping] +Up = 10-19 +Down = 10-20 +Left = 10-21 +Right = 10-22 +Circle = 10-190 +Cross = 10-189 +Square = 10-191 +Triangle = 10-188 +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-198:10-188,10-4 +Save State = 10-198:10-192 +Load State = 10-198:10-193 +RightAn.Up = 10-4007 +RightAn.Down = 10-4006 +RightAn.Left = 10-4005 +RightAn.Right = 10-4004 +Fast-forward = 10-198:10-4010 +Exit App = 10-198:10-197 diff --git a/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/RK3326/controls.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/RK3326/controls.ini new file mode 100755 index 0000000000..213f7119a3 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/RK3326/controls.ini @@ -0,0 +1,25 @@ +[ControlMapping] +Up = 10-19 +Down = 10-20 +Left = 10-21 +Right = 10-22 +Circle = 10-189 +Cross = 10-190 +Square = 10-188 +Triangle = 10-191 +Start = 10-197 +Select = 10-196 +L = 10-193 +R = 10-192 +An.Up = 10-4002 +An.Down = 10-4003 +An.Left = 10-4000 +An.Right = 10-4001 +Fast-forward = 1-61 +Pause = 10-106 +Save State = 10-4010 +Load State = 10-4008 +RightAn.Up = 10-4007 +RightAn.Down = 10-4006 +RightAn.Left = 10-4005 +RightAn.Right = 10-4004 diff --git a/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/RK3326/ppsspp.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/RK3326/ppsspp.ini new file mode 100755 index 0000000000..73a47bbab1 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/RK3326/ppsspp.ini @@ -0,0 +1,557 @@ +[General] +FirstRun = False +RunCount = 0 +Enable Logging = False +AutoRun = True +Browse = False +IgnoreBadMemAccess = False +CurrentDirectory = /storage/roms/psp +ShowDebuggerOnLoad = False +CheckForNewVersion = False +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 +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 = 1 +AndroidHwScale = 1 +HighQualityDepth = 0 +FrameSkip = 3 +FrameSkipType = 0 +AutoFrameSkip = True +FrameRate = -1 +FrameRate2 = -1 +FrameSkipUnthrottle = True +ForceMaxEmulatedFPS = 30 +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 = 0 +TexDeposterize = False +VSyncInterval = True +DisableStencilTest = False +BloomHack = 0 +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 = 3 +RenderDuplicateFrames = True +ShaderChainRequires60FPS = False +ClearFramebuffersOnFirstUseHack = False +SoftwareRendererJit = True +UnthrottlingMode = CONTINUOUS +ReplaceTexturesAllowLate = True +iShowStatusFlags = 0 +AndroidFramerateMode = 1 +UseGeometryShader = False +SkipBufferEffects = False +DisableRangeCulling = False +Smart2DTexFiltering = False +StereoRendering = False +StereoToMonoShader = RedBlue +AnalogFrameRate = 240 +MultiSampleLevel = 0 +DisplayOffsetX = 0.500000 +DisplayOffsetY = 0.500000 +DisplayScale = 1.000000 +DisplayIntegerScale = False +DisplayAspectRatio = 1.000000 +DisplayStretch = False +DisplayCropTo16x9 = False +VSync = True +SkipGPUReadbackMode = 1 +MultiThreading = True +GpuLogProfiler = False +UberShaderVertex = True +UberShaderFragment = True +[Sound] +Enable = True +AudioBackend = 0 +AudioLatency = 2 +ExtraAudioBuffering = False +SoundSpeedHack = False +AudioResampler = False +GlobalVolume = 10 +AltSpeedVolume = -1 +AutoAudioDevice = True +ReverbVolume = 10 +AchievementSoundVolume = 6 +AudioDevice = +[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 +ThemeName = Default +[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 +[VR] +VREnable = True +VREnable6DoF = True +VREnableStereo = False +VREnableMotions = True +VRForce72Hz = True +VRManualForceVR = False +VRPassthrough = False +VRRescaleHUD = True +VRCameraDistance = 0.000000 +VRCameraHeight = 0.000000 +VRCameraSide = 0.000000 +VRCameraPitch = 0 +VRCanvasDistance = 12.000000 +VRCanvas3DDistance = 3.000000 +VRHeadUpDisplayScale = 0.300000 +VRMotionLength = 0.500000 +VRHeadRotationScale = 5.000000 +VRHeadRotationEnabled = False +VRHeadRotationSmoothing = False diff --git a/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/RK3399/controls.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/RK3399/controls.ini new file mode 100644 index 0000000000..a9ab9b25ea --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/RK3399/controls.ini @@ -0,0 +1,24 @@ +[ControlMapping] +Up = 10-19 +Down = 10-20 +Left = 10-21 +Right = 10-22 +Circle = 10-189 +Cross = 10-190 +Square = 10-188 +Triangle = 10-191 +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-106 +Save State = 10-4010 +Load State = 10-4008 +RightAn.Up = 10-4007 +RightAn.Down = 10-4006 +RightAn.Left = 10-4005 +RightAn.Right = 10-4004 diff --git a/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/RK3399/ppsspp.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/RK3399/ppsspp.ini new file mode 100644 index 0000000000..90dc514327 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/RK3399/ppsspp.ini @@ -0,0 +1,557 @@ +[General] +FirstRun = False +RunCount = 0 +Enable Logging = False +AutoRun = True +Browse = False +IgnoreBadMemAccess = False +CurrentDirectory = /storage/roms/psp +ShowDebuggerOnLoad = False +CheckForNewVersion = False +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 +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 = 1 +AndroidHwScale = 1 +HighQualityDepth = 1 +FrameSkip = 3 +FrameSkipType = 0 +AutoFrameSkip = True +FrameRate = -1 +FrameRate2 = -1 +FrameSkipUnthrottle = True +ForceMaxEmulatedFPS = 30 +AnisotropyLevel = 4 +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 = 0 +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 = 3 +RenderDuplicateFrames = True +ShaderChainRequires60FPS = False +ClearFramebuffersOnFirstUseHack = False +SoftwareRendererJit = True +UnthrottlingMode = CONTINUOUS +ReplaceTexturesAllowLate = True +iShowStatusFlags = 0 +AndroidFramerateMode = 1 +UseGeometryShader = False +SkipBufferEffects = False +DisableRangeCulling = False +Smart2DTexFiltering = False +StereoRendering = False +StereoToMonoShader = RedBlue +AnalogFrameRate = 240 +MultiSampleLevel = 0 +DisplayOffsetX = 0.500000 +DisplayOffsetY = 0.500000 +DisplayScale = 1.000000 +DisplayIntegerScale = False +DisplayAspectRatio = 1.000000 +DisplayStretch = False +DisplayCropTo16x9 = False +VSync = True +SkipGPUReadbackMode = 1 +MultiThreading = True +GpuLogProfiler = False +UberShaderVertex = True +UberShaderFragment = True +[Sound] +Enable = True +AudioBackend = 0 +AudioLatency = 1 +ExtraAudioBuffering = False +SoundSpeedHack = False +AudioResampler = False +GlobalVolume = 10 +AltSpeedVolume = -1 +AutoAudioDevice = True +ReverbVolume = 10 +AchievementSoundVolume = 6 +AudioDevice = +[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 +ThemeName = Default +[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 +[VR] +VREnable = True +VREnable6DoF = True +VREnableStereo = False +VREnableMotions = True +VRForce72Hz = True +VRManualForceVR = False +VRPassthrough = False +VRRescaleHUD = True +VRCameraDistance = 0.000000 +VRCameraHeight = 0.000000 +VRCameraSide = 0.000000 +VRCameraPitch = 0 +VRCanvasDistance = 12.000000 +VRCanvas3DDistance = 3.000000 +VRHeadUpDisplayScale = 0.300000 +VRMotionLength = 0.500000 +VRHeadRotationScale = 5.000000 +VRHeadRotationEnabled = False +VRHeadRotationSmoothing = False diff --git a/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/RK3566/controls.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/RK3566/controls.ini new file mode 100644 index 0000000000..aedbae2cf7 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/RK3566/controls.ini @@ -0,0 +1,20 @@ +[ControlMapping] +Up = 10-19 +Down = 10-20 +Left = 10-21 +Right = 10-22 +Circle = 10-190 +Cross = 10-189 +Square = 10-188 +Triangle = 10-191 +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-4,10-106 +Save State = 10-4010 +Load State = 10-4008 diff --git a/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/RK3566/ppsspp.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/RK3566/ppsspp.ini new file mode 100755 index 0000000000..8be2d8b3ab --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/RK3566/ppsspp.ini @@ -0,0 +1,557 @@ +[General] +FirstRun = False +RunCount = 0 +Enable Logging = False +AutoRun = True +Browse = False +IgnoreBadMemAccess = False +CurrentDirectory = /storage/roms/psp +ShowDebuggerOnLoad = False +CheckForNewVersion = False +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 +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 = 1 +AndroidHwScale = 1 +HighQualityDepth = 1 +FrameSkip = 3 +FrameSkipType = 0 +AutoFrameSkip = True +FrameRate = -1 +FrameRate2 = -1 +FrameSkipUnthrottle = True +ForceMaxEmulatedFPS = 30 +AnisotropyLevel = 4 +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 = 0 +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 = 3 +RenderDuplicateFrames = True +ShaderChainRequires60FPS = False +ClearFramebuffersOnFirstUseHack = False +SoftwareRendererJit = True +UnthrottlingMode = CONTINUOUS +ReplaceTexturesAllowLate = True +iShowStatusFlags = 0 +AndroidFramerateMode = 1 +UseGeometryShader = False +SkipBufferEffects = False +DisableRangeCulling = False +Smart2DTexFiltering = False +StereoRendering = False +StereoToMonoShader = RedBlue +AnalogFrameRate = 240 +MultiSampleLevel = 0 +DisplayOffsetX = 0.500000 +DisplayOffsetY = 0.500000 +DisplayScale = 1.000000 +DisplayIntegerScale = False +DisplayAspectRatio = 1.000000 +DisplayStretch = False +DisplayCropTo16x9 = False +VSync = True +SkipGPUReadbackMode = 1 +MultiThreading = True +GpuLogProfiler = False +UberShaderVertex = True +UberShaderFragment = True +[Sound] +Enable = True +AudioBackend = 0 +AudioLatency = 1 +ExtraAudioBuffering = False +SoundSpeedHack = False +AudioResampler = False +GlobalVolume = 10 +AltSpeedVolume = -1 +AutoAudioDevice = True +ReverbVolume = 10 +AchievementSoundVolume = 6 +AudioDevice = +[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 +ThemeName = Default +[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 +[VR] +VREnable = True +VREnable6DoF = True +VREnableStereo = False +VREnableMotions = True +VRForce72Hz = True +VRManualForceVR = False +VRPassthrough = False +VRRescaleHUD = True +VRCameraDistance = 0.000000 +VRCameraHeight = 0.000000 +VRCameraSide = 0.000000 +VRCameraPitch = 0 +VRCanvasDistance = 12.000000 +VRCanvas3DDistance = 3.000000 +VRHeadUpDisplayScale = 0.300000 +VRMotionLength = 0.500000 +VRHeadRotationScale = 5.000000 +VRHeadRotationEnabled = False +VRHeadRotationSmoothing = False diff --git a/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/RK3588/controls.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/RK3588/controls.ini new file mode 100644 index 0000000000..83c19ca1b2 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/RK3588/controls.ini @@ -0,0 +1,18 @@ +[ControlMapping] +Up = 10-19 +Down = 10-20 +Left = 10-21 +Right = 10-22 +Circle = 10-189 +Cross = 10-190 +Square = 10-188 +Triangle = 10-191 +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/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/RK3588/ppsspp.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/RK3588/ppsspp.ini new file mode 100755 index 0000000000..52c30f6c78 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/RK3588/ppsspp.ini @@ -0,0 +1,511 @@ +[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 = 0 +FrameSkipType = 0 +AutoFrameSkip = False +FrameRate = 0 +FrameRate2 = -1 +FrameSkipUnthrottle = True +ForceMaxEmulatedFPS = 30 +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 +AutoAudioDevice = True +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/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/S922X/controls.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/S922X/controls.ini new file mode 100755 index 0000000000..cfd01a7f7b --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/S922X/controls.ini @@ -0,0 +1,24 @@ +[ControlMapping] +Up = 10-19 +Down = 10-20 +Left = 10-21 +Right = 10-22 +Circle = 10-189 +Cross = 10-190 +Square = 10-188 +Triangle = 10-191 +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 +Analog limiter = 1-60 +RapidFire = 1-59 +SpeedToggle = 1-68 +Pause = 1-111,10-106,10-104 +Rewind = 1-67 +Save State = 10-4010 +Load State = 10-4008 diff --git a/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/S922X/ppsspp.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/S922X/ppsspp.ini new file mode 100755 index 0000000000..0ed304c815 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/S922X/ppsspp.ini @@ -0,0 +1,462 @@ +[General] +FirstRun = False +RunCount = 3 +Enable Logging = True +AutoRun = True +Browse = False +IgnoreBadMemAccess = True +CurrentDirectory = /storage +ShowDebuggerOnLoad = False +CheckForNewVersion = True +Language = en_US +ForceLagSync2 = False +DiscordPresence = True +UISound = False +AutoLoadSaveState = 0 +EnableCheats = True +CwCheatRefreshRate = 77 +CwCheatScrollPosition = 0.000000 +GameListScrollPosition = 0.000000 +ScreenshotsAsPNG = False +UseFFV1 = False +DumpFrames = False +DumpVideoOutput = False +DumpAudio = False +SaveLoadResetsAVdumping = False +StateSlot = 0 +EnableStateUndo = True +StateLoadUndoGame = NA +StateUndoLastSaveGame = NA +StateUndoLastSaveSlot = -5 +RewindSnapshotInterval = 0 +ShowOnScreenMessage = True +ShowRegionOnGameIcon = False +ShowIDOnGameIcon = False +GameGridScale = 1.000000 +GridView1 = True +GridView2 = True +GridView3 = False +RightAnalogUp = 0 +RightAnalogDown = 0 +RightAnalogLeft = 0 +RightAnalogRight = 0 +RightAnalogPress = 0 +RightAnalogCustom = False +RightAnalogDisableDiagonal = False +SwipeUp = 0 +SwipeDown = 0 +SwipeLeft = 0 +SwipeRight = 0 +SwipeSensitivity = 1.000000 +SwipeSmoothing = 0.300000 +DoubleTapGesture = 0 +GestureControlEnabled = False +ReportingHost = default +AutoSaveSymbolMap = False +CacheFullIsoInRam = False +RemoteISOPort = 0 +LastRemoteISOServer = +LastRemoteISOPort = 0 +RemoteISOManualConfig = False +RemoteShareOnStartup = False +RemoteISOSubdir = / +RemoteDebuggerOnStartup = False +InternalScreenRotation = 1 +BackgroundAnimation = 1 +TransparentBackground = True +UITint = 0.000000 +UISaturation = 1.000000 +PauseWhenMinimized = False +DumpDecryptedEboots = False +ShowMenuBar = True +MemStickInserted = True +EnablePlugins = True +IgnoreCompatSettings = +[CPU] +CPUCore = 1 +SeparateSASThread = True +IOTimingMethod = 0 +FastMemoryAccess = True +FunctionReplacements = True +HideSlowWarnings = False +HideStateWarnings = False +PreloadFunctions = False +JitDisableFlags = 0x00000000 +CPUSpeed = 0 +[Graphics] +EnableCardboardVR = False +CardboardScreenSize = 50 +CardboardXShift = 0 +CardboardYShift = 0 +iShowStatusFlags = 0 +GraphicsBackend = 3 (VULKAN) +FailedGraphicsBackends = +DisabledGraphicsBackends = +VulkanDevice = +CameraDevice = +UseGeometryShader = False +SkipBufferEffects = False +SoftwareRenderer = False +SoftwareRendererJit = True +HardwareTransform = True +SoftwareSkinning = True +TextureFiltering = 1 +BufferFiltering = 1 +InternalResolution = 1 +HighQualityDepth = 1 +FrameSkip = 0 +FrameSkipType = 0 +AutoFrameSkip = False +StereoRendering = False +StereoToMonoShader = RedBlue +FrameRate = 0 +FrameRate2 = -1 +AnalogFrameRate = 240 +AnalogFrameRateMode = 0 +UnthrottlingMode = CONTINUOUS +AnisotropyLevel = 4 +MultiSampleLevel = 0 +VertexDecCache = False +TextureBackoffCache = False +FullScreen = True +FullScreenMulti = False +DisplayOffsetX = 0.500000 +DisplayOffsetY = 0.500000 +DisplayScale = 1.000000 +DisplayAspectRatio = 1.000000 +DisplayStretch = False +ImmersiveMode = True +SustainedPerformanceMode = False +IgnoreScreenInsets = True +ReplaceTextures = True +SaveNewTextures = False +IgnoreTextureFilenames = False +ReplaceTexturesAllowLate = True +TexScalingLevel = 1 +TexScalingType = 0 +TexDeposterize = False +TexHardwareScaling = False +VSyncInterval = False +BloomHack = 0 +SplineBezierQuality = 2 +HardwareTessellation = False +TextureShader = Off +ShaderChainRequires60FPS = False +SkipGPUReadbacks = False +LogFrameDrops = False +InflightFrames = 3 +RenderDuplicateFrames = False +GpuLogProfiler = False +[Sound] +Enable = True +AudioBackend = 0 +ExtraAudioBuffering = False +GlobalVolume = 10 +ReverbVolume = 10 +AltSpeedVolume = -1 +AudioDevice = +AutoAudioDevice = True +[Control] +HapticFeedback = False +ShowTouchCross = True +ShowTouchCircle = True +ShowTouchSquare = True +ShowTouchTriangle = True +Custom0Mapping = 0x0000000000000000 +Custom0Image = 0 +Custom0Shape = 0 +Custom0Toggle = False +Custom0Repeat = False +Custom1Mapping = 0x0000000000000000 +Custom1Image = 1 +Custom1Shape = 0 +Custom1Toggle = False +Custom1Repeat = False +Custom2Mapping = 0x0000000000000000 +Custom2Image = 2 +Custom2Shape = 0 +Custom2Toggle = False +Custom2Repeat = False +Custom3Mapping = 0x0000000000000000 +Custom3Image = 3 +Custom3Shape = 0 +Custom3Toggle = False +Custom3Repeat = False +Custom4Mapping = 0x0000000000000000 +Custom4Image = 4 +Custom4Shape = 0 +Custom4Toggle = False +Custom4Repeat = False +Custom5Mapping = 0x0000000000000000 +Custom5Image = 0 +Custom5Shape = 1 +Custom5Toggle = False +Custom5Repeat = False +Custom6Mapping = 0x0000000000000000 +Custom6Image = 1 +Custom6Shape = 1 +Custom6Toggle = False +Custom6Repeat = False +Custom7Mapping = 0x0000000000000000 +Custom7Image = 2 +Custom7Shape = 1 +Custom7Toggle = False +Custom7Repeat = False +Custom8Mapping = 0x0000000000000000 +Custom8Image = 3 +Custom8Shape = 1 +Custom8Toggle = False +Custom8Repeat = False +Custom9Mapping = 0x0000000000000000 +Custom9Image = 4 +Custom9Shape = 1 +Custom9Toggle = False +Custom9Repeat = False +ShowTouchPause = False +ShowTouchControls = False +DisableDpadDiagonals = False +GamepadOnlyFocused = False +TouchButtonStyle = 1 +TouchButtonOpacity = 65 +TouchButtonHideSeconds = 20 +AutoCenterTouchAnalog = False +AnalogAutoRotSpeed = 8.000000 +TouchSnapToGrid = False +TouchSnapGridSize = 64 +ActionButtonSpacing2 = 1.000000 +ActionButtonCenterX = 0.859485 +ActionButtonCenterY = 0.750000 +ActionButtonScale = 1.150000 +DPadX = 0.167447 +DPadY = 0.400000 +DPadScale = 1.150000 +ShowTouchDpad = True +DPadSpacing = 1.000000 +StartKeyX = 0.634660 +StartKeyY = 0.856250 +StartKeyScale = 1.150000 +ShowTouchStart = True +SelectKeyX = 0.500000 +SelectKeyY = 0.856250 +SelectKeyScale = 1.150000 +ShowTouchSelect = True +UnthrottleKeyX = 0.365340 +UnthrottleKeyY = 0.856250 +UnthrottleKeyScale = 1.150000 +ShowTouchUnthrottle = True +LKeyX = 0.080796 +LKeyY = 0.089583 +LKeyScale = 1.150000 +ShowTouchLTrigger = True +RKeyX = 0.919204 +RKeyY = 0.089583 +RKeyScale = 1.150000 +ShowTouchRTrigger = True +AnalogStickX = 0.167447 +AnalogStickY = 0.808333 +AnalogStickScale = 1.150000 +ShowAnalogStick = True +RightAnalogStickX = 0.859485 +RightAnalogStickY = 0.808333 +RightAnalogStickScale = 1.150000 +ShowRightAnalogStick = False +fcombo0X = 0.661592 +fcombo0Y = 0.500000 +comboKeyScale0 = 1.150000 +ShowComboKey0 = False +fcombo1X = 0.796253 +fcombo1Y = 0.500000 +comboKeyScale1 = 1.150000 +ShowComboKey1 = False +fcombo2X = 0.930913 +fcombo2Y = 0.500000 +comboKeyScale2 = 1.150000 +ShowComboKey2 = False +fcombo3X = 0.661592 +fcombo3Y = 0.333333 +comboKeyScale3 = 1.150000 +ShowComboKey3 = False +fcombo4X = 0.796253 +fcombo4Y = 0.333333 +comboKeyScale4 = 1.150000 +ShowComboKey4 = False +fcombo5X = 0.338407 +fcombo5Y = 0.500000 +comboKeyScale5 = 1.150000 +ShowComboKey5 = False +fcombo6X = 0.203747 +fcombo6Y = 0.500000 +comboKeyScale6 = 1.150000 +ShowComboKey6 = False +fcombo7X = 0.069087 +fcombo7Y = 0.500000 +comboKeyScale7 = 1.150000 +ShowComboKey7 = False +fcombo8X = 0.338407 +fcombo8Y = 0.333333 +comboKeyScale8 = 1.150000 +ShowComboKey8 = False +fcombo9X = 0.203747 +fcombo9Y = 0.333333 +comboKeyScale9 = 1.150000 +ShowComboKey9 = False +AnalogDeadzone = 0.150000 +AnalogInverseDeadzone = 0.000000 +AnalogSensitivity = 1.100000 +AnalogIsCircular = False +AnalogLimiterDeadzone = 0.600000 +LeftStickHeadScale = 1.000000 +RightStickHeadScale = 1.000000 +HideStickBackground = False +UseMouse = False +MapMouse = False +ConfineMap = False +MouseSensitivity = 0.100000 +MouseSmoothing = 0.900000 +SystemControls = True +[Network] +EnableWlan = False +EnableAdhocServer = False +proAdhocServer = socom.cc +PortOffset = 10000 +MinTimeout = 0 +ForcedFirstConnect = False +EnableUPnP = False +UPnPUseOriginalPort = False +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 +[SystemParam] +PSPModel = 1 +PSPFirmwareVersion = 660 +NickName = PPSSPP +MacAddress = dc:39:74:d2:dd:86 +Language = 1 +ParamTimeFormat = 0 +ParamDateFormat = 0 +TimeZone = 0 +DayLightSavings = False +ButtonPreference = 1 +LockParentalLevel = 0 +WlanAdhocChannel = 0 +WlanPowerSave = False +EncryptSave = True +SavedataUpgradeVersion = True +MemStickSize = 16 +[Debugger] +DisasmWindowX = -1 +DisasmWindowY = -1 +DisasmWindowW = -1 +DisasmWindowH = -1 +GEWindowX = -1 +GEWindowY = -1 +GEWindowW = -1 +GEWindowH = -1 +GEWindowTabsBL = 0x00000000 +GEWindowTabsBR = 0x00000000 +GEWindowTabsTR = 0x00000000 +ConsoleWindowX = -1 +ConsoleWindowY = -1 +FontWidth = 8 +FontHeight = 12 +DisplayStatusBar = True +ShowBottomTabTitles = True +ShowDeveloperMenu = False +SkipDeadbeefFilling = False +FuncHashMap = False +MemInfoDetailed = False +DrawFrameGraph = False +[Upgrade] +UpgradeMessage = +UpgradeVersion = +DismissedVersion = +[Theme] +ThemeName = Default +[VR] +VREnable = True +VREnable6DoF = True +VREnableStereo = False +VREnableMotions = True +VRForce72Hz = True +VRManualForceVR = False +VRCameraDistance = 0.000000 +VRCameraHeight = 0.000000 +VRCameraSide = 0.000000 +VRCanvasDistance = 12.000000 +VRFieldOfView = 100.000000 +VRHeadUpDisplayScale = 0.300000 +VRMotionLength = 0.500000 +VRHeadRotationScale = 5.000000 +VRHeadRotationSmoothing = False +VRHeadRotation = 0 +[Recent] +MaxRecent = 60 +FileName0 = /storage/roms/psp/Final Fantasy III.iso +FileName1 = /storage/roms/psp/Final Fantasy II.iso +[Log] +SYSTEMEnabled = True +SYSTEMLevel = 2 +BOOTEnabled = True +BOOTLevel = 2 +COMMONEnabled = True +COMMONLevel = 2 +CPUEnabled = True +CPULevel = 2 +FILESYSEnabled = True +FILESYSLevel = 2 +G3DEnabled = True +G3DLevel = 2 +HLEEnabled = True +HLELevel = 2 +JITEnabled = True +JITLevel = 2 +LOADEREnabled = True +LOADERLevel = 2 +MEEnabled = True +MELevel = 2 +MEMMAPEnabled = True +MEMMAPLevel = 2 +SASMIXEnabled = True +SASMIXLevel = 2 +SAVESTATEEnabled = True +SAVESTATELevel = 2 +FRAMEBUFEnabled = True +FRAMEBUFLevel = 2 +AUDIOEnabled = True +AUDIOLevel = 2 +IOEnabled = True +IOLevel = 2 +SCEAUDIOEnabled = True +SCEAUDIOLevel = 2 +SCECTRLEnabled = True +SCECTRLLevel = 2 +SCEDISPEnabled = True +SCEDISPLevel = 2 +SCEFONTEnabled = True +SCEFONTLevel = 2 +SCEGEEnabled = True +SCEGELevel = 2 +SCEINTCEnabled = True +SCEINTCLevel = 2 +SCEIOEnabled = True +SCEIOLevel = 2 +SCEKERNELEnabled = True +SCEKERNELLevel = 2 +SCEMODULEEnabled = True +SCEMODULELevel = 2 +SCENETEnabled = True +SCENETLevel = 2 +SCERTCEnabled = True +SCERTCLevel = 2 +SCESASEnabled = True +SCESASLevel = 2 +SCEUTILEnabled = True +SCEUTILLevel = 2 +SCEMISCEnabled = True +SCEMISCLevel = 2 diff --git a/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/SDM845/controls.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/SDM845/controls.ini new file mode 100644 index 0000000000..64abd2cb80 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/SDM845/controls.ini @@ -0,0 +1,27 @@ +[ControlMapping] +Up = 10-19 +Down = 10-20 +Left = 10-21 +Right = 10-22 +Circle = 10-189 +Cross = 10-190 +Square = 10-188 +Triangle = 10-191 +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-4,10-198:10-191,10-106 +Save State = 10-198:10-192 +Load State = 10-198:10-193 +RightAn.Up = 10-4007 +RightAn.Down = 10-4006 +RightAn.Left = 10-4005 +RightAn.Right = 10-4004 +Fast-forward = 10-198:10-4010 +Reset = 10-198:10-190 +Exit App = 10-4:10-197 diff --git a/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/SDM845/ppsspp.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/SDM845/ppsspp.ini new file mode 100644 index 0000000000..acc403c601 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/SDM845/ppsspp.ini @@ -0,0 +1,690 @@ +[General] +FirstRun = False +RunCount = 0 +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 +RewindSnapshotInterval = 0 +TransparentBackground = True +UITint = 0.000000 +UISaturation = 1.000000 +WindowX = -1 +WindowY = -1 +WindowWidth = 0 +WindowHeight = 0 +ShowMenuBar = True +IgnoreCompatSettings = +DiscordRichPresence = False +RemoteTab = False +RemoteISOSharedDir = +RemoteISOShareType = 0 +RunBehindPauseMenu = False +ShowGPOLEDs = False +[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 = 0 +FrameSkipType = 0 +AutoFrameSkip = False +FrameRate = 0 +FrameRate2 = -1 +FrameSkipUnthrottle = True +ForceMaxEmulatedFPS = 30 +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 +iShowStatusFlags = 0 +UseGeometryShader = False +SkipBufferEffects = False +StereoRendering = False +StereoToMonoShader = RedBlue +AnalogFrameRate = 240 +MultiSampleLevel = 0 +DisplayOffsetX = 0.500000 +DisplayOffsetY = 0.500000 +DisplayScale = 1.000000 +DisplayIntegerScale = False +DisplayAspectRatio = 1.000000 +DisplayStretch = False +SkipGPUReadbacks = False +GpuLogProfiler = False +CameraMirrorHorizontal = False +AndroidFramerateMode = 1 +DisableRangeCulling = False +Smart2DTexFiltering = False +DisplayCropTo16x9 = True +VSync = False +SkipGPUReadbackMode = 0 +MultiThreading = True +UberShaderVertex = True +UberShaderFragment = True +DisplayRefreshRate = 60 +[Sound] +Enable = True +AudioBackend = 0 +AudioLatency = 1 +ExtraAudioBuffering = False +SoundSpeedHack = False +AudioResampler = False +GlobalVolume = 10 +AltSpeedVolume = -1 +AutoAudioDevice = True +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 +Custom0Repeat = False +Custom1Repeat = False +Custom2Repeat = False +Custom3Repeat = False +Custom4Repeat = False +Custom5Repeat = False +Custom6Repeat = False +Custom7Repeat = False +Custom8Repeat = False +Custom9Repeat = False +Custom10Mapping = 0x0000000000000000 +Custom10Image = 0 +Custom10Shape = 2 +Custom10Toggle = False +Custom10Repeat = False +Custom11Mapping = 0x0000000000000000 +Custom11Image = 1 +Custom11Shape = 2 +Custom11Toggle = False +Custom11Repeat = False +Custom12Mapping = 0x0000000000000000 +Custom12Image = 2 +Custom12Shape = 2 +Custom12Toggle = False +Custom12Repeat = False +Custom13Mapping = 0x0000000000000000 +Custom13Image = 3 +Custom13Shape = 2 +Custom13Toggle = False +Custom13Repeat = False +Custom14Mapping = 0x0000000000000000 +Custom14Image = 4 +Custom14Shape = 2 +Custom14Toggle = False +Custom14Repeat = False +Custom15Mapping = 0x0000000000000000 +Custom15Image = 0 +Custom15Shape = 9 +Custom15Toggle = False +Custom15Repeat = False +Custom16Mapping = 0x0000000000000000 +Custom16Image = 1 +Custom16Shape = 9 +Custom16Toggle = False +Custom16Repeat = False +Custom17Mapping = 0x0000000000000000 +Custom17Image = 2 +Custom17Shape = 9 +Custom17Toggle = False +Custom17Repeat = False +Custom18Mapping = 0x0000000000000000 +Custom18Image = 3 +Custom18Shape = 9 +Custom18Toggle = False +Custom18Repeat = False +Custom19Mapping = 0x0000000000000000 +Custom19Image = 4 +Custom19Shape = 9 +Custom19Toggle = False +Custom19Repeat = False +fcombo10X = 0.571875 +fcombo10Y = 0.582465 +comboKeyScale10 = 1.150000 +ShowComboKey10 = False +fcombo11X = 0.631771 +fcombo11Y = 0.582465 +comboKeyScale11 = 1.150000 +ShowComboKey11 = False +fcombo12X = 0.691667 +fcombo12Y = 0.582465 +comboKeyScale12 = 1.150000 +ShowComboKey12 = False +fcombo13X = 0.571875 +fcombo13Y = 0.415799 +comboKeyScale13 = 1.150000 +ShowComboKey13 = False +fcombo14X = 0.631771 +fcombo14Y = 0.415799 +comboKeyScale14 = 1.150000 +ShowComboKey14 = False +fcombo15X = 0.428125 +fcombo15Y = 0.582465 +comboKeyScale15 = 1.150000 +ShowComboKey15 = False +fcombo16X = 0.368229 +fcombo16Y = 0.582465 +comboKeyScale16 = 1.150000 +ShowComboKey16 = False +fcombo17X = 0.308333 +fcombo17Y = 0.582465 +comboKeyScale17 = 1.150000 +ShowComboKey17 = False +fcombo18X = 0.428125 +fcombo18Y = 0.415799 +comboKeyScale18 = 1.150000 +ShowComboKey18 = False +fcombo19X = 0.368229 +fcombo19Y = 0.415799 +comboKeyScale19 = 1.150000 +ShowComboKey19 = False +StickyTouchDPad = False +AnalogTriggerThreshold = 0.750000 +AllowMappingCombos = True +StrictComboOrder = False +MouseWheelUpDelayMs = 80 +RapidFileInterval = 5 +AnalogGesture = False +AnalogGestureSensibility = 1.000000 +[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 +GEWindowTabsBL = 0x00000000 +GEWindowTabsBR = 0x00000000 +GEWindowTabsTR = 0x00000000 +SkipFuncHashMap = +[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 +ThemeName = Default +[Recent] +MaxRecent = 30 +FileName0 = +[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 +[VR] +VREnable = True +VREnable6DoF = True +VREnableStereo = False +VREnableMotions = True +VRForce72Hz = True +VRManualForceVR = False +VRPassthrough = False +VRRescaleHUD = True +VRCameraDistance = 0.000000 +VRCameraHeight = 0.000000 +VRCameraSide = 0.000000 +VRCameraPitch = 0 +VRCanvasDistance = 12.000000 +VRFieldOfView = 100.000000 +VRHeadUpDisplayScale = 0.300000 +VRMotionLength = 0.500000 +VRHeadRotationScale = 5.000000 +VRHeadRotationEnabled = False +VRHeadRotationSmoothing = False +VRForce = False +VRImmersiveMode = True +VRCanvas3DDistance = 3.000000 diff --git a/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/SM8250/controls.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/SM8250/controls.ini new file mode 100644 index 0000000000..d8d8a8611a --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/SM8250/controls.ini @@ -0,0 +1,27 @@ +[ControlMapping] +Up = 10-19 +Down = 10-20 +Left = 10-21 +Right = 10-22 +Circle = 10-189 +Cross = 10-190 +Square = 10-188 +Triangle = 10-191 +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-4,10-198:10-191,10-106 +Save State = 10-198:10-192 +Load State = 10-198:10-193 +RightAn.Up = 10-4007 +RightAn.Down = 10-4006 +RightAn.Left = 10-4005 +RightAn.Right = 10-4004 +Fast-forward = 10-198:10-4010 +Reset = 10-198:10-190 +Exit App = 10-198:10-197 diff --git a/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/SM8250/ppsspp.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/SM8250/ppsspp.ini new file mode 100644 index 0000000000..acc403c601 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/SM8250/ppsspp.ini @@ -0,0 +1,690 @@ +[General] +FirstRun = False +RunCount = 0 +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 +RewindSnapshotInterval = 0 +TransparentBackground = True +UITint = 0.000000 +UISaturation = 1.000000 +WindowX = -1 +WindowY = -1 +WindowWidth = 0 +WindowHeight = 0 +ShowMenuBar = True +IgnoreCompatSettings = +DiscordRichPresence = False +RemoteTab = False +RemoteISOSharedDir = +RemoteISOShareType = 0 +RunBehindPauseMenu = False +ShowGPOLEDs = False +[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 = 0 +FrameSkipType = 0 +AutoFrameSkip = False +FrameRate = 0 +FrameRate2 = -1 +FrameSkipUnthrottle = True +ForceMaxEmulatedFPS = 30 +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 +iShowStatusFlags = 0 +UseGeometryShader = False +SkipBufferEffects = False +StereoRendering = False +StereoToMonoShader = RedBlue +AnalogFrameRate = 240 +MultiSampleLevel = 0 +DisplayOffsetX = 0.500000 +DisplayOffsetY = 0.500000 +DisplayScale = 1.000000 +DisplayIntegerScale = False +DisplayAspectRatio = 1.000000 +DisplayStretch = False +SkipGPUReadbacks = False +GpuLogProfiler = False +CameraMirrorHorizontal = False +AndroidFramerateMode = 1 +DisableRangeCulling = False +Smart2DTexFiltering = False +DisplayCropTo16x9 = True +VSync = False +SkipGPUReadbackMode = 0 +MultiThreading = True +UberShaderVertex = True +UberShaderFragment = True +DisplayRefreshRate = 60 +[Sound] +Enable = True +AudioBackend = 0 +AudioLatency = 1 +ExtraAudioBuffering = False +SoundSpeedHack = False +AudioResampler = False +GlobalVolume = 10 +AltSpeedVolume = -1 +AutoAudioDevice = True +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 +Custom0Repeat = False +Custom1Repeat = False +Custom2Repeat = False +Custom3Repeat = False +Custom4Repeat = False +Custom5Repeat = False +Custom6Repeat = False +Custom7Repeat = False +Custom8Repeat = False +Custom9Repeat = False +Custom10Mapping = 0x0000000000000000 +Custom10Image = 0 +Custom10Shape = 2 +Custom10Toggle = False +Custom10Repeat = False +Custom11Mapping = 0x0000000000000000 +Custom11Image = 1 +Custom11Shape = 2 +Custom11Toggle = False +Custom11Repeat = False +Custom12Mapping = 0x0000000000000000 +Custom12Image = 2 +Custom12Shape = 2 +Custom12Toggle = False +Custom12Repeat = False +Custom13Mapping = 0x0000000000000000 +Custom13Image = 3 +Custom13Shape = 2 +Custom13Toggle = False +Custom13Repeat = False +Custom14Mapping = 0x0000000000000000 +Custom14Image = 4 +Custom14Shape = 2 +Custom14Toggle = False +Custom14Repeat = False +Custom15Mapping = 0x0000000000000000 +Custom15Image = 0 +Custom15Shape = 9 +Custom15Toggle = False +Custom15Repeat = False +Custom16Mapping = 0x0000000000000000 +Custom16Image = 1 +Custom16Shape = 9 +Custom16Toggle = False +Custom16Repeat = False +Custom17Mapping = 0x0000000000000000 +Custom17Image = 2 +Custom17Shape = 9 +Custom17Toggle = False +Custom17Repeat = False +Custom18Mapping = 0x0000000000000000 +Custom18Image = 3 +Custom18Shape = 9 +Custom18Toggle = False +Custom18Repeat = False +Custom19Mapping = 0x0000000000000000 +Custom19Image = 4 +Custom19Shape = 9 +Custom19Toggle = False +Custom19Repeat = False +fcombo10X = 0.571875 +fcombo10Y = 0.582465 +comboKeyScale10 = 1.150000 +ShowComboKey10 = False +fcombo11X = 0.631771 +fcombo11Y = 0.582465 +comboKeyScale11 = 1.150000 +ShowComboKey11 = False +fcombo12X = 0.691667 +fcombo12Y = 0.582465 +comboKeyScale12 = 1.150000 +ShowComboKey12 = False +fcombo13X = 0.571875 +fcombo13Y = 0.415799 +comboKeyScale13 = 1.150000 +ShowComboKey13 = False +fcombo14X = 0.631771 +fcombo14Y = 0.415799 +comboKeyScale14 = 1.150000 +ShowComboKey14 = False +fcombo15X = 0.428125 +fcombo15Y = 0.582465 +comboKeyScale15 = 1.150000 +ShowComboKey15 = False +fcombo16X = 0.368229 +fcombo16Y = 0.582465 +comboKeyScale16 = 1.150000 +ShowComboKey16 = False +fcombo17X = 0.308333 +fcombo17Y = 0.582465 +comboKeyScale17 = 1.150000 +ShowComboKey17 = False +fcombo18X = 0.428125 +fcombo18Y = 0.415799 +comboKeyScale18 = 1.150000 +ShowComboKey18 = False +fcombo19X = 0.368229 +fcombo19Y = 0.415799 +comboKeyScale19 = 1.150000 +ShowComboKey19 = False +StickyTouchDPad = False +AnalogTriggerThreshold = 0.750000 +AllowMappingCombos = True +StrictComboOrder = False +MouseWheelUpDelayMs = 80 +RapidFileInterval = 5 +AnalogGesture = False +AnalogGestureSensibility = 1.000000 +[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 +GEWindowTabsBL = 0x00000000 +GEWindowTabsBR = 0x00000000 +GEWindowTabsTR = 0x00000000 +SkipFuncHashMap = +[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 +ThemeName = Default +[Recent] +MaxRecent = 30 +FileName0 = +[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 +[VR] +VREnable = True +VREnable6DoF = True +VREnableStereo = False +VREnableMotions = True +VRForce72Hz = True +VRManualForceVR = False +VRPassthrough = False +VRRescaleHUD = True +VRCameraDistance = 0.000000 +VRCameraHeight = 0.000000 +VRCameraSide = 0.000000 +VRCameraPitch = 0 +VRCanvasDistance = 12.000000 +VRFieldOfView = 100.000000 +VRHeadUpDisplayScale = 0.300000 +VRMotionLength = 0.500000 +VRHeadRotationScale = 5.000000 +VRHeadRotationEnabled = False +VRHeadRotationSmoothing = False +VRForce = False +VRImmersiveMode = True +VRCanvas3DDistance = 3.000000 diff --git a/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/SM8550/controls.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/SM8550/controls.ini new file mode 120000 index 0000000000..b7f1ba78bb --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/SM8550/controls.ini @@ -0,0 +1 @@ +../InputPlumber/controls.ini \ No newline at end of file diff --git a/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/SM8550/ppsspp.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/SM8550/ppsspp.ini new file mode 100644 index 0000000000..acc403c601 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/SM8550/ppsspp.ini @@ -0,0 +1,690 @@ +[General] +FirstRun = False +RunCount = 0 +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 +RewindSnapshotInterval = 0 +TransparentBackground = True +UITint = 0.000000 +UISaturation = 1.000000 +WindowX = -1 +WindowY = -1 +WindowWidth = 0 +WindowHeight = 0 +ShowMenuBar = True +IgnoreCompatSettings = +DiscordRichPresence = False +RemoteTab = False +RemoteISOSharedDir = +RemoteISOShareType = 0 +RunBehindPauseMenu = False +ShowGPOLEDs = False +[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 = 0 +FrameSkipType = 0 +AutoFrameSkip = False +FrameRate = 0 +FrameRate2 = -1 +FrameSkipUnthrottle = True +ForceMaxEmulatedFPS = 30 +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 +iShowStatusFlags = 0 +UseGeometryShader = False +SkipBufferEffects = False +StereoRendering = False +StereoToMonoShader = RedBlue +AnalogFrameRate = 240 +MultiSampleLevel = 0 +DisplayOffsetX = 0.500000 +DisplayOffsetY = 0.500000 +DisplayScale = 1.000000 +DisplayIntegerScale = False +DisplayAspectRatio = 1.000000 +DisplayStretch = False +SkipGPUReadbacks = False +GpuLogProfiler = False +CameraMirrorHorizontal = False +AndroidFramerateMode = 1 +DisableRangeCulling = False +Smart2DTexFiltering = False +DisplayCropTo16x9 = True +VSync = False +SkipGPUReadbackMode = 0 +MultiThreading = True +UberShaderVertex = True +UberShaderFragment = True +DisplayRefreshRate = 60 +[Sound] +Enable = True +AudioBackend = 0 +AudioLatency = 1 +ExtraAudioBuffering = False +SoundSpeedHack = False +AudioResampler = False +GlobalVolume = 10 +AltSpeedVolume = -1 +AutoAudioDevice = True +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 +Custom0Repeat = False +Custom1Repeat = False +Custom2Repeat = False +Custom3Repeat = False +Custom4Repeat = False +Custom5Repeat = False +Custom6Repeat = False +Custom7Repeat = False +Custom8Repeat = False +Custom9Repeat = False +Custom10Mapping = 0x0000000000000000 +Custom10Image = 0 +Custom10Shape = 2 +Custom10Toggle = False +Custom10Repeat = False +Custom11Mapping = 0x0000000000000000 +Custom11Image = 1 +Custom11Shape = 2 +Custom11Toggle = False +Custom11Repeat = False +Custom12Mapping = 0x0000000000000000 +Custom12Image = 2 +Custom12Shape = 2 +Custom12Toggle = False +Custom12Repeat = False +Custom13Mapping = 0x0000000000000000 +Custom13Image = 3 +Custom13Shape = 2 +Custom13Toggle = False +Custom13Repeat = False +Custom14Mapping = 0x0000000000000000 +Custom14Image = 4 +Custom14Shape = 2 +Custom14Toggle = False +Custom14Repeat = False +Custom15Mapping = 0x0000000000000000 +Custom15Image = 0 +Custom15Shape = 9 +Custom15Toggle = False +Custom15Repeat = False +Custom16Mapping = 0x0000000000000000 +Custom16Image = 1 +Custom16Shape = 9 +Custom16Toggle = False +Custom16Repeat = False +Custom17Mapping = 0x0000000000000000 +Custom17Image = 2 +Custom17Shape = 9 +Custom17Toggle = False +Custom17Repeat = False +Custom18Mapping = 0x0000000000000000 +Custom18Image = 3 +Custom18Shape = 9 +Custom18Toggle = False +Custom18Repeat = False +Custom19Mapping = 0x0000000000000000 +Custom19Image = 4 +Custom19Shape = 9 +Custom19Toggle = False +Custom19Repeat = False +fcombo10X = 0.571875 +fcombo10Y = 0.582465 +comboKeyScale10 = 1.150000 +ShowComboKey10 = False +fcombo11X = 0.631771 +fcombo11Y = 0.582465 +comboKeyScale11 = 1.150000 +ShowComboKey11 = False +fcombo12X = 0.691667 +fcombo12Y = 0.582465 +comboKeyScale12 = 1.150000 +ShowComboKey12 = False +fcombo13X = 0.571875 +fcombo13Y = 0.415799 +comboKeyScale13 = 1.150000 +ShowComboKey13 = False +fcombo14X = 0.631771 +fcombo14Y = 0.415799 +comboKeyScale14 = 1.150000 +ShowComboKey14 = False +fcombo15X = 0.428125 +fcombo15Y = 0.582465 +comboKeyScale15 = 1.150000 +ShowComboKey15 = False +fcombo16X = 0.368229 +fcombo16Y = 0.582465 +comboKeyScale16 = 1.150000 +ShowComboKey16 = False +fcombo17X = 0.308333 +fcombo17Y = 0.582465 +comboKeyScale17 = 1.150000 +ShowComboKey17 = False +fcombo18X = 0.428125 +fcombo18Y = 0.415799 +comboKeyScale18 = 1.150000 +ShowComboKey18 = False +fcombo19X = 0.368229 +fcombo19Y = 0.415799 +comboKeyScale19 = 1.150000 +ShowComboKey19 = False +StickyTouchDPad = False +AnalogTriggerThreshold = 0.750000 +AllowMappingCombos = True +StrictComboOrder = False +MouseWheelUpDelayMs = 80 +RapidFileInterval = 5 +AnalogGesture = False +AnalogGestureSensibility = 1.000000 +[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 +GEWindowTabsBL = 0x00000000 +GEWindowTabsBR = 0x00000000 +GEWindowTabsTR = 0x00000000 +SkipFuncHashMap = +[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 +ThemeName = Default +[Recent] +MaxRecent = 30 +FileName0 = +[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 +[VR] +VREnable = True +VREnable6DoF = True +VREnableStereo = False +VREnableMotions = True +VRForce72Hz = True +VRManualForceVR = False +VRPassthrough = False +VRRescaleHUD = True +VRCameraDistance = 0.000000 +VRCameraHeight = 0.000000 +VRCameraSide = 0.000000 +VRCameraPitch = 0 +VRCanvasDistance = 12.000000 +VRFieldOfView = 100.000000 +VRHeadUpDisplayScale = 0.300000 +VRMotionLength = 0.500000 +VRHeadRotationScale = 5.000000 +VRHeadRotationEnabled = False +VRHeadRotationSmoothing = False +VRForce = False +VRImmersiveMode = True +VRCanvas3DDistance = 3.000000 diff --git a/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/SM8650/controls.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/SM8650/controls.ini new file mode 120000 index 0000000000..b7f1ba78bb --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/SM8650/controls.ini @@ -0,0 +1 @@ +../InputPlumber/controls.ini \ No newline at end of file diff --git a/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/SM8650/ppsspp.ini b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/SM8650/ppsspp.ini new file mode 100644 index 0000000000..acc403c601 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/sources/SM8650/ppsspp.ini @@ -0,0 +1,690 @@ +[General] +FirstRun = False +RunCount = 0 +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 +RewindSnapshotInterval = 0 +TransparentBackground = True +UITint = 0.000000 +UISaturation = 1.000000 +WindowX = -1 +WindowY = -1 +WindowWidth = 0 +WindowHeight = 0 +ShowMenuBar = True +IgnoreCompatSettings = +DiscordRichPresence = False +RemoteTab = False +RemoteISOSharedDir = +RemoteISOShareType = 0 +RunBehindPauseMenu = False +ShowGPOLEDs = False +[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 = 0 +FrameSkipType = 0 +AutoFrameSkip = False +FrameRate = 0 +FrameRate2 = -1 +FrameSkipUnthrottle = True +ForceMaxEmulatedFPS = 30 +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 +iShowStatusFlags = 0 +UseGeometryShader = False +SkipBufferEffects = False +StereoRendering = False +StereoToMonoShader = RedBlue +AnalogFrameRate = 240 +MultiSampleLevel = 0 +DisplayOffsetX = 0.500000 +DisplayOffsetY = 0.500000 +DisplayScale = 1.000000 +DisplayIntegerScale = False +DisplayAspectRatio = 1.000000 +DisplayStretch = False +SkipGPUReadbacks = False +GpuLogProfiler = False +CameraMirrorHorizontal = False +AndroidFramerateMode = 1 +DisableRangeCulling = False +Smart2DTexFiltering = False +DisplayCropTo16x9 = True +VSync = False +SkipGPUReadbackMode = 0 +MultiThreading = True +UberShaderVertex = True +UberShaderFragment = True +DisplayRefreshRate = 60 +[Sound] +Enable = True +AudioBackend = 0 +AudioLatency = 1 +ExtraAudioBuffering = False +SoundSpeedHack = False +AudioResampler = False +GlobalVolume = 10 +AltSpeedVolume = -1 +AutoAudioDevice = True +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 +Custom0Repeat = False +Custom1Repeat = False +Custom2Repeat = False +Custom3Repeat = False +Custom4Repeat = False +Custom5Repeat = False +Custom6Repeat = False +Custom7Repeat = False +Custom8Repeat = False +Custom9Repeat = False +Custom10Mapping = 0x0000000000000000 +Custom10Image = 0 +Custom10Shape = 2 +Custom10Toggle = False +Custom10Repeat = False +Custom11Mapping = 0x0000000000000000 +Custom11Image = 1 +Custom11Shape = 2 +Custom11Toggle = False +Custom11Repeat = False +Custom12Mapping = 0x0000000000000000 +Custom12Image = 2 +Custom12Shape = 2 +Custom12Toggle = False +Custom12Repeat = False +Custom13Mapping = 0x0000000000000000 +Custom13Image = 3 +Custom13Shape = 2 +Custom13Toggle = False +Custom13Repeat = False +Custom14Mapping = 0x0000000000000000 +Custom14Image = 4 +Custom14Shape = 2 +Custom14Toggle = False +Custom14Repeat = False +Custom15Mapping = 0x0000000000000000 +Custom15Image = 0 +Custom15Shape = 9 +Custom15Toggle = False +Custom15Repeat = False +Custom16Mapping = 0x0000000000000000 +Custom16Image = 1 +Custom16Shape = 9 +Custom16Toggle = False +Custom16Repeat = False +Custom17Mapping = 0x0000000000000000 +Custom17Image = 2 +Custom17Shape = 9 +Custom17Toggle = False +Custom17Repeat = False +Custom18Mapping = 0x0000000000000000 +Custom18Image = 3 +Custom18Shape = 9 +Custom18Toggle = False +Custom18Repeat = False +Custom19Mapping = 0x0000000000000000 +Custom19Image = 4 +Custom19Shape = 9 +Custom19Toggle = False +Custom19Repeat = False +fcombo10X = 0.571875 +fcombo10Y = 0.582465 +comboKeyScale10 = 1.150000 +ShowComboKey10 = False +fcombo11X = 0.631771 +fcombo11Y = 0.582465 +comboKeyScale11 = 1.150000 +ShowComboKey11 = False +fcombo12X = 0.691667 +fcombo12Y = 0.582465 +comboKeyScale12 = 1.150000 +ShowComboKey12 = False +fcombo13X = 0.571875 +fcombo13Y = 0.415799 +comboKeyScale13 = 1.150000 +ShowComboKey13 = False +fcombo14X = 0.631771 +fcombo14Y = 0.415799 +comboKeyScale14 = 1.150000 +ShowComboKey14 = False +fcombo15X = 0.428125 +fcombo15Y = 0.582465 +comboKeyScale15 = 1.150000 +ShowComboKey15 = False +fcombo16X = 0.368229 +fcombo16Y = 0.582465 +comboKeyScale16 = 1.150000 +ShowComboKey16 = False +fcombo17X = 0.308333 +fcombo17Y = 0.582465 +comboKeyScale17 = 1.150000 +ShowComboKey17 = False +fcombo18X = 0.428125 +fcombo18Y = 0.415799 +comboKeyScale18 = 1.150000 +ShowComboKey18 = False +fcombo19X = 0.368229 +fcombo19Y = 0.415799 +comboKeyScale19 = 1.150000 +ShowComboKey19 = False +StickyTouchDPad = False +AnalogTriggerThreshold = 0.750000 +AllowMappingCombos = True +StrictComboOrder = False +MouseWheelUpDelayMs = 80 +RapidFileInterval = 5 +AnalogGesture = False +AnalogGestureSensibility = 1.000000 +[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 +GEWindowTabsBL = 0x00000000 +GEWindowTabsBR = 0x00000000 +GEWindowTabsTR = 0x00000000 +SkipFuncHashMap = +[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 +ThemeName = Default +[Recent] +MaxRecent = 30 +FileName0 = +[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 +[VR] +VREnable = True +VREnable6DoF = True +VREnableStereo = False +VREnableMotions = True +VRForce72Hz = True +VRManualForceVR = False +VRPassthrough = False +VRRescaleHUD = True +VRCameraDistance = 0.000000 +VRCameraHeight = 0.000000 +VRCameraSide = 0.000000 +VRCameraPitch = 0 +VRCanvasDistance = 12.000000 +VRFieldOfView = 100.000000 +VRHeadUpDisplayScale = 0.300000 +VRMotionLength = 0.500000 +VRHeadRotationScale = 5.000000 +VRHeadRotationEnabled = False +VRHeadRotationSmoothing = False +VRForce = False +VRImmersiveMode = True +VRCanvas3DDistance = 3.000000 diff --git a/projects/ArchR/packages/emulators/standalone/scummvmsa/config/games/_Scan ScummVM Games.sh b/projects/ArchR/packages/emulators/standalone/scummvmsa/config/games/_Scan ScummVM Games.sh new file mode 100644 index 0000000000..b2977c3e74 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/scummvmsa/config/games/_Scan ScummVM Games.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) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile + +clear +echo "Scanning for games..." +bash /usr/bin/start_scummvm.sh add +echo "Adding games..." +bash /usr/bin/start_scummvm.sh create +clear diff --git a/projects/ArchR/packages/emulators/standalone/scummvmsa/config/scummvm.ini b/projects/ArchR/packages/emulators/standalone/scummvmsa/config/scummvm.ini new file mode 100644 index 0000000000..14851019f2 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/scummvmsa/config/scummvm.ini @@ -0,0 +1,45 @@ +[scummvm] +filtering=false +fluidsynth_misc_interpolation=4th +last_fullscreen_mode_width=1920 +multi_midi=false +gui_browser_show_hidden=true +soundfont=/usr/share/soundfonts/GeneralUser.sf2 +fluidsynth_chorus_nr=3 +fluidsynth_chorus_waveform=sine +music_driver=auto +vsync=true +local_server_port=12345 +fluidsynth_chorus_activate=true +last_fullscreen_mode_height=1152 +mt32_device=null +talkspeed=60 +gfx_mode=surfacesdl +gui_scale=100 +subtitles=false +fluidsynth_reverb_level=90 +fluidsynth_reverb_activate=true +browser_lastpath=/storage/roms/scummvm +music_volume=192 +opl_driver=auto +fluidsynth_chorus_level=100 +aspect_ratio=false +autosave_period=300 +fluidsynth_chorus_depth=80 +native_mt32=false +fluidsynth_reverb_roomsize=20 +gui_return_to_launcher_at_exit=false +fullscreen=true +gm_device=fluidsynth +sfx_volume=192 +fluidsynth_chorus_speed=30 +speech_volume=192 +gui_use_game_language=false +mute=false +confirm_exit=false +midi_gain=100 +fluidsynth_reverb_width=1 +fluidsynth_reverb_damping=0 +versioninfo=2.6.0git +speech_mute=false +enable_gs=false diff --git a/projects/ArchR/packages/emulators/standalone/scummvmsa/package.mk b/projects/ArchR/packages/emulators/standalone/scummvmsa/package.mk new file mode 100644 index 0000000000..500c2c4acc --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/scummvmsa/package.mk @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="scummvmsa" +PKG_VERSION="2026.2.0" +PKG_LICENSE="GPL2" +PKG_SITE="https://github.com/scummvm/scummvm" +PKG_URL="${PKG_SITE}/archive/refs/tags/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain SDL2 SDL2_net freetype fluidsynth soundfont-generaluser pipewire" +PKG_LONGDESC="Script Creation Utility for Maniac Mansion Virtual Machine" + +pre_configure_target() { + sed -i "s|sdl-config|sdl2-config|g" ${PKG_BUILD}/configure + TARGET_CONFIGURE_OPTS="--host=${TARGET_NAME} --backend=sdl --disable-alsa --with-sdl-prefix=${SYSROOT_PREFIX}/usr/bin --disable-debug --enable-release --enable-vkeybd --opengl-mode=gles2 --enable-optimizations" +} + +post_makeinstall_target() { + mkdir -p ${INSTALL}/usr/config/scummvm/ + cp -rf ${PKG_DIR}/config/* ${INSTALL}/usr/config/scummvm/ + chmod 0755 ${INSTALL}/usr/config/scummvm/games/*sh + + mkdir -p ${INSTALL}/usr/config/scummvm/themes + cp -rf ${PKG_BUILD}/gui/themes ${INSTALL}/usr/config/scummvm/themes + + mv ${INSTALL}/usr/local/bin ${INSTALL}/usr/ + cp -rf ${PKG_DIR}/sources/* ${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 +} diff --git a/projects/ArchR/packages/emulators/standalone/scummvmsa/sources/start_scummvm.sh b/projects/ArchR/packages/emulators/standalone/scummvmsa/sources/start_scummvm.sh new file mode 100644 index 0000000000..1a24beced8 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/scummvmsa/sources/start_scummvm.sh @@ -0,0 +1,73 @@ +#!/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" +RATMPCONF="/storage/.config/retroarch/retroarch.cfg" + +shopt -s extglob +if [[ "$1" =~ ?(add|create|libretro) ]] +then + GAME="$2" +else + GAME="$1" +fi + +if [ ! -d "${CONFIG_DIR}/games" ] +then + mkdir -p "${CONFIG_DIR}/games" +fi + +create_svm(){ + /usr/bin/scummvm --list-targets | tail -n +3 | cut -d " " -f 1 | \ + while read line + do + id=($line); + filename=$(sed -n "/^\[$id\]/,/^\[/{s/^description=//p}" ${CONFIG_DIR}/scummvm.ini | \ + sed -e 's# (.*)# ('${id}')#g' -e "s#'##g" -e "s#: # - #g" \ + ) + + SVMPATH="$(sed -n "/^\[$id\]/,/^\[/{s/^path=//p}" ${CONFIG_DIR}/scummvm.ini)" + 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 + "libretro") + GAME=$(cat "${GAME}" | awk 'BEGIN {FS="\""}; {print $2}') + cd "${GAME}" + /usr/bin/retroarch -L /tmp/cores/scummvm_libretro.so --config ${RATMPCONF} . + ;; + + "add") + if [ ! -d "${ROMSPATH}/scummvm" ]; then + mkdir "${ROMSPATH}/scummvm" + fi + /usr/bin/scummvm --add --path="${ROMSPATH}/scummvm" --recursive + mkdir -p ${BIOSPATH} + cp ${CONFIG_DIR}/scummvm.ini ${BIOSPATH}/scummvm.ini + ;; + + "create") + create_svm + ;; + + *) + set_kill set "-9 scummvm" + GAME=$(cat "${GAME}") + systemctl start fluidsynth + eval /usr/bin/scummvm --fullscreen --joystick=0 --themepath=/usr/config/scummvm/themes "${GAME}" + systemctl stop fluidsynth + ;; +esac diff --git a/projects/ArchR/packages/emulators/standalone/touchhle-sa/package.mk b/projects/ArchR/packages/emulators/standalone/touchhle-sa/package.mk new file mode 100644 index 0000000000..287497a950 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/touchhle-sa/package.mk @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2026-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="touchhle-sa" +PKG_LICENSE="MPLv2" +PKG_VERSION="d7668926268eded91545fa8ffae6590871ecf5b1" +PKG_SITE="https://github.com/touchHLE/touchHLE" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain cargo:host cargo rust SDL2 sndio" +PKG_LONGDESC="touchHLE: high-level emulator for iPhone OS apps" +PKG_TOOLCHAIN="manual" + +make_target() { + unset CMAKE + export RUSTFLAGS="-C link-arg=-lasound" + + cargo build \ + --target ${TARGET_NAME} \ + --release +} + + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp -rf ${PKG_BUILD}/.${TARGET_NAME}/target/${TARGET_NAME}/release/touchHLE ${INSTALL}/usr/bin + cp -rf ${PKG_DIR}/scripts/* ${INSTALL}/usr/bin + mkdir -p ${INSTALL}/usr/lib/touchHLE/touchHLE_dylibs + cp -rf ${PKG_BUILD}/touchHLE_dylibs/lib* ${INSTALL}/usr/lib/touchHLE/touchHLE_dylibs/ + mkdir -p ${INSTALL}/usr/lib/touchHLE/touchHLE_fonts + cp -rf ${PKG_BUILD}/touchHLE_fonts/LiberationSans-* ${INSTALL}/usr/lib/touchHLE/touchHLE_fonts + cp -rf ${PKG_BUILD}/touchHLE_default_options.txt ${INSTALL}/usr/lib/touchHLE/ + mkdir -p ${INSTALL}/usr/config/touchHLE + cp -rf ${PKG_BUILD}/touchHLE_options.txt ${INSTALL}/usr/config/touchHLE/ + chmod +x ${INSTALL}/usr/bin/* +} diff --git a/projects/ArchR/packages/emulators/standalone/touchhle-sa/patches/000-set-paths.patch b/projects/ArchR/packages/emulators/standalone/touchhle-sa/patches/000-set-paths.patch new file mode 100644 index 0000000000..aaac71e595 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/touchhle-sa/patches/000-set-paths.patch @@ -0,0 +1,59 @@ +diff --git a/src/paths.rs b/src/paths.rs +index d0ab20b8..ac14b0de 100644 +--- a/src/paths.rs ++++ b/src/paths.rs +@@ -70,9 +70,15 @@ impl ResourceFile { + // On other OSes, resources are accessed as ordinary files. + #[cfg(not(target_os = "android"))] + file: { +- let base_path = get_macos_bundled_resources_path(); +- // When not in a bundle, look in the current directory. +- let path = base_path.as_deref().unwrap_or(Path::new(".")).join(path); ++ #[cfg(target_os = "linux")] ++ let base_path = Path::new(LINUX_RESOURCE_BASE); ++ ++ #[cfg(not(target_os = "linux"))] ++ let base_path = get_macos_bundled_resources_path() ++ .as_deref() ++ .unwrap_or(Path::new(".")); ++ ++ let path = base_path.join(path); + std::fs::File::open(path).map_err(|e| e.to_string())? + }, + }) +@@ -110,6 +116,12 @@ pub const WALLPAPER_FILES: &[&str] = &[ + /// the `Documents` directory. + pub const SANDBOX_DIR: &str = "touchHLE_sandbox"; + ++#[cfg(target_os = "linux")] ++const LINUX_RESOURCE_BASE: &str = "/usr/lib/touchHLE"; ++ ++#[cfg(target_os = "linux")] ++const LINUX_USER_BASE: &str = "/storage/.config/touchHLE"; ++ + /// Get a platform-specific base path needed for accessing touchHLE's + /// user-modifiable files. This is empty on platforms other than Android. + pub fn user_data_base_path() -> Cow<'static, Path> { +@@ -136,6 +148,11 @@ pub fn user_data_base_path() -> Cow<'static, Path> { + } + #[cfg(not(target_os = "android"))] + { ++ #[cfg(target_os = "linux")] ++ { ++ return Cow::from(PathBuf::from(LINUX_USER_BASE)); ++ } ++ + // When touchHLE is run from a .app bundle on macOS, the user might not + // be able to control the current directory, so user data needs to go in + // a standard location. +@@ -190,6 +207,10 @@ pub fn prepopulate_user_data_dir() { + return; + } + ++ #[cfg(target_os = "linux")] ++ let apps_dir = PathBuf::from("/storage/roms/ios"); ++ ++ #[cfg(not(target_os = "linux"))] + let apps_dir = base_path.join(APPS_DIR); + if !apps_dir.is_dir() { + match std::fs::create_dir(&apps_dir) { diff --git a/projects/ArchR/packages/emulators/standalone/touchhle-sa/patches/001-fix-app-picker.patch b/projects/ArchR/packages/emulators/standalone/touchhle-sa/patches/001-fix-app-picker.patch new file mode 100644 index 0000000000..3c968d7694 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/touchhle-sa/patches/001-fix-app-picker.patch @@ -0,0 +1,20 @@ +diff --git a/src/app_picker.rs b/src/app_picker.rs +index 0b6fd38b..9ff58508 100644 +--- a/src/app_picker.rs ++++ b/src/app_picker.rs +@@ -495,7 +495,6 @@ fn show_app_picker_gui( + app_frame.size, + buttons_row_center, + &[ +- ("File manager", "openFileManager"), + ("Quick options", "quickOptionsShow"), + ], + None, +@@ -508,7 +507,6 @@ fn show_app_picker_gui( + buttons_row2_center, + &[ + ("Copyright info", "copyrightInfoShow"), +- ("touchHLE.org", "visitWebsite"), + ], + None, + ); diff --git a/projects/ArchR/packages/emulators/standalone/touchhle-sa/scripts/start_touchhle.sh b/projects/ArchR/packages/emulators/standalone/touchhle-sa/scripts/start_touchhle.sh new file mode 100644 index 0000000000..76f83f6f33 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/touchhle-sa/scripts/start_touchhle.sh @@ -0,0 +1,77 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2026-present ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile +set_kill set "-9 touchHLE" + +# Conf files vars +SOURCE_DIR="/usr/config/touchHLE" +CONF_DIR="/storage/.config/touchHLE" +TOUCHHLE_CONF="touchHLE_options.txt" + +# Check if touchHLE exists in /storage/.config +if [ ! -d "${CONF_DIR}" ]; then + cp -r "${SOURCE_DIR}" "/storage/.config/" +fi + +# Check if touchHLE_options.txt exists in .config/touchHLE +if [ ! -f "${CONF_DIR}/${TOUCHHLE_CONF}" ]; then + cp -r "${SOURCE_DIR}/${TOUCHHLE_CONF}" "${CONF_DIR}" +fi + +# Check if touchHLE_wallpaper.* exists in .config/touchHLE +if ! compgen -G "${CONF_DIR}/touchHLE_wallpaper.*" > /dev/null; then +printf \ +'\x89PNG\r\n\x1a\n'\ +'\x00\x00\x00\rIHDR\x00\x00\x00\x01\x00\x00\x00\x01\x08\x02\x00\x00\x00\x90wS\xde'\ +'\x00\x00\x00\x0cIDAT\x08\xd7c\x60\x60\x60\x00\x00\x00\x04\x00\x01\xf6\x17\x38\x55'\ +'\x00\x00\x00\x00IEND\xaeB`\x82' \ +> "${CONF_DIR}/touchHLE_wallpaper.png" +fi + +# Link roms/ios to touchHLE_apps +ln -snf "/storage/roms/ios" "${CONF_DIR}/touchHLE_apps" + +#Emulation Station Features +GAME=$(echo "${1}"| sed "s#^/.*/##") +PLATFORM=$(echo "${2}"| sed "s#^/.*/##") +DEVICE=$(get_setting device_type "${PLATFORM}" "${GAME}") +UPSCALE=$(get_setting upscale "${PLATFORM}" "${GAME}") + +# Set device type +if [ "${DEVICE}" != "ipad" ]; then + DEVICE="iphone" +fi + +# Set upscaling +if [[ "${UPSCALE}" =~ ^[1-4]$ ]]; then + UPSCALE="${UPSCALE}" +else + UPSCALE=1 +fi + +#Set the cores to use +CORES=$(get_setting "cores" "${PLATFORM}" "${GAME}") +if [ "${CORES}" = "little" ] +then + EMUPERF="${SLOW_CORES}" +elif [ "${CORES}" = "big" ] +then + EMUPERF="${FAST_CORES}" +else + ### All.. + unset EMUPERF +fi + +# Debugging info: + echo "GAME set to: ${GAME}" + echo "PLATFORM set to: ${PLATFORM}" + echo "CONF DIR: ${CONF_DIR}/${GOPHER64_JSON}" + echo "CPU CORES set to: ${EMUPERF}" + echo "DEVICE TYPE set to: ${DEVICE}" + echo "Launching /usr/bin/touchHLE --fullscreen=${DEVICE} ${1}" + +# Start touchHLE +${EMUPERF} /usr/bin/touchHLE --fullscreen --scale-hack=${UPSCALE} --device-family=${DEVICE} "${1}" diff --git a/projects/ArchR/packages/emulators/standalone/vice-sa/configs/sdl-vicerc b/projects/ArchR/packages/emulators/standalone/vice-sa/configs/sdl-vicerc new file mode 100644 index 0000000000..06a4a71ffa --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/vice-sa/configs/sdl-vicerc @@ -0,0 +1,26 @@ +[Version] +ConfigVersion=3.7.1 + +[C128] +KeySetEnable=0 +JoyDevice1=4 +JoyDevice2=4 +JoyMenuControl=1 + +[C64SC] +KeySetEnable=0 +JoyDevice1=4 +JoyDevice2=4 +JoyMenuControl=1 + +[PLUS4] +KeySetEnable=0 +JoyDevice1=4 +JoyDevice2=4 +JoyMenuControl=1 + +[VIC-20] +KeySetEnable=0 +JoyDevice1=4 +JoyDevice2=4 +JoyMenuControl=1 diff --git a/projects/ArchR/packages/emulators/standalone/vice-sa/package.mk b/projects/ArchR/packages/emulators/standalone/vice-sa/package.mk new file mode 100644 index 0000000000..f466edfca1 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/vice-sa/package.mk @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="vice-sa" +PKG_VERSION="3.8" +PKG_LICENSE="GPLv2" +PKG_SITE="https://sourceforge.net/projects/vice-emu" +PKG_URL="${PKG_SITE}/files/releases/vice-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain xa:host SDL2 SDL2_image ncurses readline busybox:host" +PKG_LONGDESC="Commodore 8-bit Emulator" +PKG_CONFIGURE_OPTS_TARGET+=" --disable-pdf-docs --enable-gtk3ui=no --without-alsa --with-pulse --enable-sdl2ui" + +if [ ! "${OPENGL}" = "no" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL} glu libglvnd" +fi + +if [ "${OPENGLES_SUPPORT}" = yes ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" +fi + +pre_configure_target() { + export LDFLAGS="${LDFLAGS} -lreadline -lncursesw -ltinfow" + export CFLAGS="${CFLAGS} -fcommon" +} + +post_makeinstall_target() { + mkdir -p ${INSTALL}/usr/config/vice + if [ -d "${PKG_DIR}/configs" ] + then + cp -f ${PKG_DIR}/configs/* ${INSTALL}/usr/config/vice + fi + + for sc in x128 x64sc xplus4 xvic + do + cp -f ${PKG_DIR}/sources/start_vice.sh ${INSTALL}/usr/bin/start_${sc}.sh + sed -i "s~@EMU@~${sc}~g" ${INSTALL}/usr/bin/start_${sc}.sh + done + chmod 0755 ${INSTALL}/usr/bin/* +} diff --git a/projects/ArchR/packages/emulators/standalone/vice-sa/sources/start_vice.sh b/projects/ArchR/packages/emulators/standalone/vice-sa/sources/start_vice.sh new file mode 100644 index 0000000000..3396f76ec9 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/vice-sa/sources/start_vice.sh @@ -0,0 +1,85 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile + +set_kill set "-9 @EMU@" + +CONFIG_PATH="/storage/.config/vice" +SOURCE_PATH="/usr/config/vice" + +EMU="@EMU@" + +### Get the game we want to start. +GAME=${1//[\\]/} + +if [ ! -d "/storage/.config/vice" ] +then + mkdir -p /storage/.config/vice +fi + +case ${EMU} in + x128) + EMU="C128" + ;; + x64sc) + EMU="C64SC" + ;; + xplus4) + EMU="PLUS4" + ;; + xvic) + EMU="VIC20" + ;; +esac + +if [ ! -e "${CONFIG_PATH}/sdl-hotkeys-${EMU}.vhk" ] +then + cat <${CONFIG_PATH}/sdl-hotkeys-${EMU}.vhk +!CLEAR +EOF +fi + +if [ ! -e "${CONFIG_PATH}/sdl-joymap-${EMU}.vjm" ] +then + cat <${CONFIG_PATH}/sdl-joymap-${EMU}.vjm +!CLEAR + +0 0 0 0 +0 0 1 0 +0 0 2 0 +0 0 3 0 +0 0 4 0 +0 0 5 0 +0 0 6 0 +0 0 7 0 + +0 1 0 1 0 16 +0 1 1 1 0 32 +0 1 2 1 0 64 +0 1 3 0 +0 1 4 0 +0 1 ${DEVICE_BTN_SELECT} 5 Virtual keyboard +0 1 ${DEVICE_BTN_START} 4 +EOF + + if [[ ! "${DEVICE_BTN_DPAD_UP}" =~ [a-z] ]] + then + cat <>${CONFIG_PATH}/sdl-joymap-${EMU}.vjm +0 1 ${DEVICE_BTN_DPAD_UP} 1 0 1 +0 1 ${DEVICE_BTN_DPAD_DOWN} 1 0 2 +0 1 ${DEVICE_BTN_DPAD_LEFT} 1 0 4 +0 1 ${DEVICE_BTN_DPAD_RIGHT} 1 0 8 +EOF + else + cat <>${CONFIG_PATH}/sdl-joymap-${EMU}.vjm +0 2 0 1 0 1 +0 2 1 1 0 2 +0 2 2 1 0 4 +0 2 3 1 0 8 +EOF + fi +fi + +@EMU@ -joymenucontrol "${GAME}" diff --git a/projects/ArchR/packages/emulators/standalone/vita3k-sa/package.mk b/projects/ArchR/packages/emulators/standalone/vita3k-sa/package.mk new file mode 100644 index 0000000000..3a1fdc02df --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/vita3k-sa/package.mk @@ -0,0 +1,66 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="vita3k-sa" +PKG_VERSION="f02851437d8bce2ebf54cd6d4922cd4b0faba654" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/Vita3K/Vita3K" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain SDL2 SDL2_image zlib libogg libvorbis gtk3 openssl ffmpeg" +PKG_LONGDESC="vita3k" +PKG_TOOLCHAIN="cmake" +PKG_PATCH_DIRS+="${DEVICE}" + +if [ ! "${OPENGL}" = "no" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL} glu libglvnd" +fi + +if [ "${OPENGLES_SUPPORT}" = yes ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" +fi + +if [ "${VULKAN_SUPPORT}" = "yes" ] +then + PKG_DEPENDS_TARGET+=" ${VULKAN}" +fi + + pre_configure_target() { + mkdir -p ${PKG_BUILD}/external + [ -d "nativefiledialog-cmake" ] && rm -rf nativefiledialog-cmake + cd ${PKG_BUILD}/external && git clone https://github.com/Vita3K/nativefiledialog-cmake + [ -d "ffmpeg" ] && rm -rf ffmpeg + cd ${PKG_BUILD}/external && git clone https://github.com/Vita3K/ffmpeg-core.git ffmpeg + + case ${TARGET_ARCH} in + aarch64) + CMAKE_EXTRA_OPTS="-DXXHASH_BUILD_XXHSUM=ON \ + -DXXH_X86DISPATCH_ALLOW_AVX=OFF" + ;; + *) + CMAKE_EXTRA_OPTS="-DXXH_X86DISPATCH_ALLOW_AVX=ON" + ;; + esac + + PKG_CMAKE_OPTS_TARGET+=" -DCMAKE_BUILD_TYPE=Release \ + -DBUILD_SHARED_LIBS=OFF \ + -DUSE_DISCORD_RICH_PRESENCE=OFF \ + -DUSE_VITA3K_UPDATE=OFF \ + ${CMAKE_EXTRA_OPTS}" +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + mkdir -p ${INSTALL}/usr/config/vita3k + cp -rf ${PKG_BUILD}/external/bin/Vita3K ${INSTALL}/usr/bin/ + cp -rf ${PKG_BUILD}/external/bin/* ${INSTALL}/usr/config/vita3k/ + rm -rf ${INSTALL}/usr/config/vita3k/Vita3K + cp ${PKG_DIR}/scripts/* ${INSTALL}/usr/bin + chmod 0755 ${INSTALL}/usr/bin/* + + mkdir -p ${INSTALL}/usr/config/vita3k/launcher + cp ${PKG_DIR}/scripts/start_vita3k.sh ${INSTALL}/usr/config/vita3k/launcher/_Start\ Vita3K.sh + cp ${PKG_DIR}/scripts/scan_vita3k.sh ${INSTALL}/usr/config/vita3k/launcher/_Scan\ Vita\ Games.sh + chmod 0755 ${INSTALL}/usr/config/vita3k/launcher/*sh + + cp ${PKG_DIR}/sources/vita-gamelist.txt ${INSTALL}/usr/config/vita3k +} diff --git a/projects/ArchR/packages/emulators/standalone/vita3k-sa/patches/001-base-path.patch b/projects/ArchR/packages/emulators/standalone/vita3k-sa/patches/001-base-path.patch new file mode 100644 index 0000000000..003bb01ea0 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/vita3k-sa/patches/001-base-path.patch @@ -0,0 +1,26 @@ +diff --git a/vita3k/app/src/app_init.cpp b/vita3k/app/src/app_init.cpp +index 8536b401..459e21f5 100644 +--- a/vita3k/app/src/app_init.cpp ++++ b/vita3k/app/src/app_init.cpp +@@ -103,9 +103,7 @@ void update_viewport(EmuEnvState &state) { + } + + void init_paths(Root &root_paths) { +- auto sdl_base_path = SDL_GetBasePath(); +- auto base_path = fs_utils::utf8_to_path(sdl_base_path); +- SDL_free(sdl_base_path); ++ auto base_path = fs_utils::utf8_to_path("/storage/.config/vita3k/"); + + root_paths.set_base_path(base_path); + root_paths.set_static_assets_path(base_path); +@@ -129,9 +127,7 @@ void init_paths(Root &root_paths) { + } else { + // SDL_GetPrefPath is deferred as it creates the directory. + // When using a portable directory, it is not needed. +- auto sdl_pref_path = SDL_GetPrefPath(org_name, app_name); +- auto pref_path = fs_utils::utf8_to_path(sdl_pref_path); +- SDL_free(sdl_pref_path); ++ auto pref_path = fs_utils::utf8_to_path("/storage/psvita/vita3k/"); + + #if defined(__APPLE__) + // Store other data in the user-wide path. Otherwise we may end up dumping diff --git a/projects/ArchR/packages/emulators/standalone/vita3k-sa/patches/004-fix-link-error.patch b/projects/ArchR/packages/emulators/standalone/vita3k-sa/patches/004-fix-link-error.patch new file mode 100644 index 0000000000..be1ff84d8c --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/vita3k-sa/patches/004-fix-link-error.patch @@ -0,0 +1,15 @@ +diff --git a/vita3k/CMakeLists.txt b/vita3k/CMakeLists.txt +index 04177f04..4adb1e0b 100644 +--- a/vita3k/CMakeLists.txt ++++ b/vita3k/CMakeLists.txt +@@ -136,10 +136,6 @@ if(USE_DISCORD_RICH_PRESENCE) + target_link_libraries(vita3k PRIVATE discord-rpc) + endif() + +-if(LINUX) +- target_link_libraries(vita3k PRIVATE -static-libgcc -static-libstdc++) +-endif() +- + set_target_properties(vita3k PROPERTIES OUTPUT_NAME Vita3K + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" diff --git a/projects/ArchR/packages/emulators/standalone/vita3k-sa/patches/aarch64/005-no-XXHASH-dispatch.patch b/projects/ArchR/packages/emulators/standalone/vita3k-sa/patches/aarch64/005-no-XXHASH-dispatch.patch new file mode 100644 index 0000000000..6699f92367 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/vita3k-sa/patches/aarch64/005-no-XXHASH-dispatch.patch @@ -0,0 +1,17 @@ +diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt +index 72b4010b..9509832a 100644 +--- a/external/CMakeLists.txt ++++ b/external/CMakeLists.txt +@@ -331,9 +331,9 @@ target_include_directories(libatrac9 PUBLIC LibAtrac9/C/src) + option(BUILD_SHARED_LIBS "Build shared library" OFF) + option(XXHASH_BUILD_XXHSUM "Build the xxhsum binary" OFF) + option(XXH_X86DISPATCH_ALLOW_AVX "Allow building XXH3 with AVX even if it crashes on SSE2-Only CPUs" OFF) +-if(NOT APPLE) +- set(DISPATCH 1) +-endif() ++#if(NOT APPLE) ++# set(DISPATCH 1) ++#endif() + add_subdirectory(xxHash/cmake_unofficial EXCLUDE_FROM_ALL) + if(XXH_X86DISPATCH_ALLOW_AVX) + target_compile_definitions(xxhash PRIVATE XXH_X86DISPATCH_ALLOW_AVX) diff --git a/projects/ArchR/packages/emulators/standalone/vita3k-sa/scripts/scan_vita3k.sh b/projects/ArchR/packages/emulators/standalone/vita3k-sa/scripts/scan_vita3k.sh new file mode 100755 index 0000000000..2ce1036c7f --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/vita3k-sa/scripts/scan_vita3k.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile + +GAME_PATH="/storage/psvita/vita3k/ux0/app" +GAME_DATA="/storage/.config/vita3k/vita-gamelist.txt" +OUTPUT_PATH="/storage/.config/vita3k/launcher" + +cd ${GAME_PATH} +for GAME in PC* +do + FILENAME=$(grep ${GAME} ${GAME_DATA} | sed 's~'${GAME}'\t~~g') + if [ ! -e "${OUTPUT_PATH}/${FILENAME}.psvita" ] && \ + [ -n "${FILENAME}" ] + then + echo ${GAME} > ${OUTPUT_PATH}/"${FILENAME}.psvita" + fi +done diff --git a/projects/ArchR/packages/emulators/standalone/vita3k-sa/scripts/start_vita3k.sh b/projects/ArchR/packages/emulators/standalone/vita3k-sa/scripts/start_vita3k.sh new file mode 100755 index 0000000000..9781c1e097 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/vita3k-sa/scripts/start_vita3k.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile +set_kill set "-9 Vita3K" + +OUTPUT_PATH="/storage/.config/vita3k/launcher" +GAME="${1}" + +#Check if vita3k folder exists in /storage/.config/vita3k +if [ ! -d "/storage/.config/vita3k" ]; then + mkdir -p "/storage/.config/vita3k" +fi + +#Make sure we sync any changes from /storage/.config so new features will be enabled +#without overwriting existing settings. +rsync -ah --update /usr/config/vita3k/* /storage/.config/vita3k 2>/dev/null + +#Check if vita3k folder exists in /storage/roms/psvita +if [ ! -d "/storage/roms/psvita/vita3k" ]; then + mkdir -p "/storage/roms/psvita/vita3k" +fi + +if [ -n "${GAME}" ]; then + OPTIONS="-r $(cat "${GAME}")" +fi + +#Start Vita3K +/usr/bin/Vita3K ${OPTIONS} diff --git a/projects/ArchR/packages/emulators/standalone/vita3k-sa/sources/vita-gamelist.txt b/projects/ArchR/packages/emulators/standalone/vita3k-sa/sources/vita-gamelist.txt new file mode 100644 index 0000000000..4eb1d5bcb5 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/vita3k-sa/sources/vita-gamelist.txt @@ -0,0 +1,2055 @@ +PCSE00965 #KILLALLZOMBIES +PCSG00891 √Letter +PCSE00963 √Letter +PCSB01019 √Letter +PCSE00890 10 Second Ninja X +PCSB00963 10 Second Ninja X +PCSE00349 1001 Spikes +PCSE00634 2013: Infected Wars +PCSE00972 2064: Read Only Memories +PCSE01169 36 Fragments of Midnight +PCSG00590 5-nin no Koi Prince: Himitsu no Keiyaku Kekkon +PCSE01168 7'scarlet +PCSH10090 7'scarlet +PCSG00876 7'scarlet +PCSE00914 99Vidas +PCSE01167 99vidas - Demo +PCSE00726 A Boy and His Blob +PCSH10075 A Certain Magical Virtual-On +PCSG00505 A Good Librarian Like a Good Shepherd -Library Party- +PCSE01095 A Hole New World +PCSB01095 A Rose in the Twilight +PCSE01046 A Rose in the Twilight +PCSB00955 A Virus Named TOM +PCSE00501 A Virus Named TOM +PCSE01389 A Winter's Daydream +PCSE00232 A-men +PCSB00056 A-men +PCSE00324 A-men 2 +PCSB00222 A-men 2 +PCSB00154 A-men Demo +PCSB00898 A.O.T. Wings of Freedom +PCSB00960 A.W. : Phoenix Festa +PCSE00871 A.W. : Phoenix Festa +PCSE00278 Aabs Animals +PCSG00591 Abunai Koi no Sousashitsu: Eternal Happiness +PCSB00792 AC® Chronicles +PCSE00700 AC® Chronicles +PCSB01101 Accel World vs. Sword Art Online +PCSE01071 Accel World vs. Sword Art Online +PCSG01016 Accel World vs. Sword Art Online +PCSE01356 Access Denied +PCSE01448 Active Neurons +PCSB01008 Active Soccer 2 DX +PCSB00858 Actual Sunlight +PCSE00695 Actual Sunlight +PCSE00582 Adventure Time: the Secret of the Nameless Kingdom +PCSE00905 Adventures of Mana +PCSB00975 Adventures of Mana +PCSG90182 Aegis of Earth Demo +PCSE00844 Aegis of Earth: Protonovus Assault +PCSG00362 Aegis of Earth: Protonovus Assault +PCSG01296 Aerial Life +PCSE00628 AeternoBlade +PCSG00483 AeternoBlade +PCSB00732 AeternoBlade Demo +PCSE00636 AeternoBlade Demo +PCSB00412 Age of Zombies +PCSE00362 Age of Zombies +PCSG01325 Ai Kiss +PCSG00940 AIR +PCSE00980 Air Race Speed +PCSG00461 Airship Q +PCSG00338 Aiyoku no Eustia: Angel’s Blessing +PCSG00780 Akai Suna Ochiru Tsuki +PCSE00927 Akiba's Beat +PCSB01066 AKIBA'S BEAT +PCSG00159 AKIBA'S TRIP 2 +PCSH00057 AKIBA'S TRIP 2 +PCSE00428 AKIBA'S TRIP UNDEAD & UNDRESSED +PCSG90191 ALIA's CARNIVAL! Sacramento Trial +PCSE00210 Alien Breed +PCSE00445 Alien Shooter +PCSB00964 Alone With You +PCSE00887 Alone With You +PCSB01457 Alphaset by POWGI +PCSH10271 Alphaset by POWGI +PCSE01493 Alphaset by POWGI +PCSB01187 Alteric +PCSG01243 Alvastia Chronicles +PCSG01086 Amaekata wa Kanojo Nari ni. +PCSG01293 Amamane +PCSG00638 Amatsumi Sora ni! Kumo no Hatate ni +PCSG01138 Amenity's Life +PCSG90299 Amenity's Life -アメニティーズ ライフ- 体験版 +PCSG00403 AMNESIA LATER×CROWD V Edition +PCSB00740 Amnesia Memories +PCSG00203 AMNESIA V Edition +PCSG00276 AMNESIA World +PCSE00647 Amnesia: Memories +PCSG00696 Angelique Retour +PCSE00322 Angry Birds Trilogy +PCSB00397 Angry Birds™ Star Wars +PCSE00294 Angry Birds™ Star Wars +PCSG00342 Anoko wa Ore Kara Hanarenai +PCSE00472 Another World - 20th Anniversary Edition +PCSE01147 Antiquia Lost +PCSG00700 Ao no Kanata Four Rhythm +PCSG90180 Ao no Kanata no Four Rhythm Trial Version +PCSG01281 Aoki Tsubasa no Chevalier +PCSG01283 Aonatsu Line +PCSG00848 Aqua Kitty - Milk Mine Defender DX +PCSB00798 Ar nosurge Plus: Ode to an Unborn Star +PCSE00707 AR Nosurge Plus: Ode to an Unborn Star +PCSG00751 Arcana Famiglia -La storia della Arcana Famiglia- Ancora +PCSE00427 Arcana Heart 3 LOVE MAX!!!!! +PCSG00328 Arcana Heart 3: LOVE MAX!!!!! +PCSB00050 Army Corps of Hell +PCSE00006 ARMY CORPS OF HELL +PCSE01379 Asdivine Dios +PCSE00968 Asdivine Hearts +PCSE01335 Asdivine Hearts II +PCSE01419 Asdivine Menace +PCSE00007 Asphalt: Injection +PCSG00116 Assassin's Creed® III Lady Liberty +PCSB00074 Assassin's Creed® III Liberation +PCSE00053 Assassin's Creed® III Liberation +PCSG90030 Assault Army +PCSG90032 Assault Gunners Trial Version +PCSG00901 AstralAir no Shiroki Towa: White Eternity +PCSG90248 AstralAir no Shiroki Towa: White Eternity Trial Version +PCSE01333 Atari Flashback Classics +PCSE00584 Atelier Ayesha Plus ~The Alchemist of Dusk~ +PCSB00700 Atelier Ayesha Plus ~The Alchemist of Dusk~ +PCSG00347 Atelier Ayesha Plus: The Alchemist of Dusk +PCSB00906 Atelier Escha & Logy Plus ~Alchemists of the Dusk Sky~ +PCSG00522 Atelier Escha & Logy Plus: Alchemists of the Dusk Sky +PCSE00826 Atelier Escha & Logy Plus: Alchemists of the Dusk Sky +PCSB01087 Atelier Firis ~The Alchemist and the Mysterious Journey~ +PCSE01044 Atelier Firis ~The Alchemist and the Mysterious Journey~ +PCSH10026 Atelier Firis ~The Alchemist and the Mysterious Journey~ +PCSG00929 Atelier Firis: The Alchemist of the Mysterious Journey +PCSG01116 Atelier Lydie & Suelle: The Alchemists and the Mysterious Paintings +PCSE00296 Atelier Meruru Plus: The Apprentice of Arland +PCSB00377 Atelier Meruru Plus: The Apprentice of Arland +PCSG00171 Atelier Meruru Plus: The Apprentice of Arland +PCSG01223 Atelier Nelke: The Alchemists and the New Earth +PCSE00466 Atelier Rorona Plus ~The Alchemist of Arland~ +PCSB00582 Atelier Rorona Plus ~The Alchemist of Arland~ +PCSG00245 Atelier Rorona Plus: The Alchemist of Arland +PCSE00998 Atelier Shallie Plus - Alchemists of the Dusk Sea +PCSG00821 Atelier Shallie Plus ~Alchemists of the Dusk Sea~ +PCSB01043 Atelier Shallie Plus ~Alchemists of the Dusk Sea~ +PCSE00892 Atelier Sophie ~The Alchemist of the Mysterious Book~ +PCSB00973 Atelier Sophie ~The Alchemist of the Mysterious Book~ +PCSG00694 Atelier Sophie: The Alchemist of the Mysterious Book +PCSH00220 Atelier Sophie: The Alchemist of the Mysterious Book +PCSH00231 Atelier Sophie: The Alchemist of the Mysterious Book +PCSE00231 Atelier Totori Plus: The Adventurer of Arland +PCSG00127 Atelier Totori Plus: The Adventurer of Arland +PCSB00291 Atelier Totori Plus: The Adventurer of Arland +PCSB00274 Atomic Ninjas +PCSE00274 Atomic Ninjas +PCSG00762 Attack on Titan +PCSE00812 Attack on Titan +PCSG01102 Attack on Titan 2 +PCSE00780 Attractio +PCSE01367 Awesome Pea +PCSE01474 Awesome Pea 2 +PCSB00779 Axiom Verge +PCSG00666 Ayakashi Gohan: Oomori! +PCSG01175 Azayaka na Irodori no Naka de, Kimi Rashiku +PCSE00861 Azkend 2: The World Beneath +PCSG00711 Baboon! +PCSE01343 Back in 1995 +PCSE00706 Back to Bed +PCSB00468 Backgammon Blitz +PCSB01092 Bad Apple Wars +PCSE01042 Bad Apple Wars +PCSB00669 BADLAND: Game of the Year Edition +PCSG00425 Bakumatsu Rock: Ultra Soul +PCSB01406 Balthazar's Dream +PCSG01123 Banbutsu Otome * Dungeons +PCSG00708 Bara ni Kakusareshi Verite +PCSG01006 Bard's Gold +PCSB00911 Baseball Riot +PCSE00790 Bastion +PCSB00353 Batman: Arkham Origins Blackgate +PCSE00444 Battalion Commander +PCSE01478 Battle Rockets +PCSG00244 Beast Tamer and Prince +PCSG00604 Beast Tamer and Prince ~Flower & Snow~ +PCSG00539 Believer! +PCSE00024 Ben 10™ Galactic Racing +PCSG01221 Beniiro Tenjou Ayakashi Kitan Futaai +PCSF00251 Bentley's Hackpack™ +PCSB01085 BERSERK and the Band of the Hawk +PCSE00377 Best of Arcade Games +PCSB00648 Best Of Arcade Games (FULL) +PCSE01495 Big Dipper +PCSE00091 Big Sky Infinity +PCSF00351 BigFest™ +PCSG00389 Binary Star +PCSB01105 Bit Dungeon Plus +PCSE00302 BIT.TRIP Presents... Runner2: Future Legend of Rhythm Alien +PCSG90096 Bitter Smile Trial +PCSG00242 Bitter smile. +PCSG00468 black butterfly psychedelia +PCSG00935 BLACK WOLVES SAGA -Weiβ und Schwarz- +PCSB00420 Blast 'Em Bunnies +PCSG00180 BLAZBLUE CHRONOPHANTASMA +PCSG00582 BLAZBLUE CHRONOPHANTASMA EXTEND +PCSB00042 BlazBlue Continuum Shift Extend +PCSG00003 BLAZBLUE CONTINUUM SHIFT EXTEND +PCSE00279 BlazBlue: ChronoPhantasma +PCSE00677 BlazBlue: Chronophantasma Extend +PCSE00018 BlazBlue: Continuum Shift EXTEND +PCSE01457 Blind Men +PCSB01250 Bloodstained: Curse of the Moon +PCSE00663 Bloxiq +PCSG00987 BLUE REFLECTION(幻に舞う少女の剣) +PCSE00864 Blue-Collar Astronaut +PCSE01019 Bodycheck +PCSG01205 Boku to Nurse no Kenshuu Nisshi +PCSG00797 Boku wa Mori Sekai no Kami Tonaru +PCSB00741 Bombing Busters +PCSE01368 Bonds of the Skies +PCSG00259 BOOLINK +PCSF00570 Borderlands 2 +PCSE00383 Borderlands 2 +PCSE00604 Boss +PCSE01349 Bouncy Bullets +PCSE00641 Breach & Clear +PCSE00225 BreakQuest: Extra Evolution +PCSB00265 BreakQuest: Extra Evolution +PCSE01429 Breeder Homegrown +PCSE00869 Bridge Constructor +PCSE00657 Broken Age +PCSE01517 Brotherhood United +PCSG00755 BROTHERS CONFLICT Precious Baby +PCSE01455 Bucket Knight +PCSG00361 Bullet Girls +PCSG00568 Bullet Girls 2 +PCSH10099 Bullet Girls Phantasia +PCSB01110 Bunny Must Die! Chelsea and the 7 devils +PCSG90261 Bunny Must Die! Chelsea and the 7devils. Trial version +PCSH10053 BURIED STARS +PCSE01135 Burly Men At Sea +PCSE00117 Burn the Rope +PCSG01197 Cafe Cuillere +PCSB00213 Call of Duty: Black Ops: Declassified +PCSG00135 Call of Duty® Black Ops: Declassified +PCSE00097 Call of Duty® Black Ops: Declassified +PCSB00232 Call of Duty® Black Ops: Declassified +PCSG00450 Captain Earth: Mind Labyrinth +PCSE00946 Castle Invasion: Throne Out +PCSB00111 CastleStorm +PCSG01179 Catherine: Full Body +PCSG90323 Catherine: Full Body Trial Verison +PCSH00099 CatsBlock Vestival +PCSB00573 Cel Damage HD +PCSE00422 Cel Damage HD +PCSG00409 Chain Chronicle V +PCSG00497 Chaos Rings I +PCSG00498 Chaos Rings II +PCSG00500 Chaos Rings III +PCSG00457 Chaos Rings III Prequel Trilogy +PCSG00499 Chaos Rings Ω +PCSE01022 Chaos;Child +PCSG00555 Chaos;Child +PCSB01075 CHAOS;CHILD +PCSG90169 Chaos;Child Demo +PCSG00995 Chaos;Child: Love Chuchu!! +PCSG00411 Chaos;Head Dual +PCSG00435 Chaos;Head Love Chu*Chu! +PCSG00434 Chaos;Head Noah +PCSG01150 Charade Maniacs +PCSE01031 Chasm +PCSB01233 Chicken Range +PCSB00598 Child of Light +PCSE00480 Child of Light +PCSG00850 Chou Ezaru wa Akai Hana: Koi wa Tsuki ni Shirube Kareru +PCSG00644 Chou Jigen Taisen Neptune VS Sega Hard Girls: Yume no Gattai Special +PCSG00234 Chou Megami Shinkou Noire: Gekishin Black Heart +PCSG00274 Chou no Doku Hana no Kusari Taishou Tsuyakoi Ibun +PCSG01066 Chouchou Jiken Rhapsodic +PCSE00044 Chronovolt +PCSB00102 Chronovolt +PCSE01281 Chronus Arc +PCSG00540 ChuSingura46+1 -忠臣蔵46+1- V +PCSG00454 Ciel Nosurge: Ushinawareta Hoshi e Sasagu Uta +PCSG00705 Citizens of Earth +PCSB00686 Citizens of Earth Demo +PCSE00562 Citizens of Earth Demo +PCSG00729 ClaDun Returns: This is Sengoku! +PCSE00999 ClaDun Returns: This is Sengoku! +PCSE01017 Cladun Returns: This is Sengoku! Demo +PCSB01067 Cladun Returns: This is Sengoku! Demo +PCSG90212 Cladun Returns: This is Sengoku! Trial Version +PCSG00415 CLANNAD +PCSA00038 Cliff Diving +PCSG00469 Clock Zero ~Shuuen no Ichibyou~ ExTime +PCSG00716 Clover Day's ~Making for Happiness.~ +PCSB00303 Coconut Dodge Revitalised +PCSE00267 Coconut Dodge Revitalised +PCSB01099 Code: Realize ~Future Blessings~ +PCSE00763 Code: Realize ~Guardian of Rebirth~ +PCSG01110 Code: Realize ~Silver Miracle~ +PCSG00805 Code: Realize ~The Future of Blessings~ +PCSE01278 Code:Realize ~Wintertide Miracles~ +PCSE01011 Collar x Malice +PCSB01061 Collar×Malice +PCSB00768 Color Guardians +PCSE00612 Color Guardians +PCSE01423 Color Slayer +PCSE00123 Colors! +PCSE00376 CONCEPTION II: Children of the Seven Stars +PCSB00547 Conception II: Children of the Seven Stars Demo +PCSE00425 Conception II: Children of the Seven Stars Demo +PCSG90087 Conception II: Children of the Seven Stars Demo +PCSG90092 Conception II: Children of the Seven Stars Demo +PCSE01406 Conga Master Go +PCSB01445 Contraptions +PCSB00822 Corpse Party BLOOD DRIVE +PCSE00708 Corpse Party BLOOD DRIVE +PCSG00298 Corpse Party: Blood Drive +PCSB00840 Corridor Z +PCSE00854 Corridor Z +PCSE01232 CosmicStarHeroine +PCSB00734 Cosmophony +PCSA00116 Counterspy +PCSG01246 Coven and Labyrinth of Galleria +PCSE00222 CRACKLE +PCSG00941 Crank In +PCSG90290 Crank In Trial Version +PCSE00291 Crazy Market +PCSE00916 Criminal Girls 2 Party Favors +PCSB00984 Criminal Girls 2 Party Favors +PCSG00681 Criminal Girls 2: Party Favors +PCSE00516 Criminal Girls: Invite Only +PCSB00636 Criminal Girls: Invite Only +PCSE00453 Crimsonland +PCSG00537 Croixleur Sigma +PCSE00689 Croixleur Sigma +PCSG00597 Cross Ange: Rondo of Angels and Dragons tr. +PCSG00365 CROSS†CHANNEL ~For all people~ +PCSB01331 Crossovers by POWGI +PCSH10175 Crossovers by POWGI +PCSE01377 Crossovers by POWGI +PCSE00806 Crypt of the NecroDancer +PCSE01464 Crypto by POWGI +PCSB01432 Crypto by POWGI +PCSH10240 Crypto by POWGI +PCSG00169 Cure Mate Club +PCSE01152 Cursed Castilla (Maldita Castilla EX) +PCSB01160 Cursed Castilla (Maldita Castilla EX) +PCSB00853 Curses 'N Chaos +PCSG01122 D.S.-Dal Segno- +PCSE01348 Daggerhood +PCSG00264 Dai-3-Ji Super Robot Taisen Z Jigoku-hen +PCSG00494 Dai-3-Ji Super Robot Taisen Z Tengoku-hen +PCSG00372 Daisenryaku Exceed II +PCSG00779 Daisenryaku Perfect: Senjou no Hasha +PCSG00504 Daisenryaku: Dai Toua Kouboushi 3 +PCSG00842 Damascus Gear Saikyou Exodus +PCSE00518 Damascus Gear: Operation Tokyo +PCSG00292 Damascus Gear: Operation Tokyo +PCSG90109 Damascus Gear: Operation Tokyo +PCSG00077 Danball Senki W Release +PCSG00807 Dance with Devils +PCSG01152 Dance with Devils My Carol +PCSG00202 Danganronpa 1&2 Reload +PCSE00399 Danganronpa 2: Goodbye Despair +PCSB00514 Danganronpa 2: Goodbye Despair +PCSE00692 Danganronpa Another Episode: Ultra Despair Girls +PCSB00788 Danganronpa Another Episode: Ultra Despair Girls +PCSG00772 Danganronpa Another Episode: Ultra Despair Girls +PCSE01100 Danganronpa V3: Killing Harmony +PCSE01105 Danganronpa V3: Killing Harmony Demo +PCSH10052 Danganronpa V3: Killing Harmony Demo version +PCSB01130 Danganronpa V3: Killing Harmony Demo version +PCSE00261 Danganronpa: Trigger Happy Havoc +PCSB00346 Danganronpa: Trigger Happy Havoc +PCSG01002 Danjon ni Deai o Motomeru no wa Machigatteiru Darou ka? Infinite Combate +PCSG01017 Daredemo Shodan ni Nareru Igo Kyoushitsu +PCSE00792 DARIUSBURST Chronicle Saviours +PCSE00919 Darkest Dungeon +PCSG00599 Date-A-Live Twin Edition: Rio Reincarnation +PCSB00540 Day D Tower Rush +PCSB00747 Day of the Tentacle Remastered +PCSE01181 Dead Ahead: Zombie Warfare +PCSA00151 Dead Nation™ +PCSB00296 DEAD OR ALIVE 5 PLUS +PCSG00167 DEAD OR ALIVE 5 PLUS +PCSG00771 Dead Or Alive Xtreme 3 Venus +PCSH00250 DEAD OR ALIVE Xtreme 3 Venus +PCSH00281 DEAD OR ALIVE Xtreme 3 Venus Free-to-Play Version +PCSE00578 Deadman's Cross +PCSE01279 Death Mark +PCSE00248 Deathmatch Village +PCSE00401 Deception IV: Blood Ties +PCSB00499 Deception IV: Blood Ties +PCSE00743 Deception IV: The Nightmare Princess +PCSB00829 Deception IV: The Nightmare Princess +PCSG00685 DEEMO ~The Last Recital~ +PCSE01041 DEEMO The Last Recital +PCSE01219 Deep Ones +PCSB01359 Deep Space Rush +PCSB01223 Defender's Quest: Valley of the Forgotten DX +PCSE00889 Delta Strike : First Assault +PCSE01005 Demetrios - The BIG Cynical Adventure +PCSE00358 Demon Gaze +PCSG00043 DEMON GAZE +PCSG00849 DEMON GAZE 2 +PCSB01150 DEMON GAZE 2 +PCSB01437 Demon's Tier+ +PCSE00639 Dengeki Bunko Fighting Climax +PCSG00341 Dengeki Bunko: Fighting Climax +PCSB00763 Dengeki Bunko: Fighting Climax +PCSG00758 Dengeki Bunko: Fighting Climax Ignition +PCSE00542 Desert Ashes +PCSG00959 DESIRE remaster ver. +PCSF00352 Destiny of Spirits +PCSA00106 Destiny of Spirits™ +PCSE01249 Devious Dungeon +PCSB01342 Devious Dungeon 2 +PCSB00953 Dex +PCSG00272 Diabolik Lovers Limited V Edition +PCSG00530 Diabolik Lovers: Dark Fate +PCSG00910 Diabolik Lovers: Lost Eden +PCSG00826 Diabolik Lovers: Lunatic Parade +PCSG00476 Diabolik Lovers: More, Blood Limited V Edition +PCSG00472 Diabolik Lovers: Vandead Carnival +PCSB00389 Die! Die! Die! +PCSE00755 Digimon Story Cyber Sleuth +PCSG00516 Digimon Story: Cyber Sleuth +PCSH00261 Digimon World: Next Order +PCSG00792 Digimon World: Next Order +PCSE00820 Dino Dini's Kick Off +PCSB00895 Dino Dini's Kick Off +PCSE00022 Disgaea 3: Absence of Detention +PCSB00098 Disgaea 3: Absence of Detention +PCSG00005 Disgaea 3:Return(魔界戦記ディスガイア3 Return) +PCSE00360 Disgaea 4: A Promise Revisited +PCSF00309 Disney Epic Mickey : Disney Epic Mickey 2: The Power of Two +PCSF00308 Disney Epic Mickey 2: The Power of Two +PCSA00110 Disney's Epic Mickey 2: The Power of Two +PCSB01165 DISTRAINT: Deluxe Edition +PCSB00373 Divekick +PCSE00208 DJMax Technika Tune +PCSG90047 DJMax Technika Tune Demo +PCSH00025 DJMax Technika Tune Demo +PCSC80021 DMM.com +PCSE00103 Doctor Who: The Eternity Clock +PCSG00775 Dogimegi Inryoku-Chan: Love & Peace +PCSG90220 Dogimegi Inryoku-Chan: Love & Peace Trial Version +PCSA00117 Doki-Doki Universe™ +PCSE00124 Dokuro +PCSB00215 Dokuro +PCSB00639 Don't Die, Mr Robot +PCSE00450 Don't Starve: Giant Edition +PCSE00327 Doodle Devil +PCSE00133 Doodle God +PCSB00556 Doodle Kingdom +PCSG01100 Doukoku Soshite... Remastered +PCSB00952 Downwell +PCSE00873 Downwell +PCSE00305 Dragon Ball Z: Battle of Z +PCSB00424 Dragon Ball Z: Battle of Z Demo +PCSG90095 Dragon Ball Z: Battle of Z Demo +PCSE00330 Dragon Ball Z: Battle of Z Demo +PCSE00217 Dragon Fantasy Book 1 +PCSE00299 Dragon Fantasy Book 2 +PCSE00952 Dragon Fantasy: Black Tome of Ice +PCSE01086 Dragon Fantasy: Volumes of Westeria +PCSE00447 Dragon Fin Soup +PCSB00621 Dragon Fin Soup +PCSG00697 Dragon Quest Builders +PCSE00912 DRAGON QUEST BUILDERS +PCSE00934 Dragon Quest Builders Demo +PCSB00999 Dragon Quest Builders Demo +PCSG90213 Dragon Quest Builders Demo +PCSH00270 Dragon Quest Builders Demo +PCSH00298 Dragon Quest Heroes II +PCSG90245 Dragon Quest Heroes II Demo +PCSE01190 Dragon Sinker +PCSE00019 Dragon's Crown +PCSG00187 Dragon's Crown +PCSB00408 Dragon's Crown +PCSH00050 Dragon's Crown +PCSG00212 Dragon's Dogma Quest +PCSE01360 Dragonfly Chronicles +PCSE01193 Dragooned +PCSG00420 DRAMAtical Murder re:code +PCSE00224 Draw Slasher +PCSG00026 DREAM C CLUB ZERO PORTABLE +PCSE01365 Dreamwalker +PCSE00841 Dreii +PCSB01097 Drive Girls +PCSE01099 Drive Girls +PCSE01363 Drowning +PCSB01404 Duck Souls+ +PCSB00437 Duke Nukem 3D: Megaton Edition +PCSE00339 Duke Nukem 3D: Megaton Edition +PCSB01474 Dull Grey +PCSE00008 Dungeon Hunter: Alliance +PCSE00944 Dungeon Punks +PCSE00693 Dungeon Travelers 2 +PCSG00407 Dungeon Travelers 2 : The Royal Library & the Monster Seal +PCSE00718 Dungeon Travelers 2 Demo +PCSG90141 Dungeon Travelers 2 Demo +PCSG00841 Dungeon Travelers 2-2 +PCSG90278 Dungeon Travelers 2-2 Trial Version +PCSB00824 Dungeon Travelers 2: The Royal Library Demo +PCSG00482 Durarara!! Relay +PCSE00332 Dustforce +PCSB01051 DYING: Reborn +PCSE00984 Dying:Reborn +PCSG00860 DYNAMIC CHORD feat.[reve parfait] V edition +PCSG00915 DYNAMIC CHORD feat.apple-polisher V edition +PCSG00862 DYNAMIC CHORD feat.KYOHSO V edition +PCSG00861 DYNAMIC CHORD feat.Liar-S V edition +PCSG90136 Dynasty Warriors 8 Empires Edit Mode Trial Version +PCSE00405 Dynasty Warriors 8: Xtreme Legends Complete Edition +PCSH00058 Dynasty Warriors Gundam Reborn +PCSE00014 Dynasty Warriors Next +PCSG00002 Dynasty Warriors Next +PCSB00108 Dynasty Warriors Next Demo Version +PCSE00069 Dynasty Warriors Next Demo Version +PCSG90006 Dynasty Warriors Next Trial Version +PCSG90018 Dynasty Warriors Next Trial Version +PCSH00004 Dynasty Warriors Next Trial Version +PCSE00995 DYNASTY WARRIORS: Godseekers +PCSH10007 Dynasty Warriors: Godseekers Trial Version +PCSG90243 Dynasty Warriors: Godseekers Trial Version +PCSB00084 EA SPORTS FIFA Football Demo +PCSB00082 EA SPORTS FIFA Football Demo +PCSB00086 EA SPORTS FIFA Football Demo +PCSE00059 EA SPORTS FIFA Football Demo +PCSB00083 EA SPORTS FIFA Football Démo +PCSE00060 EA SPORTS FIFA Football Démo +PCSE00055 EA SPORTS FIFA Soccer Demo +PCSG00039 EA SPORTS™ FIFA Football +PCSG00432 Earth Defense Force 2: PORTABLE V2 +PCSB00884 Earth Defense Force 2: Invaders from Planet Space +PCSE00710 Earth Defense Force 2: Invaders from Planet Space +PCSE00209 Earth Defense Force 2017 Portable +PCSG00291 EbiKore+ Amagami (エビコレ+ アマガミ) +PCSA00087 Ecolibrium™ +PCSG00753 Eikoku Tantei Mysteria: The Crown +PCSG01026 Eiyuu Densetsu: Akatsuki no Kiseki +PCSG00042 Eiyuu Densetsu: Zero no Kiseki Evolution +PCSG00316 Eiyuu*Senki +PCSH00246 Element4l +PCSB01325 Emerald Shores +PCSB01443 EMMA: Lost In Memories +PCSG00963 end sleep +PCSG90254 End Sleep Trail Version +PCSB00945 Energy Balance +PCSE01124 Energy Cycle +PCSE01192 Energy Invasion +PCSG01167 Enkan no Memoria: Kakera Tomoshi +PCSA00140 Entwined™ +PCSG01134 Ephemeral FANTASY ON DARK +PCSB01431 Epic Word Search Collection +PCSB01458 Epic Word Search Collection 2 +PCSF00023 Escape Plan +PCSA00004 Escape Plan™ +PCSE00095 escapeVektor +PCSE00395 Ethan: Meteor Hunter +PCSG00817 EVE burst error R +PCSG01249 EVE rebirth terror +PCSG01139 Evening Bell of Piofiore +PCSC00001 Everybody's Golf +PCSE00941 Exile's End +PCSG00679 Exist Archive +PCSB00995 Exist Archive +PCSE00883 Exist Archive: The Other Side of the Sky +PCSB01419 Explosive Jake +PCSG00196 Exstetra +PCSB00027 F1 2011 +PCSE00002 F1 2011 +PCSA00042 Facebook +PCSE01051 Factotum90 +PCSG00798 Fairune +PCSE00955 Fallen Legion +PCSH00157 Fantasy Hero ~unsigned legacy~ +PCSG00280 FANTASY HERO~unsigned legacy~ +PCSB00333 Farming Simulator +PCSE00285 Farming Simulator +PCSE00419 Farming Simulator 14 +PCSH00117 Farming Simulator 14 +PCSB00843 Farming Simulator 16 +PCSE01035 Farming Simulator 18 +PCSE01334 Fast Striker +PCSB00894 Fat City +PCSA00156 Fat Princess: Piece of Cake +PCSF00612 Fat Princess: Piece of Cake +PCSG00600 Fate/EXTELLA +PCSG01091 Fate/EXTELLA LINK +PCSE01254 Fate/EXTELLA LINK +PCSE00928 Fate/Extella: The Umbral Star +PCSG00386 Fate/hollow ataraxia +PCSG00122 Fate/Stay Night [Realta Nua] +PCSE01282 Fernz Gate +PCSE00404 Fez +PCSE00266 Fieldrunners 2 +PCSG00107 FIFA 13 WORLD CLASS SOCCER +PCSE00263 FIFA 14 +PCSG00201 FIFA 14 WORLD CLASS SOCCER +PCSG00404 FIFA 15 +PCSE00481 FIFA 15 +PCSE01431 Fifty Words by POWGI +PCSB01397 Fifty Words by POWGI +PCSH10211 Fifty Words by POWGI +PCSE01255 Fill-a-Pix: Phil's Epic Adventure +PCSB00395 FINAL FANTASY X HD Remaster +PCSG00219 FINAL FANTASY X HD Remaster +PCSB00394 Final Fantasy X-2 HD Remaster +PCSG00220 FINAL FANTASY X-2 HD Remaster +PCSE00504 Final Horizon +PCSA00037 Fireworks +PCSB00656 Flame Over +PCSE00566 Flame Over +PCSB00328 Floating Cloud God Saves the Pilgrims in HD! +PCSG01202 Floral flowlove +PCSA00114 Flower +PCSG00459 FLOWERS +PCSG00739 Flowers Le volume sur ete +PCSG01187 Flowers Le volume sur hiver +PCSB00382 Flyhunter Origins +PCSE00257 Flying Hamster HD +PCSE00039 Foosball 2012 +PCSB00160 Foosball 2012 +PCSE00797 Forma.8 +PCSE00321 Fort Defense +PCSB00472 Fort Defense North Menace +PCSG01131 Fortissimo +PCSH10065 Fortune Street: Dragon Quest & Final Fantasy 30th Anniversary +PCSB00522 Foul Play +PCSA00047 foursquare +PCSE01437 FoxyLand +PCSE01438 FoxyLand 2 +PCSE01380 Frane: Dragons' Odyssey +PCSA00147 Freedom Wars +PCSC00054 Freedom Wars +PCSD00087 FREEDOM WARS™ +PCSF00446 FREEDOM WARS™ +PCSG00519 Friend to Lover ~フレラバ~ +PCSA00050 FROBISHER SAYS!™ +PCSE00528 Frozen Synapse Prime +PCSE00229 Fruit Ninja +PCSB00273 Fruit Ninja +PCSG01260 Full Kiss +PCSB01053 Full Throttle Remastered +PCSE01261 FullBlast +PCSE00839 Funk of Titans +PCSB00421 Furmins +PCSE00111 Furmins +PCSG00227 Furuiro Meikyuu Rondo: La Roue de fortune +PCSG00922 Furuki Yoki Jidai no Boukentan +PCSB01333 Furwind +PCSG00569 Fushigi no Chronicle: Furikaerimasen Katsu Madewa +PCSG01085 Futagoza no Paradox +PCSE00495 Futuridium EP Deluxe +PCSG00493 Fuuraiki 3 +PCSG01065 Gakuen Club Himitsu no Nightclub +PCSG00654 Gakuen K -Wonderful School Days- V Edition +PCSH00249 Gakusen Toshi Asterisk Festa - Houka Kenran +PCSG00704 Gal Gunvolt +PCSE00881 Gal*Gun Double Peace +PCSG00699 Gal*Gun Double Peace +PCSB00956 Gal*Gun Double Peace +PCSG01029 Gal*Gun Double Peace Bilingual +PCSG01151 GALTIA V Edition +PCSE01440 Ganbare! Super Strikers +PCSE00958 GAROU: MARK OF THE WOLVES +PCSE00981 Geki Yaba Runner +PCSG00214 Gekijouban Madoka Magicka: The Battle Pentagram +PCSB00799 Gem Legends +PCSB00965 GemSmashers 3D +PCSG00373 Gendai Daisenryaku 2016 ~Chitsujo no Houkai·Haken Kokka Shittsui~ +PCSG00256 GENIMUS +PCSG00619 Genji Koi Emaki +PCSG00695 Genkai Tokki: Moero Crystal +PCSH00301 Genkai Tokki: Moero Crystal +PCSG00882 Genkai Tokki: Seven Pirates +PCSG01294 Gensou Rougoku no Kaleidoscope +PCSB00769 Geometry Wars 3: Dimensions +PCSB00610 Get Off My Lawn! +PCSE00421 Get Off My Lawn! +PCSG00921 Geten no Hana with Yume Akari - Aizouban +PCSG90098 Getsuei Gakuen -kou- +PCSG00991 Getsuei no Kusari: Kouran Moratorium +PCSG00794 Getsuei no Kusari: Sakuran Paranoia +PCSB01378 Ghoulboy +PCSE01340 Ghoulboy +PCSG00419 Ginsei Igo: Next Generation +PCSG01073 Gintama Rumble +PCSG00670 Girlfriend (Kari) - Kimi to Sugosu Natsuyasumi +PCSG00339 Girls und Panzer: Senshado, Kiwamemasu! +PCSG01277 Gnosia +PCSG00786 Gochuumon wa Usagi Desu ka?? +PCSG00240 GOD EATER 2 +PCSE00789 GOD EATER 2 RAGE BURST +PCSG00532 GOD EATER 2 RAGE BURST +PCSH00133 GOD EATER 2 RAGE BURST +PCSG00719 GOD EATER RESURRECTION +PCSH00199 GOD EATER RESURRECTION +PCSE00801 GOD EATER RESURRECTION +PCSF00438 God of War® Collection +PCSA00126 God of War® Collection +PCSG00831 God Wars: Future Past +PCSG00367 Goes! +PCSG00218 Golden Time Vivid Memories +PCSE00879 Grand Kingdom +PCSB01372 Grass Cutter +PCSE00487 Gravity Badgers +PCSB00525 Gravity Crash Ultra +PCSC00002 GRAVITY DAZE™ +PCSE01384 Gravity Duck +PCSB01338 Gravity Duck +PCSD00035 GRAVITY RUSH +PCSF00024 GRAVITY RUSH™ +PCSA00011 GRAVITY RUSH™ +PCSF00067 GRAVITY RUSH™ (DEMO) +PCSB00949 Green Game: Timeswapper +PCSE00547 Grim Fandango Remastered +PCSG00206 Grisaia no Kajitsu Le Fruit de la Grisaia +PCSG00620 Grisaia no kajitsu spinout +PCSG00421 Grisaia no Meikyuu Le Labyrinthe de la Grisaia +PCSG01149 Grisaia Phantom Trigger 01 & 02 +PCSG01218 Grisaia Phantom Trigger 03 & 04 +PCSE00033 Guacamelee! +PCSB00189 Guacamelee! +PCSB01416 Guard Duty +PCSG00131 GUILTY GEAR XX ΛCORE PLUS R +PCSG01013 Gun Gun Pixies +PCSG00126 Gundam Breaker +PCSG00412 Gundam Breaker 2 +PCSH00208 Gundam Breaker 3 +PCSH10042 Gundam Breaker 3 BREAK EDITION +PCSH10041 GUNDAM BREAKER 3 BREAK EDITION +PCSG00657 Gundam Conquest V +PCSE01283 GUNDEMONIUMS +PCSG01289 Gunka o Haita Neko +PCSE00340 Gunslugs +PCSB01365 Habroxia +PCSE01504 Habroxia 2 +PCSG00162 Haiyore! Nyaruko-San +PCSG00577 Hakuisei Aijou Izonshou +PCSG01275 Hakuisei Renai Shoukougun Re:Therapy +PCSE01001 Hakuoki Edo Blossoms +PCSG00217 Hakuouki Kyouka Roku +PCSG00605 Hakuouki Reimeiroku +PCSG00297 Hakuouki SSL: Sweet School Life +PCSG00930 Hakuouki Yugiroku The Great Banquet of the Members +PCSG00811 Hakuouki: Shinkai - Hana no Shou +PCSG00485 Hakuouki's Memoirs Omokagegehana +PCSE01258 Halloween Forever +PCSG00855 Hana Oboro ~Sengoku-den Ranki~ +PCSG01024 Hanasaki Work Spring! +PCSG00576 Hanayaka Nari, Wa ga Ichizoku: Gentou Nostalgie +PCSG00470 Hanayaka Nari, Wa ga Ichizoku: Modern Nostalgie +PCSG00451 Hanayamata: Yosakoi Live! +PCSE00681 Handball 16 +PCSG00992 Harukanaru Toki no Naka de 3 Ultimate +PCSG00542 Harukanaru Toki no Naka De 6 +PCSG00975 Harukanaru Toki no Naka de 6: Gentou Rondo +PCSG01157 Harukanaru Toki no Naka de Ultimate +PCSG01252 Haruoto Alice Gram: Snow Drop +PCSG00559 Harvest OverRay +PCSE00653 Hatoful Boyfriend +PCSE00776 Hatoful Boyfriend: Holiday Star +PCSG01229 Hatsujou Sprinkle +PCSE00867 Hatsune Miku Project DIVA X +PCSE00886 Hatsune Miku Project DIVA X Demo +PCSE00326 Hatsune Miku: Project DIVA f +PCSB00419 Hatsune Miku: Project DIVA f +PCSG00074 Hatsune Miku: Project DIVA f +PCSB00506 Hatsune Miku: Project DIVA f (DEMO) +PCSG00205 Hatsune Miku: Project DIVA F 2nd +PCSB00554 Hatsune Miku: Project DIVA F 2nd +PCSE00434 Hatsune Miku: Project DIVA F 2nd +PCSH00115 Hatsune Miku: Project DIVA F 2nd (DEMO) +PCSG00683 Hatsune Miku: Project Diva X +PCSB01007 Hatsune Miku: Project DIVA X +PCSH00239 Hatsune Miku: Project Diva X (DEMO) +PCSH00176 Hatsune Miku: Project DIVA X (初音未來 -Project DIVA- X) +PCSB01009 Hatsune Miku: Project DIVA X Demo +PCSG90214 Hatsune Miku: Project DIVA X Trial (DEMO) +PCSG00988 Hatsuru Kotonaki Mirai Yori +PCSG00997 Hatsuyuki Sakura +PCSA00134 HELLDIVERS™ +PCSE00666 Heroes of Loot +PCSE01256 Heroes Trials +PCSG00388 Hideboh: Tap Dance Hero +PCSG00406 High School DxD: New Fight +PCSG00517 Higurashi no Naku Koro ni Sui +PCSG00639 Himawari Pebble in the Sky +PCSH10186 Himno +PCSG00688 Himouto! Umaru-chan: Umaru Training Plan +PCSE00254 HISTORY: Legends of War: Patton +PCSB00922 Hitman GO: Definitive Edition +PCSE00846 Hitman GO: Definitive Edition +PCSG00506 Hitotsu Tobashi Ren’ai V +PCSB01340 Hoggy2 +PCSA00123 Hohokum +PCSE00533 Home - A Unique Horror Adventure +PCSB00687 Home - A Unique Horror Adventure +PCSG00926 Hoshi ori yume mirai +PCSA00009 Hot Shots Golf™: World Invitational +PCSG00200 Hotchkiss +PCSE00249 Hotline Miami +PCSB00318 Hotline Miami +PCSE00402 Hotline Miami 2: Wrong Number +PCSB00511 Hotline Miami 2: Wrong Number +PCSB00641 htoL#NiQ -The Firefly Diary- +PCSE00527 htoL#NiQ -The Firefly Diary- +PCSE00551 HTR+ Slot Car Simulation +PCSB00938 HTR+ Slot Car Simulation +PCSE00996 Hue +PCSB00246 Hungry Giraffe +PCSA00007 Hustle Kings +PCSG00518 Hyakka Ryouran Elixir: Record of Torenia Revival +PCSG00477 Hyakka Yakou +PCSE00568 Hyperdevotion Noire Goddess Black Heart +PCSE00400 Hyperdimension Neptunia PP +PCSB00515 Hyperdimension Neptunia PP +PCSG00226 Hyperdimension Neptunia Re;Birth 1 +PCSE00443 Hyperdimension Neptunia Re;Birth 1 +PCSB00626 Hyperdimension Neptunia Re;Birth2 +PCSE00661 Hyperdimension Neptunia Re;Birth3 V GENERATION +PCSG00486 Hyperdimension Neptunia Re;Birth3: V Century +PCSG00394 Hyperdimension Neptunia U: Action Unleashed +PCSB00710 HYPERDIMENSION NEPTUNIA U: Action Unleashed +PCSE00588 HYPERDIMENSION NEPTUNIA U: Action Unleashed +PCSG90077 Hyperdimension Neptunia: Producing Perfection Demo +PCSE01188 I Am The Hero +PCSG01257 I Am The Hero +PCSE01358 I and Me +PCSG00592 I DOLL U - +PCSG00337 I wanna say that I'm not your brother right now!! +PCSG00355 IA/VT -COLORFUL- +PCSE01245 Ice Cream Surfer +PCSE01177 Iconoclasts +PCSG00965 id: RebirthSession +PCSG00865 Idol Death Game TV +PCSG01094 IDOLiSH7 Twelve Fantasia! +PCSG00357 If my Heart Had Wings +PCSG01063 Ikemen Sengoku: Toki o Kakeru Koi - Aratanaru Deai +PCSG00756 Ikenie to Yuki no Setsuna +PCSE01418 Illusion of L'Phalcia +PCSA00113 Imaginstruments +PCSF00210 Imaginstruments +PCSG00602 Incognito, Falling in Love ― Snow Moon Flower Love Emaki ― +PCSE00041 INDOOR SPORTS WORLD +PCSH00278 Infinita Strada Hana +PCSG00270 Infinite Stratos 2: Ignition Hearts +PCSG00584 Infinite Stratos 2: Love and Purge +PCSB00356 Injustice: Gods Among Us Ultimate Edition +PCSE00271 Injustice: Gods Among Us Ultimate Edition +PCSE01237 InkSplosion +PCSB00157 International Snooker 2012 +PCSA00137 Invizimals: The Alliance +PCSF00415 Invizimals™ Hidden Challenges +PCSF00510 Invizimals™: The Resistance +PCSA00552 Invizimals™: The Resistance +PCSE00876 iO +PCSB01029 Iron Sea Defenders +PCSE01369 Iron Snout +PCSG01186 IS IT WRONG TO TRY TO PICK UP GIRLS IN A DUNGEON? SHOOTING +PCSG01000 ISLAND +PCSB01132 It's Spring Again +PCSG00932 Itadaki Street: Dragon Quest & Final Fantasy 30th Anniversary +PCSG01083 Iwaihime Matsuri +PCSG01297 IxSHE Tell +PCSG00300 J-Stars Victory VS +PCSE00595 J-Stars Victory Vs+ +PCSH00136 J-STARS Victory VS+ +PCSB00713 J-STARS Victory VS+ +PCSE01287 Jack N' Jill DX +PCSB01268 Jack N' Jill DX +PCSF00250 Jak 3 +PCSA00080 Jak and Daxter Collection +PCSF00248 Jak and Daxter: The Precursor Legacy +PCSF00249 Jak II +PCSB00236 JAZZ Trump's Journey +PCSE00393 Jet Car Stunts +PCSB00136 Jet Set Radio +PCSE00088 Jet Set Radio +PCSE00213 Jetpack Joyride +PCSB00244 Jetpack Joyride +PCSB00664 Jetpack Joyride Deluxe +PCSE00537 Jetpack Joyride Deluxe +PCSG00064 Jikkyou Powerful Pro Yakyuu 2012 +PCSG00134 Jikkyou Powerful Pro Yakyuu 2012 Kettei Ban +PCSG00207 Jikkyou Powerful Pro Yakyuu 2013 +PCSG00416 Jikkyou Powerful Pro Yakyuu 2014 +PCSG00748 Jikkyou Powerful Pro Yakyuu 2016 +PCSG01164 Jikkyou Powerful Pro Yakyuu 2018 +PCSG01045 Jikkyou Powerful Pro Yakyuu Championship 2017 +PCSG01219 Jikkyou Powerful Pro Yakyuu Championship 2018 +PCSG00596 Jinro Game +PCSE00478 Joe Danger +PCSE00477 Joe Danger 2: The Movie +PCSG00390 JUDAS CODE(ジューダス コード) +PCSE00594 Jungle Rumble: Freedom, Happiness, and Bananas +PCSB01400 Just a Phrase by POWGI +PCSH10213 Just a Phrase by POWGI +PCSE01436 Just a Phrase by POWGI +PCSB01362 Just Ignore Them +PCSG00529 Justy x Nasty: Maou Hajime Mashita +PCSG00635 Jyuzaengi: Engetsu Sangokuden 1+2 +PCSG00381 Kadenz fermata Akkord:fortissimo +PCSG00501 Kaeru Batake de Tsukamaete +PCSG00304 Kagero: Darkside Princess +PCSG00360 Kaihou Shoujo SIN +PCSG00172 Kajiri Kamui Kagura: Akebono no Hikari +PCSG01007 Kamaitachi no Yoru: Rinne Saisei +PCSG00675 Kamen Rider: Battride War Genesis +PCSG01106 Kamidanomi Shisugite Ore no Mirai ga Yabai. +PCSG00595 Kamigami no Asobi InFinite +PCSG00684 KanColle Kai +PCSG01268 Kannagi no Mori Satsukiame Tsuzuri +PCSG01182 Kanojo * Step +PCSG01253 Karigurashi Ren'ai +PCSG01044 Karumaruka Circle +PCSG01332 Kawaii Deathu Desu +PCSG00553 Ken Ga Kimi For V +PCSG00960 Ken ga Kimi: Momoyo Tsuzuri +PCSG00829 Kenka Bancho Otome +PCSG01042 Kenka Bancho Otome : Kanzenmuketsu no My Honey +PCSG01241 Kenka Bancho Otome 2nd Rumble!! +PCSE00485 Kick and Fennick +PCSE00113 KickBeat +PCSB01354 Kid Tripp +PCSG00040 Kidou Senshi Gundam Seed: Battle Destiny +PCSE00473 Kilka Card Gods +PCSB01477 Killer Dolls United +PCSG01132 Killers and Strawberries +PCSD00071 Killzone Mercenary +PCSC00045 Killzone®: Mercenary +PCSF00403 Killzone™ Mercenary +PCSA00107 Killzone™ Mercenary +PCSF00243 Killzone™ Mercenary +PCSG01087 Kimi no Hitomi ni Hit Me +PCSG00913 Kimi o Aogi Otome wa Hime ni +PCSG01318 Kin-iro Loveriche +PCSG01124 Kin'iro no Corda 2 ff +PCSG01212 Kin'iro no Corda 3: AnotherSky feat. Jinnan / Shiseikan / Amane Gakuen +PCSG01211 Kin'iro no Corda 3: Full Voice Special +PCSG00774 Kin'iro no Corda 4 +PCSH00275 Kin'iro no Corda 4 +PCSG01245 Kin'iro no Corda: Octave +PCSE00315 King Oddball +PCSG00742 Kiss Ato +PCSG00413 KissBell +PCSG00478 KLAP!! ~Kind Love And Punish~ +PCSG00970 KLAP!! ~Kind Love And Punish~ Fun Party +PCSB01409 Knightin'+ +PCSB00929 Knock-knock +PCSB00169 Knytt Underground +PCSE00092 Knytt Underground +PCSE01040 KOI +PCSG01299 Koisuru Otome to Shugo no Tate: Bara no Seibo +PCSG00761 Kono Aozora ni Yakusoku o +PCSG00345 Kono Uta ga Owattara: When This Song is Over +PCSG00996 Kono Yo no Hate de Koi wo Utau Shoujo YU-NO Original +PCSG01093 Konosuba - Attack of the Destroyer +PCSG01265 KonoSuba: Give Education to this Useless Goddess! +PCSG01028 KonoSuba: Judgment on this Greedy Game! +PCSG01258 Konosuba: Labyrinth of Hope and the Gathering Adventurers +PCSG01213 Koshotengai no Hashihime Noma +PCSG00273 Kud Wafter: Converted Edition +PCSG00894 Kujiragami no Tearstilla +PCSE00256 Kung Fu Rabbit +PCSE01036 Kung Fury: Street Rage +PCSG01158 Kurenai no Homura Sanada Ninpou Chou +PCSG00609 Kurogane Kaikijong +PCSG00641 Kurogane Kaikitan: Ichigoichie +PCSG90129 Kurogane Kaikitan: Senya Ichiya +PCSG01288 L'Phalcia no Genei +PCSE00567 LA-MULANA EX +PCSE00985 Lara Croft GO +PCSE00856 Last Wings +PCSE01085 League of Evil +PCSH10082 Legend of Heroes: Trails in the Sky 3rd Evolution +PCSH00178 Legend of Heroes: Trails in the Sky FC Evolution +PCSE01426 Legend of the Skyfish +PCSB01392 Legend of the Skyfish +PCSE00061 LEGO Batman 2: DC Super Heroes +PCSE00442 Lego Batman 3 Beyond Gotham +PCSE00057 Lego Harry Potter Years 5-7 +PCSE00587 Lego Jurassic World +PCSE00237 Lego Legends of Chima Laval’s Journey +PCSB00764 Lego Marvel's Avengers +PCSE00384 Lego Ninjago Nindroids +PCSE00534 Lego Ninjago Shadow Of Ronin +PCSE00791 Lego Star Wars The Force Awakens +PCSE00390 Lego The Hobbit +PCSE00067 Lego The Lord Of The Rings +PCSB00315 LEGO® MARVEL Super Heroes: Universe in Peril +PCSE00670 LEGO® MARVEL's Avengers +PCSA00138 Lemmings™ Touch +PCSG00405 Lend fleur +PCSE00216 Let's Fish ! Hooked On +PCSB00230 Let's Fish! Hooked On +PCSG00028 Let's Try Bass Fishing FISH ON NEXT +PCSB00879 Letter Quest Remastered +PCSB00845 LEVEL 22 +PCSE01010 Lichtspeer +PCSB01154 Licky The Lucky Lizard Lives Again +PCSB00336 Limbo +PCSE00268 Limbo +PCSE01285 Link-a-Pix Deluxe +PCSG01319 Link-a-Pix Deluxe +PCSE01231 Little Adventure on the Prairie +PCSG00007 Little Busters! Converted Edition (リトルバスターズ! Converted Edition) +PCSF00017 Little Deviants +PCSA00010 Little Deviants™ +PCSB01215 Little Red Lie +PCSE01218 Little Red Lie +PCSF00021 LittleBigPlanet™ PlayStation®Vita +PCSA00017 LittleBigPlanet™ PlayStation®Vita +PCSA00549 LittleBigPlanet™ PlayStation®Vita Marvel Super Hero Edition +PCSB00494 Llamasoft TxK +PCSE01187 London Detective Mysteria +PCSB00361 Lone Survivor +PCSE00301 Lone Survivor +PCSF00441 Looney Tunes™ Galactic Sports +PCSG00008 Lord of Apocalypse +PCSG90001 Lord Of Apocalypse ロードの誘い +PCSE00673 Lost Dimension +PCSG01314 LOVE CLEAR +PCSG00422 Love Live! School idol paradise Vol.1 Printemps +PCSG00423 Love Live! School idol paradise Vol.2 BiBi +PCSG00424 Love Live! School idol paradise Vol.3 lily white +PCSG01004 Love of Ren'ai Koutei of LOVE! +PCSG00667 LOVE:QUIZ - Koisuru Shoujo no Final Answer +PCSG00336 LOVELY QUEST Unlimited +PCSG00556 LOVELY×CATION 1&2 +PCSH10290 Luckslinger +PCSG01165 Lucky Dog 1 +PCSE00247 LUFTRAUSERS +PCSE00009 Lumines Electronic Symphony +PCSG00444 Luminous Arc Infinity +PCSE00857 Lumo +PCSG00475 M3: Sono Kuroki Hagane /// Mission Memento Mori +PCSE00212 Machinarium +PCSG00947 Macross Delta: Scramble +PCSE00084 Madden NFL 13 +PCSG00221 Magical Beat +PCSE00464 Magical Beat (DEMO) +PCSE00749 Mahjong Carnival +PCSG00029 Mahjong Fight Club: Shinsei Zenkoku Taisen Han +PCSG00368 Mahou Shoujo Taisen Zanbatsu +PCSG00456 Mahouka Koukou no Rettousei: Out of Order +PCSG00856 Maison de Maou +PCSG00852 Maji-Kyun! Renaissance +PCSG00652 Majin Shoujo - Chronicle 2D ACT (Japan) (En,Ja,Zh) (PSN) +PCSG00770 Majo Koi Nikki: Dragon x Caravan +PCSG01284 Making*Lovers +PCSG00130 MALICIOUS REBIRTH +PCSA00127 MALICIOUS™ REBIRTH +PCSE00736 Maliya +PCSG00340 MANGA-KA-KERU +PCSG00448 MARGINAL#4 IDOL OF SUPERNOVA +PCSG01008 MARGINAL#4 ROAD TO GALAXY +PCSG00662 Maru Goukaku! Takken Shiken - Heisei 27 Nendohan +PCSG00898 Mary Skelter: Nightmares +PCSB01059 Mary Skelter: Nightmares +PCSE01158 Mecho Tales +PCSE01264 Mecho Wars: Desert Ashes +PCSH10177 Mecho Wars: Desert Ashes +PCSB00921 MegaTagmension Blanc Neptune VS Zombies +PCSG00578 MegaTagmension Blanc + Neptune VS Zombies +PCSH00236 MegaTagmension Blanc + Neptune VS Zombies (Asia) +PCSE00832 MegaTagmension Blanc Neptune VS Zombies +PCSG00398 Meikyuu Cross Blood: Infinity Ultimate +PCSG00258 MeiQ +PCSE00918 MeiQ: Labyrinth of Death +PCSB00990 MeiQ: Labyrinth of Death +PCSG00606 MeiQ: Labyrinth of Death +PCSE01428 Mekabolt +PCSB01348 MEKORAMA +PCSG01285 MELLKISS +PCSG00733 Melty Moment +PCSG00176 Memories Off 6 Complete +PCSH10133 Memories Off Innocent Fille +PCSG01264 Memories Off Innocent Fille for Dearest +PCSB00313 Men's Room Mayhem +PCSE00252 Men's Room Mayhem +PCSE00956 Mercenary Kings +PCSH10097 METAGAL +PCSE01080 METAGAL +PCSE00078 Metal Gear Solid 2: Sons of Liberty HD Edition +PCSG00081 Metal Gear Solid 3 HD Edition +PCSE00079 Metal Gear Solid 3: Snake Eater HD Edition +PCSB00118 Metal Gear Solid HD Collection +PCSG00972 METAL MAX Xeno +PCSE00665 METAL SLUG 3 +PCSB00772 METAL SLUG 3 +PCSE00406 Metrico +PCSH10242 Metropolis: Lux Obscura +PCSE00010 Michael Jackson The Experience HD +PCSG00198 Midnight Deluxe +PCSE01194 Midnight Deluxe +PCSG01193 Mikagami Sumika no Seifuku Katsudou +PCSC00052 Miku Miku Hockey +PCSC00081 Miku Miku Hockey 2.0 +PCSB01393 Miles & Kilo +PCSE01425 Miles & Kilo +PCSB01414 Milo's Quest +PCSE01501 Mind Maze +PCSG00184 MIND≒0 +PCSE00491 Minecraft: Playstation Vita Edition +PCSG00302 Minecraft: Playstation Vita Edition +PCSB00560 Minecraft: PlayStation Vita Edition +PCSG00581 Minna de Spelunker Z +PCSC00055 Minna to Issho +PCSB00544 Minutes™ +PCSG00610 Miracle Girls Festival +PCSH10169 Mixups by POWGI +PCSB01332 Mixups by POWGI +PCSE01378 Mixups by POWGI +PCSA00002 MLB 12 The Show +PCSA00065 MLB 13: The Show +PCSA00511 MLB15 THE SHOW +PCSB00983 Mobile Suit Gundam Extreme Versus Force +PCSG00579 Mobile Suit Gundam: Battle Fortress +PCSG00738 Mobile Suit Gundam: Extreme VS Force +PCSE00915 Mobile Suit Gundam: Extreme VS-Force +PCSE01414 Mochi Mochi Boy +PCSA00001 ModNation™ Racers: Road Trip +PCSF00002 ModNation™ Racers: Road Trip +PCSG00989 Moe Moe 2-Ji Daisenryaku 3 +PCSG00065 Moe Moe Daisensou Gendai Ban Plus Plus +PCSG00378 Monobeno -pure smile- +PCSB00473 Monster Monpiece +PCSG00148 Monster Monpiece +PCSF00651 MonsterBag - +PCSE00838 MOP: Operation Cleanup +PCSB00106 Mortal Kombat +PCSE00023 Mortal Kombat +PCSG00706 Moshi, Kono Sekai ni Kami-sama ga Iru to suru Naraba. +PCSB00498 MotoGP 14 +PCSB00316 MotoGP™13 +PCSC00014 MOTORSTORM® RC +PCSF00046 MotorStorm®RC - +PCSG00247 Motto Nee, Chanto Shouyo! +Plus +PCSG00854 Moujuu-tachi to Ohime-sama +PCSB00530 MouseCraft +PCSE01002 Mr.Pumpkin Adventure +PCSB00367 Ms. Germinator +PCSB00182 MUD - FIM Motocross World Championship™ +PCSB00685 Multiplayer.it +PCSE00240 Muramasa Rebirth +PCSB00404 Muramasa Rebirth +PCSA00153 Murasaki Baby +PCSF00435 Murasaki Baby™ +PCSC00043 Muryou-ban E-Channel NEW Paint Park +PCSE01479 Mushroom Heroes +PCSH10037 Musou Stars +PCSE01184 Musynx +PCSB00979 Mutant Mudds Super Challenge +PCSB01234 Muv-Luv +PCSE01259 Muv-Luv +PCSG00776 Muv-Luv +PCSG00777 Muv-Luv Alternative +PCSG90203 Muv-Luv Alternative Total Eclipse: Teito Moyu +PCSE00530 MXGP - The Official Motocross Videogame +PCSB01463 My Aunt is a Witch +PCSE01386 My Big Sister +PCSE00982 My Name Is Mayo +PCSE00459 My Singing Monsters +PCSB00958 Mystery Chronicle: One Way Heroics +PCSG01178 NadeRevo! Nadeshiko Revolution +PCSG00664 Nanairo Reincarnation +PCSG01185 Natsuiro Kokoro Log +PCSG00650 Natsumegu +PCSB00594 NAtURAL DOCtRINE +PCSE00460 NAtURAL DOCtRINE +PCSG00030 NAX Music Player +PCSB01321 Necrosphere +PCSE01413 Need a packet? +PCSE00089 Need For Speed™ Most Wanted +PCSG00106 Need For Speed™ Most Wanted +PCSB00183 Need For Speed™ Most Wanted +PCSG00410 Nekketsu Inou Bukatsu: Trigger Kiss +PCSG01068 Neo Angelique: Tenshi no Namida +PCSG00877 Neo ATLAS 1469 +PCSB00910 Neon Chrome +PCSE01398 Neon Junctions +PCSG00951 Nep-Nep Connect: Chaos Chanpuru +PCSG00656 Net High +PCSE00070 Netflix +PCSE01236 NeuroVoider +PCSE01137 NeverEnd +PCSE00847 Neverending Nightmares +PCSB00940 Neverending Nightmares +PCSG00903 New Game! -The Challenge Stage!- +PCSH10101 New Game! -The Challenge Stage!- Chinese Version +PCSB00109 New Little King's Story +PCSE00066 New Little King's Story +PCSG01204 NG +PCSG80001 niconico +PCSE00514 Nidhogg +PCSH00254 Night of Azure / Yoru no Nai Kuni (無夜國度) +PCSG00986 Night of Azure 2 / Yoru no Nai Kuni 2 +PCSE01149 Night Trap - 25th Anniversary Edition +PCSE00895 NightCry +PCSG00557 Nights of Azure / Yoru no Nai Kuni +PCSB00705 Nihilumbra +PCSE00620 Nihilumbra +PCSG00586 Nihilumbra +PCSG00082 Nikoli no Puzzle V: Akari +PCSG00095 Nikoli no Puzzle V: Hashi o Kakero +PCSG00067 Nikoli no Puzzle V: Heyawake +PCSG00098 Nikoli no Puzzle V: Hitori ni Shitekure +PCSG00060 Nikoli no Puzzle V: Kakuro +PCSG00083 Nikoli no Puzzle V: Masyu +PCSG00097 Nikoli no Puzzle V: Number Link +PCSG00068 Nikoli no Puzzle V: Nurikabe +PCSG00096 Nikoli no Puzzle V: Shikaku ni Kire +PCSG00061 Nikoli no Puzzle V: Slither Link +PCSG00094 Nikoli no Puzzle V: Yajilin +PCSG00044 Nikoli no Sudoku V: Shugyoku no 12 Puzzle +PCSG01014 Nil Admirari's Balance Kuroyuri Enyoutan +PCSG00766 Nil Admirari's Balance Teito Illusion Kitan +PCSE00021 Ninja Gaiden Sigma Plus +PCSB00097 NINJA GAIDEN Σ PLUS +PCSG00157 NINJA GAIDEN Σ2 PLUS +PCSB00294 NINJA GAIDEN Σ2 PLUS +PCSB00903 Ninja Senki DX +PCSG01099 Ninja Usagimaru: Two Tails of Adventure +PCSG01111 Ninki Seiyuu no Tsukurikata +PCSG00397 Nisekoi: Yomeiri! +PCSA00150 No Heroes Allowed: No Puzzles Either!™ +PCSG00803 Nobunaga no Yabou 201X +PCSG00374 Nobunaga no Yabou: Souzou +PCSG00607 Nobunaga no Yabou: Souzou with Power-Up Kit +PCSG00741 Nobunaga no Yabou: Tenshouki with Power-Up Kit HD Version +PCSH00291 Nobunaga's Ambition: Souzou Sengoku Risshiden +PCSH00171 Nobunaga's Ambition: Sphere of Influence with Power-Up Kit +PCSG01107 Nora to Oujo to Noraneko Heart +PCSE01496 Norman's Great Illusion +PCSG00833 NORN9 ACT TUNE +PCSG00429 NORN9 LAST ERA +PCSB00847 NORN9 VAR COMMONS +PCSE00762 NORN9 VAR COMMONS +PCSE01173 NORTH +PCSE00686 Nova-111 +PCSE00828 Nuclear Throne +PCSE00220 Nun Attack +PCSE01004 Nurse Love Addiction +PCSB01054 Nurse Love Addiction +PCSE01318 Nurse Love Syndrome +PCSG00150 Oboro Muramasa +PCSG01021 Occultic;Nine +PCSE01097 Oceanhorn +PCSB00825 Octodad: Dadliest Catch +PCSE00623 Octodad: Dadliest Catch +PCSE00369 Oddworld: Munch's Oddysee HD +PCSE00899 Odin Sphere Leifthrasir +PCSH00218 Odin Sphere Leifthrasir +PCSB00986 Odin Sphere Leifthrasir +PCSE00341 OlliOlli +PCSE00479 OlliOlli2: Welcome to Olliwood +PCSG00550 Omega Labyrinth +PCSG00939 Omega Labyrinth Z +PCSH10044 Omega Labyrinth Z +PCSE00275 OMG HD Zombies! +PCSB01213 One Eyed Kutkh +PCSH10094 One More Dungeon +PCSG00358 ONE PIECE UNLIMITED WORLD R +PCSB00557 ONE PIECE Unlimited World Red +PCSH00034 ONE PIECE 海賊無雙2 +PCSG00743 One Piece: Burning Blood +PCSE00808 One Piece: Burning Blood +PCSG00142 One Piece: Pirate Warriors 2 +PCSG00544 One Piece: Pirate Warriors 3 +PCSE00638 ONE PIECE: PIRATE WARRIORS 3 +PCSH00205 One Tap Hero +PCSB01306 One Word by POWGI +PCSH10167 One Word by POWGI +PCSE01338 One Word by POWGI +PCSG00377 Ooedo Blacksmith +PCSA00118 OPEN ME!™ +PCSE00579 Operation Abyss: New Tokyo Legacy +PCSG00387 Operation Abyss: New Tokyo Legacy +PCSE01047 Operation Babel: New Tokyo Legacy +PCSG00514 Operation Babel: New Tokyo Legacy +PCSG00289 Ore ni Hatarakette Iwaretemo Otsu HD +PCSG00623 Ore ni Hatarakette Iwaretemo Tori +PCSF00536 Oreshika: Tainted Bloodlines +PCSC00060 Oreshika: Tainted Bloodlines +PCSA00155 Oreshika™: Tainted Bloodlines +PCSG00299 Oretachi ni Tsubasa wa Nai +PCSG01076 Oretachi no Sekai wa Owatteiru +PCSG00919 Orfleurs: Koufuku no Hanataba +PCSB00924 Organ Trail Complete Edition +PCSG00057 orgarhythm +PCSE00116 Orgarhythm +PCSG00427 Othello +PCSG00487 Otoko Yuukaku +PCSG00942 Otome Riron to Sono Shuuhen: Bon Voyage +PCSG01105 Ouka Sabaki Zan +PCSG00254 Oukaranman +PCSG00769 Ouma ga Toki: Kakuriyo no Enishi +PCSG90304 Our World is Ended +PCSG00728 Owari no Seraph: Unmei no Hajimari +PCSG00967 Owaru sekai to birthday +PCSG00496 OZMAFIA!! -vivace- +PCSB01462 Pachi Pachi +PCSA00059 Paint Park +PCSF00137 Paint Park +PCSA00111 Paint Park Plus +PCSE00489 Panda Run +PCSG01247 Panic Palette +PCSE01056 Papers, Please +PCSB01084 Papers, Please +PCSE01401 Paradox Soul +PCSE00821 Paranautical Activity +PCSG00549 Parfait +PCSE01082 Peasant Knight +PCSE01143 Penny-Punching Princess +PCSB01060 Period Cube ~Shackle of Amadeus~ +PCSG00853 Period Cube ~Shackle of Amadeus~ +PCSE01012 Period Cube ~Shackles of Amadeus~ +PCSG01031 Persona 3 Dancing in Moonlight +PCSE01274 Persona 3: Dancing in Moonlight +PCSB00245 Persona 4 Golden +PCSE00120 Persona 4 Golden +PCSG00563 Persona 4 Golden +PCSG00004 Persona 4 Golden +PCSH00021 Persona 4 The GOLDEN +PCSE00764 Persona 4: Dancing All Night +PCSB00867 Persona 4: Dancing All Night +PCSG00364 Persona 4: Dancing All Night +PCSG01030 Persona 5: Dancing in Starlight +PCSE01275 Persona 5: Dancing in Starlight +PCSB01257 Persona 5: Dancing in Starlight +PCSG00351 Phantasy Star Nova +PCSH00143 Phantasy Star Nova +PCSG90131 Phantasy Star Nova (DEMO) +PCSG90130 Phantasy Star Nova Battle (DEMO) +PCSG00141 Phantasy Star Online 2 +PCSF00718 Phineas and Ferb: Day of Doofenshmirtz +PCSG00139 PhotoKano Kiss +PCSG01071 Photon3 +PCSE01376 Pic-a-Pix Classic +PCSE01435 Pic-a-Pix Classic 2 +PCSE01253 Pic-a-Pix Color +PCSE01422 Pic-a-Pix Color 2 +PCSE01357 Pic-a-Pix Pieces +PCSE01466 Pic-a-Pix Pieces 2 +PCSE00065 Pinball Arcade +PCSA00109 Pinball Heroes: Complete +PCSF00167 Pinball Heroes: Complete +PCSE00751 Pirate Solitaire +PCSB00645 Pix The Cat +PCSE00553 Pix The Cat +PCSE00874 Pixel Hunter +PCSG00269 PixelJunk™ Monsters Ultimate HD +PCSE00307 PixelJunk™ Monsters Ultimate HD +PCSG00384 PixelJunk™ Shooter Ultimate +PCSE00064 Plants vs Zombies +PCSG00931 Plastic Memories +PCSA00069 PlayStation All-Stars Battle Royale +PCSC00032 PlayStation® All-Stars Battle Royale +PCSF00228 PlayStation® Home Arcade +PCSA00083 PlayStation® Home Arcade +PCSA00139 PlayStation®Vita Pets +PCSE00682 Pocket God vs Desert Ashes +PCSE00558 Pocket RPG +PCSG00672 POLARA +PCSE01050 POLARA +PCSG00509 Possession Magenta +PCSG00262 Power Pro Stadium +PCSG00006 Power Smash 4 +PCSE00961 Pox Nora +PCSG00905 Priministar +PCSG00491 Prince of Stride +PCSG00271 Princess Arthur +PCSG00188 Princess Strike! +PCSG00031 Pro Yakyuu Spirits 2012 +PCSG00151 Pro Yakyuu Spirits 2013 +PCSG00288 Pro Yakyuu Spirits 2014 +PCSG00541 Pro Yakyuu Spirits 2015 +PCSG01248 Pro Yakyuu Spirits 2019 +PCSG00572 Project Discovery +PCSE00311 Proteus +PCSH10091 Psychedelica of the Ashen Hawk +PCSE01166 Psychedelica of the Ashen Hawk +PCSE01164 Psychedelica of the black butterfly +PCSG00815 PsychicEmotion6 +PCSE00904 PSYCHO-PASS MANDATORY HAPPINESS +PCSB00985 PSYCHO-PASS MANDATORY HAPPINESS +PCSE00042 Puddle +PCSC00021 Puls-AR +PCSE00702 Pumped BMX + +PCSG00904 Puramai Wars V +PCSE00389 Putty Squad +PCSG00224 Puyo Puyo Tetris +PCSE00108 Puzzle by Nikoli V Slitherlink +PCSE00101 Puzzle by Nikoli V Sudoku +PCSG00045 Puzzle by Nikoli V: Sudoku +PCSE00561 Q*bert Rebooted +PCSE00143 Quell Memento +PCSG01037 Rabi Laby: Puzzle Out Stories +PCSE01111 Rabi-Ribi +PCSB00643 Race The Sun +PCSG01209 Radio Hammer Station +PCSG00958 Raging Loop +PCSG00025 Ragnarok Odyssey +PCSE00300 Ragnarok Odyssey ACE +PCSG00140 Ragnarok Odyssey ACE +PCSE00273 Rainbow Moon +PCSE00318 Rainbow Skies +PCSE01351 Random Heroes: Gold Edition +PCSF00484 Ratchet & Clank +PCSF00485 Ratchet & Clank 2 +PCSF00486 Ratchet & Clank 3 +PCSF00482 Ratchet & Clank Trilogy +PCSA00086 Ratchet & Clank: Full Frontal Assault +PCSF00191 Ratchet and Clank : QForce +PCSE00843 Ray Gigant +PCSB00928 RAYGIGANT +PCSE00277 Rayman Legends +PCSE00052 Rayman® Origins +PCSG00382 RE:VICE[D] +PCSG00933 Re:Zero - kara Hajimeru Isekai Seikatsu - Death or Kiss +PCSE00325 Real Boxing™ +PCSA00012 Reality Fighters™ +PCSG00663 Rear Pheles: Red of Another +PCSG00782 Reco Love: Gold Beach +PCSG00781 RecoLove: Blue Ocean +PCSE01434 Red Bow +PCSG90210 Red Sand Falling Moon Trial Version +PCSE01471 Reed 2 +PCSE01456 Reed Remastered +PCSG00795 Refrain no Chika Meikyuu to Majo no Ryodan +PCSG00426 Ren’ai 0 Kilometer V +PCSG00718 Renai Revenge +PCSG00990 RepKiss +PCSE00608 Resident Evil: Revelations 2 +PCSF00728 Resident Evil: Revelations 2 +PCSA00008 Resistance: Burning Skies +PCSF00142 Resistance: Burning Skies™ +PCSA00103 RESOGUN +PCSF00262 RESOGUN™ +PCSE00075 Retro City Rampage +PCSE00546 Retro City Rampage DX +PCSE01322 Revenant Dogma +PCSE01065 Revenant Saga +PCSE01229 Reverie +PCSG00414 Rewrite +PCSG01043 Rewrite Harvest festa! +PCSE01251 Riddled Corpses EX +PCSE00001 Ridge Racer +PCSG00001 RIDGE RACER +PCSB00048 RIDGE RACER +PCSG90003 Ridge Racer 2011 E3 Interactive Demo +PCSE00548 Ring Run Circus +PCSG00257 RisingStar +PCSE00850 Risk of Rain +PCSG00287 Ro-Kyu-Bu! Naisho no Shutter Chance +PCSG00352 Robotics;Notes Elite +PCSH00165 Robotics;Notes Elite +PCSG90115 Robotics;Notes Elite Demo +PCSE00761 Rocketbirds 2: Evolution +PCSE00112 Rocketbirds HBC +PCSB00571 Rogue Legacy +PCSE00449 Rogue Legacy +PCSG00616 Rollers of the Realm +PCSH00308 Romance of the Three Kingdoms XIII: Fame and Strategy +PCSG00870 Romancing SaGa 2 +PCSE01094 Romancing SaGa 2 +PCSE01337 Romancing SaGa 3 +PCSE01055 Root Double -Before Crime After Days Xtend Edition +PCSG01238 Root Letter Last Answer +PCSG90224 Rosé and the Old Castle of Twilight +PCSE00699 Roundabout +PCSE00750 Royal Defense +PCSE00753 Royal Defense Invisible Threat +PCSG00229 Rozen Maiden -Wechseln sie welt ab- +PCSG00216 Rui wa Tomo o Yobu +PCSA00490 Run Sackboy! Run! +PCSF00562 Run Sackboy! Run! +PCSE01387 Rush Rover +PCSB01464 Russian Subway Dogs +PCSG00503 Ryū ga Gotoku 0 Free app for PlayStation®Vita +PCSG00275 Ryū ga Gotoku: Ishin! Free app for PlayStation®Vita +PCSG00732 Ryuuyoku no Melodia: Diva with the Blessed Dragonol +PCSG00640 SA7 - Silent Ability Seven - +PCSG00543 Saenai Heroine no Sodatekata: 〜blessing flowers〜 +PCSG00802 SaGa: Scarlet Grace +PCSG00906 Saka Agari Hurricane Portable +PCSG90088 Saka-Ban +PCSG00646 Saki Zenkoku Hen +PCSG00908 Saki: Zenkoku-hen Plus +PCSG01231 Sakura Sakura +PCSG00129 Sakura-Sou no Pet na Kanojo +PCSB01072 Salt and Sanctuary +PCSE01023 Salt and Sanctuary +PCSG00041 Samurai & Dragons +PCSE01113 SAMURAI SHODOWN V SPECIAL +PCSG00279 Samurai Warriors 4 +PCSE00503 Samurai Warriors 4 +PCSE00827 SAMURAI WARRIORS 4 Empires +PCSE00737 SAMURAI WARRIORS 4-Ⅱ +PCSE00714 Samurai Warriors: Chronicles 3 +PCSH00152 Samurai Warriors: Chronicles 3 +PCSG00211 San Goku Shi 12 Taisenban +PCSG00210 San Goku Shi 12 with Power-Up Kit +PCSG00949 San Goku Shi 13 with Power-Up Kit +PCSG00863 Sangoku Hime 4: Tenka Ryouran - Tenmei no Koi Emaki +PCSG00183 Sangoku Rensenki: Otome no Heihou! +PCSG00785 Sangoku Rensenki: Otome no Heihou! Omoide Gaeshi - CS Edition +PCSG01194 Sanzen Sekai Yuugi: Re Multi Universe Myself +PCSC00007 Sawari Makuru! +PCSG00554 Sayonara UmiharaKawase + +PCSB00782 Sayonara UmiharaKawase + +PCSG00745 Scared Rider Xechs Rev. +PCSG01036 Scarlet Fragments ~Omoiiro no Memories~ +PCSE01355 Scintillatron4096 +PCSE01505 ScourgeBringer +PCSE00642 Scram Kitty DX +PCSG00793 SD Gundam G Generation Genesis +PCSH00241 SD GUNDAM G GENERATION GENESIS +PCSH00242 SD GUNDAM G GENERATION GENESIS +PCSE01153 Secret of Mana +PCSB01163 Secret of Mana +PCSG00168 Sei Madou Monogatari +PCSG00460 Seiken Densetsu: Rise of Mana (聖剣伝説RISE of MANA) +PCSG01127 Sen no Hatou, Tsukisome no Kouki +PCSG01104 Sengo Muramasa DX: Guren no Kettou +PCSG00132 Sengoku Hime 3: Tenka o Kirisaku Hikari to Kage +PCSG00232 Sengoku Hime 4: Souha Hyakkei, Hana Mamoru Chikai +PCSG00466 Sengoku Hime 5: Senkatatsu Haoh no Keifu +PCSG01034 Sengoku Hime 7: Sen'un Tsuranuku Guren no Ishi +PCSG00233 Sengoku Musou 2 with Moushouden & Empires HD Version +PCSG00471 Sengoku Musou Chronicle 3 +PCSG00867 Sengoku Otome: Legend Battle +PCSG00428 Senjou no Waltz +PCSB00602 SENRAN KAGURA Bon Appetit! (Hanzo x Crimson Squad) +PCSB00882 SENRAN KAGURA ESTIVAL VERSUS +PCSB00601 SENRAN KAGURA SHINOVI VERSUS +PCSG00133 Senran Kagura: Shinovi Versus +PCSE01480 Sense - A Cyberpunk Ghost Story +PCSG01210 Seven Days: Anata to Sugosu Nanokakan +PCSE00589 Severed +PCSE01125 Shakedown Hawaii +PCSE00950 Shantae: Half-Genie Hero +PCSG90111 She (That Girl) Can't Leave Me Trial Version +PCSG01177 Shikihime no Niwa +PCSG00278 Shin Gundam Musou +PCSG00380 Shin Hayarigami +PCSG00897 Shin Hayarigami 2 +PCSG00010 Shin Kamaitachi no Yoru 11 Hitome no Suspect +PCSG00452 Shin Sangoku Musou 7 Empires +PCSH00052 Shin Sangoku Musou 7 with Moushouden +PCSG00893 Shin Sangoku Musou Eiketsuden +PCSG00764 Shin Sangoku Musou Online Z +PCSG01282 Shinigami to Shoujo +PCSG00255 ShinobiAshi +PCSE00015 Shinobido 2: Revenge of Zen +PCSG00019 Shinobido 2: Revenge of Zen +PCSH00001 Shinobido 2: Revenge of Zen +PCSB00049 Shinobido 2: Revenge of Zen +PCSG00580 Shinsou-ban Mahou-tsukai to Goshujin-sama +PCSE00845 Shiren the Wanderer: The Tower of Fortune and the Dice of Fate +PCSG00944 Shiro to Kuro no Alice +PCSG01192 Shiro to Kuro no Alice -Twilight line- +PCSG00846 Shirogane x Spirits! +PCSG00822 Shitsuji ga Aruji o Erabu Toki +PCSB00743 Shovel Knight +PCSE00640 Shovel Knight +PCSE00923 Shu +PCSE00705 Shütshimi +PCSG00588 Sid Meier's Civilization Revolution 2+ +PCSG01001 Side Kicks! +PCSE00011 Silent Hill: Book of Memories +PCSB00115 Silent Hill: Book of Memories +PCSG01259 Silverio Trinity: Beyond the Horizon +PCSG00329 Simple V Series Vol.2: The Tousou Highway Full Boost: Nagoya +PCSB00161 Sine Mora +PCSE00090 Sine Mora +PCSE01240 Sir Eatsalot +PCSE00773 Siralim +PCSB00588 Skeleton Rider +PCSG00583 Skullgirls 2nd Encore +PCSE00865 Sky Force Anniversary +PCSE01054 Skylight Freerange +PCSE00862 Skylight Freerange 2: Gachduine +PCSC80009 Skype +PCSG00048 Slotter Mania V: Black Lagoon +PCSF00338 Sly 1 & 2 +PCSA00098 Sly 3: Honor Among Thieves™ +PCSF00209 Sly Cooper: Thieves in Time +PCSF00269 Sly Raccoon™ +PCSF00216 Smart as +PCSG00787 Snow White in the Mirror Realm +PCSG01254 Soi Kano: Gyutto Dakishimete +PCSG01070 Song of Heiligenstadt +PCSE00056 Sonic & All-Stars Racing Transformed +PCSB00190 Sonic & All-Stars Racing Transformed™ +PCSE00221 Sonic & All-Stars Racing Transformed™ Demo +PCSE00314 Sorcery Saga: Curse of the Great Curry God +PCSG90074 Sorcery Saga: Curse of the Great Curry God +PCSG00296 Soukai Buccaneers! +PCSC00039 SOUL SACRIFICE +PCSC00049 SOUL SACRIFICE DELTA +PCSD00079 SOUL SACRIFICE DELTA™ +PCSA00152 Soul Sacrifice™ Delta +PCSF00532 Soul Sacrifice™ Delta +PCSA00003 Sound Shapes +PCSF00076 Sound Shapes™ +PCSG00993 Sousei no Onmyouji +PCSE00295 Sparkle +PCSE01089 Spellspire +PCSG00145 Spelunker Collection +PCSE00288 Spelunky +PCSB00359 Spelunky +PCSB00789 Spider: Rite of the Shrouded Moon +PCSE00577 SpongeBob HeroPants +PCSE00068 Spy Hunter +PCSG00128 Spy Hunter™ +PCSG00714 Star Ocean Second Evolution +PCSC00008 STAR STRIKE DELTA +PCSB00254 Star Wars Pinball +PCSE01235 Stardew Valley +PCSB01226 Stardew Valley +PCSE00029 StarDrone Extreme +PCSG00917 Starry☆Sky ~Autumn Stories~ +PCSG00510 Starry☆Sky ~Spring Stories~ +PCSG00916 Starry☆Sky ~Summer Stories~ +PCSG00918 Starry☆Sky ~Winter Stories~ +PCSE01277 STAY +PCSB01254 STAY +PCSG01237 STAY +PCSB00690 Stealth Inc 2: A Game of Clones +PCSE00575 Stealth Inc 2: A Game of Clones +PCSB00317 Stealth Inc: A Clone in the Dark +PCSE00280 Stealth Inc: A Clone in the Dark +PCSG01062 Steam Prison: Nanatsu no Bitoku +PCSE01391 Steam Tactics +PCSB00542 SteamWorld Dig +PCSE00430 SteamWorld Dig +PCSE01101 SteamWorld Dig 2 +PCSE00583 SteamWorld Heist +PCSB00693 SteamWorld Heist +PCSE00644 Steins;Gate +PCSG00147 STEINS;GATE +PCSE00949 Steins;Gate 0 +PCSB01012 STEINS;GATE 0 +PCSG00673 STEINS;GATE 0 +PCSG01166 STEINS;GATE ELITE +PCSG00250 Steins;Gate Senkei Kousoku no Phenogram +PCSG00146 Steins;Gate: My Darling's Embrace(比翼恋理のだーりん) +PCSE00290 Stick it to the Man +PCSE01098 Still Time +PCSG00736 STORM LOVER 2nd V +PCSG00735 STORM LOVER V +PCSB00908 Stranger of Sword City +PCSE00818 Stranger of Sword City +PCSG00878 Stranger of Sword City +PCSG00907 Strawberry Nauts +PCSE00005 STREET FIGHTER X TEKKEN +PCSB00144 STREET FIGHTER X TEKKEN +PCSE00688 Strike Solitaire +PCSE01514 SturmFront - The Mutant War +PCSH00006 Sudoku by Nikoli V +PCSG01250 Suki to Suki to de Sankaku Ren’ai +PCSG90008 Sumioni Trial Version +PCSE00062 SUMIONI:DEMON ARTS +PCSB01013 Summon Night 6: Lost borders +PCSG00827 Summon Night 6: Lost borders +PCSH00225 Summon Night 6: Lost borders +PCSE00951 Summon Night 6: Lost Borders +PCSE00047 SunFlowers +PCSE00784 Super Blackout +PCSE01433 Super Box Land Demake +PCSG01240 Super Destronaut DX: Intruders Edition +PCSE01460 Super Destronaut: Land Wars +PCSB00362 Super Exploding Zoo +PCSE00734 Super Exploding Zoo +PCSG00069 Super Hero Generation +PCSB01193 Super Hydorah +PCSB01152 Super Life of Pixel +PCSE01077 Super Life of Pixel +PCSE00942 Super Magical +PCSE00769 Super Meat Boy! +PCSE00017 Super Monkey Ball Banana Splitz +PCSG00032 Super Monkey Ball Banana Splitz +PCSB01100 Super Mutant Alien Assault +PCSE01072 Super Mutant Alien Assault +PCSG00260 Super Robot Taisen +PCSG01128 Super Robot Taisen X +PCSH10001 Super Robot Wars V +PCSH10089 Super Robot Wars X +PCSH10088 SUPER ROBOT WARS X +PCSG00495 Super Robot Wars3 Z Jigoku Hen +PCSB01271 Super Skull Smash Go! 2 Turbo +PCSE00802 Super Star Wars +PCSA00006 Super Stardust Delta +PCSF00019 Super Stardust™ Delta +PCSE00698 Super Time Force ULTRA +PCSE01374 Super Weekend Mode +PCSE01415 Super Wiloo Demake +PCSE00717 SUPERBEAT XONiC +PCSE00898 Superdimension Neptune vs Sega Hard Girls +PCSB00305 Superfrog HD +PCSG01207 SuperZangyura +PCSE00012 Supremacy MMA: Unrestricted +PCSG00948 Suran digit +PCSB00439 Surge Deluxe +PCSE00860 Swap Quest +PCSB00923 SwapQuest +PCSG01196 sweet pool +PCSB00507 Switch Galaxy Ultra +PCSE00493 Switch Galaxy Ultra +PCSE00465 Sword Art Online -Hollow Fragment- +PCSG00868 Sword Art Online : Hollow Realization +PCSB00618 Sword Art Online Hollow Fragment +PCSE00740 Sword Art Online Lost Song +PCSH00134 SWORD ART ONLINE Lost Song +PCSG00294 Sword Art Online: Hollow Fragment +PCSB00972 SWORD ART ONLINE: HOLLOW REALIZATION +PCSE00903 SWORD ART ONLINE: HOLLOW REALIZATION +PCSB00830 Sword Art Online: Lost Song +PCSE01484 Swordbreaker The Game +PCSE01508 Synergia +PCSE01451 Syrup and the Ultimate Sweet +PCSF00064 t@g +PCSF00062 Table Football +PCSA00064 Table Ice Hockey +PCSD00047 Table Ice Hockey™ +PCSC00028 Table Play Golf +PCSB00416 Table Top Racing +PCSB00912 Tachyon Project +PCSE00836 Tachyon Project +PCSE00771 Taco Master +PCSB00458 Tadeo Jones: The game +PCSG00945 Taiheiyou no Arashi: Koukoku no Kouhai Koko ni Ari, 1942 Senkan Yamato Hankou no Gouhou +PCSG00637 Taiheiyou no Arashi: Shijousaidai no Gekisen Normandy Koubousen +PCSG00551 Taiko no Tatsujin V (太鼓の達人 Vバージョン) +PCSG00726 Taishou Mebiusline: Vitable +PCSG00869 Taishou x Alice: All in One +PCSG01141 Taishou x Alice: Heads & Tails +PCSE00034 Tales From Space: Mutant Blobs Attack +PCSB00096 Tales from Space: Mutant Blobs Attack!!! +PCSE00429 Tales of Hearts R +PCSG00125 Tales of Hearts R +PCSB00550 TALES OF HEARTS R +PCSG00163 Tales of Hearts R: Infinite Evolve +PCSG00009 Tales Of Innocence R +PCSE01468 Task Force Kampas +PCSG01203 Tayutama2 -you're the only one- +PCSA00099 Tearaway™ +PCSF00476 Tearaway™ +PCSG00547 Teikoku Kaigun Koi Bojou: Meiji Yokosuka Koushinkyoku +PCSG01064 Teikoku Kaleido: Kakumei no Rondo +PCSG01180 Tengai ni Mau, Iki na Hana +PCSG00137 Tenshi Tsuki no Shoujo +PCSE00317 Terraria +PCSB00722 Teslagrad +PCSE00814 Teslagrad +PCSE01238 TETRA's Escape +PCSB00642 Tetris® Ultimate +PCSE00521 Tetris® Ultimate +PCSE00333 The Amazing Spider-Man +PCSB00428 The Amazing Spider-Man™ +PCSB00676 The Binding of Isaac: Rebirth +PCSE00507 The Binding of Isaac: Rebirth +PCSE00735 THE BIT.TRIP +PCSE01037 The Caligula Effect +PCSG00687 The Caligula Effect +PCSE01112 The Count Lucanor +PCSE01021 The Deer God +PCSE01344 The Demon Rush: Legends Corrupt +PCSE01241 The Dreamlands: Aisling's Quest +PCSG01095 The Fruit of Grisaia: Side Episode +PCSE01305 The House in Fata Morgana +PCSG00677 The IdolM@ster Must Songs - Aka-Ban +PCSG00678 The IdolM@ster Must Songs - Ao-Ban +PCSE00441 The Keeper of 4 Elements +PCSE01224 THE KING OF FIGHTERS '97 GLOBAL MATCH +PCSG00508 The Labyrinth of Grisaia -LE EDEN DE LA GRISAIA- +PCSH10113 The Legend of Heroes AO NO KISEKI Evolution +PCSH10111 The Legend of Heroes ZERO NO KISEKI Evolution +PCSG00490 The Legend of Heroes: Trails in the Sky the Third Evolution +PCSG00195 The Legend of Heroes: Trails of Cold Steel +PCSE00786 THE LEGEND OF HEROES: TRAILS OF COLD STEEL +PCSB00866 THE LEGEND OF HEROES: TRAILS OF COLD STEEL +PCSG00354 The Legend of Heroes: Trails of Cold Steel II +PCSE00896 THE LEGEND OF HEROES: TRAILS OF COLD STEEL II +PCSG00246 The Legend of Heroes: Trails to Azure Evolution +PCSG90069 The Legend of Heroes: Zero no Kiseki Evolution Free Version +PCSE00353 The Lego Movie Videogame +PCSE01162 The Long Reach +PCSE00993 The Longest Five Minutes +PCSE01179 The Lost Child +PCSF00558 The Muppets Movie Adventures +PCSG01163 The Princess Guide +PCSG01235 The Princess, the Stray Cat, and Matters of the Heart 2 +PCSE00775 The Quiet Collection +PCSE00631 The Sun and Moon +PCSB00489 The Swapper +PCSE01388 The Tower of Beatrice +PCSB01347 The Tower of Beatrice +PCSE00436 The Treasures of Montezuma 4 +PCSE00027 The Treasures of Montezuma Blitz +PCSA00158 The Unfinished Swan +PCSE00316 The Walking Dead +PCSB00411 The Walking Dead +PCSE00556 The Walking Dead Season 2 +PCSE00352 The Wolf Among Us +PCSE00258 Thomas Was Alone +PCSE00774 Three Fourths Home (Extended Edition) +PCSE01463 Thunder Paw +PCSE01416 Thy Sword +PCSB01396 Tic-Tac-Letters by POWGI +PCSE01430 Tic-Tac-Letters by POWGI +PCSH10212 Tic-Tac-Letters by POWGI +PCSG90164 Time Avengers Demo +PCSE01186 Time Recoil +PCSG00062 TIME TRAVELERS +PCSG00966 Timepiece Ensemble +PCSE01246 Timespinner +PCSB00552 Tiny Troopers Joint Ops +PCSE00388 Titan Attacks! +PCSE00597 Titan Souls +PCSG00575 To Heart 2: Dungeon Travelers +PCSG00330 To Love-Ru Trouble Darkness: Battle Ecstasy +PCSG00689 To Love-Ru Trouble Darkness: True Princess +PCSG01089 Toaru Majutsu no Virtual-On +PCSG01015 Tokeijikake no Ley Line: Kagerou ni Samayou Majo +PCSG00087 Tokushu Houdoubu +PCSG01103 Tokyo Clanpool +PCSG90298 Tokyo Clanpool Trial +PCSG00615 Tokyo Ghoul: Jail +PCSG00631 Tokyo Onmyouji: Tengen Jibashi - Rei no Baai - V Edition +PCSE01150 TOKYO TATTOO GIRLS +PCSB01161 TOKYO TATTOO GIRLS +PCSE00924 Tokyo Twilight Ghost Hunters Daybreak: Special Gigs +PCSG00634 Tokyo Twilight Ghost Hunters: Daybreak Special Gigs +PCSE00893 Tokyo Xanadu +PCSG00608 Tokyo Xanadu +PCSB01062 Tokyo Xanadu +PCSG01048 TOKYO YAMANOTE BOYS for V MAIN DISC +PCSG01049 Tokyo Yamanote Boys for V: Fan Disc +PCSG01135 Tonari ni Kanojo no Iru Shiawase: Two Farce +PCSG01201 Tonari ni Kanojo no Iru Shiawase: Winter Guest +PCSF00011 Top Darts +PCSB00791 Top Trumps Turbo +PCSG00902 Torikago no Marriage: Hatsukoi no Tsubasa +PCSA00112 Toro's Friend Network +PCSE00671 TorqueL +PCSB00355 Total Recoil +PCSG00113 Tottemo E Mahjong +PCSG00593 Touch Battle Sensha SP +PCSE00016 Touch My Katamari +PCSB00047 Touch My Katamari +PCSE01015 TOUHOU DOUBLE FOCUS +PCSG00977 Touhou Genso Maroku W: The Devil of Decline +PCSE00990 TOUHOU Genso Wanderer +PCSG00985 Touhou Genso Wanderer TOD -RELOADED- +PCSE01104 Touhou Kobuto V: Burst Battle +PCSG00999 Touhou Koubuto V: Burst Battle +PCSG00752 Touhou Soujinengi V +PCSE00940 Toukiden 2 +PCSG00834 Toukiden 2 co-op version +PCSG00379 Toukiden: Kiwami +PCSB00574 Toukiden: Kiwami +PCSE00467 Toukiden: Kiwami +PCSG00193 Toukiden: The Age of Demons +PCSE00381 Toukiden: The Age of Demons +PCSB00918 Towerfall Ascension +PCSG00488 Trails in the Sky FC Evolution +PCSG00489 Trails In the Sky SC Evolution +PCSA00060 Treasure Park +PCSC80006 Treasure Park +PCSB00422 Treasures of Montezuma Arena +PCSG00515 Trillion : God Of Destruction +PCSB00904 Trillion: God of Destruction +PCSE00813 Trillion: God of Destruction +PCSG01023 Tsuihou Senkyo +PCSG00648 Tsuki ni Yorisou Otome no Sahou: Hidamari no Hibi +PCSG00152 Tsukiei Academy -kou- +PCSG01025 Tsukitomo. Tsukiuta 12 Memories +PCSG01019 Tsumikui: Sen no Noroi, Sen no Inori for V +PCSE01452 Twin Breaker: A Sacred Symbols Adventure +PCSE01081 Twin Robots +PCSE00397 TxK +PCSE00837 Type:Rider +PCSC00080 U-NEXT +PCSG00480 Ukiyo no Roushi +PCSB00070 ULTIMATE MARVEL VS. CAPCOM 3 +PCSG00011 ULTIMATE MARVEL VS. CAPCOM 3 +PCSE00004 ULTIMATE MARVEL VS. CAPCOM 3 +PCSE01487 Ultracore +PCSE00414 Ultratron +PCSG00912 Un:BIRTHDAY SONG: Ai o Utau Shinigami - Another Record +PCSE00822 Uncanny Valley +PCSF00220 Uncharted: Fight for Fortune™ +PCSC00005 UNCHARTED: Golden Abyss +PCSF00001 Uncharted: Golden Abyss™ +PCSF00012 Uncharted: Golden Abyss™ +PCSA00029 Uncharted: Golden Abyss™ +PCSD00001 UNCHARTED: Golden Abyss™ +PCSA00088 Uncharted™ Fight for Fortune +PCSE01144 Under Night In-Birth Exe:Late(st) +PCSG00964 UNDER NIGHT IN-BIRTH Exe:Late[st] +PCSB01157 Undertale +PCSE01116 Undertale +PCSG01112 UNDERTALE +PCSE00840 Unepic +PCSB00841 Unepic +PCSF00034 Unit 13 +PCSA00014 Unit 13™ +PCSH10310 UnMetal +PCSG00633 Uppers +PCSB00038 Urban Trial Freestyle +PCSE00051 Urban Trial Freestyle +PCSG01191 Usotsuki Hime to Moumoku Ouji +PCSG01046 Usotsuki Shangri-La +PCSG00199 Uta Kumi 575 +PCSG00651 Uta no * Prince-Sama: Music 3 +PCSG00914 Uta no * Prince-Sama: Repeat LOVE +PCSG00617 Utawarerumono: Mask of Deception +PCSG00838 Utawarerumono: Mask of Truth (うたわれるもの 二人の白皇) +PCSE01409 Utawarerumono: Prelude to the Fallen +PCSG01011 Utsusemi no Meguri +PCSE00756 VA-11 HALL-A +PCSB01166 VA-11 HALL-A +PCSE01223 VA-11 HALL-A +PCSG01072 VA-11 HALL-A +PCSE00244 Valhalla Knights 3 +PCSG00307 Valhalla Knights 3 Gold +PCSE01003 Valkyria Revolution +PCSB01011 VALKYRIE DRIVE -BHIKKHUNI- +PCSE00948 VALKYRIE DRIVE -BHIKKHUNI- +PCSG00467 Vamwolf Cross† +PCSG01159 Variable Barricade +PCSE01314 VASARA Collection +PCSB01133 Vegas Party +PCSE00712 Velocibox +PCSB00302 Velocity Ultra +PCSE00038 Velocity Ultra +PCSB00410 Velocity®2X +PCSE00374 Velocity®2X +PCSG00531 VENUS PROJECT +PCSE00621 Vertical Drop Heroes HD +PCSB00031 Virtua Tennis 4 +PCSE00003 Virtua Tennis 4 +PCSB00205 Virtue's Last Reward +PCSE00506 Vitamin Z +PCSG01115 VitaminX Destination +PCSE00913 Volgarr the Viking +PCSE00760 Volume +PCSB00810 VVVVVV +PCSG01084 Wagamama High Spec (ワガママハイスペック) +PCSE01266 Waking Violet +PCSG00768 Walpurgis no Uta +PCSG00790 Wand of Fortune R +PCSG00938 Wand of Fortune R2 +PCSE00938 Wanderjahr TryAgainOrWalkAway +PCSE01248 War Theatre +PCSE01045 Warlock's Tower +PCSG01018 Warriors All-Stars +PCSG00209 Warriors Orochi 2 Ultimate +PCSB00873 WE ARE DOOMED +NPXS10007 Welcome Park +PCSC00047 What Did I Do to Deserve This, My Lord? +PCSB00727 Whispering Willows +PCSG00249 White Album 2: Shiawase no Mukougawa +PCSE01032 Windjammers +PCSG00194 Winning Post 7 2013 +PCSG00545 Winning Post 8 2015 +PCSG00804 Winning Post 8 2016 +PCSG01174 Winning Post 8 2018 +PCSF00007 WipEout® 2048 +PCSA00015 WipEout® 2048 +PCSD00005 WipEout® 2048 +PCSE01516 Witchcrafty +PCSE01445 Without Escape +PCSG00511 Wizardry: Torawareshi Bourei no Machi +PCSG00512 Wizardry: Torawareshi Tomashii no Meikyuu +PCSE01432 Wizards of Brandel +PCSE00519 Woah Dave! +PCSE01453 Word Maze by POWGI +PCSH10228 Word Maze by POWGI +PCSB01418 Word Maze by POWGI +PCSE01286 Word Search by POWGI +PCSH10166 Word Search by POWGI +PCSB01267 Word Search by POWGI +PCSH10168 Word Sudoku by POWGI +PCSE01339 Word Sudoku by POWGI +PCSB01307 Word Sudoku by POWGI +PCSH10179 Word Wheel by POWGI +PCSB01367 Word Wheel by POWGI +PCSE01394 Word Wheel by POWGI +PCSH10180 Wordsweeper by POWGI +PCSB01366 Wordsweeper by POWGI +PCSE01395 Wordsweeper by POWGI +PCSG01088 World Election +PCSG01114 World End Syndrome +PCSG00709 World of Final Fantasy +PCSE00880 WORLD OF FINAL FANTASY +PCSG00647 World Trigger Borderless Mission +PCSG00832 World Trigger: Smash Borders +PCSB00332 WORMS REVOLUTION EXTREME +PCSE00286 WORMS REVOLUTION EXTREME +PCSB00204 WRC 3: FIA World Rally Championship +PCSB00345 WRC 4 FIA WORLD RALLY CHAMPIONSHIP +PCSE00667 WRC 5 FIA World Rally Championship +PCSE01477 Wurroom +PCSE00346 XBLAZE CODE : EMBRYO +PCSG00463 XBLAZE LOST : MEMORIES +PCSG00589 XCOM: Enemy Unknown Plus +PCSE01481 Xeno Crisis +PCSE01191 Xenon Valkyrie+ +PCSE00897 Xenoraid +PCSE00694 Xeodrifter™ +PCSG00215 Yahari Game Demo Ore no Seishun Love-Kome wa Machigatteiru. +PCSG00895 Yahari Game Demo Ore no Seishun Love-Kome wa Machigatteiru. Zoku +PCSG00800 Yaken no Rodem +PCSH00147 Yakuza 0! Companion App +PCSG01080 Yomawari: Midnight Shadows +PCSB01144 YOMAWARI: MIDNIGHT SHADOWS +PCSG01120 Yoshiwara Higanbana Kuon no Chigiri +PCSG01267 your diary + +PCSC80010 YouTube +PCSE01033 Ys Origin +PCSH10049 Ys Origins +PCSE01103 Ys VIII -Lacrimosa of DANA- +PCSH00297 Ys VIII -Lacrimosa of DANA- +PCSG00105 Ys: Memories of Celceta +PCSH00181 Ys: Memories of Celceta +PCSG00567 YU-NO: Konoyo no Hate de Koi o Utau Shoujo +PCSE01462 Yumeutsutsu Re:After +PCSG01317 Yumeutsutsu Re:After +PCSG00393 Yumeutsutsu Re:After +PCSE01461 Yumeutsutsu Re:Master +PCSG00653 Yunohana SpRING! +PCSG00909 Yunohana SpRING! ~Cherising Time~ +PCSG00502 Yuuki Yuuna wa Yuusha de Aru: Jukai no Kioku +PCSG01075 Yuukyuu no Tierblade: Fragments of Memory +PCSG00808 Yuukyuu no Tierblade: Lost Chronicle +PCSG00693 Yuusha Shisu +PCSB00390 Z-Run +PCSG90316 Zanki Zero trial version +PCSG01113 Zanki Zero: Last Beginning +PCSB00094 Zen Pinball 2 +PCSE00050 Zen Pinball 2 +PCSG00883 Zero Escape: 9 Jikan 9 nin 9 no Tobira Zennin Shibo Dos Double Pack +PCSE01006 Zero Escape: The Nonary Games +PCSE00085 Zero Escape: Virtue's Last Reward +PCSE00781 Zero Escape: Zero Time Dilemma +PCSE01088 Zero Zero Zero Zero +PCSE01371 Zeroptian Invasion +PCSG00880 Zettai Kaikyuu Gakuen: Eden with Roses and Phantasm +PCSG00611 Zettai Meikyuu: Himitsu no Oyayubi Hime +PCSE00102 Zombie Tycoon 2 : Brainhov's Revenge diff --git a/projects/ArchR/packages/emulators/standalone/yabasanshiro-sa/config/config b/projects/ArchR/packages/emulators/standalone/yabasanshiro-sa/config/config new file mode 100644 index 0000000000..da873a3208 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/yabasanshiro-sa/config/config @@ -0,0 +1,7 @@ +{ + "Aspect rate": 1, + "Resolution": 3, + "Rotate screen": false, + "Rotate screen resolution": 0, + "Use compute shader": false +} diff --git a/projects/ArchR/packages/emulators/standalone/yabasanshiro-sa/config/devices/keymapv2_rg_arc_joypad.json b/projects/ArchR/packages/emulators/standalone/yabasanshiro-sa/config/devices/keymapv2_rg_arc_joypad.json new file mode 100644 index 0000000000..a449d90785 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/yabasanshiro-sa/config/devices/keymapv2_rg_arc_joypad.json @@ -0,0 +1,100 @@ +{ + "0_rg_arc_joypad_1900d632010000002c0a000000010000": { + "a": { + "id": 1, + "type": "button", + "value": 1 + }, + "analogleft": { + "id": 4, + "type": "axis", + "value": 0 + }, + "analogright": { + "id": 5, + "type": "axis", + "value": 0 + }, + "analogx": { + "id": 0, + "type": "axis", + "value": 0 + }, + "analogy": { + "id": 1, + "type": "axis", + "value": 0 + }, + "b": { + "id": 0, + "type": "button", + "value": 1 + }, + "c": { + "id": 2, + "type": "button", + "value": 1 + }, + "down": { + "id": 13, + "type": "button", + "value": 1 + }, + "l": { + "id": 6, + "type": "button", + "value": 1 + }, + "left": { + "id": 14, + "type": "button", + "value": 1 + }, + "r": { + "id": 7, + "type": "button", + "value": 1 + }, + "right": { + "id": 15, + "type": "button", + "value": 1 + }, + "select": { + "id": 10, + "type": "button", + "value": 1 + }, + "start": { + "id": 11, + "type": "button", + "value": 1 + }, + "up": { + "id": 12, + "type": "button", + "value": 1 + }, + "x": { + "id": 3, + "type": "button", + "value": 1 + }, + "y": { + "id": 4, + "type": "button", + "value": 1 + }, + "z": { + "id": 5, + "type": "button", + "value": 1 + } + }, + "player1": { + "DeviceID": 0, + "deviceGUID": "1900d632010000002c0a000000010000", + "deviceName": "rg_arc_joypad", + "padmode": 0 + } +} diff --git a/projects/ArchR/packages/emulators/standalone/yabasanshiro-sa/package.mk b/projects/ArchR/packages/emulators/standalone/yabasanshiro-sa/package.mk new file mode 100644 index 0000000000..09f6525de3 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/yabasanshiro-sa/package.mk @@ -0,0 +1,85 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2022-present 351ELEC +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="yabasanshiro-sa" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/sydarn/yabause" +PKG_URL="${PKG_SITE}.git" +PKG_VERSION="a40dace1ae0af3ebd45848549fdf396f40e3930f" +PKG_GIT_CLONE_BRANCH="pi4-update" +PKG_ARCH="aarch64" +PKG_DEPENDS_TARGET="toolchain SDL2 boost openal-soft zlib" +PKG_LONGDESC="Yabause is a Sega Saturn emulator and took over as Yaba Sanshiro" +PKG_TOOLCHAIN="cmake-make" +GET_HANDLER_SUPPORT="git" +PKG_BUILD_FLAGS="+speed" + +if [ ! "${OPENGL}" = "no" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL} glu libglvnd" +fi + +if [ "${OPENGLES_SUPPORT}" = yes ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" +fi + +if [ "${VULKAN_SUPPORT}" = "yes" ] +then + PKG_DEPENDS_TARGET+=" ${VULKAN}" +fi + +post_unpack() { + # use host versions + sed -i "s|COMMAND m68kmake|COMMAND ${PKG_BUILD}/m68kmake_host|" ${PKG_BUILD}/yabause/src/musashi/CMakeLists.txt + sed -i "s|COMMAND ./bin2c|COMMAND ${PKG_BUILD}/bin2c_host|" ${PKG_BUILD}/yabause/src/retro_arena/nanogui-sdl/CMakeLists.txt + find ${PKG_BUILD} -type f -name "CMakeLists.txt" -exec sed -i 's/^\s*cmake_minimum_required.*$/cmake_minimum_required(VERSION 3.5)/' {} + +} + +pre_make_target() { + # runs on host so make them manually if package is not crosscompile friendly + ${HOST_CC} ${PKG_BUILD}/yabause/src/retro_arena/nanogui-sdl/resources/bin2c.c -o ${PKG_BUILD}/bin2c_host + ${HOST_CC} ${PKG_BUILD}/yabause/src/musashi/m68kmake.c -o ${PKG_BUILD}/m68kmake_host +} + +pre_configure_target() { + PKG_CMAKE_OPTS_TARGET="${PKG_BUILD}/yabause " + + if [ ! "${OPENGL}" = "no" ]; then + PKG_CMAKE_OPTS_TARGET+=" -DUSE_EGL=ON -DUSE_OPENGL=ON" + fi + + if [ "${OPENGLES_SUPPORT}" = yes ]; then + PKG_CMAKE_OPTS_TARGET+=" -DUSE_EGL=ON -DUSE_OPENGL=OFF" + fi + + case ${ARCH} in + aarch64) + PKG_CMAKE_OPTS_TARGET+=" -DYAB_WANT_ARM7=ON \ + -DYAB_WANT_DYNAREC_DEVMIYAX=ON \ + -DYAB_PORTS=retro_arena" + + PKG_CMAKE_OPTS_TARGET+=" -DCMAKE_PROJECT_INCLUDE=${PKG_BUILD}/yabause/src/retro_arena/n2.cmake" + ;; + esac + + PKG_CMAKE_OPTS_TARGET+=" -DCMAKE_SYSTEM_PROCESSOR=x86_64" + + PKG_CMAKE_OPTS_TARGET+=" -DOPENGL_INCLUDE_DIR=${SYSROOT_PREFIX}/usr/include \ + -DOPENGL_opengl_LIBRARY=${SYSROOT_PREFIX}/usr/lib \ + -DOPENGL_glx_LIBRARY=${SYSROOT_PREFIX}/usr/lib \ + -DLIBPNG_LIB_DIR=${SYSROOT_PREFIX}/usr/lib \ + -Dpng_STATIC_LIBRARIES=${SYSROOT_PREFIX}/usr/lib/libpng16.so \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON" +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp -a ${PKG_BUILD}/src/retro_arena/yabasanshiro ${INSTALL}/usr/bin/yabasanshiro + cp -a ${PKG_DIR}/scripts/start_yabasanshiro.sh ${INSTALL}/usr/bin + chmod 0755 ${INSTALL}/usr/bin/start_yabasanshiro.sh + mkdir -p ${INSTALL}/usr/config/yabasanshiro + cp ${PKG_DIR}/config/config ${INSTALL}/usr/config/yabasanshiro/.config + cp -r ${PKG_DIR}/config/devices ${INSTALL}/usr/config/yabasanshiro/ +} diff --git a/projects/ArchR/packages/emulators/standalone/yabasanshiro-sa/patches/02-yabasanshiroSA-use-system-libpng.patch b/projects/ArchR/packages/emulators/standalone/yabasanshiro-sa/patches/02-yabasanshiroSA-use-system-libpng.patch new file mode 100644 index 0000000000..f0e83e2630 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/yabasanshiro-sa/patches/02-yabasanshiroSA-use-system-libpng.patch @@ -0,0 +1,11 @@ +--- a/yabause/src/retro_arena/CMakeLists.txt 2022-01-05 15:44:20.891135756 -0600 ++++ b/yabause/src/retro_arena/CMakeLists.txt 2022-01-05 15:44:41.738849860 -0600 +@@ -22,7 +22,7 @@ + add_subdirectory(nanogui-sdl) + + #include( ../glfw/external_zlib.cmake ) +-include( ${CMAKE_SOURCE_DIR}/CMake/Packages/external_libpng.cmake ) ++#include( ${CMAKE_SOURCE_DIR}/CMake/Packages/external_libpng.cmake ) + + #------------------------------------------------------------------------------ + # nlohmann/json diff --git a/projects/ArchR/packages/emulators/standalone/yabasanshiro-sa/patches/04-yabasanshiroSA-use-paths.patch b/projects/ArchR/packages/emulators/standalone/yabasanshiro-sa/patches/04-yabasanshiroSA-use-paths.patch new file mode 100644 index 0000000000..045abed6d4 --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/yabasanshiro-sa/patches/04-yabasanshiroSA-use-paths.patch @@ -0,0 +1,93 @@ +diff --git a/yabause/src/retro_arena/InputManager.cpp b/yabause/src/retro_arena/InputManager.cpp +index bd806736..c32af4a7 100644 +--- a/yabause/src/retro_arena/InputManager.cpp ++++ b/yabause/src/retro_arena/InputManager.cpp +@@ -213,7 +213,7 @@ int mapKeys( const json & configs ){ + + if( SDL_NumJoysticks() == 0 ){ + +- PADLOG("No joy stic is found force to keyboard\n"); ++ PADLOG("No joystick is found force to keyboard\n"); + padbits = PerPadAdd(&PORTDATA1); + if( configs.find("player1") == configs.end() ){ + return setDefalutSettings(padbits); +@@ -460,22 +460,22 @@ int getPlayerJsonFromInputConfig( int joy, InputConfig * inputconfig, json & pla + } + + Input result; +- inputconfig->getInputByName("a", &result); ++ inputconfig->getInputByName("y", &result); + player[guid]["a"] ={ { "type", input_types[result.type] },{ "id", result.id },{ "value", result.value } }; + + inputconfig->getInputByName("b", &result); + player[guid]["b"] = { { "type", input_types[result.type] },{ "id", result.id },{ "value", result.value } }; + +- inputconfig->getInputByName("rightshoulder", &result); ++ inputconfig->getInputByName("a", &result); + player[guid]["c"] = { { "type", input_types[result.type] },{ "id", result.id },{ "value", result.value } } ; + + inputconfig->getInputByName("x", &result); + player[guid]["x"] = { { "type", input_types[result.type] },{ "id", result.id },{ "value", result.value } }; + +- inputconfig->getInputByName("y", &result); ++ inputconfig->getInputByName("leftshoulder", &result); + player[guid]["y"] = { { "type", input_types[result.type] },{ "id", result.id },{ "value", result.value } }; + +- inputconfig->getInputByName("leftshoulder", &result); ++ inputconfig->getInputByName("rightshoulder", &result); + player[guid]["z"] = { { "type", input_types[result.type] },{ "id", result.id },{ "value", result.value } }; + + inputconfig->getInputByName("lefttrigger", &result); +@@ -1209,7 +1209,7 @@ void InputManager::writeDeviceConfig(InputConfig* config) + std::string InputManager::getConfigPath() + { + std::string path = getenv("HOME"); +- path += "/.emulationstation/es_temporaryinput.cfg"; ++ path = "/storage/.config/yabasanshiro/input.cfg"; + return path; + } + +diff --git a/yabause/src/retro_arena/Preference.cpp b/yabause/src/retro_arena/Preference.cpp +index 1108c843..49815002 100644 +--- a/yabause/src/retro_arena/Preference.cpp ++++ b/yabause/src/retro_arena/Preference.cpp +@@ -17,7 +17,7 @@ Preference::Preference( const std::string & filename ){ + } + + std::string home_dir = getenv("HOME"); +- home_dir += "/.yabasanshiro/"; ++ home_dir = "/storage/.config/yabasanshiro/"; + + this->filename = home_dir + input_trace_filename + ".config"; + +diff --git a/yabause/src/retro_arena/main.cpp b/yabause/src/retro_arena/main.cpp +index 3b3b581c..dacfee8e 100644 +--- a/yabause/src/retro_arena/main.cpp ++++ b/yabause/src/retro_arena/main.cpp +@@ -290,14 +290,14 @@ int main(int argc, char** argv) + + // Inisialize home directory + std::string home_dir = getenv("HOME"); +- home_dir += "/.yabasanshiro/"; ++ home_dir = "/storage/.config/yabasanshiro/"; + struct stat st = {0}; + if (stat(home_dir.c_str(), &st) == -1) { + mkdir(home_dir.c_str(), 0700); + } +- std::string bckup_dir = home_dir + "backup.bin"; ++ std::string bckup_dir = "/storage/roms/bios/yabasanshiro/backup.bin"; + strcpy( buppath, bckup_dir.c_str() ); +- strcpy( s_savepath, home_dir.c_str() ); ++ strcpy( s_savepath, "/storage/roms/savestates/saturn/yabasanshiro/" ); + g_keymap_filename = home_dir + "keymapv2.json"; + + std::string current_exec_name = argv[0]; // Name of the current exec program +@@ -601,7 +601,7 @@ int main(int argc, char** argv) + if( ret == 0 ){ + char pngname[256]; + snprintf(pngname,256,"%s/%s_%d.png", s_savepath, cdip->itemnum, e.user.code); +- fs::copy(tmpfilename, pngname, fs::copy_options::overwrite_existing ); ++ system((std::string("cp -f ") + tmpfilename + " " + pngname).c_str()); + } + hideMenuScreen(); + } diff --git a/projects/ArchR/packages/emulators/standalone/yabasanshiro-sa/patches/05-cmake-fixes.patch b/projects/ArchR/packages/emulators/standalone/yabasanshiro-sa/patches/05-cmake-fixes.patch new file mode 100644 index 0000000000..666fa1426f --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/yabasanshiro-sa/patches/05-cmake-fixes.patch @@ -0,0 +1,49 @@ +--- a/yabause/src/retro_arena/CMakeLists.txt ++++ b/yabause/src/retro_arena/CMakeLists.txt +@@ -1,4 +1,5 @@ + project(yabause-retro-arena) ++cmake_minimum_required(VERSION 3.5) + + add_definitions( -D__RETORO_ARENA__ ) + +@@ -62,7 +63,7 @@ + target_link_libraries(yabause-retro-arena yabause ${Boost_LIBRARIES} pugixml ${YABAUSE_LIBRARIES} ${PORT_LIBRARIES} nanogui stdc++fs ${LIBCHDR_LIBRARIES} ) + target_link_libraries( yabause-retro-arena ${LIBCHDR_LIBRARIES} ) + target_link_libraries( yabause-retro-arena ${zlib_STATIC_LIBRARIES} ) +-add_dependencies(yabause-retro-arena Json png zlib libchd ) ++add_dependencies(yabause-retro-arena Json zlib ) + yab_port_success(yabause-retro-arena) + set_target_properties(yabause-retro-arena PROPERTIES OUTPUT_NAME yabasanshiro) + +--- a/yabause/CMake/Packages/external_zlib.cmake ++++ b/yabause/CMake/Packages/external_zlib.cmake +@@ -69,6 +69,7 @@ + -DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=ON + -DCMAKE_BUILD_TYPE:STRING=Release + -DCMAKE_INSTALL_PREFIX:STRING=${ZLIB_INSTALL} ++ -DCMAKE_POLICY_VERSION_MINIMUM=3.5 + ${ADDITIONAL_CMAKE_ARGS} + ) + +--- a/yabause/CMake/Packages/external_libchdr.cmake ++++ b/yabause/CMake/Packages/external_libchdr.cmake +@@ -36,6 +36,7 @@ + -DCMAKE_BUILD_TYPE:STRING=Release + -DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS} + -DCMAKE_C_FLAGS=${CMAKE_C_FLAGS} ++ -DCMAKE_POLICY_VERSION_MINIMUM=3.5 + ${ADDITIONAL_CMAKE_ARGS} + ) + +--- a/yabause/src/retro_arena/CMakeLists.txt ++++ b/yabause/src/retro_arena/CMakeLists.txt +@@ -33,7 +33,8 @@ + ExternalProject_Add( + Json + PREFIX ${CMAKE_CURRENT_BINARY_DIR}/Json +- URL https://github.com/nlohmann/json/archive/v3.2.0.zip ++ GIT_REPOSITORY "https://github.com/nlohmann/json.git" ++ GIT_TAG "359f98d14065bf4e53eeb274f5987fd08f16e5bf" + #disable following + CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_DIR "" INSTALL_COMMAND "" + ) diff --git a/projects/ArchR/packages/emulators/standalone/yabasanshiro-sa/scripts/start_yabasanshiro.sh b/projects/ArchR/packages/emulators/standalone/yabasanshiro-sa/scripts/start_yabasanshiro.sh new file mode 100644 index 0000000000..193b477dfc --- /dev/null +++ b/projects/ArchR/packages/emulators/standalone/yabasanshiro-sa/scripts/start_yabasanshiro.sh @@ -0,0 +1,112 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Source predefined functions and variables +. /etc/profile +set_kill set "-9 yabasanshiro" + +ROM_DIR="/storage/roms/saturn/yabasanshiro" +CONFIG_DIR="/storage/.config/yabasanshiro" +SOURCE_DIR="/usr/config/yabasanshiro" +BIOS_BACKUP="/storage/roms/bios/yabasanshiro" +SAVESTATE_DIR="/storage/roms/savestates/saturn/yabasanshiro/" + +if [ ! -d "${ROM_DIR}" ] +then + mkdir -p "${ROM_DIR}" +fi + +if [ ! -d "${BIOS_BACKUP}" ] +then + mkdir -p "${BIOS_BACKUP}" +fi + +if [ ! -d "${CONFIG_DIR}" ] +then + mkdir -p "${CONFIG_DIR}" +fi + +if [ ! -d "${SAVESTATE_DIR}" ] +then + mkdir -p "${SAVESTATE_DIR}" +fi + +if [ ! -e "${CONFIG_DIR}/input.cfg" ] +then + rm -f ${CONFIG_DIR}/keymapv2.json + + # Handle inputplumber platforms first + if [[ "${HW_DEVICE}" =~ SM8550|SM8650 ]]; then + GAMEPAD="'InputPlumber GameController'" + else + # Check for js0, else fall back to joypad + if grep -q "js0" /proc/bus/input/devices; then + GAMEPAD="'$(grep -b4 js0 /proc/bus/input/devices | awk 'BEGIN {FS="\""}; /Name/ {printf $2}')'" + else + GAMEPAD="'$(grep -b4 joypad /proc/bus/input/devices | awk 'BEGIN {FS="\""}; /Name/ {printf $2}')'" + fi + fi + + GAMEPADCONFIG=$(xmlstarlet sel -t -c "//inputList/inputConfig[@deviceName=${GAMEPAD}]" -n /storage/.emulationstation/es_input.cfg) + + MAPPING_FILE="/usr/config/yabasanshiro/devices/keymapv2_$(eval echo $GAMEPAD).json" + if [ -e "${MAPPING_FILE}" ]; then + cp ${MAPPING_FILE} ${CONFIG_DIR}/keymapv2.json + fi + + if [ ! -z "${GAMEPADCONFIG}" ] + then + cat <${CONFIG_DIR}/input.cfg + + +${GAMEPADCONFIG} + +EOF + fi +fi + +BIOS="" +GAME=$(echo "${1}"| sed "s#^/.*/##") +PLATFORM=$(echo "${2}"| sed "s#^/.*/##") +USE_BIOS=$(get_setting use_hlebios "${PLATFORM}" "${GAME}") +if [ ! "${USE_BIOS}" = 1 ] +then + USE_BIOS=$(get_setting use_hlebios "${PLATFORM}") +fi + +if [ "$USE_BIOS" = 1 ] +then + for BIOS in saturn_bios.bin sega_101.bin mpr-17933.bin mpr-18811-mx.ic1 mpr-19367-mx.ic1 stvbios.zip + do + BIOS=$(find /storage/roms/bios -name ${BIOS} -print 2>/dev/null) + if [ ! -z "${BIOS}" ] + then + BIOS="-b ${BIOS}" + break + fi + done +fi + +if [ ! -e "${CONFIG_DIR}/${GAME}.config" ] +then + cp -f ${SOURCE_DIR}/.config "${CONFIG_DIR}/${GAME}.config" +fi + +#Set the cores to use +CORES=$(get_setting "cores" "${PLATFORM}" "${GAME}") +if [ "${CORES}" = "little" ] +then + EMUPERF="${SLOW_CORES}" +elif [ "${CORES}" = "big" ] +then + EMUPERF="${FAST_CORES}" +else + ### All.. + unset EMUPERF +fi + +echo "Command: yabasanshiro -r 2 -i "${1}" ${BIOS}" >>/var/log/exec.log 2>&1 +${EMUPERF} yabasanshiro -r 2 -i "${1}" ${BIOS} >>/var/log/exec.log 2>&1 ||: diff --git a/projects/ArchR/packages/fonts/dejavu/package.mk b/projects/ArchR/packages/fonts/dejavu/package.mk new file mode 100644 index 0000000000..8ad673df39 --- /dev/null +++ b/projects/ArchR/packages/fonts/dejavu/package.mk @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2025-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="dejavu" +PKG_VERSION="2.37" +PKG_LICENSE="Bitstream" +PKG_SITE="https://sourceforge.net/projects/dejavu/files/dejavu/${PKG_VERSION}" +PKG_URL="${PKG_SITE}/${PKG_NAME}-fonts-ttf-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="The DejaVu fonts are a font family based upon Bitstream Vera v1.10." +PKG_TOOLCHAIN="manual" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/share/fonts/truetype/dejavu/ + cp -rf ${PKG_BUILD}/ttf/DejaVuSansCondensed.ttf ${INSTALL}/usr/share/fonts/truetype/dejavu/ +} diff --git a/projects/ArchR/packages/fonts/spleen-font/package.mk b/projects/ArchR/packages/fonts/spleen-font/package.mk new file mode 100644 index 0000000000..e61fd604bd --- /dev/null +++ b/projects/ArchR/packages/fonts/spleen-font/package.mk @@ -0,0 +1,58 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="spleen-font" +PKG_VERSION="2.0.0" +PKG_LICENSE="BSD-2-Clause" +PKG_SITE="https://github.com/fcambus/spleen" +PKG_URL="${PKG_SITE}/releases/download/${PKG_VERSION}/spleen-${PKG_VERSION}.tar.gz" + +PKG_DEPENDS_INIT="toolchain bdf2psf:host" +PKG_DEPENDS_TARGET="toolchain bdf2psf:host" +PKG_LONGDESC="This package contains the Spleen 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_target() { + : +} + +make_init() { + for font in spleen-5x8 spleen-6x12 + do + ${TOOLCHAIN}/usr/bin/bdf2psf --fb \ + ${font}.bdf \ + ${TOOLCHAIN}/usr/share/bdf2psf/standard.equivalents \ + ${TOOLCHAIN}/usr/share/bdf2psf/ascii.set+${TOOLCHAIN}/usr/share/bdf2psf/linux.set+${TOOLCHAIN}/usr/share/bdf2psf/useful.set 512 \ + ${font}.psfu + done +} + +make_target() { + make_init +} + +makeinstall_init() { + mkdir -p ${INSTALL}/usr/share/consolefonts + cp -rf *.bdf ${INSTALL}/usr/share/consolefonts + cp -rf *.psfu ${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}/*.psfu ${INSTALL}/usr/share/consolefonts +} diff --git a/projects/ArchR/packages/fonts/spleen-font/patches/001-add-block.patch b/projects/ArchR/packages/fonts/spleen-font/patches/001-add-block.patch new file mode 100644 index 0000000000..9ec92a559c --- /dev/null +++ b/projects/ArchR/packages/fonts/spleen-font/patches/001-add-block.patch @@ -0,0 +1,59 @@ +diff -rupN spleen-2.0.0.orig/spleen-5x8.bdf spleen-2.0.0/spleen-5x8.bdf +--- spleen-2.0.0.orig/spleen-5x8.bdf 2023-10-17 11:29:44.898274937 +0000 ++++ spleen-2.0.0/spleen-5x8.bdf 2023-10-17 12:21:00.033250208 +0000 +@@ -37,7 +37,7 @@ COPYRIGHT "Copyright (c) 2018-2023, Fred + DEFAULT_CHAR 32 + _GBDFED_INFO "Edited with gbdfed 1.6." + ENDPROPERTIES +-CHARS 472 ++CHARS 473 + STARTCHAR SPACE + ENCODING 32 + SWIDTH 625 0 +@@ -7118,4 +7118,19 @@ BITMAP + 20 + 10 + ENDCHAR ++STARTCHAR FULL BLOCK ++ENCODING 9608 ++SWIDTH 625 0 ++DWIDTH 5 0 ++BBX 5 8 0 -1 ++BITMAP ++FF ++FF ++FF ++FF ++FF ++FF ++FF ++FF ++ENDCHAR + ENDFONT +diff -rupN spleen-2.0.0.orig/spleen-6x12.bdf spleen-2.0.0/spleen-6x12.bdf +--- spleen-2.0.0.orig/spleen-6x12.bdf 2023-10-17 11:29:44.898274937 +0000 ++++ spleen-2.0.0/spleen-6x12.bdf 2023-10-17 12:22:31.486063337 +0000 +@@ -9006,4 +9006,23 @@ BITMAP + 08 + 04 + ENDCHAR ++STARTCHAR FULL BLOCK ++ENCODING 9608 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 6 12 0 -3 ++BITMAP ++FF ++FF ++FF ++FF ++FF ++FF ++FF ++FF ++FF ++FF ++FF ++FF ++ENDCHAR + ENDFONT diff --git a/projects/ArchR/packages/graphics/SDL2/package.mk b/projects/ArchR/packages/graphics/SDL2/package.mk new file mode 100644 index 0000000000..bbc76487fc --- /dev/null +++ b/projects/ArchR/packages/graphics/SDL2/package.mk @@ -0,0 +1,154 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2018-present 5schatten (https://github.com/5schatten) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="SDL2" +PKG_VERSION="2.32.10" +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 pulseaudio libdrm SDL2:host" +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_BUILD_FLAGS="+speed" +PKG_DEPENDS_HOST="toolchain:host distutilscross:host libX11:host" + +if [ ! "${OPENGL_SUPPORT}" = "no" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL} glu" + PKG_CMAKE_OPTS_TARGET+=" -DSDL_OPENGL=ON \ + -DVIDEO_OPENGL=ON \ + -DVIDEO_KMSDRM=OFF" + if [ "${PREFER_GLES}" = "yes" ] && [ "${OPENGLES_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" SDL2_glesonly " + fi +else + PKG_CMAKE_OPTS_TARGET+=" -DSDL_OPENGL=OFF \ + -DVIDEO_OPENGL=OFF \ + -DVIDEO_KMSDRM=OFF" +fi + +if [ "${OPENGLES_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" + PKG_CMAKE_OPTS_TARGET+=" -DSDL_OPENGLES=ON \ + -DVIDEO_OPENGLES=ON \ + -DVIDEO_KMSDRM=ON" +else + PKG_CMAKE_OPTS_TARGET+=" -DSDL_OPENGLES=OFF \ + -DVIDEO_OPENGLES=OFF \ + -DVIDEO_KMSDRM=OFF" +fi + +if [ "${VULKAN_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${VULKAN}" + PKG_CMAKE_OPTS_TARGET+=" -DSDL_VULKAN=ON \ + -DVIDEO_OPENGL=OFF \ + -DVIDEO_VULKAN=ON" +else + PKG_CMAKE_OPTS_TARGET+=" -DSDL_VULKAN=OFF \ + -DVIDEO_VULKAN=OFF" +fi + +if [ "${DISPLAYSERVER}" = "wl" ] +then + PKG_DEPENDS_TARGET+=" wayland " + case ${ARCH} in + arm) + true + ;; + *) + PKG_DEPENDS_TARGET+=" ${WINDOWMANAGER}" + ;; + esac + PKG_CMAKE_OPTS_TARGET+=" -DSDL_WAYLAND=ON \ + -DVIDEO_WAYLAND=ON \ + -DVIDEO_WAYLAND_QT_TOUCH=ON \ + -DWAYLAND_SHARED=ON \ + -DVIDEO_X11=OFF \ + -DSDL_X11=OFF" +else + PKG_CMAKE_OPTS_TARGET+=" -DVIDEO_WAYLAND=OFF \ + -DVIDEO_WAYLAND_QT_TOUCH=ON \ + -DWAYLAND_SHARED=OFF \ + -DVIDEO_X11=OFF \ + -DSDL_X11=OFF" +fi + +case ${DEVICE} in + RK*) + PKG_DEPENDS_TARGET+=" librga" + PKG_PATCH_DIRS_TARGET+="${DEVICE}" + ;; +esac + +pre_configure_target(){ + + if [ -n "${PKG_PATCH_DIRS_TARGET}" ] + then + ### + ### Patching here is necessary to allow SDL2 to be built for + ### use by host builds without requiring additional unnecessary + ### packages to also be built (and break) during the build. + ### + ### It may be better served as a hook in scripts/build. + ### + + if [ -d "${PKG_DIR}/patches/${PKG_PATCH_DIRS_TARGET}" ] + then + cd $(get_build_dir SDL2) + for PATCH in ${PKG_DIR}/patches/${PKG_PATCH_DIRS_TARGET}/* + do + patch -p1 <${PATCH} + done + cd - + fi + + ### End + fi + + export LDFLAGS="${LDFLAGS} -ludev" + 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_X11=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=ON \ + -DSDL_HIDAPI_JOYSTICK=ON \ + -DPTHREADS=ON \ + -DPTHREADS_SEM=ON \ + -DDIRECTX=OFF \ + -DSDL_DLOPEN=ON \ + -DCLOCK_GETTIME=OFF \ + -DSDL_RPATH=OFF \ + -DRENDER_D3D=OFF \ + -DPIPEWIRE=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/projects/ArchR/packages/graphics/SDL2/patches/0006-drm-resolution.patch b/projects/ArchR/packages/graphics/SDL2/patches/0006-drm-resolution.patch new file mode 100644 index 0000000000..f6243af65e --- /dev/null +++ b/projects/ArchR/packages/graphics/SDL2/patches/0006-drm-resolution.patch @@ -0,0 +1,70 @@ +From 2b837f662b12330e2d5afa867f1b6c1476b93102 Mon Sep 17 00:00:00 2001 +From: JohnnyonFlame +Date: Tue, 8 Aug 2023 04:01:53 -0300 +Subject: [PATCH 6/7] drm resolution + +--- + src/video/kmsdrm/SDL_kmsdrmvideo.c | 39 +++++++++++++++++++++++++++++- + 1 file changed, 38 insertions(+), 1 deletion(-) + +diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c +index 663c4707c..39eff8c1d 100644 +--- a/src/video/kmsdrm/SDL_kmsdrmvideo.c ++++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c +@@ -842,6 +842,24 @@ static void KMSDRM_AddDisplay(_THIS, drmModeConnector *connector, drmModeRes *re + goto cleanup; + } + ++ // 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 = KMSDRM_drmModeGetCrtc(viddata->drm_fd, encoder->crtc_id); ++ if(pcrtc != NULL) { ++ KMSDRM_drmModeSetCrtc(viddata->drm_fd, pcrtc->crtc_id, pcrtc->buffer_id, 0, 0, &connector->connector_id, 1, &connector->modes[drmMode]); ++ } ++ } ++ } ++ fclose(fdDrmMode); ++ } ++ } ++ // ++ + /* Try to find a CRTC connected to this encoder */ + crtc = KMSDRM_drmModeGetCrtc(viddata->drm_fd, encoder->crtc_id); + +@@ -1383,8 +1401,27 @@ void KMSDRM_GetDisplayModes(_THIS, SDL_VideoDisplay *display) + SDL_DisplayMode mode; + int i; + ++ // batocera ++ int wantedMode = 0; ++ { ++ FILE* fdDrmMode; ++ int drmMode; ++ if((fdDrmMode = fopen("/var/run/drmMode", "r")) != NULL) { ++ if(fscanf(fdDrmMode, "%i", &drmMode) == 1) { ++ if(drmMode>=0 && drmModecount_modes) { ++ wantedMode = drmMode; ++ } ++ } ++ fclose(fdDrmMode); ++ } ++ } ++ // ++ + for (i = 0; i < conn->count_modes; i++) { +- SDL_DisplayModeData *modedata = SDL_calloc(1, sizeof(SDL_DisplayModeData)); ++ SDL_DisplayModeData *modedata; ++ if(i != wantedMode) continue; // batocera ++ ++ modedata = SDL_calloc(1, sizeof(SDL_DisplayModeData)); + + if (modedata) { + modedata->mode_index = i; +-- +2.20.1 + diff --git a/projects/ArchR/packages/graphics/SDL2/patches/0007-Support-building-without-hacky-libmali-headers.patch b/projects/ArchR/packages/graphics/SDL2/patches/0007-Support-building-without-hacky-libmali-headers.patch new file mode 100644 index 0000000000..239a3db4aa --- /dev/null +++ b/projects/ArchR/packages/graphics/SDL2/patches/0007-Support-building-without-hacky-libmali-headers.patch @@ -0,0 +1,30 @@ +From 35a4dd0e48a82d90157e92c49dc87202a31d4c1c Mon Sep 17 00:00:00 2001 +From: JohnnyonFlame +Date: Tue, 8 Aug 2023 23:40:52 -0300 +Subject: [PATCH 7/7] Support building without hacky libmali headers. + +--- + src/video/kmsdrm/SDL_kmsdrmmouse.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/src/video/kmsdrm/SDL_kmsdrmmouse.c b/src/video/kmsdrm/SDL_kmsdrmmouse.c +index 5dcaaaab6..fe17964a9 100644 +--- a/src/video/kmsdrm/SDL_kmsdrmmouse.c ++++ b/src/video/kmsdrm/SDL_kmsdrmmouse.c +@@ -109,6 +109,13 @@ void KMSDRM_CreateCursorBO(SDL_VideoDisplay *display) + dispdata->cursor_w, dispdata->cursor_h, + GBM_FORMAT_ARGB8888, GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE | GBM_BO_USE_LINEAR); + ++ // GBM_BO_USE_LINEAR not supported on mali... retry when this fails. ++ if (!dispdata->cursor_bo) { ++ dispdata->cursor_bo = KMSDRM_gbm_bo_create(viddata->gbm_dev, ++ dispdata->cursor_w, dispdata->cursor_h, ++ GBM_FORMAT_ARGB8888, GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE); ++ } ++ + if (!dispdata->cursor_bo) { + SDL_SetError("Could not create GBM cursor BO"); + return; +-- +2.20.1 + diff --git a/projects/ArchR/packages/graphics/SDL2/patches/0008-shutdown-audio-streams-immediately.patch b/projects/ArchR/packages/graphics/SDL2/patches/0008-shutdown-audio-streams-immediately.patch new file mode 100644 index 0000000000..a00e338beb --- /dev/null +++ b/projects/ArchR/packages/graphics/SDL2/patches/0008-shutdown-audio-streams-immediately.patch @@ -0,0 +1,36 @@ +diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c +index 96586fe..2996b37 100644 +--- a/src/audio/SDL_audio.c ++++ b/src/audio/SDL_audio.c +@@ -791,7 +791,7 @@ static int SDLCALL SDL_RunAudio(void *userdata) + } + + /* Wait for the audio to drain. */ +- SDL_Delay(((device->spec.samples * 1000) / device->spec.freq) * 2); ++// SDL_Delay(((device->spec.samples * 1000) / device->spec.freq) * 2); + + current_audio.impl.ThreadDeinit(device); + +diff --git a/src/audio/alsa/SDL_alsa_audio.c b/src/audio/alsa/SDL_alsa_audio.c +index 3ed66f2..b57fe66 100644 +--- a/src/audio/alsa/SDL_alsa_audio.c ++++ b/src/audio/alsa/SDL_alsa_audio.c +@@ -454,12 +454,12 @@ static void ALSA_FlushCapture(_THIS) + static void ALSA_CloseDevice(_THIS) + { + if (this->hidden->pcm_handle) { +- /* Wait for the submitted audio to drain +- ALSA_snd_pcm_drop() can hang, so don't use that. +- */ +- Uint32 delay = ((this->spec.samples * 1000) / this->spec.freq) * 2; +- SDL_Delay(delay); +- ++// /* Wait for the submitted audio to drain ++// ALSA_snd_pcm_drop() can hang, so don't use that. ++// */ ++// Uint32 delay = ((this->spec.samples * 1000) / this->spec.freq) * 2; ++// SDL_Delay(delay); ++// + ALSA_snd_pcm_close(this->hidden->pcm_handle); + } + SDL_free(this->hidden->mixbuf); diff --git a/projects/ArchR/packages/graphics/SDL2/patches/0009-fix-snd-pcm-build.patch b/projects/ArchR/packages/graphics/SDL2/patches/0009-fix-snd-pcm-build.patch new file mode 100644 index 0000000000..f33055976a --- /dev/null +++ b/projects/ArchR/packages/graphics/SDL2/patches/0009-fix-snd-pcm-build.patch @@ -0,0 +1,12 @@ +diff -rupbN SDL2.orig/src/audio/alsa/SDL_alsa_audio.c SDL2/src/audio/alsa/SDL_alsa_audio.c +--- SDL2.orig/src/audio/alsa/SDL_alsa_audio.c 2025-09-03 13:22:21.517704691 +0000 ++++ SDL2/src/audio/alsa/SDL_alsa_audio.c 2025-09-03 13:23:53.115252598 +0000 +@@ -88,7 +88,7 @@ static const char *(*ALSA_snd_pcm_info_g + static int (*ALSA_snd_pcm_info_get_card)(const snd_pcm_info_t *); + static int (*ALSA_snd_card_get_name)(int, char **); + static int (*ALSA_snd_pcm_info_malloc)(snd_pcm_info_t **); +-static int (*ALSA_snd_pcm_info_free)(snd_pcm_info_t *); ++static void (*ALSA_snd_pcm_info_free)(snd_pcm_info_t *); + #ifdef SND_CHMAP_API_VERSION + static snd_pcm_chmap_t *(*ALSA_snd_pcm_get_chmap)(snd_pcm_t *); + static int (*ALSA_snd_pcm_chmap_print)(const snd_pcm_chmap_t *map, size_t maxlen, char *buf); diff --git a/projects/ArchR/packages/graphics/SDL2_glesonly/package.mk b/projects/ArchR/packages/graphics/SDL2_glesonly/package.mk new file mode 100644 index 0000000000..e4b9395d9a --- /dev/null +++ b/projects/ArchR/packages/graphics/SDL2_glesonly/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +# Inherit nearly everything +OPENGL_SUPPORT=no +. $(get_pkg_directory SDL2)/package.mk + +PKG_NAME="SDL2_glesonly" +PKG_DEPENDS_UNPACK+=" SDL2" + +makeinstall_target() { + mkdir -p "${INSTALL}/usr/lib/glesonly" + cp -a libSDL2-2.0.so.0.* "${INSTALL}/usr/lib/glesonly/" +} + +post_makeinstall_target() { + : +} diff --git a/projects/ArchR/packages/graphics/SDL2_glesonly/patches b/projects/ArchR/packages/graphics/SDL2_glesonly/patches new file mode 120000 index 0000000000..f42cfa14ca --- /dev/null +++ b/projects/ArchR/packages/graphics/SDL2_glesonly/patches @@ -0,0 +1 @@ +../SDL2/patches/ \ No newline at end of file diff --git a/projects/ArchR/packages/graphics/cairo/package.mk b/projects/ArchR/packages/graphics/cairo/package.mk new file mode 100644 index 0000000000..32f4462de0 --- /dev/null +++ b/projects/ArchR/packages/graphics/cairo/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="cairo" +PKG_VERSION="1.17.8" +PKG_SHA256="5b10c8892d1b58d70d3f0ba5b47863a061262fa56b9dc7944161f8c8b783bc64" +PKG_LICENSE="LGPL" +PKG_SITE="https://cairographics.org/" +PKG_URL="https://cairographics.org/snapshots/${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." + +configure_package() { + if [ "${OPENGL}" != "no" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL}" + fi + + if [ "${OPENGLES}" != "no" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" + fi + + case ${DISPLAYSERVER} in + "x11"|"wl") + PKG_DEPENDS_TARGET+=" libxcb libXrender libX11 mesa" + ;; + esac + +} + +pre_configure_target() { + PKG_MESON_OPTS_TARGET="-Ddwrite=disabled \ + -Dfontconfig=enabled \ + -Dfreetype=enabled \ + -Dpng=enabled \ + -Dquartz=disabled \ + -Dtee=disabled \ + -Dtests=disabled \ + -Dxml=disabled \ + -Dzlib=enabled \ + -Dgtk2-utils=disabled \ + -Dglib=enabled \ + -Dspectre=disabled \ + -Dsymbol-lookup=disabled \ + -Dgtk_doc=false" + + case ${DISPLAYSERVER} in + "x11"|"wl") + PKG_MESON_OPTS_TARGET+=" -Dxlib=enabled \ + -Dxcb=enabled \ + -Dxlib-xcb=enabled" + ;; + *) + PKG_MESON_OPTS_TARGET+=" -Dxlib=disabled \ + -Dxcb=disabled \ + -Dxlib-xcb=disabled" + ;; + esac + sed -i "s~'ipc_rmid_deferred_release', 'auto'~'ipc_rmid_deferred_release', 'true'~g" ${PKG_BUILD}/meson.build +} diff --git a/projects/ArchR/packages/graphics/capsimg/package.mk b/projects/ArchR/packages/graphics/capsimg/package.mk new file mode 100644 index 0000000000..dadd7e4806 --- /dev/null +++ b/projects/ArchR/packages/graphics/capsimg/package.mk @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Frank Hartung (supervisedthinking (@) gmail.com) + +PKG_NAME="capsimg" +PKG_VERSION="ed4cb0912fb1a2a0d5203111c6f6abd50d411b56" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/FrodeSolheim/capsimg" +PKG_URL="${PKG_SITE}.git" +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/include/caps5 + cp -v LibIPF/* ${INSTALL}/usr/include/caps5 +} diff --git a/projects/ArchR/packages/graphics/fbgrab/package.mk b/projects/ArchR/packages/graphics/fbgrab/package.mk new file mode 100644 index 0000000000..41c86cd40c --- /dev/null +++ b/projects/ArchR/packages/graphics/fbgrab/package.mk @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="fbgrab" +PKG_VERSION="5c2481d2b67b634e4e611610c33d30ef796afe5d" +PKG_LICENSE="GPL2.0" +PKG_SITE="https://github.com/GunnarMonell/fbgrab" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A utility to grab/screenshot the framebuffer." +GET_HANDLER_SUPPORT="git" diff --git a/projects/ArchR/packages/graphics/gdk-pixbuf/config/loaders.cache b/projects/ArchR/packages/graphics/gdk-pixbuf/config/loaders.cache new file mode 100644 index 0000000000..129bdba2ce --- /dev/null +++ b/projects/ArchR/packages/graphics/gdk-pixbuf/config/loaders.cache @@ -0,0 +1,107 @@ +# GdkPixbuf Image Loader Modules file +# Automatically generated file, do not edit +# Created by gdk-pixbuf-query-loaders from gdk-pixbuf-2.42.4 +# +# LoaderDir = /usr/lib/gdk-pixbuf-2.0/2.10.0/loaders +# +"/usr/lib/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-ani.so" +"ani" 4 "gdk-pixbuf" "Windows animated cursor" "LGPL" +"application/x-navi-animation" "" +"ani" "" +"RIFF ACON" " xxxx " 100 + +"/usr/lib/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-bmp.so" +"bmp" 5 "gdk-pixbuf" "BMP" "LGPL" +"image/bmp" "image/x-bmp" "image/x-MS-bmp" "" +"bmp" "" +"BM" "" 100 + +"/usr/lib/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-gif.so" +"gif" 4 "gdk-pixbuf" "GIF" "LGPL" +"image/gif" "" +"gif" "" +"GIF8" "" 100 + +"/usr/lib/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-icns.so" +"icns" 4 "gdk-pixbuf" "MacOS X icon" "GPL" +"image/x-icns" "" +"icns" "" +"icns" "" 100 + +"/usr/lib/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-ico.so" +"ico" 5 "gdk-pixbuf" "Windows icon" "LGPL" +"image/x-icon" "image/x-ico" "image/x-win-bitmap" "image/vnd.microsoft.icon" "application/ico" "image/ico" "image/icon" "text/ico" "" +"ico" "cur" "" +" \001 " "zz znz" 100 +" \002 " "zz znz" 100 + +"/usr/lib/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-jpeg.so" +"jpeg" 5 "gdk-pixbuf" "JPEG" "LGPL" +"image/jpeg" "" +"jpeg" "jpe" "jpg" "" +"\377\330" "" 100 + +"/usr/lib/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-png.so" +"png" 5 "gdk-pixbuf" "PNG" "LGPL" +"image/png" "" +"png" "" +"\211PNG\r\n\032\n" "" 100 + +"/usr/lib/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-pnm.so" +"pnm" 4 "gdk-pixbuf" "PNM/PBM/PGM/PPM" "LGPL" +"image/x-portable-anymap" "image/x-portable-bitmap" "image/x-portable-graymap" "image/x-portable-pixmap" "" +"pnm" "pbm" "pgm" "ppm" "" +"P1" "" 100 +"P2" "" 100 +"P3" "" 100 +"P4" "" 100 +"P5" "" 100 +"P6" "" 100 + +"/usr/lib/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-qtif.so" +"qtif" 4 "gdk-pixbuf" "QuickTime" "LGPL" +"image/x-quicktime" "image/qtif" "" +"qtif" "qif" "" +"abcdidsc" "xxxx " 100 +"abcdidat" "xxxx " 100 + +"/usr/lib/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-svg.so" +"svg" 6 "gdk-pixbuf" "Scalable Vector Graphics" "LGPL" +"image/svg+xml" "image/svg" "image/svg-xml" "image/vnd.adobe.svg+xml" "text/xml-svg" "image/svg+xml-compressed" "" +"svg" "svgz" "svg.gz" "" +" /dev/null + modprobe mali_kbase + + # Bind-mount mali GLES libraries over mesa if not already done. + # Use mount output (not /proc/mounts) to avoid squashfs false positives. + mount | grep -q "on /usr/lib/libEGL.so" || find /usr/{lib,lib32}/mali -type f -exec bash -c 'lib={}; mount --bind $lib ${lib/\/mali\//\/}' ';' + # Portmaster is not ready for SDL in glesonly subdir, so override libs the dirty way + if [ -d /usr/lib/glesonly ]; then + mount | grep -q "on /usr/lib/libSDL2" || find /usr/{lib,lib32}/glesonly -type f -exec bash -c 'lib={}; mount --bind $lib ${lib/\/glesonly\//\/}' ';' + fi + mount --bind /dev/null /usr/lib/libGL.so + mount --bind /dev/null /usr/lib32/libGL.so + + # Mask panfrost Vulkan ICD so the loader only finds mali + for icd in /usr/share/vulkan/icd.d/panfrost_icd.*.json; do + [ -f "${icd}" ] && mount --bind /dev/null "${icd}" + done + ;; + "panfrost") + modprobe -r mali_kbase 2>/dev/null + modprobe @PAN@ + + mount | grep -q "on /usr/lib/libEGL.so" && find /usr/lib/mali -type f -exec bash -c 'lib={}; umount ${lib/\/mali\//\/}' ';' + if [ -d /usr/lib/glesonly ]; then + mount | grep -q "on /usr/lib/libSDL2" && find /usr/lib/glesonly -type f -exec bash -c 'lib={}; umount ${lib/\/glesonly\//\/}' ';' + fi + + # Mask mali Vulkan ICD so the loader only finds panfrost + [ -f /usr/share/vulkan/icd.d/mali.json ] && \ + mount --bind /dev/null /usr/share/vulkan/icd.d/mali.json + ;; + *) + exit 3 + ;; + esac +} + + +case "$1" in + "--options") + echo "panfrost libmali" + ;; + "--start") + get_current_driver + load_driver ${CONFDRIVER} + # If the requested driver didn't actually bind, fall back to the + # other one so the user gets a graphical system either way. Mali-G31 + # on RK3326 is normally driven by libmali; if mali_kbase decides the + # regulator/clock state is bad it silently fails to bind, leaving a + # composited system with software rasterization that crawls. Try the + # alternate driver instead of letting the user think their device is + # just slow. + if ! gpu_is_bound; then + ALT="libmali" + [ "${CONFDRIVER}" = "libmali" ] && ALT="panfrost" + logger -t gpudriver "${CONFDRIVER} did not bind to GPU; trying ${ALT}" + load_driver "${ALT}" 2>/dev/null + fi + ;; + "libmali") + set_setting ${GPU_DRIVER_SETTING_KEY} $1 + @DTB_OVERLAY_UNLOAD@ + ;; + "panfrost") + set_setting ${GPU_DRIVER_SETTING_KEY} $1 + @DTB_OVERLAY_LOAD@ + ;; + "") + get_current_driver + echo ${CONFDRIVER} + ;; + *) + echo "Unexpected parameter $1" >&2 + echo "Usage:" >&2 + echo " List available drivers: $0 --options" >&2 + echo " Load configured driver and set libs: $0 --start" >&2 + echo " Get current driver: $0" >&2 + echo " Configure driver to load on next boot: $0 " >&2 + exit 1 + ;; +esac diff --git a/projects/ArchR/packages/graphics/grim/package.mk b/projects/ArchR/packages/graphics/grim/package.mk new file mode 100644 index 0000000000..99546f7bc2 --- /dev/null +++ b/projects/ArchR/packages/graphics/grim/package.mk @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="grim" +PKG_VERSION="1.4.1" +PKG_LICENSE="MIT" +PKG_SITE="https://wayland.emersion.fr/grim/" +PKG_URL="https://git.sr.ht/~emersion/grim/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain wayland pixman libpng" +PKG_LONGDESC="Grab images from a Wayland compositor" diff --git a/projects/ArchR/packages/graphics/grim/patches/001-fix-warning.patch b/projects/ArchR/packages/graphics/grim/patches/001-fix-warning.patch new file mode 100644 index 0000000000..a59a0881fd --- /dev/null +++ b/projects/ArchR/packages/graphics/grim/patches/001-fix-warning.patch @@ -0,0 +1,14 @@ +--- grim-1.4.1/write_ppm.c.orig 2024-12-20 20:21:19.335943763 +0000 ++++ grim-1.4.1/write_ppm.c 2024-12-20 20:25:18.726959907 +0000 +@@ -30,7 +30,10 @@ + buffer += header_len; + + pixman_format_code_t format = pixman_image_get_format(image); +- assert(format == PIXMAN_a8r8g8b8 || format == PIXMAN_x8r8g8b8); ++ if ((format != PIXMAN_a8r8g8b8) && (format != PIXMAN_x8r8g8b8)) { ++ fprintf(stderr, "Unsupported format %x\n", format); ++ return -1; ++ } + + // Both formats are native-endian 32-bit ints + uint32_t *pixels = pixman_image_get_data(image); diff --git a/projects/ArchR/packages/graphics/gtk2/files/settings.ini b/projects/ArchR/packages/graphics/gtk2/files/settings.ini new file mode 100644 index 0000000000..c6bdb7fa46 --- /dev/null +++ b/projects/ArchR/packages/graphics/gtk2/files/settings.ini @@ -0,0 +1,4 @@ +[Settings] +gtk-icon-theme-name = Adwaita +gtk-theme-name = Adwaita +gtk-font-name = Liberation Sans 12 diff --git a/projects/ArchR/packages/graphics/gtk2/package.mk b/projects/ArchR/packages/graphics/gtk2/package.mk new file mode 100644 index 0000000000..76e810fb83 --- /dev/null +++ b/projects/ArchR/packages/graphics/gtk2/package.mk @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2017 Escalade +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="gtk2" +PKG_VERSION="2.24.33" +PKG_LICENSE="LGPL" +PKG_SITE="http://www.gtk.org/" +PKG_URL="https://ftp.gnome.org/pub/gnome/sources/gtk+/${PKG_VERSION:0:4}/gtk+-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain at-spi2-atk atk cairo gdk-pixbuf glib libX11 libXi libXrandr libepoxy pango libxkbcommon wayland wayland-protocols libepoxy libpng tiff libjpeg-turbo libffi glew" +PKG_DEPENDS_CONFIG="libXft pango gdk-pixbuf shared-mime-info" +PKG_LONGDESC="A library for creating graphical user interfaces for the X Window System." +PKG_BUILD_FLAGS="-sysroot" + +PKG_CONFIGURE_OPTS_TARGET="--with-x \ + --enable-introspection=no \ + --disable-cups \ + --disable-glibtest \ + --enable-xinerama=no \ + --disable-maintainer-mode " + +pre_configure_target() { + # ${TOOLCHAIN}/bin/glib-compile-resources requires ${TOOLCHAIN}/lib/libffi.so.6 + export LD_LIBRARY_PATH="${TOOLCHAIN}/lib:${LD_LIBRARY_PATH}" + export GLIB_COMPILE_RESOURCES=glib-compile-resources GLIB_MKENUMS=glib-mkenums GLIB_GENMARSHAL=glib-genmarshal +} + diff --git a/projects/ArchR/packages/graphics/gtk2/patches/001-no-demos.patch b/projects/ArchR/packages/graphics/gtk2/patches/001-no-demos.patch new file mode 100644 index 0000000000..0121b86bd8 --- /dev/null +++ b/projects/ArchR/packages/graphics/gtk2/patches/001-no-demos.patch @@ -0,0 +1,35 @@ +--- a/Makefile.am.orig 2024-04-28 12:51:38.866216202 +0300 ++++ b/Makefile.am 2024-04-28 12:51:54.426096874 +0300 +@@ -1,7 +1,7 @@ + ## Makefile.am for GTK+ + include $(top_srcdir)/Makefile.decl + +-SRC_SUBDIRS = gdk gtk modules demos tests perf ++SRC_SUBDIRS = gdk gtk modules perf + SUBDIRS = po po-properties $(SRC_SUBDIRS) docs m4macros build + + # require automake 1.4 +--- a/Makefile.in.orig 2024-04-28 12:59:09.599008260 +0300 ++++ b/Makefile.in 2024-04-28 12:59:26.447165380 +0300 +@@ -565,7 +565,7 @@ + || { echo "Gtk+Tests:ERROR: Failed to start Xvfb environment for X11 target tests."; exit 1; } \ + && DISPLAY=:$$XID && export DISPLAY + +-SRC_SUBDIRS = gdk gtk modules demos tests perf ++SRC_SUBDIRS = gdk gtk modules perf + SUBDIRS = po po-properties $(SRC_SUBDIRS) docs m4macros build + + # require automake 1.4 +--- a/gtk/Makefile.in.orig 2024-04-28 12:59:09.599008260 +0300 ++++ b/gtk/Makefile.in 2024-04-28 12:59:26.447165380 +0300 +@@ -2010,8 +2010,8 @@ + + @USE_QUARTZ_FALSE@GTK_PRINT_PREVIEW_COMMAND = "evince --unlink-tempfile --preview --print-settings %s %f" + @USE_QUARTZ_TRUE@GTK_PRINT_PREVIEW_COMMAND = "open -b com.apple.Preview %f" +-SUBDIRS = theme-bits . tests +-DIST_SUBDIRS = theme-bits tests ++SUBDIRS = theme-bits . ++DIST_SUBDIRS = theme-bits + @HAVE_CUPS_FALSE@@HAVE_PAPI_CUPS_FALSE@@HAVE_PAPI_FALSE@GTK_PRINT_BACKENDS = file,lpr + @HAVE_CUPS_FALSE@@HAVE_PAPI_CUPS_FALSE@@HAVE_PAPI_TRUE@GTK_PRINT_BACKENDS = file,papi + @HAVE_CUPS_TRUE@@HAVE_PAPI_CUPS_FALSE@GTK_PRINT_BACKENDS = file,cups diff --git a/projects/ArchR/packages/graphics/gtk2/patches/002-gentoo-fix-casts.patch b/projects/ArchR/packages/graphics/gtk2/patches/002-gentoo-fix-casts.patch new file mode 100644 index 0000000000..4ee55d277f --- /dev/null +++ b/projects/ArchR/packages/graphics/gtk2/patches/002-gentoo-fix-casts.patch @@ -0,0 +1,167 @@ +https://bugs.gentoo.org/880617 + +From 81c42586e6d9db7434e9b3f657fbd238294dd9d9 Mon Sep 17 00:00:00 2001 +From: Matt Turner +Date: Sat, 13 May 2023 11:35:28 -0400 +Subject: [PATCH] Fix casts + +--- + gtk/gtkcellrendererspin.c | 2 +- + gtk/gtkcomboboxtext.c | 2 +- + gtk/gtkimmodule.c | 2 +- + gtk/gtklabel.c | 2 +- + gtk/gtkscale.c | 2 +- + gtk/gtktoolpalette.c | 2 +- + gtk/gtktreeview.c | 2 +- + gtk/gtkuimanager.c | 2 +- + gtk/gtkwidget.c | 2 +- + modules/other/gail/gailtreeview.c | 2 +- + modules/printbackends/cups/gtkprintbackendcups.c | 2 +- + 11 files changed, 11 insertions(+), 11 deletions(-) + +diff --git a/gtk/gtkcellrendererspin.c b/gtk/gtkcellrendererspin.c +index 2a3961bf20..68e5b9aaae 100644 +--- a/gtk/gtkcellrendererspin.c ++++ b/gtk/gtkcellrendererspin.c +@@ -207,7 +207,7 @@ gtk_cell_renderer_spin_set_property (GObject *object, + } + + if (obj) +- priv->adjustment = g_object_ref_sink (obj); ++ priv->adjustment = GTK_ADJUSTMENT (g_object_ref_sink (obj)); + break; + case PROP_CLIMB_RATE: + priv->climb_rate = g_value_get_double (value); +diff --git a/gtk/gtkcomboboxtext.c b/gtk/gtkcomboboxtext.c +index 9ffba68766..42c51abebc 100644 +--- a/gtk/gtkcomboboxtext.c ++++ b/gtk/gtkcomboboxtext.c +@@ -275,7 +275,7 @@ gtk_combo_box_text_buildable_custom_tag_start (GtkBuildable *buildable, + + parser_data = g_slice_new0 (ItemParserData); + parser_data->builder = g_object_ref (builder); +- parser_data->object = g_object_ref (buildable); ++ parser_data->object = G_OBJECT (g_object_ref (buildable)); + parser_data->domain = gtk_builder_get_translation_domain (builder); + *parser = item_parser; + *data = parser_data; +diff --git a/gtk/gtkimmodule.c b/gtk/gtkimmodule.c +index 1fcb17a7d8..445b2be87f 100644 +--- a/gtk/gtkimmodule.c ++++ b/gtk/gtkimmodule.c +@@ -662,7 +662,7 @@ lookup_immodule (gchar **immodules_list) + gboolean found; + gchar *context_id; + found = g_hash_table_lookup_extended (contexts_hash, *immodules_list, +- &context_id, NULL); ++ (gpointer *) &context_id, NULL); + if (found) + return context_id; + } +diff --git a/gtk/gtklabel.c b/gtk/gtklabel.c +index c47de5924f..cf68685536 100644 +--- a/gtk/gtklabel.c ++++ b/gtk/gtklabel.c +@@ -1336,7 +1336,7 @@ gtk_label_buildable_custom_tag_start (GtkBuildable *buildable, + + parser_data = g_slice_new0 (PangoParserData); + parser_data->builder = g_object_ref (builder); +- parser_data->object = g_object_ref (buildable); ++ parser_data->object = G_OBJECT (g_object_ref (buildable)); + *parser = pango_parser; + *data = parser_data; + return TRUE; +diff --git a/gtk/gtkscale.c b/gtk/gtkscale.c +index 4317523fb8..a573b2f6ba 100644 +--- a/gtk/gtkscale.c ++++ b/gtk/gtkscale.c +@@ -1471,7 +1471,7 @@ gtk_scale_add_mark (GtkScale *scale, + mark->position = position; + + priv->marks = g_slist_insert_sorted_with_data (priv->marks, mark, +- (GCompareFunc) compare_marks, ++ compare_marks, + GINT_TO_POINTER ( + gtk_range_get_inverted (GTK_RANGE (scale)) + )); +diff --git a/gtk/gtktoolpalette.c b/gtk/gtktoolpalette.c +index b984193ca3..f64b552fb0 100644 +--- a/gtk/gtktoolpalette.c ++++ b/gtk/gtktoolpalette.c +@@ -734,7 +734,7 @@ gtk_tool_palette_add (GtkContainer *container, + + g_ptr_array_add (palette->priv->groups, info); + info->pos = palette->priv->groups->len - 1; +- info->widget = g_object_ref_sink (child); ++ info->widget = (GtkToolItemGroup *) g_object_ref_sink (child); + + gtk_widget_set_parent (child, GTK_WIDGET (palette)); + } +diff --git a/gtk/gtktreeview.c b/gtk/gtktreeview.c +index 89301eb91d..0d2d15b488 100644 +--- a/gtk/gtktreeview.c ++++ b/gtk/gtktreeview.c +@@ -14147,7 +14147,7 @@ gtk_tree_view_set_search_entry (GtkTreeView *tree_view, + + if (entry) + { +- tree_view->priv->search_entry = g_object_ref (entry); ++ tree_view->priv->search_entry = GTK_WIDGET (g_object_ref (entry)); + tree_view->priv->search_custom_entry_set = TRUE; + + if (tree_view->priv->search_entry_changed_id == 0) +diff --git a/gtk/gtkuimanager.c b/gtk/gtkuimanager.c +index d004cf1ed3..8cbeda9e85 100644 +--- a/gtk/gtkuimanager.c ++++ b/gtk/gtkuimanager.c +@@ -503,7 +503,7 @@ gtk_ui_manager_buildable_construct_child (GtkBuildable *buildable, + g_signal_connect (widget, "hierarchy-changed", + G_CALLBACK (child_hierarchy_changed_cb), + GTK_UI_MANAGER (buildable)); +- return g_object_ref (widget); ++ return G_OBJECT (g_object_ref (widget)); + } + + static void +diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c +index 1d1f6bb60e..a2ae2b430f 100644 +--- a/gtk/gtkwidget.c ++++ b/gtk/gtkwidget.c +@@ -10679,7 +10679,7 @@ gtk_widget_buildable_custom_tag_start (GtkBuildable *buildable, + AccelGroupParserData *parser_data; + + parser_data = g_slice_new0 (AccelGroupParserData); +- parser_data->object = g_object_ref (buildable); ++ parser_data->object = G_OBJECT (g_object_ref (buildable)); + *parser = accel_group_parser; + *data = parser_data; + return TRUE; +diff --git a/modules/other/gail/gailtreeview.c b/modules/other/gail/gailtreeview.c +index 23923c59a1..ac6ff0a1c4 100644 +--- a/modules/other/gail/gailtreeview.c ++++ b/modules/other/gail/gailtreeview.c +@@ -995,7 +995,7 @@ gail_tree_view_ref_child (AtkObject *obj, + gail_cell_add_state (cell, ATK_STATE_FOCUSABLE, FALSE); + if (focus_index == i) + { +- gailview->focus_cell = g_object_ref (cell); ++ gailview->focus_cell = ATK_OBJECT (g_object_ref (cell)); + gail_cell_add_state (cell, ATK_STATE_FOCUSED, FALSE); + g_signal_emit_by_name (gailview, + "active-descendant-changed", +diff --git a/modules/printbackends/cups/gtkprintbackendcups.c b/modules/printbackends/cups/gtkprintbackendcups.c +index 2a000dc16f..753c53cb89 100644 +--- a/modules/printbackends/cups/gtkprintbackendcups.c ++++ b/modules/printbackends/cups/gtkprintbackendcups.c +@@ -3479,7 +3479,7 @@ cups_request_ppd (GtkPrinter *printer) + g_io_channel_set_encoding (data->ppd_io, NULL, NULL); + g_io_channel_set_close_on_unref (data->ppd_io, TRUE); + +- data->printer = g_object_ref (printer); ++ data->printer = GTK_PRINTER_CUPS (g_object_ref (printer)); + + resource = g_strdup_printf ("/printers/%s.ppd", + gtk_printer_cups_get_ppd_name (GTK_PRINTER_CUPS (printer))); +-- +2.39.3 + diff --git a/projects/ArchR/packages/graphics/gtk2/patches/003-fix-building-with-gcc15.patch b/projects/ArchR/packages/graphics/gtk2/patches/003-fix-building-with-gcc15.patch new file mode 100644 index 0000000000..7c95975bf1 --- /dev/null +++ b/projects/ArchR/packages/graphics/gtk2/patches/003-fix-building-with-gcc15.patch @@ -0,0 +1,11 @@ +--- a/gtk/gtkitemfactory.c ++++ b/gtk/gtkitemfactory.c +@@ -1184,7 +1184,7 @@ + + entry.path = path; + entry.accelerator = entries[i].accelerator; +- entry.callback = entries[i].callback; ++ entry.callback = (GtkItemFactoryCallback) entries[i].callback; + entry.callback_action = 0; + if (g_pattern_match_string (pspec_separator, path)) + entry.item_type = ""; diff --git a/projects/ArchR/packages/graphics/gtk3/files/settings.ini b/projects/ArchR/packages/graphics/gtk3/files/settings.ini new file mode 100644 index 0000000000..c6bdb7fa46 --- /dev/null +++ b/projects/ArchR/packages/graphics/gtk3/files/settings.ini @@ -0,0 +1,4 @@ +[Settings] +gtk-icon-theme-name = Adwaita +gtk-theme-name = Adwaita +gtk-font-name = Liberation Sans 12 diff --git a/projects/ArchR/packages/graphics/gtk3/package.mk b/projects/ArchR/packages/graphics/gtk3/package.mk new file mode 100644 index 0000000000..4a3d2ef9bb --- /dev/null +++ b/projects/ArchR/packages/graphics/gtk3/package.mk @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2017 Escalade +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2026 ArchR (standalone - original sourced from packages/addons/) + +PKG_NAME="gtk3" +PKG_VERSION="3.24.42" +PKG_SHA256="50f89f615092d4dd01bbd759719f8bd380e5f149f6fd78a94725e2de112377e2" +PKG_LICENSE="LGPL" +PKG_SITE="https://www.gtk.org/" +PKG_URL="https://ftp.gnome.org/pub/gnome/sources/gtk+/${PKG_VERSION:0:4}/gtk+-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain at-spi2-atk atk cairo gdk-pixbuf glib libX11 libXi libXrandr libepoxy pango libxkbcommon wayland wayland-protocols libpng tiff libjpeg-turbo libffi glew" +PKG_DEPENDS_CONFIG="libXft pango gdk-pixbuf shared-mime-info" +PKG_LONGDESC="A library for creating graphical user interfaces for the X Window System." + +PKG_MESON_OPTS_TARGET="-Dbroadway_backend=false \ + -Dcloudproviders=false \ + -Dcolord=no \ + -Ddemos=false \ + -Dexamples=false \ + -Dgtk_doc=false \ + -Dintrospection=false \ + -Dman=false \ + -Dprint_backends=file,lpr \ + -Dquartz_backend=false \ + -Dtests=false \ + -Dwayland_backend=true \ + -Dwin32_backend=false \ + -Dxinerama=no \ + -Dbuiltin_immodules=yes \ + -Dx11_backend=true" + +pre_configure_target() { + export LD_LIBRARY_PATH="${TOOLCHAIN}/lib:${LD_LIBRARY_PATH}" + export GLIB_COMPILE_RESOURCES=glib-compile-resources GLIB_MKENUMS=glib-mkenums GLIB_GENMARSHAL=glib-genmarshal +} + +post_makeinstall_target() { + ${TOOLCHAIN}/bin/glib-compile-schemas ${INSTALL}/usr/share/glib-2.0/schemas +} diff --git a/projects/ArchR/packages/graphics/gtk3/patches/disable-to-pixdata-build.patch b/projects/ArchR/packages/graphics/gtk3/patches/disable-to-pixdata-build.patch new file mode 100644 index 0000000000..c42f8a854c --- /dev/null +++ b/projects/ArchR/packages/graphics/gtk3/patches/disable-to-pixdata-build.patch @@ -0,0 +1,26 @@ +--- a/gtk/gen-gtk-gresources-xml.py 2021-02-24 19:13:19.000000000 +0000 ++++ b/gtk/gen-gtk-gresources-xml.py 2021-04-03 23:52:35.000000000 +0000 +@@ -23,11 +23,6 @@ + theme/Adwaita/gtk-contained-dark.css + ''' + +-for f in get_files('theme/Adwaita/assets', '.png'): +- xml += ' theme/Adwaita/assets/{0}\n'.format(f) +- +-xml += '\n' +- + for f in get_files('theme/Adwaita/assets', '.svg'): + xml += ' theme/Adwaita/assets/{0}\n'.format(f) + +@@ -38,11 +33,6 @@ + theme/HighContrast/gtk-contained-inverse.css + ''' + +-for f in get_files('theme/HighContrast/assets', '.png'): +- xml += ' theme/HighContrast/assets/{0}\n'.format(f) +- +-xml += '\n' +- + for f in get_files('theme/HighContrast/assets', '.svg'): + xml += ' theme/HighContrast/assets/{0}\n'.format(f) + diff --git a/projects/ArchR/packages/graphics/imagemagick/package.mk b/projects/ArchR/packages/graphics/imagemagick/package.mk new file mode 100644 index 0000000000..e919f545c2 --- /dev/null +++ b/projects/ArchR/packages/graphics/imagemagick/package.mk @@ -0,0 +1,36 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="imagemagick" +PKG_VERSION="f65eba252e3aa387bd99297a750a2ee250664f8c" +PKG_LICENSE="http://www.imagemagick.org/script/license.php" +PKG_SITE="https://github.com/ImageMagick/ImageMagick" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain libpng libjpeg-turbo fontconfig libraw lcms2 libtool libxml2 libzip libwebp" +PKG_LONGDESC="Software suite to create, edit, compose, or convert bitmap images" + +if [ "${DISPLAYSERVER}" = "wl" ]; then + PKG_DEPENDS_TARGET+=" libXext pango" +fi + +pre_configure_target() { + PKG_CONFIGURE_OPTS_TARGET="--disable-openmp \ + --disable-static \ + --enable-shared \ + --with-pango=no \ + --with-utilities=yes \ + --with-x=no" + + if [ "${DISPLAYSERVER}" = "wl" ]; then + PKG_CONFIGURE_OPTS_TARGET+=" --with-x=yes" + else + PKG_CONFIGURE_OPTS_TARGET+=" --with-x=no" + fi + export LDFLAGS+=" -lsharpyuv -lwebp" +} + +makeinstall_target() { + make install DESTDIR=${INSTALL} ${PKG_MAKEINSTALL_OPTS_TARGET} + rm ${INSTALL}/usr/bin/*config +} diff --git a/projects/ArchR/packages/graphics/libdrm/package.mk b/projects/ArchR/packages/graphics/libdrm/package.mk new file mode 100644 index 0000000000..1ea529959f --- /dev/null +++ b/projects/ArchR/packages/graphics/libdrm/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="libdrm" +PKG_VERSION="2.4.128" +PKG_LICENSE="GPL" +PKG_SITE="http://dri.freedesktop.org" +PKG_URL="http://dri.freedesktop.org/libdrm/libdrm-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_HOST="toolchain libpciaccess libdisplay-info" +PKG_DEPENDS_TARGET="toolchain libpciaccess libdisplay-info" +PKG_LONGDESC="The userspace interface library to kernel DRM services." +PKG_TOOLCHAIN="meson" + +get_graphicdrivers + +PKG_MESON_OPTS_TARGET="-Dnouveau=disabled \ + -Domap=disabled \ + -Dexynos=disabled \ + -Dtegra=disabled \ + -Dcairo-tests=disabled \ + -Dman-pages=disabled \ + -Dvalgrind=disabled \ + -Dfreedreno-kgsl=false \ + -Dinstall-test-programs=false \ + -Dudev=false" + +listcontains "${GRAPHIC_DRIVERS}" "(iris|i915|i965)" && + PKG_MESON_OPTS_TARGET+=" -Dintel=enabled" || PKG_MESON_OPTS_TARGET+=" -Dintel=disabled" + +listcontains "${GRAPHIC_DRIVERS}" "(r200|r300|r600|radeonsi)" && + PKG_MESON_OPTS_TARGET+=" -Dradeon=enabled" || PKG_MESON_OPTS_TARGET+=" -Dradeon=disabled" + +listcontains "${GRAPHIC_DRIVERS}" "radeonsi" && + PKG_MESON_OPTS_TARGET+=" -Damdgpu=enabled" || PKG_MESON_OPTS_TARGET+=" -Damdgpu=disabled" + +listcontains "${GRAPHIC_DRIVERS}" "freedreno" && + PKG_MESON_OPTS_TARGET+=" -Dfreedreno=enabled" || PKG_MESON_OPTS_TARGET+=" -Dfreedreno=disabled" + +listcontains "${GRAPHIC_DRIVERS}" "etnaviv" && + PKG_MESON_OPTS_TARGET+=" -Detnaviv=enabled" || PKG_MESON_OPTS_TARGET+=" -Detnaviv=disabled" + +post_makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp -a ${PKG_BUILD}/.${TARGET_NAME}/tests/modetest/modetest ${INSTALL}/usr/bin/ + for header in xf86drm.h xf86drmMode.h + do + sed -i "s###g" ${SYSROOT_PREFIX}/usr/include/${header} + sed -i "s##g" ${SYSROOT_PREFIX}/usr/include/${header} + done +} diff --git a/projects/ArchR/packages/graphics/libegl/package.mk b/projects/ArchR/packages/graphics/libegl/package.mk new file mode 100644 index 0000000000..89ad2c2dc2 --- /dev/null +++ b/projects/ArchR/packages/graphics/libegl/package.mk @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="libegl" +PKG_VERSION="1.0" +PKG_LICENSE="GPLv2" +PKG_ARCH="arm aarch64" +PKG_DEPENDS_TARGET="toolchain" +PKG_TOOLCHAIN="manual" +PKG_LONGDESC="Libraries needed to run OpenGL applications on devices that dont have native OpenGL support." + +makeinstall_target() { + export STRIP=true + mkdir -p ${INSTALL}/usr/lib/egl + tar -xvf ${PKG_DIR}/sources/libegl.tar.gz -C ${INSTALL}/usr/lib/egl +} diff --git a/projects/ArchR/packages/graphics/libegl/sources/libegl.tar.gz b/projects/ArchR/packages/graphics/libegl/sources/libegl.tar.gz new file mode 100755 index 0000000000..fc83c94415 Binary files /dev/null and b/projects/ArchR/packages/graphics/libegl/sources/libegl.tar.gz differ diff --git a/projects/ArchR/packages/graphics/libepoxy/package.mk b/projects/ArchR/packages/graphics/libepoxy/package.mk new file mode 100644 index 0000000000..99e9c5a295 --- /dev/null +++ b/projects/ArchR/packages/graphics/libepoxy/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) 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.10" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/anholt/libepoxy" +PKG_URL="${PKG_SITE}/archive/refs/tags/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Epoxy is a library for handling OpenGL function pointer management for you." + +if [ "${OPENGL}" != "no" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL}" +fi + +if [ "${OPENGLES}" != "no" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" +fi + +if [ "${DISPLAYSERVER}" != "x11" ] && \ + [ "${DISPLAYSERVER}" != "wl" ]; then + PKG_CONFIGURE_OPTS_TARGET="--disable-glx" +fi diff --git a/projects/ArchR/packages/graphics/libglvnd/package.mk b/projects/ArchR/packages/graphics/libglvnd/package.mk new file mode 100644 index 0000000000..e962478670 --- /dev/null +++ b/projects/ArchR/packages/graphics/libglvnd/package.mk @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libglvnd" +PKG_VERSION="1.7.0" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/NVIDIA/libglvnd" +PKG_URL="https://github.com/NVIDIA/libglvnd/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="libglvnd is a vendor-neutral dispatch layer for arbitrating OpenGL API calls between multiple vendors." + +configure_package() { + if [ "${DISPLAYSERVER}" = "x11" ] || \ + [ "${DISPLAYSERVER}" = "wl" ]; then + PKG_DEPENDS_TARGET+=" libX11 libXext xorgproto" + fi +} + +pre_configure_target(){ + if [ "${OPENGL_SUPPORT}" = "yes" ] + then + PKG_MESON_OPTS_TARGET+=" -Degl=true -Dglx=enabled -Dheaders=true" + fi + + if [ "${OPENGLES_SUPPORT}" = "yes" ] + then + PKG_MESON_OPTS_TARGET+=" -Dgles1=true -Dgles2=true -Dheaders=true" + else + PKG_MESON_OPTS_TARGET+=" -Dgles1=false -Dgles2=false" + fi +} + diff --git a/projects/ArchR/packages/graphics/libjpeg-turbo/package.mk b/projects/ArchR/packages/graphics/libjpeg-turbo/package.mk new file mode 100644 index 0000000000..623bb7dfc4 --- /dev/null +++ b/projects/ArchR/packages/graphics/libjpeg-turbo/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) 2018-present Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="libjpeg-turbo" +PKG_VERSION="3.0.1" +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:host" +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="-DCMAKE_POLICY_VERSION_MINIMUM=3.5 \ + -DENABLE_STATIC=ON \ + -DENABLE_SHARED=ON \ + -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} =~ i*86|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/projects/ArchR/packages/graphics/libmali/package.mk b/projects/ArchR/packages/graphics/libmali/package.mk new file mode 100644 index 0000000000..2554ce6d2c --- /dev/null +++ b/projects/ArchR/packages/graphics/libmali/package.mk @@ -0,0 +1,83 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="libmali" +PKG_LICENSE="nonfree" +PKG_SITE="https://github.com/archr-linux/libmali" +PKG_VERSION="0fe30426b822699f0a660268a6040fdafce229d1" +# zip format makes extract very fast (<1s). tgz takes 20 seconds to scan the whole file +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.zip" +PKG_DEPENDS_TARGET="toolchain libdrm patchelf:host gpudriver" +PKG_LONGDESC="OpenGL ES user-space binary for the ARM Mali GPU family" +PKG_TOOLCHAIN="meson" +PKG_PATCH_DIRS+=" ${DEVICE}" + +# patchelf is incompatible with strip, but is needed to ensure apps call wrapped functions +PKG_BUILD_FLAGS="-strip" + +case "${DEVICE}" in + S922X) + DRIVER_VERSION="r51p0" + PKG_DEPENDS_TARGET+=" vulkan-wsi-layer vulkan-tools" + ;; + RK3588) + DRIVER_VERSION="g13p0" + ;; + *) # RK3326 and RK3566 + DRIVER_VERSION="g24p0" + ;; +esac + +case "${DISPLAYSERVER}" in + wl) + PLATFORM="wayland-gbm" + PKG_DEPENDS_TARGET+=" wayland" + ;; + x11) + PLATFORM="x11-gbm" + ;; + *) + PLATFORM="gbm" + ;; +esac + +PKG_MESON_OPTS_TARGET+=" -Darch=${ARCH} -Dgpu=${MALI_FAMILY} -Dversion=${DRIVER_VERSION} -Dplatform=${PLATFORM} \ + -Dkhr-header=false -Dvendor-package=true -Dwrappers=enabled -Dhooks=true" + + +unpack() { + mkdir -p "${PKG_BUILD}" + cd "${PKG_BUILD}" + pwd + # Extract only what is needed + LIBNAME="libmali-${MALI_FAMILY}-${DRIVER_VERSION}-${PLATFORM}.so" + unzip -q "${SOURCES}/${PKG_NAME}/${PKG_SOURCE_NAME}" "*/hook/*" "*/include/*" "*/scripts/*" "*/meson*" "*/data/*" "*/${LIBNAME}" + mv libmali*/* . + rmdir libmali-* + if [ "${MALI_FAMILY}" = "meson" ]; then + mv data/vulkan/mali_meson.json.in data/vulkan/mali.json.in + fi + ln -s lib optimize_3 +} + +post_makeinstall_target() { + rm -rf "${SYSROOT_PREFIX}/usr/include" # all needed headers are installed by glvnd, mesa and wayland + rm -rf "${INSTALL}/etc/ld.so.conf.d" "${SYSROOT_PREFIX}/etc/ld.so.conf.d" # upstream installs ld.so config and we don't need it + + # IDK how libs in ubuntu package get these dependencies. Need to specify them manually here. + for lib in "${INSTALL}"/usr/lib*/mali/lib*.so.*; do + patchelf --add-needed libmali-hook.so.1 "${lib}" + done + patchelf --add-needed libmali.so.1 "${INSTALL}"/usr/lib*/libmali-hook.so.1 + + # x11 lib needed for some applications on the RK3588 + if [ ${DEVICE} = "RK3588" ] && [ ${TARGET_ARCH} = "aarch64" ]; then + curl -Lo ${INSTALL}/usr/lib/libmali-${MALI_FAMILY}-${DRIVER_VERSION}-x11-gbm.so ${PKG_SITE}/raw/master/lib/aarch64-linux-gnu/libmali-${MALI_FAMILY}-${DRIVER_VERSION}-x11-gbm.so + fi + # S922X - mali vulkan libs need moving + if [ "${DEVICE}" = "S922X" ] && [ "${ARCH}" = "aarch64" ]; then + mv "${INSTALL}"/usr/lib/mali/libMaliVulkan.* "${INSTALL}"/usr/lib/ + fi +} diff --git a/projects/ArchR/packages/graphics/libmali/patches/RK3588/000-dont-install-firmware.patch b/projects/ArchR/packages/graphics/libmali/patches/RK3588/000-dont-install-firmware.patch new file mode 100644 index 0000000000..3f7def1a5a --- /dev/null +++ b/projects/ArchR/packages/graphics/libmali/patches/RK3588/000-dont-install-firmware.patch @@ -0,0 +1,18 @@ +diff -rupN libmali.orig/meson.build libmali/meson.build +--- libmali.orig/meson.build 2024-06-26 18:37:20.569979221 +0000 ++++ libmali/meson.build 2024-06-26 18:38:04.922988416 +0000 +@@ -332,10 +332,10 @@ if get_option('with-overlay') + endif + + # Install firmwares +-if gpu == 'valhall-g610' +- install_data('firmware/g610/mali_csffw.bin', +- install_dir : get_option('firmware-dir')) +-endif ++#if gpu == 'valhall-g610' ++# install_data('firmware/g610/mali_csffw.bin', ++# install_dir : get_option('firmware-dir')) ++#endif + + if vendor_package + # Install vendor ld config diff --git a/projects/ArchR/packages/graphics/libpng/package.mk b/projects/ArchR/packages/graphics/libpng/package.mk new file mode 100644 index 0000000000..192822987a --- /dev/null +++ b/projects/ArchR/packages/graphics/libpng/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="libpng" +PKG_VERSION="1.6.40" +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/projects/ArchR/packages/graphics/librga/package.mk b/projects/ArchR/packages/graphics/librga/package.mk new file mode 100644 index 0000000000..cd144958a8 --- /dev/null +++ b/projects/ArchR/packages/graphics/librga/package.mk @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="librga" +PKG_VERSION="ccfec13d6c48e3f0c7f24810b3dac162c40cdda8" +PKG_ARCH="arm aarch64" +PKG_LICENSE="Apache-2.0" +PKG_DEPENDS_TARGET="toolchain libdrm" +PKG_SITE="https://github.com/varphone/rockchip-linux-rga" +PKG_URL="${PKG_SITE}.git" +PKG_LONGDESC="RGA is an independent 2D hardware acceleration userspace driver" +PKG_TOOLCHAIN="meson" diff --git a/projects/ArchR/packages/graphics/libwebp/package.mk b/projects/ArchR/packages/graphics/libwebp/package.mk new file mode 100644 index 0000000000..f380a0a244 --- /dev/null +++ b/projects/ArchR/packages/graphics/libwebp/package.mk @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2023-present JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="libwebp" +PKG_VERSION="e78e924f84ddcd41fc5d55583bc32f4ddc4100a3" +PKG_LICENSE="BSD" +PKG_SITE="https://github.com/webmproject/libwebp" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="toolchain:host" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="WebP codec is a library to encode and decode images in WebP format." +PKG_TOOLCHAIN="cmake" + +PKG_CMAKE_OPTS_TARGET="-DBUILD_SHARED_LIBS=ON" diff --git a/projects/ArchR/packages/graphics/mesa-demos/package.mk b/projects/ArchR/packages/graphics/mesa-demos/package.mk new file mode 100644 index 0000000000..dd4871838f --- /dev/null +++ b/projects/ArchR/packages/graphics/mesa-demos/package.mk @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="mesa-demos" +PKG_VERSION="9.0.0" +PKG_LICENSE="OSS" +PKG_SITE="https://www.mesa3d.org/" +PKG_URL="https://archive.mesa3d.org/demos/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain libX11 mesa glu glew gtk3 libXcomposite libdecor" +PKG_LONGDESC="Mesa 3D demos - installed are the well known glxinfo and glxgears." +PKG_BUILD_FLAGS="-sysroot" + +if [ "${VULKAN_SUPPORT}" = "yes" ]; then + PKG_MESON_OPTS_TARGET=" -Dvulkan=enabled" +else + PKG_MESON_OPTS_TARGET=" -Dvulkan=disabled" +fi + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp -P src/xdemos/glxdemo ${INSTALL}/usr/bin + cp -P src/xdemos/glxgears ${INSTALL}/usr/bin + cp -P src/xdemos/glxinfo ${INSTALL}/usr/bin + + if [ "${VULKAN_SUPPORT}" = "yes" ]; then + cp -P src/vulkan/vkgears ${INSTALL}/usr/bin + fi +} diff --git a/projects/ArchR/packages/graphics/mesa-demos/patches/vkcube.patch b/projects/ArchR/packages/graphics/mesa-demos/patches/vkcube.patch new file mode 100644 index 0000000000..8ffff23168 --- /dev/null +++ b/projects/ArchR/packages/graphics/mesa-demos/patches/vkcube.patch @@ -0,0 +1,69 @@ +From c14abaa36d10d104e0e9179e5215f8caff4ca096 Mon Sep 17 00:00:00 2001 +From: Erik Faye-Lund +Date: Tue, 3 Sep 2024 20:08:20 +0200 +Subject: [PATCH] vkgears: do not require vulkan 1.1 + +We're passing zero as the flags to vkGetDeviceQueue2, meaning we might +as well use vkGetDeviceQueue from Vulkan 1.0 instead. And this seems to +be the only reason we depended on Vulkan 1.1 to start with. + +This makes it easier to use vkgears to test early bootstrapped Vulkan +implementations. We still use Vulkan 1.1 if available, because GPU +assisted validation requires it to function. + +While we're at it, switch away from VK_MAKE_VERSION(), which is +deprecated. We don't really need it anyway, because we have dedicated +defines for each version. + +Reviewed-by: Hoe Hao Cheng +Reviewed-by: Antonino Maniscalco +--- + src/vulkan/vkgears.c | 21 +++++++++++---------- + 1 file changed, 11 insertions(+), 10 deletions(-) + +diff --git a/src/vulkan/vkgears.c b/src/vulkan/vkgears.c +index bb8f00640..b603e76b6 100644 +--- a/src/vulkan/vkgears.c ++++ b/src/vulkan/vkgears.c +@@ -132,13 +132,21 @@ current_time(void) + static void + init_vk(const char *extension) + { +- VkResult res = vkCreateInstance( ++ uint32_t api_version = VK_API_VERSION_1_0; ++ ++ // use Vulkan 1.1 if supported ++ uint32_t instance_version = api_version; ++ VkResult res = vkEnumerateInstanceVersion(&instance_version); ++ if (res == VK_SUCCESS && instance_version >= VK_API_VERSION_1_1) ++ api_version = VK_API_VERSION_1_1; ++ ++ res = vkCreateInstance( + &(VkInstanceCreateInfo) { + .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, + .pApplicationInfo = &(VkApplicationInfo) { + .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, + .pApplicationName = "vkgears", +- .apiVersion = VK_MAKE_VERSION(1, 1, 0), ++ .apiVersion = api_version, + }, + .enabledExtensionCount = extension ? 2 : 0, + .ppEnabledExtensionNames = (const char *[2]) { +@@ -192,14 +200,7 @@ init_vk(const char *extension) + if (res != VK_SUCCESS) + error("Failed to create Vulkan device.\n"); + +- vkGetDeviceQueue2(device, +- &(VkDeviceQueueInfo2) { +- .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2, +- .flags = 0, +- .queueFamilyIndex = 0, +- .queueIndex = 0, +- }, +- &queue); ++ vkGetDeviceQueue(device, 0, 0, &queue); + + vkCreateCommandPool(device, + &(const VkCommandPoolCreateInfo) { +-- +GitLab diff --git a/projects/ArchR/packages/graphics/mesa/package.mk b/projects/ArchR/packages/graphics/mesa/package.mk new file mode 100644 index 0000000000..971182e440 --- /dev/null +++ b/projects/ArchR/packages/graphics/mesa/package.mk @@ -0,0 +1,106 @@ +# 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_LICENSE="OSS" +PKG_SITE="http://www.mesa3d.org/" +PKG_DEPENDS_HOST="toolchain:host llvm:host libclc:host spirv-tools:host libdrm:host \ + spirv-llvm-translator:host wayland-protocols:host libX11:host libXext:host \ + libXfixes:host libxshmfence:host libXxf86vm:host xrandr:host glslang:host" +PKG_DEPENDS_TARGET="toolchain expat libdrm Mako:host pyyaml:host" +PKG_LONGDESC="Mesa is a 3-D graphics library with an API." +PKG_TOOLCHAIN="meson" +PKG_PATCH_DIRS+=" ${DEVICE}" +PKG_VERSION="26.0.5" +PKG_URL="https://gitlab.freedesktop.org/mesa/mesa/-/archive/mesa-${PKG_VERSION}/mesa-mesa-${PKG_VERSION}.tar.gz" + +if listcontains "${GRAPHIC_DRIVERS}" "panfrost"; then + PKG_DEPENDS_TARGET+=" mesa:host" +fi + +get_graphicdrivers + +pre_configure_host() { +# Host only gets built for panfrost. +PKG_MESON_OPTS_HOST+=" ${MESA_LIBS_PATH_OPTS} \ + -Dgallium-drivers=${GALLIUM_DRIVERS// /,} \ + -Dvulkan-drivers=${VULKAN_DRIVERS_MESA// /,} \ + -Dmesa-clc=enabled \ + -Dinstall-mesa-clc=true \ + -Dprecomp-compiler=enabled \ + -Dinstall-precomp-compiler=true" +} + +PKG_MESON_OPTS_TARGET=" ${MESA_LIBS_PATH_OPTS} \ + -Dgallium-drivers=${GALLIUM_DRIVERS// /,} \ + -Dgallium-extra-hud=false \ + -Dshader-cache=enabled \ + -Dshared-glapi=enabled \ + -Dopengl=true \ + -Dgbm=enabled \ + -Degl=enabled \ + -Dlibunwind=disabled \ + -Dlmsensors=disabled \ + -Dbuild-tests=false" + +if listcontains "${GRAPHIC_DRIVERS}" "panfrost"; then + # These options require that we have built mesa host as specified above + PKG_MESON_OPTS_TARGET+=" -Dmesa-clc=system \ + -Dprecomp-compiler=system" +fi + +if [ "${DISPLAYSERVER}" = "x11" ]; then + PKG_DEPENDS_TARGET+=" xorgproto libXext libXdamage libXfixes libXxf86vm libxcb libX11 libxshmfence libXrandr libglvnd glfw" + export X11_INCLUDES= + PKG_MESON_OPTS_TARGET+=" -Dplatforms=x11 \ + -Dglx=dri \ + -Dglvnd=enabled" +elif [ "${DISPLAYSERVER}" = "wl" ]; then + PKG_DEPENDS_TARGET+=" wayland wayland-protocols libglvnd glfw" + PKG_MESON_OPTS_TARGET+=" -Dplatforms=wayland,x11 \ + -Dglx=dri \ + -Dglvnd=enabled" + PKG_DEPENDS_TARGET+=" xorgproto libXext libXdamage libXfixes libXxf86vm libxcb libX11 libxshmfence libXrandr libglvnd" + export X11_INCLUDES= +else + PKG_MESON_OPTS_TARGET+=" -Dplatforms="" \ + -Dgallium-nine=false \ + -Dglx=disabled \ + -Dglvnd=disabled" +fi + +if [ "${LLVM_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" elfutils llvm" + PKG_MESON_OPTS_TARGET+=" -Dllvm=enabled" +else + PKG_MESON_OPTS_TARGET+=" -Dllvm=disabled" +fi + +if [ "${VAAPI_SUPPORT}" = "yes" ] && listcontains "${GRAPHIC_DRIVERS}" "(r600|radeonsi)"; then + PKG_DEPENDS_TARGET+=" libva" + PKG_MESON_OPTS_TARGET+=" -Dgallium-va=enabled \ + -Dvideo-codecs=vc1dec,h264dec,h264enc,h265dec,h265enc" +else + PKG_MESON_OPTS_TARGET+=" -Dgallium-va=disabled" +fi + +if [ "${OPENGLES_SUPPORT}" = "yes" ]; then + PKG_MESON_OPTS_TARGET+=" -Dgles1=enabled -Dgles2=enabled" +else + PKG_MESON_OPTS_TARGET+=" -Dgles1=disabled -Dgles2=disabled" +fi + +if [ "${VULKAN_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${VULKAN} vulkan-tools" + PKG_MESON_OPTS_TARGET+=" -Dvulkan-drivers=${VULKAN_DRIVERS_MESA// /,}" +else + PKG_MESON_OPTS_TARGET+=" -Dvulkan-drivers=" +fi + +post_makeinstall_target() { + # While this likely breaks panfrost vulkan, it does fix vulkaninfo on libmali-vulkan + if [ "${DEVICE}" = "S922X" ]; then + rm -f ${INSTALL}/usr/lib/libvulkan_panfrost.so ${INSTALL}/usr/share/vulkan/icd.d/panfrost_icd.*.json + fi +} diff --git a/projects/ArchR/packages/graphics/mesa/patches/000-fix-a740-vulkan.patch b/projects/ArchR/packages/graphics/mesa/patches/000-fix-a740-vulkan.patch new file mode 100644 index 0000000000..89bda7e086 --- /dev/null +++ b/projects/ArchR/packages/graphics/mesa/patches/000-fix-a740-vulkan.patch @@ -0,0 +1,18 @@ +diff --git a/src/freedreno/vulkan/tu_knl_drm_msm.cc b/src/freedreno/vulkan/tu_knl_drm_msm.cc +index e3a6916..d60db42 100644 +--- a/src/freedreno/vulkan/tu_knl_drm_msm.cc ++++ b/src/freedreno/vulkan/tu_knl_drm_msm.cc +@@ -1257,11 +1257,8 @@ msm_queue_submit(struct tu_queue *queue, void *_submit, + uint64_t other_timepoint = + submit->binds.size != 0 ? queue->gfx_timepoint : + queue->sparse_timepoint; +- uint32_t extra_wait_count = +- (queue->type == TU_QUEUE_GFX && other_timepoint != 0) ? 1 : 0; +- uint32_t extra_signal_count = +- (queue->type == TU_QUEUE_GFX && has_vm_bind) ? 1 : 0; +- ++ uint32_t extra_wait_count = 0; ++ uint32_t extra_signal_count = 0; + /* Allocate without wait timeline semaphores */ + in_syncobjs = (struct drm_msm_syncobj *) vk_zalloc( + &queue->device->vk.alloc, diff --git a/projects/ArchR/packages/graphics/qt6/package.mk b/projects/ArchR/packages/graphics/qt6/package.mk new file mode 100644 index 0000000000..0283d914aa --- /dev/null +++ b/projects/ArchR/packages/graphics/qt6/package.mk @@ -0,0 +1,134 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="qt6" +PKG_VERSION_MAJOR="6.8" +PKG_VERSION="${PKG_VERSION_MAJOR}.3" +PKG_LICENSE="GPL" +PKG_SITE="https://download.qt.io" +PKG_URL="${PKG_SITE}/archive/qt/${PKG_VERSION_MAJOR}/${PKG_VERSION}/single/qt-everywhere-src-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain qt6:host openssl libjpeg-turbo libpng pcre2 sqlite zlib freetype SDL2 gstreamer gst-plugins-base gst-plugins-good gst-libav" +PKG_DEPENDS_HOST="gcc:host llvm:host mesa:host" +PKG_LONGDESC="A cross-platform application and UI framework" + +# Apply project-specific patches +PKG_PATCH_DIRS="${PROJECT}" + +# Set OpenGL or OpenGLES support for CMake +if [ "${OPENGL_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_HOST+=" ${OPENGL}" + PKG_DEPENDS_TARGET+=" ${OPENGL}" + PKG_CMAKE_OPTS_TARGET+=" -DQT_FEATURE_opengl=ON -DQT_FEATURE_opengles2=OFF" +elif [ "${OPENGLES_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_HOST+=" ${OPENGLES}" + PKG_DEPENDS_TARGET+=" ${OPENGLES}" + PKG_CMAKE_OPTS_TARGET+=" -DQT_FEATURE_opengles2=ON -DQT_FEATURE_opengl=OFF" +else + PKG_CMAKE_OPTS_TARGET+=" -DQT_FEATURE_opengl=OFF -DQT_FEATURE_opengles2=OFF" +fi + +# XCB support for X11 +if [ "${DISPLAYSERVER}" = "x11" ]; then + PKG_DEPENDS_TARGET+=" xcb-util xcb-util-image xcb-util-keysyms xcb-util-renderutil xcb-util-wm libxcb-cursor libxkbcommon" +fi + +# Wayland support +if [ "${DISPLAYSERVER}" = "wl" ]; then + PKG_DEPENDS_TARGET+=" wayland xcb-util xcb-util-image xcb-util-keysyms xcb-util-renderutil xcb-util-wm libxcb-cursor libxkbcommon" + PKG_CMAKE_OPTS_TARGET+=" -DBUILD_qtwayland=ON" +else + PKG_CMAKE_OPTS_TARGET+=" -DBUILD_qtwayland=OFF" +fi + +# Vulkan support +if [ "${VULKAN_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${VULKAN}" + PKG_CMAKE_OPTS_TARGET+=" -DQT_FEATURE_vulkan=ON" +else + PKG_CMAKE_OPTS_TARGET+=" -DQT_FEATURE_vulkan=OFF" +fi + + +pre_configure_host() { + export LDFLAGS="${LDFLAGS} -lgio-2.0 -lgobject-2.0 -lglib-2.0" + echo "LDFLAGS are $LDFLAGS" + + unset HOST_CMAKE_OPTS + # Disable unneeded modules + MODULES_TO_DISABLE=("qt3d" "qt5compat" "qtactiveqt" "qtcharts" "qtcoap" "qtconnectivity" "qtdatavis3d" + "qtdoc" "qtgraphs" "qtgrpc" "qthttpserver" "qtlocation" "qtlottie" "qtmqtt" + "qtmultimedia" "qtnetworkauth" "qtopcua" "qtpositioning" "qtquick3d" "qtquick3dphysics" + "qtquickeffectmaker" "qtquicktimeline" "qtremoteobjects" "qtscxml" "qtsensors" "qtserialbus" + "qtserialport" "qtspeech" "qttranslations" "qtvirtualkeyboard" "qtwebchannel" + "qtwebengine" "qtwebsockets" "qtwebview") + for module in "${MODULES_TO_DISABLE[@]}"; do + PKG_CMAKE_OPTS_HOST+=" -DBUILD_${module}=OFF" + done + + # Enable required modules + # > qtbase qtshadertools qtdeclarative qtsvg qtlanguageserver qttools qtwayland + MODULES_TO_ENABLE=("qtbase" "qtshadertools" "qtdeclarative" "qtsvg" "qtlanguageserver" "qtimageformats" "qttools" "qtwayland") + for module in "${MODULES_TO_ENABLE[@]}"; do + PKG_CMAKE_OPTS_HOST+=" -DBUILD_${module}=ON" + done + + # Set Host Install path + PKG_CMAKE_OPTS_HOST+=" -DCMAKE_INSTALL_PREFIX=${TOOLCHAIN}/usr/local/qt6 \ + -DCMAKE_BUILD_TYPE=Release \ + -DQT_BUILD_EXAMPLES=OFF \ + -DQT_BUILD_TESTS=OFF \ + -DQT_USE_CCACHE=ON \ + -DQT_GENERATE_SBOM=OFF \ + -DQT_FEATURE_icu=OFF \ + -DQT_FEATURE_wayland=ON \ + -DBUILD_WITH_PCH=OFF" +} + +pre_configure_target(){ + unset TARGET_CMAKE_OPTS + # Disable unneeded modules + MODULES_TO_DISABLE=("qt3d" "qt5compat" "qtactiveqt" "qtcharts" "qtcoap" "qtconnectivity" "qtdatavis3d" + "qtdoc" "qtgraphs" "qtgrpc" "qthttpserver" "qtimageformats" + "qtlocation" "qtlottie" "qtmqtt" "qtnetworkauth" "qtopcua" "qtpositioning" + "qtquick3d" "qtquick3dphysics" "qtquickeffectmaker" "qtquicktimeline" "qtremoteobjects" + "qtscxml" "qtsensors" "qtspeech" "qttranslations" "qtvirtualkeyboard" + "qtwebchannel" "qtwebengine" "qtwebview") + for module in "${MODULES_TO_DISABLE[@]}"; do + PKG_CMAKE_OPTS_TARGET+=" -DBUILD_${module}=OFF" + done + + # Enable required modules: qtbase qtmultimedia qtshadertools qtdeclarative qtserialbus qtserialport qtsvg qttools qtwebsockets qtlanguageserver + # Conditionals: qtwayland + MODULES_TO_ENABLE=("qtbase" "qtmultimedia" "qtshadertools" "qtdeclarative" "qtserialbus" + "qtserialport" "qtsvg" "qttools" "qtwebsockets" "qtlanguageserver") + for module in "${MODULES_TO_ENABLE[@]}"; do + PKG_CMAKE_OPTS_TARGET+=" -DBUILD_${module}=ON" + done + + PKG_CMAKE_OPTS_TARGET+=" -DCMAKE_INSTALL_PREFIX=/usr \ + -DCMAKE_SYSROOT=${SYSROOT_PREFIX} \ + -DCMAKE_TOOLCHAIN_FILE=${CMAKE_CONF} \ + -DQT_HOST_PATH=${TOOLCHAIN}/usr/local/qt6 \ + -DCMAKE_BUILD_TYPE=Release \ + -DQT_DEBUG_FIND_PACKAGE=ON \ + -DBUILD_SHARED_LIBS=ON \ + -DQT_BUILD_EXAMPLES=OFF \ + -DQT_BUILD_TESTS=OFF \ + -DQT_FEATURE_printer=OFF \ + -DQT_USE_CCACHE=ON \ + -DQT_FEATURE_xcb=ON \ + -DQT_GENERATE_SBOM=OFF \ + -DBUILD_WITH_PCH=OFF" +} + +post_makeinstall_target() { + rm -rf ${INSTALL}/usr + + mkdir -p ${INSTALL}/usr/lib + mkdir -p ${INSTALL}/usr/plugins + mkdir -p ${INSTALL}/usr/qml + + cp -rf ${PKG_BUILD}/.${TARGET_NAME}/qtbase/lib/*.so* ${INSTALL}/usr/lib/ + cp -rf ${PKG_BUILD}/.${TARGET_NAME}/qtbase/plugins/* ${INSTALL}/usr/plugins/ + cp -rf ${PKG_BUILD}/.${TARGET_NAME}/qtbase/qml/* ${INSTALL}/usr/qml/ +} diff --git a/projects/ArchR/packages/graphics/spirv-headers/package.mk b/projects/ArchR/packages/graphics/spirv-headers/package.mk new file mode 100644 index 0000000000..43b925291b --- /dev/null +++ b/projects/ArchR/packages/graphics/spirv-headers/package.mk @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Frank Hartung (supervisedthinking (@) gmail.com) +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="spirv-headers" +# The SPIRV-Headers pkg_version needs to match the compatible (known_good) glslang pkg_version. +# https://raw.githubusercontent.com/KhronosGroup/glslang/${PKG_VERSION}/known_good.json +# When updating glslang pkg_version please update to the known_good spirv-headers pkg_version. +PKG_VERSION="3f17b2af6784bfa2c5aa5dbb8e0e74a607dd8b3b" +PKG_LICENSE="Apache-2.0" +PKG_SITE="https://github.com/KhronosGroup/SPIRV-headers" +PKG_URL="https://github.com/KhronosGroup/SPIRV-headers/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="" +PKG_LONGDESC="SPIRV-Headers" +PKG_TOOLCHAIN="manual" diff --git a/projects/ArchR/packages/graphics/spirv-llvm-translator/package.mk b/projects/ArchR/packages/graphics/spirv-llvm-translator/package.mk new file mode 100644 index 0000000000..1710669755 --- /dev/null +++ b/projects/ArchR/packages/graphics/spirv-llvm-translator/package.mk @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2024-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="spirv-llvm-translator" +PKG_VERSION="20.1.5" +PKG_SHA256="83048509774d865dab7631c887b0673753f59f337256bb56829ea32f30d7584b" +PKG_LICENSE="LLVM" +PKG_SITE="https://github.com/KhronosGroup/SPIRV-LLVM-Translator" +PKG_DEPENDS_HOST="toolchain:host llvm:host" +PKG_URL="https://github.com/KhronosGroup/SPIRV-LLVM-Translator/archive/v${PKG_VERSION}.tar.gz" +PKG_LONGDESC="SPIRV-LLVM-Translator" +PKG_TOOLCHAIN="cmake" diff --git a/projects/ArchR/packages/graphics/spirv-tools/package.mk b/projects/ArchR/packages/graphics/spirv-tools/package.mk new file mode 100644 index 0000000000..ec6fe99d1a --- /dev/null +++ b/projects/ArchR/packages/graphics/spirv-tools/package.mk @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present Frank Hartung (supervisedthinking (@) gmail.com) +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="spirv-tools" +# The SPIRV-Tools pkg_version needs to match the compatible (known_good) glslang pkg_version. +# https://raw.githubusercontent.com/KhronosGroup/glslang/${PKG_VERSION}/known_good.json +# When updating glslang pkg_version please update to the known_good spirv-tools pkg_version. +PKG_VERSION="4d2f0b40bfe290dea6c6904dafdf7fd8328ba346" +PKG_LICENSE="Apache-2.0" +PKG_SITE="https://github.com/KhronosGroup/SPIRV-Tools" +PKG_URL="https://github.com/KhronosGroup/SPIRV-Tools/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="toolchain:host" +PKG_DEPENDS_TARGET="toolchain" +PKG_DEPENDS_UNPACK="spirv-headers" +PKG_LONGDESC="The SPIR-V Tools project provides an API and commands for processing SPIR-V modules." + +PKG_CMAKE_OPTS_HOST="-DSPIRV_SKIP_TESTS=ON" + +pre_configure_host() { + export CXXFLAGS="${CXXFLAGS//-std=gnu17/-std=gnu++17}" +} + +post_unpack() { + mkdir -p ${PKG_BUILD}/external/spirv-headers + tar --strip-components=1 \ + -xf "${SOURCES}/spirv-headers/spirv-headers-$(get_pkg_version spirv-headers).tar.gz" \ + -C "${PKG_BUILD}/external/spirv-headers" +} diff --git a/projects/ArchR/packages/graphics/vulkan/vulkan-headers/package.mk b/projects/ArchR/packages/graphics/vulkan/vulkan-headers/package.mk new file mode 100755 index 0000000000..91ea2f6d8e --- /dev/null +++ b/projects/ArchR/packages/graphics/vulkan/vulkan-headers/package.mk @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Frank Hartung (supervisedthinking (@) gmail.com) +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="vulkan-headers" +PKG_VERSION="1.4.347" +PKG_LICENSE="Apache-2.0" +PKG_SITE="https://github.com/KhronosGroup/Vulkan-Headers" +PKG_URL="https://github.com/KhronosGroup/Vulkan-Headers/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="toolchain:host" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Vulkan Header files and API registry" + +pre_configure_target() { + PKG_CMAKE_OPTS_TARGET="-DCMAKE_BUILD_TYPE=Release" +} diff --git a/projects/ArchR/packages/graphics/vulkan/vulkan-loader/package.mk b/projects/ArchR/packages/graphics/vulkan/vulkan-loader/package.mk new file mode 100755 index 0000000000..8c64770b4e --- /dev/null +++ b/projects/ArchR/packages/graphics/vulkan/vulkan-loader/package.mk @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Frank Hartung (supervisedthinking (@) gmail.com) +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="vulkan-loader" +PKG_VERSION="1.4.347" +PKG_LICENSE="Apache-2.0" +PKG_SITE="https://github.com/KhronosGroup/Vulkan-Loader" +PKG_URL="https://github.com/KhronosGroup/Vulkan-Loader/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain Python3:host vulkan-headers libxcb libX11 libXrandr wayland" +PKG_LONGDESC="Vulkan Installable Client Driver (ICD) Loader." + +pre_configure_target() { + PKG_CMAKE_OPTS_TARGET="-DBUILD_TESTS=OFF \ + -DCMAKE_BUILD_TYPE=Release" + + # GAS / GNU Assembler is only supported by aarch64 & x86_64 + HOST_ARCH=$(uname -m) + case ${HOST_ARCH} in + arm|aarch64) + PKG_CMAKE_OPTS_TARGET+=" -DUSE_GAS=OFF" + ;; + esac + + if [ "${DISPLAYSERVER}" = "x11" ]; then + PKG_CMAKE_OPTS_TARGET+=" -DBUILD_WSI_XCB_SUPPORT=ON \ + -DBUILD_WSI_XLIB_SUPPORT=ON \ + -DBUILD_WSI_WAYLAND_SUPPORT=OFF" + elif [ "${DISPLAYSERVER}" = "wl" ]; then + PKG_CMAKE_OPTS_TARGET+=" -DBUILD_WSI_XCB_SUPPORT=ON \ + -DBUILD_WSI_XLIB_SUPPORT=ON \ + -DBUILD_WSI_WAYLAND_SUPPORT=ON" + else + PKG_CMAKE_OPTS_TARGET+=" -DBUILD_WSI_XCB_SUPPORT=OFF \ + -DBUILD_WSI_XLIB_SUPPORT=OFF \ + -DBUILD_WSI_WAYLAND_SUPPORT=OFF" + fi +} diff --git a/projects/ArchR/packages/graphics/vulkan/vulkan-tools/package.mk b/projects/ArchR/packages/graphics/vulkan/vulkan-tools/package.mk new file mode 100755 index 0000000000..83bf58e517 --- /dev/null +++ b/projects/ArchR/packages/graphics/vulkan/vulkan-tools/package.mk @@ -0,0 +1,62 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Frank Hartung (supervisedthinking (@) gmail.com) +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="vulkan-tools" +PKG_VERSION="1.4.347" +PKG_LICENSE="Apache-2.0" +PKG_SITE="https://github.com/KhronosGroup/Vulkan-Tools" +PKG_URL="https://github.com/KhronosGroup/Vulkan-tools/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain vulkan-loader glslang:host Python3:host volk wayland" +PKG_LONGDESC="This project provides Khronos official Vulkan Tools and Utilities." + +configure_package() { + # Displayserver Support + if [ "${DISPLAYSERVER}" = "x11" ]; then + PKG_DEPENDS_TARGET+=" libxcb libX11" + elif [ "${DISPLAYSERVER}" = "wl" ]; then + PKG_DEPENDS_TARGET+=" wayland" + fi +} + +pre_configure_target() { + PKG_CMAKE_OPTS_TARGET="-DVULKAN_HEADERS_INSTALL_DIR=${SYSROOT_PREFIX}/usr \ + -DBUILD_VULKANINFO=ON \ + -DBUILD_ICD=OFF \ + -DINSTALL_ICD=OFF \ + -DBUILD_WSI_DIRECTFB_SUPPORT=OFF \ + -DPython3_EXECUTABLE=${TOOLCHAIN}/bin/python3 \ + -DCMAKE_BUILD_TYPE=Release \ + -Wno-dev" + + if [ "${DISPLAYSERVER}" = "x11" ]; then + PKG_CMAKE_OPTS_TARGET+=" -DBUILD_CUBE=ON \ + -DBUILD_WSI_XCB_SUPPORT=ON \ + -DBUILD_WSI_XLIB_SUPPORT=ON \ + -DBUILD_WSI_WAYLAND_SUPPORT=OFF \ + -DCUBE_WSI_SELECTION=XCB" + elif [ "${DISPLAYSERVER}" = "wl" ]; then + PKG_CMAKE_OPTS_TARGET+=" -DBUILD_CUBE=ON \ + -DBUILD_WSI_XCB_SUPPORT=ON \ + -DBUILD_WSI_XLIB_SUPPORT=ON \ + -DBUILD_WSI_WAYLAND_SUPPORT=ON \ + -DCUBE_WSI_SELECTION=WAYLAND" + else + PKG_CMAKE_OPTS_TARGET+=" -DBUILD_CUBE=ON \ + -DBUILD_WSI_XCB_SUPPORT=OFF \ + -DBUILD_WSI_XLIB_SUPPORT=OFF \ + -DBUILD_WSI_WAYLAND_SUPPORT=OFF \ + -DCUBE_WSI_SELECTION=DISPLAY" + 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" \{} \; +} + +post_makeinstall_target() { + # Clean up - two graphic test tools are superflous + safe_remove ${INSTALL}/usr/bin/vkcubepp +} diff --git a/projects/ArchR/packages/graphics/waffle/package.mk b/projects/ArchR/packages/graphics/waffle/package.mk new file mode 100644 index 0000000000..76aeb1fc28 --- /dev/null +++ b/projects/ArchR/packages/graphics/waffle/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024-present ArchR (https://arch-r.io) +PKG_NAME="waffle" +PKG_LICENSE="BSD" +PKG_VERSION="5f1f48287e806544d745e9a8f5aed47234c61292" +PKG_SITE="https://waffle.freedesktop.org/" +PKG_URL="https://gitlab.freedesktop.org/mesa/waffle/-/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain wayland mesa Python3" +PKG_LONGDESC="Waffle - a library for selecting an OpenGL API and window system at runtime" +PKG_TOOLCHAIN="meson" + +PKG_MESON_OPTS_TARGET+=" -Dwayland=enabled \ + -Dgbm=enabled \ + -Dx11_egl=enabled \ + -Dsurfaceless_egl=enabled \ + -Dglx=enabled \ + -Dbuild-examples=false" diff --git a/projects/ArchR/packages/graphics/wxwidgets/package.mk b/projects/ArchR/packages/graphics/wxwidgets/package.mk new file mode 100644 index 0000000000..ff193ce441 --- /dev/null +++ b/projects/ArchR/packages/graphics/wxwidgets/package.mk @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="wxwidgets" +PKG_VERSION="b97aee4" +PKG_LICENSE="wxWindows Library Licence" +PKG_SITE="https://github.com/wxWidgets/wxWidgets" +PKG_URL="${PKG_SITE}.git" +PKG_GIT_CLONE_BRANCH="3.2" +PKG_DEPENDS_TARGET="toolchain zlib libpng libjpeg-turbo gdk-pixbuf gtk3 libaio" +PKG_LONGDESC="wxWidgets is a free and open source cross-platform C++ framework for writing advanced GUI applications using native controls." + +pre_configure_target(){ + PKG_CMAKE_OPTS_TARGET+=" -DCMAKE_SYSROOT=${SYSROOT_PREFIX}" + +} \ No newline at end of file diff --git a/projects/ArchR/packages/graphics/yasm/package.mk b/projects/ArchR/packages/graphics/yasm/package.mk new file mode 100644 index 0000000000..a1487f30b2 --- /dev/null +++ b/projects/ArchR/packages/graphics/yasm/package.mk @@ -0,0 +1,44 @@ +################################################################################ +# 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_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="toolchain" +PKG_LONGDESC="yasm: A complete rewrite of the NASM assembler" +PKG_TOOLCHAIN="configure" + +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" + +pre_configure_host() { + CFLAGS="${CFLAGS} -std=gnu17" +} diff --git a/projects/ArchR/packages/hardware/quirks/autostart/002-device-switch b/projects/ArchR/packages/hardware/quirks/autostart/002-device-switch new file mode 100644 index 0000000000..0fb21b9208 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/autostart/002-device-switch @@ -0,0 +1,5 @@ +#!/bin/sh + +if [ -f /sys/firmware/devicetree/base/archr,device_switch/this ]; then + echo 'DEVICE_DTB_SWITCH="true"' >>/storage/.config/profile.d/002-device_switch +fi diff --git a/projects/ArchR/packages/hardware/quirks/autostart/020-configs b/projects/ArchR/packages/hardware/quirks/autostart/020-configs new file mode 100755 index 0000000000..8828322eab --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/autostart/020-configs @@ -0,0 +1,25 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +( + + if [ -d "/usr/lib/autostart/quirks/platforms/${HW_DEVICE}/config" ] && \ + [ ! -f ".quirk-platform-configs" ] + then + tocon "Applying ${HW_DEVICE} specific configuration..." + rsync -a --exclude={es_features.cfg,es_systems.cfg} /usr/lib/autostart/quirks/platforms/"${HW_DEVICE}"/config/* /storage/.config/ 2>/dev/null + touch /storage/.quirk-platform-configs + fi + + if [ -d "/usr/lib/autostart/quirks/devices/${QUIRK_DEVICE}/config" ] && \ + [ ! -f ".quirk-device-configs" ] + then + tocon "Applying ${QUIRK_DEVICE} specific configuration..." + rsync -a --exclude={es_features.cfg,es_systems.cfg} /usr/lib/autostart/quirks/devices/"${QUIRK_DEVICE}"/config/* /storage/.config/ 2>/dev/null + touch /storage/.quirk-device-configs + fi +) & diff --git a/projects/ArchR/packages/hardware/quirks/autostart/020-rumble b/projects/ArchR/packages/hardware/quirks/autostart/020-rumble new file mode 100755 index 0000000000..a9139dc6c8 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/autostart/020-rumble @@ -0,0 +1,11 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025 ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile.d/001-functions + +RUMBLE_PATH=$(find /sys/devices/platform -type f -name rumble_enable) +if [ -f "${RUMBLE_PATH}" ]; then + RUMBLE_ENABLED=$(get_setting rumble.enabled) + [ -z "${RUMBLE_ENABLED}" ] && set_setting rumble.enabled 1 || echo "${RUMBLE_ENABLED}" > "${RUMBLE_PATH}" +fi diff --git a/projects/ArchR/packages/hardware/quirks/autostart/020-set_audio_latency b/projects/ArchR/packages/hardware/quirks/autostart/020-set_audio_latency new file mode 100644 index 0000000000..7287bb4fcd --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/autostart/020-set_audio_latency @@ -0,0 +1,11 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile.d/001-functions + +AUDIO_LATENCY=$(get_setting audiolatency) +if [ -z "${AUDIO_LATENCY}" ] +then + set_setting global.audiolatency 32 +fi diff --git a/projects/ArchR/packages/hardware/quirks/autostart/080-dual_screen_mode b/projects/ArchR/packages/hardware/quirks/autostart/080-dual_screen_mode new file mode 100644 index 0000000000..5c0e385800 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/autostart/080-dual_screen_mode @@ -0,0 +1,15 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +count=$(modetest | awk '$3 == "connected" {print $0}' | wc -l) + +if [ "$count" -eq 2 ]; then + dual_screen=true +else + dual_screen=false +fi + +cat </storage/.config/profile.d/080-dual_screen_mode +DEVICE_HAS_DUAL_SCREEN=$dual_screen +EOF diff --git a/projects/ArchR/packages/hardware/quirks/autostart/095-turbo-mode b/projects/ArchR/packages/hardware/quirks/autostart/095-turbo-mode new file mode 100755 index 0000000000..2d063b7ddd --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/autostart/095-turbo-mode @@ -0,0 +1,16 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024-present JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile.d/001-functions + +# Get Turbo Mode state. +TURBO_MODE_STATE=$(get_setting "enable.turbo-mode") +if [ ! -n "${TURBO_MODE_STATE}" ]; then + TURBO_MODE_STATE=0 + set_setting "enable.turbo-mode" "0" +fi + +# Set turbo-mode at boot +echo ${TURBO_MODE_STATE} > /sys/devices/system/cpu/cpufreq/boost diff --git a/projects/ArchR/packages/hardware/quirks/autostart/999-export b/projects/ArchR/packages/hardware/quirks/autostart/999-export new file mode 100755 index 0000000000..63d7d6b3d2 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/autostart/999-export @@ -0,0 +1,5 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +ln -sf /etc/profile.d/999-export /storage/.config/profile.d diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket ACE/001-device_config b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket ACE/001-device_config new file mode 100755 index 0000000000..c1f42ee5b5 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket ACE/001-device_config @@ -0,0 +1,7 @@ +#!/bin/sh +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/400-device_config +DEVICE_GPU_OVERCLOCK="true" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket ACE/020-set-xbox-gamepad b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket ACE/020-set-xbox-gamepad new file mode 100755 index 0000000000..ff500c740c --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket ACE/020-set-xbox-gamepad @@ -0,0 +1,16 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2025 ArchR + +# Serial device +SERIAL_DEVICE="/dev/ttyHS0" + +# Open serial device +stty -F $SERIAL_DEVICE 115200 -clocal -opost -isig -icanon -echo + +# Send frame to switch gamepad to fake xbox 360 controller +printf "\xe7\x55\x05\x01\x00\x00\x00\x00\x00\x5b\xed" >$SERIAL_DEVICE +sleep 0.1 +printf "\x35\x35\x30\x35\x30\x31\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30" >$SERIAL_DEVICE +sleep 0.1 diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket ACE/400-set_gpu_overclock b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket ACE/400-set_gpu_overclock new file mode 100755 index 0000000000..d2759642e0 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket ACE/400-set_gpu_overclock @@ -0,0 +1,22 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +# Get GPU overclock state +GPU_OC_STATE=$(get_setting "enable.gpu-overclock") +if [ ! -n "${GPU_OC_STATE}" ]; then + GPU_OC_STATE="disable" + set_setting "enable.gpu-overclock" "0" +elif [ "${GPU_OC_STATE}" = 1 ]; then + GPU_OC_STATE="enable" +else + GPU_OC_STATE="disable" + set_setting "enable.gpu-overclock" "0" +fi + +# Set GPU OC state +/usr/lib/autostart/quirks/platforms/SM8550/bin/gpu_overclock ${GPU_OC_STATE} diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket ACE/bin/battery_led_status b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket ACE/bin/battery_led_status new file mode 100644 index 0000000000..240448a475 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket ACE/bin/battery_led_status @@ -0,0 +1,108 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +# Simple script to watch the battery capacity and +# turn the power LED orange when it reaches 30%, red at 20%, and blinking red at 10% + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +LED_PATH="/sys/class/leds" + +function led_brightness() { + echo ${2} >${LED_PATH}/${1}/brightness +} + +function led_rgb() { + echo ${2} ${3} ${4} >${LED_PATH}/${1}/multi_intensity +} + +function bat_led_off() { + led_brightness power-led 0 + led_rgb power-led 0 0 0 +} + +function bat_led_green() { + led_brightness power-led 255 + led_rgb power-led 0 255 0 +} + +function bat_led_red() { + led_brightness power-led 255 + led_rgb power-led 255 0 0 +} + +function bat_led_orange() { + led_brightness power-led 255 + led_rgb power-led 255 20 0 +} + +function bat_led_yellow() { + led_brightness power-led 255 + led_rgb power-led 255 125 0 +} + +PREV_BATCAP="null" +while true + do + BAT_LED_STATE=$(get_setting led.color) + if [ ! ${BAT_LED_STATE} == "battery" ]; then + break + fi + + 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 + bat_led_red + sleep .5 + bat_led_off + sleep .5 + done + continue + elif (( ${CAP} <= 20 )) + then + BATCAP="D_RED" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_red + fi + elif (( ${CAP} <= 30 )) + then + BATCAP="D_ORANGE" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_orange + fi + elif (( ${CAP} <= 40 )) + then + BATCAP="D_YELLOW" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_yellow + fi + else + BATCAP="D_GREEN" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_green + fi + fi + elif (( ${CAP} <= 94 )) + then + BATCAP="C_ORANGE" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_orange + fi + elif (( ${CAP} >= 95 )) + then + BATCAP="C_GREEN" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_green + fi + fi + PREV_BATCAP=${BATCAP} + sleep 15 +done diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket ACE/bin/ledcontrol b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket ACE/bin/ledcontrol new file mode 100644 index 0000000000..3f2da3849a --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket ACE/bin/ledcontrol @@ -0,0 +1,113 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +LED_PATH="/sys/class/leds" + +function led_brightness() { + echo ${2} >${LED_PATH}/${1}/brightness +} + +function led_rgb() { + echo ${2} ${3} ${4} >${LED_PATH}/${1}/multi_intensity +} + +function led_off() { + led_brightness power-led 0 + led_rgb power-led 0 0 0 +} + +function led_red() { + led_brightness power-led 255 + led_rgb power-led 255 0 0 +} + +function led_green() { + led_brightness power-led 255 + led_rgb power-led 0 255 0 +} + +function led_blue() { + led_brightness power-led 255 + led_rgb power-led 0 0 255 +} + +function led_white() { + led_brightness power-led 255 + led_rgb power-led 255 255 255 +} + +function led_orange() { + led_brightness power-led 255 + led_rgb power-led 255 20 0 +} + +function led_yellow() { + led_brightness power-led 255 + led_rgb power-led 255 125 0 +} + +function led_purple() { + led_brightness power-led 255 + led_rgb power-led 255 0 255 +} + +case ${1} in + red) + led_red + set_setting led.color ${1} + ;; + green) + led_green + set_setting led.color ${1} + ;; + blue) + led_blue + set_setting led.color ${1} + ;; + white) + led_white + set_setting led.color ${1} + ;; + orange) + led_orange + set_setting led.color ${1} + ;; + yellow) + led_yellow + set_setting led.color ${1} + ;; + purple) + led_purple + set_setting led.color ${1} + ;; + off) + led_off + set_setting led.color ${1} + ;; + battery) + led_off + set_setting led.color ${1} + systemctl restart batteryledstatus.service + ;; + poweroff) + led_off + ;; + list) +cat </storage/.config/profile.d/010-analog_sticks_led_control +DEVICE_ANALOG_STICKS_LED_CONTROL="true" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket DMG/020-set-xbox-gamepad b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket DMG/020-set-xbox-gamepad new file mode 120000 index 0000000000..4a6b5a7a79 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket DMG/020-set-xbox-gamepad @@ -0,0 +1 @@ +../AYANEO Pocket ACE/020-set-xbox-gamepad \ No newline at end of file diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket DMG/400-set_gpu_overclock b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket DMG/400-set_gpu_overclock new file mode 120000 index 0000000000..d44c8918d9 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket DMG/400-set_gpu_overclock @@ -0,0 +1 @@ +../AYANEO Pocket ACE/400-set_gpu_overclock \ No newline at end of file diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket DMG/bin/achievements b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket DMG/bin/achievements new file mode 120000 index 0000000000..48d72fd830 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket DMG/bin/achievements @@ -0,0 +1 @@ +../../AYN Odin 2/bin/achievements \ No newline at end of file diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket DMG/bin/analog_sticks_ledcontrol b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket DMG/bin/analog_sticks_ledcontrol new file mode 100755 index 0000000000..84ca3eb577 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket DMG/bin/analog_sticks_ledcontrol @@ -0,0 +1,69 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2025 ArchR + +# Serial device +SERIAL_DEVICE="/dev/ttyHS0" + +# Display usage if wrong parameters +if [ $# -lt 4 ]; then + echo "Usage: $0 " + echo "Example: $0 255 255 0 0" + exit 1 +fi + +BRIGHTNESS=$1 +R=$2 +G=$3 +B=$4 + +# Validate range +for val in "$R" "$G" "$B"; do + if ! [ "$val" -ge 0 ] || ! [ "$val" -le 255 ]; then + echo "RGB values must be 0-255" + exit 1 + fi +done + +# Convert to hex +BRIGHTNESS_HEX=$(printf "%02X" $BRIGHTNESS) +R_HEX=$(printf "%02X" $R) +G_HEX=$(printf "%02X" $G) +B_HEX=$(printf "%02X" $B) + +# Function to calculate checksum +calculate_checksum() { + local sum=0 + for byte in "$@"; do + sum=$((sum + byte)) + done + echo $((sum & 0xFF)) +} + +# Open serial device +exec 20<>$SERIAL_DEVICE +stty -F $SERIAL_DEVICE 115200 -opost -isig -icanon -echo + +# Construct payload (without STX and checksum) +payload=(0x00 0x1C 0x20 0x01 0x80 0x00 0x81 0x00 0x8B 0x0F 0x88 0x$R_HEX 0x89 0x$G_HEX 0x8A 0x$B_HEX 0x86 0xFF 0x87 0x$BRIGHTNESS_HEX 0x58 0x02 0x45 0x00) + +# Calculate checksum +CHECKSUM=$(calculate_checksum "${payload[@]}") + +# Construct full frame: STX + payload + checksum + ETX +STX=0xF7 +ETX=0xED +FRAME=($STX "${payload[@]}" $CHECKSUM $ETX) + +# Convert to \x.. string +CMD="" +for b in "${FRAME[@]}"; do + CMD+="\\x$(printf '%02X' $b)" +done + +# Send frame +echo -ne "$CMD" > $SERIAL_DEVICE + +# Close serial device +exec 20>&- diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket DMG/bin/battery_led_status b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket DMG/bin/battery_led_status new file mode 120000 index 0000000000..a065c33d0c --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket DMG/bin/battery_led_status @@ -0,0 +1 @@ +../../AYANEO Pocket ACE/bin/battery_led_status \ No newline at end of file diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket DMG/bin/ledcontrol b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket DMG/bin/ledcontrol new file mode 120000 index 0000000000..982f897c47 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket DMG/bin/ledcontrol @@ -0,0 +1 @@ +../../AYANEO Pocket ACE/bin/ledcontrol \ No newline at end of file diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket DS/020-fan_control b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket DS/020-fan_control new file mode 100644 index 0000000000..6a2e58cdaf --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket DS/020-fan_control @@ -0,0 +1,12 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025 ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/020-fan_control + +FANPATH="\$(ls /sys/class/hwmon/hwmon*/pwm1 | grep hwmon | cut -c 18-24)" + +DEVICE_HAS_FAN="true" +DEVICE_PWM_FAN="/sys/class/hwmon/\${FANPATH}/pwm1" +DEVICE_FAN_INPUT="/sys/class/hwmon/\${FANPATH}/pwm1" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket DS/020-set-xbox-gamepad b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket DS/020-set-xbox-gamepad new file mode 120000 index 0000000000..4a6b5a7a79 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket DS/020-set-xbox-gamepad @@ -0,0 +1 @@ +../AYANEO Pocket ACE/020-set-xbox-gamepad \ No newline at end of file diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket DS/bin/battery_led_status b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket DS/bin/battery_led_status new file mode 100644 index 0000000000..240448a475 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket DS/bin/battery_led_status @@ -0,0 +1,108 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +# Simple script to watch the battery capacity and +# turn the power LED orange when it reaches 30%, red at 20%, and blinking red at 10% + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +LED_PATH="/sys/class/leds" + +function led_brightness() { + echo ${2} >${LED_PATH}/${1}/brightness +} + +function led_rgb() { + echo ${2} ${3} ${4} >${LED_PATH}/${1}/multi_intensity +} + +function bat_led_off() { + led_brightness power-led 0 + led_rgb power-led 0 0 0 +} + +function bat_led_green() { + led_brightness power-led 255 + led_rgb power-led 0 255 0 +} + +function bat_led_red() { + led_brightness power-led 255 + led_rgb power-led 255 0 0 +} + +function bat_led_orange() { + led_brightness power-led 255 + led_rgb power-led 255 20 0 +} + +function bat_led_yellow() { + led_brightness power-led 255 + led_rgb power-led 255 125 0 +} + +PREV_BATCAP="null" +while true + do + BAT_LED_STATE=$(get_setting led.color) + if [ ! ${BAT_LED_STATE} == "battery" ]; then + break + fi + + 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 + bat_led_red + sleep .5 + bat_led_off + sleep .5 + done + continue + elif (( ${CAP} <= 20 )) + then + BATCAP="D_RED" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_red + fi + elif (( ${CAP} <= 30 )) + then + BATCAP="D_ORANGE" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_orange + fi + elif (( ${CAP} <= 40 )) + then + BATCAP="D_YELLOW" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_yellow + fi + else + BATCAP="D_GREEN" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_green + fi + fi + elif (( ${CAP} <= 94 )) + then + BATCAP="C_ORANGE" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_orange + fi + elif (( ${CAP} >= 95 )) + then + BATCAP="C_GREEN" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_green + fi + fi + PREV_BATCAP=${BATCAP} + sleep 15 +done diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket DS/bin/ledcontrol b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket DS/bin/ledcontrol new file mode 100644 index 0000000000..3f2da3849a --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket DS/bin/ledcontrol @@ -0,0 +1,113 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +LED_PATH="/sys/class/leds" + +function led_brightness() { + echo ${2} >${LED_PATH}/${1}/brightness +} + +function led_rgb() { + echo ${2} ${3} ${4} >${LED_PATH}/${1}/multi_intensity +} + +function led_off() { + led_brightness power-led 0 + led_rgb power-led 0 0 0 +} + +function led_red() { + led_brightness power-led 255 + led_rgb power-led 255 0 0 +} + +function led_green() { + led_brightness power-led 255 + led_rgb power-led 0 255 0 +} + +function led_blue() { + led_brightness power-led 255 + led_rgb power-led 0 0 255 +} + +function led_white() { + led_brightness power-led 255 + led_rgb power-led 255 255 255 +} + +function led_orange() { + led_brightness power-led 255 + led_rgb power-led 255 20 0 +} + +function led_yellow() { + led_brightness power-led 255 + led_rgb power-led 255 125 0 +} + +function led_purple() { + led_brightness power-led 255 + led_rgb power-led 255 0 255 +} + +case ${1} in + red) + led_red + set_setting led.color ${1} + ;; + green) + led_green + set_setting led.color ${1} + ;; + blue) + led_blue + set_setting led.color ${1} + ;; + white) + led_white + set_setting led.color ${1} + ;; + orange) + led_orange + set_setting led.color ${1} + ;; + yellow) + led_yellow + set_setting led.color ${1} + ;; + purple) + led_purple + set_setting led.color ${1} + ;; + off) + led_off + set_setting led.color ${1} + ;; + battery) + led_off + set_setting led.color ${1} + systemctl restart batteryledstatus.service + ;; + poweroff) + led_off + ;; + list) +cat </storage/.config/profile.d/010-analog_sticks_led_control +DEVICE_ANALOG_STICKS_LED_CONTROL="true" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket EVO/020-set-xbox-gamepad b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket EVO/020-set-xbox-gamepad new file mode 120000 index 0000000000..4a6b5a7a79 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket EVO/020-set-xbox-gamepad @@ -0,0 +1 @@ +../AYANEO Pocket ACE/020-set-xbox-gamepad \ No newline at end of file diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket EVO/400-set_gpu_overclock b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket EVO/400-set_gpu_overclock new file mode 120000 index 0000000000..d44c8918d9 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket EVO/400-set_gpu_overclock @@ -0,0 +1 @@ +../AYANEO Pocket ACE/400-set_gpu_overclock \ No newline at end of file diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket EVO/bin/achievements b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket EVO/bin/achievements new file mode 120000 index 0000000000..48d72fd830 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket EVO/bin/achievements @@ -0,0 +1 @@ +../../AYN Odin 2/bin/achievements \ No newline at end of file diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket EVO/bin/analog_sticks_ledcontrol b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket EVO/bin/analog_sticks_ledcontrol new file mode 100755 index 0000000000..84ca3eb577 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket EVO/bin/analog_sticks_ledcontrol @@ -0,0 +1,69 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2025 ArchR + +# Serial device +SERIAL_DEVICE="/dev/ttyHS0" + +# Display usage if wrong parameters +if [ $# -lt 4 ]; then + echo "Usage: $0 " + echo "Example: $0 255 255 0 0" + exit 1 +fi + +BRIGHTNESS=$1 +R=$2 +G=$3 +B=$4 + +# Validate range +for val in "$R" "$G" "$B"; do + if ! [ "$val" -ge 0 ] || ! [ "$val" -le 255 ]; then + echo "RGB values must be 0-255" + exit 1 + fi +done + +# Convert to hex +BRIGHTNESS_HEX=$(printf "%02X" $BRIGHTNESS) +R_HEX=$(printf "%02X" $R) +G_HEX=$(printf "%02X" $G) +B_HEX=$(printf "%02X" $B) + +# Function to calculate checksum +calculate_checksum() { + local sum=0 + for byte in "$@"; do + sum=$((sum + byte)) + done + echo $((sum & 0xFF)) +} + +# Open serial device +exec 20<>$SERIAL_DEVICE +stty -F $SERIAL_DEVICE 115200 -opost -isig -icanon -echo + +# Construct payload (without STX and checksum) +payload=(0x00 0x1C 0x20 0x01 0x80 0x00 0x81 0x00 0x8B 0x0F 0x88 0x$R_HEX 0x89 0x$G_HEX 0x8A 0x$B_HEX 0x86 0xFF 0x87 0x$BRIGHTNESS_HEX 0x58 0x02 0x45 0x00) + +# Calculate checksum +CHECKSUM=$(calculate_checksum "${payload[@]}") + +# Construct full frame: STX + payload + checksum + ETX +STX=0xF7 +ETX=0xED +FRAME=($STX "${payload[@]}" $CHECKSUM $ETX) + +# Convert to \x.. string +CMD="" +for b in "${FRAME[@]}"; do + CMD+="\\x$(printf '%02X' $b)" +done + +# Send frame +echo -ne "$CMD" > $SERIAL_DEVICE + +# Close serial device +exec 20>&- diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket EVO/bin/battery_led_status b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket EVO/bin/battery_led_status new file mode 100644 index 0000000000..7c23846c99 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket EVO/bin/battery_led_status @@ -0,0 +1,113 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +# Simple script to watch the battery capacity and +# turn the power LED orange when it reaches 30%, red at 20%, and blinking red at 10% + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +LED_PATH="/sys/class/leds" + +function led_brightness() { + echo ${2} >${LED_PATH}/${1}/brightness +} + +function led_rgb() { + echo ${2} ${3} ${4} >${LED_PATH}/${1}/multi_intensity +} + +function bat_led_off() { + led_brightness power-led 0 + led_rgb power-led 0 0 0 + /usr/bin/analog_sticks_ledcontrol 0 0 0 0 +} + +function bat_led_green() { + led_brightness power-led 255 + led_rgb power-led 0 255 0 + /usr/bin/analog_sticks_ledcontrol 255 0 255 0 +} + +function bat_led_red() { + led_brightness power-led 255 + led_rgb power-led 255 0 0 + /usr/bin/analog_sticks_ledcontrol 255 255 0 0 +} + +function bat_led_orange() { + led_brightness power-led 255 + led_rgb power-led 255 20 0 + /usr/bin/analog_sticks_ledcontrol 255 255 20 0 +} + +function bat_led_yellow() { + led_brightness power-led 255 + led_rgb power-led 255 125 0 + /usr/bin/analog_sticks_ledcontrol 255 255 125 0 +} + +PREV_BATCAP="null" +while true + do + BAT_LED_STATE=$(get_setting led.color) + if [ ! ${BAT_LED_STATE} == "battery" ]; then + break + fi + + 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 + bat_led_red + sleep .5 + bat_led_off + sleep .5 + done + continue + elif (( ${CAP} <= 20 )) + then + BATCAP="D_RED" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_red + fi + elif (( ${CAP} <= 30 )) + then + BATCAP="D_ORANGE" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_orange + fi + elif (( ${CAP} <= 40 )) + then + BATCAP="D_YELLOW" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_yellow + fi + else + BATCAP="D_GREEN" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_green + fi + fi + elif (( ${CAP} <= 94 )) + then + BATCAP="C_ORANGE" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_orange + fi + elif (( ${CAP} >= 95 )) + then + BATCAP="C_GREEN" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_green + fi + fi + PREV_BATCAP=${BATCAP} + sleep 15 +done diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket EVO/bin/ledcontrol b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket EVO/bin/ledcontrol new file mode 100644 index 0000000000..0809d9d193 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket EVO/bin/ledcontrol @@ -0,0 +1,126 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +LED_PATH="/sys/class/leds" + +function led_brightness() { + echo ${2} >${LED_PATH}/${1}/brightness +} + +function led_rgb() { + echo ${2} ${3} ${4} >${LED_PATH}/${1}/multi_intensity +} + +function led_off() { + led_brightness power-led 0 + led_rgb power-led 0 0 0 + /usr/bin/analog_sticks_ledcontrol 0 0 0 0 +} + +function led_red() { + led_brightness power-led 255 + led_rgb power-led 255 0 0 + /usr/bin/analog_sticks_ledcontrol 255 255 0 0 +} + +function led_green() { + led_brightness power-led 255 + led_rgb power-led 0 255 0 + /usr/bin/analog_sticks_ledcontrol 255 0 255 0 +} + +function led_blue() { + led_brightness power-led 255 + led_rgb power-led 0 0 255 + /usr/bin/analog_sticks_ledcontrol 255 0 0 255 +} + +function led_white() { + led_brightness power-led 255 + led_rgb power-led 255 255 255 + /usr/bin/analog_sticks_ledcontrol 255 255 255 255 +} + +function led_orange() { + led_brightness power-led 255 + led_rgb power-led 255 20 0 + /usr/bin/analog_sticks_ledcontrol 255 255 20 0 +} + +function led_yellow() { + led_brightness power-led 255 + led_rgb power-led 255 125 0 + /usr/bin/analog_sticks_ledcontrol 255 255 125 0 +} + +function led_purple() { + led_brightness power-led 255 + led_rgb power-led 255 0 255 + /usr/bin/analog_sticks_ledcontrol 255 255 0 255 +} + +case ${1} in + red) + led_red + set_setting led.color ${1} + ;; + green) + led_green + set_setting led.color ${1} + ;; + blue) + led_blue + set_setting led.color ${1} + ;; + white) + led_white + set_setting led.color ${1} + ;; + orange) + led_orange + set_setting led.color ${1} + ;; + yellow) + led_yellow + set_setting led.color ${1} + ;; + purple) + led_purple + set_setting led.color ${1} + ;; + off) + led_off + set_setting led.color ${1} + ;; + rgb) + LEDS_CONFIG=$(get_setting analogsticks.led) + /usr/bin/analog_sticks_ledcontrol ${LEDS_CONFIG} + set_setting led.color ${1} + ;; + battery) + led_off + set_setting led.color ${1} + systemctl restart batteryledstatus.service + ;; + poweroff) + led_off + ;; + list) +cat </storage/.config/profile.d/400-device_config +DEVICE_GPU_OVERCLOCK="true" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket S 2K/020-set-xbox-gamepad b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket S 2K/020-set-xbox-gamepad new file mode 100755 index 0000000000..ff500c740c --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket S 2K/020-set-xbox-gamepad @@ -0,0 +1,16 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2025 ArchR + +# Serial device +SERIAL_DEVICE="/dev/ttyHS0" + +# Open serial device +stty -F $SERIAL_DEVICE 115200 -clocal -opost -isig -icanon -echo + +# Send frame to switch gamepad to fake xbox 360 controller +printf "\xe7\x55\x05\x01\x00\x00\x00\x00\x00\x5b\xed" >$SERIAL_DEVICE +sleep 0.1 +printf "\x35\x35\x30\x35\x30\x31\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30" >$SERIAL_DEVICE +sleep 0.1 diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket S 2K/050-game-configs b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket S 2K/050-game-configs new file mode 100755 index 0000000000..909e82fcab --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket S 2K/050-game-configs @@ -0,0 +1,7 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +#Disable retroarch microphone and set default audio driver to pulse +sed -i '/^microphone_enable =/c\microphone_enable = "false"' /storage/.config/retroarch/retroarch.cfg +sed -i '/^audio_driver =/c\audio_driver = "pulse"' /storage/.config/retroarch/retroarch.cfg diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket S 2K/400-set_gpu_overclock b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket S 2K/400-set_gpu_overclock new file mode 100755 index 0000000000..d2759642e0 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket S 2K/400-set_gpu_overclock @@ -0,0 +1,22 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +# Get GPU overclock state +GPU_OC_STATE=$(get_setting "enable.gpu-overclock") +if [ ! -n "${GPU_OC_STATE}" ]; then + GPU_OC_STATE="disable" + set_setting "enable.gpu-overclock" "0" +elif [ "${GPU_OC_STATE}" = 1 ]; then + GPU_OC_STATE="enable" +else + GPU_OC_STATE="disable" + set_setting "enable.gpu-overclock" "0" +fi + +# Set GPU OC state +/usr/lib/autostart/quirks/platforms/SM8550/bin/gpu_overclock ${GPU_OC_STATE} diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket S 2K/bin/battery_led_status b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket S 2K/bin/battery_led_status new file mode 100644 index 0000000000..240448a475 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket S 2K/bin/battery_led_status @@ -0,0 +1,108 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +# Simple script to watch the battery capacity and +# turn the power LED orange when it reaches 30%, red at 20%, and blinking red at 10% + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +LED_PATH="/sys/class/leds" + +function led_brightness() { + echo ${2} >${LED_PATH}/${1}/brightness +} + +function led_rgb() { + echo ${2} ${3} ${4} >${LED_PATH}/${1}/multi_intensity +} + +function bat_led_off() { + led_brightness power-led 0 + led_rgb power-led 0 0 0 +} + +function bat_led_green() { + led_brightness power-led 255 + led_rgb power-led 0 255 0 +} + +function bat_led_red() { + led_brightness power-led 255 + led_rgb power-led 255 0 0 +} + +function bat_led_orange() { + led_brightness power-led 255 + led_rgb power-led 255 20 0 +} + +function bat_led_yellow() { + led_brightness power-led 255 + led_rgb power-led 255 125 0 +} + +PREV_BATCAP="null" +while true + do + BAT_LED_STATE=$(get_setting led.color) + if [ ! ${BAT_LED_STATE} == "battery" ]; then + break + fi + + 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 + bat_led_red + sleep .5 + bat_led_off + sleep .5 + done + continue + elif (( ${CAP} <= 20 )) + then + BATCAP="D_RED" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_red + fi + elif (( ${CAP} <= 30 )) + then + BATCAP="D_ORANGE" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_orange + fi + elif (( ${CAP} <= 40 )) + then + BATCAP="D_YELLOW" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_yellow + fi + else + BATCAP="D_GREEN" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_green + fi + fi + elif (( ${CAP} <= 94 )) + then + BATCAP="C_ORANGE" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_orange + fi + elif (( ${CAP} >= 95 )) + then + BATCAP="C_GREEN" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_green + fi + fi + PREV_BATCAP=${BATCAP} + sleep 15 +done diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket S 2K/bin/ledcontrol b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket S 2K/bin/ledcontrol new file mode 100644 index 0000000000..3f2da3849a --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket S 2K/bin/ledcontrol @@ -0,0 +1,113 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +LED_PATH="/sys/class/leds" + +function led_brightness() { + echo ${2} >${LED_PATH}/${1}/brightness +} + +function led_rgb() { + echo ${2} ${3} ${4} >${LED_PATH}/${1}/multi_intensity +} + +function led_off() { + led_brightness power-led 0 + led_rgb power-led 0 0 0 +} + +function led_red() { + led_brightness power-led 255 + led_rgb power-led 255 0 0 +} + +function led_green() { + led_brightness power-led 255 + led_rgb power-led 0 255 0 +} + +function led_blue() { + led_brightness power-led 255 + led_rgb power-led 0 0 255 +} + +function led_white() { + led_brightness power-led 255 + led_rgb power-led 255 255 255 +} + +function led_orange() { + led_brightness power-led 255 + led_rgb power-led 255 20 0 +} + +function led_yellow() { + led_brightness power-led 255 + led_rgb power-led 255 125 0 +} + +function led_purple() { + led_brightness power-led 255 + led_rgb power-led 255 0 255 +} + +case ${1} in + red) + led_red + set_setting led.color ${1} + ;; + green) + led_green + set_setting led.color ${1} + ;; + blue) + led_blue + set_setting led.color ${1} + ;; + white) + led_white + set_setting led.color ${1} + ;; + orange) + led_orange + set_setting led.color ${1} + ;; + yellow) + led_yellow + set_setting led.color ${1} + ;; + purple) + led_purple + set_setting led.color ${1} + ;; + off) + led_off + set_setting led.color ${1} + ;; + battery) + led_off + set_setting led.color ${1} + systemctl restart batteryledstatus.service + ;; + poweroff) + led_off + ;; + list) +cat </storage/.config/profile.d/400-device_config +DEVICE_GPU_OVERCLOCK="true" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket S2/020-set-xbox-gamepad b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket S2/020-set-xbox-gamepad new file mode 100755 index 0000000000..ff500c740c --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket S2/020-set-xbox-gamepad @@ -0,0 +1,16 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2025 ArchR + +# Serial device +SERIAL_DEVICE="/dev/ttyHS0" + +# Open serial device +stty -F $SERIAL_DEVICE 115200 -clocal -opost -isig -icanon -echo + +# Send frame to switch gamepad to fake xbox 360 controller +printf "\xe7\x55\x05\x01\x00\x00\x00\x00\x00\x5b\xed" >$SERIAL_DEVICE +sleep 0.1 +printf "\x35\x35\x30\x35\x30\x31\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30" >$SERIAL_DEVICE +sleep 0.1 diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket S2/050-game-configs b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket S2/050-game-configs new file mode 100755 index 0000000000..909e82fcab --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket S2/050-game-configs @@ -0,0 +1,7 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +#Disable retroarch microphone and set default audio driver to pulse +sed -i '/^microphone_enable =/c\microphone_enable = "false"' /storage/.config/retroarch/retroarch.cfg +sed -i '/^audio_driver =/c\audio_driver = "pulse"' /storage/.config/retroarch/retroarch.cfg diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket S2/400-set_gpu_overclock b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket S2/400-set_gpu_overclock new file mode 100755 index 0000000000..9a7f55dcf9 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket S2/400-set_gpu_overclock @@ -0,0 +1,22 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +# Get GPU overclock state +GPU_OC_STATE=$(get_setting "enable.gpu-overclock") +if [ ! -n "${GPU_OC_STATE}" ]; then + GPU_OC_STATE="disable" + set_setting "enable.gpu-overclock" "0" +elif [ "${GPU_OC_STATE}" = 1 ]; then + GPU_OC_STATE="enable" +else + GPU_OC_STATE="disable" + set_setting "enable.gpu-overclock" "0" +fi + +# Set GPU OC state +/usr/lib/autostart/quirks/platforms/SM8650/bin/gpu_overclock ${GPU_OC_STATE} diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket S2/bin/battery_led_status b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket S2/bin/battery_led_status new file mode 100644 index 0000000000..240448a475 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket S2/bin/battery_led_status @@ -0,0 +1,108 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +# Simple script to watch the battery capacity and +# turn the power LED orange when it reaches 30%, red at 20%, and blinking red at 10% + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +LED_PATH="/sys/class/leds" + +function led_brightness() { + echo ${2} >${LED_PATH}/${1}/brightness +} + +function led_rgb() { + echo ${2} ${3} ${4} >${LED_PATH}/${1}/multi_intensity +} + +function bat_led_off() { + led_brightness power-led 0 + led_rgb power-led 0 0 0 +} + +function bat_led_green() { + led_brightness power-led 255 + led_rgb power-led 0 255 0 +} + +function bat_led_red() { + led_brightness power-led 255 + led_rgb power-led 255 0 0 +} + +function bat_led_orange() { + led_brightness power-led 255 + led_rgb power-led 255 20 0 +} + +function bat_led_yellow() { + led_brightness power-led 255 + led_rgb power-led 255 125 0 +} + +PREV_BATCAP="null" +while true + do + BAT_LED_STATE=$(get_setting led.color) + if [ ! ${BAT_LED_STATE} == "battery" ]; then + break + fi + + 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 + bat_led_red + sleep .5 + bat_led_off + sleep .5 + done + continue + elif (( ${CAP} <= 20 )) + then + BATCAP="D_RED" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_red + fi + elif (( ${CAP} <= 30 )) + then + BATCAP="D_ORANGE" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_orange + fi + elif (( ${CAP} <= 40 )) + then + BATCAP="D_YELLOW" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_yellow + fi + else + BATCAP="D_GREEN" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_green + fi + fi + elif (( ${CAP} <= 94 )) + then + BATCAP="C_ORANGE" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_orange + fi + elif (( ${CAP} >= 95 )) + then + BATCAP="C_GREEN" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_green + fi + fi + PREV_BATCAP=${BATCAP} + sleep 15 +done diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket S2/bin/ledcontrol b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket S2/bin/ledcontrol new file mode 100644 index 0000000000..3f2da3849a --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYANEO Pocket S2/bin/ledcontrol @@ -0,0 +1,113 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +LED_PATH="/sys/class/leds" + +function led_brightness() { + echo ${2} >${LED_PATH}/${1}/brightness +} + +function led_rgb() { + echo ${2} ${3} ${4} >${LED_PATH}/${1}/multi_intensity +} + +function led_off() { + led_brightness power-led 0 + led_rgb power-led 0 0 0 +} + +function led_red() { + led_brightness power-led 255 + led_rgb power-led 255 0 0 +} + +function led_green() { + led_brightness power-led 255 + led_rgb power-led 0 255 0 +} + +function led_blue() { + led_brightness power-led 255 + led_rgb power-led 0 0 255 +} + +function led_white() { + led_brightness power-led 255 + led_rgb power-led 255 255 255 +} + +function led_orange() { + led_brightness power-led 255 + led_rgb power-led 255 20 0 +} + +function led_yellow() { + led_brightness power-led 255 + led_rgb power-led 255 125 0 +} + +function led_purple() { + led_brightness power-led 255 + led_rgb power-led 255 0 255 +} + +case ${1} in + red) + led_red + set_setting led.color ${1} + ;; + green) + led_green + set_setting led.color ${1} + ;; + blue) + led_blue + set_setting led.color ${1} + ;; + white) + led_white + set_setting led.color ${1} + ;; + orange) + led_orange + set_setting led.color ${1} + ;; + yellow) + led_yellow + set_setting led.color ${1} + ;; + purple) + led_purple + set_setting led.color ${1} + ;; + off) + led_off + set_setting led.color ${1} + ;; + battery) + led_off + set_setting led.color ${1} + systemctl restart batteryledstatus.service + ;; + poweroff) + led_off + ;; + list) +cat </storage/.config/profile.d/010-analog_sticks_led_control +DEVICE_ANALOG_STICKS_LED_CONTROL="true" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYN Odin 2 Portal/050-game-configs b/projects/ArchR/packages/hardware/quirks/devices/AYN Odin 2 Portal/050-game-configs new file mode 100644 index 0000000000..909e82fcab --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYN Odin 2 Portal/050-game-configs @@ -0,0 +1,7 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +#Disable retroarch microphone and set default audio driver to pulse +sed -i '/^microphone_enable =/c\microphone_enable = "false"' /storage/.config/retroarch/retroarch.cfg +sed -i '/^audio_driver =/c\audio_driver = "pulse"' /storage/.config/retroarch/retroarch.cfg diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYN Odin 2 Portal/bin/analog_sticks_ledcontrol b/projects/ArchR/packages/hardware/quirks/devices/AYN Odin 2 Portal/bin/analog_sticks_ledcontrol new file mode 100644 index 0000000000..d848333528 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYN Odin 2 Portal/bin/analog_sticks_ledcontrol @@ -0,0 +1,45 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2025 ArchR (https://github.com/archr-linux/Arch-R) + +# Simple script to set led brightness and rgb color based on +# brightness and rgb values from emulation station + +LED_PATH="/sys/devices/platform/" + +function led_brightness() { + n=1 + while [ "$n" -lt 4 ]; do + echo ${2} > ${LED_PATH}/multi-led${1}${n}/leds/rgb:${1}${n}/brightness + n=$(( n + 1 )) + done +} + +function led_rgb() { + n=1 + while [ "$n" -lt 4 ]; do + echo ${2} ${3} ${4} > ${LED_PATH}/multi-led${1}${n}/leds/rgb:${1}${n}/multi_intensity + n=$(( n + 1 )) + done +} + +# Display usage if no parameters are provided +if [ $# -ne 7 ]; then + echo "Usage: $0 " + echo "Example: $0 255 255 0 0 0 0 255" + exit 1 +fi + +BRIGHTNESS=$1 +RIGHT_RED=$2 +RIGHT_GREEN=$3 +RIGHT_BLUE=$4 +LEFT_RED=$5 +LEFT_GREEN=$6 +LEFT_BLUE=$7 + +led_brightness l $BRIGHTNESS +led_rgb l $LEFT_BLUE $LEFT_GREEN $LEFT_RED +led_brightness r $BRIGHTNESS +led_rgb r $RIGHT_BLUE $RIGHT_GREEN $RIGHT_RED diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYN Odin 2 Portal/bin/battery_led_status b/projects/ArchR/packages/hardware/quirks/devices/AYN Odin 2 Portal/bin/battery_led_status new file mode 100644 index 0000000000..09f5a20f73 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYN Odin 2 Portal/bin/battery_led_status @@ -0,0 +1,128 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +# Simple script to watch the battery capacity and +# turn the power LED orange when it reaches 30%, red at 20%, and blinking red at 10% + +. /etc/profile + +LED_PATH="/sys/devices/platform/" + +function bat_led_off() { + n=1 + while [ "$n" -lt 4 ]; do + echo 0 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/brightness + echo 0 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/brightness + echo 0 0 0 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/multi_intensity + echo 0 0 0 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/multi_intensity + n=$(( n + 1 )) + done +} + +function bat_led_red() { + n=1 + while [ "$n" -lt 4 ]; do + echo 255 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/brightness + echo 255 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/brightness + echo 0 0 255 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/multi_intensity + echo 0 0 255 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/multi_intensity + n=$(( n + 1 )) + done +} + +function bat_led_green() { + n=1 + while [ "$n" -lt 4 ]; do + echo 255 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/brightness + echo 255 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/brightness + echo 0 255 0 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/multi_intensity + echo 0 255 0 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/multi_intensity + n=$(( n + 1 )) + done +} + +function bat_led_orange() { + n=1 + while [ "$n" -lt 4 ]; do + echo 255 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/brightness + echo 255 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/brightness + echo 0 20 255 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/multi_intensity + echo 0 20 255 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/multi_intensity + n=$(( n + 1 )) + done +} + +function bat_led_yellow() { + n=1 + while [ "$n" -lt 4 ]; do + echo 255 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/brightness + echo 255 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/brightness + echo 0 125 255 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/multi_intensity + echo 0 125 255 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/multi_intensity + n=$(( n + 1 )) + done +} + +PREV_BATCAP="null" +while true + do + BAT_LED_STATE=$(get_setting led.color) + if [ ! ${BAT_LED_STATE} == "battery" ]; then + break + else + 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 + bat_led_red + sleep .5 + bat_led_off + sleep .5 + done + continue + elif (( ${CAP} <= 20 )) + then + BATCAP="D_RED" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_red + fi + elif (( ${CAP} <= 30 )) + then + BATCAP="D_ORANGE" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_orange + fi + elif (( ${CAP} <= 40 )) + then + BATCAP="D_YELLOW" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_yellow + fi + else + BATCAP="D_GREEN" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_green + fi + fi + elif (( ${CAP} <= 94 )) + then + BATCAP="C_ORANGE" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_orange + fi + elif (( ${CAP} >= 95 )) + then + BATCAP="C_GREEN" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_green + fi + fi + PREV_BATCAP=${BATCAP} + sleep 15 + fi +done diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYN Odin 2 Portal/bin/ledcontrol b/projects/ArchR/packages/hardware/quirks/devices/AYN Odin 2 Portal/bin/ledcontrol new file mode 100644 index 0000000000..8726843fc9 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYN Odin 2 Portal/bin/ledcontrol @@ -0,0 +1,45 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile + +LED_PATH="/sys/devices/platform/" + +function led_off() { + n=1 + while [ "$n" -lt 4 ]; do + echo 0 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/brightness + echo 0 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/brightness + echo 0 0 0 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/multi_intensity + echo 0 0 0 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/multi_intensity + n=$(( n + 1 )) + done +} + +case ${1} in + off) + led_off + set_setting led.color ${1} + ;; + rgb) + LEDS_CONFIG=$(get_setting analogsticks.led) + /usr/bin/analog_sticks_ledcontrol ${LEDS_CONFIG} + set_setting led.color ${1} + ;; + battery) + led_off + set_setting led.color ${1} + systemctl restart batteryledstatus.service + ;; + poweroff) + led_off + ;; + list) +cat </storage/.config/commander.cfg +disp_ppu_x=4 +disp_ppu_y=4 +EOF +fi diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYN Odin 2/010-analog_sticks_led_control b/projects/ArchR/packages/hardware/quirks/devices/AYN Odin 2/010-analog_sticks_led_control new file mode 100755 index 0000000000..8a21241d44 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYN Odin 2/010-analog_sticks_led_control @@ -0,0 +1,7 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/010-analog_sticks_led_control +DEVICE_ANALOG_STICKS_LED_CONTROL="true" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYN Odin 2/050-game-configs b/projects/ArchR/packages/hardware/quirks/devices/AYN Odin 2/050-game-configs new file mode 100644 index 0000000000..909e82fcab --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYN Odin 2/050-game-configs @@ -0,0 +1,7 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +#Disable retroarch microphone and set default audio driver to pulse +sed -i '/^microphone_enable =/c\microphone_enable = "false"' /storage/.config/retroarch/retroarch.cfg +sed -i '/^audio_driver =/c\audio_driver = "pulse"' /storage/.config/retroarch/retroarch.cfg diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYN Odin 2/bin/achievements b/projects/ArchR/packages/hardware/quirks/devices/AYN Odin 2/bin/achievements new file mode 100755 index 0000000000..998b929d2d --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYN Odin 2/bin/achievements @@ -0,0 +1,100 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + + # Rainbow effect configuration + STEPS=30 # Fewer steps for faster transitions + DURATION=0.5 # Shorter duration (half a second per cycle) + SLEEP_TIME=$(echo "scale=4; $DURATION/$STEPS" | bc) + CYCLES=2 # Number of cycles to run + +function calculate_rainbow_color() { + local position=$1 + local h=$(echo "scale=2; 360*$position/$STEPS" | bc) + + # Convert HSV (with S=1, V=1) to RGB + # Calculate region and fractional part + local region=$(echo "scale=0; $h/60" | bc) + local remainder=$(echo "scale=2; $h-$region*60" | bc) + local fractional=$(echo "scale=2; $remainder/60" | bc) + + # Initialize RGB values + local r=0 + local g=0 + local b=0 + + # Calculate RGB based on hue region (0-5) + case $region in + 0) + # 0-60: Red to Yellow + r=255 + g=$(echo "scale=0; 255*$fractional" | bc) + b=0 + ;; + 1) + # 60-120: Yellow to Green + r=$(echo "scale=0; 255*(1-$fractional)" | bc) + g=255 + b=0 + ;; + 2) + # 120-180: Green to Cyan + r=0 + g=255 + b=$(echo "scale=0; 255*$fractional" | bc) + ;; + 3) + # 180-240: Cyan to Blue + r=0 + g=$(echo "scale=0; 255*(1-$fractional)" | bc) + b=255 + ;; + 4) + # 240-300: Blue to Magenta + r=$(echo "scale=0; 255*$fractional" | bc) + g=0 + b=255 + ;; + 5|6) + # 300-360: Magenta to Red + r=255 + g=0 + b=$(echo "scale=0; 255*(1-$fractional)" | bc) + ;; + esac + + # Ensure values are integers + r=${r%.*} + g=${g%.*} + b=${b%.*} + + # Ensure values are not negative or exceed 255 + r=$(( r < 0 ? 0 : r > 255 ? 255 : r )) + g=$(( g < 0 ? 0 : g > 255 ? 255 : g )) + b=$(( b < 0 ? 0 : b > 255 ? 255 : b )) + + echo "$r $g $b" +} + +# Main rainbow effect loop +# Loop several times to create a continuous effect +for ((cycle=0; cycle${LED_PATH}/${1}/brightness +} + +function led_rgb() { + echo ${2} ${3} ${4} >${LED_PATH}/${1}/multi_intensity +} + +# Display usage if no parameters are provided +if [ $# -ne 7 ]; then + echo "Usage: $0 " + echo "Example: $0 255 255 0 0 0 0 255" + exit 1 +fi + +BRIGHTNESS=$1 +RIGHT_RED=$2 +RIGHT_GREEN=$3 +RIGHT_BLUE=$4 +LEFT_RED=$5 +LEFT_GREEN=$6 +LEFT_BLUE=$7 + +led_brightness left-joystick $BRIGHTNESS +led_rgb left-joystick $LEFT_RED $LEFT_GREEN $LEFT_BLUE +led_brightness left-side $BRIGHTNESS +led_rgb left-side $LEFT_RED $LEFT_GREEN $LEFT_BLUE + +led_brightness right-joystick $BRIGHTNESS +led_rgb right-joystick $RIGHT_RED $RIGHT_GREEN $RIGHT_BLUE +led_brightness right-side $BRIGHTNESS +led_rgb right-side $RIGHT_RED $RIGHT_GREEN $RIGHT_BLUE diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYN Odin 2/bin/battery_led_status b/projects/ArchR/packages/hardware/quirks/devices/AYN Odin 2/bin/battery_led_status new file mode 100644 index 0000000000..240448a475 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYN Odin 2/bin/battery_led_status @@ -0,0 +1,108 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +# Simple script to watch the battery capacity and +# turn the power LED orange when it reaches 30%, red at 20%, and blinking red at 10% + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +LED_PATH="/sys/class/leds" + +function led_brightness() { + echo ${2} >${LED_PATH}/${1}/brightness +} + +function led_rgb() { + echo ${2} ${3} ${4} >${LED_PATH}/${1}/multi_intensity +} + +function bat_led_off() { + led_brightness power-led 0 + led_rgb power-led 0 0 0 +} + +function bat_led_green() { + led_brightness power-led 255 + led_rgb power-led 0 255 0 +} + +function bat_led_red() { + led_brightness power-led 255 + led_rgb power-led 255 0 0 +} + +function bat_led_orange() { + led_brightness power-led 255 + led_rgb power-led 255 20 0 +} + +function bat_led_yellow() { + led_brightness power-led 255 + led_rgb power-led 255 125 0 +} + +PREV_BATCAP="null" +while true + do + BAT_LED_STATE=$(get_setting led.color) + if [ ! ${BAT_LED_STATE} == "battery" ]; then + break + fi + + 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 + bat_led_red + sleep .5 + bat_led_off + sleep .5 + done + continue + elif (( ${CAP} <= 20 )) + then + BATCAP="D_RED" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_red + fi + elif (( ${CAP} <= 30 )) + then + BATCAP="D_ORANGE" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_orange + fi + elif (( ${CAP} <= 40 )) + then + BATCAP="D_YELLOW" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_yellow + fi + else + BATCAP="D_GREEN" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_green + fi + fi + elif (( ${CAP} <= 94 )) + then + BATCAP="C_ORANGE" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_orange + fi + elif (( ${CAP} >= 95 )) + then + BATCAP="C_GREEN" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_green + fi + fi + PREV_BATCAP=${BATCAP} + sleep 15 +done diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYN Odin 2/bin/ledcontrol b/projects/ArchR/packages/hardware/quirks/devices/AYN Odin 2/bin/ledcontrol new file mode 100644 index 0000000000..3f2da3849a --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYN Odin 2/bin/ledcontrol @@ -0,0 +1,113 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +LED_PATH="/sys/class/leds" + +function led_brightness() { + echo ${2} >${LED_PATH}/${1}/brightness +} + +function led_rgb() { + echo ${2} ${3} ${4} >${LED_PATH}/${1}/multi_intensity +} + +function led_off() { + led_brightness power-led 0 + led_rgb power-led 0 0 0 +} + +function led_red() { + led_brightness power-led 255 + led_rgb power-led 255 0 0 +} + +function led_green() { + led_brightness power-led 255 + led_rgb power-led 0 255 0 +} + +function led_blue() { + led_brightness power-led 255 + led_rgb power-led 0 0 255 +} + +function led_white() { + led_brightness power-led 255 + led_rgb power-led 255 255 255 +} + +function led_orange() { + led_brightness power-led 255 + led_rgb power-led 255 20 0 +} + +function led_yellow() { + led_brightness power-led 255 + led_rgb power-led 255 125 0 +} + +function led_purple() { + led_brightness power-led 255 + led_rgb power-led 255 0 255 +} + +case ${1} in + red) + led_red + set_setting led.color ${1} + ;; + green) + led_green + set_setting led.color ${1} + ;; + blue) + led_blue + set_setting led.color ${1} + ;; + white) + led_white + set_setting led.color ${1} + ;; + orange) + led_orange + set_setting led.color ${1} + ;; + yellow) + led_yellow + set_setting led.color ${1} + ;; + purple) + led_purple + set_setting led.color ${1} + ;; + off) + led_off + set_setting led.color ${1} + ;; + battery) + led_off + set_setting led.color ${1} + systemctl restart batteryledstatus.service + ;; + poweroff) + led_off + ;; + list) +cat </storage/.config/profile.d/010-analog_sticks_led_control +DEVICE_ANALOG_STICKS_LED_CONTROL="true" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYN Odin/050-game-configs b/projects/ArchR/packages/hardware/quirks/devices/AYN Odin/050-game-configs new file mode 100755 index 0000000000..909e82fcab --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYN Odin/050-game-configs @@ -0,0 +1,7 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +#Disable retroarch microphone and set default audio driver to pulse +sed -i '/^microphone_enable =/c\microphone_enable = "false"' /storage/.config/retroarch/retroarch.cfg +sed -i '/^audio_driver =/c\audio_driver = "pulse"' /storage/.config/retroarch/retroarch.cfg diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYN Thor/009-commander-cfg b/projects/ArchR/packages/hardware/quirks/devices/AYN Thor/009-commander-cfg new file mode 100644 index 0000000000..044bb46732 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYN Thor/009-commander-cfg @@ -0,0 +1,11 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025 ArchR (https://github.com/archr-linux/Arch-R) + +if [ ! -f "/storage/.config/commander.cfg" ]; then +cat </storage/.config/commander.cfg +disp_ppu_x=4 +disp_ppu_y=4 +EOF +fi diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYN Thor/010-analog_sticks_led_control b/projects/ArchR/packages/hardware/quirks/devices/AYN Thor/010-analog_sticks_led_control new file mode 100755 index 0000000000..8a21241d44 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYN Thor/010-analog_sticks_led_control @@ -0,0 +1,7 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/010-analog_sticks_led_control +DEVICE_ANALOG_STICKS_LED_CONTROL="true" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYN Thor/050-game-configs b/projects/ArchR/packages/hardware/quirks/devices/AYN Thor/050-game-configs new file mode 100644 index 0000000000..50babf7b79 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYN Thor/050-game-configs @@ -0,0 +1,21 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025-present ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile.d/001-functions + +#Disable retroarch microphone and set default audio driver to pulse +sed -i '/^microphone_enable =/c\microphone_enable = "false"' /storage/.config/retroarch/retroarch.cfg +sed -i '/^audio_driver =/c\audio_driver = "pulse"' /storage/.config/retroarch/retroarch.cfg + +#Set default layouts for 3DS +THREE_DS_SCREEN_LAYOUT=$(get_setting "3ds.screen_layout") +if [ ! -n "${THREE_DS_SCREEN_LAYOUT}" ]; then + set_setting "3ds.screen_layout" "5" +fi + +#Set default layouts for NDS +NDS_SCREEN_LAYOUT=$(get_setting "nds.screen_layout") +if [ ! -n "${NDS_SCREEN_LAYOUT}" ]; then + set_setting "nds.screen_layout" "6" +fi diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYN Thor/bin/analog_sticks_ledcontrol b/projects/ArchR/packages/hardware/quirks/devices/AYN Thor/bin/analog_sticks_ledcontrol new file mode 100644 index 0000000000..d848333528 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYN Thor/bin/analog_sticks_ledcontrol @@ -0,0 +1,45 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2025 ArchR (https://github.com/archr-linux/Arch-R) + +# Simple script to set led brightness and rgb color based on +# brightness and rgb values from emulation station + +LED_PATH="/sys/devices/platform/" + +function led_brightness() { + n=1 + while [ "$n" -lt 4 ]; do + echo ${2} > ${LED_PATH}/multi-led${1}${n}/leds/rgb:${1}${n}/brightness + n=$(( n + 1 )) + done +} + +function led_rgb() { + n=1 + while [ "$n" -lt 4 ]; do + echo ${2} ${3} ${4} > ${LED_PATH}/multi-led${1}${n}/leds/rgb:${1}${n}/multi_intensity + n=$(( n + 1 )) + done +} + +# Display usage if no parameters are provided +if [ $# -ne 7 ]; then + echo "Usage: $0 " + echo "Example: $0 255 255 0 0 0 0 255" + exit 1 +fi + +BRIGHTNESS=$1 +RIGHT_RED=$2 +RIGHT_GREEN=$3 +RIGHT_BLUE=$4 +LEFT_RED=$5 +LEFT_GREEN=$6 +LEFT_BLUE=$7 + +led_brightness l $BRIGHTNESS +led_rgb l $LEFT_BLUE $LEFT_GREEN $LEFT_RED +led_brightness r $BRIGHTNESS +led_rgb r $RIGHT_BLUE $RIGHT_GREEN $RIGHT_RED diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYN Thor/bin/battery_led_status b/projects/ArchR/packages/hardware/quirks/devices/AYN Thor/bin/battery_led_status new file mode 100644 index 0000000000..09f5a20f73 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYN Thor/bin/battery_led_status @@ -0,0 +1,128 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +# Simple script to watch the battery capacity and +# turn the power LED orange when it reaches 30%, red at 20%, and blinking red at 10% + +. /etc/profile + +LED_PATH="/sys/devices/platform/" + +function bat_led_off() { + n=1 + while [ "$n" -lt 4 ]; do + echo 0 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/brightness + echo 0 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/brightness + echo 0 0 0 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/multi_intensity + echo 0 0 0 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/multi_intensity + n=$(( n + 1 )) + done +} + +function bat_led_red() { + n=1 + while [ "$n" -lt 4 ]; do + echo 255 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/brightness + echo 255 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/brightness + echo 0 0 255 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/multi_intensity + echo 0 0 255 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/multi_intensity + n=$(( n + 1 )) + done +} + +function bat_led_green() { + n=1 + while [ "$n" -lt 4 ]; do + echo 255 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/brightness + echo 255 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/brightness + echo 0 255 0 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/multi_intensity + echo 0 255 0 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/multi_intensity + n=$(( n + 1 )) + done +} + +function bat_led_orange() { + n=1 + while [ "$n" -lt 4 ]; do + echo 255 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/brightness + echo 255 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/brightness + echo 0 20 255 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/multi_intensity + echo 0 20 255 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/multi_intensity + n=$(( n + 1 )) + done +} + +function bat_led_yellow() { + n=1 + while [ "$n" -lt 4 ]; do + echo 255 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/brightness + echo 255 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/brightness + echo 0 125 255 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/multi_intensity + echo 0 125 255 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/multi_intensity + n=$(( n + 1 )) + done +} + +PREV_BATCAP="null" +while true + do + BAT_LED_STATE=$(get_setting led.color) + if [ ! ${BAT_LED_STATE} == "battery" ]; then + break + else + 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 + bat_led_red + sleep .5 + bat_led_off + sleep .5 + done + continue + elif (( ${CAP} <= 20 )) + then + BATCAP="D_RED" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_red + fi + elif (( ${CAP} <= 30 )) + then + BATCAP="D_ORANGE" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_orange + fi + elif (( ${CAP} <= 40 )) + then + BATCAP="D_YELLOW" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_yellow + fi + else + BATCAP="D_GREEN" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_green + fi + fi + elif (( ${CAP} <= 94 )) + then + BATCAP="C_ORANGE" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_orange + fi + elif (( ${CAP} >= 95 )) + then + BATCAP="C_GREEN" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_green + fi + fi + PREV_BATCAP=${BATCAP} + sleep 15 + fi +done diff --git a/projects/ArchR/packages/hardware/quirks/devices/AYN Thor/bin/ledcontrol b/projects/ArchR/packages/hardware/quirks/devices/AYN Thor/bin/ledcontrol new file mode 100644 index 0000000000..8726843fc9 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/AYN Thor/bin/ledcontrol @@ -0,0 +1,45 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile + +LED_PATH="/sys/devices/platform/" + +function led_off() { + n=1 + while [ "$n" -lt 4 ]; do + echo 0 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/brightness + echo 0 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/brightness + echo 0 0 0 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/multi_intensity + echo 0 0 0 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/multi_intensity + n=$(( n + 1 )) + done +} + +case ${1} in + off) + led_off + set_setting led.color ${1} + ;; + rgb) + LEDS_CONFIG=$(get_setting analogsticks.led) + /usr/bin/analog_sticks_ledcontrol ${LEDS_CONFIG} + set_setting led.color ${1} + ;; + battery) + led_off + set_setting led.color ${1} + systemctl restart batteryledstatus.service + ;; + poweroff) + led_off + ;; + list) +cat </run/udev/rules.d/99-touchscreen-calibration.rules +# left panel (ID_PATH=platform-a90000.i2c) -> (0 .. 1920) x (0 .. 1080) +SUBSYSTEM=="input", KERNEL=="event*", ENV{ID_INPUT_TOUCHSCREEN}=="1", \ + ENV{ID_PATH}=="platform-a90000.i2c", \ + ENV{LIBINPUT_CALIBRATION_MATRIX}="0.607595 0 0 0 1 0" + +# right panel (ID_PATH=platform-98c000.i2c) -> (1920 .. 3160) x (0 .. 1080) +SUBSYSTEM=="input", KERNEL=="event*", ENV{ID_INPUT_TOUCHSCREEN}=="1", \ + ENV{ID_PATH}=="platform-98c000.i2c", \ + ENV{LIBINPUT_CALIBRATION_MATRIX}="0.392405 0 0.607595 0 1 0" +EOF +udevadm control --reload +udevadm trigger -s input \ No newline at end of file diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-D/001-device_config b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-D/001-device_config new file mode 100755 index 0000000000..e544be2b09 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-D/001-device_config @@ -0,0 +1,9 @@ +#!/bin/sh +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/001-device_config +DEVICE_FAKE_JACKSENSE="false" +DEVICE_BATTERY_LED_STATUS="true" +DEVICE_HAS_TOUCHSCREEN="true" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-D/020-gpios b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-D/020-gpios new file mode 100755 index 0000000000..357fcb1087 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-D/020-gpios @@ -0,0 +1,15 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/020-gpios +DEVICE_WIFI="0" +DEVICE_PWM_MOTOR="pwmchip1" +EOF + +. /storage/.config/profile.d/020-gpios +# Enable PWM for rumble and turn rumble off during startup. +echo 0 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/export +echo 1000000 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/period +echo 1 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/enable +echo 1000000 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/duty_cycle diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-D/050-game-configs b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-D/050-game-configs new file mode 100755 index 0000000000..876f8dce0e --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-D/050-game-configs @@ -0,0 +1,154 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +#Set mupen64-plus-sa config for R33S +if [ ! -d "/storage/.config/mupen64plus" ]; then + mkdir -p "/storage/.config/mupen64plus/" + cp -r /usr/local/share/mupen64plus/mupen64plus.cfg* /storage/.config/mupen64plus/ +fi +if [ -f "/storage/.config/mupen64plus/mupen64plus.cfg.rgarc" ]; then + rm /storage/.config/mupen64plus/mupen64plus.cfg + mv /storage/.config/mupen64plus/mupen64plus.cfg.rgarc /storage/.config/mupen64plus/mupen64plus.cfg +fi +if [ ! -f "/storage/.config/mupen64plus/custominput.ini" ]; then +cat </storage/.config/mupen64plus/custominput.ini +[rg_arc_joypad] +plugged = True +mouse = False +AnalogDeadzone = 0,0 +AnalogPeak = 32768,32768 +DPad R = button(15) +DPad L = button(14) +DPad D = button(13) +DPad U = button(12) +Start = button(11) +Z Trig = button(8) +B Button = button(3) +A Button = button(1) +C Button R = button(2) +C Button L = button(4) +C Button D = button(0) +C Button U = button(5) +R Trig = button(7) +L Trig = button(6) +Mempak switch = +Rumblepak switch = +# Analog axis configuration mappings +X Axis = +Y Axis = +EOF +fi + +#Set drastic-sa config +if [ ! -d "/storage/.config/drastic" ]; then + mkdir -p "/storage/.config/drastic" + cp -r "/usr/config/drastic" "/storage/.config/" +fi +if [ -f "/storage/.config/drastic/config/drastic.cfg.arc" ]; then + mv /storage/.config/drastic/config/drastic.cfg.arc /storage/.config/drastic/config/drastic.cfg +fi + +# Copy over device specific retroarch remappings unless they already exist +REMAP_DIR="/usr/lib/autostart/quirks/devices/${QUIRK_DEVICE}/remappings" +if [ -d "${REMAP_DIR}" ]; then + for dir in "${REMAP_DIR}"/*/; do + CORE_NAME=$(basename "${dir}") + if [ ! -d "/storage/remappings/${CORE_NAME}" ]; then + cp -r "${dir}" "/storage/remappings/" + fi + done +fi + +# hypseus aka daphne +if [ ! -d "/storage/.config/game/configs/hypseus/" ]; then + mkdir -p /storage/.config/game/configs/hypseus/ +fi +if [ ! -f "/storage/.config/game/configs/hypseus/hypinput.ini" ]; then +cat </storage/.config/game/configs/hypseus/hypinput.ini +# Sample hypinput.ini +# All key options listed +# Arcade layout by OzFalcon +# Hypseus uses SDL2 Keycodes +# KEY_BUTTON3 Turns scoreboard on/off +# SWITCH = Key1 Key2 Joy +# Start + Select will exit game +################################## +#Button Info for ARC-D running ArchR by Morfious +# +#Controller Button ID# Game Function +#Dpad Up 13 Dpad Up 1073741906 SDLK_UP BUTTON_DPAD_UP +#Dpad Down 14 Dpad Down 1073741905 SDLK_DOWN BUTTON_DPAD_DOWN +#Dpad Left 15 Dpad Left 1073741904 SDLK_LEFT BUTTON_DPAD_LEFT +#Dpad Right 16 Dpad Right 1073741903 SDLK_RIGHT BUTTON_DPAD_RIGHT +#Select 11 Insert Coin +#Start 12 Start Game +#A Button 2 Button 1 +#B Button 1 Button 2 +#C Button 3 Toggle Scoreboard +#X Button 4 Skill 1 +#Y Button 5 Skill 2 +#Z Button 6 Skill 3 +#L1 7 Pause +#R1 8 Test Mode +#L2 9 Reset +#R2 10 Service Mode + +[KEYBOARD] +KEY_UP = 1073741906 SDLK_UP 13 +KEY_DOWN = 1073741905 SDLK_DOWN 14 +KEY_LEFT = 1073741904 SDLK_LEFT 15 +KEY_RIGHT = 1073741903 SDLK_RIGHT 16 +KEY_COIN1 = SDLK_5 0 11 +KEY_COIN2 = SDLK_6 0 0 +KEY_START1 = SDLK_1 0 12 +KEY_START2 = SDLK_2 0 0 +KEY_BUTTON1 = SDLK_LCTRL 0 2 +KEY_BUTTON2 = SDLK_LALT 0 1 +KEY_BUTTON3 = SDLK_SPACE 0 3 +KEY_SKILL1 = SDLK_LSHIFT 0 4 +KEY_SKILL2 = SDLK_z 0 5 +KEY_SKILL3 = SDLK_x 0 6 +KEY_SERVICE = SDLK_9 0 10 +KEY_TEST = SDLK_F2 SDLK_F4 8 +KEY_RESET = SDLK_0 0 9 +KEY_SCREENSHOT = SDLK_F12 0 0 +KEY_QUIT = SDLK_ESCAPE 0 0 +KEY_PAUSE = SDLK_p 0 7 +KEY_CONSOLE = SDLK_BACKSLASH 0 0 +KEY_TILT = SDLK_t 0 0 +END +EOF +fi + +# PPSSPP controls +SOURCE_DIR="/usr/config/ppsspp" +CONF_DIR="/storage/.config/ppsspp" +# Check if conf dir exists +if [ ! -d "${CONF_DIR}" ] +then + cp -rf ${SOURCE_DIR} ${CONF_DIR} + CONTROLS_INI="${CONF_DIR}/PSP/SYSTEM/controls.ini" + cat <${CONTROLS_INI} +[ControlMapping] +Up = 10-19 +Down = 10-20 +Left = 10-21 +Right = 10-22 +Cross = 10-190 +Circle = 10-189 +Square = 10-188 +Triangle = 10-191 +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-4,10-106 +Save State = 10-4010 +Load State = 10-4008 +EOF +fi + diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-D/remappings/Beetle PC-FX/Beetle PC-FX.rmp b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-D/remappings/Beetle PC-FX/Beetle PC-FX.rmp new file mode 100644 index 0000000000..9e2a9d5037 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-D/remappings/Beetle PC-FX/Beetle PC-FX.rmp @@ -0,0 +1,22 @@ +input_libretro_device_p1 = "1" +input_libretro_device_p2 = "1" +input_libretro_device_p3 = "1" +input_libretro_device_p4 = "1" +input_libretro_device_p5 = "1" +input_player1_analog_dpad_mode = "1" +input_player1_btn_a = "0" +input_player1_btn_b = "9" +input_player1_btn_l = "-1" +input_player1_btn_l3 = "11" +input_player1_btn_r = "-1" +input_player1_btn_r3 = "8" +input_player1_btn_x = "10" +input_player2_analog_dpad_mode = "0" +input_player3_analog_dpad_mode = "0" +input_player4_analog_dpad_mode = "0" +input_player5_analog_dpad_mode = "0" +input_remap_port_p1 = "0" +input_remap_port_p2 = "1" +input_remap_port_p3 = "2" +input_remap_port_p4 = "3" +input_remap_port_p5 = "4" diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-D/remappings/Flycast/Flycast.rmp b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-D/remappings/Flycast/Flycast.rmp new file mode 100644 index 0000000000..0fd5df11c6 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-D/remappings/Flycast/Flycast.rmp @@ -0,0 +1,19 @@ +input_libretro_device_p1 = "1" +input_libretro_device_p2 = "1" +input_libretro_device_p3 = "1" +input_libretro_device_p4 = "1" +input_libretro_device_p5 = "1" +input_player1_analog_dpad_mode = "0" +input_player1_stk_l_x+ = "-1" +input_player1_stk_l_x- = "-1" +input_player1_stk_l_y+ = "-1" +input_player1_stk_l_y- = "-1" +input_player2_analog_dpad_mode = "0" +input_player3_analog_dpad_mode = "0" +input_player4_analog_dpad_mode = "0" +input_player5_analog_dpad_mode = "0" +input_remap_port_p1 = "0" +input_remap_port_p2 = "1" +input_remap_port_p3 = "2" +input_remap_port_p4 = "3" +input_remap_port_p5 = "4" diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-D/remappings/Genesis Plus GX/Genesis Plus GX.rmp b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-D/remappings/Genesis Plus GX/Genesis Plus GX.rmp new file mode 100644 index 0000000000..83420fa59b --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-D/remappings/Genesis Plus GX/Genesis Plus GX.rmp @@ -0,0 +1,22 @@ +input_libretro_device_p1 = "1" +input_libretro_device_p2 = "1" +input_libretro_device_p3 = "1" +input_libretro_device_p4 = "1" +input_libretro_device_p5 = "1" +input_player1_analog_dpad_mode = "1" +input_player1_btn_a = "0" +input_player1_btn_b = "1" +input_player1_btn_l = "-1" +input_player1_btn_l3 = "11" +input_player1_btn_r = "-1" +input_player1_btn_r3 = "8" +input_player1_btn_y = "10" +input_player2_analog_dpad_mode = "0" +input_player3_analog_dpad_mode = "0" +input_player4_analog_dpad_mode = "0" +input_player5_analog_dpad_mode = "0" +input_remap_port_p1 = "0" +input_remap_port_p2 = "1" +input_remap_port_p3 = "2" +input_remap_port_p4 = "3" +input_remap_port_p5 = "4" diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-D/remappings/Mupen64Plus GLES2/Mupen64Plus GLES2.rmp b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-D/remappings/Mupen64Plus GLES2/Mupen64Plus GLES2.rmp new file mode 100644 index 0000000000..b682320c97 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-D/remappings/Mupen64Plus GLES2/Mupen64Plus GLES2.rmp @@ -0,0 +1,33 @@ +#R33S +input_libretro_device_p1 = "1" +input_libretro_device_p2 = "1" +input_libretro_device_p3 = "1" +input_libretro_device_p4 = "1" +input_libretro_device_p5 = "1" +input_player1_analog_dpad_mode = "0" +input_player1_btn_a = "22" +input_player1_btn_down = "18" +input_player1_btn_l = "12" +input_player1_btn_l2 = "21" +input_player1_btn_left = "17" +input_player1_btn_r2 = "20" +input_player1_btn_right = "16" +input_player1_btn_up = "19" +input_player1_btn_x = "23" +input_player1_stk_l_x+ = "-1" +input_player1_stk_l_x- = "-1" +input_player1_stk_l_y+ = "-1" +input_player1_stk_l_y- = "-1" +input_player1_stk_r_x+ = "-1" +input_player1_stk_r_x- = "-1" +input_player1_stk_r_y+ = "-1" +input_player1_stk_r_y- = "-1" +input_player2_analog_dpad_mode = "0" +input_player3_analog_dpad_mode = "0" +input_player4_analog_dpad_mode = "0" +input_player5_analog_dpad_mode = "0" +input_remap_port_p1 = "0" +input_remap_port_p2 = "1" +input_remap_port_p3 = "2" +input_remap_port_p4 = "3" +input_remap_port_p5 = "4" diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-D/remappings/Opera/Opera.rmp b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-D/remappings/Opera/Opera.rmp new file mode 100644 index 0000000000..0db3b832a3 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-D/remappings/Opera/Opera.rmp @@ -0,0 +1,19 @@ +input_libretro_device_p1 = "1" +input_libretro_device_p2 = "1" +input_libretro_device_p3 = "1" +input_libretro_device_p4 = "1" +input_libretro_device_p5 = "1" +input_player1_analog_dpad_mode = "1" +input_player1_btn_a = "0" +input_player1_btn_b = "1" +input_player1_btn_r3 = "8" +input_player1_btn_y = "-1" +input_player2_analog_dpad_mode = "0" +input_player3_analog_dpad_mode = "0" +input_player4_analog_dpad_mode = "0" +input_player5_analog_dpad_mode = "0" +input_remap_port_p1 = "0" +input_remap_port_p2 = "1" +input_remap_port_p3 = "2" +input_remap_port_p4 = "3" +input_remap_port_p5 = "4" diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-D/remappings/PicoDrive/PicoDrive.rmp b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-D/remappings/PicoDrive/PicoDrive.rmp new file mode 100644 index 0000000000..83420fa59b --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-D/remappings/PicoDrive/PicoDrive.rmp @@ -0,0 +1,22 @@ +input_libretro_device_p1 = "1" +input_libretro_device_p2 = "1" +input_libretro_device_p3 = "1" +input_libretro_device_p4 = "1" +input_libretro_device_p5 = "1" +input_player1_analog_dpad_mode = "1" +input_player1_btn_a = "0" +input_player1_btn_b = "1" +input_player1_btn_l = "-1" +input_player1_btn_l3 = "11" +input_player1_btn_r = "-1" +input_player1_btn_r3 = "8" +input_player1_btn_y = "10" +input_player2_analog_dpad_mode = "0" +input_player3_analog_dpad_mode = "0" +input_player4_analog_dpad_mode = "0" +input_player5_analog_dpad_mode = "0" +input_remap_port_p1 = "0" +input_remap_port_p2 = "1" +input_remap_port_p3 = "2" +input_remap_port_p4 = "3" +input_remap_port_p5 = "4" diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-D/remappings/YabaSanshiro/YabaSanshiro.rmp b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-D/remappings/YabaSanshiro/YabaSanshiro.rmp new file mode 100644 index 0000000000..8c68e14c65 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-D/remappings/YabaSanshiro/YabaSanshiro.rmp @@ -0,0 +1,28 @@ +input_libretro_device_p1 = "1" +input_libretro_device_p2 = "1" +input_libretro_device_p3 = "1" +input_libretro_device_p4 = "1" +input_libretro_device_p5 = "1" +input_player1_analog_dpad_mode = "1" +input_player1_btn_l = "12" +input_player1_btn_l2 = "-1" +input_player1_btn_l3 = "11" +input_player1_btn_r = "13" +input_player1_btn_r2 = "-1" +input_player1_btn_r3 = "10" +input_player2_analog_dpad_mode = "0" +input_player3_analog_dpad_mode = "0" +input_player4_analog_dpad_mode = "0" +input_player5_analog_dpad_mode = "0" +input_remap_port_p1 = "0" +input_remap_port_p2 = "1" +input_remap_port_p3 = "2" +input_remap_port_p4 = "3" +input_remap_port_p5 = "4" +input_turbo_allow_dpad = "false" +input_turbo_bind = "-1" +input_turbo_button = "0" +input_turbo_duty_cycle = "0" +input_turbo_enable = "true" +input_turbo_mode = "0" +input_turbo_period = "6" diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-S/001-device_config b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-S/001-device_config new file mode 100755 index 0000000000..fb9818eec8 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-S/001-device_config @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/001-device_config +DEVICE_FAKE_JACKSENSE="false" +DEVICE_BATTERY_LED_STATUS="true" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-S/020-gpios b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-S/020-gpios new file mode 120000 index 0000000000..f892ec22a6 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-S/020-gpios @@ -0,0 +1 @@ +../Anbernic RG ARC-D/020-gpios \ No newline at end of file diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-S/050-game-configs b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-S/050-game-configs new file mode 120000 index 0000000000..940a8a6388 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-S/050-game-configs @@ -0,0 +1 @@ +../Anbernic RG ARC-D/050-game-configs \ No newline at end of file diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-S/remappings b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-S/remappings new file mode 120000 index 0000000000..aece2cf044 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG ARC-S/remappings @@ -0,0 +1 @@ +../Anbernic RG ARC-D/remappings \ No newline at end of file diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG CubeXX/010-analog_sticks_led_control b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG CubeXX/010-analog_sticks_led_control new file mode 100755 index 0000000000..8a21241d44 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG CubeXX/010-analog_sticks_led_control @@ -0,0 +1,7 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/010-analog_sticks_led_control +DEVICE_ANALOG_STICKS_LED_CONTROL="true" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG CubeXX/bin/achievements b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG CubeXX/bin/achievements new file mode 100755 index 0000000000..998b929d2d --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG CubeXX/bin/achievements @@ -0,0 +1,100 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + + # Rainbow effect configuration + STEPS=30 # Fewer steps for faster transitions + DURATION=0.5 # Shorter duration (half a second per cycle) + SLEEP_TIME=$(echo "scale=4; $DURATION/$STEPS" | bc) + CYCLES=2 # Number of cycles to run + +function calculate_rainbow_color() { + local position=$1 + local h=$(echo "scale=2; 360*$position/$STEPS" | bc) + + # Convert HSV (with S=1, V=1) to RGB + # Calculate region and fractional part + local region=$(echo "scale=0; $h/60" | bc) + local remainder=$(echo "scale=2; $h-$region*60" | bc) + local fractional=$(echo "scale=2; $remainder/60" | bc) + + # Initialize RGB values + local r=0 + local g=0 + local b=0 + + # Calculate RGB based on hue region (0-5) + case $region in + 0) + # 0-60: Red to Yellow + r=255 + g=$(echo "scale=0; 255*$fractional" | bc) + b=0 + ;; + 1) + # 60-120: Yellow to Green + r=$(echo "scale=0; 255*(1-$fractional)" | bc) + g=255 + b=0 + ;; + 2) + # 120-180: Green to Cyan + r=0 + g=255 + b=$(echo "scale=0; 255*$fractional" | bc) + ;; + 3) + # 180-240: Cyan to Blue + r=0 + g=$(echo "scale=0; 255*(1-$fractional)" | bc) + b=255 + ;; + 4) + # 240-300: Blue to Magenta + r=$(echo "scale=0; 255*$fractional" | bc) + g=0 + b=255 + ;; + 5|6) + # 300-360: Magenta to Red + r=255 + g=0 + b=$(echo "scale=0; 255*(1-$fractional)" | bc) + ;; + esac + + # Ensure values are integers + r=${r%.*} + g=${g%.*} + b=${b%.*} + + # Ensure values are not negative or exceed 255 + r=$(( r < 0 ? 0 : r > 255 ? 255 : r )) + g=$(( g < 0 ? 0 : g > 255 ? 255 : g )) + b=$(( b < 0 ? 0 : b > 255 ? 255 : b )) + + echo "$r $g $b" +} + +# Main rainbow effect loop +# Loop several times to create a continuous effect +for ((cycle=0; cycle/storage/.config/profile.d/001-device_config +DEVICE_FAKE_JACKSENSE="false" +DEVICE_BATTERY_LED_STATUS="true" +DEVICE_HAS_TOUCHSCREEN="true" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG DS/050-audio_path b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG DS/050-audio_path new file mode 100755 index 0000000000..fcfee70701 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG DS/050-audio_path @@ -0,0 +1,10 @@ +#!/bin/sh +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2021-present Fewtarius (https://github.com/fewtarius) + +cat </storage/.config/profile.d/002-audio_path +ALSA_PRIMARY_CARD=0 +DEVICE_PLAYBACK_PATH_SPK="HP" +DEVICE_PLAYBACK_PATH_HP="HP" +DEVICE_PLAYBACK_PATH="Playback Mux" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG DS/050-game_configs b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG DS/050-game_configs new file mode 100755 index 0000000000..850ce5d300 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG DS/050-game_configs @@ -0,0 +1,12 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +#Set drastic-sa config for RG DS +if [ ! -d "/storage/.config/drastic" ]; then + mkdir -p "/storage/.config/drastic" + cp -r "/usr/config/drastic" "/storage/.config/" +fi +if [ -f "/storage/.config/drastic/config/drastic.cfg.rgds" ]; then + mv /storage/.config/drastic/config/drastic.cfg.rgds /storage/.config/drastic/config/drastic.cfg +fi diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG DS/050-modifiers b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG DS/050-modifiers new file mode 100755 index 0000000000..390873af44 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG DS/050-modifiers @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2026-present ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/050-modifiers +DEVICE_FUNC_KEYA_MODIFIER="BTN_MODE" +DEVICE_FUNC_KEYB_MODIFIER="BTN_START" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG DS/110-retroarch-joypad b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG DS/110-retroarch-joypad new file mode 100755 index 0000000000..dfcc381de1 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG DS/110-retroarch-joypad @@ -0,0 +1,11 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +# Adapt retroarch joypad config for RG DS + +if [ ! -f "/storage/joypads/retrogame_joypad.cfg" ]; then + cp /usr/share/libretro/autoconfig/retrogame_joypad.cfg /storage/joypads/ + sed -i -r 's/input_enable_hotkey_btn.*/input_enable_hotkey_btn = "10"/' /storage/joypads/retrogame_joypad.cfg +fi + diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG DS/sleep.d/post/99-drastic-cont b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG DS/sleep.d/post/99-drastic-cont new file mode 100755 index 0000000000..1402b67572 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG DS/sleep.d/post/99-drastic-cont @@ -0,0 +1,6 @@ +#!/bin/sh + +# Resume DraStic if it's still there +if pgrep drastic; then + kill -CONT $(pidof drastic) +fi \ No newline at end of file diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG DS/sleep.d/pre/99-drastic-stop b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG DS/sleep.d/pre/99-drastic-stop new file mode 100755 index 0000000000..add3d0f9db --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG DS/sleep.d/pre/99-drastic-stop @@ -0,0 +1,7 @@ +#!/bin/sh + +# DraStic specifically needs to be told to stop so it doesn't backlog dynarec +# instructions while the cpu is clocking down before sleep fully completes +if pgrep drastic; then + kill -STOP $(pidof drastic) +fi \ No newline at end of file diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG DS/touchcontrol b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG DS/touchcontrol new file mode 100755 index 0000000000..efd998e0dc --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG DS/touchcontrol @@ -0,0 +1,17 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025-present ArchR (https://github.com/archr-linux/Arch-R) + +mkdir -p /run/udev/rules.d/ +cat </run/udev/rules.d/99-touchscreen-calibration.rules +SUBSYSTEM=="input", KERNEL=="event*", ENV{ID_INPUT_TOUCHSCREEN}=="1", \ + ENV{ID_PATH}=="platform-fe5c0000.i2c", \ + ENV{LIBINPUT_CALIBRATION_MATRIX}="0.5 0 0 0 1 0" + +SUBSYSTEM=="input", KERNEL=="event*", ENV{ID_INPUT_TOUCHSCREEN}=="1", \ + ENV{ID_PATH}=="platform-fe5e0000.i2c", \ + ENV{LIBINPUT_CALIBRATION_MATRIX}="0.5 0 0.5 0 1 0" +EOF + +udevadm control --reload +udevadm trigger -s input diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG351M/001-device_config b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG351M/001-device_config new file mode 100755 index 0000000000..f4da1b9ee1 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG351M/001-device_config @@ -0,0 +1,14 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/001-device_config +# Device Features +DEVICE_PLAYBACK_PATH_SPK="HP" +DEVICE_PLAYBACK_PATH_HP="SPK" +DEVICE_VOLUME="100" +DEVICE_BATTERY_LED_STATUS="true" +DEVICE_PWR_LED_GPIO="77" +DEVICE_TEMP_SENSOR="/sys/devices/virtual/thermal/thermal_zone0/temp" +DEVICE_MMC_EJECT="false" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG351M/009-commander-cfg b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG351M/009-commander-cfg new file mode 100644 index 0000000000..a9c4b8bd72 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG351M/009-commander-cfg @@ -0,0 +1,11 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025 ArchR (https://github.com/archr-linux/Arch-R) + +if [ ! -f "/storage/.config/commander.cfg" ]; then +cat </storage/.config/commander.cfg +disp_ppu_x=1.5 +disp_ppu_y=1.5 +EOF +fi diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG351M/050-game_configs b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG351M/050-game_configs new file mode 100755 index 0000000000..8c16e46ea8 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG351M/050-game_configs @@ -0,0 +1,48 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +#Set up gzdoom +if [ ! -d "/storage/.config/gzdoom/" ]; then + cp -rf /usr/config/gzdoom /storage/.config/ + sed -i '/Joy7=/c\Joy7=togglemap' /storage/.config/gzdoom/gzdoom.ini + sed -i '/Joy8=/c\Joy8=menu_main' /storage/.config/gzdoom/gzdoom.ini + sed -i '/Axis0scale=/c\Axis0scale=-0.8' /storage/.config/gzdoom/gzdoom.ini + sed -i '/Axis1scale=/c\Axis1scale=-0.6' /storage/.config/gzdoom/gzdoom.ini + sed -i '/vid_defheight=/c\vid_defheight=320' /storage/.config/gzdoom/gzdoom.ini + sed -i '/vid_defwidth=/c\vid_defwidth=480' /storage/.config/gzdoom/gzdoom.ini +fi + +#Map ppsspp controls +if grep RG351M -q "/stprage/.config/ppsspp/PSP/SYSTEM/controls.ini" +then + exit 1 +else +cat </storage/.config/ppsspp/PSP/SYSTEM/controls.ini +#RG351M +[ControlMapping] +Up = 10-19 +Down = 10-20 +Left = 10-21 +Right = 10-22 +Circle = 10-189 +Cross = 10-190 +Square = 10-188 +Triangle = 10-191 +Start = 10-197 +Select = 10-196 +L = 10-193 +R = 10-192 +An.Up = 10-4002 +An.Down = 10-4003 +An.Left = 10-4000 +An.Right = 10-4001 +Fast-forward = 1-61 +Pause = 10-106 +Save State = 10-4010 +Load State = 10-4008 +RightAn.Up = 10-4007 +RightAn.Down = 10-4006 +RightAn.Left = 10-4005 +RightAn.Right = 10-4004 +EOF +fi diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG351M/050-volume b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG351M/050-volume new file mode 100755 index 0000000000..b2c9c28a68 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG351M/050-volume @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +. /storage/.config/profile.d/001-device_config + +### RG351P/M has a volume rocker, so the internal volume should always be 100%. +amixer -c 0 set "Master" "${DEVICE_VOLUME}%" diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG351M/075-dpad-volbright b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG351M/075-dpad-volbright new file mode 100755 index 0000000000..287366f2f7 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG351M/075-dpad-volbright @@ -0,0 +1,47 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +DPAD_EVENTS=$(get_setting key.dpad.events) +if [ -z "${DPAD_EVENTS}" ] +then + set_setting key.dpad.events 1 +fi + +KEY_FUNC_A=$(get_setting key.function.a) +if [ -z "${KEY_FUNC_A}" ] +then + set_setting key.function.a BTN_WEST +fi + +KEY_FUNC_B=$(get_setting key.function.b) +if [ -z "${KEY_FUNC_B}" ] +then + set_setting key.function.b BTN_TR +fi + +KEY_HOT_A=$(get_setting key.hotkey.a) +if [ -z "${KEY_HOT_A}" ] +then + set_setting key.hotkey.a BTN_WEST +fi + +KEY_HOT_B=$(get_setting key.hotkey.b) +if [ -z "${KEY_HOT_B}" ] +then + set_setting key.hotkey.b BTN_TR +fi + +KEY_HOT_C=$(get_setting key.hotkey.c) +if [ -z "${KEY_HOT_C}" ] +then + set_setting key.hotkey.c BTN_TL +fi + +if [ "$(systemctl is-active input)" = "active" ] +then + systemctl restart input +fi diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG351V/001-device_config b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG351V/001-device_config new file mode 100755 index 0000000000..d5dde3f33f --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG351V/001-device_config @@ -0,0 +1,12 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/001-device_config +# Device Features +DEVICE_PLAYBACK_PATH_SPK="SPK" +DEVICE_PLAYBACK_PATH_HP="HP" +DEVICE_BATTERY_LED_STATUS="true" +DEVICE_PWR_LED_GPIO="77" +DEVICE_TEMP_SENSOR="/sys/devices/virtual/thermal/thermal_zone0/temp" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG351V/004-game-configs b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG351V/004-game-configs new file mode 100755 index 0000000000..aed35c84df --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG351V/004-game-configs @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +#Set up gzdoom +if [ ! -d "/storage/.config/gzdoom/" ]; then + cp -rf /usr/config/gzdoom /storage/.config/ + sed -i '/Joy7=/c\Joy7=togglemap' /storage/.config/gzdoom/gzdoom.ini + sed -i '/Joy8=/c\Joy8=menu_main' /storage/.config/gzdoom/gzdoom.ini + sed -i '/Axis0scale=/c\Axis0scale=-0.8' /storage/.config/gzdoom/gzdoom.ini + sed -i '/Axis1scale=/c\Axis1scale=-0.6' /storage/.config/gzdoom/gzdoom.ini + sed -i '/vid_defheight=/c\vid_defheight=320' /storage/.config/gzdoom/gzdoom.ini + sed -i '/vid_defwidth=/c\vid_defwidth=480' /storage/.config/gzdoom/gzdoom.ini +fi + +#Map ppsspp controls +if grep RG351V -q "/stprage/.config/ppsspp/PSP/SYSTEM/controls.ini" +then + exit 1 +else +cat </storage/.config/ppsspp/PSP/SYSTEM/controls.ini +#RG351V +[ControlMapping] +Up = 10-19 +Down = 10-20 +Left = 10-21 +Right = 10-22 +Circle = 10-189 +Cross = 10-190 +Square = 10-188 +Triangle = 10-191 +Start = 10-197 +Select = 10-196 +L = 10-193 +R = 10-192 +An.Up = 10-4002 +An.Down = 10-4003 +An.Left = 10-4000 +An.Right = 10-4001 +Fast-forward = 1-61 +Pause = 10-106 +Save State = 10-4010 +Load State = 10-4008 +EOF +fi diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG351V/075-dpad-volbright b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG351V/075-dpad-volbright new file mode 100755 index 0000000000..287366f2f7 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG351V/075-dpad-volbright @@ -0,0 +1,47 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +DPAD_EVENTS=$(get_setting key.dpad.events) +if [ -z "${DPAD_EVENTS}" ] +then + set_setting key.dpad.events 1 +fi + +KEY_FUNC_A=$(get_setting key.function.a) +if [ -z "${KEY_FUNC_A}" ] +then + set_setting key.function.a BTN_WEST +fi + +KEY_FUNC_B=$(get_setting key.function.b) +if [ -z "${KEY_FUNC_B}" ] +then + set_setting key.function.b BTN_TR +fi + +KEY_HOT_A=$(get_setting key.hotkey.a) +if [ -z "${KEY_HOT_A}" ] +then + set_setting key.hotkey.a BTN_WEST +fi + +KEY_HOT_B=$(get_setting key.hotkey.b) +if [ -z "${KEY_HOT_B}" ] +then + set_setting key.hotkey.b BTN_TR +fi + +KEY_HOT_C=$(get_setting key.hotkey.c) +if [ -z "${KEY_HOT_C}" ] +then + set_setting key.hotkey.c BTN_TL +fi + +if [ "$(systemctl is-active input)" = "active" ] +then + systemctl restart input +fi diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353M b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353M new file mode 120000 index 0000000000..58afc9983f --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353M @@ -0,0 +1 @@ +Anbernic RG353P \ No newline at end of file diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353P/001-device_config b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353P/001-device_config new file mode 100644 index 0000000000..23e3b7e4f4 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353P/001-device_config @@ -0,0 +1,9 @@ +#!/bin/sh +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/001-device_config +DEVICE_FAKE_JACKSENSE="false" +DEVICE_BATTERY_LED_STATUS="false" +DEVICE_HAS_TOUCHSCREEN="true" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353P/020-gpios b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353P/020-gpios new file mode 100755 index 0000000000..357fcb1087 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353P/020-gpios @@ -0,0 +1,15 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/020-gpios +DEVICE_WIFI="0" +DEVICE_PWM_MOTOR="pwmchip1" +EOF + +. /storage/.config/profile.d/020-gpios +# Enable PWM for rumble and turn rumble off during startup. +echo 0 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/export +echo 1000000 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/period +echo 1 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/enable +echo 1000000 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/duty_cycle diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353P/040-display b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353P/040-display new file mode 100755 index 0000000000..efb4451642 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353P/040-display @@ -0,0 +1,17 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +# Configure default contrast saturation and hue values +for PROPERTY in brightness contrast saturation hue +do + MYVAL=$(get_setting display.${PROPERTY}) + if [ -z "${MYVAL}" ] + then + MYVAL=$(drm_tool list | sed -n '/Connector: 133/,$p' | awk '/'${PROPERTY}'/ {print $5}') + fi + paneladj ${PROPERTY} ${MYVAL} +done diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353P/info.d/001-panel b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353P/info.d/001-panel new file mode 100755 index 0000000000..da49dae9de --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353P/info.d/001-panel @@ -0,0 +1,18 @@ +#!/bin/sh +ID=$(dmesg | grep "panel") +case ${ID} in + *newvision*) + ID="v1" + ;; + *sitronix*) + ID="v2" + ;; + *) + ID="Unknown" + ;; +esac + +if [ -n "${ID}" ] +then + echo "PANEL VERSION: ${ID}" +fi diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353PS/001-device_config b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353PS/001-device_config new file mode 100644 index 0000000000..711360f081 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353PS/001-device_config @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/001-device_config +DEVICE_FAKE_JACKSENSE="false" +DEVICE_BATTERY_LED_STATUS="false" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353PS/020-gpios b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353PS/020-gpios new file mode 100755 index 0000000000..357fcb1087 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353PS/020-gpios @@ -0,0 +1,15 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/020-gpios +DEVICE_WIFI="0" +DEVICE_PWM_MOTOR="pwmchip1" +EOF + +. /storage/.config/profile.d/020-gpios +# Enable PWM for rumble and turn rumble off during startup. +echo 0 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/export +echo 1000000 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/period +echo 1 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/enable +echo 1000000 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/duty_cycle diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353PS/040-display b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353PS/040-display new file mode 100755 index 0000000000..efb4451642 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353PS/040-display @@ -0,0 +1,17 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +# Configure default contrast saturation and hue values +for PROPERTY in brightness contrast saturation hue +do + MYVAL=$(get_setting display.${PROPERTY}) + if [ -z "${MYVAL}" ] + then + MYVAL=$(drm_tool list | sed -n '/Connector: 133/,$p' | awk '/'${PROPERTY}'/ {print $5}') + fi + paneladj ${PROPERTY} ${MYVAL} +done diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353PS/info.d/001-panel b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353PS/info.d/001-panel new file mode 100755 index 0000000000..da49dae9de --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353PS/info.d/001-panel @@ -0,0 +1,18 @@ +#!/bin/sh +ID=$(dmesg | grep "panel") +case ${ID} in + *newvision*) + ID="v1" + ;; + *sitronix*) + ID="v2" + ;; + *) + ID="Unknown" + ;; +esac + +if [ -n "${ID}" ] +then + echo "PANEL VERSION: ${ID}" +fi diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353V/001-device_config b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353V/001-device_config new file mode 100755 index 0000000000..56822b0507 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353V/001-device_config @@ -0,0 +1,9 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/001-device_config +DEVICE_FAKE_JACKSENSE="true" +DEVICE_HEADPHONE_DEV="/dev/input/by-path/platform-rk817-sound-event" +DEVICE_HAS_TOUCHSCREEN="true" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353V/020-gpios b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353V/020-gpios new file mode 100755 index 0000000000..6085323127 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353V/020-gpios @@ -0,0 +1,17 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/020-gpios +DEVICE_WIFI="5" +DEVICE_LED="77" +DEVICE_PWM_MOTOR="pwmchip1" +DEVICE_JACK="86" +EOF + +. /storage/.config/profile.d/020-gpios +# Enable PWM for rumble and turn rumble off during startup. +echo 0 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/export +echo 1000000 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/period +echo 1 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/enable +echo 1000000 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/duty_cycle diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353V/040-display b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353V/040-display new file mode 100755 index 0000000000..efb4451642 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353V/040-display @@ -0,0 +1,17 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +# Configure default contrast saturation and hue values +for PROPERTY in brightness contrast saturation hue +do + MYVAL=$(get_setting display.${PROPERTY}) + if [ -z "${MYVAL}" ] + then + MYVAL=$(drm_tool list | sed -n '/Connector: 133/,$p' | awk '/'${PROPERTY}'/ {print $5}') + fi + paneladj ${PROPERTY} ${MYVAL} +done diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353V/050-audio_path b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353V/050-audio_path new file mode 100755 index 0000000000..c81d27781f --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353V/050-audio_path @@ -0,0 +1,10 @@ +#!/bin/sh +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2026-present ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/002-audio_path +ALSA_PRIMARY_CARD=1 +DEVICE_PLAYBACK_PATH_SPK="SPK" +DEVICE_PLAYBACK_PATH_HP="HP" +DEVICE_PLAYBACK_PATH="Playback Mux" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353V/info.d/001-panel b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353V/info.d/001-panel new file mode 100755 index 0000000000..da49dae9de --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353V/info.d/001-panel @@ -0,0 +1,18 @@ +#!/bin/sh +ID=$(dmesg | grep "panel") +case ${ID} in + *newvision*) + ID="v1" + ;; + *sitronix*) + ID="v2" + ;; + *) + ID="Unknown" + ;; +esac + +if [ -n "${ID}" ] +then + echo "PANEL VERSION: ${ID}" +fi diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353VS/001-device_config b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353VS/001-device_config new file mode 100755 index 0000000000..8b0c1e05d8 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353VS/001-device_config @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/001-device_config +DEVICE_FAKE_JACKSENSE="true" +DEVICE_HEADPHONE_DEV="/dev/input/by-path/platform-rk817-sound-event" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353VS/020-gpios b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353VS/020-gpios new file mode 100755 index 0000000000..6085323127 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353VS/020-gpios @@ -0,0 +1,17 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/020-gpios +DEVICE_WIFI="5" +DEVICE_LED="77" +DEVICE_PWM_MOTOR="pwmchip1" +DEVICE_JACK="86" +EOF + +. /storage/.config/profile.d/020-gpios +# Enable PWM for rumble and turn rumble off during startup. +echo 0 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/export +echo 1000000 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/period +echo 1 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/enable +echo 1000000 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/duty_cycle diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353VS/040-display b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353VS/040-display new file mode 100755 index 0000000000..efb4451642 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353VS/040-display @@ -0,0 +1,17 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +# Configure default contrast saturation and hue values +for PROPERTY in brightness contrast saturation hue +do + MYVAL=$(get_setting display.${PROPERTY}) + if [ -z "${MYVAL}" ] + then + MYVAL=$(drm_tool list | sed -n '/Connector: 133/,$p' | awk '/'${PROPERTY}'/ {print $5}') + fi + paneladj ${PROPERTY} ${MYVAL} +done diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353VS/050-audio_path b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353VS/050-audio_path new file mode 100755 index 0000000000..c81d27781f --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353VS/050-audio_path @@ -0,0 +1,10 @@ +#!/bin/sh +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2026-present ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/002-audio_path +ALSA_PRIMARY_CARD=1 +DEVICE_PLAYBACK_PATH_SPK="SPK" +DEVICE_PLAYBACK_PATH_HP="HP" +DEVICE_PLAYBACK_PATH="Playback Mux" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353VS/info.d/001-panel b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353VS/info.d/001-panel new file mode 100755 index 0000000000..da49dae9de --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG353VS/info.d/001-panel @@ -0,0 +1,18 @@ +#!/bin/sh +ID=$(dmesg | grep "panel") +case ${ID} in + *newvision*) + ID="v1" + ;; + *sitronix*) + ID="v2" + ;; + *) + ID="Unknown" + ;; +esac + +if [ -n "${ID}" ] +then + echo "PANEL VERSION: ${ID}" +fi diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG40XX H/010-analog_sticks_led_control b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG40XX H/010-analog_sticks_led_control new file mode 100755 index 0000000000..8a21241d44 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG40XX H/010-analog_sticks_led_control @@ -0,0 +1,7 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/010-analog_sticks_led_control +DEVICE_ANALOG_STICKS_LED_CONTROL="true" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG40XX H/bin/achievements b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG40XX H/bin/achievements new file mode 120000 index 0000000000..6dbb204a10 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG40XX H/bin/achievements @@ -0,0 +1 @@ +../../Anbernic RG CubeXX/bin/achievements \ No newline at end of file diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG40XX V/010-analog_sticks_led_control b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG40XX V/010-analog_sticks_led_control new file mode 100755 index 0000000000..8a21241d44 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG40XX V/010-analog_sticks_led_control @@ -0,0 +1,7 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/010-analog_sticks_led_control +DEVICE_ANALOG_STICKS_LED_CONTROL="true" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG40XX V/bin/achievements b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG40XX V/bin/achievements new file mode 120000 index 0000000000..6dbb204a10 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG40XX V/bin/achievements @@ -0,0 +1 @@ +../../Anbernic RG CubeXX/bin/achievements \ No newline at end of file diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG40XX V/bin/analog_sticks_ledcontrol b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG40XX V/bin/analog_sticks_ledcontrol new file mode 100755 index 0000000000..c25d209157 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG40XX V/bin/analog_sticks_ledcontrol @@ -0,0 +1,67 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +# Simple script to watch the battery capacity and +# turn the power LED orange when it reaches 30%, red at 20%, and blinking red at 10% + +# Define the serial device +SERIAL_DEVICE="/dev/ttyS2" +LED_PATH="/sys/class/leds" + +function led_state() { + echo ${2} >${LED_PATH}/${1}/brightness +} + +# Display usage if no parameters are provided +if [ $# -ne 7 ]; then + echo "Usage: $0 " + echo "Example: $0 255 255 0 0 0 0 255" + exit 1 +fi + +LED_MODE=1 +BRIGHTNESS=$1 +RIGHT_RED=$2 +RIGHT_GREEN=$3 +RIGHT_BLUE=$4 +LEFT_RED=$5 +LEFT_GREEN=$6 +LEFT_BLUE=$7 + +# Function to calculate checksum +calculate_checksum() { + local sum=0 + for byte in "$@"; do + sum=$((sum + byte)) + done + echo $((sum & 0xFF)) +} + +# Open the serial device +exec 20<>$SERIAL_DEVICE +stty -F $SERIAL_DEVICE 115200 -opost -isig -icanon -echo + +# Enable RGB LEDs +led_state rgb:kbd_backlight 1 + +# Construct the payload +PAYLOAD=$(printf '\\x%02X\\x%02X' $LED_MODE $BRIGHTNESS) +for ((i = 0; i < 16; i++)); do + PAYLOAD+=$(printf '\\x%02X\\x%02X\\x%02X' $LEFT_RED $LEFT_GREEN $LEFT_BLUE) +done + +# Calculate checksum for the payload +PAYLOAD_BYTES=($LED_MODE $BRIGHTNESS) +for ((i = 0; i < 16; i++)); do + PAYLOAD_BYTES+=($LEFT_RED $LEFT_GREEN $LEFT_BLUE) +done +CHECKSUM=$(calculate_checksum "${PAYLOAD_BYTES[@]}") +PAYLOAD+=$(printf '\\x%02X' $CHECKSUM) + +# Send the payload +echo -e -n "$PAYLOAD" > $SERIAL_DEVICE + +# Close the serial device +exec 20>&- diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG503/001-device_config b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG503/001-device_config new file mode 100755 index 0000000000..127677e36d --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG503/001-device_config @@ -0,0 +1,7 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/001-device_config +DEVICE_FAKE_JACKSENSE="false" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG503/020-gpios b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG503/020-gpios new file mode 100755 index 0000000000..357fcb1087 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG503/020-gpios @@ -0,0 +1,15 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/020-gpios +DEVICE_WIFI="0" +DEVICE_PWM_MOTOR="pwmchip1" +EOF + +. /storage/.config/profile.d/020-gpios +# Enable PWM for rumble and turn rumble off during startup. +echo 0 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/export +echo 1000000 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/period +echo 1 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/enable +echo 1000000 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/duty_cycle diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG503/040-display b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG503/040-display new file mode 100755 index 0000000000..efb4451642 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG503/040-display @@ -0,0 +1,17 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +# Configure default contrast saturation and hue values +for PROPERTY in brightness contrast saturation hue +do + MYVAL=$(get_setting display.${PROPERTY}) + if [ -z "${MYVAL}" ] + then + MYVAL=$(drm_tool list | sed -n '/Connector: 133/,$p' | awk '/'${PROPERTY}'/ {print $5}') + fi + paneladj ${PROPERTY} ${MYVAL} +done diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/001-device_config b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/001-device_config new file mode 100755 index 0000000000..d2500c0f50 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/001-device_config @@ -0,0 +1,18 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/001-device_config +# Device Features +DEVICE_FAKE_JACKSENSE="true" +DEVICE_AUDIO_MIXER="DAC" +DEVICE_PLAYBACK_PATH_SPK="1*" +DEVICE_PLAYBACK_PATH_HP="0*" +DEVICE_HEADPHONE_DEV="/dev/input/by-path/platform-es8316-sound-event" +DEVICE_HAS_HDMI="true" +DEVICE_BATTERY_LED_STATUS="true" +DEVICE_PWR_LED_CONTROL="true" +DEVICE_HAS_TOUCHSCREEN="true" + +DEVICE_TEMP_SENSOR=("/sys/devices/virtual/thermal/thermal_zone0/temp" "/sys/devices/virtual/thermal/thermal_zone1/temp") +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/009-commander-cfg b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/009-commander-cfg new file mode 100644 index 0000000000..e6dcf766af --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/009-commander-cfg @@ -0,0 +1,11 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025 ArchR (https://github.com/archr-linux/Arch-R) + +if [ ! -f "/storage/.config/commander.cfg" ]; then +cat </storage/.config/commander.cfg +disp_ppu_x=5 +disp_ppu_y=5 +EOF +fi diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/010-governors b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/010-governors new file mode 100755 index 0000000000..607c6c1c87 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/010-governors @@ -0,0 +1,14 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/010-governors +CPU_FREQ=("/sys/devices/system/cpu/cpufreq/policy0" "/sys/devices/system/cpu/cpufreq/policy4") +GPU_FREQ="/sys/devices/platform/ff9a0000.gpu/devfreq/ff9a0000.gpu" +DMC_FREQ="/sys/devices/platform/memory-controller/devfreq/memory-controller" +EOF + +### Lock in lowest freq we want to use +echo 1008000 > /sys/devices/system/cpu/cpufreq/policy0/scaling_min_freq +echo 1008000 > /sys/devices/system/cpu/cpufreq/policy4/scaling_min_freq +echo 600000000 > /sys/devices/platform/ff9a0000.gpu/devfreq/ff9a0000.gpu/min_freq diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/020-fan_control b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/020-fan_control new file mode 100755 index 0000000000..810e1d7147 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/020-fan_control @@ -0,0 +1,9 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/020-fan_control +DEVICE_HAS_FAN="true" +DEVICE_PWM_FAN="/sys/class/hwmon/hwmon1/pwm1" +DEVICE_FAN_INPUT="/sys/class/hwmon/hwmon1/pwm1" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/020-gpios b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/020-gpios new file mode 100755 index 0000000000..6250e3e37d --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/020-gpios @@ -0,0 +1,16 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/020-gpios +DEVICE_JACK="8" +DEVICE_HDMI_GPIO="54" +DEVICE_WIFI="113" +EOF + +. /storage/.config/profile.d/020-gpios +# Enable PWM for rumble and turn rumble off during startup. +echo 0 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/export +echo 1000000 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/period +echo 1 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/enable +echo 1000000 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/duty_cycle diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/030-enable_wifi b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/030-enable_wifi new file mode 100755 index 0000000000..5552ff87c5 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/030-enable_wifi @@ -0,0 +1,20 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile.d/001-functions + +# Get Internal Wifi State +INTERNAL_WIFI_STATE=$(get_setting "internal.wifi") +if [ ! -n "${INTERNAL_WIFI_STATE}" ]; then + INTERNAL_WIFI_STATE=1 + set_setting "internal.wifi" "1" +fi + +# Set export GPIO for Wifi and set state +if [ ! -d "/sys/class/gpio/gpio${DEVICE_WIFI}" ]; then + echo ${DEVICE_WIFI} > /sys/class/gpio/export + echo out > /sys/class/gpio/gpio${DEVICE_WIFI}/direction + echo ${INTERNAL_WIFI_STATE} > /sys/class/gpio/gpio${DEVICE_WIFI}/value +fi diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/050-audio_path b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/050-audio_path new file mode 100755 index 0000000000..14042766d4 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/050-audio_path @@ -0,0 +1,9 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/002-audio_path +DEVICE_AUDIO_MIXER="DAC" +DEVICE_PLAYBACK_PATH_SPK="1*" +DEVICE_PLAYBACK_PATH_HP="0*" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/050-game-configs b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/050-game-configs new file mode 100755 index 0000000000..1bb6f687b3 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/050-game-configs @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present JELOS (https://github.com/JustEnoughLinuxOS) + +#Remap joypad name to rg552_joypad +sed -i '/^mapping_name = retrogame_joypad/c\mapping_name = rg552_joypad' /storage/.config/flycast/mappings/SDL_retrogame_joypad.cfg +sed -i '/retrogame_joypad/c\[rg552_joypad]' /storage/.config/mupen64plus/custominput.ini +sed -i '/name = "retrogame_joypad"/c\name = "rg552_joypad"' /storage/.config/mupen64plus/mupen64plus.cfg + +#Fix ES input +for config in "/storage/.config/emulationstation/es_input.cfg"; do + if ! grep -q rg552_joypad "$config"; then + cp -r /usr/config/emulationstation/es_input.cfg /storage/.config/emulationstation/es_input.cfg + fi +done; diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/bin/fancontrol b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/bin/fancontrol new file mode 100755 index 0000000000..9a4749c3e0 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/bin/fancontrol @@ -0,0 +1,83 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile + +DEBUG=false +COOLING_PROFILE=$(get_setting "cooling.profile") +FAN_PWM="${DEVICE_PWM_FAN}" + +log $0 "Setting profile to ${COOLING_PROFILE}" + +function set_control() { + log $0 "Set fan control to ${1}" + if [ -e "${DEVICE_PWM_FAN}_enable" ] + then + echo ${1} >${DEVICE_PWM_FAN}_enable + fi +} + +trap "set_control 0 && exit 0" SIGHUP SIGINT SIGQUIT SIGABRT + +if [ -e "/storage/.config/fancontrol.conf" ] && [ "${COOLING_PROFILE}" = "custom" ] +then + log $0 "Loading configuration file" 2>/dev/null + source /storage/.config/fancontrol.conf + if [ ! $? = 0 ] + then + WARN="Custom fan profile could not be loaded, defaulting to auto." + log $0 "${WARN}" + COOLING_PROFILE="auto" + set_setting cooling.profile auto + fi +fi + + +if [ ! "${COOLING_PROFILE}" = "custom" ] +then + if [ "${COOLING_PROFILE}" = "aggressive" ] + then + SPEEDS=(255 225 195) + TEMPS=(55000 45000 0) + elif [ "${COOLING_PROFILE}" = "moderate" ] + then + SPEEDS=(255 192 128 96) + TEMPS=(65000 55000 45000 0) + elif [ "${COOLING_PROFILE}" = "quiet" ] + then + # Quiet. + SPEEDS=(255 192 128 96 64 48 32) + TEMPS=(70000 60000 55000 50000 49000 47000 0) + else + # auto + set_control 0 >/dev/null 2>&1 + exit 0 + fi +fi + +log $0 "Enabling fan control." +set_control 1 >/dev/null 2>&1 + +while true +do + INDEX=0 + CPU_TEMP=$(awk '{total += $1; count++} END {printf "%d", total/count}' ${DEVICE_TEMP_SENSOR}) + $DEBUG && log $0 "CPU TEMP: ${CPU_TEMP}" 2>/dev/null + for TEMP in "${TEMPS[@]}" + do + if (( "${CPU_TEMP}" > "${TEMP}" )) && \ + [ ! "${LASTSPEED}" = "${SPEEDS[${INDEX}]}" ] + then + $DEBUG && log $0 "Setting PWM FAN to ${SPEEDS[${INDEX}]} (${TEMP})" 2>/dev/null + echo ${SPEEDS[${INDEX}]} >${FAN_PWM} + LASTSPEED=${SPEEDS[${INDEX}]} + break + fi + INDEX=$(( $INDEX + 1 )) + done + sleep 2 +done + +log $0 "Disabling fan control." +set_control 0 >/dev/null 2>&1 diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/sleep.d/post/001-audio b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/sleep.d/post/001-audio new file mode 100755 index 0000000000..cf473483dd --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/sleep.d/post/001-audio @@ -0,0 +1,30 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Workaround for no audio on wake from sleep. + +. /etc/profile + +HDMI=$(pactl list sinks short | grep hdmi | cut -c 0-2) +SPEAKER=$(pactl list sinks short | grep es8316 | cut -c 0-2) + +#Set sink to one we aren't currently using +pactl set-default-sink ${SPEAKER} + +#Then check if HDMI is plugged and switch to HDMI + +# Set export GPIO for HDMI +if [ ! -d "/sys/class/gpio/gpio${DEVICE_HDMI_GPIO}" ]; then + echo ${DEVICE_HDMI_GPIO} > /sys/class/gpio/export + echo in > /sys/class/gpio/gpio${DEVICE_HDMI_GPIO}/direction +fi + +# Check HDMI plug state and switch to HDMI audo if true +HDMI_VALUE=$(cat /sys/class/gpio/gpio${DEVICE_HDMI_GPIO}/value) + case ${HDMI_VALUE} in + "0") + sleep 11 + pactl set-default-sink ${HDMI} + ;; + esac diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/sleep.d/post/002-freq b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/sleep.d/post/002-freq new file mode 100755 index 0000000000..7ba581fc1b --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/sleep.d/post/002-freq @@ -0,0 +1,32 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +### Restore previous governors before going to sleep + +. /etc/profile + +### Set max/min freq to lowest available value +echo 1008000 > /sys/devices/system/cpu/cpufreq/policy0/scaling_min_freq +echo 1008000 > /sys/devices/system/cpu/cpufreq/policy4/scaling_min_freq +echo 600000000 > /sys/devices/platform/ff9a0000.gpu/devfreq/ff9a0000.gpu/min_freq + +echo 1608000 > /sys/devices/system/cpu/cpufreq/policy0/scaling_max_freq +echo 2088000 > /sys/devices/system/cpu/cpufreq/policy4/scaling_max_freq +echo 900000000 > /sys/devices/platform/ff9a0000.gpu/devfreq/ff9a0000.gpu/max_freq + +### Grab the old governors. +OLD_CPU_FREQ=$(get_setting "sleep.cpugovernor") +if [ ! -n "${OLD_CPU_FREQ}" ]; then + OLD_CPU_FREQ="schedutil" +fi + +OLD_GPU_FREQ=$(get_setting "sleep.gpugovernor") +if [ ! -n "${OLD_GPU_FREQ}" ]; then + OLD_GPU_FREQ="simple_ondemand" +fi + +# Restore old governors. +set_cpu_gov "${OLD_CPU_FREQ}" +set_dmc_gov "${OLD_CPU_FREQ}" +set_gpu_gov "${OLD_GPU_FREQ}" diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/sleep.d/pre/001-audio b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/sleep.d/pre/001-audio new file mode 100755 index 0000000000..2dc5fd014a --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/sleep.d/pre/001-audio @@ -0,0 +1,16 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Workaround for no audio on wake from sleep. + +. /etc/profile + +HDMI=$(pactl list sinks short | grep hdmi | cut -c 0-2) +SPEAKER=$(pactl list sinks short | grep es8316 | cut -c 0-2) + +#Set sink to one we aren't currently using +pactl set-default-sink ${HDMI} + +#Suspend the sink we are using +pactl suspend-sink ${SPEAKER} 1 diff --git a/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/sleep.d/pre/002-freq b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/sleep.d/pre/002-freq new file mode 100755 index 0000000000..64d15b20ed --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Anbernic RG552/sleep.d/pre/002-freq @@ -0,0 +1,28 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Store current freq governors and set governors to powersave. + +. /etc/profile + +### Get the current cpu and gpu governor, save for when the device wakes from sleep. +CUR_CPU_FREQ="$(cat ${CPU_FREQ}/scaling_governor)" +CUR_GPU_FREQ="$(cat ${GPU_FREQ}/governor)" + +set_setting sleep.cpugovernor "${CUR_CPU_FREQ}" +set_setting sleep.gpugovernor "${CUR_GPU_FREQ}" + +### Set all governors to powersave +set_cpu_gov powersave +set_dmc_gov powersave +set_gpu_gov powersave + +### Set max/min freq to lowest available value +echo 600000 > /sys/devices/system/cpu/cpufreq/policy0/scaling_min_freq +echo 600000 > /sys/devices/system/cpu/cpufreq/policy4/scaling_min_freq +echo 200000000 > /sys/devices/platform/ff9a0000.gpu/devfreq/ff9a0000.gpu/min_freq + +echo 600000 > /sys/devices/system/cpu/cpufreq/policy0/scaling_max_freq +echo 600000 > /sys/devices/system/cpu/cpufreq/policy4/scaling_max_freq +echo 200000000 > /sys/devices/platform/ff9a0000.gpu/devfreq/ff9a0000.gpu/max_freq diff --git a/projects/ArchR/packages/hardware/quirks/devices/Game Console R33S/001-device_config b/projects/ArchR/packages/hardware/quirks/devices/Game Console R33S/001-device_config new file mode 100755 index 0000000000..243906cf13 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Game Console R33S/001-device_config @@ -0,0 +1,11 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/001-device_config +# Device Features +DEVICE_PLAYBACK_PATH_SPK="HP" +DEVICE_PLAYBACK_PATH_HP="SPK" +DEVICE_PWR_LED_GPIO="77" +DEVICE_TEMP_SENSOR="/sys/devices/virtual/thermal/thermal_zone0/temp" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Game Console R33S/002-disable-led b/projects/ArchR/packages/hardware/quirks/devices/Game Console R33S/002-disable-led new file mode 100755 index 0000000000..7e5ed7a899 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Game Console R33S/002-disable-led @@ -0,0 +1,13 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Set export GPIO for Power LED +if [ ! -d "/sys/class/gpio/gpio${DEVICE_PWR_LED_GPIO}" ]; then + echo ${DEVICE_PWR_LED_GPIO} > /sys/class/gpio/export +fi + +#Disable blue led on R33S +echo out >/sys/class/gpio/gpio${DEVICE_PWR_LED_GPIO}/direction +echo 1 >/sys/class/gpio/gpio${DEVICE_PWR_LED_GPIO}/value diff --git a/projects/ArchR/packages/hardware/quirks/devices/Game Console R33S/050-game-configs b/projects/ArchR/packages/hardware/quirks/devices/Game Console R33S/050-game-configs new file mode 100755 index 0000000000..9ab95ceaf2 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Game Console R33S/050-game-configs @@ -0,0 +1,260 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +#Set mupen64-plus-sa config for R33S +if [ ! -d "/storage/.config/mupen64plus" ]; then + mkdir -p "/storage/.config/mupen64plus/" + cp -r /usr/local/share/mupen64plus/mupen64plus.cfg* /storage/.config/mupen64plus/ +fi +if [ -f "/storage/.config/mupen64plus/mupen64plus.cfg.r33s" ]; then + rm /storage/.config/mupen64plus/mupen64plus.cfg + mv /storage/.config/mupen64plus/mupen64plus.cfg.r33s /storage/.config/mupen64plus/mupen64plus.cfg +fi + +#Set drastic-sa config for OGA +if [ ! -d "/storage/.config/drastic" ]; then + mkdir -p "/storage/.config/drastic" + cp -r "/usr/config/drastic" "/storage/.config/" +fi +if [ -f "/storage/.config/drastic/config/drastic.cfg.r33s" ]; then + mv /storage/.config/drastic/config/drastic.cfg.r33s /storage/.config/drastic/config/drastic.cfg +fi + + +#Set gzoom config for R33S +if [ ! -d "/storage/.config/gzdoom" ]; then + cp -r "/usr/config/gzdoom" "/storage/.config/" +fi + +#Set gzdoom settings +if grep R33S -q "/storage/.config/gzdoom/gzdoom.ini" +then + exit 1 +else +sed -i '/^[Doom.Bindings]/c\[Doom.Bindings] #R33S' /storage/.config/gzdoom/gzdoom.ini +sed -i '/^vid_defheight=/c\vid_defheight=480' /storage/.config/gzdoom/gzdoom.ini +sed -i '/^vid_defwidth=/c\vid_defwidth=640' /storage/.config/gzdoom/gzdoom.ini +sed -i '/^Joy1=/c\Joy1=+use' /storage/.config/gzdoom/gzdoom.ini +sed -i '/^Joy5=/c\Joy5=+speed' /storage/.config/gzdoom/gzdoom.ini +sed -i '/^Joy6=/c\Joy6=+attack' /storage/.config/gzdoom/gzdoom.ini +sed -i '/^Joy7=/c\Joy7=+moveleft' /storage/.config/gzdoom/gzdoom.ini +sed -i '/^Joy8=/c\Joy8=+moveright' /storage/.config/gzdoom/gzdoom.ini +sed -i '/^Joy9=/c\Joy9=menu_main' /storage/.config/gzdoom/gzdoom.ini +sed -i '/^Joy11=/c\Joy11=+forward' /storage/.config/gzdoom/gzdoom.ini +sed -i '/^Joy12=/c\Joy12=+back' /storage/.config/gzdoom/gzdoom.ini +sed -i '/^Joy13=/c\Joy13=+left' /storage/.config/gzdoom/gzdoom.ini +sed -i '/^Joy14=/c\Joy14=+right' /storage/.config/gzdoom/gzdoom.ini +sed -i '/^Joy2=/c\Joy2=+attack' /storage/.config/gzdoom/gzdoom.ini +fi + +#Set ppsspp config for R33S +if [ ! -d "/storage/.config/ppsspp" ]; then + mkdir -p "/storage/.config/ppsspp" + cp -r "/usr/config/ppsspp" "/storage/.config/" +fi + +#Map ppsspp controls +if grep R33S -q "/storage/.config/ppsspp/PSP/SYSTEM/controls.ini" +then + exit 1 +else +cat </storage/.config/ppsspp/PSP/SYSTEM/controls.ini +#R33S +[ControlMapping] +Up = 10-19 +Down = 10-20 +Left = 10-21 +Right = 10-22 +Circle = 10-189 +Cross = 10-190 +Square = 10-188 +Triangle = 10-191 +Start = 10-197 +Select = 10-196 +L = 10-193 +R = 10-192 +Fast-forward = 1-61 +Pause = 10-106 +Save State = 10-4010 +Load State = 10-4008 +EOF +fi + +#Set flycast ra config for R33S +if [ ! -d "/storage/remappings/Flycast" ]; then + mkdir -p "/storage/remappings/Flycast" +fi + +#Map flycast ra controls for R33S +if grep R33S -q "/storage/remappings/Flycast/Flycast.rmp" +then + exit 1 +else +cat </storage/remappings/Flycast/Flycast.rmp +#R33S +input_libretro_device_p1 = "1" +input_libretro_device_p2 = "1" +input_libretro_device_p3 = "1" +input_libretro_device_p4 = "1" +input_libretro_device_p5 = "1" +input_player1_analog_dpad_mode = "0" +input_player1_btn_down = "18" +input_player1_btn_left = "17" +input_player1_btn_right = "16" +input_player1_btn_up = "19" +input_player1_stk_l_x+ = "-1" +input_player1_stk_l_x- = "-1" +input_player1_stk_l_y+ = "-1" +input_player1_stk_l_y- = "-1" +input_player2_analog_dpad_mode = "0" +input_player3_analog_dpad_mode = "0" +input_player4_analog_dpad_mode = "0" +input_player5_analog_dpad_mode = "0" +input_remap_port_p1 = "0" +input_remap_port_p2 = "1" +input_remap_port_p3 = "2" +input_remap_port_p4 = "3" +input_remap_port_p5 = "4" +EOF +fi + +#Set Mupen64Plus GLES2 ra config for R33S +if [ ! -d "/storage/remappings/Mupen64Plus GLES2" ]; then + mkdir -p "/storage/remappings/Mupen64Plus GLES2" +fi + +#Map Mupen64Plus GLES2 ra controls for R33S +if grep R33S -q "/storage/remappings/Mupen64Plus GLES2/Mupen64Plus GLES2.rmp" +then + exit 1 +else +cat <"/storage/remappings/Mupen64Plus GLES2/Mupen64Plus GLES2.rmp" +#R33S +input_libretro_device_p1 = "1" +input_libretro_device_p2 = "1" +input_libretro_device_p3 = "1" +input_libretro_device_p4 = "1" +input_libretro_device_p5 = "1" +input_player1_analog_dpad_mode = "0" +input_player1_btn_a = "22" +input_player1_btn_down = "18" +input_player1_btn_l = "12" +input_player1_btn_l2 = "21" +input_player1_btn_left = "17" +input_player1_btn_r2 = "20" +input_player1_btn_right = "16" +input_player1_btn_up = "19" +input_player1_btn_x = "23" +input_player1_stk_l_x+ = "-1" +input_player1_stk_l_x- = "-1" +input_player1_stk_l_y+ = "-1" +input_player1_stk_l_y- = "-1" +input_player1_stk_r_x+ = "-1" +input_player1_stk_r_x- = "-1" +input_player1_stk_r_y+ = "-1" +input_player1_stk_r_y- = "-1" +input_player2_analog_dpad_mode = "0" +input_player3_analog_dpad_mode = "0" +input_player4_analog_dpad_mode = "0" +input_player5_analog_dpad_mode = "0" +input_remap_port_p1 = "0" +input_remap_port_p2 = "1" +input_remap_port_p3 = "2" +input_remap_port_p4 = "3" +input_remap_port_p5 = "4" +EOF +fi + +#Set Mupen64Plus-Next ra config for R33S +if [ ! -d "/storage/remappings/Mupen64Plus-Next" ]; then + mkdir -p "/storage/remappings/Mupen64Plus-Next" +fi + +#Map Mupen64Plus-Next ra controls for R33S +if grep R33S -q "/storage/remappings/Mupen64Plus-Next/Mupen64Plus-Next.rmp" +then + exit 1 +else +cat </storage/remappings/Mupen64Plus-Next/Mupen64Plus-Next.rmp +#R33S +input_libretro_device_p1 = "1" +input_libretro_device_p2 = "1" +input_libretro_device_p3 = "1" +input_libretro_device_p4 = "1" +input_libretro_device_p5 = "1" +input_player1_analog_dpad_mode = "0" +input_player1_btn_a = "22" +input_player1_btn_down = "18" +input_player1_btn_l = "12" +input_player1_btn_l2 = "21" +input_player1_btn_left = "17" +input_player1_btn_r2 = "20" +input_player1_btn_right = "16" +input_player1_btn_up = "19" +input_player1_btn_x = "23" +input_player1_stk_l_x+ = "-1" +input_player1_stk_l_x- = "-1" +input_player1_stk_l_y+ = "-1" +input_player1_stk_l_y- = "-1" +input_player1_stk_r_x+ = "-1" +input_player1_stk_r_x- = "-1" +input_player1_stk_r_y+ = "-1" +input_player1_stk_r_y- = "-1" +input_player2_analog_dpad_mode = "0" +input_player3_analog_dpad_mode = "0" +input_player4_analog_dpad_mode = "0" +input_player5_analog_dpad_mode = "0" +input_remap_port_p1 = "0" +input_remap_port_p2 = "1" +input_remap_port_p3 = "2" +input_remap_port_p4 = "3" +input_remap_port_p5 = "4" +EOF +fi + +#Set ParaLLEl N64 ra config for R33S +if [ ! -d "/storage/remappings/ParaLLEl N64" ]; then + mkdir -p "/storage/remappings/ParaLLEl N64" +fi + +#Map ParaLLEl N64 ra controls for R33S +if grep R33S -q "/storage/remappings/ParaLLEl N64/ParaLLEl N64.rmp" +then + exit 1 +else +cat <"/storage/remappings/ParaLLEl N64/ParaLLEl N64.rmp" +#R33S +input_libretro_device_p1 = "1" +input_libretro_device_p2 = "1" +input_libretro_device_p3 = "1" +input_libretro_device_p4 = "1" +input_libretro_device_p5 = "1" +input_player1_analog_dpad_mode = "0" +input_player1_btn_a = "22" +input_player1_btn_down = "18" +input_player1_btn_l = "12" +input_player1_btn_l2 = "21" +input_player1_btn_left = "17" +input_player1_btn_r2 = "20" +input_player1_btn_right = "16" +input_player1_btn_up = "19" +input_player1_btn_x = "23" +input_player1_stk_l_x+ = "-1" +input_player1_stk_l_x- = "-1" +input_player1_stk_l_y+ = "-1" +input_player1_stk_l_y- = "-1" +input_player1_stk_r_x+ = "-1" +input_player1_stk_r_x- = "-1" +input_player1_stk_r_y+ = "-1" +input_player1_stk_r_y- = "-1" +input_player2_analog_dpad_mode = "0" +input_player3_analog_dpad_mode = "0" +input_player4_analog_dpad_mode = "0" +input_player5_analog_dpad_mode = "0" +input_remap_port_p1 = "0" +input_remap_port_p2 = "1" +input_remap_port_p3 = "2" +input_remap_port_p4 = "3" +input_remap_port_p5 = "4 +EOF +fi diff --git a/projects/ArchR/packages/hardware/quirks/devices/Game Console R33S/075-dpad-volbright b/projects/ArchR/packages/hardware/quirks/devices/Game Console R33S/075-dpad-volbright new file mode 100755 index 0000000000..649e8f810d --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Game Console R33S/075-dpad-volbright @@ -0,0 +1,17 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +DPAD_EVENTS=$(get_setting key.dpad.events) +if [ -z "${DPAD_EVENTS}" ] +then + set_setting key.dpad.events 1 +fi + +if [ "$(systemctl is-active input)" = "active" ] +then + systemctl restart input +fi diff --git a/projects/ArchR/packages/hardware/quirks/devices/Game Console R36S/001-device_config b/projects/ArchR/packages/hardware/quirks/devices/Game Console R36S/001-device_config new file mode 100755 index 0000000000..243906cf13 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Game Console R36S/001-device_config @@ -0,0 +1,11 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/001-device_config +# Device Features +DEVICE_PLAYBACK_PATH_SPK="HP" +DEVICE_PLAYBACK_PATH_HP="SPK" +DEVICE_PWR_LED_GPIO="77" +DEVICE_TEMP_SENSOR="/sys/devices/virtual/thermal/thermal_zone0/temp" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Game Console R36S/002-disable-led b/projects/ArchR/packages/hardware/quirks/devices/Game Console R36S/002-disable-led new file mode 100755 index 0000000000..7e5ed7a899 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Game Console R36S/002-disable-led @@ -0,0 +1,13 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Set export GPIO for Power LED +if [ ! -d "/sys/class/gpio/gpio${DEVICE_PWR_LED_GPIO}" ]; then + echo ${DEVICE_PWR_LED_GPIO} > /sys/class/gpio/export +fi + +#Disable blue led on R33S +echo out >/sys/class/gpio/gpio${DEVICE_PWR_LED_GPIO}/direction +echo 1 >/sys/class/gpio/gpio${DEVICE_PWR_LED_GPIO}/value diff --git a/projects/ArchR/packages/hardware/quirks/devices/Game Console R36S/050-game-configs b/projects/ArchR/packages/hardware/quirks/devices/Game Console R36S/050-game-configs new file mode 100755 index 0000000000..f0b56405fa --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Game Console R36S/050-game-configs @@ -0,0 +1,57 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +#Set mupen64-plus-sa config for R36S, can use same profile as OGS +if [ ! -d "/storage/.config/mupen64plus" ]; then + mkdir -p "/storage/.config/mupen64plus/" + cp -r /usr/local/share/mupen64plus/mupen64plus.cfg* /storage/.config/mupen64plus/ +fi +if [ -f "/storage/.config/mupen64plus/mupen64plus.cfg.ogs" ]; then + rm /storage/.config/mupen64plus/mupen64plus.cfg + mv /storage/.config/mupen64plus/mupen64plus.cfg.ogs /storage/.config/mupen64plus/mupen64plus.cfg +fi + +#Set drastic-sa config for R36S (think it can use the same as RG20S) +if [ ! -d "/storage/.config/drastic" ]; then + mkdir -p "/storage/.config/drastic" + cp -r "/usr/config/drastic" "/storage/.config/" +fi +if [ -f "/storage/.config/drastic/config/drastic.cfg.r36s" ]; then + rm /storage/.config/drastic/config/drastic.cfg + mv /storage/.config/drastic/config/drastic.cfg.r36s /storage/.config/drastic/config/drastic.cfg +fi + +#Map ppsspp controls +if grep R36S -q "/storage/.config/ppsspp/PSP/SYSTEM/controls.ini" +then + exit 1 +else +cat </storage/.config/ppsspp/PSP/SYSTEM/controls.ini +#R36S +[ControlMapping] +Up = 10-19 +Down = 10-20 +Left = 10-21 +Right = 10-22 +Circle = 10-189 +Cross = 10-190 +Square = 10-188 +Triangle = 10-191 +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-106 +Save State = 10-4010 +Load State = 10-4008 +RightAn.Up = 10-4007 +RightAn.Down = 10-4006 +RightAn.Left = 10-4005 +RightAn.Right = 10-4004 +EOF +fi diff --git a/projects/ArchR/packages/hardware/quirks/devices/GameForce ACE/001-device_config b/projects/ArchR/packages/hardware/quirks/devices/GameForce ACE/001-device_config new file mode 100755 index 0000000000..290cdafa1a --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/GameForce ACE/001-device_config @@ -0,0 +1,17 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/001-device_config +# Device Features +#DEVICE_FAKE_JACKSENSE="true" +#DEVICE_AUDIO_MIXER="DAC" +#DEVICE_PLAYBACK_PATH_SPK="1*" +#DEVICE_PLAYBACK_PATH_HP="0*" +#DEVICE_HEADPHONE_DEV="/dev/input/by-path/platform-es8316-sound-event" +DEVICE_HAS_TOUCHSCREEN="true" +#DEVICE_BATTERY_LED_STATUS="true" +#DEVICE_PWR_LED_CONTROL="true" + +DEVICE_TEMP_SENSOR=("/sys/devices/virtual/thermal/thermal_zone0/temp" "/sys/devices/virtual/thermal/thermal_zone1/temp") +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/GameForce ACE/020-fan_control b/projects/ArchR/packages/hardware/quirks/devices/GameForce ACE/020-fan_control new file mode 100755 index 0000000000..2200d6e339 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/GameForce ACE/020-fan_control @@ -0,0 +1,9 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/020-fan_control +DEVICE_HAS_FAN="true" +DEVICE_PWM_FAN="/sys/class/hwmon/hwmon8/pwm1" +DEVICE_FAN_INPUT="/sys/class/hwmon/hwmon8/pwm1" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/GameForce ACE/030-suspend_mode b/projects/ArchR/packages/hardware/quirks/devices/GameForce ACE/030-suspend_mode new file mode 100755 index 0000000000..e2de620533 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/GameForce ACE/030-suspend_mode @@ -0,0 +1,11 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile.d/001-functions + +MYSLEEPMODE=$(get_setting system.suspendmode) +if [ -z "${MYSLEEPMODE}" ] +then + /usr/bin/suspendmode mem +fi diff --git a/projects/ArchR/packages/hardware/quirks/devices/GameForce ACE/050-modifiers b/projects/ArchR/packages/hardware/quirks/devices/GameForce ACE/050-modifiers new file mode 100644 index 0000000000..451df8c49a --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/GameForce ACE/050-modifiers @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/050-modifiers +DEVICE_FUNC_KEYA_MODIFIER="BTN_MODE" +DEVICE_FUNC_KEYB_MODIFIER="BTN_START" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/GameForce ACE/bin/fancontrol b/projects/ArchR/packages/hardware/quirks/devices/GameForce ACE/bin/fancontrol new file mode 100755 index 0000000000..3b34cb3efc --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/GameForce ACE/bin/fancontrol @@ -0,0 +1,111 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile + +### Enable logging +case $(get_setting system.loglevel) in + verbose) + DEBUG=true + ;; + *) + DEBUG=false + ;; +esac + +COOLING_PROFILE=$(get_setting "cooling.profile") +FAN_PWM="${DEVICE_PWM_FAN}" + +log $0 "Setting profile to ${COOLING_PROFILE}" + +function set_control() { + log $0 "Set fan control to ${1}" + if [ -e "${DEVICE_PWM_FAN}_enable" ] + then + echo ${1} >${DEVICE_PWM_FAN}_enable + fi +} + +trap "set_control 0 && exit 0" SIGHUP SIGINT SIGQUIT SIGABRT + +if [ -e "/storage/.config/fancontrol.conf" ] && [ "${COOLING_PROFILE}" = "custom" ] +then + log $0 "Loading configuration file" 2>/dev/null + source /storage/.config/fancontrol.conf + if [ ! $? = 0 ] + then + WARN="Custom fan profile could not be loaded, defaulting to auto." + log $0 "${WARN}" + COOLING_PROFILE="auto" + set_setting cooling.profile auto + fi +fi + + +if [ ! "${COOLING_PROFILE}" = "custom" ] +then + if [ "${COOLING_PROFILE}" = "aggressive" ] + then + SPEEDS=(195 225 255) + TEMPS=(45000 60000 80000) + elif [ "${COOLING_PROFILE}" = "moderate" ] + then + SPEEDS=(48 64 96 128 192 255) + TEMPS=(45000 55000 65000 75000 85000 90000) + elif [ "${COOLING_PROFILE}" = "quiet" ] + then + # Quiet. + SPEEDS=(24 32 48 64 96 128 192 255) + TEMPS=(35000 45000 50000 55000 65000 75000 85000 90000) + else + # auto + set_control 0 >/dev/null 2>&1 + exit 0 + fi +fi + +log $0 "Enabling fan control." +set_control 1 >/dev/null 2>&1 + +CURRENTSPEED=0 +TEMP=${TEMPS[0]} +declare -a HISTORY +while true +do + INDEX=0 + CPU_TEMP=$(awk '{total += $1; count++} END {printf "%d", total/count}' ${DEVICE_TEMP_SENSOR}) + + ### Keep a rolling history of CPU temps. + HISTORY+=(${CPU_TEMP}) + while (( ${#HISTORY[@]} > 10 )) + do + unset HISTORY[-0] + PRIOR_HISTORY=( ${HISTORY[*]} ) + HISTORY=( ${PRIOR_HISTORY[*]} ) + unset PRIOR_HISTORY + done + AVERAGE=$(echo $(IFS=+; echo "$((${HISTORY[*]}))") / ${#HISTORY[@]} | bc) + + $DEBUG && log $0 "Current/Average/Ceiling (Speed): ${CPU_TEMP}/${AVERAGE}/${TEMP} (${CURRENTSPEED})." + for TEMP in "${TEMPS[@]}" + do + if (( "${CPU_TEMP}" >= "90000" )) || \ + (( "${AVERAGE}" <= "${TEMP}" )) + then + if (( ${CURRENTSPEED} != ${SPEEDS[${INDEX}]} )) + then + CURRENTSPEED=${SPEEDS[${INDEX}]} + echo ${SPEEDS[${INDEX}]} >${FAN_PWM} + $DEBUG && log $0 "Set fan to ${CURRENTSPEED}." + fi + break + else + INDEX=$(( $INDEX + 1 )) + fi + done + sleep 2 +done + +log $0 "Disabling fan control." +set_control 0 >/dev/null 2>&1 diff --git a/projects/ArchR/packages/hardware/quirks/devices/GameForce ACE/sleep.d/post/001-audio b/projects/ArchR/packages/hardware/quirks/devices/GameForce ACE/sleep.d/post/001-audio new file mode 100755 index 0000000000..cf473483dd --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/GameForce ACE/sleep.d/post/001-audio @@ -0,0 +1,30 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Workaround for no audio on wake from sleep. + +. /etc/profile + +HDMI=$(pactl list sinks short | grep hdmi | cut -c 0-2) +SPEAKER=$(pactl list sinks short | grep es8316 | cut -c 0-2) + +#Set sink to one we aren't currently using +pactl set-default-sink ${SPEAKER} + +#Then check if HDMI is plugged and switch to HDMI + +# Set export GPIO for HDMI +if [ ! -d "/sys/class/gpio/gpio${DEVICE_HDMI_GPIO}" ]; then + echo ${DEVICE_HDMI_GPIO} > /sys/class/gpio/export + echo in > /sys/class/gpio/gpio${DEVICE_HDMI_GPIO}/direction +fi + +# Check HDMI plug state and switch to HDMI audo if true +HDMI_VALUE=$(cat /sys/class/gpio/gpio${DEVICE_HDMI_GPIO}/value) + case ${HDMI_VALUE} in + "0") + sleep 11 + pactl set-default-sink ${HDMI} + ;; + esac diff --git a/projects/ArchR/packages/hardware/quirks/devices/GameForce ACE/sleep.d/post/002-freq b/projects/ArchR/packages/hardware/quirks/devices/GameForce ACE/sleep.d/post/002-freq new file mode 100755 index 0000000000..4be1f2d5d7 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/GameForce ACE/sleep.d/post/002-freq @@ -0,0 +1,22 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +### Restore previous governors before going to sleep + +. /etc/profile + +### Grab the old governors. +OLD_CPU_FREQ=$(get_setting "sleep.cpugovernor") +if [ ! -n "${OLD_CPU_FREQ}" ]; then + OLD_CPU_FREQ="schedutil" +fi + +OLD_GPU_FREQ=$(get_setting "sleep.gpugovernor") +if [ ! -n "${OLD_GPU_FREQ}" ]; then + OLD_GPU_FREQ="simple_ondemand" +fi + +# Restore old governors. +set_cpu_gov "${OLD_CPU_FREQ}" +set_gpu_gov "${OLD_GPU_FREQ}" diff --git a/projects/ArchR/packages/hardware/quirks/devices/GameForce ACE/sleep.d/pre/002-freq b/projects/ArchR/packages/hardware/quirks/devices/GameForce ACE/sleep.d/pre/002-freq new file mode 100755 index 0000000000..a1c235ca32 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/GameForce ACE/sleep.d/pre/002-freq @@ -0,0 +1,18 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Store current freq governors and set governors to powersave. + +. /etc/profile + +### Get the current cpu and gpu governor, save for when the device wakes from sleep. +CUR_CPU_FREQ="$(cat ${CPU_FREQ}/scaling_governor)" +CUR_GPU_FREQ="$(cat ${GPU_FREQ}/governor)" + +set_setting sleep.cpugovernor "${CUR_CPU_FREQ}" +set_setting sleep.gpugovernor "${CUR_GPU_FREQ}" + +### Set all governors to powersave +set_cpu_gov powersave +set_gpu_gov powersave diff --git a/projects/ArchR/packages/hardware/quirks/devices/Gameforce CHI/001-device_config b/projects/ArchR/packages/hardware/quirks/devices/Gameforce CHI/001-device_config new file mode 100755 index 0000000000..f4da1b9ee1 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Gameforce CHI/001-device_config @@ -0,0 +1,14 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/001-device_config +# Device Features +DEVICE_PLAYBACK_PATH_SPK="HP" +DEVICE_PLAYBACK_PATH_HP="SPK" +DEVICE_VOLUME="100" +DEVICE_BATTERY_LED_STATUS="true" +DEVICE_PWR_LED_GPIO="77" +DEVICE_TEMP_SENSOR="/sys/devices/virtual/thermal/thermal_zone0/temp" +DEVICE_MMC_EJECT="false" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Gameforce CHI/002-start-input b/projects/ArchR/packages/hardware/quirks/devices/Gameforce CHI/002-start-input new file mode 100755 index 0000000000..d061f6564f --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Gameforce CHI/002-start-input @@ -0,0 +1,5 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +/usr/bin/gameforce-chi-gamepad diff --git a/projects/ArchR/packages/hardware/quirks/devices/Gameforce CHI/050-game_configs b/projects/ArchR/packages/hardware/quirks/devices/Gameforce CHI/050-game_configs new file mode 100755 index 0000000000..8c16e46ea8 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Gameforce CHI/050-game_configs @@ -0,0 +1,48 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +#Set up gzdoom +if [ ! -d "/storage/.config/gzdoom/" ]; then + cp -rf /usr/config/gzdoom /storage/.config/ + sed -i '/Joy7=/c\Joy7=togglemap' /storage/.config/gzdoom/gzdoom.ini + sed -i '/Joy8=/c\Joy8=menu_main' /storage/.config/gzdoom/gzdoom.ini + sed -i '/Axis0scale=/c\Axis0scale=-0.8' /storage/.config/gzdoom/gzdoom.ini + sed -i '/Axis1scale=/c\Axis1scale=-0.6' /storage/.config/gzdoom/gzdoom.ini + sed -i '/vid_defheight=/c\vid_defheight=320' /storage/.config/gzdoom/gzdoom.ini + sed -i '/vid_defwidth=/c\vid_defwidth=480' /storage/.config/gzdoom/gzdoom.ini +fi + +#Map ppsspp controls +if grep RG351M -q "/stprage/.config/ppsspp/PSP/SYSTEM/controls.ini" +then + exit 1 +else +cat </storage/.config/ppsspp/PSP/SYSTEM/controls.ini +#RG351M +[ControlMapping] +Up = 10-19 +Down = 10-20 +Left = 10-21 +Right = 10-22 +Circle = 10-189 +Cross = 10-190 +Square = 10-188 +Triangle = 10-191 +Start = 10-197 +Select = 10-196 +L = 10-193 +R = 10-192 +An.Up = 10-4002 +An.Down = 10-4003 +An.Left = 10-4000 +An.Right = 10-4001 +Fast-forward = 1-61 +Pause = 10-106 +Save State = 10-4010 +Load State = 10-4008 +RightAn.Up = 10-4007 +RightAn.Down = 10-4006 +RightAn.Left = 10-4005 +RightAn.Right = 10-4004 +EOF +fi diff --git a/projects/ArchR/packages/hardware/quirks/devices/Gameforce CHI/050-modifiers b/projects/ArchR/packages/hardware/quirks/devices/Gameforce CHI/050-modifiers new file mode 100755 index 0000000000..36df82c365 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Gameforce CHI/050-modifiers @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/050-modifiers +DEVICE_FUNC_KEYA_MODIFIER="BTN_THUMBL" +DEVICE_FUNC_KEYB_MODIFIER="BTN_THUMBR" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Generic EE clone/001-device_config b/projects/ArchR/packages/hardware/quirks/devices/Generic EE clone/001-device_config new file mode 100755 index 0000000000..7c27c554b0 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Generic EE clone/001-device_config @@ -0,0 +1,13 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/001-device_config +# Device Features +DEVICE_BATTERY_LED_STATUS="true" +DEVICE_TEMP_SENSOR="/sys/devices/virtual/thermal/thermal_zone0/temp" + +# disable legacy headphone script. ALSA UCM does that for us. +# See /usr/share/alsa/ucm2/Rockchip/rk817-sound/HiFi.conf +AUDIO_MANAGEMENT=UCM +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Generic EE clone/002-generate_dtbo b/projects/ArchR/packages/hardware/quirks/devices/Generic EE clone/002-generate_dtbo new file mode 100755 index 0000000000..ccceb1378f --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Generic EE clone/002-generate_dtbo @@ -0,0 +1,49 @@ +#!/bin/bash + +set -e + +STOCKPART="/dev/disk/by-label/EMUELEC" +DTBDIR="/flash/stock" +DTBOPATH="/flash/overlays/mipi-panel.dtbo" +TMPDIR="/tmp/flash_prepare" + +# no-op if dtbo already exists +[ -f "${DTBOPATH}" ] && exit 0 + +# Obtain stock dtb if needed and possible +if ! ls "${DTBDIR}"/*.dtb; then + if [ ! -L "${STOCKPART}" ]; then + echo "No stock dtb nor stock firmware partition found. Skipping dtbo generation" >&2 + exit 1 + fi + + # Prepare temporary destination + mkdir -p "${TMPDIR}/${DTBDIR}" + # Prepare source + mkdir -p /tmp/stock + mount "${STOCKPART}" /tmp/stock + # Copy all the dtbs (actually, there should be exactly one) + cp /tmp/stock/*.dtb "${TMPDIR}/${DTBDIR}" +fi + +STOCKDTB=$(ls "${DTBDIR}"/*.dtb "${TMPDIR}/${DTBDIR}"/*.dtb | head -1) +mkdir -p "${TMPDIR}/$(dirname ${DTBOPATH})" +echo "Preparing dtbo. This may take about a minute" +/usr/libexec/generic-dsi/archr_dtbo.py "${STOCKDTB}" -o "${TMPDIR}/${DTBOPATH}" + + +# Modifications to be made on firmaware partition +if [ -d "${TMPDIR}/flash" ]; then + mount -o remount,rw /flash + + rsync -av ${TMPDIR}/flash/ /flash || true + + # reinstall bootloader to switch console to UART5 + /usr/share/bootloader/update.sh + + # Cleanup and reboot + mount -o remount,ro /flash + sync +fi + +[ -f "${DTBOPATH}" ] && reboot diff --git a/projects/ArchR/packages/hardware/quirks/devices/Generic EE clone/010-led_control b/projects/ArchR/packages/hardware/quirks/devices/Generic EE clone/010-led_control new file mode 100755 index 0000000000..8ab918b534 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Generic EE clone/010-led_control @@ -0,0 +1,9 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/010-led_control +DEVICE_LED_CONTROL="false" +DEVICE_LED_BRIGHTNESS="false" +DEVICE_LED_CHARGING="false" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Generic EE clone/050-game_configs b/projects/ArchR/packages/hardware/quirks/devices/Generic EE clone/050-game_configs new file mode 100755 index 0000000000..ca19f23aed --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Generic EE clone/050-game_configs @@ -0,0 +1,58 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +#Set mupen64-plus-sa config for OGA +if [ ! -d "/storage/.config/mupen64plus" ]; then + mkdir -p "/storage/.config/mupen64plus/" + cp -r /usr/local/share/mupen64plus/mupen64plus.cfg* /storage/.config/mupen64plus/ +fi +if [ -f "/storage/.config/mupen64plus/mupen64plus.cfg.gen_2s" ]; then + rm /storage/.config/mupen64plus/mupen64plus.cfg + cp /storage/.config/mupen64plus/mupen64plus.cfg.gen_2s /storage/.config/mupen64plus/mupen64plus.cfg +fi + +#Set drastic-sa config for OGA +if [ ! -d "/storage/.config/drastic" ]; then + mkdir -p "/storage/.config/drastic" + cp -r "/usr/config/drastic" "/storage/.config/" +fi +if [ -f "/storage/.config/drastic/config/drastic.cfg.gen_2s" ]; then + cp /storage/.config/drastic/config/drastic.cfg.gen_2s /storage/.config/drastic/config/drastic.cfg +fi + +#Set ppsspp config for OGA +if [ ! -d "/storage/.config/ppsspp" ]; then + mkdir -p "/storage/.config/ppsspp" + cp -r "/usr/config/ppsspp" "/storage/.config/" +fi + +#Map ppsspp controls +if grep OGABE -q "/storage/.config/ppsspp/PSP/SYSTEM/controls.ini"; then + exit 1 +else + cat </storage/.config/ppsspp/PSP/SYSTEM/controls.ini +#OGABE +[ControlMapping] +Up = 10-19 +Down = 10-20 +Left = 10-21 +Right = 10-22 +Circle = 10-189 +Cross = 10-190 +Square = 10-188 +Triangle = 10-191 +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 +Fast-forward = 1-61 +Pause = 10-106 +Save State = 10-4010 +Load State = 10-4008 +EOF +fi diff --git a/projects/ArchR/packages/hardware/quirks/devices/Generic EE clone/050-modifiers b/projects/ArchR/packages/hardware/quirks/devices/Generic EE clone/050-modifiers new file mode 100755 index 0000000000..a710ab7129 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Generic EE clone/050-modifiers @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/050-modifiers +DEVICE_FUNC_KEYA_MODIFIER="BTN_MODE" +DEVICE_FUNC_KEYB_MODIFIER="BTN_THUMBR" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Generic EE clone/bin/battery_led_status b/projects/ArchR/packages/hardware/quirks/devices/Generic EE clone/bin/battery_led_status new file mode 100755 index 0000000000..ed90ac61df --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Generic EE clone/bin/battery_led_status @@ -0,0 +1,54 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +# Simple script to watch the battery capacity and +# turn the power LED to different states: +# Blinking red when charge is less than 20% +# Blue turns off when charge is less than 10% + +RED_TRIGGER=/sys/class/leds/red\:charging/trigger +BLUE_TRIGGER=/sys/class/leds/blue\:status/trigger + +function red_led() { + case $1 in + none) echo none > ${RED_TRIGGER};; + blink) echo timer > ${RED_TRIGGER};; + steady) echo default-on > ${RED_TRIGGER};; + esac +} + +function blue_led() { + case $1 in + none) echo none > ${BLUE_TRIGGER};; + blink) echo timer > ${BLUE_TRIGGER};; + steady) echo default-on > ${BLUE_TRIGGER};; + 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 + blue_led none + red_led blink + continue + elif (( ${CAP} <= 20 )); then + blue_led steady + red_led blink + else + blue_led steady + red_led none + fi + elif (( ${CAP} <= 95 )); then + blue_led steady + red_led steady + else + blue_led steady + red_led none + fi + sleep 15 +done diff --git a/projects/ArchR/packages/hardware/quirks/devices/Hardkernel ODROID-GO-Ultra/001-device_config b/projects/ArchR/packages/hardware/quirks/devices/Hardkernel ODROID-GO-Ultra/001-device_config new file mode 100755 index 0000000000..39c6111a9a --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Hardkernel ODROID-GO-Ultra/001-device_config @@ -0,0 +1,9 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/001-device_config +DEVICE_FAKE_JACKSENSE="true" +DEVICE_HEADPHONE_DEV="/dev/input/by-path/platform-gpio-keys-event" +DEVICE_TEMP_SENSOR=("/sys/devices/virtual/thermal/thermal_zone0/temp" "/sys/devices/virtual/thermal/thermal_zone3/temp" "/sys/devices/virtual/thermal/thermal_zone2/temp") +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Hardkernel ODROID-GO-Ultra/002-turbo-mode_config b/projects/ArchR/packages/hardware/quirks/devices/Hardkernel ODROID-GO-Ultra/002-turbo-mode_config new file mode 100755 index 0000000000..f1b68db2fe --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Hardkernel ODROID-GO-Ultra/002-turbo-mode_config @@ -0,0 +1,7 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/002-turbo-mode_config +DEVICE_TURBO_MODE="true" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Hardkernel ODROID-GO-Ultra/050-audio_path b/projects/ArchR/packages/hardware/quirks/devices/Hardkernel ODROID-GO-Ultra/050-audio_path new file mode 100755 index 0000000000..f0a9c4d2ec --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Hardkernel ODROID-GO-Ultra/050-audio_path @@ -0,0 +1,18 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/002-audio_path +DEVICE_PLAYBACK_PATH_SPK="SPK" +DEVICE_PLAYBACK_PATH_HP="HP" +DEVICE_PLAYBACK_PATH="Playback Mux" +DEVICE_PIPEWIRE_PROFILE="pro-audio" +EOF + +### Set sound properties +amixer -c 0 -q sset 'FRDDR_A SINK 1 SEL' 'OUT 1' +amixer -c 0 -q sset 'FRDDR_A SRC 1 EN' 'on' + +### Required with kernels after 6.12 - restart pipewire so the +### source / sink get picked up correctly by wireplumber +systemctl restart pipewire diff --git a/projects/ArchR/packages/hardware/quirks/devices/Hardkernel ODROID-GO-Ultra/050-game_configs b/projects/ArchR/packages/hardware/quirks/devices/Hardkernel ODROID-GO-Ultra/050-game_configs new file mode 100755 index 0000000000..de8cffc1a2 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Hardkernel ODROID-GO-Ultra/050-game_configs @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +#Set up gzdoom +if [ ! -d "/storage/.config/gzdoom/" ]; then + cp -rf /usr/config/gzdoom /storage/.config/ + sed -i '/Joy18=/c\Joy18=togglemap' /storage/.config/gzdoom/gzdoom.ini + sed -i '/Joy13=/c\Joy13=menu_main' /storage/.config/gzdoom/gzdoom.ini + sed -i '/vid_defheight=/c\vid_defheight=480' /storage/.config/gzdoom/gzdoom.ini + sed -i '/vid_defwidth=/c\vid_defwidth=854' /storage/.config/gzdoom/gzdoom.ini +fi diff --git a/projects/ArchR/packages/hardware/quirks/devices/KONKR Pocket FIT b/projects/ArchR/packages/hardware/quirks/devices/KONKR Pocket FIT new file mode 120000 index 0000000000..ec802bb776 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/KONKR Pocket FIT @@ -0,0 +1 @@ +AYANEO Pocket S2 \ No newline at end of file diff --git a/projects/ArchR/packages/hardware/quirks/devices/MagicX XU Mini M/001-device_config b/projects/ArchR/packages/hardware/quirks/devices/MagicX XU Mini M/001-device_config new file mode 100755 index 0000000000..e3b1984b95 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/MagicX XU Mini M/001-device_config @@ -0,0 +1,12 @@ + +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/001-device_config +# Device Features +DEVICE_PLAYBACK_PATH_SPK="HP" +DEVICE_PLAYBACK_PATH_HP="SPK" +DEVICE_BATTERY_LED_STATUS="true" +DEVICE_TEMP_SENSOR="/sys/devices/virtual/thermal/thermal_zone0/temp" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/MagicX XU Mini M/004-game-configs b/projects/ArchR/packages/hardware/quirks/devices/MagicX XU Mini M/004-game-configs new file mode 100755 index 0000000000..588565ef25 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/MagicX XU Mini M/004-game-configs @@ -0,0 +1,54 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +#Set mupen64-plus-sa config for XU Mini M +if [ ! -d "/storage/.config/mupen64plus" ]; then + mkdir -p /storage/.config/mupen64plus + cp -r /usr/local/share/mupen64plus/mupen64plus.cfg* /storage/.config/mupen64plus +fi +if [ -f "/storage/.config/mupen64plus/mupen64plus.cfg.xut" ]; then + rm /storage/.config/mupen64plus/mupen64plus.cfg + mv /storage/.config/mupen64plus/mupen64plus.cfg.xut /storage/.config/mupen64plus/mupen64plus.cfg +fi + +#Set drastic-sa config for XU Mini M +if [ ! -d "/storage/.config/drastic" ]; then + mkdir -p "/storage/.config/drastic" + cp -r /usr/config/drastic /storage/.config +fi +if [ -f "/storage/.config/drastic/config/drastic.cfg.xut" ]; then + rm /storage/.config/drastic/config/drastic.cfg + mv /storage/.config/drastic/config/drastic.cfg.xut /storage/.config/drastic/config/drastic.cfg +fi + +#Map ppsspp controls +if grep XUMiniM -q "/storage/.config/ppsspp/PSP/SYSTEM/controls.ini"; then + exit 1 +else +cat </storage/.config/ppsspp/PSP/SYSTEM/controls.ini +#XUMiniM +[ControlMapping] +Up = 10-19 +Down = 10-20 +Left = 10-21 +Right = 10-22 +Circle = 10-189 +Cross = 10-190 +Square = 10-188 +Triangle = 10-191 +Start = 10-197 +Select = 10-196 +L = 10-193 +R = 10-192 +An.Up = 10-4000 +An.Down = 10-4001 +An.Left = 10-4003 +An.Right = 10-4002 +Pause = 10-196:10-4008 +RightAn.Up = 10-4004 +RightAn.Down = 10-4005 +RightAn.Left = 10-4007 +RightAn.Right = 10-4006 +EOF +fi diff --git a/projects/ArchR/packages/hardware/quirks/devices/MagicX XU Mini M/010-led_control b/projects/ArchR/packages/hardware/quirks/devices/MagicX XU Mini M/010-led_control new file mode 100755 index 0000000000..8ab918b534 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/MagicX XU Mini M/010-led_control @@ -0,0 +1,9 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/010-led_control +DEVICE_LED_CONTROL="false" +DEVICE_LED_BRIGHTNESS="false" +DEVICE_LED_CHARGING="false" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/MagicX XU Mini M/bin/battery_led_status b/projects/ArchR/packages/hardware/quirks/devices/MagicX XU Mini M/bin/battery_led_status new file mode 100755 index 0000000000..9667e06d26 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/MagicX XU Mini M/bin/battery_led_status @@ -0,0 +1,59 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +# Simple script to watch the battery capacity and +# turn the power LED to different states: +# 0-10% flashing blue and teal +# 11-20% teal +# 21+% blue +# charging purple +# fully charged white + +function set_led() { + case $1 in + white) + echo 1 > /sys/class/leds/red\:charging/brightness + echo 1 > /sys/class/leds/green\:status/brightness + ;; + purple) + echo 1 > /sys/class/leds/red\:charging/brightness + echo 0 > /sys/class/leds/green\:status/brightness + ;; + blue) + echo 0 > /sys/class/leds/red\:charging/brightness + echo 0 > /sys/class/leds/green\:status/brightness + ;; + teal) + echo 0 > /sys/class/leds/red\:charging/brightness + echo 1 > /sys/class/leds/green\:status/brightness + ;; + 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 teal + sleep .5 + set_led blue + sleep .5 + done + continue + elif (( ${CAP} <= 20 )); then + set_led teal + else + set_led blue + fi + elif (( ${CAP} <= 95 )); then + set_led purple + else + set_led white + fi + sleep 15 +done diff --git a/projects/ArchR/packages/hardware/quirks/devices/MagicX XU10/001-device_config b/projects/ArchR/packages/hardware/quirks/devices/MagicX XU10/001-device_config new file mode 100755 index 0000000000..be8c1c57b9 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/MagicX XU10/001-device_config @@ -0,0 +1,11 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/001-device_config +# Device Features +DEVICE_PLAYBACK_PATH_SPK="SPK" +DEVICE_PLAYBACK_PATH_HP="HP" +DEVICE_BATTERY_LED_STATUS="true" +DEVICE_TEMP_SENSOR="/sys/devices/virtual/thermal/thermal_zone0/temp" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/MagicX XU10/004-game-configs b/projects/ArchR/packages/hardware/quirks/devices/MagicX XU10/004-game-configs new file mode 100755 index 0000000000..130dce137d --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/MagicX XU10/004-game-configs @@ -0,0 +1,55 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +#Set mupen64-plus-sa config for XU10 +if [ ! -d "/storage/.config/mupen64plus" ]; then + mkdir -p "/storage/.config/mupen64plus/" + cp -r /usr/local/share/mupen64plus/mupen64plus.cfg* /storage/.config/mupen64plus/ +fi +if [ -f "/storage/.config/mupen64plus/mupen64plus.cfg.xut" ]; then + rm /storage/.config/mupen64plus/mupen64plus.cfg + mv /storage/.config/mupen64plus/mupen64plus.cfg.xut /storage/.config/mupen64plus/mupen64plus.cfg +fi + +#Set drastic-sa config for XU10 +if [ ! -d "/storage/.config/drastic" ]; then + mkdir -p "/storage/.config/drastic" + cp -r "/usr/config/drastic" "/storage/.config/" +fi +if [ -f "/storage/.config/drastic/config/drastic.cfg.xut" ]; then + rm /storage/.config/drastic/config/drastic.cfg + mv /storage/.config/drastic/config/drastic.cfg.xut /storage/.config/drastic/config/drastic.cfg +fi + +#Map ppsspp controls +if grep XU10 -q "/storage/.config/ppsspp/PSP/SYSTEM/controls.ini" +then + exit 1 +else +cat </storage/.config/ppsspp/PSP/SYSTEM/controls.ini +#XU10 +[ControlMapping] +Up = 10-19 +Down = 10-20 +Left = 10-21 +Right = 10-22 +Circle = 10-190 +Cross = 10-189 +Square = 10-191 +Triangle = 10-188 +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-109,10-104,1-111 +RightAn.Up = 10-4007 +RightAn.Down = 10-4006 +RightAn.Left = 10-4005 +RightAn.Right = 10-4004 +EOF +fi diff --git a/projects/ArchR/packages/hardware/quirks/devices/MagicX XU10/bin/battery_led_status b/projects/ArchR/packages/hardware/quirks/devices/MagicX XU10/bin/battery_led_status new file mode 100755 index 0000000000..089ce1370a --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/MagicX XU10/bin/battery_led_status @@ -0,0 +1,65 @@ +#!/bin/sh + +# 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 to different states: +# 0-10% flashing blue and teal +# 11-20% teal +# 21+% blue +# charging purple +# fully charged white + +function set_led() { + case $1 in + white) + echo 1 > /sys/class/leds/red\:charging/brightness + echo 1 > /sys/class/leds/green\:status/brightness + ;; + purple) + echo 1 > /sys/class/leds/red\:charging/brightness + echo 0 > /sys/class/leds/green\:status/brightness + ;; + blue) + echo 0 > /sys/class/leds/red\:charging/brightness + echo 0 > /sys/class/leds/green\:status/brightness + ;; + teal) + echo 0 > /sys/class/leds/red\:charging/brightness + echo 1 > /sys/class/leds/green\:status/brightness + ;; + 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 teal + sleep .5 + set_led blue + sleep .5 + done + continue + elif (( ${CAP} <= 20 )) + then + set_led teal + else + set_led blue + fi + elif (( ${CAP} <= 95 )) + then + set_led purple + else + set_led white + fi + sleep 15 +done diff --git a/projects/ArchR/packages/hardware/quirks/devices/ODROID-GO Advance Black Edition/001-device_config b/projects/ArchR/packages/hardware/quirks/devices/ODROID-GO Advance Black Edition/001-device_config new file mode 100755 index 0000000000..894b320b32 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/ODROID-GO Advance Black Edition/001-device_config @@ -0,0 +1,11 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/001-device_config +# Device Features +DEVICE_SW_HP_SWITCH="true" +DEVICE_PLAYBACK_PATH_SPK="SPK" +DEVICE_PLAYBACK_PATH_HP="HP" +DEVICE_MMC_EJECT="false" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/ODROID-GO Advance Black Edition/009-commander-cfg b/projects/ArchR/packages/hardware/quirks/devices/ODROID-GO Advance Black Edition/009-commander-cfg new file mode 100644 index 0000000000..a9c4b8bd72 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/ODROID-GO Advance Black Edition/009-commander-cfg @@ -0,0 +1,11 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025 ArchR (https://github.com/archr-linux/Arch-R) + +if [ ! -f "/storage/.config/commander.cfg" ]; then +cat </storage/.config/commander.cfg +disp_ppu_x=1.5 +disp_ppu_y=1.5 +EOF +fi diff --git a/projects/ArchR/packages/hardware/quirks/devices/ODROID-GO Advance Black Edition/050-game_configs b/projects/ArchR/packages/hardware/quirks/devices/ODROID-GO Advance Black Edition/050-game_configs new file mode 100755 index 0000000000..8289182285 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/ODROID-GO Advance Black Edition/050-game_configs @@ -0,0 +1,59 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +#Set mupen64-plus-sa config for OGA +if [ ! -d "/storage/.config/mupen64plus" ]; then + mkdir -p "/storage/.config/mupen64plus/" + cp -r /usr/local/share/mupen64plus/mupen64plus.cfg* /storage/.config/mupen64plus/ +fi +if [ -f "/storage/.config/mupen64plus/mupen64plus.cfg.ogabe" ]; then + rm /storage/.config/mupen64plus/mupen64plus.cfg + cp /storage/.config/mupen64plus/mupen64plus.cfg.ogabe /storage/.config/mupen64plus/mupen64plus.cfg +fi + +#Set drastic-sa config for OGA +if [ ! -d "/storage/.config/drastic" ]; then + mkdir -p "/storage/.config/drastic" + cp -r "/usr/config/drastic" "/storage/.config/" +fi +if [ -f "/storage/.config/drastic/config/drastic.cfg.ogabe" ]; then + cp /storage/.config/drastic/config/drastic.cfg.ogabe /storage/.config/drastic/config/drastic.cfg +fi + +#Set ppsspp config for OGA +if [ ! -d "/storage/.config/ppsspp" ]; then + mkdir -p "/storage/.config/ppsspp" + cp -r "/usr/config/ppsspp" "/storage/.config/" +fi + +#Map ppsspp controls +if grep OGABE -q "/storage/.config/ppsspp/PSP/SYSTEM/controls.ini" +then + exit 1 +else +cat </storage/.config/ppsspp/PSP/SYSTEM/controls.ini +#OGABE +[ControlMapping] +Up = 10-19 +Down = 10-20 +Left = 10-21 +Right = 10-22 +Circle = 10-189 +Cross = 10-190 +Square = 10-188 +Triangle = 10-191 +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 +Fast-forward = 1-61 +Pause = 10-106 +Save State = 10-4010 +Load State = 10-4008 +EOF +fi diff --git a/projects/ArchR/packages/hardware/quirks/devices/ODROID-GO Advance/001-device_config b/projects/ArchR/packages/hardware/quirks/devices/ODROID-GO Advance/001-device_config new file mode 100755 index 0000000000..e19e45f1b9 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/ODROID-GO Advance/001-device_config @@ -0,0 +1,15 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/001-device_config +# Device Features +DEVICE_PLAYBACK_PATH_SPK="SPK" +DEVICE_PLAYBACK_PATH_HP="HP" +DEVICE_SW_HP_SWITCH="true" +DEVICE_VOLUME="100" +DEVICE_BATTERY_LED_STATUS="true" +DEVICE_PWR_LED_GPIO="77" +DEVICE_TEMP_SENSOR="/sys/devices/virtual/thermal/thermal_zone0/temp" +DEVICE_MMC_EJECT="false" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/ODROID-GO Advance/009-commander-cfg b/projects/ArchR/packages/hardware/quirks/devices/ODROID-GO Advance/009-commander-cfg new file mode 100644 index 0000000000..a9c4b8bd72 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/ODROID-GO Advance/009-commander-cfg @@ -0,0 +1,11 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025 ArchR (https://github.com/archr-linux/Arch-R) + +if [ ! -f "/storage/.config/commander.cfg" ]; then +cat </storage/.config/commander.cfg +disp_ppu_x=1.5 +disp_ppu_y=1.5 +EOF +fi diff --git a/projects/ArchR/packages/hardware/quirks/devices/ODROID-GO Advance/050-game_configs b/projects/ArchR/packages/hardware/quirks/devices/ODROID-GO Advance/050-game_configs new file mode 100755 index 0000000000..1d0b5f1460 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/ODROID-GO Advance/050-game_configs @@ -0,0 +1,52 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +#Set mupen64-plus-sa config for OGA +if [ ! -d "/storage/.config/mupen64plus" ]; then + mkdir -p "/storage/.config/mupen64plus/" + cp -r /usr/local/share/mupen64plus/mupen64plus.cfg* /storage/.config/mupen64plus/ +fi +if [ -f "/storage/.config/mupen64plus/mupen64plus.cfg.oga" ]; then + rm /storage/.config/mupen64plus/mupen64plus.cfg + mv /storage/.config/mupen64plus/mupen64plus.cfg.oga /storage/.config/mupen64plus/mupen64plus.cfg +fi + +#Set drastic-sa config for OGA +if [ ! -d "/storage/.config/drastic" ]; then + mkdir -p "/storage/.config/drastic" + cp -r "/usr/config/drastic" "/storage/.config/" +fi +if [ -f "/storage/.config/drastic/config/drastic.cfg.oga" ]; then + rm /storage/.config/drastic/config/drastic.cfg + mv /storage/.config/drastic/config/drastic.cfg.oga /storage/.config/drastic/config/drastic.cfg +fi + +#Map ppsspp controls +if grep OGA-1.0 -q "/storage/.config/ppsspp/PSP/SYSTEM/controls.ini" +then + exit 1 +else +cat </storage/.config/ppsspp/PSP/SYSTEM/controls.ini +#OGA-1.0 +[ControlMapping] +Up = 10-19 +Down = 10-20 +Left = 10-21 +Right = 10-22 +Circle = 10-189 +Cross = 10-190 +Square = 10-188 +Triangle = 10-191 +Start = 10-107 +Select = 10-4008 +L = 10-193 +R = 10-192 +An.Up = 10-4002 +An.Down = 10-4003 +An.Left = 10-4000 +An.Right = 10-4001 +Fast-forward = 1-61 +Save State = 10-106 +EOF +fi diff --git a/projects/ArchR/packages/hardware/quirks/devices/ODROID-GO Super/001-device_config b/projects/ArchR/packages/hardware/quirks/devices/ODROID-GO Super/001-device_config new file mode 100755 index 0000000000..17bd55e1e3 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/ODROID-GO Super/001-device_config @@ -0,0 +1,10 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/001-device_config +# Device Features +DEVICE_PLAYBACK_PATH_SPK="SPK" +DEVICE_PLAYBACK_PATH_HP="HP" +DEVICE_MMC_EJECT="false" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/ODROID-GO Super/050-game_configs b/projects/ArchR/packages/hardware/quirks/devices/ODROID-GO Super/050-game_configs new file mode 100755 index 0000000000..e7beaa7073 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/ODROID-GO Super/050-game_configs @@ -0,0 +1,57 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +#Set mupen64-plus-sa config for OGS +if [ ! -d "/storage/.config/mupen64plus" ]; then + mkdir -p "/storage/.config/mupen64plus/" + cp -r /usr/local/share/mupen64plus/mupen64plus.cfg* /storage/.config/mupen64plus/ +fi +if [ -f "/storage/.config/mupen64plus/mupen64plus.cfg.ogs" ]; then + rm /storage/.config/mupen64plus/mupen64plus.cfg + mv /storage/.config/mupen64plus/mupen64plus.cfg.ogs /storage/.config/mupen64plus/mupen64plus.cfg +fi + +#Set drastic-sa config for OGS +if [ ! -d "/storage/.config/drastic" ]; then + mkdir -p "/storage/.config/drastic" + cp -r "/usr/config/drastic" "/storage/.config/" +fi +if [ -f "/storage/.config/drastic/config/drastic.cfg.ogs" ]; then + rm /storage/.config/drastic/config/drastic.cfg + mv /storage/.config/drastic/config/drastic.cfg.ogs /storage/.config/drastic/config/drastic.cfg +fi + +#Map ppsspp controls +if grep OGS -q "/storage/.config/ppsspp/PSP/SYSTEM/controls.ini" +then + exit 1 +else +cat </storage/.config/ppsspp/PSP/SYSTEM/controls.ini +#OGS +[ControlMapping] +Up = 10-19 +Down = 10-20 +Left = 10-21 +Right = 10-22 +Circle = 10-189 +Cross = 10-190 +Square = 10-188 +Triangle = 10-191 +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-106 +Save State = 10-4010 +Load State = 10-4008 +RightAn.Up = 10-4007 +RightAn.Down = 10-4006 +RightAn.Left = 10-4005 +RightAn.Right = 10-4004 +EOF +fi diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10 MAX 3 Pro/050-audio_path b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10 MAX 3 Pro/050-audio_path new file mode 100755 index 0000000000..091625192e --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10 MAX 3 Pro/050-audio_path @@ -0,0 +1,18 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/002-audio_path +DEVICE_PLAYBACK_PATH_SPK="HP" +DEVICE_PLAYBACK_PATH_HP="SPK" +DEVICE_PLAYBACK_PATH="Playback Path" +DEVICE_PIPEWIRE_PROFILE="pro-audio" +EOF + +### Set sound properties +amixer -c 0 -q sset 'FRDDR_A SINK 1 SEL' 'OUT 1' +amixer -c 0 -q sset 'FRDDR_A SRC 1 EN' 'on' + +### Required with kernels after 6.12 - restart pipewire so the +### source / sink get picked up correctly by wireplumber +systemctl restart pipewire diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10 MAX 3 Pro/050-game_configs b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10 MAX 3 Pro/050-game_configs new file mode 100755 index 0000000000..de8cffc1a2 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10 MAX 3 Pro/050-game_configs @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +#Set up gzdoom +if [ ! -d "/storage/.config/gzdoom/" ]; then + cp -rf /usr/config/gzdoom /storage/.config/ + sed -i '/Joy18=/c\Joy18=togglemap' /storage/.config/gzdoom/gzdoom.ini + sed -i '/Joy13=/c\Joy13=menu_main' /storage/.config/gzdoom/gzdoom.ini + sed -i '/vid_defheight=/c\vid_defheight=480' /storage/.config/gzdoom/gzdoom.ini + sed -i '/vid_defwidth=/c\vid_defwidth=854' /storage/.config/gzdoom/gzdoom.ini +fi diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10 Max 3/020-gpios b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10 Max 3/020-gpios new file mode 100755 index 0000000000..357fcb1087 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10 Max 3/020-gpios @@ -0,0 +1,15 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/020-gpios +DEVICE_WIFI="0" +DEVICE_PWM_MOTOR="pwmchip1" +EOF + +. /storage/.config/profile.d/020-gpios +# Enable PWM for rumble and turn rumble off during startup. +echo 0 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/export +echo 1000000 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/period +echo 1 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/enable +echo 1000000 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/duty_cycle diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10 Max 3/040-display b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10 Max 3/040-display new file mode 100755 index 0000000000..efb4451642 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10 Max 3/040-display @@ -0,0 +1,17 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +# Configure default contrast saturation and hue values +for PROPERTY in brightness contrast saturation hue +do + MYVAL=$(get_setting display.${PROPERTY}) + if [ -z "${MYVAL}" ] + then + MYVAL=$(drm_tool list | sed -n '/Connector: 133/,$p' | awk '/'${PROPERTY}'/ {print $5}') + fi + paneladj ${PROPERTY} ${MYVAL} +done diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10 Max 3/050-audio_path b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10 Max 3/050-audio_path new file mode 100755 index 0000000000..f5860cdb57 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10 Max 3/050-audio_path @@ -0,0 +1,9 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/002-audio_path +DEVICE_PLAYBACK_PATH_SPK="HP" +DEVICE_PLAYBACK_PATH_HP="SPK" +DEVICE_PLAYBACK_PATH="Playback Path" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10/001-device_config b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10/001-device_config new file mode 120000 index 0000000000..5ce9862c95 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10/001-device_config @@ -0,0 +1 @@ +../ODROID-GO Advance Black Edition/001-device_config \ No newline at end of file diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10/009-commander-cfg b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10/009-commander-cfg new file mode 100644 index 0000000000..a9c4b8bd72 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10/009-commander-cfg @@ -0,0 +1,11 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025 ArchR (https://github.com/archr-linux/Arch-R) + +if [ ! -f "/storage/.config/commander.cfg" ]; then +cat </storage/.config/commander.cfg +disp_ppu_x=1.5 +disp_ppu_y=1.5 +EOF +fi diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10/050-game_configs b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10/050-game_configs new file mode 120000 index 0000000000..0a41c8be26 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10/050-game_configs @@ -0,0 +1 @@ +../ODROID-GO Advance Black Edition/050-game_configs \ No newline at end of file diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10/050-modifiers b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10/050-modifiers new file mode 100755 index 0000000000..36df82c365 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10/050-modifiers @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/050-modifiers +DEVICE_FUNC_KEYA_MODIFIER="BTN_THUMBL" +DEVICE_FUNC_KEYB_MODIFIER="BTN_THUMBR" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10/075-dpad-volbright b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10/075-dpad-volbright new file mode 100755 index 0000000000..c542993977 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10/075-dpad-volbright @@ -0,0 +1,23 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +DPAD_EVENTS=$(get_setting key.dpad.events) +if [ -z "${DPAD_EVENTS}" ] +then + set_setting key.dpad.events 1 +fi + +KEY_FUNC_A=$(get_setting key.function.a) +if [ -z "${KEY_FUNC_A}" ] +then + set_setting key.function.a BTN_SELECT +fi + +if [ "$(systemctl is-active input)" = "active" ] +then + systemctl restart input +fi diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10/110-retroarch-joypad b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10/110-retroarch-joypad new file mode 100755 index 0000000000..00af09392b --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10/110-retroarch-joypad @@ -0,0 +1,11 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +# Adapt retroarch joypad config for rgb10 + +if [ ! -f "/storage/joypads/odroidgo2_v11_joypad.cfg" ]; then + cp /usr/share/libretro/autoconfig/odroidgo2_v11_joypad.cfg /storage/joypads/ + sed -i -r 's/input_enable_hotkey_btn.*/input_enable_hotkey_btn = "10"/' /storage/joypads/odroidgo2_v11_joypad.cfg +fi + diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10X/001-device_config b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10X/001-device_config new file mode 100755 index 0000000000..bbc01b57c4 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10X/001-device_config @@ -0,0 +1,11 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/001-device_config +# Device Features +DEVICE_PLAYBACK_PATH_SPK="HP" +DEVICE_PLAYBACK_PATH_HP="SPK" +DEVICE_BATTERY_LED_STATUS="true" +DEVICE_TEMP_SENSOR="/sys/devices/virtual/thermal/thermal_zone0/temp" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10X/010-led_control b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10X/010-led_control new file mode 100755 index 0000000000..8ab918b534 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10X/010-led_control @@ -0,0 +1,9 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/010-led_control +DEVICE_LED_CONTROL="false" +DEVICE_LED_BRIGHTNESS="false" +DEVICE_LED_CHARGING="false" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10X/050-game_configs b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10X/050-game_configs new file mode 100755 index 0000000000..9bd6fef780 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10X/050-game_configs @@ -0,0 +1,58 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +#Set mupen64-plus-sa config for OGA +if [ ! -d "/storage/.config/mupen64plus" ]; then + mkdir -p "/storage/.config/mupen64plus/" + cp -r /usr/local/share/mupen64plus/mupen64plus.cfg* /storage/.config/mupen64plus/ +fi +if [ -f "/storage/.config/mupen64plus/mupen64plus.cfg.s1_f2" ]; then + rm /storage/.config/mupen64plus/mupen64plus.cfg + cp /storage/.config/mupen64plus/mupen64plus.cfg.s1_f2 /storage/.config/mupen64plus/mupen64plus.cfg +fi + +#Set drastic-sa config for OGA +if [ ! -d "/storage/.config/drastic" ]; then + mkdir -p "/storage/.config/drastic" + cp -r "/usr/config/drastic" "/storage/.config/" +fi +if [ -f "/storage/.config/drastic/config/drastic.cfg.s1_f2" ]; then + cp /storage/.config/drastic/config/drastic.cfg.s1_f2 /storage/.config/drastic/config/drastic.cfg +fi + +#Set ppsspp config for OGA +if [ ! -d "/storage/.config/ppsspp" ]; then + mkdir -p "/storage/.config/ppsspp" + cp -r "/usr/config/ppsspp" "/storage/.config/" +fi + +#Map ppsspp controls +if grep OGABE -q "/storage/.config/ppsspp/PSP/SYSTEM/controls.ini"; then + exit 1 +else + cat </storage/.config/ppsspp/PSP/SYSTEM/controls.ini +#OGABE +[ControlMapping] +Up = 10-19 +Down = 10-20 +Left = 10-21 +Right = 10-22 +Circle = 10-189 +Cross = 10-190 +Square = 10-188 +Triangle = 10-191 +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 +Fast-forward = 1-61 +Pause = 10-106 +Save State = 10-4010 +Load State = 10-4008 +EOF +fi diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10X/050-modifiers b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10X/050-modifiers new file mode 100755 index 0000000000..a710ab7129 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10X/050-modifiers @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/050-modifiers +DEVICE_FUNC_KEYA_MODIFIER="BTN_MODE" +DEVICE_FUNC_KEYB_MODIFIER="BTN_THUMBR" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10X/bin/battery_led_status b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10X/bin/battery_led_status new file mode 100755 index 0000000000..280c23a000 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB10X/bin/battery_led_status @@ -0,0 +1,45 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +# Simple script to watch the battery capacity and +# turn the power LED to different states: +# 0-10% flashing green and red +# 11-20% red +# 21+% green +# charging red +# 95+% charging green + +function set_led() { + case $1 in + green) echo 0 > /sys/class/leds/red\:charging/brightness;; + red) echo 1 > /sys/class/leds/red\:charging/brightness;; + 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 green + sleep .5 + set_led red + sleep .5 + done + continue + elif (( ${CAP} <= 20 )); then + set_led red + else + set_led green + fi + elif (( ${CAP} <= 95 )); then + set_led red + else + set_led green + fi + sleep 15 +done diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB20 Pro/001-device_config b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB20 Pro/001-device_config new file mode 100755 index 0000000000..f712421662 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB20 Pro/001-device_config @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/001-device_config +# Device Features +DEVICE_BATTERY_LED_STATUS="true" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB20 Pro/010-led_control b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB20 Pro/010-led_control new file mode 100755 index 0000000000..8ab918b534 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB20 Pro/010-led_control @@ -0,0 +1,9 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/010-led_control +DEVICE_LED_CONTROL="false" +DEVICE_LED_BRIGHTNESS="false" +DEVICE_LED_CHARGING="false" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB20 Pro/bin/battery_led_status b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB20 Pro/bin/battery_led_status new file mode 100755 index 0000000000..c78d287e95 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB20 Pro/bin/battery_led_status @@ -0,0 +1,57 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +# Simple script to watch the battery capacity and +# turn the power LED to different states: +# 0-10% flashing red +# 11-20% red +# 21+% green +# <95% charging green+red +# 95+% charging green + +function set_led() { + case $1 in + green) + echo 25 > /sys/class/leds/green:status/brightness + ;; + red) + echo 255 > /sys/class/leds/red:charging/brightness + ;; + off) + echo 0 > /sys/class/leds/green:status/brightness + echo 0 > /sys/class/leds/red:charging/brightness + ;; + 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 off + sleep .5 + set_led red + sleep .5 + done + continue + elif (( ${CAP} <= 20 )); then + set_led off + set_led red + else + set_led off + set_led green + fi + elif (( ${CAP} <= 95 )); then + set_led red + set_led green + else + set_led off + set_led green + fi + sleep 15 +done diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB20S/001-device_config b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB20S/001-device_config new file mode 100755 index 0000000000..243906cf13 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB20S/001-device_config @@ -0,0 +1,11 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/001-device_config +# Device Features +DEVICE_PLAYBACK_PATH_SPK="HP" +DEVICE_PLAYBACK_PATH_HP="SPK" +DEVICE_PWR_LED_GPIO="77" +DEVICE_TEMP_SENSOR="/sys/devices/virtual/thermal/thermal_zone0/temp" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB20S/002-disable-led b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB20S/002-disable-led new file mode 100755 index 0000000000..7e5ed7a899 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB20S/002-disable-led @@ -0,0 +1,13 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Set export GPIO for Power LED +if [ ! -d "/sys/class/gpio/gpio${DEVICE_PWR_LED_GPIO}" ]; then + echo ${DEVICE_PWR_LED_GPIO} > /sys/class/gpio/export +fi + +#Disable blue led on R33S +echo out >/sys/class/gpio/gpio${DEVICE_PWR_LED_GPIO}/direction +echo 1 >/sys/class/gpio/gpio${DEVICE_PWR_LED_GPIO}/value diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB20S/050-game-configs b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB20S/050-game-configs new file mode 100755 index 0000000000..e839f4e896 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB20S/050-game-configs @@ -0,0 +1,57 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022-present JELOS (https://github.com/JustEnoughLinuxOS) + +#Set mupen64-plus-sa config for RGB20S, can use same profile as OGS +if [ ! -d "/storage/.config/mupen64plus" ]; then + mkdir -p "/storage/.config/mupen64plus/" + cp -r /usr/local/share/mupen64plus/mupen64plus.cfg* /storage/.config/mupen64plus/ +fi +if [ -f "/storage/.config/mupen64plus/mupen64plus.cfg.ogs" ]; then + rm /storage/.config/mupen64plus/mupen64plus.cfg + mv /storage/.config/mupen64plus/mupen64plus.cfg.ogs /storage/.config/mupen64plus/mupen64plus.cfg +fi + +#Set drastic-sa config for RGB20S +if [ ! -d "/storage/.config/drastic" ]; then + mkdir -p "/storage/.config/drastic" + cp -r "/usr/config/drastic" "/storage/.config/" +fi +if [ -f "/storage/.config/drastic/config/drastic.cfg.rgb20s" ]; then + rm /storage/.config/drastic/config/drastic.cfg + mv /storage/.config/drastic/config/drastic.cfg.rgb20s /storage/.config/drastic/config/drastic.cfg +fi + +#Map ppsspp controls +if grep RGB20S -q "/storage/.config/ppsspp/PSP/SYSTEM/controls.ini" +then + exit 1 +else +cat </storage/.config/ppsspp/PSP/SYSTEM/controls.ini +#RGB20S +[ControlMapping] +Up = 10-19 +Down = 10-20 +Left = 10-21 +Right = 10-22 +Circle = 10-189 +Cross = 10-190 +Square = 10-188 +Triangle = 10-191 +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-106 +Save State = 10-4010 +Load State = 10-4008 +RightAn.Up = 10-4007 +RightAn.Down = 10-4006 +RightAn.Left = 10-4005 +RightAn.Right = 10-4004 +EOF +fi diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB20SX/010-led_control b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB20SX/010-led_control new file mode 100644 index 0000000000..e54be4fc32 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB20SX/010-led_control @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/010-led_control +echo 0 > /sys/class/leds/red\:charging/brightness +echo 1 > /sys/class/leds/green\:status/brightness +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB20SX/020-gpios b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB20SX/020-gpios new file mode 100755 index 0000000000..357fcb1087 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB20SX/020-gpios @@ -0,0 +1,15 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/020-gpios +DEVICE_WIFI="0" +DEVICE_PWM_MOTOR="pwmchip1" +EOF + +. /storage/.config/profile.d/020-gpios +# Enable PWM for rumble and turn rumble off during startup. +echo 0 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/export +echo 1000000 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/period +echo 1 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/enable +echo 1000000 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/duty_cycle diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB20SX/040-display b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB20SX/040-display new file mode 100755 index 0000000000..c0d7d0d670 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB20SX/040-display @@ -0,0 +1,14 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Configure default contrast saturation and hue values +for PROPERTY in brightness contrast saturation hue +do + MYVAL=$(get_setting display.${PROPERTY}) + if [ -z "${MYVAL}" ] + then + MYVAL=$(drm_tool list | sed -n '/Connector: 133/,$p' | awk '/'${PROPERTY}'/ {print $5}') + fi + paneladj ${PROPERTY} ${MYVAL} +done diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB20SX/060-game_settings b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB20SX/060-game_settings new file mode 100755 index 0000000000..d058f2fb42 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB20SX/060-game_settings @@ -0,0 +1,12 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile.d/001-functions + +SETTING=$(get_setting pico-8.integerscale) +if [ -z ${SETTING} ] +then + set_setting pico-8.integerscale 1 +fi + diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB30/001-detect-device b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB30/001-detect-device new file mode 100755 index 0000000000..6481d02817 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB30/001-detect-device @@ -0,0 +1,9 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +if grep -q "024C:D723" "/sys/devices/platform/fe000000.mmc/mmc_host/mmc3/mmc3:0001/mmc3:0001:1/uevent"; then + mount -o rw,remount /flash + sed -i "/FDT/c\ FDT /device_trees/rk3566-powkiddy-rgb20sx.dtb" /flash/extlinux/extlinux.conf + reboot +fi diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB30/010-led_control b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB30/010-led_control new file mode 100644 index 0000000000..e54be4fc32 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB30/010-led_control @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/010-led_control +echo 0 > /sys/class/leds/red\:charging/brightness +echo 1 > /sys/class/leds/green\:status/brightness +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB30/020-gpios b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB30/020-gpios new file mode 100755 index 0000000000..357fcb1087 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB30/020-gpios @@ -0,0 +1,15 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/020-gpios +DEVICE_WIFI="0" +DEVICE_PWM_MOTOR="pwmchip1" +EOF + +. /storage/.config/profile.d/020-gpios +# Enable PWM for rumble and turn rumble off during startup. +echo 0 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/export +echo 1000000 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/period +echo 1 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/enable +echo 1000000 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/duty_cycle diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB30/040-display b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB30/040-display new file mode 100755 index 0000000000..efb4451642 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB30/040-display @@ -0,0 +1,17 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +# Configure default contrast saturation and hue values +for PROPERTY in brightness contrast saturation hue +do + MYVAL=$(get_setting display.${PROPERTY}) + if [ -z "${MYVAL}" ] + then + MYVAL=$(drm_tool list | sed -n '/Connector: 133/,$p' | awk '/'${PROPERTY}'/ {print $5}') + fi + paneladj ${PROPERTY} ${MYVAL} +done diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB30/060-game_settings b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB30/060-game_settings new file mode 100755 index 0000000000..d058f2fb42 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RGB30/060-game_settings @@ -0,0 +1,12 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile.d/001-functions + +SETTING=$(get_setting pico-8.integerscale) +if [ -z ${SETTING} ] +then + set_setting pico-8.integerscale 1 +fi + diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RK2023/001-detect-device b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RK2023/001-detect-device new file mode 100755 index 0000000000..2ca2c9c811 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RK2023/001-detect-device @@ -0,0 +1,15 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +# this quirk is for the powkiddy rgb20 pro which pk have +# shipped using the rk2023 device tree + +if grep -q "024C:D723" "/sys/devices/platform/fe000000.mmc/mmc_host/mmc3/mmc3:0001/mmc3:0001:1/uevent"; then + if ! grep -q "FDTDIR" /flash/extlinux/extlinux.conf; then + mount -o rw,remount /flash + sed -i '/FDT \/rk3566-powkiddy-rk2023.dtb/c\ FDTDIR /' /flash/extlinux/extlinux.conf + sync + reboot + fi +fi diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RK2023/020-gpios b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RK2023/020-gpios new file mode 100755 index 0000000000..357fcb1087 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RK2023/020-gpios @@ -0,0 +1,15 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/020-gpios +DEVICE_WIFI="0" +DEVICE_PWM_MOTOR="pwmchip1" +EOF + +. /storage/.config/profile.d/020-gpios +# Enable PWM for rumble and turn rumble off during startup. +echo 0 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/export +echo 1000000 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/period +echo 1 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/enable +echo 1000000 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/duty_cycle diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RK2023/040-display b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RK2023/040-display new file mode 100755 index 0000000000..efb4451642 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy RK2023/040-display @@ -0,0 +1,17 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +# Configure default contrast saturation and hue values +for PROPERTY in brightness contrast saturation hue +do + MYVAL=$(get_setting display.${PROPERTY}) + if [ -z "${MYVAL}" ] + then + MYVAL=$(drm_tool list | sed -n '/Connector: 133/,$p' | awk '/'${PROPERTY}'/ {print $5}') + fi + paneladj ${PROPERTY} ${MYVAL} +done diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy x35s b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy x35s new file mode 120000 index 0000000000..11e0fe3199 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy x35s @@ -0,0 +1 @@ +Powkiddy x55 \ No newline at end of file diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy x55/001-device_config b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy x55/001-device_config new file mode 100755 index 0000000000..66857e6df5 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy x55/001-device_config @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/001-device_config +DEVICE_FAKE_JACKSENSE="true" +DEVICE_BATTERY_LED_STATUS="true" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy x55/010-governors b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy x55/010-governors new file mode 100755 index 0000000000..e1a4622419 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy x55/010-governors @@ -0,0 +1,9 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/010-governors +CPU_FREQ=("/sys/devices/system/cpu/cpufreq/policy0") +GPU_FREQ="/sys/devices/platform/fde60000.gpu/devfreq/fde60000.gpu" +DMC_FREQ="/sys/devices/platform/dmc/devfreq/dmc" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy x55/020-gpios b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy x55/020-gpios new file mode 100755 index 0000000000..357fcb1087 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy x55/020-gpios @@ -0,0 +1,15 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/020-gpios +DEVICE_WIFI="0" +DEVICE_PWM_MOTOR="pwmchip1" +EOF + +. /storage/.config/profile.d/020-gpios +# Enable PWM for rumble and turn rumble off during startup. +echo 0 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/export +echo 1000000 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/period +echo 1 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/enable +echo 1000000 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/duty_cycle diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy x55/040-display b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy x55/040-display new file mode 100755 index 0000000000..75d6f4d1f0 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy x55/040-display @@ -0,0 +1,17 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +# Configure default contrast saturation and hue values +for PROPERTY in brightness contrast saturation hue +do + MYVAL=$(get_setting display.${PROPERTY}) + if [ -z "${MYVAL}" ] + then + MYVAL=$(drm_tool list | sed -n '/Connector: 206/,$p' | awk '/'${PROPERTY}'/ {print $5}') + fi + paneladj ${PROPERTY} ${MYVAL} +done diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy x55/040-hdmi b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy x55/040-hdmi new file mode 100755 index 0000000000..035c9899dd --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy x55/040-hdmi @@ -0,0 +1,20 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +hdmi_con() { + if [ -f "/sys/class/extcon/hdmi/state" ] + then + HDMI="$(cat /sys/class/extcon/hdmi/state)" + if [ "${HDMI}" = "HDMI=1" ] + then + if [ -f "/sys/devices/virtual/graphics/fbcon/rotate" ] + then + echo 0 >/sys/devices/virtual/graphics/fbcon/rotate + fi + fi + fi +} + +### If hdmi is connected, set the framebuffer rotation back to normal. +hdmi_con diff --git a/projects/ArchR/packages/hardware/quirks/devices/Powkiddy x55/sleep.d/README b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy x55/sleep.d/README new file mode 100755 index 0000000000..d4ea16ddf9 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Powkiddy x55/sleep.d/README @@ -0,0 +1 @@ +Sleep quirks are executed before (pre) and after (post) a sleep event occurs. diff --git a/projects/ArchR/packages/hardware/quirks/devices/RetrOLED CM5/001-device_config b/projects/ArchR/packages/hardware/quirks/devices/RetrOLED CM5/001-device_config new file mode 100755 index 0000000000..ea1481fd7c --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/RetrOLED CM5/001-device_config @@ -0,0 +1,17 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/001-device_config +# Device Features +#DEVICE_FAKE_JACKSENSE="true" +#DEVICE_AUDIO_MIXER="DAC" +#DEVICE_PLAYBACK_PATH_SPK="1*" +#DEVICE_PLAYBACK_PATH_HP="0*" +#DEVICE_HEADPHONE_DEV="/dev/input/by-path/platform-wm8960-sound-event" +DEVICE_HAS_TOUCHSCREEN="true" +#DEVICE_BATTERY_LED_STATUS="true" +#DEVICE_PWR_LED_CONTROL="true" + +DEVICE_TEMP_SENSOR=("/sys/devices/virtual/thermal/thermal_zone0/temp" "/sys/devices/virtual/thermal/thermal_zone1/temp") +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/RetrOLED CM5/020-fan_control b/projects/ArchR/packages/hardware/quirks/devices/RetrOLED CM5/020-fan_control new file mode 100644 index 0000000000..1bf812a2ce --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/RetrOLED CM5/020-fan_control @@ -0,0 +1,7 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +# Enable kernel PWM fan control +echo step_wise > /sys/class/thermal/thermal_zone0/policy + diff --git a/projects/ArchR/packages/hardware/quirks/devices/RetrOLED CM5/020-suspend_mode b/projects/ArchR/packages/hardware/quirks/devices/RetrOLED CM5/020-suspend_mode new file mode 100755 index 0000000000..7bda7aae31 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/RetrOLED CM5/020-suspend_mode @@ -0,0 +1,19 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile.d/001-functions + +MYSLEEPMODE=$(get_setting system.suspendmode) +if [ -z "${MYSLEEPMODE}" ] +then + /usr/bin/suspendmode mem +fi + +# Handle lid key as a signal to shutdown +cat <~/.config/logind.conf.d/login.conf +[Login] +HandlePowerKey=suspend +HandleLidSwitch=poweroff +EOF + diff --git a/projects/ArchR/packages/hardware/quirks/devices/RetrOLED CM5/030-modifiers b/projects/ArchR/packages/hardware/quirks/devices/RetrOLED CM5/030-modifiers new file mode 100644 index 0000000000..4b439b7e6a --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/RetrOLED CM5/030-modifiers @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/050-modifiers +DEVICE_FUNC_KEYA_MODIFIER="BTN_MODE" +DEVICE_FUNC_KEYB_MODIFIER="BTN_START" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/RetrOLED CM5/050-audio_path b/projects/ArchR/packages/hardware/quirks/devices/RetrOLED CM5/050-audio_path new file mode 100755 index 0000000000..aeb8f0df94 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/RetrOLED CM5/050-audio_path @@ -0,0 +1,21 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +SPEAKER=$(pactl list sinks short | grep wm8960 | cut -c 0-2) +pactl set-default-sink ${SPEAKER} + +cat </storage/.config/profile.d/002-audio_path +DEVICE_PLAYBACK_PATH="Playback Mux" +DEFAULT_SINK=${SPEAKER} +EOF + +### Set sound properties +amixer -c 0 -q cset name='Playback Volume' 243,243 +amixer -c 0 -q cset name='Speaker Playback Volume' 127,127 +amixer -c 0 -q cset name='Speaker DC Volume' 5 +amixer -c 0 -q cset name='Speaker AC Volume' 5 +amixer -c 0 -q cset name='Left Output Mixer PCM Playback Switch' on +amixer -c 0 -q cset name='Right Output Mixer PCM Playback Switch' on +amixer -c 0 -q cset name='DAC Polarity' 'Left Inverted' + diff --git a/projects/ArchR/packages/hardware/quirks/devices/RetrOLED CM5/sleep.d/post/001-audio b/projects/ArchR/packages/hardware/quirks/devices/RetrOLED CM5/sleep.d/post/001-audio new file mode 100755 index 0000000000..15101c8584 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/RetrOLED CM5/sleep.d/post/001-audio @@ -0,0 +1,30 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +# Workaround for no audio on wake from sleep. + +. /etc/profile + +HDMI=$(pactl list sinks short | grep hdmi | cut -c 0-2) +SPEAKER=$(pactl list sinks short | grep wm8960 | cut -c 0-2) + +#Set sink to one we aren't currently using +pactl set-default-sink ${SPEAKER} + +#Then check if HDMI is plugged and switch to HDMI + +# Set export GPIO for HDMI +if [ ! -d "/sys/class/gpio/gpio${DEVICE_HDMI_GPIO}" ]; then + echo ${DEVICE_HDMI_GPIO} > /sys/class/gpio/export + echo in > /sys/class/gpio/gpio${DEVICE_HDMI_GPIO}/direction +fi + +# Check HDMI plug state and switch to HDMI audo if true +HDMI_VALUE=$(cat /sys/class/gpio/gpio${DEVICE_HDMI_GPIO}/value) + case ${HDMI_VALUE} in + "0") + sleep 11 + pactl set-default-sink ${HDMI} + ;; + esac diff --git a/projects/ArchR/packages/hardware/quirks/devices/RetrOLED CM5/sleep.d/post/002-freq b/projects/ArchR/packages/hardware/quirks/devices/RetrOLED CM5/sleep.d/post/002-freq new file mode 100755 index 0000000000..3d94601970 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/RetrOLED CM5/sleep.d/post/002-freq @@ -0,0 +1,22 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +### Restore previous governors before going to sleep + +. /etc/profile + +### Grab the old governors. +OLD_CPU_FREQ=$(get_setting "sleep.cpugovernor") +if [ ! -n "${OLD_CPU_FREQ}" ]; then + OLD_CPU_FREQ="schedutil" +fi + +OLD_GPU_FREQ=$(get_setting "sleep.gpugovernor") +if [ ! -n "${OLD_GPU_FREQ}" ]; then + OLD_GPU_FREQ="simple_ondemand" +fi + +# Restore old governors. +set_cpu_gov "${OLD_CPU_FREQ}" +set_gpu_gov "${OLD_GPU_FREQ}" diff --git a/projects/ArchR/packages/hardware/quirks/devices/RetrOLED CM5/sleep.d/pre/002-freq b/projects/ArchR/packages/hardware/quirks/devices/RetrOLED CM5/sleep.d/pre/002-freq new file mode 100755 index 0000000000..6d0fc291dc --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/RetrOLED CM5/sleep.d/pre/002-freq @@ -0,0 +1,18 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +# Store current freq governors and set governors to powersave. + +. /etc/profile + +### Get the current cpu and gpu governor, save for when the device wakes from sleep. +CUR_CPU_FREQ="$(cat ${CPU_FREQ}/scaling_governor)" +CUR_GPU_FREQ="$(cat ${GPU_FREQ}/governor)" + +set_setting sleep.cpugovernor "${CUR_CPU_FREQ}" +set_setting sleep.gpugovernor "${CUR_GPU_FREQ}" + +### Set all governors to powersave +set_cpu_gov powersave +set_gpu_gov powersave diff --git a/projects/ArchR/packages/hardware/quirks/devices/Retro Lite CM5/001-device_config b/projects/ArchR/packages/hardware/quirks/devices/Retro Lite CM5/001-device_config new file mode 100755 index 0000000000..ea1481fd7c --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Retro Lite CM5/001-device_config @@ -0,0 +1,17 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/001-device_config +# Device Features +#DEVICE_FAKE_JACKSENSE="true" +#DEVICE_AUDIO_MIXER="DAC" +#DEVICE_PLAYBACK_PATH_SPK="1*" +#DEVICE_PLAYBACK_PATH_HP="0*" +#DEVICE_HEADPHONE_DEV="/dev/input/by-path/platform-wm8960-sound-event" +DEVICE_HAS_TOUCHSCREEN="true" +#DEVICE_BATTERY_LED_STATUS="true" +#DEVICE_PWR_LED_CONTROL="true" + +DEVICE_TEMP_SENSOR=("/sys/devices/virtual/thermal/thermal_zone0/temp" "/sys/devices/virtual/thermal/thermal_zone1/temp") +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Retro Lite CM5/020-fan_control b/projects/ArchR/packages/hardware/quirks/devices/Retro Lite CM5/020-fan_control new file mode 100644 index 0000000000..1bf812a2ce --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Retro Lite CM5/020-fan_control @@ -0,0 +1,7 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +# Enable kernel PWM fan control +echo step_wise > /sys/class/thermal/thermal_zone0/policy + diff --git a/projects/ArchR/packages/hardware/quirks/devices/Retro Lite CM5/020-suspend_mode b/projects/ArchR/packages/hardware/quirks/devices/Retro Lite CM5/020-suspend_mode new file mode 100755 index 0000000000..7bda7aae31 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Retro Lite CM5/020-suspend_mode @@ -0,0 +1,19 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile.d/001-functions + +MYSLEEPMODE=$(get_setting system.suspendmode) +if [ -z "${MYSLEEPMODE}" ] +then + /usr/bin/suspendmode mem +fi + +# Handle lid key as a signal to shutdown +cat <~/.config/logind.conf.d/login.conf +[Login] +HandlePowerKey=suspend +HandleLidSwitch=poweroff +EOF + diff --git a/projects/ArchR/packages/hardware/quirks/devices/Retro Lite CM5/030-modifiers b/projects/ArchR/packages/hardware/quirks/devices/Retro Lite CM5/030-modifiers new file mode 100644 index 0000000000..adf2be4df1 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Retro Lite CM5/030-modifiers @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/050-modifiers +DEVICE_FUNC_KEYA_MODIFIER="BTN_MODE" +DEVICE_FUNC_KEYB_MODIFIER="BTN_START" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Retro Lite CM5/050-audio_path b/projects/ArchR/packages/hardware/quirks/devices/Retro Lite CM5/050-audio_path new file mode 100755 index 0000000000..aeb8f0df94 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Retro Lite CM5/050-audio_path @@ -0,0 +1,21 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +SPEAKER=$(pactl list sinks short | grep wm8960 | cut -c 0-2) +pactl set-default-sink ${SPEAKER} + +cat </storage/.config/profile.d/002-audio_path +DEVICE_PLAYBACK_PATH="Playback Mux" +DEFAULT_SINK=${SPEAKER} +EOF + +### Set sound properties +amixer -c 0 -q cset name='Playback Volume' 243,243 +amixer -c 0 -q cset name='Speaker Playback Volume' 127,127 +amixer -c 0 -q cset name='Speaker DC Volume' 5 +amixer -c 0 -q cset name='Speaker AC Volume' 5 +amixer -c 0 -q cset name='Left Output Mixer PCM Playback Switch' on +amixer -c 0 -q cset name='Right Output Mixer PCM Playback Switch' on +amixer -c 0 -q cset name='DAC Polarity' 'Left Inverted' + diff --git a/projects/ArchR/packages/hardware/quirks/devices/Retro Lite CM5/sleep.d/post/001-audio b/projects/ArchR/packages/hardware/quirks/devices/Retro Lite CM5/sleep.d/post/001-audio new file mode 100755 index 0000000000..15101c8584 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Retro Lite CM5/sleep.d/post/001-audio @@ -0,0 +1,30 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +# Workaround for no audio on wake from sleep. + +. /etc/profile + +HDMI=$(pactl list sinks short | grep hdmi | cut -c 0-2) +SPEAKER=$(pactl list sinks short | grep wm8960 | cut -c 0-2) + +#Set sink to one we aren't currently using +pactl set-default-sink ${SPEAKER} + +#Then check if HDMI is plugged and switch to HDMI + +# Set export GPIO for HDMI +if [ ! -d "/sys/class/gpio/gpio${DEVICE_HDMI_GPIO}" ]; then + echo ${DEVICE_HDMI_GPIO} > /sys/class/gpio/export + echo in > /sys/class/gpio/gpio${DEVICE_HDMI_GPIO}/direction +fi + +# Check HDMI plug state and switch to HDMI audo if true +HDMI_VALUE=$(cat /sys/class/gpio/gpio${DEVICE_HDMI_GPIO}/value) + case ${HDMI_VALUE} in + "0") + sleep 11 + pactl set-default-sink ${HDMI} + ;; + esac diff --git a/projects/ArchR/packages/hardware/quirks/devices/Retro Lite CM5/sleep.d/post/002-freq b/projects/ArchR/packages/hardware/quirks/devices/Retro Lite CM5/sleep.d/post/002-freq new file mode 100755 index 0000000000..3d94601970 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Retro Lite CM5/sleep.d/post/002-freq @@ -0,0 +1,22 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +### Restore previous governors before going to sleep + +. /etc/profile + +### Grab the old governors. +OLD_CPU_FREQ=$(get_setting "sleep.cpugovernor") +if [ ! -n "${OLD_CPU_FREQ}" ]; then + OLD_CPU_FREQ="schedutil" +fi + +OLD_GPU_FREQ=$(get_setting "sleep.gpugovernor") +if [ ! -n "${OLD_GPU_FREQ}" ]; then + OLD_GPU_FREQ="simple_ondemand" +fi + +# Restore old governors. +set_cpu_gov "${OLD_CPU_FREQ}" +set_gpu_gov "${OLD_GPU_FREQ}" diff --git a/projects/ArchR/packages/hardware/quirks/devices/Retro Lite CM5/sleep.d/pre/002-freq b/projects/ArchR/packages/hardware/quirks/devices/Retro Lite CM5/sleep.d/pre/002-freq new file mode 100755 index 0000000000..6d0fc291dc --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Retro Lite CM5/sleep.d/pre/002-freq @@ -0,0 +1,18 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +# Store current freq governors and set governors to powersave. + +. /etc/profile + +### Get the current cpu and gpu governor, save for when the device wakes from sleep. +CUR_CPU_FREQ="$(cat ${CPU_FREQ}/scaling_governor)" +CUR_GPU_FREQ="$(cat ${GPU_FREQ}/governor)" + +set_setting sleep.cpugovernor "${CUR_CPU_FREQ}" +set_setting sleep.gpugovernor "${CUR_GPU_FREQ}" + +### Set all governors to powersave +set_cpu_gov powersave +set_gpu_gov powersave diff --git a/projects/ArchR/packages/hardware/quirks/devices/Retroid Pocket 5/001-device_config b/projects/ArchR/packages/hardware/quirks/devices/Retroid Pocket 5/001-device_config new file mode 100644 index 0000000000..7ffbe1730f --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Retroid Pocket 5/001-device_config @@ -0,0 +1,10 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/001-device_config +# Device Features +DEVICE_HAS_TOUCHSCREEN="true" +DEVICE_GPU_OVERCLOCK="true" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Retroid Pocket 5/050-game-configs b/projects/ArchR/packages/hardware/quirks/devices/Retroid Pocket 5/050-game-configs new file mode 100644 index 0000000000..cdec8122e9 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Retroid Pocket 5/050-game-configs @@ -0,0 +1,11 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +#Set Supermodel resolution for the mini +sed -i '/^XResolution =/c\XResolution = 1920' /storage/.config/supermodel/Config/Supermodel.ini +sed -i '/^YResolution =/c\YResolution = 1080' /storage/.config/supermodel/Config/Supermodel.ini + +#Disable retroarch microphone and set default audio driver to pulse +sed -i '/^microphone_enable =/c\microphone_enable = "false"' /storage/.config/retroarch/retroarch.cfg +sed -i '/^audio_driver =/c\audio_driver = "pulse"' /storage/.config/retroarch/retroarch.cfg diff --git a/projects/ArchR/packages/hardware/quirks/devices/Retroid Pocket 6 TOP-DPAD b/projects/ArchR/packages/hardware/quirks/devices/Retroid Pocket 6 TOP-DPAD new file mode 120000 index 0000000000..d756c7a30a --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Retroid Pocket 6 TOP-DPAD @@ -0,0 +1 @@ +Retroid Pocket 6 \ No newline at end of file diff --git a/projects/ArchR/packages/hardware/quirks/devices/Retroid Pocket 6/009-commander-cfg b/projects/ArchR/packages/hardware/quirks/devices/Retroid Pocket 6/009-commander-cfg new file mode 100644 index 0000000000..044bb46732 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Retroid Pocket 6/009-commander-cfg @@ -0,0 +1,11 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025 ArchR (https://github.com/archr-linux/Arch-R) + +if [ ! -f "/storage/.config/commander.cfg" ]; then +cat </storage/.config/commander.cfg +disp_ppu_x=4 +disp_ppu_y=4 +EOF +fi diff --git a/projects/ArchR/packages/hardware/quirks/devices/Retroid Pocket 6/bin/analog_sticks_ledcontrol b/projects/ArchR/packages/hardware/quirks/devices/Retroid Pocket 6/bin/analog_sticks_ledcontrol new file mode 100644 index 0000000000..d848333528 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Retroid Pocket 6/bin/analog_sticks_ledcontrol @@ -0,0 +1,45 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2025 ArchR (https://github.com/archr-linux/Arch-R) + +# Simple script to set led brightness and rgb color based on +# brightness and rgb values from emulation station + +LED_PATH="/sys/devices/platform/" + +function led_brightness() { + n=1 + while [ "$n" -lt 4 ]; do + echo ${2} > ${LED_PATH}/multi-led${1}${n}/leds/rgb:${1}${n}/brightness + n=$(( n + 1 )) + done +} + +function led_rgb() { + n=1 + while [ "$n" -lt 4 ]; do + echo ${2} ${3} ${4} > ${LED_PATH}/multi-led${1}${n}/leds/rgb:${1}${n}/multi_intensity + n=$(( n + 1 )) + done +} + +# Display usage if no parameters are provided +if [ $# -ne 7 ]; then + echo "Usage: $0 " + echo "Example: $0 255 255 0 0 0 0 255" + exit 1 +fi + +BRIGHTNESS=$1 +RIGHT_RED=$2 +RIGHT_GREEN=$3 +RIGHT_BLUE=$4 +LEFT_RED=$5 +LEFT_GREEN=$6 +LEFT_BLUE=$7 + +led_brightness l $BRIGHTNESS +led_rgb l $LEFT_BLUE $LEFT_GREEN $LEFT_RED +led_brightness r $BRIGHTNESS +led_rgb r $RIGHT_BLUE $RIGHT_GREEN $RIGHT_RED diff --git a/projects/ArchR/packages/hardware/quirks/devices/Retroid Pocket 6/bin/battery_led_status b/projects/ArchR/packages/hardware/quirks/devices/Retroid Pocket 6/bin/battery_led_status new file mode 100644 index 0000000000..09f5a20f73 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Retroid Pocket 6/bin/battery_led_status @@ -0,0 +1,128 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +# Simple script to watch the battery capacity and +# turn the power LED orange when it reaches 30%, red at 20%, and blinking red at 10% + +. /etc/profile + +LED_PATH="/sys/devices/platform/" + +function bat_led_off() { + n=1 + while [ "$n" -lt 4 ]; do + echo 0 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/brightness + echo 0 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/brightness + echo 0 0 0 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/multi_intensity + echo 0 0 0 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/multi_intensity + n=$(( n + 1 )) + done +} + +function bat_led_red() { + n=1 + while [ "$n" -lt 4 ]; do + echo 255 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/brightness + echo 255 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/brightness + echo 0 0 255 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/multi_intensity + echo 0 0 255 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/multi_intensity + n=$(( n + 1 )) + done +} + +function bat_led_green() { + n=1 + while [ "$n" -lt 4 ]; do + echo 255 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/brightness + echo 255 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/brightness + echo 0 255 0 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/multi_intensity + echo 0 255 0 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/multi_intensity + n=$(( n + 1 )) + done +} + +function bat_led_orange() { + n=1 + while [ "$n" -lt 4 ]; do + echo 255 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/brightness + echo 255 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/brightness + echo 0 20 255 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/multi_intensity + echo 0 20 255 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/multi_intensity + n=$(( n + 1 )) + done +} + +function bat_led_yellow() { + n=1 + while [ "$n" -lt 4 ]; do + echo 255 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/brightness + echo 255 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/brightness + echo 0 125 255 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/multi_intensity + echo 0 125 255 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/multi_intensity + n=$(( n + 1 )) + done +} + +PREV_BATCAP="null" +while true + do + BAT_LED_STATE=$(get_setting led.color) + if [ ! ${BAT_LED_STATE} == "battery" ]; then + break + else + 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 + bat_led_red + sleep .5 + bat_led_off + sleep .5 + done + continue + elif (( ${CAP} <= 20 )) + then + BATCAP="D_RED" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_red + fi + elif (( ${CAP} <= 30 )) + then + BATCAP="D_ORANGE" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_orange + fi + elif (( ${CAP} <= 40 )) + then + BATCAP="D_YELLOW" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_yellow + fi + else + BATCAP="D_GREEN" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_green + fi + fi + elif (( ${CAP} <= 94 )) + then + BATCAP="C_ORANGE" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_orange + fi + elif (( ${CAP} >= 95 )) + then + BATCAP="C_GREEN" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_green + fi + fi + PREV_BATCAP=${BATCAP} + sleep 15 + fi +done diff --git a/projects/ArchR/packages/hardware/quirks/devices/Retroid Pocket 6/bin/ledcontrol b/projects/ArchR/packages/hardware/quirks/devices/Retroid Pocket 6/bin/ledcontrol new file mode 100644 index 0000000000..8726843fc9 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Retroid Pocket 6/bin/ledcontrol @@ -0,0 +1,45 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile + +LED_PATH="/sys/devices/platform/" + +function led_off() { + n=1 + while [ "$n" -lt 4 ]; do + echo 0 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/brightness + echo 0 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/brightness + echo 0 0 0 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/multi_intensity + echo 0 0 0 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/multi_intensity + n=$(( n + 1 )) + done +} + +case ${1} in + off) + led_off + set_setting led.color ${1} + ;; + rgb) + LEDS_CONFIG=$(get_setting analogsticks.led) + /usr/bin/analog_sticks_ledcontrol ${LEDS_CONFIG} + set_setting led.color ${1} + ;; + battery) + led_off + set_setting led.color ${1} + systemctl restart batteryledstatus.service + ;; + poweroff) + led_off + ;; + list) +cat </storage/.config/profile.d/001-device_config +# Device Features +DEVICE_HAS_TOUCHSCREEN="true" +DEVICE_ASPECT_RATIO="4:3" +DEVICE_GPU_OVERCLOCK="true" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/devices/Retroid Pocket Mini/050-game-configs b/projects/ArchR/packages/hardware/quirks/devices/Retroid Pocket Mini/050-game-configs new file mode 100644 index 0000000000..182573be62 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/devices/Retroid Pocket Mini/050-game-configs @@ -0,0 +1,11 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +#Set Supermodel resolution for the mini +sed -i '/^XResolution =/c\XResolution = 1280' /storage/.config/supermodel/Config/Supermodel.ini +sed -i '/^YResolution =/c\YResolution = 960' /storage/.config/supermodel/Config/Supermodel.ini + +#Disable retroarch microphone and set default audio driver to pulse +sed -i '/^microphone_enable =/c\microphone_enable = "false"' /storage/.config/retroarch/retroarch.cfg +sed -i '/^audio_driver =/c\audio_driver = "pulse"' /storage/.config/retroarch/retroarch.cfg diff --git a/projects/ArchR/packages/hardware/quirks/package.mk b/projects/ArchR/packages/hardware/quirks/package.mk new file mode 100644 index 0000000000..61919ea673 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/package.mk @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="quirks" +PKG_VERSION="" +PKG_LICENSE="GPLv2" +PKG_SITE="" +PKG_URL="" +PKG_DEPENDS_TARGET="toolchain autostart" +PKG_LONGDESC="Quirks is a simple package that provides device quirks." +PKG_TOOLCHAIN="manual" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/autostart/quirks/{platforms,devices} + cp -r ${PKG_DIR}/devices/* ${INSTALL}/usr/lib/autostart/quirks/devices + if [ -d "${PKG_DIR}/platforms/${DEVICE}" ] + then + cp -r ${PKG_DIR}/platforms/* ${INSTALL}/usr/lib/autostart/quirks/platforms + fi + chmod -R 0755 ${INSTALL}/usr/lib/autostart/quirks +} + +post_install() { + enable_service led-poweroff.service + if [ "${DEVICE}" = "RK3566" ] + then + enable_service volume-fixup.service + fi +} diff --git a/projects/ArchR/packages/hardware/quirks/platforms/H700/001-device_config b/projects/ArchR/packages/hardware/quirks/platforms/H700/001-device_config new file mode 100755 index 0000000000..a578b05dbd --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/H700/001-device_config @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/001-device_config +DEVICE_TEMP_SENSOR="/sys/devices/virtual/thermal/thermal_zone2/temp" +DEVICE_GPU_OVERCLOCK="true" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/H700/002-turbo-mode_config b/projects/ArchR/packages/hardware/quirks/platforms/H700/002-turbo-mode_config new file mode 100755 index 0000000000..f1b68db2fe --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/H700/002-turbo-mode_config @@ -0,0 +1,7 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/002-turbo-mode_config +DEVICE_TURBO_MODE="true" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/H700/010-governors b/projects/ArchR/packages/hardware/quirks/platforms/H700/010-governors new file mode 100755 index 0000000000..45631b7be2 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/H700/010-governors @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/010-governors +CPU_FREQ=("/sys/devices/system/cpu/cpufreq/policy0") +GPU_FREQ=("/sys/devices/platform/soc/1800000.gpu/devfreq/1800000.gpu") +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/H700/010-led_control b/projects/ArchR/packages/hardware/quirks/platforms/H700/010-led_control new file mode 100755 index 0000000000..9196367dd3 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/H700/010-led_control @@ -0,0 +1,9 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/010-led_control +DEVICE_LED_CONTROL="true" +DEVICE_LED_BRIGHTNESS="false" +DEVICE_LED_CHARGING="false" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/H700/020-fan_control b/projects/ArchR/packages/hardware/quirks/platforms/H700/020-fan_control new file mode 100755 index 0000000000..eb4ddf9a9c --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/H700/020-fan_control @@ -0,0 +1,7 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/020-fan_control +DEVICE_HAS_FAN="false" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/H700/020-set_audio_latency b/projects/ArchR/packages/hardware/quirks/platforms/H700/020-set_audio_latency new file mode 100755 index 0000000000..c116a85f79 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/H700/020-set_audio_latency @@ -0,0 +1,11 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile.d/001-functions + +AUDIO_LATENCY=$(get_setting audiolatency) +if [ -z "${AUDIO_LATENCY}" ] +then + set_setting global.audiolatency 64 +fi diff --git a/projects/ArchR/packages/hardware/quirks/platforms/H700/030-analog_leds b/projects/ArchR/packages/hardware/quirks/platforms/H700/030-analog_leds new file mode 100755 index 0000000000..786cf5eff3 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/H700/030-analog_leds @@ -0,0 +1,13 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile.d/001-functions + +if [ $DEVICE_ANALOG_STICKS_LED_CONTROL == "true" ]; then + LEDS_CONFIG=$(get_setting analogsticks.led) + + if [ ! -z "${LEDS_CONFIG}" ]; then + /usr/bin/analog_sticks_ledcontrol $LEDS_CONFIG + fi +fi diff --git a/projects/ArchR/packages/hardware/quirks/platforms/H700/030-suspend_mode b/projects/ArchR/packages/hardware/quirks/platforms/H700/030-suspend_mode new file mode 100755 index 0000000000..4f773ea554 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/H700/030-suspend_mode @@ -0,0 +1,14 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +### Sleep is currently broken, so we'll disable it. + +/usr/bin/suspendmode off + +### Ignore power button presses for now, until we can finish up fixing sleep. +cat <~/.config/logind.conf.d/login.conf +[Login] +HandlePowerKey=ignore +HandleSuspendKey=ignore +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/H700/050-modifiers b/projects/ArchR/packages/hardware/quirks/platforms/H700/050-modifiers new file mode 100755 index 0000000000..922b60300d --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/H700/050-modifiers @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/050-modifiers +DEVICE_FUNC_KEYA_MODIFIER="BTN_MODE" +DEVICE_FUNC_KEYB_MODIFIER="BTN_START" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/H700/060-game_settings b/projects/ArchR/packages/hardware/quirks/platforms/H700/060-game_settings new file mode 100755 index 0000000000..f34ca69bd1 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/H700/060-game_settings @@ -0,0 +1,34 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile.d/001-functions + +### Set the default performance scaling mode for a few systems. +for SYSTEM in dreamcast n64 ports psp psx saturn gba pcfx cdi neogeo fbneo snes sfc +do + CPU_SETTING=$(get_setting ${SYSTEM}.cpugovernor) + if [ -z "${CPU_SETTING}" ] + then + set_setting ${SYSTEM}.cpugovernor performance + fi + GPU_SETTING=$(get_setting ${SYSTEM}.gpuperf) + if [ -z "${GPU_SETTING}" ] + then + set_setting ${SYSTEM}.gpuperf profile_peak + fi +done + +for SYSTEM in gb gbc nes famicom sms gamegear genesis mastersystem sega32x megadrive segacd megacd +do + CPU_SETTING=$(get_setting ${SYSTEM}.cpugovernor) + if [ -z ${CPU_SETTING} ] + then + set_setting ${SYSTEM}.cpugovernor powersave + fi + GPU_SETTING=$(get_setting ${SYSTEM}.gpuperf) + if [ -z ${GPU_SETTING} ] + then + set_setting ${SYSTEM}.gpuperf low + fi +done diff --git a/projects/ArchR/packages/hardware/quirks/platforms/H700/090-ui_service b/projects/ArchR/packages/hardware/quirks/platforms/H700/090-ui_service new file mode 100755 index 0000000000..b2f472a2ee --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/H700/090-ui_service @@ -0,0 +1,9 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +### Set the default device configuration +cat </storage/.config/profile.d/090-ui_service +UI_SERVICE="sway.service essway.service" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/H700/091-ui_shader b/projects/ArchR/packages/hardware/quirks/platforms/H700/091-ui_shader new file mode 100755 index 0000000000..d087007a42 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/H700/091-ui_shader @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +### Set the default device configuration +cat </storage/.config/profile.d/091-ui_shader +UI_SHADER="slangp" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/H700/400-set_gpu_overclock b/projects/ArchR/packages/hardware/quirks/platforms/H700/400-set_gpu_overclock new file mode 100755 index 0000000000..fcc70362ee --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/H700/400-set_gpu_overclock @@ -0,0 +1,22 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +# Get GPU overclock state +GPU_OC_STATE=$(get_setting "enable.gpu-overclock") +if [ ! -n "${GPU_OC_STATE}" ]; then + GPU_OC_STATE="disable" + set_setting "enable.gpu-overclock" "0" +elif [ "${GPU_OC_STATE}" = 1 ]; then + GPU_OC_STATE="enable" +else + GPU_OC_STATE="disable" + set_setting "enable.gpu-overclock" "0" +fi + +# Set GPU OC state +/usr/lib/autostart/quirks/platforms/H700/bin/gpu_overclock ${GPU_OC_STATE} diff --git a/projects/ArchR/packages/hardware/quirks/platforms/H700/bin/analog_sticks_ledcontrol b/projects/ArchR/packages/hardware/quirks/platforms/H700/bin/analog_sticks_ledcontrol new file mode 100755 index 0000000000..26e1ca511a --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/H700/bin/analog_sticks_ledcontrol @@ -0,0 +1,73 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +# Simple script to watch the battery capacity and +# turn the power LED orange when it reaches 30%, red at 20%, and blinking red at 10% + +# Define the serial device +SERIAL_DEVICE="/dev/ttyS2" +LED_PATH="/sys/class/leds" + +function led_state() { + echo ${2} >${LED_PATH}/${1}/brightness +} + +# Display usage if no parameters are provided +if [ $# -ne 7 ]; then + echo "Usage: $0 " + echo "Example: $0 255 255 0 0 0 0 255" + exit 1 +fi + +LED_MODE=1 +BRIGHTNESS=$1 +RIGHT_RED=$2 +RIGHT_GREEN=$3 +RIGHT_BLUE=$4 +LEFT_RED=$5 +LEFT_GREEN=$6 +LEFT_BLUE=$7 + +# Function to calculate checksum +calculate_checksum() { + local sum=0 + for byte in "$@"; do + sum=$((sum + byte)) + done + echo $((sum & 0xFF)) +} + +# Open the serial device +exec 20<>$SERIAL_DEVICE +stty -F $SERIAL_DEVICE 115200 -opost -isig -icanon -echo + +# Enable RGB LEDs +led_state rgb:kbd_backlight 1 + +# Construct the payload +PAYLOAD=$(printf '\\x%02X\\x%02X' $LED_MODE $BRIGHTNESS) +for ((i = 0; i < 8; i++)); do + PAYLOAD+=$(printf '\\x%02X\\x%02X\\x%02X' $RIGHT_RED $RIGHT_GREEN $RIGHT_BLUE) +done +for ((i = 0; i < 8; i++)); do + PAYLOAD+=$(printf '\\x%02X\\x%02X\\x%02X' $LEFT_RED $LEFT_GREEN $LEFT_BLUE) +done + +# Calculate checksum for the payload +PAYLOAD_BYTES=($LED_MODE $BRIGHTNESS) +for ((i = 0; i < 8; i++)); do + PAYLOAD_BYTES+=($RIGHT_RED $RIGHT_GREEN $RIGHT_BLUE) +done +for ((i = 0; i < 8; i++)); do + PAYLOAD_BYTES+=($LEFT_RED $LEFT_GREEN $LEFT_BLUE) +done +CHECKSUM=$(calculate_checksum "${PAYLOAD_BYTES[@]}") +PAYLOAD+=$(printf '\\x%02X' $CHECKSUM) + +# Send the payload +echo -e -n "$PAYLOAD" > $SERIAL_DEVICE + +# Close the serial device +exec 20>&- diff --git a/projects/ArchR/packages/hardware/quirks/platforms/H700/bin/gpu_overclock b/projects/ArchR/packages/hardware/quirks/platforms/H700/bin/gpu_overclock new file mode 100755 index 0000000000..16fc152d52 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/H700/bin/gpu_overclock @@ -0,0 +1,22 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +if [ -z "${GPU_FREQ}" ]; then + . /etc/profile +fi + +# Set max gpu freq +case $1 in + disable) + echo 600000000 > $GPU_FREQ/max_freq + set_setting enable.gpu-overclock 0 + ;; + enable) + echo 648000000 > $GPU_FREQ/max_freq + set_setting enable.gpu-overclock 1 + ;; +esac diff --git a/projects/ArchR/packages/hardware/quirks/platforms/H700/bin/ledcontrol b/projects/ArchR/packages/hardware/quirks/platforms/H700/bin/ledcontrol new file mode 100755 index 0000000000..3a55583605 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/H700/bin/ledcontrol @@ -0,0 +1,68 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 JELOS (https://github.com/JustEnoughLinuxOS) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +LED_PATH="/sys/class/leds" + +function led_state() { + echo ${2} >${LED_PATH}/${1}/brightness +} + +function led_off() { + led_state green\:power 0 + led_state red\:status 0 +} + +function led_red() { + led_off + led_state red\:status 1 +} + +function led_green() { + led_off + led_state green\:power 1 +} + +case ${1} in + green) + led_green + set_setting led.color ${1} + ;; + red) + led_red + set_setting led.color ${1} + ;; + off) + led_off + set_setting led.color ${1} + ;; + default) + del_setting led.color + led_green + ;; + brightness) + set_setting led.brightness ${2} + ledcontrol $(get_setting led.color) + ;; + poweroff) + led_off + ;; + list) +cat < /sys/devices/system/cpu/cpu1/online +echo 1 > /sys/devices/system/cpu/cpu2/online +echo 1 > /sys/devices/system/cpu/cpu3/online diff --git a/projects/ArchR/packages/hardware/quirks/platforms/H700/sleep.d/post/002-freq b/projects/ArchR/packages/hardware/quirks/platforms/H700/sleep.d/post/002-freq new file mode 100755 index 0000000000..cfd244ad7e --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/H700/sleep.d/post/002-freq @@ -0,0 +1,22 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +### Restore previous governors before going to sleep + +. /etc/profile + +### Grab the old governors. +OLD_CPU_FREQ=$(get_setting "sleep.cpugovernor") +if [ ! -n "${OLD_CPU_FREQ}" ]; then + OLD_CPU_FREQ="ondemand" +fi + +OLD_GPU_FREQ=$(get_setting "sleep.gpugovernor") +if [ ! -n "${OLD_GPU_FREQ}" ]; then + OLD_GPU_FREQ="simple_ondemand" +fi + +# Restore old governors. +set_cpu_gov "${OLD_CPU_FREQ}" +set_gpu_gov "${OLD_GPU_FREQ}" diff --git a/projects/ArchR/packages/hardware/quirks/platforms/H700/sleep.d/post/003-codec b/projects/ArchR/packages/hardware/quirks/platforms/H700/sleep.d/post/003-codec new file mode 100755 index 0000000000..f4d32bd153 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/H700/sleep.d/post/003-codec @@ -0,0 +1,9 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Unmute DAC + +. /etc/profile + +amixer -c0 sset DAC on diff --git a/projects/ArchR/packages/hardware/quirks/platforms/H700/sleep.d/pre/001-cpu b/projects/ArchR/packages/hardware/quirks/platforms/H700/sleep.d/pre/001-cpu new file mode 100755 index 0000000000..262c4028e2 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/H700/sleep.d/pre/001-cpu @@ -0,0 +1,11 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Keep only one cpu online + +. /etc/profile + +echo 0 > /sys/devices/system/cpu/cpu1/online +echo 0 > /sys/devices/system/cpu/cpu2/online +echo 0 > /sys/devices/system/cpu/cpu3/online diff --git a/projects/ArchR/packages/hardware/quirks/platforms/H700/sleep.d/pre/002-freq b/projects/ArchR/packages/hardware/quirks/platforms/H700/sleep.d/pre/002-freq new file mode 100755 index 0000000000..a1c235ca32 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/H700/sleep.d/pre/002-freq @@ -0,0 +1,18 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Store current freq governors and set governors to powersave. + +. /etc/profile + +### Get the current cpu and gpu governor, save for when the device wakes from sleep. +CUR_CPU_FREQ="$(cat ${CPU_FREQ}/scaling_governor)" +CUR_GPU_FREQ="$(cat ${GPU_FREQ}/governor)" + +set_setting sleep.cpugovernor "${CUR_CPU_FREQ}" +set_setting sleep.gpugovernor "${CUR_GPU_FREQ}" + +### Set all governors to powersave +set_cpu_gov powersave +set_gpu_gov powersave diff --git a/projects/ArchR/packages/hardware/quirks/platforms/H700/sleep.d/pre/003-codec b/projects/ArchR/packages/hardware/quirks/platforms/H700/sleep.d/pre/003-codec new file mode 100755 index 0000000000..171624b888 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/H700/sleep.d/pre/003-codec @@ -0,0 +1,9 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Mute DAC + +. /etc/profile + +amixer -c0 sset DAC off diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3326/002-turbo-mode_config b/projects/ArchR/packages/hardware/quirks/platforms/RK3326/002-turbo-mode_config new file mode 100755 index 0000000000..f1b68db2fe --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3326/002-turbo-mode_config @@ -0,0 +1,7 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/002-turbo-mode_config +DEVICE_TURBO_MODE="true" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3326/010-governors b/projects/ArchR/packages/hardware/quirks/platforms/RK3326/010-governors new file mode 100755 index 0000000000..0686b336a4 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3326/010-governors @@ -0,0 +1,9 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/010-governors +CPU_FREQ=("/sys/devices/system/cpu/cpufreq/policy0") +GPU_FREQ=("/sys/devices/platform/ff400000.gpu/devfreq/ff400000.gpu") +DMC_FREQ=("/sys/devices/platform/dmc/devfreq/dmc") +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3326/050-audio_path b/projects/ArchR/packages/hardware/quirks/platforms/RK3326/050-audio_path new file mode 100755 index 0000000000..0e619c4e52 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3326/050-audio_path @@ -0,0 +1,7 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/002-audio_path +DEVICE_PLAYBACK_PATH="Playback Mux" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3326/050-modifiers b/projects/ArchR/packages/hardware/quirks/platforms/RK3326/050-modifiers new file mode 100755 index 0000000000..8c0961439c --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3326/050-modifiers @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/050-modifiers +DEVICE_FUNC_KEYA_MODIFIER="BTN_SELECT" +DEVICE_FUNC_KEYB_MODIFIER="BTN_START" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3326/060-game_settings b/projects/ArchR/packages/hardware/quirks/platforms/RK3326/060-game_settings new file mode 100755 index 0000000000..e7bac6bc58 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3326/060-game_settings @@ -0,0 +1,6 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Need to set RA video driver to GL for libmali driver. +sed -i '/video_driver =/c\video_driver = "gl"' /storage/.config/retroarch/retroarch.cfg diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3326/075-mangohud-supported b/projects/ArchR/packages/hardware/quirks/platforms/RK3326/075-mangohud-supported new file mode 100644 index 0000000000..99363338f8 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3326/075-mangohud-supported @@ -0,0 +1,25 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025 ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile + +GPUDRIVER=$(/usr/bin/gpudriver) +MANGOHUD_ENABLED=$(get_setting "archr.mangohud.enabled") + +# Init setting to 'disabled' +if [ ! -n "${MANGOHUD_ENABLED}" ]; then + set_setting "archr.mangohud.enabled" "0" +fi + +# Enable / disable MangoHud support (panfrost / libmali) +if [ "${GPUDRIVER}" == "panfrost" ]; then + cat </storage/.config/profile.d/075-mangohud-supported +DEVICE_MANGOHUD_SUPPORT="true" +EOF +else + cat </storage/.config/profile.d/075-mangohud-supported +DEVICE_MANGOHUD_SUPPORT="false" +EOF +fi diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3326/090-ui_service b/projects/ArchR/packages/hardware/quirks/platforms/RK3326/090-ui_service new file mode 100755 index 0000000000..0abc282854 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3326/090-ui_service @@ -0,0 +1,10 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +### Set the default device configuration +cat </storage/.config/profile.d/090-ui_service +UI_SERVICE="sway.service essway.service" +MALI_WAYLAND_AFBC=0 +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3326/091-ui_shader b/projects/ArchR/packages/hardware/quirks/platforms/RK3326/091-ui_shader new file mode 100755 index 0000000000..7eab4389f5 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3326/091-ui_shader @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +### Set the default device configuration +cat </storage/.config/profile.d/091-ui_shader +UI_SHADER="glslp" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3326/bin/battery_led_status b/projects/ArchR/packages/hardware/quirks/platforms/RK3326/bin/battery_led_status new file mode 100644 index 0000000000..059c1870d1 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3326/bin/battery_led_status @@ -0,0 +1,70 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Simple script to watch the battery capacity and +# turn the power LED orange when it reaches 30%, red at 20%, and blinking red & orange at 10% + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +function set_led() { + case $1 in + red|off) + echo out >/sys/class/gpio/gpio${DEVICE_PWR_LED_GPIO}/direction + echo 1 >/sys/class/gpio/gpio${DEVICE_PWR_LED_GPIO}/value + ;; + green) + echo out >/sys/class/gpio/gpio${DEVICE_PWR_LED_GPIO}/direction + echo 0 >/sys/class/gpio/gpio${DEVICE_PWR_LED_GPIO}/value + ;; + orange) + echo in >/sys/class/gpio/gpio${DEVICE_PWR_LED_GPIO}/direction + ;; + esac +} + +# Set export GPIO for Power LED +if [ ! -d "/sys/class/gpio/gpio${DEVICE_PWR_LED_GPIO}" ]; then + echo ${DEVICE_PWR_LED_GPIO} > /sys/class/gpio/export +fi + +while true +do + CAP=$(cat /sys/class/power_supply/battery/capacity) + STAT=$(cat /sys/class/power_supply/battery/status) + ISDISABLED=$(get_setting powerled.disabled) + if [ "${ISDISABLED}" == "1" ] + then + set_led off + else + if [[ ${STAT} == "Discharging" ]] + then + #if (( ${CAP} <= 50 )) + #then + # for ctr in $(seq 1 1 5) + # do + # set_led orange + # sleep .5 + # set_led red + # sleep .5 + # done + # continue + #elif (( ${CAP} <= 20 )) + if (( ${CAP} <= 20 )) + then + set_led red + elif (( ${CAP} <= 30 )) + then + set_led orange + else + set_led green + fi + elif (( ${CAP} >= 95 )) + then + set_led green + fi + sleep 15 + fi +done diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3326/sleep.d/post/002-freq b/projects/ArchR/packages/hardware/quirks/platforms/RK3326/sleep.d/post/002-freq new file mode 100755 index 0000000000..d5c06cc41f --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3326/sleep.d/post/002-freq @@ -0,0 +1,23 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +### Restore previous governors before going to sleep + +. /etc/profile + +### Grab the old governors. +OLD_CPU_FREQ=$(get_setting "sleep.cpugovernor") +if [ ! -n "${OLD_CPU_FREQ}" ]; then + OLD_CPU_FREQ="schedutil" +fi + +OLD_GPU_FREQ=$(get_setting "sleep.gpugovernor") +if [ ! -n "${OLD_GPU_FREQ}" ]; then + OLD_GPU_FREQ="simple_ondemand" +fi + +# Restore old governors. +set_cpu_gov "${OLD_CPU_FREQ}" +set_dmc_gov "${OLD_CPU_FREQ}" +set_gpu_gov "${OLD_GPU_FREQ}" diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3326/sleep.d/pre/002-freq b/projects/ArchR/packages/hardware/quirks/platforms/RK3326/sleep.d/pre/002-freq new file mode 100755 index 0000000000..4fbe8c64f0 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3326/sleep.d/pre/002-freq @@ -0,0 +1,19 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Store current freq governors and set governors to powersave. + +. /etc/profile + +### Get the current cpu and gpu governor, save for when the device wakes from sleep. +CUR_CPU_FREQ="$(cat ${CPU_FREQ}/scaling_governor)" +CUR_GPU_FREQ="$(cat ${GPU_FREQ}/governor)" + +set_setting sleep.cpugovernor "${CUR_CPU_FREQ}" +set_setting sleep.gpugovernor "${CUR_GPU_FREQ}" + +### Set all governors to powersave +set_cpu_gov powersave +set_dmc_gov powersave +set_gpu_gov powersave diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3399/002-turbo-mode_config b/projects/ArchR/packages/hardware/quirks/platforms/RK3399/002-turbo-mode_config new file mode 100755 index 0000000000..f1b68db2fe --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3399/002-turbo-mode_config @@ -0,0 +1,7 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/002-turbo-mode_config +DEVICE_TURBO_MODE="true" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3399/040-affinity b/projects/ArchR/packages/hardware/quirks/platforms/RK3399/040-affinity new file mode 100755 index 0000000000..2896dabc8e --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3399/040-affinity @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/040-affinity +SLOW_CORES="taskset -c 0-3" +FAST_CORES="taskset -c 4-5" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3399/050-modifiers b/projects/ArchR/packages/hardware/quirks/platforms/RK3399/050-modifiers new file mode 100755 index 0000000000..e135998332 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3399/050-modifiers @@ -0,0 +1,10 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/050-modifiers +DEVICE_KEY_VOLUMEDOWN=114 +DEVICE_KEY_VOLUMEUP=115 +DEVICE_FUNC_KEYA_MODIFIER="BTN_SELECT" +DEVICE_FUNC_KEYB_MODIFIER="BTN_MODE" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3399/060-game_settings b/projects/ArchR/packages/hardware/quirks/platforms/RK3399/060-game_settings new file mode 100755 index 0000000000..f718e077d4 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3399/060-game_settings @@ -0,0 +1,34 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile.d/001-functions + +### Set the default performance scaling mode for a few systems. +for SYSTEM in dreamcast n64 ports psp psx saturn pcfx cdi ps2 gamecube +do + CPU_SETTING=$(get_setting ${SYSTEM}.cpugovernor) + if [ -z "${CPU_SETTING}" ] + then + set_setting ${SYSTEM}.cpugovernor performance + fi + GPU_SETTING=$(get_setting ${SYSTEM}.gpuperf) + if [ -z "${GPU_SETTING}" ] + then + set_setting ${SYSTEM}.gpuperf profile_peak + fi +done + +for SYSTEM in gb gbc gba snes nes sms gamegear genesis mastersystem sega32x megadrive segacd megacd +do + CPU_SETTING=$(get_setting ${SYSTEM}.cpugovernor) + if [ -z ${CPU_SETTING} ] + then + set_setting ${SYSTEM}.cpugovernor powersave + fi + GPU_SETTING=$(get_setting ${SYSTEM}.gpuperf) + if [ -z ${GPU_SETTING} ] + then + set_setting ${SYSTEM}.gpuperf low + fi +done diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3399/065-Touchscreen-events b/projects/ArchR/packages/hardware/quirks/platforms/RK3399/065-Touchscreen-events new file mode 100644 index 0000000000..2c43fc027b --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3399/065-Touchscreen-events @@ -0,0 +1,12 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025 ArchR (https://github.com/archr-linux/Arch-R) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +TOUCHSCREEN_EVENTS=$(get_setting key.touchscreen.events) +if [ -z "${TOUCHSCREEN_EVENTS}" ] +then + set_setting key.touchscreen.events 1 +fi diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3399/090-ui_service b/projects/ArchR/packages/hardware/quirks/platforms/RK3399/090-ui_service new file mode 100755 index 0000000000..5da8b376c7 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3399/090-ui_service @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +### Set the default device configuration +cat </storage/.config/profile.d/090-ui_service +UI_SERVICE="sway.service essway.service" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3399/091-ui_shader b/projects/ArchR/packages/hardware/quirks/platforms/RK3399/091-ui_shader new file mode 100755 index 0000000000..d087007a42 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3399/091-ui_shader @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +### Set the default device configuration +cat </storage/.config/profile.d/091-ui_shader +UI_SHADER="slangp" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3399/bin/battery_led_status b/projects/ArchR/packages/hardware/quirks/platforms/RK3399/bin/battery_led_status new file mode 100644 index 0000000000..c3de3aab6c --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3399/bin/battery_led_status @@ -0,0 +1,70 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Simple script to watch the battery capacity and +# turn the power LED orange when it reaches 30%, red at 20%, and blinking red at 10% + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +function set_led() { + case $1 in + red) + echo 0 > /sys/class/leds/battery_green/brightness + echo 1 > /sys/class/leds/battery_red/brightness + ;; + green) + echo 1 > /sys/class/leds/battery_green/brightness + echo 0 > /sys/class/leds/battery_red/brightness + ;; + orange) + echo 1 > /sys/class/leds/battery_green/brightness + echo 1 > /sys/class/leds/battery_red/brightness + ;; + off) + echo 0 > /sys/class/leds/battery_green/brightness + echo 0 > /sys/class/leds/battery_red/brightness + ;; + esac +} + + +while true +do + CAP=$(cat /sys/class/power_supply/battery/capacity) + STAT=$(cat /sys/class/power_supply/battery/status) + ISDISABLED=$(get_setting powerled.disabled) + if [ "${ISDISABLED}" == "1" ] + then + set_led off + else + if [ ${STAT} == "Discharging" ] + then + if (( ${CAP} <= 5 )) + then + for ctr in $(seq 1 1 5) + do + set_led red + sleep .5 + set_led off + sleep .5 + done + continue + elif (( ${CAP} <= 10 )) + then + set_led red + elif (( ${CAP} <= 20 )) + then + set_led orange + else + set_led green + fi + elif (( ${CAP} >= 95 )) + then + set_led green + fi + sleep 15 + fi +done diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3566/001-device_config b/projects/ArchR/packages/hardware/quirks/platforms/RK3566/001-device_config new file mode 100755 index 0000000000..5af9a2c160 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3566/001-device_config @@ -0,0 +1,7 @@ +#!/bin/sh +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2021-present Fewtarius (https://github.com/fewtarius) + +cat </storage/.config/profile.d/001-device_config +DEVICE_FAKE_JACKSENSE="false" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3566/002-turbo-mode_config b/projects/ArchR/packages/hardware/quirks/platforms/RK3566/002-turbo-mode_config new file mode 100755 index 0000000000..f1b68db2fe --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3566/002-turbo-mode_config @@ -0,0 +1,7 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/002-turbo-mode_config +DEVICE_TURBO_MODE="true" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3566/010-governors b/projects/ArchR/packages/hardware/quirks/platforms/RK3566/010-governors new file mode 100755 index 0000000000..3ac5684a8a --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3566/010-governors @@ -0,0 +1,9 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/010-governors +# FREQ governors +CPU_FREQ=("/sys/devices/system/cpu/cpufreq/policy0") +GPU_FREQ=("/sys/devices/platform/fde60000.gpu/devfreq/fde60000.gpu") +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3566/010-led_control b/projects/ArchR/packages/hardware/quirks/platforms/RK3566/010-led_control new file mode 100755 index 0000000000..e94be54ee4 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3566/010-led_control @@ -0,0 +1,9 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/010-led_control +DEVICE_LED_CONTROL="true" +DEVICE_LED_BRIGHTNESS="true" +DEVICE_LED_CHARGING="true" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3566/030-suspend_mode b/projects/ArchR/packages/hardware/quirks/platforms/RK3566/030-suspend_mode new file mode 100755 index 0000000000..a5b3d79e5d --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3566/030-suspend_mode @@ -0,0 +1,12 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile.d/001-functions + +MYSLEEPMODE=$(get_setting system.suspendmode) +if [ -z "${MYSLEEPMODE}" ] +then + /usr/bin/suspendmode mem +fi + diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3566/050-audio_path b/projects/ArchR/packages/hardware/quirks/platforms/RK3566/050-audio_path new file mode 100755 index 0000000000..b93c7a7507 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3566/050-audio_path @@ -0,0 +1,10 @@ +#!/bin/sh +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2021-present Fewtarius (https://github.com/fewtarius) + +cat </storage/.config/profile.d/002-audio_path +ALSA_PRIMARY_CARD=1 +DEVICE_PLAYBACK_PATH_SPK="HP" +DEVICE_PLAYBACK_PATH_HP="HP" +DEVICE_PLAYBACK_PATH="Playback Mux" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3566/050-modifiers b/projects/ArchR/packages/hardware/quirks/platforms/RK3566/050-modifiers new file mode 100755 index 0000000000..0796f20fb4 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3566/050-modifiers @@ -0,0 +1,10 @@ +#!/bin/sh +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2022-present Fewtarius + +cat </storage/.config/profile.d/050-modifiers +DEVICE_KEY_VOLUMEDOWN=114 +DEVICE_KEY_VOLUMEUP=115 +DEVICE_FUNC_KEYA_MODIFIER="BTN_SELECT" +DEVICE_FUNC_KEYB_MODIFIER="BTN_START" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3566/055-thermal-trips b/projects/ArchR/packages/hardware/quirks/platforms/RK3566/055-thermal-trips new file mode 100755 index 0000000000..47e9770523 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3566/055-thermal-trips @@ -0,0 +1,11 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# CPU thermal trips +echo "83000" > /sys/devices/virtual/thermal/thermal_zone0/trip_point_0_temp +echo "88000" > /sys/devices/virtual/thermal/thermal_zone0/trip_point_1_temp + +# GPU thermal trips +echo "80000" > /sys/devices/virtual/thermal/thermal_zone1/trip_point_0_temp +echo "88000" > /sys/devices/virtual/thermal/thermal_zone1/trip_point_1_temp diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3566/060-game_settings b/projects/ArchR/packages/hardware/quirks/platforms/RK3566/060-game_settings new file mode 100755 index 0000000000..3e5395a1d9 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3566/060-game_settings @@ -0,0 +1,25 @@ +#!/bin/sh +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2023-present Fewtarius (https://github.com/fewtarius) + +. /etc/profile.d/001-functions +. /storage/.config/profile.d/010-governors + +### Set the minimum GPU frequency to reduce UI latency. +echo 400000000 >${GPU_FREQ}/min_freq + +### Set the default performance scaling mode for a few systems. +for SYSTEM in dreamcast n64 ports psp psx saturn gba pcfx cdi +do + CPU_SETTING=$(get_setting ${SYSTEM}.cpugovernor) + if [ -z "${CPU_SETTING}" ] + then + set_setting ${SYSTEM}.cpugovernor performance + fi + GPU_SETTING=$(get_setting ${SYSTEM}.gpuperf) + if [ -z "${GPU_SETTING}" ] + then + set_setting ${SYSTEM}.gpuperf profile_peak + fi +done + diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3566/065-Touchscreen-events b/projects/ArchR/packages/hardware/quirks/platforms/RK3566/065-Touchscreen-events new file mode 100644 index 0000000000..2c43fc027b --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3566/065-Touchscreen-events @@ -0,0 +1,12 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025 ArchR (https://github.com/archr-linux/Arch-R) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +TOUCHSCREEN_EVENTS=$(get_setting key.touchscreen.events) +if [ -z "${TOUCHSCREEN_EVENTS}" ] +then + set_setting key.touchscreen.events 1 +fi diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3566/090-ui_service b/projects/ArchR/packages/hardware/quirks/platforms/RK3566/090-ui_service new file mode 100755 index 0000000000..8d02ef41e6 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3566/090-ui_service @@ -0,0 +1,14 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +### Set the default device configuration +cat </storage/.config/profile.d/090-ui_service +UI_SERVICE="sway.service essway.service" +if [ "$(gpudriver)" = "libmali" ]; then +MALI_WAYLAND_AFBC=0 +# libmali has no working Xorg +unset DISPLAY +fi +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3566/091-ui_shader b/projects/ArchR/packages/hardware/quirks/platforms/RK3566/091-ui_shader new file mode 100755 index 0000000000..7eab4389f5 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3566/091-ui_shader @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +### Set the default device configuration +cat </storage/.config/profile.d/091-ui_shader +UI_SHADER="glslp" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3566/bin/ledcontrol b/projects/ArchR/packages/hardware/quirks/platforms/RK3566/bin/ledcontrol new file mode 100755 index 0000000000..f0d29c92b4 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3566/bin/ledcontrol @@ -0,0 +1,96 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 JELOS (https://github.com/JustEnoughLinuxOS) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +LED_PATH="/sys/class/leds" +LED_STATUS=$(get_setting led.color) +DEFAULT=green + +function led_state() { + echo ${2} >${LED_PATH}/${1}/brightness +} + +function led_off() { + led_state green:power 0 + led_state red:status 0 + led_state amber:charging 0 +} + +function brightness() { + led_off + case ${1} in + green) + led_state green:power $2 + ;; + red) + led_state red:status $2 + ;; + amber) + led_state amber:charging $2 + ;; + esac +} + +GETBRIGHTNESS=$(get_setting led.brightness) +if [ ! -z "${2}" ] +then + LEDBRIGHTNESS=${2} +else + LEDBRIGHTNESS=${GETBRIGHTNESS:-max} +fi + +# on first run (no setting) or on new brightness update settings +if [[ ${LEDBRIGHTNESS} != ${GETBRIGHTNESS} ]]; then + set_setting led.brightness ${LEDBRIGHTNESS} +fi + +# expand aliases +case ${LEDBRIGHTNESS} in + max) + LEDBRIGHTNESS=255 + ;; + mid) + LEDBRIGHTNESS=63 + ;; + min) + LEDBRIGHTNESS=15 + ;; +esac + +case ${1} in + default) + del_setting led.color + brightness ${DEFAULT} ${LEDBRIGHTNESS} + ;; + green|red|amber|off) + brightness ${1} ${LEDBRIGHTNESS} + set_setting led.color ${1} + ;; + discharging) + brightness ${LED_STATUS:-${DEFAULT}} ${LEDBRIGHTNESS} + ;; + charging) + if [ ! "${LED_STATUS}" = "off" ] + then + brightness red ${LEDBRIGHTNESS} + fi + ;; + poweroff) + led_off + ;; + brightness) + brightness ${LED_STATUS:-${DEFAULT}} ${LEDBRIGHTNESS} + ;; + list) +cat </storage/.config/profile.d/001-device_config +DEVICE_TEMP_SENSOR="/sys/devices/virtual/thermal/thermal_zone*/temp" + +# Affinity +SLOW_CORES="taskset -c 0-3" +FAST_CORES="taskset -c 4-7" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3588/009-commander-cfg b/projects/ArchR/packages/hardware/quirks/platforms/RK3588/009-commander-cfg new file mode 100644 index 0000000000..044bb46732 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3588/009-commander-cfg @@ -0,0 +1,11 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025 ArchR (https://github.com/archr-linux/Arch-R) + +if [ ! -f "/storage/.config/commander.cfg" ]; then +cat </storage/.config/commander.cfg +disp_ppu_x=4 +disp_ppu_y=4 +EOF +fi diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3588/010-governors b/projects/ArchR/packages/hardware/quirks/platforms/RK3588/010-governors new file mode 100755 index 0000000000..05d7ad518b --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3588/010-governors @@ -0,0 +1,9 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/010-governors +CPU_FREQ=("/sys/devices/system/cpu/cpufreq/policy0" "/sys/devices/system/cpu/cpufreq/policy4" "/sys/devices/system/cpu/cpufreq/policy6") +GPU_FREQ=("/sys/devices/platform/fb000000.gpu/devfreq/fb000000.gpu") +DMC_FREQ=("/sys/devices/platform/dmc/devfreq/dmc") +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3588/010-led_control b/projects/ArchR/packages/hardware/quirks/platforms/RK3588/010-led_control new file mode 100755 index 0000000000..4f53c130ed --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3588/010-led_control @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/010-led_control +DEVICE_LED_CONTROL="true" +DEVICE_LED_CHARGING="true" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3588/040-affinity b/projects/ArchR/packages/hardware/quirks/platforms/RK3588/040-affinity new file mode 100755 index 0000000000..9d5b403e0a --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3588/040-affinity @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/040-affinity +SLOW_CORES="taskset -c 0-3" +FAST_CORES="taskset -c 4-7" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3588/041-panfrost b/projects/ArchR/packages/hardware/quirks/platforms/RK3588/041-panfrost new file mode 100755 index 0000000000..5a04561f5a --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3588/041-panfrost @@ -0,0 +1,7 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/041-panfrost +export PAN_MESA_DEBUG=gofaster +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3588/050-audio_path b/projects/ArchR/packages/hardware/quirks/platforms/RK3588/050-audio_path new file mode 100755 index 0000000000..3e31680b01 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3588/050-audio_path @@ -0,0 +1,7 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/002-audio_path +DEVICE_PLAYBACK_PATH="Playback Path" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3588/050-modifiers b/projects/ArchR/packages/hardware/quirks/platforms/RK3588/050-modifiers new file mode 100755 index 0000000000..8c0961439c --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3588/050-modifiers @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/050-modifiers +DEVICE_FUNC_KEYA_MODIFIER="BTN_SELECT" +DEVICE_FUNC_KEYB_MODIFIER="BTN_START" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3588/060-game_settings b/projects/ArchR/packages/hardware/quirks/platforms/RK3588/060-game_settings new file mode 100755 index 0000000000..5f060285d7 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3588/060-game_settings @@ -0,0 +1,44 @@ + +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile.d/001-functions + +### Set the default performance scaling mode for a few systems. +for SYSTEM in dreamcast n64 ports psp saturn ps2 gamecube wii +do + CPU_SETTING=$(get_setting ${SYSTEM}.cpugovernor) + if [ -z "${CPU_SETTING}" ] + then + set_setting ${SYSTEM}.cpugovernor performance + fi + GPU_SETTING=$(get_setting ${SYSTEM}.gpuperf) + if [ -z "${GPU_SETTING}" ] + then + set_setting ${SYSTEM}.gpuperf profile_peak + fi +done + +for SYSTEM in saturn st-v +do + CORES=$(get_setting ${SYSTEM}.cores) + if [ -z "${CORES}" ] + then + set_setting ${SYSTEM}.cores big + fi +done + +for SYSTEM in gb gbc gba snes nes sms gamegear genesis mastersystem sega32x megadrive segacd megacd +do + CPU_SETTING=$(get_setting ${SYSTEM}.cpugovernor) + if [ -z ${CPU_SETTING} ] + then + set_setting ${SYSTEM}.cpugovernor powersave + fi + GPU_SETTING=$(get_setting ${SYSTEM}.gpuperf) + if [ -z ${GPU_SETTING} ] + then + set_setting ${SYSTEM}.gpuperf low + fi +done diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3588/065-Touchscreen-events b/projects/ArchR/packages/hardware/quirks/platforms/RK3588/065-Touchscreen-events new file mode 100644 index 0000000000..2c43fc027b --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3588/065-Touchscreen-events @@ -0,0 +1,12 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025 ArchR (https://github.com/archr-linux/Arch-R) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +TOUCHSCREEN_EVENTS=$(get_setting key.touchscreen.events) +if [ -z "${TOUCHSCREEN_EVENTS}" ] +then + set_setting key.touchscreen.events 1 +fi diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3588/090-ui_service b/projects/ArchR/packages/hardware/quirks/platforms/RK3588/090-ui_service new file mode 100755 index 0000000000..ca14b6a938 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3588/090-ui_service @@ -0,0 +1,17 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +### Set the default device configuration +cat </storage/.config/profile.d/090-ui_service +GPUDRIVER=$(/usr/bin/gpudriver) + +case \${GPUDRIVER} in + "libmali") + UI_SERVICE="weston.service" + ;; + "panfrost") + UI_SERVICE="sway.service essway.service" + ;; +esac +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3588/091-ui_shader b/projects/ArchR/packages/hardware/quirks/platforms/RK3588/091-ui_shader new file mode 100755 index 0000000000..7eab4389f5 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3588/091-ui_shader @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +### Set the default device configuration +cat </storage/.config/profile.d/091-ui_shader +UI_SHADER="glslp" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/RK3588/bin/ledcontrol b/projects/ArchR/packages/hardware/quirks/platforms/RK3588/bin/ledcontrol new file mode 100755 index 0000000000..99881b2b2a --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/RK3588/bin/ledcontrol @@ -0,0 +1,70 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 JELOS (https://github.com/JustEnoughLinuxOS) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +LED_PATH="/sys/class/leds" +LED_STATUS=$(get_setting led.color) + +function led_state() { + echo ${2} >${LED_PATH}/${1}/brightness +} + +function led_off() { + led_state green_led 0 + led_state red_led 0 +} + +function led_red() { + led_off + led_state red_led 1 +} + +function led_green() { + led_off + led_state green_led 1 +} + +case ${1} in + green) + led_green + set_setting led.color ${1} + ;; + red) + led_red + set_setting led.color ${1} + ;; + off) + led_off + set_setting led.color ${1} + ;; + discharging) + if [ -n "${LED_STATUS}" ]; then + ledcontrol ${LED_STATUS} + else + led_green + fi + ;; + charging) + if [ ! "${LED_STATUS}" = "off" ]; then + led_red + fi + ;; + default) + del_setting led.color + led_green + ;; + poweroff) + led_off + ;; + list) +cat </storage/.config/profile.d/001-device_config +# Device Features +DEVICE_TEMP_SENSOR=("/sys/devices/virtual/thermal/thermal_zone0/temp" "/sys/devices/virtual/thermal/thermal_zone3/temp" "/sys/devices/virtual/thermal/thermal_zone2/temp") +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/S922X/010-governors b/projects/ArchR/packages/hardware/quirks/platforms/S922X/010-governors new file mode 100755 index 0000000000..233c565a4e --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/S922X/010-governors @@ -0,0 +1,18 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/010-governors +CPU_FREQ=("/sys/devices/system/cpu/cpufreq/policy0" "/sys/devices/system/cpu/cpufreq/policy2") + +GPUDRIVER=$(/usr/bin/gpudriver) + +case \${GPUDRIVER} in + "libmali") + GPU_FREQ=("/sys/devices/platform/soc/ffe40000.gpu_mali_vulkan/devfreq/ffe40000.gpu_mali_vulkan") + ;; + "panfrost") + GPU_FREQ=("/sys/devices/platform/soc/ffe40000.gpu/devfreq/ffe40000.gpu") + ;; +esac +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/S922X/030-suspend_mode b/projects/ArchR/packages/hardware/quirks/platforms/S922X/030-suspend_mode new file mode 100755 index 0000000000..96388b0f53 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/S922X/030-suspend_mode @@ -0,0 +1,14 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +### Sleep is currently broken, so we'll disable it. + +suspendmode off + +### Ignore power button presses for now, until we can finish up fixing sleep. +cat <~/.config/logind.conf.d/login.conf +[Login] +HandlePowerKey=ignore +HandleSuspendKey=ignore +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/S922X/040-affinity b/projects/ArchR/packages/hardware/quirks/platforms/S922X/040-affinity new file mode 100755 index 0000000000..852c85e327 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/S922X/040-affinity @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/040-affinity +SLOW_CORES="taskset -c 0-1" +FAST_CORES="taskset -c 2-5" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/S922X/041-panfrost b/projects/ArchR/packages/hardware/quirks/platforms/S922X/041-panfrost new file mode 100755 index 0000000000..a74f345fa7 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/S922X/041-panfrost @@ -0,0 +1,5 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +export PAN_MESA_DEBUG=forcepack diff --git a/projects/ArchR/packages/hardware/quirks/platforms/S922X/050-modifiers b/projects/ArchR/packages/hardware/quirks/platforms/S922X/050-modifiers new file mode 100755 index 0000000000..922b60300d --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/S922X/050-modifiers @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +cat </storage/.config/profile.d/050-modifiers +DEVICE_FUNC_KEYA_MODIFIER="BTN_MODE" +DEVICE_FUNC_KEYB_MODIFIER="BTN_START" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/S922X/075-mangohud-supported b/projects/ArchR/packages/hardware/quirks/platforms/S922X/075-mangohud-supported new file mode 100644 index 0000000000..99363338f8 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/S922X/075-mangohud-supported @@ -0,0 +1,25 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025 ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile + +GPUDRIVER=$(/usr/bin/gpudriver) +MANGOHUD_ENABLED=$(get_setting "archr.mangohud.enabled") + +# Init setting to 'disabled' +if [ ! -n "${MANGOHUD_ENABLED}" ]; then + set_setting "archr.mangohud.enabled" "0" +fi + +# Enable / disable MangoHud support (panfrost / libmali) +if [ "${GPUDRIVER}" == "panfrost" ]; then + cat </storage/.config/profile.d/075-mangohud-supported +DEVICE_MANGOHUD_SUPPORT="true" +EOF +else + cat </storage/.config/profile.d/075-mangohud-supported +DEVICE_MANGOHUD_SUPPORT="false" +EOF +fi diff --git a/projects/ArchR/packages/hardware/quirks/platforms/S922X/090-ui_service b/projects/ArchR/packages/hardware/quirks/platforms/S922X/090-ui_service new file mode 100755 index 0000000000..5da8b376c7 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/S922X/090-ui_service @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +### Set the default device configuration +cat </storage/.config/profile.d/090-ui_service +UI_SERVICE="sway.service essway.service" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/S922X/091-ui_shader b/projects/ArchR/packages/hardware/quirks/platforms/S922X/091-ui_shader new file mode 100755 index 0000000000..7eab4389f5 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/S922X/091-ui_shader @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +### Set the default device configuration +cat </storage/.config/profile.d/091-ui_shader +UI_SHADER="glslp" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/S922X/bin/battery_led_status b/projects/ArchR/packages/hardware/quirks/platforms/S922X/bin/battery_led_status new file mode 100644 index 0000000000..bfd4ad3551 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/S922X/bin/battery_led_status @@ -0,0 +1,53 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +# Simple script to watch the battery capacity and +# turn the power LED orange when it reaches 20% and blinking green & orange at 10% + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +function set_led() { + case $1 in + green) + echo 0 > /sys/class/leds/red\:status/brightness + ;; + orange) + echo 1 > /sys/class/leds/red\:status/brightness + ;; + 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 orange + sleep .5 + set_led green + sleep .5 + done + continue + elif (( ${CAP} <= 20 )) + then + set_led orange + else + set_led green + fi + elif (( ${CAP} <= 95 )) + then + set_led orange + else + set_led green + fi + sleep 15 +done diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SDM845/001-device_config b/projects/ArchR/packages/hardware/quirks/platforms/SDM845/001-device_config new file mode 100755 index 0000000000..3f012752cf --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SDM845/001-device_config @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/001-device_config +# Device Features +DEVICE_HAS_TOUCHSCREEN="true" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SDM845/002-audio_path b/projects/ArchR/packages/hardware/quirks/platforms/SDM845/002-audio_path new file mode 100755 index 0000000000..567efcfbf9 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SDM845/002-audio_path @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/002-audio_path +DEVICE_PLAYBACK_PATH_SPK="Speakers" +DEVICE_PLAYBACK_PATH_HP="HP" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SDM845/005-thermal_path b/projects/ArchR/packages/hardware/quirks/platforms/SDM845/005-thermal_path new file mode 100755 index 0000000000..279d52a50c --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SDM845/005-thermal_path @@ -0,0 +1,7 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025 ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/005-thermal_path +DEVICE_TEMP_SENSOR=("/sys/devices/virtual/thermal/thermal_zone10/temp") +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SDM845/010-governors b/projects/ArchR/packages/hardware/quirks/platforms/SDM845/010-governors new file mode 100755 index 0000000000..af711f9f74 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SDM845/010-governors @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025 ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/010-governors +CPU_FREQ=("/sys/devices/system/cpu/cpufreq/policy0" "/sys/devices/system/cpu/cpufreq/policy4") +GPU_FREQ=("/sys/devices/platform/soc@0/5000000.gpu/devfreq/5000000.gpu") +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SDM845/020-set_audio_latency b/projects/ArchR/packages/hardware/quirks/platforms/SDM845/020-set_audio_latency new file mode 100755 index 0000000000..c116a85f79 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SDM845/020-set_audio_latency @@ -0,0 +1,11 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile.d/001-functions + +AUDIO_LATENCY=$(get_setting audiolatency) +if [ -z "${AUDIO_LATENCY}" ] +then + set_setting global.audiolatency 64 +fi diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SDM845/040-affinity b/projects/ArchR/packages/hardware/quirks/platforms/SDM845/040-affinity new file mode 100755 index 0000000000..45851cfebe --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SDM845/040-affinity @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/040-affinity +SLOW_CORES="taskset -c 0-3" +FAST_CORES="taskset -c 4-7" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SDM845/065-Touchscreen-events b/projects/ArchR/packages/hardware/quirks/platforms/SDM845/065-Touchscreen-events new file mode 100644 index 0000000000..2c43fc027b --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SDM845/065-Touchscreen-events @@ -0,0 +1,12 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025 ArchR (https://github.com/archr-linux/Arch-R) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +TOUCHSCREEN_EVENTS=$(get_setting key.touchscreen.events) +if [ -z "${TOUCHSCREEN_EVENTS}" ] +then + set_setting key.touchscreen.events 1 +fi diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SDM845/070-modifiers b/projects/ArchR/packages/hardware/quirks/platforms/SDM845/070-modifiers new file mode 100755 index 0000000000..adf2be4df1 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SDM845/070-modifiers @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/050-modifiers +DEVICE_FUNC_KEYA_MODIFIER="BTN_MODE" +DEVICE_FUNC_KEYB_MODIFIER="BTN_START" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SDM845/075-mangohud-supported b/projects/ArchR/packages/hardware/quirks/platforms/SDM845/075-mangohud-supported new file mode 100644 index 0000000000..ff795efd72 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SDM845/075-mangohud-supported @@ -0,0 +1,18 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025 ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile + +# Enable MangoHud support +MANGOHUD_SUPPORTED=$(get_setting "archr.mangohud.enabled") +if [ ! -n "${MANGOHUD_SUPPORTED}" ]; then + MANGOHUD_SUPPORTED="0" + set_setting "archr.mangohud.enabled" "${MANGOHUD_SUPPORTED}" +fi + +cat </storage/.config/profile.d/075-mangohud-supported +# Device Features +DEVICE_MANGOHUD_SUPPORT="true" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SDM845/090-ui_service b/projects/ArchR/packages/hardware/quirks/platforms/SDM845/090-ui_service new file mode 100755 index 0000000000..4ae841806e --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SDM845/090-ui_service @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +### Set the default device configuration +cat </storage/.config/profile.d/090-ui_service +UI_SERVICE="sway.service essway.service" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SDM845/091-ui_shader b/projects/ArchR/packages/hardware/quirks/platforms/SDM845/091-ui_shader new file mode 100755 index 0000000000..0b1a8b79d9 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SDM845/091-ui_shader @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +### Set the default device configuration +cat </storage/.config/profile.d/091-ui_shader +UI_SHADER="slangp" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SDM845/bin/achievements b/projects/ArchR/packages/hardware/quirks/platforms/SDM845/bin/achievements new file mode 100755 index 0000000000..b0938417ad --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SDM845/bin/achievements @@ -0,0 +1,5 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +/usr/bin/ledcontrol rainbow diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SDM845/bin/analog_sticks_ledcontrol b/projects/ArchR/packages/hardware/quirks/platforms/SDM845/bin/analog_sticks_ledcontrol new file mode 100755 index 0000000000..bc517cd61b --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SDM845/bin/analog_sticks_ledcontrol @@ -0,0 +1,45 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2025 ArchR (https://github.com/archr-linux/Arch-R) + +# Simple script to set led brightness and rgb color based on +# brightness and rgb values from emulation station + +LED_PATH="/sys/devices/platform/" + +function led_brightness() { + n=1 + while [ "$n" -lt 4 ]; do + echo ${2} > ${LED_PATH}/multi-led${1}${n}/leds/rgb:${1}${n}/brightness + n=$(( n + 1 )) + done +} + +function led_rgb() { + n=1 + while [ "$n" -lt 4 ]; do + echo ${2} ${3} ${4} > ${LED_PATH}/multi-led${1}${n}/leds/rgb:${1}${n}/multi_intensity + n=$(( n + 1 )) + done +} + +# Display usage if no parameters are provided +if [ $# -ne 7 ]; then + echo "Usage: $0 " + echo "Example: $0 255 255 0 0 0 0 255" + exit 1 +fi + +BRIGHTNESS=$1 +RIGHT_RED=$2 +RIGHT_GREEN=$3 +RIGHT_BLUE=$4 +LEFT_RED=$5 +LEFT_GREEN=$6 +LEFT_BLUE=$7 + +led_brightness l $BRIGHTNESS +led_rgb l $LEFT_BLUE $LEFT_GREEN $LEFT_RED +led_brightness r $BRIGHTNESS +led_rgb r $RIGHT_BLUE $RIGHT_GREEN $RIGHT_RED diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SDM845/bin/battery_led_status b/projects/ArchR/packages/hardware/quirks/platforms/SDM845/bin/battery_led_status new file mode 100755 index 0000000000..b3e83e2d6f --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SDM845/bin/battery_led_status @@ -0,0 +1,129 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +# Simple script to watch the battery capacity and +# turn the power LED orange when it reaches 30%, red at 20%, and blinking red at 10% + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +LED_PATH="/sys/devices/platform/" + +function bat_led_off() { + n=1 + while [ "$n" -lt 4 ]; do + echo 0 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/brightness + echo 0 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/brightness + echo 0 0 0 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/multi_intensity + echo 0 0 0 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/multi_intensity + n=$(( n + 1 )) + done +} + +function bat_led_red() { + n=1 + while [ "$n" -lt 4 ]; do + echo 255 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/brightness + echo 255 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/brightness + echo 0 0 255 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/multi_intensity + echo 0 0 255 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/multi_intensity + n=$(( n + 1 )) + done +} + +function bat_led_green() { + n=1 + while [ "$n" -lt 4 ]; do + echo 255 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/brightness + echo 255 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/brightness + echo 0 255 0 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/multi_intensity + echo 0 255 0 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/multi_intensity + n=$(( n + 1 )) + done +} + +function bat_led_orange() { + n=1 + while [ "$n" -lt 4 ]; do + echo 255 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/brightness + echo 255 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/brightness + echo 0 20 255 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/multi_intensity + echo 0 20 255 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/multi_intensity + n=$(( n + 1 )) + done +} + +function bat_led_yellow() { + n=1 + while [ "$n" -lt 4 ]; do + echo 255 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/brightness + echo 255 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/brightness + echo 0 125 255 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/multi_intensity + echo 0 125 255 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/multi_intensity + n=$(( n + 1 )) + done +} + +PREV_BATCAP="null" +while true + do + BAT_LED_STATE=$(get_setting led.color) + if [ ! ${BAT_LED_STATE} == "battery" ]; then + break + else + 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 + bat_led_red + sleep .5 + bat_led_off + sleep .5 + done + continue + elif (( ${CAP} <= 20 )) + then + BATCAP="D_RED" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_red + fi + elif (( ${CAP} <= 30 )) + then + BATCAP="D_ORANGE" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_orange + fi + elif (( ${CAP} <= 40 )) + then + BATCAP="D_YELLOW" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_yellow + fi + else + BATCAP="D_GREEN" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_green + fi + fi + elif (( ${CAP} <= 94 )) + then + BATCAP="C_ORANGE" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_orange + fi + elif (( ${CAP} >= 95 )) + then + BATCAP="C_GREEN" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_green + fi + fi + PREV_BATCAP=${BATCAP} + sleep 15 + fi +done diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SDM845/bin/fancontrol b/projects/ArchR/packages/hardware/quirks/platforms/SDM845/bin/fancontrol new file mode 100755 index 0000000000..972e68e7b7 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SDM845/bin/fancontrol @@ -0,0 +1,103 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile + +DEBUG=false +COOLING_PROFILE=$(get_setting "cooling.profile") +FAN_PWM="${DEVICE_PWM_FAN}" + +log $0 "Setting profile to ${COOLING_PROFILE}" + +function set_control() { + log $0 "Set fan control to ${1}" + if [ -e "${DEVICE_PWM_FAN}_enable" ] + then + echo ${1} >${DEVICE_PWM_FAN}_enable + fi +} + +trap "set_control 0 && exit 0" SIGHUP SIGINT SIGQUIT SIGABRT + +if [ -e "/storage/.config/fancontrol.conf" ] && [ "${COOLING_PROFILE}" = "custom" ] +then + log $0 "Loading configuration file" 2>/dev/null + source /storage/.config/fancontrol.conf + if [ ! $? = 0 ] + then + WARN="Custom fan profile could not be loaded, defaulting to auto." + log $0 "${WARN}" + COOLING_PROFILE="auto" + set_setting cooling.profile auto + fi +fi + + +if [ ! "${COOLING_PROFILE}" = "custom" ] +then + if [ "${COOLING_PROFILE}" = "aggressive" ]; then + MAXTEMP="75000" + HIGHTEMP="65000" + MIDTEMP="55000" + LOWTEMP="45000" + MINTEMP="35000" + elif [ "${COOLING_PROFILE}" = "moderate" ]; then + MAXTEMP="80000" + HIGHTEMP="70000" + MIDTEMP="60000" + LOWTEMP="50000" + MINTEMP="40000" + elif [ "${COOLING_PROFILE}" = "quiet" ]; then + # Quiet. + MAXTEMP="85000" + HIGHTEMP="75000" + MIDTEMP="65000" + LOWTEMP="55000" + MINTEMP="45000" + else + # auto + set_control 0 >/dev/null 2>&1 + exit 0 + fi +fi + +CTEMP="1" + +log $0 "Enabling fan control." +set_control 1 >/dev/null 2>&1 + +while true + do + INDEX=0 + CPU_TEMP=$(awk '{total += $1; count++} END {printf "%d", total/count}' ${DEVICE_TEMP_SENSOR}) + $DEBUG && log $0 "CPU TEMP: ${CPU_TEMP}" 2>/dev/null + if (( "${CPU_TEMP}" > "${MAXTEMP}" )); then + FSPEED="255" + TEMP="${MAXTEMP}" + elif (( "${CPU_TEMP}" > "${HIGHTEMP}" )); then + FSPEED="196" + TEMP="${HIGHTEMP}" + elif (( "${CPU_TEMP}" > "${MIDTEMP}" )); then + FSPEED="128" + TEMP="${MIDTEMP}" + elif (( "${CPU_TEMP}" > "${LOWTEMP}" )); then + FSPEED="96" + TEMP="${LOWTEMP}" + elif (( "${CPU_TEMP}" > "${MINTEMP}" )); then + FSPEED="64" + TEMP="${MINTEMP}" + else + FSPEED="32" + TEMP=0 + fi + if (( ${TEMP} != ${CTEMP} )); then + echo ${FSPEED} > ${FAN_PWM} + CTEMP=${TEMP} + $DEBUG && log $0 "Setting PWM FAN to ${FSPEED} at CPU Temp: ${CPU_TEMP}" 2>/dev/null + fi + sleep 3 +done + +log $0 "Disabling fan control." +set_control 0 >/dev/null 2>&1 diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SDM845/bin/gpu_overclock b/projects/ArchR/packages/hardware/quirks/platforms/SDM845/bin/gpu_overclock new file mode 100755 index 0000000000..5d88686b03 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SDM845/bin/gpu_overclock @@ -0,0 +1,18 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +# Set max gpu freq +case $1 in + disable) + echo 587000000 > $GPU_FREQ/max_freq + set_setting enable.gpu-overclock 0 + ;; + enable) + echo 650000000 > $GPU_FREQ/max_freq + set_setting enable.gpu-overclock 1 + ;; +esac diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SDM845/bin/ledcontrol b/projects/ArchR/packages/hardware/quirks/platforms/SDM845/bin/ledcontrol new file mode 100755 index 0000000000..e9013d4a14 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SDM845/bin/ledcontrol @@ -0,0 +1,153 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +LED_PATH="/sys/devices/platform/" + +function led_off() { + n=1 + while [ "$n" -lt 4 ]; do + echo 0 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/brightness + echo 0 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/brightness + echo 0 0 0 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/multi_intensity + echo 0 0 0 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/multi_intensity + n=$(( n + 1 )) + done +} + +function led_rainbow() { + # Rainbow effect configuration + STEPS=30 # Fewer steps for faster transitions + DURATION=0.5 # Shorter duration (half a second per cycle) + SLEEP_TIME=$(echo "scale=4; $DURATION/$STEPS" | bc) + CYCLES=2 # Number of cycles to run + + calculate_rainbow_color() { + local position=$1 + local h=$(echo "scale=2; 360*$position/$STEPS" | bc) + + # Convert HSV (with S=1, V=1) to RGB + # Calculate region and fractional part + local region=$(echo "scale=0; $h/60" | bc) + local remainder=$(echo "scale=2; $h-$region*60" | bc) + local fractional=$(echo "scale=2; $remainder/60" | bc) + + # Initialize RGB values + local r=0 + local g=0 + local b=0 + + # Calculate RGB based on hue region (0-5) + case $region in + 0) + # 0-60: Red to Yellow + r=255 + g=$(echo "scale=0; 255*$fractional" | bc) + b=0 + ;; + 1) + # 60-120: Yellow to Green + r=$(echo "scale=0; 255*(1-$fractional)" | bc) + g=255 + b=0 + ;; + 2) + # 120-180: Green to Cyan + r=0 + g=255 + b=$(echo "scale=0; 255*$fractional" | bc) + ;; + 3) + # 180-240: Cyan to Blue + r=0 + g=$(echo "scale=0; 255*(1-$fractional)" | bc) + b=255 + ;; + 4) + # 240-300: Blue to Magenta + r=$(echo "scale=0; 255*$fractional" | bc) + g=0 + b=255 + ;; + 5|6) + # 300-360: Magenta to Red + r=255 + g=0 + b=$(echo "scale=0; 255*(1-$fractional)" | bc) + ;; + esac + + # Ensure values are integers + r=${r%.*} + g=${g%.*} + b=${b%.*} + + # Ensure values are not negative or exceed 255 + r=$(( r < 0 ? 0 : r > 255 ? 255 : r )) + g=$(( g < 0 ? 0 : g > 255 ? 255 : g )) + b=$(( b < 0 ? 0 : b > 255 ? 255 : b )) + + echo "$r $g $b" + } + + # Main rainbow effect loop + # Loop several times to create a continuous effect + for ((cycle=0; cycle/storage/.config/profile.d/001-device_config +# Device Features +DEVICE_HAS_TOUCHSCREEN="true" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8250/002-audio_path b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/002-audio_path new file mode 100644 index 0000000000..567efcfbf9 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/002-audio_path @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/002-audio_path +DEVICE_PLAYBACK_PATH_SPK="Speakers" +DEVICE_PLAYBACK_PATH_HP="HP" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8250/005-thermal_path b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/005-thermal_path new file mode 100644 index 0000000000..a8249224ba --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/005-thermal_path @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/005-thermal_path +DEVICE_TEMP_SENSOR=("/sys/devices/virtual/thermal/thermal_zone10/temp") +DEVICE_GPU_TEMP_SENSOR=("/sys/devices/virtual/thermal/thermal_zone15/temp") +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8250/009-commander-cfg b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/009-commander-cfg new file mode 100644 index 0000000000..044bb46732 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/009-commander-cfg @@ -0,0 +1,11 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025 ArchR (https://github.com/archr-linux/Arch-R) + +if [ ! -f "/storage/.config/commander.cfg" ]; then +cat </storage/.config/commander.cfg +disp_ppu_x=4 +disp_ppu_y=4 +EOF +fi diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8250/009-serial-number-path b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/009-serial-number-path new file mode 100644 index 0000000000..868efa3397 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/009-serial-number-path @@ -0,0 +1,8 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025 ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/009-serial-number-path +DEVICE_SERIAL_NUMBER_PATH=("/sys/devices/soc0/serial_number") +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8250/010-governors b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/010-governors new file mode 100644 index 0000000000..c197729c35 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/010-governors @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/010-governors +CPU_FREQ=("/sys/devices/system/cpu/cpufreq/policy0" "/sys/devices/system/cpu/cpufreq/policy4" "/sys/devices/system/cpu/cpufreq/policy7") +GPU_FREQ=("/sys/devices/platform/soc@0/3d00000.gpu/devfreq/3d00000.gpu") +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8250/020-fan_control b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/020-fan_control new file mode 100755 index 0000000000..318d3caa36 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/020-fan_control @@ -0,0 +1,12 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/020-fan_control + +FANPATH="\$(ls /sys/class/hwmon/hwmon*/pwm1 | grep hwmon | cut -c 18-24)" + +DEVICE_HAS_FAN="true" +DEVICE_PWM_FAN="/sys/class/hwmon/\${FANPATH}/pwm1" +DEVICE_FAN_INPUT="/sys/class/hwmon/\${FANPATH}/pwm1" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8250/020-set_audio_latency b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/020-set_audio_latency new file mode 100644 index 0000000000..c116a85f79 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/020-set_audio_latency @@ -0,0 +1,11 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile.d/001-functions + +AUDIO_LATENCY=$(get_setting audiolatency) +if [ -z "${AUDIO_LATENCY}" ] +then + set_setting global.audiolatency 64 +fi diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8250/030-led-control b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/030-led-control new file mode 100644 index 0000000000..f0a31c9c83 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/030-led-control @@ -0,0 +1,9 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/010-led_control +DEVICE_LED_CONTROL="true" +DEVICE_BATTERY_LED_STATUS="true" +DEVICE_ANALOG_STICKS_LED_CONTROL="true" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8250/031-analog_leds b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/031-analog_leds new file mode 100644 index 0000000000..786cf5eff3 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/031-analog_leds @@ -0,0 +1,13 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile.d/001-functions + +if [ $DEVICE_ANALOG_STICKS_LED_CONTROL == "true" ]; then + LEDS_CONFIG=$(get_setting analogsticks.led) + + if [ ! -z "${LEDS_CONFIG}" ]; then + /usr/bin/analog_sticks_ledcontrol $LEDS_CONFIG + fi +fi diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8250/040-affinity b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/040-affinity new file mode 100755 index 0000000000..45851cfebe --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/040-affinity @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/040-affinity +SLOW_CORES="taskset -c 0-3" +FAST_CORES="taskset -c 4-7" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8250/060-game_settings b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/060-game_settings new file mode 100755 index 0000000000..595cac4d55 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/060-game_settings @@ -0,0 +1,43 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile.d/001-functions + +### Set the default performance scaling mode for a few systems. +for SYSTEM in saturn ps2 gamecube wii 3ds ps3 xbox +do + CPU_SETTING=$(get_setting ${SYSTEM}.cpugovernor) + if [ -z "${CPU_SETTING}" ] + then + set_setting ${SYSTEM}.cpugovernor performance + fi + GPU_SETTING=$(get_setting ${SYSTEM}.gpuperf) + if [ -z "${GPU_SETTING}" ] + then + set_setting ${SYSTEM}.gpuperf profile_peak + fi +done + +for SYSTEM in saturn st-v +do + CORES=$(get_setting ${SYSTEM}.cores) + if [ -z "${CORES}" ] + then + set_setting ${SYSTEM}.cores big + fi +done + +for SYSTEM in gb gbc gba nes sms gamegear genesis mastersystem sega32x megadrive segacd megacd +do + CPU_SETTING=$(get_setting ${SYSTEM}.cpugovernor) + if [ -z ${CPU_SETTING} ] + then + set_setting ${SYSTEM}.cpugovernor powersave + fi + GPU_SETTING=$(get_setting ${SYSTEM}.gpuperf) + if [ -z ${GPU_SETTING} ] + then + set_setting ${SYSTEM}.gpuperf low + fi +done diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8250/061-yabasanshiro_config b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/061-yabasanshiro_config new file mode 100644 index 0000000000..5bf099d847 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/061-yabasanshiro_config @@ -0,0 +1,26 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +DEVICE_NAME="Retroid Pocket Gamepad" +CONFIG_DIR="/storage/.config/yabasanshiro" +CONFIG_FILE="input.cfg" + +if [ ! -d "${CONFIG_DIR}" ] +then + mkdir -p "${CONFIG_DIR}" +fi + +if [ ! -e "${CONFIG_DIR}/${CONFIG_FILE}" ]; then + GAMEPADCONFIG=$(xmlstarlet sel -t -c "//inputList/inputConfig[@deviceName='${DEVICE_NAME}']" -n /storage/.emulationstation/es_input.cfg) + + if [ ! -z "${GAMEPADCONFIG}" ]; then + cat <${CONFIG_DIR}/${CONFIG_FILE} + + +${GAMEPADCONFIG} + +EOF + fi +fi diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8250/065-Touchscreen-events b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/065-Touchscreen-events new file mode 100644 index 0000000000..2c43fc027b --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/065-Touchscreen-events @@ -0,0 +1,12 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025 ArchR (https://github.com/archr-linux/Arch-R) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +TOUCHSCREEN_EVENTS=$(get_setting key.touchscreen.events) +if [ -z "${TOUCHSCREEN_EVENTS}" ] +then + set_setting key.touchscreen.events 1 +fi diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8250/070-modifiers b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/070-modifiers new file mode 100644 index 0000000000..adf2be4df1 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/070-modifiers @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/050-modifiers +DEVICE_FUNC_KEYA_MODIFIER="BTN_MODE" +DEVICE_FUNC_KEYB_MODIFIER="BTN_START" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8250/075-mangohud-supported b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/075-mangohud-supported new file mode 100644 index 0000000000..ff795efd72 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/075-mangohud-supported @@ -0,0 +1,18 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025 ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile + +# Enable MangoHud support +MANGOHUD_SUPPORTED=$(get_setting "archr.mangohud.enabled") +if [ ! -n "${MANGOHUD_SUPPORTED}" ]; then + MANGOHUD_SUPPORTED="0" + set_setting "archr.mangohud.enabled" "${MANGOHUD_SUPPORTED}" +fi + +cat </storage/.config/profile.d/075-mangohud-supported +# Device Features +DEVICE_MANGOHUD_SUPPORT="true" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8250/090-ui_service b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/090-ui_service new file mode 100755 index 0000000000..4ae841806e --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/090-ui_service @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +### Set the default device configuration +cat </storage/.config/profile.d/090-ui_service +UI_SERVICE="sway.service essway.service" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8250/091-ui_shader b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/091-ui_shader new file mode 100755 index 0000000000..0b1a8b79d9 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/091-ui_shader @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +### Set the default device configuration +cat </storage/.config/profile.d/091-ui_shader +UI_SHADER="slangp" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8250/400-set_gpu_overclock b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/400-set_gpu_overclock new file mode 100644 index 0000000000..1a22d0e557 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/400-set_gpu_overclock @@ -0,0 +1,16 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile + +# Get GPU overclock state +GPU_OC_SPEED=$(get_setting "gpu-overclock-speed") +if [ ! -n "${GPU_OC_STATE}" ]; then + GPU_OC_STATE="0" + set_setting "gpu-overclock-speed" "${GPU_OC_SPEED}" +fi + +# Set GPU OC state +/usr/lib/autostart/quirks/platforms/SM8250/bin/gpu_overclock "${GPU_OC_SPEED}" diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8250/500-enable-led b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/500-enable-led new file mode 100755 index 0000000000..92d7589dca --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/500-enable-led @@ -0,0 +1,16 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile + +# Get Internal LED State +LED_STATE=$(get_setting "led.color") +if [ ! -n "${LED_STATE}" ]; then + LED_STATE="battery" + set_setting "led.color" "battery" +fi + +# Run LED control at boot +/usr/bin/ledcontrol ${LED_STATE} diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8250/bin/achievements b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/bin/achievements new file mode 100644 index 0000000000..b0938417ad --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/bin/achievements @@ -0,0 +1,5 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +/usr/bin/ledcontrol rainbow diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8250/bin/analog_sticks_ledcontrol b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/bin/analog_sticks_ledcontrol new file mode 100644 index 0000000000..bc517cd61b --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/bin/analog_sticks_ledcontrol @@ -0,0 +1,45 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2025 ArchR (https://github.com/archr-linux/Arch-R) + +# Simple script to set led brightness and rgb color based on +# brightness and rgb values from emulation station + +LED_PATH="/sys/devices/platform/" + +function led_brightness() { + n=1 + while [ "$n" -lt 4 ]; do + echo ${2} > ${LED_PATH}/multi-led${1}${n}/leds/rgb:${1}${n}/brightness + n=$(( n + 1 )) + done +} + +function led_rgb() { + n=1 + while [ "$n" -lt 4 ]; do + echo ${2} ${3} ${4} > ${LED_PATH}/multi-led${1}${n}/leds/rgb:${1}${n}/multi_intensity + n=$(( n + 1 )) + done +} + +# Display usage if no parameters are provided +if [ $# -ne 7 ]; then + echo "Usage: $0 " + echo "Example: $0 255 255 0 0 0 0 255" + exit 1 +fi + +BRIGHTNESS=$1 +RIGHT_RED=$2 +RIGHT_GREEN=$3 +RIGHT_BLUE=$4 +LEFT_RED=$5 +LEFT_GREEN=$6 +LEFT_BLUE=$7 + +led_brightness l $BRIGHTNESS +led_rgb l $LEFT_BLUE $LEFT_GREEN $LEFT_RED +led_brightness r $BRIGHTNESS +led_rgb r $RIGHT_BLUE $RIGHT_GREEN $RIGHT_RED diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8250/bin/battery_led_status b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/bin/battery_led_status new file mode 100644 index 0000000000..b3e83e2d6f --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/bin/battery_led_status @@ -0,0 +1,129 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +# Simple script to watch the battery capacity and +# turn the power LED orange when it reaches 30%, red at 20%, and blinking red at 10% + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +LED_PATH="/sys/devices/platform/" + +function bat_led_off() { + n=1 + while [ "$n" -lt 4 ]; do + echo 0 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/brightness + echo 0 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/brightness + echo 0 0 0 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/multi_intensity + echo 0 0 0 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/multi_intensity + n=$(( n + 1 )) + done +} + +function bat_led_red() { + n=1 + while [ "$n" -lt 4 ]; do + echo 255 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/brightness + echo 255 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/brightness + echo 0 0 255 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/multi_intensity + echo 0 0 255 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/multi_intensity + n=$(( n + 1 )) + done +} + +function bat_led_green() { + n=1 + while [ "$n" -lt 4 ]; do + echo 255 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/brightness + echo 255 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/brightness + echo 0 255 0 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/multi_intensity + echo 0 255 0 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/multi_intensity + n=$(( n + 1 )) + done +} + +function bat_led_orange() { + n=1 + while [ "$n" -lt 4 ]; do + echo 255 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/brightness + echo 255 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/brightness + echo 0 20 255 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/multi_intensity + echo 0 20 255 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/multi_intensity + n=$(( n + 1 )) + done +} + +function bat_led_yellow() { + n=1 + while [ "$n" -lt 4 ]; do + echo 255 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/brightness + echo 255 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/brightness + echo 0 125 255 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/multi_intensity + echo 0 125 255 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/multi_intensity + n=$(( n + 1 )) + done +} + +PREV_BATCAP="null" +while true + do + BAT_LED_STATE=$(get_setting led.color) + if [ ! ${BAT_LED_STATE} == "battery" ]; then + break + else + 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 + bat_led_red + sleep .5 + bat_led_off + sleep .5 + done + continue + elif (( ${CAP} <= 20 )) + then + BATCAP="D_RED" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_red + fi + elif (( ${CAP} <= 30 )) + then + BATCAP="D_ORANGE" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_orange + fi + elif (( ${CAP} <= 40 )) + then + BATCAP="D_YELLOW" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_yellow + fi + else + BATCAP="D_GREEN" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_green + fi + fi + elif (( ${CAP} <= 94 )) + then + BATCAP="C_ORANGE" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_orange + fi + elif (( ${CAP} >= 95 )) + then + BATCAP="C_GREEN" + if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then + bat_led_green + fi + fi + PREV_BATCAP=${BATCAP} + sleep 15 + fi +done diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8250/bin/fancontrol b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/bin/fancontrol new file mode 100755 index 0000000000..972e68e7b7 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/bin/fancontrol @@ -0,0 +1,103 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +. /etc/profile + +DEBUG=false +COOLING_PROFILE=$(get_setting "cooling.profile") +FAN_PWM="${DEVICE_PWM_FAN}" + +log $0 "Setting profile to ${COOLING_PROFILE}" + +function set_control() { + log $0 "Set fan control to ${1}" + if [ -e "${DEVICE_PWM_FAN}_enable" ] + then + echo ${1} >${DEVICE_PWM_FAN}_enable + fi +} + +trap "set_control 0 && exit 0" SIGHUP SIGINT SIGQUIT SIGABRT + +if [ -e "/storage/.config/fancontrol.conf" ] && [ "${COOLING_PROFILE}" = "custom" ] +then + log $0 "Loading configuration file" 2>/dev/null + source /storage/.config/fancontrol.conf + if [ ! $? = 0 ] + then + WARN="Custom fan profile could not be loaded, defaulting to auto." + log $0 "${WARN}" + COOLING_PROFILE="auto" + set_setting cooling.profile auto + fi +fi + + +if [ ! "${COOLING_PROFILE}" = "custom" ] +then + if [ "${COOLING_PROFILE}" = "aggressive" ]; then + MAXTEMP="75000" + HIGHTEMP="65000" + MIDTEMP="55000" + LOWTEMP="45000" + MINTEMP="35000" + elif [ "${COOLING_PROFILE}" = "moderate" ]; then + MAXTEMP="80000" + HIGHTEMP="70000" + MIDTEMP="60000" + LOWTEMP="50000" + MINTEMP="40000" + elif [ "${COOLING_PROFILE}" = "quiet" ]; then + # Quiet. + MAXTEMP="85000" + HIGHTEMP="75000" + MIDTEMP="65000" + LOWTEMP="55000" + MINTEMP="45000" + else + # auto + set_control 0 >/dev/null 2>&1 + exit 0 + fi +fi + +CTEMP="1" + +log $0 "Enabling fan control." +set_control 1 >/dev/null 2>&1 + +while true + do + INDEX=0 + CPU_TEMP=$(awk '{total += $1; count++} END {printf "%d", total/count}' ${DEVICE_TEMP_SENSOR}) + $DEBUG && log $0 "CPU TEMP: ${CPU_TEMP}" 2>/dev/null + if (( "${CPU_TEMP}" > "${MAXTEMP}" )); then + FSPEED="255" + TEMP="${MAXTEMP}" + elif (( "${CPU_TEMP}" > "${HIGHTEMP}" )); then + FSPEED="196" + TEMP="${HIGHTEMP}" + elif (( "${CPU_TEMP}" > "${MIDTEMP}" )); then + FSPEED="128" + TEMP="${MIDTEMP}" + elif (( "${CPU_TEMP}" > "${LOWTEMP}" )); then + FSPEED="96" + TEMP="${LOWTEMP}" + elif (( "${CPU_TEMP}" > "${MINTEMP}" )); then + FSPEED="64" + TEMP="${MINTEMP}" + else + FSPEED="32" + TEMP=0 + fi + if (( ${TEMP} != ${CTEMP} )); then + echo ${FSPEED} > ${FAN_PWM} + CTEMP=${TEMP} + $DEBUG && log $0 "Setting PWM FAN to ${FSPEED} at CPU Temp: ${CPU_TEMP}" 2>/dev/null + fi + sleep 3 +done + +log $0 "Disabling fan control." +set_control 0 >/dev/null 2>&1 diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8250/bin/gpu_overclock b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/bin/gpu_overclock new file mode 100644 index 0000000000..3c0b2703d6 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/bin/gpu_overclock @@ -0,0 +1,35 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +if [ -z "${GPU_FREQ}" ]; then + . /etc/profile +fi + +# Set max gpu freq +case $1 in + 0) + echo 587000000 > $GPU_FREQ/max_freq + set_setting gpu-overclock-speed 0 + ;; + 650) + echo 650000000 > $GPU_FREQ/max_freq + set_setting gpu-overclock-speed 650 + ;; + 700) + echo 700000000 > $GPU_FREQ/max_freq + set_setting gpu-overclock-speed 700 + ;; + 750) + echo 750000000 > $GPU_FREQ/max_freq + set_setting gpu-overclock-speed 750 + ;; + 800) + echo 800000000 > $GPU_FREQ/max_freq + set_setting gpu-overclock-speed 800 + ;; +esac diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8250/bin/ledcontrol b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/bin/ledcontrol new file mode 100644 index 0000000000..e9013d4a14 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8250/bin/ledcontrol @@ -0,0 +1,153 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +LED_PATH="/sys/devices/platform/" + +function led_off() { + n=1 + while [ "$n" -lt 4 ]; do + echo 0 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/brightness + echo 0 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/brightness + echo 0 0 0 > ${LED_PATH}/multi-ledl${n}/leds/rgb:l${n}/multi_intensity + echo 0 0 0 > ${LED_PATH}/multi-ledr${n}/leds/rgb:r${n}/multi_intensity + n=$(( n + 1 )) + done +} + +function led_rainbow() { + # Rainbow effect configuration + STEPS=30 # Fewer steps for faster transitions + DURATION=0.5 # Shorter duration (half a second per cycle) + SLEEP_TIME=$(echo "scale=4; $DURATION/$STEPS" | bc) + CYCLES=2 # Number of cycles to run + + calculate_rainbow_color() { + local position=$1 + local h=$(echo "scale=2; 360*$position/$STEPS" | bc) + + # Convert HSV (with S=1, V=1) to RGB + # Calculate region and fractional part + local region=$(echo "scale=0; $h/60" | bc) + local remainder=$(echo "scale=2; $h-$region*60" | bc) + local fractional=$(echo "scale=2; $remainder/60" | bc) + + # Initialize RGB values + local r=0 + local g=0 + local b=0 + + # Calculate RGB based on hue region (0-5) + case $region in + 0) + # 0-60: Red to Yellow + r=255 + g=$(echo "scale=0; 255*$fractional" | bc) + b=0 + ;; + 1) + # 60-120: Yellow to Green + r=$(echo "scale=0; 255*(1-$fractional)" | bc) + g=255 + b=0 + ;; + 2) + # 120-180: Green to Cyan + r=0 + g=255 + b=$(echo "scale=0; 255*$fractional" | bc) + ;; + 3) + # 180-240: Cyan to Blue + r=0 + g=$(echo "scale=0; 255*(1-$fractional)" | bc) + b=255 + ;; + 4) + # 240-300: Blue to Magenta + r=$(echo "scale=0; 255*$fractional" | bc) + g=0 + b=255 + ;; + 5|6) + # 300-360: Magenta to Red + r=255 + g=0 + b=$(echo "scale=0; 255*(1-$fractional)" | bc) + ;; + esac + + # Ensure values are integers + r=${r%.*} + g=${g%.*} + b=${b%.*} + + # Ensure values are not negative or exceed 255 + r=$(( r < 0 ? 0 : r > 255 ? 255 : r )) + g=$(( g < 0 ? 0 : g > 255 ? 255 : g )) + b=$(( b < 0 ? 0 : b > 255 ? 255 : b )) + + echo "$r $g $b" + } + + # Main rainbow effect loop + # Loop several times to create a continuous effect + for ((cycle=0; cycle/storage/.config/profile.d/001-device_config +# Device Features +DEVICE_HAS_TOUCHSCREEN="true" +DEVICE_NO_MAC="true" +DEVICE_MANGOHUD_SUPPORT="true" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8550/002-audio_path b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/002-audio_path new file mode 100644 index 0000000000..567efcfbf9 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/002-audio_path @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/002-audio_path +DEVICE_PLAYBACK_PATH_SPK="Speakers" +DEVICE_PLAYBACK_PATH_HP="HP" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8550/005-thermal_path b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/005-thermal_path new file mode 100644 index 0000000000..8a897fe4e8 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/005-thermal_path @@ -0,0 +1,7 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/005-thermal_path +DEVICE_TEMP_SENSOR=("/sys/devices/virtual/thermal/thermal_zone3/temp") +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8550/010-governors b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/010-governors new file mode 100644 index 0000000000..c197729c35 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/010-governors @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/010-governors +CPU_FREQ=("/sys/devices/system/cpu/cpufreq/policy0" "/sys/devices/system/cpu/cpufreq/policy4" "/sys/devices/system/cpu/cpufreq/policy7") +GPU_FREQ=("/sys/devices/platform/soc@0/3d00000.gpu/devfreq/3d00000.gpu") +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8550/020-fan_control b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/020-fan_control new file mode 100755 index 0000000000..a34d268d12 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/020-fan_control @@ -0,0 +1,6 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +# fan is controlled by kernel +rm -f /storage/.config/profile.d/020-fan_control diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8550/030-analog_leds b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/030-analog_leds new file mode 100755 index 0000000000..786cf5eff3 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/030-analog_leds @@ -0,0 +1,13 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile.d/001-functions + +if [ $DEVICE_ANALOG_STICKS_LED_CONTROL == "true" ]; then + LEDS_CONFIG=$(get_setting analogsticks.led) + + if [ ! -z "${LEDS_CONFIG}" ]; then + /usr/bin/analog_sticks_ledcontrol $LEDS_CONFIG + fi +fi diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8550/030-led-control b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/030-led-control new file mode 100644 index 0000000000..c9494ba1bf --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/030-led-control @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/010-led_control +DEVICE_LED_CONTROL="true" +DEVICE_BATTERY_LED_STATUS="true" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8550/030-suspend_mode b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/030-suspend_mode new file mode 100755 index 0000000000..4f773ea554 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/030-suspend_mode @@ -0,0 +1,14 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +### Sleep is currently broken, so we'll disable it. + +/usr/bin/suspendmode off + +### Ignore power button presses for now, until we can finish up fixing sleep. +cat <~/.config/logind.conf.d/login.conf +[Login] +HandlePowerKey=ignore +HandleSuspendKey=ignore +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8550/040-affinity b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/040-affinity new file mode 100755 index 0000000000..45851cfebe --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/040-affinity @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/040-affinity +SLOW_CORES="taskset -c 0-3" +FAST_CORES="taskset -c 4-7" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8550/060-game_settings b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/060-game_settings new file mode 100755 index 0000000000..595cac4d55 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/060-game_settings @@ -0,0 +1,43 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile.d/001-functions + +### Set the default performance scaling mode for a few systems. +for SYSTEM in saturn ps2 gamecube wii 3ds ps3 xbox +do + CPU_SETTING=$(get_setting ${SYSTEM}.cpugovernor) + if [ -z "${CPU_SETTING}" ] + then + set_setting ${SYSTEM}.cpugovernor performance + fi + GPU_SETTING=$(get_setting ${SYSTEM}.gpuperf) + if [ -z "${GPU_SETTING}" ] + then + set_setting ${SYSTEM}.gpuperf profile_peak + fi +done + +for SYSTEM in saturn st-v +do + CORES=$(get_setting ${SYSTEM}.cores) + if [ -z "${CORES}" ] + then + set_setting ${SYSTEM}.cores big + fi +done + +for SYSTEM in gb gbc gba nes sms gamegear genesis mastersystem sega32x megadrive segacd megacd +do + CPU_SETTING=$(get_setting ${SYSTEM}.cpugovernor) + if [ -z ${CPU_SETTING} ] + then + set_setting ${SYSTEM}.cpugovernor powersave + fi + GPU_SETTING=$(get_setting ${SYSTEM}.gpuperf) + if [ -z ${GPU_SETTING} ] + then + set_setting ${SYSTEM}.gpuperf low + fi +done diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8550/061-yabasanshiro_config b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/061-yabasanshiro_config new file mode 100644 index 0000000000..c16d7d17ae --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/061-yabasanshiro_config @@ -0,0 +1,26 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +DEVICE_NAME="AYN Odin2 Gamepad" +CONFIG_DIR="/storage/.config/yabasanshiro" +CONFIG_FILE="input.cfg" + +if [ ! -d "${CONFIG_DIR}" ] +then + mkdir -p "${CONFIG_DIR}" +fi + +if [ ! -e "${CONFIG_DIR}/${CONFIG_FILE}" ]; then + GAMEPADCONFIG=$(xmlstarlet sel -t -c "//inputList/inputConfig[@deviceName='${DEVICE_NAME}']" -n /storage/.emulationstation/es_input.cfg) + + if [ ! -z "${GAMEPADCONFIG}" ]; then + cat <${CONFIG_DIR}/${CONFIG_FILE} + + +${GAMEPADCONFIG} + +EOF + fi +fi diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8550/065-Touchscreen-events b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/065-Touchscreen-events new file mode 100644 index 0000000000..2c43fc027b --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/065-Touchscreen-events @@ -0,0 +1,12 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025 ArchR (https://github.com/archr-linux/Arch-R) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +TOUCHSCREEN_EVENTS=$(get_setting key.touchscreen.events) +if [ -z "${TOUCHSCREEN_EVENTS}" ] +then + set_setting key.touchscreen.events 1 +fi diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8550/070-modifiers b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/070-modifiers new file mode 100644 index 0000000000..adf2be4df1 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/070-modifiers @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/050-modifiers +DEVICE_FUNC_KEYA_MODIFIER="BTN_MODE" +DEVICE_FUNC_KEYB_MODIFIER="BTN_START" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8550/075-mangohud-supported b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/075-mangohud-supported new file mode 100644 index 0000000000..a7ab35d25b --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/075-mangohud-supported @@ -0,0 +1,13 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025 ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile + +# Enable MangoHud support +MANGOHUD_ENABLED=$(get_setting "archr.mangohud.enabled") +if [ ! -n "${MANGOHUD_ENABLED}" ]; then + MANGOHUD_ENABLED="0" + set_setting "archr.mangohud.enabled" "${MANGOHUD_ENABLED}" +fi diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8550/090-ui_service b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/090-ui_service new file mode 100755 index 0000000000..4ae841806e --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/090-ui_service @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +### Set the default device configuration +cat </storage/.config/profile.d/090-ui_service +UI_SERVICE="sway.service essway.service" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8550/091-ui_shader b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/091-ui_shader new file mode 100755 index 0000000000..0b1a8b79d9 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/091-ui_shader @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +### Set the default device configuration +cat </storage/.config/profile.d/091-ui_shader +UI_SHADER="slangp" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8550/500-enable-led b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/500-enable-led new file mode 100755 index 0000000000..1c2c659550 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/500-enable-led @@ -0,0 +1,17 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +# Get Internal LED State +LED_STATE=$(get_setting "led.color") +if [ ! -n "${LED_STATE}" ]; then + LED_STATE="battery" + set_setting "led.color" "battery" +fi + +# Run LED control at boot +/usr/bin/ledcontrol ${LED_STATE} diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8550/bin/gpu_overclock b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/bin/gpu_overclock new file mode 100755 index 0000000000..d3916232d5 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/bin/gpu_overclock @@ -0,0 +1,22 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +if [ -z "${GPU_FREQ}" ]; then + . /etc/profile +fi + +# Set max gpu freq +case $1 in + disable) + echo 680000000 > $GPU_FREQ/max_freq + set_setting enable.gpu-overclock 0 + ;; + enable) + echo 1000000000 > $GPU_FREQ/max_freq + set_setting enable.gpu-overclock 1 + ;; +esac diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8550/sleep.d/post/001-led b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/sleep.d/post/001-led new file mode 100644 index 0000000000..62d88f2412 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/sleep.d/post/001-led @@ -0,0 +1,17 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ROCNIX (https://github.com/archr-linux/Arch-R) + +# Restore LED state that was saved prior to device sleep + +. /etc/profile + +### Get the current LED state and store it +SLEEP_LED_STATE=$(get_setting "sleep.led.color") +if [ ! -n "${SLEEP_LED_STATE}" ]; then + SLEEP_LED_STATE="battery" + set_setting "sleep.led.color" "battery" +fi + +### Turn on LEDS +/usr/bin/ledcontrol ${SLEEP_LED_STATE} diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8550/sleep.d/post/002-freq b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/sleep.d/post/002-freq new file mode 100644 index 0000000000..3d94601970 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/sleep.d/post/002-freq @@ -0,0 +1,22 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +### Restore previous governors before going to sleep + +. /etc/profile + +### Grab the old governors. +OLD_CPU_FREQ=$(get_setting "sleep.cpugovernor") +if [ ! -n "${OLD_CPU_FREQ}" ]; then + OLD_CPU_FREQ="schedutil" +fi + +OLD_GPU_FREQ=$(get_setting "sleep.gpugovernor") +if [ ! -n "${OLD_GPU_FREQ}" ]; then + OLD_GPU_FREQ="simple_ondemand" +fi + +# Restore old governors. +set_cpu_gov "${OLD_CPU_FREQ}" +set_gpu_gov "${OLD_GPU_FREQ}" diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8550/sleep.d/pre/001-led b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/sleep.d/pre/001-led new file mode 100644 index 0000000000..71c9878f7e --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/sleep.d/pre/001-led @@ -0,0 +1,19 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ROCNIX (https://github.com/archr-linux/Arch-R) + +# Store current LED state and turn of LEDS as they prevent the device from sleeping while on + +. /etc/profile + +### Get the current LED state and store it +PRE_SLEEP_LED_STATE=$(get_setting "led.color") +if [ ! -n "${PRE_SLEEP_LED_STATE}" ]; then + PRE_SLEEP_LED_STATE="battery" + set_setting "led.color" "battery" +fi + +set_setting sleep.led.color "${PRE_SLEEP_LED_STATE}" + +### Turn off LEDS +/usr/bin/ledcontrol "off" diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8550/sleep.d/pre/002-freq b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/sleep.d/pre/002-freq new file mode 100644 index 0000000000..6d0fc291dc --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8550/sleep.d/pre/002-freq @@ -0,0 +1,18 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +# Store current freq governors and set governors to powersave. + +. /etc/profile + +### Get the current cpu and gpu governor, save for when the device wakes from sleep. +CUR_CPU_FREQ="$(cat ${CPU_FREQ}/scaling_governor)" +CUR_GPU_FREQ="$(cat ${GPU_FREQ}/governor)" + +set_setting sleep.cpugovernor "${CUR_CPU_FREQ}" +set_setting sleep.gpugovernor "${CUR_GPU_FREQ}" + +### Set all governors to powersave +set_cpu_gov powersave +set_gpu_gov powersave diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8650/001-device_config b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/001-device_config new file mode 100644 index 0000000000..aa0f140b77 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/001-device_config @@ -0,0 +1,10 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/001-device_config +# Device Features +DEVICE_HAS_TOUCHSCREEN="true" +DEVICE_NO_MAC="true" +DEVICE_MANGOHUD_SUPPORT="true" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8650/002-audio_path b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/002-audio_path new file mode 100644 index 0000000000..567efcfbf9 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/002-audio_path @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/002-audio_path +DEVICE_PLAYBACK_PATH_SPK="Speakers" +DEVICE_PLAYBACK_PATH_HP="HP" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8650/005-thermal_path b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/005-thermal_path new file mode 100644 index 0000000000..8a897fe4e8 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/005-thermal_path @@ -0,0 +1,7 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/005-thermal_path +DEVICE_TEMP_SENSOR=("/sys/devices/virtual/thermal/thermal_zone3/temp") +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8650/010-governors b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/010-governors new file mode 100644 index 0000000000..9ec6d19c9f --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/010-governors @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/010-governors +CPU_FREQ=("/sys/devices/system/cpu/cpufreq/policy0" "/sys/devices/system/cpu/cpufreq/policy2" "/sys/devices/system/cpu/cpufreq/policy5" "/sys/devices/system/cpu/cpufreq/policy7") +GPU_FREQ=("/sys/devices/platform/soc@0/3d00000.gpu/devfreq/3d00000.gpu") +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8650/030-analog_leds b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/030-analog_leds new file mode 100755 index 0000000000..786cf5eff3 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/030-analog_leds @@ -0,0 +1,13 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile.d/001-functions + +if [ $DEVICE_ANALOG_STICKS_LED_CONTROL == "true" ]; then + LEDS_CONFIG=$(get_setting analogsticks.led) + + if [ ! -z "${LEDS_CONFIG}" ]; then + /usr/bin/analog_sticks_ledcontrol $LEDS_CONFIG + fi +fi diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8650/030-led-control b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/030-led-control new file mode 100644 index 0000000000..c9494ba1bf --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/030-led-control @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/010-led_control +DEVICE_LED_CONTROL="true" +DEVICE_BATTERY_LED_STATUS="true" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8650/030-suspend_mode b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/030-suspend_mode new file mode 100755 index 0000000000..4f773ea554 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/030-suspend_mode @@ -0,0 +1,14 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +### Sleep is currently broken, so we'll disable it. + +/usr/bin/suspendmode off + +### Ignore power button presses for now, until we can finish up fixing sleep. +cat <~/.config/logind.conf.d/login.conf +[Login] +HandlePowerKey=ignore +HandleSuspendKey=ignore +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8650/040-affinity b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/040-affinity new file mode 100755 index 0000000000..2c563f030f --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/040-affinity @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/040-affinity +SLOW_CORES="taskset -c 0-4" +FAST_CORES="taskset -c 5-7" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8650/050-retroarch-configs b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/050-retroarch-configs new file mode 100755 index 0000000000..909e82fcab --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/050-retroarch-configs @@ -0,0 +1,7 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +#Disable retroarch microphone and set default audio driver to pulse +sed -i '/^microphone_enable =/c\microphone_enable = "false"' /storage/.config/retroarch/retroarch.cfg +sed -i '/^audio_driver =/c\audio_driver = "pulse"' /storage/.config/retroarch/retroarch.cfg diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8650/060-game_settings b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/060-game_settings new file mode 100755 index 0000000000..595cac4d55 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/060-game_settings @@ -0,0 +1,43 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile.d/001-functions + +### Set the default performance scaling mode for a few systems. +for SYSTEM in saturn ps2 gamecube wii 3ds ps3 xbox +do + CPU_SETTING=$(get_setting ${SYSTEM}.cpugovernor) + if [ -z "${CPU_SETTING}" ] + then + set_setting ${SYSTEM}.cpugovernor performance + fi + GPU_SETTING=$(get_setting ${SYSTEM}.gpuperf) + if [ -z "${GPU_SETTING}" ] + then + set_setting ${SYSTEM}.gpuperf profile_peak + fi +done + +for SYSTEM in saturn st-v +do + CORES=$(get_setting ${SYSTEM}.cores) + if [ -z "${CORES}" ] + then + set_setting ${SYSTEM}.cores big + fi +done + +for SYSTEM in gb gbc gba nes sms gamegear genesis mastersystem sega32x megadrive segacd megacd +do + CPU_SETTING=$(get_setting ${SYSTEM}.cpugovernor) + if [ -z ${CPU_SETTING} ] + then + set_setting ${SYSTEM}.cpugovernor powersave + fi + GPU_SETTING=$(get_setting ${SYSTEM}.gpuperf) + if [ -z ${GPU_SETTING} ] + then + set_setting ${SYSTEM}.gpuperf low + fi +done diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8650/061-yabasanshiro_config b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/061-yabasanshiro_config new file mode 100644 index 0000000000..c16d7d17ae --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/061-yabasanshiro_config @@ -0,0 +1,26 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +DEVICE_NAME="AYN Odin2 Gamepad" +CONFIG_DIR="/storage/.config/yabasanshiro" +CONFIG_FILE="input.cfg" + +if [ ! -d "${CONFIG_DIR}" ] +then + mkdir -p "${CONFIG_DIR}" +fi + +if [ ! -e "${CONFIG_DIR}/${CONFIG_FILE}" ]; then + GAMEPADCONFIG=$(xmlstarlet sel -t -c "//inputList/inputConfig[@deviceName='${DEVICE_NAME}']" -n /storage/.emulationstation/es_input.cfg) + + if [ ! -z "${GAMEPADCONFIG}" ]; then + cat <${CONFIG_DIR}/${CONFIG_FILE} + + +${GAMEPADCONFIG} + +EOF + fi +fi diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8650/065-Touchscreen-events b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/065-Touchscreen-events new file mode 100644 index 0000000000..2c43fc027b --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/065-Touchscreen-events @@ -0,0 +1,12 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025 ArchR (https://github.com/archr-linux/Arch-R) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +TOUCHSCREEN_EVENTS=$(get_setting key.touchscreen.events) +if [ -z "${TOUCHSCREEN_EVENTS}" ] +then + set_setting key.touchscreen.events 1 +fi diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8650/070-modifiers b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/070-modifiers new file mode 100644 index 0000000000..adf2be4df1 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/070-modifiers @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +cat </storage/.config/profile.d/050-modifiers +DEVICE_FUNC_KEYA_MODIFIER="BTN_MODE" +DEVICE_FUNC_KEYB_MODIFIER="BTN_START" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8650/075-mangohud-supported b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/075-mangohud-supported new file mode 100644 index 0000000000..a7ab35d25b --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/075-mangohud-supported @@ -0,0 +1,13 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025 ArchR (https://github.com/archr-linux/Arch-R) + +. /etc/profile + +# Enable MangoHud support +MANGOHUD_ENABLED=$(get_setting "archr.mangohud.enabled") +if [ ! -n "${MANGOHUD_ENABLED}" ]; then + MANGOHUD_ENABLED="0" + set_setting "archr.mangohud.enabled" "${MANGOHUD_ENABLED}" +fi diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8650/090-ui_service b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/090-ui_service new file mode 100755 index 0000000000..4ae841806e --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/090-ui_service @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +### Set the default device configuration +cat </storage/.config/profile.d/090-ui_service +UI_SERVICE="sway.service essway.service" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8650/091-ui_shader b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/091-ui_shader new file mode 100755 index 0000000000..0b1a8b79d9 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/091-ui_shader @@ -0,0 +1,8 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +### Set the default device configuration +cat </storage/.config/profile.d/091-ui_shader +UI_SHADER="slangp" +EOF diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8650/500-enable-led b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/500-enable-led new file mode 100755 index 0000000000..1c2c659550 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/500-enable-led @@ -0,0 +1,17 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +# Get Internal LED State +LED_STATE=$(get_setting "led.color") +if [ ! -n "${LED_STATE}" ]; then + LED_STATE="battery" + set_setting "led.color" "battery" +fi + +# Run LED control at boot +/usr/bin/ledcontrol ${LED_STATE} diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8650/bin/gpu_overclock b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/bin/gpu_overclock new file mode 100755 index 0000000000..cbbe4ae9f1 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/bin/gpu_overclock @@ -0,0 +1,22 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +# Minimal OS variable loading for performance +. /etc/profile.d/001-functions + +if [ -z "${GPU_FREQ}" ]; then + . /etc/profile +fi + +# Set max gpu freq +case $1 in + disable) + echo 834000000 > $GPU_FREQ/max_freq + set_setting enable.gpu-overclock 0 + ;; + enable) + echo 1050000000 > $GPU_FREQ/max_freq + set_setting enable.gpu-overclock 1 + ;; +esac diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8650/sleep.d/post/001-led b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/sleep.d/post/001-led new file mode 100644 index 0000000000..62d88f2412 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/sleep.d/post/001-led @@ -0,0 +1,17 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ROCNIX (https://github.com/archr-linux/Arch-R) + +# Restore LED state that was saved prior to device sleep + +. /etc/profile + +### Get the current LED state and store it +SLEEP_LED_STATE=$(get_setting "sleep.led.color") +if [ ! -n "${SLEEP_LED_STATE}" ]; then + SLEEP_LED_STATE="battery" + set_setting "sleep.led.color" "battery" +fi + +### Turn on LEDS +/usr/bin/ledcontrol ${SLEEP_LED_STATE} diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8650/sleep.d/post/002-freq b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/sleep.d/post/002-freq new file mode 100644 index 0000000000..3d94601970 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/sleep.d/post/002-freq @@ -0,0 +1,22 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +### Restore previous governors before going to sleep + +. /etc/profile + +### Grab the old governors. +OLD_CPU_FREQ=$(get_setting "sleep.cpugovernor") +if [ ! -n "${OLD_CPU_FREQ}" ]; then + OLD_CPU_FREQ="schedutil" +fi + +OLD_GPU_FREQ=$(get_setting "sleep.gpugovernor") +if [ ! -n "${OLD_GPU_FREQ}" ]; then + OLD_GPU_FREQ="simple_ondemand" +fi + +# Restore old governors. +set_cpu_gov "${OLD_CPU_FREQ}" +set_gpu_gov "${OLD_GPU_FREQ}" diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8650/sleep.d/pre/001-led b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/sleep.d/pre/001-led new file mode 100644 index 0000000000..71c9878f7e --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/sleep.d/pre/001-led @@ -0,0 +1,19 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ROCNIX (https://github.com/archr-linux/Arch-R) + +# Store current LED state and turn of LEDS as they prevent the device from sleeping while on + +. /etc/profile + +### Get the current LED state and store it +PRE_SLEEP_LED_STATE=$(get_setting "led.color") +if [ ! -n "${PRE_SLEEP_LED_STATE}" ]; then + PRE_SLEEP_LED_STATE="battery" + set_setting "led.color" "battery" +fi + +set_setting sleep.led.color "${PRE_SLEEP_LED_STATE}" + +### Turn off LEDS +/usr/bin/ledcontrol "off" diff --git a/projects/ArchR/packages/hardware/quirks/platforms/SM8650/sleep.d/pre/002-freq b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/sleep.d/pre/002-freq new file mode 100644 index 0000000000..6d0fc291dc --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/platforms/SM8650/sleep.d/pre/002-freq @@ -0,0 +1,18 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +# Store current freq governors and set governors to powersave. + +. /etc/profile + +### Get the current cpu and gpu governor, save for when the device wakes from sleep. +CUR_CPU_FREQ="$(cat ${CPU_FREQ}/scaling_governor)" +CUR_GPU_FREQ="$(cat ${GPU_FREQ}/governor)" + +set_setting sleep.cpugovernor "${CUR_CPU_FREQ}" +set_setting sleep.gpugovernor "${CUR_GPU_FREQ}" + +### Set all governors to powersave +set_cpu_gov powersave +set_gpu_gov powersave diff --git a/projects/ArchR/packages/hardware/quirks/profile.d/041-panfrost b/projects/ArchR/packages/hardware/quirks/profile.d/041-panfrost new file mode 100644 index 0000000000..1c64c4abd3 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/profile.d/041-panfrost @@ -0,0 +1,20 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +# Panfrost / Mali-G31 (Bifrost) tuning. Sourced by /etc/profile so the vars +# reach login shells AND every emulator launched from runemu.sh / start_*.sh +# (which both do `. /etc/profile`). Previously these lived in a quirks/ +# autostart subshell that exited immediately, so the shader cache and Mesa +# error-skip flags never reached emulator processes. + +# forcepack: pack vertex attributes; reduces draw call overhead on G31. +export PAN_MESA_DEBUG=forcepack + +# Skip GL error checking — emulators don't query glGetError defensively. +export MESA_NO_ERROR=1 + +# Persistent shader cache on /storage to survive reboots and avoid +# recompilation every launch. Mesa creates the dir on first write. +export MESA_SHADER_CACHE_DIR=/storage/.cache/mesa_shader_cache +export MESA_SHADER_CACHE_MAX_SIZE=128MB diff --git a/projects/ArchR/packages/hardware/quirks/profile.d/999-export b/projects/ArchR/packages/hardware/quirks/profile.d/999-export new file mode 100755 index 0000000000..73a807f0a4 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/profile.d/999-export @@ -0,0 +1,65 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +### If you add a variable that should persist across processes, +### remember to export it here. + +export OS_VERSION \ + OS_BUILD \ + SLOW_CORES \ + FAST_CORES \ + CPU_FREQ \ + DMC_FREQ \ + GPU_FREQ \ + HW_DEVICE\ + DEVICE_ASPECT_RATIO \ + DEVICE_AUDIO_MIXER \ + DEVICE_BATTERY_LED_STATUS \ + DEVICE_DTB_SWITCH \ + DEVICE_FAKE_JACKSENSE \ + DEVICE_FUNC_KEYA_MODIFIER \ + DEVICE_FUNC_KEYB_MODIFIER \ + DEVICE_HAS_FAN \ + DEVICE_GPU_OVERCLOCK \ + DEVICE_GPU_TEMP_SENSOR \ + DEVICE_HAS_HDMI \ + DEVICE_HAS_TOUCHSCREEN \ + DEVICE_HDMI_GPIO \ + DEVICE_HAS_DUAL_SCREEN \ + DEVICE_HEADPHONE_DEV \ + DEVICE_JACK \ + DEVICE_KEY_VOLUMEDOWN \ + DEVICE_KEY_VOLUMEUP \ + DEVICE_LED_BRIGHTNESS \ + DEVICE_LED_CHARGING \ + DEVICE_LED_CONTROL \ + DEVICE_ANALOG_STICKS_LED_CONTROL \ + DEVICE_MANGOHUD_SUPPORT \ + DEVICE_MMC_EJECT \ + DEVICE_PIPEWIRE_PROFILE \ + DEVICE_PWR_LED_CONTROL \ + DEVICE_PWR_LED_GPIO \ + DEVICE_PLAYBACK_PATH \ + DEVICE_PLAYBACK_PATH_HP \ + DEVICE_PLAYBACK_PATH_SPK \ + DEVICE_PWM_FAN \ + DEVICE_PWM_MOTOR \ + DEVICE_SERIAL_NUMBER_PATH \ + DEVICE_SW_HP_SWITCH \ + DEVICE_TEMP_SENSOR \ + DEVICE_TURBO_MODE \ + DEVICE_VOLUME \ + DEVICE_WIFI \ + HDMI_STATE \ + QUIRK_DEVICE \ + UI_SERVICE \ + PAN_MESA_DEBUG \ + MESA_NO_ERROR \ + MESA_SHADER_CACHE_DIR \ + MESA_SHADER_CACHE_MAX_SIZE \ + WLR_DRM_DEVICES \ + WLR_BACKENDS \ + WLR_CON \ + MALI_WAYLAND_AFBC \ + ALSA_PRIMARY_CARD diff --git a/projects/ArchR/packages/hardware/quirks/system.d/led-poweroff.service b/projects/ArchR/packages/hardware/quirks/system.d/led-poweroff.service new file mode 100644 index 0000000000..e32d6c84e1 --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/system.d/led-poweroff.service @@ -0,0 +1,12 @@ +[Unit] +Description=Power LEDs off before shutting down. +After=multi-user.target + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/bin/true +ExecStop=/usr/bin/ledcontrol poweroff + +[Install] +WantedBy=multi-user.target diff --git a/projects/ArchR/packages/hardware/quirks/system.d/volume-fixup.service b/projects/ArchR/packages/hardware/quirks/system.d/volume-fixup.service new file mode 100644 index 0000000000..d948dfc43a --- /dev/null +++ b/projects/ArchR/packages/hardware/quirks/system.d/volume-fixup.service @@ -0,0 +1,12 @@ +[Unit] +Description=Fix unset volumes on RK3566 devices +After=archr.target +Before=essway.service + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/usr/lib/autostart/quirks/platforms/RK3566/bin/volumealign + +[Install] +WantedBy=archr.target diff --git a/projects/ArchR/packages/kernel-drivers/device-tree-overlays/package.mk b/projects/ArchR/packages/kernel-drivers/device-tree-overlays/package.mk new file mode 100644 index 0000000000..77718bf4a9 --- /dev/null +++ b/projects/ArchR/packages/kernel-drivers/device-tree-overlays/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="device-tree-overlays" +PKG_LICENSE="GPL2" +PKG_LONGDESC="device-tree-overlays: ArchR linux device tree overlays" +PKG_TOOLCHAIN="manual" +PKG_IS_KERNEL_PKG="yes" + +make_target() { + for dts in ${PKG_BUILD}/${DEVICE}/*.dts; do + $(kernel_path)/scripts/dtc/dtc -@ -I dts -O dtb -o ${dts%.dts}.dtbo ${dts} + done +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/share/bootloader/overlays + cp ${PKG_BUILD}/${DEVICE}/*.dtbo ${INSTALL}/usr/share/bootloader/overlays + + if [ ${DEVICE} != "RK3326" ]; then + mkdir -p ${INSTALL}/usr/bin + cp ${PKG_BUILD}/dtb_overlay ${INSTALL}/usr/bin + fi +} diff --git a/projects/ArchR/packages/kernel-drivers/device-tree-overlays/sources/RK3566/rk3566-undervolt-cpu-l1.dts b/projects/ArchR/packages/kernel-drivers/device-tree-overlays/sources/RK3566/rk3566-undervolt-cpu-l1.dts new file mode 100644 index 0000000000..0c5c504ee5 --- /dev/null +++ b/projects/ArchR/packages/kernel-drivers/device-tree-overlays/sources/RK3566/rk3566-undervolt-cpu-l1.dts @@ -0,0 +1,35 @@ +/dts-v1/; +/plugin/; + +/ { +fragment@0 { +//target = <&cpu0_opp_table>; + target-path = "/opp-table-0"; +__overlay__ { +opp-408000000 { +opp-microvolt = <800000 800000 1150000>; +}; +opp-600000000 { +opp-microvolt = <800000 800000 1150000>; +}; +opp-816000000 { +opp-microvolt = <800000 800000 1150000>; +}; +opp-1104000000 { +opp-microvolt = <800000 800000 1150000>; +}; +opp-1416000000 { +opp-microvolt = <850000 850000 1150000>; +}; +opp-1608000000 { +opp-microvolt = <900000 900000 1150000>; +}; +opp-1800000000 { +opp-microvolt = <950000 950000 1150000>; +}; +opp-1992000000 { +opp-microvolt = <1000000 1000000 1150000>; +}; +}; +}; +}; diff --git a/projects/ArchR/packages/kernel-drivers/device-tree-overlays/sources/RK3566/rk3566-undervolt-cpu-l2.dts b/projects/ArchR/packages/kernel-drivers/device-tree-overlays/sources/RK3566/rk3566-undervolt-cpu-l2.dts new file mode 100644 index 0000000000..60036cedee --- /dev/null +++ b/projects/ArchR/packages/kernel-drivers/device-tree-overlays/sources/RK3566/rk3566-undervolt-cpu-l2.dts @@ -0,0 +1,35 @@ +/dts-v1/; +/plugin/; + +/ { +fragment@0 { +//target = <&cpu0_opp_table>; + target-path = "/opp-table-0"; +__overlay__ { +opp-408000000 { +opp-microvolt = <775000 775000 1150000>; +}; +opp-600000000 { +opp-microvolt = <800000 800000 1150000>; +}; +opp-816000000 { +opp-microvolt = <800000 800000 1150000>; +}; +opp-1104000000 { +opp-microvolt = <800000 800000 1150000>; +}; +opp-1416000000 { +opp-microvolt = <850000 850000 1150000>; +}; +opp-1608000000 { +opp-microvolt = <900000 900000 1150000>; +}; +opp-1800000000 { +opp-microvolt = <925000 925000 1150000>; +}; +opp-1992000000 { +opp-microvolt = <950000 950000 1150000>; +}; +}; +}; +}; diff --git a/projects/ArchR/packages/kernel-drivers/device-tree-overlays/sources/RK3566/rk3566-undervolt-cpu-l3.dts b/projects/ArchR/packages/kernel-drivers/device-tree-overlays/sources/RK3566/rk3566-undervolt-cpu-l3.dts new file mode 100644 index 0000000000..2fb176bfbf --- /dev/null +++ b/projects/ArchR/packages/kernel-drivers/device-tree-overlays/sources/RK3566/rk3566-undervolt-cpu-l3.dts @@ -0,0 +1,35 @@ +/dts-v1/; +/plugin/; + +/ { +fragment@0 { +//target = <&cpu0_opp_table>; + target-path = "/opp-table-0"; +__overlay__ { +opp-408000000 { +opp-microvolt = <760000 760000 1150000>; +}; +opp-600000000 { +opp-microvolt = <775000 775000 1150000>; +}; +opp-816000000 { +opp-microvolt = <790000 790000 1150000>; +}; +opp-1104000000 { +opp-microvolt = <800000 800000 1150000>; +}; +opp-1416000000 { +opp-microvolt = <825000 825000 1150000>; +}; +opp-1608000000 { +opp-microvolt = <850000 850000 1150000>; +}; +opp-1800000000 { +opp-microvolt = <875000 875000 1150000>; +}; +opp-1992000000 { +opp-microvolt = <900000 900000 1150000>; +}; +}; +}; +}; diff --git a/projects/ArchR/packages/kernel-drivers/device-tree-overlays/sources/RK3588/driver-gpu-panthor.dts b/projects/ArchR/packages/kernel-drivers/device-tree-overlays/sources/RK3588/driver-gpu-panthor.dts new file mode 100644 index 0000000000..2da62dbb4a --- /dev/null +++ b/projects/ArchR/packages/kernel-drivers/device-tree-overlays/sources/RK3588/driver-gpu-panthor.dts @@ -0,0 +1,19 @@ +/dts-v1/; +/plugin/; + +/ { + fragment@0 { + target = <&gpu>; + __overlay__ { + status = "disabled"; + }; + }; + + fragment@1 { + target = <&gpu_panthor>; + __overlay__ { + status = "okay"; + mali-supply = <&vdd_gpu_s0>; + }; + }; +}; diff --git a/projects/ArchR/packages/kernel-drivers/device-tree-overlays/sources/S922X/driver-gpu-panfrost.dts b/projects/ArchR/packages/kernel-drivers/device-tree-overlays/sources/S922X/driver-gpu-panfrost.dts new file mode 100644 index 0000000000..1bc4b9c0fc --- /dev/null +++ b/projects/ArchR/packages/kernel-drivers/device-tree-overlays/sources/S922X/driver-gpu-panfrost.dts @@ -0,0 +1,18 @@ +/dts-v1/; +/plugin/; + +/ { + fragment@0 { + target = <&mali>; + __overlay__ { + status = "okay"; + }; + }; + + fragment@1 { + target = <&mali_vulkan>; + __overlay__ { + status = "disabled"; + }; + }; +}; diff --git a/projects/ArchR/packages/kernel-drivers/device-tree-overlays/sources/S922X/gpu-underclock.dts b/projects/ArchR/packages/kernel-drivers/device-tree-overlays/sources/S922X/gpu-underclock.dts new file mode 100644 index 0000000000..2b5ed1b33f --- /dev/null +++ b/projects/ArchR/packages/kernel-drivers/device-tree-overlays/sources/S922X/gpu-underclock.dts @@ -0,0 +1,14 @@ +/dts-v1/; +/plugin/; + +/ { + fragment@0 { + target = <&gpu_opp_table>; + __overlay__ { + // Disable 800 Mhz frequency + opp-799999987 { + status = "disabled"; + }; + }; + }; +}; diff --git a/projects/ArchR/packages/kernel-drivers/device-tree-overlays/sources/dtb_overlay b/projects/ArchR/packages/kernel-drivers/device-tree-overlays/sources/dtb_overlay new file mode 100755 index 0000000000..e0738c0e7b --- /dev/null +++ b/projects/ArchR/packages/kernel-drivers/device-tree-overlays/sources/dtb_overlay @@ -0,0 +1,163 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) +. /etc/profile.d/001-functions +SPECIALIZATIONS="undervolt-cpu undervolt-gpu driver-gpu" + +check_valid_specialization() { + for spec in $SPECIALIZATIONS; do + if [ "$spec" = "${1}" ]; then + return + fi + done + echo "Unknown specialization: ${1}" + echo "Valid specializations are: ${SPECIALIZATIONS}" + exit 1 +} + +get_current_custom_overlay() { + fdtoverlaysline=$(grep FDTOVERLAYS /flash/extlinux/extlinux.conf) + overlays=${fdtoverlaysline## FDTOVERLAYS} + for ol in $overlays; do + match=0 + for spec in $SPECIALIZATIONS; do + if [[ $ol == *"$spec"* ]]; then + match=1 + break + fi + done + if [ $match = 0 ]; then + custom=$ol + break + fi + done + if [ $custom ]; then + echo $custom | cut -d '/' -f 3 + else + echo "None" + fi +} + +get_current_specialized_overlay() { + fdtoverlaysline=$(grep FDTOVERLAYS /flash/extlinux/extlinux.conf) + overlays=${fdtoverlaysline## FDTOVERLAYS} + for ol in $overlays; do + if [[ $ol == *"$1"* ]]; then + specialized="${ol} " + break + fi + done + if [ $specialized ]; then + echo $specialized | cut -d '/' -f 3 + else + echo "None" + fi + +} + +list_custom_overlays() { + for ol in /flash/overlays/*.dtbo; do + for spec in $SPECIALIZATIONS; do + if [[ $ol == *"$spec"* ]]; then + ol="" + break + fi + done + if [ $ol ]; then + echo -n $ol | cut -d '/' -f 4 | tr -d '\n' + echo -n " " + fi + done + echo +} + +list_specialized_overlays() { + for ol in /flash/overlays/*.dtbo; do + if [[ $ol == *"$1"* ]]; then + echo -n $ol | cut -d '/' -f 4 | tr -d '\n' + echo -n " " + fi + done + echo +} + +write_dtbo() { + PRE=/overlays/ + for spec in $SPECIALIZATIONS custom_dtbo; do + ol=$(get_setting system.$spec) + if [ "$ol" != "None" ] && [[ ! -z $ol ]]; then + dtbos+="${PRE}${ol} " + fi + done + mount -o remount,rw /flash + if [ "$dtbos" ]; then + if grep --quiet FDTOVERLAYS /flash/extlinux/extlinux.conf; then + sed -i "/FDTOVERLAYS/c \ \ FDTOVERLAYS ${dtbos}" /flash/extlinux/extlinux.conf + else + sed -i "/FDT/a \ \ FDTOVERLAYS ${dtbos}" /flash/extlinux/extlinux.conf + fi + else + sed -i "/FDTOVERLAYS/d" /flash/extlinux/extlinux.conf + fi + mount -o remount,ro /flash +} + +case "$1" in + "ls") + case "$2" in + "custom") + list_custom_overlays + exit 0 + ;; + *) + check_valid_specialization $2 + list_specialized_overlays $2 + exit 0 + ;; + esac + ;; + "get") + case "$2" in + "custom") + get_current_custom_overlay + exit 0 + ;; + *) + check_valid_specialization $2 + get_current_specialized_overlay $2 + exit 0 + ;; + esac + ;; + "set") + case "$2" in + "custom") + for ol in $(list_custom_overlays); do + if [ "$3" = "$ol" ] || [ $3 = None ]; then + set_setting system.custom_dtbo $3 + write_dtbo + exit 0 + fi + done + echo "dtbo doesn't exist: $3" + exit 1 + ;; + *) + check_valid_specialization $2 + for ol in $(list_specialized_overlays $2); do + if [ "$3" = "$ol" ] || [ $3 = None ]; then + set_setting system.$2 $3 + write_dtbo + exit 0 + fi + done + echo "dtbo doesn't exist: $3" + exit 1 + ;; + esac + ;; + *) + echo "Unknown operation: ${1}" + exit 1 + ;; +esac diff --git a/projects/ArchR/packages/lang/gcc-linaro-aarch64-elf/package.mk b/projects/ArchR/packages/lang/gcc-linaro-aarch64-elf/package.mk new file mode 100644 index 0000000000..0e6934356a --- /dev/null +++ b/projects/ArchR/packages/lang/gcc-linaro-aarch64-elf/package.mk @@ -0,0 +1,13 @@ +PKG_NAME="gcc-linaro-aarch64-elf" +PKG_VERSION="4.9.4-2017.01" +PKG_LICENSE="GPL" +PKG_SITE="" +PKG_URL="https://releases.linaro.org/components/toolchain/binaries/4.9-2017.01/aarch64-elf/gcc-linaro-${PKG_VERSION}-x86_64_aarch64-elf.tar.xz" +PKG_DEPENDS_HOST="ccache:host" +PKG_LONGDESC="Linaro Aarch64 GNU Linux Binary Toolchain" +PKG_TOOLCHAIN="manual" + +makeinstall_host() { + mkdir -p $TOOLCHAIN/lib/gcc-linaro-aarch64-elf/ + cp -a * $TOOLCHAIN/lib/gcc-linaro-aarch64-elf +} diff --git a/projects/ArchR/packages/lang/gcc-linaro-arm-eabi/package.mk b/projects/ArchR/packages/lang/gcc-linaro-arm-eabi/package.mk new file mode 100644 index 0000000000..e51bed521a --- /dev/null +++ b/projects/ArchR/packages/lang/gcc-linaro-arm-eabi/package.mk @@ -0,0 +1,13 @@ +PKG_NAME="gcc-linaro-arm-eabi" +PKG_VERSION="4.9.4-2017.01" +PKG_LICENSE="GPL" +PKG_SITE="" +PKG_URL="https://releases.linaro.org/components/toolchain/binaries/4.9-2017.01/arm-eabi/gcc-linaro-${PKG_VERSION}-x86_64_arm-eabi.tar.xz" +PKG_DEPENDS_HOST="ccache:host" +PKG_LONGDESC="Linaro ARM GNU Linux Binary Toolchain" +PKG_TOOLCHAIN="manual" + +makeinstall_host() { + mkdir -p $TOOLCHAIN/lib/gcc-linaro-arm-eabi/ + cp -a * $TOOLCHAIN/lib/gcc-linaro-arm-eabi +} diff --git a/projects/ArchR/packages/lang/gcc/package.mk b/projects/ArchR/packages/lang/gcc/package.mk new file mode 100644 index 0000000000..2060ee480d --- /dev/null +++ b/projects/ArchR/packages/lang/gcc/package.mk @@ -0,0 +1,193 @@ +# 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) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="gcc" +PKG_VERSION="14.2.0" +PKG_LICENSE="GPL-2.0-or-later" +PKG_SITE="https://gcc.gnu.org/" +PKG_URL="https://mirrors.kernel.org/gnu/gcc/${PKG_NAME}-${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" +PKG_DEPENDS_HOST="ccache:host autoconf:host binutils:host gmp:host mpfr:host mpc:host zstd:host glibc libxcrypt" +PKG_DEPENDS_INIT="toolchain" +PKG_LONGDESC="This package contains the GNU Compiler Collection." + +if [ "${MOLD_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_HOST+=" mold:host" +fi + +case ${TARGET_ARCH} in + arm|aarch64|riscv64) + OPTS_LIBATOMIC="--enable-libatomic" + ;; + *) + OPTS_LIBATOMIC="--disable-libatomic" + ;; +esac + +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 \ + --without-ppl \ + --without-cloog \ + --disable-libada \ + --disable-libmudflap \ + --disable-libitm \ + --disable-libquadmath \ + --enable-libgomp \ + --disable-libmpx \ + --disable-libssp \ + --disable-static \ + --enable-shared \ + --disable-werror \ + --enable-__cxa_atexit" + +PKG_CONFIGURE_OPTS_BOOTSTRAP="${GCC_COMMON_CONFIGURE_OPTS} \ + --enable-cloog-backend=isl \ + --disable-decimal-float \ + --disable-gcov \ + --enable-languages=c \ + --disable-libatomic \ + --disable-libgomp \ + --disable-libsanitizer \ + --disable-shared \ + --disable-threads \ + --without-headers \ + --with-newlib \ + ${TARGET_ARCH_GCC_OPTS}" + +PKG_CONFIGURE_OPTS_HOST="${GCC_COMMON_CONFIGURE_OPTS} \ + --enable-languages=c,c++ \ + ${OPTS_LIBATOMIC} \ + --enable-decimal-float \ + --enable-tls \ + --enable-shared \ + --disable-static \ + --enable-long-long \ + --enable-threads=posix \ + --disable-libstdcxx-pch \ + --enable-libstdcxx-time \ + --enable-clocale=gnu \ + ${TARGET_ARCH_GCC_OPTS}" + +post_makeinstall_bootstrap() { + GCC_VERSION=$(${TOOLCHAIN}/bin/${TARGET_NAME}-gcc -dumpversion) + DATE="0401$(echo ${GCC_VERSION} | sed 's/\./0/g')" + CROSS_CC=${TARGET_PREFIX}gcc-${GCC_VERSION} + + rm -f ${TARGET_PREFIX}gcc + +cat > ${TARGET_PREFIX}gcc < ${TARGET_PREFIX}gcc < ${TARGET_PREFIX}g++ < +Date: Fri, 16 Aug 2024 07:53:01 +0100 +Subject: [PATCH] aarch64: Fix invalid nested subregs [PR115464] + +The testcase extracts one arm_neon.h vector from a pair (one subreg) +and then reinterprets the result as an SVE vector (another subreg). +Each subreg makes sense individually, but we can't fold them together +into a single subreg: it's 32 bytes -> 16 bytes -> 16*N bytes, +but the interpretation of 32 bytes -> 16*N bytes depends on +whether N==1 or N>1. + +Since the second subreg makes sense individually, simplify_subreg +should bail out rather than ICE on it. simplify_gen_subreg will +then do the same (because it already checks validate_subreg). +This leaves simplify_gen_subreg returning null, requiring the +caller to take appropriate action. + +I think this is relatively likely to occur elsewhere, so the patch +adds a helper for forcing a subreg, allowing a temporary pseudo to +be created where necessary. + +I'll follow up by using force_subreg in more places. This patch +is intended to be a minimal backportable fix for the PR. + +gcc/ + PR target/115464 + * simplify-rtx.cc (simplify_context::simplify_subreg): Don't try + to fold two subregs together if their relationship isn't known + at compile time. + * explow.h (force_subreg): Declare. + * explow.cc (force_subreg): New function. + * config/aarch64/aarch64-sve-builtins-base.cc + (svset_neonq_impl::expand): Use it instead of simplify_gen_subreg. + +gcc/testsuite/ + PR target/115464 + * gcc.target/aarch64/sve/acle/general/pr115464.c: New test. + +(cherry picked from commit 0970ff46ba6330fc80e8736fc05b2eaeeae0b6a0) +--- + gcc/config/aarch64/aarch64-sve-builtins-base.cc | 2 +- + gcc/explow.cc | 15 +++++++++++++++ + gcc/explow.h | 2 ++ + gcc/simplify-rtx.cc | 5 +++++ + .../aarch64/sve/acle/general/pr115464.c | 13 +++++++++++++ + 5 files changed, 36 insertions(+), 1 deletion(-) + create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr115464.c + +diff --git a/gcc/config/aarch64/aarch64-sve-builtins-base.cc b/gcc/config/aarch64/aarch64-sve-builtins-base.cc +index 0d2edf3f19e..c9182594bc1 100644 +--- a/gcc/config/aarch64/aarch64-sve-builtins-base.cc ++++ b/gcc/config/aarch64/aarch64-sve-builtins-base.cc +@@ -1174,7 +1174,7 @@ public: + Advanced SIMD argument as an SVE vector. */ + if (!BYTES_BIG_ENDIAN + && is_undef (CALL_EXPR_ARG (e.call_expr, 0))) +- return simplify_gen_subreg (mode, e.args[1], GET_MODE (e.args[1]), 0); ++ return force_subreg (mode, e.args[1], GET_MODE (e.args[1]), 0); + + rtx_vector_builder builder (VNx16BImode, 16, 2); + for (unsigned int i = 0; i < 16; i++) +diff --git a/gcc/explow.cc b/gcc/explow.cc +index 8e5f6b8e680..f6843398c4b 100644 +--- a/gcc/explow.cc ++++ b/gcc/explow.cc +@@ -745,6 +745,21 @@ force_reg (machine_mode mode, rtx x) + return temp; + } + ++/* Like simplify_gen_subreg, but force OP into a new register if the ++ subreg cannot be formed directly. */ ++ ++rtx ++force_subreg (machine_mode outermode, rtx op, ++ machine_mode innermode, poly_uint64 byte) ++{ ++ rtx x = simplify_gen_subreg (outermode, op, innermode, byte); ++ if (x) ++ return x; ++ ++ op = copy_to_mode_reg (innermode, op); ++ return simplify_gen_subreg (outermode, op, innermode, byte); ++} ++ + /* If X is a memory ref, copy its contents to a new temp reg and return + that reg. Otherwise, return X. */ + +diff --git a/gcc/explow.h b/gcc/explow.h +index 16aa02cfb68..cbd1fcb7eb3 100644 +--- a/gcc/explow.h ++++ b/gcc/explow.h +@@ -42,6 +42,8 @@ extern rtx copy_to_suggested_reg (rtx, rtx, machine_mode); + Args are mode (in case value is a constant) and the value. */ + extern rtx force_reg (machine_mode, rtx); + ++extern rtx force_subreg (machine_mode, rtx, machine_mode, poly_uint64); ++ + /* Return given rtx, copied into a new temp reg if it was in memory. */ + extern rtx force_not_mem (rtx); + +diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc +index dceaa13333c..729d408aa55 100644 +--- a/gcc/simplify-rtx.cc ++++ b/gcc/simplify-rtx.cc +@@ -7612,6 +7612,11 @@ simplify_context::simplify_subreg (machine_mode outermode, rtx op, + poly_uint64 innermostsize = GET_MODE_SIZE (innermostmode); + rtx newx; + ++ /* Make sure that the relationship between the two subregs is ++ known at compile time. */ ++ if (!ordered_p (outersize, innermostsize)) ++ return NULL_RTX; ++ + if (outermode == innermostmode + && known_eq (byte, 0U) + && known_eq (SUBREG_BYTE (op), 0)) +diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr115464.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr115464.c +new file mode 100644 +index 00000000000..d728d1325ed +--- /dev/null ++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr115464.c +@@ -0,0 +1,13 @@ ++/* { dg-options "-O2" } */ ++ ++#include ++#include ++#include ++ ++svuint16_t ++convolve4_4_x (uint16x8x2_t permute_tbl) ++{ ++ return svset_neonq_u16 (svundef_u16 (), permute_tbl.val[1]); ++} ++ ++/* { dg-final { scan-assembler {\tmov\tz0\.d, z1\.d\n} } } */ +-- +2.43.5 + +From 86dacfb06b90371458d58872f461d358a0834305 Mon Sep 17 00:00:00 2001 +From: Richard Sandiford +Date: Fri, 16 Aug 2024 07:53:02 +0100 +Subject: [PATCH] aarch64: Add another use of force_subreg [PR115464] + +This patch includes the testcase from r15-1399 plus a miminal +fix for it, without the other proactive uses of force_subreg. +We can backport other force_subreg calls later if they're shown +to be needed. + +gcc/ + PR target/115464 + * config/aarch64/aarch64-sve-builtins-base.cc + (svset_neonq_impl::expand): Use force_subreg instead of + lowpart_subreg. + +gcc/testsuite/ + PR target/115464 + * gcc.target/aarch64/sve/acle/general/pr115464_2.c: New test. +--- + gcc/config/aarch64/aarch64-sve-builtins-base.cc | 4 +++- + .../gcc.target/aarch64/sve/acle/general/pr115464_2.c | 11 +++++++++++ + 2 files changed, 14 insertions(+), 1 deletion(-) + create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr115464_2.c + +diff --git a/gcc/config/aarch64/aarch64-sve-builtins-base.cc b/gcc/config/aarch64/aarch64-sve-builtins-base.cc +index c9182594bc1..241a249503f 100644 +--- a/gcc/config/aarch64/aarch64-sve-builtins-base.cc ++++ b/gcc/config/aarch64/aarch64-sve-builtins-base.cc +@@ -1185,7 +1185,9 @@ public: + if (BYTES_BIG_ENDIAN) + return e.use_exact_insn (code_for_aarch64_sve_set_neonq (mode)); + insn_code icode = code_for_vcond_mask (mode, mode); +- e.args[1] = lowpart_subreg (mode, e.args[1], GET_MODE (e.args[1])); ++ e.args[1] = force_subreg (mode, e.args[1], GET_MODE (e.args[1]), ++ subreg_lowpart_offset (mode, ++ GET_MODE (e.args[1]))); + e.add_output_operand (icode); + e.add_input_operand (icode, e.args[1]); + e.add_input_operand (icode, e.args[0]); +diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr115464_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr115464_2.c +new file mode 100644 +index 00000000000..f561c34f732 +--- /dev/null ++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr115464_2.c +@@ -0,0 +1,11 @@ ++/* { dg-options "-O2" } */ ++ ++#include ++#include ++#include ++ ++svuint16_t ++convolve4_4_x (uint16x8x2_t permute_tbl, svuint16_t a) ++{ ++ return svset_neonq_u16 (a, permute_tbl.val[1]); ++} +-- +2.43.5 diff --git a/projects/ArchR/packages/lang/gcc/patches/gcc-crosscompile-badness.patch b/projects/ArchR/packages/lang/gcc/patches/gcc-crosscompile-badness.patch new file mode 100644 index 0000000000..fc01ece219 --- /dev/null +++ b/projects/ArchR/packages/lang/gcc/patches/gcc-crosscompile-badness.patch @@ -0,0 +1,31 @@ +Index: gcc-4.4+svnr145550/gcc/incpath.cc +=================================================================== +--- gcc-4.4+svnr145550.orig/gcc/incpath.cc 2009-04-04 13:48:31.000000000 -0700 ++++ gcc-4.4+svnr145550/gcc/incpath.cc 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/projects/ArchR/packages/lang/go/package.mk b/projects/ArchR/packages/lang/go/package.mk new file mode 100644 index 0000000000..d8dc9fc9c6 --- /dev/null +++ b/projects/ArchR/packages/lang/go/package.mk @@ -0,0 +1,56 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Lukas Rusak (lrusak@libreelec.tv) +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="go" +PKG_VERSION="1.21.4" +PKG_LICENSE="BSD" +PKG_SITE="https://golang.org" +PKG_URL="https://github.com/golang/go/archive/${PKG_NAME}${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="toolchain" +PKG_LONGDESC="An programming language that makes it easy to build simple, reliable, and efficient software." +PKG_TOOLCHAIN="manual" + +configure_host() { + export HOME=${ROOT} + export GOOS=linux + export GOROOT_FINAL=${TOOLCHAIN}/lib/golang + export GOCACHE=${HOME}/.cache/go-build + if [ -x /usr/lib/go/bin/go ]; then + export GOROOT_BOOTSTRAP=/usr/lib/go + else + export GOROOT_BOOTSTRAP=/usr/lib/golang + fi + case ${TARGET_ARCH} in + aarch64|arm) + export GOARCH=amd64 + ;; + esac + + if [ ! -d ${GOROOT_BOOTSTRAP} ]; then + cat < +Date: Tue, 17 Jan 2023 13:05:55 -0800 +Subject: [PATCH] Make: handle warning files while building in a directory + +The dependency on the warning files breaks when we are building in a +directory *and* the files already exist from being shipped with the +distribution tarballs. The make VPATH simply isn't sophisticated +enough to deal with it, so let the C compiler handle it by #including +the generated file from a dummy C file. + +Reported-by: Rudi Heitbaum +Signed-off-by: H. Peter Anvin +--- + Makefile.in | 38 ++++++++++++++++++++------------------ + Mkfiles/msvc.mak | 14 +++++++------- + Mkfiles/openwcom.mak | 14 +++++++------- + doc/Makefile.in | 2 +- + 6 files changed, 37 insertions(+), 34 deletions(-) + +diff --git a/Makefile.in b/Makefile.in +index 148fcb50..95268fd2 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -37,8 +37,10 @@ AR = @AR@ + RANLIB = @RANLIB@ + STRIP = @STRIP@ + ++tools = $(top_srcdir)/tools ++ + PERL = perl +-PERLFLAGS = -I$(srcdir)/perllib -I$(srcdir) ++PERLFLAGS = -I$(top_srcdir)/perllib -I$(srcdir) + RUNPERL = $(PERL) $(PERLFLAGS) + + PYTHON3 = python3 +@@ -65,8 +67,8 @@ LN_S = @LN_S@ + FIND = find + + # Binary suffixes +-O = @OBJEXT@ +-X = @EXEEXT@ ++O = @OBJEXT@ ++X = @EXEEXT@ + A = @LIBEXT@ + + # Debug stuff +@@ -194,14 +196,14 @@ PERLREQ = config/unconfig.h \ + x86/iflag.c x86/iflaggen.h \ + macros/macros.c \ + asm/pptok.ph asm/directbl.c asm/directiv.h \ +- asm/warnings.c include/warnings.h doc/warnings.src \ ++ $(WARNFILES) \ + misc/nasmtok.el \ + version.h version.mac version.mak nsis/version.nsh + + INSDEP = x86/insns.dat x86/insns.pl x86/insns-iflags.ph x86/iflags.ph + + config/unconfig.h: config/config.h.in +- $(RUNPERL) $(srcdir)/tools/unconfig.pl \ ++ $(RUNPERL) $(tools)/unconfig.pl \ + '$(srcdir)' config/config.h.in config/unconfig.h + + x86/iflag.c: $(INSDEP) +@@ -273,7 +275,7 @@ x86/regs.h: x86/regs.dat x86/regs.pl + # reasonable, but doesn't update the time stamp if the files aren't + # changed, to avoid rebuilding everything every time. Track the actual + # dependency by the empty file asm/warnings.time. +-WARNFILES = asm/warnings.c include/warnings.h doc/warnings.src ++WARNFILES = asm/warnings_c.h include/warnings.h doc/warnings.src + + warnings: + $(RM_F) $(WARNFILES) $(WARNFILES:=.time) +@@ -283,11 +285,11 @@ asm/warnings.time: $(ALLOBJ_NW:.$(O)=.c) + : > asm/warnings.time + $(MAKE) $(WARNFILES:=.time) + +-asm/warnings.c.time: asm/warnings.pl asm/warnings.time +- $(RUNPERL) $(srcdir)/asm/warnings.pl c asm/warnings.c $(srcdir) +- : > asm/warnings.c.time ++asm/warnings_c.h.time: asm/warnings.pl asm/warnings.time ++ $(RUNPERL) $(srcdir)/asm/warnings.pl c asm/warnings_c.h $(srcdir) ++ : > asm/warnings_c.h.time + +-asm/warnings.c: asm/warnings.c.time ++asm/warnings_c.h: asm/warnings_c.h.time + @: Side effect + + include/warnings.h.time: asm/warnings.pl asm/warnings.time +@@ -506,8 +508,8 @@ EXTERNAL_DEPENDENCIES = 1 + # the dependency information will remain external, so it doesn't + # pollute the git logs. + # +-Makefile.dep: $(PERLREQ) tools/mkdep.pl config.status +- $(RUNPERL) tools/mkdep.pl -M Makefile.in -- $(DEPDIRS) ++Makefile.dep: $(PERLREQ) $(tools)/mkdep.pl config.status ++ $(RUNPERL) $(tools)/mkdep.pl -M Makefile.in -- $(DEPDIRS) + + dep: Makefile.dep + +@@ -517,9 +519,9 @@ dep: Makefile.dep + # be invoked manually or via "make dist". It should be run before + # creating release archives. + # +-alldeps: $(PERLREQ) tools/syncfiles.pl tools/mkdep.pl +- $(RUNPERL) tools/syncfiles.pl Makefile.in Mkfiles/*.mak +- $(RUNPERL) tools/mkdep.pl -i -M Makefile.in Mkfiles/*.mak -- \ ++alldeps: $(PERLREQ) $(tools)/syncfiles.pl $(tools)/mkdep.pl ++ $(RUNPERL) $(tools)/syncfiles.pl Makefile.in Mkfiles/*.mak ++ $(RUNPERL) $(tools)/mkdep.pl -i -M Makefile.in Mkfiles/*.mak -- \ + $(DEPDIRS) + $(RM_F) *.dep + if [ -f config.status ]; then \ +@@ -528,9 +530,9 @@ alldeps: $(PERLREQ) tools/syncfiles.pl tools/mkdep.pl + + # Strip internal dependency information from all Makefiles; this makes + # the output good for git checkin +-cleandeps: $(PERLREQ) tools/syncfiles.pl tools/mkdep.pl +- $(RUNPERL) tools/syncfiles.pl Makefile.in Mkfiles/*.mak +- $(RUNPERL) tools/mkdep.pl -e -M Makefile.in Mkfiles/*.mak -- \ ++cleandeps: $(PERLREQ) $(tools)/syncfiles.pl $(tools)/mkdep.pl ++ $(RUNPERL) $(tools)/syncfiles.pl Makefile.in Mkfiles/*.mak ++ $(RUNPERL) $(tools)/mkdep.pl -e -M Makefile.in Mkfiles/*.mak -- \ + $(DEPDIRS) + $(RM_F) *.dep + if [ -f config.status ]; then \ +diff --git a/Mkfiles/msvc.mak b/Mkfiles/msvc.mak +index cf71fffc..da71c5c6 100644 +--- a/Mkfiles/msvc.mak ++++ b/Mkfiles/msvc.mak +@@ -153,14 +153,14 @@ PERLREQ = config\unconfig.h \ + x86\iflag.c x86\iflaggen.h \ + macros\macros.c \ + asm\pptok.ph asm\directbl.c asm\directiv.h \ +- asm\warnings.c include\warnings.h doc\warnings.src \ ++ $(WARNFILES) \ + misc\nasmtok.el \ + version.h version.mac version.mak nsis\version.nsh + + INSDEP = x86\insns.dat x86\insns.pl x86\insns-iflags.ph x86\iflags.ph + + config\unconfig.h: config\config.h.in +- $(RUNPERL) $(srcdir)\tools\unconfig.pl \ ++ $(RUNPERL) $(tools)\unconfig.pl \ + '$(srcdir)' config\config.h.in config\unconfig.h + + x86\iflag.c: $(INSDEP) +@@ -232,7 +232,7 @@ x86\regs.h: x86\regs.dat x86\regs.pl + # reasonable, but doesn't update the time stamp if the files aren't + # changed, to avoid rebuilding everything every time. Track the actual + # dependency by the empty file asm\warnings.time. +-WARNFILES = asm\warnings.c include\warnings.h doc\warnings.src ++WARNFILES = asm\warnings_c.h include\warnings.h doc\warnings.src + + warnings: + $(RM_F) $(WARNFILES) $(WARNFILES:=.time) +@@ -242,11 +242,11 @@ asm\warnings.time: $(ALLOBJ_NW:.$(O)=.c) + : > asm\warnings.time + $(MAKE) $(WARNFILES:=.time) + +-asm\warnings.c.time: asm\warnings.pl asm\warnings.time +- $(RUNPERL) $(srcdir)\asm\warnings.pl c asm\warnings.c $(srcdir) +- : > asm\warnings.c.time ++asm\warnings_c.h.time: asm\warnings.pl asm\warnings.time ++ $(RUNPERL) $(srcdir)\asm\warnings.pl c asm\warnings_c.h $(srcdir) ++ : > asm\warnings_c.h.time + +-asm\warnings.c: asm\warnings.c.time ++asm\warnings_c.h: asm\warnings_c.h.time + @: Side effect + + include\warnings.h.time: asm\warnings.pl asm\warnings.time +diff --git a/Mkfiles/openwcom.mak b/Mkfiles/openwcom.mak +index 5394d85d..605f9afe 100644 +--- a/Mkfiles/openwcom.mak ++++ b/Mkfiles/openwcom.mak +@@ -166,14 +166,14 @@ PERLREQ = config\unconfig.h & + x86\iflag.c x86\iflaggen.h & + macros\macros.c & + asm\pptok.ph asm\directbl.c asm\directiv.h & +- asm\warnings.c include\warnings.h doc\warnings.src & ++ $(WARNFILES) & + misc\nasmtok.el & + version.h version.mac version.mak nsis\version.nsh + + INSDEP = x86\insns.dat x86\insns.pl x86\insns-iflags.ph x86\iflags.ph + + config\unconfig.h: config\config.h.in +- $(RUNPERL) $(srcdir)\tools\unconfig.pl & ++ $(RUNPERL) $(tools)\unconfig.pl & + '$(srcdir)' config\config.h.in config\unconfig.h + + x86\iflag.c: $(INSDEP) +@@ -245,7 +245,7 @@ x86\regs.h: x86\regs.dat x86\regs.pl + # reasonable, but doesn't update the time stamp if the files aren't + # changed, to avoid rebuilding everything every time. Track the actual + # dependency by the empty file asm\warnings.time. +-WARNFILES = asm\warnings.c include\warnings.h doc\warnings.src ++WARNFILES = asm\warnings_c.h include\warnings.h doc\warnings.src + + warnings: + $(RM_F) $(WARNFILES) $(WARNFILES:=.time) +@@ -255,11 +255,11 @@ asm\warnings.time: $(ALLOBJ_NW:.$(O)=.c) + : > asm\warnings.time + $(MAKE) $(WARNFILES:=.time) + +-asm\warnings.c.time: asm\warnings.pl asm\warnings.time +- $(RUNPERL) $(srcdir)\asm\warnings.pl c asm\warnings.c $(srcdir) +- : > asm\warnings.c.time ++asm\warnings_c.h.time: asm\warnings.pl asm\warnings.time ++ $(RUNPERL) $(srcdir)\asm\warnings.pl c asm\warnings_c.h $(srcdir) ++ : > asm\warnings_c.h.time + +-asm\warnings.c: asm\warnings.c.time ++asm\warnings_c.h: asm\warnings_c.h.time + @: Side effect + + include\warnings.h.time: asm\warnings.pl asm\warnings.time +diff --git a/doc/Makefile.in b/doc/Makefile.in +index e92437a0..1c8393c5 100644 +--- a/doc/Makefile.in ++++ b/doc/Makefile.in +@@ -20,7 +20,7 @@ INSTALL = @INSTALL@ + INSTALL_PROGRAM = @INSTALL_PROGRAM@ + INSTALL_DATA = @INSTALL_DATA@ + +-PERL = perl -I$(srcdir) ++PERL = perl -I$(top_srcdir)/perllib -I$(srcdir) + + PDFOPT = @PDFOPT@ + diff --git a/projects/ArchR/packages/linux-drivers/AIC8800/package.mk b/projects/ArchR/packages/linux-drivers/AIC8800/package.mk new file mode 100644 index 0000000000..867157d9aa --- /dev/null +++ b/projects/ArchR/packages/linux-drivers/AIC8800/package.mk @@ -0,0 +1,78 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2026-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="AIC8800" +PKG_VERSION="1018f17a629c638acc1a01df19e3f2146e7b4f5c" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/friddle/arch-aic8800-6.12" +PKG_URL="${PKG_SITE}.git" +PKG_LONGDESC="AICsemi AIC8800 USB WiFi+BT driver and firmware" +PKG_TOOLCHAIN="make" +PKG_IS_KERNEL_PKG="yes" + +pre_make_target() { + unset LDFLAGS + + # Switch platform from Ubuntu to manual cross-compilation + sed -i 's/CONFIG_PLATFORM_UBUNTU ?= y/CONFIG_PLATFORM_UBUNTU ?= n/' \ + ${PKG_BUILD}/drivers/aic8800/Makefile +} + +make_target() { + cd ${PKG_BUILD}/drivers/aic8800 + make V=1 \ + ARCH=${TARGET_KERNEL_ARCH} \ + KDIR=$(kernel_path) \ + CROSS_COMPILE=${TARGET_KERNEL_PREFIX} +} + +makeinstall_target() { + mkdir -p ${INSTALL}/$(get_full_module_dir)/kernel/drivers/net/wireless/ + find ${PKG_BUILD}/drivers/aic8800 -name "*.ko" \ + -exec cp {} ${INSTALL}/$(get_full_module_dir)/kernel/drivers/net/wireless/ \; + + # Install firmware to kernel-overlays (build system symlinks /usr/lib/firmware there) + mkdir -p ${INSTALL}/$(get_full_firmware_dir)/aic8800DC + cp -r ${PKG_BUILD}/fw/aic8800DC/* ${INSTALL}/$(get_full_firmware_dir)/aic8800DC/ + + # Install AIC8800 USB mode switch script and udev rule + mkdir -p ${INSTALL}/usr/lib/udev/rules.d + mkdir -p ${INSTALL}/usr/bin + + # Mode switch script with USB reset fallback + cat > ${INSTALL}/usr/bin/aic8800-modeswitch << 'SCRIPT' +#!/bin/sh +# AIC8800 USB mode switch: eject mass storage to activate WiFi mode +# If re-enumeration fails, reset the USB port +DEV="$1" +[ -z "$DEV" ] && exit 0 + +# Eject the mass storage device +eject "/dev/$DEV" 2>/dev/null + +# Wait for WiFi mode to enumerate +for i in $(seq 1 10); do + sleep 1 + # Check if a wireless interface appeared + ls /sys/class/net/wlan* >/dev/null 2>&1 && exit 0 +done + +# If WiFi didn't appear, try resetting the USB bus +for usbdev in /sys/bus/usb/devices/*/authorized; do + dir=$(dirname "$usbdev") + if grep -q "a69c" "$dir/idVendor" 2>/dev/null; then + echo 0 > "$usbdev" 2>/dev/null + sleep 1 + echo 1 > "$usbdev" 2>/dev/null + break + fi +done +SCRIPT + chmod +x ${INSTALL}/usr/bin/aic8800-modeswitch + + # udev rule triggers mode switch script + cat > ${INSTALL}/usr/lib/udev/rules.d/99-aic8800.rules << 'RULES' +KERNEL=="sd*", ATTRS{idVendor}=="a69c", ATTRS{idProduct}=="5721", SYMLINK+="aicudisk", RUN+="/usr/bin/aic8800-modeswitch %k" +KERNEL=="sd*", ATTRS{idVendor}=="a69c", ATTRS{idProduct}=="5722", SYMLINK+="aicudisk", RUN+="/usr/bin/aic8800-modeswitch %k" +RULES +} diff --git a/projects/ArchR/packages/linux-drivers/RTL8733BU/package.mk b/projects/ArchR/packages/linux-drivers/RTL8733BU/package.mk new file mode 100644 index 0000000000..ee09bcc103 --- /dev/null +++ b/projects/ArchR/packages/linux-drivers/RTL8733BU/package.mk @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="RTL8733BU" +PKG_VERSION="308919f005f439de433aac977f925bb57f59acf4" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/wirenboard/rtl8733bu" +PKG_URL="https://github.com/archr-linux/RTL8733BU/archive/${PKG_VERSION}.tar.gz" +PKG_LONGDESC="RTL8733BU driver" +PKG_TOOLCHAIN="make" +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=y +} + +makeinstall_target() { + mkdir -p ${INSTALL}/$(get_full_module_dir)/kernel/drivers/net/wireless + cp *.ko ${INSTALL}/$(get_full_module_dir)/kernel/drivers/net/wireless +} diff --git a/projects/ArchR/packages/linux-drivers/RTL8812AU/modprobe.d/8812au.conf b/projects/ArchR/packages/linux-drivers/RTL8812AU/modprobe.d/8812au.conf new file mode 100644 index 0000000000..abfc21fd60 --- /dev/null +++ b/projects/ArchR/packages/linux-drivers/RTL8812AU/modprobe.d/8812au.conf @@ -0,0 +1,155 @@ +# /etc/modprobe.d/8812au.conf +# +# Purpose: Allow easy access to specific driver options. +# +# Edit the following line to change, add or delete options: +options 8812au rtw_drv_log_level=0 rtw_led_ctrl=1 rtw_vht_enable=1 rtw_power_mgnt=1 rtw_beamform_cap=0 rtw_dfs_region_domain=0 rtw_switch_usb_mode=0 +# +# After editing is complete, save this file (if using nano: Ctrl + x, y, Enter) +# and reboot to activate the changes. +# +# Documentation: +# +# ----- +# +# Log options ( rtw_drv_log_level ) +# +# 0 = NONE (default) +# 1 = ALWAYS +# 2 = ERROR +# 3 = WARNING +# 4 = INFO +# 5 = DEBUG +# 6 = MAX +# +# Note: You can save a log file that only includes RTW log entries by running +# the following in a terminal: +# +# sudo ./save-log.sh +# +# Note: The name of the log file will be ```rtw.log```. +# +# ----- +# +# LED options ( rtw_led_ctrl ) +# +# 0 = Always off +# 1 = Normal blink (default) +# 2 = Always on +# +# ----- +# +# VHT options ( rtw_vht_enable ) +# +# 0 = Disable +# 1 = Enable (default) +# 2 = Force auto enable (use only for 5 GHz AP mode) +# +# Notes: +# - A non-default setting can degrade performance greatly in managed mode. +# - Option 2 allows 80 MHz channel width for 5GHz AP mode, such as when +# you are using hostapd. +# +# ----- +# +# Power options ( rtw_power_mgnt ) +# +# 0 = Disable power saving +# 1 = Power saving on, minPS (default) +# 2 = Power saving on, maxPS (not recommended for AP mode) +# +# ----- +# +# Beamforming options ( rtw_beamform_cap ) +# +# 0 = Disable (default) +# 1 = SU Beamformer +# 2 = SU Beamformee +# 3 = SU Beamformer and SU Beamformee +# 10= SU Beamformee and MU Beamformee +# 11= SU Beamformer and SU Beamformee and MU Beamformee +# +# Note: MU Beamformer is not supported. +# +# ----- +# +# Country Code options ( rtw_country_code ) +# +# Note: Allows the Country Code to be set in cases where it is unable to +# be obtained from the operating system. +# +# Example for the US: rtw_country_code=US +# Example for Panama: rtw_country_code=PA +# Example for Norway: rtw_country_code=NO +# Example for Kuwait: rtw_country_code=KW +# Example for Taiwan: rtw_country_code=TW +# +# ----- +# +# DFS Options ( rtw_dfs_region_domain ) +# +# 0 = NONE (default) +# 1 = FCC +# 2 = MKK +# 3 = ETSI +# +# Notes: +# - Activates DFS channels in AP mode. +# - DFS FCC 80 MHz channels for hostapd: 52(58), 100(106), 116(122) and 132(138) +# - For more information: https://en.wikipedia.org/wiki/List_of_WLAN_channels +# +# Note: An AP needs to listen on a DFS channel for a period of 60 seconds +# before transmitting on the channel. If any radar pulses are detected, +# the AP cannot use that channel and will have to try a different channel. +# +# ----- +# +# Select P2P interface in concurrent mode ( rtw_sel_p2p_iface ) +# +# 0 = Sets interface 0 to be p2p interface +# 1 = Sets interface 1 to be p2p interface (default) +# +# ----- +# +# USB options: ( rtw_switch_usb_mode ) +# +# 0 = No switch (default) +# 1 = Switch from usb 2.0 to usb 3.0 +# 2 = Switch from usb 3.0 to usb 2.0 +# +# ----- +# +# To see all options that are available: +# +# $ ls /sys/module/8812au/parameters/ +# +# ----- +# +# To see the values that are in use: +# +# $ grep [[:alnum:]] /sys/module/8812au/parameters/* +# +# ----- +# +# hostapd setup information for rtl8812au +# Note: The best settings can vary but the following may be a good place to start. +# +# /etc/modprobe.d/8812au.conf +# options 8812au rtw_drv_log_level=0 rtw_led_ctrl=0 rtw_vht_enable=2 rtw_power_mgnt=1 rtw_beamform_cap=0 rtw_dfs_region_domain=1 rtw_switch_usb_mode=1 +# +# Note: The best setting for `rtw_dfs_region_domain=` will depend on your location. +# +# /etc/hostapd/hostapd.conf +# +# hw ht capab: 0x862 +# ht_capab=[HT40+][HT40-][SHORT-GI-20][SHORT-GI-40][MAX-AMSDU-7935] +# +# hw vht capab: 0x03c001a2 +# vht_capab=[MAX-MPDU-11454][SHORT-GI-80][TX-STBC-2BY1][RX-STBC-1][HTC-VHT][MAX-A-MPDU-LEN-EXP7] +# +# ----- + + + + + diff --git a/projects/ArchR/packages/linux-drivers/RTL8812AU/package.mk b/projects/ArchR/packages/linux-drivers/RTL8812AU/package.mk new file mode 100644 index 0000000000..ebf9865ec1 --- /dev/null +++ b/projects/ArchR/packages/linux-drivers/RTL8812AU/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) 2018-present Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="RTL8812AU" +PKG_VERSION="3e8c73224cede1097c49fcd1ecd2e3e181f4540d" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/morrownr/8812au-20210820" +PKG_URL="${PKG_SITE}.git" +PKG_LONGDESC="Realtek 8812AU driver for 4.4-5.x" +PKG_TOOLCHAIN="make" +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=y +} + +makeinstall_target() { + mkdir -p ${INSTALL}/$(get_full_module_dir)/kernel/drivers/net/wireless/ + cp *.ko ${INSTALL}/$(get_full_module_dir)/kernel/drivers/net/wireless/ +} diff --git a/projects/ArchR/packages/linux-drivers/RTL8814AU/modprobe.d/8812au.conf b/projects/ArchR/packages/linux-drivers/RTL8814AU/modprobe.d/8812au.conf new file mode 100644 index 0000000000..abfc21fd60 --- /dev/null +++ b/projects/ArchR/packages/linux-drivers/RTL8814AU/modprobe.d/8812au.conf @@ -0,0 +1,155 @@ +# /etc/modprobe.d/8812au.conf +# +# Purpose: Allow easy access to specific driver options. +# +# Edit the following line to change, add or delete options: +options 8812au rtw_drv_log_level=0 rtw_led_ctrl=1 rtw_vht_enable=1 rtw_power_mgnt=1 rtw_beamform_cap=0 rtw_dfs_region_domain=0 rtw_switch_usb_mode=0 +# +# After editing is complete, save this file (if using nano: Ctrl + x, y, Enter) +# and reboot to activate the changes. +# +# Documentation: +# +# ----- +# +# Log options ( rtw_drv_log_level ) +# +# 0 = NONE (default) +# 1 = ALWAYS +# 2 = ERROR +# 3 = WARNING +# 4 = INFO +# 5 = DEBUG +# 6 = MAX +# +# Note: You can save a log file that only includes RTW log entries by running +# the following in a terminal: +# +# sudo ./save-log.sh +# +# Note: The name of the log file will be ```rtw.log```. +# +# ----- +# +# LED options ( rtw_led_ctrl ) +# +# 0 = Always off +# 1 = Normal blink (default) +# 2 = Always on +# +# ----- +# +# VHT options ( rtw_vht_enable ) +# +# 0 = Disable +# 1 = Enable (default) +# 2 = Force auto enable (use only for 5 GHz AP mode) +# +# Notes: +# - A non-default setting can degrade performance greatly in managed mode. +# - Option 2 allows 80 MHz channel width for 5GHz AP mode, such as when +# you are using hostapd. +# +# ----- +# +# Power options ( rtw_power_mgnt ) +# +# 0 = Disable power saving +# 1 = Power saving on, minPS (default) +# 2 = Power saving on, maxPS (not recommended for AP mode) +# +# ----- +# +# Beamforming options ( rtw_beamform_cap ) +# +# 0 = Disable (default) +# 1 = SU Beamformer +# 2 = SU Beamformee +# 3 = SU Beamformer and SU Beamformee +# 10= SU Beamformee and MU Beamformee +# 11= SU Beamformer and SU Beamformee and MU Beamformee +# +# Note: MU Beamformer is not supported. +# +# ----- +# +# Country Code options ( rtw_country_code ) +# +# Note: Allows the Country Code to be set in cases where it is unable to +# be obtained from the operating system. +# +# Example for the US: rtw_country_code=US +# Example for Panama: rtw_country_code=PA +# Example for Norway: rtw_country_code=NO +# Example for Kuwait: rtw_country_code=KW +# Example for Taiwan: rtw_country_code=TW +# +# ----- +# +# DFS Options ( rtw_dfs_region_domain ) +# +# 0 = NONE (default) +# 1 = FCC +# 2 = MKK +# 3 = ETSI +# +# Notes: +# - Activates DFS channels in AP mode. +# - DFS FCC 80 MHz channels for hostapd: 52(58), 100(106), 116(122) and 132(138) +# - For more information: https://en.wikipedia.org/wiki/List_of_WLAN_channels +# +# Note: An AP needs to listen on a DFS channel for a period of 60 seconds +# before transmitting on the channel. If any radar pulses are detected, +# the AP cannot use that channel and will have to try a different channel. +# +# ----- +# +# Select P2P interface in concurrent mode ( rtw_sel_p2p_iface ) +# +# 0 = Sets interface 0 to be p2p interface +# 1 = Sets interface 1 to be p2p interface (default) +# +# ----- +# +# USB options: ( rtw_switch_usb_mode ) +# +# 0 = No switch (default) +# 1 = Switch from usb 2.0 to usb 3.0 +# 2 = Switch from usb 3.0 to usb 2.0 +# +# ----- +# +# To see all options that are available: +# +# $ ls /sys/module/8812au/parameters/ +# +# ----- +# +# To see the values that are in use: +# +# $ grep [[:alnum:]] /sys/module/8812au/parameters/* +# +# ----- +# +# hostapd setup information for rtl8812au +# Note: The best settings can vary but the following may be a good place to start. +# +# /etc/modprobe.d/8812au.conf +# options 8812au rtw_drv_log_level=0 rtw_led_ctrl=0 rtw_vht_enable=2 rtw_power_mgnt=1 rtw_beamform_cap=0 rtw_dfs_region_domain=1 rtw_switch_usb_mode=1 +# +# Note: The best setting for `rtw_dfs_region_domain=` will depend on your location. +# +# /etc/hostapd/hostapd.conf +# +# hw ht capab: 0x862 +# ht_capab=[HT40+][HT40-][SHORT-GI-20][SHORT-GI-40][MAX-AMSDU-7935] +# +# hw vht capab: 0x03c001a2 +# vht_capab=[MAX-MPDU-11454][SHORT-GI-80][TX-STBC-2BY1][RX-STBC-1][HTC-VHT][MAX-A-MPDU-LEN-EXP7] +# +# ----- + + + + + diff --git a/projects/ArchR/packages/linux-drivers/RTL8814AU/package.mk b/projects/ArchR/packages/linux-drivers/RTL8814AU/package.mk new file mode 100644 index 0000000000..78b1ec6dba --- /dev/null +++ b/projects/ArchR/packages/linux-drivers/RTL8814AU/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) 2018-present Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="RTL8814AU" +PKG_VERSION="b5a6f96cd20a1c6a35ccb000f2f4924dd19704a3" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/morrownr/8814au" +PKG_URL="${PKG_SITE}.git" +PKG_LONGDESC="Realtek 8814AU driver for 4.4-5.x" +PKG_TOOLCHAIN="make" +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=y +} + +makeinstall_target() { + mkdir -p ${INSTALL}/$(get_full_module_dir)/kernel/drivers/net/wireless/ + cp *.ko ${INSTALL}/$(get_full_module_dir)/kernel/drivers/net/wireless/ +} diff --git a/projects/ArchR/packages/linux-drivers/RTL8821AU/modprobe.d/8812au.conf b/projects/ArchR/packages/linux-drivers/RTL8821AU/modprobe.d/8812au.conf new file mode 100644 index 0000000000..abfc21fd60 --- /dev/null +++ b/projects/ArchR/packages/linux-drivers/RTL8821AU/modprobe.d/8812au.conf @@ -0,0 +1,155 @@ +# /etc/modprobe.d/8812au.conf +# +# Purpose: Allow easy access to specific driver options. +# +# Edit the following line to change, add or delete options: +options 8812au rtw_drv_log_level=0 rtw_led_ctrl=1 rtw_vht_enable=1 rtw_power_mgnt=1 rtw_beamform_cap=0 rtw_dfs_region_domain=0 rtw_switch_usb_mode=0 +# +# After editing is complete, save this file (if using nano: Ctrl + x, y, Enter) +# and reboot to activate the changes. +# +# Documentation: +# +# ----- +# +# Log options ( rtw_drv_log_level ) +# +# 0 = NONE (default) +# 1 = ALWAYS +# 2 = ERROR +# 3 = WARNING +# 4 = INFO +# 5 = DEBUG +# 6 = MAX +# +# Note: You can save a log file that only includes RTW log entries by running +# the following in a terminal: +# +# sudo ./save-log.sh +# +# Note: The name of the log file will be ```rtw.log```. +# +# ----- +# +# LED options ( rtw_led_ctrl ) +# +# 0 = Always off +# 1 = Normal blink (default) +# 2 = Always on +# +# ----- +# +# VHT options ( rtw_vht_enable ) +# +# 0 = Disable +# 1 = Enable (default) +# 2 = Force auto enable (use only for 5 GHz AP mode) +# +# Notes: +# - A non-default setting can degrade performance greatly in managed mode. +# - Option 2 allows 80 MHz channel width for 5GHz AP mode, such as when +# you are using hostapd. +# +# ----- +# +# Power options ( rtw_power_mgnt ) +# +# 0 = Disable power saving +# 1 = Power saving on, minPS (default) +# 2 = Power saving on, maxPS (not recommended for AP mode) +# +# ----- +# +# Beamforming options ( rtw_beamform_cap ) +# +# 0 = Disable (default) +# 1 = SU Beamformer +# 2 = SU Beamformee +# 3 = SU Beamformer and SU Beamformee +# 10= SU Beamformee and MU Beamformee +# 11= SU Beamformer and SU Beamformee and MU Beamformee +# +# Note: MU Beamformer is not supported. +# +# ----- +# +# Country Code options ( rtw_country_code ) +# +# Note: Allows the Country Code to be set in cases where it is unable to +# be obtained from the operating system. +# +# Example for the US: rtw_country_code=US +# Example for Panama: rtw_country_code=PA +# Example for Norway: rtw_country_code=NO +# Example for Kuwait: rtw_country_code=KW +# Example for Taiwan: rtw_country_code=TW +# +# ----- +# +# DFS Options ( rtw_dfs_region_domain ) +# +# 0 = NONE (default) +# 1 = FCC +# 2 = MKK +# 3 = ETSI +# +# Notes: +# - Activates DFS channels in AP mode. +# - DFS FCC 80 MHz channels for hostapd: 52(58), 100(106), 116(122) and 132(138) +# - For more information: https://en.wikipedia.org/wiki/List_of_WLAN_channels +# +# Note: An AP needs to listen on a DFS channel for a period of 60 seconds +# before transmitting on the channel. If any radar pulses are detected, +# the AP cannot use that channel and will have to try a different channel. +# +# ----- +# +# Select P2P interface in concurrent mode ( rtw_sel_p2p_iface ) +# +# 0 = Sets interface 0 to be p2p interface +# 1 = Sets interface 1 to be p2p interface (default) +# +# ----- +# +# USB options: ( rtw_switch_usb_mode ) +# +# 0 = No switch (default) +# 1 = Switch from usb 2.0 to usb 3.0 +# 2 = Switch from usb 3.0 to usb 2.0 +# +# ----- +# +# To see all options that are available: +# +# $ ls /sys/module/8812au/parameters/ +# +# ----- +# +# To see the values that are in use: +# +# $ grep [[:alnum:]] /sys/module/8812au/parameters/* +# +# ----- +# +# hostapd setup information for rtl8812au +# Note: The best settings can vary but the following may be a good place to start. +# +# /etc/modprobe.d/8812au.conf +# options 8812au rtw_drv_log_level=0 rtw_led_ctrl=0 rtw_vht_enable=2 rtw_power_mgnt=1 rtw_beamform_cap=0 rtw_dfs_region_domain=1 rtw_switch_usb_mode=1 +# +# Note: The best setting for `rtw_dfs_region_domain=` will depend on your location. +# +# /etc/hostapd/hostapd.conf +# +# hw ht capab: 0x862 +# ht_capab=[HT40+][HT40-][SHORT-GI-20][SHORT-GI-40][MAX-AMSDU-7935] +# +# hw vht capab: 0x03c001a2 +# vht_capab=[MAX-MPDU-11454][SHORT-GI-80][TX-STBC-2BY1][RX-STBC-1][HTC-VHT][MAX-A-MPDU-LEN-EXP7] +# +# ----- + + + + + diff --git a/projects/ArchR/packages/linux-drivers/RTL8821AU/package.mk b/projects/ArchR/packages/linux-drivers/RTL8821AU/package.mk new file mode 100644 index 0000000000..17914d0652 --- /dev/null +++ b/projects/ArchR/packages/linux-drivers/RTL8821AU/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) 2018-present Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="RTL8821AU" +PKG_VERSION="847c74b1c272466f89c77947f7a9703222f0093b" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/morrownr/8821au-20210708" +PKG_URL="${PKG_SITE}.git" +PKG_LONGDESC="Realtek 8821AU driver for 4.4-5.x" +PKG_TOOLCHAIN="make" +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=y +} + +makeinstall_target() { + mkdir -p ${INSTALL}/$(get_full_module_dir)/kernel/drivers/net/wireless/ + cp *.ko ${INSTALL}/$(get_full_module_dir)/kernel/drivers/net/wireless/ +} diff --git a/projects/ArchR/packages/linux-drivers/RTL8821CU/modprobe.d/8821cu.conf b/projects/ArchR/packages/linux-drivers/RTL8821CU/modprobe.d/8821cu.conf new file mode 100644 index 0000000000..0512d38594 --- /dev/null +++ b/projects/ArchR/packages/linux-drivers/RTL8821CU/modprobe.d/8821cu.conf @@ -0,0 +1,145 @@ +# /etc/modprobe.d/8821cu.conf +# +# Purpose: Allow easy access to specific driver options. +# +# Edit the following line to change, add or delete options: +#options 8821cu rtw_drv_log_level=0 rtw_led_ctrl=1 rtw_vht_enable=1 rtw_power_mgnt=1 rtw_beamform_cap=0 rtw_dfs_region_domain=0 +# +# After editing is complete, save this file (if using nano: Ctrl + x, y, Enter) +# and reboot to activate the changes. +# +# Documentation: +# +# ----- +# +# Log options ( rtw_drv_log_level ) +# +# 0 = NONE (default) +# 1 = ALWAYS +# 2 = ERROR +# 3 = WARNING +# 4 = INFO +# 5 = DEBUG +# 6 = MAX +# +# Note: You can save a log file that only includes RTW log entries by running +# the following in a terminal: +# +# sudo ./save-log.sh +# +# Note: The name of the log file will be ```rtw.log```. +# +# ----- +# +# LED options ( rtw_led_ctrl ) +# +# 0 = Always off +# 1 = Normal blink (default) +# 2 = Always on +# +# ----- +# +# VHT options ( rtw_vht_enable ) +# +# 0 = Disable +# 1 = Enable (default) +# 2 = Force auto enable (use only for 5 GHz AP mode) +# +# Notes: +# - A non-default setting can degrade performance greatly in managed mode. +# - Option 2 allows 80 MHz channel width for 5GHz AP mode, such as when +# you are using hostapd. +# +# ----- +# +# Power options ( rtw_power_mgnt ) +# +# 0 = Disable power saving +# 1 = Power saving on, minPS (default) +# 2 = Power saving on, maxPS (not recommended for AP mode) +# +# ----- +# +# Beamforming options ( rtw_beamform_cap ) +# +# 0 = Disable (default) +# 1 = SU Beamformer +# 2 = SU Beamformee +# 10= SU Beamformee and MU Beamformee +# +# Note: MU Beamformer is not supported. +# +# ----- +# +# Country Code options ( rtw_country_code ) +# +# Note: Allows the Country Code to be set in cases where it is unable to +# be obtained from the operating system. +# +# Example for the US: rtw_country_code=US +# Example for Panama: rtw_country_code=PA +# Example for Norway: rtw_country_code=NO +# Example for Kuwait: rtw_country_code=KW +# Example for Taiwan: rtw_country_code=TW +# +# ----- +# +# DFS Options ( rtw_dfs_region_domain ) +# +# 0 = NONE (default) +# 1 = FCC +# 2 = MKK +# 3 = ETSI +# +# Notes: +# - Activates DFS channels in AP mode. +# - DFS FCC 80 MHz channels for hostapd: 52(58), 100(106), 116(122) and 132(138) +# - For more information: https://en.wikipedia.org/wiki/List_of_WLAN_channels +# +# Note: An AP needs to listen on a DFS channel for a period of 60 seconds +# before transmitting on the channel. If any radar pulses are detected, +# the AP cannot use that channel and will have to try a different channel. +# +# ----- +# +# Select P2P interface in concurrent mode ( rtw_sel_p2p_iface ) +# +# 0 = Sets interface 0 to be p2p interface +# 1 = Sets interface 1 to be p2p interface (default) +# +# ----- +# +# To see all options that are available: +# +# $ ls /sys/module/8821cu/parameters/ +# +# ----- +# +# To see the values that are in use: +# +# $ grep [[:alnum:]] /sys/module/8821cu/parameters/* +# +# ----- +# +# hostapd setup information for rtl8821cu +# Note: The best settings can vary but the following may be a good place to start. +# +# /etc/modprobe.d/8821cu.conf +# options 8821cu rtw_drv_log_level=0 rtw_led_ctrl=0 rtw_vht_enable=2 rtw_power_mgnt=1 rtw_beamform_cap=0 rtw_dfs_region_domain=1 +# +# Note: The best setting for `rtw_dfs_region_domain=` will depend on your location. +# +# /etc/hostapd/hostapd.conf +# +# hw ht capab: 0x862 +# ht_capab=[HT40+][HT40-][SHORT-GI-20][SHORT-GI-40][MAX-AMSDU-7935] +# +# hw vht capab: 0x03c00022 +# vht_capab=[MAX-MPDU-11454][SHORT-GI-80][HTC-VHT][MAX-A-MPDU-LEN-EXP7] +# +# ----- + + + + + diff --git a/projects/ArchR/packages/linux-drivers/RTL8821CU/package.mk b/projects/ArchR/packages/linux-drivers/RTL8821CU/package.mk new file mode 100644 index 0000000000..e5cd746cd5 --- /dev/null +++ b/projects/ArchR/packages/linux-drivers/RTL8821CU/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) 2018-present Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="RTL8821CU" +PKG_VERSION="3d1fcf4bc838542ceb03b0b4e9e40600720cf6ae" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/morrownr/8821cu-20210916" +PKG_URL="${PKG_SITE}.git" +PKG_LONGDESC="Realtek 8821CU driver for 4.4-5.x" +PKG_TOOLCHAIN="make" +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=y +} + +makeinstall_target() { + mkdir -p ${INSTALL}/$(get_full_module_dir)/kernel/drivers/net/wireless/ + cp *.ko ${INSTALL}/$(get_full_module_dir)/kernel/drivers/net/wireless/ +} diff --git a/projects/ArchR/packages/linux-drivers/RTL8821CU/patches/001-fix_btcoex.patch b/projects/ArchR/packages/linux-drivers/RTL8821CU/patches/001-fix_btcoex.patch new file mode 100644 index 0000000000..3862fe411b --- /dev/null +++ b/projects/ArchR/packages/linux-drivers/RTL8821CU/patches/001-fix_btcoex.patch @@ -0,0 +1,22 @@ +diff --git a/hal/rtl8821c/rtl8821c_ops.c b/hal/rtl8821c/rtl8821c_ops.c +index 7461142..fffd472 100755 +--- a/hal/rtl8821c/rtl8821c_ops.c ++++ b/hal/rtl8821c/rtl8821c_ops.c +@@ -524,7 +524,7 @@ u8 rtl8821c_read_efuse(PADAPTER adapter) + + if (hal_read_mac_hidden_rpt(adapter) != _SUCCESS) + goto exit; +- { ++ /*{ + struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter); + + if (hal_spec->hci_type <= 3 && hal_spec->hci_type >= 1) { +@@ -532,7 +532,7 @@ u8 rtl8821c_read_efuse(PADAPTER adapter) + RTW_INFO("EEPROM Disable BT-coex by hal_spec\n"); + rtw_btcoex_wifionly_AntInfoSetting(adapter); + } +- } ++ }*/ + + rtw_phydm_read_efuse(adapter); + diff --git a/projects/ArchR/packages/linux-drivers/RTL8831/package.mk b/projects/ArchR/packages/linux-drivers/RTL8831/package.mk new file mode 100644 index 0000000000..a0c3e16a04 --- /dev/null +++ b/projects/ArchR/packages/linux-drivers/RTL8831/package.mk @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2026-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="RTL8831" +PKG_VERSION="905fc2dd7890a6d91cb6fe9e2139664a22c7839f" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/biglinux/rtl8831" +PKG_URL="${PKG_SITE}.git" +PKG_LONGDESC="Realtek RTL8831/RTL8851BU USB WiFi 6 driver" +PKG_TOOLCHAIN="make" +PKG_IS_KERNEL_PKG="yes" + +pre_make_target() { + unset LDFLAGS + + # Switch platform from I386_PC to ARM64 for cross-compilation + sed -i 's/CONFIG_PLATFORM_I386_PC = y/CONFIG_PLATFORM_I386_PC = n/' ${PKG_BUILD}/Makefile + sed -i 's/CONFIG_PLATFORM_ARM64_PC = n/CONFIG_PLATFORM_ARM64_PC = y/' ${PKG_BUILD}/Makefile + +} + +make_target() { + make V=1 \ + ARCH=${TARGET_KERNEL_ARCH} \ + KSRC=$(kernel_path) \ + CROSS_COMPILE=${TARGET_KERNEL_PREFIX} \ + CONFIG_POWER_SAVING=y +} + +makeinstall_target() { + mkdir -p ${INSTALL}/$(get_full_module_dir)/kernel/drivers/net/wireless/ + cp *.ko ${INSTALL}/$(get_full_module_dir)/kernel/drivers/net/wireless/ +} diff --git a/projects/ArchR/packages/linux-drivers/RTL8851BU/package.mk b/projects/ArchR/packages/linux-drivers/RTL8851BU/package.mk new file mode 100644 index 0000000000..7f88c92613 --- /dev/null +++ b/projects/ArchR/packages/linux-drivers/RTL8851BU/package.mk @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="RTL8851BU" +PKG_VERSION="f94ea820634d3bd050009e861952d3b8eeef869a" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/neatojones/RTL8851bu" +PKG_URL="${PKG_SITE}.git" +PKG_LONGDESC="Realtek 8851BU Linux driver" +PKG_TOOLCHAIN="make" +PKG_IS_KERNEL_PKG="yes" + +pre_make_target() { + unset LDFLAGS + + # Switch platform for cross-compilation + sed -i 's/CONFIG_PLATFORM_I386_PC = y/CONFIG_PLATFORM_I386_PC = n/' ${PKG_BUILD}/Makefile + sed -i 's/CONFIG_PLATFORM_ARM64_PC = n/CONFIG_PLATFORM_ARM64_PC = y/' ${PKG_BUILD}/Makefile +} + +make_target() { + make V=1 \ + ARCH=${TARGET_KERNEL_ARCH} \ + KSRC=$(kernel_path) \ + CROSS_COMPILE=${TARGET_KERNEL_PREFIX} \ + CONFIG_RTW_DEBUG=n +} + +makeinstall_target() { + mkdir -p ${INSTALL}/$(get_full_module_dir)/kernel/drivers/net/wireless/ + cp *.ko ${INSTALL}/$(get_full_module_dir)/kernel/drivers/net/wireless/ +} diff --git a/projects/ArchR/packages/linux-drivers/RTL8851BU/patches/001-fix-building-on-6-12.patch b/projects/ArchR/packages/linux-drivers/RTL8851BU/patches/001-fix-building-on-6-12.patch new file mode 100644 index 0000000000..7840acffb9 --- /dev/null +++ b/projects/ArchR/packages/linux-drivers/RTL8851BU/patches/001-fix-building-on-6-12.patch @@ -0,0 +1,21 @@ +--- a/Makefile ++++ b/Makefile +@@ -14,6 +14,7 @@ + #EXTRA_CFLAGS += -Wno-unused-function + EXTRA_CFLAGS += -Wno-unused + #EXTRA_CFLAGS += -Wno-uninitialized ++EXTRA_CFLAGS += -w + + ############ ANDROID COMMON KERNEL ############ + # clang +--- a/os_dep/linux/ioctl_cfg80211.h ++++ b/os_dep/linux/ioctl_cfg80211.h +@@ -90,7 +90,7 @@ + + #if defined(CONFIG_DFS_MASTER) && (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)) + #ifndef CONFIG_RTW_CFG80211_CAC_EVENT +-#define CONFIG_RTW_CFG80211_CAC_EVENT 1 ++#define CONFIG_RTW_CFG80211_CAC_EVENT 0 + #endif + #else + #ifdef CONFIG_RTW_CFG80211_CAC_EVENT diff --git a/projects/ArchR/packages/linux-drivers/RTL88x2BU/modprobe.d/8812bu.conf b/projects/ArchR/packages/linux-drivers/RTL88x2BU/modprobe.d/8812bu.conf new file mode 100644 index 0000000000..aadea8748a --- /dev/null +++ b/projects/ArchR/packages/linux-drivers/RTL88x2BU/modprobe.d/8812bu.conf @@ -0,0 +1 @@ +options 88x2bu rtw_power_mgnt=0 rtw_ips_mode=0 rtw_enusbss=0 diff --git a/projects/ArchR/packages/linux-drivers/RTL88x2BU/package.mk b/projects/ArchR/packages/linux-drivers/RTL88x2BU/package.mk new file mode 100644 index 0000000000..80857d711c --- /dev/null +++ b/projects/ArchR/packages/linux-drivers/RTL88x2BU/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) 2018-present Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="RTL88x2BU" +PKG_VERSION="6e4c5ccfd6607e9f4b1c1befd165ce56e7d6a653" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/morrownr/88x2bu-20210702" +PKG_URL="${PKG_SITE}.git" +PKG_LONGDESC="Realtek 88x2BU driver for 4.4-5.x" +PKG_TOOLCHAIN="make" +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=y +} + +makeinstall_target() { + mkdir -p ${INSTALL}/$(get_full_module_dir)/kernel/drivers/net/wireless/ + cp *.ko ${INSTALL}/$(get_full_module_dir)/kernel/drivers/net/wireless/ +} diff --git a/projects/ArchR/packages/linux-drivers/RTW88/package.mk b/projects/ArchR/packages/linux-drivers/RTW88/package.mk new file mode 100644 index 0000000000..7d63a4b140 --- /dev/null +++ b/projects/ArchR/packages/linux-drivers/RTW88/package.mk @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024-present ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="RTW88" +PKG_VERSION="d2258b4de21aeabf7ef85ec0cada1f3cff9bcbe0" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/lwfinger/rtw88" +PKG_URL="https://github.com/lwfinger/rtw88/archive/${PKG_VERSION}.tar.gz" +PKG_LONGDESC="RTW88 downstream driver" +PKG_TOOLCHAIN="make" +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=y +} + +makeinstall_target() { + mkdir -p ${INSTALL}/$(get_full_module_dir)/kernel/drivers/net/wireless + cp *.ko ${INSTALL}/$(get_full_module_dir)/kernel/drivers/net/wireless +} diff --git a/projects/ArchR/packages/linux-drivers/archr-joypad/package.mk b/projects/ArchR/packages/linux-drivers/archr-joypad/package.mk new file mode 100644 index 0000000000..0197940a71 --- /dev/null +++ b/projects/ArchR/packages/linux-drivers/archr-joypad/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="archr-joypad" +PKG_VERSION="4a8392c1a15a9cf2cab43750c3246d53d6410301" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/archr-linux/archr-joypad" +PKG_URL="${PKG_SITE}/archive/${PKG_VERSION}.tar.gz" +PKG_LONGDESC="archr-joypad: ArchR joypad driver" +PKG_TOOLCHAIN="manual" +PKG_IS_KERNEL_PKG="yes" + +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} + cp *.ko ${INSTALL}/$(get_full_module_dir)/${PKG_NAME} +} diff --git a/projects/ArchR/packages/linux-drivers/dtbocfg/package.mk b/projects/ArchR/packages/linux-drivers/dtbocfg/package.mk new file mode 100644 index 0000000000..070942c4ee --- /dev/null +++ b/projects/ArchR/packages/linux-drivers/dtbocfg/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2023 JELOS (https://github.com/JustEnoughLinuxOS) + +PKG_NAME="dtbocfg" +PKG_VERSION="0.1.0" +PKG_LICENSE="BSD" +PKG_SITE="https://github.com/ikwzm/dtbocfg" +PKG_URL="${PKG_SITE}/archive/refs/tags/v${PKG_VERSION}.tar.gz" +PKG_LONGDESC="Device Tree Blob Overlay Configuration File System" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_NEED_UNPACK="${LINUX_DEPENDS}" +PKG_TOOLCHAIN="manual" +PKG_IS_KERNEL_PKG="yes" + +make_target() { + kernel_make KERNEL_SRC=$(kernel_path) -C ${PKG_BUILD} +} + +makeinstall_target() { + mkdir -p ${INSTALL}/$(get_full_module_dir)/${PKG_NAME} + cp dtbocfg.ko ${INSTALL}/$(get_full_module_dir)/${PKG_NAME}/ +} diff --git a/projects/ArchR/packages/linux-drivers/generic-dsi/package.mk b/projects/ArchR/packages/linux-drivers/generic-dsi/package.mk new file mode 100644 index 0000000000..c7840d31e5 --- /dev/null +++ b/projects/ArchR/packages/linux-drivers/generic-dsi/package.mk @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 ArchR (https://github.com/archr-linux/Arch-R) + +PKG_NAME="generic-dsi" +PKG_VERSION="04e5e55b82d30c5c03d060f44cb6d7cd8840f531" +PKG_LICENSE="GPL" +PKG_LONGDESC="generic DSI panel driver and stock DTB import scripts" +PKG_DEPENDS_TARGET="pyFDT" +PKG_URL="https://github.com/stolen/overlay_server/archive/${PKG_VERSION}.zip" +PKG_TOOLCHAIN="manual" + +unpack() { + mkdir -p "${PKG_BUILD}" + cd "${PKG_BUILD}" + unzip "${SOURCES}/${PKG_NAME}/${PKG_SOURCE_NAME}" +} + +### For development. Easier to check if code compiles and works. +### No need for a long build-transfer-reboot-wait-reboot-check loop +make_target() { + if [ "${I_AM_DEVELOPER}" == "yes" ]; then + # rename the driver to not conflict with built-in one + sed 's|define DRIVER_NAME .*$|define DRIVER_NAME "panel-generic-dsi-test"|' panel-generic-dsi.c > panel-generic-dsi-test.c + echo 'obj-m += panel-generic-dsi-test.o' > ${PKG_BUILD}/Makefile + kernel_make -C $(kernel_path) M=${PKG_BUILD} + fi +} + +makeinstall_target() { + mkdir -p "${INSTALL}/usr/libexec/generic-dsi" + # dtbo.py is a better script handling not just panel, but also joypad, headphones, etc. + cp -v "${PKG_BUILD}/"overlay_server*"/rocknix_dtbo.py" "${INSTALL}/usr/libexec/generic-dsi/archr_dtbo.py" + # importpanel.py still here because it's simple, documented in wiki and performs just one task well + cp -v "${PKG_DIR}/scripts/importpanel.py" "${INSTALL}/usr/libexec/generic-dsi/" +} + + +### For possible future use. The driver can use files in /lib/firmware to initialize a panel, +### thus no need in dtbo, just parameter in cmdline (if base dtb already uses generic driver) +make_init() { + : +} + +makeinstall_init() { + mkdir -p ${INSTALL}/lib + cp -av ${PKG_DIR}/firmware ${INSTALL}/lib/ +} diff --git a/projects/ArchR/packages/linux-drivers/generic-dsi/scripts/importpanel.py b/projects/ArchR/packages/linux-drivers/generic-dsi/scripts/importpanel.py new file mode 100755 index 0000000000..2de3e79aef --- /dev/null +++ b/projects/ArchR/packages/linux-drivers/generic-dsi/scripts/importpanel.py @@ -0,0 +1,274 @@ +#!/usr/bin/env python + +# https://pypi.org/project/fdt/ +# pip install fdt + +import sys, argparse +import fdt +import math + +parser = argparse.ArgumentParser(description="Extract MIPI panel description from stock dtb to use with panel-mipi-generic driver") +parser.add_argument("-n", "--name", help="human readable panel name") +parser.add_argument("-O", "--out-format", help="output format", choices=['dts', 'dtbo', 'pdesc'], default='pdesc', dest='outfmt') +parser.add_argument("-o", "--out", help="output file") +parser.add_argument("-D", "--diagonal", help="panel size (diagonal), inches; used to calculate physical size when dtb lacks it", type=float) +parser.add_argument(metavar="/path/to/vendor.dtb", dest="source_dtb", help="dtb file from stock firmware") +args = parser.parse_args() +comment = (args.outfmt == 'pdesc') + +with open(args.source_dtb, "rb") as f: + dtb_data = f.read() + +acc = [] + +g_name = f"name='{args.name}' " if args.name else "" + +dt = fdt.parse_dtb(dtb_data) +for target in ["dsi@ff450000/panel@0", "dsi@fe060000/panel@0"]: + try: + panel = dt.get_node(target) + break + except: + pass + + +def prop_default(prop, default): + try: + return panel.get_property(prop).value + except: + return default + +delays = [ + prop_default("prepare-delay-ms", 50), + prop_default("reset-delay-ms", 50), + prop_default("init-delay-ms", 50), + prop_default("enable-delay-ms", 50), + 20 # ready -- no such timeout in legacy dtbs + ] +delays_str = ','.join(map(str, delays)) + +fmt = ['rgb888', 'rgb666', 'rgb666_packed', 'rgb565'] [panel.get_property("dsi,format").value] +lanes = panel.get_property("dsi,lanes").value +flags = panel.get_property("dsi,flags").value +flags |= 0x0400 + + +timings = panel.get_subnode("display-timings") +native = timings.get_property("native-mode").value + +# Collect vendor modes +modes = {} +orig_def_fps = None +for m in timings.nodes: + clock = round(m.get_property("clock-frequency").value/1000) + hor = [ + m.get_property("hactive").value, + m.get_property("hfront-porch").value, + m.get_property("hsync-len").value, + m.get_property("hback-porch").value, + ] + ver = [ + m.get_property("vactive").value, + m.get_property("vfront-porch").value, + m.get_property("vsync-len").value, + m.get_property("vback-porch").value, + ] + + mode = {'clock': clock, 'hor': hor, 'ver': ver} + if (m.get_property("phandle").value == native): + mode['default'] = True + + htotal = sum(hor) + vtotal = sum(ver) + fps = clock*1000/(htotal*vtotal) + + if fps not in modes: + modes[fps] = mode + if (m.get_property("phandle").value == native): + modes[fps]['default'] = True + orig_def_fps = fps + + +try: + w = panel.get_property("width-mm").value + h = panel.get_property("height-mm").value +except: + if not args.diagonal: + sys.stderr.buffer.write(b'width-mm or height-mm not set, specify diagonal with -D option\n') + exit(1) + randmode = list(modes.values())[0] + hactive = randmode['hor'][0] + vactive = randmode['ver'][0] + pxdiag = math.sqrt(hactive*hactive + vactive*vactive) + diag_mm = args.diagonal * 25.4 + w = round(diag_mm * hactive/pxdiag) + h = round(diag_mm * vactive/pxdiag) + +# G size=52,70 delays=2,1,20,120,50,20 format=rgb888 lanes=4 flags=0xe03 +acc += [f"G {g_name}size={w},{h} delays={delays_str} format={fmt} lanes={lanes} flags=0x{flags:x}", ""] + +def absfrac(x): + return abs(x - round(x)) + +# Based on vendor modes construct a better set of modes +# https://tasvideos.org/PlatformFramerates +# 50, 60 -- generic +# */1.001 -- NTSC hack with 1001 divisor +# 50.0070 -- PAL NES https://www.nesdev.org/wiki/Cycle_reference_chart +# 60.0988 -- NTSC NES +# 54.8766 -- src/mame/toaplan/twincobr.cpp +# 57.5 -- src/mame/kaneko/snowbros.cpp +# 59.7275 -- https://en.wikipedia.org/wiki/Game_Boy +# 75.47 -- https://ws.nesdev.org/wiki/Display +def_fps = 60 +if orig_def_fps: + def_fps = orig_def_fps +common_fpss = [50/1.001, 50, 50.0070, 57.5, 59.7275, 60/1.001, 60, 60.0988, 75.47, 90, 120]; +common_fpss = [ fps for fps in common_fpss if fps != orig_def_fps] +for targetfps in [orig_def_fps] + common_fpss: + if not targetfps: + continue + warn = "" + # nearest fps to base on + greaterfps = [fps for fps in modes.keys() if fps >= targetfps] + if greaterfps == []: + basefps = max(modes.keys()) + basemode = modes[basefps] + clock = None + else: + # Trust original clock. If real clock differs, maybe make a whitelist or blacklist here + basefps = min(greaterfps) + basemode = modes[basefps] + clock = basemode['clock'] + hor = basemode['hor'].copy() + ver = basemode['ver'].copy() + # Assume original totals are minimal for the panel at this clock + htotal = sum(hor) + vtotal = sum(ver) + perfectclock = targetfps*htotal*vtotal/1000 + if not clock: + warn = "(CAN FAIL) " + # This may fail, but worth trying. Round up to 10kHz + clock = math.ceil(perfectclock/10)*10 + elif clock > 1.25*perfectclock: + # Too much deviation may cause no image + clock = math.ceil(perfectclock/10)*10 + + maxvtotal = round(vtotal*1.25) + # A little bruteforce to find a best totals for target fps + # TODO: maybe iterate over some clock values too + options = [(absfrac(c*1000/targetfps/vt), c, vt) + for vt in range(vtotal, maxvtotal+1) + for c in range(clock, round(1.25*perfectclock), 10) + if ((c*1000/targetfps/vt) >= htotal) and ((c*1000/targetfps/vt) < htotal*1.05) ] + if options == []: + acc += [f"# failed to find mode for fps={targetfps:.6f} c={clock} h={htotal} v={vtotal}"] + continue + (mindev, newclock, newvtotal) = min(options) + # construct a new mode with chosen vtotal + newhtotal = round(newclock*1000/targetfps/newvtotal) + addhtotal = newhtotal - htotal + addvtotal = newvtotal - vtotal + expectedfps = newclock*1000/newvtotal/newhtotal + hor[2] += addhtotal + ver[2] += addvtotal + hor_str = ','.join(map(str, hor)) + ver_str = ','.join(map(str, ver)) + maybe_default = " default=1" if targetfps == def_fps else "" + maybe_comment = f" # {warn}fps={expectedfps:.6f} (target={targetfps:.6f})" if comment else "" + acc += [f"M clock={newclock} horizontal={hor_str} vertical={ver_str}{maybe_default}{maybe_comment}"] + +acc += [""] + +iseq0 = panel.get_property("panel-init-sequence") +if (hasattr(iseq0, 'value')) and (isinstance(iseq0.value, (int))): + iseq = b''.join(map(lambda w : w.to_bytes(4, "big"), list(iseq0))) +else: + iseq = bytearray(iseq0) + +while iseq: + cmd = iseq[0] + wait = iseq[1] + datalen = iseq[2] + iseq = iseq[3:] + + data = iseq[0:datalen] + iseq = iseq[datalen:] + + maybe_wait = f" wait={wait}" if (wait) else "" + maybe_comment = f" # orig_cmd=0x{cmd:x}" if comment else "" + acc += [f"I seq={data.hex()}{maybe_wait}{maybe_comment}"] + + +# pre-formatted dts parts +dts_header = f"""/dts-v1/; +// version: 17 +// last_comp_version: 16 + +/ {{ + fragment@0 {{ + target-path = "/{target}"; + __overlay__ {{ + compatible = "archr,generic-dsi"; + panel_description =""" +dts_footer = """; + }; + }; +}; +""" + +# choose where to output +if args.out: + f = open(args.out, "wb") +else: + f = sys.stdout.buffer + +# Helper for short cmd grouping +def cmd_prefix(line): + if len(line) != 10: + return None + if line[0:6] != 'I seq=': + return None + # "I seq=0320" -> "0l" + return line[6:7] + ('l' if line[7] < '8' else 'H') + +if args.outfmt == 'dts': + # For fancy multi-line format we do not use fdt.FDT.to_dts(), but craft custom dts + f.write(dts_header.encode()) + prevpfx = None; + nocomma = True + for l in acc: + comma = '' if nocomma else ',' + + curpfx = cmd_prefix(l) + if curpfx and curpfx == prevpfx: + delimiter = ' ' + else: + delimiter = '\n ' + prevpfx = curpfx + + if l == '': + f.write((comma + '\n').encode()) + nocomma = True + else: + f.write((comma + delimiter + '"' + l + '"').encode()) + nocomma = False + + f.write(dts_footer.encode()) +elif args.outfmt == 'dtbo': + # remove empty lines as pyfdt does not like them + acc = [ l for l in acc if l != ''] + # create an overlay tree + overlay = fdt.FDT() + overlay.header.version = 17 + overlay.set_property('target-path', '/'+target, path='fragment@0') + overlay.set_property('compatible', 'archr,generic-dsi', path='fragment@0/__overlay__') + overlay.set_property('panel_description', acc, path='fragment@0/__overlay__') + # send the overlay to output + f.write(overlay.to_dtb()) +else: + for l in acc: + f.write((l + "\n").encode()) + +if args.out: + f.close() diff --git a/projects/ArchR/packages/linux-drivers/generic-dsi/sources/panel-generic-dsi.c b/projects/ArchR/packages/linux-drivers/generic-dsi/sources/panel-generic-dsi.c new file mode 100644 index 0000000000..e22c13384a --- /dev/null +++ b/projects/ArchR/packages/linux-drivers/generic-dsi/sources/panel-generic-dsi.c @@ -0,0 +1,689 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Generic MIPI-DSI panel driver + * Copyright (C) 2024 ArchR + * + * based on + * + * Rockteck jh057n00900 5.5" MIPI-DSI panel driver + * Copyright (C) Purism SPC 2019 + */ + +#include +#include +#include +#include +#include +#include +#include + +#include